def assert_exp_length(ast, length): if len(ast) > length: msg = "Malformed %s, too many arguments: %s" % (ast[0], unparse(ast)) raise LispError(msg) elif len(ast) < length: msg = "Malformed %s, too few arguments: %s" % (ast[0], unparse(ast)) raise LispError(msg)
def source(ast, env): assert_exp_length(ast, 1) symbol = ast[0] assert_symbol(symbol) if symbol in forms: return "<form/%s>" % symbol else: val = env.lookup(symbol) if is_closure(val): return "(lambda %s %s)" % (unparse(val.params), unparse(val.body)) else: return val
def evaluate(ast, env): """Evaluate an Abstract Syntax Tree in the specified environment.""" if is_boolean(ast) or is_integer(ast): return ast elif is_symbol(ast): return env.lookup(ast) if not is_atom(ast[0]): ast[0] = evaluate(ast[0], env) elif is_symbol(ast[0]): if ast[0] in keywords: return keywords[ast[0]](ast, env) elif ast[0] in math_operators: return eval_math(ast, env) else: ast[0] = env.lookup(ast[0]) if is_closure(ast[0]): args = [evaluate(x, env) for x in ast[1:]] num_args = len(args) num_params = len(ast[0].params) if num_args != num_params: raise LispError('wrong number of arguments, expected %d got %d' % (num_params, num_args)) bindings = dict(zip(ast[0].params, args)) return evaluate(ast[0].body, ast[0].env.extend(bindings)) raise LispError('not a function: %s' % unparse(ast[0]))
def assert_list(rest, env): rest = evaluate(rest, env) if is_list(rest): return rest else: raise LispError("Expected list, got: %s" % unparse(rest))
def evaluate(ast, env): """Evaluate an Abstract Syntax Tree in the specified environment.""" if is_symbol(ast): return env[ast] elif is_atom(ast): return ast elif is_list(ast): if ast[0] == 'atom': return eval_atom(ast, env) elif ast[0] == 'eq': return eval_eq(ast, env) elif ast[0] == 'macro': return eval_macro(ast, env) elif ast[0] == 'expand': return eval_expand(ast, env) elif ast[0] == 'expand-1': return eval_expand_1(ast, env) elif ast[0] == 'cond': return eval_cond(ast, env) elif ast[0] == 'let': return eval_let(ast, env) elif ast[0] == 'eval': return eval_eval(ast, env) elif ast[0] == 'set!': return eval_set(ast, env) elif ast[0] == 'quote': return eval_quote(ast, env) elif ast[0] == 'quasiquote': return eval_quasiquote(ast, env) elif ast[0] in ('lambda', 'λ'): return eval_lambda(ast, env) elif ast[0] == 'begin': return eval_begin(ast, env) elif ast[0] == 'define': return eval_define(ast, env) else: fn = evaluate(ast[0], env) if is_macro(fn): return apply_macro(ast, env) elif is_lambda(fn): return apply_lambda(ast, env) elif is_builtin(fn): return apply_builtin(ast, env) else: raise LispTypeError("Call to: " + unparse(ast[0])) else: raise LispSyntaxError(ast)
def fn(ast, env): if len(ast) != 2: raise LispError("Wrong number of arguments for function definition: %s" % len(ast)) params = ast[0] if not isinstance(params, list): raise LispError("Parameters must be a list, got: %s" % unparse(params)) else: for p in params: if not isinstance(p, str): raise LispError("Parameter must be a symbol, got: %s" % unparse(p)) body = ast[1] return Closure(env, params, body)
def solve_and_display(path="sudoku.txt", graph_display=False, iterate=False, fastest=False): if fastest: graph_display, iterate = False timestamp_unparsed = time.time() # Opening file to_solve = open(path, "r") S_init = "" for line in to_solve: S_init += line to_solve.close() #Parsing time_message = "\nSudoku solving speed:\n" S_init = parse(S_init) timestamp_parsed = time.time() time_parsing = int((timestamp_parsed - timestamp_unparsed) * 10000) / 10000 time_message += "Parsing... {} seconds\n".format(time_parsing) S = np.copy(S_init) #Solving timestamp_unsolved = time.time() S, meta, init = solve(S, display_iterations=iterate, stats=not (fastest)) timestamp_solved = time.time() time_solving = int((timestamp_solved - timestamp_unsolved) * 1000) / 1000 pretty_print(S_init, liste_init=init) pretty_print(S, liste_init=init) # Writing # Just checking if there is a .txt extension or not (can disturb Windows dumb users) if len(path) > 4: if path[-4:] == ".txt": path = path[:-4] solved = open(path + "_solved.txt", "w") s = unparse(S) solved.write(s) solved.close() # Displaying time_message += "Solving... {} seconds\n".format(time_solving) print(time_message) print("Find the answer above or in the " + path + " file!") # Pretty things if graph_display: print("Watch the figure of the solving evolution.") print(meta) plt.plot([_ for _ in map(lambda x: max(meta) - x, meta)]) plt.show()
def interpret(source, env=None): """ Interpret a lisp program statement Accepts a program statement as a string, interprets it, and then returns the resulting lisp expression as string. """ if env is None: env = Environment() return unparse(evaluate(parse(source), env))
def apply_lambda(ast, env): fn = evaluate(ast[0], env) args = ast[1:] if len(args) != len(fn.params): msg = "Wrong number of arguments, expected %d got %d: %s" \ % (len(fn.params), len(args), unparse(ast)) raise LispTypeError(msg) args = [evaluate(exp, env) for exp in ast[1:]] return evaluate(fn.body, Environment(zip(fn.params, args), env))
def evaluate(ast, env): """Evaluate an Abstract Syntax Tree in the specified environment.""" if is_symbol(ast): if ast[0] == '"': return ast return env.lookup(ast) elif is_atom(ast): return ast elif is_list(ast): return eval_list(ast, env) else: raise LispError('Syntax error: %s' % unparse(ast))
def eval_list(ast, env): """evaluate all the built-in functions""" if ast[0] == 'quote': return eval_quote(ast, env) elif ast[0] == 'exit': return eval_exit(ast) elif ast[0] == 'print': return eval_print(ast, env) elif ast[0] == 'atom': return eval_atom(ast, env) elif ast[0] == 'let': return eval_let(ast, env) elif ast[0] == 'def': return eval_def(ast, env) elif ast[0] == 'lambda': return eval_lambda(ast, env) elif ast[0] == 'eq': return eval_eq(ast, env) elif ast[0] == 'set': return eval_set(ast, env) elif ast[0] == 'if': return eval_if(ast, env) elif ast[0] == 'cons': return eval_cons(ast, env) elif ast[0] == 'head': return eval_head(ast, env) elif ast[0] == 'tail': return eval_tail(ast, env) elif ast[0] == 'rhead': return eval_rhead(ast, env) elif ast[0] == 'rtail': return eval_rtail(ast, env) elif ast[0] == 'empty': return eval_empty(ast, env) elif ast[0] in [ '+', '-', '*', '**', '/', 'mod', '<', '<=', '=', '!=', '>=', '>' ]: return eval_math(ast, env) elif ast[0] == 'random': return eval_random() elif ast[0] in ['int', 'float', 'str', 'type']: return eval_types(ast, env) elif ast[0] in ['str_append', 'str_split']: return eval_string(ast, env) elif is_closure(ast[0]): return apply(ast, env) elif is_symbol(ast[0]) or is_list(ast[0]): return evaluate([evaluate(ast[0], env)] + ast[1:], env) else: raise LispError('%s is not a function' % unparse(ast[0]))
def eval_list(ast, env): """evaluate all the built-in functions""" if ast[0] == 'quote': return eval_quote(ast, env) elif ast[0] == 'exit': return eval_exit(ast) elif ast[0] == 'print': return eval_print(ast, env) elif ast[0] == 'atom': return eval_atom(ast, env) elif ast[0] == 'let': return eval_let(ast, env) elif ast[0] == 'def': return eval_def(ast, env) elif ast[0] == 'lambda': return eval_lambda(ast, env) elif ast[0] == 'eq': return eval_eq(ast, env) elif ast[0] == 'set': return eval_set(ast, env) elif ast[0] == 'if': return eval_if(ast, env) elif ast[0] == 'cons': return eval_cons(ast, env) elif ast[0] == 'head': return eval_head(ast, env) elif ast[0] == 'tail': return eval_tail(ast, env) elif ast[0] == 'rhead': return eval_rhead(ast, env) elif ast[0] == 'rtail': return eval_rtail(ast, env) elif ast[0] == 'empty': return eval_empty(ast, env) elif ast[0] in ['+', '-', '*', '**', '/', 'mod', '<', '<=', '=', '!=', '>=', '>']: return eval_math(ast, env) elif ast[0] == 'random': return eval_random() elif ast[0] in ['int', 'float', 'str', 'type']: return eval_types(ast, env) elif ast[0] in ['str_append', 'str_split']: return eval_string(ast, env) elif is_closure(ast[0]): return apply(ast, env) elif is_symbol(ast[0]) or is_list(ast[0]): return evaluate([evaluate(ast[0], env)] + ast[1:], env) else: raise LispError('%s is not a function' % unparse(ast[0]))
def interpret_file(filename, env=None): """ Interpret a lisp file Accepts the name of a lisp file containing a series of statements. Returns the value of the last expression of the file. """ if env is None: env = Environment() with open(filename, 'r') as sourcefile: source = "".join(sourcefile.readlines()) asts = parse_multiple(source) results = [evaluate(ast, env) for ast in asts] return unparse(results[-1])
def solve_and_display(path="to_solve.txt", display_speed=True): # Opening file to_solve = open(path, "r") S = "" for line in to_solve: S += line to_solve.close() #Parsing time_message = "\nSudoku solving speed:\n" if type(S) is str: timestamp_unparsed = time.clock() S = parse(S) timestamp_parsed = time.clock() time_parsing = int( (timestamp_parsed - timestamp_unparsed) * 1000) / 1000 time_message += "Parsing... {} seconds\n".format(time_parsing) else: time_message #Solving timestamp_unsolved = time.clock() solve(S) timestamp_solved = time.clock() time_solving = int((timestamp_solved - timestamp_unsolved) * 1000) / 1000 # Displaying time_message += "Solving... {} seconds\n".format(time_solving) print(S) # Solved! if display_speed: print(time_message) print("Find the answer in the solved.txt file or above!") # Writing solved = open("solved.txt", "w") s = unparse(S) solved.write(s) solved.close() return
def evaluate(ast, env): """Evaluate an Abstract Syntax Tree in the specified environment.""" if is_atom(ast): if is_symbol(ast): return forms[ast] if ast in forms else env.lookup(ast) else: return ast else: if (len(ast) == 0): return [] fn = evaluate(ast[0], env) args = ast[1:] if len(ast) > 1 else [] if callable(fn): return fn(args, env) if is_closure(fn): return apply(fn, args, env) elif is_list(fn): return evaluate([evaluate(fn, env)] + args, env) else: raise LispError("%s is not a function." % unparse(fn))
def test_unparse(): expected = """ ADD 1 2; ST 0 2; SHL 3 0; LD 1 3; DATA 2; JMPR 0 1; JMP; CLF; JC; JCA; JCEZ; J; IN 3; OUT 1;""" parsed = [ [1, 0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 0, 0, 1, 0], [1, 0, 1, 0, 1, 1, 0, 0], [0, 0, 0, 0, 0, 1, 1, 1], [0, 0, 1, 0, 0, 0, 1, 0], [0, 0, 1, 1, 0, 0, 0, 1], [0, 1, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0], [0, 1, 0, 1, 1, 0, 0, 0], [0, 1, 0, 1, 1, 1, 0, 0], [0, 1, 0, 1, 1, 0, 1, 1], [0, 1, 0, 1, 0, 0, 0, 0], [0, 1, 1, 1, 0, 0, 1, 1], [0, 1, 1, 1, 1, 0, 0, 1], ] unparsed = [ parser.unparse(int(''.join(map(str, line)), 2)) for line in parsed ] assert unparsed == [line.strip() for line in expected.split(';') if line]
def interpret_file(filename, env=None): """ Interpret a lisp file Accepts the name of a lisp file containing a series of statements. Returns the value of the last expression of the file. """ if env is None: env = Environment() with open(filename, 'r') as sourcefile: source = "".join(sourcefile.readlines()) asts = parse_multiple(source) imports = filter(lambda a: a[0] == 'import', asts) asts = filter(lambda a: a[0] != 'import', asts) results = [evaluate(ast, env) for ast in asts] for imp in imports: interpret_file(imp[1][1:-1], env) # If the Slow Loris file contains only comments or includes, don't fail. if len(results) == 0: return '' return unparse(results[-1])
def assert_boolean(p, exp=None): if not is_boolean(p): msg = "Boolean required, got '%s'. " % unparse(p) if exp is not None: msg += "Offending expression: %s" % unparse(exp) raise LispTypeError(msg)
def interpret(exp, env=None): """Interpret a single Lisp expression""" exp = eval(parse(exp), env if env is not None else []) return unparse(exp)
def assert_symbol(p, exp=None): if not is_symbol(p): msg = "Symbol required, got '%s'. " % unparse(p) if exp is not None: msg += "Offending expression: %s" % unparse(exp) raise LispError(msg)
"zrx": "ZRX", "augur": "REP", "rep": "REP" }) while True: # takes in input from command line query = input("> ") if query == "q": break parsed_query = parser.parse(query)[0] cryptos = parser.parse(query)[1] response = cb.respond(parsed_query) if parser.unparse(response, cryptos) == "off-topic": print("off topic") # DEBUG # print(response) question = response[0] crypto = parser.unparse(response, cryptos).strip() # DEBUG: #print(question, crypto) #print("~"+crypto+"~") if cryptoDict.get(crypto) != None: if question == "price": priceOf(crypto, cryptoDict.get(crypto)) elif question == "cryptointro": cryptoIntro() elif question == "close": closeCrypto(crypto, cryptoDict.get(crypto))
def eval_begin(ast, env): if len(ast[1:]) == 0: raise LispSyntaxError("begin cannot be empty: %s" % unparse(ast)) results = [evaluate(exp, env) for exp in ast[1:]] return results[-1]
def simulation(program, frequency=12): if isinstance(program, str): program = parser.parse(program) RAM.MEM_SIZE = 6 with new_circuit() as circuit: clock = Clock() output = clock.lines >> cpu iars = tag_outputs(circuit, ["BIT"], "Cpu/IAR") irs = tag_outputs(circuit, ["BIT"], "Cpu/IR") n_rows = 8 n_cols = 8 rams = {(row, col): tag_outputs(circuit, ["BIT"], f"RAMRegister-{row * n_cols + col}/") for row in range(n_rows) for col in range(n_cols)} regs = { i: tag_outputs(circuit, ["BIT"], f"Cpu/Registers/{i}") for i in range(cpu.N_REGISTERS) } bus = tag_outputs(circuit, ["MAINBUS"]) stepper = tag_outputs(circuit, ["STEPPER"]) selectors = tag_outputs(circuit, ["SELECTOR", "CONTROL"]) enablers = tag_outputs(circuit, ["ENABLER", "CONTROL"]) mars = tag_outputs(circuit, ["MAROUTPUT"]) acc = tag_outputs(circuit, ["BIT"], "ACC") flags = tag_outputs(circuit, ["FLAG"]) bootloader_program_ = bootloader_program() simulation = {} def set_lines(lines, vals, prev=None): if prev is None: prev = {} prev.update({l: v for l, v in zip(lines, vals)}) return prev bl_length = 6 # Stores the Fibonacci sequence in RAM my_program = program print("MY PROGRAM") pprint(my_program) print("BL PROGRAM") pprint(bootloader_program_) def bootload(program): return { k: v for i, program_line in enumerate(program) for k, v in set_lines(rams[(i // n_cols, i % n_cols)], program_line).items() } fixed_dict = bootload(bootloader_program_) def vals(lines, keys=False, show_all=False, decimal=True): values = [int(simulation[line]) for line in lines] if show_all: return [(line.name, value) for line, value in zip(lines, values)] if keys: return { line.name for line, value in zip(lines, values) if value } if len(lines) != 8: decimal = True d_value = int("".join(map(str, values)), 2) if decimal: return d_value return "{0:02x}".format(d_value) io_lines = tag_outputs(circuit, ("IO", ("IO", "IN"))) out_lines = tag_outputs(circuit, ("IO", ("IO", "OUT"))) def input_dict(step): if step == 0: return { line: v for line, v in zip( io_lines, list(map(int, "{0:010b}".format(len(my_program))[2:]))) } step -= 4 if step < 0: return {} step //= bl_length if step >= len(my_program): return {} return {line: v for line, v in zip(io_lines, my_program[step])} for i in range(100000000): feed_dict = clock.step() feed_dict.update(fixed_dict) feed_dict.update(input_dict(i // 24)) simulation.update(simulate(feed_dict, circuit, simulation)) if i % frequency: continue # pprint(feed_dict) out_enablers = set() for line in enablers: if simulation[line]: for line_type in line.line_types: if not isinstance(line_type, tuple): continue if line_type[0] == "E": if line_type[1] == 'R': continue out_enablers.add(line_type[1]) if line_type[0] == "R": out_enablers.add(f'R{line_type[1]}') out_selectors = set() for line in selectors: if simulation[line]: for line_type in line.line_types: if not isinstance(line_type, tuple): continue if line_type[0] == "S": if line_type[1] == 'R': continue out_selectors.add(line_type[1]) if line_type[0] == "R": out_selectors.add(f'R{line_type[1]}') yield { "iar": vals(iars), "ram": { 'data': [[vals(rams[(row, col)]) for col in range(n_cols)] for row in range(n_rows)] }, "ir": { "value": vals(irs), "interpretation": parser.unparse(vals(irs)), }, "registers": [vals(regs[i]) for i in range(len(regs))], "steps": { "steps": [bool(simulation[line]) for line in stepper] }, "flags": { "values": {flag.name[-1]: bool(simulation[flag]) for flag in flags} }, "input": { "value": vals(io_lines), "interpretation": parser.unparse(vals(io_lines)), }, "bus": { "value": vals(bus), "interpretation": parser.unparse(vals(bus)), }, "enablers": list(out_enablers), "selectors": list(out_selectors), "output": vals(out_lines), } # for s in simulation( # """ # DATA 0 43; # Starting register to store output in RAM # DATA 1 42; # Location of next register to write to # ST 1 0; # Store the next output register value in RAM # XOR 0 0; # Zero Register 0 # DATA 1 1; # Store "1" in 1 # XOR 2 2; # START LOOP(Loc 22) Zero Register 2 # ADD 0 2; # Reg 2 <- 0 + (Reg 0) # ADD 1 2; # Reg 2 <- (Reg 0) + (Reg 1) [r2 = r0 + r1] # XOR 0 0; # Zero Reg 0 # ADD 1 0; # Reg 0 <- 0 + (Reg 1) [r0 = r1] # XOR 1 1; # Zero Reg 1 # ADD 2 1; # Reg 1 <- 0 + Reg 2 [r1 = (old r0) + (old r1)] # OUT 1 ; # Put Result on OUTPUT # DATA 3 42; # Load where to find next register address into 3 # LD 3 3; # Load the actual next register address into 3 # ST 3 1; # Store Reg 1 in the next output register # DATA 2 1; # Set Reg 2 to 1 # ADD 2 3; # Add 1 to next register address # DATA 2 42; # Load Address where to store next output address into Reg 2 # ST 2 3; # Replace next register address w/ same value + 1 # JMP 22 ; # END LOOP(Loc 22) # """): # pprint(s)
def eval_lambda(ast, env): assert_exp_length(ast, 3) if not is_list(ast[1]): raise LispError('non-list: %s' % unparse(ast[1])) return Closure(env, ast[1], ast[2])
def test_expand_crazy_quote_combo(): """One final test to see that quote expansion works.""" source = "'(this ''''(makes ''no) 'sense)" assert_equals(source, unparse(parse(source)))
import parser import cryptobot as cb while True: # takes in input from command line query = input("> ") if query == "q": break parsed_query = parser.parse(query)[0] cryptos = parser.parse(query)[1] response = cb.respond(parsed_query) function_call = "calling " + response[ 0] + " function on " + parser.unparse(response, cryptos) if parser.unparse(response, cryptos) == "off-topic": print("off topic") else: # print(input) print(parsed_query) print(cryptos) print(function_call)
def evaluate(ast, env): """Evaluate an Abstract Syntax Tree in the specified environment.""" if ast == "#t": return True if ast == "#f": return False if is_symbol(ast): symbol_value = env.lookup(ast) # if is_closure(symbol_value): # return evaluate(symbol_value, env) return symbol_value if is_integer(ast): return ast first_element = ast[0] if first_element == "quote": if len(ast) == 2: return ast[1] else: return [] if first_element == "atom": return is_atom(evaluate(ast[1], env)) if first_element == "if": if evaluate(ast[1], env): return evaluate(ast[2], env) else: return evaluate(ast[3], env) if first_element == "define": if len(ast) != 3: raise LispError("Wrong number of arguments") symbol_name = ast[1] if not is_symbol(symbol_name): raise LispError("non-symbol") value = evaluate(ast[2], env) env.set(symbol_name, value) return value if first_element == "eq": evaluated_items = [evaluate(item, env) for item in ast[1:]] for i in range(len(evaluated_items) - 1): return is_atom(evaluated_items[i]) and evaluated_items[i] == evaluated_items[i + 1] else: return True if first_element in ["+", "-", "*", "/", "mod", "<", ">"] and not (is_integer(evaluate(ast[1], env)) and is_integer( evaluate(ast[2], env))): error_message = "Math functions only take integer args but you tried to do (%s, %s, %s)" % ( first_element, (evaluate(ast[1], env)), (evaluate(ast[2], env))) raise LispError(error_message) if first_element == "+": return evaluate(ast[1], env) + evaluate(ast[2], env) if first_element == "-": return evaluate(ast[1], env) - evaluate(ast[2], env) if first_element == "*": return evaluate(ast[1], env) * evaluate(ast[2], env) if first_element == "/": return evaluate(ast[1], env) / evaluate(ast[2], env) if first_element == "mod": return evaluate(ast[1], env) % evaluate(ast[2], env) if first_element == ">": return evaluate(ast[1], env) > evaluate(ast[2], env) if first_element == "<": return evaluate(ast[1], env) < evaluate(ast[2], env) # List functions if first_element == "cons": if len(ast) != 3: raise LispError("cons requires 2 arguments") element = evaluate(ast[1], env) list = evaluate(ast[2], env) if not is_list(list): raise LispError("cons requires second arg to be list but got %s" % unparse(ast[2])) list.insert(0, element) return list if first_element == "head": if len(ast) != 2: raise LispError("head requires 1 argument") list_expression = evaluate(ast[1], env) if not is_list(list_expression) or len(list_expression) < 1: raise LispError("head requires a list of at least length 1") return list_expression[0] if first_element == "tail": if len(ast) != 2: raise LispError("tail requires 1 argument") list_expression = evaluate(ast[1], env) if not is_list(list_expression) or len(list_expression) < 1: raise LispError("tail requires a list argument") return list_expression[1:] if first_element == "empty": if len(ast) != 2: raise LispError("empty requires 1 argument") list_expression = evaluate(ast[1], env) if not is_list(list_expression): raise LispError("empty requires a list argument") return len(list_expression) == 0 # Function functions if first_element == "lambda": if len(ast) != 3: raise LispError("number of arguments") params = ast[1] if not is_list(params): raise LispError("params must be a list") body = ast[2] return Closure(env, params, body) if first_element == "quit": raise QuitError("Bye!") if first_element == "print": print "".join((str(evaluate(i, env)) for i in ast[1:])) return [] if first_element == "pp": print " ".join((str(evaluate(i, env)) for i in ast[1:])) return [] if first_element == "do": for i in ast[1:-1]: evaluate(i, env) return evaluate(ast[-1], env) if is_list(ast): if len(ast) == 0: return [] if is_symbol(first_element) and env.has_symbol(first_element): closure = env.lookup(first_element) elif is_closure(first_element): closure = first_element else: closure = evaluate(first_element, env) if not is_closure(closure): raise LispError("not a function") argument_bindings = {} if len(ast) > 1: param_values = ast[1:] closure_params = closure.params if len(closure_params) != len(param_values): raise LispError("wrong number of arguments, expected %i got %i" % (len(closure_params), len(param_values))) for i in range(len(closure_params)): param_name = closure_params[i] argument_bindings[param_name] = evaluate(param_values[i], env) result = evaluate(closure.body, closure.env.extend(argument_bindings)) if is_closure(result): return evaluate(result.body, result.env) return result
def test_cpu(circuit): circuit = circuit clock = circuit_module.Clock() output = clock.lines >> cpu iars = tag_outputs(circuit, ["BIT"], "Cpu/IAR") irs = tag_outputs(circuit, ["BIT"], "Cpu/IR") n_rows = 16 n_cols = 16 rams = { (row, col): tag_outputs(circuit, ["BIT"], f"RAMRegister-{row * n_cols + col}/") for row in range(n_rows) for col in range(n_cols) } regs = { i: tag_outputs(circuit, ["BIT"], f"Cpu/Registers/{i}") for i in range(cpu.N_REGISTERS) } bus = tag_outputs(circuit, ["MAINBUS"]) stepper = tag_outputs(circuit, ["STEPPER"]) selectors = tag_outputs(circuit, ["SELECTOR", "CONTROL"]) enablers = tag_outputs(circuit, ["ENABLER", "CONTROL"]) mars = tag_outputs(circuit, ["MAROUTPUT"]) acc = tag_outputs(circuit, ["BIT"], "ACC") flags = tag_outputs(circuit, ["FLAG"]) bootloader_program = circuit_module.bootloader_program() simulation = {} def set_lines(lines, vals, prev=None): if prev is None: prev = {} prev.update({l: v for l, v in zip(lines, vals)}) return prev bl_length = 6 # Stores the Fibonacci sequence in RAM my_program = parser.parse( """ DATA 0 43; # Starting register to store output in RAM DATA 1 42; # Location of next register to write to ST 1 0; # Store the next output register value in RAM XOR 0 0; # Zero Register 0 DATA 1 1; # Store "1" in 1 XOR 2 2; # START LOOP(Loc 22) Zero Register 2 ADD 0 2; # Reg 2 <- 0 + (Reg 0) ADD 1 2; # Reg 2 <- (Reg 0) + (Reg 1) [r2 = r0 + r1] XOR 0 0; # Zero Reg 0 ADD 1 0; # Reg 0 <- 0 + (Reg 1) [r0 = r1] XOR 1 1; # Zero Reg 1 ADD 2 1; # Reg 1 <- 0 + Reg 2 [r1 = (old r0) + (old r1)] OUT 1 ; # Put Result on OUTPUT DATA 3 42; # Load where to find next register address into 3 LD 3 3; # Load the actual next register address into 3 ST 3 1; # Store Reg 1 in the next output register DATA 2 1; # Set Reg 2 to 1 ADD 2 3; # Add 1 to next register address DATA 2 42; # Load Address where to store next output address into Reg 2 ST 2 3; # Replace next register address w/ same value + 1 JMP 22 ; # END LOOP(Loc 22) """ ) print("MY PROGRAM") pprint(my_program) print("BL PROGRAM") pprint(bootloader_program) def bootload(program): return { k: v for i, program_line in enumerate(program) for k, v in set_lines(rams[(i // n_cols, i % n_cols)], program_line).items() } fixed_dict = bootload(bootloader_program) def vals(lines, keys=False, show_all=False, decimal=False): values = [int(simulation[line]) for line in lines] if show_all: return [(line.name, value) for line, value in zip(lines, values)] if keys: return {line.name for line, value in zip(lines, values) if value} if len(lines) != 8: decimal = True d_value = int("".join(map(str, values)), 2) if decimal: return d_value return "{0:02x}".format(d_value) io_lines = tag_outputs(circuit, ("IO", ("IO", "IN"))) out_lines = tag_outputs(circuit, ("IO", ("IO", "OUT"))) def input_dict(step): if step == 0: return { line: v for line, v in zip( io_lines, list(map(int, "{0:010b}".format(len(my_program))[2:])) ) } step -= 4 if step < 0: return {} step //= bl_length if step >= len(my_program): return {} return {line: v for line, v in zip(io_lines, my_program[step])} for i in range(24 * 10000): feed_dict = clock.step() feed_dict.update(fixed_dict) feed_dict.update(input_dict(i // 24)) simulation.update(simulate(feed_dict, circuit, simulation)) if not (i + 1) % 24: print("CYC", i % 4, "RND", i // 24, "STEP", (i % 24) // 4) # print("CLOCK", vals(clock.lines)) print("IRS", vals(irs), parser.unparse(vals(irs, decimal=True))) print("BUS", vals(bus)) print("IAR", vals(iars)) print("MARS", vals(mars)) print("RAMS") print( "\n".join( " ".join(vals(rams[(row, col)]) for col in range(n_cols)) for row in range(n_rows) ) ) print("REGS") print(" ".join(vals(regs[i]) for i in range(len(regs)))) print("FLAGS", vals(flags, keys=True)) print("STEPPER", vals(stepper)) print("ACC", vals(acc)) print("ENABLERS", vals(enablers, keys=True)) print("SELECTORS", vals(selectors, keys=True)) print("IO-IN", vals(io_lines), parser.unparse(vals(io_lines, decimal=True))) print("IO-OU", vals(out_lines)) graph_tools.draw(circuit, feed_dict, simulation)
def err_not_function(expr): raise LispError("%s is not a function" % unparse(expr))