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 {
|
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);
|
||||||
|
@@ -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) {
|
||||||
|
case KeyValueExp(keyExp, nameExp):
|
||||||
|
CallExp(Symbol("dict-get").withPosOf(valueExp), [uniqueVarSymbol, keyExp]).withPosOf(valueExp);
|
||||||
|
default:
|
||||||
CallExp(Symbol("nth").withPosOf(valueExp),
|
CallExp(Symbol("nth").withPosOf(valueExp),
|
||||||
[uniqueVarSymbol, Symbol(Std.string(idx++)).withPosOf(valueExp)]).withPosOf(valueExp),
|
[uniqueVarSymbol, Symbol(Std.string(idx++)).withPosOf(valueExp)]).withPosOf(valueExp);
|
||||||
k, if (isFinal == false) false else null)
|
}, 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");
|
||||||
|
@@ -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)))
|
Reference in New Issue
Block a user