예제 #1
0
        protected override NodeBase Expand(Context ctx, bool mustReturn)
        {
            var leftType = LeftOperand.Resolve(ctx, mustReturn);

            // create a lambda expression that passes the result of left function to the right one
            if (leftType.IsCallableType())
            {
                var leftVar      = ctx.Unique.TempVariableName();
                var rightVar     = ctx.Unique.TempVariableName();
                var delegateType = ReflectionHelper.WrapDelegate(leftType);
                var argDefs      = delegateType.ArgumentTypes.Select(x => Expr.Arg(ctx.Unique.AnonymousArgName(), x.FullName)).ToArray();

                return(Expr.Lambda(
                           argDefs,
                           Expr.Block(
                               Expr.Let(leftVar, LeftOperand),
                               Expr.Let(rightVar, RightOperand),
                               Expr.Invoke(
                                   Expr.Get(rightVar),
                                   Expr.Invoke(
                                       Expr.Get(leftVar),
                                       argDefs.Select(x => Expr.Get(x.Name)).ToArray()
                                       )
                                   )
                               )
                           ));
            }

            return(base.Expand(ctx, mustReturn));
        }
예제 #2
0
        public void Should_not_allow_null_expression_in_array()
        {
            var ex = Assert.Throws <ArgumentNullException>(() => Expr.Block(Expr.Empty(), null, Expr.Empty()));

            Assert.That(ex.Message, Is.StringContaining("Value cannot be null."));
            Assert.That(ex.Message, Is.StringContaining("expressions[1]"));
        }
예제 #3
0
파일: ForeachNode.cs 프로젝트: taekun/lens
        /// <summary>
        /// Expands the foreach loop if it iterates over T[].
        /// </summary>
        private NodeBase expandArray(Context ctx)
        {
            var arrayVar = ctx.Scope.DeclareImplicit(ctx, IterableExpression.Resolve(ctx), false);
            var idxVar   = ctx.Scope.DeclareImplicit(ctx, typeof(int), false);
            var lenVar   = ctx.Scope.DeclareImplicit(ctx, typeof(int), false);

            return(Expr.Block(
                       Expr.Set(idxVar, Expr.Int(0)),
                       Expr.Set(arrayVar, IterableExpression),
                       Expr.Set(lenVar, Expr.GetMember(Expr.Get(arrayVar), "Length")),
                       Expr.While(
                           Expr.Less(
                               Expr.Get(idxVar),
                               Expr.Get(lenVar)
                               ),
                           Expr.Block(
                               getIndexAssignment(
                                   Expr.GetIdx(
                                       Expr.Get(arrayVar),
                                       Expr.Get(idxVar)
                                       )
                                   ),
                               Expr.Set(
                                   idxVar,
                                   Expr.Add(Expr.Get(idxVar), Expr.Int(1))
                                   ),
                               Body
                               )
                           )
                       ));
        }
예제 #4
0
        /// <summary>
        /// Repeats a string.
        /// </summary>
        private NodeBase StringExpand(Context ctx)
        {
            var tmpString = ctx.Scope.DeclareImplicit(ctx, typeof(string), false);
            var tmpSb     = ctx.Scope.DeclareImplicit(ctx, typeof(StringBuilder), false);
            var tmpIdx    = ctx.Scope.DeclareImplicit(ctx, RightOperand.Resolve(ctx), false);

            // var sb = new StringBuilder();
            // for _ in 1..N do
            //    sb.Append (str)
            // str.ToString ()
            return(Expr.Block(
                       Expr.Let(tmpString, LeftOperand),
                       Expr.Let(tmpSb, Expr.New(typeof(StringBuilder))),
                       Expr.For(
                           tmpIdx,
                           Expr.Int(1),
                           RightOperand,
                           Expr.Block(
                               Expr.Invoke(
                                   Expr.Get(tmpSb),
                                   "Append",
                                   Expr.Get(tmpString)
                                   )
                               )
                           ),
                       Expr.Invoke(
                           Expr.Get(tmpSb),
                           "ToString"
                           )
                       ));
        }
예제 #5
0
파일: ForeachNode.cs 프로젝트: taekun/lens
        /// <summary>
        /// Expands the foreach loop if it iterates over a numeric range.
        /// </summary>
        private NodeBase expandRange(Context ctx)
        {
            var signVar = ctx.Scope.DeclareImplicit(ctx, _VariableType, false);
            var idxVar  = ctx.Scope.DeclareImplicit(ctx, _VariableType, false);

            return(Expr.Block(
                       Expr.Set(idxVar, RangeStart),
                       Expr.Set(
                           signVar,
                           Expr.Invoke(
                               "Math",
                               "Sign",
                               Expr.Sub(RangeEnd, Expr.Get(idxVar))
                               )
                           ),
                       Expr.While(
                           Expr.NotEqual(Expr.Get(idxVar), RangeEnd),
                           Expr.Block(
                               getIndexAssignment(Expr.Get(idxVar)),
                               Body,
                               Expr.Set(
                                   idxVar,
                                   Expr.Add(
                                       Expr.Get(idxVar),
                                       Expr.Get(signVar)
                                       )
                                   )
                               )
                           )
                       ));
        }
예제 #6
0
        /// <summary>
        /// Creates a pure wrapper for parameterless function.
        /// </summary>
        private void CreatePureWrapper0(MethodEntity wrapper, string pureName)
        {
            var fieldName = string.Format(EntityNames.PureMethodCacheNameTemplate, wrapper.Name);
            var flagName  = string.Format(EntityNames.PureMethodCacheFlagNameTemplate, wrapper.Name);

            CreateField(fieldName, wrapper.ReturnTypeSignature, true);
            CreateField(flagName, typeof(bool), true);

            wrapper.Body = Expr.Block(
                ScopeKind.FunctionRoot,

                // if (not $flag) $cache = $internal (); $flag = true
                Expr.If(
                    Expr.Not(Expr.GetMember(EntityNames.MainTypeName, flagName)),
                    Expr.Block(
                        Expr.SetMember(
                            EntityNames.MainTypeName,
                            fieldName,
                            Expr.Invoke(EntityNames.MainTypeName, pureName)
                            ),
                        Expr.SetMember(EntityNames.MainTypeName, flagName, Expr.True())
                        )
                    ),

                // $cache
                Expr.GetMember(EntityNames.MainTypeName, fieldName)
                );
        }
예제 #7
0
파일: ParserTest.cs 프로젝트: taekun/lens
        public void FunWithIfThenElse()
        {
            var src = @"
fun part (x:int) ->
    if x > 100 then
        (new Large x) as TestType
    else
        new Small x";

            var result = Expr.Fun(
                "part",
                new[]
            {
                Expr.Arg("x", "int")
            },
                Expr.If(
                    Expr.Greater(Expr.Get("x"), Expr.Int(100)),
                    Expr.Block(
                        Expr.Cast(
                            Expr.New("Large", Expr.Get("x")),
                            "TestType"
                            )
                        ),
                    Expr.Block(
                        Expr.New("Small", Expr.Get("x"))
                        )
                    )
                );

            TestParser(src, result);
        }
예제 #8
0
        /// <summary>
        /// Creates a pure wrapper for function with 2 and more arguments.
        /// </summary>
        private void createPureWrapperMany(MethodEntity wrapper, string pureName)
        {
            var args = wrapper.GetArgumentTypes(Context);

            var fieldName = string.Format(EntityNames.PureMethodCacheNameTemplate, wrapper.Name);
            var tupleType = FunctionalHelper.CreateTupleType(args);
            var fieldType = typeof(Dictionary <,>).MakeGenericType(tupleType, wrapper.ReturnType);

            CreateField(fieldName, fieldType, true);

            var argGetters = wrapper.Arguments.Select(a => (NodeBase)Expr.Get(a)).ToArray();
            var tupleName  = "<args>";

            wrapper.Body = Expr.Block(
                ScopeKind.FunctionRoot,

                // $tmp = new Tuple<...> $arg1 $arg2 ...
                Expr.Let(tupleName, Expr.New(tupleType, argGetters)),

                // if ($dict == null) $dict = new Dictionary<$tupleType, $valueType> ()
                Expr.If(
                    Expr.Equal(
                        Expr.GetMember(EntityNames.MainTypeName, fieldName),
                        Expr.Null()
                        ),
                    Expr.Block(
                        Expr.SetMember(
                            EntityNames.MainTypeName, fieldName,
                            Expr.New(fieldType)
                            )
                        )
                    ),

                // if(not $dict.ContainsKey key) $dict.Add ($internal arg)
                Expr.If(
                    Expr.Not(
                        Expr.Invoke(
                            Expr.GetMember(EntityNames.MainTypeName, fieldName),
                            "ContainsKey",
                            Expr.Get(tupleName)
                            )
                        ),
                    Expr.Block(
                        Expr.Invoke(
                            Expr.GetMember(EntityNames.MainTypeName, fieldName),
                            "Add",
                            Expr.Get(tupleName),
                            Expr.Invoke(EntityNames.MainTypeName, pureName, argGetters)
                            )
                        )
                    ),

                // $dict[arg]
                Expr.GetIdx(
                    Expr.GetMember(EntityNames.MainTypeName, fieldName),
                    Expr.Get(tupleName)
                    )

                );
        }
예제 #9
0
 public override IEnumerable <NodeBase> Expand(Context ctx, NodeBase expression, Label nextStatement)
 {
     yield return(Expr.If(
                      Expr.NotEqual(Literal as NodeBase, expression),
                      Expr.Block(
                          Expr.JumpTo(nextStatement)
                          )
                      ));
 }
예제 #10
0
        /// <summary>
        /// Creates the entry point for an assembly if it is supposed to be saved.
        /// The entry point method basically calls the Run method and discards the result.
        /// </summary>
        private void createEntryPoint()
        {
            var ep = MainType.CreateMethod(EntityNames.EntryPointMethodName, "Void", args: null, isStatic: true);

            ep.Kind = TypeContentsKind.AutoGenerated;
            ep.Body = Expr.Block(
                Expr.Invoke(Expr.New(EntityNames.MainTypeName), "Run"),
                Expr.Unit()
                );
        }
예제 #11
0
파일: ForeachNode.cs 프로젝트: taekun/lens
        /// <summary>
        /// Expands the foreach loop if it iterates over an IEnumerable`1.
        /// </summary>
        private NodeBase expandEnumerable(Context ctx, bool mustReturn)
        {
            var iteratorVar    = ctx.Scope.DeclareImplicit(ctx, _EnumeratorType, false);
            var enumerableType = _EnumeratorType.IsGenericType
                                ? typeof(IEnumerable <>).MakeGenericType(_EnumeratorType.GetGenericArguments()[0])
                                : typeof(IEnumerable);

            var init = Expr.Set(
                iteratorVar,
                Expr.Invoke(
                    Expr.Cast(IterableExpression, enumerableType),
                    "GetEnumerator"
                    )
                );

            var loop = Expr.While(
                Expr.Invoke(Expr.Get(iteratorVar), "MoveNext"),
                Expr.Block(
                    getIndexAssignment(Expr.GetMember(Expr.Get(iteratorVar), "Current")),
                    Body
                    )
                );

            if (_EnumeratorType.Implements(typeof(IDisposable), false))
            {
                var dispose    = Expr.Block(Expr.Invoke(Expr.Get(iteratorVar), "Dispose"));
                var returnType = Resolve(ctx);
                var saveLast   = mustReturn && !returnType.IsVoid();

                if (saveLast)
                {
                    var resultVar = ctx.Scope.DeclareImplicit(ctx, _EnumeratorType, false);
                    return(Expr.Block(
                               Expr.Try(
                                   Expr.Block(
                                       init,
                                       Expr.Set(resultVar, loop)
                                       ),
                                   dispose
                                   ),
                               Expr.Get(resultVar)
                               ));
                }

                return(Expr.Try(
                           Expr.Block(init, loop),
                           dispose
                           ));
            }

            return(Expr.Block(
                       init,
                       loop
                       ));
        }
예제 #12
0
        protected override NodeBase Expand(Context ctx, bool mustReturn)
        {
            if (Resolve(ctx).IsNullableType())
            {
                var leftNullable  = LeftOperand.Resolve(ctx).IsNullableType();
                var rightNullable = RightOperand.Resolve(ctx).IsNullableType();
                if (leftNullable && rightNullable)
                {
                    return(Expr.If(
                               Expr.And(
                                   Expr.GetMember(LeftOperand, "HasValue"),
                                   Expr.GetMember(RightOperand, "HasValue")
                                   ),
                               Expr.Block(
                                   RecreateSelfWithArgs(
                                       Expr.GetMember(LeftOperand, "Value"),
                                       Expr.GetMember(RightOperand, "Value")
                                       )
                                   ),
                               Expr.Block(Expr.Null())
                               ));
                }

                if (leftNullable)
                {
                    return(Expr.If(
                               Expr.GetMember(LeftOperand, "HasValue"),
                               Expr.Block(
                                   RecreateSelfWithArgs(
                                       Expr.GetMember(LeftOperand, "Value"),
                                       RightOperand
                                       )
                                   ),
                               Expr.Block(Expr.Null())
                               ));
                }

                if (rightNullable)
                {
                    return(Expr.If(
                               Expr.GetMember(RightOperand, "HasValue"),
                               Expr.Block(
                                   RecreateSelfWithArgs(
                                       LeftOperand,
                                       Expr.GetMember(RightOperand, "Value")
                                       )
                                   ),
                               Expr.Block(Expr.Null())
                               ));
                }
            }

            return(base.Expand(ctx, mustReturn));
        }
예제 #13
0
        protected override NodeBase Expand(Context ctx, bool mustReturn)
        {
            if (!IsConstant)
            {
                return(Kind == LogicalOperatorKind.And
                    ? Expr.If(LeftOperand, Expr.Block(Expr.Cast <bool>(RightOperand)), Expr.Block(Expr.False()))
                    : Expr.If(LeftOperand, Expr.Block(Expr.True()), Expr.Block(Expr.Cast <bool>(RightOperand))));
            }

            return(base.Expand(ctx, mustReturn));
        }
예제 #14
0
파일: ParserTest.cs 프로젝트: taekun/lens
        public void ConditionFull()
        {
            var src    = "if true then a else b";
            var result = Expr.If(
                Expr.True(),
                Expr.Block(Expr.Get("a")),
                Expr.Block(Expr.Get("b"))
                );

            TestParser(src, result);
        }
예제 #15
0
        /// <summary>
        /// Creates a pure wrapper for function with 1 argument.
        /// </summary>
        private void CreatePureWrapper1(MethodEntity wrapper, string pureName)
        {
            var args    = wrapper.GetArgumentTypes(Context);
            var argName = wrapper.Arguments[0].Name;

            var fieldName = string.Format(EntityNames.PureMethodCacheNameTemplate, wrapper.Name);
            var fieldType = typeof(Dictionary <,>).MakeGenericType(args[0], wrapper.ReturnType);

            CreateField(fieldName, fieldType, true);

            wrapper.Body = Expr.Block(
                ScopeKind.FunctionRoot,

                // if ($dict == null) $dict = new Dictionary<$argType, $valueType> ()
                Expr.If(
                    Expr.Equal(
                        Expr.GetMember(EntityNames.MainTypeName, fieldName),
                        Expr.Null()
                        ),
                    Expr.Block(
                        Expr.SetMember(
                            EntityNames.MainTypeName, fieldName,
                            Expr.New(fieldType)
                            )
                        )
                    ),

                // if(not $dict.ContainsKey key) $dict.Add ($internal arg)
                Expr.If(
                    Expr.Not(
                        Expr.Invoke(
                            Expr.GetMember(EntityNames.MainTypeName, fieldName),
                            "ContainsKey",
                            Expr.Get(argName)
                            )
                        ),
                    Expr.Block(
                        Expr.Invoke(
                            Expr.GetMember(EntityNames.MainTypeName, fieldName),
                            "Add",
                            Expr.Get(argName),
                            Expr.Invoke(EntityNames.MainTypeName, pureName, Expr.Get(argName))
                            )
                        )
                    ),

                // $dict[arg]
                Expr.GetIdx(
                    Expr.GetMember(EntityNames.MainTypeName, fieldName),
                    Expr.Get(argName)
                    )
                );
        }
예제 #16
0
 public override IEnumerable <NodeBase> Expand(Context ctx, NodeBase expression, Label nextStatement)
 {
     yield return(Expr.If(
                      Expr.Or(
                          Expr.Less(expression, RangeStartRule.Literal as NodeBase),
                          Expr.Greater(expression, RangeEndRule.Literal as NodeBase)
                          ),
                      Expr.Block(
                          Expr.JumpTo(nextStatement)
                          )
                      ));
 }
예제 #17
0
        public void Should_execute_all_statements_in_block()
        {
            var addMethod = typeof(Counter).GetMethod("Add");
            var func      = CreateAction <Counter>(Expr.Block(
                                                       Expr.Call(Expr.Parameter(0, typeof(Counter)), addMethod),
                                                       Expr.Call(Expr.Parameter(0, typeof(Counter)), addMethod)));

            var cnt = new Counter();

            func(cnt);
            Assert.That(cnt.Value, Is.EqualTo(2));
        }
예제 #18
0
파일: ParserTest.cs 프로젝트: taekun/lens
        public void IfThenElse()
        {
            var src    = @"
if x then
    1
else
    2
";
            var result = Expr.If(Expr.Get("x"), Expr.Block(Expr.Int(1)), Expr.Block(Expr.Int(2)));

            TestParser(src, result);
        }
예제 #19
0
        /// <summary>
        /// Expands short assignment to an expression member:
        /// (expr).x += 1
        /// or type::x += 1
        /// </summary>
        private NodeBase ExpandMember(Context ctx, SetMemberNode node)
        {
            // type::name += value
            if (node.StaticType != null)
            {
                return(Expr.SetMember(
                           node.StaticType,
                           node.MemberName,
                           _assignmentOperator(
                               Expr.GetMember(
                                   node.StaticType,
                                   node.MemberName
                                   ),
                               node.Value
                               )
                           ));
            }

            // simple case: no need to cache expression
            if (node.Expression is SetIdentifierNode)
            {
                return(Expr.SetMember(
                           node.Expression,
                           node.MemberName,
                           _assignmentOperator(
                               Expr.GetMember(
                                   node.Expression,
                                   node.MemberName
                                   ),
                               node.Value
                               )
                           ));
            }

            // (x + y).name += value
            // must cache (x + y) to a local variable to prevent double execution
            var tmpVar = ctx.Scope.DeclareImplicit(ctx, node.Expression.Resolve(ctx), false);

            return(Expr.Block(
                       Expr.Set(tmpVar, node.Expression),
                       Expr.SetMember(
                           Expr.Get(tmpVar),
                           node.MemberName,
                           _assignmentOperator(
                               Expr.GetMember(
                                   Expr.Get(tmpVar),
                                   node.MemberName
                                   ),
                               node.Value
                               )
                           )
                       ));
        }
예제 #20
0
파일: ParserTest.cs 프로젝트: taekun/lens
        public void Algebraic3()
        {
            var src = @"
type TestType
    Small of int
    Large of int
fun part:TestType (x:int) ->
    if x > 100 then
        (new Large x) as TestType
    else
        new Small x


var a = part 10
new [ a is TestType; a is Small; a is Large ]";

            var result = new NodeBase[]
            {
                Expr.Type(
                    "TestType",
                    Expr.Label("Small", "int"),
                    Expr.Label("Large", "int")
                    ),

                Expr.Fun(
                    "part",
                    "TestType",
                    new [] { Expr.Arg("x", "int") },
                    Expr.If(
                        Expr.Greater(Expr.Get("x"), Expr.Int(100)),
                        Expr.Block(
                            Expr.Cast(
                                Expr.New("Large", Expr.Get("x")),
                                "TestType"
                                )
                            ),
                        Expr.Block(
                            Expr.New("Small", Expr.Get("x"))
                            )
                        )
                    ),

                Expr.Var("a", Expr.Invoke("part", Expr.Int(10))),
                Expr.Array(
                    Expr.Is(Expr.Get("a"), "TestType"),
                    Expr.Is(Expr.Get("a"), "Small"),
                    Expr.Is(Expr.Get("a"), "Large")
                    )
            };

            TestParser(src, result);
        }
예제 #21
0
        /// <summary>
        /// Repeats a typed or untyped sequence.
        /// </summary>
        private NodeBase SeqExpand(Context ctx)
        {
            var seqType = LeftOperand.Resolve(ctx);

            NodeBase leftWrapper;

            if (seqType == typeof(IEnumerable))
            {
                leftWrapper = Expr.Invoke(Expr.GetMember("System.Linq.Enumerable", "OfType", "object"), LeftOperand);
                seqType     = typeof(IEnumerable <object>);
            }
            else
            {
                leftWrapper = LeftOperand;
            }

            var tmpLeft   = ctx.Scope.DeclareImplicit(ctx, seqType, false);
            var tmpResult = ctx.Scope.DeclareImplicit(ctx, seqType, false);
            var tmpIndex  = ctx.Scope.DeclareImplicit(ctx, typeof(int), false);

            // a = <left>
            // result = a
            // for x in 1..(Math.Abs <right>) do
            //   result = result.Concat a
            // result
            return(Expr.Block(
                       Expr.Set(tmpLeft, leftWrapper),
                       Expr.Set(tmpResult, Expr.Get(tmpLeft)),
                       Expr.For(
                           tmpIndex,
                           Expr.Int(1),
                           Expr.Invoke(
                               "System.Math",
                               "Abs",
                               RightOperand
                               ),
                           Expr.Block(
                               Expr.Set(
                                   tmpResult,
                                   Expr.Invoke(
                                       "System.Linq.Enumerable",
                                       "Concat",
                                       Expr.Get(tmpResult),
                                       Expr.Get(tmpLeft)
                                       )
                                   )
                               )
                           ),
                       Expr.Get(tmpResult)
                       ));
        }
        public void Should_iterate_n_times_with_return()
        {
            var loc  = Expr.LocalVariable(typeof(int), "i");
            var func = CreateFunc <int, int>(
                Expr.DeclareLocal(loc, Expr.Constant(0)),
                Expr.Loop(Expr.Block(
                              Expr.WriteLocal(loc, Expr.Add(Expr.ReadLocal(loc), Expr.Constant(1))),
                              Expr.IfThen(
                                  Expr.Equal(Expr.ReadLocal(loc), Expr.Parameter(0, typeof(int))),
                                  Expr.Return(Expr.ReadLocal(loc))))),
                Expr.Return(Expr.Constant(0)));

            Assert.That(func(5), Is.EqualTo(5));
        }
예제 #23
0
        public void Should_allow_break_in_catch_block()
        {
            var loc  = Expr.LocalVariable(typeof(int), "i");
            var func = CreateFunc <int>(
                Expr.WriteLocal(loc, Expr.Constant(0)),
                Expr.Loop(Expr.TryCatch(
                              Expr.Block(
                                  Expr.WriteLocal(loc, Expr.Add(Expr.ReadLocal(loc), Expr.Constant(1))),
                                  Expr.Throw(Expr.New(typeof(Exception)))),
                              new CatchBlock(Expr.LoopBreak()))),
                Expr.Return(Expr.ReadLocal(loc)));

            Assert.That(func(), Is.EqualTo(2));
        }
예제 #24
0
파일: ParserTest.cs 프로젝트: taekun/lens
        public void ConditionSimple()
        {
            var src    = @"
if true then
    a = 1
    b = 2";
            var result = Expr.If(
                Expr.True(),
                Expr.Block(
                    Expr.Set("a", Expr.Int(1)),
                    Expr.Set("b", Expr.Int(2))
                    )
                );

            TestParser(src, result);
        }
예제 #25
0
파일: ParserTest.cs 프로젝트: taekun/lens
        public void For1()
        {
            var src    = "for x in y do test ()";
            var result = new NodeBase[]
            {
                Expr.For(
                    "x",
                    Expr.Get("y"),
                    Expr.Block(
                        Expr.Invoke("test")
                        )
                    )
            };

            TestParser(src, result);
        }
예제 #26
0
        public override IEnumerable <NodeBase> Expand(Context ctx, NodeBase expression, Label nextStatement)
        {
            if (Type != null)
            {
                yield return(Expr.If(
                                 Expr.Not(Expr.Is(expression, Type)),
                                 Expr.Block(
                                     Expr.JumpTo(nextStatement)
                                     )
                                 ));
            }

            if (!IsWildcard)
            {
                yield return(Expr.Set(Name, expression));
            }
        }
예제 #27
0
        /// <summary>
        /// Expands the current rule into a block of checks.
        /// </summary>
        public CodeBlockNode ExpandRules(Context ctx, NodeBase expression, Label expressionLabel)
        {
            var block = new CodeBlockNode();

            // rule is never true: do not emit its code at all
            if (Condition != null && Condition.IsConstant && Condition.ConstantValue == false)
            {
                return(block);
            }

            // declare variables
            foreach (var binding in _BindingSet)
            {
                block.Add(Expr.Var(binding.Name, binding.Type.FullName));
            }

            foreach (var rule in MatchRules)
            {
                // current and next labels for each rule
                var ruleLabels = ParentNode.GetRuleLabels(rule);

                block.Add(Expr.JumpLabel(ruleLabels.CurrentRule));
                block.AddRange(rule.Expand(ctx, expression, ruleLabels.NextRule));

                if (Condition != null)
                {
                    block.Add(
                        Expr.If(
                            Expr.Not(Condition),
                            Expr.Block(Expr.JumpTo(ruleLabels.NextRule))
                            )
                        );
                }

                block.Add(Expr.JumpTo(expressionLabel));
            }

            block.AddRange(
                Expr.JumpLabel(expressionLabel),
                Expression,
                Expr.JumpTo(ParentNode.EndLabel)
                );

            return(block);
        }
예제 #28
0
        /// <summary>
        /// Returns the code to concatenate two arrays.
        /// </summary>
        private NodeBase ArrayExpand(Context ctx)
        {
            var type = Resolve(ctx);

            var tmpArray = ctx.Scope.DeclareImplicit(ctx, type, false);
            var tmpLeft  = ctx.Scope.DeclareImplicit(ctx, type, false);
            var tmpRight = ctx.Scope.DeclareImplicit(ctx, type, false);

            // a = <left>
            // b = <right>
            // c = new T[a.Length + b.Length]
            // Array.Copy(from: a, to: c, count: a.Length)
            // Array.Copy(from: b, startFrom: 0, to: c, startTo: a.Length, count: b.Length)
            return(Expr.Block(
                       Expr.Set(tmpLeft, LeftOperand),
                       Expr.Set(tmpRight, RightOperand),
                       Expr.Set(
                           tmpArray,
                           Expr.Array(
                               type.GetElementType(),
                               Expr.Add(
                                   Expr.GetMember(Expr.Get(tmpLeft), "Length"),
                                   Expr.GetMember(Expr.Get(tmpRight), "Length")
                                   )
                               )
                           ),
                       Expr.Invoke(
                           "System.Array",
                           "Copy",
                           Expr.Get(tmpLeft),
                           Expr.Get(tmpArray),
                           Expr.GetMember(Expr.Get(tmpLeft), "Length")
                           ),
                       Expr.Invoke(
                           "System.Array",
                           "Copy",
                           Expr.Get(tmpRight),
                           Expr.Int(0),
                           Expr.Get(tmpArray),
                           Expr.GetMember(Expr.Get(tmpLeft), "Length"),
                           Expr.GetMember(Expr.Get(tmpRight), "Length")
                           ),
                       Expr.Get(tmpArray)
                       ));
        }
예제 #29
0
        public void Should_allow_inner_loop_with_break_continue_in_catch_block()
        {
            var result = Expr.LocalVariable(typeof(int), "r");
            var func   = CreateFunc <int>(
                Expr.DeclareLocal(result, Expr.Constant(0)),
                Expr.TryCatch(
                    Expr.Throw(Expr.New(typeof(Exception))),
                    new CatchBlock(Expr.Block(
                                       Expr.Loop(Expr.Block(
                                                     Expr.WriteLocal(result, Expr.Add(Expr.ReadLocal(result), Expr.Constant(1))),
                                                     Expr.IfThen(
                                                         Expr.Less(Expr.ReadLocal(result), Expr.Constant(2)),
                                                         Expr.LoopContinue()),
                                                     Expr.LoopBreak()))))),
                Expr.Return(Expr.ReadLocal(result)));

            Assert.That(func(), Is.EqualTo(2));
        }
예제 #30
0
        /// <summary>
        /// Returns the code to concatenate two dictionaries.
        /// </summary>
        private NodeBase DictExpand(Context ctx)
        {
            var keyValueTypes = LeftOperand.Resolve(ctx).GetGenericArguments();
            var dictType      = typeof(Dictionary <,>).MakeGenericType(keyValueTypes);
            var currType      = typeof(KeyValuePair <,>).MakeGenericType(keyValueTypes);
            var tmpDict       = ctx.Scope.DeclareImplicit(ctx, dictType, false);
            var tmpCurr       = ctx.Scope.DeclareImplicit(ctx, currType, false);

            // a = new Dictionary<T, T2>(<left>)
            // foreach(var kvp in <right>)
            //    a[kvp.Key] = kvp.Value
            return(Expr.Block(
                       Expr.Set(
                           tmpDict,
                           Expr.New(
                               dictType,
                               Expr.Cast(
                                   LeftOperand,
                                   typeof(IDictionary <,>).MakeGenericType(keyValueTypes)
                                   )
                               )
                           ),
                       Expr.For(
                           tmpCurr,
                           RightOperand,
                           Expr.Block(
                               Expr.SetIdx(
                                   Expr.Get(tmpDict),
                                   Expr.GetMember(
                                       Expr.Get(tmpCurr),
                                       "Key"
                                       ),
                                   Expr.GetMember(
                                       Expr.Get(tmpCurr),
                                       "Value"
                                       )
                                   )
                               )
                           ),
                       Expr.Get(tmpDict)
                       ));
        }