From e225e2736d239ee7c9ef174c85ecfdb2cfa18e24 Mon Sep 17 00:00:00 2001 From: Abegail Jakop Date: Thu, 21 Aug 2014 12:17:40 -0400 Subject: [PATCH] PR12333" array slicing for membership test parse.cxx: accept wildcards in the arrayindex for array_in elaborate.cxx: new function symresolution_info::visit_array_in that skips processing wildcards that are present in the arrayindex translate.cxx: generate code to iterate over the array until a match is found or until the end of the array --- elaborate.cxx | 40 ++++++++++++++++++ elaborate.h | 1 + parse.cxx | 16 ++++++- translate.cxx | 115 ++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 161 insertions(+), 11 deletions(-) diff --git a/elaborate.cxx b/elaborate.cxx index 4ed5a07ce..5eee4ca5b 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2168,6 +2168,46 @@ symresolution_info::visit_arrayindex (arrayindex* e) } } +void +symresolution_info::visit_array_in (array_in* e) +{ + arrayindex* ai = e->operand; + + // Can not settle for calling e->operand->visit(this) as it won't skip + // visiting wildcard symbols. Can not add in the below conditional to + // visit_arrayindex because wildcards aren't supported in all expressions that + // use array indexes. + for (unsigned i=0; iindexes.size(); i++) + if (ai->indexes[i]->tok->type != tok_operator || ai->indexes[i]->tok->content != "*") + ai->indexes[i]->visit (this); + + symbol *array = NULL; + hist_op *hist = NULL; + classify_indexable(ai->base, array, hist); + + if (array) + { + if (array->referent) + return; + + vardecl* d = find_var (array->name, ai->indexes.size (), array->tok); + if (d) + array->referent = d; + else + { + stringstream msg; + msg << _F("unresolved arity-%zu global array %s, missing global declaration?", + ai->indexes.size(), array->name.c_str()); + throw SEMANTIC_ERROR (msg.str(), ai->tok); + } + } + else + { + assert (hist); + hist->visit (this); + } +} + void symresolution_info::visit_functioncall (functioncall* e) diff --git a/elaborate.h b/elaborate.h index a3159bfe4..4b3cd911e 100644 --- a/elaborate.h +++ b/elaborate.h @@ -61,6 +61,7 @@ public: void visit_arrayindex (arrayindex* e); void visit_functioncall (functioncall* e); void visit_delete_statement (delete_statement* s); + void visit_array_in (array_in *e); }; diff --git a/parse.cxx b/parse.cxx index 4da9dc0cd..f16735d2b 100644 --- a/parse.cxx +++ b/parse.cxx @@ -3129,8 +3129,20 @@ parser::parse_array_in () while (1) { - expression* op1 = parse_comparison_or_regex_query (); - indexes.push_back (op1); + t = peek(); + if (t && t->type == tok_operator && t->content == "*" && parenthesized) + { + t = next(); + symbol* sym = new symbol; + sym->tok = t; + sym->name = t->content; + indexes.push_back(sym); + } + else + { + expression* op1 = parse_comparison_or_regex_query (); + indexes.push_back (op1); + } if (parenthesized) { diff --git a/translate.cxx b/translate.cxx index 462745254..b9fdfc44e 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4248,6 +4248,19 @@ c_tmpcounter::visit_array_in (array_in* e) { assert (array->referent != 0); vardecl* r = array->referent; + bool array_slice = false; + + // A boolean result. + tmpvar res = parent->gensym (e->type); + res.declare (*parent); + + for (unsigned i = 0; i < e->operand->indexes.size(); i ++) + if (e->operand->indexes[i]->tok->type == tok_operator + && e->operand->indexes[i]->tok->content == "*") + { + array_slice = true; + break; + } // One temporary per index dimension. for (unsigned i=0; iindex_types.size(); i++) @@ -4257,9 +4270,11 @@ c_tmpcounter::visit_array_in (array_in* e) e->operand->indexes[i]->visit(this); } - // A boolean result. - tmpvar res = parent->gensym (e->type); - res.declare (*parent); + if (array_slice) + { + itervar iv = parent->getiter(array); + parent->o->newline() << iv.declare(); + } } else { @@ -4286,15 +4301,97 @@ c_unparser::visit_array_in (array_in* e) { stmt_expr block(*this); + tmpvar res = gensym (pe_long); vector idx; - load_map_indices (e->operand, idx); - // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; - tmpvar res = gensym (pe_long); - mapvar mvar = getmap (array->referent, e->tok); - c_assign (res, mvar.exists(idx), e->tok); + // determine if the array index contains an asterisk + bool array_slice = false; + for (unsigned i = 0; i < e->operand->indexes.size(); i ++) + if (e->operand->indexes[i]->tok->type == tok_operator + && e->operand->indexes[i]->tok->content == "*") + { + array_slice = true; + break; + } + + if (!array_slice) // checking for membership of a specific element + { + load_map_indices (e->operand, idx); + // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; + + mapvar mvar = getmap (array->referent, e->tok); + c_assign (res, mvar.exists(idx), e->tok); + + o->newline() << res << ";"; + } + else + { + // create tmpvars for the array indexes, storing NULL where there is + // no specific value that the index should be + vector array_slice_vars; + for (unsigned i=0; ioperand->indexes.size(); i++) + { + tmpvar *asvar = new tmpvar(gensym(e->operand->indexes[i]->type)); + if (e->operand->indexes[i]->tok->type == tok_operator + && e->operand->indexes[i]->tok->content == "*") + array_slice_vars.push_back(NULL); + else + { + c_assign (asvar->value(), e->operand->indexes[i], "tmp var"); + array_slice_vars.push_back(asvar); + } + } + + mapvar mvar = getmap (array->referent, e->operand->tok); + itervar iv = getiter(array); + vector idx; + + string ctr = lex_cast (label_counter++); + string toplabel = "top_" + ctr; + string contlabel = "continue_" + ctr; + string breaklabel = "break_" + ctr; + + o->newline() << iv << " = " << iv.start(mvar) << ";"; + c_assign (res, "0", e->tok); // set the default to 0 + + o->newline() << toplabel << ":"; + + o->newline(1) << "if (!(" << iv << "))"; + o->newline(1) << "goto " << breaklabel << ";"; + + // generate code for comparing the keys to the index slice + o->newline(-1) << "if (true"; + for (unsigned i=0; itype() == pe_long) + o->line() << " && " << *array_slice_vars[i] << " == " + << iv.get_key(mvar, array_slice_vars[i]->type(), i); + else if (array_slice_vars[i]->type() == pe_string) + o->line() << " && strncmp(" << *array_slice_vars[i] << ", " + << iv.get_key(mvar, array_slice_vars[i]->type(), i) + << ", MAXSTRINGLEN) == 0"; + else + throw SEMANTIC_ERROR (_("unexpected type"), e->tok); + } + } + o->line() << "){"; + o->indent(1); + // conditional is true, so set res and go to break + c_assign (res, "1", e->tok); + o->newline() << "goto " << breaklabel << ";"; + o->newline(-1) << "}"; + + // else, keep iterating + o->newline() << iv << " = " << iv.next(mvar) << ";"; + o->newline() << "goto " << toplabel << ";"; + + o->newline(-1) << breaklabel<< ":"; + o->newline(1) << "; /* dummy statement */"; + o->newline(-1) << res << ";"; + } - o->newline() << res << ";"; } else { -- 2.43.5