From 0b62026d270d1198e696ea7657b7876d96b359e1 Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Sat, 7 Sep 2024 20:31:39 +0100 Subject: [PATCH] Implement simple quotation (no unquote yet though) --- src/common.cpp | 22 ++++++++++++++++++++++ src/common.hpp | 1 + src/compiler.cpp | 18 ++++++++++++++++++ src/compiler.hpp | 2 ++ src/reader.cpp | 22 ++++++++++++++++++++++ src/reader.hpp | 1 + test/collections.vli | 3 +++ 7 files changed, 69 insertions(+) diff --git a/src/common.cpp b/src/common.cpp index 014c51d..dd8d970 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -798,6 +798,28 @@ Result syntax_unwrap(const Value& value) { return TRY(value.to()->expression()); } +Result syntax_unwrap_all(const Value& value) { + if (value.is()) { + auto val = TRY(value.to()->expression()); + return syntax_unwrap_all(val); + } + + if (value.is()) { + auto res = Value(TRY(Nil::create())); + auto cur = TRY(value.copy()); + + while (!cur.is()) { + auto val = TRY(syntax_unwrap_all(TRY(cur.first()))); + res = Value(TRY(Pair::create(val, res))); + + cur = TRY(cur.rest()); + } + return reverse(res); + } + + return value.copy(); +} + Result Syntax::first() const { auto val = TRY(expression()); return val.first(); diff --git a/src/common.hpp b/src/common.hpp index e28e3da..1bb340e 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -1298,3 +1298,4 @@ Result Array::append(const V& value) const { Result syntax_is_list(const Value& value); Result syntax_is_nil(const Value& value); Result syntax_unwrap(const Value& value); +Result syntax_unwrap_all(const Value& value); diff --git a/src/compiler.cpp b/src/compiler.cpp index 523d35d..efe7583 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -584,6 +584,22 @@ Result Compiler::compile_def(Context& context, Symbol& op, return std::move(ex); } +Result Compiler::compile_quote(Context& context, Symbol& op, + const Value& expr) { + auto quoted = TRY(expr.second()); + quoted = TRY(syntax_unwrap_all(quoted)); + + uint64_t maxreg = context.maxreg; + Expression ex = TRY(Expression::create()); + + int64_t quoted_const = TRY(context.add_const(quoted)); + TRY(ex.add_opcode(Oc::Mov, {0, (int64_t)maxreg}, {1, (int64_t)quoted_const})); + + ex.reg = maxreg; + context.maxreg = maxreg + 1; + + return std::move(ex); +} Result Compiler::compile_fn(Context& context, Symbol& op, const Value& expr) { Context ctx = TRY(Context::create(context)); @@ -880,6 +896,8 @@ Result Compiler::compile_list(Context& context, const Value& expr) { return compile_fn(context, sym, expr); } else if (TRY(sym.cmp("let")) == 0) { return compile_let(context, sym, expr); + } else if (TRY(sym.cmp("quote")) == 0) { + return compile_quote(context, sym, expr); } else { return compile_function_call(context, expr); } diff --git a/src/compiler.hpp b/src/compiler.hpp index b4b611b..bdcd97a 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -47,6 +47,8 @@ class Compiler { const Value& expr); Result compile_def(Context& context, Symbol& op, const Value& expr); + Result compile_quote(Context& context, Symbol& op, + const Value& expr); Result compile_fn(Context& context, Symbol& op, const Value& expr); Result compile_let(Context& context, Symbol& op, diff --git a/src/reader.cpp b/src/reader.cpp index 9e9dbab..55ba9c2 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -63,6 +63,8 @@ Result Reader::read_one() { return read_array(); } else if (match('{')) { return read_dict(); + } else if (match('\'')) { + return read_quote(); } position_ = saved_position; @@ -351,6 +353,26 @@ Result Reader::read_nil() { return ERROR(ReadError); } +Result Reader::read_quote() { + if (!match('\'')) return ERROR(ReadError); + SourcePosition start = position_; + forward(); + + auto sym = Value(TRY(Symbol::create("quote"))); + + auto subexpr = TRY(read_one()); + SourcePosition end = position_; + + auto res = Value(TRY(Pair::create(subexpr, TRY(Nil::create())))); + res = Value(TRY(Pair::create(sym, res))); + + if (!_syntax) { + return res; + } else { + return Value(TRY(Syntax::create(_fname, start, end, res))); + } +} + Result Reader::read_string() { if (!match('"')) return ERROR(ReadError); size_t start = position_.offset + 1; diff --git a/src/reader.hpp b/src/reader.hpp index 23fb722..89f3314 100644 --- a/src/reader.hpp +++ b/src/reader.hpp @@ -41,6 +41,7 @@ class Reader { Result read_symbol(); Result read_bool(); Result read_nil(); + Result read_quote(); char32_t get(size_t offset = 0); bool match(const char* str); diff --git a/test/collections.vli b/test/collections.vli index 0f85575..1f0f616 100644 --- a/test/collections.vli +++ b/test/collections.vli @@ -13,3 +13,6 @@ ;; Accessing collections by symbol (assert (= (get {:foo 1 :bar 2} :bar) 2)) + +;; quotes +(assert (= '(1 2 3) (list 1 2 3)))