KeyValueExps allow map literals

This commit is contained in:
2020-12-07 18:28:12 -07:00
parent 857941647a
commit 544579a4d3
4 changed files with 32 additions and 3 deletions

View File

@@ -135,8 +135,18 @@ class Kiss {
ECast(convert(innerExp), if (type.length > 0) Helpers.parseComplexType(type, exp) else null).withMacroPosOf(wholeExp); ECast(convert(innerExp), if (type.length > 0) Helpers.parseComplexType(type, exp) else null).withMacroPosOf(wholeExp);
*/ */
case ListExp(elements): case ListExp(elements):
var arrayDecl = EArrayDecl([for (elementExp in elements) convert(elementExp)]).withMacroPosOf(exp); var isMap = false;
if (k.wrapListExps) { var arrayDecl = EArrayDecl([
for (elementExp in elements) {
switch (elementExp.def) {
case KeyValueExp(_, _):
isMap = true;
default:
}
convert(elementExp);
}
]).withMacroPosOf(exp);
if (!isMap && k.wrapListExps) {
ENew({ ENew({
pack: ["kiss"], pack: ["kiss"],
name: "List" name: "List"
@@ -148,6 +158,8 @@ class Kiss {
Context.parse(code, exp.macroPos()); Context.parse(code, exp.macroPos());
case FieldExp(field, innerExp): case FieldExp(field, innerExp):
EField(convert(innerExp), field).withMacroPosOf(exp); EField(convert(innerExp), field).withMacroPosOf(exp);
case KeyValueExp(keyExp, valueExp):
EBinop(OpArrow, convert(keyExp), convert(valueExp)).withMacroPosOf(exp);
default: default:
throw CompileError.fromExp(exp, 'conversion not implemented'); throw CompileError.fromExp(exp, 'conversion not implemented');
}; };

View File

@@ -19,6 +19,7 @@ enum ReaderExpDef {
TypedExp(path:String, exp:ReaderExp); // :type [exp] TypedExp(path:String, exp:ReaderExp); // :type [exp]
MetaExp(meta:String, exp:ReaderExp); // &meta [exp] MetaExp(meta:String, exp:ReaderExp); // &meta [exp]
FieldExp(field:String, exp:ReaderExp); // .field [exp] FieldExp(field:String, exp:ReaderExp); // .field [exp]
KeyValueExp(key:ReaderExp, value:ReaderExp); // =>key value
} }
typedef ReadFunction = (Stream) -> Null<ReaderExpDef>; typedef ReadFunction = (Stream) -> Null<ReaderExpDef>;
@@ -57,6 +58,9 @@ class Reader {
// Lets you dot-access a function result without binding it to a name // Lets you dot-access a function result without binding it to a name
readTable["."] = (stream:Stream) -> FieldExp(nextToken(stream, "a field name"), assertRead(stream, readTable)); readTable["."] = (stream:Stream) -> FieldExp(nextToken(stream, "a field name"), assertRead(stream, readTable));
// Lets you construct key-value pairs for map literals or for-loops
readTable["=>"] = (stream:Stream) -> KeyValueExp(assertRead(stream, readTable), assertRead(stream, readTable));
// Because macro keys are sorted by length and peekChars(0) returns "", this will be used as the default reader macro: // Because macro keys are sorted by length and peekChars(0) returns "", this will be used as the default reader macro:
readTable[""] = (stream) -> Symbol(nextToken(stream, "a symbol name")); readTable[""] = (stream) -> Symbol(nextToken(stream, "a symbol name"));
// TODO make - A macro for numerical negation // TODO make - A macro for numerical negation
@@ -173,6 +177,8 @@ class Reader {
'&$meta ${exp.def.toString()}'; '&$meta ${exp.def.toString()}';
case FieldExp(field, exp): case FieldExp(field, exp):
'.$field ${exp.def.toString()}'; '.$field ${exp.def.toString()}';
case KeyValueExp(keyExp, valueExp):
'=>${keyExp.def.toString()} ${valueExp.def.toString()}';
} }
} }
} }

View File

@@ -242,6 +242,10 @@ class BasicTestCase extends Test {
function testCase() { function testCase() {
_testCase(); _testCase();
} }
function testMaps() {
_testMaps();
}
} }
class BasicObject { class BasicObject {

View File

@@ -340,3 +340,10 @@
(otherwise (Assert.fail))) (otherwise (Assert.fail)))
(Assert.equals 5 (case (toOption 0) (Assert.equals 5 (case (toOption 0)
(otherwise 5)))) (otherwise 5))))
(defun _testMaps []
(deflocal :Map<String,String> myMap [=>"hey" "you"
=>"found" "me"])
(Assert.equals "you" (dict-get myMap "hey"))
(Assert.equals "me" (dict-get myMap "found"))
)