private void MakeTestExpr(LNode pattern, LNode candidate, out Symbol varArgSym, out LNode varArgCond) { varArgSym = null; varArgCond = null; LNode condition; bool isParams, refExistingVar; var nodeVar = GetSubstitutionVar(pattern, out condition, out isParams, out refExistingVar); int predictedTests = pattern.Attrs.Count + (nodeVar != null ? 0 : pattern.Args.Count) + (!pattern.HasSimpleHeadWithoutPAttrs() ? 1 : 0); if (predictedTests > 1) candidate = MaybePutCandidateInTempVar(candidate.IsCall, candidate); MatchAttributes(pattern, candidate); if (nodeVar != null) { if (nodeVar != __ || condition != null) { if (!refExistingVar) AddVar(nodeVar, isParams, errAt: pattern); if (!isParams) { var assignment = LNode.Call(CodeSymbols.Assign, LNode.List(F.Id(nodeVar), candidate)).SetStyle(NodeStyle.Operator); Tests.Add(LNode.Call(CodeSymbols.Neq, LNode.List(assignment.PlusAttrs(LNode.List(LNode.InParensTrivia)), LNode.Literal(null))).SetStyle(NodeStyle.Operator)); Tests.Add(condition); } } if (isParams) { varArgSym = nodeVar; varArgCond = condition; return; } } else if (pattern.IsId) { Tests.Add(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol) "IsIdNamed"))), LNode.List(LNode.Call(CodeSymbols.Cast, LNode.List(F.Literal(pattern.Name.Name), LNode.Id((Symbol) "Symbol"))).SetStyle(NodeStyle.Operator)))); } else if (pattern.IsLiteral) { if (pattern.Value == null) Tests.Add(LNode.Call(CodeSymbols.Eq, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol) "Value"))), LNode.Literal(null))).SetStyle(NodeStyle.Operator)); else Tests.Add(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(pattern, LNode.Id((Symbol) "Equals"))), LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol) "Value")))))); } else { int? varArgAt; int fixedArgC = GetFixedArgCount(pattern.Args, out varArgAt); var pTarget = pattern.Target; if (pTarget.IsId && !pTarget.HasPAttrs()) { var quoteTarget = QuoteSymbol(pTarget.Name); LNode targetTest; if (varArgAt.HasValue && fixedArgC == 0) targetTest = LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol) "Calls"))), LNode.List(quoteTarget)); else if (varArgAt.HasValue) targetTest = LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol) "CallsMin"))), LNode.List(quoteTarget, F.Literal(fixedArgC))); else targetTest = LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol) "Calls"))), LNode.List(quoteTarget, F.Literal(fixedArgC))); Tests.Add(targetTest); } else { if (fixedArgC == 0) { Tests.Add(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol) "IsCall")))); if (!varArgAt.HasValue) Tests.Add(LNode.Call(CodeSymbols.Eq, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol) "Args"))), LNode.Id((Symbol) "Count"))), LNode.Literal(0))).SetStyle(NodeStyle.Operator)); } else { var op = varArgAt.HasValue ? S.GE : S.Eq; Tests.Add(LNode.Call(op, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol) "Args"))), LNode.Id((Symbol) "Count"))), F.Literal(fixedArgC)))); } int i = Tests.Count; MakeTestExpr(pTarget, LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol) "Target")))); } MakeArgListTests(pattern.Args, ref candidate); } }
internal static bool HasSimpleHeadWPA(LNode self, Pedantics p) { return((p & Pedantics.IgnoreAttributesInOddPlaces) != 0 ? self.HasSimpleHead() : self.HasSimpleHeadWithoutPAttrs()); }
private void MakeTestExpr(LNode pattern, LNode candidate, out Symbol varArgSym, out LNode varArgCond) { varArgSym = null; varArgCond = null; // is this a $substitutionVar? LNode condition; bool isParams, refExistingVar; var nodeVar = DecodeSubstitutionExpr(pattern, out condition, out isParams, out refExistingVar); // Unless the candidate is a simple variable name, avoid repeating // it by creating a temporary variable to hold its value int predictedTests = pattern.Attrs.Count + (nodeVar != null ? 0 : pattern.Args.Count) + (!pattern.HasSimpleHeadWithoutPAttrs() ? 1 : 0); if (predictedTests > 1) { candidate = MaybePutCandidateInTempVar(candidate.IsCall, candidate); } MatchAttributes(pattern, candidate); // Look for @[$(...var)] // case $_ if (nodeVar != null) { if (nodeVar != __ || condition != null) { if (!refExistingVar) { AddVar(nodeVar, isParams, errAt: pattern); } if (!isParams) { var assignment = LNode.Call(CodeSymbols.Assign, LNode.List(F.Id(nodeVar), candidate)).SetStyle(NodeStyle.Operator); Tests.Add(LNode.Call(CodeSymbols.NotEq, LNode.List(assignment.PlusAttrs(LNode.List(LNode.InParensTrivia)), LNode.Literal(null))).SetStyle(NodeStyle.Operator)); Tests.Add(condition); } } if (isParams) { varArgSym = nodeVar; varArgCond = condition; return; } } else if (pattern.IsId) { Tests.Add(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"IsIdNamed"))).SetStyle(NodeStyle.Operator), LNode.List(LNode.Call(CodeSymbols.Cast, LNode.List(F.Literal(pattern.Name.Name), LNode.Id((Symbol)"Symbol"))).SetStyle(NodeStyle.Operator)))); } else if (pattern.IsLiteral) { if (pattern.Value == null) { Tests.Add(LNode.Call(CodeSymbols.Eq, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Value"))).SetStyle(NodeStyle.Operator), LNode.Literal(null))).SetStyle(NodeStyle.Operator)); } else { Tests.Add(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(pattern, LNode.Id((Symbol)"Equals"))).SetStyle(NodeStyle.Operator), LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Value"))).SetStyle(NodeStyle.Operator)))); } } else // call(...) { int?varArgAt; int fixedArgC = GetFixedArgCount(pattern.Args, out varArgAt); // Test if the call target matches var pTarget = pattern.Target; if (pTarget.IsId && !pTarget.HasPAttrs()) { var quoteTarget = QuoteSymbol(pTarget.Name); LNode targetTest; if (varArgAt.HasValue && fixedArgC == 0) { targetTest = LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Calls"))).SetStyle(NodeStyle.Operator), LNode.List(quoteTarget)); } else if (varArgAt.HasValue) { targetTest = LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"CallsMin"))).SetStyle(NodeStyle.Operator), LNode.List(quoteTarget, F.Literal(fixedArgC))); } else { targetTest = LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Calls"))).SetStyle(NodeStyle.Operator), LNode.List(quoteTarget, F.Literal(fixedArgC))); } Tests.Add(targetTest); } else { if (fixedArgC == 0) { Tests.Add(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"IsCall"))).SetStyle(NodeStyle.Operator)); if (!varArgAt.HasValue) { Tests.Add(LNode.Call(CodeSymbols.Eq, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Args"))).SetStyle(NodeStyle.Operator), LNode.Id((Symbol)"Count"))).SetStyle(NodeStyle.Operator), LNode.Literal(0))).SetStyle(NodeStyle.Operator)); } } else { var op = varArgAt.HasValue ? S.GE : S.Eq; Tests.Add(LNode.Call(op, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Args"))).SetStyle(NodeStyle.Operator), LNode.Id((Symbol)"Count"))).SetStyle(NodeStyle.Operator), F.Literal(fixedArgC)))); } int i = Tests.Count; MakeTestExpr(pTarget, LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Target"))).SetStyle(NodeStyle.Operator)); } MakeArgListTests(pattern.Args, ref candidate); } }
internal static bool HasSimpleHeadWPA(LNode self, Pedantics p) { return (p & Pedantics.IgnoreWeirdAttributes) != 0 ? self.HasSimpleHead() : self.HasSimpleHeadWithoutPAttrs(); }