Exemplo n.º 1
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);
        }
Exemplo n.º 2
0
        private void CreateGenerator_GetEnumerator(FunctionDefinition node, Structure enumeratorType, bool generic)
        {
            // Get the generator class.
            Class genClass = node.GeneratorClass;

            // Use the GetEnumerator name for the most specific version.
            string name = "GetEnumerator";
            Function contract = null;
            if(!generic && node.IsGenericIterator)
            {
                name = GenSym();
                contract = FindFirstConstract(currentModule.GetEnumerableIface(), "GetEnumerator");
            }

            // Create the function type.
            FunctionType functionType =
                FunctionType.Create(ReferenceType.Create(enumeratorType),
                    new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false);

            // Create the method.
            Method method = new Method(name, MemberFlags.Public, genClass);
            method.SetFunctionType(functionType);
            genClass.AddFunction(name, method);

            // Set the explicit contract.
            if(contract != null)
                method.SetExplicitContract(contract);

            // Create the method block.
            BasicBlock block = new BasicBlock(method);
            block.SetName("top");

            // Return this.
            builder.SetBlock(block);
            builder.CreateLoadArg(0);
            builder.CreateRet();
        }
Exemplo n.º 3
0
        private Method CreateTrivialConstructor(Structure building, Structure buildingInstance)
        {
            // Create the constructor function type.
            FunctionType type = FunctionType.Create(ChelaType.GetVoidType(),
                new IChelaType[]{ReferenceType.Create(buildingInstance)}, false);

            // Create the constructor.
            Method ctor = new Method(".ctor", MemberFlags.Public | MemberFlags.Constructor, building);
            ctor.SetFunctionType(type);
            building.AddFunction(".ctor", ctor);

            // Create the constructor block.
            BasicBlock top = new BasicBlock(ctor);
            top.SetName("top");
            top.Append(new Instruction(OpCode.RetVoid, null));

            return ctor;
        }
Exemplo n.º 4
0
        private void CreateGenerator_Current(FunctionDefinition node, bool generic)
        {
            // Get the generator class.
            Class genClass = node.GeneratorClass;

            // Use the get_Current name for the most specific version.
            string name = "get_Current";
            Function contract = null;
            if(!generic && node.IsGenericIterator)
            {
                name = GenSym();
                contract = FindFirstConstract(currentModule.GetEnumeratorIface(), "get_Current");
            }

            // Select the current type.
            IChelaType currentType = node.YieldType;
            if(!generic)
                currentType = ReferenceType.Create(currentModule.GetObjectClass());

            // Create the function type.
            FunctionType functionType =
                FunctionType.Create(currentType,
                    new IChelaType[]{ReferenceType.Create(node.GeneratorClassInstance)}, false);

            // Create the method.
            Method method = new Method(name, MemberFlags.Public, genClass);
            method.SetFunctionType(functionType);
            genClass.AddFunction(name, method);

            // Set the explicit contract.
            if(contract != null)
                method.SetExplicitContract(contract);

            // Create the method block.
            BasicBlock block = new BasicBlock(method);
            block.SetName("top");

            // Create the return and error blocks.
            BasicBlock retBlock = new BasicBlock(method);
            retBlock.SetName("ret");

            BasicBlock errorBlock = new BasicBlock(method);
            errorBlock.SetName("error");

            // Make sure reset was called before the first Current.
            builder.SetBlock(block);
            builder.CreateLoadArg(0);
            builder.CreateLoadField(node.GeneratorState);
            builder.CreateLoadInt32(0);
            builder.CreateCmpEQ();
            builder.CreateBr(errorBlock, retBlock);

            // Raise an error if reset wasn't called.
            builder.SetBlock(errorBlock);

            Class excpt = (Class)ExtractClass(node, currentModule.GetLangMember("InvalidOperationException"));
            builder.CreateLoadString("IEnumerator.MoveNext must be called before than IEnumerator.Current.");
            builder.CreateNewObject(excpt, GetExceptionCtor(node, excpt), 1);
            builder.CreateThrow();

            // Load the yielded value.
            builder.SetBlock(retBlock);
            builder.CreateLoadArg(0);
            builder.CreateLoadField(node.YieldedValue);

            // Cast the yielded value.
            Cast(node, null, node.YieldType, currentType);

            // Return.
            builder.CreateRet();
        }