PyDecisionGraph 0.3.2.post1__cp315-cp315t-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.
- decision_graph/__infra__.pxd +1 -0
- decision_graph/__init__.pxd +1 -0
- decision_graph/__init__.py +39 -0
- decision_graph/decision_tree/__init__.pxd +2 -0
- decision_graph/decision_tree/__init__.py +85 -0
- decision_graph/decision_tree/bake/__infra__.pxd +502 -0
- decision_graph/decision_tree/bake/__init__.pxd +502 -0
- decision_graph/decision_tree/bake/__init__.py +29 -0
- decision_graph/decision_tree/bake/c_action.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_action.h +324 -0
- decision_graph/decision_tree/bake/c_action.pxd +54 -0
- decision_graph/decision_tree/bake/c_action.pyi +126 -0
- decision_graph/decision_tree/bake/c_action.pyx +65 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.pxd +24 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.pyi +61 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.pyx +109 -0
- decision_graph/decision_tree/bake/c_bake.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_bake.h +629 -0
- decision_graph/decision_tree/bake/c_bake.pxd +52 -0
- decision_graph/decision_tree/bake/c_bake.pyi +151 -0
- decision_graph/decision_tree/bake/c_bake.pyx +142 -0
- decision_graph/decision_tree/bake/c_collections.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_collections.h +692 -0
- decision_graph/decision_tree/bake/c_collections.pxd +52 -0
- decision_graph/decision_tree/bake/c_collections.pyi +193 -0
- decision_graph/decision_tree/bake/c_collections.pyx +161 -0
- decision_graph/decision_tree/bake/c_const.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_const.h +395 -0
- decision_graph/decision_tree/bake/c_const.pxd +56 -0
- decision_graph/decision_tree/bake/c_const.pyi +305 -0
- decision_graph/decision_tree/bake/c_const.pyx +278 -0
- decision_graph/decision_tree/bake/c_edge.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_edge.h +511 -0
- decision_graph/decision_tree/bake/c_edge.pxd +117 -0
- decision_graph/decision_tree/bake/c_edge.pyi +192 -0
- decision_graph/decision_tree/bake/c_edge.pyx +270 -0
- decision_graph/decision_tree/bake/c_eval.h +848 -0
- decision_graph/decision_tree/bake/c_eval.pxd +40 -0
- decision_graph/decision_tree/bake/c_expr.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_expr.h +1900 -0
- decision_graph/decision_tree/bake/c_expr.pxd +129 -0
- decision_graph/decision_tree/bake/c_expr.pyi +280 -0
- decision_graph/decision_tree/bake/c_expr.pyx +272 -0
- decision_graph/decision_tree/bake/c_hierarchy.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_hierarchy.h +731 -0
- decision_graph/decision_tree/bake/c_hierarchy.pxd +71 -0
- decision_graph/decision_tree/bake/c_hierarchy.pyi +409 -0
- decision_graph/decision_tree/bake/c_hierarchy.pyx +277 -0
- decision_graph/decision_tree/bake/c_logic_group.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_logic_group.h +1226 -0
- decision_graph/decision_tree/bake/c_logic_group.pxd +162 -0
- decision_graph/decision_tree/bake/c_logic_group.pyi +264 -0
- decision_graph/decision_tree/bake/c_logic_group.pyx +308 -0
- decision_graph/decision_tree/bake/c_node.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_node.h +2660 -0
- decision_graph/decision_tree/bake/c_node.pxd +381 -0
- decision_graph/decision_tree/bake/c_node.pyi +438 -0
- decision_graph/decision_tree/bake/c_node.pyx +639 -0
- decision_graph/decision_tree/bake/c_reconstruct.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_reconstruct.pxd +63 -0
- decision_graph/decision_tree/bake/c_reconstruct.pyi +60 -0
- decision_graph/decision_tree/bake/c_reconstruct.pyx +252 -0
- decision_graph/decision_tree/bake/c_var.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_var.h +2054 -0
- decision_graph/decision_tree/bake/c_var.pxd +205 -0
- decision_graph/decision_tree/bake/c_var.pyi +271 -0
- decision_graph/decision_tree/bake/c_var.pyx +228 -0
- decision_graph/decision_tree/capi/__infra__.pxd +33 -0
- decision_graph/decision_tree/capi/__init__.pxd +33 -0
- decision_graph/decision_tree/capi/__init__.py +57 -0
- decision_graph/decision_tree/capi/c_abc.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/capi/c_abc.pxd +246 -0
- decision_graph/decision_tree/capi/c_abc.pyi +770 -0
- decision_graph/decision_tree/capi/c_abc.pyx +1532 -0
- decision_graph/decision_tree/capi/c_collection.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/capi/c_collection.pxd +22 -0
- decision_graph/decision_tree/capi/c_collection.pyi +245 -0
- decision_graph/decision_tree/capi/c_collection.pyx +138 -0
- decision_graph/decision_tree/capi/c_node.cp315t-win_amd64.pyd +0 -0
- decision_graph/decision_tree/capi/c_node.pxd +95 -0
- decision_graph/decision_tree/capi/c_node.pyi +492 -0
- decision_graph/decision_tree/capi/c_node.pyx +551 -0
- decision_graph/decision_tree/exc.py +189 -0
- decision_graph/decision_tree/native/__init__.py +57 -0
- decision_graph/decision_tree/native/abc.py +1167 -0
- decision_graph/decision_tree/native/collection.py +134 -0
- decision_graph/decision_tree/native/node.py +521 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_action.c +16320 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_action.h +324 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_allocator_protocol.c +12473 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_bake.c +16485 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_bake.h +629 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_collections.c +17381 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_collections.h +692 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_const.c +20815 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_const.h +395 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_edge.c +20696 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_edge.h +511 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_eval.h +848 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_expr.c +22065 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_expr.h +1900 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_hierarchy.c +23267 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_hierarchy.h +731 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_logic_group.c +22434 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_logic_group.h +1226 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_node.c +28385 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_node.h +2660 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_reconstruct.c +15955 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_var.c +16881 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_var.h +2054 -0
- decision_graph/includes/decision_graph/decision_tree/capi/c_abc.c +59196 -0
- decision_graph/includes/decision_graph/decision_tree/capi/c_collection.c +19967 -0
- decision_graph/includes/decision_graph/decision_tree/capi/c_node.c +39229 -0
- decision_graph/logic_group/__init__.py +25 -0
- decision_graph/logic_group/base.py +100 -0
- decision_graph/logic_group/pending_request.py +384 -0
- decision_graph/webui/__init__.py +24 -0
- decision_graph/webui/bake/__init__.py +65 -0
- decision_graph/webui/bake/app.py +488 -0
- decision_graph/webui/bake/static/d3.v7.min.js +2 -0
- decision_graph/webui/bake/static/script.js +1440 -0
- decision_graph/webui/bake/static/style.css +920 -0
- decision_graph/webui/bake/templates/index.html +183 -0
- decision_graph/webui/bake/templates/offline.html +184 -0
- decision_graph/webui/capi/__init__.py +54 -0
- decision_graph/webui/capi/app.py +366 -0
- decision_graph/webui/capi/main.py +53 -0
- decision_graph/webui/capi/static/d3.v7.min.js +2 -0
- decision_graph/webui/capi/static/script.js +1026 -0
- decision_graph/webui/capi/static/style.css +656 -0
- decision_graph/webui/capi/templates/index.html +93 -0
- decision_graph/webui/capi/templates/offline.html +94 -0
- decision_graph/webui/native/__init__.py +54 -0
- decision_graph/webui/native/app.py +366 -0
- decision_graph/webui/native/main.py +53 -0
- decision_graph/webui/native/static/d3.v7.min.js +2 -0
- decision_graph/webui/native/static/script.js +1026 -0
- decision_graph/webui/native/static/style.css +656 -0
- decision_graph/webui/native/templates/index.html +93 -0
- decision_graph/webui/native/templates/offline.html +94 -0
- pydecisiongraph-0.3.2.post1.dist-info/METADATA +136 -0
- pydecisiongraph-0.3.2.post1.dist-info/RECORD +148 -0
- pydecisiongraph-0.3.2.post1.dist-info/WHEEL +5 -0
- pydecisiongraph-0.3.2.post1.dist-info/licenses/LICENSE +373 -0
- pydecisiongraph-0.3.2.post1.dist-info/top_level.txt +2 -0
- tests/bake_c_evaluator.cp315t-win_amd64.pyd +0 -0
- tests/bake_eval_probe.cp315t-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()
|
|
Binary file
|