Parcourir la source

handle variadic functions

master
Ian Piumarta il y a 3 mois
Parent
révision
05f17a9383
2 fichiers modifiés avec 44 ajouts et 21 suppressions
  1. +41
    -16
      main.leg
  2. +3
    -5
      test.txt

+ 41
- 16
main.leg Voir le fichier

@ -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;

+ 3
- 5
test.txt Voir le fichier

@ -2,14 +2,12 @@
#include <stdio.h>
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;
}

Chargement…
Annuler
Enregistrer