PyDecisionGraph 0.3.2.post1__cp315-cp315-win_amd64.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 (148) hide show
  1. decision_graph/__infra__.pxd +1 -0
  2. decision_graph/__init__.pxd +1 -0
  3. decision_graph/__init__.py +39 -0
  4. decision_graph/decision_tree/__init__.pxd +2 -0
  5. decision_graph/decision_tree/__init__.py +85 -0
  6. decision_graph/decision_tree/bake/__infra__.pxd +502 -0
  7. decision_graph/decision_tree/bake/__init__.pxd +502 -0
  8. decision_graph/decision_tree/bake/__init__.py +29 -0
  9. decision_graph/decision_tree/bake/c_action.cp315-win_amd64.pyd +0 -0
  10. decision_graph/decision_tree/bake/c_action.h +324 -0
  11. decision_graph/decision_tree/bake/c_action.pxd +54 -0
  12. decision_graph/decision_tree/bake/c_action.pyi +126 -0
  13. decision_graph/decision_tree/bake/c_action.pyx +65 -0
  14. decision_graph/decision_tree/bake/c_allocator_protocol.cp315-win_amd64.pyd +0 -0
  15. decision_graph/decision_tree/bake/c_allocator_protocol.pxd +24 -0
  16. decision_graph/decision_tree/bake/c_allocator_protocol.pyi +61 -0
  17. decision_graph/decision_tree/bake/c_allocator_protocol.pyx +109 -0
  18. decision_graph/decision_tree/bake/c_bake.cp315-win_amd64.pyd +0 -0
  19. decision_graph/decision_tree/bake/c_bake.h +629 -0
  20. decision_graph/decision_tree/bake/c_bake.pxd +52 -0
  21. decision_graph/decision_tree/bake/c_bake.pyi +151 -0
  22. decision_graph/decision_tree/bake/c_bake.pyx +142 -0
  23. decision_graph/decision_tree/bake/c_collections.cp315-win_amd64.pyd +0 -0
  24. decision_graph/decision_tree/bake/c_collections.h +692 -0
  25. decision_graph/decision_tree/bake/c_collections.pxd +52 -0
  26. decision_graph/decision_tree/bake/c_collections.pyi +193 -0
  27. decision_graph/decision_tree/bake/c_collections.pyx +161 -0
  28. decision_graph/decision_tree/bake/c_const.cp315-win_amd64.pyd +0 -0
  29. decision_graph/decision_tree/bake/c_const.h +395 -0
  30. decision_graph/decision_tree/bake/c_const.pxd +56 -0
  31. decision_graph/decision_tree/bake/c_const.pyi +305 -0
  32. decision_graph/decision_tree/bake/c_const.pyx +278 -0
  33. decision_graph/decision_tree/bake/c_edge.cp315-win_amd64.pyd +0 -0
  34. decision_graph/decision_tree/bake/c_edge.h +511 -0
  35. decision_graph/decision_tree/bake/c_edge.pxd +117 -0
  36. decision_graph/decision_tree/bake/c_edge.pyi +192 -0
  37. decision_graph/decision_tree/bake/c_edge.pyx +270 -0
  38. decision_graph/decision_tree/bake/c_eval.h +848 -0
  39. decision_graph/decision_tree/bake/c_eval.pxd +40 -0
  40. decision_graph/decision_tree/bake/c_expr.cp315-win_amd64.pyd +0 -0
  41. decision_graph/decision_tree/bake/c_expr.h +1900 -0
  42. decision_graph/decision_tree/bake/c_expr.pxd +129 -0
  43. decision_graph/decision_tree/bake/c_expr.pyi +280 -0
  44. decision_graph/decision_tree/bake/c_expr.pyx +272 -0
  45. decision_graph/decision_tree/bake/c_hierarchy.cp315-win_amd64.pyd +0 -0
  46. decision_graph/decision_tree/bake/c_hierarchy.h +731 -0
  47. decision_graph/decision_tree/bake/c_hierarchy.pxd +71 -0
  48. decision_graph/decision_tree/bake/c_hierarchy.pyi +409 -0
  49. decision_graph/decision_tree/bake/c_hierarchy.pyx +277 -0
  50. decision_graph/decision_tree/bake/c_logic_group.cp315-win_amd64.pyd +0 -0
  51. decision_graph/decision_tree/bake/c_logic_group.h +1226 -0
  52. decision_graph/decision_tree/bake/c_logic_group.pxd +162 -0
  53. decision_graph/decision_tree/bake/c_logic_group.pyi +264 -0
  54. decision_graph/decision_tree/bake/c_logic_group.pyx +308 -0
  55. decision_graph/decision_tree/bake/c_node.cp315-win_amd64.pyd +0 -0
  56. decision_graph/decision_tree/bake/c_node.h +2660 -0
  57. decision_graph/decision_tree/bake/c_node.pxd +381 -0
  58. decision_graph/decision_tree/bake/c_node.pyi +438 -0
  59. decision_graph/decision_tree/bake/c_node.pyx +639 -0
  60. decision_graph/decision_tree/bake/c_reconstruct.cp315-win_amd64.pyd +0 -0
  61. decision_graph/decision_tree/bake/c_reconstruct.pxd +63 -0
  62. decision_graph/decision_tree/bake/c_reconstruct.pyi +60 -0
  63. decision_graph/decision_tree/bake/c_reconstruct.pyx +252 -0
  64. decision_graph/decision_tree/bake/c_var.cp315-win_amd64.pyd +0 -0
  65. decision_graph/decision_tree/bake/c_var.h +2054 -0
  66. decision_graph/decision_tree/bake/c_var.pxd +205 -0
  67. decision_graph/decision_tree/bake/c_var.pyi +271 -0
  68. decision_graph/decision_tree/bake/c_var.pyx +228 -0
  69. decision_graph/decision_tree/capi/__infra__.pxd +33 -0
  70. decision_graph/decision_tree/capi/__init__.pxd +33 -0
  71. decision_graph/decision_tree/capi/__init__.py +57 -0
  72. decision_graph/decision_tree/capi/c_abc.cp315-win_amd64.pyd +0 -0
  73. decision_graph/decision_tree/capi/c_abc.pxd +246 -0
  74. decision_graph/decision_tree/capi/c_abc.pyi +770 -0
  75. decision_graph/decision_tree/capi/c_abc.pyx +1532 -0
  76. decision_graph/decision_tree/capi/c_collection.cp315-win_amd64.pyd +0 -0
  77. decision_graph/decision_tree/capi/c_collection.pxd +22 -0
  78. decision_graph/decision_tree/capi/c_collection.pyi +245 -0
  79. decision_graph/decision_tree/capi/c_collection.pyx +138 -0
  80. decision_graph/decision_tree/capi/c_node.cp315-win_amd64.pyd +0 -0
  81. decision_graph/decision_tree/capi/c_node.pxd +95 -0
  82. decision_graph/decision_tree/capi/c_node.pyi +492 -0
  83. decision_graph/decision_tree/capi/c_node.pyx +551 -0
  84. decision_graph/decision_tree/exc.py +189 -0
  85. decision_graph/decision_tree/native/__init__.py +57 -0
  86. decision_graph/decision_tree/native/abc.py +1167 -0
  87. decision_graph/decision_tree/native/collection.py +134 -0
  88. decision_graph/decision_tree/native/node.py +521 -0
  89. decision_graph/includes/decision_graph/decision_tree/bake/c_action.c +16320 -0
  90. decision_graph/includes/decision_graph/decision_tree/bake/c_action.h +324 -0
  91. decision_graph/includes/decision_graph/decision_tree/bake/c_allocator_protocol.c +12473 -0
  92. decision_graph/includes/decision_graph/decision_tree/bake/c_bake.c +16485 -0
  93. decision_graph/includes/decision_graph/decision_tree/bake/c_bake.h +629 -0
  94. decision_graph/includes/decision_graph/decision_tree/bake/c_collections.c +17381 -0
  95. decision_graph/includes/decision_graph/decision_tree/bake/c_collections.h +692 -0
  96. decision_graph/includes/decision_graph/decision_tree/bake/c_const.c +20815 -0
  97. decision_graph/includes/decision_graph/decision_tree/bake/c_const.h +395 -0
  98. decision_graph/includes/decision_graph/decision_tree/bake/c_edge.c +20696 -0
  99. decision_graph/includes/decision_graph/decision_tree/bake/c_edge.h +511 -0
  100. decision_graph/includes/decision_graph/decision_tree/bake/c_eval.h +848 -0
  101. decision_graph/includes/decision_graph/decision_tree/bake/c_expr.c +22065 -0
  102. decision_graph/includes/decision_graph/decision_tree/bake/c_expr.h +1900 -0
  103. decision_graph/includes/decision_graph/decision_tree/bake/c_hierarchy.c +23267 -0
  104. decision_graph/includes/decision_graph/decision_tree/bake/c_hierarchy.h +731 -0
  105. decision_graph/includes/decision_graph/decision_tree/bake/c_logic_group.c +22434 -0
  106. decision_graph/includes/decision_graph/decision_tree/bake/c_logic_group.h +1226 -0
  107. decision_graph/includes/decision_graph/decision_tree/bake/c_node.c +28385 -0
  108. decision_graph/includes/decision_graph/decision_tree/bake/c_node.h +2660 -0
  109. decision_graph/includes/decision_graph/decision_tree/bake/c_reconstruct.c +15955 -0
  110. decision_graph/includes/decision_graph/decision_tree/bake/c_var.c +16881 -0
  111. decision_graph/includes/decision_graph/decision_tree/bake/c_var.h +2054 -0
  112. decision_graph/includes/decision_graph/decision_tree/capi/c_abc.c +59196 -0
  113. decision_graph/includes/decision_graph/decision_tree/capi/c_collection.c +19967 -0
  114. decision_graph/includes/decision_graph/decision_tree/capi/c_node.c +39229 -0
  115. decision_graph/logic_group/__init__.py +25 -0
  116. decision_graph/logic_group/base.py +100 -0
  117. decision_graph/logic_group/pending_request.py +384 -0
  118. decision_graph/webui/__init__.py +24 -0
  119. decision_graph/webui/bake/__init__.py +65 -0
  120. decision_graph/webui/bake/app.py +488 -0
  121. decision_graph/webui/bake/static/d3.v7.min.js +2 -0
  122. decision_graph/webui/bake/static/script.js +1440 -0
  123. decision_graph/webui/bake/static/style.css +920 -0
  124. decision_graph/webui/bake/templates/index.html +183 -0
  125. decision_graph/webui/bake/templates/offline.html +184 -0
  126. decision_graph/webui/capi/__init__.py +54 -0
  127. decision_graph/webui/capi/app.py +366 -0
  128. decision_graph/webui/capi/main.py +53 -0
  129. decision_graph/webui/capi/static/d3.v7.min.js +2 -0
  130. decision_graph/webui/capi/static/script.js +1026 -0
  131. decision_graph/webui/capi/static/style.css +656 -0
  132. decision_graph/webui/capi/templates/index.html +93 -0
  133. decision_graph/webui/capi/templates/offline.html +94 -0
  134. decision_graph/webui/native/__init__.py +54 -0
  135. decision_graph/webui/native/app.py +366 -0
  136. decision_graph/webui/native/main.py +53 -0
  137. decision_graph/webui/native/static/d3.v7.min.js +2 -0
  138. decision_graph/webui/native/static/script.js +1026 -0
  139. decision_graph/webui/native/static/style.css +656 -0
  140. decision_graph/webui/native/templates/index.html +93 -0
  141. decision_graph/webui/native/templates/offline.html +94 -0
  142. pydecisiongraph-0.3.2.post1.dist-info/METADATA +136 -0
  143. pydecisiongraph-0.3.2.post1.dist-info/RECORD +148 -0
  144. pydecisiongraph-0.3.2.post1.dist-info/WHEEL +5 -0
  145. pydecisiongraph-0.3.2.post1.dist-info/licenses/LICENSE +373 -0
  146. pydecisiongraph-0.3.2.post1.dist-info/top_level.txt +2 -0
  147. tests/bake_c_evaluator.cp315-win_amd64.pyd +0 -0
  148. tests/bake_eval_probe.cp315-win_amd64.pyd +0 -0
@@ -0,0 +1,129 @@
1
+ from cpython.object cimport PyObject
2
+
3
+ from cbase.allocator_protocol cimport allocator_protocol
4
+
5
+ from .c_node cimport LogicNode, dcg_node, dcg_node_type
6
+ from .c_var cimport dcg_var_t
7
+
8
+
9
+ cdef extern from "decision_graph/decision_tree/bake/c_expr.h":
10
+ const size_t DCG_EXPR_DEFAULT_ARGS
11
+
12
+ ctypedef enum dcg_op_code:
13
+ DCG_OP_NONE
14
+ DCG_OP_ARITH
15
+ DCG_OP_ADD
16
+ DCG_OP_SUB
17
+ DCG_OP_MUL
18
+ DCG_OP_DIV
19
+ DCG_OP_FLOORDIV
20
+ DCG_OP_POW
21
+ DCG_OP_NEG
22
+ DCG_OP_COMPARE
23
+ DCG_OP_EQ
24
+ DCG_OP_NE
25
+ DCG_OP_GT
26
+ DCG_OP_GE
27
+ DCG_OP_LT
28
+ DCG_OP_LE
29
+ DCG_OP_LOGIC
30
+ DCG_OP_AND
31
+ DCG_OP_OR
32
+ DCG_OP_NOT
33
+ DCG_OP_ACCESS
34
+ DCG_OP_ATTR
35
+ DCG_OP_GETITEM
36
+
37
+ ctypedef enum dcg_op_mask:
38
+ DCG_OP_FAMILY_MASK
39
+ DCG_OP_VARIANT_MASK
40
+
41
+ ctypedef int (*dcg_expr_apply_fn)(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
42
+
43
+ ctypedef struct dcg_expression_node:
44
+ dcg_node base
45
+ dcg_op_code op
46
+ size_t n_args
47
+ dcg_node** components
48
+ dcg_var_t args[]
49
+
50
+ dcg_expression_node* c_dcg_node_new_expr(size_t n_args, dcg_node_type ntype, allocator_protocol* allocator) noexcept nogil
51
+ void c_dcg_node_free_expr(dcg_expression_node* node) noexcept nogil
52
+ dcg_expression_node* c_dcg_node_new_expr_unary(dcg_op_code op, dcg_node* src, allocator_protocol* allocator) noexcept nogil
53
+ dcg_expression_node* c_dcg_node_new_expr_binary(dcg_op_code op, dcg_node* var_0, dcg_node* var_1, allocator_protocol* allocator) noexcept nogil
54
+ dcg_expression_node* c_dcg_node_new_expr_ternary(dcg_op_code op, dcg_node* var_0, dcg_node* var_1, dcg_node* var_2, allocator_protocol* allocator) noexcept nogil
55
+ dcg_expression_node* c_dcg_node_new_expr_call(dcg_op_code op, dcg_node** vars, size_t n_vars, const char* repr, allocator_protocol* allocator) noexcept nogil
56
+ int c_dcg_node_expr_bind(dcg_expression_node* node, size_t index, dcg_node* input) noexcept nogil
57
+
58
+ int c_dcg_node_expr_set_op(dcg_expression_node* node, dcg_op_code op) noexcept nogil
59
+ dcg_expr_apply_fn c_dcg_node_expr_apply_fn_of(dcg_node_type ntype, dcg_op_code op) noexcept nogil
60
+ int c_dcg_node_expr_apply_unary(dcg_var_t* out, dcg_op_code op, const dcg_var_t* a) noexcept nogil
61
+ int c_dcg_node_expr_apply_binary(dcg_var_t* out, dcg_op_code op, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
62
+
63
+ int c_dcg_node_expr_apply_refuse(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
64
+ int c_dcg_node_expr_apply_neg(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
65
+ int c_dcg_node_expr_apply_not(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
66
+ int c_dcg_node_expr_apply_add(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
67
+ int c_dcg_node_expr_apply_sub(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
68
+ int c_dcg_node_expr_apply_mul(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
69
+ int c_dcg_node_expr_apply_div(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
70
+ int c_dcg_node_expr_apply_floordiv(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
71
+ int c_dcg_node_expr_apply_pow(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
72
+ int c_dcg_node_expr_apply_eq(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
73
+ int c_dcg_node_expr_apply_ne(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
74
+ int c_dcg_node_expr_apply_gt(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
75
+ int c_dcg_node_expr_apply_ge(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
76
+ int c_dcg_node_expr_apply_lt(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
77
+ int c_dcg_node_expr_apply_le(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
78
+ int c_dcg_node_expr_apply_and(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
79
+ int c_dcg_node_expr_apply_or(dcg_var_t* out, const dcg_var_t* a, const dcg_var_t* b) noexcept nogil
80
+ int c_dcg_node_expr_eval_operand(dcg_expression_node* node, size_t index) noexcept nogil
81
+
82
+ int c_dcg_node_expr_eval(dcg_node* node, void* user_data) noexcept nogil
83
+ int c_dcg_node_expr_eval_refuse(dcg_node* node, void* user_data) noexcept nogil
84
+ int c_dcg_node_expr_eval_unknown(dcg_node* node, void* user_data) noexcept nogil
85
+ int c_dcg_node_expr_eval_ternary(dcg_node* node, void* user_data) noexcept nogil
86
+ int c_dcg_node_expr_eval_call(dcg_node* node, void* user_data) noexcept nogil
87
+ int c_dcg_node_expr_eval_neg(dcg_node* node, void* user_data) noexcept nogil
88
+ int c_dcg_node_expr_eval_not(dcg_node* node, void* user_data) noexcept nogil
89
+ int c_dcg_node_expr_eval_add(dcg_node* node, void* user_data) noexcept nogil
90
+ int c_dcg_node_expr_eval_sub(dcg_node* node, void* user_data) noexcept nogil
91
+ int c_dcg_node_expr_eval_mul(dcg_node* node, void* user_data) noexcept nogil
92
+ int c_dcg_node_expr_eval_div(dcg_node* node, void* user_data) noexcept nogil
93
+ int c_dcg_node_expr_eval_floordiv(dcg_node* node, void* user_data) noexcept nogil
94
+ int c_dcg_node_expr_eval_pow(dcg_node* node, void* user_data) noexcept nogil
95
+ int c_dcg_node_expr_eval_eq(dcg_node* node, void* user_data) noexcept nogil
96
+ int c_dcg_node_expr_eval_ne(dcg_node* node, void* user_data) noexcept nogil
97
+ int c_dcg_node_expr_eval_gt(dcg_node* node, void* user_data) noexcept nogil
98
+ int c_dcg_node_expr_eval_ge(dcg_node* node, void* user_data) noexcept nogil
99
+ int c_dcg_node_expr_eval_lt(dcg_node* node, void* user_data) noexcept nogil
100
+ int c_dcg_node_expr_eval_le(dcg_node* node, void* user_data) noexcept nogil
101
+ int c_dcg_node_expr_eval_and(dcg_node* node, void* user_data) noexcept nogil
102
+ int c_dcg_node_expr_eval_or(dcg_node* node, void* user_data) noexcept nogil
103
+ int c_dcg_node_expr_alias(const dcg_node* input, char* out, size_t cap) noexcept nogil
104
+ int c_dcg_node_expr_op_style(dcg_node* const* inputs, size_t n_inputs, dcg_op_code op, char* out, size_t cap) noexcept nogil
105
+ int c_dcg_node_expr_func_style(dcg_node* const* inputs, size_t n_inputs, dcg_op_code op, const char* name, char* out, size_t cap) noexcept nogil
106
+
107
+
108
+ cdef class ExpressionNode(LogicNode):
109
+ cdef PyObject** components
110
+
111
+ cdef void c_components_alloc(self, size_t n_args)
112
+
113
+ cdef void c_components_assign(self, size_t index, LogicNode node)
114
+
115
+
116
+ cdef class UnaryExpression(ExpressionNode):
117
+ pass
118
+
119
+
120
+ cdef class BinaryExpression(ExpressionNode):
121
+ pass
122
+
123
+
124
+ cdef class TernaryExpression(ExpressionNode):
125
+ pass
126
+
127
+
128
+ cdef class CallExpression(ExpressionNode):
129
+ pass
@@ -0,0 +1,280 @@
1
+ """The operator layer: the expressions a graph computes with.
2
+
3
+ An expression is an operator over operands, and its operands are nodes: a
4
+ literal, a read, another expression. The node its operands are bound to holds
5
+ them - a slot that refers to an operand reads that operand's storage, so the
6
+ expression keeps the node alive for as long as it reads through it.
7
+
8
+ The arity is the class: a unary node takes one operand, a binary two, a ternary
9
+ three, and a call as many as it is given.
10
+
11
+ A composition written with a Python value puts a literal in that operand's place:
12
+ ``5 + read`` builds the same node as ``ConstantNode(5) + read``, and ``read - 5``
13
+ the same as ``read - ConstantNode(5)``.
14
+ """
15
+
16
+ import enum
17
+ from typing import Any
18
+
19
+ from .c_node import LogicNode
20
+
21
+
22
+ class ExpressionOperator(enum.IntEnum):
23
+ """The op codes an expression node can carry.
24
+
25
+ One member per code the C layer knows, family by family, with the arithmetic
26
+ and comparison symbols spelled as the operators they are. The enum is the
27
+ Python face of the C op codes: a cimported C constant is not a module
28
+ attribute, so without it a caller would pass bare numbers.
29
+ """
30
+
31
+ none: int
32
+ arith: int
33
+ add: int
34
+ sub: int
35
+ mul: int
36
+ div: int
37
+ floordiv: int
38
+ pow: int
39
+ neg: int
40
+ compare: int
41
+ eq: int
42
+ ne: int
43
+ gt: int
44
+ ge: int
45
+ lt: int
46
+ le: int
47
+ logic: int
48
+ and_: int
49
+ or_: int
50
+ not_: int
51
+ access: int
52
+ attr: int
53
+ getitem: int
54
+
55
+
56
+ class ExpressionNode(LogicNode):
57
+ """An operator over operands, of an arity the type does not fix.
58
+
59
+ The operands are the nodes its arguments read from, and this wrapper HOLDS
60
+ them: an argument that refers to a node reads that node's storage, so a
61
+ released operand would leave the expression reading a block that is gone.
62
+ """
63
+
64
+ def __init__(self, n_args: int = ..., node_type: int = ...) -> None:
65
+ """Build an expression of an explicit arity and node type.
66
+
67
+ Args:
68
+ n_args: How many operands it takes.
69
+ node_type: The C node type this expression is.
70
+
71
+ Raises:
72
+ MemoryError: When the block cannot be allocated.
73
+ """
74
+ ...
75
+
76
+ def bind(self, index: int, node: LogicNode) -> None:
77
+ """Bind an operand to one of this expression's argument slots.
78
+
79
+ Args:
80
+ index: Argument position to bind.
81
+ node: Node whose value the argument takes.
82
+
83
+ Raises:
84
+ RuntimeError: When the C layer refuses the binding.
85
+ """
86
+ ...
87
+
88
+ def __add__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
89
+ """Compose a sum expression with another node."""
90
+ ...
91
+
92
+ def __radd__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
93
+ """Compose a sum expression with a Python value on the left."""
94
+ ...
95
+
96
+ def __sub__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
97
+ """Compose a difference expression with another node."""
98
+ ...
99
+
100
+ def __rsub__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
101
+ """Compose a difference expression with a Python value on the left."""
102
+ ...
103
+
104
+ def __mul__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
105
+ """Compose a product expression with another node."""
106
+ ...
107
+
108
+ def __rmul__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
109
+ """Compose a product expression with a Python value on the left."""
110
+ ...
111
+
112
+ def __truediv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
113
+ """Compose a division expression with another node."""
114
+ ...
115
+
116
+ def __rtruediv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
117
+ """Compose a division expression with a Python value on the left."""
118
+ ...
119
+
120
+ def __floordiv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
121
+ """Compose a floor-division expression with another node."""
122
+ ...
123
+
124
+ def __rfloordiv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
125
+ """Compose a floor-division expression with a Python value on the left."""
126
+ ...
127
+
128
+ def __pow__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
129
+ """Compose a power expression with another node."""
130
+ ...
131
+
132
+ def __rpow__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
133
+ """Compose a power expression with a Python value on the left."""
134
+ ...
135
+
136
+ def __neg__(self) -> UnaryExpression:
137
+ """Compose a negation of this expression."""
138
+ ...
139
+
140
+ def __eq__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
141
+ """Compose an equality CONDITION with another node."""
142
+ ...
143
+
144
+ def __ne__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
145
+ """Compose an inequality condition with another node."""
146
+ ...
147
+
148
+ def __hash__(self) -> int:
149
+ """Hash by the C block's address, so a node can key a dict."""
150
+ ...
151
+
152
+ def __lt__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
153
+ """Compose a less-than condition with another node."""
154
+ ...
155
+
156
+ def __le__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
157
+ """Compose a less-or-equal condition with another node."""
158
+ ...
159
+
160
+ def __gt__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
161
+ """Compose a greater-than condition with another node."""
162
+ ...
163
+
164
+ def __ge__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
165
+ """Compose a greater-or-equal condition with another node."""
166
+ ...
167
+
168
+ def __and__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
169
+ """Compose a conjunction with another node."""
170
+ ...
171
+
172
+ def __rand__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
173
+ """Compose a conjunction with a Python value on the left."""
174
+ ...
175
+
176
+ def __or__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
177
+ """Compose a disjunction with another node."""
178
+ ...
179
+
180
+ def __ror__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
181
+ """Compose a disjunction with a Python value on the left."""
182
+ ...
183
+
184
+ def __invert__(self) -> UnaryExpression:
185
+ """Compose the negation of this expression as a condition."""
186
+ ...
187
+
188
+ @property
189
+ def op(self) -> ExpressionOperator:
190
+ """The operator this expression applies."""
191
+ ...
192
+
193
+ @property
194
+ def n_args(self) -> int:
195
+ """How many operands the expression takes."""
196
+ ...
197
+
198
+ @property
199
+ def operands(self) -> list[LogicNode | None]:
200
+ """The nodes the arguments read from, in argument order.
201
+
202
+ An entry is None where the argument reads from nothing this wrapper
203
+ holds - an argument a value was folded into, whose operand node is gone
204
+ by design.
205
+ """
206
+ ...
207
+
208
+
209
+ class UnaryExpression(ExpressionNode):
210
+ """An expression over one operand."""
211
+
212
+ def __init__(self, op: ExpressionOperator, src: LogicNode) -> None:
213
+ """Build a one-operand expression.
214
+
215
+ Args:
216
+ op: The operator to apply.
217
+ src: The operand it applies to.
218
+
219
+ Raises:
220
+ MemoryError: When the block cannot be allocated.
221
+ """
222
+ ...
223
+
224
+
225
+ class BinaryExpression(ExpressionNode):
226
+ """An expression over two operands: the arithmetic and comparison shape."""
227
+
228
+ def __init__(self, op: ExpressionOperator, var_0: LogicNode, var_1: LogicNode) -> None:
229
+ """Build a two-operand expression.
230
+
231
+ Args:
232
+ op: The operator to apply.
233
+ var_0: The left operand.
234
+ var_1: The right operand.
235
+
236
+ Raises:
237
+ MemoryError: When the block cannot be allocated.
238
+ """
239
+ ...
240
+
241
+
242
+ class TernaryExpression(ExpressionNode):
243
+ """An expression over three operands: the conditional shape."""
244
+
245
+ def __init__(self, op: ExpressionOperator, var_0: LogicNode, var_1: LogicNode, var_2: LogicNode) -> None:
246
+ """Build a three-operand expression.
247
+
248
+ Args:
249
+ op: The operator to apply.
250
+ var_0: The first operand.
251
+ var_1: The second operand.
252
+ var_2: The third operand.
253
+
254
+ Raises:
255
+ MemoryError: When the block cannot be allocated.
256
+ """
257
+ ...
258
+
259
+
260
+ class CallExpression(ExpressionNode):
261
+ """An expression over any number of operands, written as a call.
262
+
263
+ The callee's name is display text, composed into the node's ``repr``: it is
264
+ not a field of the block, which is why a reconstruction brings a call back as
265
+ the generic node view rather than as this class.
266
+ """
267
+
268
+ def __init__(self, op: ExpressionOperator, inputs: Any, name: str | None = None) -> None:
269
+ """Build a call-shaped expression.
270
+
271
+ Args:
272
+ op: The operator to apply.
273
+ inputs: The arguments, in order.
274
+ name: The callee's name, for the node's display text.
275
+
276
+ Raises:
277
+ TypeError: When an argument is not a node.
278
+ MemoryError: When the block cannot be allocated.
279
+ """
280
+ ...
@@ -0,0 +1,272 @@
1
+ import enum
2
+
3
+ from cpython.mem cimport PyMem_Calloc, PyMem_Free, PyMem_Malloc
4
+ from cpython.ref cimport Py_XDECREF, Py_XINCREF
5
+ from cpython.unicode cimport PyUnicode_AsUTF8
6
+
7
+ from .c_allocator_protocol cimport DCG_DEFAULT_ALLOCATOR
8
+ from .c_const cimport c_dcg_node_pypack
9
+ from .c_var cimport dcg_ret_code
10
+
11
+
12
+ class ExpressionOperator(enum.IntEnum):
13
+ none = DCG_OP_NONE
14
+
15
+ arith = DCG_OP_ARITH
16
+ add = DCG_OP_ADD
17
+ sub = DCG_OP_SUB
18
+ mul = DCG_OP_MUL
19
+ div = DCG_OP_DIV
20
+ floordiv = DCG_OP_FLOORDIV
21
+ pow = DCG_OP_POW
22
+ neg = DCG_OP_NEG
23
+
24
+ compare = DCG_OP_COMPARE
25
+ eq = DCG_OP_EQ
26
+ ne = DCG_OP_NE
27
+ gt = DCG_OP_GT
28
+ ge = DCG_OP_GE
29
+ lt = DCG_OP_LT
30
+ le = DCG_OP_LE
31
+
32
+ logic = DCG_OP_LOGIC
33
+ and_ = DCG_OP_AND
34
+ or_ = DCG_OP_OR
35
+ not_ = DCG_OP_NOT
36
+
37
+ access = DCG_OP_ACCESS
38
+ attr = DCG_OP_ATTR
39
+ getitem = DCG_OP_GETITEM
40
+
41
+
42
+ cdef class ExpressionNode(LogicNode):
43
+ def __init__(self, size_t n_args=DCG_EXPR_DEFAULT_ARGS, dcg_node_type node_type=dcg_node_type.DCG_NODE_OP):
44
+ cdef dcg_expression_node* node = c_dcg_node_new_expr(n_args, node_type, DCG_DEFAULT_ALLOCATOR)
45
+ if not node:
46
+ raise MemoryError(f'Failed to allocate the {self.__class__.__name__}.')
47
+
48
+ self.header = &node.base
49
+ self.owner = True
50
+ self.c_components_alloc(node.n_args)
51
+ self.c_register_node()
52
+
53
+ def __dealloc__(self):
54
+ cdef size_t i
55
+ cdef size_t n_args = DCG_EXPR_DEFAULT_ARGS
56
+
57
+ if self.header:
58
+ n_args = (<dcg_expression_node*> self.header).n_args
59
+
60
+ if self.components:
61
+ for i in range(n_args):
62
+ Py_XDECREF(self.components[i])
63
+
64
+ PyMem_Free(self.components)
65
+
66
+ # === Cython Internal Binding ===
67
+
68
+ cdef void c_components_alloc(self, size_t n_args):
69
+ self.components = <PyObject**> PyMem_Calloc(n_args, sizeof(PyObject*))
70
+ if not self.components:
71
+ raise MemoryError(f'Failed to allocate the operand array of the {self.__class__.__name__}.')
72
+
73
+ cdef void c_components_assign(self, size_t index, LogicNode node):
74
+ if self.components[index] == <PyObject*> node:
75
+ return
76
+ Py_XINCREF(<PyObject*> node)
77
+ Py_XDECREF(self.components[index])
78
+ self.components[index] = <PyObject*> node
79
+
80
+ # === Python Interfaces ===
81
+
82
+ def bind(self, size_t index, LogicNode node):
83
+ cdef int ret_code = c_dcg_node_expr_bind(<dcg_expression_node*> self.header, index, node.header)
84
+ if ret_code != dcg_ret_code.DCG_OK:
85
+ raise RuntimeError(f'c_dcg_node_expr_bind failed with err code: {ret_code}')
86
+ self.c_components_assign(index, node)
87
+
88
+ # === Python Operators ===
89
+
90
+ def __add__(self, object other):
91
+ return BinaryExpression(DCG_OP_ADD, self, c_dcg_node_pypack(other))
92
+
93
+ def __radd__(self, object other):
94
+ return BinaryExpression(DCG_OP_ADD, c_dcg_node_pypack(other), self)
95
+
96
+ def __sub__(self, object other):
97
+ return BinaryExpression(DCG_OP_SUB, self, c_dcg_node_pypack(other))
98
+
99
+ def __rsub__(self, object other):
100
+ return BinaryExpression(DCG_OP_SUB, c_dcg_node_pypack(other), self)
101
+
102
+ def __mul__(self, object other):
103
+ return BinaryExpression(DCG_OP_MUL, self, c_dcg_node_pypack(other))
104
+
105
+ def __rmul__(self, object other):
106
+ return BinaryExpression(DCG_OP_MUL, c_dcg_node_pypack(other), self)
107
+
108
+ def __truediv__(self, object other):
109
+ return BinaryExpression(DCG_OP_DIV, self, c_dcg_node_pypack(other))
110
+
111
+ def __rtruediv__(self, object other):
112
+ return BinaryExpression(DCG_OP_DIV, c_dcg_node_pypack(other), self)
113
+
114
+ def __floordiv__(self, object other):
115
+ return BinaryExpression(DCG_OP_FLOORDIV, self, c_dcg_node_pypack(other))
116
+
117
+ def __rfloordiv__(self, object other):
118
+ return BinaryExpression(DCG_OP_FLOORDIV, c_dcg_node_pypack(other), self)
119
+
120
+ def __pow__(self, object other):
121
+ return BinaryExpression(DCG_OP_POW, self, c_dcg_node_pypack(other))
122
+
123
+ def __rpow__(self, object other):
124
+ return BinaryExpression(DCG_OP_POW, c_dcg_node_pypack(other), self)
125
+
126
+ def __neg__(self):
127
+ return UnaryExpression(DCG_OP_NEG, self)
128
+
129
+ def __eq__(self, object other):
130
+ return BinaryExpression(DCG_OP_EQ, self, c_dcg_node_pypack(other))
131
+
132
+ def __ne__(self, object other):
133
+ return BinaryExpression(DCG_OP_NE, self, c_dcg_node_pypack(other))
134
+
135
+ def __hash__(self):
136
+ return hash(self.address)
137
+
138
+ # Ordered comparisons build comparison nodes.
139
+ def __lt__(self, object other):
140
+ return BinaryExpression(DCG_OP_LT, self, c_dcg_node_pypack(other))
141
+
142
+ def __le__(self, object other):
143
+ return BinaryExpression(DCG_OP_LE, self, c_dcg_node_pypack(other))
144
+
145
+ def __gt__(self, object other):
146
+ return BinaryExpression(DCG_OP_GT, self, c_dcg_node_pypack(other))
147
+
148
+ def __ge__(self, object other):
149
+ return BinaryExpression(DCG_OP_GE, self, c_dcg_node_pypack(other))
150
+
151
+ def __and__(self, object other):
152
+ return BinaryExpression(DCG_OP_AND, self, c_dcg_node_pypack(other))
153
+
154
+ def __rand__(self, object other):
155
+ return BinaryExpression(DCG_OP_AND, c_dcg_node_pypack(other), self)
156
+
157
+ def __or__(self, object other):
158
+ return BinaryExpression(DCG_OP_OR, self, c_dcg_node_pypack(other))
159
+
160
+ def __ror__(self, object other):
161
+ return BinaryExpression(DCG_OP_OR, c_dcg_node_pypack(other), self)
162
+
163
+ def __invert__(self):
164
+ return UnaryExpression(DCG_OP_NOT, self)
165
+
166
+ property op:
167
+ def __get__(self):
168
+ if not self.header:
169
+ raise RuntimeError(f'<{self.__class__.__name__}> not initialized!')
170
+ cdef dcg_expression_node* node = <dcg_expression_node*> self.header
171
+ return ExpressionOperator(node.op)
172
+
173
+ property n_args:
174
+ def __get__(self):
175
+ if not self.header:
176
+ raise RuntimeError(f'<{self.__class__.__name__}> not initialized!')
177
+ cdef dcg_expression_node* node = <dcg_expression_node*> self.header
178
+ return node.n_args
179
+
180
+ property operands:
181
+ def __get__(self):
182
+ if not self.header:
183
+ raise RuntimeError(f'<{self.__class__.__name__}> not initialized!')
184
+
185
+ cdef dcg_expression_node* node = <dcg_expression_node*> self.header
186
+ cdef size_t i
187
+ cdef list held = []
188
+
189
+ for i in range(node.n_args):
190
+ held.append(None if not self.components[i] else <object> self.components[i])
191
+ return held
192
+
193
+
194
+ cdef class UnaryExpression(ExpressionNode):
195
+ def __init__(self, dcg_op_code op, LogicNode src):
196
+ cdef dcg_expression_node* node = c_dcg_node_new_expr_unary(op, src.header, DCG_DEFAULT_ALLOCATOR)
197
+ if not node:
198
+ raise MemoryError('Failed to allocate the UnaryExpression.')
199
+
200
+ self.header = &node.base
201
+ self.owner = True
202
+ self.c_components_alloc(1)
203
+ self.c_components_assign(0, src)
204
+ self.c_register_node()
205
+
206
+
207
+ cdef class BinaryExpression(ExpressionNode):
208
+ def __init__(self, dcg_op_code op, LogicNode var_0, LogicNode var_1):
209
+ cdef dcg_expression_node* node = c_dcg_node_new_expr_binary(op, var_0.header, var_1.header, DCG_DEFAULT_ALLOCATOR)
210
+ if not node:
211
+ raise MemoryError('Failed to allocate the BinaryExpression.')
212
+
213
+ self.header = &node.base
214
+ self.owner = True
215
+ self.c_components_alloc(2)
216
+ self.c_components_assign(0, var_0)
217
+ self.c_components_assign(1, var_1)
218
+ self.c_register_node()
219
+
220
+
221
+ cdef class TernaryExpression(ExpressionNode):
222
+ def __init__(self, dcg_op_code op, LogicNode var_0, LogicNode var_1, LogicNode var_2):
223
+ cdef dcg_expression_node* node = c_dcg_node_new_expr_ternary(op, var_0.header, var_1.header, var_2.header, DCG_DEFAULT_ALLOCATOR)
224
+ if not node:
225
+ raise MemoryError('Failed to allocate the TernaryExpression.')
226
+
227
+ self.header = &node.base
228
+ self.owner = True
229
+ self.c_components_alloc(3)
230
+ self.c_components_assign(0, var_0)
231
+ self.c_components_assign(1, var_1)
232
+ self.c_components_assign(2, var_2)
233
+ self.c_register_node()
234
+
235
+
236
+ cdef class CallExpression(ExpressionNode):
237
+ def __init__(self, dcg_op_code op, object inputs, str name=None):
238
+ cdef size_t n_vars = len(inputs)
239
+ cdef dcg_node** vars
240
+ cdef dcg_expression_node* node = NULL
241
+ cdef size_t i
242
+ cdef object argument
243
+
244
+ if n_vars == 0:
245
+ raise ValueError('A CallExpression needs at least one input.')
246
+
247
+ vars = <dcg_node**> PyMem_Malloc(n_vars * sizeof(dcg_node*))
248
+ if not vars:
249
+ raise MemoryError('Failed to allocate the argument array.')
250
+ try:
251
+ for i in range(n_vars):
252
+ argument = inputs[i]
253
+ if not isinstance(argument, LogicNode):
254
+ raise TypeError(f'CallExpression argument {i} is not a LogicNode, but {type(argument).__name__}.')
255
+ vars[i] = (<LogicNode> argument).header
256
+ node = c_dcg_node_new_expr_call(
257
+ op, vars, n_vars,
258
+ PyUnicode_AsUTF8(name) if name is not None else NULL,
259
+ DCG_DEFAULT_ALLOCATOR,
260
+ )
261
+ finally:
262
+ PyMem_Free(vars)
263
+
264
+ if not node:
265
+ raise MemoryError('Failed to allocate the CallExpression.')
266
+
267
+ self.header = &node.base
268
+ self.owner = True
269
+ self.c_components_alloc(n_vars)
270
+ for i in range(n_vars):
271
+ self.c_components_assign(i, <LogicNode> inputs[i])
272
+ self.c_register_node()