private bool AddMethodToCache(SmallType pType, MethodSyntax pMethod, out MethodDefinition pDefinition) { //Check for duplicate method definitions Compiler.FindResult found; if (pMethod.SyntaxType == SyntaxType.Method) { found = _unit.MethodExists(pType, pMethod); } else if (pMethod.SyntaxType == SyntaxType.CastDefinition) { found = _unit.CastExists(pType, pMethod.Type, out MethodDefinition pDef); } else { throw new InvalidOperationException("Unknown method type " + pMethod.SyntaxType.ToString()); } if (found != Compiler.FindResult.NotFound) { if (pMethod.SyntaxType == SyntaxType.Method) { CompilerErrors.MethodDuplicate(pMethod, pMethod.Span); } else if (pMethod.SyntaxType == SyntaxType.CastDefinition) { CompilerErrors.CastDuplicate(pMethod.Parameters[0].Type, pMethod.Type, pMethod.Span); } pDefinition = default; return(false); } else { //Create the tuple type if we are returning more than one value from a method //This will cache it in our SmallTypeCache so it can be found later if (pMethod.ReturnValues.Count > 1) { SmallTypeCache.GetOrCreateTuple(SyntaxHelper.SelectNodeTypes(pMethod.ReturnValues)); } //Set method and return types foreach (var p in pMethod.Parameters) { _unit.FromString(p.TypeNode, out SmallType t); p.TypeNode.SetType(t); } foreach (var r in pMethod.ReturnValues) { _unit.FromString(r, out SmallType t); r.SetType(t); } //Add method pDefinition = _unit.AddMethod(pType, pMethod); return(true); } }
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); }