From d914e16f0b4de7a20df9dbd2d5baa97fa08424a7 Mon Sep 17 00:00:00 2001 From: mryouse Date: Fri, 1 Jul 2022 02:45:23 +0000 Subject: attempt to add a generic list type --- neb/__init__.py | 28 ++++++++++++++++++---------- neb/parser.py | 2 +- neb/std/types.py | 36 ++++++++++++++++++++++++++++++------ neb/structs.py | 39 +++++++++++++++++++++++---------------- 4 files changed, 72 insertions(+), 33 deletions(-) (limited to 'neb') diff --git a/neb/__init__.py b/neb/__init__.py index ab0f836..cf51ed6 100644 --- a/neb/__init__.py +++ b/neb/__init__.py @@ -3,6 +3,7 @@ from .parser import parse from .exceptions import * from .typeclass import TypeEnum, is_subtype_of from .structs import * +from copy import deepcopy def interpret(exprs, env, ns=None): ret = None @@ -46,7 +47,8 @@ class Function: self.body = body self.args = args self.many = many - self.type_ = TypeEnum.ANY # TODO no it's not + #self.type_ = TypeEnum.ANY # TODO no it's not + self.type_ = Type(":any") # TODO no it's not self.return_type = Type(":any") def describe(self, name=None): @@ -82,8 +84,11 @@ class Function: ret.append(param) continue ev = evaluate(param, env, ns) - expected_name = f"{arg.type_}" - expected_type = env.get(expected_name) + #expected_name = f"{arg.type_}" + expected_name = arg.type_.name + expected_type = deepcopy(env.get(expected_name)) + if arg.type_.inner is not None: + expected_type.name.inner = arg.type_.inner valid = expected_type.validate_type(ev, env, ns) if not valid.value: exp = f"{arg.type_}" @@ -146,9 +151,11 @@ class UserFunction(Function): prev_type = False elif (isinstance(param, Type) or isinstance(param, MultiType)) and not prev_type and not first: if many is None: - args[-1].type_ = param.name + #args[-1].type_ = param.name + args[-1].type_ = param else: - many.type_ = param.name + #many.type_ = param.name + many.type_ = param prev_type = True else: raise NebPanic("invalid :func signature", param) @@ -171,7 +178,7 @@ class UserFunction(Function): class TypeWrap: def __init__(self, name, parent, is_func): - self.name = name + self.name = ALL_TYPES[name] self.parent = parent self.is_func = is_func @@ -180,14 +187,15 @@ class TypeWrap: if self.parent is None: return Bool(True) if isinstance(self.is_func, UserFunction): - valid = self.is_func.call(Expr([None, target]), env, ns) + valid = self.is_func.call(Expr([self.name, target]), env, ns) else: - valid = self.is_func(None, [target], env, ns) + valid = self.is_func(self.name, [target], env, ns) if valid.value == True: return valid - parent_type = env.get(f"{target.type_}") + #parent_type = env.get(f"{target.type_}") + parent_type = env.get(target.type_.name) while valid.value != True and parent_type.parent is not None: - parent_type = env.get(f"{parent_type.parent}") + parent_type = env.get(parent_type.parent.name.name) valid = Bool(self.name == parent_type.name) # TODO wrong return valid diff --git a/neb/parser.py b/neb/parser.py index 10c6633..9a73ef7 100644 --- a/neb/parser.py +++ b/neb/parser.py @@ -55,7 +55,7 @@ def parseType(token, prev, tokens): typ, counter = parseType(tokens[1], tokens[0], tokens[2:]) if tokens[1+counter].type_ != TokenType.CLOSE_BRACKET: raise ParseError("invalid type definition (expecting close bracket)", tokens[1+counter].line) - return MultiType(f":[{typ.name}]", typ), counter + 3 + return Type(f":[]", typ), counter + 3 else: raise ParseError("invalid type definition!", tokens[0].line) diff --git a/neb/std/types.py b/neb/std/types.py index b5422da..80288fa 100644 --- a/neb/std/types.py +++ b/neb/std/types.py @@ -1,4 +1,4 @@ -from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic, NebType +from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic, NebType, TypeWrap from ..structs import * TYPES = Environment() @@ -25,7 +25,29 @@ def interpretIsInt(symbol, args, env, ns): TYPES.register("int?", Builtin("int?", interpretIsInt, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool"))) def interpretIsList(symbol, args, env, ns): - return Bool(isinstance(args[0], List)) + + # if it's not a list, we're done + if not isinstance(args[0], List): + return Bool(False) + + # if the symbol isn't a type, we're done + elif not isinstance(symbol, Type): + return Bool(True) + + inner = symbol.inner + if inner is None or inner.name == ":any": + return Bool(True) + + inner_func = env.get(inner.name).is_func + + for arg in args[0].args: + if inner_func(inner, [arg], env, ns).value is False: + return Bool(False) + + #if not isinstance(arg, String): + # return Bool(False) + return Bool(True) + TYPES.register("list?", Builtin("list?", interpretIsList, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool"))) @@ -83,20 +105,22 @@ TYPES.register("list-of-string?", Builtin("list-of-string?", interpretIsListOfSt 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) +#list_type = NebType(":list", any_type, interpretIsList) +bracket_type = NebType(":[]", 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) -list_of_string_type = NebType(":[:string]", list_type, interpretIsListOfString) +#list_of_string_type = NebType(":[:string]", list_type, interpretIsListOfString) TYPES.register(":any", any_type) TYPES.register(":literal", literal_type) TYPES.register(":string", string_type) -TYPES.register(":list", list_type) +#TYPES.register(":list", list_type) +TYPES.register(":[]", bracket_type) TYPES.register(":bool", bool_type) TYPES.register(":number", number_type) TYPES.register(":int", int_type) TYPES.register(":float", float_type) -TYPES.register(":[:string]", list_of_string_type) +#TYPES.register(":[:string]", list_of_string_type) diff --git a/neb/structs.py b/neb/structs.py index 80252a0..0ba2aaa 100644 --- a/neb/structs.py +++ b/neb/structs.py @@ -61,48 +61,52 @@ class Literal: def __init__(self, value, type_=None): self.value = value if type_ is None: - self.type_ = TypeEnum.ANY + #self.type_ = TypeEnum.ANY + self.type_ = ALL_TYPES[":literal"] else: - self.type_ = type_ + self.type_ = ALL_TYPES[type_] def __str__(self): return f"{self.value}:literal" class Int(Literal): def __init__(self, value): - super().__init__(value, TypeEnum.INT) + super().__init__(value, ":int") def __str__(self): return f"{self.value}" class Float(Literal): def __init__(self, value): - super().__init__(value, TypeEnum.FLOAT) + super().__init__(value, ":float") def __str__(self): return f"{self.value}" class Bool(Literal): def __init__(self, value): - super().__init__(value, TypeEnum.BOOL) + super().__init__(value, ":bool") def __str__(self): return f"#{str(self.value).lower()}" class String(Literal): def __init__(self, value): - super().__init__(value, TypeEnum.STRING) + super().__init__(value, ":string") def __str__(self): return f'"{repr(self.value)[1:-1]}"' class Type: - def __init__(self, name): - self.name = name - def __str__(self): - return self.name - -class MultiType: - def __init__(self, name, inner): + def __init__(self, name, inner=None): self.name = name self.inner = inner def __str__(self): - return self.name + if self.name == ":[]": + if self.inner is None: + return f":[:any]" + else: + return f":[{self.inner}]" + else: + return self.name + +_native_types = ":any :literal :string :bool :number :int :float :[]" +ALL_TYPES = {x: Type(x) for x in _native_types.split(" ")} class Symbol: def __init__(self, name, line): @@ -122,7 +126,7 @@ class Expr: class List: def __init__(self, args): self.args = args - self.type_ = TypeEnum.LIST + self.type_ = ALL_TYPES[":[]"] def __str__(self): return "(" + " ".join(f"{arg}" for arg in self.args) + ")" @@ -131,7 +135,10 @@ class Arg: def __init__(self, name, type_, *, optional=False, lazy=False): self.name = name - self.type_ = type_ + if f"{type_}" == ":list": + self.type_ = ALL_TYPES[":[]"] + else: + self.type_ = ALL_TYPES[f"{type_}"] self.optional = optional self.lazy = lazy -- cgit v1.2.3