aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormryouse2022-06-30 03:40:39 +0000
committermryouse2022-06-30 03:40:39 +0000
commitbf8900200c25d383c883501446a8048ad8966d94 (patch)
treec9c5fbd4563b2edc066339f0933d9b225bb5bdd6
parent5274edb5484f75266304d21840f8e854f2a1d3c5 (diff)
initial commit of multi-type support (only list of strings for now)
-rw-r--r--neb/__init__.py4
-rw-r--r--neb/parser.py13
-rw-r--r--neb/std/core.py2
-rw-r--r--neb/std/types.py13
-rw-r--r--neb/structs.py7
5 files changed, 35 insertions, 4 deletions
diff --git a/neb/__init__.py b/neb/__init__.py
index 9b3c1e9..ab0f836 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):
+ elif isinstance(expr, Symbol) or isinstance(expr, Type) or isinstance(expr, MultiType):
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) and not prev_type and not first:
+ elif (isinstance(param, Type) or isinstance(param, MultiType)) 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 bbaf7a8..10c6633 100644
--- a/neb/parser.py
+++ b/neb/parser.py
@@ -45,8 +45,19 @@ def parseLiteral(token, prev, tokens):
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:
+ if 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 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 1c3c4b4..750594e 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):
+ if isinstance(args[0], Type) or isinstance(args[0], MultiType):
return_type = args[0]
new_args = args[1:]
diff --git a/neb/std/types.py b/neb/std/types.py
index f8d5405..b5422da 100644
--- a/neb/std/types.py
+++ b/neb/std/types.py
@@ -69,6 +69,16 @@ 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)
@@ -79,6 +89,8 @@ 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)
@@ -87,3 +99,4 @@ 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 b8effd0..80252a0 100644
--- a/neb/structs.py
+++ b/neb/structs.py
@@ -97,6 +97,13 @@ 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