diff --git a/oberon.c b/oberon.c
index e857b1d1ec6f93e454b5439cdcf81f96c150d167..931d948c57bc15c0faf906e0a6f23b52f991a122 100644 (file)
--- a/oberon.c
+++ b/oberon.c
@@ -665,7 +665,13 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t *
{
if(pref -> class != expr -> result -> class)
{
- oberon_error(ctx, "incompatible types");
+ if(pref -> class != OBERON_TYPE_PROCEDURE)
+ {
+ if(expr -> result -> class != OBERON_TYPE_POINTER)
+ {
+ oberon_error(ctx, "incompatible types");
+ }
+ }
}
if(pref -> class == OBERON_TYPE_INTEGER)
{
if(param -> class == OBERON_CLASS_VAR_PARAM)
{
- if(arg -> is_item)
+ if(arg -> read_only)
{
- switch(arg -> item.mode)
- {
- case MODE_VAR:
- case MODE_INDEX:
- case MODE_FIELD:
- // Допустимо разыменование?
- //case MODE_DEREF:
- break;
- default:
- oberon_error(ctx, "var-parameter accept only variables");
- break;
- }
+ oberon_error(ctx, "assign to read-only var");
}
+
+ //if(arg -> is_item)
+ //{
+ // switch(arg -> item.mode)
+ // {
+ // case MODE_VAR:
+ // case MODE_INDEX:
+ // case MODE_FIELD:
+ // // Допустимо разыменование?
+ // //case MODE_DEREF:
+ // break;
+ // default:
+ // oberon_error(ctx, "var-parameter accept only variables");
+ // break;
+ // }
+ //}
}
oberon_autocast_to(ctx, arg, param -> type);
arg = arg -> next;
@@ -2564,6 +2575,69 @@ oberon_make_abs_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_
return expr;
}
+static void
+oberon_make_new_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_args)
+{
+ if(num_args < 1)
+ {
+ oberon_error(ctx, "too few arguments");
+ }
+
+ if(num_args > 1)
+ {
+ oberon_error(ctx, "too mach arguments");
+ }
+
+ oberon_expr_t * dst;
+ dst = list_args;
+
+ oberon_type_t * type;
+ type = dst -> result;
+
+ if(type -> class != OBERON_TYPE_POINTER)
+ {
+ oberon_error(ctx, "not a pointer");
+ }
+
+ type = type -> base;
+
+ oberon_expr_t * src;
+ if(type -> class == OBERON_TYPE_ARRAY)
+ {
+ int dim = 1;
+
+ oberon_expr_t * sizes = NULL;
+ oberon_expr_t * last_size = NULL;
+
+ sizes = last_size = oberon_new_item(MODE_INTEGER, ctx -> int_type, 1);
+ sizes -> item.integer = type -> size;
+
+ oberon_type_t * base = type -> base;
+ while(base -> class == OBERON_TYPE_ARRAY)
+ {
+ oberon_expr_t * size;
+ size = last_size = oberon_new_item(MODE_INTEGER, ctx -> int_type, 1);
+ size -> item.integer = base -> size;
+
+ last_size -> next = size;
+ last_size = size;
+ base = base -> base;
+ dim += 1;
+ }
+
+ src = oberon_new_item(MODE_NEWARR, dst -> result, 0);
+ src -> item.num_args = dim;
+ src -> item.args = sizes;
+ src -> item.type = base;
+ }
+ else
+ {
+ oberon_error(ctx, "oberon_make_new_call: wat");
+ }
+
+ oberon_assign(ctx, src, dst);
+}
+
oberon_context_t *
oberon_create_context(ModuleImportCallback import_module)
{
register_default_types(ctx);
oberon_new_intrinsic(ctx, "ABS", oberon_make_abs_call, NULL);
+ oberon_new_intrinsic(ctx, "NEW", NULL, oberon_make_new_call);
return ctx;
}