Skip to content

Commit

Permalink
fix(zscript): handle non-global objects correctly when reloading game
Browse files Browse the repository at this point in the history
  • Loading branch information
connorjclark committed Apr 4, 2024
1 parent 0c65ba4 commit f93172d
Show file tree
Hide file tree
Showing 19 changed files with 310 additions and 147 deletions.
15 changes: 15 additions & 0 deletions src/base/general.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,21 @@ enum controls //Args for 'getInput()'
#define INT_BTN_X INT_BTN_EX1
#define INT_BTN_Y INT_BTN_EX2

// These values must remain stable.
enum class script_object_type
{
none,
bitmap,
dir,
file,
paldata,
rng,
stack,
websocket,
object,
last = object,
};

enum // used for gamedata ITEMS
{
// 0
Expand Down
22 changes: 13 additions & 9 deletions src/base/zc_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define __zc_array_h_

#include "base/zdefs.h"
#include "base/general.h"
#include <sstream>
#include <functional>
//#define _DEBUGZCARRAY
Expand Down Expand Up @@ -142,25 +143,25 @@ class ZCArray
typedef T* pointer;
typedef T type;

ZCArray() : _ptr(NULL), _size(0), _valid(false), _object_type(false)
ZCArray() : _ptr(NULL), _size(0), _valid(false), _object_type(script_object_type::none)
{
for(int32_t i = 0; i < 4; i++)
_dim[i] = 0;
}

ZCArray(size_type _Size) : _ptr(NULL), _valid(false), _object_type(false)
ZCArray(size_type _Size) : _ptr(NULL), _valid(false), _object_type(script_object_type::none)
{
_SetDimensions(0, 0, _Size);
_Alloc(_size);
}

ZCArray(size_type _Y, size_type _X) : _ptr(NULL), _valid(false), _object_type(false)
ZCArray(size_type _Y, size_type _X) : _ptr(NULL), _valid(false), _object_type(script_object_type::none)
{
_SetDimensions(0, _Y, _X);
_Alloc(_size);
}

ZCArray(size_type _Z, size_type _Y, size_type _X) : _ptr(NULL), _valid(false), _object_type(false)
ZCArray(size_type _Z, size_type _Y, size_type _X) : _ptr(NULL), _valid(false), _object_type(script_object_type::none)
{
_SetDimensions(_Z, _Y, _X);
_Alloc(_size);
Expand Down Expand Up @@ -384,14 +385,18 @@ class ZCArray
{
_valid = v;
}
void setObjectType(bool v)
void setObjectType(script_object_type v)
{
_object_type = v;
}
bool ObjectType() const
script_object_type ObjectType() const
{
return _object_type;
}
bool HoldsObjects() const
{
return _object_type != script_object_type::none;
}

size_type Offset(const size_type _Z, const size_type _Y, const size_type _X) const
{
Expand Down Expand Up @@ -494,7 +499,7 @@ class ZCArray
{
Resize(0);
_valid = false;
_object_type = false;
_object_type = script_object_type::none;
}


Expand Down Expand Up @@ -690,8 +695,7 @@ class ZCArray
size_type _size;
size_type _dim[ 4 ];
bool _valid;
bool _object_type;

script_object_type _object_type;
};

typedef ZCArray<int32_t> ZScriptArray;
Expand Down
2 changes: 1 addition & 1 deletion src/gamedata.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ struct gamedata
bool item_messages_played[MAXITEMS]; //Each field is set when an item pickup message plays the first time per session
bounded_map<dword,bounded_vec<byte,int32_t>> screen_d {MAX_MI, {8, 0}}; // script-controlled screen variables
int32_t global_d[MAX_SCRIPT_REGISTERS]; // script-controlled global variables
std::set<uint16_t> global_is_object;
script_object_type global_d_types[MAX_SCRIPT_REGISTERS];
std::vector<ZCArray<int32_t>> globalRAM;

word awpn = 255, bwpn = 255, xwpn = 255, ywpn = 255;
Expand Down
18 changes: 11 additions & 7 deletions src/parser/BuildVisitors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "CompileError.h"
#include "Types.h"
#include "ZScript.h"
#include "parser/ByteCode.h"

using namespace ZScript;
using std::map;
Expand Down Expand Up @@ -1623,7 +1624,7 @@ void BuildOpcodes::buildVariable(ASTDataDecl& host, OpcodeContext& context)
if (auto globalId = manager.getGlobalId())
{
if (is_object)
addOpcode(new OMarkTypeRegister(new GlobalArgument(*globalId), new LiteralArgument(1)));
addOpcode(new OMarkTypeRegister(new GlobalArgument(*globalId), new LiteralArgument((int)writeType->getScriptObjectTypeId())));

if (val)
addOpcode(new OSetImmediate(new GlobalArgument(*globalId), new LiteralArgument(*val)));
Expand Down Expand Up @@ -1685,21 +1686,21 @@ void BuildOpcodes::buildArrayUninit(
}

auto& type = host.resolveType(scope, this);
bool is_object = type.canHoldObject();
int script_object_type_id = (int)type.getScriptObjectTypeId();

// Allocate the array.
if (auto globalId = manager.getGlobalId())
{
addOpcode(new OAllocateGlobalMemImmediate(
new VarArgument(EXP1),
new LiteralArgument(totalSize),
new LiteralArgument(is_object)));
new LiteralArgument(script_object_type_id)));
addOpcode(new OSetRegister(new GlobalArgument(*globalId),
new VarArgument(EXP1)));
}
else
{
addOpcode(new OAllocateMemImmediate(new VarArgument(EXP1), new LiteralArgument(totalSize), new LiteralArgument(is_object)));
addOpcode(new OAllocateMemImmediate(new VarArgument(EXP1), new LiteralArgument(totalSize), new LiteralArgument(script_object_type_id)));
int32_t offset = manager.getStackOffset(false);
addOpcode(new OStore(new VarArgument(EXP1), new LiteralArgument(offset)));
// Register for cleanup.
Expand Down Expand Up @@ -1944,7 +1945,10 @@ void BuildOpcodes::caseExprCall(ASTExprCall& host, void* param)
{
auto& type = member.second->getNode()->resolveType(scope, nullptr);
if (type.canHoldObject())
{
object_indices.push_back(member.second->getIndex());
object_indices.push_back((int)type.getScriptObjectTypeId());
}
}
if (!object_indices.empty())
addOpcode(new OMarkTypeClass(new VectorArgument(object_indices)));
Expand Down Expand Up @@ -3819,23 +3823,23 @@ void BuildOpcodes::arrayLiteralDeclaration(
// SemanticAnalyzer::caseArrayLiteral - see "// Otherwise, default to Untyped -Em"
// For now just grab it here.
auto& type = host.declaration->resolveType(scope, this);
bool is_object = type.canHoldObject();
int script_object_type_id = (int)type.getScriptObjectTypeId();

// Create the array and store its id.
if (auto globalId = manager.getGlobalId())
{
addOpcode(new OAllocateGlobalMemImmediate(
new VarArgument(EXP1),
new LiteralArgument(size * 10000L),
new LiteralArgument(is_object)));
new LiteralArgument(script_object_type_id)));
addOpcode(new OSetRegister(new GlobalArgument(*globalId),
new VarArgument(EXP1)));
}
else
{
addOpcode(new OAllocateMemImmediate(new VarArgument(EXP1),
new LiteralArgument(size * 10000L),
new LiteralArgument(is_object)));
new LiteralArgument(script_object_type_id)));
int32_t offset = manager.getStackOffset(false);
addOpcode(new OStore(new VarArgument(EXP1), new LiteralArgument(offset)));
// Register for cleanup.
Expand Down
3 changes: 3 additions & 0 deletions src/parser/ScriptParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,10 @@ unique_ptr<IntermediateData> ScriptParser::generateOCode(FunctionData& fdata)
{
auto& type = member.second->getNode()->resolveType(scope, nullptr);
if (type.canHoldObject())
{
object_indices.push_back(member.second->getIndex());
object_indices.push_back((int)type.getScriptObjectTypeId());
}
}
if (!object_indices.empty())
addOpcode2(funccode, new OMarkTypeClass(new VectorArgument(object_indices)));
Expand Down
21 changes: 21 additions & 0 deletions src/parser/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <vector>
#include <type_traits>
#include "CompilerUtils.h"
#include "base/general.h"
#include "parser/Scope.h"
#include "parserDefs.h"

namespace ZScript
Expand Down Expand Up @@ -421,6 +423,11 @@ namespace ZScript
virtual bool canCastTo(DataType const& target) const = 0;
virtual bool canBeGlobal() const {return true;}
virtual bool canHoldObject() const {return isUsrClass();}
virtual script_object_type getScriptObjectTypeId() const {
if (isUsrClass())
return script_object_type::object;
return script_object_type::none;
}
virtual DataType const* getConstType() const {return constType;}
virtual DataType const* getMutType() const {return this;}

Expand Down Expand Up @@ -660,6 +667,19 @@ namespace ZScript
virtual bool canCastTo(DataType const& target) const;
virtual bool canBeGlobal() const {return true;}
virtual bool canHoldObject() const {return isGarbageCollected;}
virtual script_object_type getScriptObjectTypeId() const {
switch (classId)
{
case ZCLID_BITMAP: return script_object_type::bitmap;
case ZCLID_DIRECTORY: return script_object_type::dir;
case ZCLID_FILE: return script_object_type::file;
case ZCLID_PALDATA: return script_object_type::paldata;
case ZCLID_RNG: return script_object_type::rng;
case ZCLID_STACK: return script_object_type::stack;
case ZCLID_WEBSOCKET: return script_object_type::websocket;
}
return script_object_type::none;
}
virtual bool isClass() const {return true;}
virtual bool isConstant() const {return false;}

Expand Down Expand Up @@ -699,6 +719,7 @@ namespace ZScript
virtual bool canCastTo(DataType const& target) const;
virtual bool canBeGlobal() const {return true;}
virtual bool canHoldObject() const {return elementType.canHoldObject();}
virtual script_object_type getScriptObjectTypeId() const {return elementType.getScriptObjectTypeId();}

virtual bool isArray() const {return true;}
virtual bool isResolved() const {return elementType.isResolved();}
Expand Down
16 changes: 2 additions & 14 deletions src/user_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,6 @@

enum class ScriptType;

enum class script_object_type
{
bitmap,
dir,
file,
object,
paldata,
rng,
stack,
websocket,
};

struct user_abstract_obj
{
virtual bool operator==(user_abstract_obj const&) const = default;
Expand Down Expand Up @@ -76,7 +64,7 @@ struct user_object : public user_abstract_obj
{
std::vector<int32_t> data;
size_t owned_vars;
std::vector<bool> var_is_object;
std::vector<script_object_type> var_types;
scr_func_exec destruct;
bool global;
bool fake;
Expand All @@ -97,7 +85,7 @@ struct user_object : public user_abstract_obj
{
if (index < owned_vars)
{
return var_is_object.size() > index && var_is_object[index];
return var_types.size() > index && var_types[index] != script_object_type::none;
}
return false;
}
Expand Down

0 comments on commit f93172d

Please sign in to comment.