DEADSOFTWARE

Добавлена процедура NEW для аллокации обычных массивов
[dsw-obn.git] / 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)
@@ -736,21 +742,26 @@ oberon_autocast_call(oberon_context_t * ctx, oberon_expr_t * desig)
        {
                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)
 {
@@ -2579,6 +2653,7 @@ 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;
 }