|
@ -1,6 +1,6 @@ |
|
|
# main.leg -- C parser + interpreter |
|
|
# main.leg -- C parser + interpreter |
|
|
# |
|
|
# |
|
|
# Last edited: 2025-01-31 15:07:48 by piumarta on xubuntu |
|
|
|
|
|
|
|
|
# Last edited: 2025-02-01 08:55:52 by piumarta on xubuntu |
|
|
|
|
|
|
|
|
%{ |
|
|
%{ |
|
|
; |
|
|
; |
|
@ -192,8 +192,6 @@ oop false = 0; |
|
|
oop true = 0; |
|
|
oop true = 0; |
|
|
|
|
|
|
|
|
#define isNil(O) (nil == (O)) |
|
|
#define isNil(O) (nil == (O)) |
|
|
#define isFalse(O) (false == (O)) |
|
|
|
|
|
#define isTrue(O) (true == (O)) |
|
|
|
|
|
|
|
|
|
|
|
oop _new(size_t size, type_t type) |
|
|
oop _new(size_t size, type_t type) |
|
|
{ |
|
|
{ |
|
@ -1264,7 +1262,7 @@ oop toStringOn(oop obj, oop str) |
|
|
oop tag = get(obj, Tstruct,tag); |
|
|
oop tag = get(obj, Tstruct,tag); |
|
|
oop members = get(obj, Tstruct,members); |
|
|
oop members = get(obj, Tstruct,members); |
|
|
if (nil != tag) String_format(str, " %s", symbolName(tag)); |
|
|
if (nil != tag) String_format(str, " %s", symbolName(tag)); |
|
|
if (nil != members) { |
|
|
|
|
|
|
|
|
else if (nil != members) { |
|
|
String_format(str, " {"); |
|
|
String_format(str, " {"); |
|
|
List_do(members, vdecls) toStringOn(vdecls, str); |
|
|
List_do(members, vdecls) toStringOn(vdecls, str); |
|
|
String_format(str, "}"); |
|
|
String_format(str, "}"); |
|
@ -1566,7 +1564,8 @@ void printiln(oop obj, int indent) |
|
|
case Tstruct: { |
|
|
case Tstruct: { |
|
|
printf("Tstruct\n"); |
|
|
printf("Tstruct\n"); |
|
|
printiln(get(obj, Tstruct,tag ), indent+1); |
|
|
printiln(get(obj, Tstruct,tag ), indent+1); |
|
|
printiln(get(obj, Tstruct,members), indent+1); |
|
|
|
|
|
|
|
|
if (indent < 1) |
|
|
|
|
|
printiln(get(obj, Tstruct,members), indent+1); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Tfunction: { |
|
|
case Tfunction: { |
|
@ -1601,7 +1600,7 @@ void printiln(oop obj, int indent) |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Variable: { |
|
|
case Variable: { |
|
|
printf("Variable %s\n", toString(obj)); |
|
|
|
|
|
|
|
|
printf("VARIABLE\n"); |
|
|
printiln(get(obj, Variable,name ), indent+1); |
|
|
printiln(get(obj, Variable,name ), indent+1); |
|
|
printiln(get(obj, Variable,type ), indent+1); |
|
|
printiln(get(obj, Variable,type ), indent+1); |
|
|
printiln(get(obj, Variable,value), indent+1); |
|
|
printiln(get(obj, Variable,value), indent+1); |
|
@ -1876,6 +1875,7 @@ postfix = v:value ( a:args { v = newCall(v, a) } |
|
|
| PPLUS { v = newUnary(POSTINC, v) } |
|
|
| PPLUS { v = newUnary(POSTINC, v) } |
|
|
| MMINUS { v = newUnary(POSTDEC, v) } |
|
|
| MMINUS { v = newUnary(POSTDEC, v) } |
|
|
| DOT i:id { v = newMember(v, i) } |
|
|
| DOT i:id { v = newMember(v, i) } |
|
|
|
|
|
| ARROW i:id { v = newMember(newDereference(v), i) } |
|
|
)* { $$ = v } |
|
|
)* { $$ = v } |
|
|
|
|
|
|
|
|
args = LPAREN a:mkList |
|
|
args = LPAREN a:mkList |
|
@ -1969,6 +1969,7 @@ RETURN = "return" ![_a-zA-Z0-9] - |
|
|
CONTINU = "continue" ![_a-zA-Z0-9] - |
|
|
CONTINU = "continue" ![_a-zA-Z0-9] - |
|
|
BREAK = "break" ![_a-zA-Z0-9] - |
|
|
BREAK = "break" ![_a-zA-Z0-9] - |
|
|
DOT = "." !"." - |
|
|
DOT = "." !"." - |
|
|
|
|
|
ARROW = "->" - |
|
|
ETC = "..." - |
|
|
ETC = "..." - |
|
|
HASH = "#" - |
|
|
HASH = "#" - |
|
|
ASSIGN = "=" !"=" - |
|
|
ASSIGN = "=" !"=" - |
|
@ -2209,7 +2210,15 @@ int typeSize(oop type) |
|
|
case Tfloat: return 4; |
|
|
case Tfloat: return 4; |
|
|
case Tdouble: return 8; |
|
|
case Tdouble: return 8; |
|
|
case Tpointer: return 8; // fixme: make this a parameter |
|
|
case Tpointer: return 8; // fixme: make this a parameter |
|
|
case Tstruct: assert(!"unimplemented"); |
|
|
|
|
|
|
|
|
case Tstruct: { |
|
|
|
|
|
int size = get(type, Tstruct,size); |
|
|
|
|
|
if (size < 0) { |
|
|
|
|
|
oop tag = get(type, Tstruct,tag); |
|
|
|
|
|
fatal("cannot determine size of incomplete struct type '%s'", |
|
|
|
|
|
isNil(tag) ? "<anonymous>" : symbolName(tag)); |
|
|
|
|
|
} |
|
|
|
|
|
return size; |
|
|
|
|
|
} |
|
|
case Tarray: { |
|
|
case Tarray: { |
|
|
oop target = get(type, Tarray,target); |
|
|
oop target = get(type, Tarray,target); |
|
|
if (isNil(target)) fatal("cannot determine size of incomplete array type (unknown element type)"); |
|
|
if (isNil(target)) fatal("cannot determine size of incomplete array type (unknown element type)"); |
|
@ -2226,14 +2235,25 @@ int typeSize(oop type) |
|
|
int toBoolean(oop arg) |
|
|
int toBoolean(oop arg) |
|
|
{ |
|
|
{ |
|
|
switch (getType(arg)) { |
|
|
switch (getType(arg)) { |
|
|
case Integer: return _integerValue(arg); |
|
|
|
|
|
case Float: return integerValue(arg); |
|
|
|
|
|
|
|
|
case Integer: return !!_integerValue(arg); |
|
|
|
|
|
case Float: return !! integerValue(arg); |
|
|
case Reference: return 1; |
|
|
case Reference: return 1; |
|
|
|
|
|
case Pointer: { |
|
|
|
|
|
oop base = get(arg, Pointer,base); |
|
|
|
|
|
switch (getType(base)) { |
|
|
|
|
|
case Integer: return !!_integerValue(base); |
|
|
|
|
|
case Memory: return !!get(base, Memory,base); |
|
|
|
|
|
default: fatal("cannot convert pointer base %s to boolean", getTypeName(base)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
default: fatal("cannot convert %s to boolean", getTypeName(arg)); |
|
|
default: fatal("cannot convert %s to boolean", getTypeName(arg)); |
|
|
} |
|
|
} |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#define isTrue(O) ( toBoolean(O)) |
|
|
|
|
|
#define isFalse(O) (!toBoolean(O)) |
|
|
|
|
|
|
|
|
oop pointerType(oop arg) |
|
|
oop pointerType(oop arg) |
|
|
{ |
|
|
{ |
|
|
switch (getType(arg)) { |
|
|
switch (getType(arg)) { |
|
@ -2447,10 +2467,11 @@ void declareTag(oop type) |
|
|
List_do(decls, decl) { |
|
|
List_do(decls, decl) { |
|
|
oop mtype = makeType(vtype, decl); |
|
|
oop mtype = makeType(vtype, decl); |
|
|
oop mname = makeName(decl); |
|
|
oop mname = makeName(decl); |
|
|
int msize = typeSize(vtype); |
|
|
|
|
|
|
|
|
int msize = typeSize(mtype); |
|
|
int fragment = offset % msize; |
|
|
int fragment = offset % msize; |
|
|
if (fragment) offset += msize - fragment; |
|
|
if (fragment) offset += msize - fragment; |
|
|
List_append(vars, newVariable(mname, mtype, newInteger(offset))); |
|
|
|
|
|
|
|
|
oop var = newVariable(mname, mtype, newInteger(offset)); |
|
|
|
|
|
List_append(vars, var); |
|
|
offset += msize; |
|
|
offset += msize; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -2662,7 +2683,7 @@ oop typeCheck(oop exp, oop fntype) |
|
|
Scope_begin(); |
|
|
Scope_begin(); |
|
|
typeCheck(init, fntype); |
|
|
typeCheck(init, fntype); |
|
|
cond = typeCheck(cond, fntype); |
|
|
cond = typeCheck(cond, fntype); |
|
|
if (t_int != cond) fatal("for condition is not 'int'"); |
|
|
|
|
|
|
|
|
if (t_int != cond && !is(Tpointer, cond)) fatal("for condition is not 'int' or '*'"); |
|
|
typeCheck(step, fntype); |
|
|
typeCheck(step, fntype); |
|
|
typeCheck(body, fntype); |
|
|
typeCheck(body, fntype); |
|
|
Scope_end(); |
|
|
Scope_end(); |
|
@ -2896,10 +2917,12 @@ oop typeCheck(oop exp, oop fntype) |
|
|
} |
|
|
} |
|
|
default: { |
|
|
default: { |
|
|
oop initype = typeCheck(init, fntype); |
|
|
oop initype = typeCheck(init, fntype); |
|
|
|
|
|
if (is(Tpointer, vartype) && is(Integer,init) && !_integerValue(init)) |
|
|
|
|
|
break; |
|
|
cvt_t cvt = converter(getType(initype), getType(vartype)); |
|
|
cvt_t cvt = converter(getType(initype), getType(vartype)); |
|
|
if (!cvt) { |
|
|
if (!cvt) { |
|
|
fatal("initialising '%s': cannot convert '%s' to '%s'", |
|
|
fatal("initialising '%s': cannot convert '%s' to '%s'", |
|
|
toString(varname), toString(vartype), toString(initype)); |
|
|
|
|
|
|
|
|
toString(varname), toString(initype), toString(vartype)); |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
@ -2970,13 +2993,18 @@ oop getPointer(oop ptr) |
|
|
case Tlong: return newInteger(*(long *)addr); |
|
|
case Tlong: return newInteger(*(long *)addr); |
|
|
case Tfloat: return newFloat (*(float *)addr); |
|
|
case Tfloat: return newFloat (*(float *)addr); |
|
|
case Tdouble: return newFloat (*(double *)addr); |
|
|
case Tdouble: return newFloat (*(double *)addr); |
|
|
default: break; |
|
|
|
|
|
|
|
|
case Tstruct: return newStruct(type, base); |
|
|
|
|
|
default: |
|
|
|
|
|
println(ptr); |
|
|
|
|
|
fatal("cannot load '%s' from memory pointer", getTypeName(type)); |
|
|
|
|
|
break; |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
default: |
|
|
default: |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
println(ptr); |
|
|
fatal("cannot load '%s' through pointer", getTypeName(type)); |
|
|
fatal("cannot load '%s' through pointer", getTypeName(type)); |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
@ -3019,6 +3047,15 @@ oop getMemory(oop memory, int offset, oop type) |
|
|
case Tlong: return newInteger(*(long *)addr); |
|
|
case Tlong: return newInteger(*(long *)addr); |
|
|
case Tfloat: return newFloat (*(float *)addr); |
|
|
case Tfloat: return newFloat (*(float *)addr); |
|
|
case Tdouble: return newFloat (*(double *)addr); |
|
|
case Tdouble: return newFloat (*(double *)addr); |
|
|
|
|
|
case Tpointer: { |
|
|
|
|
|
void *value = *(void **)addr; |
|
|
|
|
|
oop target = get(type, Tpointer,target); |
|
|
|
|
|
switch (getType(target)) { |
|
|
|
|
|
case Tstruct: return newPointer(type, newMemory(value, typeSize(target)), 0); |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
|
|
|
fatal("cannot load pointer to '%s' from memory", getTypeName(target)); |
|
|
|
|
|
} |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
|
fatal("cannot load '%s' from memory", getTypeName(type)); |
|
|
fatal("cannot load '%s' from memory", getTypeName(type)); |
|
@ -3039,6 +3076,30 @@ oop setMemory(oop memory, int offset, oop type, oop value) |
|
|
case Tlong: return newInteger(*(long *)addr = _integerValue(value)); |
|
|
case Tlong: return newInteger(*(long *)addr = _integerValue(value)); |
|
|
case Tfloat: return newFloat (*(float *)addr = _floatValue(value)); |
|
|
case Tfloat: return newFloat (*(float *)addr = _floatValue(value)); |
|
|
case Tdouble: return newFloat (*(double *)addr = _floatValue(value)); |
|
|
case Tdouble: return newFloat (*(double *)addr = _floatValue(value)); |
|
|
|
|
|
case Tpointer: { |
|
|
|
|
|
switch (getType(value)) { |
|
|
|
|
|
case Integer: { |
|
|
|
|
|
*(void **)addr = (void *)(intptr_t)_integerValue(value); |
|
|
|
|
|
return newPointer(type, value, 0); |
|
|
|
|
|
} |
|
|
|
|
|
case Pointer: { |
|
|
|
|
|
oop base = get(value, Pointer,base); |
|
|
|
|
|
switch (getType(base)) { |
|
|
|
|
|
case Memory: { |
|
|
|
|
|
*(void **)addr = get(base, Memory,base); |
|
|
|
|
|
return value; |
|
|
|
|
|
} |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
|
|
|
println(base); |
|
|
|
|
|
assert(0); |
|
|
|
|
|
} |
|
|
|
|
|
default: { |
|
|
|
|
|
println(value); |
|
|
|
|
|
fatal("cannot store '%s' into memory", getTypeName(type)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
|
fatal("cannot store '%s' into memory", getTypeName(type)); |
|
|
fatal("cannot store '%s' into memory", getTypeName(type)); |
|
@ -3343,38 +3404,42 @@ void initialiseVariable(oop var, int local) |
|
|
|
|
|
|
|
|
oop eval(oop exp) |
|
|
oop eval(oop exp) |
|
|
{ |
|
|
{ |
|
|
if (opt_v > 2) { printf("EVAL "); println(exp); } |
|
|
|
|
|
|
|
|
static int depth = 0; |
|
|
|
|
|
# define ENTER ++depth |
|
|
|
|
|
# define RETURN(X) do { --depth; return (X); } while (0) |
|
|
|
|
|
if (opt_v > 2) { printf("EVAL "); printiln(exp, depth); } |
|
|
|
|
|
ENTER; |
|
|
switch (getType(exp)) { |
|
|
switch (getType(exp)) { |
|
|
case Undefined: assert(!"this cannot happen"); |
|
|
case Undefined: assert(!"this cannot happen"); |
|
|
case Input: assert(!"this cannot happen"); |
|
|
case Input: assert(!"this cannot happen"); |
|
|
case Integer: return exp; |
|
|
|
|
|
case Float: return exp; |
|
|
|
|
|
case Pointer: return exp; |
|
|
|
|
|
case Array: return exp; |
|
|
|
|
|
case Struct: return exp; |
|
|
|
|
|
|
|
|
case Integer: RETURN(exp); |
|
|
|
|
|
case Float: RETURN(exp); |
|
|
|
|
|
case Pointer: RETURN(exp); |
|
|
|
|
|
case Array: RETURN(exp); |
|
|
|
|
|
case Struct: RETURN(exp); |
|
|
case Symbol: { |
|
|
case Symbol: { |
|
|
oop value = Scope_lookup(exp); |
|
|
oop value = Scope_lookup(exp); |
|
|
if (!value) fatal("'%s' is undefined\n", get(exp, Symbol,name)); |
|
|
if (!value) fatal("'%s' is undefined\n", get(exp, Symbol,name)); |
|
|
if (isNil(value)) fatal("'%s' is uninitialised\n", get(exp, Symbol,name)); |
|
|
if (isNil(value)) fatal("'%s' is uninitialised\n", get(exp, Symbol,name)); |
|
|
switch (getType(value)) { |
|
|
switch (getType(value)) { |
|
|
case Variable: return get(value, Variable,value); |
|
|
|
|
|
case Function: return value; |
|
|
|
|
|
case Primitive: return value; |
|
|
|
|
|
|
|
|
case Variable: RETURN(get(value, Variable,value)); |
|
|
|
|
|
case Function: RETURN(value); |
|
|
|
|
|
case Primitive: RETURN(value); |
|
|
default: fatal("cannot eval: %s", toString(value)); |
|
|
default: fatal("cannot eval: %s", toString(value)); |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Pair: assert(!"this cannot happen"); |
|
|
case Pair: assert(!"this cannot happen"); |
|
|
case String: return exp; |
|
|
|
|
|
|
|
|
case String: RETURN(exp); |
|
|
case List: assert(!"this cannot happen"); |
|
|
case List: assert(!"this cannot happen"); |
|
|
case Memory: assert(!"this cannot happen"); |
|
|
case Memory: assert(!"this cannot happen"); |
|
|
case Primitive: return exp; |
|
|
|
|
|
case Reference: return exp; |
|
|
|
|
|
case Closure: return exp; |
|
|
|
|
|
|
|
|
case Primitive: RETURN(exp); |
|
|
|
|
|
case Reference: RETURN(exp); |
|
|
|
|
|
case Closure: RETURN(exp); |
|
|
case Call: { |
|
|
case Call: { |
|
|
oop fun = eval(get(exp, Call,function)); |
|
|
oop fun = eval(get(exp, Call,function)); |
|
|
oop args = get(exp, Call,arguments); |
|
|
oop args = get(exp, Call,arguments); |
|
|
return apply(fun, args, nil); |
|
|
|
|
|
|
|
|
RETURN(apply(fun, args, nil)); |
|
|
} |
|
|
} |
|
|
case Block: { |
|
|
case Block: { |
|
|
Object *stmts = get(exp, Block,statements); |
|
|
Object *stmts = get(exp, Block,statements); |
|
@ -3384,16 +3449,16 @@ oop eval(oop exp) |
|
|
Scope_begin(); |
|
|
Scope_begin(); |
|
|
switch (nlrPush()) { // longjmp occurred |
|
|
switch (nlrPush()) { // longjmp occurred |
|
|
case NLR_INIT: break; |
|
|
case NLR_INIT: break; |
|
|
case NLR_RETURN: Scope_end(); return nlrPop(); |
|
|
|
|
|
case NLR_CONTINUE: Scope_end(); nlrReturn(NLR_CONTINUE, nlrPop()); |
|
|
|
|
|
case NLR_BREAK: Scope_end(); nlrReturn(NLR_BREAK, nlrPop()); |
|
|
|
|
|
|
|
|
case NLR_RETURN: Scope_end(); --depth; nlrReturn(NLR_RETURN, nlrPop()); |
|
|
|
|
|
case NLR_CONTINUE: Scope_end(); --depth; nlrReturn(NLR_CONTINUE, nlrPop()); |
|
|
|
|
|
case NLR_BREAK: Scope_end(); --depth; nlrReturn(NLR_BREAK, nlrPop()); |
|
|
} |
|
|
} |
|
|
for (int i = 0; i < size; ++i) { |
|
|
for (int i = 0; i < size; ++i) { |
|
|
result = eval(elts[i]); |
|
|
result = eval(elts[i]); |
|
|
} |
|
|
} |
|
|
Scope_end(); |
|
|
Scope_end(); |
|
|
nlrPop(); |
|
|
nlrPop(); |
|
|
return result; |
|
|
|
|
|
|
|
|
RETURN(result); |
|
|
} |
|
|
} |
|
|
case Addressof: { |
|
|
case Addressof: { |
|
|
oop rhs = get(exp, Addressof,rhs); |
|
|
oop rhs = get(exp, Addressof,rhs); |
|
@ -3404,8 +3469,8 @@ oop eval(oop exp) |
|
|
switch (getType(rhs)) { |
|
|
switch (getType(rhs)) { |
|
|
case Variable: { |
|
|
case Variable: { |
|
|
oop type = get(rhs, Variable,type); |
|
|
oop type = get(rhs, Variable,type); |
|
|
if (is(Tarray,type)) return get(rhs, Variable,value); |
|
|
|
|
|
return newPointer(newTpointer(get(rhs, Variable,type)), rhs, 0); |
|
|
|
|
|
|
|
|
if (is(Tarray,type)) RETURN(get(rhs, Variable,value)); |
|
|
|
|
|
RETURN(newPointer(newTpointer(get(rhs, Variable,type)), rhs, 0)); |
|
|
} |
|
|
} |
|
|
default: |
|
|
default: |
|
|
break; |
|
|
break; |
|
@ -3421,7 +3486,7 @@ oop eval(oop exp) |
|
|
case Array: { |
|
|
case Array: { |
|
|
oop type = get(lhs, Array,type); |
|
|
oop type = get(lhs, Array,type); |
|
|
oop base = get(lhs, Array,base); // xxx check index against size |
|
|
oop base = get(lhs, Array,base); // xxx check index against size |
|
|
return newPointer(newTpointer(get(type, Tarray,target)), base, index); |
|
|
|
|
|
|
|
|
RETURN(newPointer(newTpointer(get(type, Tarray,target)), base, index)); |
|
|
} |
|
|
} |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
@ -3439,7 +3504,7 @@ oop eval(oop exp) |
|
|
oop rhs = get(exp, Dereference,rhs); |
|
|
oop rhs = get(exp, Dereference,rhs); |
|
|
rhs = eval(rhs); |
|
|
rhs = eval(rhs); |
|
|
switch (getType(rhs)) { |
|
|
switch (getType(rhs)) { |
|
|
case Pointer: return getPointer(rhs); |
|
|
|
|
|
|
|
|
case Pointer: RETURN(getPointer(rhs)); |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
|
println(rhs); |
|
|
println(rhs); |
|
@ -3448,7 +3513,7 @@ oop eval(oop exp) |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Sizeof: { |
|
|
case Sizeof: { |
|
|
return get(exp, Sizeof,size); |
|
|
|
|
|
|
|
|
RETURN(get(exp, Sizeof,size)); |
|
|
} |
|
|
} |
|
|
case Unary: { |
|
|
case Unary: { |
|
|
unary_t op = get(exp, Unary,operator); |
|
|
unary_t op = get(exp, Unary,operator); |
|
@ -3472,7 +3537,7 @@ oop eval(oop exp) |
|
|
default: assert("!this cannot happen"); |
|
|
default: assert("!this cannot happen"); |
|
|
} |
|
|
} |
|
|
set(rhs, Variable,value, value); |
|
|
set(rhs, Variable,value, value); |
|
|
return result; |
|
|
|
|
|
|
|
|
RETURN(result); |
|
|
} |
|
|
} |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
@ -3484,11 +3549,11 @@ oop eval(oop exp) |
|
|
case COM: { |
|
|
case COM: { |
|
|
rhs = eval(rhs); |
|
|
rhs = eval(rhs); |
|
|
switch (op) { |
|
|
switch (op) { |
|
|
case NEG: return ( is(Float, rhs) |
|
|
|
|
|
? newFloat (-floatValue (rhs)) |
|
|
|
|
|
: newInteger(-integerValue(rhs)) ); |
|
|
|
|
|
case NOT: return isFalse(rhs) ? true : false; |
|
|
|
|
|
case COM: return newInteger(~integerValue(rhs)); |
|
|
|
|
|
|
|
|
case NEG: RETURN( is(Float, rhs) |
|
|
|
|
|
? newFloat (-floatValue (rhs)) |
|
|
|
|
|
: newInteger(-integerValue(rhs)) ); |
|
|
|
|
|
case NOT: RETURN(isFalse(rhs) ? true : false); |
|
|
|
|
|
case COM: RETURN(newInteger(~integerValue(rhs))); |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -3500,29 +3565,29 @@ oop eval(oop exp) |
|
|
oop lhs = get(exp, Binary,lhs); |
|
|
oop lhs = get(exp, Binary,lhs); |
|
|
oop rhs = get(exp, Binary,rhs); |
|
|
oop rhs = get(exp, Binary,rhs); |
|
|
switch (get(exp, Binary,operator)) { |
|
|
switch (get(exp, Binary,operator)) { |
|
|
case LAND: return isFalse(eval(lhs)) ? false : eval(rhs); |
|
|
|
|
|
case LOR: return isTrue (eval(lhs)) ? true : eval(rhs); |
|
|
|
|
|
|
|
|
case LAND: RETURN(isFalse(eval(lhs)) ? false : eval(rhs)); |
|
|
|
|
|
case LOR: RETURN(isTrue (eval(lhs)) ? true : eval(rhs)); |
|
|
default: { |
|
|
default: { |
|
|
lhs = eval(lhs); |
|
|
lhs = eval(lhs); |
|
|
rhs = eval(rhs); |
|
|
rhs = eval(rhs); |
|
|
if (Float == getType(lhs) || Float == getType(rhs)) { // floating point result |
|
|
if (Float == getType(lhs) || Float == getType(rhs)) { // floating point result |
|
|
switch (get(exp, Binary,operator)) { |
|
|
switch (get(exp, Binary,operator)) { |
|
|
case MUL: return FBINOP(lhs, * , rhs); |
|
|
|
|
|
case DIV: return FBINOP(lhs, / , rhs); |
|
|
|
|
|
case MOD: return newFloat(fmod(floatValue(lhs), floatValue(rhs))); |
|
|
|
|
|
case ADD: return FBINOP(lhs, + , rhs); |
|
|
|
|
|
case SUB: return FBINOP(lhs, - , rhs); |
|
|
|
|
|
case SHL: return IBINOP(lhs, <<, rhs); |
|
|
|
|
|
case SHR: return IBINOP(lhs, >>, rhs); |
|
|
|
|
|
case LT: return FRELOP(lhs, < , rhs); |
|
|
|
|
|
case LE: return FRELOP(lhs, <=, rhs); |
|
|
|
|
|
case GE: return FRELOP(lhs, >=, rhs); |
|
|
|
|
|
case GT: return FRELOP(lhs, > , rhs); |
|
|
|
|
|
case EQ: return FRELOP(lhs, == , rhs); |
|
|
|
|
|
case NE: return FRELOP(lhs, !=, rhs); |
|
|
|
|
|
case BAND: return IBINOP(lhs, & , rhs); |
|
|
|
|
|
case BXOR: return IBINOP(lhs, ^ , rhs); |
|
|
|
|
|
case BOR: return IBINOP(lhs, | , rhs); |
|
|
|
|
|
|
|
|
case MUL: RETURN(FBINOP(lhs, * , rhs)); |
|
|
|
|
|
case DIV: RETURN(FBINOP(lhs, / , rhs)); |
|
|
|
|
|
case MOD: RETURN(newFloat(fmod(floatValue(lhs), floatValue(rhs)))); |
|
|
|
|
|
case ADD: RETURN(FBINOP(lhs, + , rhs)); |
|
|
|
|
|
case SUB: RETURN(FBINOP(lhs, - , rhs)); |
|
|
|
|
|
case SHL: RETURN(IBINOP(lhs, <<, rhs)); |
|
|
|
|
|
case SHR: RETURN(IBINOP(lhs, >>, rhs)); |
|
|
|
|
|
case LT: RETURN(FRELOP(lhs, < , rhs)); |
|
|
|
|
|
case LE: RETURN(FRELOP(lhs, <=, rhs)); |
|
|
|
|
|
case GE: RETURN(FRELOP(lhs, >=, rhs)); |
|
|
|
|
|
case GT: RETURN(FRELOP(lhs, > , rhs)); |
|
|
|
|
|
case EQ: RETURN(FRELOP(lhs, == , rhs)); |
|
|
|
|
|
case NE: RETURN(FRELOP(lhs, !=, rhs)); |
|
|
|
|
|
case BAND: RETURN(IBINOP(lhs, & , rhs)); |
|
|
|
|
|
case BXOR: RETURN(IBINOP(lhs, ^ , rhs)); |
|
|
|
|
|
case BOR: RETURN(IBINOP(lhs, | , rhs)); |
|
|
case LAND: |
|
|
case LAND: |
|
|
case LOR: |
|
|
case LOR: |
|
|
break; |
|
|
break; |
|
@ -3530,36 +3595,36 @@ oop eval(oop exp) |
|
|
} |
|
|
} |
|
|
else { // non-float result |
|
|
else { // non-float result |
|
|
switch (get(exp, Binary,operator)) { |
|
|
switch (get(exp, Binary,operator)) { |
|
|
case MUL: return IBINOP(lhs, * , rhs); |
|
|
|
|
|
case DIV: return IBINOP(lhs, / , rhs); |
|
|
|
|
|
case MOD: return IBINOP(lhs, % , rhs); |
|
|
|
|
|
|
|
|
case MUL: RETURN(IBINOP(lhs, * , rhs)); |
|
|
|
|
|
case DIV: RETURN(IBINOP(lhs, / , rhs)); |
|
|
|
|
|
case MOD: RETURN(IBINOP(lhs, % , rhs)); |
|
|
case ADD: { |
|
|
case ADD: { |
|
|
if (is(Pointer, lhs) && is(Integer, rhs)) { |
|
|
if (is(Pointer, lhs) && is(Integer, rhs)) { |
|
|
oop type = get(lhs, Pointer,type); |
|
|
oop type = get(lhs, Pointer,type); |
|
|
oop base = get(lhs, Pointer,base); |
|
|
oop base = get(lhs, Pointer,base); |
|
|
int offset = get(lhs, Pointer,offset); |
|
|
int offset = get(lhs, Pointer,offset); |
|
|
offset += _integerValue(rhs); |
|
|
offset += _integerValue(rhs); |
|
|
return newPointer(type, base, offset); |
|
|
|
|
|
|
|
|
RETURN(newPointer(type, base, offset)); |
|
|
} |
|
|
} |
|
|
if (is(Array, lhs) && is(Integer, rhs)) { |
|
|
if (is(Array, lhs) && is(Integer, rhs)) { |
|
|
oop type = newTpointer(get(get(lhs, Array,type), Tarray,target)); |
|
|
oop type = newTpointer(get(get(lhs, Array,type), Tarray,target)); |
|
|
oop ptr = newPointer(type, get(lhs, Array,base), _integerValue(rhs)); |
|
|
oop ptr = newPointer(type, get(lhs, Array,base), _integerValue(rhs)); |
|
|
return ptr; |
|
|
|
|
|
|
|
|
RETURN(ptr); |
|
|
} |
|
|
} |
|
|
return IBINOP(lhs, + , rhs); |
|
|
|
|
|
|
|
|
RETURN(IBINOP(lhs, + , rhs)); |
|
|
} |
|
|
} |
|
|
case SUB: return IBINOP(lhs, - , rhs); |
|
|
|
|
|
case SHL: return IBINOP(lhs, <<, rhs); |
|
|
|
|
|
case SHR: return IBINOP(lhs, >>, rhs); |
|
|
|
|
|
case LT: return compare(lhs, rhs) < 0 ? true : false; |
|
|
|
|
|
case LE: return compare(lhs, rhs) <= 0 ? true : false; |
|
|
|
|
|
case GE: return compare(lhs, rhs) >= 0 ? true : false; |
|
|
|
|
|
case GT: return compare(lhs, rhs) > 0 ? true : false; |
|
|
|
|
|
case EQ: return equal(lhs, rhs) ? true : false; |
|
|
|
|
|
case NE: return equal(lhs, rhs) ? false : true; |
|
|
|
|
|
case BAND: return IBINOP(lhs, & , rhs); |
|
|
|
|
|
case BXOR: return IBINOP(lhs, ^ , rhs); |
|
|
|
|
|
case BOR: return IBINOP(lhs, | , rhs); |
|
|
|
|
|
|
|
|
case SUB: RETURN(IBINOP(lhs, - , rhs)); |
|
|
|
|
|
case SHL: RETURN(IBINOP(lhs, <<, rhs)); |
|
|
|
|
|
case SHR: RETURN(IBINOP(lhs, >>, rhs)); |
|
|
|
|
|
case LT: RETURN(compare(lhs, rhs) < 0 ? true : false); |
|
|
|
|
|
case LE: RETURN(compare(lhs, rhs) <= 0 ? true : false); |
|
|
|
|
|
case GE: RETURN(compare(lhs, rhs) >= 0 ? true : false); |
|
|
|
|
|
case GT: RETURN(compare(lhs, rhs) > 0 ? true : false); |
|
|
|
|
|
case EQ: RETURN(equal(lhs, rhs) ? true : false); |
|
|
|
|
|
case NE: RETURN(equal(lhs, rhs) ? false : true); |
|
|
|
|
|
case BAND: RETURN(IBINOP(lhs, & , rhs)); |
|
|
|
|
|
case BXOR: RETURN(IBINOP(lhs, ^ , rhs)); |
|
|
|
|
|
case BOR: RETURN(IBINOP(lhs, | , rhs)); |
|
|
case LAND: |
|
|
case LAND: |
|
|
case LOR: |
|
|
case LOR: |
|
|
break; |
|
|
break; |
|
@ -3576,7 +3641,7 @@ oop eval(oop exp) |
|
|
int index = _integerValue(ondex); |
|
|
int index = _integerValue(ondex); |
|
|
oop lhs = eval(get(exp, Index,lhs)); |
|
|
oop lhs = eval(get(exp, Index,lhs)); |
|
|
switch (getType(lhs)) { |
|
|
switch (getType(lhs)) { |
|
|
case Array: return getArray(lhs, index); |
|
|
|
|
|
|
|
|
case Array: RETURN(getArray(lhs, index)); |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
|
println(lhs); |
|
|
println(lhs); |
|
@ -3614,15 +3679,28 @@ oop eval(oop exp) |
|
|
int offset = _integerValue(value); |
|
|
int offset = _integerValue(value); |
|
|
int vsize = typeSize(vtype); |
|
|
int vsize = typeSize(vtype); |
|
|
assert(offset + vsize <= size); |
|
|
assert(offset + vsize <= size); |
|
|
return getMemory(memory, offset, vtype); |
|
|
|
|
|
|
|
|
RETURN(getMemory(memory, offset, vtype)); |
|
|
} |
|
|
} |
|
|
case Assign: { |
|
|
case Assign: { |
|
|
return assign(get(exp, Assign,lhs), eval(get(exp, Assign,rhs))); |
|
|
|
|
|
|
|
|
RETURN(assign(get(exp, Assign,lhs), eval(get(exp, Assign,rhs)))); |
|
|
} |
|
|
} |
|
|
case Cast: { |
|
|
case Cast: { |
|
|
cvt_t cvt = get(exp, Cast,converter); assert(cvt); |
|
|
cvt_t cvt = get(exp, Cast,converter); assert(cvt); |
|
|
|
|
|
oop type = get(exp, Cast,type); |
|
|
oop rhs = eval(get(exp, Cast,rhs)); |
|
|
oop rhs = eval(get(exp, Cast,rhs)); |
|
|
return cvt(rhs); |
|
|
|
|
|
|
|
|
rhs = cvt(rhs); |
|
|
|
|
|
switch (getType(type)) { |
|
|
|
|
|
case Tpointer: { |
|
|
|
|
|
if (is(Pointer,rhs)) { |
|
|
|
|
|
int offset = get(rhs, Pointer,offset); |
|
|
|
|
|
int rscale = typeSize(get(get(rhs, Pointer,type), Tpointer,target)); |
|
|
|
|
|
int lscale = typeSize(get(type, Tpointer,target)); |
|
|
|
|
|
offset = offset * lscale / rscale; |
|
|
|
|
|
RETURN(newPointer(type, get(rhs, Pointer,base), get(rhs, Pointer,offset))); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
RETURN(cvt(rhs)); |
|
|
} |
|
|
} |
|
|
case While: { |
|
|
case While: { |
|
|
oop cond = get(exp, While,condition); |
|
|
oop cond = get(exp, While,condition); |
|
@ -3630,15 +3708,15 @@ oop eval(oop exp) |
|
|
oop result = nil; |
|
|
oop result = nil; |
|
|
switch (nlrPush()) { |
|
|
switch (nlrPush()) { |
|
|
case NLR_INIT: break; |
|
|
case NLR_INIT: break; |
|
|
case NLR_RETURN: nlrReturn(NLR_RETURN, nlrPop()); // propagate upwards |
|
|
|
|
|
|
|
|
case NLR_RETURN: --depth; nlrReturn(NLR_RETURN, nlrPop()); // propagate upwards |
|
|
case NLR_CONTINUE: break; |
|
|
case NLR_CONTINUE: break; |
|
|
case NLR_BREAK: return nlrPop(); |
|
|
|
|
|
|
|
|
case NLR_BREAK: --depth; return nlrPop(); |
|
|
} |
|
|
} |
|
|
while (isTrue(eval(cond))) { |
|
|
while (isTrue(eval(cond))) { |
|
|
result = eval(expr); |
|
|
result = eval(expr); |
|
|
} |
|
|
} |
|
|
nlrPop(); |
|
|
nlrPop(); |
|
|
return result; |
|
|
|
|
|
|
|
|
RETURN(result); |
|
|
} |
|
|
} |
|
|
case For: { |
|
|
case For: { |
|
|
oop init = get(exp, For,initialiser); |
|
|
oop init = get(exp, For,initialiser); |
|
@ -3648,19 +3726,20 @@ oop eval(oop exp) |
|
|
Scope_begin(); |
|
|
Scope_begin(); |
|
|
switch (nlrPush()) { |
|
|
switch (nlrPush()) { |
|
|
case NLR_INIT: break; |
|
|
case NLR_INIT: break; |
|
|
case NLR_RETURN: nlrReturn(NLR_RETURN, nlrPop()); |
|
|
|
|
|
|
|
|
case NLR_RETURN: --depth; Scope_end(); nlrReturn(NLR_RETURN, nlrPop()); |
|
|
case NLR_CONTINUE: goto continued; |
|
|
case NLR_CONTINUE: goto continued; |
|
|
case NLR_BREAK: goto broken; |
|
|
case NLR_BREAK: goto broken; |
|
|
} |
|
|
} |
|
|
eval(init); |
|
|
eval(init); |
|
|
while (integerValue(eval(cond))) { |
|
|
|
|
|
|
|
|
while (isTrue(eval(cond))) { |
|
|
eval(body); |
|
|
eval(body); |
|
|
continued: |
|
|
continued: |
|
|
eval(step); |
|
|
eval(step); |
|
|
} |
|
|
} |
|
|
broken: |
|
|
broken: |
|
|
Scope_end(); |
|
|
Scope_end(); |
|
|
return nil; |
|
|
|
|
|
|
|
|
nlrPop(); |
|
|
|
|
|
RETURN(nil); |
|
|
} |
|
|
} |
|
|
case If: { |
|
|
case If: { |
|
|
oop cond = get(exp, If,condition); |
|
|
oop cond = get(exp, If,condition); |
|
@ -3668,17 +3747,20 @@ oop eval(oop exp) |
|
|
oop altern = get(exp, If,alternate); |
|
|
oop altern = get(exp, If,alternate); |
|
|
if (isTrue(eval(cond))) eval(conseq); |
|
|
if (isTrue(eval(cond))) eval(conseq); |
|
|
else if (!isNil(altern)) eval(altern); |
|
|
else if (!isNil(altern)) eval(altern); |
|
|
return nil; |
|
|
|
|
|
|
|
|
RETURN(nil); |
|
|
} |
|
|
} |
|
|
case Return: { |
|
|
case Return: { |
|
|
|
|
|
--depth; |
|
|
nlrReturn(NLR_RETURN, eval(get(exp, Return,value))); |
|
|
nlrReturn(NLR_RETURN, eval(get(exp, Return,value))); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Continue: { |
|
|
case Continue: { |
|
|
|
|
|
--depth; |
|
|
nlrReturn(NLR_CONTINUE, nil); |
|
|
nlrReturn(NLR_CONTINUE, nil); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Break: { |
|
|
case Break: { |
|
|
|
|
|
--depth; |
|
|
nlrReturn(NLR_BREAK, nil); |
|
|
nlrReturn(NLR_BREAK, nil); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
@ -3702,7 +3784,7 @@ oop eval(oop exp) |
|
|
declare(name, var); |
|
|
declare(name, var); |
|
|
initialiseVariable(var, 1); |
|
|
initialiseVariable(var, 1); |
|
|
} |
|
|
} |
|
|
return nil; |
|
|
|
|
|
|
|
|
RETURN(nil); |
|
|
} |
|
|
} |
|
|
case TypeDecls: { |
|
|
case TypeDecls: { |
|
|
oop types = get(exp, TypeDecls,typenames); |
|
|
oop types = get(exp, TypeDecls,typenames); |
|
@ -3711,7 +3793,7 @@ oop eval(oop exp) |
|
|
oop type = get(type, TypeName,type); |
|
|
oop type = get(type, TypeName,type); |
|
|
declareType(name, type); |
|
|
declareType(name, type); |
|
|
} |
|
|
} |
|
|
return nil; |
|
|
|
|
|
|
|
|
RETURN(nil); |
|
|
} |
|
|
} |
|
|
case Scope: break; |
|
|
case Scope: break; |
|
|
case TypeName: break; |
|
|
case TypeName: break; |
|
@ -3721,7 +3803,9 @@ oop eval(oop exp) |
|
|
} |
|
|
} |
|
|
println(exp); |
|
|
println(exp); |
|
|
assert(!"this cannot happen"); |
|
|
assert(!"this cannot happen"); |
|
|
return 0; |
|
|
|
|
|
|
|
|
RETURN(0); |
|
|
|
|
|
# undef ENTER |
|
|
|
|
|
# undef LEAVE |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// pre-evaluate a top-level declaration, definition, or constant expression |
|
|
// pre-evaluate a top-level declaration, definition, or constant expression |
|
|