From 021f645fbfd7bee4e2a4b5cad2dcb08b42a4a0e3 Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Tue, 10 Sep 2024 02:12:49 +0100 Subject: [PATCH] Extract a common interface for Value::size() to get object sizes --- src/common.cpp | 49 ++++++++++++++++++++++++------------------ src/common.hpp | 55 +++++++++++++++++++++++++----------------------- src/compiler.cpp | 24 +++++++++++---------- src/reader.cpp | 7 +++++- src/stdlib.cpp | 22 ++++++++++++------- src/writer.cpp | 14 ++++++------ 6 files changed, 98 insertions(+), 73 deletions(-) diff --git a/src/common.cpp b/src/common.cpp index 2a2547c..5c36324 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -51,7 +51,7 @@ Result Value::create(PodObject* obj) { } Result Symbol::create(String& rhs) { - uint64_t rhs_size = rhs.size(); + uint64_t rhs_size = TRY(rhs.size()); uint64_t res_size = rhs_size; auto pod = TRY(arena_alloc(res_size * sizeof(char32_t))); @@ -63,7 +63,7 @@ Result Symbol::create(String& rhs) { } Result String::create(const Symbol& rhs) { - uint64_t rhs_size = rhs.size(); + uint64_t rhs_size = TRY(rhs.size()); uint64_t res_size = rhs_size; auto pod = TRY(arena_alloc(res_size * sizeof(char32_t))); @@ -76,7 +76,8 @@ Result String::create(const Symbol& rhs) { Result ByteArray::create(const String& str) { uint64_t size = 0; - for (uint64_t i = 0; i < str.size(); i++) { + auto strsize = TRY(str.size()); + for (uint64_t i = 0; i < strsize; i++) { size += utf8_codepoint_size(TRY(str[i])); } auto pod = TRY(arena_alloc(size * sizeof(char))); @@ -84,7 +85,7 @@ Result ByteArray::create(const String& str) { pod->size = size; char* res = pod->data; - for (uint64_t i = 0; i < str.size(); i++) { + for (uint64_t i = 0; i < strsize; i++) { char32_t codepoint = TRY(str[i]); size = utf8_codepoint_size(codepoint); res = utf8_write_codepoint(res, codepoint); @@ -365,9 +366,9 @@ Result Pair::create(const Value& first, const Value& rest) { Result Pair::create(const Array& arr) { Value cur = TRY(Nil::create()); - - for (uint64_t i = 0; i < arr.size(); i++) { - Value arr_elt = TRY(arr.get(arr.size() - i - 1)); + auto size = TRY(arr.size()); + for (uint64_t i = 0; i < size; i++) { + Value arr_elt = TRY(arr.get(size - i - 1)); cur = TRY(Pair::create(arr_elt, cur)); } @@ -510,8 +511,9 @@ Result debug_print(const char* val) { Result debug_print(const String& val) { auto ba = TRY(ByteArray::create(val)); + auto size = TRY(ba.size()); - for (uint64_t i = 0; i < ba.size(); i++) { + for (uint64_t i = 0; i < size; i++) { std::cout << TRY(ba[i]); } std::cout << "\n"; @@ -536,15 +538,16 @@ Result Array::get(const Value& key) const { } Result Array::append(const Value& rhs) const { - uint64_t res_size = size() + 1; + uint64_t res_size = TRY(size()) + 1; + auto size = TRY(this->size()); auto pod = TRY(arena_alloc(res_size * sizeof(OffPtr))); pod->header.tag = Tag::Array; pod->size = res_size; - for (uint64_t i = 0; i < size(); i++) { + for (uint64_t i = 0; i < size; i++) { pod->data[i] = _value->data[i].get(); } - pod->data[size()] = rhs.pod(); + pod->data[TRY(this->size())] = rhs.pod(); return Array(TRY(MkGcRoot(pod))); } @@ -556,11 +559,12 @@ short cmp_tag(Tag lhs, Tag rhs) { } Result Dict::create(const Array& arr) { - if (arr.size() % 2 != 0) return ERROR(KeyError); + auto arr_size = TRY(arr.size()); + if (arr_size % 2 != 0) return ERROR(KeyError); Dict res = TRY(Dict::create()); - for (uint64_t i = 0; i < arr.size() / 2; i++) { + for (uint64_t i = 0; i < arr_size / 2; i++) { auto key = TRY(Value::create(arr._value->data[2 * i].get())); auto value = TRY(Value::create(arr._value->data[2 * i + 1].get())); @@ -572,7 +576,7 @@ Result Dict::create(const Array& arr) { Result Dict::get(const Value& key) const { auto pos = TRY(find(key)); - if (pos >= size()) { + if (pos >= TRY(size())) { return ERROR(KeyError); } auto k = TRY(Value::create(_value->data[pos * 2].get())); @@ -586,7 +590,8 @@ Result Dict::get(const Value& key) const { Result Dict::insert(const Value& key, const Value& value) { auto pos = TRY(find(key)); - auto s = size(); + auto this_size = TRY(size()); + auto s = this_size; if (pos >= s) { s += 1; } else { @@ -603,7 +608,7 @@ Result Dict::insert(const Value& key, const Value& value) { if (i == pos) { pod->data[i * 2] = key.pod(); pod->data[i * 2 + 1] = value.pod(); - if (s > size() && i < s - 1) { + if (s > this_size && i < s - 1) { i++; pod->data[i * 2] = _value->data[j * 2].get(); pod->data[i * 2 + 1] = _value->data[j * 2 + 1].get(); @@ -619,7 +624,7 @@ Result Dict::insert(const Value& key, const Value& value) { Result Dict::find(const Value& key) const { uint64_t left = 0; - uint64_t right = size(); + uint64_t right = TRY(size()); uint64_t pos = (left + right) / 2; while (left < right) { auto v = TRY(Value::create(_value->data[pos * 2].get())); @@ -748,8 +753,8 @@ Result Float::cmp(const Int64& rhs) const { } Result Dict::cmp(const Dict& rhs) const { - auto lsize = size() * 2; - auto rsize = rhs.size() * 2; + auto lsize = TRY(size()) * 2; + auto rsize = TRY(rhs.size()) * 2; uint64_t i = 0; uint64_t j = 0; while (1) { @@ -769,8 +774,8 @@ Result Dict::cmp(const Dict& rhs) const { } Result Array::cmp(const Array& rhs) const { - auto lsize = size(); - auto rsize = rhs.size(); + auto lsize = TRY(size()); + auto rsize = TRY(rhs.size()); uint64_t i = 0; uint64_t j = 0; while (1) { @@ -799,6 +804,8 @@ Result Object::third() const { return ERROR(TypeMismatch); } Result Object::rest() const { return ERROR(TypeMismatch); } +Result Object::size() const { return ERROR(TypeMismatch); } + Result syntax_is_list(const Value& value) { if (!value.is()) return value.is(); diff --git a/src/common.hpp b/src/common.hpp index a931786..8e1f49c 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -129,6 +129,8 @@ class Object { virtual Result third() const; virtual Result rest() const; + virtual Result size() const; + Object() = default; Object(const Object&) = delete; }; @@ -200,7 +202,7 @@ class Array : public Object { return Array(TRY(MkGcRoot(pod))); } - uint64_t size() const { return _value->size; } + virtual Result size() const { return _value->size; } virtual Result copy_value() const final; Result copy() const; @@ -212,17 +214,17 @@ class Array : public Object { Result append(const V& value) const; Result concat(Array& rhs) { - uint64_t rhs_size = rhs.size(); - uint64_t lhs_size = size(); + uint64_t rhs_size = TRY(rhs.size()); + uint64_t lhs_size = TRY(size()); uint64_t res_size = lhs_size + rhs_size; auto pod = TRY(arena_alloc(res_size * sizeof(PodObject*))); pod->header.tag = Tag::Array; pod->size = res_size; - for (uint64_t i = 0; i < size(); i++) { + for (uint64_t i = 0; i < lhs_size; i++) { pod->data[i] = _value->data[i].get(); } - for (uint64_t i = 0; i < rhs.size(); i++) { + for (uint64_t i = 0; i < rhs_size; i++) { pod->data[lhs_size + i] = rhs._value->data[i].get(); } @@ -294,7 +296,7 @@ class ByteArray : public Object { static Result create(const String& str); - uint64_t size() const { return _value->size; } + virtual Result size() const final { return _value->size; } virtual Result copy_value() const final; Result copy() const; @@ -305,7 +307,7 @@ class ByteArray : public Object { Result concat(const char* rhs) { uint64_t rhs_size = strlen(rhs); - uint64_t lhs_size = size(); + uint64_t lhs_size = TRY(size()); uint64_t res_size = lhs_size + rhs_size; auto pod = TRY(arena_alloc(res_size * sizeof(char))); @@ -317,7 +319,7 @@ class ByteArray : public Object { } Result concat(const char* rhs, uint64_t rhs_size) { - uint64_t lhs_size = size(); + uint64_t lhs_size = TRY(size()); uint64_t res_size = lhs_size + rhs_size; auto pod = TRY(arena_alloc(res_size * sizeof(char))); @@ -329,8 +331,8 @@ class ByteArray : public Object { } Result concat(ByteArray& rhs) { - uint64_t rhs_size = rhs.size(); - uint64_t lhs_size = size(); + uint64_t rhs_size = TRY(rhs.size()); + uint64_t lhs_size = TRY(size()); uint64_t res_size = lhs_size + rhs_size; auto pod = TRY(arena_alloc(res_size * sizeof(char))); @@ -400,27 +402,28 @@ class Dict : public Object { Result insert(const K& key, const V& value); Result concat(Dict& rhs) { - uint64_t rhs_size = rhs.size(); - uint64_t lhs_size = size(); + uint64_t rhs_size = TRY(rhs.size()); + uint64_t lhs_size = TRY(size()); uint64_t res_size = lhs_size + rhs_size; auto pod = TRY(arena_alloc(2 * res_size * sizeof(PodObject*))); pod->size = res_size; - for (uint64_t i = 0; i < 2 * size(); i++) { + for (uint64_t i = 0; i < 2 * lhs_size; i++) { pod->data[i] = _value->data[i]; } - for (uint64_t i = 2 * size(); i < 2 * rhs.size(); i++) { + for (uint64_t i = 2 * lhs_size; i < 2 * rhs_size; i++) { pod->data[i] = rhs._value->data[i]; } return Dict(TRY(MkGcRoot(pod))); } + virtual Result size() const final { return _value->size; } + private: Result find(const Value& key) const; - uint64_t size() const { return _value->size; } GcRoot _value; }; @@ -441,8 +444,8 @@ class String : public Object { return -TRY(rhs.cmp(*this)); } virtual Result cmp(const String& rhs) const final { - auto lsize = size(); - auto rsize = rhs.size(); + auto lsize = TRY(size()); + auto rsize = TRY(rhs.size()); uint64_t i = 0; uint64_t j = 0; while (1) { @@ -489,7 +492,7 @@ class String : public Object { return String(TRY(MkGcRoot(pod))); } - uint64_t size() const { return _value->size; } + virtual Result size() const final { return _value->size; } virtual Result copy_value() const final; Result copy() const; @@ -499,7 +502,7 @@ class String : public Object { } Result concat(const char* rhs, uint64_t rhs_size) { - uint64_t lhs_size = size(); + uint64_t lhs_size = TRY(size()); uint64_t res_size = lhs_size + rhs_size; auto pod = TRY(arena_alloc(res_size * sizeof(char32_t))); @@ -514,7 +517,7 @@ class String : public Object { Result concat(const char* rhs) { return concat(rhs, strlen(rhs)); } Result concat(const char32_t* rhs, uint64_t rhs_size) { - uint64_t lhs_size = size(); + uint64_t lhs_size = TRY(size()); uint64_t res_size = lhs_size + rhs_size; auto pod = TRY(arena_alloc(res_size * sizeof(char32_t))); @@ -527,8 +530,8 @@ class String : public Object { } Result concat(String& rhs) { - uint64_t rhs_size = rhs.size(); - uint64_t lhs_size = size(); + uint64_t rhs_size = TRY(rhs.size()); + uint64_t lhs_size = TRY(size()); uint64_t res_size = lhs_size + rhs_size; auto pod = TRY(arena_alloc(res_size * sizeof(char32_t))); @@ -570,8 +573,8 @@ class Symbol : public Object { return -TRY(rhs.cmp(*this)); } virtual Result cmp(const Symbol& rhs) const final { - auto lsize = size(); - auto rsize = rhs.size(); + auto lsize = TRY(size()); + auto rsize = TRY(rhs.size()); uint64_t i = 0; uint64_t j = 0; while (1) { @@ -590,7 +593,7 @@ class Symbol : public Object { return 0; } virtual Result cmp(const char* rhs) const final { - auto lsize = size(); + auto lsize = TRY(size()); auto rsize = strlen(rhs); uint64_t i = 0; uint64_t j = 0; @@ -639,7 +642,7 @@ class Symbol : public Object { virtual Result copy_value() const final; Result copy() const; - uint64_t size() const { return _value->size; } + virtual Result size() const final { return _value->size; } Result operator[](uint64_t idx) const { if (idx >= _value->size) return ERROR(IndexOutOfRange); diff --git a/src/compiler.cpp b/src/compiler.cpp index 076cbea..8e8aa18 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -61,7 +61,7 @@ struct Context { return idx.value().to()->value(); } - int64_t i = constants.size(); + int64_t i = TRY(constants.size()); constants = TRY(constants.append(val)); constants_dict = TRY(constants_dict.insert(val, TRY(Value::create(i)))); @@ -132,7 +132,7 @@ struct Context { } } - int64_t i = closures.size(); + int64_t i = TRY(closures.size()); closures = TRY(closures.append(sym)); closures_dict = TRY(closures_dict.insert(sym, TRY(Value::create(i)))); @@ -423,10 +423,10 @@ Result Compiler::compile_if(Context& context, Symbol& op, TRY(ex.add_opcode(Oc::Equal, {0, (int64_t)firstreg}, {1, (int64_t)true_const}, {0, (int64_t)0})); - TRY(ex.add_opcode(Oc::Jump, {0, (int64_t)option1_comp.code.size() + 2})); + TRY(ex.add_opcode(Oc::Jump, {0, (int64_t)TRY(option1_comp.code.size()) + 2})); ex.add_code(option1_comp.code); - TRY(ex.add_opcode(Oc::Jump, {0, (int64_t)option2_comp.code.size() + 1})); + TRY(ex.add_opcode(Oc::Jump, {0, (int64_t)TRY(option2_comp.code.size()) + 1})); ex.add_code(option2_comp.code); uint64_t option2_reg = option2_comp.reg; @@ -468,7 +468,7 @@ Result Compiler::compile_and(Context& context, Symbol& op, if (!is_first) { TRY(ex.add_opcode(Oc::Equal, {0, (int64_t)prev_reg}, {1, (int64_t)true_c}, {0, (int64_t)0})); - TRY(ex.add_opcode(Oc::Jump, {0, (int64_t)param_ex.code.size() + 2})); + TRY(ex.add_opcode(Oc::Jump, {0, (int64_t)TRY(param_ex.code.size()) + 2})); } prev_reg = param_ex.reg; TRY(ex.add_code(param_ex.code)); @@ -515,7 +515,7 @@ Result Compiler::compile_or(Context& context, Symbol& op, if (!is_first) { TRY(ex.add_opcode(Oc::Equal, {0, (int64_t)prev_reg}, {1, (int64_t)true_c}, {0, (int64_t)1})); - TRY(ex.add_opcode(Oc::Jump, {0, (int64_t)param_ex.code.size() + 2})); + TRY(ex.add_opcode(Oc::Jump, {0, (int64_t)TRY(param_ex.code.size()) + 2})); } prev_reg = param_ex.reg; TRY(ex.add_code(param_ex.code)); @@ -685,7 +685,7 @@ Result Compiler::compile_fn(Context& context, Symbol& op, Expression ex_res = TRY(Expression::create()); - if (ctx.closures.size() == 0) { + if (TRY(ctx.closures.size()) == 0) { int64_t c = TRY(context.add_const(TRY(fun.copy()))); if (context.toplevel && !name.is()) { @@ -707,7 +707,8 @@ Result Compiler::compile_fn(Context& context, Symbol& op, uint64_t reg = context.alloc_reg(); TRY(ex_res.add_opcode(Oc::Mov, {0, (int64_t)reg}, {1, (int64_t)c})); - for (uint64_t i = 0; i < ctx.closures.size(); i++) { + auto closures_size = TRY(ctx.closures.size()); + for (uint64_t i = 0; i < closures_size; i++) { Value sym = TRY(ctx.closures.get(i)); // If this is a regular variable from outer scope - it is present in a @@ -738,8 +739,9 @@ Result Compiler::compile_fn(Context& context, Symbol& op, TRY(ex_res.add_opcode(Oc::GlobalLoad, {0, (int64_t)vr}, {1, (int64_t)c})); } - TRY(ex_res.add_opcode(Oc::MakeClosure, {0, (int64_t)reg}, - {0, (int64_t)reg + (int64_t)ctx.closures.size() + 1})); + TRY(ex_res.add_opcode( + Oc::MakeClosure, {0, (int64_t)reg}, + {0, (int64_t)reg + (int64_t)TRY(ctx.closures.size()) + 1})); if (context.toplevel && !name.is()) { int64_t gname = TRY(context.add_const(name)); @@ -953,7 +955,7 @@ Result Compiler::compile_symbol(Context& context, if (unwrapped.is()) { Symbol& sym = *unwrapped.to(); - if (sym.size() > 0 && TRY(sym[0]) == ':') { + if (TRY(sym.size()) > 0 && TRY(sym[0]) == ':') { int64_t c = TRY(context.add_const(unwrapped)); uint64_t reg = context.alloc_reg(); diff --git a/src/reader.cpp b/src/reader.cpp index 5957fbb..52e1524 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -559,7 +559,12 @@ char32_t Reader::get(size_t offset) { bool Reader::is_eol() { return match('\n') || match('\r'); } -bool Reader::is_eof() { return position_.offset == _str.size(); } +bool Reader::is_eof() { + // DIEX is here instead of "try" because String::size() can never fail. + // The result is wrapped to Result<> because of common interface with + // other value types. + return position_.offset == DIEX(_str.size()); +} bool Reader::is_whitespace() { return match(' ') || match('\t') || match('\v') || match('\f'); diff --git a/src/stdlib.cpp b/src/stdlib.cpp index b4d6c00..237b790 100644 --- a/src/stdlib.cpp +++ b/src/stdlib.cpp @@ -19,8 +19,9 @@ Result stdlib_unknown(const Array& params) { Result print_string(const String& s) { auto ba = TRY(ByteArray::create(s)); + auto size = TRY(ba.size()); - for (uint64_t i = 0; i < ba.size(); i++) { + for (uint64_t i = 0; i < size; i++) { std::cout << TRY(ba[i]); } @@ -28,7 +29,8 @@ Result print_string(const String& s) { } Result stdlib_print(const Array& params) { - for (uint64_t i = 0; i < params.size(); i++) { + auto size = TRY(params.size()); + for (uint64_t i = 0; i < size; i++) { Value param = TRY(params.get(i)); if (i != 0) { @@ -55,7 +57,8 @@ Result stdlib_println(const Array& params) { Result stdlib_prn(const Array& params) { return ERROR(NotImplemented); } Result stdlib_assert(const Array& params) { - for (uint64_t i = 0; i < params.size(); i++) { + auto size = TRY(params.size()); + for (uint64_t i = 0; i < size; i++) { Value param = TRY(params.get(i)); if (!param.is()) return ERROR(AssertionFailed); auto v = param.to()->value(); @@ -81,7 +84,8 @@ Result stdlib_array(const Array& params) { } Result stdlib_get(const Array& params) { - if (params.size() != 2) return ERROR(ArgumentCountMismatch); + auto size = TRY(params.size()); + if (size != 2) return ERROR(ArgumentCountMismatch); Value collection = TRY(params.get(0)); Value key = TRY(params.get(1)); return TRY(collection.get(key)); @@ -89,7 +93,8 @@ Result stdlib_get(const Array& params) { Result stdlib_srcloc(const Array& params) { Array array_copy = TRY(params.copy()); - if (params.size() != 6) return ERROR(ArgumentCountMismatch); + auto size = TRY(params.size()); + if (size != 6) return ERROR(ArgumentCountMismatch); SourceRange sr; for (uint64_t i = 0; i < 6; i++) { @@ -158,14 +163,15 @@ StdlibFunctionEntry get_function_entry(const char* name) { Result get_stdlib_function(const Symbol& name) { const uint64_t bufsize = 256; char buf[bufsize]; - if (name.size() + 1 > bufsize) { + auto size = TRY(name.size()); + if (size + 1 > bufsize) { return ERROR(KeyError); } - for (uint64_t i = 0; i < name.size(); i++) { + for (uint64_t i = 0; i < size; i++) { buf[i] = (char)TRY(name[i]); } - buf[name.size()] = 0; + buf[size] = 0; StdlibFunctionId fun_id = get_function_entry(buf).fun_id; if (fun_id == StdlibFunctionId::Unknown) { diff --git a/src/writer.cpp b/src/writer.cpp index fe5d4e5..f091ad9 100644 --- a/src/writer.cpp +++ b/src/writer.cpp @@ -121,9 +121,9 @@ Result Writer::write_bytearray(const ByteArray& val) { Result Writer::write_string(const String& val) { String res = TRY(String::create("\"")); - + auto size = TRY(val.size()); // TODO: optimize this - for (uint64_t i = 0; i < val.size(); i++) { + for (uint64_t i = 0; i < size; i++) { char32_t c = TRY(val[i]); const char* replace = 0; switch (c) { @@ -172,9 +172,9 @@ int is_valid_symbol_char(char32_t codepoint) { Result Writer::write_symbol(const Symbol& val) { String res = TRY(String::create("")); - + auto size = TRY(val.size()); // TODO: optimize this - for (uint64_t i = 0; i < val.size(); i++) { + for (uint64_t i = 0; i < size; i++) { char32_t c = TRY(val[i]); if (!is_valid_symbol_char(c)) return ERROR(InvalidSymbol); @@ -239,7 +239,8 @@ Result Writer::write_array(const Array& val) { String res = TRY(String::create("[")); bool is_first = true; - for (uint64_t i = 0; i < val.size(); i++) { + auto size = TRY(val.size()); + for (uint64_t i = 0; i < size; i++) { Value cur = TRY(val.get(i)); if (!is_first) res = TRY(res.concat(" ")); @@ -258,7 +259,8 @@ Result Writer::write_dict(const Dict& val) { String res = TRY(String::create("{")); bool is_first = true; - for (uint64_t i = 0; i < val.size(); i++) { + auto size = TRY(val.size()); + for (uint64_t i = 0; i < size; i++) { Value k = TRY(Value::create(val._value->data[i * 2].get())); Value v = TRY(Value::create(val._value->data[i * 2 + 1].get()));