From 0833fd8741d5215e8e8576fecd1f5a5f5dfc84f6 Mon Sep 17 00:00:00 2001
From: DeaDDooMER <deaddoomer@deadsoftware.ru>
Date: Mon, 24 Jul 2017 22:51:28 +0300
Subject: [PATCH] =?utf8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?=
 =?utf8?q?=D0=BE=20=D1=8D=D0=BA=D1=81=D0=BF=D0=BE=D1=80=D1=82=D0=B8=D1=80?=
 =?utf8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=B1=D1=8A=D0=B5?=
 =?utf8?q?=D0=BA=D1=82=D0=BE=D0=B2=20=D0=B2=20=D0=BC=D0=BE=D0=B4=D1=83?=
 =?utf8?q?=D0=BB=D1=8F=D1=85?=
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

---
 notes           |   2 +-
 oberon.c        | 142 ++++++++++++++++++++++++++----------------------
 oberon.h        |   2 +
 test.c          |  22 ++------
 test/.gitignore |   1 -
 5 files changed, 85 insertions(+), 84 deletions(-)
 delete mode 100644 test/.gitignore

diff --git a/notes b/notes
index 819b45f..e07d89d 100644
--- a/notes
+++ b/notes
@@ -1,4 +1,4 @@
-- нету экспорта объектов (всё доступно для чтения и записи)
+- нету проверки экспорта для чтения
 - нету списков переменных/параметров. (* VAR x, y, z : INTEGER; *)
 - нету комментариев
 
diff --git a/oberon.c b/oberon.c
index e12ee36..817da1a 100644
--- 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;
 
@@ -237,64 +239,24 @@ 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, int read_only)
 {
 	oberon_object_t * id;
-	id = oberon_define_object(scope, name, OBERON_CLASS_TYPE);
+	id = oberon_define_object(scope, name, OBERON_CLASS_TYPE, export, read_only);
 	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_define_var(oberon_scope_t * scope, int class, char * name, oberon_type_t * type, int export, int read_only)
 {
 	oberon_object_t * var;
-	var = oberon_define_object(scope, name, class);
+	var = oberon_define_object(scope, name, class, export, read_only);
 	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 +966,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,16 +1413,53 @@ 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;
+	int export;
+	int read_only;
+	oberon_object_t * x;
+
+	name = oberon_assert_ident(ctx);
+	oberon_def(ctx, &export, &read_only);
+
+	x = oberon_define_object(ctx -> decl, name, class, export, read_only);
+	return x;
+}
+
+static void
+oberon_var_decl(oberon_context_t * ctx)
+{
+	oberon_object_t * var;
 	oberon_type_t * type;
 	type = oberon_new_type_ptr(OBERON_TYPE_VOID);
 
-	name = oberon_assert_ident(ctx);
+	var = oberon_ident_def(ctx, OBERON_CLASS_VAR);
 	oberon_assert_token(ctx, COLON);
 	oberon_type(ctx, &type);
-	oberon_define_var(ctx -> decl, OBERON_CLASS_VAR, name, type);
+	var -> type = type;
 }
 
 static oberon_object_t *
@@ -1465,11 +1469,11 @@ oberon_make_param(oberon_context_t * ctx, int token, char * name, oberon_type_t
 
 	if(token == VAR)
 	{
-		param = oberon_define_var(ctx -> decl, OBERON_CLASS_VAR_PARAM, name, type);
+		param = oberon_define_var(ctx -> decl, OBERON_CLASS_VAR_PARAM, name, type, 0, 0);
 	}
 	else if(token == IDENT)
 	{
-		param = oberon_define_var(ctx -> decl, OBERON_CLASS_PARAM, name, type);
+		param = oberon_define_var(ctx -> decl, OBERON_CLASS_PARAM, name, type, 0, 0);
 	}
 	else
 	{
@@ -1662,7 +1666,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 +1700,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 +1727,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;
 }
 
@@ -1783,7 +1792,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);
 	}
 
@@ -1892,13 +1901,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 +1925,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 +2363,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 +2411,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 +2424,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 +2456,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, 0);
 
 	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, 0);
 }
 
 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;
diff --git a/oberon.h b/oberon.h
index 9956fdc..86f95de 100644
--- a/oberon.h
+++ b/oberon.h
@@ -157,6 +157,8 @@ struct oberon_object_s
 {
 	char * name;
 	int class;
+	int export;
+	int read_only;
 
 	int local;
 	int linked;
diff --git a/test.c b/test.c
index 297da8d..5b2fc48 100644
--- a/test.c
+++ b/test.c
@@ -7,33 +7,19 @@
 static char source_test[] =
 	"MODULE Test;"
 	"IMPORT I := Imported;"
-	"TYPE"
-	"	Callback = PROCEDURE() : INTEGER;"
-	""
 	"VAR"
-	"	cb : Callback;"
-	"	i : INTEGER;"
-	"	r : I.Rider;"
-	""
-	"PROCEDURE RelBack;"
+	"  x : I.Rider;"
 	"BEGIN"
-	"	i := 666;"
-	"END RelBack;"
-	""
-	"BEGIN;"
-	"	i := ABS(-1);"
-	"	i := cb();"
-	"	RelBack;"
-	"	I.Ln;"
+	"  I.Ln;"
 	"END Test."
 ;
 
 static char source_imported[] =
 	"MODULE Imported;"
 	"TYPE"
-	"	Rider = RECORD i : INTEGER; END;"
+	"	Rider* = RECORD i : INTEGER; END;"
 	""
-	"PROCEDURE Ln;"
+	"PROCEDURE Ln*;"
 	"END Ln;"
 	""
 	"BEGIN;"
diff --git a/test/.gitignore b/test/.gitignore
deleted file mode 100644
index 345e6ae..0000000
--- a/test/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-Test
-- 
2.29.2