diff --git a/oberon.c b/oberon.c
index f4a711f5da3156912e43afb4bc8887dd076936a3..dfed94a274ad3991d56ab8adf5223fabac446e38 100644 (file)
--- a/oberon.c
+++ b/oberon.c
RBRACE,
RECORD,
POINTER,
- TO
+ TO,
+ UPARROW,
+ NIL
};
// =======================================================================
{
ctx -> token = TO;
}
+ else if(strcmp(ident, "NIL") == 0)
+ {
+ ctx -> token = NIL;
+ }
}
static void
ctx -> token = RBRACE;
oberon_get_char(ctx);
break;
+ case '^':
+ ctx -> token = UPARROW;
+ oberon_get_char(ctx);
+ break;
default:
oberon_error(ctx, "invalid char");
break;
|| ((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)
{
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;
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");
}
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)
{
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);