DIRECTOR: LINGO: Add previous script context to call frame

This commit is contained in:
Scott Percival 2020-01-18 11:36:21 +08:00
parent 329b77bd82
commit 87f6d6257d
5 changed files with 40 additions and 24 deletions

View File

@ -215,15 +215,15 @@ void LC::cb_field() {
void LC::cb_localcall() {
int nameId = g_lingo->readInt();
Common::String name = g_lingo->_namelist[nameId];
int functionId = g_lingo->readInt();
Datum nargs = g_lingo->pop();
if ((nargs.type == ARGC) || (nargs.type == ARGCNORET)) {
warning("STUB: cb_localcall(%s)", name.c_str());
for (int i = 0; i < nargs.u.i; i++) {
g_lingo->pop();
}
Symbol *sym = g_lingo->_currentScriptContext->functions[functionId];
if (debugChannelSet(3, kDebugLingoExec))
g_lingo->printSTUBWithArglist(sym->name.c_str(), nargs.u.i, "call:");
LC::call(sym, nargs.u.i);
} else {
warning("cb_localcall: first arg should be of type ARGC or ARGCNORET, not %s", nargs.type2str());
@ -565,8 +565,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
}
_currentScriptFunction = i;
_currentScriptContext->functions.push_back(new ScriptData);
_currentScript = _currentScriptContext->functions[_currentScriptFunction];
_currentScript = new ScriptData;
uint16 nameIndex = stream.readUint16();
stream.readUint16();
@ -742,12 +741,20 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
}
// Attach to handlers
Symbol *sym = NULL;
if (nameIndex < _namelist.size()) {
g_lingo->define(_namelist[nameIndex], argCount, new ScriptData(&(*_currentScript)[0], _currentScript->size()));
sym = g_lingo->define(_namelist[nameIndex], argCount, _currentScript);
_currentScriptContext->functions.push_back(sym);
} else {
warning("Function has unknown name id %d, skipping define", nameIndex);
sym = new Symbol;
sym->type = HANDLER;
sym->u.defn = _currentScript;
sym->nargs = argCount;
sym->maxArgs = argCount;
}
_currentScriptContext->functions.push_back(sym);
}
free(codeStore);

View File

@ -1164,8 +1164,6 @@ void LC::c_call() {
}
void LC::call(Common::String name, int nargs) {
bool dropArgs = false;
if (debugChannelSet(3, kDebugLingoExec))
g_lingo->printSTUBWithArglist(name.c_str(), nargs, "call:");
@ -1180,16 +1178,22 @@ void LC::call(Common::String name, int nargs) {
}
}
call(sym, nargs);
}
void LC::call(Symbol *sym, int nargs) {
bool dropArgs = false;
if (sym == NULL) {
warning("Call to undefined handler '%s'. Dropping %d stack items", name.c_str(), nargs);
warning("Call to undefined handler. Dropping %d stack items", nargs);
dropArgs = true;
} else {
if ((sym->type == BLTIN || sym->type == FBLTIN || sym->type == RBLTIN)
&& sym->nargs != -1 && sym->nargs != nargs && sym->maxArgs != nargs) {
if (sym->nargs == sym->maxArgs)
warning("Incorrect number of arguments to handler '%s', expecting %d. Dropping %d stack items", name.c_str(), sym->nargs, nargs);
warning("Incorrect number of arguments to handler '%s', expecting %d. Dropping %d stack items", sym->name.c_str(), sym->nargs, nargs);
else
warning("Incorrect number of arguments to handler '%s', expecting %d or %d. Dropping %d stack items", name.c_str(), sym->nargs, sym->maxArgs, nargs);
warning("Incorrect number of arguments to handler '%s', expecting %d or %d. Dropping %d stack items", sym->name.c_str(), sym->nargs, sym->maxArgs, nargs);
dropArgs = true;
}
@ -1207,14 +1211,14 @@ void LC::call(Common::String name, int nargs) {
if (sym->nargs != -1 && sym->maxArgs < nargs) {
warning("Incorrect number of arguments for function %s (%d, expected %d to %d). Dropping extra %d",
name.c_str(), nargs, sym->nargs, sym->maxArgs, nargs - sym->nargs);
sym->name.c_str(), nargs, sym->nargs, sym->maxArgs, nargs - sym->nargs);
for (int i = 0; i < nargs - sym->maxArgs; i++)
g_lingo->pop();
}
if (sym->type == BLTIN || sym->type == FBLTIN || sym->type == RBLTIN) {
if (sym->u.bltin == LB::b_factory) {
g_lingo->factoryCall(name, nargs);
g_lingo->factoryCall(sym->name, nargs);
} else {
int stackSize = g_lingo->_stack.size() - nargs;
@ -1224,10 +1228,10 @@ void LC::call(Common::String name, int nargs) {
if (sym->type == FBLTIN || sym->type == RBLTIN) {
if (stackNewSize - stackSize != 1)
warning("built-in function %s did not return value", name.c_str());
warning("built-in function %s did not return value", sym->name.c_str());
} else {
if (stackNewSize - stackSize != 0)
warning("built-in procedure %s returned extra %d values", name.c_str(), stackNewSize - stackSize);
warning("built-in procedure %s returned extra %d values", sym->name.c_str(), stackNewSize - stackSize);
}
}
@ -1248,6 +1252,7 @@ void LC::call(Common::String name, int nargs) {
fp->sp = sym;
fp->retpc = g_lingo->_pc;
fp->retscript = g_lingo->_currentScript;
fp->retctx = g_lingo->_currentScriptContext;
fp->localvars = g_lingo->_localvars;
// Create new set of local variables
@ -1274,6 +1279,7 @@ void LC::c_procret() {
g_lingo->_callstack.pop_back();
g_lingo->_currentScript = fp->retscript;
g_lingo->_currentScriptContext = fp->retctx;
g_lingo->_pc = fp->retpc;
g_lingo->cleanLocalVars();

View File

@ -101,6 +101,7 @@ namespace LC {
void c_jumpifz();
void c_call();
void call(Symbol *, int nargs);
void call(Common::String name, int nargs);
void c_procret();

View File

@ -142,8 +142,9 @@ void Lingo::addCode(const char *code, ScriptType type, uint16 id) {
// FIXME: unpack into seperate functions
_currentScriptFunction = 0;
_currentScriptContext->functions.push_back(new ScriptData);
_currentScript = _currentScriptContext->functions[_currentScriptFunction];
_currentScriptContext->functions.push_back(new Symbol);
_currentScript = new ScriptData;
_currentScriptContext->functions[_currentScriptFunction]->u.defn = _currentScript;
_linenumber = _colnumber = 1;
_hadError = false;
@ -232,7 +233,7 @@ void Lingo::executeScript(ScriptType type, uint16 id, uint16 function) {
debugC(1, kDebugLingoExec, "Executing script type: %s, id: %d, function: %d", scriptType2str(type), id, function);
_currentScriptContext = _scriptContexts[type][id];
_currentScript = _currentScriptContext->functions[function];
_currentScript = _currentScriptContext->functions[function]->u.defn;
_pc = 0;
_returning = false;

View File

@ -82,7 +82,7 @@ struct Symbol { /* symbol table entry */
int nargs; /* number of arguments */
int maxArgs; /* maximal number of arguments, for builtins */
bool parens; /* whether parens required or not, for builitins */
bool global;
Symbol();
@ -119,7 +119,7 @@ struct Builtin {
};
struct ScriptContext {
Common::Array<ScriptData *> functions;
Common::Array<Symbol *> functions;
Common::Array<Datum> constants;
};
@ -135,6 +135,7 @@ struct CFrame { /* proc/func call stack frame */
Symbol *sp; /* symbol table entry */
int retpc; /* where to resume after return */
ScriptData *retscript; /* which script to resume after return */
ScriptContext *retctx; /* which script context to use after return */
SymbolHash *localvars;
};