|
@@ -49,6 +49,14 @@ static bool sReadInt(Script* sc, int* i) {
|
|
|
return !sRead(sc, i, sizeof(int));
|
|
|
}
|
|
|
|
|
|
+static bool sCheckType(Script* sc, Object* o, ObjectType ot) {
|
|
|
+ if(o->type == ot) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ sError(sc, "object is not of type %s on line %d", oGetName(ot), sc->line);
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
static bool sPush(Script* sc, Object* o) {
|
|
|
if(sc->stackIndex >= SCRIPT_STACK_SIZE) {
|
|
|
sError(sc, "stack overflow on line %d", sc->line);
|
|
@@ -116,11 +124,7 @@ static void sPushVars(Script* sc) {
|
|
|
static void sPopVars(Script* sc) {
|
|
|
int value = 0;
|
|
|
Object o;
|
|
|
- if(sReadInt(sc, &value) && !sPop(sc, &o)) {
|
|
|
- if(o.type != OT_INT) {
|
|
|
- sError(sc, "stack variable index has wrong type");
|
|
|
- return;
|
|
|
- }
|
|
|
+ if(sReadInt(sc, &value) && !sPop(sc, &o) && sCheckType(sc, &o, OT_INT)) {
|
|
|
sc->stackVarIndex = o.data.intValue;
|
|
|
if(sc->stackIndex < value) {
|
|
|
sError(sc, "stack underflow on line %d", sc->line);
|
|
@@ -160,30 +164,20 @@ static void sPushCodeFloat(Script* sc) {
|
|
|
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 o[2];
|
|
|
if(sPop(sc, o) || sPop(sc, o + 1)) {
|
|
|
return;
|
|
|
- }
|
|
|
- if(o[0].type == OT_INT && o[1].type == OT_INT) {
|
|
|
+ } else if(o[0].type == OT_INT && o[1].type == OT_INT) {
|
|
|
sPushInt(sc, fInt(o[0].data.intValue, o[1].data.intValue));
|
|
|
- return;
|
|
|
- }
|
|
|
- float f[2];
|
|
|
- if(sToFloat(sc, o, f) && sToFloat(sc, o + 1, f + 1)) {
|
|
|
- sPushFloat(sc, fFloat(f[0], f[1]));
|
|
|
+ } else if(o[0].type == OT_FLOAT && o[1].type == OT_INT) {
|
|
|
+ sPushFloat(sc, fFloat(o[0].data.floatValue, o[1].data.intValue));
|
|
|
+ } else if(o[0].type == OT_INT && o[1].type == OT_FLOAT) {
|
|
|
+ sPushFloat(sc, fFloat(o[0].data.intValue, o[1].data.floatValue));
|
|
|
+ } else if(o[0].type == OT_FLOAT && o[1].type == OT_FLOAT) {
|
|
|
+ sPushFloat(sc, fFloat(o[0].data.floatValue, o[1].data.floatValue));
|
|
|
+ } else {
|
|
|
+ sError(sc, "object is not a number on line %d", sc->line);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -215,14 +209,16 @@ static void sBoolBinary(Script* sc, bool (*fInt)(int, int), bool (*fFloat)(float
|
|
|
Object o[2];
|
|
|
if(sPop(sc, o) || sPop(sc, o + 1)) {
|
|
|
return;
|
|
|
- }
|
|
|
- if(o[0].type == OT_INT && o[1].type == OT_INT) {
|
|
|
+ } else if(o[0].type == OT_INT && o[1].type == OT_INT) {
|
|
|
sPushBool(sc, fInt(o[0].data.intValue, o[1].data.intValue));
|
|
|
- return;
|
|
|
- }
|
|
|
- float f[2];
|
|
|
- if(sToFloat(sc, o, f) && sToFloat(sc, o + 1, f + 1)) {
|
|
|
- sPushBool(sc, fFloat(f[0], f[1]));
|
|
|
+ } else if(o[0].type == OT_FLOAT && o[1].type == OT_INT) {
|
|
|
+ sPushBool(sc, fFloat(o[0].data.floatValue, o[1].data.intValue));
|
|
|
+ } else if(o[0].type == OT_INT && o[1].type == OT_FLOAT) {
|
|
|
+ sPushBool(sc, fFloat(o[0].data.intValue, o[1].data.floatValue));
|
|
|
+ } else if(o[0].type == OT_FLOAT && o[1].type == OT_FLOAT) {
|
|
|
+ sPushBool(sc, fFloat(o[0].data.floatValue, o[1].data.floatValue));
|
|
|
+ } else {
|
|
|
+ sError(sc, "object is not a number on line %d", sc->line);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -246,8 +242,7 @@ 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) {
|
|
|
+ } else 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);
|
|
@@ -266,13 +261,9 @@ static void sEqual(Script* sc) {
|
|
|
|
|
|
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;
|
|
|
+ if(o != NULL && sCheckType(sc, o, OT_BOOL)) {
|
|
|
+ o->data.intValue = !o->data.intValue;
|
|
|
}
|
|
|
- o->data.intValue = !o->data.intValue;
|
|
|
}
|
|
|
|
|
|
static void sPrint(Script* sc) {
|
|
@@ -312,12 +303,8 @@ static void sGoSub(Script* sc) {
|
|
|
static void sIfGoTo(Script* sc) {
|
|
|
int gotoIndex;
|
|
|
Object o;
|
|
|
- if(sReadInt(sc, &gotoIndex) && !sPop(sc, &o)) {
|
|
|
- if(o.type != OT_BOOL) {
|
|
|
- sError(sc, "object is not a bool on line %d", sc->line);
|
|
|
- } else if(!o.data.intValue) {
|
|
|
- sc->readIndex = gotoIndex;
|
|
|
- }
|
|
|
+ if(sReadInt(sc, &gotoIndex) && !sPop(sc, &o) && sCheckType(sc, &o, OT_BOOL) && !o.data.intValue) {
|
|
|
+ sc->readIndex = gotoIndex;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -327,16 +314,12 @@ static void sSetReturn(Script* sc) {
|
|
|
|
|
|
static void sReturn(Script* sc) {
|
|
|
Object o;
|
|
|
- if(sPop(sc, &o)) {
|
|
|
- return;
|
|
|
- } else if(o.type != OT_INT) {
|
|
|
- sError(sc, "return address on stack is not an int");
|
|
|
- return;
|
|
|
- }
|
|
|
- sc->readIndex = o.data.intValue;
|
|
|
- if(sc->returnValue.type != OT_VOID) {
|
|
|
- sPush(sc, &sc->returnValue);
|
|
|
- sc->returnValue.type = OT_VOID;
|
|
|
+ if(!sPop(sc, &o) && sCheckType(sc, &o, OT_INT)) {
|
|
|
+ sc->readIndex = o.data.intValue;
|
|
|
+ if(sc->returnValue.type != OT_VOID) {
|
|
|
+ sPush(sc, &sc->returnValue);
|
|
|
+ sc->returnValue.type = OT_VOID;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|