Synthetized routine parameter.
Inheritance: ParameterSymbol
示例#1
0
        protected virtual IEnumerable <ParameterSymbol> CreateParameters(IEnumerable <ParameterSymbol> baseparams)
        {
            int index = 0;

            // Context <ctx>
            yield return(new SpecialParameterSymbol(this, DeclaringCompilation.CoreTypes.Context, SpecialParameterSymbol.ContextName, index++));

            // same parameters as PHP constructor
            foreach (var p in baseparams)
            {
                if (!SpecialParameterSymbol.IsContextParameter(p))
                {
                    yield return(new SynthesizedParameterSymbol(this, p.Type, index++, p.RefKind, p.Name, p.IsParams,
                                                                explicitDefaultConstantValue: p.ExplicitDefaultConstantValue));
                }
            }
        }
示例#2
0
        /// <summary>
        /// Parameters for <see cref="SourceGeneratorSymbol"/> method are defined by <c>GeneratorStateMachineDelegate</c>.
        /// </summary>
        ParameterSymbol[] CreateParameters(SourceRoutineSymbol originalRoutine)
        {
            // resolve type of $this
            var thisType = originalRoutine.GetPhpThisVariablePlaceWithoutGenerator()?.Type ?? (TypeSymbol)originalRoutine.DeclaringCompilation.ObjectType;

            // yield sm method signature
            var index = 0;

            return(new[]
            {
                ContextParameter = new SpecialParameterSymbol(this, DeclaringCompilation.CoreTypes.Context, SpecialParameterSymbol.ContextName, index++),
                ThisParameter = new SpecialParameterSymbol(this, thisType, SpecialParameterSymbol.ThisName, index++),
                LocalsParameter = new SpecialParameterSymbol(this, DeclaringCompilation.CoreTypes.PhpArray, SpecialParameterSymbol.LocalsName, index++),
                TmpLocalsParameter = new SpecialParameterSymbol(this, DeclaringCompilation.CoreTypes.PhpArray, SpecialParameterSymbol.TemporaryLocalsName, index++),
                GeneratorParameter = new SpecialParameterSymbol(this, DeclaringCompilation.CoreTypes.Generator, "generator", index++),
            });
        }
示例#3
0
        void EmitTraitImplementations(Emit.PEModuleBuilder module)
        {
            foreach (var t in TraitUses)
            {
                foreach (var m in t.GetMembers().OfType <SynthesizedMethodSymbol>())
                {
                    Debug.Assert(m.ForwardedCall != null);

                    module.SetMethodBody(m, MethodGenerator.GenerateMethodBody(module, m, il =>
                    {
                        IPlace thisPlace          = null;
                        IPlace traitInstancePlace = null;
                        IPlace ctxPlace;

                        if (m.IsStatic)
                        {
                            // Template: return TRAIT.method(...)
                            Debug.Assert(SpecialParameterSymbol.IsContextParameter(m.Parameters[0]));
                            ctxPlace = new ParamPlace(m.Parameters[0]);
                        }
                        else
                        {
                            // Template: return this.<>trait.method(...)
                            thisPlace          = new ArgPlace(this, 0);                                   // this
                            ctxPlace           = new FieldPlace(thisPlace, this.ContextStore, module);    // this.<ctx>
                            traitInstancePlace = new FieldPlace(thisPlace, t.TraitInstanceField, module); // this.<>trait
                        }

                        using (var cg = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), module.Compilation.Options.OptimizationLevel, false, this, ctxPlace, thisPlace)
                        {
                            CallerType = this,
                        })
                        {
                            var forwarded_type = cg.EmitForwardCall(m.ForwardedCall, m, thisPlaceExplicit: traitInstancePlace);
                            var target_type    = m.ReturnType;

                            cg.EmitConvert(forwarded_type, 0, target_type); // always (forwarded_type === target_type)
                            cg.EmitRet(target_type);
                        }
                    }, null, DiagnosticBag.GetInstance(), false));
                    module.SynthesizedManager.AddMethod(this, m);
                }
            }
        }
示例#4
0
        void EmitPhpNew(SynthesizedPhpNewMethodSymbol phpnew, Emit.PEModuleBuilder module)
        {
            if (phpnew == null)
            {
                return;                 // static class
            }
            module.SetMethodBody(phpnew, MethodGenerator.GenerateMethodBody(module, phpnew, il =>
            {
                Debug.Assert(SpecialParameterSymbol.IsContextParameter(phpnew.Parameters[0]));

                var cg = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), OptimizationLevel.Release, false, this, new ParamPlace(phpnew.Parameters[0]), new ArgPlace(this, 0));

                // initialize <ctx> field,
                // if field is declared within this type
                var ctxField = this.ContextField;
                if (ctxField != null && object.ReferenceEquals(ctxField.ContainingType, this))
                {
                    var ctxFieldPlace = new FieldPlace(cg.ThisPlaceOpt, ctxField);

                    // Debug.Assert(<ctx> != null)
                    cg.EmitDebugAssertNotNull(cg.ContextPlaceOpt, "Context cannot be null.");

                    // <this>.<ctx> = <ctx>
                    ctxFieldPlace.EmitStorePrepare(il);
                    cg.EmitLoadContext();
                    ctxFieldPlace.EmitStore(il);
                }

                // initialize class fields,
                // default(PhpValue) is not a valid value, its TypeTable must not be null
                foreach (var fld in this.GetFieldsToEmit().OfType <SourceFieldSymbol>().Where(fld => !fld.IsStatic && !fld.IsConst))
                {
                    fld.EmitInit(cg);
                }

                // base..phpnew ?? base..ctor
                var basenew = phpnew.BasePhpNew;
                Debug.Assert(basenew != null);
                cg.EmitPop(cg.EmitThisCall(basenew, phpnew));

                Debug.Assert(phpnew.ReturnsVoid);
                cg.EmitRet(true);
            }, null, DiagnosticBag.GetInstance(), false));
        }
        /// <summary>
        /// Gets the special <c>&lt;static&gt;</c> parameter of given method if any. Otherwise <c>null</c>.
        /// </summary>
        internal static ParameterSymbol LateStaticParameter(this MethodSymbol method)
        {
            // in source routines, we can iterate just the implicit parameters and not populating the source parameters
            var ps = method is SourceRoutineSymbol sr ? sr.ImplicitParameters : method.Parameters;

            foreach (var p in ps)
            {
                if (SpecialParameterSymbol.IsLateStaticParameter(p))
                {
                    return(p);
                }
                else if (!p.IsImplicitlyDeclared)
                {
                    break;
                }
            }

            return(null);
        }
示例#6
0
        protected virtual IEnumerable<ParameterSymbol> CreateParameters(IEnumerable<ParameterSymbol> baseparams)
        {
            int index = 0;

            // Context <ctx>
            yield return new SpecialParameterSymbol(this, DeclaringCompilation.CoreTypes.Context, SpecialParameterSymbol.ContextName, index++);

            if (IsInitFieldsOnly)
            {
                // DummyFieldsOnlyCtor _
                yield return new SpecialParameterSymbol(this, DeclaringCompilation.CoreTypes.DummyFieldsOnlyCtor, "_", index++);
            }

            // same parameters as PHP constructor
            foreach (var p in baseparams)
            {
                if (SpecialParameterSymbol.IsContextParameter(p)) continue;
                if (SpecialParameterSymbol.IsDummyFieldsOnlyCtorParameter(p)) continue;

                yield return SynthesizedParameterSymbol.Create(this, p, index++);
            }
        }
示例#7
0
        /// <summary>
        /// Gets additional flags of the caller routine.
        /// </summary>
        public static RoutineFlags InvocationFlags(this IPhpRoutineSymbol routine)
        {
            var f = RoutineFlags.None;

            var ps = /*routine is SourceRoutineSymbol sr ? sr.ImplicitParameters :*/ routine.Parameters;

            foreach (var p in ps)
            {
                if (p.IsImplicitlyDeclared)
                {
                    if (SpecialParameterSymbol.IsImportValueParameter(p, out var spec))
                    {
                        switch (spec)
                        {
                        case SpecialParameterSymbol.ValueSpec.CallerArgs:
                            f |= RoutineFlags.UsesArgs;
                            break;

                        case SpecialParameterSymbol.ValueSpec.Locals:
                            f |= RoutineFlags.UsesLocals;
                            break;

                        case SpecialParameterSymbol.ValueSpec.CallerStaticClass:
                            f |= RoutineFlags.UsesLateStatic;
                            break;
                        }
                    }
                }
                else
                {
                    // implicit parameters are at begining only
                    break;
                }
            }

            return(f);
        }
        void EmitPhpCtors(ImmutableArray <MethodSymbol> instancectors, Emit.PEModuleBuilder module, DiagnosticBag diagnostics)
        {
            foreach (SynthesizedPhpCtorSymbol ctor in instancectors)
            {
                module.SetMethodBody(ctor, MethodGenerator.GenerateMethodBody(module, ctor, il =>
                {
                    if (ctor is SynthesizedParameterlessPhpCtorSymbol)
                    {
                        EmitParameterlessCtor(ctor, il, module, diagnostics);
                        return;
                    }

                    Debug.Assert(SpecialParameterSymbol.IsContextParameter(ctor.Parameters[0]));

                    var cg = new CodeGenerator(il, module, diagnostics, module.Compilation.Options.OptimizationLevel, false, this, new ParamPlace(ctor.Parameters[0]), new ArgPlace(this, 0))
                    {
                        CallerType     = this,
                        ContainingFile = ContainingFile,
                    };

                    Debug.Assert(ctor.BaseCtor != null);

                    // base..ctor or this..ctor
                    cg.EmitPop(cg.EmitForwardCall(ctor.BaseCtor, ctor));

                    if (ctor.PhpConstructor == null)
                    {
                        // initialize <ctx> field, if field is declared within this type
                        var ctxField = this.ContextStore;
                        if (ctxField != null && object.ReferenceEquals((object)ctxField.ContainingType, this))
                        {
                            var ctxFieldPlace = new FieldPlace(cg.ThisPlaceOpt, ctxField, module);

                            // Debug.Assert(<ctx> != null)
                            cg.EmitDebugAssertNotNull(cg.ContextPlaceOpt, "Context cannot be null.");

                            // <this>.<ctx> = <ctx>
                            ctxFieldPlace.EmitStorePrepare(il);
                            cg.EmitLoadContext();
                            ctxFieldPlace.EmitStore(il);
                        }

                        // trait specific:
                        if (ctor is SynthesizedPhpTraitCtorSymbol tctor)
                        {
                            EmitTraitCtorInit(cg, tctor);
                        }

                        // trait instances:
                        foreach (var t in this.TraitUses)
                        {
                            EmitTraitInstanceInit(cg, ctor, t);
                        }

                        // initialize instance fields:
                        foreach (var f in this.GetMembers().OfType <IPhpPropertySymbol>().Where(f => f.FieldKind == PhpPropertyKind.InstanceField))
                        {
                            Debug.Assert(f.ContainingStaticsHolder == null);
                            f.EmitInit(cg);
                        }
                    }
                    else
                    {
                        Debug.Assert(ctor.BaseCtor.ContainingType == this);

                        // this.__construct
                        cg.EmitPop(cg.EmitForwardCall(ctor.PhpConstructor, ctor));
                    }

                    // ret
                    Debug.Assert(ctor.ReturnsVoid);
                    cg.EmitRet(ctor.ReturnType);
                }, null, diagnostics, false));
            }
        }
示例#9
0
        void ResolveBaseCtorAndParameters()
        {
            if (!_parameters.IsDefaultOrEmpty)
            {
                return;
            }

            //
            var phpctor    = this.PhpCtor;                                    // this tells us what parameters are provided to resolve base .ctor that can be called
            var basephpnew = this.ContainingType.BaseType.PhpNewMethodSymbol; // base..phpnew() to be called if provided
            var basectors  = (basephpnew != null)
                ? ImmutableArray.Create(basephpnew)
                : this.ContainingType.BaseType.InstanceConstructors
                             .Where(c => c.DeclaredAccessibility != Accessibility.Private)
                             .OrderByDescending(c => c.ParameterCount) // longest ctors first
                             .AsImmutable();

            // Context <ctx>
            var ps = new List <ParameterSymbol>(1)
            {
                new SpecialParameterSymbol(this, DeclaringCompilation.CoreTypes.Context, SpecialParameterSymbol.ContextName, 0) // Context <ctx>
            };

            var givenparams = (phpctor != null)
                ? phpctor.Parameters.Where(p => !p.IsImplicitlyDeclared).ToArray()
                : EmptyArray <ParameterSymbol> .Instance;

            // find best matching basector
            foreach (var c in basectors)
            {
                var calledparams = c.Parameters.Where(p => !p.IsImplicitlyDeclared).ToArray();

                if (CanBePassedTo(givenparams, calledparams))
                {
                    // we have found base constructor with most parameters we can call with given parameters
                    _lazyBaseCtor = c;
                    break;
                }
            }

            if (_lazyBaseCtor == null)
            {
                throw new InvalidOperationException("Base .ctor cannot be resolved with provided constructor.");
            }

            //
            Debug.Assert(SpecialParameterSymbol.IsContextParameter(ps[0]));
            Debug.Assert(_lazyBaseCtor != null && !_lazyBaseCtor.IsStatic);

            foreach (var p in _lazyBaseCtor.Parameters)
            {
                if (SpecialParameterSymbol.IsContextParameter(p))
                {
                    continue;
                }

                ps.Add(new SynthesizedParameterSymbol(this, p.Type, ps.Count, p.RefKind, p.Name,
                                                      explicitDefaultConstantValue: p.ExplicitDefaultConstantValue));
            }

            //
            _parameters = ps.AsImmutable();
        }