예제 #1
0
        internal void EmitHelpers()
        {
            CompilationUnit unit = this.CompilationUnit;
            ILEmitter       il   = new ILEmitter(DeclareHelperBuilder);
            IndexedPlace    script_context_place = new IndexedPlace(PlaceHolder.Argument, 0);

            foreach (PhpFunction function in unit.GetDeclaredFunctions())
            {
                if (function.IsDefinite)
                {
                    CodeGenerator.EmitDeclareFunction(il, script_context_place, function);
                }
            }

            foreach (PhpType type in unit.GetDeclaredTypes())
            {
                if (type.IsDefinite)
                {
                    // CALL <context>.DeclareType(<type desc>, <name>);
                    type.EmitAutoDeclareOnScriptContext(il, script_context_place);
                }
                else if (!type.IsComplete)
                {
                    if (type.IncompleteClassDeclareMethodInfo != null)
                    {
                        // check whether base class is known at this point of execution,
                        // if so, declare this incomplete class immediately. As PHP does.

                        type.EmitDeclareIncompleteOnScriptContext(il, script_context_place);
                    }
                }
            }

            foreach (GlobalConstant constant in unit.GetDeclaredConstants())
            {
                if (constant.IsDefinite)
                {
                    var field = constant.RealField;
                    Debug.Assert(field != null);
                    Debug.Assert(field.IsStatic);

                    // CALL <context>.DeclareConstant(<name>, <value>);
                    script_context_place.EmitLoad(il);

                    il.Emit(OpCodes.Ldstr, constant.FullName);
                    il.LoadLiteralBox(constant.Value);  //il.Emit(OpCodes.Ldsfld, field);   // const field cannot be referenced in IL
                    il.Emit(OpCodes.Call, Methods.ScriptContext.DeclareConstant);
                }
            }

            il.Emit(OpCodes.Ret);
        }
예제 #2
0
        /// <summary>
        /// Emit the Script attribute with includes,includers,relativePath and timeStamp info.
        /// </summary>
        /// <param name="emitAttributes">Specifies single infos to emit.</param>
        internal void SetScriptAttribute(ScriptAttributes emitAttributes)
        {
            // module to resolve type tokens from:
            ModuleBuilder real_builder = this.AssemblyBuilder.RealModuleBuilder;

            // [Script(timeStamp, relativePath)]
            if ((emitAttributes & ScriptAttributes.Script) != 0)
            {
                // construct the [Script] attribute:
                CustomAttributeBuilder cab = new CustomAttributeBuilder(Constructors.Script, new object[] { sourceTimestamp.Ticks, CompilationUnit.RelativeSourcePath });
                ScriptTypeBuilder.SetCustomAttribute(cab);
            }

            // [ScriptIncluders(int[])]
            if ((emitAttributes & ScriptAttributes.ScriptIncluders) != 0 && CompilationUnit.Includers.Count > 0)
            {
                // determine includers type token, remove duplicities:
                int[] includers = ArrayUtils.Unique(Array.ConvertAll(CompilationUnit.Includers.ToArray(), x => real_builder.GetTypeToken(x.Includer.ScriptBuilder.ScriptType).Token)).ToArray();

                // construct the [ScriptIncluders] attribute:
                CustomAttributeBuilder cab = new CustomAttributeBuilder(Constructors.ScriptIncluders, new object[] { includers });
                ScriptTypeBuilder.SetCustomAttribute(cab);
            }

            // [ScriptIncludees(int[],byte[])]
            if ((emitAttributes & ScriptAttributes.ScriptIncludees) != 0 && CompilationUnit.Inclusions.Count > 0)
            {
                // determine inclusions type token, group by the token to remove duplicities:
                var inclusionsGroup = ArrayUtils.Group(CompilationUnit.Inclusions.ToArray(), x => real_builder.GetTypeToken(x.Includee.ScriptClassType).Token);
                // determine if single includees are at least once included unconditionally:
                int[]  inclusions = new int[inclusionsGroup.Count];
                bool[] inclusionsConditionalFlag = new bool[inclusions.Length];

                int i = 0;
                foreach (var includee in inclusionsGroup)
                {
                    // find any unconditional inclusion to mark this unified inclusion as unconditional
                    inclusionsConditionalFlag[i] = ArrayUtils.LogicalAnd(includee.Value, x => x.IsConditional);
                    //
                    inclusions[i] = includee.Key;
                    ++i;
                }

                // construct the [ScriptIncluders] attribute:
                CustomAttributeBuilder cab = new CustomAttributeBuilder(Constructors.ScriptIncludees, new object[] { inclusions, ScriptIncludeesAttribute.ConvertBoolsToBits(inclusionsConditionalFlag) });
                ScriptTypeBuilder.SetCustomAttribute(cab);
            }

            // [ScriptDeclares(int[])]
            if ((emitAttributes & ScriptAttributes.ScriptDeclares) != 0)
            {
                List <int> declaredTypesToken = new List <int>();

                foreach (PhpType type in CompilationUnit.GetDeclaredTypes())
                {
                    if (type.IsComplete && type.RealType != null)
                    {
                        declaredTypesToken.Add(real_builder.GetTypeToken(type.RealType).Token);
                    }
                }

                if (declaredTypesToken.Count > 0)
                {
                    // construct the [ScriptDeclares] attribute:
                    CustomAttributeBuilder cab = new CustomAttributeBuilder(Constructors.ScriptDeclares, new object[] { declaredTypesToken.ToArray() });
                    ScriptTypeBuilder.SetCustomAttribute(cab);
                }
            }
        }