from reconstruct.ast import ast_node from reconstruct.storage import ColRef from engine.types import * class expr(ast_node): name='expr' def __init__(self, parent, node, *, c_code = None): from reconstruct.ast import projection self.type = None self.raw_col = None self.inside_agg = False self.is_special = False if(type(parent) is expr): self.inside_agg = parent.inside_agg if(type(parent) is not expr): self.root = self self.c_code = type(parent) is projection else: self.root = parent.root self.c_code = parent.c_code if type(c_code) is bool: self.c_code = c_code ast_node.__init__(self, parent, node, None) def init(self, _): from reconstruct.ast import projection parent = self.parent self.isvector = parent.isvector if type(parent) is expr else False self.is_compound = parent.is_compound if type(parent) is expr else False if type(parent) in [projection, expr]: self.datasource = parent.datasource else: self.datasource = self.context.datasource self.udf_map = parent.context.udf_map self.func_maps = {**builtin_func, **self.udf_map} self.operators = {**builtin_operators, **self.udf_map} def produce(self, node): from engine.utils import enlist if type(node) is dict: for key, val in node.items(): if key in self.operators: op = self.operators[key] val = enlist(val) exp_vals = [expr(self, v, c_code = self.c_code) for v in val] str_vals = [e.sql for e in exp_vals] type_vals = [e.type for e in exp_vals] self.type = op.return_type(*type_vals) self.sql = op(self.c_code, *str_vals) special_func = [*self.context.udf_map.keys(), "maxs", "mins", "avgs", "sums"] if key in special_func and not self.is_special: self.is_special = True p = self.parent while type(p) is expr and not p.is_special: p.is_special = True p = p.parent else: print(f'Undefined expr: {key}{val}') elif type(node) is str: p = self.parent while type(p) is expr and not p.isvector: p.isvector = True p = p.parent if self.datasource is not None: self.raw_col = self.datasource.parse_col_names(node) self.raw_col = self.raw_col if type(self.raw_col) is ColRef else None if self.raw_col is not None: self.sql = self.raw_col.name self.type = self.raw_col.type else: self.sql = node self.type = StrT if self.c_code and self.datasource is not None: self.sql = f'{{y(\"{self.sql}\")}}' elif type(node) is bool: self.type = IntT if self.c_code: self.sql = '1' if node else '0' else: self.sql = 'TRUE' if node else 'FALSE' else: self.sql = f'{node}' if type(node) is int: self.type = LongT elif type(node) is float: self.type = DoubleT def finalize(self, y): if self.c_code: x = self.is_special self.sql = eval('f\'' + self.sql + '\'') def __str__(self): return self.sql def __repr__(self): return self.__str__() def eval(self): x = self.c_code y = lambda x: x return eval('f\'' + self.sql + '\'') import engine.expr as cexpr