diff --git a/main.leg b/main.leg index 58fd890..eab4905 100644 --- a/main.leg +++ b/main.leg @@ -1,6 +1,6 @@ # 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 Variable { 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 VarDecls { type_t _type; oop type, declarations, variables; }; @@ -589,6 +589,8 @@ oop newTbase(char *name, int size) return obj; } +oop s_etc = 0; +oop t_etc = 0; oop t_void = 0; oop t_char = 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.body = body; obj->Function.code = 0; + obj->Function.variadic = 0; return obj; } @@ -817,6 +820,7 @@ oop baseType(oop type) case Tbase: return type; case Tpointer: return baseType(get(type, Tpointer,target)); case Tarray: return baseType(get(type, Tarray,target)); + case Tfunction: return baseType(get(type, Tfunction,result)); default: 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 name = get(obj, Variable,name); toStringOn(baseType(type), str); - if (t_void != type) { - String_append(str, ' '); - declareStringOn(type, name, str); - } + String_append(str, ' '); + declareStringOn(type, name, str); break; } case Function: { @@ -1142,7 +1144,7 @@ void printiln(oop obj, int indent) break; } case Variable: { - printf("Variable\n"); + printf("Variable %s\n", toString(obj)); printiln(get(obj, Variable,name ), indent+1); printiln(get(obj, Variable,type ), indent+1); printiln(get(obj, Variable,value), indent+1); @@ -1286,7 +1288,8 @@ ddector = ( LPAREN d:decltor RPAREN params = LPAREN a:mkArray ( 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") } ) @@ -1459,7 +1462,6 @@ blank = [ \t\n\r] | comment comment = "//" < (![\n\r] .)* > | "/*" (!"*/" .)* "*/" -HASH = "#" - INCLUDE = "include" ![_a-zA-Z0-9] - VOID = "void" ![_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] - CONTINU = "continue" ![_a-zA-Z0-9] - BREAK = "break" ![_a-zA-Z0-9] - +ETC = "..." - +HASH = "#" - ASSIGN = "=" !"=" - PLUS = "+" !"+" - PPLUS = "++" - @@ -1573,10 +1577,18 @@ oop apply(oop function, oop arguments, oop env) oop *parv = get(parameters, Array,elements); oop *argv = get(arguments, Array,elements); 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)); + ++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 case NLR_INIT: break; @@ -1891,7 +1903,7 @@ oop prim_printf(int argc, oop *argv, oop env) // array switch (c) { case 'd': { if (argn >= argc) - fatal("not enough argments for printf format string"); + fatal("too few arguments for printf format string"); arg = argv[argn++]; if (!is(Integer, 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); ++n; } + if (argn != argc) fatal("too many arguments for printf format string"); return newInteger(n); } @@ -2400,6 +2413,11 @@ oop typeCheck(oop exp, oop fntype) oop type = get(var, Variable,type); if (t_void == type && (do_index || do_size > 1)) 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); } 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); int parc = get(params, Array,size); 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) { oop part = parv[i]; + if (part == t_etc) break; oop arg = argv[i]; oop argt = typeCheck(arg, fntype); if (argt != part) @@ -2531,7 +2552,9 @@ void replFile(char *name, FILE *file) case NLR_CONTINUE: fatal("continue outside loop"); case NLR_BREAK: fatal("break outside loop"); } + if (opt_v > 1) printf("---------------- typecheck\n"); typeCheck(yysval, nil); + if (opt_v > 1) printf("---------------- eval\n"); result = eval(yysval, nil); nlrPop(); } @@ -2552,8 +2575,10 @@ void replPath(char *path) 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_char = newTbase("char", 1); t_int = newTbase("int", 4); @@ -2565,7 +2590,7 @@ int main(int argc, char **argv) Scope_begin(); // the global scope definePrimitive(intern("printf"), - newTfunction(t_int, newArray2(t_string, t_int)), + newTfunction(t_int, newArray2(t_string, t_etc)), prim_printf); int repls = 0; diff --git a/test.txt b/test.txt index 7efecae..2e4e805 100755 --- a/test.txt +++ b/test.txt @@ -2,14 +2,12 @@ #include -int foo(void) -{ - return 42; -} +int foo(void) { return 42; } +int bar(void) { return 99; } int main(int argc, char **argv) { - printf("hello, world %d\n", foo()); + printf("hello, world %d %d\n", foo(), bar()); return 0; }