diff options
Diffstat (limited to 'neb')
| -rw-r--r-- | neb/__init__.py | 28 | ||||
| -rw-r--r-- | neb/parser.py | 11 | ||||
| -rw-r--r-- | neb/std/types.py | 32 | ||||
| -rw-r--r-- | 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: +        # [ <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 | 
