diff --git a/src/script_opt/CPP/Exprs.cc b/src/script_opt/CPP/Exprs.cc index c943a14b25..afef3ce3cd 100644 --- a/src/script_opt/CPP/Exprs.cc +++ b/src/script_opt/CPP/Exprs.cc @@ -388,7 +388,26 @@ string CPPCompile::GenIndexExpr(const Expr* e, GenType gt) { string func; if ( aggr_t->Tag() == TYPE_TABLE ) { - func = inside_when ? "when_index_table__CPP" : "index_table__CPP"; + auto ind_expr = e->GetOp2()->AsListExpr()->Exprs()[0]; + auto is_pat_str_ind = false; + + auto& indices = aggr_t->AsTableType()->GetIndices()->GetTypes(); + if ( indices.size() == 1 && indices[0]->Tag() == TYPE_PATTERN && ind_expr->GetType()->Tag() == TYPE_STRING ) + is_pat_str_ind = true; + + if ( inside_when ) { + if ( is_pat_str_ind ) + func = "when_index_patstr__CPP"; + else + func = "when_index_table__CPP"; + } + else { + if ( is_pat_str_ind ) + func = "index_patstr_table__CPP"; + else + func = "index_table__CPP"; + } + gen = func + "(" + GenExpr(aggr, GEN_NATIVE) + ", {" + GenExpr(e->GetOp2(), GEN_VAL_PTR) + "})"; } diff --git a/src/script_opt/CPP/RuntimeOps.cc b/src/script_opt/CPP/RuntimeOps.cc index ea8a81ac86..273b77b315 100644 --- a/src/script_opt/CPP/RuntimeOps.cc +++ b/src/script_opt/CPP/RuntimeOps.cc @@ -44,6 +44,10 @@ ValPtr index_table__CPP(const TableValPtr& t, vector indices) { return v; } +ValPtr index_patstr_table__CPP(const TableValPtr& t, vector indices) { + return t->LookupPattern(indices[0]->AsStringVal()); +} + ValPtr index_vec__CPP(const VectorValPtr& vec, int index) { if ( index < 0 ) index += vec->Size(); @@ -66,6 +70,13 @@ ValPtr when_index_table__CPP(const TableValPtr& t, vector indices) { return v; } +ValPtr when_index_patstr__CPP(const TableValPtr& t, vector indices) { + auto v = index_patstr_table__CPP(t, std::move(indices)); + if ( v && IndexExprWhen::evaluating > 0 ) + IndexExprWhen::results.emplace_back(v); + return v; +} + ValPtr when_index_vec__CPP(const VectorValPtr& vec, int index) { auto v = index_vec__CPP(vec, index); if ( v && IndexExprWhen::evaluating > 0 ) diff --git a/src/script_opt/CPP/RuntimeOps.h b/src/script_opt/CPP/RuntimeOps.h index b35dd2b213..5ef5ba0efa 100644 --- a/src/script_opt/CPP/RuntimeOps.h +++ b/src/script_opt/CPP/RuntimeOps.h @@ -32,13 +32,16 @@ extern ListValPtr index_val__CPP(std::vector indices); // Returns the value corresponding to indexing the given table/vector/string // with the given set of indices. These are functions rather than something // generated directly so that they can package up the error handling for -// the case where there's no such index. +// the case where there's no such index. "patstr" refers to indexing a +// table[pattern] of X with a string value. extern ValPtr index_table__CPP(const TableValPtr& t, std::vector indices); +extern ValPtr index_patstr_table__CPP(const TableValPtr& t, std::vector indices); extern ValPtr index_vec__CPP(const VectorValPtr& vec, int index); extern ValPtr index_string__CPP(const StringValPtr& svp, std::vector indices); // The same, but for indexing happening inside a "when" clause. extern ValPtr when_index_table__CPP(const TableValPtr& t, std::vector indices); +extern ValPtr when_index_patstr__CPP(const TableValPtr& t, std::vector indices); extern ValPtr when_index_vec__CPP(const VectorValPtr& vec, int index); // For vector slices, we use the existing index_slice(), but we need a diff --git a/src/script_opt/ZAM/Expr.cc b/src/script_opt/ZAM/Expr.cc index 854fb6fde5..ea5af97939 100644 --- a/src/script_opt/ZAM/Expr.cc +++ b/src/script_opt/ZAM/Expr.cc @@ -573,6 +573,19 @@ const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, int n2_slot, const T int n = l->Exprs().length(); auto n2tag = n2t->Tag(); + // Whether this is an instance of indexing a table[pattern] of X + // with a string. + bool is_pat_str_ind = false; + + if ( n2tag == TYPE_TABLE && n == 1 ) { + auto& ind_types = n2t->AsTableType()->GetIndices(); + auto& ind_type0 = ind_types->GetTypes()[0]; + auto ind = l->Exprs()[0]; + + if ( ind_type0->Tag() == TYPE_PATTERN && ind->GetType()->Tag() == TYPE_STRING ) + is_pat_str_ind = true; + } + if ( n == 1 && ! in_when ) { auto ind = l->Exprs()[0]; auto var_ind = ind->Tag() == EXPR_NAME; @@ -640,7 +653,8 @@ const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, int n2_slot, const T if ( n2tag == TYPE_TABLE ) { if ( n3 ) { int n3_slot = FrameSlot(n3); - auto zop = AssignmentFlavor(OP_TABLE_INDEX1_VVV, n1->GetType()->Tag()); + auto op = is_pat_str_ind ? OP_TABLE_PATSTR_INDEX1_VVV : OP_TABLE_INDEX1_VVV; + auto zop = AssignmentFlavor(op, n1->GetType()->Tag()); z = ZInstI(zop, Frame1Slot(n1, zop), n2_slot, n3_slot); z.SetType(n3->GetType()); } @@ -648,7 +662,8 @@ const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, int n2_slot, const T else { ASSERT(c3); - auto zop = AssignmentFlavor(OP_TABLE_INDEX1_VVC, n1->GetType()->Tag()); + auto op = is_pat_str_ind ? OP_TABLE_PATSTR_INDEX1_VVC : OP_TABLE_INDEX1_VVC; + auto zop = AssignmentFlavor(op, n1->GetType()->Tag()); z = ZInstI(zop, Frame1Slot(n1, zop), n2_slot, c3); } @@ -674,7 +689,15 @@ const ZAMStmt ZAMCompiler::CompileIndex(const NameExpr* n1, int n2_slot, const T break; case TYPE_TABLE: - op = in_when ? OP_WHEN_TABLE_INDEX_VV : OP_TABLE_INDEX_VV; + if ( in_when ) { + if ( is_pat_str_ind ) + op = OP_WHEN_PATSTR_INDEX_VV; + else + op = OP_WHEN_TABLE_INDEX_VV; + } + else + op = OP_TABLE_INDEX_VV; + z = ZInstI(op, Frame1Slot(n1, op), n2_slot); z.SetType(n1->GetType()); break; diff --git a/src/script_opt/ZAM/Ops.in b/src/script_opt/ZAM/Ops.in index d9acb601cc..87b820177f 100644 --- a/src/script_opt/ZAM/Ops.in +++ b/src/script_opt/ZAM/Ops.in @@ -1057,6 +1057,15 @@ macro EvalTableIndex(index) break; } +internal-op When-PatStr-Index +type VV +eval auto args = z.aux->ToListVal(frame); + auto arg0 = args->Idx(0); + auto v = frame[z.v2].table_val->LookupPattern(arg0->AsStringVal()); + if ( IndexExprWhen::evaluating > 0 ) + IndexExprWhen::results.emplace_back(v); + AssignV1(BuildVal(v, z.t)) + internal-assignment-op Table-Index1 type VVV assign-val v @@ -1068,6 +1077,17 @@ type VVC assign-val v eval EvalTableIndex(z.c.ToVal(z.t)) +# Same, but for indexing table[pattern] of X with a string. +internal-assignment-op Table-PatStr-Index1 +type VVV +assign-val v +eval auto v = frame[z.v2].table_val->LookupPattern(frame[z.v3].AsString()); + +internal-assignment-op Table-PatStr-Index1 +type VVC +assign-val v +eval auto v = frame[z.v2].table_val->LookupPattern(z.c.AsString()); + # This version is for a variable v3. internal-op Index-String type VVV