pytholite/compiler: support if statements

This commit is contained in:
Sebastien Bourdeauducq 2012-11-09 19:37:52 +01:00
parent 92ff5095da
commit e1075a962c
1 changed files with 37 additions and 7 deletions

View File

@ -54,6 +54,10 @@ class _Register:
sync = [Case(self.sel, *cases)] sync = [Case(self.sel, *cases)]
return Fragment(sync=sync) return Fragment(sync=sync)
class _AbstractNextState:
def __init__(self, target_state):
self.target_state = target_state
class _Compiler: class _Compiler:
def __init__(self, symdict, registers): def __init__(self, symdict, registers):
self.symdict = symdict self.symdict = symdict
@ -76,6 +80,15 @@ class _Compiler:
op = self.visit_assign(statement) op = self.visit_assign(statement)
if op: if op:
states.append(op) states.append(op)
elif isinstance(statement, ast.If):
test = self.visit_expr(statement.test)
states_t = self.visit_block(statement.body)
states_f = self.visit_block(statement.orelse)
test_state_stmt = If(test, _AbstractNextState(states_t[0]))
if states_f:
test_state_stmt.Else(_AbstractNextState(states_f[0]))
states.append([test_state_stmt])
states += states_t + states_f
else: else:
raise NotImplementedError raise NotImplementedError
return states return states
@ -163,10 +176,10 @@ class _Compiler:
raise NotImplementedError raise NotImplementedError
def visit_expr_compare(self, node): def visit_expr_compare(self, node):
test = visit_expr(node.test) test = self.visit_expr(node.left)
r = None r = None
for op, rcomparator in zip(node.ops, node.comparators): for op, rcomparator in zip(node.ops, node.comparators):
comparator = visit_expr(rcomparator) comparator = self.visit_expr(rcomparator)
if isinstance(op, ast.Eq): if isinstance(op, ast.Eq):
comparison = test == comparator comparison = test == comparator
elif isinstance(op, ast.NotEq): elif isinstance(op, ast.NotEq):
@ -197,15 +210,32 @@ class _Compiler:
def visit_expr_num(self, node): def visit_expr_num(self, node):
return node.n return node.n
# like list.index, but using "is" instead of comparison
def _index_is(l, x):
for i, e in enumerate(l):
if e is x:
return i
class _LowerAbstractNextState(fhdl.NodeTransformer):
def __init__(self, fsm, states, stnames):
self.fsm = fsm
self.states = states
self.stnames = stnames
def visit_unknown(self, node):
if isinstance(node, _AbstractNextState):
index = _index_is(self.states, node.target_state)
estate = getattr(self.fsm, self.stnames[index])
return self.fsm.next_state(estate)
else:
return node
def _create_fsm(states): def _create_fsm(states):
stnames = ["S" + str(i) for i in range(len(states))] stnames = ["S" + str(i) for i in range(len(states))]
fsm = FSM(*stnames) fsm = FSM(*stnames)
lans = _LowerAbstractNextState(fsm, states, stnames)
for i, state in enumerate(states): for i, state in enumerate(states):
if i == len(states) - 1: actions = lans.visit(state)
actions = []
else:
actions = [fsm.next_state(getattr(fsm, stnames[i+1]))]
actions += state
fsm.act(getattr(fsm, stnames[i]), *actions) fsm.act(getattr(fsm, stnames[i]), *actions)
return fsm return fsm