aboutsummaryrefslogtreecommitdiff
path: root/neb
diff options
context:
space:
mode:
Diffstat (limited to 'neb')
-rw-r--r--neb/__init__.py42
-rw-r--r--neb/std/types.py31
2 files changed, 68 insertions, 5 deletions
diff --git a/neb/__init__.py b/neb/__init__.py
index a492df8..c505a04 100644
--- a/neb/__init__.py
+++ b/neb/__init__.py
@@ -11,15 +11,18 @@ 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, Type):
+ if isinstance(expr, Literal) or isinstance(expr, Function) or isinstance(expr, TypeWrap):
return expr
- elif isinstance(expr, Symbol):
+ elif isinstance(expr, Symbol) or isinstance(expr, Type):
if env.contains(expr.name):
return evaluate(env.get(expr.name), env, ns)
elif ns is not None and env.contains(f"{ns}/{expr.name}"):
return evaluate(env.get(f"{ns}/{expr.name}"), env, ns)
else:
- raise NebPanic(f"no such symbol: {expr}")
+ if isinstance(expr, Symbol):
+ raise NebPanic(f"no such symbol: {expr}")
+ else:
+ raise NebPanic(f"no such type {expr}")
# if it's an empty list, return it
elif len(expr.args) == 0:
@@ -79,7 +82,10 @@ class Function:
ret.append(param)
continue
ev = evaluate(param, env, ns)
- if not is_subtype_of(ev.type_, arg.type_):
+ expected_name = f"{arg.type_}"
+ expected_type = env.get(expected_name)
+ valid = expected_type.validate_type(ev, env, ns)
+ if not valid.value:
exp = f"{arg.type_}"
rec = f"{ev.type_}"
raise InterpretPanic(symbol, f"received {rec}, expected {exp}", ev)
@@ -160,3 +166,31 @@ class UserFunction(Function):
this_env.register(self.many.name, List(evaluated_args[len(self.params):]))
return interpret(self.body, env=this_env, ns=ns)
+
+
+class TypeWrap:
+
+ def __init__(self, name, parent, is_func):
+ self.name = name
+ self.parent = parent
+ self.is_func = is_func
+
+ def validate_type(self, target, env, ns):
+ valid = self.is_func(None, [target], env, ns)
+ if valid.value == True:
+ return valid
+ parent_type = env.get(f"{target.type_}")
+ while valid.value != True and parent_type.parent is not None:
+ parent_type = env.get(f"{parent_type.parent}")
+ valid = Bool(self.name == parent_type.name)
+ return valid
+
+ def __str__(self):
+ return f"{self.name}"
+
+
+class NebType(TypeWrap):
+ pass
+
+class UserType(TypeWrap):
+ pass
diff --git a/neb/std/types.py b/neb/std/types.py
index ab099e2..b5fb993 100644
--- a/neb/std/types.py
+++ b/neb/std/types.py
@@ -1,4 +1,4 @@
-from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic
+from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic, NebType
from ..structs import *
TYPES = Environment()
@@ -58,3 +58,32 @@ def interpretTypeOf(symbol, args, env, ns):
return Type(f"{args[0].type_}")
TYPES.register("typeof", Builtin("typeof", interpretTypeOf, [Arg("candidate", TypeEnum.ANY)]))
+
+def interpretIsAny(symbol, args, env, ns):
+ return Bool(True)
+
+TYPES.register("any?", Builtin("any?", interpretIsAny, [Arg("arg", TypeEnum.ANY)]))
+
+def interpretIsLiteral(symbol, args, env, ns):
+ return Bool(isinstance(args[0], Literal))
+
+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)
+
+TYPES.register(":any", any_type)
+TYPES.register(":literal", literal_type)
+TYPES.register(":string", string_type)
+TYPES.register(":list", list_type)
+TYPES.register(":bool", bool_type)
+TYPES.register(":number", number_type)
+TYPES.register(":int", int_type)
+TYPES.register(":float", float_type)