Пример #1
0
    def test_function_register_and_get_no_arguments(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

        # Register basic function, no arguments
        st.registerFunction('hello', integer, ArgumentsList(), True)

        # register function again, shouldn't work
        self.assertRaises(
            FunctionAlreadyRegisteredError, lambda: st.registerFunction(
                'hello', integer, ArgumentsList(), True))

        # register function again with other return type, shouldn't work
        self.assertRaises(
            FunctionAlreadyRegisteredError, lambda: st.registerFunction(
                'hello', boolean, ArgumentsList(), True))

        # get basic function
        self.assertEqual(type(st.getFunction('hello', ParametersList())),
                         Function)

        # get not known function, should not work
        self.assertRaises(FunctionNotRegisteredError,
                          lambda: st.getFunction('add', ParametersList()))
Пример #2
0
    def test_compile_function_statement_no_arguments_no_statements(self):
        function = Function('main', IntegerType(), ArgumentsList(), 0, "main0")
        statement = FunctionStatement(function, [], True)

        self.assertEqual(function.getStaticSize(), 5)
        self.assertEqual(function.getParameterSize(), 0)
        self.assertEqual(statement.compile(), "main0:\nssp 5\nretp\n")
Пример #3
0
    def test_symbol_address_in_function(self):
        st = SymbolTable()

        integer = IntegerType()
        arrayinteger = ArrayType(integer, 3)

        # Create arguments
        argumentsList = ArgumentsList()

        # Create parameters
        parametersList = ParametersList()

        st.registerFunction('main', integer, argumentsList, 0)
        function = st.getFunction('main', parametersList)

        st.openFunctionScope(function)
        st.registerSymbol('a', integer)
        self.assertEqual(st.getSymbol('a').address, 5)
        st.registerSymbol('b', arrayinteger)
        self.assertEqual(st.getSymbol('b').address, 6)
        st.registerSymbol('c', integer)
        self.assertEqual(st.getSymbol('c').address, 9)
        st.closeFunctionScope(function)

        self.assertEqual(function.getStaticSize(), 10)
        self.assertEqual(function.getParameterSize(), 0)
Пример #4
0
    def test_compile_function_arguments_no_statements(self):
        st = SymbolTable()

        integer = IntegerType()
        arrayinteger = ArrayType(integer, 3)

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

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(
            Parameter(
                VariableCallExpression(Symbol('b', arrayinteger, 0), None)))

        st.registerFunction('main', integer, argumentsList, True)
        function = st.getFunction('main', parametersList)
        st.openFunctionScope(function)

        st.closeFunctionScope(function)

        statement = FunctionStatement(function, [], True)

        self.assertEqual(function.getStaticSize(), 9)
        self.assertEqual(function.getParameterSize(), 4)
        self.assertEqual(statement.compile(), "main0:\nssp 9\nretp\n")
Пример #5
0
    def buildIncludeStatement(self, tree):
        """Build Include Statement"""
        # must have 2 children
        if (tree.getChildCount() != 2):
            raise RuntimeError("Invalid include statement: '" +
                               tree.getText() + "'")

        path = tree.getChild(1).getText()
        # check if correct format
        if ((path.startswith('"') and path.endswith('"'))
                or (path.startswith('<') and path.endswith('>'))):
            path = path[1:-1]

            # Let's add some definitions to the symbol table
            if (path == "stdio.h"):
                #printf
                argumentsList = ArgumentsList()
                argumentsList.add(
                    Argument("string",
                             AddressType(ArrayType(CharacterType(), -1))))
                argumentsList.makeUnlimited()

                self.sym.registerFunction('printf', IntegerType(),
                                          argumentsList, True)
                self.sym.registerFunction('scanf', IntegerType(),
                                          argumentsList, True)

            return IncludeStatement(path)
        else:
            raise RuntimeError("Invalid include statement: '" +
                               tree.getText() + "'")
Пример #6
0
    def test_function_register_with_unlimited_arguments(self):
        st = SymbolTable()
        integer = IntegerType()
        real = RealType()
        boolean = BooleanType()
        character = CharacterType()

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

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

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

        # get basic function
        self.assertEqual(type(st.getFunction('printer', parametersList)),
                         Function)
Пример #7
0
    def test_symbol_address_in_function_with_arguments(self):
        st = SymbolTable()

        integer = IntegerType()
        arrayinteger = ArrayType(integer, 3)

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

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(
            Parameter(
                VariableCallExpression(Symbol('b', arrayinteger, 0), None)))

        st.registerFunction('main', integer, argumentsList, True)
        function = st.getFunction('main', parametersList)

        st.openFunctionScope(function)
        self.assertEqual(st.getSymbol('a').address, 5)
        self.assertEqual(st.getSymbol('b').address, 6)
        st.registerSymbol('c', integer)
        self.assertEqual(st.getSymbol('c').address, 9)
        st.registerSymbol('d', arrayinteger)
        self.assertEqual(st.getSymbol('d').address, 10)
        st.registerSymbol('e', integer)
        self.assertEqual(st.getSymbol('e').address, 13)
        st.closeFunctionScope(function)

        self.assertEqual(function.getStaticSize(), 14)
        self.assertEqual(function.getParameterSize(), 4)
Пример #8
0
    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()
Пример #9
0
    def test_function_parameter_size_array_one_element(self):
        st = SymbolTable()
        integer = IntegerType()
        arrayinteger = ArrayType(integer, 3)

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

        # Create array
        st.registerSymbol('b', arrayinteger)

        # Create parameters
        parametersList = ParametersList()
        parametersList.add(Parameter(ConstantExpression(1, 'int')))
        parametersList.add(
            Parameter(VariableCallExpression(st.getSymbol('b'), 1)))

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

        self.assertEqual(function.getParameterSize(), 2)
Пример #10
0
    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
Пример #11
0
    def test_function_register_and_get_with_arguments(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')))

        # fake ParametersList, has one parameters less
        fakeParametersList = ParametersList()
        fakeParametersList.add(Parameter(ConstantExpression(1, 'int')))

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

        # register function again, shouldn't work
        self.assertRaises(
            FunctionAlreadyRegisteredError,
            lambda: st.registerFunction('add', integer, argumentsList, True))

        # register function again with other return type, shouldn't work
        self.assertRaises(
            FunctionAlreadyRegisteredError,
            lambda: st.registerFunction('add', boolean, argumentsList, True))

        # get basic function
        self.assertEqual(type(st.getFunction('add', parametersList)), Function)

        # get not known function, should not work
        self.assertRaises(FunctionNotRegisteredError,
                          lambda: st.getFunction('hello', parametersList))

        # get the function with no arguments, shouldn't work
        self.assertRaises(FunctionNotRegisteredError,
                          lambda: st.getFunction('add', ParametersList()))

        # get the function with wrong arguments, shouldn't work
        self.assertRaises(FunctionNotRegisteredError,
                          lambda: st.getFunction('add', fakeParametersList))
Пример #12
0
    def test_compile_function_no_arguments_statements(self):
        st = SymbolTable()

        integer = IntegerType()
        arrayinteger = ArrayType(integer, 3)

        # Create arguments
        argumentsList = ArgumentsList()

        # Create parameters
        parametersList = ParametersList()

        st.registerFunction('main', integer, argumentsList, True)
        function = st.getFunction('main', parametersList)
        st.openFunctionScope(function)

        st.closeFunctionScope(function)

        statement = FunctionStatement(function, [], True)

        self.assertEqual(function.getStaticSize(), 5)
        self.assertEqual(function.getParameterSize(), 0)
        self.assertEqual(statement.compile(), "main0:\nssp 5\nretp\n")
Пример #13
0
    def buildFunctionStatement(self, tree):
        """Build Function Statement"""
        # basetype IDENTIFIER LPAREN (VOID|basetype IDENTIFIER? (COMMA basetype IDENTIFIER?)*)? RPAREN (SEMICOLON|LBRACE statement* RBRACE)

        # expects at least 4 children
        if (tree.getChildCount() < 5):
            raise RuntimeError("Invalid function statement: '" +
                               tree.getText() + "'")

        returntype = self.buildType(tree.getChild(0))
        identifier = tree.getChild(1).getText()
        arguments = ArgumentsList()
        statements = []
        implemented = True

        # check for LPAREN
        token = tree.getChild(2).getPayload()
        if (not isinstance(token, Token) or token.type != CLexer.LPAREN):
            raise RuntimeError("Invalid function statement: '" +
                               tree.getText() + "'")

        childIndex = 3
        while (True):
            token = tree.getChild(childIndex).getPayload()
            if (isinstance(token, Token)):
                if (token.type == CLexer.RPAREN):
                    # end of parameters list
                    break
                elif (token.type == CLexer.VOID):
                    # Set the type to VOID
                    argumentBasetype = None
                    argumentIdentifier = tree.getChild(childIndex +
                                                       1).getText()
                    if (argumentIdentifier == None):
                        raise RuntimeError("Invalid compund statement: '" +
                                           tree.getText() +
                                           "', no identifier for argument")

                    arguments.add(
                        Argument(argumentIdentifier, argumentBasetype))
                    childIndex += 1
                elif (token.type == CLexer.COMMA):
                    # skip
                    childIndex += 1
                elif (token.type == CLexer.IDENTIFIER):
                    # skip
                    childIndex += 1
            else:
                argumentBasetype = self.buildType(tree.getChild(childIndex))
                argumentIdentifier = tree.getChild(childIndex + 1).getText()
                if (argumentIdentifier == None):
                    raise RuntimeError("Invalid compund statement: '" +
                                       tree.getText() +
                                       "', no identifier for argument")

                arguments.add(Argument(argumentIdentifier, argumentBasetype))
                childIndex += 1

        # check for RPAREN
        token = tree.getChild(childIndex).getPayload()
        if (not isinstance(token, Token) or token.type != CLexer.RPAREN):
            raise RuntimeError("Invalid function statement: '" +
                               tree.getText() + "'")

        function = None

        # Check if SEMICOLON(ready) or LBRACE(parse statements)
        childIndex += 1
        token = tree.getChild(childIndex).getPayload()
        if (not isinstance(token, Token)):
            raise RuntimeError("Invalid function statement: '" +
                               tree.getText() + "'")
        else:
            if (token.type == CLexer.SEMICOLON):
                #ready
                implemented = False
                function = self.sym.registerFunction(identifier, returntype,
                                                     arguments, implemented)
                self.sym.openFunctionScope(function)
                self.sym.closeFunctionScope(function)
                pass
            elif (token.type == CLexer.LBRACE):
                # Register function in symbol table and open scope
                implemented = True
                function = self.sym.registerFunction(identifier, returntype,
                                                     arguments, implemented)
                self.sym.openFunctionScope(function)

                # Parse statements
                childIndex += 1
                while (True):
                    token = tree.getChild(childIndex).getPayload()
                    if (isinstance(token, Token)
                            and token.type == CLexer.RBRACE):
                        # end of CompoundStatement
                        break
                    else:
                        statements.append(
                            self.buildStatement(tree.getChild(childIndex)))
                        childIndex += 1
                # close scope
                self.sym.closeFunctionScope(function)
            else:
                raise RuntimeError("Invalid function statement: '" +
                                   tree.getText() + "'")

        return FunctionStatement(function, statements, implemented)