public void Analyze(ActualParam/*!*/node, Analyzer/*!*/ analyzer, bool isBaseCtorCallConstrained) { // TODO: isBaseCtorCallConstrained ExInfoFromParent info = new ExInfoFromParent(node); analyzer.EnterActParam(); if (node.IsVariadic) throw new NotImplementedException(); if (analyzer.ActParamDeclIsUnknown()) { // we don't know whether the parameter will be passed by reference at run-time: if (node.Expression.AllowsPassByReference) { info.Access = AccessType.ReadUnknown; // Although we prepare to pass reference, value can be really passed. // That's why we report warning when user use '&' in calling, // because it has no influence. if (node.Ampersand) analyzer.ErrorSink.Add(Warnings.ActualParamWithAmpersand, analyzer.SourceUnit, node.Span); } else { info.Access = AccessType.Read; } } else { if (analyzer.ActParamPassedByRef()) { if (node.Expression.AllowsPassByReference) { info.Access = AccessType.ReadRef; } else { analyzer.ErrorSink.Add(Errors.NonVariablePassedByRef, analyzer.SourceUnit, node.Expression.Span); analyzer.LeaveActParam(); return; } } else { info.Access = AccessType.Read; if (node.Ampersand) analyzer.ErrorSink.Add(Warnings.ActualParamWithAmpersand, analyzer.SourceUnit, node.Span); } } node._expression = node.Expression.Analyze(analyzer, info).Literalize(); // TODO: if signature is known, act. param has type hint and expression has known type; check if type hint matches expression analyzer.LeaveActParam(); }
/// <summary> /// Visit actual parameter expression. /// </summary> /// <param name="x"></param> virtual public void VisitActualParam(ActualParam x) { VisitElement(x.Expression); }
public PhpTypeCode Emit(ActualParam/*!*/node, CodeGenerator/*!*/ codeGenerator, bool ensureChainWritable = false) { codeGenerator.ChainBuilder.Create(); if (ensureChainWritable) codeGenerator.ChainBuilder.EnsureWritable = true; try { return node.Expression.Emit(codeGenerator); } finally { codeGenerator.ChainBuilder.End(); } }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Expression.Analyze"]/*'/> internal override Evaluation Analyze(Analyzer /*!*/ analyzer, ExInfoFromParent info) { access = info.Access; ExInfoFromParent lvalue_info = new ExInfoFromParent(this); // x[] = y if (lvalue is ItemUse && ((ItemUse)lvalue).Index == null) { if (operation != Operations.AssignValue) { var oldop = operation; operation = Operations.AssignValue; // x[] .= y -> x[] = null . y if (oldop == Operations.AssignAppend) { rvalue = new BinaryEx(Position, Operations.Concat, new NullLiteral(Position), rvalue); } // x[] += y -> x[] = 0 + y else if (oldop == Operations.AssignAdd) { rvalue = new BinaryEx(Position, Operations.Add, new NullLiteral(Position), rvalue); } // x[] -= y -> x[] = 0 - y else if (oldop == Operations.AssignSub) { rvalue = new BinaryEx(Position, Operations.Sub, new NullLiteral(Position), rvalue); } // x[] *= y -> x[] = 0 * y else if (oldop == Operations.AssignMul) { rvalue = new BinaryEx(Position, Operations.Mul, new NullLiteral(Position), rvalue); } // x[] /= y -> x[] = 0 / y else if (oldop == Operations.AssignDiv) { rvalue = new BinaryEx(Position, Operations.Div, new NullLiteral(Position), rvalue); } // x[] &= y -> x[] = 0 & y else if (oldop == Operations.AssignAnd) { rvalue = new BinaryEx(Position, Operations.BitAnd, new NullLiteral(Position), rvalue); } else { Debug.Fail("Unhandled operation " + oldop.ToString() + " must be reduced!"); operation = oldop; // change it back, this will result in compile time exception } } } // stop evaluation: rvalue = rvalue.Analyze(analyzer, ExInfoFromParent.DefaultExInfo).Literalize(); if (operation == Operations.AssignValue) { // elimination of $x = $x . expr var concat = rvalue as ConcatEx; DirectVarUse vur; DirectVarUse vul = lvalue as DirectVarUse; if (concat != null && concat.Expressions.Count >= 2 && vul != null && vul.IsMemberOf == null) { if ((vur = concat.Expressions[0] as DirectVarUse) != null && vur.VarName.Equals(vul.VarName) && vur.IsMemberOf == null) { // $x = $x.a.b.c // => // $x .= a.b.c operation = Operations.AssignAppend; lvalue_info.Access = AccessType.ReadAndWrite; //rvalue = concat.RightExpr; concat.Expressions.RemoveAt(0); } else if ((vur = concat.Expressions[concat.Expressions.Count - 1] as DirectVarUse) != null && vur.VarName.Equals(vul.VarName) && vur.IsMemberOf == null) { // $x = a.b.c.$x // => // $x =. a.b.c operation = Operations.AssignPrepend; lvalue_info.Access = AccessType.ReadAndWrite; //rvalue = (Expression)concat.LeftExpr; concat.Expressions.RemoveAt(concat.Expressions.Count - 1); } else { lvalue_info.Access = AccessType.Write; } } else { lvalue_info.Access = AccessType.Write; } } else { lvalue_info.Access = AccessType.ReadAndWrite; } // If this ValueAssignEx is actual param that is to be passed by reference, // AccessType of the destVar has to be changed, because its reference will be // (potencially) passeed ActualParam ap = info.Parent as ActualParam; if (ap != null) { if (analyzer.ActParamDeclIsUnknown()) { if (lvalue_info.Access == AccessType.Write) { lvalue_info.Access = AccessType.WriteAndReadUnknown; } else { lvalue_info.Access = AccessType.ReadAndWriteAndReadUnknown; } } else if (analyzer.ActParamPassedByRef()) { if (lvalue_info.Access == AccessType.Write) { lvalue_info.Access = AccessType.WriteAndReadRef; } else { lvalue_info.Access = AccessType.ReadAndWriteAndReadRef; } } } lvalue.Analyze(analyzer, lvalue_info); //retval not needed ... return(new Evaluation(this)); }