lambda-graphs 0.1.4__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.
Files changed (45) hide show
  1. lambda_graphs/__init__.py +18 -0
  2. lambda_graphs/__main__.py +7 -0
  3. lambda_graphs/cli.py +183 -0
  4. lambda_graphs/codeviews/AST/AST.py +120 -0
  5. lambda_graphs/codeviews/AST/AST_driver.py +37 -0
  6. lambda_graphs/codeviews/AST/__init__.py +0 -0
  7. lambda_graphs/codeviews/CFG/CFG.py +42 -0
  8. lambda_graphs/codeviews/CFG/CFG_c.py +1182 -0
  9. lambda_graphs/codeviews/CFG/CFG_cpp.py +5604 -0
  10. lambda_graphs/codeviews/CFG/CFG_driver.py +45 -0
  11. lambda_graphs/codeviews/CFG/CFG_java.py +1722 -0
  12. lambda_graphs/codeviews/CFG/__init__.py +0 -0
  13. lambda_graphs/codeviews/CST/CST_driver.py +70 -0
  14. lambda_graphs/codeviews/CST/__init__.py +0 -0
  15. lambda_graphs/codeviews/DFG/DFG_driver.py +42 -0
  16. lambda_graphs/codeviews/DFG/__init__.py +0 -0
  17. lambda_graphs/codeviews/SDFG/SDFG.py +135 -0
  18. lambda_graphs/codeviews/SDFG/SDFG_c.py +2041 -0
  19. lambda_graphs/codeviews/SDFG/SDFG_cpp.py +4030 -0
  20. lambda_graphs/codeviews/SDFG/SDFG_java.py +1618 -0
  21. lambda_graphs/codeviews/SDFG/__init__.py +0 -0
  22. lambda_graphs/codeviews/__init__.py +0 -0
  23. lambda_graphs/codeviews/combined_graph/__init__.py +0 -0
  24. lambda_graphs/codeviews/combined_graph/combined_driver.py +163 -0
  25. lambda_graphs/tree_parser/__init__.py +0 -0
  26. lambda_graphs/tree_parser/c_parser.py +565 -0
  27. lambda_graphs/tree_parser/cpp_parser.py +424 -0
  28. lambda_graphs/tree_parser/custom_parser.py +66 -0
  29. lambda_graphs/tree_parser/java_parser.py +254 -0
  30. lambda_graphs/tree_parser/parser_driver.py +54 -0
  31. lambda_graphs/utils/DFG_utils.py +44 -0
  32. lambda_graphs/utils/__init__.py +0 -0
  33. lambda_graphs/utils/c_nodes.py +431 -0
  34. lambda_graphs/utils/cpp_nodes.py +1331 -0
  35. lambda_graphs/utils/java_nodes.py +756 -0
  36. lambda_graphs/utils/multi_file_merger.py +444 -0
  37. lambda_graphs/utils/postprocessor.py +83 -0
  38. lambda_graphs/utils/preprocessor.py +68 -0
  39. lambda_graphs/utils/src_parser.py +23 -0
  40. lambda_graphs-0.1.4.dist-info/METADATA +380 -0
  41. lambda_graphs-0.1.4.dist-info/RECORD +45 -0
  42. lambda_graphs-0.1.4.dist-info/WHEEL +5 -0
  43. lambda_graphs-0.1.4.dist-info/entry_points.txt +2 -0
  44. lambda_graphs-0.1.4.dist-info/licenses/LICENSE +21 -0
  45. lambda_graphs-0.1.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,431 @@
1
+ statement_types = {
2
+ "node_list_type": [
3
+ "declaration",
4
+ "expression_statement",
5
+ "labeled_statement",
6
+ "if_statement",
7
+ "while_statement",
8
+ "for_statement",
9
+ "do_statement",
10
+ "break_statement",
11
+ "continue_statement",
12
+ "return_statement",
13
+ "switch_statement",
14
+ "function_definition",
15
+ "case_statement",
16
+ "goto_statement",
17
+ "compound_statement",
18
+ "preproc_include",
19
+ "preproc_def",
20
+ "preproc_function_def",
21
+ "preproc_call",
22
+ "preproc_if",
23
+ "preproc_ifdef",
24
+ "preproc_elif",
25
+ "preproc_else",
26
+ ],
27
+ "non_control_statement": [
28
+ "declaration",
29
+ "expression_statement",
30
+ "preproc_include",
31
+ "preproc_def",
32
+ "preproc_function_def",
33
+ "preproc_call",
34
+ ],
35
+ "control_statement": [
36
+ "if_statement",
37
+ "while_statement",
38
+ "for_statement",
39
+ "do_statement",
40
+ "break_statement",
41
+ "continue_statement",
42
+ "return_statement",
43
+ "switch_statement",
44
+ "goto_statement",
45
+ "case_statement",
46
+ "preproc_if",
47
+ "preproc_ifdef",
48
+ "preproc_elif",
49
+ "preproc_else",
50
+ ],
51
+ "loop_control_statement": [
52
+ "while_statement",
53
+ "for_statement",
54
+ "do_statement",
55
+ ],
56
+ "not_implemented": [],
57
+ "inner_node_type": [
58
+ "declaration",
59
+ "expression_statement",
60
+ ],
61
+ "outer_node_type": ["for_statement"],
62
+ "statement_holders": [
63
+ "compound_statement",
64
+ "translation_unit",
65
+ "case_statement",
66
+ "function_definition",
67
+ ],
68
+ "definition_types": [
69
+ "function_definition",
70
+ "declaration",
71
+ "struct_specifier",
72
+ "union_specifier",
73
+ "enum_specifier",
74
+ ],
75
+ }
76
+
77
+ function_return_types = [
78
+ "primitive_type",
79
+ "type_identifier",
80
+ "sized_type_specifier",
81
+ "struct_specifier",
82
+ "union_specifier",
83
+ "enum_specifier",
84
+ "pointer_declarator",
85
+ ]
86
+
87
+
88
+ def extract_parameter_type(param_node):
89
+ """
90
+ Extract the full type of a parameter declaration, including qualifiers and pointers.
91
+
92
+ Examples:
93
+ - const uint32_t *in_arr -> 'uint32_t*'
94
+ - size_t n -> 'size_t'
95
+ - char **argv -> 'char**'
96
+ - const int * const ptr -> 'int*'
97
+ - int arr[] -> 'int*' (array parameters decay to pointers)
98
+ - int arr[][10] -> 'int*' (multi-dimensional arrays decay to pointers)
99
+
100
+ Returns: string representing the parameter type
101
+ """
102
+ if param_node.type != "parameter_declaration":
103
+ return "unknown"
104
+
105
+ base_type = None
106
+ pointer_count = 0
107
+
108
+ for child in param_node.children:
109
+ if child.type == "type_qualifier":
110
+ continue
111
+
112
+ if child.type in [
113
+ "primitive_type",
114
+ "type_identifier",
115
+ "sized_type_specifier",
116
+ "struct_specifier",
117
+ "union_specifier",
118
+ "enum_specifier",
119
+ ]:
120
+ base_type = child.text.decode("utf-8")
121
+
122
+ elif child.type == "pointer_declarator":
123
+ pointer_text = child.text.decode("utf-8")
124
+ pointer_count = pointer_text.count("*")
125
+
126
+ elif child.type == "array_declarator":
127
+
128
+ def count_array_dimensions(node):
129
+ count = 0
130
+ if node.type == "array_declarator":
131
+ count = 1
132
+ for subchild in node.children:
133
+ if subchild.type == "array_declarator":
134
+ count += count_array_dimensions(subchild)
135
+ return count
136
+
137
+ pointer_count = count_array_dimensions(child)
138
+
139
+ if base_type:
140
+ return base_type + ("*" * pointer_count)
141
+
142
+ return "unknown"
143
+
144
+
145
+ def get_child_of_type(node, type_list):
146
+ out = list(filter(lambda x: x.type in type_list, node.children))
147
+ if len(out) > 0:
148
+ return out[0]
149
+ else:
150
+ return None
151
+
152
+
153
+ def return_switch_child(node):
154
+ bfs_queue = []
155
+ for child in node.children:
156
+ bfs_queue.append(child)
157
+ while bfs_queue != []:
158
+ top = bfs_queue.pop(0)
159
+ if top.type == "switch_statement":
160
+ return top
161
+ for child in top.children:
162
+ bfs_queue.append(child)
163
+ return None
164
+
165
+
166
+ def get_function_signature(node):
167
+ """
168
+ Extract function signature from function definition or declaration.
169
+
170
+ For variadic functions (e.g., int foo(int x, ...)), the signature includes
171
+ '...' as the last element to indicate variable arguments.
172
+
173
+ Handles complex types including pointers, const qualifiers, etc.
174
+ Examples:
175
+ - int foo(const uint32_t *arr, size_t n) -> ('uint32_t*', 'size_t')
176
+ - char* bar(char **argv, int argc) -> ('char**', 'int')
177
+
178
+ Returns: tuple of parameter types, e.g., ('int', 'char*') or ('int', '...')
179
+ """
180
+ signature = []
181
+ for child in node.children:
182
+ if child.type == "function_declarator":
183
+ param_list = child.child_by_field_name("parameters")
184
+ if param_list:
185
+ for param in param_list.children:
186
+ if param.type == "parameter_declaration":
187
+ param_type = extract_parameter_type(param)
188
+ signature.append(param_type)
189
+ elif param.type == "variadic_parameter":
190
+ signature.append("...")
191
+ return tuple(signature)
192
+
193
+
194
+ def get_function_name(node):
195
+ """Extract function name from function_definition"""
196
+ for child in node.children:
197
+ if child.type == "function_declarator":
198
+ for dchild in child.children:
199
+ if dchild.type == "identifier":
200
+ return dchild.text.decode("utf-8")
201
+ elif dchild.type == "pointer_declarator":
202
+ for pchild in dchild.children:
203
+ if pchild.type == "identifier":
204
+ return pchild.text.decode("utf-8")
205
+ return None
206
+
207
+
208
+ def is_function_declaration(node):
209
+ """
210
+ Check if a declaration node is a function declaration (forward declaration/prototype).
211
+
212
+ Function declarations have the form: int foo(int x);
213
+ They contain a function_declarator child but no compound_statement (function body).
214
+
215
+ Returns True if the node is a function declaration, False otherwise.
216
+ """
217
+ if node.type != "declaration":
218
+ return False
219
+
220
+ for child in node.children:
221
+ if child.type == "function_declarator":
222
+ return True
223
+
224
+ return False
225
+
226
+
227
+ def get_nodes(root_node=None, node_list={}, graph_node_list=[], index={}, records={}):
228
+ """
229
+ Returns statement level nodes recursively from the C AST.
230
+ Extracts nodes that will become CFG nodes and populates records dictionary.
231
+ """
232
+
233
+ if (
234
+ root_node.type == "parenthesized_expression"
235
+ and root_node.parent is not None
236
+ and root_node.parent.type == "do_statement"
237
+ ):
238
+ label = "while" + root_node.text.decode("UTF-8")
239
+ type_label = "while"
240
+ node_list[(root_node.start_point, root_node.end_point, root_node.type)] = (
241
+ root_node
242
+ )
243
+ graph_node_list.append(
244
+ (
245
+ index[(root_node.start_point, root_node.end_point, root_node.type)],
246
+ root_node.start_point[0],
247
+ label,
248
+ type_label,
249
+ )
250
+ )
251
+
252
+ elif root_node.type in statement_types["node_list_type"]:
253
+ if (
254
+ root_node.type in statement_types["inner_node_type"]
255
+ and root_node.parent is not None
256
+ and root_node.parent.type in statement_types["outer_node_type"]
257
+ ):
258
+ if root_node.parent.type == "for_statement":
259
+ body = root_node.parent.child_by_field_name("body")
260
+ if body != root_node:
261
+ pass
262
+ else:
263
+ node_list[
264
+ (root_node.start_point, root_node.end_point, root_node.type)
265
+ ] = root_node
266
+ label = root_node.text.decode("UTF-8")
267
+ type_label = root_node.type
268
+ graph_node_list.append(
269
+ (
270
+ index[
271
+ (
272
+ root_node.start_point,
273
+ root_node.end_point,
274
+ root_node.type,
275
+ )
276
+ ],
277
+ root_node.start_point[0],
278
+ label,
279
+ type_label,
280
+ )
281
+ )
282
+
283
+ elif (
284
+ root_node.type in statement_types["inner_node_type"]
285
+ and return_switch_child(root_node) is not None
286
+ ):
287
+ switch_child = return_switch_child(root_node)
288
+ child_index = index[
289
+ (switch_child.start_point, switch_child.end_point, switch_child.type)
290
+ ]
291
+ current_index = index[
292
+ (root_node.start_point, root_node.end_point, root_node.type)
293
+ ]
294
+ records["switch_child_map"][current_index] = child_index
295
+
296
+ else:
297
+ node_list[(root_node.start_point, root_node.end_point, root_node.type)] = (
298
+ root_node
299
+ )
300
+ label = root_node.text.decode("UTF-8")
301
+ type_label = root_node.type
302
+
303
+ if root_node.type == "function_definition":
304
+ label = ""
305
+ for child in root_node.children:
306
+ if child.type != "compound_statement":
307
+ label = label + " " + child.text.decode("utf-8")
308
+
309
+ func_name = get_function_name(root_node)
310
+ func_index = index[
311
+ (root_node.start_point, root_node.end_point, root_node.type)
312
+ ]
313
+ type_label = "function_definition"
314
+
315
+ if func_name:
316
+ signature = get_function_signature(root_node)
317
+ records["function_list"][(func_name, signature)] = func_index
318
+
319
+ if func_name == "main":
320
+ records["main_function"] = func_index
321
+
322
+ return_type = None
323
+ for child in root_node.children:
324
+ if child.type in function_return_types:
325
+ return_type = child.text.decode("utf-8")
326
+ break
327
+ records["return_type"][(func_name, signature)] = return_type
328
+
329
+ graph_node_list.append(
330
+ (func_index, root_node.start_point[0], label, type_label)
331
+ )
332
+
333
+ elif root_node.type == "if_statement":
334
+ condition = root_node.child_by_field_name("condition")
335
+ if condition:
336
+ label = "if" + condition.text.decode("UTF-8")
337
+ else:
338
+ label = "if(...)"
339
+ type_label = "if"
340
+
341
+ elif root_node.type == "for_statement":
342
+ init = root_node.child_by_field_name("initializer")
343
+ init_str = init.text.decode("UTF-8") + ";" if init else ""
344
+
345
+ condition = root_node.child_by_field_name("condition")
346
+ cond_str = condition.text.decode("UTF-8") if condition else ""
347
+
348
+ update = root_node.child_by_field_name("update")
349
+ update_str = update.text.decode("UTF-8") if update else ""
350
+
351
+ label = "for(" + init_str + " " + cond_str + "; " + update_str + ")"
352
+ type_label = "for"
353
+
354
+ elif root_node.type == "while_statement":
355
+ condition = root_node.child_by_field_name("condition")
356
+ if condition:
357
+ label = "while" + condition.text.decode("UTF-8")
358
+ else:
359
+ label = "while(...)"
360
+ type_label = "while"
361
+
362
+ elif root_node.type == "do_statement":
363
+ label = "do"
364
+ type_label = "do"
365
+
366
+ elif root_node.type == "switch_statement":
367
+ condition = root_node.child_by_field_name("condition")
368
+ if condition:
369
+ label = "switch" + condition.text.decode("UTF-8")
370
+ else:
371
+ label = "switch(...)"
372
+ type_label = "switch"
373
+
374
+ elif root_node.type == "case_statement":
375
+ value_node = root_node.child_by_field_name("value")
376
+ if value_node:
377
+ label = "case " + value_node.text.decode("UTF-8") + ":"
378
+ else:
379
+ if root_node.children and root_node.children[0].type == "default":
380
+ label = "default:"
381
+ else:
382
+ label = "case:"
383
+ type_label = "case"
384
+
385
+ elif root_node.type == "labeled_statement":
386
+ label_node = root_node.child_by_field_name("label")
387
+ if label_node:
388
+ label_name = label_node.text.decode("UTF-8")
389
+ label = label_name + ":"
390
+ current_index = index[
391
+ (root_node.start_point, root_node.end_point, root_node.type)
392
+ ]
393
+ records["label_statement_map"][label_name] = (
394
+ root_node.start_point,
395
+ root_node.end_point,
396
+ root_node.type,
397
+ )
398
+ type_label = "label"
399
+
400
+ elif root_node.type == "return_statement":
401
+ label = root_node.text.decode("UTF-8")
402
+ type_label = "return"
403
+
404
+ elif root_node.type == "break_statement":
405
+ label = "break;"
406
+ type_label = "break"
407
+
408
+ elif root_node.type == "continue_statement":
409
+ label = "continue;"
410
+ type_label = "continue"
411
+
412
+ elif root_node.type == "goto_statement":
413
+ label_node = root_node.child_by_field_name("label")
414
+ if label_node:
415
+ label = "goto " + label_node.text.decode("UTF-8") + ";"
416
+ else:
417
+ label = "goto;"
418
+ type_label = "goto"
419
+
420
+ if root_node.type not in ["function_definition"]:
421
+ node_index = index[
422
+ (root_node.start_point, root_node.end_point, root_node.type)
423
+ ]
424
+ graph_node_list.append(
425
+ (node_index, root_node.start_point[0], label, type_label)
426
+ )
427
+
428
+ for child in root_node.children:
429
+ get_nodes(child, node_list, graph_node_list, index, records)
430
+
431
+ return node_list, graph_node_list, records