|
@@ -71,6 +71,16 @@ static void sPushInt(Script* sc) {
|
|
sPush(sc, &o);
|
|
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;
|
|
|
|
+ }
|
|
|
|
+ Object o = {.type = OT_FLOAT, .data.floatValue = value};
|
|
|
|
+ sPush(sc, &o);
|
|
|
|
+}
|
|
|
|
+
|
|
static void sPushNull(Script* sc) {
|
|
static void sPushNull(Script* sc) {
|
|
Object o = {.type = OT_NULL};
|
|
Object o = {.type = OT_NULL};
|
|
sPush(sc, &o);
|
|
sPush(sc, &o);
|
|
@@ -81,7 +91,7 @@ static void sPushBool(Script* sc, bool b) {
|
|
sPush(sc, &o);
|
|
sPush(sc, &o);
|
|
}
|
|
}
|
|
|
|
|
|
-static void sIntBinary(Script* sc, int (*f)(int, int)) {
|
|
|
|
|
|
+static void sIntBinary(Script* sc, int (*fInt)(int, int), float (*fFloat)(float, float)) {
|
|
Object a;
|
|
Object a;
|
|
if(sPop(sc, &a)) {
|
|
if(sPop(sc, &a)) {
|
|
return;
|
|
return;
|
|
@@ -90,12 +100,29 @@ static void sIntBinary(Script* sc, int (*f)(int, int)) {
|
|
if(sPop(sc, &b)) {
|
|
if(sPop(sc, &b)) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- if(a.type != OT_INT || b.type != OT_INT) {
|
|
|
|
- sError(sc, "object is not an int on line %d", sc->line);
|
|
|
|
- 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);
|
|
}
|
|
}
|
|
- Object o = {.type = OT_INT, .data.intValue = f(a.data.intValue, b.data.intValue)};
|
|
|
|
- sPush(sc, &o);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static int sIntAdd(int a, int b) {
|
|
static int sIntAdd(int a, int b) {
|
|
@@ -106,6 +133,14 @@ static int sIntMul(int a, int b) {
|
|
return a * b;
|
|
return a * b;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static float sFloatAdd(float a, float b) {
|
|
|
|
+ return a + b;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static float sFloatMul(float a, float b) {
|
|
|
|
+ return a * b;
|
|
|
|
+}
|
|
|
|
+
|
|
static void sPrint(Script* sc) {
|
|
static void sPrint(Script* sc) {
|
|
Object o;
|
|
Object o;
|
|
if(sPop(sc, &o)) {
|
|
if(sPop(sc, &o)) {
|
|
@@ -120,11 +155,12 @@ static void sConsumeInstruction(Script* sc) {
|
|
switch(sReadOperation(sc)) {
|
|
switch(sReadOperation(sc)) {
|
|
case OP_NOTHING: break;
|
|
case OP_NOTHING: break;
|
|
case OP_PUSH_INT: sPushInt(sc); break;
|
|
case OP_PUSH_INT: sPushInt(sc); break;
|
|
|
|
+ case OP_PUSH_FLOAT: sPushFloat(sc); break;
|
|
case OP_PUSH_NULL: sPushNull(sc); break;
|
|
case OP_PUSH_NULL: sPushNull(sc); break;
|
|
case OP_PUSH_TRUE: sPushBool(sc, true); break;
|
|
case OP_PUSH_TRUE: sPushBool(sc, true); break;
|
|
case OP_PUSH_FALSE: sPushBool(sc, false); break;
|
|
case OP_PUSH_FALSE: sPushBool(sc, false); break;
|
|
- case OP_ADD: sIntBinary(sc, sIntAdd); break;
|
|
|
|
- case OP_MUL: sIntBinary(sc, sIntMul); break;
|
|
|
|
|
|
+ case OP_ADD: sIntBinary(sc, sIntAdd, sFloatAdd); break;
|
|
|
|
+ case OP_MUL: sIntBinary(sc, sIntMul, sFloatMul); break;
|
|
case OP_PRINT: sPrint(sc); break;
|
|
case OP_PRINT: sPrint(sc); break;
|
|
}
|
|
}
|
|
}
|
|
}
|