Пример #1
0
        public StructDefinition(MemberFlags flags, string name,
                                GenericSignature genericSignature,
		                        AstNode bases, AstNode children,
                                TokenPosition position)
            : base(children, position)
        {
            SetName(name);
            this.flags = flags;
            this.bases = bases;
            this.genericSignature = genericSignature;
            this.defaultConstructor = null;
            this.genericScope = null;
        }
Пример #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 void SetGenericScope(PseudoScope genericScope)
 {
     this.genericScope = genericScope;
 }
Пример #4
0
        public override AstNode Visit(DelegateDefinition node)
        {
            // Parse the generic signature.
            GenericSignature genericSign = node.GetGenericSignature();
            GenericPrototype genProto = GenericPrototype.Empty;
            PseudoScope protoScope = null;
            if(genericSign != null)
            {
                // Visit the generic signature.
                genericSign.Accept(this);

                // Connect the generic prototype.
                genProto = genericSign.GetPrototype();

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

            // Prevent redefinition.
            ScopeMember old = currentContainer.FindType(node.GetName(), GenericPrototype.Empty);
            if(old != null)
                Error(node, "trying to redefine a delegate.");

            // Create the structure
            MemberFlags flags = node.GetFlags();
            // TODO: Check the flags.
            Class building = new Class(node.GetName(), flags, currentContainer);
            building.SetGenericPrototype(genProto);
            building.Position = node.GetPosition();
            node.SetStructure(building);

            // Add into the current scope.
            if(currentContainer.IsNamespace())
            {
                Namespace space = (Namespace)currentContainer;
                space.AddType(building);
            }
            else if(currentContainer.IsStructure() || currentContainer.IsInterface() || currentContainer.IsClass())
            {
                Structure parent = (Structure)currentContainer;
                parent.AddType(building);
            }
            else
            {
                Error(node, "unexpected place for a delegate.");
            }

            // Register the compute binding delegate.
            if(building.GetFullName() == "Chela.Compute.ComputeBinding")
                currentModule.RegisterComputeBindingDelegate(building);

            return node;
        }
Пример #5
0
        public override AstNode Visit(InterfaceDefinition node)
        {
            // Parse the generic signature.
            GenericSignature genericSign = node.GetGenericSignature();
            GenericPrototype genProto = GenericPrototype.Empty;
            PseudoScope protoScope = null;
            if(genericSign != null)
            {
                // Visit the generic signature.
                genericSign.Accept(this);

                // Connect the generic prototype.
                genProto = genericSign.GetPrototype();

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

            // Prevent redefinition.
            ScopeMember old = currentContainer.FindType(node.GetName(), genProto);
            if(old != null)
                Error(node, "trying to redefine a class.");

            // Create the structure
            Interface iface = new Interface(node.GetName(), node.GetFlags(), currentContainer);
            iface.SetGenericPrototype(genProto);
            node.SetStructure(iface);
            iface.Position = node.GetPosition();

            // Register type maps.
            string fullName = iface.GetFullName();
            IChelaType alias;
            if(typeMaps.TryGetValue(fullName, out alias))
                currentModule.RegisterTypeMap(alias, ReferenceType.Create(iface));

            // Register some important interfaces.
            if(fullName == "Chela.Lang.NumberConstraint")
                currentModule.RegisterNumberConstraint(iface);
            else if(fullName == "Chela.Lang.IntegerConstraint")
                currentModule.RegisterIntegerConstraint(iface);
            else if(fullName == "Chela.Lang.FloatingPointConstraint")
                currentModule.RegisterFloatingPointConstraint(iface);
            else if(fullName == "Chela.Collections.IEnumerable")
                currentModule.RegisterEnumerableIface(iface);
            else if(fullName == "Chela.Collections.IEnumerator")
                currentModule.RegisterEnumeratorIface(iface);
            else if(fullName.StartsWith("Chela.Collections.Generic.IEnumerable<"))
                currentModule.RegisterEnumerableGIface(iface);
            else if(fullName.StartsWith("Chela.Collections.Generic.IEnumerator<"))
                currentModule.RegisterEnumeratorGIface(iface);

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

            // Add into the current scope.
            if(currentContainer.IsNamespace())
            {
                Namespace space = (Namespace)currentContainer;
                space.AddType(iface);
            }
            else if(currentContainer.IsStructure() || currentContainer.IsInterface() || currentContainer.IsClass())
            {
                Structure parent = (Structure)currentContainer;
                parent.AddType(iface);
            }
            else
            {
                Error(node, "unexpected place for a class.");
            }

            // Push the interface unsafe.
            if(iface.IsUnsafe())
                PushUnsafe();

            // Update the scope.
            PushScope(iface);

            // Visit the building children.
            VisitList(node.GetChildren());

            // Restore the scope.
            PopScope();

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

            // Pop the interface unsafe.
            if(iface.IsUnsafe())
                PopUnsafe();

            return node;
        }
Пример #6
0
        public override AstNode Visit(ClassDefinition node)
        {
            // Check the partial flag.
            bool isPartial = (node.GetFlags() & MemberFlags.ImplFlagMask) == MemberFlags.Partial;

            // Add the parent static flag.
            if(currentContainer.IsStatic())
            {
                MemberFlags oldInstance = node.GetFlags() & MemberFlags.InstanceMask;
                if(oldInstance == MemberFlags.Static || oldInstance == MemberFlags.Instanced)
                {
                    MemberFlags flags = node.GetFlags() & ~MemberFlags.InstanceMask;
                    node.SetFlags(flags | MemberFlags.Static);
                }
                else
                    Error(node, "static class member cannot be {0}.", oldInstance.ToString().ToLower());
            }

            // Static classes are automatically sealed.
            if((node.GetFlags() & MemberFlags.InstanceMask) == MemberFlags.Static)
            {
                MemberFlags flags = node.GetFlags() & ~MemberFlags.InheritanceMask;
                node.SetFlags(flags | MemberFlags.Sealed);
            }

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

                // Connect the generic prototype.
                genProto = genericSign.GetPrototype();

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

            // Prevent redefinition.
            ScopeMember old = currentContainer.FindType(node.GetName(), genProto);
            if(old != null && (!isPartial || !old.IsClass()))
                Error(node, "trying to redefine a class.");

            // Create the structure
            Class clazz = (Class)old;
            if(clazz != null)
            {
                if(!clazz.IsPartial())
                    Error(node, "incompatible partial class definitions.");
            }
            else
            {
                clazz = new Class(node.GetName(), node.GetFlags(), currentContainer);
                clazz.Position = node.GetPosition();
                clazz.SetGenericPrototype(genProto);
            }
            node.SetStructure(clazz);

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

            // Register type maps.
            string fullName = clazz.GetFullName();
            IChelaType alias;
            if(typeMaps.TryGetValue(fullName, out alias))
                currentModule.RegisterTypeMap(alias, clazz);

            // Register type association.
            IChelaType assoc;
            if(assocClasses.TryGetValue(fullName, out assoc))
                currentModule.RegisterAssociatedClass(assoc, clazz);

            // Array base class is special.
            if(fullName == "Chela.Lang.Array")
                currentModule.RegisterArrayClass(clazz);
            else if(fullName == "Chela.Lang.Attribute")
                currentModule.RegisterAttributeClass(clazz);
            else if(fullName == "Chela.Lang.ValueType")
                currentModule.RegisterValueTypeClass(clazz);
            else if(fullName == "Chela.Lang.Enum")
                currentModule.RegisterEnumClass(clazz);
            else if(fullName == "Chela.Lang.Type")
                currentModule.RegisterTypeClass(clazz);
            else if(fullName == "Chela.Lang.Delegate")
                currentModule.RegisterDelegateClass(clazz);
            else if(fullName == "Chela.Compute.StreamHolder")
                currentModule.RegisterStreamHolderClass(clazz);
            else if(fullName == "Chela.Compute.StreamHolder1D")
                currentModule.RegisterStreamHolder1DClass(clazz);
            else if(fullName == "Chela.Compute.StreamHolder2D")
                currentModule.RegisterStreamHolder2DClass(clazz);
            else if(fullName == "Chela.Compute.StreamHolder3D")
                currentModule.RegisterStreamHolder3DClass(clazz);
            else if(fullName == "Chela.Compute.UniformHolder")
                currentModule.RegisterUniformHolderClass(clazz);

            // Add into the current scope.
            if(currentContainer.IsNamespace())
            {
                Namespace space = (Namespace)currentContainer;
                if(old == null)
                    space.AddType(clazz);
            }
            else if(currentContainer.IsStructure() || currentContainer.IsInterface() || currentContainer.IsClass())
            {
                Structure parent = (Structure)currentContainer;
                if(old == null)
                    parent.AddType(clazz);
            }
            else
            {
                Error(node, "unexpected place for a class.");
            }

            // Push the class unsafe.
            if(clazz.IsUnsafe())
                PushUnsafe();

            // Update the scope.
            PushScope(clazz);

            // Visit the building children.
            VisitList(node.GetChildren());

            // Restore the scope.
            PopScope();

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

            // Pop the class unsafe.
            if(clazz.IsUnsafe())
                PopUnsafe();

            return node;
        }
Пример #7
0
        public override AstNode Visit(StructDefinition node)
        {
            // Parse the generic signature.
            GenericSignature genericSign = node.GetGenericSignature();
            GenericPrototype genProto = GenericPrototype.Empty;
            PseudoScope protoScope = null;
            if(genericSign != null)
            {
                // Visit the generic signature.
                genericSign.Accept(this);

                // Connect the generic prototype.
                genProto = genericSign.GetPrototype();

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

            // Prevent redefinition.
            ScopeMember old = currentContainer.FindType(node.GetName(), genProto);
            if(old != null)
                Error(node, "trying to redefine a struct.");

            // Create the structure
            Structure building = new Structure(node.GetName(), node.GetFlags(), currentContainer);
            building.SetGenericPrototype(genProto);
            node.SetStructure(building);
            building.Position = node.GetPosition();

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

            // Register type association.
            string fullName = building.GetFullName();
            IChelaType assoc;
            if(assocClasses.TryGetValue(fullName, out assoc))
                currentModule.RegisterAssociatedClass(assoc, building);

            // Add into the current scope.
            if(currentContainer.IsNamespace())
            {
                Namespace space = (Namespace)currentContainer;
                space.AddType(building);
            }
            else if(currentContainer.IsStructure() || currentContainer.IsInterface() || currentContainer.IsClass())
            {
                Structure parent = (Structure)currentContainer;
                parent.AddType(building);
            }
            else
            {
                Error(node, "unexpected place for a structure.");
            }

            // Push the building unsafe.
            if(building.IsUnsafe())
                PushUnsafe();

            // Update the scope.
            PushScope(building);

            // Visit the building children.
            VisitList(node.GetChildren());

            // Restore the scope.
            PopScope();

            // Pop the building unsafe.
            if(building.IsUnsafe())
                PopUnsafe();

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

            return node;
        }
Пример #8
0
        public override AstNode Visit(AliasDeclaration node)
        {
            PseudoScope scope = new PseudoScope(currentScope);

            // Store it in the node.
            node.SetScope(scope);

            // Change the ast layout to reflect the new scope hierarchy.
            node.SetChildren(node.GetNext());
            node.SetNext(null);

            // Update the scope.
            PushScope(node.GetScope());

            // Visit his children.
            VisitList(node.GetChildren());

            // Restore the scope.
            PopScope();

            return node;
        }
Пример #9
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;
        }