private Expression InlineIfTrueIfFalse(Compiler.SemanticNodes.BlockNode trueBlock, Compiler.SemanticNodes.BlockNode falseBlock) { NameBinding nilBinding = this.Context.GetBinding(SemanticConstants.Nil); Expression testExpression = Expression.Convert(this.Receiver, typeof(bool)); Expression trueExpression; if (trueBlock != null) { trueExpression = trueBlock.Accept(new InlineBlockVisitor(this)); } else { trueExpression = nilBinding.GenerateReadExpression(this); } Expression falseExpression; if (falseBlock != null) { falseExpression = falseBlock.Accept(new InlineBlockVisitor(this)); } else { falseExpression = nilBinding.GenerateReadExpression(this); } Expression result = Expression.Condition(testExpression, trueExpression, falseExpression, typeof(object)); this.SetResult(result); return(result); }
private Expression InlineOr(Compiler.SemanticNodes.BlockNode block) { NameBinding trueBinding = this.Context.GetBinding(SemanticConstants.True); Expression testExpression = Expression.Convert(this.Receiver, typeof(bool)); Expression blockExpression = block.Accept(new InlineBlockVisitor(this)); Expression result = Expression.Condition(testExpression, trueBinding.GenerateReadExpression(this), blockExpression, typeof(object)); this.SetResult(result); return(result); }
private Expression InlineToByDo(Expression start, Expression stop, Expression step, Compiler.SemanticNodes.BlockNode block) { /// to:by:do: /* C# semantics of the inlining * if ((start is int) && (stop is int) && (step is int)) * { * int iStart, iStop, iStep; * try * { * iStart = checked((int)start); * iStop = checked((int)stop); * iStep = checked((int)step); * // This is to ensure the calculation below do not fail running unchecked * int na = checked(iStart + iStep); * na = checked(iStop + iStep); * } * catch (OverflowException) * { * goto Int32Overwlow; * } * * if (iStep == 0) * throw new ArgumentOutOfRangeException(); * * if (iStep > 0) * { * do * { * if (iStart > iStop) * goto Exit; * block(iStart); * iStart = iStart + iStep; * } while (true); * } * else * { * do * { * if (iStop > iStart) * goto Exit; * block(iStart); * iStart = iStart + iStep; * } while (true); * } * } * Int32Overwlow: * // We could implement BigInteger optimization here, but too much work and probably not much to gain * // Fallback to dynamic invocation * dynamic dStart = start; * dynamic dStep = step; * if (dStep == 0) * throw new ArgumentOutOfRangeException(); * * if (dStep > 0) * { * do * { * if (dStart > stop) * goto Exit; * block(dStart); * dStart = dStart + step; * } while (true); * } * else * { * do * { * if (stop > dStart) * goto Exit; * block(dStart); * dStart = dStart + step; * } while (true); * } * Exit: */ NameBinding nilBinding = this.Context.GetBinding(SemanticConstants.Nil); LabelTarget exitLabel = Expression.Label(typeof(void)); LabelTarget overflowLabel = Expression.Label(typeof(void)); ParameterExpression iStart = Expression.Variable(typeof(int), "iStart"); ParameterExpression iStop = Expression.Variable(typeof(int), "iStop"); ParameterExpression iStep = Expression.Variable(typeof(int), "iStep"); ParameterExpression iNA = Expression.Variable(typeof(int), "iNA"); InlineBlockVisitor visitor = new InlineBlockVisitor(this); if (block.Arguments.Count > 0) { visitor.DefineExternalArgument(block.Arguments[0].Token.Value, Expression.Convert(iStart, typeof(object))); } Expression integerOperation = block.Accept(visitor); Expression integerTest = Expression.AndAlso(Expression.AndAlso( Expression.TypeIs(start, typeof(int)), Expression.TypeIs(stop, typeof(int))), Expression.TypeIs(step, typeof(int))); Expression integerBlock = Expression.Block( Expression.TryCatch( Expression.Block( Expression.Assign(iStart, Expression.ConvertChecked(start, typeof(int))), Expression.Assign(iStop, Expression.ConvertChecked(stop, typeof(int))), Expression.Assign(iStep, Expression.ConvertChecked(step, typeof(int))), Expression.Assign(iNA, Expression.AddChecked(iStart, iStep)), Expression.Assign(iNA, Expression.AddChecked(iStop, iStep))), Expression.Catch(typeof(OverflowException), Expression.Goto(overflowLabel, typeof(int))), Expression.Catch(typeof(InvalidCastException), Expression.Goto(overflowLabel, typeof(int)))), Expression.IfThen( Expression.Equal(iStep, Expression.Constant(0)), Expression.Throw(Expression.New(typeof(ArgumentOutOfRangeException)), typeof(object))), Expression.IfThenElse( Expression.GreaterThan(iStep, Expression.Constant(0)), Expression.Loop( Expression.IfThenElse( Expression.GreaterThan(iStart, iStop), Expression.Break(exitLabel, nilBinding.GenerateReadExpression(this)), Expression.Block( integerOperation, Expression.AddAssign(iStart, iStep)))), Expression.Loop( Expression.IfThenElse( Expression.GreaterThan(iStop, iStart), Expression.Break(exitLabel, nilBinding.GenerateReadExpression(this)), Expression.Block( integerOperation, Expression.AddAssign(iStart, iStep)))))); ParameterExpression dStart = Expression.Variable(typeof(object), "dStart"); ParameterExpression dStep = Expression.Variable(typeof(object), "dStep"); visitor = new InlineBlockVisitor(this); if (block.Arguments.Count > 0) { visitor.DefineExternalArgument(block.Arguments[0].Token.Value, dStart); } Expression dynamicOperation = block.Accept(visitor); Expression dynamicBlock = Expression.Block( Expression.Assign(dStart, start), Expression.Assign(dStep, Expression.Convert(step, typeof(object))), Expression.IfThen( Expression.IsTrue(Expression.Convert(this.Context.CompileDynamicCall(this, "=", dStep, PreboxedConstants.Int32_00000000_Expression), typeof(bool))), Expression.Throw(Expression.New(typeof(ArgumentOutOfRangeException)), typeof(object))), Expression.IfThenElse( Expression.IsTrue(Expression.Convert(this.Context.CompileDynamicCall(this, ">", dStep, PreboxedConstants.Int32_00000000_Expression), typeof(bool))), Expression.Loop( Expression.IfThenElse( Expression.IsTrue(Expression.Convert(this.Context.CompileDynamicCall(this, ">", dStart, stop), typeof(bool))), Expression.Break(exitLabel, nilBinding.GenerateReadExpression(this)), Expression.Block( dynamicOperation, Expression.Assign(dStart, this.Context.CompileDynamicCall(this, "+", dStart, dStep))))), Expression.Loop( Expression.IfThenElse( Expression.IsTrue(Expression.Convert(this.Context.CompileDynamicCall(this, ">", stop, dStart), typeof(bool))), Expression.Break(exitLabel, nilBinding.GenerateReadExpression(this)), Expression.Block( dynamicOperation, Expression.Assign(dStart, this.Context.CompileDynamicCall(this, "+", dStart, dStep))))))); return(Expression.Block( new ParameterExpression[] { iStart, iStop, iStep, iNA, dStart, dStep }, integerBlock, Expression.Label(overflowLabel), dynamicBlock, Expression.Label(exitLabel), nilBinding.GenerateReadExpression(this))); }