diff --git a/src/interpreter.cc b/src/interpreter.cc index 3068002..0a5aa54 100644 --- a/src/interpreter.cc +++ b/src/interpreter.cc @@ -3331,44 +3331,4 @@ int ProgramValue::asInt() const } } -bool ProgramValue::operator<(ProgramValue const& other) const -{ - if (opcode != other.opcode) { - return opcode < other.opcode; - } - - switch (opcode) { - case VALUE_TYPE_INT: - case VALUE_TYPE_STRING: - case VALUE_TYPE_DYNAMIC_STRING: - return integerValue < other.integerValue; - case VALUE_TYPE_PTR: - return pointerValue < other.pointerValue; - 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_INT: - case VALUE_TYPE_STRING: - case VALUE_TYPE_DYNAMIC_STRING: - return integerValue == other.integerValue; - case VALUE_TYPE_PTR: - return pointerValue == other.pointerValue; - 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 225fb5e..835e2fd 100644 --- a/src/interpreter.h +++ b/src/interpreter.h @@ -161,9 +161,6 @@ public: 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 f7357a5..bc93d8a 100644 --- a/src/sfall_arrays.cc +++ b/src/sfall_arrays.cc @@ -24,6 +24,7 @@ static ArrayId stackArrayId = 0; #define ARRAY_ACTION_REVERSE (-4) #define ARRAY_ACTION_SHUFFLE (-5) +// TODO: Move me into separate file "sfall_arrays_utils" template static void ListSort(std::vector& arr, int type, Compare cmp) { @@ -45,25 +46,126 @@ static void ListSort(std::vector& arr, int type, Compare cmp) } } +enum class ArrayElementType { + INT, + FLOAT, + STRING, + POINTER +}; + +class ArrayElement { +private: + ArrayElementType type; + union { + int integerValue; + float floatValue; + unsigned char* stringValue; + void* pointerValue; + }; + +public: + ArrayElement() { + // todo + }; + + // TODO: Remove all other constructors + + ArrayElement(ProgramValue programValue, Program* program) + { + // todo + } + ProgramValue toValue(Program* program) const + { + // todo + return ProgramValue(0); + } + + bool operator<(ArrayElement const& other) const + { + // todo + return false; + } + bool operator==(ArrayElement const& other) const + { + // todo + /* + if (!a.isString()) { + return a == b; + }; + if (!b.isString()) { + return false; + }; + auto str1 = programGetString(program, a.opcode, a.integerValue); + auto str2 = programGetString(program, a.opcode, a.integerValue); + if (!str1 || !str2) { + return false; + }; + return strcmp(str1, str2) == 0; + */ + return false; + } +}; + class SFallArray { protected: uint32_t mFlags; public: virtual int size() = 0; - virtual ProgramValue GetArrayKey(int index) = 0; - virtual ProgramValue GetArray(const ProgramValue& key) = 0; - virtual void SetArray(const ProgramValue& key, const ProgramValue& val, bool allowUnset) = 0; + virtual ProgramValue GetArrayKey(int index, Program* program) = 0; + virtual ProgramValue GetArray(const ProgramValue& key, Program* program) = 0; + virtual void SetArray(const ProgramValue& key, const ProgramValue& val, bool allowUnset, Program* program) = 0; virtual void ResizeArray(int newLen) = 0; - virtual ProgramValue ScanArray(const ProgramValue& value, ValueCompareStrings& cmp) = 0; + virtual ProgramValue ScanArray(const ProgramValue& value, Program* program) = 0; virtual ~SFallArray() = default; }; +/* +bool ProgramValue::operator<(ProgramValue const& other) const +{ + if (opcode != other.opcode) { + return opcode < other.opcode; + } + + switch (opcode) { + case VALUE_TYPE_INT: + case VALUE_TYPE_STRING: + case VALUE_TYPE_DYNAMIC_STRING: + return integerValue < other.integerValue; + case VALUE_TYPE_PTR: + return pointerValue < other.pointerValue; + 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_INT: + case VALUE_TYPE_STRING: + case VALUE_TYPE_DYNAMIC_STRING: + return integerValue == other.integerValue; + case VALUE_TYPE_PTR: + return pointerValue == other.pointerValue; + case VALUE_TYPE_FLOAT: + return floatValue == other.floatValue; + default: + throw(std::exception()); + } +} +*/ + class SFallArrayList : public SFallArray { private: - // TODO: SFall copies strings - std::vector values; + std::vector values; public: SFallArrayList() = delete; @@ -79,7 +181,7 @@ public: return values.size(); } - ProgramValue GetArrayKey(int index) + ProgramValue GetArrayKey(int index, Program* program) { if (index < -1 || index > size()) { return ProgramValue(0); @@ -90,21 +192,21 @@ public: return ProgramValue(index); } - ProgramValue GetArray(const ProgramValue& key) + ProgramValue GetArray(const ProgramValue& key, Program* program) { auto element_index = key.asInt(); if (element_index < 0 || element_index >= size()) { return ProgramValue(0); }; - return values[element_index]; + return values[element_index].toValue(program); } - void SetArray(const ProgramValue& key, const ProgramValue& val, bool allowUnset) + void SetArray(const ProgramValue& key, const ProgramValue& val, bool allowUnset, Program* program) { if (key.isInt()) { auto index = key.asInt(); if (index >= 0 && index < size()) { - values[index] = key; + values[index] = ArrayElement { key, program }; } } } @@ -119,21 +221,22 @@ 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()); } } - ProgramValue ScanArray(const ProgramValue& value, ValueCompareStrings& cmp) + ProgramValue ScanArray(const ProgramValue& value, Program* program) { + auto arrValue = ArrayElement { value, program }; for (size_t i = 0; i < size(); i++) { - if (cmp(value, values[i])) { + if (arrValue == values[i]) { return ProgramValue(i); } } @@ -144,8 +247,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); @@ -162,7 +265,7 @@ public: return keys.size(); } - ProgramValue GetArrayKey(int index) + ProgramValue GetArrayKey(int index, Program* program) { if (index < -1 || index > size()) { return ProgramValue(0); @@ -171,22 +274,24 @@ public: return ProgramValue(1); }; - return keys[index]; + return keys[index].toValue(program); } - ProgramValue GetArray(const ProgramValue& key) + ProgramValue GetArray(const ProgramValue& key, Program* program) { - auto iter = map.find(key); + auto iter = map.find(ArrayElement { key, program }); if (iter == map.end()) { return ProgramValue(0); }; - return iter->second; + return iter->second.toValue(program); } - void SetArray(const ProgramValue& key, const ProgramValue& val, bool allowUnset) + void SetArray(const ProgramValue& key, const ProgramValue& val, bool allowUnset, Program* program) { - auto iter = map.find(key); + auto keyEl = ArrayElement { key, program }; + + auto iter = map.find(keyEl); bool lookupMap = (mFlags & SFALL_ARRAYFLAG_CONSTVAL) != 0; @@ -199,10 +304,10 @@ 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) { + if (keyCandidate == keyEl) { // skip this key } else { newKeys.push_back(keyCandidate); @@ -215,8 +320,8 @@ public: // size check if (size() >= ARRAY_MAX_SIZE) return; - keys.push_back(key); - map[key] = val; + keys.push_back(keyEl); + map[keyEl] = ArrayElement { val, program }; } } } @@ -228,7 +333,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++) { @@ -245,11 +350,12 @@ public: } }; - ProgramValue ScanArray(const ProgramValue& value, ValueCompareStrings& cmp) + ProgramValue ScanArray(const ProgramValue& value, Program* program) { - for (const auto &pair : map) { - if (cmp(pair.second, value)) { - return pair.first; + auto valueEl = ArrayElement { value, program }; + for (const auto& pair : map) { + if (valueEl == pair.second) { + return pair.first.toValue(program); } } return ProgramValue(-1); @@ -265,11 +371,11 @@ void SFallArrayAssoc::MapSort(int type) } if (sortByValue) { - ListSort(keys, type, [this](const ProgramValue& a, const ProgramValue& b) -> bool { + ListSort(keys, type, [this](const ArrayElement& a, const ArrayElement& b) -> bool { return this->map[a] < this->map[b]; }); } else { - ListSort(keys, type, std::less()); + ListSort(keys, type, std::less()); } } @@ -316,13 +422,13 @@ SFallArray* get_array_by_id(ArrayId array_id) } } -ProgramValue GetArrayKey(ArrayId array_id, int index) +ProgramValue GetArrayKey(ArrayId array_id, int index, Program* program) { auto arr = get_array_by_id(array_id); if (!arr) { return ProgramValue(0); }; - return arr->GetArrayKey(index); + return arr->GetArrayKey(index, program); } int LenArray(ArrayId array_id) @@ -335,7 +441,7 @@ int LenArray(ArrayId array_id) return arr->size(); } -ProgramValue GetArray(ArrayId array_id, const ProgramValue& key) +ProgramValue GetArray(ArrayId array_id, const ProgramValue& key, Program* program) { auto arr = get_array_by_id(array_id); @@ -343,17 +449,17 @@ ProgramValue GetArray(ArrayId array_id, const ProgramValue& key) return ProgramValue(0); }; - return arr->GetArray(key); + return arr->GetArray(key, program); } -void SetArray(ArrayId array_id, const ProgramValue& key, const ProgramValue& val, bool allowUnset) +void SetArray(ArrayId array_id, const ProgramValue& key, const ProgramValue& val, bool allowUnset, Program* program) { auto arr = get_array_by_id(array_id); if (!arr) { return; } - arr->SetArray(key, val, allowUnset); + arr->SetArray(key, val, allowUnset, program); } void FreeArray(ArrayId array_id) @@ -392,7 +498,7 @@ void ResizeArray(ArrayId array_id, int newLen) arr->ResizeArray(newLen); } -int StackArray(const ProgramValue& key, const ProgramValue& val) +int StackArray(const ProgramValue& key, const ProgramValue& val, Program* program) { if (stackArrayId == 0) { return 0; @@ -407,18 +513,18 @@ int StackArray(const ProgramValue& key, const ProgramValue& val) if (size >= ARRAY_MAX_SIZE) return 0; if (key.asInt() >= size) arr->ResizeArray(size + 1); - SetArray(stackArrayId, key, val, false); + SetArray(stackArrayId, key, val, false, program); return 0; } -ProgramValue ScanArray(ArrayId array_id, const ProgramValue& val, ValueCompareStrings& cmp) +ProgramValue ScanArray(ArrayId array_id, const ProgramValue& val, Program* program) { auto arr = get_array_by_id(array_id); if (!arr) { return ProgramValue(-1); }; - return arr->ScanArray(val, cmp); + return arr->ScanArray(val, program); } } \ No newline at end of file diff --git a/src/sfall_arrays.h b/src/sfall_arrays.h index 818b9f2..7313434 100644 --- a/src/sfall_arrays.h +++ b/src/sfall_arrays.h @@ -3,7 +3,6 @@ #include "interpreter.h" #include "object.h" -#include #include namespace fallout { @@ -14,21 +13,19 @@ namespace fallout { using ArrayId = unsigned int; -using ValueCompareStrings = const std::function; - ArrayId CreateArray(int len, uint32_t flags); ArrayId CreateTempArray(int len, uint32_t flags); -ProgramValue GetArrayKey(ArrayId array_id, int index); +ProgramValue GetArrayKey(ArrayId array_id, int index, Program* program); int LenArray(ArrayId array_id); -ProgramValue GetArray(ArrayId array_id, const ProgramValue& key); -void SetArray(ArrayId array_id, const ProgramValue& key, const ProgramValue& val, bool allowUnset); +ProgramValue GetArray(ArrayId array_id, const ProgramValue& key, Program* program); +void SetArray(ArrayId array_id, const ProgramValue& key, const ProgramValue& val, bool allowUnset, Program* program); void FreeArray(ArrayId array_id); void FixArray(ArrayId id); void ResizeArray(ArrayId array_id, int newLen); void DeleteAllTempArrays(); void sfallArraysReset(); -int StackArray(const ProgramValue& key, const ProgramValue& val); -ProgramValue ScanArray(ArrayId array_id, const ProgramValue& val, ValueCompareStrings& cmp); +int StackArray(const ProgramValue& key, const ProgramValue& val, Program* program); +ProgramValue ScanArray(ArrayId array_id, const ProgramValue& val, Program* program); } #endif /* SFALL_ARRAYS */ \ No newline at end of file diff --git a/src/sfall_opcodes.cc b/src/sfall_opcodes.cc index 97d8d6e..80eb996 100644 --- a/src/sfall_opcodes.cc +++ b/src/sfall_opcodes.cc @@ -494,7 +494,7 @@ static void opGetArrayKey(Program* program) { auto index = programStackPopInteger(program); auto arrayId = programStackPopInteger(program); - auto value = GetArrayKey(arrayId, index); + auto value = GetArrayKey(arrayId, index, program); programStackPushValue(program, value); } @@ -530,7 +530,7 @@ static void opSetArray(Program* program) auto key = programStackPopValue(program); auto arrayId = programStackPopInteger(program); - SetArray(arrayId, key, value, true); + SetArray(arrayId, key, value, true, program); } // arrayexpr @@ -538,7 +538,7 @@ static void opStackArray(Program* program) { auto value = programStackPopValue(program); auto key = programStackPopValue(program); - auto returnValue = StackArray(key, value); + auto returnValue = StackArray(key, value, program); programStackPushInteger(program, returnValue); } @@ -548,20 +548,7 @@ static void opScanArray(Program* program) auto value = programStackPopValue(program); auto arrayId = programStackPopInteger(program); - auto returnValue = ScanArray(arrayId, value, [&program](const ProgramValue& a, const ProgramValue& b) -> bool { - if (!a.isString()) { - return a == b; - }; - if (!b.isString()) { - return false; - }; - auto str1 = programGetString(program, a.opcode, a.integerValue); - auto str2 = programGetString(program, a.opcode, a.integerValue); - if (!str1 || !str2) { - return false; - }; - return strcmp(str1, str2) == 0; - }); + auto returnValue = ScanArray(arrayId, value, program); programStackPushValue(program, returnValue); } @@ -572,7 +559,7 @@ static void opGetArray(Program* program) auto arrayId = programStackPopValue(program); if (arrayId.isInt()) { - auto value = GetArray(arrayId.integerValue, key); + auto value = GetArray(arrayId.integerValue, key, program); programStackPushValue(program, value); } else if (arrayId.isString() && key.isInt()) { @@ -621,7 +608,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, ProgramValue { i }, ProgramValue { objects[i] }, false); + SetArray(array_id, ProgramValue { i }, ProgramValue { objects[i] }, false, program); } programStackPushInteger(program, array_id); }