private static void interpretVariableTemplateMatching( PatternWithDecoration patternWithDecoration, InterpretationContext context, InterpretationResult interpretationResult, bool multiMatch = false ) { Debug.Assert(patternWithDecoration.decoration.type == Decoration.EnumType.VARIABLETEMPLATEMATCHING); // just debug-assert because it has to be hardly checked by the dispatching logic vmAssert(patternWithDecoration.isBranch, true, "Must be branch!"); vmAssert(patternWithDecoration.referenced.Length >= 1, false, "Must have a pattern to match"); PatternWithDecoration patterToMatch = patternWithDecoration.referenced[0]; // we resolve the variable if it is a variable if (patterToMatch.@is(PatternWithDecoration.EnumType.VARIABLE)) { ulong variableIdToResolve = patterToMatch.variableId; patterToMatch = context.valueByVariable[variableIdToResolve]; } for (int i = 1; i < patternWithDecoration.referenced.Length; i++) { vmAssert(patternWithDecoration.referenced[i].decoration.type == Decoration.EnumType.TUPLE2, true, "Must be tuple2"); Debug.Assert(patternWithDecoration.referenced[i].type == PatternWithDecoration.EnumType.BRANCH); // tuples must be branches, just assert because else it is a bug in the creation of tuple2 Debug.Assert(patternWithDecoration.referenced[i].referenced.Length == 2); // just assert because else it is a bug in the creation of tuple2 PatternWithDecoration templatePattern = patternWithDecoration.referenced[i].referenced[0]; PatternWithDecoration actionPattern = patternWithDecoration.referenced[i].referenced[1]; MatchArguments <Decoration> arguments = new MatchArguments <Decoration>(); IDictionary </*UniqueIdType*/ ulong, PatternWithDecoration> matches = new Dictionary </*UniqueIdType*/ ulong, PatternWithDecoration>(context.valueByVariable); // let it know the current variable assignments bool isSame; arguments.bidirectional = false; arguments.templatePattern = templatePattern; arguments.matchingPattern = patterToMatch; bool isMatching = Matcher <Decoration> .match(arguments, matches, out isSame); if (!isMatching) { continue; } // we are here if it does match // excute body interpretationDispatch(actionPattern, context, interpretationResult); if (!multiMatch) { return; // we return because we don't need to match the other possibilities } } }
// tries to match the 'matchingPattern' to the 'templatePattern' // 'matches' doesn't get reseted on entry, this simplifies iterated(recursive) matching public static bool match(MatchArguments <DecorationType> arguments, IDictionary </*variableId*/ ulong, Pattern <DecorationType> > matches, out bool isSame) { bool innerFnMatchVariable(Pattern <DecorationType> variable, Pattern <DecorationType> toMatch) { // it is possible that the variable is already in the dictionary // if this is the case compare the uniqueId to identify a missmatch if ( matches.ContainsKey(variable.uniqueId) && !Pattern <DecorationType> .deepCompare(toMatch, matches[variable.uniqueId]) ) { return(false); } matches[variable.uniqueId] = toMatch; return(true); } isSame = arguments.templatePattern.uniqueId == arguments.matchingPattern.uniqueId; // OPTIMIZATION if (isSame) { return(true); } else if ( // OPTIMIZATION< we can do this because uniqueId == variableId isSame && arguments.templatePattern.@is(Pattern <DecorationType> .EnumType.VARIABLE) && arguments.matchingPattern.@is(Pattern <DecorationType> .EnumType.VARIABLE) ) { Debug.Assert(arguments.templatePattern.variableId == arguments.matchingPattern.variableId); // verify return(true); } if (arguments.templatePattern.@is(Pattern <DecorationType> .EnumType.DECORATEDVALUE) && arguments.matchingPattern.@is(Pattern <DecorationType> .EnumType.DECORATEDVALUE) ) { bool isEqual = arguments.templatePattern.decoration.checkEqualValue(arguments.matchingPattern.decoration); return(isEqual); } else if ( arguments.templatePattern.@is(Pattern <DecorationType> .EnumType.SYMBOL) && arguments.matchingPattern.@is(Pattern <DecorationType> .EnumType.SYMBOL) ) { return(Pattern <DecorationType> .isSameSymbol(arguments.templatePattern.symbol, arguments.matchingPattern.symbol)); } else if (arguments.templatePattern.@is(Pattern <DecorationType> .EnumType.VARIABLE)) { return(innerFnMatchVariable(arguments.templatePattern, arguments.matchingPattern)); } // we match in the other direction too if the flag is set else if (arguments.bidirectional && arguments.matchingPattern.@is(Pattern <DecorationType> .EnumType.VARIABLE)) { return(innerFnMatchVariable(arguments.matchingPattern, arguments.templatePattern)); } else if (arguments.templatePattern.isBranch && arguments.matchingPattern.isBranch) // recursivly match { if (arguments.templatePattern.referenced.Length != arguments.matchingPattern.referenced.Length) // OPTIMIZATION { return(false); } int numberOfChildren = arguments.templatePattern.referenced.Length; for (int i = 0; i < numberOfChildren; i++) { bool calledIsSame; MatchArguments <DecorationType> calledArguments = new MatchArguments <DecorationType>(); calledArguments.templatePattern = arguments.templatePattern.referenced[i]; calledArguments.matchingPattern = arguments.matchingPattern.referenced[i]; calledArguments.bidirectional = arguments.bidirectional; if (!match(calledArguments, matches, out calledIsSame)) { return(false); } } return(true); } else { // if all possibilities failed we return a missmatch return(false); } }