/// <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)); } }
/// <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); } }
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; }
/// <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 }
/// <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); } } }
public override object VisitArgument(BoundArgument x) { return(x.Update( (BoundExpression)Accept(x.Value), x.ArgumentKind)); }
private static bool IsEmptyString(BoundArgument a) => a.Value.ConstantValue.HasValue && ExpressionsExtension.IsEmptyStringValue(a.Value.ConstantValue.Value);
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); }
public virtual void VisitArgument(BoundArgument x) { Accept(x.Value); }
public override void VisitArgument(BoundArgument x) { if (x.Parameter != null) { // TODO: write arguments access // TODO: conversion by simplifier visitor } Accept(x.Value); }