1*5f39d1b3SJooyung Han# Copyright 2016 The Gemmlowp Authors. All rights reserved. 2*5f39d1b3SJooyung Han# 3*5f39d1b3SJooyung Han# Licensed under the Apache License, Version 2.0 (the "License"); 4*5f39d1b3SJooyung Han# you may not use this file except in compliance with the License. 5*5f39d1b3SJooyung Han# You may obtain a copy of the License at 6*5f39d1b3SJooyung Han# 7*5f39d1b3SJooyung Han# http://www.apache.org/licenses/LICENSE-2.0 8*5f39d1b3SJooyung Han# 9*5f39d1b3SJooyung Han# Unless required by applicable law or agreed to in writing, software 10*5f39d1b3SJooyung Han# distributed under the License is distributed on an "AS IS" BASIS, 11*5f39d1b3SJooyung Han# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*5f39d1b3SJooyung Han# See the License for the specific language governing permissions and 13*5f39d1b3SJooyung Han# limitations under the License. 14*5f39d1b3SJooyung Han"""CC code emitter. 15*5f39d1b3SJooyung Han 16*5f39d1b3SJooyung HanUsed by generators to programatically prepare C++ code. Contains some simple 17*5f39d1b3SJooyung Hantools that allow generating nicely indented code and do basic correctness 18*5f39d1b3SJooyung Hanchecking. 19*5f39d1b3SJooyung Han""" 20*5f39d1b3SJooyung Han 21*5f39d1b3SJooyung Han 22*5f39d1b3SJooyung Hanclass Error(Exception): 23*5f39d1b3SJooyung Han """Module level error.""" 24*5f39d1b3SJooyung Han 25*5f39d1b3SJooyung Han 26*5f39d1b3SJooyung Hanclass NamespaceError(Error): 27*5f39d1b3SJooyung Han """Invalid namespace operation.""" 28*5f39d1b3SJooyung Han 29*5f39d1b3SJooyung Han 30*5f39d1b3SJooyung Hanclass HeaderError(Error): 31*5f39d1b3SJooyung Han """Invalid cc header structure.""" 32*5f39d1b3SJooyung Han 33*5f39d1b3SJooyung Han 34*5f39d1b3SJooyung Hanclass ClassError(Error): 35*5f39d1b3SJooyung Han """Invalid class syntax.""" 36*5f39d1b3SJooyung Han 37*5f39d1b3SJooyung Han 38*5f39d1b3SJooyung Hanclass CCEmitter(object): 39*5f39d1b3SJooyung Han """Emits c++ code.""" 40*5f39d1b3SJooyung Han 41*5f39d1b3SJooyung Han def __init__(self, debug=False): 42*5f39d1b3SJooyung Han self.indent = '' 43*5f39d1b3SJooyung Han self.debug = debug 44*5f39d1b3SJooyung Han self.namespaces = [] 45*5f39d1b3SJooyung Han self.classes = [] 46*5f39d1b3SJooyung Han self.header_name = None 47*5f39d1b3SJooyung Han 48*5f39d1b3SJooyung Han def PushIndent(self): 49*5f39d1b3SJooyung Han self.indent += ' ' 50*5f39d1b3SJooyung Han 51*5f39d1b3SJooyung Han def PopIndent(self): 52*5f39d1b3SJooyung Han self.indent = self.indent[:-2] 53*5f39d1b3SJooyung Han 54*5f39d1b3SJooyung Han def EmitIndented(self, what): 55*5f39d1b3SJooyung Han print(self.indent + what) 56*5f39d1b3SJooyung Han 57*5f39d1b3SJooyung Han def EmitNewline(self): 58*5f39d1b3SJooyung Han print('') 59*5f39d1b3SJooyung Han 60*5f39d1b3SJooyung Han def EmitPreprocessor1(self, op, param): 61*5f39d1b3SJooyung Han print('#%s %s' % (op, param)) 62*5f39d1b3SJooyung Han 63*5f39d1b3SJooyung Han def EmitPreprocessor(self, op): 64*5f39d1b3SJooyung Han print('#%s' % op) 65*5f39d1b3SJooyung Han 66*5f39d1b3SJooyung Han def EmitInclude(self, include): 67*5f39d1b3SJooyung Han self.EmitPreprocessor1('include', include) 68*5f39d1b3SJooyung Han 69*5f39d1b3SJooyung Han def EmitAssign(self, variable, value): 70*5f39d1b3SJooyung Han self.EmitBinaryOp(variable, '=', value) 71*5f39d1b3SJooyung Han 72*5f39d1b3SJooyung Han def EmitAssignIncrement(self, variable, value): 73*5f39d1b3SJooyung Han self.EmitBinaryOp(variable, '+=', value) 74*5f39d1b3SJooyung Han 75*5f39d1b3SJooyung Han def EmitBinaryOp(self, operand_1, op, operand_2): 76*5f39d1b3SJooyung Han self.EmitCode('%s %s %s' % (operand_1, op, operand_2)) 77*5f39d1b3SJooyung Han 78*5f39d1b3SJooyung Han def EmitCall(self, function, params=None): 79*5f39d1b3SJooyung Han if not params: 80*5f39d1b3SJooyung Han params = [] 81*5f39d1b3SJooyung Han self.EmitCode('%s(%s)' % (function, ', '.join(map(str, params)))) 82*5f39d1b3SJooyung Han 83*5f39d1b3SJooyung Han def EmitCode(self, code): 84*5f39d1b3SJooyung Han self.EmitIndented('%s;' % code) 85*5f39d1b3SJooyung Han 86*5f39d1b3SJooyung Han def EmitCodeNoSemicolon(self, code): 87*5f39d1b3SJooyung Han self.EmitIndented('%s' % code) 88*5f39d1b3SJooyung Han 89*5f39d1b3SJooyung Han def EmitDeclare(self, decl_type, name, value): 90*5f39d1b3SJooyung Han self.EmitAssign('%s %s' % (decl_type, name), value) 91*5f39d1b3SJooyung Han 92*5f39d1b3SJooyung Han def EmitAssert(self, assert_expression): 93*5f39d1b3SJooyung Han if self.debug: 94*5f39d1b3SJooyung Han self.EmitCall1('assert', assert_expression) 95*5f39d1b3SJooyung Han 96*5f39d1b3SJooyung Han def EmitHeaderBegin(self, header_name, includes=None): 97*5f39d1b3SJooyung Han if includes is None: 98*5f39d1b3SJooyung Han includes = [] 99*5f39d1b3SJooyung Han if self.header_name: 100*5f39d1b3SJooyung Han raise HeaderError('Header already defined.') 101*5f39d1b3SJooyung Han self.EmitPreprocessor1('ifndef', (header_name + '_H_').upper()) 102*5f39d1b3SJooyung Han self.EmitPreprocessor1('define', (header_name + '_H_').upper()) 103*5f39d1b3SJooyung Han self.EmitNewline() 104*5f39d1b3SJooyung Han if includes: 105*5f39d1b3SJooyung Han for include in includes: 106*5f39d1b3SJooyung Han self.EmitInclude(include) 107*5f39d1b3SJooyung Han self.EmitNewline() 108*5f39d1b3SJooyung Han self.header_name = header_name 109*5f39d1b3SJooyung Han 110*5f39d1b3SJooyung Han def EmitHeaderEnd(self): 111*5f39d1b3SJooyung Han if not self.header_name: 112*5f39d1b3SJooyung Han raise HeaderError('Header undefined.') 113*5f39d1b3SJooyung Han self.EmitPreprocessor1('endif', 114*5f39d1b3SJooyung Han ' // %s' % (self.header_name + '_H_').upper()) 115*5f39d1b3SJooyung Han self.header_name = None 116*5f39d1b3SJooyung Han 117*5f39d1b3SJooyung Han def EmitMemberFunctionBegin(self, class_name, class_template_params, 118*5f39d1b3SJooyung Han class_specializations, function_name, 119*5f39d1b3SJooyung Han function_params, return_type): 120*5f39d1b3SJooyung Han """Emit member function of a template/specialized class.""" 121*5f39d1b3SJooyung Han if class_template_params or class_specializations: 122*5f39d1b3SJooyung Han self.EmitIndented('template<%s>' % ', '.join(class_template_params)) 123*5f39d1b3SJooyung Han 124*5f39d1b3SJooyung Han if class_specializations: 125*5f39d1b3SJooyung Han class_name += '<%s>' % ', '.join(map(str, class_specializations)) 126*5f39d1b3SJooyung Han 127*5f39d1b3SJooyung Han self.EmitIndented('%s %s::%s(%s) {' % ( 128*5f39d1b3SJooyung Han return_type, class_name, function_name, 129*5f39d1b3SJooyung Han ', '.join(['%s %s' % (t, n) for (t, n) in function_params]))) 130*5f39d1b3SJooyung Han self.PushIndent() 131*5f39d1b3SJooyung Han 132*5f39d1b3SJooyung Han def EmitFunctionBegin(self, function_name, params, return_type): 133*5f39d1b3SJooyung Han self.EmitIndented('%s %s(%s) {' % 134*5f39d1b3SJooyung Han (return_type, function_name, 135*5f39d1b3SJooyung Han ', '.join(['%s %s' % (t, n) for (t, n) in params]))) 136*5f39d1b3SJooyung Han self.PushIndent() 137*5f39d1b3SJooyung Han 138*5f39d1b3SJooyung Han def EmitFunctionEnd(self): 139*5f39d1b3SJooyung Han self.PopIndent() 140*5f39d1b3SJooyung Han self.EmitIndented('}') 141*5f39d1b3SJooyung Han self.EmitNewline() 142*5f39d1b3SJooyung Han 143*5f39d1b3SJooyung Han def EmitClassBegin(self, class_name, template_params, specializations, 144*5f39d1b3SJooyung Han base_classes): 145*5f39d1b3SJooyung Han """Emit class block header.""" 146*5f39d1b3SJooyung Han self.classes.append(class_name) 147*5f39d1b3SJooyung Han if template_params or specializations: 148*5f39d1b3SJooyung Han self.EmitIndented('template<%s>' % ', '.join(template_params)) 149*5f39d1b3SJooyung Han 150*5f39d1b3SJooyung Han class_name_extended = class_name 151*5f39d1b3SJooyung Han if specializations: 152*5f39d1b3SJooyung Han class_name_extended += '<%s>' % ', '.join(map(str, specializations)) 153*5f39d1b3SJooyung Han if base_classes: 154*5f39d1b3SJooyung Han class_name_extended += ' : ' + ', '.join(base_classes) 155*5f39d1b3SJooyung Han self.EmitIndented('class %s {' % class_name_extended) 156*5f39d1b3SJooyung Han self.PushIndent() 157*5f39d1b3SJooyung Han 158*5f39d1b3SJooyung Han def EmitClassEnd(self): 159*5f39d1b3SJooyung Han if not self.classes: 160*5f39d1b3SJooyung Han raise ClassError('No class on stack.') 161*5f39d1b3SJooyung Han self.classes.pop() 162*5f39d1b3SJooyung Han self.PopIndent() 163*5f39d1b3SJooyung Han self.EmitIndented('};') 164*5f39d1b3SJooyung Han self.EmitNewline() 165*5f39d1b3SJooyung Han 166*5f39d1b3SJooyung Han def EmitAccessModifier(self, modifier): 167*5f39d1b3SJooyung Han if not self.classes: 168*5f39d1b3SJooyung Han raise ClassError('No class on stack.') 169*5f39d1b3SJooyung Han self.PopIndent() 170*5f39d1b3SJooyung Han self.EmitIndented(' %s:' % modifier) 171*5f39d1b3SJooyung Han self.PushIndent() 172*5f39d1b3SJooyung Han 173*5f39d1b3SJooyung Han def EmitNamespaceBegin(self, namespace): 174*5f39d1b3SJooyung Han self.EmitCodeNoSemicolon('namespace %s {' % namespace) 175*5f39d1b3SJooyung Han self.namespaces.append(namespace) 176*5f39d1b3SJooyung Han 177*5f39d1b3SJooyung Han def EmitNamespaceEnd(self): 178*5f39d1b3SJooyung Han if not self.namespaces: 179*5f39d1b3SJooyung Han raise NamespaceError('No namespace on stack.') 180*5f39d1b3SJooyung Han self.EmitCodeNoSemicolon('} // namespace %s' % self.namespaces.pop()) 181*5f39d1b3SJooyung Han 182*5f39d1b3SJooyung Han def EmitComment(self, comment): 183*5f39d1b3SJooyung Han self.EmitIndented('// ' + comment) 184*5f39d1b3SJooyung Han 185*5f39d1b3SJooyung Han def EmitOpenBracket(self, pre_bracket=None): 186*5f39d1b3SJooyung Han if pre_bracket: 187*5f39d1b3SJooyung Han self.EmitIndented('%s {' % pre_bracket) 188*5f39d1b3SJooyung Han else: 189*5f39d1b3SJooyung Han self.EmitIndented('{') 190*5f39d1b3SJooyung Han self.PushIndent() 191*5f39d1b3SJooyung Han 192*5f39d1b3SJooyung Han def EmitCloseBracket(self): 193*5f39d1b3SJooyung Han self.PopIndent() 194*5f39d1b3SJooyung Han self.EmitIndented('}') 195*5f39d1b3SJooyung Han 196*5f39d1b3SJooyung Han def EmitSwitch(self, switch): 197*5f39d1b3SJooyung Han self.EmitOpenBracket('switch (%s)' % switch) 198*5f39d1b3SJooyung Han 199*5f39d1b3SJooyung Han def EmitSwitchEnd(self): 200*5f39d1b3SJooyung Han self.EmitCloseBracket() 201*5f39d1b3SJooyung Han 202*5f39d1b3SJooyung Han def EmitCase(self, value): 203*5f39d1b3SJooyung Han self.EmitCodeNoSemicolon('case %s:' % value) 204*5f39d1b3SJooyung Han 205*5f39d1b3SJooyung Han def EmitBreak(self): 206*5f39d1b3SJooyung Han self.EmitCode('break') 207*5f39d1b3SJooyung Han 208*5f39d1b3SJooyung Han def EmitIf(self, condition): 209*5f39d1b3SJooyung Han self.EmitOpenBracket('if (%s)' % condition) 210*5f39d1b3SJooyung Han 211*5f39d1b3SJooyung Han def EmitElse(self): 212*5f39d1b3SJooyung Han self.PopIndent() 213*5f39d1b3SJooyung Han self.EmitCodeNoSemicolon('} else {') 214*5f39d1b3SJooyung Han self.PushIndent() 215*5f39d1b3SJooyung Han 216*5f39d1b3SJooyung Han def EmitEndif(self): 217*5f39d1b3SJooyung Han self.EmitCloseBracket() 218*5f39d1b3SJooyung Han 219*5f39d1b3SJooyung Han def Scope(self, scope, value): 220*5f39d1b3SJooyung Han return '%s::%s' % (scope, value) 221