|
@ -1,6 +1,6 @@ |
|
|
# main.leg -- C parser + interpreter |
|
|
# main.leg -- C parser + interpreter |
|
|
# |
|
|
# |
|
|
# Last edited: 2025-01-22 23:32:08 by piumarta on zora |
|
|
|
|
|
|
|
|
# Last edited: 2025-01-23 13:43:27 by piumarta on zora |
|
|
|
|
|
|
|
|
%{ |
|
|
%{ |
|
|
; |
|
|
; |
|
@ -117,7 +117,7 @@ struct Dereference { type_t _type; oop rhs; }; |
|
|
struct Unary { type_t _type; unary_t operator; oop rhs; }; |
|
|
struct Unary { type_t _type; unary_t operator; oop rhs; }; |
|
|
struct Binary { type_t _type; binary_t operator; oop lhs, rhs; }; |
|
|
struct Binary { type_t _type; binary_t operator; oop lhs, rhs; }; |
|
|
struct Assign { type_t _type; oop lhs, rhs; }; |
|
|
struct Assign { type_t _type; oop lhs, rhs; }; |
|
|
struct Cast { type_t _type; oop type, declarator, rhs; }; |
|
|
|
|
|
|
|
|
struct Cast { type_t _type; oop type, rhs; }; |
|
|
struct While { type_t _type; oop condition, expression; }; |
|
|
struct While { type_t _type; oop condition, expression; }; |
|
|
struct For { type_t _type; oop initialiser, condition, update, body; }; |
|
|
struct For { type_t _type; oop initialiser, condition, update, body; }; |
|
|
struct If { type_t _type; oop condition, consequent, alternate; }; |
|
|
struct If { type_t _type; oop condition, consequent, alternate; }; |
|
@ -125,7 +125,9 @@ struct Return { type_t _type; oop value; }; |
|
|
struct Continue { type_t _type; }; |
|
|
struct Continue { type_t _type; }; |
|
|
struct Break { type_t _type; }; |
|
|
struct Break { type_t _type; }; |
|
|
|
|
|
|
|
|
struct Tbase { type_t _type; char *name; int size; }; |
|
|
|
|
|
|
|
|
typedef enum { T_INT = 0, T_FLOAT, T_VOID, T_ETC } base_t; |
|
|
|
|
|
|
|
|
|
|
|
struct Tbase { type_t _type; char *name; int size; base_t type; }; |
|
|
struct Tpointer { type_t _type; oop target; }; |
|
|
struct Tpointer { type_t _type; oop target; }; |
|
|
struct Tarray { type_t _type; oop target; oop size; }; |
|
|
struct Tarray { type_t _type; oop target; oop size; }; |
|
|
struct Tstruct { type_t _type; oop tag, members; }; |
|
|
struct Tstruct { type_t _type; oop tag, members; }; |
|
@ -142,41 +144,9 @@ struct VarDecls { type_t _type; oop type, declarations, variables; }; |
|
|
union Object |
|
|
union Object |
|
|
{ |
|
|
{ |
|
|
type_t _type; |
|
|
type_t _type; |
|
|
struct Input Input; |
|
|
|
|
|
struct Integer Integer; |
|
|
|
|
|
struct Float Float; |
|
|
|
|
|
struct Symbol Symbol; |
|
|
|
|
|
struct Pair Pair; |
|
|
|
|
|
struct String String; |
|
|
|
|
|
struct Array Array; |
|
|
|
|
|
struct Primitive Primitive; |
|
|
|
|
|
struct Reference Reference; |
|
|
|
|
|
struct Closure Closure; |
|
|
|
|
|
struct Call Call; |
|
|
|
|
|
struct Block Block; |
|
|
|
|
|
struct Address Address; |
|
|
|
|
|
struct Dereference Dereference; |
|
|
|
|
|
struct Unary Unary; |
|
|
|
|
|
struct Binary Binary; |
|
|
|
|
|
struct Assign Assign; |
|
|
|
|
|
struct Cast Cast; |
|
|
|
|
|
struct For For; |
|
|
|
|
|
struct While While; |
|
|
|
|
|
struct If If; |
|
|
|
|
|
struct Return Return; |
|
|
|
|
|
struct Continue Continue; |
|
|
|
|
|
struct Break Break; |
|
|
|
|
|
struct Tbase Tbase; |
|
|
|
|
|
struct Tpointer Tpointer; |
|
|
|
|
|
struct Tarray Tarray; |
|
|
|
|
|
struct Tstruct Tstruct; |
|
|
|
|
|
struct Tfunction Tfunction; |
|
|
|
|
|
struct Scope Scope; |
|
|
|
|
|
struct TypeName TypeName; |
|
|
|
|
|
struct Variable Variable; |
|
|
|
|
|
struct Constant Constant; |
|
|
|
|
|
struct Function Function; |
|
|
|
|
|
struct VarDecls VarDecls; |
|
|
|
|
|
|
|
|
# define _(X) struct X X; |
|
|
|
|
|
_do_types(_) |
|
|
|
|
|
# undef _ |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
int opt_O = 0; // optimise (use VM) |
|
|
int opt_O = 0; // optimise (use VM) |
|
@ -186,8 +156,9 @@ int opt_x = 0; // disable execution |
|
|
Object _nil = { ._type = Undefined }; |
|
|
Object _nil = { ._type = Undefined }; |
|
|
|
|
|
|
|
|
#define nil (&_nil) |
|
|
#define nil (&_nil) |
|
|
#define false (&_nil) |
|
|
|
|
|
oop true = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
oop false = 0; |
|
|
|
|
|
oop true = 0; |
|
|
|
|
|
|
|
|
oop _new(size_t size, type_t type) |
|
|
oop _new(size_t size, type_t type) |
|
|
{ |
|
|
{ |
|
@ -329,7 +300,7 @@ long integerValue(oop obj) |
|
|
case Float: return _floatValue(obj); |
|
|
case Float: return _floatValue(obj); |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
|
fatal("cannot convert type %d to integer", getType(obj)); |
|
|
|
|
|
|
|
|
fatal("cannot convert %s to integer", getTypeName(obj)); |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -615,7 +586,7 @@ oop newBinary(binary_t operator, oop lhs, oop rhs) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
CTOR2(Assign, lhs, rhs); |
|
|
CTOR2(Assign, lhs, rhs); |
|
|
CTOR3(Cast, type, declarator, rhs); |
|
|
|
|
|
|
|
|
CTOR2(Cast, type, rhs); |
|
|
CTOR2(While, condition, expression); |
|
|
CTOR2(While, condition, expression); |
|
|
CTOR4(For, initialiser, condition, update, body); |
|
|
CTOR4(For, initialiser, condition, update, body); |
|
|
CTOR3(If, condition, consequent, alternate); |
|
|
CTOR3(If, condition, consequent, alternate); |
|
@ -626,11 +597,12 @@ CTOR0(Break); |
|
|
void println(oop obj); |
|
|
void println(oop obj); |
|
|
char *toString(oop obj); |
|
|
char *toString(oop obj); |
|
|
|
|
|
|
|
|
oop newTbase(char *name, int size) |
|
|
|
|
|
|
|
|
oop newTbase(char *name, int size, base_t type) |
|
|
{ |
|
|
{ |
|
|
oop obj = new(Tbase); |
|
|
oop obj = new(Tbase); |
|
|
obj->Tbase.name = name; |
|
|
obj->Tbase.name = name; |
|
|
obj->Tbase.size = size; |
|
|
obj->Tbase.size = size; |
|
|
|
|
|
obj->Tbase.type = type; |
|
|
return obj; |
|
|
return obj; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -874,8 +846,7 @@ oop baseType(oop type) |
|
|
case Tpointer: return baseType(get(type, Tpointer,target)); |
|
|
case Tpointer: return baseType(get(type, Tpointer,target)); |
|
|
case Tarray: return baseType(get(type, Tarray,target)); |
|
|
case Tarray: return baseType(get(type, Tarray,target)); |
|
|
case Tfunction: return baseType(get(type, Tfunction,result)); |
|
|
case Tfunction: return baseType(get(type, Tfunction,result)); |
|
|
default: |
|
|
|
|
|
fatal("cannot find base type of %s", getTypeName(type)); |
|
|
|
|
|
|
|
|
default: fatal("cannot find base type of %s", getTypeName(type)); |
|
|
} |
|
|
} |
|
|
return nil; |
|
|
return nil; |
|
|
} |
|
|
} |
|
@ -940,12 +911,19 @@ oop toStringOn(oop obj, oop str) |
|
|
char *chars = get(obj, String,elements); |
|
|
char *chars = get(obj, String,elements); |
|
|
for (int i = 0, n = get(obj, String,size); i < n; ++i) { |
|
|
for (int i = 0, n = get(obj, String,size); i < n; ++i) { |
|
|
int c = chars[i]; |
|
|
int c = chars[i]; |
|
|
if (' ' <= c || c <= 126) String_append(str, c); |
|
|
|
|
|
|
|
|
if ((' ' <= c) && (c <= 126)) String_append(str, c); |
|
|
else String_format(str, "\\x%02x", c); |
|
|
else String_format(str, "\\x%02x", c); |
|
|
} |
|
|
} |
|
|
String_append(str, '"'); |
|
|
String_append(str, '"'); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
case Cast: { |
|
|
|
|
|
String_append(str, '('); |
|
|
|
|
|
toStringOn(get(obj, Cast,type), str); |
|
|
|
|
|
String_append(str, ')'); |
|
|
|
|
|
toStringOn(get(obj, Cast,rhs), str); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
case Unary: { |
|
|
case Unary: { |
|
|
char *name = 0; |
|
|
char *name = 0; |
|
|
oop rhs = get(obj, Unary,rhs); |
|
|
oop rhs = get(obj, Unary,rhs); |
|
@ -963,7 +941,31 @@ oop toStringOn(oop obj, oop str) |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Binary: { |
|
|
case Binary: { |
|
|
String_format(str, "%s", binaryName(get(obj, Binary,operator))); |
|
|
|
|
|
|
|
|
char *name = 0; |
|
|
|
|
|
char *lhs = toString(get(obj, Binary,lhs)); |
|
|
|
|
|
char *rhs = toString(get(obj, Binary,rhs)); |
|
|
|
|
|
switch (get(obj, Binary,operator)) { |
|
|
|
|
|
case INDEX: String_format(str, "%s[%s]", lhs, rhs); return str; |
|
|
|
|
|
case MUL: name = "*"; break; |
|
|
|
|
|
case DIV: name = "/"; break; |
|
|
|
|
|
case MOD: name = "%"; break; |
|
|
|
|
|
case ADD: name = "+"; break; |
|
|
|
|
|
case SUB: name = "-"; break; |
|
|
|
|
|
case SHL: name = "<<"; break; |
|
|
|
|
|
case SHR: name = ">>"; break; |
|
|
|
|
|
case LT: name = "<"; break; |
|
|
|
|
|
case LE: name = "<="; break; |
|
|
|
|
|
case GE: name = ">"; break; |
|
|
|
|
|
case GT: name = ">="; break; |
|
|
|
|
|
case EQ: name = "=="; break; |
|
|
|
|
|
case NE: name = "!="; break; |
|
|
|
|
|
case BAND: name = "&"; break; |
|
|
|
|
|
case BXOR: name = "^"; break; |
|
|
|
|
|
case BOR: name = "|"; break; |
|
|
|
|
|
case LAND: name = "&&"; break; |
|
|
|
|
|
case LOR: name = "||"; break; |
|
|
|
|
|
} |
|
|
|
|
|
String_format(str, "%s %s %s", lhs, name, rhs); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Assign: { |
|
|
case Assign: { |
|
@ -972,6 +974,27 @@ oop toStringOn(oop obj, oop str) |
|
|
toStringOn(get(obj, Assign,rhs), str); |
|
|
toStringOn(get(obj, Assign,rhs), str); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
case Call: { |
|
|
|
|
|
toStringOn(get(obj, Call,function), str); |
|
|
|
|
|
String_append(str, '('); |
|
|
|
|
|
Array_do(get(obj, Call,arguments), arg) { |
|
|
|
|
|
if (do_index) String_format(str, ", "); |
|
|
|
|
|
toStringOn(arg, str); |
|
|
|
|
|
} |
|
|
|
|
|
String_append(str, ')'); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
case For: { |
|
|
|
|
|
String_format(str, "for ("); |
|
|
|
|
|
toStringOn(get(obj, For,initialiser), str); |
|
|
|
|
|
String_format(str, "; "); |
|
|
|
|
|
toStringOn(get(obj, For,condition), str); |
|
|
|
|
|
String_format(str, "; "); |
|
|
|
|
|
toStringOn(get(obj, For,update), str); |
|
|
|
|
|
String_format(str, ") "); |
|
|
|
|
|
toStringOn(get(obj, For,body), str); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
case Tbase: |
|
|
case Tbase: |
|
|
String_format(str, "%s", get(obj, Tbase,name)); |
|
|
String_format(str, "%s", get(obj, Tbase,name)); |
|
|
break; |
|
|
break; |
|
@ -1167,7 +1190,6 @@ void printiln(oop obj, int indent) |
|
|
case Cast: { |
|
|
case Cast: { |
|
|
printf("CAST\n"); |
|
|
printf("CAST\n"); |
|
|
printiln(get(obj, Cast,type ), indent+1); |
|
|
printiln(get(obj, Cast,type ), indent+1); |
|
|
printiln(get(obj, Cast,declarator), indent+1); |
|
|
|
|
|
printiln(get(obj, Cast,rhs ), indent+1); |
|
|
printiln(get(obj, Cast,rhs ), indent+1); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
@ -1496,7 +1518,7 @@ unary = MINUS r:unary { $$ = newUnary(NEG, r) } |
|
|
| postfix |
|
|
| postfix |
|
|
|
|
|
|
|
|
cast = LPAREN t:tname d:decltor |
|
|
cast = LPAREN t:tname d:decltor |
|
|
RPAREN r:unary { $$ = newCast(t, d, r) } |
|
|
|
|
|
|
|
|
RPAREN r:unary { $$ = newCast(makeType(t, d), r) } |
|
|
|
|
|
|
|
|
postfix = v:value ( a:args { v = newCall(v, a) } |
|
|
postfix = v:value ( a:args { v = newCall(v, a) } |
|
|
| i:index { v = newBinary(INDEX, v, i) } |
|
|
| i:index { v = newBinary(INDEX, v, i) } |
|
@ -1765,6 +1787,16 @@ void declarePrimitive(oop name, oop type, prim_t function) |
|
|
declare(name, newPrimitive(name, type, function)); |
|
|
declare(name, newPrimitive(name, type, function)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop incr(oop val, int amount) |
|
|
|
|
|
{ |
|
|
|
|
|
switch (getType(val)) { |
|
|
|
|
|
case Integer: return newInteger(integerValue(val) + amount); |
|
|
|
|
|
case Float: return newFloat ( floatValue(val) + amount); |
|
|
|
|
|
default: fatal("cannot increment: %s", toString(val)); |
|
|
|
|
|
} |
|
|
|
|
|
return nil; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
oop eval(oop exp, oop env) |
|
|
oop eval(oop exp, oop env) |
|
|
{ |
|
|
{ |
|
|
if (opt_v > 2) { printf("EVAL "); println(exp); } |
|
|
if (opt_v > 2) { printf("EVAL "); println(exp); } |
|
@ -1781,7 +1813,7 @@ oop eval(oop exp, oop env) |
|
|
case Variable: return get(value, Variable,value); |
|
|
case Variable: return get(value, Variable,value); |
|
|
case Function: return value; |
|
|
case Function: return value; |
|
|
case Primitive: return value; |
|
|
case Primitive: return value; |
|
|
default: fatal("cannot convert to value: %s", toString(value)); |
|
|
|
|
|
|
|
|
default: fatal("cannot eval: %s", toString(value)); |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
@ -1842,18 +1874,49 @@ oop eval(oop exp, oop env) |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Unary: { |
|
|
case Unary: { |
|
|
oop rhs = eval(get(exp, Unary,rhs), env); |
|
|
|
|
|
switch (get(exp, Unary,operator)) { |
|
|
|
|
|
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 PREINC: assert(!"unimplemented"); |
|
|
|
|
|
case PREDEC: assert(!"unimplemented"); |
|
|
|
|
|
case POSTINC: assert(!"unimplemented"); |
|
|
|
|
|
case POSTDEC: assert(!"unimplemented"); |
|
|
|
|
|
|
|
|
unary_t op = get(exp, Unary,operator); |
|
|
|
|
|
oop rhs = get(exp, Unary,rhs); |
|
|
|
|
|
switch (op) { |
|
|
|
|
|
case PREINC: |
|
|
|
|
|
case PREDEC: |
|
|
|
|
|
case POSTINC: |
|
|
|
|
|
case POSTDEC: { |
|
|
|
|
|
if (is(Symbol, rhs)) { |
|
|
|
|
|
rhs = Scope_lookup(rhs); |
|
|
|
|
|
switch (getType(rhs)) { |
|
|
|
|
|
case Variable: { |
|
|
|
|
|
oop val = get(rhs, Variable,value); |
|
|
|
|
|
oop result = nil; |
|
|
|
|
|
switch (op) { |
|
|
|
|
|
case PREINC: val = incr(val, 1); result = val; break; |
|
|
|
|
|
case PREDEC: val = incr(val, -1); result = val; break; |
|
|
|
|
|
case POSTINC: result = val; val = incr(val, 1); break; |
|
|
|
|
|
case POSTDEC: result = val; val = incr(val, -1); break; |
|
|
|
|
|
default: assert("!this cannot happen"); |
|
|
|
|
|
} |
|
|
|
|
|
set(rhs, Variable,value, val); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
fatal("illegal increment operation: %s", toString(exp)); |
|
|
|
|
|
} |
|
|
|
|
|
case NEG: |
|
|
|
|
|
case NOT: |
|
|
|
|
|
case COM: { |
|
|
|
|
|
rhs = eval(rhs, env); |
|
|
|
|
|
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)); |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
assert("!this cannot happen"); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Binary: { |
|
|
case Binary: { |
|
@ -1947,7 +2010,44 @@ oop eval(oop exp, oop env) |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Cast: { |
|
|
case Cast: { |
|
|
assert(!"unimplemented"); |
|
|
|
|
|
|
|
|
oop lhs = get(exp, Cast,type); |
|
|
|
|
|
oop rhs = eval(get(exp, Cast,rhs), nil); |
|
|
|
|
|
switch (getType(rhs)) { |
|
|
|
|
|
case Integer: |
|
|
|
|
|
case Float: { |
|
|
|
|
|
switch (getType(lhs)) { |
|
|
|
|
|
case Tbase: { |
|
|
|
|
|
switch (get(lhs, Tbase,type)) { |
|
|
|
|
|
case T_INT: { |
|
|
|
|
|
switch (get(lhs, Tbase,size)) { |
|
|
|
|
|
case 1: return newInteger( (char)integerValue(rhs)); |
|
|
|
|
|
case 2: return newInteger((short)integerValue(rhs)); |
|
|
|
|
|
case 4: return newInteger( (int)integerValue(rhs)); |
|
|
|
|
|
case 8: return rhs; |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
case T_FLOAT: { |
|
|
|
|
|
switch (get(lhs, Tbase,size)) { |
|
|
|
|
|
case 4: return newFloat((float)floatValue(rhs)); |
|
|
|
|
|
case 8: return newFloat(floatValue(rhs)); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
default: |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
default: |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
default: |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
fatal("cannot convert '%s' to '%s'", toString(rhs), toString(lhs)); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case While: { |
|
|
case While: { |
|
@ -1967,7 +2067,15 @@ oop eval(oop exp, oop env) |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
|
case For: { |
|
|
case For: { |
|
|
assert(!"unimplemented"); |
|
|
|
|
|
|
|
|
oop init = get(exp, For,initialiser); |
|
|
|
|
|
oop cond = get(exp, For,condition); |
|
|
|
|
|
oop step = get(exp, For,update); |
|
|
|
|
|
oop body = get(exp, For,body); |
|
|
|
|
|
eval(init, nil); |
|
|
|
|
|
while (integerValue(eval(cond, nil))) { |
|
|
|
|
|
eval(body, nil); |
|
|
|
|
|
eval(step, nil); |
|
|
|
|
|
} |
|
|
return nil; |
|
|
return nil; |
|
|
} |
|
|
} |
|
|
case If: { |
|
|
case If: { |
|
@ -2610,6 +2718,19 @@ oop compile(oop exp) // 6*7 |
|
|
return program; |
|
|
return program; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int typeSize(oop type) |
|
|
|
|
|
{ |
|
|
|
|
|
switch (getType(type)) { |
|
|
|
|
|
case Tbase: return get(type, Tbase,size); |
|
|
|
|
|
case Tpointer: return 8; // fixme: make this a parameter |
|
|
|
|
|
case Tstruct: assert(!"unimplemented"); |
|
|
|
|
|
case Tarray: assert(!"unimplemented"); |
|
|
|
|
|
case Tfunction: assert(!"unimplemented"); |
|
|
|
|
|
default: assert(!"this cannot happen"); |
|
|
|
|
|
} |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
oop typeCheck(oop exp, oop fntype) |
|
|
oop typeCheck(oop exp, oop fntype) |
|
|
{ |
|
|
{ |
|
|
switch (getType(exp)) { |
|
|
switch (getType(exp)) { |
|
@ -2639,13 +2760,55 @@ oop typeCheck(oop exp, oop fntype) |
|
|
} |
|
|
} |
|
|
return get(rhs, Tpointer,target); |
|
|
return get(rhs, Tpointer,target); |
|
|
} |
|
|
} |
|
|
|
|
|
case Cast: { |
|
|
|
|
|
oop lhs = get(exp, Cast,type); |
|
|
|
|
|
oop rhs = typeCheck(get(exp, Cast,rhs), fntype); |
|
|
|
|
|
switch (getType(lhs)) { |
|
|
|
|
|
case Tbase: { // int, float, void, ... |
|
|
|
|
|
if (get(lhs, Tbase,type) < T_VOID) { // int, float |
|
|
|
|
|
switch (getType(rhs)) { |
|
|
|
|
|
case Tbase: { |
|
|
|
|
|
if (get(rhs, Tbase,type) < T_VOID) return lhs; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
case Tpointer: { |
|
|
|
|
|
if (typeSize(lhs) != typeSize(rhs)) |
|
|
|
|
|
fatal("casting pointer to integer of different size"); |
|
|
|
|
|
return lhs; |
|
|
|
|
|
default: |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
case Tpointer: { |
|
|
|
|
|
switch (getType(rhs)) { |
|
|
|
|
|
case Tbase: { |
|
|
|
|
|
if (get(rhs, Tbase,type) < T_VOID) { |
|
|
|
|
|
if (typeSize(lhs) == typeSize(rhs)) return lhs; |
|
|
|
|
|
fatal("casting integer to pointer of different size"); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
case Tpointer: { |
|
|
|
|
|
return lhs; |
|
|
|
|
|
} |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
|
|
|
fatal("cannot convert '%s' to '%s'", toString(lhs), toString(rhs)); |
|
|
|
|
|
return nil; |
|
|
|
|
|
} |
|
|
case Unary: { |
|
|
case Unary: { |
|
|
oop rhs = typeCheck(get(exp, Unary,rhs), fntype); |
|
|
oop rhs = typeCheck(get(exp, Unary,rhs), fntype); |
|
|
switch (get(exp, Unary,operator)) { |
|
|
switch (get(exp, Unary,operator)) { |
|
|
case NEG: assert(!"unimplemented"); |
|
|
case NEG: assert(!"unimplemented"); |
|
|
case NOT: assert(!"unimplemented"); |
|
|
case NOT: assert(!"unimplemented"); |
|
|
case COM: assert(!"unimplemented"); |
|
|
case COM: assert(!"unimplemented"); |
|
|
case PREINC: assert(!"unimplemented"); |
|
|
|
|
|
|
|
|
case PREINC: return rhs; |
|
|
case PREDEC: assert(!"unimplemented"); |
|
|
case PREDEC: assert(!"unimplemented"); |
|
|
case POSTINC: assert(!"unimplemented"); |
|
|
case POSTINC: assert(!"unimplemented"); |
|
|
case POSTDEC: assert(!"unimplemented"); |
|
|
case POSTDEC: assert(!"unimplemented"); |
|
@ -2670,7 +2833,7 @@ oop typeCheck(oop exp, oop fntype) |
|
|
case SUB: assert(!"unimplemented"); break; |
|
|
case SUB: assert(!"unimplemented"); break; |
|
|
case SHL: assert(!"unimplemented"); break; |
|
|
case SHL: assert(!"unimplemented"); break; |
|
|
case SHR: assert(!"unimplemented"); break; |
|
|
case SHR: assert(!"unimplemented"); break; |
|
|
case LT: assert(!"unimplemented"); break; |
|
|
|
|
|
|
|
|
case LT: return t_int; |
|
|
case LE: assert(!"unimplemented"); break; |
|
|
case LE: assert(!"unimplemented"); break; |
|
|
case GE: assert(!"unimplemented"); break; |
|
|
case GE: assert(!"unimplemented"); break; |
|
|
case GT: assert(!"unimplemented"); break; |
|
|
case GT: assert(!"unimplemented"); break; |
|
@ -2691,6 +2854,18 @@ oop typeCheck(oop exp, oop fntype) |
|
|
fatal("incompatible types assigning '%s' to '%s'", toString(rhs), toString(lhs)); |
|
|
fatal("incompatible types assigning '%s' to '%s'", toString(rhs), toString(lhs)); |
|
|
return lhs; |
|
|
return lhs; |
|
|
} |
|
|
} |
|
|
|
|
|
case For: { |
|
|
|
|
|
oop init = get(exp, For,initialiser); |
|
|
|
|
|
oop cond = get(exp, For,condition); |
|
|
|
|
|
oop step = get(exp, For,update); |
|
|
|
|
|
oop body = get(exp, For,body); |
|
|
|
|
|
typeCheck(init, fntype); |
|
|
|
|
|
cond = typeCheck(cond, fntype); |
|
|
|
|
|
if (t_int != cond) fatal("for condition is not 'int'"); |
|
|
|
|
|
typeCheck(step, fntype); |
|
|
|
|
|
typeCheck(body, fntype); |
|
|
|
|
|
return nil; |
|
|
|
|
|
} |
|
|
case Primitive: { |
|
|
case Primitive: { |
|
|
return get(exp, Primitive,type); |
|
|
return get(exp, Primitive,type); |
|
|
} |
|
|
} |
|
@ -2866,14 +3041,15 @@ void replPath(char *path) |
|
|
|
|
|
|
|
|
int main(int argc, char **argv) |
|
|
int main(int argc, char **argv) |
|
|
{ |
|
|
{ |
|
|
true = newSymbol("true"); |
|
|
|
|
|
|
|
|
false = newInteger(0); |
|
|
|
|
|
true = newInteger(1); |
|
|
s_etc = newSymbol("..."); |
|
|
s_etc = newSymbol("..."); |
|
|
|
|
|
|
|
|
t_etc = newTbase("...", 0); |
|
|
|
|
|
t_void = newTbase("void", 1); |
|
|
|
|
|
t_char = newTbase("char", 1); |
|
|
|
|
|
t_int = newTbase("int", 4); |
|
|
|
|
|
t_float = newTbase("float", 4); |
|
|
|
|
|
|
|
|
t_etc = newTbase("...", 0, T_ETC); |
|
|
|
|
|
t_void = newTbase("void", 1, T_VOID); |
|
|
|
|
|
t_char = newTbase("char", 1, T_INT); |
|
|
|
|
|
t_int = newTbase("int", 4, T_INT); |
|
|
|
|
|
t_float = newTbase("float", 4, T_FLOAT); |
|
|
t_string = newTpointer(t_char); |
|
|
t_string = newTpointer(t_char); |
|
|
|
|
|
|
|
|
scopes = newArray(); |
|
|
scopes = newArray(); |
|
|