From 4b7d845757d0aad04951c5b297b77e723c05f3c5 Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Fri, 6 Sep 2024 23:32:05 +0100 Subject: [PATCH] Allow reading with preserving source location in syntax objects --- src/common.cpp | 13 ++++- src/common.hpp | 20 ++++++- src/reader.cpp | 149 ++++++++++++++++++++++++++++++++++++++++++------- src/reader.hpp | 8 ++- src/valeri.cpp | 4 +- src/writer.cpp | 2 +- 6 files changed, 165 insertions(+), 31 deletions(-) diff --git a/src/common.cpp b/src/common.cpp index f7c5b8d..1ff46a6 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -110,8 +110,8 @@ Result SrcLoc::cmp(const SrcLoc& rhs) const { return sourcerange_cmp(lhs_sourcerange, rhs_sourcerange); } -Result Syntax::create(String filename, SrcLoc srcloc, - Value expression) { +Result Syntax::create(const String& filename, const SrcLoc& srcloc, + const Value& expression) { auto pod = TRY(arena_alloc()); pod->header.tag = Tag::Syntax; pod->filename = filename.pod(); @@ -121,6 +121,15 @@ Result Syntax::create(String filename, SrcLoc srcloc, return Syntax(TRY(MkGcRoot(pod))); } +Result Syntax::create(const String& filename, + const SourcePosition& start, + const SourcePosition& end, + const Value& expression) { + auto srcloc = TRY(SrcLoc::create(start, end)); + + return Syntax::create(filename, srcloc, expression); +} + Result Syntax::filename() const { return Value::create(_value->filename.get()); } diff --git a/src/common.hpp b/src/common.hpp index d4d6d3f..cfebda2 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -9,6 +9,7 @@ #include "error.hpp" #include "opcode.hpp" #include "pod.hpp" +#include "sourcerange.hpp" #include "stdlib.hpp" #include "utf8.hpp" @@ -660,6 +661,17 @@ class SrcLoc : public Object { return SrcLoc(TRY(MkGcRoot(obj))); } + static Result create(const SourcePosition& start, + const SourcePosition& end) { + auto pod = TRY(arena_alloc()); + pod->header.tag = Tag::SrcLoc; + + pod->sourcerange.start = start; + pod->sourcerange.end = end; + + return SrcLoc(TRY(MkGcRoot(pod))); + } + SourceRange sourcerange() const; virtual Result copy_value() const final; @@ -674,8 +686,12 @@ class Syntax : public Object { Syntax() {} Syntax(Syntax&& rhs) : _value(std::move(rhs._value)) {} Syntax(GcRoot&& val) : _value(std::move(val)) {} - static Result create(String filename, SrcLoc srcloc, - Value expression); + static Result create(const String& filename, const SrcLoc& srcloc, + const Value& expression); + static Result create(const String& filename, + const SourcePosition& start, + const SourcePosition& end, + const Value& expression); virtual Tag tag() const final { return Tag::Syntax; } virtual PodObject* pod() const final { return _value.get(); } virtual Result cmp(const Object& rhs) const final { diff --git a/src/reader.cpp b/src/reader.cpp index 4a09ec5..9e9dbab 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -2,6 +2,7 @@ #include "common.hpp" #include "error.hpp" +#include "sourcerange.hpp" static bool is_digit(char32_t c) { return c >= '0' && c <= '9'; } static bool is_alpha(char32_t c) { @@ -88,7 +89,7 @@ Result Reader::read_multiple() { return ERROR(ReadError); } -Result Reader::read_list_rec(SourcePosition& end) { +Result Reader::read_list_rec() { forward_whitespace(); if (is_eof()) { @@ -97,12 +98,11 @@ Result Reader::read_list_rec(SourcePosition& end) { if (match(')')) { forward(); - end = position_; return Value(TRY(Nil::create())); } auto val = TRY(read_one()); - auto rest = TRY(read_list_rec(end)); + auto rest = TRY(read_list_rec()); auto res = Value(TRY(Pair::create(val, rest))); @@ -111,18 +111,43 @@ Result Reader::read_list_rec(SourcePosition& end) { Result Reader::read_list() { if (!match('(')) return ERROR(ReadError); - // SourcePosition start = position_; + + SourcePosition start = position_; forward(); - SourcePosition end = position_; - auto res = read_list_rec(end); + auto res = Value(TRY(Nil::create())); - return res; + while (1) { + forward_whitespace(); + + if (is_eof()) { + return ERROR(ReadError); + } + + if (match(')')) { + forward(); + SourcePosition end = position_; + + res = TRY(reverse(res)); + if (!_syntax) { + return res; + } else { + return Value(TRY(Syntax::create(_fname, start, end, res))); + } + } + + auto val = TRY(read_one()); + + res = TRY(Pair::create(val, res)); + } + + return ERROR(ReadError); } Result Reader::read_array_code() { if (!match('[')) return ERROR(ReadError); + SourcePosition start = position_; forward(); auto sym = Value(TRY(Symbol::create("array"))); @@ -137,7 +162,15 @@ Result Reader::read_array_code() { if (match(']')) { forward(); - return reverse(res); + + SourcePosition end = position_; + + res = TRY(reverse(res)); + if (!_syntax) { + return res; + } else { + return Value(TRY(Syntax::create(_fname, start, end, res))); + } } auto val = TRY(read_one()); @@ -151,6 +184,7 @@ Result Reader::read_array_code() { Result Reader::read_array_data() { if (!match('[')) return ERROR(ReadError); + SourcePosition start = position_; forward(); auto res = TRY(Array::create()); @@ -164,7 +198,14 @@ Result Reader::read_array_data() { if (match(']')) { forward(); - return Value(std::move(res)); + SourcePosition end = position_; + + if (!_syntax) { + return Value(std::move(res)); + } else { + return Value( + TRY(Syntax::create(_fname, start, end, Value(std::move(res))))); + } } auto val = TRY(read_one()); @@ -184,6 +225,7 @@ Result Reader::read_array() { Result Reader::read_dict_code() { if (!match('{')) return ERROR(ReadError); + SourcePosition start = position_; forward(); auto sym = Value(TRY(Symbol::create("dict"))); @@ -198,7 +240,15 @@ Result Reader::read_dict_code() { if (match('}')) { forward(); - return reverse(res); + + SourcePosition end = position_; + + res = TRY(reverse(res)); + if (!_syntax) { + return res; + } else { + return Value(TRY(Syntax::create(_fname, start, end, res))); + } } auto val1 = TRY(read_one()); @@ -214,6 +264,7 @@ Result Reader::read_dict_code() { Result Reader::read_dict_data() { if (!match('{')) return ERROR(ReadError); + SourcePosition start = position_; forward(); auto res = TRY(Dict::create()); @@ -227,7 +278,14 @@ Result Reader::read_dict_data() { if (match('}')) { forward(); - return Value(std::move(res)); + SourcePosition end = position_; + + if (!_syntax) { + return Value(std::move(res)); + } else { + return Value( + TRY(Syntax::create(_fname, start, end, Value(std::move(res))))); + } } auto val1 = TRY(read_one()); @@ -246,25 +304,48 @@ Result Reader::read_dict() { } Result Reader::read_bool() { + SourcePosition start = position_; if (match("true")) { forward(4); if (!is_separator(get()) && !is_eof()) return ERROR(ReadError); - return Value(TRY(Bool::create(true))); + SourcePosition end = position_; + + auto res = Value(TRY(Bool::create(true))); + if (!_syntax) { + return res; + } else { + return Value(TRY(Syntax::create(_fname, start, end, res))); + } } if (match("false")) { forward(5); if (!is_separator(get()) && !is_eof()) return ERROR(ReadError); - return Value(TRY(Bool::create(false))); + SourcePosition end = position_; + + auto res = Value(TRY(Bool::create(false))); + if (!_syntax) { + return res; + } else { + return Value(TRY(Syntax::create(_fname, start, end, res))); + } } return ERROR(ReadError); } Result Reader::read_nil() { + SourcePosition start = position_; if (match("nil")) { forward(3); if (!is_separator(get()) && !is_eof()) return ERROR(ReadError); - return Value(TRY(Nil::create())); + SourcePosition end = position_; + + auto res = Value(TRY(Nil::create())); + if (!_syntax) { + return res; + } else { + return Value(TRY(Syntax::create(_fname, start, end, res))); + } } return ERROR(ReadError); @@ -274,6 +355,7 @@ Result Reader::read_string() { if (!match('"')) return ERROR(ReadError); size_t start = position_.offset + 1; + SourcePosition startloc = position_; forward(); while (!match('"') && !match('\r') && !match('\n') && !is_eof()) { @@ -331,13 +413,20 @@ Result Reader::read_string() { } if (!is_separator(get()) && !is_eof()) return ERROR(ReadError); + SourcePosition endloc = position_; - return Value(std::move(result)); + auto res = Value(std::move(result)); + if (!_syntax) { + return res; + } else { + return Value(TRY(Syntax::create(_fname, startloc, endloc, res))); + } } Result Reader::read_number() { if (!is_numeric_start()) return ERROR(ReadError); size_t start = position_.offset; + SourcePosition startloc = position_; bool is_float = false; @@ -397,13 +486,20 @@ Result Reader::read_number() { if (!is_separator(get()) && !is_eof()) return ERROR(ReadError); - return res; + SourcePosition endloc = position_; + + if (!_syntax) { + return res; + } else { + return Value(TRY(Syntax::create(_fname, startloc, endloc, res))); + } } Result Reader::read_symbol() { if (!is_symbol_char(get())) return ERROR(ReadError); size_t start = position_.offset; + SourcePosition startloc = position_; while (is_symbol_char(get())) forward(); @@ -413,7 +509,14 @@ Result Reader::read_symbol() { if (!is_separator(get()) && !is_eof()) return ERROR(ReadError); - return Value(TRY(Symbol::create(str))); + SourcePosition endloc = position_; + + auto res = Value(TRY(Symbol::create(str))); + if (!_syntax) { + return res; + } else { + return Value(TRY(Syntax::create(_fname, startloc, endloc, res))); + } } char32_t Reader::get(size_t offset) { @@ -524,20 +627,24 @@ bool Reader::forward_exponent() { Result read_one(const Value& value, bool syntax, bool as_code) { if (!value.is()) return ERROR(TypeMismatch); - auto r = Reader(*value.to(), syntax, as_code); + auto fname = TRY(String::create("")); + auto r = Reader(fname, *value.to(), syntax, as_code); return r.read_one(); } Result read_one(const String& value, bool syntax, bool as_code) { - auto r = Reader(value, syntax, as_code); + auto fname = TRY(String::create("")); + auto r = Reader(fname, value, syntax, as_code); return r.read_one(); } Result read_one(const char* value, bool syntax, bool as_code) { + auto fname = TRY(String::create("")); auto s = TRY(String::create(value)); - auto r = Reader(s, syntax, as_code); + auto r = Reader(fname, s, syntax, as_code); return r.read_one(); } Result read_multiple(const String& value, bool syntax, bool as_code) { - auto r = Reader(value, syntax, as_code); + auto fname = TRY(String::create("")); + auto r = Reader(fname, value, syntax, as_code); return r.read_multiple(); } diff --git a/src/reader.hpp b/src/reader.hpp index 6fa28be..23fb722 100644 --- a/src/reader.hpp +++ b/src/reader.hpp @@ -5,8 +5,9 @@ class Reader { public: - Reader(const String& str, bool syntax = true, bool as_code = true) - : _str(str), _syntax(syntax), _as_code(as_code) {} + Reader(const String& fname, const String& str, bool syntax = true, + bool as_code = true) + : _fname(fname), _str(str), _syntax(syntax), _as_code(as_code) {} Result read_one(); Result read_multiple(); @@ -28,7 +29,7 @@ class Reader { bool is_string_start(); Result read_list(); - Result read_list_rec(SourcePosition& end); + Result read_list_rec(); Result read_string(); Result read_array(); Result read_array_code(); @@ -45,6 +46,7 @@ class Reader { bool match(const char* str); bool match(char c); + const String& _fname; const String& _str; bool _syntax; bool _as_code; diff --git a/src/valeri.cpp b/src/valeri.cpp index 29f7c04..1d9b0ab 100644 --- a/src/valeri.cpp +++ b/src/valeri.cpp @@ -13,7 +13,7 @@ StaticArena<64 * 1024 * 1024> arena; Result run_string(const String& src) { - auto parsed = TRY(read_multiple(src)); + auto parsed = TRY(read_multiple(src, false)); TRY(arena_gc()); @@ -32,7 +32,7 @@ Result run_repl() { while (true) { auto src = TRY(read_line("valeri> ")); - auto parsed = TRY(read_multiple(src)); + auto parsed = TRY(read_multiple(src, false)); auto compiled = TRY(compile(parsed)); Module& mod = *compiled.to(); auto vm = TRY(VM::create()); diff --git a/src/writer.cpp b/src/writer.cpp index 04fa00c..594a795 100644 --- a/src/writer.cpp +++ b/src/writer.cpp @@ -196,7 +196,7 @@ Result Writer::write_srcloc(const SrcLoc& val) { } Result Writer::write_syntax(const Syntax& val) { - return ERROR(NotImplemented); + return TRY(String::create("#")); } Result Writer::write_pair(const Pair& val) {