Example #1
0
		internal void EmitDefinition(CodeGenerator/*!*/ codeGenerator)
		{
            if (type.IsComplete)
            {
                Debug.Assert(type.IsComplete, "Incomplete types should be converted to evals.");
                Debug.Assert(type.RealTypeBuilder != null, "A class declared during compilation should have a type builder.");

                attributes.Emit(codeGenerator, this);
                typeSignature.Emit(codeGenerator);

                codeGenerator.EnterTypeDeclaration(type);

                foreach (TypeMemberDecl member_decl in members)
                {
                    member_decl.EnterCodegenerator(codeGenerator);
                    member_decl.Emit(codeGenerator);
                    member_decl.LeaveCodegenerator(codeGenerator);
                }

                // emit stubs for implemented methods & properties that were not declared by this type:
                codeGenerator.EmitGhostStubs(type);

                codeGenerator.LeaveTypeDeclaration();
            }
            else
            {
                Debug.Assert(this.typeDefinitionCode != null);

                // LOAD DynamicCode.Eval(<code>, context, definedVariables, self, includer, source, line, column, evalId)
                
                // wrap Eval into static method
                MethodBuilder method = codeGenerator.IL.TypeBuilder.DefineMethod(
                    string.Format("{0}{1}", ScriptModule.DeclareHelperNane, type.FullName),
                    MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.SpecialName,
                    Types.Void, Types.ScriptContext);

                var il = new ILEmitter(method);
                    
                codeGenerator.EnterLambdaDeclaration(il, false, LiteralPlace.Null, new IndexedPlace(PlaceHolder.Argument, 0), LiteralPlace.Null, LiteralPlace.Null);
                if (true)
                {
                    codeGenerator.EmitEval(
                        EvalKinds.SyntheticEval,
                        new StringLiteral(position, this.typeDefinitionCode, AccessType.Read),
                        position,
                        (this.Namespace != null) ? this.Namespace.QualifiedName : (QualifiedName?)null, this.validAliases);
                    il.Emit(OpCodes.Pop);
                    il.Emit(OpCodes.Ret);
                }
                codeGenerator.LeaveFunctionDeclaration();

                //
                il = codeGenerator.IL;

                type.IncompleteClassDeclareMethodInfo = method;
                type.IncompleteClassDeclarationId = String.Format("{0}${1}:{2}:{3}", type.FullName, unchecked((uint)codeGenerator.SourceUnit.SourceFile.ToString().GetHashCode()), position.FirstLine, position.FirstColumn);

                // sequence point here
                codeGenerator.MarkSequencePoint(position.FirstLine, position.FirstColumn, position.LastLine, position.LastColumn + 2);
                
                if (type.Declaration.IsConditional)
                {
                    // CALL <Declare>.<FullName>(<context>)
                    codeGenerator.EmitLoadScriptContext();
                    il.Emit(OpCodes.Call, method);
                }
                else
                {
                    // if (!<context>.IncompleteTypeDeclared(<id>))
                    //     CALL <Declare>.<FullName>(<context>)
                    var end_if = il.DefineLabel();

                    codeGenerator.EmitLoadScriptContext();
                    il.Emit(OpCodes.Ldstr, type.IncompleteClassDeclarationId);
                    il.Emit(OpCodes.Call, Methods.ScriptContext.IncompleteTypeDeclared);
                    il.Emit(OpCodes.Brtrue, end_if);
                    if (true)
                    {
                        codeGenerator.EmitLoadScriptContext();
                        il.Emit(OpCodes.Call, type.IncompleteClassDeclareMethodInfo);
                    }
                    il.MarkLabel(end_if);
                    il.ForgetLabel(end_if);
                }
            }
		}