forked from teamnwah/openmw-tes3coop
added comparison operators
This commit is contained in:
parent
1674d406dc
commit
aeb41105c4
7 changed files with 217 additions and 10 deletions
|
@ -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…
Reference in a new issue