diff --git a/CMakeLists.txt b/CMakeLists.txt index e7a50bb..0ad1252 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -271,8 +271,6 @@ target_sources(${EXECUTABLE_NAME} PUBLIC "src/sfall_lists.h" "src/sfall_opcodes.cc" "src/sfall_opcodes.h" - "src/sfall_script_value.cc" - "src/sfall_script_value.h" "src/sfall_arrays.cc" "src/sfall_arrays.h" ) diff --git a/src/interpreter.cc b/src/interpreter.cc index 23793ac..e7ad993 100644 --- a/src/interpreter.cc +++ b/src/interpreter.cc @@ -3252,7 +3252,7 @@ void* programReturnStackPopPointer(Program* program) return programValue.pointerValue; } -bool ProgramValue::isEmpty() +bool ProgramValue::isEmpty() const { switch (opcode) { case VALUE_TYPE_INT: @@ -3269,19 +3269,19 @@ bool ProgramValue::isEmpty() } // Matches Sfall implementation. -bool ProgramValue::isInt() +bool ProgramValue::isInt() const { return opcode == VALUE_TYPE_INT; } // Matches Sfall implementation. -bool ProgramValue::isFloat() +bool ProgramValue::isFloat() const { return opcode == VALUE_TYPE_FLOAT; } // Matches Sfall implementation. -float ProgramValue::asFloat() +float ProgramValue::asFloat() const { switch (opcode) { case VALUE_TYPE_INT: @@ -3293,4 +3293,77 @@ float ProgramValue::asFloat() } } +ProgramValue::ProgramValue() +{ + opcode = VALUE_TYPE_INT; + integerValue = 0; +} +ProgramValue::ProgramValue(int value) +{ + opcode = VALUE_TYPE_INT; + integerValue = value; +}; +ProgramValue::ProgramValue(Object* value) +{ + opcode = VALUE_TYPE_PTR; + pointerValue = value; +}; + +bool ProgramValue::isPointer() const +{ + return opcode == VALUE_TYPE_PTR; +} + +int ProgramValue::asInt() const +{ + switch (opcode) { + case VALUE_TYPE_INT: + return integerValue; + case VALUE_TYPE_FLOAT: + return static_cast(floatValue); + default: + return 0; + } +} + +bool ProgramValue::operator<(ProgramValue const& other) const +{ + if (opcode != other.opcode) { + return opcode < other.opcode; + } + + switch (opcode) { + case VALUE_TYPE_DYNAMIC_STRING: + case VALUE_TYPE_STRING: + case VALUE_TYPE_PTR: + return pointerValue < other.pointerValue; + case VALUE_TYPE_INT: + return integerValue < other.integerValue; + case VALUE_TYPE_FLOAT: + return floatValue < other.floatValue; + default: + throw(std::exception()); + } +} + +bool ProgramValue::operator==(ProgramValue const& other) const +{ + if (opcode != other.opcode) { + return false; + } + + switch (opcode) { + case VALUE_TYPE_DYNAMIC_STRING: + case VALUE_TYPE_STRING: + case VALUE_TYPE_PTR: + return pointerValue == other.pointerValue; + case VALUE_TYPE_INT: + return integerValue == other.integerValue; + case VALUE_TYPE_FLOAT: + return floatValue == other.floatValue; + default: + throw(std::exception()); + } +} + } // namespace fallout diff --git a/src/interpreter.h b/src/interpreter.h index f84347f..221a24a 100644 --- a/src/interpreter.h +++ b/src/interpreter.h @@ -1,6 +1,7 @@ #ifndef INTERPRETER_H #define INTERPRETER_H +#include "object.h" #include #include @@ -140,7 +141,12 @@ typedef struct Procedure { int field_14; } Procedure; -typedef struct ProgramValue { +class ProgramValue { +public: + ProgramValue(); + ProgramValue(int value); + ProgramValue(Object* value); + opcode_t opcode; union { int integerValue; @@ -148,11 +154,16 @@ typedef struct ProgramValue { void* pointerValue; }; - bool isEmpty(); - bool isInt(); - bool isFloat(); - float asFloat(); -} ProgramValue; + bool isEmpty() const; + bool isInt() const; + bool isFloat() const; + float asFloat() const; + bool isPointer() const; + int asInt() const; + + bool operator<(ProgramValue const& other) const; + bool operator==(ProgramValue const& other) const; +}; typedef std::vector ProgramStack; diff --git a/src/sfall_arrays.cc b/src/sfall_arrays.cc index e6c4771..db5e6b0 100644 --- a/src/sfall_arrays.cc +++ b/src/sfall_arrays.cc @@ -1,6 +1,5 @@ #include "sfall_arrays.h" #include "interpreter.h" -#include "sfall_script_value.h" #include #include @@ -52,15 +51,15 @@ protected: public: virtual int size() = 0; virtual ProgramValue GetArrayKey(int index) = 0; - virtual ProgramValue GetArray(const SFallScriptValue& key) = 0; - virtual void SetArray(const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset) = 0; + virtual ProgramValue GetArray(const ProgramValue& key) = 0; + virtual void SetArray(const ProgramValue& key, const ProgramValue& val, bool allowUnset) = 0; virtual void ResizeArray(int newLen) = 0; }; class SFallArrayList : public SFallArray { private: // TODO: SFall copies strings - std::vector values; + std::vector values; public: SFallArrayList() = delete; @@ -79,24 +78,24 @@ public: ProgramValue GetArrayKey(int index) { if (index < -1 || index > size()) { - return SFallScriptValue(0); + return ProgramValue(0); }; if (index == -1) { // special index to indicate if array is associative - return SFallScriptValue(0); + return ProgramValue(0); }; - return SFallScriptValue(index); + return ProgramValue(index); } - ProgramValue GetArray(const SFallScriptValue& key) + ProgramValue GetArray(const ProgramValue& key) { auto element_index = key.asInt(); if (element_index < 0 || element_index >= size()) { - return SFallScriptValue(0); + return ProgramValue(0); }; return values[element_index]; } - void SetArray(const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset) + void SetArray(const ProgramValue& key, const ProgramValue& val, bool allowUnset) { if (key.isInt()) { auto index = key.asInt(); @@ -116,14 +115,14 @@ public: } else if (newLen > 0) { if (newLen > ARRAY_MAX_SIZE) newLen = ARRAY_MAX_SIZE; // safety - std::vector newValues; + std::vector newValues; newValues.reserve(newLen); for (size_t i = 0; i < std::min(newLen, size()); i++) { newValues.push_back(values[i]); }; values = newValues; } else if (newLen >= ARRAY_ACTION_SHUFFLE) { - ListSort(values, newLen, std::less()); + ListSort(values, newLen, std::less()); } } }; @@ -131,8 +130,8 @@ public: class SFallArrayAssoc : public SFallArray { private: // TODO: SFall copies strings - std::vector keys; - std::map map; + std::vector keys; + std::map map; void MapSort(int newLen); @@ -152,26 +151,26 @@ public: ProgramValue GetArrayKey(int index) { if (index < -1 || index > size()) { - return SFallScriptValue(0); + return ProgramValue(0); }; if (index == -1) { // special index to indicate if array is associative - return SFallScriptValue(1); + return ProgramValue(1); }; return keys[index]; } - ProgramValue GetArray(const SFallScriptValue& key) + ProgramValue GetArray(const ProgramValue& key) { auto iter = map.find(key); if (iter == map.end()) { - return SFallScriptValue(0); + return ProgramValue(0); }; return iter->second; } - void SetArray(const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset) + void SetArray(const ProgramValue& key, const ProgramValue& val, bool allowUnset) { auto iter = map.find(key); @@ -186,7 +185,7 @@ public: // after assigning zero to a key, no need to store it, because "get_array" returns 0 for non-existent keys: try unset if (iter != map.end()) { map.erase(iter); - std::vector newKeys; + std::vector newKeys; newKeys.reserve(keys.size() - 1); for (auto keyCandidate : keys) { if (keyCandidate == key) { @@ -215,7 +214,7 @@ public: // only allow to reduce number of elements (adding range of elements is meaningless for maps) if (newLen >= 0 && newLen < size()) { - std::vector newKeys; + std::vector newKeys; newKeys.reserve(newLen); for (size_t i = 0; i < newLen; i++) { @@ -242,11 +241,11 @@ void SFallArrayAssoc::MapSort(int type) } if (sortByValue) { - ListSort(keys, type, [this](const SFallScriptValue& a, const SFallScriptValue& b) -> bool { + ListSort(keys, type, [this](const ProgramValue& a, const ProgramValue& b) -> bool { return this->map[a] < this->map[b]; }); } else { - ListSort(keys, type, std::less()); + ListSort(keys, type, std::less()); } } @@ -290,7 +289,7 @@ ProgramValue GetArrayKey(ArrayId array_id, int index) { auto& arr = arrays[array_id]; if (!arr) { - return SFallScriptValue(0); + return ProgramValue(0); }; return arr->GetArrayKey(index); } @@ -305,18 +304,18 @@ int LenArray(ArrayId array_id) return arr->size(); } -ProgramValue GetArray(ArrayId array_id, const SFallScriptValue& key) +ProgramValue GetArray(ArrayId array_id, const ProgramValue& key) { auto& arr = arrays[array_id]; if (!arr) { - return SFallScriptValue(0); + return ProgramValue(0); }; return arr->GetArray(key); } -void SetArray(ArrayId array_id, const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset) +void SetArray(ArrayId array_id, const ProgramValue& key, const ProgramValue& val, bool allowUnset) { auto& arr = arrays[array_id]; if (!arr) { diff --git a/src/sfall_arrays.h b/src/sfall_arrays.h index edf5839..3cc59e6 100644 --- a/src/sfall_arrays.h +++ b/src/sfall_arrays.h @@ -3,7 +3,6 @@ #include "interpreter.h" #include "object.h" -#include "sfall_script_value.h" #include namespace fallout { @@ -18,8 +17,8 @@ ArrayId CreateArray(int len, uint32_t flags); ArrayId CreateTempArray(int len, uint32_t flags); ProgramValue GetArrayKey(ArrayId array_id, int index); int LenArray(ArrayId array_id); -ProgramValue GetArray(ArrayId array_id, const SFallScriptValue& key); -void SetArray(ArrayId array_id, const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset); +ProgramValue GetArray(ArrayId array_id, const ProgramValue& key); +void SetArray(ArrayId array_id, const ProgramValue& key, const ProgramValue& val, bool allowUnset); void FreeArray(ArrayId array_id); void FixArray(ArrayId id); void ResizeArray(ArrayId array_id, int newLen); diff --git a/src/sfall_opcodes.cc b/src/sfall_opcodes.cc index 5e7f77e..5ca218e 100644 --- a/src/sfall_opcodes.cc +++ b/src/sfall_opcodes.cc @@ -18,7 +18,6 @@ #include "sfall_arrays.h" #include "sfall_global_vars.h" #include "sfall_lists.h" -#include "sfall_script_value.h" #include "stat.h" #include "svga.h" #include "tile.h" @@ -530,7 +529,7 @@ static void opSetArray(Program* program) auto key = programStackPopValue(program); auto arrayId = programStackPopInteger(program); - SetArray(arrayId, SFallScriptValue { key }, SFallScriptValue { value }, true); + SetArray(arrayId, key, value, true); } // get_array @@ -540,9 +539,9 @@ static void opGetArray(Program* program) auto key = programStackPopValue(program); - auto arrayId = SFallScriptValue { programStackPopValue(program) }; + auto arrayId = programStackPopValue(program); if (arrayId.isInt()) { - auto value = GetArray(arrayId.integerValue, SFallScriptValue { key }); + auto value = GetArray(arrayId.integerValue, key); programStackPushValue(program, value); } else { } @@ -577,7 +576,7 @@ static void opPartyMemberList(Program* program) auto objects = get_all_party_members_objects(includeHidden); auto array_id = CreateTempArray(objects.size(), SFALL_ARRAYFLAG_RESERVED); for (int i = 0; i < LenArray(array_id); i++) { - SetArray(array_id, SFallScriptValue { i }, SFallScriptValue { objects[i] }, false); + SetArray(array_id, ProgramValue { i }, ProgramValue { objects[i] }, false); } programStackPushInteger(program, array_id); }