Skip to content

Commit

Permalink
DIRECTOR: LINGO: Refactor Object
Browse files Browse the repository at this point in the history
This turns Object into a template so any type can easily act as a Lingo
object. For example, script objects no longer own a script context.
They *are* script contexts, and there are custom getters/setters for
methods and properties.
  • Loading branch information
djsrv committed Jul 7, 2020
1 parent 8ea0b01 commit b2c20a0
Show file tree
Hide file tree
Showing 16 changed files with 1,430 additions and 1,441 deletions.
1 change: 1 addition & 0 deletions engines/director/cast.cpp
Expand Up @@ -39,6 +39,7 @@
#include "director/stxt.h"
#include "director/util.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-object.h"

namespace Director {

Expand Down
10 changes: 5 additions & 5 deletions engines/director/lingo/lingo-builtins.cpp
Expand Up @@ -1288,7 +1288,7 @@ void LB::b_return(int nargs) {
CFrame *fp = g_lingo->_callstack.back();
// Do not allow a factory's mNew method to return a value
// Otherwise do not touch the top of the stack, it will be returned
if (g_lingo->_currentMe.type == OBJECT && g_lingo->_currentMe.u.obj->type == kFactoryObj && fp->sp.name->equalsIgnoreCase("mNew")) {
if (g_lingo->_currentMe.type == OBJECT && g_lingo->_currentMe.u.obj->getObjType() == kFactoryObj && fp->sp.name->equalsIgnoreCase("mNew")) {
g_lingo->pop();
}
LC::c_procret();
Expand Down Expand Up @@ -1327,8 +1327,8 @@ void LB::b_factory(int nargs) {
Datum factoryName = g_lingo->pop();
factoryName.type = VAR;
Datum o = g_lingo->varFetch(factoryName, true);
if (o.type == OBJECT && (o.u.obj->type & (kFactoryObj | kXObj))
&& o.u.obj->name->equalsIgnoreCase(*factoryName.u.s) && o.u.obj->inheritanceLevel == 1) {
if (o.type == OBJECT && (o.u.obj->getObjType() & (kFactoryObj | kXObj))
&& o.u.obj->getName().equalsIgnoreCase(*factoryName.u.s) && o.u.obj->getInheritanceLevel() == 1) {
g_lingo->push(o);
} else {
g_lingo->push(Datum(0));
Expand Down Expand Up @@ -1357,7 +1357,7 @@ void LB::b_objectp(int nargs) {
Datum d = g_lingo->pop();
Datum res;
if (d.type == OBJECT) {
res = !d.u.obj->disposed;
res = !d.u.obj->isDisposed();
} else {
res = 0;
}
Expand Down Expand Up @@ -2200,7 +2200,7 @@ void LB::b_script(int nargs) {
}

if (script) {
g_lingo->push(Datum(script->getParentScript()));
g_lingo->push(script);
return;
}
}
Expand Down
18 changes: 7 additions & 11 deletions engines/director/lingo/lingo-bytecode.cpp
Expand Up @@ -317,7 +317,7 @@ void LC::cb_objectcall() {
Datum d = g_lingo->pop();
Datum nargs = g_lingo->pop();

Object *target = nullptr;
AbstractObject *target = nullptr;

if (d.type == INT) {
if (g_lingo->_callstack.empty()) {
Expand Down Expand Up @@ -381,7 +381,7 @@ void LC::cb_objectcall() {
}
Symbol method = target->getMethod(methodName.asString());
if (method.type != VOID) {
if (target->type == kFactoryObj && method.type == HANDLER) {
if (target->getObjType() == kFactoryObj && method.type == HANDLER) {
// For kFactoryObj handlers the target is the first argument
g_lingo->push(method.target);
nargs.u.i += 1;
Expand Down Expand Up @@ -909,7 +909,6 @@ ScriptContext *Lingo::compileLingoV4(Common::SeekableSubReadStreamEndian &stream
debugC(1, kDebugCompile, "Add V4 bytecode for factory '%s' with id %d", factoryName.c_str(), castId);

codeFactory(factoryName);
_assemblyContext = _currentFactory->ctx;
} else {
debugC(1, kDebugCompile, "Add V4 bytecode for type %s with id %d", scriptType2str(scriptType), castId);

Expand All @@ -936,11 +935,7 @@ ScriptContext *Lingo::compileLingoV4(Common::SeekableSubReadStreamEndian &stream
if (0 <= index && index < (int16)archive->names.size()) {
const char *name = archive->names[index].c_str();
debugC(5, kDebugLoading, "%d: %s", i, name);
if (scriptFlags & kScriptFlagFactoryDef) {
_currentFactory->properties[name] = Datum();
} else {
_assemblyContext->_propNames.push_back(name);
}
_assemblyContext->_properties[name] = Datum();
} else {
warning("Property %d has unknown name id %d, skipping define", i, index);
}
Expand Down Expand Up @@ -1437,15 +1432,16 @@ ScriptContext *Lingo::compileLingoV4(Common::SeekableSubReadStreamEndian &stream

free(codeStore);
_assemblyContext = nullptr;
_currentFactory = nullptr;

return sc;
}

void LingoArchive::addCodeV4(Common::SeekableSubReadStreamEndian &stream, const Common::String &archName) {
ScriptContext *ctx = g_lingo->compileLingoV4(stream, this, archName);
if (ctx)
scriptContexts[ctx->_type][ctx->_id] = ctx;
if (ctx) {
scriptContexts[ctx->_scriptType][ctx->_id] = ctx;
*ctx->_refCount += 1;
}
}

void LingoArchive::addNamesV4(Common::SeekableSubReadStreamEndian &stream) {
Expand Down
14 changes: 7 additions & 7 deletions engines/director/lingo/lingo-code.cpp
Expand Up @@ -1330,15 +1330,15 @@ void LC::call(const Common::String &name, int nargs) {
// Script/Xtra method call
if (nargs > 0) {
Datum d = g_lingo->peek(nargs - 1);
if (d.type == OBJECT && (d.u.obj->type & (kScriptObj | kXtraObj))) {
if (d.type == OBJECT && (d.u.obj->getObjType() & (kScriptObj | kXtraObj))) {
debugC(3, kDebugLingoExec, "Method called on object: <%s>", d.asString(true).c_str());
Object *target = d.u.obj;
AbstractObject *target = d.u.obj;
if (name.equalsIgnoreCase("birth") || name.equalsIgnoreCase("new")) {
target = target->clone();
}
funcSym = target->getMethod(name);
if (funcSym.type != VOID) {
if (target->type == kScriptObj && funcSym.type == HANDLER) {
if (target->getObjType() == kScriptObj && funcSym.type == HANDLER) {
// For kScriptObj handlers the target is the first argument
g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.target;
} else {
Expand All @@ -1360,15 +1360,15 @@ void LC::call(const Common::String &name, int nargs) {
Datum objName(name);
objName.type = VAR;
Datum d = g_lingo->varFetch(objName);
if (d.type == OBJECT && (d.u.obj->type & (kFactoryObj | kXObj))) {
if (d.type == OBJECT && (d.u.obj->getObjType() & (kFactoryObj | kXObj))) {
debugC(3, kDebugLingoExec, "Method called on object: <%s>", d.asString(true).c_str());
Object *target = d.u.obj;
AbstractObject *target = d.u.obj;
Datum methodName = g_lingo->_stack[g_lingo->_stack.size() - nargs];
if (methodName.u.s->equalsIgnoreCase("mNew")) {
target = target->clone();
}
funcSym = target->getMethod(*methodName.u.s);
if (target->type == kScriptObj && funcSym.type == HANDLER) {
if (target->getObjType() == kScriptObj && funcSym.type == HANDLER) {
// For kFactoryObj handlers the target is the first argument
g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.target;
} else {
Expand Down Expand Up @@ -1510,7 +1510,7 @@ void LC::c_procret() {
}

CFrame *fp = g_lingo->_callstack.back();
if (g_lingo->_currentMe.type == OBJECT && g_lingo->_currentMe.u.obj->type == kFactoryObj && fp->sp.name->equalsIgnoreCase("mNew")) {
if (g_lingo->_currentMe.type == OBJECT && g_lingo->_currentMe.u.obj->getObjType() == kFactoryObj && fp->sp.name->equalsIgnoreCase("mNew")) {
// Return the newly created object after executing mNew
g_lingo->push(g_lingo->_currentMe);
}
Expand Down
18 changes: 7 additions & 11 deletions engines/director/lingo/lingo-codegen.cpp
Expand Up @@ -87,7 +87,7 @@ Symbol ScriptContext::define(Common::String &name, int nargs, ScriptData *code,

if (!g_lingo->_eventHandlerTypeIds.contains(name)) {
_functionHandlers[name] = sym;
if (_type == kMovieScript && _archive && !_archive->functionHandlers.contains(name)) {
if (_scriptType == kMovieScript && _archive && !_archive->functionHandlers.contains(name)) {
_archive->functionHandlers[name] = sym;
}
} else {
Expand All @@ -97,9 +97,9 @@ Symbol ScriptContext::define(Common::String &name, int nargs, ScriptData *code,
return sym;
}

Symbol Lingo::codeDefine(Common::String &name, int start, int nargs, Object *factory, int end, bool removeCode) {
debugC(1, kDebugCompile, "codeDefine(\"%s\"(len: %d), %d, %d, \"%s\", %d)",
name.c_str(), _currentAssembly->size() - 1, start, nargs, (factory ? factory->name->c_str() : ""), end);
Symbol Lingo::codeDefine(Common::String &name, int start, int nargs, int end, bool removeCode) {
debugC(1, kDebugCompile, "codeDefine(\"%s\"(len: %d), %d, %d, %d)",
name.c_str(), _currentAssembly->size() - 1, start, nargs, end);

if (end == -1)
end = _currentAssembly->size();
Expand All @@ -115,8 +115,7 @@ Symbol Lingo::codeDefine(Common::String &name, int start, int nargs, Object *fac
varNames->push_back(Common::String(it->_key));
}

ScriptContext *ctx = factory ? factory->ctx : _assemblyContext;
Symbol sym = ctx->define(name, nargs, code, argNames, varNames);
Symbol sym = _assemblyContext->define(name, nargs, code, argNames, varNames);

if (debugChannelSet(1, kDebugCompile)) {
debug("Function vars");
Expand Down Expand Up @@ -287,12 +286,9 @@ void Lingo::varCreate(const Common::String &name, bool global, DatumHash *localv
void Lingo::codeFactory(Common::String &name) {
// FIXME: The factory's context should not be tied to the LingoArchive
// but bytecode needs it to resolve names
ScriptContext *ctx = new ScriptContext(name, _assemblyArchive);
Object *obj = new Object(name, kFactoryObj, ctx);

_currentFactory = obj;
_assemblyContext->setFactory(true);
if (!_globalvars.contains(name)) {
_globalvars[name] = obj;
_globalvars[name] = _assemblyContext;
} else {
warning("Factory '%s' already defined", name.c_str());
}
Expand Down
1 change: 1 addition & 0 deletions engines/director/lingo/lingo-events.cpp
Expand Up @@ -23,6 +23,7 @@
#include "director/director.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-code.h"
#include "director/lingo/lingo-object.h"
#include "director/cast.h"
#include "director/movie.h"
#include "director/frame.h"
Expand Down

0 comments on commit b2c20a0

Please sign in to comment.