def resolve_stateful_func(func, args): """Resolve a stateful function given argument expressions. :param func: An instance of StatefulFunc :param args: A list of argument expressions :return: An emit expression and a StateVar list. All expressions have no free variables. """ assert isinstance(func, StatefulFunc) state_var_names = func.statemods.keys() # Mangle state variable names to allow multiple invocations to coexist state_vars_mangled = [Parser.mangle(sv) for sv in state_var_names] mangle_dict = dict(zip(state_var_names, state_vars_mangled)) statemods = [] for name, (init_expr, update_expr) in func.statemods.iteritems(): # Convert state mod references into appropriate expressions update_expr = sexpr.resolve_state_vars(update_expr, # noqa state_var_names, mangle_dict) # Convert argument references into appropriate expressions update_expr = sexpr.resolve_function(update_expr, # noqa dict(zip(func.args, args))) statemods.append(StateVar(mangle_dict[name], init_expr, update_expr)) emit_expr = sexpr.resolve_state_vars(func.sexpr, state_var_names, mangle_dict) return emit_expr, statemods
def resolve_function(p, name, args): """Resolve a function invocation into an Expression instance. :param p: The parser context :param name: The name of the function :type name: string :param args: A list of argument expressions :type args: list of raco.expression.Expression instances :return: An expression with no free variables. """ # try to get function from udf or system defined functions if name in Parser.udf_functions: func = Parser.udf_functions[name] else: func = expr_lib.lookup(name, len(args)) if func is None: raise NoSuchFunctionException(name, p.lineno(0)) if len(func.args) != len(args): raise InvalidArgumentList(name, func.args, p.lineno(0)) if isinstance(func, Function): return sexpr.resolve_function(func.sexpr, dict(zip(func.args, args))) # noqa elif isinstance(func, Apply): state_vars = func.statemods.keys() # Mangle state variable names to allow multiple invocations to # co-exist state_vars_mangled = [Parser.mangle(sv) for sv in state_vars] mangled = dict(zip(state_vars, state_vars_mangled)) for sm_name, (init_expr, update_expr) in func.statemods.iteritems(): # noqa # Convert state mod references into appropriate expressions update_expr = sexpr.resolve_state_vars(update_expr, state_vars, mangled) # noqa # Convert argument references into appropriate expressions update_expr = sexpr.resolve_function(update_expr, dict(zip(func.args, args))) # noqa Parser.statemods.append((mangled[sm_name], init_expr, update_expr)) # noqa return sexpr.resolve_state_vars(func.sexpr, state_vars, mangled) else: assert False
def resolve_function(p, name, args): """Resolve a function invocation into an Expression instance. :param p: The parser context :param name: The name of the function :type name: string :param args: A list of argument expressions :type args: list of raco.expression.Expression instances :return: An expression with no free variables. """ # try to get function from udf or system defined functions if name in Parser.udf_functions: func = Parser.udf_functions[name] else: func = expr_lib.lookup(name, len(args)) if isinstance(func, VariadicFunction): func = func.bind(*args) if func is None: raise NoSuchFunctionException(name, p.lineno(0)) if len(func.args) != len(args): raise InvalidArgumentList(name, func.args, p.lineno(0)) if isinstance(func, Function): return sexpr.resolve_function(func.sexpr, dict(zip(func.args, args))) # noqa elif isinstance(func, StatefulFunc): emit_expr, statemods = Parser.resolve_stateful_func(func, args) Parser.statemods.extend(statemods) # If the aggregate is decomposable, construct local and remote # emitters and statemods. if name in Parser.decomposable_aggs: ds = Parser.decomposable_aggs[name] local_emit, local_statemods = Parser.resolve_stateful_func( ds.local, args) # Problem: we must connect the local aggregate outputs to # the remote aggregate inputs. At this stage, we don't have # enough information to construct argument expressions to # serve as input to the remote aggregate. Instead, we # introduce a placeholder reference, which is referenced # relative to the start of the local aggregate output. remote_args = [sexpr.LocalAggregateOutput(i) for i in range(len(ds.remote.args))] remote_emit, remote_statemods = Parser.resolve_stateful_func( ds.remote, remote_args) # local and remote emitters may be tuple-valued; flatten them. local_emitters = get_emitters(local_emit) remote_emitters = get_emitters(remote_emit) ds = sexpr.DecomposableAggregateState( local_emitters, local_statemods, remote_emitters, remote_statemods) # Associate a decomposable state structure with the first # emitter. Mark the remaining emitters as decomposable, but # without their own associated decomposed emitters and # statemods. emitters = get_emitters(emit_expr) emitters[0].set_decomposable_state(ds) for emt in emitters[1:]: emt.set_decomposable_state( sexpr.DecomposableAggregateState()) return emit_expr else: assert False
def resolve_function(p, name, args): """Resolve a function invocation into an Expression instance. :param p: The parser context :param name: The name of the function :type name: string :param args: A list of argument expressions :type args: list of raco.expression.Expression instances :return: An expression with no free variables. """ # try to get function from udf or system defined functions if name in Parser.udf_functions: func = Parser.udf_functions[name] else: func = expr_lib.lookup(name, len(args)) if func is None: raise NoSuchFunctionException(name, p.lineno(0)) if len(func.args) != len(args): raise InvalidArgumentList(name, func.args, p.lineno(0)) if isinstance(func, Function): return sexpr.resolve_function(func.sexpr, dict(zip(func.args, args))) # noqa elif isinstance(func, StatefulFunc): emit_expr, statemods = Parser.resolve_stateful_func(func, args) Parser.statemods.extend(statemods) # If the aggregate is decomposable, construct local and remote # emitters and statemods. if name in Parser.decomposable_aggs: ds = Parser.decomposable_aggs[name] local_emit, local_statemods = Parser.resolve_stateful_func( ds.local, args) # Problem: we must connect the local aggregate outputs to # the remote aggregate inputs. At this stage, we don't have # enough information to construct argument expressions to # serve as input to the remote aggregate. Instead, we # introduce a placeholder reference, which is referenced # relative to the start of the local aggregate output. remote_args = [sexpr.LocalAggregateOutput(i) for i in range(len(ds.remote.args))] remote_emit, remote_statemods = Parser.resolve_stateful_func( ds.remote, remote_args) # local and remote emitters may be tuple-valued; flatten them. local_emitters = get_emitters(local_emit) remote_emitters = get_emitters(remote_emit) ds = sexpr.DecomposableAggregateState( local_emitters, local_statemods, remote_emitters, remote_statemods) # Associate a decomposable state structure with the first # emitter. Mark the remaining emitters as decomposable, but # without their own associated decomposed emitters and # statemods. emitters = get_emitters(emit_expr) emitters[0].set_decomposable_state(ds) for emt in emitters[1:]: emt.set_decomposable_state( sexpr.DecomposableAggregateState()) return emit_expr else: assert False