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