|
@ -1,6 +1,6 @@ |
|
|
# main.leg -- C parser + interpreter |
|
|
# main.leg -- C parser + interpreter |
|
|
# |
|
|
# |
|
|
# Last edited: 2025-01-22 11:03:33 by piumarta on zora |
|
|
|
|
|
|
|
|
# Last edited: 2025-01-22 11:44:37 by piumarta on zora |
|
|
|
|
|
|
|
|
%{ |
|
|
%{ |
|
|
; |
|
|
; |
|
@ -114,7 +114,7 @@ struct Scope { type_t _type; oop names, types, values; }; |
|
|
struct TypeName { type_t _type; oop name, type; }; |
|
|
struct TypeName { type_t _type; oop name, type; }; |
|
|
struct Variable { type_t _type; oop name, type, value; }; |
|
|
struct Variable { type_t _type; oop name, type, value; }; |
|
|
struct Constant { type_t _type; oop name, type, value; }; |
|
|
struct Constant { type_t _type; oop name, type, value; }; |
|
|
struct Function { type_t _type; oop name, type, parameters, body, *code; }; |
|
|
|
|
|
|
|
|
struct Function { type_t _type; oop name, type, parameters, body, *code; int variadic; }; |
|
|
struct Primitive { type_t _type; oop name, type; prim_t function; }; |
|
|
struct Primitive { type_t _type; oop name, type; prim_t function; }; |
|
|
struct VarDecls { type_t _type; oop type, declarations, variables; }; |
|
|
struct VarDecls { type_t _type; oop type, declarations, variables; }; |
|
|
|
|
|
|
|
@ -589,6 +589,8 @@ oop newTbase(char *name, int size) |
|
|
return obj; |
|
|
return obj; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop s_etc = 0; |
|
|
|
|
|
oop t_etc = 0; |
|
|
oop t_void = 0; |
|
|
oop t_void = 0; |
|
|
oop t_char = 0; |
|
|
oop t_char = 0; |
|
|
oop t_int = 0; |
|
|
oop t_int = 0; |
|
@ -723,6 +725,7 @@ oop newFunction(oop name, oop type, oop parameters, oop body) |
|
|
obj->Function.parameters = parameters; |
|
|
obj->Function.parameters = parameters; |
|
|
obj->Function.body = body; |
|
|
obj->Function.body = body; |
|
|
obj->Function.code = 0; |
|
|
obj->Function.code = 0; |
|
|
|
|
|
obj->Function.variadic = 0; |
|
|
return obj; |
|
|
return obj; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -817,6 +820,7 @@ oop baseType(oop type) |
|
|
case Tbase: return type; |
|
|
case Tbase: return 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)); |
|
|
default: |
|
|
default: |
|
|
fatal("cannot find base type of %s", getTypeName(type)); |
|
|
fatal("cannot find base type of %s", getTypeName(type)); |
|
|
} |
|
|
} |
|
@ -904,10 +908,8 @@ oop toStringOn(oop obj, oop str) |
|
|
oop type = get(obj, Variable,type); |
|
|
oop type = get(obj, Variable,type); |
|
|
oop name = get(obj, Variable,name); |
|
|
oop name = get(obj, Variable,name); |
|
|
toStringOn(baseType(type), str); |
|
|
toStringOn(baseType(type), str); |
|
|
if (t_void != type) { |
|
|
|
|
|
String_append(str, ' '); |
|
|
|
|
|
declareStringOn(type, name, str); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
String_append(str, ' '); |
|
|
|
|
|
declareStringOn(type, name, str); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Function: { |
|
|
case Function: { |
|
@ -1142,7 +1144,7 @@ void printiln(oop obj, int indent) |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case Variable: { |
|
|
case Variable: { |
|
|
printf("Variable\n"); |
|
|
|
|
|
|
|
|
printf("Variable %s\n", toString(obj)); |
|
|
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); |
|
@ -1286,7 +1288,8 @@ ddector = ( LPAREN d:decltor RPAREN |
|
|
params = LPAREN a:mkArray |
|
|
params = LPAREN a:mkArray |
|
|
( p:pdecl { Array_append(a, p) } |
|
|
( p:pdecl { Array_append(a, p) } |
|
|
( COMMA p:pdecl { Array_append(a, p) } |
|
|
( COMMA p:pdecl { Array_append(a, p) } |
|
|
)* )? ( RPAREN { $$ = a } |
|
|
|
|
|
|
|
|
)* )? ( ( COMMA ETC { Array_append(a, t_etc) } |
|
|
|
|
|
)? RPAREN { $$ = a } |
|
|
| e:error { expected(e, "parameter declaration") } |
|
|
| e:error { expected(e, "parameter declaration") } |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
@ -1459,7 +1462,6 @@ blank = [ \t\n\r] | comment |
|
|
comment = "//" < (![\n\r] .)* > |
|
|
comment = "//" < (![\n\r] .)* > |
|
|
| "/*" (!"*/" .)* "*/" |
|
|
| "/*" (!"*/" .)* "*/" |
|
|
|
|
|
|
|
|
HASH = "#" - |
|
|
|
|
|
INCLUDE = "include" ![_a-zA-Z0-9] - |
|
|
INCLUDE = "include" ![_a-zA-Z0-9] - |
|
|
VOID = "void" ![_a-zA-Z0-9] - |
|
|
VOID = "void" ![_a-zA-Z0-9] - |
|
|
CHAR = "char" ![_a-zA-Z0-9] - |
|
|
CHAR = "char" ![_a-zA-Z0-9] - |
|
@ -1474,6 +1476,8 @@ FOR = "for" ![_a-zA-Z0-9] - |
|
|
RETURN = "return" ![_a-zA-Z0-9] - |
|
|
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] - |
|
|
|
|
|
ETC = "..." - |
|
|
|
|
|
HASH = "#" - |
|
|
ASSIGN = "=" !"=" - |
|
|
ASSIGN = "=" !"=" - |
|
|
PLUS = "+" !"+" - |
|
|
PLUS = "+" !"+" - |
|
|
PPLUS = "++" - |
|
|
PPLUS = "++" - |
|
@ -1573,10 +1577,18 @@ oop apply(oop function, oop arguments, oop env) |
|
|
oop *parv = get(parameters, Array,elements); |
|
|
oop *parv = get(parameters, Array,elements); |
|
|
oop *argv = get(arguments, Array,elements); |
|
|
oop *argv = get(arguments, Array,elements); |
|
|
Scope_begin(); |
|
|
Scope_begin(); |
|
|
for (int i = 0; i < argc; ++i) { |
|
|
|
|
|
oop var = parv[i]; |
|
|
|
|
|
oop arg = argv[i]; |
|
|
|
|
|
|
|
|
if (get(function, Function,variadic)) --parc; |
|
|
|
|
|
int argn = 0; |
|
|
|
|
|
while (argn < parc) { |
|
|
|
|
|
oop var = parv[argn]; |
|
|
|
|
|
oop arg = argv[argn]; |
|
|
defineVariable(get(var, Variable,name), get(var, Variable,type), eval(arg, nil)); |
|
|
defineVariable(get(var, Variable,name), get(var, Variable,type), eval(arg, nil)); |
|
|
|
|
|
++argn; |
|
|
|
|
|
} |
|
|
|
|
|
if (argn < argc) { // put varargs array in local variable called "..." |
|
|
|
|
|
oop etc = newArray(); |
|
|
|
|
|
while (argn < argc) Array_append(etc, eval(argv[argn++], nil)); |
|
|
|
|
|
defineVariable(s_etc, t_etc, etc); |
|
|
} |
|
|
} |
|
|
switch (nlrPush()) { // longjmp occurred |
|
|
switch (nlrPush()) { // longjmp occurred |
|
|
case NLR_INIT: break; |
|
|
case NLR_INIT: break; |
|
@ -1891,7 +1903,7 @@ oop prim_printf(int argc, oop *argv, oop env) // array |
|
|
switch (c) { |
|
|
switch (c) { |
|
|
case 'd': { |
|
|
case 'd': { |
|
|
if (argn >= argc) |
|
|
if (argn >= argc) |
|
|
fatal("not enough argments for printf format string"); |
|
|
|
|
|
|
|
|
fatal("too few arguments for printf format string"); |
|
|
arg = argv[argn++]; |
|
|
arg = argv[argn++]; |
|
|
if (!is(Integer, arg)) |
|
|
if (!is(Integer, arg)) |
|
|
fatal("%%d conversion argument is %s", getTypeName(arg)); |
|
|
fatal("%%d conversion argument is %s", getTypeName(arg)); |
|
@ -1904,6 +1916,7 @@ oop prim_printf(int argc, oop *argv, oop env) // array |
|
|
putchar(c); |
|
|
putchar(c); |
|
|
++n; |
|
|
++n; |
|
|
} |
|
|
} |
|
|
|
|
|
if (argn != argc) fatal("too many arguments for printf format string"); |
|
|
return newInteger(n); |
|
|
return newInteger(n); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -2400,6 +2413,11 @@ oop typeCheck(oop exp, oop fntype) |
|
|
oop type = get(var, Variable,type); |
|
|
oop type = get(var, Variable,type); |
|
|
if (t_void == type && (do_index || do_size > 1)) |
|
|
if (t_void == type && (do_index || do_size > 1)) |
|
|
fatal("illegal void parameter"); |
|
|
fatal("illegal void parameter"); |
|
|
|
|
|
else if (t_etc == type) { |
|
|
|
|
|
if (do_index == 0 || do_index != do_size - 1) |
|
|
|
|
|
fatal("illegal varargs parameter"); |
|
|
|
|
|
set(exp, Function,variadic, 1); |
|
|
|
|
|
} |
|
|
Array_append(ptypes, type); |
|
|
Array_append(ptypes, type); |
|
|
} |
|
|
} |
|
|
if (1 == Array_size(ptypes) && Array_last(ptypes) == t_void) { |
|
|
if (1 == Array_size(ptypes) && Array_last(ptypes) == t_void) { |
|
@ -2433,9 +2451,12 @@ oop typeCheck(oop exp, oop fntype) |
|
|
oop *argv = get(arguments, Array,elements); |
|
|
oop *argv = get(arguments, Array,elements); |
|
|
int parc = get(params, Array,size); |
|
|
int parc = get(params, Array,size); |
|
|
oop *parv = get(params, Array,elements); |
|
|
oop *parv = get(params, Array,elements); |
|
|
if (argc != parc) fatal("wrong number (%d) of arguments, expected %d", argc, parc); |
|
|
|
|
|
|
|
|
int vararg = parc && t_etc == parv[parc - 1]; |
|
|
|
|
|
if ((vararg && (argc < parc)) || (!vararg && (argc != parc))) |
|
|
|
|
|
fatal("wrong number (%d %d) of arguments, expected %d", vararg, argc, parc); |
|
|
for (int i = 0; i < argc; ++i) { |
|
|
for (int i = 0; i < argc; ++i) { |
|
|
oop part = parv[i]; |
|
|
oop part = parv[i]; |
|
|
|
|
|
if (part == t_etc) break; |
|
|
oop arg = argv[i]; |
|
|
oop arg = argv[i]; |
|
|
oop argt = typeCheck(arg, fntype); |
|
|
oop argt = typeCheck(arg, fntype); |
|
|
if (argt != part) |
|
|
if (argt != part) |
|
@ -2531,7 +2552,9 @@ void replFile(char *name, FILE *file) |
|
|
case NLR_CONTINUE: fatal("continue outside loop"); |
|
|
case NLR_CONTINUE: fatal("continue outside loop"); |
|
|
case NLR_BREAK: fatal("break outside loop"); |
|
|
case NLR_BREAK: fatal("break outside loop"); |
|
|
} |
|
|
} |
|
|
|
|
|
if (opt_v > 1) printf("---------------- typecheck\n"); |
|
|
typeCheck(yysval, nil); |
|
|
typeCheck(yysval, nil); |
|
|
|
|
|
if (opt_v > 1) printf("---------------- eval\n"); |
|
|
result = eval(yysval, nil); |
|
|
result = eval(yysval, nil); |
|
|
nlrPop(); |
|
|
nlrPop(); |
|
|
} |
|
|
} |
|
@ -2552,8 +2575,10 @@ void replPath(char *path) |
|
|
|
|
|
|
|
|
int main(int argc, char **argv) |
|
|
int main(int argc, char **argv) |
|
|
{ |
|
|
{ |
|
|
true = newSymbol("true"); |
|
|
|
|
|
|
|
|
true = newSymbol("true"); |
|
|
|
|
|
s_etc = newSymbol("..."); |
|
|
|
|
|
|
|
|
|
|
|
t_etc = newTbase("...", 0); |
|
|
t_void = newTbase("void", 1); |
|
|
t_void = newTbase("void", 1); |
|
|
t_char = newTbase("char", 1); |
|
|
t_char = newTbase("char", 1); |
|
|
t_int = newTbase("int", 4); |
|
|
t_int = newTbase("int", 4); |
|
@ -2565,7 +2590,7 @@ int main(int argc, char **argv) |
|
|
Scope_begin(); // the global scope |
|
|
Scope_begin(); // the global scope |
|
|
|
|
|
|
|
|
definePrimitive(intern("printf"), |
|
|
definePrimitive(intern("printf"), |
|
|
newTfunction(t_int, newArray2(t_string, t_int)), |
|
|
|
|
|
|
|
|
newTfunction(t_int, newArray2(t_string, t_etc)), |
|
|
prim_printf); |
|
|
prim_printf); |
|
|
|
|
|
|
|
|
int repls = 0; |
|
|
int repls = 0; |
|
|