def test_python_backend_unit(operation, operation_string): symbol_table = { 'A': ast.SymbolNode(ast.NodeSymbol.ARRAY, (), None, (4, )), 'B': ast.SymbolNode(ast.NodeSymbol.ARRAY, (), None, (3, )) } tree = ast.Node((operation, ), (3, 4), (), (ast.Node( (ast.NodeSymbol.ARRAY, ), (3, 4), ('A', ), ()), ast.Node((ast.NodeSymbol.ARRAY, ), (3, 4), ('B', ), ()))) context = ast.create_context(ast=tree, symbol_table=symbol_table) expected_source = f'(A {operation_string} B)' assert expected_source == backend.generate_python_source(context)
def p_arguments(p): ''' arguments : arguments comma_tok expr | expr | ''' if len(p) == 1: # <-- arguments: <blank>; adds an empty node to the AST p[0] = ast.Node() elif len(p) == 2: # <-- arguments: expr; adds 'expr' to a node in the AST p[0] = ast.Node([p[1]]) else: p[1].children.append( p[3] ) # <-- arguments: arguments comma expr; appends 'expr' to the children of the node of the 'arguments' p[0] = p[1]
def _parse_lambda(self): node = ast.Node(ast.LAMBDA) self._add_parameters(node, first_is_value=False) node.add(self._parse_body(node)) return node
def _add_parameters(self, node, first_is_value=False): """ Assumes position is after first '(', reads tokens and verifies them until end of tokens or ')' Adds valid tokens to specified node and raises on invalid """ t = self._next_token() if not t.type == token.BLOCKSTART: self._raise("Expected (") t = self._next_token() found_value = False while not t.type == token.BLOCKEND: if not t: self._raise("Expected more") if not t.type == token.SYMBOL: self._raise("Expected symbol") if first_is_value and not found_value: node.value = t.value found_value = True else: node.add(ast.Node(ast.PARAMETER, value=t.value)) t = self._next_token() if first_is_value and not found_value: self._raise("Expected name")
def _parse_define(self): definition = ast.Node(ast.DEFINITION) t = self._next_token() if t.type == token.SYMBOL: definition.value = t.value self._children(self._next_token(), definition) return definition else: self._raise('Illegal definition, needs name!')
def p_statements(p): ''' statements : statement | statements statement ''' if len( p ) == 2: # <-- statements : statement; adds statement into a Node in the AST p[0] = ast.Node([p[1]]) else: # <-- statements : statements statement; appends 'statement' to the children of node 'statements' p[1].children.append(p[2]) p[0] = p[1]
def parse(self): self.root = ast.Node(ast.ROOT) t = self._next_token() while t: if t.type == token.BLOCKEND: self._raise('Too many )?') elif t.type == token.BLOCKSTART: self.root.add(self._begin()) else: self.root.add(self._convert(t)) t = self._next_token() return self.root
def _parse_body(self, node): body = ast.Node(ast.BODY) t = self._next_token() while t: if t.type == token.BLOCKEND: break if t.type == token.BLOCKSTART: body.add(self._begin()) else: body.add(self._convert(t)) t = self._next_token() return body
def _begin(self): t = self._next_token() if t.type == token.SYMBOL: value = t.value parser = self._keyword_parsers.get(value) if parser: return parser() if t.type in (token.SYMBOL, token.OPERATOR, token.BLOCKSTART): application = ast.Node(ast.APPLICATION) self._children(t, application) return application if self._is_atom(t.type): self._raise("Cannot evaluate atom as function") self._raise("Do not know what to do 2")
def test_python_backend_materialize_scalar(): symbol_table = { 'A': ast.SymbolNode(ast.NodeSymbol.ARRAY, (), None, (4, )), 'B': ast.SymbolNode(ast.NodeSymbol.ARRAY, (), None, (3, )) } tree = ast.Node((ast.NodeSymbol.OR, ), (), (), (ast.Node((ast.NodeSymbol.LESSTHAN, ), (), (), (ast.Node( (ast.NodeSymbol.ARRAY, ), (), ('A', ), ()), ast.Node((ast.NodeSymbol.ARRAY, ), (), ('B', ), ()))), ast.Node((ast.NodeSymbol.EQUAL, ), (), (), (ast.Node((ast.NodeSymbol.ARRAY, ), (), ('B', ), ()), ast.Node((ast.NodeSymbol.ARRAY, ), (), ('A', ), ()))))) context = ast.create_context(ast=tree, symbol_table=symbol_table) assert backend.generate_python_source( context, materialize_scalars=True) == '((4 < 3) or (3 == 4))'
def _convert_string(self, t): return ast.Node(ast.STRING, value=t.value)
def _convert_number(self, t): return ast.Node(ast.NUMBER, value=int(t.value))
def _convert_operator(self, t): return ast.Node(ast.SYMBOL, value=t.value)
def _convert_symbol(self, t): return ast.Node(ast.SYMBOL, value=t.value)
(ast.NodeSymbol.ARRAY, ), (3, 4), ('A', ), ()), ast.Node((ast.NodeSymbol.ARRAY, ), (3, 4), ('B', ), ()))) context = ast.create_context(ast=tree, symbol_table=symbol_table) expected_source = f'(A {operation_string} B)' assert expected_source == backend.generate_python_source(context) @pytest.mark.parametrize('symbol_table, tree, expected_source', [ ({ 'A': ast.SymbolNode(ast.NodeSymbol.ARRAY, (), None, (4, )), 'B': ast.SymbolNode(ast.NodeSymbol.ARRAY, (), None, (3, )) }, ast.Node((ast.NodeSymbol.GREATERTHANEQUAL, ), (), (), (ast.Node((ast.NodeSymbol.ARRAY, ), (), ('A', ), ()), ast.Node((ast.NodeSymbol.PLUS, ), (), (), (ast.Node( (ast.NodeSymbol.ARRAY, ), (), ('A', ), ()), ast.Node((ast.NodeSymbol.ARRAY, ), (), ('B', ), ()))))), '(A >= (A + B))'), ({ 'A': ast.SymbolNode(ast.NodeSymbol.ARRAY, (), None, (4, )), 'B': ast.SymbolNode(ast.NodeSymbol.ARRAY, (), None, (3, )) }, ast.Node((ast.NodeSymbol.AND, ), (), (), (ast.Node((ast.NodeSymbol.LESSTHAN, ), (), (), (ast.Node( (ast.NodeSymbol.ARRAY, ), (), ('A', ), ()), ast.Node((ast.NodeSymbol.ARRAY, ), (), ('B', ), ()))), ast.Node((ast.NodeSymbol.EQUAL, ), (), (), (ast.Node( (ast.NodeSymbol.ARRAY, ), (), ('B', ), ()), ast.Node((ast.NodeSymbol.ARRAY, ), (), ('A', ), ()))))), '((A < B) and (B == A))'), ({