Commit de6f6e33 authored by James R. Wilcox's avatar James R. Wilcox
Browse files

L23 code

parent e4cd7b26
......@@ -99,8 +99,7 @@ let rec expr_of_pst p =
| Pst.Node (head :: args) ->
match head, args with
| Pst.Node _, _ -> raise (AbstractSyntaxError ("Expression forms must start with a symbol, but got " ^ Pst.string_of_pst head))
| Pst.Symbol "+", [left; right] -> Plus (expr_of_pst left, expr_of_pst right)
| Pst.Symbol "+", _ -> raise (AbstractSyntaxError ("operator + expects 2 args but got " ^ Pst.string_of_pst p))
| Pst.Symbol "+", l -> List.fold_left (fun acc pst -> Plus (acc, expr_of_pst pst)) (IntLit 0) l
| Pst.Symbol "-", [left; right] -> Minus (expr_of_pst left, expr_of_pst right)
| Pst.Symbol "-", _ -> raise (AbstractSyntaxError ("operator - expects 2 args but got " ^ Pst.string_of_pst p))
| Pst.Symbol "*", [left; right] -> Times (expr_of_pst left, expr_of_pst right)
......@@ -137,6 +136,8 @@ let rec expr_of_pst p =
(* TODO: add parsing for match expressions here *)
| Pst.Symbol "and", [e1; e2] -> If (expr_of_pst e1, expr_of_pst e2, BoolLit false)
| Pst.Symbol "and", _ -> raise (AbstractSyntaxError ("and expects 2 args but got " ^ Pst.string_of_pst p))
(* Otherwise, if it doesn't match any of the above, it's a function call. *)
| Pst.Symbol f, args ->
......
......@@ -121,7 +121,7 @@ let rec interpret_expression (dynenv, e) =
failwith "TODO: implement the semantics of cond here"
in
loop clauses
| Symbol _ -> failwith "TODO: handle Symbols in the interpreter"
| Symbol _ -> e
(* TODO: add cases for the other "internal" expressions here *)
(* TODO: add case for match expressions here *)
......
(define msg 'hello)
; unlike in some other languages, trefoil allows any value to be thought of as a boolean
; false is the only false-y in trefoil, everything else is truth-y
(and (+ 1 2) 'hello) ; should return 'hello
(and false 'hello) ; should return false
(and true msg) ; should return 'hello
(+ 1 2 3) ; ast: Plus(Plus(Plus(IntLit(0), IntLit(1)), IntLit(2)), IntLit(3)) evaluates to: 6
(+) ; ast: IntLit(0) evaluates to: 0
(+ 17) ; ast: Plus(IntLit(0), IntLit(17)) evaluates to: 17
(+ 1 2 3 4 5 6 7 8 9 10) ; ast: evaluates to: 55
; memoization
(quote (+ 1 2))
(quote (+ 1 2 3)) ; not a valid expression! but it is a perfectly valid pst
; macros
(define (transform-syntax syn)
(match syn
((cons '+ (cons a (cons b (cons c nil))))
......
;; summary
; - syntactic sugar via parser in the metalanguage
; - representing trefoil syntax *in* trefoil
; - quote/eval
; - trefoil-level macros to replace syntax with syntax
;; motivating syntactic sugar
; say we want to write a function that auto-wraps its arg in a thunk
; (define (delay e)
; ; return a thunk with e inside it
; ...)
;
; (define f (delay (print! 'hello)))
; (f)
; the behavior we want is impossible with functions!
;
; this is why we wrap stuff in thunks manually
;;;;;;;;;;;;;
; adding syntax to the language
;;;;;;;;;;;;;
; add an operation to trefoil, called delay that auto-wraps its argument in a thunk
; the key is that this version of delay will not be a function
; - if is not a function, it's a "special form"
; - written with parenthesis and then "if" and the 3 arguments
; really we want to add a new special form, called delay
; other examples of *syntactic sugar*:
; - make it easier to evaluate several expression for side effect, then return the last one
; - semicolon in OCaml
; - && operator, traditionally written (and e1 e2) in scheme
; - have more than two arguments to arithmetic operations
; - (+ 1 2 3) instead of (+ 1 (+ 2 3))
; syntactic sugar:
; - a kind of expression or feature that's arlready expressible using existing features,
; but is more convenient
;;;;;;;;;;;;
; strategy 1: use the parser to "expand" abbreviations
;;;;;;;;;;;;
; add an (and e1 e2) special form to the language
; - "semantics by translation" or "semantics by expansion"
;
; consider an expression (and e1 e2), the semantics (by translation) is to evaluate
; (if e1 e2 false)
; not going to change the definition of the ast at all!!!
;;;;;;;;;;;;
; strategy 2: quote/eval
;;;;;;;;;;;;
; - represent trefoil syntax as trefoil data
(+ 1 2) ; returns 3
; can represent that program as data using (trefoil) symbols and (trefoil) lists
(cons '+ (cons '1 (cons '2 nil)))
(+ 1 (+ 2 3))
(cons '+ (cons '1 (cons (cons '+ (cons '2 (cons '3 nil))) nil)))
; manual translation process to represent the program as data is error-prone and confusing
; introduce an operation in the language, to turn a program into data
; quote
(quote (+ 1 2))
; (+ 1 2 3) ; not a valid expression!
(quote (+ 1 2 3))
; in ocaml, under "strategy 1" we converted the pst (+ 1 2 3) into the pst (+ (+ 1 2) 3)
(define (transform-plus-with-three-args pst)
(match pst
((cons '+ (cons e1 (cons e2 (cons e3 nil)))) (cons '+ (cons (cons '+ (cons e1 (cons e2 nil))) (cons e3 nil))))))
(define example-pst (quote (+ 1 2 3)))
(transform-plus-with-three-args example-pst) ; should return the pst representing (+ (+ 1 2) 3)
; in other words, it will return the same thing as
(quote (+ (+ 1 2) 3))
(define transformed-example (transform-plus-with-three-args example-pst))
(eval transformed-example)
; this is cool because the trefoil programmer has extended the language by themselves without writing any ocaml
;
; but the downside is they have to write quote/eval everywhere they want to use one of their language extensions
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment