flesh out quoting
This commit is contained in:
parent
7560aac500
commit
f86b7ba60b
22
README.md
22
README.md
|
@ -66,10 +66,28 @@ Sorry Phil.
|
||||||
|
|
||||||
### q
|
### q
|
||||||
Defines a terra quotation, compiling down to the `` ` `` operator if given one argument, and
|
Defines a terra quotation, compiling down to the `` ` `` operator if given one argument, and
|
||||||
`quote` / `end` if given more than one.
|
`quote` / `in` / `end` if given more than one. The resulting quote can always be used as an
|
||||||
|
expression that returns a value; if `q` is passed more than one argument, the last form is
|
||||||
|
used as the `in` block. To force no value to be returned, you can pass `($)` as the last
|
||||||
|
argument, which corresponds to the empty tuple. Note that quotes inherently creates a new
|
||||||
|
temporary scope, so variables created in a quote will go out of scope by the end of the
|
||||||
|
quote.
|
||||||
|
|
||||||
```fennel
|
```fennel
|
||||||
(fn inc [x] (q (+ x 1))) ; compiles to: function(x) `(x + 1) end
|
(fn inc [x] (q (+ x 1))) ; compiles to: function(x) return `(x + 1) end
|
||||||
|
(fn do-thing [f x]
|
||||||
|
(q (var z (+ ,x 1))
|
||||||
|
(f z)
|
||||||
|
($)))
|
||||||
|
; compiles to:
|
||||||
|
; function(f, x)
|
||||||
|
; return quote
|
||||||
|
; var z = [x] + 1
|
||||||
|
; f(z)
|
||||||
|
; in
|
||||||
|
; {}
|
||||||
|
; end
|
||||||
|
; end
|
||||||
```
|
```
|
||||||
|
|
||||||
### Type syntax
|
### Type syntax
|
||||||
|
|
31
go.fnl
31
go.fnl
|
@ -1,15 +1,20 @@
|
||||||
(local fennel (require :fennel))
|
(local fennel (require :fennel))
|
||||||
(import-macros {: def : q : ttype : static : unterra : untype} :terra)
|
(import-macros {: def : q : ttype : static : printform} :terra)
|
||||||
|
|
||||||
(local iseven (def [uint32 : bool]))
|
(print "define do-thing")
|
||||||
(local isodd (def [n uint32 : bool]
|
(fn do-thing [f x]
|
||||||
(if (= n 0)
|
(printform
|
||||||
(return true)
|
(q (var z (+ x 1))
|
||||||
(return (iseven (- n 1))))))
|
(f z)
|
||||||
(iseven:adddefinition (def [n uint32 : bool]
|
($)))
|
||||||
(if (= n 0)
|
)
|
||||||
(return false)
|
|
||||||
(return (isodd (- n 1))))))
|
(print "define thing-doer")
|
||||||
(print iseven)
|
(local thing-doer (def [x int] (return)))
|
||||||
(print (iseven 5) (isodd 5))
|
; (print thing-doer)
|
||||||
(print (iseven 6) (isodd 6))
|
; (printform
|
||||||
|
(def []
|
||||||
|
(var z 10)
|
||||||
|
,(do-thing thing-doer `z))
|
||||||
|
; )
|
||||||
|
nil
|
33
terra.fnl
33
terra.fnl
|
@ -15,11 +15,15 @@
|
||||||
(fn indent [str scope]
|
(fn indent [str scope]
|
||||||
(.. (string.rep " " scope.indent) str))
|
(.. (string.rep " " scope.indent) str))
|
||||||
|
|
||||||
(fn block [pre stmts post scope f]
|
(fn indented [f scope ?f-will-indent]
|
||||||
(set scope.indent (+ scope.indent 2))
|
(set scope.indent (+ scope.indent 2))
|
||||||
(local block (commasep stmts #(indent (f $1) scope) "\n"))
|
(local result (if ?f-will-indent (f) (indent (f) scope)))
|
||||||
(set scope.indent (- scope.indent 2))
|
(set scope.indent (- scope.indent 2))
|
||||||
(.. pre "\n" block "\n" (indent post scope)))
|
result)
|
||||||
|
|
||||||
|
(fn block [pre stmts post scope f]
|
||||||
|
(let [block (indented #(commasep stmts #(indent (f $1) scope) "\n") scope true)]
|
||||||
|
(.. pre "\n" block "\n" (indent post scope))))
|
||||||
|
|
||||||
(local extract {})
|
(local extract {})
|
||||||
(fn extract.quotes-in-table [into tbl inputs locals]
|
(fn extract.quotes-in-table [into tbl inputs locals]
|
||||||
|
@ -224,23 +228,25 @@
|
||||||
|
|
||||||
(fn forms.if [params scope]
|
(fn forms.if [params scope]
|
||||||
(let [has-else? (= (% (length params) 2) 1)
|
(let [has-else? (= (% (length params) 2) 1)
|
||||||
ilast (if has-else? (length params) (- (length params) 1))
|
ielse (when has-else? (length params))
|
||||||
ielse (when has-else? ilast)
|
|
||||||
clauses (fcollect [i 1 (length params) 2]
|
clauses (fcollect [i 1 (length params) 2]
|
||||||
(if (= i ielse)
|
(if (= i ielse)
|
||||||
{:pre (indent :else scope)
|
{:pre (indent :else scope)
|
||||||
:post :end
|
|
||||||
:clause (. params i)}
|
:clause (. params i)}
|
||||||
{:pre (.. (if (= i 1) :if (indent :elseif scope)) " " (comp.expr (. params i) scope) " then")
|
{:pre (.. (if (= i 1) :if (indent :elseif scope)) " " (comp.expr (. params i) scope) " then")
|
||||||
:post (if (= i ilast) :end "")
|
|
||||||
:clause (. params (+ i 1))}))
|
:clause (. params (+ i 1))}))
|
||||||
blocks (icollect [_ clause (ipairs clauses)]
|
blocks (icollect [_ clause (ipairs clauses)]
|
||||||
(scope:with #(block clause.pre [clause.clause] clause.post scope #(comp.expr $1 scope))))]
|
(scope:with #(.. clause.pre "\n" (indented #(comp.expr clause.clause scope) scope))))]
|
||||||
(table.concat blocks "\n")))
|
(.. (table.concat blocks "\n") "\n" (indent :end scope))))
|
||||||
|
|
||||||
(fn comp.quote [stmts scope]
|
(fn comp.quote [stmts scope]
|
||||||
(if (= (length stmts) 1) (.. "`(" (comp.expr (. stmts 1) scope) ")")
|
(if (= (length stmts) 0) (error "nothing to quote")
|
||||||
(.. "quote\n" (commasep stmts #(comp.expr $1 scope)) "\nend")))
|
(= (length stmts) 1) (.. "`(" (comp.expr (. stmts 1) scope) ")")
|
||||||
|
(let [last-expr (. stmts (length stmts))]
|
||||||
|
(tset stmts (length stmts) nil)
|
||||||
|
(.. (block :quote stmts :in scope #(comp.expr $1 scope)) "\n"
|
||||||
|
(indented #(comp.expr last-expr scope) scope) "\n"
|
||||||
|
(indent :end scope)))))
|
||||||
|
|
||||||
(fn comp.global [[typ initial-val] scope]
|
(fn comp.global [[typ initial-val] scope]
|
||||||
(.. "global(" (comp.type typ scope) "," (comp.expr initial-val scope) ")"))
|
(.. "global(" (comp.type typ scope) "," (comp.expr initial-val scope) ")"))
|
||||||
|
@ -262,7 +268,6 @@
|
||||||
(fn q [...] (build [...] comp.quote))
|
(fn q [...] (build [...] comp.quote))
|
||||||
(fn static [typ initial-value] (build [typ initial-value] comp.global))
|
(fn static [typ initial-value] (build [typ initial-value] comp.global))
|
||||||
|
|
||||||
(fn unterra [...] (view (macroexpand (terra ...))))
|
(fn printform [form] `(do (print ,(view (macroexpand form))) ,form))
|
||||||
(fn untype [...] (view (macroexpand (ttype ...))))
|
|
||||||
|
|
||||||
{: terra : ttype : def : q : static : unterra : untype}
|
{: terra : ttype : def : q : static : printform}
|
Loading…
Reference in a new issue