def prim_loop(compiler, src): if src[2] != lisp.Symbol("<-"): raise SyntaxError, src[:3] loop_binding = src[1] loop_init = src[3] loop_body = src[4:] loop_name = pycode.name("loop") context.curr().setdefault("LOOP_STACK", []).append(loop_name) tpl = ( "%s = $#\n" % (loop_name,) + "while True:\n" + " try:\n" + " $#\n" + " except _ME:\n" + " break\n" + " $#\n" + " break\n" + loop_name ) output_code = pycode.create( tpl, compiler.compile(loop_init), compiler.compile((lisp.Symbol("="), loop_binding, lisp.Symbol(loop_name))), compiler.compile_block(loop_body, loop_name), ) context.curr()["LOOP_STACK"].pop() return output_code
def prim_loop(compiler, src): if src[2] != lisp.Symbol('<-'): raise SyntaxError, src[:3] loop_binding = src[1] loop_init = src[3] loop_body = src[4:] loop_name = pycode.name('loop') context.curr().setdefault('LOOP_STACK', []).append(loop_name) tpl = \ '%s = $#\n' % (loop_name,) + \ 'while True:\n' + \ ' try:\n' + \ ' $#\n' + \ ' except _ME:\n' + \ ' break\n' + \ ' $#\n' + \ ' break\n' + \ loop_name output_code = pycode.create( tpl, compiler.compile(loop_init), compiler.compile((lisp.Symbol('='), loop_binding, lisp.Symbol(loop_name))), compiler.compile_block(loop_body, loop_name)) context.curr()['LOOP_STACK'].pop() return output_code
def prim_for(compiler, src): if lisp.Symbol('<-') != src[2]: raise SyntaxError(src[:3]) matcher = src[1] datasource = src[3] body = src[4:] queue_name = pycode.name('for_queue') context.curr().setdefault('FOR_STACK', []).append(queue_name) if type(matcher) is lisp.Symbol: tpl = '%s = []\nfor %s in $#:\n %s.append($#)\n%s' % ( queue_name, matcher.name, queue_name, queue_name) datasource_code = compiler.compile(datasource) if body: body_code = compiler.compile((lisp.Symbol('env'), matcher) + body) else: body_code = pycode.create(matcher.name) output_code = pycode.create(tpl, datasource_code, body_code) else: datasource_code = compiler.compile(datasource) if datasource_code.value == '_': datasource_code = datasource.asname(pycode.name()) for_var = pycode.name('for_var') proc_compiler = proc.Compiler(compiler) matcher_code = proc_compiler.compile(for_var, matcher) tpl = \ '%s = []\n' % (queue_name,) + \ 'for %s in $#:\n' % (for_var,) + \ ' try:\n' + \ ' $#\n' + \ ' except _ME, e:\n' + \ ' continue\n' + \ ' %s.append($#)\n' % (queue_name,) + \ queue_name if body: body_code = compiler.compile((lisp.Symbol('env'), lisp.Symbol(matcher_code.value)) + body) else: body_code = pycode.create(matcher_code.value) output_code = pycode.create(tpl, datasource_code, matcher_code, body_code) context.curr()['FOR_STACK'].pop() return output_code
def name(prefix = 'tmp'): """Assign name in current context""" nameidx = context.curr().setdefault('NAME_INDEX', {}) idx = nameidx.setdefault(prefix, 0) name = '_%s_%d' % (prefix, idx) nameidx[prefix] = idx + 1 return name
def prim_break(compiler, src): if len(src) == 1: return pycode.create('break\nNone') loop_name = context.curr()['LOOP_STACK'][-1] return pycode.create( '%s = $#\nbreak\n%s' % (loop_name, loop_name), compiler.compile(src[1]))
def name(prefix='tmp'): """Assign name in current context""" nameidx = context.curr().setdefault('NAME_INDEX', {}) idx = nameidx.setdefault(prefix, 0) name = '_%s_%d' % (prefix, idx) nameidx[prefix] = idx + 1 return name
def prim_for(compiler, src): if lisp.Symbol('<-') != src[2]: raise SyntaxError(src[:3]) matcher = src[1] datasource = src[3] body = src[4:] queue_name = pycode.name('for_queue') context.curr().setdefault('FOR_STACK', []).append(queue_name) if type(matcher) is lisp.Symbol: tpl = '%s = []\nfor %s in $#:\n %s.append($#)\n%s' % ( queue_name, matcher.name, queue_name, queue_name) datasource_code = compiler.compile(datasource) if body: body_code = compiler.compile((lisp.Symbol('env'), matcher) + body) else: body_code = pycode.create(matcher.name) output_code = pycode.create(tpl, datasource_code, body_code) else: datasource_code = compiler.compile(datasource) if datasource_code.value == '_': datasource_code = datasource.asname(pycode.name()) for_var = pycode.name('for_var') proc_compiler = proc.Compiler(compiler) matcher_code = proc_compiler.compile(for_var, matcher) tpl = \ '%s = []\n' % (queue_name,) + \ 'for %s in $#:\n' % (for_var,) + \ ' try:\n' + \ ' $#\n' + \ ' except _ME, e:\n' + \ ' continue\n' + \ ' %s.append($#)\n' % (queue_name,) + \ queue_name if body: body_code = compiler.compile( (lisp.Symbol('env'), lisp.Symbol(matcher_code.value)) + body) else: body_code = pycode.create(matcher_code.value) output_code = pycode.create(tpl, datasource_code, matcher_code, body_code) context.curr()['FOR_STACK'].pop() return output_code
def compile_section(self, proc_var, section, is_last): pattern_part, body_part = section proc_stack = context.curr().setdefault('PROC_STACK', []) lisp.env_push(proc_var) if pattern_part: proc_stack.append('#') pattern_code = self.compile_pattern(pattern_part) if pattern_code.meta.get('raise_random', False) and ( (not is_last) or (len(proc_stack) < 2 or proc_stack[-2] != '#')): # When compiled pattern code may raise random exception # And it's not the last one of matching chain or # The caller is call directely in a LISP environment (not in pattern matching) # It's the pattern matching code's responsibility to catch all exception # and turn it to _ME wrap_tpl = 'try:\n $#\nexcept:\n raise _ME(%s)\n%s' % ( proc_var, proc_var) pattern_code = pycode.create(wrap_tpl, pattern_code) proc_stack.pop() else: pattern_code = pycode.create(proc_var, shortcut_nop=True) if body_part is None: return pattern_code proc_stack.append('=>') body_code = pycode.create(proc_var + ' = $#\n' + proc_var, self.lisp_compiler.compile_block(body_part)) proc_stack.pop() lisp.env_pop() if not is_last: body_tpl = 'try:\n $#\nexcept _ME, e:\n raise _UME(%s)\n%s' % ( proc_var, proc_var) body_code = pycode.create(body_tpl, body_code) return pattern_code + body_code
def compile_section(self, proc_var, section, is_last): pattern_part, body_part = section proc_stack = context.curr().setdefault('PROC_STACK', []) lisp.env_push(proc_var) if pattern_part: proc_stack.append('#') pattern_code = self.compile_pattern(pattern_part) if pattern_code.meta.get('raise_random', False) and ( (not is_last) or (len(proc_stack) < 2 or proc_stack[-2] != '#')): # When compiled pattern code may raise random exception # And it's not the last one of matching chain or # The caller is call directely in a LISP environment (not in pattern matching) # It's the pattern matching code's responsibility to catch all exception # and turn it to _ME wrap_tpl = 'try:\n $#\nexcept:\n raise _ME(%s)\n%s' % (proc_var, proc_var) pattern_code = pycode.create(wrap_tpl, pattern_code) proc_stack.pop() else: pattern_code = pycode.create(proc_var, shortcut_nop = True) if body_part is None: return pattern_code proc_stack.append('=>') body_code = pycode.create( proc_var + ' = $#\n' + proc_var, self.lisp_compiler.compile_block(body_part)) proc_stack.pop() lisp.env_pop() if not is_last: body_tpl = 'try:\n $#\nexcept _ME, e:\n raise _UME(%s)\n%s' % ( proc_var, proc_var) body_code = pycode.create(body_tpl, body_code) return pattern_code + body_code
def prim_emit_many(compiler, src): queue_name = context.curr()['FOR_STACK'][-1] return pycode.create('%s.extend($#)\nNone' % (queue_name,), compiler.compile(src[1]))
def __call__(self, value): curr = context.curr() if curr is not None: curr[self.name] = value return value
def prim_emit_many(compiler, src): queue_name = context.curr()['FOR_STACK'][-1] return pycode.create('%s.extend($#)\nNone' % (queue_name, ), compiler.compile(src[1]))
def env_curr(): return context.curr()['ENV_STACK'][-1]
def prim_break(compiler, src): if len(src) == 1: return pycode.create("break\nNone") loop_name = context.curr()["LOOP_STACK"][-1] return pycode.create("%s = $#\nbreak\n%s" % (loop_name, loop_name), compiler.compile(src[1]))
def env_pop(): context.curr()['ENV_STACK'].pop()
def env_push(name): context.curr().setdefault('ENV_STACK', []).append(name)