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()); }
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")); }
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")); }
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)); }
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( )); } }
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( )); } }
public virtual TResult Visit(ForInExpression forInExpression) => VisitChildren(forInExpression);
protected virtual Expression VisitForIn(ForInExpression node) { Visit(node.Enumerator); Visit(node.Body); return(node); }