def pops(self, var=None, stack=False): if self.dataStack == []: raise ib.MissingValue( "instruction POPS cannot be executed: data stack is empty") if stack == True: popSymb = self.dataStack.pop(-1) return popSymb varIndex, varFound = self.foundVar(var, False) popSymb = self.dataStack.pop(-1) if popSymb[0] == '': raise ib.MissingValue("unitialized variable") self.isInitialized(var) self.setTypeValue(var[0], varIndex, popSymb[0], popSymb[1])
def setchar(self, var, symb1, symb2): varIndex, varFound = self.foundVar(var, False) symb1Index, symb1Found = self.foundVar(symb1, True) symb2Index, symb2Found = self.foundVar(symb2, True) self.isInitialized(var) if varFound[0] == '' or symb1Found[0] == '' or symb2Found[0] == '': raise ib.MissingValue("unitialized variable") if varFound[0] == 'string' and symb1Found[0] == 'int' and symb2Found[ 0] == 'string': try: if symb1Found[2] < 0: raise ib.StringError( "Index error, in function SETCHAR index '{0}' is out of range of '{1}'" .format(symb1Found[2], varFound[2])) varFound[2][symb1Found[2]] #just to raise exception result = varFound[2][:symb1Found[2]] + symb2Found[2][ 0] + varFound[2][symb1Found[2] + 1:] self.setTypeValue(var[0], varIndex, 'string', result) except (IndexError, TypeError): raise ib.StringError( "Index error, in function SETCHAR index '{0}' is out of range of '{1}'" .format(symb1Found[2], varFound[2])) else: raise ib.WrongArgTypes( "SETCHAR needs variable of type string, first symbol of type int, second symbol of type string" )
def stri2Int(self, var, symb1, symb2, stack=False): if stack == False: varIndex, varFound = self.foundVar(var, False) else: symb2 = self.pops(None, True) symb1 = self.pops(None, True) symb1Index, symb1Found = self.foundVar(symb1, True) symb2Index, symb2Found = self.foundVar(symb2, True) if stack == False: self.isInitialized(var) if symb1Found[0] == '' or symb2Found[0] == '': raise ib.MissingValue("unitialized variable") if symb1Found[0] != 'string': raise ib.WrongArgTypes( "STRI2INT needs symbol 1 of type 'string', not '%s'" % symb1Found[0]) if symb2Found[0] != 'int': raise ib.WrongArgTypes( "STRI2INT needs symbol 2 of type int, not '%s'" % symb2Found[0]) try: if symb2Found[2] < 0: raise ib.StringError( "Could not decode string in STRI2INT, '{1}' index is outside the given string '{0}'" .format(symb1Found[2], symb2Found[2])) if stack == False: self.setTypeValue(var[0], varIndex, 'int', ord(symb1Found[2][symb2Found[2]])) else: self.pushs(['int', ord(symb1Found[2][symb2Found[2]])]) except (TypeError, IndexError, ValueError): raise ib.StringError( "Could not decode string in STRI2INT, '{1}' index is outside the given string '{0}'" .format(symb1Found[2], symb2Found[2]))
def move(self, var, symb): varIndex, varFound = self.foundVar(var, False) symbIndex, symbFound = self.foundVar(symb, True) if symbFound[ 0] == '': #this means that no type was previously specified raise ib.MissingValue("unitialized variable") self.isInitialized(var) self.setTypeValue(var[0], varIndex, symbFound[0], symbFound[2])
def strlen(self, var, symb): varIndex, varFound = self.foundVar(var, False) symbIndex, symbFound = self.foundVar(symb, True) self.isInitialized(var) if symbFound[0] == '': raise ib.MissingValue("unitialized variable") if symbFound[0] == 'string' and symbFound[2] != None: self.setTypeValue(var[0], varIndex, 'int', len(symbFound[2])) else: raise ib.WrongArgTypes("STRLEN needs string argument.")
def concat(self, var, symb1, symb2): varIndex, varFound = self.foundVar(var, False) symb1Index, symb1Found = self.foundVar(symb1, True) symb2Index, symb2Found = self.foundVar(symb2, True) self.isInitialized(var) if symb1Found[0] == '' or symb2Found[0] == '': raise ib.MissingValue("unitialized variable") if symb1Found[0] == 'string' and symb2Found[0] == 'string': self.setTypeValue(var[0], varIndex, 'string', symb1Found[2] + symb2Found[2]) else: raise ib.WrongArgTypes("CONCAT needs two string arguments.")
def logical(self, op, var, symb1, symb2=[], stack=False): if stack == False: varIndex, varFound = self.foundVar(var, False) else: if op != 'NOT': symb2 = self.pops(None, True) symb1 = self.pops(None, True) symb1Index, symb1Found = self.foundVar(symb1, True) symb2Found = ['bool', ["nothing"]] #just because of 'NOT' uses only 2 args if stack == False: self.isInitialized(var) if op != 'NOT': symb2Index, symb2Found = self.foundVar(symb2, True) if symb1Found[0] == '' or symb2Found[0] == '': raise ib.MissingValue("unitialized variable") if op == 'NOT' and symb1Found[0] != 'bool': raise ib.WrongArgTypes( "Logical operations need bool type, not '{0}'('{1}')".format( symb1Found[2], symb1Found[0])) elif symb1Found[0] != 'bool' or symb2Found[0] != 'bool': raise ib.WrongArgTypes( "Logical operations need bool type, not '{0}'('{1}') '{2}'('{3}')" .format(symb1Found[2], symb1Found[0], symb2Found[2], symb2Found[0])) result = '' #final result which will be in the var, or pushed to dataStack if op == 'AND': if symb1Found[2] == 'true' and symb2Found[2] == 'true': result = True else: result = False elif op == 'OR': if symb1Found[2] == 'true' or symb2Found[2] == 'true': result = True else: result = False elif op == 'NOT': if symb1Found[2] == 'true': result = False else: result = True if result == True: if stack == False: self.setTypeValue(var[0], varIndex, 'bool', 'true') else: self.pushs(['bool', 'true']) elif result == False: if stack == False: self.setTypeValue(var[0], varIndex, 'bool', 'false') else: self.pushs(['bool', 'false'])
def instrExit(self, symb): symbIndex, symbFound = self.foundVar(symb, True) if symbFound[0] == '': raise ib.MissingValue("unitialized variable") if symbFound[0] != 'int': raise ib.WrongArgTypes( "value for EXIT should be int in range 0-49, not '%s'" % symbFound[2]) elif (symbFound[2] < 0 or symbFound[2] > 49): raise ib.WrongValue( "value for EXIT should be int in range 0-49, not '%s'" % symbFound[2]) else: return symbFound[2]
def write(self, symb): symbIndex, symbFound = self.foundVar(symb, True) if symbFound[0] == '': raise ib.MissingValue("unitialized variable") if symbFound[0] == 'nil': print('', end='') elif symbFound[0] == 'bool': if symbFound[2] == 'true': print('true', end='') else: print('false', end='') elif symbFound[0] == 'int': print(symbFound[2], end='') elif symbFound[0] == 'float': print(float.hex(symbFound[2]), end='') elif symbFound[0] == 'string': print(symbFound[2], end='')
def float2Int(self, var, symb, stack=False): if stack == False: varIndex, varFound = self.foundVar(var, False) else: symb = self.pops(None, True) varIndex, varFound = self.foundVar(var, False) symbIndex, symbFound = self.foundVar(symb, True) if stack == False: self.isInitialized(var) if symbFound[0] == '': raise ib.MissingValue("unitialized variable") if symbFound[0] != 'float': raise ib.WrongArgTypes( "FLOAT2INT needs variable of type float, not '%s'" % symbFound[0]) try: if stack == False: self.setTypeValue(var[0], varIndex, 'int', int(symbFound[2])) else: self.pushs(['int', int(symbFound[2])]) except (ValueError, TypeError): raise ib.WrongValue("Could not convert Float to Int")
def getchar(self, var, symb1, symb2): varIndex, varFound = self.foundVar(var, False) symb1Index, symb1Found = self.foundVar(symb1, True) symb2Index, symb2Found = self.foundVar(symb2, True) self.isInitialized(var) if symb1Found[0] == '' or symb2Found[0] == '': raise ib.MissingValue("unitialized variable") if symb1Found[0] == 'string' and symb2Found[0] == 'int': try: if symb2Found[2] < 0: raise ib.StringError( "Index error, in function GETCHAR index '{0}' is out of range of '{1}'" .format(symb2Found[2], symb1Found[2])) self.setTypeValue(var[0], varIndex, 'string', symb1Found[2][symb2Found[2]]) except IndexError: raise ib.StringError( "Index error, in function GETCHAR index '{0}' is out of range of '{1}'" .format(symb2Found[2], symb1Found[2])) else: raise ib.WrongArgTypes( "GETCHAR needs first argument string, second arguments int.")
def condJumps(self, op, symb1, symb2, stack=False): if stack == True: symb2 = self.pops(None, True) symb1 = self.pops(None, True) symb1Index, symb1Found = self.foundVar(symb1, True) symb2Index, symb2Found = self.foundVar(symb2, True) if symb1Found[0] == '' or symb2Found[0] == '': raise ib.MissingValue("unitialized variable") if symb1Found[0] != symb2Found[0]: if symb1Found[0] == 'nil' or symb2Found[0] == 'nil': pass else: raise ib.WrongArgTypes( "different types for relational instructions, '{0}'('{1}') '{2}'('{3}')" .format(symb1Found[2], symb1Found[0], symb2Found[2], symb2Found[0])) if symb1Found[2] == 'nil' or symb2Found[2] == 'nil': if symb1Found[2] == symb2Found[2]: if op == 'JUMPIFEQ': return True else: return False else: if op == 'JUMPIFEQ': return False else: return True else: if symb1Found[2] == symb2Found[2]: if op == 'JUMPIFEQ': return True else: return False else: if op == 'JUMPIFEQ': return False else: return True
def int2Char(self, var, symb, stack=False): if stack == False: varIndex, varFound = self.foundVar(var, False) else: symb = self.pops(None, True) symbIndex, symbFound = self.foundVar(symb, True) if stack == False: self.isInitialized(var) if symbFound[0] == '': raise ib.MissingValue("unitialized variable") if symbFound[0] != 'int': raise ib.WrongArgTypes( "INT2CHAR needs variable of type int, not '%s'" % symbFound[0]) try: if stack == False: self.setTypeValue(var[0], varIndex, 'string', chr(symbFound[2])) else: self.pushs(['string', chr(symbFound[2])]) except (UnicodeEncodeError, ValueError, OverflowError): raise ib.StringError( "UnicodeEncodeError. Could not encode string in INT2CHAR, '%s' value is invalid" % symbFound[2])
def calculate(self, op, var, symb1, symb2, stack=False): if stack == False: varIndex, varFound = self.foundVar(var, False) else: symb2 = self.pops(None, True) symb1 = self.pops(None, True) symb1Index, symb1Found = self.foundVar(symb1, True) symb2Index, symb2Found = self.foundVar(symb2, True) if stack == False: self.isInitialized(var) if symb1Found[0] == '' or symb2Found[0] == '': raise ib.MissingValue("unitialized variable") if symb1Found[0] != 'int' and symb1Found[0] != 'float': if symb1Found[1] == []: varOrSymb = 'symb' else: varOrSymb = 'var: ' + symb1Found[1] raise ib.WrongArgTypes( "operand ({3})'{0}' of type '{1}' is not of the correct type for operation '{2}'" .format(symb1Found[2], symb1Found[0], op, varOrSymb)) if symb2Found[0] != 'int' and symb2Found[0] != 'float': if symb2Found[1] == []: varOrSymb = 'symb' else: varOrSymb = 'var: ' + symb2Found[1] raise ib.WrongArgTypes( "operand ({3})'{0}' of type '{1}' is not of the correct type for operation '{2}'" .format(symb2Found[2], symb2Found[0], op, varOrSymb)) if (symb1Found[0] == 'int' and symb2Found[0] == 'int') or (symb1Found[0] == 'float' and symb2Found[0] == 'float'): pass else: raise ib.WrongArgTypes( "Could not execute {2}. Operands ({1})'{0}' and ({4})'{3}' should be both of the same type - No implicit conversions" .format(symb1Found[2], symb1Found[0], op, symb2Found[2], symb2Found[0])) if op == 'ADD' or op == 'ADDS': if isinstance(symb1Found[2] + symb2Found[2], int): if stack == False: self.setTypeValue(var[0], varIndex, 'int', symb1Found[2] + symb2Found[2]) else: self.pushs(['int', symb1Found[2] + symb2Found[2]]) else: if stack == False: self.setTypeValue(var[0], varIndex, 'float', symb1Found[2] + symb2Found[2]) else: self.pushs(['float', symb1Found[2] + symb2Found[2]]) elif op == 'SUB' or op == 'SUBS': if isinstance(symb1Found[2] - symb2Found[2], int): if stack == False: self.setTypeValue(var[0], varIndex, 'int', symb1Found[2] - symb2Found[2]) else: self.pushs(['int', symb1Found[2] - symb2Found[2]]) else: if stack == False: self.setTypeValue(var[0], varIndex, 'float', symb1Found[2] - symb2Found[2]) else: self.pushs(['float', symb1Found[2] - symb2Found[2]]) elif op == 'MUL' or op == 'MULS': if isinstance(symb1Found[2] * symb2Found[2], int): if stack == False: self.setTypeValue(var[0], varIndex, 'int', symb1Found[2] * symb2Found[2]) else: self.pushs(['int', symb1Found[2] * symb2Found[2]]) else: if stack == False: self.setTypeValue(var[0], varIndex, 'float', symb1Found[2] * symb2Found[2]) else: self.pushs(['float', symb1Found[2] * symb2Found[2]]) elif op == 'IDIV' or op == 'IDIVS': try: if isinstance(symb1Found[2] // symb2Found[2], int): if stack == False: self.setTypeValue(var[0], varIndex, 'int', symb1Found[2] // symb2Found[2]) else: self.pushs(['int', symb1Found[2] // symb2Found[2]]) else: if stack == False: self.setTypeValue(var[0], varIndex, 'float', symb1Found[2] // symb2Found[2]) else: self.pushs(['float', symb1Found[2] + symb2Found[2]]) except ZeroDivisionError: raise ib.WrongValue("Zero division error") elif op == 'DIV' or op == 'DIVS': try: if stack == False: self.setTypeValue(var[0], varIndex, 'float', symb1Found[2] / symb2Found[2]) else: self.pushs(['float', symb1Found[2] / symb2Found[2]]) except ZeroDivisionError: raise ib.WrongValue("Zero division error")
def dprint(self, symb): symbIndex, symbFound = self.foundVar(symb, True) if symbFound[0] == '': raise ib.MissingValue("unitialized variable") sys.stderr.write("%s" % symbFound[2])
def conditions(self, op, var, symb1, symb2, stack=False): if stack == False: varIndex, varFound = self.foundVar(var, False) else: symb2 = self.pops(None, True) symb1 = self.pops(None, True) symb1Index, symb1Found = self.foundVar(symb1, True) symb2Index, symb2Found = self.foundVar(symb2, True) if stack == False: self.isInitialized(var) if symb1Found[0] == '' or symb2Found[0] == '': raise ib.MissingValue("unitialized variable") if symb1Found[0] != symb2Found[0] or (symb1Found[0] == 'nil' or symb2Found[0] == 'nil'): if op == 'EQ' and (symb1Found[0] == 'nil' or symb2Found[0] == 'nil'): pass else: raise ib.WrongArgTypes( "different types for relational instructions, '{0}'('{1}') '{2}'('{3}')" .format(symb1Found[2], symb1Found[0], symb2Found[2], symb2Found[0])) if symb1Found[0] == 'bool': if symb1Found[2] == 'true': symb1Found[2] = True else: symb1Found[2] = False if symb2Found[0] == 'bool': if symb2Found[2] == 'true': symb2Found[2] = True else: symb2Found[2] = False result = '' #final result which will be in the var, or pushed to dataStack if op == 'LT': if symb1Found[2] < symb2Found[2]: result = True else: result = False elif op == 'GT': if symb1Found[2] > symb2Found[2]: result = True else: result = False elif op == 'EQ': if symb1Found[2] == 'nil' or symb2Found[2] == 'nil': if symb1Found[2] == symb2Found[2]: result = True else: result = False else: if symb1Found[2] == symb2Found[2]: result = True else: result = False if result == True: if stack == False: self.setTypeValue(var[0], varIndex, 'bool', 'true') else: self.pushs(['bool', 'true']) elif result == False: if stack == False: self.setTypeValue(var[0], varIndex, 'bool', 'false') else: self.pushs(['bool', 'false'])
def pushs(self, symb): symbIndex, symbFound = self.foundVar(symb, True) appendSymb = [symbFound[0], symbFound[2]] if symbFound[0] == '': raise ib.MissingValue("unitialized variable") self.dataStack.append(appendSymb)