Add ', `, ,, reader macros
diff --git a/src/lisp/lisp.c b/src/lisp/lisp.c
index 2d920ea..5006aa3 100644
--- a/src/lisp/lisp.c
+++ b/src/lisp/lisp.c
@@ -248,6 +248,8 @@
bool readint(struct istream *is, value_t *val)
{
+ skipws(is);
+
int number = 0;
if (!isdigit(is->peek(is)))
@@ -263,8 +265,70 @@
return true;
}
+bool readquote(struct istream *is, value_t *val)
+{
+ skipws(is);
+
+ char c = is->peek(is);
+
+ if (c == '\'' || c == '`' || c == ',')
+ {
+ is->get(is);
+
+ if (c == '`' && is->peek(is) == '@')
+ {
+ // This is actually a splice
+ is->get(is);
+ c = '@';
+ }
+
+ // Read the next form and wrap it in the appropriate function
+
+ value_t wrapped;
+ bool has_next = read1(is, &wrapped);
+
+ if (!has_next)
+ {
+ fprintf(stderr, "Expected a form after reader macro char %c\n", c);
+ is->showpos(is, stderr);
+ err("Invalid reader macro");
+ return false;
+ }
+
+ value_t symbol = nil;
+
+ switch (c)
+ {
+ case '\'':
+ symbol = symval("quote");
+ break;
+ case '`':
+ symbol = symval("backquote");
+ break;
+ case ',':
+ symbol = symval("unquote");
+ break;
+ case '@':
+ symbol = symval("splice");
+ break;
+ }
+
+ *val = cons(symbol, cons(wrapped, nil));
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
bool read1(struct istream *is, value_t *val)
{
+ // This could all be one big short-circuiting || but that is ugly.
+ if (readquote(is, val))
+ return true;
+
if (readsym(is, val))
return true;
@@ -312,12 +376,25 @@
value_t v;
char *a = malloc_aligned(strlen(str) + 1);
+ strcpy(a, str);
v = (value_t)a;
v |= STRING_TAG;
return v;
}
+value_t symval(char *str)
+{
+ value_t v;
+
+ char *a = malloc_aligned(strlen(str) + 1);
+ strcpy(a, str);
+ v = (value_t)a;
+ v |= SYMBOL_TAG;
+
+ return v;
+}
+
bool integerp(value_t v)
{
return (v & INT_MASK) == INT_TAG;
diff --git a/src/lisp/lisp.h b/src/lisp/lisp.h
index 9078b45..56fa09f 100644
--- a/src/lisp/lisp.h
+++ b/src/lisp/lisp.h
@@ -100,8 +100,15 @@
bool readlist(struct istream *is, value_t *val);
bool readint(struct istream *is, value_t *val);
+/**
+ * Read a quoted form, including `'` (quote) `\`` (backquote) and `,` (unquote)
+ * @returns true if read successfully, and sets `val`.
+ */
+bool readquote(struct istream *is, value_t *val);
+
value_t intval(int i);
value_t strval(char *str);
+value_t symval(char *str);
value_t cons(value_t car, value_t cdr);
bool read1(struct istream *is, value_t *val);
value_t read(struct istream *is);
diff --git a/src/lisp/test.lisp b/src/lisp/test.lisp
index 9cfb8b7..3c8f9ea 100644
--- a/src/lisp/test.lisp
+++ b/src/lisp/test.lisp
@@ -17,3 +17,5 @@
(let1 (unused-but-bound (cons 5 6))
(let1 (val (cons 1 (cons 2 (cons 3 nil))))
(calls-gc val))))
+
+'(hello)
\ No newline at end of file