|
@@ -38,7 +38,7 @@ static Operation sReadOperation(Script* sc) {
|
|
|
if(sRead(sc, &c, 1)) {
|
|
|
return OP_NOTHING;
|
|
|
} else if(sRead(sc, &sc->line, sizeof(int))) {
|
|
|
- // operation without line
|
|
|
+ sError(sc, "operation without line near line %d", sc->line);
|
|
|
return OP_NOTHING;
|
|
|
}
|
|
|
return c;
|
|
@@ -61,22 +61,12 @@ static bool sPop(Script* sc, Object* o) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-static void sPushInt(Script* sc) {
|
|
|
- int value = 0;
|
|
|
- if(sRead(sc, &value, sizeof(int))) {
|
|
|
- sError(sc, "cannot read an int from the bytecode on line %d", sc->line);
|
|
|
- return;
|
|
|
- }
|
|
|
+static void sPushInt(Script* sc, int value) {
|
|
|
Object o = {.type = OT_INT, .data.intValue = value};
|
|
|
sPush(sc, &o);
|
|
|
}
|
|
|
|
|
|
-static void sPushFloat(Script* sc) {
|
|
|
- float value = 0;
|
|
|
- if(sRead(sc, &value, sizeof(float))) {
|
|
|
- sError(sc, "cannot read a float from the bytecode on line %d", sc->line);
|
|
|
- return;
|
|
|
- }
|
|
|
+static void sPushFloat(Script* sc, float value) {
|
|
|
Object o = {.type = OT_FLOAT, .data.floatValue = value};
|
|
|
sPush(sc, &o);
|
|
|
}
|
|
@@ -86,42 +76,53 @@ static void sPushNull(Script* sc) {
|
|
|
sPush(sc, &o);
|
|
|
}
|
|
|
|
|
|
-static void sPushBool(Script* sc, bool b) {
|
|
|
- Object o = {.type = OT_BOOL, .data.intValue = b};
|
|
|
+static void sPushBool(Script* sc, bool value) {
|
|
|
+ Object o = {.type = OT_BOOL, .data.intValue = value};
|
|
|
sPush(sc, &o);
|
|
|
}
|
|
|
|
|
|
+static void sPushCodeInt(Script* sc) {
|
|
|
+ int value = 0;
|
|
|
+ if(sRead(sc, &value, sizeof(int))) {
|
|
|
+ sError(sc, "cannot read an int from the bytecode on line %d", sc->line);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ sPushInt(sc, value);
|
|
|
+}
|
|
|
+
|
|
|
+static void sPushCodeFloat(Script* sc) {
|
|
|
+ float value = 0;
|
|
|
+ if(sRead(sc, &value, sizeof(float))) {
|
|
|
+ sError(sc, "cannot read a float from the bytecode on line %d", sc->line);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ sPushFloat(sc, value);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sToFloat(Script* sc, Object* o, float* r) {
|
|
|
+ if(o->type == OT_FLOAT) {
|
|
|
+ *r = o->data.floatValue;
|
|
|
+ return true;
|
|
|
+ } else if(o->type == OT_INT) {
|
|
|
+ *r = o->data.intValue;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ sError(sc, "object is not a number on line %d", sc->line);
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
static void sIntBinary(Script* sc, int (*fInt)(int, int), float (*fFloat)(float, float)) {
|
|
|
- Object a;
|
|
|
- if(sPop(sc, &a)) {
|
|
|
+ Object o[2];
|
|
|
+ if(sPop(sc, o) || sPop(sc, o + 1)) {
|
|
|
return;
|
|
|
}
|
|
|
- Object b;
|
|
|
- if(sPop(sc, &b)) {
|
|
|
+ if(o[0].type == OT_INT && o[1].type == OT_INT) {
|
|
|
+ sPushInt(sc, fInt(o[0].data.intValue, o[1].data.intValue));
|
|
|
return;
|
|
|
}
|
|
|
- if(a.type == OT_INT) {
|
|
|
- if(b.type == OT_INT) {
|
|
|
- Object o = {.type = OT_INT, .data.intValue = fInt(a.data.intValue, b.data.intValue)};
|
|
|
- sPush(sc, &o);
|
|
|
- } else if(b.type == OT_FLOAT) {
|
|
|
- Object o = {.type = OT_FLOAT, .data.floatValue = fFloat(a.data.intValue, b.data.floatValue)};
|
|
|
- sPush(sc, &o);
|
|
|
- } else {
|
|
|
- sError(sc, "first object is not a number on line %d", sc->line);
|
|
|
- }
|
|
|
- } else if(a.type == OT_FLOAT) {
|
|
|
- if(b.type == OT_INT) {
|
|
|
- Object o = {.type = OT_FLOAT, .data.floatValue = fFloat(a.data.floatValue, b.data.intValue)};
|
|
|
- sPush(sc, &o);
|
|
|
- } else if(b.type == OT_FLOAT) {
|
|
|
- Object o = {.type = OT_FLOAT, .data.floatValue = fFloat(a.data.floatValue, b.data.floatValue)};
|
|
|
- sPush(sc, &o);
|
|
|
- } else {
|
|
|
- sError(sc, "first object is not a number on line %d", sc->line);
|
|
|
- }
|
|
|
- } else {
|
|
|
- sError(sc, "second object is not a number on line %d", sc->line);
|
|
|
+ float f[2];
|
|
|
+ if(sToFloat(sc, o, f) && sToFloat(sc, o + 1, f + 1)) {
|
|
|
+ sPushFloat(sc, fFloat(f[0], f[1]));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -154,8 +155,8 @@ static void sPrint(Script* sc) {
|
|
|
static void sConsumeInstruction(Script* sc) {
|
|
|
switch(sReadOperation(sc)) {
|
|
|
case OP_NOTHING: break;
|
|
|
- case OP_PUSH_INT: sPushInt(sc); break;
|
|
|
- case OP_PUSH_FLOAT: sPushFloat(sc); break;
|
|
|
+ case OP_PUSH_INT: sPushCodeInt(sc); break;
|
|
|
+ case OP_PUSH_FLOAT: sPushCodeFloat(sc); break;
|
|
|
case OP_PUSH_NULL: sPushNull(sc); break;
|
|
|
case OP_PUSH_TRUE: sPushBool(sc, true); break;
|
|
|
case OP_PUSH_FALSE: sPushBool(sc, false); break;
|