<commit_before>from rtruffle.source_section import SourceSection

from som.compiler.ast.method_generation_context import MethodGenerationContext
from som.compiler.parse_error import ParseError
from som.compiler.parser import ParserBase
from som.compiler.symbol import Symbol

from som.interpreter.ast.nodes.block_node import BlockNode, BlockNodeWithContext
from som.interpreter.ast.nodes.global_read_node import create_global_node
from som.interpreter.ast.nodes.literal_node import LiteralNode
from som.interpreter.ast.nodes.message.super_node import (
    UnarySuper,
    BinarySuper,
    TernarySuper,
    NArySuper,
)
from som.interpreter.ast.nodes.message.uninitialized_node import (
    UninitializedMessageNode,
)
from som.interpreter.ast.nodes.return_non_local_node import ReturnNonLocalNode
from som.interpreter.ast.nodes.sequence_node import SequenceNode

from som.vmobjects.array import Array
from som.vmobjects.string import String


class Parser(ParserBase):
    def __init__(self, reader, file_name, universe):
        ParserBase.__init__(self, reader, file_name, universe)
        self._source_reader = reader

    def _get_source_section(self, coord):
        return SourceSection(
            self._source_reader,
            "method",
            coord,
            self._lexer.get_number_of_characters_read(),
            self._file_name,
        )

    def _assign_source(self, node, coord):
        node.assign_source_section(self._get_source_section(coord))
        return node

    def _method_block(self, mgenc):
        self._expect(Symbol.NewTerm)
        method_body = self._block_contents(mgenc)
        self._expect(Symbol.EndTerm)
        return method_body

    def _block_body(self, mgenc, _seen_period):
        coordinate = self._lexer.get_source_coordinate()
        expressions = []

        while True:
            if self._accept(Symbol.Exit):
                expressions.append(self._result(mgenc))
                return self._create_sequence_node(coordinate, expressions)
            if self._sym == Symbol.EndBlock:
                return self._create_sequence_node(coordinate, expressions)
            if self._sym == Symbol.EndTerm:
                # the end of the method has been found (EndTerm) - make it
                # implicitly return "self"
                self_exp = self._variable_read(mgenc, "self")
                self_coord = self._lexer.get_source_coordinate()
                self._assign_source(self_exp, self_coord)
                expressions.append(self_exp)
                return self._create_sequence_node(coordinate, expressions)

            expressions.append(self._expression(mgenc))
            self._accept(Symbol.Period)

    def _create_sequence_node(self, coordinate, expressions):
        if not expressions:
            nil_exp = create_global_node(
                self.universe.sym_nil,
                self.universe,
                None,
                self._get_source_section(coordinate),
            )
            return nil_exp
        if len(expressions) == 1:
            return expressions[0]

        return SequenceNode(expressions[:], self._get_source_section(coordinate))

    def _result(self, mgenc):
        exp = self._expression(mgenc)
        coord = self._lexer.get_source_coordinate()

        self._accept(Symbol.Period)

        if mgenc.is_block_method:
            node = ReturnNonLocalNode(
                mgenc.get_outer_self_context_level(), exp, self.universe
            )
            mgenc.make_catch_non_local_return()
            return self._assign_source(node, coord)
        return exp

    def _assignation(self, mgenc):
        return self._assignments(mgenc)
<commit_msg>Use LiteralNode(nil) for empty blocks<commit_after>from rtruffle.source_section import SourceSection

from som.compiler.ast.method_generation_context import MethodGenerationContext
from som.compiler.parse_error import ParseError
from som.compiler.parser import ParserBase
from som.compiler.symbol import Symbol

from som.interpreter.ast.nodes.block_node import BlockNode, BlockNodeWithContext
from som.interpreter.ast.nodes.literal_node import LiteralNode
from som.interpreter.ast.nodes.message.super_node import (
    UnarySuper,
    BinarySuper,
    TernarySuper,
    NArySuper,
)
from som.interpreter.ast.nodes.message.uninitialized_node import (
    UninitializedMessageNode,
)
from som.interpreter.ast.nodes.return_non_local_node import ReturnNonLocalNode
from som.interpreter.ast.nodes.sequence_node import SequenceNode

from som.vmobjects.array import Array
from som.vmobjects.string import String


class Parser(ParserBase):
    def __init__(self, reader, file_name, universe):
        ParserBase.__init__(self, reader, file_name, universe)
        self._source_reader = reader

    def _get_source_section(self, coord):
        return SourceSection(
            self._source_reader,
            "method",
            coord,
            self._lexer.get_number_of_characters_read(),
            self._file_name,
        )

    def _assign_source(self, node, coord):
        node.assign_source_section(self._get_source_section(coord))
        return node

    def _method_block(self, mgenc):
        self._expect(Symbol.NewTerm)
        method_body = self._block_contents(mgenc)
        self._expect(Symbol.EndTerm)
        return method_body

    def _block_body(self, mgenc, _seen_period):
        coordinate = self._lexer.get_source_coordinate()
        expressions = []

        while True:
            if self._accept(Symbol.Exit):
                expressions.append(self._result(mgenc))
                return self._create_sequence_node(coordinate, expressions)
            if self._sym == Symbol.EndBlock:
                return self._create_sequence_node(coordinate, expressions)
            if self._sym == Symbol.EndTerm:
                # the end of the method has been found (EndTerm) - make it
                # implicitly return "self"
                self_exp = self._variable_read(mgenc, "self")
                self_coord = self._lexer.get_source_coordinate()
                self._assign_source(self_exp, self_coord)
                expressions.append(self_exp)
                return self._create_sequence_node(coordinate, expressions)

            expressions.append(self._expression(mgenc))
            self._accept(Symbol.Period)

    def _create_sequence_node(self, coordinate, expressions):
        if not expressions:
            from som.vm.globals import nilObject

            return LiteralNode(nilObject)
        if len(expressions) == 1:
            return expressions[0]

        return SequenceNode(expressions[:], self._get_source_section(coordinate))

    def _result(self, mgenc):
        exp = self._expression(mgenc)
        coord = self._lexer.get_source_coordinate()

        self._accept(Symbol.Period)

        if mgenc.is_block_method:
            node = ReturnNonLocalNode(
                mgenc.get_outer_self_context_level(), exp, self.universe
            )
            mgenc.make_catch_non_local_return()
            return self._assign_source(node, coord)
        return exp

    def _assignation(self, mgenc):
        return self._assignments(mgenc)

{'fraction_non_alphanumeric': 0.07626059174885401, 'fraction_numerical': 0.0005556327267676066, 'mean_word_length': 2.6809815950920246, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5262235', 'n_tokens_mistral': 2007, 'n_tokens_neox': 1975, 'n_words': 396}