[Scummvm-git-logs] scummvm master -> 1efd5f5c11b5bfa00640f5b567fd7761bbcbb9d4

djsrv dservilla at gmail.com
Tue Jul 7 00:21:54 UTC 2020


This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
bcac706ead DIRECTOR: Move ObjectType to types.h
856cb27870 DIRECTOR: LINGO: Reorganize Object
1efd5f5c11 DIRECTOR: LINGO: Improve object refcounting


Commit: bcac706ead43cfa76964311529035c6e529c04e8
    https://github.com/scummvm/scummvm/commit/bcac706ead43cfa76964311529035c6e529c04e8
Author: djsrv (dservilla at gmail.com)
Date: 2020-07-06T20:18:57-04:00

Commit Message:
DIRECTOR: Move ObjectType to types.h

Changed paths:
    engines/director/lingo/lingo.h
    engines/director/types.h


diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index a6d09edf05..d3bcdb516f 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -211,15 +211,6 @@ private:
 	Datum _parentScript;
 };
 
-enum ObjectType {
-	kNoneObj = 0,
-	kFactoryObj = 1 << 0,
-	kXObj = 1 << 1,
-	kScriptObj = 1 << 2,
-	kXtraObj = 1 << 3,
-	kAllObj = kFactoryObj | kXObj | kScriptObj | kXtraObj
-};
-
 struct Object {
 	Common::String *name;
 	ObjectType type;
diff --git a/engines/director/types.h b/engines/director/types.h
index 923f506245..d8e8dd2c15 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -69,6 +69,15 @@ enum ScriptFlag {
 	kScriptFlagUnkF			= (1 << 0xf)
 };
 
+enum ObjectType {
+	kNoneObj = 0,
+	kFactoryObj = 1 << 0,
+	kXObj = 1 << 1,
+	kScriptObj = 1 << 2,
+	kXtraObj = 1 << 3,
+	kAllObj = kFactoryObj | kXObj | kScriptObj | kXtraObj
+};
+
 enum ShapeType {
 	kShapeRectangle = 1,
 	kShapeRoundRect = 2,


Commit: 856cb27870a8207962f7baa74a8b83d17c547cef
    https://github.com/scummvm/scummvm/commit/856cb27870a8207962f7baa74a8b83d17c547cef
Author: djsrv (dservilla at gmail.com)
Date: 2020-07-06T20:18:57-04:00

Commit Message:
DIRECTOR: LINGO: Reorganize Object

Changed paths:
    engines/director/lingo/lingo-builtins.cpp
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/lingo/lingo-code.cpp
    engines/director/lingo/lingo-codegen.cpp
    engines/director/lingo/lingo-gr.cpp
    engines/director/lingo/lingo-gr.h
    engines/director/lingo/lingo-gr.y
    engines/director/lingo/lingo-object.cpp
    engines/director/lingo/lingo-object.h
    engines/director/lingo/lingo-the.cpp
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h
    engines/director/lingo/xlibs/fileio.cpp


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index c2a6e5881c..d0ece1c429 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -39,6 +39,7 @@
 #include "director/lingo/lingo.h"
 #include "director/lingo/lingo-builtins.h"
 #include "director/lingo/lingo-code.h"
+#include "director/lingo/lingo-object.h"
 #include "director/lingo/lingo-gr.h"
 
 namespace Director {
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 0147410ca2..43c2099375 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -33,6 +33,7 @@
 #include "director/lingo/lingo-code.h"
 #include "director/lingo/lingo-builtins.h"
 #include "director/lingo/lingo-bytecode.h"
+#include "director/lingo/lingo-object.h"
 #include "director/lingo/lingo-the.h"
 #include "director/lingo/lingo-gr.h"
 
@@ -582,7 +583,7 @@ void LC::cb_theassign() {
 	Datum value = g_lingo->pop();
 	if (g_lingo->_currentMe.type == OBJECT) {
 		if (g_lingo->_currentMe.u.obj->hasProp(name)) {
-			g_lingo->_currentMe.u.obj->getProp(name) = value;
+			g_lingo->_currentMe.u.obj->setProp(name, value);
 		} else {
 			warning("cb_theassign: me object has no property '%s'", name.c_str());
 		}
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 5f6dc5a644..894a4df3cd 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -49,6 +49,7 @@
 #include "director/util.h"
 #include "director/lingo/lingo.h"
 #include "director/lingo/lingo-code.h"
+#include "director/lingo/lingo-object.h"
 #include "director/lingo/lingo-the.h"
 #include "director/lingo/lingo-gr.h"
 
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index f3435d55d3..c90d830d81 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -48,6 +48,7 @@
 #include "director/director.h"
 #include "director/lingo/lingo.h"
 #include "director/lingo/lingo-code.h"
+#include "director/lingo/lingo-object.h"
 #include "director/lingo/lingo-gr.h"
 
 namespace Director {
diff --git a/engines/director/lingo/lingo-gr.cpp b/engines/director/lingo/lingo-gr.cpp
index 6fca02a75d..38837d1d4c 100644
--- a/engines/director/lingo/lingo-gr.cpp
+++ b/engines/director/lingo/lingo-gr.cpp
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 3.6.3.  */
+/* A Bison parser, made by GNU Bison 3.6.4.  */
 
 /* Bison implementation for Yacc-like parsers in C
 
@@ -49,7 +49,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "3.6.3"
+#define YYBISON_VERSION "3.6.4"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -79,6 +79,7 @@
 #include "director/lingo/lingo.h"
 #include "director/lingo/lingo-code.h"
 #include "director/lingo/lingo-gr.h"
+#include "director/lingo/lingo-object.h"
 
 extern int yylex();
 extern int yyparse();
@@ -180,7 +181,7 @@ static void mVar(Common::String *s, VarType type) {
 }
 
 
-#line 184 "engines/director/lingo/lingo-gr.cpp"
+#line 185 "engines/director/lingo/lingo-gr.cpp"
 
 # ifndef YY_CAST
 #  ifdef __cplusplus
@@ -316,7 +317,7 @@ extern int yydebug;
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 union YYSTYPE
 {
-#line 167 "engines/director/lingo/lingo-gr.y"
+#line 168 "engines/director/lingo/lingo-gr.y"
 
 	Common::String *s;
 	int i;
@@ -331,7 +332,7 @@ union YYSTYPE
 		Common::String *prop;
 	} objectprop;
 
-#line 335 "engines/director/lingo/lingo-gr.cpp"
+#line 336 "engines/director/lingo/lingo-gr.cpp"
 
 };
 typedef union YYSTYPE YYSTYPE;
@@ -885,25 +886,25 @@ static const yytype_int8 yytranslate[] =
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_int16 yyrline[] =
 {
-       0,   219,   219,   220,   222,   223,   224,   226,   233,   237,
-     248,   255,   258,   265,   268,   275,   282,   289,   296,   302,
-     309,   320,   331,   338,   346,   347,   348,   350,   351,   356,
-     369,   373,   376,   368,   403,   407,   410,   402,   437,   444,
-     450,   436,   480,   488,   491,   492,   494,   496,   498,   505,
-     513,   514,   516,   522,   526,   530,   534,   537,   539,   540,
-     541,   543,   546,   549,   553,   557,   561,   569,   575,   576,
-     577,   588,   589,   590,   593,   596,   602,   602,   607,   610,
-     613,   619,   620,   621,   622,   623,   624,   625,   626,   627,
-     628,   629,   630,   631,   632,   633,   634,   635,   636,   637,
-     638,   639,   640,   641,   643,   644,   645,   646,   647,   648,
-     649,   650,   652,   655,   657,   658,   659,   660,   668,   669,
-     669,   670,   670,   671,   671,   672,   675,   678,   679,   681,
-     684,   688,   691,   695,   698,   709,   710,   711,   712,   716,
-     720,   725,   726,   728,   732,   736,   740,   740,   770,   770,
-     770,   776,   777,   777,   783,   791,   797,   797,   800,   801,
-     802,   804,   805,   806,   808,   810,   818,   819,   820,   822,
-     823,   825,   827,   828,   829,   830,   832,   833,   835,   836,
-     838,   842,   846
+       0,   220,   220,   221,   223,   224,   225,   227,   234,   238,
+     249,   256,   259,   266,   269,   276,   283,   290,   297,   303,
+     310,   321,   332,   339,   347,   348,   349,   351,   352,   357,
+     370,   374,   377,   369,   404,   408,   411,   403,   438,   445,
+     451,   437,   481,   489,   492,   493,   495,   497,   499,   506,
+     514,   515,   517,   523,   527,   531,   535,   538,   540,   541,
+     542,   544,   547,   550,   554,   558,   562,   570,   576,   577,
+     578,   589,   590,   591,   594,   597,   603,   603,   608,   611,
+     614,   620,   621,   622,   623,   624,   625,   626,   627,   628,
+     629,   630,   631,   632,   633,   634,   635,   636,   637,   638,
+     639,   640,   641,   642,   644,   645,   646,   647,   648,   649,
+     650,   651,   653,   656,   658,   659,   660,   661,   669,   670,
+     670,   671,   671,   672,   672,   673,   676,   679,   680,   682,
+     685,   689,   692,   696,   699,   710,   711,   712,   713,   717,
+     721,   726,   727,   729,   733,   737,   741,   741,   771,   771,
+     771,   777,   778,   778,   784,   792,   798,   798,   801,   802,
+     803,   805,   806,   807,   809,   811,   819,   820,   821,   823,
+     824,   826,   828,   829,   830,   831,   833,   834,   836,   837,
+     839,   843,   847
 };
 #endif
 
@@ -1986,75 +1987,75 @@ yydestruct (const char *yymsg,
   switch (yykind)
     {
     case 22: /* BLTIN  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 1992 "engines/director/lingo/lingo-gr.cpp"
+#line 1993 "engines/director/lingo/lingo-gr.cpp"
         break;
 
     case 23: /* FBLTIN  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 1998 "engines/director/lingo/lingo-gr.cpp"
+#line 1999 "engines/director/lingo/lingo-gr.cpp"
         break;
 
     case 24: /* RBLTIN  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 2004 "engines/director/lingo/lingo-gr.cpp"
+#line 2005 "engines/director/lingo/lingo-gr.cpp"
         break;
 
     case 25: /* THEFBLTIN  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 2010 "engines/director/lingo/lingo-gr.cpp"
+#line 2011 "engines/director/lingo/lingo-gr.cpp"
         break;
 
     case 26: /* ID  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 2016 "engines/director/lingo/lingo-gr.cpp"
+#line 2017 "engines/director/lingo/lingo-gr.cpp"
         break;
 
     case 27: /* STRING  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 2022 "engines/director/lingo/lingo-gr.cpp"
+#line 2023 "engines/director/lingo/lingo-gr.cpp"
         break;
 
     case 28: /* HANDLER  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 2028 "engines/director/lingo/lingo-gr.cpp"
+#line 2029 "engines/director/lingo/lingo-gr.cpp"
         break;
 
     case 29: /* SYMBOL  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 2034 "engines/director/lingo/lingo-gr.cpp"
+#line 2035 "engines/director/lingo/lingo-gr.cpp"
         break;
 
     case 30: /* ENDCLAUSE  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 2040 "engines/director/lingo/lingo-gr.cpp"
+#line 2041 "engines/director/lingo/lingo-gr.cpp"
         break;
 
     case 31: /* tPLAYACCEL  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 2046 "engines/director/lingo/lingo-gr.cpp"
+#line 2047 "engines/director/lingo/lingo-gr.cpp"
         break;
 
     case 32: /* tMETHOD  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 2052 "engines/director/lingo/lingo-gr.cpp"
+#line 2053 "engines/director/lingo/lingo-gr.cpp"
         break;
 
     case 148: /* on  */
-#line 215 "engines/director/lingo/lingo-gr.y"
+#line 216 "engines/director/lingo/lingo-gr.y"
             { delete ((*yyvaluep).s); }
-#line 2058 "engines/director/lingo/lingo-gr.cpp"
+#line 2059 "engines/director/lingo/lingo-gr.cpp"
         break;
 
       default:
@@ -2333,7 +2334,7 @@ yyreduce:
   switch (yyn)
     {
   case 7:
-#line 226 "engines/director/lingo/lingo-gr.y"
+#line 227 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->code1(LC::c_varpush);
 		g_lingo->codeString((yyvsp[0].s)->c_str());
@@ -2341,19 +2342,19 @@ yyreduce:
 		g_lingo->code1(LC::c_assign);
 		(yyval.code) = (yyvsp[-2].code);
 		delete (yyvsp[0].s); }
-#line 2345 "engines/director/lingo/lingo-gr.cpp"
+#line 2346 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 8:
-#line 233 "engines/director/lingo/lingo-gr.y"
+#line 234 "engines/director/lingo/lingo-gr.y"
                                                 {
 		g_lingo->code1(LC::c_assign);
 		(yyval.code) = (yyvsp[-2].code); }
-#line 2353 "engines/director/lingo/lingo-gr.cpp"
+#line 2354 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 9:
-#line 237 "engines/director/lingo/lingo-gr.y"
+#line 238 "engines/director/lingo/lingo-gr.y"
                                                                 {
 		if (!(yyvsp[-3].s)->equalsIgnoreCase("menu")) {
 			warning("LEXER: keyword 'menu' expected");
@@ -2365,11 +2366,11 @@ yyreduce:
 		g_lingo->codeInt((yyvsp[-4].e)[1]);
 		g_lingo->code1(LC::c_assign);
 		(yyval.code) = (yyvsp[0].code); }
-#line 2369 "engines/director/lingo/lingo-gr.cpp"
+#line 2370 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 10:
-#line 248 "engines/director/lingo/lingo-gr.y"
+#line 249 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->code1(LC::c_varpush);
 		g_lingo->codeString((yyvsp[0].s)->c_str());
@@ -2377,19 +2378,19 @@ yyreduce:
 		g_lingo->code1(LC::c_after);
 		(yyval.code) = (yyvsp[-2].code);
 		delete (yyvsp[0].s); }
-#line 2381 "engines/director/lingo/lingo-gr.cpp"
+#line 2382 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 11:
-#line 255 "engines/director/lingo/lingo-gr.y"
+#line 256 "engines/director/lingo/lingo-gr.y"
                                                 {
 		g_lingo->code1(LC::c_after);
 		(yyval.code) = (yyvsp[-2].code); }
-#line 2389 "engines/director/lingo/lingo-gr.cpp"
+#line 2390 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 12:
-#line 258 "engines/director/lingo/lingo-gr.y"
+#line 259 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->code1(LC::c_varpush);
 		g_lingo->codeString((yyvsp[0].s)->c_str());
@@ -2397,19 +2398,19 @@ yyreduce:
 		g_lingo->code1(LC::c_before);
 		(yyval.code) = (yyvsp[-2].code);
 		delete (yyvsp[0].s); }
-#line 2401 "engines/director/lingo/lingo-gr.cpp"
+#line 2402 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 13:
-#line 265 "engines/director/lingo/lingo-gr.y"
+#line 266 "engines/director/lingo/lingo-gr.y"
                                                 {
 		g_lingo->code1(LC::c_before);
 		(yyval.code) = (yyvsp[-2].code); }
-#line 2409 "engines/director/lingo/lingo-gr.cpp"
+#line 2410 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 14:
-#line 268 "engines/director/lingo/lingo-gr.y"
+#line 269 "engines/director/lingo/lingo-gr.y"
                                                 {
 		g_lingo->code1(LC::c_varpush);
 		g_lingo->codeString((yyvsp[-2].s)->c_str());
@@ -2417,11 +2418,11 @@ yyreduce:
 		g_lingo->code1(LC::c_assign);
 		(yyval.code) = (yyvsp[0].code);
 		delete (yyvsp[-2].s); }
-#line 2421 "engines/director/lingo/lingo-gr.cpp"
+#line 2422 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 15:
-#line 275 "engines/director/lingo/lingo-gr.y"
+#line 276 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->code1(LC::c_intpush);
 		g_lingo->codeInt(0); // Put dummy id
@@ -2429,11 +2430,11 @@ yyreduce:
 		g_lingo->codeInt((yyvsp[-2].e)[0]);
 		g_lingo->codeInt((yyvsp[-2].e)[1]);
 		(yyval.code) = (yyvsp[0].code); }
-#line 2433 "engines/director/lingo/lingo-gr.cpp"
+#line 2434 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 16:
-#line 282 "engines/director/lingo/lingo-gr.y"
+#line 283 "engines/director/lingo/lingo-gr.y"
                                                 {
 		g_lingo->code1(LC::c_varpush);
 		g_lingo->codeString((yyvsp[-2].s)->c_str());
@@ -2441,11 +2442,11 @@ yyreduce:
 		g_lingo->code1(LC::c_assign);
 		(yyval.code) = (yyvsp[0].code);
 		delete (yyvsp[-2].s); }
-#line 2445 "engines/director/lingo/lingo-gr.cpp"
+#line 2446 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 17:
-#line 289 "engines/director/lingo/lingo-gr.y"
+#line 290 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->code1(LC::c_intpush);
 		g_lingo->codeInt(0); // Put dummy id
@@ -2453,33 +2454,33 @@ yyreduce:
 		g_lingo->codeInt((yyvsp[-2].e)[0]);
 		g_lingo->codeInt((yyvsp[-2].e)[1]);
 		(yyval.code) = (yyvsp[0].code); }
-#line 2457 "engines/director/lingo/lingo-gr.cpp"
+#line 2458 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 18:
-#line 296 "engines/director/lingo/lingo-gr.y"
+#line 297 "engines/director/lingo/lingo-gr.y"
                                                         {
 		g_lingo->code1(LC::c_swap);
 		g_lingo->code1(LC::c_theentityassign);
 		g_lingo->codeInt((yyvsp[-3].e)[0]);
 		g_lingo->codeInt((yyvsp[-3].e)[1]);
 		(yyval.code) = (yyvsp[0].code); }
-#line 2468 "engines/director/lingo/lingo-gr.cpp"
+#line 2469 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 19:
-#line 302 "engines/director/lingo/lingo-gr.y"
+#line 303 "engines/director/lingo/lingo-gr.y"
                                                         {
 		g_lingo->code1(LC::c_swap);
 		g_lingo->code1(LC::c_theentityassign);
 		g_lingo->codeInt((yyvsp[-3].e)[0]);
 		g_lingo->codeInt((yyvsp[-3].e)[1]);
 		(yyval.code) = (yyvsp[0].code); }
-#line 2479 "engines/director/lingo/lingo-gr.cpp"
+#line 2480 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 20:
-#line 309 "engines/director/lingo/lingo-gr.y"
+#line 310 "engines/director/lingo/lingo-gr.y"
                                                                         {
 		if (!(yyvsp[-3].s)->equalsIgnoreCase("menu")) {
 			warning("LEXER: keyword 'menu' expected");
@@ -2491,11 +2492,11 @@ yyreduce:
 		g_lingo->codeInt((yyvsp[-6].e)[0]);
 		g_lingo->codeInt((yyvsp[-6].e)[1]);
 		(yyval.code) = (yyvsp[0].code); }
-#line 2495 "engines/director/lingo/lingo-gr.cpp"
+#line 2496 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 21:
-#line 320 "engines/director/lingo/lingo-gr.y"
+#line 321 "engines/director/lingo/lingo-gr.y"
                                                                         {
 		if (!(yyvsp[-3].s)->equalsIgnoreCase("menu")) {
 			warning("LEXER: keyword 'menu' expected");
@@ -2507,11 +2508,11 @@ yyreduce:
 		g_lingo->codeInt((yyvsp[-6].e)[0]);
 		g_lingo->codeInt((yyvsp[-6].e)[1]);
 		(yyval.code) = (yyvsp[0].code); }
-#line 2511 "engines/director/lingo/lingo-gr.cpp"
+#line 2512 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 22:
-#line 331 "engines/director/lingo/lingo-gr.y"
+#line 332 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->code1(LC::c_objectpropassign);
 		g_lingo->codeString((yyvsp[-2].objectprop).obj->c_str());
@@ -2519,11 +2520,11 @@ yyreduce:
 		delete (yyvsp[-2].objectprop).obj;
 		delete (yyvsp[-2].objectprop).prop;
 		(yyval.code) = (yyvsp[0].code); }
-#line 2523 "engines/director/lingo/lingo-gr.cpp"
+#line 2524 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 23:
-#line 338 "engines/director/lingo/lingo-gr.y"
+#line 339 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->code1(LC::c_objectpropassign);
 		g_lingo->codeString((yyvsp[-2].objectprop).obj->c_str());
@@ -2531,11 +2532,11 @@ yyreduce:
 		delete (yyvsp[-2].objectprop).obj;
 		delete (yyvsp[-2].objectprop).prop;
 		(yyval.code) = (yyvsp[0].code); }
-#line 2535 "engines/director/lingo/lingo-gr.cpp"
+#line 2536 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 29:
-#line 356 "engines/director/lingo/lingo-gr.y"
+#line 357 "engines/director/lingo/lingo-gr.y"
                                                                                                 {
 		inst start = 0, end = 0;
 		WRITE_UINT32(&start, (yyvsp[-6].code) - (yyvsp[-1].code) + 1);
@@ -2543,32 +2544,32 @@ yyreduce:
 		(*g_lingo->_currentAssembly)[(yyvsp[-4].code)] = end;		/* end, if cond fails */
 		(*g_lingo->_currentAssembly)[(yyvsp[-1].code)] = start;	/* looping back */
 		endRepeat((yyvsp[-1].code) + 1, (yyvsp[-6].code));	}
-#line 2547 "engines/director/lingo/lingo-gr.cpp"
+#line 2548 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 30:
-#line 369 "engines/director/lingo/lingo-gr.y"
+#line 370 "engines/director/lingo/lingo-gr.y"
                                 { g_lingo->code1(LC::c_varpush);
 				  g_lingo->codeString((yyvsp[-2].s)->c_str());
 				  mVar((yyvsp[-2].s), globalCheck()); }
-#line 2555 "engines/director/lingo/lingo-gr.cpp"
+#line 2556 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 31:
-#line 373 "engines/director/lingo/lingo-gr.y"
+#line 374 "engines/director/lingo/lingo-gr.y"
                                 { g_lingo->code1(LC::c_eval);
 				  g_lingo->codeString((yyvsp[-4].s)->c_str()); }
-#line 2562 "engines/director/lingo/lingo-gr.cpp"
+#line 2563 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 32:
-#line 376 "engines/director/lingo/lingo-gr.y"
+#line 377 "engines/director/lingo/lingo-gr.y"
                                 { g_lingo->code1(LC::c_le); }
-#line 2568 "engines/director/lingo/lingo-gr.cpp"
+#line 2569 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 33:
-#line 376 "engines/director/lingo/lingo-gr.y"
+#line 377 "engines/director/lingo/lingo-gr.y"
                                                                                                       {
 
 		int nextPos = g_lingo->_currentAssembly->size();
@@ -2589,32 +2590,32 @@ yyreduce:
 		(*g_lingo->_currentAssembly)[pos] = loop;		/* final count value */
 		(*g_lingo->_currentAssembly)[(yyvsp[-3].code)] = end;	/* end, if cond fails */
 		endRepeat(pos + 1, nextPos); }
-#line 2593 "engines/director/lingo/lingo-gr.cpp"
+#line 2594 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 34:
-#line 403 "engines/director/lingo/lingo-gr.y"
+#line 404 "engines/director/lingo/lingo-gr.y"
                                 { g_lingo->code1(LC::c_varpush);
 				  g_lingo->codeString((yyvsp[-2].s)->c_str());
 				  mVar((yyvsp[-2].s), globalCheck()); }
-#line 2601 "engines/director/lingo/lingo-gr.cpp"
+#line 2602 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 35:
-#line 407 "engines/director/lingo/lingo-gr.y"
+#line 408 "engines/director/lingo/lingo-gr.y"
                                 { g_lingo->code1(LC::c_eval);
 				  g_lingo->codeString((yyvsp[-4].s)->c_str()); }
-#line 2608 "engines/director/lingo/lingo-gr.cpp"
+#line 2609 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 36:
-#line 410 "engines/director/lingo/lingo-gr.y"
+#line 411 "engines/director/lingo/lingo-gr.y"
                                 { g_lingo->code1(LC::c_ge); }
-#line 2614 "engines/director/lingo/lingo-gr.cpp"
+#line 2615 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 37:
-#line 411 "engines/director/lingo/lingo-gr.y"
+#line 412 "engines/director/lingo/lingo-gr.y"
                                                                 {
 
 		int nextPos = g_lingo->_currentAssembly->size();
@@ -2635,32 +2636,32 @@ yyreduce:
 		(*g_lingo->_currentAssembly)[pos] = loop;		/* final count value */
 		(*g_lingo->_currentAssembly)[(yyvsp[-3].code)] = end;	/* end, if cond fails */
 		endRepeat(pos + 1, nextPos); }
-#line 2639 "engines/director/lingo/lingo-gr.cpp"
+#line 2640 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 38:
-#line 437 "engines/director/lingo/lingo-gr.y"
+#line 438 "engines/director/lingo/lingo-gr.y"
                                 { g_lingo->code1(LC::c_stackpeek);
 				  g_lingo->codeInt(0);
 				  Common::String count("count");
 				  g_lingo->codeFunc(&count, 1);
 				  g_lingo->code1(LC::c_intpush);	// start counter
 				  g_lingo->codeInt(1); }
-#line 2650 "engines/director/lingo/lingo-gr.cpp"
+#line 2651 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 39:
-#line 444 "engines/director/lingo/lingo-gr.y"
+#line 445 "engines/director/lingo/lingo-gr.y"
                                 { g_lingo->code1(LC::c_stackpeek);	// get counter
 				  g_lingo->codeInt(0);
 				  g_lingo->code1(LC::c_stackpeek);	// get array size
 				  g_lingo->codeInt(2);
 				  g_lingo->code1(LC::c_le); }
-#line 2660 "engines/director/lingo/lingo-gr.cpp"
+#line 2661 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 40:
-#line 450 "engines/director/lingo/lingo-gr.y"
+#line 451 "engines/director/lingo/lingo-gr.y"
                                 { g_lingo->code1(LC::c_stackpeek);	// get list
 				  g_lingo->codeInt(2);
 				  g_lingo->code1(LC::c_stackpeek);	// get counter
@@ -2671,11 +2672,11 @@ yyreduce:
 				  g_lingo->codeString((yyvsp[-6].s)->c_str());
 				  mVar((yyvsp[-6].s), globalCheck());
 				  g_lingo->code1(LC::c_assign); }
-#line 2675 "engines/director/lingo/lingo-gr.cpp"
+#line 2676 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 41:
-#line 460 "engines/director/lingo/lingo-gr.y"
+#line 461 "engines/director/lingo/lingo-gr.y"
                                                         {
 
 		int nextPos = g_lingo->_currentAssembly->size();
@@ -2695,11 +2696,11 @@ yyreduce:
 		(*g_lingo->_currentAssembly)[jump + 1] = loop;		/* final count value */
 		(*g_lingo->_currentAssembly)[(yyvsp[-4].code)] = end;		/* end, if cond fails */
 		endRepeat(end2, nextPos); }
-#line 2699 "engines/director/lingo/lingo-gr.cpp"
+#line 2700 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 42:
-#line 480 "engines/director/lingo/lingo-gr.y"
+#line 481 "engines/director/lingo/lingo-gr.y"
                         {
 		if (g_lingo->_repeatStack.size()) {
 			g_lingo->code2(LC::c_jump, 0);
@@ -2708,43 +2709,43 @@ yyreduce:
 		} else {
 			warning("# LINGO: next repeat not inside repeat block");
 		} }
-#line 2712 "engines/director/lingo/lingo-gr.cpp"
+#line 2713 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 43:
-#line 488 "engines/director/lingo/lingo-gr.y"
+#line 489 "engines/director/lingo/lingo-gr.y"
                               {
 		g_lingo->code1(LC::c_whencode);
 		g_lingo->codeString((yyvsp[-2].s)->c_str()); }
-#line 2720 "engines/director/lingo/lingo-gr.cpp"
+#line 2721 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 44:
-#line 491 "engines/director/lingo/lingo-gr.y"
+#line 492 "engines/director/lingo/lingo-gr.y"
                                                           { g_lingo->code1(LC::c_telldone); }
-#line 2726 "engines/director/lingo/lingo-gr.cpp"
+#line 2727 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 45:
-#line 492 "engines/director/lingo/lingo-gr.y"
+#line 493 "engines/director/lingo/lingo-gr.y"
                                                     { g_lingo->code1(LC::c_telldone); }
-#line 2732 "engines/director/lingo/lingo-gr.cpp"
+#line 2733 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 46:
-#line 494 "engines/director/lingo/lingo-gr.y"
+#line 495 "engines/director/lingo/lingo-gr.y"
                                 { startRepeat(); }
-#line 2738 "engines/director/lingo/lingo-gr.cpp"
+#line 2739 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 47:
-#line 496 "engines/director/lingo/lingo-gr.y"
+#line 497 "engines/director/lingo/lingo-gr.y"
                                 { g_lingo->code1(LC::c_tell); }
-#line 2744 "engines/director/lingo/lingo-gr.cpp"
+#line 2745 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 48:
-#line 498 "engines/director/lingo/lingo-gr.y"
+#line 499 "engines/director/lingo/lingo-gr.y"
                                                                                          {
 		inst else1 = 0, end3 = 0;
 		WRITE_UINT32(&else1, (yyvsp[-3].code) + 1 - (yyvsp[-6].code) + 1);
@@ -2752,11 +2753,11 @@ yyreduce:
 		(*g_lingo->_currentAssembly)[(yyvsp[-6].code)] = else1;		/* elsepart */
 		(*g_lingo->_currentAssembly)[(yyvsp[-3].code)] = end3;		/* end, if cond fails */
 		g_lingo->processIf((yyvsp[-3].code), (yyvsp[-1].code)); }
-#line 2756 "engines/director/lingo/lingo-gr.cpp"
+#line 2757 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 49:
-#line 505 "engines/director/lingo/lingo-gr.y"
+#line 506 "engines/director/lingo/lingo-gr.y"
                                                                                                           {
 		inst else1 = 0, end = 0;
 		WRITE_UINT32(&else1, (yyvsp[-5].code) + 1 - (yyvsp[-8].code) + 1);
@@ -2764,107 +2765,107 @@ yyreduce:
 		(*g_lingo->_currentAssembly)[(yyvsp[-8].code)] = else1;		/* elsepart */
 		(*g_lingo->_currentAssembly)[(yyvsp[-5].code)] = end;		/* end, if cond fails */
 		g_lingo->processIf((yyvsp[-5].code), (yyvsp[-1].code)); }
-#line 2768 "engines/director/lingo/lingo-gr.cpp"
+#line 2769 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 52:
-#line 516 "engines/director/lingo/lingo-gr.y"
+#line 517 "engines/director/lingo/lingo-gr.y"
                                                                 {
 		inst else1 = 0;
 		WRITE_UINT32(&else1, (yyvsp[0].code) + 1 - (yyvsp[-3].code) + 1);
 		(*g_lingo->_currentAssembly)[(yyvsp[-3].code)] = else1;	/* end, if cond fails */
 		g_lingo->codeLabel((yyvsp[0].code)); }
-#line 2778 "engines/director/lingo/lingo-gr.cpp"
+#line 2779 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 53:
-#line 522 "engines/director/lingo/lingo-gr.y"
+#line 523 "engines/director/lingo/lingo-gr.y"
                                 {
 		g_lingo->code2(LC::c_jumpifz, 0);
 		(yyval.code) = g_lingo->_currentAssembly->size() - 1; }
-#line 2786 "engines/director/lingo/lingo-gr.cpp"
+#line 2787 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 54:
-#line 526 "engines/director/lingo/lingo-gr.y"
+#line 527 "engines/director/lingo/lingo-gr.y"
                                 {
 		g_lingo->code2(LC::c_jump, 0);
 		(yyval.code) = g_lingo->_currentAssembly->size() - 1; }
-#line 2794 "engines/director/lingo/lingo-gr.cpp"
+#line 2795 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 55:
-#line 530 "engines/director/lingo/lingo-gr.y"
+#line 531 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->code1(LC::c_assign);
 		(yyval.code) = g_lingo->_currentAssembly->size() - 1; }
-#line 2802 "engines/director/lingo/lingo-gr.cpp"
+#line 2803 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 56:
-#line 534 "engines/director/lingo/lingo-gr.y"
+#line 535 "engines/director/lingo/lingo-gr.y"
                                                 {
 		g_lingo->codeLabel(0); }
-#line 2809 "engines/director/lingo/lingo-gr.cpp"
+#line 2810 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 57:
-#line 537 "engines/director/lingo/lingo-gr.y"
+#line 538 "engines/director/lingo/lingo-gr.y"
                                 { (yyval.code) = g_lingo->_currentAssembly->size(); }
-#line 2815 "engines/director/lingo/lingo-gr.cpp"
+#line 2816 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 58:
-#line 539 "engines/director/lingo/lingo-gr.y"
+#line 540 "engines/director/lingo/lingo-gr.y"
                                                 { (yyval.code) = g_lingo->_currentAssembly->size(); }
-#line 2821 "engines/director/lingo/lingo-gr.cpp"
+#line 2822 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 61:
-#line 543 "engines/director/lingo/lingo-gr.y"
+#line 544 "engines/director/lingo/lingo-gr.y"
                         {
 		(yyval.code) = g_lingo->code1(LC::c_intpush);
 		g_lingo->codeInt((yyvsp[0].i)); }
-#line 2829 "engines/director/lingo/lingo-gr.cpp"
+#line 2830 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 62:
-#line 546 "engines/director/lingo/lingo-gr.y"
+#line 547 "engines/director/lingo/lingo-gr.y"
                         {
 		(yyval.code) = g_lingo->code1(LC::c_floatpush);
 		g_lingo->codeFloat((yyvsp[0].f)); }
-#line 2837 "engines/director/lingo/lingo-gr.cpp"
+#line 2838 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 63:
-#line 549 "engines/director/lingo/lingo-gr.y"
+#line 550 "engines/director/lingo/lingo-gr.y"
                         {											// D3
 		(yyval.code) = g_lingo->code1(LC::c_symbolpush);
 		g_lingo->codeString((yyvsp[0].s)->c_str());
 		delete (yyvsp[0].s); }
-#line 2846 "engines/director/lingo/lingo-gr.cpp"
+#line 2847 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 64:
-#line 553 "engines/director/lingo/lingo-gr.y"
+#line 554 "engines/director/lingo/lingo-gr.y"
                                 {
 		(yyval.code) = g_lingo->code1(LC::c_stringpush);
 		g_lingo->codeString((yyvsp[0].s)->c_str());
 		delete (yyvsp[0].s); }
-#line 2855 "engines/director/lingo/lingo-gr.cpp"
+#line 2856 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 65:
-#line 557 "engines/director/lingo/lingo-gr.y"
+#line 558 "engines/director/lingo/lingo-gr.y"
                         {
 		(yyval.code) = g_lingo->code1(LC::c_eval);
 		g_lingo->codeString((yyvsp[0].s)->c_str());
 		delete (yyvsp[0].s); }
-#line 2864 "engines/director/lingo/lingo-gr.cpp"
+#line 2865 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 66:
-#line 561 "engines/director/lingo/lingo-gr.y"
+#line 562 "engines/director/lingo/lingo-gr.y"
                         {
 		(yyval.code) = g_lingo->code1(LC::c_intpush);
 		g_lingo->codeInt(0); // Put dummy id
@@ -2873,28 +2874,28 @@ yyreduce:
 		WRITE_UINT32(&e, (yyvsp[0].e)[0]);
 		WRITE_UINT32(&f, (yyvsp[0].e)[1]);
 		g_lingo->code2(e, f); }
-#line 2877 "engines/director/lingo/lingo-gr.cpp"
+#line 2878 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 67:
-#line 569 "engines/director/lingo/lingo-gr.y"
+#line 570 "engines/director/lingo/lingo-gr.y"
                                      {
 		(yyval.code) = g_lingo->code1(LC::c_theentitypush);
 		inst e = 0, f = 0;
 		WRITE_UINT32(&e, (yyvsp[-1].e)[0]);
 		WRITE_UINT32(&f, (yyvsp[-1].e)[1]);
 		g_lingo->code2(e, f); }
-#line 2888 "engines/director/lingo/lingo-gr.cpp"
+#line 2889 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 68:
-#line 575 "engines/director/lingo/lingo-gr.y"
+#line 576 "engines/director/lingo/lingo-gr.y"
                                                 { (yyval.code) = (yyvsp[-1].code); }
-#line 2894 "engines/director/lingo/lingo-gr.cpp"
+#line 2895 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 70:
-#line 577 "engines/director/lingo/lingo-gr.y"
+#line 578 "engines/director/lingo/lingo-gr.y"
                                 {
 		// Director parser till D3 was forgiving for any hanging parentheses
 		if (g_lingo->_ignoreError) {
@@ -2905,280 +2906,280 @@ yyreduce:
 			yyerrok;
 		}
 	}
-#line 2909 "engines/director/lingo/lingo-gr.cpp"
+#line 2910 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 71:
-#line 588 "engines/director/lingo/lingo-gr.y"
+#line 589 "engines/director/lingo/lingo-gr.y"
                  { (yyval.code) = (yyvsp[0].code); }
-#line 2915 "engines/director/lingo/lingo-gr.cpp"
+#line 2916 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 73:
-#line 590 "engines/director/lingo/lingo-gr.y"
+#line 591 "engines/director/lingo/lingo-gr.y"
                                  {
 		g_lingo->codeFunc((yyvsp[-3].s), (yyvsp[-1].narg));
 		delete (yyvsp[-3].s); }
-#line 2923 "engines/director/lingo/lingo-gr.cpp"
+#line 2924 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 74:
-#line 593 "engines/director/lingo/lingo-gr.y"
+#line 594 "engines/director/lingo/lingo-gr.y"
                                 {
 		g_lingo->codeFunc((yyvsp[-1].s), (yyvsp[0].narg));
 		delete (yyvsp[-1].s); }
-#line 2931 "engines/director/lingo/lingo-gr.cpp"
+#line 2932 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 75:
-#line 596 "engines/director/lingo/lingo-gr.y"
+#line 597 "engines/director/lingo/lingo-gr.y"
                                       {
 			g_lingo->code1(LC::c_lazyeval);
 			g_lingo->codeString((yyvsp[-1].s)->c_str());
 			g_lingo->codeFunc((yyvsp[-3].s), 1);
 			delete (yyvsp[-3].s);
 			delete (yyvsp[-1].s); }
-#line 2942 "engines/director/lingo/lingo-gr.cpp"
+#line 2943 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 76:
-#line 602 "engines/director/lingo/lingo-gr.y"
+#line 603 "engines/director/lingo/lingo-gr.y"
                                       { g_lingo->code1(LC::c_lazyeval); g_lingo->codeString((yyvsp[-1].s)->c_str()); }
-#line 2948 "engines/director/lingo/lingo-gr.cpp"
+#line 2949 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 77:
-#line 603 "engines/director/lingo/lingo-gr.y"
+#line 604 "engines/director/lingo/lingo-gr.y"
                                                     {
 			g_lingo->codeFunc((yyvsp[-6].s), (yyvsp[-1].narg) + 1);
 			delete (yyvsp[-6].s);
 			delete (yyvsp[-4].s); }
-#line 2957 "engines/director/lingo/lingo-gr.cpp"
+#line 2958 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 78:
-#line 607 "engines/director/lingo/lingo-gr.y"
+#line 608 "engines/director/lingo/lingo-gr.y"
                                 {
 		(yyval.code) = g_lingo->codeFunc((yyvsp[-3].s), (yyvsp[-1].narg));
 		delete (yyvsp[-3].s); }
-#line 2965 "engines/director/lingo/lingo-gr.cpp"
+#line 2966 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 79:
-#line 610 "engines/director/lingo/lingo-gr.y"
+#line 611 "engines/director/lingo/lingo-gr.y"
                                         {
 		(yyval.code) = g_lingo->codeFunc((yyvsp[-2].s), 1);
 		delete (yyvsp[-2].s); }
-#line 2973 "engines/director/lingo/lingo-gr.cpp"
+#line 2974 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 80:
-#line 613 "engines/director/lingo/lingo-gr.y"
+#line 614 "engines/director/lingo/lingo-gr.y"
                         {
 		g_lingo->code1(LC::c_objectproppush);
 		g_lingo->codeString((yyvsp[0].objectprop).obj->c_str());
 		g_lingo->codeString((yyvsp[0].objectprop).prop->c_str());
 		delete (yyvsp[0].objectprop).obj;
 		delete (yyvsp[0].objectprop).prop; }
-#line 2984 "engines/director/lingo/lingo-gr.cpp"
+#line 2985 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 82:
-#line 620 "engines/director/lingo/lingo-gr.y"
+#line 621 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_add); }
-#line 2990 "engines/director/lingo/lingo-gr.cpp"
+#line 2991 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 83:
-#line 621 "engines/director/lingo/lingo-gr.y"
+#line 622 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_sub); }
-#line 2996 "engines/director/lingo/lingo-gr.cpp"
+#line 2997 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 84:
-#line 622 "engines/director/lingo/lingo-gr.y"
+#line 623 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_mul); }
-#line 3002 "engines/director/lingo/lingo-gr.cpp"
+#line 3003 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 85:
-#line 623 "engines/director/lingo/lingo-gr.y"
+#line 624 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_div); }
-#line 3008 "engines/director/lingo/lingo-gr.cpp"
+#line 3009 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 86:
-#line 624 "engines/director/lingo/lingo-gr.y"
+#line 625 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_mod); }
-#line 3014 "engines/director/lingo/lingo-gr.cpp"
+#line 3015 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 87:
-#line 625 "engines/director/lingo/lingo-gr.y"
+#line 626 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_gt); }
-#line 3020 "engines/director/lingo/lingo-gr.cpp"
+#line 3021 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 88:
-#line 626 "engines/director/lingo/lingo-gr.y"
+#line 627 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_lt); }
-#line 3026 "engines/director/lingo/lingo-gr.cpp"
+#line 3027 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 89:
-#line 627 "engines/director/lingo/lingo-gr.y"
+#line 628 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_eq); }
-#line 3032 "engines/director/lingo/lingo-gr.cpp"
+#line 3033 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 90:
-#line 628 "engines/director/lingo/lingo-gr.y"
+#line 629 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_neq); }
-#line 3038 "engines/director/lingo/lingo-gr.cpp"
+#line 3039 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 91:
-#line 629 "engines/director/lingo/lingo-gr.y"
+#line 630 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_ge); }
-#line 3044 "engines/director/lingo/lingo-gr.cpp"
+#line 3045 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 92:
-#line 630 "engines/director/lingo/lingo-gr.y"
+#line 631 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_le); }
-#line 3050 "engines/director/lingo/lingo-gr.cpp"
+#line 3051 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 93:
-#line 631 "engines/director/lingo/lingo-gr.y"
+#line 632 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_and); }
-#line 3056 "engines/director/lingo/lingo-gr.cpp"
+#line 3057 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 94:
-#line 632 "engines/director/lingo/lingo-gr.y"
+#line 633 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_or); }
-#line 3062 "engines/director/lingo/lingo-gr.cpp"
+#line 3063 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 95:
-#line 633 "engines/director/lingo/lingo-gr.y"
+#line 634 "engines/director/lingo/lingo-gr.y"
                                         { g_lingo->code1(LC::c_not); }
-#line 3068 "engines/director/lingo/lingo-gr.cpp"
+#line 3069 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 96:
-#line 634 "engines/director/lingo/lingo-gr.y"
+#line 635 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_ampersand); }
-#line 3074 "engines/director/lingo/lingo-gr.cpp"
+#line 3075 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 97:
-#line 635 "engines/director/lingo/lingo-gr.y"
+#line 636 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_concat); }
-#line 3080 "engines/director/lingo/lingo-gr.cpp"
+#line 3081 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 98:
-#line 636 "engines/director/lingo/lingo-gr.y"
+#line 637 "engines/director/lingo/lingo-gr.y"
                                         { g_lingo->code1(LC::c_contains); }
-#line 3086 "engines/director/lingo/lingo-gr.cpp"
+#line 3087 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 99:
-#line 637 "engines/director/lingo/lingo-gr.y"
+#line 638 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_starts); }
-#line 3092 "engines/director/lingo/lingo-gr.cpp"
+#line 3093 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 100:
-#line 638 "engines/director/lingo/lingo-gr.y"
+#line 639 "engines/director/lingo/lingo-gr.y"
                                         { (yyval.code) = (yyvsp[0].code); }
-#line 3098 "engines/director/lingo/lingo-gr.cpp"
+#line 3099 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 101:
-#line 639 "engines/director/lingo/lingo-gr.y"
+#line 640 "engines/director/lingo/lingo-gr.y"
                                         { (yyval.code) = (yyvsp[0].code); g_lingo->code1(LC::c_negate); }
-#line 3104 "engines/director/lingo/lingo-gr.cpp"
+#line 3105 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 102:
-#line 640 "engines/director/lingo/lingo-gr.y"
+#line 641 "engines/director/lingo/lingo-gr.y"
                                         { g_lingo->code1(LC::c_intersects); }
-#line 3110 "engines/director/lingo/lingo-gr.cpp"
+#line 3111 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 103:
-#line 641 "engines/director/lingo/lingo-gr.y"
+#line 642 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_within); }
-#line 3116 "engines/director/lingo/lingo-gr.cpp"
+#line 3117 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 104:
-#line 643 "engines/director/lingo/lingo-gr.y"
+#line 644 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_charOf); }
-#line 3122 "engines/director/lingo/lingo-gr.cpp"
+#line 3123 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 105:
-#line 644 "engines/director/lingo/lingo-gr.y"
+#line 645 "engines/director/lingo/lingo-gr.y"
                                         { g_lingo->code1(LC::c_charToOf); }
-#line 3128 "engines/director/lingo/lingo-gr.cpp"
+#line 3129 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 106:
-#line 645 "engines/director/lingo/lingo-gr.y"
+#line 646 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_itemOf); }
-#line 3134 "engines/director/lingo/lingo-gr.cpp"
+#line 3135 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 107:
-#line 646 "engines/director/lingo/lingo-gr.y"
+#line 647 "engines/director/lingo/lingo-gr.y"
                                         { g_lingo->code1(LC::c_itemToOf); }
-#line 3140 "engines/director/lingo/lingo-gr.cpp"
+#line 3141 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 108:
-#line 647 "engines/director/lingo/lingo-gr.y"
+#line 648 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_lineOf); }
-#line 3146 "engines/director/lingo/lingo-gr.cpp"
+#line 3147 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 109:
-#line 648 "engines/director/lingo/lingo-gr.y"
+#line 649 "engines/director/lingo/lingo-gr.y"
                                         { g_lingo->code1(LC::c_lineToOf); }
-#line 3152 "engines/director/lingo/lingo-gr.cpp"
+#line 3153 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 110:
-#line 649 "engines/director/lingo/lingo-gr.y"
+#line 650 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_wordOf); }
-#line 3158 "engines/director/lingo/lingo-gr.cpp"
+#line 3159 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 111:
-#line 650 "engines/director/lingo/lingo-gr.y"
+#line 651 "engines/director/lingo/lingo-gr.y"
                                         { g_lingo->code1(LC::c_wordToOf); }
-#line 3164 "engines/director/lingo/lingo-gr.cpp"
+#line 3165 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 112:
-#line 652 "engines/director/lingo/lingo-gr.y"
+#line 653 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->codeFunc((yyvsp[-1].s), 1);
 		delete (yyvsp[-1].s); }
-#line 3172 "engines/director/lingo/lingo-gr.cpp"
+#line 3173 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 114:
-#line 657 "engines/director/lingo/lingo-gr.y"
+#line 658 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_printtop); }
-#line 3178 "engines/director/lingo/lingo-gr.cpp"
+#line 3179 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 117:
-#line 660 "engines/director/lingo/lingo-gr.y"
+#line 661 "engines/director/lingo/lingo-gr.y"
                                                 {
 		if (g_lingo->_repeatStack.size()) {
 			g_lingo->code2(LC::c_jump, 0);
@@ -3187,260 +3188,260 @@ yyreduce:
 		} else {
 			warning("# LINGO: exit repeat not inside repeat block");
 		} }
-#line 3191 "engines/director/lingo/lingo-gr.cpp"
+#line 3192 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 118:
-#line 668 "engines/director/lingo/lingo-gr.y"
+#line 669 "engines/director/lingo/lingo-gr.y"
                                                         { g_lingo->code1(LC::c_procret); }
-#line 3197 "engines/director/lingo/lingo-gr.cpp"
+#line 3198 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 119:
-#line 669 "engines/director/lingo/lingo-gr.y"
+#line 670 "engines/director/lingo/lingo-gr.y"
                                                         { inArgs(); }
-#line 3203 "engines/director/lingo/lingo-gr.cpp"
+#line 3204 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 120:
-#line 669 "engines/director/lingo/lingo-gr.y"
+#line 670 "engines/director/lingo/lingo-gr.y"
                                                                                  { inLast(); }
-#line 3209 "engines/director/lingo/lingo-gr.cpp"
+#line 3210 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 121:
-#line 670 "engines/director/lingo/lingo-gr.y"
+#line 671 "engines/director/lingo/lingo-gr.y"
                                                         { inArgs(); }
-#line 3215 "engines/director/lingo/lingo-gr.cpp"
+#line 3216 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 122:
-#line 670 "engines/director/lingo/lingo-gr.y"
+#line 671 "engines/director/lingo/lingo-gr.y"
                                                                                    { inLast(); }
-#line 3221 "engines/director/lingo/lingo-gr.cpp"
+#line 3222 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 123:
-#line 671 "engines/director/lingo/lingo-gr.y"
+#line 672 "engines/director/lingo/lingo-gr.y"
                                                         { inArgs(); }
-#line 3227 "engines/director/lingo/lingo-gr.cpp"
+#line 3228 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 124:
-#line 671 "engines/director/lingo/lingo-gr.y"
+#line 672 "engines/director/lingo/lingo-gr.y"
                                                                                    { inLast(); }
-#line 3233 "engines/director/lingo/lingo-gr.cpp"
+#line 3234 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 125:
-#line 672 "engines/director/lingo/lingo-gr.y"
+#line 673 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->codeFunc((yyvsp[-3].s), (yyvsp[-1].narg));
 		delete (yyvsp[-3].s); }
-#line 3241 "engines/director/lingo/lingo-gr.cpp"
+#line 3242 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 126:
-#line 675 "engines/director/lingo/lingo-gr.y"
+#line 676 "engines/director/lingo/lingo-gr.y"
                                                 {
 		g_lingo->codeFunc((yyvsp[-1].s), (yyvsp[0].narg));
 		delete (yyvsp[-1].s); }
-#line 3249 "engines/director/lingo/lingo-gr.cpp"
+#line 3250 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 127:
-#line 678 "engines/director/lingo/lingo-gr.y"
+#line 679 "engines/director/lingo/lingo-gr.y"
                                         { g_lingo->code1(LC::c_open); }
-#line 3255 "engines/director/lingo/lingo-gr.cpp"
+#line 3256 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 128:
-#line 679 "engines/director/lingo/lingo-gr.y"
+#line 680 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code2(LC::c_voidpush, LC::c_open); }
-#line 3261 "engines/director/lingo/lingo-gr.cpp"
+#line 3262 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 129:
-#line 681 "engines/director/lingo/lingo-gr.y"
+#line 682 "engines/director/lingo/lingo-gr.y"
                                                 {
 		mVar((yyvsp[0].s), kVarGlobal);
 		delete (yyvsp[0].s); }
-#line 3269 "engines/director/lingo/lingo-gr.cpp"
+#line 3270 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 130:
-#line 684 "engines/director/lingo/lingo-gr.y"
+#line 685 "engines/director/lingo/lingo-gr.y"
                                                 {
 		mVar((yyvsp[0].s), kVarGlobal);
 		delete (yyvsp[0].s); }
-#line 3277 "engines/director/lingo/lingo-gr.cpp"
+#line 3278 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 131:
-#line 688 "engines/director/lingo/lingo-gr.y"
+#line 689 "engines/director/lingo/lingo-gr.y"
                                                 {
 		mVar((yyvsp[0].s), kVarProperty);
 		delete (yyvsp[0].s); }
-#line 3285 "engines/director/lingo/lingo-gr.cpp"
+#line 3286 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 132:
-#line 691 "engines/director/lingo/lingo-gr.y"
+#line 692 "engines/director/lingo/lingo-gr.y"
                                         {
 		mVar((yyvsp[0].s), kVarProperty);
 		delete (yyvsp[0].s); }
-#line 3293 "engines/director/lingo/lingo-gr.cpp"
+#line 3294 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 133:
-#line 695 "engines/director/lingo/lingo-gr.y"
+#line 696 "engines/director/lingo/lingo-gr.y"
                                                 {
 		mVar((yyvsp[0].s), kVarInstance);
 		delete (yyvsp[0].s); }
-#line 3301 "engines/director/lingo/lingo-gr.cpp"
+#line 3302 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 134:
-#line 698 "engines/director/lingo/lingo-gr.y"
+#line 699 "engines/director/lingo/lingo-gr.y"
                                         {
 		mVar((yyvsp[0].s), kVarInstance);
 		delete (yyvsp[0].s); }
-#line 3309 "engines/director/lingo/lingo-gr.cpp"
+#line 3310 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 135:
-#line 709 "engines/director/lingo/lingo-gr.y"
+#line 710 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_gotoloop); }
-#line 3315 "engines/director/lingo/lingo-gr.cpp"
+#line 3316 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 136:
-#line 710 "engines/director/lingo/lingo-gr.y"
+#line 711 "engines/director/lingo/lingo-gr.y"
                                                         { g_lingo->code1(LC::c_gotonext); }
-#line 3321 "engines/director/lingo/lingo-gr.cpp"
+#line 3322 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 137:
-#line 711 "engines/director/lingo/lingo-gr.y"
+#line 712 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->code1(LC::c_gotoprevious); }
-#line 3327 "engines/director/lingo/lingo-gr.cpp"
+#line 3328 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 138:
-#line 712 "engines/director/lingo/lingo-gr.y"
+#line 713 "engines/director/lingo/lingo-gr.y"
                                                         {
 		g_lingo->code1(LC::c_intpush);
 		g_lingo->codeInt(1);
 		g_lingo->code1(LC::c_goto); }
-#line 3336 "engines/director/lingo/lingo-gr.cpp"
+#line 3337 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 139:
-#line 716 "engines/director/lingo/lingo-gr.y"
+#line 717 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->code1(LC::c_intpush);
 		g_lingo->codeInt(3);
 		g_lingo->code1(LC::c_goto); }
-#line 3345 "engines/director/lingo/lingo-gr.cpp"
+#line 3346 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 140:
-#line 720 "engines/director/lingo/lingo-gr.y"
+#line 721 "engines/director/lingo/lingo-gr.y"
                                                 {
 		g_lingo->code1(LC::c_intpush);
 		g_lingo->codeInt(2);
 		g_lingo->code1(LC::c_goto); }
-#line 3354 "engines/director/lingo/lingo-gr.cpp"
+#line 3355 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 143:
-#line 728 "engines/director/lingo/lingo-gr.y"
+#line 729 "engines/director/lingo/lingo-gr.y"
                                         { // "play #done" is also caught by this
 		g_lingo->code1(LC::c_intpush);
 		g_lingo->codeInt(1);
 		g_lingo->code1(LC::c_play); }
-#line 3363 "engines/director/lingo/lingo-gr.cpp"
+#line 3364 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 144:
-#line 732 "engines/director/lingo/lingo-gr.y"
+#line 733 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->code1(LC::c_intpush);
 		g_lingo->codeInt(3);
 		g_lingo->code1(LC::c_play); }
-#line 3372 "engines/director/lingo/lingo-gr.cpp"
+#line 3373 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 145:
-#line 736 "engines/director/lingo/lingo-gr.y"
+#line 737 "engines/director/lingo/lingo-gr.y"
                                                 {
 		g_lingo->code1(LC::c_intpush);
 		g_lingo->codeInt(2);
 		g_lingo->code1(LC::c_play); }
-#line 3381 "engines/director/lingo/lingo-gr.cpp"
+#line 3382 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 146:
-#line 740 "engines/director/lingo/lingo-gr.y"
+#line 741 "engines/director/lingo/lingo-gr.y"
                      { g_lingo->codeSetImmediate(true); }
-#line 3387 "engines/director/lingo/lingo-gr.cpp"
+#line 3388 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 147:
-#line 740 "engines/director/lingo/lingo-gr.y"
+#line 741 "engines/director/lingo/lingo-gr.y"
                                                                   {
 		g_lingo->codeSetImmediate(false);
 		g_lingo->codeFunc((yyvsp[-2].s), (yyvsp[0].narg));
 		delete (yyvsp[-2].s); }
-#line 3396 "engines/director/lingo/lingo-gr.cpp"
+#line 3397 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 148:
-#line 770 "engines/director/lingo/lingo-gr.y"
+#line 771 "engines/director/lingo/lingo-gr.y"
              { startDef(); }
-#line 3402 "engines/director/lingo/lingo-gr.cpp"
+#line 3403 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 149:
-#line 770 "engines/director/lingo/lingo-gr.y"
+#line 771 "engines/director/lingo/lingo-gr.y"
                                 { g_lingo->_currentFactory = NULL; }
-#line 3408 "engines/director/lingo/lingo-gr.cpp"
+#line 3409 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 150:
-#line 771 "engines/director/lingo/lingo-gr.y"
+#line 772 "engines/director/lingo/lingo-gr.y"
                                                                         {
 		g_lingo->code1(LC::c_procret);
 		g_lingo->codeDefine(*(yyvsp[-6].s), (yyvsp[-4].code), (yyvsp[-3].narg));
 		endDef();
 		delete (yyvsp[-6].s); }
-#line 3418 "engines/director/lingo/lingo-gr.cpp"
+#line 3419 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 151:
-#line 776 "engines/director/lingo/lingo-gr.y"
+#line 777 "engines/director/lingo/lingo-gr.y"
                         { g_lingo->codeFactory(*(yyvsp[0].s)); delete (yyvsp[0].s); }
-#line 3424 "engines/director/lingo/lingo-gr.cpp"
+#line 3425 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 152:
-#line 777 "engines/director/lingo/lingo-gr.y"
-                  { startDef(); }
-#line 3430 "engines/director/lingo/lingo-gr.cpp"
+#line 778 "engines/director/lingo/lingo-gr.y"
+                  { startDef(); (*g_lingo->_methodVars)["me"] = kVarArgument; }
+#line 3431 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 153:
-#line 778 "engines/director/lingo/lingo-gr.y"
+#line 779 "engines/director/lingo/lingo-gr.y"
                                                                         {
 		g_lingo->code1(LC::c_procret);
-		g_lingo->codeDefine(*(yyvsp[-6].s), (yyvsp[-4].code), (yyvsp[-3].narg), g_lingo->_currentFactory);
+		g_lingo->codeDefine(*(yyvsp[-6].s), (yyvsp[-4].code), (yyvsp[-3].narg) + 1, g_lingo->_currentFactory);
 		endDef();
 		delete (yyvsp[-6].s); }
-#line 3440 "engines/director/lingo/lingo-gr.cpp"
+#line 3441 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 154:
-#line 783 "engines/director/lingo/lingo-gr.y"
+#line 784 "engines/director/lingo/lingo-gr.y"
                                                                    {	// D3
 		g_lingo->code1(LC::c_procret);
 		g_lingo->codeDefine(*(yyvsp[-7].s), (yyvsp[-6].code), (yyvsp[-5].narg));
@@ -3449,70 +3450,70 @@ yyreduce:
 		checkEnd((yyvsp[-1].s), (yyvsp[-7].s)->c_str(), false);
 		delete (yyvsp[-7].s);
 		delete (yyvsp[-1].s); }
-#line 3453 "engines/director/lingo/lingo-gr.cpp"
+#line 3454 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 155:
-#line 791 "engines/director/lingo/lingo-gr.y"
+#line 792 "engines/director/lingo/lingo-gr.y"
                                                {	// D4. No 'end' clause
 		g_lingo->code1(LC::c_procret);
 		g_lingo->codeDefine(*(yyvsp[-5].s), (yyvsp[-4].code), (yyvsp[-3].narg));
 		endDef();
 		delete (yyvsp[-5].s); }
-#line 3463 "engines/director/lingo/lingo-gr.cpp"
+#line 3464 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 156:
-#line 797 "engines/director/lingo/lingo-gr.y"
+#line 798 "engines/director/lingo/lingo-gr.y"
          { startDef(); }
-#line 3469 "engines/director/lingo/lingo-gr.cpp"
+#line 3470 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 157:
-#line 797 "engines/director/lingo/lingo-gr.y"
+#line 798 "engines/director/lingo/lingo-gr.y"
                                 {
 		(yyval.s) = (yyvsp[0].s); g_lingo->_currentFactory = NULL; }
-#line 3476 "engines/director/lingo/lingo-gr.cpp"
+#line 3477 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 158:
-#line 800 "engines/director/lingo/lingo-gr.y"
+#line 801 "engines/director/lingo/lingo-gr.y"
                                         { (yyval.narg) = 0; }
-#line 3482 "engines/director/lingo/lingo-gr.cpp"
+#line 3483 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 159:
-#line 801 "engines/director/lingo/lingo-gr.y"
+#line 802 "engines/director/lingo/lingo-gr.y"
                                                         { g_lingo->codeArg((yyvsp[0].s)); mVar((yyvsp[0].s), kVarArgument); (yyval.narg) = 1; delete (yyvsp[0].s); }
-#line 3488 "engines/director/lingo/lingo-gr.cpp"
+#line 3489 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 160:
-#line 802 "engines/director/lingo/lingo-gr.y"
+#line 803 "engines/director/lingo/lingo-gr.y"
                                                 { g_lingo->codeArg((yyvsp[0].s)); mVar((yyvsp[0].s), kVarArgument); (yyval.narg) = (yyvsp[-2].narg) + 1; delete (yyvsp[0].s); }
-#line 3494 "engines/director/lingo/lingo-gr.cpp"
+#line 3495 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 162:
-#line 805 "engines/director/lingo/lingo-gr.y"
+#line 806 "engines/director/lingo/lingo-gr.y"
                                                         { delete (yyvsp[0].s); }
-#line 3500 "engines/director/lingo/lingo-gr.cpp"
+#line 3501 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 163:
-#line 806 "engines/director/lingo/lingo-gr.y"
+#line 807 "engines/director/lingo/lingo-gr.y"
                                                 { delete (yyvsp[0].s); }
-#line 3506 "engines/director/lingo/lingo-gr.cpp"
+#line 3507 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 164:
-#line 808 "engines/director/lingo/lingo-gr.y"
+#line 809 "engines/director/lingo/lingo-gr.y"
                                         { inDef(); }
-#line 3512 "engines/director/lingo/lingo-gr.cpp"
+#line 3513 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 165:
-#line 810 "engines/director/lingo/lingo-gr.y"
+#line 811 "engines/director/lingo/lingo-gr.y"
                                         {
 		g_lingo->code1(LC::c_call);
 		g_lingo->codeString((yyvsp[-1].s)->c_str());
@@ -3520,122 +3521,122 @@ yyreduce:
 		WRITE_UINT32(&numpar, (yyvsp[0].narg));
 		g_lingo->code1(numpar);
 		delete (yyvsp[-1].s); }
-#line 3524 "engines/director/lingo/lingo-gr.cpp"
+#line 3525 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 166:
-#line 818 "engines/director/lingo/lingo-gr.y"
+#line 819 "engines/director/lingo/lingo-gr.y"
                                         { (yyval.narg) = 0; }
-#line 3530 "engines/director/lingo/lingo-gr.cpp"
+#line 3531 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 167:
-#line 819 "engines/director/lingo/lingo-gr.y"
+#line 820 "engines/director/lingo/lingo-gr.y"
                                                         { (yyval.narg) = 1; }
-#line 3536 "engines/director/lingo/lingo-gr.cpp"
+#line 3537 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 168:
-#line 820 "engines/director/lingo/lingo-gr.y"
+#line 821 "engines/director/lingo/lingo-gr.y"
                                                 { (yyval.narg) = (yyvsp[-2].narg) + 1; }
-#line 3542 "engines/director/lingo/lingo-gr.cpp"
+#line 3543 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 169:
-#line 822 "engines/director/lingo/lingo-gr.y"
+#line 823 "engines/director/lingo/lingo-gr.y"
                                         { (yyval.narg) = 1; }
-#line 3548 "engines/director/lingo/lingo-gr.cpp"
+#line 3549 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 170:
-#line 823 "engines/director/lingo/lingo-gr.y"
+#line 824 "engines/director/lingo/lingo-gr.y"
                                         { (yyval.narg) = (yyvsp[-2].narg) + 1; }
-#line 3554 "engines/director/lingo/lingo-gr.cpp"
+#line 3555 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 171:
-#line 825 "engines/director/lingo/lingo-gr.y"
+#line 826 "engines/director/lingo/lingo-gr.y"
                                         { (yyval.code) = (yyvsp[-1].code); }
-#line 3560 "engines/director/lingo/lingo-gr.cpp"
+#line 3561 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 172:
-#line 827 "engines/director/lingo/lingo-gr.y"
+#line 828 "engines/director/lingo/lingo-gr.y"
                                         { (yyval.code) = g_lingo->code2(LC::c_arraypush, 0); }
-#line 3566 "engines/director/lingo/lingo-gr.cpp"
+#line 3567 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 173:
-#line 828 "engines/director/lingo/lingo-gr.y"
+#line 829 "engines/director/lingo/lingo-gr.y"
                                                         { (yyval.code) = g_lingo->code2(LC::c_proparraypush, 0); }
-#line 3572 "engines/director/lingo/lingo-gr.cpp"
+#line 3573 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 174:
-#line 829 "engines/director/lingo/lingo-gr.y"
+#line 830 "engines/director/lingo/lingo-gr.y"
                          { (yyval.code) = g_lingo->code1(LC::c_proparraypush); (yyval.code) = g_lingo->codeInt((yyvsp[0].narg)); }
-#line 3578 "engines/director/lingo/lingo-gr.cpp"
+#line 3579 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 175:
-#line 830 "engines/director/lingo/lingo-gr.y"
+#line 831 "engines/director/lingo/lingo-gr.y"
                      { (yyval.code) = g_lingo->code1(LC::c_arraypush); (yyval.code) = g_lingo->codeInt((yyvsp[0].narg)); }
-#line 3584 "engines/director/lingo/lingo-gr.cpp"
+#line 3585 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 176:
-#line 832 "engines/director/lingo/lingo-gr.y"
+#line 833 "engines/director/lingo/lingo-gr.y"
                                                 { (yyval.narg) = 1; }
-#line 3590 "engines/director/lingo/lingo-gr.cpp"
+#line 3591 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 177:
-#line 833 "engines/director/lingo/lingo-gr.y"
+#line 834 "engines/director/lingo/lingo-gr.y"
                                         { (yyval.narg) = (yyvsp[-2].narg) + 1; }
-#line 3596 "engines/director/lingo/lingo-gr.cpp"
+#line 3597 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 178:
-#line 835 "engines/director/lingo/lingo-gr.y"
+#line 836 "engines/director/lingo/lingo-gr.y"
                                                 { (yyval.narg) = 1; }
-#line 3602 "engines/director/lingo/lingo-gr.cpp"
+#line 3603 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 179:
-#line 836 "engines/director/lingo/lingo-gr.y"
+#line 837 "engines/director/lingo/lingo-gr.y"
                                         { (yyval.narg) = (yyvsp[-2].narg) + 1; }
-#line 3608 "engines/director/lingo/lingo-gr.cpp"
+#line 3609 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 180:
-#line 838 "engines/director/lingo/lingo-gr.y"
+#line 839 "engines/director/lingo/lingo-gr.y"
                           {
 		g_lingo->code1(LC::c_symbolpush);
 		g_lingo->codeString((yyvsp[-2].s)->c_str());
 		delete (yyvsp[-2].s); }
-#line 3617 "engines/director/lingo/lingo-gr.cpp"
+#line 3618 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 181:
-#line 842 "engines/director/lingo/lingo-gr.y"
+#line 843 "engines/director/lingo/lingo-gr.y"
                                 {
 		g_lingo->code1(LC::c_stringpush);
 		g_lingo->codeString((yyvsp[-2].s)->c_str());
 		delete (yyvsp[-2].s); }
-#line 3626 "engines/director/lingo/lingo-gr.cpp"
+#line 3627 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 182:
-#line 846 "engines/director/lingo/lingo-gr.y"
+#line 847 "engines/director/lingo/lingo-gr.y"
                         {
 		g_lingo->code1(LC::c_stringpush);
 		g_lingo->codeString((yyvsp[-2].s)->c_str());
 		delete (yyvsp[-2].s); }
-#line 3635 "engines/director/lingo/lingo-gr.cpp"
+#line 3636 "engines/director/lingo/lingo-gr.cpp"
     break;
 
 
-#line 3639 "engines/director/lingo/lingo-gr.cpp"
+#line 3640 "engines/director/lingo/lingo-gr.cpp"
 
       default: break;
     }
@@ -3834,7 +3835,7 @@ yyreturn:
   return yyresult;
 }
 
-#line 852 "engines/director/lingo/lingo-gr.y"
+#line 853 "engines/director/lingo/lingo-gr.y"
 
 
 int yyreport_syntax_error(const yypcontext_t *ctx) {
diff --git a/engines/director/lingo/lingo-gr.h b/engines/director/lingo/lingo-gr.h
index cf524c695f..0e8ad2b57f 100644
--- a/engines/director/lingo/lingo-gr.h
+++ b/engines/director/lingo/lingo-gr.h
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 3.6.3.  */
+/* A Bison parser, made by GNU Bison 3.6.4.  */
 
 /* Bison interface for Yacc-like parsers in C
 
@@ -146,7 +146,7 @@ extern int yydebug;
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 union YYSTYPE
 {
-#line 167 "engines/director/lingo/lingo-gr.y"
+#line 168 "engines/director/lingo/lingo-gr.y"
 
 	Common::String *s;
 	int i;
diff --git a/engines/director/lingo/lingo-gr.y b/engines/director/lingo/lingo-gr.y
index c1b0be66bd..e4e9dc4445 100644
--- a/engines/director/lingo/lingo-gr.y
+++ b/engines/director/lingo/lingo-gr.y
@@ -62,6 +62,7 @@
 #include "director/lingo/lingo.h"
 #include "director/lingo/lingo-code.h"
 #include "director/lingo/lingo-gr.h"
+#include "director/lingo/lingo-object.h"
 
 extern int yylex();
 extern int yyparse();
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 046f406f77..9ff334b72e 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -39,17 +39,23 @@ static struct MethodProto {
 	int type;
 	int version;
 } predefinedMethods[] = {
-	{ "birth",					LM::m_new,					-1, 0,	kScriptObj | kXtraObj, 	4 },			// D4
+	// all except window
+	{ "new",					LM::m_new,					-1, 0,	kAllObj, 				2 },	// D2
+
+	// factory and XObject
 	{ "describe",				LM::m_describe,				 0, 0,	kXObj,					2 },	// D2
 	{ "dispose",				LM::m_dispose,				 0, 0,	kFactoryObj | kXObj,	2 },	// D2
 	{ "get",					LM::m_get,					 1, 1,	kFactoryObj,			2 },	// D2
 	{ "instanceRespondsTo",		LM::m_instanceRespondsTo,	 1, 1,	kXObj,					3 },		// D3
 	{ "messageList",			LM::m_messageList,			 0, 0,	kXObj,					3 },		// D3
 	{ "name",					LM::m_name,					 0, 0,	kXObj,					3 },		// D3
-	{ "new",					LM::m_new,					-1, 0,	kAllObj, 				2 },	// D2
 	{ "perform",				LM::m_perform,				-1, 0,	kFactoryObj | kXObj, 	3 },		// D3
 	{ "put",					LM::m_put,					 2, 2,	kFactoryObj,			2 },	// D2
 	{ "respondsTo",				LM::m_respondsTo,			 1, 1,	kXObj,					2 },	// D2
+
+	// script object and Xtra
+	{ "birth",					LM::m_new,					-1, 0,	kScriptObj | kXtraObj, 	4 },			// D4
+
 	{ 0, 0, 0, 0, 0, 0 }
 };
 
@@ -104,6 +110,50 @@ void Lingo::openXLib(const Common::String &name, ObjectType type) {
 	}
 }
 
+Object::Object(const Common::String &objName, ObjectType objType, ScriptContext *objCtx) {
+	name = new Common::String(objName);
+	type = objType;
+	disposed = false;
+	inheritanceLevel = 1;
+	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>;
+	} else {
+		objArray = nullptr;
+	}
+}
+
+Object::Object(const Object &obj) {
+	name = new Common::String(*obj.name);
+	type = obj.type;
+	disposed = obj.disposed;
+	inheritanceLevel = obj.inheritanceLevel + 1;
+	properties = obj.properties;
+	ctx = new ScriptContext(*obj.ctx);
+	ctx->_target = this;
+	*ctx->_target.refCount -= 1;
+
+	if (obj.objArray) {
+		objArray = new Common::HashMap<uint32, Datum>(*obj.objArray);
+	} else {
+		objArray = nullptr;
+	}
+}
+
+Object::~Object() {
+	delete name;
+	delete objArray;
+	ctx->_target.refCount = nullptr; // refCount has already been freed
+	delete ctx;
+}
+
 Object *Object::clone() {
 	return new Object(*this);
 }
@@ -119,28 +169,29 @@ Symbol Object::getMethod(const Common::String &methodName) {
 	}
 
 	if ((type & (kFactoryObj | kXObj)) && methodName.hasPrefixIgnoreCase("m")) {
+		// factory or XObject
 		Common::String shortName = methodName.substr(1);
-		// instance method (XObject)
 		if (type == kXObj && ctx->_functionHandlers.contains(shortName) && inheritanceLevel > 1) {
+			// instance method (XObject)
 			return ctx->_functionHandlers[shortName];
 		}
-		// predefined method (factory and XObject)
 		if (g_lingo->_methods.contains(shortName) && (type & g_lingo->_methods[shortName].targetType)) {
+			// predefined method
 			Symbol sym = g_lingo->_methods[shortName];
 			sym.ctx = ctx;
 			return sym;
 		}
-	} else if (type & (kScriptObj | kXtraObj)) {
-		// predefined method (script object and Xtra)
+	} else {
+		// script object, Xtra, etc.
 		if (g_lingo->_methods.contains(methodName) && (type & g_lingo->_methods[methodName].targetType)) {
+			// predefined method
 			Symbol sym = g_lingo->_methods[methodName];
 			sym.ctx = ctx;
 			return sym;
 		}
-
-		// ancestor method
 		if (properties.contains("ancestor") && properties["ancestor"].type == OBJECT
 				&& (properties["ancestor"].u.obj->type & (kScriptObj | kXtraObj))) {
+			// ancestor method
 			debugC(3, kDebugLingoExec, "Calling method '%s' on ancestor: <%s>", methodName.c_str(), properties["ancestor"].asString(true).c_str());
 			return properties["ancestor"].u.obj->getMethod(methodName);
 		}
@@ -167,7 +218,7 @@ bool Object::hasProp(const Common::String &propName) {
 	return false;
 }
 
-Datum &Object::getProp(const Common::String &propName) {
+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());
 	}
@@ -184,6 +235,24 @@ Datum &Object::getProp(const Common::String &propName) {
 	return properties[propName]; // return new property
 }
 
+bool Object::setProp(const Common::String &propName, const Datum &value) {
+	if (disposed) {
+		error("Property '%s' accessed on disposed object <%s>", propName.c_str(), Datum(this).asString(true).c_str());
+	}
+	if (properties.contains(propName)) {
+		properties[propName] = value;
+		return true;
+	}
+	if (type & (kScriptObj | kXtraObj)) {
+		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());
+			return properties["ancestor"].u.obj->setProp(propName, value);
+		}
+	}
+	return false;
+}
+
 // Initialization/disposal
 
 void LM::m_new(int nargs) {
diff --git a/engines/director/lingo/lingo-object.h b/engines/director/lingo/lingo-object.h
index 7ff8ba16a3..6384fc1ca9 100644
--- a/engines/director/lingo/lingo-object.h
+++ b/engines/director/lingo/lingo-object.h
@@ -25,6 +25,29 @@
 
 namespace Director {
 
+struct Object {
+	Common::String *name;
+	ObjectType type;
+	bool disposed;
+
+	DatumHash properties;
+	ScriptContext *ctx;
+	int inheritanceLevel; // 1 for original object
+
+	// used only for factories
+	Common::HashMap<uint32, Datum> *objArray;
+
+	Object(const Common::String &objName, ObjectType objType, ScriptContext *objCtx);
+	Object(const Object &obj);
+	virtual ~Object();
+
+	virtual Object *clone();
+	Symbol getMethod(const Common::String &methodName);
+	bool hasProp(const Common::String &propName);
+	Datum getProp(const Common::String &propName);
+	bool setProp(const Common::String &propName, const Datum &value);
+};
+
 namespace LM {
 	// predefined methods
 	void m_describe(int nargs);
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 330a42f26f..ba8442a208 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -32,6 +32,7 @@
 #include "director/stage.h"
 #include "director/lingo/lingo.h"
 #include "director/lingo/lingo-code.h"
+#include "director/lingo/lingo-object.h"
 #include "director/lingo/lingo-the.h"
 #include "director/lingo/lingo-gr.h"
 namespace Director {
@@ -1237,7 +1238,7 @@ Datum Lingo::getObjectProp(Datum &obj, Common::String &propName) {
 void Lingo::setObjectProp(Datum &obj, Common::String &propName, Datum &val) {
 	if (obj.type == OBJECT) {
 		if (obj.u.obj->hasProp(propName)) {
-			obj.u.obj->getProp(propName) = val;
+			obj.u.obj->setProp(propName, val);
 		} else {
 			warning("Lingo::setObjectProp: Object <%s> has no property '%s'", obj.asString(true).c_str(), propName.c_str());
 		}
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 43b2a6623f..0ea191928c 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -37,6 +37,7 @@
 #include "director/lingo/lingo.h"
 #include "director/lingo/lingo-code.h"
 #include "director/lingo/lingo-gr.h"
+#include "director/lingo/lingo-object.h"
 
 namespace Director {
 
@@ -1201,29 +1202,28 @@ void Lingo::varAssign(Datum &var, Datum &value, bool global, DatumHash *localvar
 	}
 
 	if (var.type == VAR) {
-		Datum *d = nullptr;
 		Common::String name = *var.u.s;
 
 		if (localvars && localvars->contains(name)) {
-			d = &(*localvars)[name];
+			(*localvars)[name] = value;
 			if (global)
 				warning("varAssign: variable %s is local, not global", name.c_str());
-		} else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
-			d = &_currentMe.u.obj->getProp(name);
+			return;
+		}
+		if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
+			_currentMe.u.obj->setProp(name, value);
 			if (global)
 				warning("varAssign: variable %s is instance or property, not global", name.c_str());
-		} else if (_globalvars.contains(name)) {
-			d = &_globalvars[name];
+			return;
+		}
+		if (_globalvars.contains(name)) {
+			_globalvars[name] = value;
 			if (!global)
 				warning("varAssign: variable %s is global, not local", name.c_str());
-		}
-
-		if (!d) {
-			warning("varAssign: variable %s not defined", name.c_str());
 			return;
 		}
 
-		*d = value;
+		warning("varAssign: variable %s not defined", name.c_str());
 	} else if (var.type == FIELDREF) {
 		Movie *movie = g_director->getCurrentMovie();
 		if (!movie) {
@@ -1260,7 +1260,7 @@ Datum Lingo::varFetch(Datum &var, bool global, DatumHash *localvars) {
 	}
 
 	if (var.type == VAR) {
-		Datum *d = nullptr;
+		Datum d;
 		Common::String name = *var.u.s;
 
 		// For kScriptObj handlers the target is an argument
@@ -1270,25 +1270,23 @@ Datum Lingo::varFetch(Datum &var, bool global, DatumHash *localvars) {
 			return result;
 		}
 		if (localvars && localvars->contains(name)) {
-			d = &(*localvars)[name];
 			if (global)
 				warning("varFetch: variable %s is local, not global", name.c_str());
-		} else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
-			d = &_currentMe.u.obj->getProp(name);
+			return (*localvars)[name];
+		}
+		if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
 			if (global)
 				warning("varFetch: variable %s is instance or property, not global", name.c_str());
-		} else if (_globalvars.contains(name)) {
-			d = &_globalvars[name];
+			return _currentMe.u.obj->getProp(name);
+		}
+		if (_globalvars.contains(name)) {
 			if (!global)
 				warning("varFetch: variable %s is global, not local", name.c_str());
+			return _globalvars[name];
 		}
 
-		if (!d) {
-			warning("varFetch: variable %s not found", name.c_str());
-			return result;
-		}
-
-		return *d;
+		warning("varFetch: variable %s not found", name.c_str());
+		return result;
 	} else if (var.type == FIELDREF) {
 		CastMember *cast = _vm->getCurrentMovie()->getCastMember(var.u.i);
 		if (cast) {
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index d3bcdb516f..cd5c1bcfa2 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -211,68 +211,6 @@ private:
 	Datum _parentScript;
 };
 
-struct Object {
-	Common::String *name;
-	ObjectType type;
-	bool disposed;
-
-	DatumHash properties;
-	ScriptContext *ctx;
-	int inheritanceLevel; // 1 for original object
-
-	// used only for factories
-	Common::HashMap<uint32, Datum> *objArray;
-
-	Object(const Common::String &objName, ObjectType objType, ScriptContext *objCtx) {
-		name = new Common::String(objName);
-		type = objType;
-		disposed = false;
-		inheritanceLevel = 1;
-		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>;
-		} else {
-			objArray = nullptr;
-		}
-	}
-
-	Object(const Object &obj) {
-		name = new Common::String(*obj.name);
-		type = obj.type;
-		disposed = obj.disposed;
-		inheritanceLevel = obj.inheritanceLevel + 1;
-		properties = obj.properties;
-		ctx = new ScriptContext(*obj.ctx);
-		ctx->_target = this;
-		*ctx->_target.refCount -= 1;
-
-		if (obj.objArray) {
-			objArray = new Common::HashMap<uint32, Datum>(*obj.objArray);
-		} else {
-			objArray = nullptr;
-		}
-	}
-
-	virtual ~Object() {
-		delete name;
-		delete objArray;
-		ctx->_target.refCount = nullptr; // refCount has already been freed
-		delete ctx;
-	}
-
-	virtual Object *clone();
-	Symbol getMethod(const Common::String &methodName);
-	bool hasProp(const Common::String &propName);
-	Datum &getProp(const Common::String &propName);
-};
-
 struct CFrame {	/* proc/func call stack frame */
 	Symbol	sp;	/* symbol table entry */
 	int		retpc;	/* where to resume after return */
diff --git a/engines/director/lingo/xlibs/fileio.cpp b/engines/director/lingo/xlibs/fileio.cpp
index bcd0eee72c..6c1013b293 100644
--- a/engines/director/lingo/xlibs/fileio.cpp
+++ b/engines/director/lingo/xlibs/fileio.cpp
@@ -27,6 +27,7 @@
 
 #include "director/director.h"
 #include "director/lingo/lingo.h"
+#include "director/lingo/lingo-object.h"
 #include "director/lingo/lingo-gr.h"
 #include "director/lingo/xlibs/fileio.h"
 


Commit: 1efd5f5c11b5bfa00640f5b567fd7761bbcbb9d4
    https://github.com/scummvm/scummvm/commit/1efd5f5c11b5bfa00640f5b567fd7761bbcbb9d4
Author: djsrv (dservilla at gmail.com)
Date: 2020-07-06T20:18:57-04:00

Commit Message:
DIRECTOR: LINGO: Improve object refcounting

Changed paths:
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/lingo/lingo-code.cpp
    engines/director/lingo/lingo-codegen.cpp
    engines/director/lingo/lingo-object.cpp
    engines/director/lingo/lingo-object.h
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h
    engines/director/lingo/xlibs/fileio.cpp


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 43c2099375..de69ae7b26 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -383,7 +383,7 @@ void LC::cb_objectcall() {
 		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
+				g_lingo->push(method.target);
 				nargs.u.i += 1;
 			}
 			while (args.size()) {
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 894a4df3cd..df012d0f60 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -222,10 +222,13 @@ void Lingo::pushContext(const Symbol funcSym, bool preserveVarFrame) {
 	fp->sp = funcSym;
 
 	g_lingo->_currentScript = funcSym.u.defn;
-	if (funcSym.ctx) {
+
+	if (funcSym.target)
+		g_lingo->_currentMe = funcSym.target;
+
+	if (funcSym.ctx)
 		g_lingo->_currentScriptContext = funcSym.ctx;
-		g_lingo->_currentMe = funcSym.ctx->_target; // reference-counted datum
-	}
+
 	g_lingo->_currentArchive = funcSym.archive;
 
 	// Execute anonymous functions within the current var frame.
@@ -1337,7 +1340,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; // reference-counted datum
+					g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.target;
 				} else {
 					// Otherwise, take the target object out of the stack
 					g_lingo->_stack.remove_at(g_lingo->_stack.size() - nargs);
@@ -1367,7 +1370,7 @@ void LC::call(const Common::String &name, int nargs) {
 			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
+				g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.target;
 			} else {
 				// Otherwise, take the methodName out of the stack
 				g_lingo->_stack.remove_at(g_lingo->_stack.size() - nargs);
@@ -1419,7 +1422,7 @@ void LC::call(const Symbol &funcSym, int nargs) {
 
 		Datum target;
 		if (funcSym.ctx) {
-			target = funcSym.ctx->_target; // reference-counted datum
+			target = funcSym.target;
 		}
 
 		if (target.type == OBJECT) {
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index c90d830d81..5eb42296bc 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -292,7 +292,7 @@ void Lingo::codeFactory(Common::String &name) {
 
 	_currentFactory = obj;
 	if (!_globalvars.contains(name)) {
-		_globalvars[name] = obj->ctx->_target;
+		_globalvars[name] = obj;
 	} else {
 		warning("Factory '%s' already defined", name.c_str());
 	}
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 9ff334b72e..a77363b5b9 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -115,13 +115,11 @@ Object::Object(const Common::String &objName, ObjectType objType, ScriptContext
 	type = objType;
 	disposed = false;
 	inheritanceLevel = 1;
+	refCount = new int;
+	*refCount = 0;
 	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 (ctx)
+		ctx->setTarget(this);
 
 	if (objType == kFactoryObj) {
 		objArray = new Common::HashMap<uint32, Datum>;
@@ -136,9 +134,14 @@ Object::Object(const Object &obj) {
 	disposed = obj.disposed;
 	inheritanceLevel = obj.inheritanceLevel + 1;
 	properties = obj.properties;
-	ctx = new ScriptContext(*obj.ctx);
-	ctx->_target = this;
-	*ctx->_target.refCount -= 1;
+	refCount = new int;
+	*refCount = 0;
+	if (obj.ctx) {
+		ctx = new ScriptContext(*obj.ctx);
+		ctx->setTarget(this);
+	} else {
+		ctx = nullptr;
+	}
 
 	if (obj.objArray) {
 		objArray = new Common::HashMap<uint32, Datum>(*obj.objArray);
@@ -150,7 +153,7 @@ Object::Object(const Object &obj) {
 Object::~Object() {
 	delete name;
 	delete objArray;
-	ctx->_target.refCount = nullptr; // refCount has already been freed
+	delete refCount;
 	delete ctx;
 }
 
@@ -178,7 +181,7 @@ Symbol Object::getMethod(const Common::String &methodName) {
 		if (g_lingo->_methods.contains(shortName) && (type & g_lingo->_methods[shortName].targetType)) {
 			// predefined method
 			Symbol sym = g_lingo->_methods[shortName];
-			sym.ctx = ctx;
+			sym.target = this;
 			return sym;
 		}
 	} else {
@@ -186,7 +189,7 @@ Symbol Object::getMethod(const Common::String &methodName) {
 		if (g_lingo->_methods.contains(methodName) && (type & g_lingo->_methods[methodName].targetType)) {
 			// predefined method
 			Symbol sym = g_lingo->_methods[methodName];
-			sym.ctx = ctx;
+			sym.target = this;
 			return sym;
 		}
 		if (properties.contains("ancestor") && properties["ancestor"].type == OBJECT
diff --git a/engines/director/lingo/lingo-object.h b/engines/director/lingo/lingo-object.h
index 6384fc1ca9..49206f698c 100644
--- a/engines/director/lingo/lingo-object.h
+++ b/engines/director/lingo/lingo-object.h
@@ -31,13 +31,14 @@ struct Object {
 	bool disposed;
 
 	DatumHash properties;
+	int *refCount;
 	ScriptContext *ctx;
 	int inheritanceLevel; // 1 for original object
 
 	// used only for factories
 	Common::HashMap<uint32, Datum> *objArray;
 
-	Object(const Common::String &objName, ObjectType objType, ScriptContext *objCtx);
+	Object(const Common::String &objName, ObjectType objType, ScriptContext *objCtx = nullptr);
 	Object(const Object &obj);
 	virtual ~Object();
 
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 0ea191928c..584419ba33 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -57,6 +57,7 @@ Symbol::Symbol() {
 	varNames = nullptr;
 	ctx = nullptr;
 	archive = nullptr;
+	target = nullptr;
 	anonymous = false;
 }
 
@@ -74,6 +75,7 @@ Symbol::Symbol(const Symbol &s) {
 	varNames = s.varNames;
 	ctx = s.ctx;
 	archive = s.archive;
+	target = s.target;
 	anonymous = s.anonymous;
 }
 
@@ -93,6 +95,7 @@ Symbol& Symbol::operator=(const Symbol &s) {
 		varNames = s.varNames;
 		ctx = s.ctx;
 		archive = s.archive;
+		target = s.target;
 		anonymous = s.anonymous;
 	}
 	return *this;
@@ -686,7 +689,9 @@ Datum::Datum(const Datum &d) {
 }
 
 Datum& Datum::operator=(const Datum &d) {
-	if (this != &d) {
+	if (d.type == OBJECT)
+		warning("%p = REFCOUNT %d", (void *)this, *refCount);
+	if (this != &d && refCount != d.refCount) {
 		reset();
 		type = d.type;
 		u = d.u;
@@ -724,8 +729,9 @@ Datum::Datum(Object *val) {
 	u.obj = val;
 	type = OBJECT;
 	lazy = false;
-	refCount = new int;
-	*refCount = 1;
+	refCount = val->refCount;
+	*refCount += 1;
+	warning("%p create REFCOUNT %d", (void *)this, *refCount);
 }
 
 void Datum::reset() {
@@ -767,7 +773,8 @@ void Datum::reset() {
 		default:
 			break;
 		}
-		delete refCount;
+		if (type != OBJECT) // object owns refCount
+			delete refCount;
 	}
 #endif
 }
@@ -1040,6 +1047,16 @@ int Datum::compareTo(Datum &d, bool ignoreCase) {
 	}
 }
 
+void ScriptContext::setTarget(Object *target) {
+	_target = target;
+	for (SymbolHash::iterator it = _functionHandlers.begin(); it != _functionHandlers.end(); ++it) {
+		it->_value.target = target;
+	}
+	for (Common::HashMap<uint32, Symbol>::iterator it = _eventHandlers.begin(); it != _eventHandlers.end(); ++it) {
+		it->_value.target = target;
+	}
+}
+
 Datum ScriptContext::getParentScript() {
 	if (_parentScript.type != OBJECT) {
 		_parentScript.type = OBJECT;
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index cd5c1bcfa2..3c1dbf9d50 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -97,6 +97,7 @@ struct Symbol {	/* symbol table entry */
 	Common::Array<Common::String> *varNames;
 	ScriptContext *ctx;		/* optional script context to execute with */
 	LingoArchive *archive; 	/* optional archive to execute with */
+	Object *target;			/* optional method target */
 	bool anonymous;
 
 	Symbol();
@@ -181,10 +182,9 @@ public:
 	Common::HashMap<uint32, Symbol> _eventHandlers;
 	Common::Array<Datum> _constants;
 	Common::Array<Common::String> _propNames;
-	Datum _target;
 
 	ScriptContext(Common::String name, LingoArchive *archive = nullptr, ScriptType type = kNoneScript, uint16 id = 0)
-		: _name(name), _archive(archive), _type(type), _id(id) {}
+		: _name(name), _archive(archive), _type(type), _id(id), _target(nullptr) {}
 	ScriptContext(const ScriptContext &sc) {
 		_type = sc._type;
 		_name = sc._name;
@@ -204,11 +204,14 @@ public:
 		_id = sc._id;
 	}
 
+	Object *getTarget() const { return _target; }
+	void setTarget(Object *target);
 	Datum getParentScript();
 	Symbol define(Common::String &name, int nargs, ScriptData *code, Common::Array<Common::String> *argNames, Common::Array<Common::String> *varNames);
 
 private:
 	Datum _parentScript;
+	Object *_target;
 };
 
 struct CFrame {	/* proc/func call stack frame */
diff --git a/engines/director/lingo/xlibs/fileio.cpp b/engines/director/lingo/xlibs/fileio.cpp
index 6c1013b293..2cbab90aee 100644
--- a/engines/director/lingo/xlibs/fileio.cpp
+++ b/engines/director/lingo/xlibs/fileio.cpp
@@ -65,7 +65,7 @@ void FileIO::initialize(int type) {
 			ScriptContext *ctx = new ScriptContext(Common::String(xlibName));
 			FileObject *xobj = new FileObject(kXObj, ctx);
 			xobj->initMethods();
-			g_lingo->_globalvars[xlibName] = xobj->ctx->_target;
+			g_lingo->_globalvars[xlibName] = xobj;
 		} else {
 			warning("FileIO XObject already initialized");
 		}




More information about the Scummvm-git-logs mailing list