source: proto/Compiler/lookAhead.py @ 4223

Last change on this file since 4223 was 2894, checked in by cameron, 7 years ago

Fix final block lookahead

File size: 3.0 KB
RevLine 
[2885]1#
2# lookAhead.py
3#
4# Copyright 2013, Robert D. Cameron, Kenneth S. Herdy
5# All rights reserved.
6#
7# Information Gathering for Carry Processing in Pablo
8
9import ast
10
11def isLookAhead(builtin_fn):
12   return builtin_fn in ['Lookahead']
13
14def CheckForLookAhead(fncall, builtin_fnmod_noprefix='pablo'):
15  if not isinstance(fncall, ast.Call): return False
16  if isinstance(fncall.func, ast.Name): return isLookAhead(fncall.func)
17  elif isinstance(fncall.func, ast.Attribute) and isinstance(fncall.func.value, ast.Name):
18    if fncall.func.value.id == builtin_fnmod_noprefix: return isLookAhead(fncall.func.attr)
19    else: return False
20  else: return False
21
22class LookAheadError(Exception): pass
23
24#
25# LookAhead Info Set
26#
27class LookAheadInfoSetVisitor(ast.NodeVisitor):
28  def __init__(self, streamFunctionNode):
29    self.LookAheadSet = {}
30    self.generic_visit(streamFunctionNode)
31
32  def visit_Call(self, callnode):
33    self.generic_visit(callnode)
34    if CheckForLookAhead(callnode):
35      if len(callnode.args) == 2:
[2892]36        if not isinstance(callnode.args[1], ast.Num):
[2885]37          raise LookAheadError('2nd argument to lookahead, if present, must be a numeric constant')
38        peek_amount = callnode.args[1].n
[2891]39      elif len(callnode.args) == 1: 
[2885]40        peek_amount = 1
41      else: raise LookAheadError('lookahead needs 1 or 2 args')
42      if not isinstance(callnode.args[0], ast.Attribute):
43        raise LookAheadError('lookahead needs a stream within a stream struct, e.g. lex.RAngle')
44      if not isinstance(callnode.args[0].value, ast.Name):
45         raise LookAheadError('lookahead needs a stream within a stream struct, e.g. lex.RAngle')
46      struct_name = callnode.args[0].value.id
47      if not self.LookAheadSet.has_key(struct_name): self.LookAheadSet[struct_name] = []
48      self.LookAheadSet[struct_name].append(callnode.args[0].attr)
49
50class LookAheadTransformer (ast.NodeTransformer):
[2891]51  def __init__(self, streamFunctionNode, mode="nonfinal"):
52    self.LookAheadSet = streamFunctionNode.lookahead_info.LookAheadSet
53    self.block_mode = mode
54
[2885]55  def xfrm(self, t):
56    return self.generic_visit(t)
57  def visit_Call(self, callnode):
58    self.generic_visit(callnode)
59    if not CheckForLookAhead(callnode): return callnode
60    if len(callnode.args) > 1:
61        peek_amount = callnode.args[1].n
62    else: 
63        peek_amount = 1
64    module_name = callnode.args[0].value
65    strm = callnode.args[0].attr
[2891]66    #b0 = ast.Attribute(ast.Subscript(module_name, ast.Index(ast.Num(0)), ast.Load()), strm, ast.Load())
67    #b1 = ast.Attribute(ast.Subscript(module_name, ast.Index(ast.Num(1)), ast.Load()), strm, ast.Load())
68    b0 = ast.Attribute(module_name, strm, ast.Load())
69    b1 = ast.Attribute(ast.Name(module_name.id + "_ahead", ast.Load()), strm, ast.Load())
[2894]70    if self.block_mode == "final":
71      b1 = ast.Call(ast.Name('simd<1>::constant<0>', ast.Load()), [], [], None, None)
[2885]72    return ast.Call(ast.Name('pablo_blk_Lookahead_n_<%i>' %  peek_amount, ast.Load()), [b0, b1], [], None, None)
73
74
75if __name__ == "__main__":
76                import doctest
77                doctest.testmod()
Note: See TracBrowser for help on using the repository browser.