DEADSOFTWARE

Добавлены списки объявлений
[dsw-obn.git] / oberon.c
index e12ee36174e9fd9cfd9a870225dea8528d46e8f8..5b4c4ea84efada1e388a0c775f4d363e16df49d8 100644 (file)
--- a/oberon.c
+++ b/oberon.c
@@ -134,7 +134,7 @@ oberon_close_scope(oberon_scope_t * scope)
 }
 
 static oberon_object_t *
-oberon_define_object(oberon_scope_t * scope, char * name, int class)
+oberon_define_object(oberon_scope_t * scope, char * name, int class, int export, int read_only)
 {
        oberon_object_t * x = scope -> list;
        while(x -> next && strcmp(x -> next -> name, name) != 0)
@@ -151,6 +151,8 @@ oberon_define_object(oberon_scope_t * scope, char * name, int class)
        memset(newvar, 0, sizeof *newvar);
        newvar -> name = name;
        newvar -> class = class;
+       newvar -> export = export;
+       newvar -> read_only = read_only;
        newvar -> local = scope -> local;
        newvar -> parent = scope -> parent;
 
@@ -159,6 +161,7 @@ oberon_define_object(oberon_scope_t * scope, char * name, int class)
        return newvar;
 }
 
+/*
 static void
 oberon_define_field(oberon_context_t * ctx, oberon_type_t * rec, char *  name, oberon_type_t * type)
 {
@@ -186,6 +189,7 @@ oberon_define_field(oberon_context_t * ctx, oberon_type_t * rec, char *  name, o
        rec -> num_decl += 1;
        x -> next = field;
 }
+*/
 
 static oberon_object_t *
 oberon_find_object_in_list(oberon_object_t * list, char * name)
@@ -237,64 +241,15 @@ oberon_find_field(oberon_context_t * ctx, oberon_type_t * rec, char * name)
 }
 
 static oberon_object_t *
-oberon_define_type(oberon_scope_t * scope, char * name, oberon_type_t * type)
+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);
+       id = oberon_define_object(scope, name, OBERON_CLASS_TYPE, export, 0);
        id -> type = type;
        oberon_generator_init_type(scope -> ctx, type);
        return id;
 }
 
-/*
-static oberon_type_t *
-oberon_find_type(oberon_scope_t * scope, char * name)
-{
-       oberon_object_t * x = oberon_find_object(scope, name);
-       if(x -> class != OBERON_CLASS_TYPE)
-       {
-               oberon_error(scope -> ctx, "%s not a type", name);
-       }
-
-       return x -> type;
-}
-*/
-
-static oberon_object_t *
-oberon_define_var(oberon_scope_t * scope, int class, char * name, oberon_type_t * type)
-{
-       oberon_object_t * var;
-       var = oberon_define_object(scope, name, class);
-       var -> type = type;
-       return var;
-}
-
-/*
-static oberon_object_t *
-oberon_find_var(oberon_scope_t * scope, char * name)
-{
-       oberon_object_t * x = oberon_find_object(scope, name);
-
-       if(x -> class != OBERON_CLASS_VAR)
-       {
-               oberon_error(scope -> ctx, "%s not a var", name);
-       }
-
-       return x;
-}
-*/
-
-/*
-static oberon_object_t *
-oberon_define_proc(oberon_scope_t * scope, char * name, oberon_type_t * signature)
-{
-       oberon_object_t * proc;
-       proc = oberon_define_object(scope, name, OBERON_CLASS_PROC);
-       proc -> type = signature;
-       return proc;
-}
-*/
-
 // =======================================================================
 //   SCANER
 // ======================================================================= 
@@ -1004,6 +959,11 @@ oberon_qualident(oberon_context_t * ctx, char ** xname, int check)
                        name = oberon_assert_ident(ctx);
                        /* Наличие объектов в левых модулях всегда проверяется */
                        x = oberon_find_object(x -> module -> decl, name, 1);
+
+                       if(x -> export == 0)
+                       {
+                               oberon_error(ctx, "not exported");
+                       }
                }
        }
 
@@ -1446,50 +1406,88 @@ oberon_assert_ident(oberon_context_t * ctx)
 }
 
 static void
-oberon_var_decl(oberon_context_t * ctx)
+oberon_def(oberon_context_t * ctx, int * export, int * read_only)
+{
+       switch(ctx -> token)
+       {
+               case STAR:
+                       oberon_assert_token(ctx, STAR);
+                       *export = 1;
+                       *read_only = 0;
+                       break;
+               case MINUS:
+                       oberon_assert_token(ctx, MINUS);
+                       *export = 1;
+                       *read_only = 1;
+                       break;
+               default:
+                       *export = 0;
+                       *read_only = 0;
+                       break;
+       }
+}
+
+static oberon_object_t *
+oberon_ident_def(oberon_context_t * ctx, int class)
 {
        char * name;
-       oberon_type_t * type;
-       type = oberon_new_type_ptr(OBERON_TYPE_VOID);
+       int export;
+       int read_only;
+       oberon_object_t * x;
 
        name = oberon_assert_ident(ctx);
-       oberon_assert_token(ctx, COLON);
-       oberon_type(ctx, &type);
-       oberon_define_var(ctx -> decl, OBERON_CLASS_VAR, name, type);
+       oberon_def(ctx, &export, &read_only);
+
+       x = oberon_define_object(ctx -> decl, name, class, export, read_only);
+       return x;
 }
 
-static oberon_object_t *
-oberon_make_param(oberon_context_t * ctx, int token, char * name, oberon_type_t * type)
+static void
+oberon_ident_list(oberon_context_t * ctx, int class, int * num, oberon_object_t ** list)
 {
-       oberon_object_t * param;
-
-       if(token == VAR)
-       {
-               param = oberon_define_var(ctx -> decl, OBERON_CLASS_VAR_PARAM, name, type);
-       }
-       else if(token == IDENT)
+       *num = 1;
+       *list = oberon_ident_def(ctx, class);
+       while(ctx -> token == COMMA)
        {
-               param = oberon_define_var(ctx -> decl, OBERON_CLASS_PARAM, name, type);
+               oberon_assert_token(ctx, COMMA);
+               oberon_ident_def(ctx, class);
+               *num += 1;
        }
-       else
+}
+
+static void
+oberon_var_decl(oberon_context_t * ctx)
+{
+       int num;
+       oberon_object_t * list;
+       oberon_type_t * type;
+       type = oberon_new_type_ptr(OBERON_TYPE_VOID);
+
+       oberon_ident_list(ctx, OBERON_CLASS_VAR, &num, &list);
+       oberon_assert_token(ctx, COLON);
+       oberon_type(ctx, &type);
+
+       oberon_object_t * var = list;
+       for(int i = 0; i < num; i++)
        {
-               oberon_error(ctx, "oberon_make_param: wat");
+               var -> type = type;
+               var = var -> next;
        }
-
-       return param;
 }
 
 static oberon_object_t *
 oberon_fp_section(oberon_context_t * ctx, int * num_decl)
 {
-       int modifer_token = ctx -> token;
+       int class = OBERON_CLASS_PARAM;
        if(ctx -> token == VAR)
        {
                oberon_read_token(ctx);
+               class = OBERON_CLASS_VAR_PARAM;
        }
 
-       char * name;
-       name = oberon_assert_ident(ctx);
+       int num;
+       oberon_object_t * list;
+       oberon_ident_list(ctx, class, &num, &list);
 
        oberon_assert_token(ctx, COLON);
 
@@ -1497,11 +1495,15 @@ oberon_fp_section(oberon_context_t * ctx, int * num_decl)
        type = oberon_new_type_ptr(OBERON_TYPE_VOID);
        oberon_type(ctx, &type);
 
-       oberon_object_t * first;
-       first = oberon_make_param(ctx, modifer_token, name, type);
+       oberon_object_t * param = list;
+       for(int i = 0; i < num; i++)
+       {
+               param -> type = type;
+               param = param -> next;
+       }
 
-       *num_decl += 1;
-       return first;
+       *num_decl += num;
+       return list;
 }
 
 #define ISFPSECTION \
@@ -1662,7 +1664,10 @@ oberon_proc_decl(oberon_context_t * ctx)
        }
 
        char * name;
+       int export;
+       int read_only;
        name = oberon_assert_ident(ctx);
+       oberon_def(ctx, &export, &read_only);
 
        oberon_scope_t * proc_scope;
        proc_scope = oberon_open_scope(ctx);
@@ -1693,11 +1698,16 @@ oberon_proc_decl(oberon_context_t * ctx)
                        }
                }
 
+               if(proc -> export != export || proc -> read_only != read_only)
+               {
+                       oberon_error(ctx, "export type not matched");
+               }
+
                oberon_compare_signatures(ctx, proc -> type, signature);
        }
        else
        {
-               proc = oberon_define_object(ctx -> decl, name, OBERON_CLASS_PROC);
+               proc = oberon_define_object(ctx -> decl, name, OBERON_CLASS_PROC, export, read_only);
                proc -> type = signature;
                proc -> scope = proc_scope;
                oberon_generator_init_proc(ctx, proc);
@@ -1715,15 +1725,12 @@ oberon_proc_decl(oberon_context_t * ctx)
 static void
 oberon_const_decl(oberon_context_t * ctx)
 {
-       char * name;
        oberon_item_t * value;
        oberon_object_t * constant;
 
-       name = oberon_assert_ident(ctx);
+       constant = oberon_ident_def(ctx, OBERON_CLASS_CONST);
        oberon_assert_token(ctx, EQUAL);
        value = oberon_const_expr(ctx);
-
-       constant = oberon_define_object(ctx -> decl, name, OBERON_CLASS_CONST);
        constant -> value = value;
 }
 
@@ -1752,14 +1759,23 @@ oberon_field_list(oberon_context_t * ctx, oberon_type_t * rec)
 {
        if(ctx -> token == IDENT)
        {
-               char * name;
+               int num;
+               oberon_object_t * list;
                oberon_type_t * type;
                type = oberon_new_type_ptr(OBERON_TYPE_VOID);
 
-               name = oberon_assert_ident(ctx);
+               oberon_ident_list(ctx, OBERON_CLASS_FIELD, &num, &list);
                oberon_assert_token(ctx, COLON);
                oberon_type(ctx, &type);
-               oberon_define_field(ctx, rec, name, type);
+
+               oberon_object_t * field = list;
+               for(int i = 0; i < num; i++)
+               {
+                       field -> type = type;
+                       field = field -> next;
+               }
+
+               rec -> num_decl += num;
        }
 }
 
@@ -1783,7 +1799,7 @@ oberon_qualident_type(oberon_context_t * ctx, oberon_type_t ** type)
        }
        else
        {
-               to = oberon_define_object(ctx -> decl, name, OBERON_CLASS_TYPE);
+               to = oberon_define_object(ctx -> decl, name, OBERON_CLASS_TYPE, 0, 0);
                to -> type = oberon_new_type_ptr(OBERON_TYPE_VOID);
        }
 
@@ -1841,11 +1857,12 @@ oberon_type(oberon_context_t * ctx, oberon_type_t ** type)
                oberon_type_t * rec;
                rec = *type;
                rec -> class = OBERON_TYPE_RECORD;
-               oberon_object_t * list = malloc(sizeof *list);
-               memset(list, 0, sizeof *list);
-               rec -> num_decl = 0;
-               rec -> base = NULL;
-               rec -> decl = list;
+
+               oberon_scope_t * record_scope;
+               record_scope = oberon_open_scope(ctx);
+               // TODO parent object
+               //record_scope -> parent = NULL;
+               record_scope -> local = 1;
 
                oberon_assert_token(ctx, RECORD);
                oberon_field_list(ctx, rec);
@@ -1856,7 +1873,9 @@ oberon_type(oberon_context_t * ctx, oberon_type_t ** type)
                }
                oberon_assert_token(ctx, END);
 
-               rec -> decl = rec -> decl -> next;
+               rec -> decl = record_scope -> list -> next;
+               oberon_close_scope(record_scope);
+
                *type = rec;
        }
        else if(ctx -> token == POINTER)
@@ -1892,13 +1911,16 @@ oberon_type_decl(oberon_context_t * ctx)
        char * name;
        oberon_object_t * newtype;
        oberon_type_t * type;
+       int export;
+       int read_only;
 
        name = oberon_assert_ident(ctx);
+       oberon_def(ctx, &export, &read_only);
 
        newtype = oberon_find_object(ctx -> decl, name, 0);
        if(newtype == NULL)
        {
-               newtype = oberon_define_object(ctx -> decl, name, OBERON_CLASS_TYPE);
+               newtype = oberon_define_object(ctx -> decl, name, OBERON_CLASS_TYPE, export, read_only);
                newtype -> type = oberon_new_type_ptr(OBERON_TYPE_VOID);
                assert(newtype -> type);
        }
@@ -1913,6 +1935,9 @@ oberon_type_decl(oberon_context_t * ctx)
                {
                        oberon_error(ctx, "mult definition - already linked");
                }
+
+               newtype -> export = export;
+               newtype -> read_only = read_only;
        }
 
        oberon_assert_token(ctx, EQUAL);
@@ -2348,7 +2373,7 @@ oberon_import_module(oberon_context_t * ctx, char * alias, char * name)
        }
 
        oberon_object_t * ident;
-       ident = oberon_define_object(ctx -> decl, alias, OBERON_CLASS_MODULE);
+       ident = oberon_define_object(ctx -> decl, alias, OBERON_CLASS_MODULE, 0, 0);
        ident -> module = m;
 }
 
@@ -2396,7 +2421,7 @@ oberon_parse_module(oberon_context_t * ctx)
        ctx -> mod -> name = name1;
 
        oberon_object_t * this_module;
-       this_module = oberon_define_object(ctx -> decl, name1, OBERON_CLASS_MODULE);
+       this_module = oberon_define_object(ctx -> decl, name1, OBERON_CLASS_MODULE, 0, 0);
        this_module -> module = ctx -> mod;
 
        if(ctx -> token == IMPORT)
@@ -2409,13 +2434,12 @@ oberon_parse_module(oberon_context_t * ctx)
        oberon_decl_seq(ctx);
 
        oberon_generate_begin_module(ctx);
-
        if(ctx -> token == BEGIN)
        {
                oberon_assert_token(ctx, BEGIN);
                oberon_statement_seq(ctx);
-               oberon_generate_end_module(ctx);
        }
+       oberon_generate_end_module(ctx);
 
        oberon_assert_token(ctx, END);
        name2 = oberon_assert_ident(ctx);
@@ -2442,17 +2466,17 @@ register_default_types(oberon_context_t * ctx)
        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);
+       oberon_define_type(ctx -> world_scope, "INTEGER", ctx -> int_type, 1);
 
        ctx -> bool_type = oberon_new_type_boolean(sizeof(int));
-       oberon_define_type(ctx -> world_scope, "BOOLEAN", ctx -> bool_type);
+       oberon_define_type(ctx -> world_scope, "BOOLEAN", ctx -> bool_type, 1);
 }
 
 static void
 oberon_new_intrinsic(oberon_context_t * ctx, char * name, GenerateFuncCallback f, GenerateProcCallback p)
 {
        oberon_object_t * proc;
-       proc = oberon_define_object(ctx -> decl, name, OBERON_CLASS_PROC);
+       proc = oberon_define_object(ctx -> decl, name, OBERON_CLASS_PROC, 1, 0);
        proc -> sysproc = 1;
        proc -> genfunc = f;
        proc -> genproc = p;