From: DeaDDooMER Date: Fri, 4 Aug 2017 16:23:43 +0000 (+0300) Subject: Добавлен оператор IN X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=b7a2685d39da39f69ee4530dda2ec5977159dc0c;p=dsw-obn.git Добавлен оператор IN --- diff --git a/notes b/notes index 29121d6..705055e 100644 --- a/notes +++ b/notes @@ -1,4 +1,3 @@ -- Нет оператора IN - Нет конструкции CASE - Нет конструкции WITH diff --git a/src/backends/jvm/generator-jvm.c b/src/backends/jvm/generator-jvm.c index fe8bc00..03b29f8 100644 --- a/src/backends/jvm/generator-jvm.c +++ b/src/backends/jvm/generator-jvm.c @@ -1778,6 +1778,34 @@ jvm_generate_range(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b) /* TODO free registers */ } +static void +jvm_generate_in(gen_proc_t * p, oberon_expr_t * a, oberon_expr_t * b) +{ + oberon_type_t * t = a -> result; + int cell_size = jvm_cell_size_for_type(t); + char prefix = jvm_get_prefix(t); + int label_else = jvm_new_label_id(p); + int label_end = jvm_new_label_id(p); + + jvm_generate_push_int_size(p, 1, t -> size); + push_expr(p, a); + jvm_generate(p, 2 * cell_size, cell_size, "%cshl", prefix); + push_expr(p, b); + jvm_generate(p, 2 * cell_size, cell_size, "%cand", prefix); + + if(cell_size > 1) + { + jvm_generate(p, cell_size, 0, "lcmp"); + } + + jvm_generate(p, 1, 0, "ifeq L%i", label_else); + jvm_generate(p, 0, 1, "iconst_1"); + jvm_generate(p, 0, 0, "goto L%i", label_end); + jvm_generate_label(p, label_else); + jvm_generate(p, 0, 1, "iconst_0"); + jvm_generate_label(p, label_end); +} + static void push_operator(gen_proc_t * p, oberon_oper_t * oper) { @@ -1835,6 +1863,9 @@ push_operator(gen_proc_t * p, oberon_oper_t * oper) case OP_RANGE: jvm_generate_range(p, oper -> left, oper -> right); break; + case OP_IN: + jvm_generate_in(p, oper -> left, oper -> right); + break; default: gen_error("push_oper: unk op %i", op); break; diff --git a/src/oberon-internals.h b/src/oberon-internals.h index 96fd166..3963146 100644 --- a/src/oberon-internals.h +++ b/src/oberon-internals.h @@ -211,7 +211,8 @@ enum oberon_operator_kind OP_INTERSECTION, OP_DIFFERENCE, OP_SYM_DIFFERENCE, - OP_COMPLEMENTATION + OP_COMPLEMENTATION, + OP_IN }; struct oberon_item_t diff --git a/src/oberon.c b/src/oberon.c index 5042964..38e24a8 100644 --- a/src/oberon.c +++ b/src/oberon.c @@ -1814,7 +1814,22 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_ oberon_type_t * result; bool error = false; - if(token == IS) + if(token == IN) + { + if(a -> result -> class != OBERON_TYPE_INTEGER) + { + oberon_error(ctx, "must be integer"); + } + + if(b -> result -> class != OBERON_TYPE_SET) + { + oberon_error(ctx, "must be set"); + } + + result = ctx -> bool_type; + expr = oberon_new_operator(OP_IN, result, a, b); + } + else if(token == IS) { oberon_type_t * v = a -> result; if(v -> class == OBERON_TYPE_POINTER) diff --git a/src/test.c b/src/test.c index 9279c33..25497b0 100644 --- a/src/test.c +++ b/src/test.c @@ -9,11 +9,13 @@ static char source_test[] = "MODULE Test;" "IMPORT Out;" "" - "VAR" - " s0 : SET;" - "" "BEGIN" - " s0 := -{ 1, 3..6 } + { 3, 4, 10 };" + " Out.Open;" + " IF 8 IN { 2, 3, 7..10 } THEN" + " Out.String('Yes'); Out.Ln;" + " ELSE" + " Out.String('No'); Out.Ln;" + " END;" "END Test." ;