DEADSOFTWARE

Исправлены выражения с операторами
[dsw-obn.git] / src / oberon.c
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);
        }