Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_value_block.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Interface afw_value Implementation for block
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
9 
15 #include "afw_internal.h"
16 
17 
18 #define impl_afw_value_optional_release NULL
19 #define impl_afw_value_get_reference NULL
20 
21 
22 
23 #define impl_afw_value_get_evaluated_meta \
24  afw_value_internal_get_evaluated_meta_default
25 
26 #define impl_afw_value_get_evaluated_metas \
27  afw_value_internal_get_evaluated_metas_default
28 
29 /* Declares and rti/inf defines for interface afw_value */
30 #define AFW_IMPLEMENTATION_ID "block"
31 #define AFW_IMPLEMENTATION_INF_SPECIFIER AFW_DEFINE_CONST_DATA
32 #define AFW_IMPLEMENTATION_INF_LABEL afw_value_block_inf
34 
35 #define IMPL_TEMP_FIX_ASSIGNS(XX) \
36  modified_x.p = p; \
37  modified_x.xctx = xctx; \
38  modified_x.function = &afw_function_definition_ ## XX; \
39  modified_x.argv = argv; \
40  modified_x.argc = argc; \
41 
42 #define IMPL_TEMP_FIX(XX) \
43  afw_function_execute_t modified_x; \
44  afw_memory_clear(&modified_x); \
45  IMPL_TEMP_FIX_ASSIGNS(XX) \
46  x = &modified_x
47 
48 
49 
50 
51 static void
52 impl_assign(
53  const afw_value_t *target,
54  const afw_value_t *value,
56  const afw_pool_t *p,
57  afw_xctx_t *xctx);
58 
59 
60 
61 static void
62 impl_assign_value(
63  const afw_value_t *target,
64  const afw_value_t *value,
66  const afw_pool_t *p,
67  afw_xctx_t *xctx);
68 
69 
70 
71 static void
72 impl_set_variable(
73  const afw_utf8_t *name,
74  const afw_value_t *value,
76  afw_xctx_t *xctx)
77 {
78  switch (assignment_type) {
79 
82  case afw_compile_assignment_type_assign_only:
83  afw_xctx_set_defined_variable(name, value, xctx);
84  break;
85 
86  case afw_compile_assignment_type_const:
87  afw_xctx_define_variable(name, value, xctx);
88  break;
89 
90  case afw_compile_assignment_type_loc:
91  afw_xctx_define_variable(name, value, xctx);
92  break;
93 
94  case afw_compile_assignment_type_define_loc_if_needed:
95  afw_xctx_set_local_variable(name, value, xctx);
96  break;
97 
98  default:
99  AFW_THROW_ERROR_Z(general, "Internal error", xctx);
100  }
101 
102 }
103 
104 
105 
106 static void
107 impl_list_destructure(
110  const afw_value_t *value,
112  const afw_pool_t *p,
113  afw_xctx_t *xctx)
114 {
116  const afw_iterator_t *iterator;
117  const afw_value_t *v;
118  const afw_list_t *rest;
119  afw_boolean_t eol;
120 
121  if (!afw_value_is_list(value)) {
122  AFW_THROW_ERROR_Z(general,
123  "List destructure can only be performed on a list", xctx);
124  }
125 
126  for (eol = false,
127  iterator = NULL,
128  ae = ld->assignment_element,
129  v = NULL;
130  ae;
131  ae = ae->next)
132  {
133  if (!eol) {
135  ((const afw_value_list_t *)value)->internal,
136  &iterator, p, xctx);
137  if (!v) {
138  eol = true;
139  }
140  }
141  if (!ae->assignment_target) {
142  continue;
143  }
144  if (eol) {
145  v = ae->default_value;
146  }
147  if (v) {
148  impl_assign_value(ae->assignment_target, v, assignment_type,
149  p, xctx);
150  }
151  else {
152  //FIXME ???
153  }
154  }
155 
156  if (!eol && ld->rest) {
157  for (rest = NULL;;) {
159  ((const afw_value_list_t *)value)->internal,
160  &iterator, p, xctx);
161  if (!v) {
162  break;
163  }
164  if (!rest) {
165  rest = afw_list_create_generic(p, xctx);
166  }
167  afw_list_add_value(rest, v, xctx);
168  }
169  if (rest) {
170  v = afw_value_create_list(rest, p, xctx);
171  impl_assign_value(ld->rest, v, assignment_type, p, xctx);
172  }
173  }
174 }
175 
176 
177 
178 static void
179 impl_object_destructure(
182  const afw_value_t *value,
184  const afw_pool_t *p,
185  afw_xctx_t *xctx)
186 {
188  const afw_object_t *object;
189  const afw_iterator_t *iterator;
190  const afw_utf8_t *property_name;
191  const afw_value_t *v;
192  const afw_object_t *rest;
193 
194  object = afw_value_as_object(value, xctx);
195 
196  /* Process assignment properties. */
197  for (ap = od->assignment_property; ap; ap = ap->next)
198  {
199  if (ap->is_rename) {
200  v = afw_object_get_property(object, ap->property_name, xctx);
201  if (!v) {
202  v = ap->assignment_element->default_value;
203  }
204  if (v) {
205  impl_assign_value(ap->assignment_element->assignment_target, v,
206  assignment_type, p, xctx);
207  }
208  else {
209  //FIXME ???
210  }
211  }
212  else {
213  v = afw_object_get_property(object,
214  ap->variable_reference->symbol->name, xctx);
215  if (!v) {
216  v = ap->default_value;
217  }
218  if (v) {
219  impl_assign_value((const afw_value_t *)ap->variable_reference,
220  v, assignment_type, p, xctx);
221  }
222  else {
223  //FIXME ???
224  }
225 
226  }
227  }
228 
229  /* Add other properties to rest. */
230  if (od->rest) {
231  rest = afw_object_create_managed(p, xctx);
232  for (iterator = NULL;;) {
233  v = afw_object_get_next_property(object, &iterator, &property_name,
234  xctx);
235  if (!v) {
236  break;
237  }
238 
239  for (ap = od->assignment_property; ap; ap = ap->next)
240  {
241  if (
242  (ap->is_rename && afw_utf8_equal(
243  ap->property_name, property_name))
244  ||
245  (!ap->is_rename && afw_utf8_equal(
246  ap->variable_reference->symbol->name, property_name))
247  )
248  {
249  break;
250  }
251  }
252  if (!ap) {
253  afw_object_set_property(rest, property_name, v, xctx);
254  }
255  }
256  v = afw_value_create_object(rest, p, xctx);
257  impl_assign_value(od->rest, v, assignment_type, p, xctx);
258  }
259 }
260 
261 
262 
263 static void
264 impl_assignment_target(
265  const afw_value_assignment_target_t *target,
266  const afw_value_t *value,
268  const afw_pool_t *p,
269  afw_xctx_t *xctx)
270 {
272  target->assignment_target;
273 
274  switch (at->target_type) {
275  case afw_compile_assignment_target_type_list_destructure:
276  impl_list_destructure(at, at->list_destructure, value,
277  assignment_type, p, xctx);
278  break;
279 
280  case afw_compile_assignment_target_type_object_destructure:
281  impl_object_destructure(at, at->object_destructure, value,
282  assignment_type, p, xctx);
283  break;
284 
285  case afw_compile_assignment_target_type_variable_reference:
286  impl_set_variable(at->variable_reference->symbol->name,
287  value, assignment_type, xctx);
288  break;
289 
290  case afw_compile_assignment_target_type_max_type:
291  default:
292  AFW_THROW_ERROR_FZ(code, xctx, "Invalid case %d", at->target_type);
293  }
294 }
295 
296 
297 
298 static void
299 impl_assign(
300  const afw_value_t *target,
301  const afw_value_t *value,
303  const afw_pool_t *p,
304  afw_xctx_t *xctx)
305 {
307 
308  if (assignment_type == afw_compile_assignment_type_use_assignment_targets)
309  {
310  if (afw_value_is_assignment_target(target)) {
311  at = (const afw_value_assignment_target_t *)target;
312  assignment_type = at->assignment_target->assignment_type;
313  }
314  else {
315  AFW_THROW_ERROR_Z(general, "Internal error", xctx);
316  }
317  }
318 
319  impl_assign_value(target, value, assignment_type, p, xctx);
320 }
321 
322 
323 
324 static void
325 impl_assign_value(
326  const afw_value_t *target,
327  const afw_value_t *value,
329  const afw_pool_t *p,
330  afw_xctx_t *xctx)
331 {
333 
334  if (afw_value_is_assignment_target(target)) {
335  at = (const afw_value_assignment_target_t *)target;
336  impl_assignment_target(at, value, assignment_type, p, xctx);
337  }
338 
339  /* String containing variable name */
340  else if (afw_value_is_string(target)) {
341  impl_set_variable(
342  &((afw_value_string_t *)target)->internal,
343  value, assignment_type, xctx);
344  }
345 
346  /* Variable Reference */
347  else if (afw_value_is_variable_reference(target)) {
350  impl_set_variable(t->symbol->name, value,
351  assignment_type, xctx);
352  }
353 
354  /* Reference by key */
355  else if (afw_value_is_reference_by_key(target)) {
358  const afw_object_t *object;
359  const afw_list_t *list;
360  const afw_value_t *key;
361  const afw_value_t *aggregate_value;
362  const afw_utf8_t *name;
363 
364  aggregate_value = afw_value_evaluate(t->aggregate_value, p, xctx);
365  key = afw_value_evaluate(t->key, p, xctx);
366 
367  if (afw_value_is_object(aggregate_value)) {
368  object = ((const afw_value_object_t *)aggregate_value)->internal;
369  if (afw_object_is_immutable(object, xctx)) {
370  AFW_THROW_ERROR_Z(general, "Target object is immutable", xctx);
371  }
372  name = afw_value_is_string(key)
373  ? &((const afw_value_string_t *)key)->internal
374  : afw_value_as_utf8(key, p, xctx);
375  afw_object_set_property(object, name, value, xctx);
376  }
377 
378  else if (afw_value_is_list(aggregate_value)) {
379  list = ((const afw_value_list_t *)aggregate_value)->internal;
380 
381  if (afw_list_is_immutable(list, xctx)) {
382  AFW_THROW_ERROR_Z(general, "Target list is immutable", xctx);
383  }
384 
385  if (!afw_value_is_integer(key)) {
386  AFW_THROW_ERROR_Z(general, "List index must be integer", xctx);
387  }
388 
390  (afw_size_t)((const afw_value_integer_t *)key)->internal,
391  value, xctx);
392  }
393 
394  else {
395  AFW_THROW_ERROR_Z(general, "Invalid assignment target", xctx);
396  }
397 
398  }
399 
400  /* Invalid assignment target. */
401  else {
402  AFW_THROW_ERROR_Z(general, "Invalid assignment target", xctx);
403  }
404 
405 }
406 
407 
408 
409 /* Use by for statement assignments. Result of evaluate is ignored. */
410 static const afw_value_t *
411 impl_evaluate_one_or_more_values(
413  afw_size_t parameter_number,
414  const afw_value_t *values,
415  const afw_pool_t *p,
416  afw_xctx_t *xctx)
417 {
418  const afw_value_t *result;
419  const afw_value_t *value;
420  const afw_iterator_t *iterator;
421  afw_value_block_statement_type_t type;
422 
423  result = NULL;
424  if (afw_value_is_list(values)) {
425  iterator = NULL;
426  for (;;) {
427  value = afw_list_get_next_value(
428  ((const afw_value_list_t *)values)->internal,
429  &iterator, p, xctx);
430  if (!value) {
431  break;
432  }
433  result = afw_value_block_evaluate_statement(x, &type,
434  false, false, value, p, xctx);
435  }
436  }
437 
438  else {
439  result = afw_value_block_evaluate_statement(x, &type,
440  false, false, values, p, xctx);
441  }
442 
443  return result;
444 }
445 
446 
447 
449 afw_value_block_evaluate_block(
451  afw_value_block_statement_type_t *type,
452  const afw_value_block_t *self,
453  afw_boolean_t is_loop,
454  const afw_pool_t *p,
455  afw_xctx_t *xctx)
456 {
457  const afw_value_t *result;
458  const afw_compile_value_contextual_t *saved_contextual;
459  afw_size_t i;
460  int local_top;
461 
462  /* Push value on evaluation stack. */
464  (const afw_value_t *)self, xctx);
465  saved_contextual = xctx->error->contextual;
466  xctx->error->contextual = self->contextual;
467  result = afw_value_null;
468 
469  local_top = afw_xctx_begin_stack_frame(xctx);
470  AFW_TRY{
471  for (i = 0; i < self->argc; i++) {
472  result = afw_value_block_evaluate_statement(x, type,
473  true, is_loop, self->argv[i], p, xctx);
474  if (*type != afw_value_block_statement_type_sequential)
475  {
476  break;
477  }
478  }
479  }
480  AFW_FINALLY{
481  afw_xctx_end_stack_frame(local_top, xctx);
482  }
483  AFW_ENDTRY;
484 
485  /* Pop value from evaluation stack and return result. */
487  xctx->error->contextual = saved_contextual;
488 
489  return result;
490 }
491 
492 
493 
495 afw_value_block_evaluate_for(
497  afw_value_block_statement_type_t *type,
498  afw_size_t argc,
499  const afw_value_t * const * argv,
500  const afw_pool_t *p,
501  afw_xctx_t *xctx)
502 {
503  IMPL_TEMP_FIX(for);
504  const afw_value_boolean_t *condition;
505  const afw_value_t *result;
506  const afw_value_t *increment;
507  const afw_value_t *body;
508  int local_top;
509 
510  local_top = afw_xctx_begin_stack_frame(xctx);
511  AFW_TRY{
512 
514 
516  impl_evaluate_one_or_more_values(x, 1, argv[1], p, xctx);
517  }
518 
519  increment = NULL;
521  increment = argv[3];
522  }
523 
524  body = NULL;
526  body = argv[4];
527  }
528 
529  for (result= afw_value_null;;) {
530 
533  2);
534  if (!condition->internal) {
535  break;
536  }
537  }
538 
539  if (body) {
540  result = afw_value_block_evaluate_statement(x, type,
541  true, true, body, p, xctx);
542  if (*type == afw_value_block_statement_type_break ||
543  *type == afw_value_block_statement_type_return)
544  {
545  break;
546  }
547  }
548 
549  if (increment) {
550  impl_evaluate_one_or_more_values(x, 3, increment, p, xctx);
551  }
552  }
553  }
554  AFW_FINALLY{
555  /* We don't want continue/break outside of this loop */
556  if (*type == afw_value_block_statement_type_continue ||
557  *type == afw_value_block_statement_type_break)
558  {
559  *type = afw_value_block_statement_type_sequential;
560  }
561  afw_xctx_end_stack_frame(local_top, xctx);
562  }
563  AFW_ENDTRY;
564 
565  return result;
566 }
567 
568 
570 afw_value_block_evaluate_foreach(
572  afw_value_block_statement_type_t *type,
573  afw_size_t argc,
574  const afw_value_t *const *argv,
575  const afw_pool_t *p,
576  afw_xctx_t *xctx)
577 {
578  IMPL_TEMP_FIX(foreach);
579  const afw_value_t *result;
580  const afw_value_list_t *list;
581  const afw_iterator_t *iterator;
582  const afw_value_t *value;
584  int local_top;
585 
586  local_top = afw_xctx_begin_stack_frame(xctx);
587  AFW_TRY{
588 
591 
592  assignment_type = afw_compile_assignment_type_use_assignment_targets;
593  for (iterator = NULL;;) {
594  value = afw_list_get_next_value(list->internal, &iterator,
595  p, xctx);
596  if (!value) {
597  break;
598  }
599  impl_assign(argv[1], value, assignment_type, p, xctx);
600  assignment_type = afw_compile_assignment_type_assign_only;
601  result = afw_value_block_evaluate_statement(x, type,
602  true, true, argv[3], p, xctx);
603  if (*type == afw_value_block_statement_type_break ||
604  *type == afw_value_block_statement_type_return)
605  {
606  break;
607  }
608  }
609  }
610  AFW_FINALLY{
611  /* We don't want continue/break outside of this loop */
612  if (*type == afw_value_block_statement_type_continue ||
613  *type == afw_value_block_statement_type_break)
614  {
615  *type = afw_value_block_statement_type_sequential;
616  }
617  afw_xctx_end_stack_frame(local_top, xctx);
618  }
619  AFW_ENDTRY;
620 
621  return result;
622 }
623 
624 
625 
627 afw_value_block_evaluate_do_while(
629  afw_value_block_statement_type_t *type,
630  afw_size_t argc,
631  const afw_value_t *const *argv,
632  const afw_pool_t *p,
633  afw_xctx_t *xctx)
634 {
635  IMPL_TEMP_FIX(do_while);
636  const afw_value_t *result;
637  const afw_value_boolean_t *condition;
638 
640  for (result = afw_value_null;;) {
641  result = afw_value_block_evaluate_statement(x, type,
642  true, true, argv[2], p, xctx);
643  if (*type == afw_value_block_statement_type_break ||
644  *type == afw_value_block_statement_type_return)
645  {
646  break;
647  }
649  if (!condition->internal) {
650  break;
651  }
652  }
653 
654  /* We don't want continue/break outside of this loop */
655  if (*type == afw_value_block_statement_type_continue ||
656  *type == afw_value_block_statement_type_break)
657  {
658  *type = afw_value_block_statement_type_sequential;
659  }
660 
661  return result;
662 }
663 
664 
666 afw_value_block_evaluate_if(
668  afw_value_block_statement_type_t *type,
669  afw_size_t argc,
670  const afw_value_t * const * argv,
671  afw_boolean_t is_loop,
672  const afw_pool_t *p,
673  afw_xctx_t *xctx)
674 {
675  IMPL_TEMP_FIX(if);
676  const afw_value_t *result;
677  const afw_value_boolean_t *condition;
678 
681 
683  result = afw_value_null;
684  if (condition->internal) {
685  result = afw_value_block_evaluate_statement(x, type,
686  true, is_loop, argv[2], p, xctx);
687  }
688  else if (x->argc == 3) {
689  result = afw_value_block_evaluate_statement(x, type,
690  true, is_loop, argv[3], p, xctx);
691  }
692 
693  return result;
694 }
695 
696 
698 afw_value_block_evaluate_while(
700  afw_value_block_statement_type_t *type,
701  afw_size_t argc,
702  const afw_value_t * const * argv,
703  const afw_pool_t *p,
704  afw_xctx_t *xctx)
705 {
706  IMPL_TEMP_FIX(while);
707  const afw_value_t *result;
708  const afw_value_boolean_t *condition;
709 
711 
712  for (result = afw_value_null;;) {
714  if (!condition->internal) {
715  break;
716  }
717  result = afw_value_block_evaluate_statement(x, type,
718  true, true, argv[2], p, xctx);
719  if (*type == afw_value_block_statement_type_break ||
720  *type == afw_value_block_statement_type_return)
721  {
722  break;
723  }
724  }
725 
726  /* We don't want continue/break outside of this loop */
727  if (*type == afw_value_block_statement_type_continue ||
728  *type == afw_value_block_statement_type_break)
729  {
730  *type = afw_value_block_statement_type_sequential;
731  }
732 
733  return result;
734 }
735 
736 
740  afw_value_block_statement_type_t *type,
741  afw_boolean_t allow_return,
742  afw_boolean_t is_loop,
743  const afw_value_t *statement,
744  const afw_pool_t *p,
745  afw_xctx_t *xctx)
746 {
747  const afw_value_t *result;
748  const afw_value_call_t *call;
749  const afw_compile_value_contextual_t *saved_contextual;
750  const afw_value_function_definition_t *function;
751 
753  afw_function_execute_t modified_x;
754  afw_memory_copy(&modified_x, x);
755  modified_x.p = p;
756  modified_x.xctx = xctx;
757  modified_x.function = NULL;
758  x = &modified_x;
759 
760 
761  result = afw_value_null;
762  *type = afw_value_block_statement_type_sequential;
763 
764  /* If statement is block, handle special. */
765  if (afw_value_is_block(statement)) {
766  result = afw_value_block_evaluate_block(x, type,
767  (const afw_value_block_t *)statement, is_loop, p, xctx);
768  }
769 
770  /* If statement is special call, handle special. */
771  else if (afw_value_is_any_call(statement) &&
773  ((const afw_value_call_t *)statement)->function_value))
774  {
775  call = (const afw_value_call_t *)statement;
776  function = (const afw_value_function_definition_t *)
777  (call->function_value);
778  switch (function->scriptSupportNumber) {
779 
780  case AFW_VALUE_SCRIPT_SUPPORT_NUMBER_ASSIGN:
781  afw_xctx_evaluation_stack_push_value(statement, xctx);
782  saved_contextual = xctx->error->contextual;
783  xctx->error->contextual = call->args.contextual;
784  modified_x.argc = call->args.argc;
785  modified_x.argv = call->args.argv;
787 
789  AFW_FUNCTION_EVALUATE_PARAMETER(statement, 2);
790 
791  impl_assign(modified_x.argv[1], statement,
792  afw_compile_assignment_type_assign_only,
793  p, xctx);
794  result = statement;
795 
797  xctx->error->contextual = saved_contextual;
798  break;
799 
800  case AFW_VALUE_SCRIPT_SUPPORT_NUMBER_BREAK:
801  if (!is_loop) {
802  AFW_THROW_ERROR_Z(general, "Misplaced break()", xctx);
803  }
804  modified_x.argc = call->args.argc;
805  modified_x.argv = call->args.argv;
808  *type = afw_value_block_statement_type_break;
811  &modified_x, 1, NULL);
812  }
813  break;
814 
815  case AFW_VALUE_SCRIPT_SUPPORT_NUMBER_CONST:
816  afw_xctx_evaluation_stack_push_value(statement, xctx);
817  saved_contextual = xctx->error->contextual;
818  xctx->error->contextual = call->args.contextual;
819  modified_x.argc = call->args.argc;
820  modified_x.argv = call->args.argv;
824  AFW_FUNCTION_EVALUATE_PARAMETER(statement, 2);
825 
828  impl_assign(modified_x.argv[1], statement,
829  afw_compile_assignment_type_const,
830  p, xctx);
831  result = statement;
832 
834  xctx->error->contextual = saved_contextual;
835  break;
836 
837  case AFW_VALUE_SCRIPT_SUPPORT_NUMBER_CONTINUE:
838  if (!is_loop) {
839  AFW_THROW_ERROR_Z(general, "Misplaced continue()", xctx);
840  }
841  modified_x.argc = call->args.argc;
844 
845  *type = afw_value_block_statement_type_continue;
846  break;
847 
848  case AFW_VALUE_SCRIPT_SUPPORT_NUMBER_DO_WHILE:
849  afw_xctx_evaluation_stack_push_value(statement, xctx);
850  saved_contextual = xctx->error->contextual;
851  xctx->error->contextual = call->args.contextual;
852 
853  result = afw_value_block_evaluate_do_while(x, type,
854  call->args.argc, call->args.argv,
855  p, xctx);
856 
858  xctx->error->contextual = saved_contextual;
859  break;
860 
861  case AFW_VALUE_SCRIPT_SUPPORT_NUMBER_FOR:
862  afw_xctx_evaluation_stack_push_value(statement, xctx);
863  saved_contextual = xctx->error->contextual;
864  xctx->error->contextual = call->args.contextual;
865 
866  result = afw_value_block_evaluate_for(x, type,
867  call->args.argc, call->args.argv,
868  p, xctx);
869 
871  xctx->error->contextual = saved_contextual;
872  break;
873 
874  case AFW_VALUE_SCRIPT_SUPPORT_NUMBER_FOREACH:
875  afw_xctx_evaluation_stack_push_value(statement, xctx);
876  saved_contextual = xctx->error->contextual;
877  xctx->error->contextual = call->args.contextual;
878 
879  result = afw_value_block_evaluate_foreach(x, type,
880  call->args.argc, call->args.argv,
881  p, xctx);
882 
884  xctx->error->contextual = saved_contextual;
885  break;
886 
887  case AFW_VALUE_SCRIPT_SUPPORT_NUMBER_IF:
888  afw_xctx_evaluation_stack_push_value(statement, xctx);
889  saved_contextual = xctx->error->contextual;
890  xctx->error->contextual = call->args.contextual;
891 
892  result = afw_value_block_evaluate_if(x, type,
893  call->args.argc, call->args.argv, is_loop,
894  p, xctx);
895 
897  xctx->error->contextual = saved_contextual;
898  break;
899 
900  case AFW_VALUE_SCRIPT_SUPPORT_NUMBER_LOC:
901  afw_xctx_evaluation_stack_push_value(statement, xctx);
902  saved_contextual = xctx->error->contextual;
903  xctx->error->contextual = call->args.contextual;
904  modified_x.argc = call->args.argc;
905  modified_x.argv = call->args.argv;
909 
910  statement = NULL;
912  AFW_FUNCTION_EVALUATE_PARAMETER(statement, 2);
913  }
914 
915  impl_assign(modified_x.argv[1], statement,
916  afw_compile_assignment_type_loc,
917  p, xctx);
918  result = statement;
919 
921  xctx->error->contextual = saved_contextual;
922  break;
923 
924  case AFW_VALUE_SCRIPT_SUPPORT_NUMBER_RETURN:
925  *type = afw_value_block_statement_type_return;
926  modified_x.argc = call->args.argc;
927  modified_x.argv = call->args.argv;
929  if (!allow_return) {
930  AFW_THROW_ERROR_Z(general, "Misplaced return()", xctx);
931  }
934  /* NULL (undefined) is okay here. */
935  result = afw_function_evaluate_parameter(&modified_x, 1,
936  NULL);
937  }
938  break;
939 
940  case AFW_VALUE_SCRIPT_SUPPORT_NUMBER_WHILE:
941  afw_xctx_evaluation_stack_push_value(statement, xctx);
942  saved_contextual = xctx->error->contextual;
943  xctx->error->contextual = call->args.contextual;
944 
945  result = afw_value_block_evaluate_while(x, type,
946  call->args.argc, call->args.argv,
947  p, xctx);
948 
950  xctx->error->contextual = saved_contextual;
951  break;
952 
953  default:
954  result = afw_value_evaluate(statement, p, xctx);
955  }
956  }
957 
958  /* If statement is not special call, just evaluate. */
959  else {
960  result = afw_value_evaluate(statement, p, xctx);
961  }
962 
963  return result;
964 }
965 
966 
967 
970  const afw_compile_value_contextual_t *contextual,
971  afw_value_compiled_value_t *compiled_value,
972  afw_size_t *block_count,
973  const afw_pool_t *p,
974  afw_xctx_t *xctx)
975 {
976  afw_value_block_t *block;
977 
978  /* Error if top block has already ended. */
979  if (compiled_value->top_block &&
980  !compiled_value->current_block)
981  {
982  /*
983  * This is probably caused by parent being passed with top_block
984  * but already backed out of current_block.
985  */
986  AFW_THROW_ERROR_Z(general, "Block block underflow", xctx);
987 
993  }
994  else {
995  block = afw_pool_calloc_type(p, afw_value_block_t, xctx);
996  block->inf = &afw_value_block_inf;
997  block->contextual = contextual;
998  }
999  if (!compiled_value->top_block) {
1000  compiled_value->top_block = block;
1001  }
1002  else {
1003  block->parent_block = compiled_value->current_block;
1004  block->depth = block->parent_block->depth + 1;
1005  (*block_count)++;
1006  block->number = *block_count;
1007  if (!block->parent_block->first_child_block) {
1008  block->parent_block->first_child_block = block;
1009  }
1010  else {
1011  block->parent_block->final_child_block->next_sibling_block = block;
1012  }
1013  block->parent_block->final_child_block = block;
1014  }
1015  compiled_value->current_block = block;
1016 
1017  return (const afw_value_block_t*)block;
1018 }
1019 
1020 
1021 
1022 AFW_DEFINE(const afw_value_t *)
1024  const afw_value_block_t *block,
1025  afw_size_t argc,
1026  const afw_value_t * const *argv,
1027  afw_xctx_t *xctx)
1028 {
1029  afw_value_block_t *self = (afw_value_block_t *)block;
1030 
1031  self->argc = argc;
1032  self->argv = argv;
1033 
1034  return (const afw_value_t *)self;
1035 }
1036 
1037 
1038 
1039 /*
1040  * Implementation of method optional_evaluate for interface afw_value.
1041  */
1042 const afw_value_t *
1044  const afw_value_t * instance,
1045  const afw_pool_t * p,
1046  afw_xctx_t *xctx)
1047 {
1048  const afw_value_t *result;
1049  afw_value_block_statement_type_t type;
1051 
1053  x.p = p;
1054  x.xctx = xctx;
1055 
1056  /* Evaluate block. */
1057  result = afw_value_block_evaluate_block(&x, &type,
1058  (const afw_value_block_t *)instance, false, p, xctx);
1059 
1060  return result;
1061 }
1062 
1063 /*
1064  * Implementation of method get_data_type for interface afw_value.
1065  */
1066 const afw_data_type_t *
1067 impl_afw_value_get_data_type(
1068  const afw_value_t * instance,
1069  afw_xctx_t *xctx)
1070 {
1071  return NULL;
1072 }
1073 
1074 /*
1075  * Implementation of method get_evaluated_data_type for interface afw_value.
1076  */
1077 const afw_data_type_t *
1078 impl_afw_value_get_evaluated_data_type(
1079  const afw_value_t * instance,
1080  afw_xctx_t *xctx)
1081 {
1082  return NULL;
1083 }
1084 
1085 /*
1086  * Implementation of method get_evaluated_data_type_parameter for interface
1087  * afw_value.
1088  */
1089 const afw_utf8_t *
1090 impl_afw_value_get_evaluated_data_type_parameter(
1091  const afw_value_t * instance,
1092  afw_xctx_t *xctx)
1093 {
1094  return NULL;
1095 }
1096 
1097 
1098 /*
1099  * Implementation of method decompile for interface afw_value.
1100  */
1101 void
1102 impl_afw_value_produce_compiler_listing(
1103  const afw_value_t *instance,
1104  const afw_writer_t *writer,
1105  afw_xctx_t *xctx)
1106 {
1107  const afw_value_block_t *self =
1108  (const afw_value_block_t *)instance;
1109  afw_size_t i;
1110 
1111  afw_value_compiler_listing_begin_value(writer, instance,
1112  self->contextual, xctx);
1113 
1114  afw_writer_write_z(writer, " number=", xctx);
1115  afw_writer_write_size(writer, self->number, xctx);
1116 
1117  afw_writer_write_z(writer, ": [", xctx);
1118  afw_writer_write_eol(writer, xctx);
1119  afw_writer_increment_indent(writer, xctx);
1120 
1121  AFW_VALUE_COMPILER_LISTING_IF_NOT_LIMIT_EXCEEDED
1122  for (i = 0; i < self->argc; i++) {
1123  afw_value_produce_compiler_listing(self->argv[i], writer, xctx);
1124  }
1125 
1126  afw_writer_decrement_indent(writer, xctx);
1127  afw_writer_write_z(writer, "]", xctx);
1128 
1129  afw_writer_write_eol(writer, xctx);
1130 }
1131 
1132 
1133 
1134 /*
1135  * Implementation of method decompile for interface afw_value.
1136  */
1137 void
1138 impl_afw_value_decompile(
1139  const afw_value_t * instance,
1140  const afw_writer_t * writer,
1141  afw_xctx_t *xctx)
1142 {
1143  /*
1144 
1145  if (self->qualifier.len > 0) {
1146  afw_writer_write_utf8(writer, &self->qualifier, xctx);
1147  afw_writer_write_z(writer, "::", xctx);
1148  }
1149  afw_writer_write_utf8(writer, &self->name, xctx);
1150  afw_value_decompile_call_args(writer, 0, &self->args, xctx);
1151 
1152  */
1153 }
1154 
1155 
1156 /*
1157  * Implementation of method get_info for interface afw_value.
1158  */
1159 void
1160 impl_afw_value_get_info(
1161  const afw_value_t *instance,
1162  afw_value_info_t *info,
1163  const afw_pool_t *p,
1164  afw_xctx_t *xctx)
1165 {
1166  const afw_value_block_t *self =
1167  (const afw_value_block_t *)instance;
1168 
1169  afw_memory_clear(info);
1170  info->value_inf_id = &instance->inf->rti.implementation_id;
1171  info->contextual = self->contextual;
1172 }
AFW_DEFINE(const afw_object_t *)
#define AFW_DEFINE_INTERNAL(type)
Define an internal function for /src/afw/ source*.c files.
Adaptive Framework Core Internal.
Interface afw_interface implementation declares.
#define afw_value_is_integer(A_VALUE)
Macro to determine if value is evaluated integer.
afw_value_create_list(const afw_list_t *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type list value.
#define afw_value_is_list(A_VALUE)
Macro to determine if value is evaluated list.
#define afw_value_is_object(A_VALUE)
Macro to determine if value is evaluated object.
afw_value_create_object(const afw_object_t *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type object value.
afw_value_as_object(const afw_value_t *value, afw_xctx_t *xctx)
Typesafe cast of data type object.
#define afw_value_is_string(A_VALUE)
Macro to determine if value is evaluated string.
struct afw_iterator_s afw_iterator_t
_Bool afw_boolean_t
Definition: afw_common.h:373
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
afw_compile_internal_assignment_type_t
Enum for assignment types.
#define AFW_FINALLY
Always executed regardless of error.
Definition: afw_error.h:702
#define AFW_ENDTRY
Ends an AFW try block.
Definition: afw_error.h:727
#define AFW_TRY
Begin an AFW TRY block.
Definition: afw_error.h:634
#define AFW_THROW_ERROR_FZ(code, xctx, format_z,...)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:319
#define AFW_THROW_ERROR_Z(code, message_z, xctx)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:283
#define AFW_FUNCTION_EVALUATE_REQUIRED_CONDITION_PARAMETER(A_RESULT, A_N)
Evaluate an arg that is a required condition.
Definition: afw_function.h:309
afw_function_evaluate_required_parameter(afw_function_execute_t *x, afw_size_t parameter_number, const afw_data_type_t *data_type)
Evaluate an required parameter and convert if necessary.
Definition: afw_function.c:213
#define AFW_FUNCTION_EVALUATE_REQUIRED_DATA_TYPE_PARAMETER(A_RESULT, A_N, A_TYPE)
Evaluate an arg for a particular data type.
Definition: afw_function.h:328
#define AFW_FUNCTION_ASSERT_PARAMETER_COUNT_MIN(n)
Assert that argc is at least a specific number.
Definition: afw_function.h:189
#define AFW_FUNCTION_PARAMETER_IS_PRESENT(A_N)
Determine if a specific parameter value is present.
Definition: afw_function.h:242
#define AFW_FUNCTION_EVALUATE_PARAMETER(A_RESULT, A_N)
Evaluate a parameter.
Definition: afw_function.h:279
#define AFW_FUNCTION_ASSERT_PARAMETER_COUNT_MAX(n)
Assert that argc is no more than specific number.
Definition: afw_function.h:206
afw_function_evaluate_parameter(afw_function_execute_t *x, afw_size_t parameter_number, const afw_data_type_t *data_type)
Evaluate a parameter and convert if necessary.
Definition: afw_function.c:129
#define AFW_FUNCTION_ASSERT_PARAMETER_COUNT_IS(n)
Assert that argc is a specific number.
Definition: afw_function.h:172
afw_function_definition_loc
Adaptive Function le<script>
afw_function_definition_const
Function definition const.
afw_function_definition_continue
Function definition continue.
afw_function_definition_assign
Function definition assign.
afw_function_definition_break
Adaptive Function bag_size<script>
afw_function_definition_return
Adaptive Function nex<script>
#define afw_list_get_next_value(instance, iterator, p, xctx)
Call method get_next_value of interface afw_list.
afw_list_set_value_by_index(const afw_list_t *instance, afw_size_t index, const afw_value_t *value, afw_xctx_t *xctx)
Call method set_value_by_index of interface afw_list_setter.
Definition: afw_list.c:188
#define afw_list_is_immutable(list, xctx)
Determine if list is immutable.
Definition: afw_list.h:454
#define afw_list_create_generic(p, xctx)
Create an value list in memory.
Definition: afw_list.h:81
afw_list_add_value(const afw_list_t *instance, const afw_value_t *value, afw_xctx_t *xctx)
Call method add_value of interface afw_list_setter.
Definition: afw_list.c:104
#define afw_memory_clear(to)
Clear preallocated memory for sizeof(*(to)).
Definition: afw_memory.h:47
#define afw_memory_copy(to, from)
Copy to preallocated memory of same type.
Definition: afw_memory.h:39
#define afw_object_get_property(instance, property_name, xctx)
Call method get_property of interface afw_object.
#define afw_object_get_next_property(instance, iterator, property_name, xctx)
Call method get_next_property of interface afw_object.
#define afw_object_is_immutable(instance, xctx)
Determine if object is immutable.
Definition: afw_object.h:158
#define afw_object_create_managed(p, xctx)
Create an empty entity object in its own pool.
Definition: afw_object.h:913
afw_object_set_property(const afw_object_t *instance, const afw_utf8_t *property_name, const afw_value_t *value, afw_xctx_t *xctx)
Set the value of an object's property.
Definition: afw_object.c:46
#define afw_pool_calloc_type(instance, type, xctx)
Macro to allocate cleared memory to hold type in pool.
Definition: afw_pool.h:167
afw_boolean_t afw_utf8_equal(const afw_utf8_t *s1, const afw_utf8_t *s2)
Check to see if a string equals another string.
const afw_value_t * impl_afw_value_optional_evaluate(const afw_value_t *instance, const afw_pool_t *p, afw_xctx_t *xctx)
#define afw_value_produce_compiler_listing(instance, writer, xctx)
Call method produce_compiler_listing of interface afw_value.
afw_value_block_evaluate_statement(afw_function_execute_t *x, afw_value_block_statement_type_t *type, afw_boolean_t allow_return, afw_boolean_t is_loop, const afw_value_t *statement, const afw_pool_t *p, afw_xctx_t *xctx)
#define afw_value_is_variable_reference(A_VALUE)
Macro to determine if value is a variable reference.
Definition: afw_value.h:718
#define afw_value_is_block(A_VALUE)
Macro to determine if value is a block.
Definition: afw_value.h:533
#define afw_value_is_reference_by_key(A_VALUE)
Macro to determine if value is a access property by index.
Definition: afw_value.h:692
#define afw_value_evaluate(value, p, xctx)
Evaluate value if needed using specific pool.
Definition: afw_value.h:841
#define afw_value_is_assignment_target(A_VALUE)
Macro to determine if value is an assignment target.
Definition: afw_value.h:520
afw_value_as_utf8(const afw_value_t *value, const afw_pool_t *p, afw_xctx_t *xctx)
Definition: afw_value.c:456
afw_value_block_inf
Value block inf.
Definition: afw_value.h:231
#define afw_value_is_function_definition(A_VALUE)
Macro to determine if value is a function definition.
Definition: afw_value.h:614
afw_value_block_finalize(const afw_value_block_t *block, afw_size_t argc, const afw_value_t *const *argv, afw_xctx_t *xctx)
Create and link a new block.
afw_value_block_allocated_and_link(const afw_compile_value_contextual_t *contextual, afw_value_compiled_value_t *compiled_value, afw_size_t *block_count, const afw_pool_t *p, afw_xctx_t *xctx)
Create and link a new block.
afw_value_null
Adaptive value null.
Definition: afw_value.h:320
#define afw_value_is_any_call(A_VALUE)
Macro to determine if value is a call.
Definition: afw_value.h:572
#define afw_writer_increment_indent(instance, xctx)
Call method increment_indent of interface afw_writer.
#define afw_writer_write_eol(instance, xctx)
Call method write_eol of interface afw_writer.
#define afw_writer_decrement_indent(instance, xctx)
Call method decrement_indent of interface afw_writer.
#define afw_writer_write_z(writer, s_z, xctx)
Call afw_writer_write() with zero terminated string.
Definition: afw_writer.h:35
afw_writer_write_size(const afw_writer_t *writer, afw_size_t size, afw_xctx_t *xctx)
Call afw_writer_write() with an size.
Definition: afw_writer.c:162
afw_xctx_define_variable(const afw_utf8_t *name, const afw_value_t *value, afw_xctx_t *xctx)
Defined a variable in current xctx frame.
Definition: afw_xctx.c:235
int afw_xctx_begin_stack_frame(afw_xctx_t *xctx)
Begin stack frame.
Definition: afw_xctx.h:329
afw_xctx_set_local_variable(const afw_utf8_t *name, const afw_value_t *value, afw_xctx_t *xctx)
Set a variable then current xctx frame.
Definition: afw_xctx.c:289
#define afw_xctx_evaluation_stack_push_value(VALUE, xctx)
Push VALUE onto execution stack.
Definition: afw_xctx.h:78
#define afw_xctx_evaluation_stack_pop_value(xctx)
Pop top VALUE off execution stack.
Definition: afw_xctx.h:113
void afw_xctx_end_stack_frame(int top, afw_xctx_t *xctx)
Set stack top.
Definition: afw_xctx.h:343
afw_xctx_set_defined_variable(const afw_utf8_t *name, const afw_value_t *value, afw_xctx_t *xctx)
Set a defined variable in xctx.
Definition: afw_xctx.c:263
Contextual information provided in some values.
Interface afw_data_type public struct.
const afw_compile_value_contextual_t * contextual
Contextual information or NULL.
Definition: afw_error.h:83
Function execute parameter.
Definition: afw_function.h:53
const afw_value_t *const * argv
This is the function parameters.
Definition: afw_function.h:86
afw_xctx_t * xctx
The execution context (xctx) of caller.
Definition: afw_function.h:62
const afw_value_function_definition_t * function
The evaluated function definition.
Definition: afw_function.h:71
const afw_pool_t * p
Pool for result.
Definition: afw_function.h:59
afw_size_t argc
This is the argv count not counting argv[0].
Definition: afw_function.h:89
Interface afw_list public struct.
Interface afw_object public struct.
Interface afw_pool public struct.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Struct for assignment target value.
struct for afw_value_block_t
struct for data type boolean values.
const afw_value_t *const * argv
const afw_compile_value_contextual_t * contextual
Struct for call value.
Struct for function value.
Definition: afw_value.h:102
Filled in by afw_value get_info method.
Definition: afw_value.h:49
struct for data type integer values.
Struct for compiled value value.
struct for data type list values.
struct for data type object values.
Struct for reference_by_key value.
Interface afw_value public struct.
struct for data type string values.
Interface afw_writer public struct.
Interface afw_xctx public struct.