internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { if (_isCondition) { return(TransformReadCondition(gen)); } else { return((_isExclusive ? Methods.CreateExclusiveRange : Methods.CreateInclusiveRange). OpCall(gen.CurrentScopeVariable, AstFactory.Box(_begin.TransformRead(gen)), AstFactory.Box(_end.TransformRead(gen)))); } }
internal override MSA.Expression TransformDefinedCondition(AstGenerator/*!*/ gen) { // MRI doesn't evaluate the arguments MSA.Expression result = AstUtils.LightDynamic( RubyCallAction.Make(gen.Context, _methodName, RubyCallSignature.IsDefined(_target == null)), typeof(bool), gen.CurrentScopeVariable, (_target != null) ? AstUtils.Box(_target.TransformRead(gen)) : gen.CurrentSelfVariable ); return (_target != null) ? gen.TryCatchAny(result, AstFactory.False) : result; }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { if (_value != null) { return(Ast.Block( AstUtils.IfThen( _condition.TransformReadBoolean(gen, !_negateCondition), _jumpStatement.Transform(gen) ), _value.TransformRead(gen) )); } else { MSA.Expression tmpVariable = gen.CurrentScope.DefineHiddenVariable("#tmp_cond", typeof(object)); return(Ast.Block( Ast.Assign(tmpVariable, AstUtils.Box(_condition.TransformRead(gen))), AstUtils.IfThen( (_negateCondition ? Methods.IsFalse : Methods.IsTrue).OpCall(tmpVariable), _jumpStatement.Transform(gen) ), tmpVariable )); } }
// when <expr0>, ... [*<array>] // generates: // <MakeTest>(<expr0>) || <MakeTest>(<expr1>) || ... [ || <MakeArrayTest>(<array>) ] internal static MSA.Expression /*!*/ TransformWhenCondition(AstGenerator /*!*/ gen, Expression[] comparisons, Expression comparisonArray, MSA.Expression value) { MSA.Expression result; if (comparisonArray != null) { result = MakeArrayTest(gen, comparisonArray.TransformRead(gen), value); } else { result = AstUtils.Constant(false); } if (comparisons != null) { for (int i = comparisons.Length - 1; i >= 0; i--) { result = Ast.OrElse( MakeTest(gen, comparisons[i].TransformRead(gen), value), result ); } } return(result); }
internal StaticScopeKind TransformQualifier(AstGenerator /*!*/ gen, out MSA.Expression transformedQualifier) { if (_qualifier != null) { Debug.Assert(_explicitlyBound); // qualifier.Foo transformedQualifier = _qualifier.TransformRead(gen); return(StaticScopeKind.Explicit); } else if (_explicitlyBound) { // ::Foo transformedQualifier = null; return(StaticScopeKind.Global); } else if (gen.CurrentModule != null) { // statically (lexically) implicitly bound to the enclosing module: transformedQualifier = gen.CurrentModule.SelfVariable; // TODO: remove, should be retrieved from code context/scope return(StaticScopeKind.EnclosingModule); } else { // statically (lexically) implicitly bound to top declaring module: transformedQualifier = null; return(StaticScopeKind.EnclosingModule); } }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { MSA.Expression transformedTarget; bool hasImplicitSelf; if (_target != null) { transformedTarget = _target.TransformRead(gen); hasImplicitSelf = false; } else { transformedTarget = gen.CurrentSelfVariable; hasImplicitSelf = true; } return(TransformRead(this, gen, hasImplicitSelf, _methodName, transformedTarget, Arguments, Block, null, null)); }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { return(Ast.Condition( TransformCondition(gen), AstFactory.Box(_body.TransformRead(gen)), (_elseStatement != null) ? AstFactory.Box(_elseStatement.TransformRead(gen)) : (MSA.Expression)Ast.Constant(null) )); }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { return(AstFactory.Condition( _condition.TransformReadBoolean(gen, true), _trueExpression.TransformRead(gen), _falseExpression.TransformRead(gen) )); }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { return(AstFactory.Condition( Methods.IsFalse.OpCall(AstFactory.Box(_condition.TransformRead(gen))), gen.TransformStatementsToExpression(_statements), gen.TransformStatementsToExpression(_elseClause != null ? _elseClause.Statements : null) )); }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { return(Ast.Condition( _condition.TransformReadBoolean(gen, !_negateCondition), AstUtils.Box(_body.TransformRead(gen)), (_elseStatement != null) ? AstUtils.Box(_elseStatement.TransformRead(gen)) : (MSA.Expression)AstUtils.Constant(null) )); }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { return(Methods.DefineMethod.OpCall( (_target != null) ? AstUtils.Box(_target.TransformRead(gen)) : AstUtils.Constant(null), gen.CurrentScopeVariable, Ast.Constant(new RubyMethodBody(this, gen.Document, gen.Encoding)) )); }
private MSA.Expression /*!*/ TransformSplatType(AstGenerator /*!*/ gen) { return(Ast.Dynamic( TryConvertToArrayAction.Instance, typeof(object), gen.CurrentScopeVariable, _splatType.TransformRead(gen) )); }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { // TODO: // {target}[{arguments}] op= rhs // we need to evaluate {arguments} once: http://ironruby.codeplex.com/workitem/4525 // first, read target into a temp: MSA.Expression transformedLeftTarget = _left.TransformTargetRead(gen); MSA.Expression leftTargetTemp; if (transformedLeftTarget != null) { leftTargetTemp = gen.CurrentScope.DefineHiddenVariable(String.Empty, transformedLeftTarget.Type); } else { leftTargetTemp = null; } MSA.Expression transformedRight = _right.TransformRead(gen); // lhs &&= rhs --> lhs && (lhs = rhs) // lhs ||= rhs --> lhs || (lhs = rhs) if (Operation == Symbols.And || Operation == Symbols.Or) { MSA.Expression transformedLeftRead = _left.TransformRead(gen, (transformedLeftTarget != null) ? Ast.Assign(leftTargetTemp, transformedLeftTarget) : null, true // tryRead ); MSA.Expression transformedWrite = _left.TransformWrite(gen, leftTargetTemp, transformedRight); if (Operation == Symbols.And) { return(AndExpression.TransformRead(gen, transformedLeftRead, transformedWrite)); } else { return(OrExpression.TransformRead(gen, transformedLeftRead, transformedWrite)); } } else { // lhs op= rhs --> lhs = lhs op rhs if (Operation != null) { MSA.Expression transformedLeftRead = _left.TransformRead(gen, leftTargetTemp, false); transformedRight = MethodCall.TransformRead(this, gen, false, Operation, transformedLeftRead, null, null, transformedRight, null); } // transform lhs write assigning lhs-target temp: return(_left.TransformWrite(gen, (transformedLeftTarget != null) ? Ast.Assign(leftTargetTemp, transformedLeftTarget) : null, transformedRight )); } }
internal override MSA.Expression /*!*/ Transform(AstGenerator /*!*/ gen) { Assert.NotNull(gen); return(Ast.Dynamic( ConvertToProcAction.Instance, typeof(Proc), gen.CurrentScopeVariable, _expression.TransformRead(gen) )); }
internal void TransformToCall(AstGenerator /*!*/ gen, CallBuilder callBuilder) { if (_expressions != null) { foreach (var arg in _expressions) { callBuilder.Add(arg.TransformRead(gen)); } } if (_maplets != null) { callBuilder.Add(gen.TransformToHashConstructor(_maplets)); } if (_array != null) { callBuilder.SplattedArgument = _array.TransformRead(gen); } }
internal void TransformToCall(AstGenerator /*!*/ gen, CallSiteBuilder /*!*/ siteBuilder) { if (_expressions != null) { foreach (var arg in _expressions) { siteBuilder.Add(arg.TransformRead(gen)); } } if (_maplets != null) { siteBuilder.Add(gen.TransformToHashConstructor(_maplets)); } if (_array != null) { siteBuilder.SplattedArgument = AstUtils.LightDynamic(SplatAction.Make(gen.Context), typeof(IList), _array.TransformRead(gen)); } }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { MSA.Expression transformedCondition = AstFactory.Box(_condition.TransformRead(gen)); MSA.Expression tmpVariable = gen.CurrentScope.DefineHiddenVariable("#tmp_cond", transformedCondition.Type); return(AstFactory.Block( Ast.Assign(tmpVariable, transformedCondition), AstUtils.IfThen( (_negateCondition ? AstFactory.IsFalse(tmpVariable) : AstFactory.IsTrue(tmpVariable)), _jumpStatement.Transform(gen) ), (_value != null) ? _value.TransformRead(gen) : tmpVariable )); }
internal StaticScopeKind TransformQualifier(AstGenerator /*!*/ gen, out MSA.Expression transformedQualifier) { if (_qualifier != null) { Debug.Assert(_explicitlyBound); // qualifier.Foo transformedQualifier = _qualifier.TransformRead(gen); return(StaticScopeKind.Explicit); } else if (_explicitlyBound) { // ::Foo transformedQualifier = null; return(StaticScopeKind.Global); } else { // bound to the enclosing module: transformedQualifier = null; return(StaticScopeKind.EnclosingModule); } }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { MSA.Expression result; if (_elseStatements != null) { // ... else body end result = gen.TransformStatementsToExpression(_elseStatements); } else { // no else clause => the result of the if-expression is nil: result = AstUtils.Constant(null); } MSA.Expression value; if (_value != null) { value = gen.CurrentScope.DefineHiddenVariable("#case-compare-value", typeof(object)); } else { value = null; } if (_whenClauses != null) { for (int i = _whenClauses.Count - 1; i >= 0; i--) { // emit: else (if (condition) body else result) result = AstFactory.Condition( TransformWhenCondition(gen, _whenClauses[i].Comparisons, _whenClauses[i].ComparisonArray, value), gen.TransformStatementsToExpression(_whenClauses[i].Statements), result ); } } if (_value != null) { result = Ast.Block( Ast.Assign(value, Ast.Convert(_value.TransformRead(gen), typeof(object))), result ); } return(result); }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { Assert.NotNull(gen); MSA.Expression transformedBlock = _block.Transform(gen); MSA.Expression blockArgVariable = gen.CurrentScope.DefineHiddenVariable("#forloop-block", typeof(Proc)); MSA.Expression result = CallSiteBuilder.InvokeMethod(gen.Context, "each", RubyCallSignature.WithScopeAndBlock(0), gen.CurrentScopeVariable, _list.TransformRead(gen), blockArgVariable ); return(gen.DebugMark(MethodCall.MakeCallWithBlockRetryable(gen, result, blockArgVariable, transformedBlock, true), "#RB: method call with a block ('for-loop')")); }
// // Traverses expressions in "parts" and concats all contiguous literal strings. // Notes: // - Instead of usign StringBuilder we place the string values that can be concatenated so far in to "literals" list and keep track // of their total length in "concatLength" and encoding in "concatEncoding". // If we reach a non-literal expression and we have some literals ready in "literals" array we do the concat and clear the list // and "concatLength" and "concatEncoding". // - "result" list contains argument expressions to the CreateMutableString* overloads. // - "opName" contains the name of the operation. This method appends suffix based on the argument types (see RubyOps.Suffix*). // private static void ConcatLiteralsAndTransformRecursive(AstGenerator /*!*/ gen, List <Expression> /*!*/ parts, List <string> /*!*/ literals, ref int concatLength, ref StringLiteralEncoding concatEncoding, List <MSA.Expression> /*!*/ result, StringBuilder /*!*/ opName) { for (int i = 0; i < parts.Count; i++) { Expression part = parts[i]; StringLiteral literal; StringConstructor ctor; if ((literal = part as StringLiteral) != null) { literals.Add(literal.Value); concatEncoding = CombineEncoding(concatEncoding, literal); concatLength += literal.Value.Length; } else if ((ctor = part as StringConstructor) != null) { ConcatLiteralsAndTransformRecursive(gen, ctor.Parts, literals, ref concatLength, ref concatEncoding, result, opName); } else { if (literals.Count > 0) { result.Add(Ast.Constant(Concat(literals, concatLength))); opName.Append(OpSuffix(gen, concatEncoding)); concatLength = 0; concatEncoding = StringLiteralEncoding.Ascii; literals.Clear(); } result.Add( Ast.Dynamic( ConvertToSAction.Instance, typeof(MutableString), gen.CurrentScopeVariable, part.TransformRead(gen) ) ); opName.Append(RubyOps.SuffixMutable); } } }
internal override MSA.Expression /*!*/ MakeDefinitionExpression(AstGenerator /*!*/ gen) { MSA.Expression transformedQualifier; MSA.Expression name = QualifiedName.TransformName(gen); MSA.Expression transformedSuper = (_superClass != null) ? AstUtils.Box(_superClass.TransformRead(gen)) : AstUtils.Constant(null); switch (QualifiedName.TransformQualifier(gen, out transformedQualifier)) { case StaticScopeKind.Global: return(Methods.DefineGlobalClass.OpCall(gen.CurrentScopeVariable, name, transformedSuper)); case StaticScopeKind.EnclosingModule: return(Methods.DefineNestedClass.OpCall(gen.CurrentScopeVariable, name, transformedSuper)); case StaticScopeKind.Explicit: return(Methods.DefineClass.OpCall(gen.CurrentScopeVariable, transformedQualifier, name, transformedSuper)); } throw Assert.Unreachable; }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { int intBegin, intEnd; if (IsIntegerRange(out intBegin, out intEnd)) { return((_isExclusive ? Methods.CreateExclusiveIntegerRange : Methods.CreateInclusiveIntegerRange).OpCall( AstUtils.Constant(intBegin), AstUtils.Constant(intEnd) )); } else { return((_isExclusive ? Methods.CreateExclusiveRange : Methods.CreateInclusiveRange).OpCall( AstUtils.Box(_begin.TransformRead(gen)), AstUtils.Box(_end.TransformRead(gen)), gen.CurrentScopeVariable, AstUtils.Constant(new BinaryOpStorage(gen.Context)) )); } }
// when <expr> // generates into: // RubyOps.IsTrue(<expr>) if the case has no value, otherise: // RubyOps.IsTrue(Call("===", <expr>, <value>)) private static MSA.Expression /*!*/ MakeTest(AstGenerator /*!*/ gen, Expression /*!*/ expr, MSA.Expression value) { MSA.Expression transformedExpr = expr.TransformRead(gen); if (expr is SplattedArgument) { if (value != null) { return(Methods.ExistsUnsplatCompare.OpCall( Ast.Constant(CallSite <Func <CallSite, object, object, object> > .Create( RubyCallAction.Make(gen.Context, "===", RubyCallSignature.WithImplicitSelf(2)) )), AstUtils.LightDynamic(ExplicitTrySplatAction.Make(gen.Context), transformedExpr), AstUtils.Box(value) )); } else { return(Methods.ExistsUnsplat.OpCall( AstUtils.LightDynamic(ExplicitTrySplatAction.Make(gen.Context), transformedExpr) )); } } else { if (value != null) { return(AstFactory.IsTrue( CallSiteBuilder.InvokeMethod(gen.Context, "===", RubyCallSignature.WithScope(1), gen.CurrentScopeVariable, transformedExpr, value ) )); } else { return(AstFactory.IsTrue(transformedExpr)); } } }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { string setterName = _memberName + "="; MSA.Expression transformedLeftTarget = _leftTarget.TransformRead(gen); MSA.Expression transformedRight = _right.TransformRead(gen); MSA.Expression leftTemp = gen.CurrentScope.DefineHiddenVariable(String.Empty, transformedLeftTarget.Type); bool leftIsSelf = _leftTarget.NodeType == NodeTypes.SelfReference; // lhs &&= rhs --> left.member && (left.member = rhs) // lhs ||= rhs --> left.member || (left.member = rhs) if (Operation == Symbols.And || Operation == Symbols.Or) { MSA.Expression leftMemberRead = MethodCall.TransformRead(this, gen, false, _memberName, Ast.Assign(leftTemp, transformedLeftTarget), null, null, null, null); MSA.Expression transformedWrite = MethodCall.TransformRead(this, gen, leftIsSelf, setterName, leftTemp, null, null, null, transformedRight); if (Operation == Symbols.And) { return(AndExpression.TransformRead(gen, leftMemberRead, transformedWrite)); } else { return(OrExpression.TransformRead(gen, leftMemberRead, transformedWrite)); } } else { // left.member= left.member().op(right) MSA.Expression leftMemberRead = MethodCall.TransformRead(this, gen, false, _memberName, leftTemp, null, null, null, null); MSA.Expression operationCall = MethodCall.TransformRead(this, gen, false, Operation, leftMemberRead, null, null, transformedRight, null); MSA.Expression transformedWrite = MethodCall.TransformRead(this, gen, leftIsSelf, setterName, Ast.Assign(leftTemp, transformedLeftTarget), null, null, null, operationCall); return(transformedWrite); } }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { MSA.Expression result; int i = _elseIfClauses.Count - 1; if (i >= 0 && _elseIfClauses[i].Condition == null) { // ... else body end result = gen.TransformStatementsToExpression(_elseIfClauses[i].Statements); i--; } else { // no else clause => the result of the if-expression is nil: result = Ast.Constant(null); } while (i >= 0) { // emit: else (if (condition) body else result) result = AstFactory.Condition( AstFactory.IsTrue(_elseIfClauses[i].Condition.TransformRead(gen)), gen.TransformStatementsToExpression(_elseIfClauses[i].Statements), result ); i--; } // if (condition) body else result return(AstFactory.Condition( AstFactory.IsTrue(_condition.TransformRead(gen)), gen.TransformStatementsToExpression(_body), result )); }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { return(AstUtils.LightDynamic(ExplicitSplatAction.Make(gen.Context), typeof(IList), _argument.TransformRead(gen))); }
internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen) { return(TransformRead(gen, _left.TransformRead(gen), _right.TransformRead(gen))); }
// when <expr> // generates into: // RubyOps.IsTrue(<expr>) if the case has no value, otherise: // RubyOps.IsTrue(Call("===", <expr>, <value>)) /*!*/ private static MSA.Expression MakeTest(AstGenerator/*!*/ gen, Expression/*!*/ expr, MSA.Expression value) { MSA.Expression transformedExpr = expr.TransformRead(gen); if (expr is SplattedArgument) { if (value != null) { return Methods.ExistsUnsplatCompare.OpCall( Ast.Constant(CallSite<Func<CallSite, object, object, object>>.Create( RubyCallAction.Make(gen.Context, "===", RubyCallSignature.WithImplicitSelf(2)) )), AstUtils.LightDynamic(ExplicitTrySplatAction.Make(gen.Context), transformedExpr), AstUtils.Box(value) ); } else { return Methods.ExistsUnsplat.OpCall( AstUtils.LightDynamic(ExplicitTrySplatAction.Make(gen.Context), transformedExpr) ); } } else { if (value != null) { return AstFactory.IsTrue( CallSiteBuilder.InvokeMethod(gen.Context, "===", RubyCallSignature.WithScope(1), gen.CurrentScopeVariable, transformedExpr, value ) ); } else { return AstFactory.IsTrue(transformedExpr); } } }
// when <expr0>, ... [*<array>] // generates: // <MakeTest>(<expr0>) || <MakeTest>(<expr1>) || ... [ || <MakeArrayTest>(<array>) ] internal static MSA.Expression/*!*/ TransformWhenCondition(AstGenerator/*!*/ gen, Expression[] comparisons, Expression comparisonArray, MSA.Expression value) { MSA.Expression result; if (comparisonArray != null) { result = MakeArrayTest(gen, comparisonArray.TransformRead(gen), value); } else { result = Ast.Constant(false); } if (comparisons != null) { for (int i = comparisons.Length - 1; i >= 0; i--) { result = Ast.OrElse( MakeTest(gen, comparisons[i].TransformRead(gen), value), result ); } } return result; }
internal override MSA.Expression TransformTargetRead(AstGenerator /*!*/ gen) { return(_qualifier.TransformRead(gen)); }
internal static MSA.Expression /*!*/ MakeConversion(AstGenerator /*!*/ gen, Expression /*!*/ expression) { return(AstUtils.LightDynamic(ConvertToSAction.Make(gen.Context), typeof(MutableString), expression.TransformRead(gen))); }