python-cc 0.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -0,0 +1,238 @@
1
+ import llvmlite.ir as ir
2
+ import llvmlite.binding as llvm
3
+ import os
4
+ import subprocess
5
+ import shutil
6
+ import sys
7
+ from ..codegen.c_codegen import LLVMCodeGenerator, postprocess_ir_text
8
+ from ..parse.c_parser import CParser
9
+ from ..preprocessor import preprocess
10
+
11
+ from ctypes import (
12
+ CFUNCTYPE,
13
+ c_double,
14
+ c_int64,
15
+ c_int32,
16
+ c_int16,
17
+ c_int8,
18
+ c_char_p,
19
+ POINTER,
20
+ )
21
+
22
+
23
+ def get_c_type_from_ir(ir_type):
24
+ if isinstance(ir_type, ir.VoidType):
25
+ return None
26
+ elif isinstance(ir_type, ir.IntType):
27
+ if ir_type.width == 8:
28
+ return c_int8
29
+ elif ir_type.width == 16:
30
+ return c_int16
31
+ elif ir_type.width == 32:
32
+ return c_int32
33
+ return c_int64
34
+ elif isinstance(ir_type, ir.DoubleType):
35
+ return c_double
36
+ elif isinstance(ir_type, ir.PointerType):
37
+ point_type = get_c_type_from_ir(ir_type.pointee)
38
+ return POINTER(point_type)
39
+ else:
40
+ return c_int64
41
+
42
+
43
+ class CEvaluator(object):
44
+
45
+ def __init__(self):
46
+
47
+ llvm.initialize_native_target()
48
+ llvm.initialize_native_asmprinter()
49
+
50
+ self.codegen = LLVMCodeGenerator()
51
+ self.parser = CParser()
52
+ self.target = llvm.Target.from_default_triple()
53
+ self.ee = None
54
+
55
+ def evaluate(
56
+ self,
57
+ codestr,
58
+ optimize=True,
59
+ llvmdump=False,
60
+ args=None,
61
+ base_dir=None,
62
+ use_system_cpp=None,
63
+ prog_args=None,
64
+ ):
65
+ if use_system_cpp is None:
66
+ use_system_cpp = self._has_system_cpp()
67
+ if use_system_cpp:
68
+ codestr = self._system_cpp(codestr, base_dir)
69
+ import re
70
+
71
+ codestr = re.sub(
72
+ r"typedef\s+(int|char|short|long|double|float|void)\s+\1\s*;",
73
+ "",
74
+ codestr,
75
+ )
76
+ else:
77
+ codestr = preprocess(codestr, base_dir=base_dir)
78
+ ast = self.parser.parse(codestr)
79
+ self.codegen = LLVMCodeGenerator()
80
+ self.codegen.generate_code(ast)
81
+ ir_text = postprocess_ir_text(str(self.codegen.module))
82
+
83
+ if llvmdump:
84
+ with open("temp.ir", "w") as f:
85
+ f.write(ir_text)
86
+
87
+ llvmmod = llvm.parse_assembly(ir_text)
88
+
89
+ if optimize:
90
+ target_machine = self.target.create_target_machine()
91
+ pto = llvm.create_pipeline_tuning_options(speed_level=2, size_level=0)
92
+ pb = llvm.create_pass_builder(target_machine, pto)
93
+ pm = pb.getModulePassManager()
94
+ pm.run(llvmmod, pb)
95
+
96
+ if llvmdump:
97
+ tempbcode = str(llvmmod)
98
+ with open("temp.ooptimize.bcode", "w") as f:
99
+ f.write(tempbcode)
100
+
101
+ target_machine = self.target.create_target_machine()
102
+
103
+ self.ee = llvm.create_mcjit_compiler(llvmmod, target_machine)
104
+ self.ee.finalize_object()
105
+
106
+ if llvmdump:
107
+ tempbcode = target_machine.emit_assembly(llvmmod)
108
+ with open("temp.bcode", "w") as f:
109
+ f.write(tempbcode)
110
+
111
+ return_type = get_c_type_from_ir(self.codegen.return_type)
112
+
113
+ main_addr = self.ee.get_function_address("main")
114
+
115
+ if prog_args:
116
+ # Build argc/argv for main(int argc, char **argv)
117
+ argv_strings = ["pcc"] + list(prog_args)
118
+ argc = len(argv_strings)
119
+ ArgvType = c_char_p * (argc + 1)
120
+ argv = ArgvType(*[s.encode() for s in argv_strings], None)
121
+ fptr = CFUNCTYPE(return_type, c_int32, POINTER(c_char_p))(main_addr)
122
+ result = fptr(argc, argv)
123
+ else:
124
+ fptr = CFUNCTYPE(return_type)(main_addr)
125
+ if args is None:
126
+ args = []
127
+ result = fptr(*args)
128
+
129
+ return result
130
+
131
+ @staticmethod
132
+ def _has_system_cpp():
133
+ return shutil.which("cc") is not None or shutil.which("gcc") is not None
134
+
135
+ @staticmethod
136
+ def _system_cpp(source, base_dir=None):
137
+ """Use system C preprocessor (cc -E) for fast preprocessing.
138
+
139
+ Uses -nostdinc + fake libc headers so output is pycparser-compatible.
140
+ """
141
+ import tempfile
142
+
143
+ cc = shutil.which("cc") or shutil.which("gcc") or shutil.which("clang")
144
+ if not cc:
145
+ raise RuntimeError("No system C compiler found for preprocessing")
146
+
147
+ # Find fake libc headers (shipped with pcc)
148
+ # __file__ = pcc/evaluater/c_evaluator.py → project root is 2 levels up
149
+ pcc_root = os.path.dirname(
150
+ os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
151
+ )
152
+ fake_libc = os.path.join(pcc_root, "utils", "fake_libc_include")
153
+ base_dir = os.path.abspath(base_dir) if base_dir else os.getcwd()
154
+
155
+ with tempfile.NamedTemporaryFile(
156
+ mode="w", suffix=".c", dir=base_dir, delete=False
157
+ ) as f:
158
+ f.write(source)
159
+ tmp_path = f.name
160
+ try:
161
+ platform_defs = []
162
+ if sys.platform == "darwin":
163
+ # fake libc headers do not provide the stdio macro remaps that
164
+ # macOS uses for FILE* globals.
165
+ platform_defs.extend(
166
+ [
167
+ "-Dstdin=__stdinp",
168
+ "-Dstdout=__stdoutp",
169
+ "-Dstderr=__stderrp",
170
+ ]
171
+ )
172
+
173
+ cmd = [
174
+ cc,
175
+ "-E",
176
+ "-P",
177
+ "-nostdinc", # skip real system headers
178
+ "-isystem",
179
+ fake_libc, # fake libc as system headers
180
+ "-I",
181
+ base_dir or ".", # project headers
182
+ # Standard limits (fake headers don't have these)
183
+ "-DLLONG_MAX=9223372036854775807LL",
184
+ "-DLLONG_MIN=(-9223372036854775807LL-1)",
185
+ "-DULLONG_MAX=18446744073709551615ULL",
186
+ "-DLONG_MAX=9223372036854775807L",
187
+ "-DINT_MAX=2147483647",
188
+ "-DINT_MIN=(-2147483647-1)",
189
+ "-DLONG_MIN=(-9223372036854775807L-1)",
190
+ "-DUINT_MAX=4294967295U",
191
+ "-DCHAR_BIT=8",
192
+ "-DSHRT_MAX=32767",
193
+ "-DUSHRT_MAX=65535",
194
+ "-DCHAR_MAX=127",
195
+ "-DUCHAR_MAX=255",
196
+ "-DSIG_DFL=0",
197
+ "-DSIG_IGN=1",
198
+ "-DSIGINT=2",
199
+ "-DCLOCKS_PER_SEC=1000000",
200
+ "-DLC_ALL=0",
201
+ "-DLC_COLLATE=1",
202
+ "-DLC_CTYPE=2",
203
+ "-DLC_MONETARY=3",
204
+ "-DLC_NUMERIC=4",
205
+ "-DLC_TIME=5",
206
+ "-Doffsetof(t,m)=((long)&((t*)0)->m)",
207
+ "-DDBL_MANT_DIG=53",
208
+ "-DFLT_MANT_DIG=24",
209
+ "-DDBL_MAX_EXP=1024",
210
+ "-DFLT_MAX_EXP=128",
211
+ "-DDBL_MAX=1.7976931348623158e+308",
212
+ "-DHUGE_VAL=1e309",
213
+ "-DHUGE_VALF=1e39f",
214
+ "-DDBL_MAX_10_EXP=308",
215
+ "-DFLT_MAX_10_EXP=38",
216
+ "-DDBL_MIN_EXP=-1021",
217
+ "-DDBL_EPSILON=2.2204460492503131e-16",
218
+ "-D_IONBF=2",
219
+ "-D_IOLBF=1",
220
+ "-D_IOFBF=0",
221
+ # GCC/Clang extensions
222
+ "-D__attribute__(x)=",
223
+ "-D__extension__=",
224
+ # Disable Lua's computed goto and builtins
225
+ "-DLUA_USE_JUMPTABLE=0",
226
+ "-DLUA_NOBUILTIN",
227
+ *platform_defs,
228
+ tmp_path,
229
+ ]
230
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
231
+ if result.returncode == 0:
232
+ return result.stdout
233
+ # Fallback: without -nostdinc
234
+ cmd = [cc, "-E", "-P", "-I", base_dir or ".", tmp_path]
235
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
236
+ return result.stdout
237
+ finally:
238
+ os.unlink(tmp_path)
File without changes
@@ -0,0 +1,399 @@
1
+ #------------------------------------------------------------------------------
2
+ # pycparser: c_generator.py
3
+ #
4
+ # C code generator from pycparser AST nodes.
5
+ #
6
+ # Copyright (C) 2008-2015, Eli Bendersky
7
+ # License: BSD
8
+ #------------------------------------------------------------------------------
9
+ from ..ast import c_ast
10
+
11
+
12
+ class CGenerator(object):
13
+ """ Uses the same visitor pattern as c_ast.NodeVisitor, but modified to
14
+ return a value from each visit method, using string accumulation in
15
+ generic_visit.
16
+ """
17
+ def __init__(self):
18
+ # Statements start with indentation of self.indent_level spaces, using
19
+ # the _make_indent method
20
+ #
21
+ self.indent_level = 0
22
+
23
+ def _make_indent(self):
24
+ return ' ' * self.indent_level
25
+
26
+ def visit(self, node):
27
+ method = 'visit_' + node.__class__.__name__
28
+ return getattr(self, method, self.generic_visit)(node)
29
+
30
+ def generic_visit(self, node):
31
+ #~ print('generic:', type(node))
32
+ if node is None:
33
+ return ''
34
+ else:
35
+ return ''.join(self.visit(c) for c_name, c in node.children())
36
+
37
+ def visit_Constant(self, n):
38
+ return n.value
39
+
40
+ def visit_ID(self, n):
41
+ return n.name
42
+
43
+ def visit_ArrayRef(self, n):
44
+ arrref = self._parenthesize_unless_simple(n.name)
45
+ return arrref + '[' + self.visit(n.subscript) + ']'
46
+
47
+ def visit_StructRef(self, n):
48
+ sref = self._parenthesize_unless_simple(n.name)
49
+ return sref + n.type + self.visit(n.field)
50
+
51
+ def visit_FuncCall(self, n):
52
+ fref = self._parenthesize_unless_simple(n.name)
53
+ return fref + '(' + self.visit(n.args) + ')'
54
+
55
+ def visit_UnaryOp(self, n):
56
+ operand = self._parenthesize_unless_simple(n.expr)
57
+ if n.op == 'p++':
58
+ return '%s++' % operand
59
+ elif n.op == 'p--':
60
+ return '%s--' % operand
61
+ elif n.op == 'sizeof':
62
+ # Always parenthesize the argument of sizeof since it can be
63
+ # a name.
64
+ return 'sizeof(%s)' % self.visit(n.expr)
65
+ else:
66
+ return '%s%s' % (n.op, operand)
67
+
68
+ def visit_BinaryOp(self, n):
69
+ lval_str = self._parenthesize_if(n.left,
70
+ lambda d: not self._is_simple_node(d))
71
+ rval_str = self._parenthesize_if(n.right,
72
+ lambda d: not self._is_simple_node(d))
73
+ return '%s %s %s' % (lval_str, n.op, rval_str)
74
+
75
+ def visit_Assignment(self, n):
76
+ rval_str = self._parenthesize_if(
77
+ n.rvalue,
78
+ lambda n: isinstance(n, c_ast.Assignment))
79
+ return '%s %s %s' % (self.visit(n.lvalue), n.op, rval_str)
80
+
81
+ def visit_IdentifierType(self, n):
82
+ return ' '.join(n.names)
83
+
84
+ def _visit_expr(self, n):
85
+ if isinstance(n, c_ast.InitList):
86
+ return '{' + self.visit(n) + '}'
87
+ elif isinstance(n, c_ast.ExprList):
88
+ return '(' + self.visit(n) + ')'
89
+ else:
90
+ return self.visit(n)
91
+
92
+ def visit_Decl(self, n, no_type=False):
93
+ # no_type is used when a Decl is part of a DeclList, where the type is
94
+ # explicitly only for the first declaration in a list.
95
+ #
96
+ s = n.name if no_type else self._generate_decl(n)
97
+ if n.bitsize: s += ' : ' + self.visit(n.bitsize)
98
+ if n.init:
99
+ s += ' = ' + self._visit_expr(n.init)
100
+ return s
101
+
102
+ def visit_DeclList(self, n):
103
+ s = self.visit(n.decls[0])
104
+ if len(n.decls) > 1:
105
+ s += ', ' + ', '.join(self.visit_Decl(decl, no_type=True)
106
+ for decl in n.decls[1:])
107
+ return s
108
+
109
+ def visit_Typedef(self, n):
110
+ s = ''
111
+ if n.storage: s += ' '.join(n.storage) + ' '
112
+ s += self._generate_type(n.type)
113
+ return s
114
+
115
+ def visit_Cast(self, n):
116
+ s = '(' + self._generate_type(n.to_type) + ')'
117
+ return s + ' ' + self._parenthesize_unless_simple(n.expr)
118
+
119
+ def visit_ExprList(self, n):
120
+ visited_subexprs = []
121
+ for expr in n.exprs:
122
+ visited_subexprs.append(self._visit_expr(expr))
123
+ return ', '.join(visited_subexprs)
124
+
125
+ def visit_InitList(self, n):
126
+ visited_subexprs = []
127
+ for expr in n.exprs:
128
+ visited_subexprs.append(self._visit_expr(expr))
129
+ return ', '.join(visited_subexprs)
130
+
131
+ def visit_Enum(self, n):
132
+ s = 'enum'
133
+ if n.name: s += ' ' + n.name
134
+ if n.values:
135
+ s += ' {'
136
+ for i, enumerator in enumerate(n.values.enumerators):
137
+ s += enumerator.name
138
+ if enumerator.value:
139
+ s += ' = ' + self.visit(enumerator.value)
140
+ if i != len(n.values.enumerators) - 1:
141
+ s += ', '
142
+ s += '}'
143
+ return s
144
+
145
+ def visit_FuncDef(self, n):
146
+ decl = self.visit(n.decl)
147
+ self.indent_level = 0
148
+ body = self.visit(n.body)
149
+ if n.param_decls:
150
+ knrdecls = ';\n'.join(self.visit(p) for p in n.param_decls)
151
+ return decl + '\n' + knrdecls + ';\n' + body + '\n'
152
+ else:
153
+ return decl + '\n' + body + '\n'
154
+
155
+ def visit_FileAST(self, n):
156
+ s = ''
157
+ for ext in n.ext:
158
+ if isinstance(ext, c_ast.FuncDef):
159
+ s += self.visit(ext)
160
+ else:
161
+ s += self.visit(ext) + ';\n'
162
+ return s
163
+
164
+ def visit_Compound(self, n):
165
+ s = self._make_indent() + '{\n'
166
+ self.indent_level += 2
167
+ if n.block_items:
168
+ s += ''.join(self._generate_stmt(stmt) for stmt in n.block_items)
169
+ self.indent_level -= 2
170
+ s += self._make_indent() + '}\n'
171
+ return s
172
+
173
+ def visit_EmptyStatement(self, n):
174
+ return ';'
175
+
176
+ def visit_ParamList(self, n):
177
+ return ', '.join(self.visit(param) for param in n.params)
178
+
179
+ def visit_Return(self, n):
180
+ s = 'return'
181
+ if n.expr: s += ' ' + self.visit(n.expr)
182
+ return s + ';'
183
+
184
+ def visit_Break(self, n):
185
+ return 'break;'
186
+
187
+ def visit_Continue(self, n):
188
+ return 'continue;'
189
+
190
+ def visit_TernaryOp(self, n):
191
+ s = self._visit_expr(n.cond) + ' ? '
192
+ s += self._visit_expr(n.iftrue) + ' : '
193
+ s += self._visit_expr(n.iffalse)
194
+ return s
195
+
196
+ def visit_If(self, n):
197
+ s = 'if ('
198
+ if n.cond: s += self.visit(n.cond)
199
+ s += ')\n'
200
+ s += self._generate_stmt(n.iftrue, add_indent=True)
201
+ if n.iffalse:
202
+ s += self._make_indent() + 'else\n'
203
+ s += self._generate_stmt(n.iffalse, add_indent=True)
204
+ return s
205
+
206
+ def visit_For(self, n):
207
+ s = 'for ('
208
+ if n.init: s += self.visit(n.init)
209
+ s += ';'
210
+ if n.cond: s += ' ' + self.visit(n.cond)
211
+ s += ';'
212
+ if n.next: s += ' ' + self.visit(n.next)
213
+ s += ')\n'
214
+ s += self._generate_stmt(n.stmt, add_indent=True)
215
+ return s
216
+
217
+ def visit_While(self, n):
218
+ s = 'while ('
219
+ if n.cond: s += self.visit(n.cond)
220
+ s += ')\n'
221
+ s += self._generate_stmt(n.stmt, add_indent=True)
222
+ return s
223
+
224
+ def visit_DoWhile(self, n):
225
+ s = 'do\n'
226
+ s += self._generate_stmt(n.stmt, add_indent=True)
227
+ s += self._make_indent() + 'while ('
228
+ if n.cond: s += self.visit(n.cond)
229
+ s += ');'
230
+ return s
231
+
232
+ def visit_Switch(self, n):
233
+ s = 'switch (' + self.visit(n.cond) + ')\n'
234
+ s += self._generate_stmt(n.stmt, add_indent=True)
235
+ return s
236
+
237
+ def visit_Case(self, n):
238
+ s = 'case ' + self.visit(n.expr) + ':\n'
239
+ for stmt in n.stmts:
240
+ s += self._generate_stmt(stmt, add_indent=True)
241
+ return s
242
+
243
+ def visit_Default(self, n):
244
+ s = 'default:\n'
245
+ for stmt in n.stmts:
246
+ s += self._generate_stmt(stmt, add_indent=True)
247
+ return s
248
+
249
+ def visit_Label(self, n):
250
+ return n.name + ':\n' + self._generate_stmt(n.stmt)
251
+
252
+ def visit_Goto(self, n):
253
+ return 'goto ' + n.name + ';'
254
+
255
+ def visit_EllipsisParam(self, n):
256
+ return '...'
257
+
258
+ def visit_Struct(self, n):
259
+ return self._generate_struct_union(n, 'struct')
260
+
261
+ def visit_Typename(self, n):
262
+ return self._generate_type(n.type)
263
+
264
+ def visit_Union(self, n):
265
+ return self._generate_struct_union(n, 'union')
266
+
267
+ def visit_NamedInitializer(self, n):
268
+ s = ''
269
+ for name in n.name:
270
+ if isinstance(name, c_ast.ID):
271
+ s += '.' + name.name
272
+ elif isinstance(name, c_ast.Constant):
273
+ s += '[' + name.value + ']'
274
+ s += ' = ' + self.visit(n.expr)
275
+ return s
276
+
277
+ def visit_FuncDecl(self, n):
278
+ return self._generate_type(n)
279
+
280
+ def _generate_struct_union(self, n, name):
281
+ """ Generates code for structs and unions. name should be either
282
+ 'struct' or union.
283
+ """
284
+ s = name + ' ' + (n.name or '')
285
+ if n.decls:
286
+ s += '\n'
287
+ s += self._make_indent()
288
+ self.indent_level += 2
289
+ s += '{\n'
290
+ for decl in n.decls:
291
+ s += self._generate_stmt(decl)
292
+ self.indent_level -= 2
293
+ s += self._make_indent() + '}'
294
+ return s
295
+
296
+ def _generate_stmt(self, n, add_indent=False):
297
+ """ Generation from a statement node. This method exists as a wrapper
298
+ for individual visit_* methods to handle different treatment of
299
+ some statements in this context.
300
+ """
301
+ typ = type(n)
302
+ if add_indent: self.indent_level += 2
303
+ indent = self._make_indent()
304
+ if add_indent: self.indent_level -= 2
305
+
306
+ if typ in (
307
+ c_ast.Decl, c_ast.Assignment, c_ast.Cast, c_ast.UnaryOp,
308
+ c_ast.BinaryOp, c_ast.TernaryOp, c_ast.FuncCall, c_ast.ArrayRef,
309
+ c_ast.StructRef, c_ast.Constant, c_ast.ID, c_ast.Typedef,
310
+ c_ast.ExprList):
311
+ # These can also appear in an expression context so no semicolon
312
+ # is added to them automatically
313
+ #
314
+ return indent + self.visit(n) + ';\n'
315
+ elif typ in (c_ast.Compound,):
316
+ # No extra indentation required before the opening brace of a
317
+ # compound - because it consists of multiple lines it has to
318
+ # compute its own indentation.
319
+ #
320
+ return self.visit(n)
321
+ else:
322
+ return indent + self.visit(n) + '\n'
323
+
324
+ def _generate_decl(self, n):
325
+ """ Generation from a Decl node.
326
+ """
327
+ s = ''
328
+ if n.funcspec: s = ' '.join(n.funcspec) + ' '
329
+ if n.storage: s += ' '.join(n.storage) + ' '
330
+ s += self._generate_type(n.type)
331
+ return s
332
+
333
+ def _generate_type(self, n, modifiers=[]):
334
+ """ Recursive generation from a type node. n is the type node.
335
+ modifiers collects the PtrDecl, ArrayDecl and FuncDecl modifiers
336
+ encountered on the way down to a TypeDecl, to allow proper
337
+ generation from it.
338
+ """
339
+ typ = type(n)
340
+ #~ print(n, modifiers)
341
+
342
+ if typ == c_ast.TypeDecl:
343
+ s = ''
344
+ if n.quals: s += ' '.join(n.quals) + ' '
345
+ s += self.visit(n.type)
346
+
347
+ nstr = n.declname if n.declname else ''
348
+ # Resolve modifiers.
349
+ # Wrap in parens to distinguish pointer to array and pointer to
350
+ # function syntax.
351
+ #
352
+ for i, modifier in enumerate(modifiers):
353
+ if isinstance(modifier, c_ast.ArrayDecl):
354
+ if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)):
355
+ nstr = '(' + nstr + ')'
356
+ nstr += '[' + self.visit(modifier.dim) + ']'
357
+ elif isinstance(modifier, c_ast.FuncDecl):
358
+ if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)):
359
+ nstr = '(' + nstr + ')'
360
+ nstr += '(' + self.visit(modifier.args) + ')'
361
+ elif isinstance(modifier, c_ast.PtrDecl):
362
+ if modifier.quals:
363
+ nstr = '* %s %s' % (' '.join(modifier.quals), nstr)
364
+ else:
365
+ nstr = '*' + nstr
366
+ if nstr: s += ' ' + nstr
367
+ return s
368
+ elif typ == c_ast.Decl:
369
+ return self._generate_decl(n.type)
370
+ elif typ == c_ast.Typename:
371
+ return self._generate_type(n.type)
372
+ elif typ == c_ast.IdentifierType:
373
+ return ' '.join(n.names) + ' '
374
+ elif typ in (c_ast.ArrayDecl, c_ast.PtrDecl, c_ast.FuncDecl):
375
+ return self._generate_type(n.type, modifiers + [n])
376
+ else:
377
+ return self.visit(n)
378
+
379
+ def _parenthesize_if(self, n, condition):
380
+ """ Visits 'n' and returns its string representation, parenthesized
381
+ if the condition function applied to the node returns True.
382
+ """
383
+ s = self._visit_expr(n)
384
+ if condition(n):
385
+ return '(' + s + ')'
386
+ else:
387
+ return s
388
+
389
+ def _parenthesize_unless_simple(self, n):
390
+ """ Common use case for _parenthesize_if
391
+ """
392
+ return self._parenthesize_if(n, lambda d: not self._is_simple_node(d))
393
+
394
+ def _is_simple_node(self, n):
395
+ """ Returns True for nodes that are "simple" - i.e. nodes that always
396
+ have higher precedence than operators.
397
+ """
398
+ return isinstance(n,( c_ast.Constant, c_ast.ID, c_ast.ArrayRef,
399
+ c_ast.StructRef, c_ast.FuncCall))
pcc/lex/__init__.py ADDED
File without changes