From: DeaDDooMER Date: Mon, 24 Jul 2017 19:33:46 +0000 (+0300) Subject: Добавлены многомерные массивы и статическая проверка индексов X-Git-Url: http://deadsoftware.ru/gitweb?p=dsw-obn.git;a=commitdiff_plain;h=060a955ff58efde6cb51ab18eaed8f479e2550f3 Добавлены многомерные массивы и статическая проверка индексов --- diff --git a/notes b/notes index 0dd194e..c7324d2 100644 --- a/notes +++ b/notes @@ -1,13 +1,13 @@ -- хреновая проверка типов-указателей +- не реализованы var-параметры в генераторе + - нету процедуры NEW - не реализовано расширение типа record -- не реализована краткая форма многомерных массивов и краткой формы доступа к ним (* [1, 2, 3] - компилится, но вычисляется только первый аргумент *) +- нету открытых массивов - не реализованы локальные объявления в процедурах - не работает присваивание к переменным-процедурам. - не понятен результат присваивания статических структур (* reca := recb; *) - не понятен результат присваивания статических массивов (* arr1 := arr2; *) -- не реализованы var-параметры в генераторе - не реализованы процедуры "наперёд" - нету типа set diff --git a/oberon.c b/oberon.c index dfed94a..b7ffd0e 100644 --- a/oberon.c +++ b/oberon.c @@ -572,6 +572,7 @@ static oberon_expr_t * oberon_expr(oberon_context_t * ctx); static void oberon_assert_token(oberon_context_t * ctx, int token); static char * oberon_assert_ident(oberon_context_t * ctx); static void oberon_type(oberon_context_t * ctx, oberon_type_t ** type); +static oberon_item_t * oberon_const_expr(oberon_context_t * ctx); static oberon_expr_t * oberon_new_operator(int op, oberon_type_t * result, oberon_expr_t * left, oberon_expr_t * right) @@ -638,7 +639,7 @@ oberon_make_unary_op(oberon_context_t * ctx, int token, oberon_expr_t * a) } static void -oberon_expr_list(oberon_context_t * ctx, int * num_expr, oberon_expr_t ** first) +oberon_expr_list(oberon_context_t * ctx, int * num_expr, oberon_expr_t ** first, int const_expr) { oberon_expr_t * last; @@ -648,7 +649,16 @@ oberon_expr_list(oberon_context_t * ctx, int * num_expr, oberon_expr_t ** first) { oberon_assert_token(ctx, COMMA); oberon_expr_t * current; - current = oberon_expr(ctx); + + if(const_expr) + { + current = (oberon_expr_t *) oberon_const_expr(ctx); + } + else + { + current = oberon_expr(ctx); + } + last -> next = current; last = current; *num_expr += 1; @@ -663,7 +673,6 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t * oberon_error(ctx, "incompatible types"); } - if(pref -> class == OBERON_TYPE_INTEGER) { if(expr -> result -> class > pref -> class) @@ -679,6 +688,16 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t * oberon_error(ctx, "incompatible record types"); } } + else if(pref -> class == OBERON_TYPE_POINTER) + { + if(expr -> result -> base != pref -> base) + { + if(expr -> result -> base -> class != OBERON_TYPE_VOID) + { + oberon_error(ctx, "incompatible pointer types"); + } + } + } // TODO cast @@ -754,7 +773,7 @@ oberno_make_dereferencing(oberon_context_t * ctx, oberon_expr_t * expr) } static oberon_expr_t * -oberon_make_array_selector(oberon_context_t * ctx, oberon_expr_t * desig, int num_indexes, oberon_expr_t * indexes) +oberon_make_array_selector(oberon_context_t * ctx, oberon_expr_t * desig, oberon_expr_t * index) { if(desig -> result -> class == OBERON_TYPE_POINTER) { @@ -773,11 +792,30 @@ oberon_make_array_selector(oberon_context_t * ctx, oberon_expr_t * desig, int nu // TODO check ranges + printf("oberon_make_array_selector: index class %i\n", index -> result -> class); + if(index -> result -> class != OBERON_TYPE_INTEGER) + { + oberon_error(ctx, "index must be integer"); + } + + if(index -> is_item) + { + if(index -> item.mode == MODE_INTEGER) + { + int arr_size = desig -> result -> size; + int index_int = index -> item.integer; + if(index_int < 0 || index_int > arr_size - 1) + { + oberon_error(ctx, "not in range (dimension size 0..%i)", arr_size - 1); + } + } + } + oberon_expr_t * selector; selector = oberon_new_item(MODE_INDEX, base); selector -> item.parent = (oberon_item_t *) desig; - selector -> item.num_args = num_indexes; - selector -> item.args = indexes; + selector -> item.num_args = 1; + selector -> item.args = index; return selector; } @@ -858,9 +896,14 @@ oberon_designator(oberon_context_t * ctx) oberon_assert_token(ctx, LBRACE); int num_indexes = 0; oberon_expr_t * indexes = NULL; - oberon_expr_list(ctx, &num_indexes, &indexes); + oberon_expr_list(ctx, &num_indexes, &indexes, 0); oberon_assert_token(ctx, RBRACE); - expr = oberon_make_array_selector(ctx, expr, num_indexes, indexes); + + for(int i = 0; i < num_indexes; i++) + { + expr = oberon_make_array_selector(ctx, expr, indexes); + indexes = indexes -> next; + } break; case UPARROW: oberon_assert_token(ctx, UPARROW); @@ -893,7 +936,7 @@ oberon_opt_proc_parens(oberon_context_t * ctx, oberon_expr_t * expr) if(ISEXPR(ctx -> token)) { - oberon_expr_list(ctx, &num_args, &arguments); + oberon_expr_list(ctx, &num_args, &arguments, 0); } expr -> result = expr -> item.var -> type -> base; @@ -1423,9 +1466,14 @@ oberon_const_decl(oberon_context_t * ctx) } static void -oberon_make_array_type(oberon_context_t * ctx, oberon_item_t * size, oberon_type_t * base, oberon_type_t ** type) +oberon_make_array_type(oberon_context_t * ctx, oberon_expr_t * size, oberon_type_t * base, oberon_type_t ** type) { - if(size -> mode != MODE_INTEGER) + if(size -> is_item == 0) + { + oberon_error(ctx, "requires constant"); + } + + if(size -> item.mode != MODE_INTEGER) { oberon_error(ctx, "requires integer constant"); } @@ -1433,7 +1481,7 @@ oberon_make_array_type(oberon_context_t * ctx, oberon_item_t * size, oberon_type oberon_type_t * arr; arr = *type; arr -> class = OBERON_TYPE_ARRAY; - arr -> size = size -> integer; + arr -> size = size -> item.integer; arr -> base = base; } @@ -1484,6 +1532,23 @@ static void oberon_opt_formal_pars(oberon_context_t * ctx, oberon_type_t ** type * Правило граматики "type". Указатель type должен указывать на существующий объект! */ +static void +oberon_make_multiarray(oberon_context_t * ctx, oberon_expr_t * sizes, oberon_type_t * base, oberon_type_t ** type) +{ + if(sizes == NULL) + { + *type = base; + return; + } + + oberon_type_t * dim; + dim = oberon_new_type_ptr(OBERON_TYPE_VOID); + + oberon_make_multiarray(ctx, sizes -> next, base, &dim); + + oberon_make_array_type(ctx, sizes, dim, type); +} + static void oberon_type(oberon_context_t * ctx, oberon_type_t ** type) { @@ -1495,8 +1560,9 @@ oberon_type(oberon_context_t * ctx, oberon_type_t ** type) { oberon_assert_token(ctx, ARRAY); - oberon_item_t * size; - size = oberon_const_expr(ctx); + int num_sizes = 0; + oberon_expr_t * sizes; + oberon_expr_list(ctx, &num_sizes, &sizes, 1); oberon_assert_token(ctx, OF); @@ -1504,7 +1570,7 @@ oberon_type(oberon_context_t * ctx, oberon_type_t ** type) base = oberon_new_type_ptr(OBERON_TYPE_VOID); oberon_type(ctx, &base); - oberon_make_array_type(ctx, size, base, type); + oberon_make_multiarray(ctx, sizes, base, type); } else if(ctx -> token == RECORD) { diff --git a/test.c b/test.c index b934af8..d8f1083 100644 --- a/test.c +++ b/test.c @@ -5,15 +5,11 @@ static const char source[] = "MODULE Test;" "TYPE" - " MyRec = POINTER TO MyRecDesc;" - " MyRecDesc = RECORD" - " a : INTEGER;" - " END;" + " Matrix = ARRAY 3, 4 OF INTEGER;" "VAR" - " r : MyRec;" + " m : Matrix;" "BEGIN;" - " r := NIL;" - " r.a := 1;" + " m[2, 3] := 0;" "END Test." ; diff --git a/test/Test b/test/Test index 09dbea8..de23f9b 100755 Binary files a/test/Test and b/test/Test differ diff --git a/test/Test.Mod b/test/Test.Mod index 41e1fae..5d8536d 100644 --- a/test/Test.Mod +++ b/test/Test.Mod @@ -3,18 +3,18 @@ MODULE Test; IMPORT Out; TYPE - MyArr = ARRAY 3 OF POINTER TO ARRAY 6 OF INTEGER; + PVector = POINTER TO Vector; + Vector = ARRAY 3 OF INTEGER; VAR - a : MyArr; + a : PVector; + b : Vector; BEGIN Out.Open; - NEW(a[0]); - a[0][0] := 1; - Out.Int(a[0][0], 0); + NEW(a); + a^ := b; - Out.Ln; Out.Flush; END Test. diff --git a/test/Test.c b/test/Test.c index 22b0e5b..8f1b741 100644 --- a/test/Test.c +++ b/test/Test.c @@ -9,17 +9,21 @@ #include "Out.h" typedef - INT16 (*Test_MyArr[3])[6]; + INT16 Test_Vector[3]; + +typedef + Test_Vector *Test_PVector; -static Test_MyArr Test_a; +static Test_PVector Test_a; +static Test_Vector Test_b; static void EnumPtrs(void (*P)(void*)) { - __ENUMP(Test_a, 3, P); + P(Test_a); } @@ -30,10 +34,8 @@ export int main(int argc, char **argv) __REGMAIN("Test", EnumPtrs); /* BEGIN */ Out_Open(); - Test_a[0] = __NEWARR(NIL, 2, 2, 1, 0, ((INT64)(6))); - (*Test_a[0])[0] = 1; - Out_Int((*Test_a[0])[0], 0); - Out_Ln(); + Test_a = __NEWARR(NIL, 2, 2, 1, 0, ((INT64)(3))); + __MOVE(Test_b, *Test_a, 6); Out_Flush(); __FINI; }