#!/usr/bin/env python3 from neb import lex, parse, interpret, NebPanic, Environment, MultiFunction, Builtin, UserFunction from neb.std import * import sys import readline from pathlib import Path class NebCompleter: def __init__(self, syntax): self.syntax = syntax def complete(self, text, state): results = [x for x in self.syntax if x.startswith(text)] + [None] return results[state] def build_std(repl=False): GLOBALS = Environment() envs = [ BOOLEAN.environment, CORE.environment, FUNCTOOLS.environment, FS.environment, LISTS.environment, MATH.environment, STRINGS.environment, SYS.environment, TERM.environment, TYPES.environment ] global_dict = {} for env in envs: for key, val in env.items(): if key not in global_dict: global_dict[key] = val continue global_item = global_dict[key] if isinstance(global_item, MultiFunction): for i in val.impls.values(): global_item.register(i) elif isinstance(global_item, Builtin) or isinstance(global_item, UserFunction): mf = MultiFunction(key) mf.register(global_item) mf.register(val) global_dict[key] = mf else: raise NebPanic("bad environment juju") ''' global_dict = { **BOOLEAN.environment, **CORE.environment, **FUNCTOOLS.environment, **FS.environment, **LISTS.environment, **MATH.environment, **STRINGS.environment, **SYS.environment, **TERM.environment, **TYPES.environment } ''' if repl: for key, val in REPL.environment.items(): if key not in global_dict: global_dict[key] = val elif isinstance(global_dict[key], MultiFunction): for i in val.impls: global_dict[key].register(i) else: raise NebPanic("bad environment juju") GLOBALS.environment = global_dict return GLOBALS def debug(prev_lexed, prev_parsed): if prev_lexed is not None: acc = " ".join([f"{l}" for l in prev_lexed]) print(f" - LEX: {acc}") if prev_parsed is not None: acc = " ".join([f"{p}" for p in prev_parsed]) print(f" - PARSE: {acc}") def repl(): env = build_std(True) readline.parse_and_bind("tab: complete") cmp = NebCompleter(env.environment.keys()) readline.set_completer(cmp.complete) readline.set_completer_delims(" ()") initfil = Path("~/.local/share/neb/init.neb").expanduser() if initfil.exists(): try: lexed = lex(f'(use "{initfil}")') parsed = parse(lexed) ev = interpret(parsed, env) except NebPanic as ne: print(f"panic! {ne}") return except Exception as e: print(f"exception! {type(e)} {e}") return print("### neb :)(:") print("version: < 0") idx = 1 prev_idx = 0 prev_lexed = None prev_parsed = None while True: inp = input(f"#{idx}> ") if len(inp.strip()) == 0: continue try: if inp.strip() == "(debug)": debug(prev_lexed, prev_parsed) continue lexed = lex(inp) prev_lexed = lexed parsed = parse(lexed) prev_parsed = parsed inter = interpret(parsed, env) print(f"=> {inter}") prev_idx = idx idx += 1 except NebPanic as ne: print(f"panic! {ne}") except Exception as e: print(f"exception! {type(e)} {e}") def run_file(filename): env = build_std(True) readline.parse_and_bind("tab: complete") cmp = NebCompleter(env.environment.keys()) readline.set_completer(cmp.complete) readline.set_completer_delims(" ()") with open(filename, "r") as fil: data = fil.read() try: lexed = lex(data) parsed = parse(lexed) ev = interpret(parsed, env) except NebPanic as ne: print(f"panic! {ne}") except Exception as e: print(f"exception! {type(e)} {e}") if __name__ == "__main__": if len(sys.argv) == 1: repl() elif len(sys.argv) >= 2: run_file(sys.argv[1]) else: print("usage: neb []") sys.exit(1)