Ejemplo n.º 1
0
 public ConstantData(FieldVariable variable, Expression initializer)
 {
     this.variable = variable;
     this.initializer = initializer;
     this.dependencies = new List<ConstantData> ();
     this.visited = false;
     this.visiting = false;
 }
Ejemplo n.º 2
0
        public void AddField(FieldVariable field)
        {
            // Store the field.
            fields.Add(field);

            // Register the position filename.
            TokenPosition pos = field.Position;
            if(pos == null)
                pos = NullPosition;
            AddFileName(pos.GetFileName());
        }
Ejemplo n.º 3
0
        public void AddField(FieldVariable field)
        {
            // Store the field.
            fields.Add(field);

            // Register the position filename.
            TokenPosition pos = field.Position;

            if (pos == null)
            {
                pos = NullPosition;
            }
            AddFileName(pos.GetFileName());
        }
Ejemplo n.º 4
0
        private void EmitFieldDebugInfo(ModuleWriter writer, FieldVariable field)
        {
            // Emit the field id.
            uint fieldId = field.GetSerialId();

            writer.Write(fieldId);

            // Emit the field position.
            TokenPosition position = field.Position;

            if (position == null)
            {
                position = NullPosition;
            }
            EmitPosition(writer, position);
        }
Ejemplo n.º 5
0
 public void SetVariable(FieldVariable variable)
 {
     this.variable = variable;
 }
Ejemplo n.º 6
0
 public void CreateLoadFieldRef(FieldVariable field)
 {
     AppendInst1(OpCode.LoadFieldRef, field);
 }
Ejemplo n.º 7
0
 public void CreateStoreField(FieldVariable field)
 {
     AppendInst1(OpCode.StoreField, field);
 }
Ejemplo n.º 8
0
        private void PrepareReturning(AstNode where, Function function, LexicalScope scope)
        {
            // Get the definition node and check for generator.
            FunctionDefinition defNode = function.DefinitionNode;
            bool isGenerator = false;
            if(defNode != null)
                isGenerator = defNode.IsGenerator;

            // Use standard return.
            if(function.GetExceptionContext() == null && !isGenerator)
                return;

            // Create the return block.
            BasicBlock returnBlock = new BasicBlock(function);
            returnBlock.SetName("retBlock");
            function.ReturnBlock = returnBlock;

            // Create the return value local.
            FunctionType functionType = function.GetFunctionType();
            IChelaType retType = functionType.GetReturnType();
            if(retType != ChelaType.GetVoidType() && !isGenerator)
                function.ReturnValueVar = new LocalVariable(GenSym() + "_retval", scope, retType);

            // Create the is returning flag.
            function.ReturningVar = new LocalVariable(GenSym() + "_isret", scope, ChelaType.GetBoolType(), isGenerator);
            function.ReturningVar.Type = LocalType.Return;

            // Create the field for generators.
            if(isGenerator)
            {
                FieldVariable returningField = new FieldVariable("returning", MemberFlags.Private,
                    ChelaType.GetBoolType(), defNode.GeneratorClass);
                defNode.GeneratorClass.AddField(returningField);
                function.ReturningVar.ActualVariable = returningField;
            }

            // Initializer the returning flag to false.
            builder.CreateLoadBool(false);
            PerformAssignment(where, function.ReturningVar);
        }
Ejemplo n.º 9
0
        private void DefineGeneratorBody(FunctionDefinition node)
        {
            // Get entry function.
            Function entryFunction = node.GetFunction();

            // Rebase his locals.
            entryFunction.RebaseLocals();

            // Create the generator class.
            Scope spaceScope = entryFunction.GetParentScope();
            Class generatorClass =
                new Class(GenSym(), MemberFlags.Internal, spaceScope);
            node.GeneratorClass = generatorClass;

            // Use the same generic prototype as the entry point function.
            generatorClass.SetGenericPrototype(entryFunction.GetGenericPrototype());

            // Add the generator class to the same scope as the function.
            if(spaceScope.IsClass() || spaceScope.IsStructure())
            {
                Structure parentClass = (Structure)spaceScope;
                parentClass.AddType(generatorClass);
            }
            else if(spaceScope.IsNamespace())
            {
                Namespace parentSpace = (Namespace)spaceScope;
                parentSpace.AddMember(generatorClass);
            }
            else
            {
                Error(node, "Cannot create generator class in {0}", spaceScope.GetFullName());
            }

            // Add the enumerable interface.
            Structure enumerableIface = null;
            if(node.IsEnumerable)
            {
                enumerableIface = currentModule.GetEnumerableIface();
                if(node.IsGenericIterator)
                {
                    enumerableIface = currentModule.GetEnumerableGIface();
                    GenericInstance gargs = new GenericInstance(enumerableIface.GetGenericPrototype(),
                        new IChelaType[]{node.YieldType});
                    enumerableIface = (Structure)enumerableIface.InstanceGeneric(gargs, currentModule);
                }

                generatorClass.AddInterface(enumerableIface);
            }

            // Add the enumerator interface.
            Structure enumeratorIface = currentModule.GetEnumeratorIface();
            if(node.IsGenericIterator)
            {
                enumeratorIface = currentModule.GetEnumeratorGIface();
                GenericInstance gargs = new GenericInstance(enumeratorIface.GetGenericPrototype(),
                    new IChelaType[]{node.YieldType});
                enumeratorIface = (Structure)enumeratorIface.InstanceGeneric(gargs, currentModule);
            }
            generatorClass.AddInterface(enumeratorIface);

            // Create the yielded field.
            FieldVariable yieldedValue = new FieldVariable("yielded", MemberFlags.Private, node.YieldType, generatorClass);
            generatorClass.AddField(yieldedValue);
            node.YieldedValue = yieldedValue;

            // Create the generator state variable.
            FieldVariable generatorState = new FieldVariable("state", MemberFlags.Private, ChelaType.GetIntType(), generatorClass);
            generatorClass.AddField(generatorState);
            node.GeneratorState = generatorState;

            // Encapsulate the locals in fields.
            foreach(LocalVariable local in entryFunction.GetLocals())
            {
                if(!local.IsPseudoLocal)
                    continue;

                // Variables containing arguments must be public.
                MemberFlags access = MemberFlags.Private;
                if(local.ArgumentIndex >= 0)
                    access = MemberFlags.Public;

                // Create the field to hold the state.
                FieldVariable localField = new FieldVariable(GenSym(), access, local.GetVariableType(), generatorClass);
                generatorClass.AddField(localField);
                local.ActualVariable = localField;
            }

            // Create an instance of the generator class.
            Structure generatorClassInstance = generatorClass.GetClassInstance();
            if(generatorClass.GetGenericPrototype().GetPlaceHolderCount() != 0)
            {
                // Create an instance using the same placeholders.
                GenericPrototype proto = generatorClass.GetGenericPrototype();
                int numargs = proto.GetPlaceHolderCount();
                IChelaType[] protoInstance = new IChelaType[numargs];
                for(int i = 0; i < numargs; ++i)
                    protoInstance[i] = proto.GetPlaceHolder(i);

                // Instance the generic class.
                GenericInstance instance = new GenericInstance(proto, protoInstance);
                generatorClassInstance = (Structure)generatorClassInstance.InstanceGeneric(instance, currentModule);
            }
            node.GeneratorClassInstance = generatorClassInstance;

            // Create the trivial constructor.
            Function ctor = CreateTrivialConstructor(generatorClass, generatorClassInstance);
            if(generatorClass.IsGeneric())
                ctor = FindFirstConstructor(generatorClassInstance);

            // Create a local to hold the created closure.
            LexicalScope topScope = (LexicalScope)node.GetScope();
            LocalVariable closureLocal = new LocalVariable("closure", topScope, ReferenceType.Create(generatorClassInstance));

            // Create the entry point content.
            BasicBlock entryBlock = CreateBasicBlock();
            entryBlock.SetName("entry");
            builder.SetBlock(entryBlock);

            // Create the closure and store it in his local.
            builder.CreateNewObject(generatorClassInstance, ctor, 0);
            builder.CreateStoreLocal(closureLocal);

            // Load the closure.
            builder.CreateLoadLocal(closureLocal);

            // Store the arguments into the closure.
            FunctionPrototype prototype = node.GetPrototype();
            AstNode argument = prototype.GetArguments();
            byte index = 0;
            while(argument != null)
            {
                FunctionArgument argNode = (FunctionArgument) argument;

                // TODO: Forbid ref, out, stream arguments here.

                // Store the argument in the closure.
                LocalVariable argVar = argNode.GetVariable();
                if(argVar != null)
                {
                    // Load the closure
                    builder.CreateDup1();

                    // Load the argument.
                    builder.CreateLoadArg(index);

                    // Store it into the field.
                    builder.CreateStoreField((FieldVariable)argVar.ActualVariable);
                }

                // Process the next argument.
                argument = argument.GetNext();
                index++;
            }

            // Encapsulate the argument variables.
            foreach(ArgumentVariable argVar in node.ArgumentVariables)
            {
                if(!argVar.IsPseudoArgument)
                    continue;

                // Create the argument field.
                FieldVariable argField = new FieldVariable(GenSym(), MemberFlags.Public, argVar.GetVariableType(), generatorClass);
                generatorClass.AddField(argField);
                argVar.ActualVariable = argField;

                // Store the self field.
                if(!currentFunction.IsStatic() && argVar.GetArgumentIndex() == 0)
                    node.GeneratorSelf = argField;

                // Load the closure.
                builder.CreateDup1();

                // Load the argument.
                builder.CreateLoadArg((byte)argVar.GetArgumentIndex());

                // Store it into the closure.
                builder.CreateStoreField(argField);
            }

            // Return the generator.
            builder.CreateRet();

            // Notify the yields about their states.
            int stateIndex = 2;
            foreach(ReturnStatement yieldStmtn in node.Yields)
            {
                yieldStmtn.YieldState = stateIndex;
                stateIndex += 2;
            }

            // Implement IEnumerator.
            if(node.IsEnumerable)
            {
                // Create the object GetEnumerator method.
                CreateGenerator_GetEnumerator(node, currentModule.GetEnumeratorIface(), false);

                // Create the generic GetEnumerator method
                if(node.IsGenericIterator)
                    CreateGenerator_GetEnumerator(node, enumeratorIface, true);
            }

            // Create the Current property.
            CreateGenerator_Current(node, false);
            if(node.IsGenericIterator)
                CreateGenerator_Current(node, true);

            // Create the Reset method.
            CreateGenerator_Reset(node);

            // Create the MoveNext method.
            Function moveNext = CreateGenerator_MoveNext(node);

            // Create the Dispose method.
            CreateGenerator_Dispose(node, moveNext);

            // Fix the inheritance.
            generatorClass.FixInheritance();
        }
Ejemplo n.º 10
0
 public void CreateStoreField(FieldVariable field)
 {
     AppendInst1(OpCode.StoreField, field);
 }
Ejemplo n.º 11
0
 public void CreateLoadFieldRef(FieldVariable field)
 {
     AppendInst1(OpCode.LoadFieldRef, field);
 }
Ejemplo n.º 12
0
        private void EmitFieldDebugInfo(ModuleWriter writer, FieldVariable field)
        {
            // Emit the field id.
            uint fieldId = field.GetSerialId();
            writer.Write(fieldId);

            // Emit the field position.
            TokenPosition position = field.Position;
            if(position == null)
                position = NullPosition;
            EmitPosition(writer, position);
        }
Ejemplo n.º 13
0
        public override AstNode Visit(FieldDefinition node)
        {
            // Push the unsafe context.
            bool isUnsafe = (node.GetFlags() & MemberFlags.SecurityMask) == MemberFlags.Unsafe;
            if(isUnsafe)
                PushUnsafe();

            // Get the type node.
            Expression typeExpression = node.GetTypeNode();

            // Visit the type node.
            typeExpression.Accept(this);

            // Get the type of the type expression.
            IChelaType type = typeExpression.GetNodeType();
            type = ExtractActualType(typeExpression, type);

            // Check field type security.
            if(type.IsUnsafe())
                UnsafeError(node, "safe field with unsafe type.");

            // Class/interfaces instances are held by reference.
            if(type.IsPassedByReference())
                type = ReferenceType.Create(type);

            // Constants are always static.
            if(type.IsConstant())
                node.SetFlags((node.GetFlags() & ~MemberFlags.InstanceMask) | MemberFlags.Static);

            // Process the declarations.
            FieldDeclaration decl = node.GetDeclarations();
            while(decl != null)
            {
                // Find an existent member.
                ScopeMember oldField = currentContainer.FindMember(decl.GetName());
                if(oldField != null)
                    Error(node, "already declared a member with the same name.");

                // Create the field.
                FieldVariable field = new FieldVariable(decl.GetName(), node.GetFlags(), type, currentContainer);
                field.Position = decl.GetPosition();
                decl.SetVariable(field);
                decl.SetNodeType(type);

                // Add the field into the scope.
                if(currentContainer.IsStructure() || currentContainer.IsClass())
                {
                    // Add the field.
                    Structure building = (Structure)currentContainer;
                    building.AddField(field);
                }
                else if(currentContainer.IsNamespace())
                {
                    // Make sure its a global variable.
                    if(!field.IsStatic())
                        Error(node, "namespaces only can have static fields.");

                    Namespace space = (Namespace)currentContainer;
                    space.AddMember(field);
                }
                else
                {
                    Error(node, "a field must be declared inside an structure or class.");
                }

                // Process the next declaration.
                decl = (FieldDeclaration)decl.GetNext();
            }

            if(isUnsafe)
                PopUnsafe();

            return node;
        }
Ejemplo n.º 14
0
        public override AstNode Visit(EnumConstantDefinition node)
        {
            // Use the same flags for all of the constants.
            MemberFlags flags = MemberFlags.Static | MemberFlags.Public;

            // The current container must be a structure.
            Structure building = (Structure)currentContainer;

            // Create the field.
            FieldVariable field = new FieldVariable(node.GetName(), flags, node.GetNodeType(), building);
            node.SetVariable(field);

            // Add it to the enumeration.
            building.AddField(field);

            // Return the node.
            return node;
        }
Ejemplo n.º 15
0
        private void DeclareSimplifiedEvent(EventDefinition node)
        {
            // Get the event variable.
            EventVariable eventVariable = node.GetEvent();

            // Get the flags.
            MemberFlags flags = node.GetFlags();

            // Get the instance type.
            MemberFlags instanceFlags = MemberFlags.InstanceMask & flags;

            // Create the argument list.
            List<IChelaType> arguments = new List<IChelaType> ();

            // Add the this argument.
            IChelaType selfType = null;
            if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface())
            {
                Structure building = (Structure) currentContainer;
                if(instanceFlags != MemberFlags.Static)
                {
                    // Instance the building.
                    building = building.GetSelfInstance();

                    // Create the self argument.
                    selfType = ReferenceType.Create(building);
                    arguments.Add(selfType);
                }
            }

            // Add the value argument.
            arguments.Add(eventVariable.GetVariableType());

            // Create the function type.
            FunctionType functionType = FunctionType.Create(ChelaType.GetVoidType(), arguments, false);

            // Create the add function.
            CreateSimplifiedEventFunction(node, eventVariable, functionType, true);

            // Create the remove function
            CreateSimplifiedEventFunction(node, eventVariable, functionType, false);

            // Create the delegate field.
            string delFieldName = "_evdel_" + eventVariable.GetName();
            MemberFlags delFieldFlags = flags & ~MemberFlags.VisibilityMask;
            if(eventVariable.IsPrivate())
                delFieldFlags |= MemberFlags.Private;
            else
                delFieldFlags |= MemberFlags.Protected;

            // Store the delegate field in the current container.
            FieldVariable delField = new FieldVariable(delFieldName, delFieldFlags, eventVariable.GetVariableType(), currentContainer);
            delField.Position = node.GetPosition();
            eventVariable.AssociatedField = delField;
            if(currentContainer.IsNamespace())
            {
                Namespace space = (Namespace) currentContainer;
                space.AddMember(delField);
            }
            else if(currentContainer.IsClass() || currentContainer.IsStructure() || currentContainer.IsInterface())
            {
                Structure building = (Structure) currentContainer;
                building.AddField(delField);
            }
            else
                Error(node, "an event cannot be defined here.");
        }
Ejemplo n.º 16
0
        public override AstNode Visit(EnumDefinition node)
        {
            // Push the scope.
            PushScope(node.GetScope());

            // Use a default type of const int.
            IChelaType baseType = ChelaType.GetIntType();
            IChelaType enumType = ConstantType.Create(baseType);

            // Declare the value field.
            Structure building = node.GetStructure();
            FieldVariable valueField =
                new FieldVariable("m_value", MemberFlags.Public, baseType, building);
            building.AddField(valueField);

            // Used for implicit prev + 1.
            IChelaType enumConst = ConstantType.Create(building);
            TypeNode enumIntExpr = new TypeNode(TypeKind.Other, node.GetPosition());
            enumIntExpr.SetOtherType(enumType);

            // Visit the constant defininitions.
            EnumConstantDefinition prev = null;
            AstNode child = node.GetChildren();
            while(child != null)
            {
                // Cast the child.
                EnumConstantDefinition constDef = (EnumConstantDefinition)child;

                // Set the child type.
                constDef.SetCoercionType(enumType);
                constDef.SetNodeType(enumConst);

                // If there isn't a constant expression, use previous + 1 or 0.
                if(constDef.GetValue() == null)
                {
                    TokenPosition constPos = constDef.GetPosition();
                    if(prev != null)
                    {
                        // Previous + 1
                        Expression prevExpr = new CastOperation(enumIntExpr,
                                                                new VariableReference(prev.GetName(), constPos),
                                                                constPos);
                        Expression implicitVal = new BinaryOperation(BinaryOperation.OpAdd,
                                                                     prevExpr,
                                                                     new ByteConstant(1, constPos),
                                                                     constPos);
                        constDef.SetValue(implicitVal);
                    }
                    else
                    {
                        // First element is 0
                        constDef.SetValue(new ByteConstant(0, constPos));
                    }
                }

                // Visit the constant definition.
                constDef.Accept(this);

                // Process the next constant.
                prev = constDef;
                child = child.GetNext();
            }

            // Restore the scope.
            PopScope();

            return node;
        }