def _concat_or_add(operator, left, right): if isinstance(left, numbers.Number) and isinstance(right, numbers.Number): return float(left) + float(right) elif isinstance(left, str) and isinstance(right, str): return left + right else: raise LoxRuntimeError(operator, "Operands must be two numbers or two strings.")
def get(self, name): # of type Token """get name in current scope or outer scope""" if name.lexeme in self.values.keys(): return self.values.get(name.lexeme) if self.enclosing is not None: return self.enclosing.get(name) raise LoxRuntimeError(name, "Undefined variable " + name.lexeme + ".")
def visit_call(self, expr): callee = self._evaluate(expr.callee) arguments = [] for argument in expr.arguments: arguments.append(self._evaluate(argument)) if not isinstance(callee, LoxCallable): raise LoxRuntimeError(expr.paren, "Can only call function and classes.") function = callee if len(arguments) != function.arity(): raise LoxRuntimeError( expr.paren, "Expected" + str(function.arity()) + "arguments but got {len(arguments)} .") return function.call(self, arguments)
def assign(self, name, value): # name of type Token """The key difference between assignment and definition is that assignment is not allowed to create a new variable.""" if name.lexeme in self.values: self.values[name.lexeme] = value return if self.enclosing is not None: self.enclosing.values[name.lexeme] = value return raise LoxRuntimeError(name, "Undefined variable " + name.lexeme + ".")
def _check_number_operands(operator, left, right): if isinstance(left, numbers.Number) and isinstance(right, numbers.Number): return raise LoxRuntimeError(operator, "Operands must be numbers.")
def _check_number_operand(operator, operand): if isinstance(operand, numbers.Number): return raise LoxRuntimeError(operator, "Operand must be a number.")