示例#1
0
    def assignment(self, tree, scope):
        target_symbol = self.path_resolver.path(tree.path)

        tree.expect(target_symbol.can_write(),
                    'readonly_type_assignment',
                    left=target_symbol.name())

        frag = tree.assignment_fragment
        expr_sym = self.resolver.base_expression(frag.base_expression)
        expr_type = expr_sym.type()
        storage_class = expr_sym._storage_class
        if expr_sym.can_write():
            storage_class = self.storage_class_scope

        token = frag.child(0)
        tree.expect('/' not in token.value, 'variables_backslash', token=token)
        tree.expect('/' not in token.value, 'variables_dash', token=token)

        if target_symbol.type() == NoneType.instance():
            if not target_symbol.is_internal():
                frag.base_expression.expect(expr_type != NoneType.instance(),
                                            'assignment_type_none')
            sym = Symbol(target_symbol.name(),
                         expr_type,
                         storage_class=storage_class)
            scope.symbols().insert(sym)
        else:
            tree.expect(target_symbol.type().can_be_assigned(expr_type),
                        'type_assignment_different',
                        target=target_symbol._type,
                        source=expr_type)

        self.visit_children(tree, scope)
示例#2
0
 def return_statement(self, tree, scope):
     assert tree.data == "return_statement"
     with self.scope(tree.scope):
         obj = tree.base_expression
         if obj is None:
             return base_symbol(NoneType.instance()), tree
         return self.resolver.base_expression(tree.base_expression), obj
示例#3
0
    def get_type_instance(cls, ty):
        """
        Maps a type class from the hub SDK to its corresponding TypeClass
        in the compiler.
        """
        assert isinstance(ty, OutputBase), ty
        if isinstance(ty, OutputBoolean):
            return BooleanType.instance()
        if isinstance(ty, OutputInt):
            return IntType.instance()
        if isinstance(ty, OutputFloat):
            return FloatType.instance()
        if isinstance(ty, OutputString):
            return StringType.instance()
        if isinstance(ty, OutputAny):
            return AnyType.instance()
        if isinstance(ty, OutputObject):
            return ObjectType({
                k: cls.get_type_instance(v)
                for k, v in ty.properties().items()
            })
        if isinstance(ty, OutputList):
            return ListType(cls.get_type_instance(ty.elements()), )
        if isinstance(ty, OutputNone):
            return NoneType.instance()
        if isinstance(ty, OutputRegex):
            return RegExpType.instance()
        if isinstance(ty, OutputEnum):
            return StringType.instance()

        assert isinstance(ty, OutputMap), f"Unknown Hub Type: {ty!r}"
        return MapType(
            cls.get_type_instance(ty.keys()),
            cls.get_type_instance(ty.values()),
        )
示例#4
0
 def return_statement(self, tree, scope):
     assert tree.data == 'return_statement'
     self.symbol_resolver.update_scope(scope)
     obj = tree.base_expression
     if obj is None:
         return base_symbol(NoneType.instance()), tree
     return self.resolver.base_expression(tree.base_expression), obj
示例#5
0
    def function_block(self, tree, scope):
        if tree.function_statement.function_output:
            if not self.has_return(tree):
                t = tree.function_statement.function_output
                raise CompilerError('return_required', tree=t)
            for ret in tree.find_data('return_statement'):
                ret_sym, obj = self.return_statement(ret, scope)
                ret_type = ret_sym.type()
                obj.expect(ret_sym.can_write(), 'return_type_readonly',
                           source=ret_type)
                node = obj
                # obj might not have any tokens, e.g. {}
                if obj.line() is None:
                    node = ret

                node.expect(
                    self.return_type.can_be_assigned(ret_type),
                    'return_type_differs',
                    target=self.return_type,
                    source=ret_type
                )
        else:
            # function has no return output, so only `return` may be used
            for ret in tree.find_data('return_statement'):
                ret_sym, obj = self.return_statement(ret, scope)
                ret_type = ret_sym.type()
                # obj might not have any tokens, e.g. {}
                obj.expect(
                    ret_type == NoneType.instance(),
                    'function_without_output_return',
                    return_type=ret_type
                )
示例#6
0
def test_none_op():
    none = NoneType.instance()
    assert none.binary_op(none, Token("MINUS", "-")) is None
    assert none.binary_op(IntType.instance(), Token("MINUS", "-")) is None
    assert none.binary_op(IntType.instance(), Token("PLUS", "+")) is None
    assert none.binary_op(StringType.instance(), Token("PLUS", "+")) is None
    assert none.binary_op(AnyType.instance(), None) is None
示例#7
0
 def function_statement(self, tree, scope):
     """
     Create a new scope _without_ a parent scope for this function.
     Prepopulate the scope with symbols from the function arguments.
     """
     scope = Scope.root()
     return_type = NoneType.instance()
     args = {}
     for c in tree.children[2:]:
         if isinstance(c, Tree) and c.data == "typed_argument":
             name = c.child(0)
             e_sym = self.resolver.types(c.types)
             c.expect(
                 e_sym.type() != ObjectType.instance(),
                 "arg_type_no_object",
                 arg=name,
                 type=e_sym.type(),
             )
             sym = Symbol.from_path(name, e_sym.type())
             scope.insert(sym)
             args[sym.name()] = sym
     # add function to the function table
     function_name = tree.child(1).value
     tree.expect(
         self.module.function_table.resolve(function_name) is None,
         "function_redeclaration",
         name=function_name,
     )
     output = tree.function_output
     if output is not None:
         return_type = self.resolver.types(output.types).type()
         tree.expect(return_type != ObjectType.instance(),
                     "return_type_no_object")
     self.module.function_table.insert(function_name, args, return_type)
     return scope, return_type
示例#8
0
def test_none_op():
    none = NoneType.instance()
    assert none.binary_op(none, Token('MINUS', '-')) is None
    assert none.binary_op(IntType.instance(), Token('MINUS', '-')) is None
    assert none.binary_op(IntType.instance(), Token('PLUS', '+')) is None
    assert none.binary_op(StringType.instance(), Token('PLUS', '+')) is None
    assert none.binary_op(AnyType.instance(), None) is None
示例#9
0
def test_service_output_none(patch, magic):
    patch.init(ServiceTyping)
    patch.object(TypeMappings, "get_type_instance")
    action = magic()
    action.output.return_value = None
    typings = ServiceTyping()
    res = typings.get_service_output(action)
    TypeMappings.get_type_instance.assert_not_called()
    assert res == NoneType.instance()
示例#10
0
 def insert(self, name, args, output=None):
     """
     Insert a new function into the function table.
     """
     assert name not in self.functions
     if output is None:
         output = NoneType.instance()
     fn = Function(name, args, output)
     self.functions[name] = fn
示例#11
0
    def assignment(self, tree, scope):
        lhs_node = tree.path
        target_symbol = self.path_resolver.path(lhs_node)

        # allow rebindable assignments here
        lhs_node.expect(
            target_symbol.can_assign(),
            "readonly_type_assignment",
            left=target_symbol.name(),
        )

        frag = tree.assignment_fragment
        expr_sym = self.resolver.base_expression(frag.base_expression)
        expr_type = expr_sym.type()
        storage_class = expr_sym._storage_class
        if expr_sym.can_write():
            storage_class = self.storage_class_scope

        token = frag.child(0)
        tree.expect("/" not in token.value, "variables_backslash", token=token)
        tree.expect("/" not in token.value, "variables_dash", token=token)

        if target_symbol.type() == NoneType.instance():
            can_assign = self.storage_class_scope.can_assign()
            storage_class = storage_class.declaration_from_symbol(
                rebindable=can_assign)
            if not target_symbol.is_internal():
                frag.base_expression.expect(expr_type != NoneType.instance(),
                                            "assignment_type_none")
            sym = Symbol(target_symbol.name(),
                         expr_type,
                         storage_class=storage_class)
            scope.insert(sym)
        else:
            tree.expect(
                target_symbol.type().can_be_assigned(expr_type),
                "type_assignment_different",
                target=target_symbol._type,
                source=expr_type,
            )

        self.visit_children(tree, scope)
示例#12
0
    def resolve(self, tree, paths):
        val = paths[0]
        if isinstance(val, Token):
            val = val.value
        assert isinstance(val, str)
        symbol = self.scope.resolve(val)

        if self._check_variable_existence:
            tree.expect(symbol is not None, 'var_not_defined', name=paths[0])
        else:
            if symbol is None:
                tree.expect(len(paths) == 1, 'var_not_defined', name=paths[0])
                return Symbol(val, NoneType.instance())

        return symbol.index(paths[1:], tree)
示例#13
0
    def resolve(self, tree, val, paths):
        assert isinstance(val, str)
        symbol = self.scope.resolve(val)

        if self._check_variable_existence:
            tree.expect(symbol is not None, 'var_not_defined', name=val)
        else:
            if symbol is None:
                tree.expect(len(paths) == 0, 'var_not_defined', name=val)
                return Symbol(val, NoneType.instance())

        for p in paths:
            symbol = symbol.index(tree,
                                  name=p.value,
                                  type_=p.type,
                                  kind=p.kind)
        return symbol
 def function_block(self, tree, scope):
     if tree.function_statement.function_output:
         if not self.has_return(tree):
             t = tree.function_statement.function_output
             raise CompilerError('return_required', tree=t)
         for ret in tree.find_data('return_statement'):
             ret_type, obj = self.return_statement(ret, scope)
             obj.expect(self.return_type.can_be_assigned(ret_type),
                        'return_type_differs',
                        target=self.return_type,
                        source=ret_type)
     else:
         # function has no return output, so only `return` may be used
         for ret in tree.find_data('return_statement'):
             ret_type, obj = self.return_statement(ret, scope)
             obj.expect(
                 ret_type == NoneType.instance(),
                 'function_without_output_return',
             )
示例#15
0
def parse_type(type_):
    """
    Parses a type string and returns its parsed type which can be a:
        - BaseType (e.g. `IntType`)
        - TypeSymbol (e.g. `TypeSymbol(A)`)
        - GenericType (e.g. `ListGenericType(TypeSymbol(A))`)
    """
    assert len(type_) > 0
    type_ = type_.strip()
    if type_ == "boolean":
        return BooleanType.instance()
    if type_ == "int":
        return IntType.instance()
    if type_ == "float":
        return FloatType.instance()
    if type_ == "string":
        return StringType.instance()
    if type_ == "time":
        return TimeType.instance()
    if type_ == "none":
        return NoneType.instance()
    if type_ == "regexp":
        return RegExpType.instance()
    if type_ == "any":
        return AnyType.instance()

    if "[" in type_:
        types = []
        for t in parse_type_inner(type_).split(","):
            t2 = parse_type(t)
            types.append(t2)
        if type_.startswith("List["):
            return ListGenericType(types)
        else:
            assert type_.startswith("Map[")
            return MapGenericType(types)

    assert "]" not in type_
    return TypeSymbol(type_)
示例#16
0
    def test_fn():
        nonlocal c
        c = c + 1
        return c

    single_fn = singleton(test_fn)
    assert single_fn() == 1
    assert single_fn() == 1
    assert c == 1


@mark.parametrize('type_,expected', [
    (BooleanType.instance(), 'boolean'),
    (IntType.instance(), 'int'),
    (FloatType.instance(), 'float'),
    (NoneType.instance(), 'none'),
    (AnyType.instance(), 'any'),
    (RegExpType.instance(), 'regexp'),
    (ListType(AnyType.instance()), 'List[any]'),
    (MapType(IntType.instance(), StringType.instance()), 'Map[int,string]'),
])
def test_boolean_str(type_, expected):
    assert str(type_) == expected


def test_none_eq():
    assert NoneType.instance() == NoneType.instance()
    assert NoneType.instance() != IntType.instance()
    assert NoneType.instance() != AnyType.instance()

示例#17
0
        c = c + 1
        return c

    single_fn = singleton(test_fn)
    assert single_fn() == 1
    assert single_fn() == 1
    assert c == 1


@mark.parametrize(
    "type_,expected",
    [
        (BooleanType.instance(), "boolean"),
        (IntType.instance(), "int"),
        (FloatType.instance(), "float"),
        (NoneType.instance(), "none"),
        (AnyType.instance(), "any"),
        (RegExpType.instance(), "regexp"),
        (ListType(AnyType.instance()), "List[any]"),
        (
            MapType(IntType.instance(), StringType.instance()),
            "Map[int,string]",
        ),
        (NullType.instance(), "null"),
    ],
)
def test_boolean_str(type_, expected):
    assert str(type_) == expected


def test_none_eq():
示例#18
0
def test_null_explicit_from():
    assert NullType.instance().explicit_from(NoneType.instance()) is None
    assert (NullType.instance().explicit_from(AnyType.instance()) is
            NullType.instance())
    assert (NullType.instance().explicit_from(IntType.instance()) is
            NullType.instance())
示例#19
0
    ('foo[a, b]   arg:  []', ['foo[a, b]', 'arg:  []']),
    ('foo[a, b] arg:list[int] a2:bar',
     ['foo[a, b]', 'arg:list[int]', 'a2:bar']),
    ('foo[a, b] arg:foo[bar]', ['foo[a, b]', 'arg:foo[bar]']),
    ('foo[bar[abc]] arg:foo[bar]', ['foo[bar[abc]]', 'arg:foo[bar]']),
])
def test_split_args(text, expected):
    assert [*split_type_arguments(text)] == expected


@mark.parametrize('text,expected', [
    ('any', AnyType.instance()),
    ('boolean', BooleanType.instance()),
    ('float', FloatType.instance()),
    ('int', IntType.instance()),
    ('none', NoneType.instance()),
    ('string', StringType.instance()),
    ('time', TimeType.instance()),
    ('A', TypeSymbol('A')),
])
def test_parse_type_base(text, expected):
    t = parse_type(text)
    assert str(t) == str(expected)


@mark.parametrize('text,expected_type,expected_symbols', [
    ('List[int]', ListGenericType, [IntType.instance()]),
    ('List[float]', ListGenericType, [FloatType.instance()]),
    ('Map[int,string]', MapGenericType,
     [IntType.instance(), StringType.instance()]),
    ('List[A]', ListGenericType, [TypeSymbol('A')]),
示例#20
0
    MapType,
    NoneType,
    ObjectType,
    RegExpType,
    StringType,
)
from storyscript.hub.TypeMappings import TypeMappings


@mark.parametrize(
    "expected,hub",
    [
        (BooleanType.instance(), OutputBoolean(data={})),
        (IntType.instance(), OutputInt(data={})),
        (FloatType.instance(), OutputFloat(data={})),
        (NoneType.instance(), OutputNone(data={})),
        (AnyType.instance(), OutputAny(data={})),
        (RegExpType.instance(), OutputRegex(data={})),
        (StringType.instance(), OutputEnum(data={})),
        (
            ListType(AnyType.instance()),
            OutputList(OutputAny.create(), data={}),
        ),
        (
            ListType(IntType.instance()),
            OutputList(OutputInt(data={}), data={}),
        ),
        (
            MapType(IntType.instance(), StringType.instance()),
            OutputMap(OutputInt(data={}), OutputString(data={}), data={}),
        ),
示例#21
0
def test_none_explicit_from():
    assert NoneType.instance().explicit_from(IntType.instance()) is None
    assert NoneType.instance().explicit_from(AnyType.instance()) is None
示例#22
0
    assert parse_type_inner(text) == expected


def test_parse_end_error():
    with raises(AssertionError):
        parse_type_inner("foo[bar")


@mark.parametrize(
    "text,expected",
    [
        ("any", AnyType.instance()),
        ("boolean", BooleanType.instance()),
        ("float", FloatType.instance()),
        ("int", IntType.instance()),
        ("none", NoneType.instance()),
        ("string", StringType.instance()),
        ("time", TimeType.instance()),
        ("A", TypeSymbol("A")),
    ],
)
def test_parse_type_base(text, expected):
    t = parse_type(text)
    assert str(t) == str(expected)


@mark.parametrize(
    "text,expected_type,expected_symbols",
    [
        ("List[int]", ListGenericType, [IntType.instance()]),
        ("List[float]", ListGenericType, [FloatType.instance()]),
示例#23
0
def test_none_assign():
    assert not NoneType.instance().can_be_assigned(IntType.instance())
    assert not NoneType.instance().can_be_assigned(AnyType.instance())
示例#24
0
def test_none_eq():
    assert NoneType.instance() == NoneType.instance()
    assert NoneType.instance() != IntType.instance()
    assert NoneType.instance() != AnyType.instance()