Implement simple quotation (no unquote yet though)

This commit is contained in:
Konstantin Nazarov 2024-09-07 20:31:39 +01:00
parent 02dce3e11c
commit 0b62026d27
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
7 changed files with 69 additions and 0 deletions

View file

@ -798,6 +798,28 @@ Result<Value> syntax_unwrap(const Value& value) {
return TRY(value.to<Syntax>()->expression());
}
Result<Value> syntax_unwrap_all(const Value& value) {
if (value.is<Syntax>()) {
auto val = TRY(value.to<Syntax>()->expression());
return syntax_unwrap_all(val);
}
if (value.is<Pair>()) {
auto res = Value(TRY(Nil::create()));
auto cur = TRY(value.copy());
while (!cur.is<Nil>()) {
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<Value> Syntax::first() const {
auto val = TRY(expression());
return val.first();

View file

@ -1298,3 +1298,4 @@ Result<Array> Array::append(const V& value) const {
Result<bool> syntax_is_list(const Value& value);
Result<bool> syntax_is_nil(const Value& value);
Result<Value> syntax_unwrap(const Value& value);
Result<Value> syntax_unwrap_all(const Value& value);

View file

@ -584,6 +584,22 @@ Result<Expression> Compiler::compile_def(Context& context, Symbol& op,
return std::move(ex);
}
Result<Expression> 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<Expression> Compiler::compile_fn(Context& context, Symbol& op,
const Value& expr) {
Context ctx = TRY(Context::create(context));
@ -880,6 +896,8 @@ Result<Expression> 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);
}

View file

@ -47,6 +47,8 @@ class Compiler {
const Value& expr);
Result<Expression> compile_def(Context& context, Symbol& op,
const Value& expr);
Result<Expression> compile_quote(Context& context, Symbol& op,
const Value& expr);
Result<Expression> compile_fn(Context& context, Symbol& op,
const Value& expr);
Result<Expression> compile_let(Context& context, Symbol& op,

View file

@ -63,6 +63,8 @@ Result<Value> 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<Value> Reader::read_nil() {
return ERROR(ReadError);
}
Result<Value> 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<Value> Reader::read_string() {
if (!match('"')) return ERROR(ReadError);
size_t start = position_.offset + 1;

View file

@ -41,6 +41,7 @@ class Reader {
Result<Value> read_symbol();
Result<Value> read_bool();
Result<Value> read_nil();
Result<Value> read_quote();
char32_t get(size_t offset = 0);
bool match(const char* str);

View file

@ -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)))