DIRECTOR: LINGO: Implement chunk refs

This commit is contained in:
djsrv 2020-08-21 21:35:53 -04:00
parent 3bf6f79a3e
commit c147a5c979
8 changed files with 1058 additions and 1059 deletions

View File

@ -875,266 +875,226 @@ void LC::c_within() {
}
}
Datum LC::chunkRef(ChunkType type, int startChunk, int endChunk, const Datum &src) {
// A chunk expression is made up of 0 or more chunks within a source text.
// These chunks are called chars, words, items, or lines, but it's easier to think of them
// as a substring between 0 or more skip characters and a break character (or the end of the string).
// This function returns a reference to the source text, the start index of the first chunk,
// and the end index of the last chunk in the chunk expression.
if (startChunk < 1 || (0 > endChunk && endChunk < startChunk))
return src;
if (endChunk < 1)
endChunk = startChunk;
Common::String skipChars;
Common::String breakChars;
switch (type) {
case kChunkChar:
skipChars = "";
breakChars = "";
break;
case kChunkWord:
skipChars = "\t\n\r ";
breakChars = "\t\n\r ";
break;
case kChunkItem:
skipChars = "";
breakChars = Common::String::format("%c", g_lingo->_itemDelimiter);
break;
case kChunkLine:
skipChars = "";
breakChars = "\n\r";
break;
}
Common::String str = src.asString();
int idx = 0;
int chunkNum = 0;
int startIdx = -1;
int endIdx = -1;
while (true) {
// each iteration processes one chunk
// find the start of the chunk
while (idx < (int)str.size() && skipChars.contains(str[idx])) {
idx++;
}
chunkNum++;
if (chunkNum == startChunk) {
startIdx = idx; // found start of chunk expression
}
// find the end of the chunk
if (!breakChars.empty()) {
while (idx < (int)str.size() && !breakChars.contains(str[idx])) {
idx++;
}
} else if (idx < (int)str.size()) {
idx++;
}
if (chunkNum == endChunk || idx == (int)str.size()) {
endIdx = idx; // found end of chunk expression
break;
}
if (!breakChars.empty())
idx++; // skip break char
}
if (startIdx < 0)
startIdx = endIdx;
Datum res;
res.u.cref = new ChunkReference(src, startIdx, endIdx);
res.type = CHUNKREF;
return res;
}
void LC::c_of() {
// put char 5 of word 1 of line 2 into field "thing"
Datum target = g_lingo->pop();
Datum last_line = g_lingo->pop();
Datum first_line = g_lingo->pop();
Datum last_item = g_lingo->pop();
Datum first_item = g_lingo->pop();
Datum last_word = g_lingo->pop();
Datum first_word = g_lingo->pop();
Datum last_char = g_lingo->pop();
Datum first_char = g_lingo->pop();
Datum src = g_lingo->pop();
Datum lastLine = g_lingo->pop();
Datum firstLine = g_lingo->pop();
Datum lastItem = g_lingo->pop();
Datum firstItem = g_lingo->pop();
Datum lastWord = g_lingo->pop();
Datum firstWord = g_lingo->pop();
Datum lastChar = g_lingo->pop();
Datum firstChar = g_lingo->pop();
Common::String result = target.asString();
Datum res = src;
if (first_line.u.i > 0) {
Common::String newline("\r");
int first = first_line.u.i;
int last = first;
if (last_line.u.i > 0) {
if ((first_item.u.i > 0) || (first_word.u.i > 0) || (first_char.u.i > 0)) {
warning("LC::c_of(): last_line defined but unused");
} else if (last_line.u.i < first_line.u.i) {
warning("LC::c_of(): last_line before first_line, ignoring");
} else {
last = last_line.u.i;
}
}
uint32 pointer = 0;
int curLine = 0;
int firstIndex = -1;
int lastIndex = -1;
while (pointer < result.size()) {
curLine += 1;
if (curLine == first) {
firstIndex = pointer;
}
pointer = result.find(newline, pointer);
if (curLine == last) {
lastIndex = pointer;
break;
}
}
if (firstIndex < 0 || lastIndex < 0) {
warning("LC::c_of(): first_line or last_line out of range");
result = "";
} else {
result = result.substr(firstIndex, lastIndex);
}
}
if (firstChar.asInt() > 0)
res = LC::chunkRef(kChunkChar, firstChar.asInt(), lastChar.asInt(), src);
else if (firstWord.asInt() > 0)
res = LC::chunkRef(kChunkWord, firstWord.asInt(), lastWord.asInt(), src);
else if (firstItem.asInt() > 0)
res = LC::chunkRef(kChunkItem, firstItem.asInt(), lastItem.asInt(), src);
else if (lastLine.asInt() > 0)
res = LC::chunkRef(kChunkLine, firstLine.asInt(), lastLine.asInt(), src);
if (first_item.u.i > 0 || last_item.u.i > 0) {
warning("STUB: LC::c_of() item indexing");
}
if (first_word.u.i > 0) {
int first = first_word.u.i;
int last = first;
if (last_word.u.i > 0) {
if (first_char.u.i > 0) {
warning("LC::c_of(): last_word defined but unused");
} else if (last_word.u.i < first_word.u.i) {
warning("LC::c_of(): last_word before first_word, ignoring");
} else {
last = last_word.u.i;
}
}
uint32 pointer = 0;
int curWord = 0;
int firstIndex = -1;
int lastIndex = -1;
bool inWord = false;
while (pointer < result.size()) {
if ((result[pointer] == '\r') || (result[pointer] == '\t') ||
(result[pointer] == '\n') || (result[pointer] == ' ')) {
if (inWord) {
inWord = false;
if (last == curWord) {
break;
}
}
} else {
if (!inWord) {
inWord = true;
curWord += 1;
if (first == curWord) {
firstIndex = pointer;
}
}
}
pointer += 1;
}
lastIndex = pointer;
if (firstIndex < 0) {
warning("LC::c_of(): first_word out of range");
result = "";
} else {
result = result.substr(firstIndex, lastIndex - firstIndex);
}
}
if (first_char.u.i > 0) {
int first = first_char.u.i;
int last = first;
if (last_char.u.i > 0) {
if (last_char.u.i < first_char.u.i) {
warning("LC::c_of(): last_char before first_char, ignoring");
} else {
last = last_char.u.i;
}
}
result = result.substr(first - 1, last - first);
}
target = Datum(result);
g_lingo->push(target);
g_lingo->push(res);
}
void LC::c_charOf() {
Datum d2 = g_lingo->pop(); // string
Datum d1 = g_lingo->pop(); // index
Datum src = g_lingo->pop(false);
Datum index = g_lingo->pop();
if ((d1.type != INT && d1.type != FLOAT) || d2.type != STRING) {
warning("LC::c_charOf(): Called with wrong data types: %s and %s", d1.type2str(), d2.type2str());
if ((index.type != INT && index.type != FLOAT)
|| (src.type != STRING && src.type != VAR && src.type != FIELDREF && src.type != CHUNKREF && src.type != CASTREF)) {
g_lingo->lingoError("LC::c_charOf(): Called with wrong data types: %s and %s", index.type2str(), src.type2str());
g_lingo->push(Datum(""));
return;
}
Datum res;
int index = d1.asInt();
Common::String chunkExpr = *d2.u.s;
if (index < 1)
res = Datum(chunkExpr);
else if (uint(index) > chunkExpr.size())
res = Datum("");
else
res = Datum(Common::String(chunkExpr[index - 1]));
g_lingo->push(res);
g_lingo->push(LC::chunkRef(kChunkChar, index.asInt(), 0, src));
}
void LC::c_charToOf() {
Datum d3 = g_lingo->pop(); // string
Datum d2 = g_lingo->pop(); // indexFrom
Datum d1 = g_lingo->pop(); // indexTo
Datum src = g_lingo->pop(false);
Datum indexTo = g_lingo->pop();
Datum indexFrom = g_lingo->pop();
if ((d1.type != INT && d1.type != FLOAT) || (d2.type != INT && d2.type != FLOAT) || d3.type != STRING) {
warning("LC::c_charToOf(): Called with wrong data types: %s, %s and %s", d1.type2str(), d2.type2str(), d3.type2str());
if ((indexTo.type != INT && indexTo.type != FLOAT) || (indexFrom.type != INT && indexFrom.type != FLOAT)
|| (src.type != STRING && src.type != VAR && src.type != FIELDREF && src.type != CHUNKREF && src.type != CASTREF)) {
warning("LC::c_charToOf(): Called with wrong data types: %s, %s and %s", indexTo.type2str(), indexFrom.type2str(), src.type2str());
g_lingo->push(Datum(""));
return;
}
int indexFrom = d1.asInt();
int indexTo = d2.asInt();
Common::String chunkExpr = *d3.u.s;
Datum res;
// The if order is important. It mimicks the checks, i.e. bugs, of Director 4.
if (indexFrom < 1)
res = Datum(chunkExpr);
else if (indexTo < 1)
res = Datum(Common::String(chunkExpr[indexFrom - 1])); // treat as charOf
else if (indexFrom > indexTo)
res = Datum("");
else if (uint(indexFrom) > chunkExpr.size())
res = Datum("");
else
res = Datum(chunkExpr.substr(indexFrom - 1, indexTo - indexFrom + 1));
g_lingo->push(res);
g_lingo->push(LC::chunkRef(kChunkChar, indexFrom.asInt(), indexTo.asInt(), src));
}
void LC::c_itemOf() {
Datum src = g_lingo->pop(false);
Datum index = g_lingo->pop();
Datum d2 = g_lingo->pop(); // chunkExpression
Datum d1 = g_lingo->pop(); // index
char delimiter = g_lingo->_itemDelimiter;
if ((d1.type != INT && d1.type != FLOAT) || d2.type != STRING) {
warning("LC::c_itemOf(): Called with wrong data types: %s and %s", d1.type2str(), d2.type2str());
if ((index.type != INT && index.type != FLOAT)
|| (src.type != STRING && src.type != VAR && src.type != FIELDREF && src.type != CHUNKREF && src.type != CASTREF)) {
warning("LC::c_itemOf(): Called with wrong data types: %s and %s", index.type2str(), src.type2str());
g_lingo->push(Datum(""));
return;
}
int index = d1.asInt();
if (index < 1) {
// returns the input string
g_lingo->push(d2);
return;
}
Common::String chunkExpr = *d2.u.s;
uint startPos = 0;
while (index-- > 1) {
startPos = chunkExpr.find(delimiter, startPos);
if (startPos == Common::String::npos)
break;
startPos++; // skipping comma
}
Datum res;
if (startPos == Common::String::npos) {
res = Datum("");
} else {
uint endPos = chunkExpr.find(delimiter, startPos);
if (endPos == Common::String::npos)
endPos = chunkExpr.size();
res = Datum(chunkExpr.substr(startPos, endPos - startPos));
}
g_lingo->push(res);
g_lingo->push(LC::chunkRef(kChunkItem, index.asInt(), 0, src));
}
void LC::c_itemToOf() {
Datum d3 = g_lingo->pop();
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
Datum src = g_lingo->pop(false);
Datum indexTo = g_lingo->pop();
Datum indexFrom = g_lingo->pop();
warning("STUB: LC::c_itemToOf(): %d %d %d", d1.u.i, d2.u.i, d3.u.i);
if ((indexTo.type != INT && indexTo.type != FLOAT) || (indexFrom.type != INT && indexFrom.type != FLOAT)
|| (src.type != STRING && src.type != VAR && src.type != FIELDREF && src.type != CHUNKREF && src.type != CASTREF)) {
warning("LC::c_itemToOf(): Called with wrong data types: %s, %s and %s", indexTo.type2str(), indexFrom.type2str(), src.type2str());
g_lingo->push(Datum(""));
return;
}
g_lingo->push(d1);
g_lingo->push(LC::chunkRef(kChunkItem, indexFrom.asInt(), indexTo.asInt(), src));
}
void LC::c_lineOf() {
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
Datum src = g_lingo->pop(false);
Datum index = g_lingo->pop();
warning("STUB: LC::c_lineOf(): %d %d", d1.u.i, d2.u.i);
if ((index.type != INT && index.type != FLOAT)
|| (src.type != STRING && src.type != VAR && src.type != FIELDREF && src.type != CHUNKREF && src.type != CASTREF)) {
warning("LC::c_lineOf(): Called with wrong data types: %s and %s", index.type2str(), src.type2str());
g_lingo->push(Datum(""));
return;
}
g_lingo->push(d1);
g_lingo->push(LC::chunkRef(kChunkLine, index.asInt(), 0, src));
}
void LC::c_lineToOf() {
Datum d3 = g_lingo->pop();
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
Datum src = g_lingo->pop(false);
Datum indexTo = g_lingo->pop();
Datum indexFrom = g_lingo->pop();
warning("STUB: LC::c_lineToOf(): %d %d %d", d1.u.i, d2.u.i, d3.u.i);
if ((indexTo.type != INT && indexTo.type != FLOAT) || (indexFrom.type != INT && indexFrom.type != FLOAT)
|| (src.type != STRING && src.type != VAR && src.type != FIELDREF && src.type != CHUNKREF && src.type != CASTREF)) {
warning("LC::c_lineToOf(): Called with wrong data types: %s, %s and %s", indexTo.type2str(), indexFrom.type2str(), src.type2str());
g_lingo->push(Datum(""));
return;
}
g_lingo->push(d1);
g_lingo->push(LC::chunkRef(kChunkLine, indexFrom.asInt(), indexTo.asInt(), src));
}
void LC::c_wordOf() {
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
Datum src = g_lingo->pop(false);
Datum index = g_lingo->pop();
warning("STUB: LC::c_wordOf(): %d %d", d1.u.i, d2.u.i);
if ((index.type != INT && index.type != FLOAT)
|| (src.type != STRING && src.type != VAR && src.type != FIELDREF && src.type != CHUNKREF && src.type != CASTREF)) {
warning("LC::c_wordOf(): Called with wrong data types: %s and %s", index.type2str(), src.type2str());
g_lingo->push(Datum(""));
return;
}
g_lingo->push(d1);
g_lingo->push(LC::chunkRef(kChunkWord, index.asInt(), 0, src));
}
void LC::c_wordToOf() {
Datum d3 = g_lingo->pop();
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
Datum src = g_lingo->pop(false);
Datum indexTo = g_lingo->pop();
Datum indexFrom = g_lingo->pop();
warning("STUB: LC::c_wordToOf(): %d %d %d", d1.u.i, d2.u.i, d3.u.i);
if ((indexTo.type != INT && indexTo.type != FLOAT) || (indexFrom.type != INT && indexFrom.type != FLOAT)
|| (src.type != STRING && src.type != VAR && src.type != FIELDREF && src.type != CHUNKREF && src.type != CASTREF)) {
warning("LC::c_wordToOf(): Called with wrong data types: %s, %s and %s", indexTo.type2str(), indexFrom.type2str(), src.type2str());
g_lingo->push(Datum(""));
return;
}
g_lingo->push(d1);
g_lingo->push(LC::chunkRef(kChunkWord, indexFrom.asInt(), indexTo.asInt(), src));
}
void LC::c_and() {

View File

@ -56,6 +56,7 @@ void c_starts();
void c_intersects();
void c_within();
Datum chunkRef(ChunkType type, int startChunk, int endChunk, const Datum &src);
void c_of();
void c_charOf();
void c_charToOf();

File diff suppressed because it is too large Load Diff

View File

@ -65,81 +65,82 @@ extern int yydebug;
PARRAY = 266, /* PARRAY */
CASTREF = 267, /* CASTREF */
FIELDREF = 268, /* FIELDREF */
INT = 269, /* INT */
ARGC = 270, /* ARGC */
ARGCNORET = 271, /* ARGCNORET */
THEENTITY = 272, /* THEENTITY */
THEENTITYWITHID = 273, /* THEENTITYWITHID */
THEMENUITEMENTITY = 274, /* THEMENUITEMENTITY */
THEMENUITEMSENTITY = 275, /* THEMENUITEMSENTITY */
FLOAT = 276, /* FLOAT */
THEFUNC = 277, /* THEFUNC */
THEFUNCINOF = 278, /* THEFUNCINOF */
VARID = 279, /* VARID */
STRING = 280, /* STRING */
SYMBOL = 281, /* SYMBOL */
ENDCLAUSE = 282, /* ENDCLAUSE */
tPLAYACCEL = 283, /* tPLAYACCEL */
tMETHOD = 284, /* tMETHOD */
THEOBJECTPROP = 285, /* THEOBJECTPROP */
tCAST = 286, /* tCAST */
tFIELD = 287, /* tFIELD */
tSCRIPT = 288, /* tSCRIPT */
tWINDOW = 289, /* tWINDOW */
tDOWN = 290, /* tDOWN */
tELSE = 291, /* tELSE */
tELSIF = 292, /* tELSIF */
tEXIT = 293, /* tEXIT */
tGLOBAL = 294, /* tGLOBAL */
tGO = 295, /* tGO */
tGOLOOP = 296, /* tGOLOOP */
tIF = 297, /* tIF */
tIN = 298, /* tIN */
tINTO = 299, /* tINTO */
tMACRO = 300, /* tMACRO */
tMOVIE = 301, /* tMOVIE */
tNEXT = 302, /* tNEXT */
tOF = 303, /* tOF */
tPREVIOUS = 304, /* tPREVIOUS */
tPUT = 305, /* tPUT */
tREPEAT = 306, /* tREPEAT */
tSET = 307, /* tSET */
tTHEN = 308, /* tTHEN */
tTO = 309, /* tTO */
tWHEN = 310, /* tWHEN */
tWITH = 311, /* tWITH */
tWHILE = 312, /* tWHILE */
tFACTORY = 313, /* tFACTORY */
tOPEN = 314, /* tOPEN */
tPLAY = 315, /* tPLAY */
tINSTANCE = 316, /* tINSTANCE */
tGE = 317, /* tGE */
tLE = 318, /* tLE */
tEQ = 319, /* tEQ */
tNEQ = 320, /* tNEQ */
tAND = 321, /* tAND */
tOR = 322, /* tOR */
tNOT = 323, /* tNOT */
tMOD = 324, /* tMOD */
tAFTER = 325, /* tAFTER */
tBEFORE = 326, /* tBEFORE */
tCONCAT = 327, /* tCONCAT */
tCONTAINS = 328, /* tCONTAINS */
tSTARTS = 329, /* tSTARTS */
tCHAR = 330, /* tCHAR */
tITEM = 331, /* tITEM */
tLINE = 332, /* tLINE */
tWORD = 333, /* tWORD */
tSPRITE = 334, /* tSPRITE */
tINTERSECTS = 335, /* tINTERSECTS */
tWITHIN = 336, /* tWITHIN */
tTELL = 337, /* tTELL */
tPROPERTY = 338, /* tPROPERTY */
tON = 339, /* tON */
tENDIF = 340, /* tENDIF */
tENDREPEAT = 341, /* tENDREPEAT */
tENDTELL = 342, /* tENDTELL */
tASSERTERROR = 343 /* tASSERTERROR */
CHUNKREF = 269, /* CHUNKREF */
INT = 270, /* INT */
ARGC = 271, /* ARGC */
ARGCNORET = 272, /* ARGCNORET */
THEENTITY = 273, /* THEENTITY */
THEENTITYWITHID = 274, /* THEENTITYWITHID */
THEMENUITEMENTITY = 275, /* THEMENUITEMENTITY */
THEMENUITEMSENTITY = 276, /* THEMENUITEMSENTITY */
FLOAT = 277, /* FLOAT */
THEFUNC = 278, /* THEFUNC */
THEFUNCINOF = 279, /* THEFUNCINOF */
VARID = 280, /* VARID */
STRING = 281, /* STRING */
SYMBOL = 282, /* SYMBOL */
ENDCLAUSE = 283, /* ENDCLAUSE */
tPLAYACCEL = 284, /* tPLAYACCEL */
tMETHOD = 285, /* tMETHOD */
THEOBJECTPROP = 286, /* THEOBJECTPROP */
tCAST = 287, /* tCAST */
tFIELD = 288, /* tFIELD */
tSCRIPT = 289, /* tSCRIPT */
tWINDOW = 290, /* tWINDOW */
tDOWN = 291, /* tDOWN */
tELSE = 292, /* tELSE */
tELSIF = 293, /* tELSIF */
tEXIT = 294, /* tEXIT */
tGLOBAL = 295, /* tGLOBAL */
tGO = 296, /* tGO */
tGOLOOP = 297, /* tGOLOOP */
tIF = 298, /* tIF */
tIN = 299, /* tIN */
tINTO = 300, /* tINTO */
tMACRO = 301, /* tMACRO */
tMOVIE = 302, /* tMOVIE */
tNEXT = 303, /* tNEXT */
tOF = 304, /* tOF */
tPREVIOUS = 305, /* tPREVIOUS */
tPUT = 306, /* tPUT */
tREPEAT = 307, /* tREPEAT */
tSET = 308, /* tSET */
tTHEN = 309, /* tTHEN */
tTO = 310, /* tTO */
tWHEN = 311, /* tWHEN */
tWITH = 312, /* tWITH */
tWHILE = 313, /* tWHILE */
tFACTORY = 314, /* tFACTORY */
tOPEN = 315, /* tOPEN */
tPLAY = 316, /* tPLAY */
tINSTANCE = 317, /* tINSTANCE */
tGE = 318, /* tGE */
tLE = 319, /* tLE */
tEQ = 320, /* tEQ */
tNEQ = 321, /* tNEQ */
tAND = 322, /* tAND */
tOR = 323, /* tOR */
tNOT = 324, /* tNOT */
tMOD = 325, /* tMOD */
tAFTER = 326, /* tAFTER */
tBEFORE = 327, /* tBEFORE */
tCONCAT = 328, /* tCONCAT */
tCONTAINS = 329, /* tCONTAINS */
tSTARTS = 330, /* tSTARTS */
tCHAR = 331, /* tCHAR */
tITEM = 332, /* tITEM */
tLINE = 333, /* tLINE */
tWORD = 334, /* tWORD */
tSPRITE = 335, /* tSPRITE */
tINTERSECTS = 336, /* tINTERSECTS */
tWITHIN = 337, /* tWITHIN */
tTELL = 338, /* tTELL */
tPROPERTY = 339, /* tPROPERTY */
tON = 340, /* tON */
tENDIF = 341, /* tENDIF */
tENDREPEAT = 342, /* tENDREPEAT */
tENDTELL = 343, /* tENDTELL */
tASSERTERROR = 344 /* tASSERTERROR */
};
typedef enum yytokentype yytoken_kind_t;
#endif
@ -163,7 +164,7 @@ union YYSTYPE
Common::String *prop;
} objectprop;
#line 167 "engines/director/lingo/lingo-gr.h"
#line 168 "engines/director/lingo/lingo-gr.h"
};
typedef union YYSTYPE YYSTYPE;

View File

@ -196,7 +196,7 @@ static void mVar(Common::String *s, VarType type) {
// Datum types
%token VOID VAR POINT RECT ARRAY OBJECT LEXERROR PARRAY
%token CASTREF FIELDREF
%token CASTREF FIELDREF CHUNKREF
%token<i> INT ARGC ARGCNORET
%token<e> THEENTITY THEENTITYWITHID THEMENUITEMENTITY THEMENUITEMSENTITY

View File

@ -838,6 +838,9 @@ void Datum::reset() {
delete u.obj;
}
break;
case CHUNKREF:
delete u.cref;
break;
default:
break;
}
@ -848,7 +851,7 @@ void Datum::reset() {
}
Datum Datum::eval() {
if (type == VAR || type == FIELDREF) {
if (type == VAR || type == FIELDREF || type == CHUNKREF) {
return g_lingo->varFetch(*this);
}
@ -982,6 +985,12 @@ Common::String Datum::asString(bool printonly) const {
s = Common::String::format("field: \"%s\"", ((TextCastMember *)member)->getText().c_str());
}
break;
case CHUNKREF:
{
Common::String src = u.cref->source.asString(true);
s = Common::String::format("chunk: char %d to %d of %s", u.cref->start, u.cref->end, src.c_str());
}
break;
case POINT:
s = "point:";
// fallthrough
@ -1076,6 +1085,8 @@ const char *Datum::type2str(bool isk) const {
return isk ? "#object" : "OBJECT";
case FIELDREF:
return "FIELDREF";
case CHUNKREF:
return "CHUNKREF";
case VAR:
return isk ? "#var" : "VAR";
default:
@ -1360,6 +1371,10 @@ Datum Lingo::varFetch(Datum &var, bool global, DatumHash *localvars, bool silent
warning("varFetch: Unhandled cast type %d", member->_type);
break;
}
} else if (var.type == CHUNKREF) {
Common::String src = var.u.cref->source.eval().asString();
result.type = STRING;
result.u.s = new Common::String(src.substr(var.u.cref->start, var.u.cref->end - var.u.cref->start));
} else {
warning("varFetch: fetch from non-variable");
}

View File

@ -37,6 +37,7 @@ class SeekableReadStreamEndian;
namespace Director {
struct ChunkReference;
struct TheEntity;
struct TheEntityField;
struct LingoArchive;
@ -116,7 +117,8 @@ struct Datum { /* interpreter stack type */
Common::String *s; /* STRING, VAR, OBJECT */
DatumArray *farr; /* ARRAY, POINT, RECT */
PropertyArray *parr; /* PARRAY */
AbstractObject *obj;
AbstractObject *obj; /* OBJECT */
ChunkReference *cref; /* CHUNKREF */
} u;
int *refCount;
@ -146,6 +148,14 @@ struct Datum { /* interpreter stack type */
int compareTo(Datum &d, bool ignoreCase = false) const;
};
struct ChunkReference {
Datum source;
int start;
int end;
ChunkReference(const Datum &src, uint s, uint e) : source(src), start(s), end(e) {}
};
struct PCell {
Datum p;
Datum v;

View File

@ -307,6 +307,13 @@ enum SymbolType {
HANDLER // user-defined handler
};
enum ChunkType {
kChunkChar,
kChunkWord,
kChunkItem,
kChunkLine
};
struct Datum;
struct PCell;
typedef Common::Array<Datum> DatumArray;