예제 #1
0
            /// <summary>Emits argument to be passed to callsite.</summary>
            public void EmitArg(BoundArgument a)
            {
                if (a.IsUnpacking)
                {
                    EmitUnpackingParam(_cg.Emit(a.Value));
                }
                else
                {
                    TypeSymbol t     = null;
                    bool       byref = false;

                    if (a.Value is BoundReferenceExpression varref && !varref.ConstantValue.HasValue)
                    {
                        // try read the value by ref,
                        // we might need the value ref in the callsite:

                        var place = varref.Place(_cg.Builder);
                        if (place != null && place.HasAddress && place.TypeOpt == _cg.CoreTypes.PhpValue)
                        {
                            place.EmitLoadAddress(_cg.Builder);

                            t     = place.TypeOpt;
                            byref = true;
                        }
                        else
                        {
                            var bound = varref.BindPlace(_cg);
                            bound.EmitLoadPrepare(_cg);
                            if ((bound.TypeOpt == null || bound.TypeOpt == _cg.CoreTypes.PhpValue) && // makes sense only if type is PhpValue (or unknown)
                                (t = bound.EmitLoadAddress(_cg)) != null)                             // try to load address
                            {
                                byref = true;
                            }
                            else
                            {
                                t = bound.EmitLoad(_cg); // just load by value if address cannot be loaded
                            }
                        }
                    }

                    if (t == null)
                    {
                        t = _cg.Emit(a.Value);
                    }

                    if (t.SpecialType == SpecialType.System_Void)
                    {
                        Debug.Fail("Unexpected: argument evaluates to 'void'.");
                        // NOTE: this is an error somewhere, no expression shall return void
                        t = _cg.Emit_PhpValue_Null();
                    }

                    AddArg(t, byref: byref);
                }
            }
 /// <summary>Emits argument to be passed to callsite.</summary>
 public void EmitArg(BoundArgument a)
 {
     if (a.IsUnpacking)
     {
         EmitUnpackingParam(_cg.Emit(a.Value));
     }
     else
     {
         AddArg(_cg.Emit(a.Value));
     }
 }
예제 #3
0
            /// <summary>Emits argument to be passed to callsite.</summary>
            public void EmitArg(BoundArgument a)
            {
                if (a.IsUnpacking)
                {
                    EmitUnpackingParam(_cg.Emit(a.Value));
                }
                else
                {
                    TypeSymbol t     = null;
                    bool       byref = false;

                    if (a.Value is BoundReferenceExpression varref && !varref.ConstantValue.HasValue)
                    {
                        // try read the value by ref,
                        // we might need the value ref in the callsite:

                        var place = varref.Place(_cg.Builder);
                        if (place != null && place.HasAddress && place.TypeOpt == _cg.CoreTypes.PhpValue)
                        {
                            place.EmitLoadAddress(_cg.Builder);

                            t     = place.TypeOpt;
                            byref = true;
                        }
                        else
                        {
                            var bound = varref.BindPlace(_cg);
                            bound.EmitLoadPrepare(_cg);
                            if ((bound.TypeOpt == null || bound.TypeOpt == _cg.CoreTypes.PhpValue) && // makes sense only if type is PhpValue (or unknown)
                                (t = bound.EmitLoadAddress(_cg)) != null)                             // try to load address
                            {
                                byref = true;
                            }
                            else
                            {
                                t = bound.EmitLoad(_cg); // just load by value if address cannot be loaded
                            }
                        }
                    }

                    if (t == null)
                    {
                        t = _cg.Emit(a.Value);
                    }

                    AddArg(t, byref: byref);
                }
            }
예제 #4
0
        public override T VisitArgument(BoundArgument x)
        {
            base.VisitArgument(x);

            //if (!x.Value.TypeRefMask.IsRef && NOT PASSED BY REF) // if value is referenced, we dunno
            //{
            //    // argument should not be 'void' (NULL in PHP)
            //    if ((x.Type != null && x.Type.SpecialType == SpecialType.System_Void) ||
            //        x.Value.TypeRefMask.IsVoid(TypeCtx))
            //    {
            //        // WRN: Argument has no value, parameter will be always NULL
            //        _diagnostics.Add(_routine, x.Value.PhpSyntax, ErrorCode.WRN_ArgumentVoid);
            //    }
            //}

            //
            return default;
        }
예제 #5
0
            /// <summary>Emits argument to be passed to callsite.</summary>
            public void EmitArg(BoundArgument a)
            {
                if (a.IsUnpacking)
                {
                    EmitUnpackingParam(_cg.Emit(a.Value));
                }
                else
                {
                    TypeSymbol t     = null;
                    bool       byref = false;

                    if (a.Value is BoundReferenceExpression varref && !varref.ConstantValue.HasValue)
                    {
                        // try read the value by ref,
                        // we might need the value ref in the callsite:

                        var bound = varref.BindPlace(_cg);
                        if (bound is LocalVariableReference loc && !loc.IsOptimized)
                        {
                            t = loc.LoadIndirectLocal(_cg); // IndirectLocal wrapper
                        }
예제 #6
0
            /// <summary>Emits argument to be passed to callsite.</summary>
            void EmitArg(BoundArgument a)
            {
                var expr = a.Value;

                if (a.IsUnpacking)
                {
                    EmitUnpackingParam(_cg.Emit(expr));
                }
                else
                {
                    RuntimeChainElement runtimeChain = null;

                    // construct the runtime chain if possible:
                    while (TryConstructRuntimeChainElement(expr, out var element))
                    {
                        element.Next = runtimeChain ?? new RuntimeChainElement(_cg.CoreTypes.RuntimeChain_ChainEnd);
                        if (element.Type.Arity == 1)
                        {
                            // construct Element<TNext> // TNext:typeof(element.Next)
                            element.Type = element.Type.Construct(element.Next.Type);
                        }
                        runtimeChain = element;

                        //
                        if (element.Parent == null)
                        {
                            break;
                        }

                        expr = element.Parent;
                    }

                    // emit the root of the chain:
                    TypeSymbol t     = null;
                    bool       byref = false;

                    if (!expr.IsConstant() && expr is BoundReferenceExpression varref)
                    {
                        // try to read the value by ref so it can be changed if necessary
                        var place = varref.Place();
                        if (place != null)
                        {
                            if (place.HasAddress && place.Type == _cg.CoreTypes.PhpValue)
                            {
                                place.EmitLoadAddress(_cg.Builder);
                                t     = place.Type;
                                byref = true;
                            }
                        }
                        else if (varref.BindPlace(_cg) is LocalVariableReference loc && !loc.IsOptimized)
                        {
                            t = loc.LoadIndirectLocal(_cg); // IndirectLocal wrapper
                        }
                    }

                    if (t == null)
                    {
                        // load by value
                        t = _cg.Emit(expr);
                    }

                    if (t.SpecialType == SpecialType.System_Void)
                    {
                        Debug.WriteLine("Unexpected: argument evaluates to 'void'.");
                        // NOTE: this should be handled in diagnostics
                        t = _cg.Emit_PhpValue_Null();
                    }

                    //
                    AddArg(t, byref: byref);

                    // emit the chain eventually:
                    // after the root of the chain, order matters!
                    if (runtimeChain != null)
                    {
                        AddArg(runtimeChain.EmitRuntimeChain(_cg), byref: false);
                    }
                }
            }
예제 #7
0
 public override object VisitArgument(BoundArgument x)
 {
     return(x.Update(
                (BoundExpression)Accept(x.Value),
                x.ArgumentKind));
 }
예제 #8
0
 private static bool IsEmptyString(BoundArgument a) => a.Value.ConstantValue.HasValue && ExpressionsExtension.IsEmptyStringValue(a.Value.ConstantValue.Value);
예제 #9
0
        public override object VisitConcat(BoundConcatEx x)
        {
            // transform arguments first:
            x = (BoundConcatEx)base.VisitConcat(x);

            //
            var args = x.ArgumentsInSourceOrder;

            if (args.Length == 0 || args.All(IsEmptyString))
            {
                // empty string:
                TransformationCount++;
                return(new BoundLiteral(string.Empty)
                {
                    ConstantValue = new Optional <object>(string.Empty)
                }.WithContext(x));
            }

            // visit & concat in compile time if we can:
            var newargs = args;
            int i       = 0;

            do
            {
                // accumulate evaluated string value if possible:
                if (newargs[i].Value.ConstantValue.TryConvertToString(out var value))
                {
                    string result = value;
                    int    end    = i + 1;
                    while (end < newargs.Length && newargs[end].Value.ConstantValue.TryConvertToString(out var tmp))
                    {
                        result += tmp;
                        end++;
                    }

                    if (end > i + 1) // we concat'ed something!
                    {
                        newargs = newargs.RemoveRange(i, end - i);

                        if (!string.IsNullOrEmpty(result))
                        {
                            newargs = newargs.Insert(i, BoundArgument.Create(new BoundLiteral(result)
                            {
                                ConstantValue = new Optional <object>(result),
                                TypeRefMask   = _routine.TypeRefContext.GetStringTypeMask(),
                                ResultType    = DeclaringCompilation.CoreTypes.String,
                            }.WithAccess(BoundAccess.Read)));
                        }
                    }
                }

                //
                i++;
            } while (i < newargs.Length);

            //
            if (newargs != args)
            {
                TransformationCount++;

                if (newargs.Length == 0)
                {
                    return(new BoundLiteral(string.Empty)
                    {
                        ConstantValue = new Optional <object>(string.Empty)
                    }.WithContext(x));
                }
                else if (newargs.Length == 1 && newargs[0].Value.ConstantValue.TryConvertToString(out var value))
                {
                    // "value"
                    return(new BoundLiteral(value)
                    {
                        ConstantValue = new Optional <object>(value)
                    }.WithContext(x));
                }

                //
                return(x.Update(newargs));
            }

            //
            return(x);
        }
예제 #10
0
 public virtual void VisitArgument(BoundArgument x)
 {
     Accept(x.Value);
 }
예제 #11
0
        public override void VisitArgument(BoundArgument x)
        {
            if (x.Parameter != null)
            {
                // TODO: write arguments access
                // TODO: conversion by simplifier visitor
            }

            Accept(x.Value);
        }