protected override void VisitMethodCallSyntax(MethodCallSyntax pNode) { base.VisitMethodCallSyntax(pNode); //We only care about methods that aren't in the current module if (_module != null || Namespace != null) { System.Diagnostics.Debug.Assert(_module != null || _unit.HasReference(Namespace)); //Get the referenced module var mod = Namespace == null ? _module : _unit.GetReference(Namespace); //Find the method foreach (var m in mod.Module.Methods) { if (IsCalledMethod(m, pNode)) { var rn = new ReferencedNode(m, mod.Cache); if (!MethodNodes.Contains(rn)) { MethodNodes.Add(rn); //Get any type/methods that this method references var mrv = new ModuleReferenceVisitor(mod.Cache, _context, mod); mrv.MethodNodes.Add(rn); mrv.Visit(m); MethodNodes.AddRange(mrv.MethodNodes); TypeNodes.AddRange(mrv.TypeNodes); } } } } }
protected virtual SyntaxNode VisitMethodCallSyntax(MethodCallSyntax pNode) { List <SyntaxNode> arguments = new List <SyntaxNode>(pNode.Arguments.Count); foreach (var a in pNode.Arguments) { arguments.Add(Visit(a)); } return(SyntaxFactory.MethodCall(pNode.Value, arguments)); }
public static bool HasUndefinedCastAsArg(MethodCallSyntax pMethod) { for (int i = 0; i < pMethod.Arguments.Count; i++) { if (pMethod.Arguments[i].Type == SmallTypeCache.Undefined && pMethod.Arguments[i].SyntaxType == SyntaxType.Cast) { return(true); } } return(false); }
protected virtual void VisitMethodCallSyntax(MethodCallSyntax pNode) { var n = Namespace; Namespace = null; using (var t = Store.AddValue <SmallType>("__Type", null)) { foreach (var a in pNode.Arguments) { Visit(a); } } Namespace = n; }
protected override SyntaxNode VisitMethodCallSyntax(MethodCallSyntax pNode) { if (_methodsToPoly.ContainsKey(pNode.Value)) { var method = _unit.MatchMethod(pNode, _methodsToPoly[pNode.Value]); if (method == null) { throw new InvalidOperationException("Unable to find matching method"); } if (TryPolyMethod(method, ref pNode)) { return(pNode); } } return(base.VisitMethodCallSyntax(pNode)); }
protected override void VisitMethodCallSyntax(MethodCallSyntax pNode) { SmallType[] types = SyntaxHelper.SelectNodeTypes(pNode.Arguments); //Current type can be undefined if we have a method call on a type that isn't defined if (CurrentType != SmallTypeCache.Undefined) { var methodFound = SyntaxHelper.FindMethodOnType(out MethodDefinition m, _unit, Namespace, pNode.Value, CurrentType, types); System.Diagnostics.Debug.Assert(methodFound == Compiler.FindResult.Found, "This shouldn't have happened..."); //Method calls are finally validated, set the mangled method name which we will actually call m = m.MakeConcreteDefinition(CurrentType); pNode.SetDefinition(m); } base.VisitMethodCallSyntax(pNode); }
private bool IsCalledMethod(MethodSyntax pMethod, MethodCallSyntax pCall) { if (pMethod.Name != pCall.Value) { return(false); } if (pMethod.Parameters.Count != pCall.Arguments.Count) { return(false); } for (int i = 0; i < pMethod.Parameters.Count; i++) { if (!pMethod.Parameters[i].Type.IsAssignableFrom(pCall.Arguments[i].Type)) { return(false); } } return(true); }
public MethodSyntax MatchMethod(MethodCallSyntax pCallSite, IEnumerable <MethodSyntax> pMethods) { var arguments = Utils.SyntaxHelper.SelectNodeTypes(pCallSite.Arguments); foreach (var m in pMethods) { var parameters = Utils.SyntaxHelper.SelectNodeTypes(m.Parameters); if (arguments.Length == parameters.Length) { bool found = true; for (int i = 0; i < arguments.Length && found; i++) { found = arguments[i].IsAssignableFrom(parameters[i]); } if (found) { return(m); } } } return(null); }
protected override void VisitMethodCallSyntax(MethodCallSyntax pNode) { base.VisitMethodCallSyntax(pNode); SmallType[] types = new SmallType[pNode.Arguments.Count]; for (int i = 0; i < types.Length; i++) { types[i] = pNode.Arguments[i].Type; if (types[i] == SmallTypeCache.NoValue) { CompilerErrors.ExpressionNoValue(pNode.Arguments[i].Span); } } if (SyntaxHelper.HasUndefinedCastAsArg(pNode)) { IList <MethodDefinition> matches = _unit.GetAllMatches(Namespace, pNode.Value, pNode.Arguments.Count); if (matches.Count > 1) { //If multiple matches are found the implicit cast could map to either method, so we can't tell CompilerErrors.InferImplicitCast(pNode.Span); return; } else if (matches.Count == 1) { //Check if we can determine implicit cast type yet for (int j = 0; j < Math.Min(matches[0].ArgumentTypes.Count, pNode.Arguments.Count); j++) { if (SyntaxHelper.IsUndefinedCast(pNode.Arguments[j])) { TrySetImplicitCastType(pNode.Arguments[j], matches[0].ArgumentTypes[j]); types[j] = pNode.Arguments[j].Type; } } } } //Check to ensure this method exists var result = SyntaxHelper.FindMethodOnType(out MethodDefinition m, _unit, Namespace, pNode.Value, CurrentType, types); switch (result) { case Compiler.FindResult.NotFound: CompilerErrors.MethodNotFound(m, Struct, pNode.Value, pNode.Arguments, pNode.Span); return; case Compiler.FindResult.IncorrectScope: CompilerErrors.MethodNotInScope(m, Struct, pNode.Value, pNode.Arguments, pNode.Span); return; } for (int i = 0; i < m.ArgumentTypes.Count; i++) { ForceCastLiteral(m.ArgumentTypes[i], pNode.Arguments[i]); } //Poly our method definition to match any generic types m = m.MakeConcreteDefinition(CurrentType); pNode.SetType(m.ReturnType); }
private bool TryPolyMethod(MethodSyntax pMethod, ref MethodCallSyntax pCallSite) { System.Diagnostics.Debug.Assert(pMethod.Parameters.Count == pCallSite.Arguments.Count); //Get name of the new method StringBuilder name = new StringBuilder(pMethod.Name + "!!!"); for (int i = 0; i < pMethod.Parameters.Count; i++) { if (pMethod.Parameters[i].Type.IsTrait) { name.Append(pCallSite.Arguments[i].Type.Name + "_"); } } name = name.Remove(name.Length - 1, 1); //Ensure we haven't polymorphed this method before if (!_polydMethods.ContainsKey(name.ToString())) { List <TypedIdentifierSyntax> parameters = new List <TypedIdentifierSyntax>(pMethod.Parameters.Count); for (int i = 0; i < pMethod.Parameters.Count; i++) { TypedIdentifierSyntax parm; if (pMethod.Parameters[i].Type.IsTrait) { //Ensure the argument implements the proper trait... we haven't done type checking yet if (!pCallSite.Arguments[i].Type.IsAssignableFrom(pMethod.Parameters[i].Type)) { return(false); } parm = SyntaxFactory.TypedIdentifier(SyntaxFactory.Type(pCallSite.Arguments[i].Type.Name), pMethod.Parameters[i].Value); } else { parm = (TypedIdentifierSyntax)Visit(pMethod.Parameters[i]); } parameters.Add(parm); } var method = SyntaxFactory.Method(pMethod.Scope, name.ToString(), pMethod.ReturnValues, parameters, (BlockSyntax)Visit(pMethod.Body)).FromNode(pMethod); var tiv = new Typing.TypeInferenceVisitor(_unit); tiv.Visit(method); _unit.AddMethod(null, method); if (!_polydMethods.ContainsKey(name.ToString())) { _polydMethods.Add(name.ToString(), new List <MethodSyntax>()); } _polydMethods[name.ToString()].Add(method); } //Have the call site point to the new method List <SyntaxNode> arguments = new List <SyntaxNode>(pCallSite.Arguments.Count); foreach (var a in pCallSite.Arguments) { arguments.Add(Visit(a)); } pCallSite = SyntaxFactory.MethodCall(name.ToString(), arguments); return(true); }
public MethodSyntax MatchMethod(MethodCallSyntax pCall, IEnumerable <MethodSyntax> pCandidates) { return(_methods.MatchMethod(pCall, pCandidates)); }