示例#1
0
        public IncompleteType(List <object> vector)
        {
            // Read the type names.
            List <TypeNameMember> incompletes = new List <TypeNameMember> ();

            foreach (object dep in vector)
            {
                TypeNameMember typeName = dep as TypeNameMember;
                if (typeName != null)
                {
                    incompletes.Add(typeName);
                }
                else
                {
                    IncompleteType inc = (IncompleteType)dep;
                    foreach (TypeNameMember incTypeName in inc.Dependencies)
                    {
                        incompletes.Add(incTypeName);
                    }
                }
            }

            // Create the dependencies array.
            deps = incompletes.ToArray();
        }
示例#2
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;
        }
示例#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;
        }