1# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this
3# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5import os, sys
6
7from ipdl.ast import Visitor
8
9class CodePrinter:
10    def __init__(self, outf=sys.stdout, indentCols=4):
11        self.outf = outf
12        self.col = 0
13        self.indentCols = indentCols
14
15    def write(self, str):
16        self.outf.write(str)
17
18    def printdent(self, str=''):
19        self.write((' '* self.col) + str)
20
21    def println(self, str=''):
22        self.write(str +'\n')
23
24    def printdentln(self, str):
25        self.write((' '* self.col) + str +'\n')
26
27    def indent(self):  self.col += self.indentCols
28    def dedent(self):  self.col -= self.indentCols
29
30
31##-----------------------------------------------------------------------------
32class IPDLCodeGen(CodePrinter, Visitor):
33    '''Spits back out equivalent IPDL to the code that generated this.
34Also known as pretty-printing.'''
35
36    def __init__(self, outf=sys.stdout, indentCols=4, printed=set()):
37        CodePrinter.__init__(self, outf, indentCols)
38        self.printed = printed
39
40    def visitTranslationUnit(self, tu):
41        self.printed.add(tu.filename)
42        self.println('//\n// Automatically generated by ipdlc\n//')
43        CodeGen.visitTranslationUnit(self, tu)
44
45    def visitCxxInclude(self, inc):
46        self.println('include "'+ inc.file +'";')
47
48    def visitProtocolInclude(self, inc):
49        self.println('include protocol "'+ inc.file +'";')
50        if inc.tu.filename not in self.printed:
51            self.println('/* Included file:')
52            IPDLCodeGen(outf=self.outf, indentCols=self.indentCols,
53                        printed=self.printed).visitTranslationUnit(inc.tu)
54
55            self.println('*/')
56
57    def visitProtocol(self, p):
58        self.println()
59        for namespace in p.namespaces:  namespace.accept(self)
60
61        self.println('%s protocol %s\n{'% (p.sendSemantics[0], p.name))
62        self.indent()
63
64        for mgs in p.managesStmts:
65            mgs.accept(self)
66        if len(p.managesStmts):  self.println()
67
68        for msgDecl in p.messageDecls:  msgDecl.accept(self)
69        self.println()
70
71        self.dedent()
72        self.println('}')
73        self.write('}\n'* len(p.namespaces))
74
75    def visitManagerStmt(self, mgr):
76        self.printdentln('manager '+ mgr.name +';')
77
78    def visitManagesStmt(self, mgs):
79        self.printdentln('manages '+ mgs.name +';')
80
81    def visitMessageDecl(self, msg):
82        self.printdent('%s %s %s('% (msg.sendSemantics[0], msg.direction[0], msg.name))
83        for i, inp in enumerate(msg.inParams):
84            inp.accept(self)
85            if i != (len(msg.inParams) - 1):  self.write(', ')
86        self.write(')')
87        if 0 == len(msg.outParams):
88            self.println(';')
89            return
90
91        self.println()
92        self.indent()
93        self.printdent('returns (')
94        for i, outp in enumerate(msg.outParams):
95            outp.accept(self)
96            if i != (len(msg.outParams) - 1):  self.write(', ')
97        self.println(');')
98        self.dedent()
99