aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormryouse2022-07-01 02:45:23 +0000
committermryouse2022-07-02 03:15:45 +0000
commit2f43cbc79d5aa5d4677e44377492a3010840b58a (patch)
treeedd8f6b9202f59a406d57b11c586853bdd02bf11
parent74a048dd493788bab9f9c93b0ed6d925a998822b (diff)
attempt to add a generic list type
-rw-r--r--neb/__init__.py28
-rw-r--r--neb/parser.py11
-rw-r--r--neb/std/types.py32
-rw-r--r--neb/structs.py34
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:
+ # [ <type> ]
+ 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