tuple destructuring
This commit is contained in:
parent
f86b7ba60b
commit
6b5035c111
26
README.md
26
README.md
|
@ -4,6 +4,18 @@ An experiment in combining [Fennel](https://fennel-lang.org) and [Terra](https:/
|
||||||
## Rationale
|
## Rationale
|
||||||
Idk, seemed cool
|
Idk, seemed cool
|
||||||
|
|
||||||
|
## Goals and Non-Goals
|
||||||
|
At its core are a few a largely non-opinionated macros that directly expose the functionality
|
||||||
|
that is only available through Terra's custom syntax. Terra code is not necessarily meant to
|
||||||
|
read like Fennel or have the same semantics. Early returns are fine, all variables are mutable,
|
||||||
|
break and continue and imperative loops are the norm.
|
||||||
|
|
||||||
|
Ideally it would be possible to build a much cleaner set of macros on top of these base macros.
|
||||||
|
But the goal isn't to design a nice low-level language, it's to expose a powerful compilation
|
||||||
|
target. It's assumed that if you want to take advantage of Terra, it's probably because you
|
||||||
|
want to do horrible code-generation tricks. Hosting it inside Fennel simply makes it more
|
||||||
|
comfortable to do so.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
At the top of your file, include the following:
|
At the top of your file, include the following:
|
||||||
```fennel
|
```fennel
|
||||||
|
@ -179,15 +191,25 @@ it consistently mean "create a quote" everywhere. Not sure.)
|
||||||
```fennel
|
```fennel
|
||||||
(var name initial-value) ; compiles to: var name = initial-value
|
(var name initial-value) ; compiles to: var name = initial-value
|
||||||
(var name type initial-value) ; compiles to: var name : type = initial-value
|
(var name type initial-value) ; compiles to: var name : type = initial-value
|
||||||
|
(var (name1 name2) val1 val2) ; compiles to: var name1, name2 = val1, val2
|
||||||
|
(var {name1 type1 name2 type2} val1 val2) ; compiles to: var name1 : type1, name2 : type2 = val1, val2
|
||||||
|
(var {undefined type}) ; compiles to: var undefined : type
|
||||||
```
|
```
|
||||||
Define a local variable named `var`, and set its initial value to `initial-value`. You can
|
Define a local variable named `var`, and set its initial value to `initial-value`. You can
|
||||||
manually specify a `type`, or you can let terra infer it from `initial-value`. There is no
|
manually specify a `type`, or you can let terra infer it from `initial-value`. Both forms
|
||||||
syntax for _not_ initalizing the variable on declaration.
|
require `initial-value` to be provided.
|
||||||
|
|
||||||
|
You can define multiple type-inferred variables at once with the `(name1 name2)` syntax, and
|
||||||
|
multiple explicitly-typed variables with the `{name1 type1 name2 type2}` syntax. Both of those
|
||||||
|
forms accept any number of initial values. If no values are provided, the variables are left
|
||||||
|
uninitialized. If one value is passed, Terra will treat it as a tuple destructuring. Otherwise
|
||||||
|
you should probably pass the same number of values as names.
|
||||||
|
|
||||||
#### assignment
|
#### assignment
|
||||||
```fennel
|
```fennel
|
||||||
(set varname value) ; compiles to: varname = value
|
(set varname value) ; compiles to: varname = value
|
||||||
(set struct.field value) ; compiles to: struct.field = value
|
(set struct.field value) ; compiles to: struct.field = value
|
||||||
|
(set (field1 field2) tuple) ; compiles to: field1, field2 = tuple
|
||||||
(tset struct (getfield) value) ; compiles to: struct.[getfield()] = value
|
(tset struct (getfield) value) ; compiles to: struct.[getfield()] = value
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
11
terra.fnl
11
terra.fnl
|
@ -180,7 +180,15 @@
|
||||||
(fn type-constructors.raw-escape [[text] scope] text)
|
(fn type-constructors.raw-escape [[text] scope] text)
|
||||||
|
|
||||||
(fn forms.var [defn scope]
|
(fn forms.var [defn scope]
|
||||||
|
(fn rvaluelist [initvals]
|
||||||
|
(if (> (length initvals) 0)
|
||||||
|
(.. " = " (commasep initvals #(comp.expr $1 scope)))
|
||||||
|
""))
|
||||||
(case defn
|
(case defn
|
||||||
|
(where [names & initvals] (list? names))
|
||||||
|
(.. "var " (commasep names #(scope:addlocal $1)) (rvaluelist initvals))
|
||||||
|
(where [nametyps & initvals] (kv-table? nametyps))
|
||||||
|
(.. "var " (kvcommasep nametyps #(.. (scope:addlocal $1) " : " (comp.type $2 scope))) (rvaluelist initvals))
|
||||||
[name typ initval] (.. "var " (scope:addlocal name) " : " (comp.type typ scope) " = " (comp.expr initval scope))
|
[name typ initval] (.. "var " (scope:addlocal name) " : " (comp.type typ scope) " = " (comp.expr initval scope))
|
||||||
[name initval] (.. "var " (scope:addlocal name) " = " (comp.expr initval scope))))
|
[name initval] (.. "var " (scope:addlocal name) " = " (comp.expr initval scope))))
|
||||||
|
|
||||||
|
@ -214,7 +222,8 @@
|
||||||
(def-infix :not= "~=")
|
(def-infix :not= "~=")
|
||||||
(fn forms.not [[expr] scope] (.. "not (" (comp.expr expr scope) ")"))
|
(fn forms.not [[expr] scope] (.. "not (" (comp.expr expr scope) ")"))
|
||||||
(fn forms.set [[left right] scope]
|
(fn forms.set [[left right] scope]
|
||||||
(.. (comp.expr left scope) " = (" (comp.expr right scope) ")"))
|
(if (list? left) (.. (commasep left #(comp.expr $1 scope)) " = (" (comp.expr right scope) ")")
|
||||||
|
(.. (comp.expr left scope) " = (" (comp.expr right scope) ")")))
|
||||||
(fn forms.tset [args scope]
|
(fn forms.tset [args scope]
|
||||||
(let [iright (length args)
|
(let [iright (length args)
|
||||||
right (. args iright)]
|
right (. args iright)]
|
||||||
|
|
Loading…
Reference in a new issue