Beginnings of a reader

This commit is contained in:
Konstantin Nazarov 2024-07-27 16:25:44 +01:00
parent ded19f7962
commit 46381cccef
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
10 changed files with 343 additions and 79 deletions

View file

@ -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/reader.cpp
PUBLIC PUBLIC
FILE_SET HEADERS FILE_SET HEADERS
@ -25,6 +26,8 @@ target_sources(vm_lib
src/pod.hpp src/pod.hpp
src/result.hpp src/result.hpp
src/vm.hpp src/vm.hpp
src/sourcerange.hpp
src/reader.hpp
) )
add_executable(vli src/vli.cpp) add_executable(vli src/vli.cpp)

View file

@ -17,6 +17,8 @@ class GcRootBase {
~GcRootBase(); ~GcRootBase();
PodObject* get() { return _ptr; }
protected: protected:
PodObject* _ptr; PodObject* _ptr;
GcRootList* _node; GcRootList* _node;
@ -35,6 +37,7 @@ class GcRoot : public GcRootBase {
return GcRoot<T>::create((T*)_ptr, arena); return GcRoot<T>::create((T*)_ptr, arena);
} }
T* get() { return (T*)_ptr; }
T& operator*() { return *(T*)_ptr; } T& operator*() { return *(T*)_ptr; }
T* operator->() { return (T*)_ptr; } T* operator->() { return (T*)_ptr; }
}; };

View file

@ -1,6 +1,8 @@
#include "common.hpp" #include "common.hpp"
#include "arena.hpp" #include "arena.hpp"
#include "error.hpp"
#include "pod.hpp"
Syntax::Syntax(String filename, String modulename, Value expression) {} 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) { Result<Value> Value::create(Arena& arena, PodObject* obj) {
switch (obj->header.tag) { switch (obj->header.tag) {
case Tag::Nil: case Tag::Nil:
return Value(); return Value(TRY(Nil::create(arena, (PodNil*)obj)));
case Tag::Int64: case Tag::Int64:
return Value(Int64(((PodInt64*)obj)->value)); return Value(TRY(Int64::create(arena, (PodInt64*)obj)));
case Tag::Float: case Tag::Float:
return Value(Int64(((PodFloat*)obj)->value)); return Value(TRY(Float::create(arena, (PodFloat*)obj)));
case Tag::String: case Tag::String:
return Value(TRY(String::create(arena, (PodString*)obj))); return Value(TRY(String::create(arena, (PodString*)obj)));
case Tag::Symbol: 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> Nil::copy(Arena& arena) { return Value(Nil()); }
Result<Value> Int64::copy(Arena& arena) { return Value(Int64(_value)); } Result<Value> Int64::copy(Arena& arena) {
Result<Value> Float::copy(Arena& arena) { return Value(Float(_value)); } 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) { Result<Value> String::copy(Arena& arena) {
return Value(String(TRY(_value.copy(arena)))); return Value(String(TRY(_value.copy(arena))));
@ -55,3 +61,37 @@ Result<Value> Syntax::copy(Arena& arena) {
Result<Value> Pair::copy(Arena& arena) { Result<Value> Pair::copy(Arena& arena) {
return Value(Pair(TRY(_value.copy(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;
}

View file

@ -12,75 +12,35 @@
class Value; 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 { class Object {
public: public:
virtual Tag tag() = 0; virtual Tag tag() = 0;
virtual Result<Value> copy(Arena& arena) = 0; virtual Result<Value> copy(Arena& arena) = 0;
virtual PodObject* pod() = 0;
}; };
class Nil : public Object { class Nil : public Object {
public: public:
Nil() {} Nil() {}
Nil(GcRoot<PodNil>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Nil; } 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; virtual Result<Value> copy(Arena& arena) final;
private:
GcRoot<PodNil> _value;
}; };
class String : public Object { class String : public Object {
@ -88,6 +48,7 @@ class String : public Object {
String() {} String() {}
String(GcRoot<PodString>&& val) : _value(std::move(val)) {} String(GcRoot<PodString>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::String; } virtual Tag tag() final { return Tag::String; }
virtual PodObject* pod() final { return _value.get(); }
static Result<String> create(Arena& arena, PodString* obj) { static Result<String> create(Arena& arena, PodString* obj) {
return String(TRY(MkGcRoot(obj, arena))); return String(TRY(MkGcRoot(obj, arena)));
@ -129,6 +90,7 @@ class Symbol : public Object {
Symbol() {} Symbol() {}
Symbol(GcRoot<PodSymbol>&& val) : _value(std::move(val)) {} Symbol(GcRoot<PodSymbol>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Symbol; } virtual Tag tag() final { return Tag::Symbol; }
virtual PodObject* pod() final { return _value.get(); }
static Result<Symbol> create(Arena& arena, PodSymbol* obj) { static Result<Symbol> create(Arena& arena, PodSymbol* obj) {
return Symbol(TRY(MkGcRoot(obj, arena))); return Symbol(TRY(MkGcRoot(obj, arena)));
@ -154,6 +116,7 @@ class Syntax : public Object {
Syntax(GcRoot<PodSyntax>&& val) : _value(std::move(val)) {} Syntax(GcRoot<PodSyntax>&& val) : _value(std::move(val)) {}
Syntax(String filename, String modulename, Value expression); Syntax(String filename, String modulename, Value expression);
virtual Tag tag() final { return Tag::Syntax; } virtual Tag tag() final { return Tag::Syntax; }
virtual PodObject* pod() final { return _value.get(); }
static Result<Syntax> create(Arena& arena, PodSyntax* obj) { static Result<Syntax> create(Arena& arena, PodSyntax* obj) {
return Syntax(TRY(MkGcRoot(obj, arena))); return Syntax(TRY(MkGcRoot(obj, arena)));
@ -172,12 +135,15 @@ class Pair : public Object {
Pair() {} Pair() {}
Pair(GcRoot<PodPair>&& val) : _value(std::move(val)) {} Pair(GcRoot<PodPair>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Pair; } virtual Tag tag() final { return Tag::Pair; }
virtual PodObject* pod() final { return _value.get(); }
static Result<Pair> create(Arena& arena, PodPair* obj) { static Result<Pair> create(Arena& arena, PodPair* obj) {
return Pair(TRY(MkGcRoot(obj, arena))); 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; virtual Result<Value> copy(Arena& arena) final;
@ -187,34 +153,54 @@ class Pair : public Object {
class Int64 : public Object { class Int64 : public Object {
public: public:
Int64() : _value(0) {} Int64() {}
Int64(int64_t val) : _value(val) {} Int64(GcRoot<PodInt64>&& val) : _value(std::move(val)) {}
virtual ~Int64() = default;
virtual Tag tag() final { return Tag::Int64; } 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; virtual Result<Value> copy(Arena& arena) final;
private: private:
int64_t _value; GcRoot<PodInt64> _value;
}; };
class Float : public Object { class Float : public Object {
public: public:
Float() : _value(0) {} Float() {}
Float(double val) : _value(val) {} Float(GcRoot<PodFloat>&& val) : _value(std::move(val)) {}
virtual ~Float() = default;
virtual Tag tag() final { return Tag::Float; } 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; virtual Result<Value> copy(Arena& arena) final;
private: private:
double _value; GcRoot<PodFloat> _value;
}; };
// note: this class doesn't perform proper destruction of objects in some cases // 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)); 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); static Result<Value> create(Arena& arena, PodObject* obj);
template <class T> template <class T>
@ -247,6 +239,8 @@ class Value {
return dynamic_cast<T*>((Object*)buf); return dynamic_cast<T*>((Object*)buf);
} }
PodObject* pod() { return ((Object*)buf)->pod(); }
Object& operator*() { return *(Object*)(buf); } Object& operator*() { return *(Object*)(buf); }
Object* operator->() { return (Object*)(buf); } Object* operator->() { return (Object*)(buf); }
@ -257,3 +251,5 @@ class Value {
}; };
Result<Value> syntax_unwrap(Value& val); Result<Value> syntax_unwrap(Value& val);
Result<Value> reverse(Arena& arena, Value& val);

View file

@ -3,6 +3,7 @@
enum class ErrorCode { enum class ErrorCode {
Success, Success,
OutOfMemory, OutOfMemory,
IndexOutOfRange IndexOutOfRange,
TypeMismatch,
ReadError
}; };

View file

@ -2,6 +2,9 @@
#include <cstdint> #include <cstdint>
#include "result.hpp"
#include "sourcerange.hpp"
enum class Tag : uint8_t { enum class Tag : uint8_t {
Nil, Nil,
Int64, Int64,
@ -43,3 +46,78 @@ static_assert(sizeof(PodHeader) == 8);
struct PodObject { struct PodObject {
PodHeader header; 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
View 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
View 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
View 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;
};

View file

@ -21,10 +21,10 @@ int main() {
{ {
auto s = DIEIF(String::create(arena, "foo")); 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 << "char: " << (char)DIEIF(s[2]) << "\n";
} }
std::cout << "roout count: " << arena.root_count() << "\n"; std::cout << "root count: " << arena.root_count() << "\n";
return 0; return 0;
} }