예제 #1
0
        public void ParseSimpleForInCommandSingleLine()
        {
            Parser parser   = new Parser("for k in [1,2,3]; puts k; end");
            var    expected = new ForInExpression("k", new ArrayExpression(new IExpression[] { new ConstantExpression(1), new ConstantExpression(2), new ConstantExpression(3) }), new CallExpression("puts", new IExpression[] { new NameExpression("k") }));
            var    result   = parser.ParseCommand();

            Assert.IsNotNull(result);
            Assert.AreEqual(expected, result);

            Assert.IsNull(parser.ParseCommand());
        }
예제 #2
0
        public void GetLocalVariables()
        {
            ForInExpression command = new ForInExpression("k", new ConstantExpression(new int[] { 1, 2, 3 }), new AssignExpression("total", new AddExpression(new NameExpression("total"), new NameExpression("k"))));

            var result = command.GetLocalVariables();

            Assert.IsNotNull(result);
            Assert.AreEqual(2, result.Count);
            Assert.IsTrue(result.Contains("k"));
            Assert.IsTrue(result.Contains("total"));
        }
예제 #3
0
        public void ExecuteForIn()
        {
            Context context = new Context();

            context.SetLocalValue("total", 0);
            ForInExpression command = new ForInExpression("k", new ConstantExpression(new int[] { 1, 2, 3 }), new AssignExpression("total", new AddExpression(new NameExpression("total"), new NameExpression("k"))));

            command.Evaluate(context);

            Assert.AreEqual(6, context.GetValue("total"));
        }
예제 #4
0
        public void Equals()
        {
            ForInExpression cmd1 = new ForInExpression("k", new ConstantExpression(1), new ConstantExpression(2));
            ForInExpression cmd2 = new ForInExpression("j", new ConstantExpression(1), new ConstantExpression(2));
            ForInExpression cmd3 = new ForInExpression("k", new ConstantExpression(2), new ConstantExpression(2));
            ForInExpression cmd4 = new ForInExpression("k", new ConstantExpression(1), new ConstantExpression(3));
            ForInExpression cmd5 = new ForInExpression("k", new ConstantExpression(1), new ConstantExpression(2));

            Assert.IsTrue(cmd1.Equals(cmd5));
            Assert.IsTrue(cmd5.Equals(cmd1));
            Assert.AreEqual(cmd1.GetHashCode(), cmd5.GetHashCode());

            Assert.IsFalse(cmd1.Equals(null));
            Assert.IsFalse(cmd1.Equals(123));
            Assert.IsFalse(cmd1.Equals(cmd2));
            Assert.IsFalse(cmd2.Equals(cmd1));
            Assert.IsFalse(cmd1.Equals(cmd3));
            Assert.IsFalse(cmd3.Equals(cmd1));
            Assert.IsFalse(cmd1.Equals(cmd4));
            Assert.IsFalse(cmd4.Equals(cmd1));
        }
예제 #5
0
        public override Value?Visit(ForInExpression forInExpression)
        {
            forInExpression.ValidateNotNull(nameof(forInExpression));
            EmitLocation(forInExpression);
            var function = InstructionBuilder.InsertFunction;

            if (function is null)
            {
                throw new InternalCodeGeneratorException("ICE: Expected block attached to a function at this point");
            }

            string varName   = forInExpression.LoopVariable.Name;
            Alloca allocaVar = LookupVariable(varName);

            // Emit the start code first, without 'variable' in scope.
            Value?startVal;

            if (forInExpression.LoopVariable.Initializer != null)
            {
                startVal = forInExpression.LoopVariable.Initializer.Accept(this);
                if (startVal is null)
                {
                    return(null);
                }
            }
            else
            {
                startVal = Context.CreateConstant(0.0);
            }

            // store the value into allocated location
            InstructionBuilder.Store(startVal, allocaVar);

            // Make the new basic block for the loop header.
            var loopBlock = function.AppendBasicBlock("loop");

            // Insert an explicit fall through from the current block to the loopBlock.
            InstructionBuilder.Branch(loopBlock);

            // Start insertion in loopBlock.
            InstructionBuilder.PositionAtEnd(loopBlock);

            // Within the loop, the variable is defined equal to the PHI node.
            // So, push a new scope for it and any values the body might set
            using (NamedValues.EnterScope( ))
            {
                EmitBranchToNewBlock("ForInScope");

                // Emit the body of the loop.  This, like any other expression, can change the
                // current BB.  Note that we ignore the value computed by the body, but don't
                // allow an error.
                if (forInExpression.Body.Accept(this) == null)
                {
                    return(null);
                }

                Value?stepValue = forInExpression.Step.Accept(this);
                if (stepValue == null)
                {
                    return(null);
                }

                // Compute the end condition.
                Value?endCondition = forInExpression.Condition.Accept(this);
                if (endCondition == null)
                {
                    return(null);
                }

                // since the Alloca is created as a non-opaque pointer it is OK to just use the
                // ElementType. If full opaque pointer support was used, then the Lookup map
                // would need to include the type of the value allocated.
                var curVar = InstructionBuilder.Load(allocaVar.ElementType, allocaVar)
                             .RegisterName(varName);
                var nextVar = InstructionBuilder.FAdd(curVar, stepValue)
                              .RegisterName("nextvar");
                InstructionBuilder.Store(nextVar, allocaVar);

                // Convert condition to a bool by comparing non-equal to 0.0.
                endCondition = InstructionBuilder.Compare(RealPredicate.OrderedAndNotEqual, endCondition, Context.CreateConstant(0.0))
                               .RegisterName("loopcond");

                // Create the "after loop" block and insert it.
                var afterBlock = function.AppendBasicBlock("afterloop");

                // Insert the conditional branch into the end of LoopEndBB.
                InstructionBuilder.Branch(endCondition, loopBlock, afterBlock);
                InstructionBuilder.PositionAtEnd(afterBlock);

                // for expression always returns 0.0 for consistency, there is no 'void'
                return(Context.DoubleType.GetNullValue( ));
            }
        }
예제 #6
0
        public override Value Visit(ForInExpression forInExpression)
        {
            var    function = InstructionBuilder.InsertBlock.ContainingFunction;
            string varName  = forInExpression.LoopVariable.Name;

            // Emit the start code first, without 'variable' in scope.
            Value startVal;

            if (forInExpression.LoopVariable.Initializer != null)
            {
                startVal = forInExpression.LoopVariable.Initializer.Accept(this);
                if (startVal == null)
                {
                    return(null);
                }
            }
            else
            {
                startVal = Context.CreateConstant(0.0);
            }

            // Make the new basic block for the loop header, inserting after current
            // block.
            var preHeaderBlock = InstructionBuilder.InsertBlock;
            var loopBlock      = function.AppendBasicBlock("loop");

            // Insert an explicit fall through from the current block to the loopBlock.
            InstructionBuilder.Branch(loopBlock);

            // Start insertion in loopBlock.
            InstructionBuilder.PositionAtEnd(loopBlock);

            // Start the PHI node with an entry for Start.
            var variable = InstructionBuilder.PhiNode(Context.DoubleType)
                           .RegisterName(varName);

            variable.AddIncoming(startVal, preHeaderBlock);

            // Within the loop, the variable is defined equal to the PHI node.
            // So, push a new scope for it and any values the body might set
            using (NamedValues.EnterScope( ))
            {
                NamedValues[varName] = variable;

                // Emit the body of the loop.  This, like any other expression, can change the
                // current BB.  Note that we ignore the value computed by the body, but don't
                // allow an error.
                if (forInExpression.Body.Accept(this) == null)
                {
                    return(null);
                }

                Value stepValue = forInExpression.Step.Accept(this);
                if (stepValue == null)
                {
                    return(null);
                }

                var nextVar = InstructionBuilder.FAdd(variable, stepValue)
                              .RegisterName("nextvar");

                // Compute the end condition.
                Value endCondition = forInExpression.Condition.Accept(this);
                if (endCondition == null)
                {
                    return(null);
                }

                // Convert condition to a bool by comparing non-equal to 0.0.
                endCondition = InstructionBuilder.Compare(RealPredicate.OrderedAndNotEqual, endCondition, Context.CreateConstant(0.0))
                               .RegisterName("loopcond");

                // capture loop end result block for loop variable PHI node
                var loopEndBlock = InstructionBuilder.InsertBlock;

                // Create the "after loop" block and insert it.
                var afterBlock = function.AppendBasicBlock("afterloop");

                // Insert the conditional branch into the end of LoopEndBB.
                InstructionBuilder.Branch(endCondition, loopBlock, afterBlock);
                InstructionBuilder.PositionAtEnd(afterBlock);

                // Add a new entry to the PHI node for the back-edge.
                variable.AddIncoming(nextVar, loopEndBlock);

                // for expression always returns 0.0 for consistency, there is no 'void'
                return(Context.DoubleType.GetNullValue( ));
            }
        }
예제 #7
0
 public virtual TResult Visit(ForInExpression forInExpression) => VisitChildren(forInExpression);
 protected virtual Expression VisitForIn(ForInExpression node)
 {
     Visit(node.Enumerator);
     Visit(node.Body);
     return(node);
 }