[Scummvm-git-logs] scummvm master -> 0906dc324032e0fc8b0cc8562fd3888ed62049d7
djsrv
dservilla at gmail.com
Fri Jun 26 01:07:57 UTC 2020
This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
4dab1f59dd DIRECTOR: LINGO: Fix Object::getMethod
e709661c40 DIRECTOR: LINGO: Remove redundant var methods
16ba15d5b6 DIRECTOR: LINGO Add bytecode instruction 0x02
3157c9775d DIRECTOR: LINGO: Improve Lscr name resolution
0906dc3240 DIRECTOR: LINGO: Improve factory method calls
Commit: 4dab1f59ddf3ab90f71eba674f848e7916e3f960
https://github.com/scummvm/scummvm/commit/4dab1f59ddf3ab90f71eba674f848e7916e3f960
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-25T20:49:47-04:00
Commit Message:
DIRECTOR: LINGO: Fix Object::getMethod
Changed paths:
engines/director/lingo/lingo-object.cpp
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 8054613de0..a01d62ed7c 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -111,7 +111,7 @@ Symbol Object::getMethod(const Common::String &methodName) {
}
// instance method (factory, script object, and Xtra)
- if ((type | (kFactoryObj & kScriptObj & kXtraObj)) && ctx->_functionHandlers.contains(methodName)) {
+ if ((type & (kFactoryObj | kScriptObj | kXtraObj)) && ctx->_functionHandlers.contains(methodName)) {
return ctx->_functionHandlers[methodName];
}
@@ -122,13 +122,17 @@ Symbol Object::getMethod(const Common::String &methodName) {
return ctx->_functionHandlers[shortName];
}
// predefined method (factory and XObject)
- if (g_lingo->_methods.contains(shortName) && (type & g_lingo->_methods[shortName].type)) {
- return g_lingo->_methods[shortName];
+ if (g_lingo->_methods.contains(shortName) && (type & g_lingo->_methods[shortName].targetType)) {
+ Symbol sym = g_lingo->_methods[shortName];
+ sym.ctx = ctx;
+ return sym;
}
} else if (type & (kScriptObj | kXtraObj)) {
// predefined method (script object and Xtra)
- if (g_lingo->_methods.contains(methodName) && (type & g_lingo->_methods[methodName].type)) {
- return g_lingo->_methods[methodName];
+ if (g_lingo->_methods.contains(methodName) && (type & g_lingo->_methods[methodName].targetType)) {
+ Symbol sym = g_lingo->_methods[methodName];
+ sym.ctx = ctx;
+ return sym;
}
// ancestor method
Commit: e709661c40aa0bfcc544117d0ca80a42102b0683
https://github.com/scummvm/scummvm/commit/e709661c40aa0bfcc544117d0ca80a42102b0683
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-25T20:53:33-04:00
Commit Message:
DIRECTOR: LINGO: Remove redundant var methods
Changed paths:
engines/director/lingo/lingo-codegen.cpp
engines/director/lingo/lingo-object.cpp
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index eaa3ac2269..cc938267df 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -275,7 +275,7 @@ void Lingo::varCreate(const Common::String &name, bool global, DatumHash *localv
if (global)
warning("varCreate: variable %s is local, not global", name.c_str());
return;
- } else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasVar(name)) {
+ } else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
if (global)
warning("varCreate: variable %s is instance or property, not global", name.c_str());
return;
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index a01d62ed7c..1806695834 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -146,51 +146,16 @@ Symbol Object::getMethod(const Common::String &methodName) {
return Symbol();
}
-// Variable access (e.g. `put variable`, within a method)
-
-bool Object::hasVar(const Common::String &varName) {
- if (disposed) {
- error("Variable '%s' accessed on disposed object <%s>", varName.c_str(), Datum(this).asString(true).c_str());
- }
- if (properties.contains(varName)) {
- return true;
- }
- if (type & (kScriptObj | kXtraObj)) {
- if (properties.contains("ancestor") && properties["ancestor"].type == OBJECT
- && (properties["ancestor"].u.obj->type & (kScriptObj | kXtraObj))) {
- return properties["ancestor"].u.obj->hasVar(varName);
- }
- }
- return false;
-}
-
-Datum &Object::getVar(const Common::String &varName) {
- if (disposed) {
- error("Variable '%s' accessed on disposed object <%s>", varName.c_str(), Datum(this).asString(true).c_str());
- }
- if (properties.contains(varName)) {
- return properties[varName];
- }
- if (type & (kScriptObj | kXtraObj)) {
- if (properties.contains("ancestor") && properties["ancestor"].type == OBJECT
- && (properties["ancestor"].u.obj->type & (kScriptObj | kXtraObj))) {
- debugC(3, kDebugLingoExec, "Getting var '%s' from ancestor: <%s>", varName.c_str(), properties["ancestor"].asString(true).c_str());
- return properties["ancestor"].u.obj->getVar(varName);
- }
- }
- return properties[varName]; // return new variable
-}
-
-// Property access (e.g. `put the property of object`)
+// Property access
bool Object::hasProp(const Common::String &propName) {
if (disposed) {
error("Property '%s' accessed on disposed object <%s>", propName.c_str(), Datum(this).asString(true).c_str());
}
+ if (properties.contains(propName)) {
+ return true;
+ }
if (type & (kScriptObj | kXtraObj)) {
- if (properties.contains(propName)) {
- return true;
- }
if (properties.contains("ancestor") && properties["ancestor"].type == OBJECT
&& (properties["ancestor"].u.obj->type & (kScriptObj | kXtraObj))) {
return properties["ancestor"].u.obj->hasProp(propName);
@@ -203,10 +168,10 @@ Datum &Object::getProp(const Common::String &propName) {
if (disposed) {
error("Property '%s' accessed on disposed object <%s>", propName.c_str(), Datum(this).asString(true).c_str());
}
+ if (properties.contains(propName)) {
+ return properties[propName];
+ }
if (type & (kScriptObj | kXtraObj)) {
- if (properties.contains(propName)) {
- return properties[propName];
- }
if (properties.contains("ancestor") && properties["ancestor"].type == OBJECT
&& (properties["ancestor"].u.obj->type & (kScriptObj | kXtraObj))) {
debugC(3, kDebugLingoExec, "Getting prop '%s' from ancestor: <%s>", propName.c_str(), properties["ancestor"].asString(true).c_str());
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 3737ecbf19..7e41fc81df 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1155,8 +1155,8 @@ void Lingo::varAssign(Datum &var, Datum &value, bool global, DatumHash *localvar
d = &(*localvars)[name];
if (global)
warning("varAssign: variable %s is local, not global", name.c_str());
- } else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasVar(name)) {
- d = &_currentMe.u.obj->getVar(name);
+ } else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
+ d = &_currentMe.u.obj->getProp(name);
if (global)
warning("varAssign: variable %s is instance or property, not global", name.c_str());
} else if (_globalvars.contains(name)) {
@@ -1220,8 +1220,8 @@ Datum Lingo::varFetch(Datum &var, bool global, DatumHash *localvars) {
d = &(*localvars)[name];
if (global)
warning("varFetch: variable %s is local, not global", name.c_str());
- } else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasVar(name)) {
- d = &_currentMe.u.obj->getVar(name);
+ } else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
+ d = &_currentMe.u.obj->getProp(name);
if (global)
warning("varFetch: variable %s is instance or property, not global", name.c_str());
} else if (_globalvars.contains(name)) {
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index a2d0781abd..fc69d149bb 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -316,8 +316,6 @@ struct Object {
virtual Object *clone();
Symbol getMethod(const Common::String &methodName);
- bool hasVar(const Common::String &varName);
- Datum &getVar(const Common::String &varName);
bool hasProp(const Common::String &propName);
Datum &getProp(const Common::String &propName);
};
Commit: 16ba15d5b6876608be08b3d12f451c0d922e9835
https://github.com/scummvm/scummvm/commit/16ba15d5b6876608be08b3d12f451c0d922e9835
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-25T20:54:28-04:00
Commit Message:
DIRECTOR: LINGO Add bytecode instruction 0x02
This just seems to be procret but for methods.
Changed paths:
engines/director/lingo/lingo-bytecode.cpp
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 95e73da06a..568cdc2b45 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -38,6 +38,7 @@ namespace Director {
static LingoV4Bytecode lingoV4[] = {
{ 0x01, LC::c_procret, "" },
+ { 0x02, LC::c_procret, "" },
{ 0x03, LC::cb_zeropush, "" },
{ 0x04, LC::c_mul, "" },
{ 0x05, LC::c_add, "" },
Commit: 3157c9775d584833ef38e08ee2b931aba63a5179
https://github.com/scummvm/scummvm/commit/3157c9775d584833ef38e08ee2b931aba63a5179
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-25T21:01:51-04:00
Commit Message:
DIRECTOR: LINGO: Improve Lscr name resolution
Changed paths:
engines/director/lingo/lingo-bytecode.cpp
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 568cdc2b45..7f80c812a7 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -892,8 +892,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
debugC(5, kDebugLoading, "Lscr property list:");
stream.seek(propertiesOffset);
for (uint16 i = 0; i < propertiesCount; i++) {
- uint16 index = stream.readUint16();
- if (index < _archives[_assemblyArchive].names.size()) {
+ int16 index = stream.readSint16();
+ if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
const char *name = _archives[_assemblyArchive].names[index].c_str();
debugC(5, kDebugLoading, "%d: %s", i, name);
if (scriptFlags & kScriptFlagFactoryDef) {
@@ -915,8 +915,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
debugC(5, kDebugLoading, "Lscr globals list:");
stream.seek(globalsOffset);
for (uint16 i = 0; i < globalsCount; i++) {
- uint16 index = stream.readUint16();
- if (index < _archives[_assemblyArchive].names.size()) {
+ int16 index = stream.readSint16();
+ if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
const char *name = _archives[_assemblyArchive].names[index].c_str();
debugC(5, kDebugLoading, "%d: %s", i, name);
if (!_globalvars.contains(name)) {
@@ -1092,7 +1092,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
stream.hexdump(0x2a);
}
- uint16 nameIndex = stream.readUint16();
+ int16 nameIndex = stream.readUint16();
stream.readUint16();
uint32 length = stream.readUint32();
uint32 startOffset = stream.readUint32();
@@ -1129,15 +1129,27 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
debugC(5, kDebugLoading, "Function %d argument list:", i);
uint16 namePointer = argOffset - codeStoreOffset;
for (int j = 0; j < argCount; j++) {
- uint16 index = (uint16)READ_BE_UINT16(&codeStore[namePointer]);
+ int16 index = READ_BE_INT16(&codeStore[namePointer]);
namePointer += 2;
Common::String name;
- if (index < _archives[_assemblyArchive].names.size()) {
+ if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
name = _archives[_assemblyArchive].names[index];
+ argMap[j] = index;
+ } else if (j == 0 && (scriptFlags & kScriptFlagFactoryDef)) {
+ name = "me";
+
+ // find or add "me" in the names list
+ for (index = 0; index < (int16)_archives[_assemblyArchive].names.size(); index++) {
+ if (_archives[_assemblyArchive].names[index].equalsIgnoreCase(name))
+ break;
+ }
+ if (index == (int16)_archives[_assemblyArchive].names.size())
+ _archives[_assemblyArchive].names.push_back(name);
+
argMap[j] = index;
} else {
name = Common::String::format("arg_%d", j);
- warning("Argument has unknown name id %d, using name %s", j, name.c_str());
+ warning("Argument has unknown name id %d, using name %s", index, name.c_str());
}
debugC(5, kDebugLoading, "%d: %s", j, name.c_str());
argNames->push_back(name);
@@ -1155,10 +1167,10 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
debugC(5, kDebugLoading, "Function %d variable list:", i);
uint16 namePointer = varOffset - codeStoreOffset;
for (int j = 0; j < varCount; j++) {
- uint16 index = (uint16)READ_BE_UINT16(&codeStore[namePointer]);
+ int16 index = READ_BE_INT16(&codeStore[namePointer]);
namePointer += 2;
Common::String name;
- if (index < _archives[_assemblyArchive].names.size()) {
+ if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
name = _archives[_assemblyArchive].names[index];
varMap[j] = index;
} else {
@@ -1345,7 +1357,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
// Attach to handlers
Symbol sym;
- if (nameIndex < _archives[_assemblyArchive].names.size()) {
+ if (0 <= nameIndex && nameIndex < (int16)_archives[_assemblyArchive].names.size()) {
debugC(5, kDebugLoading, "Function %d binding: %s()", i, _archives[_assemblyArchive].names[nameIndex].c_str());
sym = g_lingo->define(_archives[_assemblyArchive].names[nameIndex], argCount, _currentAssembly, argNames, varNames);
} else {
@@ -1360,7 +1372,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
}
if (!skipdump && ConfMan.getBool("dump_scripts")) {
- if (nameIndex < _archives[_assemblyArchive].names.size())
+ if (0 <= nameIndex && nameIndex < (int16)_archives[_assemblyArchive].names.size())
out.writeString(Common::String::format("function %s, %d args\n", _archives[_assemblyArchive].names[nameIndex].c_str(), argCount));
else
out.writeString(Common::String::format("<noname>, %d args\n", argCount));
Commit: 0906dc324032e0fc8b0cc8562fd3888ed62049d7
https://github.com/scummvm/scummvm/commit/0906dc324032e0fc8b0cc8562fd3888ed62049d7
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-25T21:04:00-04:00
Commit Message:
DIRECTOR: LINGO: Improve factory method calls
Changed paths:
engines/director/lingo/lingo-bytecode.cpp
engines/director/lingo/lingo-code.cpp
engines/director/lingo/lingo-gr.y
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 7f80c812a7..9af4a8b702 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -311,68 +311,105 @@ void LC::cb_localcall() {
void LC::cb_objectcall() {
g_lingo->readInt();
- Datum object = g_lingo->pop();
+ Datum d = g_lingo->pop();
Datum nargs = g_lingo->pop();
- if (object.type != SYMBOL) {
- warning("cb_objectcall: first arg should be of type SYMBOL, not %s", object.type2str());
- } else if ((nargs.type != ARGC) && (nargs.type != ARGCNORET)) {
- warning("cb_objectcall: second arg should be of type ARGC or ARGCNORET, not %s", nargs.type2str());
- } else {
- // first, try looking up an object with that name
- object.type = VAR;
- Datum target = g_lingo->varFetch(object);
-
- StackData args;
- if (target.type == OBJECT) {
- // last arg on the stack is the method name
- nargs.u.i -= 1;
- }
- for (int i = 0; i < nargs.u.i; i++) {
- Datum arg = g_lingo->pop();
- // for some reason, strings that are sent to here are actually variable names???
- // other constants (e.g. ints) are fine.
- if (arg.type == STRING) {
- Datum varTest(arg);
- varTest.type = VAR;
- varTest = g_lingo->varFetch(varTest);
- if (varTest.type != VOID)
- arg = varTest;
- }
- args.push_back(arg);
- }
+ Object *target;
- if (target.type == OBJECT) {
- Datum methodName = g_lingo->pop();
- Symbol method = target.u.obj->getMethod(methodName.asString());
- if (method.type != VOID) {
- for (int i = 0; i < nargs.u.i; i++) {
- g_lingo->push(args.back());
- args.pop_back();
- }
- LC::call(method, nargs.u.i);
- } else {
- warning("cb_objectcall: object %s has no method named %s", object.u.s->c_str(), methodName.asString().c_str());
- }
+ if (d.type == INT) {
+ if (g_lingo->_callstack.empty()) {
+ warning("cb_objectcall: no call frame");
+ }
+ Common::Array<Common::String> *varNames = g_lingo->_callstack.back()->sp.varNames;
+ if ((d.asInt() % 6 == 0) && varNames && (d.asInt() / 6 < (int)varNames->size())) {
+ d = (*varNames)[d.asInt() / 6];
+ d.type = SYMBOL;
+ } else {
+ warning("cb_objectcall: invalid variable ID %d", d.asInt());
return;
}
+ }
- // if there's nothing, try calling a function with that name
- Symbol func = g_lingo->getHandler(*object.u.s);
- if (func.type != VOID) {
- for (int i = 0; i < nargs.u.i; i++) {
+ if (d.type != SYMBOL) {
+ warning("cb_objectcall: first arg should be of type SYMBOL or INT, not %s", d.type2str());
+ return;
+ }
+
+ // try to fetch target
+ d.type = VAR;
+ Datum val = g_lingo->varFetch(d);
+ if (val.type == OBJECT) {
+ target = val.u.obj;
+ } else {
+ warning("cb_objectcall: target is not an object");
+ }
+
+ if ((nargs.type != ARGC) && (nargs.type != ARGCNORET)) {
+ warning("cb_objectcall: second arg should be of type ARGC or ARGCNORET, not %s", nargs.type2str());
+ return;
+ }
+
+ StackData args;
+ if (target) {
+ // last arg on the stack is the method name
+ nargs.u.i -= 1;
+ }
+
+ for (int i = 0; i < nargs.u.i; i++) {
+ Datum arg = g_lingo->pop();
+ // for some reason, strings that are sent to here are actually variable names???
+ // other constants (e.g. ints) are fine.
+ if (arg.type == STRING) {
+ Datum varTest(arg);
+ varTest.type = VAR;
+ varTest = g_lingo->varFetch(varTest);
+ if (varTest.type != VOID)
+ arg = varTest;
+ }
+ args.push_back(arg);
+ }
+
+ Datum methodName;
+ if (target) {
+ methodName = g_lingo->pop();
+ if (methodName.u.s->equalsIgnoreCase("mNew")) {
+ target = target->clone();
+ }
+ Symbol method = target->getMethod(methodName.asString());
+ if (method.type != VOID) {
+ if (target->type == kFactoryObj && method.type == HANDLER) {
+ // For kFactoryObj handlers the target is the first argument
+ g_lingo->push(method.ctx->_target); // reference-counted datum
+ nargs.u.i += 1;
+ }
+ while (args.size()) {
g_lingo->push(args.back());
args.pop_back();
}
+ LC::call(method, nargs.u.i);
+ return;
+ }
- LC::call(func, nargs.u.i);
- } else {
- warning("cb_objectcall: could not find object or function with name %s", object.u.s->c_str());
- // Push a VOID to the stack if function is supposed to return
- if (nargs.type == ARGC)
- g_lingo->push(Datum());
+ warning("cb_objectcall: target has no method named %s", methodName.asString().c_str());
+ }
+ // if there's nothing, try calling a function with that name
+ Symbol func = g_lingo->getHandler(*d.u.s);
+ if (func.type != VOID) {
+ if (target) {
+ g_lingo->push(methodName);
+ }
+ while (args.size()) {
+ g_lingo->push(args.back());
+ args.pop_back();
}
+
+ LC::call(func, nargs.u.i);
+ } else {
+ warning("cb_objectcall: could not find object or function with name %s", d.u.s->c_str());
+ // Push a VOID to the stack if function is supposed to return
+ if (nargs.type == ARGC)
+ g_lingo->push(Datum());
}
}
@@ -514,7 +551,6 @@ void LC::cb_objectfieldpush() {
void LC::cb_objectpush() {
int nameId = g_lingo->readInt();
Common::String name = g_lingo->getName(nameId);
- warning("STUB: cb_objectpush(%s)", name.c_str());
Datum result(name);
result.type = SYMBOL;
g_lingo->push(result);
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 6efc74773b..8c0a1e7169 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -224,7 +224,7 @@ void Lingo::pushContext(const Symbol funcSym, bool preserveVarFrame) {
g_lingo->_currentScript = funcSym.u.defn;
if (funcSym.ctx) {
g_lingo->_currentScriptContext = funcSym.ctx;
- g_lingo->_currentMe = funcSym.ctx->_target;
+ g_lingo->_currentMe = funcSym.ctx->_target; // reference-counted datum
}
g_lingo->_archiveIndex = funcSym.archiveIndex;
@@ -1338,7 +1338,7 @@ void LC::call(const Common::String &name, int nargs) {
if (funcSym.type != VOID) {
if (target->type == kScriptObj && funcSym.type == HANDLER) {
// For kScriptObj handlers the target is the first argument
- g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.ctx->_target;
+ g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.ctx->_target; // reference-counted datum
} else {
// Otherwise, take the target object out of the stack
g_lingo->_stack.remove_at(g_lingo->_stack.size() - nargs);
@@ -1361,12 +1361,19 @@ void LC::call(const Common::String &name, int nargs) {
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;
+ 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) {
+ // For kFactoryObj handlers the target is the first argument
+ g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.ctx->_target; // reference-counted datum
+ } else {
+ // Otherwise, take the methodName out of the stack
+ g_lingo->_stack.remove_at(g_lingo->_stack.size() - nargs);
+ nargs -= 1;
+ }
}
}
@@ -1413,7 +1420,7 @@ void LC::call(const Symbol &funcSym, int nargs) {
Datum target;
if (funcSym.ctx) {
- target = funcSym.ctx->_target;
+ target = funcSym.ctx->_target; // reference-counted datum
}
if (target.type == OBJECT) {
diff --git a/engines/director/lingo/lingo-gr.y b/engines/director/lingo/lingo-gr.y
index c1776ba5b5..c1b0be66bd 100644
--- a/engines/director/lingo/lingo-gr.y
+++ b/engines/director/lingo/lingo-gr.y
@@ -774,10 +774,10 @@ defn: tMACRO { startDef(); } ID { g_lingo->_currentFactory = NULL; }
endDef();
delete $ID; }
| tFACTORY ID { g_lingo->codeFactory(*$ID); delete $ID; }
- | tMETHOD { startDef(); }
+ | tMETHOD { startDef(); (*g_lingo->_methodVars)["me"] = kVarArgument; }
lbl argdef '\n' argstore stmtlist {
g_lingo->code1(LC::c_procret);
- g_lingo->codeDefine(*$tMETHOD, $lbl, $argdef, g_lingo->_currentFactory);
+ g_lingo->codeDefine(*$tMETHOD, $lbl, $argdef + 1, g_lingo->_currentFactory);
endDef();
delete $tMETHOD; }
| on lbl argdef '\n' argstore stmtlist ENDCLAUSE endargdef { // D3
More information about the Scummvm-git-logs
mailing list