Implement simple quotation (no unquote yet though)
This commit is contained in:
parent
02dce3e11c
commit
0b62026d27
7 changed files with 69 additions and 0 deletions
|
@ -798,6 +798,28 @@ Result<Value> syntax_unwrap(const Value& value) {
|
||||||
return TRY(value.to<Syntax>()->expression());
|
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 {
|
Result<Value> Syntax::first() const {
|
||||||
auto val = TRY(expression());
|
auto val = TRY(expression());
|
||||||
return val.first();
|
return val.first();
|
||||||
|
|
|
@ -1298,3 +1298,4 @@ Result<Array> Array::append(const V& value) const {
|
||||||
Result<bool> syntax_is_list(const Value& value);
|
Result<bool> syntax_is_list(const Value& value);
|
||||||
Result<bool> syntax_is_nil(const Value& value);
|
Result<bool> syntax_is_nil(const Value& value);
|
||||||
Result<Value> syntax_unwrap(const Value& value);
|
Result<Value> syntax_unwrap(const Value& value);
|
||||||
|
Result<Value> syntax_unwrap_all(const Value& value);
|
||||||
|
|
|
@ -584,6 +584,22 @@ Result<Expression> Compiler::compile_def(Context& context, Symbol& op,
|
||||||
return std::move(ex);
|
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,
|
Result<Expression> Compiler::compile_fn(Context& context, Symbol& op,
|
||||||
const Value& expr) {
|
const Value& expr) {
|
||||||
Context ctx = TRY(Context::create(context));
|
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);
|
return compile_fn(context, sym, expr);
|
||||||
} else if (TRY(sym.cmp("let")) == 0) {
|
} else if (TRY(sym.cmp("let")) == 0) {
|
||||||
return compile_let(context, sym, expr);
|
return compile_let(context, sym, expr);
|
||||||
|
} else if (TRY(sym.cmp("quote")) == 0) {
|
||||||
|
return compile_quote(context, sym, expr);
|
||||||
} else {
|
} else {
|
||||||
return compile_function_call(context, expr);
|
return compile_function_call(context, expr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,8 @@ class Compiler {
|
||||||
const Value& expr);
|
const Value& expr);
|
||||||
Result<Expression> compile_def(Context& context, Symbol& op,
|
Result<Expression> compile_def(Context& context, Symbol& op,
|
||||||
const Value& expr);
|
const Value& expr);
|
||||||
|
Result<Expression> compile_quote(Context& context, Symbol& op,
|
||||||
|
const Value& expr);
|
||||||
Result<Expression> compile_fn(Context& context, Symbol& op,
|
Result<Expression> compile_fn(Context& context, Symbol& op,
|
||||||
const Value& expr);
|
const Value& expr);
|
||||||
Result<Expression> compile_let(Context& context, Symbol& op,
|
Result<Expression> compile_let(Context& context, Symbol& op,
|
||||||
|
|
|
@ -63,6 +63,8 @@ Result<Value> Reader::read_one() {
|
||||||
return read_array();
|
return read_array();
|
||||||
} else if (match('{')) {
|
} else if (match('{')) {
|
||||||
return read_dict();
|
return read_dict();
|
||||||
|
} else if (match('\'')) {
|
||||||
|
return read_quote();
|
||||||
}
|
}
|
||||||
|
|
||||||
position_ = saved_position;
|
position_ = saved_position;
|
||||||
|
@ -351,6 +353,26 @@ Result<Value> Reader::read_nil() {
|
||||||
return ERROR(ReadError);
|
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() {
|
Result<Value> Reader::read_string() {
|
||||||
if (!match('"')) return ERROR(ReadError);
|
if (!match('"')) return ERROR(ReadError);
|
||||||
size_t start = position_.offset + 1;
|
size_t start = position_.offset + 1;
|
||||||
|
|
|
@ -41,6 +41,7 @@ class Reader {
|
||||||
Result<Value> read_symbol();
|
Result<Value> read_symbol();
|
||||||
Result<Value> read_bool();
|
Result<Value> read_bool();
|
||||||
Result<Value> read_nil();
|
Result<Value> read_nil();
|
||||||
|
Result<Value> read_quote();
|
||||||
|
|
||||||
char32_t get(size_t offset = 0);
|
char32_t get(size_t offset = 0);
|
||||||
bool match(const char* str);
|
bool match(const char* str);
|
||||||
|
|
|
@ -13,3 +13,6 @@
|
||||||
;; Accessing collections by symbol
|
;; Accessing collections by symbol
|
||||||
(assert (= (get {:foo 1 :bar 2} :bar)
|
(assert (= (get {:foo 1 :bar 2} :bar)
|
||||||
2))
|
2))
|
||||||
|
|
||||||
|
;; quotes
|
||||||
|
(assert (= '(1 2 3) (list 1 2 3)))
|
||||||
|
|
Loading…
Reference in a new issue