DEADSOFTWARE

Добавлены многомерные массивы и статическая проверка индексов
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Mon, 24 Jul 2017 19:33:46 +0000 (22:33 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Mon, 24 Jul 2017 19:33:46 +0000 (22:33 +0300)
notes
oberon.c
test.c
test/Test
test/Test.Mod
test/Test.c

diff --git a/notes b/notes
index 0dd194e9e6e6057ced4ec2518616dd9f63622934..c7324d2ec5175d84d4bd80e989d0f85e5daddbaa 100644 (file)
--- a/notes
+++ b/notes
@@ -1,13 +1,13 @@
-- хреновая проверка типов-указателей
+- не реализованы var-параметры в генераторе
+
 - нету процедуры NEW
 - не реализовано расширение типа record
-- не реализована краткая форма многомерных массивов и краткой формы доступа к ним (* [1, 2, 3] - компилится, но вычисляется только первый аргумент *)
+- нету открытых массивов
 
 - не реализованы локальные объявления в процедурах
 - не работает присваивание к переменным-процедурам.
 - не понятен результат присваивания статических структур (* reca := recb; *)
 - не понятен результат присваивания статических массивов (* arr1 := arr2; *)
-- не реализованы var-параметры в генераторе
 - не реализованы процедуры "наперёд"
 
 - нету типа set
index dfed94a274ad3991d56ab8adf5223fabac446e38..b7ffd0ea73ab2b9cd366a04d96a2b1e16a80a94d 100644 (file)
--- 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 b934af876ca2bde9d44397015f95c7ce70953bd5..d8f108377c2fa5299bc8460109e59289ea280c61 100644 (file)
--- 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."
 ;
 
index 09dbea89f6a56f7f03fd224992382247908ac664..de23f9b639cfb000e82fcdc28851179dcb4907da 100755 (executable)
Binary files a/test/Test and b/test/Test differ
index 41e1faeb099b8b10a52e4abd8a4822de32c9c08e..5d8536d5febdcc37b5d7e8f671723f6e42ceebbe 100644 (file)
@@ -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.
index 22b0e5bd3ff0cbc2179f75cfe1da48159b9fb4b6..8f1b741fb78b8d84351a99400a889a365b784ff5 100644 (file)
@@ -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;
 }