From dbaf15c64869a114c71004bc6a657d9710c784e5 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Fri, 7 May 2021 16:52:26 -0400 Subject: [PATCH] started adding array indexing --- cerise/backend/c99/codegen.c | 16 +++++ cerise/backend/test/codegen.c | 5 ++ cerise/backend/x86_64/codegen.c | 5 ++ cerise/inc/cerise.h | 2 + cerise/oberon0/OSG.Mod | 105 +++++++++++++++++++++++++------- cerise/oberon0/OSP.Mod | 78 ++++++++++++++++++------ cerise/src/grammar.c | 75 ++++++++++++----------- cerise/src/type_checks.c | 3 + cerise/tests/Module.m | 2 + 9 files changed, 213 insertions(+), 78 deletions(-) diff --git a/cerise/backend/c99/codegen.c b/cerise/backend/c99/codegen.c index 6c1fd3d..9c3636f 100644 --- a/cerise/backend/c99/codegen.c +++ b/cerise/backend/c99/codegen.c @@ -286,3 +286,19 @@ void codegen_return(Parser* p, Item* item) printf(" return _T%d;\n", item->reg); } } + +void codegen_rangecheck(Parser* p, long length, Item* index) +{ +// codegen_binop(p, '*', index, base); + if (index->mode == ITEM_CONST) + { + if (index->type->form != FORM_INT) + { + error(p, "array indexes must be of integral type"); + } + else if (index->imm.i >= length) + { + error(p, "array index out of bounds"); + } + } +} diff --git a/cerise/backend/test/codegen.c b/cerise/backend/test/codegen.c index ad2db8b..78e13a8 100644 --- a/cerise/backend/test/codegen.c +++ b/cerise/backend/test/codegen.c @@ -120,3 +120,8 @@ void codegen_return(Parser* p, Item* item) { (void)p, (void)item; } + +void codegen_rangecheck(Parser* p, long length, Item* index) +{ + (void)p, (void)length, (void)index; +} diff --git a/cerise/backend/x86_64/codegen.c b/cerise/backend/x86_64/codegen.c index dccec0c..fb3ea6a 100644 --- a/cerise/backend/x86_64/codegen.c +++ b/cerise/backend/x86_64/codegen.c @@ -348,3 +348,8 @@ void codegen_return(Parser* p, Item* item) { (void)p, (void)item; } + +void codegen_rangecheck(Parser* p, long length, Item* index) +{ + (void)p, (void)length, (void)index; +} diff --git a/cerise/inc/cerise.h b/cerise/inc/cerise.h index de6938f..ec2181d 100644 --- a/cerise/inc/cerise.h +++ b/cerise/inc/cerise.h @@ -120,6 +120,7 @@ typedef struct Item { Symbol* sym; Type* type; int reg; + int offset; ImmValue imm; } Item; @@ -223,6 +224,7 @@ void codegen_prepcall(Parser* p, Item* item); void codegen_call(Parser* p, Item* item, Item* args); void codegen_setarg(Parser* p, Item* item, bool firstarg); void codegen_return(Parser* p, Item* item); +void codegen_rangecheck(Parser* p, long length, Item* index); /* diff --git a/cerise/oberon0/OSG.Mod b/cerise/oberon0/OSG.Mod index f75fb1e..c8a226c 100644 --- a/cerise/oberon0/OSG.Mod +++ b/cerise/oberon0/OSG.Mod @@ -92,7 +92,11 @@ MODULE OSG; (* NW 19.12.94 / 20.10.07 / OSGX 9.5.2017*) END CheckRegs; PROCEDURE SetCC(VAR x: Item; n: LONGINT); - BEGIN x.mode := Cond; x.a := 0; x.b := 0; x.r := n + BEGIN + x.mode := Cond; + x.a := 0; + x.b := 0; + x.r := n END SetCC; PROCEDURE TestRange(x: LONGINT); @@ -180,11 +184,23 @@ MODULE OSG; (* NW 19.12.94 / 20.10.07 / OSGX 9.5.2017*) PROCEDURE loadAdr(VAR x: Item); BEGIN IF x.mode = Var THEN - IF x.r > 0 THEN (*local*) Put1(Add, RH, SP, x.a); x.r := RH ELSE GetSB; Put1(Add, RH, SB, x.a) END ; + IF x.r > 0 THEN (*local*) + Put1(Add, RH, SP, x.a); + x.r := RH + ELSE + GetSB; + Put1(Add, RH, SB, x.a) + END ; + incR + ELSIF x.mode = Par THEN + Put2(Ldw, RH, SP, x.a); + Put1(Add, RH, RH, x.b); + x.r := RH; incR - ELSIF x.mode = Par THEN Put2(Ldw, RH, SP, x.a); Put1(Add, RH, RH, x.b); x.r := RH; incR - ELSIF (x.mode = RegI) & (x.a # 0) THEN Put1(Add, x.r, x.r, x.a) - ELSE OSS.Mark("address error") + ELSIF (x.mode = RegI) & (x.a # 0) THEN + Put1(Add, x.r, x.r, x.a) + ELSE + OSS.Mark("address error") END ; x.mode := Reg END loadAdr; @@ -192,9 +208,19 @@ MODULE OSG; (* NW 19.12.94 / 20.10.07 / OSGX 9.5.2017*) PROCEDURE loadCond(VAR x: Item); BEGIN IF x.type.form = Boolean THEN - IF x.mode = Const THEN x.r := 15 - x.a*8 ELSE load(x); Put1(Cmp, x.r, x.r, 0); x.r := NE; DEC(RH) END ; - x.mode := Cond; x.a := 0; x.b := 0 - ELSE OSS.Mark("not Boolean") + IF x.mode = Const THEN + x.r := 15 - x.a*8 + ELSE + load(x); + Put1(Cmp, x.r, x.r, 0); + x.r := NE; + DEC(RH) + END ; + x.mode := Cond; + x.a := 0; + x.b := 0 + ELSE + OSS.Mark("not Boolean") END END loadCond; @@ -203,8 +229,12 @@ MODULE OSG; (* NW 19.12.94 / 20.10.07 / OSGX 9.5.2017*) BEGIN IF L0 # 0 THEN L3 := L0; - REPEAT L2 := L3; L3 := code[L2] MOD 40000H UNTIL L3 = 0; - code[L2] := code[L2] + L1; L1 := L0 + REPEAT + L2 := L3; + L3 := code[L2] MOD 40000H + UNTIL L3 = 0; + code[L2] := code[L2] + L1; + L1 := L0 END ; RETURN L1 END merged; @@ -212,7 +242,8 @@ MODULE OSG; (* NW 19.12.94 / 20.10.07 / OSGX 9.5.2017*) (*-----------------------------------------------*) PROCEDURE IncLevel*(n: INTEGER); - BEGIN curlev := curlev + n + BEGIN + curlev := curlev + n END IncLevel; PROCEDURE MakeConstItem*(VAR x: Item; typ: Type; val: LONGINT); @@ -240,8 +271,14 @@ MODULE OSG; (* NW 19.12.94 / 20.10.07 / OSGX 9.5.2017*) PROCEDURE Field*(VAR x: Item; y: Object); (* x := x.y *) BEGIN - IF (x.mode = Var) OR (x.mode = RegI) THEN x.a := x.a + y.val - ELSIF x.mode = Par THEN Put2(Ldw, RH, x.r, x.a); x.mode := RegI; x.r := RH; x.a := y.val; incR + IF (x.mode = Var) OR (x.mode = RegI) THEN + x.a := x.a + y.val + ELSIF x.mode = Par THEN + Put2(Ldw, RH, x.r, x.a); + x.mode := RegI; + x.r := RH; + x.a := y.val; + incR END END Field; @@ -249,18 +286,42 @@ MODULE OSG; (* NW 19.12.94 / 20.10.07 / OSGX 9.5.2017*) VAR s: LONGINT; BEGIN IF y.mode = Const THEN - IF (y.a < 0) OR (y.a >= x.type.len) THEN OSS.Mark("bad index") END ; - IF x.mode = Par THEN Put2(Ldw, RH, x.r, x.a); x.mode := RegI; x.a := 0 END ; + IF (y.a < 0) OR (y.a >= x.type.len) THEN + OSS.Mark("bad index") + END ; + IF x.mode = Par THEN + Put2(Ldw, RH, x.r, x.a); + x.mode := RegI; + x.a := 0 + END ; x.a := x.a + y.a * x.type.base.size - ELSE s := x.type.base.size; - IF y.mode # Reg THEN load(y) END ; - IF s = 4 THEN Put1(Lsl, y.r, y.r, 2) ELSE Put1(Mul, y.r, y.r, s) END ; + ELSE + s := x.type.base.size; + IF y.mode # Reg THEN + load(y) + END ; + IF s = 4 THEN + Put1(Lsl, y.r, y.r, 2) + ELSE + Put1(Mul, y.r, y.r, s) + END ; IF x.mode = Var THEN - IF x.r > 0 THEN Put0(Add, y.r, SP, y.r) ELSE GetSB; Put0(Add, y.r, SB, y.r) END ; - x.mode := RegI; x.r := y.r + IF x.r > 0 THEN + Put0(Add, y.r, SP, y.r) + ELSE + GetSB; + Put0(Add, y.r, SB, y.r) + END ; + x.mode := RegI; + x.r := y.r ELSIF x.mode = Par THEN - Put2(Ldw, RH, SP, x.a); Put0(Add, y.r, RH, y.r); x.mode := RegI; x.r := y.r - ELSIF x.mode = RegI THEN Put0(Add, x.r, x.r, y.r); DEC(RH) + Put2(Ldw, RH, SP, x.a); + Put0(Add, y.r, RH, y.r); + x.mode := RegI; + x.r := y.r + ELSIF x.mode = RegI THEN + Put0(Add, x.r, x.r, y.r); + DEC(RH) END END END Index; diff --git a/cerise/oberon0/OSP.Mod b/cerise/oberon0/OSP.Mod index ecaf363..503d84a 100644 --- a/cerise/oberon0/OSP.Mod +++ b/cerise/oberon0/OSP.Mod @@ -108,12 +108,15 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) VAR y: OSG.Item; obj: OSG.Object; BEGIN WHILE (sym = OSS.lbrak) OR (sym = OSS.period) DO - IF sym = OSS.lbrak THEN - OSS.Get(sym); expression(y); + OSS.Get(sym); + expression(y); IF x.type.form = OSG.Array THEN - CheckInt(y); OSG.Index(x, y); x.type := x.type.base - ELSE OSS.Mark("not an array") + CheckInt(y); + OSG.Index(x, y); + x.type := x.type.base + ELSE + OSS.Mark("not an array") END ; Check(OSS.rbrak, "no ]") @@ -196,12 +199,22 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) BEGIN IF sym = OSS.lparen THEN OSS.Get(sym); - IF fctno = 0 THEN (*ORD*) expression(x); OSG.Ord(x) - ELSIF fctno = 1 THEN (*eot*) OSG.eot(x) - ELSE (*fctno = 2*) OSG.Switch(x) + IF fctno = 0 THEN (*ORD*) + expression(x); + OSG.Ord(x) + ELSIF fctno = 1 THEN (*eot*) + OSG.eot(x) + ELSE (*fctno = 2*) + OSG.Switch(x) END ; - IF sym = OSS.rparen THEN OSS.Get(sym) ELSE OSS.Mark("rparen expected") END - ELSE OSS.Mark("param missing"); OSG.MakeConstItem(x, OSG.intType, 0) + IF sym = OSS.rparen THEN + OSS.Get(sym) + ELSE + OSS.Mark("rparen expected") + END + ELSE + OSS.Mark("param missing"); + OSG.MakeConstItem(x, OSG.intType, 0) END END StandF\unc; @@ -343,20 +356,39 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) PROCEDURE StandProc(pno: LONGINT); VAR x, y: OSG.Item; BEGIN - IF pno = 0 THEN OSG.OpenInput + IF pno = 0 THEN + OSG.OpenInput ELSIF pno IN {1, 2, 3, 5} THEN - IF sym = OSS.lparen THEN OSS.Get(sym); expression(x); - IF pno = 1 THEN OSG.ReadInt(x); + IF sym = OSS.lparen THEN + OSS.Get(sym); + expression(x); + IF pno = 1 THEN + OSG.ReadInt(x); ELSIF pno = 2 THEN - IF sym = OSS.comma THEN OSS.Get(sym); expression(y); OSG.WriteInt(x, y) ELSE OSS.Mark("no comma") END - ELSIF pno = 3 THEN OSG.WriteChar(x) - ELSIF pno = 5 THEN OSG.LED(x) - END ; - IF sym = OSS.rparen THEN OSS.Get(sym) ELSE OSS.Mark("no rparen") END - ELSE OSS.Mark(" missing lparen") + IF sym = OSS.comma THEN + OSS.Get(sym); + expression(y); + OSG.WriteInt(x, y) + ELSE + OSS.Mark("no comma") END - ELSIF pno = 4 THEN OSG.WriteLn - ELSE OSS.Mark("undef proc") + ELSIF pno = 3 THEN + OSG.WriteChar(x) + ELSIF pno = 5 THEN + OSG.LED(x) + END ; + IF sym = OSS.rparen THEN + OSS.Get(sym) + ELSE + OSS.Mark("no rparen") + END + ELSE + OSS.Mark(" missing lparen") + END + ELSIF pno = 4 THEN + OSG.WriteLn + ELSE + OSS.Mark("undef proc") END END StandProc; @@ -430,6 +462,7 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) Check(OSS.then, "no THEN"); StatSequence; L := 0; + WHILE sym = OSS.elsif DO OSS.Get(sym); OSG.FJump(L); @@ -444,6 +477,7 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) END ; StatSequence END ; + IF sym = OSS.else THEN OSS.Get(sym); OSG.FJump(L); @@ -452,7 +486,9 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) ELSE OSG.FixLink(x.a) END ; + OSG.FixLink(L); + IF sym = OSS.end THEN OSS.Get(sym) ELSE @@ -486,7 +522,9 @@ MODULE OSP; (* NW 23.9.93 / 9,5.2017 OSPX*) OSS.Get(sym) END END ; + OSG.CheckRegs; + IF sym = OSS.semicolon THEN OSS.Get(sym) ELSIF sym < OSS.semicolon THEN diff --git a/cerise/src/grammar.c b/cerise/src/grammar.c index 4140051..c90a895 100644 --- a/cerise/src/grammar.c +++ b/cerise/src/grammar.c @@ -111,22 +111,16 @@ RULE(designator) // case '.': // expect(p, IDENT); // break; -// + case '[': { expect(p, '['); Type* type = item->type; - while (type && type->form == FORM_ARRAY) - { - Item expr = {0}; - expression(p, &expr); - check_int(p, &expr); - type = type->base; - if (type->form == FORM_ARRAY) - { - expect(p, ','); - } - } + Item index = {0}; + expression(p, &index); + codegen_rangecheck(p, item->type->size, &index); + //codegen_binop(p, '*', &index, &base); + item->type = item->type->base; expect(p, ']'); break; } @@ -352,28 +346,29 @@ RULE(statement_seq) { do { - if (matches(p, IDENT)) - { - Item right = { 0 }; - char* text = expect_text(p, IDENT); - if (accept(p, '=')) - { - Symbol* sym = symbol_get(p, SYM_VAR, text); - init_item(item, sym); - item->imm.s = sym->name; - - expression(p, &right); - check_types(p, item, &right); - codegen_store(p, item, &right); - } - else - { - /* TODO: add function calls and other complex stuff */ - error(p, "expected assignment"); - } - expect(p, ';'); - } - else if (matches(p, IF)) +// if (matches(p, IDENT)) +// { +// Item right = { 0 }; +// char* text = expect_text(p, IDENT); +// if (accept(p, '=')) +// { +// Symbol* sym = symbol_get(p, SYM_VAR, text); +// init_item(item, sym); +// item->imm.s = sym->name; +// +// expression(p, &right); +// check_types(p, item, &right); +// codegen_store(p, item, &right); +// } +// else +// { +// /* TODO: add function calls and other complex stuff */ +// error(p, "expected assignment"); +// } +// expect(p, ';'); +// } +// else + if (matches(p, IF)) { expect(p, IF); expression(p, item); @@ -400,9 +395,17 @@ RULE(statement_seq) codegen_endif(p, elsifs, item); expect(p, END); } - else + else /* assignments/expressions */ { - error(p, "expected a statement"); + expression(p, item); + if (accept(p, '=')) + { + Item right = { 0 }; + expression(p, &right); + check_types(p, item, &right); + codegen_store(p, item, &right); + } + expect(p, ';'); } } while (!matches(p, END) && !matches(p, ELSE) && !matches(p, ELSIF) && !matches(p, RETURN)); diff --git a/cerise/src/type_checks.c b/cerise/src/type_checks.c index a50130e..b7285d6 100644 --- a/cerise/src/type_checks.c +++ b/cerise/src/type_checks.c @@ -81,6 +81,9 @@ void check_types(Parser* p, Item* a, Item* b) { check_bools(p, a, b); } +// else if (a->type->form == FORM_ARRAY) +// { +// } else { error(p, "type mismatch"); diff --git a/cerise/tests/Module.m b/cerise/tests/Module.m index fc74734..d7d9328 100644 --- a/cerise/tests/Module.m +++ b/cerise/tests/Module.m @@ -102,5 +102,7 @@ begin # # Function calls # c = Foo(1,2); +# e[0] = 1; +# Foo(1,2); e[0] = 1; end -- 2.49.0