mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-10 12:55:24 +00:00
DIRECTOR: LINGO: Allow 'the' to fall back to generic object instructions
This commit is contained in:
parent
89152dc2c4
commit
eb6670366e
@ -587,17 +587,14 @@ bool LingoCompiler::visitPutBeforeNode(PutBeforeNode *node) {
|
||||
|
||||
/* SetNode */
|
||||
|
||||
bool LingoCompiler::codeTheFieldSet(int entity, Node *id, const Common::String &field) {
|
||||
Common::String fieldId = Common::String::format("%d%s", entity, field.c_str());
|
||||
if (!g_lingo->_theEntityFields.contains(fieldId)) {
|
||||
warning("BUILDBOT: LingoCompiler::codeTheFieldSet: Unhandled the field %s of %s", field.c_str(), g_lingo->entity2str(entity));
|
||||
return false;
|
||||
int LingoCompiler::getTheFieldID(int entity, const Common::String &field, bool silent) {
|
||||
Common::String fieldKey = Common::String::format("%d%s", entity, field.c_str());
|
||||
if (!g_lingo->_theEntityFields.contains(fieldKey)) {
|
||||
if (!silent)
|
||||
warning("BUILDBOT: LingoCompiler::getTheFieldId: Unhandled the field %s of %s", field.c_str(), g_lingo->entity2str(entity));
|
||||
return -1;
|
||||
}
|
||||
COMPILE(id);
|
||||
code1(LC::c_theentityassign);
|
||||
codeInt(entity);
|
||||
codeInt(g_lingo->_theEntityFields[fieldId]->field);
|
||||
return true;
|
||||
return g_lingo->_theEntityFields[fieldKey]->field;
|
||||
}
|
||||
|
||||
bool LingoCompiler::visitSetNode(SetNode *node) {
|
||||
@ -617,7 +614,6 @@ bool LingoCompiler::visitSetNode(SetNode *node) {
|
||||
}
|
||||
|
||||
if (node->var->type == kTheOfNode) {
|
||||
COMPILE(node->val);
|
||||
TheOfNode *the = static_cast<TheOfNode *>(node->var);
|
||||
switch (the->obj->type) {
|
||||
case kFuncNode:
|
||||
@ -625,10 +621,28 @@ bool LingoCompiler::visitSetNode(SetNode *node) {
|
||||
FuncNode *func = static_cast<FuncNode *>(the->obj);
|
||||
if (func->args->size() == 1) {
|
||||
if (func->name->equalsIgnoreCase("cast")) {
|
||||
return codeTheFieldSet(kTheCast, (*func->args)[0], *the->prop);
|
||||
int fieldId = getTheFieldID(kTheCast, *the->prop, true);
|
||||
if (fieldId >= 0) {
|
||||
COMPILE(node->val);
|
||||
COMPILE((*func->args)[0]);
|
||||
code1(LC::c_theentityassign);
|
||||
codeInt(kTheCast);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
// fall back to generic object
|
||||
}
|
||||
if (func->name->equalsIgnoreCase("field")) {
|
||||
return codeTheFieldSet(kTheField, (*func->args)[0], *the->prop);
|
||||
int fieldId = getTheFieldID(kTheField, *the->prop, true);
|
||||
if (fieldId >= 0) {
|
||||
COMPILE(node->val);
|
||||
COMPILE((*func->args)[0]);
|
||||
code1(LC::c_theentityassign);
|
||||
codeInt(kTheField);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
// fall back to generic object
|
||||
}
|
||||
// window is an object and is handled by that case
|
||||
}
|
||||
@ -637,41 +651,65 @@ bool LingoCompiler::visitSetNode(SetNode *node) {
|
||||
case kMenuNode:
|
||||
{
|
||||
MenuNode *menu = static_cast<MenuNode *>(the->obj);
|
||||
return codeTheFieldSet(kTheMenu, menu->arg, *the->prop);
|
||||
int fieldId = getTheFieldID(kTheMenu, *the->prop);
|
||||
if (fieldId < 0)
|
||||
return false;
|
||||
COMPILE(node->val);
|
||||
COMPILE(menu->arg);
|
||||
code1(LC::c_theentityassign);
|
||||
codeInt(kTheMenu);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case kMenuItemNode:
|
||||
{
|
||||
MenuItemNode *menuItem = static_cast<MenuItemNode *>(the->obj);
|
||||
Common::String fieldId = Common::String::format("%d%s", kTheMenuItem, the->prop->c_str());
|
||||
if (!g_lingo->_theEntityFields.contains(fieldId)) {
|
||||
warning("BUILDBOT: LingoCompiler:visitTheNode: Unhandled the field %s of menuItem", the->prop->c_str());
|
||||
int fieldId = getTheFieldID(kTheMenuItem, *the->prop);
|
||||
if (fieldId < 0)
|
||||
return false;
|
||||
}
|
||||
COMPILE(node->val);
|
||||
COMPILE(menuItem->arg1)
|
||||
COMPILE(menuItem->arg2);
|
||||
code1(LC::c_theentityassign);
|
||||
codeInt(kTheMenuItem);
|
||||
codeInt(g_lingo->_theEntityFields[fieldId]->field);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case kSoundNode:
|
||||
{
|
||||
SoundNode *sound = static_cast<SoundNode *>(the->obj);
|
||||
return codeTheFieldSet(kTheSoundEntity, sound->arg, *the->prop);
|
||||
int fieldId = getTheFieldID(kTheSoundEntity, *the->prop);
|
||||
if (fieldId < 0)
|
||||
return false;
|
||||
COMPILE(node->val);
|
||||
COMPILE(sound->arg);
|
||||
code1(LC::c_theentityassign);
|
||||
codeInt(kTheSoundEntity);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case kSpriteNode:
|
||||
{
|
||||
SpriteNode *sprite = static_cast<SpriteNode *>(the->obj);
|
||||
return codeTheFieldSet(kTheSprite, sprite->arg, *the->prop);
|
||||
int fieldId = getTheFieldID(kTheSprite, *the->prop);
|
||||
if (fieldId < 0)
|
||||
return false;
|
||||
COMPILE(node->val);
|
||||
COMPILE(sprite->arg);
|
||||
code1(LC::c_theentityassign);
|
||||
codeInt(kTheSprite);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case kVarNode:
|
||||
{
|
||||
VarNode *var = static_cast<VarNode *>(the->obj);
|
||||
if (the->prop->equalsIgnoreCase("number") && var->name->equalsIgnoreCase("castMembers")) {
|
||||
COMPILE(node->val);
|
||||
code1(LC::c_intpush);
|
||||
codeInt(0); // Put dummy id
|
||||
code1(LC::c_theentityassign);
|
||||
@ -1166,19 +1204,6 @@ bool LingoCompiler::visitTheNode(TheNode *node) {
|
||||
|
||||
/* TheOfNode */
|
||||
|
||||
bool LingoCompiler::codeTheFieldGet(int entity, Node *id, const Common::String &field) {
|
||||
Common::String fieldId = Common::String::format("%d%s", entity, field.c_str());
|
||||
if (!g_lingo->_theEntityFields.contains(fieldId)) {
|
||||
warning("BUILDBOT: LingoCompiler::codeTheFieldGet: Unhandled the field %s of %s", field.c_str(), g_lingo->entity2str(entity));
|
||||
return false;
|
||||
}
|
||||
COMPILE(id);
|
||||
code1(LC::c_theentitypush);
|
||||
codeInt(entity);
|
||||
codeInt(g_lingo->_theEntityFields[fieldId]->field);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LingoCompiler::visitTheOfNode(TheOfNode *node) {
|
||||
switch (node->obj->type) {
|
||||
case kFuncNode:
|
||||
@ -1186,10 +1211,26 @@ bool LingoCompiler::visitTheOfNode(TheOfNode *node) {
|
||||
FuncNode *func = static_cast<FuncNode *>(node->obj);
|
||||
if (func->args->size() == 1) {
|
||||
if (func->name->equalsIgnoreCase("cast")) {
|
||||
return codeTheFieldGet(kTheCast, (*func->args)[0], *node->prop);
|
||||
int fieldId = getTheFieldID(kTheCast, *node->prop, true);
|
||||
if (fieldId >= 0) {
|
||||
COMPILE((*func->args)[0]);
|
||||
code1(LC::c_theentitypush);
|
||||
codeInt(kTheCast);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
// fall back to generic object
|
||||
}
|
||||
if (func->name->equalsIgnoreCase("field")) {
|
||||
return codeTheFieldGet(kTheField, (*func->args)[0], *node->prop);
|
||||
int fieldId = getTheFieldID(kTheField, *node->prop, true);
|
||||
if (fieldId >= 0) {
|
||||
COMPILE((*func->args)[0]);
|
||||
code1(LC::c_theentitypush);
|
||||
codeInt(kTheField);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
// fall back to generic object
|
||||
}
|
||||
// window is an object and is handled by that case
|
||||
}
|
||||
@ -1198,35 +1239,54 @@ bool LingoCompiler::visitTheOfNode(TheOfNode *node) {
|
||||
case kMenuNode:
|
||||
{
|
||||
MenuNode *menu = static_cast<MenuNode *>(node->obj);
|
||||
return codeTheFieldGet(kTheMenu, menu->arg, *node->prop);
|
||||
int fieldId = getTheFieldID(kTheMenu, *node->prop);
|
||||
if (fieldId < 0)
|
||||
return false;
|
||||
COMPILE(menu->arg);
|
||||
code1(LC::c_theentitypush);
|
||||
codeInt(kTheMenu);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case kMenuItemNode:
|
||||
{
|
||||
MenuItemNode *menuItem = static_cast<MenuItemNode *>(node->obj);
|
||||
Common::String fieldId = Common::String::format("%d%s", kTheMenuItem, node->prop->c_str());
|
||||
if (!g_lingo->_theEntityFields.contains(fieldId)) {
|
||||
warning("BUILDBOT: LingoCompiler:visitTheNode: Unhandled the field %s of menuItem", node->prop->c_str());
|
||||
int fieldId = getTheFieldID(kTheMenuItem, *node->prop);
|
||||
if (fieldId < 0)
|
||||
return false;
|
||||
}
|
||||
COMPILE(menuItem->arg1)
|
||||
COMPILE(menuItem->arg2);
|
||||
code1(LC::c_theentitypush);
|
||||
codeInt(kTheMenuItem);
|
||||
codeInt(g_lingo->_theEntityFields[fieldId]->field);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case kSoundNode:
|
||||
{
|
||||
SoundNode *sound = static_cast<SoundNode *>(node->obj);
|
||||
return codeTheFieldGet(kTheSoundEntity, sound->arg, *node->prop);
|
||||
int fieldId = getTheFieldID(kTheSoundEntity, *node->prop);
|
||||
if (fieldId < 0)
|
||||
return false;
|
||||
COMPILE(sound->arg);
|
||||
code1(LC::c_theentitypush);
|
||||
codeInt(kTheSoundEntity);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case kSpriteNode:
|
||||
{
|
||||
SpriteNode *sprite = static_cast<SpriteNode *>(node->obj);
|
||||
return codeTheFieldGet(kTheSprite, sprite->arg, *node->prop);
|
||||
int fieldId = getTheFieldID(kTheSprite, *node->prop);
|
||||
if (fieldId < 0)
|
||||
return false;
|
||||
COMPILE(sprite->arg);
|
||||
code1(LC::c_theentitypush);
|
||||
codeInt(kTheSprite);
|
||||
codeInt(fieldId);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case kVarNode:
|
||||
|
@ -50,8 +50,7 @@ public:
|
||||
void codeVarSet(const Common::String &name);
|
||||
void codeVarRef(const Common::String &name);
|
||||
void codeVarGet(const Common::String &name);
|
||||
bool codeTheFieldSet(int entity, Node *id, const Common::String &field);
|
||||
bool codeTheFieldGet(int entity, Node *id, const Common::String &field);
|
||||
int getTheFieldID(int entity, const Common::String &field, bool silent = false);
|
||||
void registerFactory(Common::String &s);
|
||||
void registerMethodVar(const Common::String &name, VarType type = kVarGeneric);
|
||||
void updateLoopJumps(uint nextTargetPos, uint exitTargetPos);
|
||||
|
Loading…
x
Reference in New Issue
Block a user