%nonassoc ELSE
%type <xp> cmds_int cmd_prep
-%type <x> term term_bs cmd cmd_var cmds cmds_scoped constant constructor print_list var var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail term_dot_method method_name_cont
+%type <x> term term_bs cmd cmd_var cmds cmds_scoped constant constructor var var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail term_dot_method method_name_cont
%type <fda> dynamic_attr
%type <fsa> static_attr
%type <f> filter where_filter
| ERROR { $$ = F_ERROR; }
;
-print_list: /* EMPTY */ { $$ = NULL; }
- | term { $$ = $1; }
- | term ',' print_list {
- ASSERT($1);
- ASSERT($1->next == NULL);
- $1->next = $3;
- $$ = $1;
- }
- ;
-
var:
type symbol '=' term ';' {
struct symbol *sym = cf_define_symbol(new_config, $2, SYM_VARIABLE | $1, offset, f_new_var(sym_->scope));
| UNSET '(' dynamic_attr ')' ';' {
$$ = f_new_inst(FI_EA_UNSET, $3);
}
- | break_command print_list ';' {
- struct f_inst *breaker = f_new_inst(FI_DIE, $1);
- if ($2) {
- struct f_inst *printer = f_new_inst(FI_PRINT, $2);
- struct f_inst *flusher = f_new_inst(FI_FLUSH);
- printer->next = flusher;
- flusher->next = breaker;
- $$ = printer;
- } else
- $$ = breaker;
+ | break_command var_list ';' {
+ $$ = f_print($2, !!$2, $1);
}
- | PRINT print_list ';' {
- $$ = f_new_inst(FI_PRINT, $2);
- $$->next = f_new_inst(FI_FLUSH);
+ | PRINT var_list ';' {
+ $$ = f_print($2, 1, F_NOP);
}
- | PRINTN print_list ';' {
- $$ = f_new_inst(FI_PRINT, $2);
+ | PRINTN var_list ';' {
+ $$ = f_print($2, 0, F_NOP);
}
| function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); }
| CASE term '{' switch_body '}' {
struct filter *f_new_where(struct f_inst *);
struct f_inst *f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block);
+struct f_inst *f_print(struct f_inst *vars, int flush, enum filter_return fret);
static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
{ return (struct f_dynamic_attr) { .type = type, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */
return ms->method->new_inst(term, loop_start);
}
+struct f_inst *
+f_print(struct f_inst *vars, int flush, enum filter_return fret)
+{
+#define AX(...) do { struct f_inst *_tmp = f_new_inst(__VA_ARGS__); _tmp->next = output; output = _tmp; } while (0)
+ struct f_inst *output = NULL;
+ if (fret != F_NOP)
+ AX(FI_DIE, fret);
+
+ if (flush)
+ AX(FI_FLUSH);
+
+ while (vars)
+ {
+ struct f_inst *tmp = vars;
+ vars = vars->next;
+ tmp->next = NULL;
+
+ AX(FI_PRINT, tmp);
+ }
+
+ return output;
+#undef AX
+}
+
+
#define CA_KEY(n) n->name, n->fda.type
#define CA_NEXT(n) n->next
#define CA_EQ(na,ta,nb,tb) (!strcmp(na,nb) && (ta == tb))