diff options
| author | mryouse | 2022-07-27 00:43:17 +0000 |
|---|---|---|
| committer | mryouse | 2022-07-27 00:43:17 +0000 |
| commit | aa52ae991cd7bfaebd358f7d1a9482613b82396c (patch) | |
| tree | ddfe4fe51bc5280a59df970f2b13d75cf5215128 /neb | |
| parent | f2125f46a689abd037b081a17c112ec3170ee0e4 (diff) | |
implement {} syntax for non-empty lists
Diffstat (limited to 'neb')
| -rw-r--r-- | neb/lexer.py | 6 | ||||
| -rw-r--r-- | neb/parser.py | 11 | ||||
| -rw-r--r-- | neb/std/types.py | 28 | ||||
| -rw-r--r-- | neb/structs.py | 11 |
4 files changed, 53 insertions, 3 deletions
diff --git a/neb/lexer.py b/neb/lexer.py index 5b3fff1..e9142bb 100644 --- a/neb/lexer.py +++ b/neb/lexer.py @@ -21,7 +21,7 @@ keywords = { WHITESPACE = [" ", "\n", "\t"] -SEPARATORS = WHITESPACE + [")", "]"] +SEPARATORS = WHITESPACE + [")", "]", "}"] DIGITS = list("0123456789") def lex(data): @@ -51,6 +51,10 @@ def lex(data): tokens.append(Token(TokenType.OPEN_BRACKET, "[", None, line)) elif char == "]": tokens.append(Token(TokenType.CLOSE_BRACKET, "]", None, line)) + elif char == "{": + tokens.append(Token(TokenType.OPEN_BRACE, "{", None, line)) + elif char == "}": + tokens.append(Token(TokenType.CLOSE_BRACE, "}", None, line)) elif char == ":": tokens.append(Token(TokenType.COLON, ":", None, line)) # numbers diff --git a/neb/parser.py b/neb/parser.py index 930e77e..81f7672 100644 --- a/neb/parser.py +++ b/neb/parser.py @@ -160,6 +160,17 @@ def parseType(token, prev, tokens): 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 + + elif tokens[0].type_ == TokenType.OPEN_BRACE: + # 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_BRACE: + raise ParseError("invalid type definition (expecting close brace)", tokens[1+counter].line) + return Type(":{}", 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 7e77597..cc40066 100644 --- a/neb/std/types.py +++ b/neb/std/types.py @@ -62,6 +62,32 @@ islist_multi = MultiFunction("list?") islist_multi.register(islist_func) TYPES.register("list?", islist_multi) +def interpretIsNonEmptyList(symbol, args, env, ns): + + # if it's not a list, we're done + if not (isinstance(args[0], List) or isinstance(args[0], Expr)): + return Bool(False) + + # if it's empty, we're done + elif len(args[0].args) == 0: + 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_type = env.get(f"{inner.name}") + for arg in args[0].args: + valid = inner_type.validate_type(arg, env, ns) + if valid.value is False: + return Bool(False) + return Bool(True) + + def interpretIsString(symbol, args, env, ns): return Bool(isinstance(args[0], String)) @@ -142,6 +168,7 @@ literal_type = NebType(":literal", any_type, interpretIsLiteral) string_type = NebType(":string", literal_type, interpretIsString) #list_type = NebType(":list", any_type, interpretIsList) bracket_type = NebType(":[]", any_type, interpretIsList) +brace_type = NebType(":{}", any_type, interpretIsNonEmptyList) bool_type = NebType(":bool", literal_type, interpretIsBool) number_type = NebType(":number", literal_type, interpretIsNumber) int_type = NebType(":int", number_type, interpretIsInt) @@ -154,6 +181,7 @@ TYPES.register(":literal", literal_type) TYPES.register(":string", string_type) #TYPES.register(":list", list_type) TYPES.register(":[]", bracket_type) +TYPES.register(":{}", brace_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 51cdb34..8c643b5 100644 --- a/neb/structs.py +++ b/neb/structs.py @@ -13,6 +13,8 @@ class TokenType(Enum): CLOSE_PAREN = auto() OPEN_BRACKET = auto() CLOSE_BRACKET = auto() + OPEN_BRACE = auto() + CLOSE_BRACE = auto() EOF = auto() @@ -111,10 +113,15 @@ class Type: return f":[:any]" else: return f":[{self.inner}]" + elif self.name == ":{}": + if self.inner is None: + return ":{:any}" + else: + return ":{" + f"{self.inner}" + "}" else: return self.name -_native_types = ":any :literal :string :bool :number :int :float :[] :handle :type" +_native_types = ":any :literal :string :bool :number :int :float :[] :{} :handle :type" ALL_TYPES = {x: Type(x) for x in _native_types.split(" ")} class Symbol: @@ -151,7 +158,7 @@ class NebFuncDef: class Expr: def __init__(self, args): self.args = args - self.type_ = ALL_TYPES[":[]"] # TODO no it's not + self.type_ = ALL_TYPES[":{}"] # TODO no it's not def __str__(self): return "(" + " ".join(f"{arg}" for arg in self.args) + ")" |
