Use inheritance for values

This commit is contained in:
Felipe Martinez 2024-07-07 21:01:23 +00:00
parent 7ac66dc237
commit bf13db05ce
2 changed files with 87 additions and 77 deletions

View file

@ -72,31 +72,31 @@ void ASM::run() {
return; return;
case Push0: case Push0:
push(std::make_shared<Value>((uint32_t) 0)); push(std::make_shared<ValueInteger>(0));
break; break;
case PushU8: case PushU8:
push(std::make_shared<Value>(read_byte(pc))); push(std::make_shared<ValueInteger>(read_byte(pc)));
pc++; pc++;
break; break;
case PushU16: case PushU16:
push(std::make_shared<Value>(read_u16(pc))); push(std::make_shared<ValueInteger>(read_u16(pc)));
pc += 2; pc += 2;
break; break;
case PushU24: case PushU24:
push(std::make_shared<Value>(read_u24(pc))); push(std::make_shared<ValueInteger>(read_u24(pc)));
pc += 3; pc += 3;
break; break;
case PushU32: case PushU32:
push(std::make_shared<Value>(read_u32(pc))); push(std::make_shared<ValueInteger>(read_u32(pc)));
pc += 4; pc += 4;
break; break;
case PushEmptyString: case PushEmptyString:
push(std::make_shared<Value>(new char[1] {0}, 1)); push(std::make_shared<ValueString>(new char[1] {0}, 1));
break; break;
case Duplicate: case Duplicate:
@ -114,7 +114,7 @@ void ASM::run() {
text[i] = read_byte(ptr + 1 + i); text[i] = read_byte(ptr + 1 + i);
} }
push(std::make_shared<Value>(text, length + 1)); push(std::make_shared<ValueString>(text, length + 1));
break; break;
} }
@ -133,7 +133,7 @@ void ASM::run() {
case Call: { case Call: {
uint32_t next = pc; uint32_t next = pc;
pc = pop_uint32(); pc = pop_uint32();
push(std::make_shared<Value>(next)); push(std::make_shared<ValueInteger>(next));
break; break;
} }
@ -151,23 +151,23 @@ void ASM::run() {
break; break;
case SetLabelText: { case SetLabelText: {
auto str = pop(String); auto str = pop<ValueString>(String);
auto obj = pop(LvglObject); auto obj = pop<ValueLvglObject>(LvglObject);
lv_label_set_text(obj->data.lvobj, str->data.s); lv_label_set_text(obj->obj, str->str);
break; break;
} }
case CreateLabel: case CreateLabel:
push(std::make_shared<Value>(lv_label_create(lv_scr_act(), NULL))); push(std::make_shared<ValueLvglObject>(lv_label_create(lv_scr_act(), NULL)));
break; break;
case SetObjectAlign: { case SetObjectAlign: {
int16_t y = pop_uint32(); int16_t y = pop_uint32();
int16_t x = pop_uint32(); int16_t x = pop_uint32();
uint8_t align = pop_uint32(); uint8_t align = pop_uint32();
auto obj = pop(LvglObject); auto obj = pop<ValueLvglObject>(LvglObject);
lv_obj_align(obj->data.lvobj, lv_scr_act(), align, x, y); lv_obj_align(obj->obj, lv_scr_act(), align, x, y);
break; break;
} }
@ -177,15 +177,15 @@ void ASM::run() {
uint32_t value = pop_uint32(); uint32_t value = pop_uint32();
uint32_t prop = pop_uint32(); uint32_t prop = pop_uint32();
uint32_t part = pop_uint32(); uint32_t part = pop_uint32();
auto obj = pop(LvglObject); auto obj = pop<ValueLvglObject>(LvglObject);
switch (opcode) { switch (opcode) {
case SetStyleLocalInt: case SetStyleLocalInt:
_lv_obj_set_style_local_int(obj->data.lvobj, part, prop, value); _lv_obj_set_style_local_int(obj->obj, part, prop, value);
break; break;
case SetStyleLocalColor: case SetStyleLocalColor:
_lv_obj_set_style_local_color(obj->data.lvobj, part, prop, lv_color_hex(value)); _lv_obj_set_style_local_color(obj->obj, part, prop, lv_color_hex(value));
break; break;
case SetStyleLocalFont: { case SetStyleLocalFont: {
@ -202,7 +202,7 @@ void ASM::run() {
} }
if (font) if (font)
_lv_obj_set_style_local_ptr(obj->data.lvobj, part, prop, font); _lv_obj_set_style_local_ptr(obj->obj, part, prop, font);
break; break;
} }
@ -214,33 +214,33 @@ void ASM::run() {
} }
case Add: { case Add: {
push(std::make_shared<Value>(pop_uint32() + pop_uint32())); push(std::make_shared<ValueInteger>(pop_uint32() + pop_uint32()));
break; break;
} }
case Subtract: case Subtract:
push(std::make_shared<Value>(pop_uint32() - pop_uint32())); push(std::make_shared<ValueInteger>(pop_uint32() - pop_uint32()));
break; break;
case Multiply: case Multiply:
push(std::make_shared<Value>(pop_uint32() * pop_uint32())); push(std::make_shared<ValueInteger>(pop_uint32() * pop_uint32()));
break; break;
case Divide: case Divide:
push(std::make_shared<Value>(pop_uint32() / pop_uint32())); push(std::make_shared<ValueInteger>(pop_uint32() / pop_uint32()));
break; break;
case GrowString: { case GrowString: {
auto len = pop(Integer); auto len = pop_uint32();
auto str = pop(String); auto str = pop<ValueString>(String);
size_t new_cap = len->data.i + str->data.cap; size_t new_cap = len + str->capacity;
asm_assert(new_cap >= str->data.cap); asm_assert(new_cap >= str->capacity);
char* new_str = new char[new_cap]; char* new_str = new char[new_cap];
memcpy(new_str, str->data.s, str->data.cap); memcpy(new_str, str->str, str->capacity);
push(std::make_shared<Value>(new_str, new_cap)); push(std::make_shared<ValueString>(new_str, new_cap));
break; break;
} }
@ -248,29 +248,37 @@ void ASM::run() {
auto b = pop(); auto b = pop();
auto a = pop(); auto a = pop();
if (a->type == String && b->type == String) { if (a->type() == String && b->type() == String) {
int len_a = strlen(a->data.s); auto aString = static_cast<ValueString*>(a.get());
int len_b = strlen(b->data.s); auto bString = static_cast<ValueString*>(b.get());
int len_a = strlen(aString->str);
int len_b = strlen(bString->str);
size_t new_len = len_a + len_b + 1; size_t new_len = len_a + len_b + 1;
if (a->data.cap >= new_len) { if (aString->capacity >= new_len) {
strcat(a->data.s, b->data.s); strcat(aString->str, bString->str);
push(a); push(a);
} else { } else {
char* s = new char[new_len + 1]; char* s = new char[new_len + 1];
strcpy(s, a->data.s); strcpy(s, aString->str);
strcat(s, b->data.s); strcat(s, bString->str);
push(std::make_shared<Value>(s, new_len + 1)); push(std::make_shared<ValueString>(s, new_len + 1));
} }
} else if (a->type == String && b->type == Integer) { } else if (a->type() == String && b->type() == Integer) {
size_t cap = strlen(a->data.s) + 12 + 1; auto aString = static_cast<ValueString*>(a.get());
char* s = new char[cap]; auto bInt = static_cast<ValueInteger*>(b.get());
snprintf(s, cap, "%s%lu", a->data.s, b->data.i);
push(std::make_shared<Value>(s, cap)); if (bInt) {
size_t cap = strlen(aString->str) + 12 + 1;
char* s = new char[cap];
snprintf(s, cap, "%s%lu", aString->str, bInt->i);
push(std::make_shared<ValueString>(s, cap));
}
} else { } else {
asm_assert(false); asm_assert(false);
} }

View file

@ -25,51 +25,50 @@ namespace Pinetime {
enum DataType : uint8_t { Integer, String, LvglObject }; enum DataType : uint8_t { Integer, String, LvglObject };
// TODO: Use fancy C++ type stuff
struct Value { struct Value {
const DataType type; virtual DataType type() = 0;
union {
uint32_t i;
lv_obj_t* lvobj;
struct {
char* s;
uint16_t cap;
}; };
} data;
Value() : type(Integer), data {0} { struct ValueInteger : public Value {
uint32_t i;
ValueInteger(uint32_t i) : i(i) {
} }
Value(DataType t) : type(t), data {0} { DataType type() override {
return Integer;
}
};
struct ValueString : public Value {
char* str;
uint16_t capacity;
ValueString(char* str, uint16_t cap) : str(str), capacity(cap) {
} }
Value(uint32_t i) : type(Integer) { ~ValueString() {
data.i = i; delete[] str;
} }
Value(lv_obj_t* obj) : type(LvglObject) { DataType type() override {
data.lvobj = obj; return String;
}
};
struct ValueLvglObject : public Value {
lv_obj_t* obj;
ValueLvglObject(lv_obj_t* obj) : obj(obj) {
} }
Value(char* s, uint16_t cap) : type(String) { ~ValueLvglObject() {
data.s = s; lv_obj_del(obj);
data.cap = cap;
} }
~Value() { DataType type() override {
switch (type) { return LvglObject;
case String:
delete[] data.s;
break;
case LvglObject:
lv_obj_del(data.lvobj);
break;
default:
break;
}
} }
}; };
@ -140,15 +139,18 @@ namespace Pinetime {
return v; return v;
} }
std::shared_ptr<Value> pop(DataType type) { template <typename T>
std::shared_ptr<T> pop(DataType type)
requires(std::is_base_of_v<Value, T>)
{
auto v = pop(); auto v = pop();
asm_assert(v->type == type); asm_assert(v->type() == type);
return v; return std::static_pointer_cast<T>(v);
} }
uint32_t pop_uint32() { uint32_t pop_uint32() {
return pop(Integer)->data.i; return pop<ValueInteger>(Integer)->i;
} }
void push(std::shared_ptr<Value> v) { void push(std::shared_ptr<Value> v) {