From d11b76dfc015306841ed4befae800ba1ed7c765b Mon Sep 17 00:00:00 2001
From: DeaDDooMER <deaddoomer@deadsoftware.ru>
Date: Sun, 30 Jul 2017 17:57:00 +0300
Subject: [PATCH] =?utf8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5?=
 =?utf8?q?=D0=BD=D1=8B=20=D0=B2=D1=8B=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8?=
 =?utf8?q?=D1=8F=20=D1=81=20=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=82=D0=BE?=
 =?utf8?q?=D1=80=D0=B0=D0=BC=D0=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

---
 notes                            | 16 ++++----
 src/backends/jvm/generator-jvm.c | 17 ++++++---
 src/oberon-internals.h           |  2 +-
 src/oberon.c                     | 65 ++++++++++++++++----------------
 src/test.c                       |  9 +++--
 5 files changed, 57 insertions(+), 52 deletions(-)

diff --git a/notes b/notes
index 79510a0..7092150 100644
--- a/notes
+++ b/notes
@@ -7,22 +7,20 @@
 - Нужно изменить передачу информации о вызываемой процедуре в MODE_CALL
    На данный момент конкретная процедура передаётся в поле var, вместо parent
    Что не позволяет делать процедуры-переменные в полях записей, массивах и т.д.
-- Нужны средства создания биндингов. На данный момент реализуемо как заглушки для модулей.
 
-- нужен автокаст int -> real для DIV. Да и вообще каст типов.
 - нет символов и строк
+- не реализовано расширение типа record
+- нету типа set
 
 - нету операторов if, while и т.д.
 
-- нету типа set
+- не реализованы все встроенные функции
 - не реализована свёртка констант
-- не протестированы типы разнных размеров
 
-- не реализовано расширение типа record
-- не реализован автокаст
+- нету счёта строк / столбцов
+- любая ошибка фатальна
+
+- Нужны средства создания биндингов. На данный момент реализуемо как заглушки для модулей.
 - нет проверок переполнения в компилтайме.
     Возможно можно заюзать это:
       https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
-
-- нету счёта строк / столбцов
-- любая ошибка фатальна
diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c
index 1225a86..581faf9 100644
--- a/src/backends/jvm/generator-jvm.c
+++ b/src/backends/jvm/generator-jvm.c
@@ -1342,17 +1342,20 @@ push_item(gen_proc_t * p, oberon_item_t * item)
 			;
 			char postfix = jvm_get_postfix(item -> result);
 			int cell_size = jvm_cell_size_for_postfix(postfix);
-			push_item(p, item -> parent);
+			assert(item -> parent -> is_item);
+			push_item(p, (oberon_item_t *) item -> parent);
 			push_expr(p, item -> args);
 			jvm_generate(p, 1 + 1, cell_size, "%caload", postfix);
 			break;
 		case MODE_FIELD:
-			push_item(p, item -> parent);
+			assert(item -> parent -> is_item);
+			push_item(p, (oberon_item_t *) item -> parent);
 			jvm_generate_load(p, item -> result, item -> var -> gen_var);
 			break;
 		case MODE_DEREF:
 			/* Все объекты в jvm представляются как указатели */
-			push_item(p, item -> parent);
+			assert(item -> parent -> is_item);
+			push_item(p, (oberon_item_t *) item -> parent);
 			break;
 		case MODE_NIL:
 			jvm_generate(p, 0, 1, "aconst_null");
@@ -1364,7 +1367,7 @@ push_item(gen_proc_t * p, oberon_item_t * item)
 			jvm_generate_push_float(p, item -> real, item -> result -> size);
 			break;
 		case MODE_CAST:
-			push_item(p, item -> parent);
+			push_expr(p, item -> parent);
 			jvm_generate_cast_type(p, item -> parent -> result, item -> result);
 			break;
 		default:
@@ -1629,13 +1632,15 @@ store_expr(gen_proc_t * p, oberon_expr_t * dst, oberon_expr_t * src)
 			;
 			char postfix = jvm_get_postfix(src -> result);
 			int cell_size = jvm_cell_size_for_postfix(postfix);
-			push_item(p, item -> parent);
+			assert(item -> parent -> is_item);
+			push_item(p, (oberon_item_t *) item -> parent);
 			push_expr(p, item -> args);
 			push_expr(p, src);
 			jvm_generate(p, 1 + 1 + cell_size, 0, "%castore", postfix);
 			break;
 		case MODE_FIELD:
-			push_item(p, item -> parent);
+			assert(item -> parent -> is_item);
+			push_item(p, (oberon_item_t *) item -> parent);
 			push_expr(p, src);
 			jvm_generate_store(p, src -> result, item -> var -> gen_var);
 			break;
diff --git a/src/oberon-internals.h b/src/oberon-internals.h
index b01a1d7..5cfaa13 100644
--- a/src/oberon-internals.h
+++ b/src/oberon-internals.h
@@ -208,7 +208,7 @@ struct oberon_item_t
 	int boolean;
 	oberon_object_t * var;
 
-	oberon_item_t * parent;
+	oberon_expr_t * parent;
 
 	int num_args;
 	oberon_expr_t * args;
diff --git a/src/oberon.c b/src/oberon.c
index 8de42d9..6a74f92 100644
--- a/src/oberon.c
+++ b/src/oberon.c
@@ -770,10 +770,9 @@ oberon_expr_list(oberon_context_t * ctx, int * num_expr, oberon_expr_t ** first,
 static oberon_expr_t *
 oberon_cast_expr(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t * pref)
 {
-	assert(expr -> is_item);
 	oberon_expr_t * cast;
 	cast = oberon_new_item(MODE_CAST, pref, expr -> read_only);
-	cast -> item.parent = (oberon_item_t *) expr;
+	cast -> item.parent = expr;
 	cast -> next = expr -> next;
 	return cast;
 }
@@ -1068,7 +1067,7 @@ oberno_make_dereferencing(oberon_context_t * ctx, oberon_expr_t * expr)
 
 	oberon_expr_t * selector;
 	selector = oberon_new_item(MODE_DEREF, expr -> result -> base, expr -> read_only);
-	selector -> item.parent = (oberon_item_t *) expr;
+	selector -> item.parent = expr;
 
 	return selector;
 }
@@ -1115,7 +1114,7 @@ oberon_make_array_selector(oberon_context_t * ctx, oberon_expr_t * desig, oberon
 
 	oberon_expr_t * selector;
 	selector = oberon_new_item(MODE_INDEX, base, desig -> read_only);
-	selector -> item.parent = (oberon_item_t *) desig;
+	selector -> item.parent = desig;
 	selector -> item.num_args = 1;
 	selector -> item.args = index;
 
@@ -1162,7 +1161,7 @@ oberon_make_record_selector(oberon_context_t * ctx, oberon_expr_t * expr, char *
 	oberon_expr_t * selector;
 	selector = oberon_new_item(MODE_FIELD, field -> type, read_only);
 	selector -> item.var = field;
-	selector -> item.parent = (oberon_item_t *) expr;
+	selector -> item.parent = expr;
 
 	return selector;
 }
@@ -1412,6 +1411,27 @@ oberon_factor(oberon_context_t * ctx)
 #define ITUSEONLYBOOLEAN(x) \
 	(((x) == OR) || ((x) == AND))
 
+static void
+oberon_autocast_to_real(oberon_context_t * ctx, oberon_expr_t ** e)
+{
+	oberon_expr_t * expr = *e;
+	if(expr -> result -> class == OBERON_TYPE_INTEGER)
+	{
+		if(expr -> result -> size <= ctx -> real_type -> size)
+		{
+			*e = oberon_cast_expr(ctx, expr, ctx -> real_type);
+		}
+		else
+		{
+			*e = oberon_cast_expr(ctx, expr, ctx -> longreal_type);
+		}
+	}
+	else if(expr -> result -> class != OBERON_TYPE_REAL)
+	{
+		oberon_error(ctx, "required numeric type");
+	}
+}
+
 static oberon_expr_t *
 oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_expr_t * b)
 {
@@ -1422,10 +1442,12 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_
 	{
 		if(ITUSEONLYINTEGER(token))
 		{
-			if(a -> result -> class != OBERON_TYPE_INTEGER
-				|| b -> result -> class != OBERON_TYPE_INTEGER)
+			if(a -> result -> class == OBERON_TYPE_INTEGER
+				|| b -> result -> class == OBERON_TYPE_INTEGER
+				|| a -> result -> class == OBERON_TYPE_REAL
+				|| b -> result -> class == OBERON_TYPE_REAL)
 			{
-				oberon_error(ctx, "used only with integer types");
+				oberon_error(ctx, "used only with numeric types");
 			}
 		}
 		else if(ITUSEONLYBOOLEAN(token))
@@ -1437,6 +1459,7 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_
 			}
 		}
 
+		oberon_autocast_binary_op(ctx, &a, &b);
 		result = ctx -> bool_type;
 
 		if(token == EQUAL)
@@ -1478,30 +1501,8 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_
 	}
 	else if(token == SLASH)
 	{
-		if(a -> result -> class != OBERON_TYPE_REAL)
-		{
-			if(a -> result -> class == OBERON_TYPE_INTEGER)
-			{
-				oberon_error(ctx, "TODO cast int -> real");
-			}
-			else
-			{
-				oberon_error(ctx, "operator / requires numeric type");
-			}
-		}
-
-		if(b -> result -> class != OBERON_TYPE_REAL)
-		{
-			if(b -> result -> class == OBERON_TYPE_INTEGER)
-			{
-				oberon_error(ctx, "TODO cast int -> real");
-			}
-			else
-			{
-				oberon_error(ctx, "operator / requires numeric type");
-			}
-		}
-
+		oberon_autocast_to_real(ctx, &a);
+		oberon_autocast_to_real(ctx, &b);
 		oberon_autocast_binary_op(ctx, &a, &b);
 		expr = oberon_new_operator(OP_DIV, a -> result, a, b);
 	}
diff --git a/src/test.c b/src/test.c
index 2c5fb04..9fad93d 100644
--- a/src/test.c
+++ b/src/test.c
@@ -20,13 +20,14 @@ static char source_test[] =
 	"BEGIN"
 	"  Out.Open;"
 	"  byte := 127;"
-	"  int := 666;"
+	"  int := 666 DIV 2;"
 	"  long := int;"
-	"  real := int;"
-	"  longreal := int;"
+	"  real := (4 / 1) - (4 / 3) + (4 / 5) - (4 / 7) + (4 / 9) - (4 / 11) + (4 / 13) - (4 / 15) + (4 / 17);"
+	"  longreal := (4 / 1) - (4 / 3) + (4 / 5) - (4 / 7) + (4 / 9) - (4 / 11) + (4 / 13) - (4 / 15) + (4 / 17);"
 	"  Out.Int(666, 0); Out.Ln;"
 	"  Out.Int(byte, 0); Out.Ln;"
-	"  Out.LongReal(real, 0); Out.Ln;"
+	"  Out.Real(real, 0); Out.Ln;"
+	"  Out.LongReal(longreal, 0); Out.Ln;"
 	"END Test."
 ;
 
-- 
2.29.2