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()))
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")
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)
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")
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() + "'")
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)
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)
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_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)
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_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))
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")
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)