From d11b76dfc015306841ed4befae800ba1ed7c765b Mon Sep 17 00:00:00 2001 From: DeaDDooMER 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