[Scummvm-git-logs] scummvm master -> 71ea2d7f57766bd8a498dfc3bf76d90f434a993a
scemino
noreply at scummvm.org
Fri May 17 20:41:22 UTC 2024
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
71ea2d7f57 DIRECTOR: Remove use of CodeWriter
Commit: 71ea2d7f57766bd8a498dfc3bf76d90f434a993a
https://github.com/scummvm/scummvm/commit/71ea2d7f57766bd8a498dfc3bf76d90f434a993a
Author: scemino (scemino74 at gmail.com)
Date: 2024-05-17T22:37:33+02:00
Commit Message:
DIRECTOR: Remove use of CodeWriter
Changed paths:
A engines/director/lingo/lingodec/codewritervisitor.cpp
A engines/director/lingo/lingodec/codewritervisitor.h
R engines/director/lingo/lingodec/codewriter.cpp
R engines/director/lingo/lingodec/codewriter.h
engines/director/debugtools.cpp
engines/director/lingo/lingodec/ast.cpp
engines/director/lingo/lingodec/ast.h
engines/director/lingo/lingodec/handler.cpp
engines/director/lingo/lingodec/handler.h
engines/director/lingo/lingodec/script.cpp
engines/director/lingo/lingodec/script.h
engines/director/module.mk
diff --git a/engines/director/debugtools.cpp b/engines/director/debugtools.cpp
index d81bde6a9eb..8cf8fc042da 100644
--- a/engines/director/debugtools.cpp
+++ b/engines/director/debugtools.cpp
@@ -32,7 +32,7 @@
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-object.h"
#include "director/lingo/lingodec/ast.h"
-#include "director/lingo/lingodec/codewriter.h"
+#include "director/lingo/lingodec/codewritervisitor.h"
#include "director/lingo/lingodec/context.h"
#include "director/lingo/lingodec/handler.h"
#include "director/lingo/lingodec/resolver.h"
@@ -102,67 +102,67 @@ public:
LingoDec::Script *script = node.handler->script;
bool isMethod = script->isFactory();
{
- LingoDec::CodeWriter code("\n");
+ Common::String code;
if (isMethod) {
- code.write("method ");
+ code += "method ";
} else {
- code.write("on ");
+ code += "on ";
}
- code.write(node.handler->name);
+ code += node.handler->name;
if (node.handler->argumentNames.size() > 0) {
- code.write(" ");
+ code += " ";
for (size_t i = 0; i < node.handler->argumentNames.size(); i++) {
if (i > 0)
- code.write(", ");
- code.write(node.handler->argumentNames[i]);
+ code += ", ";
+ code += node.handler->argumentNames[i];
}
}
- write(node._startOffset, code.str());
+ write(node._startOffset, code);
}
{
- LingoDec::CodeWriter code("\n");
+ Common::String code;
if (isMethod && node.handler->script->propertyNames.size() > 0 && node.handler == &node.handler->script->handlers[0]) {
- code.write("instance ");
+ code += "instance ";
for (size_t i = 0; i < node.handler->script->propertyNames.size(); i++) {
if (i > 0)
- code.write(", ");
- code.write(node.handler->script->propertyNames[i]);
+ code += ", ";
+ code += node.handler->script->propertyNames[i];
}
- write(node._startOffset, code.str());
+ write(node._startOffset, code);
}
}
{
if (node.handler->globalNames.size() > 0) {
- LingoDec::CodeWriter code("\n");
- code.write("global ");
+ Common::String code;
+ code += "global ";
for (size_t i = 0; i < node.handler->globalNames.size(); i++) {
if (i > 0)
- code.write(", ");
- code.write(node.handler->globalNames[i]);
+ code += ", ";
+ code += node.handler->globalNames[i];
}
- write(node._startOffset, code.str());
+ write(node._startOffset, code);
}
}
node.block->accept(*this);
{
- LingoDec::CodeWriter code("\n");
+ Common::String code;
if (!isMethod) {
- code.writeLine("end");
+ code += "end";
}
- _script.code.push_back({node.block->_endOffset, code.str()});
+ _script.code.push_back({node.block->_endOffset, code});
}
}
virtual void visit(const LingoDec::RepeatWhileStmtNode &node) override {
- LingoDec::CodeWriter code("\n");
+ LingoDec::CodeWriterVisitor code(_dot, false);
code.write("repeat while ");
- node.condition->writeScriptText(code, _dot, false);
- write(node._startOffset, code.str());
+ node.condition->accept(code);
+ write(node._startOffset, code._str);
node.block->accept(*this);
@@ -170,40 +170,40 @@ public:
}
virtual void visit(const LingoDec::RepeatWithInStmtNode &node) override {
- LingoDec::CodeWriter code("\n");
+ LingoDec::CodeWriterVisitor code(_dot, false);
code.write("repeat with ");
code.write(node.varName);
code.write(" in ");
- node.list->writeScriptText(code, _dot, false);
- write(node._startOffset, code.str());
+ node.list->accept(code);
+ write(node._startOffset, code._str);
node.block->accept(*this);
write(node._endOffset, "end repeat");
}
virtual void visit(const LingoDec::RepeatWithToStmtNode &node) override {
- LingoDec::CodeWriter code("\n");
+ LingoDec::CodeWriterVisitor code(_dot, false);
code.write("repeat with ");
code.write(node.varName);
code.write(" = ");
- node.start->writeScriptText(code, _dot, false);
+ node.start->accept(code);
if (node.up) {
code.write(" to ");
} else {
code.write(" down to ");
}
- node.end->writeScriptText(code, _dot, false);
- write(node._startOffset, code.str());
+ node.end->accept(code);
+ write(node._startOffset, code._str);
node.block->accept(*this);
write(node._endOffset, "end repeat");
}
virtual void visit(const LingoDec::IfStmtNode &node) override {
{
- LingoDec::CodeWriter code("\n");
+ LingoDec::CodeWriterVisitor code(_dot, false);
code.write("if ");
- node.condition->writeScriptText(code, _dot, false);
+ node.condition->accept(code);
code.write(" then");
- write(node._startOffset, code.str());
+ write(node._startOffset, code._str);
}
node.block1->accept(*this);
if (node.hasElse) {
@@ -214,18 +214,18 @@ public:
}
virtual void visit(const LingoDec::TellStmtNode &node) override {
- LingoDec::CodeWriter code("\n");
+ LingoDec::CodeWriterVisitor code(_dot, false);
code.write("tell ");
- node.window->writeScriptText(code, _dot, false);
- write(node._startOffset, code.str());
+ node.window->accept(*this);
+ write(node._startOffset, code._str);
node.block->accept(*this);
write(node._endOffset, "end tell");
}
virtual void defaultVisit(const LingoDec::Node &node) override {
- LingoDec::CodeWriter code("\n");
- node.writeScriptText(code, _dot, false);
- write(node._startOffset, code.str());
+ LingoDec::CodeWriterVisitor code(_dot, false);
+ node.accept(code);
+ write(node._startOffset, code._str);
}
void write(uint32 offset, const Common::String &code) {
diff --git a/engines/director/lingo/lingodec/ast.cpp b/engines/director/lingo/lingodec/ast.cpp
index ea357808c2d..a0a6121855a 100644
--- a/engines/director/lingo/lingodec/ast.cpp
+++ b/engines/director/lingo/lingodec/ast.cpp
@@ -6,7 +6,6 @@
#include "common/util.h"
#include "./ast.h"
-#include "./codewriter.h"
#include "./handler.h"
#include "./names.h"
#include "./script.h"
@@ -27,96 +26,8 @@ int Datum::toInt() {
return 0;
}
-void Datum::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- switch (type) {
- case kDatumVoid:
- code.write("VOID");
- return;
- case kDatumSymbol:
- code.write("#" + s);
- return;
- case kDatumVarRef:
- code.write(s);
- return;
- case kDatumString:
- if (s.size() == 0) {
- code.write("EMPTY");
- return;
- }
- if (s.size() == 1) {
- switch (s[0]) {
- case '\x03':
- code.write("ENTER");
- return;
- case '\x08':
- code.write("BACKSPACE");
- return;
- case '\t':
- code.write("TAB");
- return;
- case '\r':
- code.write("RETURN");
- return;
- case '"':
- code.write("QUOTE");
- return;
- default:
- break;
- }
- }
- if (sum) {
- code.write("\"" + Common::toPrintable(s) + "\"");
- return;
- }
- code.write("\"" + s + "\"");
- return;
- case kDatumInt:
- code.write(Common::String::format("%d", i));
- return;
- case kDatumFloat:
- code.write(Common::String::format("%g", f));
- return;
- case kDatumList:
- case kDatumArgList:
- case kDatumArgListNoRet:
- {
- if (type == kDatumList)
- code.write("[");
- for (size_t ii = 0; ii < l.size(); ii++) {
- if (ii > 0)
- code.write(", ");
- l[ii]->writeScriptText(code, dot, sum);
- }
- if (type == kDatumList)
- code.write("]");
- }
- return;
- case kDatumPropList:
- {
- code.write("[");
- if (l.size() == 0) {
- code.write(":");
- } else {
- for (size_t ii = 0; ii < l.size(); ii += 2) {
- if (ii > 0)
- code.write(", ");
- l[ii]->writeScriptText(code, dot, sum);
- code.write(": ");
- l[ii + 1]->writeScriptText(code, dot, sum);
- }
- }
- code.write("]");
- }
- return;
- }
-}
-
/* AST */
-void AST::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- root->writeScriptText(code, dot, sum);
-}
-
void AST::addStatement(Common::SharedPtr<Node> statement) {
currentBlock->addChild(Common::move(statement));
}
@@ -169,27 +80,12 @@ bool Node::hasSpaces(bool) {
/* ErrorNode */
-void ErrorNode::writeScriptText(CodeWriter &code, bool, bool) const {
- code.write("ERROR");
-}
-
bool ErrorNode::hasSpaces(bool) {
return false;
}
-/* CommentNode */
-
-void CommentNode::writeScriptText(CodeWriter &code, bool, bool) const {
- code.write("-- ");
- code.write(text);
-}
-
/* LiteralNode */
-void LiteralNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- value->writeScriptText(code, dot, sum);
-}
-
Common::SharedPtr<Datum> LiteralNode::getValue() {
return value;
}
@@ -200,139 +96,13 @@ bool LiteralNode::hasSpaces(bool) {
/* BlockNode */
-void BlockNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- for (const auto &child : children) {
- child->writeScriptText(code, dot, sum);
- code.writeLine();
- }
-}
-
void BlockNode::addChild(Common::SharedPtr<Node> child) {
child->parent = this;
children.push_back(Common::move(child));
}
-/* HandlerNode */
-
-void HandlerNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- if (handler->isGenericEvent) {
- block->writeScriptText(code, dot, sum);
- } else {
- Script *script = handler->script;
- bool isMethod = script->isFactory();
- if (isMethod) {
- code.write("method ");
- } else {
- code.write("on ");
- }
- code.write(handler->name);
- if (handler->argumentNames.size() > 0) {
- code.write(" ");
- for (size_t i = 0; i < handler->argumentNames.size(); i++) {
- if (i > 0)
- code.write(", ");
- code.write(handler->argumentNames[i]);
- }
- }
- code.writeLine();
- code.indent();
- if (isMethod && script->propertyNames.size() > 0 && handler == &script->handlers[0]) {
- code.write("instance ");
- for (size_t i = 0; i < script->propertyNames.size(); i++) {
- if (i > 0)
- code.write(", ");
- code.write(script->propertyNames[i]);
- }
- code.writeLine();
- }
- if (handler->globalNames.size() > 0) {
- code.write("global ");
- for (size_t i = 0; i < handler->globalNames.size(); i++) {
- if (i > 0)
- code.write(", ");
- code.write(handler->globalNames[i]);
- }
- code.writeLine();
- }
- block->writeScriptText(code, dot, sum);
- code.unindent();
- if (!isMethod) {
- code.writeLine("end");
- }
- }
-}
-
-/* ExitStmtNode */
-
-void ExitStmtNode::writeScriptText(CodeWriter &code, bool, bool) const {
- code.write("exit");
-}
-
-/* InverseOpNode */
-
-void InverseOpNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("-");
-
- bool parenOperand = operand->hasSpaces(dot);
- if (parenOperand) {
- code.write("(");
- }
- operand->writeScriptText(code, dot, sum);
- if (parenOperand) {
- code.write(")");
- }
-}
-
-/* NotOpNode */
-
-void NotOpNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("not ");
-
- bool parenOperand = operand->hasSpaces(dot);
- if (parenOperand) {
- code.write("(");
- }
- operand->writeScriptText(code, dot, sum);
- if (parenOperand) {
- code.write(")");
- }
-}
-
/* BinaryOpNode */
-void BinaryOpNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- unsigned int precedence = getPrecedence();
- bool parenLeft = false;
- bool parenRight = false;
- if (precedence) {
- if (left->type == kBinaryOpNode) {
- auto leftBinaryOpNode = static_cast<BinaryOpNode *>(left.get());
- parenLeft = (leftBinaryOpNode->getPrecedence() != precedence);
- }
- parenRight = (right->type == kBinaryOpNode);
- }
-
- if (parenLeft) {
- code.write("(");
- }
- left->writeScriptText(code, dot, sum);
- if (parenLeft) {
- code.write(")");
- }
-
- code.write(" ");
- code.write(StandardNames::binaryOpNames[opcode]);
- code.write(" ");
-
- if (parenRight) {
- code.write("(");
- }
- right->writeScriptText(code, dot, sum);
- if (parenRight) {
- code.write(")");
- }
-}
-
unsigned int BinaryOpNode::getPrecedence() const {
switch (opcode) {
case kOpMul:
@@ -359,390 +129,26 @@ unsigned int BinaryOpNode::getPrecedence() const {
return 0;
}
-/* ChunkExprNode */
-
-void ChunkExprNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write(StandardNames::chunkTypeNames[type]);
- code.write(" ");
- first->writeScriptText(code, dot, sum);
- if (!(last->type == kLiteralNode && last->getValue()->type == kDatumInt && last->getValue()->i == 0)) {
- code.write(" to ");
- last->writeScriptText(code, dot, sum);
- }
- code.write(" of ");
- string->writeScriptText(code, false, sum); // we want the string to always be verbose
-}
-
-/* ChunkHiliteStmtNode */
-
-void ChunkHiliteStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("hilite ");
- chunk->writeScriptText(code, dot, sum);
-}
-
-/* ChunkDeleteStmtNode */
-
-void ChunkDeleteStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("delete ");
- chunk->writeScriptText(code, dot, sum);
-}
-
-/* SpriteIntersectsExprNode */
-
-void SpriteIntersectsExprNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("sprite ");
-
- bool parenFirstSprite = (firstSprite->type == kBinaryOpNode);
- if (parenFirstSprite) {
- code.write("(");
- }
- firstSprite->writeScriptText(code, dot, sum);
- if (parenFirstSprite) {
- code.write(")");
- }
-
- code.write(" intersects ");
-
- bool parenSecondSprite = (secondSprite->type == kBinaryOpNode);
- if (parenSecondSprite) {
- code.write("(");
- }
- secondSprite->writeScriptText(code, dot, sum);
- if (parenSecondSprite) {
- code.write(")");
- }
-}
-
-/* SpriteWithinExprNode */
-
-void SpriteWithinExprNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("sprite ");
-
- bool parenFirstSprite = (firstSprite->type == kBinaryOpNode);
- if (parenFirstSprite) {
- code.write("(");
- }
- firstSprite->writeScriptText(code, dot, sum);
- if (parenFirstSprite) {
- code.write(")");
- }
-
- code.write(" within ");
-
- bool parenSecondSprite = (secondSprite->type == kBinaryOpNode);
- if (parenSecondSprite) {
- code.write("(");
- }
- secondSprite->writeScriptText(code, dot, sum);
- if (parenSecondSprite) {
- code.write(")");
- }
-}
-
/* MemberExprNode */
-void MemberExprNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- bool hasCastID = castID && !(castID->type == kLiteralNode && castID->getValue()->type == kDatumInt && castID->getValue()->i == 0);
- code.write(type);
- if (dot) {
- code.write("(");
- memberID->writeScriptText(code, dot, sum);
- if (hasCastID) {
- code.write(", ");
- castID->writeScriptText(code, dot, sum);
- }
- code.write(")");
- } else {
- code.write(" ");
-
- bool parenMemberID = (memberID->type == kBinaryOpNode);
- if (parenMemberID) {
- code.write("(");
- }
- memberID->writeScriptText(code, dot, sum);
- if (parenMemberID) {
- code.write(")");
- }
-
- if (hasCastID) {
- code.write(" of castLib ");
-
- bool parenCastID = (castID->type == kBinaryOpNode);
- if (parenCastID) {
- code.write("(");
- }
- castID->writeScriptText(code, dot, sum);
- if (parenCastID) {
- code.write(")");
- }
- }
- }
-}
-
bool MemberExprNode::hasSpaces(bool dot) {
return !dot;
}
/* VarNode */
-void VarNode::writeScriptText(CodeWriter &code, bool, bool) const {
- code.write(varName);
-}
-
bool VarNode::hasSpaces(bool) {
return false;
}
-/* AssignmentStmtNode */
-
-void AssignmentStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- if (!dot || forceVerbose) {
- code.write("set ");
- variable->writeScriptText(code, false, sum); // we want the variable to always be verbose
- code.write(" to ");
- value->writeScriptText(code, dot, sum);
- } else {
- variable->writeScriptText(code, dot, sum);
- code.write(" = ");
- value->writeScriptText(code, dot, sum);
- }
-}
-
-/* IfStmtNode */
-
-void IfStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("if ");
- condition->writeScriptText(code, dot, sum);
- code.write(" then");
- if (sum) {
- if (hasElse) {
- code.write(" / else");
- }
- } else {
- code.writeLine();
- code.indent();
- block1->writeScriptText(code, dot, sum);
- code.unindent();
- if (hasElse) {
- code.writeLine("else");
- code.indent();
- block2->writeScriptText(code, dot, sum);
- code.unindent();
- }
- code.write("end if");
- }
-}
-
-/* RepeatWhileStmtNode */
-
-void RepeatWhileStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("repeat while ");
- condition->writeScriptText(code, dot, sum);
- if (!sum) {
- code.writeLine();
- code.indent();
- block->writeScriptText(code, dot, sum);
- code.unindent();
- code.write("end repeat");
- }
-}
-
-/* RepeatWithInStmtNode */
-
-void RepeatWithInStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("repeat with ");
- code.write(varName);
- code.write(" in ");
- list->writeScriptText(code, dot, sum);
- if (!sum) {
- code.writeLine();
- code.indent();
- block->writeScriptText(code, dot, sum);
- code.unindent();
- code.write("end repeat");
- }
-}
-
-/* RepeatWithToStmtNode */
-
-void RepeatWithToStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("repeat with ");
- code.write(varName);
- code.write(" = ");
- start->writeScriptText(code, dot, sum);
- if (up) {
- code.write(" to ");
- } else {
- code.write(" down to ");
- }
- end->writeScriptText(code, dot, sum);
- if (!sum) {
- code.writeLine();
- code.indent();
- block->writeScriptText(code, dot, sum);
- code.unindent();
- code.write("end repeat");
- }
-}
-
-/* CaseLabelNode */
-
-void CaseLabelNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- if (sum) {
- code.write("(case) ");
- if (parent->type == kCaseLabelNode) {
- auto parentLabel = static_cast<CaseLabelNode *>(parent);
- if (parentLabel->nextOr.get() == this) {
- code.write("..., ");
- }
- }
-
- bool parenValue = value->hasSpaces(dot);
- if (parenValue) {
- code.write("(");
- }
- value->writeScriptText(code, dot, sum);
- if (parenValue) {
- code.write(")");
- }
-
- if (nextOr) {
- code.write(", ...");
- } else {
- code.write(":");
- }
- } else {
- bool parenValue = value->hasSpaces(dot);
- if (parenValue) {
- code.write("(");
- }
- value->writeScriptText(code, dot, sum);
- if (parenValue) {
- code.write(")");
- }
-
- if (nextOr) {
- code.write(", ");
- nextOr->writeScriptText(code, dot, sum);
- } else {
- code.writeLine(":");
- code.indent();
- block->writeScriptText(code, dot, sum);
- code.unindent();
- }
- if (nextLabel) {
- nextLabel->writeScriptText(code, dot, sum);
- }
- }
-}
-
-/* OtherwiseNode */
-
-void OtherwiseNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- if (sum) {
- code.write("(case) otherwise:");
- } else {
- code.writeLine("otherwise:");
- code.indent();
- block->writeScriptText(code, dot, sum);
- code.unindent();
- }
-}
-
-/* EndCaseNode */
-
-void EndCaseNode::writeScriptText(CodeWriter &code, bool, bool) const {
- code.write("end case");
-}
-
/* CaseStmtNode */
-void CaseStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("case ");
- value->writeScriptText(code, dot, sum);
- code.write(" of");
- if (sum) {
- if (!firstLabel) {
- if (otherwise) {
- code.write(" / otherwise:");
- } else {
- code.write(" / end case");
- }
- }
- } else {
- code.writeLine();
- code.indent();
- if (firstLabel) {
- firstLabel->writeScriptText(code, dot, sum);
- }
- if (otherwise) {
- otherwise->writeScriptText(code, dot, sum);
- }
- code.unindent();
- code.write("end case");
- }
-}
-
void CaseStmtNode::addOtherwise(uint32 offset) {
otherwise = Common::SharedPtr<OtherwiseNode>(new OtherwiseNode(offset));
otherwise->parent = this;
otherwise->block->endPos = endPos;
}
-/* TellStmtNode */
-
-void TellStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("tell ");
- window->writeScriptText(code, dot, sum);
- if (!sum) {
- code.writeLine();
- code.indent();
- block->writeScriptText(code, dot, sum);
- code.unindent();
- code.write("end tell");
- }
-}
-
-/* SoundCmdStmtNode */
-
-void SoundCmdStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("sound ");
- code.write(cmd);
- if (argList->getValue()->l.size() > 0) {
- code.write(" ");
- argList->writeScriptText(code, dot, sum);
- }
-}
-
-/* PlayCmdStmtNode */
-
-void PlayCmdStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- auto &rawArgs = argList->getValue()->l;
-
- code.write("play");
-
- if (rawArgs.size() == 0) {
- code.write(" done");
- return;
- }
-
- auto &frame = rawArgs[0];
- if (rawArgs.size() == 1) {
- code.write(" frame ");
- frame->writeScriptText(code, dot, sum);
- return;
- }
-
- auto &movie = rawArgs[1];
- if (!(frame->type == kLiteralNode && frame->getValue()->type == kDatumInt && frame->getValue()->i == 1)) {
- code.write(" frame ");
- frame->writeScriptText(code, dot, sum);
- code.write(" of");
- }
- code.write(" movie ");
- movie->writeScriptText(code, dot, sum);
-}
-
/* CallNode */
bool CallNode::noParens() const {
@@ -775,70 +181,6 @@ bool CallNode::isMemberExpr() const {
return false;
}
-void CallNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- if (isExpression && argList->getValue()->l.size() == 0) {
- if (name == "pi") {
- code.write("PI");
- return;
- }
- if (name == "space") {
- code.write("SPACE");
- return;
- }
- if (name == "void") {
- code.write("VOID");
- return;
- }
- }
-
- if (!dot && isMemberExpr()) {
- /**
- * In some cases, member expressions such as `member 1 of castLib 1` compile
- * to the function call `member(1, 1)`. However, this doesn't parse correctly
- * in pre-dot-syntax versions of Director, and `put(member(1, 1))` does not
- * compile. Therefore, we rewrite these expressions to the verbose syntax when
- * in verbose mode.
- */
- code.write(name);
- code.write(" ");
-
- auto memberID = argList->getValue()->l[0];
- bool parenMemberID = (memberID->type == kBinaryOpNode);
- if (parenMemberID) {
- code.write("(");
- }
- memberID->writeScriptText(code, dot, sum);
- if (parenMemberID) {
- code.write(")");
- }
-
- if (argList->getValue()->l.size() == 2) {
- code.write(" of castLib ");
-
- auto castID = argList->getValue()->l[1];
- bool parenCastID = (castID->type == kBinaryOpNode);
- if (parenCastID) {
- code.write("(");
- }
- castID->writeScriptText(code, dot, sum);
- if (parenCastID) {
- code.write(")");
- }
- }
- return;
- }
-
- code.write(name);
- if (noParens()) {
- code.write(" ");
- argList->writeScriptText(code, dot, sum);
- } else {
- code.write("(");
- argList->writeScriptText(code, dot, sum);
- code.write(")");
- }
-}
-
bool CallNode::hasSpaces(bool dot) {
if (!dot && isMemberExpr())
return true;
@@ -851,321 +193,34 @@ bool CallNode::hasSpaces(bool dot) {
/* ObjCallNode */
-void ObjCallNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- auto &rawArgs = argList->getValue()->l;
-
- auto &obj = rawArgs[0];
- bool parenObj = obj->hasSpaces(dot);
- if (parenObj) {
- code.write("(");
- }
- obj->writeScriptText(code, dot, sum);
- if (parenObj) {
- code.write(")");
- }
-
- code.write(".");
- code.write(name);
- code.write("(");
- for (size_t i = 1; i < rawArgs.size(); i++) {
- if (i > 1)
- code.write(", ");
- rawArgs[i]->writeScriptText(code, dot, sum);
- }
- code.write(")");
-}
-
bool ObjCallNode::hasSpaces(bool) {
return false;
}
/* ObjCallV4Node */
-void ObjCallV4Node::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- obj->writeScriptText(code, dot, sum);
- code.write("(");
- argList->writeScriptText(code, dot, sum);
- code.write(")");
-}
-
bool ObjCallV4Node::hasSpaces(bool) {
return false;
}
-/* TheExprNode */
-
-void TheExprNode::writeScriptText(CodeWriter &code, bool, bool) const {
- code.write("the ");
- code.write(prop);
-}
-
-/* LastStringChunkExprNode */
-
-void LastStringChunkExprNode::writeScriptText(CodeWriter &code, bool, bool sum) const {
- code.write("the last ");
- code.write(StandardNames::chunkTypeNames[type]);
- code.write(" in ");
-
- bool parenObj = (obj->type == kBinaryOpNode);
- if (parenObj) {
- code.write("(");
- }
- obj->writeScriptText(code, false, sum); // we want the object to always be verbose
- if (parenObj) {
- code.write(")");
- }
-}
-
-/* StringChunkCountExprNode */
-
-void StringChunkCountExprNode::writeScriptText(CodeWriter &code, bool, bool sum) const {
- code.write("the number of ");
- code.write(StandardNames::chunkTypeNames[type]); // we want the object to always be verbose
- code.write("s in ");
-
- bool parenObj = (obj->type == kBinaryOpNode);
- if (parenObj) {
- code.write("(");
- }
- obj->writeScriptText(code, false, sum);
- if (parenObj) {
- code.write(")");
- }
-}
-
-/* MenuPropExprNode */
-
-void MenuPropExprNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("the ");
- code.write(StandardNames::menuPropertyNames[prop]);
- code.write(" of menu ");
-
- bool parenMenuID = (menuID->type == kBinaryOpNode);
- if (parenMenuID) {
- code.write("(");
- }
- menuID->writeScriptText(code, dot, sum);
- if (parenMenuID) {
- code.write(")");
- }
-}
-
-/* MenuItemPropExprNode */
-
-void MenuItemPropExprNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("the ");
- code.write(StandardNames::menuItemPropertyNames[prop]);
- code.write(" of menuItem ");
-
- bool parenItemID = (itemID->type == kBinaryOpNode);
- if (parenItemID) {
- code.write("(");
- }
- itemID->writeScriptText(code, dot, sum);
- if (parenItemID) {
- code.write(")");
- }
-
- code.write(" of menu ");
-
- bool parenMenuID = (menuID->type == kBinaryOpNode);
- if (parenMenuID) {
- code.write("(");
- }
- menuID->writeScriptText(code, dot, sum);
- if (parenMenuID) {
- code.write(")");
- }
-}
-
-/* SoundPropExprNode */
-
-void SoundPropExprNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("the ");
- code.write(StandardNames::soundPropertyNames[prop]);
- code.write(" of sound ");
-
- bool parenSoundID = (soundID->type == kBinaryOpNode);
- if (parenSoundID) {
- code.write("(");
- }
- soundID->writeScriptText(code, dot, sum);
- if (parenSoundID) {
- code.write(")");
- }
-}
-
-/* SpritePropExprNode */
-
-void SpritePropExprNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("the ");
- code.write(StandardNames::spritePropertyNames[prop]);
- code.write(" of sprite ");
-
- bool parenSpriteID = (spriteID->type == kBinaryOpNode);
- if (parenSpriteID) {
- code.write("(");
- }
- spriteID->writeScriptText(code, dot, sum);
- if (parenSpriteID) {
- code.write(")");
- }
-}
-
-/* ThePropExprNode */
-
-void ThePropExprNode::writeScriptText(CodeWriter &code, bool, bool sum) const {
- code.write("the ");
- code.write(prop);
- code.write(" of ");
-
- bool parenObj = (obj->type == kBinaryOpNode);
- if (parenObj) {
- code.write("(");
- }
- obj->writeScriptText(code, false, sum); // we want the object to always be verbose
- if (parenObj) {
- code.write(")");
- }
-}
-
/* ObjPropExprNode */
-void ObjPropExprNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- if (dot) {
- bool parenObj = obj->hasSpaces(dot);
- if (parenObj) {
- code.write("(");
- }
- obj->writeScriptText(code, dot, sum);
- if (parenObj) {
- code.write(")");
- }
-
- code.write(".");
- code.write(prop);
- } else {
- code.write("the ");
- code.write(prop);
- code.write(" of ");
-
- bool parenObj = (obj->type == kBinaryOpNode);
- if (parenObj) {
- code.write("(");
- }
- obj->writeScriptText(code, dot, sum);
- if (parenObj) {
- code.write(")");
- }
- }
-}
-
bool ObjPropExprNode::hasSpaces(bool dot) {
return !dot;
}
/* ObjBracketExprNode */
-void ObjBracketExprNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- bool parenObj = obj->hasSpaces(dot);
- if (parenObj) {
- code.write("(");
- }
- obj->writeScriptText(code, dot, sum);
- if (parenObj) {
- code.write(")");
- }
-
- code.write("[");
- prop->writeScriptText(code, dot, sum);
- code.write("]");
-}
-
bool ObjBracketExprNode::hasSpaces(bool) {
return false;
}
/* ObjPropIndexExprNode */
-void ObjPropIndexExprNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- bool parenObj = obj->hasSpaces(dot);
- if (parenObj) {
- code.write("(");
- }
- obj->writeScriptText(code, dot, sum);
- if (parenObj) {
- code.write(")");
- }
-
- code.write(".");
- code.write(prop);
- code.write("[");
- index->writeScriptText(code, dot, sum);
- if (index2) {
- code.write("..");
- index2->writeScriptText(code, dot, sum);
- }
- code.write("]");
-}
-
bool ObjPropIndexExprNode::hasSpaces(bool) {
return false;
}
-/* ExitRepeatStmtNode */
-
-void ExitRepeatStmtNode::writeScriptText(CodeWriter &code, bool, bool) const {
- code.write("exit repeat");
-}
-
-/* NextRepeatStmtNode */
-
-void NextRepeatStmtNode::writeScriptText(CodeWriter &code, bool, bool) const {
- code.write("next repeat");
-}
-
-/* PutStmtNode */
-
-void PutStmtNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("put ");
- value->writeScriptText(code, dot, sum);
- code.write(" ");
- code.write(StandardNames::putTypeNames[type]);
- code.write(" ");
- variable->writeScriptText(code, false, sum); // we want the variable to always be verbose
-}
-
-/* WhenStmtNode */
-
-void WhenStmtNode::writeScriptText(CodeWriter &code, bool, bool) const {
- code.write("when ");
- code.write(StandardNames::whenEventNames[event]);
- code.write(" then");
-
- code.doIndentation = false;
- for (size_t i = 0; i < script.size(); i++) {
- char ch = script[i];
- if (ch == '\r') {
- if (i != script.size() - 1) {
- code.writeLine();
- }
- } else {
- code.write(ch);
- }
- }
- code.doIndentation = true;
-}
-
-/* NewObjNode */
-
-void NewObjNode::writeScriptText(CodeWriter &code, bool dot, bool sum) const {
- code.write("new ");
- code.write(objType);
- code.write("(");
- objArgs->writeScriptText(code, dot, sum);
- code.write(")");
-}
-
void ErrorNode::accept(NodeVisitor &visitor) const { visitor.visit(*this); }
void CommentNode::accept(NodeVisitor &visitor) const { visitor.visit(*this); }
void LiteralNode::accept(NodeVisitor &visitor) const { visitor.visit(*this); }
diff --git a/engines/director/lingo/lingodec/ast.h b/engines/director/lingo/lingodec/ast.h
index 3ec33b7e22f..1a0e334ce8a 100644
--- a/engines/director/lingo/lingodec/ast.h
+++ b/engines/director/lingo/lingodec/ast.h
@@ -11,7 +11,6 @@
#include "common/ptr.h"
#include "common/str.h"
#include "common/util.h"
-#include "./codewriter.h"
#include "./enums.h"
namespace LingoDec {
@@ -52,7 +51,6 @@ struct Datum {
}
int toInt();
- void writeScriptText(CodeWriter &code, bool dot, bool sum) const;
};
class NodeVisitor;
@@ -71,7 +69,6 @@ struct Node {
Node(NodeType t, uint32 offset) : type(t), isExpression(false), isStatement(false), isLabel(false), isLoop(false), parent(nullptr), _startOffset(offset), _endOffset(offset) {}
virtual ~Node() {}
- virtual void writeScriptText(CodeWriter&, bool, bool) const {}
virtual void accept(NodeVisitor& visitor) const = 0;
virtual Common::SharedPtr<Datum> getValue();
Node *ancestorStatement();
@@ -117,7 +114,6 @@ struct LoopNode : StmtNode {
struct ErrorNode : ExprNode {
explicit ErrorNode(uint32 offset) : ExprNode(kErrorNode, offset) {}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual bool hasSpaces(bool dot) override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -128,7 +124,6 @@ struct CommentNode : Node {
Common::String text;
CommentNode(uint32 offset, Common::String t) : Node(kCommentNode, offset), text(t) {}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -140,7 +135,6 @@ struct LiteralNode : ExprNode {
LiteralNode(uint32 offset, Common::SharedPtr<Datum> d) : ExprNode(kLiteralNode, offset) {
value = Common::move(d);
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual Common::SharedPtr<Datum> getValue() override;
virtual bool hasSpaces(bool dot) override;
virtual void accept(NodeVisitor &visitor) const override;
@@ -156,7 +150,6 @@ struct BlockNode : Node {
CaseLabelNode *currentCaseLabel;
explicit BlockNode(uint32 offset) : Node(kBlockNode, offset), endPos(-1), currentCaseLabel(nullptr) {}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
void addChild(Common::SharedPtr<Node> child);
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -172,7 +165,6 @@ struct HandlerNode : Node {
block = Common::SharedPtr<BlockNode>(new BlockNode(offset));
block->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -180,7 +172,6 @@ struct HandlerNode : Node {
struct ExitStmtNode : StmtNode {
explicit ExitStmtNode(uint32 offset) : StmtNode(kExitStmtNode, offset) {}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -193,7 +184,6 @@ struct InverseOpNode : ExprNode {
operand = Common::move(o);
operand->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -206,7 +196,6 @@ struct NotOpNode : ExprNode {
operand = Common::move(o);
operand->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -224,7 +213,6 @@ struct BinaryOpNode : ExprNode {
right = Common::move(b);
right->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual unsigned int getPrecedence() const;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -246,7 +234,6 @@ struct ChunkExprNode : ExprNode {
string = Common::move(s);
string->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -259,7 +246,6 @@ struct ChunkHiliteStmtNode : StmtNode {
chunk = Common::move(c);
chunk->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -272,7 +258,6 @@ struct ChunkDeleteStmtNode : StmtNode {
chunk = Common::move(c);
chunk->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -289,7 +274,6 @@ struct SpriteIntersectsExprNode : ExprNode {
secondSprite = Common::move(b);
secondSprite->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -306,7 +290,6 @@ struct SpriteWithinExprNode : ExprNode {
secondSprite = Common::move(b);
secondSprite->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -326,7 +309,6 @@ struct MemberExprNode : ExprNode {
this->castID->parent = this;
}
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual bool hasSpaces(bool dot) override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -337,7 +319,6 @@ struct VarNode : ExprNode {
Common::String varName;
VarNode(uint32 offset, Common::String v) : ExprNode(kVarNode, offset), varName(v) {}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual bool hasSpaces(bool dot) override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -357,7 +338,6 @@ struct AssignmentStmtNode : StmtNode {
value->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -377,7 +357,6 @@ struct IfStmtNode : StmtNode {
block2 = Common::SharedPtr<BlockNode>(new BlockNode(offset));
block2->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -394,7 +373,6 @@ struct RepeatWhileStmtNode : LoopNode {
block = Common::SharedPtr<BlockNode>(new BlockNode(offset));
block->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -413,7 +391,6 @@ struct RepeatWithInStmtNode : LoopNode {
block = Common::SharedPtr<BlockNode>(new BlockNode(offset));
block->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -436,7 +413,6 @@ struct RepeatWithToStmtNode : LoopNode {
block = Common::SharedPtr<BlockNode>(new BlockNode(offset));
block->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -455,7 +431,6 @@ struct CaseLabelNode : LabelNode {
value = Common::move(v);
value->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -468,7 +443,6 @@ struct OtherwiseNode : LabelNode {
block = Common::SharedPtr<BlockNode>(new BlockNode(offset));
block->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -476,7 +450,6 @@ struct OtherwiseNode : LabelNode {
struct EndCaseNode : LabelNode {
explicit EndCaseNode(uint32 offset) : LabelNode(kEndCaseNode, offset) {}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -495,7 +468,6 @@ struct CaseStmtNode : StmtNode {
value = Common::move(v);
value->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
void addOtherwise(uint32 offset);
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -512,7 +484,6 @@ struct TellStmtNode : StmtNode {
block = Common::SharedPtr<BlockNode>(new BlockNode(offset));
block->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -527,7 +498,6 @@ struct SoundCmdStmtNode : StmtNode {
argList = Common::move(a);
argList->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -540,7 +510,6 @@ struct PlayCmdStmtNode : StmtNode {
argList = Common::move(a);
argList->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -561,7 +530,6 @@ struct CallNode : Node {
}
bool noParens() const;
bool isMemberExpr() const;
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual bool hasSpaces(bool dot) override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -581,7 +549,6 @@ struct ObjCallNode : Node {
else
isExpression = true;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual bool hasSpaces(bool dot) override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -601,7 +568,6 @@ struct ObjCallV4Node : Node {
else
isExpression = true;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual bool hasSpaces(bool dot) override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -612,7 +578,6 @@ struct TheExprNode : ExprNode {
Common::String prop;
TheExprNode(uint32 offset, Common::String p) : ExprNode(kTheExprNode, offset), prop(p) {}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -627,7 +592,6 @@ struct LastStringChunkExprNode : ExprNode {
obj = Common::move(o);
obj->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -642,7 +606,6 @@ struct StringChunkCountExprNode : ExprNode {
obj = Common::move(o);
obj->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -657,7 +620,6 @@ struct MenuPropExprNode : ExprNode {
menuID = Common::move(m);
menuID->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -675,7 +637,6 @@ struct MenuItemPropExprNode : ExprNode {
itemID = Common::move(i);
itemID->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -690,7 +651,6 @@ struct SoundPropExprNode : ExprNode {
soundID = Common::move(s);
soundID->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -705,7 +665,6 @@ struct SpritePropExprNode : ExprNode {
spriteID = Common::move(s);
spriteID->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -720,7 +679,6 @@ struct ThePropExprNode : ExprNode {
obj = Common::move(o);
obj->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -735,7 +693,6 @@ struct ObjPropExprNode : ExprNode {
obj = Common::move(o);
obj->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual bool hasSpaces(bool dot) override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -753,7 +710,6 @@ struct ObjBracketExprNode : ExprNode {
prop = Common::move(p);
prop->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual bool hasSpaces(bool dot) override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -777,7 +733,6 @@ struct ObjPropIndexExprNode : ExprNode {
index2->parent = this;
}
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual bool hasSpaces(bool dot) override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -786,7 +741,6 @@ struct ObjPropIndexExprNode : ExprNode {
struct ExitRepeatStmtNode : StmtNode {
explicit ExitRepeatStmtNode(uint32 offset) : StmtNode(kExitRepeatStmtNode, offset) {}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -794,7 +748,6 @@ struct ExitRepeatStmtNode : StmtNode {
struct NextRepeatStmtNode : StmtNode {
explicit NextRepeatStmtNode(uint32 offset) : StmtNode(kNextRepeatStmtNode, offset) {}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -812,7 +765,6 @@ struct PutStmtNode : StmtNode {
value = Common::move(val);
value->parent = this;
}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -824,7 +776,6 @@ struct WhenStmtNode : StmtNode {
WhenStmtNode(uint32 offset, int e, Common::String s)
: StmtNode(kWhenStmtNode, offset), event(e), script(s) {}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -835,7 +786,6 @@ struct NewObjNode : ExprNode {
Common::SharedPtr<Node> objArgs;
NewObjNode(uint32 offset, Common::String o, Common::SharedPtr<Node> args) : ExprNode(kNewObjNode, offset), objType(o), objArgs(args) {}
- virtual void writeScriptText(CodeWriter &code, bool dot, bool sum) const override;
virtual void accept(NodeVisitor &visitor) const override;
};
@@ -904,7 +854,6 @@ struct AST {
currentBlock = root->block.get();
}
- void writeScriptText(CodeWriter &code, bool dot, bool sum) const;
void addStatement(Common::SharedPtr<Node> statement);
void enterBlock(BlockNode *block);
void exitBlock();
diff --git a/engines/director/lingo/lingodec/codewriter.cpp b/engines/director/lingo/lingodec/codewriter.cpp
deleted file mode 100644
index fa20eae8883..00000000000
--- a/engines/director/lingo/lingodec/codewriter.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-#include "./codewriter.h"
-
-namespace LingoDec {
-
-void CodeWriter::write(Common::String str) {
- if (str.empty())
- return;
-
- writeIndentation();
- _res += str;
- _lineWidth += str.size();
- _size += str.size();
-}
-
-void CodeWriter::write(char ch) {
- writeIndentation();
- _res += ch;
- _lineWidth += 1;
- _size += 1;
-}
-
-void CodeWriter::writeLine(Common::String str) {
- if (str.empty()) {
- _res += _lineEnding;
- } else {
- writeIndentation();
- _res += str;
- _res += _lineEnding;
- }
- _indentationWritten = false;
- _lineWidth = 0;
- _size += str.size() + _lineEnding.size();
-}
-
-void CodeWriter::writeLine() {
- _res += _lineEnding;
- _indentationWritten = false;
- _lineWidth = 0;
- _size += _lineEnding.size();
-}
-
-void CodeWriter::indent() {
- _indentationLevel += 1;
-}
-
-void CodeWriter::unindent() {
- if (_indentationLevel > 0) {
- _indentationLevel -= 1;
- }
-}
-
-Common::String CodeWriter::str() const {
- return _res;
-}
-
-void CodeWriter::writeIndentation() {
- if (_indentationWritten || !doIndentation)
- return;
-
- for (int i = 0; i < _indentationLevel; i++) {
- _res += _indentation;
- }
-
- _indentationWritten = true;
- _lineWidth = _indentationLevel * _indentation.size();
- _size += _lineWidth;
-}
-
-} // namespace Common
diff --git a/engines/director/lingo/lingodec/codewriter.h b/engines/director/lingo/lingodec/codewriter.h
deleted file mode 100644
index 81e0f8d7209..00000000000
--- a/engines/director/lingo/lingodec/codewriter.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/.
- */
-
-#ifndef LINGODEC_CODEWRITER_H
-#define LINGODEC_CODEWRITER_H
-
-#include "common/str.h"
-
-namespace LingoDec {
-
-class CodeWriter {
-protected:
- Common::String _res;
-
- Common::String _lineEnding;
- Common::String _indentation;
-
- int _indentationLevel = 0;
- bool _indentationWritten = false;
- size_t _lineWidth = 0;
- size_t _size = 0;
-
-public:
- bool doIndentation = true;
-
-public:
- CodeWriter(Common::String lineEnding, Common::String indentation = " ")
- : _lineEnding(lineEnding), _indentation(indentation) {}
-
- void write(Common::String str);
- void write(char ch);
- void writeLine(Common::String str);
- void writeLine();
-
- void indent();
- void unindent();
-
- Common::String str() const;
- size_t lineWidth() const { return _lineWidth; }
- size_t size() const { return _size; }
-
-protected:
- void writeIndentation();
-};
-
-} // namespace Common
-
-#endif // LINGODEC_CODEWRITER_H
diff --git a/engines/director/lingo/lingodec/codewritervisitor.cpp b/engines/director/lingo/lingodec/codewritervisitor.cpp
new file mode 100644
index 00000000000..78a8a3b5ea6
--- /dev/null
+++ b/engines/director/lingo/lingodec/codewritervisitor.cpp
@@ -0,0 +1,876 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#include "common/ptr.h"
+#include "./ast.h"
+#include "./handler.h"
+#include "./names.h"
+#include "./script.h"
+#include "./codewritervisitor.h"
+
+namespace LingoDec {
+
+void CodeWriterVisitor::visit(const HandlerNode &node) {
+ if (node.handler->isGenericEvent) {
+ node.block->accept(*this);
+ } else {
+ Script *script = node.handler->script;
+ bool isMethod = script->isFactory();
+ if (isMethod) {
+ write("method ");
+ } else {
+ write("on ");
+ }
+ write(node.handler->name);
+ if (node.handler->argumentNames.size() > 0) {
+ write(" ");
+ for (size_t i = 0; i < node.handler->argumentNames.size(); i++) {
+ if (i > 0)
+ write(", ");
+ write(node.handler->argumentNames[i]);
+ }
+ }
+ writeLine();
+ indent();
+ if (isMethod && script->propertyNames.size() > 0 && node.handler == &script->handlers[0]) {
+ write("instance ");
+ for (size_t i = 0; i < script->propertyNames.size(); i++) {
+ if (i > 0)
+ write(", ");
+ write(script->propertyNames[i]);
+ }
+ writeLine();
+ }
+ if (node.handler->globalNames.size() > 0) {
+ write("global ");
+ for (size_t i = 0; i < node.handler->globalNames.size(); i++) {
+ if (i > 0)
+ write(", ");
+ write(node.handler->globalNames[i]);
+ }
+ writeLine();
+ }
+ unindent();
+ node.block->accept(*this);
+ if (!isMethod) {
+ writeLine("end");
+ }
+ }
+}
+void CodeWriterVisitor::visit(const ErrorNode &) {
+ write("ERROR");
+}
+void CodeWriterVisitor::visit(const CommentNode &node) {
+ write("-- ");
+ write(node.text);
+}
+void CodeWriterVisitor::visit(const NewObjNode &node) {
+ write("new ");
+ write(node.objType);
+ write("(");
+ node.objArgs->accept(*this);
+ write(")");
+}
+void CodeWriterVisitor::visit(const LiteralNode &node) {
+ write(*node.value);
+}
+void CodeWriterVisitor::visit(const IfStmtNode &node) {
+ write("if ");
+ node.condition->accept(*this);
+ write(" then");
+ if (_sum) {
+ if (node.hasElse) {
+ write(" / else");
+ }
+ } else {
+ writeLine();
+ node.block1->accept(*this);
+ if (node.hasElse) {
+ writeLine("else");
+ node.block2->accept(*this);
+ }
+ write("end if");
+ }
+}
+void CodeWriterVisitor::visit(const EndCaseNode &) {
+ write("end case");
+}
+
+void CodeWriterVisitor::visit(const ObjCallNode &node) {
+ auto &rawArgs = node.argList->getValue()->l;
+
+ auto &obj = rawArgs[0];
+ bool parenObj = obj->hasSpaces(_dot);
+ if (parenObj) {
+ write("(");
+ }
+ obj->accept(*this);
+ if (parenObj) {
+ write(")");
+ }
+
+ write(".");
+ write(node.name);
+ write("(");
+ for (size_t i = 1; i < rawArgs.size(); i++) {
+ if (i > 1)
+ write(", ");
+ rawArgs[i]->accept(*this);
+ }
+ write(")");
+}
+void CodeWriterVisitor::visit(const PutStmtNode &node) {
+ write("put ");
+ node.value->accept(*this);
+ write(" ");
+ write(StandardNames::putTypeNames[node.type]);
+ write(" ");
+ node.variable->accept(*this); // TODO: we want the variable to always be verbose
+}
+void CodeWriterVisitor::visit(const TheExprNode &node) {
+ write("the ");
+ write(node.prop);
+}
+void CodeWriterVisitor::visit(const BinaryOpNode &node) {
+ unsigned int precedence = node.getPrecedence();
+ bool parenLeft = false;
+ bool parenRight = false;
+ if (precedence) {
+ if (node.left->type == kBinaryOpNode) {
+ auto leftBinaryOpNode = static_cast<BinaryOpNode *>(node.left.get());
+ parenLeft = (leftBinaryOpNode->getPrecedence() != precedence);
+ }
+ parenRight = (node.right->type == kBinaryOpNode);
+ }
+
+ if (parenLeft) {
+ write("(");
+ }
+ node.left->accept(*this);
+ if (parenLeft) {
+ write(")");
+ }
+
+ write(" ");
+ write(StandardNames::binaryOpNames[node.opcode]);
+ write(" ");
+
+ if (parenRight) {
+ write("(");
+ }
+ node.right->accept(*this);
+ if (parenRight) {
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const CaseStmtNode &node) {
+ write("case ");
+ node.value->accept(*this);
+ write(" of");
+ if (_sum) {
+ if (!node.firstLabel) {
+ if (node.otherwise) {
+ write(" / otherwise:");
+ } else {
+ write(" / end case");
+ }
+ }
+ } else {
+ writeLine();
+ indent();
+ if (node.firstLabel) {
+ node.firstLabel->accept(*this);
+ }
+ if (node.otherwise) {
+ node.otherwise->accept(*this);
+ }
+ unindent();
+ write("end case");
+ }
+}
+void CodeWriterVisitor::visit(const ExitStmtNode &) {
+ write("exit");
+}
+void CodeWriterVisitor::visit(const TellStmtNode &node) {
+ write("tell ");
+ node.window->accept(*this);
+ if (!_sum) {
+ writeLine();
+ node.block->accept(*this);
+ write("end tell");
+ }
+}
+void CodeWriterVisitor::visit(const WhenStmtNode &node) {
+ write("when ");
+ write(StandardNames::whenEventNames[node.event]);
+ write(" then");
+
+ for (size_t i = 0; i < node.script.size(); i++) {
+ char ch = node.script[i];
+ if (ch == '\r') {
+ if (i != node.script.size() - 1) {
+ writeLine();
+ }
+ } else {
+ write(ch);
+ }
+ }
+}
+
+void CodeWriterVisitor::visit(const CaseLabelNode &node) {
+ if (_sum) {
+ write("(case) ");
+ if (node.parent->type == kCaseLabelNode) {
+ auto parentLabel = static_cast<CaseLabelNode *>(node.parent);
+ if (parentLabel->nextOr.get() == &node) {
+ write("..., ");
+ }
+ }
+
+ bool parenValue = node.value->hasSpaces(_dot);
+ if (parenValue) {
+ write("(");
+ }
+ node.value->accept(*this);
+ if (parenValue) {
+ write(")");
+ }
+
+ if (node.nextOr) {
+ write(", ...");
+ } else {
+ write(":");
+ }
+ } else {
+ bool parenValue = node.value->hasSpaces(_dot);
+ if (parenValue) {
+ write("(");
+ }
+ node.value->accept(*this);
+ if (parenValue) {
+ write(")");
+ }
+
+ if (node.nextOr) {
+ write(", ");
+ node.nextOr->accept(*this);
+ } else {
+ writeLine(":");
+ node.block->accept(*this);
+ }
+ if (node.nextLabel) {
+ node.nextLabel->accept(*this);
+ }
+ }
+}
+void CodeWriterVisitor::visit(const ChunkExprNode &node) {
+ write(StandardNames::chunkTypeNames[node.type]);
+ write(" ");
+ node.first->accept(*this);
+ if (!(node.last->type == kLiteralNode && node.last->getValue()->type == kDatumInt && node.last->getValue()->i == 0)) {
+ write(" to ");
+ node.last->accept(*this);
+ }
+ write(" of ");
+ node.string->accept(*this); // TODO: we want the string to always be verbose
+}
+void CodeWriterVisitor::visit(const InverseOpNode &node) {
+ write("-");
+
+ bool parenOperand = node.operand->hasSpaces(_dot);
+ if (parenOperand) {
+ write("(");
+ }
+ node.operand->accept(*this);
+ if (parenOperand) {
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const ObjCallV4Node &node) {
+ node.obj->accept(*this);
+ write("(");
+ node.argList->accept(*this);
+ write(")");
+}
+void CodeWriterVisitor::visit(const OtherwiseNode &node) {
+ if (_sum) {
+ write("(case) otherwise:");
+ } else {
+ writeLine("otherwise:");
+ node.block->accept(*this);
+ }
+}
+void CodeWriterVisitor::visit(const MemberExprNode &node) {
+ bool hasCastID = node.castID && !(node.castID->type == kLiteralNode && node.castID->getValue()->type == kDatumInt && node.castID->getValue()->i == 0);
+ write(node.type);
+ if (_dot) {
+ write("(");
+ node.memberID->accept(*this);
+ if (hasCastID) {
+ write(", ");
+ node.castID->accept(*this);
+ }
+ write(")");
+ } else {
+ write(" ");
+
+ bool parenMemberID = (node.memberID->type == kBinaryOpNode);
+ if (parenMemberID) {
+ write("(");
+ }
+ node.memberID->accept(*this);
+ if (parenMemberID) {
+ write(")");
+ }
+
+ if (hasCastID) {
+ write(" of castLib ");
+
+ bool parenCastID = (node.castID->type == kBinaryOpNode);
+ if (parenCastID) {
+ write("(");
+ }
+ node.castID->accept(*this);
+ if (parenCastID) {
+ write(")");
+ }
+ }
+ }
+}
+void CodeWriterVisitor::visit(const ObjPropExprNode &node) {
+ if (_dot) {
+ bool parenObj = node.obj->hasSpaces(_dot);
+ if (parenObj) {
+ write("(");
+ }
+ node.obj->accept(*this);
+ if (parenObj) {
+ write(")");
+ }
+
+ write(".");
+ write(node.prop);
+ } else {
+ write("the ");
+ write(node.prop);
+ write(" of ");
+
+ bool parenObj = (node.obj->type == kBinaryOpNode);
+ if (parenObj) {
+ write("(");
+ }
+ node.obj->accept(*this);
+ if (parenObj) {
+ write(")");
+ }
+ }
+}
+void CodeWriterVisitor::visit(const PlayCmdStmtNode &node) {
+ auto &rawArgs = node.argList->getValue()->l;
+
+ write("play");
+
+ if (rawArgs.size() == 0) {
+ write(" done");
+ return;
+ }
+
+ auto &frame = rawArgs[0];
+ if (rawArgs.size() == 1) {
+ write(" frame ");
+ frame->accept(*this);
+ return;
+ }
+
+ auto &movie = rawArgs[1];
+ if (!(frame->type == kLiteralNode && frame->getValue()->type == kDatumInt && frame->getValue()->i == 1)) {
+ write(" frame ");
+ frame->accept(*this);
+ write(" of");
+ }
+ write(" movie ");
+ movie->accept(*this);
+}
+void CodeWriterVisitor::visit(const ThePropExprNode &node) {
+ write("the ");
+ write(node.prop);
+ write(" of ");
+
+ bool parenObj = (node.obj->type == kBinaryOpNode);
+ if (parenObj) {
+ write("(");
+ }
+ node.obj->accept(*this); // TODO: we want the object to always be verbose
+ if (parenObj) {
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const MenuPropExprNode &node) {
+ write("the ");
+ write(StandardNames::menuPropertyNames[node.prop]);
+ write(" of menu ");
+
+ bool parenMenuID = (node.menuID->type == kBinaryOpNode);
+ if (parenMenuID) {
+ write("(");
+ }
+ node.menuID->accept(*this);
+ if (parenMenuID) {
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const SoundCmdStmtNode &node) {
+ write("sound ");
+ write(node.cmd);
+ if (node.argList->getValue()->l.size() > 0) {
+ write(" ");
+ node.argList->accept(*this);
+ }
+}
+void CodeWriterVisitor::visit(const SoundPropExprNode &node) {
+ write("the ");
+ write(StandardNames::soundPropertyNames[node.prop]);
+ write(" of sound ");
+
+ bool parenSoundID = (node.soundID->type == kBinaryOpNode);
+ if (parenSoundID) {
+ write("(");
+ }
+ node.soundID->accept(*this);
+ if (parenSoundID) {
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const AssignmentStmtNode &node) {
+ if (!_dot) { // TODO: forceVerboseÃ
+ write("set ");
+ node.variable->accept(*this); // TODO: we want the variable to always be verbose
+ write(" to ");
+ node.value->accept(*this);
+ } else {
+ node.variable->accept(*this);
+ write(" = ");
+ node.value->accept(*this);
+ }
+}
+void CodeWriterVisitor::visit(const ExitRepeatStmtNode &) {
+ write("exit repeat");
+}
+void CodeWriterVisitor::visit(const NextRepeatStmtNode &) {
+ write("next repeat");
+}
+void CodeWriterVisitor::visit(const ObjBracketExprNode &node) {
+ bool parenObj = node.obj->hasSpaces(_dot);
+ if (parenObj) {
+ write("(");
+ }
+ node.obj->accept(*this);
+ if (parenObj) {
+ write(")");
+ }
+
+ write("[");
+ node.prop->accept(*this);
+ write("]");
+}
+void CodeWriterVisitor::visit(const SpritePropExprNode &node) {
+ write("the ");
+ write(StandardNames::spritePropertyNames[node.prop]);
+ write(" of sprite ");
+
+ bool parenSpriteID = (node.spriteID->type == kBinaryOpNode);
+ if (parenSpriteID) {
+ write("(");
+ }
+ node.spriteID->accept(*this);
+ if (parenSpriteID) {
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const ChunkDeleteStmtNode &node) {
+ write("delete ");
+ node.chunk->accept(*this);
+}
+void CodeWriterVisitor::visit(const ChunkHiliteStmtNode &node) {
+ write("hilite ");
+ node.chunk->accept(*this);
+}
+void CodeWriterVisitor::visit(const RepeatWhileStmtNode &node) {
+ write("repeat while ");
+ node.condition->accept(*this);
+ if (!_sum) {
+ writeLine();
+ node.block->accept(*this);
+ write("end repeat");
+ }
+}
+void CodeWriterVisitor::visit(const MenuItemPropExprNode &node) {
+ write("the ");
+ write(StandardNames::menuItemPropertyNames[node.prop]);
+ write(" of menuItem ");
+
+ bool parenItemID = (node.itemID->type == kBinaryOpNode);
+ if (parenItemID) {
+ write("(");
+ }
+ node.itemID->accept(*this);
+ if (parenItemID) {
+ write(")");
+ }
+
+ write(" of menu ");
+
+ bool parenMenuID = (node.menuID->type ==kBinaryOpNode);
+ if (parenMenuID) {
+ write("(");
+ }
+ node.menuID->accept(*this);
+ if (parenMenuID) {
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const ObjPropIndexExprNode &node) {
+ bool parenObj = node.obj->hasSpaces(_dot);
+ if (parenObj) {
+ write("(");
+ }
+ node.obj->accept(*this);
+ if (parenObj) {
+ write(")");
+ }
+
+ write(".");
+ write(node.prop);
+ write("[");
+ node.index->accept(*this);
+ if (node.index2) {
+ write("..");
+ node.index2->accept(*this);
+ }
+ write("]");
+}
+void CodeWriterVisitor::visit(const RepeatWithInStmtNode &node) {
+ write("repeat with ");
+ write(node.varName);
+ write(" in ");
+ node.list->accept(*this);
+ if (!_sum) {
+ writeLine();
+ node.block->accept(*this);
+ write("end repeat");
+ }
+}
+void CodeWriterVisitor::visit(const RepeatWithToStmtNode &node) {
+ write("repeat with ");
+ write(node.varName);
+ write(" = ");
+ node.start->accept(*this);
+ if (node.up) {
+ write(" to ");
+ } else {
+ write(" down to ");
+ }
+ node.end->accept(*this);
+ if (!_sum) {
+ writeLine();
+ node.block->accept(*this);
+ write("end repeat");
+ }
+}
+void CodeWriterVisitor::visit(const SpriteWithinExprNode &node) {
+ write("sprite ");
+
+ bool parenFirstSprite = (node.firstSprite->type == kBinaryOpNode);
+ if (parenFirstSprite) {
+ write("(");
+ }
+ node.firstSprite->accept(*this);
+ if (parenFirstSprite) {
+ write(")");
+ }
+
+ write(" within ");
+
+ bool parenSecondSprite = (node.secondSprite->type == kBinaryOpNode);
+ if (parenSecondSprite) {
+ write("(");
+ }
+ node.secondSprite->accept(*this);
+ if (parenSecondSprite) {
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const LastStringChunkExprNode &node) {
+ write("the last ");
+ write(StandardNames::chunkTypeNames[node.type]);
+ write(" in ");
+
+ bool parenObj = (node.obj->type == kBinaryOpNode);
+ if (parenObj) {
+ write("(");
+ }
+ node.obj->accept(*this); // TODO: we want the object to always be verbose
+ if (parenObj) {
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const SpriteIntersectsExprNode &node) {
+ write("sprite ");
+
+ bool parenFirstSprite = (node.firstSprite->type == kBinaryOpNode);
+ if (parenFirstSprite) {
+ write("(");
+ }
+ node.firstSprite->accept(*this);
+ if (parenFirstSprite) {
+ write(")");
+ }
+
+ write(" intersects ");
+
+ bool parenSecondSprite = (node.secondSprite->type == kBinaryOpNode);
+ if (parenSecondSprite) {
+ write("(");
+ }
+ node.secondSprite->accept(*this);
+ if (parenSecondSprite) {
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const StringChunkCountExprNode &node) {
+ write("the number of ");
+ write(StandardNames::chunkTypeNames[node.type]); // we want the object to always be verbose
+ write("s in ");
+
+ bool parenObj = (node.obj->type == kBinaryOpNode);
+ if (parenObj) {
+ write("(");
+ }
+ node.obj->accept(*this); // TODO dot false?
+ if (parenObj) {
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const VarNode &node) {
+ write(node.varName);
+}
+void CodeWriterVisitor::visit(const CallNode &node) {
+ if (node.isExpression && node.argList->getValue()->l.size() == 0) {
+ if (node.name == "pi") {
+ write("PI");
+ return;
+ }
+ if (node.name == "space") {
+ write("SPACE");
+ return;
+ }
+ if (node.name == "void") {
+ write("VOID");
+ return;
+ }
+ }
+
+ if (!_dot && node.isMemberExpr()) {
+ /**
+ * In some cases, member expressions such as `member 1 of castLib 1` compile
+ * to the function call `member(1, 1)`. However, this doesn't parse correctly
+ * in pre-dot-syntax versions of Director, and `put(member(1, 1))` does not
+ * compile. Therefore, we rewrite these expressions to the verbose syntax when
+ * in verbose mode.
+ */
+ write(node.name);
+ write(" ");
+
+ auto memberID = node.argList->getValue()->l[0];
+ bool parenMemberID = (memberID->type == kBinaryOpNode);
+ if (parenMemberID) {
+ write("(");
+ }
+ memberID->accept(*this);
+ if (parenMemberID) {
+ write(")");
+ }
+
+ if (node.argList->getValue()->l.size() == 2) {
+ write(" of castLib ");
+
+ auto castID = node.argList->getValue()->l[1];
+ bool parenCastID = (castID->type == kBinaryOpNode);
+ if (parenCastID) {
+ write("(");
+ }
+ castID->accept(*this);
+ if (parenCastID) {
+ write(")");
+ }
+ }
+ return;
+ }
+
+ write(node.name);
+ if (node.noParens()) {
+ write(" ");
+ node.argList->accept(*this);
+ } else {
+ write("(");
+ node.argList->accept(*this);
+ write(")");
+ }
+}
+void CodeWriterVisitor::visit(const BlockNode &node) {
+ indent();
+ for (const auto &child : node.children) {
+ child->accept(*this);
+ writeLine();
+ }
+ unindent();
+}
+void CodeWriterVisitor::visit(const NotOpNode &node) {
+ write("not ");
+
+ bool parenOperand = node.operand->hasSpaces(_dot);
+ if (parenOperand) {
+ write("(");
+ }
+ node.operand->accept(*this);
+ if (parenOperand) {
+ write(")");
+ }
+}
+
+void CodeWriterVisitor::indent() {
+ _indent++;
+}
+
+void CodeWriterVisitor::unindent() {
+ if (_indent > 0)
+ _indent--;
+}
+
+void CodeWriterVisitor::writeIndentation() {
+ if (_indentWritten)
+ return;
+
+ for (int i = 0; i < _indent; i++) {
+ _str += _indentation;
+ }
+
+ _indentWritten = true;
+ _lineWidth = _indent * _indentation.size();
+}
+
+void CodeWriterVisitor::write(char c) {
+ writeIndentation();
+ _str += c;
+ _lineWidth++;
+}
+
+void CodeWriterVisitor::write(const Common::String &s) {
+ writeIndentation();
+ _str += s;
+ _lineWidth += s.size();
+}
+
+void CodeWriterVisitor::writeLine() {
+ _str += _lineEnding;
+ _lineWidth += _lineEnding.size();
+ _indentWritten = false;
+ _lineWidth = 0;
+}
+
+void CodeWriterVisitor::writeLine(const Common::String &s) {
+ writeIndentation();
+ _str += s;
+ _lineWidth += s.size();
+ _str += _lineEnding;
+ _lineWidth += _lineEnding.size();
+ _indentWritten = false;
+ _lineWidth = 0;
+}
+
+void CodeWriterVisitor::write(Datum &datum) {
+ switch (datum.type) {
+ case kDatumVoid:
+ write("VOID");
+ return;
+ case kDatumSymbol:
+ write("#" + datum.s);
+ return;
+ case kDatumVarRef:
+ write(datum.s);
+ return;
+ case kDatumString:
+ if (datum.s.size() == 0) {
+ write("EMPTY");
+ return;
+ }
+ if (datum.s.size() == 1) {
+ switch (datum.s[0]) {
+ case '\x03':
+ write("ENTER");
+ return;
+ case '\x08':
+ write("BACKSPACE");
+ return;
+ case '\t':
+ write("TAB");
+ return;
+ case '\r':
+ write("RETURN");
+ return;
+ case '"':
+ write("QUOTE");
+ return;
+ default:
+ break;
+ }
+ }
+ if (_sum) {
+ write("\"" + Common::toPrintable(datum.s) + "\"");
+ return;
+ }
+ write("\"" + datum.s + "\"");
+ return;
+ case kDatumInt:
+ write(Common::String::format("%d", datum.i));
+ return;
+ case kDatumFloat:
+ write(Common::String::format("%g", datum.f));
+ return;
+ case kDatumList:
+ case kDatumArgList:
+ case kDatumArgListNoRet: {
+ if (datum.type == kDatumList)
+ write("[");
+ for (size_t ii = 0; ii < datum.l.size(); ii++) {
+ if (ii > 0)
+ write(", ");
+ datum.l[ii]->accept(*this);
+ }
+ if (datum.type == kDatumList)
+ write("]");
+ }
+ return;
+ case kDatumPropList: {
+ write("[");
+ if (datum.l.size() == 0) {
+ write(":");
+ } else {
+ for (size_t ii = 0; ii < datum.l.size(); ii += 2) {
+ if (ii > 0)
+ write(", ");
+ datum.l[ii]->accept(*this);
+ write(": ");
+ datum.l[ii + 1]->accept(*this);
+ }
+ }
+ write("]");
+ }
+ return;
+ }
+}
+
+} // namespace LingoDec
diff --git a/engines/director/lingo/lingodec/codewritervisitor.h b/engines/director/lingo/lingodec/codewritervisitor.h
new file mode 100644
index 00000000000..aaa4e2e43bb
--- /dev/null
+++ b/engines/director/lingo/lingodec/codewritervisitor.h
@@ -0,0 +1,92 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef LINGODEC_CODEWRITERVISITOR_H
+#define LINGODEC_CODEWRITERVISITOR_H
+
+#include "./ast.h"
+
+namespace LingoDec {
+
+class CodeWriterVisitor: public LingoDec::NodeVisitor {
+public:
+ CodeWriterVisitor(bool dotSyntax, bool sum, const Common::String &lineEnding = "\n", const Common::String &indentation = " ")
+ : _dot(dotSyntax), _sum(sum), _lineEnding(lineEnding), _indentation(indentation) {}
+ virtual ~CodeWriterVisitor() {}
+ virtual void visit(const LingoDec::HandlerNode& node) override;
+ virtual void visit(const LingoDec::ErrorNode& node) override;
+ virtual void visit(const LingoDec::CommentNode& node) override;
+ virtual void visit(const LingoDec::NewObjNode& node) override;
+ virtual void visit(const LingoDec::LiteralNode& node) override;
+ virtual void visit(const LingoDec::IfStmtNode& node) override;
+ virtual void visit(const LingoDec::EndCaseNode& node) override;
+ virtual void visit(const LingoDec::ObjCallNode& node) override;
+ virtual void visit(const LingoDec::PutStmtNode& node) override;
+ virtual void visit(const LingoDec::TheExprNode& node) override;
+ virtual void visit(const LingoDec::BinaryOpNode& node) override;
+ virtual void visit(const LingoDec::CaseStmtNode& node) override;
+ virtual void visit(const LingoDec::ExitStmtNode& node) override;
+ virtual void visit(const LingoDec::TellStmtNode& node) override;
+ virtual void visit(const LingoDec::WhenStmtNode& node) override;
+ virtual void visit(const LingoDec::CaseLabelNode& node) override;
+ virtual void visit(const LingoDec::ChunkExprNode& node) override;
+ virtual void visit(const LingoDec::InverseOpNode& node) override;
+ virtual void visit(const LingoDec::ObjCallV4Node& node) override;
+ virtual void visit(const LingoDec::OtherwiseNode& node) override;
+ virtual void visit(const LingoDec::MemberExprNode& node) override;
+ virtual void visit(const LingoDec::ObjPropExprNode& node) override;
+ virtual void visit(const LingoDec::PlayCmdStmtNode& node) override;
+ virtual void visit(const LingoDec::ThePropExprNode& node) override;
+ virtual void visit(const LingoDec::MenuPropExprNode& node) override;
+ virtual void visit(const LingoDec::SoundCmdStmtNode& node) override;
+ virtual void visit(const LingoDec::SoundPropExprNode& node) override;
+ virtual void visit(const LingoDec::AssignmentStmtNode& node) override;
+ virtual void visit(const LingoDec::ExitRepeatStmtNode& node) override;
+ virtual void visit(const LingoDec::NextRepeatStmtNode& node) override;
+ virtual void visit(const LingoDec::ObjBracketExprNode& node) override;
+ virtual void visit(const LingoDec::SpritePropExprNode& node) override;
+ virtual void visit(const LingoDec::ChunkDeleteStmtNode& node) override;
+ virtual void visit(const LingoDec::ChunkHiliteStmtNode& node) override;
+ virtual void visit(const LingoDec::RepeatWhileStmtNode& node) override;
+ virtual void visit(const LingoDec::MenuItemPropExprNode& node) override;
+ virtual void visit(const LingoDec::ObjPropIndexExprNode& node) override;
+ virtual void visit(const LingoDec::RepeatWithInStmtNode& node) override;
+ virtual void visit(const LingoDec::RepeatWithToStmtNode& node) override;
+ virtual void visit(const LingoDec::SpriteWithinExprNode& node) override;
+ virtual void visit(const LingoDec::LastStringChunkExprNode& node) override;
+ virtual void visit(const LingoDec::SpriteIntersectsExprNode& node) override;
+ virtual void visit(const LingoDec::StringChunkCountExprNode& node) override;
+ virtual void visit(const LingoDec::VarNode& node) override;
+ virtual void visit(const LingoDec::CallNode& node) override;
+ virtual void visit(const LingoDec::BlockNode& node) override;
+ virtual void visit(const LingoDec::NotOpNode& node) override;
+
+ size_t lineWidth() const { return _lineWidth; }
+ void indent();
+ void unindent();
+ void writeIndentation();
+ void write(char c);
+ void write(const Common::String& s);
+ void writeLine();
+ void writeLine(const Common::String& s);
+ void write(LingoDec::Datum& datum);
+
+public:
+ Common::String _str;
+
+private:
+ bool _dot = false;
+ bool _sum = false;
+ Common::String _lineEnding;
+ Common::String _indentation = " ";
+ bool _indentWritten = false;
+ int _indent = 0;
+ size_t _lineWidth = 0;
+};
+
+} // namespace LingoDec
+
+#endif // LINGODEC_CODEWRITERVISITOR_H
diff --git a/engines/director/lingo/lingodec/handler.cpp b/engines/director/lingo/lingodec/handler.cpp
index a8da30ae7ac..909d93823a9 100644
--- a/engines/director/lingo/lingodec/handler.cpp
+++ b/engines/director/lingo/lingodec/handler.cpp
@@ -7,7 +7,7 @@
#include "common/stream.h"
#include "common/util.h"
#include "./ast.h"
-#include "./codewriter.h"
+#include "./codewritervisitor.h"
#include "./handler.h"
#include "./names.h"
#include "./script.h"
@@ -1249,7 +1249,7 @@ Common::String posToString(int32 pos) {
return Common::String::format("[%3d]", pos);
}
-void Handler::writeBytecodeText(CodeWriter &code, bool dotSyntax) const {
+void Handler::writeBytecodeText(CodeWriterVisitor &code) const {
bool isMethod = script->isFactory();
if (!isGenericEvent) {
@@ -1304,7 +1304,7 @@ void Handler::writeBytecodeText(CodeWriter &code, bool dotSyntax) const {
if (bytecode.translation->isExpression) {
code.write("<");
}
- bytecode.translation->writeScriptText(code, dotSyntax, true);
+ bytecode.translation->accept(code);
if (bytecode.translation->isExpression) {
code.write(">");
}
diff --git a/engines/director/lingo/lingodec/handler.h b/engines/director/lingo/lingodec/handler.h
index ae6ff0034e0..d6cbb3536bf 100644
--- a/engines/director/lingo/lingodec/handler.h
+++ b/engines/director/lingo/lingodec/handler.h
@@ -20,7 +20,7 @@ namespace LingoDec {
struct AST;
struct Bytecode;
-class CodeWriter;
+class CodeWriterVisitor;
struct Node;
struct Script;
@@ -85,7 +85,7 @@ struct Handler {
BytecodeTag identifyLoop(uint32 startIndex, uint32 endIndex);
void parse();
uint32 translateBytecode(Bytecode &bytecode, uint32 index);
- void writeBytecodeText(CodeWriter &code, bool dotSyntax) const;
+ void writeBytecodeText(CodeWriterVisitor &code) const;
};
/* Bytecode */
diff --git a/engines/director/lingo/lingodec/script.cpp b/engines/director/lingo/lingodec/script.cpp
index 59e783090e0..77949bb2ae1 100644
--- a/engines/director/lingo/lingodec/script.cpp
+++ b/engines/director/lingo/lingodec/script.cpp
@@ -6,7 +6,7 @@
#include "common/stream.h"
#include "./ast.h"
-#include "./codewriter.h"
+#include "./codewritervisitor.h"
#include "./context.h"
#include "./handler.h"
#include "./script.h"
@@ -127,7 +127,7 @@ void Script::parse() {
}
}
-void Script::writeVarDeclarations(CodeWriter &code) const {
+void Script::writeVarDeclarations(CodeWriterVisitor &code) const {
if (!isFactory()) {
if (propertyNames.size() > 0) {
code.write("property ");
@@ -150,64 +150,64 @@ void Script::writeVarDeclarations(CodeWriter &code) const {
}
}
-void Script::writeScriptText(CodeWriter &code, bool dotSyntax) const {
- size_t origSize = code.size();
+void Script::writeScriptText(CodeWriterVisitor &code) const {
+ size_t origSize = code._str.size();
writeVarDeclarations(code);
if (isFactory()) {
- if (code.size() != origSize) {
+ if (code._str.size() != origSize) {
code.writeLine();
}
code.write("factory ");
code.writeLine(factoryName);
}
for (size_t i = 0; i < handlers.size(); i++) {
- if ((!isFactory() || i > 0) && code.size() != origSize) {
+ if ((!isFactory() || i > 0) && code._str.size() != origSize) {
code.writeLine();
}
- handlers[i].ast.writeScriptText(code, dotSyntax, false);
+ handlers[i].ast.root->accept(code);
}
for (auto factory : factories) {
- if (code.size() != origSize) {
+ if (code._str.size() != origSize) {
code.writeLine();
}
- factory->writeScriptText(code, dotSyntax);
+ factory->writeScriptText(code);
}
}
Common::String Script::scriptText(const char *lineEnding, bool dotSyntax) const {
- CodeWriter code(lineEnding);
- writeScriptText(code, dotSyntax);
- return code.str();
+ CodeWriterVisitor code(dotSyntax, false, lineEnding);
+ writeScriptText(code);
+ return code._str;
}
-void Script::writeBytecodeText(CodeWriter &code, bool dotSyntax) const {
- size_t origSize = code.size();
+void Script::writeBytecodeText(CodeWriterVisitor &code) const {
+ size_t origSize = code._str.size();
writeVarDeclarations(code);
if (isFactory()) {
- if (code.size() != origSize) {
+ if (code._str.size() != origSize) {
code.writeLine();
}
code.write("factory ");
code.writeLine(factoryName);
}
for (size_t i = 0; i < handlers.size(); i++) {
- if ((!isFactory() || i > 0) && code.size() != origSize) {
+ if ((!isFactory() || i > 0) && code._str.size() != origSize) {
code.writeLine();
}
- handlers[i].writeBytecodeText(code, dotSyntax);
+ handlers[i].writeBytecodeText(code);
}
for (auto factory : factories) {
- if (code.size() != origSize) {
+ if (code._str.size() != origSize) {
code.writeLine();
}
- factory->writeBytecodeText(code, dotSyntax);
+ factory->writeBytecodeText(code);
}
}
Common::String Script::bytecodeText(const char *lineEnding, bool dotSyntax) const {
- CodeWriter code(lineEnding);
- writeBytecodeText(code, dotSyntax);
- return code.str();
+ CodeWriterVisitor code(dotSyntax, true, lineEnding);
+ writeBytecodeText(code);
+ return code._str;
}
bool Script::isFactory() const {
diff --git a/engines/director/lingo/lingodec/script.h b/engines/director/lingo/lingodec/script.h
index 33945ee4c81..53cb6bcdbd7 100644
--- a/engines/director/lingo/lingodec/script.h
+++ b/engines/director/lingo/lingodec/script.h
@@ -17,7 +17,7 @@ class ReadStream;
namespace LingoDec {
-class CodeWriter;
+class CodeWriterVisitor;
struct Datum;
struct Handler;
struct ScriptContext;
@@ -82,10 +82,10 @@ struct Script {
Common::String getName(int id) const;
void setContext(ScriptContext *ctx);
void parse();
- void writeVarDeclarations(CodeWriter &code) const;
- void writeScriptText(CodeWriter &code, bool dotSyntax) const;
+ void writeVarDeclarations(CodeWriterVisitor &code) const;
+ void writeScriptText(CodeWriterVisitor &code) const;
Common::String scriptText(const char *lineEnding, bool dotSyntax) const;
- void writeBytecodeText(CodeWriter &code, bool dotSyntax) const;
+ void writeBytecodeText(CodeWriterVisitor &code) const;
Common::String bytecodeText(const char *lineEnding, bool dotSyntax) const;
bool isFactory() const;
diff --git a/engines/director/module.mk b/engines/director/module.mk
index 36d494a4411..6f8d817928d 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -55,7 +55,7 @@ MODULE_OBJS = \
lingo/lingo-utils.o \
lingo/lingodec/ast.o \
lingo/lingodec/context.o \
- lingo/lingodec/codewriter.o \
+ lingo/lingodec/codewritervisitor.o \
lingo/lingodec/handler.o \
lingo/lingodec/names.o \
lingo/lingodec/script.o \
More information about the Scummvm-git-logs
mailing list