M lib/scopes/core.sc +32 -15
@@ 3059,6 3059,16 @@ fn has-binding-operator? (expr)
return true
repeat next
+# properly expand a right hand side term of a binding-like expression to conform to
+ how `:=` treats right hand side terms
+fn expand-binding-expr (anchor rhs next-expr env)
+ let rhs =
+ if (== (countof rhs) 1)
+ let rhs = (decons rhs)
+ rhs
+ else `rhs
+ sc_expand ('tag rhs anchor) next-expr env
+
fn parse-binding-expr (anchor expr next-expr env)
loop (lhs rhs = '() expr)
if (empty? rhs)
@@ 3067,12 3077,7 @@ fn parse-binding-expr (anchor expr next-
if (== ('typeof at) Symbol)
let at = (as at Symbol)
if (== at ':=)
- let rhs =
- if (== (countof rhs) 1)
- let rhs = (decons rhs)
- rhs
- else `rhs
- let rhs next-expr env = (sc_expand ('tag rhs anchor) next-expr env)
+ let rhs next-expr env = (expand-binding-expr anchor rhs next-expr env)
let newexpr =
'join
cons let ('reverse lhs)
@@ 7770,18 7775,30 @@ inline gen-allocator-sugar (copyf newf)
let _let = ('tag `let anchor)
let result =
sugar-match values...
- case (name '= value)
+ case (name '= value...)
+ let value next-expr sugar-scope = (expand-binding-expr anchor value... next-expr sugar-scope)
+ let callexpr =
+ 'tag `[(qq ([copy-by-value expr-head value]))] anchor
+ return `[(qq [_let name] = [callexpr])] next-expr sugar-scope
+ case (name ':= value...)
+ let value next-expr sugar-scope = (expand-binding-expr anchor value... next-expr sugar-scope)
let callexpr =
'tag `[(qq ([copy-by-value expr-head value]))] anchor
- `[(qq [_let name] = [callexpr])]
- case ('= value)
- `[(qq ([copy-by-value expr-head value]))]
- case (name ': T '= value)
+ return `[(qq [_let name] = [callexpr])] next-expr sugar-scope
+ case ('= value...)
+ let value next-expr sugar-scope = (expand-binding-expr anchor value... next-expr sugar-scope)
+ return `[(qq ([copy-by-value expr-head value]))] next-expr sugar-scope
+ case (':= value...)
+ let value next-expr sugar-scope = (expand-binding-expr anchor value... next-expr sugar-scope)
+ return `[(qq ([copy-by-value expr-head value]))] next-expr sugar-scope
+ case (name ': T '= value...)
+ let value next-expr sugar-scope = (expand-binding-expr anchor value... next-expr sugar-scope)
let callexpr =
'tag `[(qq ([copyf expr-head T value]))] anchor
- `[(qq [_let name] = [callexpr])]
- case (': T '= value)
- `[(qq ([copyf expr-head T value]))]
+ return `[(qq [_let name] = [callexpr])] next-expr sugar-scope
+ case (': T '= value...)
+ let value next-expr sugar-scope = (expand-binding-expr anchor value... next-expr sugar-scope)
+ return `[(qq ([copyf expr-head T value]))] next-expr sugar-scope
case (name ': T args...)
let callexpr =
'tag `[(qq [newf expr-head T] (unquote-splice args...))] anchor
@@ 7793,7 7810,7 @@ inline gen-allocator-sugar (copyf newf)
default
error
.. "syntax: " (tostring expr-head) " [<name>] [: <type>] [= <value>]"
- 'tag result anchor
+ _ ('tag result anchor) next-expr sugar-scope
""""declares a mutable variable on the local function stack.
M testing/test_local.sc +19 -2
@@ 1,3 1,5 @@
+
+using import testing
# define stack variable with type signature and init value
local a : i32 = 3:i8
@@ 5,8 7,23 @@ local a : i32 = 3:i8
local b : i32
assert (b == 0)
b = 2
-# infer type from initialization argument
-local k = (a + b)
+# infer type from initialization argument; both `=` and `:=` are accepted
+local k := (a + b)
assert (k == 5)
+# local ... = auto-wraps the right hand side, accepts multiple left hand arguments
+local x = + 1 2
+test (x == 3)
+local x2 : i32 = + 1 2
+test (x2 == 3)
+test ((local : i32 = + 1 2) == 3)
+
+# local ... = also supports block sugars like `if`
+# right hand side is evaluated in same scope
+local x := if ((local z := 10) == 10)
+ 20
+else
+ 30
+test (and (x == 20) (z == 10))
+
true