/* astxi.cpp Script Language Development Kit Execute from Abstract Syntax Tree Copyright (c) 1996-2002 Parsifal Software. All Rights Reserved. For further information about this program or the AnaGram parser generator, please contact: Parsifal Software http://www.parsifalsoft.com info@parsifalsoft.com +1-800-879-2577, Voice/Fax +1-508-358-2564 P.O. Box 219 Wayland, MA 01778 USA */ #include "comdefs.h" #include "astxi.h" #include // The interpret function implements the astxi interpreter // It is declared in comdefs.h Value interpret(const char *text, Dataset &dataset) { return Interpreter(text, dataset).execute(); } Value Interpreter::execute() { // Scan the tree to update the dictionary updateDictionary(tree.root); // Now execute recursively, starting at the root of the tree. execute(tree.root); return returnValue; } // Function to evaluate an expression Value Interpreter::evaluate(const AstNode *node) { try { switch (node->type) { case typeCommaExpression: { evaluate(node->subnodesCommaExpression.left); return evaluate(node->subnodesCommaExpression.right); } case typeAssignment: { AssignmentNode *assignment = (AssignmentNode *) node; Value destination = evaluate(node->subnodesAssignment.lvalue); Value value = evaluate(node->subnodesAssignment.expression); switch (assignment->opcode) { case STORE: return destination = value; case ADDM: return destination += value; case SUBM: return destination -= value; case MULM: return destination *= value; case DIVM: return destination /= value; case MODM: return destination %= value; case ANDM: return destination &= value; case IORM: return destination |= value; case XORM: return destination ^= value; case LSM: return destination <<= value; case RSM: return destination >>= value; case POWM: { Value base = destination; destination = pow(base.deref(), value); return destination.deref(); } default: return Value(); } } case typeConditionalExpression: { return evaluate(node->subnodesConditionalExpression.condition).isTrue() ? evaluate(node->subnodesConditionalExpression.onTrue) : evaluate(node->subnodesConditionalExpression.onFalse); } case typeLogicalOrExpression: { Value value = evaluate(node->subnodesLogicalOrExpression.left); if (value.isFalse()) value = evaluate(node->subnodesLogicalOrExpression.right); return value; } case typeLogicalAndExpression: { Value value = evaluate(node->subnodesLogicalAndExpression.left); if (value.isTrue()) value = evaluate(node->subnodesLogicalAndExpression.right); return value; } case typeBinary: { Value left = evaluate(node->subnodesBinary.left); Value right = evaluate(node->subnodesBinary.right); BinaryNode *binary = (BinaryNode *) node; switch (binary->opcode) { case EQ: return left == right; case NE: return left != right; case LT: return left < right; case LE: return left <= right; case GT: return left > right; case GE: return left >= right; case ADD: return left += right; case SUB: return left -= right; case MUL: return left *= right; case DIV: return left /= right; case IDIV: return left.idiv(right); case RDIV: return left.rdiv(right); case MOD: return left %= right; case POW: return pow(left, right); case AND: return left &= right; case IOR: return left |= right; case XOR: return left ^= right; case LS: return left <<= right; case RS: return left >>= right; default: return Value(); } } case typeUnary: { Value value = evaluate(node->subnodesUnary.operand); UnaryNode *unary = (UnaryNode *) node; switch (unary->opcode) { case FETCH: return value.deref(); case I_FETCH: return ++value; case D_FETCH: return --value; case FETCH_I: return value++; case FETCH_D: return value--; case NEG: return -value; case NOT: return !value; case COM: return ~value; case CAST_LONG: return value.makeInteger(); case CAST_DOUBLE: return value.makeReal(); default: return Value(); } } case typeConstant: { ConstantNode *constant = (ConstantNode *) node; return constant->value; } case typeVariable: { VariableNode *variable = (VariableNode *) node; return Value(&dataset.value(variable->name)); } case typeFunctionCall: { FunctionCallNode *function = (FunctionCallNode *) node; AgStack argValues; for (int i = 0; i < function->argList.size(); i++) argValues.push(evaluate(function->argList[i])); return callFunction(function->name, argValues); } } } catch(ErrorMessage e) { node->reportError(e.message()); } return Value(); } // Recursively defined function to execute a statement node Interpreter::Outcome Interpreter::execute(const AstNode *node) { Outcome outcome = normal; switch(node->type) { // For nodes not otherwise specified, execute all subnodes in order default: { for (int i = 0; i < nSubnodes[node->type]; i++) { outcome = execute(node->subnode[i]); if (outcome != normal) return outcome; } return normal; } case typeStatementBlock: { ListNode *listNode = (ListNode *) node; for (int i = 0; i < listNode->list.size(); i++) { outcome = execute(listNode->list[i]); if (outcome != normal) return outcome; } return normal; } case typeExpressionStatement: { // evaluate the expression evaluate(node->subnodesExpressionStatement.expression); return normal; } case typeAssignment: { AssignmentNode *assignment = (AssignmentNode *) node; Value destination = evaluate(node->subnodesAssignment.lvalue); Value value = evaluate(node->subnodesAssignment.expression); destination = value; return normal; } case typeIfStatement: { if (evaluate(node->subnodesIfStatement.condition).isTrue()) return execute(node->subnodesIfStatement.statement); return normal; } case typeIfElseStatement: { if (evaluate(node->subnodesIfElseStatement.condition).isTrue()) return execute(node->subnodesIfElseStatement.onTrue); else return execute(node->subnodesIfElseStatement.onFalse); } case typeWhileStatement: { while (evaluate(node->subnodesWhileStatement.condition).isTrue()) { Outcome outcome = execute(node->subnodesWhileStatement.statement); if (outcome == returnEncountered) return returnEncountered; if (outcome == breakEncountered) break; } return normal; } case typeDoStatement: { for (;;) { Outcome outcome = execute(node->subnodesDoStatement.statement); if (outcome == returnEncountered) return returnEncountered; if (outcome == breakEncountered) break; if (evaluate(node->subnodesDoStatement.condition).isFalse()) break; } return normal; } case typeRepeatStatement: { for (;;) { Outcome outcome = execute(node->subnodesDoStatement.statement); if (outcome == returnEncountered) return returnEncountered; if (outcome == breakEncountered) break; if (evaluate(node->subnodesDoStatement.condition).isTrue()) break; } return normal; } case typeSimpleFor: { Value lvalue = evaluate(node->subnodesSimpleFor.lvalue); Value begin = evaluate(node->subnodesSimpleFor.begin); Value inc = evaluate(node->subnodesSimpleFor.inc); Value end = evaluate(node->subnodesSimpleFor.end); lvalue = begin; Value count = (end + inc - begin)/inc; count.makeInteger(); long n = count.getLong(); while (n--) { Outcome outcome = execute(node->subnodesSimpleFor.statement); if (outcome == returnEncountered) return returnEncountered; if (outcome == breakEncountered) break; lvalue += inc; } return normal; } case typeForStatement: { AstNode *condition = node->subnodesForStatement.cond; for (evaluate(node->subnodesForStatement.init); (condition->type == typeNull || evaluate(node->subnodesForStatement.cond).isTrue()); evaluate(node->subnodesForStatement.inc)) { Outcome outcome = execute(node->subnodesForStatement.statement); if (outcome == returnEncountered) return returnEncountered; if (outcome == breakEncountered) break; } return normal; } case typeBreak: { return breakEncountered; } case typeContinue: { return continueEncountered; } case typeDump: { ListNode *listNode = (ListNode *) node; const AgArray &list = listNode->list; for (int i = 0; i < list.size(); i++) { VariableNode *variable = (VariableNode *) list[i]; Value &value = dataset.value(variable->name); cout << (const char *) variable->name << " = " << (const char *) value.asLiteral() << "\n"; } return normal; } case typePrint: { ListNode *listNode = (ListNode *) node; const AgArray &list = listNode->list; for (int i = 0; i < list.size(); i++) cout << (const char *) evaluate(list[i]).asString(); return normal; } case typeReturn: { returnValue = evaluate(node->subnodesReturn.expression); return returnEncountered; } } } // Function to scan tree and add variable names to string dictionary void Interpreter::updateDictionary(const AstNode *node) { switch(node->type) { case typeVariable: { VariableNode *variable = (VariableNode *) node; dataset.dictionary.intern(variable->name); return; } case typeStatementBlock: case typeDump: case typePrint: { ListNode *listNode = (ListNode *) node; const AgArray &list = listNode->list; for (int i = 0; i < list.size(); i++) updateDictionary(list[i]); return; } default: { for (int i = 0; i < nSubnodes[node->type]; i++) updateDictionary(node->subnode[i]); return; } } }