Undefined function defs and if statements
This commit is contained in:
parent
eafe21c6db
commit
7560aac500
31
README.md
31
README.md
|
@ -18,15 +18,15 @@ I could maybe be persuaded to make `def` work like `fn` and optionally define a
|
||||||
eh, whatever.
|
eh, whatever.
|
||||||
|
|
||||||
### def
|
### def
|
||||||
Defines a function, compiling down to the `terra` keyword.
|
Defines a function, compiling down to the `terra` keyword. Can also be used to create an undefined
|
||||||
|
function, if called with no statements.
|
||||||
|
|
||||||
Syntax:
|
|
||||||
```fennel
|
```fennel
|
||||||
|
; syntax:
|
||||||
(def [argname1 argtype1 argname2 argtype2... : rettype1 rettype2...] statement...)
|
(def [argname1 argtype1 argname2 argtype2... : rettype1 rettype2...] statement...)
|
||||||
```
|
(def [argtype1 argtype2... : rettype1 rettype2...])
|
||||||
|
|
||||||
Simple example:
|
; examples:
|
||||||
```fennel
|
|
||||||
(local add (def [x int y int : int]
|
(local add (def [x int y int : int]
|
||||||
(return (+ x y))))
|
(return (+ x y))))
|
||||||
|
|
||||||
|
@ -36,10 +36,31 @@ Simple example:
|
||||||
; end
|
; end
|
||||||
|
|
||||||
(add 1 2) ; returns 3
|
(add 1 2) ; returns 3
|
||||||
|
|
||||||
|
(local iseven (def [uint32 : bool]))
|
||||||
|
(local isodd (def [n uint32 : bool]
|
||||||
|
(if (= n 0)
|
||||||
|
(return true)
|
||||||
|
(return (iseven (- n 1))))))
|
||||||
|
(iseven:adddefinition (def [n uint32 : bool]
|
||||||
|
(if (= n 0)
|
||||||
|
(return false)
|
||||||
|
(return (isodd (- n 1))))))
|
||||||
|
|
||||||
|
; compiles to:
|
||||||
|
; local terra iseven :: { uint32 } -> { bool }
|
||||||
|
; local isodd = terra(n : uint32) : { bool }
|
||||||
|
; if n == 0 then return true else return iseven(n - 1) end
|
||||||
|
; end
|
||||||
|
; iseven:adddefinition(terra(n : uint32) : { bool }
|
||||||
|
; if n == 0 then return false else return isodd(n - 1) end
|
||||||
|
; end)
|
||||||
```
|
```
|
||||||
|
|
||||||
To define a function as returning "void", simply end the argument list with a `:`.
|
To define a function as returning "void", simply end the argument list with a `:`.
|
||||||
To make terra infer the return type, do not include a `:` in the argument list at all.
|
To make terra infer the return type, do not include a `:` in the argument list at all.
|
||||||
|
Undefined functions can't have their return types inferred.
|
||||||
|
|
||||||
Unlike Fennel, we do not implement implicit return semantics, and early returns are A-OK.
|
Unlike Fennel, we do not implement implicit return semantics, and early returns are A-OK.
|
||||||
Sorry Phil.
|
Sorry Phil.
|
||||||
|
|
||||||
|
|
31
go.fnl
31
go.fnl
|
@ -1,22 +1,15 @@
|
||||||
(local fennel (require :fennel))
|
(local fennel (require :fennel))
|
||||||
(import-macros {: def : q : ttype : static : unterra : untype} :terra)
|
(import-macros {: def : q : ttype : static : unterra : untype} :terra)
|
||||||
|
|
||||||
(local Complex (ttype {real float imag float}))
|
(local iseven (def [uint32 : bool]))
|
||||||
(print (unterra
|
(local isodd (def [n uint32 : bool]
|
||||||
(def [: Complex] (return (Complex { real 5 imag 1 })))
|
(if (= n 0)
|
||||||
))
|
(return true)
|
||||||
(print (unterra
|
(return (iseven (- n 1))))))
|
||||||
(def [c Complex r float] (tset c :real r))
|
(iseven:adddefinition (def [n uint32 : bool]
|
||||||
))
|
(if (= n 0)
|
||||||
(local thing (def [: Complex] (return (Complex { real 5 imag 1 }))))
|
(return false)
|
||||||
(local get-real (def [val Complex] (return (. val :real))))
|
(return (isodd (- n 1))))))
|
||||||
(local set-real (def [c [Complex] r float] (tset c :real r)))
|
(print iseven)
|
||||||
|
(print (iseven 5) (isodd 5))
|
||||||
(let [result (thing)]
|
(print (iseven 6) (isodd 6))
|
||||||
(print result result.real result.imag (get-real result))
|
|
||||||
(set-real result 10)
|
|
||||||
(print (get-real result)))
|
|
||||||
|
|
||||||
(print (unterra
|
|
||||||
(def [: int bool] (return 5 true))
|
|
||||||
))
|
|
||||||
|
|
28
terra.fnl
28
terra.fnl
|
@ -184,11 +184,13 @@
|
||||||
(scope:with #(block :do stmts :end scope #(comp.expr $1 scope))))
|
(scope:with #(block :do stmts :end scope #(comp.expr $1 scope))))
|
||||||
|
|
||||||
(fn forms.def [[arglist & stmts] scope]
|
(fn forms.def [[arglist & stmts] scope]
|
||||||
(scope:with #(let [(in out) (split-arglist arglist)
|
(if (> (length stmts) 0)
|
||||||
argpairs (fcollect [i 1 (length in) 2] {:name (. in i) :type (. in (+ i 1))})
|
(scope:with #(let [(in out) (split-arglist arglist)
|
||||||
rettyp (if out (.. ": { " (commasep out #(comp.type $1 scope)) " }") "")
|
argpairs (fcollect [i 1 (length in) 2] {:name (. in i) :type (. in (+ i 1))})
|
||||||
argdefs (commasep argpairs #(.. (scope:addlocal $1.name) " : " (comp.type $1.type scope)))]
|
rettyp (if out (.. ": { " (commasep out #(comp.type $1 scope)) " }") "")
|
||||||
(block (.. "terra (" argdefs ")" rettyp) stmts :end scope #(comp.expr $1 scope)))))
|
argdefs (commasep argpairs #(.. (scope:addlocal $1.name) " : " (comp.type $1.type scope)))]
|
||||||
|
(block (.. "terra (" argdefs ")" rettyp) stmts :end scope #(comp.expr $1 scope))))
|
||||||
|
(.. "(function () local terra anonfn :: " ((. type-constructors "->") arglist scope) " return anonfn end)()")))
|
||||||
|
|
||||||
(fn forms.return [vals scope] (.. "return " (commasep vals #(comp.expr $1 scope))))
|
(fn forms.return [vals scope] (.. "return " (commasep vals #(comp.expr $1 scope))))
|
||||||
|
|
||||||
|
@ -220,6 +222,22 @@
|
||||||
(tset forms ":" (fn [[obj field & args] scope]
|
(tset forms ":" (fn [[obj field & args] scope]
|
||||||
(.. (comp.expr obj scope) ":[" (scope:expr field) "](" (commasep args #(comp.expr $1 scope)) ")")))
|
(.. (comp.expr obj scope) ":[" (scope:expr field) "](" (commasep args #(comp.expr $1 scope)) ")")))
|
||||||
|
|
||||||
|
(fn forms.if [params scope]
|
||||||
|
(let [has-else? (= (% (length params) 2) 1)
|
||||||
|
ilast (if has-else? (length params) (- (length params) 1))
|
||||||
|
ielse (when has-else? ilast)
|
||||||
|
clauses (fcollect [i 1 (length params) 2]
|
||||||
|
(if (= i ielse)
|
||||||
|
{:pre (indent :else scope)
|
||||||
|
:post :end
|
||||||
|
:clause (. params i)}
|
||||||
|
{:pre (.. (if (= i 1) :if (indent :elseif scope)) " " (comp.expr (. params i) scope) " then")
|
||||||
|
:post (if (= i ilast) :end "")
|
||||||
|
:clause (. params (+ i 1))}))
|
||||||
|
blocks (icollect [_ clause (ipairs clauses)]
|
||||||
|
(scope:with #(block clause.pre [clause.clause] clause.post scope #(comp.expr $1 scope))))]
|
||||||
|
(table.concat blocks "\n")))
|
||||||
|
|
||||||
(fn comp.quote [stmts scope]
|
(fn comp.quote [stmts scope]
|
||||||
(if (= (length stmts) 1) (.. "`(" (comp.expr (. stmts 1) scope) ")")
|
(if (= (length stmts) 1) (.. "`(" (comp.expr (. stmts 1) scope) ")")
|
||||||
(.. "quote\n" (commasep stmts #(comp.expr $1 scope)) "\nend")))
|
(.. "quote\n" (commasep stmts #(comp.expr $1 scope)) "\nend")))
|
||||||
|
|
Loading…
Reference in a new issue