diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 1268f602b..516879c40 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -9,6 +9,36 @@ namespace Compiler { + char ExprParser::popUnaryOperator() + { + if (mOperators.empty()) + return 0; + + char op = mOperators[mOperators.size()-1]; + + if (op!='m') // unary - + return 0; + + mOperators.resize (mOperators.size()-1); + + return op; + } + + char ExprParser::popOperand (std::vector& code) + { + Operand operand = mOperands[mOperands.size()-1]; + mOperands.resize (mOperands.size()-1); + + if (operand.mType=='l') + Generator::pushInt (code, mLiterals, operand.mInteger); + else if (operand.mType=='f') + Generator::pushFloat (code, mLiterals, operand.mFloat); + else + throw std::logic_error ("unknown expression type"); + + return operand.mType; + } + ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, Literals& literals) : Parser (errorHandler, context), mLocals (locals), mLiterals (literals), @@ -18,7 +48,7 @@ namespace Compiler bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner) { if (mNextOperand) - { + { Operand operand; operand.mType = 'l'; operand.mInteger = value; @@ -79,6 +109,17 @@ namespace Compiler return false; } + if (code==Scanner::S_minus) + { + if (mNextOperand) + { + // unary + mOperators.push_back ('m'); + mTokenLoc = loc; + return true; + } + } + return Parser::parseSpecial (code, loc, scanner); } @@ -97,17 +138,24 @@ namespace Compiler if (mNextOperand) getErrorHandler().error ("syntax error in expression", mTokenLoc); - Operand operand = mOperands[mOperands.size()-1]; - mOperands.clear(); - - if (operand.mType=='l') - Generator::pushInt (code, mLiterals, operand.mInteger); - else if (operand.mType=='f') - Generator::pushFloat (code, mLiterals, operand.mFloat); - else - throw std::logic_error ("unknown expression type"); + char type = ' '; + + while (!mOperands.empty()) + { + type = popOperand (code); + + while (char op = popUnaryOperator()) + { + if (op=='m') + { + Generator::negate (code, type); + } + else + throw std::logic_error ("unknown unary operator"); + } + } - return operand.mType; + return type; } } diff --git a/components/compiler/exprparser.hpp b/components/compiler/exprparser.hpp index 0370e35e2..93f5db478 100644 --- a/components/compiler/exprparser.hpp +++ b/components/compiler/exprparser.hpp @@ -29,6 +29,11 @@ namespace Compiler bool mNextOperand; TokenLoc mTokenLoc; + char popUnaryOperator(); + ///< returns 0 and not popping, if the next operator isn't unary + + char popOperand (std::vector& code); + public: ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 8d37f57a9..cf9f68eef 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -84,6 +84,16 @@ namespace { code.push_back (segment5 (2)); } + + void opNegateInt (Compiler::Generator::CodeContainer& code) + { + code.push_back (segment5 (7)); + } + + void opNegateFloat (Compiler::Generator::CodeContainer& code) + { + code.push_back (segment5 (8)); + } } namespace Compiler @@ -145,6 +155,26 @@ namespace Compiler assert (0); } } + + void negate (CodeContainer& code, char valueType) + { + switch (valueType) + { + case 'l': + + opNegateInt (code); + break; + + case 'f': + + opNegateFloat (code); + break; + + default: + + assert (0); + } + } } } diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 061a30df4..42117eecb 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -19,6 +19,8 @@ namespace Compiler void assignToLocal (CodeContainer& code, char localType, int localIndex, const CodeContainer& value, char valueType); + + void negate (CodeContainer& code, char valueType); } } diff --git a/components/interpreter/docs/vmformat.txt b/components/interpreter/docs/vmformat.txt index ca76d00f3..1a4db8b56 100644 --- a/components/interpreter/docs/vmformat.txt +++ b/components/interpreter/docs/vmformat.txt @@ -58,6 +58,8 @@ op 3: convert stack[0] from integer to float op 4: replace stack[0] with integer literal index stack[0] op 5: replace stack[0] with float literal index stack[0] op 6: convert stack[0] from float to integer -opcodes 7-33554431 unused +op 7: invert sign of int value stack[0] +op 8: invert sign of float value stack[0] +opcodes 9-33554431 unused opcodes 33554432-67108863 reserved for extensions diff --git a/components/interpreter/genericopcodes.hpp b/components/interpreter/genericopcodes.hpp index 44e1e9cb4..db22ac089 100644 --- a/components/interpreter/genericopcodes.hpp +++ b/components/interpreter/genericopcodes.hpp @@ -39,6 +39,30 @@ namespace Interpreter runtime[0] = *reinterpret_cast (&integerValue); } }; + + class OpNegateInt : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Integer data = *reinterpret_cast (&runtime[0]); + data = -data; + runtime[0] = *reinterpret_cast (&data); + } + }; + + class OpNegateFloat : public Opcode0 + { + public: + + virtual void execute (Runtime& runtime) + { + Type_Float data = *reinterpret_cast (&runtime[0]); + data = -data; + runtime[0] = *reinterpret_cast (&data); + } + }; } #endif diff --git a/components/interpreter/installopcodes.cpp b/components/interpreter/installopcodes.cpp index df3f69201..15755a38a 100644 --- a/components/interpreter/installopcodes.cpp +++ b/components/interpreter/installopcodes.cpp @@ -13,7 +13,9 @@ namespace Interpreter interpreter.installSegment0 (0, new OpPushInt); interpreter.installSegment5 (3, new OpIntToFloat); interpreter.installSegment5 (6, new OpFloatToInt); - + interpreter.installSegment5 (7, new OpNegateInt); + interpreter.installSegment5 (8, new OpNegateFloat); + // local variables interpreter.installSegment5 (0, new OpStoreLocalShort); interpreter.installSegment5 (1, new OpStoreLocalLong);