Esempio n. 1
0
    def __init__(self, instructions: List, data_input: IO, stats: Stats):
        # Datovy vstup pro instrukci read.
        self.input = data_input
        # Aktualni pozice v programu.
        self.instruction_pointer = 0
        self.GF: Dict[str, Symbol] = dict()  # Globalni ramec
        self.TF: Dict[str, Symbol] = None  # Docasny ramec.
        self.LF_Stack: List[Dict[str, Symbol]] = list()  # Lokalni ramec.
        self.data_stack: List[Symbol] = list()  # Datovy zasobnik
        self.call_stack: List[int] = list()  # Zasobnik volani
        self.exit_code = 0  # Navratovy kod
        self.stats = stats  # Statistiky

        # <label, instructionPointerPosition>
        self.labels: Dict[str, int] = dict()
        self.instructions: List[instrs.InstructionBase] = list()

        # Detekce navesti
        for instruction in instructions:
            if type(instruction) is instrs.Label:
                if instruction.name.name in self.labels:
                    exit_app(exitCodes.SEMANTIC_ERROR,
                             'Detected label redefinition.', True)

                self.labels.update(
                    {instruction.name.name: len(self.instructions)})
            else:
                self.instructions.append(instruction)
Esempio n. 2
0
    def validate_scope(scope: str):
        """ Kontrola platnosti ramce. """

        if scope != Frames.GLOBAL.value and scope != Frames.LOCAL.value and \
                scope != Frames.TEMPORARY.value:
            exit_app(exitCodes.INVALID_XML_STRUCT,
                     'Invalid scope. ({})'.format(scope), True)
Esempio n. 3
0
    def execute(self, program: Program):
        label: LabelModel = self.args[0]
        if label.name not in program.labels:
            exit_app(exitCodes.SEMANTIC_ERROR,
                     'Undefined label to jump. ({})'.format(label.name), True)

        program.instruction_pointer = program.labels[label.name]
Esempio n. 4
0
    def execute(self, program: Program):
        arg = self.args[0]

        if program.var_exists(arg):
            exit_app(exitCodes.SEMANTIC_ERROR,
                     'DEFVAR\nVariable {} now exists. Cannot redefine.', True)

        program.var_set('DEFVAR', arg, None, True)
Esempio n. 5
0
    def __init__(self, args: List[InstructionArgument], opcode: str):
        if len(self.expected_args) != len(args):
            exit_app(exitCodes.INVALID_XML_STRUCT,
                     'Invalid count of arguments at opcode {}'.format(opcode),
                     True)

        self.opcode = opcode
        self.args = args
Esempio n. 6
0
    def validate_variable_name(name: str, is_label: bool = False):
        """ Kontrola spravnosti nazvu promenne, nebo navesti. """

        if re.compile(r"^[_\-$&%*!?a-zA-Z][_\-$&%*!?a-zA-Z0-9]*$").match(name)\
                is None:
            exit_app(
                exitCodes.INVALID_XML_STRUCT, 'Invalid {} name. ({})'.format(
                    'label' if is_label else 'variable', name), True)
Esempio n. 7
0
    def execute(self, program: Program):
        if len(program.data_stack) == 0:
            exit_app(
                exitCodes.UNDEFINED_VALUE,
                'POPS\nInstruction {}. Data Stack is empty.'.format(
                    self.opcode), True)

        program.var_set('POPS', self.args[0], program.pop_stack(1)[0])
Esempio n. 8
0
    def execute(self, program: Program):
        if program.TF is None:
            exit_app(
                exitCodes.INVALID_FRAME,
                'PUSHFRAME\nInvalid access to undefined temporary frame.',
                True)

        program.LF_Stack.append(program.TF)
        program.TF = None
Esempio n. 9
0
    def execute(self, program: Program):
        string = program.get_symb('STRLEN', self.args[1])

        if not string.is_string():
            exit_app(exitCodes.INVALID_DATA_TYPE, 'STRLEN\nExpected string',
                     True)

        string_length = Symbol(DataTypes.INT, len(string.value))
        program.var_set('STRLEN', self.args[0], string_length)
Esempio n. 10
0
    def execute(self, program: Program):
        symb = program.pop_stack(1)[0]

        if not symb.is_float():
            exit_app(
                exitCodes.INVALID_DATA_TYPE, 'INT2CHAR\nInvalid data type' +
                ' Expected FLOAT in second parameter.')

        symbol = Symbol(DataTypes.INT, int(symb.value))
        program.data_stack.append(symbol)
Esempio n. 11
0
    def execute(self, program: Program):
        symb = program.get_symb('FLOAT2INT', self.args[1])

        if not symb.is_float():
            exit_app(
                exitCodes.INVALID_DATA_TYPE, 'INT2CHAR\nInvalid data type' +
                ' Expected FLOAT in second parameter.')

        symbol = Symbol(DataTypes.INT, int(symb.value))
        program.var_set('FLOAT2INT', self.args[0], symbol)
Esempio n. 12
0
    def execute(self, program: Program):
        symb1 = program.get_symb('JUMPNIFEQ', self.args[1])
        symb2 = program.get_symb('JUMPNIFEQ', self.args[2])

        if symb2.equal_type(symb1.data_type) or symb1.is_nil() or\
                symb2.is_nil():
            if not symb2.equals_value(symb1):
                Jump.execute(self, program)
        else:
            exit_app(exitCodes.INVALID_DATA_TYPE,
                     'JUMPIFEQ\nOperands must have same type.', True)
Esempio n. 13
0
    def execute(self, program: Program):
        symb = program.get_symb('NOT', self.args[1])

        if not symb.is_bool():
            exit_app(
                exitCodes.INVALID_DATA_TYPE,
                'NOT\nInvalid data type. Expected: bool. Have: ({})'.format(
                    symb.data_type.value), True)

        result = Symbol(DataTypes.BOOL, not symb.value)
        program.var_set('NOT', self.args[0], result)
Esempio n. 14
0
    def execute(self, program: Program):
        symb = program.pop_stack(1)[0]

        if not symb.is_bool():
            exit_app(
                exitCodes.INVALID_DATA_TYPE,
                'NOT\nInvalid data type. Expected: bool. Have: ({})'.format(
                    symb.data_type.value), True)

        result = Symbol(DataTypes.BOOL, not symb.value)
        program.data_stack.append(result)
Esempio n. 15
0
    def execute(self, program: Program):
        symb = program.get_symb('EXIT', self.args[0], True)

        if not symb.is_int():
            exit_app(exitCodes.INVALID_DATA_TYPE, 'EXIT\nInvalid exit code',
                     True)
        elif symb.value < 0 or symb.value > 49:
            exit_app(exitCodes.INVALID_OPERAND_VALUE,
                     'EXIT\nInvalid exit code. Allowed range is <0; 49>.',
                     True)
        else:
            program.exit(symb.value)
Esempio n. 16
0
    def get_symb(self,
                 opcode: str,
                 symb: Symbol or Variable,
                 required_value: bool = True):
        result = symb
        if type(symb) is Variable:
            result = self.var_get(opcode, symb)

        if required_value and result is None:
            exit_app(exitCodes.UNDEFINED_VALUE,
                     '{}\nSymbol or variable is undefined.'.format(opcode))

        return result
Esempio n. 17
0
    def execute(self, program: Program):
        symbols = program.pop_stack(2)

        symb2 = symbols[0]
        symb1 = symbols[1]

        if symb2.equal_type(symb1.data_type) or symb1.is_nil() or\
                symb2.is_nil():
            if not symb2.equals_value(symb1):
                Jump.execute(self, program)
        else:
            exit_app(exitCodes.INVALID_DATA_TYPE,
                     'JUMPIFEQS\nOperands must have same type.', True)
Esempio n. 18
0
    def execute(self, program: Program):
        variable = program.var_get('SETCHAR', self.args[0])
        index = program.get_symb('SETCHAR', self.args[1])
        toModify = program.get_symb('SETCHAR', self.args[2])

        if variable is None:
            exit_app(exitCodes.UNDEFINED_VALUE, 'SETCHAR\nUndefined variable.',
                     True)

        if not index.is_int() or not variable.is_string() or\
                not toModify.is_string():
            exit_app(exitCodes.INVALID_DATA_TYPE,
                     'SETCHAR\nExpected: string variable, int, string', True)

        if len(toModify.value) == 0 or index.value >= len(variable.value):
            exit_app(exitCodes.INVALID_STRING_OPERATION,
                     'SETCHAR\nZero length of to modify characters.', True)

        try:
            result = "{}{}{}".format(variable.value[:index.value],
                                     toModify.value[0],
                                     variable.value[index.value + 1:])
            program.var_set('SETCHAR', self.args[0],
                            Symbol(DataTypes.STRING, result))
        except IndexError:
            exit_app(exitCodes.INVALID_STRING_OPERATION,
                     'SETCHAR\nIndex is out of range.', True)
Esempio n. 19
0
    def execute(self, program: Program):
        string = program.get_symb('GETCHAR', self.args[1])
        index = program.get_symb('GETCHAR', self.args[2])

        if not string.is_string() or not index.is_int():
            exit_app(exitCodes.INVALID_DATA_TYPE,
                     'GETCHAR\nExpected string and int', True)

        try:
            result = Symbol(DataTypes.STRING, string.value[index.value])
            program.var_set('GETCHAR', self.args[0], result)
        except IndexError:
            exit_app(exitCodes.INVALID_STRING_OPERATION,
                     'GETCHAR\nIndex out of range.', True)
Esempio n. 20
0
    def var_get(self, opcode: str, var: Variable) -> Symbol:
        """ Ziskani hodnoty promenne. """

        if not self.var_exists(var):
            exit_app(exitCodes.UNDEFINED_VARIABLE,
                     '{}\nVariable {} not exists'.format(opcode,
                                                         var.value), True)

        if var.frame == Frames.TEMPORARY:
            return self.TF[var.value]
        elif var.frame == Frames.GLOBAL:
            return self.GF[var.value]
        elif var.frame == Frames.LOCAL:
            return self.LF_Stack[-1][var.value]
Esempio n. 21
0
    def execute(self, program: Program):
        symb1 = program.get_symb('CONCAT', self.args[1])

        if not symb1.is_string():
            exit_app(exitCodes.INVALID_DATA_TYPE,
                     'CONCAT\nInvalid type at second operand.', True)

        symb2 = program.get_symb('CONCAT', self.args[2])

        if not symb2.is_string():
            exit_app(exitCodes.INVALID_DATA_TYPE,
                     'CONCAT\nInvalid type at third operand.', True)

        result = Symbol(DataTypes.STRING, symb1.value + symb2.value)
        program.var_set('CONCAT', self.args[0], result)
Esempio n. 22
0
    def pop_stack(self, required_count: int):
        """ Ziskani N hodnot ze zasovniku. """

        if len(self.data_stack) < required_count:
            exit_app(
                exitCodes.UNDEFINED_VALUE,
                'Invalid count of required arguments in stack at' +
                ' instruction {}. Count of values in data_stack: {}'.format(
                    self.instructions[self.instruction_pointer].opcode,
                    len(self.data_stack)))

        stack_data = list()
        for i in range(required_count):
            stack_data.append(self.data_stack.pop())

        return stack_data
Esempio n. 23
0
    def execute(self, program: Program):
        symb = program.pop_stack(1)[0]

        if not symb.is_int():
            exit_app(exitCodes.INVALID_DATA_TYPE,
                     'INT2CHARS\nInvalid data type. Expected: int', True)

        try:
            char = chr(symb.value)
        except Exception:
            exit_app(
                exitCodes.INVALID_STRING_OPERATION,
                'INT2CHARS\nInvalid int to char conversion value. {}'.format(
                    symb.value))
        else:
            program.data_stack.append(Symbol(DataTypes.STRING, char))
Esempio n. 24
0
    def var_exists(self, var: Variable):
        """ Kontrola na existenci promenne. """

        if var.frame == Frames.GLOBAL:
            return var.value in self.GF
        elif var.frame == Frames.TEMPORARY:
            if self.TF is None:
                exit_app(exitCodes.INVALID_FRAME,
                         'Temporary frame is unitialized', True)

            return var.value in self.TF
        elif var.frame == Frames.LOCAL:
            if len(self.LF_Stack) == 0:
                exit_app(exitCodes.INVALID_FRAME,
                         'Local frame stack is empty.', True)
            return var.value in self.LF_Stack[-1]
Esempio n. 25
0
    def execute(self, program: Program):
        var = self.args[0]
        symb = program.get_symb('INT2CHAR', self.args[1])

        if not symb.is_int():
            exit_app(exitCodes.INVALID_DATA_TYPE,
                     'INT2CHARS\nInvalid data type. Expected: int', True)

        try:
            char = chr(symb.value)
            program.var_set('INT2CHAR', var, Symbol(DataTypes.STRING, char))
        except Exception:
            exit_app(
                exitCodes.INVALID_STRING_OPERATION,
                'INT2CHAR\nInvalid int to char conversion value. {}'.format(
                    symb.value))
Esempio n. 26
0
    def parse_file(file: IO) -> Dict[int, instructions.InstructionBase]:
        """ Nacteni XML dat z datoveho proudu a zpracovani. 

        Perameters
        ----------
        file: IO
            Vstupni datovy proud.

        Returns
        -------
        Dict[int, instructions.InstructionBase]
            Serazeny slovnik, kde klicem bude obsah XML atributu order.
        """
        try:
            xml_data = parse_xml(file).getroot()
            return InstructionsParser.parse(xml_data)
        except ParseError:
            exit_app(exitCodes.INVALID_XML_FORMAT, 'Invalid XML format.', True)
Esempio n. 27
0
    def var_set(self,
                opcode: str,
                var: Variable,
                value: Symbol,
                create: bool = False):
        """ Nastaveni hodnoty promenne. Pripadne vytvořeni. """

        if not create and not self.var_exists(var):
            exit_app(exitCodes.UNDEFINED_VARIABLE,
                     '{}\nVariable {} not exists'.format(opcode,
                                                         var.value), True)

        if var.frame == Frames.GLOBAL:
            self.GF[var.value] = value
        elif var.frame == Frames.LOCAL:
            self.LF_Stack[-1][var.value] = value
        elif var.frame == Frames.TEMPORARY:
            self.TF[var.value] = value
Esempio n. 28
0
    def parse_arguments(element: Element) -> List[InstructionArgument]:
        """ Nacteni parametru instrukce.

        Parameters
        ----------
        element: Element
            XML element obsahujici data instrukce.
        Returns
        -------
        List[InstructionArgument]
            Pole instanci parametru instrukce.
        """
        arg1 = element.findall('arg1')
        arg2 = element.findall('arg2')
        arg3 = element.findall('arg3')

        if len(arg1) > 1:
            exit_app(exitCodes.INVALID_XML_STRUCT,
                     'Multiple elements named arg1', True)
        elif len(arg2) > 1:
            exit_app(exitCodes.INVALID_XML_STRUCT,
                     'Multiple elements named arg2', True)
        elif len(arg3) > 1:
            exit_app(exitCodes.INVALID_XML_STRUCT,
                     'Multiple elements named arg3', True)

        if len(arg3) > 0 and (len(arg1) == 0 or len(arg2) == 0):
            exit_app(exitCodes.INVALID_XML_STRUCT,
                     'Third argument was set, but first or second missing.',
                     True)
        if len(arg2) > 0 and len(arg1) == 0:
            exit_app(exitCodes.INVALID_XML_STRUCT,
                     'Second argument was set, but first missing.', True)

        args = list()

        if len(arg1) > 0:
            args.append(InstructionsParser.parse_argument(arg1[0]))
        if len(arg2) > 0:
            args.append(InstructionsParser.parse_argument(arg2[0]))
        if len(arg3) > 0:
            args.append(InstructionsParser.parse_argument(arg3[0]))

        return args
Esempio n. 29
0
    def execute(self, program: Program):
        symbols = program.pop_stack(2)
        index = symbols[0]
        string = symbols[1]

        if not string.is_string() or not index.is_int():
            exit_app(
                exitCodes.INVALID_DATA_TYPE,
                'STRI2INTS\nInvalid data type. Expected: string and int.' +
                ' Have: {} and {}'.format(string.data_type.value,
                                          index.data_type.value), True)

        try:
            ordinary = ord(string.value[index.value])
        except IndexError:
            exit_app(exitCodes.INVALID_STRING_OPERATION,
                     'String is out of range.', True)
        else:
            program.data_stack.append(Symbol(DataTypes.INT, ordinary))
Esempio n. 30
0
    def execute(self, program: Program):
        string = program.get_symb('STRI2INT', self.args[1])
        index = program.get_symb('STRI2INT', self.args[2])

        if string is None or not string.is_string(
        ) or index is None or not index.is_int():
            exit_app(
                exitCodes.INVALID_DATA_TYPE,
                'STRI2INT\nInvalid data type. Expected: string and int.' +
                ' Have: {} and {}'.format(string.data_type.value,
                                          index.data_type.value), True)

        try:
            ordinary = ord(string.value[index.value])
            program.var_set('STRI2INT', self.args[0],
                            Symbol(DataTypes.INT, ordinary))
        except IndexError:
            exit_app(exitCodes.INVALID_STRING_OPERATION,
                     'String is out of range.', True)