Extract a common interface for Value::size() to get object sizes

This commit is contained in:
Konstantin Nazarov 2024-09-10 02:12:49 +01:00
parent 3c30440d65
commit 021f645fbf
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
6 changed files with 98 additions and 73 deletions

View file

@ -51,7 +51,7 @@ Result<Value> Value::create(PodObject* obj) {
}
Result<Symbol> 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<PodSymbol>(res_size * sizeof(char32_t)));
@ -63,7 +63,7 @@ Result<Symbol> Symbol::create(String& rhs) {
}
Result<String> 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<PodString>(res_size * sizeof(char32_t)));
@ -76,7 +76,8 @@ Result<String> String::create(const Symbol& rhs) {
Result<ByteArray> 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<PodByteArray>(size * sizeof(char)));
@ -84,7 +85,7 @@ Result<ByteArray> 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> Pair::create(const Value& first, const Value& rest) {
Result<Pair> 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<void> debug_print(const char* val) {
Result<void> 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<Value> Array::get(const Value& key) const {
}
Result<Array> 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<PodArray>(res_size * sizeof(OffPtr<PodObject>)));
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> 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> Dict::create(const Array& arr) {
Result<Value> 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<Value> Dict::get(const Value& key) const {
Result<Dict> 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> 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> Dict::insert(const Value& key, const Value& value) {
Result<uint64_t> 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<short> Float::cmp(const Int64& rhs) const {
}
Result<short> 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<short> Dict::cmp(const Dict& rhs) const {
}
Result<short> 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<Value> Object::third() const { return ERROR(TypeMismatch); }
Result<Value> Object::rest() const { return ERROR(TypeMismatch); }
Result<uint64_t> Object::size() const { return ERROR(TypeMismatch); }
Result<bool> syntax_is_list(const Value& value) {
if (!value.is<Syntax>()) return value.is<Pair>();

View file

@ -129,6 +129,8 @@ class Object {
virtual Result<Value> third() const;
virtual Result<Value> rest() const;
virtual Result<uint64_t> 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<uint64_t> size() const { return _value->size; }
virtual Result<Value> copy_value() const final;
Result<Array> copy() const;
@ -212,17 +214,17 @@ class Array : public Object {
Result<Array> append(const V& value) const;
Result<Array> 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<PodArray>(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<ByteArray> create(const String& str);
uint64_t size() const { return _value->size; }
virtual Result<uint64_t> size() const final { return _value->size; }
virtual Result<Value> copy_value() const final;
Result<ByteArray> copy() const;
@ -305,7 +307,7 @@ class ByteArray : public Object {
Result<ByteArray> 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<PodByteArray>(res_size * sizeof(char)));
@ -317,7 +319,7 @@ class ByteArray : public Object {
}
Result<ByteArray> 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<PodByteArray>(res_size * sizeof(char)));
@ -329,8 +331,8 @@ class ByteArray : public Object {
}
Result<ByteArray> 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<PodByteArray>(res_size * sizeof(char)));
@ -400,27 +402,28 @@ class Dict : public Object {
Result<Dict> insert(const K& key, const V& value);
Result<Dict> 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<PodDict>(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<uint64_t> size() const final { return _value->size; }
private:
Result<uint64_t> find(const Value& key) const;
uint64_t size() const { return _value->size; }
GcRoot<PodDict> _value;
};
@ -441,8 +444,8 @@ class String : public Object {
return -TRY(rhs.cmp(*this));
}
virtual Result<short> 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<uint64_t> size() const final { return _value->size; }
virtual Result<Value> copy_value() const final;
Result<String> copy() const;
@ -499,7 +502,7 @@ class String : public Object {
}
Result<String> 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<PodString>(res_size * sizeof(char32_t)));
@ -514,7 +517,7 @@ class String : public Object {
Result<String> concat(const char* rhs) { return concat(rhs, strlen(rhs)); }
Result<String> 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<PodString>(res_size * sizeof(char32_t)));
@ -527,8 +530,8 @@ class String : public Object {
}
Result<String> 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<PodString>(res_size * sizeof(char32_t)));
@ -570,8 +573,8 @@ class Symbol : public Object {
return -TRY(rhs.cmp(*this));
}
virtual Result<short> 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<short> 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<Value> copy_value() const final;
Result<Symbol> copy() const;
uint64_t size() const { return _value->size; }
virtual Result<uint64_t> size() const final { return _value->size; }
Result<char32_t> operator[](uint64_t idx) const {
if (idx >= _value->size) return ERROR(IndexOutOfRange);

View file

@ -61,7 +61,7 @@ struct Context {
return idx.value().to<Int64>()->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<Expression> 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<Expression> 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<Expression> 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<Expression> 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<Nil>()) {
@ -707,7 +707,8 @@ Result<Expression> 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<Expression> 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<Nil>()) {
int64_t gname = TRY(context.add_const(name));
@ -953,7 +955,7 @@ Result<Expression> Compiler::compile_symbol(Context& context,
if (unwrapped.is<Symbol>()) {
Symbol& sym = *unwrapped.to<Symbol>();
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();

View file

@ -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');

View file

@ -19,8 +19,9 @@ Result<Value> stdlib_unknown(const Array& params) {
Result<void> 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<void> print_string(const String& s) {
}
Result<Value> 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<Value> stdlib_println(const Array& params) {
Result<Value> stdlib_prn(const Array& params) { return ERROR(NotImplemented); }
Result<Value> 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<Bool>()) return ERROR(AssertionFailed);
auto v = param.to<Bool>()->value();
@ -81,7 +84,8 @@ Result<Value> stdlib_array(const Array& params) {
}
Result<Value> 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<Value> stdlib_get(const Array& params) {
Result<Value> 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<StdlibFunctionId> 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) {

View file

@ -121,9 +121,9 @@ Result<String> Writer::write_bytearray(const ByteArray& val) {
Result<String> 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<String> 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<String> 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<String> 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()));