aboutsummaryrefslogtreecommitdiff
path: root/neb/std
diff options
context:
space:
mode:
Diffstat (limited to 'neb/std')
-rw-r--r--neb/std/core.py32
-rw-r--r--neb/std/types.py16
2 files changed, 39 insertions, 9 deletions
diff --git a/neb/std/core.py b/neb/std/core.py
index 8881468..83b164c 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
+from .. import TypeEnum, Environment, Arg, Builtin, UserFunction, evaluate, interpret, parse, lex, InterpretPanic, TypeWrap, Function, UserType
from ..structs import *
from pathlib import Path
@@ -182,3 +182,33 @@ def interpretEval(symbol, args, env, ns):
eval_arg = Arg("arg", TypeEnum.ANY)
CORE.register("eval", Builtin("eval", interpretEval, [eval_arg]))
+
+def interpretType(symbol, args, env, ns):
+ # (type typename parent func)
+ if not isinstance(args[0], Type):
+ raise InterpretPanic(symbol, "types must begin with a colon")
+ name = args[0].name # NOTE: we are not evaluating the name!!
+
+ # 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)
+
+ func = args[2]
+ if not isinstance(func, Function):
+ raise InterpretPanic(symbol, "validation must be a :func", func)
+
+ new_type = UserType(name, parent, func)
+ env.register(name, new_type)
+ return List([])
+
+type_name_arg = Arg("name", TypeEnum.ANY, lazy=True)
+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]))
+
+
diff --git a/neb/std/types.py b/neb/std/types.py
index b5fb993..855a1d9 100644
--- a/neb/std/types.py
+++ b/neb/std/types.py
@@ -70,14 +70,14 @@ def interpretIsLiteral(symbol, args, env, ns):
TYPES.register("literal?", Builtin("literal?", interpretIsLiteral, [Arg("arg", TypeEnum.ANY)]))
# add types to env
-any_type = NebType(":any", None, interpretIsAny)
-literal_type = NebType(":literal", any_type, interpretIsLiteral)
-string_type = NebType(":string", literal_type, interpretIsString)
-list_type = NebType(":list", any_type, interpretIsList)
-bool_type = NebType(":bool", literal_type, interpretIsBool)
-number_type = NebType(":number", literal_type, interpretIsNumber)
-int_type = NebType(":int", number_type, interpretIsInt)
-float_type = NebType(":float", number_type, interpretIsFloat)
+any_type = NebType(":any", None, Builtin("any?", interpretIsAny, [Arg("arg", TypeEnum.ANY)]))
+literal_type = NebType(":literal", any_type, Builtin("literal?", interpretIsLiteral, [Arg("arg", TypeEnum.ANY)]))
+string_type = NebType(":string", literal_type, Builtin("string?", interpretIsString, [Arg("arg", TypeEnum.ANY)]))
+list_type = NebType(":list", any_type, Builtin("list?", interpretIsList, [Arg("arg", TypeEnum.ANY)]))
+bool_type = NebType(":bool", literal_type, Builtin("bool?", interpretIsBool, [Arg("arg", TypeEnum.ANY)]))
+number_type = NebType(":number", literal_type, Builtin("number?", interpretIsNumber, [Arg("arg", TypeEnum.ANY)]))
+int_type = NebType(":int", number_type, Builtin("int?", interpretIsInt, [Arg("arg", TypeEnum.ANY)]))
+float_type = NebType(":float", number_type, Builtin("float?", interpretIsFloat, [Arg("arg", TypeEnum.ANY)]))
TYPES.register(":any", any_type)
TYPES.register(":literal", literal_type)