diff --git a/demofiles/pointer-compare.c b/demofiles/pointer-compare.c index 2359b20..4ad2e0c 100644 --- a/demofiles/pointer-compare.c +++ b/demofiles/pointer-compare.c @@ -2,14 +2,17 @@ #include #include +#include int main() { - int array[5] = {0, 1, 2, 3, 4}; - int brray[5] = {0, 1, 2, 3, 4}; - int *p = array + 2; - int *q = array + 4; - int *r = brray + 4; - if (p > q) abort(); printf("compare OK\n"); - if (p < r) abort(); printf("compare OK\n"); // illegal comparison - return 0; + int array[5] = {0, 1, 2, 3, 4}; + int brray[5] = {0, 1, 2, 3, 4}; + int *p = array + 2; + int *q = array + 4; + int *r = brray + 4; + if (p > q) printf("compare KO\n"); else printf("compare OK\n"); + // illegal comparison + if (p < r) printf("compare KO\n"); else printf("compare KO\n"); + assert(!"this should not be reached"); + return 0; } diff --git a/main.leg b/main.leg index 4e7303c..dfd8522 100644 --- a/main.leg +++ b/main.leg @@ -1,6 +1,6 @@ # main.leg -- C parser + interpreter # -# Last edited: 2025-02-01 15:04:48 by piumarta on xubuntu +# Last edited: 2025-02-03 10:47:46 by piumarta on xubuntu %{ ; @@ -60,16 +60,17 @@ typedef union Object Object, *oop; #define YYSTYPE oop -#define _do_types(_) \ - _(Undefined) _(Input) _(Integer) _(Float) _(Array) _(Symbol) _(Pair) _(String) _(List) \ - _(Pointer) _(Struct) \ - _(Memory) _(Reference) _(Closure) _(Call) _(Block) \ - _(Addressof) _(Dereference) _(Sizeof) _(Unary) \ - _(Binary) _(Index) _(Member) _(Assign) _(Cast) \ - _(While) _(For) _(If) _(Return) _(Continue) _(Break) \ - _(Tvoid) _(Tchar) _(Tshort) _(Tint) _(Tlong) _(Tfloat) _(Tdouble) \ - _(Tpointer) _(Tarray) _(Tstruct) _(Tfunction) _(Tetc) \ - _(Scope) _(TypeName) _(Variable) _(Constant) _(Function) _(Primitive) \ +#define _do_types(_) \ + _(Undefined) _(Input) _(Token )_(Integer) _(Float) _(Array) _(Symbol) _(Pair) \ + _(String) _(List) \ + _(Pointer) _(Struct) \ + _(Memory) _(Reference) _(Closure) _(Call) _(Block) \ + _(Addressof) _(Dereference) _(Sizeof) _(Unary) \ + _(Binary) _(Index) _(Member) _(Assign) _(Cast) \ + _(While) _(For) _(If) _(Return) _(Continue) _(Break) \ + _(Tvoid) _(Tchar) _(Tshort) _(Tint) _(Tlong) _(Tfloat) _(Tdouble) \ + _(Tpointer) _(Tarray) _(Tstruct) _(Tfunction) _(Tetc) \ + _(Scope) _(TypeName) _(Variable) _(Constant) _(Function) _(Primitive) \ _(VarDecls) _(TypeDecls) #define _do_unaries(_) \ @@ -116,7 +117,8 @@ typedef oop (* prim_t)(int nargs, oop *arguments, oop environment); typedef oop (*cvt_t)(oop input); struct Undefined { type_t _type; }; -struct Input { type_t _type; char *name; FILE *file; oop next; }; +struct Input { type_t _type; char *name; int line; FILE *file; oop next; }; +struct Token { type_t _type; char *text; char *file; int line; }; struct Integer { type_t _type; long value; }; struct Float { type_t _type; double value; }; struct Pointer { type_t _type; oop type, base; int offset; }; @@ -138,7 +140,7 @@ struct Unary { type_t _type; unary_t operator; oop rhs; }; struct Binary { type_t _type; binary_t operator; oop lhs, rhs; }; struct Index { type_t _type; oop lhs, rhs; }; struct Member { type_t _type; oop lhs, name; }; -struct Assign { type_t _type; oop lhs, rhs; }; +struct Assign { type_t _type; oop token, lhs, rhs; }; struct Cast { type_t _type; oop type, rhs; cvt_t converter; }; struct While { type_t _type; oop condition, expression; }; struct For { type_t _type; oop initialiser, condition, update, body; }; @@ -669,7 +671,7 @@ oop newBinary(binary_t operator, oop lhs, oop rhs) CTOR2(Index, lhs, rhs); CTOR2(Member, lhs, name); -CTOR2(Assign, lhs, rhs); +CTOR3(Assign, token, lhs, rhs); oop newCast(oop type, oop rhs) { @@ -1063,6 +1065,10 @@ oop toStringOn(oop obj, oop str) case Undefined: String_appendAll(str, "", 5); break; + case Token: { + String_format(str, "%s:%d: ", get(obj, Token,file), get(obj, Token,line)); + break; + } case Integer: String_format(str, "%d", _integerValue(obj)); break; @@ -1346,6 +1352,12 @@ char *toString(oop obj) return get(str, String,elements); } +char *tokloc(oop token) +{ + if (Token == getType(token)) return toString(token); + return ""; +} + void printiln(oop obj, int indent) { printf("%*s", indent*2, ""); @@ -1636,19 +1648,23 @@ oop pushInput(char *name, FILE *file) { oop obj = new(Input); obj->Input.name = STRDUP(name); + obj->Input.line = 1; obj->Input.file = file; obj->Input.next = input; - return input = obj; + input = obj; + return input; } void popInput(void) { if (!input) return; + FILE *file = get(input, Input,file); oop obj = input; input = get(obj, Input,next); - FREE(get(obj, Input,name)); - fclose(get(obj, Input,file)); - FREE(obj); + if (file) { + fclose(file); + set(obj, Input,file, 0); + } } FILE *sysOpen(char *path) @@ -1669,13 +1685,13 @@ FILE *usrOpen(char *path) int getChar(char *buf) { - while (input) { + if (input && get(input, Input,file)) { int c = getc(get(input, Input,file)); if (c != EOF) { *buf = c; + if ('\n' == c) get(input, Input,line) += 1; return 1; } - popInput(); } return 0; } @@ -1684,31 +1700,68 @@ int getChar(char *buf) YYSTYPE yysval = 0; +int errorLine = 0; + void expected(oop where, char *what) { - fatal("%s expected near: %.*s", what, get(where, String,size), get(where, String,elements)); + fatal("%s:%d: %s expected near: %.*s", + get(input, Input,name), errorLine, + what, get(where, String,size), get(where, String,elements)); } oop eval(oop exp); oop preval(oop exp); +int lineNo = 1; + +oop newToken(char *text) +{ + oop obj = new(Token); + obj->Token.text = text; + assert(input); + obj->Token.file = get(input, Input,name); + obj->Token.line = lineNo; + return obj; +} + +oop names = 0; +oop lines = 0; + +void startInput(char *name) +{ + if (!names) names = newList(); + if (!lines) lines = newList(); + List_append(names, newStringWith(name)); + List_append(lines, newInteger(lineNo)); + lineNo = 1; +} + +void endInput(void) +{ + if (List_size(lines)) { + lineNo = _integerValue(List_popLast(lines)); + List_popLast(names); + } +} + %} -start = - ( interp { yysval = 0 } - | include { yysval = 0 } - | x:tldecl { yysval = x } - | !. { yysval = 0 } - | e:error { expected(e, "declaration") } +start = - ( interp { yysval = 0 } + | include { yysval = 0 } + | x:tldecl { yysval = x } + | !. @{ popInput() } { yysval = 0; endInput() } + | e:error { expected(e, "declaration") } ) -error = < (![\n\r] .)* > { $$ = newStringWith(yytext) } +error = @{ errorLine = get(input, Input,line) } + < (![\n\r] .)* > { $$ = newStringWith(yytext) } -interp = HASH PLING (![\n\r] .)* +interp = "#!" (!eol .)* eol include = HASH INCLUDE ( '<' < [a-zA-Z0-9_.]* > '>' @{ pushInput(yytext, sysOpen(yytext)) } | '"' < [a-zA-Z0-9_.]* > '"' @{ pushInput(yytext, usrOpen(yytext)) } - ) + ) { startInput(yytext) } tldecl = typedec | fundefn | primdef | vardecl @@ -1742,10 +1795,10 @@ members = LBRACE l:mkList ( v:vardecl { List_append(l, v) } | e:error { expected(e, "struct/union member specification") } ) { $$ = l } -inidecl = d:decltor ( ASSIGN ( e:initor { $$ = newAssign(d, e) } - | e:error { expected(e, "variable initialiser") } - ) - | { $$ = d } +inidecl = d:decltor ( a:ASSIGN ( e:initor { $$ = newAssign(a, d, e) } + | e:error { expected(e, "variable initialiser") } + ) + | { $$ = d } ) decltor = STAR d:decltor { $$ = newTpointer(d) } @@ -1813,7 +1866,7 @@ expropt = expr | { $$ = nil } expr = assign -assign = l:unary ASSIGN x:expr { $$ = newAssign(l, x) } +assign = l:unary a:ASSIGN x:expr { $$ = newAssign(a, l, x) } | logor logor = l:logand ( BARBAR r:logand { l = newBinary(LOR, l, r) } @@ -1943,9 +1996,11 @@ alpha = [a-zA-Z_] alnum = [a-zA-Z_0-9] - = blank* -blank = [ \t\n\r] | comment -comment = "//" < (![\n\r] .)* > - | "/*" (!"*/" .)* "*/" +blank = space | eol | comment +space = [ \t] +eol = ( '\n' '\r'? | '\r' '\n'? ) { lineNo += 1 } +comment = "//" (!eol .)* eol + | "/*" (!"*/" (eol | .))* "*/" INCLUDE = "include" ![_a-zA-Z0-9] - EXTERN = "extern" ![_a-zA-Z0-9] - @@ -1975,7 +2030,7 @@ DOT = "." !"." - ARROW = "->" - ETC = "..." - HASH = "#" - -ASSIGN = "=" !"=" - +ASSIGN = < "=" !"=" > { $$ = newToken(yytext) } - PLUS = "+" !"+" - PPLUS = "++" - MINUS = "-" !"-" - @@ -2240,6 +2295,7 @@ int toBoolean(oop arg) switch (getType(arg)) { case Integer: return !!_integerValue(arg); case Float: return !! integerValue(arg); + case String: return 1; case Reference: return 1; case Pointer: { oop base = get(arg, Pointer,base); @@ -2472,7 +2528,7 @@ oop prim_sqrtf(int argc, oop *argv, oop env) // array { if (argc != 1) fatal("sqrtf: wrong number of arguments"); oop arg = argv[0]; - if (!is(Float, arg)) fatal("sqrtf: argument is not an integer"); + if (!is(Float, arg)) fatal("sqrtf: argument is not a float"); return newFloat(sqrtf(_floatValue(arg))); } @@ -2843,10 +2899,12 @@ oop typeCheck(oop exp, oop fntype) oop decls = get(exp, VarDecls,variables); oop vars = newList(); List_do(decls, decl) { - oop init = nil; + oop init = nil; + oop assign = nil; if (is(Assign, decl)) { - init = get(decl, Assign,rhs); - decl = get(decl, Assign,lhs); + assign = get(decl, Assign,token); + init = get(decl, Assign,rhs); + decl = get(decl, Assign,lhs); } oop varname = makeName(decl); oop vartype = makeType(base, decl); @@ -2943,8 +3001,10 @@ oop typeCheck(oop exp, oop fntype) break; cvt_t cvt = converter(getType(initype), getType(vartype)); if (!cvt) { - fatal("initialising '%s': cannot convert '%s' to '%s'", - toString(varname), toString(initype), toString(vartype)); + fatal("%sinitialising '%s': cannot convert '%s' to '%s'", + tokloc(assign), + toString(varname), toString(initype), toString(vartype) + ); } break; } @@ -3561,8 +3621,6 @@ oop eval(oop exp) } default: break; } - println(lhs); - fatal("cannot take address"); break; } default: @@ -4486,7 +4544,7 @@ void compileOn(oop exp, oop program, oop cs, oop bs) return; } case Break: { - if (nil == bs) fatal("continue outside loop"); + if (nil == bs) fatal("break outside loop"); EMITio(iPUSH, nil); LABEL(L1); EMITio(iJMP, nil); @@ -4585,6 +4643,8 @@ void replPath(char *path) int main(int argc, char **argv) { + setbuf(stdout, 0); + false = newInteger(0); true = newInteger(1); s_etc = newSymbol("..."); diff --git a/test.txt b/test.txt index a5569dd..87594ee 100755 --- a/test.txt +++ b/test.txt @@ -1,10 +1,10 @@ #!./main #include +#include #include #include #include -#include int x = 21; @@ -142,6 +142,8 @@ int main(int argc, char **argv) printf("passed\n"); + float f = 42; + return 0; }