1 #include <stdlib.h>
2 #include "lib/mlr_globals.h"
3 #include "lib/mlrutil.h"
4 #include "mlr_dsl_cst.h"
5 #include "context_flags.h"
6
7 // ----------------------------------------------------------------
8 static mlr_dsl_cst_statement_freer_t free_for_srec;
9 static mlr_dsl_cst_statement_handler_t handle_for_srec;
10
11 // The variable names are used only for type-decl exceptions. Otherwise the
12 // names are replaced with frame-relative indices by the stack allocator.
13 typedef struct _for_srec_state_t {
14 char* k_variable_name;
15 int k_frame_relative_index;
16 int k_type_mask;
17
18 char* v_variable_name;
19 int v_frame_relative_index;
20 int v_type_mask;
21
22 type_inferenced_srec_field_copy_getter_t* ptype_inferenced_srec_field_copy_getter;
23
24 } for_srec_state_t;
25
26 // ----------------------------------------------------------------
27 // $ mlr -n put -v 'for (k,v in $*) { $x=1; $y=2 }'
28 // AST ROOT:
29 // text="block", type=STATEMENT_BLOCK:
30 // text="for", type=FOR_SREC:
31 // text="variables", type=FOR_VARIABLES:
32 // text="k", type=UNTYPED_LOCAL_DEFINITION.
33 // text="v", type=UNTYPED_LOCAL_DEFINITION.
34 // text="for_full_srec_block", type=STATEMENT_BLOCK:
35 // text="=", type=SREC_ASSIGNMENT:
36 // text="x", type=FIELD_NAME.
37 // text="1", type=NUMERIC_LITERAL.
38 // text="=", type=SREC_ASSIGNMENT:
39 // text="y", type=FIELD_NAME.
40 // text="2", type=NUMERIC_LITERAL.
41
alloc_for_srec(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)42 mlr_dsl_cst_statement_t* alloc_for_srec(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
43 int type_inferencing, int context_flags)
44 {
45 for_srec_state_t* pstate = mlr_malloc_or_die(sizeof(for_srec_state_t));
46
47 pstate->k_variable_name = NULL;
48 pstate->k_frame_relative_index = 0;
49 pstate->k_type_mask = TYPE_MASK_ANY;
50 pstate->v_variable_name = NULL;
51 pstate->v_frame_relative_index = 0;
52 pstate->v_type_mask = TYPE_MASK_ANY;
53 pstate-> ptype_inferenced_srec_field_copy_getter = NULL;
54
55 // Left child node is list of bound variables.
56 // Right child node is the list of statements in the body.
57 mlr_dsl_ast_node_t* pleft = pnode->pchildren->phead->pvvalue;
58 mlr_dsl_ast_node_t* pright = pnode->pchildren->phead->pnext->pvvalue;
59
60 mlr_dsl_ast_node_t* pknode = pleft->pchildren->phead->pvvalue;
61 mlr_dsl_ast_node_t* pvnode = pleft->pchildren->phead->pnext->pvvalue;
62
63 if (streq(pknode->text, pvnode->text)) {
64 fprintf(stderr, "%s: duplicate for-loop boundvars \"%s\" and \"%s\".\n",
65 MLR_GLOBALS.bargv0, pknode->text, pvnode->text);
66 exit(1);
67 }
68
69 pstate->k_variable_name = mlr_strdup_or_die(pknode->text);
70 pstate->v_variable_name = mlr_strdup_or_die(pvnode->text);
71 MLR_INTERNAL_CODING_ERROR_IF(pknode->vardef_frame_relative_index == MD_UNUSED_INDEX);
72 MLR_INTERNAL_CODING_ERROR_IF(pvnode->vardef_frame_relative_index == MD_UNUSED_INDEX);
73 pstate->k_frame_relative_index = pknode->vardef_frame_relative_index;
74 pstate->v_frame_relative_index = pvnode->vardef_frame_relative_index;
75 pstate->k_type_mask = mlr_dsl_ast_node_type_to_type_mask(pknode->type);
76 pstate->v_type_mask = mlr_dsl_ast_node_type_to_type_mask(pvnode->type);
77
78 MLR_INTERNAL_CODING_ERROR_IF(pnode->subframe_var_count == MD_UNUSED_INDEX);
79 cst_statement_block_t* pblock = cst_statement_block_alloc(pnode->subframe_var_count);
80
81 for (sllve_t* pe = pright->pchildren->phead; pe != NULL; pe = pe->pnext) {
82 mlr_dsl_ast_node_t* pbody_ast_node = pe->pvvalue;
83 sllv_append(pblock->pstatements, mlr_dsl_cst_alloc_statement(pcst, pbody_ast_node,
84 type_inferencing, context_flags));
85 }
86
87 pstate->ptype_inferenced_srec_field_copy_getter =
88 (type_inferencing == TYPE_INFER_STRING_ONLY) ? get_copy_srec_value_string_only_aux :
89 (type_inferencing == TYPE_INFER_STRING_FLOAT) ? get_copy_srec_value_string_float_aux :
90 (type_inferencing == TYPE_INFER_STRING_FLOAT_INT) ? get_copy_srec_value_string_float_int_aux :
91 NULL;
92 MLR_INTERNAL_CODING_ERROR_IF(pstate->ptype_inferenced_srec_field_copy_getter == NULL);
93
94 return mlr_dsl_cst_statement_valloc_with_block(
95 pnode,
96 handle_for_srec,
97 pblock,
98 mlr_dsl_cst_handle_statement_block_with_break_continue,
99 free_for_srec,
100 pstate);
101 }
102
103 // ----------------------------------------------------------------
free_for_srec(mlr_dsl_cst_statement_t * pstatement,context_t * _)104 static void free_for_srec(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
105 for_srec_state_t* pstate = pstatement->pvstate;
106 free(pstate->k_variable_name);
107 free(pstate->v_variable_name);
108 free(pstate);
109 }
110
111 // ----------------------------------------------------------------
handle_for_srec(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)112 static void handle_for_srec(
113 mlr_dsl_cst_statement_t* pstatement,
114 variables_t* pvars,
115 cst_outputs_t* pcst_outputs)
116 {
117 for_srec_state_t* pstate = pstatement->pvstate;
118
119 local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
120 local_stack_subframe_enter(pframe, pstatement->pblock->subframe_var_count);
121 loop_stack_push(pvars->ploop_stack);
122
123 // Copy the lrec for the very likely case that it is being updated inside the for-loop.
124 lrec_t* pcopyrec = lrec_copy(pvars->pinrec);
125 lhmsmv_t* pcopyoverlay = lhmsmv_copy(pvars->ptyped_overlay);
126
127 for (lrece_t* pe = pcopyrec->phead; pe != NULL; pe = pe->pnext) {
128
129 mv_t mvkey = mv_from_string_no_free(pe->key);
130 mv_t mvval = pstate->ptype_inferenced_srec_field_copy_getter(pe, pcopyoverlay);
131
132 local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
133 local_stack_frame_define_terminal(pframe,
134 pstate->k_variable_name, pstate->k_frame_relative_index,
135 pstate->k_type_mask, mvkey);
136 local_stack_frame_define_terminal(pframe,
137 pstate->v_variable_name, pstate->v_frame_relative_index,
138 pstate->v_type_mask, mvval);
139
140 pstatement->pblock_handler(pstatement->pblock, pvars, pcst_outputs);
141 if (loop_stack_get(pvars->ploop_stack) & LOOP_BROKEN) {
142 loop_stack_clear(pvars->ploop_stack, LOOP_BROKEN);
143 break;
144 } else if (loop_stack_get(pvars->ploop_stack) & LOOP_CONTINUED) {
145 loop_stack_clear(pvars->ploop_stack, LOOP_CONTINUED);
146 }
147 }
148 lhmsmv_free(pcopyoverlay);
149 lrec_free(pcopyrec);
150
151 loop_stack_pop(pvars->ploop_stack);
152 local_stack_subframe_exit(pframe, pstatement->pblock->subframe_var_count);
153 }
154
155 // ----------------------------------------------------------------
156 static mlr_dsl_cst_statement_freer_t free_for_srec_key_only;
157 static mlr_dsl_cst_statement_handler_t handle_for_srec_key_only;
158
159 // The variable names are used only for type-decl exceptions. Otherwise the
160 // names are replaced with frame-relative indices by the stack allocator.
161 typedef struct _for_srec_key_only_state_t {
162 char* k_variable_name;
163 int k_frame_relative_index;
164 int k_type_mask;
165
166 type_inferenced_srec_field_copy_getter_t* ptype_inferenced_srec_field_copy_getter;
167
168 } for_srec_key_only_state_t;
169
170 // ----------------------------------------------------------------
171 // $ mlr -n put -v 'for (k in $*) { $x=1; $y=2 }'
172 //
173 // AST ROOT:
174 // text="block", type=STATEMENT_BLOCK:
175 // text="for", type=FOR_SREC_KEY_ONLY:
176 // text="variables", type=FOR_VARIABLES:
177 // text="k", type=UNTYPED_LOCAL_DEFINITION.
178 // text="for_full_srec_block", type=STATEMENT_BLOCK:
179 // text="=", type=SREC_ASSIGNMENT:
180 // text="x", type=FIELD_NAME.
181 // text="1", type=NUMERIC_LITERAL.
182 // text="=", type=SREC_ASSIGNMENT:
183 // text="y", type=FIELD_NAME.
184 // text="2", type=NUMERIC_LITERAL.
185
alloc_for_srec_key_only(mlr_dsl_cst_t * pcst,mlr_dsl_ast_node_t * pnode,int type_inferencing,int context_flags)186 mlr_dsl_cst_statement_t* alloc_for_srec_key_only(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode,
187 int type_inferencing, int context_flags)
188 {
189 for_srec_key_only_state_t* pstate = mlr_malloc_or_die(sizeof(for_srec_key_only_state_t));
190
191 pstate->k_variable_name = NULL;
192 pstate->k_frame_relative_index = 0;
193 pstate->k_type_mask = TYPE_MASK_ANY;
194 pstate-> ptype_inferenced_srec_field_copy_getter = NULL;
195
196 // Left child node is list of bound variables.
197 // Right child node is the list of statements in the body.
198 mlr_dsl_ast_node_t* pleft = pnode->pchildren->phead->pvvalue;
199 mlr_dsl_ast_node_t* pright = pnode->pchildren->phead->pnext->pvvalue;
200
201 mlr_dsl_ast_node_t* pknode = pleft->pchildren->phead->pvvalue;
202
203 pstate->k_variable_name = mlr_strdup_or_die(pknode->text);
204 MLR_INTERNAL_CODING_ERROR_IF(pknode->vardef_frame_relative_index == MD_UNUSED_INDEX);
205 pstate->k_frame_relative_index = pknode->vardef_frame_relative_index;
206 pstate->k_type_mask = mlr_dsl_ast_node_type_to_type_mask(pknode->type);
207
208 MLR_INTERNAL_CODING_ERROR_IF(pnode->subframe_var_count == MD_UNUSED_INDEX);
209 cst_statement_block_t* pblock = cst_statement_block_alloc(pnode->subframe_var_count);
210
211 for (sllve_t* pe = pright->pchildren->phead; pe != NULL; pe = pe->pnext) {
212 mlr_dsl_ast_node_t* pbody_ast_node = pe->pvvalue;
213 sllv_append(pblock->pstatements, mlr_dsl_cst_alloc_statement(pcst, pbody_ast_node,
214 type_inferencing, context_flags));
215 }
216
217 pstate->ptype_inferenced_srec_field_copy_getter =
218 (type_inferencing == TYPE_INFER_STRING_ONLY) ? get_copy_srec_value_string_only_aux :
219 (type_inferencing == TYPE_INFER_STRING_FLOAT) ? get_copy_srec_value_string_float_aux :
220 (type_inferencing == TYPE_INFER_STRING_FLOAT_INT) ? get_copy_srec_value_string_float_int_aux :
221 NULL;
222 MLR_INTERNAL_CODING_ERROR_IF(pstate->ptype_inferenced_srec_field_copy_getter == NULL);
223
224 return mlr_dsl_cst_statement_valloc_with_block(
225 pnode,
226 handle_for_srec_key_only,
227 pblock,
228 mlr_dsl_cst_handle_statement_block_with_break_continue,
229 free_for_srec_key_only,
230 pstate);
231 }
232
233 // ----------------------------------------------------------------
free_for_srec_key_only(mlr_dsl_cst_statement_t * pstatement,context_t * _)234 static void free_for_srec_key_only(mlr_dsl_cst_statement_t* pstatement, context_t* _) {
235 for_srec_key_only_state_t* pstate = pstatement->pvstate;
236 free(pstate->k_variable_name);
237 free(pstate);
238 }
239
240 // ----------------------------------------------------------------
handle_for_srec_key_only(mlr_dsl_cst_statement_t * pstatement,variables_t * pvars,cst_outputs_t * pcst_outputs)241 static void handle_for_srec_key_only(
242 mlr_dsl_cst_statement_t* pstatement,
243 variables_t* pvars,
244 cst_outputs_t* pcst_outputs)
245 {
246 for_srec_key_only_state_t* pstate = pstatement->pvstate;
247
248 local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
249 local_stack_subframe_enter(pframe, pstatement->pblock->subframe_var_count);
250 loop_stack_push(pvars->ploop_stack);
251
252 // Copy the lrec for the very likely case that it is being updated inside the for-loop.
253 lrec_t* pcopyrec = lrec_copy(pvars->pinrec);
254 lhmsmv_t* pcopyoverlay = lhmsmv_copy(pvars->ptyped_overlay);
255
256 for (lrece_t* pe = pcopyrec->phead; pe != NULL; pe = pe->pnext) {
257
258 mv_t mvkey = mv_from_string_no_free(pe->key);
259
260 local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
261 local_stack_frame_define_terminal(pframe,
262 pstate->k_variable_name, pstate->k_frame_relative_index,
263 pstate->k_type_mask, mvkey);
264
265 pstatement->pblock_handler(pstatement->pblock, pvars, pcst_outputs);
266 if (loop_stack_get(pvars->ploop_stack) & LOOP_BROKEN) {
267 loop_stack_clear(pvars->ploop_stack, LOOP_BROKEN);
268 break;
269 } else if (loop_stack_get(pvars->ploop_stack) & LOOP_CONTINUED) {
270 loop_stack_clear(pvars->ploop_stack, LOOP_CONTINUED);
271 }
272 }
273 lhmsmv_free(pcopyoverlay);
274 lrec_free(pcopyrec);
275
276 loop_stack_pop(pvars->ploop_stack);
277 local_stack_subframe_exit(pframe, pstatement->pblock->subframe_var_count);
278 }
279