Parcourir la source

Fix try catch mechanism and runtimeError with mrAST

master
mtardy il y a 4 ans
Parent
révision
1a82135eab
5 fichiers modifiés avec 307 ajouts et 89 suppressions
  1. +1
    -1
      object.c
  2. +55
    -72
      parse.leg
  3. +2
    -3
      test-runtime-error.txt
  4. +237
    -0
      test-throw.txt
  5. +12
    -13
      test-try-catch.txt

+ 1
- 1
object.c Voir le fichier

@ -122,7 +122,7 @@ union object {
};
union object _null = {.Undefined = {Undefined}};
oop null = &_null;
const oop null = &_null;
int is(type_t type, oop obj);

+ 55
- 72
parse.leg Voir le fichier

@ -85,7 +85,8 @@ DO_SYMBOLS()
DO_PROTOS()
#undef _DO
int opt_v = 0;
int opt_v= 0;
oop mrAST= null;
typedef struct input_t
{
@ -910,10 +911,10 @@ oop clone(oop obj)
return obj;
}
void runtimeError(oop ast, char *msg)
void runtimeError(char *msg)
{
char *fileName= get(map_get(ast, __file___symbol), String, value);
fprintf(stderr, "\nRuntime error in %s near line %i:\nError: %s\n", fileName, getInteger(map_get(ast, __line___symbol)), msg);
char *fileName= get(map_get(mrAST, __file___symbol), String, value);
fprintf(stderr, "\nRuntime error in %s near line %i:\nError: %s\n", fileName, getInteger(map_get(mrAST, __line___symbol)), msg);
exit(1);
}
@ -924,7 +925,7 @@ oop addOperation(oop ast, oop lhs, oop rhs)
} else if (getType(lhs) == String && getType(rhs) == String) {
return string_concat(lhs, rhs);
} else {
runtimeError(ast, "addition between two incompatible types");
runtimeError("addition between two incompatible types");
assert(0); // to prevent: control may reach end of non-void function
}
}
@ -938,7 +939,7 @@ oop mulOperation(oop ast, oop lhs, oop rhs)
} else if (getType(lhs) == Integer && getType(rhs) == String) {
return string_mul(rhs, lhs);
} else {
runtimeError(ast, "multiplication between two incompatible types");
runtimeError("multiplication between two incompatible types");
assert(0);
}
}
@ -1076,6 +1077,8 @@ oop eval(oop scope, oop ast)
assert(is(Map, ast));
mrAST= ast;
oop proto = map_get(ast, __proto___symbol);
if (proto == null) {
return ast;
@ -1100,7 +1103,7 @@ oop eval(oop scope, oop ast)
return expandUnquotes(scope, obj);
}
case t_Unquote: {
runtimeError(ast, "@ outside of `");
runtimeError("@ outside of `");
}
case t_Declaration: {
oop lhs = map_get(ast, lhs_symbol);
@ -1315,10 +1318,10 @@ oop eval(oop scope, oop ast)
return result;
}
case j_break: {
runtimeError(ast, "break outside of a loop");
runtimeError("break outside of a loop");
}
case j_continue: {
runtimeError(ast, "continue outside of a loop");
runtimeError("continue outside of a loop");
}
case j_throw: {
oop res= jbs->result;
@ -1370,10 +1373,10 @@ oop eval(oop scope, oop ast)
return result;
}
case j_break: {
runtimeError(ast, "break outside of a loop");
runtimeError("break outside of a loop");
}
case j_continue: {
runtimeError(ast, "continue outside of a loop");
runtimeError("continue outside of a loop");
}
case j_throw: {
oop res= jbs->result;
@ -1414,53 +1417,40 @@ oop eval(oop scope, oop ast)
jbRecPush();
int jbt = sigsetjmp(jbs->jb, 0);
switch (jbt) {
case j_return: {
runtimeError(ast, "return outside of a function");
}
case j_break: {
runtimeError(ast, "break outside of a loop or switch");
}
case j_continue: {
runtimeError(ast, "continue outside of a loop");
if (0 == jbt) {
oop res = eval(scope, try);
jbRecPop();
eval(scope, finally);
return res;
}
oop res= jbs->result;
jbRecPop();
// something happend in the try block
if (j_throw == jbt) {
assert(jbs);
jbs->result= res;
if (null == catch) {
return eval(scope, finally);
}
case j_throw: {
oop e= jbs->result;
jbRecPop();
jbs->result= e;
// that should only be set in the catch local scope
setVariable(scope, exception, e);
jbRecPush();
jbt = sigsetjmp(jbs->jb, 0);
switch (jbt) {
case j_return: {
runtimeError(ast, "return outside of a function");
}
case j_break: {
runtimeError(ast, "break outside of a loop or switch");
}
case j_continue: {
runtimeError(ast, "continue outside of a loop");
}
case j_throw: {
// transfer exception
oop e= jbs->result;
jbRecPop();
jbs->result= e;
eval(scope, finally);
siglongjmp(jbs->jb, j_throw);
}
}
oop catchRes= eval(scope, catch);
eval(scope, finally);
oop localScope= newObject(scope);
setVariable(localScope, exception, res);
jbRecPush();
jbt= sigsetjmp(jbs->jb, 0);
if (0 == jbt) {
eval(localScope, catch);
jbRecPop();
return catchRes;
return eval(scope, finally);
}
// something happend in the catch block
res= jbs->result;
jbRecPop();
}
oop res = eval(scope, try);
jbRecPop();
return res;
eval(scope, finally);
assert(jbs);
jbs->result= res;
siglongjmp(jbs->jb, jbt);
}
case t_Block: {
oop statements = map_get(ast, statements_symbol);
@ -1500,13 +1490,13 @@ oop eval(oop scope, oop ast)
switch (getType(map)) {
case String:
if (getInteger(key) >= get(map, String, size)) {
runtimeError(ast, "GetIndex out of range on String");
runtimeError("GetIndex out of range on String");
}
return makeInteger(unescape(get(map, String, value))[getInteger(key)]);
case Map:
return map_get(map, key);
default:
runtimeError(ast, "GetIndex on non Map or String");
runtimeError("GetIndex on non Map or String");
}
}
case t_SetIndex: {
@ -1517,7 +1507,7 @@ oop eval(oop scope, oop ast)
switch (getType(map)) {
case String:
if (getInteger(key) >= get(map, String, size)) {
runtimeError(ast, "SetIndex out of range on String");
runtimeError("SetIndex out of range on String");
}
get(map, String, value)[getInteger(key)] = getInteger(value);
return value;
@ -1525,7 +1515,7 @@ oop eval(oop scope, oop ast)
if (null != op) value= applyOperator(ast, op, map_get(map, key), value);
return map_set(map, key, value);
default:
runtimeError(ast, "SetIndex on non Map or String");
runtimeError("SetIndex on non Map or String");
}
}
@ -1763,12 +1753,10 @@ oop prim_invoke(oop params)
return result;
}
case j_break: {
fprintf(stderr, "\nbreak outside of a loop\n");
exit(1);
runtimeError("break outside of a loop or switch");
}
case j_continue: {
fprintf(stderr, "\ncontinue outside of a loop\n");
exit(1);
runtimeError("continue oustide of a loop");
}
case j_throw: {
oop res= jbs->result;
@ -1805,12 +1793,10 @@ oop apply(oop func, oop args)
return result;
}
case j_break: {
fprintf(stderr, "\nbreak outside of a loop\n");
exit(1);
runtimeError("break outside of a loop or switch");
}
case j_continue: {
fprintf(stderr, "\ncontinue outside of a loop\n");
exit(1);
runtimeError("continue outside of a loop");
}
case j_throw: {
oop res= jbs->result;
@ -1894,14 +1880,11 @@ void readEvalPrint(char *fileName) {
jbRecPop();
switch (jbt) {
case j_return:
fprintf(stderr, "\nreturn outside of a function\n");
exit(1);
runtimeError("return outside of a function");
case j_break:
fprintf(stderr, "\nbreak outside of a loop or switch\n");
exit(1);
runtimeError("break outside of a loop or switch");
case j_continue:
fprintf(stderr, "\ncontinue outside of a loop\n");
exit(1);
runtimeError("continue outside of a loop");
case j_throw:
printf("\nunhandled exception: ");
println(res);

+ 2
- 3
test-runtime-error.txt Voir le fichier

@ -1,6 +1,5 @@
2;
12;
(3*null);
a = {}
a.piz = fun f() {continue;}
`invoke(a, (a.piz), {})
a.piz = fun f() {break;}
invoke(a, (a.piz), {})

+ 237
- 0
test-throw.txt Voir le fichier

@ -0,0 +1,237 @@
fun println() {
apply(print, __arguments__);
print("\n");
__arguments__;
}
fun ok() {
println("OK!");
}
fun ko() {
println("KO!");
throw "this is ko'd";
println("CANNOT HAPPEN");
}
println("----------------A");
try {
println(ok());
}
println("----------------B");
try {
println(ko());
}
println("----------------C");
try {
println(ko());
}
finally {
println("CLEANUP 1");
}
println("----------------D");
try {
println(ko());
}
catch (e) {
println("CAUGHT ", e);
}
println("----------------E");
try {
println(ko());
}
catch (e) {
println("CAUGHT ", e);
}
finally {
println("CLEANUP 2");
}
println("----------------F");
try {
try {
println(ko());
}
catch (e) {
println("CAUGHT ", e);
throw "throwing in catch"
}
finally {
println("CLEANUP 3");
}
} catch (e) println(e);
println("----------------G");
try {
try {
println(ko());
}
catch (e) {
println("CAUGHT ", e);
}
finally {
println("CLEANUP 4");
throw "throwing in finally"
}
} catch (e) println(e);
println("----------------H");
try {
try {
println(ko());
}
catch (e) {
println("RETHROW ", e);
throw e;
}
finally {
println("CLEANUP 5");
}
}
catch (e) {
println("CAUGHT ", e);
}
println("----------------I");
try {
try {
try {
try {
try {
try {
println(ko());
}
catch (e) {
println("RETHROW 6 ", e);
throw e;
}
finally {
println("CLEANUP 6");
}
}
catch (e) {
println("RETHROW 7 ", e);
throw e;
}
finally {
println("CLEANUP 7");
}
}
catch (e) {
println("CAUGHT 8")
}
finally {
println("CLEANUP 8");
}
}
finally {
println("CLEANUP 9");
}
}
finally {
println("CLEANUP 10");
}
}
catch (e) {
println("CAUGHT 11 ", e);
}
finally {
println("CLEANUP 11");
}
println("----------------J");
t=millis();
sum= 0;
for (a= 0; a < 100000; a++) {
sum += a;
}
println(sum, " loop: ", millis()-t);
t=millis();
sum= 0;
for (a= 0; a < 100000; a++) {
sum += a;
continue;
}
println(sum, " continue: ", millis()-t);
println("----------------K");
t=millis();
sum= 0;
for (a= 0; a < 100000; a++) {
try {
try {
try {
try {
try {
try {
try {
try {
try {
try {
sum += a;
// throw "oops";
}
}
}
}
}
}
}
}
}
}
}
println(sum, " tries: ", millis()-t);
t=millis();
sum= 0;
for (a= 0; a < 100000; a++) {
try {
try {
try {
try {
try {
try {
try {
try {
try {
try {
sum += a;
throw "oops";
}
}
}
}
}
}
}
}
}
}
catch (e) {}
}
println(sum, " throws: ", millis()-t);

+ 12
- 13
test-try-catch.txt Voir le fichier

@ -1,18 +1,17 @@
try {
for(i=0; i<10; ++i) {
try {
println("hello")
throw "ERROR 12";
println("that should not be executed");
throw i
} catch (e) {
println("catch!")
println("inner: ", e)
throw "pizza"
print("after pizza")
if (e == 5) {
continue;
}
println(e)
if (e == 8) {
break;
}
} finally {
println("finally...")
throw "oh no"
println("after oh no")
if (i == 3) {
return;
}
}
} catch (e) {
println("outer: ", e);
}

Chargement…
Annuler
Enregistrer