diff --git a/CMakeLists.txt b/CMakeLists.txt index 5934c14..17ccdf2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(vm_lib src/vm.cpp src/common.cpp src/arena.cpp + src/error.cpp src/reader.cpp src/writer.cpp src/utf8.cpp diff --git a/src/arena.cpp b/src/arena.cpp index b3b7075..e89aeae 100644 --- a/src/arena.cpp +++ b/src/arena.cpp @@ -81,7 +81,7 @@ Result Arena::gc_pod(PodObject* obj) { return gc_dict((PodDict*)obj); } - return ErrorCode::TypeMismatch; + return ERROR(TypeMismatch); } Result Arena::gc_nil(PodNil* obj) { @@ -128,7 +128,7 @@ Result Arena::gc_symbol(PodSymbol* obj) { } Result Arena::gc_syntax(PodSyntax* obj) { - return ErrorCode::NotImplemented; + return ERROR(NotImplemented); } Result Arena::gc_pair(PodPair* obj) { @@ -176,7 +176,6 @@ Result Arena::gc_dict(PodDict* obj) { nobj->data[i] = TRY(gc_pod(val)); } return nobj; - // return ErrorCode::NotImplemented; } Arena& get_arena() { diff --git a/src/arena.hpp b/src/arena.hpp index b954bd3..98fac15 100644 --- a/src/arena.hpp +++ b/src/arena.hpp @@ -102,8 +102,7 @@ class ArenaHeap { // padding for guard value uint64_t boundary_size = 8; - if (boundary + size + boundary_size >= bufsize) - return ErrorCode::OutOfMemory; + if (boundary + size + boundary_size >= bufsize) return ERROR(OutOfMemory); void* res = buf + boundary; boundary += size; ASAN_UNPOISON_MEMORY_REGION(res, size); diff --git a/src/common.cpp b/src/common.cpp index 3fa2268..9a39bfd 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -120,13 +120,13 @@ Result Pair::rest() { } Result reverse(Value& val) { - if (!val.is()) return ErrorCode::TypeMismatch; + if (!val.is()) return ERROR(TypeMismatch); auto res = Value(TRY(Nil::create())); auto cur = TRY(val.copy()); while (!cur.is()) { - if (!cur.is()) return ErrorCode::TypeMismatch; + if (!cur.is()) return ERROR(TypeMismatch); Pair& pair = *cur.to(); Value first = TRY(pair.first()); cur = TRY(pair.rest()); @@ -153,13 +153,13 @@ Result debug_print(Value& val) { } Result Array::get(uint64_t idx) { - if (idx >= _value->size) return ErrorCode::IndexOutOfRange; + if (idx >= _value->size) return ERROR(IndexOutOfRange); auto val = _value->data[idx].get(); return Value::create(val); } Result Array::get(Value& key) { - if (!key.is()) return ErrorCode::TypeMismatch; + if (!key.is()) return ERROR(TypeMismatch); return get(key.to()->value()); } @@ -185,11 +185,11 @@ short cmp_tag(Tag lhs, Tag rhs) { Result Dict::get(Value& key) { auto pos = TRY(find(key)); - if (pos > size()) return ErrorCode::KeyError; + if (pos > size()) return ERROR(KeyError); auto k = TRY(Value::create(_value->data[pos * 2].get())); if (TRY(k.cmp(key)) != 0) { - return ErrorCode::KeyError; + return ERROR(KeyError); } return TRY(Value::create(_value->data[pos * 2 + 1].get())); @@ -280,4 +280,4 @@ Result Dict::cmp(Dict& rhs) { return 0; } -Result Object::get(Value& key) { return ErrorCode::TypeMismatch; } +Result Object::get(Value& key) { return ERROR(TypeMismatch); } diff --git a/src/common.hpp b/src/common.hpp index 3d3c498..a328767 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -143,7 +143,7 @@ class Array : public Object { } Result sub(uint64_t start, uint64_t end) { - if (start > end) return ErrorCode::IndexOutOfRange; + if (start > end) return ERROR(IndexOutOfRange); uint64_t res_size = end - start; auto pod = TRY(arena_alloc(res_size * sizeof(PodObject*))); pod->size = res_size; @@ -208,7 +208,7 @@ class ByteArray : public Object { virtual Result copy() const final; Result operator[](uint64_t idx) { - if (idx >= _value->size) return ErrorCode::IndexOutOfRange; + if (idx >= _value->size) return ERROR(IndexOutOfRange); return _value->data[idx]; } @@ -251,7 +251,7 @@ class ByteArray : public Object { } Result sub(uint64_t start, uint64_t end) { - if (start > end) return ErrorCode::IndexOutOfRange; + if (start > end) return ERROR(IndexOutOfRange); uint64_t res_size = end - start; auto pod = TRY(arena_alloc(res_size * sizeof(char))); pod->size = res_size; @@ -393,7 +393,7 @@ class String : public Object { virtual Result copy() const final; Result operator[](uint64_t idx) { - if (idx >= _value->size) return ErrorCode::IndexOutOfRange; + if (idx >= _value->size) return ERROR(IndexOutOfRange); return _value->data[idx]; } @@ -439,7 +439,7 @@ class String : public Object { } Result sub(uint64_t start, uint64_t end) { - if (start > end) return ErrorCode::IndexOutOfRange; + if (start > end) return ERROR(IndexOutOfRange); uint64_t res_size = end - start; auto pod = TRY(arena_alloc(res_size * sizeof(char32_t))); pod->header.tag = Tag::String; @@ -483,6 +483,26 @@ class Symbol : public Object { } return 0; } + virtual Result cmp(const char* rhs) final { + auto lsize = size(); + auto rsize = strlen(rhs); + uint64_t i = 0; + uint64_t j = 0; + while (1) { + if (i == lsize && j == lsize) return 0; + + short cmp = short(i == lsize) - short(j == rsize); + if (cmp != 0) return cmp; + + char32_t lc = _value->data[i]; + char32_t rc = rhs[j]; + cmp = (lc > rc) - (lc < rc); + if (cmp != 0) return cmp; + i++; + j++; + } + return 0; + } virtual void move(Object* obj) final { new (obj) Symbol(std::move(_value)); } static Result create(PodSymbol* obj) { @@ -515,7 +535,7 @@ class Symbol : public Object { uint64_t size() { return _value->size; } Result operator[](uint64_t idx) { - if (idx >= _value->size) return ErrorCode::IndexOutOfRange; + if (idx >= _value->size) return ERROR(IndexOutOfRange); return _value->data[idx]; } diff --git a/src/compiler.cpp b/src/compiler.cpp index 3d42fa1..b130079 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -21,8 +21,9 @@ struct Context { uint64_t maxconst; }; -bool is_primitive_op(Symbol& sym) { - // return (sym.cmp("+") == 0); +Result is_primitive_op(Symbol& sym) { + return TRY(sym.cmp("+")) == 0 || TRY(sym.cmp("-")) == 0 || + TRY(sym.cmp("*")) == 0 || TRY(sym.cmp("/")) == 0; return false; } @@ -30,7 +31,7 @@ Result Compiler::compile(Value& expr) { auto context = TRY(Context::create()); TRY(compile_expr(context, expr)); - return ErrorCode::NotImplemented; + return ERROR(NotImplemented); } Result Compiler::compile_expr(Context& context, Value& expr) { switch (expr.tag()) { @@ -46,16 +47,36 @@ Result Compiler::compile_expr(Context& context, Value& expr) { case Tag::Array: case Tag::ByteArray: case Tag::Dict: - return ErrorCode::TypeMismatch; + return ERROR(TypeMismatch); } - return ErrorCode::TypeMismatch; + return ERROR(TypeMismatch); } +Result Compiler::compile_primop(Context& context, Symbol& op, + Pair& expr) { + std::cout << "primop\n"; + + Value cur = TRY(expr.rest()); + Array code = TRY(Array::create()); + + while (!cur.is()) { + Pair& pair = *cur.to(); + auto subexpr = TRY(pair.first()); + + auto comp = TRY(compile_expr(context, subexpr)); + + cur = TRY(pair.rest()); + } + return ERROR(TypeMismatch); +} Result Compiler::compile_list(Context& context, Pair& expr) { auto first = TRY(expr.first()); if (first.is()) { Symbol& sym = *first.to(); + if (TRY(is_primitive_op(sym))) { + return compile_primop(context, sym, expr); + } } - return ErrorCode::TypeMismatch; + return ERROR(TypeMismatch); } diff --git a/src/compiler.hpp b/src/compiler.hpp index 2bc4181..5591bec 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -18,4 +18,5 @@ class Compiler { Result compile(Value& expr); Result compile_expr(Context& context, Value& expr); Result compile_list(Context& context, Pair& expr); + Result compile_primop(Context& context, Symbol& op, Pair& expr); }; diff --git a/src/error.cpp b/src/error.cpp new file mode 100644 index 0000000..6d07093 --- /dev/null +++ b/src/error.cpp @@ -0,0 +1,6 @@ +#include "error.hpp" + +static const char* curerr = 0; + +void seterr(const char* err) { curerr = err; } +const char* geterr(void) { return curerr; } diff --git a/src/error.hpp b/src/error.hpp index ca1a07a..085dc6a 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -13,3 +13,15 @@ enum class ErrorCode { MalformedList, KeyError, }; + +void seterr(const char* err); +const char* geterr(void); + +#define STRINGIZE_NESTED(A) #A +#define STRINGIZE(A) STRINGIZE_NESTED(A) + +#define ERROR(code) \ + (({ \ + seterr("Error " STRINGIZE(code) " at " __FILE__ ":" STRINGIZE(__LINE__)); \ + ErrorCode::code; \ + })) diff --git a/src/pod.hpp b/src/pod.hpp index 15e8aab..fcd5277 100644 --- a/src/pod.hpp +++ b/src/pod.hpp @@ -153,12 +153,12 @@ class Ptr { T* operator->() { return _ptr; } Result get_int() { - if (_ptr->tag != Tag::Int64) return ErrorCode::TypeMismatch; + if (_ptr->tag != Tag::Int64) return ERROR(TypeMismatch); return ((PodInt64*)_ptr)->value; } Result get_float() { - if (_ptr->tag != Tag::Float) return ErrorCode::TypeMismatch; + if (_ptr->tag != Tag::Float) return ERROR(TypeMismatch); return ((PodFloat*)_ptr)->value; } diff --git a/src/reader.cpp b/src/reader.cpp index f4a1fc6..74de2fa 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -58,10 +58,10 @@ Result Reader::read_one() { } else if (match('[')) { // TODO: implement array // return read_array(); - return ErrorCode::ReadError; + return ERROR(ReadError); } else if (match('{')) { return read_dict(); - return ErrorCode::ReadError; + return ERROR(ReadError); } position_ = saved_position; @@ -69,7 +69,7 @@ Result Reader::read_one() { return read_symbol(); } - return ErrorCode::ReadError; + return ERROR(ReadError); } Result Reader::read_multiple() { @@ -85,11 +85,11 @@ Result Reader::read_multiple() { res = Value(TRY(Pair::create(val, res))); } - return ErrorCode::ReadError; + return ERROR(ReadError); } Result Reader::read_list() { - if (!match('(')) return ErrorCode::ReadError; + if (!match('(')) return ERROR(ReadError); forward(); @@ -99,7 +99,7 @@ Result Reader::read_list() { forward_whitespace(); if (is_eof()) { - return ErrorCode::ReadError; + return ERROR(ReadError); } if (match(')')) { @@ -112,11 +112,11 @@ Result Reader::read_list() { res = Value(TRY(Pair::create(val, res))); } - return ErrorCode::ReadError; + return ERROR(ReadError); } Result Reader::read_dict() { - if (!match('{')) return ErrorCode::ReadError; + if (!match('{')) return ERROR(ReadError); forward(); @@ -126,7 +126,7 @@ Result Reader::read_dict() { forward_whitespace(); if (is_eof()) { - return ErrorCode::ReadError; + return ERROR(ReadError); } if (match('}')) { @@ -140,25 +140,25 @@ Result Reader::read_dict() { res = TRY(res.insert(val1, val2)); } - return ErrorCode::ReadError; + return ERROR(ReadError); } Result Reader::read_bool() { if (match("true")) { forward(4); - if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError; + if (!is_separator(get()) && !is_eof()) return ERROR(ReadError); return Value(TRY(Bool::create(true))); } if (match("false")) { forward(5); - if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError; + if (!is_separator(get()) && !is_eof()) return ERROR(ReadError); return Value(TRY(Bool::create(false))); } - return ErrorCode::ReadError; + return ERROR(ReadError); } Result Reader::read_string() { - if (!match('"')) return ErrorCode::ReadError; + if (!match('"')) return ERROR(ReadError); size_t start = position_.offset + 1; forward(); @@ -171,7 +171,7 @@ Result Reader::read_string() { forward(); } - if (!match('"')) return ErrorCode::UnterminatedStringLiteral; + if (!match('"')) return ERROR(UnterminatedStringLiteral); forward(); @@ -217,13 +217,13 @@ Result Reader::read_string() { result = TRY(result.concat(&next, 1)); } - if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError; + if (!is_separator(get()) && !is_eof()) return ERROR(ReadError); return Value(std::move(result)); } Result Reader::read_number() { - if (!is_numeric_start()) return ErrorCode::ReadError; + if (!is_numeric_start()) return ERROR(ReadError); size_t start = position_.offset; bool is_float = false; @@ -238,13 +238,13 @@ Result Reader::read_number() { while (is_digit(get())) forward(); if (match('e') || match('E')) { - if (!forward_exponent()) return ErrorCode::InvalidNumericLiteral; + if (!forward_exponent()) return ERROR(InvalidNumericLiteral); } } else if (match('e') || match('E')) { is_float = true; - if (!forward_exponent()) return ErrorCode::InvalidNumericLiteral; + if (!forward_exponent()) return ERROR(InvalidNumericLiteral); } else if (match('x') || match('X')) { - if (!forward_hex_number()) return ErrorCode::InvalidNumericLiteral; + if (!forward_hex_number()) return ERROR(InvalidNumericLiteral); } else if (is_digit(get())) { do { forward(); @@ -259,13 +259,13 @@ Result Reader::read_number() { } if (match('e') || match('E')) { is_float = true; - if (!forward_exponent()) return ErrorCode::InvalidNumericLiteral; + if (!forward_exponent()) return ERROR(InvalidNumericLiteral); } } Value res; - if (position_.offset - start >= 32) return ErrorCode::InvalidNumericLiteral; + if (position_.offset - start >= 32) return ERROR(InvalidNumericLiteral); char buf[32]; for (size_t i = 0; i < position_.offset - start; ++i) { @@ -282,13 +282,13 @@ Result Reader::read_number() { res = Value(TRY(Int64::create(strtoll(buf, 0, 10)))); } - if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError; + if (!is_separator(get()) && !is_eof()) return ERROR(ReadError); return res; } Result Reader::read_symbol() { - if (!is_symbol_char(get())) return ErrorCode::ReadError; + if (!is_symbol_char(get())) return ERROR(ReadError); size_t start = position_.offset; @@ -298,7 +298,7 @@ Result Reader::read_symbol() { String str = TRY(_str.sub(start, end)); - if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError; + if (!is_separator(get()) && !is_eof()) return ERROR(ReadError); return Value(TRY(Symbol::create(str))); } @@ -410,7 +410,7 @@ bool Reader::forward_exponent() { } Result read_one(Value& value) { - if (!value.is()) return ErrorCode::TypeMismatch; + if (!value.is()) return ERROR(TypeMismatch); auto r = Reader(*value.to()); return r.read_one(); } diff --git a/src/result.hpp b/src/result.hpp index f96364e..8da24f5 100644 --- a/src/result.hpp +++ b/src/result.hpp @@ -55,12 +55,16 @@ class Result { std::move(___res); \ }).release_value()) -#define DIEX(m) \ - (({ \ - auto ___res = (m); \ - if (!___res.has_value()) { \ - fprintf(stderr, "%s:%d assertion failed\n", __FILE__, __LINE__); \ - exit(EXIT_FAILURE); \ - } \ - std::move(___res); \ +#define DIEX(m) \ + (({ \ + auto ___res = (m); \ + if (!___res.has_value()) { \ + const char* err = geterr(); \ + if (err == 0) \ + fprintf(stderr, "%s:%d assertion failed\n", __FILE__, __LINE__); \ + else \ + fprintf(stderr, "%s\n", err); \ + exit(EXIT_FAILURE); \ + } \ + std::move(___res); \ }).release_value()) diff --git a/src/writer.cpp b/src/writer.cpp index f6e9973..027c00b 100644 --- a/src/writer.cpp +++ b/src/writer.cpp @@ -70,7 +70,7 @@ Result Writer::write_bool(Bool& val) { } Result Writer::write_bytearray(ByteArray& val) { - return ErrorCode::NotImplemented; + return ERROR(NotImplemented); } Result Writer::write_string(String& val) { @@ -131,7 +131,7 @@ Result Writer::write_symbol(Symbol& val) { for (uint64_t i = 0; i < val.size(); i++) { char32_t c = TRY(val[i]); - if (!is_valid_symbol_char(c)) return ErrorCode::InvalidSymbol; + if (!is_valid_symbol_char(c)) return ERROR(InvalidSymbol); res = TRY(res.concat(&c, 1)); } @@ -140,7 +140,7 @@ Result Writer::write_symbol(Symbol& val) { } Result Writer::write_syntax(Syntax& val) { - return ErrorCode::NotImplemented; + return ERROR(NotImplemented); } Result Writer::write_pair(Pair& val) { @@ -150,7 +150,7 @@ Result Writer::write_pair(Pair& val) { bool is_first = true; while (!cur.is()) { - if (!cur.is()) return ErrorCode::MalformedList; + if (!cur.is()) return ERROR(MalformedList); Pair& pair = *cur.to();