Ejemplo n.º 1
0
    def concat_string_templates(self, fake_tree, orig_node, string_objs):
        """
        Concatenates the to-be-inserted string templates.
        For example, a string template like "a{exp}b" gets flatten to:
            "a" + fake_path_to_exp as string + "b"

        Strings can be inserted directly, but string templates must be
        evaluated to new AST nodes and the reference to their fake_node
        assignment should be used instead.
        """
        ks = []
        for s in string_objs:
            if s['$OBJECT'] == 'string':
                # plain string -> insert directly
                str_node = self.build_string_value(orig_node=orig_node,
                                                   text=s['string'])
                string_tree = Tree('expression', [
                    Tree('entity', [
                        str_node
                    ])
                ])
                string_tree.kind = 'primary_expression'
                ks.append(string_tree)
            else:
                assert s['$OBJECT'] == 'code'
                # string template -> eval
                # ignore newlines in string interpolation
                code = ''.join(s['code'].split('\n'))

                evaled_node = self.eval(orig_node, code, fake_tree)

                # cast to string (`as string`)
                base_type = orig_node.create_token('STRING_TYPE', 'string')
                as_operator = Tree('as_operator', [
                    Tree('types', [
                        Tree('base_type', [
                            base_type
                        ])
                    ])
                ])
                as_tree = Tree('expression', [
                    Tree('expression', [
                        Tree('entity', [
                            evaled_node
                        ]),
                    ]),
                    as_operator
                ])
                as_tree.kind = 'pow_expression'
                as_tree.child(0).kind = 'primary_expression'
                ks.append(as_tree)

        return ks
Ejemplo n.º 2
0
    def add_strings(n1, *other_nodes):
        """
        Create an AST for concating two or more nodes.
        """
        # concatenation is currently defined as
        # expression = expression arith_operator expression
        base_tree = Tree("expression", [n1])
        base_tree.kind = "arith_expression"

        # if we only got one node, no concatenation is required. return
        # directly
        if len(other_nodes) == 0:
            return base_tree.children[0]

        base_tree.children.append(
            Tree("arith_operator", [n1.create_token("PLUS", "+")]),
        )

        # Technically, the grammar only supports binary expressions, but
        # the compiler and engine can handle n-ary expressions, so we can
        # directly flatten the tree and add all additional nodes as extra
        # expressions
        for n2 in other_nodes:
            base_tree.children.append(n2)
        return base_tree
Ejemplo n.º 3
0
    def concat_string_templates(self, fake_tree, orig_node, string_objs):
        """
        Concatenates the to-be-inserted string templates.
        For example, a string template like "a{exp}b" gets flatten to:
            "a" + fake_path_to_exp as string + "b"

        Strings can be inserted directly, but string templates must be
        evaluated to new AST nodes and the reference to their fake_node
        assignment should be used instead.
        """
        ks = []
        for s in string_objs:
            if s["$OBJECT"] == "string":
                # plain string -> insert directly
                str_node = self.build_string_value(
                    orig_node=orig_node, text=s["string"]
                )
                string_tree = Tree("expression", [Tree("entity", [str_node])])
                string_tree.kind = "primary_expression"
                ks.append(string_tree)
            else:
                assert s["$OBJECT"] == "code"
                # string template -> eval
                # ignore newlines in string interpolation
                code = "".join(s["code"].split("\n"))

                evaled_node = self.eval(orig_node, code, fake_tree)

                # cast to string (`as string`)
                base_type = orig_node.create_token("STRING_TYPE", "string")
                to_operator = Tree(
                    "to_operator",
                    [Tree("types", [Tree("base_type", [base_type])])],
                )
                as_tree = Tree(
                    "expression",
                    [
                        Tree("expression", [Tree("entity", [evaled_node]),]),
                        to_operator,
                    ],
                )
                as_tree.kind = "pow_expression"
                as_tree.child(0).kind = "primary_expression"
                ks.append(as_tree)

        return ks