From 84e46f8bd087de34595d9ed6ede507c9ee2713ef Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Mon, 3 Feb 2025 11:42:18 +0530 Subject: [PATCH 01/53] add assert statement, add verification for assignment and assert statements --- ChironCore/ChironAST/builder.py | 3 + ChironCore/chiron.py | 17 + ChironCore/example/assignmentBMC.tl | 6 + ChironCore/interpreter.py | 11 + ChironCore/smtConverter.py | 86 +++++ ChironCore/turtparse/tlang.g4 | 5 + ChironCore/turtparse/tlang.interp | 7 +- ChironCore/turtparse/tlang.tokens | 67 ++-- ChironCore/turtparse/tlangLexer.interp | 8 +- ChironCore/turtparse/tlangLexer.py | 226 ++++++------ ChironCore/turtparse/tlangLexer.tokens | 67 ++-- ChironCore/turtparse/tlangParser.py | 478 +++++++++++++++---------- ChironCore/turtparse/tlangVisitor.py | 5 + 13 files changed, 615 insertions(+), 371 deletions(-) create mode 100644 ChironCore/example/assignmentBMC.tl create mode 100644 ChironCore/smtConverter.py diff --git a/ChironCore/ChironAST/builder.py b/ChironCore/ChironAST/builder.py index b38265e..95ad1a2 100644 --- a/ChironCore/ChironAST/builder.py +++ b/ChironCore/ChironAST/builder.py @@ -172,3 +172,6 @@ def visitMoveCommand(self, ctx:tlangParser.MoveCommandContext): def visitPenCommand(self, ctx:tlangParser.PenCommandContext): return [(ChironAST.PenCommand(ctx.getText()), 1)] + + def visitAssertionCommand(self, ctx:tlangParser.AssertionCommandContext): + return [(ChironAST.AssertCommand(self.visit(ctx.condition())), 1)] diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 2eca801..1c29ff2 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -21,6 +21,7 @@ from fuzzer import * import sExecution as se import cfg.cfgBuilder as cfgB +import smtConverter import submissionDFA as DFASub import submissionAI as AISub from sbflSubmission import computeRanks @@ -196,6 +197,13 @@ def stopTurtle(): type=bool, ) + cmdparser.add_argument( + "-bmc", + "--bmc", + action="store_true", + help="Run Bounded Model Checking on a Chiron Program.", + ) + args = cmdparser.parse_args() ir = "" @@ -392,3 +400,12 @@ def stopTurtle(): writer = csv.writer(file) writer.writerows(spectrum) print("DONE..") + + if args.bmc: + print("Bounded Model Checking..") + print("Converting program to SMT-LIB format..") + smt = smtConverter.SMTConverter(ir) + smt.convert() + smt.solve() + + print("DONE..") diff --git a/ChironCore/example/assignmentBMC.tl b/ChironCore/example/assignmentBMC.tl new file mode 100644 index 0000000..fa1d6a7 --- /dev/null +++ b/ChironCore/example/assignmentBMC.tl @@ -0,0 +1,6 @@ +// inputs: :x, :y, :z + +:t = :x + 2*:y + + +assert (:x + 100 < :y) && (:x + 200 > :y) && !(:x >= 0) && (:x * :y < -:x) && (:t > 0) \ No newline at end of file diff --git a/ChironCore/interpreter.py b/ChironCore/interpreter.py index bb30bcb..f2bd6a6 100644 --- a/ChironCore/interpreter.py +++ b/ChironCore/interpreter.py @@ -107,6 +107,8 @@ def interpret(self): ntgt = self.handleGotoCommand(stmt, tgt) elif isinstance(stmt, ChironAST.NoOpCommand): ntgt = self.handleNoOpCommand(stmt, tgt) + elif isinstance(stmt, ChironAST.AssertCommand): + ntgt = self.handleAssertCommand(stmt, tgt) else: raise NotImplementedError("Unknown instruction: %s, %s."%(type(stmt), stmt)) @@ -164,3 +166,12 @@ def handleGotoCommand(self, stmt, tgt): ycor = addContext(stmt.ycor) exec("self.trtl.goto(%s, %s)" % (xcor, ycor)) return 1 + + def handleAssertCommand(self, stmt, tgt): + print(" AssertCommand") + print(" Asserting: ", stmt.cond) + exec("self.cond_eval = %s" % (addContext(stmt.cond))) + if not self.cond_eval: + raise AssertionError("Assertion Failed!") + + return 1 diff --git a/ChironCore/smtConverter.py b/ChironCore/smtConverter.py new file mode 100644 index 0000000..630a220 --- /dev/null +++ b/ChironCore/smtConverter.py @@ -0,0 +1,86 @@ +''' +This file is used to convert the Kachua IR to SMT-LIB format. +''' +import z3 +from ChironAST import ChironAST + +def parseExpression(node): + if isinstance(node, ChironAST.ArithExpr): + if isinstance(node, ChironAST.BinArithOp): + left = parseExpression(node.lexpr) + right = parseExpression(node.rexpr) + if isinstance(node, ChironAST.Sum): + return left.__add__(right) + elif isinstance(node, ChironAST.Diff): + return left.__sub__(right) + elif isinstance(node, ChironAST.Mult): + return left.__mul__(right) + elif isinstance(node, ChironAST.Div): + return left.__div__(right) + elif isinstance(node, ChironAST.UnaryArithOp): + if isinstance(node, ChironAST.UMinus): + left = parseExpression(node.expr) + return left.__neg__() + + elif isinstance(node, ChironAST.BoolExpr): + if isinstance(node, ChironAST.BinCondOp): + left = parseExpression(node.lexpr) + right = parseExpression(node.rexpr) + if isinstance(node, ChironAST.AND): + return left.__and__(right) + elif isinstance(node, ChironAST.OR): + return left.__or__(right) + elif isinstance(node, ChironAST.LT): + return left.__lt__(right) + elif isinstance(node, ChironAST.GT): + return left.__gt__(right) + elif isinstance(node, ChironAST.LTE): + return left.__le__(right) + elif isinstance(node, ChironAST.GTE): + return left.__ge__(right) + elif isinstance(node, ChironAST.EQ): + return left.__eq__(right) + elif isinstance(node, ChironAST.NEQ): + return left.__ne__(right) + elif isinstance(node, ChironAST.NOT): + left = parseExpression(node.expr) + return left.__invert__() + elif isinstance(node, ChironAST.BoolTrue): + return z3.BoolVal(True) + elif isinstance(node, ChironAST.BoolFalse): + return z3.BoolVal(False) + + else: + if isinstance(node, ChironAST.Num): + return z3.IntVal(node.val) + elif isinstance(node, ChironAST.Var): + return z3.Int(node.varname) + + +class SMTConverter: + def __init__(self, ir): + self.solver = z3.Solver() + self.ir = ir + + def convert(self): + for instruction, jumpTarget in self.ir: + if isinstance(instruction, ChironAST.AssignmentCommand): + left = z3.Int(instruction.lvar.varname) + right = parseExpression(instruction.rexpr) + self.solver.add(left == right) + + elif isinstance(instruction, ChironAST.AssertCommand): + condition = parseExpression(instruction.cond) + self.solver.add(z3.Not(condition)) + + # TODO: Implement the rest of the commands + + def solve(self): + print("Assertions are:") + print(self.solver.assertions()) + sat = self.solver.check() + if sat == z3.sat: + print("Bug found!") + print(self.solver.model()) + else: + print("No bug found!") \ No newline at end of file diff --git a/ChironCore/turtparse/tlang.g4 b/ChironCore/turtparse/tlang.g4 index ff3a2f6..34adbfc 100644 --- a/ChironCore/turtparse/tlang.g4 +++ b/ChironCore/turtparse/tlang.g4 @@ -17,6 +17,7 @@ instruction : assignment | penCommand | gotoCommand | pauseCommand + | assertionCommand ; conditional : ifConditional | ifElseConditional ; @@ -39,6 +40,8 @@ penCommand : 'penup' | 'pendown' ; pauseCommand : 'pause' ; +assertionCommand : 'assert' condition ; + expression : unaryArithOp expression #unaryExpr | expression multiplicative expression #mulExpr @@ -96,3 +99,5 @@ VAR : ':'[a-zA-Z_] [a-zA-Z0-9]* ; NAME : [a-zA-Z]+ ; Whitespace: [ \t\n\r]+ -> skip; + +Comment: '//' ~[\r\n]* -> skip; diff --git a/ChironCore/turtparse/tlang.interp b/ChironCore/turtparse/tlang.interp index f3cba53..9b42a13 100644 --- a/ChironCore/turtparse/tlang.interp +++ b/ChironCore/turtparse/tlang.interp @@ -17,6 +17,7 @@ null 'penup' 'pendown' 'pause' +'assert' '+' '-' '*' @@ -35,6 +36,7 @@ null null null null +null token symbolic names: null @@ -55,6 +57,7 @@ null null null null +null PLUS MINUS MUL @@ -73,6 +76,7 @@ NUM VAR NAME Whitespace +Comment rule names: start @@ -89,6 +93,7 @@ moveCommand moveOp penCommand pauseCommand +assertionCommand expression multiplicative additive @@ -100,4 +105,4 @@ value atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 37, 175, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 51, 10, 3, 12, 3, 14, 3, 54, 11, 3, 3, 4, 6, 4, 57, 10, 4, 13, 4, 14, 4, 58, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 68, 10, 5, 3, 6, 3, 6, 5, 6, 72, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 5, 16, 125, 10, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 7, 16, 135, 10, 16, 12, 16, 14, 16, 138, 11, 16, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 5, 20, 158, 10, 20, 3, 20, 3, 20, 3, 20, 3, 20, 7, 20, 164, 10, 20, 12, 20, 14, 20, 167, 11, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 2, 4, 30, 38, 24, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 2, 9, 3, 2, 13, 16, 3, 2, 17, 18, 3, 2, 22, 23, 3, 2, 20, 21, 3, 2, 25, 30, 3, 2, 31, 32, 3, 2, 34, 35, 2, 169, 2, 46, 3, 2, 2, 2, 4, 52, 3, 2, 2, 2, 6, 56, 3, 2, 2, 2, 8, 67, 3, 2, 2, 2, 10, 71, 3, 2, 2, 2, 12, 73, 3, 2, 2, 2, 14, 79, 3, 2, 2, 2, 16, 89, 3, 2, 2, 2, 18, 95, 3, 2, 2, 2, 20, 102, 3, 2, 2, 2, 22, 106, 3, 2, 2, 2, 24, 109, 3, 2, 2, 2, 26, 111, 3, 2, 2, 2, 28, 113, 3, 2, 2, 2, 30, 124, 3, 2, 2, 2, 32, 139, 3, 2, 2, 2, 34, 141, 3, 2, 2, 2, 36, 143, 3, 2, 2, 2, 38, 157, 3, 2, 2, 2, 40, 168, 3, 2, 2, 2, 42, 170, 3, 2, 2, 2, 44, 172, 3, 2, 2, 2, 46, 47, 5, 4, 3, 2, 47, 48, 7, 2, 2, 3, 48, 3, 3, 2, 2, 2, 49, 51, 5, 8, 5, 2, 50, 49, 3, 2, 2, 2, 51, 54, 3, 2, 2, 2, 52, 50, 3, 2, 2, 2, 52, 53, 3, 2, 2, 2, 53, 5, 3, 2, 2, 2, 54, 52, 3, 2, 2, 2, 55, 57, 5, 8, 5, 2, 56, 55, 3, 2, 2, 2, 57, 58, 3, 2, 2, 2, 58, 56, 3, 2, 2, 2, 58, 59, 3, 2, 2, 2, 59, 7, 3, 2, 2, 2, 60, 68, 5, 20, 11, 2, 61, 68, 5, 10, 6, 2, 62, 68, 5, 16, 9, 2, 63, 68, 5, 22, 12, 2, 64, 68, 5, 26, 14, 2, 65, 68, 5, 18, 10, 2, 66, 68, 5, 28, 15, 2, 67, 60, 3, 2, 2, 2, 67, 61, 3, 2, 2, 2, 67, 62, 3, 2, 2, 2, 67, 63, 3, 2, 2, 2, 67, 64, 3, 2, 2, 2, 67, 65, 3, 2, 2, 2, 67, 66, 3, 2, 2, 2, 68, 9, 3, 2, 2, 2, 69, 72, 5, 12, 7, 2, 70, 72, 5, 14, 8, 2, 71, 69, 3, 2, 2, 2, 71, 70, 3, 2, 2, 2, 72, 11, 3, 2, 2, 2, 73, 74, 7, 3, 2, 2, 74, 75, 5, 38, 20, 2, 75, 76, 7, 4, 2, 2, 76, 77, 5, 6, 4, 2, 77, 78, 7, 5, 2, 2, 78, 13, 3, 2, 2, 2, 79, 80, 7, 3, 2, 2, 80, 81, 5, 38, 20, 2, 81, 82, 7, 4, 2, 2, 82, 83, 5, 6, 4, 2, 83, 84, 7, 5, 2, 2, 84, 85, 7, 6, 2, 2, 85, 86, 7, 4, 2, 2, 86, 87, 5, 6, 4, 2, 87, 88, 7, 5, 2, 2, 88, 15, 3, 2, 2, 2, 89, 90, 7, 7, 2, 2, 90, 91, 5, 44, 23, 2, 91, 92, 7, 4, 2, 2, 92, 93, 5, 6, 4, 2, 93, 94, 7, 5, 2, 2, 94, 17, 3, 2, 2, 2, 95, 96, 7, 8, 2, 2, 96, 97, 7, 9, 2, 2, 97, 98, 5, 30, 16, 2, 98, 99, 7, 10, 2, 2, 99, 100, 5, 30, 16, 2, 100, 101, 7, 11, 2, 2, 101, 19, 3, 2, 2, 2, 102, 103, 7, 35, 2, 2, 103, 104, 7, 12, 2, 2, 104, 105, 5, 30, 16, 2, 105, 21, 3, 2, 2, 2, 106, 107, 5, 24, 13, 2, 107, 108, 5, 30, 16, 2, 108, 23, 3, 2, 2, 2, 109, 110, 9, 2, 2, 2, 110, 25, 3, 2, 2, 2, 111, 112, 9, 3, 2, 2, 112, 27, 3, 2, 2, 2, 113, 114, 7, 19, 2, 2, 114, 29, 3, 2, 2, 2, 115, 116, 8, 16, 1, 2, 116, 117, 5, 36, 19, 2, 117, 118, 5, 30, 16, 7, 118, 125, 3, 2, 2, 2, 119, 125, 5, 44, 23, 2, 120, 121, 7, 9, 2, 2, 121, 122, 5, 30, 16, 2, 122, 123, 7, 11, 2, 2, 123, 125, 3, 2, 2, 2, 124, 115, 3, 2, 2, 2, 124, 119, 3, 2, 2, 2, 124, 120, 3, 2, 2, 2, 125, 136, 3, 2, 2, 2, 126, 127, 12, 6, 2, 2, 127, 128, 5, 32, 17, 2, 128, 129, 5, 30, 16, 7, 129, 135, 3, 2, 2, 2, 130, 131, 12, 5, 2, 2, 131, 132, 5, 34, 18, 2, 132, 133, 5, 30, 16, 6, 133, 135, 3, 2, 2, 2, 134, 126, 3, 2, 2, 2, 134, 130, 3, 2, 2, 2, 135, 138, 3, 2, 2, 2, 136, 134, 3, 2, 2, 2, 136, 137, 3, 2, 2, 2, 137, 31, 3, 2, 2, 2, 138, 136, 3, 2, 2, 2, 139, 140, 9, 4, 2, 2, 140, 33, 3, 2, 2, 2, 141, 142, 9, 5, 2, 2, 142, 35, 3, 2, 2, 2, 143, 144, 7, 21, 2, 2, 144, 37, 3, 2, 2, 2, 145, 146, 8, 20, 1, 2, 146, 147, 7, 33, 2, 2, 147, 158, 5, 38, 20, 7, 148, 149, 5, 30, 16, 2, 149, 150, 5, 40, 21, 2, 150, 151, 5, 30, 16, 2, 151, 158, 3, 2, 2, 2, 152, 158, 7, 24, 2, 2, 153, 154, 7, 9, 2, 2, 154, 155, 5, 38, 20, 2, 155, 156, 7, 11, 2, 2, 156, 158, 3, 2, 2, 2, 157, 145, 3, 2, 2, 2, 157, 148, 3, 2, 2, 2, 157, 152, 3, 2, 2, 2, 157, 153, 3, 2, 2, 2, 158, 165, 3, 2, 2, 2, 159, 160, 12, 5, 2, 2, 160, 161, 5, 42, 22, 2, 161, 162, 5, 38, 20, 6, 162, 164, 3, 2, 2, 2, 163, 159, 3, 2, 2, 2, 164, 167, 3, 2, 2, 2, 165, 163, 3, 2, 2, 2, 165, 166, 3, 2, 2, 2, 166, 39, 3, 2, 2, 2, 167, 165, 3, 2, 2, 2, 168, 169, 9, 6, 2, 2, 169, 41, 3, 2, 2, 2, 170, 171, 9, 7, 2, 2, 171, 43, 3, 2, 2, 2, 172, 173, 9, 8, 2, 2, 173, 45, 3, 2, 2, 2, 11, 52, 58, 67, 71, 124, 134, 136, 157, 165] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 39, 181, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 53, 10, 3, 12, 3, 14, 3, 56, 11, 3, 3, 4, 6, 4, 59, 10, 4, 13, 4, 14, 4, 60, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 71, 10, 5, 3, 6, 3, 6, 5, 6, 75, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 5, 17, 131, 10, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 141, 10, 17, 12, 17, 14, 17, 144, 11, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 164, 10, 21, 3, 21, 3, 21, 3, 21, 3, 21, 7, 21, 170, 10, 21, 12, 21, 14, 21, 173, 11, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 2, 4, 32, 40, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 2, 9, 3, 2, 13, 16, 3, 2, 17, 18, 3, 2, 23, 24, 3, 2, 21, 22, 3, 2, 26, 31, 3, 2, 32, 33, 3, 2, 35, 36, 2, 175, 2, 48, 3, 2, 2, 2, 4, 54, 3, 2, 2, 2, 6, 58, 3, 2, 2, 2, 8, 70, 3, 2, 2, 2, 10, 74, 3, 2, 2, 2, 12, 76, 3, 2, 2, 2, 14, 82, 3, 2, 2, 2, 16, 92, 3, 2, 2, 2, 18, 98, 3, 2, 2, 2, 20, 105, 3, 2, 2, 2, 22, 109, 3, 2, 2, 2, 24, 112, 3, 2, 2, 2, 26, 114, 3, 2, 2, 2, 28, 116, 3, 2, 2, 2, 30, 118, 3, 2, 2, 2, 32, 130, 3, 2, 2, 2, 34, 145, 3, 2, 2, 2, 36, 147, 3, 2, 2, 2, 38, 149, 3, 2, 2, 2, 40, 163, 3, 2, 2, 2, 42, 174, 3, 2, 2, 2, 44, 176, 3, 2, 2, 2, 46, 178, 3, 2, 2, 2, 48, 49, 5, 4, 3, 2, 49, 50, 7, 2, 2, 3, 50, 3, 3, 2, 2, 2, 51, 53, 5, 8, 5, 2, 52, 51, 3, 2, 2, 2, 53, 56, 3, 2, 2, 2, 54, 52, 3, 2, 2, 2, 54, 55, 3, 2, 2, 2, 55, 5, 3, 2, 2, 2, 56, 54, 3, 2, 2, 2, 57, 59, 5, 8, 5, 2, 58, 57, 3, 2, 2, 2, 59, 60, 3, 2, 2, 2, 60, 58, 3, 2, 2, 2, 60, 61, 3, 2, 2, 2, 61, 7, 3, 2, 2, 2, 62, 71, 5, 20, 11, 2, 63, 71, 5, 10, 6, 2, 64, 71, 5, 16, 9, 2, 65, 71, 5, 22, 12, 2, 66, 71, 5, 26, 14, 2, 67, 71, 5, 18, 10, 2, 68, 71, 5, 28, 15, 2, 69, 71, 5, 30, 16, 2, 70, 62, 3, 2, 2, 2, 70, 63, 3, 2, 2, 2, 70, 64, 3, 2, 2, 2, 70, 65, 3, 2, 2, 2, 70, 66, 3, 2, 2, 2, 70, 67, 3, 2, 2, 2, 70, 68, 3, 2, 2, 2, 70, 69, 3, 2, 2, 2, 71, 9, 3, 2, 2, 2, 72, 75, 5, 12, 7, 2, 73, 75, 5, 14, 8, 2, 74, 72, 3, 2, 2, 2, 74, 73, 3, 2, 2, 2, 75, 11, 3, 2, 2, 2, 76, 77, 7, 3, 2, 2, 77, 78, 5, 40, 21, 2, 78, 79, 7, 4, 2, 2, 79, 80, 5, 6, 4, 2, 80, 81, 7, 5, 2, 2, 81, 13, 3, 2, 2, 2, 82, 83, 7, 3, 2, 2, 83, 84, 5, 40, 21, 2, 84, 85, 7, 4, 2, 2, 85, 86, 5, 6, 4, 2, 86, 87, 7, 5, 2, 2, 87, 88, 7, 6, 2, 2, 88, 89, 7, 4, 2, 2, 89, 90, 5, 6, 4, 2, 90, 91, 7, 5, 2, 2, 91, 15, 3, 2, 2, 2, 92, 93, 7, 7, 2, 2, 93, 94, 5, 46, 24, 2, 94, 95, 7, 4, 2, 2, 95, 96, 5, 6, 4, 2, 96, 97, 7, 5, 2, 2, 97, 17, 3, 2, 2, 2, 98, 99, 7, 8, 2, 2, 99, 100, 7, 9, 2, 2, 100, 101, 5, 32, 17, 2, 101, 102, 7, 10, 2, 2, 102, 103, 5, 32, 17, 2, 103, 104, 7, 11, 2, 2, 104, 19, 3, 2, 2, 2, 105, 106, 7, 36, 2, 2, 106, 107, 7, 12, 2, 2, 107, 108, 5, 32, 17, 2, 108, 21, 3, 2, 2, 2, 109, 110, 5, 24, 13, 2, 110, 111, 5, 32, 17, 2, 111, 23, 3, 2, 2, 2, 112, 113, 9, 2, 2, 2, 113, 25, 3, 2, 2, 2, 114, 115, 9, 3, 2, 2, 115, 27, 3, 2, 2, 2, 116, 117, 7, 19, 2, 2, 117, 29, 3, 2, 2, 2, 118, 119, 7, 20, 2, 2, 119, 120, 5, 40, 21, 2, 120, 31, 3, 2, 2, 2, 121, 122, 8, 17, 1, 2, 122, 123, 5, 38, 20, 2, 123, 124, 5, 32, 17, 7, 124, 131, 3, 2, 2, 2, 125, 131, 5, 46, 24, 2, 126, 127, 7, 9, 2, 2, 127, 128, 5, 32, 17, 2, 128, 129, 7, 11, 2, 2, 129, 131, 3, 2, 2, 2, 130, 121, 3, 2, 2, 2, 130, 125, 3, 2, 2, 2, 130, 126, 3, 2, 2, 2, 131, 142, 3, 2, 2, 2, 132, 133, 12, 6, 2, 2, 133, 134, 5, 34, 18, 2, 134, 135, 5, 32, 17, 7, 135, 141, 3, 2, 2, 2, 136, 137, 12, 5, 2, 2, 137, 138, 5, 36, 19, 2, 138, 139, 5, 32, 17, 6, 139, 141, 3, 2, 2, 2, 140, 132, 3, 2, 2, 2, 140, 136, 3, 2, 2, 2, 141, 144, 3, 2, 2, 2, 142, 140, 3, 2, 2, 2, 142, 143, 3, 2, 2, 2, 143, 33, 3, 2, 2, 2, 144, 142, 3, 2, 2, 2, 145, 146, 9, 4, 2, 2, 146, 35, 3, 2, 2, 2, 147, 148, 9, 5, 2, 2, 148, 37, 3, 2, 2, 2, 149, 150, 7, 22, 2, 2, 150, 39, 3, 2, 2, 2, 151, 152, 8, 21, 1, 2, 152, 153, 7, 34, 2, 2, 153, 164, 5, 40, 21, 7, 154, 155, 5, 32, 17, 2, 155, 156, 5, 42, 22, 2, 156, 157, 5, 32, 17, 2, 157, 164, 3, 2, 2, 2, 158, 164, 7, 25, 2, 2, 159, 160, 7, 9, 2, 2, 160, 161, 5, 40, 21, 2, 161, 162, 7, 11, 2, 2, 162, 164, 3, 2, 2, 2, 163, 151, 3, 2, 2, 2, 163, 154, 3, 2, 2, 2, 163, 158, 3, 2, 2, 2, 163, 159, 3, 2, 2, 2, 164, 171, 3, 2, 2, 2, 165, 166, 12, 5, 2, 2, 166, 167, 5, 44, 23, 2, 167, 168, 5, 40, 21, 6, 168, 170, 3, 2, 2, 2, 169, 165, 3, 2, 2, 2, 170, 173, 3, 2, 2, 2, 171, 169, 3, 2, 2, 2, 171, 172, 3, 2, 2, 2, 172, 41, 3, 2, 2, 2, 173, 171, 3, 2, 2, 2, 174, 175, 9, 6, 2, 2, 175, 43, 3, 2, 2, 2, 176, 177, 9, 7, 2, 2, 177, 45, 3, 2, 2, 2, 178, 179, 9, 8, 2, 2, 179, 47, 3, 2, 2, 2, 11, 54, 60, 70, 74, 130, 140, 142, 163, 171] \ No newline at end of file diff --git a/ChironCore/turtparse/tlang.tokens b/ChironCore/turtparse/tlang.tokens index 78f9526..b0a2b1d 100644 --- a/ChironCore/turtparse/tlang.tokens +++ b/ChironCore/turtparse/tlang.tokens @@ -15,24 +15,26 @@ T__13=14 T__14=15 T__15=16 T__16=17 -PLUS=18 -MINUS=19 -MUL=20 -DIV=21 -PENCOND=22 -LT=23 -GT=24 -EQ=25 -NEQ=26 -LTE=27 -GTE=28 -AND=29 -OR=30 -NOT=31 -NUM=32 -VAR=33 -NAME=34 -Whitespace=35 +T__17=18 +PLUS=19 +MINUS=20 +MUL=21 +DIV=22 +PENCOND=23 +LT=24 +GT=25 +EQ=26 +NEQ=27 +LTE=28 +GTE=29 +AND=30 +OR=31 +NOT=32 +NUM=33 +VAR=34 +NAME=35 +Whitespace=36 +Comment=37 'if'=1 '['=2 ']'=3 @@ -50,17 +52,18 @@ Whitespace=35 'penup'=15 'pendown'=16 'pause'=17 -'+'=18 -'-'=19 -'*'=20 -'/'=21 -'pendown?'=22 -'<'=23 -'>'=24 -'=='=25 -'!='=26 -'<='=27 -'>='=28 -'&&'=29 -'||'=30 -'!'=31 +'assert'=18 +'+'=19 +'-'=20 +'*'=21 +'/'=22 +'pendown?'=23 +'<'=24 +'>'=25 +'=='=26 +'!='=27 +'<='=28 +'>='=29 +'&&'=30 +'||'=31 +'!'=32 diff --git a/ChironCore/turtparse/tlangLexer.interp b/ChironCore/turtparse/tlangLexer.interp index 106eae4..7d6f824 100644 --- a/ChironCore/turtparse/tlangLexer.interp +++ b/ChironCore/turtparse/tlangLexer.interp @@ -17,6 +17,7 @@ null 'penup' 'pendown' 'pause' +'assert' '+' '-' '*' @@ -35,6 +36,7 @@ null null null null +null token symbolic names: null @@ -55,6 +57,7 @@ null null null null +null PLUS MINUS MUL @@ -73,6 +76,7 @@ NUM VAR NAME Whitespace +Comment rule names: T__0 @@ -92,6 +96,7 @@ T__13 T__14 T__15 T__16 +T__17 PLUS MINUS MUL @@ -110,6 +115,7 @@ NUM VAR NAME Whitespace +Comment channel names: DEFAULT_TOKEN_CHANNEL @@ -119,4 +125,4 @@ mode names: DEFAULT_MODE atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 37, 219, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 6, 33, 196, 10, 33, 13, 33, 14, 33, 197, 3, 34, 3, 34, 3, 34, 7, 34, 203, 10, 34, 12, 34, 14, 34, 206, 11, 34, 3, 35, 6, 35, 209, 10, 35, 13, 35, 14, 35, 210, 3, 36, 6, 36, 214, 10, 36, 13, 36, 14, 36, 215, 3, 36, 3, 36, 2, 2, 37, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 3, 2, 7, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 2, 222, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 3, 73, 3, 2, 2, 2, 5, 76, 3, 2, 2, 2, 7, 78, 3, 2, 2, 2, 9, 80, 3, 2, 2, 2, 11, 85, 3, 2, 2, 2, 13, 92, 3, 2, 2, 2, 15, 97, 3, 2, 2, 2, 17, 99, 3, 2, 2, 2, 19, 101, 3, 2, 2, 2, 21, 103, 3, 2, 2, 2, 23, 105, 3, 2, 2, 2, 25, 113, 3, 2, 2, 2, 27, 122, 3, 2, 2, 2, 29, 127, 3, 2, 2, 2, 31, 133, 3, 2, 2, 2, 33, 139, 3, 2, 2, 2, 35, 147, 3, 2, 2, 2, 37, 153, 3, 2, 2, 2, 39, 155, 3, 2, 2, 2, 41, 157, 3, 2, 2, 2, 43, 159, 3, 2, 2, 2, 45, 161, 3, 2, 2, 2, 47, 170, 3, 2, 2, 2, 49, 172, 3, 2, 2, 2, 51, 174, 3, 2, 2, 2, 53, 177, 3, 2, 2, 2, 55, 180, 3, 2, 2, 2, 57, 183, 3, 2, 2, 2, 59, 186, 3, 2, 2, 2, 61, 189, 3, 2, 2, 2, 63, 192, 3, 2, 2, 2, 65, 195, 3, 2, 2, 2, 67, 199, 3, 2, 2, 2, 69, 208, 3, 2, 2, 2, 71, 213, 3, 2, 2, 2, 73, 74, 7, 107, 2, 2, 74, 75, 7, 104, 2, 2, 75, 4, 3, 2, 2, 2, 76, 77, 7, 93, 2, 2, 77, 6, 3, 2, 2, 2, 78, 79, 7, 95, 2, 2, 79, 8, 3, 2, 2, 2, 80, 81, 7, 103, 2, 2, 81, 82, 7, 110, 2, 2, 82, 83, 7, 117, 2, 2, 83, 84, 7, 103, 2, 2, 84, 10, 3, 2, 2, 2, 85, 86, 7, 116, 2, 2, 86, 87, 7, 103, 2, 2, 87, 88, 7, 114, 2, 2, 88, 89, 7, 103, 2, 2, 89, 90, 7, 99, 2, 2, 90, 91, 7, 118, 2, 2, 91, 12, 3, 2, 2, 2, 92, 93, 7, 105, 2, 2, 93, 94, 7, 113, 2, 2, 94, 95, 7, 118, 2, 2, 95, 96, 7, 113, 2, 2, 96, 14, 3, 2, 2, 2, 97, 98, 7, 42, 2, 2, 98, 16, 3, 2, 2, 2, 99, 100, 7, 46, 2, 2, 100, 18, 3, 2, 2, 2, 101, 102, 7, 43, 2, 2, 102, 20, 3, 2, 2, 2, 103, 104, 7, 63, 2, 2, 104, 22, 3, 2, 2, 2, 105, 106, 7, 104, 2, 2, 106, 107, 7, 113, 2, 2, 107, 108, 7, 116, 2, 2, 108, 109, 7, 121, 2, 2, 109, 110, 7, 99, 2, 2, 110, 111, 7, 116, 2, 2, 111, 112, 7, 102, 2, 2, 112, 24, 3, 2, 2, 2, 113, 114, 7, 100, 2, 2, 114, 115, 7, 99, 2, 2, 115, 116, 7, 101, 2, 2, 116, 117, 7, 109, 2, 2, 117, 118, 7, 121, 2, 2, 118, 119, 7, 99, 2, 2, 119, 120, 7, 116, 2, 2, 120, 121, 7, 102, 2, 2, 121, 26, 3, 2, 2, 2, 122, 123, 7, 110, 2, 2, 123, 124, 7, 103, 2, 2, 124, 125, 7, 104, 2, 2, 125, 126, 7, 118, 2, 2, 126, 28, 3, 2, 2, 2, 127, 128, 7, 116, 2, 2, 128, 129, 7, 107, 2, 2, 129, 130, 7, 105, 2, 2, 130, 131, 7, 106, 2, 2, 131, 132, 7, 118, 2, 2, 132, 30, 3, 2, 2, 2, 133, 134, 7, 114, 2, 2, 134, 135, 7, 103, 2, 2, 135, 136, 7, 112, 2, 2, 136, 137, 7, 119, 2, 2, 137, 138, 7, 114, 2, 2, 138, 32, 3, 2, 2, 2, 139, 140, 7, 114, 2, 2, 140, 141, 7, 103, 2, 2, 141, 142, 7, 112, 2, 2, 142, 143, 7, 102, 2, 2, 143, 144, 7, 113, 2, 2, 144, 145, 7, 121, 2, 2, 145, 146, 7, 112, 2, 2, 146, 34, 3, 2, 2, 2, 147, 148, 7, 114, 2, 2, 148, 149, 7, 99, 2, 2, 149, 150, 7, 119, 2, 2, 150, 151, 7, 117, 2, 2, 151, 152, 7, 103, 2, 2, 152, 36, 3, 2, 2, 2, 153, 154, 7, 45, 2, 2, 154, 38, 3, 2, 2, 2, 155, 156, 7, 47, 2, 2, 156, 40, 3, 2, 2, 2, 157, 158, 7, 44, 2, 2, 158, 42, 3, 2, 2, 2, 159, 160, 7, 49, 2, 2, 160, 44, 3, 2, 2, 2, 161, 162, 7, 114, 2, 2, 162, 163, 7, 103, 2, 2, 163, 164, 7, 112, 2, 2, 164, 165, 7, 102, 2, 2, 165, 166, 7, 113, 2, 2, 166, 167, 7, 121, 2, 2, 167, 168, 7, 112, 2, 2, 168, 169, 7, 65, 2, 2, 169, 46, 3, 2, 2, 2, 170, 171, 7, 62, 2, 2, 171, 48, 3, 2, 2, 2, 172, 173, 7, 64, 2, 2, 173, 50, 3, 2, 2, 2, 174, 175, 7, 63, 2, 2, 175, 176, 7, 63, 2, 2, 176, 52, 3, 2, 2, 2, 177, 178, 7, 35, 2, 2, 178, 179, 7, 63, 2, 2, 179, 54, 3, 2, 2, 2, 180, 181, 7, 62, 2, 2, 181, 182, 7, 63, 2, 2, 182, 56, 3, 2, 2, 2, 183, 184, 7, 64, 2, 2, 184, 185, 7, 63, 2, 2, 185, 58, 3, 2, 2, 2, 186, 187, 7, 40, 2, 2, 187, 188, 7, 40, 2, 2, 188, 60, 3, 2, 2, 2, 189, 190, 7, 126, 2, 2, 190, 191, 7, 126, 2, 2, 191, 62, 3, 2, 2, 2, 192, 193, 7, 35, 2, 2, 193, 64, 3, 2, 2, 2, 194, 196, 9, 2, 2, 2, 195, 194, 3, 2, 2, 2, 196, 197, 3, 2, 2, 2, 197, 195, 3, 2, 2, 2, 197, 198, 3, 2, 2, 2, 198, 66, 3, 2, 2, 2, 199, 200, 7, 60, 2, 2, 200, 204, 9, 3, 2, 2, 201, 203, 9, 4, 2, 2, 202, 201, 3, 2, 2, 2, 203, 206, 3, 2, 2, 2, 204, 202, 3, 2, 2, 2, 204, 205, 3, 2, 2, 2, 205, 68, 3, 2, 2, 2, 206, 204, 3, 2, 2, 2, 207, 209, 9, 5, 2, 2, 208, 207, 3, 2, 2, 2, 209, 210, 3, 2, 2, 2, 210, 208, 3, 2, 2, 2, 210, 211, 3, 2, 2, 2, 211, 70, 3, 2, 2, 2, 212, 214, 9, 6, 2, 2, 213, 212, 3, 2, 2, 2, 214, 215, 3, 2, 2, 2, 215, 213, 3, 2, 2, 2, 215, 216, 3, 2, 2, 2, 216, 217, 3, 2, 2, 2, 217, 218, 8, 36, 2, 2, 218, 72, 3, 2, 2, 2, 7, 2, 197, 204, 210, 215, 3, 8, 2, 2] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 39, 241, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 6, 34, 207, 10, 34, 13, 34, 14, 34, 208, 3, 35, 3, 35, 3, 35, 7, 35, 214, 10, 35, 12, 35, 14, 35, 217, 11, 35, 3, 36, 6, 36, 220, 10, 36, 13, 36, 14, 36, 221, 3, 37, 6, 37, 225, 10, 37, 13, 37, 14, 37, 226, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38, 7, 38, 235, 10, 38, 12, 38, 14, 38, 238, 11, 38, 3, 38, 3, 38, 2, 2, 39, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 3, 2, 8, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 245, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 3, 77, 3, 2, 2, 2, 5, 80, 3, 2, 2, 2, 7, 82, 3, 2, 2, 2, 9, 84, 3, 2, 2, 2, 11, 89, 3, 2, 2, 2, 13, 96, 3, 2, 2, 2, 15, 101, 3, 2, 2, 2, 17, 103, 3, 2, 2, 2, 19, 105, 3, 2, 2, 2, 21, 107, 3, 2, 2, 2, 23, 109, 3, 2, 2, 2, 25, 117, 3, 2, 2, 2, 27, 126, 3, 2, 2, 2, 29, 131, 3, 2, 2, 2, 31, 137, 3, 2, 2, 2, 33, 143, 3, 2, 2, 2, 35, 151, 3, 2, 2, 2, 37, 157, 3, 2, 2, 2, 39, 164, 3, 2, 2, 2, 41, 166, 3, 2, 2, 2, 43, 168, 3, 2, 2, 2, 45, 170, 3, 2, 2, 2, 47, 172, 3, 2, 2, 2, 49, 181, 3, 2, 2, 2, 51, 183, 3, 2, 2, 2, 53, 185, 3, 2, 2, 2, 55, 188, 3, 2, 2, 2, 57, 191, 3, 2, 2, 2, 59, 194, 3, 2, 2, 2, 61, 197, 3, 2, 2, 2, 63, 200, 3, 2, 2, 2, 65, 203, 3, 2, 2, 2, 67, 206, 3, 2, 2, 2, 69, 210, 3, 2, 2, 2, 71, 219, 3, 2, 2, 2, 73, 224, 3, 2, 2, 2, 75, 230, 3, 2, 2, 2, 77, 78, 7, 107, 2, 2, 78, 79, 7, 104, 2, 2, 79, 4, 3, 2, 2, 2, 80, 81, 7, 93, 2, 2, 81, 6, 3, 2, 2, 2, 82, 83, 7, 95, 2, 2, 83, 8, 3, 2, 2, 2, 84, 85, 7, 103, 2, 2, 85, 86, 7, 110, 2, 2, 86, 87, 7, 117, 2, 2, 87, 88, 7, 103, 2, 2, 88, 10, 3, 2, 2, 2, 89, 90, 7, 116, 2, 2, 90, 91, 7, 103, 2, 2, 91, 92, 7, 114, 2, 2, 92, 93, 7, 103, 2, 2, 93, 94, 7, 99, 2, 2, 94, 95, 7, 118, 2, 2, 95, 12, 3, 2, 2, 2, 96, 97, 7, 105, 2, 2, 97, 98, 7, 113, 2, 2, 98, 99, 7, 118, 2, 2, 99, 100, 7, 113, 2, 2, 100, 14, 3, 2, 2, 2, 101, 102, 7, 42, 2, 2, 102, 16, 3, 2, 2, 2, 103, 104, 7, 46, 2, 2, 104, 18, 3, 2, 2, 2, 105, 106, 7, 43, 2, 2, 106, 20, 3, 2, 2, 2, 107, 108, 7, 63, 2, 2, 108, 22, 3, 2, 2, 2, 109, 110, 7, 104, 2, 2, 110, 111, 7, 113, 2, 2, 111, 112, 7, 116, 2, 2, 112, 113, 7, 121, 2, 2, 113, 114, 7, 99, 2, 2, 114, 115, 7, 116, 2, 2, 115, 116, 7, 102, 2, 2, 116, 24, 3, 2, 2, 2, 117, 118, 7, 100, 2, 2, 118, 119, 7, 99, 2, 2, 119, 120, 7, 101, 2, 2, 120, 121, 7, 109, 2, 2, 121, 122, 7, 121, 2, 2, 122, 123, 7, 99, 2, 2, 123, 124, 7, 116, 2, 2, 124, 125, 7, 102, 2, 2, 125, 26, 3, 2, 2, 2, 126, 127, 7, 110, 2, 2, 127, 128, 7, 103, 2, 2, 128, 129, 7, 104, 2, 2, 129, 130, 7, 118, 2, 2, 130, 28, 3, 2, 2, 2, 131, 132, 7, 116, 2, 2, 132, 133, 7, 107, 2, 2, 133, 134, 7, 105, 2, 2, 134, 135, 7, 106, 2, 2, 135, 136, 7, 118, 2, 2, 136, 30, 3, 2, 2, 2, 137, 138, 7, 114, 2, 2, 138, 139, 7, 103, 2, 2, 139, 140, 7, 112, 2, 2, 140, 141, 7, 119, 2, 2, 141, 142, 7, 114, 2, 2, 142, 32, 3, 2, 2, 2, 143, 144, 7, 114, 2, 2, 144, 145, 7, 103, 2, 2, 145, 146, 7, 112, 2, 2, 146, 147, 7, 102, 2, 2, 147, 148, 7, 113, 2, 2, 148, 149, 7, 121, 2, 2, 149, 150, 7, 112, 2, 2, 150, 34, 3, 2, 2, 2, 151, 152, 7, 114, 2, 2, 152, 153, 7, 99, 2, 2, 153, 154, 7, 119, 2, 2, 154, 155, 7, 117, 2, 2, 155, 156, 7, 103, 2, 2, 156, 36, 3, 2, 2, 2, 157, 158, 7, 99, 2, 2, 158, 159, 7, 117, 2, 2, 159, 160, 7, 117, 2, 2, 160, 161, 7, 103, 2, 2, 161, 162, 7, 116, 2, 2, 162, 163, 7, 118, 2, 2, 163, 38, 3, 2, 2, 2, 164, 165, 7, 45, 2, 2, 165, 40, 3, 2, 2, 2, 166, 167, 7, 47, 2, 2, 167, 42, 3, 2, 2, 2, 168, 169, 7, 44, 2, 2, 169, 44, 3, 2, 2, 2, 170, 171, 7, 49, 2, 2, 171, 46, 3, 2, 2, 2, 172, 173, 7, 114, 2, 2, 173, 174, 7, 103, 2, 2, 174, 175, 7, 112, 2, 2, 175, 176, 7, 102, 2, 2, 176, 177, 7, 113, 2, 2, 177, 178, 7, 121, 2, 2, 178, 179, 7, 112, 2, 2, 179, 180, 7, 65, 2, 2, 180, 48, 3, 2, 2, 2, 181, 182, 7, 62, 2, 2, 182, 50, 3, 2, 2, 2, 183, 184, 7, 64, 2, 2, 184, 52, 3, 2, 2, 2, 185, 186, 7, 63, 2, 2, 186, 187, 7, 63, 2, 2, 187, 54, 3, 2, 2, 2, 188, 189, 7, 35, 2, 2, 189, 190, 7, 63, 2, 2, 190, 56, 3, 2, 2, 2, 191, 192, 7, 62, 2, 2, 192, 193, 7, 63, 2, 2, 193, 58, 3, 2, 2, 2, 194, 195, 7, 64, 2, 2, 195, 196, 7, 63, 2, 2, 196, 60, 3, 2, 2, 2, 197, 198, 7, 40, 2, 2, 198, 199, 7, 40, 2, 2, 199, 62, 3, 2, 2, 2, 200, 201, 7, 126, 2, 2, 201, 202, 7, 126, 2, 2, 202, 64, 3, 2, 2, 2, 203, 204, 7, 35, 2, 2, 204, 66, 3, 2, 2, 2, 205, 207, 9, 2, 2, 2, 206, 205, 3, 2, 2, 2, 207, 208, 3, 2, 2, 2, 208, 206, 3, 2, 2, 2, 208, 209, 3, 2, 2, 2, 209, 68, 3, 2, 2, 2, 210, 211, 7, 60, 2, 2, 211, 215, 9, 3, 2, 2, 212, 214, 9, 4, 2, 2, 213, 212, 3, 2, 2, 2, 214, 217, 3, 2, 2, 2, 215, 213, 3, 2, 2, 2, 215, 216, 3, 2, 2, 2, 216, 70, 3, 2, 2, 2, 217, 215, 3, 2, 2, 2, 218, 220, 9, 5, 2, 2, 219, 218, 3, 2, 2, 2, 220, 221, 3, 2, 2, 2, 221, 219, 3, 2, 2, 2, 221, 222, 3, 2, 2, 2, 222, 72, 3, 2, 2, 2, 223, 225, 9, 6, 2, 2, 224, 223, 3, 2, 2, 2, 225, 226, 3, 2, 2, 2, 226, 224, 3, 2, 2, 2, 226, 227, 3, 2, 2, 2, 227, 228, 3, 2, 2, 2, 228, 229, 8, 37, 2, 2, 229, 74, 3, 2, 2, 2, 230, 231, 7, 49, 2, 2, 231, 232, 7, 49, 2, 2, 232, 236, 3, 2, 2, 2, 233, 235, 10, 7, 2, 2, 234, 233, 3, 2, 2, 2, 235, 238, 3, 2, 2, 2, 236, 234, 3, 2, 2, 2, 236, 237, 3, 2, 2, 2, 237, 239, 3, 2, 2, 2, 238, 236, 3, 2, 2, 2, 239, 240, 8, 38, 2, 2, 240, 76, 3, 2, 2, 2, 8, 2, 208, 215, 221, 226, 236, 3, 8, 2, 2] \ No newline at end of file diff --git a/ChironCore/turtparse/tlangLexer.py b/ChironCore/turtparse/tlangLexer.py index fc951de..74f2a7a 100644 --- a/ChironCore/turtparse/tlangLexer.py +++ b/ChironCore/turtparse/tlangLexer.py @@ -5,93 +5,104 @@ import sys + def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2%") - buf.write("\u00db\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\'") + buf.write("\u00f1\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") buf.write("\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r") buf.write("\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23") buf.write("\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30") buf.write("\4\31\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36") - buf.write("\t\36\4\37\t\37\4 \t \4!\t!\4\"\t\"\4#\t#\4$\t$\3\2\3") - buf.write("\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6") - buf.write("\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\t\3\t\3") - buf.write("\n\3\n\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3") - buf.write("\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16") - buf.write("\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20") - buf.write("\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22") - buf.write("\3\22\3\22\3\22\3\22\3\23\3\23\3\24\3\24\3\25\3\25\3\26") - buf.write("\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\30") - buf.write("\3\30\3\31\3\31\3\32\3\32\3\32\3\33\3\33\3\33\3\34\3\34") - buf.write("\3\34\3\35\3\35\3\35\3\36\3\36\3\36\3\37\3\37\3\37\3 ") - buf.write("\3 \3!\6!\u00c4\n!\r!\16!\u00c5\3\"\3\"\3\"\7\"\u00cb") - buf.write("\n\"\f\"\16\"\u00ce\13\"\3#\6#\u00d1\n#\r#\16#\u00d2\3") - buf.write("$\6$\u00d6\n$\r$\16$\u00d7\3$\3$\2\2%\3\3\5\4\7\5\t\6") - buf.write("\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20") - buf.write("\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65") - buf.write("\34\67\359\36;\37= ?!A\"C#E$G%\3\2\7\3\2\62;\5\2C\\aa") - buf.write("c|\5\2\62;C\\c|\4\2C\\c|\5\2\13\f\17\17\"\"\2\u00de\2") - buf.write("\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3") - buf.write("\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2") - buf.write("\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2") - buf.write("\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%") - buf.write("\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2") - buf.write("\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67") - buf.write("\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2") - buf.write("A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\3I\3\2\2\2") - buf.write("\5L\3\2\2\2\7N\3\2\2\2\tP\3\2\2\2\13U\3\2\2\2\r\\\3\2") - buf.write("\2\2\17a\3\2\2\2\21c\3\2\2\2\23e\3\2\2\2\25g\3\2\2\2\27") - buf.write("i\3\2\2\2\31q\3\2\2\2\33z\3\2\2\2\35\177\3\2\2\2\37\u0085") - buf.write("\3\2\2\2!\u008b\3\2\2\2#\u0093\3\2\2\2%\u0099\3\2\2\2") - buf.write("\'\u009b\3\2\2\2)\u009d\3\2\2\2+\u009f\3\2\2\2-\u00a1") - buf.write("\3\2\2\2/\u00aa\3\2\2\2\61\u00ac\3\2\2\2\63\u00ae\3\2") - buf.write("\2\2\65\u00b1\3\2\2\2\67\u00b4\3\2\2\29\u00b7\3\2\2\2") - buf.write(";\u00ba\3\2\2\2=\u00bd\3\2\2\2?\u00c0\3\2\2\2A\u00c3\3") - buf.write("\2\2\2C\u00c7\3\2\2\2E\u00d0\3\2\2\2G\u00d5\3\2\2\2IJ") - buf.write("\7k\2\2JK\7h\2\2K\4\3\2\2\2LM\7]\2\2M\6\3\2\2\2NO\7_\2") - buf.write("\2O\b\3\2\2\2PQ\7g\2\2QR\7n\2\2RS\7u\2\2ST\7g\2\2T\n\3") - buf.write("\2\2\2UV\7t\2\2VW\7g\2\2WX\7r\2\2XY\7g\2\2YZ\7c\2\2Z[") - buf.write("\7v\2\2[\f\3\2\2\2\\]\7i\2\2]^\7q\2\2^_\7v\2\2_`\7q\2") - buf.write("\2`\16\3\2\2\2ab\7*\2\2b\20\3\2\2\2cd\7.\2\2d\22\3\2\2") - buf.write("\2ef\7+\2\2f\24\3\2\2\2gh\7?\2\2h\26\3\2\2\2ij\7h\2\2") - buf.write("jk\7q\2\2kl\7t\2\2lm\7y\2\2mn\7c\2\2no\7t\2\2op\7f\2\2") - buf.write("p\30\3\2\2\2qr\7d\2\2rs\7c\2\2st\7e\2\2tu\7m\2\2uv\7y") - buf.write("\2\2vw\7c\2\2wx\7t\2\2xy\7f\2\2y\32\3\2\2\2z{\7n\2\2{") - buf.write("|\7g\2\2|}\7h\2\2}~\7v\2\2~\34\3\2\2\2\177\u0080\7t\2") - buf.write("\2\u0080\u0081\7k\2\2\u0081\u0082\7i\2\2\u0082\u0083\7") - buf.write("j\2\2\u0083\u0084\7v\2\2\u0084\36\3\2\2\2\u0085\u0086") - buf.write("\7r\2\2\u0086\u0087\7g\2\2\u0087\u0088\7p\2\2\u0088\u0089") - buf.write("\7w\2\2\u0089\u008a\7r\2\2\u008a \3\2\2\2\u008b\u008c") - buf.write("\7r\2\2\u008c\u008d\7g\2\2\u008d\u008e\7p\2\2\u008e\u008f") - buf.write("\7f\2\2\u008f\u0090\7q\2\2\u0090\u0091\7y\2\2\u0091\u0092") - buf.write("\7p\2\2\u0092\"\3\2\2\2\u0093\u0094\7r\2\2\u0094\u0095") - buf.write("\7c\2\2\u0095\u0096\7w\2\2\u0096\u0097\7u\2\2\u0097\u0098") - buf.write("\7g\2\2\u0098$\3\2\2\2\u0099\u009a\7-\2\2\u009a&\3\2\2") - buf.write("\2\u009b\u009c\7/\2\2\u009c(\3\2\2\2\u009d\u009e\7,\2") - buf.write("\2\u009e*\3\2\2\2\u009f\u00a0\7\61\2\2\u00a0,\3\2\2\2") - buf.write("\u00a1\u00a2\7r\2\2\u00a2\u00a3\7g\2\2\u00a3\u00a4\7p") - buf.write("\2\2\u00a4\u00a5\7f\2\2\u00a5\u00a6\7q\2\2\u00a6\u00a7") - buf.write("\7y\2\2\u00a7\u00a8\7p\2\2\u00a8\u00a9\7A\2\2\u00a9.\3") - buf.write("\2\2\2\u00aa\u00ab\7>\2\2\u00ab\60\3\2\2\2\u00ac\u00ad") - buf.write("\7@\2\2\u00ad\62\3\2\2\2\u00ae\u00af\7?\2\2\u00af\u00b0") - buf.write("\7?\2\2\u00b0\64\3\2\2\2\u00b1\u00b2\7#\2\2\u00b2\u00b3") - buf.write("\7?\2\2\u00b3\66\3\2\2\2\u00b4\u00b5\7>\2\2\u00b5\u00b6") - buf.write("\7?\2\2\u00b68\3\2\2\2\u00b7\u00b8\7@\2\2\u00b8\u00b9") - buf.write("\7?\2\2\u00b9:\3\2\2\2\u00ba\u00bb\7(\2\2\u00bb\u00bc") - buf.write("\7(\2\2\u00bc<\3\2\2\2\u00bd\u00be\7~\2\2\u00be\u00bf") - buf.write("\7~\2\2\u00bf>\3\2\2\2\u00c0\u00c1\7#\2\2\u00c1@\3\2\2") - buf.write("\2\u00c2\u00c4\t\2\2\2\u00c3\u00c2\3\2\2\2\u00c4\u00c5") - buf.write("\3\2\2\2\u00c5\u00c3\3\2\2\2\u00c5\u00c6\3\2\2\2\u00c6") - buf.write("B\3\2\2\2\u00c7\u00c8\7<\2\2\u00c8\u00cc\t\3\2\2\u00c9") - buf.write("\u00cb\t\4\2\2\u00ca\u00c9\3\2\2\2\u00cb\u00ce\3\2\2\2") - buf.write("\u00cc\u00ca\3\2\2\2\u00cc\u00cd\3\2\2\2\u00cdD\3\2\2") - buf.write("\2\u00ce\u00cc\3\2\2\2\u00cf\u00d1\t\5\2\2\u00d0\u00cf") - buf.write("\3\2\2\2\u00d1\u00d2\3\2\2\2\u00d2\u00d0\3\2\2\2\u00d2") - buf.write("\u00d3\3\2\2\2\u00d3F\3\2\2\2\u00d4\u00d6\t\6\2\2\u00d5") - buf.write("\u00d4\3\2\2\2\u00d6\u00d7\3\2\2\2\u00d7\u00d5\3\2\2\2") - buf.write("\u00d7\u00d8\3\2\2\2\u00d8\u00d9\3\2\2\2\u00d9\u00da\b") - buf.write("$\2\2\u00daH\3\2\2\2\7\2\u00c5\u00cc\u00d2\u00d7\3\b\2") - buf.write("\2") + buf.write("\t\36\4\37\t\37\4 \t \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%") + buf.write("\4&\t&\3\2\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\5\3\5\3\5") + buf.write("\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\b\3") + buf.write("\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3") + buf.write("\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3") + buf.write("\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20") + buf.write("\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21") + buf.write("\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23") + buf.write("\3\23\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26\3\27\3\27") + buf.write("\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31") + buf.write("\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35") + buf.write("\3\36\3\36\3\36\3\37\3\37\3\37\3 \3 \3 \3!\3!\3\"\6\"") + buf.write("\u00cf\n\"\r\"\16\"\u00d0\3#\3#\3#\7#\u00d6\n#\f#\16#") + buf.write("\u00d9\13#\3$\6$\u00dc\n$\r$\16$\u00dd\3%\6%\u00e1\n%") + buf.write("\r%\16%\u00e2\3%\3%\3&\3&\3&\3&\7&\u00eb\n&\f&\16&\u00ee") + buf.write("\13&\3&\3&\2\2\'\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23") + buf.write("\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25") + buf.write(")\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A") + buf.write("\"C#E$G%I&K\'\3\2\b\3\2\62;\5\2C\\aac|\5\2\62;C\\c|\4") + buf.write("\2C\\c|\5\2\13\f\17\17\"\"\4\2\f\f\17\17\2\u00f5\2\3\3") + buf.write("\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2") + buf.write("\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2") + buf.write("\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2") + buf.write("\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2") + buf.write("\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3") + buf.write("\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2") + buf.write("\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3") + buf.write("\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K") + buf.write("\3\2\2\2\3M\3\2\2\2\5P\3\2\2\2\7R\3\2\2\2\tT\3\2\2\2\13") + buf.write("Y\3\2\2\2\r`\3\2\2\2\17e\3\2\2\2\21g\3\2\2\2\23i\3\2\2") + buf.write("\2\25k\3\2\2\2\27m\3\2\2\2\31u\3\2\2\2\33~\3\2\2\2\35") + buf.write("\u0083\3\2\2\2\37\u0089\3\2\2\2!\u008f\3\2\2\2#\u0097") + buf.write("\3\2\2\2%\u009d\3\2\2\2\'\u00a4\3\2\2\2)\u00a6\3\2\2\2") + buf.write("+\u00a8\3\2\2\2-\u00aa\3\2\2\2/\u00ac\3\2\2\2\61\u00b5") + buf.write("\3\2\2\2\63\u00b7\3\2\2\2\65\u00b9\3\2\2\2\67\u00bc\3") + buf.write("\2\2\29\u00bf\3\2\2\2;\u00c2\3\2\2\2=\u00c5\3\2\2\2?\u00c8") + buf.write("\3\2\2\2A\u00cb\3\2\2\2C\u00ce\3\2\2\2E\u00d2\3\2\2\2") + buf.write("G\u00db\3\2\2\2I\u00e0\3\2\2\2K\u00e6\3\2\2\2MN\7k\2\2") + buf.write("NO\7h\2\2O\4\3\2\2\2PQ\7]\2\2Q\6\3\2\2\2RS\7_\2\2S\b\3") + buf.write("\2\2\2TU\7g\2\2UV\7n\2\2VW\7u\2\2WX\7g\2\2X\n\3\2\2\2") + buf.write("YZ\7t\2\2Z[\7g\2\2[\\\7r\2\2\\]\7g\2\2]^\7c\2\2^_\7v\2") + buf.write("\2_\f\3\2\2\2`a\7i\2\2ab\7q\2\2bc\7v\2\2cd\7q\2\2d\16") + buf.write("\3\2\2\2ef\7*\2\2f\20\3\2\2\2gh\7.\2\2h\22\3\2\2\2ij\7") + buf.write("+\2\2j\24\3\2\2\2kl\7?\2\2l\26\3\2\2\2mn\7h\2\2no\7q\2") + buf.write("\2op\7t\2\2pq\7y\2\2qr\7c\2\2rs\7t\2\2st\7f\2\2t\30\3") + buf.write("\2\2\2uv\7d\2\2vw\7c\2\2wx\7e\2\2xy\7m\2\2yz\7y\2\2z{") + buf.write("\7c\2\2{|\7t\2\2|}\7f\2\2}\32\3\2\2\2~\177\7n\2\2\177") + buf.write("\u0080\7g\2\2\u0080\u0081\7h\2\2\u0081\u0082\7v\2\2\u0082") + buf.write("\34\3\2\2\2\u0083\u0084\7t\2\2\u0084\u0085\7k\2\2\u0085") + buf.write("\u0086\7i\2\2\u0086\u0087\7j\2\2\u0087\u0088\7v\2\2\u0088") + buf.write("\36\3\2\2\2\u0089\u008a\7r\2\2\u008a\u008b\7g\2\2\u008b") + buf.write("\u008c\7p\2\2\u008c\u008d\7w\2\2\u008d\u008e\7r\2\2\u008e") + buf.write(" \3\2\2\2\u008f\u0090\7r\2\2\u0090\u0091\7g\2\2\u0091") + buf.write("\u0092\7p\2\2\u0092\u0093\7f\2\2\u0093\u0094\7q\2\2\u0094") + buf.write("\u0095\7y\2\2\u0095\u0096\7p\2\2\u0096\"\3\2\2\2\u0097") + buf.write("\u0098\7r\2\2\u0098\u0099\7c\2\2\u0099\u009a\7w\2\2\u009a") + buf.write("\u009b\7u\2\2\u009b\u009c\7g\2\2\u009c$\3\2\2\2\u009d") + buf.write("\u009e\7c\2\2\u009e\u009f\7u\2\2\u009f\u00a0\7u\2\2\u00a0") + buf.write("\u00a1\7g\2\2\u00a1\u00a2\7t\2\2\u00a2\u00a3\7v\2\2\u00a3") + buf.write("&\3\2\2\2\u00a4\u00a5\7-\2\2\u00a5(\3\2\2\2\u00a6\u00a7") + buf.write("\7/\2\2\u00a7*\3\2\2\2\u00a8\u00a9\7,\2\2\u00a9,\3\2\2") + buf.write("\2\u00aa\u00ab\7\61\2\2\u00ab.\3\2\2\2\u00ac\u00ad\7r") + buf.write("\2\2\u00ad\u00ae\7g\2\2\u00ae\u00af\7p\2\2\u00af\u00b0") + buf.write("\7f\2\2\u00b0\u00b1\7q\2\2\u00b1\u00b2\7y\2\2\u00b2\u00b3") + buf.write("\7p\2\2\u00b3\u00b4\7A\2\2\u00b4\60\3\2\2\2\u00b5\u00b6") + buf.write("\7>\2\2\u00b6\62\3\2\2\2\u00b7\u00b8\7@\2\2\u00b8\64\3") + buf.write("\2\2\2\u00b9\u00ba\7?\2\2\u00ba\u00bb\7?\2\2\u00bb\66") + buf.write("\3\2\2\2\u00bc\u00bd\7#\2\2\u00bd\u00be\7?\2\2\u00be8") + buf.write("\3\2\2\2\u00bf\u00c0\7>\2\2\u00c0\u00c1\7?\2\2\u00c1:") + buf.write("\3\2\2\2\u00c2\u00c3\7@\2\2\u00c3\u00c4\7?\2\2\u00c4<") + buf.write("\3\2\2\2\u00c5\u00c6\7(\2\2\u00c6\u00c7\7(\2\2\u00c7>") + buf.write("\3\2\2\2\u00c8\u00c9\7~\2\2\u00c9\u00ca\7~\2\2\u00ca@") + buf.write("\3\2\2\2\u00cb\u00cc\7#\2\2\u00ccB\3\2\2\2\u00cd\u00cf") + buf.write("\t\2\2\2\u00ce\u00cd\3\2\2\2\u00cf\u00d0\3\2\2\2\u00d0") + buf.write("\u00ce\3\2\2\2\u00d0\u00d1\3\2\2\2\u00d1D\3\2\2\2\u00d2") + buf.write("\u00d3\7<\2\2\u00d3\u00d7\t\3\2\2\u00d4\u00d6\t\4\2\2") + buf.write("\u00d5\u00d4\3\2\2\2\u00d6\u00d9\3\2\2\2\u00d7\u00d5\3") + buf.write("\2\2\2\u00d7\u00d8\3\2\2\2\u00d8F\3\2\2\2\u00d9\u00d7") + buf.write("\3\2\2\2\u00da\u00dc\t\5\2\2\u00db\u00da\3\2\2\2\u00dc") + buf.write("\u00dd\3\2\2\2\u00dd\u00db\3\2\2\2\u00dd\u00de\3\2\2\2") + buf.write("\u00deH\3\2\2\2\u00df\u00e1\t\6\2\2\u00e0\u00df\3\2\2") + buf.write("\2\u00e1\u00e2\3\2\2\2\u00e2\u00e0\3\2\2\2\u00e2\u00e3") + buf.write("\3\2\2\2\u00e3\u00e4\3\2\2\2\u00e4\u00e5\b%\2\2\u00e5") + buf.write("J\3\2\2\2\u00e6\u00e7\7\61\2\2\u00e7\u00e8\7\61\2\2\u00e8") + buf.write("\u00ec\3\2\2\2\u00e9\u00eb\n\7\2\2\u00ea\u00e9\3\2\2\2") + buf.write("\u00eb\u00ee\3\2\2\2\u00ec\u00ea\3\2\2\2\u00ec\u00ed\3") + buf.write("\2\2\2\u00ed\u00ef\3\2\2\2\u00ee\u00ec\3\2\2\2\u00ef\u00f0") + buf.write("\b&\2\2\u00f0L\3\2\2\2\b\2\u00d0\u00d7\u00dd\u00e2\u00ec") + buf.write("\3\b\2\2") return buf.getvalue() @@ -118,24 +129,26 @@ class tlangLexer(Lexer): T__14 = 15 T__15 = 16 T__16 = 17 - PLUS = 18 - MINUS = 19 - MUL = 20 - DIV = 21 - PENCOND = 22 - LT = 23 - GT = 24 - EQ = 25 - NEQ = 26 - LTE = 27 - GTE = 28 - AND = 29 - OR = 30 - NOT = 31 - NUM = 32 - VAR = 33 - NAME = 34 - Whitespace = 35 + T__17 = 18 + PLUS = 19 + MINUS = 20 + MUL = 21 + DIV = 22 + PENCOND = 23 + LT = 24 + GT = 25 + EQ = 26 + NEQ = 27 + LTE = 28 + GTE = 29 + AND = 30 + OR = 31 + NOT = 32 + NUM = 33 + VAR = 34 + NAME = 35 + Whitespace = 36 + Comment = 37 channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] @@ -144,20 +157,21 @@ class tlangLexer(Lexer): literalNames = [ "", "'if'", "'['", "']'", "'else'", "'repeat'", "'goto'", "'('", "','", "')'", "'='", "'forward'", "'backward'", "'left'", "'right'", - "'penup'", "'pendown'", "'pause'", "'+'", "'-'", "'*'", "'/'", - "'pendown?'", "'<'", "'>'", "'=='", "'!='", "'<='", "'>='", - "'&&'", "'||'", "'!'" ] + "'penup'", "'pendown'", "'pause'", "'assert'", "'+'", "'-'", + "'*'", "'/'", "'pendown?'", "'<'", "'>'", "'=='", "'!='", "'<='", + "'>='", "'&&'", "'||'", "'!'" ] symbolicNames = [ "", "PLUS", "MINUS", "MUL", "DIV", "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", "VAR", "NAME", - "Whitespace" ] + "Whitespace", "Comment" ] ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", - "T__14", "T__15", "T__16", "PLUS", "MINUS", "MUL", "DIV", - "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", "GTE", "AND", - "OR", "NOT", "NUM", "VAR", "NAME", "Whitespace" ] + "T__14", "T__15", "T__16", "T__17", "PLUS", "MINUS", "MUL", + "DIV", "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", "GTE", + "AND", "OR", "NOT", "NUM", "VAR", "NAME", "Whitespace", + "Comment" ] grammarFileName = "tlang.g4" diff --git a/ChironCore/turtparse/tlangLexer.tokens b/ChironCore/turtparse/tlangLexer.tokens index 78f9526..b0a2b1d 100644 --- a/ChironCore/turtparse/tlangLexer.tokens +++ b/ChironCore/turtparse/tlangLexer.tokens @@ -15,24 +15,26 @@ T__13=14 T__14=15 T__15=16 T__16=17 -PLUS=18 -MINUS=19 -MUL=20 -DIV=21 -PENCOND=22 -LT=23 -GT=24 -EQ=25 -NEQ=26 -LTE=27 -GTE=28 -AND=29 -OR=30 -NOT=31 -NUM=32 -VAR=33 -NAME=34 -Whitespace=35 +T__17=18 +PLUS=19 +MINUS=20 +MUL=21 +DIV=22 +PENCOND=23 +LT=24 +GT=25 +EQ=26 +NEQ=27 +LTE=28 +GTE=29 +AND=30 +OR=31 +NOT=32 +NUM=33 +VAR=34 +NAME=35 +Whitespace=36 +Comment=37 'if'=1 '['=2 ']'=3 @@ -50,17 +52,18 @@ Whitespace=35 'penup'=15 'pendown'=16 'pause'=17 -'+'=18 -'-'=19 -'*'=20 -'/'=21 -'pendown?'=22 -'<'=23 -'>'=24 -'=='=25 -'!='=26 -'<='=27 -'>='=28 -'&&'=29 -'||'=30 -'!'=31 +'assert'=18 +'+'=19 +'-'=20 +'*'=21 +'/'=22 +'pendown?'=23 +'<'=24 +'>'=25 +'=='=26 +'!='=27 +'<='=28 +'>='=29 +'&&'=30 +'||'=31 +'!'=32 diff --git a/ChironCore/turtparse/tlangParser.py b/ChironCore/turtparse/tlangParser.py index b02d4a2..bc95100 100644 --- a/ChironCore/turtparse/tlangParser.py +++ b/ChironCore/turtparse/tlangParser.py @@ -5,71 +5,75 @@ from typing.io import TextIO import sys + def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3%") - buf.write("\u00af\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\'") + buf.write("\u00b5\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16") buf.write("\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23\t\23") - buf.write("\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\3\2\3\2\3\2\3") - buf.write("\3\7\3\63\n\3\f\3\16\3\66\13\3\3\4\6\49\n\4\r\4\16\4:") - buf.write("\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5D\n\5\3\6\3\6\5\6H\n\6") - buf.write("\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3") - buf.write("\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n") - buf.write("\3\n\3\n\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\r\3\r\3\16") - buf.write("\3\16\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20") - buf.write("\3\20\5\20}\n\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3") - buf.write("\20\7\20\u0087\n\20\f\20\16\20\u008a\13\20\3\21\3\21\3") - buf.write("\22\3\22\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\24") - buf.write("\3\24\3\24\3\24\3\24\3\24\5\24\u009e\n\24\3\24\3\24\3") - buf.write("\24\3\24\7\24\u00a4\n\24\f\24\16\24\u00a7\13\24\3\25\3") - buf.write("\25\3\26\3\26\3\27\3\27\3\27\2\4\36&\30\2\4\6\b\n\f\16") - buf.write("\20\22\24\26\30\32\34\36 \"$&(*,\2\t\3\2\r\20\3\2\21\22") - buf.write("\3\2\26\27\3\2\24\25\3\2\31\36\3\2\37 \3\2\"#\2\u00a9") - buf.write("\2.\3\2\2\2\4\64\3\2\2\2\68\3\2\2\2\bC\3\2\2\2\nG\3\2") - buf.write("\2\2\fI\3\2\2\2\16O\3\2\2\2\20Y\3\2\2\2\22_\3\2\2\2\24") - buf.write("f\3\2\2\2\26j\3\2\2\2\30m\3\2\2\2\32o\3\2\2\2\34q\3\2") - buf.write("\2\2\36|\3\2\2\2 \u008b\3\2\2\2\"\u008d\3\2\2\2$\u008f") - buf.write("\3\2\2\2&\u009d\3\2\2\2(\u00a8\3\2\2\2*\u00aa\3\2\2\2") - buf.write(",\u00ac\3\2\2\2./\5\4\3\2/\60\7\2\2\3\60\3\3\2\2\2\61") - buf.write("\63\5\b\5\2\62\61\3\2\2\2\63\66\3\2\2\2\64\62\3\2\2\2") - buf.write("\64\65\3\2\2\2\65\5\3\2\2\2\66\64\3\2\2\2\679\5\b\5\2") - buf.write("8\67\3\2\2\29:\3\2\2\2:8\3\2\2\2:;\3\2\2\2;\7\3\2\2\2") - buf.write("D\5\20\t\2?D\5\26\f\2@D\5\32\16") - buf.write("\2AD\5\22\n\2BD\5\34\17\2C<\3\2\2\2C=\3\2\2\2C>\3\2\2") - buf.write("\2C?\3\2\2\2C@\3\2\2\2CA\3\2\2\2CB\3\2\2\2D\t\3\2\2\2") - buf.write("EH\5\f\7\2FH\5\16\b\2GE\3\2\2\2GF\3\2\2\2H\13\3\2\2\2") - buf.write("IJ\7\3\2\2JK\5&\24\2KL\7\4\2\2LM\5\6\4\2MN\7\5\2\2N\r") - buf.write("\3\2\2\2OP\7\3\2\2PQ\5&\24\2QR\7\4\2\2RS\5\6\4\2ST\7\5") - buf.write("\2\2TU\7\6\2\2UV\7\4\2\2VW\5\6\4\2WX\7\5\2\2X\17\3\2\2") - buf.write("\2YZ\7\7\2\2Z[\5,\27\2[\\\7\4\2\2\\]\5\6\4\2]^\7\5\2\2") - buf.write("^\21\3\2\2\2_`\7\b\2\2`a\7\t\2\2ab\5\36\20\2bc\7\n\2\2") - buf.write("cd\5\36\20\2de\7\13\2\2e\23\3\2\2\2fg\7#\2\2gh\7\f\2\2") - buf.write("hi\5\36\20\2i\25\3\2\2\2jk\5\30\r\2kl\5\36\20\2l\27\3") - buf.write("\2\2\2mn\t\2\2\2n\31\3\2\2\2op\t\3\2\2p\33\3\2\2\2qr\7") - buf.write("\23\2\2r\35\3\2\2\2st\b\20\1\2tu\5$\23\2uv\5\36\20\7v") - buf.write("}\3\2\2\2w}\5,\27\2xy\7\t\2\2yz\5\36\20\2z{\7\13\2\2{") - buf.write("}\3\2\2\2|s\3\2\2\2|w\3\2\2\2|x\3\2\2\2}\u0088\3\2\2\2") - buf.write("~\177\f\6\2\2\177\u0080\5 \21\2\u0080\u0081\5\36\20\7") - buf.write("\u0081\u0087\3\2\2\2\u0082\u0083\f\5\2\2\u0083\u0084\5") - buf.write("\"\22\2\u0084\u0085\5\36\20\6\u0085\u0087\3\2\2\2\u0086") - buf.write("~\3\2\2\2\u0086\u0082\3\2\2\2\u0087\u008a\3\2\2\2\u0088") - buf.write("\u0086\3\2\2\2\u0088\u0089\3\2\2\2\u0089\37\3\2\2\2\u008a") - buf.write("\u0088\3\2\2\2\u008b\u008c\t\4\2\2\u008c!\3\2\2\2\u008d") - buf.write("\u008e\t\5\2\2\u008e#\3\2\2\2\u008f\u0090\7\25\2\2\u0090") - buf.write("%\3\2\2\2\u0091\u0092\b\24\1\2\u0092\u0093\7!\2\2\u0093") - buf.write("\u009e\5&\24\7\u0094\u0095\5\36\20\2\u0095\u0096\5(\25") - buf.write("\2\u0096\u0097\5\36\20\2\u0097\u009e\3\2\2\2\u0098\u009e") - buf.write("\7\30\2\2\u0099\u009a\7\t\2\2\u009a\u009b\5&\24\2\u009b") - buf.write("\u009c\7\13\2\2\u009c\u009e\3\2\2\2\u009d\u0091\3\2\2") - buf.write("\2\u009d\u0094\3\2\2\2\u009d\u0098\3\2\2\2\u009d\u0099") - buf.write("\3\2\2\2\u009e\u00a5\3\2\2\2\u009f\u00a0\f\5\2\2\u00a0") - buf.write("\u00a1\5*\26\2\u00a1\u00a2\5&\24\6\u00a2\u00a4\3\2\2\2") - buf.write("\u00a3\u009f\3\2\2\2\u00a4\u00a7\3\2\2\2\u00a5\u00a3\3") - buf.write("\2\2\2\u00a5\u00a6\3\2\2\2\u00a6\'\3\2\2\2\u00a7\u00a5") - buf.write("\3\2\2\2\u00a8\u00a9\t\6\2\2\u00a9)\3\2\2\2\u00aa\u00ab") - buf.write("\t\7\2\2\u00ab+\3\2\2\2\u00ac\u00ad\t\b\2\2\u00ad-\3\2") - buf.write("\2\2\13\64:CG|\u0086\u0088\u009d\u00a5") + buf.write("\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\3\2") + buf.write("\3\2\3\2\3\3\7\3\65\n\3\f\3\16\38\13\3\3\4\6\4;\n\4\r") + buf.write("\4\16\4<\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5G\n\5\3\6") + buf.write("\3\6\5\6K\n\6\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b") + buf.write("\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3") + buf.write("\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\f\3\f\3\f") + buf.write("\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\21\3\21") + buf.write("\3\21\3\21\3\21\3\21\3\21\3\21\3\21\5\21\u0083\n\21\3") + buf.write("\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\7\21\u008d\n\21") + buf.write("\f\21\16\21\u0090\13\21\3\22\3\22\3\23\3\23\3\24\3\24") + buf.write("\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25") + buf.write("\3\25\5\25\u00a4\n\25\3\25\3\25\3\25\3\25\7\25\u00aa\n") + buf.write("\25\f\25\16\25\u00ad\13\25\3\26\3\26\3\27\3\27\3\30\3") + buf.write("\30\3\30\2\4 (\31\2\4\6\b\n\f\16\20\22\24\26\30\32\34") + buf.write("\36 \"$&(*,.\2\t\3\2\r\20\3\2\21\22\3\2\27\30\3\2\25\26") + buf.write("\3\2\32\37\3\2 !\3\2#$\2\u00af\2\60\3\2\2\2\4\66\3\2\2") + buf.write("\2\6:\3\2\2\2\bF\3\2\2\2\nJ\3\2\2\2\fL\3\2\2\2\16R\3\2") + buf.write("\2\2\20\\\3\2\2\2\22b\3\2\2\2\24i\3\2\2\2\26m\3\2\2\2") + buf.write("\30p\3\2\2\2\32r\3\2\2\2\34t\3\2\2\2\36v\3\2\2\2 \u0082") + buf.write("\3\2\2\2\"\u0091\3\2\2\2$\u0093\3\2\2\2&\u0095\3\2\2\2") + buf.write("(\u00a3\3\2\2\2*\u00ae\3\2\2\2,\u00b0\3\2\2\2.\u00b2\3") + buf.write("\2\2\2\60\61\5\4\3\2\61\62\7\2\2\3\62\3\3\2\2\2\63\65") + buf.write("\5\b\5\2\64\63\3\2\2\2\658\3\2\2\2\66\64\3\2\2\2\66\67") + buf.write("\3\2\2\2\67\5\3\2\2\28\66\3\2\2\29;\5\b\5\2:9\3\2\2\2") + buf.write(";<\3\2\2\2<:\3\2\2\2<=\3\2\2\2=\7\3\2\2\2>G\5\24\13\2") + buf.write("?G\5\n\6\2@G\5\20\t\2AG\5\26\f\2BG\5\32\16\2CG\5\22\n") + buf.write("\2DG\5\34\17\2EG\5\36\20\2F>\3\2\2\2F?\3\2\2\2F@\3\2\2") + buf.write("\2FA\3\2\2\2FB\3\2\2\2FC\3\2\2\2FD\3\2\2\2FE\3\2\2\2G") + buf.write("\t\3\2\2\2HK\5\f\7\2IK\5\16\b\2JH\3\2\2\2JI\3\2\2\2K\13") + buf.write("\3\2\2\2LM\7\3\2\2MN\5(\25\2NO\7\4\2\2OP\5\6\4\2PQ\7\5") + buf.write("\2\2Q\r\3\2\2\2RS\7\3\2\2ST\5(\25\2TU\7\4\2\2UV\5\6\4") + buf.write("\2VW\7\5\2\2WX\7\6\2\2XY\7\4\2\2YZ\5\6\4\2Z[\7\5\2\2[") + buf.write("\17\3\2\2\2\\]\7\7\2\2]^\5.\30\2^_\7\4\2\2_`\5\6\4\2`") + buf.write("a\7\5\2\2a\21\3\2\2\2bc\7\b\2\2cd\7\t\2\2de\5 \21\2ef") + buf.write("\7\n\2\2fg\5 \21\2gh\7\13\2\2h\23\3\2\2\2ij\7$\2\2jk\7") + buf.write("\f\2\2kl\5 \21\2l\25\3\2\2\2mn\5\30\r\2no\5 \21\2o\27") + buf.write("\3\2\2\2pq\t\2\2\2q\31\3\2\2\2rs\t\3\2\2s\33\3\2\2\2t") + buf.write("u\7\23\2\2u\35\3\2\2\2vw\7\24\2\2wx\5(\25\2x\37\3\2\2") + buf.write("\2yz\b\21\1\2z{\5&\24\2{|\5 \21\7|\u0083\3\2\2\2}\u0083") + buf.write("\5.\30\2~\177\7\t\2\2\177\u0080\5 \21\2\u0080\u0081\7") + buf.write("\13\2\2\u0081\u0083\3\2\2\2\u0082y\3\2\2\2\u0082}\3\2") + buf.write("\2\2\u0082~\3\2\2\2\u0083\u008e\3\2\2\2\u0084\u0085\f") + buf.write("\6\2\2\u0085\u0086\5\"\22\2\u0086\u0087\5 \21\7\u0087") + buf.write("\u008d\3\2\2\2\u0088\u0089\f\5\2\2\u0089\u008a\5$\23\2") + buf.write("\u008a\u008b\5 \21\6\u008b\u008d\3\2\2\2\u008c\u0084\3") + buf.write("\2\2\2\u008c\u0088\3\2\2\2\u008d\u0090\3\2\2\2\u008e\u008c") + buf.write("\3\2\2\2\u008e\u008f\3\2\2\2\u008f!\3\2\2\2\u0090\u008e") + buf.write("\3\2\2\2\u0091\u0092\t\4\2\2\u0092#\3\2\2\2\u0093\u0094") + buf.write("\t\5\2\2\u0094%\3\2\2\2\u0095\u0096\7\26\2\2\u0096\'\3") + buf.write("\2\2\2\u0097\u0098\b\25\1\2\u0098\u0099\7\"\2\2\u0099") + buf.write("\u00a4\5(\25\7\u009a\u009b\5 \21\2\u009b\u009c\5*\26\2") + buf.write("\u009c\u009d\5 \21\2\u009d\u00a4\3\2\2\2\u009e\u00a4\7") + buf.write("\31\2\2\u009f\u00a0\7\t\2\2\u00a0\u00a1\5(\25\2\u00a1") + buf.write("\u00a2\7\13\2\2\u00a2\u00a4\3\2\2\2\u00a3\u0097\3\2\2") + buf.write("\2\u00a3\u009a\3\2\2\2\u00a3\u009e\3\2\2\2\u00a3\u009f") + buf.write("\3\2\2\2\u00a4\u00ab\3\2\2\2\u00a5\u00a6\f\5\2\2\u00a6") + buf.write("\u00a7\5,\27\2\u00a7\u00a8\5(\25\6\u00a8\u00aa\3\2\2\2") + buf.write("\u00a9\u00a5\3\2\2\2\u00aa\u00ad\3\2\2\2\u00ab\u00a9\3") + buf.write("\2\2\2\u00ab\u00ac\3\2\2\2\u00ac)\3\2\2\2\u00ad\u00ab") + buf.write("\3\2\2\2\u00ae\u00af\t\6\2\2\u00af+\3\2\2\2\u00b0\u00b1") + buf.write("\t\7\2\2\u00b1-\3\2\2\2\u00b2\u00b3\t\b\2\2\u00b3/\3\2") + buf.write("\2\2\13\66", "'if'", "'['", "']'", "'else'", "'repeat'", "'goto'", "'('", "','", "')'", "'='", "'forward'", "'backward'", "'left'", "'right'", "'penup'", "'pendown'", - "'pause'", "'+'", "'-'", "'*'", "'/'", "'pendown?'", - "'<'", "'>'", "'=='", "'!='", "'<='", "'>='", "'&&'", - "'||'", "'!'" ] + "'pause'", "'assert'", "'+'", "'-'", "'*'", "'/'", + "'pendown?'", "'<'", "'>'", "'=='", "'!='", "'<='", + "'>='", "'&&'", "'||'", "'!'" ] symbolicNames = [ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", "", "PLUS", "MINUS", "MUL", - "DIV", "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", - "GTE", "AND", "OR", "NOT", "NUM", "VAR", "NAME", "Whitespace" ] + "", "", "", "PLUS", "MINUS", + "MUL", "DIV", "PENCOND", "LT", "GT", "EQ", "NEQ", + "LTE", "GTE", "AND", "OR", "NOT", "NUM", "VAR", "NAME", + "Whitespace", "Comment" ] RULE_start = 0 RULE_instruction_list = 1 @@ -112,21 +117,22 @@ class tlangParser ( Parser ): RULE_moveOp = 11 RULE_penCommand = 12 RULE_pauseCommand = 13 - RULE_expression = 14 - RULE_multiplicative = 15 - RULE_additive = 16 - RULE_unaryArithOp = 17 - RULE_condition = 18 - RULE_binCondOp = 19 - RULE_logicOp = 20 - RULE_value = 21 + RULE_assertionCommand = 14 + RULE_expression = 15 + RULE_multiplicative = 16 + RULE_additive = 17 + RULE_unaryArithOp = 18 + RULE_condition = 19 + RULE_binCondOp = 20 + RULE_logicOp = 21 + RULE_value = 22 ruleNames = [ "start", "instruction_list", "strict_ilist", "instruction", "conditional", "ifConditional", "ifElseConditional", "loop", "gotoCommand", "assignment", "moveCommand", "moveOp", - "penCommand", "pauseCommand", "expression", "multiplicative", - "additive", "unaryArithOp", "condition", "binCondOp", - "logicOp", "value" ] + "penCommand", "pauseCommand", "assertionCommand", "expression", + "multiplicative", "additive", "unaryArithOp", "condition", + "binCondOp", "logicOp", "value" ] EOF = Token.EOF T__0=1 @@ -146,24 +152,26 @@ class tlangParser ( Parser ): T__14=15 T__15=16 T__16=17 - PLUS=18 - MINUS=19 - MUL=20 - DIV=21 - PENCOND=22 - LT=23 - GT=24 - EQ=25 - NEQ=26 - LTE=27 - GTE=28 - AND=29 - OR=30 - NOT=31 - NUM=32 - VAR=33 - NAME=34 - Whitespace=35 + T__17=18 + PLUS=19 + MINUS=20 + MUL=21 + DIV=22 + PENCOND=23 + LT=24 + GT=25 + EQ=26 + NEQ=27 + LTE=28 + GTE=29 + AND=30 + OR=31 + NOT=32 + NUM=33 + VAR=34 + NAME=35 + Whitespace=36 + Comment=37 def __init__(self, input:TokenStream, output:TextIO = sys.stdout): super().__init__(input, output) @@ -173,6 +181,7 @@ def __init__(self, input:TokenStream, output:TextIO = sys.stdout): + class StartContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -204,9 +213,9 @@ def start(self): self.enterRule(localctx, 0, self.RULE_start) try: self.enterOuterAlt(localctx, 1) - self.state = 44 + self.state = 46 self.instruction_list() - self.state = 45 + self.state = 47 self.match(tlangParser.EOF) except RecognitionException as re: localctx.exception = re @@ -216,6 +225,7 @@ def start(self): self.exitRule() return localctx + class Instruction_listContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -248,13 +258,13 @@ def instruction_list(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 50 + self.state = 52 self._errHandler.sync(self) _la = self._input.LA(1) - while (((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.VAR))) != 0): - self.state = 47 + while (((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.VAR))) != 0): + self.state = 49 self.instruction() - self.state = 52 + self.state = 54 self._errHandler.sync(self) _la = self._input.LA(1) @@ -266,6 +276,7 @@ def instruction_list(self): self.exitRule() return localctx + class Strict_ilistContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -298,16 +309,16 @@ def strict_ilist(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 54 + self.state = 56 self._errHandler.sync(self) _la = self._input.LA(1) while True: - self.state = 53 + self.state = 55 self.instruction() - self.state = 56 + self.state = 58 self._errHandler.sync(self) _la = self._input.LA(1) - if not ((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.VAR))) != 0)): + if not ((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.VAR))) != 0)): break except RecognitionException as re: @@ -318,6 +329,7 @@ def strict_ilist(self): self.exitRule() return localctx + class InstructionContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -352,6 +364,10 @@ def pauseCommand(self): return self.getTypedRuleContext(tlangParser.PauseCommandContext,0) + def assertionCommand(self): + return self.getTypedRuleContext(tlangParser.AssertionCommandContext,0) + + def getRuleIndex(self): return tlangParser.RULE_instruction @@ -369,44 +385,49 @@ def instruction(self): localctx = tlangParser.InstructionContext(self, self._ctx, self.state) self.enterRule(localctx, 6, self.RULE_instruction) try: - self.state = 65 + self.state = 68 self._errHandler.sync(self) token = self._input.LA(1) if token in [tlangParser.VAR]: self.enterOuterAlt(localctx, 1) - self.state = 58 + self.state = 60 self.assignment() pass elif token in [tlangParser.T__0]: self.enterOuterAlt(localctx, 2) - self.state = 59 + self.state = 61 self.conditional() pass elif token in [tlangParser.T__4]: self.enterOuterAlt(localctx, 3) - self.state = 60 + self.state = 62 self.loop() pass elif token in [tlangParser.T__10, tlangParser.T__11, tlangParser.T__12, tlangParser.T__13]: self.enterOuterAlt(localctx, 4) - self.state = 61 + self.state = 63 self.moveCommand() pass elif token in [tlangParser.T__14, tlangParser.T__15]: self.enterOuterAlt(localctx, 5) - self.state = 62 + self.state = 64 self.penCommand() pass elif token in [tlangParser.T__5]: self.enterOuterAlt(localctx, 6) - self.state = 63 + self.state = 65 self.gotoCommand() pass elif token in [tlangParser.T__16]: self.enterOuterAlt(localctx, 7) - self.state = 64 + self.state = 66 self.pauseCommand() pass + elif token in [tlangParser.T__17]: + self.enterOuterAlt(localctx, 8) + self.state = 67 + self.assertionCommand() + pass else: raise NoViableAltException(self) @@ -418,6 +439,7 @@ def instruction(self): self.exitRule() return localctx + class ConditionalContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -449,18 +471,18 @@ def conditional(self): localctx = tlangParser.ConditionalContext(self, self._ctx, self.state) self.enterRule(localctx, 8, self.RULE_conditional) try: - self.state = 69 + self.state = 72 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,3,self._ctx) if la_ == 1: self.enterOuterAlt(localctx, 1) - self.state = 67 + self.state = 70 self.ifConditional() pass elif la_ == 2: self.enterOuterAlt(localctx, 2) - self.state = 68 + self.state = 71 self.ifElseConditional() pass @@ -473,6 +495,7 @@ def conditional(self): self.exitRule() return localctx + class IfConditionalContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -505,15 +528,15 @@ def ifConditional(self): self.enterRule(localctx, 10, self.RULE_ifConditional) try: self.enterOuterAlt(localctx, 1) - self.state = 71 + self.state = 74 self.match(tlangParser.T__0) - self.state = 72 + self.state = 75 self.condition(0) - self.state = 73 + self.state = 76 self.match(tlangParser.T__1) - self.state = 74 + self.state = 77 self.strict_ilist() - self.state = 75 + self.state = 78 self.match(tlangParser.T__2) except RecognitionException as re: localctx.exception = re @@ -523,6 +546,7 @@ def ifConditional(self): self.exitRule() return localctx + class IfElseConditionalContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -558,23 +582,23 @@ def ifElseConditional(self): self.enterRule(localctx, 12, self.RULE_ifElseConditional) try: self.enterOuterAlt(localctx, 1) - self.state = 77 + self.state = 80 self.match(tlangParser.T__0) - self.state = 78 + self.state = 81 self.condition(0) - self.state = 79 + self.state = 82 self.match(tlangParser.T__1) - self.state = 80 + self.state = 83 self.strict_ilist() - self.state = 81 + self.state = 84 self.match(tlangParser.T__2) - self.state = 82 + self.state = 85 self.match(tlangParser.T__3) - self.state = 83 + self.state = 86 self.match(tlangParser.T__1) - self.state = 84 + self.state = 87 self.strict_ilist() - self.state = 85 + self.state = 88 self.match(tlangParser.T__2) except RecognitionException as re: localctx.exception = re @@ -584,6 +608,7 @@ def ifElseConditional(self): self.exitRule() return localctx + class LoopContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -616,15 +641,15 @@ def loop(self): self.enterRule(localctx, 14, self.RULE_loop) try: self.enterOuterAlt(localctx, 1) - self.state = 87 + self.state = 90 self.match(tlangParser.T__4) - self.state = 88 + self.state = 91 self.value() - self.state = 89 + self.state = 92 self.match(tlangParser.T__1) - self.state = 90 + self.state = 93 self.strict_ilist() - self.state = 91 + self.state = 94 self.match(tlangParser.T__2) except RecognitionException as re: localctx.exception = re @@ -634,6 +659,7 @@ def loop(self): self.exitRule() return localctx + class GotoCommandContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -665,17 +691,17 @@ def gotoCommand(self): self.enterRule(localctx, 16, self.RULE_gotoCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 93 + self.state = 96 self.match(tlangParser.T__5) - self.state = 94 + self.state = 97 self.match(tlangParser.T__6) - self.state = 95 + self.state = 98 self.expression(0) - self.state = 96 + self.state = 99 self.match(tlangParser.T__7) - self.state = 97 + self.state = 100 self.expression(0) - self.state = 98 + self.state = 101 self.match(tlangParser.T__8) except RecognitionException as re: localctx.exception = re @@ -685,6 +711,7 @@ def gotoCommand(self): self.exitRule() return localctx + class AssignmentContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -716,11 +743,11 @@ def assignment(self): self.enterRule(localctx, 18, self.RULE_assignment) try: self.enterOuterAlt(localctx, 1) - self.state = 100 + self.state = 103 self.match(tlangParser.VAR) - self.state = 101 + self.state = 104 self.match(tlangParser.T__9) - self.state = 102 + self.state = 105 self.expression(0) except RecognitionException as re: localctx.exception = re @@ -730,6 +757,7 @@ def assignment(self): self.exitRule() return localctx + class MoveCommandContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -762,9 +790,9 @@ def moveCommand(self): self.enterRule(localctx, 20, self.RULE_moveCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 104 + self.state = 107 self.moveOp() - self.state = 105 + self.state = 108 self.expression(0) except RecognitionException as re: localctx.exception = re @@ -774,6 +802,7 @@ def moveCommand(self): self.exitRule() return localctx + class MoveOpContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -800,7 +829,7 @@ def moveOp(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 107 + self.state = 110 _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13))) != 0)): self._errHandler.recoverInline(self) @@ -815,6 +844,7 @@ def moveOp(self): self.exitRule() return localctx + class PenCommandContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -841,7 +871,7 @@ def penCommand(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 109 + self.state = 112 _la = self._input.LA(1) if not(_la==tlangParser.T__14 or _la==tlangParser.T__15): self._errHandler.recoverInline(self) @@ -856,6 +886,7 @@ def penCommand(self): self.exitRule() return localctx + class PauseCommandContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -881,7 +912,7 @@ def pauseCommand(self): self.enterRule(localctx, 26, self.RULE_pauseCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 111 + self.state = 114 self.match(tlangParser.T__16) except RecognitionException as re: localctx.exception = re @@ -891,6 +922,48 @@ def pauseCommand(self): self.exitRule() return localctx + + class AssertionCommandContext(ParserRuleContext): + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + def condition(self): + return self.getTypedRuleContext(tlangParser.ConditionContext,0) + + + def getRuleIndex(self): + return tlangParser.RULE_assertionCommand + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitAssertionCommand" ): + return visitor.visitAssertionCommand(self) + else: + return visitor.visitChildren(self) + + + + + def assertionCommand(self): + + localctx = tlangParser.AssertionCommandContext(self, self._ctx, self.state) + self.enterRule(localctx, 28, self.RULE_assertionCommand) + try: + self.enterOuterAlt(localctx, 1) + self.state = 116 + self.match(tlangParser.T__17) + self.state = 117 + self.condition(0) + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + class ExpressionContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -1012,11 +1085,11 @@ def expression(self, _p:int=0): _parentState = self.state localctx = tlangParser.ExpressionContext(self, self._ctx, _parentState) _prevctx = localctx - _startState = 28 - self.enterRecursionRule(localctx, 28, self.RULE_expression, _p) + _startState = 30 + self.enterRecursionRule(localctx, 30, self.RULE_expression, _p) try: self.enterOuterAlt(localctx, 1) - self.state = 122 + self.state = 128 self._errHandler.sync(self) token = self._input.LA(1) if token in [tlangParser.MINUS]: @@ -1024,34 +1097,34 @@ def expression(self, _p:int=0): self._ctx = localctx _prevctx = localctx - self.state = 114 + self.state = 120 self.unaryArithOp() - self.state = 115 + self.state = 121 self.expression(5) pass elif token in [tlangParser.NUM, tlangParser.VAR]: localctx = tlangParser.ValueExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 117 + self.state = 123 self.value() pass elif token in [tlangParser.T__6]: localctx = tlangParser.ParenExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 118 + self.state = 124 self.match(tlangParser.T__6) - self.state = 119 + self.state = 125 self.expression(0) - self.state = 120 + self.state = 126 self.match(tlangParser.T__8) pass else: raise NoViableAltException(self) self._ctx.stop = self._input.LT(-1) - self.state = 134 + self.state = 140 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,6,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: @@ -1059,37 +1132,37 @@ def expression(self, _p:int=0): if self._parseListeners is not None: self.triggerExitRuleEvent() _prevctx = localctx - self.state = 132 + self.state = 138 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,5,self._ctx) if la_ == 1: localctx = tlangParser.MulExprContext(self, tlangParser.ExpressionContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expression) - self.state = 124 + self.state = 130 if not self.precpred(self._ctx, 4): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 4)") - self.state = 125 + self.state = 131 self.multiplicative() - self.state = 126 + self.state = 132 self.expression(5) pass elif la_ == 2: localctx = tlangParser.AddExprContext(self, tlangParser.ExpressionContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expression) - self.state = 128 + self.state = 134 if not self.precpred(self._ctx, 3): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 3)") - self.state = 129 + self.state = 135 self.additive() - self.state = 130 + self.state = 136 self.expression(4) pass - self.state = 136 + self.state = 142 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,6,self._ctx) @@ -1101,6 +1174,7 @@ def expression(self, _p:int=0): self.unrollRecursionContexts(_parentctx) return localctx + class MultiplicativeContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -1128,11 +1202,11 @@ def accept(self, visitor:ParseTreeVisitor): def multiplicative(self): localctx = tlangParser.MultiplicativeContext(self, self._ctx, self.state) - self.enterRule(localctx, 30, self.RULE_multiplicative) + self.enterRule(localctx, 32, self.RULE_multiplicative) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 137 + self.state = 143 _la = self._input.LA(1) if not(_la==tlangParser.MUL or _la==tlangParser.DIV): self._errHandler.recoverInline(self) @@ -1147,6 +1221,7 @@ def multiplicative(self): self.exitRule() return localctx + class AdditiveContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -1174,11 +1249,11 @@ def accept(self, visitor:ParseTreeVisitor): def additive(self): localctx = tlangParser.AdditiveContext(self, self._ctx, self.state) - self.enterRule(localctx, 32, self.RULE_additive) + self.enterRule(localctx, 34, self.RULE_additive) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 139 + self.state = 145 _la = self._input.LA(1) if not(_la==tlangParser.PLUS or _la==tlangParser.MINUS): self._errHandler.recoverInline(self) @@ -1193,6 +1268,7 @@ def additive(self): self.exitRule() return localctx + class UnaryArithOpContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -1217,10 +1293,10 @@ def accept(self, visitor:ParseTreeVisitor): def unaryArithOp(self): localctx = tlangParser.UnaryArithOpContext(self, self._ctx, self.state) - self.enterRule(localctx, 34, self.RULE_unaryArithOp) + self.enterRule(localctx, 36, self.RULE_unaryArithOp) try: self.enterOuterAlt(localctx, 1) - self.state = 141 + self.state = 147 self.match(tlangParser.MINUS) except RecognitionException as re: localctx.exception = re @@ -1230,6 +1306,7 @@ def unaryArithOp(self): self.exitRule() return localctx + class ConditionContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -1280,46 +1357,46 @@ def condition(self, _p:int=0): _parentState = self.state localctx = tlangParser.ConditionContext(self, self._ctx, _parentState) _prevctx = localctx - _startState = 36 - self.enterRecursionRule(localctx, 36, self.RULE_condition, _p) + _startState = 38 + self.enterRecursionRule(localctx, 38, self.RULE_condition, _p) try: self.enterOuterAlt(localctx, 1) - self.state = 155 + self.state = 161 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,7,self._ctx) if la_ == 1: - self.state = 144 + self.state = 150 self.match(tlangParser.NOT) - self.state = 145 + self.state = 151 self.condition(5) pass elif la_ == 2: - self.state = 146 + self.state = 152 self.expression(0) - self.state = 147 + self.state = 153 self.binCondOp() - self.state = 148 + self.state = 154 self.expression(0) pass elif la_ == 3: - self.state = 150 + self.state = 156 self.match(tlangParser.PENCOND) pass elif la_ == 4: - self.state = 151 + self.state = 157 self.match(tlangParser.T__6) - self.state = 152 + self.state = 158 self.condition(0) - self.state = 153 + self.state = 159 self.match(tlangParser.T__8) pass self._ctx.stop = self._input.LT(-1) - self.state = 163 + self.state = 169 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,8,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: @@ -1329,15 +1406,15 @@ def condition(self, _p:int=0): _prevctx = localctx localctx = tlangParser.ConditionContext(self, _parentctx, _parentState) self.pushNewRecursionContext(localctx, _startState, self.RULE_condition) - self.state = 157 + self.state = 163 if not self.precpred(self._ctx, 3): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 3)") - self.state = 158 + self.state = 164 self.logicOp() - self.state = 159 + self.state = 165 self.condition(4) - self.state = 165 + self.state = 171 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,8,self._ctx) @@ -1349,6 +1426,7 @@ def condition(self, _p:int=0): self.unrollRecursionContexts(_parentctx) return localctx + class BinCondOpContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -1388,11 +1466,11 @@ def accept(self, visitor:ParseTreeVisitor): def binCondOp(self): localctx = tlangParser.BinCondOpContext(self, self._ctx, self.state) - self.enterRule(localctx, 38, self.RULE_binCondOp) + self.enterRule(localctx, 40, self.RULE_binCondOp) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 166 + self.state = 172 _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.LT) | (1 << tlangParser.GT) | (1 << tlangParser.EQ) | (1 << tlangParser.NEQ) | (1 << tlangParser.LTE) | (1 << tlangParser.GTE))) != 0)): self._errHandler.recoverInline(self) @@ -1407,6 +1485,7 @@ def binCondOp(self): self.exitRule() return localctx + class LogicOpContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -1434,11 +1513,11 @@ def accept(self, visitor:ParseTreeVisitor): def logicOp(self): localctx = tlangParser.LogicOpContext(self, self._ctx, self.state) - self.enterRule(localctx, 40, self.RULE_logicOp) + self.enterRule(localctx, 42, self.RULE_logicOp) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 168 + self.state = 174 _la = self._input.LA(1) if not(_la==tlangParser.AND or _la==tlangParser.OR): self._errHandler.recoverInline(self) @@ -1453,6 +1532,7 @@ def logicOp(self): self.exitRule() return localctx + class ValueContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -1480,11 +1560,11 @@ def accept(self, visitor:ParseTreeVisitor): def value(self): localctx = tlangParser.ValueContext(self, self._ctx, self.state) - self.enterRule(localctx, 42, self.RULE_value) + self.enterRule(localctx, 44, self.RULE_value) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 170 + self.state = 176 _la = self._input.LA(1) if not(_la==tlangParser.NUM or _la==tlangParser.VAR): self._errHandler.recoverInline(self) @@ -1504,8 +1584,8 @@ def value(self): def sempred(self, localctx:RuleContext, ruleIndex:int, predIndex:int): if self._predicates == None: self._predicates = dict() - self._predicates[14] = self.expression_sempred - self._predicates[18] = self.condition_sempred + self._predicates[15] = self.expression_sempred + self._predicates[19] = self.condition_sempred pred = self._predicates.get(ruleIndex, None) if pred is None: raise Exception("No predicate with index:" + str(ruleIndex)) diff --git a/ChironCore/turtparse/tlangVisitor.py b/ChironCore/turtparse/tlangVisitor.py index 7ac289a..f027ccb 100644 --- a/ChironCore/turtparse/tlangVisitor.py +++ b/ChironCore/turtparse/tlangVisitor.py @@ -79,6 +79,11 @@ def visitPauseCommand(self, ctx:tlangParser.PauseCommandContext): return self.visitChildren(ctx) + # Visit a parse tree produced by tlangParser#assertionCommand. + def visitAssertionCommand(self, ctx:tlangParser.AssertionCommandContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by tlangParser#unaryExpr. def visitUnaryExpr(self, ctx:tlangParser.UnaryExprContext): return self.visitChildren(ctx) From b19acd89312e153a73ddaa6a45f161a87b4de94d Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Fri, 7 Feb 2025 15:34:29 +0530 Subject: [PATCH 02/53] add conversion to SSA, fix implementation --- ChironCore/ChironAST/ChironAST.py | 15 +- ChironCore/{smtConverter.py => bmc.py} | 0 ChironCore/cfg/ChironCFG.py | 19 ++ ChironCore/chiron.py | 11 +- ChironCore/ssa.py | 247 +++++++++++++++++++++++++ 5 files changed, 289 insertions(+), 3 deletions(-) rename ChironCore/{smtConverter.py => bmc.py} (100%) create mode 100644 ChironCore/ssa.py diff --git a/ChironCore/ChironAST/ChironAST.py b/ChironCore/ChironAST/ChironAST.py index f86c5da..c3155f9 100644 --- a/ChironCore/ChironAST/ChironAST.py +++ b/ChironCore/ChironAST/ChironAST.py @@ -34,7 +34,7 @@ def __init__(self, condition): self.cond = condition def __str__(self): - return self.cond.__str__() + return "assert: " + self.cond.__str__() class MoveCommand(Instruction): def __init__(self, motion, expr): @@ -74,6 +74,19 @@ def __init__(self): def __str__(self): return "pause" +# Phi function for SSA form +class PhiAssignmentCommand(Instruction): + def __init__(self, lvar, varlist): + self.lvar = lvar + self.varlist = varlist + + def __str__(self): + output = self.lvar.__str__() + " = PHI(" + for var in self.varlist: + output += var.__str__() + ", " + return output + ")" + + class Expression(AST): pass diff --git a/ChironCore/smtConverter.py b/ChironCore/bmc.py similarity index 100% rename from ChironCore/smtConverter.py rename to ChironCore/bmc.py diff --git a/ChironCore/cfg/ChironCFG.py b/ChironCore/cfg/ChironCFG.py index f0230be..a5b29d8 100644 --- a/ChironCore/cfg/ChironCFG.py +++ b/ChironCore/cfg/ChironCFG.py @@ -13,6 +13,9 @@ def __init__(self, bbname): def __str__(self): return self.name + + def prepend(self, instruction): + self.instrlist.insert(0, instruction) def append(self, instruction): self.instrlist.append(instruction) @@ -38,6 +41,8 @@ def __init__(self, gname='cfg'): self.nxgraph = nx.DiGraph(name=gname) self.entry = "0" self.exit = "END" + self.df = None + self.idom = None def __iter__(self): return self.nxgraph.__iter__() @@ -87,3 +92,17 @@ def get_edge_label(self, u, v): return edata['label'] if len(edata) else 'T' # TODO: add more methods to expose other methods of the Networkx.DiGraph + def compute_dominance(self): + # find entry node + entry = None + for node in self.nxgraph.nodes(): + if node.name == "START": + entry = node + break + + if entry is None: + raise ValueError("No entry node found") + + self.df = nx.dominance.dominance_frontiers(self.nxgraph, entry) + self.idom = nx.dominance.immediate_dominators(self.nxgraph, entry) + diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 1c29ff2..d2ef39d 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -21,7 +21,8 @@ from fuzzer import * import sExecution as se import cfg.cfgBuilder as cfgB -import smtConverter +import bmc as bmc +import ssa as ssa import submissionDFA as DFASub import submissionAI as AISub from sbflSubmission import computeRanks @@ -403,8 +404,14 @@ def stopTurtle(): if args.bmc: print("Bounded Model Checking..") + print("Converting 3 address code to SSA form...") + cfg = cfgB.buildCFG(ir, "ssa_cfg") + cfg.compute_dominance() + ssaConverter = ssa.SSAConverter(ir, cfg) + ssaIR = ssaConverter.convert() + print("Converting program to SMT-LIB format..") - smt = smtConverter.SMTConverter(ir) + smt = bmc.SMTConverter(ir) smt.convert() smt.solve() diff --git a/ChironCore/ssa.py b/ChironCore/ssa.py new file mode 100644 index 0000000..2b6d709 --- /dev/null +++ b/ChironCore/ssa.py @@ -0,0 +1,247 @@ +import ChironAST.ChironAST as ChironAST +import networkx as nx + +class SSAConverter: + def __init__(self, ir, cfg): + self.ir = ir + self.cfg = cfg + self.globals = set() + self.varBlocks = {} + self.counter = {} + self.stack = {} + + def getVariablesExpr(self, expr): + vars = set() + if isinstance(expr, ChironAST.Var): + vars.add(expr.varname) + elif isinstance(expr, ChironAST.BinArithOp): + vars = vars.union(self.getVariablesExpr(expr.lexpr)) + vars = vars.union(self.getVariablesExpr(expr.rexpr)) + elif isinstance(expr, ChironAST.UnaryArithOp): + vars = vars.union(self.getVariablesExpr(expr.expr)) + elif isinstance(expr, ChironAST.BinCondOp): + vars = vars.union(self.getVariablesExpr(expr.lexpr)) + vars = vars.union(self.getVariablesExpr(expr.rexpr)) + elif isinstance(expr, ChironAST.NOT): + vars = vars.union(self.getVariablesExpr(expr.expr)) + + return vars + + def getVariablesInstr(self, instr): + vars = set() + + if isinstance(instr, ChironAST.AssignmentCommand): + vars.add(instr.lvar.varname) + vars = vars.union(self.getVariablesExpr(instr.rexpr)) + elif isinstance(instr, ChironAST.ConditionCommand): + vars = vars.union(self.getVariablesExpr(instr.cond)) + elif isinstance(instr, ChironAST.AssertCommand): + vars = vars.union(self.getVariablesExpr(instr.cond)) + elif isinstance(instr, ChironAST.MoveCommand): + vars = vars.union(self.getVariablesExpr(instr.expr)) + elif isinstance(instr, ChironAST.GotoCommand): + vars = vars.union(self.getVariablesExpr(instr.xcor)) + vars = vars.union(self.getVariablesExpr(instr.ycor)) + + return vars + + def getGlobals(self): + for node in self.cfg.nodes(): + varkill = set() + for instr, _ in node.instrlist: + if isinstance(instr, ChironAST.AssignmentCommand): + rvars = self.getVariablesExpr(instr.rexpr) + for var in rvars: + if var not in varkill: + self.globals.add(var) + + varkill.add(instr.lvar.varname) + if self.varBlocks.get(instr.lvar.varname) is None: + self.varBlocks[instr.lvar.varname] = set() + self.varBlocks[instr.lvar.varname].add(node) + if isinstance(instr, ChironAST.ConditionCommand): + rvars = self.getVariablesExpr(instr.cond) + for var in rvars: + if var not in varkill: + self.globals.add(var) + if isinstance(instr, ChironAST.AssertCommand): + rvars = self.getVariablesExpr(instr.cond) + for var in rvars: + if var not in varkill: + self.globals.add(var) + if isinstance(instr, ChironAST.MoveCommand): + rvars = self.getVariablesExpr(instr.expr) + for var in rvars: + if var not in varkill: + self.globals.add(var) + if isinstance(instr, ChironAST.GotoCommand): + rvars = self.getVariablesExpr(instr.xcor) + for var in rvars: + if var not in varkill: + self.globals.add(var) + rvars = self.getVariablesExpr(instr.ycor) + for var in rvars: + if var not in varkill: + self.globals.add(var) + + return self.globals + + def addPhiFunctions(self): + for var in self.globals: + if self.varBlocks.get(var) is None: + continue + + worklist = self.varBlocks[var] + while len(worklist) > 0: + node = worklist.pop() + + for block in self.cfg.df[node]: + found = False + for instr, _ in block.instrlist: + if not isinstance(instr, ChironAST.PhiAssignmentCommand): + continue + if instr.lvar.varname == var: + found = True + # instr.varlist.append(ChironAST.Var(var)) + break + + if not found: + block.prepend((ChironAST.PhiAssignmentCommand(ChironAST.Var(var), []), 1)) + worklist.add(block) + + def renameVariables(self): + for var in self.globals: + self.counter[var] = 0 + self.stack[var] = [] + for node in self.cfg.nodes(): + if node.name == "START": + self.rename(node) + + def newName(self, var): + var = var.split("#")[0] + self.stack[var].append(var + "#" + str(self.counter[var])) + self.counter[var] += 1 + return self.stack[var][-1] + + def renameVar(self, expr, oldvar, newvar): + if isinstance(expr, ChironAST.Var): + if expr.varname.split('#')[0] == oldvar: + return ChironAST.Var(newvar) + return expr + if isinstance(expr, ChironAST.BinArithOp): + return ChironAST.BinArithOp(self.renameVar(expr.lexpr, oldvar, newvar), self.renameVar(expr.rexpr, oldvar, newvar), expr.symbol) + if isinstance(expr, ChironAST.UnaryArithOp): + return ChironAST.UnaryArithOp(self.renameVar(expr.expr, oldvar, newvar), expr.symbol) + if isinstance(expr, ChironAST.BinCondOp): + return ChironAST.BinCondOp(self.renameVar(expr.lexpr, oldvar, newvar), self.renameVar(expr.rexpr, oldvar, newvar), expr.symbol) + if isinstance(expr, ChironAST.NOT): + return ChironAST.NOT(self.renameVar(expr.expr, oldvar, newvar)) + return expr + + def rename(self, block): + print("Renaming block: ", block.name) + for instr, _ in block.instrlist: + if isinstance(instr, ChironAST.PhiAssignmentCommand): + print("renaming phi function: ", instr, " to ", end="") + instr.lvar.varname = self.newName(instr.lvar.varname) + print(instr) + + for instr, _ in block.instrlist: + print("Renaming instruction: ", instr, " to ", end="") + if isinstance(instr, ChironAST.AssignmentCommand): + rvars = self.getVariablesExpr(instr.rexpr) + for var in rvars: + var = var.split("#")[0] + if var in self.globals and len(self.stack[var]) > 0: + instr.rexpr = self.renameVar(instr.rexpr, var, self.stack[var][-1]) + instr.lvar.varname = self.newName(instr.lvar.varname) + if isinstance(instr, ChironAST.ConditionCommand): + rvars = self.getVariablesExpr(instr.cond) + for var in rvars: + var = var.split("#")[0] + if var in self.globals and len(self.stack[var]) > 0: + instr.cond = self.renameVar(instr.cond, var, self.stack[var][-1]) + if isinstance(instr, ChironAST.AssertCommand): + rvars = self.getVariablesExpr(instr.cond) + for var in rvars: + var = var.split("#")[0] + if var in self.globals and len(self.stack[var]) > 0: + instr.cond = self.renameVar(instr.cond, var, self.stack[var][-1]) + if isinstance(instr, ChironAST.MoveCommand): + rvars = self.getVariablesExpr(instr.expr) + for var in rvars: + var = var.split("#")[0] + if var in self.globals and len(self.stack[var]) > 0: + instr.expr = self.renameVar(instr.expr, var, self.stack[var][-1]) + if isinstance(instr, ChironAST.GotoCommand): + rvars = self.getVariablesExpr(instr.xcor) + for var in rvars: + var = var.split("#")[0] + if var in self.globals and len(self.stack[var]) > 0: + instr.xcor = self.renameVar(instr.xcor, var, self.stack[var][-1]) + rvars = self.getVariablesExpr(instr.ycor) + for var in rvars: + var = var.split("#")[0] + if var in self.globals and len(self.stack[var]) > 0: + instr.ycor = self.renameVar(instr.ycor, var, self.stack[var][-1]) + + print(instr) + + for succ in self.cfg.successors(block): + print("Filing phi functions for block: ", succ.name) + for instr, _ in succ.instrlist: + if not isinstance(instr, ChironAST.PhiAssignmentCommand): + continue + var = instr.lvar.varname + var = var.split("#")[0] + if len(self.stack[var]) == 0: + continue + + instr.varlist.append(ChironAST.Var(self.stack[var][-1])) + + for succ in self.cfg.successors(block): + # check if succ is next in dominator tree + if self.cfg.idom[succ] == block: + self.rename(succ) + + for instr, _ in block.instrlist: + if isinstance(instr, ChironAST.PhiAssignmentCommand) or isinstance(instr, ChironAST.AssignmentCommand): + var = instr.lvar.varname + var = var.split("#")[0] + self.stack[var].pop() + + + def convert(self): + + self.getGlobals() + print("Globals: ", self.globals) + self.addPhiFunctions() + # dump newly created CFG image + G = self.cfg.nxgraph + labels = {} + for node in self.cfg: + labels[node] = node.name + "\n" + node.label() + + G = nx.relabel_nodes(G, labels) + A = nx.nx_agraph.to_agraph(G) + A.layout('dot') + A.draw('cfg_before_renaming.png') + self.renameVariables() + + + # dump newly created CFG image + G = self.cfg.nxgraph + labels = {} + for node in self.cfg: + labels[node] = node.name + "\n" + node.label() + + G = nx.relabel_nodes(G, labels) + A = nx.nx_agraph.to_agraph(G) + A.layout('dot') + A.draw('cfg_after_renaming.png') + + + + + + From efcfba05c25e8f7aebb6ebaf31b3bc391b079658 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Mon, 10 Feb 2025 20:22:34 +0530 Subject: [PATCH 03/53] revert to assignment BMC --- ChironCore/ChironAST/ChironAST.py | 15 +- ChironCore/cfg/ChironCFG.py | 19 --- ChironCore/chiron.py | 7 - ChironCore/ssa.py | 247 ------------------------------ 4 files changed, 1 insertion(+), 287 deletions(-) delete mode 100644 ChironCore/ssa.py diff --git a/ChironCore/ChironAST/ChironAST.py b/ChironCore/ChironAST/ChironAST.py index c3155f9..f86c5da 100644 --- a/ChironCore/ChironAST/ChironAST.py +++ b/ChironCore/ChironAST/ChironAST.py @@ -34,7 +34,7 @@ def __init__(self, condition): self.cond = condition def __str__(self): - return "assert: " + self.cond.__str__() + return self.cond.__str__() class MoveCommand(Instruction): def __init__(self, motion, expr): @@ -74,19 +74,6 @@ def __init__(self): def __str__(self): return "pause" -# Phi function for SSA form -class PhiAssignmentCommand(Instruction): - def __init__(self, lvar, varlist): - self.lvar = lvar - self.varlist = varlist - - def __str__(self): - output = self.lvar.__str__() + " = PHI(" - for var in self.varlist: - output += var.__str__() + ", " - return output + ")" - - class Expression(AST): pass diff --git a/ChironCore/cfg/ChironCFG.py b/ChironCore/cfg/ChironCFG.py index a5b29d8..f0230be 100644 --- a/ChironCore/cfg/ChironCFG.py +++ b/ChironCore/cfg/ChironCFG.py @@ -13,9 +13,6 @@ def __init__(self, bbname): def __str__(self): return self.name - - def prepend(self, instruction): - self.instrlist.insert(0, instruction) def append(self, instruction): self.instrlist.append(instruction) @@ -41,8 +38,6 @@ def __init__(self, gname='cfg'): self.nxgraph = nx.DiGraph(name=gname) self.entry = "0" self.exit = "END" - self.df = None - self.idom = None def __iter__(self): return self.nxgraph.__iter__() @@ -92,17 +87,3 @@ def get_edge_label(self, u, v): return edata['label'] if len(edata) else 'T' # TODO: add more methods to expose other methods of the Networkx.DiGraph - def compute_dominance(self): - # find entry node - entry = None - for node in self.nxgraph.nodes(): - if node.name == "START": - entry = node - break - - if entry is None: - raise ValueError("No entry node found") - - self.df = nx.dominance.dominance_frontiers(self.nxgraph, entry) - self.idom = nx.dominance.immediate_dominators(self.nxgraph, entry) - diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index d2ef39d..665c415 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -22,7 +22,6 @@ import sExecution as se import cfg.cfgBuilder as cfgB import bmc as bmc -import ssa as ssa import submissionDFA as DFASub import submissionAI as AISub from sbflSubmission import computeRanks @@ -404,12 +403,6 @@ def stopTurtle(): if args.bmc: print("Bounded Model Checking..") - print("Converting 3 address code to SSA form...") - cfg = cfgB.buildCFG(ir, "ssa_cfg") - cfg.compute_dominance() - ssaConverter = ssa.SSAConverter(ir, cfg) - ssaIR = ssaConverter.convert() - print("Converting program to SMT-LIB format..") smt = bmc.SMTConverter(ir) smt.convert() diff --git a/ChironCore/ssa.py b/ChironCore/ssa.py deleted file mode 100644 index 2b6d709..0000000 --- a/ChironCore/ssa.py +++ /dev/null @@ -1,247 +0,0 @@ -import ChironAST.ChironAST as ChironAST -import networkx as nx - -class SSAConverter: - def __init__(self, ir, cfg): - self.ir = ir - self.cfg = cfg - self.globals = set() - self.varBlocks = {} - self.counter = {} - self.stack = {} - - def getVariablesExpr(self, expr): - vars = set() - if isinstance(expr, ChironAST.Var): - vars.add(expr.varname) - elif isinstance(expr, ChironAST.BinArithOp): - vars = vars.union(self.getVariablesExpr(expr.lexpr)) - vars = vars.union(self.getVariablesExpr(expr.rexpr)) - elif isinstance(expr, ChironAST.UnaryArithOp): - vars = vars.union(self.getVariablesExpr(expr.expr)) - elif isinstance(expr, ChironAST.BinCondOp): - vars = vars.union(self.getVariablesExpr(expr.lexpr)) - vars = vars.union(self.getVariablesExpr(expr.rexpr)) - elif isinstance(expr, ChironAST.NOT): - vars = vars.union(self.getVariablesExpr(expr.expr)) - - return vars - - def getVariablesInstr(self, instr): - vars = set() - - if isinstance(instr, ChironAST.AssignmentCommand): - vars.add(instr.lvar.varname) - vars = vars.union(self.getVariablesExpr(instr.rexpr)) - elif isinstance(instr, ChironAST.ConditionCommand): - vars = vars.union(self.getVariablesExpr(instr.cond)) - elif isinstance(instr, ChironAST.AssertCommand): - vars = vars.union(self.getVariablesExpr(instr.cond)) - elif isinstance(instr, ChironAST.MoveCommand): - vars = vars.union(self.getVariablesExpr(instr.expr)) - elif isinstance(instr, ChironAST.GotoCommand): - vars = vars.union(self.getVariablesExpr(instr.xcor)) - vars = vars.union(self.getVariablesExpr(instr.ycor)) - - return vars - - def getGlobals(self): - for node in self.cfg.nodes(): - varkill = set() - for instr, _ in node.instrlist: - if isinstance(instr, ChironAST.AssignmentCommand): - rvars = self.getVariablesExpr(instr.rexpr) - for var in rvars: - if var not in varkill: - self.globals.add(var) - - varkill.add(instr.lvar.varname) - if self.varBlocks.get(instr.lvar.varname) is None: - self.varBlocks[instr.lvar.varname] = set() - self.varBlocks[instr.lvar.varname].add(node) - if isinstance(instr, ChironAST.ConditionCommand): - rvars = self.getVariablesExpr(instr.cond) - for var in rvars: - if var not in varkill: - self.globals.add(var) - if isinstance(instr, ChironAST.AssertCommand): - rvars = self.getVariablesExpr(instr.cond) - for var in rvars: - if var not in varkill: - self.globals.add(var) - if isinstance(instr, ChironAST.MoveCommand): - rvars = self.getVariablesExpr(instr.expr) - for var in rvars: - if var not in varkill: - self.globals.add(var) - if isinstance(instr, ChironAST.GotoCommand): - rvars = self.getVariablesExpr(instr.xcor) - for var in rvars: - if var not in varkill: - self.globals.add(var) - rvars = self.getVariablesExpr(instr.ycor) - for var in rvars: - if var not in varkill: - self.globals.add(var) - - return self.globals - - def addPhiFunctions(self): - for var in self.globals: - if self.varBlocks.get(var) is None: - continue - - worklist = self.varBlocks[var] - while len(worklist) > 0: - node = worklist.pop() - - for block in self.cfg.df[node]: - found = False - for instr, _ in block.instrlist: - if not isinstance(instr, ChironAST.PhiAssignmentCommand): - continue - if instr.lvar.varname == var: - found = True - # instr.varlist.append(ChironAST.Var(var)) - break - - if not found: - block.prepend((ChironAST.PhiAssignmentCommand(ChironAST.Var(var), []), 1)) - worklist.add(block) - - def renameVariables(self): - for var in self.globals: - self.counter[var] = 0 - self.stack[var] = [] - for node in self.cfg.nodes(): - if node.name == "START": - self.rename(node) - - def newName(self, var): - var = var.split("#")[0] - self.stack[var].append(var + "#" + str(self.counter[var])) - self.counter[var] += 1 - return self.stack[var][-1] - - def renameVar(self, expr, oldvar, newvar): - if isinstance(expr, ChironAST.Var): - if expr.varname.split('#')[0] == oldvar: - return ChironAST.Var(newvar) - return expr - if isinstance(expr, ChironAST.BinArithOp): - return ChironAST.BinArithOp(self.renameVar(expr.lexpr, oldvar, newvar), self.renameVar(expr.rexpr, oldvar, newvar), expr.symbol) - if isinstance(expr, ChironAST.UnaryArithOp): - return ChironAST.UnaryArithOp(self.renameVar(expr.expr, oldvar, newvar), expr.symbol) - if isinstance(expr, ChironAST.BinCondOp): - return ChironAST.BinCondOp(self.renameVar(expr.lexpr, oldvar, newvar), self.renameVar(expr.rexpr, oldvar, newvar), expr.symbol) - if isinstance(expr, ChironAST.NOT): - return ChironAST.NOT(self.renameVar(expr.expr, oldvar, newvar)) - return expr - - def rename(self, block): - print("Renaming block: ", block.name) - for instr, _ in block.instrlist: - if isinstance(instr, ChironAST.PhiAssignmentCommand): - print("renaming phi function: ", instr, " to ", end="") - instr.lvar.varname = self.newName(instr.lvar.varname) - print(instr) - - for instr, _ in block.instrlist: - print("Renaming instruction: ", instr, " to ", end="") - if isinstance(instr, ChironAST.AssignmentCommand): - rvars = self.getVariablesExpr(instr.rexpr) - for var in rvars: - var = var.split("#")[0] - if var in self.globals and len(self.stack[var]) > 0: - instr.rexpr = self.renameVar(instr.rexpr, var, self.stack[var][-1]) - instr.lvar.varname = self.newName(instr.lvar.varname) - if isinstance(instr, ChironAST.ConditionCommand): - rvars = self.getVariablesExpr(instr.cond) - for var in rvars: - var = var.split("#")[0] - if var in self.globals and len(self.stack[var]) > 0: - instr.cond = self.renameVar(instr.cond, var, self.stack[var][-1]) - if isinstance(instr, ChironAST.AssertCommand): - rvars = self.getVariablesExpr(instr.cond) - for var in rvars: - var = var.split("#")[0] - if var in self.globals and len(self.stack[var]) > 0: - instr.cond = self.renameVar(instr.cond, var, self.stack[var][-1]) - if isinstance(instr, ChironAST.MoveCommand): - rvars = self.getVariablesExpr(instr.expr) - for var in rvars: - var = var.split("#")[0] - if var in self.globals and len(self.stack[var]) > 0: - instr.expr = self.renameVar(instr.expr, var, self.stack[var][-1]) - if isinstance(instr, ChironAST.GotoCommand): - rvars = self.getVariablesExpr(instr.xcor) - for var in rvars: - var = var.split("#")[0] - if var in self.globals and len(self.stack[var]) > 0: - instr.xcor = self.renameVar(instr.xcor, var, self.stack[var][-1]) - rvars = self.getVariablesExpr(instr.ycor) - for var in rvars: - var = var.split("#")[0] - if var in self.globals and len(self.stack[var]) > 0: - instr.ycor = self.renameVar(instr.ycor, var, self.stack[var][-1]) - - print(instr) - - for succ in self.cfg.successors(block): - print("Filing phi functions for block: ", succ.name) - for instr, _ in succ.instrlist: - if not isinstance(instr, ChironAST.PhiAssignmentCommand): - continue - var = instr.lvar.varname - var = var.split("#")[0] - if len(self.stack[var]) == 0: - continue - - instr.varlist.append(ChironAST.Var(self.stack[var][-1])) - - for succ in self.cfg.successors(block): - # check if succ is next in dominator tree - if self.cfg.idom[succ] == block: - self.rename(succ) - - for instr, _ in block.instrlist: - if isinstance(instr, ChironAST.PhiAssignmentCommand) or isinstance(instr, ChironAST.AssignmentCommand): - var = instr.lvar.varname - var = var.split("#")[0] - self.stack[var].pop() - - - def convert(self): - - self.getGlobals() - print("Globals: ", self.globals) - self.addPhiFunctions() - # dump newly created CFG image - G = self.cfg.nxgraph - labels = {} - for node in self.cfg: - labels[node] = node.name + "\n" + node.label() - - G = nx.relabel_nodes(G, labels) - A = nx.nx_agraph.to_agraph(G) - A.layout('dot') - A.draw('cfg_before_renaming.png') - self.renameVariables() - - - # dump newly created CFG image - G = self.cfg.nxgraph - labels = {} - for node in self.cfg: - labels[node] = node.name + "\n" + node.label() - - G = nx.relabel_nodes(G, labels) - A = nx.nx_agraph.to_agraph(G) - A.layout('dot') - A.draw('cfg_after_renaming.png') - - - - - - From 8a478d4807acd72ff7014b3ff0712f54fe941ba5 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Mon, 10 Feb 2025 20:24:26 +0530 Subject: [PATCH 04/53] update .gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3e9dcb3..d42b920 100644 --- a/.gitignore +++ b/.gitignore @@ -162,4 +162,6 @@ cython_debug/ # Extra files and hidden folder. testcases/ -build/ \ No newline at end of file +build/ + +*.png \ No newline at end of file From e8110c7473bc01bc90875f05e9d759420760d685 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 11 Feb 2025 00:17:34 +0530 Subject: [PATCH 05/53] converted ir into 3ac --- ChironCore/ChironAST/ChironTAC.py | 194 ++++++++++++++++ ChironCore/bmc.py | 2 +- ChironCore/chiron.py | 17 +- ChironCore/example/assignmentBMC.tl | 5 +- ChironCore/example/move.tl | 9 + ChironCore/irhandler.py | 346 +++++++++++++++++++++++++++- 6 files changed, 560 insertions(+), 13 deletions(-) create mode 100644 ChironCore/ChironAST/ChironTAC.py create mode 100644 ChironCore/example/move.tl diff --git a/ChironCore/ChironAST/ChironTAC.py b/ChironCore/ChironAST/ChironTAC.py new file mode 100644 index 0000000..6779036 --- /dev/null +++ b/ChironCore/ChironAST/ChironTAC.py @@ -0,0 +1,194 @@ +# Three Address Code (TAC) generation for Chiron +class TAC(object): + pass + +# Instruction Classes +class TAC_Instruction(TAC): + pass + +class TAC_AssignmentCommand(TAC_Instruction): + def __init__(self, lvar, rvar1, rvar2, op): + self.lvar = lvar + self.rvar1 = rvar1 + self.rvar2 = rvar2 + self.op = op + + def __str__(self): + return self.lvar.__str__() + " = " + self.rvar1.__str__() + " " + self.op + " " + self.rvar2.__str__() + +class TAC_ConditionCommand(TAC_Instruction): + def __init__(self, condition): + self.cond = condition + + def __str__(self): + return "BRANCH: " + self.cond.__str__() + +class TAC_AssertCommand(TAC_Instruction): + def __init__(self, condition): + self.cond = condition + + def __str__(self): + return "ASSERT: " + self.cond.__str__() + +class TAC_MoveCommand(TAC_Instruction): + def __init__(self, motion, var): + self.direction = motion + self.var = var + + def __str__(self): + return "MOVE: " + self.direction + " " + self.var.__str__() + +class TAC_PenCommand(TAC_Instruction): + def __init__(self, penstat): + self.status = penstat + + def __str__(self): + return "PEN: " + self.status + +class TAC_GotoCommand(TAC_Instruction): + def __init__(self, x, y): + self.xcor = x + self.ycor = y + + def __str__(self): + return "goto " + str(self.xcor) + " " + str(self.ycor) + +class TAC_NoOpCommand(TAC_Instruction): + def __str__(self): + return "NoOp" + +class TAC_PauseCommand(TAC_Instruction): + def __str__(self): + return "Pause" + + +class TAC_Expression(TAC): + pass +# -- Arithmetic Expressions ------------------------------------------ +class TAC_ArithExpr(TAC_Expression): + pass + +class TAC_BinArithOp(TAC_ArithExpr): + def __init__(self, lvar, rvar, op): + self.lvar = lvar + self.rvar = rvar + self.op = op + + def __str__(self): + return self.lvar.__str__() + " " + self.op + " " + self.rvar.__str__() + +class TAC_Sum(TAC_BinArithOp): + def __init__(self, lvar, rvar): + TAC_BinArithOp.__init__(self, lvar, rvar, "+") + +class TAC_Sub(TAC_BinArithOp): + def __init__(self, lvar, rvar): + TAC_BinArithOp.__init__(self, lvar, rvar, "-") + +class TAC_Mul(TAC_BinArithOp): + def __init__(self, lvar, rvar): + TAC_BinArithOp.__init__(self, lvar, rvar, "*") + +class TAC_Div(TAC_BinArithOp): + def __init__(self, lvar, rvar): + TAC_BinArithOp.__init__(self, lvar, rvar, "/") + + +class TAC_UnaryArithOp(TAC_ArithExpr): + def __init__(self, op, var): + self.op = op + self.var = var + + def __str__(self): + return self.op + " " + self.var.__str__() + +class TAC_UMinus(TAC_UnaryArithOp): + def __init__(self, var): + TAC_UnaryArithOp.__init__(self, "-", var) + + +# -- Boolean Expressions -------------------------------------------- +class TAC_BoolExpr(TAC_Expression): + pass + +class TAC_BinBoolOp(TAC_BoolExpr): + def __init__(self, lvar, rvar, op): + self.lvar = lvar + self.rvar = rvar + self.op = op + + def __str__(self): + return self.lvar.__str__() + " " + self.op + " " + self.rvar.__str__() + +class TAC_And(TAC_BinBoolOp): + def __init__(self, lvar, rvar): + TAC_BinBoolOp.__init__(self, lvar, rvar, "and") + +class TAC_Or(TAC_BinBoolOp): + def __init__(self, lvar, rvar): + TAC_BinBoolOp.__init__(self, lvar, rvar, "or") + +class TAC_LT(TAC_BinBoolOp): + def __init__(self, lvar, rvar): + TAC_BinBoolOp.__init__(self, lvar, rvar, "<") + +class TAC_GT(TAC_BinBoolOp): + def __init__(self, lvar, rvar): + TAC_BinBoolOp.__init__(self, lvar, rvar, ">") + +class TAC_LTE(TAC_BinBoolOp): + def __init__(self, lvar, rvar): + TAC_BinBoolOp.__init__(self, lvar, rvar, "<=") + +class TAC_GTE(TAC_BinBoolOp): + def __init__(self, lvar, rvar): + TAC_BinBoolOp.__init__(self, lvar, rvar, ">=") + +class TAC_EQ(TAC_BinBoolOp): + def __init__(self, lvar, rvar): + TAC_BinBoolOp.__init__(self, lvar, rvar, "==") + +class TAC_NEQ(TAC_BinBoolOp): + def __init__(self, lvar, rvar): + TAC_BinBoolOp.__init__(self, lvar, rvar, "!=") + +class TAC_Not(TAC_BoolExpr): + def __init__(self, var): + self.var = var + + def __str__(self): + return "not " + self.var.__str__() + +class TAC_PenStatus(TAC_Expression): + def __str__(self): + return "penstatus" + +class TAC_BoolTrue(TAC_Expression): + def __str__(self): + return "true" + +class TAC_BoolFalse(TAC_Expression): + def __str__(self): + return "false" + +# -- Value Expressions ---------------------------------------------- +class TAC_Value(TAC_Expression): + pass + +class TAC_Num(TAC_Value): + def __init__(self, value): + self.value = value + + def __str__(self): + return str(self.value) + +class TAC_Var(TAC_Value): + def __init__(self, name): + self.name = name + + def __str__(self): + return self.name + +class TAC_Unused(TAC_Value): + def __str__(self): + return "" diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 630a220..cb8c4e8 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -57,7 +57,7 @@ def parseExpression(node): return z3.Int(node.varname) -class SMTConverter: +class BMC: def __init__(self, ir): self.solver = z3.Solver() self.ir = ir diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 665c415..b143389 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -200,7 +200,7 @@ def stopTurtle(): cmdparser.add_argument( "-bmc", "--bmc", - action="store_true", + type=str, help="Run Bounded Model Checking on a Chiron Program.", ) @@ -403,9 +403,14 @@ def stopTurtle(): if args.bmc: print("Bounded Model Checking..") - print("Converting program to SMT-LIB format..") - smt = bmc.SMTConverter(ir) - smt.convert() - smt.solve() + print("Converting program to 3 address code...") + print("input statement: ", args.bmc) + tacGen = TACGenerator(ir) + tacGen.generateTAC() + tacGen.printTAC() + # print("Converting program to SMT-LIB format..") + # smt = bmc.SMTConverter(ir) + # smt.convert() + # smt.solve() - print("DONE..") + # print("DONE..") diff --git a/ChironCore/example/assignmentBMC.tl b/ChironCore/example/assignmentBMC.tl index fa1d6a7..5532ccd 100644 --- a/ChironCore/example/assignmentBMC.tl +++ b/ChironCore/example/assignmentBMC.tl @@ -1,6 +1,7 @@ // inputs: :x, :y, :z -:t = :x + 2*:y +:t = :x + 2*:y + 3*:z + :x * :w * :u +:z = :x + :w -assert (:x + 100 < :y) && (:x + 200 > :y) && !(:x >= 0) && (:x * :y < -:x) && (:t > 0) \ No newline at end of file +// assert (:x + 100 < :y) && (:x + 200 > :y) && !(:x >= 0) && (:x * :y < -:x) && (:t > 0) \ No newline at end of file diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl new file mode 100644 index 0000000..c37ac08 --- /dev/null +++ b/ChironCore/example/move.tl @@ -0,0 +1,9 @@ +if (:x > 1) [ + :x = :x + 10 +] else [ + :x = :x + 5 +] + +goto (20, :y + 10) + + diff --git a/ChironCore/irhandler.py b/ChironCore/irhandler.py index 56e60de..f48c6df 100644 --- a/ChironCore/irhandler.py +++ b/ChironCore/irhandler.py @@ -6,6 +6,7 @@ from turtparse.tlangLexer import tlangLexer from ChironAST import ChironAST +from ChironAST import ChironTAC def getParseTree(progfl): @@ -123,10 +124,347 @@ def removeInstruction(self, stmtList, pos): def pretty_print(self, irList): """ - We pass a IR list and print it here. + We pass a IR list and print it here. """ print("\n========== Chiron IR ==========\n") - print("The first label before the opcode name represents the IR index or label \non the control flow graph for that node.\n") - print("The number after the opcode name represents the jump offset \nrelative to that statement.\n") + print( + "The first label before the opcode name represents the IR index or label \non the control flow graph for that node.\n" + ) + print( + "The number after the opcode name represents the jump offset \nrelative to that statement.\n" + ) for idx, item in enumerate(irList): - print(f"[L{idx}]".rjust(5), item[0], f"[{item[1]}]") \ No newline at end of file + print(f"[L{idx}]".rjust(5), item[0], f"[{item[1]}]") + + +""" +Class for converting IR to Three Address Code (TAC) +""" + + +class TACGenerator: + def __init__(self, ir): + self.ir = ir + self.tac = [] + self.tempCount = 0 + self.branchCount = 0 + self.assertCount = 0 + self.moveCount = 0 + self.gotoCount = 0 + self.ast_to_tac_line = {} + self.line = 0 + + def parseExpresssion(self, expr, dest): + """ + Parse the expression and return the TAC for the expression. + """ + if isinstance(expr, ChironAST.BinArithOp): + left = None + right = None + if isinstance(expr.lexpr, ChironAST.Num): + left = ChironTAC.TAC_Num(expr.lexpr.val) + elif isinstance(expr.lexpr, ChironAST.Var): + left = ChironTAC.TAC_Var(expr.lexpr.varname) + else: + temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + self.tempCount += 1 + left = temp + self.parseExpresssion(expr.lexpr, temp) + + if isinstance(expr.rexpr, ChironAST.Num): + right = ChironTAC.TAC_Num(expr.rexpr.val) + elif isinstance(expr.rexpr, ChironAST.Var): + right = ChironTAC.TAC_Var(expr.rexpr.varname) + else: + temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + self.tempCount += 1 + right = temp + self.parseExpresssion(expr.rexpr, temp) + + self.line += 1 + self.tac.append( + (ChironTAC.TAC_AssignmentCommand(dest, left, right, expr.symbol), 1) + ) + elif isinstance(expr, ChironAST.UMinus): + if isinstance(expr.expr, ChironAST.Num): + self.line += 1 + self.tac.append( + ( + ChironTAC.TAC_AssignmentCommand( + dest, + ChironTAC.TAC_Num(0), + ChironTAC.TAC_Num(expr.expr.val), + "-", + ) + ), + 1, + ) + elif isinstance(expr.expr, ChironAST.Var): + self.line += 1 + self.tac.append( + ( + ChironTAC.TAC_AssignmentCommand( + dest, + ChironTAC.TAC_Num(0), + ChironTAC.TAC_Var(expr.expr.varname), + "-", + ) + ), + 1, + ) + else: + temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + self.tempCount += 1 + self.parseExpresssion(expr.expr, temp) + self.line += 1 + self.tac.append( + ( + ChironTAC.TAC_AssignmentCommand( + dest, ChironTAC.TAC_Num(0), temp, "-" + ), + 1, + ) + ) + elif isinstance(expr, ChironAST.BinCondOp) and not ( + isinstance(expr, ChironAST.AND) + or isinstance(expr, ChironAST.OR) + or isinstance(expr, ChironAST.NOT) + ): + left = None + right = None + if isinstance(expr.lexpr, ChironAST.Num): + left = ChironTAC.TAC_Num(expr.lexpr.val) + elif isinstance(expr.lexpr, ChironAST.Var): + left = ChironTAC.TAC_Var(expr.lexpr.varname) + else: + temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + self.tempCount += 1 + left = temp + self.parseExpresssion(expr.lexpr, temp) + + if isinstance(expr.rexpr, ChironAST.Num): + right = ChironTAC.TAC_Num(expr.rexpr.val) + elif isinstance(expr.rexpr, ChironAST.Var): + right = ChironTAC.TAC_Var(expr.rexpr.varname) + else: + temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + self.tempCount += 1 + right = temp + self.parseExpresssion(expr.rexpr, temp) + + self.line += 1 + self.tac.append( + (ChironTAC.TAC_AssignmentCommand(dest, left, right, expr.symbol), 1) + ) + elif isinstance(expr, ChironAST.AND) or isinstance(expr, ChironAST.OR): + left = None + right = None + if isinstance(expr.lexpr, ChironAST.BoolTrue): + left = ChironTAC.TAC_BoolTrue() + elif isinstance(expr.lexpr, ChironAST.BoolFalse): + left = ChironTAC.TAC_BoolFalse() + elif isinstance(expr.lexpr, ChironAST.Var): + left = ChironTAC.TAC_Var(expr.lexpr.varname) + else: + temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + self.tempCount += 1 + left = temp + self.parseExpresssion(expr.lexpr, temp) + + if isinstance(expr.rexpr, ChironAST.BoolTrue): + right = ChironTAC.TAC_BoolTrue() + elif isinstance(expr.rexpr, ChironAST.BoolFalse): + right = ChironTAC.TAC_BoolFalse() + elif isinstance(expr.rexpr, ChironAST.Var): + right = ChironTAC.TAC_Var(expr.rexpr.varname) + else: + temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + self.tempCount += 1 + right = temp + self.parseExpresssion(expr.rexpr, temp) + + self.line += 1 + self.tac.append( + (ChironTAC.TAC_AssignmentCommand(dest, left, right, expr.symbol), 1) + ) + elif isinstance(expr, ChironAST.NOT): + if isinstance(expr.expr, ChironAST.BoolTrue): + self.line += 1 + self.tac.append( + ( + ChironTAC.TAC_AssignmentCommand( + dest, + ChironTAC.TAC_Unused(), + ChironTAC.TAC_BoolTrue(), + "not", + ), + 1, + ) + ) + elif isinstance(expr.expr, ChironAST.BoolFalse): + self.line += 1 + self.tac.append( + ( + ChironTAC.TAC_AssignmentCommand( + dest, + ChironTAC.TAC_Unused(), + ChironTAC.TAC_BoolFalse(), + "not", + ), + 1, + ) + ) + elif isinstance(expr.expr, ChironAST.Var): + self.line += 1 + self.tac.append( + ( + ChironTAC.TAC_AssignmentCommand( + dest, + ChironTAC.TAC_Unused(), + ChironTAC.TAC_Var(expr.expr.varname), + "not", + ), + 1, + ) + ) + else: + temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + self.tempCount += 1 + self.parseExpresssion(expr.expr, temp) + self.line += 1 + self.tac.append( + (ChironTAC.TAC_AssignmentCommand(dest, None, temp, "not"), 1) + ) + elif isinstance(expr, ChironAST.Var): + self.line += 1 + self.tac.append( + ( + ChironTAC.TAC_AssignmentCommand( + dest, ChironTAC.TAC_Num(0), ChironTAC.TAC_Var(expr.varname), "+" + ), + 1, + ) + ) + elif isinstance(expr, ChironAST.Num): + self.line += 1 + self.tac.append( + ( + ChironTAC.TAC_AssignmentCommand( + dest, ChironTAC.TAC_Num(0), ChironTAC.TAC_Num(expr.val), "+" + ), + 1, + ) + ) + elif isinstance(expr, ChironAST.BoolTrue): + self.line += 1 + self.tac.append( + ( + ChironTAC.TAC_AssignmentCommand( + dest, ChironTAC.TAC_Unused(), ChironTAC.TAC_BoolTrue(), "" + ), + 1, + ) + ) + elif isinstance(expr, ChironAST.BoolFalse): + self.line += 1 + self.tac.append( + ( + ChironTAC.TAC_AssignmentCommand( + dest, ChironTAC.TAC_Unused(), ChironTAC.TAC_BoolFalse(), "" + ), + 1, + ) + ) + else: + raise NotImplementedError( + "Unknown expression: %s, %s." % (type(expr), expr) + ) + + def generateTAC(self): + line_number = 0 + for stmt, tgt in self.ir: + self.ast_to_tac_line[line_number] = self.line + line_number += 1 + + if isinstance(stmt, ChironAST.AssignmentCommand): + self.parseExpresssion(stmt.rexpr, ChironTAC.TAC_Var(stmt.lvar.varname)) + + elif isinstance(stmt, ChironAST.ConditionCommand): + branchvar = None + if isinstance(stmt.cond, ChironAST.BoolTrue): + branchvar = ChironTAC.TAC_BoolTrue() + elif isinstance(stmt.cond, ChironAST.BoolFalse): + branchvar = ChironTAC.TAC_BoolFalse() + elif isinstance(stmt.cond, ChironAST.Var): + branchvar = ChironTAC.TAC_Var(stmt.cond.varname) + else: + branchvar = ChironTAC.TAC_Var(f"__branch_{self.branchCount}") + self.branchCount += 1 + self.parseExpresssion(stmt.cond, branchvar) + newtgt = line_number - 1 + tgt # Adjusted later + self.line += 1 + self.tac.append((ChironTAC.TAC_ConditionCommand(branchvar), newtgt)) + elif isinstance(stmt, ChironAST.AssertCommand): + assertvar = ChironTAC.TAC_Var(f"__assert_{self.assertCount}") + self.assertCount += 1 + self.parseExpresssion(stmt.cond, assertvar) + self.line += 1 + self.tac.append((ChironTAC.TAC_AssertCommand(assertvar), 1)) + elif isinstance(stmt, ChironAST.MoveCommand): + movevar = None + if isinstance(stmt.expr, ChironAST.Num): + movevar = ChironTAC.TAC_Num(stmt.expr.val) + elif isinstance(stmt.expr, ChironAST.Var): + movevar = ChironTAC.TAC_Var(stmt.expr.varname) + else: + movevar = ChironTAC.TAC_Var(f"__move_{self.moveCount}") + self.moveCount += 1 + self.parseExpresssion(stmt.expr, movevar) + self.line += 1 + self.tac.append((ChironTAC.TAC_MoveCommand(stmt.direction, movevar), 1)) + elif isinstance(stmt, ChironAST.PenCommand): + self.line += 1 + self.tac.append((ChironTAC.TAC_PenCommand(stmt.status), 1)) + elif isinstance(stmt, ChironAST.GotoCommand): + xvar = None + yvar = None + if isinstance(stmt.xcor, ChironAST.Num): + xvar = ChironTAC.TAC_Num(stmt.xcor.val) + elif isinstance(stmt.xcor, ChironAST.Var): + xvar = ChironTAC.TAC_Var(stmt.xcor.varname) + else: + xvar = ChironTAC.TAC_Var(f"__x_{self.gotoCount}") + self.gotoCount += 1 + self.parseExpresssion(stmt.xcor, xvar) + if isinstance(stmt.ycor, ChironAST.Num): + yvar = ChironTAC.TAC_Num(stmt.ycor.val) + elif isinstance(stmt.ycor, ChironAST.Var): + yvar = ChironTAC.TAC_Var(stmt.ycor.varname) + else: + yvar = ChironTAC.TAC_Var(f"__y_{self.gotoCount}") + self.gotoCount += 1 + self.parseExpresssion(stmt.ycor, yvar) + self.line += 1 + self.tac.append((ChironTAC.TAC_GotoCommand(xvar, yvar), 1)) + elif isinstance(stmt, ChironAST.NoOpCommand): + self.line += 1 + self.tac.append((ChironTAC.TAC_NoOpCommand(), 1)) + elif isinstance(stmt, ChironAST.PauseCommand): + self.line += 1 + self.tac.append((ChironTAC.TAC_PauseCommand(), 1)) + else: + raise NotImplementedError( + "Unknown instruction: %s, %s." % (type(stmt), stmt) + ) + + self.ast_to_tac_line[line_number] = self.line + + for i in range(len(self.tac)): + stmt, tgt = self.tac[i] + if isinstance(stmt, ChironTAC.TAC_ConditionCommand): + newtgt = self.ast_to_tac_line[tgt] - i + self.tac[i] = (stmt, newtgt) + + def printTAC(self): + for (stmt, tgt), line in zip(self.tac, range(len(self.tac))): + print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") From 978b285c21d4b9ebff53c08e5b7c5ca46e61b236 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 11 Feb 2025 15:24:19 +0530 Subject: [PATCH 06/53] modify cfg builder to include TAC instructions --- ChironCore/cfg/cfgBuilder.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ChironCore/cfg/cfgBuilder.py b/ChironCore/cfg/cfgBuilder.py index 1bc5460..9e0a48b 100644 --- a/ChironCore/cfg/cfgBuilder.py +++ b/ChironCore/cfg/cfgBuilder.py @@ -5,6 +5,7 @@ from cfg.ChironCFG import * import ChironAST.ChironAST as ChironAST +import ChironAST.ChironTAC as ChironTAC import networkx as nx from networkx.drawing.nx_agraph import to_agraph @@ -28,7 +29,7 @@ def buildCFG(ir, cfgName="", isSingle=False): # finding leaders in the IR for idx, item in enumerate(ir): #print(idx, item) - if isinstance(item[0], ChironAST.ConditionCommand) or isSingle: + if isinstance(item[0], ChironAST.ConditionCommand) or isinstance(item[0], ChironTAC.TAC_ConditionCommand) or isSingle: # updating then branch meta data if idx + 1 < len(ir) and (idx + 1 not in leaderIndices): leaderIndices.add(idx + 1) @@ -37,7 +38,7 @@ def buildCFG(ir, cfgName="", isSingle=False): indices2LeadersMap[idx + 1] = thenBranchLeader if idx + item[1] < len(ir) and (idx + item[1] - not in leaderIndices) and (isinstance(item[0], ChironAST.ConditionCommand)): + not in leaderIndices) and (isinstance(item[0], ChironAST.ConditionCommand) or isinstance(item[0], ChironTAC.TAC_ConditionCommand)): leaderIndices.add(idx + item[1]) elseBranchLeader = BasicBlock(str(idx + item[1])) leader2IndicesMap[elseBranchLeader] = idx + item[1] @@ -66,13 +67,13 @@ def buildCFG(ir, cfgName="", isSingle=False): irIdx = (node.instrlist[-1])[1] lastInstr = (node.instrlist[-1])[0] # print (irIdx, lastInstr, type(lastInstr), isinstance(lastInstr, ChironAST.ConditionCommand)) - if isinstance(lastInstr, ChironAST.ConditionCommand): - if not isinstance(lastInstr.cond, ChironAST.BoolFalse): + if isinstance(lastInstr, ChironAST.ConditionCommand) or isinstance(lastInstr, ChironTAC.TAC_ConditionCommand): + if not (isinstance(lastInstr.cond, ChironAST.BoolFalse) or isinstance(lastInstr.cond, ChironTAC.TAC_BoolFalse)): thenIdx = irIdx + 1 if (irIdx + 1 < len(ir)) else len(ir) thenBB = indices2LeadersMap[thenIdx] cfg.add_edge(node, thenBB, label='Cond_True', color='green') - if not isinstance(lastInstr.cond, ChironAST.BoolTrue): + if not (isinstance(lastInstr.cond, ChironAST.BoolTrue) or isinstance(lastInstr.cond, ChironTAC.TAC_BoolTrue)): elseIdx = irIdx + ir[irIdx][1] if (irIdx + ir[irIdx][1] < len(ir)) else len(ir) elseBB = indices2LeadersMap[elseIdx] cfg.add_edge(node, elseBB, label='Cond_False', color='red') From c18cd00b2aadd9b6bc84f3e39867f377bf2be269 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Thu, 13 Feb 2025 14:46:24 +0530 Subject: [PATCH 07/53] modify cfg,bmc for TAC format --- ChironCore/bmc.py | 168 ++++++++++++++++++---------- ChironCore/chiron.py | 11 +- ChironCore/example/assignmentBMC.tl | 2 +- ChironCore/irhandler.py | 36 +++--- 4 files changed, 137 insertions(+), 80 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index cb8c4e8..8e2ab50 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -1,60 +1,91 @@ ''' -This file is used to convert the Kachua IR to SMT-LIB format. +This file is used to convert the 3 address code IR to SMT-LIB format. ''' import z3 -from ChironAST import ChironAST +from ChironAST import ChironTAC -def parseExpression(node): - if isinstance(node, ChironAST.ArithExpr): - if isinstance(node, ChironAST.BinArithOp): - left = parseExpression(node.lexpr) - right = parseExpression(node.rexpr) - if isinstance(node, ChironAST.Sum): - return left.__add__(right) - elif isinstance(node, ChironAST.Diff): - return left.__sub__(right) - elif isinstance(node, ChironAST.Mult): - return left.__mul__(right) - elif isinstance(node, ChironAST.Div): - return left.__div__(right) - elif isinstance(node, ChironAST.UnaryArithOp): - if isinstance(node, ChironAST.UMinus): - left = parseExpression(node.expr) - return left.__neg__() +# def parseExpression(node): +# if isinstance(node, ChironTAC.TAC_ArithExpr): +# if isinstance(node, ChironTAC.TAC_BinArithOp): +# if isinstance(node.lvar, ChironTAC.TAC_Num): +# left = z3.IntVal(node.lvar.value) +# else: +# left = z3.Int(node.lvar.name) + +# if isinstance(node.rvar, ChironTAC.TAC_Num): +# right = z3.IntVal(node.rvar.value) +# else: +# right = z3.Int(node.rvar.name) + +# if isinstance(node, ChironTAC.TAC_Sum): +# return left.__add__(right) +# elif isinstance(node, ChironTAC.TAC_Diff): +# return left.__sub__(right) +# elif isinstance(node, ChironTAC.TAC_Mult): +# return left.__mul__(right) +# elif isinstance(node, ChironTAC.TAC_Div): +# return left.__div__(right) + +# elif isinstance(node, ChironTAC.TAC_UnaryArithOp): +# if isinstance(node, ChironTAC.TAC_UMinus): +# if isinstance(node.lvar, ChironTAC.TAC_Num): +# left = z3.IntVal(node.lvar.value) +# else: +# left = z3.Int(node.lvar.name) + +# return left.__neg__() - elif isinstance(node, ChironAST.BoolExpr): - if isinstance(node, ChironAST.BinCondOp): - left = parseExpression(node.lexpr) - right = parseExpression(node.rexpr) - if isinstance(node, ChironAST.AND): - return left.__and__(right) - elif isinstance(node, ChironAST.OR): - return left.__or__(right) - elif isinstance(node, ChironAST.LT): - return left.__lt__(right) - elif isinstance(node, ChironAST.GT): - return left.__gt__(right) - elif isinstance(node, ChironAST.LTE): - return left.__le__(right) - elif isinstance(node, ChironAST.GTE): - return left.__ge__(right) - elif isinstance(node, ChironAST.EQ): - return left.__eq__(right) - elif isinstance(node, ChironAST.NEQ): - return left.__ne__(right) - elif isinstance(node, ChironAST.NOT): - left = parseExpression(node.expr) - return left.__invert__() - elif isinstance(node, ChironAST.BoolTrue): - return z3.BoolVal(True) - elif isinstance(node, ChironAST.BoolFalse): - return z3.BoolVal(False) +# elif isinstance(node, ChironTAC.TAC_BoolExpr): +# if isinstance(node, ChironTAC.TAC_BinBoolOp): +# if isinstance(node.lvar, ChironTAC.TAC_BoolFalse): +# left = z3.BoolVal(False) +# elif isinstance(node.lvar, ChironTAC.TAC_BoolTrue): +# left = z3.BoolVal(True) +# else: +# left = z3.Bool(node.lvar.name) + +# if isinstance(node.rvar, ChironTAC.TAC_BoolFalse): +# right = z3.BoolVal(False) +# elif isinstance(node.rvar, ChironTAC.TAC_BoolTrue): +# right = z3.BoolVal(True) +# else: +# right = z3.Bool(node.rvar.name) + +# if isinstance(node, ChironTAC.TAC_And): +# return left.__and__(right) +# elif isinstance(node, ChironTAC.TAC_Or): +# return left.__or__(right) +# elif isinstance(node, ChironTAC.TAC_LT): +# return left.__lt__(right) +# elif isinstance(node, ChironTAC.TAC_GT): +# return left.__gt__(right) +# elif isinstance(node, ChironTAC.TAC_LTE): +# return left.__le__(right) +# elif isinstance(node, ChironTAC.TAC_GTE): +# return left.__ge__(right) +# elif isinstance(node, ChironTAC.TAC_EQ): +# return left.__eq__(right) +# elif isinstance(node, ChironTAC.TAC_NEQ): +# return left.__ne__(right) +# elif isinstance(node, ChironTAC.TAC_Not): +# if isinstance(node.var, ChironTAC.TAC_BoolFalse): +# left = z3.BoolVal(False) +# elif isinstance(node.var, ChironTAC.TAC_BoolTrue): +# left = z3.BoolVal(True) +# else: +# left = z3.Bool(node.var.name) + +# return left.__invert__() +# elif isinstance(node, ChironTAC.BoolTrue): +# return z3.BoolVal(True) +# elif isinstance(node, ChironTAC.BoolFalse): +# return z3.BoolVal(False) - else: - if isinstance(node, ChironAST.Num): - return z3.IntVal(node.val) - elif isinstance(node, ChironAST.Var): - return z3.Int(node.varname) +# else: +# if isinstance(node, ChironTAC.Num): +# return z3.IntVal(node.value) +# elif isinstance(node, ChironTAC.Var): +# return z3.Int(node.name) class BMC: @@ -64,13 +95,36 @@ def __init__(self, ir): def convert(self): for instruction, jumpTarget in self.ir: - if isinstance(instruction, ChironAST.AssignmentCommand): - left = z3.Int(instruction.lvar.varname) - right = parseExpression(instruction.rexpr) - self.solver.add(left == right) + if isinstance(instruction, ChironTAC.TAC_AssignmentCommand): + lhs = z3.Int(instruction.lvar.name) + if isinstance(instruction.rvar1, ChironTAC.TAC_Num): + rvar1 = z3.IntVal(instruction.rvar1.value) + elif isinstance(instruction.rvar1, ChironTAC.TAC_Var): + rvar1 = z3.Int(instruction.rvar1.name) + + if isinstance(instruction.rvar2, ChironTAC.TAC_Num): + rvar2 = z3.IntVal(instruction.rvar2.value) + elif isinstance(instruction.rvar2, ChironTAC.TAC_Var): + rvar2 = z3.Int(instruction.rvar2.name) + + if instruction.op == "+": + self.solver.add(lhs == rvar1 + rvar2) + elif instruction.op == "-": + self.solver.add(lhs == rvar1 - rvar2) + elif instruction.op == "*": + self.solver.add(lhs == rvar1 * rvar2) + elif instruction.op == "/": + self.solver.add(lhs == rvar1 / rvar2) - elif isinstance(instruction, ChironAST.AssertCommand): - condition = parseExpression(instruction.cond) + elif isinstance(instruction, ChironTAC.TAC_AssertCommand): + if isinstance(instruction.cond, ChironTAC.TAC_BinBoolOp): + if isinstance(instruction.cond.lvar, ChironTAC.TAC_BoolFalse): + left = z3.BoolVal(False) + elif isinstance(instruction.cond.lvar, ChironTAC.TAC_BoolTrue): + left = z3.BoolVal(True) + else: + left = z3.Bool(instruction.cond.lvar.name) + self.solver.add(z3.Not(condition)) # TODO: Implement the rest of the commands diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index b143389..4d356d2 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -408,9 +408,12 @@ def stopTurtle(): tacGen = TACGenerator(ir) tacGen.generateTAC() tacGen.printTAC() - # print("Converting program to SMT-LIB format..") - # smt = bmc.SMTConverter(ir) - # smt.convert() - # smt.solve() + cfg = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) + cfgB.dumpCFG(cfg, 'tac_cfg.png') + tac_ir = tacGen.tac + print("Converting program to SMT-LIB format..") + smt = bmc.BMC(tac_ir) + smt.convert() + smt.solve() # print("DONE..") diff --git a/ChironCore/example/assignmentBMC.tl b/ChironCore/example/assignmentBMC.tl index 5532ccd..252083b 100644 --- a/ChironCore/example/assignmentBMC.tl +++ b/ChironCore/example/assignmentBMC.tl @@ -4,4 +4,4 @@ :z = :x + :w -// assert (:x + 100 < :y) && (:x + 200 > :y) && !(:x >= 0) && (:x * :y < -:x) && (:t > 0) \ No newline at end of file +assert (:x + 100 < :y) && (:x + 200 > :y) && !(:x >= 0) && (:x * :y < -:x) && (:t > 0) \ No newline at end of file diff --git a/ChironCore/irhandler.py b/ChironCore/irhandler.py index f48c6df..e40e1bc 100644 --- a/ChironCore/irhandler.py +++ b/ChironCore/irhandler.py @@ -115,7 +115,7 @@ def removeInstruction(self, stmtList, pos): print("[Skip] Instruction Type not supported for removal. \n") return - if "__rep_counter_" in str(stmtList[pos][0]): + if ":__rep_counter_" in str(stmtList[pos][0]): print("[Skip] Instruction affecting loop counter. \n") return @@ -166,7 +166,7 @@ def parseExpresssion(self, expr, dest): elif isinstance(expr.lexpr, ChironAST.Var): left = ChironTAC.TAC_Var(expr.lexpr.varname) else: - temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") self.tempCount += 1 left = temp self.parseExpresssion(expr.lexpr, temp) @@ -176,7 +176,7 @@ def parseExpresssion(self, expr, dest): elif isinstance(expr.rexpr, ChironAST.Var): right = ChironTAC.TAC_Var(expr.rexpr.varname) else: - temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") self.tempCount += 1 right = temp self.parseExpresssion(expr.rexpr, temp) @@ -195,9 +195,9 @@ def parseExpresssion(self, expr, dest): ChironTAC.TAC_Num(0), ChironTAC.TAC_Num(expr.expr.val), "-", - ) + ), + 1, ), - 1, ) elif isinstance(expr.expr, ChironAST.Var): self.line += 1 @@ -208,12 +208,12 @@ def parseExpresssion(self, expr, dest): ChironTAC.TAC_Num(0), ChironTAC.TAC_Var(expr.expr.varname), "-", - ) + ), + 1, ), - 1, ) else: - temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") self.tempCount += 1 self.parseExpresssion(expr.expr, temp) self.line += 1 @@ -237,7 +237,7 @@ def parseExpresssion(self, expr, dest): elif isinstance(expr.lexpr, ChironAST.Var): left = ChironTAC.TAC_Var(expr.lexpr.varname) else: - temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") self.tempCount += 1 left = temp self.parseExpresssion(expr.lexpr, temp) @@ -247,7 +247,7 @@ def parseExpresssion(self, expr, dest): elif isinstance(expr.rexpr, ChironAST.Var): right = ChironTAC.TAC_Var(expr.rexpr.varname) else: - temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") self.tempCount += 1 right = temp self.parseExpresssion(expr.rexpr, temp) @@ -266,7 +266,7 @@ def parseExpresssion(self, expr, dest): elif isinstance(expr.lexpr, ChironAST.Var): left = ChironTAC.TAC_Var(expr.lexpr.varname) else: - temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") self.tempCount += 1 left = temp self.parseExpresssion(expr.lexpr, temp) @@ -278,7 +278,7 @@ def parseExpresssion(self, expr, dest): elif isinstance(expr.rexpr, ChironAST.Var): right = ChironTAC.TAC_Var(expr.rexpr.varname) else: - temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") self.tempCount += 1 right = temp self.parseExpresssion(expr.rexpr, temp) @@ -328,7 +328,7 @@ def parseExpresssion(self, expr, dest): ) ) else: - temp = ChironTAC.TAC_Var(f"__temp_{self.tempCount}") + temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") self.tempCount += 1 self.parseExpresssion(expr.expr, temp) self.line += 1 @@ -398,14 +398,14 @@ def generateTAC(self): elif isinstance(stmt.cond, ChironAST.Var): branchvar = ChironTAC.TAC_Var(stmt.cond.varname) else: - branchvar = ChironTAC.TAC_Var(f"__branch_{self.branchCount}") + branchvar = ChironTAC.TAC_Var(f":__branch_{self.branchCount}") self.branchCount += 1 self.parseExpresssion(stmt.cond, branchvar) newtgt = line_number - 1 + tgt # Adjusted later self.line += 1 self.tac.append((ChironTAC.TAC_ConditionCommand(branchvar), newtgt)) elif isinstance(stmt, ChironAST.AssertCommand): - assertvar = ChironTAC.TAC_Var(f"__assert_{self.assertCount}") + assertvar = ChironTAC.TAC_Var(f":__assert_{self.assertCount}") self.assertCount += 1 self.parseExpresssion(stmt.cond, assertvar) self.line += 1 @@ -417,7 +417,7 @@ def generateTAC(self): elif isinstance(stmt.expr, ChironAST.Var): movevar = ChironTAC.TAC_Var(stmt.expr.varname) else: - movevar = ChironTAC.TAC_Var(f"__move_{self.moveCount}") + movevar = ChironTAC.TAC_Var(f":__move_{self.moveCount}") self.moveCount += 1 self.parseExpresssion(stmt.expr, movevar) self.line += 1 @@ -433,7 +433,7 @@ def generateTAC(self): elif isinstance(stmt.xcor, ChironAST.Var): xvar = ChironTAC.TAC_Var(stmt.xcor.varname) else: - xvar = ChironTAC.TAC_Var(f"__x_{self.gotoCount}") + xvar = ChironTAC.TAC_Var(f":__x_{self.gotoCount}") self.gotoCount += 1 self.parseExpresssion(stmt.xcor, xvar) if isinstance(stmt.ycor, ChironAST.Num): @@ -441,7 +441,7 @@ def generateTAC(self): elif isinstance(stmt.ycor, ChironAST.Var): yvar = ChironTAC.TAC_Var(stmt.ycor.varname) else: - yvar = ChironTAC.TAC_Var(f"__y_{self.gotoCount}") + yvar = ChironTAC.TAC_Var(f":__y_{self.gotoCount}") self.gotoCount += 1 self.parseExpresssion(stmt.ycor, yvar) self.line += 1 From 812d116a03da010a532907a658e59edcc380ddef Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Sun, 16 Feb 2025 22:34:43 +0530 Subject: [PATCH 08/53] added ssa to chiron --- ChironCore/ChironSSA/ChironSSA.py | 202 +++++++++++++++++++++++++++++ ChironCore/ChironSSA/ssaBuilder.py | 183 ++++++++++++++++++++++++++ ChironCore/cfg/cfgBuilder.py | 12 +- ChironCore/chiron.py | 18 ++- ChironCore/example/move.tl | 22 +++- 5 files changed, 423 insertions(+), 14 deletions(-) create mode 100644 ChironCore/ChironSSA/ChironSSA.py create mode 100644 ChironCore/ChironSSA/ssaBuilder.py diff --git a/ChironCore/ChironSSA/ChironSSA.py b/ChironCore/ChironSSA/ChironSSA.py new file mode 100644 index 0000000..cc08a0f --- /dev/null +++ b/ChironCore/ChironSSA/ChironSSA.py @@ -0,0 +1,202 @@ +# Static Single Assignment (SSA) generation for Chiron +class SSA(object): + pass + +# Instruction Classes +class SSA_Instruction(SSA): + pass + +class SSA_PhiCommand(SSA_Instruction): + def __init__(self, lvar, rvars): + self.lvar = lvar + self.rvars = rvars + + def __str__(self): + return self.lvar.__str__() + " = PHI " + ", ".join([var.__str__() for var in list(self.rvars)]) + +class SSA_AssignmentCommand(SSA_Instruction): + def __init__(self, lvar, rvar1, rvar2, op): + self.lvar = lvar + self.rvar1 = rvar1 + self.rvar2 = rvar2 + self.op = op + + def __str__(self): + return self.lvar.__str__() + " = " + self.rvar1.__str__() + " " + self.op + " " + self.rvar2.__str__() + +class SSA_ConditionCommand(SSA_Instruction): + def __init__(self, condition): + self.cond = condition + + def __str__(self): + return "BRANCH: " + self.cond.__str__() + +class SSA_AssertCommand(SSA_Instruction): + def __init__(self, condition): + self.cond = condition + + def __str__(self): + return "ASSERT: " + self.cond.__str__() + +class SSA_MoveCommand(SSA_Instruction): + def __init__(self, motion, var): + self.direction = motion + self.var = var + + def __str__(self): + return "MOVE: " + self.direction + " " + self.var.__str__() + +class SSA_PenCommand(SSA_Instruction): + def __init__(self, penstat): + self.status = penstat + + def __str__(self): + return "PEN: " + self.status + +class SSA_GotoCommand(SSA_Instruction): + def __init__(self, x, y): + self.xcor = x + self.ycor = y + + def __str__(self): + return "goto " + str(self.xcor) + " " + str(self.ycor) + +class SSA_NoOpCommand(SSA_Instruction): + def __str__(self): + return "NoOp" + +class SSA_PauseCommand(SSA_Instruction): + def __str__(self): + return "Pause" + + +class SSA_Expression(SSA): + pass +# -- Arithmetic Expressions ------------------------------------------ +class SSA_ArithExpr(SSA_Expression): + pass + +class SSA_BinArithOp(SSA_ArithExpr): + def __init__(self, lvar, rvar, op): + self.lvar = lvar + self.rvar = rvar + self.op = op + + def __str__(self): + return self.lvar.__str__() + " " + self.op + " " + self.rvar.__str__() + +class SSA_Sum(SSA_BinArithOp): + def __init__(self, lvar, rvar): + SSA_BinArithOp.__init__(self, lvar, rvar, "+") + +class SSA_Sub(SSA_BinArithOp): + def __init__(self, lvar, rvar): + SSA_BinArithOp.__init__(self, lvar, rvar, "-") + +class SSA_Mul(SSA_BinArithOp): + def __init__(self, lvar, rvar): + SSA_BinArithOp.__init__(self, lvar, rvar, "*") + +class SSA_Div(SSA_BinArithOp): + def __init__(self, lvar, rvar): + SSA_BinArithOp.__init__(self, lvar, rvar, "/") + + +class SSA_UnaryArithOp(SSA_ArithExpr): + def __init__(self, op, var): + self.op = op + self.var = var + + def __str__(self): + return self.op + " " + self.var.__str__() + +class SSA_UMinus(SSA_UnaryArithOp): + def __init__(self, var): + SSA_UnaryArithOp.__init__(self, "-", var) + + +# -- Boolean Expressions -------------------------------------------- +class SSA_BoolExpr(SSA_Expression): + pass + +class SSA_BinBoolOp(SSA_BoolExpr): + def __init__(self, lvar, rvar, op): + self.lvar = lvar + self.rvar = rvar + self.op = op + + def __str__(self): + return self.lvar.__str__() + " " + self.op + " " + self.rvar.__str__() + +class SSA_And(SSA_BinBoolOp): + def __init__(self, lvar, rvar): + SSA_BinBoolOp.__init__(self, lvar, rvar, "and") + +class SSA_Or(SSA_BinBoolOp): + def __init__(self, lvar, rvar): + SSA_BinBoolOp.__init__(self, lvar, rvar, "or") + +class SSA_LT(SSA_BinBoolOp): + def __init__(self, lvar, rvar): + SSA_BinBoolOp.__init__(self, lvar, rvar, "<") + +class SSA_GT(SSA_BinBoolOp): + def __init__(self, lvar, rvar): + SSA_BinBoolOp.__init__(self, lvar, rvar, ">") + +class SSA_LTE(SSA_BinBoolOp): + def __init__(self, lvar, rvar): + SSA_BinBoolOp.__init__(self, lvar, rvar, "<=") + +class SSA_GTE(SSA_BinBoolOp): + def __init__(self, lvar, rvar): + SSA_BinBoolOp.__init__(self, lvar, rvar, ">=") + +class SSA_EQ(SSA_BinBoolOp): + def __init__(self, lvar, rvar): + SSA_BinBoolOp.__init__(self, lvar, rvar, "==") + +class SSA_NEQ(SSA_BinBoolOp): + def __init__(self, lvar, rvar): + SSA_BinBoolOp.__init__(self, lvar, rvar, "!=") + +class SSA_Not(SSA_BoolExpr): + def __init__(self, var): + self.var = var + + def __str__(self): + return "not " + self.var.__str__() + +class SSA_PenStatus(SSA_Expression): + def __str__(self): + return "penstatus" + +class SSA_BoolTrue(SSA_Expression): + def __str__(self): + return "true" + +class SSA_BoolFalse(SSA_Expression): + def __str__(self): + return "false" + +# -- Value Expressions ---------------------------------------------- +class SSA_Value(SSA_Expression): + pass + +class SSA_Num(SSA_Value): + def __init__(self, value): + self.value = value + + def __str__(self): + return str(self.value) + +class SSA_Var(SSA_Value): + def __init__(self, name): + self.name = name + + def __str__(self): + return self.name + +class SSA_Unused(SSA_Value): + def __str__(self): + return "" diff --git a/ChironCore/ChironSSA/ssaBuilder.py b/ChironCore/ChironSSA/ssaBuilder.py new file mode 100644 index 0000000..da6fae7 --- /dev/null +++ b/ChironCore/ChironSSA/ssaBuilder.py @@ -0,0 +1,183 @@ +from cfg.ChironCFG import * +import ChironAST.ChironAST as ChironAST +import ChironAST.ChironTAC as ChironTAC +import ChironSSA.ChironSSA as ChironSSA + +def buildSSA(tac, cfg, line2BlockMap): + """ + Builds SSA form from TAC and CFG. + """ + + ssa = [] + lastDeclaration = {} # lastDeclaration[bb][var] = version + varCounter = {} # varCounter[var] = counter + phiStatements = {} # phiStatements[bb][var] = [var_1, var_2, ...] + ssaLineCounter = 0 + block2ssaLine = {} # block2ssaLine[bb] = ssaLine + + # Initialize + for (stmt, tgt), line in zip(tac, range(len(tac))): + if isinstance(stmt, ChironTAC.TAC_AssignmentCommand): + varCounter[stmt.lvar.__str__()] = 0 + lastDeclaration[line2BlockMap[line]] = {} + for node in cfg: + phiStatements[node] = {} + + # Renamed the declarations of variables in TAC + for (stmt, tgt), line in zip(tac, range(len(tac))): + if isinstance(stmt, ChironTAC.TAC_AssignmentCommand): + var = stmt.lvar.__str__() + lastDeclaration[line2BlockMap[line]][var] = varCounter[var] + varCounter[var] += 1 + stmt.lvar = ChironTAC.TAC_Var(f"{var}__{varCounter[var] - 1}") + tac[line] = (stmt, tgt) + + for node in cfg: + predes = cfg.predecessors(node) + for parent in predes: + for var in lastDeclaration[parent]: + if var not in phiStatements[node]: + phiStatements[node][var] = [] + phiStatements[node][var].append(lastDeclaration[parent][var]) + + visited = {} + for node in cfg: + visited[node] = False + + lastUsed = {} + for var in varCounter.keys(): + lastUsed[var] = varCounter[var] + + for (stmt, tgt), line in zip(tac, range(len(tac))): + node = line2BlockMap[line] + if visited[node] == False: + visited[node] = True + block2ssaLine[node] = ssaLineCounter + for var in phiStatements[node].keys(): + if len(phiStatements[node][var]) > 1: + ssaLineCounter += 1 + ssa.append((ChironSSA.SSA_PhiCommand(ChironSSA.SSA_Var(f"{var}__{varCounter[var]}"), [ChironSSA.SSA_Var(f"{var}__{version}") for version in phiStatements[node][var]]), 1)) + lastUsed[var] = varCounter[var] + varCounter[var] += 1 + + if isinstance(stmt, ChironTAC.TAC_AssignmentCommand): + rvar1 = None + rvar2 = None + if isinstance(stmt.rvar1, ChironTAC.TAC_Var): + if stmt.rvar1.__str__() not in lastUsed.keys(): + lastUsed[stmt.rvar1.__str__()] = 0 + rvar1 = ChironSSA.SSA_Var(f"{stmt.rvar1.__str__()}__{lastUsed[stmt.rvar1.__str__()]}") + elif isinstance(stmt.rvar1, ChironTAC.TAC_BoolTrue): + rvar1 = ChironSSA.SSA_BoolTrue() + elif isinstance(stmt.rvar1, ChironTAC.TAC_BoolFalse): + rvar1 = ChironSSA.SSA_BoolFalse() + elif isinstance(stmt.rvar1, ChironTAC.TAC_Num): + rvar1 = ChironSSA.SSA_Num(stmt.rvar1.value) + if isinstance(stmt.rvar2, ChironTAC.TAC_Var): + if stmt.rvar2.__str__() not in lastUsed.keys(): + lastUsed[stmt.rvar2.__str__()] = 0 + rvar2 = ChironSSA.SSA_Var(f"{stmt.rvar2.__str__()}__{lastUsed[stmt.rvar2.__str__()]}") + elif isinstance(stmt.rvar2, ChironTAC.TAC_BoolTrue): + rvar2 = ChironSSA.SSA_BoolTrue() + elif isinstance(stmt.rvar2, ChironTAC.TAC_BoolFalse): + rvar2 = ChironSSA.SSA_BoolFalse() + elif isinstance(stmt.rvar2, ChironTAC.TAC_Num): + rvar2 = ChironSSA.SSA_Num(stmt.rvar2.value) + lvar = ChironSSA.SSA_Var(f"{stmt.lvar.__str__()}") + + lvar_string = lvar.__str__().rsplit('__', 1)[0] + lastUsed[lvar_string] = int(lvar.__str__().rsplit('__', 1)[1]) + + ssaLineCounter += 1 + ssa.append((ChironSSA.SSA_AssignmentCommand(lvar, rvar1, rvar2, stmt.op), tgt)) + + elif isinstance(stmt, ChironTAC.TAC_ConditionCommand): + tgt_block = line2BlockMap[line + tgt] + if isinstance(stmt.cond, ChironTAC.TAC_BoolTrue): + ssa.append((ChironSSA.SSA_ConditionCommand(ChironSSA.SSA_BoolTrue()), tgt_block)) + elif isinstance(stmt.cond, ChironTAC.TAC_BoolFalse): + ssa.append((ChironSSA.SSA_ConditionCommand(ChironSSA.SSA_BoolFalse()), tgt_block)) + else: + if isinstance(stmt.cond, ChironTAC.TAC_Var): + if stmt.cond.__str__() not in lastUsed.keys(): + lastUsed[stmt.cond.__str__()] = 0 + cond = ChironSSA.SSA_Var(f"{stmt.cond.__str__()}__{lastUsed[stmt.cond.__str__()]}") + elif isinstance(stmt.cond, ChironTAC.TAC_Num): + cond = ChironSSA.SSA_Num(stmt.cond.value) + ssa.append((ChironSSA.SSA_ConditionCommand(cond), tgt_block)) + ssaLineCounter += 1 + + elif isinstance(stmt, ChironTAC.TAC_AssertCommand): + if isinstance(stmt.cond, ChironTAC.TAC_BoolTrue): + ssa.append((ChironSSA.SSA_AssertCommand(ChironSSA.SSA_BoolTrue()), tgt)) + elif isinstance(stmt.cond, ChironTAC.TAC_BoolFalse): + ssa.append((ChironSSA.SSA_AssertCommand(ChironSSA.SSA_BoolFalse()), tgt)) + else: + if isinstance(stmt.cond, ChironTAC.TAC_Var): + if stmt.cond.__str__() not in lastUsed.keys(): + lastUsed[stmt.cond.__str__()] = 0 + cond = ChironSSA.SSA_Var(f"{stmt.cond.__str__()}__{lastUsed[stmt.cond.__str__()]}") + elif isinstance(stmt.cond, ChironTAC.TAC_Num): + cond = ChironSSA.SSA_Num(stmt.cond.value) + ssa.append((ChironSSA.SSA_AssertCommand(cond), tgt)) + ssaLineCounter += 1 + + elif isinstance(stmt, ChironTAC.TAC_MoveCommand): + var = None + if isinstance(stmt.var, ChironTAC.TAC_Var): + if stmt.var.__str__() not in lastUsed.keys(): + lastUsed[stmt.var.__str__()] = 0 + var = ChironSSA.SSA_Var(f"{stmt.var.__str__()}__{lastUsed[stmt.var.__str__()]}") + elif isinstance(stmt.var, ChironTAC.TAC_Num): + var = ChironSSA.SSA_Num(stmt.var.value) + ssa.append((ChironSSA.SSA_MoveCommand(stmt.direction, var), tgt)) + ssaLineCounter += 1 + + elif isinstance(stmt, ChironTAC.TAC_PenCommand): + ssa.append((ChironSSA.SSA_PenCommand(stmt.status), tgt)) + ssaLineCounter += 1 + + elif isinstance(stmt, ChironTAC.TAC_GotoCommand): + x_var = None + y_var = None + if isinstance(stmt.xcor, ChironTAC.TAC_Var): + if stmt.xcor.__str__() not in lastUsed.keys(): + lastUsed[stmt.xcor.__str__()] = 0 + x_var = ChironSSA.SSA_Var(f"{stmt.xcor.__str__()}__{lastUsed[stmt.xcor.__str__()]}") + elif isinstance(stmt.xcor, ChironTAC.TAC_Num): + x_var = ChironSSA.SSA_Num(stmt.xcor.value) + if isinstance(stmt.ycor, ChironTAC.TAC_Var): + if stmt.ycor.__str__() not in lastUsed.keys(): + lastUsed[stmt.ycor.__str__()] = 0 + y_var = ChironSSA.SSA_Var(f"{stmt.ycor.__str__()}__{lastUsed[stmt.ycor.__str__()]}") + elif isinstance(stmt.ycor, ChironTAC.TAC_Num): + y_var = ChironSSA.SSA_Num(stmt.ycor.value) + ssa.append((ChironSSA.SSA_GotoCommand(x_var, y_var), tgt)) + ssaLineCounter += 1 + + elif isinstance(stmt, ChironTAC.TAC_NoOpCommand): + ssa.append((ChironSSA.SSA_NoOpCommand(), tgt)) + ssaLineCounter += 1 + + elif isinstance(stmt, ChironTAC.TAC_PauseCommand): + ssa.append((ChironSSA.SSA_PauseCommand(), tgt)) + ssaLineCounter += 1 + + else: + raise Exception(f"Unknown TAC command: {stmt}") + + block2ssaLine[line2BlockMap[len(tac)]] = ssaLineCounter + + for (stmt, tgt), line in zip(ssa, range(len(ssa))): + if isinstance(stmt, ChironSSA.SSA_ConditionCommand): + tgt = block2ssaLine[tgt] - line + ssa[line] = (stmt, tgt) + + return ssa + +def printSSA(ssa): + """ + Prints SSA form. + """ + for (stmt, tgt), line in zip(ssa, range(len(ssa))): + print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") \ No newline at end of file diff --git a/ChironCore/cfg/cfgBuilder.py b/ChironCore/cfg/cfgBuilder.py index 9e0a48b..bb96595 100644 --- a/ChironCore/cfg/cfgBuilder.py +++ b/ChironCore/cfg/cfgBuilder.py @@ -81,8 +81,16 @@ def buildCFG(ir, cfgName="", isSingle=False): nextBB = indices2LeadersMap[irIdx + 1] if (irIdx + 1 < len(ir)) else endBB cfg.add_edge(node, nextBB, label='flow_edge', color='blue') - return cfg + line2BlockMap = {} + last_block = None + for line in range(len(ir)): + if line in indices2LeadersMap.keys(): + last_block = indices2LeadersMap[line] + line2BlockMap[line] = last_block + line2BlockMap[len(ir)] = endBB + + return cfg, line2BlockMap def dumpCFG(cfg, filename="out"): @@ -97,4 +105,4 @@ def dumpCFG(cfg, filename="out"): G = nx.relabel_nodes(G, labels) A = to_agraph(G) A.layout('dot') - A.draw(filename + ".png") + A.draw(filename + ".png") \ No newline at end of file diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 4d356d2..26f0ce1 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -22,6 +22,7 @@ import sExecution as se import cfg.cfgBuilder as cfgB import bmc as bmc +from ChironSSA.ssaBuilder import * import submissionDFA as DFASub import submissionAI as AISub from sbflSubmission import computeRanks @@ -408,12 +409,17 @@ def stopTurtle(): tacGen = TACGenerator(ir) tacGen.generateTAC() tacGen.printTAC() - cfg = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) + cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) cfgB.dumpCFG(cfg, 'tac_cfg.png') - tac_ir = tacGen.tac - print("Converting program to SMT-LIB format..") - smt = bmc.BMC(tac_ir) - smt.convert() - smt.solve() + + print() + ssa = buildSSA(tacGen.tac, cfg, line2BlockMap) + printSSA(ssa) + + # tac_ir = tacGen.tac + # print("Converting program to SMT-LIB format..") + # smt = bmc.BMC(tac_ir) + # smt.convert() + # smt.solve() # print("DONE..") diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index c37ac08..9272f22 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,9 +1,19 @@ -if (:x > 1) [ - :x = :x + 10 +:x = 10 +:x = :x + 2 +if (:x > 2) [ + :x = 4 ] else [ - :x = :x + 5 + :x = 3 ] +:y = :x + 2 +:x = :x + 1 +:x = :x + 5 -goto (20, :y + 10) - - +repeat :x [ +if (:y > 0) [ +:x = :x + :y + :z +] +if (:y < 0) [ +:x = :w + :lam +] +] From 57ebb324e787c45703c8c56eedb1b106aba2a915 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Sun, 16 Feb 2025 22:46:00 +0530 Subject: [PATCH 09/53] added cfg of ssa --- ChironCore/chiron.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 26f0ce1..05dac87 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -415,7 +415,10 @@ def stopTurtle(): print() ssa = buildSSA(tacGen.tac, cfg, line2BlockMap) printSSA(ssa) - + + ssa_cfg, ssa_line2BlockMap = cfgB.buildCFG(ssa, "ssa_cfg", False) + cfgB.dumpCFG(ssa_cfg, 'ssa_cfg.png') + # tac_ir = tacGen.tac # print("Converting program to SMT-LIB format..") # smt = bmc.BMC(tac_ir) From b8354aab7fb695ac3c533e447ba5d0c890d551be Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Fri, 21 Feb 2025 00:51:29 +0530 Subject: [PATCH 10/53] added bmc for parts of SSA ir --- ChironCore/ChironSSA/ssaBuilder.py | 2 +- ChironCore/bmc.py | 236 ++++++++++++++--------------- ChironCore/chiron.py | 31 ++-- ChironCore/example/move.tl | 25 +-- 4 files changed, 136 insertions(+), 158 deletions(-) diff --git a/ChironCore/ChironSSA/ssaBuilder.py b/ChironCore/ChironSSA/ssaBuilder.py index da6fae7..6cdbadb 100644 --- a/ChironCore/ChironSSA/ssaBuilder.py +++ b/ChironCore/ChironSSA/ssaBuilder.py @@ -1,5 +1,4 @@ from cfg.ChironCFG import * -import ChironAST.ChironAST as ChironAST import ChironAST.ChironTAC as ChironTAC import ChironSSA.ChironSSA as ChironSSA @@ -179,5 +178,6 @@ def printSSA(ssa): """ Prints SSA form. """ + print("\nSSA Form:") for (stmt, tgt), line in zip(ssa, range(len(ssa))): print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") \ No newline at end of file diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 8e2ab50..6e3703b 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -1,140 +1,130 @@ ''' -This file is used to convert the 3 address code IR to SMT-LIB format. +This file is used to convert the SSA IR to SMT-LIB format. ''' import z3 -from ChironAST import ChironTAC - -# def parseExpression(node): -# if isinstance(node, ChironTAC.TAC_ArithExpr): -# if isinstance(node, ChironTAC.TAC_BinArithOp): -# if isinstance(node.lvar, ChironTAC.TAC_Num): -# left = z3.IntVal(node.lvar.value) -# else: -# left = z3.Int(node.lvar.name) - -# if isinstance(node.rvar, ChironTAC.TAC_Num): -# right = z3.IntVal(node.rvar.value) -# else: -# right = z3.Int(node.rvar.name) - -# if isinstance(node, ChironTAC.TAC_Sum): -# return left.__add__(right) -# elif isinstance(node, ChironTAC.TAC_Diff): -# return left.__sub__(right) -# elif isinstance(node, ChironTAC.TAC_Mult): -# return left.__mul__(right) -# elif isinstance(node, ChironTAC.TAC_Div): -# return left.__div__(right) - -# elif isinstance(node, ChironTAC.TAC_UnaryArithOp): -# if isinstance(node, ChironTAC.TAC_UMinus): -# if isinstance(node.lvar, ChironTAC.TAC_Num): -# left = z3.IntVal(node.lvar.value) -# else: -# left = z3.Int(node.lvar.name) - -# return left.__neg__() - -# elif isinstance(node, ChironTAC.TAC_BoolExpr): -# if isinstance(node, ChironTAC.TAC_BinBoolOp): -# if isinstance(node.lvar, ChironTAC.TAC_BoolFalse): -# left = z3.BoolVal(False) -# elif isinstance(node.lvar, ChironTAC.TAC_BoolTrue): -# left = z3.BoolVal(True) -# else: -# left = z3.Bool(node.lvar.name) - -# if isinstance(node.rvar, ChironTAC.TAC_BoolFalse): -# right = z3.BoolVal(False) -# elif isinstance(node.rvar, ChironTAC.TAC_BoolTrue): -# right = z3.BoolVal(True) -# else: -# right = z3.Bool(node.rvar.name) - -# if isinstance(node, ChironTAC.TAC_And): -# return left.__and__(right) -# elif isinstance(node, ChironTAC.TAC_Or): -# return left.__or__(right) -# elif isinstance(node, ChironTAC.TAC_LT): -# return left.__lt__(right) -# elif isinstance(node, ChironTAC.TAC_GT): -# return left.__gt__(right) -# elif isinstance(node, ChironTAC.TAC_LTE): -# return left.__le__(right) -# elif isinstance(node, ChironTAC.TAC_GTE): -# return left.__ge__(right) -# elif isinstance(node, ChironTAC.TAC_EQ): -# return left.__eq__(right) -# elif isinstance(node, ChironTAC.TAC_NEQ): -# return left.__ne__(right) -# elif isinstance(node, ChironTAC.TAC_Not): -# if isinstance(node.var, ChironTAC.TAC_BoolFalse): -# left = z3.BoolVal(False) -# elif isinstance(node.var, ChironTAC.TAC_BoolTrue): -# left = z3.BoolVal(True) -# else: -# left = z3.Bool(node.var.name) - -# return left.__invert__() -# elif isinstance(node, ChironTAC.BoolTrue): -# return z3.BoolVal(True) -# elif isinstance(node, ChironTAC.BoolFalse): -# return z3.BoolVal(False) - -# else: -# if isinstance(node, ChironTAC.Num): -# return z3.IntVal(node.value) -# elif isinstance(node, ChironTAC.Var): -# return z3.Int(node.name) - +from ChironSSA import ChironSSA class BMC: def __init__(self, ir): self.solver = z3.Solver() self.ir = ir - def convert(self): - for instruction, jumpTarget in self.ir: - if isinstance(instruction, ChironTAC.TAC_AssignmentCommand): - lhs = z3.Int(instruction.lvar.name) - if isinstance(instruction.rvar1, ChironTAC.TAC_Num): - rvar1 = z3.IntVal(instruction.rvar1.value) - elif isinstance(instruction.rvar1, ChironTAC.TAC_Var): - rvar1 = z3.Int(instruction.rvar1.name) - - if isinstance(instruction.rvar2, ChironTAC.TAC_Num): - rvar2 = z3.IntVal(instruction.rvar2.value) - elif isinstance(instruction.rvar2, ChironTAC.TAC_Var): - rvar2 = z3.Int(instruction.rvar2.name) - - if instruction.op == "+": - self.solver.add(lhs == rvar1 + rvar2) - elif instruction.op == "-": - self.solver.add(lhs == rvar1 - rvar2) - elif instruction.op == "*": - self.solver.add(lhs == rvar1 * rvar2) - elif instruction.op == "/": - self.solver.add(lhs == rvar1 / rvar2) + def convert_SSA_to_SMT(self): + for stmt, tgt in self.ir: + if isinstance(stmt, ChironSSA.SSA_PhiCommand): # TODO: Add support for Phi commands + lvar = z3.Int(stmt.lvar.name) + rvars = [] + for rvar in stmt.rvars: + if isinstance(rvar, ChironSSA.SSA_Var): + rvars.append(z3.Int(rvar.name)) + elif isinstance(rvar, ChironSSA.SSA_Num): + rvars.append(z3.IntVal(rvar.value)) + elif isinstance(rvar, ChironSSA.SSA_BoolTrue): + rvars.append(z3.BoolVal(True)) + elif isinstance(rvar, ChironSSA.SSA_BoolFalse): + rvars.append(z3.BoolVal(False)) + or_expr = z3.Or([lvar == rvar for rvar in rvars]) + self.solver.add(or_expr) + + elif isinstance(stmt, ChironSSA.SSA_AssignmentCommand): + lvar = None + rvar1 = None + rvar2 = None + if stmt.op in ["+", "-", "*", "/"]: + lvar = z3.Int(stmt.lvar.name) + if isinstance(stmt.rvar1, ChironSSA.SSA_Var): + rvar1 = z3.Int(stmt.rvar1.name) + elif isinstance(stmt.rvar1, ChironSSA.SSA_Num): + rvar1 = z3.IntVal(stmt.rvar1.value) + if isinstance(stmt.rvar2, ChironSSA.SSA_Var): + rvar2 = z3.Int(stmt.rvar2.name) + elif isinstance(stmt.rvar2, ChironSSA.SSA_Num): + rvar2 = z3.IntVal(stmt.rvar2.value) + elif stmt.op in ["<", ">", "<=", ">=", "==", "!="]: + lvar = z3.Bool(stmt.lvar.name) + if isinstance(stmt.rvar1, ChironSSA.SSA_Var): + rvar1 = z3.Int(stmt.rvar1.name) + elif isinstance(stmt.rvar1, ChironSSA.SSA_Num): + rvar1 = z3.IntVal(stmt.rvar1.value) + if isinstance(stmt.rvar2, ChironSSA.SSA_Var): + rvar2 = z3.Int(stmt.rvar2.name) + elif isinstance(stmt.rvar2, ChironSSA.SSA_Num): + rvar2 = z3.IntVal(stmt.rvar2.value) + elif stmt.op in ["and", "or"]: + lvar = z3.Bool(stmt.lvar.name) + if isinstance(stmt.rvar1, ChironSSA.SSA_Var): + rvar1 = z3.Bool(stmt.rvar1.name) + elif isinstance(stmt.rvar1, ChironSSA.SSA_BoolTrue): + rvar1 = z3.BoolVal(True) + if isinstance(stmt.rvar2, ChironSSA.SSA_Var): + rvar2 = z3.Bool(stmt.rvar2.name) + elif isinstance(stmt.rvar2, ChironSSA.SSA_BoolFalse): + rvar2 = z3.BoolVal(False) + elif stmt.op == "not": + lvar = z3.Bool(stmt.lvar.name) + if isinstance(stmt.rvar1, ChironSSA.SSA_Var): + rvar1 = z3.Bool(stmt.rvar1.name) + elif isinstance(stmt.rvar1, ChironSSA.SSA_BoolTrue): + rvar1 = z3.BoolVal(True) + elif isinstance(stmt.rvar1, ChironSSA.SSA_BoolFalse): + rvar1 = z3.BoolVal(False) + else: + raise Exception("Unknown SSA instruction") + + if stmt.op == "+": + self.solver.add(lvar == (rvar1 + rvar2)) + elif stmt.op == "-": + self.solver.add(lvar == (rvar1 - rvar2)) + elif stmt.op == "*": + self.solver.add(lvar == (rvar1 * rvar2)) + elif stmt.op == "/": + self.solver.add(lvar == (rvar1 / rvar2)) + elif stmt.op == "<": + self.solver.add(lvar == (rvar1 < rvar2)) + elif stmt.op == ">": + self.solver.add(lvar == (rvar1 > rvar2)) + elif stmt.op == "<=": + self.solver.add(lvar == (rvar1 <= rvar2)) + elif stmt.op == ">=": + self.solver.add(lvar == (rvar1 >= rvar2)) + elif stmt.op == "==": + self.solver.add(lvar == (rvar1 == rvar2)) + elif stmt.op == "!=": + self.solver.add(lvar == (rvar1 != rvar2)) + elif stmt.op == "and": + self.solver.add(lvar == z3.And(rvar1, rvar2)) + elif stmt.op == "or": + self.solver.add(lvar == z3.Or(rvar1, rvar2)) + elif stmt.op == "not": + self.solver.add(lvar == z3.Not(rvar1)) + + elif isinstance(stmt, ChironSSA.SSA_AssertCommand): + cond = None + if isinstance(stmt.cond, ChironSSA.SSA_BoolTrue): + cond = z3.BoolVal(True) + elif isinstance(stmt.cond, ChironSSA.SSA_BoolFalse): + cond = z3.BoolVal(False) + elif isinstance(stmt.cond, ChironSSA.SSA_Var): + cond = z3.Bool(stmt.cond.name) + self.solver.add(z3.Not(cond)) + + # TODO add support for other SSA instructions + # elif isinstance(stmt, ChironSSA.SSA_ConditionCommand): + # elif isinstance(stmt, ChironSSA.SSA_MoveCommand): + # elif isinstance(stmt, ChironSSA.SSA_PenCommand): + # elif isinstance(stmt, ChironSSA.SSA_GotoCommand): + # elif isinstance(stmt, ChironSSA.SSA_NoOpCommand): + # elif isinstance(stmt, ChironSSA.SSA_PauseCommand): + # else: + # raise Exception("Unknown SSA instruction") - elif isinstance(instruction, ChironTAC.TAC_AssertCommand): - if isinstance(instruction.cond, ChironTAC.TAC_BinBoolOp): - if isinstance(instruction.cond.lvar, ChironTAC.TAC_BoolFalse): - left = z3.BoolVal(False) - elif isinstance(instruction.cond.lvar, ChironTAC.TAC_BoolTrue): - left = z3.BoolVal(True) - else: - left = z3.Bool(instruction.cond.lvar.name) - - self.solver.add(z3.Not(condition)) - - # TODO: Implement the rest of the commands - def solve(self): print("Assertions are:") print(self.solver.assertions()) + print() sat = self.solver.check() if sat == z3.sat: - print("Bug found!") + print("Condition not satisfied!") print(self.solver.model()) else: - print("No bug found!") \ No newline at end of file + print("Condition always holds true!") \ No newline at end of file diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 05dac87..d1d3a52 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -403,26 +403,23 @@ def stopTurtle(): print("DONE..") if args.bmc: - print("Bounded Model Checking..") - print("Converting program to 3 address code...") - print("input statement: ", args.bmc) - tacGen = TACGenerator(ir) + print("\nBounded Model Checking..") + + tacGen = TACGenerator(ir) # Converting IR to TAC tacGen.generateTAC() - tacGen.printTAC() - cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) + # tacGen.printTAC() # Printing TAC + + cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) # Building CFG cfgB.dumpCFG(cfg, 'tac_cfg.png') - print() - ssa = buildSSA(tacGen.tac, cfg, line2BlockMap) - printSSA(ssa) + ssa = buildSSA(tacGen.tac, cfg, line2BlockMap) # Building SSA + printSSA(ssa) # Printing SSA - ssa_cfg, ssa_line2BlockMap = cfgB.buildCFG(ssa, "ssa_cfg", False) + ssa_cfg, ssa_line2BlockMap = cfgB.buildCFG(ssa, "ssa_cfg", False) # Building CFG for SSA cfgB.dumpCFG(ssa_cfg, 'ssa_cfg.png') - # tac_ir = tacGen.tac - # print("Converting program to SMT-LIB format..") - # smt = bmc.BMC(tac_ir) - # smt.convert() - # smt.solve() - - # print("DONE..") + print("\nConverting program to SMT-LIB format..\n") + smt = bmc.BMC(ssa) + smt.convert_SSA_to_SMT() + smt.solve() + print("DONE..") \ No newline at end of file diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 9272f22..6254496 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,19 +1,10 @@ -:x = 10 -:x = :x + 2 -if (:x > 2) [ - :x = 4 +if (:a > :b) [ + :x = 1 ] else [ - :x = 3 -] -:y = :x + 2 -:x = :x + 1 -:x = :x + 5 - -repeat :x [ -if (:y > 0) [ -:x = :x + :y + :z -] -if (:y < 0) [ -:x = :w + :lam -] + if (:b > :c) [ + :x = 2 + ] else [ + :x = 3 + ] ] +:y = :x \ No newline at end of file From 7481e9be54cc17142cde3783640df28e2274e0fb Mon Sep 17 00:00:00 2001 From: Debraj Karmakar <128470284+debrajk22@users.noreply.github.com> Date: Fri, 21 Feb 2025 01:14:23 +0530 Subject: [PATCH 11/53] Update dependencies --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 74ca21d..fc6634e 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,9 @@ If you want to cite this work, you may use this. ### Installing Dependencies ```bash -$ pip install antlr4-python3-runtime==4.7.2 networkx z3-solver numpy -$ sudo apt-get install python3-tk +pip install antlr4-python3-runtime==4.7.2 networkx z3-solver numpy +sudo apt-get install python3-tk +pip install pygraphviz ``` ### Generating the ANTLR files. @@ -51,8 +52,8 @@ The `antlr` files need to be rebuilt if any changes are made to the `tlang.g4` f We use a visitor pattern to generate the AST from parsing. ``` -$ cd ChironCore/turtparse -$ java -cp ../extlib/antlr-4.7.2-complete.jar org.antlr.v4.Tool \ +cd ChironCore/turtparse +java -cp ../extlib/antlr-4.7.2-complete.jar org.antlr.v4.Tool \ -Dlanguage=Python3 -visitor -no-listener tlang.g4 ``` @@ -62,8 +63,8 @@ The main directory for source files is `ChironCore`. We have examples of the tur To pass parameters (input params) for running a turtle program, use the `-d` flag. Pass the parameters as a python dictionary. ```bash -$ cd ChironCore -$ ./chiron.py -r ./example/example1.tl -d '{":x": 20, "y": 30, ":z": 20, ":p": 40}' +cd ChironCore +./chiron.py -r ./example/example1.tl -d '{":x": 20, "y": 30, ":z": 20, ":p": 40}' ``` ### See help for other command line options From 798df64a45d48f8d249c5d2c5505da043f1e63e9 Mon Sep 17 00:00:00 2001 From: Debraj Karmakar <128470284+debrajk22@users.noreply.github.com> Date: Tue, 4 Mar 2025 00:50:31 +0530 Subject: [PATCH 12/53] fixed initialization bug --- ChironCore/ChironSSA/ssaBuilder.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ChironCore/ChironSSA/ssaBuilder.py b/ChironCore/ChironSSA/ssaBuilder.py index 6cdbadb..4b4e827 100644 --- a/ChironCore/ChironSSA/ssaBuilder.py +++ b/ChironCore/ChironSSA/ssaBuilder.py @@ -18,9 +18,10 @@ def buildSSA(tac, cfg, line2BlockMap): for (stmt, tgt), line in zip(tac, range(len(tac))): if isinstance(stmt, ChironTAC.TAC_AssignmentCommand): varCounter[stmt.lvar.__str__()] = 0 - lastDeclaration[line2BlockMap[line]] = {} + for node in cfg: phiStatements[node] = {} + lastDeclaration[node] = {} # Renamed the declarations of variables in TAC for (stmt, tgt), line in zip(tac, range(len(tac))): @@ -180,4 +181,4 @@ def printSSA(ssa): """ print("\nSSA Form:") for (stmt, tgt), line in zip(ssa, range(len(ssa))): - print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") \ No newline at end of file + print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") From 64a1a835c35043429707f1d6825a4b84b65eb845 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 4 Mar 2025 14:33:08 +0530 Subject: [PATCH 13/53] ssa cfg update --- ChironCore/ChironSSA/ssaBuilder.py | 5 ++++- ChironCore/cfg/cfgBuilder.py | 14 +++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ChironCore/ChironSSA/ssaBuilder.py b/ChironCore/ChironSSA/ssaBuilder.py index 6cdbadb..8498afa 100644 --- a/ChironCore/ChironSSA/ssaBuilder.py +++ b/ChironCore/ChironSSA/ssaBuilder.py @@ -34,6 +34,9 @@ def buildSSA(tac, cfg, line2BlockMap): for node in cfg: predes = cfg.predecessors(node) for parent in predes: + if lastDeclaration.get(parent) == None: + continue + for var in lastDeclaration[parent]: if var not in phiStatements[node]: phiStatements[node][var] = [] @@ -180,4 +183,4 @@ def printSSA(ssa): """ print("\nSSA Form:") for (stmt, tgt), line in zip(ssa, range(len(ssa))): - print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") \ No newline at end of file + print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") diff --git a/ChironCore/cfg/cfgBuilder.py b/ChironCore/cfg/cfgBuilder.py index bb96595..8983e48 100644 --- a/ChironCore/cfg/cfgBuilder.py +++ b/ChironCore/cfg/cfgBuilder.py @@ -6,6 +6,7 @@ from cfg.ChironCFG import * import ChironAST.ChironAST as ChironAST import ChironAST.ChironTAC as ChironTAC +import ChironSSA.ChironSSA as ChironSSA import networkx as nx from networkx.drawing.nx_agraph import to_agraph @@ -29,7 +30,7 @@ def buildCFG(ir, cfgName="", isSingle=False): # finding leaders in the IR for idx, item in enumerate(ir): #print(idx, item) - if isinstance(item[0], ChironAST.ConditionCommand) or isinstance(item[0], ChironTAC.TAC_ConditionCommand) or isSingle: + if isinstance(item[0], ChironAST.ConditionCommand) or isinstance(item[0], ChironTAC.TAC_ConditionCommand) or isinstance(item[0], ChironSSA.SSA_ConditionCommand) or isSingle: # updating then branch meta data if idx + 1 < len(ir) and (idx + 1 not in leaderIndices): leaderIndices.add(idx + 1) @@ -37,8 +38,7 @@ def buildCFG(ir, cfgName="", isSingle=False): leader2IndicesMap[thenBranchLeader] = idx + 1 indices2LeadersMap[idx + 1] = thenBranchLeader - if idx + item[1] < len(ir) and (idx + item[1] - not in leaderIndices) and (isinstance(item[0], ChironAST.ConditionCommand) or isinstance(item[0], ChironTAC.TAC_ConditionCommand)): + if idx + item[1] < len(ir) and (idx + item[1] not in leaderIndices) and (isinstance(item[0], ChironAST.ConditionCommand) or isinstance(item[0], ChironTAC.TAC_ConditionCommand) or isinstance(item[0], ChironSSA.SSA_ConditionCommand)): leaderIndices.add(idx + item[1]) elseBranchLeader = BasicBlock(str(idx + item[1])) leader2IndicesMap[elseBranchLeader] = idx + item[1] @@ -67,13 +67,13 @@ def buildCFG(ir, cfgName="", isSingle=False): irIdx = (node.instrlist[-1])[1] lastInstr = (node.instrlist[-1])[0] # print (irIdx, lastInstr, type(lastInstr), isinstance(lastInstr, ChironAST.ConditionCommand)) - if isinstance(lastInstr, ChironAST.ConditionCommand) or isinstance(lastInstr, ChironTAC.TAC_ConditionCommand): - if not (isinstance(lastInstr.cond, ChironAST.BoolFalse) or isinstance(lastInstr.cond, ChironTAC.TAC_BoolFalse)): + if isinstance(lastInstr, ChironAST.ConditionCommand) or isinstance(lastInstr, ChironTAC.TAC_ConditionCommand) or isinstance(lastInstr, ChironSSA.SSA_ConditionCommand): + if not (isinstance(lastInstr.cond, ChironAST.BoolFalse) or isinstance(lastInstr.cond, ChironTAC.TAC_BoolFalse) or isinstance(lastInstr.cond, ChironSSA.SSA_BoolFalse)): thenIdx = irIdx + 1 if (irIdx + 1 < len(ir)) else len(ir) thenBB = indices2LeadersMap[thenIdx] cfg.add_edge(node, thenBB, label='Cond_True', color='green') - if not (isinstance(lastInstr.cond, ChironAST.BoolTrue) or isinstance(lastInstr.cond, ChironTAC.TAC_BoolTrue)): + if not (isinstance(lastInstr.cond, ChironAST.BoolTrue) or isinstance(lastInstr.cond, ChironTAC.TAC_BoolTrue) or isinstance(lastInstr.cond, ChironSSA.SSA_BoolTrue)): elseIdx = irIdx + ir[irIdx][1] if (irIdx + ir[irIdx][1] < len(ir)) else len(ir) elseBB = indices2LeadersMap[elseIdx] cfg.add_edge(node, elseBB, label='Cond_False', color='red') @@ -105,4 +105,4 @@ def dumpCFG(cfg, filename="out"): G = nx.relabel_nodes(G, labels) A = to_agraph(G) A.layout('dot') - A.draw(filename + ".png") \ No newline at end of file + A.draw(filename + ".png") From 185cda6f7bc6f303c721fa87a017f2d3aa45de7d Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 4 Mar 2025 22:35:58 +0530 Subject: [PATCH 14/53] rename variables, fix directory structure --- ChironCore/ChironSSA/ChironSSA.py | 102 ++++++------ ChironCore/ChironSSA/ssaBuilder.py | 137 ++++++++-------- .../{ChironAST => ChironTAC}/ChironTAC.py | 98 ++++++------ ChironCore/bmc.py | 52 +++--- ChironCore/cfg/cfgBuilder.py | 12 +- ChironCore/chiron.py | 6 +- ChironCore/example/move.tl | 21 +-- ChironCore/irhandler.py | 150 +++++++++--------- 8 files changed, 289 insertions(+), 289 deletions(-) rename ChironCore/{ChironAST => ChironTAC}/ChironTAC.py (62%) diff --git a/ChironCore/ChironSSA/ChironSSA.py b/ChironCore/ChironSSA/ChironSSA.py index cc08a0f..1c4e478 100644 --- a/ChironCore/ChironSSA/ChironSSA.py +++ b/ChironCore/ChironSSA/ChironSSA.py @@ -3,18 +3,18 @@ class SSA(object): pass # Instruction Classes -class SSA_Instruction(SSA): +class Instruction(SSA): pass -class SSA_PhiCommand(SSA_Instruction): +class PhiCommand(Instruction): def __init__(self, lvar, rvars): self.lvar = lvar self.rvars = rvars def __str__(self): - return self.lvar.__str__() + " = PHI " + ", ".join([var.__str__() for var in list(self.rvars)]) + return self.lvar.__str__() + " = PHI (" + ", ".join([var.__str__() for var in list(self.rvars)]) + ")" -class SSA_AssignmentCommand(SSA_Instruction): +class AssignmentCommand(Instruction): def __init__(self, lvar, rvar1, rvar2, op): self.lvar = lvar self.rvar1 = rvar1 @@ -24,21 +24,21 @@ def __init__(self, lvar, rvar1, rvar2, op): def __str__(self): return self.lvar.__str__() + " = " + self.rvar1.__str__() + " " + self.op + " " + self.rvar2.__str__() -class SSA_ConditionCommand(SSA_Instruction): +class ConditionCommand(Instruction): def __init__(self, condition): self.cond = condition def __str__(self): return "BRANCH: " + self.cond.__str__() -class SSA_AssertCommand(SSA_Instruction): +class AssertCommand(Instruction): def __init__(self, condition): self.cond = condition def __str__(self): return "ASSERT: " + self.cond.__str__() -class SSA_MoveCommand(SSA_Instruction): +class MoveCommand(Instruction): def __init__(self, motion, var): self.direction = motion self.var = var @@ -46,14 +46,14 @@ def __init__(self, motion, var): def __str__(self): return "MOVE: " + self.direction + " " + self.var.__str__() -class SSA_PenCommand(SSA_Instruction): +class PenCommand(Instruction): def __init__(self, penstat): self.status = penstat def __str__(self): return "PEN: " + self.status -class SSA_GotoCommand(SSA_Instruction): +class GotoCommand(Instruction): def __init__(self, x, y): self.xcor = x self.ycor = y @@ -61,22 +61,22 @@ def __init__(self, x, y): def __str__(self): return "goto " + str(self.xcor) + " " + str(self.ycor) -class SSA_NoOpCommand(SSA_Instruction): +class NoOpCommand(Instruction): def __str__(self): return "NoOp" -class SSA_PauseCommand(SSA_Instruction): +class PauseCommand(Instruction): def __str__(self): return "Pause" -class SSA_Expression(SSA): +class Expression(SSA): pass # -- Arithmetic Expressions ------------------------------------------ -class SSA_ArithExpr(SSA_Expression): +class ArithExpr(Expression): pass -class SSA_BinArithOp(SSA_ArithExpr): +class BinArithOp(ArithExpr): def __init__(self, lvar, rvar, op): self.lvar = lvar self.rvar = rvar @@ -85,24 +85,24 @@ def __init__(self, lvar, rvar, op): def __str__(self): return self.lvar.__str__() + " " + self.op + " " + self.rvar.__str__() -class SSA_Sum(SSA_BinArithOp): +class Sum(BinArithOp): def __init__(self, lvar, rvar): - SSA_BinArithOp.__init__(self, lvar, rvar, "+") + BinArithOp.__init__(self, lvar, rvar, "+") -class SSA_Sub(SSA_BinArithOp): +class Sub(BinArithOp): def __init__(self, lvar, rvar): - SSA_BinArithOp.__init__(self, lvar, rvar, "-") + BinArithOp.__init__(self, lvar, rvar, "-") -class SSA_Mul(SSA_BinArithOp): +class Mul(BinArithOp): def __init__(self, lvar, rvar): - SSA_BinArithOp.__init__(self, lvar, rvar, "*") + BinArithOp.__init__(self, lvar, rvar, "*") -class SSA_Div(SSA_BinArithOp): +class Div(BinArithOp): def __init__(self, lvar, rvar): - SSA_BinArithOp.__init__(self, lvar, rvar, "/") + BinArithOp.__init__(self, lvar, rvar, "/") -class SSA_UnaryArithOp(SSA_ArithExpr): +class UnaryArithOp(ArithExpr): def __init__(self, op, var): self.op = op self.var = var @@ -110,16 +110,16 @@ def __init__(self, op, var): def __str__(self): return self.op + " " + self.var.__str__() -class SSA_UMinus(SSA_UnaryArithOp): +class UMinus(UnaryArithOp): def __init__(self, var): - SSA_UnaryArithOp.__init__(self, "-", var) + UnaryArithOp.__init__(self, "-", var) # -- Boolean Expressions -------------------------------------------- -class SSA_BoolExpr(SSA_Expression): +class BoolExpr(Expression): pass -class SSA_BinBoolOp(SSA_BoolExpr): +class BinBoolOp(BoolExpr): def __init__(self, lvar, rvar, op): self.lvar = lvar self.rvar = rvar @@ -128,75 +128,75 @@ def __init__(self, lvar, rvar, op): def __str__(self): return self.lvar.__str__() + " " + self.op + " " + self.rvar.__str__() -class SSA_And(SSA_BinBoolOp): +class And(BinBoolOp): def __init__(self, lvar, rvar): - SSA_BinBoolOp.__init__(self, lvar, rvar, "and") + BinBoolOp.__init__(self, lvar, rvar, "and") -class SSA_Or(SSA_BinBoolOp): +class Or(BinBoolOp): def __init__(self, lvar, rvar): - SSA_BinBoolOp.__init__(self, lvar, rvar, "or") + BinBoolOp.__init__(self, lvar, rvar, "or") -class SSA_LT(SSA_BinBoolOp): +class LT(BinBoolOp): def __init__(self, lvar, rvar): - SSA_BinBoolOp.__init__(self, lvar, rvar, "<") + BinBoolOp.__init__(self, lvar, rvar, "<") -class SSA_GT(SSA_BinBoolOp): +class GT(BinBoolOp): def __init__(self, lvar, rvar): - SSA_BinBoolOp.__init__(self, lvar, rvar, ">") + BinBoolOp.__init__(self, lvar, rvar, ">") -class SSA_LTE(SSA_BinBoolOp): +class LTE(BinBoolOp): def __init__(self, lvar, rvar): - SSA_BinBoolOp.__init__(self, lvar, rvar, "<=") + BinBoolOp.__init__(self, lvar, rvar, "<=") -class SSA_GTE(SSA_BinBoolOp): +class GTE(BinBoolOp): def __init__(self, lvar, rvar): - SSA_BinBoolOp.__init__(self, lvar, rvar, ">=") + BinBoolOp.__init__(self, lvar, rvar, ">=") -class SSA_EQ(SSA_BinBoolOp): +class EQ(BinBoolOp): def __init__(self, lvar, rvar): - SSA_BinBoolOp.__init__(self, lvar, rvar, "==") + BinBoolOp.__init__(self, lvar, rvar, "==") -class SSA_NEQ(SSA_BinBoolOp): +class NEQ(BinBoolOp): def __init__(self, lvar, rvar): - SSA_BinBoolOp.__init__(self, lvar, rvar, "!=") + BinBoolOp.__init__(self, lvar, rvar, "!=") -class SSA_Not(SSA_BoolExpr): +class Not(BoolExpr): def __init__(self, var): self.var = var def __str__(self): return "not " + self.var.__str__() -class SSA_PenStatus(SSA_Expression): +class PenStatus(Expression): def __str__(self): return "penstatus" -class SSA_BoolTrue(SSA_Expression): +class BoolTrue(Expression): def __str__(self): return "true" -class SSA_BoolFalse(SSA_Expression): +class BoolFalse(Expression): def __str__(self): return "false" # -- Value Expressions ---------------------------------------------- -class SSA_Value(SSA_Expression): +class Value(Expression): pass -class SSA_Num(SSA_Value): +class Num(Value): def __init__(self, value): self.value = value def __str__(self): return str(self.value) -class SSA_Var(SSA_Value): +class Var(Value): def __init__(self, name): self.name = name def __str__(self): return self.name -class SSA_Unused(SSA_Value): +class Unused(Value): def __str__(self): return "" diff --git a/ChironCore/ChironSSA/ssaBuilder.py b/ChironCore/ChironSSA/ssaBuilder.py index ac7ee55..633e9a0 100644 --- a/ChironCore/ChironSSA/ssaBuilder.py +++ b/ChironCore/ChironSSA/ssaBuilder.py @@ -1,5 +1,5 @@ from cfg.ChironCFG import * -import ChironAST.ChironTAC as ChironTAC +import ChironTAC.ChironTAC as ChironTAC import ChironSSA.ChironSSA as ChironSSA def buildSSA(tac, cfg, line2BlockMap): @@ -16,7 +16,7 @@ def buildSSA(tac, cfg, line2BlockMap): # Initialize for (stmt, tgt), line in zip(tac, range(len(tac))): - if isinstance(stmt, ChironTAC.TAC_AssignmentCommand): + if isinstance(stmt, ChironTAC.AssignmentCommand): varCounter[stmt.lvar.__str__()] = 0 for node in cfg: @@ -25,19 +25,16 @@ def buildSSA(tac, cfg, line2BlockMap): # Renamed the declarations of variables in TAC for (stmt, tgt), line in zip(tac, range(len(tac))): - if isinstance(stmt, ChironTAC.TAC_AssignmentCommand): + if isinstance(stmt, ChironTAC.AssignmentCommand): var = stmt.lvar.__str__() lastDeclaration[line2BlockMap[line]][var] = varCounter[var] varCounter[var] += 1 - stmt.lvar = ChironTAC.TAC_Var(f"{var}__{varCounter[var] - 1}") + stmt.lvar = ChironTAC.Var(f"{var}__{varCounter[var] - 1}") tac[line] = (stmt, tgt) for node in cfg: predes = cfg.predecessors(node) for parent in predes: - if lastDeclaration.get(parent) == None: - continue - for var in lastDeclaration[parent]: if var not in phiStatements[node]: phiStatements[node][var] = [] @@ -59,111 +56,111 @@ def buildSSA(tac, cfg, line2BlockMap): for var in phiStatements[node].keys(): if len(phiStatements[node][var]) > 1: ssaLineCounter += 1 - ssa.append((ChironSSA.SSA_PhiCommand(ChironSSA.SSA_Var(f"{var}__{varCounter[var]}"), [ChironSSA.SSA_Var(f"{var}__{version}") for version in phiStatements[node][var]]), 1)) + ssa.append((ChironSSA.PhiCommand(ChironSSA.Var(f"{var}__{varCounter[var]}"), [ChironSSA.Var(f"{var}__{version}") for version in phiStatements[node][var]]), 1)) lastUsed[var] = varCounter[var] varCounter[var] += 1 - if isinstance(stmt, ChironTAC.TAC_AssignmentCommand): + if isinstance(stmt, ChironTAC.AssignmentCommand): rvar1 = None rvar2 = None - if isinstance(stmt.rvar1, ChironTAC.TAC_Var): + if isinstance(stmt.rvar1, ChironTAC.Var): if stmt.rvar1.__str__() not in lastUsed.keys(): lastUsed[stmt.rvar1.__str__()] = 0 - rvar1 = ChironSSA.SSA_Var(f"{stmt.rvar1.__str__()}__{lastUsed[stmt.rvar1.__str__()]}") - elif isinstance(stmt.rvar1, ChironTAC.TAC_BoolTrue): - rvar1 = ChironSSA.SSA_BoolTrue() - elif isinstance(stmt.rvar1, ChironTAC.TAC_BoolFalse): - rvar1 = ChironSSA.SSA_BoolFalse() - elif isinstance(stmt.rvar1, ChironTAC.TAC_Num): - rvar1 = ChironSSA.SSA_Num(stmt.rvar1.value) - if isinstance(stmt.rvar2, ChironTAC.TAC_Var): + rvar1 = ChironSSA.Var(f"{stmt.rvar1.__str__()}__{lastUsed[stmt.rvar1.__str__()]}") + elif isinstance(stmt.rvar1, ChironTAC.BoolTrue): + rvar1 = ChironSSA.BoolTrue() + elif isinstance(stmt.rvar1, ChironTAC.BoolFalse): + rvar1 = ChironSSA.BoolFalse() + elif isinstance(stmt.rvar1, ChironTAC.Num): + rvar1 = ChironSSA.Num(stmt.rvar1.value) + if isinstance(stmt.rvar2, ChironTAC.Var): if stmt.rvar2.__str__() not in lastUsed.keys(): lastUsed[stmt.rvar2.__str__()] = 0 - rvar2 = ChironSSA.SSA_Var(f"{stmt.rvar2.__str__()}__{lastUsed[stmt.rvar2.__str__()]}") - elif isinstance(stmt.rvar2, ChironTAC.TAC_BoolTrue): - rvar2 = ChironSSA.SSA_BoolTrue() - elif isinstance(stmt.rvar2, ChironTAC.TAC_BoolFalse): - rvar2 = ChironSSA.SSA_BoolFalse() - elif isinstance(stmt.rvar2, ChironTAC.TAC_Num): - rvar2 = ChironSSA.SSA_Num(stmt.rvar2.value) - lvar = ChironSSA.SSA_Var(f"{stmt.lvar.__str__()}") + rvar2 = ChironSSA.Var(f"{stmt.rvar2.__str__()}__{lastUsed[stmt.rvar2.__str__()]}") + elif isinstance(stmt.rvar2, ChironTAC.BoolTrue): + rvar2 = ChironSSA.BoolTrue() + elif isinstance(stmt.rvar2, ChironTAC.BoolFalse): + rvar2 = ChironSSA.BoolFalse() + elif isinstance(stmt.rvar2, ChironTAC.Num): + rvar2 = ChironSSA.Num(stmt.rvar2.value) + lvar = ChironSSA.Var(f"{stmt.lvar.__str__()}") lvar_string = lvar.__str__().rsplit('__', 1)[0] lastUsed[lvar_string] = int(lvar.__str__().rsplit('__', 1)[1]) ssaLineCounter += 1 - ssa.append((ChironSSA.SSA_AssignmentCommand(lvar, rvar1, rvar2, stmt.op), tgt)) + ssa.append((ChironSSA.AssignmentCommand(lvar, rvar1, rvar2, stmt.op), tgt)) - elif isinstance(stmt, ChironTAC.TAC_ConditionCommand): + elif isinstance(stmt, ChironTAC.ConditionCommand): tgt_block = line2BlockMap[line + tgt] - if isinstance(stmt.cond, ChironTAC.TAC_BoolTrue): - ssa.append((ChironSSA.SSA_ConditionCommand(ChironSSA.SSA_BoolTrue()), tgt_block)) - elif isinstance(stmt.cond, ChironTAC.TAC_BoolFalse): - ssa.append((ChironSSA.SSA_ConditionCommand(ChironSSA.SSA_BoolFalse()), tgt_block)) + if isinstance(stmt.cond, ChironTAC.BoolTrue): + ssa.append((ChironSSA.ConditionCommand(ChironSSA.BoolTrue()), tgt_block)) + elif isinstance(stmt.cond, ChironTAC.BoolFalse): + ssa.append((ChironSSA.ConditionCommand(ChironSSA.BoolFalse()), tgt_block)) else: - if isinstance(stmt.cond, ChironTAC.TAC_Var): + if isinstance(stmt.cond, ChironTAC.Var): if stmt.cond.__str__() not in lastUsed.keys(): lastUsed[stmt.cond.__str__()] = 0 - cond = ChironSSA.SSA_Var(f"{stmt.cond.__str__()}__{lastUsed[stmt.cond.__str__()]}") - elif isinstance(stmt.cond, ChironTAC.TAC_Num): - cond = ChironSSA.SSA_Num(stmt.cond.value) - ssa.append((ChironSSA.SSA_ConditionCommand(cond), tgt_block)) + cond = ChironSSA.Var(f"{stmt.cond.__str__()}__{lastUsed[stmt.cond.__str__()]}") + elif isinstance(stmt.cond, ChironTAC.Num): + cond = ChironSSA.Num(stmt.cond.value) + ssa.append((ChironSSA.ConditionCommand(cond), tgt_block)) ssaLineCounter += 1 - elif isinstance(stmt, ChironTAC.TAC_AssertCommand): - if isinstance(stmt.cond, ChironTAC.TAC_BoolTrue): - ssa.append((ChironSSA.SSA_AssertCommand(ChironSSA.SSA_BoolTrue()), tgt)) - elif isinstance(stmt.cond, ChironTAC.TAC_BoolFalse): - ssa.append((ChironSSA.SSA_AssertCommand(ChironSSA.SSA_BoolFalse()), tgt)) + elif isinstance(stmt, ChironTAC.AssertCommand): + if isinstance(stmt.cond, ChironTAC.BoolTrue): + ssa.append((ChironSSA.AssertCommand(ChironSSA.BoolTrue()), tgt)) + elif isinstance(stmt.cond, ChironTAC.BoolFalse): + ssa.append((ChironSSA.AssertCommand(ChironSSA.BoolFalse()), tgt)) else: - if isinstance(stmt.cond, ChironTAC.TAC_Var): + if isinstance(stmt.cond, ChironTAC.Var): if stmt.cond.__str__() not in lastUsed.keys(): lastUsed[stmt.cond.__str__()] = 0 - cond = ChironSSA.SSA_Var(f"{stmt.cond.__str__()}__{lastUsed[stmt.cond.__str__()]}") - elif isinstance(stmt.cond, ChironTAC.TAC_Num): - cond = ChironSSA.SSA_Num(stmt.cond.value) - ssa.append((ChironSSA.SSA_AssertCommand(cond), tgt)) + cond = ChironSSA.Var(f"{stmt.cond.__str__()}__{lastUsed[stmt.cond.__str__()]}") + elif isinstance(stmt.cond, ChironTAC.Num): + cond = ChironSSA.Num(stmt.cond.value) + ssa.append((ChironSSA.AssertCommand(cond), tgt)) ssaLineCounter += 1 - elif isinstance(stmt, ChironTAC.TAC_MoveCommand): + elif isinstance(stmt, ChironTAC.MoveCommand): var = None - if isinstance(stmt.var, ChironTAC.TAC_Var): + if isinstance(stmt.var, ChironTAC.Var): if stmt.var.__str__() not in lastUsed.keys(): lastUsed[stmt.var.__str__()] = 0 - var = ChironSSA.SSA_Var(f"{stmt.var.__str__()}__{lastUsed[stmt.var.__str__()]}") - elif isinstance(stmt.var, ChironTAC.TAC_Num): - var = ChironSSA.SSA_Num(stmt.var.value) - ssa.append((ChironSSA.SSA_MoveCommand(stmt.direction, var), tgt)) + var = ChironSSA.Var(f"{stmt.var.__str__()}__{lastUsed[stmt.var.__str__()]}") + elif isinstance(stmt.var, ChironTAC.Num): + var = ChironSSA.Num(stmt.var.value) + ssa.append((ChironSSA.MoveCommand(stmt.direction, var), tgt)) ssaLineCounter += 1 - elif isinstance(stmt, ChironTAC.TAC_PenCommand): - ssa.append((ChironSSA.SSA_PenCommand(stmt.status), tgt)) + elif isinstance(stmt, ChironTAC.PenCommand): + ssa.append((ChironSSA.PenCommand(stmt.status), tgt)) ssaLineCounter += 1 - elif isinstance(stmt, ChironTAC.TAC_GotoCommand): + elif isinstance(stmt, ChironTAC.GotoCommand): x_var = None y_var = None - if isinstance(stmt.xcor, ChironTAC.TAC_Var): + if isinstance(stmt.xcor, ChironTAC.Var): if stmt.xcor.__str__() not in lastUsed.keys(): lastUsed[stmt.xcor.__str__()] = 0 - x_var = ChironSSA.SSA_Var(f"{stmt.xcor.__str__()}__{lastUsed[stmt.xcor.__str__()]}") - elif isinstance(stmt.xcor, ChironTAC.TAC_Num): - x_var = ChironSSA.SSA_Num(stmt.xcor.value) - if isinstance(stmt.ycor, ChironTAC.TAC_Var): + x_var = ChironSSA.Var(f"{stmt.xcor.__str__()}__{lastUsed[stmt.xcor.__str__()]}") + elif isinstance(stmt.xcor, ChironTAC.Num): + x_var = ChironSSA.Num(stmt.xcor.value) + if isinstance(stmt.ycor, ChironTAC.Var): if stmt.ycor.__str__() not in lastUsed.keys(): lastUsed[stmt.ycor.__str__()] = 0 - y_var = ChironSSA.SSA_Var(f"{stmt.ycor.__str__()}__{lastUsed[stmt.ycor.__str__()]}") - elif isinstance(stmt.ycor, ChironTAC.TAC_Num): - y_var = ChironSSA.SSA_Num(stmt.ycor.value) - ssa.append((ChironSSA.SSA_GotoCommand(x_var, y_var), tgt)) + y_var = ChironSSA.Var(f"{stmt.ycor.__str__()}__{lastUsed[stmt.ycor.__str__()]}") + elif isinstance(stmt.ycor, ChironTAC.Num): + y_var = ChironSSA.Num(stmt.ycor.value) + ssa.append((ChironSSA.GotoCommand(x_var, y_var), tgt)) ssaLineCounter += 1 - elif isinstance(stmt, ChironTAC.TAC_NoOpCommand): - ssa.append((ChironSSA.SSA_NoOpCommand(), tgt)) + elif isinstance(stmt, ChironTAC.NoOpCommand): + ssa.append((ChironSSA.NoOpCommand(), tgt)) ssaLineCounter += 1 - elif isinstance(stmt, ChironTAC.TAC_PauseCommand): - ssa.append((ChironSSA.SSA_PauseCommand(), tgt)) + elif isinstance(stmt, ChironTAC.PauseCommand): + ssa.append((ChironSSA.PauseCommand(), tgt)) ssaLineCounter += 1 else: @@ -172,7 +169,7 @@ def buildSSA(tac, cfg, line2BlockMap): block2ssaLine[line2BlockMap[len(tac)]] = ssaLineCounter for (stmt, tgt), line in zip(ssa, range(len(ssa))): - if isinstance(stmt, ChironSSA.SSA_ConditionCommand): + if isinstance(stmt, ChironSSA.ConditionCommand): tgt = block2ssaLine[tgt] - line ssa[line] = (stmt, tgt) diff --git a/ChironCore/ChironAST/ChironTAC.py b/ChironCore/ChironTAC/ChironTAC.py similarity index 62% rename from ChironCore/ChironAST/ChironTAC.py rename to ChironCore/ChironTAC/ChironTAC.py index 6779036..df5bbad 100644 --- a/ChironCore/ChironAST/ChironTAC.py +++ b/ChironCore/ChironTAC/ChironTAC.py @@ -3,10 +3,10 @@ class TAC(object): pass # Instruction Classes -class TAC_Instruction(TAC): +class Instruction(TAC): pass -class TAC_AssignmentCommand(TAC_Instruction): +class AssignmentCommand(Instruction): def __init__(self, lvar, rvar1, rvar2, op): self.lvar = lvar self.rvar1 = rvar1 @@ -16,21 +16,21 @@ def __init__(self, lvar, rvar1, rvar2, op): def __str__(self): return self.lvar.__str__() + " = " + self.rvar1.__str__() + " " + self.op + " " + self.rvar2.__str__() -class TAC_ConditionCommand(TAC_Instruction): +class ConditionCommand(Instruction): def __init__(self, condition): self.cond = condition def __str__(self): return "BRANCH: " + self.cond.__str__() -class TAC_AssertCommand(TAC_Instruction): +class AssertCommand(Instruction): def __init__(self, condition): self.cond = condition def __str__(self): return "ASSERT: " + self.cond.__str__() -class TAC_MoveCommand(TAC_Instruction): +class MoveCommand(Instruction): def __init__(self, motion, var): self.direction = motion self.var = var @@ -38,14 +38,14 @@ def __init__(self, motion, var): def __str__(self): return "MOVE: " + self.direction + " " + self.var.__str__() -class TAC_PenCommand(TAC_Instruction): +class PenCommand(Instruction): def __init__(self, penstat): self.status = penstat def __str__(self): return "PEN: " + self.status -class TAC_GotoCommand(TAC_Instruction): +class GotoCommand(Instruction): def __init__(self, x, y): self.xcor = x self.ycor = y @@ -53,22 +53,22 @@ def __init__(self, x, y): def __str__(self): return "goto " + str(self.xcor) + " " + str(self.ycor) -class TAC_NoOpCommand(TAC_Instruction): +class NoOpCommand(Instruction): def __str__(self): return "NoOp" -class TAC_PauseCommand(TAC_Instruction): +class PauseCommand(Instruction): def __str__(self): return "Pause" -class TAC_Expression(TAC): +class Expression(TAC): pass # -- Arithmetic Expressions ------------------------------------------ -class TAC_ArithExpr(TAC_Expression): +class ArithExpr(Expression): pass -class TAC_BinArithOp(TAC_ArithExpr): +class BinArithOp(ArithExpr): def __init__(self, lvar, rvar, op): self.lvar = lvar self.rvar = rvar @@ -77,24 +77,24 @@ def __init__(self, lvar, rvar, op): def __str__(self): return self.lvar.__str__() + " " + self.op + " " + self.rvar.__str__() -class TAC_Sum(TAC_BinArithOp): +class Sum(BinArithOp): def __init__(self, lvar, rvar): - TAC_BinArithOp.__init__(self, lvar, rvar, "+") + BinArithOp.__init__(self, lvar, rvar, "+") -class TAC_Sub(TAC_BinArithOp): +class Sub(BinArithOp): def __init__(self, lvar, rvar): - TAC_BinArithOp.__init__(self, lvar, rvar, "-") + BinArithOp.__init__(self, lvar, rvar, "-") -class TAC_Mul(TAC_BinArithOp): +class Mul(BinArithOp): def __init__(self, lvar, rvar): - TAC_BinArithOp.__init__(self, lvar, rvar, "*") + BinArithOp.__init__(self, lvar, rvar, "*") -class TAC_Div(TAC_BinArithOp): +class Div(BinArithOp): def __init__(self, lvar, rvar): - TAC_BinArithOp.__init__(self, lvar, rvar, "/") + BinArithOp.__init__(self, lvar, rvar, "/") -class TAC_UnaryArithOp(TAC_ArithExpr): +class UnaryArithOp(ArithExpr): def __init__(self, op, var): self.op = op self.var = var @@ -102,16 +102,16 @@ def __init__(self, op, var): def __str__(self): return self.op + " " + self.var.__str__() -class TAC_UMinus(TAC_UnaryArithOp): +class UMinus(UnaryArithOp): def __init__(self, var): - TAC_UnaryArithOp.__init__(self, "-", var) + UnaryArithOp.__init__(self, "-", var) # -- Boolean Expressions -------------------------------------------- -class TAC_BoolExpr(TAC_Expression): +class BoolExpr(Expression): pass -class TAC_BinBoolOp(TAC_BoolExpr): +class BinBoolOp(BoolExpr): def __init__(self, lvar, rvar, op): self.lvar = lvar self.rvar = rvar @@ -120,75 +120,75 @@ def __init__(self, lvar, rvar, op): def __str__(self): return self.lvar.__str__() + " " + self.op + " " + self.rvar.__str__() -class TAC_And(TAC_BinBoolOp): +class And(BinBoolOp): def __init__(self, lvar, rvar): - TAC_BinBoolOp.__init__(self, lvar, rvar, "and") + BinBoolOp.__init__(self, lvar, rvar, "and") -class TAC_Or(TAC_BinBoolOp): +class Or(BinBoolOp): def __init__(self, lvar, rvar): - TAC_BinBoolOp.__init__(self, lvar, rvar, "or") + BinBoolOp.__init__(self, lvar, rvar, "or") -class TAC_LT(TAC_BinBoolOp): +class LT(BinBoolOp): def __init__(self, lvar, rvar): - TAC_BinBoolOp.__init__(self, lvar, rvar, "<") + BinBoolOp.__init__(self, lvar, rvar, "<") -class TAC_GT(TAC_BinBoolOp): +class GT(BinBoolOp): def __init__(self, lvar, rvar): - TAC_BinBoolOp.__init__(self, lvar, rvar, ">") + BinBoolOp.__init__(self, lvar, rvar, ">") -class TAC_LTE(TAC_BinBoolOp): +class LTE(BinBoolOp): def __init__(self, lvar, rvar): - TAC_BinBoolOp.__init__(self, lvar, rvar, "<=") + BinBoolOp.__init__(self, lvar, rvar, "<=") -class TAC_GTE(TAC_BinBoolOp): +class GTE(BinBoolOp): def __init__(self, lvar, rvar): - TAC_BinBoolOp.__init__(self, lvar, rvar, ">=") + BinBoolOp.__init__(self, lvar, rvar, ">=") -class TAC_EQ(TAC_BinBoolOp): +class EQ(BinBoolOp): def __init__(self, lvar, rvar): - TAC_BinBoolOp.__init__(self, lvar, rvar, "==") + BinBoolOp.__init__(self, lvar, rvar, "==") -class TAC_NEQ(TAC_BinBoolOp): +class NEQ(BinBoolOp): def __init__(self, lvar, rvar): - TAC_BinBoolOp.__init__(self, lvar, rvar, "!=") + BinBoolOp.__init__(self, lvar, rvar, "!=") -class TAC_Not(TAC_BoolExpr): +class Not(BoolExpr): def __init__(self, var): self.var = var def __str__(self): return "not " + self.var.__str__() -class TAC_PenStatus(TAC_Expression): +class PenStatus(Expression): def __str__(self): return "penstatus" -class TAC_BoolTrue(TAC_Expression): +class BoolTrue(Expression): def __str__(self): return "true" -class TAC_BoolFalse(TAC_Expression): +class BoolFalse(Expression): def __str__(self): return "false" # -- Value Expressions ---------------------------------------------- -class TAC_Value(TAC_Expression): +class Value(Expression): pass -class TAC_Num(TAC_Value): +class Num(Value): def __init__(self, value): self.value = value def __str__(self): return str(self.value) -class TAC_Var(TAC_Value): +class Var(Value): def __init__(self, name): self.name = name def __str__(self): return self.name -class TAC_Unused(TAC_Value): +class Unused(Value): def __str__(self): return "" diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 6e3703b..cae5c19 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -11,62 +11,62 @@ def __init__(self, ir): def convert_SSA_to_SMT(self): for stmt, tgt in self.ir: - if isinstance(stmt, ChironSSA.SSA_PhiCommand): # TODO: Add support for Phi commands + if isinstance(stmt, ChironSSA.PhiCommand): # TODO: Add support for Phi commands lvar = z3.Int(stmt.lvar.name) rvars = [] for rvar in stmt.rvars: - if isinstance(rvar, ChironSSA.SSA_Var): + if isinstance(rvar, ChironSSA.Var): rvars.append(z3.Int(rvar.name)) - elif isinstance(rvar, ChironSSA.SSA_Num): + elif isinstance(rvar, ChironSSA.Num): rvars.append(z3.IntVal(rvar.value)) - elif isinstance(rvar, ChironSSA.SSA_BoolTrue): + elif isinstance(rvar, ChironSSA.BoolTrue): rvars.append(z3.BoolVal(True)) - elif isinstance(rvar, ChironSSA.SSA_BoolFalse): + elif isinstance(rvar, ChironSSA.BoolFalse): rvars.append(z3.BoolVal(False)) or_expr = z3.Or([lvar == rvar for rvar in rvars]) self.solver.add(or_expr) - elif isinstance(stmt, ChironSSA.SSA_AssignmentCommand): + elif isinstance(stmt, ChironSSA.AssignmentCommand): lvar = None rvar1 = None rvar2 = None if stmt.op in ["+", "-", "*", "/"]: lvar = z3.Int(stmt.lvar.name) - if isinstance(stmt.rvar1, ChironSSA.SSA_Var): + if isinstance(stmt.rvar1, ChironSSA.Var): rvar1 = z3.Int(stmt.rvar1.name) - elif isinstance(stmt.rvar1, ChironSSA.SSA_Num): + elif isinstance(stmt.rvar1, ChironSSA.Num): rvar1 = z3.IntVal(stmt.rvar1.value) - if isinstance(stmt.rvar2, ChironSSA.SSA_Var): + if isinstance(stmt.rvar2, ChironSSA.Var): rvar2 = z3.Int(stmt.rvar2.name) - elif isinstance(stmt.rvar2, ChironSSA.SSA_Num): + elif isinstance(stmt.rvar2, ChironSSA.Num): rvar2 = z3.IntVal(stmt.rvar2.value) elif stmt.op in ["<", ">", "<=", ">=", "==", "!="]: lvar = z3.Bool(stmt.lvar.name) - if isinstance(stmt.rvar1, ChironSSA.SSA_Var): + if isinstance(stmt.rvar1, ChironSSA.Var): rvar1 = z3.Int(stmt.rvar1.name) - elif isinstance(stmt.rvar1, ChironSSA.SSA_Num): + elif isinstance(stmt.rvar1, ChironSSA.Num): rvar1 = z3.IntVal(stmt.rvar1.value) - if isinstance(stmt.rvar2, ChironSSA.SSA_Var): + if isinstance(stmt.rvar2, ChironSSA.Var): rvar2 = z3.Int(stmt.rvar2.name) - elif isinstance(stmt.rvar2, ChironSSA.SSA_Num): + elif isinstance(stmt.rvar2, ChironSSA.Num): rvar2 = z3.IntVal(stmt.rvar2.value) elif stmt.op in ["and", "or"]: lvar = z3.Bool(stmt.lvar.name) - if isinstance(stmt.rvar1, ChironSSA.SSA_Var): + if isinstance(stmt.rvar1, ChironSSA.Var): rvar1 = z3.Bool(stmt.rvar1.name) - elif isinstance(stmt.rvar1, ChironSSA.SSA_BoolTrue): + elif isinstance(stmt.rvar1, ChironSSA.BoolTrue): rvar1 = z3.BoolVal(True) - if isinstance(stmt.rvar2, ChironSSA.SSA_Var): + if isinstance(stmt.rvar2, ChironSSA.Var): rvar2 = z3.Bool(stmt.rvar2.name) - elif isinstance(stmt.rvar2, ChironSSA.SSA_BoolFalse): + elif isinstance(stmt.rvar2, ChironSSA.BoolFalse): rvar2 = z3.BoolVal(False) elif stmt.op == "not": lvar = z3.Bool(stmt.lvar.name) - if isinstance(stmt.rvar1, ChironSSA.SSA_Var): + if isinstance(stmt.rvar1, ChironSSA.Var): rvar1 = z3.Bool(stmt.rvar1.name) - elif isinstance(stmt.rvar1, ChironSSA.SSA_BoolTrue): + elif isinstance(stmt.rvar1, ChironSSA.BoolTrue): rvar1 = z3.BoolVal(True) - elif isinstance(stmt.rvar1, ChironSSA.SSA_BoolFalse): + elif isinstance(stmt.rvar1, ChironSSA.BoolFalse): rvar1 = z3.BoolVal(False) else: raise Exception("Unknown SSA instruction") @@ -98,13 +98,13 @@ def convert_SSA_to_SMT(self): elif stmt.op == "not": self.solver.add(lvar == z3.Not(rvar1)) - elif isinstance(stmt, ChironSSA.SSA_AssertCommand): + elif isinstance(stmt, ChironSSA.AssertCommand): cond = None - if isinstance(stmt.cond, ChironSSA.SSA_BoolTrue): + if isinstance(stmt.cond, ChironSSA.BoolTrue): cond = z3.BoolVal(True) - elif isinstance(stmt.cond, ChironSSA.SSA_BoolFalse): + elif isinstance(stmt.cond, ChironSSA.BoolFalse): cond = z3.BoolVal(False) - elif isinstance(stmt.cond, ChironSSA.SSA_Var): + elif isinstance(stmt.cond, ChironSSA.Var): cond = z3.Bool(stmt.cond.name) self.solver.add(z3.Not(cond)) @@ -127,4 +127,4 @@ def solve(self): print("Condition not satisfied!") print(self.solver.model()) else: - print("Condition always holds true!") \ No newline at end of file + print("Condition always holds true!") diff --git a/ChironCore/cfg/cfgBuilder.py b/ChironCore/cfg/cfgBuilder.py index 8983e48..21ec892 100644 --- a/ChironCore/cfg/cfgBuilder.py +++ b/ChironCore/cfg/cfgBuilder.py @@ -5,7 +5,7 @@ from cfg.ChironCFG import * import ChironAST.ChironAST as ChironAST -import ChironAST.ChironTAC as ChironTAC +import ChironTAC.ChironTAC as ChironTAC import ChironSSA.ChironSSA as ChironSSA import networkx as nx @@ -30,7 +30,7 @@ def buildCFG(ir, cfgName="", isSingle=False): # finding leaders in the IR for idx, item in enumerate(ir): #print(idx, item) - if isinstance(item[0], ChironAST.ConditionCommand) or isinstance(item[0], ChironTAC.TAC_ConditionCommand) or isinstance(item[0], ChironSSA.SSA_ConditionCommand) or isSingle: + if isinstance(item[0], ChironAST.ConditionCommand) or isinstance(item[0], ChironTAC.ConditionCommand) or isinstance(item[0], ChironSSA.ConditionCommand) or isSingle: # updating then branch meta data if idx + 1 < len(ir) and (idx + 1 not in leaderIndices): leaderIndices.add(idx + 1) @@ -38,7 +38,7 @@ def buildCFG(ir, cfgName="", isSingle=False): leader2IndicesMap[thenBranchLeader] = idx + 1 indices2LeadersMap[idx + 1] = thenBranchLeader - if idx + item[1] < len(ir) and (idx + item[1] not in leaderIndices) and (isinstance(item[0], ChironAST.ConditionCommand) or isinstance(item[0], ChironTAC.TAC_ConditionCommand) or isinstance(item[0], ChironSSA.SSA_ConditionCommand)): + if idx + item[1] < len(ir) and (idx + item[1] not in leaderIndices) and (isinstance(item[0], ChironAST.ConditionCommand) or isinstance(item[0], ChironTAC.ConditionCommand) or isinstance(item[0], ChironSSA.ConditionCommand)): leaderIndices.add(idx + item[1]) elseBranchLeader = BasicBlock(str(idx + item[1])) leader2IndicesMap[elseBranchLeader] = idx + item[1] @@ -67,13 +67,13 @@ def buildCFG(ir, cfgName="", isSingle=False): irIdx = (node.instrlist[-1])[1] lastInstr = (node.instrlist[-1])[0] # print (irIdx, lastInstr, type(lastInstr), isinstance(lastInstr, ChironAST.ConditionCommand)) - if isinstance(lastInstr, ChironAST.ConditionCommand) or isinstance(lastInstr, ChironTAC.TAC_ConditionCommand) or isinstance(lastInstr, ChironSSA.SSA_ConditionCommand): - if not (isinstance(lastInstr.cond, ChironAST.BoolFalse) or isinstance(lastInstr.cond, ChironTAC.TAC_BoolFalse) or isinstance(lastInstr.cond, ChironSSA.SSA_BoolFalse)): + if isinstance(lastInstr, ChironAST.ConditionCommand) or isinstance(lastInstr, ChironTAC.ConditionCommand) or isinstance(lastInstr, ChironSSA.ConditionCommand): + if not (isinstance(lastInstr.cond, ChironAST.BoolFalse) or isinstance(lastInstr.cond, ChironTAC.BoolFalse) or isinstance(lastInstr.cond, ChironSSA.BoolFalse)): thenIdx = irIdx + 1 if (irIdx + 1 < len(ir)) else len(ir) thenBB = indices2LeadersMap[thenIdx] cfg.add_edge(node, thenBB, label='Cond_True', color='green') - if not (isinstance(lastInstr.cond, ChironAST.BoolTrue) or isinstance(lastInstr.cond, ChironTAC.TAC_BoolTrue) or isinstance(lastInstr.cond, ChironSSA.SSA_BoolTrue)): + if not (isinstance(lastInstr.cond, ChironAST.BoolTrue) or isinstance(lastInstr.cond, ChironTAC.BoolTrue) or isinstance(lastInstr.cond, ChironSSA.BoolTrue)): elseIdx = irIdx + ir[irIdx][1] if (irIdx + ir[irIdx][1] < len(ir)) else len(ir) elseBB = indices2LeadersMap[elseIdx] cfg.add_edge(node, elseBB, label='Cond_False', color='red') diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index d1d3a52..cef061c 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -410,16 +410,16 @@ def stopTurtle(): # tacGen.printTAC() # Printing TAC cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) # Building CFG - cfgB.dumpCFG(cfg, 'tac_cfg.png') + cfgB.dumpCFG(cfg, 'tac_cfg') ssa = buildSSA(tacGen.tac, cfg, line2BlockMap) # Building SSA printSSA(ssa) # Printing SSA ssa_cfg, ssa_line2BlockMap = cfgB.buildCFG(ssa, "ssa_cfg", False) # Building CFG for SSA - cfgB.dumpCFG(ssa_cfg, 'ssa_cfg.png') + cfgB.dumpCFG(ssa_cfg, 'ssa_cfg') print("\nConverting program to SMT-LIB format..\n") smt = bmc.BMC(ssa) smt.convert_SSA_to_SMT() smt.solve() - print("DONE..") \ No newline at end of file + print("DONE..") diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 6254496..f60dd4d 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,10 +1,13 @@ -if (:a > :b) [ - :x = 1 -] else [ - if (:b > :c) [ - :x = 2 - ] else [ - :x = 3 - ] +repeat 3 [ + if (:a > :b) [ + :x = 1 + ] else [ + if (:b > :c) [ + :x = 2 + ] else [ + :x = 3 + ] + ] + :a = :a + 10 ] -:y = :x \ No newline at end of file +:y = :x diff --git a/ChironCore/irhandler.py b/ChironCore/irhandler.py index e40e1bc..54fc8da 100644 --- a/ChironCore/irhandler.py +++ b/ChironCore/irhandler.py @@ -6,7 +6,7 @@ from turtparse.tlangLexer import tlangLexer from ChironAST import ChironAST -from ChironAST import ChironTAC +from ChironTAC import ChironTAC def getParseTree(progfl): @@ -162,38 +162,38 @@ def parseExpresssion(self, expr, dest): left = None right = None if isinstance(expr.lexpr, ChironAST.Num): - left = ChironTAC.TAC_Num(expr.lexpr.val) + left = ChironTAC.Num(expr.lexpr.val) elif isinstance(expr.lexpr, ChironAST.Var): - left = ChironTAC.TAC_Var(expr.lexpr.varname) + left = ChironTAC.Var(expr.lexpr.varname) else: - temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") + temp = ChironTAC.Var(f":__temp_{self.tempCount}") self.tempCount += 1 left = temp self.parseExpresssion(expr.lexpr, temp) if isinstance(expr.rexpr, ChironAST.Num): - right = ChironTAC.TAC_Num(expr.rexpr.val) + right = ChironTAC.Num(expr.rexpr.val) elif isinstance(expr.rexpr, ChironAST.Var): - right = ChironTAC.TAC_Var(expr.rexpr.varname) + right = ChironTAC.Var(expr.rexpr.varname) else: - temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") + temp = ChironTAC.Var(f":__temp_{self.tempCount}") self.tempCount += 1 right = temp self.parseExpresssion(expr.rexpr, temp) self.line += 1 self.tac.append( - (ChironTAC.TAC_AssignmentCommand(dest, left, right, expr.symbol), 1) + (ChironTAC.AssignmentCommand(dest, left, right, expr.symbol), 1) ) elif isinstance(expr, ChironAST.UMinus): if isinstance(expr.expr, ChironAST.Num): self.line += 1 self.tac.append( ( - ChironTAC.TAC_AssignmentCommand( + ChironTAC.AssignmentCommand( dest, - ChironTAC.TAC_Num(0), - ChironTAC.TAC_Num(expr.expr.val), + ChironTAC.Num(0), + ChironTAC.Num(expr.expr.val), "-", ), 1, @@ -203,24 +203,24 @@ def parseExpresssion(self, expr, dest): self.line += 1 self.tac.append( ( - ChironTAC.TAC_AssignmentCommand( + ChironTAC.AssignmentCommand( dest, - ChironTAC.TAC_Num(0), - ChironTAC.TAC_Var(expr.expr.varname), + ChironTAC.Num(0), + ChironTAC.Var(expr.expr.varname), "-", ), 1, ), ) else: - temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") + temp = ChironTAC.Var(f":__temp_{self.tempCount}") self.tempCount += 1 self.parseExpresssion(expr.expr, temp) self.line += 1 self.tac.append( ( - ChironTAC.TAC_AssignmentCommand( - dest, ChironTAC.TAC_Num(0), temp, "-" + ChironTAC.AssignmentCommand( + dest, ChironTAC.Num(0), temp, "-" ), 1, ) @@ -233,69 +233,69 @@ def parseExpresssion(self, expr, dest): left = None right = None if isinstance(expr.lexpr, ChironAST.Num): - left = ChironTAC.TAC_Num(expr.lexpr.val) + left = ChironTAC.Num(expr.lexpr.val) elif isinstance(expr.lexpr, ChironAST.Var): - left = ChironTAC.TAC_Var(expr.lexpr.varname) + left = ChironTAC.Var(expr.lexpr.varname) else: - temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") + temp = ChironTAC.Var(f":__temp_{self.tempCount}") self.tempCount += 1 left = temp self.parseExpresssion(expr.lexpr, temp) if isinstance(expr.rexpr, ChironAST.Num): - right = ChironTAC.TAC_Num(expr.rexpr.val) + right = ChironTAC.Num(expr.rexpr.val) elif isinstance(expr.rexpr, ChironAST.Var): - right = ChironTAC.TAC_Var(expr.rexpr.varname) + right = ChironTAC.Var(expr.rexpr.varname) else: - temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") + temp = ChironTAC.Var(f":__temp_{self.tempCount}") self.tempCount += 1 right = temp self.parseExpresssion(expr.rexpr, temp) self.line += 1 self.tac.append( - (ChironTAC.TAC_AssignmentCommand(dest, left, right, expr.symbol), 1) + (ChironTAC.AssignmentCommand(dest, left, right, expr.symbol), 1) ) elif isinstance(expr, ChironAST.AND) or isinstance(expr, ChironAST.OR): left = None right = None if isinstance(expr.lexpr, ChironAST.BoolTrue): - left = ChironTAC.TAC_BoolTrue() + left = ChironTAC.BoolTrue() elif isinstance(expr.lexpr, ChironAST.BoolFalse): - left = ChironTAC.TAC_BoolFalse() + left = ChironTAC.BoolFalse() elif isinstance(expr.lexpr, ChironAST.Var): - left = ChironTAC.TAC_Var(expr.lexpr.varname) + left = ChironTAC.Var(expr.lexpr.varname) else: - temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") + temp = ChironTAC.Var(f":__temp_{self.tempCount}") self.tempCount += 1 left = temp self.parseExpresssion(expr.lexpr, temp) if isinstance(expr.rexpr, ChironAST.BoolTrue): - right = ChironTAC.TAC_BoolTrue() + right = ChironTAC.BoolTrue() elif isinstance(expr.rexpr, ChironAST.BoolFalse): - right = ChironTAC.TAC_BoolFalse() + right = ChironTAC.BoolFalse() elif isinstance(expr.rexpr, ChironAST.Var): - right = ChironTAC.TAC_Var(expr.rexpr.varname) + right = ChironTAC.Var(expr.rexpr.varname) else: - temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") + temp = ChironTAC.Var(f":__temp_{self.tempCount}") self.tempCount += 1 right = temp self.parseExpresssion(expr.rexpr, temp) self.line += 1 self.tac.append( - (ChironTAC.TAC_AssignmentCommand(dest, left, right, expr.symbol), 1) + (ChironTAC.AssignmentCommand(dest, left, right, expr.symbol), 1) ) elif isinstance(expr, ChironAST.NOT): if isinstance(expr.expr, ChironAST.BoolTrue): self.line += 1 self.tac.append( ( - ChironTAC.TAC_AssignmentCommand( + ChironTAC.AssignmentCommand( dest, - ChironTAC.TAC_Unused(), - ChironTAC.TAC_BoolTrue(), + ChironTAC.Unused(), + ChironTAC.BoolTrue(), "not", ), 1, @@ -305,10 +305,10 @@ def parseExpresssion(self, expr, dest): self.line += 1 self.tac.append( ( - ChironTAC.TAC_AssignmentCommand( + ChironTAC.AssignmentCommand( dest, - ChironTAC.TAC_Unused(), - ChironTAC.TAC_BoolFalse(), + ChironTAC.Unused(), + ChironTAC.BoolFalse(), "not", ), 1, @@ -318,29 +318,29 @@ def parseExpresssion(self, expr, dest): self.line += 1 self.tac.append( ( - ChironTAC.TAC_AssignmentCommand( + ChironTAC.AssignmentCommand( dest, - ChironTAC.TAC_Unused(), - ChironTAC.TAC_Var(expr.expr.varname), + ChironTAC.Unused(), + ChironTAC.Var(expr.expr.varname), "not", ), 1, ) ) else: - temp = ChironTAC.TAC_Var(f":__temp_{self.tempCount}") + temp = ChironTAC.Var(f":__temp_{self.tempCount}") self.tempCount += 1 self.parseExpresssion(expr.expr, temp) self.line += 1 self.tac.append( - (ChironTAC.TAC_AssignmentCommand(dest, None, temp, "not"), 1) + (ChironTAC.AssignmentCommand(dest, None, temp, "not"), 1) ) elif isinstance(expr, ChironAST.Var): self.line += 1 self.tac.append( ( - ChironTAC.TAC_AssignmentCommand( - dest, ChironTAC.TAC_Num(0), ChironTAC.TAC_Var(expr.varname), "+" + ChironTAC.AssignmentCommand( + dest, ChironTAC.Num(0), ChironTAC.Var(expr.varname), "+" ), 1, ) @@ -349,8 +349,8 @@ def parseExpresssion(self, expr, dest): self.line += 1 self.tac.append( ( - ChironTAC.TAC_AssignmentCommand( - dest, ChironTAC.TAC_Num(0), ChironTAC.TAC_Num(expr.val), "+" + ChironTAC.AssignmentCommand( + dest, ChironTAC.Num(0), ChironTAC.Num(expr.val), "+" ), 1, ) @@ -359,8 +359,8 @@ def parseExpresssion(self, expr, dest): self.line += 1 self.tac.append( ( - ChironTAC.TAC_AssignmentCommand( - dest, ChironTAC.TAC_Unused(), ChironTAC.TAC_BoolTrue(), "" + ChironTAC.AssignmentCommand( + dest, ChironTAC.Unused(), ChironTAC.BoolTrue(), "" ), 1, ) @@ -369,8 +369,8 @@ def parseExpresssion(self, expr, dest): self.line += 1 self.tac.append( ( - ChironTAC.TAC_AssignmentCommand( - dest, ChironTAC.TAC_Unused(), ChironTAC.TAC_BoolFalse(), "" + ChironTAC.AssignmentCommand( + dest, ChironTAC.Unused(), ChironTAC.BoolFalse(), "" ), 1, ) @@ -387,71 +387,71 @@ def generateTAC(self): line_number += 1 if isinstance(stmt, ChironAST.AssignmentCommand): - self.parseExpresssion(stmt.rexpr, ChironTAC.TAC_Var(stmt.lvar.varname)) + self.parseExpresssion(stmt.rexpr, ChironTAC.Var(stmt.lvar.varname)) elif isinstance(stmt, ChironAST.ConditionCommand): branchvar = None if isinstance(stmt.cond, ChironAST.BoolTrue): - branchvar = ChironTAC.TAC_BoolTrue() + branchvar = ChironTAC.BoolTrue() elif isinstance(stmt.cond, ChironAST.BoolFalse): - branchvar = ChironTAC.TAC_BoolFalse() + branchvar = ChironTAC.BoolFalse() elif isinstance(stmt.cond, ChironAST.Var): - branchvar = ChironTAC.TAC_Var(stmt.cond.varname) + branchvar = ChironTAC.Var(stmt.cond.varname) else: - branchvar = ChironTAC.TAC_Var(f":__branch_{self.branchCount}") + branchvar = ChironTAC.Var(f":__branch_{self.branchCount}") self.branchCount += 1 self.parseExpresssion(stmt.cond, branchvar) newtgt = line_number - 1 + tgt # Adjusted later self.line += 1 - self.tac.append((ChironTAC.TAC_ConditionCommand(branchvar), newtgt)) + self.tac.append((ChironTAC.ConditionCommand(branchvar), newtgt)) elif isinstance(stmt, ChironAST.AssertCommand): - assertvar = ChironTAC.TAC_Var(f":__assert_{self.assertCount}") + assertvar = ChironTAC.Var(f":__assert_{self.assertCount}") self.assertCount += 1 self.parseExpresssion(stmt.cond, assertvar) self.line += 1 - self.tac.append((ChironTAC.TAC_AssertCommand(assertvar), 1)) + self.tac.append((ChironTAC.AssertCommand(assertvar), 1)) elif isinstance(stmt, ChironAST.MoveCommand): movevar = None if isinstance(stmt.expr, ChironAST.Num): - movevar = ChironTAC.TAC_Num(stmt.expr.val) + movevar = ChironTAC.Num(stmt.expr.val) elif isinstance(stmt.expr, ChironAST.Var): - movevar = ChironTAC.TAC_Var(stmt.expr.varname) + movevar = ChironTAC.Var(stmt.expr.varname) else: - movevar = ChironTAC.TAC_Var(f":__move_{self.moveCount}") + movevar = ChironTAC.Var(f":__move_{self.moveCount}") self.moveCount += 1 self.parseExpresssion(stmt.expr, movevar) self.line += 1 - self.tac.append((ChironTAC.TAC_MoveCommand(stmt.direction, movevar), 1)) + self.tac.append((ChironTAC.MoveCommand(stmt.direction, movevar), 1)) elif isinstance(stmt, ChironAST.PenCommand): self.line += 1 - self.tac.append((ChironTAC.TAC_PenCommand(stmt.status), 1)) + self.tac.append((ChironTAC.PenCommand(stmt.status), 1)) elif isinstance(stmt, ChironAST.GotoCommand): xvar = None yvar = None if isinstance(stmt.xcor, ChironAST.Num): - xvar = ChironTAC.TAC_Num(stmt.xcor.val) + xvar = ChironTAC.Num(stmt.xcor.val) elif isinstance(stmt.xcor, ChironAST.Var): - xvar = ChironTAC.TAC_Var(stmt.xcor.varname) + xvar = ChironTAC.Var(stmt.xcor.varname) else: - xvar = ChironTAC.TAC_Var(f":__x_{self.gotoCount}") + xvar = ChironTAC.Var(f":__x_{self.gotoCount}") self.gotoCount += 1 self.parseExpresssion(stmt.xcor, xvar) if isinstance(stmt.ycor, ChironAST.Num): - yvar = ChironTAC.TAC_Num(stmt.ycor.val) + yvar = ChironTAC.Num(stmt.ycor.val) elif isinstance(stmt.ycor, ChironAST.Var): - yvar = ChironTAC.TAC_Var(stmt.ycor.varname) + yvar = ChironTAC.Var(stmt.ycor.varname) else: - yvar = ChironTAC.TAC_Var(f":__y_{self.gotoCount}") + yvar = ChironTAC.Var(f":__y_{self.gotoCount}") self.gotoCount += 1 self.parseExpresssion(stmt.ycor, yvar) self.line += 1 - self.tac.append((ChironTAC.TAC_GotoCommand(xvar, yvar), 1)) + self.tac.append((ChironTAC.GotoCommand(xvar, yvar), 1)) elif isinstance(stmt, ChironAST.NoOpCommand): self.line += 1 - self.tac.append((ChironTAC.TAC_NoOpCommand(), 1)) + self.tac.append((ChironTAC.NoOpCommand(), 1)) elif isinstance(stmt, ChironAST.PauseCommand): self.line += 1 - self.tac.append((ChironTAC.TAC_PauseCommand(), 1)) + self.tac.append((ChironTAC.PauseCommand(), 1)) else: raise NotImplementedError( "Unknown instruction: %s, %s." % (type(stmt), stmt) @@ -461,7 +461,7 @@ def generateTAC(self): for i in range(len(self.tac)): stmt, tgt = self.tac[i] - if isinstance(stmt, ChironTAC.TAC_ConditionCommand): + if isinstance(stmt, ChironTAC.ConditionCommand): newtgt = self.ast_to_tac_line[tgt] - i self.tac[i] = (stmt, newtgt) From 5c01c861f3b0f4a4045b4bdbd53ae09d69369356 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 4 Mar 2025 23:13:26 +0530 Subject: [PATCH 15/53] fix free variable ssa conversion bug --- ChironCore/ChironSSA/ssaBuilder.py | 5 ++-- ChironCore/bmc.py | 6 +++-- ChironCore/chiron.py | 2 +- ChironCore/irhandler.py | 40 ++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/ChironCore/ChironSSA/ssaBuilder.py b/ChironCore/ChironSSA/ssaBuilder.py index 633e9a0..a10b093 100644 --- a/ChironCore/ChironSSA/ssaBuilder.py +++ b/ChironCore/ChironSSA/ssaBuilder.py @@ -61,8 +61,8 @@ def buildSSA(tac, cfg, line2BlockMap): varCounter[var] += 1 if isinstance(stmt, ChironTAC.AssignmentCommand): - rvar1 = None - rvar2 = None + rvar1 = ChironSSA.Unused() + rvar2 = ChironSSA.Unused() if isinstance(stmt.rvar1, ChironTAC.Var): if stmt.rvar1.__str__() not in lastUsed.keys(): lastUsed[stmt.rvar1.__str__()] = 0 @@ -182,3 +182,4 @@ def printSSA(ssa): print("\nSSA Form:") for (stmt, tgt), line in zip(ssa, range(len(ssa))): print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") + diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index cae5c19..09ac505 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -28,8 +28,8 @@ def convert_SSA_to_SMT(self): elif isinstance(stmt, ChironSSA.AssignmentCommand): lvar = None - rvar1 = None - rvar2 = None + rvar1 = ChironSSA.Unused() + rvar2 = ChironSSA.Unused() if stmt.op in ["+", "-", "*", "/"]: lvar = z3.Int(stmt.lvar.name) if isinstance(stmt.rvar1, ChironSSA.Var): @@ -68,6 +68,8 @@ def convert_SSA_to_SMT(self): rvar1 = z3.BoolVal(True) elif isinstance(stmt.rvar1, ChironSSA.BoolFalse): rvar1 = z3.BoolVal(False) + elif stmt.op == "": + continue else: raise Exception("Unknown SSA instruction") diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index cef061c..be723ea 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -407,7 +407,7 @@ def stopTurtle(): tacGen = TACGenerator(ir) # Converting IR to TAC tacGen.generateTAC() - # tacGen.printTAC() # Printing TAC + tacGen.printTAC() # Printing TAC cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) # Building CFG cfgB.dumpCFG(cfg, 'tac_cfg') diff --git a/ChironCore/irhandler.py b/ChironCore/irhandler.py index 54fc8da..11ce4fd 100644 --- a/ChironCore/irhandler.py +++ b/ChironCore/irhandler.py @@ -465,6 +465,46 @@ def generateTAC(self): newtgt = self.ast_to_tac_line[tgt] - i self.tac[i] = (stmt, newtgt) + self.handleFreeVariables() + + def handleFreeVariables(self): + freeVars = self.getFreeVariables() + + for var in freeVars: + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(var), ChironTAC.Unused(), ChironTAC.Unused(), ""), 0)) + + + def getFreeVariables(self): + """ + Returns free variables in TAC. + """ + freeVars = set() + boundVars = set() + for (stmt, _), _ in zip(self.tac, range(len(self.tac))): + if isinstance(stmt, ChironTAC.AssignmentCommand): + if isinstance(stmt.rvar1, ChironTAC.Var) and stmt.rvar1.__str__() not in boundVars: + freeVars.add(stmt.rvar1.__str__()) + if isinstance(stmt.rvar2, ChironTAC.Var) and stmt.rvar2.__str__() not in boundVars: + freeVars.add(stmt.rvar2.__str__()) + boundVars.add(stmt.lvar.__str__()) + elif isinstance(stmt, ChironTAC.ConditionCommand): + if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: + freeVars.add(stmt.cond.__str__()) + elif isinstance(stmt, ChironTAC.AssertCommand): + if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: + freeVars.add(stmt.cond.__str__()) + elif isinstance(stmt, ChironTAC.MoveCommand): + if isinstance(stmt.var, ChironTAC.Var) and stmt.var.__str__() not in boundVars: + freeVars.add(stmt.var.__str__()) + elif isinstance(stmt, ChironTAC.GotoCommand): + if isinstance(stmt.xcor, ChironTAC.Var) and stmt.xcor.__str__() not in boundVars: + freeVars.add(stmt.xcor.__str__()) + if isinstance(stmt.ycor, ChironTAC.Var) and stmt.ycor.__str__() not in boundVars: + freeVars.add(stmt.ycor.__str__()) + + return freeVars + + def printTAC(self): for (stmt, tgt), line in zip(self.tac, range(len(self.tac))): print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") From d89f28da22e32a9d275dfb7d2c4ae2dbe6361514 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 11 Mar 2025 00:15:18 +0530 Subject: [PATCH 16/53] add condition for each basic block execution --- ChironCore/bmc.py | 21 ++++++++++++++++++++- ChironCore/cfg/ChironCFG.py | 12 +++++++++++- ChironCore/chiron.py | 2 +- ChironCore/example/move.tl | 15 ++++++--------- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 09ac505..cd6374f 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -3,13 +3,31 @@ ''' import z3 from ChironSSA import ChironSSA +from cfg import cfgBuilder class BMC: def __init__(self, ir): self.solver = z3.Solver() self.ir = ir + self.cfg, _ = cfgBuilder.buildCFG(ir) + self.buildConditions() - def convert_SSA_to_SMT(self): + def buildConditions(self): + topological_order = list(self.cfg.get_topological_order()) + for node in topological_order: + for next in self.cfg.successors(node): + next.add_condition(node.get_condition()) + + if len(list(self.cfg.successors(node))) > 1: + condition = z3.Bool(node.instrlist[-1][0].cond.name) + for next in self.cfg.successors(node): + if self.cfg.get_edge_label(node, next) == 'Cond_True': + next.add_condition(condition) + else: + next.add_condition(z3.Not(condition)) + print(f"Node {node.name} has condition {node.get_condition()}") + + def convertBasicBlock(self): for stmt, tgt in self.ir: if isinstance(stmt, ChironSSA.PhiCommand): # TODO: Add support for Phi commands lvar = z3.Int(stmt.lvar.name) @@ -130,3 +148,4 @@ def solve(self): print(self.solver.model()) else: print("Condition always holds true!") + diff --git a/ChironCore/cfg/ChironCFG.py b/ChironCore/cfg/ChironCFG.py index f0230be..708e4f3 100644 --- a/ChironCore/cfg/ChironCFG.py +++ b/ChironCore/cfg/ChironCFG.py @@ -1,11 +1,13 @@ #!/usr/bin/python3.8 import networkx as nx +import z3 class BasicBlock: def __init__(self, bbname): self.name = bbname self.instrlist = [] + self.condition = z3.BoolVal(True) if bbname == "START" or bbname == "END": self.irID = bbname else: @@ -20,9 +22,15 @@ def append(self, instruction): def extend(self, instructions): self.instrlist.extend(instructions) + def add_condition(self, condition): + self.condition = z3.And(self.condition, condition) + + def get_condition(self): + return self.condition + def label(self): if len(self.instrlist): - return '\n'.join(str(instr[0])+'; L'+ str(instr[1]) for instr in self.instrlist) + return self.name + '\n' + '\n'.join(str(instr[0])+'; L'+ str(instr[1]) for instr in self.instrlist) else: return self.name @@ -86,4 +94,6 @@ def get_edge_label(self, u, v): edata = self.nxgraph.get_edge_data(u,v) return edata['label'] if len(edata) else 'T' + def get_topological_order(self): + return list(nx.topological_sort(self.nxgraph)) # TODO: add more methods to expose other methods of the Networkx.DiGraph diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index be723ea..2ace57d 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -420,6 +420,6 @@ def stopTurtle(): print("\nConverting program to SMT-LIB format..\n") smt = bmc.BMC(ssa) - smt.convert_SSA_to_SMT() + smt.convertBasicBlock() smt.solve() print("DONE..") diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index f60dd4d..23145e0 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,13 +1,10 @@ -repeat 3 [ - if (:a > :b) [ - :x = 1 +if (:a > :b) [ + :x = 1 +] else [ + if (:b > :c) [ + :x = 2 ] else [ - if (:b > :c) [ - :x = 2 - ] else [ - :x = 3 - ] + :x = 3 ] - :a = :a + 10 ] :y = :x From e77bce574189fbd5661113ce89437a72449f9d3e Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 11 Mar 2025 10:35:16 +0530 Subject: [PATCH 17/53] fix block condition logic --- ChironCore/bmc.py | 29 ++++++++++++++++++----------- ChironCore/cfg/ChironCFG.py | 6 +++--- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index cd6374f..ca1d11c 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -14,18 +14,25 @@ def __init__(self, ir): def buildConditions(self): topological_order = list(self.cfg.get_topological_order()) + start = topological_order[0] + start.setCondition(z3.BoolVal(True)) + topological_order.pop(0) for node in topological_order: - for next in self.cfg.successors(node): - next.add_condition(node.get_condition()) - - if len(list(self.cfg.successors(node))) > 1: - condition = z3.Bool(node.instrlist[-1][0].cond.name) - for next in self.cfg.successors(node): - if self.cfg.get_edge_label(node, next) == 'Cond_True': - next.add_condition(condition) - else: - next.add_condition(z3.Not(condition)) - print(f"Node {node.name} has condition {node.get_condition()}") + for pred in self.cfg.predecessors(node): + instr = pred.instrlist[-1][0] + current_cond = node.get_condition() + if isinstance(instr, ChironSSA.ConditionCommand) and type(instr.cond) == ChironSSA.Var: + cond = z3.Bool(instr.cond.name) + label = self.cfg.get_edge_label(pred, node) + if label == 'Cond_True': + node.setCondition(z3.Or(current_cond, z3.And(pred.get_condition(), cond))) + elif label == 'Cond_False': + node.setCondition(z3.Or(current_cond, z3.And(pred.get_condition(), z3.Not(cond)))) + else: + node.setCondition(z3.Or(pred.get_condition(), current_cond)) + + t = z3.Tactic('ctx-simplify').apply(node.get_condition()).as_expr() + node.setCondition(t) def convertBasicBlock(self): for stmt, tgt in self.ir: diff --git a/ChironCore/cfg/ChironCFG.py b/ChironCore/cfg/ChironCFG.py index 708e4f3..69ed351 100644 --- a/ChironCore/cfg/ChironCFG.py +++ b/ChironCore/cfg/ChironCFG.py @@ -7,7 +7,7 @@ class BasicBlock: def __init__(self, bbname): self.name = bbname self.instrlist = [] - self.condition = z3.BoolVal(True) + self.condition = z3.BoolVal(False) if bbname == "START" or bbname == "END": self.irID = bbname else: @@ -22,8 +22,8 @@ def append(self, instruction): def extend(self, instructions): self.instrlist.extend(instructions) - def add_condition(self, condition): - self.condition = z3.And(self.condition, condition) + def setCondition(self, condition): + self.condition = condition def get_condition(self): return self.condition From f326a9308d7103ff02772bed694f0986f6393e4d Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 11 Mar 2025 10:40:53 +0530 Subject: [PATCH 18/53] TODO: add basic block conversion --- ChironCore/bmc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index ca1d11c..4917083 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -34,8 +34,8 @@ def buildConditions(self): t = z3.Tactic('ctx-simplify').apply(node.get_condition()).as_expr() node.setCondition(t) - def convertBasicBlock(self): - for stmt, tgt in self.ir: + def convertBasicBlock(self, bb): + for stmt, _ in bb.instrlist: if isinstance(stmt, ChironSSA.PhiCommand): # TODO: Add support for Phi commands lvar = z3.Int(stmt.lvar.name) rvars = [] From f36115bb5c8d701fbff67ec6ecafa702a32d5f6a Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Wed, 12 Mar 2025 12:08:58 +0530 Subject: [PATCH 19/53] set conditions for basic blocks --- ChironCore/bmc.py | 67 +++++++++++++++++++++++--------------------- ChironCore/chiron.py | 4 +-- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 4917083..2aa2d14 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -9,33 +9,36 @@ class BMC: def __init__(self, ir): self.solver = z3.Solver() self.ir = ir - self.cfg, _ = cfgBuilder.buildCFG(ir) - self.buildConditions() + self.cfg, self.line_to_bb_map = cfgBuilder.buildCFG(ir) - def buildConditions(self): - topological_order = list(self.cfg.get_topological_order()) - start = topological_order[0] - start.setCondition(z3.BoolVal(True)) - topological_order.pop(0) - for node in topological_order: - for pred in self.cfg.predecessors(node): - instr = pred.instrlist[-1][0] - current_cond = node.get_condition() - if isinstance(instr, ChironSSA.ConditionCommand) and type(instr.cond) == ChironSSA.Var: - cond = z3.Bool(instr.cond.name) - label = self.cfg.get_edge_label(pred, node) - if label == 'Cond_True': - node.setCondition(z3.Or(current_cond, z3.And(pred.get_condition(), cond))) - elif label == 'Cond_False': - node.setCondition(z3.Or(current_cond, z3.And(pred.get_condition(), z3.Not(cond)))) - else: - node.setCondition(z3.Or(pred.get_condition(), current_cond)) - - t = z3.Tactic('ctx-simplify').apply(node.get_condition()).as_expr() - node.setCondition(t) + self.bbConditions = {} # bbConditions[bb] = condition for bb + for bb in self.cfg: + self.bbConditions[bb] = None + self.bbConditions[self.line_to_bb_map[0]] = z3.BoolVal(True) + + self.setConditions(self.line_to_bb_map[len(self.ir)]) + + def setConditions(self, node): + for pred in self.cfg.predecessors(node): + if self.bbConditions[pred] == None: + self.setConditions(pred) + instr = pred.instrlist[-1][0] + temp_cond = None + if isinstance(instr, ChironSSA.ConditionCommand) and type(instr.cond) == ChironSSA.Var: + edge_label = self.cfg.get_edge_label(pred, node) + if edge_label == 'Cond_True': + temp_cond = z3.And(self.bbConditions[pred], z3.Bool(instr.cond.name)) + elif edge_label == 'Cond_False': + temp_cond = z3.And(self.bbConditions[pred], z3.Not(z3.Bool(instr.cond.name))) + else: + temp_cond = self.bbConditions[pred] + if self.bbConditions[node] == None: + self.bbConditions[node] = temp_cond + else: + self.bbConditions[node] = z3.Or(self.bbConditions[node], temp_cond) - def convertBasicBlock(self, bb): - for stmt, _ in bb.instrlist: + def convertSSAtoSMT(self): + for stmt, tgt in self.ir: if isinstance(stmt, ChironSSA.PhiCommand): # TODO: Add support for Phi commands lvar = z3.Int(stmt.lvar.name) rvars = [] @@ -87,12 +90,12 @@ def convertBasicBlock(self, bb): rvar2 = z3.BoolVal(False) elif stmt.op == "not": lvar = z3.Bool(stmt.lvar.name) - if isinstance(stmt.rvar1, ChironSSA.Var): - rvar1 = z3.Bool(stmt.rvar1.name) - elif isinstance(stmt.rvar1, ChironSSA.BoolTrue): - rvar1 = z3.BoolVal(True) - elif isinstance(stmt.rvar1, ChironSSA.BoolFalse): - rvar1 = z3.BoolVal(False) + if isinstance(stmt.rvar2, ChironSSA.Var): + rvar2 = z3.Bool(stmt.rvar2.name) + elif isinstance(stmt.rvar2, ChironSSA.BoolTrue): + rvar2 = z3.BoolVal(True) + elif isinstance(stmt.rvar2, ChironSSA.BoolFalse): + rvar2 = z3.BoolVal(False) elif stmt.op == "": continue else: @@ -123,7 +126,7 @@ def convertBasicBlock(self, bb): elif stmt.op == "or": self.solver.add(lvar == z3.Or(rvar1, rvar2)) elif stmt.op == "not": - self.solver.add(lvar == z3.Not(rvar1)) + self.solver.add(lvar == z3.Not(rvar2)) elif isinstance(stmt, ChironSSA.AssertCommand): cond = None diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 2ace57d..26eb0e7 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -420,6 +420,6 @@ def stopTurtle(): print("\nConverting program to SMT-LIB format..\n") smt = bmc.BMC(ssa) - smt.convertBasicBlock() - smt.solve() + smt.convertSSAtoSMT() + # smt.solve() print("DONE..") From 85f8f38132a3a93f5b1c4af92ddced854147911d Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Wed, 12 Mar 2025 13:29:25 +0530 Subject: [PATCH 20/53] converted phi to smt --- ChironCore/bmc.py | 24 ++++++++++++------------ ChironCore/chiron.py | 2 +- ChironCore/example/move.tl | 3 ++- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 2aa2d14..8d0eff5 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -18,6 +18,11 @@ def __init__(self, ir): self.setConditions(self.line_to_bb_map[len(self.ir)]) + self.varConditions = {} # varConditions[var] = condition for var + for (stmt, tgt), line in zip(self.ir, range(len(self.ir))): + if isinstance(stmt, ChironSSA.AssignmentCommand): + self.varConditions[stmt.lvar.name] = self.bbConditions[self.line_to_bb_map[line]] + def setConditions(self, node): for pred in self.cfg.predecessors(node): if self.bbConditions[pred] == None: @@ -41,18 +46,13 @@ def convertSSAtoSMT(self): for stmt, tgt in self.ir: if isinstance(stmt, ChironSSA.PhiCommand): # TODO: Add support for Phi commands lvar = z3.Int(stmt.lvar.name) - rvars = [] - for rvar in stmt.rvars: - if isinstance(rvar, ChironSSA.Var): - rvars.append(z3.Int(rvar.name)) - elif isinstance(rvar, ChironSSA.Num): - rvars.append(z3.IntVal(rvar.value)) - elif isinstance(rvar, ChironSSA.BoolTrue): - rvars.append(z3.BoolVal(True)) - elif isinstance(rvar, ChironSSA.BoolFalse): - rvars.append(z3.BoolVal(False)) - or_expr = z3.Or([lvar == rvar for rvar in rvars]) - self.solver.add(or_expr) + rvars = [z3.Int(rvar.name) for rvar in stmt.rvars] + + rhs_expr = rvars[0] + for i in range(1, len(stmt.rvars)): + rhs_expr = z3.If(self.varConditions[stmt.rvars[i].name], rvars[i], (rhs_expr)) + + self.solver.add(lvar == rhs_expr) elif isinstance(stmt, ChironSSA.AssignmentCommand): lvar = None diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 26eb0e7..3678553 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -421,5 +421,5 @@ def stopTurtle(): print("\nConverting program to SMT-LIB format..\n") smt = bmc.BMC(ssa) smt.convertSSAtoSMT() - # smt.solve() + smt.solve() print("DONE..") diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 23145e0..dbe33ff 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,5 +1,5 @@ if (:a > :b) [ - :x = 1 + :x = 3 ] else [ if (:b > :c) [ :x = 2 @@ -8,3 +8,4 @@ if (:a > :b) [ ] ] :y = :x +assert :x == 3 From 05b7bea7d7794c40c988cf82472693c70479f644 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Wed, 12 Mar 2025 13:59:40 +0530 Subject: [PATCH 21/53] revert block condition, print only input variables for bug --- ChironCore/bmc.py | 60 +++++++++++++++++++++++------------------ ChironCore/chiron.py | 2 +- ChironCore/irhandler.py | 25 +++++++++-------- 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 8d0eff5..5368c93 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -14,37 +14,40 @@ def __init__(self, ir): self.bbConditions = {} # bbConditions[bb] = condition for bb for bb in self.cfg: self.bbConditions[bb] = None - self.bbConditions[self.line_to_bb_map[0]] = z3.BoolVal(True) - self.setConditions(self.line_to_bb_map[len(self.ir)]) + self.buildConditions() self.varConditions = {} # varConditions[var] = condition for var - for (stmt, tgt), line in zip(self.ir, range(len(self.ir))): + for (stmt, _), line in zip(self.ir, range(len(self.ir))): if isinstance(stmt, ChironSSA.AssignmentCommand): self.varConditions[stmt.lvar.name] = self.bbConditions[self.line_to_bb_map[line]] - def setConditions(self, node): - for pred in self.cfg.predecessors(node): - if self.bbConditions[pred] == None: - self.setConditions(pred) - instr = pred.instrlist[-1][0] - temp_cond = None - if isinstance(instr, ChironSSA.ConditionCommand) and type(instr.cond) == ChironSSA.Var: - edge_label = self.cfg.get_edge_label(pred, node) - if edge_label == 'Cond_True': - temp_cond = z3.And(self.bbConditions[pred], z3.Bool(instr.cond.name)) - elif edge_label == 'Cond_False': - temp_cond = z3.And(self.bbConditions[pred], z3.Not(z3.Bool(instr.cond.name))) - else: - temp_cond = self.bbConditions[pred] - if self.bbConditions[node] == None: - self.bbConditions[node] = temp_cond - else: - self.bbConditions[node] = z3.Or(self.bbConditions[node], temp_cond) + def buildConditions(self): + topological_order = list(self.cfg.get_topological_order()) + start = topological_order[0] + start.setCondition(z3.BoolVal(True)) + topological_order.pop(0) + for node in topological_order: + for pred in self.cfg.predecessors(node): + instr = pred.instrlist[-1][0] + current_cond = node.get_condition() + if isinstance(instr, ChironSSA.ConditionCommand) and type(instr.cond) == ChironSSA.Var: + cond = z3.Bool(instr.cond.name) + label = self.cfg.get_edge_label(pred, node) + if label == 'Cond_True': + node.setCondition(z3.Or(current_cond, z3.And(pred.get_condition(), cond))) + elif label == 'Cond_False': + node.setCondition(z3.Or(current_cond, z3.And(pred.get_condition(), z3.Not(cond)))) + else: + node.setCondition(z3.Or(pred.get_condition(), current_cond)) + + t = z3.Tactic('ctx-simplify').apply(node.get_condition()).as_expr() + node.setCondition(t) + self.bbConditions[node] = node.get_condition() def convertSSAtoSMT(self): - for stmt, tgt in self.ir: - if isinstance(stmt, ChironSSA.PhiCommand): # TODO: Add support for Phi commands + for stmt, _ in self.ir: + if isinstance(stmt, ChironSSA.PhiCommand): lvar = z3.Int(stmt.lvar.name) rvars = [z3.Int(rvar.name) for rvar in stmt.rvars] @@ -148,14 +151,19 @@ def convertSSAtoSMT(self): # else: # raise Exception("Unknown SSA instruction") - def solve(self): + def solve(self, inputVars): print("Assertions are:") print(self.solver.assertions()) print() sat = self.solver.check() if sat == z3.sat: - print("Condition not satisfied!") - print(self.solver.model()) + print("Condition not satisfied! Bug found for the following input:") + model = self.solver.model() + for var in model: + varname = str(var)[:-3] + if varname in inputVars: + print(varname + " = " + str(model[var])) + else: print("Condition always holds true!") diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 3678553..d2ca123 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -421,5 +421,5 @@ def stopTurtle(): print("\nConverting program to SMT-LIB format..\n") smt = bmc.BMC(ssa) smt.convertSSAtoSMT() - smt.solve() + smt.solve(tacGen.getFreeVariables()) print("DONE..") diff --git a/ChironCore/irhandler.py b/ChironCore/irhandler.py index 11ce4fd..edfe0e9 100644 --- a/ChironCore/irhandler.py +++ b/ChironCore/irhandler.py @@ -153,6 +153,7 @@ def __init__(self, ir): self.gotoCount = 0 self.ast_to_tac_line = {} self.line = 0 + self.freeVars = set() def parseExpresssion(self, expr, dest): """ @@ -468,9 +469,9 @@ def generateTAC(self): self.handleFreeVariables() def handleFreeVariables(self): - freeVars = self.getFreeVariables() + self.freeVars = self.getFreeVariables() - for var in freeVars: + for var in self.freeVars: self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(var), ChironTAC.Unused(), ChironTAC.Unused(), ""), 0)) @@ -478,31 +479,33 @@ def getFreeVariables(self): """ Returns free variables in TAC. """ - freeVars = set() + if len(self.freeVars) > 0: + return self.freeVars + boundVars = set() for (stmt, _), _ in zip(self.tac, range(len(self.tac))): if isinstance(stmt, ChironTAC.AssignmentCommand): if isinstance(stmt.rvar1, ChironTAC.Var) and stmt.rvar1.__str__() not in boundVars: - freeVars.add(stmt.rvar1.__str__()) + self.freeVars.add(stmt.rvar1.__str__()) if isinstance(stmt.rvar2, ChironTAC.Var) and stmt.rvar2.__str__() not in boundVars: - freeVars.add(stmt.rvar2.__str__()) + self.freeVars.add(stmt.rvar2.__str__()) boundVars.add(stmt.lvar.__str__()) elif isinstance(stmt, ChironTAC.ConditionCommand): if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: - freeVars.add(stmt.cond.__str__()) + self.freeVars.add(stmt.cond.__str__()) elif isinstance(stmt, ChironTAC.AssertCommand): if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: - freeVars.add(stmt.cond.__str__()) + self.freeVars.add(stmt.cond.__str__()) elif isinstance(stmt, ChironTAC.MoveCommand): if isinstance(stmt.var, ChironTAC.Var) and stmt.var.__str__() not in boundVars: - freeVars.add(stmt.var.__str__()) + self.freeVars.add(stmt.var.__str__()) elif isinstance(stmt, ChironTAC.GotoCommand): if isinstance(stmt.xcor, ChironTAC.Var) and stmt.xcor.__str__() not in boundVars: - freeVars.add(stmt.xcor.__str__()) + self.freeVars.add(stmt.xcor.__str__()) if isinstance(stmt.ycor, ChironTAC.Var) and stmt.ycor.__str__() not in boundVars: - freeVars.add(stmt.ycor.__str__()) + self.freeVars.add(stmt.ycor.__str__()) - return freeVars + return self.freeVars def printTAC(self): From 9e1fc9b60a471ba834864cf231275e5d6cfce255 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Wed, 12 Mar 2025 23:07:53 +0530 Subject: [PATCH 22/53] added support for move, pen, and goto command --- ChironCore/ChironSSA/ChironSSA.py | 16 ++++++++++ ChironCore/ChironSSA/ssaBuilder.py | 30 +++++++++++++++++- ChironCore/ChironTAC/ChironTAC.py | 16 ++++++++++ ChironCore/bmc.py | 23 +++++++++----- ChironCore/example/move.tl | 17 ++++++----- ChironCore/irhandler.py | 49 +++++++++++++++++++++++++++--- 6 files changed, 131 insertions(+), 20 deletions(-) diff --git a/ChironCore/ChironSSA/ChironSSA.py b/ChironCore/ChironSSA/ChironSSA.py index 1c4e478..20eb216 100644 --- a/ChironCore/ChironSSA/ChironSSA.py +++ b/ChironCore/ChironSSA/ChironSSA.py @@ -6,6 +6,22 @@ class SSA(object): class Instruction(SSA): pass +class CosCommand(Instruction): + def __init__(self, lvar, rvar): # lvar = cos(rvar) + self.lvar = lvar + self.rvar = rvar + + def __str__(self): + return self.lvar.__str__() + " = cos(" + self.rvar.__str__() + ")" + +class SinCommand(Instruction): + def __init__(self, lvar, rvar): # lvar = sin(rvar) + self.lvar = lvar + self.rvar = rvar + + def __str__(self): + return self.lvar.__str__() + " = sin(" + self.rvar.__str__() + ")" + class PhiCommand(Instruction): def __init__(self, lvar, rvars): self.lvar = lvar diff --git a/ChironCore/ChironSSA/ssaBuilder.py b/ChironCore/ChironSSA/ssaBuilder.py index a10b093..3b7fb05 100644 --- a/ChironCore/ChironSSA/ssaBuilder.py +++ b/ChironCore/ChironSSA/ssaBuilder.py @@ -8,7 +8,7 @@ def buildSSA(tac, cfg, line2BlockMap): """ ssa = [] - lastDeclaration = {} # lastDeclaration[bb][var] = version + lastDeclaration = {} # lastDeclaration[bb][var] = last version of var in bb varCounter = {} # varCounter[var] = counter phiStatements = {} # phiStatements[bb][var] = [var_1, var_2, ...] ssaLineCounter = 0 @@ -31,6 +31,18 @@ def buildSSA(tac, cfg, line2BlockMap): varCounter[var] += 1 stmt.lvar = ChironTAC.Var(f"{var}__{varCounter[var] - 1}") tac[line] = (stmt, tgt) + elif isinstance(stmt, ChironTAC.CosCommand): + var = stmt.lvar.__str__() + lastDeclaration[line2BlockMap[line]][var] = varCounter[var] + varCounter[var] += 1 + stmt.lvar = ChironTAC.Var(f"{var}__{varCounter[var] - 1}") + tac[line] = (stmt, tgt) + elif isinstance(stmt, ChironTAC.SinCommand): + var = stmt.lvar.__str__() + lastDeclaration[line2BlockMap[line]][var] = varCounter[var] + varCounter[var] += 1 + stmt.lvar = ChironTAC.Var(f"{var}__{varCounter[var] - 1}") + tac[line] = (stmt, tgt) for node in cfg: predes = cfg.predecessors(node) @@ -163,6 +175,22 @@ def buildSSA(tac, cfg, line2BlockMap): ssa.append((ChironSSA.PauseCommand(), tgt)) ssaLineCounter += 1 + elif isinstance(stmt, ChironTAC.CosCommand): + if stmt.rvar.__str__() not in lastUsed.keys(): + lastUsed[stmt.rvar.__str__()] = 0 + ssa.append((ChironSSA.CosCommand(ChironSSA.Var(f"{stmt.lvar.__str__()}"), ChironSSA.Var(f"{stmt.rvar.__str__()}__{lastUsed[stmt.rvar.__str__()]}")), tgt)) + lvar_string = lvar.__str__().rsplit('__', 1)[0] + lastUsed[lvar_string] = int(lvar.__str__().rsplit('__', 1)[1]) + ssaLineCounter += 1 + + elif isinstance(stmt, ChironTAC.SinCommand): + if stmt.rvar.__str__() not in lastUsed.keys(): + lastUsed[stmt.rvar.__str__()] = 0 + ssa.append((ChironSSA.SinCommand(ChironSSA.Var(f"{stmt.lvar.__str__()}"), ChironSSA.Var(f"{stmt.rvar.__str__()}__{lastUsed[stmt.rvar.__str__()]}")), tgt)) + lvar_string = lvar.__str__().rsplit('__', 1)[0] + lastUsed[lvar_string] = int(lvar.__str__().rsplit('__', 1)[1]) + ssaLineCounter += 1 + else: raise Exception(f"Unknown TAC command: {stmt}") diff --git a/ChironCore/ChironTAC/ChironTAC.py b/ChironCore/ChironTAC/ChironTAC.py index df5bbad..293adb6 100644 --- a/ChironCore/ChironTAC/ChironTAC.py +++ b/ChironCore/ChironTAC/ChironTAC.py @@ -6,6 +6,22 @@ class TAC(object): class Instruction(TAC): pass +class CosCommand(Instruction): + def __init__(self, lvar, rvar): # lvar = cos(rvar) + self.lvar = lvar + self.rvar = rvar + + def __str__(self): + return self.lvar.__str__() + " = cos(" + self.rvar.__str__() + ")" + +class SinCommand(Instruction): + def __init__(self, lvar, rvar): # lvar = sin(rvar) + self.lvar = lvar + self.rvar = rvar + + def __str__(self): + return self.lvar.__str__() + " = sin(" + self.rvar.__str__() + ")" + class AssignmentCommand(Instruction): def __init__(self, lvar, rvar1, rvar2, op): self.lvar = lvar diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 5368c93..62fa83e 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -141,15 +141,22 @@ def convertSSAtoSMT(self): cond = z3.Bool(stmt.cond.name) self.solver.add(z3.Not(cond)) - # TODO add support for other SSA instructions - # elif isinstance(stmt, ChironSSA.SSA_ConditionCommand): - # elif isinstance(stmt, ChironSSA.SSA_MoveCommand): - # elif isinstance(stmt, ChironSSA.SSA_PenCommand): - # elif isinstance(stmt, ChironSSA.SSA_GotoCommand): - # elif isinstance(stmt, ChironSSA.SSA_NoOpCommand): - # elif isinstance(stmt, ChironSSA.SSA_PauseCommand): + # elif isinstance(stmt, ChironSSA.CosCommand): # Problem: z3.Cos, z3.Sin is not supported + # self.solver.add(z3.Real(stmt.lvar.name) == z3.Cos(z3.Real(stmt.rvar1.name))) + # elif isinstance(stmt, ChironSSA.SinCommand): + # self.solver.add(z3.Real(stmt.lvar.name) == z3.Sin(z3.Real(stmt.rvar1.name))) + + # elif isinstance(stmt, ChironSSA.MoveCommand): + # elif isinstance(stmt, ChironSSA.PenCommand): + # elif isinstance(stmt, ChironSSA.GotoCommand): + elif isinstance(stmt, ChironSSA.ConditionCommand): + pass + elif isinstance(stmt, ChironSSA.NoOpCommand): + pass + elif isinstance(stmt, ChironSSA.PauseCommand): + pass # else: - # raise Exception("Unknown SSA instruction") + # raise Exception("Unknown SSA instruction") def solve(self, inputVars): print("Assertions are:") diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index dbe33ff..4e433ea 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,11 +1,14 @@ -if (:a > :b) [ - :x = 3 +if (:a > 1) [ + :y = 1 ] else [ - if (:b > :c) [ - :x = 2 + :y = 0 + if (:b < 1) [ + :x = 1 ] else [ - :x = 3 + :x = 2 ] ] -:y = :x -assert :x == 3 + +if (:c == 1) [ + :x = 2 +] \ No newline at end of file diff --git a/ChironCore/irhandler.py b/ChironCore/irhandler.py index edfe0e9..b395247 100644 --- a/ChironCore/irhandler.py +++ b/ChironCore/irhandler.py @@ -405,12 +405,14 @@ def generateTAC(self): newtgt = line_number - 1 + tgt # Adjusted later self.line += 1 self.tac.append((ChironTAC.ConditionCommand(branchvar), newtgt)) + elif isinstance(stmt, ChironAST.AssertCommand): assertvar = ChironTAC.Var(f":__assert_{self.assertCount}") self.assertCount += 1 self.parseExpresssion(stmt.cond, assertvar) self.line += 1 self.tac.append((ChironTAC.AssertCommand(assertvar), 1)) + elif isinstance(stmt, ChironAST.MoveCommand): movevar = None if isinstance(stmt.expr, ChironAST.Num): @@ -423,9 +425,37 @@ def generateTAC(self): self.parseExpresssion(stmt.expr, movevar) self.line += 1 self.tac.append((ChironTAC.MoveCommand(stmt.direction, movevar), 1)) + if (stmt.direction == "forward" or stmt.direction == "backward"): + self.line += 6 + self.tac.append((ChironTAC.CosCommand(ChironTAC.Var(":__cos_theta"), ChironTAC.Var(":__turtle_theta")), 1)) + self.tac.append((ChironTAC.SinCommand(ChironTAC.Var(":__sin_theta"), ChironTAC.Var(":__turtle_theta")), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__delta_x"), movevar, ChironTAC.Var(":__cos_theta"), "*"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__delta_y"), movevar, ChironTAC.Var(":__sin_theta"), "*"), 1)) + if (stmt.direction == "forward"): + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__delta_x"), "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__delta_y"), "+"), 1)) + elif (stmt.direction == "backward"): + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__delta_x"), "-"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__delta_y"), "-"), 1)) + elif (stmt.direction == "left"): + self.line += 1 + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta"), ChironTAC.Var(":__turtle_theta"), movevar, "-"), 1)) + elif (stmt.direction == "right"): + self.line += 1 + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta"), ChironTAC.Var(":__turtle_theta"), movevar, "+"), 1)) + else: + raise NotImplementedError("Unknown move direction: %s, %s." % (type(stmt), stmt)) + elif isinstance(stmt, ChironAST.PenCommand): - self.line += 1 + self.line += 2 self.tac.append((ChironTAC.PenCommand(stmt.status), 1)) + if (stmt.status == "penup"): + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(1), ChironTAC.Num(0), "+"), 1)) + elif (stmt.status == "pendown"): + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + else: + raise NotImplementedError("Unknown pen status: %s, %s." % (type(stmt), stmt)) + elif isinstance(stmt, ChironAST.GotoCommand): xvar = None yvar = None @@ -445,14 +475,19 @@ def generateTAC(self): yvar = ChironTAC.Var(f":__y_{self.gotoCount}") self.gotoCount += 1 self.parseExpresssion(stmt.ycor, yvar) - self.line += 1 + self.line += 3 self.tac.append((ChironTAC.GotoCommand(xvar, yvar), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), xvar, ChironTAC.Num(0), "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), yvar, ChironTAC.Num(0), "+"), 1)) + elif isinstance(stmt, ChironAST.NoOpCommand): self.line += 1 self.tac.append((ChironTAC.NoOpCommand(), 1)) + elif isinstance(stmt, ChironAST.PauseCommand): self.line += 1 self.tac.append((ChironTAC.PauseCommand(), 1)) + else: raise NotImplementedError( "Unknown instruction: %s, %s." % (type(stmt), stmt) @@ -466,15 +501,21 @@ def generateTAC(self): newtgt = self.ast_to_tac_line[tgt] - i self.tac[i] = (stmt, newtgt) + self.handleMoveVariables() self.handleFreeVariables() def handleFreeVariables(self): self.freeVars = self.getFreeVariables() for var in self.freeVars: - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(var), ChironTAC.Unused(), ChironTAC.Unused(), ""), 0)) - + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(var), ChironTAC.Unused(), ChironTAC.Unused(), ""), 1)) + def handleMoveVariables(self): + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) # 0->down 1->up + def getFreeVariables(self): """ Returns free variables in TAC. From 2d7cc37723878b0228e067d8fc790884ecaed5f8 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Thu, 13 Mar 2025 13:23:50 +0530 Subject: [PATCH 23/53] fix ssa, rename left --- ChironCore/ChironSSA/builder.py | 142 ++++++++++++++++++++++++++++++++ ChironCore/bmc.py | 10 +-- ChironCore/cfg/ChironCFG.py | 17 +++- ChironCore/chiron.py | 20 +++-- ChironCore/example/move.tl | 20 +++-- ChironCore/example/move1.tl | 17 ++++ 6 files changed, 203 insertions(+), 23 deletions(-) create mode 100644 ChironCore/ChironSSA/builder.py create mode 100644 ChironCore/example/move1.tl diff --git a/ChironCore/ChironSSA/builder.py b/ChironCore/ChironSSA/builder.py new file mode 100644 index 0000000..b8f7bd6 --- /dev/null +++ b/ChironCore/ChironSSA/builder.py @@ -0,0 +1,142 @@ +from ChironSSA import ChironSSA +from cfg import cfgBuilder +import ChironTAC.ChironTAC as ChironTAC +import cfg.ChironCFG as ChironCFG +import networkx as nx +import copy +import collections + +class SSABuilder: + def __init__(self, cfg : ChironCFG.ChironCFG): + self.cfg = cfg + self.globals = set() + self.blocksMap = collections.defaultdict(set) + self.counter = collections.defaultdict(int) + self.stack = collections.defaultdict(list) + + def build(self): + self.cfg.compute_dominance() + self.insert_phi_nodes() + self.rename_variables() + + # save the SSA CFG as png + cfgBuilder.dumpCFG(self.cfg, "cfg") + + def rename_variables(self): + for var in self.globals: + self.counter[var] = 0 + self.stack[var] = [] + + entry = None + for block in self.cfg.nodes(): + if block.name == "START": + entry = block + break + + self.rename(entry) + + def rename(self, block): # TODO + print("renaming block: ", block.name) + for instr, _ in block.instrlist: + temp = set() + if isinstance(instr, ChironSSA.PhiCommand): + temp.add(instr.lvar.name) + instr.lvar = self.new_name(instr.lvar.name) + + elif isinstance(instr, ChironTAC.AssignmentCommand): + instr.lvar = self.new_name(instr.lvar.name) + if isinstance(instr.rvar1, ChironTAC.Var): + instr.rvar1 = ChironSSA.Var(instr.rvar1.name + "__" + str(self.stack[instr.rvar1.name][-1])) + if isinstance(instr.rvar2, ChironTAC.Var): + instr.rvar2 = ChironSSA.Var(instr.rvar2.name + "__" + str(self.stack[instr.rvar2.name][-1])) + + elif isinstance(instr, ChironTAC.AssertCommand): + if isinstance(instr.cond, ChironTAC.Var): + instr.cond = ChironSSA.Var(instr.cond.name + "__" + str(self.stack[instr.cond.name][-1])) + + elif isinstance(instr, ChironTAC.ConditionCommand): + if isinstance(instr.cond, ChironTAC.Var): + instr.cond = ChironSSA.Var(instr.cond.name + "__" + str(self.stack[instr.cond.name][-1])) + + elif isinstance(instr, ChironTAC.MoveCommand): + if isinstance(instr.var, ChironTAC.Var): + instr.var = ChironSSA.Var(instr.var.name + "__" + str(self.stack[instr.var.name][-1])) + + elif isinstance(instr, ChironTAC.GotoCommand): + if isinstance(instr.xcor, ChironTAC.Var): + instr.xcor = ChironSSA.Var(instr.xcor.name + "__" + str(self.stack[instr.xcor.name][-1])) + if isinstance(instr.ycor, ChironTAC.Var): + instr.ycor = ChironSSA.Var(instr.ycor.name + "__" + str(self.stack[instr.ycor.name][-1])) + + print("df: ", self.cfg.df[block], "idom: ", self.cfg.idom[block].name) + for next in self.cfg.df[block]: + print("idom: ", self.cfg.idom[next].name) + if self.cfg.idom[next] == block: + self.rename(next) + + for var in temp: + self.stack[var].pop() + + def new_name(self, var): + i = self.counter[var] + self.counter[var] += 1 + self.stack[var].append(i) + return ChironSSA.Var(var + "__" + str(i)) + + def insert_phi_nodes(self): + for var in self.get_globals(): + if var not in self.blocksMap: + continue + + worklist = self.blocksMap[var] + while len(worklist) > 0: + block = worklist.pop() + for next in self.cfg.df[block]: + found = False + for instr, _ in next.instrlist: + if isinstance(instr, ChironSSA.PhiCommand) and instr.lvar.name == var: + found = True + instr.rvars.append(ChironSSA.Var(var)) + break + + if not found: + phi = ChironSSA.PhiCommand(ChironSSA.Var(var), [ChironSSA.Var(var)]) + next.instrlist.insert(0, (phi, None)) + worklist.add(next) + + def get_globals(self): + if len(self.globals) > 0: + return self.globals + + for block in self.cfg.nodes(): + varkill = set() + for instr, _ in block.instrlist: + if isinstance(instr, ChironTAC.AssignmentCommand): + if isinstance(instr.rvar1, ChironTAC.Var) and instr.rvar1.name not in varkill: + self.globals.add(instr.rvar1.name) + if isinstance(instr.rvar2, ChironTAC.Var) and instr.rvar2.name not in varkill: + self.globals.add(instr.rvar2.name) + + varkill.add(instr.lvar.name) + self.blocksMap[instr.lvar.name].add(block) + + elif isinstance(instr, ChironTAC.AssertCommand): + if isinstance(instr.cond, ChironTAC.Var) and instr.cond.name not in varkill: + self.globals.add(instr.cond.name) + + elif isinstance(instr, ChironTAC.ConditionCommand): + if isinstance(instr.cond, ChironTAC.Var) and instr.cond.name not in varkill: + self.globals.add(instr.cond.name) + + elif isinstance(instr, ChironTAC.MoveCommand): + if isinstance(instr.var, ChironTAC.Var) and instr.var.name not in varkill: + self.globals.add(instr.var.name) + + elif isinstance(instr, ChironTAC.GotoCommand): + if isinstance(instr.xcor, ChironTAC.Var) and instr.xcor.name not in varkill: + self.globals.add(instr.xcor.name) + if isinstance(instr.ycor, ChironTAC.Var) and instr.ycor.name not in varkill: + self.globals.add(instr.ycor.name) + + return self.globals + diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 5368c93..f78f22d 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -25,7 +25,7 @@ def __init__(self, ir): def buildConditions(self): topological_order = list(self.cfg.get_topological_order()) start = topological_order[0] - start.setCondition(z3.BoolVal(True)) + start.set_condition(z3.BoolVal(True)) topological_order.pop(0) for node in topological_order: for pred in self.cfg.predecessors(node): @@ -35,14 +35,14 @@ def buildConditions(self): cond = z3.Bool(instr.cond.name) label = self.cfg.get_edge_label(pred, node) if label == 'Cond_True': - node.setCondition(z3.Or(current_cond, z3.And(pred.get_condition(), cond))) + node.set_condition(z3.Or(current_cond, z3.And(pred.get_condition(), cond))) elif label == 'Cond_False': - node.setCondition(z3.Or(current_cond, z3.And(pred.get_condition(), z3.Not(cond)))) + node.set_condition(z3.Or(current_cond, z3.And(pred.get_condition(), z3.Not(cond)))) else: - node.setCondition(z3.Or(pred.get_condition(), current_cond)) + node.set_condition(z3.Or(pred.get_condition(), current_cond)) t = z3.Tactic('ctx-simplify').apply(node.get_condition()).as_expr() - node.setCondition(t) + node.set_condition(t) self.bbConditions[node] = node.get_condition() def convertSSAtoSMT(self): diff --git a/ChironCore/cfg/ChironCFG.py b/ChironCore/cfg/ChironCFG.py index 69ed351..554b257 100644 --- a/ChironCore/cfg/ChironCFG.py +++ b/ChironCore/cfg/ChironCFG.py @@ -22,7 +22,7 @@ def append(self, instruction): def extend(self, instructions): self.instrlist.extend(instructions) - def setCondition(self, condition): + def set_condition(self, condition): self.condition = condition def get_condition(self): @@ -46,6 +46,8 @@ def __init__(self, gname='cfg'): self.nxgraph = nx.DiGraph(name=gname) self.entry = "0" self.exit = "END" + self.df = None + self.idom = None def __iter__(self): return self.nxgraph.__iter__() @@ -94,6 +96,19 @@ def get_edge_label(self, u, v): edata = self.nxgraph.get_edge_data(u,v) return edata['label'] if len(edata) else 'T' + def compute_dominance(self): + entry = None + for node in self.nxgraph.nodes(): + if node.name == "START": + entry = node + break + + if entry is None: + raise ValueError("CFG does not have an entry node") + + self.idom = nx.immediate_dominators(self.nxgraph, entry) + self.df = nx.dominance_frontiers(self.nxgraph, entry) + def get_topological_order(self): return list(nx.topological_sort(self.nxgraph)) # TODO: add more methods to expose other methods of the Networkx.DiGraph diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index d2ca123..aa51d3b 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -23,6 +23,7 @@ import cfg.cfgBuilder as cfgB import bmc as bmc from ChironSSA.ssaBuilder import * +from ChironSSA.builder import * import submissionDFA as DFASub import submissionAI as AISub from sbflSubmission import computeRanks @@ -412,14 +413,17 @@ def stopTurtle(): cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) # Building CFG cfgB.dumpCFG(cfg, 'tac_cfg') - ssa = buildSSA(tacGen.tac, cfg, line2BlockMap) # Building SSA - printSSA(ssa) # Printing SSA + amoghssa = SSABuilder(cfg) + amoghssa.build() - ssa_cfg, ssa_line2BlockMap = cfgB.buildCFG(ssa, "ssa_cfg", False) # Building CFG for SSA - cfgB.dumpCFG(ssa_cfg, 'ssa_cfg') + #ssa = buildSSA(tacGen.tac, cfg, line2BlockMap) # Building SSA + #printSSA(ssa) # Printing SSA - print("\nConverting program to SMT-LIB format..\n") - smt = bmc.BMC(ssa) - smt.convertSSAtoSMT() - smt.solve(tacGen.getFreeVariables()) + #ssa_cfg, ssa_line2BlockMap = cfgB.buildCFG(ssa, "ssa_cfg", False) # Building CFG for SSA + #cfgB.dumpCFG(ssa_cfg, 'ssa_cfg') + + #print("\nConverting program to SMT-LIB format..\n") + #smt = bmc.BMC(ssa) + #smt.convertSSAtoSMT() + #smt.solve(tacGen.getFreeVariables()) print("DONE..") diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index dbe33ff..097534b 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,11 +1,13 @@ -if (:a > :b) [ - :x = 3 +if :a > :b [ + :x = :a ] else [ - if (:b > :c) [ - :x = 2 - ] else [ - :x = 3 - ] + :x = :b - 2 ] -:y = :x -assert :x == 3 + +if :a > :b [ + :y = :b - 1 +] else [ + :y = :a + 100 +] + +assert :x >= :y diff --git a/ChironCore/example/move1.tl b/ChironCore/example/move1.tl new file mode 100644 index 0000000..aefaa73 --- /dev/null +++ b/ChironCore/example/move1.tl @@ -0,0 +1,17 @@ +if (:a > 1) [ + :y = 1 +] else [ + :y = 0 + if (:b < 1) [ + :x = 1 + ] else [ + :x = 2 + ] +] + +if (:c == 1) [ + :x = 2 +] + +assert(:x > 0) +assert(:y > 0) From f9511e7a547d9ea89fa420874e33d211cb392def Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Fri, 14 Mar 2025 14:54:35 +0530 Subject: [PATCH 24/53] fix ssa --- ChironCore/ChironSSA/builder.py | 163 +++++++++++++++------- ChironCore/bmc.py | 236 ++++++++++++++++---------------- ChironCore/cfg/ChironCFG.py | 7 + ChironCore/chiron.py | 17 +-- ChironCore/example/move.tl | 42 ++++-- ChironCore/example/move1.tl | 17 --- 6 files changed, 278 insertions(+), 204 deletions(-) delete mode 100644 ChironCore/example/move1.tl diff --git a/ChironCore/ChironSSA/builder.py b/ChironCore/ChironSSA/builder.py index b8f7bd6..6b8588b 100644 --- a/ChironCore/ChironSSA/builder.py +++ b/ChironCore/ChironSSA/builder.py @@ -1,14 +1,17 @@ +from numpy import format_float_scientific from ChironSSA import ChironSSA from cfg import cfgBuilder import ChironTAC.ChironTAC as ChironTAC +import ChironSSA.ChironSSA as ChironSSA import cfg.ChironCFG as ChironCFG import networkx as nx import copy import collections class SSABuilder: - def __init__(self, cfg : ChironCFG.ChironCFG): - self.cfg = cfg + def __init__(self, ir): + self.convert(ir) + self.cfg, self.line2BlockMap = cfgBuilder.buildCFG(ir) self.globals = set() self.blocksMap = collections.defaultdict(set) self.counter = collections.defaultdict(int) @@ -19,8 +22,7 @@ def build(self): self.insert_phi_nodes() self.rename_variables() - # save the SSA CFG as png - cfgBuilder.dumpCFG(self.cfg, "cfg") + return self.cfg def rename_variables(self): for var in self.globals: @@ -36,43 +38,60 @@ def rename_variables(self): self.rename(entry) def rename(self, block): # TODO - print("renaming block: ", block.name) + temp = set() for instr, _ in block.instrlist: - temp = set() if isinstance(instr, ChironSSA.PhiCommand): temp.add(instr.lvar.name) instr.lvar = self.new_name(instr.lvar.name) - elif isinstance(instr, ChironTAC.AssignmentCommand): + elif isinstance(instr, ChironSSA.AssignmentCommand): + temp.add(instr.lvar.name) instr.lvar = self.new_name(instr.lvar.name) - if isinstance(instr.rvar1, ChironTAC.Var): - instr.rvar1 = ChironSSA.Var(instr.rvar1.name + "__" + str(self.stack[instr.rvar1.name][-1])) - if isinstance(instr.rvar2, ChironTAC.Var): - instr.rvar2 = ChironSSA.Var(instr.rvar2.name + "__" + str(self.stack[instr.rvar2.name][-1])) - - elif isinstance(instr, ChironTAC.AssertCommand): - if isinstance(instr.cond, ChironTAC.Var): - instr.cond = ChironSSA.Var(instr.cond.name + "__" + str(self.stack[instr.cond.name][-1])) - - elif isinstance(instr, ChironTAC.ConditionCommand): - if isinstance(instr.cond, ChironTAC.Var): - instr.cond = ChironSSA.Var(instr.cond.name + "__" + str(self.stack[instr.cond.name][-1])) - - elif isinstance(instr, ChironTAC.MoveCommand): - if isinstance(instr.var, ChironTAC.Var): - instr.var = ChironSSA.Var(instr.var.name + "__" + str(self.stack[instr.var.name][-1])) - - elif isinstance(instr, ChironTAC.GotoCommand): - if isinstance(instr.xcor, ChironTAC.Var): - instr.xcor = ChironSSA.Var(instr.xcor.name + "__" + str(self.stack[instr.xcor.name][-1])) - if isinstance(instr.ycor, ChironTAC.Var): - instr.ycor = ChironSSA.Var(instr.ycor.name + "__" + str(self.stack[instr.ycor.name][-1])) - - print("df: ", self.cfg.df[block], "idom: ", self.cfg.idom[block].name) - for next in self.cfg.df[block]: - print("idom: ", self.cfg.idom[next].name) - if self.cfg.idom[next] == block: - self.rename(next) + if isinstance(instr.rvar1, ChironSSA.Var): + instr.rvar1 = ChironSSA.Var(instr.rvar1.name + "$" + str(self.stack[instr.rvar1.name][-1])) + if isinstance(instr.rvar2, ChironSSA.Var): + instr.rvar2 = ChironSSA.Var(instr.rvar2.name + "$" + str(self.stack[instr.rvar2.name][-1])) + + elif isinstance(instr, ChironSSA.AssertCommand): + if isinstance(instr.cond, ChironSSA.Var): + instr.cond = ChironSSA.Var(instr.cond.name + "$" + str(self.stack[instr.cond.name][-1])) + + elif isinstance(instr, ChironSSA.ConditionCommand): + if isinstance(instr.cond, ChironSSA.Var): + instr.cond = ChironSSA.Var(instr.cond.name + "$" + str(self.stack[instr.cond.name][-1])) + + elif isinstance(instr, ChironSSA.MoveCommand): + if isinstance(instr.var, ChironSSA.Var): + instr.var = ChironSSA.Var(instr.var.name + "$" + str(self.stack[instr.var.name][-1])) + + elif isinstance(instr, ChironSSA.GotoCommand): + if isinstance(instr.xcor, ChironSSA.Var): + instr.xcor = ChironSSA.Var(instr.xcor.name + "$" + str(self.stack[instr.xcor.name][-1])) + if isinstance(instr.ycor, ChironSSA.Var): + instr.ycor = ChironSSA.Var(instr.ycor.name + "$" + str(self.stack[instr.ycor.name][-1])) + + visited = set() + def phi_dfs(curr, var): + visited.add(curr) + flag = False + for instr, _ in curr.instrlist: + if isinstance(instr, ChironSSA.PhiCommand): + if instr.lvar.name == var: + instr.rvars.append(ChironSSA.Var(instr.lvar.name + "$" + str(self.stack[instr.lvar.name][-1]))) + flag = True + + if not flag: + for next in self.cfg.successors(curr): + if next in visited: + continue + phi_dfs(next, var) + + for next in self.cfg.successors(block): + for var in temp: + phi_dfs(next, var) + + for next in self.cfg.dominator_tree[block]: + self.rename(next) for var in temp: self.stack[var].pop() @@ -81,7 +100,7 @@ def new_name(self, var): i = self.counter[var] self.counter[var] += 1 self.stack[var].append(i) - return ChironSSA.Var(var + "__" + str(i)) + return ChironSSA.Var(var + "$" + str(i)) def insert_phi_nodes(self): for var in self.get_globals(): @@ -96,11 +115,10 @@ def insert_phi_nodes(self): for instr, _ in next.instrlist: if isinstance(instr, ChironSSA.PhiCommand) and instr.lvar.name == var: found = True - instr.rvars.append(ChironSSA.Var(var)) break if not found: - phi = ChironSSA.PhiCommand(ChironSSA.Var(var), [ChironSSA.Var(var)]) + phi = ChironSSA.PhiCommand(ChironSSA.Var(var), []) next.instrlist.insert(0, (phi, None)) worklist.add(next) @@ -111,32 +129,77 @@ def get_globals(self): for block in self.cfg.nodes(): varkill = set() for instr, _ in block.instrlist: - if isinstance(instr, ChironTAC.AssignmentCommand): - if isinstance(instr.rvar1, ChironTAC.Var) and instr.rvar1.name not in varkill: + if isinstance(instr, ChironSSA.AssignmentCommand): + if isinstance(instr.rvar1, ChironSSA.Var) and instr.rvar1.name not in varkill: self.globals.add(instr.rvar1.name) - if isinstance(instr.rvar2, ChironTAC.Var) and instr.rvar2.name not in varkill: + if isinstance(instr.rvar2, ChironSSA.Var) and instr.rvar2.name not in varkill: self.globals.add(instr.rvar2.name) varkill.add(instr.lvar.name) self.blocksMap[instr.lvar.name].add(block) - elif isinstance(instr, ChironTAC.AssertCommand): - if isinstance(instr.cond, ChironTAC.Var) and instr.cond.name not in varkill: + elif isinstance(instr, ChironSSA.AssertCommand): + if isinstance(instr.cond, ChironSSA.Var) and instr.cond.name not in varkill: self.globals.add(instr.cond.name) - elif isinstance(instr, ChironTAC.ConditionCommand): - if isinstance(instr.cond, ChironTAC.Var) and instr.cond.name not in varkill: + elif isinstance(instr, ChironSSA.ConditionCommand): + if isinstance(instr.cond, ChironSSA.Var) and instr.cond.name not in varkill: self.globals.add(instr.cond.name) - elif isinstance(instr, ChironTAC.MoveCommand): - if isinstance(instr.var, ChironTAC.Var) and instr.var.name not in varkill: + elif isinstance(instr, ChironSSA.MoveCommand): + if isinstance(instr.var, ChironSSA.Var) and instr.var.name not in varkill: self.globals.add(instr.var.name) - elif isinstance(instr, ChironTAC.GotoCommand): - if isinstance(instr.xcor, ChironTAC.Var) and instr.xcor.name not in varkill: + elif isinstance(instr, ChironSSA.GotoCommand): + if isinstance(instr.xcor, ChironSSA.Var) and instr.xcor.name not in varkill: self.globals.add(instr.xcor.name) - if isinstance(instr.ycor, ChironTAC.Var) and instr.ycor.name not in varkill: + if isinstance(instr.ycor, ChironSSA.Var) and instr.ycor.name not in varkill: self.globals.add(instr.ycor.name) return self.globals + + def convert(self, ir): + # convert each statement from ChironTAC to ChironSSA + for instr, tgt in ir: + if isinstance(instr, ChironTAC.AssignmentCommand): + lvar = ChironSSA.Var(instr.lvar.name) + rvar1 = ChironSSA.Var(instr.rvar1.name) if isinstance(instr.rvar1, ChironTAC.Var) else ChironSSA.Num(instr.rvar1.value) if isinstance(instr.rvar1, ChironTAC.Num) else ChironSSA.Unused() + rvar2 = ChironSSA.Var(instr.rvar2.name) if isinstance(instr.rvar2, ChironTAC.Var) else ChironSSA.Num(instr.rvar2.value) if isinstance(instr.rvar2, ChironTAC.Num) else ChironSSA.Unused() + ir[ir.index((instr, tgt))] = (ChironSSA.AssignmentCommand(lvar, rvar1, rvar2, instr.op), tgt) + + elif isinstance(instr, ChironTAC.AssertCommand): + cond = ChironSSA.Var(instr.cond.name) if isinstance(instr.cond, ChironTAC.Var) else ChironSSA.BoolTrue() if isinstance(instr.cond, ChironTAC.BoolTrue) else ChironSSA.BoolFalse() + ir[ir.index((instr, tgt))] = (ChironSSA.AssertCommand(cond), tgt) + + elif isinstance(instr, ChironTAC.ConditionCommand): + cond = ChironSSA.Var(instr.cond.name) if isinstance(instr.cond, ChironTAC.Var) else ChironSSA.BoolTrue() if isinstance(instr.cond, ChironTAC.BoolTrue) else ChironSSA.BoolFalse() + ir[ir.index((instr, tgt))] = (ChironSSA.ConditionCommand(cond), tgt) + + elif isinstance(instr, ChironTAC.MoveCommand): + var = ChironSSA.Var(instr.var.name) if isinstance(instr.var, ChironTAC.Var) else ChironSSA.Num(instr.var.value) + ir[ir.index((instr, tgt))] = (ChironSSA.MoveCommand(instr.direction, var), tgt) + + elif isinstance(instr, ChironTAC.GotoCommand): + xcor = ChironSSA.Var(instr.xcor.name) if isinstance(instr.xcor, ChironTAC.Var) else ChironSSA.Num(instr.xcor.value) + ycor = ChironSSA.Var(instr.ycor.name) if isinstance(instr.ycor, ChironTAC.Var) else ChironSSA.Num(instr.ycor.value) + ir[ir.index((instr, tgt))] = (ChironSSA.GotoCommand(xcor, ycor), tgt) + + elif isinstance(instr, ChironTAC.SinCommand): + lvar = ChironSSA.Var(instr.lvar.name) + rvar = ChironSSA.Var(instr.rvar.name) if isinstance(instr.rvar, ChironTAC.Var) else ChironSSA.Num(instr.rvar.value) + ir[ir.index((instr, tgt))] = (ChironSSA.SinCommand(lvar, rvar), tgt) + + elif isinstance(instr, ChironTAC.CosCommand): + lvar = ChironSSA.Var(instr.lvar.name) + rvar = ChironSSA.Var(instr.rvar.name) if isinstance(instr.rvar, ChironTAC.Var) else ChironSSA.Num(instr.rvar.value) + ir[ir.index((instr, tgt))] = (ChironSSA.CosCommand(lvar, rvar), tgt) + + elif isinstance(instr, ChironTAC.PenCommand): + ir[ir.index((instr, tgt))] = (ChironSSA.PenCommand(instr.status), tgt) + + elif isinstance(instr, ChironTAC.PauseCommand): + ir[ir.index((instr, tgt))] = (ChironSSA.PauseCommand(), tgt) + + elif isinstance(instr, ChironTAC.NoOpCommand): + ir[ir.index((instr, tgt))] = (ChironSSA.NoOpCommand(), tgt) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 038a507..bdb1f3f 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -6,10 +6,9 @@ from cfg import cfgBuilder class BMC: - def __init__(self, ir): + def __init__(self, cfg): self.solver = z3.Solver() - self.ir = ir - self.cfg, self.line_to_bb_map = cfgBuilder.buildCFG(ir) + self.cfg = cfg self.bbConditions = {} # bbConditions[bb] = condition for bb for bb in self.cfg: @@ -18,9 +17,12 @@ def __init__(self, ir): self.buildConditions() self.varConditions = {} # varConditions[var] = condition for var - for (stmt, _), line in zip(self.ir, range(len(self.ir))): - if isinstance(stmt, ChironSSA.AssignmentCommand): - self.varConditions[stmt.lvar.name] = self.bbConditions[self.line_to_bb_map[line]] + for bb in self.cfg.nodes(): + for stmt, _ in bb.instrlist: + if isinstance(stmt, ChironSSA.PhiCommand): + self.varConditions[stmt.lvar.name] = self.bbConditions[bb] + elif isinstance(stmt, ChironSSA.AssignmentCommand): + self.varConditions[stmt.lvar.name] = self.bbConditions[bb] def buildConditions(self): topological_order = list(self.cfg.get_topological_order()) @@ -46,128 +48,126 @@ def buildConditions(self): self.bbConditions[node] = node.get_condition() def convertSSAtoSMT(self): - for stmt, _ in self.ir: - if isinstance(stmt, ChironSSA.PhiCommand): - lvar = z3.Int(stmt.lvar.name) - rvars = [z3.Int(rvar.name) for rvar in stmt.rvars] - - rhs_expr = rvars[0] - for i in range(1, len(stmt.rvars)): - rhs_expr = z3.If(self.varConditions[stmt.rvars[i].name], rvars[i], (rhs_expr)) - - self.solver.add(lvar == rhs_expr) - - elif isinstance(stmt, ChironSSA.AssignmentCommand): - lvar = None - rvar1 = ChironSSA.Unused() - rvar2 = ChironSSA.Unused() - if stmt.op in ["+", "-", "*", "/"]: + for bb in self.cfg.nodes(): + for stmt, _ in bb.instrlist: + if isinstance(stmt, ChironSSA.PhiCommand): lvar = z3.Int(stmt.lvar.name) - if isinstance(stmt.rvar1, ChironSSA.Var): - rvar1 = z3.Int(stmt.rvar1.name) - elif isinstance(stmt.rvar1, ChironSSA.Num): - rvar1 = z3.IntVal(stmt.rvar1.value) - if isinstance(stmt.rvar2, ChironSSA.Var): - rvar2 = z3.Int(stmt.rvar2.name) - elif isinstance(stmt.rvar2, ChironSSA.Num): - rvar2 = z3.IntVal(stmt.rvar2.value) - elif stmt.op in ["<", ">", "<=", ">=", "==", "!="]: - lvar = z3.Bool(stmt.lvar.name) - if isinstance(stmt.rvar1, ChironSSA.Var): - rvar1 = z3.Int(stmt.rvar1.name) - elif isinstance(stmt.rvar1, ChironSSA.Num): - rvar1 = z3.IntVal(stmt.rvar1.value) - if isinstance(stmt.rvar2, ChironSSA.Var): - rvar2 = z3.Int(stmt.rvar2.name) - elif isinstance(stmt.rvar2, ChironSSA.Num): - rvar2 = z3.IntVal(stmt.rvar2.value) - elif stmt.op in ["and", "or"]: - lvar = z3.Bool(stmt.lvar.name) - if isinstance(stmt.rvar1, ChironSSA.Var): - rvar1 = z3.Bool(stmt.rvar1.name) - elif isinstance(stmt.rvar1, ChironSSA.BoolTrue): - rvar1 = z3.BoolVal(True) - if isinstance(stmt.rvar2, ChironSSA.Var): - rvar2 = z3.Bool(stmt.rvar2.name) - elif isinstance(stmt.rvar2, ChironSSA.BoolFalse): - rvar2 = z3.BoolVal(False) - elif stmt.op == "not": - lvar = z3.Bool(stmt.lvar.name) - if isinstance(stmt.rvar2, ChironSSA.Var): - rvar2 = z3.Bool(stmt.rvar2.name) - elif isinstance(stmt.rvar2, ChironSSA.BoolTrue): - rvar2 = z3.BoolVal(True) - elif isinstance(stmt.rvar2, ChironSSA.BoolFalse): - rvar2 = z3.BoolVal(False) - elif stmt.op == "": - continue - else: - raise Exception("Unknown SSA instruction") - - if stmt.op == "+": - self.solver.add(lvar == (rvar1 + rvar2)) - elif stmt.op == "-": - self.solver.add(lvar == (rvar1 - rvar2)) - elif stmt.op == "*": - self.solver.add(lvar == (rvar1 * rvar2)) - elif stmt.op == "/": - self.solver.add(lvar == (rvar1 / rvar2)) - elif stmt.op == "<": - self.solver.add(lvar == (rvar1 < rvar2)) - elif stmt.op == ">": - self.solver.add(lvar == (rvar1 > rvar2)) - elif stmt.op == "<=": - self.solver.add(lvar == (rvar1 <= rvar2)) - elif stmt.op == ">=": - self.solver.add(lvar == (rvar1 >= rvar2)) - elif stmt.op == "==": - self.solver.add(lvar == (rvar1 == rvar2)) - elif stmt.op == "!=": - self.solver.add(lvar == (rvar1 != rvar2)) - elif stmt.op == "and": - self.solver.add(lvar == z3.And(rvar1, rvar2)) - elif stmt.op == "or": - self.solver.add(lvar == z3.Or(rvar1, rvar2)) - elif stmt.op == "not": - self.solver.add(lvar == z3.Not(rvar2)) - - elif isinstance(stmt, ChironSSA.AssertCommand): - cond = None - if isinstance(stmt.cond, ChironSSA.BoolTrue): - cond = z3.BoolVal(True) - elif isinstance(stmt.cond, ChironSSA.BoolFalse): - cond = z3.BoolVal(False) - elif isinstance(stmt.cond, ChironSSA.Var): - cond = z3.Bool(stmt.cond.name) - self.solver.add(z3.Not(cond)) - - # elif isinstance(stmt, ChironSSA.CosCommand): # Problem: z3.Cos, z3.Sin is not supported - # self.solver.add(z3.Real(stmt.lvar.name) == z3.Cos(z3.Real(stmt.rvar1.name))) - # elif isinstance(stmt, ChironSSA.SinCommand): - # self.solver.add(z3.Real(stmt.lvar.name) == z3.Sin(z3.Real(stmt.rvar1.name))) - - # elif isinstance(stmt, ChironSSA.MoveCommand): - # elif isinstance(stmt, ChironSSA.PenCommand): - # elif isinstance(stmt, ChironSSA.GotoCommand): - elif isinstance(stmt, ChironSSA.ConditionCommand): - pass - elif isinstance(stmt, ChironSSA.NoOpCommand): - pass - elif isinstance(stmt, ChironSSA.PauseCommand): - pass + rvars = [z3.Int(rvar.name) for rvar in stmt.rvars] + + rhs_expr = rvars[0] + for i in range(1, len(stmt.rvars)): + rhs_expr = z3.If(self.varConditions[stmt.rvars[i].name], rvars[i], (rhs_expr)) + + self.solver.add(lvar == rhs_expr) + + elif isinstance(stmt, ChironSSA.AssignmentCommand): + lvar = None + rvar1 = ChironSSA.Unused() + rvar2 = ChironSSA.Unused() + if stmt.op in ["+", "-", "*", "/"]: + lvar = z3.Int(stmt.lvar.name) + if isinstance(stmt.rvar1, ChironSSA.Var): + rvar1 = z3.Int(stmt.rvar1.name) + elif isinstance(stmt.rvar1, ChironSSA.Num): + rvar1 = z3.IntVal(stmt.rvar1.value) + if isinstance(stmt.rvar2, ChironSSA.Var): + rvar2 = z3.Int(stmt.rvar2.name) + elif isinstance(stmt.rvar2, ChironSSA.Num): + rvar2 = z3.IntVal(stmt.rvar2.value) + elif stmt.op in ["<", ">", "<=", ">=", "==", "!="]: + lvar = z3.Bool(stmt.lvar.name) + if isinstance(stmt.rvar1, ChironSSA.Var): + rvar1 = z3.Int(stmt.rvar1.name) + elif isinstance(stmt.rvar1, ChironSSA.Num): + rvar1 = z3.IntVal(stmt.rvar1.value) + if isinstance(stmt.rvar2, ChironSSA.Var): + rvar2 = z3.Int(stmt.rvar2.name) + elif isinstance(stmt.rvar2, ChironSSA.Num): + rvar2 = z3.IntVal(stmt.rvar2.value) + elif stmt.op in ["and", "or"]: + lvar = z3.Bool(stmt.lvar.name) + if isinstance(stmt.rvar1, ChironSSA.Var): + rvar1 = z3.Bool(stmt.rvar1.name) + elif isinstance(stmt.rvar1, ChironSSA.BoolTrue): + rvar1 = z3.BoolVal(True) + if isinstance(stmt.rvar2, ChironSSA.Var): + rvar2 = z3.Bool(stmt.rvar2.name) + elif isinstance(stmt.rvar2, ChironSSA.BoolFalse): + rvar2 = z3.BoolVal(False) + elif stmt.op == "not": + lvar = z3.Bool(stmt.lvar.name) + if isinstance(stmt.rvar2, ChironSSA.Var): + rvar2 = z3.Bool(stmt.rvar2.name) + elif isinstance(stmt.rvar2, ChironSSA.BoolTrue): + rvar2 = z3.BoolVal(True) + elif isinstance(stmt.rvar2, ChironSSA.BoolFalse): + rvar2 = z3.BoolVal(False) + elif stmt.op == "": + continue + else: + raise Exception("Unknown SSA instruction") + + if stmt.op == "+": + self.solver.add(lvar == (rvar1 + rvar2)) + elif stmt.op == "-": + self.solver.add(lvar == (rvar1 - rvar2)) + elif stmt.op == "*": + self.solver.add(lvar == (rvar1 * rvar2)) + elif stmt.op == "/": + self.solver.add(lvar == (rvar1 / rvar2)) + elif stmt.op == "<": + self.solver.add(lvar == (rvar1 < rvar2)) + elif stmt.op == ">": + self.solver.add(lvar == (rvar1 > rvar2)) + elif stmt.op == "<=": + self.solver.add(lvar == (rvar1 <= rvar2)) + elif stmt.op == ">=": + self.solver.add(lvar == (rvar1 >= rvar2)) + elif stmt.op == "==": + self.solver.add(lvar == (rvar1 == rvar2)) + elif stmt.op == "!=": + self.solver.add(lvar == (rvar1 != rvar2)) + elif stmt.op == "and": + self.solver.add(lvar == z3.And(rvar1, rvar2)) + elif stmt.op == "or": + self.solver.add(lvar == z3.Or(rvar1, rvar2)) + elif stmt.op == "not": + self.solver.add(lvar == z3.Not(rvar2)) + + elif isinstance(stmt, ChironSSA.AssertCommand): + cond = None + if isinstance(stmt.cond, ChironSSA.BoolTrue): + cond = z3.BoolVal(True) + elif isinstance(stmt.cond, ChironSSA.BoolFalse): + cond = z3.BoolVal(False) + elif isinstance(stmt.cond, ChironSSA.Var): + cond = z3.Bool(stmt.cond.name) + self.solver.add(z3.Not(cond)) + + # elif isinstance(stmt, ChironSSA.CosCommand): # Problem: z3.Cos, z3.Sin is not supported + # self.solver.add(z3.Real(stmt.lvar.name) == z3.Cos(z3.Real(stmt.rvar1.name))) + # elif isinstance(stmt, ChironSSA.SinCommand): + # self.solver.add(z3.Real(stmt.lvar.name) == z3.Sin(z3.Real(stmt.rvar1.name))) + + # elif isinstance(stmt, ChironSSA.MoveCommand): + # elif isinstance(stmt, ChironSSA.PenCommand): + # elif isinstance(stmt, ChironSSA.GotoCommand): + elif isinstance(stmt, ChironSSA.ConditionCommand): + pass + elif isinstance(stmt, ChironSSA.NoOpCommand): + pass + elif isinstance(stmt, ChironSSA.PauseCommand): + pass # else: # raise Exception("Unknown SSA instruction") def solve(self, inputVars): - print("Assertions are:") - print(self.solver.assertions()) - print() sat = self.solver.check() if sat == z3.sat: print("Condition not satisfied! Bug found for the following input:") model = self.solver.model() for var in model: - varname = str(var)[:-3] + varname = str(var).split("$")[0] if varname in inputVars: print(varname + " = " + str(model[var])) diff --git a/ChironCore/cfg/ChironCFG.py b/ChironCore/cfg/ChironCFG.py index 554b257..f502411 100644 --- a/ChironCore/cfg/ChironCFG.py +++ b/ChironCore/cfg/ChironCFG.py @@ -2,6 +2,7 @@ import networkx as nx import z3 +import collections class BasicBlock: def __init__(self, bbname): @@ -48,6 +49,7 @@ def __init__(self, gname='cfg'): self.exit = "END" self.df = None self.idom = None + self.dominator_tree = collections.defaultdict(list) def __iter__(self): return self.nxgraph.__iter__() @@ -108,6 +110,11 @@ def compute_dominance(self): self.idom = nx.immediate_dominators(self.nxgraph, entry) self.df = nx.dominance_frontiers(self.nxgraph, entry) + for i in self.nodes(): + for j in self.nodes(): + if i != j and self.idom[j] == i: + self.dominator_tree[i].append(j) + def get_topological_order(self): return list(nx.topological_sort(self.nxgraph)) diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index aa51d3b..7c1973b 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -413,17 +413,14 @@ def stopTurtle(): cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) # Building CFG cfgB.dumpCFG(cfg, 'tac_cfg') - amoghssa = SSABuilder(cfg) - amoghssa.build() + amoghssa = SSABuilder(tacGen.tac) + ssaCfg = amoghssa.build() - #ssa = buildSSA(tacGen.tac, cfg, line2BlockMap) # Building SSA - #printSSA(ssa) # Printing SSA - - #ssa_cfg, ssa_line2BlockMap = cfgB.buildCFG(ssa, "ssa_cfg", False) # Building CFG for SSA - #cfgB.dumpCFG(ssa_cfg, 'ssa_cfg') + print("\nSaving SSA Form of the program to file ssa_cfg.png\n") + cfgB.dumpCFG(ssaCfg, 'ssa_cfg') #print("\nConverting program to SMT-LIB format..\n") - #smt = bmc.BMC(ssa) - #smt.convertSSAtoSMT() - #smt.solve(tacGen.getFreeVariables()) + smt = bmc.BMC(ssaCfg) + smt.convertSSAtoSMT() + smt.solve(tacGen.getFreeVariables()) print("DONE..") diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 5085cdb..ec8c6e5 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,14 +1,38 @@ -if (:a > 1) [ - :y = 1 +if (:a > :b + :c) [ + :result = :a - :b + if (:c > :a - :b) [ + :result = :result + :c - :a + if (:result < :b - :c) [ + :result = :result + :b + :b + ] else [ + :result = :result - :c - :c + ] + ] else [ + :result = :a + :c + if (:a + :c - :b > :result) [ + :result = :result + :a - :b - :b + ] else [ + :result = :result - :a + :b + :b + ] + ] ] else [ - :y = 0 - if (:b < 1) [ - :x = 1 + :result = :b + :c + if (:b + :c - :a < :a + :a) [ + :result = :result - :a - :a + if (:result + :b > 0) [ + :result = :result + :b + :b - :c + ] else [ + :result = :result + :c + :c - :b + ] ] else [ - :x = 2 + :result = :a + :a + :a + if (:result - :c < :b + :b) [ + :result = :result + :b + :b + :b + ] else [ + :result = :result - :c - :c - :c + ] ] ] -if (:c == 1) [ - :x = 2 -] +goto (:result, 0) + diff --git a/ChironCore/example/move1.tl b/ChironCore/example/move1.tl deleted file mode 100644 index aefaa73..0000000 --- a/ChironCore/example/move1.tl +++ /dev/null @@ -1,17 +0,0 @@ -if (:a > 1) [ - :y = 1 -] else [ - :y = 0 - if (:b < 1) [ - :x = 1 - ] else [ - :x = 2 - ] -] - -if (:c == 1) [ - :x = 2 -] - -assert(:x > 0) -assert(:y > 0) From 9bc76abcd239c3329a952a118b68b51818e8ffd8 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Tue, 18 Mar 2025 01:27:19 +0530 Subject: [PATCH 25/53] added modulo operator and handled angle of turtle --- ChironCore/ChironAST/ChironAST.py | 4 + ChironCore/ChironAST/builder.py | 8 + ChironCore/ChironSSA/ChironSSA.py | 8 + ChironCore/ChironSSA/builder.py | 32 +- ChironCore/ChironSSA/ssaBuilder.py | 213 ----------- ChironCore/ChironTAC/ChironTAC.py | 10 +- ChironCore/ChironTAC/builder.py | 435 ++++++++++++++++++++++ ChironCore/bmc.py | 15 +- ChironCore/chiron.py | 13 +- ChironCore/example/move.tl | 2 +- ChironCore/example/move1.tl | 8 + ChironCore/irhandler.py | 420 +--------------------- ChironCore/turtparse/tlang.g4 | 3 + ChironCore/turtparse/tlang.interp | 5 +- ChironCore/turtparse/tlang.tokens | 52 +-- ChironCore/turtparse/tlangLexer.interp | 5 +- ChironCore/turtparse/tlangLexer.py | 225 ++++++------ ChironCore/turtparse/tlangLexer.tokens | 52 +-- ChironCore/turtparse/tlangParser.py | 478 +++++++++++++++---------- ChironCore/turtparse/tlangVisitor.py | 10 + 20 files changed, 994 insertions(+), 1004 deletions(-) delete mode 100644 ChironCore/ChironSSA/ssaBuilder.py create mode 100644 ChironCore/ChironTAC/builder.py create mode 100644 ChironCore/example/move1.tl diff --git a/ChironCore/ChironAST/ChironAST.py b/ChironCore/ChironAST/ChironAST.py index f86c5da..a2da4b9 100644 --- a/ChironCore/ChironAST/ChironAST.py +++ b/ChironCore/ChironAST/ChironAST.py @@ -126,6 +126,10 @@ class Div(BinArithOp): def __init__(self, lexpr, rexpr): super().__init__(lexpr, rexpr, "/") +class Mod(BinArithOp): + def __init__(self, lexpr, rexpr): + super().__init__(lexpr, rexpr, "%") + # --Boolean Expressions----------------------------------------------- diff --git a/ChironCore/ChironAST/builder.py b/ChironCore/ChironAST/builder.py index 95ad1a2..90db734 100644 --- a/ChironCore/ChironAST/builder.py +++ b/ChironCore/ChironAST/builder.py @@ -88,6 +88,14 @@ def visitMulExpr(self, ctx:tlangParser.MulExprContext): return ChironAST.Mult(left, right) elif ctx.multiplicative().DIV(): return ChironAST.Div(left, right) + + + # Visit a parse tree produced by tlangParser#valueExpr. + def visitModExpr(self, ctx:tlangParser.ModExprContext): + left = self.visit(ctx.expression(0)) + right = self.visit(ctx.expression(1)) + if ctx.modulo().MOD(): + return ChironAST.Mod(left, right) # Visit a parse tree produced by tlangParser#parenExpr. diff --git a/ChironCore/ChironSSA/ChironSSA.py b/ChironCore/ChironSSA/ChironSSA.py index 20eb216..5e05e46 100644 --- a/ChironCore/ChironSSA/ChironSSA.py +++ b/ChironCore/ChironSSA/ChironSSA.py @@ -6,6 +6,14 @@ class SSA(object): class Instruction(SSA): pass +class DegToRadCommand(Instruction): + def __init__(self, lvar, rvar): # lvar = degToRad(rvar) + self.lvar = lvar + self.rvar = rvar + + def __str__(self): + return self.lvar.__str__() + " = degToRad(" + self.rvar.__str__() + ")" + class CosCommand(Instruction): def __init__(self, lvar, rvar): # lvar = cos(rvar) self.lvar = lvar diff --git a/ChironCore/ChironSSA/builder.py b/ChironCore/ChironSSA/builder.py index 6b8588b..c20d79a 100644 --- a/ChironCore/ChironSSA/builder.py +++ b/ChironCore/ChironSSA/builder.py @@ -21,8 +21,15 @@ def build(self): self.cfg.compute_dominance() self.insert_phi_nodes() self.rename_variables() + self.remove_empty_phi() return self.cfg + + def remove_empty_phi(self): + for block in self.cfg.nodes(): + for instr, _ in block.instrlist: + if isinstance(instr, ChironSSA.PhiCommand) and len(instr.rvars) == 0: + block.instrlist.remove((instr, None)) def rename_variables(self): for var in self.globals: @@ -37,7 +44,7 @@ def rename_variables(self): self.rename(entry) - def rename(self, block): # TODO + def rename(self, block): temp = set() for instr, _ in block.instrlist: if isinstance(instr, ChironSSA.PhiCommand): @@ -70,6 +77,24 @@ def rename(self, block): # TODO if isinstance(instr.ycor, ChironSSA.Var): instr.ycor = ChironSSA.Var(instr.ycor.name + "$" + str(self.stack[instr.ycor.name][-1])) + elif isinstance(instr, ChironSSA.SinCommand): + temp.add(instr.lvar.name) + instr.lvar = self.new_name(instr.lvar.name) + if isinstance(instr.rvar, ChironSSA.Var): + instr.rvar = ChironSSA.Var(instr.rvar.name + "$" + str(self.stack[instr.rvar.name][-1])) + + elif isinstance(instr, ChironSSA.CosCommand): + temp.add(instr.lvar.name) + instr.lvar = self.new_name(instr.lvar.name) + if isinstance(instr.rvar, ChironSSA.Var): + instr.rvar = ChironSSA.Var(instr.rvar.name + "$" + str(self.stack[instr.rvar.name][-1])) + + elif isinstance(instr, ChironSSA.DegToRadCommand): + temp.add(instr.lvar.name) + instr.lvar = self.new_name(instr.lvar.name) + if isinstance(instr.rvar, ChironSSA.Var): + instr.rvar = ChironSSA.Var(instr.rvar.name + "$" + str(self.stack[instr.rvar.name][-1])) + visited = set() def phi_dfs(curr, var): visited.add(curr) @@ -194,6 +219,11 @@ def convert(self, ir): rvar = ChironSSA.Var(instr.rvar.name) if isinstance(instr.rvar, ChironTAC.Var) else ChironSSA.Num(instr.rvar.value) ir[ir.index((instr, tgt))] = (ChironSSA.CosCommand(lvar, rvar), tgt) + elif isinstance(instr, ChironTAC.DegToRadCommand): + lvar = ChironSSA.Var(instr.lvar.name) + rvar = ChironSSA.Var(instr.rvar.name) if isinstance(instr.rvar, ChironTAC.Var) else ChironSSA.Num(instr.rvar.value) + ir[ir.index((instr, tgt))] = (ChironSSA.DegToRadCommand(lvar, rvar), tgt) + elif isinstance(instr, ChironTAC.PenCommand): ir[ir.index((instr, tgt))] = (ChironSSA.PenCommand(instr.status), tgt) diff --git a/ChironCore/ChironSSA/ssaBuilder.py b/ChironCore/ChironSSA/ssaBuilder.py deleted file mode 100644 index 3b7fb05..0000000 --- a/ChironCore/ChironSSA/ssaBuilder.py +++ /dev/null @@ -1,213 +0,0 @@ -from cfg.ChironCFG import * -import ChironTAC.ChironTAC as ChironTAC -import ChironSSA.ChironSSA as ChironSSA - -def buildSSA(tac, cfg, line2BlockMap): - """ - Builds SSA form from TAC and CFG. - """ - - ssa = [] - lastDeclaration = {} # lastDeclaration[bb][var] = last version of var in bb - varCounter = {} # varCounter[var] = counter - phiStatements = {} # phiStatements[bb][var] = [var_1, var_2, ...] - ssaLineCounter = 0 - block2ssaLine = {} # block2ssaLine[bb] = ssaLine - - # Initialize - for (stmt, tgt), line in zip(tac, range(len(tac))): - if isinstance(stmt, ChironTAC.AssignmentCommand): - varCounter[stmt.lvar.__str__()] = 0 - - for node in cfg: - phiStatements[node] = {} - lastDeclaration[node] = {} - - # Renamed the declarations of variables in TAC - for (stmt, tgt), line in zip(tac, range(len(tac))): - if isinstance(stmt, ChironTAC.AssignmentCommand): - var = stmt.lvar.__str__() - lastDeclaration[line2BlockMap[line]][var] = varCounter[var] - varCounter[var] += 1 - stmt.lvar = ChironTAC.Var(f"{var}__{varCounter[var] - 1}") - tac[line] = (stmt, tgt) - elif isinstance(stmt, ChironTAC.CosCommand): - var = stmt.lvar.__str__() - lastDeclaration[line2BlockMap[line]][var] = varCounter[var] - varCounter[var] += 1 - stmt.lvar = ChironTAC.Var(f"{var}__{varCounter[var] - 1}") - tac[line] = (stmt, tgt) - elif isinstance(stmt, ChironTAC.SinCommand): - var = stmt.lvar.__str__() - lastDeclaration[line2BlockMap[line]][var] = varCounter[var] - varCounter[var] += 1 - stmt.lvar = ChironTAC.Var(f"{var}__{varCounter[var] - 1}") - tac[line] = (stmt, tgt) - - for node in cfg: - predes = cfg.predecessors(node) - for parent in predes: - for var in lastDeclaration[parent]: - if var not in phiStatements[node]: - phiStatements[node][var] = [] - phiStatements[node][var].append(lastDeclaration[parent][var]) - - visited = {} - for node in cfg: - visited[node] = False - - lastUsed = {} - for var in varCounter.keys(): - lastUsed[var] = varCounter[var] - - for (stmt, tgt), line in zip(tac, range(len(tac))): - node = line2BlockMap[line] - if visited[node] == False: - visited[node] = True - block2ssaLine[node] = ssaLineCounter - for var in phiStatements[node].keys(): - if len(phiStatements[node][var]) > 1: - ssaLineCounter += 1 - ssa.append((ChironSSA.PhiCommand(ChironSSA.Var(f"{var}__{varCounter[var]}"), [ChironSSA.Var(f"{var}__{version}") for version in phiStatements[node][var]]), 1)) - lastUsed[var] = varCounter[var] - varCounter[var] += 1 - - if isinstance(stmt, ChironTAC.AssignmentCommand): - rvar1 = ChironSSA.Unused() - rvar2 = ChironSSA.Unused() - if isinstance(stmt.rvar1, ChironTAC.Var): - if stmt.rvar1.__str__() not in lastUsed.keys(): - lastUsed[stmt.rvar1.__str__()] = 0 - rvar1 = ChironSSA.Var(f"{stmt.rvar1.__str__()}__{lastUsed[stmt.rvar1.__str__()]}") - elif isinstance(stmt.rvar1, ChironTAC.BoolTrue): - rvar1 = ChironSSA.BoolTrue() - elif isinstance(stmt.rvar1, ChironTAC.BoolFalse): - rvar1 = ChironSSA.BoolFalse() - elif isinstance(stmt.rvar1, ChironTAC.Num): - rvar1 = ChironSSA.Num(stmt.rvar1.value) - if isinstance(stmt.rvar2, ChironTAC.Var): - if stmt.rvar2.__str__() not in lastUsed.keys(): - lastUsed[stmt.rvar2.__str__()] = 0 - rvar2 = ChironSSA.Var(f"{stmt.rvar2.__str__()}__{lastUsed[stmt.rvar2.__str__()]}") - elif isinstance(stmt.rvar2, ChironTAC.BoolTrue): - rvar2 = ChironSSA.BoolTrue() - elif isinstance(stmt.rvar2, ChironTAC.BoolFalse): - rvar2 = ChironSSA.BoolFalse() - elif isinstance(stmt.rvar2, ChironTAC.Num): - rvar2 = ChironSSA.Num(stmt.rvar2.value) - lvar = ChironSSA.Var(f"{stmt.lvar.__str__()}") - - lvar_string = lvar.__str__().rsplit('__', 1)[0] - lastUsed[lvar_string] = int(lvar.__str__().rsplit('__', 1)[1]) - - ssaLineCounter += 1 - ssa.append((ChironSSA.AssignmentCommand(lvar, rvar1, rvar2, stmt.op), tgt)) - - elif isinstance(stmt, ChironTAC.ConditionCommand): - tgt_block = line2BlockMap[line + tgt] - if isinstance(stmt.cond, ChironTAC.BoolTrue): - ssa.append((ChironSSA.ConditionCommand(ChironSSA.BoolTrue()), tgt_block)) - elif isinstance(stmt.cond, ChironTAC.BoolFalse): - ssa.append((ChironSSA.ConditionCommand(ChironSSA.BoolFalse()), tgt_block)) - else: - if isinstance(stmt.cond, ChironTAC.Var): - if stmt.cond.__str__() not in lastUsed.keys(): - lastUsed[stmt.cond.__str__()] = 0 - cond = ChironSSA.Var(f"{stmt.cond.__str__()}__{lastUsed[stmt.cond.__str__()]}") - elif isinstance(stmt.cond, ChironTAC.Num): - cond = ChironSSA.Num(stmt.cond.value) - ssa.append((ChironSSA.ConditionCommand(cond), tgt_block)) - ssaLineCounter += 1 - - elif isinstance(stmt, ChironTAC.AssertCommand): - if isinstance(stmt.cond, ChironTAC.BoolTrue): - ssa.append((ChironSSA.AssertCommand(ChironSSA.BoolTrue()), tgt)) - elif isinstance(stmt.cond, ChironTAC.BoolFalse): - ssa.append((ChironSSA.AssertCommand(ChironSSA.BoolFalse()), tgt)) - else: - if isinstance(stmt.cond, ChironTAC.Var): - if stmt.cond.__str__() not in lastUsed.keys(): - lastUsed[stmt.cond.__str__()] = 0 - cond = ChironSSA.Var(f"{stmt.cond.__str__()}__{lastUsed[stmt.cond.__str__()]}") - elif isinstance(stmt.cond, ChironTAC.Num): - cond = ChironSSA.Num(stmt.cond.value) - ssa.append((ChironSSA.AssertCommand(cond), tgt)) - ssaLineCounter += 1 - - elif isinstance(stmt, ChironTAC.MoveCommand): - var = None - if isinstance(stmt.var, ChironTAC.Var): - if stmt.var.__str__() not in lastUsed.keys(): - lastUsed[stmt.var.__str__()] = 0 - var = ChironSSA.Var(f"{stmt.var.__str__()}__{lastUsed[stmt.var.__str__()]}") - elif isinstance(stmt.var, ChironTAC.Num): - var = ChironSSA.Num(stmt.var.value) - ssa.append((ChironSSA.MoveCommand(stmt.direction, var), tgt)) - ssaLineCounter += 1 - - elif isinstance(stmt, ChironTAC.PenCommand): - ssa.append((ChironSSA.PenCommand(stmt.status), tgt)) - ssaLineCounter += 1 - - elif isinstance(stmt, ChironTAC.GotoCommand): - x_var = None - y_var = None - if isinstance(stmt.xcor, ChironTAC.Var): - if stmt.xcor.__str__() not in lastUsed.keys(): - lastUsed[stmt.xcor.__str__()] = 0 - x_var = ChironSSA.Var(f"{stmt.xcor.__str__()}__{lastUsed[stmt.xcor.__str__()]}") - elif isinstance(stmt.xcor, ChironTAC.Num): - x_var = ChironSSA.Num(stmt.xcor.value) - if isinstance(stmt.ycor, ChironTAC.Var): - if stmt.ycor.__str__() not in lastUsed.keys(): - lastUsed[stmt.ycor.__str__()] = 0 - y_var = ChironSSA.Var(f"{stmt.ycor.__str__()}__{lastUsed[stmt.ycor.__str__()]}") - elif isinstance(stmt.ycor, ChironTAC.Num): - y_var = ChironSSA.Num(stmt.ycor.value) - ssa.append((ChironSSA.GotoCommand(x_var, y_var), tgt)) - ssaLineCounter += 1 - - elif isinstance(stmt, ChironTAC.NoOpCommand): - ssa.append((ChironSSA.NoOpCommand(), tgt)) - ssaLineCounter += 1 - - elif isinstance(stmt, ChironTAC.PauseCommand): - ssa.append((ChironSSA.PauseCommand(), tgt)) - ssaLineCounter += 1 - - elif isinstance(stmt, ChironTAC.CosCommand): - if stmt.rvar.__str__() not in lastUsed.keys(): - lastUsed[stmt.rvar.__str__()] = 0 - ssa.append((ChironSSA.CosCommand(ChironSSA.Var(f"{stmt.lvar.__str__()}"), ChironSSA.Var(f"{stmt.rvar.__str__()}__{lastUsed[stmt.rvar.__str__()]}")), tgt)) - lvar_string = lvar.__str__().rsplit('__', 1)[0] - lastUsed[lvar_string] = int(lvar.__str__().rsplit('__', 1)[1]) - ssaLineCounter += 1 - - elif isinstance(stmt, ChironTAC.SinCommand): - if stmt.rvar.__str__() not in lastUsed.keys(): - lastUsed[stmt.rvar.__str__()] = 0 - ssa.append((ChironSSA.SinCommand(ChironSSA.Var(f"{stmt.lvar.__str__()}"), ChironSSA.Var(f"{stmt.rvar.__str__()}__{lastUsed[stmt.rvar.__str__()]}")), tgt)) - lvar_string = lvar.__str__().rsplit('__', 1)[0] - lastUsed[lvar_string] = int(lvar.__str__().rsplit('__', 1)[1]) - ssaLineCounter += 1 - - else: - raise Exception(f"Unknown TAC command: {stmt}") - - block2ssaLine[line2BlockMap[len(tac)]] = ssaLineCounter - - for (stmt, tgt), line in zip(ssa, range(len(ssa))): - if isinstance(stmt, ChironSSA.ConditionCommand): - tgt = block2ssaLine[tgt] - line - ssa[line] = (stmt, tgt) - - return ssa - -def printSSA(ssa): - """ - Prints SSA form. - """ - print("\nSSA Form:") - for (stmt, tgt), line in zip(ssa, range(len(ssa))): - print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") - diff --git a/ChironCore/ChironTAC/ChironTAC.py b/ChironCore/ChironTAC/ChironTAC.py index 293adb6..cd2c636 100644 --- a/ChironCore/ChironTAC/ChironTAC.py +++ b/ChironCore/ChironTAC/ChironTAC.py @@ -6,6 +6,14 @@ class TAC(object): class Instruction(TAC): pass +class DegToRadCommand(Instruction): + def __init__(self, lvar, rvar): # lvar = degToRad(rvar) + self.lvar = lvar + self.rvar = rvar + + def __str__(self): + return self.lvar.__str__() + " = degToRad(" + self.rvar.__str__() + ")" + class CosCommand(Instruction): def __init__(self, lvar, rvar): # lvar = cos(rvar) self.lvar = lvar @@ -207,4 +215,4 @@ def __str__(self): class Unused(Value): def __str__(self): - return "" + return "" \ No newline at end of file diff --git a/ChironCore/ChironTAC/builder.py b/ChironCore/ChironTAC/builder.py new file mode 100644 index 0000000..19def3e --- /dev/null +++ b/ChironCore/ChironTAC/builder.py @@ -0,0 +1,435 @@ +""" +Class for converting IR to Three Address Code (TAC) +""" + +from ChironAST import ChironAST +from ChironTAC import ChironTAC + + +class TACGenerator: + def __init__(self, ir): + self.ir = ir + self.tac = [] + self.tempCount = 0 + self.branchCount = 0 + self.assertCount = 0 + self.moveCount = 0 + self.gotoCount = 0 + self.ast_to_tac_line = {} + self.line = 0 + self.freeVars = set() + + def parseExpresssion(self, expr, dest): + """ + Parse the expression and return the TAC for the expression. + """ + if isinstance(expr, ChironAST.BinArithOp): + left = None + right = None + if isinstance(expr.lexpr, ChironAST.Num): + left = ChironTAC.Num(expr.lexpr.val) + elif isinstance(expr.lexpr, ChironAST.Var): + left = ChironTAC.Var(expr.lexpr.varname) + else: + temp = ChironTAC.Var(f":__temp_{self.tempCount}") + self.tempCount += 1 + left = temp + self.parseExpresssion(expr.lexpr, temp) + + if isinstance(expr.rexpr, ChironAST.Num): + right = ChironTAC.Num(expr.rexpr.val) + elif isinstance(expr.rexpr, ChironAST.Var): + right = ChironTAC.Var(expr.rexpr.varname) + else: + temp = ChironTAC.Var(f":__temp_{self.tempCount}") + self.tempCount += 1 + right = temp + self.parseExpresssion(expr.rexpr, temp) + + self.line += 1 + self.tac.append( + (ChironTAC.AssignmentCommand(dest, left, right, expr.symbol), 1) + ) + elif isinstance(expr, ChironAST.UMinus): + if isinstance(expr.expr, ChironAST.Num): + self.line += 1 + self.tac.append( + ( + ChironTAC.AssignmentCommand( + dest, + ChironTAC.Num(0), + ChironTAC.Num(expr.expr.val), + "-", + ), + 1, + ), + ) + elif isinstance(expr.expr, ChironAST.Var): + self.line += 1 + self.tac.append( + ( + ChironTAC.AssignmentCommand( + dest, + ChironTAC.Num(0), + ChironTAC.Var(expr.expr.varname), + "-", + ), + 1, + ), + ) + else: + temp = ChironTAC.Var(f":__temp_{self.tempCount}") + self.tempCount += 1 + self.parseExpresssion(expr.expr, temp) + self.line += 1 + self.tac.append( + ( + ChironTAC.AssignmentCommand( + dest, ChironTAC.Num(0), temp, "-" + ), + 1, + ) + ) + elif isinstance(expr, ChironAST.BinCondOp) and not ( + isinstance(expr, ChironAST.AND) + or isinstance(expr, ChironAST.OR) + or isinstance(expr, ChironAST.NOT) + ): + left = None + right = None + if isinstance(expr.lexpr, ChironAST.Num): + left = ChironTAC.Num(expr.lexpr.val) + elif isinstance(expr.lexpr, ChironAST.Var): + left = ChironTAC.Var(expr.lexpr.varname) + else: + temp = ChironTAC.Var(f":__temp_{self.tempCount}") + self.tempCount += 1 + left = temp + self.parseExpresssion(expr.lexpr, temp) + + if isinstance(expr.rexpr, ChironAST.Num): + right = ChironTAC.Num(expr.rexpr.val) + elif isinstance(expr.rexpr, ChironAST.Var): + right = ChironTAC.Var(expr.rexpr.varname) + else: + temp = ChironTAC.Var(f":__temp_{self.tempCount}") + self.tempCount += 1 + right = temp + self.parseExpresssion(expr.rexpr, temp) + + self.line += 1 + self.tac.append( + (ChironTAC.AssignmentCommand(dest, left, right, expr.symbol), 1) + ) + elif isinstance(expr, ChironAST.AND) or isinstance(expr, ChironAST.OR): + left = None + right = None + if isinstance(expr.lexpr, ChironAST.BoolTrue): + left = ChironTAC.BoolTrue() + elif isinstance(expr.lexpr, ChironAST.BoolFalse): + left = ChironTAC.BoolFalse() + elif isinstance(expr.lexpr, ChironAST.Var): + left = ChironTAC.Var(expr.lexpr.varname) + else: + temp = ChironTAC.Var(f":__temp_{self.tempCount}") + self.tempCount += 1 + left = temp + self.parseExpresssion(expr.lexpr, temp) + + if isinstance(expr.rexpr, ChironAST.BoolTrue): + right = ChironTAC.BoolTrue() + elif isinstance(expr.rexpr, ChironAST.BoolFalse): + right = ChironTAC.BoolFalse() + elif isinstance(expr.rexpr, ChironAST.Var): + right = ChironTAC.Var(expr.rexpr.varname) + else: + temp = ChironTAC.Var(f":__temp_{self.tempCount}") + self.tempCount += 1 + right = temp + self.parseExpresssion(expr.rexpr, temp) + + self.line += 1 + self.tac.append( + (ChironTAC.AssignmentCommand(dest, left, right, expr.symbol), 1) + ) + elif isinstance(expr, ChironAST.NOT): + if isinstance(expr.expr, ChironAST.BoolTrue): + self.line += 1 + self.tac.append( + ( + ChironTAC.AssignmentCommand( + dest, + ChironTAC.Unused(), + ChironTAC.BoolTrue(), + "not", + ), + 1, + ) + ) + elif isinstance(expr.expr, ChironAST.BoolFalse): + self.line += 1 + self.tac.append( + ( + ChironTAC.AssignmentCommand( + dest, + ChironTAC.Unused(), + ChironTAC.BoolFalse(), + "not", + ), + 1, + ) + ) + elif isinstance(expr.expr, ChironAST.Var): + self.line += 1 + self.tac.append( + ( + ChironTAC.AssignmentCommand( + dest, + ChironTAC.Unused(), + ChironTAC.Var(expr.expr.varname), + "not", + ), + 1, + ) + ) + else: + temp = ChironTAC.Var(f":__temp_{self.tempCount}") + self.tempCount += 1 + self.parseExpresssion(expr.expr, temp) + self.line += 1 + self.tac.append( + (ChironTAC.AssignmentCommand(dest, None, temp, "not"), 1) + ) + elif isinstance(expr, ChironAST.Var): + self.line += 1 + self.tac.append( + ( + ChironTAC.AssignmentCommand( + dest, ChironTAC.Num(0), ChironTAC.Var(expr.varname), "+" + ), + 1, + ) + ) + elif isinstance(expr, ChironAST.Num): + self.line += 1 + self.tac.append( + ( + ChironTAC.AssignmentCommand( + dest, ChironTAC.Num(0), ChironTAC.Num(expr.val), "+" + ), + 1, + ) + ) + elif isinstance(expr, ChironAST.BoolTrue): + self.line += 1 + self.tac.append( + ( + ChironTAC.AssignmentCommand( + dest, ChironTAC.Unused(), ChironTAC.BoolTrue(), "" + ), + 1, + ) + ) + elif isinstance(expr, ChironAST.BoolFalse): + self.line += 1 + self.tac.append( + ( + ChironTAC.AssignmentCommand( + dest, ChironTAC.Unused(), ChironTAC.BoolFalse(), "" + ), + 1, + ) + ) + else: + raise NotImplementedError( + "Unknown expression: %s, %s." % (type(expr), expr) + ) + + def generateTAC(self): + line_number = 0 + for stmt, tgt in self.ir: + self.ast_to_tac_line[line_number] = self.line + line_number += 1 + + if isinstance(stmt, ChironAST.AssignmentCommand): + self.parseExpresssion(stmt.rexpr, ChironTAC.Var(stmt.lvar.varname)) + + elif isinstance(stmt, ChironAST.ConditionCommand): + branchvar = None + if isinstance(stmt.cond, ChironAST.BoolTrue): + branchvar = ChironTAC.BoolTrue() + elif isinstance(stmt.cond, ChironAST.BoolFalse): + branchvar = ChironTAC.BoolFalse() + elif isinstance(stmt.cond, ChironAST.Var): + branchvar = ChironTAC.Var(stmt.cond.varname) + else: + branchvar = ChironTAC.Var(f":__branch_{self.branchCount}") + self.branchCount += 1 + self.parseExpresssion(stmt.cond, branchvar) + newtgt = line_number - 1 + tgt # Adjusted later + self.line += 1 + self.tac.append((ChironTAC.ConditionCommand(branchvar), newtgt)) + + elif isinstance(stmt, ChironAST.AssertCommand): + assertvar = ChironTAC.Var(f":__assert_{self.assertCount}") + self.assertCount += 1 + self.parseExpresssion(stmt.cond, assertvar) + self.line += 1 + self.tac.append((ChironTAC.AssertCommand(assertvar), 1)) + + elif isinstance(stmt, ChironAST.MoveCommand): + movevar = None + if isinstance(stmt.expr, ChironAST.Num): + movevar = ChironTAC.Num(stmt.expr.val) + elif isinstance(stmt.expr, ChironAST.Var): + movevar = ChironTAC.Var(stmt.expr.varname) + else: + movevar = ChironTAC.Var(f":__move_{self.moveCount}") + self.moveCount += 1 + self.parseExpresssion(stmt.expr, movevar) + self.line += 1 + self.tac.append((ChironTAC.MoveCommand(stmt.direction, movevar), 1)) + if (stmt.direction == "forward" or stmt.direction == "backward"): + self.line += 6 + self.tac.append((ChironTAC.CosCommand(ChironTAC.Var(":__cos_theta"), ChironTAC.Var(":__turtle_theta_rad")), 1)) + self.tac.append((ChironTAC.SinCommand(ChironTAC.Var(":__sin_theta"), ChironTAC.Var(":__turtle_theta_rad")), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__delta_x"), movevar, ChironTAC.Var(":__cos_theta"), "*"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__delta_y"), movevar, ChironTAC.Var(":__sin_theta"), "*"), 1)) + if (stmt.direction == "forward"): + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__delta_x"), "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__delta_y"), "+"), 1)) + elif (stmt.direction == "backward"): + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__delta_x"), "-"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__delta_y"), "-"), 1)) + elif (stmt.direction == "left"): + self.line += 3 + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Var(":__turtle_theta_deg"), movevar, "-"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Num(360), "%"), 1)) + self.tac.append((ChironTAC.DegToRadCommand(ChironTAC.Var(":__turtle_theta_rad"), ChironTAC.Var(":__turtle_theta_deg")), 1)) + elif (stmt.direction == "right"): + self.line += 3 + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Var(":__turtle_theta_deg"), movevar, "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Num(360), "%"), 1)) + self.tac.append((ChironTAC.DegToRadCommand(ChironTAC.Var(":__turtle_theta_rad"), ChironTAC.Var(":__turtle_theta_deg")), 1)) + else: + raise NotImplementedError("Unknown move direction: %s, %s." % (type(stmt), stmt)) + + elif isinstance(stmt, ChironAST.PenCommand): + self.line += 2 + self.tac.append((ChironTAC.PenCommand(stmt.status), 1)) + if (stmt.status == "penup"): + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(1), ChironTAC.Num(0), "+"), 1)) + elif (stmt.status == "pendown"): + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + else: + raise NotImplementedError("Unknown pen status: %s, %s." % (type(stmt), stmt)) + + elif isinstance(stmt, ChironAST.GotoCommand): + xvar = None + yvar = None + if isinstance(stmt.xcor, ChironAST.Num): + xvar = ChironTAC.Num(stmt.xcor.val) + elif isinstance(stmt.xcor, ChironAST.Var): + xvar = ChironTAC.Var(stmt.xcor.varname) + else: + xvar = ChironTAC.Var(f":__x_{self.gotoCount}") + self.gotoCount += 1 + self.parseExpresssion(stmt.xcor, xvar) + if isinstance(stmt.ycor, ChironAST.Num): + yvar = ChironTAC.Num(stmt.ycor.val) + elif isinstance(stmt.ycor, ChironAST.Var): + yvar = ChironTAC.Var(stmt.ycor.varname) + else: + yvar = ChironTAC.Var(f":__y_{self.gotoCount}") + self.gotoCount += 1 + self.parseExpresssion(stmt.ycor, yvar) + self.line += 3 + self.tac.append((ChironTAC.GotoCommand(xvar, yvar), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), xvar, ChironTAC.Num(0), "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), yvar, ChironTAC.Num(0), "+"), 1)) + + elif isinstance(stmt, ChironAST.NoOpCommand): + self.line += 1 + self.tac.append((ChironTAC.NoOpCommand(), 1)) + + elif isinstance(stmt, ChironAST.PauseCommand): + self.line += 1 + self.tac.append((ChironTAC.PauseCommand(), 1)) + + else: + raise NotImplementedError( + "Unknown instruction: %s, %s." % (type(stmt), stmt) + ) + + self.ast_to_tac_line[line_number] = self.line + + for i in range(len(self.tac)): + stmt, tgt = self.tac[i] + if isinstance(stmt, ChironTAC.ConditionCommand): + newtgt = self.ast_to_tac_line[tgt] - i + self.tac[i] = (stmt, newtgt) + + self.handleMoveVariables() + self.handleFreeVariables() + + def handleFreeVariables(self): + self.freeVars = self.getFreeVariables() + + for var in self.freeVars: + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(var), ChironTAC.Unused(), ChironTAC.Unused(), ""), 1)) + + def handleMoveVariables(self): + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_rad"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) # 0->down 1->up + + def getFreeVariables(self): + """ + Returns free variables in TAC. + """ + if len(self.freeVars) > 0: + return self.freeVars + + boundVars = set() + for (stmt, _), _ in zip(self.tac, range(len(self.tac))): + if isinstance(stmt, ChironTAC.AssignmentCommand): + if isinstance(stmt.rvar1, ChironTAC.Var) and stmt.rvar1.__str__() not in boundVars: + self.freeVars.add(stmt.rvar1.__str__()) + if isinstance(stmt.rvar2, ChironTAC.Var) and stmt.rvar2.__str__() not in boundVars: + self.freeVars.add(stmt.rvar2.__str__()) + boundVars.add(stmt.lvar.__str__()) + elif isinstance(stmt, ChironTAC.ConditionCommand): + if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: + self.freeVars.add(stmt.cond.__str__()) + elif isinstance(stmt, ChironTAC.AssertCommand): + if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: + self.freeVars.add(stmt.cond.__str__()) + elif isinstance(stmt, ChironTAC.MoveCommand): + if isinstance(stmt.var, ChironTAC.Var) and stmt.var.__str__() not in boundVars: + self.freeVars.add(stmt.var.__str__()) + elif isinstance(stmt, ChironTAC.GotoCommand): + if isinstance(stmt.xcor, ChironTAC.Var) and stmt.xcor.__str__() not in boundVars: + self.freeVars.add(stmt.xcor.__str__()) + if isinstance(stmt.ycor, ChironTAC.Var) and stmt.ycor.__str__() not in boundVars: + self.freeVars.add(stmt.ycor.__str__()) + elif isinstance(stmt, ChironTAC.SinCommand): + if isinstance(stmt.rvar, ChironTAC.Var) and stmt.rvar.__str__() not in boundVars: + self.freeVars.add(stmt.rvar.__str__()) + boundVars.add(stmt.lvar.__str__()) + elif isinstance(stmt, ChironTAC.CosCommand): + if isinstance(stmt.rvar, ChironTAC.Var) and stmt.rvar.__str__() not in boundVars: + self.freeVars.add(stmt.rvar.__str__()) + boundVars.add(stmt.lvar.__str__()) + elif isinstance(stmt, ChironTAC.DegToRadCommand): + if isinstance(stmt.rvar, ChironTAC.Var) and stmt.rvar.__str__() not in boundVars: + self.freeVars.add(stmt.rvar.__str__()) + boundVars.add(stmt.lvar.__str__()) + + return self.freeVars + + + def printTAC(self): + for (stmt, tgt), line in zip(self.tac, range(len(self.tac))): + print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index bdb1f3f..9e96644 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -64,7 +64,7 @@ def convertSSAtoSMT(self): lvar = None rvar1 = ChironSSA.Unused() rvar2 = ChironSSA.Unused() - if stmt.op in ["+", "-", "*", "/"]: + if stmt.op in ["+", "-", "*", "/", "%"]: lvar = z3.Int(stmt.lvar.name) if isinstance(stmt.rvar1, ChironSSA.Var): rvar1 = z3.Int(stmt.rvar1.name) @@ -115,6 +115,8 @@ def convertSSAtoSMT(self): self.solver.add(lvar == (rvar1 * rvar2)) elif stmt.op == "/": self.solver.add(lvar == (rvar1 / rvar2)) + elif stmt.op == "%": + self.solver.add(lvar == (rvar1 % rvar2)) elif stmt.op == "<": self.solver.add(lvar == (rvar1 < rvar2)) elif stmt.op == ">": @@ -143,7 +145,16 @@ def convertSSAtoSMT(self): elif isinstance(stmt.cond, ChironSSA.Var): cond = z3.Bool(stmt.cond.name) self.solver.add(z3.Not(cond)) - + + elif isinstance(stmt, ChironSSA.DegToRadCommand): + rvar = None + if isinstance(stmt.rvar1, ChironSSA.Var): + rvar = z3.Real(stmt.rvar1.name) + elif isinstance(stmt.rvar1, ChironSSA.Num): + rvar = z3.RealVal(stmt.rvar1.value) + lvar = z3.Real(stmt.lvar.name) + self.solver.add(lvar == (rvar * 3.141592653589793 / 180)) + # elif isinstance(stmt, ChironSSA.CosCommand): # Problem: z3.Cos, z3.Sin is not supported # self.solver.add(z3.Real(stmt.lvar.name) == z3.Cos(z3.Real(stmt.rvar1.name))) # elif isinstance(stmt, ChironSSA.SinCommand): diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 7c1973b..5516822 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -22,7 +22,7 @@ import sExecution as se import cfg.cfgBuilder as cfgB import bmc as bmc -from ChironSSA.ssaBuilder import * +from ChironTAC.builder import * from ChironSSA.builder import * import submissionDFA as DFASub import submissionAI as AISub @@ -408,19 +408,18 @@ def stopTurtle(): tacGen = TACGenerator(ir) # Converting IR to TAC tacGen.generateTAC() - tacGen.printTAC() # Printing TAC + # tacGen.printTAC() # Printing TAC cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) # Building CFG cfgB.dumpCFG(cfg, 'tac_cfg') - amoghssa = SSABuilder(tacGen.tac) - ssaCfg = amoghssa.build() + ssa = SSABuilder(tacGen.tac) # Converting TAC to SSA + ssaCfg = ssa.build() - print("\nSaving SSA Form of the program to file ssa_cfg.png\n") - cfgB.dumpCFG(ssaCfg, 'ssa_cfg') + cfgB.dumpCFG(ssaCfg, 'ssa_cfg') # Saving SSA Form of the program to file ssa_cfg.png #print("\nConverting program to SMT-LIB format..\n") smt = bmc.BMC(ssaCfg) smt.convertSSAtoSMT() smt.solve(tacGen.getFreeVariables()) - print("DONE..") + # print("DONE..") diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index ec8c6e5..d379fc0 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -34,5 +34,5 @@ if (:a > :b + :c) [ ] ] -goto (:result, 0) +// goto (:result, 0) diff --git a/ChironCore/example/move1.tl b/ChironCore/example/move1.tl new file mode 100644 index 0000000..c7f3752 --- /dev/null +++ b/ChironCore/example/move1.tl @@ -0,0 +1,8 @@ +if (1 < 0) [ + :x = 10 + left 50 +] else [ + :x = 30 + right 50 +] +forward :x \ No newline at end of file diff --git a/ChironCore/irhandler.py b/ChironCore/irhandler.py index b395247..26bb124 100644 --- a/ChironCore/irhandler.py +++ b/ChironCore/irhandler.py @@ -6,7 +6,6 @@ from turtparse.tlangLexer import tlangLexer from ChironAST import ChironAST -from ChironTAC import ChironTAC def getParseTree(progfl): @@ -134,421 +133,4 @@ def pretty_print(self, irList): "The number after the opcode name represents the jump offset \nrelative to that statement.\n" ) for idx, item in enumerate(irList): - print(f"[L{idx}]".rjust(5), item[0], f"[{item[1]}]") - - -""" -Class for converting IR to Three Address Code (TAC) -""" - - -class TACGenerator: - def __init__(self, ir): - self.ir = ir - self.tac = [] - self.tempCount = 0 - self.branchCount = 0 - self.assertCount = 0 - self.moveCount = 0 - self.gotoCount = 0 - self.ast_to_tac_line = {} - self.line = 0 - self.freeVars = set() - - def parseExpresssion(self, expr, dest): - """ - Parse the expression and return the TAC for the expression. - """ - if isinstance(expr, ChironAST.BinArithOp): - left = None - right = None - if isinstance(expr.lexpr, ChironAST.Num): - left = ChironTAC.Num(expr.lexpr.val) - elif isinstance(expr.lexpr, ChironAST.Var): - left = ChironTAC.Var(expr.lexpr.varname) - else: - temp = ChironTAC.Var(f":__temp_{self.tempCount}") - self.tempCount += 1 - left = temp - self.parseExpresssion(expr.lexpr, temp) - - if isinstance(expr.rexpr, ChironAST.Num): - right = ChironTAC.Num(expr.rexpr.val) - elif isinstance(expr.rexpr, ChironAST.Var): - right = ChironTAC.Var(expr.rexpr.varname) - else: - temp = ChironTAC.Var(f":__temp_{self.tempCount}") - self.tempCount += 1 - right = temp - self.parseExpresssion(expr.rexpr, temp) - - self.line += 1 - self.tac.append( - (ChironTAC.AssignmentCommand(dest, left, right, expr.symbol), 1) - ) - elif isinstance(expr, ChironAST.UMinus): - if isinstance(expr.expr, ChironAST.Num): - self.line += 1 - self.tac.append( - ( - ChironTAC.AssignmentCommand( - dest, - ChironTAC.Num(0), - ChironTAC.Num(expr.expr.val), - "-", - ), - 1, - ), - ) - elif isinstance(expr.expr, ChironAST.Var): - self.line += 1 - self.tac.append( - ( - ChironTAC.AssignmentCommand( - dest, - ChironTAC.Num(0), - ChironTAC.Var(expr.expr.varname), - "-", - ), - 1, - ), - ) - else: - temp = ChironTAC.Var(f":__temp_{self.tempCount}") - self.tempCount += 1 - self.parseExpresssion(expr.expr, temp) - self.line += 1 - self.tac.append( - ( - ChironTAC.AssignmentCommand( - dest, ChironTAC.Num(0), temp, "-" - ), - 1, - ) - ) - elif isinstance(expr, ChironAST.BinCondOp) and not ( - isinstance(expr, ChironAST.AND) - or isinstance(expr, ChironAST.OR) - or isinstance(expr, ChironAST.NOT) - ): - left = None - right = None - if isinstance(expr.lexpr, ChironAST.Num): - left = ChironTAC.Num(expr.lexpr.val) - elif isinstance(expr.lexpr, ChironAST.Var): - left = ChironTAC.Var(expr.lexpr.varname) - else: - temp = ChironTAC.Var(f":__temp_{self.tempCount}") - self.tempCount += 1 - left = temp - self.parseExpresssion(expr.lexpr, temp) - - if isinstance(expr.rexpr, ChironAST.Num): - right = ChironTAC.Num(expr.rexpr.val) - elif isinstance(expr.rexpr, ChironAST.Var): - right = ChironTAC.Var(expr.rexpr.varname) - else: - temp = ChironTAC.Var(f":__temp_{self.tempCount}") - self.tempCount += 1 - right = temp - self.parseExpresssion(expr.rexpr, temp) - - self.line += 1 - self.tac.append( - (ChironTAC.AssignmentCommand(dest, left, right, expr.symbol), 1) - ) - elif isinstance(expr, ChironAST.AND) or isinstance(expr, ChironAST.OR): - left = None - right = None - if isinstance(expr.lexpr, ChironAST.BoolTrue): - left = ChironTAC.BoolTrue() - elif isinstance(expr.lexpr, ChironAST.BoolFalse): - left = ChironTAC.BoolFalse() - elif isinstance(expr.lexpr, ChironAST.Var): - left = ChironTAC.Var(expr.lexpr.varname) - else: - temp = ChironTAC.Var(f":__temp_{self.tempCount}") - self.tempCount += 1 - left = temp - self.parseExpresssion(expr.lexpr, temp) - - if isinstance(expr.rexpr, ChironAST.BoolTrue): - right = ChironTAC.BoolTrue() - elif isinstance(expr.rexpr, ChironAST.BoolFalse): - right = ChironTAC.BoolFalse() - elif isinstance(expr.rexpr, ChironAST.Var): - right = ChironTAC.Var(expr.rexpr.varname) - else: - temp = ChironTAC.Var(f":__temp_{self.tempCount}") - self.tempCount += 1 - right = temp - self.parseExpresssion(expr.rexpr, temp) - - self.line += 1 - self.tac.append( - (ChironTAC.AssignmentCommand(dest, left, right, expr.symbol), 1) - ) - elif isinstance(expr, ChironAST.NOT): - if isinstance(expr.expr, ChironAST.BoolTrue): - self.line += 1 - self.tac.append( - ( - ChironTAC.AssignmentCommand( - dest, - ChironTAC.Unused(), - ChironTAC.BoolTrue(), - "not", - ), - 1, - ) - ) - elif isinstance(expr.expr, ChironAST.BoolFalse): - self.line += 1 - self.tac.append( - ( - ChironTAC.AssignmentCommand( - dest, - ChironTAC.Unused(), - ChironTAC.BoolFalse(), - "not", - ), - 1, - ) - ) - elif isinstance(expr.expr, ChironAST.Var): - self.line += 1 - self.tac.append( - ( - ChironTAC.AssignmentCommand( - dest, - ChironTAC.Unused(), - ChironTAC.Var(expr.expr.varname), - "not", - ), - 1, - ) - ) - else: - temp = ChironTAC.Var(f":__temp_{self.tempCount}") - self.tempCount += 1 - self.parseExpresssion(expr.expr, temp) - self.line += 1 - self.tac.append( - (ChironTAC.AssignmentCommand(dest, None, temp, "not"), 1) - ) - elif isinstance(expr, ChironAST.Var): - self.line += 1 - self.tac.append( - ( - ChironTAC.AssignmentCommand( - dest, ChironTAC.Num(0), ChironTAC.Var(expr.varname), "+" - ), - 1, - ) - ) - elif isinstance(expr, ChironAST.Num): - self.line += 1 - self.tac.append( - ( - ChironTAC.AssignmentCommand( - dest, ChironTAC.Num(0), ChironTAC.Num(expr.val), "+" - ), - 1, - ) - ) - elif isinstance(expr, ChironAST.BoolTrue): - self.line += 1 - self.tac.append( - ( - ChironTAC.AssignmentCommand( - dest, ChironTAC.Unused(), ChironTAC.BoolTrue(), "" - ), - 1, - ) - ) - elif isinstance(expr, ChironAST.BoolFalse): - self.line += 1 - self.tac.append( - ( - ChironTAC.AssignmentCommand( - dest, ChironTAC.Unused(), ChironTAC.BoolFalse(), "" - ), - 1, - ) - ) - else: - raise NotImplementedError( - "Unknown expression: %s, %s." % (type(expr), expr) - ) - - def generateTAC(self): - line_number = 0 - for stmt, tgt in self.ir: - self.ast_to_tac_line[line_number] = self.line - line_number += 1 - - if isinstance(stmt, ChironAST.AssignmentCommand): - self.parseExpresssion(stmt.rexpr, ChironTAC.Var(stmt.lvar.varname)) - - elif isinstance(stmt, ChironAST.ConditionCommand): - branchvar = None - if isinstance(stmt.cond, ChironAST.BoolTrue): - branchvar = ChironTAC.BoolTrue() - elif isinstance(stmt.cond, ChironAST.BoolFalse): - branchvar = ChironTAC.BoolFalse() - elif isinstance(stmt.cond, ChironAST.Var): - branchvar = ChironTAC.Var(stmt.cond.varname) - else: - branchvar = ChironTAC.Var(f":__branch_{self.branchCount}") - self.branchCount += 1 - self.parseExpresssion(stmt.cond, branchvar) - newtgt = line_number - 1 + tgt # Adjusted later - self.line += 1 - self.tac.append((ChironTAC.ConditionCommand(branchvar), newtgt)) - - elif isinstance(stmt, ChironAST.AssertCommand): - assertvar = ChironTAC.Var(f":__assert_{self.assertCount}") - self.assertCount += 1 - self.parseExpresssion(stmt.cond, assertvar) - self.line += 1 - self.tac.append((ChironTAC.AssertCommand(assertvar), 1)) - - elif isinstance(stmt, ChironAST.MoveCommand): - movevar = None - if isinstance(stmt.expr, ChironAST.Num): - movevar = ChironTAC.Num(stmt.expr.val) - elif isinstance(stmt.expr, ChironAST.Var): - movevar = ChironTAC.Var(stmt.expr.varname) - else: - movevar = ChironTAC.Var(f":__move_{self.moveCount}") - self.moveCount += 1 - self.parseExpresssion(stmt.expr, movevar) - self.line += 1 - self.tac.append((ChironTAC.MoveCommand(stmt.direction, movevar), 1)) - if (stmt.direction == "forward" or stmt.direction == "backward"): - self.line += 6 - self.tac.append((ChironTAC.CosCommand(ChironTAC.Var(":__cos_theta"), ChironTAC.Var(":__turtle_theta")), 1)) - self.tac.append((ChironTAC.SinCommand(ChironTAC.Var(":__sin_theta"), ChironTAC.Var(":__turtle_theta")), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__delta_x"), movevar, ChironTAC.Var(":__cos_theta"), "*"), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__delta_y"), movevar, ChironTAC.Var(":__sin_theta"), "*"), 1)) - if (stmt.direction == "forward"): - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__delta_x"), "+"), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__delta_y"), "+"), 1)) - elif (stmt.direction == "backward"): - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__delta_x"), "-"), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__delta_y"), "-"), 1)) - elif (stmt.direction == "left"): - self.line += 1 - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta"), ChironTAC.Var(":__turtle_theta"), movevar, "-"), 1)) - elif (stmt.direction == "right"): - self.line += 1 - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta"), ChironTAC.Var(":__turtle_theta"), movevar, "+"), 1)) - else: - raise NotImplementedError("Unknown move direction: %s, %s." % (type(stmt), stmt)) - - elif isinstance(stmt, ChironAST.PenCommand): - self.line += 2 - self.tac.append((ChironTAC.PenCommand(stmt.status), 1)) - if (stmt.status == "penup"): - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(1), ChironTAC.Num(0), "+"), 1)) - elif (stmt.status == "pendown"): - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) - else: - raise NotImplementedError("Unknown pen status: %s, %s." % (type(stmt), stmt)) - - elif isinstance(stmt, ChironAST.GotoCommand): - xvar = None - yvar = None - if isinstance(stmt.xcor, ChironAST.Num): - xvar = ChironTAC.Num(stmt.xcor.val) - elif isinstance(stmt.xcor, ChironAST.Var): - xvar = ChironTAC.Var(stmt.xcor.varname) - else: - xvar = ChironTAC.Var(f":__x_{self.gotoCount}") - self.gotoCount += 1 - self.parseExpresssion(stmt.xcor, xvar) - if isinstance(stmt.ycor, ChironAST.Num): - yvar = ChironTAC.Num(stmt.ycor.val) - elif isinstance(stmt.ycor, ChironAST.Var): - yvar = ChironTAC.Var(stmt.ycor.varname) - else: - yvar = ChironTAC.Var(f":__y_{self.gotoCount}") - self.gotoCount += 1 - self.parseExpresssion(stmt.ycor, yvar) - self.line += 3 - self.tac.append((ChironTAC.GotoCommand(xvar, yvar), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), xvar, ChironTAC.Num(0), "+"), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), yvar, ChironTAC.Num(0), "+"), 1)) - - elif isinstance(stmt, ChironAST.NoOpCommand): - self.line += 1 - self.tac.append((ChironTAC.NoOpCommand(), 1)) - - elif isinstance(stmt, ChironAST.PauseCommand): - self.line += 1 - self.tac.append((ChironTAC.PauseCommand(), 1)) - - else: - raise NotImplementedError( - "Unknown instruction: %s, %s." % (type(stmt), stmt) - ) - - self.ast_to_tac_line[line_number] = self.line - - for i in range(len(self.tac)): - stmt, tgt = self.tac[i] - if isinstance(stmt, ChironTAC.ConditionCommand): - newtgt = self.ast_to_tac_line[tgt] - i - self.tac[i] = (stmt, newtgt) - - self.handleMoveVariables() - self.handleFreeVariables() - - def handleFreeVariables(self): - self.freeVars = self.getFreeVariables() - - for var in self.freeVars: - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(var), ChironTAC.Unused(), ChironTAC.Unused(), ""), 1)) - - def handleMoveVariables(self): - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) # 0->down 1->up - - def getFreeVariables(self): - """ - Returns free variables in TAC. - """ - if len(self.freeVars) > 0: - return self.freeVars - - boundVars = set() - for (stmt, _), _ in zip(self.tac, range(len(self.tac))): - if isinstance(stmt, ChironTAC.AssignmentCommand): - if isinstance(stmt.rvar1, ChironTAC.Var) and stmt.rvar1.__str__() not in boundVars: - self.freeVars.add(stmt.rvar1.__str__()) - if isinstance(stmt.rvar2, ChironTAC.Var) and stmt.rvar2.__str__() not in boundVars: - self.freeVars.add(stmt.rvar2.__str__()) - boundVars.add(stmt.lvar.__str__()) - elif isinstance(stmt, ChironTAC.ConditionCommand): - if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: - self.freeVars.add(stmt.cond.__str__()) - elif isinstance(stmt, ChironTAC.AssertCommand): - if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: - self.freeVars.add(stmt.cond.__str__()) - elif isinstance(stmt, ChironTAC.MoveCommand): - if isinstance(stmt.var, ChironTAC.Var) and stmt.var.__str__() not in boundVars: - self.freeVars.add(stmt.var.__str__()) - elif isinstance(stmt, ChironTAC.GotoCommand): - if isinstance(stmt.xcor, ChironTAC.Var) and stmt.xcor.__str__() not in boundVars: - self.freeVars.add(stmt.xcor.__str__()) - if isinstance(stmt.ycor, ChironTAC.Var) and stmt.ycor.__str__() not in boundVars: - self.freeVars.add(stmt.ycor.__str__()) - - return self.freeVars - - - def printTAC(self): - for (stmt, tgt), line in zip(self.tac, range(len(self.tac))): - print(f"[L{line}]".rjust(5), stmt, f"[{tgt}]") + print(f"[L{idx}]".rjust(5), item[0], f"[{item[1]}]") \ No newline at end of file diff --git a/ChironCore/turtparse/tlang.g4 b/ChironCore/turtparse/tlang.g4 index 34adbfc..a45d389 100644 --- a/ChironCore/turtparse/tlang.g4 +++ b/ChironCore/turtparse/tlang.g4 @@ -46,12 +46,14 @@ expression : unaryArithOp expression #unaryExpr | expression multiplicative expression #mulExpr | expression additive expression #addExpr + | expression modulo expression #modExpr | value #valueExpr | '(' expression ')' #parenExpr ; multiplicative : MUL | DIV; additive : PLUS | MINUS; +modulo : MOD; unaryArithOp : MINUS ; @@ -59,6 +61,7 @@ PLUS : '+' ; MINUS : '-' ; MUL : '*' ; DIV : '/' ; +MOD : '%' ; // TODO : diff --git a/ChironCore/turtparse/tlang.interp b/ChironCore/turtparse/tlang.interp index 9b42a13..c709152 100644 --- a/ChironCore/turtparse/tlang.interp +++ b/ChironCore/turtparse/tlang.interp @@ -22,6 +22,7 @@ null '-' '*' '/' +'%' 'pendown?' '<' '>' @@ -62,6 +63,7 @@ PLUS MINUS MUL DIV +MOD PENCOND LT GT @@ -97,6 +99,7 @@ assertionCommand expression multiplicative additive +modulo unaryArithOp condition binCondOp @@ -105,4 +108,4 @@ value atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 39, 181, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 53, 10, 3, 12, 3, 14, 3, 56, 11, 3, 3, 4, 6, 4, 59, 10, 4, 13, 4, 14, 4, 60, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 71, 10, 5, 3, 6, 3, 6, 5, 6, 75, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 5, 17, 131, 10, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 141, 10, 17, 12, 17, 14, 17, 144, 11, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 164, 10, 21, 3, 21, 3, 21, 3, 21, 3, 21, 7, 21, 170, 10, 21, 12, 21, 14, 21, 173, 11, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 2, 4, 32, 40, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 2, 9, 3, 2, 13, 16, 3, 2, 17, 18, 3, 2, 23, 24, 3, 2, 21, 22, 3, 2, 26, 31, 3, 2, 32, 33, 3, 2, 35, 36, 2, 175, 2, 48, 3, 2, 2, 2, 4, 54, 3, 2, 2, 2, 6, 58, 3, 2, 2, 2, 8, 70, 3, 2, 2, 2, 10, 74, 3, 2, 2, 2, 12, 76, 3, 2, 2, 2, 14, 82, 3, 2, 2, 2, 16, 92, 3, 2, 2, 2, 18, 98, 3, 2, 2, 2, 20, 105, 3, 2, 2, 2, 22, 109, 3, 2, 2, 2, 24, 112, 3, 2, 2, 2, 26, 114, 3, 2, 2, 2, 28, 116, 3, 2, 2, 2, 30, 118, 3, 2, 2, 2, 32, 130, 3, 2, 2, 2, 34, 145, 3, 2, 2, 2, 36, 147, 3, 2, 2, 2, 38, 149, 3, 2, 2, 2, 40, 163, 3, 2, 2, 2, 42, 174, 3, 2, 2, 2, 44, 176, 3, 2, 2, 2, 46, 178, 3, 2, 2, 2, 48, 49, 5, 4, 3, 2, 49, 50, 7, 2, 2, 3, 50, 3, 3, 2, 2, 2, 51, 53, 5, 8, 5, 2, 52, 51, 3, 2, 2, 2, 53, 56, 3, 2, 2, 2, 54, 52, 3, 2, 2, 2, 54, 55, 3, 2, 2, 2, 55, 5, 3, 2, 2, 2, 56, 54, 3, 2, 2, 2, 57, 59, 5, 8, 5, 2, 58, 57, 3, 2, 2, 2, 59, 60, 3, 2, 2, 2, 60, 58, 3, 2, 2, 2, 60, 61, 3, 2, 2, 2, 61, 7, 3, 2, 2, 2, 62, 71, 5, 20, 11, 2, 63, 71, 5, 10, 6, 2, 64, 71, 5, 16, 9, 2, 65, 71, 5, 22, 12, 2, 66, 71, 5, 26, 14, 2, 67, 71, 5, 18, 10, 2, 68, 71, 5, 28, 15, 2, 69, 71, 5, 30, 16, 2, 70, 62, 3, 2, 2, 2, 70, 63, 3, 2, 2, 2, 70, 64, 3, 2, 2, 2, 70, 65, 3, 2, 2, 2, 70, 66, 3, 2, 2, 2, 70, 67, 3, 2, 2, 2, 70, 68, 3, 2, 2, 2, 70, 69, 3, 2, 2, 2, 71, 9, 3, 2, 2, 2, 72, 75, 5, 12, 7, 2, 73, 75, 5, 14, 8, 2, 74, 72, 3, 2, 2, 2, 74, 73, 3, 2, 2, 2, 75, 11, 3, 2, 2, 2, 76, 77, 7, 3, 2, 2, 77, 78, 5, 40, 21, 2, 78, 79, 7, 4, 2, 2, 79, 80, 5, 6, 4, 2, 80, 81, 7, 5, 2, 2, 81, 13, 3, 2, 2, 2, 82, 83, 7, 3, 2, 2, 83, 84, 5, 40, 21, 2, 84, 85, 7, 4, 2, 2, 85, 86, 5, 6, 4, 2, 86, 87, 7, 5, 2, 2, 87, 88, 7, 6, 2, 2, 88, 89, 7, 4, 2, 2, 89, 90, 5, 6, 4, 2, 90, 91, 7, 5, 2, 2, 91, 15, 3, 2, 2, 2, 92, 93, 7, 7, 2, 2, 93, 94, 5, 46, 24, 2, 94, 95, 7, 4, 2, 2, 95, 96, 5, 6, 4, 2, 96, 97, 7, 5, 2, 2, 97, 17, 3, 2, 2, 2, 98, 99, 7, 8, 2, 2, 99, 100, 7, 9, 2, 2, 100, 101, 5, 32, 17, 2, 101, 102, 7, 10, 2, 2, 102, 103, 5, 32, 17, 2, 103, 104, 7, 11, 2, 2, 104, 19, 3, 2, 2, 2, 105, 106, 7, 36, 2, 2, 106, 107, 7, 12, 2, 2, 107, 108, 5, 32, 17, 2, 108, 21, 3, 2, 2, 2, 109, 110, 5, 24, 13, 2, 110, 111, 5, 32, 17, 2, 111, 23, 3, 2, 2, 2, 112, 113, 9, 2, 2, 2, 113, 25, 3, 2, 2, 2, 114, 115, 9, 3, 2, 2, 115, 27, 3, 2, 2, 2, 116, 117, 7, 19, 2, 2, 117, 29, 3, 2, 2, 2, 118, 119, 7, 20, 2, 2, 119, 120, 5, 40, 21, 2, 120, 31, 3, 2, 2, 2, 121, 122, 8, 17, 1, 2, 122, 123, 5, 38, 20, 2, 123, 124, 5, 32, 17, 7, 124, 131, 3, 2, 2, 2, 125, 131, 5, 46, 24, 2, 126, 127, 7, 9, 2, 2, 127, 128, 5, 32, 17, 2, 128, 129, 7, 11, 2, 2, 129, 131, 3, 2, 2, 2, 130, 121, 3, 2, 2, 2, 130, 125, 3, 2, 2, 2, 130, 126, 3, 2, 2, 2, 131, 142, 3, 2, 2, 2, 132, 133, 12, 6, 2, 2, 133, 134, 5, 34, 18, 2, 134, 135, 5, 32, 17, 7, 135, 141, 3, 2, 2, 2, 136, 137, 12, 5, 2, 2, 137, 138, 5, 36, 19, 2, 138, 139, 5, 32, 17, 6, 139, 141, 3, 2, 2, 2, 140, 132, 3, 2, 2, 2, 140, 136, 3, 2, 2, 2, 141, 144, 3, 2, 2, 2, 142, 140, 3, 2, 2, 2, 142, 143, 3, 2, 2, 2, 143, 33, 3, 2, 2, 2, 144, 142, 3, 2, 2, 2, 145, 146, 9, 4, 2, 2, 146, 35, 3, 2, 2, 2, 147, 148, 9, 5, 2, 2, 148, 37, 3, 2, 2, 2, 149, 150, 7, 22, 2, 2, 150, 39, 3, 2, 2, 2, 151, 152, 8, 21, 1, 2, 152, 153, 7, 34, 2, 2, 153, 164, 5, 40, 21, 7, 154, 155, 5, 32, 17, 2, 155, 156, 5, 42, 22, 2, 156, 157, 5, 32, 17, 2, 157, 164, 3, 2, 2, 2, 158, 164, 7, 25, 2, 2, 159, 160, 7, 9, 2, 2, 160, 161, 5, 40, 21, 2, 161, 162, 7, 11, 2, 2, 162, 164, 3, 2, 2, 2, 163, 151, 3, 2, 2, 2, 163, 154, 3, 2, 2, 2, 163, 158, 3, 2, 2, 2, 163, 159, 3, 2, 2, 2, 164, 171, 3, 2, 2, 2, 165, 166, 12, 5, 2, 2, 166, 167, 5, 44, 23, 2, 167, 168, 5, 40, 21, 6, 168, 170, 3, 2, 2, 2, 169, 165, 3, 2, 2, 2, 170, 173, 3, 2, 2, 2, 171, 169, 3, 2, 2, 2, 171, 172, 3, 2, 2, 2, 172, 41, 3, 2, 2, 2, 173, 171, 3, 2, 2, 2, 174, 175, 9, 6, 2, 2, 175, 43, 3, 2, 2, 2, 176, 177, 9, 7, 2, 2, 177, 45, 3, 2, 2, 2, 178, 179, 9, 8, 2, 2, 179, 47, 3, 2, 2, 2, 11, 54, 60, 70, 74, 130, 140, 142, 163, 171] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 40, 189, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 55, 10, 3, 12, 3, 14, 3, 58, 11, 3, 3, 4, 6, 4, 61, 10, 4, 13, 4, 14, 4, 62, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 73, 10, 5, 3, 6, 3, 6, 5, 6, 77, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 5, 17, 133, 10, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 147, 10, 17, 12, 17, 14, 17, 150, 11, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 172, 10, 22, 3, 22, 3, 22, 3, 22, 3, 22, 7, 22, 178, 10, 22, 12, 22, 14, 22, 181, 11, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 2, 4, 32, 42, 26, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 2, 9, 3, 2, 13, 16, 3, 2, 17, 18, 3, 2, 23, 24, 3, 2, 21, 22, 3, 2, 27, 32, 3, 2, 33, 34, 3, 2, 36, 37, 2, 183, 2, 50, 3, 2, 2, 2, 4, 56, 3, 2, 2, 2, 6, 60, 3, 2, 2, 2, 8, 72, 3, 2, 2, 2, 10, 76, 3, 2, 2, 2, 12, 78, 3, 2, 2, 2, 14, 84, 3, 2, 2, 2, 16, 94, 3, 2, 2, 2, 18, 100, 3, 2, 2, 2, 20, 107, 3, 2, 2, 2, 22, 111, 3, 2, 2, 2, 24, 114, 3, 2, 2, 2, 26, 116, 3, 2, 2, 2, 28, 118, 3, 2, 2, 2, 30, 120, 3, 2, 2, 2, 32, 132, 3, 2, 2, 2, 34, 151, 3, 2, 2, 2, 36, 153, 3, 2, 2, 2, 38, 155, 3, 2, 2, 2, 40, 157, 3, 2, 2, 2, 42, 171, 3, 2, 2, 2, 44, 182, 3, 2, 2, 2, 46, 184, 3, 2, 2, 2, 48, 186, 3, 2, 2, 2, 50, 51, 5, 4, 3, 2, 51, 52, 7, 2, 2, 3, 52, 3, 3, 2, 2, 2, 53, 55, 5, 8, 5, 2, 54, 53, 3, 2, 2, 2, 55, 58, 3, 2, 2, 2, 56, 54, 3, 2, 2, 2, 56, 57, 3, 2, 2, 2, 57, 5, 3, 2, 2, 2, 58, 56, 3, 2, 2, 2, 59, 61, 5, 8, 5, 2, 60, 59, 3, 2, 2, 2, 61, 62, 3, 2, 2, 2, 62, 60, 3, 2, 2, 2, 62, 63, 3, 2, 2, 2, 63, 7, 3, 2, 2, 2, 64, 73, 5, 20, 11, 2, 65, 73, 5, 10, 6, 2, 66, 73, 5, 16, 9, 2, 67, 73, 5, 22, 12, 2, 68, 73, 5, 26, 14, 2, 69, 73, 5, 18, 10, 2, 70, 73, 5, 28, 15, 2, 71, 73, 5, 30, 16, 2, 72, 64, 3, 2, 2, 2, 72, 65, 3, 2, 2, 2, 72, 66, 3, 2, 2, 2, 72, 67, 3, 2, 2, 2, 72, 68, 3, 2, 2, 2, 72, 69, 3, 2, 2, 2, 72, 70, 3, 2, 2, 2, 72, 71, 3, 2, 2, 2, 73, 9, 3, 2, 2, 2, 74, 77, 5, 12, 7, 2, 75, 77, 5, 14, 8, 2, 76, 74, 3, 2, 2, 2, 76, 75, 3, 2, 2, 2, 77, 11, 3, 2, 2, 2, 78, 79, 7, 3, 2, 2, 79, 80, 5, 42, 22, 2, 80, 81, 7, 4, 2, 2, 81, 82, 5, 6, 4, 2, 82, 83, 7, 5, 2, 2, 83, 13, 3, 2, 2, 2, 84, 85, 7, 3, 2, 2, 85, 86, 5, 42, 22, 2, 86, 87, 7, 4, 2, 2, 87, 88, 5, 6, 4, 2, 88, 89, 7, 5, 2, 2, 89, 90, 7, 6, 2, 2, 90, 91, 7, 4, 2, 2, 91, 92, 5, 6, 4, 2, 92, 93, 7, 5, 2, 2, 93, 15, 3, 2, 2, 2, 94, 95, 7, 7, 2, 2, 95, 96, 5, 48, 25, 2, 96, 97, 7, 4, 2, 2, 97, 98, 5, 6, 4, 2, 98, 99, 7, 5, 2, 2, 99, 17, 3, 2, 2, 2, 100, 101, 7, 8, 2, 2, 101, 102, 7, 9, 2, 2, 102, 103, 5, 32, 17, 2, 103, 104, 7, 10, 2, 2, 104, 105, 5, 32, 17, 2, 105, 106, 7, 11, 2, 2, 106, 19, 3, 2, 2, 2, 107, 108, 7, 37, 2, 2, 108, 109, 7, 12, 2, 2, 109, 110, 5, 32, 17, 2, 110, 21, 3, 2, 2, 2, 111, 112, 5, 24, 13, 2, 112, 113, 5, 32, 17, 2, 113, 23, 3, 2, 2, 2, 114, 115, 9, 2, 2, 2, 115, 25, 3, 2, 2, 2, 116, 117, 9, 3, 2, 2, 117, 27, 3, 2, 2, 2, 118, 119, 7, 19, 2, 2, 119, 29, 3, 2, 2, 2, 120, 121, 7, 20, 2, 2, 121, 122, 5, 42, 22, 2, 122, 31, 3, 2, 2, 2, 123, 124, 8, 17, 1, 2, 124, 125, 5, 40, 21, 2, 125, 126, 5, 32, 17, 8, 126, 133, 3, 2, 2, 2, 127, 133, 5, 48, 25, 2, 128, 129, 7, 9, 2, 2, 129, 130, 5, 32, 17, 2, 130, 131, 7, 11, 2, 2, 131, 133, 3, 2, 2, 2, 132, 123, 3, 2, 2, 2, 132, 127, 3, 2, 2, 2, 132, 128, 3, 2, 2, 2, 133, 148, 3, 2, 2, 2, 134, 135, 12, 7, 2, 2, 135, 136, 5, 34, 18, 2, 136, 137, 5, 32, 17, 8, 137, 147, 3, 2, 2, 2, 138, 139, 12, 6, 2, 2, 139, 140, 5, 36, 19, 2, 140, 141, 5, 32, 17, 7, 141, 147, 3, 2, 2, 2, 142, 143, 12, 5, 2, 2, 143, 144, 5, 38, 20, 2, 144, 145, 5, 32, 17, 6, 145, 147, 3, 2, 2, 2, 146, 134, 3, 2, 2, 2, 146, 138, 3, 2, 2, 2, 146, 142, 3, 2, 2, 2, 147, 150, 3, 2, 2, 2, 148, 146, 3, 2, 2, 2, 148, 149, 3, 2, 2, 2, 149, 33, 3, 2, 2, 2, 150, 148, 3, 2, 2, 2, 151, 152, 9, 4, 2, 2, 152, 35, 3, 2, 2, 2, 153, 154, 9, 5, 2, 2, 154, 37, 3, 2, 2, 2, 155, 156, 7, 25, 2, 2, 156, 39, 3, 2, 2, 2, 157, 158, 7, 22, 2, 2, 158, 41, 3, 2, 2, 2, 159, 160, 8, 22, 1, 2, 160, 161, 7, 35, 2, 2, 161, 172, 5, 42, 22, 7, 162, 163, 5, 32, 17, 2, 163, 164, 5, 44, 23, 2, 164, 165, 5, 32, 17, 2, 165, 172, 3, 2, 2, 2, 166, 172, 7, 26, 2, 2, 167, 168, 7, 9, 2, 2, 168, 169, 5, 42, 22, 2, 169, 170, 7, 11, 2, 2, 170, 172, 3, 2, 2, 2, 171, 159, 3, 2, 2, 2, 171, 162, 3, 2, 2, 2, 171, 166, 3, 2, 2, 2, 171, 167, 3, 2, 2, 2, 172, 179, 3, 2, 2, 2, 173, 174, 12, 5, 2, 2, 174, 175, 5, 46, 24, 2, 175, 176, 5, 42, 22, 6, 176, 178, 3, 2, 2, 2, 177, 173, 3, 2, 2, 2, 178, 181, 3, 2, 2, 2, 179, 177, 3, 2, 2, 2, 179, 180, 3, 2, 2, 2, 180, 43, 3, 2, 2, 2, 181, 179, 3, 2, 2, 2, 182, 183, 9, 6, 2, 2, 183, 45, 3, 2, 2, 2, 184, 185, 9, 7, 2, 2, 185, 47, 3, 2, 2, 2, 186, 187, 9, 8, 2, 2, 187, 49, 3, 2, 2, 2, 11, 56, 62, 72, 76, 132, 146, 148, 171, 179] \ No newline at end of file diff --git a/ChironCore/turtparse/tlang.tokens b/ChironCore/turtparse/tlang.tokens index b0a2b1d..2c2f507 100644 --- a/ChironCore/turtparse/tlang.tokens +++ b/ChironCore/turtparse/tlang.tokens @@ -20,21 +20,22 @@ PLUS=19 MINUS=20 MUL=21 DIV=22 -PENCOND=23 -LT=24 -GT=25 -EQ=26 -NEQ=27 -LTE=28 -GTE=29 -AND=30 -OR=31 -NOT=32 -NUM=33 -VAR=34 -NAME=35 -Whitespace=36 -Comment=37 +MOD=23 +PENCOND=24 +LT=25 +GT=26 +EQ=27 +NEQ=28 +LTE=29 +GTE=30 +AND=31 +OR=32 +NOT=33 +NUM=34 +VAR=35 +NAME=36 +Whitespace=37 +Comment=38 'if'=1 '['=2 ']'=3 @@ -57,13 +58,14 @@ Comment=37 '-'=20 '*'=21 '/'=22 -'pendown?'=23 -'<'=24 -'>'=25 -'=='=26 -'!='=27 -'<='=28 -'>='=29 -'&&'=30 -'||'=31 -'!'=32 +'%'=23 +'pendown?'=24 +'<'=25 +'>'=26 +'=='=27 +'!='=28 +'<='=29 +'>='=30 +'&&'=31 +'||'=32 +'!'=33 diff --git a/ChironCore/turtparse/tlangLexer.interp b/ChironCore/turtparse/tlangLexer.interp index 7d6f824..964b7b8 100644 --- a/ChironCore/turtparse/tlangLexer.interp +++ b/ChironCore/turtparse/tlangLexer.interp @@ -22,6 +22,7 @@ null '-' '*' '/' +'%' 'pendown?' '<' '>' @@ -62,6 +63,7 @@ PLUS MINUS MUL DIV +MOD PENCOND LT GT @@ -101,6 +103,7 @@ PLUS MINUS MUL DIV +MOD PENCOND LT GT @@ -125,4 +128,4 @@ mode names: DEFAULT_MODE atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 39, 241, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 6, 34, 207, 10, 34, 13, 34, 14, 34, 208, 3, 35, 3, 35, 3, 35, 7, 35, 214, 10, 35, 12, 35, 14, 35, 217, 11, 35, 3, 36, 6, 36, 220, 10, 36, 13, 36, 14, 36, 221, 3, 37, 6, 37, 225, 10, 37, 13, 37, 14, 37, 226, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38, 7, 38, 235, 10, 38, 12, 38, 14, 38, 238, 11, 38, 3, 38, 3, 38, 2, 2, 39, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 3, 2, 8, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 245, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 3, 77, 3, 2, 2, 2, 5, 80, 3, 2, 2, 2, 7, 82, 3, 2, 2, 2, 9, 84, 3, 2, 2, 2, 11, 89, 3, 2, 2, 2, 13, 96, 3, 2, 2, 2, 15, 101, 3, 2, 2, 2, 17, 103, 3, 2, 2, 2, 19, 105, 3, 2, 2, 2, 21, 107, 3, 2, 2, 2, 23, 109, 3, 2, 2, 2, 25, 117, 3, 2, 2, 2, 27, 126, 3, 2, 2, 2, 29, 131, 3, 2, 2, 2, 31, 137, 3, 2, 2, 2, 33, 143, 3, 2, 2, 2, 35, 151, 3, 2, 2, 2, 37, 157, 3, 2, 2, 2, 39, 164, 3, 2, 2, 2, 41, 166, 3, 2, 2, 2, 43, 168, 3, 2, 2, 2, 45, 170, 3, 2, 2, 2, 47, 172, 3, 2, 2, 2, 49, 181, 3, 2, 2, 2, 51, 183, 3, 2, 2, 2, 53, 185, 3, 2, 2, 2, 55, 188, 3, 2, 2, 2, 57, 191, 3, 2, 2, 2, 59, 194, 3, 2, 2, 2, 61, 197, 3, 2, 2, 2, 63, 200, 3, 2, 2, 2, 65, 203, 3, 2, 2, 2, 67, 206, 3, 2, 2, 2, 69, 210, 3, 2, 2, 2, 71, 219, 3, 2, 2, 2, 73, 224, 3, 2, 2, 2, 75, 230, 3, 2, 2, 2, 77, 78, 7, 107, 2, 2, 78, 79, 7, 104, 2, 2, 79, 4, 3, 2, 2, 2, 80, 81, 7, 93, 2, 2, 81, 6, 3, 2, 2, 2, 82, 83, 7, 95, 2, 2, 83, 8, 3, 2, 2, 2, 84, 85, 7, 103, 2, 2, 85, 86, 7, 110, 2, 2, 86, 87, 7, 117, 2, 2, 87, 88, 7, 103, 2, 2, 88, 10, 3, 2, 2, 2, 89, 90, 7, 116, 2, 2, 90, 91, 7, 103, 2, 2, 91, 92, 7, 114, 2, 2, 92, 93, 7, 103, 2, 2, 93, 94, 7, 99, 2, 2, 94, 95, 7, 118, 2, 2, 95, 12, 3, 2, 2, 2, 96, 97, 7, 105, 2, 2, 97, 98, 7, 113, 2, 2, 98, 99, 7, 118, 2, 2, 99, 100, 7, 113, 2, 2, 100, 14, 3, 2, 2, 2, 101, 102, 7, 42, 2, 2, 102, 16, 3, 2, 2, 2, 103, 104, 7, 46, 2, 2, 104, 18, 3, 2, 2, 2, 105, 106, 7, 43, 2, 2, 106, 20, 3, 2, 2, 2, 107, 108, 7, 63, 2, 2, 108, 22, 3, 2, 2, 2, 109, 110, 7, 104, 2, 2, 110, 111, 7, 113, 2, 2, 111, 112, 7, 116, 2, 2, 112, 113, 7, 121, 2, 2, 113, 114, 7, 99, 2, 2, 114, 115, 7, 116, 2, 2, 115, 116, 7, 102, 2, 2, 116, 24, 3, 2, 2, 2, 117, 118, 7, 100, 2, 2, 118, 119, 7, 99, 2, 2, 119, 120, 7, 101, 2, 2, 120, 121, 7, 109, 2, 2, 121, 122, 7, 121, 2, 2, 122, 123, 7, 99, 2, 2, 123, 124, 7, 116, 2, 2, 124, 125, 7, 102, 2, 2, 125, 26, 3, 2, 2, 2, 126, 127, 7, 110, 2, 2, 127, 128, 7, 103, 2, 2, 128, 129, 7, 104, 2, 2, 129, 130, 7, 118, 2, 2, 130, 28, 3, 2, 2, 2, 131, 132, 7, 116, 2, 2, 132, 133, 7, 107, 2, 2, 133, 134, 7, 105, 2, 2, 134, 135, 7, 106, 2, 2, 135, 136, 7, 118, 2, 2, 136, 30, 3, 2, 2, 2, 137, 138, 7, 114, 2, 2, 138, 139, 7, 103, 2, 2, 139, 140, 7, 112, 2, 2, 140, 141, 7, 119, 2, 2, 141, 142, 7, 114, 2, 2, 142, 32, 3, 2, 2, 2, 143, 144, 7, 114, 2, 2, 144, 145, 7, 103, 2, 2, 145, 146, 7, 112, 2, 2, 146, 147, 7, 102, 2, 2, 147, 148, 7, 113, 2, 2, 148, 149, 7, 121, 2, 2, 149, 150, 7, 112, 2, 2, 150, 34, 3, 2, 2, 2, 151, 152, 7, 114, 2, 2, 152, 153, 7, 99, 2, 2, 153, 154, 7, 119, 2, 2, 154, 155, 7, 117, 2, 2, 155, 156, 7, 103, 2, 2, 156, 36, 3, 2, 2, 2, 157, 158, 7, 99, 2, 2, 158, 159, 7, 117, 2, 2, 159, 160, 7, 117, 2, 2, 160, 161, 7, 103, 2, 2, 161, 162, 7, 116, 2, 2, 162, 163, 7, 118, 2, 2, 163, 38, 3, 2, 2, 2, 164, 165, 7, 45, 2, 2, 165, 40, 3, 2, 2, 2, 166, 167, 7, 47, 2, 2, 167, 42, 3, 2, 2, 2, 168, 169, 7, 44, 2, 2, 169, 44, 3, 2, 2, 2, 170, 171, 7, 49, 2, 2, 171, 46, 3, 2, 2, 2, 172, 173, 7, 114, 2, 2, 173, 174, 7, 103, 2, 2, 174, 175, 7, 112, 2, 2, 175, 176, 7, 102, 2, 2, 176, 177, 7, 113, 2, 2, 177, 178, 7, 121, 2, 2, 178, 179, 7, 112, 2, 2, 179, 180, 7, 65, 2, 2, 180, 48, 3, 2, 2, 2, 181, 182, 7, 62, 2, 2, 182, 50, 3, 2, 2, 2, 183, 184, 7, 64, 2, 2, 184, 52, 3, 2, 2, 2, 185, 186, 7, 63, 2, 2, 186, 187, 7, 63, 2, 2, 187, 54, 3, 2, 2, 2, 188, 189, 7, 35, 2, 2, 189, 190, 7, 63, 2, 2, 190, 56, 3, 2, 2, 2, 191, 192, 7, 62, 2, 2, 192, 193, 7, 63, 2, 2, 193, 58, 3, 2, 2, 2, 194, 195, 7, 64, 2, 2, 195, 196, 7, 63, 2, 2, 196, 60, 3, 2, 2, 2, 197, 198, 7, 40, 2, 2, 198, 199, 7, 40, 2, 2, 199, 62, 3, 2, 2, 2, 200, 201, 7, 126, 2, 2, 201, 202, 7, 126, 2, 2, 202, 64, 3, 2, 2, 2, 203, 204, 7, 35, 2, 2, 204, 66, 3, 2, 2, 2, 205, 207, 9, 2, 2, 2, 206, 205, 3, 2, 2, 2, 207, 208, 3, 2, 2, 2, 208, 206, 3, 2, 2, 2, 208, 209, 3, 2, 2, 2, 209, 68, 3, 2, 2, 2, 210, 211, 7, 60, 2, 2, 211, 215, 9, 3, 2, 2, 212, 214, 9, 4, 2, 2, 213, 212, 3, 2, 2, 2, 214, 217, 3, 2, 2, 2, 215, 213, 3, 2, 2, 2, 215, 216, 3, 2, 2, 2, 216, 70, 3, 2, 2, 2, 217, 215, 3, 2, 2, 2, 218, 220, 9, 5, 2, 2, 219, 218, 3, 2, 2, 2, 220, 221, 3, 2, 2, 2, 221, 219, 3, 2, 2, 2, 221, 222, 3, 2, 2, 2, 222, 72, 3, 2, 2, 2, 223, 225, 9, 6, 2, 2, 224, 223, 3, 2, 2, 2, 225, 226, 3, 2, 2, 2, 226, 224, 3, 2, 2, 2, 226, 227, 3, 2, 2, 2, 227, 228, 3, 2, 2, 2, 228, 229, 8, 37, 2, 2, 229, 74, 3, 2, 2, 2, 230, 231, 7, 49, 2, 2, 231, 232, 7, 49, 2, 2, 232, 236, 3, 2, 2, 2, 233, 235, 10, 7, 2, 2, 234, 233, 3, 2, 2, 2, 235, 238, 3, 2, 2, 2, 236, 234, 3, 2, 2, 2, 236, 237, 3, 2, 2, 2, 237, 239, 3, 2, 2, 2, 238, 236, 3, 2, 2, 2, 239, 240, 8, 38, 2, 2, 240, 76, 3, 2, 2, 2, 8, 2, 208, 215, 221, 226, 236, 3, 8, 2, 2] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 40, 245, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 6, 35, 211, 10, 35, 13, 35, 14, 35, 212, 3, 36, 3, 36, 3, 36, 7, 36, 218, 10, 36, 12, 36, 14, 36, 221, 11, 36, 3, 37, 6, 37, 224, 10, 37, 13, 37, 14, 37, 225, 3, 38, 6, 38, 229, 10, 38, 13, 38, 14, 38, 230, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 7, 39, 239, 10, 39, 12, 39, 14, 39, 242, 11, 39, 3, 39, 3, 39, 2, 2, 40, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 3, 2, 8, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 249, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 3, 79, 3, 2, 2, 2, 5, 82, 3, 2, 2, 2, 7, 84, 3, 2, 2, 2, 9, 86, 3, 2, 2, 2, 11, 91, 3, 2, 2, 2, 13, 98, 3, 2, 2, 2, 15, 103, 3, 2, 2, 2, 17, 105, 3, 2, 2, 2, 19, 107, 3, 2, 2, 2, 21, 109, 3, 2, 2, 2, 23, 111, 3, 2, 2, 2, 25, 119, 3, 2, 2, 2, 27, 128, 3, 2, 2, 2, 29, 133, 3, 2, 2, 2, 31, 139, 3, 2, 2, 2, 33, 145, 3, 2, 2, 2, 35, 153, 3, 2, 2, 2, 37, 159, 3, 2, 2, 2, 39, 166, 3, 2, 2, 2, 41, 168, 3, 2, 2, 2, 43, 170, 3, 2, 2, 2, 45, 172, 3, 2, 2, 2, 47, 174, 3, 2, 2, 2, 49, 176, 3, 2, 2, 2, 51, 185, 3, 2, 2, 2, 53, 187, 3, 2, 2, 2, 55, 189, 3, 2, 2, 2, 57, 192, 3, 2, 2, 2, 59, 195, 3, 2, 2, 2, 61, 198, 3, 2, 2, 2, 63, 201, 3, 2, 2, 2, 65, 204, 3, 2, 2, 2, 67, 207, 3, 2, 2, 2, 69, 210, 3, 2, 2, 2, 71, 214, 3, 2, 2, 2, 73, 223, 3, 2, 2, 2, 75, 228, 3, 2, 2, 2, 77, 234, 3, 2, 2, 2, 79, 80, 7, 107, 2, 2, 80, 81, 7, 104, 2, 2, 81, 4, 3, 2, 2, 2, 82, 83, 7, 93, 2, 2, 83, 6, 3, 2, 2, 2, 84, 85, 7, 95, 2, 2, 85, 8, 3, 2, 2, 2, 86, 87, 7, 103, 2, 2, 87, 88, 7, 110, 2, 2, 88, 89, 7, 117, 2, 2, 89, 90, 7, 103, 2, 2, 90, 10, 3, 2, 2, 2, 91, 92, 7, 116, 2, 2, 92, 93, 7, 103, 2, 2, 93, 94, 7, 114, 2, 2, 94, 95, 7, 103, 2, 2, 95, 96, 7, 99, 2, 2, 96, 97, 7, 118, 2, 2, 97, 12, 3, 2, 2, 2, 98, 99, 7, 105, 2, 2, 99, 100, 7, 113, 2, 2, 100, 101, 7, 118, 2, 2, 101, 102, 7, 113, 2, 2, 102, 14, 3, 2, 2, 2, 103, 104, 7, 42, 2, 2, 104, 16, 3, 2, 2, 2, 105, 106, 7, 46, 2, 2, 106, 18, 3, 2, 2, 2, 107, 108, 7, 43, 2, 2, 108, 20, 3, 2, 2, 2, 109, 110, 7, 63, 2, 2, 110, 22, 3, 2, 2, 2, 111, 112, 7, 104, 2, 2, 112, 113, 7, 113, 2, 2, 113, 114, 7, 116, 2, 2, 114, 115, 7, 121, 2, 2, 115, 116, 7, 99, 2, 2, 116, 117, 7, 116, 2, 2, 117, 118, 7, 102, 2, 2, 118, 24, 3, 2, 2, 2, 119, 120, 7, 100, 2, 2, 120, 121, 7, 99, 2, 2, 121, 122, 7, 101, 2, 2, 122, 123, 7, 109, 2, 2, 123, 124, 7, 121, 2, 2, 124, 125, 7, 99, 2, 2, 125, 126, 7, 116, 2, 2, 126, 127, 7, 102, 2, 2, 127, 26, 3, 2, 2, 2, 128, 129, 7, 110, 2, 2, 129, 130, 7, 103, 2, 2, 130, 131, 7, 104, 2, 2, 131, 132, 7, 118, 2, 2, 132, 28, 3, 2, 2, 2, 133, 134, 7, 116, 2, 2, 134, 135, 7, 107, 2, 2, 135, 136, 7, 105, 2, 2, 136, 137, 7, 106, 2, 2, 137, 138, 7, 118, 2, 2, 138, 30, 3, 2, 2, 2, 139, 140, 7, 114, 2, 2, 140, 141, 7, 103, 2, 2, 141, 142, 7, 112, 2, 2, 142, 143, 7, 119, 2, 2, 143, 144, 7, 114, 2, 2, 144, 32, 3, 2, 2, 2, 145, 146, 7, 114, 2, 2, 146, 147, 7, 103, 2, 2, 147, 148, 7, 112, 2, 2, 148, 149, 7, 102, 2, 2, 149, 150, 7, 113, 2, 2, 150, 151, 7, 121, 2, 2, 151, 152, 7, 112, 2, 2, 152, 34, 3, 2, 2, 2, 153, 154, 7, 114, 2, 2, 154, 155, 7, 99, 2, 2, 155, 156, 7, 119, 2, 2, 156, 157, 7, 117, 2, 2, 157, 158, 7, 103, 2, 2, 158, 36, 3, 2, 2, 2, 159, 160, 7, 99, 2, 2, 160, 161, 7, 117, 2, 2, 161, 162, 7, 117, 2, 2, 162, 163, 7, 103, 2, 2, 163, 164, 7, 116, 2, 2, 164, 165, 7, 118, 2, 2, 165, 38, 3, 2, 2, 2, 166, 167, 7, 45, 2, 2, 167, 40, 3, 2, 2, 2, 168, 169, 7, 47, 2, 2, 169, 42, 3, 2, 2, 2, 170, 171, 7, 44, 2, 2, 171, 44, 3, 2, 2, 2, 172, 173, 7, 49, 2, 2, 173, 46, 3, 2, 2, 2, 174, 175, 7, 39, 2, 2, 175, 48, 3, 2, 2, 2, 176, 177, 7, 114, 2, 2, 177, 178, 7, 103, 2, 2, 178, 179, 7, 112, 2, 2, 179, 180, 7, 102, 2, 2, 180, 181, 7, 113, 2, 2, 181, 182, 7, 121, 2, 2, 182, 183, 7, 112, 2, 2, 183, 184, 7, 65, 2, 2, 184, 50, 3, 2, 2, 2, 185, 186, 7, 62, 2, 2, 186, 52, 3, 2, 2, 2, 187, 188, 7, 64, 2, 2, 188, 54, 3, 2, 2, 2, 189, 190, 7, 63, 2, 2, 190, 191, 7, 63, 2, 2, 191, 56, 3, 2, 2, 2, 192, 193, 7, 35, 2, 2, 193, 194, 7, 63, 2, 2, 194, 58, 3, 2, 2, 2, 195, 196, 7, 62, 2, 2, 196, 197, 7, 63, 2, 2, 197, 60, 3, 2, 2, 2, 198, 199, 7, 64, 2, 2, 199, 200, 7, 63, 2, 2, 200, 62, 3, 2, 2, 2, 201, 202, 7, 40, 2, 2, 202, 203, 7, 40, 2, 2, 203, 64, 3, 2, 2, 2, 204, 205, 7, 126, 2, 2, 205, 206, 7, 126, 2, 2, 206, 66, 3, 2, 2, 2, 207, 208, 7, 35, 2, 2, 208, 68, 3, 2, 2, 2, 209, 211, 9, 2, 2, 2, 210, 209, 3, 2, 2, 2, 211, 212, 3, 2, 2, 2, 212, 210, 3, 2, 2, 2, 212, 213, 3, 2, 2, 2, 213, 70, 3, 2, 2, 2, 214, 215, 7, 60, 2, 2, 215, 219, 9, 3, 2, 2, 216, 218, 9, 4, 2, 2, 217, 216, 3, 2, 2, 2, 218, 221, 3, 2, 2, 2, 219, 217, 3, 2, 2, 2, 219, 220, 3, 2, 2, 2, 220, 72, 3, 2, 2, 2, 221, 219, 3, 2, 2, 2, 222, 224, 9, 5, 2, 2, 223, 222, 3, 2, 2, 2, 224, 225, 3, 2, 2, 2, 225, 223, 3, 2, 2, 2, 225, 226, 3, 2, 2, 2, 226, 74, 3, 2, 2, 2, 227, 229, 9, 6, 2, 2, 228, 227, 3, 2, 2, 2, 229, 230, 3, 2, 2, 2, 230, 228, 3, 2, 2, 2, 230, 231, 3, 2, 2, 2, 231, 232, 3, 2, 2, 2, 232, 233, 8, 38, 2, 2, 233, 76, 3, 2, 2, 2, 234, 235, 7, 49, 2, 2, 235, 236, 7, 49, 2, 2, 236, 240, 3, 2, 2, 2, 237, 239, 10, 7, 2, 2, 238, 237, 3, 2, 2, 2, 239, 242, 3, 2, 2, 2, 240, 238, 3, 2, 2, 2, 240, 241, 3, 2, 2, 2, 241, 243, 3, 2, 2, 2, 242, 240, 3, 2, 2, 2, 243, 244, 8, 39, 2, 2, 244, 78, 3, 2, 2, 2, 8, 2, 212, 219, 225, 230, 240, 3, 8, 2, 2] \ No newline at end of file diff --git a/ChironCore/turtparse/tlangLexer.py b/ChironCore/turtparse/tlangLexer.py index 74f2a7a..ecb24d7 100644 --- a/ChironCore/turtparse/tlangLexer.py +++ b/ChironCore/turtparse/tlangLexer.py @@ -8,100 +8,102 @@ def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\'") - buf.write("\u00f1\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2(") + buf.write("\u00f5\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") buf.write("\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r") buf.write("\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23") buf.write("\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30") buf.write("\4\31\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36") buf.write("\t\36\4\37\t\37\4 \t \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%") - buf.write("\4&\t&\3\2\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\5\3\5\3\5") - buf.write("\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\b\3") - buf.write("\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3") - buf.write("\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3") - buf.write("\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20") - buf.write("\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21") - buf.write("\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23") - buf.write("\3\23\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26\3\27\3\27") - buf.write("\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31") - buf.write("\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35") - buf.write("\3\36\3\36\3\36\3\37\3\37\3\37\3 \3 \3 \3!\3!\3\"\6\"") - buf.write("\u00cf\n\"\r\"\16\"\u00d0\3#\3#\3#\7#\u00d6\n#\f#\16#") - buf.write("\u00d9\13#\3$\6$\u00dc\n$\r$\16$\u00dd\3%\6%\u00e1\n%") - buf.write("\r%\16%\u00e2\3%\3%\3&\3&\3&\3&\7&\u00eb\n&\f&\16&\u00ee") - buf.write("\13&\3&\3&\2\2\'\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23") - buf.write("\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25") - buf.write(")\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A") - buf.write("\"C#E$G%I&K\'\3\2\b\3\2\62;\5\2C\\aac|\5\2\62;C\\c|\4") - buf.write("\2C\\c|\5\2\13\f\17\17\"\"\4\2\f\f\17\17\2\u00f5\2\3\3") - buf.write("\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2") - buf.write("\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2") - buf.write("\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2") - buf.write("\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2") - buf.write("\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3") - buf.write("\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2") - buf.write("\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3") - buf.write("\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K") - buf.write("\3\2\2\2\3M\3\2\2\2\5P\3\2\2\2\7R\3\2\2\2\tT\3\2\2\2\13") - buf.write("Y\3\2\2\2\r`\3\2\2\2\17e\3\2\2\2\21g\3\2\2\2\23i\3\2\2") - buf.write("\2\25k\3\2\2\2\27m\3\2\2\2\31u\3\2\2\2\33~\3\2\2\2\35") - buf.write("\u0083\3\2\2\2\37\u0089\3\2\2\2!\u008f\3\2\2\2#\u0097") - buf.write("\3\2\2\2%\u009d\3\2\2\2\'\u00a4\3\2\2\2)\u00a6\3\2\2\2") - buf.write("+\u00a8\3\2\2\2-\u00aa\3\2\2\2/\u00ac\3\2\2\2\61\u00b5") - buf.write("\3\2\2\2\63\u00b7\3\2\2\2\65\u00b9\3\2\2\2\67\u00bc\3") - buf.write("\2\2\29\u00bf\3\2\2\2;\u00c2\3\2\2\2=\u00c5\3\2\2\2?\u00c8") - buf.write("\3\2\2\2A\u00cb\3\2\2\2C\u00ce\3\2\2\2E\u00d2\3\2\2\2") - buf.write("G\u00db\3\2\2\2I\u00e0\3\2\2\2K\u00e6\3\2\2\2MN\7k\2\2") - buf.write("NO\7h\2\2O\4\3\2\2\2PQ\7]\2\2Q\6\3\2\2\2RS\7_\2\2S\b\3") - buf.write("\2\2\2TU\7g\2\2UV\7n\2\2VW\7u\2\2WX\7g\2\2X\n\3\2\2\2") - buf.write("YZ\7t\2\2Z[\7g\2\2[\\\7r\2\2\\]\7g\2\2]^\7c\2\2^_\7v\2") - buf.write("\2_\f\3\2\2\2`a\7i\2\2ab\7q\2\2bc\7v\2\2cd\7q\2\2d\16") - buf.write("\3\2\2\2ef\7*\2\2f\20\3\2\2\2gh\7.\2\2h\22\3\2\2\2ij\7") - buf.write("+\2\2j\24\3\2\2\2kl\7?\2\2l\26\3\2\2\2mn\7h\2\2no\7q\2") - buf.write("\2op\7t\2\2pq\7y\2\2qr\7c\2\2rs\7t\2\2st\7f\2\2t\30\3") - buf.write("\2\2\2uv\7d\2\2vw\7c\2\2wx\7e\2\2xy\7m\2\2yz\7y\2\2z{") - buf.write("\7c\2\2{|\7t\2\2|}\7f\2\2}\32\3\2\2\2~\177\7n\2\2\177") - buf.write("\u0080\7g\2\2\u0080\u0081\7h\2\2\u0081\u0082\7v\2\2\u0082") - buf.write("\34\3\2\2\2\u0083\u0084\7t\2\2\u0084\u0085\7k\2\2\u0085") - buf.write("\u0086\7i\2\2\u0086\u0087\7j\2\2\u0087\u0088\7v\2\2\u0088") - buf.write("\36\3\2\2\2\u0089\u008a\7r\2\2\u008a\u008b\7g\2\2\u008b") - buf.write("\u008c\7p\2\2\u008c\u008d\7w\2\2\u008d\u008e\7r\2\2\u008e") - buf.write(" \3\2\2\2\u008f\u0090\7r\2\2\u0090\u0091\7g\2\2\u0091") - buf.write("\u0092\7p\2\2\u0092\u0093\7f\2\2\u0093\u0094\7q\2\2\u0094") - buf.write("\u0095\7y\2\2\u0095\u0096\7p\2\2\u0096\"\3\2\2\2\u0097") - buf.write("\u0098\7r\2\2\u0098\u0099\7c\2\2\u0099\u009a\7w\2\2\u009a") - buf.write("\u009b\7u\2\2\u009b\u009c\7g\2\2\u009c$\3\2\2\2\u009d") - buf.write("\u009e\7c\2\2\u009e\u009f\7u\2\2\u009f\u00a0\7u\2\2\u00a0") - buf.write("\u00a1\7g\2\2\u00a1\u00a2\7t\2\2\u00a2\u00a3\7v\2\2\u00a3") - buf.write("&\3\2\2\2\u00a4\u00a5\7-\2\2\u00a5(\3\2\2\2\u00a6\u00a7") - buf.write("\7/\2\2\u00a7*\3\2\2\2\u00a8\u00a9\7,\2\2\u00a9,\3\2\2") - buf.write("\2\u00aa\u00ab\7\61\2\2\u00ab.\3\2\2\2\u00ac\u00ad\7r") - buf.write("\2\2\u00ad\u00ae\7g\2\2\u00ae\u00af\7p\2\2\u00af\u00b0") - buf.write("\7f\2\2\u00b0\u00b1\7q\2\2\u00b1\u00b2\7y\2\2\u00b2\u00b3") - buf.write("\7p\2\2\u00b3\u00b4\7A\2\2\u00b4\60\3\2\2\2\u00b5\u00b6") - buf.write("\7>\2\2\u00b6\62\3\2\2\2\u00b7\u00b8\7@\2\2\u00b8\64\3") - buf.write("\2\2\2\u00b9\u00ba\7?\2\2\u00ba\u00bb\7?\2\2\u00bb\66") - buf.write("\3\2\2\2\u00bc\u00bd\7#\2\2\u00bd\u00be\7?\2\2\u00be8") - buf.write("\3\2\2\2\u00bf\u00c0\7>\2\2\u00c0\u00c1\7?\2\2\u00c1:") - buf.write("\3\2\2\2\u00c2\u00c3\7@\2\2\u00c3\u00c4\7?\2\2\u00c4<") - buf.write("\3\2\2\2\u00c5\u00c6\7(\2\2\u00c6\u00c7\7(\2\2\u00c7>") - buf.write("\3\2\2\2\u00c8\u00c9\7~\2\2\u00c9\u00ca\7~\2\2\u00ca@") - buf.write("\3\2\2\2\u00cb\u00cc\7#\2\2\u00ccB\3\2\2\2\u00cd\u00cf") - buf.write("\t\2\2\2\u00ce\u00cd\3\2\2\2\u00cf\u00d0\3\2\2\2\u00d0") - buf.write("\u00ce\3\2\2\2\u00d0\u00d1\3\2\2\2\u00d1D\3\2\2\2\u00d2") - buf.write("\u00d3\7<\2\2\u00d3\u00d7\t\3\2\2\u00d4\u00d6\t\4\2\2") - buf.write("\u00d5\u00d4\3\2\2\2\u00d6\u00d9\3\2\2\2\u00d7\u00d5\3") - buf.write("\2\2\2\u00d7\u00d8\3\2\2\2\u00d8F\3\2\2\2\u00d9\u00d7") - buf.write("\3\2\2\2\u00da\u00dc\t\5\2\2\u00db\u00da\3\2\2\2\u00dc") - buf.write("\u00dd\3\2\2\2\u00dd\u00db\3\2\2\2\u00dd\u00de\3\2\2\2") - buf.write("\u00deH\3\2\2\2\u00df\u00e1\t\6\2\2\u00e0\u00df\3\2\2") - buf.write("\2\u00e1\u00e2\3\2\2\2\u00e2\u00e0\3\2\2\2\u00e2\u00e3") - buf.write("\3\2\2\2\u00e3\u00e4\3\2\2\2\u00e4\u00e5\b%\2\2\u00e5") - buf.write("J\3\2\2\2\u00e6\u00e7\7\61\2\2\u00e7\u00e8\7\61\2\2\u00e8") - buf.write("\u00ec\3\2\2\2\u00e9\u00eb\n\7\2\2\u00ea\u00e9\3\2\2\2") - buf.write("\u00eb\u00ee\3\2\2\2\u00ec\u00ea\3\2\2\2\u00ec\u00ed\3") - buf.write("\2\2\2\u00ed\u00ef\3\2\2\2\u00ee\u00ec\3\2\2\2\u00ef\u00f0") - buf.write("\b&\2\2\u00f0L\3\2\2\2\b\2\u00d0\u00d7\u00dd\u00e2\u00ec") + buf.write("\4&\t&\4\'\t\'\3\2\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\5") + buf.write("\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3") + buf.write("\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\f\3\f\3") + buf.write("\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16") + buf.write("\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\20") + buf.write("\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21") + buf.write("\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23") + buf.write("\3\23\3\23\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26\3\27") + buf.write("\3\27\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31") + buf.write("\3\31\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35") + buf.write("\3\36\3\36\3\36\3\37\3\37\3\37\3 \3 \3 \3!\3!\3!\3\"\3") + buf.write("\"\3#\6#\u00d3\n#\r#\16#\u00d4\3$\3$\3$\7$\u00da\n$\f") + buf.write("$\16$\u00dd\13$\3%\6%\u00e0\n%\r%\16%\u00e1\3&\6&\u00e5") + buf.write("\n&\r&\16&\u00e6\3&\3&\3\'\3\'\3\'\3\'\7\'\u00ef\n\'\f") + buf.write("\'\16\'\u00f2\13\'\3\'\3\'\2\2(\3\3\5\4\7\5\t\6\13\7\r") + buf.write("\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!") + buf.write("\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67") + buf.write("\359\36;\37= ?!A\"C#E$G%I&K\'M(\3\2\b\3\2\62;\5\2C\\a") + buf.write("ac|\5\2\62;C\\c|\4\2C\\c|\5\2\13\f\17\17\"\"\4\2\f\f\17") + buf.write("\17\2\u00f9\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3") + buf.write("\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2") + buf.write("\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2") + buf.write("\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2") + buf.write("#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2") + buf.write("\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65") + buf.write("\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2") + buf.write("\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2") + buf.write("\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\3O\3\2\2\2\5R\3\2") + buf.write("\2\2\7T\3\2\2\2\tV\3\2\2\2\13[\3\2\2\2\rb\3\2\2\2\17g") + buf.write("\3\2\2\2\21i\3\2\2\2\23k\3\2\2\2\25m\3\2\2\2\27o\3\2\2") + buf.write("\2\31w\3\2\2\2\33\u0080\3\2\2\2\35\u0085\3\2\2\2\37\u008b") + buf.write("\3\2\2\2!\u0091\3\2\2\2#\u0099\3\2\2\2%\u009f\3\2\2\2") + buf.write("\'\u00a6\3\2\2\2)\u00a8\3\2\2\2+\u00aa\3\2\2\2-\u00ac") + buf.write("\3\2\2\2/\u00ae\3\2\2\2\61\u00b0\3\2\2\2\63\u00b9\3\2") + buf.write("\2\2\65\u00bb\3\2\2\2\67\u00bd\3\2\2\29\u00c0\3\2\2\2") + buf.write(";\u00c3\3\2\2\2=\u00c6\3\2\2\2?\u00c9\3\2\2\2A\u00cc\3") + buf.write("\2\2\2C\u00cf\3\2\2\2E\u00d2\3\2\2\2G\u00d6\3\2\2\2I\u00df") + buf.write("\3\2\2\2K\u00e4\3\2\2\2M\u00ea\3\2\2\2OP\7k\2\2PQ\7h\2") + buf.write("\2Q\4\3\2\2\2RS\7]\2\2S\6\3\2\2\2TU\7_\2\2U\b\3\2\2\2") + buf.write("VW\7g\2\2WX\7n\2\2XY\7u\2\2YZ\7g\2\2Z\n\3\2\2\2[\\\7t") + buf.write("\2\2\\]\7g\2\2]^\7r\2\2^_\7g\2\2_`\7c\2\2`a\7v\2\2a\f") + buf.write("\3\2\2\2bc\7i\2\2cd\7q\2\2de\7v\2\2ef\7q\2\2f\16\3\2\2") + buf.write("\2gh\7*\2\2h\20\3\2\2\2ij\7.\2\2j\22\3\2\2\2kl\7+\2\2") + buf.write("l\24\3\2\2\2mn\7?\2\2n\26\3\2\2\2op\7h\2\2pq\7q\2\2qr") + buf.write("\7t\2\2rs\7y\2\2st\7c\2\2tu\7t\2\2uv\7f\2\2v\30\3\2\2") + buf.write("\2wx\7d\2\2xy\7c\2\2yz\7e\2\2z{\7m\2\2{|\7y\2\2|}\7c\2") + buf.write("\2}~\7t\2\2~\177\7f\2\2\177\32\3\2\2\2\u0080\u0081\7n") + buf.write("\2\2\u0081\u0082\7g\2\2\u0082\u0083\7h\2\2\u0083\u0084") + buf.write("\7v\2\2\u0084\34\3\2\2\2\u0085\u0086\7t\2\2\u0086\u0087") + buf.write("\7k\2\2\u0087\u0088\7i\2\2\u0088\u0089\7j\2\2\u0089\u008a") + buf.write("\7v\2\2\u008a\36\3\2\2\2\u008b\u008c\7r\2\2\u008c\u008d") + buf.write("\7g\2\2\u008d\u008e\7p\2\2\u008e\u008f\7w\2\2\u008f\u0090") + buf.write("\7r\2\2\u0090 \3\2\2\2\u0091\u0092\7r\2\2\u0092\u0093") + buf.write("\7g\2\2\u0093\u0094\7p\2\2\u0094\u0095\7f\2\2\u0095\u0096") + buf.write("\7q\2\2\u0096\u0097\7y\2\2\u0097\u0098\7p\2\2\u0098\"") + buf.write("\3\2\2\2\u0099\u009a\7r\2\2\u009a\u009b\7c\2\2\u009b\u009c") + buf.write("\7w\2\2\u009c\u009d\7u\2\2\u009d\u009e\7g\2\2\u009e$\3") + buf.write("\2\2\2\u009f\u00a0\7c\2\2\u00a0\u00a1\7u\2\2\u00a1\u00a2") + buf.write("\7u\2\2\u00a2\u00a3\7g\2\2\u00a3\u00a4\7t\2\2\u00a4\u00a5") + buf.write("\7v\2\2\u00a5&\3\2\2\2\u00a6\u00a7\7-\2\2\u00a7(\3\2\2") + buf.write("\2\u00a8\u00a9\7/\2\2\u00a9*\3\2\2\2\u00aa\u00ab\7,\2") + buf.write("\2\u00ab,\3\2\2\2\u00ac\u00ad\7\61\2\2\u00ad.\3\2\2\2") + buf.write("\u00ae\u00af\7\'\2\2\u00af\60\3\2\2\2\u00b0\u00b1\7r\2") + buf.write("\2\u00b1\u00b2\7g\2\2\u00b2\u00b3\7p\2\2\u00b3\u00b4\7") + buf.write("f\2\2\u00b4\u00b5\7q\2\2\u00b5\u00b6\7y\2\2\u00b6\u00b7") + buf.write("\7p\2\2\u00b7\u00b8\7A\2\2\u00b8\62\3\2\2\2\u00b9\u00ba") + buf.write("\7>\2\2\u00ba\64\3\2\2\2\u00bb\u00bc\7@\2\2\u00bc\66\3") + buf.write("\2\2\2\u00bd\u00be\7?\2\2\u00be\u00bf\7?\2\2\u00bf8\3") + buf.write("\2\2\2\u00c0\u00c1\7#\2\2\u00c1\u00c2\7?\2\2\u00c2:\3") + buf.write("\2\2\2\u00c3\u00c4\7>\2\2\u00c4\u00c5\7?\2\2\u00c5<\3") + buf.write("\2\2\2\u00c6\u00c7\7@\2\2\u00c7\u00c8\7?\2\2\u00c8>\3") + buf.write("\2\2\2\u00c9\u00ca\7(\2\2\u00ca\u00cb\7(\2\2\u00cb@\3") + buf.write("\2\2\2\u00cc\u00cd\7~\2\2\u00cd\u00ce\7~\2\2\u00ceB\3") + buf.write("\2\2\2\u00cf\u00d0\7#\2\2\u00d0D\3\2\2\2\u00d1\u00d3\t") + buf.write("\2\2\2\u00d2\u00d1\3\2\2\2\u00d3\u00d4\3\2\2\2\u00d4\u00d2") + buf.write("\3\2\2\2\u00d4\u00d5\3\2\2\2\u00d5F\3\2\2\2\u00d6\u00d7") + buf.write("\7<\2\2\u00d7\u00db\t\3\2\2\u00d8\u00da\t\4\2\2\u00d9") + buf.write("\u00d8\3\2\2\2\u00da\u00dd\3\2\2\2\u00db\u00d9\3\2\2\2") + buf.write("\u00db\u00dc\3\2\2\2\u00dcH\3\2\2\2\u00dd\u00db\3\2\2") + buf.write("\2\u00de\u00e0\t\5\2\2\u00df\u00de\3\2\2\2\u00e0\u00e1") + buf.write("\3\2\2\2\u00e1\u00df\3\2\2\2\u00e1\u00e2\3\2\2\2\u00e2") + buf.write("J\3\2\2\2\u00e3\u00e5\t\6\2\2\u00e4\u00e3\3\2\2\2\u00e5") + buf.write("\u00e6\3\2\2\2\u00e6\u00e4\3\2\2\2\u00e6\u00e7\3\2\2\2") + buf.write("\u00e7\u00e8\3\2\2\2\u00e8\u00e9\b&\2\2\u00e9L\3\2\2\2") + buf.write("\u00ea\u00eb\7\61\2\2\u00eb\u00ec\7\61\2\2\u00ec\u00f0") + buf.write("\3\2\2\2\u00ed\u00ef\n\7\2\2\u00ee\u00ed\3\2\2\2\u00ef") + buf.write("\u00f2\3\2\2\2\u00f0\u00ee\3\2\2\2\u00f0\u00f1\3\2\2\2") + buf.write("\u00f1\u00f3\3\2\2\2\u00f2\u00f0\3\2\2\2\u00f3\u00f4\b") + buf.write("\'\2\2\u00f4N\3\2\2\2\b\2\u00d4\u00db\u00e1\u00e6\u00f0") buf.write("\3\b\2\2") return buf.getvalue() @@ -134,21 +136,22 @@ class tlangLexer(Lexer): MINUS = 20 MUL = 21 DIV = 22 - PENCOND = 23 - LT = 24 - GT = 25 - EQ = 26 - NEQ = 27 - LTE = 28 - GTE = 29 - AND = 30 - OR = 31 - NOT = 32 - NUM = 33 - VAR = 34 - NAME = 35 - Whitespace = 36 - Comment = 37 + MOD = 23 + PENCOND = 24 + LT = 25 + GT = 26 + EQ = 27 + NEQ = 28 + LTE = 29 + GTE = 30 + AND = 31 + OR = 32 + NOT = 33 + NUM = 34 + VAR = 35 + NAME = 36 + Whitespace = 37 + Comment = 38 channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] @@ -158,19 +161,19 @@ class tlangLexer(Lexer): "'if'", "'['", "']'", "'else'", "'repeat'", "'goto'", "'('", "','", "')'", "'='", "'forward'", "'backward'", "'left'", "'right'", "'penup'", "'pendown'", "'pause'", "'assert'", "'+'", "'-'", - "'*'", "'/'", "'pendown?'", "'<'", "'>'", "'=='", "'!='", "'<='", - "'>='", "'&&'", "'||'", "'!'" ] + "'*'", "'/'", "'%'", "'pendown?'", "'<'", "'>'", "'=='", "'!='", + "'<='", "'>='", "'&&'", "'||'", "'!'" ] symbolicNames = [ "", - "PLUS", "MINUS", "MUL", "DIV", "PENCOND", "LT", "GT", "EQ", - "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", "VAR", "NAME", - "Whitespace", "Comment" ] + "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", + "EQ", "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", "VAR", + "NAME", "Whitespace", "Comment" ] ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", "T__17", "PLUS", "MINUS", "MUL", - "DIV", "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", "GTE", - "AND", "OR", "NOT", "NUM", "VAR", "NAME", "Whitespace", + "DIV", "MOD", "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", + "GTE", "AND", "OR", "NOT", "NUM", "VAR", "NAME", "Whitespace", "Comment" ] grammarFileName = "tlang.g4" diff --git a/ChironCore/turtparse/tlangLexer.tokens b/ChironCore/turtparse/tlangLexer.tokens index b0a2b1d..2c2f507 100644 --- a/ChironCore/turtparse/tlangLexer.tokens +++ b/ChironCore/turtparse/tlangLexer.tokens @@ -20,21 +20,22 @@ PLUS=19 MINUS=20 MUL=21 DIV=22 -PENCOND=23 -LT=24 -GT=25 -EQ=26 -NEQ=27 -LTE=28 -GTE=29 -AND=30 -OR=31 -NOT=32 -NUM=33 -VAR=34 -NAME=35 -Whitespace=36 -Comment=37 +MOD=23 +PENCOND=24 +LT=25 +GT=26 +EQ=27 +NEQ=28 +LTE=29 +GTE=30 +AND=31 +OR=32 +NOT=33 +NUM=34 +VAR=35 +NAME=36 +Whitespace=37 +Comment=38 'if'=1 '['=2 ']'=3 @@ -57,13 +58,14 @@ Comment=37 '-'=20 '*'=21 '/'=22 -'pendown?'=23 -'<'=24 -'>'=25 -'=='=26 -'!='=27 -'<='=28 -'>='=29 -'&&'=30 -'||'=31 -'!'=32 +'%'=23 +'pendown?'=24 +'<'=25 +'>'=26 +'=='=27 +'!='=28 +'<='=29 +'>='=30 +'&&'=31 +'||'=32 +'!'=33 diff --git a/ChironCore/turtparse/tlangParser.py b/ChironCore/turtparse/tlangParser.py index bc95100..e36b76e 100644 --- a/ChironCore/turtparse/tlangParser.py +++ b/ChironCore/turtparse/tlangParser.py @@ -8,72 +8,76 @@ def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\'") - buf.write("\u00b5\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3(") + buf.write("\u00bd\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16") buf.write("\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23\t\23") - buf.write("\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\3\2") - buf.write("\3\2\3\2\3\3\7\3\65\n\3\f\3\16\38\13\3\3\4\6\4;\n\4\r") - buf.write("\4\16\4<\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5G\n\5\3\6") - buf.write("\3\6\5\6K\n\6\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b") - buf.write("\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3") - buf.write("\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\f\3\f\3\f") - buf.write("\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\21\3\21") - buf.write("\3\21\3\21\3\21\3\21\3\21\3\21\3\21\5\21\u0083\n\21\3") - buf.write("\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\7\21\u008d\n\21") - buf.write("\f\21\16\21\u0090\13\21\3\22\3\22\3\23\3\23\3\24\3\24") - buf.write("\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25") - buf.write("\3\25\5\25\u00a4\n\25\3\25\3\25\3\25\3\25\7\25\u00aa\n") - buf.write("\25\f\25\16\25\u00ad\13\25\3\26\3\26\3\27\3\27\3\30\3") - buf.write("\30\3\30\2\4 (\31\2\4\6\b\n\f\16\20\22\24\26\30\32\34") - buf.write("\36 \"$&(*,.\2\t\3\2\r\20\3\2\21\22\3\2\27\30\3\2\25\26") - buf.write("\3\2\32\37\3\2 !\3\2#$\2\u00af\2\60\3\2\2\2\4\66\3\2\2") - buf.write("\2\6:\3\2\2\2\bF\3\2\2\2\nJ\3\2\2\2\fL\3\2\2\2\16R\3\2") - buf.write("\2\2\20\\\3\2\2\2\22b\3\2\2\2\24i\3\2\2\2\26m\3\2\2\2") - buf.write("\30p\3\2\2\2\32r\3\2\2\2\34t\3\2\2\2\36v\3\2\2\2 \u0082") - buf.write("\3\2\2\2\"\u0091\3\2\2\2$\u0093\3\2\2\2&\u0095\3\2\2\2") - buf.write("(\u00a3\3\2\2\2*\u00ae\3\2\2\2,\u00b0\3\2\2\2.\u00b2\3") - buf.write("\2\2\2\60\61\5\4\3\2\61\62\7\2\2\3\62\3\3\2\2\2\63\65") - buf.write("\5\b\5\2\64\63\3\2\2\2\658\3\2\2\2\66\64\3\2\2\2\66\67") - buf.write("\3\2\2\2\67\5\3\2\2\28\66\3\2\2\29;\5\b\5\2:9\3\2\2\2") - buf.write(";<\3\2\2\2<:\3\2\2\2<=\3\2\2\2=\7\3\2\2\2>G\5\24\13\2") - buf.write("?G\5\n\6\2@G\5\20\t\2AG\5\26\f\2BG\5\32\16\2CG\5\22\n") - buf.write("\2DG\5\34\17\2EG\5\36\20\2F>\3\2\2\2F?\3\2\2\2F@\3\2\2") - buf.write("\2FA\3\2\2\2FB\3\2\2\2FC\3\2\2\2FD\3\2\2\2FE\3\2\2\2G") - buf.write("\t\3\2\2\2HK\5\f\7\2IK\5\16\b\2JH\3\2\2\2JI\3\2\2\2K\13") - buf.write("\3\2\2\2LM\7\3\2\2MN\5(\25\2NO\7\4\2\2OP\5\6\4\2PQ\7\5") - buf.write("\2\2Q\r\3\2\2\2RS\7\3\2\2ST\5(\25\2TU\7\4\2\2UV\5\6\4") - buf.write("\2VW\7\5\2\2WX\7\6\2\2XY\7\4\2\2YZ\5\6\4\2Z[\7\5\2\2[") - buf.write("\17\3\2\2\2\\]\7\7\2\2]^\5.\30\2^_\7\4\2\2_`\5\6\4\2`") - buf.write("a\7\5\2\2a\21\3\2\2\2bc\7\b\2\2cd\7\t\2\2de\5 \21\2ef") - buf.write("\7\n\2\2fg\5 \21\2gh\7\13\2\2h\23\3\2\2\2ij\7$\2\2jk\7") - buf.write("\f\2\2kl\5 \21\2l\25\3\2\2\2mn\5\30\r\2no\5 \21\2o\27") - buf.write("\3\2\2\2pq\t\2\2\2q\31\3\2\2\2rs\t\3\2\2s\33\3\2\2\2t") - buf.write("u\7\23\2\2u\35\3\2\2\2vw\7\24\2\2wx\5(\25\2x\37\3\2\2") - buf.write("\2yz\b\21\1\2z{\5&\24\2{|\5 \21\7|\u0083\3\2\2\2}\u0083") - buf.write("\5.\30\2~\177\7\t\2\2\177\u0080\5 \21\2\u0080\u0081\7") - buf.write("\13\2\2\u0081\u0083\3\2\2\2\u0082y\3\2\2\2\u0082}\3\2") - buf.write("\2\2\u0082~\3\2\2\2\u0083\u008e\3\2\2\2\u0084\u0085\f") - buf.write("\6\2\2\u0085\u0086\5\"\22\2\u0086\u0087\5 \21\7\u0087") - buf.write("\u008d\3\2\2\2\u0088\u0089\f\5\2\2\u0089\u008a\5$\23\2") - buf.write("\u008a\u008b\5 \21\6\u008b\u008d\3\2\2\2\u008c\u0084\3") - buf.write("\2\2\2\u008c\u0088\3\2\2\2\u008d\u0090\3\2\2\2\u008e\u008c") - buf.write("\3\2\2\2\u008e\u008f\3\2\2\2\u008f!\3\2\2\2\u0090\u008e") - buf.write("\3\2\2\2\u0091\u0092\t\4\2\2\u0092#\3\2\2\2\u0093\u0094") - buf.write("\t\5\2\2\u0094%\3\2\2\2\u0095\u0096\7\26\2\2\u0096\'\3") - buf.write("\2\2\2\u0097\u0098\b\25\1\2\u0098\u0099\7\"\2\2\u0099") - buf.write("\u00a4\5(\25\7\u009a\u009b\5 \21\2\u009b\u009c\5*\26\2") - buf.write("\u009c\u009d\5 \21\2\u009d\u00a4\3\2\2\2\u009e\u00a4\7") - buf.write("\31\2\2\u009f\u00a0\7\t\2\2\u00a0\u00a1\5(\25\2\u00a1") - buf.write("\u00a2\7\13\2\2\u00a2\u00a4\3\2\2\2\u00a3\u0097\3\2\2") - buf.write("\2\u00a3\u009a\3\2\2\2\u00a3\u009e\3\2\2\2\u00a3\u009f") - buf.write("\3\2\2\2\u00a4\u00ab\3\2\2\2\u00a5\u00a6\f\5\2\2\u00a6") - buf.write("\u00a7\5,\27\2\u00a7\u00a8\5(\25\6\u00a8\u00aa\3\2\2\2") - buf.write("\u00a9\u00a5\3\2\2\2\u00aa\u00ad\3\2\2\2\u00ab\u00a9\3") - buf.write("\2\2\2\u00ab\u00ac\3\2\2\2\u00ac)\3\2\2\2\u00ad\u00ab") - buf.write("\3\2\2\2\u00ae\u00af\t\6\2\2\u00af+\3\2\2\2\u00b0\u00b1") - buf.write("\t\7\2\2\u00b1-\3\2\2\2\u00b2\u00b3\t\b\2\2\u00b3/\3\2") - buf.write("\2\2\13\66\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5") + buf.write("I\n\5\3\6\3\6\5\6M\n\6\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b") + buf.write("\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3") + buf.write("\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\f") + buf.write("\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3") + buf.write("\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\5\21\u0085") + buf.write("\n\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21") + buf.write("\3\21\3\21\7\21\u0093\n\21\f\21\16\21\u0096\13\21\3\22") + buf.write("\3\22\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26\3\26\3\26") + buf.write("\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\5\26\u00ac\n") + buf.write("\26\3\26\3\26\3\26\3\26\7\26\u00b2\n\26\f\26\16\26\u00b5") + buf.write("\13\26\3\27\3\27\3\30\3\30\3\31\3\31\3\31\2\4 *\32\2\4") + buf.write("\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\2\t\3") + buf.write("\2\r\20\3\2\21\22\3\2\27\30\3\2\25\26\3\2\33 \3\2!\"\3") + buf.write("\2$%\2\u00b7\2\62\3\2\2\2\48\3\2\2\2\6<\3\2\2\2\bH\3\2") + buf.write("\2\2\nL\3\2\2\2\fN\3\2\2\2\16T\3\2\2\2\20^\3\2\2\2\22") + buf.write("d\3\2\2\2\24k\3\2\2\2\26o\3\2\2\2\30r\3\2\2\2\32t\3\2") + buf.write("\2\2\34v\3\2\2\2\36x\3\2\2\2 \u0084\3\2\2\2\"\u0097\3") + buf.write("\2\2\2$\u0099\3\2\2\2&\u009b\3\2\2\2(\u009d\3\2\2\2*\u00ab") + buf.write("\3\2\2\2,\u00b6\3\2\2\2.\u00b8\3\2\2\2\60\u00ba\3\2\2") + buf.write("\2\62\63\5\4\3\2\63\64\7\2\2\3\64\3\3\2\2\2\65\67\5\b") + buf.write("\5\2\66\65\3\2\2\2\67:\3\2\2\28\66\3\2\2\289\3\2\2\29") + buf.write("\5\3\2\2\2:8\3\2\2\2;=\5\b\5\2<;\3\2\2\2=>\3\2\2\2><\3") + buf.write("\2\2\2>?\3\2\2\2?\7\3\2\2\2@I\5\24\13\2AI\5\n\6\2BI\5") + buf.write("\20\t\2CI\5\26\f\2DI\5\32\16\2EI\5\22\n\2FI\5\34\17\2") + buf.write("GI\5\36\20\2H@\3\2\2\2HA\3\2\2\2HB\3\2\2\2HC\3\2\2\2H") + buf.write("D\3\2\2\2HE\3\2\2\2HF\3\2\2\2HG\3\2\2\2I\t\3\2\2\2JM\5") + buf.write("\f\7\2KM\5\16\b\2LJ\3\2\2\2LK\3\2\2\2M\13\3\2\2\2NO\7") + buf.write("\3\2\2OP\5*\26\2PQ\7\4\2\2QR\5\6\4\2RS\7\5\2\2S\r\3\2") + buf.write("\2\2TU\7\3\2\2UV\5*\26\2VW\7\4\2\2WX\5\6\4\2XY\7\5\2\2") + buf.write("YZ\7\6\2\2Z[\7\4\2\2[\\\5\6\4\2\\]\7\5\2\2]\17\3\2\2\2") + buf.write("^_\7\7\2\2_`\5\60\31\2`a\7\4\2\2ab\5\6\4\2bc\7\5\2\2c") + buf.write("\21\3\2\2\2de\7\b\2\2ef\7\t\2\2fg\5 \21\2gh\7\n\2\2hi") + buf.write("\5 \21\2ij\7\13\2\2j\23\3\2\2\2kl\7%\2\2lm\7\f\2\2mn\5") + buf.write(" \21\2n\25\3\2\2\2op\5\30\r\2pq\5 \21\2q\27\3\2\2\2rs") + buf.write("\t\2\2\2s\31\3\2\2\2tu\t\3\2\2u\33\3\2\2\2vw\7\23\2\2") + buf.write("w\35\3\2\2\2xy\7\24\2\2yz\5*\26\2z\37\3\2\2\2{|\b\21\1") + buf.write("\2|}\5(\25\2}~\5 \21\b~\u0085\3\2\2\2\177\u0085\5\60\31") + buf.write("\2\u0080\u0081\7\t\2\2\u0081\u0082\5 \21\2\u0082\u0083") + buf.write("\7\13\2\2\u0083\u0085\3\2\2\2\u0084{\3\2\2\2\u0084\177") + buf.write("\3\2\2\2\u0084\u0080\3\2\2\2\u0085\u0094\3\2\2\2\u0086") + buf.write("\u0087\f\7\2\2\u0087\u0088\5\"\22\2\u0088\u0089\5 \21") + buf.write("\b\u0089\u0093\3\2\2\2\u008a\u008b\f\6\2\2\u008b\u008c") + buf.write("\5$\23\2\u008c\u008d\5 \21\7\u008d\u0093\3\2\2\2\u008e") + buf.write("\u008f\f\5\2\2\u008f\u0090\5&\24\2\u0090\u0091\5 \21\6") + buf.write("\u0091\u0093\3\2\2\2\u0092\u0086\3\2\2\2\u0092\u008a\3") + buf.write("\2\2\2\u0092\u008e\3\2\2\2\u0093\u0096\3\2\2\2\u0094\u0092") + buf.write("\3\2\2\2\u0094\u0095\3\2\2\2\u0095!\3\2\2\2\u0096\u0094") + buf.write("\3\2\2\2\u0097\u0098\t\4\2\2\u0098#\3\2\2\2\u0099\u009a") + buf.write("\t\5\2\2\u009a%\3\2\2\2\u009b\u009c\7\31\2\2\u009c\'\3") + buf.write("\2\2\2\u009d\u009e\7\26\2\2\u009e)\3\2\2\2\u009f\u00a0") + buf.write("\b\26\1\2\u00a0\u00a1\7#\2\2\u00a1\u00ac\5*\26\7\u00a2") + buf.write("\u00a3\5 \21\2\u00a3\u00a4\5,\27\2\u00a4\u00a5\5 \21\2") + buf.write("\u00a5\u00ac\3\2\2\2\u00a6\u00ac\7\32\2\2\u00a7\u00a8") + buf.write("\7\t\2\2\u00a8\u00a9\5*\26\2\u00a9\u00aa\7\13\2\2\u00aa") + buf.write("\u00ac\3\2\2\2\u00ab\u009f\3\2\2\2\u00ab\u00a2\3\2\2\2") + buf.write("\u00ab\u00a6\3\2\2\2\u00ab\u00a7\3\2\2\2\u00ac\u00b3\3") + buf.write("\2\2\2\u00ad\u00ae\f\5\2\2\u00ae\u00af\5.\30\2\u00af\u00b0") + buf.write("\5*\26\6\u00b0\u00b2\3\2\2\2\u00b1\u00ad\3\2\2\2\u00b2") + buf.write("\u00b5\3\2\2\2\u00b3\u00b1\3\2\2\2\u00b3\u00b4\3\2\2\2") + buf.write("\u00b4+\3\2\2\2\u00b5\u00b3\3\2\2\2\u00b6\u00b7\t\6\2") + buf.write("\2\u00b7-\3\2\2\2\u00b8\u00b9\t\7\2\2\u00b9/\3\2\2\2\u00ba") + buf.write("\u00bb\t\b\2\2\u00bb\61\3\2\2\2\138>HL\u0084\u0092\u0094") + buf.write("\u00ab\u00b3") return buf.getvalue() @@ -91,17 +95,17 @@ class tlangParser ( Parser ): "'goto'", "'('", "','", "')'", "'='", "'forward'", "'backward'", "'left'", "'right'", "'penup'", "'pendown'", "'pause'", "'assert'", "'+'", "'-'", "'*'", "'/'", - "'pendown?'", "'<'", "'>'", "'=='", "'!='", "'<='", - "'>='", "'&&'", "'||'", "'!'" ] + "'%'", "'pendown?'", "'<'", "'>'", "'=='", "'!='", + "'<='", "'>='", "'&&'", "'||'", "'!'" ] symbolicNames = [ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "PLUS", "MINUS", - "MUL", "DIV", "PENCOND", "LT", "GT", "EQ", "NEQ", - "LTE", "GTE", "AND", "OR", "NOT", "NUM", "VAR", "NAME", - "Whitespace", "Comment" ] + "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", "EQ", + "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", "VAR", + "NAME", "Whitespace", "Comment" ] RULE_start = 0 RULE_instruction_list = 1 @@ -121,18 +125,19 @@ class tlangParser ( Parser ): RULE_expression = 15 RULE_multiplicative = 16 RULE_additive = 17 - RULE_unaryArithOp = 18 - RULE_condition = 19 - RULE_binCondOp = 20 - RULE_logicOp = 21 - RULE_value = 22 + RULE_modulo = 18 + RULE_unaryArithOp = 19 + RULE_condition = 20 + RULE_binCondOp = 21 + RULE_logicOp = 22 + RULE_value = 23 ruleNames = [ "start", "instruction_list", "strict_ilist", "instruction", "conditional", "ifConditional", "ifElseConditional", "loop", "gotoCommand", "assignment", "moveCommand", "moveOp", "penCommand", "pauseCommand", "assertionCommand", "expression", - "multiplicative", "additive", "unaryArithOp", "condition", - "binCondOp", "logicOp", "value" ] + "multiplicative", "additive", "modulo", "unaryArithOp", + "condition", "binCondOp", "logicOp", "value" ] EOF = Token.EOF T__0=1 @@ -157,21 +162,22 @@ class tlangParser ( Parser ): MINUS=20 MUL=21 DIV=22 - PENCOND=23 - LT=24 - GT=25 - EQ=26 - NEQ=27 - LTE=28 - GTE=29 - AND=30 - OR=31 - NOT=32 - NUM=33 - VAR=34 - NAME=35 - Whitespace=36 - Comment=37 + MOD=23 + PENCOND=24 + LT=25 + GT=26 + EQ=27 + NEQ=28 + LTE=29 + GTE=30 + AND=31 + OR=32 + NOT=33 + NUM=34 + VAR=35 + NAME=36 + Whitespace=37 + Comment=38 def __init__(self, input:TokenStream, output:TextIO = sys.stdout): super().__init__(input, output) @@ -213,9 +219,9 @@ def start(self): self.enterRule(localctx, 0, self.RULE_start) try: self.enterOuterAlt(localctx, 1) - self.state = 46 + self.state = 48 self.instruction_list() - self.state = 47 + self.state = 49 self.match(tlangParser.EOF) except RecognitionException as re: localctx.exception = re @@ -258,13 +264,13 @@ def instruction_list(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 52 + self.state = 54 self._errHandler.sync(self) _la = self._input.LA(1) while (((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.VAR))) != 0): - self.state = 49 + self.state = 51 self.instruction() - self.state = 54 + self.state = 56 self._errHandler.sync(self) _la = self._input.LA(1) @@ -309,13 +315,13 @@ def strict_ilist(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 56 + self.state = 58 self._errHandler.sync(self) _la = self._input.LA(1) while True: - self.state = 55 + self.state = 57 self.instruction() - self.state = 58 + self.state = 60 self._errHandler.sync(self) _la = self._input.LA(1) if not ((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.VAR))) != 0)): @@ -385,47 +391,47 @@ def instruction(self): localctx = tlangParser.InstructionContext(self, self._ctx, self.state) self.enterRule(localctx, 6, self.RULE_instruction) try: - self.state = 68 + self.state = 70 self._errHandler.sync(self) token = self._input.LA(1) if token in [tlangParser.VAR]: self.enterOuterAlt(localctx, 1) - self.state = 60 + self.state = 62 self.assignment() pass elif token in [tlangParser.T__0]: self.enterOuterAlt(localctx, 2) - self.state = 61 + self.state = 63 self.conditional() pass elif token in [tlangParser.T__4]: self.enterOuterAlt(localctx, 3) - self.state = 62 + self.state = 64 self.loop() pass elif token in [tlangParser.T__10, tlangParser.T__11, tlangParser.T__12, tlangParser.T__13]: self.enterOuterAlt(localctx, 4) - self.state = 63 + self.state = 65 self.moveCommand() pass elif token in [tlangParser.T__14, tlangParser.T__15]: self.enterOuterAlt(localctx, 5) - self.state = 64 + self.state = 66 self.penCommand() pass elif token in [tlangParser.T__5]: self.enterOuterAlt(localctx, 6) - self.state = 65 + self.state = 67 self.gotoCommand() pass elif token in [tlangParser.T__16]: self.enterOuterAlt(localctx, 7) - self.state = 66 + self.state = 68 self.pauseCommand() pass elif token in [tlangParser.T__17]: self.enterOuterAlt(localctx, 8) - self.state = 67 + self.state = 69 self.assertionCommand() pass else: @@ -471,18 +477,18 @@ def conditional(self): localctx = tlangParser.ConditionalContext(self, self._ctx, self.state) self.enterRule(localctx, 8, self.RULE_conditional) try: - self.state = 72 + self.state = 74 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,3,self._ctx) if la_ == 1: self.enterOuterAlt(localctx, 1) - self.state = 70 + self.state = 72 self.ifConditional() pass elif la_ == 2: self.enterOuterAlt(localctx, 2) - self.state = 71 + self.state = 73 self.ifElseConditional() pass @@ -528,15 +534,15 @@ def ifConditional(self): self.enterRule(localctx, 10, self.RULE_ifConditional) try: self.enterOuterAlt(localctx, 1) - self.state = 74 + self.state = 76 self.match(tlangParser.T__0) - self.state = 75 + self.state = 77 self.condition(0) - self.state = 76 + self.state = 78 self.match(tlangParser.T__1) - self.state = 77 + self.state = 79 self.strict_ilist() - self.state = 78 + self.state = 80 self.match(tlangParser.T__2) except RecognitionException as re: localctx.exception = re @@ -582,23 +588,23 @@ def ifElseConditional(self): self.enterRule(localctx, 12, self.RULE_ifElseConditional) try: self.enterOuterAlt(localctx, 1) - self.state = 80 + self.state = 82 self.match(tlangParser.T__0) - self.state = 81 + self.state = 83 self.condition(0) - self.state = 82 + self.state = 84 self.match(tlangParser.T__1) - self.state = 83 + self.state = 85 self.strict_ilist() - self.state = 84 + self.state = 86 self.match(tlangParser.T__2) - self.state = 85 + self.state = 87 self.match(tlangParser.T__3) - self.state = 86 + self.state = 88 self.match(tlangParser.T__1) - self.state = 87 + self.state = 89 self.strict_ilist() - self.state = 88 + self.state = 90 self.match(tlangParser.T__2) except RecognitionException as re: localctx.exception = re @@ -641,15 +647,15 @@ def loop(self): self.enterRule(localctx, 14, self.RULE_loop) try: self.enterOuterAlt(localctx, 1) - self.state = 90 + self.state = 92 self.match(tlangParser.T__4) - self.state = 91 + self.state = 93 self.value() - self.state = 92 + self.state = 94 self.match(tlangParser.T__1) - self.state = 93 + self.state = 95 self.strict_ilist() - self.state = 94 + self.state = 96 self.match(tlangParser.T__2) except RecognitionException as re: localctx.exception = re @@ -691,17 +697,17 @@ def gotoCommand(self): self.enterRule(localctx, 16, self.RULE_gotoCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 96 - self.match(tlangParser.T__5) - self.state = 97 - self.match(tlangParser.T__6) self.state = 98 - self.expression(0) + self.match(tlangParser.T__5) self.state = 99 - self.match(tlangParser.T__7) + self.match(tlangParser.T__6) self.state = 100 self.expression(0) self.state = 101 + self.match(tlangParser.T__7) + self.state = 102 + self.expression(0) + self.state = 103 self.match(tlangParser.T__8) except RecognitionException as re: localctx.exception = re @@ -743,11 +749,11 @@ def assignment(self): self.enterRule(localctx, 18, self.RULE_assignment) try: self.enterOuterAlt(localctx, 1) - self.state = 103 + self.state = 105 self.match(tlangParser.VAR) - self.state = 104 + self.state = 106 self.match(tlangParser.T__9) - self.state = 105 + self.state = 107 self.expression(0) except RecognitionException as re: localctx.exception = re @@ -790,9 +796,9 @@ def moveCommand(self): self.enterRule(localctx, 20, self.RULE_moveCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 107 + self.state = 109 self.moveOp() - self.state = 108 + self.state = 110 self.expression(0) except RecognitionException as re: localctx.exception = re @@ -829,7 +835,7 @@ def moveOp(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 110 + self.state = 112 _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13))) != 0)): self._errHandler.recoverInline(self) @@ -871,7 +877,7 @@ def penCommand(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 112 + self.state = 114 _la = self._input.LA(1) if not(_la==tlangParser.T__14 or _la==tlangParser.T__15): self._errHandler.recoverInline(self) @@ -912,7 +918,7 @@ def pauseCommand(self): self.enterRule(localctx, 26, self.RULE_pauseCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 114 + self.state = 116 self.match(tlangParser.T__16) except RecognitionException as re: localctx.exception = re @@ -951,9 +957,9 @@ def assertionCommand(self): self.enterRule(localctx, 28, self.RULE_assertionCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 116 + self.state = 118 self.match(tlangParser.T__17) - self.state = 117 + self.state = 119 self.condition(0) except RecognitionException as re: localctx.exception = re @@ -1016,6 +1022,29 @@ def accept(self, visitor:ParseTreeVisitor): return visitor.visitChildren(self) + class ModExprContext(ExpressionContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a tlangParser.ExpressionContext + super().__init__(parser) + self.copyFrom(ctx) + + def expression(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(tlangParser.ExpressionContext) + else: + return self.getTypedRuleContext(tlangParser.ExpressionContext,i) + + def modulo(self): + return self.getTypedRuleContext(tlangParser.ModuloContext,0) + + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitModExpr" ): + return visitor.visitModExpr(self) + else: + return visitor.visitChildren(self) + + class AddExprContext(ExpressionContext): def __init__(self, parser, ctx:ParserRuleContext): # actually a tlangParser.ExpressionContext @@ -1089,7 +1118,7 @@ def expression(self, _p:int=0): self.enterRecursionRule(localctx, 30, self.RULE_expression, _p) try: self.enterOuterAlt(localctx, 1) - self.state = 128 + self.state = 130 self._errHandler.sync(self) token = self._input.LA(1) if token in [tlangParser.MINUS]: @@ -1097,34 +1126,34 @@ def expression(self, _p:int=0): self._ctx = localctx _prevctx = localctx - self.state = 120 + self.state = 122 self.unaryArithOp() - self.state = 121 - self.expression(5) + self.state = 123 + self.expression(6) pass elif token in [tlangParser.NUM, tlangParser.VAR]: localctx = tlangParser.ValueExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 123 + self.state = 125 self.value() pass elif token in [tlangParser.T__6]: localctx = tlangParser.ParenExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 124 + self.state = 126 self.match(tlangParser.T__6) - self.state = 125 + self.state = 127 self.expression(0) - self.state = 126 + self.state = 128 self.match(tlangParser.T__8) pass else: raise NoViableAltException(self) self._ctx.stop = self._input.LT(-1) - self.state = 140 + self.state = 146 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,6,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: @@ -1132,37 +1161,50 @@ def expression(self, _p:int=0): if self._parseListeners is not None: self.triggerExitRuleEvent() _prevctx = localctx - self.state = 138 + self.state = 144 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,5,self._ctx) if la_ == 1: localctx = tlangParser.MulExprContext(self, tlangParser.ExpressionContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expression) - self.state = 130 - if not self.precpred(self._ctx, 4): + self.state = 132 + if not self.precpred(self._ctx, 5): from antlr4.error.Errors import FailedPredicateException - raise FailedPredicateException(self, "self.precpred(self._ctx, 4)") - self.state = 131 + raise FailedPredicateException(self, "self.precpred(self._ctx, 5)") + self.state = 133 self.multiplicative() - self.state = 132 - self.expression(5) + self.state = 134 + self.expression(6) pass elif la_ == 2: localctx = tlangParser.AddExprContext(self, tlangParser.ExpressionContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expression) - self.state = 134 + self.state = 136 + if not self.precpred(self._ctx, 4): + from antlr4.error.Errors import FailedPredicateException + raise FailedPredicateException(self, "self.precpred(self._ctx, 4)") + self.state = 137 + self.additive() + self.state = 138 + self.expression(5) + pass + + elif la_ == 3: + localctx = tlangParser.ModExprContext(self, tlangParser.ExpressionContext(self, _parentctx, _parentState)) + self.pushNewRecursionContext(localctx, _startState, self.RULE_expression) + self.state = 140 if not self.precpred(self._ctx, 3): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 3)") - self.state = 135 - self.additive() - self.state = 136 + self.state = 141 + self.modulo() + self.state = 142 self.expression(4) pass - self.state = 142 + self.state = 148 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,6,self._ctx) @@ -1206,7 +1248,7 @@ def multiplicative(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 143 + self.state = 149 _la = self._input.LA(1) if not(_la==tlangParser.MUL or _la==tlangParser.DIV): self._errHandler.recoverInline(self) @@ -1253,7 +1295,7 @@ def additive(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 145 + self.state = 151 _la = self._input.LA(1) if not(_la==tlangParser.PLUS or _la==tlangParser.MINUS): self._errHandler.recoverInline(self) @@ -1269,6 +1311,44 @@ def additive(self): return localctx + class ModuloContext(ParserRuleContext): + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + def MOD(self): + return self.getToken(tlangParser.MOD, 0) + + def getRuleIndex(self): + return tlangParser.RULE_modulo + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitModulo" ): + return visitor.visitModulo(self) + else: + return visitor.visitChildren(self) + + + + + def modulo(self): + + localctx = tlangParser.ModuloContext(self, self._ctx, self.state) + self.enterRule(localctx, 36, self.RULE_modulo) + try: + self.enterOuterAlt(localctx, 1) + self.state = 153 + self.match(tlangParser.MOD) + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + class UnaryArithOpContext(ParserRuleContext): def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): @@ -1293,10 +1373,10 @@ def accept(self, visitor:ParseTreeVisitor): def unaryArithOp(self): localctx = tlangParser.UnaryArithOpContext(self, self._ctx, self.state) - self.enterRule(localctx, 36, self.RULE_unaryArithOp) + self.enterRule(localctx, 38, self.RULE_unaryArithOp) try: self.enterOuterAlt(localctx, 1) - self.state = 147 + self.state = 155 self.match(tlangParser.MINUS) except RecognitionException as re: localctx.exception = re @@ -1357,46 +1437,46 @@ def condition(self, _p:int=0): _parentState = self.state localctx = tlangParser.ConditionContext(self, self._ctx, _parentState) _prevctx = localctx - _startState = 38 - self.enterRecursionRule(localctx, 38, self.RULE_condition, _p) + _startState = 40 + self.enterRecursionRule(localctx, 40, self.RULE_condition, _p) try: self.enterOuterAlt(localctx, 1) - self.state = 161 + self.state = 169 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,7,self._ctx) if la_ == 1: - self.state = 150 + self.state = 158 self.match(tlangParser.NOT) - self.state = 151 + self.state = 159 self.condition(5) pass elif la_ == 2: - self.state = 152 + self.state = 160 self.expression(0) - self.state = 153 + self.state = 161 self.binCondOp() - self.state = 154 + self.state = 162 self.expression(0) pass elif la_ == 3: - self.state = 156 + self.state = 164 self.match(tlangParser.PENCOND) pass elif la_ == 4: - self.state = 157 + self.state = 165 self.match(tlangParser.T__6) - self.state = 158 + self.state = 166 self.condition(0) - self.state = 159 + self.state = 167 self.match(tlangParser.T__8) pass self._ctx.stop = self._input.LT(-1) - self.state = 169 + self.state = 177 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,8,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: @@ -1406,15 +1486,15 @@ def condition(self, _p:int=0): _prevctx = localctx localctx = tlangParser.ConditionContext(self, _parentctx, _parentState) self.pushNewRecursionContext(localctx, _startState, self.RULE_condition) - self.state = 163 + self.state = 171 if not self.precpred(self._ctx, 3): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 3)") - self.state = 164 + self.state = 172 self.logicOp() - self.state = 165 + self.state = 173 self.condition(4) - self.state = 171 + self.state = 179 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,8,self._ctx) @@ -1466,11 +1546,11 @@ def accept(self, visitor:ParseTreeVisitor): def binCondOp(self): localctx = tlangParser.BinCondOpContext(self, self._ctx, self.state) - self.enterRule(localctx, 40, self.RULE_binCondOp) + self.enterRule(localctx, 42, self.RULE_binCondOp) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 172 + self.state = 180 _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.LT) | (1 << tlangParser.GT) | (1 << tlangParser.EQ) | (1 << tlangParser.NEQ) | (1 << tlangParser.LTE) | (1 << tlangParser.GTE))) != 0)): self._errHandler.recoverInline(self) @@ -1513,11 +1593,11 @@ def accept(self, visitor:ParseTreeVisitor): def logicOp(self): localctx = tlangParser.LogicOpContext(self, self._ctx, self.state) - self.enterRule(localctx, 42, self.RULE_logicOp) + self.enterRule(localctx, 44, self.RULE_logicOp) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 174 + self.state = 182 _la = self._input.LA(1) if not(_la==tlangParser.AND or _la==tlangParser.OR): self._errHandler.recoverInline(self) @@ -1560,11 +1640,11 @@ def accept(self, visitor:ParseTreeVisitor): def value(self): localctx = tlangParser.ValueContext(self, self._ctx, self.state) - self.enterRule(localctx, 44, self.RULE_value) + self.enterRule(localctx, 46, self.RULE_value) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 176 + self.state = 184 _la = self._input.LA(1) if not(_la==tlangParser.NUM or _la==tlangParser.VAR): self._errHandler.recoverInline(self) @@ -1585,7 +1665,7 @@ def sempred(self, localctx:RuleContext, ruleIndex:int, predIndex:int): if self._predicates == None: self._predicates = dict() self._predicates[15] = self.expression_sempred - self._predicates[19] = self.condition_sempred + self._predicates[20] = self.condition_sempred pred = self._predicates.get(ruleIndex, None) if pred is None: raise Exception("No predicate with index:" + str(ruleIndex)) @@ -1594,15 +1674,19 @@ def sempred(self, localctx:RuleContext, ruleIndex:int, predIndex:int): def expression_sempred(self, localctx:ExpressionContext, predIndex:int): if predIndex == 0: - return self.precpred(self._ctx, 4) + return self.precpred(self._ctx, 5) if predIndex == 1: + return self.precpred(self._ctx, 4) + + + if predIndex == 2: return self.precpred(self._ctx, 3) def condition_sempred(self, localctx:ConditionContext, predIndex:int): - if predIndex == 2: + if predIndex == 3: return self.precpred(self._ctx, 3) diff --git a/ChironCore/turtparse/tlangVisitor.py b/ChironCore/turtparse/tlangVisitor.py index f027ccb..f1fbdb4 100644 --- a/ChironCore/turtparse/tlangVisitor.py +++ b/ChironCore/turtparse/tlangVisitor.py @@ -94,6 +94,11 @@ def visitValueExpr(self, ctx:tlangParser.ValueExprContext): return self.visitChildren(ctx) + # Visit a parse tree produced by tlangParser#modExpr. + def visitModExpr(self, ctx:tlangParser.ModExprContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by tlangParser#addExpr. def visitAddExpr(self, ctx:tlangParser.AddExprContext): return self.visitChildren(ctx) @@ -119,6 +124,11 @@ def visitAdditive(self, ctx:tlangParser.AdditiveContext): return self.visitChildren(ctx) + # Visit a parse tree produced by tlangParser#modulo. + def visitModulo(self, ctx:tlangParser.ModuloContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by tlangParser#unaryArithOp. def visitUnaryArithOp(self, ctx:tlangParser.UnaryArithOpContext): return self.visitChildren(ctx) From 218e700fc7e4c6b9e9df4abf231f4b4e213e0151 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Tue, 18 Mar 2025 01:46:18 +0530 Subject: [PATCH 26/53] fixed bugs --- ChironCore/bmc.py | 13 ++++++++----- ChironCore/chiron.py | 2 +- ChironCore/example/move1.tl | 8 ++++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 9e96644..1b86315 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -148,12 +148,12 @@ def convertSSAtoSMT(self): elif isinstance(stmt, ChironSSA.DegToRadCommand): rvar = None - if isinstance(stmt.rvar1, ChironSSA.Var): - rvar = z3.Real(stmt.rvar1.name) - elif isinstance(stmt.rvar1, ChironSSA.Num): - rvar = z3.RealVal(stmt.rvar1.value) + if isinstance(stmt.rvar, ChironSSA.Var): + rvar = z3.Real(stmt.rvar.name) + elif isinstance(stmt.rvar, ChironSSA.Num): + rvar = z3.RealVal(stmt.rvar.value) lvar = z3.Real(stmt.lvar.name) - self.solver.add(lvar == (rvar * 3.141592653589793 / 180)) + self.solver.add(lvar == (rvar * 3.14 / 180)) # elif isinstance(stmt, ChironSSA.CosCommand): # Problem: z3.Cos, z3.Sin is not supported # self.solver.add(z3.Real(stmt.lvar.name) == z3.Cos(z3.Real(stmt.rvar1.name))) @@ -173,6 +173,9 @@ def convertSSAtoSMT(self): # raise Exception("Unknown SSA instruction") def solve(self, inputVars): + print("The clauses are:") + print(self.solver, end="\n\n") + sat = self.solver.check() if sat == z3.sat: print("Condition not satisfied! Bug found for the following input:") diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 5516822..9bd6654 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -418,7 +418,7 @@ def stopTurtle(): cfgB.dumpCFG(ssaCfg, 'ssa_cfg') # Saving SSA Form of the program to file ssa_cfg.png - #print("\nConverting program to SMT-LIB format..\n") + print("\nConverting program to SMT-LIB format..\n") smt = bmc.BMC(ssaCfg) smt.convertSSAtoSMT() smt.solve(tacGen.getFreeVariables()) diff --git a/ChironCore/example/move1.tl b/ChironCore/example/move1.tl index c7f3752..7450f3f 100644 --- a/ChironCore/example/move1.tl +++ b/ChironCore/example/move1.tl @@ -1,8 +1,8 @@ -if (1 < 0) [ +if (1 > 0) [ :x = 10 - left 50 + // left 50 ] else [ - :x = 30 - right 50 + :x = 10 ] +assert :x == 10 forward :x \ No newline at end of file From d3ec4f2e7b96f5ba7f317de6819631ac91bcab3a Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 18 Mar 2025 18:36:31 +0530 Subject: [PATCH 27/53] fix SSA --- ChironCore/ChironSSA/builder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChironCore/ChironSSA/builder.py b/ChironCore/ChironSSA/builder.py index c20d79a..d009be0 100644 --- a/ChironCore/ChironSSA/builder.py +++ b/ChironCore/ChironSSA/builder.py @@ -52,12 +52,12 @@ def rename(self, block): instr.lvar = self.new_name(instr.lvar.name) elif isinstance(instr, ChironSSA.AssignmentCommand): - temp.add(instr.lvar.name) - instr.lvar = self.new_name(instr.lvar.name) if isinstance(instr.rvar1, ChironSSA.Var): instr.rvar1 = ChironSSA.Var(instr.rvar1.name + "$" + str(self.stack[instr.rvar1.name][-1])) if isinstance(instr.rvar2, ChironSSA.Var): instr.rvar2 = ChironSSA.Var(instr.rvar2.name + "$" + str(self.stack[instr.rvar2.name][-1])) + temp.add(instr.lvar.name) + instr.lvar = self.new_name(instr.lvar.name) elif isinstance(instr, ChironSSA.AssertCommand): if isinstance(instr.cond, ChironSSA.Var): From 9470acad6b71c4c6e4cdb3e8ddffbb36832d3645 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 18 Mar 2025 18:36:49 +0530 Subject: [PATCH 28/53] modify BMC to check unknown verdict --- ChironCore/bmc.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 1b86315..5017b8f 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -184,7 +184,8 @@ def solve(self, inputVars): varname = str(var).split("$")[0] if varname in inputVars: print(varname + " = " + str(model[var])) - + elif sat == z3.unsat: + print("Condition satisfied for all inputs!") else: - print("Condition always holds true!") + print("Unknown") From 80fc3be98e665315edf59d5ece1f22959d40fb26 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 18 Mar 2025 23:18:35 +0530 Subject: [PATCH 29/53] add loop unrolling --- ChironCore/bmc.py | 5 +- ChironCore/chiron.py | 11 +++++ ChironCore/example/move.tl | 39 ++------------- ChironCore/irhandler.py | 2 +- ChironCore/unroll.py | 99 +++++++++++++++++++++++++++++++++++++ ChironCore/unrolled_code.tl | 35 +++++++++++++ 6 files changed, 154 insertions(+), 37 deletions(-) create mode 100644 ChironCore/unroll.py create mode 100644 ChironCore/unrolled_code.tl diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 5017b8f..b593f48 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -181,9 +181,10 @@ def solve(self, inputVars): print("Condition not satisfied! Bug found for the following input:") model = self.solver.model() for var in model: - varname = str(var).split("$")[0] - if varname in inputVars: + varname, index = str(var).split("$") + if varname in inputVars and index == "0": print(varname + " = " + str(model[var])) + elif sat == z3.unsat: print("Condition satisfied for all inputs!") else: diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 9bd6654..80fef83 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -22,6 +22,7 @@ import sExecution as se import cfg.cfgBuilder as cfgB import bmc as bmc +import unroll as unroll from ChironTAC.builder import * from ChironSSA.builder import * import submissionDFA as DFASub @@ -212,6 +213,7 @@ def stopTurtle(): if not (type(args.params) is dict): raise ValueError("Wrong type for command line arguement '-d' or '--params'.") + # Instantiate the irHandler # this object is passed around everywhere. irHandler = IRHandler(ir) @@ -405,6 +407,15 @@ def stopTurtle(): if args.bmc: print("\nBounded Model Checking..") + print("Unrolling the program with bound ", 5) + unrolled_code = unroll.UnrollLoops(5).visitStart(getParseTree(args.progfl)) + # write to file + with open("unrolled_code.tl", "w") as f: + f.write(unrolled_code) + + parseTree = getParseTree("unrolled_code.tl") + astgen = astGenPass() + ir = astgen.visitStart(parseTree) tacGen = TACGenerator(ir) # Converting IR to TAC tacGen.generateTAC() diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index d379fc0..4cc48bc 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,38 +1,9 @@ -if (:a > :b + :c) [ - :result = :a - :b - if (:c > :a - :b) [ - :result = :result + :c - :a - if (:result < :b - :c) [ - :result = :result + :b + :b - ] else [ - :result = :result - :c - :c - ] - ] else [ - :result = :a + :c - if (:a + :c - :b > :result) [ - :result = :result + :a - :b - :b - ] else [ - :result = :result - :a + :b + :b - ] - ] -] else [ - :result = :b + :c - if (:b + :c - :a < :a + :a) [ - :result = :result - :a - :a - if (:result + :b > 0) [ - :result = :result + :b + :b - :c - ] else [ - :result = :result + :c + :c - :b - ] - ] else [ - :result = :a + :a + :a - if (:result - :c < :b + :b) [ - :result = :result + :b + :b + :b - ] else [ - :result = :result - :c - :c - :c - ] +repeat 3 [ + repeat 4 [ + :x = :y + 2 ] + :z = :x + 1 ] -// goto (:result, 0) +assert :y >= :x diff --git a/ChironCore/irhandler.py b/ChironCore/irhandler.py index 26bb124..ca75be1 100644 --- a/ChironCore/irhandler.py +++ b/ChironCore/irhandler.py @@ -133,4 +133,4 @@ def pretty_print(self, irList): "The number after the opcode name represents the jump offset \nrelative to that statement.\n" ) for idx, item in enumerate(irList): - print(f"[L{idx}]".rjust(5), item[0], f"[{item[1]}]") \ No newline at end of file + print(f"[L{idx}]".rjust(5), item[0], f"[{item[1]}]") diff --git a/ChironCore/unroll.py b/ChironCore/unroll.py new file mode 100644 index 0000000..646dbd3 --- /dev/null +++ b/ChironCore/unroll.py @@ -0,0 +1,99 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# ChironLang Abstract Syntax Tree Builder +from turtparse.tlangParser import tlangParser +from turtparse.tlangVisitor import tlangVisitor + +class UnrollLoops(tlangVisitor): + def __init__(self, bound): + self.bound = bound + pass + + def visitStart(self, ctx:tlangParser.StartContext): + stmtList = self.visit(ctx.instruction_list()) + return stmtList + + def visitInstruction_list(self, ctx:tlangParser.Instruction_listContext): + code = "" + for instr in ctx.instruction(): + code += self.visit(instr) + "\n" + + return code + + def visitStrict_ilist(self, ctx:tlangParser.Strict_ilistContext): + code = "" + for instr in ctx.instruction(): + code += self.visit(instr) + "\n" + + return code + + + def visitAssignment(self, ctx:tlangParser.AssignmentContext): + return ctx.getText() + + def visitIfConditional(self, ctx:tlangParser.IfConditionalContext): + condition = self.visit(ctx.condition()) + ifBlock = self.visit(ctx.strict_ilist()) + return "if (" + condition + ") [\n" + ifBlock + "\n]" + + def visitIfElseConditional(self, ctx:tlangParser.IfElseConditionalContext): + condition = self.visit(ctx.condition()) + ifBlock = self.visit(ctx.strict_ilist(0)) + elseBlock = self.visit(ctx.strict_ilist(1)) + return "if (" + condition + ") [\n" + ifBlock + "\n] else [\n" + elseBlock + "\n]" + + def visitGotoCommand(self, ctx:tlangParser.GotoCommandContext): + xcor = self.visit(ctx.expression(0)) + ycor = self.visit(ctx.expression(1)) + return "goto (" + xcor + ", " + ycor + ")" + + # Visit a parse tree produced by tlangParser#unaryExpr. + def visitUnaryExpr(self, ctx:tlangParser.UnaryExprContext): + return ctx.getText() + + # Visit a parse tree produced by tlangParser#addExpr. + def visitAddExpr(self, ctx:tlangParser.AddExprContext): + return ctx.getText() + + # Visit a parse tree produced by tlangParser#mulExpr. + def visitMulExpr(self, ctx:tlangParser.MulExprContext): + return ctx.getText() + + # Visit a parse tree produced by tlangParser#valueExpr. + def visitModExpr(self, ctx:tlangParser.ModExprContext): + return ctx.getText() + + # Visit a parse tree produced by tlangParser#parenExpr. + def visitParenExpr(self, ctx:tlangParser.ParenExprContext): + return ctx.getText() + + def visitCondition(self, ctx:tlangParser.ConditionContext): + return ctx.getText() + + def visitValue(self, ctx:tlangParser.ValueContext): + return ctx.getText() + + def visitLoop(self, ctx:tlangParser.LoopContext): + repeatCount = self.visit(ctx.value()) + loopBlock = self.visit(ctx.strict_ilist()) + code = "" + if (repeatCount[0] != ":"): + # constant number of iterations + for i in range(min(int(repeatCount), self.bound)): + code += loopBlock + "\n" + else: + # variable number of iterations + for i in range(self.bound): + code += "if (" + repeatCount + " > " + str(i) + ") [\n" + loopBlock + "\n]\n" + + return code + + def visitMoveCommand(self, ctx:tlangParser.MoveCommandContext): + return ctx.getText() + + def visitPenCommand(self, ctx:tlangParser.PenCommandContext): + return ctx.getText() + + def visitAssertionCommand(self, ctx:tlangParser.AssertionCommandContext): + return ctx.getText() + diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl new file mode 100644 index 0000000..719ffb6 --- /dev/null +++ b/ChironCore/unrolled_code.tl @@ -0,0 +1,35 @@ +:x=:y+2 + +:x=:y+2 + +:x=:y+2 + +:x=:y+2 + + +:z=:x+1 + +:x=:y+2 + +:x=:y+2 + +:x=:y+2 + +:x=:y+2 + + +:z=:x+1 + +:x=:y+2 + +:x=:y+2 + +:x=:y+2 + +:x=:y+2 + + +:z=:x+1 + + +assert:y>=:x From ba2923724d46b945823d2a609459279229480d39 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Wed, 19 Mar 2025 15:25:24 +0530 Subject: [PATCH 30/53] included termainal functionalities --- ChironCore/bmc.py | 4 ++-- ChironCore/chiron.py | 38 +++++++++++++++++++++++++++++++----- ChironCore/example/move.tl | 8 ++++---- ChironCore/example/move1.tl | 8 +++++--- ChironCore/irhandler.py | 2 +- ChironCore/unrolled_code.tl | 39 ++++++++++--------------------------- 6 files changed, 55 insertions(+), 44 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index b593f48..8ee8f76 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -173,8 +173,8 @@ def convertSSAtoSMT(self): # raise Exception("Unknown SSA instruction") def solve(self, inputVars): - print("The clauses are:") - print(self.solver, end="\n\n") + # print("The clauses are:") + # print(self.solver, end="\n\n") sat = self.solver.check() if sat == z3.sat: diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 80fef83..81fc06a 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -203,7 +203,8 @@ def stopTurtle(): cmdparser.add_argument( "-bmc", "--bmc", - type=str, + # type=str, + action="store_true", help="Run Bounded Model Checking on a Chiron Program.", ) @@ -406,12 +407,39 @@ def stopTurtle(): print("DONE..") if args.bmc: - print("\nBounded Model Checking..") - print("Unrolling the program with bound ", 5) - unrolled_code = unroll.UnrollLoops(5).visitStart(getParseTree(args.progfl)) + print("\nBounded Model Checking...") + unroll_bound = int(input("Enter the unroll bound for the program: ")) + # unroll_bound = 5 + if unroll_bound < 1: + print("Invalid unroll bound. Exiting..") + exit(1) + + unrolled_code = unroll.UnrollLoops(unroll_bound).visitStart(getParseTree(args.progfl)) + + cond_count = int(input("Enter the number of conditions in the program: ")) + # cond_count = 1 + if cond_count < 1: + print("Invalid number of conditions. Exiting..") + exit(1) + + # cond = [":turtlex == 1"] + cond = [] + for i in range(cond_count): + cond.append(input(f"Enter condition {i+1}: ")) + + assert_stmt = "assert (" + cond[0] +")" + for i in range(1, cond_count): + assert_stmt = assert_stmt + " && (" + cond[i] + ")" + + print(unrolled_code) + + unrolled_code_lines = unrolled_code.split('\n') + unrolled_code_lines = [line for line in unrolled_code_lines if line != ""] + unrolled_code_with_asserts = '\n'.join([line + '\n' + assert_stmt for line in unrolled_code_lines]) + # write to file with open("unrolled_code.tl", "w") as f: - f.write(unrolled_code) + f.write(unrolled_code_with_asserts) parseTree = getParseTree("unrolled_code.tl") astgen = astGenPass() diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 4cc48bc..6c1296f 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,9 +1,9 @@ -repeat 3 [ - repeat 4 [ +:y = 4 +repeat 2 [ + repeat 2 [ :x = :y + 2 ] :z = :x + 1 ] -assert :y >= :x - +:_debraj = 1 \ No newline at end of file diff --git a/ChironCore/example/move1.tl b/ChironCore/example/move1.tl index 7450f3f..d2692fd 100644 --- a/ChironCore/example/move1.tl +++ b/ChironCore/example/move1.tl @@ -1,8 +1,10 @@ -if (1 > 0) [ - :x = 10 +if (:p > 0) [ + :x = 20 + :f = :x * 2 + :x + backward :x // left 50 ] else [ :x = 10 ] -assert :x == 10 +assert :x == 20 forward :x \ No newline at end of file diff --git a/ChironCore/irhandler.py b/ChironCore/irhandler.py index ca75be1..3e0af2a 100644 --- a/ChironCore/irhandler.py +++ b/ChironCore/irhandler.py @@ -10,7 +10,7 @@ def getParseTree(progfl): input_stream = antlr4.FileStream(progfl) - print(input_stream) + # print(input_stream) try: lexer = tlangLexer(input_stream) stream = antlr4.CommonTokenStream(lexer) diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 719ffb6..1a04ec0 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,35 +1,16 @@ +:y=4 +assert (:debraj > 3) :x=:y+2 - +assert (:debraj > 3) :x=:y+2 - -:x=:y+2 - -:x=:y+2 - - +assert (:debraj > 3) :z=:x+1 - -:x=:y+2 - -:x=:y+2 - -:x=:y+2 - -:x=:y+2 - - -:z=:x+1 - -:x=:y+2 - -:x=:y+2 - +assert (:debraj > 3) :x=:y+2 - +assert (:debraj > 3) :x=:y+2 - - +assert (:debraj > 3) :z=:x+1 - - -assert:y>=:x +assert (:debraj > 3) +:_debraj=1 +assert (:debraj > 3) \ No newline at end of file From c00d9f6cc829e13475106031155da3007246d716 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Wed, 19 Mar 2025 16:48:00 +0530 Subject: [PATCH 31/53] fixed assert bug --- ChironCore/ChironTAC/builder.py | 42 ++++++++++++++++----------------- ChironCore/bmc.py | 19 ++++++++++----- ChironCore/chiron.py | 11 +++++---- ChironCore/example/move.tl | 11 ++------- ChironCore/unrolled_code.tl | 20 ++++------------ 5 files changed, 46 insertions(+), 57 deletions(-) diff --git a/ChironCore/ChironTAC/builder.py b/ChironCore/ChironTAC/builder.py index 19def3e..10d634d 100644 --- a/ChironCore/ChironTAC/builder.py +++ b/ChironCore/ChironTAC/builder.py @@ -291,26 +291,26 @@ def generateTAC(self): self.tac.append((ChironTAC.MoveCommand(stmt.direction, movevar), 1)) if (stmt.direction == "forward" or stmt.direction == "backward"): self.line += 6 - self.tac.append((ChironTAC.CosCommand(ChironTAC.Var(":__cos_theta"), ChironTAC.Var(":__turtle_theta_rad")), 1)) - self.tac.append((ChironTAC.SinCommand(ChironTAC.Var(":__sin_theta"), ChironTAC.Var(":__turtle_theta_rad")), 1)) + self.tac.append((ChironTAC.CosCommand(ChironTAC.Var(":__cos_theta"), ChironTAC.Var(":turtleThetaRad")), 1)) + self.tac.append((ChironTAC.SinCommand(ChironTAC.Var(":__sin_theta"), ChironTAC.Var(":turtleThetaRad")), 1)) self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__delta_x"), movevar, ChironTAC.Var(":__cos_theta"), "*"), 1)) self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__delta_y"), movevar, ChironTAC.Var(":__sin_theta"), "*"), 1)) if (stmt.direction == "forward"): - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__delta_x"), "+"), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__delta_y"), "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleX"), ChironTAC.Var(":turtleX"), ChironTAC.Var(":__delta_x"), "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleY"), ChironTAC.Var(":turtleY"), ChironTAC.Var(":__delta_y"), "+"), 1)) elif (stmt.direction == "backward"): - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__turtle_x"), ChironTAC.Var(":__delta_x"), "-"), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__turtle_y"), ChironTAC.Var(":__delta_y"), "-"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleX"), ChironTAC.Var(":turtleX"), ChironTAC.Var(":__delta_x"), "-"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleY"), ChironTAC.Var(":turtleY"), ChironTAC.Var(":__delta_y"), "-"), 1)) elif (stmt.direction == "left"): self.line += 3 - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Var(":__turtle_theta_deg"), movevar, "-"), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Num(360), "%"), 1)) - self.tac.append((ChironTAC.DegToRadCommand(ChironTAC.Var(":__turtle_theta_rad"), ChironTAC.Var(":__turtle_theta_deg")), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), movevar, "-"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Num(360), "%"), 1)) + self.tac.append((ChironTAC.DegToRadCommand(ChironTAC.Var(":turtleThetaRad"), ChironTAC.Var(":turtleThetaDeg")), 1)) elif (stmt.direction == "right"): self.line += 3 - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Var(":__turtle_theta_deg"), movevar, "+"), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Num(360), "%"), 1)) - self.tac.append((ChironTAC.DegToRadCommand(ChironTAC.Var(":__turtle_theta_rad"), ChironTAC.Var(":__turtle_theta_deg")), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), movevar, "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Num(360), "%"), 1)) + self.tac.append((ChironTAC.DegToRadCommand(ChironTAC.Var(":turtleThetaRad"), ChironTAC.Var(":turtleThetaDeg")), 1)) else: raise NotImplementedError("Unknown move direction: %s, %s." % (type(stmt), stmt)) @@ -318,9 +318,9 @@ def generateTAC(self): self.line += 2 self.tac.append((ChironTAC.PenCommand(stmt.status), 1)) if (stmt.status == "penup"): - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(1), ChironTAC.Num(0), "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtlePen"), ChironTAC.Num(1), ChironTAC.Num(0), "+"), 1)) elif (stmt.status == "pendown"): - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtlePen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) else: raise NotImplementedError("Unknown pen status: %s, %s." % (type(stmt), stmt)) @@ -345,8 +345,8 @@ def generateTAC(self): self.parseExpresssion(stmt.ycor, yvar) self.line += 3 self.tac.append((ChironTAC.GotoCommand(xvar, yvar), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), xvar, ChironTAC.Num(0), "+"), 1)) - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), yvar, ChironTAC.Num(0), "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleX"), xvar, ChironTAC.Num(0), "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleY"), yvar, ChironTAC.Num(0), "+"), 1)) elif isinstance(stmt, ChironAST.NoOpCommand): self.line += 1 @@ -379,11 +379,11 @@ def handleFreeVariables(self): self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(var), ChironTAC.Unused(), ChironTAC.Unused(), ""), 1)) def handleMoveVariables(self): - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_x"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_y"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_deg"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_theta_rad"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":__turtle_pen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) # 0->down 1->up + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleX"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleY"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaRad"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) + self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":turtlePen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) # 0->down 1->up def getFreeVariables(self): """ diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 8ee8f76..4c96673 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -48,6 +48,7 @@ def buildConditions(self): self.bbConditions[node] = node.get_condition() def convertSSAtoSMT(self): + assert_conditions = z3.BoolVal(True) for bb in self.cfg.nodes(): for stmt, _ in bb.instrlist: if isinstance(stmt, ChironSSA.PhiCommand): @@ -144,7 +145,7 @@ def convertSSAtoSMT(self): cond = z3.BoolVal(False) elif isinstance(stmt.cond, ChironSSA.Var): cond = z3.Bool(stmt.cond.name) - self.solver.add(z3.Not(cond)) + assert_conditions = z3.And(assert_conditions, cond) elif isinstance(stmt, ChironSSA.DegToRadCommand): rvar = None @@ -160,9 +161,12 @@ def convertSSAtoSMT(self): # elif isinstance(stmt, ChironSSA.SinCommand): # self.solver.add(z3.Real(stmt.lvar.name) == z3.Sin(z3.Real(stmt.rvar1.name))) - # elif isinstance(stmt, ChironSSA.MoveCommand): - # elif isinstance(stmt, ChironSSA.PenCommand): - # elif isinstance(stmt, ChironSSA.GotoCommand): + elif isinstance(stmt, ChironSSA.MoveCommand): + pass + elif isinstance(stmt, ChironSSA.PenCommand): + pass + elif isinstance(stmt, ChironSSA.GotoCommand): + pass elif isinstance(stmt, ChironSSA.ConditionCommand): pass elif isinstance(stmt, ChironSSA.NoOpCommand): @@ -171,10 +175,13 @@ def convertSSAtoSMT(self): pass # else: # raise Exception("Unknown SSA instruction") + + assert_conditions = z3.Tactic('ctx-simplify').apply(assert_conditions).as_expr() + self.solver.add(z3.Not(assert_conditions)) def solve(self, inputVars): - # print("The clauses are:") - # print(self.solver, end="\n\n") + print("The clauses are:") + print(self.solver, end="\n\n") sat = self.solver.check() if sat == z3.sat: diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 81fc06a..08e4eb0 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -410,6 +410,7 @@ def stopTurtle(): print("\nBounded Model Checking...") unroll_bound = int(input("Enter the unroll bound for the program: ")) # unroll_bound = 5 + if unroll_bound < 1: print("Invalid unroll bound. Exiting..") exit(1) @@ -418,20 +419,20 @@ def stopTurtle(): cond_count = int(input("Enter the number of conditions in the program: ")) # cond_count = 1 + if cond_count < 1: print("Invalid number of conditions. Exiting..") exit(1) - # cond = [":turtlex == 1"] + # cond = [":turtleX == 0"] cond = [] for i in range(cond_count): cond.append(input(f"Enter condition {i+1}: ")) - assert_stmt = "assert (" + cond[0] +")" + cond_stmt = "(" + cond[0] +")" for i in range(1, cond_count): - assert_stmt = assert_stmt + " && (" + cond[i] + ")" - - print(unrolled_code) + cond_stmt = cond_stmt + " && (" + cond[i] + ")" + assert_stmt = "assert " + cond_stmt unrolled_code_lines = unrolled_code.split('\n') unrolled_code_lines = [line for line in unrolled_code_lines if line != ""] diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 6c1296f..6014da9 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,9 +1,2 @@ -:y = 4 -repeat 2 [ - repeat 2 [ - :x = :y + 2 - ] - :z = :x + 1 -] - -:_debraj = 1 \ No newline at end of file +:d = 1 +assert :d == 2 \ No newline at end of file diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 1a04ec0..76a9fa9 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,16 +1,4 @@ -:y=4 -assert (:debraj > 3) -:x=:y+2 -assert (:debraj > 3) -:x=:y+2 -assert (:debraj > 3) -:z=:x+1 -assert (:debraj > 3) -:x=:y+2 -assert (:debraj > 3) -:x=:y+2 -assert (:debraj > 3) -:z=:x+1 -assert (:debraj > 3) -:_debraj=1 -assert (:debraj > 3) \ No newline at end of file +:d=1 +assert (:turtleX == 0) +assert:d==2 +assert (:turtleX == 0) \ No newline at end of file From 3965c573651b5b17367b3656a27937ae19fd20b7 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Wed, 19 Mar 2025 22:02:07 +0530 Subject: [PATCH 32/53] added sin and cos --- ChironCore/bmc.py | 39 +++++++++++++++++++++++++++++-------- ChironCore/chiron.py | 37 +++++++++++++++++++---------------- ChironCore/example/move.tl | 5 +++-- ChironCore/unrolled_code.tl | 7 +++---- 4 files changed, 57 insertions(+), 31 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 4c96673..9905344 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -65,6 +65,7 @@ def convertSSAtoSMT(self): lvar = None rvar1 = ChironSSA.Unused() rvar2 = ChironSSA.Unused() + if stmt.op in ["+", "-", "*", "/", "%"]: lvar = z3.Int(stmt.lvar.name) if isinstance(stmt.rvar1, ChironSSA.Var): @@ -106,7 +107,23 @@ def convertSSAtoSMT(self): elif stmt.op == "": continue else: - raise Exception("Unknown SSA instruction") + raise Exception("Unknown SSA instruction") + + if stmt.lvar.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$")): + lvar = z3.Real(stmt.lvar.name) + if isinstance(stmt.rvar1, ChironSSA.Var): + rvar1 = z3.Real(stmt.rvar1.name) + elif isinstance(stmt.rvar1, ChironSSA.Num): + rvar1 = z3.RealVal(stmt.rvar1.value) + if isinstance(stmt.rvar2, ChironSSA.Var): + rvar2 = z3.Real(stmt.rvar2.name) + elif isinstance(stmt.rvar2, ChironSSA.Num): + rvar2 = z3.RealVal(stmt.rvar2.value) + + if isinstance(stmt.rvar1, ChironSSA.Var) and stmt.rvar1.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$")): + rvar1 = z3.Real(stmt.rvar1.name) + if isinstance(stmt.rvar2, ChironSSA.Var) and stmt.rvar2.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$")): + rvar2 = z3.Real(stmt.rvar2.name) if stmt.op == "+": self.solver.add(lvar == (rvar1 + rvar2)) @@ -156,11 +173,16 @@ def convertSSAtoSMT(self): lvar = z3.Real(stmt.lvar.name) self.solver.add(lvar == (rvar * 3.14 / 180)) - # elif isinstance(stmt, ChironSSA.CosCommand): # Problem: z3.Cos, z3.Sin is not supported - # self.solver.add(z3.Real(stmt.lvar.name) == z3.Cos(z3.Real(stmt.rvar1.name))) - # elif isinstance(stmt, ChironSSA.SinCommand): - # self.solver.add(z3.Real(stmt.lvar.name) == z3.Sin(z3.Real(stmt.rvar1.name))) - + elif isinstance(stmt, ChironSSA.CosCommand): # Using taylor series + rvar = z3.Real(stmt.rvar.name) + rhs_expr = 1 - (rvar ** 2) / 2 + (rvar ** 4) / 24 - (rvar ** 6) / 720 + (rvar ** 8) / 40320 - (rvar ** 10) / 3628800 + (rvar ** 12) / 479001600 - (rvar ** 14) / 87178291200 + (rvar ** 16) / 20922789888000 - (rvar ** 18) / 6402373705728000 + (rvar ** 20) / 2432902008176640000 + self.solver.add(z3.Real(stmt.lvar.name) == rhs_expr) + + elif isinstance(stmt, ChironSSA.SinCommand): + rvar = z3.Real(stmt.rvar.name) + rhs_expr = rvar - (rvar ** 3) / 6 + (rvar ** 5) / 120 - (rvar ** 7) / 5040 + (rvar ** 9) / 362880 - (rvar ** 11) / 39916800 + (rvar ** 13) / 6227020800 - (rvar ** 15) / 1307674368000 + (rvar ** 17) / 355687428096000 - (rvar ** 19) / 121645100408832000 + (rvar ** 21) / 51090942171709440000 + self.solver.add(z3.Real(stmt.lvar.name) == rhs_expr) + elif isinstance(stmt, ChironSSA.MoveCommand): pass elif isinstance(stmt, ChironSSA.PenCommand): @@ -173,8 +195,8 @@ def convertSSAtoSMT(self): pass elif isinstance(stmt, ChironSSA.PauseCommand): pass - # else: - # raise Exception("Unknown SSA instruction") + else: + raise Exception("Unknown SSA instruction") assert_conditions = z3.Tactic('ctx-simplify').apply(assert_conditions).as_expr() self.solver.add(z3.Not(assert_conditions)) @@ -184,6 +206,7 @@ def solve(self, inputVars): print(self.solver, end="\n\n") sat = self.solver.check() + if sat == z3.sat: print("Condition not satisfied! Bug found for the following input:") model = self.solver.model() diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 08e4eb0..70974a9 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -409,7 +409,6 @@ def stopTurtle(): if args.bmc: print("\nBounded Model Checking...") unroll_bound = int(input("Enter the unroll bound for the program: ")) - # unroll_bound = 5 if unroll_bound < 1: print("Invalid unroll bound. Exiting..") @@ -418,29 +417,29 @@ def stopTurtle(): unrolled_code = unroll.UnrollLoops(unroll_bound).visitStart(getParseTree(args.progfl)) cond_count = int(input("Enter the number of conditions in the program: ")) - # cond_count = 1 - if cond_count < 1: + if cond_count < 0: print("Invalid number of conditions. Exiting..") exit(1) - # cond = [":turtleX == 0"] - cond = [] - for i in range(cond_count): - cond.append(input(f"Enter condition {i+1}: ")) + if cond_count != 0: + cond = [] + for i in range(cond_count): + cond.append(input(f"Enter condition {i+1}: ")) - cond_stmt = "(" + cond[0] +")" - for i in range(1, cond_count): - cond_stmt = cond_stmt + " && (" + cond[i] + ")" - assert_stmt = "assert " + cond_stmt + cond_stmt = "(" + cond[0] +")" + for i in range(1, cond_count): + cond_stmt = cond_stmt + " && (" + cond[i] + ")" + assert_stmt = "assert " + cond_stmt + + unrolled_code = unrolled_code + '\n' + assert_stmt # for adding asserts at the end + + # unrolled_code_lines = unrolled_code.split('\n') # for adding asserts after every line + # unrolled_code_lines = [line for line in unrolled_code_lines if line != ""] + # unrolled_code = '\n'.join([line + '\n' + assert_stmt for line in unrolled_code_lines]) - unrolled_code_lines = unrolled_code.split('\n') - unrolled_code_lines = [line for line in unrolled_code_lines if line != ""] - unrolled_code_with_asserts = '\n'.join([line + '\n' + assert_stmt for line in unrolled_code_lines]) - - # write to file with open("unrolled_code.tl", "w") as f: - f.write(unrolled_code_with_asserts) + f.write(unrolled_code) parseTree = getParseTree("unrolled_code.tl") astgen = astGenPass() @@ -450,6 +449,10 @@ def stopTurtle(): tacGen.generateTAC() # tacGen.printTAC() # Printing TAC + if tacGen.assertCount == 0: + print("No conditions found in the program. Exiting..") + exit(1) + cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) # Building CFG cfgB.dumpCFG(cfg, 'tac_cfg') diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 6014da9..5ddfb87 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,2 +1,3 @@ -:d = 1 -assert :d == 2 \ No newline at end of file +left 45 +forward 5 +assert :turtleX < 5 \ No newline at end of file diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 76a9fa9..9c32f75 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,4 +1,3 @@ -:d=1 -assert (:turtleX == 0) -assert:d==2 -assert (:turtleX == 0) \ No newline at end of file +left45 +forward5 +assert:turtleX<5 From a64c9e7e5668ab8fde11d91417fbbd2ef2207292 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Thu, 20 Mar 2025 10:26:50 +0530 Subject: [PATCH 33/53] fixed multiple solutions from z3 --- ChironCore/bmc.py | 6 +++++- ChironCore/chiron.py | 6 ++++-- ChironCore/example/move.tl | 6 +++--- ChironCore/unrolled_code.tl | 6 +++--- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 9905344..1c4b174 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -210,10 +210,14 @@ def solve(self, inputVars): if sat == z3.sat: print("Condition not satisfied! Bug found for the following input:") model = self.solver.model() + print(model) + solution = {} for var in model: varname, index = str(var).split("$") if varname in inputVars and index == "0": - print(varname + " = " + str(model[var])) + solution[varname] = model[var] + for var in solution: + print(var + " = " + str(solution[var])) elif sat == z3.unsat: print("Condition satisfied for all inputs!") diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 70974a9..10f123f 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -408,7 +408,8 @@ def stopTurtle(): if args.bmc: print("\nBounded Model Checking...") - unroll_bound = int(input("Enter the unroll bound for the program: ")) + # unroll_bound = int(input("Enter the unroll bound for the program: ")) + unroll_bound = 1 if unroll_bound < 1: print("Invalid unroll bound. Exiting..") @@ -416,7 +417,8 @@ def stopTurtle(): unrolled_code = unroll.UnrollLoops(unroll_bound).visitStart(getParseTree(args.progfl)) - cond_count = int(input("Enter the number of conditions in the program: ")) + # cond_count = int(input("Enter the number of conditions in the program: ")) + cond_count = 0 if cond_count < 0: print("Invalid number of conditions. Exiting..") diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 5ddfb87..7919c3f 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,3 +1,3 @@ -left 45 -forward 5 -assert :turtleX < 5 \ No newline at end of file +:x = :y + 1 +goto (:x, :y) +assert :turtleX > 0 \ No newline at end of file diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 9c32f75..f697126 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,3 +1,3 @@ -left45 -forward5 -assert:turtleX<5 +:x=:y+1 +goto (:x, :y) +assert:turtleX>0 From 2b8b37f137c4016aed2d3b2513540f0cbbd6996a Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Thu, 20 Mar 2025 10:41:41 +0530 Subject: [PATCH 34/53] fixed type conversion --- ChironCore/bmc.py | 12 +----------- ChironCore/chiron.py | 4 ++-- ChironCore/example/move.tl | 9 ++++++++- ChironCore/unrolled_code.tl | 13 ++++++++++++- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 1c4b174..e89f621 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -109,17 +109,8 @@ def convertSSAtoSMT(self): else: raise Exception("Unknown SSA instruction") - if stmt.lvar.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$")): + if isinstance(stmt.lvar, ChironSSA.Var) and stmt.lvar.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$")): lvar = z3.Real(stmt.lvar.name) - if isinstance(stmt.rvar1, ChironSSA.Var): - rvar1 = z3.Real(stmt.rvar1.name) - elif isinstance(stmt.rvar1, ChironSSA.Num): - rvar1 = z3.RealVal(stmt.rvar1.value) - if isinstance(stmt.rvar2, ChironSSA.Var): - rvar2 = z3.Real(stmt.rvar2.name) - elif isinstance(stmt.rvar2, ChironSSA.Num): - rvar2 = z3.RealVal(stmt.rvar2.value) - if isinstance(stmt.rvar1, ChironSSA.Var) and stmt.rvar1.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$")): rvar1 = z3.Real(stmt.rvar1.name) if isinstance(stmt.rvar2, ChironSSA.Var) and stmt.rvar2.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$")): @@ -210,7 +201,6 @@ def solve(self, inputVars): if sat == z3.sat: print("Condition not satisfied! Bug found for the following input:") model = self.solver.model() - print(model) solution = {} for var in model: varname, index = str(var).split("$") diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 10f123f..d238d80 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -409,7 +409,7 @@ def stopTurtle(): if args.bmc: print("\nBounded Model Checking...") # unroll_bound = int(input("Enter the unroll bound for the program: ")) - unroll_bound = 1 + unroll_bound = 2 if unroll_bound < 1: print("Invalid unroll bound. Exiting..") @@ -419,7 +419,7 @@ def stopTurtle(): # cond_count = int(input("Enter the number of conditions in the program: ")) cond_count = 0 - + if cond_count < 0: print("Invalid number of conditions. Exiting..") exit(1) diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 7919c3f..ae63a07 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,3 +1,10 @@ -:x = :y + 1 +:a = 1 +:y = 0 +repeat :a [ + :x = :y + 2 +] + goto (:x, :y) + +assert :x > 0 assert :turtleX > 0 \ No newline at end of file diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index f697126..95ad3ed 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,3 +1,14 @@ -:x=:y+1 +:a=1 +:y=0 +if (:a > 0) [ +:x=:y+2 + +] +if (:a > 1) [ +:x=:y+2 + +] + goto (:x, :y) +assert:x>0 assert:turtleX>0 From faf8ca7711dee524dede4cc648d6b0275f164551 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Thu, 20 Mar 2025 11:32:40 +0530 Subject: [PATCH 35/53] debugged cases when loop does not run or if cond is not true --- ChironCore/bmc.py | 97 ++++++++++++++++++++++++++++--------- ChironCore/example/move.tl | 1 - ChironCore/unrolled_code.tl | 1 - 3 files changed, 75 insertions(+), 24 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index e89f621..66f7117 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -19,11 +19,10 @@ def __init__(self, cfg): self.varConditions = {} # varConditions[var] = condition for var for bb in self.cfg.nodes(): for stmt, _ in bb.instrlist: - if isinstance(stmt, ChironSSA.PhiCommand): - self.varConditions[stmt.lvar.name] = self.bbConditions[bb] - elif isinstance(stmt, ChironSSA.AssignmentCommand): + if isinstance(stmt, (ChironSSA.PhiCommand, ChironSSA.AssignmentCommand, ChironSSA.SinCommand, ChironSSA.CosCommand, ChironSSA.DegToRadCommand)): self.varConditions[stmt.lvar.name] = self.bbConditions[bb] + def buildConditions(self): topological_order = list(self.cfg.get_topological_order()) start = topological_order[0] @@ -58,8 +57,11 @@ def convertSSAtoSMT(self): rhs_expr = rvars[0] for i in range(1, len(stmt.rvars)): rhs_expr = z3.If(self.varConditions[stmt.rvars[i].name], rvars[i], (rhs_expr)) - - self.solver.add(lvar == rhs_expr) + + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == rhs_expr)) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == rhs_expr) elif isinstance(stmt, ChironSSA.AssignmentCommand): lvar = None @@ -117,33 +119,75 @@ def convertSSAtoSMT(self): rvar2 = z3.Real(stmt.rvar2.name) if stmt.op == "+": - self.solver.add(lvar == (rvar1 + rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 + rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar1 + rvar2)) elif stmt.op == "-": - self.solver.add(lvar == (rvar1 - rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 - rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar1 - rvar2)) elif stmt.op == "*": - self.solver.add(lvar == (rvar1 * rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 * rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar1 * rvar2)) elif stmt.op == "/": - self.solver.add(lvar == (rvar1 / rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 / rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar1 / rvar2)) elif stmt.op == "%": - self.solver.add(lvar == (rvar1 % rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 % rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar1 % rvar2)) elif stmt.op == "<": - self.solver.add(lvar == (rvar1 < rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 < rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar1 < rvar2)) elif stmt.op == ">": - self.solver.add(lvar == (rvar1 > rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 > rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar1 > rvar2)) elif stmt.op == "<=": - self.solver.add(lvar == (rvar1 <= rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 <= rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar1 <= rvar2)) elif stmt.op == ">=": - self.solver.add(lvar == (rvar1 >= rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 >= rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar1 >= rvar2)) elif stmt.op == "==": - self.solver.add(lvar == (rvar1 == rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 == rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar1 == rvar2)) elif stmt.op == "!=": - self.solver.add(lvar == (rvar1 != rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 != rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar1 != rvar2)) elif stmt.op == "and": - self.solver.add(lvar == z3.And(rvar1, rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == z3.And(rvar1, rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == z3.And(rvar1, rvar2)) elif stmt.op == "or": - self.solver.add(lvar == z3.Or(rvar1, rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == z3.Or(rvar1, rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == z3.Or(rvar1, rvar2)) elif stmt.op == "not": - self.solver.add(lvar == z3.Not(rvar2)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == z3.Not(rvar2))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == z3.Not(rvar2)) elif isinstance(stmt, ChironSSA.AssertCommand): cond = None @@ -162,17 +206,26 @@ def convertSSAtoSMT(self): elif isinstance(stmt.rvar, ChironSSA.Num): rvar = z3.RealVal(stmt.rvar.value) lvar = z3.Real(stmt.lvar.name) - self.solver.add(lvar == (rvar * 3.14 / 180)) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar * 3.14 / 180))) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(lvar == (rvar * 3.14 / 180)) elif isinstance(stmt, ChironSSA.CosCommand): # Using taylor series rvar = z3.Real(stmt.rvar.name) rhs_expr = 1 - (rvar ** 2) / 2 + (rvar ** 4) / 24 - (rvar ** 6) / 720 + (rvar ** 8) / 40320 - (rvar ** 10) / 3628800 + (rvar ** 12) / 479001600 - (rvar ** 14) / 87178291200 + (rvar ** 16) / 20922789888000 - (rvar ** 18) / 6402373705728000 + (rvar ** 20) / 2432902008176640000 - self.solver.add(z3.Real(stmt.lvar.name) == rhs_expr) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Real(stmt.lvar.name) == rhs_expr)) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(z3.Real(stmt.lvar.name) == rhs_expr) elif isinstance(stmt, ChironSSA.SinCommand): rvar = z3.Real(stmt.rvar.name) rhs_expr = rvar - (rvar ** 3) / 6 + (rvar ** 5) / 120 - (rvar ** 7) / 5040 + (rvar ** 9) / 362880 - (rvar ** 11) / 39916800 + (rvar ** 13) / 6227020800 - (rvar ** 15) / 1307674368000 + (rvar ** 17) / 355687428096000 - (rvar ** 19) / 121645100408832000 + (rvar ** 21) / 51090942171709440000 - self.solver.add(z3.Real(stmt.lvar.name) == rhs_expr) + if self.varConditions[stmt.lvar.name] not in (None, True, False): + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Real(stmt.lvar.name) == rhs_expr)) + elif self.varConditions[stmt.lvar.name] is not False: + self.solver.add(z3.Real(stmt.lvar.name) == rhs_expr) elif isinstance(stmt, ChironSSA.MoveCommand): pass diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index ae63a07..5ffbcce 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,4 +1,3 @@ -:a = 1 :y = 0 repeat :a [ :x = :y + 2 diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 95ad3ed..82c66bf 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,4 +1,3 @@ -:a=1 :y=0 if (:a > 0) [ :x=:y+2 From c704482d34eb26bbe1fd9ba0a6ef847be948db94 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Thu, 20 Mar 2025 11:47:19 +0530 Subject: [PATCH 36/53] removed testing hardcode --- ChironCore/chiron.py | 8 +++----- ChironCore/example/move.tl | 2 +- ChironCore/unrolled_code.tl | 9 ++++----- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index d238d80..0048728 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -408,8 +408,7 @@ def stopTurtle(): if args.bmc: print("\nBounded Model Checking...") - # unroll_bound = int(input("Enter the unroll bound for the program: ")) - unroll_bound = 2 + unroll_bound = int(input("Enter the unroll bound for the program: ")) if unroll_bound < 1: print("Invalid unroll bound. Exiting..") @@ -417,8 +416,7 @@ def stopTurtle(): unrolled_code = unroll.UnrollLoops(unroll_bound).visitStart(getParseTree(args.progfl)) - # cond_count = int(input("Enter the number of conditions in the program: ")) - cond_count = 0 + cond_count = int(input("Enter the number of conditions in the program: ")) if cond_count < 0: print("Invalid number of conditions. Exiting..") @@ -467,4 +465,4 @@ def stopTurtle(): smt = bmc.BMC(ssaCfg) smt.convertSSAtoSMT() smt.solve(tacGen.getFreeVariables()) - # print("DONE..") + print("DONE..") diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 5ffbcce..4c9c5a0 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -3,7 +3,7 @@ repeat :a [ :x = :y + 2 ] -goto (:x, :y) +goto (20, :y) assert :x > 0 assert :turtleX > 0 \ No newline at end of file diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 82c66bf..001e976 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,13 +1,12 @@ -:y=0 if (:a > 0) [ +if (:z > 0) [ :x=:y+2 ] -if (:a > 1) [ -:x=:y+2 + +:z=:x+1 ] goto (:x, :y) -assert:x>0 -assert:turtleX>0 +assert:turtleX<0 From 3e045967e8aa9b8f8747a47efbf5ea880da1f93d Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Thu, 20 Mar 2025 15:57:05 +0530 Subject: [PATCH 37/53] handled typecasting for sin, cos and assert --- ChironCore/bmc.py | 20 ++++++++++++-------- ChironCore/chiron.py | 10 +++++----- ChironCore/example/move.tl | 11 +++++------ ChironCore/example/move1.tl | 11 +---------- ChironCore/unrolled_code.tl | 26 +++++++++++++++++++++----- 5 files changed, 44 insertions(+), 34 deletions(-) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 66f7117..5d1bed2 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -20,8 +20,7 @@ def __init__(self, cfg): for bb in self.cfg.nodes(): for stmt, _ in bb.instrlist: if isinstance(stmt, (ChironSSA.PhiCommand, ChironSSA.AssignmentCommand, ChironSSA.SinCommand, ChironSSA.CosCommand, ChironSSA.DegToRadCommand)): - self.varConditions[stmt.lvar.name] = self.bbConditions[bb] - + self.varConditions[stmt.lvar.name] = self.bbConditions[bb] if self.bbConditions[bb] is not None else z3.BoolVal(True) def buildConditions(self): topological_order = list(self.cfg.get_topological_order()) @@ -52,7 +51,9 @@ def convertSSAtoSMT(self): for stmt, _ in bb.instrlist: if isinstance(stmt, ChironSSA.PhiCommand): lvar = z3.Int(stmt.lvar.name) - rvars = [z3.Int(rvar.name) for rvar in stmt.rvars] + if stmt.lvar.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$", ":__cos_theta$", ":__sin_theta$")): + lvar = z3.Real(stmt.lvar.name) + rvars = [z3.Real(rvar.name) if rvar.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$", ":__cos_theta$", ":__sin_theta$")) else z3.Int(rvar.name) for rvar in stmt.rvars] rhs_expr = rvars[0] for i in range(1, len(stmt.rvars)): @@ -111,11 +112,11 @@ def convertSSAtoSMT(self): else: raise Exception("Unknown SSA instruction") - if isinstance(stmt.lvar, ChironSSA.Var) and stmt.lvar.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$")): + if isinstance(stmt.lvar, ChironSSA.Var) and stmt.lvar.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$", ":__cos_theta$", ":__sin_theta$")): lvar = z3.Real(stmt.lvar.name) - if isinstance(stmt.rvar1, ChironSSA.Var) and stmt.rvar1.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$")): + if isinstance(stmt.rvar1, ChironSSA.Var) and stmt.rvar1.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$", ":__cos_theta$", ":__sin_theta$")): rvar1 = z3.Real(stmt.rvar1.name) - if isinstance(stmt.rvar2, ChironSSA.Var) and stmt.rvar2.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$")): + if isinstance(stmt.rvar2, ChironSSA.Var) and stmt.rvar2.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$", ":__cos_theta$", ":__sin_theta$")): rvar2 = z3.Real(stmt.rvar2.name) if stmt.op == "+": @@ -213,7 +214,8 @@ def convertSSAtoSMT(self): elif isinstance(stmt, ChironSSA.CosCommand): # Using taylor series rvar = z3.Real(stmt.rvar.name) - rhs_expr = 1 - (rvar ** 2) / 2 + (rvar ** 4) / 24 - (rvar ** 6) / 720 + (rvar ** 8) / 40320 - (rvar ** 10) / 3628800 + (rvar ** 12) / 479001600 - (rvar ** 14) / 87178291200 + (rvar ** 16) / 20922789888000 - (rvar ** 18) / 6402373705728000 + (rvar ** 20) / 2432902008176640000 + rhs_expr = 1 - (rvar ** 2) / 2 + (rvar ** 4) / 24 + # rhs_expr = 1 - (rvar ** 2) / 2 + (rvar ** 4) / 24 - (rvar ** 6) / 720 + (rvar ** 8) / 40320 - (rvar ** 10) / 3628800 + (rvar ** 12) / 479001600 - (rvar ** 14) / 87178291200 + (rvar ** 16) / 20922789888000 - (rvar ** 18) / 6402373705728000 + (rvar ** 20) / 2432902008176640000 if self.varConditions[stmt.lvar.name] not in (None, True, False): self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Real(stmt.lvar.name) == rhs_expr)) elif self.varConditions[stmt.lvar.name] is not False: @@ -221,7 +223,8 @@ def convertSSAtoSMT(self): elif isinstance(stmt, ChironSSA.SinCommand): rvar = z3.Real(stmt.rvar.name) - rhs_expr = rvar - (rvar ** 3) / 6 + (rvar ** 5) / 120 - (rvar ** 7) / 5040 + (rvar ** 9) / 362880 - (rvar ** 11) / 39916800 + (rvar ** 13) / 6227020800 - (rvar ** 15) / 1307674368000 + (rvar ** 17) / 355687428096000 - (rvar ** 19) / 121645100408832000 + (rvar ** 21) / 51090942171709440000 + rhs_expr = rvar - (rvar ** 3) / 6 + # rhs_expr = rvar - (rvar ** 3) / 6 + (rvar ** 5) / 120 - (rvar ** 7) / 5040 + (rvar ** 9) / 362880 - (rvar ** 11) / 39916800 + (rvar ** 13) / 6227020800 - (rvar ** 15) / 1307674368000 + (rvar ** 17) / 355687428096000 - (rvar ** 19) / 121645100408832000 + (rvar ** 21) / 51090942171709440000 if self.varConditions[stmt.lvar.name] not in (None, True, False): self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Real(stmt.lvar.name) == rhs_expr)) elif self.varConditions[stmt.lvar.name] is not False: @@ -254,6 +257,7 @@ def solve(self, inputVars): if sat == z3.sat: print("Condition not satisfied! Bug found for the following input:") model = self.solver.model() + print(model) solution = {} for var in model: varname, index = str(var).split("$") diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 0048728..b41d9ea 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -411,7 +411,7 @@ def stopTurtle(): unroll_bound = int(input("Enter the unroll bound for the program: ")) if unroll_bound < 1: - print("Invalid unroll bound. Exiting..") + print("Invalid unroll bound. Exiting...") exit(1) unrolled_code = unroll.UnrollLoops(unroll_bound).visitStart(getParseTree(args.progfl)) @@ -419,7 +419,7 @@ def stopTurtle(): cond_count = int(input("Enter the number of conditions in the program: ")) if cond_count < 0: - print("Invalid number of conditions. Exiting..") + print("Invalid number of conditions. Exiting...") exit(1) if cond_count != 0: @@ -450,7 +450,7 @@ def stopTurtle(): # tacGen.printTAC() # Printing TAC if tacGen.assertCount == 0: - print("No conditions found in the program. Exiting..") + print("No conditions found in the program. Exiting...") exit(1) cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) # Building CFG @@ -461,8 +461,8 @@ def stopTurtle(): cfgB.dumpCFG(ssaCfg, 'ssa_cfg') # Saving SSA Form of the program to file ssa_cfg.png - print("\nConverting program to SMT-LIB format..\n") + print("\nConverting program to SMT-LIB format...\n") smt = bmc.BMC(ssaCfg) smt.convertSSAtoSMT() smt.solve(tacGen.getFreeVariables()) - print("DONE..") + print("DONE...") diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 4c9c5a0..41ea12f 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,9 +1,8 @@ -:y = 0 +:a = 2 + repeat :a [ - :x = :y + 2 + forward 50 + :a = :a - 2 ] -goto (20, :y) - -assert :x > 0 -assert :turtleX > 0 \ No newline at end of file +assert :turtleX == 50 \ No newline at end of file diff --git a/ChironCore/example/move1.tl b/ChironCore/example/move1.tl index d2692fd..055782d 100644 --- a/ChironCore/example/move1.tl +++ b/ChironCore/example/move1.tl @@ -1,10 +1 @@ -if (:p > 0) [ - :x = 20 - :f = :x * 2 + :x - backward :x - // left 50 -] else [ - :x = 10 -] -assert :x == 20 -forward :x \ No newline at end of file +forward 50 \ No newline at end of file diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 001e976..8a1e748 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,12 +1,28 @@ +:a=2 if (:a > 0) [ -if (:z > 0) [ -:x=:y+2 +forward50 +:a=:a-2 ] +if (:a > 1) [ +forward50 +:a=:a-2 -:z=:x+1 +] +if (:a > 2) [ +forward50 +:a=:a-2 + +] +if (:a > 3) [ +forward50 +:a=:a-2 + +] +if (:a > 4) [ +forward50 +:a=:a-2 ] -goto (:x, :y) -assert:turtleX<0 +assert:turtleX==50 From 7091d0a8c174d6a4465103fce393149206112ac2 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Thu, 20 Mar 2025 16:10:11 +0530 Subject: [PATCH 38/53] fix variable repeat unrolling --- ChironCore/example/bmc_tc1.tl | 7 +++++++ ChironCore/example/bmc_tc2.tl | 22 ++++++++++++++++++++++ ChironCore/example/bmc_tc3.tl | 11 +++++++++++ ChironCore/unroll.py | 7 +++++-- 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 ChironCore/example/bmc_tc1.tl create mode 100644 ChironCore/example/bmc_tc2.tl create mode 100644 ChironCore/example/bmc_tc3.tl diff --git a/ChironCore/example/bmc_tc1.tl b/ChironCore/example/bmc_tc1.tl new file mode 100644 index 0000000..57e65e3 --- /dev/null +++ b/ChironCore/example/bmc_tc1.tl @@ -0,0 +1,7 @@ +:t = 1 +repeat 2 [ + :t = :t * :x +] +:s = 5 * :x +:z = :t + :s + 2 +assert :z >= -5 diff --git a/ChironCore/example/bmc_tc2.tl b/ChironCore/example/bmc_tc2.tl new file mode 100644 index 0000000..7626556 --- /dev/null +++ b/ChironCore/example/bmc_tc2.tl @@ -0,0 +1,22 @@ +:p = 1 +repeat 5 [ + :t = :t * :x +] + +:q = 1 +repeat 4 [ + :q = :q * :x +] + +:r = 1 +repeat 7 [ + :r = :r * :x +] + +:s = 1 +repeat 9 [ + :s = :s * :x +] + +:z = 2*:p - 3*:q + 5*:r - 7*:s +assert :z > -10000 diff --git a/ChironCore/example/bmc_tc3.tl b/ChironCore/example/bmc_tc3.tl new file mode 100644 index 0000000..78fca10 --- /dev/null +++ b/ChironCore/example/bmc_tc3.tl @@ -0,0 +1,11 @@ +:a = 1 +:y = 0 +if (:a > 0) [ + :x = :y + 2 +] +if (:a > 1) [ + :x = :y + 3 +] +goto (:x, :y) +assert :x > 0 +assert :turtleX > 0 diff --git a/ChironCore/unroll.py b/ChironCore/unroll.py index 646dbd3..2be1aec 100644 --- a/ChironCore/unroll.py +++ b/ChironCore/unroll.py @@ -7,7 +7,7 @@ class UnrollLoops(tlangVisitor): def __init__(self, bound): self.bound = bound - pass + self.repeatVariablesCounter = 0 def visitStart(self, ctx:tlangParser.StartContext): stmtList = self.visit(ctx.instruction_list()) @@ -83,8 +83,11 @@ def visitLoop(self, ctx:tlangParser.LoopContext): code += loopBlock + "\n" else: # variable number of iterations + repeatVariable = ":__repeat" + str(self.repeatVariablesCounter) + code += repeatVariable + " = " + repeatCount + "\n" for i in range(self.bound): - code += "if (" + repeatCount + " > " + str(i) + ") [\n" + loopBlock + "\n]\n" + code += "if (" + repeatVariable + " > " + str(i) + ") [\n" + loopBlock + "\n]\n" + self.repeatVariablesCounter += 1 return code From b818ca2fe9451df26a3e988c4beb0c602232ce95 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Tue, 25 Mar 2025 01:51:58 +0530 Subject: [PATCH 39/53] restricted 90 deg rotations only --- ChironCore/ChironSSA/ChironSSA.py | 8 --- ChironCore/ChironSSA/builder.py | 11 ---- ChironCore/ChironTAC/ChironTAC.py | 8 --- ChironCore/ChironTAC/builder.py | 25 ++++----- ChironCore/bmc.py | 92 ++++++++++++++++--------------- ChironCore/example/bmc_tc3.tl | 2 + ChironCore/example/move.tl | 19 +++++-- ChironCore/unroll.py | 2 +- ChironCore/unrolled_code.tl | 82 +++++++++++++++++++++------ 9 files changed, 139 insertions(+), 110 deletions(-) diff --git a/ChironCore/ChironSSA/ChironSSA.py b/ChironCore/ChironSSA/ChironSSA.py index 5e05e46..20eb216 100644 --- a/ChironCore/ChironSSA/ChironSSA.py +++ b/ChironCore/ChironSSA/ChironSSA.py @@ -6,14 +6,6 @@ class SSA(object): class Instruction(SSA): pass -class DegToRadCommand(Instruction): - def __init__(self, lvar, rvar): # lvar = degToRad(rvar) - self.lvar = lvar - self.rvar = rvar - - def __str__(self): - return self.lvar.__str__() + " = degToRad(" + self.rvar.__str__() + ")" - class CosCommand(Instruction): def __init__(self, lvar, rvar): # lvar = cos(rvar) self.lvar = lvar diff --git a/ChironCore/ChironSSA/builder.py b/ChironCore/ChironSSA/builder.py index d009be0..9c9943e 100644 --- a/ChironCore/ChironSSA/builder.py +++ b/ChironCore/ChironSSA/builder.py @@ -88,12 +88,6 @@ def rename(self, block): instr.lvar = self.new_name(instr.lvar.name) if isinstance(instr.rvar, ChironSSA.Var): instr.rvar = ChironSSA.Var(instr.rvar.name + "$" + str(self.stack[instr.rvar.name][-1])) - - elif isinstance(instr, ChironSSA.DegToRadCommand): - temp.add(instr.lvar.name) - instr.lvar = self.new_name(instr.lvar.name) - if isinstance(instr.rvar, ChironSSA.Var): - instr.rvar = ChironSSA.Var(instr.rvar.name + "$" + str(self.stack[instr.rvar.name][-1])) visited = set() def phi_dfs(curr, var): @@ -219,11 +213,6 @@ def convert(self, ir): rvar = ChironSSA.Var(instr.rvar.name) if isinstance(instr.rvar, ChironTAC.Var) else ChironSSA.Num(instr.rvar.value) ir[ir.index((instr, tgt))] = (ChironSSA.CosCommand(lvar, rvar), tgt) - elif isinstance(instr, ChironTAC.DegToRadCommand): - lvar = ChironSSA.Var(instr.lvar.name) - rvar = ChironSSA.Var(instr.rvar.name) if isinstance(instr.rvar, ChironTAC.Var) else ChironSSA.Num(instr.rvar.value) - ir[ir.index((instr, tgt))] = (ChironSSA.DegToRadCommand(lvar, rvar), tgt) - elif isinstance(instr, ChironTAC.PenCommand): ir[ir.index((instr, tgt))] = (ChironSSA.PenCommand(instr.status), tgt) diff --git a/ChironCore/ChironTAC/ChironTAC.py b/ChironCore/ChironTAC/ChironTAC.py index cd2c636..fd0b063 100644 --- a/ChironCore/ChironTAC/ChironTAC.py +++ b/ChironCore/ChironTAC/ChironTAC.py @@ -6,14 +6,6 @@ class TAC(object): class Instruction(TAC): pass -class DegToRadCommand(Instruction): - def __init__(self, lvar, rvar): # lvar = degToRad(rvar) - self.lvar = lvar - self.rvar = rvar - - def __str__(self): - return self.lvar.__str__() + " = degToRad(" + self.rvar.__str__() + ")" - class CosCommand(Instruction): def __init__(self, lvar, rvar): # lvar = cos(rvar) self.lvar = lvar diff --git a/ChironCore/ChironTAC/builder.py b/ChironCore/ChironTAC/builder.py index 10d634d..55ba843 100644 --- a/ChironCore/ChironTAC/builder.py +++ b/ChironCore/ChironTAC/builder.py @@ -287,12 +287,11 @@ def generateTAC(self): movevar = ChironTAC.Var(f":__move_{self.moveCount}") self.moveCount += 1 self.parseExpresssion(stmt.expr, movevar) - self.line += 1 - self.tac.append((ChironTAC.MoveCommand(stmt.direction, movevar), 1)) + if (stmt.direction == "forward" or stmt.direction == "backward"): self.line += 6 - self.tac.append((ChironTAC.CosCommand(ChironTAC.Var(":__cos_theta"), ChironTAC.Var(":turtleThetaRad")), 1)) - self.tac.append((ChironTAC.SinCommand(ChironTAC.Var(":__sin_theta"), ChironTAC.Var(":turtleThetaRad")), 1)) + self.tac.append((ChironTAC.CosCommand(ChironTAC.Var(":__cos_theta"), ChironTAC.Var(":turtleThetaDeg")), 1)) + self.tac.append((ChironTAC.SinCommand(ChironTAC.Var(":__sin_theta"), ChironTAC.Var(":turtleThetaDeg")), 1)) self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__delta_x"), movevar, ChironTAC.Var(":__cos_theta"), "*"), 1)) self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":__delta_y"), movevar, ChironTAC.Var(":__sin_theta"), "*"), 1)) if (stmt.direction == "forward"): @@ -302,27 +301,28 @@ def generateTAC(self): self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleX"), ChironTAC.Var(":turtleX"), ChironTAC.Var(":__delta_x"), "-"), 1)) self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleY"), ChironTAC.Var(":turtleY"), ChironTAC.Var(":__delta_y"), "-"), 1)) elif (stmt.direction == "left"): - self.line += 3 + self.line += 2 self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), movevar, "-"), 1)) self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Num(360), "%"), 1)) - self.tac.append((ChironTAC.DegToRadCommand(ChironTAC.Var(":turtleThetaRad"), ChironTAC.Var(":turtleThetaDeg")), 1)) elif (stmt.direction == "right"): - self.line += 3 + self.line += 2 self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), movevar, "+"), 1)) self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Num(360), "%"), 1)) - self.tac.append((ChironTAC.DegToRadCommand(ChironTAC.Var(":turtleThetaRad"), ChironTAC.Var(":turtleThetaDeg")), 1)) else: raise NotImplementedError("Unknown move direction: %s, %s." % (type(stmt), stmt)) + + self.line += 1 + self.tac.append((ChironTAC.MoveCommand(stmt.direction, movevar), 1)) elif isinstance(stmt, ChironAST.PenCommand): self.line += 2 - self.tac.append((ChironTAC.PenCommand(stmt.status), 1)) if (stmt.status == "penup"): self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtlePen"), ChironTAC.Num(1), ChironTAC.Num(0), "+"), 1)) elif (stmt.status == "pendown"): self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtlePen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) else: raise NotImplementedError("Unknown pen status: %s, %s." % (type(stmt), stmt)) + self.tac.append((ChironTAC.PenCommand(stmt.status), 1)) elif isinstance(stmt, ChironAST.GotoCommand): xvar = None @@ -344,9 +344,9 @@ def generateTAC(self): self.gotoCount += 1 self.parseExpresssion(stmt.ycor, yvar) self.line += 3 - self.tac.append((ChironTAC.GotoCommand(xvar, yvar), 1)) self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleX"), xvar, ChironTAC.Num(0), "+"), 1)) self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleY"), yvar, ChironTAC.Num(0), "+"), 1)) + self.tac.append((ChironTAC.GotoCommand(xvar, yvar), 1)) elif isinstance(stmt, ChironAST.NoOpCommand): self.line += 1 @@ -382,7 +382,6 @@ def handleMoveVariables(self): self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleX"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleY"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) - self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaRad"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) self.tac.insert(0, (ChironTAC.AssignmentCommand(ChironTAC.Var(":turtlePen"), ChironTAC.Num(0), ChironTAC.Num(0), "+"), 1)) # 0->down 1->up def getFreeVariables(self): @@ -422,10 +421,6 @@ def getFreeVariables(self): if isinstance(stmt.rvar, ChironTAC.Var) and stmt.rvar.__str__() not in boundVars: self.freeVars.add(stmt.rvar.__str__()) boundVars.add(stmt.lvar.__str__()) - elif isinstance(stmt, ChironTAC.DegToRadCommand): - if isinstance(stmt.rvar, ChironTAC.Var) and stmt.rvar.__str__() not in boundVars: - self.freeVars.add(stmt.rvar.__str__()) - boundVars.add(stmt.lvar.__str__()) return self.freeVars diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 5d1bed2..df20e08 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -8,6 +8,9 @@ class BMC: def __init__(self, cfg): self.solver = z3.Solver() + self.solver_without_cond = z3.Solver() + self.angle_conditions = z3.BoolVal(True) + self.assert_conditions = z3.BoolVal(True) self.cfg = cfg self.bbConditions = {} # bbConditions[bb] = condition for bb @@ -19,7 +22,7 @@ def __init__(self, cfg): self.varConditions = {} # varConditions[var] = condition for var for bb in self.cfg.nodes(): for stmt, _ in bb.instrlist: - if isinstance(stmt, (ChironSSA.PhiCommand, ChironSSA.AssignmentCommand, ChironSSA.SinCommand, ChironSSA.CosCommand, ChironSSA.DegToRadCommand)): + if isinstance(stmt, (ChironSSA.PhiCommand, ChironSSA.AssignmentCommand, ChironSSA.SinCommand, ChironSSA.CosCommand)): self.varConditions[stmt.lvar.name] = self.bbConditions[bb] if self.bbConditions[bb] is not None else z3.BoolVal(True) def buildConditions(self): @@ -46,14 +49,11 @@ def buildConditions(self): self.bbConditions[node] = node.get_condition() def convertSSAtoSMT(self): - assert_conditions = z3.BoolVal(True) for bb in self.cfg.nodes(): for stmt, _ in bb.instrlist: if isinstance(stmt, ChironSSA.PhiCommand): lvar = z3.Int(stmt.lvar.name) - if stmt.lvar.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$", ":__cos_theta$", ":__sin_theta$")): - lvar = z3.Real(stmt.lvar.name) - rvars = [z3.Real(rvar.name) if rvar.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$", ":__cos_theta$", ":__sin_theta$")) else z3.Int(rvar.name) for rvar in stmt.rvars] + rvars = [z3.Int(rvar.name) for rvar in stmt.rvars] rhs_expr = rvars[0] for i in range(1, len(stmt.rvars)): @@ -63,7 +63,7 @@ def convertSSAtoSMT(self): self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == rhs_expr)) elif self.varConditions[stmt.lvar.name] is not False: self.solver.add(lvar == rhs_expr) - + elif isinstance(stmt, ChironSSA.AssignmentCommand): lvar = None rvar1 = ChironSSA.Unused() @@ -111,13 +111,6 @@ def convertSSAtoSMT(self): continue else: raise Exception("Unknown SSA instruction") - - if isinstance(stmt.lvar, ChironSSA.Var) and stmt.lvar.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$", ":__cos_theta$", ":__sin_theta$")): - lvar = z3.Real(stmt.lvar.name) - if isinstance(stmt.rvar1, ChironSSA.Var) and stmt.rvar1.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$", ":__cos_theta$", ":__sin_theta$")): - rvar1 = z3.Real(stmt.rvar1.name) - if isinstance(stmt.rvar2, ChironSSA.Var) and stmt.rvar2.name.startswith((":turtleX$", ":turtleY$", ":__delta_x$", ":__delta_y$", ":turtleThetaRad$", ":__cos_theta$", ":__sin_theta$")): - rvar2 = z3.Real(stmt.rvar2.name) if stmt.op == "+": if self.varConditions[stmt.lvar.name] not in (None, True, False): @@ -142,8 +135,12 @@ def convertSSAtoSMT(self): elif stmt.op == "%": if self.varConditions[stmt.lvar.name] not in (None, True, False): self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 % rvar2))) + if stmt.lvar.name.startswith(":turtleThetaDeg$"): + self.angle_conditions = z3.And(self.angle_conditions, z3.Implies(self.varConditions[stmt.lvar.name], z3.Or(lvar == 0, lvar == 90, lvar == 180, lvar == 270))) elif self.varConditions[stmt.lvar.name] is not False: self.solver.add(lvar == (rvar1 % rvar2)) + if stmt.lvar.name.startswith(":turtleThetaDeg$"): + self.angle_conditions = z3.And(self.angle_conditions, z3.Or(lvar == 0, lvar == 90, lvar == 180, lvar == 270)) elif stmt.op == "<": if self.varConditions[stmt.lvar.name] not in (None, True, False): self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 < rvar2))) @@ -198,37 +195,23 @@ def convertSSAtoSMT(self): cond = z3.BoolVal(False) elif isinstance(stmt.cond, ChironSSA.Var): cond = z3.Bool(stmt.cond.name) - assert_conditions = z3.And(assert_conditions, cond) - - elif isinstance(stmt, ChironSSA.DegToRadCommand): - rvar = None - if isinstance(stmt.rvar, ChironSSA.Var): - rvar = z3.Real(stmt.rvar.name) - elif isinstance(stmt.rvar, ChironSSA.Num): - rvar = z3.RealVal(stmt.rvar.value) - lvar = z3.Real(stmt.lvar.name) - if self.varConditions[stmt.lvar.name] not in (None, True, False): - self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar * 3.14 / 180))) - elif self.varConditions[stmt.lvar.name] is not False: - self.solver.add(lvar == (rvar * 3.14 / 180)) + self.assert_conditions = z3.And(self.assert_conditions, cond) - elif isinstance(stmt, ChironSSA.CosCommand): # Using taylor series - rvar = z3.Real(stmt.rvar.name) - rhs_expr = 1 - (rvar ** 2) / 2 + (rvar ** 4) / 24 - # rhs_expr = 1 - (rvar ** 2) / 2 + (rvar ** 4) / 24 - (rvar ** 6) / 720 + (rvar ** 8) / 40320 - (rvar ** 10) / 3628800 + (rvar ** 12) / 479001600 - (rvar ** 14) / 87178291200 + (rvar ** 16) / 20922789888000 - (rvar ** 18) / 6402373705728000 + (rvar ** 20) / 2432902008176640000 + elif isinstance(stmt, ChironSSA.CosCommand): # Only for 0, 90, 180, 270 degree + rvar = z3.Int(stmt.rvar.name) + rhs_expr = z3.If(rvar == 0, 1, z3.If(rvar == 90, 0, z3.If(rvar == 180, -1, 0))) if self.varConditions[stmt.lvar.name] not in (None, True, False): - self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Real(stmt.lvar.name) == rhs_expr)) + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Int(stmt.lvar.name) == rhs_expr)) elif self.varConditions[stmt.lvar.name] is not False: - self.solver.add(z3.Real(stmt.lvar.name) == rhs_expr) + self.solver.add(z3.Int(stmt.lvar.name) == rhs_expr) elif isinstance(stmt, ChironSSA.SinCommand): - rvar = z3.Real(stmt.rvar.name) - rhs_expr = rvar - (rvar ** 3) / 6 - # rhs_expr = rvar - (rvar ** 3) / 6 + (rvar ** 5) / 120 - (rvar ** 7) / 5040 + (rvar ** 9) / 362880 - (rvar ** 11) / 39916800 + (rvar ** 13) / 6227020800 - (rvar ** 15) / 1307674368000 + (rvar ** 17) / 355687428096000 - (rvar ** 19) / 121645100408832000 + (rvar ** 21) / 51090942171709440000 + rvar = z3.Int(stmt.rvar.name) + rhs_expr = z3.If(rvar == 0, 0, z3.If(rvar == 90, 1, z3.If(rvar == 180, 0, -1))) if self.varConditions[stmt.lvar.name] not in (None, True, False): - self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Real(stmt.lvar.name) == rhs_expr)) + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Int(stmt.lvar.name) == rhs_expr)) elif self.varConditions[stmt.lvar.name] is not False: - self.solver.add(z3.Real(stmt.lvar.name) == rhs_expr) + self.solver.add(z3.Int(stmt.lvar.name) == rhs_expr) elif isinstance(stmt, ChironSSA.MoveCommand): pass @@ -244,20 +227,24 @@ def convertSSAtoSMT(self): pass else: raise Exception("Unknown SSA instruction") - - assert_conditions = z3.Tactic('ctx-simplify').apply(assert_conditions).as_expr() - self.solver.add(z3.Not(assert_conditions)) + + self.solver_without_cond.add(self.solver.assertions()) + self.assert_conditions = z3.Tactic('ctx-simplify').apply(self.assert_conditions).as_expr() + self.angle_conditions = z3.Tactic('ctx-simplify').apply(self.angle_conditions).as_expr() def solve(self, inputVars): - print("The clauses are:") - print(self.solver, end="\n\n") - + self.solver.add(z3.Not(self.assert_conditions)) + self.solver.add(self.angle_conditions) + + # print("The clauses are:") + # print(self.solver, end="\n\n") + sat = self.solver.check() if sat == z3.sat: print("Condition not satisfied! Bug found for the following input:") model = self.solver.model() - print(model) + solution = {} for var in model: varname, index = str(var).split("$") @@ -267,7 +254,22 @@ def solve(self, inputVars): print(var + " = " + str(solution[var])) elif sat == z3.unsat: - print("Condition satisfied for all inputs!") + solver_with_angle = z3.Solver() + solver_with_angle.add(self.solver_without_cond.assertions()) + solver_with_angle.add(self.angle_conditions) + sat_angle = solver_with_angle.check() + + # solver_with_assert = z3.Solver() + # solver_with_assert.add(self.solver_without_cond.assertions()) + # solver_with_assert.add(z3.Not(self.assert_conditions)) + # sat_assert = solver_with_assert.check() + + if sat_angle == z3.unsat: + print("Angle not 0, 90, 180, 270 degrees for all cases") + elif sat_angle != z3.unknown: # sat_assert is unsat + print("Condition satisfied for all inputs!") + else: + print("Unknown") else: print("Unknown") diff --git a/ChironCore/example/bmc_tc3.tl b/ChironCore/example/bmc_tc3.tl index 78fca10..8fe648a 100644 --- a/ChironCore/example/bmc_tc3.tl +++ b/ChironCore/example/bmc_tc3.tl @@ -7,5 +7,7 @@ if (:a > 1) [ :x = :y + 3 ] goto (:x, :y) +assert :turtleX == 2 && :turtleY == 0 +right :x assert :x > 0 assert :turtleX > 0 diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl index 41ea12f..6c8335c 100644 --- a/ChironCore/example/move.tl +++ b/ChironCore/example/move.tl @@ -1,8 +1,17 @@ -:a = 2 +// left 90 // valid +// assert 1 > 0 // true -repeat :a [ - forward 50 - :a = :a - 2 +// left 45 // invalid +// assert 1 > 0 // true + +// left 90 // valid +// assert 1 < 0 // flase + +// left 45 // invalid +// assert 1 < 0 // flase + +repeat 3 [ + left 90 ] -assert :turtleX == 50 \ No newline at end of file +assert :turtleX == 0 \ No newline at end of file diff --git a/ChironCore/unroll.py b/ChironCore/unroll.py index 2be1aec..e9ebb18 100644 --- a/ChironCore/unroll.py +++ b/ChironCore/unroll.py @@ -83,7 +83,7 @@ def visitLoop(self, ctx:tlangParser.LoopContext): code += loopBlock + "\n" else: # variable number of iterations - repeatVariable = ":__repeat" + str(self.repeatVariablesCounter) + repeatVariable = ":_repeat" + str(self.repeatVariablesCounter) code += repeatVariable + " = " + repeatCount + "\n" for i in range(self.bound): code += "if (" + repeatVariable + " > " + str(i) + ") [\n" + loopBlock + "\n]\n" diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 8a1e748..77b1269 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,28 +1,76 @@ -:a=2 -if (:a > 0) [ -forward50 -:a=:a-2 +:cnt=0 +:i=0 +:_repeat0 = :steps +if (:_repeat0 > 0) [ +:i=:cnt+:i +:cnt=:cnt+1 +forward(1+:cnt) +right(:radius) ] -if (:a > 1) [ -forward50 -:a=:a-2 +if (:_repeat0 > 1) [ +:i=:cnt+:i +:cnt=:cnt+1 +forward(1+:cnt) +right(:radius) ] -if (:a > 2) [ -forward50 -:a=:a-2 +if (:_repeat0 > 2) [ +:i=:cnt+:i +:cnt=:cnt+1 +forward(1+:cnt) +right(:radius) ] -if (:a > 3) [ -forward50 -:a=:a-2 +if (:_repeat0 > 3) [ +:i=:cnt+:i +:cnt=:cnt+1 +forward(1+:cnt) +right(:radius) ] -if (:a > 4) [ -forward50 -:a=:a-2 +if (:_repeat0 > 4) [ +:i=:cnt+:i +:cnt=:cnt+1 +forward(1+:cnt) +right(:radius) ] +if (:_repeat0 > 5) [ +:i=:cnt+:i +:cnt=:cnt+1 +forward(1+:cnt) +right(:radius) -assert:turtleX==50 +] +if (:_repeat0 > 6) [ +:i=:cnt+:i +:cnt=:cnt+1 +forward(1+:cnt) +right(:radius) + +] +if (:_repeat0 > 7) [ +:i=:cnt+:i +:cnt=:cnt+1 +forward(1+:cnt) +right(:radius) + +] +if (:_repeat0 > 8) [ +:i=:cnt+:i +:cnt=:cnt+1 +forward(1+:cnt) +right(:radius) + +] +if (:_repeat0 > 9) [ +:i=:cnt+:i +:cnt=:cnt+1 +forward(1+:cnt) +right(:radius) + +] + + +assert (:turtleX > 0) \ No newline at end of file From 8aa177ed5bbeb1627d1559db9cfd230a5ddc8f4f Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Sat, 29 Mar 2025 09:55:49 +0530 Subject: [PATCH 40/53] fix left right turn, assert statement during runtime --- ChironCore/ChironTAC/builder.py | 4 ++-- ChironCore/interpreter.py | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ChironCore/ChironTAC/builder.py b/ChironCore/ChironTAC/builder.py index 55ba843..18106e6 100644 --- a/ChironCore/ChironTAC/builder.py +++ b/ChironCore/ChironTAC/builder.py @@ -302,11 +302,11 @@ def generateTAC(self): self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleY"), ChironTAC.Var(":turtleY"), ChironTAC.Var(":__delta_y"), "-"), 1)) elif (stmt.direction == "left"): self.line += 2 - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), movevar, "-"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), movevar, "+"), 1)) self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Num(360), "%"), 1)) elif (stmt.direction == "right"): self.line += 2 - self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), movevar, "+"), 1)) + self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), movevar, "-"), 1)) self.tac.append((ChironTAC.AssignmentCommand(ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Var(":turtleThetaDeg"), ChironTAC.Num(360), "%"), 1)) else: raise NotImplementedError("Unknown move direction: %s, %s." % (type(stmt), stmt)) diff --git a/ChironCore/interpreter.py b/ChironCore/interpreter.py index f2bd6a6..8188a65 100644 --- a/ChironCore/interpreter.py +++ b/ChironCore/interpreter.py @@ -170,8 +170,11 @@ def handleGotoCommand(self, stmt, tgt): def handleAssertCommand(self, stmt, tgt): print(" AssertCommand") print(" Asserting: ", stmt.cond) - exec("self.cond_eval = %s" % (addContext(stmt.cond))) - if not self.cond_eval: - raise AssertionError("Assertion Failed!") + try: + exec("self.cond_eval = %s" % (addContext(stmt.cond))) + if not self.cond_eval: + raise AssertionError("Assertion Failed!") + except Exception as e: + print("Exception: ", e) return 1 From 4a1cd0023e9dab63ddbc43633b4a96905ac8bfc1 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Sat, 29 Mar 2025 10:32:54 +0530 Subject: [PATCH 41/53] add assume command --- ChironCore/ChironAST/ChironAST.py | 8 +- ChironCore/ChironAST/builder.py | 4 + ChironCore/ChironSSA/ChironSSA.py | 7 + ChironCore/ChironSSA/builder.py | 12 + ChironCore/ChironTAC/ChironTAC.py | 9 +- ChironCore/ChironTAC/builder.py | 11 + ChironCore/bmc.py | 13 + ChironCore/chiron.py | 16 + ChironCore/example/amogh.tl | 18 + ChironCore/interpreter.py | 15 + ChironCore/turtparse/tlang.g4 | 3 + ChironCore/turtparse/tlang.interp | 5 +- ChironCore/turtparse/tlang.tokens | 72 ++-- ChironCore/turtparse/tlangLexer.interp | 5 +- ChironCore/turtparse/tlangLexer.py | 241 ++++++------ ChironCore/turtparse/tlangLexer.tokens | 72 ++-- ChironCore/turtparse/tlangParser.py | 488 ++++++++++++++----------- ChironCore/turtparse/tlangVisitor.py | 5 + ChironCore/unroll.py | 3 + ChironCore/unrolled_code.tl | 416 ++++++++++++++++++--- 20 files changed, 971 insertions(+), 452 deletions(-) create mode 100644 ChironCore/example/amogh.tl diff --git a/ChironCore/ChironAST/ChironAST.py b/ChironCore/ChironAST/ChironAST.py index a2da4b9..aeb0b9f 100644 --- a/ChironCore/ChironAST/ChironAST.py +++ b/ChironCore/ChironAST/ChironAST.py @@ -28,7 +28,6 @@ def __init__(self, condition): def __str__(self): return self.cond.__str__() -# Not Implemented Yet. class AssertCommand(Instruction): def __init__(self, condition): self.cond = condition @@ -36,6 +35,13 @@ def __init__(self, condition): def __str__(self): return self.cond.__str__() +class AssumeCommand(Instruction): + def __init__(self, condition): + self.cond = condition + + def __str__(self): + return self.cond.__str__() + class MoveCommand(Instruction): def __init__(self, motion, expr): self.direction = motion diff --git a/ChironCore/ChironAST/builder.py b/ChironCore/ChironAST/builder.py index 90db734..4f9d034 100644 --- a/ChironCore/ChironAST/builder.py +++ b/ChironCore/ChironAST/builder.py @@ -183,3 +183,7 @@ def visitPenCommand(self, ctx:tlangParser.PenCommandContext): def visitAssertionCommand(self, ctx:tlangParser.AssertionCommandContext): return [(ChironAST.AssertCommand(self.visit(ctx.condition())), 1)] + + def visitAssumeCommand(self, ctx:tlangParser.AssumeCommandContext): + return [(ChironAST.AssumeCommand(self.visit(ctx.condition())), 1)] + diff --git a/ChironCore/ChironSSA/ChironSSA.py b/ChironCore/ChironSSA/ChironSSA.py index 20eb216..80d6632 100644 --- a/ChironCore/ChironSSA/ChironSSA.py +++ b/ChironCore/ChironSSA/ChironSSA.py @@ -53,6 +53,13 @@ def __init__(self, condition): def __str__(self): return "ASSERT: " + self.cond.__str__() + +class AssumeCommand(Instruction): + def __init__(self, condition): + self.cond = condition + + def __str__(self): + return "ASSUME: " + self.cond.__str__() class MoveCommand(Instruction): def __init__(self, motion, var): diff --git a/ChironCore/ChironSSA/builder.py b/ChironCore/ChironSSA/builder.py index 9c9943e..bf06268 100644 --- a/ChironCore/ChironSSA/builder.py +++ b/ChironCore/ChironSSA/builder.py @@ -63,6 +63,10 @@ def rename(self, block): if isinstance(instr.cond, ChironSSA.Var): instr.cond = ChironSSA.Var(instr.cond.name + "$" + str(self.stack[instr.cond.name][-1])) + elif isinstance(instr, ChironSSA.AssumeCommand): + if isinstance(instr.cond, ChironSSA.Var): + instr.cond = ChironSSA.Var(instr.cond.name + "$" + str(self.stack[instr.cond.name][-1])) + elif isinstance(instr, ChironSSA.ConditionCommand): if isinstance(instr.cond, ChironSSA.Var): instr.cond = ChironSSA.Var(instr.cond.name + "$" + str(self.stack[instr.cond.name][-1])) @@ -161,6 +165,10 @@ def get_globals(self): if isinstance(instr.cond, ChironSSA.Var) and instr.cond.name not in varkill: self.globals.add(instr.cond.name) + elif isinstance(instr, ChironSSA.AssumeCommand): + if isinstance(instr.cond, ChironSSA.Var) and instr.cond.name not in varkill: + self.globals.add(instr.cond.name) + elif isinstance(instr, ChironSSA.ConditionCommand): if isinstance(instr.cond, ChironSSA.Var) and instr.cond.name not in varkill: self.globals.add(instr.cond.name) @@ -190,6 +198,10 @@ def convert(self, ir): cond = ChironSSA.Var(instr.cond.name) if isinstance(instr.cond, ChironTAC.Var) else ChironSSA.BoolTrue() if isinstance(instr.cond, ChironTAC.BoolTrue) else ChironSSA.BoolFalse() ir[ir.index((instr, tgt))] = (ChironSSA.AssertCommand(cond), tgt) + elif isinstance(instr, ChironTAC.AssumeCommand): + cond = ChironSSA.Var(instr.cond.name) if isinstance(instr.cond, ChironTAC.Var) else ChironSSA.BoolTrue() if isinstance(instr.cond, ChironTAC.BoolTrue) else ChironSSA.BoolFalse() + ir[ir.index((instr, tgt))] = (ChironSSA.AssumeCommand(cond), tgt) + elif isinstance(instr, ChironTAC.ConditionCommand): cond = ChironSSA.Var(instr.cond.name) if isinstance(instr.cond, ChironTAC.Var) else ChironSSA.BoolTrue() if isinstance(instr.cond, ChironTAC.BoolTrue) else ChironSSA.BoolFalse() ir[ir.index((instr, tgt))] = (ChironSSA.ConditionCommand(cond), tgt) diff --git a/ChironCore/ChironTAC/ChironTAC.py b/ChironCore/ChironTAC/ChironTAC.py index fd0b063..d792f23 100644 --- a/ChironCore/ChironTAC/ChironTAC.py +++ b/ChironCore/ChironTAC/ChironTAC.py @@ -45,6 +45,13 @@ def __init__(self, condition): def __str__(self): return "ASSERT: " + self.cond.__str__() + +class AssumeCommand(Instruction): + def __init__(self, condition): + self.cond = condition + + def __str__(self): + return "ASSUME: " + self.cond.__str__() class MoveCommand(Instruction): def __init__(self, motion, var): @@ -207,4 +214,4 @@ def __str__(self): class Unused(Value): def __str__(self): - return "" \ No newline at end of file + return "" diff --git a/ChironCore/ChironTAC/builder.py b/ChironCore/ChironTAC/builder.py index 18106e6..311269f 100644 --- a/ChironCore/ChironTAC/builder.py +++ b/ChironCore/ChironTAC/builder.py @@ -13,6 +13,7 @@ def __init__(self, ir): self.tempCount = 0 self.branchCount = 0 self.assertCount = 0 + self.assumeCount = 0 self.moveCount = 0 self.gotoCount = 0 self.ast_to_tac_line = {} @@ -276,6 +277,13 @@ def generateTAC(self): self.parseExpresssion(stmt.cond, assertvar) self.line += 1 self.tac.append((ChironTAC.AssertCommand(assertvar), 1)) + + elif isinstance(stmt, ChironAST.AssumeCommand): + assumevar = ChironTAC.Var(f":__assume_{self.assumeCount}") + self.assumeCount += 1 + self.parseExpresssion(stmt.cond, assumevar) + self.line += 1 + self.tac.append((ChironTAC.AssumeCommand(assumevar), 1)) elif isinstance(stmt, ChironAST.MoveCommand): movevar = None @@ -405,6 +413,9 @@ def getFreeVariables(self): elif isinstance(stmt, ChironTAC.AssertCommand): if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: self.freeVars.add(stmt.cond.__str__()) + elif isinstance(stmt, ChironTAC.AssumeCommand): + if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: + self.freeVars.add(stmt.cond.__str__()) elif isinstance(stmt, ChironTAC.MoveCommand): if isinstance(stmt.var, ChironTAC.Var) and stmt.var.__str__() not in boundVars: self.freeVars.add(stmt.var.__str__()) diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index df20e08..3719825 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -11,6 +11,7 @@ def __init__(self, cfg): self.solver_without_cond = z3.Solver() self.angle_conditions = z3.BoolVal(True) self.assert_conditions = z3.BoolVal(True) + self.assume_conditions = z3.BoolVal(True) self.cfg = cfg self.bbConditions = {} # bbConditions[bb] = condition for bb @@ -197,6 +198,16 @@ def convertSSAtoSMT(self): cond = z3.Bool(stmt.cond.name) self.assert_conditions = z3.And(self.assert_conditions, cond) + elif isinstance(stmt, ChironSSA.AssumeCommand): + cond = None + if isinstance(stmt.cond, ChironSSA.BoolTrue): + cond = z3.BoolVal(True) + elif isinstance(stmt.cond, ChironSSA.BoolFalse): + cond = z3.BoolVal(False) + elif isinstance(stmt.cond, ChironSSA.Var): + cond = z3.Bool(stmt.cond.name) + self.assume_conditions = z3.And(self.assume_conditions, cond) + elif isinstance(stmt, ChironSSA.CosCommand): # Only for 0, 90, 180, 270 degree rvar = z3.Int(stmt.rvar.name) rhs_expr = z3.If(rvar == 0, 1, z3.If(rvar == 90, 0, z3.If(rvar == 180, -1, 0))) @@ -231,10 +242,12 @@ def convertSSAtoSMT(self): self.solver_without_cond.add(self.solver.assertions()) self.assert_conditions = z3.Tactic('ctx-simplify').apply(self.assert_conditions).as_expr() self.angle_conditions = z3.Tactic('ctx-simplify').apply(self.angle_conditions).as_expr() + self.assume_conditions = z3.Tactic('ctx-simplify').apply(self.assume_conditions).as_expr() def solve(self, inputVars): self.solver.add(z3.Not(self.assert_conditions)) self.solver.add(self.angle_conditions) + self.solver.add(self.assume_conditions) # print("The clauses are:") # print(self.solver, end="\n\n") diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index b41d9ea..d998161 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -416,6 +416,22 @@ def stopTurtle(): unrolled_code = unroll.UnrollLoops(unroll_bound).visitStart(getParseTree(args.progfl)) + constraint_count = int(input("Enter the number of constraints in the program: ")) + if constraint_count < 0: + print("Invalid number of constraints. Exiting...") + exit(1) + + if constraint_count != 0: + constraints = [] + for i in range(constraint_count): + constraints.append(input(f"Enter constraint {i+1}: ")) + + constraint_stmt = constraints[0] + for i in range(1, constraint_count): + constraint_stmt = constraint_stmt + " && " + constraints[i] + + unrolled_code = unrolled_code + '\n' + "assume " + constraint_stmt + cond_count = int(input("Enter the number of conditions in the program: ")) if cond_count < 0: diff --git a/ChironCore/example/amogh.tl b/ChironCore/example/amogh.tl new file mode 100644 index 0000000..f0105ae --- /dev/null +++ b/ChironCore/example/amogh.tl @@ -0,0 +1,18 @@ +//:delta = 10 +//repeat 5 [ +// forward :delta +// left 90 +// forward :delta +// left 90 +// :delta = :delta + 10 +//] +// +//:a = 29 +//assert :turtleX >= -:a && :turtleX <= :a && :turtleY >= -:a && :turtleY <= :a + +repeat :a [ + forward 10 +] + +assume :a < 1 +assert :turtleX <= 1 && :turtleX >= -1 && :turtleY <= 1 && :turtleY >= -1 diff --git a/ChironCore/interpreter.py b/ChironCore/interpreter.py index 8188a65..ec56cf5 100644 --- a/ChironCore/interpreter.py +++ b/ChironCore/interpreter.py @@ -109,6 +109,8 @@ def interpret(self): ntgt = self.handleNoOpCommand(stmt, tgt) elif isinstance(stmt, ChironAST.AssertCommand): ntgt = self.handleAssertCommand(stmt, tgt) + elif isinstance(stmt, ChironAST.AssumeCommand): + ntgt = self.handleAssumeCommand(stmt, tgt) else: raise NotImplementedError("Unknown instruction: %s, %s."%(type(stmt), stmt)) @@ -178,3 +180,16 @@ def handleAssertCommand(self, stmt, tgt): print("Exception: ", e) return 1 + + def handleAssumeCommand(self, stmt, tgt): + print(" AssumeCommand") + print(" Assuming: ", stmt.cond) + try: + exec("self.cond_eval = %s" % (addContext(stmt.cond))) + if not self.cond_eval: + raise AssertionError("Assumption Failed!") + except Exception as e: + print("Exception: ", e) + + return 1 + diff --git a/ChironCore/turtparse/tlang.g4 b/ChironCore/turtparse/tlang.g4 index a45d389..ff6c103 100644 --- a/ChironCore/turtparse/tlang.g4 +++ b/ChironCore/turtparse/tlang.g4 @@ -18,6 +18,7 @@ instruction : assignment | gotoCommand | pauseCommand | assertionCommand + | assumeCommand ; conditional : ifConditional | ifElseConditional ; @@ -42,6 +43,8 @@ pauseCommand : 'pause' ; assertionCommand : 'assert' condition ; +assumeCommand : 'assume' condition ; + expression : unaryArithOp expression #unaryExpr | expression multiplicative expression #mulExpr diff --git a/ChironCore/turtparse/tlang.interp b/ChironCore/turtparse/tlang.interp index c709152..eb06ca0 100644 --- a/ChironCore/turtparse/tlang.interp +++ b/ChironCore/turtparse/tlang.interp @@ -18,6 +18,7 @@ null 'pendown' 'pause' 'assert' +'assume' '+' '-' '*' @@ -59,6 +60,7 @@ null null null null +null PLUS MINUS MUL @@ -96,6 +98,7 @@ moveOp penCommand pauseCommand assertionCommand +assumeCommand expression multiplicative additive @@ -108,4 +111,4 @@ value atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 40, 189, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 55, 10, 3, 12, 3, 14, 3, 58, 11, 3, 3, 4, 6, 4, 61, 10, 4, 13, 4, 14, 4, 62, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 73, 10, 5, 3, 6, 3, 6, 5, 6, 77, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 5, 17, 133, 10, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 147, 10, 17, 12, 17, 14, 17, 150, 11, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 172, 10, 22, 3, 22, 3, 22, 3, 22, 3, 22, 7, 22, 178, 10, 22, 12, 22, 14, 22, 181, 11, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 2, 4, 32, 42, 26, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 2, 9, 3, 2, 13, 16, 3, 2, 17, 18, 3, 2, 23, 24, 3, 2, 21, 22, 3, 2, 27, 32, 3, 2, 33, 34, 3, 2, 36, 37, 2, 183, 2, 50, 3, 2, 2, 2, 4, 56, 3, 2, 2, 2, 6, 60, 3, 2, 2, 2, 8, 72, 3, 2, 2, 2, 10, 76, 3, 2, 2, 2, 12, 78, 3, 2, 2, 2, 14, 84, 3, 2, 2, 2, 16, 94, 3, 2, 2, 2, 18, 100, 3, 2, 2, 2, 20, 107, 3, 2, 2, 2, 22, 111, 3, 2, 2, 2, 24, 114, 3, 2, 2, 2, 26, 116, 3, 2, 2, 2, 28, 118, 3, 2, 2, 2, 30, 120, 3, 2, 2, 2, 32, 132, 3, 2, 2, 2, 34, 151, 3, 2, 2, 2, 36, 153, 3, 2, 2, 2, 38, 155, 3, 2, 2, 2, 40, 157, 3, 2, 2, 2, 42, 171, 3, 2, 2, 2, 44, 182, 3, 2, 2, 2, 46, 184, 3, 2, 2, 2, 48, 186, 3, 2, 2, 2, 50, 51, 5, 4, 3, 2, 51, 52, 7, 2, 2, 3, 52, 3, 3, 2, 2, 2, 53, 55, 5, 8, 5, 2, 54, 53, 3, 2, 2, 2, 55, 58, 3, 2, 2, 2, 56, 54, 3, 2, 2, 2, 56, 57, 3, 2, 2, 2, 57, 5, 3, 2, 2, 2, 58, 56, 3, 2, 2, 2, 59, 61, 5, 8, 5, 2, 60, 59, 3, 2, 2, 2, 61, 62, 3, 2, 2, 2, 62, 60, 3, 2, 2, 2, 62, 63, 3, 2, 2, 2, 63, 7, 3, 2, 2, 2, 64, 73, 5, 20, 11, 2, 65, 73, 5, 10, 6, 2, 66, 73, 5, 16, 9, 2, 67, 73, 5, 22, 12, 2, 68, 73, 5, 26, 14, 2, 69, 73, 5, 18, 10, 2, 70, 73, 5, 28, 15, 2, 71, 73, 5, 30, 16, 2, 72, 64, 3, 2, 2, 2, 72, 65, 3, 2, 2, 2, 72, 66, 3, 2, 2, 2, 72, 67, 3, 2, 2, 2, 72, 68, 3, 2, 2, 2, 72, 69, 3, 2, 2, 2, 72, 70, 3, 2, 2, 2, 72, 71, 3, 2, 2, 2, 73, 9, 3, 2, 2, 2, 74, 77, 5, 12, 7, 2, 75, 77, 5, 14, 8, 2, 76, 74, 3, 2, 2, 2, 76, 75, 3, 2, 2, 2, 77, 11, 3, 2, 2, 2, 78, 79, 7, 3, 2, 2, 79, 80, 5, 42, 22, 2, 80, 81, 7, 4, 2, 2, 81, 82, 5, 6, 4, 2, 82, 83, 7, 5, 2, 2, 83, 13, 3, 2, 2, 2, 84, 85, 7, 3, 2, 2, 85, 86, 5, 42, 22, 2, 86, 87, 7, 4, 2, 2, 87, 88, 5, 6, 4, 2, 88, 89, 7, 5, 2, 2, 89, 90, 7, 6, 2, 2, 90, 91, 7, 4, 2, 2, 91, 92, 5, 6, 4, 2, 92, 93, 7, 5, 2, 2, 93, 15, 3, 2, 2, 2, 94, 95, 7, 7, 2, 2, 95, 96, 5, 48, 25, 2, 96, 97, 7, 4, 2, 2, 97, 98, 5, 6, 4, 2, 98, 99, 7, 5, 2, 2, 99, 17, 3, 2, 2, 2, 100, 101, 7, 8, 2, 2, 101, 102, 7, 9, 2, 2, 102, 103, 5, 32, 17, 2, 103, 104, 7, 10, 2, 2, 104, 105, 5, 32, 17, 2, 105, 106, 7, 11, 2, 2, 106, 19, 3, 2, 2, 2, 107, 108, 7, 37, 2, 2, 108, 109, 7, 12, 2, 2, 109, 110, 5, 32, 17, 2, 110, 21, 3, 2, 2, 2, 111, 112, 5, 24, 13, 2, 112, 113, 5, 32, 17, 2, 113, 23, 3, 2, 2, 2, 114, 115, 9, 2, 2, 2, 115, 25, 3, 2, 2, 2, 116, 117, 9, 3, 2, 2, 117, 27, 3, 2, 2, 2, 118, 119, 7, 19, 2, 2, 119, 29, 3, 2, 2, 2, 120, 121, 7, 20, 2, 2, 121, 122, 5, 42, 22, 2, 122, 31, 3, 2, 2, 2, 123, 124, 8, 17, 1, 2, 124, 125, 5, 40, 21, 2, 125, 126, 5, 32, 17, 8, 126, 133, 3, 2, 2, 2, 127, 133, 5, 48, 25, 2, 128, 129, 7, 9, 2, 2, 129, 130, 5, 32, 17, 2, 130, 131, 7, 11, 2, 2, 131, 133, 3, 2, 2, 2, 132, 123, 3, 2, 2, 2, 132, 127, 3, 2, 2, 2, 132, 128, 3, 2, 2, 2, 133, 148, 3, 2, 2, 2, 134, 135, 12, 7, 2, 2, 135, 136, 5, 34, 18, 2, 136, 137, 5, 32, 17, 8, 137, 147, 3, 2, 2, 2, 138, 139, 12, 6, 2, 2, 139, 140, 5, 36, 19, 2, 140, 141, 5, 32, 17, 7, 141, 147, 3, 2, 2, 2, 142, 143, 12, 5, 2, 2, 143, 144, 5, 38, 20, 2, 144, 145, 5, 32, 17, 6, 145, 147, 3, 2, 2, 2, 146, 134, 3, 2, 2, 2, 146, 138, 3, 2, 2, 2, 146, 142, 3, 2, 2, 2, 147, 150, 3, 2, 2, 2, 148, 146, 3, 2, 2, 2, 148, 149, 3, 2, 2, 2, 149, 33, 3, 2, 2, 2, 150, 148, 3, 2, 2, 2, 151, 152, 9, 4, 2, 2, 152, 35, 3, 2, 2, 2, 153, 154, 9, 5, 2, 2, 154, 37, 3, 2, 2, 2, 155, 156, 7, 25, 2, 2, 156, 39, 3, 2, 2, 2, 157, 158, 7, 22, 2, 2, 158, 41, 3, 2, 2, 2, 159, 160, 8, 22, 1, 2, 160, 161, 7, 35, 2, 2, 161, 172, 5, 42, 22, 7, 162, 163, 5, 32, 17, 2, 163, 164, 5, 44, 23, 2, 164, 165, 5, 32, 17, 2, 165, 172, 3, 2, 2, 2, 166, 172, 7, 26, 2, 2, 167, 168, 7, 9, 2, 2, 168, 169, 5, 42, 22, 2, 169, 170, 7, 11, 2, 2, 170, 172, 3, 2, 2, 2, 171, 159, 3, 2, 2, 2, 171, 162, 3, 2, 2, 2, 171, 166, 3, 2, 2, 2, 171, 167, 3, 2, 2, 2, 172, 179, 3, 2, 2, 2, 173, 174, 12, 5, 2, 2, 174, 175, 5, 46, 24, 2, 175, 176, 5, 42, 22, 6, 176, 178, 3, 2, 2, 2, 177, 173, 3, 2, 2, 2, 178, 181, 3, 2, 2, 2, 179, 177, 3, 2, 2, 2, 179, 180, 3, 2, 2, 2, 180, 43, 3, 2, 2, 2, 181, 179, 3, 2, 2, 2, 182, 183, 9, 6, 2, 2, 183, 45, 3, 2, 2, 2, 184, 185, 9, 7, 2, 2, 185, 47, 3, 2, 2, 2, 186, 187, 9, 8, 2, 2, 187, 49, 3, 2, 2, 2, 11, 56, 62, 72, 76, 132, 146, 148, 171, 179] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 41, 195, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 57, 10, 3, 12, 3, 14, 3, 60, 11, 3, 3, 4, 6, 4, 63, 10, 4, 13, 4, 14, 4, 64, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 76, 10, 5, 3, 6, 3, 6, 5, 6, 80, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 139, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 153, 10, 18, 12, 18, 14, 18, 156, 11, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 178, 10, 23, 3, 23, 3, 23, 3, 23, 3, 23, 7, 23, 184, 10, 23, 12, 23, 14, 23, 187, 11, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 2, 4, 34, 44, 27, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 2, 9, 3, 2, 13, 16, 3, 2, 17, 18, 3, 2, 24, 25, 3, 2, 22, 23, 3, 2, 28, 33, 3, 2, 34, 35, 3, 2, 37, 38, 2, 189, 2, 52, 3, 2, 2, 2, 4, 58, 3, 2, 2, 2, 6, 62, 3, 2, 2, 2, 8, 75, 3, 2, 2, 2, 10, 79, 3, 2, 2, 2, 12, 81, 3, 2, 2, 2, 14, 87, 3, 2, 2, 2, 16, 97, 3, 2, 2, 2, 18, 103, 3, 2, 2, 2, 20, 110, 3, 2, 2, 2, 22, 114, 3, 2, 2, 2, 24, 117, 3, 2, 2, 2, 26, 119, 3, 2, 2, 2, 28, 121, 3, 2, 2, 2, 30, 123, 3, 2, 2, 2, 32, 126, 3, 2, 2, 2, 34, 138, 3, 2, 2, 2, 36, 157, 3, 2, 2, 2, 38, 159, 3, 2, 2, 2, 40, 161, 3, 2, 2, 2, 42, 163, 3, 2, 2, 2, 44, 177, 3, 2, 2, 2, 46, 188, 3, 2, 2, 2, 48, 190, 3, 2, 2, 2, 50, 192, 3, 2, 2, 2, 52, 53, 5, 4, 3, 2, 53, 54, 7, 2, 2, 3, 54, 3, 3, 2, 2, 2, 55, 57, 5, 8, 5, 2, 56, 55, 3, 2, 2, 2, 57, 60, 3, 2, 2, 2, 58, 56, 3, 2, 2, 2, 58, 59, 3, 2, 2, 2, 59, 5, 3, 2, 2, 2, 60, 58, 3, 2, 2, 2, 61, 63, 5, 8, 5, 2, 62, 61, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 62, 3, 2, 2, 2, 64, 65, 3, 2, 2, 2, 65, 7, 3, 2, 2, 2, 66, 76, 5, 20, 11, 2, 67, 76, 5, 10, 6, 2, 68, 76, 5, 16, 9, 2, 69, 76, 5, 22, 12, 2, 70, 76, 5, 26, 14, 2, 71, 76, 5, 18, 10, 2, 72, 76, 5, 28, 15, 2, 73, 76, 5, 30, 16, 2, 74, 76, 5, 32, 17, 2, 75, 66, 3, 2, 2, 2, 75, 67, 3, 2, 2, 2, 75, 68, 3, 2, 2, 2, 75, 69, 3, 2, 2, 2, 75, 70, 3, 2, 2, 2, 75, 71, 3, 2, 2, 2, 75, 72, 3, 2, 2, 2, 75, 73, 3, 2, 2, 2, 75, 74, 3, 2, 2, 2, 76, 9, 3, 2, 2, 2, 77, 80, 5, 12, 7, 2, 78, 80, 5, 14, 8, 2, 79, 77, 3, 2, 2, 2, 79, 78, 3, 2, 2, 2, 80, 11, 3, 2, 2, 2, 81, 82, 7, 3, 2, 2, 82, 83, 5, 44, 23, 2, 83, 84, 7, 4, 2, 2, 84, 85, 5, 6, 4, 2, 85, 86, 7, 5, 2, 2, 86, 13, 3, 2, 2, 2, 87, 88, 7, 3, 2, 2, 88, 89, 5, 44, 23, 2, 89, 90, 7, 4, 2, 2, 90, 91, 5, 6, 4, 2, 91, 92, 7, 5, 2, 2, 92, 93, 7, 6, 2, 2, 93, 94, 7, 4, 2, 2, 94, 95, 5, 6, 4, 2, 95, 96, 7, 5, 2, 2, 96, 15, 3, 2, 2, 2, 97, 98, 7, 7, 2, 2, 98, 99, 5, 50, 26, 2, 99, 100, 7, 4, 2, 2, 100, 101, 5, 6, 4, 2, 101, 102, 7, 5, 2, 2, 102, 17, 3, 2, 2, 2, 103, 104, 7, 8, 2, 2, 104, 105, 7, 9, 2, 2, 105, 106, 5, 34, 18, 2, 106, 107, 7, 10, 2, 2, 107, 108, 5, 34, 18, 2, 108, 109, 7, 11, 2, 2, 109, 19, 3, 2, 2, 2, 110, 111, 7, 38, 2, 2, 111, 112, 7, 12, 2, 2, 112, 113, 5, 34, 18, 2, 113, 21, 3, 2, 2, 2, 114, 115, 5, 24, 13, 2, 115, 116, 5, 34, 18, 2, 116, 23, 3, 2, 2, 2, 117, 118, 9, 2, 2, 2, 118, 25, 3, 2, 2, 2, 119, 120, 9, 3, 2, 2, 120, 27, 3, 2, 2, 2, 121, 122, 7, 19, 2, 2, 122, 29, 3, 2, 2, 2, 123, 124, 7, 20, 2, 2, 124, 125, 5, 44, 23, 2, 125, 31, 3, 2, 2, 2, 126, 127, 7, 21, 2, 2, 127, 128, 5, 44, 23, 2, 128, 33, 3, 2, 2, 2, 129, 130, 8, 18, 1, 2, 130, 131, 5, 42, 22, 2, 131, 132, 5, 34, 18, 8, 132, 139, 3, 2, 2, 2, 133, 139, 5, 50, 26, 2, 134, 135, 7, 9, 2, 2, 135, 136, 5, 34, 18, 2, 136, 137, 7, 11, 2, 2, 137, 139, 3, 2, 2, 2, 138, 129, 3, 2, 2, 2, 138, 133, 3, 2, 2, 2, 138, 134, 3, 2, 2, 2, 139, 154, 3, 2, 2, 2, 140, 141, 12, 7, 2, 2, 141, 142, 5, 36, 19, 2, 142, 143, 5, 34, 18, 8, 143, 153, 3, 2, 2, 2, 144, 145, 12, 6, 2, 2, 145, 146, 5, 38, 20, 2, 146, 147, 5, 34, 18, 7, 147, 153, 3, 2, 2, 2, 148, 149, 12, 5, 2, 2, 149, 150, 5, 40, 21, 2, 150, 151, 5, 34, 18, 6, 151, 153, 3, 2, 2, 2, 152, 140, 3, 2, 2, 2, 152, 144, 3, 2, 2, 2, 152, 148, 3, 2, 2, 2, 153, 156, 3, 2, 2, 2, 154, 152, 3, 2, 2, 2, 154, 155, 3, 2, 2, 2, 155, 35, 3, 2, 2, 2, 156, 154, 3, 2, 2, 2, 157, 158, 9, 4, 2, 2, 158, 37, 3, 2, 2, 2, 159, 160, 9, 5, 2, 2, 160, 39, 3, 2, 2, 2, 161, 162, 7, 26, 2, 2, 162, 41, 3, 2, 2, 2, 163, 164, 7, 23, 2, 2, 164, 43, 3, 2, 2, 2, 165, 166, 8, 23, 1, 2, 166, 167, 7, 36, 2, 2, 167, 178, 5, 44, 23, 7, 168, 169, 5, 34, 18, 2, 169, 170, 5, 46, 24, 2, 170, 171, 5, 34, 18, 2, 171, 178, 3, 2, 2, 2, 172, 178, 7, 27, 2, 2, 173, 174, 7, 9, 2, 2, 174, 175, 5, 44, 23, 2, 175, 176, 7, 11, 2, 2, 176, 178, 3, 2, 2, 2, 177, 165, 3, 2, 2, 2, 177, 168, 3, 2, 2, 2, 177, 172, 3, 2, 2, 2, 177, 173, 3, 2, 2, 2, 178, 185, 3, 2, 2, 2, 179, 180, 12, 5, 2, 2, 180, 181, 5, 48, 25, 2, 181, 182, 5, 44, 23, 6, 182, 184, 3, 2, 2, 2, 183, 179, 3, 2, 2, 2, 184, 187, 3, 2, 2, 2, 185, 183, 3, 2, 2, 2, 185, 186, 3, 2, 2, 2, 186, 45, 3, 2, 2, 2, 187, 185, 3, 2, 2, 2, 188, 189, 9, 6, 2, 2, 189, 47, 3, 2, 2, 2, 190, 191, 9, 7, 2, 2, 191, 49, 3, 2, 2, 2, 192, 193, 9, 8, 2, 2, 193, 51, 3, 2, 2, 2, 11, 58, 64, 75, 79, 138, 152, 154, 177, 185] \ No newline at end of file diff --git a/ChironCore/turtparse/tlang.tokens b/ChironCore/turtparse/tlang.tokens index 2c2f507..ee84fda 100644 --- a/ChironCore/turtparse/tlang.tokens +++ b/ChironCore/turtparse/tlang.tokens @@ -16,26 +16,27 @@ T__14=15 T__15=16 T__16=17 T__17=18 -PLUS=19 -MINUS=20 -MUL=21 -DIV=22 -MOD=23 -PENCOND=24 -LT=25 -GT=26 -EQ=27 -NEQ=28 -LTE=29 -GTE=30 -AND=31 -OR=32 -NOT=33 -NUM=34 -VAR=35 -NAME=36 -Whitespace=37 -Comment=38 +T__18=19 +PLUS=20 +MINUS=21 +MUL=22 +DIV=23 +MOD=24 +PENCOND=25 +LT=26 +GT=27 +EQ=28 +NEQ=29 +LTE=30 +GTE=31 +AND=32 +OR=33 +NOT=34 +NUM=35 +VAR=36 +NAME=37 +Whitespace=38 +Comment=39 'if'=1 '['=2 ']'=3 @@ -54,18 +55,19 @@ Comment=38 'pendown'=16 'pause'=17 'assert'=18 -'+'=19 -'-'=20 -'*'=21 -'/'=22 -'%'=23 -'pendown?'=24 -'<'=25 -'>'=26 -'=='=27 -'!='=28 -'<='=29 -'>='=30 -'&&'=31 -'||'=32 -'!'=33 +'assume'=19 +'+'=20 +'-'=21 +'*'=22 +'/'=23 +'%'=24 +'pendown?'=25 +'<'=26 +'>'=27 +'=='=28 +'!='=29 +'<='=30 +'>='=31 +'&&'=32 +'||'=33 +'!'=34 diff --git a/ChironCore/turtparse/tlangLexer.interp b/ChironCore/turtparse/tlangLexer.interp index 964b7b8..68fc09f 100644 --- a/ChironCore/turtparse/tlangLexer.interp +++ b/ChironCore/turtparse/tlangLexer.interp @@ -18,6 +18,7 @@ null 'pendown' 'pause' 'assert' +'assume' '+' '-' '*' @@ -59,6 +60,7 @@ null null null null +null PLUS MINUS MUL @@ -99,6 +101,7 @@ T__14 T__15 T__16 T__17 +T__18 PLUS MINUS MUL @@ -128,4 +131,4 @@ mode names: DEFAULT_MODE atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 40, 245, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 6, 35, 211, 10, 35, 13, 35, 14, 35, 212, 3, 36, 3, 36, 3, 36, 7, 36, 218, 10, 36, 12, 36, 14, 36, 221, 11, 36, 3, 37, 6, 37, 224, 10, 37, 13, 37, 14, 37, 225, 3, 38, 6, 38, 229, 10, 38, 13, 38, 14, 38, 230, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 7, 39, 239, 10, 39, 12, 39, 14, 39, 242, 11, 39, 3, 39, 3, 39, 2, 2, 40, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 3, 2, 8, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 249, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 3, 79, 3, 2, 2, 2, 5, 82, 3, 2, 2, 2, 7, 84, 3, 2, 2, 2, 9, 86, 3, 2, 2, 2, 11, 91, 3, 2, 2, 2, 13, 98, 3, 2, 2, 2, 15, 103, 3, 2, 2, 2, 17, 105, 3, 2, 2, 2, 19, 107, 3, 2, 2, 2, 21, 109, 3, 2, 2, 2, 23, 111, 3, 2, 2, 2, 25, 119, 3, 2, 2, 2, 27, 128, 3, 2, 2, 2, 29, 133, 3, 2, 2, 2, 31, 139, 3, 2, 2, 2, 33, 145, 3, 2, 2, 2, 35, 153, 3, 2, 2, 2, 37, 159, 3, 2, 2, 2, 39, 166, 3, 2, 2, 2, 41, 168, 3, 2, 2, 2, 43, 170, 3, 2, 2, 2, 45, 172, 3, 2, 2, 2, 47, 174, 3, 2, 2, 2, 49, 176, 3, 2, 2, 2, 51, 185, 3, 2, 2, 2, 53, 187, 3, 2, 2, 2, 55, 189, 3, 2, 2, 2, 57, 192, 3, 2, 2, 2, 59, 195, 3, 2, 2, 2, 61, 198, 3, 2, 2, 2, 63, 201, 3, 2, 2, 2, 65, 204, 3, 2, 2, 2, 67, 207, 3, 2, 2, 2, 69, 210, 3, 2, 2, 2, 71, 214, 3, 2, 2, 2, 73, 223, 3, 2, 2, 2, 75, 228, 3, 2, 2, 2, 77, 234, 3, 2, 2, 2, 79, 80, 7, 107, 2, 2, 80, 81, 7, 104, 2, 2, 81, 4, 3, 2, 2, 2, 82, 83, 7, 93, 2, 2, 83, 6, 3, 2, 2, 2, 84, 85, 7, 95, 2, 2, 85, 8, 3, 2, 2, 2, 86, 87, 7, 103, 2, 2, 87, 88, 7, 110, 2, 2, 88, 89, 7, 117, 2, 2, 89, 90, 7, 103, 2, 2, 90, 10, 3, 2, 2, 2, 91, 92, 7, 116, 2, 2, 92, 93, 7, 103, 2, 2, 93, 94, 7, 114, 2, 2, 94, 95, 7, 103, 2, 2, 95, 96, 7, 99, 2, 2, 96, 97, 7, 118, 2, 2, 97, 12, 3, 2, 2, 2, 98, 99, 7, 105, 2, 2, 99, 100, 7, 113, 2, 2, 100, 101, 7, 118, 2, 2, 101, 102, 7, 113, 2, 2, 102, 14, 3, 2, 2, 2, 103, 104, 7, 42, 2, 2, 104, 16, 3, 2, 2, 2, 105, 106, 7, 46, 2, 2, 106, 18, 3, 2, 2, 2, 107, 108, 7, 43, 2, 2, 108, 20, 3, 2, 2, 2, 109, 110, 7, 63, 2, 2, 110, 22, 3, 2, 2, 2, 111, 112, 7, 104, 2, 2, 112, 113, 7, 113, 2, 2, 113, 114, 7, 116, 2, 2, 114, 115, 7, 121, 2, 2, 115, 116, 7, 99, 2, 2, 116, 117, 7, 116, 2, 2, 117, 118, 7, 102, 2, 2, 118, 24, 3, 2, 2, 2, 119, 120, 7, 100, 2, 2, 120, 121, 7, 99, 2, 2, 121, 122, 7, 101, 2, 2, 122, 123, 7, 109, 2, 2, 123, 124, 7, 121, 2, 2, 124, 125, 7, 99, 2, 2, 125, 126, 7, 116, 2, 2, 126, 127, 7, 102, 2, 2, 127, 26, 3, 2, 2, 2, 128, 129, 7, 110, 2, 2, 129, 130, 7, 103, 2, 2, 130, 131, 7, 104, 2, 2, 131, 132, 7, 118, 2, 2, 132, 28, 3, 2, 2, 2, 133, 134, 7, 116, 2, 2, 134, 135, 7, 107, 2, 2, 135, 136, 7, 105, 2, 2, 136, 137, 7, 106, 2, 2, 137, 138, 7, 118, 2, 2, 138, 30, 3, 2, 2, 2, 139, 140, 7, 114, 2, 2, 140, 141, 7, 103, 2, 2, 141, 142, 7, 112, 2, 2, 142, 143, 7, 119, 2, 2, 143, 144, 7, 114, 2, 2, 144, 32, 3, 2, 2, 2, 145, 146, 7, 114, 2, 2, 146, 147, 7, 103, 2, 2, 147, 148, 7, 112, 2, 2, 148, 149, 7, 102, 2, 2, 149, 150, 7, 113, 2, 2, 150, 151, 7, 121, 2, 2, 151, 152, 7, 112, 2, 2, 152, 34, 3, 2, 2, 2, 153, 154, 7, 114, 2, 2, 154, 155, 7, 99, 2, 2, 155, 156, 7, 119, 2, 2, 156, 157, 7, 117, 2, 2, 157, 158, 7, 103, 2, 2, 158, 36, 3, 2, 2, 2, 159, 160, 7, 99, 2, 2, 160, 161, 7, 117, 2, 2, 161, 162, 7, 117, 2, 2, 162, 163, 7, 103, 2, 2, 163, 164, 7, 116, 2, 2, 164, 165, 7, 118, 2, 2, 165, 38, 3, 2, 2, 2, 166, 167, 7, 45, 2, 2, 167, 40, 3, 2, 2, 2, 168, 169, 7, 47, 2, 2, 169, 42, 3, 2, 2, 2, 170, 171, 7, 44, 2, 2, 171, 44, 3, 2, 2, 2, 172, 173, 7, 49, 2, 2, 173, 46, 3, 2, 2, 2, 174, 175, 7, 39, 2, 2, 175, 48, 3, 2, 2, 2, 176, 177, 7, 114, 2, 2, 177, 178, 7, 103, 2, 2, 178, 179, 7, 112, 2, 2, 179, 180, 7, 102, 2, 2, 180, 181, 7, 113, 2, 2, 181, 182, 7, 121, 2, 2, 182, 183, 7, 112, 2, 2, 183, 184, 7, 65, 2, 2, 184, 50, 3, 2, 2, 2, 185, 186, 7, 62, 2, 2, 186, 52, 3, 2, 2, 2, 187, 188, 7, 64, 2, 2, 188, 54, 3, 2, 2, 2, 189, 190, 7, 63, 2, 2, 190, 191, 7, 63, 2, 2, 191, 56, 3, 2, 2, 2, 192, 193, 7, 35, 2, 2, 193, 194, 7, 63, 2, 2, 194, 58, 3, 2, 2, 2, 195, 196, 7, 62, 2, 2, 196, 197, 7, 63, 2, 2, 197, 60, 3, 2, 2, 2, 198, 199, 7, 64, 2, 2, 199, 200, 7, 63, 2, 2, 200, 62, 3, 2, 2, 2, 201, 202, 7, 40, 2, 2, 202, 203, 7, 40, 2, 2, 203, 64, 3, 2, 2, 2, 204, 205, 7, 126, 2, 2, 205, 206, 7, 126, 2, 2, 206, 66, 3, 2, 2, 2, 207, 208, 7, 35, 2, 2, 208, 68, 3, 2, 2, 2, 209, 211, 9, 2, 2, 2, 210, 209, 3, 2, 2, 2, 211, 212, 3, 2, 2, 2, 212, 210, 3, 2, 2, 2, 212, 213, 3, 2, 2, 2, 213, 70, 3, 2, 2, 2, 214, 215, 7, 60, 2, 2, 215, 219, 9, 3, 2, 2, 216, 218, 9, 4, 2, 2, 217, 216, 3, 2, 2, 2, 218, 221, 3, 2, 2, 2, 219, 217, 3, 2, 2, 2, 219, 220, 3, 2, 2, 2, 220, 72, 3, 2, 2, 2, 221, 219, 3, 2, 2, 2, 222, 224, 9, 5, 2, 2, 223, 222, 3, 2, 2, 2, 224, 225, 3, 2, 2, 2, 225, 223, 3, 2, 2, 2, 225, 226, 3, 2, 2, 2, 226, 74, 3, 2, 2, 2, 227, 229, 9, 6, 2, 2, 228, 227, 3, 2, 2, 2, 229, 230, 3, 2, 2, 2, 230, 228, 3, 2, 2, 2, 230, 231, 3, 2, 2, 2, 231, 232, 3, 2, 2, 2, 232, 233, 8, 38, 2, 2, 233, 76, 3, 2, 2, 2, 234, 235, 7, 49, 2, 2, 235, 236, 7, 49, 2, 2, 236, 240, 3, 2, 2, 2, 237, 239, 10, 7, 2, 2, 238, 237, 3, 2, 2, 2, 239, 242, 3, 2, 2, 2, 240, 238, 3, 2, 2, 2, 240, 241, 3, 2, 2, 2, 241, 243, 3, 2, 2, 2, 242, 240, 3, 2, 2, 2, 243, 244, 8, 39, 2, 2, 244, 78, 3, 2, 2, 2, 8, 2, 212, 219, 225, 230, 240, 3, 8, 2, 2] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 41, 254, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 6, 36, 220, 10, 36, 13, 36, 14, 36, 221, 3, 37, 3, 37, 3, 37, 7, 37, 227, 10, 37, 12, 37, 14, 37, 230, 11, 37, 3, 38, 6, 38, 233, 10, 38, 13, 38, 14, 38, 234, 3, 39, 6, 39, 238, 10, 39, 13, 39, 14, 39, 239, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 7, 40, 248, 10, 40, 12, 40, 14, 40, 251, 11, 40, 3, 40, 3, 40, 2, 2, 41, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 3, 2, 8, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 258, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 3, 81, 3, 2, 2, 2, 5, 84, 3, 2, 2, 2, 7, 86, 3, 2, 2, 2, 9, 88, 3, 2, 2, 2, 11, 93, 3, 2, 2, 2, 13, 100, 3, 2, 2, 2, 15, 105, 3, 2, 2, 2, 17, 107, 3, 2, 2, 2, 19, 109, 3, 2, 2, 2, 21, 111, 3, 2, 2, 2, 23, 113, 3, 2, 2, 2, 25, 121, 3, 2, 2, 2, 27, 130, 3, 2, 2, 2, 29, 135, 3, 2, 2, 2, 31, 141, 3, 2, 2, 2, 33, 147, 3, 2, 2, 2, 35, 155, 3, 2, 2, 2, 37, 161, 3, 2, 2, 2, 39, 168, 3, 2, 2, 2, 41, 175, 3, 2, 2, 2, 43, 177, 3, 2, 2, 2, 45, 179, 3, 2, 2, 2, 47, 181, 3, 2, 2, 2, 49, 183, 3, 2, 2, 2, 51, 185, 3, 2, 2, 2, 53, 194, 3, 2, 2, 2, 55, 196, 3, 2, 2, 2, 57, 198, 3, 2, 2, 2, 59, 201, 3, 2, 2, 2, 61, 204, 3, 2, 2, 2, 63, 207, 3, 2, 2, 2, 65, 210, 3, 2, 2, 2, 67, 213, 3, 2, 2, 2, 69, 216, 3, 2, 2, 2, 71, 219, 3, 2, 2, 2, 73, 223, 3, 2, 2, 2, 75, 232, 3, 2, 2, 2, 77, 237, 3, 2, 2, 2, 79, 243, 3, 2, 2, 2, 81, 82, 7, 107, 2, 2, 82, 83, 7, 104, 2, 2, 83, 4, 3, 2, 2, 2, 84, 85, 7, 93, 2, 2, 85, 6, 3, 2, 2, 2, 86, 87, 7, 95, 2, 2, 87, 8, 3, 2, 2, 2, 88, 89, 7, 103, 2, 2, 89, 90, 7, 110, 2, 2, 90, 91, 7, 117, 2, 2, 91, 92, 7, 103, 2, 2, 92, 10, 3, 2, 2, 2, 93, 94, 7, 116, 2, 2, 94, 95, 7, 103, 2, 2, 95, 96, 7, 114, 2, 2, 96, 97, 7, 103, 2, 2, 97, 98, 7, 99, 2, 2, 98, 99, 7, 118, 2, 2, 99, 12, 3, 2, 2, 2, 100, 101, 7, 105, 2, 2, 101, 102, 7, 113, 2, 2, 102, 103, 7, 118, 2, 2, 103, 104, 7, 113, 2, 2, 104, 14, 3, 2, 2, 2, 105, 106, 7, 42, 2, 2, 106, 16, 3, 2, 2, 2, 107, 108, 7, 46, 2, 2, 108, 18, 3, 2, 2, 2, 109, 110, 7, 43, 2, 2, 110, 20, 3, 2, 2, 2, 111, 112, 7, 63, 2, 2, 112, 22, 3, 2, 2, 2, 113, 114, 7, 104, 2, 2, 114, 115, 7, 113, 2, 2, 115, 116, 7, 116, 2, 2, 116, 117, 7, 121, 2, 2, 117, 118, 7, 99, 2, 2, 118, 119, 7, 116, 2, 2, 119, 120, 7, 102, 2, 2, 120, 24, 3, 2, 2, 2, 121, 122, 7, 100, 2, 2, 122, 123, 7, 99, 2, 2, 123, 124, 7, 101, 2, 2, 124, 125, 7, 109, 2, 2, 125, 126, 7, 121, 2, 2, 126, 127, 7, 99, 2, 2, 127, 128, 7, 116, 2, 2, 128, 129, 7, 102, 2, 2, 129, 26, 3, 2, 2, 2, 130, 131, 7, 110, 2, 2, 131, 132, 7, 103, 2, 2, 132, 133, 7, 104, 2, 2, 133, 134, 7, 118, 2, 2, 134, 28, 3, 2, 2, 2, 135, 136, 7, 116, 2, 2, 136, 137, 7, 107, 2, 2, 137, 138, 7, 105, 2, 2, 138, 139, 7, 106, 2, 2, 139, 140, 7, 118, 2, 2, 140, 30, 3, 2, 2, 2, 141, 142, 7, 114, 2, 2, 142, 143, 7, 103, 2, 2, 143, 144, 7, 112, 2, 2, 144, 145, 7, 119, 2, 2, 145, 146, 7, 114, 2, 2, 146, 32, 3, 2, 2, 2, 147, 148, 7, 114, 2, 2, 148, 149, 7, 103, 2, 2, 149, 150, 7, 112, 2, 2, 150, 151, 7, 102, 2, 2, 151, 152, 7, 113, 2, 2, 152, 153, 7, 121, 2, 2, 153, 154, 7, 112, 2, 2, 154, 34, 3, 2, 2, 2, 155, 156, 7, 114, 2, 2, 156, 157, 7, 99, 2, 2, 157, 158, 7, 119, 2, 2, 158, 159, 7, 117, 2, 2, 159, 160, 7, 103, 2, 2, 160, 36, 3, 2, 2, 2, 161, 162, 7, 99, 2, 2, 162, 163, 7, 117, 2, 2, 163, 164, 7, 117, 2, 2, 164, 165, 7, 103, 2, 2, 165, 166, 7, 116, 2, 2, 166, 167, 7, 118, 2, 2, 167, 38, 3, 2, 2, 2, 168, 169, 7, 99, 2, 2, 169, 170, 7, 117, 2, 2, 170, 171, 7, 117, 2, 2, 171, 172, 7, 119, 2, 2, 172, 173, 7, 111, 2, 2, 173, 174, 7, 103, 2, 2, 174, 40, 3, 2, 2, 2, 175, 176, 7, 45, 2, 2, 176, 42, 3, 2, 2, 2, 177, 178, 7, 47, 2, 2, 178, 44, 3, 2, 2, 2, 179, 180, 7, 44, 2, 2, 180, 46, 3, 2, 2, 2, 181, 182, 7, 49, 2, 2, 182, 48, 3, 2, 2, 2, 183, 184, 7, 39, 2, 2, 184, 50, 3, 2, 2, 2, 185, 186, 7, 114, 2, 2, 186, 187, 7, 103, 2, 2, 187, 188, 7, 112, 2, 2, 188, 189, 7, 102, 2, 2, 189, 190, 7, 113, 2, 2, 190, 191, 7, 121, 2, 2, 191, 192, 7, 112, 2, 2, 192, 193, 7, 65, 2, 2, 193, 52, 3, 2, 2, 2, 194, 195, 7, 62, 2, 2, 195, 54, 3, 2, 2, 2, 196, 197, 7, 64, 2, 2, 197, 56, 3, 2, 2, 2, 198, 199, 7, 63, 2, 2, 199, 200, 7, 63, 2, 2, 200, 58, 3, 2, 2, 2, 201, 202, 7, 35, 2, 2, 202, 203, 7, 63, 2, 2, 203, 60, 3, 2, 2, 2, 204, 205, 7, 62, 2, 2, 205, 206, 7, 63, 2, 2, 206, 62, 3, 2, 2, 2, 207, 208, 7, 64, 2, 2, 208, 209, 7, 63, 2, 2, 209, 64, 3, 2, 2, 2, 210, 211, 7, 40, 2, 2, 211, 212, 7, 40, 2, 2, 212, 66, 3, 2, 2, 2, 213, 214, 7, 126, 2, 2, 214, 215, 7, 126, 2, 2, 215, 68, 3, 2, 2, 2, 216, 217, 7, 35, 2, 2, 217, 70, 3, 2, 2, 2, 218, 220, 9, 2, 2, 2, 219, 218, 3, 2, 2, 2, 220, 221, 3, 2, 2, 2, 221, 219, 3, 2, 2, 2, 221, 222, 3, 2, 2, 2, 222, 72, 3, 2, 2, 2, 223, 224, 7, 60, 2, 2, 224, 228, 9, 3, 2, 2, 225, 227, 9, 4, 2, 2, 226, 225, 3, 2, 2, 2, 227, 230, 3, 2, 2, 2, 228, 226, 3, 2, 2, 2, 228, 229, 3, 2, 2, 2, 229, 74, 3, 2, 2, 2, 230, 228, 3, 2, 2, 2, 231, 233, 9, 5, 2, 2, 232, 231, 3, 2, 2, 2, 233, 234, 3, 2, 2, 2, 234, 232, 3, 2, 2, 2, 234, 235, 3, 2, 2, 2, 235, 76, 3, 2, 2, 2, 236, 238, 9, 6, 2, 2, 237, 236, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 237, 3, 2, 2, 2, 239, 240, 3, 2, 2, 2, 240, 241, 3, 2, 2, 2, 241, 242, 8, 39, 2, 2, 242, 78, 3, 2, 2, 2, 243, 244, 7, 49, 2, 2, 244, 245, 7, 49, 2, 2, 245, 249, 3, 2, 2, 2, 246, 248, 10, 7, 2, 2, 247, 246, 3, 2, 2, 2, 248, 251, 3, 2, 2, 2, 249, 247, 3, 2, 2, 2, 249, 250, 3, 2, 2, 2, 250, 252, 3, 2, 2, 2, 251, 249, 3, 2, 2, 2, 252, 253, 8, 40, 2, 2, 253, 80, 3, 2, 2, 2, 8, 2, 221, 228, 234, 239, 249, 3, 8, 2, 2] \ No newline at end of file diff --git a/ChironCore/turtparse/tlangLexer.py b/ChironCore/turtparse/tlangLexer.py index ecb24d7..26f3011 100644 --- a/ChironCore/turtparse/tlangLexer.py +++ b/ChironCore/turtparse/tlangLexer.py @@ -8,102 +8,106 @@ def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2(") - buf.write("\u00f5\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2)") + buf.write("\u00fe\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") buf.write("\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r") buf.write("\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23") buf.write("\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30") buf.write("\4\31\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36") buf.write("\t\36\4\37\t\37\4 \t \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%") - buf.write("\4&\t&\4\'\t\'\3\2\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\5") - buf.write("\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3") - buf.write("\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\f\3\f\3") - buf.write("\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16") - buf.write("\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\20") - buf.write("\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21") - buf.write("\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23") - buf.write("\3\23\3\23\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26\3\27") - buf.write("\3\27\3\30\3\30\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31") - buf.write("\3\31\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35") - buf.write("\3\36\3\36\3\36\3\37\3\37\3\37\3 \3 \3 \3!\3!\3!\3\"\3") - buf.write("\"\3#\6#\u00d3\n#\r#\16#\u00d4\3$\3$\3$\7$\u00da\n$\f") - buf.write("$\16$\u00dd\13$\3%\6%\u00e0\n%\r%\16%\u00e1\3&\6&\u00e5") - buf.write("\n&\r&\16&\u00e6\3&\3&\3\'\3\'\3\'\3\'\7\'\u00ef\n\'\f") - buf.write("\'\16\'\u00f2\13\'\3\'\3\'\2\2(\3\3\5\4\7\5\t\6\13\7\r") - buf.write("\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!") - buf.write("\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67") - buf.write("\359\36;\37= ?!A\"C#E$G%I&K\'M(\3\2\b\3\2\62;\5\2C\\a") - buf.write("ac|\5\2\62;C\\c|\4\2C\\c|\5\2\13\f\17\17\"\"\4\2\f\f\17") - buf.write("\17\2\u00f9\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3") - buf.write("\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2") - buf.write("\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2") - buf.write("\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2") - buf.write("#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2") - buf.write("\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65") - buf.write("\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2") - buf.write("\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2") - buf.write("\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\3O\3\2\2\2\5R\3\2") - buf.write("\2\2\7T\3\2\2\2\tV\3\2\2\2\13[\3\2\2\2\rb\3\2\2\2\17g") - buf.write("\3\2\2\2\21i\3\2\2\2\23k\3\2\2\2\25m\3\2\2\2\27o\3\2\2") - buf.write("\2\31w\3\2\2\2\33\u0080\3\2\2\2\35\u0085\3\2\2\2\37\u008b") - buf.write("\3\2\2\2!\u0091\3\2\2\2#\u0099\3\2\2\2%\u009f\3\2\2\2") - buf.write("\'\u00a6\3\2\2\2)\u00a8\3\2\2\2+\u00aa\3\2\2\2-\u00ac") - buf.write("\3\2\2\2/\u00ae\3\2\2\2\61\u00b0\3\2\2\2\63\u00b9\3\2") - buf.write("\2\2\65\u00bb\3\2\2\2\67\u00bd\3\2\2\29\u00c0\3\2\2\2") - buf.write(";\u00c3\3\2\2\2=\u00c6\3\2\2\2?\u00c9\3\2\2\2A\u00cc\3") - buf.write("\2\2\2C\u00cf\3\2\2\2E\u00d2\3\2\2\2G\u00d6\3\2\2\2I\u00df") - buf.write("\3\2\2\2K\u00e4\3\2\2\2M\u00ea\3\2\2\2OP\7k\2\2PQ\7h\2") - buf.write("\2Q\4\3\2\2\2RS\7]\2\2S\6\3\2\2\2TU\7_\2\2U\b\3\2\2\2") - buf.write("VW\7g\2\2WX\7n\2\2XY\7u\2\2YZ\7g\2\2Z\n\3\2\2\2[\\\7t") - buf.write("\2\2\\]\7g\2\2]^\7r\2\2^_\7g\2\2_`\7c\2\2`a\7v\2\2a\f") - buf.write("\3\2\2\2bc\7i\2\2cd\7q\2\2de\7v\2\2ef\7q\2\2f\16\3\2\2") - buf.write("\2gh\7*\2\2h\20\3\2\2\2ij\7.\2\2j\22\3\2\2\2kl\7+\2\2") - buf.write("l\24\3\2\2\2mn\7?\2\2n\26\3\2\2\2op\7h\2\2pq\7q\2\2qr") - buf.write("\7t\2\2rs\7y\2\2st\7c\2\2tu\7t\2\2uv\7f\2\2v\30\3\2\2") - buf.write("\2wx\7d\2\2xy\7c\2\2yz\7e\2\2z{\7m\2\2{|\7y\2\2|}\7c\2") - buf.write("\2}~\7t\2\2~\177\7f\2\2\177\32\3\2\2\2\u0080\u0081\7n") - buf.write("\2\2\u0081\u0082\7g\2\2\u0082\u0083\7h\2\2\u0083\u0084") - buf.write("\7v\2\2\u0084\34\3\2\2\2\u0085\u0086\7t\2\2\u0086\u0087") - buf.write("\7k\2\2\u0087\u0088\7i\2\2\u0088\u0089\7j\2\2\u0089\u008a") - buf.write("\7v\2\2\u008a\36\3\2\2\2\u008b\u008c\7r\2\2\u008c\u008d") - buf.write("\7g\2\2\u008d\u008e\7p\2\2\u008e\u008f\7w\2\2\u008f\u0090") - buf.write("\7r\2\2\u0090 \3\2\2\2\u0091\u0092\7r\2\2\u0092\u0093") - buf.write("\7g\2\2\u0093\u0094\7p\2\2\u0094\u0095\7f\2\2\u0095\u0096") - buf.write("\7q\2\2\u0096\u0097\7y\2\2\u0097\u0098\7p\2\2\u0098\"") - buf.write("\3\2\2\2\u0099\u009a\7r\2\2\u009a\u009b\7c\2\2\u009b\u009c") - buf.write("\7w\2\2\u009c\u009d\7u\2\2\u009d\u009e\7g\2\2\u009e$\3") - buf.write("\2\2\2\u009f\u00a0\7c\2\2\u00a0\u00a1\7u\2\2\u00a1\u00a2") - buf.write("\7u\2\2\u00a2\u00a3\7g\2\2\u00a3\u00a4\7t\2\2\u00a4\u00a5") - buf.write("\7v\2\2\u00a5&\3\2\2\2\u00a6\u00a7\7-\2\2\u00a7(\3\2\2") - buf.write("\2\u00a8\u00a9\7/\2\2\u00a9*\3\2\2\2\u00aa\u00ab\7,\2") - buf.write("\2\u00ab,\3\2\2\2\u00ac\u00ad\7\61\2\2\u00ad.\3\2\2\2") - buf.write("\u00ae\u00af\7\'\2\2\u00af\60\3\2\2\2\u00b0\u00b1\7r\2") - buf.write("\2\u00b1\u00b2\7g\2\2\u00b2\u00b3\7p\2\2\u00b3\u00b4\7") - buf.write("f\2\2\u00b4\u00b5\7q\2\2\u00b5\u00b6\7y\2\2\u00b6\u00b7") - buf.write("\7p\2\2\u00b7\u00b8\7A\2\2\u00b8\62\3\2\2\2\u00b9\u00ba") - buf.write("\7>\2\2\u00ba\64\3\2\2\2\u00bb\u00bc\7@\2\2\u00bc\66\3") - buf.write("\2\2\2\u00bd\u00be\7?\2\2\u00be\u00bf\7?\2\2\u00bf8\3") - buf.write("\2\2\2\u00c0\u00c1\7#\2\2\u00c1\u00c2\7?\2\2\u00c2:\3") - buf.write("\2\2\2\u00c3\u00c4\7>\2\2\u00c4\u00c5\7?\2\2\u00c5<\3") - buf.write("\2\2\2\u00c6\u00c7\7@\2\2\u00c7\u00c8\7?\2\2\u00c8>\3") - buf.write("\2\2\2\u00c9\u00ca\7(\2\2\u00ca\u00cb\7(\2\2\u00cb@\3") - buf.write("\2\2\2\u00cc\u00cd\7~\2\2\u00cd\u00ce\7~\2\2\u00ceB\3") - buf.write("\2\2\2\u00cf\u00d0\7#\2\2\u00d0D\3\2\2\2\u00d1\u00d3\t") - buf.write("\2\2\2\u00d2\u00d1\3\2\2\2\u00d3\u00d4\3\2\2\2\u00d4\u00d2") - buf.write("\3\2\2\2\u00d4\u00d5\3\2\2\2\u00d5F\3\2\2\2\u00d6\u00d7") - buf.write("\7<\2\2\u00d7\u00db\t\3\2\2\u00d8\u00da\t\4\2\2\u00d9") - buf.write("\u00d8\3\2\2\2\u00da\u00dd\3\2\2\2\u00db\u00d9\3\2\2\2") - buf.write("\u00db\u00dc\3\2\2\2\u00dcH\3\2\2\2\u00dd\u00db\3\2\2") - buf.write("\2\u00de\u00e0\t\5\2\2\u00df\u00de\3\2\2\2\u00e0\u00e1") - buf.write("\3\2\2\2\u00e1\u00df\3\2\2\2\u00e1\u00e2\3\2\2\2\u00e2") - buf.write("J\3\2\2\2\u00e3\u00e5\t\6\2\2\u00e4\u00e3\3\2\2\2\u00e5") - buf.write("\u00e6\3\2\2\2\u00e6\u00e4\3\2\2\2\u00e6\u00e7\3\2\2\2") - buf.write("\u00e7\u00e8\3\2\2\2\u00e8\u00e9\b&\2\2\u00e9L\3\2\2\2") - buf.write("\u00ea\u00eb\7\61\2\2\u00eb\u00ec\7\61\2\2\u00ec\u00f0") - buf.write("\3\2\2\2\u00ed\u00ef\n\7\2\2\u00ee\u00ed\3\2\2\2\u00ef") - buf.write("\u00f2\3\2\2\2\u00f0\u00ee\3\2\2\2\u00f0\u00f1\3\2\2\2") - buf.write("\u00f1\u00f3\3\2\2\2\u00f2\u00f0\3\2\2\2\u00f3\u00f4\b") - buf.write("\'\2\2\u00f4N\3\2\2\2\b\2\u00d4\u00db\u00e1\u00e6\u00f0") + buf.write("\4&\t&\4\'\t\'\4(\t(\3\2\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3") + buf.write("\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7") + buf.write("\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\f") + buf.write("\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3") + buf.write("\r\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3") + buf.write("\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21") + buf.write("\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\23") + buf.write("\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24") + buf.write("\3\24\3\24\3\25\3\25\3\26\3\26\3\27\3\27\3\30\3\30\3\31") + buf.write("\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\33") + buf.write("\3\33\3\34\3\34\3\35\3\35\3\35\3\36\3\36\3\36\3\37\3\37") + buf.write("\3\37\3 \3 \3 \3!\3!\3!\3\"\3\"\3\"\3#\3#\3$\6$\u00dc") + buf.write("\n$\r$\16$\u00dd\3%\3%\3%\7%\u00e3\n%\f%\16%\u00e6\13") + buf.write("%\3&\6&\u00e9\n&\r&\16&\u00ea\3\'\6\'\u00ee\n\'\r\'\16") + buf.write("\'\u00ef\3\'\3\'\3(\3(\3(\3(\7(\u00f8\n(\f(\16(\u00fb") + buf.write("\13(\3(\3(\2\2)\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23") + buf.write("\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25") + buf.write(")\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A") + buf.write("\"C#E$G%I&K\'M(O)\3\2\b\3\2\62;\5\2C\\aac|\5\2\62;C\\") + buf.write("c|\4\2C\\c|\5\2\13\f\17\17\"\"\4\2\f\f\17\17\2\u0102\2") + buf.write("\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3") + buf.write("\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2") + buf.write("\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2") + buf.write("\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%") + buf.write("\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2") + buf.write("\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67") + buf.write("\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2") + buf.write("A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2") + buf.write("\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\3Q\3\2\2\2\5T\3\2\2") + buf.write("\2\7V\3\2\2\2\tX\3\2\2\2\13]\3\2\2\2\rd\3\2\2\2\17i\3") + buf.write("\2\2\2\21k\3\2\2\2\23m\3\2\2\2\25o\3\2\2\2\27q\3\2\2\2") + buf.write("\31y\3\2\2\2\33\u0082\3\2\2\2\35\u0087\3\2\2\2\37\u008d") + buf.write("\3\2\2\2!\u0093\3\2\2\2#\u009b\3\2\2\2%\u00a1\3\2\2\2") + buf.write("\'\u00a8\3\2\2\2)\u00af\3\2\2\2+\u00b1\3\2\2\2-\u00b3") + buf.write("\3\2\2\2/\u00b5\3\2\2\2\61\u00b7\3\2\2\2\63\u00b9\3\2") + buf.write("\2\2\65\u00c2\3\2\2\2\67\u00c4\3\2\2\29\u00c6\3\2\2\2") + buf.write(";\u00c9\3\2\2\2=\u00cc\3\2\2\2?\u00cf\3\2\2\2A\u00d2\3") + buf.write("\2\2\2C\u00d5\3\2\2\2E\u00d8\3\2\2\2G\u00db\3\2\2\2I\u00df") + buf.write("\3\2\2\2K\u00e8\3\2\2\2M\u00ed\3\2\2\2O\u00f3\3\2\2\2") + buf.write("QR\7k\2\2RS\7h\2\2S\4\3\2\2\2TU\7]\2\2U\6\3\2\2\2VW\7") + buf.write("_\2\2W\b\3\2\2\2XY\7g\2\2YZ\7n\2\2Z[\7u\2\2[\\\7g\2\2") + buf.write("\\\n\3\2\2\2]^\7t\2\2^_\7g\2\2_`\7r\2\2`a\7g\2\2ab\7c") + buf.write("\2\2bc\7v\2\2c\f\3\2\2\2de\7i\2\2ef\7q\2\2fg\7v\2\2gh") + buf.write("\7q\2\2h\16\3\2\2\2ij\7*\2\2j\20\3\2\2\2kl\7.\2\2l\22") + buf.write("\3\2\2\2mn\7+\2\2n\24\3\2\2\2op\7?\2\2p\26\3\2\2\2qr\7") + buf.write("h\2\2rs\7q\2\2st\7t\2\2tu\7y\2\2uv\7c\2\2vw\7t\2\2wx\7") + buf.write("f\2\2x\30\3\2\2\2yz\7d\2\2z{\7c\2\2{|\7e\2\2|}\7m\2\2") + buf.write("}~\7y\2\2~\177\7c\2\2\177\u0080\7t\2\2\u0080\u0081\7f") + buf.write("\2\2\u0081\32\3\2\2\2\u0082\u0083\7n\2\2\u0083\u0084\7") + buf.write("g\2\2\u0084\u0085\7h\2\2\u0085\u0086\7v\2\2\u0086\34\3") + buf.write("\2\2\2\u0087\u0088\7t\2\2\u0088\u0089\7k\2\2\u0089\u008a") + buf.write("\7i\2\2\u008a\u008b\7j\2\2\u008b\u008c\7v\2\2\u008c\36") + buf.write("\3\2\2\2\u008d\u008e\7r\2\2\u008e\u008f\7g\2\2\u008f\u0090") + buf.write("\7p\2\2\u0090\u0091\7w\2\2\u0091\u0092\7r\2\2\u0092 \3") + buf.write("\2\2\2\u0093\u0094\7r\2\2\u0094\u0095\7g\2\2\u0095\u0096") + buf.write("\7p\2\2\u0096\u0097\7f\2\2\u0097\u0098\7q\2\2\u0098\u0099") + buf.write("\7y\2\2\u0099\u009a\7p\2\2\u009a\"\3\2\2\2\u009b\u009c") + buf.write("\7r\2\2\u009c\u009d\7c\2\2\u009d\u009e\7w\2\2\u009e\u009f") + buf.write("\7u\2\2\u009f\u00a0\7g\2\2\u00a0$\3\2\2\2\u00a1\u00a2") + buf.write("\7c\2\2\u00a2\u00a3\7u\2\2\u00a3\u00a4\7u\2\2\u00a4\u00a5") + buf.write("\7g\2\2\u00a5\u00a6\7t\2\2\u00a6\u00a7\7v\2\2\u00a7&\3") + buf.write("\2\2\2\u00a8\u00a9\7c\2\2\u00a9\u00aa\7u\2\2\u00aa\u00ab") + buf.write("\7u\2\2\u00ab\u00ac\7w\2\2\u00ac\u00ad\7o\2\2\u00ad\u00ae") + buf.write("\7g\2\2\u00ae(\3\2\2\2\u00af\u00b0\7-\2\2\u00b0*\3\2\2") + buf.write("\2\u00b1\u00b2\7/\2\2\u00b2,\3\2\2\2\u00b3\u00b4\7,\2") + buf.write("\2\u00b4.\3\2\2\2\u00b5\u00b6\7\61\2\2\u00b6\60\3\2\2") + buf.write("\2\u00b7\u00b8\7\'\2\2\u00b8\62\3\2\2\2\u00b9\u00ba\7") + buf.write("r\2\2\u00ba\u00bb\7g\2\2\u00bb\u00bc\7p\2\2\u00bc\u00bd") + buf.write("\7f\2\2\u00bd\u00be\7q\2\2\u00be\u00bf\7y\2\2\u00bf\u00c0") + buf.write("\7p\2\2\u00c0\u00c1\7A\2\2\u00c1\64\3\2\2\2\u00c2\u00c3") + buf.write("\7>\2\2\u00c3\66\3\2\2\2\u00c4\u00c5\7@\2\2\u00c58\3\2") + buf.write("\2\2\u00c6\u00c7\7?\2\2\u00c7\u00c8\7?\2\2\u00c8:\3\2") + buf.write("\2\2\u00c9\u00ca\7#\2\2\u00ca\u00cb\7?\2\2\u00cb<\3\2") + buf.write("\2\2\u00cc\u00cd\7>\2\2\u00cd\u00ce\7?\2\2\u00ce>\3\2") + buf.write("\2\2\u00cf\u00d0\7@\2\2\u00d0\u00d1\7?\2\2\u00d1@\3\2") + buf.write("\2\2\u00d2\u00d3\7(\2\2\u00d3\u00d4\7(\2\2\u00d4B\3\2") + buf.write("\2\2\u00d5\u00d6\7~\2\2\u00d6\u00d7\7~\2\2\u00d7D\3\2") + buf.write("\2\2\u00d8\u00d9\7#\2\2\u00d9F\3\2\2\2\u00da\u00dc\t\2") + buf.write("\2\2\u00db\u00da\3\2\2\2\u00dc\u00dd\3\2\2\2\u00dd\u00db") + buf.write("\3\2\2\2\u00dd\u00de\3\2\2\2\u00deH\3\2\2\2\u00df\u00e0") + buf.write("\7<\2\2\u00e0\u00e4\t\3\2\2\u00e1\u00e3\t\4\2\2\u00e2") + buf.write("\u00e1\3\2\2\2\u00e3\u00e6\3\2\2\2\u00e4\u00e2\3\2\2\2") + buf.write("\u00e4\u00e5\3\2\2\2\u00e5J\3\2\2\2\u00e6\u00e4\3\2\2") + buf.write("\2\u00e7\u00e9\t\5\2\2\u00e8\u00e7\3\2\2\2\u00e9\u00ea") + buf.write("\3\2\2\2\u00ea\u00e8\3\2\2\2\u00ea\u00eb\3\2\2\2\u00eb") + buf.write("L\3\2\2\2\u00ec\u00ee\t\6\2\2\u00ed\u00ec\3\2\2\2\u00ee") + buf.write("\u00ef\3\2\2\2\u00ef\u00ed\3\2\2\2\u00ef\u00f0\3\2\2\2") + buf.write("\u00f0\u00f1\3\2\2\2\u00f1\u00f2\b\'\2\2\u00f2N\3\2\2") + buf.write("\2\u00f3\u00f4\7\61\2\2\u00f4\u00f5\7\61\2\2\u00f5\u00f9") + buf.write("\3\2\2\2\u00f6\u00f8\n\7\2\2\u00f7\u00f6\3\2\2\2\u00f8") + buf.write("\u00fb\3\2\2\2\u00f9\u00f7\3\2\2\2\u00f9\u00fa\3\2\2\2") + buf.write("\u00fa\u00fc\3\2\2\2\u00fb\u00f9\3\2\2\2\u00fc\u00fd\b") + buf.write("(\2\2\u00fdP\3\2\2\2\b\2\u00dd\u00e4\u00ea\u00ef\u00f9") buf.write("\3\b\2\2") return buf.getvalue() @@ -132,26 +136,27 @@ class tlangLexer(Lexer): T__15 = 16 T__16 = 17 T__17 = 18 - PLUS = 19 - MINUS = 20 - MUL = 21 - DIV = 22 - MOD = 23 - PENCOND = 24 - LT = 25 - GT = 26 - EQ = 27 - NEQ = 28 - LTE = 29 - GTE = 30 - AND = 31 - OR = 32 - NOT = 33 - NUM = 34 - VAR = 35 - NAME = 36 - Whitespace = 37 - Comment = 38 + T__18 = 19 + PLUS = 20 + MINUS = 21 + MUL = 22 + DIV = 23 + MOD = 24 + PENCOND = 25 + LT = 26 + GT = 27 + EQ = 28 + NEQ = 29 + LTE = 30 + GTE = 31 + AND = 32 + OR = 33 + NOT = 34 + NUM = 35 + VAR = 36 + NAME = 37 + Whitespace = 38 + Comment = 39 channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] @@ -160,9 +165,9 @@ class tlangLexer(Lexer): literalNames = [ "", "'if'", "'['", "']'", "'else'", "'repeat'", "'goto'", "'('", "','", "')'", "'='", "'forward'", "'backward'", "'left'", "'right'", - "'penup'", "'pendown'", "'pause'", "'assert'", "'+'", "'-'", - "'*'", "'/'", "'%'", "'pendown?'", "'<'", "'>'", "'=='", "'!='", - "'<='", "'>='", "'&&'", "'||'", "'!'" ] + "'penup'", "'pendown'", "'pause'", "'assert'", "'assume'", "'+'", + "'-'", "'*'", "'/'", "'%'", "'pendown?'", "'<'", "'>'", "'=='", + "'!='", "'<='", "'>='", "'&&'", "'||'", "'!'" ] symbolicNames = [ "", "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", @@ -171,10 +176,10 @@ class tlangLexer(Lexer): ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", - "T__14", "T__15", "T__16", "T__17", "PLUS", "MINUS", "MUL", - "DIV", "MOD", "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", - "GTE", "AND", "OR", "NOT", "NUM", "VAR", "NAME", "Whitespace", - "Comment" ] + "T__14", "T__15", "T__16", "T__17", "T__18", "PLUS", "MINUS", + "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", "EQ", "NEQ", + "LTE", "GTE", "AND", "OR", "NOT", "NUM", "VAR", "NAME", + "Whitespace", "Comment" ] grammarFileName = "tlang.g4" diff --git a/ChironCore/turtparse/tlangLexer.tokens b/ChironCore/turtparse/tlangLexer.tokens index 2c2f507..ee84fda 100644 --- a/ChironCore/turtparse/tlangLexer.tokens +++ b/ChironCore/turtparse/tlangLexer.tokens @@ -16,26 +16,27 @@ T__14=15 T__15=16 T__16=17 T__17=18 -PLUS=19 -MINUS=20 -MUL=21 -DIV=22 -MOD=23 -PENCOND=24 -LT=25 -GT=26 -EQ=27 -NEQ=28 -LTE=29 -GTE=30 -AND=31 -OR=32 -NOT=33 -NUM=34 -VAR=35 -NAME=36 -Whitespace=37 -Comment=38 +T__18=19 +PLUS=20 +MINUS=21 +MUL=22 +DIV=23 +MOD=24 +PENCOND=25 +LT=26 +GT=27 +EQ=28 +NEQ=29 +LTE=30 +GTE=31 +AND=32 +OR=33 +NOT=34 +NUM=35 +VAR=36 +NAME=37 +Whitespace=38 +Comment=39 'if'=1 '['=2 ']'=3 @@ -54,18 +55,19 @@ Comment=38 'pendown'=16 'pause'=17 'assert'=18 -'+'=19 -'-'=20 -'*'=21 -'/'=22 -'%'=23 -'pendown?'=24 -'<'=25 -'>'=26 -'=='=27 -'!='=28 -'<='=29 -'>='=30 -'&&'=31 -'||'=32 -'!'=33 +'assume'=19 +'+'=20 +'-'=21 +'*'=22 +'/'=23 +'%'=24 +'pendown?'=25 +'<'=26 +'>'=27 +'=='=28 +'!='=29 +'<='=30 +'>='=31 +'&&'=32 +'||'=33 +'!'=34 diff --git a/ChironCore/turtparse/tlangParser.py b/ChironCore/turtparse/tlangParser.py index e36b76e..9f6ac23 100644 --- a/ChironCore/turtparse/tlangParser.py +++ b/ChironCore/turtparse/tlangParser.py @@ -8,76 +8,79 @@ def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3(") - buf.write("\u00bd\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3)") + buf.write("\u00c3\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16") buf.write("\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23\t\23") buf.write("\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31") - buf.write("\t\31\3\2\3\2\3\2\3\3\7\3\67\n\3\f\3\16\3:\13\3\3\4\6") - buf.write("\4=\n\4\r\4\16\4>\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5") - buf.write("I\n\5\3\6\3\6\5\6M\n\6\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b") - buf.write("\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3") - buf.write("\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\f") - buf.write("\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3") - buf.write("\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\5\21\u0085") - buf.write("\n\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21\3\21") - buf.write("\3\21\3\21\7\21\u0093\n\21\f\21\16\21\u0096\13\21\3\22") - buf.write("\3\22\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26\3\26\3\26") - buf.write("\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\5\26\u00ac\n") - buf.write("\26\3\26\3\26\3\26\3\26\7\26\u00b2\n\26\f\26\16\26\u00b5") - buf.write("\13\26\3\27\3\27\3\30\3\30\3\31\3\31\3\31\2\4 *\32\2\4") - buf.write("\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\2\t\3") - buf.write("\2\r\20\3\2\21\22\3\2\27\30\3\2\25\26\3\2\33 \3\2!\"\3") - buf.write("\2$%\2\u00b7\2\62\3\2\2\2\48\3\2\2\2\6<\3\2\2\2\bH\3\2") - buf.write("\2\2\nL\3\2\2\2\fN\3\2\2\2\16T\3\2\2\2\20^\3\2\2\2\22") - buf.write("d\3\2\2\2\24k\3\2\2\2\26o\3\2\2\2\30r\3\2\2\2\32t\3\2") - buf.write("\2\2\34v\3\2\2\2\36x\3\2\2\2 \u0084\3\2\2\2\"\u0097\3") - buf.write("\2\2\2$\u0099\3\2\2\2&\u009b\3\2\2\2(\u009d\3\2\2\2*\u00ab") - buf.write("\3\2\2\2,\u00b6\3\2\2\2.\u00b8\3\2\2\2\60\u00ba\3\2\2") - buf.write("\2\62\63\5\4\3\2\63\64\7\2\2\3\64\3\3\2\2\2\65\67\5\b") - buf.write("\5\2\66\65\3\2\2\2\67:\3\2\2\28\66\3\2\2\289\3\2\2\29") - buf.write("\5\3\2\2\2:8\3\2\2\2;=\5\b\5\2<;\3\2\2\2=>\3\2\2\2><\3") - buf.write("\2\2\2>?\3\2\2\2?\7\3\2\2\2@I\5\24\13\2AI\5\n\6\2BI\5") - buf.write("\20\t\2CI\5\26\f\2DI\5\32\16\2EI\5\22\n\2FI\5\34\17\2") - buf.write("GI\5\36\20\2H@\3\2\2\2HA\3\2\2\2HB\3\2\2\2HC\3\2\2\2H") - buf.write("D\3\2\2\2HE\3\2\2\2HF\3\2\2\2HG\3\2\2\2I\t\3\2\2\2JM\5") - buf.write("\f\7\2KM\5\16\b\2LJ\3\2\2\2LK\3\2\2\2M\13\3\2\2\2NO\7") - buf.write("\3\2\2OP\5*\26\2PQ\7\4\2\2QR\5\6\4\2RS\7\5\2\2S\r\3\2") - buf.write("\2\2TU\7\3\2\2UV\5*\26\2VW\7\4\2\2WX\5\6\4\2XY\7\5\2\2") - buf.write("YZ\7\6\2\2Z[\7\4\2\2[\\\5\6\4\2\\]\7\5\2\2]\17\3\2\2\2") - buf.write("^_\7\7\2\2_`\5\60\31\2`a\7\4\2\2ab\5\6\4\2bc\7\5\2\2c") - buf.write("\21\3\2\2\2de\7\b\2\2ef\7\t\2\2fg\5 \21\2gh\7\n\2\2hi") - buf.write("\5 \21\2ij\7\13\2\2j\23\3\2\2\2kl\7%\2\2lm\7\f\2\2mn\5") - buf.write(" \21\2n\25\3\2\2\2op\5\30\r\2pq\5 \21\2q\27\3\2\2\2rs") - buf.write("\t\2\2\2s\31\3\2\2\2tu\t\3\2\2u\33\3\2\2\2vw\7\23\2\2") - buf.write("w\35\3\2\2\2xy\7\24\2\2yz\5*\26\2z\37\3\2\2\2{|\b\21\1") - buf.write("\2|}\5(\25\2}~\5 \21\b~\u0085\3\2\2\2\177\u0085\5\60\31") - buf.write("\2\u0080\u0081\7\t\2\2\u0081\u0082\5 \21\2\u0082\u0083") - buf.write("\7\13\2\2\u0083\u0085\3\2\2\2\u0084{\3\2\2\2\u0084\177") - buf.write("\3\2\2\2\u0084\u0080\3\2\2\2\u0085\u0094\3\2\2\2\u0086") - buf.write("\u0087\f\7\2\2\u0087\u0088\5\"\22\2\u0088\u0089\5 \21") - buf.write("\b\u0089\u0093\3\2\2\2\u008a\u008b\f\6\2\2\u008b\u008c") - buf.write("\5$\23\2\u008c\u008d\5 \21\7\u008d\u0093\3\2\2\2\u008e") - buf.write("\u008f\f\5\2\2\u008f\u0090\5&\24\2\u0090\u0091\5 \21\6") - buf.write("\u0091\u0093\3\2\2\2\u0092\u0086\3\2\2\2\u0092\u008a\3") - buf.write("\2\2\2\u0092\u008e\3\2\2\2\u0093\u0096\3\2\2\2\u0094\u0092") - buf.write("\3\2\2\2\u0094\u0095\3\2\2\2\u0095!\3\2\2\2\u0096\u0094") - buf.write("\3\2\2\2\u0097\u0098\t\4\2\2\u0098#\3\2\2\2\u0099\u009a") - buf.write("\t\5\2\2\u009a%\3\2\2\2\u009b\u009c\7\31\2\2\u009c\'\3") - buf.write("\2\2\2\u009d\u009e\7\26\2\2\u009e)\3\2\2\2\u009f\u00a0") - buf.write("\b\26\1\2\u00a0\u00a1\7#\2\2\u00a1\u00ac\5*\26\7\u00a2") - buf.write("\u00a3\5 \21\2\u00a3\u00a4\5,\27\2\u00a4\u00a5\5 \21\2") - buf.write("\u00a5\u00ac\3\2\2\2\u00a6\u00ac\7\32\2\2\u00a7\u00a8") - buf.write("\7\t\2\2\u00a8\u00a9\5*\26\2\u00a9\u00aa\7\13\2\2\u00aa") - buf.write("\u00ac\3\2\2\2\u00ab\u009f\3\2\2\2\u00ab\u00a2\3\2\2\2") - buf.write("\u00ab\u00a6\3\2\2\2\u00ab\u00a7\3\2\2\2\u00ac\u00b3\3") - buf.write("\2\2\2\u00ad\u00ae\f\5\2\2\u00ae\u00af\5.\30\2\u00af\u00b0") - buf.write("\5*\26\6\u00b0\u00b2\3\2\2\2\u00b1\u00ad\3\2\2\2\u00b2") - buf.write("\u00b5\3\2\2\2\u00b3\u00b1\3\2\2\2\u00b3\u00b4\3\2\2\2") - buf.write("\u00b4+\3\2\2\2\u00b5\u00b3\3\2\2\2\u00b6\u00b7\t\6\2") - buf.write("\2\u00b7-\3\2\2\2\u00b8\u00b9\t\7\2\2\u00b9/\3\2\2\2\u00ba") - buf.write("\u00bb\t\b\2\2\u00bb\61\3\2\2\2\138>HL\u0084\u0092\u0094") - buf.write("\u00ab\u00b3") + buf.write("\t\31\4\32\t\32\3\2\3\2\3\2\3\3\7\39\n\3\f\3\16\3<\13") + buf.write("\3\3\4\6\4?\n\4\r\4\16\4@\3\5\3\5\3\5\3\5\3\5\3\5\3\5") + buf.write("\3\5\3\5\5\5L\n\5\3\6\3\6\5\6P\n\6\3\7\3\7\3\7\3\7\3\7") + buf.write("\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3") + buf.write("\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3") + buf.write("\13\3\13\3\f\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\3\20") + buf.write("\3\20\3\20\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22") + buf.write("\3\22\3\22\3\22\5\22\u008b\n\22\3\22\3\22\3\22\3\22\3") + buf.write("\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\7\22\u0099\n\22") + buf.write("\f\22\16\22\u009c\13\22\3\23\3\23\3\24\3\24\3\25\3\25") + buf.write("\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27") + buf.write("\3\27\3\27\3\27\5\27\u00b2\n\27\3\27\3\27\3\27\3\27\7") + buf.write("\27\u00b8\n\27\f\27\16\27\u00bb\13\27\3\30\3\30\3\31\3") + buf.write("\31\3\32\3\32\3\32\2\4\",\33\2\4\6\b\n\f\16\20\22\24\26") + buf.write("\30\32\34\36 \"$&(*,.\60\62\2\t\3\2\r\20\3\2\21\22\3\2") + buf.write("\30\31\3\2\26\27\3\2\34!\3\2\"#\3\2%&\2\u00bd\2\64\3\2") + buf.write("\2\2\4:\3\2\2\2\6>\3\2\2\2\bK\3\2\2\2\nO\3\2\2\2\fQ\3") + buf.write("\2\2\2\16W\3\2\2\2\20a\3\2\2\2\22g\3\2\2\2\24n\3\2\2\2") + buf.write("\26r\3\2\2\2\30u\3\2\2\2\32w\3\2\2\2\34y\3\2\2\2\36{\3") + buf.write("\2\2\2 ~\3\2\2\2\"\u008a\3\2\2\2$\u009d\3\2\2\2&\u009f") + buf.write("\3\2\2\2(\u00a1\3\2\2\2*\u00a3\3\2\2\2,\u00b1\3\2\2\2") + buf.write(".\u00bc\3\2\2\2\60\u00be\3\2\2\2\62\u00c0\3\2\2\2\64\65") + buf.write("\5\4\3\2\65\66\7\2\2\3\66\3\3\2\2\2\679\5\b\5\28\67\3") + buf.write("\2\2\29<\3\2\2\2:8\3\2\2\2:;\3\2\2\2;\5\3\2\2\2<:\3\2") + buf.write("\2\2=?\5\b\5\2>=\3\2\2\2?@\3\2\2\2@>\3\2\2\2@A\3\2\2\2") + buf.write("A\7\3\2\2\2BL\5\24\13\2CL\5\n\6\2DL\5\20\t\2EL\5\26\f") + buf.write("\2FL\5\32\16\2GL\5\22\n\2HL\5\34\17\2IL\5\36\20\2JL\5") + buf.write(" \21\2KB\3\2\2\2KC\3\2\2\2KD\3\2\2\2KE\3\2\2\2KF\3\2\2") + buf.write("\2KG\3\2\2\2KH\3\2\2\2KI\3\2\2\2KJ\3\2\2\2L\t\3\2\2\2") + buf.write("MP\5\f\7\2NP\5\16\b\2OM\3\2\2\2ON\3\2\2\2P\13\3\2\2\2") + buf.write("QR\7\3\2\2RS\5,\27\2ST\7\4\2\2TU\5\6\4\2UV\7\5\2\2V\r") + buf.write("\3\2\2\2WX\7\3\2\2XY\5,\27\2YZ\7\4\2\2Z[\5\6\4\2[\\\7") + buf.write("\5\2\2\\]\7\6\2\2]^\7\4\2\2^_\5\6\4\2_`\7\5\2\2`\17\3") + buf.write("\2\2\2ab\7\7\2\2bc\5\62\32\2cd\7\4\2\2de\5\6\4\2ef\7\5") + buf.write("\2\2f\21\3\2\2\2gh\7\b\2\2hi\7\t\2\2ij\5\"\22\2jk\7\n") + buf.write("\2\2kl\5\"\22\2lm\7\13\2\2m\23\3\2\2\2no\7&\2\2op\7\f") + buf.write("\2\2pq\5\"\22\2q\25\3\2\2\2rs\5\30\r\2st\5\"\22\2t\27") + buf.write("\3\2\2\2uv\t\2\2\2v\31\3\2\2\2wx\t\3\2\2x\33\3\2\2\2y") + buf.write("z\7\23\2\2z\35\3\2\2\2{|\7\24\2\2|}\5,\27\2}\37\3\2\2") + buf.write("\2~\177\7\25\2\2\177\u0080\5,\27\2\u0080!\3\2\2\2\u0081") + buf.write("\u0082\b\22\1\2\u0082\u0083\5*\26\2\u0083\u0084\5\"\22") + buf.write("\b\u0084\u008b\3\2\2\2\u0085\u008b\5\62\32\2\u0086\u0087") + buf.write("\7\t\2\2\u0087\u0088\5\"\22\2\u0088\u0089\7\13\2\2\u0089") + buf.write("\u008b\3\2\2\2\u008a\u0081\3\2\2\2\u008a\u0085\3\2\2\2") + buf.write("\u008a\u0086\3\2\2\2\u008b\u009a\3\2\2\2\u008c\u008d\f") + buf.write("\7\2\2\u008d\u008e\5$\23\2\u008e\u008f\5\"\22\b\u008f") + buf.write("\u0099\3\2\2\2\u0090\u0091\f\6\2\2\u0091\u0092\5&\24\2") + buf.write("\u0092\u0093\5\"\22\7\u0093\u0099\3\2\2\2\u0094\u0095") + buf.write("\f\5\2\2\u0095\u0096\5(\25\2\u0096\u0097\5\"\22\6\u0097") + buf.write("\u0099\3\2\2\2\u0098\u008c\3\2\2\2\u0098\u0090\3\2\2\2") + buf.write("\u0098\u0094\3\2\2\2\u0099\u009c\3\2\2\2\u009a\u0098\3") + buf.write("\2\2\2\u009a\u009b\3\2\2\2\u009b#\3\2\2\2\u009c\u009a") + buf.write("\3\2\2\2\u009d\u009e\t\4\2\2\u009e%\3\2\2\2\u009f\u00a0") + buf.write("\t\5\2\2\u00a0\'\3\2\2\2\u00a1\u00a2\7\32\2\2\u00a2)\3") + buf.write("\2\2\2\u00a3\u00a4\7\27\2\2\u00a4+\3\2\2\2\u00a5\u00a6") + buf.write("\b\27\1\2\u00a6\u00a7\7$\2\2\u00a7\u00b2\5,\27\7\u00a8") + buf.write("\u00a9\5\"\22\2\u00a9\u00aa\5.\30\2\u00aa\u00ab\5\"\22") + buf.write("\2\u00ab\u00b2\3\2\2\2\u00ac\u00b2\7\33\2\2\u00ad\u00ae") + buf.write("\7\t\2\2\u00ae\u00af\5,\27\2\u00af\u00b0\7\13\2\2\u00b0") + buf.write("\u00b2\3\2\2\2\u00b1\u00a5\3\2\2\2\u00b1\u00a8\3\2\2\2") + buf.write("\u00b1\u00ac\3\2\2\2\u00b1\u00ad\3\2\2\2\u00b2\u00b9\3") + buf.write("\2\2\2\u00b3\u00b4\f\5\2\2\u00b4\u00b5\5\60\31\2\u00b5") + buf.write("\u00b6\5,\27\6\u00b6\u00b8\3\2\2\2\u00b7\u00b3\3\2\2\2") + buf.write("\u00b8\u00bb\3\2\2\2\u00b9\u00b7\3\2\2\2\u00b9\u00ba\3") + buf.write("\2\2\2\u00ba-\3\2\2\2\u00bb\u00b9\3\2\2\2\u00bc\u00bd") + buf.write("\t\6\2\2\u00bd/\3\2\2\2\u00be\u00bf\t\7\2\2\u00bf\61\3") + buf.write("\2\2\2\u00c0\u00c1\t\b\2\2\u00c1\63\3\2\2\2\13:@KO\u008a") + buf.write("\u0098\u009a\u00b1\u00b9") return buf.getvalue() @@ -94,18 +97,18 @@ class tlangParser ( Parser ): literalNames = [ "", "'if'", "'['", "']'", "'else'", "'repeat'", "'goto'", "'('", "','", "')'", "'='", "'forward'", "'backward'", "'left'", "'right'", "'penup'", "'pendown'", - "'pause'", "'assert'", "'+'", "'-'", "'*'", "'/'", - "'%'", "'pendown?'", "'<'", "'>'", "'=='", "'!='", + "'pause'", "'assert'", "'assume'", "'+'", "'-'", "'*'", + "'/'", "'%'", "'pendown?'", "'<'", "'>'", "'=='", "'!='", "'<='", "'>='", "'&&'", "'||'", "'!'" ] symbolicNames = [ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", "", "", "PLUS", "MINUS", - "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", "EQ", - "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", "VAR", - "NAME", "Whitespace", "Comment" ] + "", "", "", "", + "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", + "GT", "EQ", "NEQ", "LTE", "GTE", "AND", "OR", "NOT", + "NUM", "VAR", "NAME", "Whitespace", "Comment" ] RULE_start = 0 RULE_instruction_list = 1 @@ -122,22 +125,24 @@ class tlangParser ( Parser ): RULE_penCommand = 12 RULE_pauseCommand = 13 RULE_assertionCommand = 14 - RULE_expression = 15 - RULE_multiplicative = 16 - RULE_additive = 17 - RULE_modulo = 18 - RULE_unaryArithOp = 19 - RULE_condition = 20 - RULE_binCondOp = 21 - RULE_logicOp = 22 - RULE_value = 23 + RULE_assumeCommand = 15 + RULE_expression = 16 + RULE_multiplicative = 17 + RULE_additive = 18 + RULE_modulo = 19 + RULE_unaryArithOp = 20 + RULE_condition = 21 + RULE_binCondOp = 22 + RULE_logicOp = 23 + RULE_value = 24 ruleNames = [ "start", "instruction_list", "strict_ilist", "instruction", "conditional", "ifConditional", "ifElseConditional", "loop", "gotoCommand", "assignment", "moveCommand", "moveOp", - "penCommand", "pauseCommand", "assertionCommand", "expression", - "multiplicative", "additive", "modulo", "unaryArithOp", - "condition", "binCondOp", "logicOp", "value" ] + "penCommand", "pauseCommand", "assertionCommand", "assumeCommand", + "expression", "multiplicative", "additive", "modulo", + "unaryArithOp", "condition", "binCondOp", "logicOp", + "value" ] EOF = Token.EOF T__0=1 @@ -158,26 +163,27 @@ class tlangParser ( Parser ): T__15=16 T__16=17 T__17=18 - PLUS=19 - MINUS=20 - MUL=21 - DIV=22 - MOD=23 - PENCOND=24 - LT=25 - GT=26 - EQ=27 - NEQ=28 - LTE=29 - GTE=30 - AND=31 - OR=32 - NOT=33 - NUM=34 - VAR=35 - NAME=36 - Whitespace=37 - Comment=38 + T__18=19 + PLUS=20 + MINUS=21 + MUL=22 + DIV=23 + MOD=24 + PENCOND=25 + LT=26 + GT=27 + EQ=28 + NEQ=29 + LTE=30 + GTE=31 + AND=32 + OR=33 + NOT=34 + NUM=35 + VAR=36 + NAME=37 + Whitespace=38 + Comment=39 def __init__(self, input:TokenStream, output:TextIO = sys.stdout): super().__init__(input, output) @@ -219,9 +225,9 @@ def start(self): self.enterRule(localctx, 0, self.RULE_start) try: self.enterOuterAlt(localctx, 1) - self.state = 48 + self.state = 50 self.instruction_list() - self.state = 49 + self.state = 51 self.match(tlangParser.EOF) except RecognitionException as re: localctx.exception = re @@ -264,13 +270,13 @@ def instruction_list(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 54 + self.state = 56 self._errHandler.sync(self) _la = self._input.LA(1) - while (((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.VAR))) != 0): - self.state = 51 + while (((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.T__18) | (1 << tlangParser.VAR))) != 0): + self.state = 53 self.instruction() - self.state = 56 + self.state = 58 self._errHandler.sync(self) _la = self._input.LA(1) @@ -315,16 +321,16 @@ def strict_ilist(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 58 + self.state = 60 self._errHandler.sync(self) _la = self._input.LA(1) while True: - self.state = 57 + self.state = 59 self.instruction() - self.state = 60 + self.state = 62 self._errHandler.sync(self) _la = self._input.LA(1) - if not ((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.VAR))) != 0)): + if not ((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.T__18) | (1 << tlangParser.VAR))) != 0)): break except RecognitionException as re: @@ -374,6 +380,10 @@ def assertionCommand(self): return self.getTypedRuleContext(tlangParser.AssertionCommandContext,0) + def assumeCommand(self): + return self.getTypedRuleContext(tlangParser.AssumeCommandContext,0) + + def getRuleIndex(self): return tlangParser.RULE_instruction @@ -391,49 +401,54 @@ def instruction(self): localctx = tlangParser.InstructionContext(self, self._ctx, self.state) self.enterRule(localctx, 6, self.RULE_instruction) try: - self.state = 70 + self.state = 73 self._errHandler.sync(self) token = self._input.LA(1) if token in [tlangParser.VAR]: self.enterOuterAlt(localctx, 1) - self.state = 62 + self.state = 64 self.assignment() pass elif token in [tlangParser.T__0]: self.enterOuterAlt(localctx, 2) - self.state = 63 + self.state = 65 self.conditional() pass elif token in [tlangParser.T__4]: self.enterOuterAlt(localctx, 3) - self.state = 64 + self.state = 66 self.loop() pass elif token in [tlangParser.T__10, tlangParser.T__11, tlangParser.T__12, tlangParser.T__13]: self.enterOuterAlt(localctx, 4) - self.state = 65 + self.state = 67 self.moveCommand() pass elif token in [tlangParser.T__14, tlangParser.T__15]: self.enterOuterAlt(localctx, 5) - self.state = 66 + self.state = 68 self.penCommand() pass elif token in [tlangParser.T__5]: self.enterOuterAlt(localctx, 6) - self.state = 67 + self.state = 69 self.gotoCommand() pass elif token in [tlangParser.T__16]: self.enterOuterAlt(localctx, 7) - self.state = 68 + self.state = 70 self.pauseCommand() pass elif token in [tlangParser.T__17]: self.enterOuterAlt(localctx, 8) - self.state = 69 + self.state = 71 self.assertionCommand() pass + elif token in [tlangParser.T__18]: + self.enterOuterAlt(localctx, 9) + self.state = 72 + self.assumeCommand() + pass else: raise NoViableAltException(self) @@ -477,18 +492,18 @@ def conditional(self): localctx = tlangParser.ConditionalContext(self, self._ctx, self.state) self.enterRule(localctx, 8, self.RULE_conditional) try: - self.state = 74 + self.state = 77 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,3,self._ctx) if la_ == 1: self.enterOuterAlt(localctx, 1) - self.state = 72 + self.state = 75 self.ifConditional() pass elif la_ == 2: self.enterOuterAlt(localctx, 2) - self.state = 73 + self.state = 76 self.ifElseConditional() pass @@ -534,15 +549,15 @@ def ifConditional(self): self.enterRule(localctx, 10, self.RULE_ifConditional) try: self.enterOuterAlt(localctx, 1) - self.state = 76 + self.state = 79 self.match(tlangParser.T__0) - self.state = 77 + self.state = 80 self.condition(0) - self.state = 78 + self.state = 81 self.match(tlangParser.T__1) - self.state = 79 + self.state = 82 self.strict_ilist() - self.state = 80 + self.state = 83 self.match(tlangParser.T__2) except RecognitionException as re: localctx.exception = re @@ -588,23 +603,23 @@ def ifElseConditional(self): self.enterRule(localctx, 12, self.RULE_ifElseConditional) try: self.enterOuterAlt(localctx, 1) - self.state = 82 + self.state = 85 self.match(tlangParser.T__0) - self.state = 83 + self.state = 86 self.condition(0) - self.state = 84 + self.state = 87 self.match(tlangParser.T__1) - self.state = 85 + self.state = 88 self.strict_ilist() - self.state = 86 + self.state = 89 self.match(tlangParser.T__2) - self.state = 87 + self.state = 90 self.match(tlangParser.T__3) - self.state = 88 + self.state = 91 self.match(tlangParser.T__1) - self.state = 89 + self.state = 92 self.strict_ilist() - self.state = 90 + self.state = 93 self.match(tlangParser.T__2) except RecognitionException as re: localctx.exception = re @@ -647,15 +662,15 @@ def loop(self): self.enterRule(localctx, 14, self.RULE_loop) try: self.enterOuterAlt(localctx, 1) - self.state = 92 + self.state = 95 self.match(tlangParser.T__4) - self.state = 93 + self.state = 96 self.value() - self.state = 94 + self.state = 97 self.match(tlangParser.T__1) - self.state = 95 + self.state = 98 self.strict_ilist() - self.state = 96 + self.state = 99 self.match(tlangParser.T__2) except RecognitionException as re: localctx.exception = re @@ -697,17 +712,17 @@ def gotoCommand(self): self.enterRule(localctx, 16, self.RULE_gotoCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 98 + self.state = 101 self.match(tlangParser.T__5) - self.state = 99 + self.state = 102 self.match(tlangParser.T__6) - self.state = 100 + self.state = 103 self.expression(0) - self.state = 101 + self.state = 104 self.match(tlangParser.T__7) - self.state = 102 + self.state = 105 self.expression(0) - self.state = 103 + self.state = 106 self.match(tlangParser.T__8) except RecognitionException as re: localctx.exception = re @@ -749,11 +764,11 @@ def assignment(self): self.enterRule(localctx, 18, self.RULE_assignment) try: self.enterOuterAlt(localctx, 1) - self.state = 105 + self.state = 108 self.match(tlangParser.VAR) - self.state = 106 + self.state = 109 self.match(tlangParser.T__9) - self.state = 107 + self.state = 110 self.expression(0) except RecognitionException as re: localctx.exception = re @@ -796,9 +811,9 @@ def moveCommand(self): self.enterRule(localctx, 20, self.RULE_moveCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 109 + self.state = 112 self.moveOp() - self.state = 110 + self.state = 113 self.expression(0) except RecognitionException as re: localctx.exception = re @@ -835,7 +850,7 @@ def moveOp(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 112 + self.state = 115 _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13))) != 0)): self._errHandler.recoverInline(self) @@ -877,7 +892,7 @@ def penCommand(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 114 + self.state = 117 _la = self._input.LA(1) if not(_la==tlangParser.T__14 or _la==tlangParser.T__15): self._errHandler.recoverInline(self) @@ -918,7 +933,7 @@ def pauseCommand(self): self.enterRule(localctx, 26, self.RULE_pauseCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 116 + self.state = 119 self.match(tlangParser.T__16) except RecognitionException as re: localctx.exception = re @@ -957,9 +972,50 @@ def assertionCommand(self): self.enterRule(localctx, 28, self.RULE_assertionCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 118 + self.state = 121 self.match(tlangParser.T__17) - self.state = 119 + self.state = 122 + self.condition(0) + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + + class AssumeCommandContext(ParserRuleContext): + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + def condition(self): + return self.getTypedRuleContext(tlangParser.ConditionContext,0) + + + def getRuleIndex(self): + return tlangParser.RULE_assumeCommand + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitAssumeCommand" ): + return visitor.visitAssumeCommand(self) + else: + return visitor.visitChildren(self) + + + + + def assumeCommand(self): + + localctx = tlangParser.AssumeCommandContext(self, self._ctx, self.state) + self.enterRule(localctx, 30, self.RULE_assumeCommand) + try: + self.enterOuterAlt(localctx, 1) + self.state = 124 + self.match(tlangParser.T__18) + self.state = 125 self.condition(0) except RecognitionException as re: localctx.exception = re @@ -1114,11 +1170,11 @@ def expression(self, _p:int=0): _parentState = self.state localctx = tlangParser.ExpressionContext(self, self._ctx, _parentState) _prevctx = localctx - _startState = 30 - self.enterRecursionRule(localctx, 30, self.RULE_expression, _p) + _startState = 32 + self.enterRecursionRule(localctx, 32, self.RULE_expression, _p) try: self.enterOuterAlt(localctx, 1) - self.state = 130 + self.state = 136 self._errHandler.sync(self) token = self._input.LA(1) if token in [tlangParser.MINUS]: @@ -1126,34 +1182,34 @@ def expression(self, _p:int=0): self._ctx = localctx _prevctx = localctx - self.state = 122 + self.state = 128 self.unaryArithOp() - self.state = 123 + self.state = 129 self.expression(6) pass elif token in [tlangParser.NUM, tlangParser.VAR]: localctx = tlangParser.ValueExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 125 + self.state = 131 self.value() pass elif token in [tlangParser.T__6]: localctx = tlangParser.ParenExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 126 + self.state = 132 self.match(tlangParser.T__6) - self.state = 127 + self.state = 133 self.expression(0) - self.state = 128 + self.state = 134 self.match(tlangParser.T__8) pass else: raise NoViableAltException(self) self._ctx.stop = self._input.LT(-1) - self.state = 146 + self.state = 152 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,6,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: @@ -1161,50 +1217,50 @@ def expression(self, _p:int=0): if self._parseListeners is not None: self.triggerExitRuleEvent() _prevctx = localctx - self.state = 144 + self.state = 150 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,5,self._ctx) if la_ == 1: localctx = tlangParser.MulExprContext(self, tlangParser.ExpressionContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expression) - self.state = 132 + self.state = 138 if not self.precpred(self._ctx, 5): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 5)") - self.state = 133 + self.state = 139 self.multiplicative() - self.state = 134 + self.state = 140 self.expression(6) pass elif la_ == 2: localctx = tlangParser.AddExprContext(self, tlangParser.ExpressionContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expression) - self.state = 136 + self.state = 142 if not self.precpred(self._ctx, 4): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 4)") - self.state = 137 + self.state = 143 self.additive() - self.state = 138 + self.state = 144 self.expression(5) pass elif la_ == 3: localctx = tlangParser.ModExprContext(self, tlangParser.ExpressionContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expression) - self.state = 140 + self.state = 146 if not self.precpred(self._ctx, 3): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 3)") - self.state = 141 + self.state = 147 self.modulo() - self.state = 142 + self.state = 148 self.expression(4) pass - self.state = 148 + self.state = 154 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,6,self._ctx) @@ -1244,11 +1300,11 @@ def accept(self, visitor:ParseTreeVisitor): def multiplicative(self): localctx = tlangParser.MultiplicativeContext(self, self._ctx, self.state) - self.enterRule(localctx, 32, self.RULE_multiplicative) + self.enterRule(localctx, 34, self.RULE_multiplicative) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 149 + self.state = 155 _la = self._input.LA(1) if not(_la==tlangParser.MUL or _la==tlangParser.DIV): self._errHandler.recoverInline(self) @@ -1291,11 +1347,11 @@ def accept(self, visitor:ParseTreeVisitor): def additive(self): localctx = tlangParser.AdditiveContext(self, self._ctx, self.state) - self.enterRule(localctx, 34, self.RULE_additive) + self.enterRule(localctx, 36, self.RULE_additive) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 151 + self.state = 157 _la = self._input.LA(1) if not(_la==tlangParser.PLUS or _la==tlangParser.MINUS): self._errHandler.recoverInline(self) @@ -1335,10 +1391,10 @@ def accept(self, visitor:ParseTreeVisitor): def modulo(self): localctx = tlangParser.ModuloContext(self, self._ctx, self.state) - self.enterRule(localctx, 36, self.RULE_modulo) + self.enterRule(localctx, 38, self.RULE_modulo) try: self.enterOuterAlt(localctx, 1) - self.state = 153 + self.state = 159 self.match(tlangParser.MOD) except RecognitionException as re: localctx.exception = re @@ -1373,10 +1429,10 @@ def accept(self, visitor:ParseTreeVisitor): def unaryArithOp(self): localctx = tlangParser.UnaryArithOpContext(self, self._ctx, self.state) - self.enterRule(localctx, 38, self.RULE_unaryArithOp) + self.enterRule(localctx, 40, self.RULE_unaryArithOp) try: self.enterOuterAlt(localctx, 1) - self.state = 155 + self.state = 161 self.match(tlangParser.MINUS) except RecognitionException as re: localctx.exception = re @@ -1437,46 +1493,46 @@ def condition(self, _p:int=0): _parentState = self.state localctx = tlangParser.ConditionContext(self, self._ctx, _parentState) _prevctx = localctx - _startState = 40 - self.enterRecursionRule(localctx, 40, self.RULE_condition, _p) + _startState = 42 + self.enterRecursionRule(localctx, 42, self.RULE_condition, _p) try: self.enterOuterAlt(localctx, 1) - self.state = 169 + self.state = 175 self._errHandler.sync(self) la_ = self._interp.adaptivePredict(self._input,7,self._ctx) if la_ == 1: - self.state = 158 + self.state = 164 self.match(tlangParser.NOT) - self.state = 159 + self.state = 165 self.condition(5) pass elif la_ == 2: - self.state = 160 + self.state = 166 self.expression(0) - self.state = 161 + self.state = 167 self.binCondOp() - self.state = 162 + self.state = 168 self.expression(0) pass elif la_ == 3: - self.state = 164 + self.state = 170 self.match(tlangParser.PENCOND) pass elif la_ == 4: - self.state = 165 + self.state = 171 self.match(tlangParser.T__6) - self.state = 166 + self.state = 172 self.condition(0) - self.state = 167 + self.state = 173 self.match(tlangParser.T__8) pass self._ctx.stop = self._input.LT(-1) - self.state = 177 + self.state = 183 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,8,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: @@ -1486,15 +1542,15 @@ def condition(self, _p:int=0): _prevctx = localctx localctx = tlangParser.ConditionContext(self, _parentctx, _parentState) self.pushNewRecursionContext(localctx, _startState, self.RULE_condition) - self.state = 171 + self.state = 177 if not self.precpred(self._ctx, 3): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 3)") - self.state = 172 + self.state = 178 self.logicOp() - self.state = 173 + self.state = 179 self.condition(4) - self.state = 179 + self.state = 185 self._errHandler.sync(self) _alt = self._interp.adaptivePredict(self._input,8,self._ctx) @@ -1546,11 +1602,11 @@ def accept(self, visitor:ParseTreeVisitor): def binCondOp(self): localctx = tlangParser.BinCondOpContext(self, self._ctx, self.state) - self.enterRule(localctx, 42, self.RULE_binCondOp) + self.enterRule(localctx, 44, self.RULE_binCondOp) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 180 + self.state = 186 _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.LT) | (1 << tlangParser.GT) | (1 << tlangParser.EQ) | (1 << tlangParser.NEQ) | (1 << tlangParser.LTE) | (1 << tlangParser.GTE))) != 0)): self._errHandler.recoverInline(self) @@ -1593,11 +1649,11 @@ def accept(self, visitor:ParseTreeVisitor): def logicOp(self): localctx = tlangParser.LogicOpContext(self, self._ctx, self.state) - self.enterRule(localctx, 44, self.RULE_logicOp) + self.enterRule(localctx, 46, self.RULE_logicOp) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 182 + self.state = 188 _la = self._input.LA(1) if not(_la==tlangParser.AND or _la==tlangParser.OR): self._errHandler.recoverInline(self) @@ -1640,11 +1696,11 @@ def accept(self, visitor:ParseTreeVisitor): def value(self): localctx = tlangParser.ValueContext(self, self._ctx, self.state) - self.enterRule(localctx, 46, self.RULE_value) + self.enterRule(localctx, 48, self.RULE_value) self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 184 + self.state = 190 _la = self._input.LA(1) if not(_la==tlangParser.NUM or _la==tlangParser.VAR): self._errHandler.recoverInline(self) @@ -1664,8 +1720,8 @@ def value(self): def sempred(self, localctx:RuleContext, ruleIndex:int, predIndex:int): if self._predicates == None: self._predicates = dict() - self._predicates[15] = self.expression_sempred - self._predicates[20] = self.condition_sempred + self._predicates[16] = self.expression_sempred + self._predicates[21] = self.condition_sempred pred = self._predicates.get(ruleIndex, None) if pred is None: raise Exception("No predicate with index:" + str(ruleIndex)) diff --git a/ChironCore/turtparse/tlangVisitor.py b/ChironCore/turtparse/tlangVisitor.py index f1fbdb4..8305cdf 100644 --- a/ChironCore/turtparse/tlangVisitor.py +++ b/ChironCore/turtparse/tlangVisitor.py @@ -84,6 +84,11 @@ def visitAssertionCommand(self, ctx:tlangParser.AssertionCommandContext): return self.visitChildren(ctx) + # Visit a parse tree produced by tlangParser#assumeCommand. + def visitAssumeCommand(self, ctx:tlangParser.AssumeCommandContext): + return self.visitChildren(ctx) + + # Visit a parse tree produced by tlangParser#unaryExpr. def visitUnaryExpr(self, ctx:tlangParser.UnaryExprContext): return self.visitChildren(ctx) diff --git a/ChironCore/unroll.py b/ChironCore/unroll.py index e9ebb18..e1dd41c 100644 --- a/ChironCore/unroll.py +++ b/ChironCore/unroll.py @@ -100,3 +100,6 @@ def visitPenCommand(self, ctx:tlangParser.PenCommandContext): def visitAssertionCommand(self, ctx:tlangParser.AssertionCommandContext): return ctx.getText() + def visitAssumeCommand(self, ctx:tlangParser.AssumeCommandContext): + return ctx.getText() + diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 77b1269..598012d 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,76 +1,404 @@ -:cnt=0 -:i=0 -:_repeat0 = :steps +:_repeat0 = :a if (:_repeat0 > 0) [ -:i=:cnt+:i -:cnt=:cnt+1 -forward(1+:cnt) -right(:radius) +forward10 ] if (:_repeat0 > 1) [ -:i=:cnt+:i -:cnt=:cnt+1 -forward(1+:cnt) -right(:radius) +forward10 ] if (:_repeat0 > 2) [ -:i=:cnt+:i -:cnt=:cnt+1 -forward(1+:cnt) -right(:radius) +forward10 ] if (:_repeat0 > 3) [ -:i=:cnt+:i -:cnt=:cnt+1 -forward(1+:cnt) -right(:radius) +forward10 ] if (:_repeat0 > 4) [ -:i=:cnt+:i -:cnt=:cnt+1 -forward(1+:cnt) -right(:radius) +forward10 ] if (:_repeat0 > 5) [ -:i=:cnt+:i -:cnt=:cnt+1 -forward(1+:cnt) -right(:radius) +forward10 ] if (:_repeat0 > 6) [ -:i=:cnt+:i -:cnt=:cnt+1 -forward(1+:cnt) -right(:radius) +forward10 ] if (:_repeat0 > 7) [ -:i=:cnt+:i -:cnt=:cnt+1 -forward(1+:cnt) -right(:radius) +forward10 ] if (:_repeat0 > 8) [ -:i=:cnt+:i -:cnt=:cnt+1 -forward(1+:cnt) -right(:radius) +forward10 ] if (:_repeat0 > 9) [ -:i=:cnt+:i -:cnt=:cnt+1 -forward(1+:cnt) -right(:radius) +forward10 ] +if (:_repeat0 > 10) [ +forward10 +] +if (:_repeat0 > 11) [ +forward10 + +] +if (:_repeat0 > 12) [ +forward10 + +] +if (:_repeat0 > 13) [ +forward10 + +] +if (:_repeat0 > 14) [ +forward10 + +] +if (:_repeat0 > 15) [ +forward10 + +] +if (:_repeat0 > 16) [ +forward10 + +] +if (:_repeat0 > 17) [ +forward10 + +] +if (:_repeat0 > 18) [ +forward10 + +] +if (:_repeat0 > 19) [ +forward10 + +] +if (:_repeat0 > 20) [ +forward10 + +] +if (:_repeat0 > 21) [ +forward10 + +] +if (:_repeat0 > 22) [ +forward10 + +] +if (:_repeat0 > 23) [ +forward10 + +] +if (:_repeat0 > 24) [ +forward10 + +] +if (:_repeat0 > 25) [ +forward10 + +] +if (:_repeat0 > 26) [ +forward10 + +] +if (:_repeat0 > 27) [ +forward10 + +] +if (:_repeat0 > 28) [ +forward10 + +] +if (:_repeat0 > 29) [ +forward10 + +] +if (:_repeat0 > 30) [ +forward10 + +] +if (:_repeat0 > 31) [ +forward10 + +] +if (:_repeat0 > 32) [ +forward10 + +] +if (:_repeat0 > 33) [ +forward10 + +] +if (:_repeat0 > 34) [ +forward10 + +] +if (:_repeat0 > 35) [ +forward10 + +] +if (:_repeat0 > 36) [ +forward10 + +] +if (:_repeat0 > 37) [ +forward10 + +] +if (:_repeat0 > 38) [ +forward10 + +] +if (:_repeat0 > 39) [ +forward10 + +] +if (:_repeat0 > 40) [ +forward10 + +] +if (:_repeat0 > 41) [ +forward10 + +] +if (:_repeat0 > 42) [ +forward10 + +] +if (:_repeat0 > 43) [ +forward10 + +] +if (:_repeat0 > 44) [ +forward10 + +] +if (:_repeat0 > 45) [ +forward10 + +] +if (:_repeat0 > 46) [ +forward10 + +] +if (:_repeat0 > 47) [ +forward10 + +] +if (:_repeat0 > 48) [ +forward10 + +] +if (:_repeat0 > 49) [ +forward10 + +] +if (:_repeat0 > 50) [ +forward10 + +] +if (:_repeat0 > 51) [ +forward10 + +] +if (:_repeat0 > 52) [ +forward10 + +] +if (:_repeat0 > 53) [ +forward10 + +] +if (:_repeat0 > 54) [ +forward10 + +] +if (:_repeat0 > 55) [ +forward10 + +] +if (:_repeat0 > 56) [ +forward10 + +] +if (:_repeat0 > 57) [ +forward10 + +] +if (:_repeat0 > 58) [ +forward10 + +] +if (:_repeat0 > 59) [ +forward10 + +] +if (:_repeat0 > 60) [ +forward10 + +] +if (:_repeat0 > 61) [ +forward10 + +] +if (:_repeat0 > 62) [ +forward10 + +] +if (:_repeat0 > 63) [ +forward10 + +] +if (:_repeat0 > 64) [ +forward10 + +] +if (:_repeat0 > 65) [ +forward10 + +] +if (:_repeat0 > 66) [ +forward10 + +] +if (:_repeat0 > 67) [ +forward10 + +] +if (:_repeat0 > 68) [ +forward10 + +] +if (:_repeat0 > 69) [ +forward10 + +] +if (:_repeat0 > 70) [ +forward10 + +] +if (:_repeat0 > 71) [ +forward10 + +] +if (:_repeat0 > 72) [ +forward10 + +] +if (:_repeat0 > 73) [ +forward10 + +] +if (:_repeat0 > 74) [ +forward10 + +] +if (:_repeat0 > 75) [ +forward10 + +] +if (:_repeat0 > 76) [ +forward10 + +] +if (:_repeat0 > 77) [ +forward10 + +] +if (:_repeat0 > 78) [ +forward10 + +] +if (:_repeat0 > 79) [ +forward10 + +] +if (:_repeat0 > 80) [ +forward10 + +] +if (:_repeat0 > 81) [ +forward10 + +] +if (:_repeat0 > 82) [ +forward10 + +] +if (:_repeat0 > 83) [ +forward10 + +] +if (:_repeat0 > 84) [ +forward10 + +] +if (:_repeat0 > 85) [ +forward10 + +] +if (:_repeat0 > 86) [ +forward10 + +] +if (:_repeat0 > 87) [ +forward10 + +] +if (:_repeat0 > 88) [ +forward10 + +] +if (:_repeat0 > 89) [ +forward10 + +] +if (:_repeat0 > 90) [ +forward10 + +] +if (:_repeat0 > 91) [ +forward10 + +] +if (:_repeat0 > 92) [ +forward10 + +] +if (:_repeat0 > 93) [ +forward10 + +] +if (:_repeat0 > 94) [ +forward10 + +] +if (:_repeat0 > 95) [ +forward10 + +] +if (:_repeat0 > 96) [ +forward10 + +] +if (:_repeat0 > 97) [ +forward10 + +] +if (:_repeat0 > 98) [ +forward10 + +] +if (:_repeat0 > 99) [ +forward10 + +] -assert (:turtleX > 0) \ No newline at end of file +assume:a<1 +assert:turtleX<=1&&:turtleX>=-1&&:turtleY<=1&&:turtleY>=-1 From 9686dff3698ae2bf4fbe0b5dd1e9ef60a5155abd Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Sat, 5 Apr 2025 15:44:05 +0530 Subject: [PATCH 42/53] added implies in assert, assume and assume before loops --- ChironCore/bmc.py | 23 +- ChironCore/example/amogh.tl | 5 +- ChironCore/example/bmc_tc1.tl | 11 +- ChironCore/example/bmc_tc2.tl | 6 +- ChironCore/example/bmc_tc3.tl | 2 +- ChironCore/example/exm.tl | 5 + ChironCore/example/exm2.tl | 4 + ChironCore/unroll.py | 2 + ChironCore/unrolled_code.tl | 418 ++++------------------------------ 9 files changed, 98 insertions(+), 378 deletions(-) create mode 100644 ChironCore/example/exm.tl create mode 100644 ChironCore/example/exm2.tl diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 3719825..50a7361 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -196,7 +196,10 @@ def convertSSAtoSMT(self): cond = z3.BoolVal(False) elif isinstance(stmt.cond, ChironSSA.Var): cond = z3.Bool(stmt.cond.name) - self.assert_conditions = z3.And(self.assert_conditions, cond) + if self.varConditions[stmt.cond.name] not in (None, True, False): + self.assert_conditions = z3.And(self.assert_conditions, z3.Implies(self.varConditions[stmt.cond.name], cond)) + elif self.varConditions[stmt.cond.name] is not False: + self.assert_conditions = z3.And(self.assert_conditions, cond) elif isinstance(stmt, ChironSSA.AssumeCommand): cond = None @@ -206,7 +209,10 @@ def convertSSAtoSMT(self): cond = z3.BoolVal(False) elif isinstance(stmt.cond, ChironSSA.Var): cond = z3.Bool(stmt.cond.name) - self.assume_conditions = z3.And(self.assume_conditions, cond) + if self.varConditions[stmt.cond.name] not in (None, True, False): + self.assume_conditions = z3.And(self.assume_conditions, z3.Implies(self.varConditions[stmt.cond.name], cond)) + elif self.varConditions[stmt.cond.name] is not False: + self.assume_conditions = z3.And(self.assume_conditions, cond) elif isinstance(stmt, ChironSSA.CosCommand): # Only for 0, 90, 180, 270 degree rvar = z3.Int(stmt.rvar.name) @@ -249,8 +255,17 @@ def solve(self, inputVars): self.solver.add(self.angle_conditions) self.solver.add(self.assume_conditions) - # print("The clauses are:") - # print(self.solver, end="\n\n") + checker_with_assume = z3.Solver() + checker_with_assume.add(self.solver_without_cond.assertions()) + checker_with_assume.add(self.assume_conditions) + + assume_check = checker_with_assume.check() + if assume_check == z3.unsat: + print("Give a larger unroll bound") + return + elif assume_check == z3.unknown: + print("Cannot determine if unroll bound is sufficient") + return sat = self.solver.check() diff --git a/ChironCore/example/amogh.tl b/ChironCore/example/amogh.tl index f0105ae..c350c78 100644 --- a/ChironCore/example/amogh.tl +++ b/ChironCore/example/amogh.tl @@ -12,7 +12,10 @@ repeat :a [ forward 10 + if (:a < 2) [ + :y = 3 + ] ] -assume :a < 1 +// assume :a == 2 assert :turtleX <= 1 && :turtleX >= -1 && :turtleY <= 1 && :turtleY >= -1 diff --git a/ChironCore/example/bmc_tc1.tl b/ChironCore/example/bmc_tc1.tl index 57e65e3..43ee10c 100644 --- a/ChironCore/example/bmc_tc1.tl +++ b/ChironCore/example/bmc_tc1.tl @@ -1,7 +1,16 @@ :t = 1 +assume :x > 0 repeat 2 [ :t = :t * :x + assert :t > 0 ] :s = 5 * :x :z = :t + :s + 2 -assert :z >= -5 +// assert :z >= -5 + + +// cant do the following +// if (b > 0) [ // :a is not defined earlier +// :a = 1 +// ] +// forward :a \ No newline at end of file diff --git a/ChironCore/example/bmc_tc2.tl b/ChironCore/example/bmc_tc2.tl index 7626556..e8f498d 100644 --- a/ChironCore/example/bmc_tc2.tl +++ b/ChironCore/example/bmc_tc2.tl @@ -1,4 +1,5 @@ :p = 1 + repeat 5 [ :t = :t * :x ] @@ -14,8 +15,11 @@ repeat 7 [ ] :s = 1 -repeat 9 [ + +@unroll +repeat :o [ :s = :s * :x + :o = :o - 1 ] :z = 2*:p - 3*:q + 5*:r - 7*:s diff --git a/ChironCore/example/bmc_tc3.tl b/ChironCore/example/bmc_tc3.tl index 8fe648a..728daa7 100644 --- a/ChironCore/example/bmc_tc3.tl +++ b/ChironCore/example/bmc_tc3.tl @@ -1,4 +1,4 @@ -:a = 1 +:a = -1 :y = 0 if (:a > 0) [ :x = :y + 2 diff --git a/ChironCore/example/exm.tl b/ChironCore/example/exm.tl new file mode 100644 index 0000000..7ac92a7 --- /dev/null +++ b/ChironCore/example/exm.tl @@ -0,0 +1,5 @@ +forward 10 +left 90 +right 90 +forward :x +assert :turtleX*:turtleX + :turtleY*:turtleY <= 100 \ No newline at end of file diff --git a/ChironCore/example/exm2.tl b/ChironCore/example/exm2.tl new file mode 100644 index 0000000..01038b9 --- /dev/null +++ b/ChironCore/example/exm2.tl @@ -0,0 +1,4 @@ +if (:b > 0) [ + :a = 1 + assert :a == 2 +] \ No newline at end of file diff --git a/ChironCore/unroll.py b/ChironCore/unroll.py index e1dd41c..62d0571 100644 --- a/ChironCore/unroll.py +++ b/ChironCore/unroll.py @@ -79,12 +79,14 @@ def visitLoop(self, ctx:tlangParser.LoopContext): code = "" if (repeatCount[0] != ":"): # constant number of iterations + code += "assume " + str(repeatCount) + " <= " + str(self.bound) +"\n" for i in range(min(int(repeatCount), self.bound)): code += loopBlock + "\n" else: # variable number of iterations repeatVariable = ":_repeat" + str(self.repeatVariablesCounter) code += repeatVariable + " = " + repeatCount + "\n" + code += "assume " + repeatVariable + " <= " + str(self.bound) +" \n" for i in range(self.bound): code += "if (" + repeatVariable + " > " + str(i) + ") [\n" + loopBlock + "\n]\n" self.repeatVariablesCounter += 1 diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 598012d..cc950b0 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,404 +1,82 @@ -:_repeat0 = :a -if (:_repeat0 > 0) [ -forward10 - -] -if (:_repeat0 > 1) [ -forward10 - -] -if (:_repeat0 > 2) [ -forward10 - -] -if (:_repeat0 > 3) [ -forward10 - -] -if (:_repeat0 > 4) [ -forward10 - -] -if (:_repeat0 > 5) [ -forward10 - -] -if (:_repeat0 > 6) [ -forward10 - -] -if (:_repeat0 > 7) [ -forward10 - -] -if (:_repeat0 > 8) [ -forward10 +:p=1 +assume 5 <= 7 +:t=:t*:x -] -if (:_repeat0 > 9) [ -forward10 +:t=:t*:x -] -if (:_repeat0 > 10) [ -forward10 +:t=:t*:x -] -if (:_repeat0 > 11) [ -forward10 +:t=:t*:x -] -if (:_repeat0 > 12) [ -forward10 +:t=:t*:x -] -if (:_repeat0 > 13) [ -forward10 -] -if (:_repeat0 > 14) [ -forward10 +:q=1 +assume 4 <= 7 +:q=:q*:x -] -if (:_repeat0 > 15) [ -forward10 +:q=:q*:x -] -if (:_repeat0 > 16) [ -forward10 +:q=:q*:x -] -if (:_repeat0 > 17) [ -forward10 +:q=:q*:x -] -if (:_repeat0 > 18) [ -forward10 -] -if (:_repeat0 > 19) [ -forward10 +:r=1 +assume 7 <= 7 +:r=:r*:x -] -if (:_repeat0 > 20) [ -forward10 +:r=:r*:x -] -if (:_repeat0 > 21) [ -forward10 - -] -if (:_repeat0 > 22) [ -forward10 +:r=:r*:x -] -if (:_repeat0 > 23) [ -forward10 +:r=:r*:x -] -if (:_repeat0 > 24) [ -forward10 +:r=:r*:x -] -if (:_repeat0 > 25) [ -forward10 +:r=:r*:x -] -if (:_repeat0 > 26) [ -forward10 - -] -if (:_repeat0 > 27) [ -forward10 - -] -if (:_repeat0 > 28) [ -forward10 +:r=:r*:x -] -if (:_repeat0 > 29) [ -forward10 - -] -if (:_repeat0 > 30) [ -forward10 - -] -if (:_repeat0 > 31) [ -forward10 - -] -if (:_repeat0 > 32) [ -forward10 - -] -if (:_repeat0 > 33) [ -forward10 - -] -if (:_repeat0 > 34) [ -forward10 - -] -if (:_repeat0 > 35) [ -forward10 - -] -if (:_repeat0 > 36) [ -forward10 - -] -if (:_repeat0 > 37) [ -forward10 - -] -if (:_repeat0 > 38) [ -forward10 - -] -if (:_repeat0 > 39) [ -forward10 - -] -if (:_repeat0 > 40) [ -forward10 - -] -if (:_repeat0 > 41) [ -forward10 - -] -if (:_repeat0 > 42) [ -forward10 - -] -if (:_repeat0 > 43) [ -forward10 - -] -if (:_repeat0 > 44) [ -forward10 - -] -if (:_repeat0 > 45) [ -forward10 - -] -if (:_repeat0 > 46) [ -forward10 - -] -if (:_repeat0 > 47) [ -forward10 - -] -if (:_repeat0 > 48) [ -forward10 - -] -if (:_repeat0 > 49) [ -forward10 - -] -if (:_repeat0 > 50) [ -forward10 - -] -if (:_repeat0 > 51) [ -forward10 -] -if (:_repeat0 > 52) [ -forward10 - -] -if (:_repeat0 > 53) [ -forward10 - -] -if (:_repeat0 > 54) [ -forward10 - -] -if (:_repeat0 > 55) [ -forward10 - -] -if (:_repeat0 > 56) [ -forward10 - -] -if (:_repeat0 > 57) [ -forward10 - -] -if (:_repeat0 > 58) [ -forward10 - -] -if (:_repeat0 > 59) [ -forward10 - -] -if (:_repeat0 > 60) [ -forward10 - -] -if (:_repeat0 > 61) [ -forward10 - -] -if (:_repeat0 > 62) [ -forward10 - -] -if (:_repeat0 > 63) [ -forward10 - -] -if (:_repeat0 > 64) [ -forward10 - -] -if (:_repeat0 > 65) [ -forward10 - -] -if (:_repeat0 > 66) [ -forward10 - -] -if (:_repeat0 > 67) [ -forward10 - -] -if (:_repeat0 > 68) [ -forward10 - -] -if (:_repeat0 > 69) [ -forward10 - -] -if (:_repeat0 > 70) [ -forward10 - -] -if (:_repeat0 > 71) [ -forward10 - -] -if (:_repeat0 > 72) [ -forward10 - -] -if (:_repeat0 > 73) [ -forward10 - -] -if (:_repeat0 > 74) [ -forward10 - -] -if (:_repeat0 > 75) [ -forward10 - -] -if (:_repeat0 > 76) [ -forward10 - -] -if (:_repeat0 > 77) [ -forward10 - -] -if (:_repeat0 > 78) [ -forward10 - -] -if (:_repeat0 > 79) [ -forward10 - -] -if (:_repeat0 > 80) [ -forward10 - -] -if (:_repeat0 > 81) [ -forward10 - -] -if (:_repeat0 > 82) [ -forward10 - -] -if (:_repeat0 > 83) [ -forward10 - -] -if (:_repeat0 > 84) [ -forward10 - -] -if (:_repeat0 > 85) [ -forward10 - -] -if (:_repeat0 > 86) [ -forward10 - -] -if (:_repeat0 > 87) [ -forward10 - -] -if (:_repeat0 > 88) [ -forward10 - -] -if (:_repeat0 > 89) [ -forward10 - -] -if (:_repeat0 > 90) [ -forward10 - -] -if (:_repeat0 > 91) [ -forward10 - -] -if (:_repeat0 > 92) [ -forward10 - -] -if (:_repeat0 > 93) [ -forward10 +:s=1 +:_repeat0 = :o +assume :_repeat0 <= 7 +if (:_repeat0 > 0) [ +:s=:s*:x +:o=:o-1 ] -if (:_repeat0 > 94) [ -forward10 +if (:_repeat0 > 1) [ +:s=:s*:x +:o=:o-1 ] -if (:_repeat0 > 95) [ -forward10 +if (:_repeat0 > 2) [ +:s=:s*:x +:o=:o-1 ] -if (:_repeat0 > 96) [ -forward10 +if (:_repeat0 > 3) [ +:s=:s*:x +:o=:o-1 ] -if (:_repeat0 > 97) [ -forward10 +if (:_repeat0 > 4) [ +:s=:s*:x +:o=:o-1 ] -if (:_repeat0 > 98) [ -forward10 +if (:_repeat0 > 5) [ +:s=:s*:x +:o=:o-1 ] -if (:_repeat0 > 99) [ -forward10 +if (:_repeat0 > 6) [ +:s=:s*:x +:o=:o-1 ] -assume:a<1 -assert:turtleX<=1&&:turtleX>=-1&&:turtleY<=1&&:turtleY>=-1 +:z=2*:p-3*:q+5*:r-7*:s +assert:z>-10000 From b124abd92e84f41b31b9572d2e44d6891ad918be Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Sat, 5 Apr 2025 17:39:47 +0530 Subject: [PATCH 43/53] modified free variables --- ChironCore/ChironTAC/builder.py | 49 ++++++- ChironCore/chiron.py | 4 +- ChironCore/example/bmc_tc1.tl | 2 +- ChironCore/example/bmc_tc2.tl | 3 +- ChironCore/example/exm.tl | 1 + ChironCore/example/exm2.tl | 7 +- ChironCore/unrolled_code.tl | 240 +++++++++++++++++++++++++------- 7 files changed, 245 insertions(+), 61 deletions(-) diff --git a/ChironCore/ChironTAC/builder.py b/ChironCore/ChironTAC/builder.py index 311269f..60c17d4 100644 --- a/ChironCore/ChironTAC/builder.py +++ b/ChironCore/ChironTAC/builder.py @@ -4,7 +4,8 @@ from ChironAST import ChironAST from ChironTAC import ChironTAC - +import cfg.cfgBuilder as cfgB +import z3 class TACGenerator: def __init__(self, ir): @@ -19,6 +20,9 @@ def __init__(self, ir): self.ast_to_tac_line = {} self.line = 0 self.freeVars = set() + self.tacCfg = None + self.bbConditions = {} # bbConditions[bb] = condition for bb + self.varConditions = {} # varConditions[var] = condition for var def parseExpresssion(self, expr, dest): """ @@ -378,8 +382,42 @@ def generateTAC(self): self.tac[i] = (stmt, newtgt) self.handleMoveVariables() + + self.tacCfg, _ = cfgB.buildCFG(self.tac, "control_flow_graph", False) # Building CFG + for bb in self.tacCfg: + self.bbConditions[bb] = None + self.buildConditions() + self.handleFreeVariables() + def buildConditions(self): + topological_order = list(self.tacCfg.get_topological_order()) + start = topological_order[0] + start.set_condition(z3.BoolVal(True)) + topological_order.pop(0) + for node in topological_order: + for pred in self.tacCfg.predecessors(node): + instr = pred.instrlist[-1][0] + current_cond = node.get_condition() + if isinstance(instr, ChironTAC.ConditionCommand) and type(instr.cond) == ChironTAC.Var: + cond = z3.Bool(instr.cond.name) + label = self.tacCfg.get_edge_label(pred, node) + if label == 'Cond_True': + node.set_condition(z3.Or(current_cond, z3.And(pred.get_condition(), cond))) + elif label == 'Cond_False': + node.set_condition(z3.Or(current_cond, z3.And(pred.get_condition(), z3.Not(cond)))) + else: + node.set_condition(z3.Or(pred.get_condition(), current_cond)) + + t = z3.Tactic('ctx-simplify').apply(node.get_condition()).as_expr() + node.set_condition(t) + self.bbConditions[node] = node.get_condition() + + for bb in self.tacCfg.nodes(): + for stmt, _ in bb.instrlist: + if isinstance(stmt, (ChironTAC.AssignmentCommand, ChironTAC.SinCommand, ChironTAC.CosCommand)): + self.varConditions[stmt.lvar.name] = self.bbConditions[bb] if self.bbConditions[bb] is not None else z3.BoolVal(True) + def handleFreeVariables(self): self.freeVars = self.getFreeVariables() @@ -406,7 +444,8 @@ def getFreeVariables(self): self.freeVars.add(stmt.rvar1.__str__()) if isinstance(stmt.rvar2, ChironTAC.Var) and stmt.rvar2.__str__() not in boundVars: self.freeVars.add(stmt.rvar2.__str__()) - boundVars.add(stmt.lvar.__str__()) + if self.varConditions[stmt.lvar.name] is True: + boundVars.add(stmt.lvar.__str__()) elif isinstance(stmt, ChironTAC.ConditionCommand): if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: self.freeVars.add(stmt.cond.__str__()) @@ -427,11 +466,13 @@ def getFreeVariables(self): elif isinstance(stmt, ChironTAC.SinCommand): if isinstance(stmt.rvar, ChironTAC.Var) and stmt.rvar.__str__() not in boundVars: self.freeVars.add(stmt.rvar.__str__()) - boundVars.add(stmt.lvar.__str__()) + if self.varConditions[stmt.lvar.name] is True: + boundVars.add(stmt.lvar.__str__()) elif isinstance(stmt, ChironTAC.CosCommand): if isinstance(stmt.rvar, ChironTAC.Var) and stmt.rvar.__str__() not in boundVars: self.freeVars.add(stmt.rvar.__str__()) - boundVars.add(stmt.lvar.__str__()) + if self.varConditions[stmt.lvar.name] is True: + boundVars.add(stmt.lvar.__str__()) return self.freeVars diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index d998161..0528c8e 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -469,8 +469,8 @@ def stopTurtle(): print("No conditions found in the program. Exiting...") exit(1) - cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) # Building CFG - cfgB.dumpCFG(cfg, 'tac_cfg') + # cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) # Building CFG + cfgB.dumpCFG(tacGen.tacCfg, 'tac_cfg') ssa = SSABuilder(tacGen.tac) # Converting TAC to SSA ssaCfg = ssa.build() diff --git a/ChironCore/example/bmc_tc1.tl b/ChironCore/example/bmc_tc1.tl index 43ee10c..57533f7 100644 --- a/ChironCore/example/bmc_tc1.tl +++ b/ChironCore/example/bmc_tc1.tl @@ -1,5 +1,5 @@ :t = 1 -assume :x > 0 +// assume :x > 0 repeat 2 [ :t = :t * :x assert :t > 0 diff --git a/ChironCore/example/bmc_tc2.tl b/ChironCore/example/bmc_tc2.tl index e8f498d..1ddca2a 100644 --- a/ChironCore/example/bmc_tc2.tl +++ b/ChironCore/example/bmc_tc2.tl @@ -16,11 +16,10 @@ repeat 7 [ :s = 1 -@unroll repeat :o [ :s = :s * :x :o = :o - 1 ] :z = 2*:p - 3*:q + 5*:r - 7*:s -assert :z > -10000 +assert :z < -10000 diff --git a/ChironCore/example/exm.tl b/ChironCore/example/exm.tl index 7ac92a7..62c5439 100644 --- a/ChironCore/example/exm.tl +++ b/ChironCore/example/exm.tl @@ -1,5 +1,6 @@ forward 10 left 90 right 90 +assume :x > 0 forward :x assert :turtleX*:turtleX + :turtleY*:turtleY <= 100 \ No newline at end of file diff --git a/ChironCore/example/exm2.tl b/ChironCore/example/exm2.tl index 01038b9..2ac7b91 100644 --- a/ChironCore/example/exm2.tl +++ b/ChironCore/example/exm2.tl @@ -1,4 +1,7 @@ +assume :a < 0 if (:b > 0) [ :a = 1 - assert :a == 2 -] \ No newline at end of file + assert :a == 1 +] +forward :a +assert :turtleX > 0 \ No newline at end of file diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index cc950b0..a4e1e60 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,82 +1,222 @@ -:p=1 -assume 5 <= 7 -:t=:t*:x +pendown +assume 3 <= 10 +if ((:x>:y)) [ +penup +goto (:x, :y) +pendown +assume 4 <= 10 +forward:x +left90 -:t=:t*:x +forward:x +left90 -:t=:t*:x +forward:x +left90 -:t=:t*:x +forward:x +left90 -:t=:t*:x -:q=1 -assume 4 <= 7 -:q=:q*:x +] else [ +penup +goto (:y, :x) +pendown +assume 5 <= 10 +forward:p +left72 -:q=:q*:x +forward:p +left72 -:q=:q*:x +forward:p +left72 -:q=:q*:x +forward:p +left72 +forward:p +left72 -:r=1 -assume 7 <= 7 -:r=:r*:x -:r=:r*:x -:r=:r*:x +] +if ((:z>=:p)) [ +penup +goto (:p, :x+:z) +pendown +assume 6 <= 10 +backward:x +left60 -:r=:r*:x +backward:x +left60 -:r=:r*:x +backward:x +left60 -:r=:r*:x +backward:x +left60 -:r=:r*:x +backward:x +left60 +backward:x +left60 -:s=1 -:_repeat0 = :o -assume :_repeat0 <= 7 -if (:_repeat0 > 0) [ -:s=:s*:x -:o=:o-1 -] -if (:_repeat0 > 1) [ -:s=:s*:x -:o=:o-1 ] -if (:_repeat0 > 2) [ -:s=:s*:x -:o=:o-1 +:x=:x+10 +:y=:y+10 +:z=:z+10 + +if ((:x>:y)) [ +penup +goto (:x, :y) +pendown +assume 4 <= 10 +forward:x +left90 + +forward:x +left90 + +forward:x +left90 + +forward:x +left90 + + + +] else [ +penup +goto (:y, :x) +pendown +assume 5 <= 10 +forward:p +left72 + +forward:p +left72 + +forward:p +left72 + +forward:p +left72 + +forward:p +left72 + -] -if (:_repeat0 > 3) [ -:s=:s*:x -:o=:o-1 ] -if (:_repeat0 > 4) [ -:s=:s*:x -:o=:o-1 +if ((:z>=:p)) [ +penup +goto (:p, :x+:z) +pendown +assume 6 <= 10 +backward:x +left60 + +backward:x +left60 + +backward:x +left60 + +backward:x +left60 + +backward:x +left60 + +backward:x +left60 + + ] -if (:_repeat0 > 5) [ -:s=:s*:x -:o=:o-1 +:x=:x+10 +:y=:y+10 +:z=:z+10 + +if ((:x>:y)) [ +penup +goto (:x, :y) +pendown +assume 4 <= 10 +forward:x +left90 + +forward:x +left90 + +forward:x +left90 + +forward:x +left90 + + + +] else [ +penup +goto (:y, :x) +pendown +assume 5 <= 10 +forward:p +left72 + +forward:p +left72 + +forward:p +left72 + +forward:p +left72 + +forward:p +left72 + + ] -if (:_repeat0 > 6) [ -:s=:s*:x -:o=:o-1 +if ((:z>=:p)) [ +penup +goto (:p, :x+:z) +pendown +assume 6 <= 10 +backward:x +left60 + +backward:x +left60 + +backward:x +left60 + +backward:x +left60 + +backward:x +left60 + +backward:x +left60 + + ] +:x=:x+10 +:y=:y+10 +:z=:z+10 + + +penup -:z=2*:p-3*:q+5*:r-7*:s -assert:z>-10000 +assert (:turtleX > 0) \ No newline at end of file From 6a51979f90c2cc479ce36ad4ca268781ec81f4de Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Sat, 5 Apr 2025 21:18:42 +0530 Subject: [PATCH 44/53] add decorator for unroll bound for each loop --- ChironCore/chiron.py | 63 ++-- ChironCore/example/amogh.tl | 20 +- ChironCore/turtparse/tlang.g4 | 3 +- ChironCore/turtparse/tlang.interp | 4 +- ChironCore/turtparse/tlang.tokens | 100 +++--- ChironCore/turtparse/tlangLexer.interp | 5 +- ChironCore/turtparse/tlangLexer.py | 253 +++++++-------- ChironCore/turtparse/tlangLexer.tokens | 100 +++--- ChironCore/turtparse/tlangParser.py | 419 ++++++++++++++----------- ChironCore/unroll.py | 11 +- ChironCore/unrolled_code.tl | 273 ++++++---------- 11 files changed, 593 insertions(+), 658 deletions(-) diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 0528c8e..08e6ee8 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -3,6 +3,8 @@ import ast import sys + +from antlr4 import InputStream from ChironAST.builder import astGenPass import abstractInterpretation as AI import dataFlowAnalysis as DFA @@ -208,6 +210,14 @@ def stopTurtle(): help="Run Bounded Model Checking on a Chiron Program.", ) + cmdparser.add_argument( + "-ub", + "--unroll-bound", + type=int, + default=10, + help="Unroll bound for the program. Default is 10.", + ) + args = cmdparser.parse_args() ir = "" @@ -408,7 +418,7 @@ def stopTurtle(): if args.bmc: print("\nBounded Model Checking...") - unroll_bound = int(input("Enter the unroll bound for the program: ")) + unroll_bound = args.unroll_bound if unroll_bound < 1: print("Invalid unroll bound. Exiting...") @@ -416,48 +426,21 @@ def stopTurtle(): unrolled_code = unroll.UnrollLoops(unroll_bound).visitStart(getParseTree(args.progfl)) - constraint_count = int(input("Enter the number of constraints in the program: ")) - if constraint_count < 0: - print("Invalid number of constraints. Exiting...") - exit(1) - - if constraint_count != 0: - constraints = [] - for i in range(constraint_count): - constraints.append(input(f"Enter constraint {i+1}: ")) - - constraint_stmt = constraints[0] - for i in range(1, constraint_count): - constraint_stmt = constraint_stmt + " && " + constraints[i] - - unrolled_code = unrolled_code + '\n' + "assume " + constraint_stmt - - cond_count = int(input("Enter the number of conditions in the program: ")) - - if cond_count < 0: - print("Invalid number of conditions. Exiting...") - exit(1) - - if cond_count != 0: - cond = [] - for i in range(cond_count): - cond.append(input(f"Enter condition {i+1}: ")) - - cond_stmt = "(" + cond[0] +")" - for i in range(1, cond_count): - cond_stmt = cond_stmt + " && (" + cond[i] + ")" - assert_stmt = "assert " + cond_stmt - - unrolled_code = unrolled_code + '\n' + assert_stmt # for adding asserts at the end - - # unrolled_code_lines = unrolled_code.split('\n') # for adding asserts after every line - # unrolled_code_lines = [line for line in unrolled_code_lines if line != ""] - # unrolled_code = '\n'.join([line + '\n' + assert_stmt for line in unrolled_code_lines]) - with open("unrolled_code.tl", "w") as f: f.write(unrolled_code) - parseTree = getParseTree("unrolled_code.tl") + try: + lexer = tlangLexer(InputStream(unrolled_code)) + stream = antlr4.CommonTokenStream(lexer) + lexer._listeners = [SyntaxErrorListener()] + tparser = tlangParser(stream) + tparser._listeners = [SyntaxErrorListener()] + parseTree = tparser.start() + except Exception as e: + print("\033[91m\n====================") + print(e.__str__() + "\033[0m\n") + exit(1) + astgen = astGenPass() ir = astgen.visitStart(parseTree) diff --git a/ChironCore/example/amogh.tl b/ChironCore/example/amogh.tl index c350c78..3cee916 100644 --- a/ChironCore/example/amogh.tl +++ b/ChironCore/example/amogh.tl @@ -1,15 +1,10 @@ -//:delta = 10 -//repeat 5 [ -// forward :delta -// left 90 -// forward :delta -// left 90 -// :delta = :delta + 10 -//] -// -//:a = 29 -//assert :turtleX >= -:a && :turtleX <= :a && :turtleY >= -:a && :turtleY <= :a - +@unroll 5 +repeat :a [ + forward 10 + if (:a < 2) [ + :y = 3 + ] +] repeat :a [ forward 10 if (:a < 2) [ @@ -17,5 +12,4 @@ repeat :a [ ] ] -// assume :a == 2 assert :turtleX <= 1 && :turtleX >= -1 && :turtleY <= 1 && :turtleY >= -1 diff --git a/ChironCore/turtparse/tlang.g4 b/ChironCore/turtparse/tlang.g4 index ff6c103..e474267 100644 --- a/ChironCore/turtparse/tlang.g4 +++ b/ChironCore/turtparse/tlang.g4 @@ -27,7 +27,8 @@ ifConditional : 'if' condition '[' strict_ilist ']' ; ifElseConditional : 'if' condition '[' strict_ilist ']' 'else' '[' strict_ilist ']' ; -loop : 'repeat' value '[' strict_ilist ']' ; +loop : 'repeat' value '[' strict_ilist ']' + | '@unroll' NUM 'repeat' value '[' strict_ilist ']' ; gotoCommand : 'goto' '(' expression ',' expression ')'; diff --git a/ChironCore/turtparse/tlang.interp b/ChironCore/turtparse/tlang.interp index eb06ca0..c0dd5ff 100644 --- a/ChironCore/turtparse/tlang.interp +++ b/ChironCore/turtparse/tlang.interp @@ -5,6 +5,7 @@ null ']' 'else' 'repeat' +'@unroll' 'goto' '(' ',' @@ -61,6 +62,7 @@ null null null null +null PLUS MINUS MUL @@ -111,4 +113,4 @@ value atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 41, 195, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 57, 10, 3, 12, 3, 14, 3, 60, 11, 3, 3, 4, 6, 4, 63, 10, 4, 13, 4, 14, 4, 64, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 76, 10, 5, 3, 6, 3, 6, 5, 6, 80, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 139, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 153, 10, 18, 12, 18, 14, 18, 156, 11, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 178, 10, 23, 3, 23, 3, 23, 3, 23, 3, 23, 7, 23, 184, 10, 23, 12, 23, 14, 23, 187, 11, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 2, 4, 34, 44, 27, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 2, 9, 3, 2, 13, 16, 3, 2, 17, 18, 3, 2, 24, 25, 3, 2, 22, 23, 3, 2, 28, 33, 3, 2, 34, 35, 3, 2, 37, 38, 2, 189, 2, 52, 3, 2, 2, 2, 4, 58, 3, 2, 2, 2, 6, 62, 3, 2, 2, 2, 8, 75, 3, 2, 2, 2, 10, 79, 3, 2, 2, 2, 12, 81, 3, 2, 2, 2, 14, 87, 3, 2, 2, 2, 16, 97, 3, 2, 2, 2, 18, 103, 3, 2, 2, 2, 20, 110, 3, 2, 2, 2, 22, 114, 3, 2, 2, 2, 24, 117, 3, 2, 2, 2, 26, 119, 3, 2, 2, 2, 28, 121, 3, 2, 2, 2, 30, 123, 3, 2, 2, 2, 32, 126, 3, 2, 2, 2, 34, 138, 3, 2, 2, 2, 36, 157, 3, 2, 2, 2, 38, 159, 3, 2, 2, 2, 40, 161, 3, 2, 2, 2, 42, 163, 3, 2, 2, 2, 44, 177, 3, 2, 2, 2, 46, 188, 3, 2, 2, 2, 48, 190, 3, 2, 2, 2, 50, 192, 3, 2, 2, 2, 52, 53, 5, 4, 3, 2, 53, 54, 7, 2, 2, 3, 54, 3, 3, 2, 2, 2, 55, 57, 5, 8, 5, 2, 56, 55, 3, 2, 2, 2, 57, 60, 3, 2, 2, 2, 58, 56, 3, 2, 2, 2, 58, 59, 3, 2, 2, 2, 59, 5, 3, 2, 2, 2, 60, 58, 3, 2, 2, 2, 61, 63, 5, 8, 5, 2, 62, 61, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 62, 3, 2, 2, 2, 64, 65, 3, 2, 2, 2, 65, 7, 3, 2, 2, 2, 66, 76, 5, 20, 11, 2, 67, 76, 5, 10, 6, 2, 68, 76, 5, 16, 9, 2, 69, 76, 5, 22, 12, 2, 70, 76, 5, 26, 14, 2, 71, 76, 5, 18, 10, 2, 72, 76, 5, 28, 15, 2, 73, 76, 5, 30, 16, 2, 74, 76, 5, 32, 17, 2, 75, 66, 3, 2, 2, 2, 75, 67, 3, 2, 2, 2, 75, 68, 3, 2, 2, 2, 75, 69, 3, 2, 2, 2, 75, 70, 3, 2, 2, 2, 75, 71, 3, 2, 2, 2, 75, 72, 3, 2, 2, 2, 75, 73, 3, 2, 2, 2, 75, 74, 3, 2, 2, 2, 76, 9, 3, 2, 2, 2, 77, 80, 5, 12, 7, 2, 78, 80, 5, 14, 8, 2, 79, 77, 3, 2, 2, 2, 79, 78, 3, 2, 2, 2, 80, 11, 3, 2, 2, 2, 81, 82, 7, 3, 2, 2, 82, 83, 5, 44, 23, 2, 83, 84, 7, 4, 2, 2, 84, 85, 5, 6, 4, 2, 85, 86, 7, 5, 2, 2, 86, 13, 3, 2, 2, 2, 87, 88, 7, 3, 2, 2, 88, 89, 5, 44, 23, 2, 89, 90, 7, 4, 2, 2, 90, 91, 5, 6, 4, 2, 91, 92, 7, 5, 2, 2, 92, 93, 7, 6, 2, 2, 93, 94, 7, 4, 2, 2, 94, 95, 5, 6, 4, 2, 95, 96, 7, 5, 2, 2, 96, 15, 3, 2, 2, 2, 97, 98, 7, 7, 2, 2, 98, 99, 5, 50, 26, 2, 99, 100, 7, 4, 2, 2, 100, 101, 5, 6, 4, 2, 101, 102, 7, 5, 2, 2, 102, 17, 3, 2, 2, 2, 103, 104, 7, 8, 2, 2, 104, 105, 7, 9, 2, 2, 105, 106, 5, 34, 18, 2, 106, 107, 7, 10, 2, 2, 107, 108, 5, 34, 18, 2, 108, 109, 7, 11, 2, 2, 109, 19, 3, 2, 2, 2, 110, 111, 7, 38, 2, 2, 111, 112, 7, 12, 2, 2, 112, 113, 5, 34, 18, 2, 113, 21, 3, 2, 2, 2, 114, 115, 5, 24, 13, 2, 115, 116, 5, 34, 18, 2, 116, 23, 3, 2, 2, 2, 117, 118, 9, 2, 2, 2, 118, 25, 3, 2, 2, 2, 119, 120, 9, 3, 2, 2, 120, 27, 3, 2, 2, 2, 121, 122, 7, 19, 2, 2, 122, 29, 3, 2, 2, 2, 123, 124, 7, 20, 2, 2, 124, 125, 5, 44, 23, 2, 125, 31, 3, 2, 2, 2, 126, 127, 7, 21, 2, 2, 127, 128, 5, 44, 23, 2, 128, 33, 3, 2, 2, 2, 129, 130, 8, 18, 1, 2, 130, 131, 5, 42, 22, 2, 131, 132, 5, 34, 18, 8, 132, 139, 3, 2, 2, 2, 133, 139, 5, 50, 26, 2, 134, 135, 7, 9, 2, 2, 135, 136, 5, 34, 18, 2, 136, 137, 7, 11, 2, 2, 137, 139, 3, 2, 2, 2, 138, 129, 3, 2, 2, 2, 138, 133, 3, 2, 2, 2, 138, 134, 3, 2, 2, 2, 139, 154, 3, 2, 2, 2, 140, 141, 12, 7, 2, 2, 141, 142, 5, 36, 19, 2, 142, 143, 5, 34, 18, 8, 143, 153, 3, 2, 2, 2, 144, 145, 12, 6, 2, 2, 145, 146, 5, 38, 20, 2, 146, 147, 5, 34, 18, 7, 147, 153, 3, 2, 2, 2, 148, 149, 12, 5, 2, 2, 149, 150, 5, 40, 21, 2, 150, 151, 5, 34, 18, 6, 151, 153, 3, 2, 2, 2, 152, 140, 3, 2, 2, 2, 152, 144, 3, 2, 2, 2, 152, 148, 3, 2, 2, 2, 153, 156, 3, 2, 2, 2, 154, 152, 3, 2, 2, 2, 154, 155, 3, 2, 2, 2, 155, 35, 3, 2, 2, 2, 156, 154, 3, 2, 2, 2, 157, 158, 9, 4, 2, 2, 158, 37, 3, 2, 2, 2, 159, 160, 9, 5, 2, 2, 160, 39, 3, 2, 2, 2, 161, 162, 7, 26, 2, 2, 162, 41, 3, 2, 2, 2, 163, 164, 7, 23, 2, 2, 164, 43, 3, 2, 2, 2, 165, 166, 8, 23, 1, 2, 166, 167, 7, 36, 2, 2, 167, 178, 5, 44, 23, 7, 168, 169, 5, 34, 18, 2, 169, 170, 5, 46, 24, 2, 170, 171, 5, 34, 18, 2, 171, 178, 3, 2, 2, 2, 172, 178, 7, 27, 2, 2, 173, 174, 7, 9, 2, 2, 174, 175, 5, 44, 23, 2, 175, 176, 7, 11, 2, 2, 176, 178, 3, 2, 2, 2, 177, 165, 3, 2, 2, 2, 177, 168, 3, 2, 2, 2, 177, 172, 3, 2, 2, 2, 177, 173, 3, 2, 2, 2, 178, 185, 3, 2, 2, 2, 179, 180, 12, 5, 2, 2, 180, 181, 5, 48, 25, 2, 181, 182, 5, 44, 23, 6, 182, 184, 3, 2, 2, 2, 183, 179, 3, 2, 2, 2, 184, 187, 3, 2, 2, 2, 185, 183, 3, 2, 2, 2, 185, 186, 3, 2, 2, 2, 186, 45, 3, 2, 2, 2, 187, 185, 3, 2, 2, 2, 188, 189, 9, 6, 2, 2, 189, 47, 3, 2, 2, 2, 190, 191, 9, 7, 2, 2, 191, 49, 3, 2, 2, 2, 192, 193, 9, 8, 2, 2, 193, 51, 3, 2, 2, 2, 11, 58, 64, 75, 79, 138, 152, 154, 177, 185] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 42, 205, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 57, 10, 3, 12, 3, 14, 3, 60, 11, 3, 3, 4, 6, 4, 63, 10, 4, 13, 4, 14, 4, 64, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 76, 10, 5, 3, 6, 3, 6, 5, 6, 80, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 5, 9, 112, 10, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 149, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 163, 10, 18, 12, 18, 14, 18, 166, 11, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 188, 10, 23, 3, 23, 3, 23, 3, 23, 3, 23, 7, 23, 194, 10, 23, 12, 23, 14, 23, 197, 11, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 2, 4, 34, 44, 27, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 2, 9, 3, 2, 14, 17, 3, 2, 18, 19, 3, 2, 25, 26, 3, 2, 23, 24, 3, 2, 29, 34, 3, 2, 35, 36, 3, 2, 38, 39, 2, 200, 2, 52, 3, 2, 2, 2, 4, 58, 3, 2, 2, 2, 6, 62, 3, 2, 2, 2, 8, 75, 3, 2, 2, 2, 10, 79, 3, 2, 2, 2, 12, 81, 3, 2, 2, 2, 14, 87, 3, 2, 2, 2, 16, 111, 3, 2, 2, 2, 18, 113, 3, 2, 2, 2, 20, 120, 3, 2, 2, 2, 22, 124, 3, 2, 2, 2, 24, 127, 3, 2, 2, 2, 26, 129, 3, 2, 2, 2, 28, 131, 3, 2, 2, 2, 30, 133, 3, 2, 2, 2, 32, 136, 3, 2, 2, 2, 34, 148, 3, 2, 2, 2, 36, 167, 3, 2, 2, 2, 38, 169, 3, 2, 2, 2, 40, 171, 3, 2, 2, 2, 42, 173, 3, 2, 2, 2, 44, 187, 3, 2, 2, 2, 46, 198, 3, 2, 2, 2, 48, 200, 3, 2, 2, 2, 50, 202, 3, 2, 2, 2, 52, 53, 5, 4, 3, 2, 53, 54, 7, 2, 2, 3, 54, 3, 3, 2, 2, 2, 55, 57, 5, 8, 5, 2, 56, 55, 3, 2, 2, 2, 57, 60, 3, 2, 2, 2, 58, 56, 3, 2, 2, 2, 58, 59, 3, 2, 2, 2, 59, 5, 3, 2, 2, 2, 60, 58, 3, 2, 2, 2, 61, 63, 5, 8, 5, 2, 62, 61, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 62, 3, 2, 2, 2, 64, 65, 3, 2, 2, 2, 65, 7, 3, 2, 2, 2, 66, 76, 5, 20, 11, 2, 67, 76, 5, 10, 6, 2, 68, 76, 5, 16, 9, 2, 69, 76, 5, 22, 12, 2, 70, 76, 5, 26, 14, 2, 71, 76, 5, 18, 10, 2, 72, 76, 5, 28, 15, 2, 73, 76, 5, 30, 16, 2, 74, 76, 5, 32, 17, 2, 75, 66, 3, 2, 2, 2, 75, 67, 3, 2, 2, 2, 75, 68, 3, 2, 2, 2, 75, 69, 3, 2, 2, 2, 75, 70, 3, 2, 2, 2, 75, 71, 3, 2, 2, 2, 75, 72, 3, 2, 2, 2, 75, 73, 3, 2, 2, 2, 75, 74, 3, 2, 2, 2, 76, 9, 3, 2, 2, 2, 77, 80, 5, 12, 7, 2, 78, 80, 5, 14, 8, 2, 79, 77, 3, 2, 2, 2, 79, 78, 3, 2, 2, 2, 80, 11, 3, 2, 2, 2, 81, 82, 7, 3, 2, 2, 82, 83, 5, 44, 23, 2, 83, 84, 7, 4, 2, 2, 84, 85, 5, 6, 4, 2, 85, 86, 7, 5, 2, 2, 86, 13, 3, 2, 2, 2, 87, 88, 7, 3, 2, 2, 88, 89, 5, 44, 23, 2, 89, 90, 7, 4, 2, 2, 90, 91, 5, 6, 4, 2, 91, 92, 7, 5, 2, 2, 92, 93, 7, 6, 2, 2, 93, 94, 7, 4, 2, 2, 94, 95, 5, 6, 4, 2, 95, 96, 7, 5, 2, 2, 96, 15, 3, 2, 2, 2, 97, 98, 7, 7, 2, 2, 98, 99, 5, 50, 26, 2, 99, 100, 7, 4, 2, 2, 100, 101, 5, 6, 4, 2, 101, 102, 7, 5, 2, 2, 102, 112, 3, 2, 2, 2, 103, 104, 7, 8, 2, 2, 104, 105, 7, 38, 2, 2, 105, 106, 7, 7, 2, 2, 106, 107, 5, 50, 26, 2, 107, 108, 7, 4, 2, 2, 108, 109, 5, 6, 4, 2, 109, 110, 7, 5, 2, 2, 110, 112, 3, 2, 2, 2, 111, 97, 3, 2, 2, 2, 111, 103, 3, 2, 2, 2, 112, 17, 3, 2, 2, 2, 113, 114, 7, 9, 2, 2, 114, 115, 7, 10, 2, 2, 115, 116, 5, 34, 18, 2, 116, 117, 7, 11, 2, 2, 117, 118, 5, 34, 18, 2, 118, 119, 7, 12, 2, 2, 119, 19, 3, 2, 2, 2, 120, 121, 7, 39, 2, 2, 121, 122, 7, 13, 2, 2, 122, 123, 5, 34, 18, 2, 123, 21, 3, 2, 2, 2, 124, 125, 5, 24, 13, 2, 125, 126, 5, 34, 18, 2, 126, 23, 3, 2, 2, 2, 127, 128, 9, 2, 2, 2, 128, 25, 3, 2, 2, 2, 129, 130, 9, 3, 2, 2, 130, 27, 3, 2, 2, 2, 131, 132, 7, 20, 2, 2, 132, 29, 3, 2, 2, 2, 133, 134, 7, 21, 2, 2, 134, 135, 5, 44, 23, 2, 135, 31, 3, 2, 2, 2, 136, 137, 7, 22, 2, 2, 137, 138, 5, 44, 23, 2, 138, 33, 3, 2, 2, 2, 139, 140, 8, 18, 1, 2, 140, 141, 5, 42, 22, 2, 141, 142, 5, 34, 18, 8, 142, 149, 3, 2, 2, 2, 143, 149, 5, 50, 26, 2, 144, 145, 7, 10, 2, 2, 145, 146, 5, 34, 18, 2, 146, 147, 7, 12, 2, 2, 147, 149, 3, 2, 2, 2, 148, 139, 3, 2, 2, 2, 148, 143, 3, 2, 2, 2, 148, 144, 3, 2, 2, 2, 149, 164, 3, 2, 2, 2, 150, 151, 12, 7, 2, 2, 151, 152, 5, 36, 19, 2, 152, 153, 5, 34, 18, 8, 153, 163, 3, 2, 2, 2, 154, 155, 12, 6, 2, 2, 155, 156, 5, 38, 20, 2, 156, 157, 5, 34, 18, 7, 157, 163, 3, 2, 2, 2, 158, 159, 12, 5, 2, 2, 159, 160, 5, 40, 21, 2, 160, 161, 5, 34, 18, 6, 161, 163, 3, 2, 2, 2, 162, 150, 3, 2, 2, 2, 162, 154, 3, 2, 2, 2, 162, 158, 3, 2, 2, 2, 163, 166, 3, 2, 2, 2, 164, 162, 3, 2, 2, 2, 164, 165, 3, 2, 2, 2, 165, 35, 3, 2, 2, 2, 166, 164, 3, 2, 2, 2, 167, 168, 9, 4, 2, 2, 168, 37, 3, 2, 2, 2, 169, 170, 9, 5, 2, 2, 170, 39, 3, 2, 2, 2, 171, 172, 7, 27, 2, 2, 172, 41, 3, 2, 2, 2, 173, 174, 7, 24, 2, 2, 174, 43, 3, 2, 2, 2, 175, 176, 8, 23, 1, 2, 176, 177, 7, 37, 2, 2, 177, 188, 5, 44, 23, 7, 178, 179, 5, 34, 18, 2, 179, 180, 5, 46, 24, 2, 180, 181, 5, 34, 18, 2, 181, 188, 3, 2, 2, 2, 182, 188, 7, 28, 2, 2, 183, 184, 7, 10, 2, 2, 184, 185, 5, 44, 23, 2, 185, 186, 7, 12, 2, 2, 186, 188, 3, 2, 2, 2, 187, 175, 3, 2, 2, 2, 187, 178, 3, 2, 2, 2, 187, 182, 3, 2, 2, 2, 187, 183, 3, 2, 2, 2, 188, 195, 3, 2, 2, 2, 189, 190, 12, 5, 2, 2, 190, 191, 5, 48, 25, 2, 191, 192, 5, 44, 23, 6, 192, 194, 3, 2, 2, 2, 193, 189, 3, 2, 2, 2, 194, 197, 3, 2, 2, 2, 195, 193, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196, 45, 3, 2, 2, 2, 197, 195, 3, 2, 2, 2, 198, 199, 9, 6, 2, 2, 199, 47, 3, 2, 2, 2, 200, 201, 9, 7, 2, 2, 201, 49, 3, 2, 2, 2, 202, 203, 9, 8, 2, 2, 203, 51, 3, 2, 2, 2, 12, 58, 64, 75, 79, 111, 148, 162, 164, 187, 195] \ No newline at end of file diff --git a/ChironCore/turtparse/tlang.tokens b/ChironCore/turtparse/tlang.tokens index ee84fda..08759dc 100644 --- a/ChironCore/turtparse/tlang.tokens +++ b/ChironCore/turtparse/tlang.tokens @@ -17,57 +17,59 @@ T__15=16 T__16=17 T__17=18 T__18=19 -PLUS=20 -MINUS=21 -MUL=22 -DIV=23 -MOD=24 -PENCOND=25 -LT=26 -GT=27 -EQ=28 -NEQ=29 -LTE=30 -GTE=31 -AND=32 -OR=33 -NOT=34 -NUM=35 -VAR=36 -NAME=37 -Whitespace=38 -Comment=39 +T__19=20 +PLUS=21 +MINUS=22 +MUL=23 +DIV=24 +MOD=25 +PENCOND=26 +LT=27 +GT=28 +EQ=29 +NEQ=30 +LTE=31 +GTE=32 +AND=33 +OR=34 +NOT=35 +NUM=36 +VAR=37 +NAME=38 +Whitespace=39 +Comment=40 'if'=1 '['=2 ']'=3 'else'=4 'repeat'=5 -'goto'=6 -'('=7 -','=8 -')'=9 -'='=10 -'forward'=11 -'backward'=12 -'left'=13 -'right'=14 -'penup'=15 -'pendown'=16 -'pause'=17 -'assert'=18 -'assume'=19 -'+'=20 -'-'=21 -'*'=22 -'/'=23 -'%'=24 -'pendown?'=25 -'<'=26 -'>'=27 -'=='=28 -'!='=29 -'<='=30 -'>='=31 -'&&'=32 -'||'=33 -'!'=34 +'@unroll'=6 +'goto'=7 +'('=8 +','=9 +')'=10 +'='=11 +'forward'=12 +'backward'=13 +'left'=14 +'right'=15 +'penup'=16 +'pendown'=17 +'pause'=18 +'assert'=19 +'assume'=20 +'+'=21 +'-'=22 +'*'=23 +'/'=24 +'%'=25 +'pendown?'=26 +'<'=27 +'>'=28 +'=='=29 +'!='=30 +'<='=31 +'>='=32 +'&&'=33 +'||'=34 +'!'=35 diff --git a/ChironCore/turtparse/tlangLexer.interp b/ChironCore/turtparse/tlangLexer.interp index 68fc09f..9a991d9 100644 --- a/ChironCore/turtparse/tlangLexer.interp +++ b/ChironCore/turtparse/tlangLexer.interp @@ -5,6 +5,7 @@ null ']' 'else' 'repeat' +'@unroll' 'goto' '(' ',' @@ -61,6 +62,7 @@ null null null null +null PLUS MINUS MUL @@ -102,6 +104,7 @@ T__15 T__16 T__17 T__18 +T__19 PLUS MINUS MUL @@ -131,4 +134,4 @@ mode names: DEFAULT_MODE atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 41, 254, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 6, 36, 220, 10, 36, 13, 36, 14, 36, 221, 3, 37, 3, 37, 3, 37, 7, 37, 227, 10, 37, 12, 37, 14, 37, 230, 11, 37, 3, 38, 6, 38, 233, 10, 38, 13, 38, 14, 38, 234, 3, 39, 6, 39, 238, 10, 39, 13, 39, 14, 39, 239, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 7, 40, 248, 10, 40, 12, 40, 14, 40, 251, 11, 40, 3, 40, 3, 40, 2, 2, 41, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 3, 2, 8, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 258, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 3, 81, 3, 2, 2, 2, 5, 84, 3, 2, 2, 2, 7, 86, 3, 2, 2, 2, 9, 88, 3, 2, 2, 2, 11, 93, 3, 2, 2, 2, 13, 100, 3, 2, 2, 2, 15, 105, 3, 2, 2, 2, 17, 107, 3, 2, 2, 2, 19, 109, 3, 2, 2, 2, 21, 111, 3, 2, 2, 2, 23, 113, 3, 2, 2, 2, 25, 121, 3, 2, 2, 2, 27, 130, 3, 2, 2, 2, 29, 135, 3, 2, 2, 2, 31, 141, 3, 2, 2, 2, 33, 147, 3, 2, 2, 2, 35, 155, 3, 2, 2, 2, 37, 161, 3, 2, 2, 2, 39, 168, 3, 2, 2, 2, 41, 175, 3, 2, 2, 2, 43, 177, 3, 2, 2, 2, 45, 179, 3, 2, 2, 2, 47, 181, 3, 2, 2, 2, 49, 183, 3, 2, 2, 2, 51, 185, 3, 2, 2, 2, 53, 194, 3, 2, 2, 2, 55, 196, 3, 2, 2, 2, 57, 198, 3, 2, 2, 2, 59, 201, 3, 2, 2, 2, 61, 204, 3, 2, 2, 2, 63, 207, 3, 2, 2, 2, 65, 210, 3, 2, 2, 2, 67, 213, 3, 2, 2, 2, 69, 216, 3, 2, 2, 2, 71, 219, 3, 2, 2, 2, 73, 223, 3, 2, 2, 2, 75, 232, 3, 2, 2, 2, 77, 237, 3, 2, 2, 2, 79, 243, 3, 2, 2, 2, 81, 82, 7, 107, 2, 2, 82, 83, 7, 104, 2, 2, 83, 4, 3, 2, 2, 2, 84, 85, 7, 93, 2, 2, 85, 6, 3, 2, 2, 2, 86, 87, 7, 95, 2, 2, 87, 8, 3, 2, 2, 2, 88, 89, 7, 103, 2, 2, 89, 90, 7, 110, 2, 2, 90, 91, 7, 117, 2, 2, 91, 92, 7, 103, 2, 2, 92, 10, 3, 2, 2, 2, 93, 94, 7, 116, 2, 2, 94, 95, 7, 103, 2, 2, 95, 96, 7, 114, 2, 2, 96, 97, 7, 103, 2, 2, 97, 98, 7, 99, 2, 2, 98, 99, 7, 118, 2, 2, 99, 12, 3, 2, 2, 2, 100, 101, 7, 105, 2, 2, 101, 102, 7, 113, 2, 2, 102, 103, 7, 118, 2, 2, 103, 104, 7, 113, 2, 2, 104, 14, 3, 2, 2, 2, 105, 106, 7, 42, 2, 2, 106, 16, 3, 2, 2, 2, 107, 108, 7, 46, 2, 2, 108, 18, 3, 2, 2, 2, 109, 110, 7, 43, 2, 2, 110, 20, 3, 2, 2, 2, 111, 112, 7, 63, 2, 2, 112, 22, 3, 2, 2, 2, 113, 114, 7, 104, 2, 2, 114, 115, 7, 113, 2, 2, 115, 116, 7, 116, 2, 2, 116, 117, 7, 121, 2, 2, 117, 118, 7, 99, 2, 2, 118, 119, 7, 116, 2, 2, 119, 120, 7, 102, 2, 2, 120, 24, 3, 2, 2, 2, 121, 122, 7, 100, 2, 2, 122, 123, 7, 99, 2, 2, 123, 124, 7, 101, 2, 2, 124, 125, 7, 109, 2, 2, 125, 126, 7, 121, 2, 2, 126, 127, 7, 99, 2, 2, 127, 128, 7, 116, 2, 2, 128, 129, 7, 102, 2, 2, 129, 26, 3, 2, 2, 2, 130, 131, 7, 110, 2, 2, 131, 132, 7, 103, 2, 2, 132, 133, 7, 104, 2, 2, 133, 134, 7, 118, 2, 2, 134, 28, 3, 2, 2, 2, 135, 136, 7, 116, 2, 2, 136, 137, 7, 107, 2, 2, 137, 138, 7, 105, 2, 2, 138, 139, 7, 106, 2, 2, 139, 140, 7, 118, 2, 2, 140, 30, 3, 2, 2, 2, 141, 142, 7, 114, 2, 2, 142, 143, 7, 103, 2, 2, 143, 144, 7, 112, 2, 2, 144, 145, 7, 119, 2, 2, 145, 146, 7, 114, 2, 2, 146, 32, 3, 2, 2, 2, 147, 148, 7, 114, 2, 2, 148, 149, 7, 103, 2, 2, 149, 150, 7, 112, 2, 2, 150, 151, 7, 102, 2, 2, 151, 152, 7, 113, 2, 2, 152, 153, 7, 121, 2, 2, 153, 154, 7, 112, 2, 2, 154, 34, 3, 2, 2, 2, 155, 156, 7, 114, 2, 2, 156, 157, 7, 99, 2, 2, 157, 158, 7, 119, 2, 2, 158, 159, 7, 117, 2, 2, 159, 160, 7, 103, 2, 2, 160, 36, 3, 2, 2, 2, 161, 162, 7, 99, 2, 2, 162, 163, 7, 117, 2, 2, 163, 164, 7, 117, 2, 2, 164, 165, 7, 103, 2, 2, 165, 166, 7, 116, 2, 2, 166, 167, 7, 118, 2, 2, 167, 38, 3, 2, 2, 2, 168, 169, 7, 99, 2, 2, 169, 170, 7, 117, 2, 2, 170, 171, 7, 117, 2, 2, 171, 172, 7, 119, 2, 2, 172, 173, 7, 111, 2, 2, 173, 174, 7, 103, 2, 2, 174, 40, 3, 2, 2, 2, 175, 176, 7, 45, 2, 2, 176, 42, 3, 2, 2, 2, 177, 178, 7, 47, 2, 2, 178, 44, 3, 2, 2, 2, 179, 180, 7, 44, 2, 2, 180, 46, 3, 2, 2, 2, 181, 182, 7, 49, 2, 2, 182, 48, 3, 2, 2, 2, 183, 184, 7, 39, 2, 2, 184, 50, 3, 2, 2, 2, 185, 186, 7, 114, 2, 2, 186, 187, 7, 103, 2, 2, 187, 188, 7, 112, 2, 2, 188, 189, 7, 102, 2, 2, 189, 190, 7, 113, 2, 2, 190, 191, 7, 121, 2, 2, 191, 192, 7, 112, 2, 2, 192, 193, 7, 65, 2, 2, 193, 52, 3, 2, 2, 2, 194, 195, 7, 62, 2, 2, 195, 54, 3, 2, 2, 2, 196, 197, 7, 64, 2, 2, 197, 56, 3, 2, 2, 2, 198, 199, 7, 63, 2, 2, 199, 200, 7, 63, 2, 2, 200, 58, 3, 2, 2, 2, 201, 202, 7, 35, 2, 2, 202, 203, 7, 63, 2, 2, 203, 60, 3, 2, 2, 2, 204, 205, 7, 62, 2, 2, 205, 206, 7, 63, 2, 2, 206, 62, 3, 2, 2, 2, 207, 208, 7, 64, 2, 2, 208, 209, 7, 63, 2, 2, 209, 64, 3, 2, 2, 2, 210, 211, 7, 40, 2, 2, 211, 212, 7, 40, 2, 2, 212, 66, 3, 2, 2, 2, 213, 214, 7, 126, 2, 2, 214, 215, 7, 126, 2, 2, 215, 68, 3, 2, 2, 2, 216, 217, 7, 35, 2, 2, 217, 70, 3, 2, 2, 2, 218, 220, 9, 2, 2, 2, 219, 218, 3, 2, 2, 2, 220, 221, 3, 2, 2, 2, 221, 219, 3, 2, 2, 2, 221, 222, 3, 2, 2, 2, 222, 72, 3, 2, 2, 2, 223, 224, 7, 60, 2, 2, 224, 228, 9, 3, 2, 2, 225, 227, 9, 4, 2, 2, 226, 225, 3, 2, 2, 2, 227, 230, 3, 2, 2, 2, 228, 226, 3, 2, 2, 2, 228, 229, 3, 2, 2, 2, 229, 74, 3, 2, 2, 2, 230, 228, 3, 2, 2, 2, 231, 233, 9, 5, 2, 2, 232, 231, 3, 2, 2, 2, 233, 234, 3, 2, 2, 2, 234, 232, 3, 2, 2, 2, 234, 235, 3, 2, 2, 2, 235, 76, 3, 2, 2, 2, 236, 238, 9, 6, 2, 2, 237, 236, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 237, 3, 2, 2, 2, 239, 240, 3, 2, 2, 2, 240, 241, 3, 2, 2, 2, 241, 242, 8, 39, 2, 2, 242, 78, 3, 2, 2, 2, 243, 244, 7, 49, 2, 2, 244, 245, 7, 49, 2, 2, 245, 249, 3, 2, 2, 2, 246, 248, 10, 7, 2, 2, 247, 246, 3, 2, 2, 2, 248, 251, 3, 2, 2, 2, 249, 247, 3, 2, 2, 2, 249, 250, 3, 2, 2, 2, 250, 252, 3, 2, 2, 2, 251, 249, 3, 2, 2, 2, 252, 253, 8, 40, 2, 2, 253, 80, 3, 2, 2, 2, 8, 2, 221, 228, 234, 239, 249, 3, 8, 2, 2] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 42, 264, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 6, 37, 230, 10, 37, 13, 37, 14, 37, 231, 3, 38, 3, 38, 3, 38, 7, 38, 237, 10, 38, 12, 38, 14, 38, 240, 11, 38, 3, 39, 6, 39, 243, 10, 39, 13, 39, 14, 39, 244, 3, 40, 6, 40, 248, 10, 40, 13, 40, 14, 40, 249, 3, 40, 3, 40, 3, 41, 3, 41, 3, 41, 3, 41, 7, 41, 258, 10, 41, 12, 41, 14, 41, 261, 11, 41, 3, 41, 3, 41, 2, 2, 42, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 81, 42, 3, 2, 8, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 268, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 3, 83, 3, 2, 2, 2, 5, 86, 3, 2, 2, 2, 7, 88, 3, 2, 2, 2, 9, 90, 3, 2, 2, 2, 11, 95, 3, 2, 2, 2, 13, 102, 3, 2, 2, 2, 15, 110, 3, 2, 2, 2, 17, 115, 3, 2, 2, 2, 19, 117, 3, 2, 2, 2, 21, 119, 3, 2, 2, 2, 23, 121, 3, 2, 2, 2, 25, 123, 3, 2, 2, 2, 27, 131, 3, 2, 2, 2, 29, 140, 3, 2, 2, 2, 31, 145, 3, 2, 2, 2, 33, 151, 3, 2, 2, 2, 35, 157, 3, 2, 2, 2, 37, 165, 3, 2, 2, 2, 39, 171, 3, 2, 2, 2, 41, 178, 3, 2, 2, 2, 43, 185, 3, 2, 2, 2, 45, 187, 3, 2, 2, 2, 47, 189, 3, 2, 2, 2, 49, 191, 3, 2, 2, 2, 51, 193, 3, 2, 2, 2, 53, 195, 3, 2, 2, 2, 55, 204, 3, 2, 2, 2, 57, 206, 3, 2, 2, 2, 59, 208, 3, 2, 2, 2, 61, 211, 3, 2, 2, 2, 63, 214, 3, 2, 2, 2, 65, 217, 3, 2, 2, 2, 67, 220, 3, 2, 2, 2, 69, 223, 3, 2, 2, 2, 71, 226, 3, 2, 2, 2, 73, 229, 3, 2, 2, 2, 75, 233, 3, 2, 2, 2, 77, 242, 3, 2, 2, 2, 79, 247, 3, 2, 2, 2, 81, 253, 3, 2, 2, 2, 83, 84, 7, 107, 2, 2, 84, 85, 7, 104, 2, 2, 85, 4, 3, 2, 2, 2, 86, 87, 7, 93, 2, 2, 87, 6, 3, 2, 2, 2, 88, 89, 7, 95, 2, 2, 89, 8, 3, 2, 2, 2, 90, 91, 7, 103, 2, 2, 91, 92, 7, 110, 2, 2, 92, 93, 7, 117, 2, 2, 93, 94, 7, 103, 2, 2, 94, 10, 3, 2, 2, 2, 95, 96, 7, 116, 2, 2, 96, 97, 7, 103, 2, 2, 97, 98, 7, 114, 2, 2, 98, 99, 7, 103, 2, 2, 99, 100, 7, 99, 2, 2, 100, 101, 7, 118, 2, 2, 101, 12, 3, 2, 2, 2, 102, 103, 7, 66, 2, 2, 103, 104, 7, 119, 2, 2, 104, 105, 7, 112, 2, 2, 105, 106, 7, 116, 2, 2, 106, 107, 7, 113, 2, 2, 107, 108, 7, 110, 2, 2, 108, 109, 7, 110, 2, 2, 109, 14, 3, 2, 2, 2, 110, 111, 7, 105, 2, 2, 111, 112, 7, 113, 2, 2, 112, 113, 7, 118, 2, 2, 113, 114, 7, 113, 2, 2, 114, 16, 3, 2, 2, 2, 115, 116, 7, 42, 2, 2, 116, 18, 3, 2, 2, 2, 117, 118, 7, 46, 2, 2, 118, 20, 3, 2, 2, 2, 119, 120, 7, 43, 2, 2, 120, 22, 3, 2, 2, 2, 121, 122, 7, 63, 2, 2, 122, 24, 3, 2, 2, 2, 123, 124, 7, 104, 2, 2, 124, 125, 7, 113, 2, 2, 125, 126, 7, 116, 2, 2, 126, 127, 7, 121, 2, 2, 127, 128, 7, 99, 2, 2, 128, 129, 7, 116, 2, 2, 129, 130, 7, 102, 2, 2, 130, 26, 3, 2, 2, 2, 131, 132, 7, 100, 2, 2, 132, 133, 7, 99, 2, 2, 133, 134, 7, 101, 2, 2, 134, 135, 7, 109, 2, 2, 135, 136, 7, 121, 2, 2, 136, 137, 7, 99, 2, 2, 137, 138, 7, 116, 2, 2, 138, 139, 7, 102, 2, 2, 139, 28, 3, 2, 2, 2, 140, 141, 7, 110, 2, 2, 141, 142, 7, 103, 2, 2, 142, 143, 7, 104, 2, 2, 143, 144, 7, 118, 2, 2, 144, 30, 3, 2, 2, 2, 145, 146, 7, 116, 2, 2, 146, 147, 7, 107, 2, 2, 147, 148, 7, 105, 2, 2, 148, 149, 7, 106, 2, 2, 149, 150, 7, 118, 2, 2, 150, 32, 3, 2, 2, 2, 151, 152, 7, 114, 2, 2, 152, 153, 7, 103, 2, 2, 153, 154, 7, 112, 2, 2, 154, 155, 7, 119, 2, 2, 155, 156, 7, 114, 2, 2, 156, 34, 3, 2, 2, 2, 157, 158, 7, 114, 2, 2, 158, 159, 7, 103, 2, 2, 159, 160, 7, 112, 2, 2, 160, 161, 7, 102, 2, 2, 161, 162, 7, 113, 2, 2, 162, 163, 7, 121, 2, 2, 163, 164, 7, 112, 2, 2, 164, 36, 3, 2, 2, 2, 165, 166, 7, 114, 2, 2, 166, 167, 7, 99, 2, 2, 167, 168, 7, 119, 2, 2, 168, 169, 7, 117, 2, 2, 169, 170, 7, 103, 2, 2, 170, 38, 3, 2, 2, 2, 171, 172, 7, 99, 2, 2, 172, 173, 7, 117, 2, 2, 173, 174, 7, 117, 2, 2, 174, 175, 7, 103, 2, 2, 175, 176, 7, 116, 2, 2, 176, 177, 7, 118, 2, 2, 177, 40, 3, 2, 2, 2, 178, 179, 7, 99, 2, 2, 179, 180, 7, 117, 2, 2, 180, 181, 7, 117, 2, 2, 181, 182, 7, 119, 2, 2, 182, 183, 7, 111, 2, 2, 183, 184, 7, 103, 2, 2, 184, 42, 3, 2, 2, 2, 185, 186, 7, 45, 2, 2, 186, 44, 3, 2, 2, 2, 187, 188, 7, 47, 2, 2, 188, 46, 3, 2, 2, 2, 189, 190, 7, 44, 2, 2, 190, 48, 3, 2, 2, 2, 191, 192, 7, 49, 2, 2, 192, 50, 3, 2, 2, 2, 193, 194, 7, 39, 2, 2, 194, 52, 3, 2, 2, 2, 195, 196, 7, 114, 2, 2, 196, 197, 7, 103, 2, 2, 197, 198, 7, 112, 2, 2, 198, 199, 7, 102, 2, 2, 199, 200, 7, 113, 2, 2, 200, 201, 7, 121, 2, 2, 201, 202, 7, 112, 2, 2, 202, 203, 7, 65, 2, 2, 203, 54, 3, 2, 2, 2, 204, 205, 7, 62, 2, 2, 205, 56, 3, 2, 2, 2, 206, 207, 7, 64, 2, 2, 207, 58, 3, 2, 2, 2, 208, 209, 7, 63, 2, 2, 209, 210, 7, 63, 2, 2, 210, 60, 3, 2, 2, 2, 211, 212, 7, 35, 2, 2, 212, 213, 7, 63, 2, 2, 213, 62, 3, 2, 2, 2, 214, 215, 7, 62, 2, 2, 215, 216, 7, 63, 2, 2, 216, 64, 3, 2, 2, 2, 217, 218, 7, 64, 2, 2, 218, 219, 7, 63, 2, 2, 219, 66, 3, 2, 2, 2, 220, 221, 7, 40, 2, 2, 221, 222, 7, 40, 2, 2, 222, 68, 3, 2, 2, 2, 223, 224, 7, 126, 2, 2, 224, 225, 7, 126, 2, 2, 225, 70, 3, 2, 2, 2, 226, 227, 7, 35, 2, 2, 227, 72, 3, 2, 2, 2, 228, 230, 9, 2, 2, 2, 229, 228, 3, 2, 2, 2, 230, 231, 3, 2, 2, 2, 231, 229, 3, 2, 2, 2, 231, 232, 3, 2, 2, 2, 232, 74, 3, 2, 2, 2, 233, 234, 7, 60, 2, 2, 234, 238, 9, 3, 2, 2, 235, 237, 9, 4, 2, 2, 236, 235, 3, 2, 2, 2, 237, 240, 3, 2, 2, 2, 238, 236, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 76, 3, 2, 2, 2, 240, 238, 3, 2, 2, 2, 241, 243, 9, 5, 2, 2, 242, 241, 3, 2, 2, 2, 243, 244, 3, 2, 2, 2, 244, 242, 3, 2, 2, 2, 244, 245, 3, 2, 2, 2, 245, 78, 3, 2, 2, 2, 246, 248, 9, 6, 2, 2, 247, 246, 3, 2, 2, 2, 248, 249, 3, 2, 2, 2, 249, 247, 3, 2, 2, 2, 249, 250, 3, 2, 2, 2, 250, 251, 3, 2, 2, 2, 251, 252, 8, 40, 2, 2, 252, 80, 3, 2, 2, 2, 253, 254, 7, 49, 2, 2, 254, 255, 7, 49, 2, 2, 255, 259, 3, 2, 2, 2, 256, 258, 10, 7, 2, 2, 257, 256, 3, 2, 2, 2, 258, 261, 3, 2, 2, 2, 259, 257, 3, 2, 2, 2, 259, 260, 3, 2, 2, 2, 260, 262, 3, 2, 2, 2, 261, 259, 3, 2, 2, 2, 262, 263, 8, 41, 2, 2, 263, 82, 3, 2, 2, 2, 8, 2, 231, 238, 244, 249, 259, 3, 8, 2, 2] \ No newline at end of file diff --git a/ChironCore/turtparse/tlangLexer.py b/ChironCore/turtparse/tlangLexer.py index 26f3011..900a5ae 100644 --- a/ChironCore/turtparse/tlangLexer.py +++ b/ChironCore/turtparse/tlangLexer.py @@ -8,106 +8,110 @@ def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2)") - buf.write("\u00fe\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2*") + buf.write("\u0108\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") buf.write("\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r") buf.write("\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23") buf.write("\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30") buf.write("\4\31\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36") buf.write("\t\36\4\37\t\37\4 \t \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%") - buf.write("\4&\t&\4\'\t\'\4(\t(\3\2\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3") - buf.write("\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7") - buf.write("\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\f") - buf.write("\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3") - buf.write("\r\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3") - buf.write("\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21") - buf.write("\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\23") - buf.write("\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24") - buf.write("\3\24\3\24\3\25\3\25\3\26\3\26\3\27\3\27\3\30\3\30\3\31") - buf.write("\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\33") - buf.write("\3\33\3\34\3\34\3\35\3\35\3\35\3\36\3\36\3\36\3\37\3\37") - buf.write("\3\37\3 \3 \3 \3!\3!\3!\3\"\3\"\3\"\3#\3#\3$\6$\u00dc") - buf.write("\n$\r$\16$\u00dd\3%\3%\3%\7%\u00e3\n%\f%\16%\u00e6\13") - buf.write("%\3&\6&\u00e9\n&\r&\16&\u00ea\3\'\6\'\u00ee\n\'\r\'\16") - buf.write("\'\u00ef\3\'\3\'\3(\3(\3(\3(\7(\u00f8\n(\f(\16(\u00fb") - buf.write("\13(\3(\3(\2\2)\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23") - buf.write("\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25") - buf.write(")\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A") - buf.write("\"C#E$G%I&K\'M(O)\3\2\b\3\2\62;\5\2C\\aac|\5\2\62;C\\") - buf.write("c|\4\2C\\c|\5\2\13\f\17\17\"\"\4\2\f\f\17\17\2\u0102\2") - buf.write("\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3") - buf.write("\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2") - buf.write("\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2") - buf.write("\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%") - buf.write("\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2") - buf.write("\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67") - buf.write("\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2") - buf.write("A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2") - buf.write("\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\3Q\3\2\2\2\5T\3\2\2") - buf.write("\2\7V\3\2\2\2\tX\3\2\2\2\13]\3\2\2\2\rd\3\2\2\2\17i\3") - buf.write("\2\2\2\21k\3\2\2\2\23m\3\2\2\2\25o\3\2\2\2\27q\3\2\2\2") - buf.write("\31y\3\2\2\2\33\u0082\3\2\2\2\35\u0087\3\2\2\2\37\u008d") - buf.write("\3\2\2\2!\u0093\3\2\2\2#\u009b\3\2\2\2%\u00a1\3\2\2\2") - buf.write("\'\u00a8\3\2\2\2)\u00af\3\2\2\2+\u00b1\3\2\2\2-\u00b3") - buf.write("\3\2\2\2/\u00b5\3\2\2\2\61\u00b7\3\2\2\2\63\u00b9\3\2") - buf.write("\2\2\65\u00c2\3\2\2\2\67\u00c4\3\2\2\29\u00c6\3\2\2\2") - buf.write(";\u00c9\3\2\2\2=\u00cc\3\2\2\2?\u00cf\3\2\2\2A\u00d2\3") - buf.write("\2\2\2C\u00d5\3\2\2\2E\u00d8\3\2\2\2G\u00db\3\2\2\2I\u00df") - buf.write("\3\2\2\2K\u00e8\3\2\2\2M\u00ed\3\2\2\2O\u00f3\3\2\2\2") - buf.write("QR\7k\2\2RS\7h\2\2S\4\3\2\2\2TU\7]\2\2U\6\3\2\2\2VW\7") - buf.write("_\2\2W\b\3\2\2\2XY\7g\2\2YZ\7n\2\2Z[\7u\2\2[\\\7g\2\2") - buf.write("\\\n\3\2\2\2]^\7t\2\2^_\7g\2\2_`\7r\2\2`a\7g\2\2ab\7c") - buf.write("\2\2bc\7v\2\2c\f\3\2\2\2de\7i\2\2ef\7q\2\2fg\7v\2\2gh") - buf.write("\7q\2\2h\16\3\2\2\2ij\7*\2\2j\20\3\2\2\2kl\7.\2\2l\22") - buf.write("\3\2\2\2mn\7+\2\2n\24\3\2\2\2op\7?\2\2p\26\3\2\2\2qr\7") - buf.write("h\2\2rs\7q\2\2st\7t\2\2tu\7y\2\2uv\7c\2\2vw\7t\2\2wx\7") - buf.write("f\2\2x\30\3\2\2\2yz\7d\2\2z{\7c\2\2{|\7e\2\2|}\7m\2\2") - buf.write("}~\7y\2\2~\177\7c\2\2\177\u0080\7t\2\2\u0080\u0081\7f") - buf.write("\2\2\u0081\32\3\2\2\2\u0082\u0083\7n\2\2\u0083\u0084\7") - buf.write("g\2\2\u0084\u0085\7h\2\2\u0085\u0086\7v\2\2\u0086\34\3") - buf.write("\2\2\2\u0087\u0088\7t\2\2\u0088\u0089\7k\2\2\u0089\u008a") - buf.write("\7i\2\2\u008a\u008b\7j\2\2\u008b\u008c\7v\2\2\u008c\36") - buf.write("\3\2\2\2\u008d\u008e\7r\2\2\u008e\u008f\7g\2\2\u008f\u0090") - buf.write("\7p\2\2\u0090\u0091\7w\2\2\u0091\u0092\7r\2\2\u0092 \3") - buf.write("\2\2\2\u0093\u0094\7r\2\2\u0094\u0095\7g\2\2\u0095\u0096") - buf.write("\7p\2\2\u0096\u0097\7f\2\2\u0097\u0098\7q\2\2\u0098\u0099") - buf.write("\7y\2\2\u0099\u009a\7p\2\2\u009a\"\3\2\2\2\u009b\u009c") - buf.write("\7r\2\2\u009c\u009d\7c\2\2\u009d\u009e\7w\2\2\u009e\u009f") - buf.write("\7u\2\2\u009f\u00a0\7g\2\2\u00a0$\3\2\2\2\u00a1\u00a2") - buf.write("\7c\2\2\u00a2\u00a3\7u\2\2\u00a3\u00a4\7u\2\2\u00a4\u00a5") - buf.write("\7g\2\2\u00a5\u00a6\7t\2\2\u00a6\u00a7\7v\2\2\u00a7&\3") - buf.write("\2\2\2\u00a8\u00a9\7c\2\2\u00a9\u00aa\7u\2\2\u00aa\u00ab") - buf.write("\7u\2\2\u00ab\u00ac\7w\2\2\u00ac\u00ad\7o\2\2\u00ad\u00ae") - buf.write("\7g\2\2\u00ae(\3\2\2\2\u00af\u00b0\7-\2\2\u00b0*\3\2\2") - buf.write("\2\u00b1\u00b2\7/\2\2\u00b2,\3\2\2\2\u00b3\u00b4\7,\2") - buf.write("\2\u00b4.\3\2\2\2\u00b5\u00b6\7\61\2\2\u00b6\60\3\2\2") - buf.write("\2\u00b7\u00b8\7\'\2\2\u00b8\62\3\2\2\2\u00b9\u00ba\7") - buf.write("r\2\2\u00ba\u00bb\7g\2\2\u00bb\u00bc\7p\2\2\u00bc\u00bd") - buf.write("\7f\2\2\u00bd\u00be\7q\2\2\u00be\u00bf\7y\2\2\u00bf\u00c0") - buf.write("\7p\2\2\u00c0\u00c1\7A\2\2\u00c1\64\3\2\2\2\u00c2\u00c3") - buf.write("\7>\2\2\u00c3\66\3\2\2\2\u00c4\u00c5\7@\2\2\u00c58\3\2") - buf.write("\2\2\u00c6\u00c7\7?\2\2\u00c7\u00c8\7?\2\2\u00c8:\3\2") - buf.write("\2\2\u00c9\u00ca\7#\2\2\u00ca\u00cb\7?\2\2\u00cb<\3\2") - buf.write("\2\2\u00cc\u00cd\7>\2\2\u00cd\u00ce\7?\2\2\u00ce>\3\2") - buf.write("\2\2\u00cf\u00d0\7@\2\2\u00d0\u00d1\7?\2\2\u00d1@\3\2") - buf.write("\2\2\u00d2\u00d3\7(\2\2\u00d3\u00d4\7(\2\2\u00d4B\3\2") - buf.write("\2\2\u00d5\u00d6\7~\2\2\u00d6\u00d7\7~\2\2\u00d7D\3\2") - buf.write("\2\2\u00d8\u00d9\7#\2\2\u00d9F\3\2\2\2\u00da\u00dc\t\2") - buf.write("\2\2\u00db\u00da\3\2\2\2\u00dc\u00dd\3\2\2\2\u00dd\u00db") - buf.write("\3\2\2\2\u00dd\u00de\3\2\2\2\u00deH\3\2\2\2\u00df\u00e0") - buf.write("\7<\2\2\u00e0\u00e4\t\3\2\2\u00e1\u00e3\t\4\2\2\u00e2") - buf.write("\u00e1\3\2\2\2\u00e3\u00e6\3\2\2\2\u00e4\u00e2\3\2\2\2") - buf.write("\u00e4\u00e5\3\2\2\2\u00e5J\3\2\2\2\u00e6\u00e4\3\2\2") - buf.write("\2\u00e7\u00e9\t\5\2\2\u00e8\u00e7\3\2\2\2\u00e9\u00ea") - buf.write("\3\2\2\2\u00ea\u00e8\3\2\2\2\u00ea\u00eb\3\2\2\2\u00eb") - buf.write("L\3\2\2\2\u00ec\u00ee\t\6\2\2\u00ed\u00ec\3\2\2\2\u00ee") - buf.write("\u00ef\3\2\2\2\u00ef\u00ed\3\2\2\2\u00ef\u00f0\3\2\2\2") - buf.write("\u00f0\u00f1\3\2\2\2\u00f1\u00f2\b\'\2\2\u00f2N\3\2\2") - buf.write("\2\u00f3\u00f4\7\61\2\2\u00f4\u00f5\7\61\2\2\u00f5\u00f9") - buf.write("\3\2\2\2\u00f6\u00f8\n\7\2\2\u00f7\u00f6\3\2\2\2\u00f8") - buf.write("\u00fb\3\2\2\2\u00f9\u00f7\3\2\2\2\u00f9\u00fa\3\2\2\2") - buf.write("\u00fa\u00fc\3\2\2\2\u00fb\u00f9\3\2\2\2\u00fc\u00fd\b") - buf.write("(\2\2\u00fdP\3\2\2\2\b\2\u00dd\u00e4\u00ea\u00ef\u00f9") + buf.write("\4&\t&\4\'\t\'\4(\t(\4)\t)\3\2\3\2\3\2\3\3\3\3\3\4\3\4") + buf.write("\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3") + buf.write("\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\t\3\t") + buf.write("\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r") + buf.write("\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17") + buf.write("\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21") + buf.write("\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22") + buf.write("\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24") + buf.write("\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25") + buf.write("\3\26\3\26\3\27\3\27\3\30\3\30\3\31\3\31\3\32\3\32\3\33") + buf.write("\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\35") + buf.write("\3\35\3\36\3\36\3\36\3\37\3\37\3\37\3 \3 \3 \3!\3!\3!") + buf.write("\3\"\3\"\3\"\3#\3#\3#\3$\3$\3%\6%\u00e6\n%\r%\16%\u00e7") + buf.write("\3&\3&\3&\7&\u00ed\n&\f&\16&\u00f0\13&\3\'\6\'\u00f3\n") + buf.write("\'\r\'\16\'\u00f4\3(\6(\u00f8\n(\r(\16(\u00f9\3(\3(\3") + buf.write(")\3)\3)\3)\7)\u0102\n)\f)\16)\u0105\13)\3)\3)\2\2*\3\3") + buf.write("\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16") + buf.write("\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61") + buf.write("\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*") + buf.write("\3\2\b\3\2\62;\5\2C\\aac|\5\2\62;C\\c|\4\2C\\c|\5\2\13") + buf.write("\f\17\17\"\"\4\2\f\f\17\17\2\u010c\2\3\3\2\2\2\2\5\3\2") + buf.write("\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2") + buf.write("\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2") + buf.write("\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37") + buf.write("\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2") + buf.write("\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2") + buf.write("\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2") + buf.write("\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2") + buf.write("\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2") + buf.write("\2\2\2O\3\2\2\2\2Q\3\2\2\2\3S\3\2\2\2\5V\3\2\2\2\7X\3") + buf.write("\2\2\2\tZ\3\2\2\2\13_\3\2\2\2\rf\3\2\2\2\17n\3\2\2\2\21") + buf.write("s\3\2\2\2\23u\3\2\2\2\25w\3\2\2\2\27y\3\2\2\2\31{\3\2") + buf.write("\2\2\33\u0083\3\2\2\2\35\u008c\3\2\2\2\37\u0091\3\2\2") + buf.write("\2!\u0097\3\2\2\2#\u009d\3\2\2\2%\u00a5\3\2\2\2\'\u00ab") + buf.write("\3\2\2\2)\u00b2\3\2\2\2+\u00b9\3\2\2\2-\u00bb\3\2\2\2") + buf.write("/\u00bd\3\2\2\2\61\u00bf\3\2\2\2\63\u00c1\3\2\2\2\65\u00c3") + buf.write("\3\2\2\2\67\u00cc\3\2\2\29\u00ce\3\2\2\2;\u00d0\3\2\2") + buf.write("\2=\u00d3\3\2\2\2?\u00d6\3\2\2\2A\u00d9\3\2\2\2C\u00dc") + buf.write("\3\2\2\2E\u00df\3\2\2\2G\u00e2\3\2\2\2I\u00e5\3\2\2\2") + buf.write("K\u00e9\3\2\2\2M\u00f2\3\2\2\2O\u00f7\3\2\2\2Q\u00fd\3") + buf.write("\2\2\2ST\7k\2\2TU\7h\2\2U\4\3\2\2\2VW\7]\2\2W\6\3\2\2") + buf.write("\2XY\7_\2\2Y\b\3\2\2\2Z[\7g\2\2[\\\7n\2\2\\]\7u\2\2]^") + buf.write("\7g\2\2^\n\3\2\2\2_`\7t\2\2`a\7g\2\2ab\7r\2\2bc\7g\2\2") + buf.write("cd\7c\2\2de\7v\2\2e\f\3\2\2\2fg\7B\2\2gh\7w\2\2hi\7p\2") + buf.write("\2ij\7t\2\2jk\7q\2\2kl\7n\2\2lm\7n\2\2m\16\3\2\2\2no\7") + buf.write("i\2\2op\7q\2\2pq\7v\2\2qr\7q\2\2r\20\3\2\2\2st\7*\2\2") + buf.write("t\22\3\2\2\2uv\7.\2\2v\24\3\2\2\2wx\7+\2\2x\26\3\2\2\2") + buf.write("yz\7?\2\2z\30\3\2\2\2{|\7h\2\2|}\7q\2\2}~\7t\2\2~\177") + buf.write("\7y\2\2\177\u0080\7c\2\2\u0080\u0081\7t\2\2\u0081\u0082") + buf.write("\7f\2\2\u0082\32\3\2\2\2\u0083\u0084\7d\2\2\u0084\u0085") + buf.write("\7c\2\2\u0085\u0086\7e\2\2\u0086\u0087\7m\2\2\u0087\u0088") + buf.write("\7y\2\2\u0088\u0089\7c\2\2\u0089\u008a\7t\2\2\u008a\u008b") + buf.write("\7f\2\2\u008b\34\3\2\2\2\u008c\u008d\7n\2\2\u008d\u008e") + buf.write("\7g\2\2\u008e\u008f\7h\2\2\u008f\u0090\7v\2\2\u0090\36") + buf.write("\3\2\2\2\u0091\u0092\7t\2\2\u0092\u0093\7k\2\2\u0093\u0094") + buf.write("\7i\2\2\u0094\u0095\7j\2\2\u0095\u0096\7v\2\2\u0096 \3") + buf.write("\2\2\2\u0097\u0098\7r\2\2\u0098\u0099\7g\2\2\u0099\u009a") + buf.write("\7p\2\2\u009a\u009b\7w\2\2\u009b\u009c\7r\2\2\u009c\"") + buf.write("\3\2\2\2\u009d\u009e\7r\2\2\u009e\u009f\7g\2\2\u009f\u00a0") + buf.write("\7p\2\2\u00a0\u00a1\7f\2\2\u00a1\u00a2\7q\2\2\u00a2\u00a3") + buf.write("\7y\2\2\u00a3\u00a4\7p\2\2\u00a4$\3\2\2\2\u00a5\u00a6") + buf.write("\7r\2\2\u00a6\u00a7\7c\2\2\u00a7\u00a8\7w\2\2\u00a8\u00a9") + buf.write("\7u\2\2\u00a9\u00aa\7g\2\2\u00aa&\3\2\2\2\u00ab\u00ac") + buf.write("\7c\2\2\u00ac\u00ad\7u\2\2\u00ad\u00ae\7u\2\2\u00ae\u00af") + buf.write("\7g\2\2\u00af\u00b0\7t\2\2\u00b0\u00b1\7v\2\2\u00b1(\3") + buf.write("\2\2\2\u00b2\u00b3\7c\2\2\u00b3\u00b4\7u\2\2\u00b4\u00b5") + buf.write("\7u\2\2\u00b5\u00b6\7w\2\2\u00b6\u00b7\7o\2\2\u00b7\u00b8") + buf.write("\7g\2\2\u00b8*\3\2\2\2\u00b9\u00ba\7-\2\2\u00ba,\3\2\2") + buf.write("\2\u00bb\u00bc\7/\2\2\u00bc.\3\2\2\2\u00bd\u00be\7,\2") + buf.write("\2\u00be\60\3\2\2\2\u00bf\u00c0\7\61\2\2\u00c0\62\3\2") + buf.write("\2\2\u00c1\u00c2\7\'\2\2\u00c2\64\3\2\2\2\u00c3\u00c4") + buf.write("\7r\2\2\u00c4\u00c5\7g\2\2\u00c5\u00c6\7p\2\2\u00c6\u00c7") + buf.write("\7f\2\2\u00c7\u00c8\7q\2\2\u00c8\u00c9\7y\2\2\u00c9\u00ca") + buf.write("\7p\2\2\u00ca\u00cb\7A\2\2\u00cb\66\3\2\2\2\u00cc\u00cd") + buf.write("\7>\2\2\u00cd8\3\2\2\2\u00ce\u00cf\7@\2\2\u00cf:\3\2\2") + buf.write("\2\u00d0\u00d1\7?\2\2\u00d1\u00d2\7?\2\2\u00d2<\3\2\2") + buf.write("\2\u00d3\u00d4\7#\2\2\u00d4\u00d5\7?\2\2\u00d5>\3\2\2") + buf.write("\2\u00d6\u00d7\7>\2\2\u00d7\u00d8\7?\2\2\u00d8@\3\2\2") + buf.write("\2\u00d9\u00da\7@\2\2\u00da\u00db\7?\2\2\u00dbB\3\2\2") + buf.write("\2\u00dc\u00dd\7(\2\2\u00dd\u00de\7(\2\2\u00deD\3\2\2") + buf.write("\2\u00df\u00e0\7~\2\2\u00e0\u00e1\7~\2\2\u00e1F\3\2\2") + buf.write("\2\u00e2\u00e3\7#\2\2\u00e3H\3\2\2\2\u00e4\u00e6\t\2\2") + buf.write("\2\u00e5\u00e4\3\2\2\2\u00e6\u00e7\3\2\2\2\u00e7\u00e5") + buf.write("\3\2\2\2\u00e7\u00e8\3\2\2\2\u00e8J\3\2\2\2\u00e9\u00ea") + buf.write("\7<\2\2\u00ea\u00ee\t\3\2\2\u00eb\u00ed\t\4\2\2\u00ec") + buf.write("\u00eb\3\2\2\2\u00ed\u00f0\3\2\2\2\u00ee\u00ec\3\2\2\2") + buf.write("\u00ee\u00ef\3\2\2\2\u00efL\3\2\2\2\u00f0\u00ee\3\2\2") + buf.write("\2\u00f1\u00f3\t\5\2\2\u00f2\u00f1\3\2\2\2\u00f3\u00f4") + buf.write("\3\2\2\2\u00f4\u00f2\3\2\2\2\u00f4\u00f5\3\2\2\2\u00f5") + buf.write("N\3\2\2\2\u00f6\u00f8\t\6\2\2\u00f7\u00f6\3\2\2\2\u00f8") + buf.write("\u00f9\3\2\2\2\u00f9\u00f7\3\2\2\2\u00f9\u00fa\3\2\2\2") + buf.write("\u00fa\u00fb\3\2\2\2\u00fb\u00fc\b(\2\2\u00fcP\3\2\2\2") + buf.write("\u00fd\u00fe\7\61\2\2\u00fe\u00ff\7\61\2\2\u00ff\u0103") + buf.write("\3\2\2\2\u0100\u0102\n\7\2\2\u0101\u0100\3\2\2\2\u0102") + buf.write("\u0105\3\2\2\2\u0103\u0101\3\2\2\2\u0103\u0104\3\2\2\2") + buf.write("\u0104\u0106\3\2\2\2\u0105\u0103\3\2\2\2\u0106\u0107\b") + buf.write(")\2\2\u0107R\3\2\2\2\b\2\u00e7\u00ee\u00f4\u00f9\u0103") buf.write("\3\b\2\2") return buf.getvalue() @@ -137,37 +141,38 @@ class tlangLexer(Lexer): T__16 = 17 T__17 = 18 T__18 = 19 - PLUS = 20 - MINUS = 21 - MUL = 22 - DIV = 23 - MOD = 24 - PENCOND = 25 - LT = 26 - GT = 27 - EQ = 28 - NEQ = 29 - LTE = 30 - GTE = 31 - AND = 32 - OR = 33 - NOT = 34 - NUM = 35 - VAR = 36 - NAME = 37 - Whitespace = 38 - Comment = 39 + T__19 = 20 + PLUS = 21 + MINUS = 22 + MUL = 23 + DIV = 24 + MOD = 25 + PENCOND = 26 + LT = 27 + GT = 28 + EQ = 29 + NEQ = 30 + LTE = 31 + GTE = 32 + AND = 33 + OR = 34 + NOT = 35 + NUM = 36 + VAR = 37 + NAME = 38 + Whitespace = 39 + Comment = 40 channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] modeNames = [ "DEFAULT_MODE" ] literalNames = [ "", - "'if'", "'['", "']'", "'else'", "'repeat'", "'goto'", "'('", - "','", "')'", "'='", "'forward'", "'backward'", "'left'", "'right'", - "'penup'", "'pendown'", "'pause'", "'assert'", "'assume'", "'+'", - "'-'", "'*'", "'/'", "'%'", "'pendown?'", "'<'", "'>'", "'=='", - "'!='", "'<='", "'>='", "'&&'", "'||'", "'!'" ] + "'if'", "'['", "']'", "'else'", "'repeat'", "'@unroll'", "'goto'", + "'('", "','", "')'", "'='", "'forward'", "'backward'", "'left'", + "'right'", "'penup'", "'pendown'", "'pause'", "'assert'", "'assume'", + "'+'", "'-'", "'*'", "'/'", "'%'", "'pendown?'", "'<'", "'>'", + "'=='", "'!='", "'<='", "'>='", "'&&'", "'||'", "'!'" ] symbolicNames = [ "", "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", @@ -176,10 +181,10 @@ class tlangLexer(Lexer): ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", - "T__14", "T__15", "T__16", "T__17", "T__18", "PLUS", "MINUS", - "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", "EQ", "NEQ", - "LTE", "GTE", "AND", "OR", "NOT", "NUM", "VAR", "NAME", - "Whitespace", "Comment" ] + "T__14", "T__15", "T__16", "T__17", "T__18", "T__19", + "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", + "GT", "EQ", "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", + "VAR", "NAME", "Whitespace", "Comment" ] grammarFileName = "tlang.g4" diff --git a/ChironCore/turtparse/tlangLexer.tokens b/ChironCore/turtparse/tlangLexer.tokens index ee84fda..08759dc 100644 --- a/ChironCore/turtparse/tlangLexer.tokens +++ b/ChironCore/turtparse/tlangLexer.tokens @@ -17,57 +17,59 @@ T__15=16 T__16=17 T__17=18 T__18=19 -PLUS=20 -MINUS=21 -MUL=22 -DIV=23 -MOD=24 -PENCOND=25 -LT=26 -GT=27 -EQ=28 -NEQ=29 -LTE=30 -GTE=31 -AND=32 -OR=33 -NOT=34 -NUM=35 -VAR=36 -NAME=37 -Whitespace=38 -Comment=39 +T__19=20 +PLUS=21 +MINUS=22 +MUL=23 +DIV=24 +MOD=25 +PENCOND=26 +LT=27 +GT=28 +EQ=29 +NEQ=30 +LTE=31 +GTE=32 +AND=33 +OR=34 +NOT=35 +NUM=36 +VAR=37 +NAME=38 +Whitespace=39 +Comment=40 'if'=1 '['=2 ']'=3 'else'=4 'repeat'=5 -'goto'=6 -'('=7 -','=8 -')'=9 -'='=10 -'forward'=11 -'backward'=12 -'left'=13 -'right'=14 -'penup'=15 -'pendown'=16 -'pause'=17 -'assert'=18 -'assume'=19 -'+'=20 -'-'=21 -'*'=22 -'/'=23 -'%'=24 -'pendown?'=25 -'<'=26 -'>'=27 -'=='=28 -'!='=29 -'<='=30 -'>='=31 -'&&'=32 -'||'=33 -'!'=34 +'@unroll'=6 +'goto'=7 +'('=8 +','=9 +')'=10 +'='=11 +'forward'=12 +'backward'=13 +'left'=14 +'right'=15 +'penup'=16 +'pendown'=17 +'pause'=18 +'assert'=19 +'assume'=20 +'+'=21 +'-'=22 +'*'=23 +'/'=24 +'%'=25 +'pendown?'=26 +'<'=27 +'>'=28 +'=='=29 +'!='=30 +'<='=31 +'>='=32 +'&&'=33 +'||'=34 +'!'=35 diff --git a/ChironCore/turtparse/tlangParser.py b/ChironCore/turtparse/tlangParser.py index 9f6ac23..d289bda 100644 --- a/ChironCore/turtparse/tlangParser.py +++ b/ChironCore/turtparse/tlangParser.py @@ -8,8 +8,8 @@ def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3)") - buf.write("\u00c3\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3*") + buf.write("\u00cd\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16") buf.write("\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23\t\23") buf.write("\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31") @@ -17,70 +17,75 @@ def serializedATN(): buf.write("\3\3\4\6\4?\n\4\r\4\16\4@\3\5\3\5\3\5\3\5\3\5\3\5\3\5") buf.write("\3\5\3\5\5\5L\n\5\3\6\3\6\5\6P\n\6\3\7\3\7\3\7\3\7\3\7") buf.write("\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3") - buf.write("\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3") - buf.write("\13\3\13\3\f\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\3\20") - buf.write("\3\20\3\20\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22") - buf.write("\3\22\3\22\3\22\5\22\u008b\n\22\3\22\3\22\3\22\3\22\3") - buf.write("\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\7\22\u0099\n\22") - buf.write("\f\22\16\22\u009c\13\22\3\23\3\23\3\24\3\24\3\25\3\25") - buf.write("\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27") - buf.write("\3\27\3\27\3\27\5\27\u00b2\n\27\3\27\3\27\3\27\3\27\7") - buf.write("\27\u00b8\n\27\f\27\16\27\u00bb\13\27\3\30\3\30\3\31\3") - buf.write("\31\3\32\3\32\3\32\2\4\",\33\2\4\6\b\n\f\16\20\22\24\26") - buf.write("\30\32\34\36 \"$&(*,.\60\62\2\t\3\2\r\20\3\2\21\22\3\2") - buf.write("\30\31\3\2\26\27\3\2\34!\3\2\"#\3\2%&\2\u00bd\2\64\3\2") - buf.write("\2\2\4:\3\2\2\2\6>\3\2\2\2\bK\3\2\2\2\nO\3\2\2\2\fQ\3") - buf.write("\2\2\2\16W\3\2\2\2\20a\3\2\2\2\22g\3\2\2\2\24n\3\2\2\2") - buf.write("\26r\3\2\2\2\30u\3\2\2\2\32w\3\2\2\2\34y\3\2\2\2\36{\3") - buf.write("\2\2\2 ~\3\2\2\2\"\u008a\3\2\2\2$\u009d\3\2\2\2&\u009f") - buf.write("\3\2\2\2(\u00a1\3\2\2\2*\u00a3\3\2\2\2,\u00b1\3\2\2\2") - buf.write(".\u00bc\3\2\2\2\60\u00be\3\2\2\2\62\u00c0\3\2\2\2\64\65") - buf.write("\5\4\3\2\65\66\7\2\2\3\66\3\3\2\2\2\679\5\b\5\28\67\3") - buf.write("\2\2\29<\3\2\2\2:8\3\2\2\2:;\3\2\2\2;\5\3\2\2\2<:\3\2") - buf.write("\2\2=?\5\b\5\2>=\3\2\2\2?@\3\2\2\2@>\3\2\2\2@A\3\2\2\2") - buf.write("A\7\3\2\2\2BL\5\24\13\2CL\5\n\6\2DL\5\20\t\2EL\5\26\f") - buf.write("\2FL\5\32\16\2GL\5\22\n\2HL\5\34\17\2IL\5\36\20\2JL\5") - buf.write(" \21\2KB\3\2\2\2KC\3\2\2\2KD\3\2\2\2KE\3\2\2\2KF\3\2\2") - buf.write("\2KG\3\2\2\2KH\3\2\2\2KI\3\2\2\2KJ\3\2\2\2L\t\3\2\2\2") - buf.write("MP\5\f\7\2NP\5\16\b\2OM\3\2\2\2ON\3\2\2\2P\13\3\2\2\2") - buf.write("QR\7\3\2\2RS\5,\27\2ST\7\4\2\2TU\5\6\4\2UV\7\5\2\2V\r") - buf.write("\3\2\2\2WX\7\3\2\2XY\5,\27\2YZ\7\4\2\2Z[\5\6\4\2[\\\7") - buf.write("\5\2\2\\]\7\6\2\2]^\7\4\2\2^_\5\6\4\2_`\7\5\2\2`\17\3") - buf.write("\2\2\2ab\7\7\2\2bc\5\62\32\2cd\7\4\2\2de\5\6\4\2ef\7\5") - buf.write("\2\2f\21\3\2\2\2gh\7\b\2\2hi\7\t\2\2ij\5\"\22\2jk\7\n") - buf.write("\2\2kl\5\"\22\2lm\7\13\2\2m\23\3\2\2\2no\7&\2\2op\7\f") - buf.write("\2\2pq\5\"\22\2q\25\3\2\2\2rs\5\30\r\2st\5\"\22\2t\27") - buf.write("\3\2\2\2uv\t\2\2\2v\31\3\2\2\2wx\t\3\2\2x\33\3\2\2\2y") - buf.write("z\7\23\2\2z\35\3\2\2\2{|\7\24\2\2|}\5,\27\2}\37\3\2\2") - buf.write("\2~\177\7\25\2\2\177\u0080\5,\27\2\u0080!\3\2\2\2\u0081") - buf.write("\u0082\b\22\1\2\u0082\u0083\5*\26\2\u0083\u0084\5\"\22") - buf.write("\b\u0084\u008b\3\2\2\2\u0085\u008b\5\62\32\2\u0086\u0087") - buf.write("\7\t\2\2\u0087\u0088\5\"\22\2\u0088\u0089\7\13\2\2\u0089") - buf.write("\u008b\3\2\2\2\u008a\u0081\3\2\2\2\u008a\u0085\3\2\2\2") - buf.write("\u008a\u0086\3\2\2\2\u008b\u009a\3\2\2\2\u008c\u008d\f") - buf.write("\7\2\2\u008d\u008e\5$\23\2\u008e\u008f\5\"\22\b\u008f") - buf.write("\u0099\3\2\2\2\u0090\u0091\f\6\2\2\u0091\u0092\5&\24\2") - buf.write("\u0092\u0093\5\"\22\7\u0093\u0099\3\2\2\2\u0094\u0095") - buf.write("\f\5\2\2\u0095\u0096\5(\25\2\u0096\u0097\5\"\22\6\u0097") - buf.write("\u0099\3\2\2\2\u0098\u008c\3\2\2\2\u0098\u0090\3\2\2\2") - buf.write("\u0098\u0094\3\2\2\2\u0099\u009c\3\2\2\2\u009a\u0098\3") - buf.write("\2\2\2\u009a\u009b\3\2\2\2\u009b#\3\2\2\2\u009c\u009a") - buf.write("\3\2\2\2\u009d\u009e\t\4\2\2\u009e%\3\2\2\2\u009f\u00a0") - buf.write("\t\5\2\2\u00a0\'\3\2\2\2\u00a1\u00a2\7\32\2\2\u00a2)\3") - buf.write("\2\2\2\u00a3\u00a4\7\27\2\2\u00a4+\3\2\2\2\u00a5\u00a6") - buf.write("\b\27\1\2\u00a6\u00a7\7$\2\2\u00a7\u00b2\5,\27\7\u00a8") - buf.write("\u00a9\5\"\22\2\u00a9\u00aa\5.\30\2\u00aa\u00ab\5\"\22") - buf.write("\2\u00ab\u00b2\3\2\2\2\u00ac\u00b2\7\33\2\2\u00ad\u00ae") - buf.write("\7\t\2\2\u00ae\u00af\5,\27\2\u00af\u00b0\7\13\2\2\u00b0") - buf.write("\u00b2\3\2\2\2\u00b1\u00a5\3\2\2\2\u00b1\u00a8\3\2\2\2") - buf.write("\u00b1\u00ac\3\2\2\2\u00b1\u00ad\3\2\2\2\u00b2\u00b9\3") - buf.write("\2\2\2\u00b3\u00b4\f\5\2\2\u00b4\u00b5\5\60\31\2\u00b5") - buf.write("\u00b6\5,\27\6\u00b6\u00b8\3\2\2\2\u00b7\u00b3\3\2\2\2") - buf.write("\u00b8\u00bb\3\2\2\2\u00b9\u00b7\3\2\2\2\u00b9\u00ba\3") - buf.write("\2\2\2\u00ba-\3\2\2\2\u00bb\u00b9\3\2\2\2\u00bc\u00bd") - buf.write("\t\6\2\2\u00bd/\3\2\2\2\u00be\u00bf\t\7\2\2\u00bf\61\3") - buf.write("\2\2\2\u00c0\u00c1\t\b\2\2\u00c1\63\3\2\2\2\13:@KO\u008a") - buf.write("\u0098\u009a\u00b1\u00b9") + buf.write("\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\5\tp\n") + buf.write("\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\f") + buf.write("\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3") + buf.write("\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22") + buf.write("\3\22\5\22\u0095\n\22\3\22\3\22\3\22\3\22\3\22\3\22\3") + buf.write("\22\3\22\3\22\3\22\3\22\3\22\7\22\u00a3\n\22\f\22\16\22") + buf.write("\u00a6\13\22\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26\3") + buf.write("\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27") + buf.write("\3\27\5\27\u00bc\n\27\3\27\3\27\3\27\3\27\7\27\u00c2\n") + buf.write("\27\f\27\16\27\u00c5\13\27\3\30\3\30\3\31\3\31\3\32\3") + buf.write("\32\3\32\2\4\",\33\2\4\6\b\n\f\16\20\22\24\26\30\32\34") + buf.write("\36 \"$&(*,.\60\62\2\t\3\2\16\21\3\2\22\23\3\2\31\32\3") + buf.write("\2\27\30\3\2\35\"\3\2#$\3\2&\'\2\u00c8\2\64\3\2\2\2\4") + buf.write(":\3\2\2\2\6>\3\2\2\2\bK\3\2\2\2\nO\3\2\2\2\fQ\3\2\2\2") + buf.write("\16W\3\2\2\2\20o\3\2\2\2\22q\3\2\2\2\24x\3\2\2\2\26|\3") + buf.write("\2\2\2\30\177\3\2\2\2\32\u0081\3\2\2\2\34\u0083\3\2\2") + buf.write("\2\36\u0085\3\2\2\2 \u0088\3\2\2\2\"\u0094\3\2\2\2$\u00a7") + buf.write("\3\2\2\2&\u00a9\3\2\2\2(\u00ab\3\2\2\2*\u00ad\3\2\2\2") + buf.write(",\u00bb\3\2\2\2.\u00c6\3\2\2\2\60\u00c8\3\2\2\2\62\u00ca") + buf.write("\3\2\2\2\64\65\5\4\3\2\65\66\7\2\2\3\66\3\3\2\2\2\679") + buf.write("\5\b\5\28\67\3\2\2\29<\3\2\2\2:8\3\2\2\2:;\3\2\2\2;\5") + buf.write("\3\2\2\2<:\3\2\2\2=?\5\b\5\2>=\3\2\2\2?@\3\2\2\2@>\3\2") + buf.write("\2\2@A\3\2\2\2A\7\3\2\2\2BL\5\24\13\2CL\5\n\6\2DL\5\20") + buf.write("\t\2EL\5\26\f\2FL\5\32\16\2GL\5\22\n\2HL\5\34\17\2IL\5") + buf.write("\36\20\2JL\5 \21\2KB\3\2\2\2KC\3\2\2\2KD\3\2\2\2KE\3\2") + buf.write("\2\2KF\3\2\2\2KG\3\2\2\2KH\3\2\2\2KI\3\2\2\2KJ\3\2\2\2") + buf.write("L\t\3\2\2\2MP\5\f\7\2NP\5\16\b\2OM\3\2\2\2ON\3\2\2\2P") + buf.write("\13\3\2\2\2QR\7\3\2\2RS\5,\27\2ST\7\4\2\2TU\5\6\4\2UV") + buf.write("\7\5\2\2V\r\3\2\2\2WX\7\3\2\2XY\5,\27\2YZ\7\4\2\2Z[\5") + buf.write("\6\4\2[\\\7\5\2\2\\]\7\6\2\2]^\7\4\2\2^_\5\6\4\2_`\7\5") + buf.write("\2\2`\17\3\2\2\2ab\7\7\2\2bc\5\62\32\2cd\7\4\2\2de\5\6") + buf.write("\4\2ef\7\5\2\2fp\3\2\2\2gh\7\b\2\2hi\7&\2\2ij\7\7\2\2") + buf.write("jk\5\62\32\2kl\7\4\2\2lm\5\6\4\2mn\7\5\2\2np\3\2\2\2o") + buf.write("a\3\2\2\2og\3\2\2\2p\21\3\2\2\2qr\7\t\2\2rs\7\n\2\2st") + buf.write("\5\"\22\2tu\7\13\2\2uv\5\"\22\2vw\7\f\2\2w\23\3\2\2\2") + buf.write("xy\7\'\2\2yz\7\r\2\2z{\5\"\22\2{\25\3\2\2\2|}\5\30\r\2") + buf.write("}~\5\"\22\2~\27\3\2\2\2\177\u0080\t\2\2\2\u0080\31\3\2") + buf.write("\2\2\u0081\u0082\t\3\2\2\u0082\33\3\2\2\2\u0083\u0084") + buf.write("\7\24\2\2\u0084\35\3\2\2\2\u0085\u0086\7\25\2\2\u0086") + buf.write("\u0087\5,\27\2\u0087\37\3\2\2\2\u0088\u0089\7\26\2\2\u0089") + buf.write("\u008a\5,\27\2\u008a!\3\2\2\2\u008b\u008c\b\22\1\2\u008c") + buf.write("\u008d\5*\26\2\u008d\u008e\5\"\22\b\u008e\u0095\3\2\2") + buf.write("\2\u008f\u0095\5\62\32\2\u0090\u0091\7\n\2\2\u0091\u0092") + buf.write("\5\"\22\2\u0092\u0093\7\f\2\2\u0093\u0095\3\2\2\2\u0094") + buf.write("\u008b\3\2\2\2\u0094\u008f\3\2\2\2\u0094\u0090\3\2\2\2") + buf.write("\u0095\u00a4\3\2\2\2\u0096\u0097\f\7\2\2\u0097\u0098\5") + buf.write("$\23\2\u0098\u0099\5\"\22\b\u0099\u00a3\3\2\2\2\u009a") + buf.write("\u009b\f\6\2\2\u009b\u009c\5&\24\2\u009c\u009d\5\"\22") + buf.write("\7\u009d\u00a3\3\2\2\2\u009e\u009f\f\5\2\2\u009f\u00a0") + buf.write("\5(\25\2\u00a0\u00a1\5\"\22\6\u00a1\u00a3\3\2\2\2\u00a2") + buf.write("\u0096\3\2\2\2\u00a2\u009a\3\2\2\2\u00a2\u009e\3\2\2\2") + buf.write("\u00a3\u00a6\3\2\2\2\u00a4\u00a2\3\2\2\2\u00a4\u00a5\3") + buf.write("\2\2\2\u00a5#\3\2\2\2\u00a6\u00a4\3\2\2\2\u00a7\u00a8") + buf.write("\t\4\2\2\u00a8%\3\2\2\2\u00a9\u00aa\t\5\2\2\u00aa\'\3") + buf.write("\2\2\2\u00ab\u00ac\7\33\2\2\u00ac)\3\2\2\2\u00ad\u00ae") + buf.write("\7\30\2\2\u00ae+\3\2\2\2\u00af\u00b0\b\27\1\2\u00b0\u00b1") + buf.write("\7%\2\2\u00b1\u00bc\5,\27\7\u00b2\u00b3\5\"\22\2\u00b3") + buf.write("\u00b4\5.\30\2\u00b4\u00b5\5\"\22\2\u00b5\u00bc\3\2\2") + buf.write("\2\u00b6\u00bc\7\34\2\2\u00b7\u00b8\7\n\2\2\u00b8\u00b9") + buf.write("\5,\27\2\u00b9\u00ba\7\f\2\2\u00ba\u00bc\3\2\2\2\u00bb") + buf.write("\u00af\3\2\2\2\u00bb\u00b2\3\2\2\2\u00bb\u00b6\3\2\2\2") + buf.write("\u00bb\u00b7\3\2\2\2\u00bc\u00c3\3\2\2\2\u00bd\u00be\f") + buf.write("\5\2\2\u00be\u00bf\5\60\31\2\u00bf\u00c0\5,\27\6\u00c0") + buf.write("\u00c2\3\2\2\2\u00c1\u00bd\3\2\2\2\u00c2\u00c5\3\2\2\2") + buf.write("\u00c3\u00c1\3\2\2\2\u00c3\u00c4\3\2\2\2\u00c4-\3\2\2") + buf.write("\2\u00c5\u00c3\3\2\2\2\u00c6\u00c7\t\6\2\2\u00c7/\3\2") + buf.write("\2\2\u00c8\u00c9\t\7\2\2\u00c9\61\3\2\2\2\u00ca\u00cb") + buf.write("\t\b\2\2\u00cb\63\3\2\2\2\f:@KOo\u0094\u00a2\u00a4\u00bb") + buf.write("\u00c3") return buf.getvalue() @@ -95,20 +100,21 @@ class tlangParser ( Parser ): sharedContextCache = PredictionContextCache() literalNames = [ "", "'if'", "'['", "']'", "'else'", "'repeat'", - "'goto'", "'('", "','", "')'", "'='", "'forward'", - "'backward'", "'left'", "'right'", "'penup'", "'pendown'", - "'pause'", "'assert'", "'assume'", "'+'", "'-'", "'*'", - "'/'", "'%'", "'pendown?'", "'<'", "'>'", "'=='", "'!='", - "'<='", "'>='", "'&&'", "'||'", "'!'" ] + "'@unroll'", "'goto'", "'('", "','", "')'", "'='", + "'forward'", "'backward'", "'left'", "'right'", "'penup'", + "'pendown'", "'pause'", "'assert'", "'assume'", "'+'", + "'-'", "'*'", "'/'", "'%'", "'pendown?'", "'<'", "'>'", + "'=='", "'!='", "'<='", "'>='", "'&&'", "'||'", "'!'" ] symbolicNames = [ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", - "GT", "EQ", "NEQ", "LTE", "GTE", "AND", "OR", "NOT", - "NUM", "VAR", "NAME", "Whitespace", "Comment" ] + "", "PLUS", "MINUS", "MUL", "DIV", "MOD", + "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", "GTE", + "AND", "OR", "NOT", "NUM", "VAR", "NAME", "Whitespace", + "Comment" ] RULE_start = 0 RULE_instruction_list = 1 @@ -164,26 +170,27 @@ class tlangParser ( Parser ): T__16=17 T__17=18 T__18=19 - PLUS=20 - MINUS=21 - MUL=22 - DIV=23 - MOD=24 - PENCOND=25 - LT=26 - GT=27 - EQ=28 - NEQ=29 - LTE=30 - GTE=31 - AND=32 - OR=33 - NOT=34 - NUM=35 - VAR=36 - NAME=37 - Whitespace=38 - Comment=39 + T__19=20 + PLUS=21 + MINUS=22 + MUL=23 + DIV=24 + MOD=25 + PENCOND=26 + LT=27 + GT=28 + EQ=29 + NEQ=30 + LTE=31 + GTE=32 + AND=33 + OR=34 + NOT=35 + NUM=36 + VAR=37 + NAME=38 + Whitespace=39 + Comment=40 def __init__(self, input:TokenStream, output:TextIO = sys.stdout): super().__init__(input, output) @@ -273,7 +280,7 @@ def instruction_list(self): self.state = 56 self._errHandler.sync(self) _la = self._input.LA(1) - while (((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.T__18) | (1 << tlangParser.VAR))) != 0): + while (((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__6) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.T__18) | (1 << tlangParser.T__19) | (1 << tlangParser.VAR))) != 0): self.state = 53 self.instruction() self.state = 58 @@ -330,7 +337,7 @@ def strict_ilist(self): self.state = 62 self._errHandler.sync(self) _la = self._input.LA(1) - if not ((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.T__18) | (1 << tlangParser.VAR))) != 0)): + if not ((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__0) | (1 << tlangParser.T__4) | (1 << tlangParser.T__5) | (1 << tlangParser.T__6) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14) | (1 << tlangParser.T__15) | (1 << tlangParser.T__16) | (1 << tlangParser.T__17) | (1 << tlangParser.T__18) | (1 << tlangParser.T__19) | (1 << tlangParser.VAR))) != 0)): break except RecognitionException as re: @@ -414,37 +421,37 @@ def instruction(self): self.state = 65 self.conditional() pass - elif token in [tlangParser.T__4]: + elif token in [tlangParser.T__4, tlangParser.T__5]: self.enterOuterAlt(localctx, 3) self.state = 66 self.loop() pass - elif token in [tlangParser.T__10, tlangParser.T__11, tlangParser.T__12, tlangParser.T__13]: + elif token in [tlangParser.T__11, tlangParser.T__12, tlangParser.T__13, tlangParser.T__14]: self.enterOuterAlt(localctx, 4) self.state = 67 self.moveCommand() pass - elif token in [tlangParser.T__14, tlangParser.T__15]: + elif token in [tlangParser.T__15, tlangParser.T__16]: self.enterOuterAlt(localctx, 5) self.state = 68 self.penCommand() pass - elif token in [tlangParser.T__5]: + elif token in [tlangParser.T__6]: self.enterOuterAlt(localctx, 6) self.state = 69 self.gotoCommand() pass - elif token in [tlangParser.T__16]: + elif token in [tlangParser.T__17]: self.enterOuterAlt(localctx, 7) self.state = 70 self.pauseCommand() pass - elif token in [tlangParser.T__17]: + elif token in [tlangParser.T__18]: self.enterOuterAlt(localctx, 8) self.state = 71 self.assertionCommand() pass - elif token in [tlangParser.T__18]: + elif token in [tlangParser.T__19]: self.enterOuterAlt(localctx, 9) self.state = 72 self.assumeCommand() @@ -644,6 +651,9 @@ def strict_ilist(self): return self.getTypedRuleContext(tlangParser.Strict_ilistContext,0) + def NUM(self): + return self.getToken(tlangParser.NUM, 0) + def getRuleIndex(self): return tlangParser.RULE_loop @@ -661,17 +671,42 @@ def loop(self): localctx = tlangParser.LoopContext(self, self._ctx, self.state) self.enterRule(localctx, 14, self.RULE_loop) try: - self.enterOuterAlt(localctx, 1) - self.state = 95 - self.match(tlangParser.T__4) - self.state = 96 - self.value() - self.state = 97 - self.match(tlangParser.T__1) - self.state = 98 - self.strict_ilist() - self.state = 99 - self.match(tlangParser.T__2) + self.state = 109 + self._errHandler.sync(self) + token = self._input.LA(1) + if token in [tlangParser.T__4]: + self.enterOuterAlt(localctx, 1) + self.state = 95 + self.match(tlangParser.T__4) + self.state = 96 + self.value() + self.state = 97 + self.match(tlangParser.T__1) + self.state = 98 + self.strict_ilist() + self.state = 99 + self.match(tlangParser.T__2) + pass + elif token in [tlangParser.T__5]: + self.enterOuterAlt(localctx, 2) + self.state = 101 + self.match(tlangParser.T__5) + self.state = 102 + self.match(tlangParser.NUM) + self.state = 103 + self.match(tlangParser.T__4) + self.state = 104 + self.value() + self.state = 105 + self.match(tlangParser.T__1) + self.state = 106 + self.strict_ilist() + self.state = 107 + self.match(tlangParser.T__2) + pass + else: + raise NoViableAltException(self) + except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) @@ -712,18 +747,18 @@ def gotoCommand(self): self.enterRule(localctx, 16, self.RULE_gotoCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 101 - self.match(tlangParser.T__5) - self.state = 102 + self.state = 111 self.match(tlangParser.T__6) - self.state = 103 - self.expression(0) - self.state = 104 + self.state = 112 self.match(tlangParser.T__7) - self.state = 105 + self.state = 113 self.expression(0) - self.state = 106 + self.state = 114 self.match(tlangParser.T__8) + self.state = 115 + self.expression(0) + self.state = 116 + self.match(tlangParser.T__9) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) @@ -764,11 +799,11 @@ def assignment(self): self.enterRule(localctx, 18, self.RULE_assignment) try: self.enterOuterAlt(localctx, 1) - self.state = 108 + self.state = 118 self.match(tlangParser.VAR) - self.state = 109 - self.match(tlangParser.T__9) - self.state = 110 + self.state = 119 + self.match(tlangParser.T__10) + self.state = 120 self.expression(0) except RecognitionException as re: localctx.exception = re @@ -811,9 +846,9 @@ def moveCommand(self): self.enterRule(localctx, 20, self.RULE_moveCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 112 + self.state = 122 self.moveOp() - self.state = 113 + self.state = 123 self.expression(0) except RecognitionException as re: localctx.exception = re @@ -850,9 +885,9 @@ def moveOp(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 115 + self.state = 125 _la = self._input.LA(1) - if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__10) | (1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13))) != 0)): + if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.T__11) | (1 << tlangParser.T__12) | (1 << tlangParser.T__13) | (1 << tlangParser.T__14))) != 0)): self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) @@ -892,9 +927,9 @@ def penCommand(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 117 + self.state = 127 _la = self._input.LA(1) - if not(_la==tlangParser.T__14 or _la==tlangParser.T__15): + if not(_la==tlangParser.T__15 or _la==tlangParser.T__16): self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) @@ -933,8 +968,8 @@ def pauseCommand(self): self.enterRule(localctx, 26, self.RULE_pauseCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 119 - self.match(tlangParser.T__16) + self.state = 129 + self.match(tlangParser.T__17) except RecognitionException as re: localctx.exception = re self._errHandler.reportError(self, re) @@ -972,9 +1007,9 @@ def assertionCommand(self): self.enterRule(localctx, 28, self.RULE_assertionCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 121 - self.match(tlangParser.T__17) - self.state = 122 + self.state = 131 + self.match(tlangParser.T__18) + self.state = 132 self.condition(0) except RecognitionException as re: localctx.exception = re @@ -1013,9 +1048,9 @@ def assumeCommand(self): self.enterRule(localctx, 30, self.RULE_assumeCommand) try: self.enterOuterAlt(localctx, 1) - self.state = 124 - self.match(tlangParser.T__18) - self.state = 125 + self.state = 134 + self.match(tlangParser.T__19) + self.state = 135 self.condition(0) except RecognitionException as re: localctx.exception = re @@ -1174,7 +1209,7 @@ def expression(self, _p:int=0): self.enterRecursionRule(localctx, 32, self.RULE_expression, _p) try: self.enterOuterAlt(localctx, 1) - self.state = 136 + self.state = 146 self._errHandler.sync(self) token = self._input.LA(1) if token in [tlangParser.MINUS]: @@ -1182,87 +1217,87 @@ def expression(self, _p:int=0): self._ctx = localctx _prevctx = localctx - self.state = 128 + self.state = 138 self.unaryArithOp() - self.state = 129 + self.state = 139 self.expression(6) pass elif token in [tlangParser.NUM, tlangParser.VAR]: localctx = tlangParser.ValueExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 131 + self.state = 141 self.value() pass - elif token in [tlangParser.T__6]: + elif token in [tlangParser.T__7]: localctx = tlangParser.ParenExprContext(self, localctx) self._ctx = localctx _prevctx = localctx - self.state = 132 - self.match(tlangParser.T__6) - self.state = 133 + self.state = 142 + self.match(tlangParser.T__7) + self.state = 143 self.expression(0) - self.state = 134 - self.match(tlangParser.T__8) + self.state = 144 + self.match(tlangParser.T__9) pass else: raise NoViableAltException(self) self._ctx.stop = self._input.LT(-1) - self.state = 152 + self.state = 162 self._errHandler.sync(self) - _alt = self._interp.adaptivePredict(self._input,6,self._ctx) + _alt = self._interp.adaptivePredict(self._input,7,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: if _alt==1: if self._parseListeners is not None: self.triggerExitRuleEvent() _prevctx = localctx - self.state = 150 + self.state = 160 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input,5,self._ctx) + la_ = self._interp.adaptivePredict(self._input,6,self._ctx) if la_ == 1: localctx = tlangParser.MulExprContext(self, tlangParser.ExpressionContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expression) - self.state = 138 + self.state = 148 if not self.precpred(self._ctx, 5): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 5)") - self.state = 139 + self.state = 149 self.multiplicative() - self.state = 140 + self.state = 150 self.expression(6) pass elif la_ == 2: localctx = tlangParser.AddExprContext(self, tlangParser.ExpressionContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expression) - self.state = 142 + self.state = 152 if not self.precpred(self._ctx, 4): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 4)") - self.state = 143 + self.state = 153 self.additive() - self.state = 144 + self.state = 154 self.expression(5) pass elif la_ == 3: localctx = tlangParser.ModExprContext(self, tlangParser.ExpressionContext(self, _parentctx, _parentState)) self.pushNewRecursionContext(localctx, _startState, self.RULE_expression) - self.state = 146 + self.state = 156 if not self.precpred(self._ctx, 3): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 3)") - self.state = 147 + self.state = 157 self.modulo() - self.state = 148 + self.state = 158 self.expression(4) pass - self.state = 154 + self.state = 164 self._errHandler.sync(self) - _alt = self._interp.adaptivePredict(self._input,6,self._ctx) + _alt = self._interp.adaptivePredict(self._input,7,self._ctx) except RecognitionException as re: localctx.exception = re @@ -1304,7 +1339,7 @@ def multiplicative(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 155 + self.state = 165 _la = self._input.LA(1) if not(_la==tlangParser.MUL or _la==tlangParser.DIV): self._errHandler.recoverInline(self) @@ -1351,7 +1386,7 @@ def additive(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 157 + self.state = 167 _la = self._input.LA(1) if not(_la==tlangParser.PLUS or _la==tlangParser.MINUS): self._errHandler.recoverInline(self) @@ -1394,7 +1429,7 @@ def modulo(self): self.enterRule(localctx, 38, self.RULE_modulo) try: self.enterOuterAlt(localctx, 1) - self.state = 159 + self.state = 169 self.match(tlangParser.MOD) except RecognitionException as re: localctx.exception = re @@ -1432,7 +1467,7 @@ def unaryArithOp(self): self.enterRule(localctx, 40, self.RULE_unaryArithOp) try: self.enterOuterAlt(localctx, 1) - self.state = 161 + self.state = 171 self.match(tlangParser.MINUS) except RecognitionException as re: localctx.exception = re @@ -1497,44 +1532,44 @@ def condition(self, _p:int=0): self.enterRecursionRule(localctx, 42, self.RULE_condition, _p) try: self.enterOuterAlt(localctx, 1) - self.state = 175 + self.state = 185 self._errHandler.sync(self) - la_ = self._interp.adaptivePredict(self._input,7,self._ctx) + la_ = self._interp.adaptivePredict(self._input,8,self._ctx) if la_ == 1: - self.state = 164 + self.state = 174 self.match(tlangParser.NOT) - self.state = 165 + self.state = 175 self.condition(5) pass elif la_ == 2: - self.state = 166 + self.state = 176 self.expression(0) - self.state = 167 + self.state = 177 self.binCondOp() - self.state = 168 + self.state = 178 self.expression(0) pass elif la_ == 3: - self.state = 170 + self.state = 180 self.match(tlangParser.PENCOND) pass elif la_ == 4: - self.state = 171 - self.match(tlangParser.T__6) - self.state = 172 + self.state = 181 + self.match(tlangParser.T__7) + self.state = 182 self.condition(0) - self.state = 173 - self.match(tlangParser.T__8) + self.state = 183 + self.match(tlangParser.T__9) pass self._ctx.stop = self._input.LT(-1) - self.state = 183 + self.state = 193 self._errHandler.sync(self) - _alt = self._interp.adaptivePredict(self._input,8,self._ctx) + _alt = self._interp.adaptivePredict(self._input,9,self._ctx) while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: if _alt==1: if self._parseListeners is not None: @@ -1542,17 +1577,17 @@ def condition(self, _p:int=0): _prevctx = localctx localctx = tlangParser.ConditionContext(self, _parentctx, _parentState) self.pushNewRecursionContext(localctx, _startState, self.RULE_condition) - self.state = 177 + self.state = 187 if not self.precpred(self._ctx, 3): from antlr4.error.Errors import FailedPredicateException raise FailedPredicateException(self, "self.precpred(self._ctx, 3)") - self.state = 178 + self.state = 188 self.logicOp() - self.state = 179 + self.state = 189 self.condition(4) - self.state = 185 + self.state = 195 self._errHandler.sync(self) - _alt = self._interp.adaptivePredict(self._input,8,self._ctx) + _alt = self._interp.adaptivePredict(self._input,9,self._ctx) except RecognitionException as re: localctx.exception = re @@ -1606,7 +1641,7 @@ def binCondOp(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 186 + self.state = 196 _la = self._input.LA(1) if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.LT) | (1 << tlangParser.GT) | (1 << tlangParser.EQ) | (1 << tlangParser.NEQ) | (1 << tlangParser.LTE) | (1 << tlangParser.GTE))) != 0)): self._errHandler.recoverInline(self) @@ -1653,7 +1688,7 @@ def logicOp(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 188 + self.state = 198 _la = self._input.LA(1) if not(_la==tlangParser.AND or _la==tlangParser.OR): self._errHandler.recoverInline(self) @@ -1700,7 +1735,7 @@ def value(self): self._la = 0 # Token type try: self.enterOuterAlt(localctx, 1) - self.state = 190 + self.state = 200 _la = self._input.LA(1) if not(_la==tlangParser.NUM or _la==tlangParser.VAR): self._errHandler.recoverInline(self) diff --git a/ChironCore/unroll.py b/ChironCore/unroll.py index 62d0571..a413156 100644 --- a/ChironCore/unroll.py +++ b/ChironCore/unroll.py @@ -74,20 +74,23 @@ def visitValue(self, ctx:tlangParser.ValueContext): return ctx.getText() def visitLoop(self, ctx:tlangParser.LoopContext): + unrollCount = self.bound + if ctx.NUM() is not None: + unrollCount = int(ctx.NUM().getText()) repeatCount = self.visit(ctx.value()) loopBlock = self.visit(ctx.strict_ilist()) code = "" if (repeatCount[0] != ":"): # constant number of iterations - code += "assume " + str(repeatCount) + " <= " + str(self.bound) +"\n" - for i in range(min(int(repeatCount), self.bound)): + code += "assume " + str(repeatCount) + " <= " + str(unrollCount) +"\n" + for i in range(min(int(repeatCount), unrollCount)): code += loopBlock + "\n" else: # variable number of iterations repeatVariable = ":_repeat" + str(self.repeatVariablesCounter) code += repeatVariable + " = " + repeatCount + "\n" - code += "assume " + repeatVariable + " <= " + str(self.bound) +" \n" - for i in range(self.bound): + code += "assume " + repeatVariable + " <= " + str(unrollCount) +" \n" + for i in range(unrollCount): code += "if (" + repeatVariable + " > " + str(i) + ") [\n" + loopBlock + "\n]\n" self.repeatVariablesCounter += 1 diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index a4e1e60..fa2b089 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,222 +1,127 @@ -pendown -assume 3 <= 10 -if ((:x>:y)) [ -penup -goto (:x, :y) -pendown -assume 4 <= 10 -forward:x -left90 - -forward:x -left90 - -forward:x -left90 - -forward:x -left90 - - - -] else [ -penup -goto (:y, :x) -pendown -assume 5 <= 10 -forward:p -left72 - -forward:p -left72 - -forward:p -left72 - -forward:p -left72 - -forward:p -left72 - - +:_repeat0 = :a +assume :_repeat0 <= 5 +if (:_repeat0 > 0) [ +forward10 +if ((:a<2)) [ +:y=3 ] -if ((:z>=:p)) [ -penup -goto (:p, :x+:z) -pendown -assume 6 <= 10 -backward:x -left60 - -backward:x -left60 - -backward:x -left60 - -backward:x -left60 - -backward:x -left60 - -backward:x -left60 - - ] -:x=:x+10 -:y=:y+10 -:z=:z+10 - -if ((:x>:y)) [ -penup -goto (:x, :y) -pendown -assume 4 <= 10 -forward:x -left90 - -forward:x -left90 - -forward:x -left90 - -forward:x -left90 - - - -] else [ -penup -goto (:y, :x) -pendown -assume 5 <= 10 -forward:p -left72 - -forward:p -left72 - -forward:p -left72 - -forward:p -left72 - -forward:p -left72 - - +if (:_repeat0 > 1) [ +forward10 +if ((:a<2)) [ +:y=3 ] -if ((:z>=:p)) [ -penup -goto (:p, :x+:z) -pendown -assume 6 <= 10 -backward:x -left60 - -backward:x -left60 - -backward:x -left60 -backward:x -left60 - -backward:x -left60 - -backward:x -left60 +] +if (:_repeat0 > 2) [ +forward10 +if ((:a<2)) [ +:y=3 +] +] +if (:_repeat0 > 3) [ +forward10 +if ((:a<2)) [ +:y=3 ] -:x=:x+10 -:y=:y+10 -:z=:z+10 -if ((:x>:y)) [ -penup -goto (:x, :y) -pendown -assume 4 <= 10 -forward:x -left90 +] +if (:_repeat0 > 4) [ +forward10 +if ((:a<2)) [ +:y=3 -forward:x -left90 +] -forward:x -left90 +] -forward:x -left90 +:_repeat1 = :a +assume :_repeat1 <= 10 +if (:_repeat1 > 0) [ +forward10 +if ((:a<2)) [ +:y=3 +] +] +if (:_repeat1 > 1) [ +forward10 +if ((:a<2)) [ +:y=3 -] else [ -penup -goto (:y, :x) -pendown -assume 5 <= 10 -forward:p -left72 +] -forward:p -left72 +] +if (:_repeat1 > 2) [ +forward10 +if ((:a<2)) [ +:y=3 -forward:p -left72 +] -forward:p -left72 +] +if (:_repeat1 > 3) [ +forward10 +if ((:a<2)) [ +:y=3 -forward:p -left72 +] +] +if (:_repeat1 > 4) [ +forward10 +if ((:a<2)) [ +:y=3 +] ] -if ((:z>=:p)) [ -penup -goto (:p, :x+:z) -pendown -assume 6 <= 10 -backward:x -left60 +if (:_repeat1 > 5) [ +forward10 +if ((:a<2)) [ +:y=3 -backward:x -left60 +] -backward:x -left60 +] +if (:_repeat1 > 6) [ +forward10 +if ((:a<2)) [ +:y=3 -backward:x -left60 +] -backward:x -left60 +] +if (:_repeat1 > 7) [ +forward10 +if ((:a<2)) [ +:y=3 -backward:x -left60 +] +] +if (:_repeat1 > 8) [ +forward10 +if ((:a<2)) [ +:y=3 +] ] -:x=:x+10 -:y=:y+10 -:z=:z+10 +if (:_repeat1 > 9) [ +forward10 +if ((:a<2)) [ +:y=3 +] -penup +] -assert (:turtleX > 0) \ No newline at end of file +assert:turtleX<=1&&:turtleX>=-1&&:turtleY<=1&&:turtleY>=-1 From bacb2a185a3462c973b9f09cf7bfd45b8ddcb7f1 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Mon, 7 Apr 2025 16:53:22 +0530 Subject: [PATCH 45/53] modulo int, add decimal support in language, angle config file --- ChironCore/ChironAST/ChironAST.py | 2 +- ChironCore/ChironAST/builder.py | 3 + ChironCore/ChironTAC/builder.py | 9 +- ChironCore/angles.conf | 3 + ChironCore/bmc.py | 109 ++++++++----- ChironCore/chiron.py | 22 ++- ChironCore/example/example1.tl | 4 +- ChironCore/turtparse/tlang.g4 | 5 +- ChironCore/turtparse/tlang.interp | 4 +- ChironCore/turtparse/tlang.tokens | 9 +- ChironCore/turtparse/tlangLexer.interp | 5 +- ChironCore/turtparse/tlangLexer.py | 217 +++++++++++++------------ ChironCore/turtparse/tlangLexer.tokens | 9 +- ChironCore/turtparse/tlangParser.py | 34 ++-- 14 files changed, 249 insertions(+), 186 deletions(-) create mode 100644 ChironCore/angles.conf diff --git a/ChironCore/ChironAST/ChironAST.py b/ChironCore/ChironAST/ChironAST.py index aeb0b9f..5380ebc 100644 --- a/ChironCore/ChironAST/ChironAST.py +++ b/ChironCore/ChironAST/ChironAST.py @@ -231,7 +231,7 @@ class Value(Expression): class Num(Value): def __init__(self, v): - self.val = int(v) + self.val = float(v) def __str__(self): return str(self.val) diff --git a/ChironCore/ChironAST/builder.py b/ChironCore/ChironAST/builder.py index 4f9d034..8769aae 100644 --- a/ChironCore/ChironAST/builder.py +++ b/ChironCore/ChironAST/builder.py @@ -150,6 +150,9 @@ def visitCondition(self, ctx:tlangParser.ConditionContext): def visitValue(self, ctx:tlangParser.ValueContext): if ctx.NUM(): return ChironAST.Num(ctx.NUM().getText()) + elif ctx.FLOAT(): + print("returning ", ctx.FLOAT().getText()) + return ChironAST.Num(ctx.FLOAT().getText()) elif ctx.VAR(): return ChironAST.Var(ctx.VAR().getText()) diff --git a/ChironCore/ChironTAC/builder.py b/ChironCore/ChironTAC/builder.py index 60c17d4..1e68f68 100644 --- a/ChironCore/ChironTAC/builder.py +++ b/ChironCore/ChironTAC/builder.py @@ -444,8 +444,7 @@ def getFreeVariables(self): self.freeVars.add(stmt.rvar1.__str__()) if isinstance(stmt.rvar2, ChironTAC.Var) and stmt.rvar2.__str__() not in boundVars: self.freeVars.add(stmt.rvar2.__str__()) - if self.varConditions[stmt.lvar.name] is True: - boundVars.add(stmt.lvar.__str__()) + boundVars.add(stmt.lvar.__str__()) elif isinstance(stmt, ChironTAC.ConditionCommand): if isinstance(stmt.cond, ChironTAC.Var) and stmt.cond.__str__() not in boundVars: self.freeVars.add(stmt.cond.__str__()) @@ -466,13 +465,11 @@ def getFreeVariables(self): elif isinstance(stmt, ChironTAC.SinCommand): if isinstance(stmt.rvar, ChironTAC.Var) and stmt.rvar.__str__() not in boundVars: self.freeVars.add(stmt.rvar.__str__()) - if self.varConditions[stmt.lvar.name] is True: - boundVars.add(stmt.lvar.__str__()) + boundVars.add(stmt.lvar.__str__()) elif isinstance(stmt, ChironTAC.CosCommand): if isinstance(stmt.rvar, ChironTAC.Var) and stmt.rvar.__str__() not in boundVars: self.freeVars.add(stmt.rvar.__str__()) - if self.varConditions[stmt.lvar.name] is True: - boundVars.add(stmt.lvar.__str__()) + boundVars.add(stmt.lvar.__str__()) return self.freeVars diff --git a/ChironCore/angles.conf b/ChironCore/angles.conf new file mode 100644 index 0000000..37e9307 --- /dev/null +++ b/ChironCore/angles.conf @@ -0,0 +1,3 @@ +0,1,0 +45,0.707,0.707 +90,0,1 diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 50a7361..37685fa 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -6,13 +6,14 @@ from cfg import cfgBuilder class BMC: - def __init__(self, cfg): + def __init__(self, cfg, angle_conf): self.solver = z3.Solver() self.solver_without_cond = z3.Solver() self.angle_conditions = z3.BoolVal(True) self.assert_conditions = z3.BoolVal(True) self.assume_conditions = z3.BoolVal(True) self.cfg = cfg + self.angle_conf = angle_conf self.bbConditions = {} # bbConditions[bb] = condition for bb for bb in self.cfg: @@ -53,8 +54,8 @@ def convertSSAtoSMT(self): for bb in self.cfg.nodes(): for stmt, _ in bb.instrlist: if isinstance(stmt, ChironSSA.PhiCommand): - lvar = z3.Int(stmt.lvar.name) - rvars = [z3.Int(rvar.name) for rvar in stmt.rvars] + lvar = z3.Real(stmt.lvar.name) + rvars = [z3.Real(rvar.name) for rvar in stmt.rvars] rhs_expr = rvars[0] for i in range(1, len(stmt.rvars)): @@ -71,25 +72,25 @@ def convertSSAtoSMT(self): rvar2 = ChironSSA.Unused() if stmt.op in ["+", "-", "*", "/", "%"]: - lvar = z3.Int(stmt.lvar.name) + lvar = z3.Real(stmt.lvar.name) if isinstance(stmt.rvar1, ChironSSA.Var): - rvar1 = z3.Int(stmt.rvar1.name) + rvar1 = z3.Real(stmt.rvar1.name) elif isinstance(stmt.rvar1, ChironSSA.Num): - rvar1 = z3.IntVal(stmt.rvar1.value) + rvar1 = z3.RealVal(stmt.rvar1.value) if isinstance(stmt.rvar2, ChironSSA.Var): - rvar2 = z3.Int(stmt.rvar2.name) + rvar2 = z3.Real(stmt.rvar2.name) elif isinstance(stmt.rvar2, ChironSSA.Num): - rvar2 = z3.IntVal(stmt.rvar2.value) + rvar2 = z3.RealVal(stmt.rvar2.value) elif stmt.op in ["<", ">", "<=", ">=", "==", "!="]: lvar = z3.Bool(stmt.lvar.name) if isinstance(stmt.rvar1, ChironSSA.Var): - rvar1 = z3.Int(stmt.rvar1.name) + rvar1 = z3.Real(stmt.rvar1.name) elif isinstance(stmt.rvar1, ChironSSA.Num): - rvar1 = z3.IntVal(stmt.rvar1.value) + rvar1 = z3.RealVal(stmt.rvar1.value) if isinstance(stmt.rvar2, ChironSSA.Var): - rvar2 = z3.Int(stmt.rvar2.name) + rvar2 = z3.Real(stmt.rvar2.name) elif isinstance(stmt.rvar2, ChironSSA.Num): - rvar2 = z3.IntVal(stmt.rvar2.value) + rvar2 = z3.RealVal(stmt.rvar2.value) elif stmt.op in ["and", "or"]: lvar = z3.Bool(stmt.lvar.name) if isinstance(stmt.rvar1, ChironSSA.Var): @@ -135,13 +136,20 @@ def convertSSAtoSMT(self): self.solver.add(lvar == (rvar1 / rvar2)) elif stmt.op == "%": if self.varConditions[stmt.lvar.name] not in (None, True, False): - self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 % rvar2))) + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (z3.ToInt(rvar1) % z3.ToInt(rvar2)))) if stmt.lvar.name.startswith(":turtleThetaDeg$"): - self.angle_conditions = z3.And(self.angle_conditions, z3.Implies(self.varConditions[stmt.lvar.name], z3.Or(lvar == 0, lvar == 90, lvar == 180, lvar == 270))) + condition = z3.BoolVal(False) + for (angle, _, _) in self.angle_conf: + condition = z3.Or(condition, lvar == angle) + self.angle_conditions = z3.And(self.angle_conditions, z3.Implies(self.varConditions[stmt.lvar.name], condition)) elif self.varConditions[stmt.lvar.name] is not False: - self.solver.add(lvar == (rvar1 % rvar2)) + self.solver.add(lvar == (z3.ToInt(rvar1) % z3.ToInt(rvar2))) if stmt.lvar.name.startswith(":turtleThetaDeg$"): - self.angle_conditions = z3.And(self.angle_conditions, z3.Or(lvar == 0, lvar == 90, lvar == 180, lvar == 270)) + condition = z3.BoolVal(False) + for (angle, _, _) in self.angle_conf: + condition = z3.Or(condition, lvar == angle) + self.angle_conditions = z3.And(self.angle_conditions, condition) + elif stmt.op == "<": if self.varConditions[stmt.lvar.name] not in (None, True, False): self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], lvar == (rvar1 < rvar2))) @@ -214,21 +222,28 @@ def convertSSAtoSMT(self): elif self.varConditions[stmt.cond.name] is not False: self.assume_conditions = z3.And(self.assume_conditions, cond) - elif isinstance(stmt, ChironSSA.CosCommand): # Only for 0, 90, 180, 270 degree - rvar = z3.Int(stmt.rvar.name) - rhs_expr = z3.If(rvar == 0, 1, z3.If(rvar == 90, 0, z3.If(rvar == 180, -1, 0))) + elif isinstance(stmt, ChironSSA.CosCommand): # Only for angles given in angle_conf + rvar = z3.Real(stmt.rvar.name) + # rhs_expr = z3.If(rvar == 0, 1, z3.If(rvar == 90, 0, z3.If(rvar == 180, -1, 0))) + rhs_expr = 0 + for (angle, cos, _) in self.angle_conf: + rhs_expr = z3.If(rvar == angle, cos, rhs_expr) if self.varConditions[stmt.lvar.name] not in (None, True, False): - self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Int(stmt.lvar.name) == rhs_expr)) + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Real(stmt.lvar.name) == rhs_expr)) elif self.varConditions[stmt.lvar.name] is not False: - self.solver.add(z3.Int(stmt.lvar.name) == rhs_expr) + self.solver.add(z3.Real(stmt.lvar.name) == rhs_expr) elif isinstance(stmt, ChironSSA.SinCommand): - rvar = z3.Int(stmt.rvar.name) - rhs_expr = z3.If(rvar == 0, 0, z3.If(rvar == 90, 1, z3.If(rvar == 180, 0, -1))) + rvar = z3.Real(stmt.rvar.name) + # rhs_expr = z3.If(rvar == 0, 0, z3.If(rvar == 90, 1, z3.If(rvar == 180, 0, -1))) + rhs_expr = 0 + for (angle, _, sin) in self.angle_conf: + rhs_expr = z3.If(rvar == angle, sin, rhs_expr) + if self.varConditions[stmt.lvar.name] not in (None, True, False): - self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Int(stmt.lvar.name) == rhs_expr)) + self.solver.add(z3.Implies(self.varConditions[stmt.lvar.name], z3.Real(stmt.lvar.name) == rhs_expr)) elif self.varConditions[stmt.lvar.name] is not False: - self.solver.add(z3.Int(stmt.lvar.name) == rhs_expr) + self.solver.add(z3.Real(stmt.lvar.name) == rhs_expr) elif isinstance(stmt, ChironSSA.MoveCommand): pass @@ -251,10 +266,14 @@ def convertSSAtoSMT(self): self.assume_conditions = z3.Tactic('ctx-simplify').apply(self.assume_conditions).as_expr() def solve(self, inputVars): - self.solver.add(z3.Not(self.assert_conditions)) - self.solver.add(self.angle_conditions) - self.solver.add(self.assume_conditions) + # Uncomment following lines if input variables are restricted to be integers. + # for var in inputVars: + # # should be integer + # varname = var + "$0" + # self.solver_without_cond.add(z3.ToInt(z3.Real(varname)) == z3.Real(varname)) + # self.solver.add(z3.ToInt(z3.Real(varname)) == z3.Real(varname)) + checker_with_assume = z3.Solver() checker_with_assume.add(self.solver_without_cond.assertions()) checker_with_assume.add(self.assume_conditions) @@ -267,6 +286,23 @@ def solve(self, inputVars): print("Cannot determine if unroll bound is sufficient") return + checker_with_angles = z3.Solver() + checker_with_angles.add(self.solver_without_cond.assertions()) + checker_with_angles.add(self.angle_conditions) + checker_with_angles.add(self.assume_conditions) + + angles_check = checker_with_angles.check() + if angles_check == z3.unsat: + print("Angle not in angles.conf for all cases") + return + elif angles_check == z3.unknown: + print("Cannot determine if unroll bound is sufficient") + return + + self.solver.add(z3.Not(self.assert_conditions)) + self.solver.add(self.angle_conditions) + self.solver.add(self.assume_conditions) + sat = self.solver.check() if sat == z3.sat: @@ -282,22 +318,7 @@ def solve(self, inputVars): print(var + " = " + str(solution[var])) elif sat == z3.unsat: - solver_with_angle = z3.Solver() - solver_with_angle.add(self.solver_without_cond.assertions()) - solver_with_angle.add(self.angle_conditions) - sat_angle = solver_with_angle.check() - - # solver_with_assert = z3.Solver() - # solver_with_assert.add(self.solver_without_cond.assertions()) - # solver_with_assert.add(z3.Not(self.assert_conditions)) - # sat_assert = solver_with_assert.check() - - if sat_angle == z3.unsat: - print("Angle not 0, 90, 180, 270 degrees for all cases") - elif sat_angle != z3.unknown: # sat_assert is unsat - print("Condition satisfied for all inputs!") - else: - print("Unknown") + print("Condition satisfied for all inputs!") else: print("Unknown") diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index 08e6ee8..f1e5378 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -218,6 +218,14 @@ def stopTurtle(): help="Unroll bound for the program. Default is 10.", ) + cmdparser.add_argument( + "-aconf", + "--angle-conf", + type=str, + default="", + help="Angle configuration file for BMC.", + ) + args = cmdparser.parse_args() ir = "" @@ -420,6 +428,18 @@ def stopTurtle(): print("\nBounded Model Checking...") unroll_bound = args.unroll_bound + angle_conf = [[0, 1, 0], [90, 0, 1], [180, -1, 0], [270, 0, -1]] + if args.angle_conf: + with open(args.angle_conf, "r") as f: + angle_conf = f.read() + # csv format (angle,cos,sin) + angle_conf = [x.split(",") for x in angle_conf.split("\n") if x] + angle_conf = [ + (int(x[0]), float(x[1]), float(x[2])) for x in angle_conf + ] + + print("Valid angles: ", angle_conf) + if unroll_bound < 1: print("Invalid unroll bound. Exiting...") exit(1) @@ -461,7 +481,7 @@ def stopTurtle(): cfgB.dumpCFG(ssaCfg, 'ssa_cfg') # Saving SSA Form of the program to file ssa_cfg.png print("\nConverting program to SMT-LIB format...\n") - smt = bmc.BMC(ssaCfg) + smt = bmc.BMC(ssaCfg, angle_conf) smt.convertSSAtoSMT() smt.solve(tacGen.getFreeVariables()) print("DONE...") diff --git a/ChironCore/example/example1.tl b/ChironCore/example/example1.tl index 7d15f80..9e64a04 100644 --- a/ChironCore/example/example1.tl +++ b/ChironCore/example/example1.tl @@ -35,4 +35,6 @@ repeat 3 [ :z = :z + 10 ] -penup \ No newline at end of file +penup + +assert :turtleX > 0 diff --git a/ChironCore/turtparse/tlang.g4 b/ChironCore/turtparse/tlang.g4 index e474267..cb5cdec 100644 --- a/ChironCore/turtparse/tlang.g4 +++ b/ChironCore/turtparse/tlang.g4 @@ -95,12 +95,15 @@ AND: '&&'; OR : '||'; NOT: '!' ; -value : NUM +value : NUM | VAR + | FLOAT ; NUM : [0-9]+ ; +FLOAT : NUM '.' NUM ; + VAR : ':'[a-zA-Z_] [a-zA-Z0-9]* ; NAME : [a-zA-Z]+ ; diff --git a/ChironCore/turtparse/tlang.interp b/ChironCore/turtparse/tlang.interp index c0dd5ff..da83104 100644 --- a/ChironCore/turtparse/tlang.interp +++ b/ChironCore/turtparse/tlang.interp @@ -40,6 +40,7 @@ null null null null +null token symbolic names: null @@ -79,6 +80,7 @@ AND OR NOT NUM +FLOAT VAR NAME Whitespace @@ -113,4 +115,4 @@ value atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 42, 205, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 57, 10, 3, 12, 3, 14, 3, 60, 11, 3, 3, 4, 6, 4, 63, 10, 4, 13, 4, 14, 4, 64, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 76, 10, 5, 3, 6, 3, 6, 5, 6, 80, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 5, 9, 112, 10, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 149, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 163, 10, 18, 12, 18, 14, 18, 166, 11, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 188, 10, 23, 3, 23, 3, 23, 3, 23, 3, 23, 7, 23, 194, 10, 23, 12, 23, 14, 23, 197, 11, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 2, 4, 34, 44, 27, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 2, 9, 3, 2, 14, 17, 3, 2, 18, 19, 3, 2, 25, 26, 3, 2, 23, 24, 3, 2, 29, 34, 3, 2, 35, 36, 3, 2, 38, 39, 2, 200, 2, 52, 3, 2, 2, 2, 4, 58, 3, 2, 2, 2, 6, 62, 3, 2, 2, 2, 8, 75, 3, 2, 2, 2, 10, 79, 3, 2, 2, 2, 12, 81, 3, 2, 2, 2, 14, 87, 3, 2, 2, 2, 16, 111, 3, 2, 2, 2, 18, 113, 3, 2, 2, 2, 20, 120, 3, 2, 2, 2, 22, 124, 3, 2, 2, 2, 24, 127, 3, 2, 2, 2, 26, 129, 3, 2, 2, 2, 28, 131, 3, 2, 2, 2, 30, 133, 3, 2, 2, 2, 32, 136, 3, 2, 2, 2, 34, 148, 3, 2, 2, 2, 36, 167, 3, 2, 2, 2, 38, 169, 3, 2, 2, 2, 40, 171, 3, 2, 2, 2, 42, 173, 3, 2, 2, 2, 44, 187, 3, 2, 2, 2, 46, 198, 3, 2, 2, 2, 48, 200, 3, 2, 2, 2, 50, 202, 3, 2, 2, 2, 52, 53, 5, 4, 3, 2, 53, 54, 7, 2, 2, 3, 54, 3, 3, 2, 2, 2, 55, 57, 5, 8, 5, 2, 56, 55, 3, 2, 2, 2, 57, 60, 3, 2, 2, 2, 58, 56, 3, 2, 2, 2, 58, 59, 3, 2, 2, 2, 59, 5, 3, 2, 2, 2, 60, 58, 3, 2, 2, 2, 61, 63, 5, 8, 5, 2, 62, 61, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 62, 3, 2, 2, 2, 64, 65, 3, 2, 2, 2, 65, 7, 3, 2, 2, 2, 66, 76, 5, 20, 11, 2, 67, 76, 5, 10, 6, 2, 68, 76, 5, 16, 9, 2, 69, 76, 5, 22, 12, 2, 70, 76, 5, 26, 14, 2, 71, 76, 5, 18, 10, 2, 72, 76, 5, 28, 15, 2, 73, 76, 5, 30, 16, 2, 74, 76, 5, 32, 17, 2, 75, 66, 3, 2, 2, 2, 75, 67, 3, 2, 2, 2, 75, 68, 3, 2, 2, 2, 75, 69, 3, 2, 2, 2, 75, 70, 3, 2, 2, 2, 75, 71, 3, 2, 2, 2, 75, 72, 3, 2, 2, 2, 75, 73, 3, 2, 2, 2, 75, 74, 3, 2, 2, 2, 76, 9, 3, 2, 2, 2, 77, 80, 5, 12, 7, 2, 78, 80, 5, 14, 8, 2, 79, 77, 3, 2, 2, 2, 79, 78, 3, 2, 2, 2, 80, 11, 3, 2, 2, 2, 81, 82, 7, 3, 2, 2, 82, 83, 5, 44, 23, 2, 83, 84, 7, 4, 2, 2, 84, 85, 5, 6, 4, 2, 85, 86, 7, 5, 2, 2, 86, 13, 3, 2, 2, 2, 87, 88, 7, 3, 2, 2, 88, 89, 5, 44, 23, 2, 89, 90, 7, 4, 2, 2, 90, 91, 5, 6, 4, 2, 91, 92, 7, 5, 2, 2, 92, 93, 7, 6, 2, 2, 93, 94, 7, 4, 2, 2, 94, 95, 5, 6, 4, 2, 95, 96, 7, 5, 2, 2, 96, 15, 3, 2, 2, 2, 97, 98, 7, 7, 2, 2, 98, 99, 5, 50, 26, 2, 99, 100, 7, 4, 2, 2, 100, 101, 5, 6, 4, 2, 101, 102, 7, 5, 2, 2, 102, 112, 3, 2, 2, 2, 103, 104, 7, 8, 2, 2, 104, 105, 7, 38, 2, 2, 105, 106, 7, 7, 2, 2, 106, 107, 5, 50, 26, 2, 107, 108, 7, 4, 2, 2, 108, 109, 5, 6, 4, 2, 109, 110, 7, 5, 2, 2, 110, 112, 3, 2, 2, 2, 111, 97, 3, 2, 2, 2, 111, 103, 3, 2, 2, 2, 112, 17, 3, 2, 2, 2, 113, 114, 7, 9, 2, 2, 114, 115, 7, 10, 2, 2, 115, 116, 5, 34, 18, 2, 116, 117, 7, 11, 2, 2, 117, 118, 5, 34, 18, 2, 118, 119, 7, 12, 2, 2, 119, 19, 3, 2, 2, 2, 120, 121, 7, 39, 2, 2, 121, 122, 7, 13, 2, 2, 122, 123, 5, 34, 18, 2, 123, 21, 3, 2, 2, 2, 124, 125, 5, 24, 13, 2, 125, 126, 5, 34, 18, 2, 126, 23, 3, 2, 2, 2, 127, 128, 9, 2, 2, 2, 128, 25, 3, 2, 2, 2, 129, 130, 9, 3, 2, 2, 130, 27, 3, 2, 2, 2, 131, 132, 7, 20, 2, 2, 132, 29, 3, 2, 2, 2, 133, 134, 7, 21, 2, 2, 134, 135, 5, 44, 23, 2, 135, 31, 3, 2, 2, 2, 136, 137, 7, 22, 2, 2, 137, 138, 5, 44, 23, 2, 138, 33, 3, 2, 2, 2, 139, 140, 8, 18, 1, 2, 140, 141, 5, 42, 22, 2, 141, 142, 5, 34, 18, 8, 142, 149, 3, 2, 2, 2, 143, 149, 5, 50, 26, 2, 144, 145, 7, 10, 2, 2, 145, 146, 5, 34, 18, 2, 146, 147, 7, 12, 2, 2, 147, 149, 3, 2, 2, 2, 148, 139, 3, 2, 2, 2, 148, 143, 3, 2, 2, 2, 148, 144, 3, 2, 2, 2, 149, 164, 3, 2, 2, 2, 150, 151, 12, 7, 2, 2, 151, 152, 5, 36, 19, 2, 152, 153, 5, 34, 18, 8, 153, 163, 3, 2, 2, 2, 154, 155, 12, 6, 2, 2, 155, 156, 5, 38, 20, 2, 156, 157, 5, 34, 18, 7, 157, 163, 3, 2, 2, 2, 158, 159, 12, 5, 2, 2, 159, 160, 5, 40, 21, 2, 160, 161, 5, 34, 18, 6, 161, 163, 3, 2, 2, 2, 162, 150, 3, 2, 2, 2, 162, 154, 3, 2, 2, 2, 162, 158, 3, 2, 2, 2, 163, 166, 3, 2, 2, 2, 164, 162, 3, 2, 2, 2, 164, 165, 3, 2, 2, 2, 165, 35, 3, 2, 2, 2, 166, 164, 3, 2, 2, 2, 167, 168, 9, 4, 2, 2, 168, 37, 3, 2, 2, 2, 169, 170, 9, 5, 2, 2, 170, 39, 3, 2, 2, 2, 171, 172, 7, 27, 2, 2, 172, 41, 3, 2, 2, 2, 173, 174, 7, 24, 2, 2, 174, 43, 3, 2, 2, 2, 175, 176, 8, 23, 1, 2, 176, 177, 7, 37, 2, 2, 177, 188, 5, 44, 23, 7, 178, 179, 5, 34, 18, 2, 179, 180, 5, 46, 24, 2, 180, 181, 5, 34, 18, 2, 181, 188, 3, 2, 2, 2, 182, 188, 7, 28, 2, 2, 183, 184, 7, 10, 2, 2, 184, 185, 5, 44, 23, 2, 185, 186, 7, 12, 2, 2, 186, 188, 3, 2, 2, 2, 187, 175, 3, 2, 2, 2, 187, 178, 3, 2, 2, 2, 187, 182, 3, 2, 2, 2, 187, 183, 3, 2, 2, 2, 188, 195, 3, 2, 2, 2, 189, 190, 12, 5, 2, 2, 190, 191, 5, 48, 25, 2, 191, 192, 5, 44, 23, 6, 192, 194, 3, 2, 2, 2, 193, 189, 3, 2, 2, 2, 194, 197, 3, 2, 2, 2, 195, 193, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196, 45, 3, 2, 2, 2, 197, 195, 3, 2, 2, 2, 198, 199, 9, 6, 2, 2, 199, 47, 3, 2, 2, 2, 200, 201, 9, 7, 2, 2, 201, 49, 3, 2, 2, 2, 202, 203, 9, 8, 2, 2, 203, 51, 3, 2, 2, 2, 12, 58, 64, 75, 79, 111, 148, 162, 164, 187, 195] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 43, 205, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 57, 10, 3, 12, 3, 14, 3, 60, 11, 3, 3, 4, 6, 4, 63, 10, 4, 13, 4, 14, 4, 64, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 76, 10, 5, 3, 6, 3, 6, 5, 6, 80, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 5, 9, 112, 10, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 149, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 163, 10, 18, 12, 18, 14, 18, 166, 11, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 188, 10, 23, 3, 23, 3, 23, 3, 23, 3, 23, 7, 23, 194, 10, 23, 12, 23, 14, 23, 197, 11, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 2, 4, 34, 44, 27, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 2, 9, 3, 2, 14, 17, 3, 2, 18, 19, 3, 2, 25, 26, 3, 2, 23, 24, 3, 2, 29, 34, 3, 2, 35, 36, 3, 2, 38, 40, 2, 200, 2, 52, 3, 2, 2, 2, 4, 58, 3, 2, 2, 2, 6, 62, 3, 2, 2, 2, 8, 75, 3, 2, 2, 2, 10, 79, 3, 2, 2, 2, 12, 81, 3, 2, 2, 2, 14, 87, 3, 2, 2, 2, 16, 111, 3, 2, 2, 2, 18, 113, 3, 2, 2, 2, 20, 120, 3, 2, 2, 2, 22, 124, 3, 2, 2, 2, 24, 127, 3, 2, 2, 2, 26, 129, 3, 2, 2, 2, 28, 131, 3, 2, 2, 2, 30, 133, 3, 2, 2, 2, 32, 136, 3, 2, 2, 2, 34, 148, 3, 2, 2, 2, 36, 167, 3, 2, 2, 2, 38, 169, 3, 2, 2, 2, 40, 171, 3, 2, 2, 2, 42, 173, 3, 2, 2, 2, 44, 187, 3, 2, 2, 2, 46, 198, 3, 2, 2, 2, 48, 200, 3, 2, 2, 2, 50, 202, 3, 2, 2, 2, 52, 53, 5, 4, 3, 2, 53, 54, 7, 2, 2, 3, 54, 3, 3, 2, 2, 2, 55, 57, 5, 8, 5, 2, 56, 55, 3, 2, 2, 2, 57, 60, 3, 2, 2, 2, 58, 56, 3, 2, 2, 2, 58, 59, 3, 2, 2, 2, 59, 5, 3, 2, 2, 2, 60, 58, 3, 2, 2, 2, 61, 63, 5, 8, 5, 2, 62, 61, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 62, 3, 2, 2, 2, 64, 65, 3, 2, 2, 2, 65, 7, 3, 2, 2, 2, 66, 76, 5, 20, 11, 2, 67, 76, 5, 10, 6, 2, 68, 76, 5, 16, 9, 2, 69, 76, 5, 22, 12, 2, 70, 76, 5, 26, 14, 2, 71, 76, 5, 18, 10, 2, 72, 76, 5, 28, 15, 2, 73, 76, 5, 30, 16, 2, 74, 76, 5, 32, 17, 2, 75, 66, 3, 2, 2, 2, 75, 67, 3, 2, 2, 2, 75, 68, 3, 2, 2, 2, 75, 69, 3, 2, 2, 2, 75, 70, 3, 2, 2, 2, 75, 71, 3, 2, 2, 2, 75, 72, 3, 2, 2, 2, 75, 73, 3, 2, 2, 2, 75, 74, 3, 2, 2, 2, 76, 9, 3, 2, 2, 2, 77, 80, 5, 12, 7, 2, 78, 80, 5, 14, 8, 2, 79, 77, 3, 2, 2, 2, 79, 78, 3, 2, 2, 2, 80, 11, 3, 2, 2, 2, 81, 82, 7, 3, 2, 2, 82, 83, 5, 44, 23, 2, 83, 84, 7, 4, 2, 2, 84, 85, 5, 6, 4, 2, 85, 86, 7, 5, 2, 2, 86, 13, 3, 2, 2, 2, 87, 88, 7, 3, 2, 2, 88, 89, 5, 44, 23, 2, 89, 90, 7, 4, 2, 2, 90, 91, 5, 6, 4, 2, 91, 92, 7, 5, 2, 2, 92, 93, 7, 6, 2, 2, 93, 94, 7, 4, 2, 2, 94, 95, 5, 6, 4, 2, 95, 96, 7, 5, 2, 2, 96, 15, 3, 2, 2, 2, 97, 98, 7, 7, 2, 2, 98, 99, 5, 50, 26, 2, 99, 100, 7, 4, 2, 2, 100, 101, 5, 6, 4, 2, 101, 102, 7, 5, 2, 2, 102, 112, 3, 2, 2, 2, 103, 104, 7, 8, 2, 2, 104, 105, 7, 38, 2, 2, 105, 106, 7, 7, 2, 2, 106, 107, 5, 50, 26, 2, 107, 108, 7, 4, 2, 2, 108, 109, 5, 6, 4, 2, 109, 110, 7, 5, 2, 2, 110, 112, 3, 2, 2, 2, 111, 97, 3, 2, 2, 2, 111, 103, 3, 2, 2, 2, 112, 17, 3, 2, 2, 2, 113, 114, 7, 9, 2, 2, 114, 115, 7, 10, 2, 2, 115, 116, 5, 34, 18, 2, 116, 117, 7, 11, 2, 2, 117, 118, 5, 34, 18, 2, 118, 119, 7, 12, 2, 2, 119, 19, 3, 2, 2, 2, 120, 121, 7, 40, 2, 2, 121, 122, 7, 13, 2, 2, 122, 123, 5, 34, 18, 2, 123, 21, 3, 2, 2, 2, 124, 125, 5, 24, 13, 2, 125, 126, 5, 34, 18, 2, 126, 23, 3, 2, 2, 2, 127, 128, 9, 2, 2, 2, 128, 25, 3, 2, 2, 2, 129, 130, 9, 3, 2, 2, 130, 27, 3, 2, 2, 2, 131, 132, 7, 20, 2, 2, 132, 29, 3, 2, 2, 2, 133, 134, 7, 21, 2, 2, 134, 135, 5, 44, 23, 2, 135, 31, 3, 2, 2, 2, 136, 137, 7, 22, 2, 2, 137, 138, 5, 44, 23, 2, 138, 33, 3, 2, 2, 2, 139, 140, 8, 18, 1, 2, 140, 141, 5, 42, 22, 2, 141, 142, 5, 34, 18, 8, 142, 149, 3, 2, 2, 2, 143, 149, 5, 50, 26, 2, 144, 145, 7, 10, 2, 2, 145, 146, 5, 34, 18, 2, 146, 147, 7, 12, 2, 2, 147, 149, 3, 2, 2, 2, 148, 139, 3, 2, 2, 2, 148, 143, 3, 2, 2, 2, 148, 144, 3, 2, 2, 2, 149, 164, 3, 2, 2, 2, 150, 151, 12, 7, 2, 2, 151, 152, 5, 36, 19, 2, 152, 153, 5, 34, 18, 8, 153, 163, 3, 2, 2, 2, 154, 155, 12, 6, 2, 2, 155, 156, 5, 38, 20, 2, 156, 157, 5, 34, 18, 7, 157, 163, 3, 2, 2, 2, 158, 159, 12, 5, 2, 2, 159, 160, 5, 40, 21, 2, 160, 161, 5, 34, 18, 6, 161, 163, 3, 2, 2, 2, 162, 150, 3, 2, 2, 2, 162, 154, 3, 2, 2, 2, 162, 158, 3, 2, 2, 2, 163, 166, 3, 2, 2, 2, 164, 162, 3, 2, 2, 2, 164, 165, 3, 2, 2, 2, 165, 35, 3, 2, 2, 2, 166, 164, 3, 2, 2, 2, 167, 168, 9, 4, 2, 2, 168, 37, 3, 2, 2, 2, 169, 170, 9, 5, 2, 2, 170, 39, 3, 2, 2, 2, 171, 172, 7, 27, 2, 2, 172, 41, 3, 2, 2, 2, 173, 174, 7, 24, 2, 2, 174, 43, 3, 2, 2, 2, 175, 176, 8, 23, 1, 2, 176, 177, 7, 37, 2, 2, 177, 188, 5, 44, 23, 7, 178, 179, 5, 34, 18, 2, 179, 180, 5, 46, 24, 2, 180, 181, 5, 34, 18, 2, 181, 188, 3, 2, 2, 2, 182, 188, 7, 28, 2, 2, 183, 184, 7, 10, 2, 2, 184, 185, 5, 44, 23, 2, 185, 186, 7, 12, 2, 2, 186, 188, 3, 2, 2, 2, 187, 175, 3, 2, 2, 2, 187, 178, 3, 2, 2, 2, 187, 182, 3, 2, 2, 2, 187, 183, 3, 2, 2, 2, 188, 195, 3, 2, 2, 2, 189, 190, 12, 5, 2, 2, 190, 191, 5, 48, 25, 2, 191, 192, 5, 44, 23, 6, 192, 194, 3, 2, 2, 2, 193, 189, 3, 2, 2, 2, 194, 197, 3, 2, 2, 2, 195, 193, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196, 45, 3, 2, 2, 2, 197, 195, 3, 2, 2, 2, 198, 199, 9, 6, 2, 2, 199, 47, 3, 2, 2, 2, 200, 201, 9, 7, 2, 2, 201, 49, 3, 2, 2, 2, 202, 203, 9, 8, 2, 2, 203, 51, 3, 2, 2, 2, 12, 58, 64, 75, 79, 111, 148, 162, 164, 187, 195] \ No newline at end of file diff --git a/ChironCore/turtparse/tlang.tokens b/ChironCore/turtparse/tlang.tokens index 08759dc..355acdc 100644 --- a/ChironCore/turtparse/tlang.tokens +++ b/ChironCore/turtparse/tlang.tokens @@ -34,10 +34,11 @@ AND=33 OR=34 NOT=35 NUM=36 -VAR=37 -NAME=38 -Whitespace=39 -Comment=40 +FLOAT=37 +VAR=38 +NAME=39 +Whitespace=40 +Comment=41 'if'=1 '['=2 ']'=3 diff --git a/ChironCore/turtparse/tlangLexer.interp b/ChironCore/turtparse/tlangLexer.interp index 9a991d9..957a8c5 100644 --- a/ChironCore/turtparse/tlangLexer.interp +++ b/ChironCore/turtparse/tlangLexer.interp @@ -40,6 +40,7 @@ null null null null +null token symbolic names: null @@ -79,6 +80,7 @@ AND OR NOT NUM +FLOAT VAR NAME Whitespace @@ -121,6 +123,7 @@ AND OR NOT NUM +FLOAT VAR NAME Whitespace @@ -134,4 +137,4 @@ mode names: DEFAULT_MODE atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 42, 264, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 6, 37, 230, 10, 37, 13, 37, 14, 37, 231, 3, 38, 3, 38, 3, 38, 7, 38, 237, 10, 38, 12, 38, 14, 38, 240, 11, 38, 3, 39, 6, 39, 243, 10, 39, 13, 39, 14, 39, 244, 3, 40, 6, 40, 248, 10, 40, 13, 40, 14, 40, 249, 3, 40, 3, 40, 3, 41, 3, 41, 3, 41, 3, 41, 7, 41, 258, 10, 41, 12, 41, 14, 41, 261, 11, 41, 3, 41, 3, 41, 2, 2, 42, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 81, 42, 3, 2, 8, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 268, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 3, 83, 3, 2, 2, 2, 5, 86, 3, 2, 2, 2, 7, 88, 3, 2, 2, 2, 9, 90, 3, 2, 2, 2, 11, 95, 3, 2, 2, 2, 13, 102, 3, 2, 2, 2, 15, 110, 3, 2, 2, 2, 17, 115, 3, 2, 2, 2, 19, 117, 3, 2, 2, 2, 21, 119, 3, 2, 2, 2, 23, 121, 3, 2, 2, 2, 25, 123, 3, 2, 2, 2, 27, 131, 3, 2, 2, 2, 29, 140, 3, 2, 2, 2, 31, 145, 3, 2, 2, 2, 33, 151, 3, 2, 2, 2, 35, 157, 3, 2, 2, 2, 37, 165, 3, 2, 2, 2, 39, 171, 3, 2, 2, 2, 41, 178, 3, 2, 2, 2, 43, 185, 3, 2, 2, 2, 45, 187, 3, 2, 2, 2, 47, 189, 3, 2, 2, 2, 49, 191, 3, 2, 2, 2, 51, 193, 3, 2, 2, 2, 53, 195, 3, 2, 2, 2, 55, 204, 3, 2, 2, 2, 57, 206, 3, 2, 2, 2, 59, 208, 3, 2, 2, 2, 61, 211, 3, 2, 2, 2, 63, 214, 3, 2, 2, 2, 65, 217, 3, 2, 2, 2, 67, 220, 3, 2, 2, 2, 69, 223, 3, 2, 2, 2, 71, 226, 3, 2, 2, 2, 73, 229, 3, 2, 2, 2, 75, 233, 3, 2, 2, 2, 77, 242, 3, 2, 2, 2, 79, 247, 3, 2, 2, 2, 81, 253, 3, 2, 2, 2, 83, 84, 7, 107, 2, 2, 84, 85, 7, 104, 2, 2, 85, 4, 3, 2, 2, 2, 86, 87, 7, 93, 2, 2, 87, 6, 3, 2, 2, 2, 88, 89, 7, 95, 2, 2, 89, 8, 3, 2, 2, 2, 90, 91, 7, 103, 2, 2, 91, 92, 7, 110, 2, 2, 92, 93, 7, 117, 2, 2, 93, 94, 7, 103, 2, 2, 94, 10, 3, 2, 2, 2, 95, 96, 7, 116, 2, 2, 96, 97, 7, 103, 2, 2, 97, 98, 7, 114, 2, 2, 98, 99, 7, 103, 2, 2, 99, 100, 7, 99, 2, 2, 100, 101, 7, 118, 2, 2, 101, 12, 3, 2, 2, 2, 102, 103, 7, 66, 2, 2, 103, 104, 7, 119, 2, 2, 104, 105, 7, 112, 2, 2, 105, 106, 7, 116, 2, 2, 106, 107, 7, 113, 2, 2, 107, 108, 7, 110, 2, 2, 108, 109, 7, 110, 2, 2, 109, 14, 3, 2, 2, 2, 110, 111, 7, 105, 2, 2, 111, 112, 7, 113, 2, 2, 112, 113, 7, 118, 2, 2, 113, 114, 7, 113, 2, 2, 114, 16, 3, 2, 2, 2, 115, 116, 7, 42, 2, 2, 116, 18, 3, 2, 2, 2, 117, 118, 7, 46, 2, 2, 118, 20, 3, 2, 2, 2, 119, 120, 7, 43, 2, 2, 120, 22, 3, 2, 2, 2, 121, 122, 7, 63, 2, 2, 122, 24, 3, 2, 2, 2, 123, 124, 7, 104, 2, 2, 124, 125, 7, 113, 2, 2, 125, 126, 7, 116, 2, 2, 126, 127, 7, 121, 2, 2, 127, 128, 7, 99, 2, 2, 128, 129, 7, 116, 2, 2, 129, 130, 7, 102, 2, 2, 130, 26, 3, 2, 2, 2, 131, 132, 7, 100, 2, 2, 132, 133, 7, 99, 2, 2, 133, 134, 7, 101, 2, 2, 134, 135, 7, 109, 2, 2, 135, 136, 7, 121, 2, 2, 136, 137, 7, 99, 2, 2, 137, 138, 7, 116, 2, 2, 138, 139, 7, 102, 2, 2, 139, 28, 3, 2, 2, 2, 140, 141, 7, 110, 2, 2, 141, 142, 7, 103, 2, 2, 142, 143, 7, 104, 2, 2, 143, 144, 7, 118, 2, 2, 144, 30, 3, 2, 2, 2, 145, 146, 7, 116, 2, 2, 146, 147, 7, 107, 2, 2, 147, 148, 7, 105, 2, 2, 148, 149, 7, 106, 2, 2, 149, 150, 7, 118, 2, 2, 150, 32, 3, 2, 2, 2, 151, 152, 7, 114, 2, 2, 152, 153, 7, 103, 2, 2, 153, 154, 7, 112, 2, 2, 154, 155, 7, 119, 2, 2, 155, 156, 7, 114, 2, 2, 156, 34, 3, 2, 2, 2, 157, 158, 7, 114, 2, 2, 158, 159, 7, 103, 2, 2, 159, 160, 7, 112, 2, 2, 160, 161, 7, 102, 2, 2, 161, 162, 7, 113, 2, 2, 162, 163, 7, 121, 2, 2, 163, 164, 7, 112, 2, 2, 164, 36, 3, 2, 2, 2, 165, 166, 7, 114, 2, 2, 166, 167, 7, 99, 2, 2, 167, 168, 7, 119, 2, 2, 168, 169, 7, 117, 2, 2, 169, 170, 7, 103, 2, 2, 170, 38, 3, 2, 2, 2, 171, 172, 7, 99, 2, 2, 172, 173, 7, 117, 2, 2, 173, 174, 7, 117, 2, 2, 174, 175, 7, 103, 2, 2, 175, 176, 7, 116, 2, 2, 176, 177, 7, 118, 2, 2, 177, 40, 3, 2, 2, 2, 178, 179, 7, 99, 2, 2, 179, 180, 7, 117, 2, 2, 180, 181, 7, 117, 2, 2, 181, 182, 7, 119, 2, 2, 182, 183, 7, 111, 2, 2, 183, 184, 7, 103, 2, 2, 184, 42, 3, 2, 2, 2, 185, 186, 7, 45, 2, 2, 186, 44, 3, 2, 2, 2, 187, 188, 7, 47, 2, 2, 188, 46, 3, 2, 2, 2, 189, 190, 7, 44, 2, 2, 190, 48, 3, 2, 2, 2, 191, 192, 7, 49, 2, 2, 192, 50, 3, 2, 2, 2, 193, 194, 7, 39, 2, 2, 194, 52, 3, 2, 2, 2, 195, 196, 7, 114, 2, 2, 196, 197, 7, 103, 2, 2, 197, 198, 7, 112, 2, 2, 198, 199, 7, 102, 2, 2, 199, 200, 7, 113, 2, 2, 200, 201, 7, 121, 2, 2, 201, 202, 7, 112, 2, 2, 202, 203, 7, 65, 2, 2, 203, 54, 3, 2, 2, 2, 204, 205, 7, 62, 2, 2, 205, 56, 3, 2, 2, 2, 206, 207, 7, 64, 2, 2, 207, 58, 3, 2, 2, 2, 208, 209, 7, 63, 2, 2, 209, 210, 7, 63, 2, 2, 210, 60, 3, 2, 2, 2, 211, 212, 7, 35, 2, 2, 212, 213, 7, 63, 2, 2, 213, 62, 3, 2, 2, 2, 214, 215, 7, 62, 2, 2, 215, 216, 7, 63, 2, 2, 216, 64, 3, 2, 2, 2, 217, 218, 7, 64, 2, 2, 218, 219, 7, 63, 2, 2, 219, 66, 3, 2, 2, 2, 220, 221, 7, 40, 2, 2, 221, 222, 7, 40, 2, 2, 222, 68, 3, 2, 2, 2, 223, 224, 7, 126, 2, 2, 224, 225, 7, 126, 2, 2, 225, 70, 3, 2, 2, 2, 226, 227, 7, 35, 2, 2, 227, 72, 3, 2, 2, 2, 228, 230, 9, 2, 2, 2, 229, 228, 3, 2, 2, 2, 230, 231, 3, 2, 2, 2, 231, 229, 3, 2, 2, 2, 231, 232, 3, 2, 2, 2, 232, 74, 3, 2, 2, 2, 233, 234, 7, 60, 2, 2, 234, 238, 9, 3, 2, 2, 235, 237, 9, 4, 2, 2, 236, 235, 3, 2, 2, 2, 237, 240, 3, 2, 2, 2, 238, 236, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 76, 3, 2, 2, 2, 240, 238, 3, 2, 2, 2, 241, 243, 9, 5, 2, 2, 242, 241, 3, 2, 2, 2, 243, 244, 3, 2, 2, 2, 244, 242, 3, 2, 2, 2, 244, 245, 3, 2, 2, 2, 245, 78, 3, 2, 2, 2, 246, 248, 9, 6, 2, 2, 247, 246, 3, 2, 2, 2, 248, 249, 3, 2, 2, 2, 249, 247, 3, 2, 2, 2, 249, 250, 3, 2, 2, 2, 250, 251, 3, 2, 2, 2, 251, 252, 8, 40, 2, 2, 252, 80, 3, 2, 2, 2, 253, 254, 7, 49, 2, 2, 254, 255, 7, 49, 2, 2, 255, 259, 3, 2, 2, 2, 256, 258, 10, 7, 2, 2, 257, 256, 3, 2, 2, 2, 258, 261, 3, 2, 2, 2, 259, 257, 3, 2, 2, 2, 259, 260, 3, 2, 2, 2, 260, 262, 3, 2, 2, 2, 261, 259, 3, 2, 2, 2, 262, 263, 8, 41, 2, 2, 263, 82, 3, 2, 2, 2, 8, 2, 231, 238, 244, 249, 259, 3, 8, 2, 2] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 43, 270, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 6, 37, 232, 10, 37, 13, 37, 14, 37, 233, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 7, 39, 243, 10, 39, 12, 39, 14, 39, 246, 11, 39, 3, 40, 6, 40, 249, 10, 40, 13, 40, 14, 40, 250, 3, 41, 6, 41, 254, 10, 41, 13, 41, 14, 41, 255, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 42, 7, 42, 264, 10, 42, 12, 42, 14, 42, 267, 11, 42, 3, 42, 3, 42, 2, 2, 43, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 81, 42, 83, 43, 3, 2, 8, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 274, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2, 83, 3, 2, 2, 2, 3, 85, 3, 2, 2, 2, 5, 88, 3, 2, 2, 2, 7, 90, 3, 2, 2, 2, 9, 92, 3, 2, 2, 2, 11, 97, 3, 2, 2, 2, 13, 104, 3, 2, 2, 2, 15, 112, 3, 2, 2, 2, 17, 117, 3, 2, 2, 2, 19, 119, 3, 2, 2, 2, 21, 121, 3, 2, 2, 2, 23, 123, 3, 2, 2, 2, 25, 125, 3, 2, 2, 2, 27, 133, 3, 2, 2, 2, 29, 142, 3, 2, 2, 2, 31, 147, 3, 2, 2, 2, 33, 153, 3, 2, 2, 2, 35, 159, 3, 2, 2, 2, 37, 167, 3, 2, 2, 2, 39, 173, 3, 2, 2, 2, 41, 180, 3, 2, 2, 2, 43, 187, 3, 2, 2, 2, 45, 189, 3, 2, 2, 2, 47, 191, 3, 2, 2, 2, 49, 193, 3, 2, 2, 2, 51, 195, 3, 2, 2, 2, 53, 197, 3, 2, 2, 2, 55, 206, 3, 2, 2, 2, 57, 208, 3, 2, 2, 2, 59, 210, 3, 2, 2, 2, 61, 213, 3, 2, 2, 2, 63, 216, 3, 2, 2, 2, 65, 219, 3, 2, 2, 2, 67, 222, 3, 2, 2, 2, 69, 225, 3, 2, 2, 2, 71, 228, 3, 2, 2, 2, 73, 231, 3, 2, 2, 2, 75, 235, 3, 2, 2, 2, 77, 239, 3, 2, 2, 2, 79, 248, 3, 2, 2, 2, 81, 253, 3, 2, 2, 2, 83, 259, 3, 2, 2, 2, 85, 86, 7, 107, 2, 2, 86, 87, 7, 104, 2, 2, 87, 4, 3, 2, 2, 2, 88, 89, 7, 93, 2, 2, 89, 6, 3, 2, 2, 2, 90, 91, 7, 95, 2, 2, 91, 8, 3, 2, 2, 2, 92, 93, 7, 103, 2, 2, 93, 94, 7, 110, 2, 2, 94, 95, 7, 117, 2, 2, 95, 96, 7, 103, 2, 2, 96, 10, 3, 2, 2, 2, 97, 98, 7, 116, 2, 2, 98, 99, 7, 103, 2, 2, 99, 100, 7, 114, 2, 2, 100, 101, 7, 103, 2, 2, 101, 102, 7, 99, 2, 2, 102, 103, 7, 118, 2, 2, 103, 12, 3, 2, 2, 2, 104, 105, 7, 66, 2, 2, 105, 106, 7, 119, 2, 2, 106, 107, 7, 112, 2, 2, 107, 108, 7, 116, 2, 2, 108, 109, 7, 113, 2, 2, 109, 110, 7, 110, 2, 2, 110, 111, 7, 110, 2, 2, 111, 14, 3, 2, 2, 2, 112, 113, 7, 105, 2, 2, 113, 114, 7, 113, 2, 2, 114, 115, 7, 118, 2, 2, 115, 116, 7, 113, 2, 2, 116, 16, 3, 2, 2, 2, 117, 118, 7, 42, 2, 2, 118, 18, 3, 2, 2, 2, 119, 120, 7, 46, 2, 2, 120, 20, 3, 2, 2, 2, 121, 122, 7, 43, 2, 2, 122, 22, 3, 2, 2, 2, 123, 124, 7, 63, 2, 2, 124, 24, 3, 2, 2, 2, 125, 126, 7, 104, 2, 2, 126, 127, 7, 113, 2, 2, 127, 128, 7, 116, 2, 2, 128, 129, 7, 121, 2, 2, 129, 130, 7, 99, 2, 2, 130, 131, 7, 116, 2, 2, 131, 132, 7, 102, 2, 2, 132, 26, 3, 2, 2, 2, 133, 134, 7, 100, 2, 2, 134, 135, 7, 99, 2, 2, 135, 136, 7, 101, 2, 2, 136, 137, 7, 109, 2, 2, 137, 138, 7, 121, 2, 2, 138, 139, 7, 99, 2, 2, 139, 140, 7, 116, 2, 2, 140, 141, 7, 102, 2, 2, 141, 28, 3, 2, 2, 2, 142, 143, 7, 110, 2, 2, 143, 144, 7, 103, 2, 2, 144, 145, 7, 104, 2, 2, 145, 146, 7, 118, 2, 2, 146, 30, 3, 2, 2, 2, 147, 148, 7, 116, 2, 2, 148, 149, 7, 107, 2, 2, 149, 150, 7, 105, 2, 2, 150, 151, 7, 106, 2, 2, 151, 152, 7, 118, 2, 2, 152, 32, 3, 2, 2, 2, 153, 154, 7, 114, 2, 2, 154, 155, 7, 103, 2, 2, 155, 156, 7, 112, 2, 2, 156, 157, 7, 119, 2, 2, 157, 158, 7, 114, 2, 2, 158, 34, 3, 2, 2, 2, 159, 160, 7, 114, 2, 2, 160, 161, 7, 103, 2, 2, 161, 162, 7, 112, 2, 2, 162, 163, 7, 102, 2, 2, 163, 164, 7, 113, 2, 2, 164, 165, 7, 121, 2, 2, 165, 166, 7, 112, 2, 2, 166, 36, 3, 2, 2, 2, 167, 168, 7, 114, 2, 2, 168, 169, 7, 99, 2, 2, 169, 170, 7, 119, 2, 2, 170, 171, 7, 117, 2, 2, 171, 172, 7, 103, 2, 2, 172, 38, 3, 2, 2, 2, 173, 174, 7, 99, 2, 2, 174, 175, 7, 117, 2, 2, 175, 176, 7, 117, 2, 2, 176, 177, 7, 103, 2, 2, 177, 178, 7, 116, 2, 2, 178, 179, 7, 118, 2, 2, 179, 40, 3, 2, 2, 2, 180, 181, 7, 99, 2, 2, 181, 182, 7, 117, 2, 2, 182, 183, 7, 117, 2, 2, 183, 184, 7, 119, 2, 2, 184, 185, 7, 111, 2, 2, 185, 186, 7, 103, 2, 2, 186, 42, 3, 2, 2, 2, 187, 188, 7, 45, 2, 2, 188, 44, 3, 2, 2, 2, 189, 190, 7, 47, 2, 2, 190, 46, 3, 2, 2, 2, 191, 192, 7, 44, 2, 2, 192, 48, 3, 2, 2, 2, 193, 194, 7, 49, 2, 2, 194, 50, 3, 2, 2, 2, 195, 196, 7, 39, 2, 2, 196, 52, 3, 2, 2, 2, 197, 198, 7, 114, 2, 2, 198, 199, 7, 103, 2, 2, 199, 200, 7, 112, 2, 2, 200, 201, 7, 102, 2, 2, 201, 202, 7, 113, 2, 2, 202, 203, 7, 121, 2, 2, 203, 204, 7, 112, 2, 2, 204, 205, 7, 65, 2, 2, 205, 54, 3, 2, 2, 2, 206, 207, 7, 62, 2, 2, 207, 56, 3, 2, 2, 2, 208, 209, 7, 64, 2, 2, 209, 58, 3, 2, 2, 2, 210, 211, 7, 63, 2, 2, 211, 212, 7, 63, 2, 2, 212, 60, 3, 2, 2, 2, 213, 214, 7, 35, 2, 2, 214, 215, 7, 63, 2, 2, 215, 62, 3, 2, 2, 2, 216, 217, 7, 62, 2, 2, 217, 218, 7, 63, 2, 2, 218, 64, 3, 2, 2, 2, 219, 220, 7, 64, 2, 2, 220, 221, 7, 63, 2, 2, 221, 66, 3, 2, 2, 2, 222, 223, 7, 40, 2, 2, 223, 224, 7, 40, 2, 2, 224, 68, 3, 2, 2, 2, 225, 226, 7, 126, 2, 2, 226, 227, 7, 126, 2, 2, 227, 70, 3, 2, 2, 2, 228, 229, 7, 35, 2, 2, 229, 72, 3, 2, 2, 2, 230, 232, 9, 2, 2, 2, 231, 230, 3, 2, 2, 2, 232, 233, 3, 2, 2, 2, 233, 231, 3, 2, 2, 2, 233, 234, 3, 2, 2, 2, 234, 74, 3, 2, 2, 2, 235, 236, 5, 73, 37, 2, 236, 237, 7, 48, 2, 2, 237, 238, 5, 73, 37, 2, 238, 76, 3, 2, 2, 2, 239, 240, 7, 60, 2, 2, 240, 244, 9, 3, 2, 2, 241, 243, 9, 4, 2, 2, 242, 241, 3, 2, 2, 2, 243, 246, 3, 2, 2, 2, 244, 242, 3, 2, 2, 2, 244, 245, 3, 2, 2, 2, 245, 78, 3, 2, 2, 2, 246, 244, 3, 2, 2, 2, 247, 249, 9, 5, 2, 2, 248, 247, 3, 2, 2, 2, 249, 250, 3, 2, 2, 2, 250, 248, 3, 2, 2, 2, 250, 251, 3, 2, 2, 2, 251, 80, 3, 2, 2, 2, 252, 254, 9, 6, 2, 2, 253, 252, 3, 2, 2, 2, 254, 255, 3, 2, 2, 2, 255, 253, 3, 2, 2, 2, 255, 256, 3, 2, 2, 2, 256, 257, 3, 2, 2, 2, 257, 258, 8, 41, 2, 2, 258, 82, 3, 2, 2, 2, 259, 260, 7, 49, 2, 2, 260, 261, 7, 49, 2, 2, 261, 265, 3, 2, 2, 2, 262, 264, 10, 7, 2, 2, 263, 262, 3, 2, 2, 2, 264, 267, 3, 2, 2, 2, 265, 263, 3, 2, 2, 2, 265, 266, 3, 2, 2, 2, 266, 268, 3, 2, 2, 2, 267, 265, 3, 2, 2, 2, 268, 269, 8, 42, 2, 2, 269, 84, 3, 2, 2, 2, 8, 2, 233, 244, 250, 255, 265, 3, 8, 2, 2] \ No newline at end of file diff --git a/ChironCore/turtparse/tlangLexer.py b/ChironCore/turtparse/tlangLexer.py index 900a5ae..e8d8c8a 100644 --- a/ChironCore/turtparse/tlangLexer.py +++ b/ChironCore/turtparse/tlangLexer.py @@ -8,111 +8,113 @@ def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2*") - buf.write("\u0108\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2+") + buf.write("\u010e\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") buf.write("\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r") buf.write("\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23") buf.write("\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30") buf.write("\4\31\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36") buf.write("\t\36\4\37\t\37\4 \t \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%") - buf.write("\4&\t&\4\'\t\'\4(\t(\4)\t)\3\2\3\2\3\2\3\3\3\3\3\4\3\4") - buf.write("\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3") - buf.write("\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\t\3\t") - buf.write("\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r") - buf.write("\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17") - buf.write("\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21") - buf.write("\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22") - buf.write("\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24") - buf.write("\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25") - buf.write("\3\26\3\26\3\27\3\27\3\30\3\30\3\31\3\31\3\32\3\32\3\33") - buf.write("\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\35") - buf.write("\3\35\3\36\3\36\3\36\3\37\3\37\3\37\3 \3 \3 \3!\3!\3!") - buf.write("\3\"\3\"\3\"\3#\3#\3#\3$\3$\3%\6%\u00e6\n%\r%\16%\u00e7") - buf.write("\3&\3&\3&\7&\u00ed\n&\f&\16&\u00f0\13&\3\'\6\'\u00f3\n") - buf.write("\'\r\'\16\'\u00f4\3(\6(\u00f8\n(\r(\16(\u00f9\3(\3(\3") - buf.write(")\3)\3)\3)\7)\u0102\n)\f)\16)\u0105\13)\3)\3)\2\2*\3\3") - buf.write("\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16") - buf.write("\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61") - buf.write("\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*") - buf.write("\3\2\b\3\2\62;\5\2C\\aac|\5\2\62;C\\c|\4\2C\\c|\5\2\13") - buf.write("\f\17\17\"\"\4\2\f\f\17\17\2\u010c\2\3\3\2\2\2\2\5\3\2") - buf.write("\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2") - buf.write("\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2") - buf.write("\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37") - buf.write("\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2") - buf.write("\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2") - buf.write("\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2") - buf.write("\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2") - buf.write("\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2") - buf.write("\2\2\2O\3\2\2\2\2Q\3\2\2\2\3S\3\2\2\2\5V\3\2\2\2\7X\3") - buf.write("\2\2\2\tZ\3\2\2\2\13_\3\2\2\2\rf\3\2\2\2\17n\3\2\2\2\21") - buf.write("s\3\2\2\2\23u\3\2\2\2\25w\3\2\2\2\27y\3\2\2\2\31{\3\2") - buf.write("\2\2\33\u0083\3\2\2\2\35\u008c\3\2\2\2\37\u0091\3\2\2") - buf.write("\2!\u0097\3\2\2\2#\u009d\3\2\2\2%\u00a5\3\2\2\2\'\u00ab") - buf.write("\3\2\2\2)\u00b2\3\2\2\2+\u00b9\3\2\2\2-\u00bb\3\2\2\2") - buf.write("/\u00bd\3\2\2\2\61\u00bf\3\2\2\2\63\u00c1\3\2\2\2\65\u00c3") - buf.write("\3\2\2\2\67\u00cc\3\2\2\29\u00ce\3\2\2\2;\u00d0\3\2\2") - buf.write("\2=\u00d3\3\2\2\2?\u00d6\3\2\2\2A\u00d9\3\2\2\2C\u00dc") - buf.write("\3\2\2\2E\u00df\3\2\2\2G\u00e2\3\2\2\2I\u00e5\3\2\2\2") - buf.write("K\u00e9\3\2\2\2M\u00f2\3\2\2\2O\u00f7\3\2\2\2Q\u00fd\3") - buf.write("\2\2\2ST\7k\2\2TU\7h\2\2U\4\3\2\2\2VW\7]\2\2W\6\3\2\2") - buf.write("\2XY\7_\2\2Y\b\3\2\2\2Z[\7g\2\2[\\\7n\2\2\\]\7u\2\2]^") - buf.write("\7g\2\2^\n\3\2\2\2_`\7t\2\2`a\7g\2\2ab\7r\2\2bc\7g\2\2") - buf.write("cd\7c\2\2de\7v\2\2e\f\3\2\2\2fg\7B\2\2gh\7w\2\2hi\7p\2") - buf.write("\2ij\7t\2\2jk\7q\2\2kl\7n\2\2lm\7n\2\2m\16\3\2\2\2no\7") - buf.write("i\2\2op\7q\2\2pq\7v\2\2qr\7q\2\2r\20\3\2\2\2st\7*\2\2") - buf.write("t\22\3\2\2\2uv\7.\2\2v\24\3\2\2\2wx\7+\2\2x\26\3\2\2\2") - buf.write("yz\7?\2\2z\30\3\2\2\2{|\7h\2\2|}\7q\2\2}~\7t\2\2~\177") - buf.write("\7y\2\2\177\u0080\7c\2\2\u0080\u0081\7t\2\2\u0081\u0082") - buf.write("\7f\2\2\u0082\32\3\2\2\2\u0083\u0084\7d\2\2\u0084\u0085") - buf.write("\7c\2\2\u0085\u0086\7e\2\2\u0086\u0087\7m\2\2\u0087\u0088") - buf.write("\7y\2\2\u0088\u0089\7c\2\2\u0089\u008a\7t\2\2\u008a\u008b") - buf.write("\7f\2\2\u008b\34\3\2\2\2\u008c\u008d\7n\2\2\u008d\u008e") - buf.write("\7g\2\2\u008e\u008f\7h\2\2\u008f\u0090\7v\2\2\u0090\36") - buf.write("\3\2\2\2\u0091\u0092\7t\2\2\u0092\u0093\7k\2\2\u0093\u0094") - buf.write("\7i\2\2\u0094\u0095\7j\2\2\u0095\u0096\7v\2\2\u0096 \3") - buf.write("\2\2\2\u0097\u0098\7r\2\2\u0098\u0099\7g\2\2\u0099\u009a") - buf.write("\7p\2\2\u009a\u009b\7w\2\2\u009b\u009c\7r\2\2\u009c\"") - buf.write("\3\2\2\2\u009d\u009e\7r\2\2\u009e\u009f\7g\2\2\u009f\u00a0") - buf.write("\7p\2\2\u00a0\u00a1\7f\2\2\u00a1\u00a2\7q\2\2\u00a2\u00a3") - buf.write("\7y\2\2\u00a3\u00a4\7p\2\2\u00a4$\3\2\2\2\u00a5\u00a6") - buf.write("\7r\2\2\u00a6\u00a7\7c\2\2\u00a7\u00a8\7w\2\2\u00a8\u00a9") - buf.write("\7u\2\2\u00a9\u00aa\7g\2\2\u00aa&\3\2\2\2\u00ab\u00ac") - buf.write("\7c\2\2\u00ac\u00ad\7u\2\2\u00ad\u00ae\7u\2\2\u00ae\u00af") - buf.write("\7g\2\2\u00af\u00b0\7t\2\2\u00b0\u00b1\7v\2\2\u00b1(\3") - buf.write("\2\2\2\u00b2\u00b3\7c\2\2\u00b3\u00b4\7u\2\2\u00b4\u00b5") - buf.write("\7u\2\2\u00b5\u00b6\7w\2\2\u00b6\u00b7\7o\2\2\u00b7\u00b8") - buf.write("\7g\2\2\u00b8*\3\2\2\2\u00b9\u00ba\7-\2\2\u00ba,\3\2\2") - buf.write("\2\u00bb\u00bc\7/\2\2\u00bc.\3\2\2\2\u00bd\u00be\7,\2") - buf.write("\2\u00be\60\3\2\2\2\u00bf\u00c0\7\61\2\2\u00c0\62\3\2") - buf.write("\2\2\u00c1\u00c2\7\'\2\2\u00c2\64\3\2\2\2\u00c3\u00c4") - buf.write("\7r\2\2\u00c4\u00c5\7g\2\2\u00c5\u00c6\7p\2\2\u00c6\u00c7") - buf.write("\7f\2\2\u00c7\u00c8\7q\2\2\u00c8\u00c9\7y\2\2\u00c9\u00ca") - buf.write("\7p\2\2\u00ca\u00cb\7A\2\2\u00cb\66\3\2\2\2\u00cc\u00cd") - buf.write("\7>\2\2\u00cd8\3\2\2\2\u00ce\u00cf\7@\2\2\u00cf:\3\2\2") - buf.write("\2\u00d0\u00d1\7?\2\2\u00d1\u00d2\7?\2\2\u00d2<\3\2\2") - buf.write("\2\u00d3\u00d4\7#\2\2\u00d4\u00d5\7?\2\2\u00d5>\3\2\2") - buf.write("\2\u00d6\u00d7\7>\2\2\u00d7\u00d8\7?\2\2\u00d8@\3\2\2") - buf.write("\2\u00d9\u00da\7@\2\2\u00da\u00db\7?\2\2\u00dbB\3\2\2") - buf.write("\2\u00dc\u00dd\7(\2\2\u00dd\u00de\7(\2\2\u00deD\3\2\2") - buf.write("\2\u00df\u00e0\7~\2\2\u00e0\u00e1\7~\2\2\u00e1F\3\2\2") - buf.write("\2\u00e2\u00e3\7#\2\2\u00e3H\3\2\2\2\u00e4\u00e6\t\2\2") - buf.write("\2\u00e5\u00e4\3\2\2\2\u00e6\u00e7\3\2\2\2\u00e7\u00e5") - buf.write("\3\2\2\2\u00e7\u00e8\3\2\2\2\u00e8J\3\2\2\2\u00e9\u00ea") - buf.write("\7<\2\2\u00ea\u00ee\t\3\2\2\u00eb\u00ed\t\4\2\2\u00ec") - buf.write("\u00eb\3\2\2\2\u00ed\u00f0\3\2\2\2\u00ee\u00ec\3\2\2\2") - buf.write("\u00ee\u00ef\3\2\2\2\u00efL\3\2\2\2\u00f0\u00ee\3\2\2") - buf.write("\2\u00f1\u00f3\t\5\2\2\u00f2\u00f1\3\2\2\2\u00f3\u00f4") - buf.write("\3\2\2\2\u00f4\u00f2\3\2\2\2\u00f4\u00f5\3\2\2\2\u00f5") - buf.write("N\3\2\2\2\u00f6\u00f8\t\6\2\2\u00f7\u00f6\3\2\2\2\u00f8") - buf.write("\u00f9\3\2\2\2\u00f9\u00f7\3\2\2\2\u00f9\u00fa\3\2\2\2") - buf.write("\u00fa\u00fb\3\2\2\2\u00fb\u00fc\b(\2\2\u00fcP\3\2\2\2") - buf.write("\u00fd\u00fe\7\61\2\2\u00fe\u00ff\7\61\2\2\u00ff\u0103") - buf.write("\3\2\2\2\u0100\u0102\n\7\2\2\u0101\u0100\3\2\2\2\u0102") - buf.write("\u0105\3\2\2\2\u0103\u0101\3\2\2\2\u0103\u0104\3\2\2\2") - buf.write("\u0104\u0106\3\2\2\2\u0105\u0103\3\2\2\2\u0106\u0107\b") - buf.write(")\2\2\u0107R\3\2\2\2\b\2\u00e7\u00ee\u00f4\u00f9\u0103") - buf.write("\3\b\2\2") + buf.write("\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\3\2\3\2\3\2\3\3\3\3\3") + buf.write("\4\3\4\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6") + buf.write("\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3") + buf.write("\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3") + buf.write("\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16") + buf.write("\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20") + buf.write("\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22") + buf.write("\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24") + buf.write("\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25") + buf.write("\3\25\3\26\3\26\3\27\3\27\3\30\3\30\3\31\3\31\3\32\3\32") + buf.write("\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34") + buf.write("\3\35\3\35\3\36\3\36\3\36\3\37\3\37\3\37\3 \3 \3 \3!\3") + buf.write("!\3!\3\"\3\"\3\"\3#\3#\3#\3$\3$\3%\6%\u00e8\n%\r%\16%") + buf.write("\u00e9\3&\3&\3&\3&\3\'\3\'\3\'\7\'\u00f3\n\'\f\'\16\'") + buf.write("\u00f6\13\'\3(\6(\u00f9\n(\r(\16(\u00fa\3)\6)\u00fe\n") + buf.write(")\r)\16)\u00ff\3)\3)\3*\3*\3*\3*\7*\u0108\n*\f*\16*\u010b") + buf.write("\13*\3*\3*\2\2+\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23") + buf.write("\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25") + buf.write(")\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A") + buf.write("\"C#E$G%I&K\'M(O)Q*S+\3\2\b\3\2\62;\5\2C\\aac|\5\2\62") + buf.write(";C\\c|\4\2C\\c|\5\2\13\f\17\17\"\"\4\2\f\f\17\17\2\u0112") + buf.write("\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13") + buf.write("\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3") + buf.write("\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2") + buf.write("\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2") + buf.write("%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2") + buf.write("\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67") + buf.write("\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2") + buf.write("A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2") + buf.write("\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2") + buf.write("\2\3U\3\2\2\2\5X\3\2\2\2\7Z\3\2\2\2\t\\\3\2\2\2\13a\3") + buf.write("\2\2\2\rh\3\2\2\2\17p\3\2\2\2\21u\3\2\2\2\23w\3\2\2\2") + buf.write("\25y\3\2\2\2\27{\3\2\2\2\31}\3\2\2\2\33\u0085\3\2\2\2") + buf.write("\35\u008e\3\2\2\2\37\u0093\3\2\2\2!\u0099\3\2\2\2#\u009f") + buf.write("\3\2\2\2%\u00a7\3\2\2\2\'\u00ad\3\2\2\2)\u00b4\3\2\2\2") + buf.write("+\u00bb\3\2\2\2-\u00bd\3\2\2\2/\u00bf\3\2\2\2\61\u00c1") + buf.write("\3\2\2\2\63\u00c3\3\2\2\2\65\u00c5\3\2\2\2\67\u00ce\3") + buf.write("\2\2\29\u00d0\3\2\2\2;\u00d2\3\2\2\2=\u00d5\3\2\2\2?\u00d8") + buf.write("\3\2\2\2A\u00db\3\2\2\2C\u00de\3\2\2\2E\u00e1\3\2\2\2") + buf.write("G\u00e4\3\2\2\2I\u00e7\3\2\2\2K\u00eb\3\2\2\2M\u00ef\3") + buf.write("\2\2\2O\u00f8\3\2\2\2Q\u00fd\3\2\2\2S\u0103\3\2\2\2UV") + buf.write("\7k\2\2VW\7h\2\2W\4\3\2\2\2XY\7]\2\2Y\6\3\2\2\2Z[\7_\2") + buf.write("\2[\b\3\2\2\2\\]\7g\2\2]^\7n\2\2^_\7u\2\2_`\7g\2\2`\n") + buf.write("\3\2\2\2ab\7t\2\2bc\7g\2\2cd\7r\2\2de\7g\2\2ef\7c\2\2") + buf.write("fg\7v\2\2g\f\3\2\2\2hi\7B\2\2ij\7w\2\2jk\7p\2\2kl\7t\2") + buf.write("\2lm\7q\2\2mn\7n\2\2no\7n\2\2o\16\3\2\2\2pq\7i\2\2qr\7") + buf.write("q\2\2rs\7v\2\2st\7q\2\2t\20\3\2\2\2uv\7*\2\2v\22\3\2\2") + buf.write("\2wx\7.\2\2x\24\3\2\2\2yz\7+\2\2z\26\3\2\2\2{|\7?\2\2") + buf.write("|\30\3\2\2\2}~\7h\2\2~\177\7q\2\2\177\u0080\7t\2\2\u0080") + buf.write("\u0081\7y\2\2\u0081\u0082\7c\2\2\u0082\u0083\7t\2\2\u0083") + buf.write("\u0084\7f\2\2\u0084\32\3\2\2\2\u0085\u0086\7d\2\2\u0086") + buf.write("\u0087\7c\2\2\u0087\u0088\7e\2\2\u0088\u0089\7m\2\2\u0089") + buf.write("\u008a\7y\2\2\u008a\u008b\7c\2\2\u008b\u008c\7t\2\2\u008c") + buf.write("\u008d\7f\2\2\u008d\34\3\2\2\2\u008e\u008f\7n\2\2\u008f") + buf.write("\u0090\7g\2\2\u0090\u0091\7h\2\2\u0091\u0092\7v\2\2\u0092") + buf.write("\36\3\2\2\2\u0093\u0094\7t\2\2\u0094\u0095\7k\2\2\u0095") + buf.write("\u0096\7i\2\2\u0096\u0097\7j\2\2\u0097\u0098\7v\2\2\u0098") + buf.write(" \3\2\2\2\u0099\u009a\7r\2\2\u009a\u009b\7g\2\2\u009b") + buf.write("\u009c\7p\2\2\u009c\u009d\7w\2\2\u009d\u009e\7r\2\2\u009e") + buf.write("\"\3\2\2\2\u009f\u00a0\7r\2\2\u00a0\u00a1\7g\2\2\u00a1") + buf.write("\u00a2\7p\2\2\u00a2\u00a3\7f\2\2\u00a3\u00a4\7q\2\2\u00a4") + buf.write("\u00a5\7y\2\2\u00a5\u00a6\7p\2\2\u00a6$\3\2\2\2\u00a7") + buf.write("\u00a8\7r\2\2\u00a8\u00a9\7c\2\2\u00a9\u00aa\7w\2\2\u00aa") + buf.write("\u00ab\7u\2\2\u00ab\u00ac\7g\2\2\u00ac&\3\2\2\2\u00ad") + buf.write("\u00ae\7c\2\2\u00ae\u00af\7u\2\2\u00af\u00b0\7u\2\2\u00b0") + buf.write("\u00b1\7g\2\2\u00b1\u00b2\7t\2\2\u00b2\u00b3\7v\2\2\u00b3") + buf.write("(\3\2\2\2\u00b4\u00b5\7c\2\2\u00b5\u00b6\7u\2\2\u00b6") + buf.write("\u00b7\7u\2\2\u00b7\u00b8\7w\2\2\u00b8\u00b9\7o\2\2\u00b9") + buf.write("\u00ba\7g\2\2\u00ba*\3\2\2\2\u00bb\u00bc\7-\2\2\u00bc") + buf.write(",\3\2\2\2\u00bd\u00be\7/\2\2\u00be.\3\2\2\2\u00bf\u00c0") + buf.write("\7,\2\2\u00c0\60\3\2\2\2\u00c1\u00c2\7\61\2\2\u00c2\62") + buf.write("\3\2\2\2\u00c3\u00c4\7\'\2\2\u00c4\64\3\2\2\2\u00c5\u00c6") + buf.write("\7r\2\2\u00c6\u00c7\7g\2\2\u00c7\u00c8\7p\2\2\u00c8\u00c9") + buf.write("\7f\2\2\u00c9\u00ca\7q\2\2\u00ca\u00cb\7y\2\2\u00cb\u00cc") + buf.write("\7p\2\2\u00cc\u00cd\7A\2\2\u00cd\66\3\2\2\2\u00ce\u00cf") + buf.write("\7>\2\2\u00cf8\3\2\2\2\u00d0\u00d1\7@\2\2\u00d1:\3\2\2") + buf.write("\2\u00d2\u00d3\7?\2\2\u00d3\u00d4\7?\2\2\u00d4<\3\2\2") + buf.write("\2\u00d5\u00d6\7#\2\2\u00d6\u00d7\7?\2\2\u00d7>\3\2\2") + buf.write("\2\u00d8\u00d9\7>\2\2\u00d9\u00da\7?\2\2\u00da@\3\2\2") + buf.write("\2\u00db\u00dc\7@\2\2\u00dc\u00dd\7?\2\2\u00ddB\3\2\2") + buf.write("\2\u00de\u00df\7(\2\2\u00df\u00e0\7(\2\2\u00e0D\3\2\2") + buf.write("\2\u00e1\u00e2\7~\2\2\u00e2\u00e3\7~\2\2\u00e3F\3\2\2") + buf.write("\2\u00e4\u00e5\7#\2\2\u00e5H\3\2\2\2\u00e6\u00e8\t\2\2") + buf.write("\2\u00e7\u00e6\3\2\2\2\u00e8\u00e9\3\2\2\2\u00e9\u00e7") + buf.write("\3\2\2\2\u00e9\u00ea\3\2\2\2\u00eaJ\3\2\2\2\u00eb\u00ec") + buf.write("\5I%\2\u00ec\u00ed\7\60\2\2\u00ed\u00ee\5I%\2\u00eeL\3") + buf.write("\2\2\2\u00ef\u00f0\7<\2\2\u00f0\u00f4\t\3\2\2\u00f1\u00f3") + buf.write("\t\4\2\2\u00f2\u00f1\3\2\2\2\u00f3\u00f6\3\2\2\2\u00f4") + buf.write("\u00f2\3\2\2\2\u00f4\u00f5\3\2\2\2\u00f5N\3\2\2\2\u00f6") + buf.write("\u00f4\3\2\2\2\u00f7\u00f9\t\5\2\2\u00f8\u00f7\3\2\2\2") + buf.write("\u00f9\u00fa\3\2\2\2\u00fa\u00f8\3\2\2\2\u00fa\u00fb\3") + buf.write("\2\2\2\u00fbP\3\2\2\2\u00fc\u00fe\t\6\2\2\u00fd\u00fc") + buf.write("\3\2\2\2\u00fe\u00ff\3\2\2\2\u00ff\u00fd\3\2\2\2\u00ff") + buf.write("\u0100\3\2\2\2\u0100\u0101\3\2\2\2\u0101\u0102\b)\2\2") + buf.write("\u0102R\3\2\2\2\u0103\u0104\7\61\2\2\u0104\u0105\7\61") + buf.write("\2\2\u0105\u0109\3\2\2\2\u0106\u0108\n\7\2\2\u0107\u0106") + buf.write("\3\2\2\2\u0108\u010b\3\2\2\2\u0109\u0107\3\2\2\2\u0109") + buf.write("\u010a\3\2\2\2\u010a\u010c\3\2\2\2\u010b\u0109\3\2\2\2") + buf.write("\u010c\u010d\b*\2\2\u010dT\3\2\2\2\b\2\u00e9\u00f4\u00fa") + buf.write("\u00ff\u0109\3\b\2\2") return buf.getvalue() @@ -158,10 +160,11 @@ class tlangLexer(Lexer): OR = 34 NOT = 35 NUM = 36 - VAR = 37 - NAME = 38 - Whitespace = 39 - Comment = 40 + FLOAT = 37 + VAR = 38 + NAME = 39 + Whitespace = 40 + Comment = 41 channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] @@ -176,15 +179,15 @@ class tlangLexer(Lexer): symbolicNames = [ "", "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", - "EQ", "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", "VAR", - "NAME", "Whitespace", "Comment" ] + "EQ", "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", "FLOAT", + "VAR", "NAME", "Whitespace", "Comment" ] ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", "T__17", "T__18", "T__19", "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", - "VAR", "NAME", "Whitespace", "Comment" ] + "FLOAT", "VAR", "NAME", "Whitespace", "Comment" ] grammarFileName = "tlang.g4" diff --git a/ChironCore/turtparse/tlangLexer.tokens b/ChironCore/turtparse/tlangLexer.tokens index 08759dc..355acdc 100644 --- a/ChironCore/turtparse/tlangLexer.tokens +++ b/ChironCore/turtparse/tlangLexer.tokens @@ -34,10 +34,11 @@ AND=33 OR=34 NOT=35 NUM=36 -VAR=37 -NAME=38 -Whitespace=39 -Comment=40 +FLOAT=37 +VAR=38 +NAME=39 +Whitespace=40 +Comment=41 'if'=1 '['=2 ']'=3 diff --git a/ChironCore/turtparse/tlangParser.py b/ChironCore/turtparse/tlangParser.py index d289bda..fee85dd 100644 --- a/ChironCore/turtparse/tlangParser.py +++ b/ChironCore/turtparse/tlangParser.py @@ -8,7 +8,7 @@ def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3*") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3+") buf.write("\u00cd\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16") buf.write("\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23\t\23") @@ -29,11 +29,11 @@ def serializedATN(): buf.write("\27\f\27\16\27\u00c5\13\27\3\30\3\30\3\31\3\31\3\32\3") buf.write("\32\3\32\2\4\",\33\2\4\6\b\n\f\16\20\22\24\26\30\32\34") buf.write("\36 \"$&(*,.\60\62\2\t\3\2\16\21\3\2\22\23\3\2\31\32\3") - buf.write("\2\27\30\3\2\35\"\3\2#$\3\2&\'\2\u00c8\2\64\3\2\2\2\4") - buf.write(":\3\2\2\2\6>\3\2\2\2\bK\3\2\2\2\nO\3\2\2\2\fQ\3\2\2\2") - buf.write("\16W\3\2\2\2\20o\3\2\2\2\22q\3\2\2\2\24x\3\2\2\2\26|\3") - buf.write("\2\2\2\30\177\3\2\2\2\32\u0081\3\2\2\2\34\u0083\3\2\2") - buf.write("\2\36\u0085\3\2\2\2 \u0088\3\2\2\2\"\u0094\3\2\2\2$\u00a7") + buf.write("\2\27\30\3\2\35\"\3\2#$\3\2&(\2\u00c8\2\64\3\2\2\2\4:") + buf.write("\3\2\2\2\6>\3\2\2\2\bK\3\2\2\2\nO\3\2\2\2\fQ\3\2\2\2\16") + buf.write("W\3\2\2\2\20o\3\2\2\2\22q\3\2\2\2\24x\3\2\2\2\26|\3\2") + buf.write("\2\2\30\177\3\2\2\2\32\u0081\3\2\2\2\34\u0083\3\2\2\2") + buf.write("\36\u0085\3\2\2\2 \u0088\3\2\2\2\"\u0094\3\2\2\2$\u00a7") buf.write("\3\2\2\2&\u00a9\3\2\2\2(\u00ab\3\2\2\2*\u00ad\3\2\2\2") buf.write(",\u00bb\3\2\2\2.\u00c6\3\2\2\2\60\u00c8\3\2\2\2\62\u00ca") buf.write("\3\2\2\2\64\65\5\4\3\2\65\66\7\2\2\3\66\3\3\2\2\2\679") @@ -52,7 +52,7 @@ def serializedATN(): buf.write("jk\5\62\32\2kl\7\4\2\2lm\5\6\4\2mn\7\5\2\2np\3\2\2\2o") buf.write("a\3\2\2\2og\3\2\2\2p\21\3\2\2\2qr\7\t\2\2rs\7\n\2\2st") buf.write("\5\"\22\2tu\7\13\2\2uv\5\"\22\2vw\7\f\2\2w\23\3\2\2\2") - buf.write("xy\7\'\2\2yz\7\r\2\2z{\5\"\22\2{\25\3\2\2\2|}\5\30\r\2") + buf.write("xy\7(\2\2yz\7\r\2\2z{\5\"\22\2{\25\3\2\2\2|}\5\30\r\2") buf.write("}~\5\"\22\2~\27\3\2\2\2\177\u0080\t\2\2\2\u0080\31\3\2") buf.write("\2\2\u0081\u0082\t\3\2\2\u0082\33\3\2\2\2\u0083\u0084") buf.write("\7\24\2\2\u0084\35\3\2\2\2\u0085\u0086\7\25\2\2\u0086") @@ -113,8 +113,8 @@ class tlangParser ( Parser ): "", "", "", "", "", "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", "GTE", - "AND", "OR", "NOT", "NUM", "VAR", "NAME", "Whitespace", - "Comment" ] + "AND", "OR", "NOT", "NUM", "FLOAT", "VAR", "NAME", + "Whitespace", "Comment" ] RULE_start = 0 RULE_instruction_list = 1 @@ -187,10 +187,11 @@ class tlangParser ( Parser ): OR=34 NOT=35 NUM=36 - VAR=37 - NAME=38 - Whitespace=39 - Comment=40 + FLOAT=37 + VAR=38 + NAME=39 + Whitespace=40 + Comment=41 def __init__(self, input:TokenStream, output:TextIO = sys.stdout): super().__init__(input, output) @@ -1222,7 +1223,7 @@ def expression(self, _p:int=0): self.state = 139 self.expression(6) pass - elif token in [tlangParser.NUM, tlangParser.VAR]: + elif token in [tlangParser.NUM, tlangParser.FLOAT, tlangParser.VAR]: localctx = tlangParser.ValueExprContext(self, localctx) self._ctx = localctx _prevctx = localctx @@ -1716,6 +1717,9 @@ def NUM(self): def VAR(self): return self.getToken(tlangParser.VAR, 0) + def FLOAT(self): + return self.getToken(tlangParser.FLOAT, 0) + def getRuleIndex(self): return tlangParser.RULE_value @@ -1737,7 +1741,7 @@ def value(self): self.enterOuterAlt(localctx, 1) self.state = 200 _la = self._input.LA(1) - if not(_la==tlangParser.NUM or _la==tlangParser.VAR): + if not((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << tlangParser.NUM) | (1 << tlangParser.FLOAT) | (1 << tlangParser.VAR))) != 0)): self._errHandler.recoverInline(self) else: self._errHandler.reportMatch(self) From 4e2d8a258caa94756c0c80ae3682e01aeb7dcc09 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 8 Apr 2025 00:14:34 +0530 Subject: [PATCH 46/53] linear time algorithm for dominator tree --- ChironCore/cfg/ChironCFG.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ChironCore/cfg/ChironCFG.py b/ChironCore/cfg/ChironCFG.py index f502411..7bcb3c5 100644 --- a/ChironCore/cfg/ChironCFG.py +++ b/ChironCore/cfg/ChironCFG.py @@ -110,11 +110,11 @@ def compute_dominance(self): self.idom = nx.immediate_dominators(self.nxgraph, entry) self.df = nx.dominance_frontiers(self.nxgraph, entry) - for i in self.nodes(): - for j in self.nodes(): - if i != j and self.idom[j] == i: - self.dominator_tree[i].append(j) + # build the dominator tree + for i in self.nodes(): + if i != entry: + self.dominator_tree[self.idom[i]].append(i) def get_topological_order(self): return list(nx.topological_sort(self.nxgraph)) From 7b4dbb2946847f9f9b941f444cd5e7f0075459dd Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Thu, 10 Apr 2025 16:44:14 +0530 Subject: [PATCH 47/53] cleanup --- ChironCore/ChironAST/builder.py | 1 - ChironCore/example/amogh.tl | 15 --------------- 2 files changed, 16 deletions(-) delete mode 100644 ChironCore/example/amogh.tl diff --git a/ChironCore/ChironAST/builder.py b/ChironCore/ChironAST/builder.py index 8769aae..80ce294 100644 --- a/ChironCore/ChironAST/builder.py +++ b/ChironCore/ChironAST/builder.py @@ -151,7 +151,6 @@ def visitValue(self, ctx:tlangParser.ValueContext): if ctx.NUM(): return ChironAST.Num(ctx.NUM().getText()) elif ctx.FLOAT(): - print("returning ", ctx.FLOAT().getText()) return ChironAST.Num(ctx.FLOAT().getText()) elif ctx.VAR(): return ChironAST.Var(ctx.VAR().getText()) diff --git a/ChironCore/example/amogh.tl b/ChironCore/example/amogh.tl deleted file mode 100644 index 3cee916..0000000 --- a/ChironCore/example/amogh.tl +++ /dev/null @@ -1,15 +0,0 @@ -@unroll 5 -repeat :a [ - forward 10 - if (:a < 2) [ - :y = 3 - ] -] -repeat :a [ - forward 10 - if (:a < 2) [ - :y = 3 - ] -] - -assert :turtleX <= 1 && :turtleX >= -1 && :turtleY <= 1 && :turtleY >= -1 From 7f5057a98ba62ce5521dea17d369fdcee932421e Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Thu, 17 Apr 2025 04:24:10 +0530 Subject: [PATCH 48/53] added description of bmc --- ChironCore/bmc_examples/bmc1.tl | 7 +++++++ ChironCore/bmc_examples/bmc2.tl | 16 ++++++++++++++++ ChironCore/bmc_examples/bmc3.tl | 26 ++++++++++++++++++++++++++ ChironCore/bmc_examples/bmc4.tl | 14 ++++++++++++++ ChironCore/bmc_examples/bmc5.tl | 6 ++++++ ChironCore/bmc_examples/bmc6.tl | 7 +++++++ ChironCore/bmc_examples/bmc7.tl | 26 ++++++++++++++++++++++++++ 7 files changed, 102 insertions(+) create mode 100644 ChironCore/bmc_examples/bmc1.tl create mode 100644 ChironCore/bmc_examples/bmc2.tl create mode 100644 ChironCore/bmc_examples/bmc3.tl create mode 100644 ChironCore/bmc_examples/bmc4.tl create mode 100644 ChironCore/bmc_examples/bmc5.tl create mode 100644 ChironCore/bmc_examples/bmc6.tl create mode 100644 ChironCore/bmc_examples/bmc7.tl diff --git a/ChironCore/bmc_examples/bmc1.tl b/ChironCore/bmc_examples/bmc1.tl new file mode 100644 index 0000000..73cee31 --- /dev/null +++ b/ChironCore/bmc_examples/bmc1.tl @@ -0,0 +1,7 @@ +// inputs: :x, :y, :z + +:t = :x + 2*:y + 3*:z + :x * :w * :u +:z = :x + :w + + +assert (:x + 100 < :y) && (:x + 200 > :y) && !(:x >= 0) && (:x * :y < -:x) && (:t > 0) diff --git a/ChironCore/bmc_examples/bmc2.tl b/ChironCore/bmc_examples/bmc2.tl new file mode 100644 index 0000000..515cea2 --- /dev/null +++ b/ChironCore/bmc_examples/bmc2.tl @@ -0,0 +1,16 @@ +:t = 1 +// assume :x > 0 +repeat 2 [ + :t = :t * :x + assert :t > 0 +] +:s = 5 * :x +:z = :t + :s + 2 +// assert :z >= -5 + + +// cant do the following +// if (b > 0) [ // :a is not defined earlier +// :a = 1 +// ] +// forward :a diff --git a/ChironCore/bmc_examples/bmc3.tl b/ChironCore/bmc_examples/bmc3.tl new file mode 100644 index 0000000..ed0607a --- /dev/null +++ b/ChironCore/bmc_examples/bmc3.tl @@ -0,0 +1,26 @@ +:p = 1 + +repeat 5 [ + :t = :t * :x +] + +:q = 1 +repeat 4 [ + :q = :q * :x +] + +:r = 1 +repeat 7 [ + :r = :r * :x +] + +:s = 1 + +repeat :o [ + :s = :s * :x + :o = :o - 1 +] + +:z = 2*:p - 3*:q + 5*:r - 7*:s +assert :z < -10000 + diff --git a/ChironCore/bmc_examples/bmc4.tl b/ChironCore/bmc_examples/bmc4.tl new file mode 100644 index 0000000..8e52372 --- /dev/null +++ b/ChironCore/bmc_examples/bmc4.tl @@ -0,0 +1,14 @@ +:a = -1 +:y = 0 +if (:a > 0) [ + :x = :y + 2 +] +if (:a > 1) [ + :x = :y + 3 +] +goto (:x, :y) +assert :turtleX == 2 && :turtleY == 0 +right :x +assert :x > 0 +assert :turtleX > 0 + diff --git a/ChironCore/bmc_examples/bmc5.tl b/ChironCore/bmc_examples/bmc5.tl new file mode 100644 index 0000000..380a234 --- /dev/null +++ b/ChironCore/bmc_examples/bmc5.tl @@ -0,0 +1,6 @@ +forward 10 +left 90 +right 90 +assume :x > 0 +forward :x +assert :turtleX*:turtleX + :turtleY*:turtleY <= 100 diff --git a/ChironCore/bmc_examples/bmc6.tl b/ChironCore/bmc_examples/bmc6.tl new file mode 100644 index 0000000..b58b255 --- /dev/null +++ b/ChironCore/bmc_examples/bmc6.tl @@ -0,0 +1,7 @@ +assume :a < 0 +if (:b > 0) [ + :a = 1 + assert :a == 1 +] +forward :a +assert :turtleX > 0 diff --git a/ChironCore/bmc_examples/bmc7.tl b/ChironCore/bmc_examples/bmc7.tl new file mode 100644 index 0000000..4bcc2cb --- /dev/null +++ b/ChironCore/bmc_examples/bmc7.tl @@ -0,0 +1,26 @@ +// left 90 // valid +// assert 1 > 0 // true + +// left 45 // invalid +// assert 1 > 0 // true + +// left 90 // valid +// assert 1 < 0 // flase + +// left 45 // invalid +// assert 1 < 0 // flase + +// repeat 3 [ +// left 90 +// ] + +forward 10 +// assume :turtleX <= 5 +assert :turtleX == 10 + +@unroll 50 repeat :turtleX [ + :x = :x + 1 +] + +assert :x <= 100 + From 9fb040df5232126a501d5266a05464b3ded6e253 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Thu, 17 Apr 2025 04:27:32 +0530 Subject: [PATCH 49/53] added BMC.md --- BMC.md | 97 +++++++++++++ ChironCore/bmc.py | 6 +- ChironCore/chiron.py | 18 ++- ChironCore/example/assignmentBMC.tl | 7 - ChironCore/example/bmc_tc1.tl | 16 --- ChironCore/example/bmc_tc2.tl | 25 ---- ChironCore/example/bmc_tc3.tl | 13 -- ChironCore/example/exm.tl | 6 - ChironCore/example/exm2.tl | 7 - ChironCore/example/move.tl | 17 --- ChironCore/example/move1.tl | 1 - ChironCore/unrolled_code.tl | 207 +++++++++++++++++++--------- README.md | 10 +- 13 files changed, 258 insertions(+), 172 deletions(-) create mode 100644 BMC.md delete mode 100644 ChironCore/example/assignmentBMC.tl delete mode 100644 ChironCore/example/bmc_tc1.tl delete mode 100644 ChironCore/example/bmc_tc2.tl delete mode 100644 ChironCore/example/bmc_tc3.tl delete mode 100644 ChironCore/example/exm.tl delete mode 100644 ChironCore/example/exm2.tl delete mode 100644 ChironCore/example/move.tl delete mode 100644 ChironCore/example/move1.tl diff --git a/BMC.md b/BMC.md new file mode 100644 index 0000000..3e7bff5 --- /dev/null +++ b/BMC.md @@ -0,0 +1,97 @@ +# Bounded Model Checker (BMC) of Chiron + +## Introduction + +A Bounded Model Checker (BMC) engine is a verification tool used to check the satisfiability of a condition within a given bound without actually running the code. It systematically explores all possible states of a system up to a specified depth to detect errors. + +The BMC engine works by encoding the system's behavior and the properties to be verified into a logical formula. This formula is then solved using a SAT (Satisfiability) solver. If the solver finds a solution within the bounds, it indicates a counterexample that demonstrates a violation of the property being checked. If no solution is found within the given bound, the system is considered correct up to the bounds. + +### What makes BMC interesting + +The BMC engine provides an automated approach to verify the correctness of complex systems. Unlike traditional testing, which relies on specific test cases, BMC explores all possible states within a given bound, ensuring thorough coverage. This makes it particularly effective in uncovering subtle bugs that might be missed by conventional methods. + +The use of SAT solvers to encode and solve logical formulas demonstrates the power of combining formal methods with computational tools. The ability to detect counterexamples and provide concrete scenarios where a property fails is invaluable for debugging and improving system reliability. + +Moreover, BMC's ability to handle constraints, conditions, and configurations, including loop unrolling and custom angle restrictions, makes it a versatile tool for diverse software verification applications. + +## How to use Chiron BMC + +### Adding Bounds +We can restrict the domain of variables by `assume` statements. For example: +- `assume :x >= 0` bounds the domain of variable `:x` in the positive side of number line +- `assume :x*:x + :y*:y <= r*r` restricts the point `(:x, :y)` inside the circle of radius `r`. + +### Adding Conditions +We add the conditions to be checked by `assert` statements. For example: +- `assert :x >= 0 && :y >= 0` checks whether the point `(:x, :y)` lies in the first quadrant +- `assert :x*:x + :y*:y >= r*r` checks whether the point `(:x, :y)` lies outside the circle of radius `r`. + +### Handling Loops + +Loops in the code are managed through a technique called **loop unrolling**. Loop unrolling involves replicating the loop's body multiple times, constrained by a specified unroll bound. For the purpose of understaning unrolling, we store the unrolled code in file `unrolled_code.tl`. + +### Adding Loop Unroll Bound +`-ub ` is used to set the unroll bound of loops. By default, it is set to 10. + +A custom unroll bound for a particular loop can be set by using the `@unroll` decorator. For example, +```c +@unroll repeat [ + ... +] +``` + +### Tracking Position of Turtle +We assume that turle starts at position $(0, 0)$ and facing at $0^\circ$ angle with respect to the positive direction of $x$-axis. The position of turtle is maintained by the variables `:turtleX` ($x$-coordinate), `:turtleY` ($y$-coordinate) and `:turtleThetaDeg` (angle in degrees). + +### Adding Angle Constraints +By default, the turtle can face towards $0^\circ$, $90^\circ$, $180^\circ$ and $270^\circ$. Custom angles can be added by maintaining a configuration file that specifies the angles along with their cosine and sine values in the following format: + +```plaintext +, , +, , +... +``` + +This configuration file is then passed to the BMC engine using the `-aconf ` argument. + +### Tracking Pen State +The variable `:turtlePen` is used to maintain the up/down state of pen. +- `:turtlePen = 0` indicates pendown state +- `:turtlePen = 1` indicates penup state + +At the start of the program, pen is in pendown state. + +## Examples +Examples for working of the BMC engine are provided in the `/ChironCore/bmc_examples/` directory. To run the BMC engine on these test cases, navigate to the `ChironCore` directory and execute the following command: + +```bash +./chiron.py -bmc -ub -aconf +``` +where `-ub` and `-aconf` are optional arguments + +## Implementation Methodology + +1. **Loop Unrolling**: + All the loops of the code are unrolled based on the unroll bound and the unrolled code is used for further processing. + +2. **Converting Chiron Intermediate Representation (IR) into Three Address Code (TAC)**: + The Chiron IR of the unrolled code is generated and is transformed into TAC to simplify the representation of operations and facilitate further analysis. + +3. **Generating Static Single Assignment (SSA)**: + The TAC is converted into SSA form to simplify data flow analysis and accurately track variable dependencies and states throughout the program. + +4. **SAT Solver Integration**: + The SSA form is translated into SMT-LIB statements. This process encodes the constraints, conditions, and properties into a series of logical assertions and declarations to accurately represent the program's semantics. These statements are then checked for satisfiability using the Z3 solver. + +5. **Reporting Results**: + - **Checking tightness of bounds**: + The BMC engine verifies if a solution exists within the given bounds. If no solution is found, it suggests relaxing the bounds. + + - **Checking satisfiability under all bounds**: + The BMC engine checks satisfiability until either a counterexample is found or all possible states of the program within the specified bounds are exhausted. If no violations are detected, the system is considered correct up to the given bounds. + + - **Counter Example generation**: + If the BMC engine detects a violation, it generates a counterexample for the input variables. + +## Acknowledgement +We express our gratitude to Professor Subhajit Roy and Chiron team for their unwavering guidance and support throughout the duration of this project. Their assistance significantly influenced the course of our journey, making it markedly distinct from what it would have been otherwise. \ No newline at end of file diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 37685fa..3c15b65 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -280,10 +280,10 @@ def solve(self, inputVars): assume_check = checker_with_assume.check() if assume_check == z3.unsat: - print("Give a larger unroll bound") + print("The program cannot execute within the provided bounds. Consider increasing the bounds and trying again..") return elif assume_check == z3.unknown: - print("Cannot determine if unroll bound is sufficient") + print("Cannot determine if bounds are sufficient") return checker_with_angles = z3.Solver() @@ -296,7 +296,7 @@ def solve(self, inputVars): print("Angle not in angles.conf for all cases") return elif angles_check == z3.unknown: - print("Cannot determine if unroll bound is sufficient") + print("Cannot determine if angles are as per configuration file") return self.solver.add(z3.Not(self.assert_conditions)) diff --git a/ChironCore/chiron.py b/ChironCore/chiron.py index f1e5378..2310fc9 100755 --- a/ChironCore/chiron.py +++ b/ChironCore/chiron.py @@ -202,12 +202,11 @@ def stopTurtle(): type=bool, ) - cmdparser.add_argument( + cmdparser.add_argument( # example usage: ./chiron.py -bmc -ub 20 -aconf "-bmc", "--bmc", - # type=str, action="store_true", - help="Run Bounded Model Checking on a Chiron Program.", + help="Run Bounded Model Checking on a Chiron Program", ) cmdparser.add_argument( @@ -215,15 +214,15 @@ def stopTurtle(): "--unroll-bound", type=int, default=10, - help="Unroll bound for the program. Default is 10.", + help="Unroll bound for the BMC engine. Default is 10", ) - cmdparser.add_argument( + cmdparser.add_argument( # By default we take angles 0, 90, 180 and 270 "-aconf", "--angle-conf", type=str, default="", - help="Angle configuration file for BMC.", + help="Angle configuration file for BMC", ) args = cmdparser.parse_args() @@ -446,7 +445,7 @@ def stopTurtle(): unrolled_code = unroll.UnrollLoops(unroll_bound).visitStart(getParseTree(args.progfl)) - with open("unrolled_code.tl", "w") as f: + with open("unrolled_code.tl", "w") as f: # Saving unrolled code to file unrolled_code.tl f.write(unrolled_code) try: @@ -466,14 +465,13 @@ def stopTurtle(): tacGen = TACGenerator(ir) # Converting IR to TAC tacGen.generateTAC() - # tacGen.printTAC() # Printing TAC + # tacGen.printTAC() # for printing TAC if tacGen.assertCount == 0: print("No conditions found in the program. Exiting...") exit(1) - # cfg, line2BlockMap = cfgB.buildCFG(tacGen.tac, "control_flow_graph", False) # Building CFG - cfgB.dumpCFG(tacGen.tacCfg, 'tac_cfg') + cfgB.dumpCFG(tacGen.tacCfg, 'tac_cfg') # Saving TAC CFG to file tac_cfg.png ssa = SSABuilder(tacGen.tac) # Converting TAC to SSA ssaCfg = ssa.build() diff --git a/ChironCore/example/assignmentBMC.tl b/ChironCore/example/assignmentBMC.tl deleted file mode 100644 index 252083b..0000000 --- a/ChironCore/example/assignmentBMC.tl +++ /dev/null @@ -1,7 +0,0 @@ -// inputs: :x, :y, :z - -:t = :x + 2*:y + 3*:z + :x * :w * :u -:z = :x + :w - - -assert (:x + 100 < :y) && (:x + 200 > :y) && !(:x >= 0) && (:x * :y < -:x) && (:t > 0) \ No newline at end of file diff --git a/ChironCore/example/bmc_tc1.tl b/ChironCore/example/bmc_tc1.tl deleted file mode 100644 index 57533f7..0000000 --- a/ChironCore/example/bmc_tc1.tl +++ /dev/null @@ -1,16 +0,0 @@ -:t = 1 -// assume :x > 0 -repeat 2 [ - :t = :t * :x - assert :t > 0 -] -:s = 5 * :x -:z = :t + :s + 2 -// assert :z >= -5 - - -// cant do the following -// if (b > 0) [ // :a is not defined earlier -// :a = 1 -// ] -// forward :a \ No newline at end of file diff --git a/ChironCore/example/bmc_tc2.tl b/ChironCore/example/bmc_tc2.tl deleted file mode 100644 index 1ddca2a..0000000 --- a/ChironCore/example/bmc_tc2.tl +++ /dev/null @@ -1,25 +0,0 @@ -:p = 1 - -repeat 5 [ - :t = :t * :x -] - -:q = 1 -repeat 4 [ - :q = :q * :x -] - -:r = 1 -repeat 7 [ - :r = :r * :x -] - -:s = 1 - -repeat :o [ - :s = :s * :x - :o = :o - 1 -] - -:z = 2*:p - 3*:q + 5*:r - 7*:s -assert :z < -10000 diff --git a/ChironCore/example/bmc_tc3.tl b/ChironCore/example/bmc_tc3.tl deleted file mode 100644 index 728daa7..0000000 --- a/ChironCore/example/bmc_tc3.tl +++ /dev/null @@ -1,13 +0,0 @@ -:a = -1 -:y = 0 -if (:a > 0) [ - :x = :y + 2 -] -if (:a > 1) [ - :x = :y + 3 -] -goto (:x, :y) -assert :turtleX == 2 && :turtleY == 0 -right :x -assert :x > 0 -assert :turtleX > 0 diff --git a/ChironCore/example/exm.tl b/ChironCore/example/exm.tl deleted file mode 100644 index 62c5439..0000000 --- a/ChironCore/example/exm.tl +++ /dev/null @@ -1,6 +0,0 @@ -forward 10 -left 90 -right 90 -assume :x > 0 -forward :x -assert :turtleX*:turtleX + :turtleY*:turtleY <= 100 \ No newline at end of file diff --git a/ChironCore/example/exm2.tl b/ChironCore/example/exm2.tl deleted file mode 100644 index 2ac7b91..0000000 --- a/ChironCore/example/exm2.tl +++ /dev/null @@ -1,7 +0,0 @@ -assume :a < 0 -if (:b > 0) [ - :a = 1 - assert :a == 1 -] -forward :a -assert :turtleX > 0 \ No newline at end of file diff --git a/ChironCore/example/move.tl b/ChironCore/example/move.tl deleted file mode 100644 index 6c8335c..0000000 --- a/ChironCore/example/move.tl +++ /dev/null @@ -1,17 +0,0 @@ -// left 90 // valid -// assert 1 > 0 // true - -// left 45 // invalid -// assert 1 > 0 // true - -// left 90 // valid -// assert 1 < 0 // flase - -// left 45 // invalid -// assert 1 < 0 // flase - -repeat 3 [ - left 90 -] - -assert :turtleX == 0 \ No newline at end of file diff --git a/ChironCore/example/move1.tl b/ChironCore/example/move1.tl deleted file mode 100644 index 055782d..0000000 --- a/ChironCore/example/move1.tl +++ /dev/null @@ -1 +0,0 @@ -forward 50 \ No newline at end of file diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index fa2b089..f7b906b 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,127 +1,206 @@ -:_repeat0 = :a -assume :_repeat0 <= 5 -if (:_repeat0 > 0) [ forward10 -if ((:a<2)) [ -:y=3 +assert:turtleX==10 +:_repeat0 = :turtleX +assume :_repeat0 <= 50 +if (:_repeat0 > 0) [ +:x=:x+1 ] +if (:_repeat0 > 1) [ +:x=:x+1 ] -if (:_repeat0 > 1) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 2) [ +:x=:x+1 ] +if (:_repeat0 > 3) [ +:x=:x+1 ] -if (:_repeat0 > 2) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 4) [ +:x=:x+1 ] +if (:_repeat0 > 5) [ +:x=:x+1 ] -if (:_repeat0 > 3) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 6) [ +:x=:x+1 ] +if (:_repeat0 > 7) [ +:x=:x+1 ] -if (:_repeat0 > 4) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 8) [ +:x=:x+1 ] +if (:_repeat0 > 9) [ +:x=:x+1 ] +if (:_repeat0 > 10) [ +:x=:x+1 -:_repeat1 = :a -assume :_repeat1 <= 10 -if (:_repeat1 > 0) [ -forward10 -if ((:a<2)) [ -:y=3 +] +if (:_repeat0 > 11) [ +:x=:x+1 ] +if (:_repeat0 > 12) [ +:x=:x+1 ] -if (:_repeat1 > 1) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 13) [ +:x=:x+1 ] +if (:_repeat0 > 14) [ +:x=:x+1 ] -if (:_repeat1 > 2) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 15) [ +:x=:x+1 ] +if (:_repeat0 > 16) [ +:x=:x+1 ] -if (:_repeat1 > 3) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 17) [ +:x=:x+1 ] +if (:_repeat0 > 18) [ +:x=:x+1 ] -if (:_repeat1 > 4) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 19) [ +:x=:x+1 ] +if (:_repeat0 > 20) [ +:x=:x+1 ] -if (:_repeat1 > 5) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 21) [ +:x=:x+1 ] +if (:_repeat0 > 22) [ +:x=:x+1 ] -if (:_repeat1 > 6) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 23) [ +:x=:x+1 ] +if (:_repeat0 > 24) [ +:x=:x+1 ] -if (:_repeat1 > 7) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 25) [ +:x=:x+1 ] +if (:_repeat0 > 26) [ +:x=:x+1 ] -if (:_repeat1 > 8) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 27) [ +:x=:x+1 ] +if (:_repeat0 > 28) [ +:x=:x+1 ] -if (:_repeat1 > 9) [ -forward10 -if ((:a<2)) [ -:y=3 +if (:_repeat0 > 29) [ +:x=:x+1 + +] +if (:_repeat0 > 30) [ +:x=:x+1 + +] +if (:_repeat0 > 31) [ +:x=:x+1 + +] +if (:_repeat0 > 32) [ +:x=:x+1 + +] +if (:_repeat0 > 33) [ +:x=:x+1 + +] +if (:_repeat0 > 34) [ +:x=:x+1 + +] +if (:_repeat0 > 35) [ +:x=:x+1 + +] +if (:_repeat0 > 36) [ +:x=:x+1 + +] +if (:_repeat0 > 37) [ +:x=:x+1 + +] +if (:_repeat0 > 38) [ +:x=:x+1 + +] +if (:_repeat0 > 39) [ +:x=:x+1 + +] +if (:_repeat0 > 40) [ +:x=:x+1 + +] +if (:_repeat0 > 41) [ +:x=:x+1 + +] +if (:_repeat0 > 42) [ +:x=:x+1 + +] +if (:_repeat0 > 43) [ +:x=:x+1 + +] +if (:_repeat0 > 44) [ +:x=:x+1 + +] +if (:_repeat0 > 45) [ +:x=:x+1 + +] +if (:_repeat0 > 46) [ +:x=:x+1 + +] +if (:_repeat0 > 47) [ +:x=:x+1 + +] +if (:_repeat0 > 48) [ +:x=:x+1 ] +if (:_repeat0 > 49) [ +:x=:x+1 ] -assert:turtleX<=1&&:turtleX>=-1&&:turtleY<=1&&:turtleY>=-1 +assert:x<=100 diff --git a/README.md b/README.md index fc6634e..95a5c61 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,8 @@ If you want to cite this work, you may use this. ### Installing Dependencies ```bash -pip install antlr4-python3-runtime==4.7.2 networkx z3-solver numpy +pip install antlr4-python3-runtime==4.7.2 networkx z3-solver numpy pygraphviz sudo apt-get install python3-tk -pip install pygraphviz ``` ### Generating the ANTLR files. @@ -85,7 +84,7 @@ Chiron v1.0.1 ------------ usage: chiron.py [-h] [-p] [-r] [-gr] [-b] [-z] [-t TIMEOUT] [-d PARAMS] [-c CONSTPARAMS] [-se] [-ai] [-dfa] [-sbfl] [-bg BUGGY] [-vars INPUTVARSLIST] [-nt NTESTS] [-pop POPSIZE] [-cp CXPB] [-mp MUTPB] [-ng NGEN] - [-vb VERBOSE] + [-vb VERBOSE] [-bmc] [-ub UNROLL_BOUND] [-aconf ANGLE_CONF] progfl Program Analysis Framework for ChironLang Programs. @@ -132,5 +131,10 @@ options: number of times Genetic Algorithm iterates -vb VERBOSE, --verbose VERBOSE To display computation to Console + -bmc, --bmc Run Bounded Model Checking on a Chiron Program + -ub UNROLL_BOUND, --unroll-bound UNROLL_BOUND + Unroll bound for the BMC engine. Default is 10 + -aconf ANGLE_CONF, --angle-conf ANGLE_CONF + Angle configuration file for BMC ``` From 260ba74c16e2737c6c6a03011163faba3f88a88b Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Thu, 17 Apr 2025 04:44:31 +0530 Subject: [PATCH 50/53] added multiline comments --- ChironCore/turtparse/tlang.g4 | 5 +- ChironCore/turtparse/tlang.interp | 6 +- ChironCore/turtparse/tlang.tokens | 3 +- ChironCore/turtparse/tlangLexer.interp | 9 +- ChironCore/turtparse/tlangLexer.py | 220 +++++++++++++------------ ChironCore/turtparse/tlangLexer.tokens | 3 +- ChironCore/turtparse/tlangParser.py | 7 +- ChironCore/unrolled_code.tl | 209 +---------------------- 8 files changed, 139 insertions(+), 323 deletions(-) diff --git a/ChironCore/turtparse/tlang.g4 b/ChironCore/turtparse/tlang.g4 index cb5cdec..f840290 100644 --- a/ChironCore/turtparse/tlang.g4 +++ b/ChironCore/turtparse/tlang.g4 @@ -108,6 +108,7 @@ VAR : ':'[a-zA-Z_] [a-zA-Z0-9]* ; NAME : [a-zA-Z]+ ; -Whitespace: [ \t\n\r]+ -> skip; +Whitespace : [ \t\n\r]+ -> skip; -Comment: '//' ~[\r\n]* -> skip; +COMMENT_LINE : '//' ~[\r\n]* -> skip; +COMMENT_BLOCK : '/*' .*? '*/' -> skip; diff --git a/ChironCore/turtparse/tlang.interp b/ChironCore/turtparse/tlang.interp index da83104..007a475 100644 --- a/ChironCore/turtparse/tlang.interp +++ b/ChironCore/turtparse/tlang.interp @@ -41,6 +41,7 @@ null null null null +null token symbolic names: null @@ -84,7 +85,8 @@ FLOAT VAR NAME Whitespace -Comment +COMMENT_LINE +COMMENT_BLOCK rule names: start @@ -115,4 +117,4 @@ value atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 43, 205, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 57, 10, 3, 12, 3, 14, 3, 60, 11, 3, 3, 4, 6, 4, 63, 10, 4, 13, 4, 14, 4, 64, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 76, 10, 5, 3, 6, 3, 6, 5, 6, 80, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 5, 9, 112, 10, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 149, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 163, 10, 18, 12, 18, 14, 18, 166, 11, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 188, 10, 23, 3, 23, 3, 23, 3, 23, 3, 23, 7, 23, 194, 10, 23, 12, 23, 14, 23, 197, 11, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 2, 4, 34, 44, 27, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 2, 9, 3, 2, 14, 17, 3, 2, 18, 19, 3, 2, 25, 26, 3, 2, 23, 24, 3, 2, 29, 34, 3, 2, 35, 36, 3, 2, 38, 40, 2, 200, 2, 52, 3, 2, 2, 2, 4, 58, 3, 2, 2, 2, 6, 62, 3, 2, 2, 2, 8, 75, 3, 2, 2, 2, 10, 79, 3, 2, 2, 2, 12, 81, 3, 2, 2, 2, 14, 87, 3, 2, 2, 2, 16, 111, 3, 2, 2, 2, 18, 113, 3, 2, 2, 2, 20, 120, 3, 2, 2, 2, 22, 124, 3, 2, 2, 2, 24, 127, 3, 2, 2, 2, 26, 129, 3, 2, 2, 2, 28, 131, 3, 2, 2, 2, 30, 133, 3, 2, 2, 2, 32, 136, 3, 2, 2, 2, 34, 148, 3, 2, 2, 2, 36, 167, 3, 2, 2, 2, 38, 169, 3, 2, 2, 2, 40, 171, 3, 2, 2, 2, 42, 173, 3, 2, 2, 2, 44, 187, 3, 2, 2, 2, 46, 198, 3, 2, 2, 2, 48, 200, 3, 2, 2, 2, 50, 202, 3, 2, 2, 2, 52, 53, 5, 4, 3, 2, 53, 54, 7, 2, 2, 3, 54, 3, 3, 2, 2, 2, 55, 57, 5, 8, 5, 2, 56, 55, 3, 2, 2, 2, 57, 60, 3, 2, 2, 2, 58, 56, 3, 2, 2, 2, 58, 59, 3, 2, 2, 2, 59, 5, 3, 2, 2, 2, 60, 58, 3, 2, 2, 2, 61, 63, 5, 8, 5, 2, 62, 61, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 62, 3, 2, 2, 2, 64, 65, 3, 2, 2, 2, 65, 7, 3, 2, 2, 2, 66, 76, 5, 20, 11, 2, 67, 76, 5, 10, 6, 2, 68, 76, 5, 16, 9, 2, 69, 76, 5, 22, 12, 2, 70, 76, 5, 26, 14, 2, 71, 76, 5, 18, 10, 2, 72, 76, 5, 28, 15, 2, 73, 76, 5, 30, 16, 2, 74, 76, 5, 32, 17, 2, 75, 66, 3, 2, 2, 2, 75, 67, 3, 2, 2, 2, 75, 68, 3, 2, 2, 2, 75, 69, 3, 2, 2, 2, 75, 70, 3, 2, 2, 2, 75, 71, 3, 2, 2, 2, 75, 72, 3, 2, 2, 2, 75, 73, 3, 2, 2, 2, 75, 74, 3, 2, 2, 2, 76, 9, 3, 2, 2, 2, 77, 80, 5, 12, 7, 2, 78, 80, 5, 14, 8, 2, 79, 77, 3, 2, 2, 2, 79, 78, 3, 2, 2, 2, 80, 11, 3, 2, 2, 2, 81, 82, 7, 3, 2, 2, 82, 83, 5, 44, 23, 2, 83, 84, 7, 4, 2, 2, 84, 85, 5, 6, 4, 2, 85, 86, 7, 5, 2, 2, 86, 13, 3, 2, 2, 2, 87, 88, 7, 3, 2, 2, 88, 89, 5, 44, 23, 2, 89, 90, 7, 4, 2, 2, 90, 91, 5, 6, 4, 2, 91, 92, 7, 5, 2, 2, 92, 93, 7, 6, 2, 2, 93, 94, 7, 4, 2, 2, 94, 95, 5, 6, 4, 2, 95, 96, 7, 5, 2, 2, 96, 15, 3, 2, 2, 2, 97, 98, 7, 7, 2, 2, 98, 99, 5, 50, 26, 2, 99, 100, 7, 4, 2, 2, 100, 101, 5, 6, 4, 2, 101, 102, 7, 5, 2, 2, 102, 112, 3, 2, 2, 2, 103, 104, 7, 8, 2, 2, 104, 105, 7, 38, 2, 2, 105, 106, 7, 7, 2, 2, 106, 107, 5, 50, 26, 2, 107, 108, 7, 4, 2, 2, 108, 109, 5, 6, 4, 2, 109, 110, 7, 5, 2, 2, 110, 112, 3, 2, 2, 2, 111, 97, 3, 2, 2, 2, 111, 103, 3, 2, 2, 2, 112, 17, 3, 2, 2, 2, 113, 114, 7, 9, 2, 2, 114, 115, 7, 10, 2, 2, 115, 116, 5, 34, 18, 2, 116, 117, 7, 11, 2, 2, 117, 118, 5, 34, 18, 2, 118, 119, 7, 12, 2, 2, 119, 19, 3, 2, 2, 2, 120, 121, 7, 40, 2, 2, 121, 122, 7, 13, 2, 2, 122, 123, 5, 34, 18, 2, 123, 21, 3, 2, 2, 2, 124, 125, 5, 24, 13, 2, 125, 126, 5, 34, 18, 2, 126, 23, 3, 2, 2, 2, 127, 128, 9, 2, 2, 2, 128, 25, 3, 2, 2, 2, 129, 130, 9, 3, 2, 2, 130, 27, 3, 2, 2, 2, 131, 132, 7, 20, 2, 2, 132, 29, 3, 2, 2, 2, 133, 134, 7, 21, 2, 2, 134, 135, 5, 44, 23, 2, 135, 31, 3, 2, 2, 2, 136, 137, 7, 22, 2, 2, 137, 138, 5, 44, 23, 2, 138, 33, 3, 2, 2, 2, 139, 140, 8, 18, 1, 2, 140, 141, 5, 42, 22, 2, 141, 142, 5, 34, 18, 8, 142, 149, 3, 2, 2, 2, 143, 149, 5, 50, 26, 2, 144, 145, 7, 10, 2, 2, 145, 146, 5, 34, 18, 2, 146, 147, 7, 12, 2, 2, 147, 149, 3, 2, 2, 2, 148, 139, 3, 2, 2, 2, 148, 143, 3, 2, 2, 2, 148, 144, 3, 2, 2, 2, 149, 164, 3, 2, 2, 2, 150, 151, 12, 7, 2, 2, 151, 152, 5, 36, 19, 2, 152, 153, 5, 34, 18, 8, 153, 163, 3, 2, 2, 2, 154, 155, 12, 6, 2, 2, 155, 156, 5, 38, 20, 2, 156, 157, 5, 34, 18, 7, 157, 163, 3, 2, 2, 2, 158, 159, 12, 5, 2, 2, 159, 160, 5, 40, 21, 2, 160, 161, 5, 34, 18, 6, 161, 163, 3, 2, 2, 2, 162, 150, 3, 2, 2, 2, 162, 154, 3, 2, 2, 2, 162, 158, 3, 2, 2, 2, 163, 166, 3, 2, 2, 2, 164, 162, 3, 2, 2, 2, 164, 165, 3, 2, 2, 2, 165, 35, 3, 2, 2, 2, 166, 164, 3, 2, 2, 2, 167, 168, 9, 4, 2, 2, 168, 37, 3, 2, 2, 2, 169, 170, 9, 5, 2, 2, 170, 39, 3, 2, 2, 2, 171, 172, 7, 27, 2, 2, 172, 41, 3, 2, 2, 2, 173, 174, 7, 24, 2, 2, 174, 43, 3, 2, 2, 2, 175, 176, 8, 23, 1, 2, 176, 177, 7, 37, 2, 2, 177, 188, 5, 44, 23, 7, 178, 179, 5, 34, 18, 2, 179, 180, 5, 46, 24, 2, 180, 181, 5, 34, 18, 2, 181, 188, 3, 2, 2, 2, 182, 188, 7, 28, 2, 2, 183, 184, 7, 10, 2, 2, 184, 185, 5, 44, 23, 2, 185, 186, 7, 12, 2, 2, 186, 188, 3, 2, 2, 2, 187, 175, 3, 2, 2, 2, 187, 178, 3, 2, 2, 2, 187, 182, 3, 2, 2, 2, 187, 183, 3, 2, 2, 2, 188, 195, 3, 2, 2, 2, 189, 190, 12, 5, 2, 2, 190, 191, 5, 48, 25, 2, 191, 192, 5, 44, 23, 6, 192, 194, 3, 2, 2, 2, 193, 189, 3, 2, 2, 2, 194, 197, 3, 2, 2, 2, 195, 193, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196, 45, 3, 2, 2, 2, 197, 195, 3, 2, 2, 2, 198, 199, 9, 6, 2, 2, 199, 47, 3, 2, 2, 2, 200, 201, 9, 7, 2, 2, 201, 49, 3, 2, 2, 2, 202, 203, 9, 8, 2, 2, 203, 51, 3, 2, 2, 2, 12, 58, 64, 75, 79, 111, 148, 162, 164, 187, 195] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 44, 205, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 57, 10, 3, 12, 3, 14, 3, 60, 11, 3, 3, 4, 6, 4, 63, 10, 4, 13, 4, 14, 4, 64, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 76, 10, 5, 3, 6, 3, 6, 5, 6, 80, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 5, 9, 112, 10, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 149, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 163, 10, 18, 12, 18, 14, 18, 166, 11, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 188, 10, 23, 3, 23, 3, 23, 3, 23, 3, 23, 7, 23, 194, 10, 23, 12, 23, 14, 23, 197, 11, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 2, 4, 34, 44, 27, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 2, 9, 3, 2, 14, 17, 3, 2, 18, 19, 3, 2, 25, 26, 3, 2, 23, 24, 3, 2, 29, 34, 3, 2, 35, 36, 3, 2, 38, 40, 2, 200, 2, 52, 3, 2, 2, 2, 4, 58, 3, 2, 2, 2, 6, 62, 3, 2, 2, 2, 8, 75, 3, 2, 2, 2, 10, 79, 3, 2, 2, 2, 12, 81, 3, 2, 2, 2, 14, 87, 3, 2, 2, 2, 16, 111, 3, 2, 2, 2, 18, 113, 3, 2, 2, 2, 20, 120, 3, 2, 2, 2, 22, 124, 3, 2, 2, 2, 24, 127, 3, 2, 2, 2, 26, 129, 3, 2, 2, 2, 28, 131, 3, 2, 2, 2, 30, 133, 3, 2, 2, 2, 32, 136, 3, 2, 2, 2, 34, 148, 3, 2, 2, 2, 36, 167, 3, 2, 2, 2, 38, 169, 3, 2, 2, 2, 40, 171, 3, 2, 2, 2, 42, 173, 3, 2, 2, 2, 44, 187, 3, 2, 2, 2, 46, 198, 3, 2, 2, 2, 48, 200, 3, 2, 2, 2, 50, 202, 3, 2, 2, 2, 52, 53, 5, 4, 3, 2, 53, 54, 7, 2, 2, 3, 54, 3, 3, 2, 2, 2, 55, 57, 5, 8, 5, 2, 56, 55, 3, 2, 2, 2, 57, 60, 3, 2, 2, 2, 58, 56, 3, 2, 2, 2, 58, 59, 3, 2, 2, 2, 59, 5, 3, 2, 2, 2, 60, 58, 3, 2, 2, 2, 61, 63, 5, 8, 5, 2, 62, 61, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 62, 3, 2, 2, 2, 64, 65, 3, 2, 2, 2, 65, 7, 3, 2, 2, 2, 66, 76, 5, 20, 11, 2, 67, 76, 5, 10, 6, 2, 68, 76, 5, 16, 9, 2, 69, 76, 5, 22, 12, 2, 70, 76, 5, 26, 14, 2, 71, 76, 5, 18, 10, 2, 72, 76, 5, 28, 15, 2, 73, 76, 5, 30, 16, 2, 74, 76, 5, 32, 17, 2, 75, 66, 3, 2, 2, 2, 75, 67, 3, 2, 2, 2, 75, 68, 3, 2, 2, 2, 75, 69, 3, 2, 2, 2, 75, 70, 3, 2, 2, 2, 75, 71, 3, 2, 2, 2, 75, 72, 3, 2, 2, 2, 75, 73, 3, 2, 2, 2, 75, 74, 3, 2, 2, 2, 76, 9, 3, 2, 2, 2, 77, 80, 5, 12, 7, 2, 78, 80, 5, 14, 8, 2, 79, 77, 3, 2, 2, 2, 79, 78, 3, 2, 2, 2, 80, 11, 3, 2, 2, 2, 81, 82, 7, 3, 2, 2, 82, 83, 5, 44, 23, 2, 83, 84, 7, 4, 2, 2, 84, 85, 5, 6, 4, 2, 85, 86, 7, 5, 2, 2, 86, 13, 3, 2, 2, 2, 87, 88, 7, 3, 2, 2, 88, 89, 5, 44, 23, 2, 89, 90, 7, 4, 2, 2, 90, 91, 5, 6, 4, 2, 91, 92, 7, 5, 2, 2, 92, 93, 7, 6, 2, 2, 93, 94, 7, 4, 2, 2, 94, 95, 5, 6, 4, 2, 95, 96, 7, 5, 2, 2, 96, 15, 3, 2, 2, 2, 97, 98, 7, 7, 2, 2, 98, 99, 5, 50, 26, 2, 99, 100, 7, 4, 2, 2, 100, 101, 5, 6, 4, 2, 101, 102, 7, 5, 2, 2, 102, 112, 3, 2, 2, 2, 103, 104, 7, 8, 2, 2, 104, 105, 7, 38, 2, 2, 105, 106, 7, 7, 2, 2, 106, 107, 5, 50, 26, 2, 107, 108, 7, 4, 2, 2, 108, 109, 5, 6, 4, 2, 109, 110, 7, 5, 2, 2, 110, 112, 3, 2, 2, 2, 111, 97, 3, 2, 2, 2, 111, 103, 3, 2, 2, 2, 112, 17, 3, 2, 2, 2, 113, 114, 7, 9, 2, 2, 114, 115, 7, 10, 2, 2, 115, 116, 5, 34, 18, 2, 116, 117, 7, 11, 2, 2, 117, 118, 5, 34, 18, 2, 118, 119, 7, 12, 2, 2, 119, 19, 3, 2, 2, 2, 120, 121, 7, 40, 2, 2, 121, 122, 7, 13, 2, 2, 122, 123, 5, 34, 18, 2, 123, 21, 3, 2, 2, 2, 124, 125, 5, 24, 13, 2, 125, 126, 5, 34, 18, 2, 126, 23, 3, 2, 2, 2, 127, 128, 9, 2, 2, 2, 128, 25, 3, 2, 2, 2, 129, 130, 9, 3, 2, 2, 130, 27, 3, 2, 2, 2, 131, 132, 7, 20, 2, 2, 132, 29, 3, 2, 2, 2, 133, 134, 7, 21, 2, 2, 134, 135, 5, 44, 23, 2, 135, 31, 3, 2, 2, 2, 136, 137, 7, 22, 2, 2, 137, 138, 5, 44, 23, 2, 138, 33, 3, 2, 2, 2, 139, 140, 8, 18, 1, 2, 140, 141, 5, 42, 22, 2, 141, 142, 5, 34, 18, 8, 142, 149, 3, 2, 2, 2, 143, 149, 5, 50, 26, 2, 144, 145, 7, 10, 2, 2, 145, 146, 5, 34, 18, 2, 146, 147, 7, 12, 2, 2, 147, 149, 3, 2, 2, 2, 148, 139, 3, 2, 2, 2, 148, 143, 3, 2, 2, 2, 148, 144, 3, 2, 2, 2, 149, 164, 3, 2, 2, 2, 150, 151, 12, 7, 2, 2, 151, 152, 5, 36, 19, 2, 152, 153, 5, 34, 18, 8, 153, 163, 3, 2, 2, 2, 154, 155, 12, 6, 2, 2, 155, 156, 5, 38, 20, 2, 156, 157, 5, 34, 18, 7, 157, 163, 3, 2, 2, 2, 158, 159, 12, 5, 2, 2, 159, 160, 5, 40, 21, 2, 160, 161, 5, 34, 18, 6, 161, 163, 3, 2, 2, 2, 162, 150, 3, 2, 2, 2, 162, 154, 3, 2, 2, 2, 162, 158, 3, 2, 2, 2, 163, 166, 3, 2, 2, 2, 164, 162, 3, 2, 2, 2, 164, 165, 3, 2, 2, 2, 165, 35, 3, 2, 2, 2, 166, 164, 3, 2, 2, 2, 167, 168, 9, 4, 2, 2, 168, 37, 3, 2, 2, 2, 169, 170, 9, 5, 2, 2, 170, 39, 3, 2, 2, 2, 171, 172, 7, 27, 2, 2, 172, 41, 3, 2, 2, 2, 173, 174, 7, 24, 2, 2, 174, 43, 3, 2, 2, 2, 175, 176, 8, 23, 1, 2, 176, 177, 7, 37, 2, 2, 177, 188, 5, 44, 23, 7, 178, 179, 5, 34, 18, 2, 179, 180, 5, 46, 24, 2, 180, 181, 5, 34, 18, 2, 181, 188, 3, 2, 2, 2, 182, 188, 7, 28, 2, 2, 183, 184, 7, 10, 2, 2, 184, 185, 5, 44, 23, 2, 185, 186, 7, 12, 2, 2, 186, 188, 3, 2, 2, 2, 187, 175, 3, 2, 2, 2, 187, 178, 3, 2, 2, 2, 187, 182, 3, 2, 2, 2, 187, 183, 3, 2, 2, 2, 188, 195, 3, 2, 2, 2, 189, 190, 12, 5, 2, 2, 190, 191, 5, 48, 25, 2, 191, 192, 5, 44, 23, 6, 192, 194, 3, 2, 2, 2, 193, 189, 3, 2, 2, 2, 194, 197, 3, 2, 2, 2, 195, 193, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196, 45, 3, 2, 2, 2, 197, 195, 3, 2, 2, 2, 198, 199, 9, 6, 2, 2, 199, 47, 3, 2, 2, 2, 200, 201, 9, 7, 2, 2, 201, 49, 3, 2, 2, 2, 202, 203, 9, 8, 2, 2, 203, 51, 3, 2, 2, 2, 12, 58, 64, 75, 79, 111, 148, 162, 164, 187, 195] \ No newline at end of file diff --git a/ChironCore/turtparse/tlang.tokens b/ChironCore/turtparse/tlang.tokens index 355acdc..39f4806 100644 --- a/ChironCore/turtparse/tlang.tokens +++ b/ChironCore/turtparse/tlang.tokens @@ -38,7 +38,8 @@ FLOAT=37 VAR=38 NAME=39 Whitespace=40 -Comment=41 +COMMENT_LINE=41 +COMMENT_BLOCK=42 'if'=1 '['=2 ']'=3 diff --git a/ChironCore/turtparse/tlangLexer.interp b/ChironCore/turtparse/tlangLexer.interp index 957a8c5..4829228 100644 --- a/ChironCore/turtparse/tlangLexer.interp +++ b/ChironCore/turtparse/tlangLexer.interp @@ -41,6 +41,7 @@ null null null null +null token symbolic names: null @@ -84,7 +85,8 @@ FLOAT VAR NAME Whitespace -Comment +COMMENT_LINE +COMMENT_BLOCK rule names: T__0 @@ -127,7 +129,8 @@ FLOAT VAR NAME Whitespace -Comment +COMMENT_LINE +COMMENT_BLOCK channel names: DEFAULT_TOKEN_CHANNEL @@ -137,4 +140,4 @@ mode names: DEFAULT_MODE atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 43, 270, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 6, 37, 232, 10, 37, 13, 37, 14, 37, 233, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 7, 39, 243, 10, 39, 12, 39, 14, 39, 246, 11, 39, 3, 40, 6, 40, 249, 10, 40, 13, 40, 14, 40, 250, 3, 41, 6, 41, 254, 10, 41, 13, 41, 14, 41, 255, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 42, 7, 42, 264, 10, 42, 12, 42, 14, 42, 267, 11, 42, 3, 42, 3, 42, 2, 2, 43, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 81, 42, 83, 43, 3, 2, 8, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 274, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2, 83, 3, 2, 2, 2, 3, 85, 3, 2, 2, 2, 5, 88, 3, 2, 2, 2, 7, 90, 3, 2, 2, 2, 9, 92, 3, 2, 2, 2, 11, 97, 3, 2, 2, 2, 13, 104, 3, 2, 2, 2, 15, 112, 3, 2, 2, 2, 17, 117, 3, 2, 2, 2, 19, 119, 3, 2, 2, 2, 21, 121, 3, 2, 2, 2, 23, 123, 3, 2, 2, 2, 25, 125, 3, 2, 2, 2, 27, 133, 3, 2, 2, 2, 29, 142, 3, 2, 2, 2, 31, 147, 3, 2, 2, 2, 33, 153, 3, 2, 2, 2, 35, 159, 3, 2, 2, 2, 37, 167, 3, 2, 2, 2, 39, 173, 3, 2, 2, 2, 41, 180, 3, 2, 2, 2, 43, 187, 3, 2, 2, 2, 45, 189, 3, 2, 2, 2, 47, 191, 3, 2, 2, 2, 49, 193, 3, 2, 2, 2, 51, 195, 3, 2, 2, 2, 53, 197, 3, 2, 2, 2, 55, 206, 3, 2, 2, 2, 57, 208, 3, 2, 2, 2, 59, 210, 3, 2, 2, 2, 61, 213, 3, 2, 2, 2, 63, 216, 3, 2, 2, 2, 65, 219, 3, 2, 2, 2, 67, 222, 3, 2, 2, 2, 69, 225, 3, 2, 2, 2, 71, 228, 3, 2, 2, 2, 73, 231, 3, 2, 2, 2, 75, 235, 3, 2, 2, 2, 77, 239, 3, 2, 2, 2, 79, 248, 3, 2, 2, 2, 81, 253, 3, 2, 2, 2, 83, 259, 3, 2, 2, 2, 85, 86, 7, 107, 2, 2, 86, 87, 7, 104, 2, 2, 87, 4, 3, 2, 2, 2, 88, 89, 7, 93, 2, 2, 89, 6, 3, 2, 2, 2, 90, 91, 7, 95, 2, 2, 91, 8, 3, 2, 2, 2, 92, 93, 7, 103, 2, 2, 93, 94, 7, 110, 2, 2, 94, 95, 7, 117, 2, 2, 95, 96, 7, 103, 2, 2, 96, 10, 3, 2, 2, 2, 97, 98, 7, 116, 2, 2, 98, 99, 7, 103, 2, 2, 99, 100, 7, 114, 2, 2, 100, 101, 7, 103, 2, 2, 101, 102, 7, 99, 2, 2, 102, 103, 7, 118, 2, 2, 103, 12, 3, 2, 2, 2, 104, 105, 7, 66, 2, 2, 105, 106, 7, 119, 2, 2, 106, 107, 7, 112, 2, 2, 107, 108, 7, 116, 2, 2, 108, 109, 7, 113, 2, 2, 109, 110, 7, 110, 2, 2, 110, 111, 7, 110, 2, 2, 111, 14, 3, 2, 2, 2, 112, 113, 7, 105, 2, 2, 113, 114, 7, 113, 2, 2, 114, 115, 7, 118, 2, 2, 115, 116, 7, 113, 2, 2, 116, 16, 3, 2, 2, 2, 117, 118, 7, 42, 2, 2, 118, 18, 3, 2, 2, 2, 119, 120, 7, 46, 2, 2, 120, 20, 3, 2, 2, 2, 121, 122, 7, 43, 2, 2, 122, 22, 3, 2, 2, 2, 123, 124, 7, 63, 2, 2, 124, 24, 3, 2, 2, 2, 125, 126, 7, 104, 2, 2, 126, 127, 7, 113, 2, 2, 127, 128, 7, 116, 2, 2, 128, 129, 7, 121, 2, 2, 129, 130, 7, 99, 2, 2, 130, 131, 7, 116, 2, 2, 131, 132, 7, 102, 2, 2, 132, 26, 3, 2, 2, 2, 133, 134, 7, 100, 2, 2, 134, 135, 7, 99, 2, 2, 135, 136, 7, 101, 2, 2, 136, 137, 7, 109, 2, 2, 137, 138, 7, 121, 2, 2, 138, 139, 7, 99, 2, 2, 139, 140, 7, 116, 2, 2, 140, 141, 7, 102, 2, 2, 141, 28, 3, 2, 2, 2, 142, 143, 7, 110, 2, 2, 143, 144, 7, 103, 2, 2, 144, 145, 7, 104, 2, 2, 145, 146, 7, 118, 2, 2, 146, 30, 3, 2, 2, 2, 147, 148, 7, 116, 2, 2, 148, 149, 7, 107, 2, 2, 149, 150, 7, 105, 2, 2, 150, 151, 7, 106, 2, 2, 151, 152, 7, 118, 2, 2, 152, 32, 3, 2, 2, 2, 153, 154, 7, 114, 2, 2, 154, 155, 7, 103, 2, 2, 155, 156, 7, 112, 2, 2, 156, 157, 7, 119, 2, 2, 157, 158, 7, 114, 2, 2, 158, 34, 3, 2, 2, 2, 159, 160, 7, 114, 2, 2, 160, 161, 7, 103, 2, 2, 161, 162, 7, 112, 2, 2, 162, 163, 7, 102, 2, 2, 163, 164, 7, 113, 2, 2, 164, 165, 7, 121, 2, 2, 165, 166, 7, 112, 2, 2, 166, 36, 3, 2, 2, 2, 167, 168, 7, 114, 2, 2, 168, 169, 7, 99, 2, 2, 169, 170, 7, 119, 2, 2, 170, 171, 7, 117, 2, 2, 171, 172, 7, 103, 2, 2, 172, 38, 3, 2, 2, 2, 173, 174, 7, 99, 2, 2, 174, 175, 7, 117, 2, 2, 175, 176, 7, 117, 2, 2, 176, 177, 7, 103, 2, 2, 177, 178, 7, 116, 2, 2, 178, 179, 7, 118, 2, 2, 179, 40, 3, 2, 2, 2, 180, 181, 7, 99, 2, 2, 181, 182, 7, 117, 2, 2, 182, 183, 7, 117, 2, 2, 183, 184, 7, 119, 2, 2, 184, 185, 7, 111, 2, 2, 185, 186, 7, 103, 2, 2, 186, 42, 3, 2, 2, 2, 187, 188, 7, 45, 2, 2, 188, 44, 3, 2, 2, 2, 189, 190, 7, 47, 2, 2, 190, 46, 3, 2, 2, 2, 191, 192, 7, 44, 2, 2, 192, 48, 3, 2, 2, 2, 193, 194, 7, 49, 2, 2, 194, 50, 3, 2, 2, 2, 195, 196, 7, 39, 2, 2, 196, 52, 3, 2, 2, 2, 197, 198, 7, 114, 2, 2, 198, 199, 7, 103, 2, 2, 199, 200, 7, 112, 2, 2, 200, 201, 7, 102, 2, 2, 201, 202, 7, 113, 2, 2, 202, 203, 7, 121, 2, 2, 203, 204, 7, 112, 2, 2, 204, 205, 7, 65, 2, 2, 205, 54, 3, 2, 2, 2, 206, 207, 7, 62, 2, 2, 207, 56, 3, 2, 2, 2, 208, 209, 7, 64, 2, 2, 209, 58, 3, 2, 2, 2, 210, 211, 7, 63, 2, 2, 211, 212, 7, 63, 2, 2, 212, 60, 3, 2, 2, 2, 213, 214, 7, 35, 2, 2, 214, 215, 7, 63, 2, 2, 215, 62, 3, 2, 2, 2, 216, 217, 7, 62, 2, 2, 217, 218, 7, 63, 2, 2, 218, 64, 3, 2, 2, 2, 219, 220, 7, 64, 2, 2, 220, 221, 7, 63, 2, 2, 221, 66, 3, 2, 2, 2, 222, 223, 7, 40, 2, 2, 223, 224, 7, 40, 2, 2, 224, 68, 3, 2, 2, 2, 225, 226, 7, 126, 2, 2, 226, 227, 7, 126, 2, 2, 227, 70, 3, 2, 2, 2, 228, 229, 7, 35, 2, 2, 229, 72, 3, 2, 2, 2, 230, 232, 9, 2, 2, 2, 231, 230, 3, 2, 2, 2, 232, 233, 3, 2, 2, 2, 233, 231, 3, 2, 2, 2, 233, 234, 3, 2, 2, 2, 234, 74, 3, 2, 2, 2, 235, 236, 5, 73, 37, 2, 236, 237, 7, 48, 2, 2, 237, 238, 5, 73, 37, 2, 238, 76, 3, 2, 2, 2, 239, 240, 7, 60, 2, 2, 240, 244, 9, 3, 2, 2, 241, 243, 9, 4, 2, 2, 242, 241, 3, 2, 2, 2, 243, 246, 3, 2, 2, 2, 244, 242, 3, 2, 2, 2, 244, 245, 3, 2, 2, 2, 245, 78, 3, 2, 2, 2, 246, 244, 3, 2, 2, 2, 247, 249, 9, 5, 2, 2, 248, 247, 3, 2, 2, 2, 249, 250, 3, 2, 2, 2, 250, 248, 3, 2, 2, 2, 250, 251, 3, 2, 2, 2, 251, 80, 3, 2, 2, 2, 252, 254, 9, 6, 2, 2, 253, 252, 3, 2, 2, 2, 254, 255, 3, 2, 2, 2, 255, 253, 3, 2, 2, 2, 255, 256, 3, 2, 2, 2, 256, 257, 3, 2, 2, 2, 257, 258, 8, 41, 2, 2, 258, 82, 3, 2, 2, 2, 259, 260, 7, 49, 2, 2, 260, 261, 7, 49, 2, 2, 261, 265, 3, 2, 2, 2, 262, 264, 10, 7, 2, 2, 263, 262, 3, 2, 2, 2, 264, 267, 3, 2, 2, 2, 265, 263, 3, 2, 2, 2, 265, 266, 3, 2, 2, 2, 266, 268, 3, 2, 2, 2, 267, 265, 3, 2, 2, 2, 268, 269, 8, 42, 2, 2, 269, 84, 3, 2, 2, 2, 8, 2, 233, 244, 250, 255, 265, 3, 8, 2, 2] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 44, 286, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 6, 37, 234, 10, 37, 13, 37, 14, 37, 235, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 7, 39, 245, 10, 39, 12, 39, 14, 39, 248, 11, 39, 3, 40, 6, 40, 251, 10, 40, 13, 40, 14, 40, 252, 3, 41, 6, 41, 256, 10, 41, 13, 41, 14, 41, 257, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 42, 7, 42, 266, 10, 42, 12, 42, 14, 42, 269, 11, 42, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 7, 43, 277, 10, 43, 12, 43, 14, 43, 280, 11, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 278, 2, 44, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 81, 42, 83, 43, 85, 44, 3, 2, 8, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 67, 92, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 291, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2, 83, 3, 2, 2, 2, 2, 85, 3, 2, 2, 2, 3, 87, 3, 2, 2, 2, 5, 90, 3, 2, 2, 2, 7, 92, 3, 2, 2, 2, 9, 94, 3, 2, 2, 2, 11, 99, 3, 2, 2, 2, 13, 106, 3, 2, 2, 2, 15, 114, 3, 2, 2, 2, 17, 119, 3, 2, 2, 2, 19, 121, 3, 2, 2, 2, 21, 123, 3, 2, 2, 2, 23, 125, 3, 2, 2, 2, 25, 127, 3, 2, 2, 2, 27, 135, 3, 2, 2, 2, 29, 144, 3, 2, 2, 2, 31, 149, 3, 2, 2, 2, 33, 155, 3, 2, 2, 2, 35, 161, 3, 2, 2, 2, 37, 169, 3, 2, 2, 2, 39, 175, 3, 2, 2, 2, 41, 182, 3, 2, 2, 2, 43, 189, 3, 2, 2, 2, 45, 191, 3, 2, 2, 2, 47, 193, 3, 2, 2, 2, 49, 195, 3, 2, 2, 2, 51, 197, 3, 2, 2, 2, 53, 199, 3, 2, 2, 2, 55, 208, 3, 2, 2, 2, 57, 210, 3, 2, 2, 2, 59, 212, 3, 2, 2, 2, 61, 215, 3, 2, 2, 2, 63, 218, 3, 2, 2, 2, 65, 221, 3, 2, 2, 2, 67, 224, 3, 2, 2, 2, 69, 227, 3, 2, 2, 2, 71, 230, 3, 2, 2, 2, 73, 233, 3, 2, 2, 2, 75, 237, 3, 2, 2, 2, 77, 241, 3, 2, 2, 2, 79, 250, 3, 2, 2, 2, 81, 255, 3, 2, 2, 2, 83, 261, 3, 2, 2, 2, 85, 272, 3, 2, 2, 2, 87, 88, 7, 107, 2, 2, 88, 89, 7, 104, 2, 2, 89, 4, 3, 2, 2, 2, 90, 91, 7, 93, 2, 2, 91, 6, 3, 2, 2, 2, 92, 93, 7, 95, 2, 2, 93, 8, 3, 2, 2, 2, 94, 95, 7, 103, 2, 2, 95, 96, 7, 110, 2, 2, 96, 97, 7, 117, 2, 2, 97, 98, 7, 103, 2, 2, 98, 10, 3, 2, 2, 2, 99, 100, 7, 116, 2, 2, 100, 101, 7, 103, 2, 2, 101, 102, 7, 114, 2, 2, 102, 103, 7, 103, 2, 2, 103, 104, 7, 99, 2, 2, 104, 105, 7, 118, 2, 2, 105, 12, 3, 2, 2, 2, 106, 107, 7, 66, 2, 2, 107, 108, 7, 119, 2, 2, 108, 109, 7, 112, 2, 2, 109, 110, 7, 116, 2, 2, 110, 111, 7, 113, 2, 2, 111, 112, 7, 110, 2, 2, 112, 113, 7, 110, 2, 2, 113, 14, 3, 2, 2, 2, 114, 115, 7, 105, 2, 2, 115, 116, 7, 113, 2, 2, 116, 117, 7, 118, 2, 2, 117, 118, 7, 113, 2, 2, 118, 16, 3, 2, 2, 2, 119, 120, 7, 42, 2, 2, 120, 18, 3, 2, 2, 2, 121, 122, 7, 46, 2, 2, 122, 20, 3, 2, 2, 2, 123, 124, 7, 43, 2, 2, 124, 22, 3, 2, 2, 2, 125, 126, 7, 63, 2, 2, 126, 24, 3, 2, 2, 2, 127, 128, 7, 104, 2, 2, 128, 129, 7, 113, 2, 2, 129, 130, 7, 116, 2, 2, 130, 131, 7, 121, 2, 2, 131, 132, 7, 99, 2, 2, 132, 133, 7, 116, 2, 2, 133, 134, 7, 102, 2, 2, 134, 26, 3, 2, 2, 2, 135, 136, 7, 100, 2, 2, 136, 137, 7, 99, 2, 2, 137, 138, 7, 101, 2, 2, 138, 139, 7, 109, 2, 2, 139, 140, 7, 121, 2, 2, 140, 141, 7, 99, 2, 2, 141, 142, 7, 116, 2, 2, 142, 143, 7, 102, 2, 2, 143, 28, 3, 2, 2, 2, 144, 145, 7, 110, 2, 2, 145, 146, 7, 103, 2, 2, 146, 147, 7, 104, 2, 2, 147, 148, 7, 118, 2, 2, 148, 30, 3, 2, 2, 2, 149, 150, 7, 116, 2, 2, 150, 151, 7, 107, 2, 2, 151, 152, 7, 105, 2, 2, 152, 153, 7, 106, 2, 2, 153, 154, 7, 118, 2, 2, 154, 32, 3, 2, 2, 2, 155, 156, 7, 114, 2, 2, 156, 157, 7, 103, 2, 2, 157, 158, 7, 112, 2, 2, 158, 159, 7, 119, 2, 2, 159, 160, 7, 114, 2, 2, 160, 34, 3, 2, 2, 2, 161, 162, 7, 114, 2, 2, 162, 163, 7, 103, 2, 2, 163, 164, 7, 112, 2, 2, 164, 165, 7, 102, 2, 2, 165, 166, 7, 113, 2, 2, 166, 167, 7, 121, 2, 2, 167, 168, 7, 112, 2, 2, 168, 36, 3, 2, 2, 2, 169, 170, 7, 114, 2, 2, 170, 171, 7, 99, 2, 2, 171, 172, 7, 119, 2, 2, 172, 173, 7, 117, 2, 2, 173, 174, 7, 103, 2, 2, 174, 38, 3, 2, 2, 2, 175, 176, 7, 99, 2, 2, 176, 177, 7, 117, 2, 2, 177, 178, 7, 117, 2, 2, 178, 179, 7, 103, 2, 2, 179, 180, 7, 116, 2, 2, 180, 181, 7, 118, 2, 2, 181, 40, 3, 2, 2, 2, 182, 183, 7, 99, 2, 2, 183, 184, 7, 117, 2, 2, 184, 185, 7, 117, 2, 2, 185, 186, 7, 119, 2, 2, 186, 187, 7, 111, 2, 2, 187, 188, 7, 103, 2, 2, 188, 42, 3, 2, 2, 2, 189, 190, 7, 45, 2, 2, 190, 44, 3, 2, 2, 2, 191, 192, 7, 47, 2, 2, 192, 46, 3, 2, 2, 2, 193, 194, 7, 44, 2, 2, 194, 48, 3, 2, 2, 2, 195, 196, 7, 49, 2, 2, 196, 50, 3, 2, 2, 2, 197, 198, 7, 39, 2, 2, 198, 52, 3, 2, 2, 2, 199, 200, 7, 114, 2, 2, 200, 201, 7, 103, 2, 2, 201, 202, 7, 112, 2, 2, 202, 203, 7, 102, 2, 2, 203, 204, 7, 113, 2, 2, 204, 205, 7, 121, 2, 2, 205, 206, 7, 112, 2, 2, 206, 207, 7, 65, 2, 2, 207, 54, 3, 2, 2, 2, 208, 209, 7, 62, 2, 2, 209, 56, 3, 2, 2, 2, 210, 211, 7, 64, 2, 2, 211, 58, 3, 2, 2, 2, 212, 213, 7, 63, 2, 2, 213, 214, 7, 63, 2, 2, 214, 60, 3, 2, 2, 2, 215, 216, 7, 35, 2, 2, 216, 217, 7, 63, 2, 2, 217, 62, 3, 2, 2, 2, 218, 219, 7, 62, 2, 2, 219, 220, 7, 63, 2, 2, 220, 64, 3, 2, 2, 2, 221, 222, 7, 64, 2, 2, 222, 223, 7, 63, 2, 2, 223, 66, 3, 2, 2, 2, 224, 225, 7, 40, 2, 2, 225, 226, 7, 40, 2, 2, 226, 68, 3, 2, 2, 2, 227, 228, 7, 126, 2, 2, 228, 229, 7, 126, 2, 2, 229, 70, 3, 2, 2, 2, 230, 231, 7, 35, 2, 2, 231, 72, 3, 2, 2, 2, 232, 234, 9, 2, 2, 2, 233, 232, 3, 2, 2, 2, 234, 235, 3, 2, 2, 2, 235, 233, 3, 2, 2, 2, 235, 236, 3, 2, 2, 2, 236, 74, 3, 2, 2, 2, 237, 238, 5, 73, 37, 2, 238, 239, 7, 48, 2, 2, 239, 240, 5, 73, 37, 2, 240, 76, 3, 2, 2, 2, 241, 242, 7, 60, 2, 2, 242, 246, 9, 3, 2, 2, 243, 245, 9, 4, 2, 2, 244, 243, 3, 2, 2, 2, 245, 248, 3, 2, 2, 2, 246, 244, 3, 2, 2, 2, 246, 247, 3, 2, 2, 2, 247, 78, 3, 2, 2, 2, 248, 246, 3, 2, 2, 2, 249, 251, 9, 5, 2, 2, 250, 249, 3, 2, 2, 2, 251, 252, 3, 2, 2, 2, 252, 250, 3, 2, 2, 2, 252, 253, 3, 2, 2, 2, 253, 80, 3, 2, 2, 2, 254, 256, 9, 6, 2, 2, 255, 254, 3, 2, 2, 2, 256, 257, 3, 2, 2, 2, 257, 255, 3, 2, 2, 2, 257, 258, 3, 2, 2, 2, 258, 259, 3, 2, 2, 2, 259, 260, 8, 41, 2, 2, 260, 82, 3, 2, 2, 2, 261, 262, 7, 49, 2, 2, 262, 263, 7, 49, 2, 2, 263, 267, 3, 2, 2, 2, 264, 266, 10, 7, 2, 2, 265, 264, 3, 2, 2, 2, 266, 269, 3, 2, 2, 2, 267, 265, 3, 2, 2, 2, 267, 268, 3, 2, 2, 2, 268, 270, 3, 2, 2, 2, 269, 267, 3, 2, 2, 2, 270, 271, 8, 42, 2, 2, 271, 84, 3, 2, 2, 2, 272, 273, 7, 49, 2, 2, 273, 274, 7, 44, 2, 2, 274, 278, 3, 2, 2, 2, 275, 277, 11, 2, 2, 2, 276, 275, 3, 2, 2, 2, 277, 280, 3, 2, 2, 2, 278, 279, 3, 2, 2, 2, 278, 276, 3, 2, 2, 2, 279, 281, 3, 2, 2, 2, 280, 278, 3, 2, 2, 2, 281, 282, 7, 44, 2, 2, 282, 283, 7, 49, 2, 2, 283, 284, 3, 2, 2, 2, 284, 285, 8, 43, 2, 2, 285, 86, 3, 2, 2, 2, 9, 2, 235, 246, 252, 257, 267, 278, 3, 8, 2, 2] \ No newline at end of file diff --git a/ChironCore/turtparse/tlangLexer.py b/ChironCore/turtparse/tlangLexer.py index e8d8c8a..95d0321 100644 --- a/ChironCore/turtparse/tlangLexer.py +++ b/ChironCore/turtparse/tlangLexer.py @@ -8,113 +8,121 @@ def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2+") - buf.write("\u010e\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2,") + buf.write("\u011e\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7") buf.write("\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r") buf.write("\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23") buf.write("\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30") buf.write("\4\31\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36") buf.write("\t\36\4\37\t\37\4 \t \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%") - buf.write("\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\3\2\3\2\3\2\3\3\3\3\3") - buf.write("\4\3\4\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6") - buf.write("\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3") - buf.write("\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3") - buf.write("\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16") - buf.write("\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20") - buf.write("\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22") - buf.write("\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24") - buf.write("\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25") - buf.write("\3\25\3\26\3\26\3\27\3\27\3\30\3\30\3\31\3\31\3\32\3\32") - buf.write("\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\34\3\34") - buf.write("\3\35\3\35\3\36\3\36\3\36\3\37\3\37\3\37\3 \3 \3 \3!\3") - buf.write("!\3!\3\"\3\"\3\"\3#\3#\3#\3$\3$\3%\6%\u00e8\n%\r%\16%") - buf.write("\u00e9\3&\3&\3&\3&\3\'\3\'\3\'\7\'\u00f3\n\'\f\'\16\'") - buf.write("\u00f6\13\'\3(\6(\u00f9\n(\r(\16(\u00fa\3)\6)\u00fe\n") - buf.write(")\r)\16)\u00ff\3)\3)\3*\3*\3*\3*\7*\u0108\n*\f*\16*\u010b") - buf.write("\13*\3*\3*\2\2+\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23") - buf.write("\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25") - buf.write(")\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A") - buf.write("\"C#E$G%I&K\'M(O)Q*S+\3\2\b\3\2\62;\5\2C\\aac|\5\2\62") - buf.write(";C\\c|\4\2C\\c|\5\2\13\f\17\17\"\"\4\2\f\f\17\17\2\u0112") - buf.write("\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13") - buf.write("\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3") - buf.write("\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2") - buf.write("\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2") - buf.write("%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2") - buf.write("\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67") - buf.write("\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2") - buf.write("A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2") - buf.write("\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2") - buf.write("\2\3U\3\2\2\2\5X\3\2\2\2\7Z\3\2\2\2\t\\\3\2\2\2\13a\3") - buf.write("\2\2\2\rh\3\2\2\2\17p\3\2\2\2\21u\3\2\2\2\23w\3\2\2\2") - buf.write("\25y\3\2\2\2\27{\3\2\2\2\31}\3\2\2\2\33\u0085\3\2\2\2") - buf.write("\35\u008e\3\2\2\2\37\u0093\3\2\2\2!\u0099\3\2\2\2#\u009f") - buf.write("\3\2\2\2%\u00a7\3\2\2\2\'\u00ad\3\2\2\2)\u00b4\3\2\2\2") - buf.write("+\u00bb\3\2\2\2-\u00bd\3\2\2\2/\u00bf\3\2\2\2\61\u00c1") - buf.write("\3\2\2\2\63\u00c3\3\2\2\2\65\u00c5\3\2\2\2\67\u00ce\3") - buf.write("\2\2\29\u00d0\3\2\2\2;\u00d2\3\2\2\2=\u00d5\3\2\2\2?\u00d8") - buf.write("\3\2\2\2A\u00db\3\2\2\2C\u00de\3\2\2\2E\u00e1\3\2\2\2") - buf.write("G\u00e4\3\2\2\2I\u00e7\3\2\2\2K\u00eb\3\2\2\2M\u00ef\3") - buf.write("\2\2\2O\u00f8\3\2\2\2Q\u00fd\3\2\2\2S\u0103\3\2\2\2UV") - buf.write("\7k\2\2VW\7h\2\2W\4\3\2\2\2XY\7]\2\2Y\6\3\2\2\2Z[\7_\2") - buf.write("\2[\b\3\2\2\2\\]\7g\2\2]^\7n\2\2^_\7u\2\2_`\7g\2\2`\n") - buf.write("\3\2\2\2ab\7t\2\2bc\7g\2\2cd\7r\2\2de\7g\2\2ef\7c\2\2") - buf.write("fg\7v\2\2g\f\3\2\2\2hi\7B\2\2ij\7w\2\2jk\7p\2\2kl\7t\2") - buf.write("\2lm\7q\2\2mn\7n\2\2no\7n\2\2o\16\3\2\2\2pq\7i\2\2qr\7") - buf.write("q\2\2rs\7v\2\2st\7q\2\2t\20\3\2\2\2uv\7*\2\2v\22\3\2\2") - buf.write("\2wx\7.\2\2x\24\3\2\2\2yz\7+\2\2z\26\3\2\2\2{|\7?\2\2") - buf.write("|\30\3\2\2\2}~\7h\2\2~\177\7q\2\2\177\u0080\7t\2\2\u0080") - buf.write("\u0081\7y\2\2\u0081\u0082\7c\2\2\u0082\u0083\7t\2\2\u0083") - buf.write("\u0084\7f\2\2\u0084\32\3\2\2\2\u0085\u0086\7d\2\2\u0086") - buf.write("\u0087\7c\2\2\u0087\u0088\7e\2\2\u0088\u0089\7m\2\2\u0089") - buf.write("\u008a\7y\2\2\u008a\u008b\7c\2\2\u008b\u008c\7t\2\2\u008c") - buf.write("\u008d\7f\2\2\u008d\34\3\2\2\2\u008e\u008f\7n\2\2\u008f") - buf.write("\u0090\7g\2\2\u0090\u0091\7h\2\2\u0091\u0092\7v\2\2\u0092") - buf.write("\36\3\2\2\2\u0093\u0094\7t\2\2\u0094\u0095\7k\2\2\u0095") - buf.write("\u0096\7i\2\2\u0096\u0097\7j\2\2\u0097\u0098\7v\2\2\u0098") - buf.write(" \3\2\2\2\u0099\u009a\7r\2\2\u009a\u009b\7g\2\2\u009b") - buf.write("\u009c\7p\2\2\u009c\u009d\7w\2\2\u009d\u009e\7r\2\2\u009e") - buf.write("\"\3\2\2\2\u009f\u00a0\7r\2\2\u00a0\u00a1\7g\2\2\u00a1") - buf.write("\u00a2\7p\2\2\u00a2\u00a3\7f\2\2\u00a3\u00a4\7q\2\2\u00a4") - buf.write("\u00a5\7y\2\2\u00a5\u00a6\7p\2\2\u00a6$\3\2\2\2\u00a7") - buf.write("\u00a8\7r\2\2\u00a8\u00a9\7c\2\2\u00a9\u00aa\7w\2\2\u00aa") - buf.write("\u00ab\7u\2\2\u00ab\u00ac\7g\2\2\u00ac&\3\2\2\2\u00ad") - buf.write("\u00ae\7c\2\2\u00ae\u00af\7u\2\2\u00af\u00b0\7u\2\2\u00b0") - buf.write("\u00b1\7g\2\2\u00b1\u00b2\7t\2\2\u00b2\u00b3\7v\2\2\u00b3") - buf.write("(\3\2\2\2\u00b4\u00b5\7c\2\2\u00b5\u00b6\7u\2\2\u00b6") - buf.write("\u00b7\7u\2\2\u00b7\u00b8\7w\2\2\u00b8\u00b9\7o\2\2\u00b9") - buf.write("\u00ba\7g\2\2\u00ba*\3\2\2\2\u00bb\u00bc\7-\2\2\u00bc") - buf.write(",\3\2\2\2\u00bd\u00be\7/\2\2\u00be.\3\2\2\2\u00bf\u00c0") - buf.write("\7,\2\2\u00c0\60\3\2\2\2\u00c1\u00c2\7\61\2\2\u00c2\62") - buf.write("\3\2\2\2\u00c3\u00c4\7\'\2\2\u00c4\64\3\2\2\2\u00c5\u00c6") - buf.write("\7r\2\2\u00c6\u00c7\7g\2\2\u00c7\u00c8\7p\2\2\u00c8\u00c9") - buf.write("\7f\2\2\u00c9\u00ca\7q\2\2\u00ca\u00cb\7y\2\2\u00cb\u00cc") - buf.write("\7p\2\2\u00cc\u00cd\7A\2\2\u00cd\66\3\2\2\2\u00ce\u00cf") - buf.write("\7>\2\2\u00cf8\3\2\2\2\u00d0\u00d1\7@\2\2\u00d1:\3\2\2") - buf.write("\2\u00d2\u00d3\7?\2\2\u00d3\u00d4\7?\2\2\u00d4<\3\2\2") - buf.write("\2\u00d5\u00d6\7#\2\2\u00d6\u00d7\7?\2\2\u00d7>\3\2\2") - buf.write("\2\u00d8\u00d9\7>\2\2\u00d9\u00da\7?\2\2\u00da@\3\2\2") - buf.write("\2\u00db\u00dc\7@\2\2\u00dc\u00dd\7?\2\2\u00ddB\3\2\2") - buf.write("\2\u00de\u00df\7(\2\2\u00df\u00e0\7(\2\2\u00e0D\3\2\2") - buf.write("\2\u00e1\u00e2\7~\2\2\u00e2\u00e3\7~\2\2\u00e3F\3\2\2") - buf.write("\2\u00e4\u00e5\7#\2\2\u00e5H\3\2\2\2\u00e6\u00e8\t\2\2") - buf.write("\2\u00e7\u00e6\3\2\2\2\u00e8\u00e9\3\2\2\2\u00e9\u00e7") - buf.write("\3\2\2\2\u00e9\u00ea\3\2\2\2\u00eaJ\3\2\2\2\u00eb\u00ec") - buf.write("\5I%\2\u00ec\u00ed\7\60\2\2\u00ed\u00ee\5I%\2\u00eeL\3") - buf.write("\2\2\2\u00ef\u00f0\7<\2\2\u00f0\u00f4\t\3\2\2\u00f1\u00f3") - buf.write("\t\4\2\2\u00f2\u00f1\3\2\2\2\u00f3\u00f6\3\2\2\2\u00f4") - buf.write("\u00f2\3\2\2\2\u00f4\u00f5\3\2\2\2\u00f5N\3\2\2\2\u00f6") - buf.write("\u00f4\3\2\2\2\u00f7\u00f9\t\5\2\2\u00f8\u00f7\3\2\2\2") - buf.write("\u00f9\u00fa\3\2\2\2\u00fa\u00f8\3\2\2\2\u00fa\u00fb\3") - buf.write("\2\2\2\u00fbP\3\2\2\2\u00fc\u00fe\t\6\2\2\u00fd\u00fc") - buf.write("\3\2\2\2\u00fe\u00ff\3\2\2\2\u00ff\u00fd\3\2\2\2\u00ff") - buf.write("\u0100\3\2\2\2\u0100\u0101\3\2\2\2\u0101\u0102\b)\2\2") - buf.write("\u0102R\3\2\2\2\u0103\u0104\7\61\2\2\u0104\u0105\7\61") - buf.write("\2\2\u0105\u0109\3\2\2\2\u0106\u0108\n\7\2\2\u0107\u0106") - buf.write("\3\2\2\2\u0108\u010b\3\2\2\2\u0109\u0107\3\2\2\2\u0109") - buf.write("\u010a\3\2\2\2\u010a\u010c\3\2\2\2\u010b\u0109\3\2\2\2") - buf.write("\u010c\u010d\b*\2\2\u010dT\3\2\2\2\b\2\u00e9\u00f4\u00fa") - buf.write("\u00ff\u0109\3\b\2\2") + buf.write("\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\3\2\3\2\3\2\3\3") + buf.write("\3\3\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3") + buf.write("\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b") + buf.write("\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\r\3\r") + buf.write("\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3") + buf.write("\16\3\16\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20") + buf.write("\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22") + buf.write("\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23") + buf.write("\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25") + buf.write("\3\25\3\25\3\25\3\26\3\26\3\27\3\27\3\30\3\30\3\31\3\31") + buf.write("\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33") + buf.write("\3\34\3\34\3\35\3\35\3\36\3\36\3\36\3\37\3\37\3\37\3 ") + buf.write("\3 \3 \3!\3!\3!\3\"\3\"\3\"\3#\3#\3#\3$\3$\3%\6%\u00ea") + buf.write("\n%\r%\16%\u00eb\3&\3&\3&\3&\3\'\3\'\3\'\7\'\u00f5\n\'") + buf.write("\f\'\16\'\u00f8\13\'\3(\6(\u00fb\n(\r(\16(\u00fc\3)\6") + buf.write(")\u0100\n)\r)\16)\u0101\3)\3)\3*\3*\3*\3*\7*\u010a\n*") + buf.write("\f*\16*\u010d\13*\3*\3*\3+\3+\3+\3+\7+\u0115\n+\f+\16") + buf.write("+\u0118\13+\3+\3+\3+\3+\3+\3\u0116\2,\3\3\5\4\7\5\t\6") + buf.write("\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20") + buf.write("\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65") + buf.write("\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,\3\2\b\3") + buf.write("\2\62;\5\2C\\aac|\5\2\62;C\\c|\4\2C\\c|\5\2\13\f\17\17") + buf.write("\"\"\4\2\f\f\17\17\2\u0123\2\3\3\2\2\2\2\5\3\2\2\2\2\7") + buf.write("\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2") + buf.write("\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2") + buf.write("\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2") + buf.write("\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2") + buf.write("\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63") + buf.write("\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2") + buf.write("\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2") + buf.write("\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3") + buf.write("\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\3W\3\2\2\2\5Z") + buf.write("\3\2\2\2\7\\\3\2\2\2\t^\3\2\2\2\13c\3\2\2\2\rj\3\2\2\2") + buf.write("\17r\3\2\2\2\21w\3\2\2\2\23y\3\2\2\2\25{\3\2\2\2\27}\3") + buf.write("\2\2\2\31\177\3\2\2\2\33\u0087\3\2\2\2\35\u0090\3\2\2") + buf.write("\2\37\u0095\3\2\2\2!\u009b\3\2\2\2#\u00a1\3\2\2\2%\u00a9") + buf.write("\3\2\2\2\'\u00af\3\2\2\2)\u00b6\3\2\2\2+\u00bd\3\2\2\2") + buf.write("-\u00bf\3\2\2\2/\u00c1\3\2\2\2\61\u00c3\3\2\2\2\63\u00c5") + buf.write("\3\2\2\2\65\u00c7\3\2\2\2\67\u00d0\3\2\2\29\u00d2\3\2") + buf.write("\2\2;\u00d4\3\2\2\2=\u00d7\3\2\2\2?\u00da\3\2\2\2A\u00dd") + buf.write("\3\2\2\2C\u00e0\3\2\2\2E\u00e3\3\2\2\2G\u00e6\3\2\2\2") + buf.write("I\u00e9\3\2\2\2K\u00ed\3\2\2\2M\u00f1\3\2\2\2O\u00fa\3") + buf.write("\2\2\2Q\u00ff\3\2\2\2S\u0105\3\2\2\2U\u0110\3\2\2\2WX") + buf.write("\7k\2\2XY\7h\2\2Y\4\3\2\2\2Z[\7]\2\2[\6\3\2\2\2\\]\7_") + buf.write("\2\2]\b\3\2\2\2^_\7g\2\2_`\7n\2\2`a\7u\2\2ab\7g\2\2b\n") + buf.write("\3\2\2\2cd\7t\2\2de\7g\2\2ef\7r\2\2fg\7g\2\2gh\7c\2\2") + buf.write("hi\7v\2\2i\f\3\2\2\2jk\7B\2\2kl\7w\2\2lm\7p\2\2mn\7t\2") + buf.write("\2no\7q\2\2op\7n\2\2pq\7n\2\2q\16\3\2\2\2rs\7i\2\2st\7") + buf.write("q\2\2tu\7v\2\2uv\7q\2\2v\20\3\2\2\2wx\7*\2\2x\22\3\2\2") + buf.write("\2yz\7.\2\2z\24\3\2\2\2{|\7+\2\2|\26\3\2\2\2}~\7?\2\2") + buf.write("~\30\3\2\2\2\177\u0080\7h\2\2\u0080\u0081\7q\2\2\u0081") + buf.write("\u0082\7t\2\2\u0082\u0083\7y\2\2\u0083\u0084\7c\2\2\u0084") + buf.write("\u0085\7t\2\2\u0085\u0086\7f\2\2\u0086\32\3\2\2\2\u0087") + buf.write("\u0088\7d\2\2\u0088\u0089\7c\2\2\u0089\u008a\7e\2\2\u008a") + buf.write("\u008b\7m\2\2\u008b\u008c\7y\2\2\u008c\u008d\7c\2\2\u008d") + buf.write("\u008e\7t\2\2\u008e\u008f\7f\2\2\u008f\34\3\2\2\2\u0090") + buf.write("\u0091\7n\2\2\u0091\u0092\7g\2\2\u0092\u0093\7h\2\2\u0093") + buf.write("\u0094\7v\2\2\u0094\36\3\2\2\2\u0095\u0096\7t\2\2\u0096") + buf.write("\u0097\7k\2\2\u0097\u0098\7i\2\2\u0098\u0099\7j\2\2\u0099") + buf.write("\u009a\7v\2\2\u009a \3\2\2\2\u009b\u009c\7r\2\2\u009c") + buf.write("\u009d\7g\2\2\u009d\u009e\7p\2\2\u009e\u009f\7w\2\2\u009f") + buf.write("\u00a0\7r\2\2\u00a0\"\3\2\2\2\u00a1\u00a2\7r\2\2\u00a2") + buf.write("\u00a3\7g\2\2\u00a3\u00a4\7p\2\2\u00a4\u00a5\7f\2\2\u00a5") + buf.write("\u00a6\7q\2\2\u00a6\u00a7\7y\2\2\u00a7\u00a8\7p\2\2\u00a8") + buf.write("$\3\2\2\2\u00a9\u00aa\7r\2\2\u00aa\u00ab\7c\2\2\u00ab") + buf.write("\u00ac\7w\2\2\u00ac\u00ad\7u\2\2\u00ad\u00ae\7g\2\2\u00ae") + buf.write("&\3\2\2\2\u00af\u00b0\7c\2\2\u00b0\u00b1\7u\2\2\u00b1") + buf.write("\u00b2\7u\2\2\u00b2\u00b3\7g\2\2\u00b3\u00b4\7t\2\2\u00b4") + buf.write("\u00b5\7v\2\2\u00b5(\3\2\2\2\u00b6\u00b7\7c\2\2\u00b7") + buf.write("\u00b8\7u\2\2\u00b8\u00b9\7u\2\2\u00b9\u00ba\7w\2\2\u00ba") + buf.write("\u00bb\7o\2\2\u00bb\u00bc\7g\2\2\u00bc*\3\2\2\2\u00bd") + buf.write("\u00be\7-\2\2\u00be,\3\2\2\2\u00bf\u00c0\7/\2\2\u00c0") + buf.write(".\3\2\2\2\u00c1\u00c2\7,\2\2\u00c2\60\3\2\2\2\u00c3\u00c4") + buf.write("\7\61\2\2\u00c4\62\3\2\2\2\u00c5\u00c6\7\'\2\2\u00c6\64") + buf.write("\3\2\2\2\u00c7\u00c8\7r\2\2\u00c8\u00c9\7g\2\2\u00c9\u00ca") + buf.write("\7p\2\2\u00ca\u00cb\7f\2\2\u00cb\u00cc\7q\2\2\u00cc\u00cd") + buf.write("\7y\2\2\u00cd\u00ce\7p\2\2\u00ce\u00cf\7A\2\2\u00cf\66") + buf.write("\3\2\2\2\u00d0\u00d1\7>\2\2\u00d18\3\2\2\2\u00d2\u00d3") + buf.write("\7@\2\2\u00d3:\3\2\2\2\u00d4\u00d5\7?\2\2\u00d5\u00d6") + buf.write("\7?\2\2\u00d6<\3\2\2\2\u00d7\u00d8\7#\2\2\u00d8\u00d9") + buf.write("\7?\2\2\u00d9>\3\2\2\2\u00da\u00db\7>\2\2\u00db\u00dc") + buf.write("\7?\2\2\u00dc@\3\2\2\2\u00dd\u00de\7@\2\2\u00de\u00df") + buf.write("\7?\2\2\u00dfB\3\2\2\2\u00e0\u00e1\7(\2\2\u00e1\u00e2") + buf.write("\7(\2\2\u00e2D\3\2\2\2\u00e3\u00e4\7~\2\2\u00e4\u00e5") + buf.write("\7~\2\2\u00e5F\3\2\2\2\u00e6\u00e7\7#\2\2\u00e7H\3\2\2") + buf.write("\2\u00e8\u00ea\t\2\2\2\u00e9\u00e8\3\2\2\2\u00ea\u00eb") + buf.write("\3\2\2\2\u00eb\u00e9\3\2\2\2\u00eb\u00ec\3\2\2\2\u00ec") + buf.write("J\3\2\2\2\u00ed\u00ee\5I%\2\u00ee\u00ef\7\60\2\2\u00ef") + buf.write("\u00f0\5I%\2\u00f0L\3\2\2\2\u00f1\u00f2\7<\2\2\u00f2\u00f6") + buf.write("\t\3\2\2\u00f3\u00f5\t\4\2\2\u00f4\u00f3\3\2\2\2\u00f5") + buf.write("\u00f8\3\2\2\2\u00f6\u00f4\3\2\2\2\u00f6\u00f7\3\2\2\2") + buf.write("\u00f7N\3\2\2\2\u00f8\u00f6\3\2\2\2\u00f9\u00fb\t\5\2") + buf.write("\2\u00fa\u00f9\3\2\2\2\u00fb\u00fc\3\2\2\2\u00fc\u00fa") + buf.write("\3\2\2\2\u00fc\u00fd\3\2\2\2\u00fdP\3\2\2\2\u00fe\u0100") + buf.write("\t\6\2\2\u00ff\u00fe\3\2\2\2\u0100\u0101\3\2\2\2\u0101") + buf.write("\u00ff\3\2\2\2\u0101\u0102\3\2\2\2\u0102\u0103\3\2\2\2") + buf.write("\u0103\u0104\b)\2\2\u0104R\3\2\2\2\u0105\u0106\7\61\2") + buf.write("\2\u0106\u0107\7\61\2\2\u0107\u010b\3\2\2\2\u0108\u010a") + buf.write("\n\7\2\2\u0109\u0108\3\2\2\2\u010a\u010d\3\2\2\2\u010b") + buf.write("\u0109\3\2\2\2\u010b\u010c\3\2\2\2\u010c\u010e\3\2\2\2") + buf.write("\u010d\u010b\3\2\2\2\u010e\u010f\b*\2\2\u010fT\3\2\2\2") + buf.write("\u0110\u0111\7\61\2\2\u0111\u0112\7,\2\2\u0112\u0116\3") + buf.write("\2\2\2\u0113\u0115\13\2\2\2\u0114\u0113\3\2\2\2\u0115") + buf.write("\u0118\3\2\2\2\u0116\u0117\3\2\2\2\u0116\u0114\3\2\2\2") + buf.write("\u0117\u0119\3\2\2\2\u0118\u0116\3\2\2\2\u0119\u011a\7") + buf.write(",\2\2\u011a\u011b\7\61\2\2\u011b\u011c\3\2\2\2\u011c\u011d") + buf.write("\b+\2\2\u011dV\3\2\2\2\t\2\u00eb\u00f6\u00fc\u0101\u010b") + buf.write("\u0116\3\b\2\2") return buf.getvalue() @@ -164,7 +172,8 @@ class tlangLexer(Lexer): VAR = 38 NAME = 39 Whitespace = 40 - Comment = 41 + COMMENT_LINE = 41 + COMMENT_BLOCK = 42 channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] @@ -180,14 +189,15 @@ class tlangLexer(Lexer): symbolicNames = [ "", "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", "FLOAT", - "VAR", "NAME", "Whitespace", "Comment" ] + "VAR", "NAME", "Whitespace", "COMMENT_LINE", "COMMENT_BLOCK" ] ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", "T__17", "T__18", "T__19", "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", - "FLOAT", "VAR", "NAME", "Whitespace", "Comment" ] + "FLOAT", "VAR", "NAME", "Whitespace", "COMMENT_LINE", + "COMMENT_BLOCK" ] grammarFileName = "tlang.g4" diff --git a/ChironCore/turtparse/tlangLexer.tokens b/ChironCore/turtparse/tlangLexer.tokens index 355acdc..39f4806 100644 --- a/ChironCore/turtparse/tlangLexer.tokens +++ b/ChironCore/turtparse/tlangLexer.tokens @@ -38,7 +38,8 @@ FLOAT=37 VAR=38 NAME=39 Whitespace=40 -Comment=41 +COMMENT_LINE=41 +COMMENT_BLOCK=42 'if'=1 '['=2 ']'=3 diff --git a/ChironCore/turtparse/tlangParser.py b/ChironCore/turtparse/tlangParser.py index fee85dd..fce79b5 100644 --- a/ChironCore/turtparse/tlangParser.py +++ b/ChironCore/turtparse/tlangParser.py @@ -8,7 +8,7 @@ def serializedATN(): with StringIO() as buf: - buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3+") + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3,") buf.write("\u00cd\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16") buf.write("\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\4\23\t\23") @@ -114,7 +114,7 @@ class tlangParser ( Parser ): "", "PLUS", "MINUS", "MUL", "DIV", "MOD", "PENCOND", "LT", "GT", "EQ", "NEQ", "LTE", "GTE", "AND", "OR", "NOT", "NUM", "FLOAT", "VAR", "NAME", - "Whitespace", "Comment" ] + "Whitespace", "COMMENT_LINE", "COMMENT_BLOCK" ] RULE_start = 0 RULE_instruction_list = 1 @@ -191,7 +191,8 @@ class tlangParser ( Parser ): VAR=38 NAME=39 Whitespace=40 - Comment=41 + COMMENT_LINE=41 + COMMENT_BLOCK=42 def __init__(self, input:TokenStream, output:TextIO = sys.stdout): super().__init__(input, output) diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index f7b906b..1297bd4 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,206 +1,3 @@ -forward10 -assert:turtleX==10 -:_repeat0 = :turtleX -assume :_repeat0 <= 50 -if (:_repeat0 > 0) [ -:x=:x+1 - -] -if (:_repeat0 > 1) [ -:x=:x+1 - -] -if (:_repeat0 > 2) [ -:x=:x+1 - -] -if (:_repeat0 > 3) [ -:x=:x+1 - -] -if (:_repeat0 > 4) [ -:x=:x+1 - -] -if (:_repeat0 > 5) [ -:x=:x+1 - -] -if (:_repeat0 > 6) [ -:x=:x+1 - -] -if (:_repeat0 > 7) [ -:x=:x+1 - -] -if (:_repeat0 > 8) [ -:x=:x+1 - -] -if (:_repeat0 > 9) [ -:x=:x+1 - -] -if (:_repeat0 > 10) [ -:x=:x+1 - -] -if (:_repeat0 > 11) [ -:x=:x+1 - -] -if (:_repeat0 > 12) [ -:x=:x+1 - -] -if (:_repeat0 > 13) [ -:x=:x+1 - -] -if (:_repeat0 > 14) [ -:x=:x+1 - -] -if (:_repeat0 > 15) [ -:x=:x+1 - -] -if (:_repeat0 > 16) [ -:x=:x+1 - -] -if (:_repeat0 > 17) [ -:x=:x+1 - -] -if (:_repeat0 > 18) [ -:x=:x+1 - -] -if (:_repeat0 > 19) [ -:x=:x+1 - -] -if (:_repeat0 > 20) [ -:x=:x+1 - -] -if (:_repeat0 > 21) [ -:x=:x+1 - -] -if (:_repeat0 > 22) [ -:x=:x+1 - -] -if (:_repeat0 > 23) [ -:x=:x+1 - -] -if (:_repeat0 > 24) [ -:x=:x+1 - -] -if (:_repeat0 > 25) [ -:x=:x+1 - -] -if (:_repeat0 > 26) [ -:x=:x+1 - -] -if (:_repeat0 > 27) [ -:x=:x+1 - -] -if (:_repeat0 > 28) [ -:x=:x+1 - -] -if (:_repeat0 > 29) [ -:x=:x+1 - -] -if (:_repeat0 > 30) [ -:x=:x+1 - -] -if (:_repeat0 > 31) [ -:x=:x+1 - -] -if (:_repeat0 > 32) [ -:x=:x+1 - -] -if (:_repeat0 > 33) [ -:x=:x+1 - -] -if (:_repeat0 > 34) [ -:x=:x+1 - -] -if (:_repeat0 > 35) [ -:x=:x+1 - -] -if (:_repeat0 > 36) [ -:x=:x+1 - -] -if (:_repeat0 > 37) [ -:x=:x+1 - -] -if (:_repeat0 > 38) [ -:x=:x+1 - -] -if (:_repeat0 > 39) [ -:x=:x+1 - -] -if (:_repeat0 > 40) [ -:x=:x+1 - -] -if (:_repeat0 > 41) [ -:x=:x+1 - -] -if (:_repeat0 > 42) [ -:x=:x+1 - -] -if (:_repeat0 > 43) [ -:x=:x+1 - -] -if (:_repeat0 > 44) [ -:x=:x+1 - -] -if (:_repeat0 > 45) [ -:x=:x+1 - -] -if (:_repeat0 > 46) [ -:x=:x+1 - -] -if (:_repeat0 > 47) [ -:x=:x+1 - -] -if (:_repeat0 > 48) [ -:x=:x+1 - -] -if (:_repeat0 > 49) [ -:x=:x+1 - -] - -assert:x<=100 +:t=:x+2*:y+3*:z+:x*:w*:u +:z=:x+:w +assert(:x+100<:y)&&(:x+200>:y)&&!(:x>=0)&&(:x*:y<-:x)&&(:t>0) From f9025dd285f04350443819dfa86ef3fc993d2324 Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Thu, 17 Apr 2025 06:36:10 +0530 Subject: [PATCH 51/53] created test cases with explaination --- BMC.md | 6 +- ChironCore/angles.conf | 5 ++ ChironCore/bmc.py | 6 +- ChironCore/bmc_examples/bmc1.tl | 14 +++-- ChironCore/bmc_examples/bmc2.tl | 20 ++++--- ChironCore/bmc_examples/bmc3.tl | 38 +++++++------ ChironCore/bmc_examples/bmc4.tl | 30 ++++++++-- ChironCore/bmc_examples/bmc5.tl | 21 +++++-- ChironCore/bmc_examples/bmc6.tl | 42 ++++++++++++-- ChironCore/bmc_examples/bmc7.tl | 26 --------- ChironCore/unrolled_code.tl | 98 ++++++++++++++++++++++++++++++++- 11 files changed, 227 insertions(+), 79 deletions(-) delete mode 100644 ChironCore/bmc_examples/bmc7.tl diff --git a/BMC.md b/BMC.md index 3e7bff5..202b1c4 100644 --- a/BMC.md +++ b/BMC.md @@ -62,7 +62,7 @@ The variable `:turtlePen` is used to maintain the up/down state of pen. At the start of the program, pen is in pendown state. ## Examples -Examples for working of the BMC engine are provided in the `/ChironCore/bmc_examples/` directory. To run the BMC engine on these test cases, navigate to the `ChironCore` directory and execute the following command: +Examples demonstrating working of the BMC engine with explaination are provided in the `/ChironCore/bmc_examples/` directory. To run the BMC engine on these test cases, navigate to the `ChironCore` directory and execute the following command: ```bash ./chiron.py -bmc -ub -aconf @@ -75,10 +75,10 @@ where `-ub` and `-aconf` are optional arguments All the loops of the code are unrolled based on the unroll bound and the unrolled code is used for further processing. 2. **Converting Chiron Intermediate Representation (IR) into Three Address Code (TAC)**: - The Chiron IR of the unrolled code is generated and is transformed into TAC to simplify the representation of operations and facilitate further analysis. + The Chiron IR of the unrolled code is generated and is transformed into TAC to simplify the representation of operations and facilitate further analysis. We show the TAC in `tac_cfg.png`. 3. **Generating Static Single Assignment (SSA)**: - The TAC is converted into SSA form to simplify data flow analysis and accurately track variable dependencies and states throughout the program. + The TAC is converted into SSA form to simplify data flow analysis and accurately track variable dependencies and states throughout the program. We show the SSA in `ssa_cfg.png`. 4. **SAT Solver Integration**: The SSA form is translated into SMT-LIB statements. This process encodes the constraints, conditions, and properties into a series of logical assertions and declarations to accurately represent the program's semantics. These statements are then checked for satisfiability using the Z3 solver. diff --git a/ChironCore/angles.conf b/ChironCore/angles.conf index 37e9307..1fb9a50 100644 --- a/ChironCore/angles.conf +++ b/ChironCore/angles.conf @@ -1,3 +1,8 @@ 0,1,0 45,0.707,0.707 90,0,1 +135,-0.707,0.707 +180,-1,0 +225,-0.707,-0.707 +270,0,-1 +315,0.707,-0.707 \ No newline at end of file diff --git a/ChironCore/bmc.py b/ChironCore/bmc.py index 3c15b65..791dc79 100644 --- a/ChironCore/bmc.py +++ b/ChironCore/bmc.py @@ -306,7 +306,7 @@ def solve(self, inputVars): sat = self.solver.check() if sat == z3.sat: - print("Condition not satisfied! Bug found for the following input:") + print("Condition not satisfied!") model = self.solver.model() solution = {} @@ -314,7 +314,9 @@ def solve(self, inputVars): varname, index = str(var).split("$") if varname in inputVars and index == "0": solution[varname] = model[var] - for var in solution: + if len(solution) > 0: + print("Bug found for the following input:") + for var in solution: print(var + " = " + str(solution[var])) elif sat == z3.unsat: diff --git a/ChironCore/bmc_examples/bmc1.tl b/ChironCore/bmc_examples/bmc1.tl index 73cee31..105f204 100644 --- a/ChironCore/bmc_examples/bmc1.tl +++ b/ChironCore/bmc_examples/bmc1.tl @@ -1,7 +1,13 @@ -// inputs: :x, :y, :z +:y = :x * :x +assert :y >= 0 -:t = :x + 2*:y + 3*:z + :x * :w * :u -:z = :x + :w +/* +Explaination: -assert (:x + 100 < :y) && (:x + 200 > :y) && !(:x >= 0) && (:x * :y < -:x) && (:t > 0) +Run this program by: +./chiron.py bmc_examples/bmc1.tl -bmc + +In this program :x is the free input variable. Since :y is square of :x, :y is positive hence the BMC engine outputs that consition is always satified. +If we change the assert statement to :y >= 1, then the BMC gives us a counter example of :x such that :y < 1. Eg: :x = 0 is a counter example. +*/ \ No newline at end of file diff --git a/ChironCore/bmc_examples/bmc2.tl b/ChironCore/bmc_examples/bmc2.tl index 515cea2..0594d96 100644 --- a/ChironCore/bmc_examples/bmc2.tl +++ b/ChironCore/bmc_examples/bmc2.tl @@ -2,15 +2,17 @@ // assume :x > 0 repeat 2 [ :t = :t * :x - assert :t > 0 + assert :t >= 0 ] -:s = 5 * :x -:z = :t + :s + 2 -// assert :z >= -5 -// cant do the following -// if (b > 0) [ // :a is not defined earlier -// :a = 1 -// ] -// forward :a +/* +Explaination: + +Run this program by: +./chiron.py bmc_examples/bmc2.tl -bmc + +In this program, :x is a free input variable. After the 1st iteration, :t = :x and after the 2nd iteration, :t = :x * :x. +In the case when assume statement is commented, :t >= 0 is violated for any :x < 0. Thus the BMC outputs a negative :x as a counter example. +In the case when assume statement is uncommented, the domain of :x is restricted among the positive real numbers. Hence, the assert consition always holds true. +*/ \ No newline at end of file diff --git a/ChironCore/bmc_examples/bmc3.tl b/ChironCore/bmc_examples/bmc3.tl index ed0607a..7566789 100644 --- a/ChironCore/bmc_examples/bmc3.tl +++ b/ChironCore/bmc_examples/bmc3.tl @@ -1,26 +1,32 @@ -:p = 1 - -repeat 5 [ - :t = :t * :x -] - -:q = 1 -repeat 4 [ - :q = :q * :x -] - :r = 1 repeat 7 [ :r = :r * :x ] +// :r = :x ** 7 :s = 1 - -repeat :o [ +@unroll 4 repeat :m [ :s = :s * :x - :o = :o - 1 ] +/* +Here, :m <= 4 (since unroll bound is 4 for this loop) +:s = 1 if :m = 0 +:s = :x ** :m if :m > 0 +*/ + +:z = 5*:r - 7*:s // :z = 5*(:x ** 7) - 7*(:x ** :m) +assert :z < -100 + + +/* +Explaination: -:z = 2*:p - 3*:q + 5*:r - 7*:s -assert :z < -10000 +Run this program by: +./chiron.py bmc_examples/bmc3.tl -bmc -ub 5 +This would give an error because the 2nd loops iterates 7 times, which is more the specified unroll bound 5. So, we loosen the bound. +Run this program by: +./chiron.py bmc_examples/bmc3.tl -bmc -ub 7 +In this case, there exists a counter example (for free input variable :x and :m) to the condition that gets printed. +Eg: take :x = 0 and :m = 0. Thus, :z = -7 >= -100 +*/ \ No newline at end of file diff --git a/ChironCore/bmc_examples/bmc4.tl b/ChironCore/bmc_examples/bmc4.tl index 8e52372..5f1d0e1 100644 --- a/ChironCore/bmc_examples/bmc4.tl +++ b/ChironCore/bmc_examples/bmc4.tl @@ -1,14 +1,32 @@ -:a = -1 +:a = 2 :y = 0 +:x = 0 + if (:a > 0) [ - :x = :y + 2 + :x = :y + 45 ] if (:a > 1) [ - :x = :y + 3 + :x = :y + 135 ] + +// :x = 135, :y = 0 + +assert :turtleX == 0 && :turtleY == 0 + goto (:x, :y) -assert :turtleX == 2 && :turtleY == 0 right :x -assert :x > 0 -assert :turtleX > 0 +assert :turtleX == 135 && :turtleY == 0 + + +/* +Explaination: + +Run this program by: +./chiron.py bmc_examples/bmc4.tl -bmc +This gives error because right :x rotates turtle by 135 deg, which is not in default angle. + +Run this program by: +./chiron.py bmc_examples/bmc4.tl -bmc -aconf angles.conf +In this case, 135 deg is in angle.conf and thus all conditions are satisfied. +*/ \ No newline at end of file diff --git a/ChironCore/bmc_examples/bmc5.tl b/ChironCore/bmc_examples/bmc5.tl index 380a234..ac0dd64 100644 --- a/ChironCore/bmc_examples/bmc5.tl +++ b/ChironCore/bmc_examples/bmc5.tl @@ -1,6 +1,19 @@ forward 10 left 90 -right 90 -assume :x > 0 -forward :x -assert :turtleX*:turtleX + :turtleY*:turtleY <= 100 +forward :t // turtle is at (10, :t) +:r = 20 +assert :turtleX*:turtleX + :turtleY*:turtleY <= :r*:r +// assume -17 <= :t && :t <= 17 + + +/* +Explaination: + +Run this program by: +./chiron.py bmc_examples/bmc5.tl -bmc +Here, we are checking whether turtle lies in the circle of radius :r = 20. The program outputs a counter example of this case (for free variable :t). Eg: :t = -18 + +Now uncomment the assert statement and run this program by: +./chiron.py bmc_examples/bmc5.tl -bmc +Now, we restrict :t between [-17, 17], then the turtle does not go outside the circle and condition is satisfied. +*/ \ No newline at end of file diff --git a/ChironCore/bmc_examples/bmc6.tl b/ChironCore/bmc_examples/bmc6.tl index b58b255..b1f9404 100644 --- a/ChironCore/bmc_examples/bmc6.tl +++ b/ChironCore/bmc_examples/bmc6.tl @@ -1,7 +1,37 @@ -assume :a < 0 -if (:b > 0) [ - :a = 1 - assert :a == 1 +assume :t > 0 +assert !(:turtleX*:turtleX + :turtleY*:turtleY > 20*20 && :turtlePen == 0) + +repeat 7 [ + pendown + assert !(:turtleX*:turtleX + :turtleY*:turtleY > 20*20 && :turtlePen == 0) + + forward :t + assert !(:turtleX*:turtleX + :turtleY*:turtleY > 20*20 && :turtlePen == 0) + + left 45 + assert !(:turtleX*:turtleX + :turtleY*:turtleY > 20*20 && :turtlePen == 0) + + penup + assert !(:turtleX*:turtleX + :turtleY*:turtleY > 20*20 && :turtlePen == 0) + + forward :t + assert !(:turtleX*:turtleX + :turtleY*:turtleY > 20*20 && :turtlePen == 0) + + left 45 + assert !(:turtleX*:turtleX + :turtleY*:turtleY > 20*20 && :turtlePen == 0) ] -forward :a -assert :turtleX > 0 + + +/* +Explaination: + +Run this program by: +./chiron.py bmc_examples/bmc6.tl -bmc -aconf angles.conf + +Consider the circle of radius 20 and center at (0,0) +Note that assert condition is not(turtle outside circle and pendown). We place the condition after every instruction. +So, we are asserting that turtle should not draw anything outside circle at any instance. + +But for large :t, turtle draws outside circle and a counter example of free input variable :t is given by BMC. +Eg: :t = 21 +*/ \ No newline at end of file diff --git a/ChironCore/bmc_examples/bmc7.tl b/ChironCore/bmc_examples/bmc7.tl deleted file mode 100644 index 4bcc2cb..0000000 --- a/ChironCore/bmc_examples/bmc7.tl +++ /dev/null @@ -1,26 +0,0 @@ -// left 90 // valid -// assert 1 > 0 // true - -// left 45 // invalid -// assert 1 > 0 // true - -// left 90 // valid -// assert 1 < 0 // flase - -// left 45 // invalid -// assert 1 < 0 // flase - -// repeat 3 [ -// left 90 -// ] - -forward 10 -// assume :turtleX <= 5 -assert :turtleX == 10 - -@unroll 50 repeat :turtleX [ - :x = :x + 1 -] - -assert :x <= 100 - diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 1297bd4..cec923c 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,3 +1,95 @@ -:t=:x+2*:y+3*:z+:x*:w*:u -:z=:x+:w -assert(:x+100<:y)&&(:x+200>:y)&&!(:x>=0)&&(:x*:y<-:x)&&(:t>0) +assume:t>0 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +assume 7 <= 10 +pendown +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +penup +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) + +pendown +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +penup +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) + +pendown +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +penup +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) + +pendown +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +penup +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) + +pendown +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +penup +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) + +pendown +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +penup +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) + +pendown +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +penup +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +forward:t +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) +left45 +assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) + + From d8fe94d9101e09fea2a5172677106a2af992440f Mon Sep 17 00:00:00 2001 From: debrajk22 Date: Thu, 17 Apr 2025 07:04:26 +0530 Subject: [PATCH 52/53] added nested loops --- BMC.md | 7 ++- ChironCore/bmc_examples/bmc3.tl | 28 +++++----- ChironCore/unrolled_code.tl | 97 +-------------------------------- 3 files changed, 21 insertions(+), 111 deletions(-) diff --git a/BMC.md b/BMC.md index 202b1c4..200f1c1 100644 --- a/BMC.md +++ b/BMC.md @@ -70,14 +70,17 @@ Examples demonstrating working of the BMC engine with explaination are provided where `-ub` and `-aconf` are optional arguments ## Implementation Methodology +We have added support for `assume` statement, `assert` statement, `modulo` operator, `float` numbers, `single line comments` and `multi-line comments` to Chiron. We have also added code to convert Chiron Intermediate Representation (IR) into Three Address Code (TAC) and Static Single Assignment (SSA). + +The working of BMC engine is explained as follows: 1. **Loop Unrolling**: All the loops of the code are unrolled based on the unroll bound and the unrolled code is used for further processing. -2. **Converting Chiron Intermediate Representation (IR) into Three Address Code (TAC)**: +2. **Converting Chiron IR into TAC**: The Chiron IR of the unrolled code is generated and is transformed into TAC to simplify the representation of operations and facilitate further analysis. We show the TAC in `tac_cfg.png`. -3. **Generating Static Single Assignment (SSA)**: +3. **Generating SSA**: The TAC is converted into SSA form to simplify data flow analysis and accurately track variable dependencies and states throughout the program. We show the SSA in `ssa_cfg.png`. 4. **SAT Solver Integration**: diff --git a/ChironCore/bmc_examples/bmc3.tl b/ChironCore/bmc_examples/bmc3.tl index 7566789..dbfce08 100644 --- a/ChironCore/bmc_examples/bmc3.tl +++ b/ChironCore/bmc_examples/bmc3.tl @@ -1,32 +1,32 @@ :r = 1 -repeat 7 [ +repeat 4 [ :r = :r * :x ] -// :r = :x ** 7 :s = 1 -@unroll 4 repeat :m [ - :s = :s * :x +@unroll 6 repeat :m [ + if (:m % 2 == 0) [ + :s = :s * :x + ] else [ + repeat 3 [ + :s = :s * 2 * :x + ] + ] ] -/* -Here, :m <= 4 (since unroll bound is 4 for this loop) -:s = 1 if :m = 0 -:s = :x ** :m if :m > 0 -*/ -:z = 5*:r - 7*:s // :z = 5*(:x ** 7) - 7*(:x ** :m) -assert :z < -100 +:z = 5*:r - 7*:s +assert :z > -1000 /* Explaination: Run this program by: -./chiron.py bmc_examples/bmc3.tl -bmc -ub 5 -This would give an error because the 2nd loops iterates 7 times, which is more the specified unroll bound 5. So, we loosen the bound. +./chiron.py bmc_examples/bmc3.tl -bmc -ub 3 +This would give an error because the 1st loops iterates 4 times, which is more the specified unroll bound 3. So, we loosen the bound. Run this program by: ./chiron.py bmc_examples/bmc3.tl -bmc -ub 7 In this case, there exists a counter example (for free input variable :x and :m) to the condition that gets printed. -Eg: take :x = 0 and :m = 0. Thus, :z = -7 >= -100 +Eg: take :x = 3 and :m = 1. */ \ No newline at end of file diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index cec923c..189a740 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,95 +1,2 @@ -assume:t>0 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -assume 7 <= 10 -pendown -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -penup -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) - -pendown -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -penup -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) - -pendown -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -penup -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) - -pendown -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -penup -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) - -pendown -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -penup -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) - -pendown -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -penup -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) - -pendown -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -penup -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -forward:t -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) -left45 -assert!(:turtleX*:turtleX+:turtleY*:turtleY>20*20&&:turtlePen==0) - - +:y=:x*:x +assert:y>=0 From 3696ce3cecb8bb655ff57a14f88f58a99c73ad77 Mon Sep 17 00:00:00 2001 From: AmoghBhagwat Date: Tue, 22 Apr 2025 10:28:09 +0530 Subject: [PATCH 53/53] add path planning example --- ChironCore/ChironSSA/builder.py | 23 +++- ChironCore/bmc_examples/bmc5.tl | 2 +- ChironCore/bmc_examples/bmc7.tl | 24 ++++ ChironCore/bmc_examples/path_planning.tl | 73 +++++++++++ ChironCore/bmc_examples/shortest_path.tl | 83 +++++++++++++ ChironCore/unrolled_code.tl | 152 ++++++++++++++++++++++- 6 files changed, 350 insertions(+), 7 deletions(-) create mode 100644 ChironCore/bmc_examples/bmc7.tl create mode 100644 ChironCore/bmc_examples/path_planning.tl create mode 100644 ChironCore/bmc_examples/shortest_path.tl diff --git a/ChironCore/ChironSSA/builder.py b/ChironCore/ChironSSA/builder.py index bf06268..3b03789 100644 --- a/ChironCore/ChironSSA/builder.py +++ b/ChironCore/ChironSSA/builder.py @@ -1,3 +1,4 @@ + from numpy import format_float_scientific from ChironSSA import ChironSSA from cfg import cfgBuilder @@ -21,15 +22,23 @@ def build(self): self.cfg.compute_dominance() self.insert_phi_nodes() self.rename_variables() - self.remove_empty_phi() + self.remove_empty_and_duplicate_phi() return self.cfg - def remove_empty_phi(self): + def remove_empty_and_duplicate_phi(self): for block in self.cfg.nodes(): for instr, _ in block.instrlist: - if isinstance(instr, ChironSSA.PhiCommand) and len(instr.rvars) == 0: - block.instrlist.remove((instr, None)) + if isinstance(instr, ChironSSA.PhiCommand): + if len(instr.rvars) == 0: + block.instrlist.remove((instr, None)) + else: + rvars = [[int(rvar.name.split('$')[-1]), rvar.name] for rvar in instr.rvars] + rvars.sort(key=lambda x: x[0]) + instr.rvars = [ChironSSA.Var(rvars[0][1])] + for i in range(1, len(rvars)): + if rvars[i][1] != rvars[i-1][1]: + instr.rvars.append(ChironSSA.Var(rvars[i][1])) def rename_variables(self): for var in self.globals: @@ -102,6 +111,9 @@ def phi_dfs(curr, var): if instr.lvar.name == var: instr.rvars.append(ChironSSA.Var(instr.lvar.name + "$" + str(self.stack[instr.lvar.name][-1]))) flag = True + if isinstance(instr, ChironSSA.AssignmentCommand): + if instr.lvar.name == var: + flag = True if not flag: for next in self.cfg.successors(curr): @@ -111,6 +123,7 @@ def phi_dfs(curr, var): for next in self.cfg.successors(block): for var in temp: + visited.clear() phi_dfs(next, var) for next in self.cfg.dominator_tree[block]: @@ -234,3 +247,5 @@ def convert(self, ir): elif isinstance(instr, ChironTAC.NoOpCommand): ir[ir.index((instr, tgt))] = (ChironSSA.NoOpCommand(), tgt) + + diff --git a/ChironCore/bmc_examples/bmc5.tl b/ChironCore/bmc_examples/bmc5.tl index ac0dd64..c009a88 100644 --- a/ChironCore/bmc_examples/bmc5.tl +++ b/ChironCore/bmc_examples/bmc5.tl @@ -16,4 +16,4 @@ Here, we are checking whether turtle lies in the circle of radius :r = 20. The p Now uncomment the assert statement and run this program by: ./chiron.py bmc_examples/bmc5.tl -bmc Now, we restrict :t between [-17, 17], then the turtle does not go outside the circle and condition is satisfied. -*/ \ No newline at end of file +*/ diff --git a/ChironCore/bmc_examples/bmc7.tl b/ChironCore/bmc_examples/bmc7.tl new file mode 100644 index 0000000..2c874e7 --- /dev/null +++ b/ChironCore/bmc_examples/bmc7.tl @@ -0,0 +1,24 @@ +assume :step > 0 && :step < 50 +assume :iterations > 0 + +:count = 0 +:inc = 2 + +repeat :iterations [ + forward :step + + if :count % 2 == 0 [ + left 90 + ] else [ + right 90 + ] + + :count = :count + 1 + :step = :step + :inc + + if (:count + 1) % 8 == 0 [ + :inc = - :inc + ] +] + +assert :turtleX * :turtleX + :turtleY * :turtleY <= 100 diff --git a/ChironCore/bmc_examples/path_planning.tl b/ChironCore/bmc_examples/path_planning.tl new file mode 100644 index 0000000..c7a1958 --- /dev/null +++ b/ChironCore/bmc_examples/path_planning.tl @@ -0,0 +1,73 @@ + +// max steps = 5, max obstacles = 2 + +assume :s1 == 0 || :s1 == 1 || :s1 == 2 || :s1 == 3 || :s1 == 4 +assume :s2 == 0 || :s2 == 1 || :s2 == 2 || :s2 == 3 || :s2 == 4 +assume :s3 == 0 || :s3 == 1 || :s3 == 2 || :s3 == 3 || :s3 == 4 +assume :s4 == 0 || :s4 == 1 || :s4 == 2 || :s4 == 3 || :s4 == 4 +assume :s5 == 0 || :s5 == 1 || :s5 == 2 || :s5 == 3 || :s5 == 4 + +:step = 50 + +:targetX = 3 * :step +:targetY = 5 * :step + +:obs1x = 1 * :step +:obs1y = 1 * :step + +:obs2x = 0 * :step +:obs2y = 1 * :step + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +if (:s1 == 1) [forward :step] +if (:s1 == 2) [left 90 forward :step right 90] +if (:s1 == 3) [backward :step] +if (:s1 == 4) [left 90 backward :step right 90] + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +if (:s2 == 1) [forward :step] +if (:s2 == 2) [left 90 forward :step right 90] +if (:s2 == 3) [backward :step] +if (:s2 == 4) [left 90 backward :step right 90] + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +if (:s3 == 1) [forward :step] +if (:s3 == 2) [left 90 forward :step right 90] +if (:s3 == 3) [backward :step] +if (:s3 == 4) [left 90 backward :step right 90] + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +if (:s4 == 1) [forward :step] +if (:s4 == 2) [left 90 forward :step right 90] +if (:s4 == 3) [backward :step] +if (:s4 == 4) [left 90 backward :step right 90] + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +if (:s5 == 1) [forward :step] +if (:s5 == 2) [left 90 forward :step right 90] +if (:s5 == 3) [backward :step] +if (:s5 == 4) [left 90 backward :step right 90] + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +assert !(:turtleX == :targetX && :turtleY == :targetY) + + +/* +This code assumes that the turtle can move in a 2D grid in 4 directions, moving :steps amount of distance at a time. +We check whether there is a path from (0, 0) to (:targetX, :targetY) that is reachable in at most 5 steps, also avoiding the 2 obstacles. +In each step, turtle decides to not move or move in +x, +y, -x, -y directions (corresponding to values 0, 1, 2, 3, 4 respectively). +We assert that the turtle is unable to reach the target. If there exists a path then the assertion is false and BMC returns a path. +*/ + diff --git a/ChironCore/bmc_examples/shortest_path.tl b/ChironCore/bmc_examples/shortest_path.tl new file mode 100644 index 0000000..d9d2ef6 --- /dev/null +++ b/ChironCore/bmc_examples/shortest_path.tl @@ -0,0 +1,83 @@ + +// max steps = 5, max obstacles = 2 + +assume :s1 == 0 || :s1 == 1 || :s1 == 2 || :s1 == 3 || :s1 == 4 +assume :s2 == 0 || :s2 == 1 || :s2 == 2 || :s2 == 3 || :s2 == 4 +assume :s3 == 0 || :s3 == 1 || :s3 == 2 || :s3 == 3 || :s3 == 4 +assume :s4 == 0 || :s4 == 1 || :s4 == 2 || :s4 == 3 || :s4 == 4 +assume :s5 == 0 || :s5 == 1 || :s5 == 2 || :s5 == 3 || :s5 == 4 + +assume !(:s4 == 0) || (:s5 == 0) +assume !(:s3 == 0) || (:s5 == 0 && :s4 == 0) +assume !(:s2 == 0) || (:s5 == 0 && :s4 == 0 && :s3 == 0) +assume !(:s1 == 0) || (:s5 == 0 && :s4 == 0 && :s3 == 0 && :s2 == 0) + +:step = 50 + +:length = 0 + +:targetX = 3 * :step +:targetY = 0 * :step + +:obs1x = 1 * :step +:obs1y = 1 * :step + +:obs2x = 0 * :step +:obs2y = 1 * :step + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +if (:s1 == 1) [forward :step] +if (:s1 == 2) [left 90 forward :step right 90] +if (:s1 == 3) [backward :step] +if (:s1 == 4) [left 90 backward :step right 90] +if (:s1 != 0) [:length = :length + 1] + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +if (:s2 == 1) [forward :step] +if (:s2 == 2) [left 90 forward :step right 90] +if (:s2 == 3) [backward :step] +if (:s2 == 4) [left 90 backward :step right 90] +if (:s2 != 0) [:length = :length + 1] + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +if (:s3 == 1) [forward :step] +if (:s3 == 2) [left 90 forward :step right 90] +if (:s3 == 3) [backward :step] +if (:s3 == 4) [left 90 backward :step right 90] +if (:s3 != 0) [:length = :length + 1] + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +if (:s4 == 1) [forward :step] +if (:s4 == 2) [left 90 forward :step right 90] +if (:s4 == 3) [backward :step] +if (:s4 == 4) [left 90 backward :step right 90] +if (:s4 != 0) [:length = :length + 1] + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +if (:s5 == 1) [forward :step] +if (:s5 == 2) [left 90 forward :step right 90] +if (:s5 == 3) [backward :step] +if (:s5 == 4) [left 90 backward :step right 90] +if (:s5 != 0) [:length = :length + 1] + +assume !(:turtleX == :obs1x && :turtleY == :obs1y) +assume !(:turtleX == :obs2x && :turtleY == :obs2y) + +assert !(:turtleX == :targetX && :turtleY == :targetY && :length <= 2) + + +/* +Similar to the path planning code, this code gives us a path that has least distance to travel. +Only the assert statement is changed. Rest of the code is same. +*/ + diff --git a/ChironCore/unrolled_code.tl b/ChironCore/unrolled_code.tl index 189a740..ae4bd6f 100644 --- a/ChironCore/unrolled_code.tl +++ b/ChironCore/unrolled_code.tl @@ -1,2 +1,150 @@ -:y=:x*:x -assert:y>=0 +assume:s1==0||:s1==1||:s1==2||:s1==3||:s1==4 +assume:s2==0||:s2==1||:s2==2||:s2==3||:s2==4 +assume:s3==0||:s3==1||:s3==2||:s3==3||:s3==4 +assume:s4==0||:s4==1||:s4==2||:s4==3||:s4==4 +assume:s5==0||:s5==1||:s5==2||:s5==3||:s5==4 +assume!(:s4==0)||(:s5==0) +assume!(:s3==0)||(:s5==0&&:s4==0) +assume!(:s2==0)||(:s5==0&&:s4==0&&:s3==0) +assume!(:s1==0)||(:s5==0&&:s4==0&&:s3==0&&:s2==0) +:step=50 +:length=0 +:targetX=3*:step +:targetY=0*:step +:obs1x=1*:step +:obs1y=1*:step +:obs2x=0*:step +:obs2y=1*:step +assume!(:turtleX==:obs1x&&:turtleY==:obs1y) +assume!(:turtleX==:obs2x&&:turtleY==:obs2y) +if ((:s1==1)) [ +forward:step + +] +if ((:s1==2)) [ +left90 +forward:step +right90 + +] +if ((:s1==3)) [ +backward:step + +] +if ((:s1==4)) [ +left90 +backward:step +right90 + +] +if ((:s1!=0)) [ +:length=:length+1 + +] +assume!(:turtleX==:obs1x&&:turtleY==:obs1y) +assume!(:turtleX==:obs2x&&:turtleY==:obs2y) +if ((:s2==1)) [ +forward:step + +] +if ((:s2==2)) [ +left90 +forward:step +right90 + +] +if ((:s2==3)) [ +backward:step + +] +if ((:s2==4)) [ +left90 +backward:step +right90 + +] +if ((:s2!=0)) [ +:length=:length+1 + +] +assume!(:turtleX==:obs1x&&:turtleY==:obs1y) +assume!(:turtleX==:obs2x&&:turtleY==:obs2y) +if ((:s3==1)) [ +forward:step + +] +if ((:s3==2)) [ +left90 +forward:step +right90 + +] +if ((:s3==3)) [ +backward:step + +] +if ((:s3==4)) [ +left90 +backward:step +right90 + +] +if ((:s3!=0)) [ +:length=:length+1 + +] +assume!(:turtleX==:obs1x&&:turtleY==:obs1y) +assume!(:turtleX==:obs2x&&:turtleY==:obs2y) +if ((:s4==1)) [ +forward:step + +] +if ((:s4==2)) [ +left90 +forward:step +right90 + +] +if ((:s4==3)) [ +backward:step + +] +if ((:s4==4)) [ +left90 +backward:step +right90 + +] +if ((:s4!=0)) [ +:length=:length+1 + +] +assume!(:turtleX==:obs1x&&:turtleY==:obs1y) +assume!(:turtleX==:obs2x&&:turtleY==:obs2y) +if ((:s5==1)) [ +forward:step + +] +if ((:s5==2)) [ +left90 +forward:step +right90 + +] +if ((:s5==3)) [ +backward:step + +] +if ((:s5==4)) [ +left90 +backward:step +right90 + +] +if ((:s5!=0)) [ +:length=:length+1 + +] +assume!(:turtleX==:obs1x&&:turtleY==:obs1y) +assume!(:turtleX==:obs2x&&:turtleY==:obs2y) +assert!(:turtleX==:targetX&&:turtleY==:targetY&&:length<=2)