diff options
Diffstat (limited to 'neb')
| -rw-r--r-- | neb/__init__.py | 42 | ||||
| -rw-r--r-- | neb/std/types.py | 31 |
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) |
