From 3afad56f71d58f75f3ff47379483090c00c33622 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Wed, 9 Dec 2020 21:46:07 -0700 Subject: [PATCH] Refactor reader macros in AOC Day 8 pt 1 --- kiss/src/kiss/Helpers.hx | 12 ++++++-- kiss/src/kiss/Reader.hx | 8 +++-- kiss/src/kiss/Stream.hx | 2 +- projects/aoc/src/year2020/BootCodeDSL.kiss | 34 +++++----------------- 4 files changed, 25 insertions(+), 31 deletions(-) diff --git a/kiss/src/kiss/Helpers.hx b/kiss/src/kiss/Helpers.hx index f5fd1350..0be308d5 100644 --- a/kiss/src/kiss/Helpers.hx +++ b/kiss/src/kiss/Helpers.hx @@ -197,6 +197,7 @@ class Helpers { interp.variables.set("read", Reader.assertRead.bind(_, k.readTable)); interp.variables.set("readExpArray", Reader.readExpArray.bind(_, _, k.readTable)); interp.variables.set("ReaderExp", ReaderExpDef); + interp.variables.set("nextToken", Reader.nextToken.bind(_, "a token")); interp.variables.set("kiss", { Reader: { ReaderExpDef: ReaderExpDef @@ -247,8 +248,15 @@ class Helpers { FieldExp(field, evalUnquotes(innerExp, k, args)); case KeyValueExp(keyExp, valueExp): KeyValueExp(evalUnquotes(keyExp, k, args), evalUnquotes(valueExp, k, args)); - case Unquote(exp): - runAtCompileTime(exp, k, args).def; + case Unquote(innerExp): + var unquoteValue:Dynamic = runAtCompileTime(innerExp, k, args); + if (unquoteValue == null) { + throw CompileError.fromExp(innerExp, "unquote evaluated to null"); + } else if (Std.isOfType(unquoteValue, ReaderExpDef)) { + unquoteValue; + } else { + unquoteValue.def; + }; default: throw CompileError.fromExp(exp, 'unquote evaluation not implemented'); }; diff --git a/kiss/src/kiss/Reader.hx b/kiss/src/kiss/Reader.hx index 124b78b2..45616fdd 100644 --- a/kiss/src/kiss/Reader.hx +++ b/kiss/src/kiss/Reader.hx @@ -93,8 +93,12 @@ class Reader { public static final terminators = [")", "]", "/*", "\n", " "]; - static function nextToken(stream:Stream, expect:String) { - return stream.expect(expect, () -> stream.takeUntilOneOf(terminators)); + public static function nextToken(stream:Stream, expect:String) { + var tok = stream.expect(expect, () -> stream.takeUntilOneOf(terminators)); + if (tok.length == 0) { + throw 'Expected token $expect at ${stream.position()}'; + } + return tok; } public static function assertRead(stream:Stream, readTable:Map):ReaderExp { diff --git a/kiss/src/kiss/Stream.hx b/kiss/src/kiss/Stream.hx index 4531d99f..7fc3175c 100644 --- a/kiss/src/kiss/Stream.hx +++ b/kiss/src/kiss/Stream.hx @@ -158,7 +158,7 @@ class Stream { switch (f()) { case Some(s): return s; - case None: + default: throw 'Expected $whatToExpect at $position'; } } diff --git a/projects/aoc/src/year2020/BootCodeDSL.kiss b/projects/aoc/src/year2020/BootCodeDSL.kiss index f2efb688..efa0e5d5 100644 --- a/projects/aoc/src/year2020/BootCodeDSL.kiss +++ b/projects/aoc/src/year2020/BootCodeDSL.kiss @@ -1,28 +1,10 @@ (load "BootCodeCommon.kiss") -(defreadermacro "" [stream] #| ReaderExp.CallExp( - { - pos: {file: "bleh", line: 1, column: 1, absoluteChar: 1}, - def: ReaderExp.Symbol(stream.expect("an instruction", function () { stream.takeUntilAndDrop(" "); })) - }, - [ - { - pos: {file: "fefea", line: 1, column: 1, absoluteChar: 1}, - def: ReaderExp.CallExp( - { - pos: {file: "treh", line: 1, column: 1, absoluteChar: 1}, - def: ReaderExp.Symbol(stream.expect("+/-", function () { stream.takeChars(1); })) - }, - [ - { - pos: {file: "smeeh", line: 1, column: 1, absoluteChar: 1}, - def: ReaderExp.Symbol("0") - }, - { - pos: {file: "greeeh", line: 1, column: 1, absoluteChar: 1}, - def: ReaderExp.Symbol(stream.expect("an argument", function () { stream.takeUntilAndDrop("\n"); })) - } - ]) - } - ]) - |#) \ No newline at end of file +(defreadermacro "" [stream] + `(,(ReaderExp.Symbol + (begin (stream.dropWhitespace) (nextToken stream))) + (,(ReaderExp.Symbol + (begin (stream.dropWhitespace) (stream.expect "+/-" (lambda [] (stream.takeChars 1))))) + 0 + ,(ReaderExp.Symbol + (nextToken stream))))) \ No newline at end of file