def __init__(self, name: str = None, local_id: int = None, temp: 'Temp' = None, position: Position = Position(0, 0), unique_id: int = -1): IExp.__init__(self, position) if local_id is None and temp is None: self.id = Temp.counter Temp.counter += 1 self.local_id = 0 self.name = name self.info_enum = InfoEnum.NAME self.unique = unique_id != -1 if self.unique: self.id = unique_id self.local_id = unique_id elif name is None and temp is None: self.id = Temp.counter Temp.counter += 1 self.local_id = local_id self.name = '' self.info_enum = InfoEnum.ID self.unique = False elif name is None and local_id is None: self.id = temp.id self.local_id = temp.local_id self.name = temp.name self.info_enum = temp.info_enum self.position = temp.position self.unique = temp.unique
def __init__(self, func_expr: IExp, args: ExpList, position: Position = Position(0, 0)): IExp.__init__(self, position) self.func_expr = func_expr self.args = args
def __init__(self, operation, expression: IExp, position: Position = Position(0, 0)): IExp.__init__(self, position) self.operation = operation self.expression = expression
def __init__(self, destination: IExp, source: IExp, position: Position = Position(0, 0)): IStm.__init__(self, position) self.source = source self.destination = destination
def __init__(self, head: IExp = None, tail: IExp = None, position=Position(0, 0)): IExp.__init__(self, position) self.head = head self.tail = tail
def add_method_to_scope(self, method_name: str, position: Position = Position(0, 0)): """ Отвечает за добавление метода в текущий Scope по его названию :param method_name: название метода :param position: расположение метода :return: """ self._add_method_to_scope(self.get_method(method_name, position))
def fill_table(self, program: Program): """ Отвечает за обход AST и заполнение таблицы :param program: корень AST (class Program) :return: """ program.accept(self) if self.verbose: for class_name in self.table.classes_names: try: class_info = self.table.get_class(class_name, Position(0, 0)) self.table.add_class_to_scope(class_name, Position(0, 0)) if self.verbose: self._print_class_info(class_info) self.table.free_last_scope() print() except SyntaxError as error: print(error)
def get_class(self, class_name: str, position: Position = Position(0, 0)) -> ClassInfo: """ Отвечает за получение информации о классе по его названию и расположению :param class_name: название класса :param position: расположение класса :return: """ class_info = self.classes_block.get(class_name) if class_info is not None: return class_info raise SyntaxError(f'Not declared class {class_name} requested! Position {position}')
def __init__(self, head: IStm = None, tail: IStm = None, position=Position(0, 0)): IStm.__init__(self, position) self.head = head self.tail = tail #ExpList: List[IExp] = list #StmList: List[IStm] = list
def __init__(self, jump_type_enum: JumpTypeEnum, condition_left_expression: IExp, condition_right_expression: IExp, true_label: Label, position: Position = Position(0, 0)): IStm.__init__(self, position) self.true_label = true_label self.condition_left_expression = condition_left_expression self.condition_right_expression = condition_right_expression self.jump_type_enum = jump_type_enum
def get_method(self, method_name: str, position: Position = Position(0, 0)) -> MethodInfo: """ Отвечает за получение информации о методе по его названию и расположению :param method_name: название метода :param position: расположение метода :return: """ for block in reversed(self.blocks): methods_block = block.methods_block result = methods_block.get(method_name) if result is not None: return result raise SyntaxError(f'Not declared method {method_name} requested! Position {position}')
def get_variable(self, variable_name: str, position: Position = Position(0, 0)) -> VariableInfo: """ Отвечает за получение информации о переменной по ее названию и расположению :param variable_name: название переменной :param position: расположение переменной :return: """ for block in reversed(self.blocks): variables_block = block.variables_block result = variables_block.get(variable_name) if result is not None: return result raise SyntaxError(f'Not declared variable {variable_name} requested! Position {position}')
def does_type_have_super(self, class_info: ClassInfo, super_class_name: str, position: Position = Position(0, 0)) -> bool: """ Проверяет, является ли класс наследником другого класса :param class_info: название класса :param super_class_name: название предполагаемого базового класса :param position: позиция, на которой произошел вызов :return: """ while class_info.super_class_name is not None: if class_info.super_class_name == super_class_name: return True class_info = self.get_class(class_info.super_class_name, position) return False
def verify_class(self, class_info: ClassInfo, position: Position = Position(0, 0)): """ Отвечает за проверку класса на циклическую зависимость :param class_info: информация о проверяемом классе :param position: расположение проверяемого класса :return: """ classes_in_graph = set() class_to_check = class_info while class_to_check.super_class_name is not None: class_to_check = self.get_class(class_to_check.super_class_name, position) if class_to_check in classes_in_graph: raise SyntaxError(f'Cyclic dependency of class {class_to_check.name}! Position {class_info.position}') classes_in_graph.add(class_info) for class_info in classes_in_graph: self.verified_classes.add(class_info)
def add_class_to_scope(self, class_name: str, position: Position = Position(0, 0)): """ Отвечает за добавление класса в текущий Scope по его названию :param class_name: название класса :param position: расположение класса :return: """ class_to_add = self.get_class(class_name, position) if class_to_add.name not in self.verified_classes: self.verify_class(class_to_add, position) classes_stack = [class_to_add] while class_to_add.super_class_name is not None: class_to_add = self.get_class(class_to_add.super_class_name, position) classes_stack.append(class_to_add) for class_info in classes_stack: self._add_class_to_scope(class_info)
def fill(self): """ Отвечает за вывод задания по записям активации Заполняет фрейм, словно был вызов метода на пустом стеке :return: """ assert self.filled is not True class_names = self.table.classes_names for class_name in class_names: position = Position(0, 0) self.table.add_class_to_scope(class_name, position) class_info = self.table.get_class(class_name, position) methods_names = class_info.methods_names for method in methods_names: method_info = self.table.get_method(method, position) frame = X86MiniJavaFrame() this_variable = VariableInfo(THIS_NAME, position, class_info.type_info) frame.add_formal(this_variable) for arg_info in method_info.args_block: frame.add_formal(arg_info) for var_info in method_info.vars_block: frame.add_local(var_info) frame.add_address_exit() self.print(f'Method name: {method_info.name}') activation = frame.find_local_or_formal(THIS_NAME) self.print(f'this: {activation.print(frame.FP())}') for arg_name in method_info.args_names: activation = frame.find_local_or_formal(arg_name) self.print( f'{arg_name}: {activation.print(TempAddress(0))}') self.print(f'FP: {frame.FP().get_address()}') for var_name in method_info.vars_names: activation = frame.find_local_or_formal(var_name) self.print(f'{var_name}: {activation.print(frame.FP())}') self.print(f'SP: {frame.SP().get_address()}') self.print( f'Return address: {frame.return_address.print(TempAddress(0))}' ) self.print( f'Exit address: {frame.exit_address().print(TempAddress(0))}' ) self.print('- - - - - - - - - - - - -') self.print('') self.table.free_last_scope() self.filled = True
def create_frame(class_info: ClassInfo, method_info: MethodInfo): """ Отвечает за создание и заполнении фрейма на основании данных о классе и методе :param class_info: :param method_info: :return: """ frame = X86MiniJavaFrame() this_variable = VariableInfo(THIS_NAME, Position(0, 0), class_info.type_info) frame.add_formal(this_variable) for arg_info in method_info.args_block: frame.add_formal(arg_info) for var_info in method_info.vars_block: frame.add_local(var_info) frame.add_address_exit() frame.add_address_return_value(method_info.return_type) return frame
def _print_class_info(self, class_info: ClassInfo): """ Отвечает за вывод информации о классе на экран :param class_info: информация о классе, который будет выведен :return: """ print(f'class {class_info.name} {class_info.position}') if class_info.super_class_name is not None: print(f'extends {class_info.super_class_name}') self.table.get_class(class_info.super_class_name, Position(0, 0)) print(f' fields:') for var_name in class_info.vars_names: variable_info = self.table.get_variable(var_name, Position(0, 0)) print(f' {self._format_variable_info(variable_info)}') for method_name in class_info.methods_names: method_info = self.table.get_method(method_name, Position(0, 0)) self.table.add_method_to_scope(method_info.name, Position(0, 0)) access_modifier = 'public' if method_info.access_modifier == AccessModifierEnum.Public else 'private' print( f' func {access_modifier} {method_info.name} {method_info.position}' ) if method_info.get_args_count() > 0: print(f' arguments:') for arg_name in method_info.args_names: arg_info = self.table.get_variable(arg_name, Position(0, 0)) print( f' {self._format_variable_info(arg_info)}') if method_info.get_vars_count() > 0: print(f' local variables:') for var_name in method_info.vars_names: variable_info = self.table.get_variable( var_name, Position(0, 0)) print( f' {self._format_variable_info(variable_info)}' ) self.table.free_last_scope()
def __init__(self, label: Label, position: Position = Position(0, 0)): IStm.__init__(self, position) self.label_name = label
def __init__(self, value: int, position: Position = Position(0, 0)): IExp.__init__(self, position) self.value = value
def __init__(self, operation: BinopEnum, left_expression: IExp, right_expression: IExp, position: Position = Position(0, 0)): IExp.__init__(self, position) self.operation = operation self.left_expression = left_expression self.right_expression = right_expression
def __init__(self, statement: IStm, expression: IExp, position: Position = Position(0, 0)): IExp.__init__(self, position) self.statement = statement self.expression = expression
def __init__(self, position: Position = Position(0, 0)): INode.__init__(self, position)
def __init__(self, expression: IExp, position: Position = Position(0, 0)): IStm.__init__(self, position) self.expression = expression
def __init__(self, name: str = None, position: Position = Position(0, 0)): IExp.__init__(self, position) if str is None: self.label_name = Label.get_next_enumerated_label() else: self.label_name = Label.get_label(name)