예제 #1
0
    def assign(self, name, value):
        # Check that variable exists
        if self.scopeAbove:
            if not name.lexeme in self.values:
                self.scopeAbove.assign(name, value)
                return
        else:  # At the global level, if not here than var does not exist
            if not name.lexeme in self.values:
                raise exceptions.RuntimeException(
                    "Line %d Undefined variable %s" % (name.line, name.lexeme))

        # Variable is in this scope
        # Check type
        vtype = self.types[name.lexeme]
        if vtype == "num":
            if not (isinstance(value, int) or isinstance(value, float)):
                raise exceptions.RuntimeException(
                    "Line %d Type error: not num" % name.line)
        if vtype == "str":
            if not isinstance(value, str):
                raise exceptions.RuntimeException(
                    "Line %d Type error: not str" % name.line)
        if vtype == "bool":
            if not isinstance(value, bool):
                raise exceptions.RuntimeException(
                    "Line %d Type error: not bool" % name.line)
        self.values[name.lexeme] = value
예제 #2
0
    def define(self, name, type, value):
        typetok = type
        type = typetok.type

        # Check that value type and vartype match
        # Uninitialized strs are nil, nums are 0 and bools are false
        if value is not None:
            if type.lower() == "str":
                if not isinstance(value, str):
                    raise exceptions.RuntimeException(
                        "Line %d Type error: not str" % typetok.line)
            if type.lower() == "num":
                if not (isinstance(value, int) or isinstance(value, float)):
                    raise exceptions.RuntimeException(
                        "Line %d Type error: not a num" % typetok.line)
            if type.lower() == "bool":
                if not isinstance(value, bool):
                    raise exceptions.RuntimeException(
                        "Line %d Type error not a bool" % typetok.line)
        else:
            if type.lower() == "num":
                value = 0
            elif type.lower() == "bool":
                value = False

        # Save variable type and value
        self.types[name] = type.lower()
        self.values[name] = value
예제 #3
0
    def get(self, name):
        # Look for the variable in our scope/env
        if name.lexeme in self.values:
            # nums and bools can be accessed before being initialized
            # nothing else can
            varval = self.values[name.lexeme]
            vartype = self.types[name.lexeme]
            if (vartype != "num" or vartype != "bool") and \
                    (varval is None):
                raise exceptions.RuntimeException(
                    "Line %d Cannot access uninitialized variable" % name.line)
            return self.values[name.lexeme]

        # Did not find the variable in our scope so go up the chain
        if self.scopeAbove:
            return self.scopeAbove.get(name)

        # Variable is not defined in any scope
        raise exceptions.RuntimeException("Undefined variable " + name.lexeme)
예제 #4
0
    def visitBinary(self, expr):
        """ Evaluate the expressions on the left and right of
        the operator, then perform the operation on them."""
        left = self._evaluate(expr.left)
        right = self._evaluate(expr.right)
        op = str(expr.operator.type)

        # Math operator
        if op == "MINUS":
            self._checkNumbersOperand(expr.operator, left, right)
            return float(left) - float(right)
        if op == "PLUS":
            if isinstance(right, str) and isinstance(left, str):
                return str(left) + str(right)
            if isinstance(right, float) and isinstance(left, float):
                return float(left) + float(right)
            raise exceptions.RuntimeException("Operands must be two numbers"
                                              " or two strings", expr.operator)
        if op == "STAR":
            self._checkNumbersOperand(expr.operator, left, right)
            return float(left) * float(right)
        if op == "SLASH":
            self._checkNumbersOperand(expr.operator, left, right)
            return float(left) / float(right)

        # Comparison operator
        if op == "GREATER":
            self._checkNumbersOperand(expr.operator, left, right)
            return float(left) > float(right)
        if op == "GREATER_EQUAL":
            self._checkNumbersOperand(expr.operator, left, right)
            return float(left) >= float(right)
        if op == "LESS":
            self._checkNumbersOperand(expr.operator, left, right)
            return float(left) < float(right)
        if op == "LESS_EQUAL":
            self._checkNumbersOperand(expr.operator, left, right)
            return float(left) <= float(right)

        # Equality operators
        if op == "BANG_EQUAL":
            return not self._isEqual(left, right)
        if op == "EQUAL_EQUAL":
            return self._isEqual(left, right)
예제 #5
0
 def _checkNumbersOperand(self, op, operand1, operand2):
     if isinstance(operand1, float) and isinstance(operand2, float):
         return
     raise exceptions.RuntimeException("Operands must be numbers!", op)
예제 #6
0
 def _checkNumberOperand(self, op, operand):
     if isinstance(operand, float):
         return
     raise exceptions.RuntimeException("Operand must be a number!", op)