From a465917f36caf4176aa0657e9afd043b71128dd5 Mon Sep 17 00:00:00 2001 From: Jacob Signorovitch Date: Fri, 9 Jan 2026 13:06:08 -0500 Subject: [PATCH] Added TidBIT --- 08-barf/9BARF.pdf | Bin 0 -> 37192 bytes 08-barf/main.rkt | 89 +------------------------- 10-tidbit/main.rkt | 152 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 87 deletions(-) create mode 100644 08-barf/9BARF.pdf create mode 100644 10-tidbit/main.rkt diff --git a/08-barf/9BARF.pdf b/08-barf/9BARF.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9e07f5c81ff8b599f62722ac774494fa7a9bb513 GIT binary patch literal 37192 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 literal 0 HcmV?d00001 diff --git a/08-barf/main.rkt b/08-barf/main.rkt index d66b708..022091e 100644 --- a/08-barf/main.rkt +++ b/08-barf/main.rkt @@ -272,8 +272,8 @@ CFG for the BARF language: (if (string=? name fname) (f) (#f))])))])) (if (not foundfun) (error 'findfun "Function not found.") foundfun)) -(: eval : BARF -> Primitive) -;; evaluates BARF expressions by reducing them to numbers +(: eval : PROGRAM -> Primitive) +;; evaluates PROGRAM expressions by reducing them to numbers (define (eval expr) (cases expr [(Num n) n] @@ -304,88 +304,3 @@ CFG for the BARF language: ;; evaluate an BARF program contained in a string (define (run str) (eval (parse str))) - -; As we'ren't writing a lazy language, we need to use the Z combinator to delay evaluation of f (otherwise it'd never terminate). This factorial function also isn't tail recursive cause it's hard enough for me to understand already ;-;. -; Z = λf.(λx.(f λv.((x x) v)))(λx.(f λv.((x x) v))) -; factorial = (Y (λself.λn.if (<= n 1) 1 (* n (self (- n 1))))) - -(test (run " -{with Z as {lambda f { - {lambda x {f of {lambda v {{x of x} of v}}}} - of - {lambda x {f of {lambda v {{x of x} of v}}}} -}} - -{with factorial as {Z of - {lambda self {lambda n - {if {n is less than or equal to 1} then 1 else {* n {self of {- n 1}}}} - } -}} - -{{{factorial of 4} is 24} and - {{factorial of 5} is 120}}}}") => #t) - -(test (run "{{lambda f {f of 1}} of {lambda x {+ x 1}}}") => 2) -(test (run "{{lambda x {+ x 1}} of 2}") => 3) -(test (run "{{lambda + {+ + +}} of 2}") =error> "Can't create parameter binding to reserved name '+'.") -(test (run "{1 of 1}") =error> "eval-call: Expected lambda expression to call, instead got: (Num 1).") -(test (run "{with {x 2} {x of 1}}") =error> "eval-call: Expected lambda expression to call, instead got: (Num 2).") - -(test (run "{and T T}") => #t) -(test (run "{and F aaaaaaaaaa}") => #f) -(test (run "{or T aaaaaaaaaa}") => #T) -(test (run "{or F T}") => #T) -(test (run "{or T T}") => #T) -(test (run "{not T}") => #F) -(test (run "{not F}") => #T) -(test (run "{with {p1 {< 1 2}} {with {p2 {< 3 4}} {and p1 p2}}}") => #T) - -(test (run "{if T 1 2}") => 1) -(test (run "{if T then 1 else 2}") => 1) - -(test (run "{with {T 2} {+ T 1}}") =error> "Can't create binding to reserved name 'T'.") -(test (run "{with {+ 2} {+ + 1}}") =error> "Can't create binding to reserved name '+'.") - -(test (run "{< 1 2}") => #t) -(test (run "{< 2 2}") => #f) -(test (run "{< 2 1}") => #f) -(test (run "{1 is 2}") => #f) -(test (run "{= 1 2}") => #f) -(test (run "{= 2 2}") => #t) -(test (run "{2 is 2}") => #t) -(test (run "{<= 1 2}") => #t) -(test (run "{<= 2 2}") => #t) -(test (run "{<= 2 1}") => #f) - -(test (run "{+}") => 0) -(test (run "{+ 12}") => 12) -(test (run "{+ 1 2 3}") => 6) - -(test (run "{*}") => 1) -(test (run "{* 12}") => 12) -(test (run "{* 2 3 5}") => 30) - -(test (run "{-}") =error> "parse-sexpr: bad syntax in (-)") -(test (run "{- 1}") => -1) -(test (run "{- 3 2 1}") => 0) -(test (run "{- 1 2 3}") => -4) - -(test (run "{/}") =error> "parse-sexpr: bad syntax in (/)") -(test (run "{/ 2}") => 1/2) -(test (run "{/ 3 2 1}") => 3/2) -(test (run "{/ 1 2 3}") => 1/6) - -(test (run "{+ x 1}") =error> "eval: free identifier: x") - -;; tests (for simple expressions) -(test (run "5") => 5) -(test (run "{+ 5 5}") => 10) -(test (run "{with {x {+ 5 5}} {+ x x}}") => 20) -(test (run "{with {x 5} {+ x x}}") => 10) -(test (run "{with {x {+ 5 5}} {with {y {- x 3}} {+ y y}}}") => 14) -(test (run "{with {x 5} {with {y {- x 3}} {+ y y}}}") => 4) -(test (run "{with {x 5} {+ x {with {x 3} 10}}}") => 15) -(test (run "{with {x 5} {+ x {with {x 3} x}}}") => 8) -(test (run "{with {x 5} {+ x {with {y 3} x}}}") => 10) -(test (run "{with {x 5} {with {y x} y}}") => 5) -(test (run "{with {x 5} {with {x x} x}}") => 5) diff --git a/10-tidbit/main.rkt b/10-tidbit/main.rkt new file mode 100644 index 0000000..cc966e5 --- /dev/null +++ b/10-tidbit/main.rkt @@ -0,0 +1,152 @@ +#lang pl + +#| +The grammar: + ::= + | { + } + | { - } + | { * } + | { / } + | { with { } } + | + | { fun { } } + | { call } +|# + +(define-type TIDBIT + [Num Number] + [Add TIDBIT TIDBIT] + [Sub TIDBIT TIDBIT] + [Mul TIDBIT TIDBIT] + [Div TIDBIT TIDBIT] + [Id Symbol] + [With Symbol TIDBIT TIDBIT] + [Fun Symbol TIDBIT] + [Call TIDBIT TIDBIT]) + +(: parse-sexpr : Sexpr -> TIDBIT) +;; parses s-expressions into TIDBITs +(define (parse-sexpr sexpr) + (match sexpr + [(number: n) (Num n)] + [(symbol: name) (Id name)] + [(cons 'with more) + (match sexpr + [(list 'with (list (symbol: name) named) body) + (With name (parse-sexpr named) (parse-sexpr body))] + [else (error 'parse-sexpr "bad `with' syntax in ~s" sexpr)])] + [(cons 'fun more) + (match sexpr + [(list 'fun (list (symbol: name)) body) + (Fun name (parse-sexpr body))] + [else (error 'parse-sexpr "bad `fun' syntax in ~s" sexpr)])] + [(list '+ lhs rhs) (Add (parse-sexpr lhs) (parse-sexpr rhs))] + [(list '- lhs rhs) (Sub (parse-sexpr lhs) (parse-sexpr rhs))] + [(list '* lhs rhs) (Mul (parse-sexpr lhs) (parse-sexpr rhs))] + [(list '/ lhs rhs) (Div (parse-sexpr lhs) (parse-sexpr rhs))] + [(list 'call fun arg) + (Call (parse-sexpr fun) (parse-sexpr arg))] + [else (error 'parse-sexpr "bad syntax in ~s" sexpr)])) + +(: parse : String -> TIDBIT) +;; parses a string containing a TIDBIT expression to a TIDBIT AST +(define (parse str) + (parse-sexpr (string->sexpr str))) + +;; Types for environments, values, and a lookup function + +(define-type ENV + [EmptyEnv] + [Extend Symbol VAL ENV]) + +(define-type VAL + [NumV Number] + [FunV Symbol TIDBIT ENV]) + +(: lookup : Symbol ENV -> VAL) +;; lookup a symbol in an environment, return its value or throw an +;; error if it isn't bound +(define (lookup name env) + (cases env + [(EmptyEnv) (error 'lookup "no binding for ~s" name)] + [(Extend id val rest-env) + (if (eq? id name) val (lookup name rest-env))])) + +(: NumV->number : VAL -> Number) +;; convert a TIDBIT runtime numeric value to a Racket one +(define (NumV->number val) + (cases val + [(NumV n) n] + [else (error 'arith-op "expected a number, got: ~s" val)])) + +(: arith-op : (Number Number -> Number) VAL VAL -> VAL) +;; gets a Racket numeric binary operator, and uses it within a NumV +;; wrapper +(define (arith-op op val1 val2) + (NumV (op (NumV->number val1) (NumV->number val2)))) + +(: eval : TIDBIT ENV -> VAL) +;; evaluates TIDBIT expressions by reducing them to values +(define (eval expr env) + (cases expr + [(Num n) (NumV n)] + [(Add l r) (arith-op + (eval l env) (eval r env))] + [(Sub l r) (arith-op - (eval l env) (eval r env))] + [(Mul l r) (arith-op * (eval l env) (eval r env))] + [(Div l r) (arith-op / (eval l env) (eval r env))] + [(With bound-id named-expr bound-body) + (eval bound-body + (Extend bound-id (eval named-expr env) env))] + [(Id name) (lookup name env)] + [(Fun bound-id bound-body) + (FunV bound-id bound-body env)] + [(Call fun-expr arg-expr) + (let ([fval (eval fun-expr env)]) + (cases fval + [(FunV bound-id bound-body f-env) + (eval bound-body + (Extend bound-id (eval arg-expr env) f-env))] + [else (error 'eval "`call' expects a function, got: ~s" + fval)]))])) + +(: run : String -> Number) +;; evaluate a TIDBIT program contained in a string +(define (run str) + (let ([result (eval (parse str) (EmptyEnv))]) + (cases result + [(NumV n) n] + [else (error 'run "evaluation returned a non-number: ~s" + result)]))) + +;; tests +(test (run "{call {fun {x} {+ x 1}} 4}") + => 5) +(test (run "{with {add3 {fun {x} {+ x 3}}} + {call add3 1}}") + => 4) +(test (run "{with {add3 {fun {x} {+ x 3}}} + {with {add1 {fun {x} {+ x 1}}} + {with {x 3} + {call add1 {call add3 x}}}}}") + => 7) +(test (run "{with {identity {fun {x} x}} + {with {foo {fun {x} {+ x 1}}} + {call {call identity foo} 123}}}") + => 124) +(test (run "{with {x 3} + {with {f {fun {y} {+ x y}}} + {with {x 5} + {call f 4}}}}") + => 7) +(test (run "{call {with {x 3} + {fun {y} {+ x y}}} + 4}") + => 7) +(test (run "{with {f {with {x 3} {fun {y} {+ x y}}}} + {with {x 100} + {call f 4}}}") + => 7) +(test (run "{call {call {fun {x} {call x 1}} + {fun {x} {fun {y} {+ x y}}}} + 123}") + => 124) \ No newline at end of file