コード例 #1
0
ファイル: FunctionGenerator.cs プロジェクト: ronsaldo/chela
        private void CreateGenerator_Reset(FunctionDefinition node)
        {
            // Get the generator class.
            Class genClass = node.GeneratorClass;

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

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

            // Create the top block.
            BasicBlock top = new BasicBlock(method);
            builder.SetBlock(top);

            // Throw an exception.
            Class excpt = (Class)ExtractClass(node, currentModule.GetLangMember("InvalidOperationException"));
            builder.CreateLoadString("IEnumerator.Reset cannot be called in generators.");
            builder.CreateNewObject(excpt, GetExceptionCtor(node, excpt), 1);
            builder.CreateThrow();
        }
コード例 #2
0
ファイル: FunctionGenerator.cs プロジェクト: ronsaldo/chela
        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;
        }
コード例 #3
0
ファイル: FunctionGenerator.cs プロジェクト: ronsaldo/chela
        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();
        }
コード例 #4
0
ファイル: FunctionGenerator.cs プロジェクト: ronsaldo/chela
        private Function CreateGenerator_MoveNext(FunctionDefinition node)
        {
            // Get the generator class.
            Class genClass = node.GeneratorClass;

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

            // Create the method.
            Method method = new Method("MoveNext", MemberFlags.Public, genClass);
            method.SetFunctionType(functionType);
            method.DefinitionNode = node;
            genClass.AddFunction("MoveNext", method);

            // Swap the exception contexts.
            method.SwapExceptionContexts(currentFunction);

            // Store the old function.
            Function oldFunction = currentFunction;
            currentFunction = method;

            // Create the jump table block.
            BasicBlock jmpBlock = CreateBasicBlock();
            jmpBlock.SetName("jmp");

            // Generate the main code.
            BasicBlock topBlock = CreateBasicBlock();
            topBlock.SetName("top");
            builder.SetBlock(topBlock);

            // Prepare returning.
            LexicalScope topScope = (LexicalScope) node.GetScope();
            PrepareReturning(node, currentFunction, topScope);

            // Create the function body.
            VisitList(node.GetChildren());

            // Finish returning.
            FinishReturn(node, currentFunction);

            // Create the state jump table.
            builder.SetBlock(jmpBlock);

            // Load the current state.
            builder.CreateLoadArg(0);
            builder.CreateLoadField(node.GeneratorState);

            // Build the jump table.
            int numstates = node.Yields.Count*2+3;
            int[] stateConstants = new int[numstates];
            BasicBlock[] stateEntries = new BasicBlock[numstates];

            // The default case is return.
            stateConstants[0] = -1;
            stateEntries[0] = currentFunction.ReturnBlock;

            // The first state is the top block.
            stateConstants[1] = 0;
            stateEntries[1] = topBlock;

            // The second state is the return block.
            stateConstants[2] = 1;
            stateEntries[2] = currentFunction.ReturnBlock;

            // The next states are the yield merges followed by yield disposes.
            for(int i = 0; i < node.Yields.Count; ++i)
            {
                ReturnStatement yieldStmnt = node.Yields[i];

                // Emit the merge state.
                int stateId = i*2+2;
                int entryIndex = stateId+1;
                stateConstants[entryIndex] = stateId;
                stateEntries[entryIndex] = yieldStmnt.MergeBlock;

                // Emit the dispose state.
                stateConstants[entryIndex+1] = stateId+1;
                stateEntries[entryIndex+1] = yieldStmnt.DisposeBlock;
            }

            builder.CreateSwitch(stateConstants, stateEntries);

            // Restore the old function.
            currentFunction = oldFunction;

            return method;
        }
コード例 #5
0
ファイル: FunctionGenerator.cs プロジェクト: ronsaldo/chela
        private void CreateGenerator_Dispose(FunctionDefinition node, Function moveNext)
        {
            // Get the generator class.
            Class genClass = node.GeneratorClass;

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

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

            // Create the top block.
            BasicBlock top = new BasicBlock(method);
            builder.SetBlock(top);

            // Create the return and dispose blocks.
            BasicBlock justReturn = new BasicBlock(method);
            BasicBlock disposeAndReturn = new BasicBlock(method);

            // Load the current state.
            builder.CreateLoadArg(0);
            builder.CreateDup1();
            builder.CreateDup1();
            builder.CreateLoadField(node.GeneratorState);
            builder.CreateDup1();
            builder.CreateLoadInt32(1);
            builder.CreateCmpEQ();
            builder.CreateBr(justReturn, disposeAndReturn);

            // Dispose and return implementation.
            builder.SetBlock(disposeAndReturn);

            // Increase the state.
            builder.CreateLoadInt32(1);
            builder.CreateAdd();
            builder.CreateStoreField(node.GeneratorState);

            // Call move next.
            builder.CreateCall(moveNext, 1);
            builder.CreateRetVoid();

            // Just return implementation.
            builder.SetBlock(justReturn);
            builder.CreateRetVoid();
        }
コード例 #6
0
ファイル: FunctionGenerator.cs プロジェクト: ronsaldo/chela
        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();
        }
コード例 #7
0
ファイル: FunctionGenerator.cs プロジェクト: ronsaldo/chela
        private void CreateDefaultStaticConstructor(StructDefinition node)
        {
            // Get the structure.
            Structure building = node.GetStructure();

            // Check for an user defined constructor.
            if(building.GetStaticConstructor() != null)
                return;

            // Get the static initialization fields.
            List<FieldDeclaration> staticInitedField = new List<FieldDeclaration> ();
            bool isUnsafe = false;
            foreach(FieldDeclaration decl in building.GetFieldInitializations())
            {
                Variable variable = decl.GetVariable();
                if(variable.IsStatic())
                {
                    staticInitedField.Add(decl);
                    if(variable.IsUnsafe())
                        isUnsafe = true;
                }
            }

            // If there aren't field to initialize, don't create the static constructor.
            if(staticInitedField.Count == 0)
                return;

            // Begin the node.
            builder.BeginNode(node);

            // Create the static constructor function type.
            FunctionType ctorType = FunctionType.Create(ChelaType.GetVoidType());

            // Create the constructor method.
            MemberFlags flags = MemberFlags.StaticConstructor;
            if(isUnsafe)
                flags |= MemberFlags.Unsafe;
            Method constructor = new Method("<sctor>", flags, building);
            constructor.SetFunctionType(ctorType);

            // Store it.
            building.AddFunction("<sctor>", constructor);

            // Create the constructor scope.
            LexicalScope ctorScope = CreateLexicalScope(node, constructor);
            PushScope(ctorScope);

            // Create the top basic block.
            BasicBlock topBlock = new BasicBlock(constructor);
            builder.SetBlock(topBlock);

            // Initialize the static fields.
            GenerateStaticFieldInitializations(node, staticInitedField);

            // Restore the scope.
            PopScope();

            // Return void.
            builder.CreateRetVoid();

            // End the node.
            builder.EndNode();
        }
コード例 #8
0
ファイル: ModuleInheritance.cs プロジェクト: ronsaldo/chela
        private void CreateDefaultConstructor(StructDefinition node)
        {
            // Get the structure.
            Structure building = node.GetStructure();

            // Check for an user defined constructor.
            if(building.GetConstructor() != null)
                return;

            // Instance the building.
            GenericPrototype contGenProto = building.GetGenericPrototype();
            int templateArgs = contGenProto.GetPlaceHolderCount();
            Structure buildingInstance = building;
            if(templateArgs != 0)
            {
                IChelaType[] thisArgs = new IChelaType[templateArgs];
                for(int i = 0; i < templateArgs; ++i)
                    thisArgs[i] = contGenProto.GetPlaceHolder(i);
                buildingInstance = (Structure)building.InstanceGeneric(
                    new GenericInstance(contGenProto, thisArgs), currentModule);
            }

            // Create the default constructor function type.
            List<IChelaType> arguments = new List<IChelaType> ();
            arguments.Add(ReferenceType.Create(buildingInstance));
            FunctionType ctorType = FunctionType.Create(ChelaType.GetVoidType(), arguments);

            // Create the constructor method.
            MemberFlags flags = MemberFlags.Public | MemberFlags.Constructor;
            Method constructor = new Method(building.GetName(), flags, building);
            constructor.SetFunctionType(ctorType);

            // Store it.
            building.AddFunction("<ctor>", constructor);
            node.SetDefaultConstructor(constructor);
        }
コード例 #9
0
        public override AstNode Visit(DelegateDefinition node)
        {
            // Check the security.
            bool isUnsafe = (node.GetFlags() & MemberFlags.SecurityMask) == MemberFlags.Unsafe;
            if(isUnsafe)
                PushUnsafe();

            // Get the delegate building.
            Structure building = node.GetStructure();

            // Use the generic prototype.
            // Use the generic scope.
            PseudoScope genScope = node.GetGenericScope();
            if(genScope != null)
                PushScope(genScope);

            // Visit the argument list.
            VisitList(node.GetArguments());

            // Visit the return type.
            Expression returnTypeExpr = node.GetReturnType();
            returnTypeExpr.Accept(this);

            IChelaType returnType = returnTypeExpr.GetNodeType();
            returnType = ExtractActualType(returnTypeExpr, returnType);

            // Use references for class/interface.
            if(returnType.IsPassedByReference())
                returnType = ReferenceType.Create(returnType);

            // Create the invoke function type.
            List<IChelaType> arguments = new List<IChelaType> ();

            // Add the argument types.
            AstNode argNode = node.GetArguments();
            while(argNode != null)
            {
                arguments.Add(argNode.GetNodeType());
                argNode = argNode.GetNext();
            }

            // Create the function type.
            FunctionType functionType = FunctionType.Create(returnType, arguments);

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

            // Create the invoke type.
            List<IChelaType> invokeArguments = new List<IChelaType> ();
            invokeArguments.Add(ReferenceType.Create(building));
            for(int i = 0; i < arguments.Count; ++i)
                invokeArguments.Add(arguments[i]);
            FunctionType invokeType = FunctionType.Create(returnType, invokeArguments);

            // Create the constructor type.
            List<IChelaType> ctorArguments = new List<IChelaType> ();
            ctorArguments.Add(ReferenceType.Create(building));
            ctorArguments.Add(ReferenceType.Create(currentModule.TypeMap(ChelaType.GetObjectType())));
            ctorArguments.Add(ReferenceType.Create(functionType));
            FunctionType ctorType = FunctionType.Create(ChelaType.GetVoidType(), ctorArguments);

            // Create the constructor method.
            Method ctorMethod = new Method("<ctor>", MemberFlags.Public | MemberFlags.Runtime | MemberFlags.Constructor, building);
            ctorMethod.SetFunctionType(ctorType);
            building.AddFunction("<ctor>", ctorMethod);

            // Create the invoke function.
            Method invokeMethod = new Method("Invoke", MemberFlags.Public | MemberFlags.Runtime, building);
            invokeMethod.SetFunctionType(invokeType);
            building.AddFunction("Invoke", invokeMethod);

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

            // Restore the security level.
            if(isUnsafe)
                PushUnsafe();

            return node;
        }