def go(self, intro: str, outro: str, base: str, target: str, *, fn_name: Optional[str] = None, **kwargs: Any) -> int: base = intro + "\n" + base + "\n" + outro target = intro + "\n" + target + "\n" + outro compiler = Compiler("test/compile.sh", show_errors=True) # For debugging, to avoid the auto-deleted directory: # target_dir = tempfile.mkdtemp() with tempfile.TemporaryDirectory() as target_dir: with open(os.path.join(target_dir, "base.c"), "w") as f: f.write(base) target_o = compiler.compile(target, show_errors=True) assert target_o is not None shutil.move(target_o, os.path.join(target_dir, "target.o")) shutil.copy2("test/compile.sh", os.path.join(target_dir, "compile.sh")) if fn_name: with open(os.path.join(target_dir, "function.txt"), "w") as f: f.write(fn_name) opts = main.Options(directories=[target_dir], stop_on_zero=True, **kwargs) return main.run(opts)[0]
def setUpClass(cls): compiler = Compiler("test/compile.sh") cls.tmp_dirs = {} for test_c, test_fn in c_files_list: d = tempfile.TemporaryDirectory() file_test = os.path.join("test", test_c) file_actual = os.path.join(d.name, "actual.c") file_base = os.path.join(d.name, "base.c") file_target = os.path.join(d.name, "target.o") actual_preprocessed = preprocess(file_test, cpp_args=["-DACTUAL"]) base_preprocessed = preprocess(file_test, cpp_args=["-UACTUAL"]) strip_other_fns_and_write(actual_preprocessed, test_fn, file_actual) strip_other_fns_and_write(base_preprocessed, test_fn, file_base) actual_source = Path(file_actual).read_text() target_o = compiler.compile(actual_source, show_errors=True) assert target_o is not None shutil.copy2(target_o, file_target) os.remove(target_o) shutil.copy2("test/compile.sh", d.name) cls.tmp_dirs[(test_c, test_fn)] = d
def testing2Param(resMgr, p0, p1, opts): ''' Test the kernel opts['hfilebasename'] for the cartesian product of the values in the given intervals p0, p1. ''' sizesP0 = range(p0[0], p0[1] + 1) if len(p0) == 2 else range(p0[0], p0[1] + 1, p0[2]) sizesP1 = range(p1[0], p1[1] + 1) if len(p1) == 2 else range(p1[0], p1[1] + 1, p1[2]) sizes = [(i, j) for i in sizesP0 for j in sizesP1] for M, N in sizes: opts['static_params'] = [M, N] genCode = not 'libname' in opts onlygen = 'onlygen' in opts and opts['onlygen'] compiler = None if genCode: llprog = parseLL({'M': M, 'N': N}, opts) # expr = eval(opts['hfilebasename'])(N, opts) compiler = Compiler(llprog, opts) else: compiler = LibraryCode(opts) s = datetime.now() if not onlygen: printToLog( " " + "Starting compiler at " + str(s) + " ----------------------------------------", opts) compiler.compile() e = datetime.now() if not (genCode and onlygen): procOutcome(resMgr, compiler, opts, " ") printToLog( " " + "Compiling took " + str(e - s) + " ----------------------------------------------------------", opts) recordTime((e - s).total_seconds(), opts)
def testing3Param(resMgr, p0, p1, p2, opts): ''' Test the kernel for the cartesian product of the values in the given intervals p0, p1, p3. ''' sizesP0 = range(p0[0], p0[1] + 1) if len(p0) == 2 else range(p0[0], p0[1] + 1, p0[2]) sizesP1 = range(p1[0], p1[1] + 1) if len(p1) == 2 else range(p1[0], p1[1] + 1, p1[2]) sizesP2 = range(p2[0], p2[1] + 1) if len(p2) == 2 else range(p2[0], p2[1] + 1, p2[2]) sizes = [(i, j, k) for i in sizesP0 for j in sizesP1 for k in sizesP2] fine = True for M, K, N in sizes: try: opts['static_params'] = [M, K, N] genCode = not 'libname' in opts onlygen = 'onlygen' in opts and opts['onlygen'] compiler = None if genCode: llprog = parseLL({'M': M, 'K': K, 'N': N}, opts) # expr = eval(opts['hfilebasename'])(M, K, N, opts) compiler = Compiler(llprog, opts) else: compiler = LibraryCode(opts) s = datetime.now() if not onlygen: printToLog( " " + "Starting compiler at " + str(s) + " ----------------------------------------", opts) fine = fine and compiler.compile() e = datetime.now() if not (genCode and onlygen): procOutcome(resMgr, compiler, opts, " ") printToLog( " " + "Compiling took " + str(e - s) + " ----------------------------------------------------------", opts) recordTime((e - s).total_seconds(), opts) except Exception: if opts.get('breakonexc', False): raise fine = False openLog(opts) ts = '%s.%s' % (date.today().isoformat(), time.strftime('%H-%M-%S', time.localtime(time.time()))) msg = "=@" * 10 + " Begin Exc Report from testing3Param (" + ts + ") " + "=@" * 10 + "\n" msg += "-" * 10 + " opts " + "-" * 10 + "\n" msg += str(opts) + "\n" msg += "-" * 10 + " traceback " + "-" * 10 + "\n" printToLog(msg, opts, openf=False, closef=False) traceback.print_exc(file=opts['logfile']) msg = "\n" + "=@" * 10 + " End Exc Report (" + ts + ") " + "=@" * 10 + "\n" printToLog(msg, opts, openf=False) return fine
def testingRandom(resMgr, maxops, maxdim, maxeq, numgen, opts): fine = True llgen = RandomLLGen(maxops=maxops, maxdim=maxdim, maxeq=maxeq) for _ in range(numgen): genres = llgen.gen() srcfile = open(opts['source'], 'w') srcfile.write(genres[0]) srcfile.close() for pvalues in genres[2]: try: opts['static_params'] = pvalues genCode = not 'libname' in opts onlygen = 'onlygen' in opts and opts['onlygen'] compiler = None if genCode: llprog = parseLL(dict(zip(genres[1], pvalues)), opts) compiler = Compiler(llprog, opts) s = datetime.now() if not onlygen: printToLog( " " + "Starting compiler at " + str(s) + " ----------------------------------------", opts) fine = fine and compiler.compile() e = datetime.now() if not (genCode and onlygen): procOutcome(resMgr, compiler, opts, " ") printToLog( " " + "Compiling took " + str(e - s) + " ----------------------------------------------------------", opts) recordTime((e - s).total_seconds(), opts) else: print "Please enable code generation." except Exception: if opts.get('breakonexc', False): raise fine = False openLog(opts) ts = '%s.%s' % (date.today().isoformat(), time.strftime('%H-%M-%S', time.localtime(time.time()))) msg = "=@" * 10 + " Begin Exc Report from testingRandom (" + ts + ") " + "=@" * 10 + "\n" msg += "Generation of:\n\n%s\n\nParams:\n\n%s = %s\n\n" % ( genres[0], str(genres[1]), str(genres[2])) msg += "-" * 10 + " opts " + "-" * 10 + "\n" msg += str(opts) + "\n" msg += "-" * 10 + " traceback " + "-" * 10 + "\n" printToLog(msg, opts, openf=False, closef=False) traceback.print_exc(file=opts['logfile']) msg = "\n" + "=@" * 10 + " End Exc Report (" + ts + ") " + "=@" * 10 + "\n" printToLog(msg, opts, openf=False) return fine
def testing1Param(resMgr, p, opts): sizes = range(p[0], p[1] + 1) if len(p) == 2 else range(p[0], p[1] + 1, p[2]) fine = True for M in sizes: try: opts['static_params'] = [M] genCode = not 'libname' in opts onlygen = 'onlygen' in opts and opts['onlygen'] compiler = None if genCode: llprog = parseLL({'M': M}, opts) # expr = eval(opts['hfilebasename'])(N, opts) compiler = Compiler(llprog, opts) else: compiler = LibraryCode(opts) s = datetime.now() if not onlygen: printToLog( " " + "Starting compiler at " + str(s) + " ----------------------------------------", opts) fine = fine and compiler.compile() e = datetime.now() if not (genCode and onlygen): procOutcome(resMgr, compiler, opts, " ") printToLog( " " + "Compiling took " + str(e - s) + " ----------------------------------------------------------", opts) recordTime((e - s).total_seconds(), opts) except Exception: if opts.get('breakonexc', False): raise fine = False openLog(opts) ts = '%s.%s' % (date.today().isoformat(), time.strftime('%H-%M-%S', time.localtime(time.time()))) msg = "=@" * 10 + " Begin Exc Report from testing1Param (" + ts + ") " + "=@" * 10 + "\n" msg += "-" * 10 + " opts " + "-" * 10 + "\n" msg += str(opts) + "\n" msg += "-" * 10 + " traceback " + "-" * 10 + "\n" printToLog(msg, opts, openf=False, closef=False) traceback.print_exc(file=opts['logfile']) msg = "\n" + "=@" * 10 + " End Exc Report (" + ts + ") " + "=@" * 10 + "\n" printToLog(msg, opts, openf=False) return fine
def compile_base(compile_script: str, source: str, c_file: str, out_file: str) -> None: if "PERM_" in source: print( "Cannot test-compile imported code because it contains PERM macros. " "It is recommended to put in PERM macros after import.") return escaped_c_file = json.dumps(c_file) source = "#line 1 " + escaped_c_file + "\n" + source compiler = Compiler(compile_script, show_errors=True) o_file = compiler.compile(source) if o_file: shutil.move(o_file, out_file) else: print("Warning: failed to compile .c file.")
def ask_question(): req = request.get_json() data = Compiler(req).compile() res = make_response(jsonify(data), 200) return res
def main(): argv = sys.argv[1:] parser = argparse.ArgumentParser() parser.add_argument("-i", "--input", type=str) parser.add_argument("-o", "--output", type=str) args = parser.parse_args(argv) input_path = Path(args.input) output_path = Path(args.output) if not input_path.exists(): print(f"ERROR: Input path '{input_path}' does not exist.") return if not output_path.exists(): print(f"ERROR: Output path '{output_path}' does not exist.") return if input_path.parent == output_path: output_path = output_path.joinpath("out") output_path = output_path.joinpath(input_path.name) start_time = time.process_time() print(f"Compiling at {output_path}...") # TODO Save compilation time by not recompiling unedited files in a datapack # by comparing compiled file timestamp and uncompiled file timestamp. # User can force compile all files by adding the --force argument if output_path.exists(): shutil.rmtree(output_path, ignore_errors=True) shutil.copytree(input_path, output_path, ignore=shutil.ignore_patterns("*.mcfunctionx")) for file in input_path.joinpath("data").glob("**/*.mcfunctionx"): compiler = Compiler(file, input_path, output_path) compiler.compile() print( f"Done! Took {(time.process_time() - start_time)*1000}ms to complete.")
from src.compiler import Compiler compiler = Compiler() compiler.run()
def testing1toNParam(resMgr, p0, fs, opts): sizesP0 = range(p0[0], p0[1] + 1) if len(p0) == 2 else range(p0[0], p0[1] + 1, p0[2]) params = [f[0] for f in fs] sizes = [] for i in sizesP0: sizes.append([f[1](i) for f in fs]) fine = True for pvalues, i in zip(sizes, sizesP0): try: opts['static_params'] = pvalues genCode = not 'libname' in opts onlygen = 'onlygen' in opts and opts['onlygen'] compiler = None if genCode: opts['pvalues'] = { p: pvalue for p, pvalue in zip(params, pvalues) } llprog = parseLL( {p: pvalue for p, pvalue in zip(params, pvalues)}, opts) compiler = Compiler(llprog, opts) else: compiler = LibraryCode(opts) s = datetime.now() if not onlygen: printToLog( " " + "Starting compiler at " + str(s) + " ----------------------------------------", opts) fine = fine and compiler.compile() e = datetime.now() if not (genCode and onlygen): procOutcome(resMgr, compiler, opts, " ", sizeParams=[i]) printToLog( " " + "Compiling took " + str(e - s) + " ----------------------------------------------------------", opts) recordTime((e - s).total_seconds(), opts) except Exception: # openLog(opts) ts = '%s.%s' % (date.today().isoformat(), time.strftime('%H-%M-%S', time.localtime(time.time()))) msg = "=@" * 10 + " Begin Exc Report from testing1toNParam (" + ts + ") " + "=@" * 10 + "\n" msg += "-" * 10 + " opts " + "-" * 10 + "\n" msg += str(opts) + "\n" msg += "-" * 10 + " traceback " + "-" * 10 + "\n" # printToLog(msg, opts, openf=False, closef=False) # traceback.print_exc(file=opts['logfile']) msg += traceback.format_exc() msg += "\n" + "=@" * 10 + " End Exc Report (" + ts + ") " + "=@" * 10 + "\n" printToLog(msg, opts) if opts.get('breakonexc', False): # openLog(opts, 'r') # body = opts['logfile'].read() # closeLog(opts) send_email_with_log(opts, subj="SLinGen Report on Exception", body=msg) raise fine = False return fine
def testingNParam(resMgr, ps, opts): ''' Test the kernel for the cartesian product of the values in the given intervals p0, p1, p2, ... ''' params = [pi[0] for pi in ps] sizesPi = [ range(pi[1], pi[2] + 1) if len(pi) == 3 else range(pi[1], pi[2] + 1, pi[3]) for pi in ps ] sizes = list(itertools.product(*sizesPi)) fine = True for pvalues in sizes: try: opts['static_params'] = list(pvalues) genCode = not 'libname' in opts onlygen = 'onlygen' in opts and opts['onlygen'] compiler = None if genCode: opts['pvalues'] = { p: pvalue for p, pvalue in zip(params, pvalues) } llprog = parseLL( {p: pvalue for p, pvalue in zip(params, pvalues)}, opts) compiler = Compiler(llprog, opts) else: compiler = LibraryCode(opts) s = datetime.now() if not onlygen: printToLog( " " + "Starting compiler at " + str(s) + " ----------------------------------------", opts) fine = fine and compiler.compile() e = datetime.now() if not (genCode and onlygen): procOutcome(resMgr, compiler, opts, " ") printToLog( " " + "Compiling took " + str(e - s) + " ----------------------------------------------------------", opts) recordTime((e - s).total_seconds(), opts) except Exception: openLog(opts) ts = '%s.%s' % (date.today().isoformat(), time.strftime('%H-%M-%S', time.localtime(time.time()))) msg = "=@" * 10 + " Begin Exc Report from testingNParam (" + ts + ") " + "=@" * 10 + "\n" msg += "-" * 10 + " opts " + "-" * 10 + "\n" msg += str(opts) + "\n" msg += "-" * 10 + " traceback " + "-" * 10 + "\n" # printToLog(msg, opts, openf=False, closef=False) # traceback.print_exc(file=opts['logfile']) msg += traceback.format_exc() msg += "\n" + "=@" * 10 + " End Exc Report (" + ts + ") " + "=@" * 10 + "\n" # printToLog(msg, opts, openf=False) printToLog(msg, opts) if opts.get('breakonexc', False): send_email_with_log(opts, subj="SLinGen Report on Exception", body=msg) raise fine = False return fine
def test_init(self): c = Compiler(self.rootPath) c.compile()
def setUp(self): self.c = Compiler("str_list", 1)
class CompilerUnitTest(unittest.TestCase): def setUp(self): self.c = Compiler("str_list", 1) def test_compile_expression(self): self.assertEqual(self.c.compile_expression("if", "if x == y", 0), "\n if context['x'] == context['y']:") self.assertEqual(self.c.compile_expression("variable", "a.b", 0), "\n str_0 = context['a']['b']" "\n str_list.append(str_0)") self.assertEqual(self.c.compile_expression("static_string", "xyz", 0), "\n str_1 = 'xyz'\n str_list.append(str_1)") self.assertEqual(self.c.compile_expression("for", "for x in y", 0), "\n for x in context['y']:") self.c.add_variable_to_scope("z", 1) self.assertEqual(self.c.compile_expression("for", "for x in z", 2), "\n for x in z:") self.assertEqual(self.c.compile_expression("for", "for x in z", 1), "\n for x in context['z']:") def test_compile_if(self): self.assertEqual(self.c.compile_if("if x == y", 0), "\n if context['x'] == context['y']:") self.assertEqual(self.c.compile_if("if x.k == y", 0), "\n if context['x']['k'] == context['y']:") self.assertEqual(self.c.compile_if("if x == y", 1), "\n if context['x'] == context['y']:") self.assertEqual(self.c.compile_if("if x != y", 0), "\n if context['x'] != context['y']:") self.assertEqual(self.c.compile_if("if x > y", 0), "\n if context['x'] > context['y']:") self.assertEqual(self.c.compile_if("if x >= y", 0), "\n if context['x'] >= context['y']:") self.assertEqual(self.c.compile_if("if x < y", 0), "\n if context['x'] < context['y']:") self.assertEqual(self.c.compile_if("if x <= y", 0), "\n if context['x'] <= context['y']:") self.assertEqual(self.c.compile_if("if x is True", 0), "\n if context['x'] is True:") self.assertEqual(self.c.compile_if("if x is not True", 0), "\n if context['x'] is not True:") self.assertEqual(self.c.compile_if("if x", 0), "\n if context['x']:") self.assertEqual(self.c.compile_if("if x and y", 0), "\n if context['x'] and context['y']:") self.assertEqual(self.c.compile_if("if x or y", 0), "\n if context['x'] or context['y']:") self.assertEqual(self.c.compile_if("if x is y", 0), "\n if context['x'] is context['y']:") self.assertEqual(self.c.compile_if("if x is None", 0), "\n if context['x'] is None:") self.assertEqual(self.c.compile_if("if x is not None", 0), "\n if context['x'] is not None:") self.c.add_variable_to_scope("z", 0) self.assertEqual(self.c.compile_if("if x == z", 1), "\n if context['x'] == z:") self.assertEqual(self.c.compile_if("if 'abc' == y", 1), "\n if 'abc' == context['y']:") self.assertEqual(self.c.compile_if("if 123.4 == y", 1), "\n if 123.4 == context['y']:") self.assertEqual(self.c.compile_if("if x == True", 1), "\n if context['x'] == True:") self.assertEqual(self.c.compile_if("if x == False", 1), "\n if context['x'] == False:") self.assertEqual(self.c.compile_if("if x > 1 and x < 3", 1), "\n if context['x'] > 1 and context['x'] < 3:") self.assertEqual(self.c.compile_if("if x < 1 or x > 3", 1), "\n if context['x'] < 1 or context['x'] > 3:") self.assertEqual( self.c.compile_if("if x < 1 or x > 3 and y is True", 1), "\n if context['x'] < 1 or context['x'] > 3 " "and context['y'] is True:") def test_if_value_is_static_string(self): self.assertEqual(self.c.is_static_string("'abc'"), True) self.assertEqual(self.c.is_static_string("abc"), False) self.assertEqual(self.c.is_static_string("'abc"), False) self.assertEqual(self.c.is_static_string("abc'"), False) self.assertEqual(self.c.is_static_string('"abc"'), True) self.assertEqual(self.c.is_static_string('abc'), False) self.assertEqual(self.c.is_static_string('"abc'), False) self.assertEqual(self.c.is_static_string('abc"'), False) def test_if_value_is_numeric(self): self.assertEqual(self.c.is_numeric("123"), True) self.assertEqual(self.c.is_numeric("123.0"), True) self.assertEqual(self.c.is_numeric("123."), True) self.assertEqual(self.c.is_numeric("123.2.3"), False) self.assertEqual(self.c.is_numeric("abc"), False) self.assertEqual(self.c.is_numeric("True"), False) self.assertEqual(self.c.is_numeric("False"), False) def test_if_value_is_boolean(self): self.assertEqual(self.c.is_boolean("True"), True) self.assertEqual(self.c.is_boolean("False"), True) self.assertEqual(self.c.is_boolean("123"), False) self.assertEqual(self.c.is_boolean("x.y"), False) def test_is_comparison_operator(self): self.assertEqual(self.c.is_operator("=="), True) self.assertEqual(self.c.is_operator("!="), True) self.assertEqual(self.c.is_operator(">="), True) self.assertEqual(self.c.is_operator(">"), True) self.assertEqual(self.c.is_operator("<="), True) self.assertEqual(self.c.is_operator("<"), True) self.assertEqual(self.c.is_operator("or"), True) self.assertEqual(self.c.is_operator("and"), True) self.assertEqual(self.c.is_operator("is"), True) self.assertEqual(self.c.is_operator("not"), True) self.assertEqual(self.c.is_operator("abc"), False) def test_element_of_if_expression_is_variable(self): self.assertEqual(self.c.element_of_if_expression_is_variable("abc"), True) self.assertEqual(self.c.element_of_if_expression_is_variable("'abc'"), False) self.assertEqual(self.c.element_of_if_expression_is_variable('"abc"'), False) self.assertEqual(self.c.element_of_if_expression_is_variable("True"), False) self.assertEqual(self.c.element_of_if_expression_is_variable("False"), False) self.assertEqual(self.c.element_of_if_expression_is_variable("None"), False) self.assertEqual(self.c.element_of_if_expression_is_variable("123"), False) self.assertEqual(self.c.element_of_if_expression_is_variable("=="), False) self.assertEqual(self.c.element_of_if_expression_is_variable("!="), False) self.assertEqual(self.c.element_of_if_expression_is_variable(">="), False) self.assertEqual(self.c.element_of_if_expression_is_variable(">"), False) self.assertEqual(self.c.element_of_if_expression_is_variable("<="), False) self.assertEqual(self.c.element_of_if_expression_is_variable("<"), False) self.assertEqual(self.c.element_of_if_expression_is_variable("or"), False) self.assertEqual(self.c.element_of_if_expression_is_variable("and"), False) self.assertEqual(self.c.element_of_if_expression_is_variable("is"), False) self.assertEqual(self.c.element_of_if_expression_is_variable("not"), False) def test_compile_for(self): self.assertEqual(self.c.compile_for("for x in y", 0), "\n for x in context['y']:") self.assertEqual(self.c.compile_for("for x in y", 1), "\n for x in context['y']:") self.c.add_variable_to_scope("z", 0) self.assertEqual(self.c.compile_for("for x in z", 0), "\n for x in z:") def test_get_element_of_sequence(self): self.assertEqual(self.c.get_element_of_sequence("for x in y"), "x") self.assertEqual(self.c.get_element_of_sequence("for x in y"), "x") def test_get_sequence(self): self.assertEqual(self.c.get_sequence("for x in y"), "y") self.assertEqual(self.c.get_sequence("for x in y "), "y") self.assertEqual(self.c.get_sequence("for x in y.z"), "y.z") def test_compile_variable(self): self.assertEqual(self.c.compile_variable("a", 0), "\n str_0 = context['a']" "\n str_list.append(str_0)") self.assertEqual(self.c.compile_variable("a.b.c", 0), "\n str_1 = context['a']['b']['c']" "\n str_list.append(str_1)") self.c.add_variable_to_scope("z", 0) self.assertEqual(self.c.compile_variable("z", 1), "\n str_2 = z" "\n str_list.append(str_2)") self.assertEqual(self.c.compile_variable("z.a", 1), "\n str_3 = z['a']" "\n str_list.append(str_3)") self.assertEqual(self.c.compile_variable("z.a", 0, True), "z['a']") def test_compile_static_string(self): self.assertEqual(self.c.compile_static_string("abc", 0), "\n str_0 = 'abc'\n str_list.append(str_0)") self.assertEqual(self.c.compile_static_string('abc', 0), "\n str_1 = 'abc'\n str_list.append(str_1)") def test_compile_string(self): self.assertEqual(self.c.compile_static_string("abc def", 0), "\n str_0 = 'abc def'\n str_list.append(str_0)") self.assertEqual(self.c.compile_static_string('hij', 0), "\n str_1 = 'hij'\n str_list.append(str_1)") def test_get_append_string_to_list_statement(self): self.assertEqual( self.c.get_append_string_to_list_statement("str_0", 0), "\n str_list.append(str_0)") self.c.string_list_identifier = "lst" self.assertEqual( self.c.get_append_string_to_list_statement("str_0", 0), "\n lst.append(str_0)") def test_indent(self): self.assertEqual(self.c.indent("for x in y:", 0), "\n for x in y:") self.assertEqual(self.c.indent("if x == y:", 1), "\n if x == y:") self.c.indentation = self.c.TAB self.assertEqual(self.c.indent("str_1 = 'abc'", 1), "\n\t\tstr_1 = 'abc'") self.c.initial_indent_level = 3 self.assertEqual(self.c.indent("str_1 = 'abc'", 2), "\n\t\t\t\t\tstr_1 = 'abc'") def test_get_scope_variable(self): self.assertEqual(self.c.get_scope_variable("context"), "context") self.c.scope_variables = [("context", -1), ("x", 1)] self.assertEqual(self.c.get_scope_variable("x"), "x") self.assertEqual(self.c.get_scope_variable("y"), "context") self.c.scope_variables = [("context", -1), ("x", 1), ("y", 2)] self.assertEqual(self.c.get_scope_variable("x"), "x") def test_add_variable_to_scope(self): self.c.add_variable_to_scope("x", 0) self.assertEqual(self.c.scope_variables, [("context", -1), ("x", 1)]) self.c.add_variable_to_scope("z", 1) self.assertEqual(self.c.scope_variables, [("context", -1), ("x", 1), ("z", 2)]) def test_remove_out_of_scope_variables(self): self.c.scope_variables = [("context", -1), ("abc", 1), ("def", 2)] self.c.remove_out_of_scope_variables(2) self.assertSequenceEqual(self.c.scope_variables, [("context", -1), ("abc", 1)]) self.c.scope_variables = [("context", -1), ("abc", 1), ("def", 2)] self.c.remove_out_of_scope_variables(1) self.assertSequenceEqual(self.c.scope_variables, [("context", -1)])