示例#1
0
 public FixedVariableDecl(string name, Expression value, TokenPosition position)
     : base(position)
 {
     SetName(name);
     this.value = value;
     this.variable = null;
 }
示例#2
0
 public FunctionArgument(Expression typeExpression, bool @params, string name, TokenPosition position)
     : base(position)
 {
     SetName(name);
     this.typeExpression = typeExpression;
     this.@params = @params;
     this.variable = null;
 }
示例#3
0
 public PropertyAccessor(MemberFlags flags, AstNode children, TokenPosition position)
     : base(null, children, position)
 {
     this.flags = flags;
     this.property = null;
     this.selfLocal = null;
     this.indices = null;
     this.indexerVariables = null;
 }
示例#4
0
 public CatchStatement(Expression exceptionType, string name,
                        AstNode children, TokenPosition position)
     : base(children, position)
 {
     SetName(name);
     this.exceptionType = exceptionType;
     this.context = null;
     this.variable = null;
 }
示例#5
0
 public EventAccessorDefinition(MemberFlags flags, string name, AstNode children, TokenPosition position)
     : base(children, position)
 {
     SetName(name);
     this.flags = flags;
     this.eventVariable = null;
     this.function = null;
     this.selfLocal = null;
     this.valueLocal = null;
 }
示例#6
0
 protected Function(ChelaModule module)
     : base(module)
 {
     this.name = string.Empty;
     this.flags = MemberFlags.Default;
     this.parentScope = null;
     this.basicBlocks = new List<BasicBlock> ();
     this.lexicalScopes = new List<LexicalScope>();
     this.locals = new List<LocalVariable> ();
     this.position = null;
     this.exceptionContext = null;
     this.returnBlock = null;
     this.returningVar = null;
     this.returnValueVar = null;
     this.genericPrototype = GenericPrototype.Empty;
     this.arguments  = null;
 }
示例#7
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();
        }
示例#8
0
 public void CreateLoadLocalRef(LocalVariable local)
 {
     CreateLoadLocalRef((ushort)local.GetLocalIndex());
 }
示例#9
0
        public override AstNode Visit(CatchStatement node)
        {
            // Get the type expression.
            Expression typeExpression = node.GetExceptionType();

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

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

            // Only accept classes.
            if(!objectType.IsClass())
                Error(node, "only class instances can be exceptions.");

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

            // Create the catch lexical scope.
            LexicalScope scope = CreateLexicalScope(node);
            node.SetScope(scope);

            // Create the exception variable.
            string exceptName = node.GetName();
            if(exceptName != null && exceptName != "")
            {
                LocalVariable exceptLocal = new LocalVariable(exceptName, scope,
                                                              ReferenceType.Create(objectType));
                node.SetVariable(exceptLocal);
            }

            // Enter into the catch scope.
            PushScope(scope);

            // Visit the children.
            node.GetChildren().Accept(this);

            // Restore the scope.
            PopScope();

            return node;
        }
示例#10
0
        internal int AddLocal(LocalVariable local)
        {
            // TODO: Throw an exception for duplicated variables.
            members.Add(local.GetName(), local);

            // Notify the parent function.
            return parentFunction.AddLocal(local);
        }
示例#11
0
        public override AstNode Visit(VariableDeclaration node)
        {
            // Get the variable name.
            string varName = node.GetName();

            // Avoid redefinition.
            if(currentContainer.FindMember(varName) != null)
                Error(node, "attempting to redefine a variable in a same scope.");

            // Get the initial value.
            Expression initialValue = node.GetInitialValue();

            // Visit the initial value.
            // Do this here to use the state previous to the variable declaration.
            if(initialValue != null)
                initialValue.Accept(this);

            // Create the variable.
            LocalVariable local = new LocalVariable(node.GetName(), (LexicalScope)currentContainer,
                                                    node.GetNodeType());

            // Store it in the node.
            node.SetVariable(local);

            // Check the compatibility with the initial value.
            if(initialValue == null)
                return node;

            // Get the variable type and the initial value type.
            IChelaType varType = node.GetNodeType();
            IChelaType valueType = initialValue.GetNodeType();

            // Class instances are held by reference.
            if(varType != valueType && Coerce(node, varType, valueType, initialValue.GetNodeValue()) != varType)
                Error(node, "cannot implicitly cast from {0} to {1}.", valueType.GetFullName(), varType.GetFullName());

            return node;
        }
示例#12
0
 public void SetValueLocal(LocalVariable local)
 {
     valueLocal = local;
 }
示例#13
0
        public override AstNode Visit(FunctionDefinition node)
        {
            // Process attributes.
            ProcessAttributes(node);

            // Get the prototype.
            FunctionPrototype prototype = node.GetPrototype();

            // Get the function.
            Function function = prototype.GetFunction();

            // Store the definition node in the function.
            if(function.DefinitionNode != null)
                Error(node, "multiples definition of a function.");
            function.DefinitionNode = node;

            // Check for declarations, interfaces.
            MemberFlags instanceFlags = function.GetFlags() & MemberFlags.InstanceMask;
            if(instanceFlags == MemberFlags.Abstract || instanceFlags == MemberFlags.Contract
               || function.IsExternal())
            {
                if(node.GetChildren() != null)
                    Error(node, "abstract/extern functions cannot have a definition body.");
                return node;
            }
            else
            {
                if(node.GetChildren() == null)
                    Error(node, "functions must have a definition.");
            }

            // Store the old function.
            // TODO: Add closures
            Function oldFunction = currentFunction;
            currentFunction = function;

            // Create the function lexical scope.
            LexicalScope topScope = CreateLexicalScope(node);
            node.SetScope(topScope);

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

            // Update the scope.
            PushScope(topScope);

            // Push the security.
            if(function.IsUnsafe())
                PushUnsafe();

            // Declare the argument variables.
            AstNode argument = prototype.GetArguments();
            int index = 0;
            while(argument != null)
            {
                // Cast the argument node.
                FunctionArgument argNode = (FunctionArgument)argument;

                // Set the argument name.
                string name = argument.GetName();
                ArgumentData argData = function.GetArguments()[index++];
                argData.Name = name;

                // Create the argument variable.
                if(name != null && name != "" && name != "this")
                {
                    // Create the argument local variable
                    LocalVariable argLocal = new LocalVariable(name, topScope, argNode.GetNodeType());
                    argLocal.Type = LocalType.Argument;
                    argLocal.ArgumentIndex = index;

                    // Store it in the argument node.
                    argNode.SetVariable(argLocal);
                }
                else if(name == "this")
                {
                    // Create the this argument.
                    node.ArgumentVariables.Add(
                        new ArgumentVariable(0, "this", topScope, argument.GetNodeType())
                    );
                }

                argument = argument.GetNext();
            }

            // Check the constructor initializer.
            if(function.IsConstructor())
                CheckConstructorInit(node);

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

            // Restore the security.
            if(function.IsUnsafe())
                PopUnsafe();

            // Restore the scope.
            PopScope();

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

            // Restore the current function.
            currentFunction = oldFunction;

            return node;
        }
示例#14
0
        public override AstNode Visit(EventAccessorDefinition node)
        {
            EventVariable eventVariable = node.GetEvent();

            // Build the event flags.
            MemberFlags flags = node.GetFlags();
            if(flags == MemberFlags.ImplicitVis)
            {
                flags = eventVariable.GetFlags();
            }
            else
            {
                // TODO: Check compatibility.
                flags |= eventVariable.GetFlags() & ~MemberFlags.VisibilityMask;
            }

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

            // Abstract properties cannot have a body.
            if((instanceFlags == MemberFlags.Abstract ||
               instanceFlags == MemberFlags.Contract) && node.GetChildren() != null)
                Error(node, "abstract events cannot have a definition body.");

            // 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);

            // Build the function name.
            string functionName = node.GetName() + "_" + eventVariable.GetName();

            // Create the function.
            Function accessor;
            if(selfType != null)
                accessor = new Method(functionName, flags, currentContainer);
            else
                accessor = new Function(functionName, flags, currentContainer);

            // Set the arguments.
            accessor.SetFunctionType(functionType);

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

            // Store the function in the event.
            if(node.GetName() == "add")
                eventVariable.AddModifier = accessor;
            else
                eventVariable.RemoveModifier = accessor;

            // Store the function in his scope.
            if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface())
            {
                Structure building = (Structure)currentContainer;
                building.AddFunction(functionName, accessor);
            }
            else if(currentContainer.IsNamespace())
            {
                Namespace space = (Namespace)currentContainer;
                space.AddMember(accessor);
            }
            else
            {
                Error(node, "an event cannot be declared here.");
            }

            // If there's a body, declare the "argument" variables.
            if(node.GetChildren() != null)
            {
                LexicalScope scope = CreateLexicalScope(node, accessor);

                // Add the "this" local.
                if(selfType != null)
                    new ArgumentVariable(0, "this", scope, selfType);

                // Add the "value" local
                LocalVariable valueVar = new LocalVariable("value", scope, eventVariable.GetVariableType());
                node.SetValueLocal(valueVar);

                // Store the scope
                node.SetScope(scope);
            }

            // Set the node function to the accessor.
            node.SetFunction(accessor);

            return node;
        }
示例#15
0
        internal int AddLocal(LocalVariable local)
        {
            // Don't write pseudo locals.
            if(local.IsPseudoLocal)
                return -1;

            // Add the local.
            this.locals.Add(local);
            return nextLocalId++;
        }
示例#16
0
        public void CreateLoadLocalAddr(LocalVariable local)
        {
            if(local.IsPseudoLocal)
                throw new ModuleException("Cannot use pseudo variable directly.");

            CreateLoadLocalAddr((ushort)local.GetLocalIndex());
        }
示例#17
0
        public override AstNode Visit(SetAccessorDefinition node)
        {
            PropertyVariable property = node.GetProperty();

            if(node.GetChildren() == null && property.SetAccessor != null)
                return node;

            if(node.GetChildren() != null && property.SetAccessor != null)
                Error(node, "multiples definitions of the set accessor.");

            // Build the property flags.
            MemberFlags flags = node.GetFlags();
            if(flags == MemberFlags.ImplicitVis)
            {
                flags = property.GetFlags();
            }
            else
            {
                // TODO: Check compatibility.
                flags |= property.GetFlags() & ~MemberFlags.VisibilityMask;
            }

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

            // Abstract properties cannot have a body.
            if((instanceFlags == MemberFlags.Abstract ||
               instanceFlags == MemberFlags.Contract) && node.GetChildren() != null)
                Error(node, "abstract properties cannot have a definition body.");

            // Create the set accesor.
            if(property.SetAccessor == null)
            {
                // 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 parameter.
                        selfType = ReferenceType.Create(building);
                        arguments.Add(selfType);
                    }
                }

                // Append the indices.
                foreach(IChelaType indexType in property.Indices)
                    arguments.Add(indexType);

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

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

                // Create the function.
                Function accessor;
                if(selfType != null)
                    accessor = new Method("set_" + property.GetName(), flags, currentContainer);
                else
                    accessor = new Function("set_" + property.GetName(), flags, currentContainer);

                // Set the arguments.
                accessor.SetFunctionType(functionType);

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

                // Store the function in the property.
                property.SetAccessor = accessor;

                // Store the function in his scope.
                if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface())
                {
                    Structure building = (Structure)currentContainer;
                    building.AddFunction("set_" + property.GetName(), accessor);
                }
                else if(currentContainer.IsNamespace())
                {
                    Namespace space = (Namespace)currentContainer;
                    space.AddMember(accessor);
                }
                else
                {
                    Error(node, "a property cannot be declared here.");
                }

                // If there's a body, declare the "argument" variables.
                if(node.GetChildren() != null)
                {
                    LexicalScope scope = CreateLexicalScope(node, accessor);

                    // Add the "this" local.
                    if(selfType != null)
                        new ArgumentVariable(0, "this", scope, selfType);

                    // Add the "value" local
                    LocalVariable valueVar = new LocalVariable("value", scope, property.GetVariableType());
                    node.SetValueLocal(valueVar);

                    // Add the indices variables.
                    AstNode index = node.GetIndices();
                    List<LocalVariable> indexerVars = new List<LocalVariable> ();
                    while(index != null)
                    {
                        // Create the local
                        LocalVariable local = new LocalVariable(index.GetName(), scope, index.GetNodeType());
                        indexerVars.Add(local);

                        // Process the next.
                        index = index.GetNext();
                    }
                    node.SetIndexerVariables(indexerVars);
                    node.SetScope(scope);
                }
            }
            else
            {
                // Check for declaration compatibility.
                if(flags != property.SetAccessor.GetFlags())
                    Error(node, "incompatible set accessor declarations.");
            }

            // Set the node function to the accessor.
            node.SetFunction(property.SetAccessor);

            return node;
        }
示例#18
0
 public void CreateLoadLocalRef(LocalVariable local)
 {
     CreateLoadLocalRef((ushort)local.GetLocalIndex());
 }
示例#19
0
        public void CreateStoreLocal(LocalVariable variable)
        {
            if(variable.IsPseudoLocal)
                throw new ModuleException("Cannot use pseudo variable directly.");

            uint index = (uint)variable.GetLocalIndex();
            if(index < 256)
                CreateStoreLocal((byte)index);
            else
                CreateStoreLocalS((ushort)index);
        }
示例#20
0
 public void SetVariable(LocalVariable variable)
 {
     this.variable = variable;
 }
示例#21
0
 public SetAccessorDefinition(MemberFlags flags, AstNode content, TokenPosition position)
     : base(flags, content, position)
 {
     valueLocal = null;
 }
示例#22
0
 public void SetSelfLocal(LocalVariable local)
 {
     selfLocal = local;
 }
示例#23
0
        public override AstNode Visit(FixedVariableDecl node)
        {
            // Get the variable type.
            IChelaType type = node.GetNodeType();

            // Create the variable.
            LocalVariable fixedVar = new LocalVariable(node.GetName(), (LexicalScope)currentScope, type);
            node.SetVariable(fixedVar);

            // Visit the value expression.
            Expression valueExpr = node.GetValueExpression();
            valueExpr.Accept(this);

            // Get the value type.
            IChelaType valueType = valueExpr.GetNodeType();

            // The value must be a reference or a pointer.
            if(!valueType.IsReference() && !valueType.IsPointer())
                Error(valueExpr, "the value expression must be a reference or a pointer.");

            if(valueType.IsPointer())
            {
                if(Coerce(node, type, valueType, valueExpr.GetNodeValue()) != type)
                    Error(valueExpr, "cannot convert {0} into {1}.", valueType.GetName(), type.GetName());

                // Coerce the value.
                node.SetCoercionType(type);
            }
            else
            {
                // Remove references.
                IChelaType refType = DeReferenceType(valueType);
                if(refType.IsReference())
                    refType = DeReferenceType(refType);

                // Only support arrays
                if(refType.IsArray())
                {
                    ArrayType array = (ArrayType)refType;
                    IChelaType pointerType = PointerType.Create(array.GetValueType());
                    if(Coerce(node, type, pointerType, null) != type)
                        Error(valueExpr, "cannot convert {0} into {1}.", pointerType.GetName(), type.GetName());
                }

                // Set the new coercion type.
                node.SetCoercionType(ReferenceType.Create(refType));
            }

            return node;
        }