Beginnings of a reader
This commit is contained in:
parent
ded19f7962
commit
46381cccef
10 changed files with 343 additions and 79 deletions
|
@ -14,6 +14,7 @@ target_sources(vm_lib
|
|||
src/vm.cpp
|
||||
src/common.cpp
|
||||
src/arena.cpp
|
||||
src/reader.cpp
|
||||
|
||||
PUBLIC
|
||||
FILE_SET HEADERS
|
||||
|
@ -25,6 +26,8 @@ target_sources(vm_lib
|
|||
src/pod.hpp
|
||||
src/result.hpp
|
||||
src/vm.hpp
|
||||
src/sourcerange.hpp
|
||||
src/reader.hpp
|
||||
)
|
||||
|
||||
add_executable(vli src/vli.cpp)
|
||||
|
|
|
@ -17,6 +17,8 @@ class GcRootBase {
|
|||
|
||||
~GcRootBase();
|
||||
|
||||
PodObject* get() { return _ptr; }
|
||||
|
||||
protected:
|
||||
PodObject* _ptr;
|
||||
GcRootList* _node;
|
||||
|
@ -35,6 +37,7 @@ class GcRoot : public GcRootBase {
|
|||
return GcRoot<T>::create((T*)_ptr, arena);
|
||||
}
|
||||
|
||||
T* get() { return (T*)_ptr; }
|
||||
T& operator*() { return *(T*)_ptr; }
|
||||
T* operator->() { return (T*)_ptr; }
|
||||
};
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "common.hpp"
|
||||
|
||||
#include "arena.hpp"
|
||||
#include "error.hpp"
|
||||
#include "pod.hpp"
|
||||
|
||||
Syntax::Syntax(String filename, String modulename, Value expression) {}
|
||||
|
||||
|
@ -11,11 +13,11 @@ Result<Value> Syntax::get_value(Arena& arena) {
|
|||
Result<Value> Value::create(Arena& arena, PodObject* obj) {
|
||||
switch (obj->header.tag) {
|
||||
case Tag::Nil:
|
||||
return Value();
|
||||
return Value(TRY(Nil::create(arena, (PodNil*)obj)));
|
||||
case Tag::Int64:
|
||||
return Value(Int64(((PodInt64*)obj)->value));
|
||||
return Value(TRY(Int64::create(arena, (PodInt64*)obj)));
|
||||
case Tag::Float:
|
||||
return Value(Int64(((PodFloat*)obj)->value));
|
||||
return Value(TRY(Float::create(arena, (PodFloat*)obj)));
|
||||
case Tag::String:
|
||||
return Value(TRY(String::create(arena, (PodString*)obj)));
|
||||
case Tag::Symbol:
|
||||
|
@ -37,8 +39,12 @@ Result<Value> syntax_unwrap(Arena& arena, Value& val) {
|
|||
|
||||
Result<Value> Nil::copy(Arena& arena) { return Value(Nil()); }
|
||||
|
||||
Result<Value> Int64::copy(Arena& arena) { return Value(Int64(_value)); }
|
||||
Result<Value> Float::copy(Arena& arena) { return Value(Float(_value)); }
|
||||
Result<Value> Int64::copy(Arena& arena) {
|
||||
return Value(Int64(TRY(_value.copy(arena))));
|
||||
}
|
||||
Result<Value> Float::copy(Arena& arena) {
|
||||
return Value(Float(TRY(_value.copy(arena))));
|
||||
}
|
||||
|
||||
Result<Value> String::copy(Arena& arena) {
|
||||
return Value(String(TRY(_value.copy(arena))));
|
||||
|
@ -55,3 +61,37 @@ Result<Value> Syntax::copy(Arena& arena) {
|
|||
Result<Value> Pair::copy(Arena& arena) {
|
||||
return Value(Pair(TRY(_value.copy(arena))));
|
||||
}
|
||||
|
||||
Result<Pair> Pair::create(Arena& arena, Value& first, Value& rest) {
|
||||
auto pod = TRY(arena.alloc<PodPair>());
|
||||
pod->first = OffPtr<PodObject>(pod, first.pod());
|
||||
pod->rest = OffPtr<PodObject>(pod, rest.pod());
|
||||
|
||||
return Pair(TRY(MkGcRoot(pod, arena)));
|
||||
}
|
||||
|
||||
Result<Value> Pair::first(Arena& arena) {
|
||||
auto val = _value->first.get(pod());
|
||||
return Value::create(arena, val);
|
||||
}
|
||||
Result<Value> Pair::rest(Arena& arena) {
|
||||
auto val = _value->rest.get(pod());
|
||||
return Value::create(arena, val);
|
||||
}
|
||||
|
||||
Result<Value> reverse(Arena& arena, Value& val) {
|
||||
if (!val.is<Pair>()) return ErrorCode::TypeMismatch;
|
||||
|
||||
auto res = Value(TRY(Nil::create(arena)));
|
||||
auto cur = TRY(val.copy(arena));
|
||||
|
||||
while (!cur.is<Nil>()) {
|
||||
if (!cur.is<Pair>()) return ErrorCode::TypeMismatch;
|
||||
Pair& pair = *cur.to<Pair>();
|
||||
Value first = TRY(pair.first(arena));
|
||||
cur = TRY(pair.rest(arena));
|
||||
res = TRY(Pair::create(arena, first, res));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
136
src/common.hpp
136
src/common.hpp
|
@ -12,75 +12,35 @@
|
|||
|
||||
class Value;
|
||||
|
||||
struct SourcePosition {
|
||||
size_t line{1};
|
||||
size_t column{1};
|
||||
size_t offset{0};
|
||||
};
|
||||
|
||||
struct SourceRange {
|
||||
SourcePosition start;
|
||||
SourcePosition end;
|
||||
};
|
||||
|
||||
class PodInt64 final : public PodObject {
|
||||
public:
|
||||
PodInt64() : PodObject(Tag::Int64){};
|
||||
|
||||
int64_t value;
|
||||
};
|
||||
|
||||
class PodFloat final : public PodObject {
|
||||
public:
|
||||
PodFloat() : PodObject(Tag::Float){};
|
||||
|
||||
double value;
|
||||
};
|
||||
|
||||
class PodString final : public PodObject {
|
||||
public:
|
||||
PodString() : PodObject(Tag::String){};
|
||||
|
||||
uint64_t size;
|
||||
char32_t data[];
|
||||
};
|
||||
|
||||
class PodSymbol final : public PodObject {
|
||||
public:
|
||||
PodSymbol() : PodObject(Tag::Symbol){};
|
||||
|
||||
uint64_t size;
|
||||
char32_t data[];
|
||||
};
|
||||
|
||||
class PodSyntax : public PodObject {
|
||||
public:
|
||||
PodSyntax() : PodObject(Tag::Syntax){};
|
||||
OffPtr<PodString> filename;
|
||||
OffPtr<PodString> modulename;
|
||||
OffPtr<PodObject> expression;
|
||||
SourceRange sourcerange;
|
||||
};
|
||||
|
||||
class PodPair : public PodObject {
|
||||
public:
|
||||
PodPair() : PodObject(Tag::Pair){};
|
||||
OffPtr<PodObject> first;
|
||||
OffPtr<PodObject> second;
|
||||
};
|
||||
|
||||
class Object {
|
||||
public:
|
||||
virtual Tag tag() = 0;
|
||||
virtual Result<Value> copy(Arena& arena) = 0;
|
||||
virtual PodObject* pod() = 0;
|
||||
};
|
||||
|
||||
class Nil : public Object {
|
||||
public:
|
||||
Nil() {}
|
||||
Nil(GcRoot<PodNil>&& val) : _value(std::move(val)) {}
|
||||
|
||||
virtual Tag tag() final { return Tag::Nil; }
|
||||
virtual PodObject* pod() final { return _value.get(); }
|
||||
|
||||
static Result<Nil> create(Arena& arena, PodNil* obj) {
|
||||
return Nil(TRY(MkGcRoot(obj, arena)));
|
||||
}
|
||||
|
||||
static Result<Nil> create(Arena& arena) {
|
||||
auto pod = TRY(arena.alloc<PodNil>());
|
||||
|
||||
return Nil(TRY(MkGcRoot(pod, arena)));
|
||||
}
|
||||
|
||||
virtual Result<Value> copy(Arena& arena) final;
|
||||
|
||||
private:
|
||||
GcRoot<PodNil> _value;
|
||||
};
|
||||
|
||||
class String : public Object {
|
||||
|
@ -88,6 +48,7 @@ class String : public Object {
|
|||
String() {}
|
||||
String(GcRoot<PodString>&& val) : _value(std::move(val)) {}
|
||||
virtual Tag tag() final { return Tag::String; }
|
||||
virtual PodObject* pod() final { return _value.get(); }
|
||||
|
||||
static Result<String> create(Arena& arena, PodString* obj) {
|
||||
return String(TRY(MkGcRoot(obj, arena)));
|
||||
|
@ -129,6 +90,7 @@ class Symbol : public Object {
|
|||
Symbol() {}
|
||||
Symbol(GcRoot<PodSymbol>&& val) : _value(std::move(val)) {}
|
||||
virtual Tag tag() final { return Tag::Symbol; }
|
||||
virtual PodObject* pod() final { return _value.get(); }
|
||||
|
||||
static Result<Symbol> create(Arena& arena, PodSymbol* obj) {
|
||||
return Symbol(TRY(MkGcRoot(obj, arena)));
|
||||
|
@ -154,6 +116,7 @@ class Syntax : public Object {
|
|||
Syntax(GcRoot<PodSyntax>&& val) : _value(std::move(val)) {}
|
||||
Syntax(String filename, String modulename, Value expression);
|
||||
virtual Tag tag() final { return Tag::Syntax; }
|
||||
virtual PodObject* pod() final { return _value.get(); }
|
||||
|
||||
static Result<Syntax> create(Arena& arena, PodSyntax* obj) {
|
||||
return Syntax(TRY(MkGcRoot(obj, arena)));
|
||||
|
@ -172,12 +135,15 @@ class Pair : public Object {
|
|||
Pair() {}
|
||||
Pair(GcRoot<PodPair>&& val) : _value(std::move(val)) {}
|
||||
virtual Tag tag() final { return Tag::Pair; }
|
||||
virtual PodObject* pod() final { return _value.get(); }
|
||||
|
||||
static Result<Pair> create(Arena& arena, PodPair* obj) {
|
||||
return Pair(TRY(MkGcRoot(obj, arena)));
|
||||
}
|
||||
static Result<Pair> create(Arena& arena, Value& first, Value& rest);
|
||||
|
||||
static Result<Value> first(Arena& arena);
|
||||
Result<Value> first(Arena& arena);
|
||||
Result<Value> rest(Arena& arena);
|
||||
|
||||
virtual Result<Value> copy(Arena& arena) final;
|
||||
|
||||
|
@ -187,34 +153,54 @@ class Pair : public Object {
|
|||
|
||||
class Int64 : public Object {
|
||||
public:
|
||||
Int64() : _value(0) {}
|
||||
Int64(int64_t val) : _value(val) {}
|
||||
virtual ~Int64() = default;
|
||||
|
||||
Int64() {}
|
||||
Int64(GcRoot<PodInt64>&& val) : _value(std::move(val)) {}
|
||||
virtual Tag tag() final { return Tag::Int64; }
|
||||
virtual PodObject* pod() final { return _value.get(); }
|
||||
|
||||
int64_t value() { return _value; }
|
||||
static Result<Int64> create(Arena& arena, PodInt64* obj) {
|
||||
return Int64(TRY(MkGcRoot(obj, arena)));
|
||||
}
|
||||
|
||||
static Result<Int64> create(Arena& arena, double val) {
|
||||
auto pod = TRY(arena.alloc<PodInt64>());
|
||||
pod->value = val;
|
||||
|
||||
return Int64(TRY(MkGcRoot(pod, arena)));
|
||||
}
|
||||
|
||||
int64_t value() { return _value->value; }
|
||||
|
||||
virtual Result<Value> copy(Arena& arena) final;
|
||||
|
||||
private:
|
||||
int64_t _value;
|
||||
GcRoot<PodInt64> _value;
|
||||
};
|
||||
|
||||
class Float : public Object {
|
||||
public:
|
||||
Float() : _value(0) {}
|
||||
Float(double val) : _value(val) {}
|
||||
virtual ~Float() = default;
|
||||
|
||||
Float() {}
|
||||
Float(GcRoot<PodFloat>&& val) : _value(std::move(val)) {}
|
||||
virtual Tag tag() final { return Tag::Float; }
|
||||
virtual PodObject* pod() final { return _value.get(); }
|
||||
|
||||
double value() { return _value; }
|
||||
static Result<Float> create(Arena& arena, PodFloat* obj) {
|
||||
return Float(TRY(MkGcRoot(obj, arena)));
|
||||
}
|
||||
|
||||
static Result<Float> create(Arena& arena, double val) {
|
||||
auto pod = TRY(arena.alloc<PodFloat>());
|
||||
pod->value = val;
|
||||
|
||||
return Float(TRY(MkGcRoot(pod, arena)));
|
||||
}
|
||||
|
||||
double value() { return _value->value; }
|
||||
|
||||
virtual Result<Value> copy(Arena& arena) final;
|
||||
|
||||
private:
|
||||
double _value;
|
||||
GcRoot<PodFloat> _value;
|
||||
};
|
||||
|
||||
// note: this class doesn't perform proper destruction of objects in some cases
|
||||
|
@ -235,6 +221,12 @@ class Value {
|
|||
new (buf) T(std::move(obj));
|
||||
}
|
||||
|
||||
Value& operator=(Value&& val) {
|
||||
memcpy(buf, val.buf, 24);
|
||||
new (val.buf) Nil();
|
||||
return *this;
|
||||
}
|
||||
|
||||
static Result<Value> create(Arena& arena, PodObject* obj);
|
||||
|
||||
template <class T>
|
||||
|
@ -247,6 +239,8 @@ class Value {
|
|||
return dynamic_cast<T*>((Object*)buf);
|
||||
}
|
||||
|
||||
PodObject* pod() { return ((Object*)buf)->pod(); }
|
||||
|
||||
Object& operator*() { return *(Object*)(buf); }
|
||||
Object* operator->() { return (Object*)(buf); }
|
||||
|
||||
|
@ -257,3 +251,5 @@ class Value {
|
|||
};
|
||||
|
||||
Result<Value> syntax_unwrap(Value& val);
|
||||
|
||||
Result<Value> reverse(Arena& arena, Value& val);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
enum class ErrorCode {
|
||||
Success,
|
||||
OutOfMemory,
|
||||
IndexOutOfRange
|
||||
|
||||
IndexOutOfRange,
|
||||
TypeMismatch,
|
||||
ReadError
|
||||
};
|
||||
|
|
78
src/pod.hpp
78
src/pod.hpp
|
@ -2,6 +2,9 @@
|
|||
|
||||
#include <cstdint>
|
||||
|
||||
#include "result.hpp"
|
||||
#include "sourcerange.hpp"
|
||||
|
||||
enum class Tag : uint8_t {
|
||||
Nil,
|
||||
Int64,
|
||||
|
@ -43,3 +46,78 @@ static_assert(sizeof(PodHeader) == 8);
|
|||
struct PodObject {
|
||||
PodHeader header;
|
||||
};
|
||||
|
||||
class PodNil final : public PodObject {
|
||||
public:
|
||||
PodNil() : PodObject(Tag::Nil){};
|
||||
};
|
||||
|
||||
class PodInt64 final : public PodObject {
|
||||
public:
|
||||
PodInt64() : PodObject(Tag::Int64){};
|
||||
|
||||
int64_t value;
|
||||
};
|
||||
|
||||
class PodFloat final : public PodObject {
|
||||
public:
|
||||
PodFloat() : PodObject(Tag::Float){};
|
||||
|
||||
double value;
|
||||
};
|
||||
|
||||
class PodString final : public PodObject {
|
||||
public:
|
||||
PodString() : PodObject(Tag::String){};
|
||||
|
||||
uint64_t size;
|
||||
char32_t data[];
|
||||
};
|
||||
|
||||
class PodSymbol final : public PodObject {
|
||||
public:
|
||||
PodSymbol() : PodObject(Tag::Symbol){};
|
||||
|
||||
uint64_t size;
|
||||
char32_t data[];
|
||||
};
|
||||
|
||||
class PodSyntax : public PodObject {
|
||||
public:
|
||||
PodSyntax() : PodObject(Tag::Syntax){};
|
||||
OffPtr<PodString> filename;
|
||||
OffPtr<PodString> modulename;
|
||||
OffPtr<PodObject> expression;
|
||||
SourceRange sourcerange;
|
||||
};
|
||||
|
||||
class PodPair : public PodObject {
|
||||
public:
|
||||
PodPair() : PodObject(Tag::Pair){};
|
||||
OffPtr<PodObject> first;
|
||||
OffPtr<PodObject> rest;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Ptr {
|
||||
public:
|
||||
Ptr() : _ptr(0) {}
|
||||
Ptr(T* ptr) : _ptr(ptr){};
|
||||
|
||||
T* get() { return _ptr; }
|
||||
T& operator*() { return *_ptr; }
|
||||
T* operator->() { return _ptr; }
|
||||
|
||||
Result<int64_t> get_int() {
|
||||
if (_ptr->tag != Tag::Int64) return ErrorCode::TypeMismatch;
|
||||
return ((PodInt64*)_ptr)->value;
|
||||
}
|
||||
|
||||
Result<double> get_float() {
|
||||
if (_ptr->tag != Tag::Float) return ErrorCode::TypeMismatch;
|
||||
return ((PodFloat*)_ptr)->value;
|
||||
}
|
||||
|
||||
private:
|
||||
T* _ptr;
|
||||
};
|
||||
|
|
85
src/reader.cpp
Normal file
85
src/reader.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include "reader.hpp"
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
static bool is_digit(char32_t c) { return c >= '0' && c <= '9'; }
|
||||
static bool is_alpha(char32_t c) {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
static bool is_hex_digit(char32_t c) {
|
||||
return is_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
}
|
||||
|
||||
static bool is_symbol_char(char32_t c) {
|
||||
static char valid_char[] = {'!', '$', '%', '&', '*', '+', '-', '.', '/',
|
||||
':', '<', '=', '>', '?', '@', '^', '_', '~'};
|
||||
|
||||
if (is_digit(c)) return true;
|
||||
if (is_alpha(c)) return true;
|
||||
|
||||
for (size_t i = 0; i < sizeof(valid_char); ++i) {
|
||||
if (char32_t(valid_char[i]) == c) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_whitespace(char32_t c) {
|
||||
return c == ' ' || c == '\t' || c == '\v' || c == '\f';
|
||||
}
|
||||
|
||||
static bool is_brace(char32_t c) {
|
||||
return c == '[' || c == ']' || c == '(' || c == ')' || c == '{' || c == '}';
|
||||
}
|
||||
|
||||
static bool is_newline(char32_t c) { return c == '\r' || c == '\n'; }
|
||||
|
||||
static bool is_separator(char32_t c) {
|
||||
return is_whitespace(c) || is_brace(c) || is_newline(c) || c == ';';
|
||||
}
|
||||
|
||||
#define EOS 0
|
||||
|
||||
Result<Value> Reader::read_one() {
|
||||
forward_whitespace();
|
||||
|
||||
auto saved_position = position_;
|
||||
if (is_numeric_start()) {
|
||||
auto res = read_number();
|
||||
if (res.has_value()) return res;
|
||||
} else if (match("true") || match("false")) {
|
||||
auto res = read_bool();
|
||||
if (res.has_value()) return res;
|
||||
} else if (is_string_start()) {
|
||||
return read_string();
|
||||
} else if (match('(')) {
|
||||
return read_list();
|
||||
} else if (match('[')) {
|
||||
return read_array();
|
||||
} else if (match('{')) {
|
||||
return read_dict();
|
||||
}
|
||||
|
||||
position_ = saved_position;
|
||||
if (is_symbol_start()) {
|
||||
return read_symbol();
|
||||
}
|
||||
|
||||
return ErrorCode::ReadError;
|
||||
}
|
||||
|
||||
Result<Value> Reader::read_multiple() {
|
||||
Value res = TRY(Nil::create(_arena));
|
||||
|
||||
while (1) {
|
||||
forward_whitespace();
|
||||
if (is_eof()) {
|
||||
return reverse(_arena, res);
|
||||
}
|
||||
|
||||
auto val = TRY(read_one());
|
||||
res = Value(TRY(Pair::create(_arena, val, res)));
|
||||
}
|
||||
|
||||
return ErrorCode::ReadError;
|
||||
}
|
44
src/reader.hpp
Normal file
44
src/reader.hpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
#include "common.hpp"
|
||||
#include "result.hpp"
|
||||
#include "sourcerange.hpp"
|
||||
|
||||
class Reader {
|
||||
public:
|
||||
Reader(Arena& arena, String&& str) : _arena(arena), _str(std::move(str)) {}
|
||||
|
||||
Result<Value> read_one();
|
||||
Result<Value> read_multiple();
|
||||
|
||||
private:
|
||||
void forward();
|
||||
void forward(size_t n);
|
||||
bool forward_exponent();
|
||||
bool forward_decimal_number();
|
||||
bool forward_hex_number();
|
||||
void forward_whitespace();
|
||||
|
||||
bool is_eol();
|
||||
bool is_eof();
|
||||
bool is_whitespace();
|
||||
bool is_comment_start();
|
||||
bool is_numeric_start();
|
||||
bool is_symbol_start();
|
||||
bool is_string_start();
|
||||
|
||||
Result<Value> read_list();
|
||||
Result<Value> read_string();
|
||||
Result<Value> read_array();
|
||||
Result<Value> read_dict();
|
||||
Result<Value> read_number();
|
||||
Result<Value> read_symbol();
|
||||
Result<Value> read_bool();
|
||||
|
||||
char32_t get(size_t offset = 0);
|
||||
bool match(const char* str);
|
||||
bool match(char c);
|
||||
|
||||
Arena& _arena;
|
||||
String _str;
|
||||
SourcePosition position_{1, 1, 0};
|
||||
};
|
14
src/sourcerange.hpp
Normal file
14
src/sourcerange.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
struct SourcePosition {
|
||||
size_t line{1};
|
||||
size_t column{1};
|
||||
size_t offset{0};
|
||||
};
|
||||
|
||||
struct SourceRange {
|
||||
SourcePosition start;
|
||||
SourcePosition end;
|
||||
};
|
|
@ -21,10 +21,10 @@ int main() {
|
|||
{
|
||||
auto s = DIEIF(String::create(arena, "foo"));
|
||||
|
||||
std::cout << "roout count: " << arena.root_count() << "\n";
|
||||
std::cout << "root count: " << arena.root_count() << "\n";
|
||||
std::cout << "char: " << (char)DIEIF(s[2]) << "\n";
|
||||
}
|
||||
std::cout << "roout count: " << arena.root_count() << "\n";
|
||||
std::cout << "root count: " << arena.root_count() << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue