def extract_functions(prgm): """ Removes all function bodies from prgm and inserts the functions into a new environment frame. """ lines = prgm.split('\n') lines = [line.strip() for line in lines] env = Environment() i = 0 max_len = len(lines) while i < max_len: line = lines[i] # Transform classes into functions that return objects if line.startswith('class '): match_obj = re.match(r'class ([\$A-Za-z_][A-Za-z0-9_]*)\((.*)\)(.*)', line) child_class_name = match_obj.group(1) arguments = match_obj.group(2) parent_classes = match_obj.group(3) inherit_obj = re.match(r' inherits (.*)', parent_classes) if inherit_obj: parent_class_names = inherit_obj.group(1) classes = [name.strip() for name in parent_class_names.split(',')] env.new_type(classes, child_class_name) else: # There were no parent classes provided. # By default, this class should inherit from Object. env.new_type(['Object'], child_class_name) lines[i] = 'sub ' + child_class_name + '(' + arguments + ')' lines.insert(i + 1, '$type="' + child_class_name + '"') max_len += 1 _, end = find_next_end_else(lines, i + 1, True) lines.insert(end, 'return this') max_len += 1 i += 1 i = 0 while i < len(lines): line = lines[i] if line.startswith('sub '): name = name_of_function(line) arg_list = args_of_function(line) ret_type = return_type_of_function(line) _, end = find_next_end_else(lines, i + 1, True) func_body = lines[i+1 : end] env.assign_hook(name, Function(name, arg_list, func_body, return_type=ret_type)) # Remove the function definition from the program, # and replace it with a hook directive. lines[i : end+1] = [':hook {0}'.format(name)] else: i += 1 prgm = '\n'.join(lines) return prgm, env
def main(): """Main function - includes tests and runs the REPL.""" if len(sys.argv) > 1: first_arg = sys.argv[1] if first_arg == '--test': env = Environment() execute_statement('x = 3', env) execute_statement('x+=7', env) execute_statement('y=9.23', env) env.new_frame() execute_statement('x = 5', env) print(env.frames) execute_statement('z="hello world"', env) execute_statement('z +="!!!"', env) execute_statement('a= `gelatin`', env) print(env.frames) ast = AST("3*4+5 ^ 7") print(ast.parse()) print(ast.collapse_indices(ast.build_indices())) ast = AST("18+15*9:3+10") print(ast.parse()) print(ast.collapse_indices(ast.build_indices())) print(evaluate_expression('1+2+3+4', Environment())) print(evaluate_expression('45+7*8', Environment())) print(evaluate_expression('3.2+18^2-7', Environment())) print(evaluate_expression('1:2 + 1:3 + 1:5', Environment())) print(evaluate_expression('2:3 + 3^3 - 1:5', Environment())) print(evaluate_expression('1234', Environment())) ast = AST("3 + 1 == 4") print(ast.parse()) ast = AST("3 + 1 > 4") print(ast.parse()) ast = AST("18:1 != 18.2") print(ast.parse()) ast = AST("x = 4") print(ast.parse()) ast = AST("y = 3 > 4") print(ast.parse()) env2 = Environment() execute_statement('x = 3+5*4', env2) execute_statement('y = x + 19 - 3*6', env2) print(env2.frames) elif first_arg == '--test2': ast = AST('x = "ice cream, eggs, and milk" + "...alpha or beta"') print(ast.parse()) ast = AST('y = f(1 + 1, 2 + 2, 3 + 3) - g((9+7)*2, 128/(2+2))') print(ast.parse()) ast = AST('z = f("ice cream", "eggs and milk") * g("alpha or beta", 3:8, "gamma or delta")') print(ast.parse()) ast = AST('makeList(1,2,3) + makeList(4,5,6)') print(ast.parse()) ast = AST('[max(16, 25), max(36, max(49, 64))]') print(ast.parse()) ast = AST('[concat_lists([10], [20]), concat_lists([30], [40])]') print(ast.parse()) elif first_arg == '--test3': ast = AST('[1, 2, 3]') print(ast.split_list_elems()) ast = AST('[f(2), f(3), f(4)]') print(ast.split_list_elems()) ast = AST('[f(2, 3), f(3, 4, 5), f(4, 1)]') print(ast.split_list_elems()) ast = AST('1 + 2 * 3') print(ast.split_list_elems()) print(ast.parse()) elif first_arg == '--test4': ast = AST('x.length()') print(ast.parse()) ast = AST('[1,2,3].length()') print(ast.parse()) ast = AST('3.01') print(ast.parse()) ast = AST('3.1') print(ast.parse()) elif first_arg == '--test5': env = Environment() env.new_type(['Number'], 'ComplexNumber') c = {'$type': 'ComplexNumber', 'real': 1, 'imag': 2} print(env.value_is_a(c, 'ComplexNumber')) print(env.value_is_a(c, 'Number')) print(env.value_is_a(c, 'Int')) print("") env.new_type(['Object'], 'Food') env.new_type(['Food'], 'Pizza') env.new_type(['Food'], 'Dessert') env.new_type(['Dessert'], 'ChocolateItem') env.new_type(['Pizza'], 'PepperoniPizza') env.new_type(['Pizza', 'ChocolateItem'], 'ChocolatePizza') pepperoni_pizza = {'$type': 'PepperoniPizza'} chocolate_pizza = {'$type': 'ChocolatePizza'} print(env.value_is_a(pepperoni_pizza, 'PepperoniPizza')) print(env.value_is_a(pepperoni_pizza, 'Pizza')) print(env.value_is_a(pepperoni_pizza, 'Food')) print(env.value_is_a(pepperoni_pizza, 'Dessert')) print(env.value_is_a(pepperoni_pizza, 'ChocolateItem')) print("") print(env.value_is_a(chocolate_pizza, 'PepperoniPizza')) print(env.value_is_a(chocolate_pizza, 'Pizza')) print(env.value_is_a(chocolate_pizza, 'Food')) print(env.value_is_a(chocolate_pizza, 'Dessert')) print(env.value_is_a(chocolate_pizza, 'ChocolateItem')) print("") env.new_type(['ChocolatePizza'], 'HugeChocolatePizza') huge_chocolate_pizza = {'$type': 'HugeChocolatePizza'} print(env.value_is_a(huge_chocolate_pizza, 'PepperoniPizza')) print(env.value_is_a(huge_chocolate_pizza, 'Pizza')) print(env.value_is_a(huge_chocolate_pizza, 'Food')) print(env.value_is_a(huge_chocolate_pizza, 'Dessert')) print(env.value_is_a(huge_chocolate_pizza, 'ChocolateItem')) print(env.value_is_a(huge_chocolate_pizza, 'ChocolatePizza')) print("") elif first_arg == '--test6': ast = AST('{1, 2 | 3, 4}') print(ast.parse()) elif first_arg == '--test7': ast = AST('throw "something"') print(ast.parse()) elif first_arg == '--test8': ast = AST('true and not false') print(ast.parse()) print(ast.collapse_indices(ast.build_indices())) elif first_arg == '--test9': sample = """ x = 5 // comment // comment /* multi line comment */y = 6 z = "https://example.com" """ print(preprocess(sample)) elif first_arg == '--test-all': tests.test_all('capacita_programs') elif first_arg == '--test-all-fast': tests.test_all('capacita_programs', False) else: # Run a program from a text file: file_name = first_arg try: execute_program(file_to_str(file_name)) except IOError: print("Could not read file: " + file_name) exit() repl()