[Scummvm-git-logs] scummvm master -> 662e2cdddb2adfddc830e76ca567356adade7fe6
djsrv
dservilla at gmail.com
Tue Jun 23 23:42:19 UTC 2020
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
f220a0c469 DIRECTOR: LINGO: Give each Object a script context
662e2cdddb DIRECTOR: LINGO: Rename ScriptContext::getObject
Commit: f220a0c4690968b9cbe51dc51997fdd00a6650f4
https://github.com/scummvm/scummvm/commit/f220a0c4690968b9cbe51dc51997fdd00a6650f4
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-23T19:34:49-04:00
Commit Message:
DIRECTOR: LINGO: Give each Object a script context
Since symbols are bound to a script context, this will allow objects and
their methods to persist between movie changes. By extension, symbols
are now bound to a target object, eliminating the need for the extra
LC::call parameter.
Changed paths:
engines/director/lingo/lingo-code.cpp
engines/director/lingo/lingo-code.h
engines/director/lingo/lingo-codegen.cpp
engines/director/lingo/lingo-object.cpp
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
engines/director/lingo/xlibs/fileio.cpp
engines/director/lingo/xlibs/fileio.h
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 6f2036ad1c..6efc74773b 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -209,7 +209,7 @@ void LC::c_xpop() {
g_lingo->pop();
}
-void Lingo::pushContext(const Symbol *funcSym, bool preserveVarFrame) {
+void Lingo::pushContext(const Symbol funcSym, bool preserveVarFrame) {
debugC(5, kDebugLingoExec, "Pushing frame %d", g_lingo->_callstack.size() + 1);
CFrame *fp = new CFrame;
@@ -219,13 +219,18 @@ void Lingo::pushContext(const Symbol *funcSym, bool preserveVarFrame) {
fp->retarchive = g_lingo->_archiveIndex;
fp->localvars = g_lingo->_localvars;
fp->retMe = g_lingo->_currentMe;
- if (funcSym)
- fp->sp = *funcSym;
+ fp->sp = funcSym;
+
+ g_lingo->_currentScript = funcSym.u.defn;
+ if (funcSym.ctx) {
+ g_lingo->_currentScriptContext = funcSym.ctx;
+ g_lingo->_currentMe = funcSym.ctx->_target;
+ }
+ g_lingo->_archiveIndex = funcSym.archiveIndex;
- g_lingo->_currentMe = Datum();
// Functions with an archiveIndex of -1 are anonymous.
// Execute them within the current var frame.
- if (!preserveVarFrame && funcSym && funcSym->archiveIndex >= 0)
+ if (!preserveVarFrame && funcSym.archiveIndex >= 0)
g_lingo->_localvars = new DatumHash;
g_lingo->_callstack.push_back(fp);
@@ -1322,23 +1327,24 @@ void LC::call(const Common::String &name, int nargs) {
// Script/Xtra method call
if (nargs > 0) {
- Datum target = g_lingo->peek(nargs - 1);
- if (target.type == OBJECT && (target.u.obj->type & (kScriptObj | kXtraObj))) {
- debugC(3, kDebugLingoExec, "Method called on object: <%s>", target.asString(true).c_str());
+ Datum d = g_lingo->peek(nargs - 1);
+ if (d.type == OBJECT && (d.u.obj->type & (kScriptObj | kXtraObj))) {
+ debugC(3, kDebugLingoExec, "Method called on object: <%s>", d.asString(true).c_str());
+ Object *target = d.u.obj;
if (name.equalsIgnoreCase("birth") || name.equalsIgnoreCase("new")) {
- target = Datum(target.u.obj->clone());
+ target = target->clone();
}
- funcSym = target.u.obj->getMethod(name);
+ funcSym = target->getMethod(name);
if (funcSym.type != VOID) {
- if (target.u.obj->type == kScriptObj && funcSym.type == HANDLER) {
+ if (target->type == kScriptObj && funcSym.type == HANDLER) {
// For kScriptObj handlers the target is the first argument
- g_lingo->_stack[g_lingo->_stack.size() - nargs] = target;
+ g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.ctx->_target;
} else {
// Otherwise, take the target object out of the stack
g_lingo->_stack.remove_at(g_lingo->_stack.size() - nargs);
nargs -= 1;
}
- call(funcSym, nargs, target);
+ call(funcSym, nargs);
return;
}
}
@@ -1351,24 +1357,23 @@ void LC::call(const Common::String &name, int nargs) {
if (funcSym.type == VOID) {
Datum objName(name);
objName.type = VAR;
- Datum target = g_lingo->varFetch(objName);
- if (target.type == OBJECT && (target.u.obj->type & (kFactoryObj | kXObj))) {
- debugC(3, kDebugLingoExec, "Method called on object: <%s>", target.asString(true).c_str());
+ Datum d = g_lingo->varFetch(objName);
+ if (d.type == OBJECT && (d.u.obj->type & (kFactoryObj | kXObj))) {
+ debugC(3, kDebugLingoExec, "Method called on object: <%s>", d.asString(true).c_str());
+ Object *target = d.u.obj;
Datum methodName = g_lingo->_stack.remove_at(g_lingo->_stack.size() - nargs); // Take method name out of stack
nargs -= 1;
if (methodName.u.s->equalsIgnoreCase("mNew")) {
- target = Datum(target.u.obj->clone());
+ target = target->clone();
}
- funcSym = target.u.obj->getMethod(*methodName.u.s);
- call(funcSym, nargs, target);
- return;
+ funcSym = target->getMethod(*methodName.u.s);
}
}
call(funcSym, nargs);
}
-void LC::call(const Symbol &funcSym, int nargs, Datum target) {
+void LC::call(const Symbol &funcSym, int nargs) {
bool dropArgs = false;
if (funcSym.type == VOID) {
@@ -1406,6 +1411,11 @@ void LC::call(const Symbol &funcSym, int nargs, Datum target) {
if (funcSym.type == BLTIN || funcSym.type == FBLTIN || funcSym.type == RBLTIN) {
int stackSize = g_lingo->_stack.size() - nargs;
+ Datum target;
+ if (funcSym.ctx) {
+ target = funcSym.ctx->_target;
+ }
+
if (target.type == OBJECT) {
// Only need to update the me obj
// Pushing an entire stack frame is not necessary
@@ -1437,7 +1447,7 @@ void LC::call(const Symbol &funcSym, int nargs, Datum target) {
g_lingo->push(d);
}
- g_lingo->pushContext(&funcSym, true);
+ g_lingo->pushContext(funcSym, true);
DatumHash *localvars = g_lingo->_localvars;
if (funcSym.archiveIndex >= 0) {
@@ -1485,16 +1495,6 @@ void LC::call(const Symbol &funcSym, int nargs, Datum target) {
}
g_lingo->_localvars = localvars;
- if (target.type == OBJECT) {
- g_lingo->_currentMe = target;
- }
-
- g_lingo->_currentScript = funcSym.u.defn;
- if (funcSym.ctx) {
- g_lingo->_currentScriptContext = funcSym.ctx;
- }
- g_lingo->_archiveIndex = funcSym.archiveIndex;
-
g_lingo->_pc = 0;
}
diff --git a/engines/director/lingo/lingo-code.h b/engines/director/lingo/lingo-code.h
index 2837aa6ec7..8eb6ea2a10 100644
--- a/engines/director/lingo/lingo-code.h
+++ b/engines/director/lingo/lingo-code.h
@@ -114,7 +114,7 @@ namespace LC {
void c_jumpifz();
void c_call();
- void call(const Symbol &targetSym, int nargs, Datum target = Datum());
+ void call(const Symbol &targetSym, int nargs);
void call(const Common::String &name, int nargs);
void c_procret();
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 8dd872c1f0..0dc1e27daa 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -49,6 +49,7 @@
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-builtins.h"
#include "director/lingo/lingo-code.h"
+#include "director/types.h"
#include "director/util.h"
@@ -87,10 +88,10 @@ Symbol Lingo::define(Common::String &name, int nargs, ScriptData *code, Common::
}
if (factory) {
- if (factory->methods.contains(name)) {
+ if (factory->ctx->_functionHandlers.contains(name)) {
warning("Redefining method '%s' on factory '%s'", name.c_str(), factory->name->c_str());
}
- factory->methods[name] = sym;
+ factory->ctx->_functionHandlers[name] = sym;
} else if (_assemblyArchive >= 0) {
Symbol existing = getHandler(name);
if (existing.type != VOID)
@@ -294,7 +295,8 @@ void Lingo::varCreate(const Common::String &name, bool global, DatumHash *localv
}
void Lingo::codeFactory(Common::String &name) {
- Object *obj = new Object(name, kFactoryObj);
+ ScriptContext *ctx = new ScriptContext(kNoneScript, name);
+ Object *obj = new Object(name, kFactoryObj, ctx);
_currentFactory = obj;
if (!_globalvars.contains(name)) {
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 60fe49309d..c878ef0ee1 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -108,11 +108,9 @@ void Lingo::openXLib(const Common::String &name, ObjectType type) {
}
Object *Object::clone() {
- Object *res = new Object(*name, type);
+ Object *res = new Object(*name, type, new ScriptContext(*ctx));
res->disposed = disposed;
- res->prototype = this;
res->properties = properties;
- res->methods = methods;
res->inheritanceLevel = inheritanceLevel + 1;
if (objArray) {
res->objArray = new Common::HashMap<uint32, Datum>(*objArray);
@@ -126,15 +124,15 @@ Symbol Object::getMethod(const Common::String &methodName) {
}
// instance method (factory, script object, and Xtra)
- if ((type | (kFactoryObj & kScriptObj & kXtraObj)) && methods.contains(methodName)) {
- return methods[methodName];
+ if ((type | (kFactoryObj & kScriptObj & kXtraObj)) && ctx->_functionHandlers.contains(methodName)) {
+ return ctx->_functionHandlers[methodName];
}
if ((type & (kFactoryObj | kXObj)) && methodName.hasPrefixIgnoreCase("m")) {
Common::String shortName = methodName.substr(1);
// instance method (XObject)
- if (type == kXObj && methods.contains(shortName) && inheritanceLevel > 1) {
- return methods[shortName];
+ if (type == kXObj && ctx->_functionHandlers.contains(shortName) && inheritanceLevel > 1) {
+ return ctx->_functionHandlers[shortName];
}
// predefined method (factory and XObject)
if (g_lingo->_methods.contains(shortName) && (type & g_lingo->_methods[shortName].type)) {
@@ -269,7 +267,7 @@ void LM::m_perform(int nargs) {
Datum methodName = g_lingo->_stack.remove_at(g_lingo->_stack.size() - nargs); // Take method name out of stack
nargs -= 1;
Symbol funcSym = me->getMethod(*methodName.u.s);
- LC::call(funcSym, nargs, g_lingo->_currentMe);
+ LC::call(funcSym, nargs);
}
// XObject
@@ -283,7 +281,7 @@ void LM::m_instanceRespondsTo(int nargs) {
Datum d = g_lingo->pop();
Common::String methodName = d.asString();
- if (me->methods.contains(methodName)) {
+ if (me->ctx->_functionHandlers.contains(methodName)) {
g_lingo->push(Datum(1));
return;
}
@@ -309,7 +307,7 @@ void LM::m_respondsTo(int nargs) {
Datum d = g_lingo->pop();
Common::String methodName = d.asString();
- if (me->methods.contains(methodName) && me->inheritanceLevel > 1) {
+ if (me->ctx->_functionHandlers.contains(methodName) && me->inheritanceLevel > 1) {
g_lingo->push(Datum(1));
return;
}
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 883d5ae0b0..a53636132b 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -685,6 +685,9 @@ int Lingo::getAlignedType(Datum &d1, Datum &d2) {
}
void Datum::reset() {
+ if (!refCount)
+ return;
+
*refCount -= 1;
if (*refCount <= 0) {
switch (type) {
@@ -1077,7 +1080,7 @@ void Lingo::executePerFrameHook(int frame, int subframe) {
debugC(1, kDebugLingoExec, "Executing perFrameHook : <%s>(mAtFrame, %d, %d)", _perFrameHook.asString(true).c_str(), frame, subframe);
push(Datum(frame));
push(Datum(subframe));
- LC::call(method, 2, _perFrameHook);
+ LC::call(method, 2);
execute(_pc);
}
}
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index cda2b856ad..1618471839 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -220,12 +220,29 @@ public:
ScriptType _type;
Common::String _name;
Common::Array<Common::String> _functionNames; // used by cb_localcall
- Common::HashMap<uint32, Symbol> _eventHandlers;
SymbolHash _functionHandlers;
+ Common::HashMap<uint32, Symbol> _eventHandlers;
Common::Array<Datum> _constants;
Common::Array<Common::String> _propNames;
+ Datum _target;
ScriptContext(ScriptType type, Common::String name) : _type(type), _name(name) {}
+ ScriptContext(const ScriptContext &sc) {
+ _type = sc._type;
+ _name = sc._name;
+ _functionNames = sc._functionNames;
+ for (SymbolHash::iterator it = sc._functionHandlers.begin(); it != sc._functionHandlers.end(); ++it) {
+ _functionHandlers[it->_key] = it->_value;
+ _functionHandlers[it->_key].ctx = this;
+ }
+ for (Common::HashMap<uint32, Symbol>::iterator it = sc._eventHandlers.begin(); it != sc._eventHandlers.end(); ++it) {
+ _eventHandlers[it->_key] = it->_value;
+ _eventHandlers[it->_key].ctx = this;
+ }
+ _constants = sc._constants;
+ _propNames = sc._propNames;
+ }
+
Datum getObject();
private:
@@ -246,20 +263,25 @@ struct Object {
ObjectType type;
bool disposed;
- Object *prototype;
DatumHash properties;
- SymbolHash methods;
+ ScriptContext *ctx;
int inheritanceLevel; // 1 for original object
// used only for factories
Common::HashMap<uint32, Datum> *objArray;
- Object(const Common::String &objName, ObjectType objType) {
+ Object(const Common::String &objName, ObjectType objType, ScriptContext *objCtx) {
name = new Common::String(objName);
type = objType;
disposed = false;
inheritanceLevel = 1;
- prototype = nullptr;
+ ctx = objCtx;
+ ctx->_target = this;
+
+ // Don't include the ctx's reference to me in the refCount.
+ // Once that's the only remaining reference,
+ // I should be destroyed, killing the ctx with me.
+ *ctx->_target.refCount -= 1;
if (objType == kFactoryObj) {
objArray = new Common::HashMap<uint32, Datum>;
@@ -271,6 +293,8 @@ struct Object {
virtual ~Object() {
delete name;
delete objArray;
+ ctx->_target.refCount = nullptr; // refCount has already been freed
+ delete ctx;
}
virtual Object *clone();
@@ -385,7 +409,7 @@ public:
public:
void execute(uint pc);
- void pushContext(const Symbol *funcSym = nullptr, bool preserveVarFrame = false);
+ void pushContext(const Symbol funcSym, bool preserveVarFrame = false);
void popContext();
void cleanLocalVars();
int castIdFetch(Datum &var);
diff --git a/engines/director/lingo/xlibs/fileio.cpp b/engines/director/lingo/xlibs/fileio.cpp
index 724cf3e87f..64bcf231ce 100644
--- a/engines/director/lingo/xlibs/fileio.cpp
+++ b/engines/director/lingo/xlibs/fileio.cpp
@@ -28,6 +28,7 @@
#include "director/director.h"
#include "director/lingo/lingo.h"
#include "director/lingo/xlibs/fileio.h"
+#include "director/types.h"
namespace Director {
@@ -60,7 +61,8 @@ static struct MethodProto {
void FileIO::initialize(int type) {
if (type & kXObj) {
if (!g_lingo->_globalvars.contains(xlibName)) {
- FileObject *xobj = new FileObject(kXObj);
+ ScriptContext *ctx = new ScriptContext(kNoneScript, Common::String(xlibName));
+ FileObject *xobj = new FileObject(kXObj, ctx);
xobj->initMethods();
g_lingo->_globalvars[xlibName] = Datum();
g_lingo->_globalvars[xlibName].type = OBJECT;
@@ -88,16 +90,14 @@ void FileObject::initMethods() {
sym.maxArgs = mtd->maxArgs;
sym.targetType = mtd->type;
sym.u.bltin = mtd->func;
- methods[mtd->name] = sym;
+ ctx->_functionHandlers[mtd->name] = sym;
}
}
Object *FileObject::clone() {
- FileObject *res = new FileObject(type);
+ FileObject *res = new FileObject(type, new ScriptContext(*ctx));
res->disposed = disposed;
- res->prototype = this;
res->properties = properties;
- res->methods = methods;
res->inheritanceLevel = inheritanceLevel + 1;
return res;
}
diff --git a/engines/director/lingo/xlibs/fileio.h b/engines/director/lingo/xlibs/fileio.h
index 5a93a3182d..d20bd65c61 100644
--- a/engines/director/lingo/xlibs/fileio.h
+++ b/engines/director/lingo/xlibs/fileio.h
@@ -57,7 +57,7 @@ struct FileObject : Object {
Common::OutSaveFile *outFile;
Common::MemoryWriteStreamDynamic *outStream;
- FileObject(ObjectType objType) : Object("FileIO", objType) {
+ FileObject(ObjectType objType, ScriptContext *objCtx) : Object("FileIO", objType, objCtx) {
filename = nullptr;
inFile = nullptr;
inStream = nullptr;
Commit: 662e2cdddb2adfddc830e76ca567356adade7fe6
https://github.com/scummvm/scummvm/commit/662e2cdddb2adfddc830e76ca567356adade7fe6
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-23T19:34:54-04:00
Commit Message:
DIRECTOR: LINGO: Rename ScriptContext::getObject
Should be less confusing since a ctx can have a target object now.
Changed paths:
engines/director/lingo/lingo-builtins.cpp
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 87b896078e..8444605811 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -2162,7 +2162,7 @@ void LB::b_script(int nargs) {
}
if (script) {
- g_lingo->push(Datum(script->getObject()));
+ g_lingo->push(Datum(script->getParentScript()));
return;
}
}
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index a53636132b..b0c434d676 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -992,20 +992,15 @@ int Datum::compareTo(Datum &d, bool ignoreCase) {
}
}
-Datum ScriptContext::getObject() {
- if (_obj.type != OBJECT) {
- _obj.type = OBJECT;
- _obj.u.obj = new Object(_name, kScriptObj);
+Datum ScriptContext::getParentScript() {
+ if (_parentScript.type != OBJECT) {
+ _parentScript.type = OBJECT;
+ _parentScript.u.obj = new Object(_name, kScriptObj, new ScriptContext(*this));
for (Common::Array<Common::String>::iterator it = _propNames.begin(); it != _propNames.end(); ++it) {
- _obj.u.obj->properties[*it] = Datum();
- }
- for (SymbolHash::iterator it = _functionHandlers.begin(); it != _functionHandlers.end(); ++it) {
- Symbol sym = it->_value;
- sym.targetType = kScriptObj;
- _obj.u.obj->methods[it->_key] = sym;
+ _parentScript.u.obj->properties[*it] = Datum();
}
}
- return _obj;
+ return _parentScript;
}
void Lingo::parseMenu(const char *code) {
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 1618471839..cba18f9fbb 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -243,10 +243,10 @@ public:
_propNames = sc._propNames;
}
- Datum getObject();
+ Datum getParentScript();
private:
- Datum _obj;
+ Datum _parentScript;
};
enum ObjectType {
More information about the Scummvm-git-logs
mailing list