def test_symbol_call(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        st.registerSymbol('a', integer)

        # call in scope
        self.assertEqual(type(st.getSymbol('a').basetype), IntegerType)

        # call in nested scope
        st.openScope()
        self.assertEqual(type(st.getSymbol('a').basetype), IntegerType)

        # define in nested scope
        st.registerSymbol('a', character)

        # call in nested scope
        self.assertEqual(type(st.getSymbol('a').basetype), CharacterType)

        # call original in main scope
        st.closeScope()
        self.assertEqual(type(st.getSymbol('a').basetype), IntegerType)
    def test_function_label(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        # Create arguments
        argumentsList = ArgumentsList()
        argumentsList.add(Argument('a', integer))
        argumentsList.add(Argument('b', real))

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(Parameter(ConstantExpression(3.14, 'float')))

        # Register basic function, no arguments
        st.registerFunction('add', integer, argumentsList, True)

        # Check for label
        self.assertEqual(st.getFunction('add', parametersList).label, 'add0')

        # Check for label in scope
        st.openScope()
        st.registerFunction('add', integer, argumentsList, True)
        self.assertEqual(st.getFunction('add', parametersList).label, 'add1')
        st.closeScope()
    def test_not_registered_symbol_call(self):
        st = SymbolTable()
        integer = IntegerType()

        self.assertRaises(SymbolNotRegisteredError, lambda: st.getSymbol('a'))

        # open scope and register
        st.openScope()
        st.registerSymbol('a', integer)
        st.closeScope()

        self.assertRaises(SymbolNotRegisteredError, lambda: st.getSymbol('a'))
    def test_register_symbols_nested(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        st.registerSymbol('a', integer)

        st.openScope()
        st.registerSymbol('a', real)

        st.openScope()
        st.registerSymbol('a', boolean)

        st.openScope()
        st.registerSymbol('a', character)

        # Check
        self.assertEqual(type(st.getSymbol('a').basetype), CharacterType)

        st.closeScope()

        self.assertEqual(type(st.getSymbol('a').basetype), BooleanType)

        st.closeScope()

        self.assertEqual(type(st.getSymbol('a').basetype), RealType)

        st.closeScope()

        self.assertEqual(type(st.getSymbol('a').basetype), IntegerType)
    def test_scope_allocated(self):
        st = SymbolTable()

        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()
        address = AddressType(integer)

        array = ArrayType(integer, 10)

        st.registerSymbol('a', integer)
        st.registerSymbol('b', real)
        st.registerSymbol('c', boolean)
        st.registerSymbol('d', character)
        st.registerSymbol('e', address)

        self.assertEqual(st.scope.allocated, 5)
        self.assertEqual(st.scope.getTotalAllocated(), 5)

        st.openScope()
        st.registerSymbol('a', integer)
        st.registerSymbol('b', real)
        st.registerSymbol('c', boolean)
        st.registerSymbol('d', character)
        st.registerSymbol('e', address)

        self.assertEqual(st.scope.allocated, 5)
        self.assertEqual(st.scope.getTotalAllocated(), 5)
        st.closeScope()

        self.assertEqual(st.scope.allocated, 5)
        self.assertEqual(st.scope.getTotalAllocated(), 10)
        st.registerSymbol('f', array)

        self.assertEqual(st.scope.allocated, 15)
        self.assertEqual(st.scope.getTotalAllocated(), 20)
    def test_function_scoped(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        # Create arguments
        argumentsList = ArgumentsList()
        argumentsList.add(Argument('a', integer))
        argumentsList.add(Argument('b', real))

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(Parameter(ConstantExpression(3.14, 'float')))

        # Register basic function, no arguments
        st.registerFunction('add', integer, argumentsList, True)

        # Call function in main scope
        self.assertEqual(type(st.getFunction('add', parametersList)), Function)

        # open scope and get function again
        st.openScope()
        self.assertEqual(type(st.getFunction('add', parametersList)), Function)

        # register function in scope
        st.registerFunction('divide', integer, argumentsList, True)

        # call new function in scope
        self.assertEqual(type(st.getFunction('add', parametersList)), Function)

        # close scope and call new created function, shouldn't work
        st.closeScope()
        self.assertRaises(FunctionNotRegisteredError,
                          lambda: st.getFunction('divide', parametersList))

        # open scope and register add again
        st.openScope()
        st.registerFunction('add', integer, argumentsList, True)
        self.assertEqual(type(st.getFunction('add', parametersList)), Function)
        self.assertRaises(
            FunctionAlreadyRegisteredError,
            lambda: st.registerFunction('add', integer, argumentsList, True))
        st.closeScope()

        # register function in higher scope and call in lower scope
        st.registerFunction('multiply', integer, argumentsList, True)
        st.openScope()
        self.assertEqual(type(st.getFunction('multiply', parametersList)),
                         Function)
        self.assertRaises(
            FunctionNotRegisteredError,
            lambda: st.getFunction('multiplynotexisting', parametersList))
        st.closeScope
 def test_open_and_close_scope(self):
     st = SymbolTable()
     st.openScope()
     st.closeScope()
 def test_close_too_much_scopes(self):
     st = SymbolTable()
     st.openScope()
     st.closeScope()
     self.assertRaises(ScopeError, lambda: st.closeScope())