|
@@ -72,6 +72,14 @@ static void sPopEmpty(Script* sc) {
|
|
|
sPop(sc, &o);
|
|
|
}
|
|
|
|
|
|
+static Object* sPeek(Script* sc) {
|
|
|
+ if(sc->stackIndex <= 0) {
|
|
|
+ sError(sc, "stack underflow on line %d", sc->line);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ return sc->stack + (sc->stackIndex - 1);
|
|
|
+}
|
|
|
+
|
|
|
static bool sPushInt(Script* sc, int value) {
|
|
|
Object o = {.type = OT_INT, .data.intValue = value};
|
|
|
return sPush(sc, &o);
|
|
@@ -222,10 +230,51 @@ static bool sIntLess(int a, int b) {
|
|
|
return b < a;
|
|
|
}
|
|
|
|
|
|
+static bool sIntGreater(int a, int b) {
|
|
|
+ return b > a;
|
|
|
+}
|
|
|
+
|
|
|
static bool sFloatLess(float a, float b) {
|
|
|
return b < a;
|
|
|
}
|
|
|
|
|
|
+static bool sFloatGreater(float a, float b) {
|
|
|
+ return b > a;
|
|
|
+}
|
|
|
+
|
|
|
+static void sEqual(Script* sc) {
|
|
|
+ Object o[2];
|
|
|
+ if(sPop(sc, o) || sPop(sc, o + 1)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(o[0].type == OT_INT && o[1].type == OT_INT) {
|
|
|
+ sPushBool(sc, o[0].data.intValue == o[1].data.intValue);
|
|
|
+ } else if(o[0].type == OT_INT && o[1].type == OT_FLOAT) {
|
|
|
+ sPushBool(sc, o[0].data.intValue == o[1].data.floatValue);
|
|
|
+ } else if(o[0].type == OT_FLOAT && o[1].type == OT_INT) {
|
|
|
+ sPushBool(sc, o[0].data.floatValue == o[1].data.intValue);
|
|
|
+ } else if(o[0].type == OT_FLOAT && o[1].type == OT_FLOAT) {
|
|
|
+ sPushBool(sc, o[0].data.floatValue == o[1].data.floatValue);
|
|
|
+ } else if(o[0].type == OT_BOOL && o[1].type == OT_BOOL) {
|
|
|
+ sPushBool(sc, o[0].data.intValue == o[1].data.intValue);
|
|
|
+ } else if(o[0].type == OT_NULL && o[1].type == OT_NULL) {
|
|
|
+ sPushBool(sc, true);
|
|
|
+ } else {
|
|
|
+ sError(sc, "object types do not match on line %d", sc->line);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void sNot(Script* sc) {
|
|
|
+ Object* o = sPeek(sc);
|
|
|
+ if(o == NULL) {
|
|
|
+ return;
|
|
|
+ } else if(o->type != OT_BOOL) {
|
|
|
+ sError(sc, "object is not a bool on line %d", sc->line);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ o->data.intValue = !o->data.intValue;
|
|
|
+}
|
|
|
+
|
|
|
static void sPrint(Script* sc) {
|
|
|
Object o;
|
|
|
if(!sPop(sc, &o) && printer(&o)) {
|
|
@@ -308,6 +357,9 @@ static void sConsumeInstruction(Script* sc) {
|
|
|
case OP_SUB: sIntBinary(sc, sIntSub, sFloatSub); break;
|
|
|
case OP_MUL: sIntBinary(sc, sIntMul, sFloatMul); break;
|
|
|
case OP_LESS: sBoolBinary(sc, sIntLess, sFloatLess); break;
|
|
|
+ case OP_GREATER: sBoolBinary(sc, sIntGreater, sFloatGreater); break;
|
|
|
+ case OP_EQUAL: sEqual(sc); break;
|
|
|
+ case OP_NOT: sNot(sc); break;
|
|
|
case OP_PRINT: sPrint(sc); break;
|
|
|
case OP_LINE: sLine(sc); break;
|
|
|
case OP_GOTO: sGoTo(sc); break;
|
|
@@ -400,6 +452,9 @@ void sPrintCode(Script* sc) {
|
|
|
case OP_SUB: puts("Sub"); break;
|
|
|
case OP_MUL: puts("Mul"); break;
|
|
|
case OP_LESS: puts("Less"); break;
|
|
|
+ case OP_GREATER: puts("Greater"); break;
|
|
|
+ case OP_EQUAL: puts("Equal"); break;
|
|
|
+ case OP_NOT: puts("Not"); break;
|
|
|
case OP_PRINT: puts("Print"); break;
|
|
|
case OP_LINE: sPrintInt16(sc, "------------ Line"); break;
|
|
|
case OP_GOTO: sPrintInt(sc, "GoTo"); break;
|