@@ -610,7 +610,7 @@ class OpEvalImpl {
610610 BlockItrTy patternFail (mlir::Operation* Op, llvm::StringRef ErrMsg,
611611 llvm::ArrayRef<heavy::Value> Irr) {
612612 assert ((isa<MatchOp, MatchPairOp, MatchTailOp, MatchArgsOp,
613- MatchIdOp>(Op)) &&
613+ MatchIdOp, SubpatternOp >(Op)) &&
614614 " Operation must be a pattern matcher" );
615615
616616 mlir::Operation* ParentOp = Op->getParentOp ();
@@ -623,8 +623,9 @@ class OpEvalImpl {
623623 return BlockItrTy ();
624624 }
625625
626+ // Use the SubPatternOp itself as the sentinel for pattern failure.
626627 if (auto SubpatternOp = dyn_cast<heavy::SubpatternOp>(ParentOp))
627- return BlockItrTy ();
628+ return BlockItrTy (SubpatternOp );
628629
629630 assert (isa<heavy::PatternOp>(ParentOp) && " expecting a PatternOp." );
630631
@@ -636,27 +637,36 @@ class OpEvalImpl {
636637 heavy::Value P = Op.getVal ().getValue (Context);
637638 heavy::Value E = getValue (Op.getInput ());
638639 heavy::EnvEntry Entry;
639- if (Symbol* S = dyn_cast<Symbol>(E )) {
640+ if (isIdentifier (E) && isIdentifier (P )) {
640641 // If the symbol is in the environment we can skip
641642 // because it will not match a literal.
642- Entry = Context.Lookup (S);
643- if (Entry)
644- E = Entry.Value ;
643+ heavy::EnvEntry EntryE = Context.Lookup (E);
644+ heavy::EnvEntry EntryP = Context.Lookup (P);
645+ if (EntryE && EntryP && EntryE.Value == EntryP.Value )
646+ return next (Op);
647+ else if (EntryE || EntryP)
648+ return patternFail (Op,
649+ " expecting identifier with identical binding: {1}" , {E, P});
650+ // Unwrap syntax closures.
651+ P = Context.RebuildLiteral (P);
652+ E = Context.RebuildLiteral (E);
645653 }
646- if (equal (P, E))
654+ if (equal (P, E)) {
647655 return next (Op);
648- else
649- return patternFail (Op, " expecting literal" , {P, E});
656+ } else {
657+ Context.setLoc (E.getSourceLocation ());
658+ return patternFail (Op, " expecting literal: {1}" , {E, P});
659+ }
650660 }
651661
652662 BlockItrTy Visit (MatchPairOp Op) {
653663 heavy::Value E = getValue (Op.getInput ());
654664 if (auto * Pair = dyn_cast<heavy::Pair>(E)) {
655- Context.setLoc (E.getSourceLocation ());
656665 setValue (Op.getCar (), Pair->Car );
657666 setValue (Op.getCdr (), Pair->Cdr );
658667 return next (Op);
659668 }
669+ Context.setLoc (E.getSourceLocation ());
660670 return patternFail (Op, " expecting pair" , E);
661671 }
662672
@@ -755,7 +765,7 @@ class OpEvalImpl {
755765
756766 BlockItrTy Visit (SubpatternOp Op) {
757767 heavy::Value E = getValue (Op.getInput ());
758- heavy::Pair* Tail = dyn_cast<heavy::Pair>( getValue (Op.getTail () ));
768+ heavy::Value Tail = getValue (Op.getTail ());
759769
760770 // Match the empty list.
761771 if (isa<heavy::Empty>(E)) {
@@ -775,16 +785,24 @@ class OpEvalImpl {
775785 // stopping when we find tail or a non-pair object.
776786 // Each "pack" should be a list.
777787 while (auto * Pair = dyn_cast<heavy::Pair>(E)) {
778- if (Pair == Tail)
788+ if (E == Tail)
779789 break ;
780790 auto Scope = ValueMapScope (ValueMap);
781791 BlockItrTy Itr = Op.getBody ().front ().begin ();
782792 setValue (BodyArg, Pair->Car );
783- while (Itr != BlockItrTy ())
793+ while (Itr != BlockItrTy () && Itr != BlockItrTy (Op) )
784794 Itr = Visit (&*Itr);
795+ // Check subpattern failure.
796+ if (Itr == BlockItrTy (Op))
797+ break ;
785798 E = Pair->Cdr ;
786799 }
787800
801+ // Fail if E still has junk that is not Tail and
802+ // did not get gobbled up by the subpattern.
803+ if (E != Tail)
804+ return patternFail (Op, " unexpected elements after subpattern" , {E});
805+
788806 return next (Op);
789807 }
790808
@@ -820,7 +838,7 @@ class OpEvalImpl {
820838 if (P == E) {
821839 return next (Op);
822840 }
823- return patternFail (Op, " identifier does not match" , {P, E });
841+ return patternFail (Op, " identifier does not match" , {E, P });
824842 }
825843
826844 BlockItrTy Visit (SyntaxClosureOp Op) {
0 commit comments