def eq(self, other): with logger.context("EQ STRING") as log: if not isinstance(other, String): raise UnsupportedOperationError( f"Cannot compare (==) {self} and {other}") result = factory().types.Bool(str(self.text == other.text)) log(f"{self} == {other} => {logger.emphasize(result)}") return result
def _compare(left, right, accepted_types, log_msg, symbol, operation): with logger.context(log_msg) as log: if not any(isinstance(right, t) for t in accepted_types): raise UnsupportedOperationError( f"Cannot compare: {left} {symbol} {right}") result = factory().types.Bool(str(operation())) log(f"{left} {symbol} {right} => {logger.emphasize(result)}") return result
def and_(self, other): with logger.context("AND BOOL") as log: if not isinstance(other, Bool): raise UnsupportedOperationError( f"Cannot compare (&&) {self} and {other}") result = factory().types.Bool(str(other.val and self.val)) log(f"{self} && {other} => {logger.emphasize(result)}") return result
def eval(self): with logger.context("FUNC CALL") as log: log(str(self)) # Grab the function function = self.atom.eval() # Assert arg count if len(function.variables) != len(self.arguments): start = "Too few" if len(function.variables) > len( self.arguments) else "Too many" raise FunctionError( f"{start} arguments passed for function {self.atom}, " f"expected {len(function.variables)}, but got {len(self.arguments)}" ) # Eval all args args = [arg.eval() for arg in self.arguments] # Create a new BlockingFrame for this function call STACK.push(BlockingFrame()) try: # Create all new variables on that frame for var, arg in zip(function.variables, args): var.assign(arg) # Execute the function try: function.code.eval() except ReturnSignal as r: result = r.payload else: result = factory().types.Null() log(f"{self._format(function.name, args)} => {logger.emphasize(result)}" ) return result finally: STACK.pop()
def eval(self): with logger.context("POST DECREMENT") as log: log(str(self)) val = self.assignable.eval() self.assignable.assign(val.sub(factory().types.Int(1))) return val
def mod_float(self, left): with logger.context("CONV FLOAT") as log: self_float = factory().types.Float(self.val) log(f"{left} % {self} => {left} % {logger.emphasize(self_float)}") return self_float.mod_float(left)
def add_float(self, left): with logger.context("ADD FLOAT") as log: res = factory().types.Float(left.val + self.val) log(f"{left} + {self} => {logger.emphasize(res)}") return res
def eval(self): return factory().types.Array([item.eval() for item in self.items])
def eval(self): return factory().types.String(self.val)
def eval(self): return factory().types.Bool(self.val)
def eval(self): return factory().types.Float(self.val)
def eval(self): return factory().types.Null()
def index(self, index): if not isinstance(index, Int): raise UnsupportedOperationError( f"Cannot index into String with index {index}") return factory().types.String(self.text[index.val])
def not_(self): with logger.context("NOT BOOL") as log: result = factory().types.Bool(str(not self.val)) log(f"!{self} => {logger.emphasize(result)}") return result
def to_int(self): return factory().types.Int(self.val)
def negate(self): return factory().types.Int(-self.val)
def div_int(self, left): with logger.context("CONV FLOAT") as log: left_float = factory().types.Float(left.val) log(f"{left} / {self} => {logger.emphasize(left_float)} / {self}") return self.div_float(left_float)
def mul_float(self, left): with logger.context("MUL FLOAT") as log: res = factory().types.Float(left.val * self.val) log(f"{left} * {self} => {logger.emphasize(res)}") return res
def eval(self): with logger.context("PRE INCREMENT") as log: log(str(self)) val = self.assignable.eval().add(factory().types.Int(1)) self.assignable.assign(val) return val
def length(self): return factory().types.Int(len(self.text))
def eval(self): return factory().types.Int(self.val)
def length(self): return factory().types.Int(len(self.items))
def __str__(self): return str(factory().types.Float(self.val))
def sub_int(self, left): with logger.context("SUB INT") as log: res = factory().types.Int(left.val - self.val) log(f"{left} - {self} => {logger.emphasize(res)}") return res
def __str__(self): return str(factory().types.Bool(self.val))
def div_int(self, left): with logger.context("DIV INT") as log: res = factory().types.Int(left.val // self.val) log(f"{left} / {self} => {logger.emphasize(res)}") return res
def __str__(self): return str(factory().types.String(self.val))
def mod_int(self, left): with logger.context("MOD INT") as log: res = factory().types.Int(left.val % self.val) log(f"{left} % {self} => {logger.emphasize(res)}") return res
def __str__(self): return str(factory().types.Array(self.items))
def to_float(self): return factory().types.Float(self.val)