Move SFallScriptValue into ProgramValue
This commit is contained in:
parent
89ba7fdcb3
commit
b3e838e5b3
|
@ -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"
|
||||||
)
|
)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue