예제 #1
0
 protected void VisitList(AstNode list)
 {
     try
     {
         while (list != null)
         {
             list.Accept(this);
             list = list.GetNext();
         }
     }
     catch (System.SystemException sysException)
     {
         System.Console.WriteLine("Compiler bug near {0}", list.GetPosition().ToString());
         System.Console.WriteLine(sysException.ToString());
         System.Console.WriteLine(sysException.StackTrace);
         System.Environment.Exit(-1);
     }
 }
예제 #2
0
        public Structure ExtractClass(AstNode where, ScopeMember member)
        {
            // Make sure its a structure or type group.
            if(!member.IsClass() && !member.IsStructure() &&!member.IsInternal() &&
                !member.IsTypeGroup())
                Error(where, "coudn't load runtime class.");

            // Read the type group.
            if(member.IsTypeGroup())
            {
                TypeGroup group = (TypeGroup)member;
                Structure building = group.GetDefaultType();
                if(building == null)
                    Error(where, "unexpected type group {0}", @group.GetDisplayName());

                // Prevent ambiguity of merged type group.
                building.CheckAmbiguity(where.GetPosition());
                return building;
            }

            return (Structure)member;
        }
예제 #3
0
 protected LexicalScope CreateLexicalScope(AstNode where, Function parentFunction)
 {
     LexicalScope ret = new LexicalScope(currentContainer, parentFunction);
     ret.Position = where.GetPosition();
     return ret;
 }
예제 #4
0
        public IChelaType ExtractActualType(AstNode where, IChelaType type)
        {
            // Extract from the meta type.
            if(!type.IsMetaType())
                Error(where, "expected a type.");
            type = ExtractMetaType(type);

            // Use the default element from the type group.
            if(type.IsTypeGroup())
            {
                TypeGroup group = (TypeGroup)type;
                Structure building = group.GetDefaultType();
                type = building;
                if(building == null)
                    Error(where, "unexpected type group {0}", @group.GetDisplayName());

                // Prevent ambiguity of merged type group.
                building.CheckAmbiguity(where.GetPosition());
            }
            return type;
        }
예제 #5
0
 protected void Warning(AstNode where, string what)
 {
     System.Console.Error.Write(where.GetPosition().ToString() +
                                ": warning: " + what + "\n");
 }
예제 #6
0
 protected void VisitList(AstNode list)
 {
     try
     {
         while(list != null)
         {
             list.Accept(this);
             list = list.GetNext();
         }
     }
     catch(System.SystemException sysException)
     {
         System.Console.WriteLine("Compiler bug near {0}", list.GetPosition().ToString());
         System.Console.WriteLine(sysException.ToString());
         System.Console.WriteLine(sysException.StackTrace);
         System.Environment.Exit(-1);
     }
 }
예제 #7
0
 protected void Error(AstNode where, string what)
 {
     throw new CompilerException(what, where.GetPosition());
 }
예제 #8
0
 protected void Warning(AstNode where, string what)
 {
     System.Console.Error.Write(where.GetPosition().ToString() +
                                ": warning: " + what + "\n");
 }
예제 #9
0
 protected void Error(AstNode where, string what)
 {
     throw new CompilerException(what, where.GetPosition());
 }
예제 #10
0
        private void CreateSimplifiedEventFunction(AstNode node, EventVariable eventVariable, FunctionType functionType, bool isAdd)
        {
            // Create the function name.
            string functionName = (isAdd ? "add_" : "remove_") + eventVariable.GetName();

            // Create the function.
            Function function;
            if(functionType.GetArgumentCount() > 1)
                function = new Method(functionName, eventVariable.GetFlags(), currentContainer);
            else
                function = new Function(functionName, eventVariable.GetFlags(), currentContainer);

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

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

            // Store the function in the event.
            if(isAdd)
                eventVariable.AddModifier = function;
            else
                eventVariable.RemoveModifier = function;

            // Store the function in his container.
            if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface())
            {
                Structure building = (Structure)currentContainer;
                building.AddFunction(functionName, function);
            }
            else if(currentContainer.IsNamespace())
            {
                Namespace space = (Namespace)currentContainer;
                space.AddMember(function);
            }
            else
            {
                Error(node, "an event cannot be declared here.");
            }
        }
예제 #11
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;
        }