|
@ -1,6 +1,6 @@ |
|
|
# main.leg -- C parser + interpreter |
|
|
# main.leg -- C parser + interpreter |
|
|
# |
|
|
# |
|
|
# Last edited: 2025-02-04 09:10:32 by piumarta on xubuntu |
|
|
|
|
|
|
|
|
# Last edited: 2025-02-05 12:43:42 by piumarta on m1mbp |
|
|
|
|
|
|
|
|
%{ |
|
|
%{ |
|
|
; |
|
|
; |
|
@ -1832,12 +1832,12 @@ ddector = ( LPAREN d:decltor RPAREN |
|
|
)* { $$ = d } |
|
|
)* { $$ = d } |
|
|
|
|
|
|
|
|
params = LPAREN a:mkList |
|
|
params = LPAREN a:mkList |
|
|
( p:pdecl { List_append(a, p) } |
|
|
|
|
|
( COMMA p:pdecl { List_append(a, p) } |
|
|
|
|
|
)* )? ( ( COMMA ETC { List_append(a, t_etc) } |
|
|
|
|
|
)? RPAREN { $$ = a } |
|
|
|
|
|
| e:error { expected(e, "parameter declaration") } |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
( p:pdecl { List_append(a, p) } |
|
|
|
|
|
( COMMA p:pdecl { List_append(a, p) } |
|
|
|
|
|
)* )? ( ( COMMA ETC { List_append(a, t_etc) } |
|
|
|
|
|
)? RPAREN { $$ = a } |
|
|
|
|
|
| e:error { expected(e, "parameter declaration") } |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
pdecl = t:tname d:decltor { $$ = newVariable(d, t, nil) } |
|
|
pdecl = t:tname d:decltor { $$ = newVariable(d, t, nil) } |
|
|
|
|
|
|
|
@ -2699,7 +2699,22 @@ oop typeCheck(oop exp, oop fntype) |
|
|
toString(lhs), toString(rhs)); |
|
|
toString(lhs), toString(rhs)); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case SUB: assert(!"unimplemented"); break; |
|
|
|
|
|
|
|
|
case SUB: { |
|
|
|
|
|
if (lhs == rhs) { |
|
|
|
|
|
if (t_int == lhs) return lhs; |
|
|
|
|
|
if (t_float == lhs) return lhs; |
|
|
|
|
|
} |
|
|
|
|
|
if (is(Tpointer, lhs) && t_int == rhs) { |
|
|
|
|
|
return lhs; |
|
|
|
|
|
} |
|
|
|
|
|
if (is(Tpointer, lhs) && is(Tpointer, rhs)) { |
|
|
|
|
|
return t_long; |
|
|
|
|
|
} |
|
|
|
|
|
fatal("%scannot subtract '%s' and '%s'", |
|
|
|
|
|
tokloc(get(exp, Binary,token)), |
|
|
|
|
|
toString(lhs), toString(rhs)); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
case SHL: assert(!"unimplemented"); break; |
|
|
case SHL: assert(!"unimplemented"); break; |
|
|
case SHR: assert(!"unimplemented"); break; |
|
|
case SHR: assert(!"unimplemented"); break; |
|
|
case LT: return t_int; |
|
|
case LT: return t_int; |
|
@ -2723,7 +2738,7 @@ oop typeCheck(oop exp, oop fntype) |
|
|
fatal("%sarray index is not 'int': %s", |
|
|
fatal("%sarray index is not 'int': %s", |
|
|
tokloc(get(exp, Index,token)), toString(get(exp, Index,rhs))); |
|
|
tokloc(get(exp, Index,token)), toString(get(exp, Index,rhs))); |
|
|
switch (getType(lhs)) { |
|
|
switch (getType(lhs)) { |
|
|
case Tpointer: assert(!"unimplemented"); |
|
|
|
|
|
|
|
|
case Tpointer: return get(lhs, Tpointer,target); |
|
|
case Tarray: return get(lhs, Tarray,target); |
|
|
case Tarray: return get(lhs, Tarray,target); |
|
|
default: fatal("'%s' is not indexable: %s", toString(lhs), toString(exp)); |
|
|
default: fatal("'%s' is not indexable: %s", toString(lhs), toString(exp)); |
|
|
} |
|
|
} |
|
@ -3123,30 +3138,6 @@ oop getPointer(oop ptr) |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
oop getArray(oop array, int index) |
|
|
|
|
|
{ |
|
|
|
|
|
int size = get(array, Array,size); |
|
|
|
|
|
if (index < 0) fatal("array index is negative"); |
|
|
|
|
|
if (index >= size) fatal("array index out of bounds"); |
|
|
|
|
|
oop base = get(array, Array,base); |
|
|
|
|
|
oop type = get(get(array, Array,type), Tarray,target); |
|
|
|
|
|
int scale = typeSize(type); |
|
|
|
|
|
assert(is(Memory, base)); |
|
|
|
|
|
void *addr = get(base, Memory,base) + index * scale; |
|
|
|
|
|
assert(addr < get(base, Memory,base) + get(base, Memory,size)); |
|
|
|
|
|
switch (getType(type)) { |
|
|
|
|
|
case Tchar: return newInteger(*(char *)addr); |
|
|
|
|
|
case Tshort: return newInteger(*(short *)addr); |
|
|
|
|
|
case Tint: return newInteger(*(int *)addr); |
|
|
|
|
|
case Tlong: return newInteger(*(long *)addr); |
|
|
|
|
|
case Tfloat: return newFloat (*(float *)addr); |
|
|
|
|
|
case Tdouble: return newFloat (*(double *)addr); |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
|
|
|
fatal("cannot load '%s' from array", getTypeName(type)); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop getMemory(oop memory, int offset, oop type) |
|
|
oop getMemory(oop memory, int offset, oop type) |
|
|
{ |
|
|
{ |
|
|
int memsize = get(memory, Memory,size); |
|
|
int memsize = get(memory, Memory,size); |
|
@ -3166,6 +3157,7 @@ oop getMemory(oop memory, int offset, oop type) |
|
|
oop target = get(type, Tpointer,target); |
|
|
oop target = get(type, Tpointer,target); |
|
|
switch (getType(target)) { |
|
|
switch (getType(target)) { |
|
|
case Tstruct: return newPointer(type, newMemory(value, typeSize(target)), 0); |
|
|
case Tstruct: return newPointer(type, newMemory(value, typeSize(target)), 0); |
|
|
|
|
|
case Tchar: return newPointer(t_pchar, newMemory(value, strlen(value)+1), 0); |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
|
fatal("cannot load pointer to '%s' from memory", getTypeName(target)); |
|
|
fatal("cannot load pointer to '%s' from memory", getTypeName(target)); |
|
@ -3220,7 +3212,7 @@ oop setMemory(oop memory, int offset, oop type, oop value) |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
oop setArray(oop array, int index, oop value) |
|
|
|
|
|
|
|
|
oop getArray(oop array, int index) |
|
|
{ |
|
|
{ |
|
|
int size = get(array, Array,size); |
|
|
int size = get(array, Array,size); |
|
|
if (index < 0) fatal("array index is negative"); |
|
|
if (index < 0) fatal("array index is negative"); |
|
@ -3231,6 +3223,36 @@ oop setArray(oop array, int index, oop value) |
|
|
assert(is(Memory, base)); |
|
|
assert(is(Memory, base)); |
|
|
void *addr = get(base, Memory,base) + index * scale; |
|
|
void *addr = get(base, Memory,base) + index * scale; |
|
|
assert(addr < get(base, Memory,base) + get(base, Memory,size)); |
|
|
assert(addr < get(base, Memory,base) + get(base, Memory,size)); |
|
|
|
|
|
switch (getType(type)) { |
|
|
|
|
|
case Tchar: return newInteger(*(char *)addr); |
|
|
|
|
|
case Tshort: return newInteger(*(short *)addr); |
|
|
|
|
|
case Tint: return newInteger(*(int *)addr); |
|
|
|
|
|
case Tlong: return newInteger(*(long *)addr); |
|
|
|
|
|
case Tfloat: return newFloat (*(float *)addr); |
|
|
|
|
|
case Tdouble: return newFloat (*(double *)addr); |
|
|
|
|
|
case Tpointer: return getMemory(base, scale * index, type); |
|
|
|
|
|
default: break; |
|
|
|
|
|
} |
|
|
|
|
|
fatal("cannot load '%s' from array", getTypeName(type)); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop setArray(oop array, int index, oop value) |
|
|
|
|
|
{ |
|
|
|
|
|
int size = get(array, Array,size); |
|
|
|
|
|
if (index < 0) fatal("array index is negative"); |
|
|
|
|
|
if (index >= size) fatal("array index out of bounds"); |
|
|
|
|
|
oop base = get(array, Array,base); |
|
|
|
|
|
oop type = get(array, Array,type); |
|
|
|
|
|
switch (getType(type)) { |
|
|
|
|
|
case Tarray: type = get(type, Tarray,target); break; |
|
|
|
|
|
case Tpointer: type = get(type, Tpointer,target); break; |
|
|
|
|
|
default: assert(0); |
|
|
|
|
|
} |
|
|
|
|
|
int scale = typeSize(type); |
|
|
|
|
|
assert(is(Memory, base)); |
|
|
|
|
|
void *addr = get(base, Memory,base) + index * scale; |
|
|
|
|
|
assert(addr < get(base, Memory,base) + get(base, Memory,size)); |
|
|
switch (getType(type)) { |
|
|
switch (getType(type)) { |
|
|
case Tchar: return newInteger(*(char *)addr = _integerValue(value)); |
|
|
case Tchar: return newInteger(*(char *)addr = _integerValue(value)); |
|
|
case Tshort: return newInteger(*(short *)addr = _integerValue(value)); |
|
|
case Tshort: return newInteger(*(short *)addr = _integerValue(value)); |
|
@ -3238,6 +3260,10 @@ oop setArray(oop array, int index, 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: { |
|
|
|
|
|
setMemory(base, scale * index, type, value); |
|
|
|
|
|
return value; |
|
|
|
|
|
} |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
|
fatal("cannot store '%s' into array", getTypeName(type)); |
|
|
fatal("cannot store '%s' into array", getTypeName(type)); |
|
@ -3806,7 +3832,8 @@ 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)); |
|
|
|
|
|
case Pointer: assert(0); |
|
|
default: break; |
|
|
default: break; |
|
|
} |
|
|
} |
|
|
println(lhs); |
|
|
println(lhs); |
|
@ -4710,35 +4737,52 @@ int main(int argc, char **argv) |
|
|
|
|
|
|
|
|
Scope_begin(); // the global scope |
|
|
Scope_begin(); // the global scope |
|
|
|
|
|
|
|
|
int repls = 0; |
|
|
|
|
|
|
|
|
|
|
|
for (int argn = 1; argn < argc;) { |
|
|
|
|
|
char *arg = argv[argn++]; |
|
|
|
|
|
if (*arg != '-') { |
|
|
|
|
|
replPath(arg); |
|
|
|
|
|
++repls; |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
while (*++arg) { |
|
|
|
|
|
switch (*arg) { |
|
|
|
|
|
case 'O': ++opt_O; continue; |
|
|
|
|
|
case 'v': ++opt_v; continue; |
|
|
|
|
|
case 'x': ++opt_x; continue; |
|
|
|
|
|
default: fatal("uknown option '%c'", *arg); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
int argn = 1; |
|
|
|
|
|
|
|
|
|
|
|
while (argn < argc) { |
|
|
|
|
|
char *arg = argv[argn]; |
|
|
|
|
|
if (*arg != '-') break; |
|
|
|
|
|
++argn; |
|
|
|
|
|
while (*++arg) { |
|
|
|
|
|
switch (*arg) { |
|
|
|
|
|
case 'O': ++opt_O; continue; |
|
|
|
|
|
case 'v': ++opt_v; continue; |
|
|
|
|
|
case 'x': ++opt_x; continue; |
|
|
|
|
|
default: fatal("uknown option '%c'", *arg); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (!repls) replFile("stdin", stdin); |
|
|
|
|
|
|
|
|
oop args = newList(); |
|
|
|
|
|
if (argn == argc) fatal("no program file specified"); |
|
|
|
|
|
|
|
|
|
|
|
char *program = argv[argn++]; |
|
|
|
|
|
replPath(program); |
|
|
|
|
|
List_append(args, newStringWith(program)); |
|
|
|
|
|
|
|
|
|
|
|
while (argn < argc) |
|
|
|
|
|
List_append(args, newStringWith(argv[argn++])); |
|
|
|
|
|
|
|
|
|
|
|
int cargs = List_size(args); |
|
|
|
|
|
int vsize = sizeof(char *) * cargs; |
|
|
|
|
|
oop vargs = newArray(newTarray(t_pchar, newInteger(cargs)), |
|
|
|
|
|
newMemory(malloc(vsize), vsize), |
|
|
|
|
|
cargs); |
|
|
|
|
|
List_do(args, arg) { |
|
|
|
|
|
char *elts = String_cString(arg); |
|
|
|
|
|
oop mem = newMemory(elts, get(arg, String,size)); |
|
|
|
|
|
setArray(vargs, do_index, newPointer(t_pchar, mem, 0)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
oop args = newList(); |
|
|
|
|
|
List_append(args, newInteger(1)); |
|
|
|
|
|
List_append(args, newStringWith("main")); |
|
|
|
|
|
|
|
|
args = newList(); |
|
|
|
|
|
List_append(args, newInteger(cargs)); |
|
|
|
|
|
List_append(args, vargs); |
|
|
|
|
|
List_append(args, newPointer(t_ppchar, newMemory(0, 0), 0)); |
|
|
|
|
|
|
|
|
oop entry = Scope_lookup(intern("main")); |
|
|
oop entry = Scope_lookup(intern("main")); |
|
|
if (!entry || isNil(entry)) fatal("main is not defined"); |
|
|
if (!entry || isNil(entry)) fatal("main is not defined"); |
|
|
if (!is(Function, entry)) fatal("main is not a function"); |
|
|
if (!is(Function, entry)) fatal("main is not a function"); |
|
|
|
|
|
|
|
|
oop params = get(get(entry, Function,type), Tfunction, parameters); |
|
|
oop params = get(get(entry, Function,type), Tfunction, parameters); |
|
|
switch (List_size(params)) { |
|
|
switch (List_size(params)) { |
|
|
default: |
|
|
default: |
|
|