added basic arithmetic

actorid
Marc Zinnschlag 15 years ago
parent ca8002e533
commit 48f6ad0f89

@ -2,6 +2,7 @@
#include "exprparser.hpp" #include "exprparser.hpp"
#include <stdexcept> #include <stdexcept>
#include <cassert>
#include "generator.hpp" #include "generator.hpp"
#include "scanner.hpp" #include "scanner.hpp"
@ -9,34 +10,137 @@
namespace Compiler namespace Compiler
{ {
char ExprParser::popUnaryOperator() int ExprParser::getPriority (char op) const
{ {
if (mOperators.empty()) switch (op)
return 0; {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
char op = mOperators[mOperators.size()-1]; case 'm':
return 3;
}
if (op!='m') // unary -
return 0; return 0;
}
mOperators.resize (mOperators.size()-1); char ExprParser::getOperandType (int Index) const
{
assert (!mOperands.empty());
assert (Index>=0);
assert (Index<static_cast<int> (mOperands.size()));
return mOperands[mOperands.size()-1-Index];
}
return op; char ExprParser::getOperator() const
{
assert (!mOperators.empty());
return mOperators[mOperators.size()-1];
} }
char ExprParser::popOperand (std::vector<Interpreter::Type_Code>& code) void ExprParser::popOperator()
{ {
Operand operand = mOperands[mOperands.size()-1]; assert (!mOperators.empty());
mOperators.resize (mOperators.size()-1);
}
void ExprParser::popOperand()
{
assert (!mOperands.empty());
mOperands.resize (mOperands.size()-1); mOperands.resize (mOperands.size()-1);
}
void ExprParser::replaceBinaryOperands()
{
char t1 = getOperandType (1);
char t2 = getOperandType();
if (operand.mType=='l') popOperand();
Generator::pushInt (code, mLiterals, operand.mInteger); popOperand();
else if (operand.mType=='f')
Generator::pushFloat (code, mLiterals, operand.mFloat); if (t1==t2)
mOperands.push_back (t1);
else if (t1=='f' || t2=='f')
mOperands.push_back ('f');
else else
throw std::logic_error ("unknown expression type"); std::logic_error ("failed to determine result operand type");
}
void ExprParser::pop()
{
char op = getOperator();
switch (op)
{
case 'm':
Generator::negate (mCode, getOperandType());
popOperator();
break;
case '+':
Generator::add (mCode, getOperandType (1), getOperandType());
popOperator();
replaceBinaryOperands();
break;
case '-':
Generator::sub (mCode, getOperandType (1), getOperandType());
popOperator();
replaceBinaryOperands();
break;
case '*':
Generator::mul (mCode, getOperandType (1), getOperandType());
popOperator();
replaceBinaryOperands();
break;
case '/':
Generator::div (mCode, getOperandType (1), getOperandType());
popOperator();
replaceBinaryOperands();
break;
default:
throw std::logic_error ("unknown operator");
}
}
void ExprParser::pushIntegerLiteral (int value)
{
mNextOperand = false;
mOperands.push_back ('l');
Generator::pushInt (mCode, mLiterals, value);
}
return operand.mType; void ExprParser::pushFloatLiteral (float value)
{
mNextOperand = false;
mOperands.push_back ('f');
Generator::pushFloat (mCode, mLiterals, value);
}
void ExprParser::pushBinaryOperator (char c)
{
while (!mOperators.empty() && getPriority (getOperator())>=getPriority (c))
pop();
mOperators.push_back (c);
mNextOperand = true;
} }
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals, ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
@ -49,13 +153,7 @@ namespace Compiler
{ {
if (mNextOperand) if (mNextOperand)
{ {
Operand operand; pushIntegerLiteral (value);
operand.mType = 'l';
operand.mInteger = value;
mOperands.push_back (operand);
mNextOperand = false;
mTokenLoc = loc; mTokenLoc = loc;
return true; return true;
} }
@ -67,13 +165,7 @@ namespace Compiler
{ {
if (mNextOperand) if (mNextOperand)
{ {
Operand operand; pushFloatLiteral (value);
operand.mType = 'f';
operand.mFloat = value;
mOperands.push_back (operand);
mNextOperand = false;
mTokenLoc = loc; mTokenLoc = loc;
return true; return true;
} }
@ -109,15 +201,22 @@ namespace Compiler
return false; return false;
} }
if (code==Scanner::S_minus) if (code==Scanner::S_minus && mNextOperand)
{
if (mNextOperand)
{ {
// unary // unary
mOperators.push_back ('m'); mOperators.push_back ('m');
mTokenLoc = loc; mTokenLoc = loc;
return true; return true;
} }
mTokenLoc = loc;
switch (code)
{
case Scanner::S_plus: pushBinaryOperator ('+'); return true;
case Scanner::S_minus: pushBinaryOperator ('-'); return true;
case Scanner::S_mult: pushBinaryOperator ('*'); return true;
case Scanner::S_div: pushBinaryOperator ('/'); return true;
} }
return Parser::parseSpecial (code, loc, scanner); return Parser::parseSpecial (code, loc, scanner);
@ -128,34 +227,30 @@ namespace Compiler
mOperands.clear(); mOperands.clear();
mOperators.clear(); mOperators.clear();
mNextOperand = true; mNextOperand = true;
mCode.clear();
} }
char ExprParser::write (std::vector<Interpreter::Type_Code>& code) char ExprParser::append (std::vector<Interpreter::Type_Code>& code)
{ {
if (mOperands.empty() && mOperators.empty()) if (mOperands.empty() && mOperators.empty())
{
getErrorHandler().error ("missing expression", mTokenLoc); getErrorHandler().error ("missing expression", mTokenLoc);
return 'l';
}
if (mNextOperand) if (mNextOperand || mOperands.empty())
{
getErrorHandler().error ("syntax error in expression", mTokenLoc); getErrorHandler().error ("syntax error in expression", mTokenLoc);
return 'l';
}
char type = ' '; while (!mOperators.empty())
pop();
while (!mOperands.empty())
{
type = popOperand (code);
while (char op = popUnaryOperator()) std::copy (mCode.begin(), mCode.end(), std::back_inserter (code));
{
if (op=='m')
{
Generator::negate (code, type);
}
else
throw std::logic_error ("unknown unary operator");
}
}
return type; assert (mOperands.size()==1);
return mOperands[0];
} }
} }

@ -15,24 +15,33 @@ namespace Compiler
class ExprParser : public Parser class ExprParser : public Parser
{ {
struct Operand
{
char mType;
int mInteger;
float mFloat;
};
Locals& mLocals; Locals& mLocals;
Literals& mLiterals; Literals& mLiterals;
std::vector<Operand> mOperands; std::vector<char> mOperands;
std::vector<char> mOperators; std::vector<char> mOperators;
bool mNextOperand; bool mNextOperand;
TokenLoc mTokenLoc; TokenLoc mTokenLoc;
std::vector<Interpreter::Type_Code> mCode;
int getPriority (char op) const;
char getOperandType (int Index = 0) const;
char getOperator() const;
void popOperator();
void popOperand();
void replaceBinaryOperands();
void pop();
void pushIntegerLiteral (int value);
char popUnaryOperator(); void pushFloatLiteral (float value);
///< returns 0 and not popping, if the next operator isn't unary
char popOperand (std::vector<Interpreter::Type_Code>& code); void pushBinaryOperator (char c);
public: public:
@ -67,7 +76,7 @@ namespace Compiler
void reset(); void reset();
///< Reset parser to clean state. ///< Reset parser to clean state.
char write (std::vector<Interpreter::Type_Code>& code); char append (std::vector<Interpreter::Type_Code>& code);
///< Generate code for parsed expression. ///< Generate code for parsed expression.
/// \return Type ('l': integer, 'f': float) /// \return Type ('l': integer, 'f': float)
}; };

@ -94,6 +94,56 @@ namespace
{ {
code.push_back (segment5 (8)); code.push_back (segment5 (8));
} }
void opAddInt (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (9));
}
void opAddFloat (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (10));
}
void opSubInt (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (11));
}
void opSubFloat (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (12));
}
void opMulInt (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (13));
}
void opMulFloat (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (14));
}
void opDivInt (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (15));
}
void opDivFloat (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (16));
}
void opIntToFloat1 (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (17));
}
void opFloatToInt1 (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (18));
}
} }
namespace Compiler namespace Compiler
@ -175,6 +225,78 @@ namespace Compiler
assert (0); assert (0);
} }
} }
void add (CodeContainer& code, char valueType1, char valueType2)
{
if (valueType1=='l' && valueType2=='l')
{
opAddInt (code);
}
else
{
if (valueType1=='l')
opIntToFloat1 (code);
if (valueType2=='l')
opIntToFloat (code);
opAddFloat (code);
}
}
void sub (CodeContainer& code, char valueType1, char valueType2)
{
if (valueType1=='l' && valueType2=='l')
{
opSubInt (code);
}
else
{
if (valueType1=='l')
opIntToFloat1 (code);
if (valueType2=='l')
opIntToFloat (code);
opSubFloat (code);
}
}
void mul (CodeContainer& code, char valueType1, char valueType2)
{
if (valueType1=='l' && valueType2=='l')
{
opMulInt (code);
}
else
{
if (valueType1=='l')
opIntToFloat1 (code);
if (valueType2=='l')
opIntToFloat (code);
opMulFloat (code);
}
}
void div (CodeContainer& code, char valueType1, char valueType2)
{
if (valueType1=='l' && valueType2=='l')
{
opDivInt (code);
}
else
{
if (valueType1=='l')
opIntToFloat1 (code);
if (valueType2=='l')
opIntToFloat (code);
opDivFloat (code);
}
}
} }
} }

@ -21,6 +21,14 @@ namespace Compiler
int localIndex, const CodeContainer& value, char valueType); int localIndex, const CodeContainer& value, char valueType);
void negate (CodeContainer& code, char valueType); void negate (CodeContainer& code, char valueType);
void add (CodeContainer& code, char valueType1, char valueType2);
void sub (CodeContainer& code, char valueType1, char valueType2);
void mul (CodeContainer& code, char valueType1, char valueType2);
void div (CodeContainer& code, char valueType1, char valueType2);
} }
} }

@ -97,7 +97,7 @@ namespace Compiler
scanner.scan (mExprParser); scanner.scan (mExprParser);
std::vector<Interpreter::Type_Code> code; std::vector<Interpreter::Type_Code> code;
char type = mExprParser.write (code); char type = mExprParser.append (code);
Generator::assignToLocal (mCode, mLocals.getType (mName), Generator::assignToLocal (mCode, mLocals.getType (mName),
mLocals.getIndex (mName), code, type); mLocals.getIndex (mName), code, type);

@ -60,6 +60,16 @@ op 5: replace stack[0] with float literal index stack[0]
op 6: convert stack[0] from float to integer op 6: convert stack[0] from float to integer
op 7: invert sign of int value stack[0] op 7: invert sign of int value stack[0]
op 8: invert sign of float value stack[0] op 8: invert sign of float value stack[0]
opcodes 9-33554431 unused op 9: add (integer) stack[0] to stack[1], pop twice, push result
op 10: add (float) stack[0] to stack[1], pop twice, push result
op 11: sub (integer) stack[1] from stack[0], pop twice, push result
op 12: sub (float) stack[1] from stack[0], pop twice, push result
op 13: mul (integer) stack[0] with stack[1], pop twice, push result
op 14: mul (float) stack[0] with stack[1], pop twice, push result
op 15: div (integer) stack[1] by stack[0], pop twice, push result
op 16: div (float) stack[1] by stack[0], pop twice, push result
op 17: convert stack[1] from integer to float
op 18: convert stack[1] from float to integer
opcodes 19-33554431 unused
opcodes 33554432-67108863 reserved for extensions opcodes 33554432-67108863 reserved for extensions

@ -63,6 +63,30 @@ namespace Interpreter
runtime[0] = *reinterpret_cast<Type_Data *> (&data); runtime[0] = *reinterpret_cast<Type_Data *> (&data);
} }
}; };
class OpIntToFloat1 : public Opcode0
{
public:
virtual void execute (Runtime& runtime)
{
Type_Integer data = *reinterpret_cast<Type_Integer *> (&runtime[1]);
Type_Float floatValue = static_cast<Type_Float> (data);
runtime[1] = *reinterpret_cast<Type_Data *> (&floatValue);
}
};
class OpFloatToInt1 : public Opcode0
{
public:
virtual void execute (Runtime& runtime)
{
Type_Float data = *reinterpret_cast<Type_Float *> (&runtime[1]);
Type_Integer integerValue = static_cast<Type_Integer> (data);
runtime[1] = *reinterpret_cast<Type_Data *> (&integerValue);
}
};
} }
#endif #endif

@ -4,6 +4,7 @@
#include "interpreter.hpp" #include "interpreter.hpp"
#include "genericopcodes.hpp" #include "genericopcodes.hpp"
#include "localopcodes.hpp" #include "localopcodes.hpp"
#include "mathopcodes.hpp"
namespace Interpreter namespace Interpreter
{ {
@ -15,6 +16,8 @@ namespace Interpreter
interpreter.installSegment5 (6, new OpFloatToInt); interpreter.installSegment5 (6, new OpFloatToInt);
interpreter.installSegment5 (7, new OpNegateInt); interpreter.installSegment5 (7, new OpNegateInt);
interpreter.installSegment5 (8, new OpNegateFloat); interpreter.installSegment5 (8, new OpNegateFloat);
interpreter.installSegment5 (17, new OpIntToFloat1);
interpreter.installSegment5 (18, new OpFloatToInt1);
// local variables // local variables
interpreter.installSegment5 (0, new OpStoreLocalShort); interpreter.installSegment5 (0, new OpStoreLocalShort);
@ -22,6 +25,16 @@ namespace Interpreter
interpreter.installSegment5 (2, new OpStoreLocalFloat); interpreter.installSegment5 (2, new OpStoreLocalFloat);
interpreter.installSegment5 (4, new OpFetchIntLiteral); interpreter.installSegment5 (4, new OpFetchIntLiteral);
interpreter.installSegment5 (5, new OpFetchFloatLiteral); interpreter.installSegment5 (5, new OpFetchFloatLiteral);
// math
interpreter.installSegment5 (9, new OpAddInt<Type_Integer>);
interpreter.installSegment5 (10, new OpAddInt<Type_Float>);
interpreter.installSegment5 (11, new OpSubInt<Type_Integer>);
interpreter.installSegment5 (12, new OpSubInt<Type_Float>);
interpreter.installSegment5 (13, new OpMulInt<Type_Integer>);
interpreter.installSegment5 (14, new OpMulInt<Type_Float>);
interpreter.installSegment5 (15, new OpDivInt<Type_Integer>);
interpreter.installSegment5 (16, new OpDivInt<Type_Float>);
} }
} }

@ -0,0 +1,90 @@
#ifndef INTERPRETER_MATHOPCODES_H_INCLUDED
#define INTERPRETER_MATHOPCODES_H_INCLUDED
#include <stdexcept>
#include "opcodes.hpp"
#include "runtime.hpp"
namespace Interpreter
{
template<typename T>
class OpAddInt : public Opcode0
{
public:
virtual void execute (Runtime& runtime)
{
T result =
*reinterpret_cast<T *> (&runtime[1])
+
*reinterpret_cast<T *> (&runtime[0]);
runtime.pop();
runtime[0] = *reinterpret_cast<Type_Data *> (&result);
}
};
template<typename T>
class OpSubInt : public Opcode0
{
public:
virtual void execute (Runtime& runtime)
{
T result =
*reinterpret_cast<T *> (&runtime[1])
-
*reinterpret_cast<T *> (&runtime[0]);
runtime.pop();
runtime[0] = *reinterpret_cast<Type_Data *> (&result);
}
};
template<typename T>
class OpMulInt : public Opcode0
{
public:
virtual void execute (Runtime& runtime)
{
T result =
*reinterpret_cast<T *> (&runtime[1])
*
*reinterpret_cast<T *> (&runtime[0]);
runtime.pop();
runtime[0] = *reinterpret_cast<Type_Data *> (&result);
}
};
template<typename T>
class OpDivInt : public Opcode0
{
public:
virtual void execute (Runtime& runtime)
{
T left = *reinterpret_cast<T *> (&runtime[0]);
if (left==0)
throw std::runtime_error ("division by zero");
T result =
*reinterpret_cast<T *> (&runtime[1])
/
left;
runtime.pop();
runtime[0] = *reinterpret_cast<Type_Data *> (&result);
}
};
}
#endif
Loading…
Cancel
Save