aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormryouse2022-06-22 00:59:28 +0000
committermryouse2022-06-22 00:59:28 +0000
commitf126db2e1d476d5f7457594bcb318a5cb5f0c528 (patch)
treee23fc55a7d864cc47685c6199ce1775c265f1a85
parentf2c9f51359f7f2c7a1b968bc72ca911b7bb2b2d0 (diff)
give builtin functions proper names
-rw-r--r--neb/__init__.py12
-rw-r--r--neb/std/boolean.py10
-rw-r--r--neb/std/core.py32
-rw-r--r--neb/std/fs.py14
-rw-r--r--neb/std/functools.py8
-rw-r--r--neb/std/lists.py44
-rw-r--r--neb/std/math.py20
-rw-r--r--neb/std/repl.py8
-rw-r--r--neb/std/strings.py18
-rw-r--r--neb/std/sys.py10
-rw-r--r--neb/std/term.py8
-rw-r--r--neb/std/types.py20
-rw-r--r--neb/structs.py7
13 files changed, 113 insertions, 98 deletions
diff --git a/neb/__init__.py b/neb/__init__.py
index 583bef8..a492df8 100644
--- a/neb/__init__.py
+++ b/neb/__init__.py
@@ -49,12 +49,8 @@ class Function:
if name is None:
name = self.name
out = [f"({name}"]
- if self.args is not None:
- for arg in self.args:
- out.append(f"{arg}")
- if self.many is not None:
- out.append(f"{self.many}")
- return " ".join(out) + ")"
+ out.append(string_args(self.args, self.many))
+ return " ".join(out).strip() + ")"
def arity_check(self, symbol, params):
min_arity = len([a for a in self.args if not a.optional])
@@ -95,8 +91,8 @@ class Function:
class Builtin(Function):
- def __init__(self, callable_, args=None, many=None):
- super().__init__("<builtin>", None, callable_, args, many)
+ def __init__(self, name, callable_, args=None, many=None):
+ super().__init__(name, None, callable_, args, many)
def __str__(self):
return f"builtin function {self.name}"
diff --git a/neb/std/boolean.py b/neb/std/boolean.py
index b851d7d..1d99737 100644
--- a/neb/std/boolean.py
+++ b/neb/std/boolean.py
@@ -1,4 +1,4 @@
-from .. import TypeEnum, Environment, Arg, Builtin, evaluate
+from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic
from ..structs import *
BOOLEAN = Environment()
@@ -14,7 +14,7 @@ def interpretOr(symbol, args, env, ns):
return Bool(False)
or_arg = Arg("arg", TypeEnum.BOOL, lazy=True)
-BOOLEAN.register("or", Builtin(interpretOr, [or_arg, or_arg], or_arg))
+BOOLEAN.register("or", Builtin("or", interpretOr, [or_arg, or_arg], or_arg))
def interpretAnd(symbol, args, env, ns):
# and returns false for the first expression that returns false
@@ -26,7 +26,7 @@ def interpretAnd(symbol, args, env, ns):
return ev
return Bool(True)
-BOOLEAN.register("and", Builtin(interpretAnd, [or_arg, or_arg], or_arg))
+BOOLEAN.register("and", Builtin("and", interpretAnd, [or_arg, or_arg], or_arg))
def interpretEq(symbol, args, env, ns):
# NOTE this currently only works for literals
@@ -37,11 +37,11 @@ def interpretEq(symbol, args, env, ns):
return Bool(False)
eq_arg = Arg("value", TypeEnum.LITERAL)
-BOOLEAN.register("eq?", Builtin(interpretEq, [eq_arg, eq_arg]))
+BOOLEAN.register("eq?", Builtin("eq?", interpretEq, [eq_arg, eq_arg]))
def interpretNot(symbol, args, env, ns):
return Bool(not args[0].value)
not_arg = Arg("not", TypeEnum.BOOL)
-BOOLEAN.register("not", Builtin(interpretNot, [not_arg]))
+BOOLEAN.register("not", Builtin("not", interpretNot, [not_arg]))
diff --git a/neb/std/core.py b/neb/std/core.py
index d481daa..171b96b 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
+from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, evaluate, interpret, parse, lex, InterpretPanic
from ..structs import *
from pathlib import Path
@@ -14,7 +14,7 @@ def interpretIf(symbol, args, env, ns):
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(interpretIf, [cond, t_branch, f_branch]))
+CORE.register("if", Builtin("if", interpretIf, [cond, t_branch, f_branch]))
def interpretDef(symbol, args, env, ns):
@@ -30,7 +30,7 @@ def interpretDef(symbol, args, env, ns):
def_name_arg = Arg("name", TypeEnum.ANY, lazy=True)
def_val_arg = Arg("value", TypeEnum.ANY)
-CORE.register("def", Builtin(interpretDef, [def_name_arg, def_val_arg]))
+CORE.register("def", Builtin("def", interpretDef, [def_name_arg, def_val_arg]))
def interpretRedef(symbol, args, env, ns):
if not isinstance(args[0], Symbol):
@@ -42,7 +42,7 @@ def interpretRedef(symbol, args, env, ns):
env.reregister(name, args[1])
return List([])
-CORE.register("redef", Builtin(interpretRedef, [def_name_arg, def_val_arg]))
+CORE.register("redef", Builtin("redef", interpretRedef, [def_name_arg, def_val_arg]))
def interpretLambda(symbol, args, env, ns):
if len(args[0].args) != 0:
@@ -53,7 +53,7 @@ def interpretLambda(symbol, args, env, ns):
lambda_args_arg = Arg("args", TypeEnum.ANY, lazy=True)
lambda_body_arg = Arg("body", TypeEnum.ANY, lazy=True)
-CORE.register("lambda", Builtin(interpretLambda, [lambda_args_arg, lambda_body_arg], lambda_body_arg))
+CORE.register("lambda", Builtin("lambda", interpretLambda, [lambda_args_arg, lambda_body_arg], lambda_body_arg))
def interpretForCount(symbol, args, env, ns):
new_env = Environment(env)
@@ -68,7 +68,7 @@ def interpretForCount(symbol, args, env, ns):
for_count_arg = Arg("count", TypeEnum.INT)
for_body_arg = Arg("body", TypeEnum.ANY, lazy=True)
-CORE.register("for-count", Builtin(interpretForCount, [for_count_arg, for_body_arg], for_body_arg))
+CORE.register("for-count", Builtin("for-count", interpretForCount, [for_count_arg, for_body_arg], for_body_arg))
def interpretForEach(symbol, args, env, ns):
new_env = Environment(env)
@@ -82,7 +82,7 @@ def interpretForEach(symbol, args, env, ns):
return ret
for_each_arg = Arg("list", TypeEnum.LIST)
-CORE.register("for-each", Builtin(interpretForEach, [for_each_arg, for_body_arg], for_body_arg))
+CORE.register("for-each", Builtin("for-each", interpretForEach, [for_each_arg, for_body_arg], for_body_arg))
def interpretBranch(symbol, args, env, ns):
for arg in args:
@@ -95,7 +95,7 @@ def interpretBranch(symbol, args, env, ns):
return evaluate(arg.args[1], env, ns)
return List([])
-CORE.register("branch", Builtin(interpretBranch, [for_body_arg], for_body_arg))
+CORE.register("branch", Builtin("branch", interpretBranch, [for_body_arg], for_body_arg))
def interpretFunc(symbol, args, env, ns):
if not isinstance(args[0], Symbol):
@@ -114,7 +114,7 @@ def interpretFunc(symbol, args, env, ns):
env.register(name, func)
return List([])
-CORE.register("func", Builtin(interpretFunc, [def_name_arg, lambda_args_arg, lambda_body_arg], lambda_body_arg))
+CORE.register("func", Builtin("func", interpretFunc, [def_name_arg, lambda_args_arg, lambda_body_arg], lambda_body_arg))
def interpretBlock(symbol, args, env, ns):
ret = List([])
@@ -123,7 +123,7 @@ def interpretBlock(symbol, args, env, ns):
return ret
block_arg = Arg("expr", TypeEnum.ANY, lazy=True)
-CORE.register("block", Builtin(interpretBlock, [block_arg], block_arg))
+CORE.register("block", Builtin("block", interpretBlock, [block_arg], block_arg))
def interpretWhile(symbol, args, env, ns):
cond = args[0]
@@ -138,7 +138,7 @@ def interpretWhile(symbol, args, env, ns):
ret = evaluate(arg, env, ns)
return ret
-CORE.register("while", Builtin(interpretWhile, [Arg("cond", TypeEnum.BOOL, lazy=True)], Arg("expr", TypeEnum.ANY, lazy=True)))
+CORE.register("while", Builtin("while", interpretWhile, [Arg("cond", TypeEnum.BOOL, lazy=True)], Arg("expr", TypeEnum.ANY, lazy=True)))
def interpretUse(symbol, args, env, ns):
target_file_name = args[0].value
@@ -150,14 +150,14 @@ def interpretUse(symbol, args, env, ns):
interpret(parse(lex(data)), env, ns)
return List([])
-CORE.register("use", Builtin(interpretUse, [Arg("filename", TypeEnum.STRING)]))
+CORE.register("use", Builtin("use", interpretUse, [Arg("filename", TypeEnum.STRING)]))
def interpretAssert(symbol, args, env, ns):
if args[0].value != True:
raise InterpretPanic(symbol, "assertion failed")
return List([])
-CORE.register("assert", Builtin(interpretAssert, [Arg("cond", TypeEnum.BOOL)]))
+CORE.register("assert", Builtin("assert", interpretAssert, [Arg("cond", TypeEnum.BOOL)]))
def interpretUseAs(symbol, args, env, ns):
target_file_name = args[0].value
@@ -169,16 +169,16 @@ def interpretUseAs(symbol, args, env, ns):
interpret(parse(lex(data)), ns=args[1].name)
return List([])
-CORE.register("use-as", Builtin(interpretUseAs, [Arg("filename", TypeEnum.STRING), Arg("namespace", TypeEnum.ANY, lazy=True)]))
+CORE.register("use-as", Builtin("use-as", interpretUseAs, [Arg("filename", TypeEnum.STRING), Arg("namespace", TypeEnum.ANY, lazy=True)]))
def interpretQuote(symbol, args, env, ns):
return args[0]
quote_arg = Arg("arg", TypeEnum.ANY, lazy=True)
-CORE.register("quote", Builtin(interpretQuote, [quote_arg]))
+CORE.register("quote", Builtin("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?
eval_arg = Arg("arg", TypeEnum.ANY)
-CORE.register("eval", Builtin(interpretEval, [eval_arg]))
+CORE.register("eval", Builtin("eval", interpretEval, [eval_arg]))
diff --git a/neb/std/fs.py b/neb/std/fs.py
index 2265719..5983e20 100644
--- a/neb/std/fs.py
+++ b/neb/std/fs.py
@@ -1,4 +1,4 @@
-from .. import TypeEnum, Environment, Arg, Builtin, evaluate
+from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic
from ..structs import *
from pathlib import Path
from glob import glob
@@ -8,13 +8,13 @@ FS = Environment()
def interpretExists(symbol, args, env, ns):
return Bool(Path(args[0].value).resolve().exists())
-FS.register("exists?", Builtin(interpretExists, [Arg("filename", TypeEnum.STRING)]))
+FS.register("exists?", Builtin("exists?", interpretExists, [Arg("filename", TypeEnum.STRING)]))
def interpretGlob(symbol, args, env, ns):
items = glob(args[0].value)
return List([String(item) for item in items])
-FS.register("glob", Builtin(interpretGlob, [Arg("regex", TypeEnum.STRING)]))
+FS.register("glob", Builtin("glob", interpretGlob, [Arg("regex", TypeEnum.STRING)]))
def interpretUnlink(symbol, args, env, ns):
target_path = Path(args[0].value).resolve()
@@ -23,7 +23,7 @@ def interpretUnlink(symbol, args, env, ns):
target_path.unlink()
return List([])
-FS.register("unlink", Builtin(interpretUnlink, [Arg("filename", TypeEnum.STRING)]))
+FS.register("unlink", Builtin("unlink", interpretUnlink, [Arg("filename", TypeEnum.STRING)]))
def interpretWithWrite(symbol, args, env, ns):
target_file = args[0]
@@ -36,7 +36,7 @@ def interpretWithWrite(symbol, args, env, ns):
ret = evaluate(arg, new_env, ns)
return ret
-FS.register("with-write", Builtin(interpretWithWrite, [Arg("filename", TypeEnum.STRING)], Arg("exprs", TypeEnum.ANY, lazy=True)))
+FS.register("with-write", Builtin("with-write", interpretWithWrite, [Arg("filename", TypeEnum.STRING)], Arg("exprs", TypeEnum.ANY, lazy=True)))
def interpretWrite(symbol, args, env, ns):
# write :string :filehandle
@@ -45,7 +45,7 @@ def interpretWrite(symbol, args, env, ns):
handle.args[0].write(line.value) # TODO wrong! how do we evaluate a handle?
return Literal([])
-FS.register("write", Builtin(interpretWrite, [Arg("string", TypeEnum.STRING), Arg("filename", TypeEnum.LIST)]))
+FS.register("write", Builtin("write", interpretWrite, [Arg("string", TypeEnum.STRING), Arg("filename", TypeEnum.LIST)]))
def interpretReadLines(symbol, args, env, ns):
target_file_name = args[0].value
@@ -57,5 +57,5 @@ def interpretReadLines(symbol, args, env, ns):
out = List([String(d) for d in data]) # all lines are strings
return out
-FS.register("read-lines", Builtin(interpretReadLines, [Arg("filename", TypeEnum.STRING)]))
+FS.register("read-lines", Builtin("read-lines", interpretReadLines, [Arg("filename", TypeEnum.STRING)]))
diff --git a/neb/std/functools.py b/neb/std/functools.py
index 59f4a2a..83475b9 100644
--- a/neb/std/functools.py
+++ b/neb/std/functools.py
@@ -1,4 +1,4 @@
-from .. import TypeEnum, Environment, Arg, Builtin, Function, evaluate
+from .. import TypeEnum, Environment, Arg, Builtin, Function, evaluate, InterpretPanic
from ..structs import *
FUNCTOOLS = Environment()
@@ -17,7 +17,7 @@ def interpretFilter(symbol, args, env, ns):
out.append(arg)
return List(out)
-FUNCTOOLS.register("filter", Builtin(interpretFilter, [Arg("func", TypeEnum.ANY), Arg("list", TypeEnum.LIST)]))
+FUNCTOOLS.register("filter", Builtin("filter", interpretFilter, [Arg("func", TypeEnum.ANY), Arg("list", TypeEnum.LIST)]))
def interpretMap(symbol, args, env, ns):
func = args[0]
@@ -32,7 +32,7 @@ def interpretMap(symbol, args, env, ns):
out.append(ev)
return List(out)
-FUNCTOOLS.register("map", Builtin(interpretMap, [Arg("func", TypeEnum.ANY), Arg("list", TypeEnum.LIST)]))
+FUNCTOOLS.register("map", Builtin("map", interpretMap, [Arg("func", TypeEnum.ANY), Arg("list", TypeEnum.LIST)]))
def interpretApply(symbol, args, env, ns):
# TODO: to support lambdas, we can't assume the func is defined
@@ -42,5 +42,5 @@ def interpretApply(symbol, args, env, ns):
new_lst = List([func] + args[1].args)
return evaluate(new_lst, env, ns)
-FUNCTOOLS.register("apply", Builtin(interpretApply, [Arg("func", TypeEnum.ANY, lazy=True), Arg("list", TypeEnum.LIST)]))
+FUNCTOOLS.register("apply", Builtin("apply", interpretApply, [Arg("func", TypeEnum.ANY, lazy=True), Arg("list", TypeEnum.LIST)]))
diff --git a/neb/std/lists.py b/neb/std/lists.py
index d5c18c2..5aaab53 100644
--- a/neb/std/lists.py
+++ b/neb/std/lists.py
@@ -1,4 +1,4 @@
-from .. import TypeEnum, Environment, Arg, Builtin, evaluate
+from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic
from ..structs import *
import random
@@ -7,39 +7,39 @@ LISTS = Environment()
def interpretListLength(symbol, args, env, ns):
return Int(len(args[0].args))
-LISTS.register("list-length", Builtin(interpretListLength, [Arg("arg", TypeEnum.LIST)]))
+LISTS.register("list-length", Builtin("list-length", interpretListLength, [Arg("arg", TypeEnum.LIST)]))
def interpretFirst(symbol, args, env, ns):
if len(args[0].args) == 0:
raise InterpretPanic(symbol, "list is empty")
return evaluate(args[0].args[0], env, ns)
-LISTS.register("first", Builtin(interpretFirst, [Arg("arg", TypeEnum.LIST, )]))
+LISTS.register("first", Builtin("first", interpretFirst, [Arg("arg", TypeEnum.LIST, )]))
def interpretRest(symbol, args, env, ns):
# TODO do we know it's not evaluated?
return List(args[0].args[1:]) # we don't evaluate the remainder of the list
-LISTS.register("rest", Builtin(interpretRest, [Arg("arg", TypeEnum.LIST)]))
+LISTS.register("rest", Builtin("rest", interpretRest, [Arg("arg", TypeEnum.LIST)]))
def interpretListReverse(symbol, args, env, ns):
new_args = args[0].args[:] # make a copy of the args
new_args.reverse()
return List(new_args)
-LISTS.register("list-reverse", Builtin(interpretListReverse, [Arg("list", TypeEnum.LIST)]))
+LISTS.register("list-reverse", Builtin("list-reverse", interpretListReverse, [Arg("list", TypeEnum.LIST)]))
def interpretEmpty(symbol, args, env, ns):
return Bool(len(args[0].args) == 0)
-LISTS.register("empty?", Builtin(interpretEmpty, [Arg("list", TypeEnum.LIST)]))
+LISTS.register("empty?", Builtin("empty?", interpretEmpty, [Arg("list", TypeEnum.LIST)]))
def interpretShuf(symbol, args, env, ns):
items = args[0].args[:]
random.shuffle(items)
return List(items)
-LISTS.register("shuf", Builtin(interpretShuf, [Arg("list", TypeEnum.LIST)]))
+LISTS.register("shuf", Builtin("shuf", interpretShuf, [Arg("list", TypeEnum.LIST)]))
def interpretIn(symbol, args, env, ns):
target = args[0]
@@ -51,14 +51,14 @@ def interpretIn(symbol, args, env, ns):
in_target_arg = Arg("target", TypeEnum.LITERAL)
in_list_arg = Arg("list", TypeEnum.LIST)
-LISTS.register("in?", Builtin(interpretIn, [in_target_arg, in_list_arg]))
+LISTS.register("in?", Builtin("in?", interpretIn, [in_target_arg, in_list_arg]))
def interpretLast(symbol, args, env, ns):
if len(args[0].args) == 0:
raise InterpretPanic("List is empty")
return evaluate(args[0].args[-1], env, ns)
-LISTS.register("last", Builtin(interpretLast, [Arg("list", TypeEnum.LIST)]))
+LISTS.register("last", Builtin("last", interpretLast, [Arg("list", TypeEnum.LIST)]))
def interpretSlice(symbol, args, env, ns):
lst = args[0]
@@ -72,7 +72,7 @@ def interpretSlice(symbol, args, env, ns):
slice_list_arg = Arg("list", TypeEnum.LIST)
slice_idx_arg = Arg("idx", TypeEnum.INT)
slice_length_arg = Arg("length", TypeEnum.INT, optional=True)
-LISTS.register("slice", Builtin(interpretSlice, [slice_list_arg, slice_idx_arg, slice_length_arg]))
+LISTS.register("slice", Builtin("slice", interpretSlice, [slice_list_arg, slice_idx_arg, slice_length_arg]))
def interpretAppend(symbol, args, env, ns):
lst = args[0]
@@ -80,7 +80,7 @@ def interpretAppend(symbol, args, env, ns):
items = lst.args[:]
return List(items + [val])
-LISTS.register("append", Builtin(interpretAppend, [Arg("list", TypeEnum.LIST), Arg("item", TypeEnum.ANY)]))
+LISTS.register("append", Builtin("append", interpretAppend, [Arg("list", TypeEnum.LIST), Arg("item", TypeEnum.ANY)]))
# TODO: this is actually for records/structs/whatever they're called
def interpretRemove(symbol, args, env, ns):
@@ -92,7 +92,7 @@ def interpretRemove(symbol, args, env, ns):
out.append(arg)
return List(out)
-LISTS.register("remove", Builtin(interpretRemove, [Arg("list", TypeEnum.LIST), Arg("key", TypeEnum.ANY)]))
+LISTS.register("remove", Builtin("remove", interpretRemove, [Arg("list", TypeEnum.LIST), Arg("key", TypeEnum.ANY)]))
def interpretZip(symbol, args, env, ns):
z1 = args[0]
@@ -107,10 +107,26 @@ def interpretZip(symbol, args, env, ns):
return List(out)
zip_arg = Arg("list", TypeEnum.LIST)
-LISTS.register("zip", Builtin(interpretZip, [zip_arg, zip_arg]))
+LISTS.register("zip", Builtin("zip", interpretZip, [zip_arg, zip_arg]))
def interpretList(symbol, args, env, ns):
return List(args)
-LISTS.register("list", Builtin(interpretList, [], Arg("item", TypeEnum.ANY)))
+LISTS.register("list", Builtin("list", interpretList, [], Arg("item", TypeEnum.ANY)))
+def interpretSortNumbers(symbol, args, env, ns):
+ items = []
+ for arg in args[0].args:
+ if not isinstance(arg, Int) and not isinstance(arg, Float):
+ raise InterpretPanic(symbol, "requires all :numbers", arg)
+ items.append(arg.value)
+ items.sort()
+ out = []
+ for item in items:
+ if isinstance(item, int):
+ out.append(Int(item))
+ else:
+ out.append(Float(item))
+ return List(out)
+
+LISTS.register("sort-numbers", Builtin("sort-numbers", interpretSortNumbers, [Arg("list", TypeEnum.LIST)]))
diff --git a/neb/std/math.py b/neb/std/math.py
index 85d4f55..66d153e 100644
--- a/neb/std/math.py
+++ b/neb/std/math.py
@@ -1,4 +1,4 @@
-from .. import TypeEnum, Environment, Arg, Builtin, evaluate
+from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic
from ..structs import *
import math
@@ -8,23 +8,23 @@ def interpretLessThanEqual(symbol, args, env, ns):
return Bool(args[0].value <= args[1].value)
compare_arg = Arg("num", TypeEnum.NUMBER)
-MATH.register("<=", Builtin(interpretLessThanEqual, [compare_arg, compare_arg]))
+MATH.register("<=", Builtin("<=", interpretLessThanEqual, [compare_arg, compare_arg]))
def interpretGreaterThan(symbol, args, env, ns):
return Bool(args[0].value > args[1].value)
compare_arg = Arg("num", TypeEnum.NUMBER)
-MATH.register(">", Builtin(interpretGreaterThan, [compare_arg, compare_arg]))
+MATH.register(">", Builtin(">", interpretGreaterThan, [compare_arg, compare_arg]))
def interpretGreaterThanEqual(symbol, args, env, ns):
return Bool(args[0].value >= args[1].value)
-MATH.register(">=", Builtin(interpretGreaterThanEqual, [compare_arg, compare_arg]))
+MATH.register(">=", Builtin(">=", interpretGreaterThanEqual, [compare_arg, compare_arg]))
def interpretLessThan(symbol, args, env, ns):
return Bool(args[0].value < args[1].value)
-MATH.register("<", Builtin(interpretLessThan, [compare_arg, compare_arg]))
+MATH.register("<", Builtin("<", interpretLessThan, [compare_arg, compare_arg]))
def interpretAddition(symbol, args, env, ns):
res = 0
@@ -36,7 +36,7 @@ def interpretAddition(symbol, args, env, ns):
return Int(res)
term_arg = Arg("term", TypeEnum.NUMBER)
-MATH.register("+", Builtin(interpretAddition, [term_arg], term_arg))
+MATH.register("+", Builtin("+", interpretAddition, [term_arg], term_arg))
def interpretSubtraction(symbol, args, env, ns):
if len(args) == 1:
@@ -50,7 +50,7 @@ def interpretSubtraction(symbol, args, env, ns):
else:
return Int(res)
-MATH.register("-", Builtin(interpretSubtraction, [term_arg], term_arg))
+MATH.register("-", Builtin("-", interpretSubtraction, [term_arg], term_arg))
def interpretMultiplication(symbol, args, env, ns):
res = args[0].value
@@ -62,7 +62,7 @@ def interpretMultiplication(symbol, args, env, ns):
return Int(res)
factor_arg = Arg("factor", TypeEnum.NUMBER)
-MATH.register("*", Builtin(interpretMultiplication, [factor_arg, factor_arg], factor_arg))
+MATH.register("*", Builtin("*", interpretMultiplication, [factor_arg, factor_arg], factor_arg))
def interpretDivision(symbol, args, env, ns):
ret = args[0].value / args[1].value
@@ -71,9 +71,9 @@ def interpretDivision(symbol, args, env, ns):
else:
return Float(ret)
-MATH.register("/", Builtin(interpretDivision, [factor_arg, factor_arg]))
+MATH.register("/", Builtin("/", interpretDivision, [factor_arg, factor_arg]))
def interpretFloor(symbol, args, env, ns):
return Int(math.floor(args[0].value))
-MATH.register("floor", Builtin(interpretFloor, [Arg("floor", TypeEnum.NUMBER)]))
+MATH.register("floor", Builtin("floor", interpretFloor, [Arg("floor", TypeEnum.NUMBER)]))
diff --git a/neb/std/repl.py b/neb/std/repl.py
index 0bf1dfd..39aba3b 100644
--- a/neb/std/repl.py
+++ b/neb/std/repl.py
@@ -1,4 +1,4 @@
-from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, Function, evaluate
+from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, Function, evaluate, InterpretPanic
from ..structs import *
REPL = Environment()
@@ -9,16 +9,16 @@ def interpretHowTo(symbol, args, env, ns):
print(args[0].describe())
return List([])
-REPL.register("howto", Builtin(interpretHowTo, [Arg("symbol", TypeEnum.ANY)]))
+REPL.register("howto", Builtin("howto", interpretHowTo, [Arg("symbol", TypeEnum.ANY)]))
def interpretSymbols(symbol, args, env, ns):
keys = [Symbol(k, -1) for k,v in env.environment.items()]
return List(keys)
-REPL.register("symbols", Builtin(interpretSymbols, []))
+REPL.register("symbols", Builtin("symbols", interpretSymbols, []))
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)]
return List(keys)
-REPL.register("user-symbols", Builtin(interpretUserSymbols, []))
+REPL.register("user-symbols", Builtin("user-symbols", interpretUserSymbols, []))
diff --git a/neb/std/strings.py b/neb/std/strings.py
index 0d5ebdb..68f02d5 100644
--- a/neb/std/strings.py
+++ b/neb/std/strings.py
@@ -1,4 +1,4 @@
-from .. import TypeEnum, Environment, Arg, Builtin, evaluate
+from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic
from ..structs import *
STRINGS = Environment()
@@ -10,16 +10,12 @@ def interpretConcat(symbol, args, env, ns):
return String(out)
string_arg = Arg("arg", TypeEnum.STRING)
-STRINGS.register("concat", Builtin(interpretConcat, [string_arg, string_arg], string_arg))
+STRINGS.register("concat", Builtin("concat", interpretConcat, [string_arg, string_arg], string_arg))
def interpretStrip(symbol, args, env, ns):
return String(args[0].value.strip())
-STRINGS.register("strip", Builtin(interpretStrip, [Arg("filename", TypeEnum.STRING)]))
-def interpretStrip(symbol, args, env, ns):
- return String(args[0].value.strip())
-
-STRINGS.register("strip", Builtin(interpretStrip, [Arg("filename", TypeEnum.STRING)]))
+STRINGS.register("strip", Builtin("strip", interpretStrip, [Arg("filename", TypeEnum.STRING)]))
def interpretSplit(symbol, args, env, ns):
target = args[0]
@@ -29,7 +25,7 @@ def interpretSplit(symbol, args, env, ns):
ret = target.value.split(splitter.value)
return List([String(r) for r in ret])
-STRINGS.register("split", Builtin(interpretSplit, [Arg("target", TypeEnum.STRING)], Arg("splitter", TypeEnum.STRING, optional=True)))
+STRINGS.register("split", Builtin("split", interpretSplit, [Arg("target", TypeEnum.STRING)], Arg("splitter", TypeEnum.STRING, optional=True)))
def interpretJoin(symbol, args, env, ns):
lst = args[0]
@@ -38,16 +34,16 @@ def interpretJoin(symbol, args, env, ns):
join_list_arg = Arg("list", TypeEnum.LIST)
join_string_arg = Arg("joiner", TypeEnum.STRING)
-STRINGS.register("join", Builtin(interpretJoin, [join_list_arg, join_string_arg]))
+STRINGS.register("join", Builtin("join", interpretJoin, [join_list_arg, join_string_arg]))
def interpretFirstChar(symbol, args, env, ns):
if len(args[0].value) == 0:
raise InterpretPanic(symbol, ":string is empty", ev)
return String(args[0].value[0])
-STRINGS.register("first-char", Builtin(interpretFirstChar, [Arg("string", TypeEnum.STRING)]))
+STRINGS.register("first-char", Builtin("first-char", interpretFirstChar, [Arg("string", TypeEnum.STRING)]))
def interpretRestChar(symbol, args, env, ns):
return String(args[0].value[1:])
-STRINGS.register("rest-char", Builtin(interpretRestChar, [Arg("string", TypeEnum.STRING)]))
+STRINGS.register("rest-char", Builtin("rest-char", interpretRestChar, [Arg("string", TypeEnum.STRING)]))
diff --git a/neb/std/sys.py b/neb/std/sys.py
index 252a0b0..98266f2 100644
--- a/neb/std/sys.py
+++ b/neb/std/sys.py
@@ -1,4 +1,4 @@
-from .. import TypeEnum, Environment, Arg, Builtin, evaluate
+from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic
from ..structs import *
import shlex
import subprocess
@@ -12,13 +12,13 @@ def interpretArgv(symbol, args, env, ns):
out.append(String(arg))
return List(out)
-SYS.register("argv", Builtin(interpretArgv, []))
+SYS.register("argv", Builtin("argv", interpretArgv, []))
def interpretShell(symbol, args, env, ns):
ret = subprocess.run(shlex.split(args[0].value), capture_output=True)
return List([String(r) for r in ret.stdout.decode("utf-8").split("\n")])
-SYS.register("$", Builtin(interpretShell, [Arg("command", TypeEnum.STRING)]))
+SYS.register("$", Builtin("$", interpretShell, [Arg("command", TypeEnum.STRING)]))
def interpretExit(symbol, args, env, ns):
status = 0 if len(args) == 0 else args[0].value
@@ -26,10 +26,10 @@ def interpretExit(symbol, args, env, ns):
return List([])
exit_arg = Arg("status", TypeEnum.INT, optional=True)
-SYS.register("exit", Builtin(interpretExit, [exit_arg]))
+SYS.register("exit", Builtin("exit", interpretExit, [exit_arg]))
def interpretPrint(symbol, args, env, ns):
print(args[0].value)
return List([]) # print returns nothing
-SYS.register("print", Builtin(interpretPrint, [Arg("arg", TypeEnum.STRING)]))
+SYS.register("print", Builtin("print", interpretPrint, [Arg("arg", TypeEnum.STRING)]))
diff --git a/neb/std/term.py b/neb/std/term.py
index e706005..59f6fdf 100644
--- a/neb/std/term.py
+++ b/neb/std/term.py
@@ -1,4 +1,4 @@
-from .. import TypeEnum, Environment, Arg, Builtin, evaluate
+from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic
from ..structs import *
import subprocess
import sys
@@ -9,13 +9,13 @@ def interpretClear(symbol, args, env, ns):
subprocess.run(["clear"])
return List([])
-TERM.register("clear", Builtin(interpretClear, []))
+TERM.register("clear", Builtin("clear", interpretClear, []))
def interpretReadLine(symbol, args, env, ns):
ret = input(args[0].value)
return String(ret)
-TERM.register("read-line", Builtin(interpretReadLine, [Arg("prompt", TypeEnum.STRING)]))
+TERM.register("read-line", Builtin("read-line", interpretReadLine, [Arg("prompt", TypeEnum.STRING)]))
def interpretReadChar(symbol, args, env, ns):
import termios, tty
@@ -30,4 +30,4 @@ def interpretReadChar(symbol, args, env, ns):
termios.tcsetattr(fd, termios.TCSADRAIN, old)
return String(ch.decode("utf-8"))
-TERM.register("read-char", Builtin(interpretReadChar, []))
+TERM.register("read-char", Builtin("read-char", interpretReadChar, []))
diff --git a/neb/std/types.py b/neb/std/types.py
index 3cf55ac..ab099e2 100644
--- a/neb/std/types.py
+++ b/neb/std/types.py
@@ -1,4 +1,4 @@
-from .. import TypeEnum, Environment, Arg, Builtin, evaluate
+from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic
from ..structs import *
TYPES = Environment()
@@ -6,33 +6,33 @@ TYPES = Environment()
def interpretIsBool(symbol, args, env, ns):
return Bool(isinstance(args[0], Bool))
-TYPES.register("bool?", Builtin(interpretIsBool, [Arg("arg", TypeEnum.ANY)]))
+TYPES.register("bool?", Builtin("bool?", interpretIsBool, [Arg("arg", TypeEnum.ANY)]))
def interpretIsFloat(symbol, args, env, ns):
return Bool(isinstance(args[0], Float))
-TYPES.register("float?", Builtin(interpretIsFloat, [Arg("arg", TypeEnum.ANY)]))
+TYPES.register("float?", Builtin("float?", interpretIsFloat, [Arg("arg", TypeEnum.ANY)]))
def interpretIsNumber(symbol, args, env, ns):
ret = isinstance(args[0], Int) or isinstance(args[0], Float)
return Bool(ret)
-TYPES.register("number?", Builtin(interpretIsNumber, [Arg("arg", TypeEnum.ANY)]))
+TYPES.register("number?", Builtin("number?", interpretIsNumber, [Arg("arg", TypeEnum.ANY)]))
def interpretIsInt(symbol, args, env, ns):
return Bool(isinstance(args[0], Int))
-TYPES.register("int?", Builtin(interpretIsInt, [Arg("arg", TypeEnum.ANY)]))
+TYPES.register("int?", Builtin("int?", interpretIsInt, [Arg("arg", TypeEnum.ANY)]))
def interpretIsList(symbol, args, env, ns):
return Bool(isinstance(args[0], List))
-TYPES.register("list?", Builtin(interpretIsList, [Arg("arg", TypeEnum.ANY)]))
+TYPES.register("list?", Builtin("list?", interpretIsList, [Arg("arg", TypeEnum.ANY)]))
def interpretIsString(symbol, args, env, ns):
return Bool(isinstance(args[0], String))
-TYPES.register("string?", Builtin(interpretIsString, [Arg("arg", TypeEnum.ANY)]))
+TYPES.register("string?", Builtin("string?", interpretIsString, [Arg("arg", TypeEnum.ANY)]))
def interpretStringToInt(symbol, args, env, ns):
try:
@@ -41,7 +41,7 @@ def interpretStringToInt(symbol, args, env, ns):
except:
raise InterpretPanic(symbol, "can't convert to an :int", args[0])
-TYPES.register("string->int", Builtin(interpretStringToInt, [Arg("arg", TypeEnum.STRING)]))
+TYPES.register("string->int", Builtin("string->int", interpretStringToInt, [Arg("arg", TypeEnum.STRING)]))
def interpretToString(symbol, args, env, ns):
item = args[0]
@@ -52,9 +52,9 @@ def interpretToString(symbol, args, env, ns):
else:
return String(f"{item}")
-TYPES.register("->string", Builtin(interpretToString, [Arg("arg", TypeEnum.ANY)]))
+TYPES.register("->string", Builtin("->string", interpretToString, [Arg("arg", TypeEnum.ANY)]))
def interpretTypeOf(symbol, args, env, ns):
return Type(f"{args[0].type_}")
-TYPES.register("typeof", Builtin(interpretTypeOf, [Arg("candidate", TypeEnum.ANY)]))
+TYPES.register("typeof", Builtin("typeof", interpretTypeOf, [Arg("candidate", TypeEnum.ANY)]))
diff --git a/neb/structs.py b/neb/structs.py
index cba0c03..f1cee95 100644
--- a/neb/structs.py
+++ b/neb/structs.py
@@ -128,6 +128,13 @@ class Arg:
lazy = "~" if self.lazy else ""
return f"{lazy}{opt}{self.name} {self.type_}"
+def string_args(args, many):
+ out = [f"{arg}" for arg in args]
+ if many is not None:
+ many.name = "&"
+ out.append(f"{many}")
+ return " ".join(out).strip()
+
class Environment:
def __init__(self, parent=None):