def write_ensurers(code, functions): code( ''' $bar // compound ensurers ''', bar=bar, ).newline() functions = [(name, signature.get_nargs(arity)) for arity, funs in functions.iteritems() if signature.get_nargs(arity) > 0 for name in funs] def Ob(x): return 'Ob %s' % x for name1, argc1 in functions: for name2, argc2 in functions: if name1 > name2: continue vars1 = ['key1'] if argc1 == 1 else ['lhs1', 'rhs1'] vars2 = ['key2'] if argc2 == 1 else ['lhs2', 'rhs2'] code( ''' inline void ensure_${name1}_${name2} ( $typed_args1, $typed_args2) { if (Ob val1 = $NAME1.find($args1)) { $NAME2.insert($args2, val1); } else { if (Ob val2 = $NAME2.find($args2)) { $NAME1.insert($args1, val2); } } } ''', name1=name1.lower(), name2=name2.lower(), NAME1=name1, NAME2=name2, args1=', '.join(vars1), args2=', '.join(vars2), typed_args1=', '.join(map(Ob, vars1)), typed_args2=', '.join(map(Ob, vars2)), ).newline()
def __init__(self, name, *args): assert isinstance(name, str) assert re.match('[a-zA-Z][a-zA-Z_]*$', name),\ 'invalid name: {0}'.format(name) args = list(args) arity = signature.get_arity(name) assert len(args) == signature.get_nargs(arity) for arg in args: assert isinstance(arg, Expression), arg self._name = name self._args = args self._arity = arity self._polish = ' '.join([name] + [arg._polish for arg in args]) self._hash = hash(self._polish) if arity == 'Variable': self._var = self self._vars = set([self]) elif arity == 'NullaryFunction': self._var = Expression(name + '_') self._vars = set() elif arity in [ 'InjectiveFunction', 'BinaryFunction', 'SymmetricFunction', ]: var = re.sub('[ _]+', '_', self.polish).rstrip('_') self._var = Expression(var) self._vars = union(arg.vars for arg in args) else: self._var = None self._vars = union(arg.vars for arg in args)
def __init__(self, name, *args): assert isinstance(name, str), type(name) assert re_name.match(name), name arity = signature.get_arity(name) assert len(args) == signature.get_nargs(arity), (args, arity) for arg in args: assert isinstance(arg, Expression), arg self._name = intern(name) self._args = args self._arity = arity self._polish = intern(' '.join([name] + [arg._polish for arg in args])) self._hash = hash(self._polish) self._sort = (len(self._polish), self._polish) # all other fields are lazily initialized self._var = None self._vars = None self._consts = None self._terms = None
def write_event_tasks(code, sequents): code( ''' $bar // event tasks ''', bar=bar, ).newline() event_tasks = {} for sequent in sequents: for event in compiler.get_events(sequent): name = '<variable>' if event.is_var() else event.name tasks = event_tasks.setdefault(name, []) strategies = compiler.compile_given(sequent, event) strategies.sort(key=lambda (cost, _): cost) costs = [cost for cost, _ in strategies] cost = log_sum_exp(*costs) tasks.append((event, cost, strategies)) def get_group(name): special = { 'LESS': 'PositiveOrder', 'NLESS': 'NegativeOrder', '<variable>': 'Exists', } return special.get(name, signature.get_arity(name)) group_tasks = {} for name, tasks in event_tasks.iteritems(): groupname = get_group(name) group_tasks.setdefault(groupname, {})[name] = tasks # TODO sort groups # event_tasks = event_tasks.items() # event_tasks.sort(key=lambda (name, tasks): (len(tasks), len(name), name)) group_tasks = list(group_tasks.iteritems()) group_tasks.sort() for groupname, group in group_tasks: group = list(group.iteritems()) group.sort() body = Code() for eventname, tasks in group: subbody = Code() nargs = signature.get_nargs(signature.get_arity(group[0][0])) args = [[], ['arg'], ['lhs', 'rhs']][nargs] for arg in args: subbody('const Ob $arg = task.$arg;', arg=arg) if signature.is_fun(eventname): subbody( ''' const Ob val = $eventname.find($args); ''', eventname=eventname, args=', '.join(args)) for event, _, strategies in tasks: subsubbody = Code() diagonal = (nargs == 2 and event.args[0] == event.args[1]) if diagonal: subsubbody( ''' const Ob $local __attribute__((unused)) = $arg; ''', local=event.args[0], arg=args[0], ) else: for local, arg in zip(event.args, args): subsubbody( ''' const Ob $local __attribute__((unused)) = $arg; ''', local=local, arg=arg, ) if event.is_fun(): subsubbody('const Ob $arg = val;', arg=event.var.name) elif event.is_var(): subsubbody('const Ob $arg = task.ob;', arg=event.name) subcost = 0 for cost, strategy in strategies: subsubbody.newline() strategy.cpp(subsubbody) subcost += cost if diagonal: subbody( ''' if (lhs == rhs) { // cost = $cost $subsubbody } ''', cost=cost, subsubbody=wrapindent(subsubbody), ) else: subbody( ''' { // cost = $cost $subsubbody } ''', cost=cost, subsubbody=wrapindent(subsubbody), ) if eventname in ['LESS', 'NLESS', '<variable>']: body(str(subbody)).newline() else: body( ''' if (task.fun == & $eventname) { $subbody } ''', eventname=eventname, subbody=wrapindent(subbody), ).newline() code( ''' void execute (const ${groupname}Task & task) { $body } ''', groupname=groupname, body=wrapindent(body), ).newline() nontrivial_arities = [groupname for groupname, _ in group_tasks] for arity in signature.FUNCTION_ARITIES: if arity not in nontrivial_arities: code( ''' void execute (const ${arity}Task &) {} ''', arity=arity, ).newline()
def write_merge_task(code, functions): body = Code() body( ''' const Ob dep = task.dep; const Ob rep = carrier.find(dep); POMAGMA_ASSERT(dep > rep, "ill-formed merge: " << dep << ", " << rep); bool invalid = NLESS.find(dep, rep) or NLESS.find(rep, dep); POMAGMA_ASSERT(not invalid, "invalid merge: " << dep << ", " << rep); std::vector<std::thread> threads; threads.push_back(std::thread( &BinaryRelation::unsafe_merge, &LESS, dep)); threads.push_back(std::thread( &BinaryRelation::unsafe_merge, &NLESS, dep)); ''', ) functions = [ (name, arity, signature.get_nargs(arity)) for arity, funs in functions.iteritems() for name in funs ] functions.sort(key=lambda (name, arity, argc): -argc) for name, arity, argc in functions: if argc <= 1: body('$name.unsafe_merge(dep);', name=name) else: body( ''' threads.push_back(std::thread( &$arity::unsafe_merge, &$name, dep)); ''', name=name, arity=arity, ) body.newline() body( ''' for (auto & thread : threads) { thread.join(); } carrier.unsafe_remove(dep); ''' ) code( ''' void execute (const MergeTask & task) { $body } ''', body=wrapindent(body), ).newline()
def parse_tokens_to_expr(tokens): head = tokens.pop() arity = get_arity(head) nargs = get_nargs(arity) args = [parse_tokens_to_expr(tokens) for _ in xrange(nargs)] return Expression.make(head, *args)
def make_template(name): assert isinstance(name, str), name holes = [HOLE] * get_nargs(get_arity(name)) return Expression.make(name, *holes)