Example #1
0
 public ConstructorInitializer(bool baseCall, AstNode arguments, TokenPosition position)
     : base(position)
 {
     this.baseCall = baseCall;
     this.arguments = arguments;
     this.ctorGroup = null;
 }
Example #2
0
 /// <summary>
 /// Creates a merged group with a level of superior scope.
 /// </summary>
 public FunctionGroup CreateMerged(FunctionGroup firstLevel, bool isNamespace)
 {
     FunctionGroup ret = new FunctionGroupInstance(this);
     ret.mergedGroup = true;
     ret.AppendLevel(this, false);
     ret.AppendLevel(firstLevel, isNamespace);
     return ret;
 }
Example #3
0
 /// <summary>
 /// Appends a function group level, detecting ambiguity for namespace functions.
 /// </summary>
 public void AppendLevel(FunctionGroup level, bool isNamespaceLevel)
 {
     if (levels == null)
     {
         levels = new List <LevelData>();
     }
     levels.Add(new LevelData(level, isNamespaceLevel));
 }
Example #4
0
        /// <summary>
        /// Creates a merged group with a level of superior scope.
        /// </summary>
        public FunctionGroup CreateMerged(FunctionGroup firstLevel, bool isNamespace)
        {
            FunctionGroup ret = new FunctionGroupInstance(this);

            ret.mergedGroup = true;
            ret.AppendLevel(this, false);
            ret.AppendLevel(firstLevel, isNamespace);
            return(ret);
        }
Example #5
0
        internal static void PreloadMember(ChelaModule module, ModuleReader reader, MemberHeader header)
        {
            // Create the temporal event and register it.
            FunctionGroup fgroup = new FunctionGroup(module);

            module.RegisterMember(fgroup);

            // Read the name.
            fgroup.name = module.GetString(header.memberName);

            // Skip the structure elements.
            reader.Skip(header.memberSize);
        }
Example #6
0
        private void AppendLevelContent(FunctionGroup level, bool isNamespaceLevel)
        {
            level.MakeConcrete();
            foreach (FunctionGroupName gname in level.functions)
            {
                // Check if the object belongs to the included namespace level
                bool isNamespace = gname.IsNamespaceLevel || isNamespaceLevel;

                // Read the name data.
                FunctionType type     = gname.GetFunctionType();
                bool         isStatic = gname.IsStatic();

                // Find a similar group.
                FunctionGroupName old = Find(gname);
                if (old == null)
                {
                    FunctionGroupName newName = new FunctionGroupName(type, isStatic);
                    newName.IsNamespaceLevel = isNamespace;
                    newName.SetFunction(gname.GetFunction());
                    functions.Add(newName);
                    continue;
                }

                // Ignore names of lower scopes.
                if (!isNamespace || !old.IsNamespaceLevel)
                {
                    continue;
                }

                // Now the old name is a namespace level, and we are adding another
                // namespace level function, in other words, we have detected an ambiguity.
                Function          oldFunction = old.GetFunction();
                FunctionAmbiguity amb;
                if (!oldFunction.IsAmbiguity())
                {
                    amb = new FunctionAmbiguity(oldFunction.GetName(), oldFunction.GetFlags(), oldFunction.GetParentScope());
                    amb.AddCandidate(oldFunction);
                    old.SetFunction(amb);
                }
                else
                {
                    amb = (FunctionAmbiguity)oldFunction;
                }

                // Add the new function into the ambiguity list.
                amb.AddCandidate(gname.GetFunction());
            }
        }
Example #7
0
        protected static bool RecursiveMerge(ref ScopeMember res, ScopeMember level)
        {
            if (level != null && res != null)
            {
                if (res.IsTypeGroup() && level.IsTypeGroup())
                {
                    // Merge type groups.
                    TypeGroup lower = (TypeGroup)res;
                    TypeGroup next  = (TypeGroup)level;
                    if (!lower.IsMergedGroup())
                    {
                        res = lower.CreateMerged(next, false);
                    }
                    else
                    {
                        lower.AppendLevel(next, false);
                    }
                }
                else if (res.IsFunctionGroup() && level.IsFunctionGroup())
                {
                    // Merge function groups.
                    FunctionGroup lower = (FunctionGroup)res;
                    FunctionGroup next  = (FunctionGroup)level;
                    if (!lower.IsMergedGroup())
                    {
                        res = lower.CreateMerged(next, false);
                    }
                    else
                    {
                        lower.AppendLevel(next, false);
                    }
                }
            }
            else if (res == null)
            {
                // Set the result to the next level.
                res = level;
            }

            return(IsRecursiveContinue(res));
        }
Example #8
0
 public LevelData(FunctionGroup level, bool isNamespaceLevel)
 {
     this.data = level;
     this.isNamespaceLevel = isNamespaceLevel;
 }
Example #9
0
 private Function PickFunction(AstNode node, FunctionGroup fgroup, FunctionGroupType groupType,
                               FunctionGroupSelector selector, Expression arguments)
 {
     if(groupType == ChelaType.GetAnyFunctionGroupType())
     {
         Function ret = PickFunction(node, fgroup, false, selector, arguments, true);
         if(ret != null)
             return ret;
         return PickFunction(node, fgroup, true, selector, arguments, false);
     }
     else if(groupType == ChelaType.GetStaticFunctionGroupType())
     {
         return PickFunction(node, fgroup, true, selector, arguments, false);
     }
     else
     {
         return PickFunction(node, fgroup, false, selector, arguments, false);
     }
 }
Example #10
0
 public LevelData(FunctionGroup level, bool isNamespaceLevel)
 {
     this.data             = level;
     this.isNamespaceLevel = isNamespaceLevel;
 }
Example #11
0
 public void SetConstructorGroup(FunctionGroup ctorGroup)
 {
     this.ctorGroup = ctorGroup;
 }
Example #12
0
 private Function PickFunction(AstNode node, FunctionGroup fgroup, FunctionGroupType groupType,
                               FunctionGroupSelector selector, List<object> arguments, bool forgive)
 {
     if(groupType == ChelaType.GetAnyFunctionGroupType())
     {
         Function ret = PickFunction(node, fgroup, false, selector, arguments, true);
         if(ret != null)
             return ret;
         return PickFunction(node, fgroup, true, selector, arguments, false || forgive);
     }
     else if(groupType == ChelaType.GetStaticFunctionGroupType())
     {
         return PickFunction(node, fgroup, true, selector, arguments, false || forgive);
     }
     else
     {
         return PickFunction(node, fgroup, false, selector, arguments, false || forgive);
     }
 }
Example #13
0
 private Function PickFunction(AstNode node, FunctionGroup fgroup, FunctionGroupType groupType,
                               List<object> arguments)
 {
     return PickFunction(node, fgroup, groupType, null, arguments, false);
 }
Example #14
0
        private Function PickFunction(AstNode node, FunctionGroup fgroup, bool isStatic,
                                      FunctionGroupSelector selector, Expression arguments, bool forgive)
        {
            // Store the arguments in a vector.
            AstNode arg = arguments;
            List<object> argList = new List<object> ();
            while(arg != null)
            {
                argList.Add(arg);
                arg = arg.GetNext();
            }

            return PickFunction(node, fgroup, isStatic, selector, argList, forgive);
        }
Example #15
0
        public override AstNode Visit(FunctionPrototype node)
        {
            MemberFlags callingConvention = node.GetFlags() & MemberFlags.LanguageMask;
            bool isCdecl = callingConvention == MemberFlags.Cdecl;
            bool isUnsafe = (node.GetFlags() & MemberFlags.SecurityMask) == MemberFlags.Unsafe;

            // Use the unsafe scope.
            if(isUnsafe)
                PushUnsafe();

            // Generate a name for explicit contracts.
            if(node.GetNameExpression() != null)
                node.SetName(GenSym());

            // Find an existing group.
            ScopeMember oldGroup = currentContainer.FindMember(node.GetName());
            if(oldGroup != null && (oldGroup.IsType() || !oldGroup.IsFunctionGroup()))
            {
                if(oldGroup.IsFunction() && isCdecl)
                {
                    // TODO: Add additional checks.
                    Function oldDefinition = (Function)oldGroup;
                    node.SetFunction(oldDefinition);
                    node.SetNodeType(oldDefinition.GetFunctionType());
                    oldGroup = null;
                    return node;
                }
                else
                    Error(node, "cannot override something without a function group.");
            }

            FunctionGroup functionGroup = null;
            if(oldGroup != null) // Cast the group member.
                functionGroup = (FunctionGroup)oldGroup;

            // Make sure the destructor name is correct.
            if(node.GetDestructorName() != null)
            {
                // Get the building scope.
                Scope buildingScope = currentScope;
                while(buildingScope != null && (buildingScope.IsFunction() || buildingScope.IsPseudoScope() || buildingScope.IsLexicalScope()))
                    buildingScope = buildingScope.GetParentScope();

                // Make sure we are in a class.
                if(buildingScope == null || !buildingScope.IsClass())
                    Error(node, "only classes can have finalizers.");

                // Make sure the destructor and class name are the same.
                if(node.GetDestructorName() != buildingScope.GetName())
                    Error(node, "finalizers must have the same name as their class.");
            }

            // Read the instance flag.
            MemberFlags instanceFlags = node.GetFlags() & MemberFlags.InstanceMask;

            // Don't allow overloading with cdecl.
            if(isCdecl && functionGroup != null)
                Error(node, "overloading and cdecl are incompatible.");

            // Make sure static constructor doesn't have modifiers.
            if(instanceFlags == MemberFlags.StaticConstructor &&
               node.GetFlags() != MemberFlags.StaticConstructor)
                Error(node, "static constructors cannot have modifiers.");

            // Static constructors cannot have paraemeters.
            if(instanceFlags == MemberFlags.StaticConstructor &&
               node.GetArguments() != null)
                Error(node, "static constructors cannot have parameters.");

            // Add the this argument.
            if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface())
            {
                // Cast the scope.
                Structure building = (Structure)currentContainer;

                // Add the this argument.
                if(instanceFlags != MemberFlags.Static &&
                   instanceFlags != MemberFlags.StaticConstructor)
                {
                    // Instance the building.
                    building = building.GetSelfInstance();

                    // Use the structure type.
                    TypeNode thisType = new TypeNode(TypeKind.Reference, node.GetPosition());
                    thisType.SetOtherType(building);

                    // Create the this argument.
                    FunctionArgument thisArg = new FunctionArgument(thisType, "this",
                                                                    node.GetPosition());

                    // Add to the begin of the argument list.
                    thisArg.SetNext(node.GetArguments());
                    node.SetArguments(thisArg);
                }
            }

            // Parse the generic signature.
            GenericSignature genericSign = node.GetGenericSignature();
            GenericPrototype genProto = null;
            PseudoScope protoScope = null;
            if(genericSign != null)
            {
                // Visit the generic signature.
                genericSign.Accept(this);

                // Create the placeholders scope.
                genProto = genericSign.GetPrototype();
                protoScope = new PseudoScope(currentScope, genProto);
                node.SetScope(protoScope);
            }

            // Use the prototype scope.
            if(protoScope != null)
                PushScope(protoScope);

            // Visit the arguments.
            VisitList(node.GetArguments());

            // Visit the return type.
            Expression returnTypeExpr = node.GetReturnType();
            IChelaType returnType;
            if(returnTypeExpr != null)
            {
                // Don't allow the same name as the container.
                if((currentContainer.IsStructure() || currentContainer.IsClass() ||
                   currentContainer.IsInterface()) &&
                   node.GetName() == currentContainer.GetName())
                    Error(node, "constructors cannot have a return type.");

                returnTypeExpr.Accept(this);
                returnType = returnTypeExpr.GetNodeType();
                returnType = ExtractActualType(returnTypeExpr, returnType);

                // Use references for class/interface.
                if(returnType.IsPassedByReference())
                    returnType = ReferenceType.Create(returnType);
            }
            else if(node.GetDestructorName() != null)
            {
                returnType = ChelaType.GetVoidType();
            }
            else
            {
                returnType = ChelaType.GetVoidType();
                if(!currentContainer.IsStructure() && !currentContainer.IsClass())
                    Error(node, "only classes and structures can have constructors.");

                if(node.GetName() != currentContainer.GetName())
                    Error(node, "constructors must have the same name as their parent.");
            }

            // Restore the prototype scope.
            if(protoScope != null)
                PopScope();

            // Create his function type.
            List<IChelaType> arguments = new List<IChelaType> ();
            bool variableArgs = false;

            // Add the argument types.
            AstNode argNode = node.GetArguments();
            while(argNode != null)
            {
                // Cast the argument node.
                FunctionArgument funArg = (FunctionArgument)argNode;

                // Store the argument type.
                arguments.Add(funArg.GetNodeType());

                // Set the variable argument flags.
                variableArgs = funArg.IsParams();

                // Check the next argument.
                argNode = argNode.GetNext();
            }

            // Set the function type.
            FunctionType type = FunctionType.Create(returnType, arguments,
                                                    variableArgs, callingConvention);
            node.SetNodeType(type);

            // Check the function safetyness.
            if(type.IsUnsafe())
                UnsafeError(node, "safe function with unsafe type.");

            // Avoid collisions.
            if(functionGroup != null)
            {
                Function ambiguos = functionGroup.Find(type, instanceFlags == MemberFlags.Static);
                if(ambiguos != null)
                    Error(node, "adding ambiguous overload for " + ambiguos.GetFullName());
            }

            // Create and add the method into his scope.
            Function function = null;
            if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface())
            {
                // Cast the scope.
                Structure building = (Structure) currentContainer;

                // Create the function according to his instance type.
                if(instanceFlags == MemberFlags.Static ||
                   instanceFlags == MemberFlags.StaticConstructor)
                {
                    function = new Function(node.GetName(), node.GetFlags(), currentContainer);
                }
                else
                {
                    Method method = new Method(node.GetName(), node.GetFlags(), currentContainer);
                    function = method;

                    // Check the constructor initializer.
                    ConstructorInitializer ctorInit = node.GetConstructorInitializer();
                    if(ctorInit == null || ctorInit.IsBaseCall())
                        method.SetCtorLeaf(true);
                }

                // Set the function position.
                function.Position = node.GetPosition();

                // Set the function type.
                function.SetFunctionType(type);

                // Add the function.
                try
                {
                    building.AddFunction(node.GetName(), function);
                }
                catch(ModuleException error)
                {
                    Error(node, error.Message);
                }
            }
            else if(currentContainer.IsNamespace())
            {
                // Create the function.
                function = new Function(node.GetName(), node.GetFlags(), currentContainer);
                function.SetFunctionType(type);

                // Set the function position.
                function.Position = node.GetPosition();

                // Add the method into his namespace.
                Namespace space = (Namespace) currentContainer;

                // Create the function group.
                if(functionGroup == null && !isCdecl)
                {
                    functionGroup = new FunctionGroup(node.GetName(), currentContainer);
                    oldGroup = functionGroup;
                    space.AddMember(functionGroup);
                }

                // Add the function into the function group or the namespace.
                if(!isCdecl)
                    functionGroup.Insert(function);
                else
                    space.AddMember(function);
            }
            else
            {
                Error(node, "a function cannot be added here.");
            }

            // Store the generic prototype.
            if(genProto != null)
                function.SetGenericPrototype(genProto);

            // Set the node function.
            node.SetFunction(function);

            // Check for main function.
            if(function.IsStatic() && function.GetName() == "Main")
                CheckMainCandidate(node, function);

            // Create kernel entry point.
            if(function.IsKernel())
                CreateKernelEntryPoint(node, function);

            // Restore the safety scope.
            if(isUnsafe)
                PopUnsafe();

            return node;
        }
Example #16
0
        private void AppendLevelContent(FunctionGroup level, bool isNamespaceLevel)
        {
            level.MakeConcrete();
            foreach(FunctionGroupName gname in level.functions)
            {
                // Check if the object belongs to the included namespace level
                bool isNamespace = gname.IsNamespaceLevel || isNamespaceLevel;

                // Read the name data.
                FunctionType type = gname.GetFunctionType();
                bool isStatic = gname.IsStatic();

                // Find a similar group.
                FunctionGroupName old = Find(gname);
                if(old == null)
                {
                    FunctionGroupName newName = new FunctionGroupName(type, isStatic);
                    newName.IsNamespaceLevel = isNamespace;
                    newName.SetFunction(gname.GetFunction());
                    functions.Add(newName);
                    continue;
                }

                // Ignore names of lower scopes.
                if(!isNamespace || !old.IsNamespaceLevel)
                    continue;

                // Now the old name is a namespace level, and we are adding another
                // namespace level function, in other words, we have detected an ambiguity.
                Function oldFunction = old.GetFunction();
                FunctionAmbiguity amb;
                if(!oldFunction.IsAmbiguity())
                {
                    amb = new FunctionAmbiguity(oldFunction.GetName(), oldFunction.GetFlags(), oldFunction.GetParentScope());
                    amb.AddCandidate(oldFunction);
                    old.SetFunction(amb);
                }
                else
                {
                    amb = (FunctionAmbiguity)oldFunction;
                }

                // Add the new function into the ambiguity list.
                amb.AddCandidate(gname.GetFunction());
            }
        }
Example #17
0
        internal static void PreloadMember(ChelaModule module, ModuleReader reader, MemberHeader header)
        {
            // Create the temporal event and register it.
            FunctionGroup fgroup = new FunctionGroup(module);
            module.RegisterMember(fgroup);

            // Read the name.
            fgroup.name = module.GetString(header.memberName);

            // Skip the structure elements.
            reader.Skip(header.memberSize);
        }
Example #18
0
 /// <summary>
 /// Appends a function group level, detecting ambiguity for namespace functions.
 /// </summary>
 public void AppendLevel(FunctionGroup level, bool isNamespaceLevel)
 {
     if(levels == null)
         levels = new List<LevelData>();
     levels.Add(new LevelData(level, isNamespaceLevel));
 }
Example #19
0
        private Function PickFunction(AstNode node, FunctionGroup fgroup, bool isStatic,
                                      FunctionGroupSelector selector, List<object> arguments, bool forgive)
        {
            // Count the number of arguments.
            int startIndex = isStatic ? 0 : 1;
            int numargs = startIndex + arguments.Count;

            // Store the generic arguments.
            IChelaType[] genericArguments = null;
            if(selector != null)
                genericArguments = selector.GenericParameters;

            // Select a function in the group.
            List<Function> bestMatches = new List<Function> ();
            int bestCoercions = -1;
            int numfunctions = fgroup.GetFunctionCount();
            bool nonKernelContext = !currentContainer.IsKernel();
            foreach(FunctionGroupName groupName in fgroup.GetFunctions())
            {
                // Only use the same static-ness.
                if(groupName.IsStatic() != isStatic)
                    continue;

                // Get the candidate prototype.
                Function function = groupName.GetFunction();
                FunctionType prototype = groupName.GetFunctionType();

                // Use the kernel entry point when it exists, and calling a kernel from a non-kernel context.
                if(nonKernelContext && function.IsKernel() && function.EntryPoint != null)
                {
                    function = function.EntryPoint;
                    prototype = function.GetFunctionType();
                }

                // Check for generics.
                IChelaType[] genericArgumentsMatched = null;
                GenericPrototype genProto = null;
                if(function != null)
                {
                    genProto = function.GetGenericPrototype();
                    if(genProto.GetPlaceHolderCount() > 0 && genericArguments != null)
                    {
                        // Check if the generic function is matched.
                        if(!CheckGenericArguments(fgroup.GetFunctionCount() == 1 ? node : null,
                                                  genProto, genericArguments))
                            continue;

                        // Matched function, store the arguments and substitute in the prototype
                        genericArgumentsMatched = genericArguments;
                        function = function.InstanceGeneric(new GenericInstance(genProto, genericArguments), currentModule);
                        prototype = function.GetFunctionType();
                    }
                    else if(genProto.GetPlaceHolderCount() > 0)
                    {
                        // Try replacing arguments.
                        genericArgumentsMatched = new IChelaType[genProto.GetPlaceHolderCount()];
                    }
                }

                // TODO: Add variable arguments.
                if(numargs != prototype.GetArgumentCount())
                    continue;

                // Check the arguments.
                int index = startIndex;
                bool match = true;
                int coercions = 0;
                for(int i = 0; i < arguments.Count; ++i)
                {
                    // Get the argument type.
                    object argObject = arguments[i];
                    object argValue = null;
                    AstNode arg = null;
                    IChelaType argExprType = null;
                    if(argObject is IChelaType)
                    {
                        argExprType = (IChelaType)argObject;
                    }
                    else
                    {
                        arg = (AstNode)argObject;
                        argExprType = arg.GetNodeType();
                        argValue = arg.GetNodeValue();
                    }

                    // Get the argument type.
                    IChelaType argType = prototype.GetArgument(index);

                    // Check for reference value.
                    Variable argValueVar = argValue as Variable;
                    bool refValue = argValueVar != null && argValueVar.IsTemporalReferencedSlot();

                    // Reference argument requires exact match.
                    bool cantMatch = false;
                    bool refArg = false;
                    if(argType.IsReference())
                    {
                        IChelaType referencedArg = DeReferenceType(argType);

                        // Check for reference argument.
                        if(!referencedArg.IsPassedByReference() || referencedArg.IsReference())
                        {
                            refArg = true;
                            if(!argExprType.IsReference() || argValueVar == null || !refValue)
                            {
                                cantMatch = true;
                            }
                            else if(argType != argExprType)
                            {
                                // Extract the expression base type.
                                IChelaType exprValueType = DeReferenceType(argExprType);
                                exprValueType = DeConstType(exprValueType);

                                // Check for some type equivalences.
                                IChelaType argValueType = referencedArg;

                                // Check for out-ref differences.
                                if(exprValueType == argValueType)
                                {
                                    // Out-ref difference, so don't match.
                                    cantMatch = true;
                                }
                                else
                                {
                                    // Check primitive-associated pairs.
                                    if(!exprValueType.IsFirstClass() ||
                                        argValueType != currentModule.GetAssociatedClass(exprValueType))
                                    {
                                        if(!argValueType.IsFirstClass() ||
                                            exprValueType != currentModule.GetAssociatedClass(argValueType))
                                            cantMatch = true;
                                    }
                                }
                            }
                        }
                        else if(refValue)
                        {
                            // Ignore not references candidates when the argument is a reference.
                            cantMatch = true;
                        }
                    }
                    else if(refValue)
                    {
                        // Ignore not references candidates when the argument is a reference.
                        cantMatch = true;
                    }

                    // Check coercion.
                    if(argExprType != argType || cantMatch)
                    {
                        int argCoercions = 0;
                        IChelaType coercedArgument = null;

                        // Perform coercion.
                        if(!cantMatch)
                        {
                            if(argType.IsGenericType() && !argType.IsGenericImplicit() && genericArguments == null)
                            {
                                // Perform generic coercion.
                                coercedArgument = GenericCoercion(arg, argType, argExprType,
                                    genProto, genericArgumentsMatched, out argCoercions);
                            }
                            else
                            {
                                // Perform ordinary coercion.
                                if(refArg)
                                    coercedArgument = RefCoerceCounted(arg, argType, argExprType,
                                        argValue, out argCoercions);
                                else
                                    coercedArgument = CoerceCounted(arg, argType, argExprType,
                                        argValue, out argCoercions);
                            }
                        }

                        // Check for coercion success.
                        if(cantMatch || coercedArgument != argType)
                        {
                            // Print early error message.
                            if(numfunctions == 1 && !forgive)
                                Error(node, "cannot implicitly cast argument {0} from {1} to {2}.{3}",
                                    i+1, argExprType.GetDisplayName(), argType.GetDisplayName(), cantMatch ? " Must use ref/out operator." : null);

                            match = false;
                            break;
                        }
                        else
                            coercions += argCoercions;
                    }

                    // Check the next argument.
                    index++;
                }

                // Ignore not matching candidates.
                if(!match)
                    continue;

                // Has at least one match.
                if(bestMatches.Count == 0)
                {
                    bestMatches.Add(function);
                    bestCoercions = coercions;
                    continue;
                }

                // Prefer the candidates with less coercions.
                if(coercions < bestCoercions || bestCoercions < 0)
                {
                    bestMatches.Clear();
                    bestMatches.Add(function);
                    bestCoercions = coercions;
                }
                else if(coercions == bestCoercions)
                {
                    bestMatches.Add(function);
                }
            }

            // Only one function can be the match.
            if(bestMatches.Count == 0 && !forgive)
            {
                string error = "cannot find a matching function for '" + fgroup.GetName() + "'";
                if(fgroup.GetFunctionCount() > 1)
                    error += "\ncandidates are:";
                else
                    error += " the option is:";

                foreach(FunctionGroupName gname in fgroup.GetFunctions())
                {
                    Function function = gname.GetFunction();
                    FunctionType functionType = function.GetFunctionType();
                    if(nonKernelContext && function.IsKernel() && function.EntryPoint != null)
                        functionType = function.EntryPoint.GetFunctionType();
                    error += "\n\t" + functionType.GetDisplayName();
                }

                Error(node, error);
            }
            else if(bestMatches.Count > 1)
            {
                string error = "ambiguous matches for '" + fgroup.GetName() + "'\n"
                                + "candidates are:";
                foreach(Function candidate in bestMatches)
                {
                    error += "\n\t" + candidate.GetFunctionType().GetName();
                }
                Error(node, error);
            }

            // Get the selected function.
            Function matched = null;
            if(bestMatches.Count != 0)
            {
                matched = (Function)bestMatches[0];

                // Prevent ambiguity.
                matched.CheckAmbiguity(node.GetPosition());

                // Perform coercion again, required by delegates.
                FunctionType prototype = matched.GetFunctionType();
                int index = startIndex;
                for(int i = 0; i < arguments.Count; ++i)
                {
                    // Get the argument type.
                    object argObject = arguments[i];
                    if(argObject is IChelaType)
                        continue;

                    // Read the argument data.
                    AstNode arg = (AstNode)argObject;
                    IChelaType argExprType = arg.GetNodeType();
                    object argValue = arg.GetNodeValue();

                    // Perform the coercion again.
                    IChelaType argType = prototype.GetArgument(index);
                    if(argExprType != argType)
                    {
                        int argCoercions = 0;
                        CoerceCounted(arg, argType, argExprType, argValue, out argCoercions);
                    }

                    // Coerce the next argument.
                    index++;
                }
            }

            // Return the matched function.
            return matched;
        }