Map destructuring

This commit is contained in:
2020-12-07 18:52:33 -07:00
parent b23c457243
commit c39ec902ee
3 changed files with 29 additions and 12 deletions

View File

@@ -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 { return {
ret: if (name != null) switch (name.def) { ret: if (name != null) switch (name.def) {
case TypedExp(type, _): Helpers.parseComplexType(type, name); case TypedExp(type, _): Helpers.parseComplexType(type, name);

View File

@@ -91,6 +91,17 @@ class SpecialForms {
EBinop(OpAssign, k.convert(args[0]), k.convert(args[1])).withMacroPosOf(wholeExp); 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 { 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 // 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) { return if (isFinal == null) {
@@ -101,12 +112,7 @@ class SpecialForms {
toVar(nameExp, valueExp, k, true); toVar(nameExp, valueExp, k, true);
}; };
} else { } else {
name: switch (nameExp.def) { name: varName(nameExp),
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');
},
type: switch (nameExp.def) { type: switch (nameExp.def) {
case TypedExp(type, _): case TypedExp(type, _):
Helpers.parseComplexType(type, nameExp); Helpers.parseComplexType(type, nameExp);
@@ -136,10 +142,13 @@ class SpecialForms {
// Only evaluate the list expression being destructured once: // Only evaluate the list expression being destructured once:
[toVar(uniqueVarSymbol, valueExp, k, true)].concat([ [toVar(uniqueVarSymbol, valueExp, k, true)].concat([
for (nameExp in nameExps) for (nameExp in nameExps)
toVar(nameExp, toVar(nameExp, switch (nameExp.def) {
CallExp(Symbol("nth").withPosOf(valueExp), case KeyValueExp(keyExp, nameExp):
[uniqueVarSymbol, Symbol(Std.string(idx++)).withPosOf(valueExp)]).withPosOf(valueExp), CallExp(Symbol("dict-get").withPosOf(valueExp), [uniqueVarSymbol, keyExp]).withPosOf(valueExp);
k, if (isFinal == false) false else null) default:
CallExp(Symbol("nth").withPosOf(valueExp),
[uniqueVarSymbol, Symbol(Std.string(idx++)).withPosOf(valueExp)]).withPosOf(valueExp);
}, k, if (isFinal == false) false else null)
]); ]);
default: default:
throw CompileError.fromExp(namesExp, "Can only bind variables to a symbol or list of symbols for destructuring"); throw CompileError.fromExp(namesExp, "Can only bind variables to a symbol or list of symbols for destructuring");

View File

@@ -348,4 +348,9 @@
(Assert.equals "me" (dict-get myMap "found")) (Assert.equals "me" (dict-get myMap "found"))
(doFor =>key value myMap (doFor =>key value myMap
(Assert.isTrue (<= 0 (.indexOf ["hey" "found"] key))) (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)))