DEADSOFTWARE

Добавлен модуль SYSTEM и тип SYSTEM.TYPE
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Thu, 17 Aug 2017 22:14:49 +0000 (01:14 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Thu, 17 Aug 2017 22:14:49 +0000 (01:14 +0300)
Files.obn
Test.obn
Test19.obn
proguard.conf
src/backends/jvm/generator-jvm-basic.c
src/backends/jvm/generator-jvm.c
src/oberon-internals.h
src/oberon-type-compat.c
src/oberon-type-compat.h
src/oberon.c

index 873866687e733ff8b031b030fdc7e87cee65be15..651bff944c0c527489e94f1d461c970d502fe39a 100644 (file)
--- a/Files.obn
+++ b/Files.obn
@@ -1,5 +1,7 @@
 MODULE Files;
 
+IMPORT SYSTEM;
+
 TYPE
   File* = POINTER TO Handle;
 
@@ -46,8 +48,7 @@ BEGIN RETURN 0 END Pos;
 PROCEDURE Base*(VAR r : Rider) : File;
 BEGIN RETURN NIL END Base;
 
-(* PROCEDURE Read*(VAR r : Rider; VAR x : SYSTEM.BYTE); *)
-PROCEDURE Read*(VAR r : Rider; VAR x : SHORTINT);
+PROCEDURE Read*(VAR r : Rider; VAR x : SYSTEM.BYTE);
 END Read;
 
 PROCEDURE ReadInt*(VAR R : Rider; VAR x : INTEGER);
@@ -74,12 +75,10 @@ END ReadSet;
 PROCEDURE ReadBool*(VAR R : Rider; VAR x : BOOLEAN);
 END ReadBool;
 
-(* PROCEDURE ReadBytes*(VAR r : Rider; VAR x : ARRAY OF SYSTEM.BYTE; n : LONGINT); *)
-PROCEDURE ReadBytes (VAR r : Rider; VAR x : ARRAY OF SHORTINT; n : LONGINT);
+PROCEDURE ReadBytes*(VAR r : Rider; VAR x : ARRAY OF SYSTEM.BYTE; n : LONGINT);
 END ReadBytes;
 
-(* PROCEDURE Write*(VAR r: Rider; x: SYSTEM.BYTE); *)
-PROCEDURE Write*(VAR r : Rider; x : SHORTINT); 
+PROCEDURE Write*(VAR r: Rider; x: SYSTEM.BYTE);
 END Write;
 
 PROCEDURE WriteInt*(VAR R : Rider; x : INTEGER);
@@ -106,8 +105,7 @@ END WriteSet;
 PROCEDURE WriteBool*(VAR R : Rider; x : BOOLEAN);
 END WriteBool;
 
-(* PROCEDURE WriteBytes*(VAR r : Rider; VAR x : ARRAY OF SYSTEM.BYTE; n : LONGINT); *)
-PROCEDURE WriteBytes*(VAR r : Rider; VAR x : ARRAY OF SHORTINT; n : LONGINT);
+PROCEDURE WriteBytes*(VAR r : Rider; VAR x : ARRAY OF SYSTEM.BYTE; n : LONGINT);
 END WriteBytes;
 
 END Files.
index c80345e560b5ed362e18a58a9a1abc772b084c44..fa347cddf19074ac48f9ac84d99c4993074f5aef 100644 (file)
--- a/Test.obn
+++ b/Test.obn
@@ -5,16 +5,17 @@ IMPORT Files, Out;
 VAR
   f : Files.File;
   r : Files.Rider;
-  i, len : LONGINT;
-  g : SHORTINT;
+  len : LONGINT;
   x : POINTER TO ARRAY OF CHAR;
 
 BEGIN
   f := Files.Old("Test.obn");
   ASSERT(f # NIL);
   Files.Set(r, f, 0);
+
   len := Files.Length(f);
   NEW(x, len + 1);
-  FOR i := 0 TO len - 1 DO Files.Read(r, g); x[i] := CHR(g) END;
+
+  Files.ReadBytes(r, x, len);
   Out.String(x^); Out.Ln;
 END Test.
index a8f63a0c43d1dde37dab4f9e124395178779068a..323d52829abcee47f89ae98fcde1b5c447a4e8c4 100644 (file)
@@ -5,17 +5,18 @@ IMPORT Files, Out;
 VAR
   f : Files.File;
   r : Files.Rider;
-  i, len : LONGINT;
-  g : SHORTINT;
+  len : LONGINT;
   x : POINTER TO ARRAY OF CHAR;
 
 BEGIN
   f := Files.Old("Test19.obn");
   ASSERT(f # NIL);
   Files.Set(r, f, 0);
+
   len := Files.Length(f);
   NEW(x, len + 1);
-  FOR i := 0 TO len - 1 DO Files.Read(r, g); x[i] := CHR(g) END;
+
+  Files.ReadBytes(r, x, len);
   Out.String(x^); Out.Ln;
 END Test19.
 
index b341d16d559b34b39e0d23bf70658a6d1775fe32..3adc0fef4708243054afc1d08219952774f8188a 100644 (file)
@@ -2,5 +2,4 @@
 -dontobfuscate
 -dontoptimize
 
--dontwarn Files**
 -keep class ** { void BEGIN(); }
index 27f1c56390802b409621ef18779d6781c6f10595..478a92c6f38cb91acb3c03c3f939c3158023d5f3 100644 (file)
@@ -77,6 +77,9 @@ jvm_get_descriptor(oberon_type_t * type)
                                        break;
                        }
                        break;
+               case OBERON_TYPE_SYSTEM_BYTE:
+                       return new_string("B");
+                       break;
                case OBERON_TYPE_REAL:
                        switch(type -> size)
                        {
@@ -187,6 +190,7 @@ jvm_get_prefix(oberon_type_t * type)
                case OBERON_TYPE_INTEGER:
                case OBERON_TYPE_CHAR:
                case OBERON_TYPE_SET:
+               case OBERON_TYPE_SYSTEM_BYTE:
                        return (size <= 4) ? ('i') : ('l');
                        break;
                case OBERON_TYPE_PROCEDURE:
@@ -237,6 +241,9 @@ jvm_get_postfix(oberon_type_t * type)
                                        break;
                        }
                        break;
+               case OBERON_TYPE_SYSTEM_BYTE:
+                       return 'b';
+                       break;
                case OBERON_TYPE_CHAR:
                        switch(size)
                        {
index 24268e178a7474cf893ec5836b437fedc6197bcf..1ba25c9afe28ee69e957cb10b6c9572814f06176 100644 (file)
@@ -492,6 +492,7 @@ oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
                case OBERON_TYPE_STRING:
                case OBERON_TYPE_SET:
                case OBERON_TYPE_NIL:
+               case OBERON_TYPE_SYSTEM_BYTE:
                        break;
                case OBERON_TYPE_RECORD:
                        m = type -> module -> gen_mod;
@@ -750,7 +751,10 @@ oberon_generate_begin_module(oberon_context_t * ctx)
        {
                if(x -> class == OBERON_CLASS_MODULE)
                {
-                       jvm_generate(p, 0, 0, "invokestatic %s/BEGIN()V", x -> module -> gen_mod -> class -> full_name);
+                       if(!x -> module -> intrinsic)
+                       {
+                               jvm_generate(p, 0, 0, "invokestatic %s/BEGIN()V", x -> module -> gen_mod -> class -> full_name);
+                       }
                }
                else if(x -> class == OBERON_CLASS_VAR)
                {
@@ -1044,13 +1048,16 @@ push_varptr(gen_proc_t * p, oberon_expr_t * expr)
                        jvm_generate_ldst_prepare(p, expr -> item.var -> gen_var);
                        break;
                case MODE_INDEX:
-                       push_item(p, (oberon_item_t *) expr -> item.parent);
+                       push_item(p, expr -> item.parent);
                        push_expr(p, expr -> item.args);
                        break;
                case MODE_FIELD:
-                       push_item(p, (oberon_item_t *) expr -> item.parent);
+                       push_item(p, expr -> item.parent);
                        jvm_generate_ldst_prepare(p, expr -> item.var -> gen_var);
                        break;
+               case MODE_DEREF:
+                       push_varptr(p, (oberon_expr_t *) expr -> item.parent);
+                       break;
                default:
                        gen_error("push_varptr: wat %i", expr -> item.mode);
                        break;
index 703ba6c5e4b4b6eb88fa9bb3f98d94973fd9e56e..c1454d433ff77e38c97ad35569bec8e8a4dd2a15 100644 (file)
@@ -47,7 +47,8 @@ enum oberon_type_kind
        OBERON_TYPE_CHAR,
        OBERON_TYPE_STRING,
        OBERON_TYPE_SET,
-       OBERON_TYPE_NIL
+       OBERON_TYPE_NIL,
+       OBERON_TYPE_SYSTEM_BYTE
 };
 
 typedef oberon_expr_t * (*GenerateFuncCallback)(oberon_context_t *, int, oberon_expr_t *);
@@ -118,7 +119,8 @@ struct oberon_object_t
 struct oberon_module_t
 {
        char * name;
-       int ready;
+       bool ready;
+       bool intrinsic;
 
        oberon_scope_t * decl;
 
@@ -148,6 +150,7 @@ struct oberon_context_t
        oberon_module_t * mod;
        /*** END PARSER DATA ***/
 
+       oberon_scope_t * world_scope;
        oberon_type_t * notype_type;
        oberon_type_t * nil_type;
        oberon_type_t * bool_type;
@@ -161,7 +164,9 @@ struct oberon_context_t
        oberon_type_t * string_type;
        oberon_type_t * set_type;
 
-       oberon_scope_t * world_scope;
+       oberon_module_t * system_module;
+       oberon_type_t * system_byte_type;
+
        oberon_module_t * module_list;
        ModuleImportCallback import_module;
        gen_context_t * gen_context;
index 60b37c40e76895feb562ccfda9930c8462cd8440..a99a04d37c70652f3add5a483b0ca5b0bf1edbfd 100644 (file)
@@ -39,6 +39,18 @@ oberon_is_integer_type(oberon_type_t * t)
        return t -> class == OBERON_TYPE_INTEGER;
 }
 
+bool
+oberon_is_system_byte_type(oberon_type_t * t)
+{
+       return t -> class == OBERON_TYPE_SYSTEM_BYTE;
+}
+
+bool
+oberon_is_byte_type(oberon_type_t * t)
+{
+       return oberon_is_integer_type(t) && t -> size == 1;
+}
+
 bool
 oberon_is_number_type(oberon_type_t * t)
 {
@@ -100,6 +112,12 @@ oberon_is_array_of_char_type(oberon_type_t * t)
        return oberon_is_array_type(t) && oberon_is_char_type(t -> base);
 }
 
+bool
+oberon_is_array_of_system_byte_type(oberon_type_t * t)
+{
+       return oberon_is_array_type(t) && oberon_is_system_byte_type(t -> base);
+}
+
 bool
 oberon_is_nil_type(oberon_type_t * t)
 {
@@ -272,6 +290,8 @@ oberon_is_assignment_compatible_expressions(oberon_expr_t * e, oberon_type_t * T
        /*      совпадают с параметрами Tv. */
        /* Доп: Tv - символ, е - строковая константа из одного символа */
 
+       /* SYSTEM: переменным типа BYTE можно присваивать значения переменных типа CHAR или SHORTINT. */
+
        oberon_type_t * Te = e -> result;
 
 /*
@@ -296,7 +316,8 @@ oberon_is_assignment_compatible_expressions(oberon_expr_t * e, oberon_type_t * T
                || ((oberon_is_pointer_type(Tv) || oberon_is_procedure_type(Tv)) && oberon_is_nil_type(Te))
                || (oberon_is_array_of_char_type(Tv) && !oberon_is_open_array(Tv) && oberon_is_const_string(e) && (strlen(e -> item.string) < Tv -> size))
                || (oberon_is_procedure_type(Tv) && e -> is_item && e -> item.var -> class == OBERON_CLASS_PROC && oberon_is_some_procedure_signatures(Tv, e -> result))
-               || (oberon_is_char_type(Tv) && oberon_is_const_string(e) && strlen(e -> item.string) == 1);
+               || (oberon_is_char_type(Tv) && oberon_is_const_string(e) && strlen(e -> item.string) == 1)
+               || (oberon_is_system_byte_type(Tv) && (oberon_is_char_type(Te) || oberon_is_byte_type(Te)));
 }
 
 static bool
@@ -429,8 +450,12 @@ oberon_is_compatible_var_param(oberon_type_t * Tf, oberon_type_t * Ta)
        /* Для параметров-переменных Ta и Tf должны быть одинаковыми типами */
        /* или Tf должен быть типом запись, а Ta - расширением Tf. */
 
+       /* SYSTEM: Если формальный параметр-переменная имеет тип ARRAY OF BYTE, */
+       /* то соответствующий фактический параметр может иметь любой тип. */
+
        return oberon_is_some_types(Tf, Ta)
-               || (oberon_is_record_type(Tf) && oberon_extension_of(Ta, Tf));
+               || (oberon_is_record_type(Tf) && oberon_extension_of(Ta, Tf))
+               || (oberon_is_array_of_system_byte_type(Tf));
 }
 
 void
index 904a89c4577de0ee9b270281103e3391b0530e0d..92b67503c78ffe37cfffa3b85c0adf543b648b18 100644 (file)
@@ -10,6 +10,9 @@ oberon_is_real_type(oberon_type_t * t);
 bool
 oberon_is_integer_type(oberon_type_t * t);
 
+bool
+oberon_is_system_byte_type(oberon_type_t * t);
+
 bool
 oberon_is_number_type(oberon_type_t * t);
 
index 365f47d6a107ac047dbe13e5f3293a5ea138123d..0bbeec188b3d5b4e7fafe506285a9d096cb809b7 100644 (file)
@@ -261,7 +261,6 @@ oberon_find_object_in_list(oberon_object_t * list, char * name)
        oberon_object_t * x = list;
        while(x -> next && strcmp(x -> next -> name, name) != 0)
        {
-               printf("inlist: '%s' != '%s'\n", x -> next -> name, name);
                x = x -> next;
        }
        return x -> next;
@@ -290,7 +289,6 @@ oberon_find_object(oberon_scope_t * scope, char * name, bool check_it)
 static oberon_object_t *
 oberon_create_object(oberon_scope_t * scope, char * name, int class, bool export, bool read_only)
 {
-       printf("oberon_create_object: '%s'\n", name);
        oberon_object_t * newvar = GC_MALLOC(sizeof *newvar);
        memset(newvar, 0, sizeof *newvar);
        newvar -> name = name;
@@ -318,7 +316,6 @@ oberon_define_object(oberon_scope_t * scope, char * name, int class, bool export
        oberon_object_t * x = scope -> list;
        while(x -> next && strcmp(x -> next -> name, name) != 0)
        {
-               printf("inlist: '%s' != '%s'\n", x -> next -> name, name);
                x = x -> next;
        }
 
@@ -334,16 +331,6 @@ oberon_define_object(oberon_scope_t * scope, char * name, int class, bool export
        return newvar;
 }
 
-static oberon_object_t *
-oberon_define_type(oberon_scope_t * scope, char * name, oberon_type_t * type, int export)
-{
-       oberon_object_t * id;
-       id = oberon_define_object(scope, name, OBERON_CLASS_TYPE, export, false, false);
-       id -> type = type;
-       oberon_generator_init_type(scope -> ctx, type);
-       return id;
-}
-
 // =======================================================================
 //   SCANER
 // ======================================================================= 
@@ -1137,7 +1124,8 @@ oberon_autocast_call(oberon_context_t * ctx, oberon_item_t * desig)
                        {
                                oberon_check_compatible_var_param(ctx, param -> type, arg -> result);
                        }
-                       casted[i] = oberon_cast_expr(ctx, arg, param -> type);
+                       casted[i] = arg;
+                       //casted[i] = oberon_cast_expr(ctx, arg, param -> type);
                }
                else
                {
@@ -4476,34 +4464,36 @@ register_default_types(oberon_context_t * ctx)
        oberon_generator_init_type(ctx, ctx -> string_type);
 
        ctx -> bool_type = oberon_new_type_boolean();
-       oberon_define_type(ctx -> world_scope, "BOOLEAN", ctx -> bool_type, 1);
+       oberon_generator_init_type(ctx, ctx -> bool_type);
 
        ctx -> char_type = oberon_new_type_char(1);
-       oberon_define_type(ctx -> world_scope, "CHAR", ctx -> char_type, 1);
+       oberon_generator_init_type(ctx, ctx -> char_type);
 
        ctx -> byte_type = oberon_new_type_integer(1);
-       oberon_define_type(ctx -> world_scope, "SHORTINT", ctx -> byte_type, 1);
+       oberon_generator_init_type(ctx, ctx -> byte_type);
 
        ctx -> shortint_type = oberon_new_type_integer(2);
-       oberon_define_type(ctx -> world_scope, "INTEGER", ctx -> shortint_type, 1);
+       oberon_generator_init_type(ctx, ctx -> shortint_type);
 
        ctx -> int_type = oberon_new_type_integer(4);
-       oberon_define_type(ctx -> world_scope, "LONGINT", ctx -> int_type, 1);
+       oberon_generator_init_type(ctx, ctx -> int_type);
 
        ctx -> longint_type = oberon_new_type_integer(8);
-       oberon_define_type(ctx -> world_scope, "HUGEINT", ctx -> longint_type, 1);
+       oberon_generator_init_type(ctx, ctx -> longint_type);
 
        ctx -> real_type = oberon_new_type_real(4);
-       oberon_define_type(ctx -> world_scope, "REAL", ctx -> real_type, 1);
+       oberon_generator_init_type(ctx, ctx -> real_type);
 
        ctx -> longreal_type = oberon_new_type_real(8);
-       oberon_define_type(ctx -> world_scope, "LONGREAL", ctx -> longreal_type, 1);
+       oberon_generator_init_type(ctx, ctx -> longreal_type);
 
        ctx -> set_type = oberon_new_type_set(4);
-       oberon_define_type(ctx -> world_scope, "SET", ctx -> set_type, 1);
-
+       oberon_generator_init_type(ctx, ctx -> set_type);
 
+       ctx -> system_byte_type = oberon_new_type_ptr(OBERON_TYPE_SYSTEM_BYTE);
+       oberon_generator_init_type(ctx, ctx -> system_byte_type);
 
+       /* LONG / SHORT support */
        ctx -> byte_type -> shorter = NULL;
        ctx -> byte_type -> longer = ctx -> shortint_type;
 
@@ -4534,6 +4524,41 @@ oberon_new_intrinsic(oberon_context_t * ctx, char * name, GenerateFuncCallback f
        proc -> type -> genproc = p;
 }
 
+static void oberon_new_intrinsic_type(oberon_context_t * ctx, char * name, oberon_type_t * type)
+{
+       oberon_object_t * id;
+       id = oberon_define_object(ctx -> decl, name, OBERON_CLASS_TYPE, true, false, false);
+       id -> type = type;
+}
+
+static void
+oberon_begin_intrinsic_module(oberon_context_t * ctx, char * name, oberon_module_t ** m)
+{
+       oberon_scope_t * module_scope;
+       module_scope = oberon_open_scope(ctx);
+
+       oberon_module_t * module;
+       module = GC_MALLOC(sizeof *module);
+       memset(module, 0, sizeof *module);
+       module -> name = name;
+       module -> intrinsic = true;
+       module -> decl = module_scope;
+       module -> next = ctx -> module_list;
+
+       ctx -> mod = module;
+       ctx -> module_list = module;
+
+       *m = module;
+}
+
+static void
+oberon_end_intrinsic_module(oberon_context_t * ctx, oberon_module_t * m)
+{
+       oberon_close_scope(m -> decl);
+       m -> ready = true;
+       ctx -> mod = NULL;
+}
+
 oberon_context_t *
 oberon_create_context(ModuleImportCallback import_module)
 {
@@ -4548,12 +4573,24 @@ oberon_create_context(ModuleImportCallback import_module)
 
        oberon_generator_init_context(ctx);
 
+       /* Types */
        register_default_types(ctx);
 
        /* Constants */
        oberon_new_const(ctx, "TRUE", oberon_make_boolean(ctx, true));
        oberon_new_const(ctx, "FALSE", oberon_make_boolean(ctx, false));
 
+       /* Types */
+       oberon_new_intrinsic_type(ctx, "BOOLEAN", ctx -> bool_type);
+       oberon_new_intrinsic_type(ctx, "CHAR", ctx -> char_type);
+       oberon_new_intrinsic_type(ctx, "SHORTINT", ctx -> byte_type);
+       oberon_new_intrinsic_type(ctx, "INTEGER", ctx -> shortint_type);
+       oberon_new_intrinsic_type(ctx, "LONGINT", ctx -> int_type);
+       oberon_new_intrinsic_type(ctx, "HUGEINT", ctx -> longint_type);
+       oberon_new_intrinsic_type(ctx, "REAL", ctx -> real_type);
+       oberon_new_intrinsic_type(ctx, "LONGREAL", ctx -> longreal_type);
+       oberon_new_intrinsic_type(ctx, "SET", ctx -> set_type);
+
        /* Functions */
        oberon_new_intrinsic(ctx, "ABS", oberon_make_abs_call, NULL);
        oberon_new_intrinsic(ctx, "ASH", oberon_make_ash_call, NULL);
@@ -4579,6 +4616,14 @@ oberon_create_context(ModuleImportCallback import_module)
        oberon_new_intrinsic(ctx, "INCL", NULL, oberon_make_incl_call);
        oberon_new_intrinsic(ctx, "NEW", NULL, oberon_make_new_call);
 
+       /* MODULE SYSTEM */
+       oberon_begin_intrinsic_module(ctx, "SYSTEM", &ctx -> system_module);
+
+               /* Types */
+               oberon_new_intrinsic_type(ctx, "BYTE", ctx -> system_byte_type);
+
+       oberon_end_intrinsic_module(ctx, ctx -> system_module);
+
        return ctx;
 }