17b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang"""CC code emitter. 27b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 37b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao WangUsed by generators to programatically prepare C++ code. Contains some simple 47b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wangtools that allow generating nicely indented code and do basic correctness 57b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wangchecking. 67b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang""" 77b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 87b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 97b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wangclass Error(Exception): 107b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang """Module level error.""" 117b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 127b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 137b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wangclass NamespaceError(Error): 147b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang """Invalid namespace operation.""" 157b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 167b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 177b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wangclass HeaderError(Error): 187b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang """Invalid cc header structure.""" 197b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 207b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 217b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wangclass CCEmitter(object): 227b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang """Emits c++ code.""" 237b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 247b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def __init__(self, debug=False): 257b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.indent = '' 267b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.debug = debug 277b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.namespaces = [] 287b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.header_name = None 297b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 307b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def PushIndent(self): 317b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.indent += ' ' 327b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 337b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def PopIndent(self): 347b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.indent = self.indent[:-2] 357b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 367b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitIndented(self, what): 377b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang print self.indent + what 387b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 397b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitNewline(self): 407b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang print '' 417b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 427b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitPreprocessor1(self, op, param): 437b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang print '#%s %s' % (op, param) 447b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 457b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitPreprocessor(self, op): 467b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang print '#%s' % op 477b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 487b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitInclude(self, include): 497b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitPreprocessor1('include', include) 507b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 517b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitAssign(self, variable, value): 527b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitBinaryOp(variable, '=', value) 537b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 547b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitAssignIncrement(self, variable, value): 557b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitBinaryOp(variable, '+=', value) 567b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 577b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitBinaryOp(self, operand_1, op, operand_2): 587b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitCode('%s %s %s' % (operand_1, op, operand_2)) 597b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 607b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitCall(self, function, params=[]): 617b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitCode('%s(%s)' % (function, ', '.join(map(str, params)))) 627b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 637b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitCode(self, code): 647b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitIndented('%s;' % code) 657b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 667b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitCodeNoSemicolon(self, code): 677b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitIndented('%s' % code) 687b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 697b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitDeclare(self, decl_type, name, value): 707b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitAssign('%s %s' % (decl_type, name), value) 717b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 727b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitAssert(self, assert_expression): 737b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang if self.debug: 747b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitCall1('assert', assert_expression) 757b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 767b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitHeaderBegin(self, header_name, includes=None): 777b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang if includes is None: 787b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang includes = [] 797b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang if self.header_name: 807b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang raise HeaderError('Header already defined.') 817b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitPreprocessor1('ifndef', (header_name + '_H_').upper()) 827b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitPreprocessor1('define', (header_name + '_H_').upper()) 837b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitNewline() 847b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang if includes: 857b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang for include in includes: 867b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitInclude(include) 877b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitNewline() 887b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.header_name = header_name 897b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 907b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitHeaderEnd(self): 917b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang if not self.header_name: 927b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang raise HeaderError('Header undefined.') 937b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitPreprocessor1('endif', 947b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang ' // %s' % (self.header_name + '_H_').upper()) 957b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.header_name = None 967b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 977b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitFunctionBeginA(self, function_name, params, return_type): 987b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitIndented('%s %s(%s) {' % 997b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang (return_type, function_name, 1007b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang ', '.join(['%s %s' % (t, n) for (t, n) in params]))) 1017b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.PushIndent() 1027b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1037b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitFunctionEnd(self): 1047b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.PopIndent() 1057b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitIndented('}') 1067b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1077b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitNamespaceBegin(self, namespace): 1087b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitCodeNoSemicolon('namespace %s {' % namespace) 1097b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.namespaces.append(namespace) 1107b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1117b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitNamespaceEnd(self): 1127b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang if not self.namespaces: 1137b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang raise NamespaceError('No namespace on stack.') 1147b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitCodeNoSemicolon('} // namespace %s' % self.namespaces.pop()) 1157b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1167b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitComment(self, comment): 1177b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitIndented('// ' + comment) 1187b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1197b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitOpenBracket(self, pre_bracket=None): 1207b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang if pre_bracket: 1217b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitIndented('%s {' % pre_bracket) 1227b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang else: 1237b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitIndented('{') 1247b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.PushIndent() 1257b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1267b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitCloseBracket(self): 1277b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.PopIndent() 1287b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitIndented('}') 1297b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1307b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitSwitch(self, switch): 1317b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitOpenBracket('switch (%s)' % switch) 1327b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1337b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitSwitchEnd(self): 1347b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitCloseBracket() 1357b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1367b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitCase(self, value): 1377b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitCodeNoSemicolon('case %s:' % value) 1387b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1397b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitBreak(self): 1407b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitCode('break') 1417b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1427b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitIf(self, condition): 1437b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitOpenBracket('if (%s)' % condition) 1447b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1457b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitElse(self): 1467b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.PopIndent() 1477b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitCodeNoSemicolon('} else {') 1487b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.PushIndent() 1497b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1507b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def EmitEndif(self): 1517b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang self.EmitCloseBracket() 1527b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang 1537b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang def Scope(self, scope, value): 1547b05d573cf2e0fd3a58e98cdbfc65153a83fd6f1Miao Wang return '%s::%s' % (scope, value) 155