Пример #1
0
        public override AstNode Visit(MemberAccess node)
        {
            // Evaluate the base reference.
            Expression baseReference = node.GetReference();
            baseReference.SetHints(node.Hints);
            baseReference.Accept(this);

            // Get the base reference type.
            IChelaType baseRefType = baseReference.GetNodeType();
            if(baseRefType.IsConstant())
                baseRefType = DeConstType(baseRefType);

            // Set a default coercion type.
            node.SetCoercionType(baseRefType);

            // Get the scope.
            Scope scope = null;
            bool canStatic = true;
            bool canNoStatic = node.HasHints(Expression.MemberHint);
            bool suppressVirtual = false;
            bool implicitThis = false;
            if(baseRefType.IsMetaType())
            {
                // Read the base reference type.
                baseRefType = ExtractActualType(node, baseRefType);

                // Handle incomplete types.
                if(baseRefType.IsIncompleteType())
                {
                    node.SetNodeType(baseRefType);
                    return node;
                }

                // Handle built-in types
                if(!baseRefType.IsStructure() && !baseRefType.IsClass() && !baseRefType.IsInterface())
                {
                    baseRefType = currentModule.GetAssociatedClass(baseRefType);
                    if(baseRefType == null)
                        Error(node, "expected a known type.");
                }

                scope = (Scope) baseRefType;
                suppressVirtual = true;

                // Get the current container scope.
                Scope contScope = currentScope;
                while(contScope != null && (contScope.IsPseudoScope() || contScope.IsFunction() || contScope.IsLexicalScope()))
                    contScope = contScope.GetParentScope();

                // Check if the base type is a base of me.
                Structure building = contScope as Structure;
                if(building != null)
                {
                    Structure scopeBuilding = (Structure) baseRefType;
                    if(building.IsDerivedFrom(scopeBuilding))
                    {
                        canNoStatic = true;
                        implicitThis = true;
                    }
                }
            }
            else if(baseRefType.IsNamespace())
            {
                scope = (Namespace) baseReference.GetNodeValue();
            }
            else if(baseRefType.IsReference())
            {
                canStatic = false;
                canNoStatic = true;

                // Get the variable referenced type.
                ReferenceType refType = (ReferenceType)baseRefType;
                IChelaType objectType = refType.GetReferencedType();

                if(objectType.IsReference())
                {
                    // Set the variable type as the coercion type.
                    node.SetCoercionType(objectType);

                    // Dereference.
                    refType = (ReferenceType)objectType;
                    objectType = refType.GetReferencedType();
                }
                else if(objectType.IsStructure())
                {
                    // Use the structure type as the coercion type.
                    node.SetCoercionType(objectType);
                }
                else if(objectType.IsPrimitive() || objectType.IsVector() ||
                        objectType.IsPlaceHolderType())
                {
                    node.SetCoercionType(objectType);
                }

                if(objectType.IsStructure() || objectType.IsClass() || objectType.IsInterface() ||
                    objectType.IsTypeInstance())
                    scope = (Scope)objectType;
                else if(objectType.IsPlaceHolderType())
                    scope = new PseudoScope((PlaceHolderType)objectType);
                else
                {
                    scope = currentModule.GetAssociatedClass(objectType);
                    if(scope == null)
                        Error(node, "unimplemented primitive type classes.");
                }
            }
            else if(baseRefType.IsStructure())
            {
                canStatic = false;
                canNoStatic = true;
                scope = (Scope)baseRefType;
            }
            else if(baseRefType.IsPrimitive())
            {
                canStatic = false;
                canNoStatic = true;
                scope = currentModule.GetAssociatedClass(baseRefType);
                if(scope == null)
                    Error(node, "unimplemented primitive type classes.");
            }
            else if(baseRefType.IsVector())
            {
                canStatic = false;
                canNoStatic = true;
                scope = currentModule.GetAssociatedClass(baseRefType);
                if(scope == null)
                    Error(node, "unimplemented vector type classes.");
            }
            else if(baseRefType.IsPlaceHolderType())
            {
                canStatic = false;
                canNoStatic = true;
                scope = new PseudoScope((PlaceHolderType)baseRefType);
            }
            else
            {
                Error(node, "expected reference, namespace, struct, class, primitive, vector.");
            }

            // Check vectorial swizzle.
            IChelaType coercionType = node.GetCoercionType();
            if(coercionType.IsVector())
            {
                VectorType vectorType = (VectorType)coercionType;
                int minSize = 0;
                int mask = 0;
                string fieldName = node.GetName();
                if(fieldName.Length <= 4)
                {
                    // It can be a vectorial swizzle
                    bool isSwizzle = true;
                    for(int i = 0; i < fieldName.Length; ++i)
                    {
                        switch(fieldName[i])
                        {
                        case 'x':
                        case 'r':
                        case 's':
                            mask |= 0<<(2*i);
                            if(minSize < 1)
                                minSize = 1;
                            break;
                        case 'y':
                        case 'g':
                        case 't':
                            mask |= 1<<(2*i);
                            if(minSize < 2)
                                minSize = 2;
                            break;
                        case 'z':
                        case 'b':
                        case 'p':
                            mask |= 2<<(2*i);
                            if(minSize < 3)
                                minSize = 3;
                            break;
                        case 'w':
                        case 'a':
                        case 'q':
                            mask |= 3<<(2*i);
                            if(minSize < 4)
                                minSize = 4;
                            break;
                        default:
                            i = fieldName.Length + 1;
                            isSwizzle = false;
                            break;
                        }
                    }

                    // Swizzle found.
                    if(isSwizzle)
                    {
                        // Check the validity.
                        if(minSize > vectorType.GetNumComponents())
                            Error(node, "accessing inexistent elements in the vector.");

                        // Store the base variable.
                        Variable baseVar = baseReference.GetNodeValue() as Variable;

                        // Return the swizzle.
                        IChelaType swizzleType = VectorType.Create(vectorType.GetPrimitiveType(), fieldName.Length);
                        SwizzleVariable swizzleVar =
                            new SwizzleVariable(swizzleType, baseVar, (byte)mask, fieldName.Length);
                        node.SetNodeValue(swizzleVar);
                        node.SetNodeType(ReferenceType.Create(swizzleType));
                        return node;
                    }
                }
            }

            // Find the scope member.
            ScopeMember member = scope.FindMemberRecursive(node.GetName());
            if(member == null)
            {
                // Check attribute name.
                if(node.IsAttributeName())
                    member = scope.FindMemberRecursive(node.GetName() + "Attribute");

                if(member == null)
                    Error(node, "couldn't find member '" + node.GetName()
                                + "' in '" + scope.GetFullName() + "'.");
            }

            // Check the accesiblity.
            CheckMemberVisibility(node, member);

            // Return it.
            IChelaType type = null;
            if(member.IsNamespace())
            {
                type = ChelaType.GetNamespaceType();
            }
            else if(member.IsType())
            {
                type = MetaType.Create((IChelaType)member);
            }
            else if(member.IsTypeName())
            {
                // Read the type name.
                TypeNameMember typeName = (TypeNameMember)member;
                type = typeName.GetActualType();

                // Create an incomplete type if necessary.
                if(type == null)
                    type = new IncompleteType(typeName);

                type = MetaType.Create(type);
            }
            else if(member.IsFunctionGroup())
            {
                FunctionGroup fgroup = (FunctionGroup)member;
                FunctionGroupSelector selector = new FunctionGroupSelector(fgroup);
                selector.SuppressVirtual = suppressVirtual;
                selector.ImplicitThis = implicitThis;
                member = selector;
                if(canNoStatic && canStatic)
                    type = ChelaType.GetAnyFunctionGroupType();
                else if(canStatic)
                    type = ChelaType.GetStaticFunctionGroupType();
                else
                    type = ChelaType.GetFunctionGroupType();
            }
            else if(member.IsFunction())
            {
                Function function = (Function)member;
                type = function.GetFunctionType();

                // Check the static flag.
                if(!canNoStatic &&
                   (function.GetFlags() & MemberFlags.InstanceMask) != MemberFlags.Static)
                {
                    Error(node, "expected a static function.");
                }
                else if(function.IsMethod())
                {
                    Method method = (Method)function;
                    node.SetSlot(method.GetVSlot());
                }
            }
            else
            {
                Variable variable = (Variable)member;
                IChelaType variableType = variable.GetVariableType();
                if(variableType.IsPassedByReference())
                    variableType = ReferenceType.Create(variableType); // Required for nested access.
                type = ReferenceType.Create(variableType);

                // Check the static flag.
                if(!canNoStatic && !variable.IsStatic())
                {
                    Error(node, "expected a static variable.");
                }
                else if(variable.IsField())
                {
                    // Use the slot.
                    FieldVariable field = (FieldVariable) variable;
                    node.SetSlot(field.GetSlot());
                }
                else if(variable.IsProperty() && !variable.IsStatic() && suppressVirtual)
                {
                    // Wrap the property in a direct property slot.
                    member = new DirectPropertySlot((PropertyVariable)variable);
                }

                // Store the implicit this property.
                if(!variable.IsStatic())
                    node.ImplicitSelf = implicitThis;
            }

            // Set the value.
            node.SetNodeValue(member);

            // Set the type.
            node.SetNodeType(type);

            return node;
        }
Пример #2
0
 private Function PickFunction(AstNode node, FunctionGroup fgroup, FunctionGroupType groupType,
                               FunctionGroupSelector selector, List<object> arguments)
 {
     return PickFunction(node, fgroup, groupType, selector, arguments, false);
 }
Пример #3
0
        public override AstNode Visit(VariableReference node)
        {
            Scope scope = currentScope;
            IEnumerator<Scope> iterator = scopeStack.GetEnumerator();
            ScopeMember value = null;
            string attrName = null;
            bool typeHint = node.HasHints(Expression.TypeHint);
            bool isTypeGroup = false;
            bool isFunctionGroup = false;
            bool isNamespaceLevel = false;
            int mergedLevels = 0;
            while(scope != null)
            {
                // Find the variable in the scope.
                ScopeMember newValue = scope.FindMemberRecursive(node.GetName());
                bool validValue = CheckTypeHint(newValue, typeHint);

                // Check the attribute name.
                if(newValue == null && node.IsAttributeName())
                {
                    if(attrName == null)
                        attrName = node.GetName() + "Attribute";
                    newValue = scope.FindMemberRecursive(attrName);
                    validValue = CheckTypeHint(newValue, typeHint);
                }

                // Use the value.
                if(validValue)
                {
                    // If the first value its a type group, begin merging.
                    if(value == null)
                    {
                        value = newValue;
                        isTypeGroup = value.IsTypeGroup();
                        isFunctionGroup = value.IsFunctionGroup();

                        // If not merging, found the member.
                        if(!isTypeGroup && !isFunctionGroup)
                            break;
                    }

                    // Check if its a namespace level
                    isNamespaceLevel = isNamespaceLevel || scope.IsPseudoScope();

                    // Found the next level.
                    if(isTypeGroup && newValue.IsTypeGroup())
                    {
                        TypeGroup typeGroup = (TypeGroup)value;
                        TypeGroup newGroup = (TypeGroup)newValue;

                        // Create the merged type group.
                        if(mergedLevels == 0)
                            value = typeGroup.CreateMerged(newGroup, isNamespaceLevel);
                        else
                            typeGroup.AppendLevel(newGroup, isNamespaceLevel);
                    }
                    else if(isFunctionGroup && newValue.IsFunctionGroup())
                    {
                        FunctionGroup functionGroup = (FunctionGroup)value;
                        FunctionGroup newGroup = (FunctionGroup)newValue;

                        // Create the merged function group.
                        if(mergedLevels == 0)
                            value = functionGroup.CreateMerged(newGroup, isNamespaceLevel);
                        else
                            functionGroup.AppendLevel(newGroup, isNamespaceLevel);
                    }

                    // Increase the level count.
                    ++mergedLevels;
                }

                // Increase the scope.
                if(!iterator.MoveNext())
                    break;

                scope = iterator.Current;
            }

            // If the value couldn't be found.
            if(value == null)
                Error(node, "undeclared {0} '{1}'.", typeHint ? "type" : "variable",
                        node.GetName());

            // Check the accesiblity.
            CheckMemberVisibility(node, value);

            // Calculate the type.
            IChelaType type = null;
            if(value.IsType())
            {
                type = MetaType.Create((IChelaType)value);
            }
            else if(value.IsNamespace())
            {
                type = ChelaType.GetNamespaceType();
            }
            else if(value.IsTypeName())
            {
                // Read the type name.
                TypeNameMember typeName = (TypeNameMember)value;
                type = typeName.GetActualType();

                // Create an incomplete type if necessary.
                if(type == null)
                    type = new IncompleteType(typeName);

                type = MetaType.Create(type);
            }
            else if(value.IsVariable())
            {
                Variable variable = (Variable)value;

                // Check for aliases(ref/out parameters).
                IChelaType varType = variable.GetVariableType();
                bool isAliasVariable = false;
                if(varType.IsReference())
                {
                    // De-reference.
                    ReferenceType refType = (ReferenceType)varType;
                    IChelaType referenced = refType.GetReferencedType();
                    if(!referenced.IsPassedByReference() || referenced.IsReference())
                    {
                        // This variable is reference.
                        isAliasVariable = true;
                        type = varType;
                        node.SetAliasVariable(variable);
                        value = new ReferencedSlot(referenced);
                    }
                }

                if(!isAliasVariable)
                    type = ReferenceType.Create(variable.GetVariableType());

                // Special checks for field variables
                if(variable.IsField())
                {
                    FieldVariable field = (FieldVariable) variable;
                    if(!field.IsStatic() && currentFunction.IsStatic())
                        Error(node, "cannot access no static fields without an object.");
                }
            }
            else if(value.IsFunction())
            {
                Function function = (Function)value;
                type = function.GetFunctionType();

                // Special checks for methods.
                if(function.IsMethod())
                {
                    Method method = (Method) function;
                    if(!method.IsStatic() && currentFunction.IsStatic())
                        Error(node, "cannot access no static methods without an object.");
                }
            }
            else if(value.IsFunctionGroup())
            {
                FunctionGroup fgroup = (FunctionGroup)value;
                value = new FunctionGroupSelector(fgroup);

                type = ChelaType.GetStaticFunctionGroupType();

                // Check for implicit this.
                if(!currentFunction.IsStatic())
                {
                    Structure groupScope = fgroup.GetParentScope() as Structure;
                    Structure myScope = currentFunction.GetParentScope() as Structure;
                    if(groupScope != null && myScope != null &&
                        (groupScope == myScope || myScope.IsDerivedFrom(groupScope)))
                        type = ChelaType.GetAnyFunctionGroupType();
                }
            }
            else
                Error(node, "unexpected member type.");

            // Set the value.
            node.SetNodeValue(value);

            // Set the node type.
            node.SetNodeType(type);

            return node;
        }
Пример #4
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);
     }
 }
Пример #5
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);
     }
 }
Пример #6
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);
        }
Пример #7
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;
        }
Пример #8
0
        public override AstNode Visit(IndirectAccess node)
        {
            // Evaluate the base pointer.
            Expression basePointer = node.GetBasePointer();
            basePointer.Accept(this);

            // Get the base pointer type.
            IChelaType pointerType = basePointer.GetNodeType();
            if(pointerType.IsReference())
            {
                // Dereference the variable.
                ReferenceType refType = (ReferenceType) pointerType;
                pointerType = refType.GetReferencedType();
            }

            if(!pointerType.IsPointer())
                Error(node, "expected pointer indirection.");

            // Set the coercion type.
            node.SetCoercionType(pointerType);

            // Get the pointed type.
            PointerType pointer = (PointerType) pointerType;
            IChelaType pointedType = pointer.GetPointedType();

            // Only structure type are supported.
            if(!pointedType.IsStructure())
                Error(node, "only structure indirection is supported.");

            // Cast the structure type.
            Structure structType = (Structure) pointedType;

            // Check that the structure has the member.
            ScopeMember member = structType.FindMemberRecursive(node.GetName());
            if(member == null)
                Error(node, "couldn't find the member '{0}'.", node.GetName());

            // Check the flags.
            if((member.GetFlags() & MemberFlags.InstanceMask) == MemberFlags.Static)
                Error(node, "cannot use pointer indirectionto access static members.");

            // TODO: Check the access flags.

            // Perform checks depending on the type of the member.
            if(member.IsVariable())
            {
                Variable variable = (Variable) member;
                if(!variable.IsField() && !variable.IsProperty())
                    Error(node, "expected field/property member.");

                IChelaType varType = variable.GetVariableType();
                if(varType.IsStructure())
                    varType = ReferenceType.Create(varType); // Required for nested access.
                node.SetNodeType(ReferenceType.Create(varType));
                node.SetNodeValue(variable);

                if(variable.IsField())
                {
                    FieldVariable field = (FieldVariable) variable;
                    node.SetSlot(field.GetSlot());
                }
            }
            else if(member.IsFunction())
            {
                Function function = (Function) member;
                if(!function.IsMethod())
                    Error(node, "expected a method member.");

                Method method = (Method) function;
                node.SetSlot(method.GetVSlot());
                node.SetNodeType(method.GetFunctionType());
                node.SetNodeValue(method);
            }
            else if(member.IsFunctionGroup())
            {
                FunctionGroup functionGroup = (FunctionGroup)member;
                FunctionGroupSelector selector = new FunctionGroupSelector(functionGroup);
                node.SetNodeType(ChelaType.GetFunctionGroupType());
                node.SetNodeValue(selector);
            }
            else
            {
                Error(node, "expected field or method member.");
            }

            return node;
        }