Move SFallScriptValue into ProgramValue

This commit is contained in:
Vasilii Rogin 2023-04-24 16:02:23 +03:00
parent 89ba7fdcb3
commit b3e838e5b3
6 changed files with 126 additions and 47 deletions

View File

@ -271,8 +271,6 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/sfall_lists.h" "src/sfall_lists.h"
"src/sfall_opcodes.cc" "src/sfall_opcodes.cc"
"src/sfall_opcodes.h" "src/sfall_opcodes.h"
"src/sfall_script_value.cc"
"src/sfall_script_value.h"
"src/sfall_arrays.cc" "src/sfall_arrays.cc"
"src/sfall_arrays.h" "src/sfall_arrays.h"
) )

View File

@ -3252,7 +3252,7 @@ void* programReturnStackPopPointer(Program* program)
return programValue.pointerValue; return programValue.pointerValue;
} }
bool ProgramValue::isEmpty() bool ProgramValue::isEmpty() const
{ {
switch (opcode) { switch (opcode) {
case VALUE_TYPE_INT: case VALUE_TYPE_INT:
@ -3269,19 +3269,19 @@ bool ProgramValue::isEmpty()
} }
// Matches Sfall implementation. // Matches Sfall implementation.
bool ProgramValue::isInt() bool ProgramValue::isInt() const
{ {
return opcode == VALUE_TYPE_INT; return opcode == VALUE_TYPE_INT;
} }
// Matches Sfall implementation. // Matches Sfall implementation.
bool ProgramValue::isFloat() bool ProgramValue::isFloat() const
{ {
return opcode == VALUE_TYPE_FLOAT; return opcode == VALUE_TYPE_FLOAT;
} }
// Matches Sfall implementation. // Matches Sfall implementation.
float ProgramValue::asFloat() float ProgramValue::asFloat() const
{ {
switch (opcode) { switch (opcode) {
case VALUE_TYPE_INT: 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<int>(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 } // namespace fallout

View File

@ -1,6 +1,7 @@
#ifndef INTERPRETER_H #ifndef INTERPRETER_H
#define INTERPRETER_H #define INTERPRETER_H
#include "object.h"
#include <setjmp.h> #include <setjmp.h>
#include <vector> #include <vector>
@ -140,7 +141,12 @@ typedef struct Procedure {
int field_14; int field_14;
} Procedure; } Procedure;
typedef struct ProgramValue { class ProgramValue {
public:
ProgramValue();
ProgramValue(int value);
ProgramValue(Object* value);
opcode_t opcode; opcode_t opcode;
union { union {
int integerValue; int integerValue;
@ -148,11 +154,16 @@ typedef struct ProgramValue {
void* pointerValue; void* pointerValue;
}; };
bool isEmpty(); bool isEmpty() const;
bool isInt(); bool isInt() const;
bool isFloat(); bool isFloat() const;
float asFloat(); float asFloat() const;
} ProgramValue; bool isPointer() const;
int asInt() const;
bool operator<(ProgramValue const& other) const;
bool operator==(ProgramValue const& other) const;
};
typedef std::vector<ProgramValue> ProgramStack; typedef std::vector<ProgramValue> ProgramStack;

View File

@ -1,6 +1,5 @@
#include "sfall_arrays.h" #include "sfall_arrays.h"
#include "interpreter.h" #include "interpreter.h"
#include "sfall_script_value.h"
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
@ -52,15 +51,15 @@ protected:
public: public:
virtual int size() = 0; virtual int size() = 0;
virtual ProgramValue GetArrayKey(int index) = 0; virtual ProgramValue GetArrayKey(int index) = 0;
virtual ProgramValue GetArray(const SFallScriptValue& key) = 0; virtual ProgramValue GetArray(const ProgramValue& key) = 0;
virtual void SetArray(const SFallScriptValue& key, const SFallScriptValue& val, bool allowUnset) = 0; virtual void SetArray(const ProgramValue& key, const ProgramValue& val, bool allowUnset) = 0;
virtual void ResizeArray(int newLen) = 0; virtual void ResizeArray(int newLen) = 0;
}; };
class SFallArrayList : public SFallArray { class SFallArrayList : public SFallArray {
private: private:
// TODO: SFall copies strings // TODO: SFall copies strings
std::vector<SFallScriptValue> values; std::vector<ProgramValue> values;
public: public:
SFallArrayList() = delete; SFallArrayList() = delete;
@ -79,24 +78,24 @@ public:
ProgramValue GetArrayKey(int index) ProgramValue GetArrayKey(int index)
{ {
if (index < -1 || index > size()) { if (index < -1 || index > size()) {
return SFallScriptValue(0); return ProgramValue(0);
}; };
if (index == -1) { // special index to indicate if array is associative 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(); auto element_index = key.asInt();
if (element_index < 0 || element_index >= size()) { if (element_index < 0 || element_index >= size()) {
return SFallScriptValue(0); return ProgramValue(0);
}; };
return values[element_index]; 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()) { if (key.isInt()) {
auto index = key.asInt(); auto index = key.asInt();
@ -116,14 +115,14 @@ public:
} else if (newLen > 0) { } else if (newLen > 0) {
if (newLen > ARRAY_MAX_SIZE) newLen = ARRAY_MAX_SIZE; // safety if (newLen > ARRAY_MAX_SIZE) newLen = ARRAY_MAX_SIZE; // safety
std::vector<SFallScriptValue> newValues; std::vector<ProgramValue> newValues;
newValues.reserve(newLen); newValues.reserve(newLen);
for (size_t i = 0; i < std::min(newLen, size()); i++) { for (size_t i = 0; i < std::min(newLen, size()); i++) {
newValues.push_back(values[i]); newValues.push_back(values[i]);
}; };
values = newValues; values = newValues;
} else if (newLen >= ARRAY_ACTION_SHUFFLE) { } else if (newLen >= ARRAY_ACTION_SHUFFLE) {
ListSort(values, newLen, std::less<SFallScriptValue>()); ListSort(values, newLen, std::less<ProgramValue>());
} }
} }
}; };
@ -131,8 +130,8 @@ public:
class SFallArrayAssoc : public SFallArray { class SFallArrayAssoc : public SFallArray {
private: private:
// TODO: SFall copies strings // TODO: SFall copies strings
std::vector<SFallScriptValue> keys; std::vector<ProgramValue> keys;
std::map<SFallScriptValue, SFallScriptValue> map; std::map<ProgramValue, ProgramValue> map;
void MapSort(int newLen); void MapSort(int newLen);
@ -152,26 +151,26 @@ public:
ProgramValue GetArrayKey(int index) ProgramValue GetArrayKey(int index)
{ {
if (index < -1 || index > size()) { if (index < -1 || index > size()) {
return SFallScriptValue(0); return ProgramValue(0);
}; };
if (index == -1) { // special index to indicate if array is associative if (index == -1) { // special index to indicate if array is associative
return SFallScriptValue(1); return ProgramValue(1);
}; };
return keys[index]; return keys[index];
} }
ProgramValue GetArray(const SFallScriptValue& key) ProgramValue GetArray(const ProgramValue& key)
{ {
auto iter = map.find(key); auto iter = map.find(key);
if (iter == map.end()) { if (iter == map.end()) {
return SFallScriptValue(0); return ProgramValue(0);
}; };
return iter->second; 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); 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 // 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()) { if (iter != map.end()) {
map.erase(iter); map.erase(iter);
std::vector<SFallScriptValue> newKeys; std::vector<ProgramValue> newKeys;
newKeys.reserve(keys.size() - 1); newKeys.reserve(keys.size() - 1);
for (auto keyCandidate : keys) { for (auto keyCandidate : keys) {
if (keyCandidate == key) { if (keyCandidate == key) {
@ -215,7 +214,7 @@ public:
// only allow to reduce number of elements (adding range of elements is meaningless for maps) // only allow to reduce number of elements (adding range of elements is meaningless for maps)
if (newLen >= 0 && newLen < size()) { if (newLen >= 0 && newLen < size()) {
std::vector<SFallScriptValue> newKeys; std::vector<ProgramValue> newKeys;
newKeys.reserve(newLen); newKeys.reserve(newLen);
for (size_t i = 0; i < newLen; i++) { for (size_t i = 0; i < newLen; i++) {
@ -242,11 +241,11 @@ void SFallArrayAssoc::MapSort(int type)
} }
if (sortByValue) { 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]; return this->map[a] < this->map[b];
}); });
} else { } else {
ListSort(keys, type, std::less<SFallScriptValue>()); ListSort(keys, type, std::less<ProgramValue>());
} }
} }
@ -290,7 +289,7 @@ ProgramValue GetArrayKey(ArrayId array_id, int index)
{ {
auto& arr = arrays[array_id]; auto& arr = arrays[array_id];
if (!arr) { if (!arr) {
return SFallScriptValue(0); return ProgramValue(0);
}; };
return arr->GetArrayKey(index); return arr->GetArrayKey(index);
} }
@ -305,18 +304,18 @@ int LenArray(ArrayId array_id)
return arr->size(); return arr->size();
} }
ProgramValue GetArray(ArrayId array_id, const SFallScriptValue& key) ProgramValue GetArray(ArrayId array_id, const ProgramValue& key)
{ {
auto& arr = arrays[array_id]; auto& arr = arrays[array_id];
if (!arr) { if (!arr) {
return SFallScriptValue(0); return ProgramValue(0);
}; };
return arr->GetArray(key); 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]; auto& arr = arrays[array_id];
if (!arr) { if (!arr) {

View File

@ -3,7 +3,6 @@
#include "interpreter.h" #include "interpreter.h"
#include "object.h" #include "object.h"
#include "sfall_script_value.h"
#include <cstdint> #include <cstdint>
namespace fallout { namespace fallout {
@ -18,8 +17,8 @@ ArrayId CreateArray(int len, uint32_t flags);
ArrayId CreateTempArray(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);
int LenArray(ArrayId array_id); int LenArray(ArrayId array_id);
ProgramValue GetArray(ArrayId array_id, const SFallScriptValue& key); ProgramValue GetArray(ArrayId array_id, const ProgramValue& 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);
void FreeArray(ArrayId array_id); void FreeArray(ArrayId array_id);
void FixArray(ArrayId id); void FixArray(ArrayId id);
void ResizeArray(ArrayId array_id, int newLen); void ResizeArray(ArrayId array_id, int newLen);

View File

@ -18,7 +18,6 @@
#include "sfall_arrays.h" #include "sfall_arrays.h"
#include "sfall_global_vars.h" #include "sfall_global_vars.h"
#include "sfall_lists.h" #include "sfall_lists.h"
#include "sfall_script_value.h"
#include "stat.h" #include "stat.h"
#include "svga.h" #include "svga.h"
#include "tile.h" #include "tile.h"
@ -530,7 +529,7 @@ static void opSetArray(Program* program)
auto key = programStackPopValue(program); auto key = programStackPopValue(program);
auto arrayId = programStackPopInteger(program); auto arrayId = programStackPopInteger(program);
SetArray(arrayId, SFallScriptValue { key }, SFallScriptValue { value }, true); SetArray(arrayId, key, value, true);
} }
// get_array // get_array
@ -540,9 +539,9 @@ static void opGetArray(Program* program)
auto key = programStackPopValue(program); auto key = programStackPopValue(program);
auto arrayId = SFallScriptValue { programStackPopValue(program) }; auto arrayId = programStackPopValue(program);
if (arrayId.isInt()) { if (arrayId.isInt()) {
auto value = GetArray(arrayId.integerValue, SFallScriptValue { key }); auto value = GetArray(arrayId.integerValue, key);
programStackPushValue(program, value); programStackPushValue(program, value);
} else { } else {
} }
@ -577,7 +576,7 @@ static void opPartyMemberList(Program* program)
auto objects = get_all_party_members_objects(includeHidden); auto objects = get_all_party_members_objects(includeHidden);
auto array_id = CreateTempArray(objects.size(), SFALL_ARRAYFLAG_RESERVED); auto array_id = CreateTempArray(objects.size(), SFALL_ARRAYFLAG_RESERVED);
for (int i = 0; i < LenArray(array_id); i++) { 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); programStackPushInteger(program, array_id);
} }