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

L24 code

parent de6f6e33
; three strategies to extend the language with "syntactic sugar"
; 1. in the parser, just expand the sugar to its equivalent core feature (desugaring) (involves writing OCaml)
; 2. manipulate trefoil syntax in trefoil, using quote/eval
(quote (+ 1 2 3))
(quote (foo (bar (baz))))
(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)
(eval (transform-plus-with-three-args (quote (+ 1 2 3))))
(+ (+ 1 2) 3)
;;;;;;;;;;;;;;
; strategy 3: macros
;;;;;;;;;;;;;;
; want to write
; (define f (delay (print! 'hello)))
; would bind f to a thunk with (print! 'hello) as its bodyt
;
; would not print yet!!!
; (f) ; now it would print
(quote (delay (print! 'hello)))
(quote (lambda () e))
(define (delay-transformer pst)
(match pst
((cons 'delay (cons e nil))
; wrap e in a thunk: (lambda () e)
(cons 'lambda (cons nil (cons e nil))))))
(delay-transformer (quote (delay (print! 'hello))))
(quote (lambda () (print! 'hello)))
; error! have not installed the syntax tranformer yet
; (define f (delay (print! 'hello)))
; (f)
; install-syntax-transformer! takes two arguments
; - the "key", aka the name of the macro as the trefoil programmer will call it
; - and the transformer, which is any trefoil expression, but usually a function name
; - the transformer will be called with the pst to transform, and should return new pst
(install-syntax-transformer! delay delay-transformer) ; changes the syntax of the language!!
; now this is valid syntax
(define f (delay (print! 'hello)))
(f)
; (list 1 2 3 4 5 6)
; (cons 1 (cons 2 ...))
(quote (list 1 2 3 4 5 6))
; returns: (cons 'list (cons '1 (cons '2 (cons '3 (cons '4 (cons '5 (cons '6 nil)))))))
; a function from a trefoil list to a pst that when evaluated will be that list
(define (nest-conses xs)
(match xs
(nil 'nil)
((cons x xs) (cons 'cons (cons x (cons (nest-conses xs) nil)))))) ; (cons 1 (...))
; aside:
; - quasiquote allows to escape the quote
; - written with the backtick symbol `
;
; example:
; (quasiquote (cons (unquote x) (unquote (nest-conses))))
; `(cons ,x ,(nest-conses))
;
; end of aside
(quote (cons 1 nil))
(quote (cons 1 (cons 2 (cons 3 nil))))
(nest-conses (quote (1 2 3 4 5 6)))
(eval (nest-conses (quote (1 2 3 4 5 6))))
(define (list-transformer pst)
(match pst
((cons _ tail) (nest-conses tail))))
(list-transformer (quote (list 1 2 3 4 5 6)))
(install-syntax-transformer! list list-transformer)
(list 1 2 3 4 5 6)
; "begin" macro
; now that we have side-effects in trefoil, it's to evaluate several expressions just for side effect
; (like semicolon in OCaml)
;; (begin
;; (print! 'hello)
;; (+ 1 2)
;; (print! 'world)
;; (+ 2 3))
; transformer will generated nested lets that ignore their arguments
(let ((_ (print! 'hello)))
(let ((_ (+ 1 2)))
(let ((_ (print! 'world)))
(+ 2 3))))
;(define (begin-transformer pst)
; ...)
(quote
(begin
(print! 'hello)
(+ 1 2)
(print! 'world)
(+ 2 3)))
; transformer will generated nested lets that ignore their arguments
(quote
(let ((_ (print! 'hello)))
(let ((_ (+ 1 2)))
(let ((_ (print! 'world)))
(+ 2 3)))))
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