DEADSOFTWARE

Исправлены выражения с операторами
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Sun, 30 Jul 2017 14:57:00 +0000 (17:57 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Sun, 30 Jul 2017 14:57:00 +0000 (17:57 +0300)
notes
src/backends/jvm/generator-jvm.c
src/oberon-internals.h
src/oberon.c
src/test.c

diff --git a/notes b/notes
index 79510a02b93db54f93aee3d4508dd2a6391e10d1..7092150dcbbcf53b3179614ba6ea19146adad7ac 100644 (file)
--- 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
-
-- нету счёта строк / столбцов
-- любая ошибка фатальна
index 1225a86a23b4a0f1479b6a8fc0a0265b574a654b..581faf92c302bab84ce601e5087eeb39e480d4ef 100644 (file)
@@ -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;
index b01a1d71958aa8e43cd9a4b10190291b8357802f..5cfaa1313777e98eb45f8fac7a14406ac67cd6c5 100644 (file)
@@ -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;
index 8de42d912fbb0ed03442b54072db6e353316d594..6a74f92c0aad16f6a3b13a6053e3e5b58e145fcc 100644 (file)
@@ -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);
        }
index 2c5fb0462c6cb482a0d66fbd593af3fa4f85f5d8..9fad93d4461223fcc752d5a79e48261711e9709d 100644 (file)
@@ -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."
 ;