DEADSOFTWARE

Добавлен NIL и автоматическое разыменование указателей
[dsw-obn.git] / oberon.c
index f4a711f5da3156912e43afb4bc8887dd076936a3..dfed94a274ad3991d56ab8adf5223fabac446e38 100644 (file)
--- a/oberon.c
+++ b/oberon.c
@@ -50,7 +50,9 @@ enum {
        RBRACE,
        RECORD,
        POINTER,
-       TO
+       TO,
+       UPARROW,
+       NIL
 };
 
 // =======================================================================
@@ -395,6 +397,10 @@ oberon_read_ident(oberon_context_t * ctx)
        {
                ctx -> token = TO;
        }
+       else if(strcmp(ident, "NIL") == 0)
+       {
+               ctx -> token = NIL;
+       }
 }
 
 static void
@@ -527,6 +533,10 @@ oberon_read_symbol(oberon_context_t * ctx)
                        ctx -> token = RBRACE;
                        oberon_get_char(ctx);
                        break;
+               case '^':
+                       ctx -> token = UPARROW;
+                       oberon_get_char(ctx);
+                       break;
                default:
                        oberon_error(ctx, "invalid char");
                        break;
@@ -726,45 +736,42 @@ oberon_autocast_call(oberon_context_t * ctx, oberon_expr_t * desig)
        || ((x) == TRUE) \
        || ((x) == FALSE))
 
-#define ISSELECTOR(x) \
-       (((x) == LBRACE) \
-       || ((x) == DOT))
-
 static oberon_expr_t *
-oberon_make_array_selector(oberon_context_t * ctx, oberon_expr_t * desig, int num_indexes, oberon_expr_t * indexes)
+oberno_make_dereferencing(oberon_context_t * ctx, oberon_expr_t * expr)
 {
-       assert(desig -> is_item == 1);
-
-       if(desig -> item.mode != MODE_VAR)
+       if(expr -> result -> class != OBERON_TYPE_POINTER)
        {
-               oberon_error(ctx, "not MODE_VAR");
+               oberon_error(ctx, "not a pointer");
        }
 
-       int class = desig -> item.var -> class;
-       switch(class)
+       assert(expr -> is_item);
+
+       oberon_expr_t * selector;
+       selector = oberon_new_item(MODE_DEREF, expr -> result -> base);
+       selector -> item.parent = (oberon_item_t *) expr;
+
+       return selector;
+}
+
+static oberon_expr_t *
+oberon_make_array_selector(oberon_context_t * ctx, oberon_expr_t * desig, int num_indexes, oberon_expr_t * indexes)
+{
+       if(desig -> result -> class == OBERON_TYPE_POINTER)
        {
-               case OBERON_CLASS_VAR:
-               case OBERON_CLASS_VAR_PARAM:
-               case OBERON_CLASS_PARAM:
-                       break;
-               default:
-                       oberon_error(ctx, "not variable");
-                       break;
+               desig = oberno_make_dereferencing(ctx, desig);
        }
 
-       oberon_type_t * type = desig -> item.var -> type;
-       if(type -> class != OBERON_TYPE_ARRAY)
+       assert(desig -> is_item);
+
+       if(desig -> result -> class != OBERON_TYPE_ARRAY)
        {
                oberon_error(ctx, "not array");
        }
 
-//     int dim = desig -> item.var -> type -> dim;
-//     if(num_indexes != dim)
-//     {
-//             oberon_error(ctx, "dimesions not matched");
-//     }
+       oberon_type_t * base;
+       base = desig -> result -> base;
 
-       oberon_type_t * base = desig -> item.var -> type -> base;
+       // TODO check ranges
 
        oberon_expr_t * selector;
        selector = oberon_new_item(MODE_INDEX, base);
@@ -778,10 +785,14 @@ oberon_make_array_selector(oberon_context_t * ctx, oberon_expr_t * desig, int nu
 static oberon_expr_t *
 oberon_make_record_selector(oberon_context_t * ctx, oberon_expr_t * expr, char * name)
 {
+       if(expr -> result -> class == OBERON_TYPE_POINTER)
+       {
+               expr = oberno_make_dereferencing(ctx, expr);
+       }
+
        assert(expr -> is_item == 1);
 
-       int class = expr -> result -> class;
-       if(class != OBERON_TYPE_RECORD)
+       if(expr -> result -> class != OBERON_TYPE_RECORD)
        {
                oberon_error(ctx, "not record");
        }
@@ -799,6 +810,11 @@ oberon_make_record_selector(oberon_context_t * ctx, oberon_expr_t * expr, char *
        return selector;
 }
 
+#define ISSELECTOR(x) \
+       (((x) == LBRACE) \
+       || ((x) == DOT) \
+       || ((x) == UPARROW))
+
 static oberon_expr_t *
 oberon_designator(oberon_context_t * ctx)
 {
@@ -846,6 +862,10 @@ oberon_designator(oberon_context_t * ctx)
                                oberon_assert_token(ctx, RBRACE);
                                expr = oberon_make_array_selector(ctx, expr, num_indexes, indexes);
                                break;
+                       case UPARROW:
+                               oberon_assert_token(ctx, UPARROW);
+                               expr = oberno_make_dereferencing(ctx, expr);
+                               break;
                        default:
                                oberon_error(ctx, "oberon_designator: wat");
                                break;
@@ -924,6 +944,10 @@ oberon_factor(oberon_context_t * ctx)
                        expr = oberon_factor(ctx);
                        expr = oberon_make_unary_op(ctx, NOT, expr);
                        break;
+               case NIL:
+                       oberon_assert_token(ctx, NIL);
+                       expr = oberon_new_item(MODE_NIL, ctx -> void_ptr_type);
+                       break;
                default:
                        oberon_error(ctx, "invalid expression");
        }
@@ -1773,16 +1797,8 @@ oberon_initialize_type(oberon_context_t * ctx, oberon_type_t * type)
 
        if(type -> class == OBERON_TYPE_POINTER)
        {
-               if(type -> base -> class == OBERON_TYPE_RECORD)
-               {
-                       oberon_generator_init_type(ctx, type -> base);
-                       oberon_generator_init_type(ctx, type);
-               }
-               else
-               {
-                       oberon_initialize_type(ctx, type -> base);
-                       oberon_generator_init_type(ctx, type);
-               }
+               oberon_initialize_type(ctx, type -> base);
+               oberon_generator_init_type(ctx, type);
        }
        else if(type -> class == OBERON_TYPE_ARRAY)
        {
@@ -1995,6 +2011,10 @@ register_default_types(oberon_context_t * ctx)
        ctx -> void_type = oberon_new_type_ptr(OBERON_TYPE_VOID);
        oberon_generator_init_type(ctx, ctx -> void_type);
 
+       ctx -> void_ptr_type = oberon_new_type_ptr(OBERON_TYPE_POINTER);
+       ctx -> void_ptr_type -> base = ctx -> void_type;
+       oberon_generator_init_type(ctx, ctx -> void_ptr_type);
+
        ctx -> int_type = oberon_new_type_integer(sizeof(int));
        oberon_define_type(ctx -> world_scope, "INTEGER", ctx -> int_type);