[Scummvm-git-logs] scummvm master -> b0d8880919ef68688fc3fd033ceb4aec647d091f

sev- sev at scummvm.org
Tue Apr 28 21:33:03 UTC 2020


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

Summary:
94b80a2e10 DIRECTOR: LINGO: Collapse compareTo functions
1f77ea3a31 DIRECTOR: LINGO: Finish property array datum type
c74ef4136b DIRECTOR: LINGO: Implement property array comparisons
b0d8880919 DIRECTOR: LINGO: Implement property array functions


Commit: 94b80a2e1080d40f9f68ef611939f36f9c2f2832
    https://github.com/scummvm/scummvm/commit/94b80a2e1080d40f9f68ef611939f36f9c2f2832
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-04-28T23:32:57+02:00

Commit Message:
DIRECTOR: LINGO: Collapse compareTo functions

Changed paths:
    engines/director/lingo/lingo-code.cpp
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index e4ab35f9cf..b1465a3548 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -1022,7 +1022,7 @@ Datum LC::eqData(Datum d1, Datum d2) {
 	if (d1.type == ARRAY || d2.type == ARRAY) {
 		return LC::compareArrays(LC::eqData, d1, d2);
 	}
-	d1.u.i = (d1.compareToIgnoreCase(d2) == 0) ? 1 : 0;
+	d1.u.i = (d1.compareTo(d2, true) == 0) ? 1 : 0;
 	d1.type = INT;
 	return d1;
 }
@@ -1037,7 +1037,7 @@ Datum LC::neqData(Datum d1, Datum d2) {
 	if (d1.type == ARRAY || d2.type == ARRAY) {
 		return LC::compareArrays(LC::neqData, d1, d2);
 	}
-	d1.u.i = (d1.compareToIgnoreCase(d2) != 0) ? 1 : 0;
+	d1.u.i = (d1.compareTo(d2, true) != 0) ? 1 : 0;
 	d1.type = INT;
 	return d1;
 }
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 3816c4edd6..c515a0eda3 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -578,9 +578,9 @@ const char *Datum::type2str(bool isk) {
 	}
 }
 
-int Datum::compareTo(Datum d) {
+int Datum::compareTo(Datum d, bool ignoreCase) {
 	if (type == STRING && d.type == STRING) {
-		return u.s->compareTo(*d.u.s);
+		return ignoreCase ? u.s->compareToIgnoreCase(*d.u.s) : u.s->compareTo(*d.u.s);
 	} else if (g_lingo->alignTypes(*this, d) == FLOAT) {
 		if (u.f < d.u.f) {
 			return -1;
@@ -600,15 +600,6 @@ int Datum::compareTo(Datum d) {
 	}
 }
 
-int Datum::compareToIgnoreCase(Datum d) {
-	if (type == STRING && d.type == STRING) {
-		Common::String *s1 = toLowercaseMac(u.s);
-		Common::String *s2 = toLowercaseMac(d.u.s);
-		return s1->compareTo(*s2);
-	}
-	return compareTo(d);
-}
-
 void Lingo::parseMenu(const char *code) {
 	warning("STUB: parseMenu");
 }
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index b5413fe0dd..cc7655348b 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -115,8 +115,7 @@ struct Datum {	/* interpreter stack type */
 
 	const char *type2str(bool isk = false);
 
-	int compareTo(Datum d);
-	int compareToIgnoreCase(Datum d);
+	int compareTo(Datum d, bool ignoreCase = false);
 };
 
 struct Builtin {


Commit: 1f77ea3a31ad2912daf3f56550a1cc70dce7c22c
    https://github.com/scummvm/scummvm/commit/1f77ea3a31ad2912daf3f56550a1cc70dce7c22c
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-04-28T23:32:57+02:00

Commit Message:
DIRECTOR: LINGO: Finish property array datum type

Changed paths:
    engines/director/lingo/lingo-code.cpp
    engines/director/lingo/lingo-codegen.cpp
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h
    engines/director/types.h


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index b1465a3548..52cd7a6303 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -230,6 +230,9 @@ void LC::c_printtop(void) {
 	case ARRAY:
 		warning("%s", d.getPrintable().c_str());
 		break;
+	case PARRAY:
+		warning("%s", d.getPrintable().c_str());
+		break;
 	default:
 		warning("--unknown--");
 	}
@@ -315,13 +318,17 @@ void LC::c_proparraypush() {
 	Datum d;
 	int arraySize = g_lingo->readInt();
 
-	warning("STUB: c_proparraypush()");
+	d.type = PARRAY;
+	d.u.parr = new PropertyArray;
 
-	for (int i = 0; i < arraySize * 2; i++)
-		g_lingo->pop();
+	for (int i = 0; i < arraySize; i++) {
+		Datum p = g_lingo->pop();
+		Datum v = g_lingo->pop();
+
+		PCell cell = PCell(p, v);
+		d.u.parr->insert_at(0, cell);
+	}
 
-	d.u.i = arraySize;
-	d.type = INT;
 	g_lingo->push(d);
 }
 
@@ -380,7 +387,7 @@ void LC::c_assign() {
 }
 
 bool LC::verify(Symbol *s) {
-	if (s->type != INT && s->type != VOID && s->type != FLOAT && s->type != STRING && s->type != POINT && s->type != SYMBOL && s->type != ARRAY) {
+	if (s->type != INT && s->type != VOID && s->type != FLOAT && s->type != STRING && s->type != POINT && s->type != SYMBOL && s->type != ARRAY && s->type != PARRAY) {
 		warning("attempt to evaluate non-variable '%s'", s->name.c_str());
 
 		return false;
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 292b296e8f..10e23bac72 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -532,7 +532,8 @@ void Lingo::varAssign(Datum &var, Datum &value) {
 		}
 
 		if (sym->type != INT && sym->type != VOID &&
-				sym->type != FLOAT && sym->type != STRING && sym->type != ARRAY) {
+				sym->type != FLOAT && sym->type != STRING &&
+				sym->type != ARRAY && sym->type != PARRAY) {
 			warning("varAssign: assignment to non-variable '%s'", sym->name.c_str());
 			return;
 		}
@@ -542,6 +543,8 @@ void Lingo::varAssign(Datum &var, Datum &value) {
 
 		if (sym->type == POINT || sym->type == RECT || sym->type == ARRAY)
 			delete var.u.sym->u.farr;
+		else if (sym->type == PARRAY)
+			delete var.u.sym->u.parr;
 
 		sym->type = value.type;
 		if (value.type == INT) {
@@ -554,6 +557,8 @@ void Lingo::varAssign(Datum &var, Datum &value) {
 		} else if (value.type == POINT || value.type == ARRAY) {
 			sym->u.farr = new DatumArray(*value.u.farr);
 			delete value.u.farr;
+		} else if (value.type == PARRAY) {
+			sym->u.parr = new PropertyArray(*value.u.parr);
 		} else if (value.type == SYMBOL) {
 			sym->u.s = value.u.s;
 		} else if (value.type == OBJECT) {
@@ -623,9 +628,11 @@ Datum Lingo::varFetch(Datum &var) {
 			result.u.s = var.u.sym->u.s;
 		else if (sym->type == VOID)
 			result.u.i = 0;
-		else if (sym->type == ARRAY) {
+		else if (sym->type == ARRAY)
 			result.u.farr = sym->u.farr;
-		} else {
+		else if (sym->type == PARRAY)
+			result.u.parr = sym->u.parr;
+		else {
 			warning("varFetch: unhandled type: %s", var.type2str());
 			result.type = VOID;
 		}
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index c515a0eda3..80bd0d03e6 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -50,6 +50,21 @@ Symbol::Symbol() {
 	archiveIndex = 0;
 }
 
+PCell::PCell() {
+	p = nullptr;
+	v = nullptr;
+}
+
+PCell::PCell(Datum &prop, Datum &val) {
+	p = new Datum;
+	p->type = prop.type;
+	p->u = prop.u;
+
+	v = new Datum;
+	v->type = val.type;
+	v->u = val.u;
+}
+
 Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
 	g_lingo = this;
 
@@ -533,6 +548,20 @@ Common::String *Datum::makeString(bool printonly) {
 			*s += *d.makeString(printonly);
 		}
 
+		*s += "]";
+		break;
+	case PARRAY:
+		*s = "[";
+		if (u.parr->size() == 0)
+			*s += ":";
+		for (uint i = 0; i < u.parr->size(); i++) {
+			if (i > 0)
+				*s += ", ";
+			Datum p = *u.parr->operator[](i).p;
+			Datum v = *u.parr->operator[](i).v;
+			*s += Common::String::format("%s:%s", p.makeString(printonly)->c_str(), v.makeString(printonly)->c_str());
+		}
+
 		*s += "]";
 		break;
 	default:
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index cc7655348b..44cccd75d7 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -78,6 +78,7 @@ struct Symbol {	/* symbol table entry */
 		void (*bltin)(int);	/* BUILTIN */
 		Common::String	*s;	/* STRING */
 		DatumArray *farr;	/* ARRAY, POINT, RECT */
+		PropertyArray *parr;
 	} u;
 	int nargs;		/* number of arguments */
 	int maxArgs;	/* maximal number of arguments, for builtins */
@@ -92,6 +93,14 @@ struct Symbol {	/* symbol table entry */
 	Symbol();
 };
 
+struct PCell {
+	Datum *p;
+	Datum *v;
+
+	PCell();
+	PCell(Datum &prop, Datum &val);
+};
+
 struct Datum {	/* interpreter stack type */
 	int type;
 
@@ -101,6 +110,7 @@ struct Datum {	/* interpreter stack type */
 		Common::String *s;	/* STRING */
 		Symbol	*sym;
 		DatumArray *farr;	/* ARRAY, POINT, RECT */
+		PropertyArray *parr; /* PARRAY */
 	} u;
 
 	Datum() { u.sym = NULL; type = VOID; }
diff --git a/engines/director/types.h b/engines/director/types.h
index 647d976144..ac74569a19 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -238,7 +238,9 @@ enum {
 };
 
 struct Datum;
+struct PCell;
 typedef Common::Array<Datum> DatumArray;
+typedef Common::Array<PCell> PropertyArray;
 
 const char *scriptType2str(ScriptType scr);
 


Commit: c74ef4136be3a29badd114ca1b93e4d71e3b9465
    https://github.com/scummvm/scummvm/commit/c74ef4136be3a29badd114ca1b93e4d71e3b9465
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-04-28T23:32:57+02:00

Commit Message:
DIRECTOR: LINGO: Implement property array comparisons

Changed paths:
    engines/director/lingo/lingo-code.cpp
    engines/director/lingo/lingo-code.h
    engines/director/lingo/lingo.cpp


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 52cd7a6303..da14421752 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -995,38 +995,62 @@ void LC::c_not() {
 	g_lingo->push(d);
 }
 
-Datum LC::compareArrays(Datum (*compareFunc)(Datum, Datum), Datum d1, Datum d2) {
+Datum LC::compareArrays(Datum (*compareFunc)(Datum, Datum), Datum d1, Datum d2, bool location, bool value) {
 	// At least one of d1 and d2 must be an array
 	uint arraySize;
 	if (d1.type == ARRAY && d2.type == ARRAY) {
 		arraySize = MIN(d1.u.farr->size(), d2.u.farr->size());
+	} else if (d1.type == PARRAY && d2.type == PARRAY) {
+		arraySize = MIN(d1.u.parr->size(), d2.u.parr->size());
 	} else if (d1.type == ARRAY) {
 		arraySize = d1.u.farr->size();
-	} else {
+	} else if (d1.type == PARRAY) {
+		arraySize = d1.u.parr->size();
+	} else if (d2.type == ARRAY) {
 		arraySize = d2.u.farr->size();
+	} else if (d2.type == PARRAY) {
+		arraySize = d2.u.parr->size();
 	}
+
 	Datum res;
 	res.type = INT;
-	res.u.i = 1;
+	res.u.i = location ? -1 : 1;
 	Datum a = d1;
 	Datum b = d2;
 	for (uint i = 0; i < arraySize; i++) {
 		if (d1.type == ARRAY) {
 			a = d1.u.farr->operator[](i);
+		} else if (d1.type == PARRAY) {
+			PCell t = d1.u.parr->operator[](i);
+			a = value ? *t.v : *t.p;
 		}
+
 		if (d2.type == ARRAY) {
 			b = d2.u.farr->operator[](i);
+		} else if (d2.type == PARRAY) {
+			PCell t = d2.u.parr->operator[](i);
+			b = value ? *t.v : *t.p;
 		}
+
 		res = compareFunc(a, b);
-		if (res.u.i == 0) {
-			break;
+		if (!location) {
+			if (res.u.i == 0) {
+				break;
+			}
+		} else {
+			if (res.u.i == 1) {
+				// Lingo indexing starts at 1
+				res.u.i = (int)i + 1;
+				break;
+			}
 		}
 	}
 	return res;
 }
 
 Datum LC::eqData(Datum d1, Datum d2) {
-	if (d1.type == ARRAY || d2.type == ARRAY) {
+	if (d1.type == ARRAY || d2.type == ARRAY ||
+			d1.type == PARRAY || d2.type == PARRAY) {
 		return LC::compareArrays(LC::eqData, d1, d2);
 	}
 	d1.u.i = (d1.compareTo(d2, true) == 0) ? 1 : 0;
diff --git a/engines/director/lingo/lingo-code.h b/engines/director/lingo/lingo-code.h
index 02abd91164..ac3d61fbb4 100644
--- a/engines/director/lingo/lingo-code.h
+++ b/engines/director/lingo/lingo-code.h
@@ -101,7 +101,7 @@ namespace LC {
 	void c_tell();
 	void c_telldone();
 	void c_exitRepeat();
-	Datum compareArrays(Datum (*compareFunc)(Datum, Datum), Datum d1, Datum d2);
+	Datum compareArrays(Datum (*compareFunc)(Datum, Datum), Datum d1, Datum d2, bool location = false, bool value = false);
 	Datum eqData(Datum d1, Datum d2);
 	void c_eq();
 	Datum neqData(Datum d1, Datum d2);
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 80bd0d03e6..d57c093c94 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -349,10 +349,10 @@ void Lingo::restartLingo() {
 int Lingo::alignTypes(Datum &d1, Datum &d2) {
 	int opType = VOID;
 
-	if (d1.type == REFERENCE)
+	if (d1.type == REFERENCE || d1.type == SYMBOL)
 		d1.makeString();
 
-	if (d2.type == REFERENCE)
+	if (d2.type == REFERENCE || d2.type == SYMBOL)
 		d2.makeString();
 
 	if (d1.type == STRING) {
@@ -609,7 +609,14 @@ const char *Datum::type2str(bool isk) {
 
 int Datum::compareTo(Datum d, bool ignoreCase) {
 	if (type == STRING && d.type == STRING) {
-		return ignoreCase ? u.s->compareToIgnoreCase(*d.u.s) : u.s->compareTo(*d.u.s);
+		if (ignoreCase) {
+			return toLowercaseMac(u.s)->compareTo(*toLowercaseMac(d.u.s));
+		} else {
+			return u.s->compareTo(*d.u.s);
+		}
+	} else if (type == SYMBOL && d.type == SYMBOL) {
+		// TODO: Implement union comparisons
+		return ignoreCase ? u.sym->name.compareToIgnoreCase(d.u.sym->name) : u.sym->name.compareTo(d.u.sym->name);
 	} else if (g_lingo->alignTypes(*this, d) == FLOAT) {
 		if (u.f < d.u.f) {
 			return -1;


Commit: b0d8880919ef68688fc3fd033ceb4aec647d091f
    https://github.com/scummvm/scummvm/commit/b0d8880919ef68688fc3fd033ceb4aec647d091f
Author: Nathanael Gentry (nathanael.gentrydb8 at gmail.com)
Date: 2020-04-28T23:32:57+02:00

Commit Message:
DIRECTOR: LINGO: Implement property array functions

Changed paths:
    engines/director/lingo/lingo-builtins.cpp


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 55a7b934fc..d2c90ca2ea 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -52,6 +52,12 @@ namespace Director {
 		return; \
 	}
 
+#define TYPECHECK2(datum, t1, t2)	\
+	if ((datum).type != (t1) && (datum).type != (t2)) { \
+		warning("%s: %s arg should be of type %s or %s, not %s", __FUNCTION__, #datum, #t1, #t2, (datum).type2str()); \
+		return; \
+	}
+
 #define ARRBOUNDSCHECK(idx,array) \
 	if ((idx)-1 < 0 || (idx) > (array).u.farr->size()) { \
 		warning("%s: index out of bounds (%d of %d)", __FUNCTION__, (idx), (array).u.farr->size()); \
@@ -582,14 +588,30 @@ void LB::b_addAt(int nargs) {
 	Datum list = g_lingo->pop();
 
 	TYPECHECK(index, INT);
+	if (index.type == FLOAT)
+		index.makeInt();
 	TYPECHECK(list, ARRAY);
 
+	if (!((uint)index.u.i < list.u.farr->size())) {
+		for (uint i = 0; i < index.u.i-list.u.farr->size()-1; i++)
+			list.u.farr->push_back(Datum(0));
+	}
 	list.u.farr->insert_at(index.u.i-1, value);
 }
 
 void LB::b_addProp(int nargs) {
-	g_lingo->printSTUBWithArglist("b_addProp", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(3);
+
+	Datum value = g_lingo->pop();
+	Datum prop = g_lingo->pop();
+	Datum list = g_lingo->pop();
+
+	TYPECHECK(list, PARRAY);
+	if (prop.type == REFERENCE)
+		prop = g_lingo->varFetch(prop);
+
+	PCell cell = PCell(prop, value);
+	list.u.parr->push_back(cell);
 }
 
 void LB::b_append(int nargs) {
@@ -607,12 +629,20 @@ void LB::b_count(int nargs) {
 	ARGNUMCHECK(1);
 
 	Datum list = g_lingo->pop();
-
-	TYPECHECK(list, ARRAY);
-
 	Datum result;
 	result.type = INT;
-	result.u.i = list.u.farr->size();
+
+	switch (list.type) {
+	case ARRAY:
+		result.u.i = list.u.farr->size();
+		break;
+	case PARRAY:
+		result.u.i = list.u.parr->size();
+		break;
+	default:
+		TYPECHECK2(list, ARRAY, PARRAY);
+	}
+
 	g_lingo->push(result);
 }
 
@@ -621,31 +651,111 @@ void LB::b_deleteAt(int nargs) {
 
 	Datum index = g_lingo->pop();
 	Datum list = g_lingo->pop();
-
+	if (index.type == FLOAT)
+		index.makeInt();
 	TYPECHECK(index, INT);
-	TYPECHECK(list, ARRAY);
 
-	list.u.farr->remove_at(index.u.i-1);
+	switch (list.type) {
+	case ARRAY:
+		list.u.farr->remove_at(index.u.i-1);
+		break;
+	case PARRAY:
+		list.u.parr->remove_at(index.u.i-1);
+		break;
+	default:
+		TYPECHECK2(list, ARRAY, PARRAY);
+	}
 }
 
 void LB::b_deleteProp(int nargs) {
-	g_lingo->printSTUBWithArglist("b_deleteProp", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(2);
+
+	Datum prop = g_lingo->pop();
+	Datum list = g_lingo->pop();
+
+	switch (list.type) {
+	case ARRAY:
+		g_lingo->push(list);
+		g_lingo->push(prop);
+		b_deleteAt(nargs);
+		break;
+	case PARRAY: {
+		int index = LC::compareArrays(LC::eqData, list, prop, true).u.i;
+		if (index > 0) {
+			list.u.parr->remove_at(index-1);
+		}
+		break;
+	}
+	default:
+		TYPECHECK2(list, ARRAY, PARRAY);
+	}
 }
 
 void LB::b_findPos(int nargs) {
-	g_lingo->printSTUBWithArglist("b_findPos", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(2);
+
+	Datum prop = g_lingo->pop();
+	Datum list = g_lingo->pop();
+	Datum d(0);
+	TYPECHECK(list, PARRAY);
+
+	int index = LC::compareArrays(LC::eqData, list, prop, true).u.i;
+	if (index > 0) {
+		d.type = INT;
+		d.u.i = index;
+	}
+
+	g_lingo->push(d);
 }
 
 void LB::b_findPosNear(int nargs) {
-	g_lingo->printSTUBWithArglist("b_findPosNear", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(2);
+
+	Datum prop = g_lingo->pop();
+	Datum list = g_lingo->pop();
+	Datum d(0);
+	TYPECHECK(list, PARRAY);
+
+	// FIXME: Integrate with compareTo framework
+	prop = prop.makeString();
+	prop.u.s->toLowercase();
+
+	for (uint i = 0; i < list.u.parr->size(); i++) {
+		Datum p = *list.u.parr->operator[](i).p;
+		p.makeString();
+		p.u.s->toLowercase();
+		if (p.u.s->find(prop.u.s->c_str()) == 0) {
+			d.u.i = i+1;
+			break;
+		}
+	}
+
+	g_lingo->push(d);
 }
 
 void LB::b_getaProp(int nargs) {
-	g_lingo->printSTUBWithArglist("b_getaProp", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(2);
+	Datum prop = g_lingo->pop();
+	Datum list = g_lingo->pop();
+
+	switch (list.type) {
+	case ARRAY:
+		g_lingo->push(list);
+		g_lingo->push(prop);
+		b_getAt(nargs);
+		break;
+	case PARRAY: {
+		Datum d;
+		int index = LC::compareArrays(LC::eqData, list, prop, true).u.i;
+		if (index > 0) {
+			d = *list.u.parr->operator[](index-1).v;
+		}
+		g_lingo->push(d);
+		break;
+	}
+	default:
+		TYPECHECK2(list, ARRAY, PARRAY);
+	}
 }
 
 void LB::b_getAt(int nargs) {
@@ -655,38 +765,131 @@ void LB::b_getAt(int nargs) {
 	Datum list = g_lingo->pop();
 	if (index.type == FLOAT)
 		index.makeInt();
-
 	TYPECHECK(index, INT);
-	TYPECHECK(list, ARRAY);
-	ARRBOUNDSCHECK(index.u.i, list);
 
-	Datum result = list.u.farr->operator[](index.u.i-1);
-	g_lingo->push(result);
+	switch (list.type) {
+	case ARRAY:
+		ARRBOUNDSCHECK(index.u.i, list);
+		g_lingo->push(list.u.farr->operator[](index.u.i-1));
+		break;
+	case PARRAY:
+		ARRBOUNDSCHECK(index.u.i, list);
+		g_lingo->push(*list.u.parr->operator[](index.u.i-1).v);
+		break;
+	default:
+		TYPECHECK2(list, ARRAY, PARRAY);
+	}
 }
 
 void LB::b_getLast(int nargs) {
-	g_lingo->printSTUBWithArglist("b_getLast", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(1);
+
+	Datum list = g_lingo->pop();
+	switch (list.type) {
+	case ARRAY:
+		g_lingo->push(list.u.farr->back());
+		break;
+	case PARRAY:
+		g_lingo->push(*list.u.parr->back().v);
+		break;
+	default:
+		TYPECHECK(list, ARRAY);
+	}
 }
 
 void LB::b_getOne(int nargs) {
-	g_lingo->printSTUBWithArglist("b_getOne", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(2);
+	Datum val = g_lingo->pop();
+	Datum list = g_lingo->pop();
+
+	switch (list.type) {
+	case ARRAY:
+		g_lingo->push(list);
+		g_lingo->push(val);
+		b_getPos(nargs);
+		break;
+	case PARRAY: {
+		Datum d;
+		int index = LC::compareArrays(LC::eqData, list, val, true, true).u.i;
+		if (index > 0) {
+			d = *list.u.parr->operator[](index-1).p;
+		}
+		g_lingo->push(d);
+		break;
+	}
+	default:
+		TYPECHECK2(list, ARRAY, PARRAY);
+	}
 }
 
 void LB::b_getPos(int nargs) {
-	g_lingo->printSTUBWithArglist("b_getPos", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(2);
+	Datum val = g_lingo->pop();
+	Datum list = g_lingo->pop();
+
+	switch (list.type) {
+	case ARRAY: {
+		if (val.type == FLOAT)
+			val.makeInt();
+		TYPECHECK(val, INT);
+		Datum d(0);
+		int index = LC::compareArrays(LC::eqData, list, val, true).u.i;
+		if (index > 0) {
+			d.u.i = index;
+		}
+		g_lingo->push(d);
+		break;
+	}
+	case PARRAY: {
+		Datum d(0);
+		int index = LC::compareArrays(LC::eqData, list, val, true, true).u.i;
+		if (index > 0) {
+			d.u.i = index;
+		}
+		g_lingo->push(d);
+		break;
+	}
+	default:
+		TYPECHECK2(list, ARRAY, PARRAY);
+	}
 }
 
 void LB::b_getProp(int nargs) {
-	g_lingo->printSTUBWithArglist("b_getProp", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(2);
+	Datum prop = g_lingo->pop();
+	Datum list = g_lingo->pop();
+
+	switch (list.type) {
+	case ARRAY:
+		g_lingo->push(list);
+		g_lingo->push(prop);
+		b_getPos(nargs);
+		break;
+	case PARRAY: {
+		int index = LC::compareArrays(LC::eqData, list, prop, true).u.i;
+		if (index > 0) {
+			g_lingo->push(*list.u.parr->operator[](index-1).v);
+		} else {
+			error("b_getProp: Property %s not found", prop.makeString()->c_str());
+		}
+		break;
+	}
+	default:
+		TYPECHECK2(list, ARRAY, PARRAY);
+	}
 }
 
 void LB::b_getPropAt(int nargs) {
-	g_lingo->printSTUBWithArglist("b_getPropAt", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(2);
+	Datum index = g_lingo->pop();
+	Datum list = g_lingo->pop();
+	TYPECHECK(list, PARRAY);
+
+	if (index.type == FLOAT)
+		index.makeInt();
+	TYPECHECK(index, INT);
+
+	g_lingo->push(*list.u.parr->operator[](index.u.i-1).p);
 }
 
 void LB::b_list(int nargs) {
@@ -701,8 +904,13 @@ void LB::b_list(int nargs) {
 }
 
 void LB::b_listP(int nargs) {
-	g_lingo->printSTUBWithArglist("b_listP", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(1);
+	Datum list = g_lingo->pop();
+	Datum d(0);
+	if (list.type == ARRAY || list.type == PARRAY) {
+		d.u.i = 1;
+	}
+	g_lingo->push(d);
 }
 
 void LB::b_max(int nargs) {
@@ -772,18 +980,75 @@ void LB::b_min(int nargs) {
 }
 
 void LB::b_setaProp(int nargs) {
-	g_lingo->printSTUBWithArglist("b_setaProp", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(3);
+	Datum value = g_lingo->pop();
+	Datum prop = g_lingo->pop();
+	Datum list = g_lingo->pop();
+
+	switch (list.type) {
+	case ARRAY:
+		g_lingo->push(list);
+		g_lingo->push(prop);
+		g_lingo->push(value);
+		b_setAt(nargs);
+		break;
+	case PARRAY: {
+		int index = LC::compareArrays(LC::eqData, list, prop, true).u.i;
+		if (index > 0) {
+			*list.u.parr->operator[](index-1).v = value;
+		} else {
+			PCell cell = PCell(prop, value);
+			list.u.parr->push_back(cell);
+		}
+		break;
+	}
+	default:
+		TYPECHECK2(list, ARRAY, PARRAY);
+	}
 }
 
 void LB::b_setAt(int nargs) {
-	g_lingo->printSTUBWithArglist("b_setAt", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(3);
+	Datum value = g_lingo->pop();
+	Datum index = g_lingo->pop();
+	Datum list = g_lingo->pop();
+	if (index.type == FLOAT)
+		index.makeInt();
+	TYPECHECK(index, INT);
+
+	switch (list.type) {
+	case ARRAY:
+		if ((uint)index.u.i < list.u.farr->size()) {
+			list.u.farr->operator[](index.u.i-1) = value;
+		} else {
+			// TODO: Extend the list if we request an index beyond it
+			ARRBOUNDSCHECK(index.u.i, list);
+		}
+		break;
+	case PARRAY:
+		ARRBOUNDSCHECK(index.u.i, list);
+		*list.u.parr->operator[](index.u.i-1).v = value;
+		break;
+	default:
+		TYPECHECK2(list, ARRAY, PARRAY);
+	}
 }
 
 void LB::b_setProp(int nargs) {
-	g_lingo->printSTUBWithArglist("b_setProp", nargs);
-	g_lingo->dropStack(nargs);
+	ARGNUMCHECK(3);
+	Datum value = g_lingo->pop();
+	Datum prop = g_lingo->pop();
+	Datum list = g_lingo->pop();
+	TYPECHECK(list, PARRAY);
+	if (prop.type == REFERENCE)
+		prop = g_lingo->varFetch(prop);
+
+	int index = LC::compareArrays(LC::eqData, list, prop, true).u.i;
+	if (index > 0) {
+		*list.u.parr->operator[](index-1).v = value;
+	} else {
+		warning("b_setProp: Property not found");
+	}
 }
 
 void LB::b_sort(int nargs) {




More information about the Scummvm-git-logs mailing list