protected override string[] whileTr(WhileLoop loop) { dynamic[] info = loop.getTranslatorInfo(); string condition = normalizeExpression(((Expression)info[0]).expr); string[] instructions = instr2Lines((List <Instruction>)info[1]); var loop_str_list = new List <string> { "while (" + condition + ") {" }; loop_str_list.AddRange(instructions); loop_str_list.Add("}"); return(loop_str_list.ToArray()); }
public void Equality_ReallyTheSame() { var a = new WhileLoop { Condition = new ConstantValueExpression() }; a.Body.Add(new ReturnStatement()); var b = new WhileLoop { Condition = new ConstantValueExpression() }; b.Body.Add(new ReturnStatement()); Assert.AreEqual(a, b); Assert.AreEqual(a.GetHashCode(), b.GetHashCode()); }
/// <summary> /// Attempts to get complex behavior from the tag. Will return null if tags are not /// <see cref="IfTag"/> or <see cref="WhileTag"/> implementations of the <see cref="ProfileBehavior"/> class /// </summary> /// <param name="behavior"></param> /// <returns></returns> private Composite GetProfileBehaviorTree(ProfileBehavior behavior) { var ifBehavior = behavior as IfTag; var whileBehavior = behavior as WhileTag; Composite bodyBehavior; if (ifBehavior != null) { bodyBehavior = new Decorator( (r) => ScriptManager.GetCondition(ifBehavior.Condition).Invoke(), new Sequence( this.GetProfileBehaviorCollectionBehavior(ifBehavior.Body).ToArray() ) ); } else if (whileBehavior != null) { bodyBehavior = new WhileLoop( (r) => ScriptManager.GetCondition(whileBehavior.Condition).Invoke(), this.GetProfileBehaviorCollectionBehavior(whileBehavior.Body).ToArray() ); } else { bodyBehavior = (Composite)behavior.InvokePrivateMethod <Composite>("CreateBehavior", null); } return(new PrioritySelector( new ActionRunOnce( (r) => { try { behavior.InvokePrivateMethod("UpdateBehavior"); behavior.Start(); } catch { // TODO: Get a better understanding of how RB starts the profile behaviors during behavior execution } return RunStatus.Failure; } ), bodyBehavior, new ActionAlwaysSucceed() )); }
public void CompileWhileLoop(WhileLoop whileLoop) { XmlElement previousElement = currentElement; XmlElement tmpElement = document.CreateElement("WhileLoop"); currentElement = document.CreateElement("Guard"); whileLoop.Guard.AcceptCompiler(this); tmpElement.AppendChild(currentElement); currentElement = document.CreateElement("Body"); whileLoop.Body.AcceptCompiler(this); tmpElement.AppendChild(currentElement); previousElement.AppendChild(tmpElement); currentElement = previousElement; }
protected virtual ICfgNode Build(WhileLoop whileLoop) { whileLoop.Condition.Accept(this); var condition = Result; whileLoop.Body?.Accept(this); var body = Result; if (condition == null && body == null) { return(null); } return(Emit.While( condition ?? whileLoop.Condition, body ?? whileLoop.Body)); }
protected override void TranslateWhileLoop(List <string> output, WhileLoop whileLoop) { output.Add(this.CurrentTabIndention); output.Add("while ("); this.TranslateExpression(output, whileLoop.Condition); if (this.isEgyptian) { output.Add(") {" + this.NL); } else { output.Add(")"); output.Add(this.NL); output.Add(this.CurrentTabIndention); output.Add("{"); output.Add(this.NL); } this.CurrentIndention++; this.Translate(output, whileLoop.Code); this.CurrentIndention--; output.Add(this.CurrentTabIndention); output.Add("}" + this.NL); }
public async void BreakWhileLoopTest() { // Arrange var step1 = new LoopStep("one"); var step2 = new LoopStep("two"); var breakStep = new StopThatThrowsBreak("break-step"); var baseStepList = new List <Step <SimpleWorkflowState> > { step1, step2, breakStep }; var forLoop = new WhileLoop <SimpleWorkflowState>(name: "foo", steps: baseStepList); // Act var result = await forLoop.Execute(_workflowState); var nonBreakStepCount = baseStepList.Count(x => x.GetType() != breakStep.GetType()); // Assert Assert.Equal(nonBreakStepCount, result.State.MyInteger); Assert.Equal(baseStepList.Count + 1, result.WorkflowChain.Count); Assert.Equal(0, forLoop.CurrentIteration); }
public override Value Visit(WhileLoop node) { // br whileloop ; llvm demands it // whileloop: // br cond, whilebody, whileend // whilebody: // body // br whileloop // whileend: // func was set in Visit(RoutineDefinition node) Function func = evalCtx.func; BasicBlock whileloop = func.AppendBasicBlock("whileloop"); BasicBlock whilebody = func.AppendBasicBlock("whilebody"); BasicBlock whileend = func.AppendBasicBlock("whileend"); evalCtx.EnterLoop(whileloop, whileend); builder.BuildBr(whileloop); builder.ResetInsertPoint(func, whileloop); Value cond = traverse(node.condition); builder.BuildCondBr(cond, whilebody, whileend); builder.ResetInsertPoint(func, whilebody); Value block = traverse(node.block); builder.BuildBr(whileend); Debug.Assert(!block.IsNull, "Invalid While loop block"); Debug.Assert(!cond.IsNull, "Invalid While loop condition"); builder.ResetInsertPoint(func, whileend); evalCtx.LeaveLoop(); return(Value.NonNull); }
public void StepMethods() { // Arrange var step1 = new BaseStep("one"); var step2 = new BaseStep("two"); var step3 = new BaseStep("three"); var baseStepList = new List <Step <SimpleWorkflowState> > { step1, step2, step3 }; var whileLoop = new WhileLoop <SimpleWorkflowState>(); // ActSert a lot because who cares... whileLoop.SetSteps(baseStepList); Assert.Equal(baseStepList, whileLoop.Steps); whileLoop.ClearSteps(); Assert.Empty(whileLoop.Steps); whileLoop.AddStep(step1); Assert.Single(whileLoop.Steps); Assert.Equal(step1, whileLoop.Steps.First()); }
public override bool Visit(WhileLoop node) { Visit((LoopStatement)node); return(true); }
public void Visit(WhileLoop ast) { Exec(ast); }
public abstract void TranslateWhileLoop(StringBuilder sb, WhileLoop whileLoop);
private Stmt ParseStmt() { Stmt result = null; if (this.index == this.tokens.Count) { throw new System.Exception("expected statement, got EOF"); } // <stmt> := print <expr> // <expr> := <string> // | <int> // | <arith_expr> // | <ident> if (this.tokens[this.index].Equals(languageSetting["End"])) { this.index++; } else if (this.tokens[this.index].Equals(languageSetting["Start"])) { this.index++; return(ParseStmt()); } else if (this.tokens[this.index].Equals(languageSetting["Print"])) { this.index++; Print print = new Print(); print.Expr = this.ParseExpr(); result = print; } else if (this.tokens[this.index] == Scanner.Call) { VoidMethodCall vmc = new VoidMethodCall(); vmc.Expr = this.ParseExpr(); result = vmc; } else if (this.tokens[this.index].Equals(languageSetting["VariableDeclaration"])) { this.index++; DeclareVar declareVar = new DeclareVar(); if (this.index < this.tokens.Count && this.tokens[this.index] is string) { declareVar.Ident = (string)this.tokens[this.index]; } else { throw new System.Exception("expected variable name after 'var'"); } this.index++; if (this.index == this.tokens.Count || this.tokens[this.index] != Scanner.Equal) { throw new System.Exception("expected = after 'var ident'"); } this.index++; declareVar.Expr = this.ParseExpr(); result = declareVar; } else if (this.tokens[this.index].Equals(languageSetting["if"])) { this.index++; IfCondition ifCon = new IfCondition(); ifCon.BooleanExp = this.ParseExpr(); if (!this.tokens[++this.index].Equals(languageSetting["Start"])) { throw new System.Exception("Start Expected"); } ifCon.Body = this.ParseStmt(); if (!this.tokens[this.index++].Equals(languageSetting["End"])) { throw new System.Exception("End Expected"); } result = ifCon; } else if (this.tokens[this.index].Equals(languageSetting["while"])) { this.index++; WhileLoop whileLoop = new WhileLoop(); whileLoop.BooleanExp = this.ParseExpr(); if (!this.tokens[++this.index].Equals(languageSetting["Start"])) { throw new System.Exception("Start Expected"); } whileLoop.Body = this.ParseStmt(); if (!this.tokens[this.index++].Equals(languageSetting["End"])) { throw new System.Exception("End Expected"); } result = whileLoop; } else if (this.tokens[this.index].Equals("read_int")) { this.index++; ReadInt readInt = new ReadInt(); if (this.index < this.tokens.Count && this.tokens[this.index] is string) { readInt.Ident = (string)this.tokens[this.index++]; result = readInt; } else { throw new System.Exception("expected variable name after 'read_int'"); } } else if (this.tokens[this.index].Equals("for")) { this.index++; ForLoop forLoop = new ForLoop(); if (this.index < this.tokens.Count && this.tokens[this.index] is string) { forLoop.Ident = (string)this.tokens[this.index]; } else { throw new System.Exception("expected identifier after 'for'"); } this.index++; if (this.index == this.tokens.Count || this.tokens[this.index] != Scanner.Equal) { throw new System.Exception("for missing '='"); } this.index++; forLoop.From = this.ParseSingleExpression(); if (this.index == this.tokens.Count || !this.tokens[this.index].Equals("to")) { throw new System.Exception("expected 'to' after for"); } this.index++; forLoop.To = this.ParseSingleExpression(); if (this.index == this.tokens.Count || !this.tokens[this.index].Equals("do")) { throw new System.Exception("expected 'do' after from expression in for loop"); } this.index++; forLoop.Body = this.ParseStmt(); result = forLoop; if (this.index == this.tokens.Count || !this.tokens[this.index].Equals("end")) { throw new System.Exception("unterminated 'for' loop body"); } this.index++; } else if (this.tokens[this.index] is string) { // assignment Assign assign = new Assign(); assign.Ident = (string)this.tokens[this.index++]; if (this.index == this.tokens.Count || this.tokens[this.index] != Scanner.Equal) { throw new System.Exception("expected '='"); } this.index++; assign.Expr = this.ParseExpr(); result = assign; } else { throw new System.Exception("parse error at token " + this.index + ": " + this.tokens[this.index]); } if (this.index < this.tokens.Count && this.tokens[this.index] == Scanner.Semi) { this.index++; if (this.index < this.tokens.Count && !this.tokens[this.index].Equals(languageSetting["End"])) { Sequence sequence = new Sequence(); sequence.First = result; sequence.Second = this.ParseStmt(); result = sequence; } } return(result); }
void IStatementVisitor.Visit(WhileLoop stmt) { throw new NotImplementedException(); }
public Statement DecompileConditionalJump(bool isOpt = false) // TODO: guess for loop, probably requires a large restructure { PopByte(); var scopeStartOffset = StartPositions.Pop(); Statement statement = null; bool hasElse = false; var scopeStatements = new List <Statement>(); UInt16 scopeEndJmpOffset = 0; UInt16 afterScopeOffset = 0; Expression conditional = null; if (isOpt) { var obj = ReadObject(); var optCheck = Convert.ToBoolean(ReadByte()); afterScopeOffset = ReadUInt16(); String special = (optCheck ? "" : "!") + obj.ObjectName; conditional = new SymbolReference(null, null, null, special); } else { afterScopeOffset = ReadUInt16(); conditional = DecompileExpression(); } if (conditional == null) { return(null); } if (afterScopeOffset < scopeStartOffset) // end of do_until detection { scopeStartOffset = afterScopeOffset; var outerScope = Scopes[CurrentScope.Peek()]; var startStatement = StatementLocations[afterScopeOffset]; StatementLocations.Remove(afterScopeOffset); var index = outerScope.IndexOf(startStatement); scopeStatements = new List <Statement>(outerScope.Skip(index)); outerScope.RemoveRange(index, outerScope.Count - index); statement = new DoUntilLoop(conditional, new CodeBody(scopeStatements, null, null), null, null); } Scopes.Add(scopeStatements); CurrentScope.Push(Scopes.Count - 1); while (Position < afterScopeOffset) { if (CurrentIs(StandardByteCodes.Jump)) { var contPos = (UInt16)Position; PopByte(); scopeEndJmpOffset = ReadUInt16(); if (scopeEndJmpOffset == scopeStartOffset) { statement = new WhileLoop(conditional, new CodeBody(scopeStatements, null, null), null, null); break; } else if (Position < afterScopeOffset) // if we are not at the end of the scope, this is a continue statement in a loop rather than an else statement { var cont = new ContinueStatement(null, null); StatementLocations.Add(contPos, cont); scopeStatements.Add(cont); } else if (ForEachScopes.Count != 0 && scopeEndJmpOffset == ForEachScopes.Peek()) { var breakStatement = new BreakStatement(null, null); StatementLocations.Add(contPos, breakStatement); scopeStatements.Add(breakStatement); } else { hasElse = true; } continue; } var current = DecompileStatement(); if (current == null) { return(null); // ERROR ? } scopeStatements.Add(current); } CurrentScope.Pop(); List <Statement> elseStatements = new List <Statement>(); if (hasElse) { var endElseOffset = scopeEndJmpOffset; Scopes.Add(elseStatements); CurrentScope.Push(Scopes.Count - 1); while (Position < endElseOffset) { var current = DecompileStatement(); if (current == null) { return(null); // ERROR ? } elseStatements.Add(current); } CurrentScope.Pop(); } statement = statement ?? new IfStatement(conditional, new CodeBody(scopeStatements, null, null), null, null, elseStatements.Count != 0 ? new CodeBody(elseStatements, null, null) : null); StatementLocations.Add(scopeStartOffset, statement); return(statement); }
public abstract void Visit(WhileLoop visitable);
static void Main() { WhileLoop.Run(); // @MDB LINE: main Foreach.Run(); MarshalByRefTest.Run(); }
protected abstract string[] whileTr(WhileLoop loop);
public Statement(WhileLoop whileLoop) { WhileLoop = whileLoop; }
public abstract void TranslateWhileLoop(TranspilerContext sb, WhileLoop whileLoop);
public void Visit(WhileLoop whileLoop) => Result = Build(whileLoop);
public bool VisitNode(WhileLoop node) { throw new NotImplementedException(); }
/// <summary> /// Attempts to get complex behavior from the tag. Will return null if tags are not /// <see cref="IfTag"/> or <see cref="WhileTag"/> implementations of the <see cref="ProfileBehavior"/> class /// </summary> /// <param name="behavior"></param> /// <returns></returns> private Composite GetProfileBehaviorTree(ProfileBehavior behavior) { var ifBehavior = behavior as IfTag; var whileBehavior = behavior as WhileTag; Composite bodyBehavior; if (ifBehavior != null) { bodyBehavior = new Decorator( (r) => ScriptManager.GetCondition(ifBehavior.Condition).Invoke(), new Sequence( this.GetProfileBehaviorCollectionBehavior(ifBehavior.Body).ToArray() ) ); } else if (whileBehavior != null) { bodyBehavior = new WhileLoop( (r) => ScriptManager.GetCondition(whileBehavior.Condition).Invoke(), this.GetProfileBehaviorCollectionBehavior(whileBehavior.Body).ToArray() ); } else { bodyBehavior = (Composite) behavior.InvokePrivateMethod<Composite>("CreateBehavior", null); } return new PrioritySelector( new ActionRunOnce( (r) => { try { behavior.InvokePrivateMethod("UpdateBehavior"); behavior.Start(); } catch { // TODO: Get a better understanding of how RB starts the profile behaviors during behavior execution } return RunStatus.Failure; } ), bodyBehavior, new ActionAlwaysSucceed() ); }
private Stmt ParseStmt() { Stmt resultado; if (this.indice == this.tokens.Count) { throw new System.Exception("se esperaban sentencias, se llego al final del archivo"); } // <stmt> := print <expr> // <expr> := <string> // | <int> // | <arith_expr> // | <ident> if (this.tokens[this.indice].Equals("print")) { this.indice++; Print print = new Print(); print.Expr = this.ParseExpr(); resultado = print; } else if (this.tokens[this.indice].Equals("var")) { this.indice++; DeclareVar declareVar = new DeclareVar(); if (this.indice < this.tokens.Count && this.tokens[this.indice] is string) { declareVar.Ident = (string)this.tokens[this.indice]; } else { throw new System.Exception("Se esperaba nombre de variable despues de 'var'"); } this.indice++; if (this.indice == this.tokens.Count || this.tokens[this.indice] != Scanner.Igual) { throw new System.Exception("se esperaba = despues de 'var ident'"); } this.indice++; declareVar.Expr = this.ParseExpr(); resultado = declareVar; } else if (this.tokens[this.indice].Equals("read_int")) { this.indice++; ReadInt readInt = new ReadInt(); if (this.indice < this.tokens.Count && this.tokens[this.indice] is string) { readInt.Ident = (string)this.tokens[this.indice++]; resultado = readInt; } else { throw new System.Exception("Se esperaba el nombre de la variable 'read_int'"); } } //******************* else if (this.tokens[this.indice].Equals("if")) { this.indice++; mcIf mcif = new mcIf(); Expr temp = ParseExpr(); if (this.tokens[this.indice] == Scanner.Eq || this.tokens[this.indice] == Scanner.Neq || this.tokens[this.indice] == Scanner.Gt || this.tokens[this.indice] == Scanner.Gte || this.tokens[this.indice] == Scanner.Lt || this.tokens[this.indice] == Scanner.Lte) { CompExpr compExpr = new CompExpr(); compExpr.Left = temp; object op = this.tokens[this.indice++]; if (op == Scanner.Eq) { compExpr.Op = CompOp.Eq; } else if (op == Scanner.Neq) { compExpr.Op = CompOp.Neq; } else if (op == Scanner.Gt) { compExpr.Op = CompOp.Gt; } else if (op == Scanner.Gte) { compExpr.Op = CompOp.Gte; } else if (op == Scanner.Lt) { compExpr.Op = CompOp.Lt; } else if (op == Scanner.Lte) { compExpr.Op = CompOp.Lte; } compExpr.Rigth = ParseExpr(); temp = compExpr; } mcif.compExpr = temp; if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("then")) { throw new System.Exception("Se esperaba el identificador 'then' despues de 'if'"); } this.indice++; mcif.Then = ParseStmt(); if (this.tokens[this.indice].Equals("else")) { this.indice++; mcif.Else = ParseStmt(); } resultado = mcif; if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("end")) { throw new System.Exception("Sentencia if inconclusa"); } this.indice++; } else if (this.tokens[this.indice].Equals("while")) { this.indice++; WhileLoop whileLoop = new WhileLoop(); Expr temp = ParseExpr(); if (this.tokens[this.indice] == Scanner.Eq || this.tokens[this.indice] == Scanner.Neq || this.tokens[this.indice] == Scanner.Gt || this.tokens[this.indice] == Scanner.Gte || this.tokens[this.indice] == Scanner.Lt || this.tokens[this.indice] == Scanner.Lte) { CompExpr compExpr = new CompExpr(); compExpr.Left = temp; object op = this.tokens[this.indice++]; if (op == Scanner.Eq) { compExpr.Op = CompOp.Eq; } else if (op == Scanner.Neq) { compExpr.Op = CompOp.Neq; } else if (op == Scanner.Gt) { compExpr.Op = CompOp.Gt; } else if (op == Scanner.Gte) { compExpr.Op = CompOp.Gte; } else if (op == Scanner.Lt) { compExpr.Op = CompOp.Lt; } else if (op == Scanner.Lte) { compExpr.Op = CompOp.Lte; } compExpr.Rigth = ParseExpr(); temp = compExpr; } whileLoop.Cond = temp; if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("do")) { throw new System.Exception("Se esperaba el identificador 'do' despues de 'while'"); } this.indice++; whileLoop.Body = ParseStmt(); resultado = whileLoop; if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("end")) { throw new System.Exception("sentencia while inconclusa"); } this.indice++; } //******************* else if (this.tokens[this.indice].Equals("for")) { this.indice++; ForLoop forLoop = new ForLoop(); if (this.indice < this.tokens.Count && this.tokens[this.indice] is string) { forLoop.Ident = (string)this.tokens[this.indice]; } else { throw new System.Exception("se esperaba un indentificador despues de 'for'"); } this.indice++; if (this.indice == this.tokens.Count || this.tokens[this.indice] != Scanner.Igual) { throw new System.Exception("no se encontro en la sentencia for '='"); } this.indice++; forLoop.From = this.ParseExpr(); if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("to")) { throw new System.Exception("se epsaraba 'to' despues de for"); } this.indice++; forLoop.To = this.ParseExpr(); if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("do")) { throw new System.Exception("se esperaba 'do' despues de la expresion en el ciclo for"); } this.indice++; forLoop.Body = this.ParseStmt(); resultado = forLoop; if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("end")) { throw new System.Exception("setencia for inconclusa"); } this.indice++; } else if (this.tokens[this.indice] is string) { // assignment Assign assign = new Assign(); assign.Ident = (string)this.tokens[this.indice++]; if (this.indice == this.tokens.Count || this.tokens[this.indice] != Scanner.Igual) { throw new System.Exception("se esperaba '='"); } this.indice++; assign.Expr = this.ParseExpr(); resultado = assign; } else { throw new System.Exception("Error en el token " + this.indice + ": " + this.tokens[this.indice]); } if (this.indice < this.tokens.Count && this.tokens[this.indice] == Scanner.PyC) { this.indice++; if (this.indice < this.tokens.Count && !this.tokens[this.indice].Equals("end") && !this.tokens[this.indice].Equals("else")) { Sequence sequence = new Sequence(); sequence.First = resultado; sequence.Second = this.ParseStmt(); resultado = sequence; } } return(resultado); }
public virtual T Visit(WhileLoop node) { return(Visit((LoopStatement)node)); }
private void DecompileLoopsAndIfs(List <Statement> statements, Dictionary <Statement, ushort> positions, bool inLoop = false) { var defaultCaseStatements = new Stack <Statement>(); var switchEnds = new Dictionary <int, ushort>(); for (int i = statements.Count - 1; i >= 0; i--) { var cur = statements[i]; if (!positions.TryGetValue(cur, out ushort curPos)) { continue; //default param values, labels } if (cur is UnconditionalJump loopEnd && loopEnd.JumpLoc < curPos) { //end of while or for loop var continueToPos = curPos; Statement statementBeforeEndOfLoop = statements[i - 1]; bool isForLoop = IsIncrementDecrement(statementBeforeEndOfLoop, out Statement update); var loopStart = StatementLocations[loopEnd.JumpLoc]; int conditionIdx = statements.IndexOf(loopStart); int skipStart = conditionIdx; int numToSkip = i - conditionIdx + 1; if (!(statements[conditionIdx] is ConditionalJump conditionalJump)) { //TODO: replace the unconditional jump with a goto? or perhaps this is a loop with no condition? throw new Exception("Invalid Control Flow!"); } CodeBody loopBody = new CodeBody(statements.GetRange(conditionIdx + 1, i - conditionIdx - 1)); if (!isForLoop && !(statementBeforeEndOfLoop is Jump)) { //check to see if there is an unconditional jump to the statement before the end of the loop. This indicates a continue inside a for loop var checkPos = positions[statementBeforeEndOfLoop]; if (loopBody.Statements.OfType <UnconditionalJump>().Any(possibleContinue => possibleContinue.JumpLoc == checkPos)) { update = statementBeforeEndOfLoop; isForLoop = true; } } else if (isForLoop) { //check to see if there is an unconditional jump to the end of the loop. //This indicates that the loop is NOT a for loop, as there is no way to skip the increment statement in a for loop for (int j = i - 2; j > conditionIdx; j--) { if (statements[j] is UnconditionalJump unj && unj.JumpLoc == curPos) { isForLoop = false; break; } } } AssignStatement forInit = null; ushort loopLoc = loopEnd.JumpLoc; if (isForLoop && conditionIdx > 0 && statements[conditionIdx - 1] is AssignStatement assignStatement) { forInit = assignStatement; skipStart = conditionIdx - 1; numToSkip++; loopLoc = positions[assignStatement]; } Statement loop; Expression condition = conditionalJump.Condition; if (isForLoop) { continueToPos = positions[statementBeforeEndOfLoop]; loopBody.Statements.RemoveAt(loopBody.Statements.Count - 1); loop = new ForLoop(forInit, condition, update, loopBody); } else { loop = new WhileLoop(condition, loopBody); } //recurse into body of loop DecompileLoopsAndIfs(loopBody.Statements, positions, true); //convert unconditional jumps into continue and break const int sizeOfUnconditionalJump = 3; ConvertJumps(loopBody, continueToPos, loopEnd.JumpLoc, curPos + sizeOfUnconditionalJump); statements.RemoveRange(skipStart, numToSkip); statements.Insert(skipStart, loop); StatementLocations[loopLoc] = loop; positions[loop] = loopLoc; i = skipStart; }
public void Evaluate(List <Step> evaluationSteps) { for (int index = 0; index < evaluationSteps.Count; index++) { Step evalStep = evaluationSteps[index]; // .Type() can only be "VAR_DECLARE", "VAR_CHANGE", "FUNC_CALL", "IF_STATEMENT", "WHILE_LOOP" // It could also be "ELSE_STATEMENT", but we should only check for that DIRECTLY after an IF_STATEMENT if (evalStep.Type().Equals("IF_STATEMENT")) { // Evaluate if statement - contains OPERAND1, OPERAND2, COMPARISON, codeBlockContents IfStatement ifState = (IfStatement)evalStep; // Cast as we know it is now an IfStatement obj bool conditionResult = CompareExpressions(ifState.GetOp1(), ifState.GetOp2(), ifState.GetComparator()); bool hasElse = index + 1 < evaluationSteps.Count && evaluationSteps[index + 1].Type().Equals("ELSE_STATEMENT"); // No chance of index out of range error as set to False before reaching it if (conditionResult) // If the 'IfStatement' condition is TRUE { Evaluate(ifState.GetCBContents()); // 'run' the contents of the if statement - this is RECURSIVE if (hasElse) { evaluationSteps.RemoveAt(index + 1); } // If we have an ELSE_STATEMENT after this, we need to remove it as the IF_STATEMENT has triggered (therefore the ELSE will not be triggered). } else if (hasElse) { // If the CONDITION is FALSE and the next Step obj is an ELSE_STATEMENT type ElseStatement elseState = (ElseStatement)evaluationSteps[index + 1]; // Cast to else Evaluate(elseState.GetCBContents()); // 'run' the contents of the else (RECURSION) evaluationSteps.RemoveAt(index + 1); // Remove ELSE_STATEMENT as we have used it and do not want to go over it again. } } else if (evalStep.Type().Equals("WHILE_LOOP")) { WhileLoop whileLoop = (WhileLoop)evalStep; // Similar to if statement evaluation though no need to set a 'condition' variable because that condition may change // Basically just reusing the C# while loop with the template of the Interpreted one while (CompareExpressions(whileLoop.GetOp1(), whileLoop.GetOp2(), whileLoop.GetComparator())) { // While the condition is true, evaluate code inside Evaluate(whileLoop.GetCBContents()); } } else if (evalStep.Type().Equals("VAR_DECLARE")) // Declare a variable in the variableScope { VarDeclare varDecl = (VarDeclare)evalStep; // Cast as we know it's a VarDeclare obj if (variableScope.ContainsKey(varDecl.GetName())) { throw new DeclareError(); } // If scope already has a variable that name, you cannot redeclare it as it already exists. // Potential endpoint if variable exists - entire program will stop (crash). Token varExpr = ResolveExpression(varDecl.Value()); if (!varExpr.Type().Equals(varDecl.GetVarType())) { throw new TypeError(); } // Value of variable does not match type with declared one. e.g 'int x = "Hello";' variableScope.Add(varDecl.GetName(), varExpr); // Type of variable can be found out by the .Type() of the key's Token. // e.g 'int x = 1 + 2;' // if we want to find variable 'x' type, we find variableScope[x].Type() which will return 'number', with variableScope[x].Value() being '3' } else if (evalStep.Type().Equals("VAR_CHANGE")) // Change a pre-existing variable { VarChange varChan = (VarChange)evalStep; // Cast as we know it is a VarChange obj if (!variableScope.ContainsKey(varChan.GetName())) { throw new ReferenceError(); } // If variable is NOT in the variableScope then we cannot change it as it doesn't exist. // Potential endpoint for program crash string varType = variableScope[varChan.GetName()].Type(); Token newValue = ResolveExpression(varChan.Value()); if (!varType.Equals(newValue.Type())) { throw new TypeError(); } // If the new value of the variable is not the right type, then crash. // Potential endpoint // e.g int x = 0; x = "hi"; will cause this error variableScope[varChan.GetName()] = newValue; // Assign new value (Token) } else if (evalStep.Type().Equals("FUNC_CALL")) // Call a function { FuncCall functionCall = (FuncCall)evalStep; // Cast as we know it is a FuncCall obj now if (!functionCall.GetName().Equals("inputstr") && !functionCall.GetName().Equals("inputint")) // If NOT calling 'input' function { CallFunction(functionCall.GetName(), ResolveExpression(functionCall.GetArguments())); // Call function with name and *resolved* list of arguments // Resolve function always outputs a single token which is the result of an expression (list of tokens) being evaluated } else // SPECIAL CASE: Calling inputStr or inputInt functions indicates that the 'argument' is NOT an expression to be resolved, but rather a variable name to store input value in. // This means functionCall.Argumnets() will only have 1 token: { CallFunction(functionCall.GetName(), functionCall.GetArguments()[0]); // Pass in first value in Arguments as there only should be one - the variable to be input to } } else { throw new SyntaxError(); // Unrecognised Step, crash program. } } }
public virtual void Visit(WhileLoop whileLoop) { whileLoop.Condition.Accept(this); whileLoop.Body?.Accept(this); }
private void GenStmt(Stmt stmt) { if (stmt is Sequence) { Sequence seq = (Sequence)stmt; this.GenStmt(seq.First); this.GenStmt(seq.Second); } else if (stmt is DeclareVar) { // declare a local DeclareVar declare = (DeclareVar)stmt; this.symbolTable[declare.Ident] = this.il.DeclareLocal(this.TypeOfExpr(declare.Expr)); // set the initial value Assign assign = new Assign(); assign.Ident = declare.Ident; assign.Expr = declare.Expr; this.GenStmt(assign); } else if (stmt is Assign) { Assign assign = (Assign)stmt; this.GenExpr(assign.Expr, this.TypeOfExpr(assign.Expr)); this.Store(assign.Ident, this.TypeOfExpr(assign.Expr)); } else if (stmt is Print) { // the "print" statement is an alias for System.Console.WriteLine. // it uses the string case this.GenExpr(((Print)stmt).Expr, typeof(string)); this.il.Emit(Emit.OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new System.Type[] { typeof(string) })); } else if (stmt is ReadInt) { this.il.Emit(Emit.OpCodes.Call, typeof(System.Console).GetMethod("ReadLine", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static, null, new System.Type[] { }, null)); this.il.Emit(Emit.OpCodes.Call, typeof(int).GetMethod("Parse", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static, null, new System.Type[] { typeof(string) }, null)); this.Store(((ReadInt)stmt).Ident, typeof(int)); } //******************* else if (stmt is mcIf) { mcIf mcif = (mcIf)stmt; //this.GenExpr(mcif.compExpr, typeof(int)); Emit.Label Else = this.il.DefineLabel(); Emit.Label Then = this.il.DefineLabel(); Emit.Label Salida = this.il.DefineLabel(); if (mcif.compExpr is CompExpr) { CompExpr compExpr = (CompExpr)mcif.compExpr; this.GenExpr(compExpr.Left, typeof(int)); this.GenExpr(compExpr.Rigth, typeof(int)); genCodComp(compExpr.Op, Then); } else { GenExpr(mcif.compExpr, typeof(string)); this.il.Emit(Emit.OpCodes.Ldc_I4, 0); this.il.Emit(Emit.OpCodes.Bne_Un, Then); } if (mcif.Else != null) { this.il.Emit(Emit.OpCodes.Br, Else); } else { this.il.Emit(Emit.OpCodes.Br, Salida); } this.il.MarkLabel(Then); GenStmt(mcif.Then); this.il.Emit(Emit.OpCodes.Br, Salida); this.il.MarkLabel(Else); if (mcif.Else != null) { GenStmt(mcif.Else); } this.il.MarkLabel(Salida); } else if (stmt is WhileLoop) { WhileLoop whileLoop = (WhileLoop)stmt; Emit.Label Body = this.il.DefineLabel(); Emit.Label Salida = this.il.DefineLabel(); Emit.Label Cond = this.il.DefineLabel(); this.il.MarkLabel(Cond); if (whileLoop.Cond is CompExpr) { CompExpr compExpr = (CompExpr)whileLoop.Cond; this.GenExpr(compExpr.Left, typeof(int)); this.GenExpr(compExpr.Rigth, typeof(int)); genCodComp(compExpr.Op, Body); } else { GenExpr(whileLoop.Cond, typeof(string)); this.il.Emit(Emit.OpCodes.Ldc_I4, 0); this.il.Emit(Emit.OpCodes.Bne_Un, Body); } this.il.Emit(Emit.OpCodes.Br, Salida); this.il.MarkLabel(Body); GenStmt(whileLoop.Body); this.il.Emit(Emit.OpCodes.Br, Cond); this.il.MarkLabel(Salida); } //******************* else if (stmt is ForLoop) { // example: // for x = 0 to 100 do // print "hello"; // end; // x = 0 ForLoop forLoop = (ForLoop)stmt; Assign assign = new Assign(); assign.Ident = forLoop.Ident; assign.Expr = forLoop.From; this.GenStmt(assign); // jump to the test Emit.Label test = this.il.DefineLabel(); this.il.Emit(Emit.OpCodes.Br, test); // statements in the body of the for loop Emit.Label body = this.il.DefineLabel(); this.il.MarkLabel(body); this.GenStmt(forLoop.Body); // to (increment the value of x) this.il.Emit(Emit.OpCodes.Ldloc, this.symbolTable[forLoop.Ident]); this.il.Emit(Emit.OpCodes.Ldc_I4, 1); this.il.Emit(Emit.OpCodes.Add); this.Store(forLoop.Ident, typeof(int)); // **test** does x equal 100? (do the test) this.il.MarkLabel(test); this.il.Emit(Emit.OpCodes.Ldloc, this.symbolTable[forLoop.Ident]); this.GenExpr(forLoop.To, typeof(int)); this.il.Emit(Emit.OpCodes.Blt, body); } else { throw new System.Exception("imposible generar: " + stmt.GetType().Name); } }
// Performs actions defined by the Node // If the Node is part of core functionality of the language, e.g. assigning to variables, performing arithmetic, etc. then handle it here. // Otherwise, continue to child implementations of this method. public virtual ExecutionStatus ExecuteNode(NodeBase node) { if (node == null) { programRunning = false; currentNode = program.programStart; return(new ExecutionStatus { success = false, handover = false }); } switch (CheckNodeType(node)) { // Handlers for different commands case NodeType.ProgramStart: Logger.Log("Program starting!"); processingDone = true; InitSymTable(); // TODO: this doesn't actually reset the buffer? outputBuffer = ""; return(new ExecutionStatus { success = true, handover = false }); case NodeType.AssignValue: AssignValue assignValue = node.GetComponent <AssignValue>(); SetSymbol(assignValue.leftHand, assignValue.rightHand); return(new ExecutionStatus { success = true, handover = false }); case NodeType.ArithmeticOperationBase: // Arithmetic only takes a tick when it gets executed currentNode = (NodeBase)currentNode.nextNode; return(ExecuteNode(currentNode)); case NodeType.ProgramEnd: processingDone = true; programRunning = false; return(new ExecutionStatus { success = true, handover = false }); case NodeType.FunctionCallBase: string funcName = node.GetComponent <FunctionCallBase>().functionName; if (BaseControllerFunctions().ContainsKey(funcName)) { // TODO: passing a copy of symbolTable here might consume too much memory. Make static? functions[funcName].DynamicInvoke(node.GetComponent <FunctionCallBase>().GetRawParameters(symbolTable)); Logger.Log($"Found base function {funcName}"); return(new ExecutionStatus { success = true, handover = false }); } Logger.Log($"Couldn't find base function {funcName}"); break; case NodeType.LogicalBlock: case NodeType.WhileLoop: case NodeType.ElseBlock: // Make sure all nodes in the block body have their ownerLoop assigned node.GetComponent <LogicalBlock>().PropagateOwnership(); if (DistanceCheck()) { GameObject.Find("OutputRenderer").transform.Find("Canvas").GetComponentInChildren <Text>().text = ((CodeBlock)currentNode).SerializeBlockHeader(); } //new WaitForSeconds((float)tickTime bool evaluatedResult = false; // ElseBlocks should activate when its associated LogicalBlocks evaluate as false. if (node.GetComponent <ElseBlock>()) { if (node.PrevNodeObject.GetComponent <LogicalBlock>() && !node.PrevNodeObject.GetComponent <ElseBlock>() && !node.PrevNodeObject.GetComponent <WhileLoop>()) { evaluatedResult = !node.PrevNodeObject.GetComponent <LogicalBlock>().evaluatedResult; } } else { evaluatedResult = node.GetComponent <LogicalBlock>().condition.Evaluate(ref symbolTable); } node.GetComponent <LogicalBlock>().evaluatedResult = evaluatedResult; if (evaluatedResult && ((!node.GetComponent <WhileLoop>()) || (node.GetComponent <WhileLoop>() && !node.GetComponent <WhileLoop>().breakNow))) { NodeBase nodeToFollow = (NodeBase)(node.GetComponent <LogicalBlock>().firstBodyNode); if (nodeToFollow != null) { specialNextNode = nodeToFollow; } else { specialNextNode = (NodeBase)currentNode.nextNode; } //return ExecuteNode(currentNode); timeSinceTick = -tickTime; return(new ExecutionStatus { success = true, handover = false }); } break; case NodeType.AllocateArray: if (node.GetComponent <AllocateArray>()) { int count = -1; // Check if entered size was a valid >= 0 integer. // TODO: unexpected behaviour when allocating with size == 0 Logger.Log($"Allocating array with count {(string)node.GetComponent<AllocateArray>().GetRawParameters(symbolTable)[0]}"); if (int.TryParse((string)node.GetComponent <AllocateArray>().GetRawParameters(symbolTable)[0], out count)) { string arrName = node.GetComponent <AllocateArray>().parameters[1].Value; if (string.IsNullOrWhiteSpace(arrName)) { // TODO: error too? return(new ExecutionStatus { success = false, handover = false }); } for (int i = 0; i < count; i++) { Logger.Log($"Adding array element \"{arrName}[{i}]\""); symbolTable.Add($"{arrName}[{i}]", new FunctionParameter { Value = "None" }); } // Only initialise elements in the symbol table if size was provided as a literal if (int.TryParse(node.GetComponent <AllocateArray>().parameters[0].Value, out count)) { for (int i = 2; i < 2 + count; i++) { FunctionParameter listElement = node.GetComponent <AllocateArray>().parameters[i]; SetSymbol(new FunctionParameter { Value = listElement.Name }, new FunctionParameter { Value = string.IsNullOrWhiteSpace(listElement.Value) ? "None" : listElement.Value }); } } return(new ExecutionStatus { success = true, handover = false }); } } break; case NodeType.Continue: if (node.GetComponent <Continue>()) { // Find the while loop LogicalBlock owner = node.ownerLoop; while (owner != null) { WhileLoop loop = owner.GetComponent <WhileLoop>(); if (loop != null) { currentNode = loop; return(ExecuteNode(currentNode)); } else { owner = owner.ownerLoop; } } if (owner == null) { return(new ExecutionStatus { success = false, handover = false }); } } break; case NodeType.Break: if (node.GetComponent <Break>()) { // Find the while loop LogicalBlock owner = node.ownerLoop; while (owner != null) { WhileLoop loop = owner.GetComponent <WhileLoop>(); if (loop != null) { loop.breakNow = true; currentNode = loop; return(ExecuteNode(currentNode)); } else { owner = owner.ownerLoop; } } if (owner == null) { return(new ExecutionStatus { success = false, handover = false }); } } break; } return(new ExecutionStatus { success = true, handover = true }); }
protected abstract void TranslateWhileLoop(List <string> output, WhileLoop whileLoop);
private Stmt ParseStmt() { Stmt resultado; if (this.indice == this.tokens.Count) { throw new System.Exception("se esperaban sentencias, se llego al final del archivo"); } // <stmt> := print <expr> // <expr> := <string> // | <int> // | <arith_expr> // | <ident> if (this.tokens[this.indice].Equals("print")) { this.indice++; Print print = new Print(); print.Expr = this.ParseExpr(); resultado = print; } else if (this.tokens[this.indice].Equals("var")) { this.indice++; DeclareVar declareVar = new DeclareVar(); if (this.indice < this.tokens.Count && this.tokens[this.indice] is string) { declareVar.Ident = (string)this.tokens[this.indice]; } else { throw new System.Exception("Se esperaba nombre de variable despues de 'var'"); } this.indice++; if (this.indice == this.tokens.Count || this.tokens[this.indice] != Scanner.Igual) { throw new System.Exception("se esperaba = despues de 'var ident'"); } this.indice++; declareVar.Expr = this.ParseExpr(); resultado = declareVar; } else if (this.tokens[this.indice].Equals("read_int")) { this.indice++; ReadInt readInt = new ReadInt(); if (this.indice < this.tokens.Count && this.tokens[this.indice] is string) { readInt.Ident = (string)this.tokens[this.indice++]; resultado = readInt; } else { throw new System.Exception("Se esperaba el nombre de la variable 'read_int'"); } } //******************* else if (this.tokens[this.indice].Equals("if")) { this.indice++; mcIf mcif = new mcIf(); Expr temp = ParseExpr(); if (this.tokens[this.indice] == Scanner.Eq || this.tokens[this.indice] == Scanner.Neq || this.tokens[this.indice] == Scanner.Gt || this.tokens[this.indice] == Scanner.Gte || this.tokens[this.indice] == Scanner.Lt || this.tokens[this.indice] == Scanner.Lte) { CompExpr compExpr = new CompExpr(); compExpr.Left = temp; object op = this.tokens[this.indice++]; if (op == Scanner.Eq) compExpr.Op = CompOp.Eq; else if (op == Scanner.Neq) compExpr.Op = CompOp.Neq; else if (op == Scanner.Gt) compExpr.Op = CompOp.Gt; else if (op == Scanner.Gte) compExpr.Op = CompOp.Gte; else if (op == Scanner.Lt) compExpr.Op = CompOp.Lt; else if (op == Scanner.Lte) compExpr.Op = CompOp.Lte; compExpr.Rigth = ParseExpr(); temp = compExpr; } mcif.compExpr = temp; if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("then")) { throw new System.Exception("Se esperaba el identificador 'then' despues de 'if'"); } this.indice++; mcif.Then = ParseStmt(); if (this.tokens[this.indice].Equals("else")) { this.indice++; mcif.Else = ParseStmt(); } resultado = mcif; if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("end")) { throw new System.Exception("Sentencia if inconclusa"); } this.indice++; } else if (this.tokens[this.indice].Equals("while")) { this.indice++; WhileLoop whileLoop = new WhileLoop(); Expr temp = ParseExpr(); if (this.tokens[this.indice] == Scanner.Eq || this.tokens[this.indice] == Scanner.Neq || this.tokens[this.indice] == Scanner.Gt || this.tokens[this.indice] == Scanner.Gte || this.tokens[this.indice] == Scanner.Lt || this.tokens[this.indice] == Scanner.Lte) { CompExpr compExpr = new CompExpr(); compExpr.Left = temp; object op = this.tokens[this.indice++]; if (op == Scanner.Eq) compExpr.Op = CompOp.Eq; else if (op == Scanner.Neq) compExpr.Op = CompOp.Neq; else if (op == Scanner.Gt) compExpr.Op = CompOp.Gt; else if (op == Scanner.Gte) compExpr.Op = CompOp.Gte; else if (op == Scanner.Lt) compExpr.Op = CompOp.Lt; else if (op == Scanner.Lte) compExpr.Op = CompOp.Lte; compExpr.Rigth = ParseExpr(); temp = compExpr; } whileLoop.Cond = temp; if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("do")) { throw new System.Exception("Se esperaba el identificador 'do' despues de 'while'"); } this.indice++; whileLoop.Body = ParseStmt(); resultado = whileLoop; if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("end")) { throw new System.Exception("sentencia while inconclusa"); } this.indice++; } //******************* else if (this.tokens[this.indice].Equals("for")) { this.indice++; ForLoop forLoop = new ForLoop(); if (this.indice < this.tokens.Count && this.tokens[this.indice] is string) { forLoop.Ident = (string)this.tokens[this.indice]; } else { throw new System.Exception("se esperaba un indentificador despues de 'for'"); } this.indice++; if (this.indice == this.tokens.Count || this.tokens[this.indice] != Scanner.Igual) { throw new System.Exception("no se encontro en la sentencia for '='"); } this.indice++; forLoop.From = this.ParseExpr(); if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("to")) { throw new System.Exception("se epsaraba 'to' despues de for"); } this.indice++; forLoop.To = this.ParseExpr(); if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("do")) { throw new System.Exception("se esperaba 'do' despues de la expresion en el ciclo for"); } this.indice++; forLoop.Body = this.ParseStmt(); resultado = forLoop; if (this.indice == this.tokens.Count || !this.tokens[this.indice].Equals("end")) { throw new System.Exception("setencia for inconclusa"); } this.indice++; } else if (this.tokens[this.indice] is string) { // assignment Assign assign = new Assign(); assign.Ident = (string)this.tokens[this.indice++]; if (this.indice == this.tokens.Count || this.tokens[this.indice] != Scanner.Igual) { throw new System.Exception("se esperaba '='"); } this.indice++; assign.Expr = this.ParseExpr(); resultado = assign; } else { throw new System.Exception("Error en el token " + this.indice + ": " + this.tokens[this.indice]); } if (this.indice < this.tokens.Count && this.tokens[this.indice] == Scanner.PyC) { this.indice++; if (this.indice < this.tokens.Count && !this.tokens[this.indice].Equals("end") && !this.tokens[this.indice].Equals("else")) { Sequence sequence = new Sequence(); sequence.First = resultado; sequence.Second = this.ParseStmt(); resultado = sequence; } } return resultado; }