From c53e4b579a0217e01208b7e06ead853f4319df7c Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Thu, 30 Jun 2016 17:03:02 +0200 Subject: [PATCH] DIRECTOR: Lingo: Make global/local vars work --- engines/director/director.cpp | 7 +++++- engines/director/lingo/lingo-code.cpp | 26 +++++----------------- engines/director/lingo/lingo-codegen.cpp | 28 ++++++++++++++++++------ engines/director/lingo/lingo.cpp | 2 +- engines/director/lingo/lingo.h | 5 +++-- 5 files changed, 36 insertions(+), 32 deletions(-) diff --git a/engines/director/director.cpp b/engines/director/director.cpp index 9a22e675cb7a..7463a9e77acf 100644 --- a/engines/director/director.cpp +++ b/engines/director/director.cpp @@ -105,6 +105,7 @@ _lingo->executeScript(kMovieScript, 2); _lingo->addCode("--\n\ macro SHIPX\n\ +global x\n\ set x = 5\n\ if x = 1 then\n\ go \"Zoom\"\n\ @@ -117,12 +118,13 @@ put 100\n\ \n\ --\n\ macro ZIPX\n\ -set x = 5\n\ +set x = 7\n\ if x = 1 then\n\ go \"ZIP\"\n\ exit\n\ end if\n\ if x >1 then\n\ +put x\n\ exit\n\ end if\n\ \n\ @@ -136,8 +138,11 @@ end if\n\ ", kMovieScript, 1); _lingo->addCode("check(2, 3)\n\ +global x\n\ shipx\n\ put x\n\ +zipx\n\ +put x\n\ ", kMovieScript, 2); _lingo->executeScript(kMovieScript, 2); diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp index 9bc6b48b90b1..1a297e50fd39 100644 --- a/engines/director/lingo/lingo-code.cpp +++ b/engines/director/lingo/lingo-code.cpp @@ -406,10 +406,7 @@ void Lingo::c_call() { fp->retscript = g_lingo->_currentScript; fp->localvars = g_lingo->_localvars; - // Clean up current scope local variables - for (SymbolHash::const_iterator h = g_lingo->_localvars->begin(); h != g_lingo->_localvars->end(); ++h) - g_lingo->_vars.erase(h->_key); - + // Create new set of local variables g_lingo->_localvars = new SymbolHash; g_lingo->_callstack.push_back(fp); @@ -426,17 +423,10 @@ void Lingo::c_procret() { g_lingo->_currentScript = fp->retscript; g_lingo->_pc = fp->retpc; - // Clean up current scope local variables and clean up memory - for (SymbolHash::const_iterator h = g_lingo->_localvars->begin(); h != g_lingo->_localvars->end(); ++h) { - g_lingo->_vars.erase(h->_key); - delete h->_value; - } - delete g_lingo->_localvars; + g_lingo->cleanLocalVars(); // Restore local variables g_lingo->_localvars = fp->localvars; - for (SymbolHash::const_iterator h = g_lingo->_localvars->begin(); h != g_lingo->_localvars->end(); ++h) - g_lingo->_vars[h->_key] = h->_value; delete fp; @@ -447,17 +437,11 @@ void Lingo::c_global() { Common::String name((char *)&(*g_lingo->_currentScript)[g_lingo->_pc]); Symbol *s = g_lingo->lookupVar(name.c_str(), false); - if (s) { - if (s->global) { - warning("Redefinition of global variable %s", name.c_str()); - } else { - warning("Local variable %s declared as global", name.c_str()); - } - - return; + if (s && !s->global) { + warning("Local variable %s declared as global", name.c_str()); } - s = g_lingo->lookupVar(name.c_str(), true, false); + s = g_lingo->lookupVar(name.c_str(), true, true); s->global = true; g_lingo->_pc += g_lingo->calcStringAlignment(name.c_str()); diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp index ae6242867aba..89d30bec4765 100644 --- a/engines/director/lingo/lingo-codegen.cpp +++ b/engines/director/lingo/lingo-codegen.cpp @@ -64,10 +64,10 @@ void Lingo::execute(int pc) { } } -Symbol *Lingo::lookupVar(const char *name, bool create, bool putInLocalList) { +Symbol *Lingo::lookupVar(const char *name, bool create, bool putInGlobalList) { Symbol *sym; - if (!_vars.contains(name)) { // Create variable if it was not defined + if (!_localvars->contains(name)) { // Create variable if it was not defined if (!create) return NULL; @@ -77,17 +77,31 @@ Symbol *Lingo::lookupVar(const char *name, bool create, bool putInLocalList) { sym->type = VOID; sym->u.val = 0; - _vars[name] = sym; + (*_localvars)[name] = sym; + + if (putInGlobalList) { + sym->global = true; + _globalvars[name] = sym; + } } else { - sym = g_lingo->_vars[name]; - } + sym = (*_localvars)[name]; - if (putInLocalList) - (*_localvars)[name] = sym; + if (sym->global) + sym = _globalvars[name]; + } return sym; } +void Lingo::cleanLocalVars() { + // Clean up current scope local variables and clean up memory + for (SymbolHash::const_iterator h = _localvars->begin(); h != _localvars->end(); ++h) { + if (!h->_value->global) + delete h->_value; + } + delete g_lingo->_localvars; +} + void Lingo::define(Common::String &name, int start, int nargs) { debug(3, "define(\"%s\", %d, %d, %d)", name.c_str(), start, _currentScript->size() - 1, nargs); diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp index accd9a113df4..e584ac02b909 100644 --- a/engines/director/lingo/lingo.cpp +++ b/engines/director/lingo/lingo.cpp @@ -167,7 +167,7 @@ void Lingo::executeScript(ScriptType type, uint16 id) { execute(_pc); - delete _localvars; + cleanLocalVars(); } void Lingo::processEvent(LEvent event, int entityId) { diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h index e30d8a465a9c..f9c58f0fa453 100644 --- a/engines/director/lingo/lingo.h +++ b/engines/director/lingo/lingo.h @@ -138,7 +138,8 @@ class Lingo { void execute(int pc); void pushContext(); void popContext(); - Symbol *lookupVar(const char *name, bool create = true, bool putInLocalList = true); + Symbol *lookupVar(const char *name, bool create = true, bool putInGlobalList = false); + void cleanLocalVars(); void define(Common::String &s, int start, int nargs); void codeArg(Common::String *s); void codeArgStore(); @@ -204,7 +205,7 @@ class Lingo { ScriptHash _scripts[kMaxScriptType + 1]; - SymbolHash _vars; + SymbolHash _globalvars; SymbolHash *_localvars; SymbolHash _handlers;