From ed2a063a4388ef7e315f4d7b9e59405b9aad71e4 Mon Sep 17 00:00:00 2001 From: mryouse Date: Fri, 1 Jul 2022 02:59:39 +0000 Subject: Revert "initial commit of multi-type support (only list of strings for now)" This reverts commit bf8900200c25d383c883501446a8048ad8966d94. --- neb/__init__.py | 4 ++-- neb/parser.py | 13 +------------ neb/std/core.py | 2 +- neb/std/types.py | 13 ------------- neb/structs.py | 7 ------- 5 files changed, 4 insertions(+), 35 deletions(-) diff --git a/neb/__init__.py b/neb/__init__.py index ab0f836..9b3c1e9 100644 --- a/neb/__init__.py +++ b/neb/__init__.py @@ -13,7 +13,7 @@ def interpret(exprs, env, ns=None): def evaluate(expr, env, ns=None): if isinstance(expr, Literal) or isinstance(expr, Function) or isinstance(expr, TypeWrap) or isinstance(expr, List): return expr - elif isinstance(expr, Symbol) or isinstance(expr, Type) or isinstance(expr, MultiType): + 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}"): @@ -144,7 +144,7 @@ class UserFunction(Function): newparams.append(param) args.append(Arg(param.name, TypeEnum.ANY)) prev_type = False - elif (isinstance(param, Type) or isinstance(param, MultiType)) and not prev_type and not first: + elif isinstance(param, Type) and not prev_type and not first: if many is None: args[-1].type_ = param.name else: diff --git a/neb/parser.py b/neb/parser.py index 10c6633..bbaf7a8 100644 --- a/neb/parser.py +++ b/neb/parser.py @@ -45,19 +45,8 @@ def parseLiteral(token, prev, tokens): def parseType(token, prev, tokens): # if the next token is a symbol, combine for a type - if tokens[0].type_ == TokenType.SYMBOL: + if len(tokens) > 0 and tokens[0].type_ == TokenType.SYMBOL: return Type(f":{tokens[0].text}"), 2 - elif tokens[0].type_ == TokenType.OPEN_BRACKET: - # only format currently supported: - # [ ] - if tokens[1].type_ != TokenType.COLON: - raise ParseError("invalid type definition (expecting colon)", tokens[1].line) - 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 - else: - raise ParseError("invalid type definition!", tokens[0].line) def parse(tokens): idx = 0 diff --git a/neb/std/core.py b/neb/std/core.py index 750594e..1c3c4b4 100644 --- a/neb/std/core.py +++ b/neb/std/core.py @@ -47,7 +47,7 @@ CORE.register("redef", Builtin("redef", interpretRedef, [def_name_arg, def_val_a def interpretLambda(symbol, args, env, ns): new_args = args return_type = Type(":any") - if isinstance(args[0], Type) or isinstance(args[0], MultiType): + if isinstance(args[0], Type): return_type = args[0] new_args = args[1:] diff --git a/neb/std/types.py b/neb/std/types.py index b5422da..f8d5405 100644 --- a/neb/std/types.py +++ b/neb/std/types.py @@ -69,16 +69,6 @@ def interpretIsLiteral(symbol, args, env, ns): TYPES.register("literal?", Builtin("literal?", interpretIsLiteral, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool"))) -def interpretIsListOfString(symbol, args, env, ns): - if not isinstance(args[0], List): - return Bool(False) - for arg in args[0].args: - if not isinstance(arg, String): - return Bool(False) - return Bool(True) - -TYPES.register("list-of-string?", Builtin("list-of-string?", interpretIsListOfString, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool"))) - # add types to env any_type = NebType(":any", None, interpretIsAny) literal_type = NebType(":literal", any_type, interpretIsLiteral) @@ -89,8 +79,6 @@ 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) - TYPES.register(":any", any_type) TYPES.register(":literal", literal_type) TYPES.register(":string", string_type) @@ -99,4 +87,3 @@ 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) diff --git a/neb/structs.py b/neb/structs.py index 80252a0..b8effd0 100644 --- a/neb/structs.py +++ b/neb/structs.py @@ -97,13 +97,6 @@ class Type: def __str__(self): return self.name -class MultiType: - def __init__(self, name, inner): - self.name = name - self.inner = inner - def __str__(self): - return self.name - class Symbol: def __init__(self, name, line): self.name = name -- cgit v1.2.3 From 74a048dd493788bab9f9c93b0ed6d925a998822b Mon Sep 17 00:00:00 2001 From: mryouse Date: Fri, 1 Jul 2022 03:03:45 +0000 Subject: return type hints for ansi.neb --- libs/ansi.neb | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/libs/ansi.neb b/libs/ansi.neb index 21b9bbb..6de7f2f 100644 --- a/libs/ansi.neb +++ b/libs/ansi.neb @@ -8,91 +8,91 @@ ; COLORS (def black-on (wrap "30")) -(func black (str :string) +(func black :string (str :string) (concat black-on str reset)) (def bright-black-on (wrap "90")) -(func bright-black (str :string) +(func bright-black :string (str :string) (concat bright-black-on str reset)) (def red-on (wrap "31")) -(func red (str :string) +(func red :string (str :string) (concat red str reset)) (def bright-red-on (wrap "91")) -(func bright-red (str :string) +(func bright-red :string (str :string) (concat bright-red-on str reset)) (def green-on (wrap "32")) -(func green (str :string) +(func green :string (str :string) (concat green-on str reset)) (def bright-green-on (wrap "92")) -(func bright-green (str :string) +(func bright-green :string (str :string) (concat bright-green-on str reset)) (def yellow-on (wrap "33")) -(func yellow (str :string) +(func yellow :string (str :string) (concat yellow-on str reset)) (def bright-yellow-on (wrap "93")) -(func bright-yellow (str :string) +(func bright-yellow :string (str :string) (concat bright-yellow-on str reset)) (def blue-on (wrap "34")) -(func blue (str :string) +(func blue :string (str :string) (concat blue-on str reset)) (def bright-blue-on (wrap "94")) -(func bright-blue (str :string) +(func bright-blue :string (str :string) (concat bright-blue-on str reset)) (def magenta-on (wrap "35")) -(func magenta (str :string) +(func magenta :string (str :string) (concat magenta-on str reset)) (def bright-magenta-on (wrap "95")) -(func bright-magenta (str :string) +(func bright-magenta :string (str :string) (concat bright-magenta-on str reset)) (def cyan-on (wrap "36")) -(func cyan (str :string) +(func cyan :string (str :string) (concat cyan-on str reset)) (def bright-cyan-on (wrap "96")) -(func bright-cyan (str :string) +(func bright-cyan :string (str :string) (concat bright-cyan-on str reset)) (def white-on (wrap "37")) -(func white (str :string) +(func white :string (str :string) (concat white-on str reset)) (def bright-white-on (wrap "97")) -(func bright-white (str :string) +(func bright-white :string (str :string) (concat bright-white-on str reset)) ; STYLES (def bold-on (wrap "1")) -(func bold (str :string) +(func bold :string (str :string) (concat bold-on str reset)) (def faint-on (wrap "2")) -(func faint (str :string) +(func faint :string (str :string) (concat faint-on str reset)) (def italic-on (wrap "3")) -(func italic (str :string) +(func italic :string (str :string) (concat italic-on str reset)) (def underline-on (wrap "4")) -(func underline (str :string) +(func underline :string (str :string) (concat underline-on str reset)) (def blink-on (wrap "5")) -(func blink (str :string) +(func blink :string (str :string) (concat blink-on str reset)) (def reverse-on (wrap "7")) -(func reverse (str :string) +(func reverse :string (str :string) (concat reverse-on str reset)) -- cgit v1.2.3 From 2f43cbc79d5aa5d4677e44377492a3010840b58a 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 | 11 +++++++++++ neb/std/types.py | 32 ++++++++++++++++++++++++++++---- neb/structs.py | 34 ++++++++++++++++++++++++---------- 4 files changed, 81 insertions(+), 24 deletions(-) diff --git a/neb/__init__.py b/neb/__init__.py index 9b3c1e9..3ba9172 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) 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 bbaf7a8..d5712d2 100644 --- a/neb/parser.py +++ b/neb/parser.py @@ -47,6 +47,17 @@ def parseType(token, prev, tokens): # if the next token is a symbol, combine for a type if len(tokens) > 0 and tokens[0].type_ == TokenType.SYMBOL: return Type(f":{tokens[0].text}"), 2 + elif tokens[0].type_ == TokenType.OPEN_BRACKET: + # only format currently supported: + # [ ] + if tokens[1].type_ != TokenType.COLON: + raise ParseError("invalid type definition (expecting colon)", tokens[1].line) + 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 Type(f":[]", typ), counter + 3 + else: + raise ParseError("invalid type definition!", tokens[0].line) def parse(tokens): idx = 0 diff --git a/neb/std/types.py b/neb/std/types.py index f8d5405..3517384 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"))) @@ -73,7 +95,8 @@ TYPES.register("literal?", Builtin("literal?", interpretIsLiteral, [Arg("arg", T 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) @@ -82,7 +105,8 @@ 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(":list", list_type) +TYPES.register(":[]", bracket_type) TYPES.register(":bool", bool_type) TYPES.register(":number", number_type) TYPES.register(":int", int_type) diff --git a/neb/structs.py b/neb/structs.py index b8effd0..0ba2aaa 100644 --- a/neb/structs.py +++ b/neb/structs.py @@ -61,41 +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): + 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): @@ -115,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) + ")" @@ -124,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 From 78398a11828e9affd8be0c83ee16d6283e0a27dc Mon Sep 17 00:00:00 2001 From: mryouse Date: Sat, 2 Jul 2022 03:51:10 +0000 Subject: refactor: get rid of deepcopy for performance, pass inner type instead --- neb/__init__.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/neb/__init__.py b/neb/__init__.py index 3ba9172..0757071 100644 --- a/neb/__init__.py +++ b/neb/__init__.py @@ -84,12 +84,12 @@ class Function: ret.append(param) continue ev = evaluate(param, env, ns) - #expected_name = f"{arg.type_}" expected_name = arg.type_.name - expected_type = deepcopy(env.get(expected_name)) + expected_type = env.get(expected_name) + inner = None if arg.type_.inner is not None: - expected_type.name.inner = arg.type_.inner - valid = expected_type.validate_type(ev, env, ns) + inner = env.get(arg.type_.inner.name) + valid = expected_type.validate_type(ev, env, ns, inner) if not valid.value: exp = f"{arg.type_}" rec = f"{ev.type_}" @@ -182,7 +182,7 @@ class TypeWrap: self.parent = parent self.is_func = is_func - def validate_type(self, target, env, ns): + def validate_type(self, target, env, ns, inner=None): # if it's an any type, it's valid if self.parent is None: return Bool(True) @@ -191,7 +191,15 @@ class TypeWrap: else: valid = self.is_func(self.name, [target], env, ns) if valid.value == True: - return valid + if inner is None: + return valid + else: + for arg in target.args: + valid = inner.validate_type(arg, env, ns) + if valid.value == False: + return Bool(False) + return valid + #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: -- cgit v1.2.3