From f40c9063afb03f3fe0c43fec40c0de3f81a18329 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Thu, 22 Apr 2021 09:46:52 -0400 Subject: [PATCH] scaffolding is in place for assignment statements. Need to decipher level handling and generate the proper code for the assignments (and expressions) --- cerise/build.sh | 2 +- cerise/cerise.h | 2 + cerise/codegen.c | 5 ++ cerise/oberon0/OSG.Mod | 15 +++- cerise/parser.c | 163 ++++++++++++++++++++++++++++++----------- 5 files changed, 142 insertions(+), 45 deletions(-) diff --git a/cerise/build.sh b/cerise/build.sh index 6328d79..a6d65d1 100755 --- a/cerise/build.sh +++ b/cerise/build.sh @@ -2,6 +2,6 @@ ctags -R & cc -g -D CERISE_TESTS -Wall -Wextra --std=c99 -o cerisec-test *.c \ && ./cerisec-test \ - && cc -g -Wall -Wextra -Werror --std=c99 -o cerisec *.c \ + && cc -g -Wall -Wextra --std=c99 -o cerisec *.c \ && ./cerisec tests/Module.m #[ $? -gt 0 ] && printf "\a" diff --git a/cerise/cerise.h b/cerise/cerise.h index 84339aa..5b6a02d 100644 --- a/cerise/cerise.h +++ b/cerise/cerise.h @@ -134,7 +134,9 @@ extern Type BoolType, IntType, RealType, StringType; void codegen_setint(Item* item, Type* type, long long val); void codegen_setreal(Item* item, double val); void codegen_setstr(Item* item, char* val); + void codegen_unop(int op, Item* a); void codegen_binop(int op, Item* a, Item* b); void codegen_startproc(char* name, long long localsz); void codegen_endproc(void); +void codegen_store(Item* a, Item* b); diff --git a/cerise/codegen.c b/cerise/codegen.c index 8601913..5e2708f 100644 --- a/cerise/codegen.c +++ b/cerise/codegen.c @@ -225,3 +225,8 @@ void codegen_endproc(void) printf(" pop %%rbp\n"); printf(" ret\n"); } + +void codegen_store(Item* a, Item* b) +{ + (void)a, (void)b; +} diff --git a/cerise/oberon0/OSG.Mod b/cerise/oberon0/OSG.Mod index f54a5c1..29e8753 100644 --- a/cerise/oberon0/OSG.Mod +++ b/cerise/oberon0/OSG.Mod @@ -188,9 +188,18 @@ MODULE OSG; (* NW 19.12.94 / 20.10.07 / OSGX 9.5.2017*) PROCEDURE MakeItem*(VAR x: Item; y: Object; curlev: LONGINT); VAR r: LONGINT; - BEGIN x.mode := y.class; x.type := y.type; x.a := y.val; x.r := y.lev; - IF y.class = Par THEN x.b := 0 END ; - IF (y.lev > 0) & (y.lev # curlev) & (y.class # Const) THEN OSS.Mark("level error") END + BEGIN + x.mode := y.class; + x.type := y.type; + x.a := y.val; + x.r := y.lev; + + IF y.class = Par THEN + x.b := 0 + END ; + IF (y.lev > 0) & (y.lev # curlev) & (y.class # Const) THEN + OSS.Mark("level error") + END END MakeItem; PROCEDURE Field*(VAR x: Item; y: Object); (* x := x.y *) diff --git a/cerise/parser.c b/cerise/parser.c index c91309e..5a5e20c 100644 --- a/cerise/parser.c +++ b/cerise/parser.c @@ -136,13 +136,23 @@ static Symbol* symbol_new(Parser* p, char* name, int class, bool export) return sym; } -static Symbol* symbol_get(Parser* p, char* name) +static Symbol* symbol_get(Parser* p, int class, char* name) { Symbol* sym = p->scope; for (; sym; sym = sym->next) { if (!strcmp(sym->name, name)) { + if (class >= 0 && (int)sym->class != class) + { + switch(class) + { + case SYM_CONST: error(p, "'%s' is not a constant", name); break; + case SYM_VAR: error(p, "'%s' is not a variable", name); break; + case SYM_TYPE: error(p, "'%s' is not a type", name); break; + default: assert(!"unknown identifier type"); break; + } + } return sym; } } @@ -150,6 +160,15 @@ static Symbol* symbol_get(Parser* p, char* name) return NULL; } +/* Item Handling + *****************************************************************************/ +static void init_item(Item* item, Symbol* sym) +{ + item->mode = sym->class; + item->imm = sym->imm; + item->type = sym->type; +} + /* Type Checking *****************************************************************************/ static void check_int(Parser* p, Item* item) @@ -160,7 +179,7 @@ static void check_int(Parser* p, Item* item) } } -static void check_int2(Parser* p, Item* a, Item* b) +static void check_ints(Parser* p, Item* a, Item* b) { check_int(p, a); check_int(p, b); @@ -174,7 +193,7 @@ static void check_real(Parser* p, Item* item) } } -static void check_real2(Parser* p, Item* a, Item* b) +static void check_reals(Parser* p, Item* a, Item* b) { check_real(p, a); check_real(p, b); @@ -192,15 +211,15 @@ static void check_num(Parser* p, Item* a) } } -static void check_num2(Parser* p, Item* a, Item* b) +static void check_nums(Parser* p, Item* a, Item* b) { if (a->type->form == FORM_REAL) { - check_real2(p, a, b); + check_reals(p, a, b); } else { - check_int2(p, a, b); + check_ints(p, a, b); } } @@ -212,12 +231,28 @@ static void check_bool(Parser* p, Item* item) } } -static void check_bool2(Parser* p, Item* a, Item* b) +static void check_bools(Parser* p, Item* a, Item* b) { check_bool(p, a); check_bool(p, b); } +static void check_types(Parser* p, Item* a, Item* b) +{ + if (a->type->form == FORM_REAL) + { + check_reals(p, a, b); + } + else if (a->type->form == FORM_INT) + { + check_ints(p, a, b); + } + else + { + error(p, "type mismatch"); + } +} + /* Grammar Definition *****************************************************************************/ @@ -238,13 +273,19 @@ static void expression(Parser* p, Item* item); RULE(qualident) { char* name = expect_text(p, IDENT); - Symbol* sym = symbol_get(p, name); + Symbol* sym = symbol_get(p, -1, name); + init_item(item, sym); + +// item->mode = sym->class; +// item->type = sym->type; +// item->imm = sym->imm; + +// if (sym->class == SYM_CONST) +// { +// item->mode = ITEM_CONST; +// item->imm = sym->imm; +// } - if (sym->class == SYM_CONST) - { - item->mode = ITEM_CONST; - item->imm = sym->imm; - } // if (accept(p, '.')) // { // expect(p, IDENT); @@ -340,12 +381,12 @@ RULE(term) case '*': case '/': case '%': - check_num2(p, item, &right); + check_nums(p, item, &right); codegen_binop(op, item, &right); break; case AND: - check_bool2(p, item, &right); + check_bools(p, item, &right); codegen_binop(op, item, &right); break; @@ -379,11 +420,11 @@ RULE(simple_expr) term(p, &right); if (op == OR) { - check_bool2(p, item, &right); + check_bools(p, item, &right); } else { - check_num2(p, item, &right); + check_nums(p, item, &right); } codegen_binop(op, item, &right); } @@ -398,7 +439,7 @@ RULE(expression) Item right = { 0 }; int op = consume(p); simple_expr(p, &right); - check_num2(p, item, &right); + check_nums(p, item, &right); codegen_binop(op, item, &right); } } @@ -427,15 +468,7 @@ RULE(var_decl) expect(p, ':'); name = expect_text(p, IDENT); - type = symbol_get(p, name); - if (!type) - { - error(p, "unknown type identifier '%'\n", name); - } - if (type->class != SYM_TYPE) - { - error(p, "'%' is not a type identifier\n", name); - } + type = symbol_get(p, SYM_TYPE, name); /* apply the type to the newly created symbols */ for (int i = 0; i < nsyms; i++) @@ -464,6 +497,7 @@ RULE(const_decl) expect(p, '='); expression(p, item); sym->imm = item->imm; + sym->type = item->type; if (!accept(p, ',')) { @@ -472,26 +506,73 @@ RULE(const_decl) } } +/* Code generation for +find(obj); +OSS.Get(sym); +IF obj.class = OSG.SProc THEN + StandProc(obj.val) +ELSE + OSG.MakeItem(x, obj, level); + selector(x); + + IF sym = OSS.becomes THEN (*assignment*) + + OSS.Get(sym); + expression(y); + IF (x.type.form IN {OSG.Boolean, OSG.Integer}) & (x.type.form = y.type.form) THEN + OSG.Store(x, y) + ELSE + OSS.Mark("incompatible assignment") + END + +// ELSIF sym = OSS.eql THEN +// OSS.Mark("should be :="); +// OSS.Get(sym); +// expression(y) +// ELSIF sym = OSS.lparen THEN (*procedure call*) +// OSS.Get(sym); +// IF (obj.class = OSG.Proc) & (obj.type = NIL) THEN +// ParamList(obj); +// OSG.Call(obj); +// ELSE +// OSS.Mark("not a procedure") +// END +// ELSIF obj.class = OSG.Proc THEN (*procedure call without parameters*) +// IF obj.nofpar > 0 THEN +// OSS.Mark("missing parameters") +// END ; +// IF obj.type = NIL THEN +// OSG.Call(obj) ELSE +// OSS.Mark("not a procedure") +// END +// ELSIF (obj.class = OSG.SProc) & (obj.val = 3) THEN +// OSG.WriteLn +// ELSIF obj.class = OSG.Typ THEN +// OSS.Mark("illegal assignment") +// ELSE +// OSS.Mark("not a procedure") +// END +END + +*/ + RULE(statement_seq) { if (matches(p, IDENT)) { + Item right = { 0 }; char* text = expect_text(p, IDENT); if (accept(p, '=')) { - Symbol* sym = symbol_get(p, text); - if (!sym) - { - error(p, "undefined variable '%s'", text); - } - else if (sym->class != SYM_VAR) - { - error(p, "assignment to non-variable '%s'", text); - } - expression(p, item); + Symbol* sym = symbol_get(p, SYM_VAR, text); + init_item(item, sym); + expression(p, &right); + check_types(p, item, &right); + codegen_store(item, &right); } else { + /* TODO: add function calls and other complex stuff */ error(p, "expected assignment"); } } @@ -578,12 +659,12 @@ RULE(module) expect(p, ';'); } -static inline char* file_load(char* path) +static inline char* file_load(char* path) { int fd = -1, nread = 0, length = 0; struct stat sb = {0}; char* contents = NULL; - if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0)) + if (((fd = open(path, O_RDONLY, 0)) >= 0) && (fstat(fd, &sb) >= 0) && (sb.st_size > 0)) { contents = calloc(sb.st_size + 1u, 1u); while (sb.st_size && (nread = read(fd, contents+length, sb.st_size)) > 0) @@ -591,7 +672,7 @@ static inline char* file_load(char* path) length += nread, sb.st_size -= nread; } } - if (fd > 0) + if (fd > 0) { close(fd); } @@ -609,7 +690,7 @@ void compile(char* fname) .fbeg = fcontents, .fpos = fcontents, } - }, + }, &(Item){0} ); -- 2.49.0