Map destructuring
This commit is contained in:
@@ -146,7 +146,10 @@ class Helpers {
|
||||
};
|
||||
}
|
||||
|
||||
// TODO use let instead of begin to make the args immutable by default
|
||||
// To make function args immutable by default, we would use (let...) instead of (begin...)
|
||||
// to make the body expression.
|
||||
// But setting default arguments is so common, and arguments are not settable references,
|
||||
// so function args are not immutable.
|
||||
return {
|
||||
ret: if (name != null) switch (name.def) {
|
||||
case TypedExp(type, _): Helpers.parseComplexType(type, name);
|
||||
|
@@ -91,6 +91,17 @@ class SpecialForms {
|
||||
EBinop(OpAssign, k.convert(args[0]), k.convert(args[1])).withMacroPosOf(wholeExp);
|
||||
};
|
||||
|
||||
function varName(nameExp:ReaderExp) {
|
||||
return switch (nameExp.def) {
|
||||
case Symbol(name) | TypedExp(_, {pos: _, def: Symbol(name)}):
|
||||
name;
|
||||
case KeyValueExp(_, valueNameExp):
|
||||
varName(valueNameExp);
|
||||
default:
|
||||
throw CompileError.fromExp(nameExp, 'expected a symbol, typed symbol, or keyed symbol for variable name in a var binding');
|
||||
};
|
||||
}
|
||||
|
||||
function toVar(nameExp:ReaderExp, valueExp:ReaderExp, k:KissState, ?isFinal:Bool):Var {
|
||||
// This check seems like unnecessary repetition but it's not. It allows is so that individual destructured bindings can specify mutability
|
||||
return if (isFinal == null) {
|
||||
@@ -101,12 +112,7 @@ class SpecialForms {
|
||||
toVar(nameExp, valueExp, k, true);
|
||||
};
|
||||
} else {
|
||||
name: switch (nameExp.def) {
|
||||
case Symbol(name) | TypedExp(_, {pos: _, def: Symbol(name)}):
|
||||
name;
|
||||
default:
|
||||
throw CompileError.fromExp(nameExp, 'expected a symbol or typed symbol for variable name in a var binding');
|
||||
},
|
||||
name: varName(nameExp),
|
||||
type: switch (nameExp.def) {
|
||||
case TypedExp(type, _):
|
||||
Helpers.parseComplexType(type, nameExp);
|
||||
@@ -136,10 +142,13 @@ class SpecialForms {
|
||||
// Only evaluate the list expression being destructured once:
|
||||
[toVar(uniqueVarSymbol, valueExp, k, true)].concat([
|
||||
for (nameExp in nameExps)
|
||||
toVar(nameExp,
|
||||
CallExp(Symbol("nth").withPosOf(valueExp),
|
||||
[uniqueVarSymbol, Symbol(Std.string(idx++)).withPosOf(valueExp)]).withPosOf(valueExp),
|
||||
k, if (isFinal == false) false else null)
|
||||
toVar(nameExp, switch (nameExp.def) {
|
||||
case KeyValueExp(keyExp, nameExp):
|
||||
CallExp(Symbol("dict-get").withPosOf(valueExp), [uniqueVarSymbol, keyExp]).withPosOf(valueExp);
|
||||
default:
|
||||
CallExp(Symbol("nth").withPosOf(valueExp),
|
||||
[uniqueVarSymbol, Symbol(Std.string(idx++)).withPosOf(valueExp)]).withPosOf(valueExp);
|
||||
}, k, if (isFinal == false) false else null)
|
||||
]);
|
||||
default:
|
||||
throw CompileError.fromExp(namesExp, "Can only bind variables to a symbol or list of symbols for destructuring");
|
||||
|
@@ -348,4 +348,9 @@
|
||||
(Assert.equals "me" (dict-get myMap "found"))
|
||||
(doFor =>key value myMap
|
||||
(Assert.isTrue (<= 0 (.indexOf ["hey" "found"] key)))
|
||||
(Assert.isTrue (<= 0 (.indexOf ["you" "me"] value)))))
|
||||
(Assert.isTrue (<= 0 (.indexOf ["you" "me"] value))))
|
||||
|
||||
// Map destructuring:
|
||||
(let [[=>"hey" v1 =>"found" v2] myMap]
|
||||
(Assert.equals "you" v1)
|
||||
(Assert.equals "me" v2)))
|
Reference in New Issue
Block a user