From f30590112182355e483ee105cdf58ec80b842b0a Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Sun, 11 Aug 2024 21:37:37 +0100 Subject: [PATCH] Return compiled function from the compile() --- src/arena.cpp | 13 +++++++++ src/arena.hpp | 1 + src/common.cpp | 36 ++++++++++++++++++++++--- src/common.hpp | 69 +++++++++++++++++++++++++++++++++++++----------- src/compiler.cpp | 16 ++++++++--- src/compiler.hpp | 2 ++ src/pod.hpp | 11 ++++++++ src/vli.cpp | 24 +++++++++++------ src/writer.cpp | 47 +++++++++++++++++++++++---------- src/writer.hpp | 33 ++++++++++++----------- 10 files changed, 192 insertions(+), 60 deletions(-) diff --git a/src/arena.cpp b/src/arena.cpp index 848ef1d..a8efa56 100644 --- a/src/arena.cpp +++ b/src/arena.cpp @@ -81,6 +81,8 @@ Result Arena::gc_pod(PodObject* obj) { return gc_dict((PodDict*)obj); case Tag::Opcode: return gc_opcode((PodOpcode*)obj); + case Tag::Function: + return gc_function((PodFunction*)obj); } return ERROR(TypeMismatch); @@ -192,6 +194,17 @@ Result Arena::gc_opcode(PodOpcode* obj) { return nobj; } +Result Arena::gc_function(PodFunction* obj) { + auto nobj = TRY(alloc()); + nobj->header.tag = Tag::Function; + nobj->arity = obj->arity; + nobj->name = TRY(gc_pod(obj->name.get())); + nobj->constants = TRY(gc_pod(obj->constants.get())); + nobj->code = TRY(gc_pod(obj->code.get())); + + return nobj; +} + Arena& get_arena() { if (current_arena == 0) die("Arena not set\n"); return *current_arena; diff --git a/src/arena.hpp b/src/arena.hpp index f21c009..449a843 100644 --- a/src/arena.hpp +++ b/src/arena.hpp @@ -155,6 +155,7 @@ class Arena { Result gc_bytearray(PodByteArray* obj); Result gc_dict(PodDict* obj); Result gc_opcode(PodOpcode* obj); + Result gc_function(PodFunction* obj); void add_root(GcRootList* node) { _gcroot.insert(node); } diff --git a/src/common.cpp b/src/common.cpp index af70f67..053d28f 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -38,6 +38,8 @@ Result Value::create(PodObject* obj) { return Value(TRY(Pair::create((PodPair*)obj))); case Tag::Opcode: return Value(TRY(Opcode::create((PodOpcode*)obj))); + case Tag::Function: + return Value(TRY(Function::create((PodFunction*)obj))); }; return Value(); } @@ -54,7 +56,7 @@ Result Symbol::create(String& rhs) { return Symbol(TRY(MkGcRoot(pod))); } -Result ByteArray::create(String& str) { +Result ByteArray::create(const String& str) { uint64_t size = 0; for (uint64_t i = 0; i < str.size(); i++) { size += utf8_codepoint_size(TRY(str[i])); @@ -105,6 +107,10 @@ Result Bool::copy() const { return Value(Bool(TRY(_value.copy()))); } Result Opcode::copy() const { return Value(Opcode(TRY(_value.copy()))); } +Result Function::copy() const { + return Value(Function(TRY(_value.copy()))); +} + Result Pair::create(Value& first, Value& rest) { auto pod = TRY(arena_alloc()); pod->header.tag = Tag::Pair; @@ -123,6 +129,30 @@ Result Pair::rest() { return Value::create(val); } +Result Function::create(const Value& name, uint64_t arity, + const Value& constants, const Value& code) { + auto pod = TRY(arena_alloc()); + pod->header.tag = Tag::Function; + pod->arity = arity; + pod->name = name.pod(); + pod->constants = constants.pod(); + pod->code = code.pod(); + + return Function(TRY(MkGcRoot(pod))); +} + +Result Function::name() const { + return Value::create(_value->name.get()); +} + +Result Function::code() const { + return Value::create(_value->code.get()); +} + +Result Function::constants() const { + return Value::create(_value->constants.get()); +} + Result reverse(Value& val) { if (!val.is()) return ERROR(TypeMismatch); @@ -140,7 +170,7 @@ Result reverse(Value& val) { return res; } -Result debug_print(String& val) { +Result debug_print(const String& val) { auto ba = TRY(ByteArray::create(val)); for (uint64_t i = 0; i < ba.size(); i++) { @@ -150,7 +180,7 @@ Result debug_print(String& val) { return Result(); } -Result debug_print(Value& val) { +Result debug_print(const Value& val) { auto w = Writer(); auto s = TRY(w.write_one(val)); return debug_print(s); diff --git a/src/common.hpp b/src/common.hpp index ed3500a..60d6d32 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -227,12 +227,12 @@ class ByteArray : public Object { return ByteArray(TRY(MkGcRoot(pod))); } - static Result create(String& str); + static Result create(const String& str); - uint64_t size() { return _value->size; } + uint64_t size() const { return _value->size; } virtual Result copy() const final; - Result operator[](uint64_t idx) { + Result operator[](uint64_t idx) const { if (idx >= _value->size) return ERROR(IndexOutOfRange); return _value->data[idx]; } @@ -421,7 +421,7 @@ class String : public Object { uint64_t size() const { return _value->size; } virtual Result copy() const final; - Result operator[](uint64_t idx) { + Result operator[](uint64_t idx) const { if (idx >= _value->size) return ERROR(IndexOutOfRange); return _value->data[idx]; } @@ -565,7 +565,7 @@ class Symbol : public Object { uint64_t size() const { return _value->size; } - Result operator[](uint64_t idx) { + Result operator[](uint64_t idx) const { if (idx >= _value->size) return ERROR(IndexOutOfRange); return _value->data[idx]; } @@ -659,7 +659,7 @@ class Int64 : public Object { return Int64(TRY(MkGcRoot(pod))); } - int64_t value() { return _value->value; } + int64_t value() const { return _value->value; } virtual Result copy() const final; @@ -699,7 +699,7 @@ class Float : public Object { return Float(TRY(MkGcRoot(pod))); } - double value() { return _value->value; } + double value() const { return _value->value; } virtual Result copy() const final; @@ -732,7 +732,7 @@ class Bool : public Object { return Bool(TRY(MkGcRoot(pod))); } - bool value() { return _value->value; } + bool value() const { return _value->value; } virtual Result copy() const final; @@ -773,17 +773,54 @@ class Opcode : public Object { return Opcode(TRY(MkGcRoot(pod))); } - Oc opcode() { return _value->opcode; } - OpArg arg1() { return _value->arg1; } - OpArg arg2() { return _value->arg2; } - OpArg arg3() { return _value->arg3; } - OpArg arg4() { return _value->arg4; } + Oc opcode() const { return _value->opcode; } + OpArg arg1() const { return _value->arg1; } + OpArg arg2() const { return _value->arg2; } + OpArg arg3() const { return _value->arg3; } + OpArg arg4() const { return _value->arg4; } virtual Result copy() const final; private: GcRoot _value; }; + +class Function : public Object { + public: + Function() {} + Function(Function&& rhs) : _value(std::move(rhs._value)) {} + Function(GcRoot&& val) : _value(std::move(val)) {} + + virtual Tag tag() const final { return Tag::Function; } + virtual PodObject* pod() const final { return _value.get(); } + virtual Result cmp(const Object& rhs) const final { + return -TRY(rhs.cmp(*this)); + } + virtual Result cmp(const Opcode& rhs) const final { return 0; } + + virtual void move(Object* obj) final { + new (obj) Function(std::move(_value)); + } + + static Result create(PodFunction* obj) { + return Function(TRY(MkGcRoot(obj))); + } + + static Result create(const Value& name, uint64_t arity, + const Value& constants, const Value& code); + + uint64_t arity() { return _value->arity; } + + Result name() const; + Result code() const; + Result constants() const; + + virtual Result copy() const final; + + private: + GcRoot _value; +}; + // note: this class doesn't perform proper destruction of objects in some cases class Value { public: @@ -830,7 +867,7 @@ class Value { } PodObject* pod() const { return ((Object*)buf)->pod(); } - Tag tag() { return ((Object*)buf)->tag(); } + Tag tag() const { return ((Object*)buf)->tag(); } Object& operator*() { return *(Object*)(buf); } Object* operator->() { return (Object*)(buf); } @@ -859,8 +896,8 @@ Result syntax_unwrap(Value& val); Result reverse(Value& val); -Result debug_print(String& val); -Result debug_print(Value& val); +Result debug_print(const String& val); +Result debug_print(const Value& val); template Result Dict::insert(const K& key, const V& value) { diff --git a/src/compiler.cpp b/src/compiler.cpp index 3274d83..ec8d33c 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -64,12 +64,16 @@ Result Compiler::compile(Value& expr) { auto context = TRY(Context::create()); auto ex = TRY(compile_expr(context, expr)); + TRY(ex.add_opcode(Oc::Ret, {0, (int64_t)ex.reg})); + Value name = TRY(Nil::create()); Value constants = TRY(context.constants.copy()); Value code = TRY(ex.code.copy()); - TRY(debug_print(constants)); - TRY(debug_print(code)); - return ERROR(NotImplemented); + // TRY(debug_print(constants)); + // TRY(debug_print(code)); + + auto fun = TRY(Function::create(name, 0, constants, code)); + return Value(std::move(fun)); } Result Compiler::compile_expr(Context& context, Value& expr) { @@ -88,6 +92,7 @@ Result Compiler::compile_expr(Context& context, Value& expr) { case Tag::ByteArray: case Tag::Dict: case Tag::Opcode: + case Tag::Function: return ERROR(TypeMismatch); } return ERROR(TypeMismatch); @@ -185,3 +190,8 @@ Result Compiler::compile_int64(Context& context, Int64& value) { ex.reg = reg; return std::move(ex); } + +Result compile(Value& expr) { + Compiler c = Compiler(); + return c.compile(expr); +} diff --git a/src/compiler.hpp b/src/compiler.hpp index 4ba20f3..2d0115a 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -34,3 +34,5 @@ class Compiler { Result compile_primop(Context& context, Symbol& op, Pair& expr); Result compile_int64(Context& context, Int64& value); }; + +Result compile(Value& expr); diff --git a/src/pod.hpp b/src/pod.hpp index 9d193a4..5d01def 100644 --- a/src/pod.hpp +++ b/src/pod.hpp @@ -19,6 +19,7 @@ enum class Tag : uint8_t { ByteArray, Dict, Opcode, + Function, }; template @@ -155,6 +156,16 @@ class PodOpcode final : public PodObject { OpArg arg4; }; +class PodFunction final : public PodObject { + public: + PodFunction() : PodObject(Tag::Function){}; + + uint64_t arity; + OffPtr name; + OffPtr constants; + OffPtr code; +}; + template class Ptr { public: diff --git a/src/vli.cpp b/src/vli.cpp index d30e9fd..ead2146 100644 --- a/src/vli.cpp +++ b/src/vli.cpp @@ -8,19 +8,27 @@ StaticArena<64 * 1024 * 1024> arena; -int main() { - auto s = DIEX(String::create("(* (+ 1 2 3) 4)")); +Result run() { + auto s = TRY(String::create("(* (+ 1 2 3) 4)")); auto reader = Reader(s); - auto r = DIEX(reader.read_one()); - auto s2 = DIEX(write_one(r)); + auto r = TRY(reader.read_one()); + auto s2 = TRY(write_one(r)); - DIEX(arena_gc()); + TRY(arena_gc()); - DIEX(debug_print(s2)); + TRY(debug_print(s2)); - Compiler c = Compiler(); - auto compiled = DIEX(c.compile(r)); + auto compiled = TRY(compile(r)); + Function& fun = *compiled.to(); + TRY(debug_print(TRY(fun.constants()))); + TRY(debug_print(TRY(fun.code()))); + + return Result(); +} + +int main() { + DIEX(run()); return 0; } diff --git a/src/writer.cpp b/src/writer.cpp index b6f396c..edafe0b 100644 --- a/src/writer.cpp +++ b/src/writer.cpp @@ -3,7 +3,7 @@ #include "error.hpp" #include "opcode.hpp" -Result Writer::write_one(Value& obj) { +Result Writer::write_one(const Value& obj) { switch (obj.tag()) { case Tag::Nil: return write_nil(*obj.to()); @@ -29,11 +29,13 @@ Result Writer::write_one(Value& obj) { return write_pair(*obj.to()); case Tag::Opcode: return write_opcode(*obj.to()); + case Tag::Function: + return write_function(*obj.to()); }; return String(); } -Result Writer::write_int64(Int64& val) { +Result Writer::write_int64(const Int64& val) { char tmp[32]; sprintf(tmp, "%lu", val.value()); size_t len = strlen(tmp); @@ -51,7 +53,7 @@ bool needs_dot(char* str) { return !has_e && !has_dot; } -Result Writer::write_float(Float& val) { +Result Writer::write_float(const Float& val) { char tmp[32]; sprintf(tmp, "%g", val.value()); size_t len = strlen(tmp); @@ -66,19 +68,21 @@ Result Writer::write_float(Float& val) { return String::create(tmp); } -Result Writer::write_nil(Nil& val) { return String::create("nil"); } +Result Writer::write_nil(const Nil& val) { + return String::create("nil"); +} -Result Writer::write_bool(Bool& val) { +Result Writer::write_bool(const Bool& val) { if (val.value()) return String::create("true"); return String::create("false"); } -Result Writer::write_bytearray(ByteArray& val) { +Result Writer::write_bytearray(const ByteArray& val) { return ERROR(NotImplemented); } -Result Writer::write_string(String& val) { +Result Writer::write_string(const String& val) { String res = TRY(String::create("\"")); // TODO: optimize this @@ -129,7 +133,7 @@ int is_valid_symbol_char(char32_t codepoint) { codepoint == '_' || codepoint == '~'; } -Result Writer::write_symbol(Symbol& val) { +Result Writer::write_symbol(const Symbol& val) { String res = TRY(String::create("")); // TODO: optimize this @@ -144,11 +148,11 @@ Result Writer::write_symbol(Symbol& val) { return res; } -Result Writer::write_syntax(Syntax& val) { +Result Writer::write_syntax(const Syntax& val) { return ERROR(NotImplemented); } -Result Writer::write_pair(Pair& val) { +Result Writer::write_pair(const Pair& val) { String res = TRY(String::create("(")); Value cur = TRY(val.copy()); @@ -173,7 +177,7 @@ Result Writer::write_pair(Pair& val) { return res; } -Result Writer::write_array(Array& val) { +Result Writer::write_array(const Array& val) { String res = TRY(String::create("[")); bool is_first = true; @@ -192,7 +196,7 @@ Result Writer::write_array(Array& val) { return res; } -Result Writer::write_dict(Dict& val) { +Result Writer::write_dict(const Dict& val) { String res = TRY(String::create("{")); bool is_first = true; @@ -217,7 +221,7 @@ Result Writer::write_dict(Dict& val) { return res; } -Result Writer::write_opcode(Opcode& val) { +Result Writer::write_opcode(const Opcode& val) { String res = TRY(String::create("# Writer::write_opcode(Opcode& val) { return res; } -Result write_one(Value& value) { +Result Writer::write_function(const Function& val) { + auto name = TRY(val.name()); + if (name.is()) { + return TRY(String::create("#")); + } + + if (!name.is()) return ERROR(TypeMismatch); + String& name_str = *name.to(); + + String res = TRY(String::create("#")); + return res; +} + +Result write_one(const Value& value) { auto w = Writer(); return w.write_one(value); } diff --git a/src/writer.hpp b/src/writer.hpp index c0630ea..4888473 100644 --- a/src/writer.hpp +++ b/src/writer.hpp @@ -7,28 +7,29 @@ class Writer { public: Writer(){}; - Result write_one(Value& obj); - Result write_multiple(Value& obj); + Result write_one(const Value& obj); + Result write_multiple(const Value& obj); private: - Result write_int64(Int64& val); - Result write_float(Float& val); - Result write_string(String& val); - Result write_pair(Pair& val); - Result write_nil(Nil& val); - Result write_bool(Bool& val); - Result write_array(Array& val); - Result write_bytearray(ByteArray& val); - Result write_dict(Dict& val); - Result write_symbol(Symbol& val); - Result write_syntax(Syntax& val); - Result write_opcode(Opcode& val); + Result write_int64(const Int64& val); + Result write_float(const Float& val); + Result write_string(const String& val); + Result write_pair(const Pair& val); + Result write_nil(const Nil& val); + Result write_bool(const Bool& val); + Result write_array(const Array& val); + Result write_bytearray(const ByteArray& val); + Result write_dict(const Dict& val); + Result write_symbol(const Symbol& val); + Result write_syntax(const Syntax& val); + Result write_opcode(const Opcode& val); + Result write_function(const Function& val); }; -Result write_one(Value& value); +Result write_one(const Value& value); template -Result write_one(T& value) +Result write_one(const T& value) requires std::derived_from { auto w = Writer();