From f4622e734ef2be1c3793113e93219d593e3e11fb Mon Sep 17 00:00:00 2001 From: mryouse Date: Thu, 7 Jul 2022 02:04:28 +0000 Subject: refactor move all functions with 'lazy' to core --- neb/std/boolean.py | 25 ------------------------- neb/std/core.py | 43 +++++++++++++++++++++++++++++++++++++++++++ neb/std/functools.py | 10 ---------- neb/std/sys.py | 9 --------- 4 files changed, 43 insertions(+), 44 deletions(-) (limited to 'neb') diff --git a/neb/std/boolean.py b/neb/std/boolean.py index 973fa67..e716a87 100644 --- a/neb/std/boolean.py +++ b/neb/std/boolean.py @@ -3,31 +3,6 @@ from ..structs import * BOOLEAN = Environment() -def interpretOr(symbol, args, env, ns): - # or returns true for the first expression that returns true - for arg in args: - ev = evaluate(arg, env, ns) - if not isinstance(ev, Bool): - raise InterpretPanic(symbol, "requires :bool arguments") - if ev.value == True: - return ev - return Bool(False) - -or_arg = Arg("arg", TypeEnum.BOOL, lazy=True) -BOOLEAN.register("or", Builtin("or", interpretOr, [or_arg, or_arg], or_arg, Type(":bool"))) - -def interpretAnd(symbol, args, env, ns): - # and returns false for the first expression that returns false - for arg in args: - ev = evaluate(arg, env, ns) - if not isinstance(ev, Bool): - raise InterpretPanic(symbol, "requires :bool arguments") - if ev.value == False: - return ev - return Bool(True) - -BOOLEAN.register("and", Builtin("and", interpretAnd, [or_arg, or_arg], or_arg, Type(":bool"))) - def interpretEq(symbol, args, env, ns): # NOTE this currently only works for literals # compare types because 0 != #false in neb diff --git a/neb/std/core.py b/neb/std/core.py index 574455d..1645699 100644 --- a/neb/std/core.py +++ b/neb/std/core.py @@ -220,3 +220,46 @@ type_parent_arg = Arg("name", TypeEnum.ANY) type_func_arg = Arg("func", TypeEnum.ANY) CORE.register("type", Builtin("type", interpretType, [type_name_arg, type_parent_arg, type_func_arg])) +def interpretOr(symbol, args, env, ns): + # or returns true for the first expression that returns true + for arg in args: + ev = evaluate(arg, env, ns) + if not isinstance(ev, Bool): + raise InterpretPanic(symbol, "requires :bool arguments") + if ev.value == True: + return ev + return Bool(False) + +or_arg = Arg("arg", TypeEnum.BOOL, lazy=True) +CORE.register("or", Builtin("or", interpretOr, [or_arg, or_arg], or_arg, Type(":bool"))) + +def interpretAnd(symbol, args, env, ns): + # and returns false for the first expression that returns false + for arg in args: + ev = evaluate(arg, env, ns) + if not isinstance(ev, Bool): + raise InterpretPanic(symbol, "requires :bool arguments") + if ev.value == False: + return ev + return Bool(True) + +CORE.register("and", Builtin("and", interpretAnd, [or_arg, or_arg], or_arg, Type(":bool"))) + +def interpretApply(symbol, args, env, ns): + # TODO: to support lambdas, we can't assume the func is defined + func = args[0] + if not isinstance(func, Symbol): + raise InterpretPanic(symbol, "requires a symbol as its first argument", func) + new_expr = Expr([func] + args[1].args) + return evaluate(new_expr, env, ns) + +CORE.register("apply", Builtin("apply", interpretApply, [Arg("func", TypeEnum.ANY, lazy=True), Arg("list", TypeEnum.LIST)])) + +def interpretBench(symbol, args, env, ns): + before = datetime.now() + ret = evaluate(args[0], env, ns) + after = datetime.now() + print(f"bench [{symbol.line}]: {args[0]} => {after - before}") + return ret + +CORE.register("bench", Builtin("bench", interpretBench, [Arg("command", TypeEnum.ANY, lazy=True)], return_type=Type(":any"))) diff --git a/neb/std/functools.py b/neb/std/functools.py index 9e426b8..8a76e98 100644 --- a/neb/std/functools.py +++ b/neb/std/functools.py @@ -34,13 +34,3 @@ def interpretMap(symbol, args, env, ns): FUNCTOOLS.register("map", Builtin("map", interpretMap, [Arg("func", TypeEnum.ANY), Arg("list", TypeEnum.LIST)], return_type=Type(":list"))) -def interpretApply(symbol, args, env, ns): - # TODO: to support lambdas, we can't assume the func is defined - func = args[0] - if not isinstance(func, Symbol): - raise InterpretPanic(symbol, "requires a symbol as its first argument", func) - new_expr = Expr([func] + args[1].args) - return evaluate(new_expr, env, ns) - -FUNCTOOLS.register("apply", Builtin("apply", interpretApply, [Arg("func", TypeEnum.ANY, lazy=True), Arg("list", TypeEnum.LIST)])) - diff --git a/neb/std/sys.py b/neb/std/sys.py index 525895a..f92eb77 100644 --- a/neb/std/sys.py +++ b/neb/std/sys.py @@ -35,15 +35,6 @@ def interpretPrint(symbol, args, env, ns): SYS.register("print", Builtin("print", interpretPrint, [Arg("arg", TypeEnum.STRING)], return_type=Type(":list"))) -def interpretBench(symbol, args, env, ns): - before = datetime.now() - ret = evaluate(args[0], env, ns) - after = datetime.now() - print(f"bench [{symbol.line}]: {args[0]} => {after - before}") - return ret - -SYS.register("bench", Builtin("bench", interpretBench, [Arg("command", TypeEnum.ANY, lazy=True)], return_type=Type(":any"))) - def interpretEnv(symbol, args, env, ns): items = os.environ[args[0].value].split(":") return List([String(item) for item in items]) -- cgit v1.2.3 From 5716911ede71261177073ca57fd139641149ace0 Mon Sep 17 00:00:00 2001 From: mryouse Date: Thu, 7 Jul 2022 02:16:54 +0000 Subject: refactor: add a higher level of Callable --- neb/__init__.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'neb') diff --git a/neb/__init__.py b/neb/__init__.py index dd7245a..76d5775 100644 --- a/neb/__init__.py +++ b/neb/__init__.py @@ -38,7 +38,8 @@ def evaluate(expr, env, ns=None): else: raise InterpretPanic(expr.args[0], "unable to evaluate") -class Function: + +class Callable: def __init__(self, name, params, body, args=None, many=None): self.name = name @@ -56,6 +57,18 @@ class Function: out.append(string_args(self.args, self.many)) return " ".join(out).strip() + f") => {self.return_type}" + def evaluate_args(self, symbol, params, env, ns): + pass + + def call(self, expr, env): + pass + + +class Function(Callable): + + def __init__(self, name, params, body, args=None, many=None): + super().__init__(name, params, body, args, many) + def arity_check(self, symbol, params): min_arity = len([a for a in self.args if not a.optional]) max_arity = -1 if self.many is not None else len(self.args) @@ -92,8 +105,6 @@ class Function: ret.append(ev) return ret - def call(self, expr, env): - pass class Builtin(Function): -- cgit v1.2.3 From 9e07b83ff396a8986d86e3968c4df77ee302a6a0 Mon Sep 17 00:00:00 2001 From: mryouse Date: Thu, 7 Jul 2022 02:27:42 +0000 Subject: refactor: s/evaluate_args/precall/ --- neb/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'neb') diff --git a/neb/__init__.py b/neb/__init__.py index 76d5775..b280914 100644 --- a/neb/__init__.py +++ b/neb/__init__.py @@ -57,7 +57,7 @@ class Callable: out.append(string_args(self.args, self.many)) return " ".join(out).strip() + f") => {self.return_type}" - def evaluate_args(self, symbol, params, env, ns): + def precall(self, symbol, params, env, ns): pass def call(self, expr, env): @@ -83,7 +83,7 @@ class Function(Callable): raise InterpretPanic(symbol, f"expected [{fmt}] arguments, received {len(params)}") return True - def evaluate_args(self, symbol, params, env, ns): + def precall(self, symbol, params, env, ns): ret = [] for idx, param in enumerate(params): @@ -118,7 +118,7 @@ class Builtin(Function): def call(self, expr, env, ns): self.arity_check(expr.args[0], expr.args[1:]) - evaluated_args = self.evaluate_args(expr.args[0], expr.args[1:], env, ns) + evaluated_args = self.precall(expr.args[0], expr.args[1:], env, ns) return self.body(expr.args[0], evaluated_args, env, ns) @@ -168,7 +168,7 @@ class UserFunction(Function): def call(self, expr, env, ns): self.arity_check(expr.args[0], expr.args[1:]) - evaluated_args = self.evaluate_args(expr.args[0], expr.args[1:], env, ns) + evaluated_args = self.precall(expr.args[0], expr.args[1:], env, ns) this_env = Environment(env) for idx, param in enumerate(self.params): this_env.register(param.name, evaluated_args[idx]) -- cgit v1.2.3 From 46cefa721d145af17bee3696ef533d752989458c Mon Sep 17 00:00:00 2001 From: mryouse Date: Thu, 7 Jul 2022 03:47:22 +0000 Subject: refactor: 'apply' to functools --- neb/std/core.py | 10 ---------- neb/std/functools.py | 8 ++++++++ 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'neb') diff --git a/neb/std/core.py b/neb/std/core.py index 1645699..f6b5b06 100644 --- a/neb/std/core.py +++ b/neb/std/core.py @@ -245,16 +245,6 @@ def interpretAnd(symbol, args, env, ns): CORE.register("and", Builtin("and", interpretAnd, [or_arg, or_arg], or_arg, Type(":bool"))) -def interpretApply(symbol, args, env, ns): - # TODO: to support lambdas, we can't assume the func is defined - func = args[0] - if not isinstance(func, Symbol): - raise InterpretPanic(symbol, "requires a symbol as its first argument", func) - new_expr = Expr([func] + args[1].args) - return evaluate(new_expr, env, ns) - -CORE.register("apply", Builtin("apply", interpretApply, [Arg("func", TypeEnum.ANY, lazy=True), Arg("list", TypeEnum.LIST)])) - def interpretBench(symbol, args, env, ns): before = datetime.now() ret = evaluate(args[0], env, ns) diff --git a/neb/std/functools.py b/neb/std/functools.py index 8a76e98..f83c49d 100644 --- a/neb/std/functools.py +++ b/neb/std/functools.py @@ -34,3 +34,11 @@ def interpretMap(symbol, args, env, ns): FUNCTOOLS.register("map", Builtin("map", interpretMap, [Arg("func", TypeEnum.ANY), Arg("list", TypeEnum.LIST)], return_type=Type(":list"))) +# TODO I think this is wrong +def interpretApply(symbol, args, env, ns): + func = args[0] + if not isinstance(func, Function): + raise InterpretPanic(symbol, "requires a symbol as its first argument", func) + return func.call(Expr([func] + args[1].args), env, ns) + +FUNCTOOLS.register("apply", Builtin("apply", interpretApply, [Arg("func", TypeEnum.ANY), Arg("list", TypeEnum.LIST)])) -- cgit v1.2.3 From 3412d4d0e35dfe1faac5254199aa34f0354e992b Mon Sep 17 00:00:00 2001 From: mryouse Date: Thu, 7 Jul 2022 03:48:05 +0000 Subject: refactor: add Macro structure under Callable, which is all core --- neb/__init__.py | 42 ++++++++++++------ neb/std/core.py | 135 ++++++++++++++++++++++++++++++++------------------------ neb/std/repl.py | 4 +- 3 files changed, 109 insertions(+), 72 deletions(-) (limited to 'neb') diff --git a/neb/__init__.py b/neb/__init__.py index b280914..6aeec88 100644 --- a/neb/__init__.py +++ b/neb/__init__.py @@ -11,7 +11,7 @@ def interpret(exprs, env, ns=None): return ret def evaluate(expr, env, ns=None): - if isinstance(expr, Literal) or isinstance(expr, Function) or isinstance(expr, TypeWrap) or isinstance(expr, List) or isinstance(expr, Handle): + if isinstance(expr, Literal) or isinstance(expr, Callable) or isinstance(expr, TypeWrap) or isinstance(expr, List) or isinstance(expr, Handle): return expr elif isinstance(expr, Symbol) or isinstance(expr, Type): if env.contains(expr.name): @@ -57,18 +57,6 @@ class Callable: out.append(string_args(self.args, self.many)) return " ".join(out).strip() + f") => {self.return_type}" - def precall(self, symbol, params, env, ns): - pass - - def call(self, expr, env): - pass - - -class Function(Callable): - - def __init__(self, name, params, body, args=None, many=None): - super().__init__(name, params, body, args, many) - def arity_check(self, symbol, params): min_arity = len([a for a in self.args if not a.optional]) max_arity = -1 if self.many is not None else len(self.args) @@ -83,6 +71,34 @@ class Function(Callable): raise InterpretPanic(symbol, f"expected [{fmt}] arguments, received {len(params)}") return True + def call(self, expr, env): + pass + +class Macro(Callable): + + def __init__(self, name, params, body, args=None, many=None): + super().__init__(name, params, body, args, many) + +class NebMacro(Callable): + + def __init__(self, name, callable_, args=None, many=None, return_type=None): + super().__init__(name, None, callable_, args, many) + if return_type is not None: + self.return_type = return_type + + def __str__(self): + return f"builtin function {self.name}" + + def call(self, expr, env, ns): + self.arity_check(expr.args[0], expr.args[1:]) + return self.body(expr.args[0], expr.args[1:], env, ns) + + +class Function(Callable): + + def __init__(self, name, params, body, args=None, many=None): + super().__init__(name, params, body, args, many) + def precall(self, symbol, params, env, ns): ret = [] diff --git a/neb/std/core.py b/neb/std/core.py index f6b5b06..a0f2cf6 100644 --- a/neb/std/core.py +++ b/neb/std/core.py @@ -1,48 +1,49 @@ -from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, evaluate, interpret, parse, lex, InterpretPanic, TypeWrap, Function, UserType +from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, evaluate, interpret, parse, lex, InterpretPanic, TypeWrap, Function, UserType, NebMacro from ..structs import * from pathlib import Path CORE = Environment() def interpretIf(symbol, args, env, ns): - if args[0].value: + cond = evaluate(args[0], env, ns) + if not isinstance(cond, Bool): + raise InterpretPanic(symbol, "requires a :bool condition", cond) + + if cond.value: return evaluate(args[1], env, ns) elif len(args) == 3: return evaluate(args[2], env, ns) return List([]) cond = Arg("cond", TypeEnum.BOOL) -t_branch = Arg("t-branch", TypeEnum.ANY, lazy=True) -f_branch = Arg("f-branch", TypeEnum.ANY, optional=True, lazy=True) -CORE.register("if", Builtin("if", interpretIf, [cond, t_branch, f_branch])) +t_branch = Arg("t-branch", TypeEnum.ANY) +f_branch = Arg("f-branch", TypeEnum.ANY, optional=True) +CORE.register("if", NebMacro("if", interpretIf, [cond, t_branch, f_branch])) def interpretDef(symbol, args, env, ns): - if not isinstance(args[0], Symbol): - raise InterpretPanic(symbol, "requires a :string name", args[0]) + raise InterpretPanic(symbol, "requires a :symbol", args[0]) name = args[0].name # NOTE: we are not evaluating the name!! - if not isinstance(name, str): - raise InterpretPanic(symbol, "requires a :string name") - - env.register(name, args[1]) # TODO since this isn't lazily evaluated, side effects are allowed (bad!) - + res = evaluate(args[1], env, ns) + env.register(name, res) return List([]) -def_name_arg = Arg("name", TypeEnum.ANY, lazy=True) +def_name_arg = Arg("name", TypeEnum.ANY) def_val_arg = Arg("value", TypeEnum.ANY) -CORE.register("def", Builtin("def", interpretDef, [def_name_arg, def_val_arg], return_type=Type(":list"))) +CORE.register("def", NebMacro("def", interpretDef, [def_name_arg, def_val_arg], return_type=Type(":list"))) def interpretRedef(symbol, args, env, ns): if not isinstance(args[0], Symbol): - raise InterpretPanic(symbol, "requires a :string name", args[0]) + raise InterpretPanic(symbol, "requires a :symbol", args[0]) name = args[0].name # NOTE: we are not evaluating the name!! if not env.contains(name): raise InterpretPanic(symbol, "not previously defined", args[0]) - env.reregister(name, args[1]) + res = evaluate(args[1], env, ns) + env.reregister(name, res) return List([]) -CORE.register("redef", Builtin("redef", interpretRedef, [def_name_arg, def_val_arg], return_type=Type(":list"))) +CORE.register("redef", NebMacro("redef", interpretRedef, [def_name_arg, def_val_arg], return_type=Type(":list"))) def interpretLambda(symbol, args, env, ns): new_args = args @@ -58,14 +59,17 @@ def interpretLambda(symbol, args, env, ns): func.return_type = return_type return func -lambda_args_arg = Arg("args", TypeEnum.ANY, lazy=True) -lambda_body_arg = Arg("body", TypeEnum.ANY, lazy=True) -CORE.register("lambda", Builtin("lambda", interpretLambda, [lambda_args_arg, lambda_body_arg], lambda_body_arg)) +lambda_args_arg = Arg("args", TypeEnum.ANY) +lambda_body_arg = Arg("body", TypeEnum.ANY) +CORE.register("lambda", NebMacro("lambda", interpretLambda, [lambda_args_arg, lambda_body_arg], lambda_body_arg)) def interpretForCount(symbol, args, env, ns): + num = evaluate(args[0], env, ns) + if not isinstance(num, Int): + raise InterpretPanic(symbol, "count must be an :int", num) new_env = Environment(env) ret = None - for idx in range(0, args[0].value): + for idx in range(0, num.value): new_env.register("idx", Int(idx + 1)) for arg in args[1:]: ret = evaluate(arg, new_env, ns) @@ -74,13 +78,16 @@ def interpretForCount(symbol, args, env, ns): return ret for_count_arg = Arg("count", TypeEnum.INT) -for_body_arg = Arg("body", TypeEnum.ANY, lazy=True) -CORE.register("for-count", Builtin("for-count", interpretForCount, [for_count_arg, for_body_arg], for_body_arg)) +for_body_arg = Arg("body", TypeEnum.ANY) +CORE.register("for-count", NebMacro("for-count", interpretForCount, [for_count_arg, for_body_arg], for_body_arg)) def interpretForEach(symbol, args, env, ns): + coll = evaluate(args[0], env, ns) + if not isinstance(coll, List): + raise InterpretPanic(symbol, "coll must be a :list", coll) new_env = Environment(env) ret = None - for item in args[0].args: + for item in coll.args: new_env.register("_item_", evaluate(item, env, ns)) for arg in args[1:]: ret = evaluate(arg, new_env, ns) @@ -89,12 +96,12 @@ def interpretForEach(symbol, args, env, ns): return ret for_each_arg = Arg("list", TypeEnum.LIST) -CORE.register("for-each", Builtin("for-each", interpretForEach, [for_each_arg, for_body_arg], for_body_arg)) +CORE.register("for-each", NebMacro("for-each", interpretForEach, [for_each_arg, for_body_arg], for_body_arg)) def interpretBranch(symbol, args, env, ns): for arg in args: if len(arg.args) != 2: - raise InterpretPanic(symbol, "each branch requires two expressions") + raise InterpretPanic(symbol, "each branch requires two expressions", len(arg.args)) cond = evaluate(arg.args[0], env, ns) # this is the condition if not isinstance(cond, Bool): raise InterpretPanic(symbol, "branch condition must be :bool", cond) @@ -102,11 +109,11 @@ def interpretBranch(symbol, args, env, ns): return evaluate(arg.args[1], env, ns) return List([]) -CORE.register("branch", Builtin("branch", interpretBranch, [for_body_arg], for_body_arg)) +CORE.register("branch", NebMacro("branch", interpretBranch, [for_body_arg], for_body_arg)) def interpretFunc(symbol, args, env, ns): if not isinstance(args[0], Symbol): - raise InterpretPanic(symbol, "requires a :string name") + raise InterpretPanic(symbol, "requires a :symbol") name = args[0].name # NOTE: we are not evaluating the name!! if ns is not None: @@ -121,7 +128,7 @@ def interpretFunc(symbol, args, env, ns): env.register(name, func) return List([]) -CORE.register("func", Builtin("func", interpretFunc, [def_name_arg, lambda_args_arg, lambda_body_arg], lambda_body_arg, Type(":list"))) +CORE.register("func", NebMacro("func", interpretFunc, [def_name_arg, lambda_args_arg, lambda_body_arg], lambda_body_arg, Type(":list"))) def interpretBlock(symbol, args, env, ns): new_env = Environment(env) @@ -130,8 +137,8 @@ def interpretBlock(symbol, args, env, ns): ret = evaluate(arg, new_env, ns) return ret -block_arg = Arg("expr", TypeEnum.ANY, lazy=True) -CORE.register("block", Builtin("block", interpretBlock, [block_arg], block_arg)) +block_arg = Arg("expr", TypeEnum.ANY) +CORE.register("block", NebMacro("block", interpretBlock, [block_arg], block_arg)) def interpretWhile(symbol, args, env, ns): new_env = Environment(env) @@ -140,18 +147,21 @@ def interpretWhile(symbol, args, env, ns): while True: ev = evaluate(cond, new_env, ns) if not isinstance(ev, Bool): - raise InterpretPanic(symbol, "expects a :bool condition", ev) + raise InterpretPanic(symbol, "requires a :bool condition", cond) if not ev.value: break for arg in args[1:]: ret = evaluate(arg, new_env, ns) return ret -CORE.register("while", Builtin("while", interpretWhile, [Arg("cond", TypeEnum.BOOL, lazy=True)], Arg("expr", TypeEnum.ANY, lazy=True))) +CORE.register("while", NebMacro("while", interpretWhile, [Arg("cond", TypeEnum.BOOL)], Arg("expr", TypeEnum.ANY))) +# NOTE this doesn't technically need to be a macro def interpretUse(symbol, args, env, ns): - target_file_name = args[0].value - target_file = Path(target_file_name).resolve() + target = evaluate(args[0], env, ns) + if not isinstance(target, String): + raise InterpretPanic(symbol, "filename must be a :string", target) + target_file = Path(target.value).resolve() if not target_file.exists(): raise InterpretPanic(symbol, "no such file", target_file) with open(target_file, "r") as fil: @@ -159,38 +169,48 @@ def interpretUse(symbol, args, env, ns): interpret(parse(lex(data)), env, ns) return List([]) -CORE.register("use", Builtin("use", interpretUse, [Arg("filename", TypeEnum.STRING)], return_type=Type(":list"))) +CORE.register("use", NebMacro("use", interpretUse, [Arg("filename", TypeEnum.STRING)], return_type=Type(":list"))) +# NOTE this doesn't technically need to be a macro def interpretAssert(symbol, args, env, ns): - if args[0].value != True: + cond = evaluate(args[0], env, ns) + if not isinstance(cond, Bool): + raise InterpretPanic(symbol, "requires a :bool condition", cond) + if cond.value != True: raise InterpretPanic(symbol, "assertion failed") return List([]) -CORE.register("assert", Builtin("assert", interpretAssert, [Arg("cond", TypeEnum.BOOL)], return_type=Type(":list"))) +CORE.register("assert", NebMacro("assert", interpretAssert, [Arg("cond", TypeEnum.BOOL)], return_type=Type(":list"))) def interpretUseAs(symbol, args, env, ns): - target_file_name = args[0].value - target_file = Path(target_file_name).resolve() + target = evaluate(args[0], env, ns) + if not isinstance(target, String): + raise InterpretPanic(symbol, "filename must be a :string", target) + target_file = Path(target.value).resolve() if not target_file.exists(): raise InterpretPanic(symbol, "no such file", target_file) + if not isinstance(args[1], Symbol): + raise InterpretPanic(symbol, "requires a :symbol", args[1]) + new_ns = args[1].name with open(target_file, "r") as fil: data = fil.read() - interpret(parse(lex(data)), env, args[1].name) + interpret(parse(lex(data)), env, new_ns) return List([]) -CORE.register("use-as", Builtin("use-as", interpretUseAs, [Arg("filename", TypeEnum.STRING), Arg("namespace", TypeEnum.ANY, lazy=True)], return_type=Type(":list"))) +CORE.register("use-as", NebMacro("use-as", interpretUseAs, [Arg("filename", TypeEnum.STRING), Arg("namespace", TypeEnum.ANY)], return_type=Type(":list"))) def interpretQuote(symbol, args, env, ns): return args[0] -quote_arg = Arg("arg", TypeEnum.ANY, lazy=True) -CORE.register("quote", Builtin("quote", interpretQuote, [quote_arg])) +quote_arg = Arg("arg", TypeEnum.ANY) +CORE.register("quote", NebMacro("quote", interpretQuote, [quote_arg])) def interpretEval(symbol, args, env, ns): - return evaluate(args[0], env, ns) # TODO why do i have to explicitly evaluate here? + ev = evaluate(args[0], env, ns) # TODO why do i have to evaluate twice? + return evaluate(ev, env, ns) eval_arg = Arg("arg", TypeEnum.ANY) -CORE.register("eval", Builtin("eval", interpretEval, [eval_arg])) +CORE.register("eval", NebMacro("eval", interpretEval, [eval_arg])) def interpretType(symbol, args, env, ns): # (type typename parent func) @@ -201,13 +221,14 @@ def interpretType(symbol, args, env, ns): # TODO we may need to do namespace things here # also, we probably shouldn't be able to rename types - if not isinstance(args[1], TypeWrap): - raise InterpretPanic(symbol, "parent must be a valid type", args[1]) - elif not env.contains(args[1].name): - raise InterpretPanic(symbol, f"no such type {args[1]}") - parent = env.get(args[1].name) + parent_type = evaluate(args[1], env, ns) + if not isinstance(parent_type, TypeWrap): + raise InterpretPanic(symbol, "parent must be a valid type", parent_type) + elif not env.contains(parent_type.name): + raise InterpretPanic(symbol, f"no such type {parent_type}") + parent = env.get(parent_type.name) - func = args[2] + func = evaluate(args[2], env, ns) if not isinstance(func, Function): raise InterpretPanic(symbol, "validation must be a :func", func) @@ -215,10 +236,10 @@ def interpretType(symbol, args, env, ns): env.register(name, new_type) return List([]) -type_name_arg = Arg("name", TypeEnum.ANY, lazy=True) +type_name_arg = Arg("name", TypeEnum.ANY) type_parent_arg = Arg("name", TypeEnum.ANY) type_func_arg = Arg("func", TypeEnum.ANY) -CORE.register("type", Builtin("type", interpretType, [type_name_arg, type_parent_arg, type_func_arg])) +CORE.register("type", NebMacro("type", interpretType, [type_name_arg, type_parent_arg, type_func_arg])) def interpretOr(symbol, args, env, ns): # or returns true for the first expression that returns true @@ -230,8 +251,8 @@ def interpretOr(symbol, args, env, ns): return ev return Bool(False) -or_arg = Arg("arg", TypeEnum.BOOL, lazy=True) -CORE.register("or", Builtin("or", interpretOr, [or_arg, or_arg], or_arg, Type(":bool"))) +or_arg = Arg("arg", TypeEnum.BOOL) +CORE.register("or", NebMacro("or", interpretOr, [or_arg, or_arg], or_arg, Type(":bool"))) def interpretAnd(symbol, args, env, ns): # and returns false for the first expression that returns false @@ -252,4 +273,4 @@ def interpretBench(symbol, args, env, ns): print(f"bench [{symbol.line}]: {args[0]} => {after - before}") return ret -CORE.register("bench", Builtin("bench", interpretBench, [Arg("command", TypeEnum.ANY, lazy=True)], return_type=Type(":any"))) +CORE.register("bench", NebMacro("bench", interpretBench, [Arg("command", TypeEnum.ANY)], return_type=Type(":any"))) diff --git a/neb/std/repl.py b/neb/std/repl.py index 16efb20..73f82d6 100644 --- a/neb/std/repl.py +++ b/neb/std/repl.py @@ -1,10 +1,10 @@ -from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, Function, evaluate, InterpretPanic +from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, Function, evaluate, InterpretPanic, Callable from ..structs import * REPL = Environment() def interpretHowTo(symbol, args, env, ns): - if not isinstance(args[0], Function): + if not isinstance(args[0], Callable): raise InterpretPanic(symbol, "expects a :func", args[0]) print(args[0].describe()) return List([]) -- cgit v1.2.3 From 8e8b54a2a141955d0cbf4dd6ca6635fd5f6fb786 Mon Sep 17 00:00:00 2001 From: mryouse Date: Thu, 7 Jul 2022 03:53:52 +0000 Subject: bugfix: NebMacro inherits from Macro --- neb/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'neb') diff --git a/neb/__init__.py b/neb/__init__.py index 6aeec88..63b6d51 100644 --- a/neb/__init__.py +++ b/neb/__init__.py @@ -79,7 +79,7 @@ class Macro(Callable): def __init__(self, name, params, body, args=None, many=None): super().__init__(name, params, body, args, many) -class NebMacro(Callable): +class NebMacro(Macro): def __init__(self, name, callable_, args=None, many=None, return_type=None): super().__init__(name, None, callable_, args, many) -- cgit v1.2.3 From 4f7269c5c78170157a234ce262053742fef73953 Mon Sep 17 00:00:00 2001 From: mryouse Date: Thu, 7 Jul 2022 03:54:11 +0000 Subject: implement macros function --- neb/std/repl.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'neb') diff --git a/neb/std/repl.py b/neb/std/repl.py index 73f82d6..fbb0366 100644 --- a/neb/std/repl.py +++ b/neb/std/repl.py @@ -1,4 +1,4 @@ -from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, Function, evaluate, InterpretPanic, Callable +from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, Function, evaluate, InterpretPanic, Callable, Macro from ..structs import * REPL = Environment() @@ -18,7 +18,7 @@ def interpretSymbols(symbol, args, env, ns): REPL.register("symbols", Builtin("symbols", interpretSymbols, [], return_type=Type(":list"))) def interpretFuncs(symbol, args, env, ns): - keys = [Symbol(k, -1) for k,v in env.environment.items() if isinstance(v, Builtin)] + keys = [Symbol(k, -1) for k,v in sorted(env.environment.items()) if isinstance(v, Function)] return List(keys) REPL.register("funcs", Builtin("funcs", interpretFuncs, [], return_type=Type(":list"))) @@ -28,3 +28,9 @@ def interpretUserSymbols(symbol, args, env, ns): return List(keys) REPL.register("user-symbols", Builtin("user-symbols", interpretUserSymbols, [], return_type=Type(":list"))) + +def interpretMacros(symbol, args, env, ns): + keys = [Symbol(k, -1) for k,v in sorted(env.environment.items()) if isinstance(v, Macro)] + return List(keys) + +REPL.register("macros", Builtin("macros", interpretMacros, [], return_type=Type(":list"))) -- cgit v1.2.3 From e2c7c060c370b6c9137f41e69ce44481afbcf89d Mon Sep 17 00:00:00 2001 From: mryouse Date: Thu, 7 Jul 2022 03:57:57 +0000 Subject: remove 'lazy' as an Arg parameter --- neb/__init__.py | 3 --- neb/std/fs.py | 13 ------------- neb/structs.py | 3 +-- 3 files changed, 1 insertion(+), 18 deletions(-) (limited to 'neb') diff --git a/neb/__init__.py b/neb/__init__.py index 63b6d51..4831019 100644 --- a/neb/__init__.py +++ b/neb/__init__.py @@ -107,9 +107,6 @@ class Function(Callable): arg = self.args[idx] else: arg = self.many - if arg.lazy: - ret.append(param) - continue ev = evaluate(param, env, ns) expected_name = f"{arg.type_}" expected_type = env.get(expected_name) diff --git a/neb/std/fs.py b/neb/std/fs.py index d20cde9..144df0f 100644 --- a/neb/std/fs.py +++ b/neb/std/fs.py @@ -31,19 +31,6 @@ def interpretUnlink(symbol, args, env, ns): FS.register("unlink", Builtin("unlink", interpretUnlink, [Arg("filename", TypeEnum.STRING)], return_type=Type(":list"))) -def interpretWithWrite(symbol, args, env, ns): - target_file = args[0] - new_env = Environment(env) - target_path = Path(target_file.value).resolve() - ret = Literal([]) - with open(str(target_path), "w") as fil: - new_env.register("_file_", List([fil])) # TODO wrong! - for arg in args[1:]: - ret = evaluate(arg, new_env, ns) - return ret - -FS.register("with-write", Builtin("with-write", interpretWithWrite, [Arg("filename", TypeEnum.STRING)], Arg("exprs", TypeEnum.ANY, lazy=True))) - def interpretWrite(symbol, args, env, ns): string = args[0] handle = args[1] diff --git a/neb/structs.py b/neb/structs.py index c5707a4..88c4c6f 100644 --- a/neb/structs.py +++ b/neb/structs.py @@ -129,11 +129,10 @@ class List: # function things class Arg: - def __init__(self, name, type_, *, optional=False, lazy=False): + def __init__(self, name, type_, *, optional=False): self.name = name self.type_ = type_ self.optional = optional - self.lazy = lazy def __str__(self): return f"{self.name} {self.type_}" -- cgit v1.2.3 From 0a646ac3dacafd7c266a34fb9dcab40e6e9649c1 Mon Sep 17 00:00:00 2001 From: mryouse Date: Fri, 8 Jul 2022 23:40:10 +0000 Subject: (symbols) returns all symbols, not just those in current env --- neb/std/repl.py | 2 +- neb/structs.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'neb') diff --git a/neb/std/repl.py b/neb/std/repl.py index fbb0366..ccd48bd 100644 --- a/neb/std/repl.py +++ b/neb/std/repl.py @@ -12,7 +12,7 @@ def interpretHowTo(symbol, args, env, ns): REPL.register("howto", Builtin("howto", interpretHowTo, [Arg("symbol", TypeEnum.ANY)], return_type=Type(":list"))) def interpretSymbols(symbol, args, env, ns): - keys = [Symbol(k, -1) for k,v in sorted(env.environment.items())] + keys = [Symbol(k, -1) for k,v in sorted(env.get_all().items())] return List(keys) REPL.register("symbols", Builtin("symbols", interpretSymbols, [], return_type=Type(":list"))) diff --git a/neb/structs.py b/neb/structs.py index 88c4c6f..df7127f 100644 --- a/neb/structs.py +++ b/neb/structs.py @@ -179,6 +179,12 @@ class Environment: except: raise NebPanic(f"undefined symbol: '{key}") + def get_all(self): + if self.parent is None: + return self.environment + else: + return dict(self.parent.get_all(), **self.environment) + def __str__(self): out = "" for k, v in self.environment.items(): -- cgit v1.2.3 From a96a94ede913b87f6e5e7bba79591750268c95e9 Mon Sep 17 00:00:00 2001 From: mryouse Date: Fri, 8 Jul 2022 23:59:01 +0000 Subject: implement parse-neb --- neb/std/repl.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'neb') diff --git a/neb/std/repl.py b/neb/std/repl.py index ccd48bd..b888d1a 100644 --- a/neb/std/repl.py +++ b/neb/std/repl.py @@ -1,4 +1,5 @@ -from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, Function, evaluate, InterpretPanic, Callable, Macro +from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, Function, evaluate, InterpretPanic, Callable, Macro, lex, parse +from .core import interpretQuote from ..structs import * REPL = Environment() @@ -34,3 +35,8 @@ def interpretMacros(symbol, args, env, ns): return List(keys) REPL.register("macros", Builtin("macros", interpretMacros, [], return_type=Type(":list"))) + +def interpretParseNeb(symbol, args, env, ns): + return interpretQuote(None, [parse(lex(args[0].value))[0]], env, ns) + +REPL.register("parse-neb", Builtin("parse-neb", interpretParseNeb, [Arg("string", TypeEnum.STRING)], return_type=Type(":any"))) -- cgit v1.2.3 From 5f484ca29fa49584fb82d789cde1ac084dfef30e Mon Sep 17 00:00:00 2001 From: mryouse Date: Sat, 9 Jul 2022 00:14:36 +0000 Subject: rename 'macros' to 'syntax' --- neb/__init__.py | 6 +++--- neb/std/core.py | 40 ++++++++++++++++++++-------------------- neb/std/repl.py | 8 ++++---- 3 files changed, 27 insertions(+), 27 deletions(-) (limited to 'neb') diff --git a/neb/__init__.py b/neb/__init__.py index 4831019..71d06e5 100644 --- a/neb/__init__.py +++ b/neb/__init__.py @@ -74,12 +74,12 @@ class Callable: def call(self, expr, env): pass -class Macro(Callable): +class Special(Callable): def __init__(self, name, params, body, args=None, many=None): super().__init__(name, params, body, args, many) -class NebMacro(Macro): +class NebSyntax(Special): def __init__(self, name, callable_, args=None, many=None, return_type=None): super().__init__(name, None, callable_, args, many) @@ -87,7 +87,7 @@ class NebMacro(Macro): self.return_type = return_type def __str__(self): - return f"builtin function {self.name}" + return f"syntax function {self.name}" def call(self, expr, env, ns): self.arity_check(expr.args[0], expr.args[1:]) diff --git a/neb/std/core.py b/neb/std/core.py index a0f2cf6..cf0686b 100644 --- a/neb/std/core.py +++ b/neb/std/core.py @@ -1,4 +1,4 @@ -from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, evaluate, interpret, parse, lex, InterpretPanic, TypeWrap, Function, UserType, NebMacro +from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, evaluate, interpret, parse, lex, InterpretPanic, TypeWrap, Function, UserType, NebSyntax from ..structs import * from pathlib import Path @@ -18,7 +18,7 @@ def interpretIf(symbol, args, env, ns): cond = Arg("cond", TypeEnum.BOOL) t_branch = Arg("t-branch", TypeEnum.ANY) f_branch = Arg("f-branch", TypeEnum.ANY, optional=True) -CORE.register("if", NebMacro("if", interpretIf, [cond, t_branch, f_branch])) +CORE.register("if", NebSyntax("if", interpretIf, [cond, t_branch, f_branch])) def interpretDef(symbol, args, env, ns): if not isinstance(args[0], Symbol): @@ -30,7 +30,7 @@ def interpretDef(symbol, args, env, ns): def_name_arg = Arg("name", TypeEnum.ANY) def_val_arg = Arg("value", TypeEnum.ANY) -CORE.register("def", NebMacro("def", interpretDef, [def_name_arg, def_val_arg], return_type=Type(":list"))) +CORE.register("def", NebSyntax("def", interpretDef, [def_name_arg, def_val_arg], return_type=Type(":list"))) def interpretRedef(symbol, args, env, ns): if not isinstance(args[0], Symbol): @@ -43,7 +43,7 @@ def interpretRedef(symbol, args, env, ns): env.reregister(name, res) return List([]) -CORE.register("redef", NebMacro("redef", interpretRedef, [def_name_arg, def_val_arg], return_type=Type(":list"))) +CORE.register("redef", NebSyntax("redef", interpretRedef, [def_name_arg, def_val_arg], return_type=Type(":list"))) def interpretLambda(symbol, args, env, ns): new_args = args @@ -61,7 +61,7 @@ def interpretLambda(symbol, args, env, ns): lambda_args_arg = Arg("args", TypeEnum.ANY) lambda_body_arg = Arg("body", TypeEnum.ANY) -CORE.register("lambda", NebMacro("lambda", interpretLambda, [lambda_args_arg, lambda_body_arg], lambda_body_arg)) +CORE.register("lambda", NebSyntax("lambda", interpretLambda, [lambda_args_arg, lambda_body_arg], lambda_body_arg)) def interpretForCount(symbol, args, env, ns): num = evaluate(args[0], env, ns) @@ -79,7 +79,7 @@ def interpretForCount(symbol, args, env, ns): for_count_arg = Arg("count", TypeEnum.INT) for_body_arg = Arg("body", TypeEnum.ANY) -CORE.register("for-count", NebMacro("for-count", interpretForCount, [for_count_arg, for_body_arg], for_body_arg)) +CORE.register("for-count", NebSyntax("for-count", interpretForCount, [for_count_arg, for_body_arg], for_body_arg)) def interpretForEach(symbol, args, env, ns): coll = evaluate(args[0], env, ns) @@ -96,7 +96,7 @@ def interpretForEach(symbol, args, env, ns): return ret for_each_arg = Arg("list", TypeEnum.LIST) -CORE.register("for-each", NebMacro("for-each", interpretForEach, [for_each_arg, for_body_arg], for_body_arg)) +CORE.register("for-each", NebSyntax("for-each", interpretForEach, [for_each_arg, for_body_arg], for_body_arg)) def interpretBranch(symbol, args, env, ns): for arg in args: @@ -109,7 +109,7 @@ def interpretBranch(symbol, args, env, ns): return evaluate(arg.args[1], env, ns) return List([]) -CORE.register("branch", NebMacro("branch", interpretBranch, [for_body_arg], for_body_arg)) +CORE.register("branch", NebSyntax("branch", interpretBranch, [for_body_arg], for_body_arg)) def interpretFunc(symbol, args, env, ns): if not isinstance(args[0], Symbol): @@ -128,7 +128,7 @@ def interpretFunc(symbol, args, env, ns): env.register(name, func) return List([]) -CORE.register("func", NebMacro("func", interpretFunc, [def_name_arg, lambda_args_arg, lambda_body_arg], lambda_body_arg, Type(":list"))) +CORE.register("func", NebSyntax("func", interpretFunc, [def_name_arg, lambda_args_arg, lambda_body_arg], lambda_body_arg, Type(":list"))) def interpretBlock(symbol, args, env, ns): new_env = Environment(env) @@ -138,7 +138,7 @@ def interpretBlock(symbol, args, env, ns): return ret block_arg = Arg("expr", TypeEnum.ANY) -CORE.register("block", NebMacro("block", interpretBlock, [block_arg], block_arg)) +CORE.register("block", NebSyntax("block", interpretBlock, [block_arg], block_arg)) def interpretWhile(symbol, args, env, ns): new_env = Environment(env) @@ -154,7 +154,7 @@ def interpretWhile(symbol, args, env, ns): ret = evaluate(arg, new_env, ns) return ret -CORE.register("while", NebMacro("while", interpretWhile, [Arg("cond", TypeEnum.BOOL)], Arg("expr", TypeEnum.ANY))) +CORE.register("while", NebSyntax("while", interpretWhile, [Arg("cond", TypeEnum.BOOL)], Arg("expr", TypeEnum.ANY))) # NOTE this doesn't technically need to be a macro def interpretUse(symbol, args, env, ns): @@ -169,7 +169,7 @@ def interpretUse(symbol, args, env, ns): interpret(parse(lex(data)), env, ns) return List([]) -CORE.register("use", NebMacro("use", interpretUse, [Arg("filename", TypeEnum.STRING)], return_type=Type(":list"))) +CORE.register("use", NebSyntax("use", interpretUse, [Arg("filename", TypeEnum.STRING)], return_type=Type(":list"))) # NOTE this doesn't technically need to be a macro def interpretAssert(symbol, args, env, ns): @@ -180,7 +180,7 @@ def interpretAssert(symbol, args, env, ns): raise InterpretPanic(symbol, "assertion failed") return List([]) -CORE.register("assert", NebMacro("assert", interpretAssert, [Arg("cond", TypeEnum.BOOL)], return_type=Type(":list"))) +CORE.register("assert", NebSyntax("assert", interpretAssert, [Arg("cond", TypeEnum.BOOL)], return_type=Type(":list"))) def interpretUseAs(symbol, args, env, ns): target = evaluate(args[0], env, ns) @@ -197,20 +197,20 @@ def interpretUseAs(symbol, args, env, ns): interpret(parse(lex(data)), env, new_ns) return List([]) -CORE.register("use-as", NebMacro("use-as", interpretUseAs, [Arg("filename", TypeEnum.STRING), Arg("namespace", TypeEnum.ANY)], return_type=Type(":list"))) +CORE.register("use-as", NebSyntax("use-as", interpretUseAs, [Arg("filename", TypeEnum.STRING), Arg("namespace", TypeEnum.ANY)], return_type=Type(":list"))) def interpretQuote(symbol, args, env, ns): return args[0] quote_arg = Arg("arg", TypeEnum.ANY) -CORE.register("quote", NebMacro("quote", interpretQuote, [quote_arg])) +CORE.register("quote", NebSyntax("quote", interpretQuote, [quote_arg])) def interpretEval(symbol, args, env, ns): ev = evaluate(args[0], env, ns) # TODO why do i have to evaluate twice? return evaluate(ev, env, ns) eval_arg = Arg("arg", TypeEnum.ANY) -CORE.register("eval", NebMacro("eval", interpretEval, [eval_arg])) +CORE.register("eval", NebSyntax("eval", interpretEval, [eval_arg])) def interpretType(symbol, args, env, ns): # (type typename parent func) @@ -239,7 +239,7 @@ def interpretType(symbol, args, env, ns): type_name_arg = Arg("name", TypeEnum.ANY) type_parent_arg = Arg("name", TypeEnum.ANY) type_func_arg = Arg("func", TypeEnum.ANY) -CORE.register("type", NebMacro("type", interpretType, [type_name_arg, type_parent_arg, type_func_arg])) +CORE.register("type", NebSyntax("type", interpretType, [type_name_arg, type_parent_arg, type_func_arg])) def interpretOr(symbol, args, env, ns): # or returns true for the first expression that returns true @@ -252,7 +252,7 @@ def interpretOr(symbol, args, env, ns): return Bool(False) or_arg = Arg("arg", TypeEnum.BOOL) -CORE.register("or", NebMacro("or", interpretOr, [or_arg, or_arg], or_arg, Type(":bool"))) +CORE.register("or", NebSyntax("or", interpretOr, [or_arg, or_arg], or_arg, Type(":bool"))) def interpretAnd(symbol, args, env, ns): # and returns false for the first expression that returns false @@ -264,7 +264,7 @@ def interpretAnd(symbol, args, env, ns): return ev return Bool(True) -CORE.register("and", Builtin("and", interpretAnd, [or_arg, or_arg], or_arg, Type(":bool"))) +CORE.register("and", NebSyntax("and", interpretAnd, [or_arg, or_arg], or_arg, Type(":bool"))) def interpretBench(symbol, args, env, ns): before = datetime.now() @@ -273,4 +273,4 @@ def interpretBench(symbol, args, env, ns): print(f"bench [{symbol.line}]: {args[0]} => {after - before}") return ret -CORE.register("bench", NebMacro("bench", interpretBench, [Arg("command", TypeEnum.ANY)], return_type=Type(":any"))) +CORE.register("bench", NebSyntax("bench", interpretBench, [Arg("command", TypeEnum.ANY)], return_type=Type(":any"))) diff --git a/neb/std/repl.py b/neb/std/repl.py index b888d1a..e8f2857 100644 --- a/neb/std/repl.py +++ b/neb/std/repl.py @@ -1,4 +1,4 @@ -from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, Function, evaluate, InterpretPanic, Callable, Macro, lex, parse +from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, Function, evaluate, InterpretPanic, Callable, NebSyntax, lex, parse from .core import interpretQuote from ..structs import * @@ -30,11 +30,11 @@ def interpretUserSymbols(symbol, args, env, ns): REPL.register("user-symbols", Builtin("user-symbols", interpretUserSymbols, [], return_type=Type(":list"))) -def interpretMacros(symbol, args, env, ns): - keys = [Symbol(k, -1) for k,v in sorted(env.environment.items()) if isinstance(v, Macro)] +def interpretSyntax(symbol, args, env, ns): + keys = [Symbol(k, -1) for k,v in sorted(env.environment.items()) if isinstance(v, NebSyntax)] return List(keys) -REPL.register("macros", Builtin("macros", interpretMacros, [], return_type=Type(":list"))) +REPL.register("syntax", Builtin("syntax", interpretSyntax, [], return_type=Type(":list"))) def interpretParseNeb(symbol, args, env, ns): return interpretQuote(None, [parse(lex(args[0].value))[0]], env, ns) -- cgit v1.2.3 From f6815e804fb35621e84031ef880d183140b7a523 Mon Sep 17 00:00:00 2001 From: mryouse Date: Sat, 9 Jul 2022 01:59:47 +0000 Subject: implement 'try' --- neb/std/core.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'neb') diff --git a/neb/std/core.py b/neb/std/core.py index cf0686b..9e2e743 100644 --- a/neb/std/core.py +++ b/neb/std/core.py @@ -274,3 +274,13 @@ def interpretBench(symbol, args, env, ns): return ret CORE.register("bench", NebSyntax("bench", interpretBench, [Arg("command", TypeEnum.ANY)], return_type=Type(":any"))) + +def interpretTry(symbol, args, env, ns): + try: + return evaluate(args[0], env, ns) + except NebPanic as e: + new_env = Environment(env) + new_env.register("_panic_", String(f"{e}")) + return evaluate(args[1], new_env, ns) + +CORE.register("try", NebSyntax("try", interpretTry, [Arg("expr", TypeEnum.ANY), Arg("except", TypeEnum.ANY)], return_type=Type(":any"))) -- cgit v1.2.3 From 55259a331bcdf9fddcd96aac18eca8f7d669dd30 Mon Sep 17 00:00:00 2001 From: mryouse Date: Sat, 9 Jul 2022 02:18:23 +0000 Subject: amend all meta functions to include everything (not just locals) --- neb/std/repl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'neb') diff --git a/neb/std/repl.py b/neb/std/repl.py index e8f2857..a404cad 100644 --- a/neb/std/repl.py +++ b/neb/std/repl.py @@ -19,19 +19,19 @@ def interpretSymbols(symbol, args, env, ns): REPL.register("symbols", Builtin("symbols", interpretSymbols, [], return_type=Type(":list"))) def interpretFuncs(symbol, args, env, ns): - keys = [Symbol(k, -1) for k,v in sorted(env.environment.items()) if isinstance(v, Function)] + keys = [Symbol(k, -1) for k,v in sorted(env.get_all().items()) if isinstance(v, Function)] return List(keys) REPL.register("funcs", Builtin("funcs", interpretFuncs, [], return_type=Type(":list"))) def interpretUserSymbols(symbol, args, env, ns): - keys = [Symbol(k, -1) for k,v in env.environment.items() if isinstance(v, UserFunction) or isinstance(v, Literal)] + keys = [Symbol(k, -1) for k,v in env.get_all().items() if isinstance(v, UserFunction) or isinstance(v, Literal)] return List(keys) REPL.register("user-symbols", Builtin("user-symbols", interpretUserSymbols, [], return_type=Type(":list"))) def interpretSyntax(symbol, args, env, ns): - keys = [Symbol(k, -1) for k,v in sorted(env.environment.items()) if isinstance(v, NebSyntax)] + keys = [Symbol(k, -1) for k,v in sorted(env.get_all().items()) if isinstance(v, NebSyntax)] return List(keys) REPL.register("syntax", Builtin("syntax", interpretSyntax, [], return_type=Type(":list"))) -- cgit v1.2.3 From 5d16387be0437fe711f51933b9b10674da18f116 Mon Sep 17 00:00:00 2001 From: mryouse Date: Sat, 9 Jul 2022 02:19:06 +0000 Subject: implement 'user-funcs' --- neb/std/repl.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'neb') diff --git a/neb/std/repl.py b/neb/std/repl.py index a404cad..6b6be83 100644 --- a/neb/std/repl.py +++ b/neb/std/repl.py @@ -30,6 +30,12 @@ def interpretUserSymbols(symbol, args, env, ns): REPL.register("user-symbols", Builtin("user-symbols", interpretUserSymbols, [], return_type=Type(":list"))) +def interpretUserFuncs(symbol, args, env, ns): + keys = [Symbol(k, -1) for k,v in env.get_all().items() if isinstance(v, UserFunction)] + return List(keys) + +REPL.register("user-funcs", Builtin("user-funcs", interpretUserFuncs, [], return_type=Type(":list"))) + def interpretSyntax(symbol, args, env, ns): keys = [Symbol(k, -1) for k,v in sorted(env.get_all().items()) if isinstance(v, NebSyntax)] return List(keys) -- cgit v1.2.3