From: DeaDDooMER Date: Tue, 1 Aug 2017 14:40:09 +0000 (+0300) Subject: Добавлен ручной каст типов-записей X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=5eab721345c3e472bbfbb97645729069b0b6bb40;p=dsw-obn.git Добавлен ручной каст типов-записей --- diff --git a/notes b/notes index b580745..22d31b0 100644 --- a/notes +++ b/notes @@ -1,5 +1,4 @@ - Нет оператора IS -- Нет ручного каста записей - Нет автокаста записей - Нужно изменить передачу информации о вызываемой процедуре в MODE_CALL На данный момент конкретная процедура передаётся в поле var, вместо parent diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c index d99d1da..8c9d69f 100644 --- a/src/backends/jvm/generator-jvm.c +++ b/src/backends/jvm/generator-jvm.c @@ -1315,19 +1315,27 @@ jvm_generate_expr_new_pointer(gen_proc_t * p, oberon_type_t * type, int num, obe static void jvm_generate_cast_type(gen_proc_t * p, oberon_type_t * from, oberon_type_t * to) { - char prefix = jvm_get_prefix(from); - char postfix = jvm_get_postfix(to); - int from_cell_size = jvm_cell_size_for_type(from); - int to_cell_size = jvm_cell_size_for_type(to); - - jvm_generate_comment(p, "cast type class from %i(%i) to %i(%i)", from -> class, from -> size, to -> class, to -> size); - - if(prefix == postfix) + if(to -> class == OBERON_TYPE_RECORD || to -> class == OBERON_TYPE_POINTER) { - return; + char * full_name = jvm_get_class_full_name(to); + jvm_generate(p, 1, 1, "checkcast %s", full_name); } + else + { + char prefix = jvm_get_prefix(from); + char postfix = jvm_get_postfix(to); + int from_cell_size = jvm_cell_size_for_type(from); + int to_cell_size = jvm_cell_size_for_type(to); - jvm_generate(p, from_cell_size, to_cell_size, "%c2%c", prefix, postfix); + jvm_generate_comment(p, "cast type class from %i(%i) to %i(%i)", from -> class, from -> size, to -> class, to -> size); + + if(prefix == postfix) + { + return; + } + + jvm_generate(p, from_cell_size, to_cell_size, "%c2%c", prefix, postfix); + } } static void diff --git a/src/oberon.c b/src/oberon.c index 0118ff9..6aa94d6 100644 --- a/src/oberon.c +++ b/src/oberon.c @@ -1159,7 +1159,8 @@ oberon_make_record_selector(oberon_context_t * ctx, oberon_expr_t * expr, char * #define ISSELECTOR(x) \ (((x) == LBRACE) \ || ((x) == DOT) \ - || ((x) == UPARROW)) + || ((x) == UPARROW) \ + || ((x) == LPAREN)) static oberon_object_t * oberon_qualident(oberon_context_t * ctx, char ** xname, int check) @@ -1194,6 +1195,18 @@ oberon_qualident(oberon_context_t * ctx, char ** xname, int check) return x; } +static oberon_expr_t * +oberno_make_record_cast(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t * rec) +{ + if(expr -> result -> class != OBERON_TYPE_RECORD + || rec -> class != OBERON_TYPE_RECORD) + { + oberon_error(ctx, "must be record type"); + } + + return oberon_cast_expr(ctx, expr, rec); +} + static oberon_expr_t * oberon_designator(oberon_context_t * ctx) { @@ -1258,6 +1271,16 @@ oberon_designator(oberon_context_t * ctx) oberon_assert_token(ctx, UPARROW); expr = oberno_make_dereferencing(ctx, expr); break; + case LPAREN: + oberon_assert_token(ctx, LPAREN); + oberon_object_t * objtype = oberon_qualident(ctx, NULL, 1); + if(objtype -> class != OBERON_CLASS_TYPE) + { + oberon_error(ctx, "must be type"); + } + oberon_assert_token(ctx, RPAREN); + expr = oberno_make_record_cast(ctx, expr, objtype -> type); + break; default: oberon_error(ctx, "oberon_designator: wat"); break; diff --git a/src/test.c b/src/test.c index 6a08bce..7a449d6 100644 --- a/src/test.c +++ b/src/test.c @@ -19,10 +19,13 @@ static char source_test[] = " END;" "" "VAR" + " baser : Baser;" " r : R1;" + " inv : R2;" "" "BEGIN" " r.a := 1;" + " baser := r(Baser);" "END Test." ;