1111import os
1212import math
1313import re
14+ import functools
1415from jinja2 import Environment , FileSystemLoader
1516
1617sys .path .insert (0 , os .path .dirname (os .path .dirname (os .path .dirname (os .path .abspath (__file__ )))) )
2223
2324DEFAULT_TEMPLATE_DIR = os .path .dirname (os .path .abspath (__file__ )) + '/template/'
2425
26+ #-------------------------------------------------------------------------------
27+ try :
28+ import textwrap
29+ indent = textwrap .indent
30+ except :
31+ def indent (text , prefix , predicate = None ):
32+ if predicate is None : predicate = lambda x : x and not x .isspace ()
33+ ret = []
34+ for line in text .split ('\n ' ):
35+ if predicate (line ):
36+ ret .append (prefix )
37+ ret .append (line )
38+ ret .append ('\n ' )
39+ return '' .join (ret [:- 1 ])
40+
41+ #-------------------------------------------------------------------------------
2542class ConvertVisitor (object ):
2643 def visit (self , node ):
2744 method = 'visit_' + node .__class__ .__name__
@@ -42,8 +59,9 @@ def escape(s):
4259 return s
4360
4461class ASTCodeGenerator (ConvertVisitor ):
45- def __init__ (self ):
62+ def __init__ (self , indentsize = 2 ):
4663 self .env = Environment (loader = FileSystemLoader (DEFAULT_TEMPLATE_DIR ))
64+ self .indent = functools .partial (indent , prefix = ' ' * indentsize )
4765
4866 def visit_Source (self , node ):
4967 filename = getfilename (node )
@@ -66,13 +84,13 @@ def visit_Description(self, node):
6684 def visit_ModuleDef (self , node ):
6785 filename = getfilename (node )
6886 template = self .env .get_template (filename )
69- paramlist = self .visit (node .paramlist ) if node .paramlist is not None else ''
70- portlist = self .visit (node .portlist ) if node .portlist is not None else ''
87+ paramlist = self .indent ( self . visit (node .paramlist ) ) if node .paramlist is not None else ''
88+ portlist = self .indent ( self . visit (node .portlist ) ) if node .portlist is not None else ''
7189 template_dict = {
7290 'modulename' : escape (node .name ),
7391 'paramlist' : paramlist ,
7492 'portlist' : portlist ,
75- 'items' : [ self .visit (item ) for item in node .items ] if node .items else (),
93+ 'items' : [ self .indent ( self . visit (item ) ) for item in node .items ] if node .items else (),
7694 }
7795 rslt = template .render (template_dict )
7896 return rslt
@@ -641,10 +659,12 @@ def visit_NonblockingSubstitution(self, node):
641659 def visit_IfStatement (self , node ):
642660 filename = getfilename (node )
643661 template = self .env .get_template (filename )
662+ true_statement = '' if node .true_statement is None else self .visit (node .true_statement )
663+ false_statement = '' if node .false_statement is None else self .visit (node .false_statement )
644664 template_dict = {
645665 'cond' : self .visit (node .cond ),
646- 'true_statement' : '' if node . true_statement is None else self . visit ( node . true_statement ) ,
647- 'false_statement' : '' if node . false_statement is None else self . visit ( node . false_statement ) ,
666+ 'true_statement' : true_statement ,
667+ 'false_statement' : false_statement ,
648668 }
649669 rslt = template .render (template_dict )
650670 return rslt
@@ -711,7 +731,7 @@ def visit_Block(self, node):
711731 template = self .env .get_template (filename )
712732 template_dict = {
713733 'scope' : '' if node .scope is None else escape (node .scope ),
714- 'statements' : [ self .visit (statement ) for statement in node .statements ],
734+ 'statements' : [ self .indent ( self . visit (statement ) ) for statement in node .statements ],
715735 }
716736 rslt = template .render (template_dict )
717737 return rslt
@@ -765,7 +785,7 @@ def visit_DelayStatement(self, node):
765785 def visit_InstanceList (self , node ):
766786 filename = getfilename (node )
767787 template = self .env .get_template (filename )
768- parameterlist = [ self .visit (param ) for param in node .parameterlist ]
788+ parameterlist = [ self .indent ( self . visit (param ) ) for param in node .parameterlist ]
769789 instances = [ self .visit (instance ) for instance in node .instances ]
770790 template_dict = {
771791 'module' : escape (node .module ),
@@ -781,7 +801,7 @@ def visit_Instance(self, node):
781801 filename = getfilename (node )
782802 template = self .env .get_template (filename )
783803 array = '' if node .array is None else self .visit (node .array )
784- portlist = [ self .visit (port ) for port in node .portlist ]
804+ portlist = [ self .indent ( self . visit (port ) ) for port in node .portlist ]
785805 template_dict = {
786806 'name' : escape (node .name ),
787807 'array' : array ,
@@ -814,7 +834,7 @@ def visit_PortArg(self, node):
814834 def visit_Function (self , node ):
815835 filename = getfilename (node )
816836 template = self .env .get_template (filename )
817- statement = [ self .visit (s ) for s in node .statement ]
837+ statement = [ self .indent ( self . visit (s ) ) for s in node .statement ]
818838 template_dict = {
819839 'name' : escape (node .name ),
820840 'retwidth' : self .visit (node .retwidth ),
@@ -838,9 +858,10 @@ def visit_FunctionCall(self, node):
838858 def visit_Task (self , node ):
839859 filename = getfilename (node )
840860 template = self .env .get_template (filename )
861+ statement = [ self .indent (self .visit (s )) for s in node .statement ]
841862 template_dict = {
842863 'name' : escape (node .name ),
843- 'statement' : self . visit ( node . statement ) ,
864+ 'statement' : statement ,
844865 }
845866 rslt = template .render (template_dict )
846867 return rslt
@@ -931,7 +952,7 @@ def visit_ParallelBlock(self, node):
931952 template = self .env .get_template (filename )
932953 template_dict = {
933954 'scope' : '' if node .scope is None else escape (node .scope ),
934- 'statements' : [ self .visit (statement ) for statement in node .statements ],
955+ 'statements' : [ self .indent ( self . visit (statement ) ) for statement in node .statements ],
935956 }
936957 rslt = template .render (template_dict )
937958 return rslt
0 commit comments