added comparison operators

actorid
Marc Zinnschlag 15 years ago
parent 1674d406dc
commit aeb41105c4

@ -20,19 +20,28 @@ namespace Compiler
return 0;
case 'e': // ==
case 'n': // !=
case 'l': // <
case 'L': // <=
case 'g': // <
case 'G': // >=
return 1;
case '+':
case '-':
return 1;
return 2;
case '*':
case '/':
return 2;
return 3;
case 'm':
return 3;
return 4;
}
return 0;
@ -125,6 +134,20 @@ namespace Compiler
replaceBinaryOperands();
break;
case 'e':
case 'n':
case 'l':
case 'L':
case 'g':
case 'G':
Generator::compare (mCode, op, getOperandType (1), getOperandType());
popOperator();
popOperand();
popOperand();
mOperands.push_back ('l');
break;
default:
throw std::logic_error ("unknown operator");
@ -164,7 +187,7 @@ namespace Compiler
void ExprParser::parseArguments (const std::string& arguments, Scanner& scanner)
{
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals);
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end();
++iter)
@ -182,9 +205,9 @@ namespace Compiler
}
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
Literals& literals)
Literals& literals, bool argument)
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
mNextOperand (true), mFirst (true)
mNextOperand (true), mFirst (true), mArgument (argument)
{}
bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
@ -345,6 +368,7 @@ namespace Compiler
if (!mNextOperand)
{
mTokenLoc = loc;
char c = 0; // comparison
switch (code)
{
@ -352,6 +376,26 @@ namespace Compiler
case Scanner::S_minus: pushBinaryOperator ('-'); return true;
case Scanner::S_mult: pushBinaryOperator ('*'); return true;
case Scanner::S_div: pushBinaryOperator ('/'); return true;
case Scanner::S_cmpEQ: c = 'e'; break;
case Scanner::S_cmpNE: c = 'n'; break;
case Scanner::S_cmpLT: c = 'l'; break;
case Scanner::S_cmpLE: c = 'L'; break;
case Scanner::S_cmpGT: c = 'g'; break;
case Scanner::S_cmpGE: c = 'G'; break;
}
if (c)
{
if (mArgument && !isOpen())
{
// expression ends here
// Thank you Morrowind for this rotten syntax :(
scanner.putbackSpecial (code, loc);
return false;
}
pushBinaryOperator (c);
return true;
}
}

@ -23,6 +23,7 @@ namespace Compiler
TokenLoc mTokenLoc;
std::vector<Interpreter::Type_Code> mCode;
bool mFirst;
bool mArgument;
int getPriority (char op) const;
@ -53,8 +54,10 @@ namespace Compiler
public:
ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
Literals& literals);
Literals& literals, bool argument = false);
///< constructor
/// \param argument Parser is used to parse function- or instruction-
/// arguments (this influences the precedence rules).
char getType() const;
///< Return type of parsed expression ('l' integer, 'f' float)

@ -195,6 +195,66 @@ namespace
{
code.push_back (segment5 (25));
}
void opEqualInt (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (26));
}
void opNonEqualInt (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (27));
}
void opLessThanInt (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (28));
}
void opLessOrEqualInt (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (29));
}
void opGreaterThanInt (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (30));
}
void opGreaterOrEqualInt (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (31));
}
void opEqualFloat (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (32));
}
void opNonEqualFloat (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (33));
}
void opLessThanFloat (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (34));
}
void opLessOrEqualFloat (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (35));
}
void opGreaterThanFloat (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (36));
}
void opGreaterOrEqualFloat (Compiler::Generator::CodeContainer& code)
{
code.push_back (segment5 (37));
}
}
namespace Compiler
@ -439,6 +499,48 @@ namespace Compiler
jump (code, offset);
}
void compare (CodeContainer& code, char op, char valueType1, char valueType2)
{
if (valueType1=='l' && valueType2=='l')
{
switch (op)
{
case 'e': opEqualInt (code); break;
case 'n': opNonEqualInt (code); break;
case 'l': opLessThanInt (code); break;
case 'L': opLessOrEqualInt (code); break;
case 'g': opGreaterThanInt (code); break;
case 'G': opGreaterOrEqualInt (code); break;
default:
assert (0);
}
}
else
{
if (valueType1=='l')
opIntToFloat1 (code);
if (valueType2=='l')
opIntToFloat (code);
switch (op)
{
case 'e': opEqualFloat (code); break;
case 'n': opNonEqualFloat (code); break;
case 'l': opLessThanFloat (code); break;
case 'L': opLessOrEqualFloat (code); break;
case 'g': opGreaterThanFloat (code); break;
case 'G': opGreaterOrEqualFloat (code); break;
default:
assert (0);
}
}
}
}
}

@ -47,6 +47,8 @@ namespace Compiler
void jumpOnZero (CodeContainer& code, int offset);
void jumpOnNonZero (CodeContainer& code, int offset);
void compare (CodeContainer& code, char op, char valueType1, char valueType2);
}
}

@ -84,6 +84,18 @@ op 22: replace stack[0] with local long stack[0]
op 23: replace stack[0] with local float stack[0]
op 24: skip next instruction if stack[0]==0; pop
op 25: skip next instruction if stack[0]!=0; pop
opcodes 26-33554431 unused
op 26: compare (intger) stack[1] with stack[0]; pop twice; push 1 if equal, 0 else
op 27: compare (intger) stack[1] with stack[0]; pop twice; push 1 if no equal, 0 else
op 28: compare (intger) stack[1] with stack[0]; pop twice; push 1 if lesser than, 0 else
op 29: compare (intger) stack[1] with stack[0]; pop twice; push 1 if lesser or equal, 0 else
op 30: compare (intger) stack[1] with stack[0]; pop twice; push 1 if greater than, 0 else
op 31: compare (intger) stack[1] with stack[0]; pop twice; push 1 if greater or equal, 0 else
op 32: compare (float) stack[1] with stack[0]; pop twice; push 1 if equal, 0 else
op 33: compare (float) stack[1] with stack[0]; pop twice; push 1 if no equal, 0 else
op 34: compare (float) stack[1] with stack[0]; pop twice; push 1 if lesser than, 0 else
op 35: compare (float) stack[1] with stack[0]; pop twice; push 1 if lesser or equal, 0 else
op 36: compare (float) stack[1] with stack[0]; pop twice; push 1 if greater than, 0 else
op 37: compare (float) stack[1] with stack[0]; pop twice; push 1 if greater or equal, 0 else
opcodes 38-33554431 unused
opcodes 33554432-67108863 reserved for extensions

@ -1,6 +1,8 @@
#include "installopcodes.hpp"
#include <functional>
#include "interpreter.hpp"
#include "genericopcodes.hpp"
#include "localopcodes.hpp"
@ -40,8 +42,33 @@ namespace Interpreter
interpreter.installSegment5 (14, new OpMulInt<Type_Float>);
interpreter.installSegment5 (15, new OpDivInt<Type_Integer>);
interpreter.installSegment5 (16, new OpDivInt<Type_Float>);
interpreter.installSegment5 (19, new OpSquareRoot);
interpreter.installSegment5 (19, new OpSquareRoot);
interpreter.installSegment5 (26,
new OpCompare<Type_Integer, std::equal_to<Type_Integer> >);
interpreter.installSegment5 (27,
new OpCompare<Type_Integer, std::not_equal_to<Type_Integer> >);
interpreter.installSegment5 (28,
new OpCompare<Type_Integer, std::less<Type_Integer> >);
interpreter.installSegment5 (29,
new OpCompare<Type_Integer, std::less_equal<Type_Integer> >);
interpreter.installSegment5 (30,
new OpCompare<Type_Integer, std::greater<Type_Integer> >);
interpreter.installSegment5 (31,
new OpCompare<Type_Integer, std::greater_equal<Type_Integer> >);
interpreter.installSegment5 (32,
new OpCompare<Type_Float, std::equal_to<Type_Float> >);
interpreter.installSegment5 (33,
new OpCompare<Type_Float, std::not_equal_to<Type_Float> >);
interpreter.installSegment5 (34,
new OpCompare<Type_Float, std::less<Type_Float> >);
interpreter.installSegment5 (35,
new OpCompare<Type_Float, std::less_equal<Type_Float> >);
interpreter.installSegment5 (36,
new OpCompare<Type_Float, std::greater<Type_Float> >);
interpreter.installSegment5 (37,
new OpCompare<Type_Float, std::greater_equal<Type_Float> >);
// control structures
interpreter.installSegment5 (20, new OpReturn);
interpreter.installSegment5 (24, new OpSkipZero);

@ -103,6 +103,23 @@ namespace Interpreter
runtime[0] = *reinterpret_cast<Type_Data *> (&value);
}
};
template<typename T, typename C>
class OpCompare : public Opcode0
{
public:
virtual void execute (Runtime& runtime)
{
int result = C() (
*reinterpret_cast<T *> (&runtime[1]),
*reinterpret_cast<T *> (&runtime[0]));
runtime.pop();
runtime[0] = *reinterpret_cast<Type_Data *> (&result);
}
};
}
#endif

Loading…
Cancel
Save