Add error location reporting
This commit is contained in:
parent
4c7b44ff01
commit
935c629460
13 changed files with 127 additions and 64 deletions
|
@ -14,6 +14,7 @@ target_sources(vm_lib
|
||||||
src/vm.cpp
|
src/vm.cpp
|
||||||
src/common.cpp
|
src/common.cpp
|
||||||
src/arena.cpp
|
src/arena.cpp
|
||||||
|
src/error.cpp
|
||||||
src/reader.cpp
|
src/reader.cpp
|
||||||
src/writer.cpp
|
src/writer.cpp
|
||||||
src/utf8.cpp
|
src/utf8.cpp
|
||||||
|
|
|
@ -81,7 +81,7 @@ Result<PodObject*> Arena::gc_pod(PodObject* obj) {
|
||||||
return gc_dict((PodDict*)obj);
|
return gc_dict((PodDict*)obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorCode::TypeMismatch;
|
return ERROR(TypeMismatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<PodObject*> Arena::gc_nil(PodNil* obj) {
|
Result<PodObject*> Arena::gc_nil(PodNil* obj) {
|
||||||
|
@ -128,7 +128,7 @@ Result<PodObject*> Arena::gc_symbol(PodSymbol* obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<PodObject*> Arena::gc_syntax(PodSyntax* obj) {
|
Result<PodObject*> Arena::gc_syntax(PodSyntax* obj) {
|
||||||
return ErrorCode::NotImplemented;
|
return ERROR(NotImplemented);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<PodObject*> Arena::gc_pair(PodPair* obj) {
|
Result<PodObject*> Arena::gc_pair(PodPair* obj) {
|
||||||
|
@ -176,7 +176,6 @@ Result<PodObject*> Arena::gc_dict(PodDict* obj) {
|
||||||
nobj->data[i] = TRY(gc_pod(val));
|
nobj->data[i] = TRY(gc_pod(val));
|
||||||
}
|
}
|
||||||
return nobj;
|
return nobj;
|
||||||
// return ErrorCode::NotImplemented;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Arena& get_arena() {
|
Arena& get_arena() {
|
||||||
|
|
|
@ -102,8 +102,7 @@ class ArenaHeap {
|
||||||
// padding for guard value
|
// padding for guard value
|
||||||
uint64_t boundary_size = 8;
|
uint64_t boundary_size = 8;
|
||||||
|
|
||||||
if (boundary + size + boundary_size >= bufsize)
|
if (boundary + size + boundary_size >= bufsize) return ERROR(OutOfMemory);
|
||||||
return ErrorCode::OutOfMemory;
|
|
||||||
void* res = buf + boundary;
|
void* res = buf + boundary;
|
||||||
boundary += size;
|
boundary += size;
|
||||||
ASAN_UNPOISON_MEMORY_REGION(res, size);
|
ASAN_UNPOISON_MEMORY_REGION(res, size);
|
||||||
|
|
|
@ -120,13 +120,13 @@ Result<Value> Pair::rest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> reverse(Value& val) {
|
Result<Value> reverse(Value& val) {
|
||||||
if (!val.is<Pair>()) return ErrorCode::TypeMismatch;
|
if (!val.is<Pair>()) return ERROR(TypeMismatch);
|
||||||
|
|
||||||
auto res = Value(TRY(Nil::create()));
|
auto res = Value(TRY(Nil::create()));
|
||||||
auto cur = TRY(val.copy());
|
auto cur = TRY(val.copy());
|
||||||
|
|
||||||
while (!cur.is<Nil>()) {
|
while (!cur.is<Nil>()) {
|
||||||
if (!cur.is<Pair>()) return ErrorCode::TypeMismatch;
|
if (!cur.is<Pair>()) return ERROR(TypeMismatch);
|
||||||
Pair& pair = *cur.to<Pair>();
|
Pair& pair = *cur.to<Pair>();
|
||||||
Value first = TRY(pair.first());
|
Value first = TRY(pair.first());
|
||||||
cur = TRY(pair.rest());
|
cur = TRY(pair.rest());
|
||||||
|
@ -153,13 +153,13 @@ Result<void> debug_print(Value& val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> Array::get(uint64_t idx) {
|
Result<Value> 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();
|
auto val = _value->data[idx].get();
|
||||||
return Value::create(val);
|
return Value::create(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> Array::get(Value& key) {
|
Result<Value> Array::get(Value& key) {
|
||||||
if (!key.is<Int64>()) return ErrorCode::TypeMismatch;
|
if (!key.is<Int64>()) return ERROR(TypeMismatch);
|
||||||
return get(key.to<Int64>()->value());
|
return get(key.to<Int64>()->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,11 +185,11 @@ short cmp_tag(Tag lhs, Tag rhs) {
|
||||||
|
|
||||||
Result<Value> Dict::get(Value& key) {
|
Result<Value> Dict::get(Value& key) {
|
||||||
auto pos = TRY(find(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()));
|
auto k = TRY(Value::create(_value->data[pos * 2].get()));
|
||||||
|
|
||||||
if (TRY(k.cmp(key)) != 0) {
|
if (TRY(k.cmp(key)) != 0) {
|
||||||
return ErrorCode::KeyError;
|
return ERROR(KeyError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRY(Value::create(_value->data[pos * 2 + 1].get()));
|
return TRY(Value::create(_value->data[pos * 2 + 1].get()));
|
||||||
|
@ -280,4 +280,4 @@ Result<short> Dict::cmp(Dict& rhs) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> Object::get(Value& key) { return ErrorCode::TypeMismatch; }
|
Result<Value> Object::get(Value& key) { return ERROR(TypeMismatch); }
|
||||||
|
|
|
@ -143,7 +143,7 @@ class Array : public Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Array> sub(uint64_t start, uint64_t end) {
|
Result<Array> 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;
|
uint64_t res_size = end - start;
|
||||||
auto pod = TRY(arena_alloc<PodArray>(res_size * sizeof(PodObject*)));
|
auto pod = TRY(arena_alloc<PodArray>(res_size * sizeof(PodObject*)));
|
||||||
pod->size = res_size;
|
pod->size = res_size;
|
||||||
|
@ -208,7 +208,7 @@ class ByteArray : public Object {
|
||||||
virtual Result<Value> copy() const final;
|
virtual Result<Value> copy() const final;
|
||||||
|
|
||||||
Result<char> operator[](uint64_t idx) {
|
Result<char> operator[](uint64_t idx) {
|
||||||
if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
|
if (idx >= _value->size) return ERROR(IndexOutOfRange);
|
||||||
return _value->data[idx];
|
return _value->data[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +251,7 @@ class ByteArray : public Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<ByteArray> sub(uint64_t start, uint64_t end) {
|
Result<ByteArray> 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;
|
uint64_t res_size = end - start;
|
||||||
auto pod = TRY(arena_alloc<PodByteArray>(res_size * sizeof(char)));
|
auto pod = TRY(arena_alloc<PodByteArray>(res_size * sizeof(char)));
|
||||||
pod->size = res_size;
|
pod->size = res_size;
|
||||||
|
@ -393,7 +393,7 @@ class String : public Object {
|
||||||
virtual Result<Value> copy() const final;
|
virtual Result<Value> copy() const final;
|
||||||
|
|
||||||
Result<char32_t> operator[](uint64_t idx) {
|
Result<char32_t> operator[](uint64_t idx) {
|
||||||
if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
|
if (idx >= _value->size) return ERROR(IndexOutOfRange);
|
||||||
return _value->data[idx];
|
return _value->data[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,7 +439,7 @@ class String : public Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<String> sub(uint64_t start, uint64_t end) {
|
Result<String> 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;
|
uint64_t res_size = end - start;
|
||||||
auto pod = TRY(arena_alloc<PodString>(res_size * sizeof(char32_t)));
|
auto pod = TRY(arena_alloc<PodString>(res_size * sizeof(char32_t)));
|
||||||
pod->header.tag = Tag::String;
|
pod->header.tag = Tag::String;
|
||||||
|
@ -483,6 +483,26 @@ class Symbol : public Object {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
virtual Result<short> 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)); }
|
virtual void move(Object* obj) final { new (obj) Symbol(std::move(_value)); }
|
||||||
|
|
||||||
static Result<Symbol> create(PodSymbol* obj) {
|
static Result<Symbol> create(PodSymbol* obj) {
|
||||||
|
@ -515,7 +535,7 @@ class Symbol : public Object {
|
||||||
uint64_t size() { return _value->size; }
|
uint64_t size() { return _value->size; }
|
||||||
|
|
||||||
Result<char32_t> operator[](uint64_t idx) {
|
Result<char32_t> operator[](uint64_t idx) {
|
||||||
if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
|
if (idx >= _value->size) return ERROR(IndexOutOfRange);
|
||||||
return _value->data[idx];
|
return _value->data[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,9 @@ struct Context {
|
||||||
uint64_t maxconst;
|
uint64_t maxconst;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool is_primitive_op(Symbol& sym) {
|
Result<bool> is_primitive_op(Symbol& sym) {
|
||||||
// return (sym.cmp("+") == 0);
|
return TRY(sym.cmp("+")) == 0 || TRY(sym.cmp("-")) == 0 ||
|
||||||
|
TRY(sym.cmp("*")) == 0 || TRY(sym.cmp("/")) == 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ Result<Value> Compiler::compile(Value& expr) {
|
||||||
auto context = TRY(Context::create());
|
auto context = TRY(Context::create());
|
||||||
|
|
||||||
TRY(compile_expr(context, expr));
|
TRY(compile_expr(context, expr));
|
||||||
return ErrorCode::NotImplemented;
|
return ERROR(NotImplemented);
|
||||||
}
|
}
|
||||||
Result<Expression> Compiler::compile_expr(Context& context, Value& expr) {
|
Result<Expression> Compiler::compile_expr(Context& context, Value& expr) {
|
||||||
switch (expr.tag()) {
|
switch (expr.tag()) {
|
||||||
|
@ -46,16 +47,36 @@ Result<Expression> Compiler::compile_expr(Context& context, Value& expr) {
|
||||||
case Tag::Array:
|
case Tag::Array:
|
||||||
case Tag::ByteArray:
|
case Tag::ByteArray:
|
||||||
case Tag::Dict:
|
case Tag::Dict:
|
||||||
return ErrorCode::TypeMismatch;
|
return ERROR(TypeMismatch);
|
||||||
}
|
}
|
||||||
return ErrorCode::TypeMismatch;
|
return ERROR(TypeMismatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<Expression> 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<Nil>()) {
|
||||||
|
Pair& pair = *cur.to<Pair>();
|
||||||
|
auto subexpr = TRY(pair.first());
|
||||||
|
|
||||||
|
auto comp = TRY(compile_expr(context, subexpr));
|
||||||
|
|
||||||
|
cur = TRY(pair.rest());
|
||||||
|
}
|
||||||
|
return ERROR(TypeMismatch);
|
||||||
|
}
|
||||||
Result<Expression> Compiler::compile_list(Context& context, Pair& expr) {
|
Result<Expression> Compiler::compile_list(Context& context, Pair& expr) {
|
||||||
auto first = TRY(expr.first());
|
auto first = TRY(expr.first());
|
||||||
|
|
||||||
if (first.is<Symbol>()) {
|
if (first.is<Symbol>()) {
|
||||||
Symbol& sym = *first.to<Symbol>();
|
Symbol& sym = *first.to<Symbol>();
|
||||||
|
if (TRY(is_primitive_op(sym))) {
|
||||||
|
return compile_primop(context, sym, expr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ErrorCode::TypeMismatch;
|
return ERROR(TypeMismatch);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,4 +18,5 @@ class Compiler {
|
||||||
Result<Value> compile(Value& expr);
|
Result<Value> compile(Value& expr);
|
||||||
Result<Expression> compile_expr(Context& context, Value& expr);
|
Result<Expression> compile_expr(Context& context, Value& expr);
|
||||||
Result<Expression> compile_list(Context& context, Pair& expr);
|
Result<Expression> compile_list(Context& context, Pair& expr);
|
||||||
|
Result<Expression> compile_primop(Context& context, Symbol& op, Pair& expr);
|
||||||
};
|
};
|
||||||
|
|
6
src/error.cpp
Normal file
6
src/error.cpp
Normal file
|
@ -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; }
|
|
@ -13,3 +13,15 @@ enum class ErrorCode {
|
||||||
MalformedList,
|
MalformedList,
|
||||||
KeyError,
|
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; \
|
||||||
|
}))
|
||||||
|
|
|
@ -153,12 +153,12 @@ class Ptr {
|
||||||
T* operator->() { return _ptr; }
|
T* operator->() { return _ptr; }
|
||||||
|
|
||||||
Result<int64_t> get_int() {
|
Result<int64_t> get_int() {
|
||||||
if (_ptr->tag != Tag::Int64) return ErrorCode::TypeMismatch;
|
if (_ptr->tag != Tag::Int64) return ERROR(TypeMismatch);
|
||||||
return ((PodInt64*)_ptr)->value;
|
return ((PodInt64*)_ptr)->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<double> get_float() {
|
Result<double> get_float() {
|
||||||
if (_ptr->tag != Tag::Float) return ErrorCode::TypeMismatch;
|
if (_ptr->tag != Tag::Float) return ERROR(TypeMismatch);
|
||||||
return ((PodFloat*)_ptr)->value;
|
return ((PodFloat*)_ptr)->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,10 +58,10 @@ Result<Value> Reader::read_one() {
|
||||||
} else if (match('[')) {
|
} else if (match('[')) {
|
||||||
// TODO: implement array
|
// TODO: implement array
|
||||||
// return read_array();
|
// return read_array();
|
||||||
return ErrorCode::ReadError;
|
return ERROR(ReadError);
|
||||||
} else if (match('{')) {
|
} else if (match('{')) {
|
||||||
return read_dict();
|
return read_dict();
|
||||||
return ErrorCode::ReadError;
|
return ERROR(ReadError);
|
||||||
}
|
}
|
||||||
|
|
||||||
position_ = saved_position;
|
position_ = saved_position;
|
||||||
|
@ -69,7 +69,7 @@ Result<Value> Reader::read_one() {
|
||||||
return read_symbol();
|
return read_symbol();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorCode::ReadError;
|
return ERROR(ReadError);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> Reader::read_multiple() {
|
Result<Value> Reader::read_multiple() {
|
||||||
|
@ -85,11 +85,11 @@ Result<Value> Reader::read_multiple() {
|
||||||
res = Value(TRY(Pair::create(val, res)));
|
res = Value(TRY(Pair::create(val, res)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorCode::ReadError;
|
return ERROR(ReadError);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> Reader::read_list() {
|
Result<Value> Reader::read_list() {
|
||||||
if (!match('(')) return ErrorCode::ReadError;
|
if (!match('(')) return ERROR(ReadError);
|
||||||
|
|
||||||
forward();
|
forward();
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ Result<Value> Reader::read_list() {
|
||||||
forward_whitespace();
|
forward_whitespace();
|
||||||
|
|
||||||
if (is_eof()) {
|
if (is_eof()) {
|
||||||
return ErrorCode::ReadError;
|
return ERROR(ReadError);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match(')')) {
|
if (match(')')) {
|
||||||
|
@ -112,11 +112,11 @@ Result<Value> Reader::read_list() {
|
||||||
res = Value(TRY(Pair::create(val, res)));
|
res = Value(TRY(Pair::create(val, res)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorCode::ReadError;
|
return ERROR(ReadError);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> Reader::read_dict() {
|
Result<Value> Reader::read_dict() {
|
||||||
if (!match('{')) return ErrorCode::ReadError;
|
if (!match('{')) return ERROR(ReadError);
|
||||||
|
|
||||||
forward();
|
forward();
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ Result<Value> Reader::read_dict() {
|
||||||
forward_whitespace();
|
forward_whitespace();
|
||||||
|
|
||||||
if (is_eof()) {
|
if (is_eof()) {
|
||||||
return ErrorCode::ReadError;
|
return ERROR(ReadError);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match('}')) {
|
if (match('}')) {
|
||||||
|
@ -140,25 +140,25 @@ Result<Value> Reader::read_dict() {
|
||||||
res = TRY(res.insert(val1, val2));
|
res = TRY(res.insert(val1, val2));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorCode::ReadError;
|
return ERROR(ReadError);
|
||||||
}
|
}
|
||||||
Result<Value> Reader::read_bool() {
|
Result<Value> Reader::read_bool() {
|
||||||
if (match("true")) {
|
if (match("true")) {
|
||||||
forward(4);
|
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)));
|
return Value(TRY(Bool::create(true)));
|
||||||
}
|
}
|
||||||
if (match("false")) {
|
if (match("false")) {
|
||||||
forward(5);
|
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 Value(TRY(Bool::create(false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrorCode::ReadError;
|
return ERROR(ReadError);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> Reader::read_string() {
|
Result<Value> Reader::read_string() {
|
||||||
if (!match('"')) return ErrorCode::ReadError;
|
if (!match('"')) return ERROR(ReadError);
|
||||||
size_t start = position_.offset + 1;
|
size_t start = position_.offset + 1;
|
||||||
|
|
||||||
forward();
|
forward();
|
||||||
|
@ -171,7 +171,7 @@ Result<Value> Reader::read_string() {
|
||||||
forward();
|
forward();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!match('"')) return ErrorCode::UnterminatedStringLiteral;
|
if (!match('"')) return ERROR(UnterminatedStringLiteral);
|
||||||
|
|
||||||
forward();
|
forward();
|
||||||
|
|
||||||
|
@ -217,13 +217,13 @@ Result<Value> Reader::read_string() {
|
||||||
result = TRY(result.concat(&next, 1));
|
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));
|
return Value(std::move(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> Reader::read_number() {
|
Result<Value> Reader::read_number() {
|
||||||
if (!is_numeric_start()) return ErrorCode::ReadError;
|
if (!is_numeric_start()) return ERROR(ReadError);
|
||||||
size_t start = position_.offset;
|
size_t start = position_.offset;
|
||||||
|
|
||||||
bool is_float = false;
|
bool is_float = false;
|
||||||
|
@ -238,13 +238,13 @@ Result<Value> Reader::read_number() {
|
||||||
while (is_digit(get())) forward();
|
while (is_digit(get())) forward();
|
||||||
|
|
||||||
if (match('e') || match('E')) {
|
if (match('e') || match('E')) {
|
||||||
if (!forward_exponent()) return ErrorCode::InvalidNumericLiteral;
|
if (!forward_exponent()) return ERROR(InvalidNumericLiteral);
|
||||||
}
|
}
|
||||||
} else if (match('e') || match('E')) {
|
} else if (match('e') || match('E')) {
|
||||||
is_float = true;
|
is_float = true;
|
||||||
if (!forward_exponent()) return ErrorCode::InvalidNumericLiteral;
|
if (!forward_exponent()) return ERROR(InvalidNumericLiteral);
|
||||||
} else if (match('x') || match('X')) {
|
} 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())) {
|
} else if (is_digit(get())) {
|
||||||
do {
|
do {
|
||||||
forward();
|
forward();
|
||||||
|
@ -259,13 +259,13 @@ Result<Value> Reader::read_number() {
|
||||||
}
|
}
|
||||||
if (match('e') || match('E')) {
|
if (match('e') || match('E')) {
|
||||||
is_float = true;
|
is_float = true;
|
||||||
if (!forward_exponent()) return ErrorCode::InvalidNumericLiteral;
|
if (!forward_exponent()) return ERROR(InvalidNumericLiteral);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Value res;
|
Value res;
|
||||||
|
|
||||||
if (position_.offset - start >= 32) return ErrorCode::InvalidNumericLiteral;
|
if (position_.offset - start >= 32) return ERROR(InvalidNumericLiteral);
|
||||||
|
|
||||||
char buf[32];
|
char buf[32];
|
||||||
for (size_t i = 0; i < position_.offset - start; ++i) {
|
for (size_t i = 0; i < position_.offset - start; ++i) {
|
||||||
|
@ -282,13 +282,13 @@ Result<Value> Reader::read_number() {
|
||||||
res = Value(TRY(Int64::create(strtoll(buf, 0, 10))));
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> Reader::read_symbol() {
|
Result<Value> Reader::read_symbol() {
|
||||||
if (!is_symbol_char(get())) return ErrorCode::ReadError;
|
if (!is_symbol_char(get())) return ERROR(ReadError);
|
||||||
|
|
||||||
size_t start = position_.offset;
|
size_t start = position_.offset;
|
||||||
|
|
||||||
|
@ -298,7 +298,7 @@ Result<Value> Reader::read_symbol() {
|
||||||
|
|
||||||
String str = TRY(_str.sub(start, end));
|
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)));
|
return Value(TRY(Symbol::create(str)));
|
||||||
}
|
}
|
||||||
|
@ -410,7 +410,7 @@ bool Reader::forward_exponent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Value> read_one(Value& value) {
|
Result<Value> read_one(Value& value) {
|
||||||
if (!value.is<String>()) return ErrorCode::TypeMismatch;
|
if (!value.is<String>()) return ERROR(TypeMismatch);
|
||||||
auto r = Reader(*value.to<String>());
|
auto r = Reader(*value.to<String>());
|
||||||
return r.read_one();
|
return r.read_one();
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,12 +55,16 @@ class Result<void> {
|
||||||
std::move(___res); \
|
std::move(___res); \
|
||||||
}).release_value())
|
}).release_value())
|
||||||
|
|
||||||
#define DIEX(m) \
|
#define DIEX(m) \
|
||||||
(({ \
|
(({ \
|
||||||
auto ___res = (m); \
|
auto ___res = (m); \
|
||||||
if (!___res.has_value()) { \
|
if (!___res.has_value()) { \
|
||||||
fprintf(stderr, "%s:%d assertion failed\n", __FILE__, __LINE__); \
|
const char* err = geterr(); \
|
||||||
exit(EXIT_FAILURE); \
|
if (err == 0) \
|
||||||
} \
|
fprintf(stderr, "%s:%d assertion failed\n", __FILE__, __LINE__); \
|
||||||
std::move(___res); \
|
else \
|
||||||
|
fprintf(stderr, "%s\n", err); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
|
std::move(___res); \
|
||||||
}).release_value())
|
}).release_value())
|
||||||
|
|
|
@ -70,7 +70,7 @@ Result<String> Writer::write_bool(Bool& val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<String> Writer::write_bytearray(ByteArray& val) {
|
Result<String> Writer::write_bytearray(ByteArray& val) {
|
||||||
return ErrorCode::NotImplemented;
|
return ERROR(NotImplemented);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<String> Writer::write_string(String& val) {
|
Result<String> Writer::write_string(String& val) {
|
||||||
|
@ -131,7 +131,7 @@ Result<String> Writer::write_symbol(Symbol& val) {
|
||||||
for (uint64_t i = 0; i < val.size(); i++) {
|
for (uint64_t i = 0; i < val.size(); i++) {
|
||||||
char32_t c = TRY(val[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));
|
res = TRY(res.concat(&c, 1));
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ Result<String> Writer::write_symbol(Symbol& val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<String> Writer::write_syntax(Syntax& val) {
|
Result<String> Writer::write_syntax(Syntax& val) {
|
||||||
return ErrorCode::NotImplemented;
|
return ERROR(NotImplemented);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<String> Writer::write_pair(Pair& val) {
|
Result<String> Writer::write_pair(Pair& val) {
|
||||||
|
@ -150,7 +150,7 @@ Result<String> Writer::write_pair(Pair& val) {
|
||||||
|
|
||||||
bool is_first = true;
|
bool is_first = true;
|
||||||
while (!cur.is<Nil>()) {
|
while (!cur.is<Nil>()) {
|
||||||
if (!cur.is<Pair>()) return ErrorCode::MalformedList;
|
if (!cur.is<Pair>()) return ERROR(MalformedList);
|
||||||
|
|
||||||
Pair& pair = *cur.to<Pair>();
|
Pair& pair = *cur.to<Pair>();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue