mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-22 15:37:59 +00:00
scope-validation iterate
This commit is contained in:
parent
b6b1ea5950
commit
e0bf2bf54e
7 changed files with 165 additions and 80 deletions
|
|
@ -134,7 +134,7 @@ md_unbraced_statement(A) ::= MD_TOKEN_BREAK(O). {
|
|||
A = mlr_dsl_ast_node_alloc(O->text, MD_AST_NODE_TYPE_BREAK);
|
||||
}
|
||||
md_unbraced_statement(A) ::= MD_TOKEN_CONTINUE(O). {
|
||||
A = mlr_dsl_ast_node_alloc(O->text, MD_AST_NODE_TYPE_BREAK);
|
||||
A = mlr_dsl_ast_node_alloc(O->text, MD_AST_NODE_TYPE_CONTINUE);
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
|
|
|
|||
|
|
@ -133,13 +133,14 @@ static mapper_t* mapper_filter_alloc(ap_state_t* pargp, char* mlr_dsl_expression
|
|||
mlr_dsl_ast_node_t* past, int type_inferencing, int do_exclude)
|
||||
{
|
||||
mapper_filter_state_t* pstate = mlr_malloc_or_die(sizeof(mapper_filter_state_t));
|
||||
int context_flags = 0; // xxx
|
||||
|
||||
pstate->pargp = pargp;
|
||||
// Retain the string contents along with any in-pointers from the AST/CST
|
||||
pstate->mlr_dsl_expression = mlr_dsl_expression;
|
||||
pstate->comment_stripped_mlr_dsl_expression = comment_stripped_mlr_dsl_expression;
|
||||
pstate->past = past;
|
||||
pstate->pevaluator = rval_evaluator_alloc_from_ast(past, type_inferencing);
|
||||
pstate->pevaluator = rval_evaluator_alloc_from_ast(past, type_inferencing, context_flags);
|
||||
pstate->poosvars = mlhmmv_alloc();
|
||||
pstate->do_exclude = do_exclude;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,7 @@
|
|||
#include "lib/mlr_globals.h"
|
||||
#include "lib/mlrutil.h"
|
||||
#include "mlr_dsl_cst.h"
|
||||
|
||||
// The grammar permits certain statements which are syntactically invalid, (a) because it's awkward to handle
|
||||
// there, and (b) because we get far better control over error messages here (vs. 'syntax error').
|
||||
// The following flags are used as the CST is built from the AST for CST-build-time validation.
|
||||
// xxx move to header file for use by rval expr evaluators
|
||||
#define IN_BINDABLE 0x0100 // boundvars are only OK inside a bindable, e.g. (recursively) inside a for-loop
|
||||
#define IN_BREAKABLE 0x0200 // break/continue are only OK (recursively) inside for/while/do-while
|
||||
#define IN_BEGIN_OR_END 0x0400 // $stuff is not OK (recursively) inside begin/end
|
||||
#include "context_flags.h"
|
||||
|
||||
static mlr_dsl_ast_node_t* get_list_for_block(mlr_dsl_ast_node_t* pnode);
|
||||
|
||||
|
|
@ -31,6 +24,8 @@ static mlr_dsl_cst_statement_t* alloc_while(mlr_dsl_a
|
|||
static mlr_dsl_cst_statement_t* alloc_do_while(mlr_dsl_ast_node_t* past, int ti, int cf);
|
||||
static mlr_dsl_cst_statement_t* alloc_for_srec(mlr_dsl_ast_node_t* past, int ti, int cf);
|
||||
static mlr_dsl_cst_statement_t* alloc_for_oosvar(mlr_dsl_ast_node_t* past, int ti, int cf);
|
||||
static mlr_dsl_cst_statement_t* alloc_break(mlr_dsl_ast_node_t* past, int ti, int cf);
|
||||
static mlr_dsl_cst_statement_t* alloc_continue(mlr_dsl_ast_node_t* past, int ti, int cf);
|
||||
static mlr_dsl_cst_statement_t* alloc_conditional_block(mlr_dsl_ast_node_t* past, int ti, int cf);
|
||||
static mlr_dsl_cst_statement_t* alloc_if_head(mlr_dsl_ast_node_t* past, int ti, int cf);
|
||||
static mlr_dsl_cst_statement_t* alloc_filter(mlr_dsl_ast_node_t* past, int ti, int cf);
|
||||
|
|
@ -73,6 +68,8 @@ static void handle_do_while(mlr_dsl_cst_statement_t* s,
|
|||
static void handle_do_while(mlr_dsl_cst_statement_t* s, variables_t* v, cst_outputs_t* o);
|
||||
static void handle_for_srec(mlr_dsl_cst_statement_t* s, variables_t* v, cst_outputs_t* o);
|
||||
static void handle_for_oosvar(mlr_dsl_cst_statement_t* s, variables_t* v, cst_outputs_t* o);
|
||||
static void handle_break(mlr_dsl_cst_statement_t* s, variables_t* v, cst_outputs_t* o);
|
||||
static void handle_continue(mlr_dsl_cst_statement_t* s, variables_t* v, cst_outputs_t* o);
|
||||
static void handle_if_head(mlr_dsl_cst_statement_t* s, variables_t* v, cst_outputs_t* o);
|
||||
static void handle_bare_boolean(mlr_dsl_cst_statement_t* s, variables_t* v, cst_outputs_t* o);
|
||||
|
||||
|
|
@ -267,6 +264,7 @@ static mlr_dsl_cst_statement_t* alloc_cst_statement(mlr_dsl_ast_node_t* pnode, i
|
|||
switch(pnode->type) {
|
||||
|
||||
// xxx invalidates based on context flags
|
||||
// xxx comment we only invalidate LHS here (and RHS for full-srec stuff). the rest in rval_expr_evaluators.
|
||||
// IN_BINDABLE
|
||||
// IN_BREAKABLE
|
||||
// IN_BEGIN_OR_END
|
||||
|
|
@ -294,14 +292,20 @@ static mlr_dsl_cst_statement_t* alloc_cst_statement(mlr_dsl_ast_node_t* pnode, i
|
|||
break;
|
||||
|
||||
case MD_AST_NODE_TYPE_BREAK:
|
||||
// xxx not OK unless IN_BREAKABLE
|
||||
printf("break alloc stub!\n");
|
||||
return NULL;
|
||||
if (!(context_flags & IN_BREAKABLE)) {
|
||||
fprintf(stderr, "%s: break statements are only valid within for, while, or do-while.\n",
|
||||
MLR_GLOBALS.argv0);
|
||||
exit(1);
|
||||
}
|
||||
return alloc_break(pnode, type_inferencing, context_flags);
|
||||
break;
|
||||
case MD_AST_NODE_TYPE_CONTINUE:
|
||||
printf("continue alloc stub!\n");
|
||||
// xxx not OK unless IN_BREAKABLE
|
||||
return NULL;
|
||||
if (!(context_flags & IN_BREAKABLE)) {
|
||||
fprintf(stderr, "%s: break statements are only valid within for, while, or do-while.\n",
|
||||
MLR_GLOBALS.argv0);
|
||||
exit(1);
|
||||
}
|
||||
return alloc_continue(pnode, type_inferencing, context_flags);
|
||||
break;
|
||||
|
||||
case MD_AST_NODE_TYPE_CONDITIONAL_BLOCK:
|
||||
|
|
@ -312,26 +316,42 @@ static mlr_dsl_cst_statement_t* alloc_cst_statement(mlr_dsl_ast_node_t* pnode, i
|
|||
break;
|
||||
|
||||
case MD_AST_NODE_TYPE_SREC_ASSIGNMENT:
|
||||
// xxx not OK IN_BEGIN_OR_END
|
||||
if ((context_flags & IN_BEGIN_OR_END)) {
|
||||
fprintf(stderr, "%s: assignments to $-variables are not valid within begin or end blocks.\n",
|
||||
MLR_GLOBALS.argv0);
|
||||
exit(1);
|
||||
}
|
||||
return alloc_srec_assignment(pnode, type_inferencing, context_flags);
|
||||
break;
|
||||
case MD_AST_NODE_TYPE_INDIRECT_SREC_ASSIGNMENT:
|
||||
// xxx not OK IN_BEGIN_OR_END
|
||||
if ((context_flags & IN_BEGIN_OR_END)) {
|
||||
fprintf(stderr, "%s: assignments to $-variables are not valid within begin or end blocks.\n",
|
||||
MLR_GLOBALS.argv0);
|
||||
exit(1);
|
||||
}
|
||||
return alloc_indirect_srec_assignment(pnode, type_inferencing, context_flags);
|
||||
break;
|
||||
case MD_AST_NODE_TYPE_OOSVAR_ASSIGNMENT:
|
||||
return alloc_oosvar_assignment(pnode, type_inferencing, context_flags);
|
||||
break;
|
||||
case MD_AST_NODE_TYPE_OOSVAR_FROM_FULL_SREC_ASSIGNMENT:
|
||||
// xxx not OK IN_BEGIN_OR_END
|
||||
if ((context_flags & IN_BEGIN_OR_END)) {
|
||||
fprintf(stderr, "%s: assignments from $-variables are not valid within begin or end blocks.\n",
|
||||
MLR_GLOBALS.argv0);
|
||||
exit(1);
|
||||
}
|
||||
return alloc_oosvar_from_full_srec_assignment(pnode, type_inferencing, context_flags);
|
||||
break;
|
||||
case MD_AST_NODE_TYPE_FULL_SREC_FROM_OOSVAR_ASSIGNMENT:
|
||||
// xxx not OK IN_BEGIN_OR_END
|
||||
if ((context_flags & IN_BEGIN_OR_END)) {
|
||||
fprintf(stderr, "%s: assignments to $-variables are not valid within begin or end blocks.\n",
|
||||
MLR_GLOBALS.argv0);
|
||||
exit(1);
|
||||
}
|
||||
return alloc_full_srec_from_oosvar_assignment(pnode, type_inferencing, context_flags);
|
||||
break;
|
||||
case MD_AST_NODE_TYPE_UNSET:
|
||||
// xxx not OK to unset srec IN_BEGIN_OR_END
|
||||
// xxx not OK to unset srec IN_BEGIN_OR_END. pass this through.
|
||||
return alloc_unset(pnode, type_inferencing, context_flags);
|
||||
break;
|
||||
case MD_AST_NODE_TYPE_EMITF:
|
||||
|
|
@ -344,14 +364,14 @@ static mlr_dsl_cst_statement_t* alloc_cst_statement(mlr_dsl_ast_node_t* pnode, i
|
|||
return alloc_emit_or_emitp(pnode, type_inferencing, FALSE, context_flags);
|
||||
break;
|
||||
case MD_AST_NODE_TYPE_FILTER:
|
||||
// xxx not OK to test on srec IN_BEGIN_OR_END
|
||||
// xxx not OK to test on srec IN_BEGIN_OR_END. pass this through.
|
||||
return alloc_filter(pnode, type_inferencing, context_flags);
|
||||
break;
|
||||
case MD_AST_NODE_TYPE_DUMP:
|
||||
return alloc_dump(pnode, type_inferencing, context_flags);
|
||||
break;
|
||||
default:
|
||||
// xxx not OK to test on srec IN_BEGIN_OR_END
|
||||
// xxx not OK to test on srec IN_BEGIN_OR_END. pass this through.
|
||||
return alloc_bare_boolean(pnode, type_inferencing, context_flags);
|
||||
break;
|
||||
}
|
||||
|
|
@ -406,7 +426,7 @@ static mlr_dsl_cst_statement_t* alloc_srec_assignment(mlr_dsl_ast_node_t* past,
|
|||
|
||||
pstatement->phandler = handle_srec_assignment;
|
||||
pstatement->srec_lhs_field_name = pleft->text;
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pright, type_inferencing);
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pright, type_inferencing, context_flags);
|
||||
return pstatement;
|
||||
}
|
||||
|
||||
|
|
@ -432,8 +452,8 @@ static mlr_dsl_cst_statement_t* alloc_indirect_srec_assignment(mlr_dsl_ast_node_
|
|||
mlr_dsl_ast_node_t* pright = past->pchildren->phead->pnext->pvvalue;
|
||||
|
||||
pstatement->phandler = handle_indirect_srec_assignment;
|
||||
pstatement->psrec_lhs_evaluator = rval_evaluator_alloc_from_ast(pleft, type_inferencing);
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pright, type_inferencing);
|
||||
pstatement->psrec_lhs_evaluator = rval_evaluator_alloc_from_ast(pleft, type_inferencing, context_flags);
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pright, type_inferencing, context_flags);
|
||||
return pstatement;
|
||||
}
|
||||
|
||||
|
|
@ -465,7 +485,7 @@ static mlr_dsl_cst_statement_t* alloc_oosvar_assignment(mlr_dsl_ast_node_t* past
|
|||
}
|
||||
|
||||
pstatement->poosvar_lhs_keylist_evaluators = poosvar_lhs_keylist_evaluators;
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pright, type_inferencing);
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pright, type_inferencing, context_flags);
|
||||
|
||||
return pstatement;
|
||||
}
|
||||
|
|
@ -549,7 +569,7 @@ static mlr_dsl_cst_statement_t* alloc_unset(mlr_dsl_ast_node_t* past, int type_i
|
|||
} else if (pnode->type == MD_AST_NODE_TYPE_INDIRECT_FIELD_NAME) {
|
||||
sllv_append(pstatement->pvarargs, mlr_dsl_cst_statement_vararg_alloc(
|
||||
NULL,
|
||||
rval_evaluator_alloc_from_ast(pnode->pchildren->phead->pvvalue, type_inferencing),
|
||||
rval_evaluator_alloc_from_ast(pnode->pchildren->phead->pvvalue, type_inferencing, context_flags),
|
||||
NULL,
|
||||
NULL));
|
||||
|
||||
|
|
@ -609,7 +629,7 @@ static mlr_dsl_cst_statement_t* alloc_emitf(mlr_dsl_ast_node_t* pnode, int type_
|
|||
sllv_append(pstatement->pvarargs, mlr_dsl_cst_statement_vararg_alloc(
|
||||
pchild->text,
|
||||
NULL,
|
||||
rval_evaluator_alloc_from_ast(pwalker, type_inferencing),
|
||||
rval_evaluator_alloc_from_ast(pwalker, type_inferencing, context_flags),
|
||||
NULL));
|
||||
}
|
||||
|
||||
|
|
@ -652,7 +672,7 @@ static mlr_dsl_cst_statement_t* alloc_emit_or_emitp(mlr_dsl_ast_node_t* pnode, i
|
|||
for (sllve_t* pe = pnode->pchildren->phead->pnext; pe != NULL; pe = pe->pnext) {
|
||||
mlr_dsl_ast_node_t* pkeynode = pe->pvvalue;
|
||||
sllv_append(pemit_oosvar_namelist_evaluators,
|
||||
rval_evaluator_alloc_from_ast(pkeynode, type_inferencing));
|
||||
rval_evaluator_alloc_from_ast(pkeynode, type_inferencing, context_flags));
|
||||
}
|
||||
|
||||
pstatement->phandler = do_full_prefixing
|
||||
|
|
@ -666,7 +686,7 @@ static mlr_dsl_cst_statement_t* alloc_emit_or_emitp(mlr_dsl_ast_node_t* pnode, i
|
|||
for (sllve_t* pe = pnode->pchildren->phead->pnext; pe != NULL; pe = pe->pnext) {
|
||||
mlr_dsl_ast_node_t* pkeynode = pe->pvvalue;
|
||||
sllv_append(pemit_oosvar_namelist_evaluators,
|
||||
rval_evaluator_alloc_from_ast(pkeynode, type_inferencing));
|
||||
rval_evaluator_alloc_from_ast(pkeynode, type_inferencing, context_flags));
|
||||
}
|
||||
|
||||
pstatement->phandler = do_full_prefixing
|
||||
|
|
@ -703,7 +723,7 @@ static mlr_dsl_cst_statement_t* alloc_while(mlr_dsl_ast_node_t* past, int type_i
|
|||
}
|
||||
|
||||
pstatement->phandler = handle_while;
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pleft, type_inferencing);
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pleft, type_inferencing, context_flags);
|
||||
pstatement->pblock_statements = pblock_statements;
|
||||
return pstatement;
|
||||
}
|
||||
|
|
@ -726,7 +746,7 @@ static mlr_dsl_cst_statement_t* alloc_do_while(mlr_dsl_ast_node_t* past, int typ
|
|||
}
|
||||
|
||||
pstatement->phandler = handle_do_while;
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pright, type_inferencing);
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pright, type_inferencing, context_flags);
|
||||
pstatement->pblock_statements = pblock_statements;
|
||||
return pstatement;
|
||||
}
|
||||
|
|
@ -827,17 +847,7 @@ static mlr_dsl_cst_statement_t* alloc_for_oosvar(mlr_dsl_ast_node_t* past, int t
|
|||
sllv_t* pblock_statements = sllv_alloc();
|
||||
for (sllve_t* pe = pright->pchildren->phead; pe != NULL; pe = pe->pnext) {
|
||||
mlr_dsl_ast_node_t* pbody_ast_node = pe->pvvalue;
|
||||
// xxx also elsewhere, invalidate. cmt there this is done at the CST
|
||||
// rather than AST-parse level since we can give better error messages
|
||||
// (and, a simpler Lemon grammar).
|
||||
if (pbody_ast_node->type == MD_AST_NODE_TYPE_CONTINUE) {
|
||||
printf("continue alloc stub!\n");
|
||||
} else if (pbody_ast_node->type == MD_AST_NODE_TYPE_BREAK) {
|
||||
printf("break alloc stub!\n");
|
||||
} else {
|
||||
// xxx stub 3rd arg
|
||||
sllv_append(pblock_statements, alloc_cst_statement(pbody_ast_node, type_inferencing, context_flags));
|
||||
}
|
||||
sllv_append(pblock_statements, alloc_cst_statement(pbody_ast_node, type_inferencing, context_flags));
|
||||
}
|
||||
pstatement->pblock_statements = pblock_statements;
|
||||
pstatement->pbound_variables = lhmsmv_alloc();
|
||||
|
|
@ -847,6 +857,23 @@ static mlr_dsl_cst_statement_t* alloc_for_oosvar(mlr_dsl_ast_node_t* past, int t
|
|||
return pstatement;
|
||||
}
|
||||
|
||||
static mlr_dsl_cst_statement_t* alloc_break(mlr_dsl_ast_node_t* past, int type_inferencing,
|
||||
int context_flags)
|
||||
{
|
||||
mlr_dsl_cst_statement_t* pstatement = alloc_blank();
|
||||
pstatement->phandler = handle_break;
|
||||
return pstatement;
|
||||
}
|
||||
|
||||
static mlr_dsl_cst_statement_t* alloc_continue(mlr_dsl_ast_node_t* past, int type_inferencing,
|
||||
int context_flags)
|
||||
{
|
||||
mlr_dsl_cst_statement_t* pstatement = alloc_blank();
|
||||
pstatement->phandler = handle_continue;
|
||||
return pstatement;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static mlr_dsl_cst_statement_t* alloc_conditional_block(mlr_dsl_ast_node_t* pnode,
|
||||
int type_inferencing, int context_flags)
|
||||
{
|
||||
|
|
@ -865,7 +892,7 @@ static mlr_dsl_cst_statement_t* alloc_conditional_block(mlr_dsl_ast_node_t* pnod
|
|||
}
|
||||
|
||||
pstatement->phandler = handle_conditional_block;
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pleft, type_inferencing);
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pleft, type_inferencing, context_flags);
|
||||
pstatement->pblock_statements = pblock_statements;
|
||||
return pstatement;
|
||||
}
|
||||
|
|
@ -966,7 +993,7 @@ static mlr_dsl_cst_statement_t* alloc_if_item(mlr_dsl_ast_node_t* pexprnode,
|
|||
|
||||
pstatement->phandler = NULL; // handled by the containing if-head evaluator
|
||||
pstatement->prhs_evaluator = pexprnode != NULL
|
||||
? rval_evaluator_alloc_from_ast(pexprnode, type_inferencing) // if-statement or elif-statement
|
||||
? rval_evaluator_alloc_from_ast(pexprnode, type_inferencing, context_flags) // if-statement or elif-statement
|
||||
: rval_evaluator_alloc_from_boolean(TRUE); // else-statement
|
||||
pstatement->pblock_statements = pblock_statements;
|
||||
return pstatement;
|
||||
|
|
@ -981,7 +1008,7 @@ static mlr_dsl_cst_statement_t* alloc_filter(mlr_dsl_ast_node_t* past, int type_
|
|||
mlr_dsl_ast_node_t* pnode = past->pchildren->phead->pvvalue;
|
||||
|
||||
pstatement->phandler = handle_filter;
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pnode, type_inferencing);
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(pnode, type_inferencing, context_flags);
|
||||
return pstatement;
|
||||
}
|
||||
|
||||
|
|
@ -1000,7 +1027,7 @@ static mlr_dsl_cst_statement_t* alloc_bare_boolean(mlr_dsl_ast_node_t* past, int
|
|||
mlr_dsl_cst_statement_t* pstatement = alloc_blank();
|
||||
|
||||
pstatement->phandler = handle_bare_boolean;
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(past, type_inferencing);
|
||||
pstatement->prhs_evaluator = rval_evaluator_alloc_from_ast(past, type_inferencing, context_flags);
|
||||
return pstatement;
|
||||
}
|
||||
|
||||
|
|
@ -1575,7 +1602,7 @@ static void handle_for_srec(
|
|||
|
||||
mlr_dsl_cst_handle(pnode->pblock_statements, pvars, pcst_outputs);
|
||||
}
|
||||
// xxx break/continue-handling (needs to be in rval evaluators w/ stack of brk/ctu flags @ context
|
||||
// xxx break/continue-handling (needs to be in rval evaluators w/ stack of brk/ctu flags @ context)
|
||||
lrec_free(pcopy);
|
||||
bind_stack_pop(pvars->pbind_stack);
|
||||
}
|
||||
|
|
@ -1649,6 +1676,24 @@ static void handle_for_oosvar_aux(
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void handle_break(
|
||||
mlr_dsl_cst_statement_t* pnode,
|
||||
variables_t* pvars,
|
||||
cst_outputs_t* pcst_outputs)
|
||||
{
|
||||
// xxx stub
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void handle_continue(
|
||||
mlr_dsl_cst_statement_t* pnode,
|
||||
variables_t* pvars,
|
||||
cst_outputs_t* pcst_outputs)
|
||||
{
|
||||
// xxx stub
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
static void handle_if_head(
|
||||
mlr_dsl_cst_statement_t* pnode,
|
||||
|
|
@ -1737,7 +1782,7 @@ static sllv_t* allocate_keylist_evaluators_from_oosvar_node(mlr_dsl_ast_node_t*
|
|||
if (pkeynode->type == MD_AST_NODE_TYPE_STRING_LITERAL) {
|
||||
sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_string(pkeynode->text));
|
||||
} else {
|
||||
sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_ast(pkeynode, type_inferencing));
|
||||
sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_ast(pkeynode, type_inferencing, context_flags));
|
||||
}
|
||||
}
|
||||
return pkeylist_evaluators;
|
||||
|
|
|
|||
|
|
@ -61,12 +61,14 @@ extern function_lookup_t FUNCTION_LOOKUP_TABLE[];
|
|||
// rval_expr_evaluators.c
|
||||
|
||||
// Topmost function:
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t* past, int type_inferencing);
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t* past, int type_inferencing, int context_flags);
|
||||
|
||||
// Next level:
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_field_name(char* field_name, int type_inferencing);
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_indirect_field_name(mlr_dsl_ast_node_t* pnode, int type_inferencing);
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_oosvar_keylist(mlr_dsl_ast_node_t* pnode, int type_inferencing);
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_indirect_field_name(mlr_dsl_ast_node_t* pnode,
|
||||
int type_inferencing, int context_flags);
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_oosvar_keylist(mlr_dsl_ast_node_t* pnode,
|
||||
int type_inferencing, int context_flags);
|
||||
|
||||
// This is used for evaluating strings and numbers in literal expressions, e.g. '$x = "abc"'
|
||||
// or '$x = "left_\1". The values are subject to replacement with regex captures. See comments
|
||||
|
|
@ -82,7 +84,8 @@ rval_evaluator_t* rval_evaluator_alloc_from_string(char* string);
|
|||
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_boolean_literal(char* string);
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_boolean(int boolval);
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_environment(mlr_dsl_ast_node_t* pnode, int type_inferencing);
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_environment(mlr_dsl_ast_node_t* pnode,
|
||||
int type_inferencing, int context_flags);
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_NF();
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_NR();
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_FNR();
|
||||
|
|
|
|||
|
|
@ -8,24 +8,40 @@
|
|||
#include "lib/mtrand.h"
|
||||
#include "mapping/mapper.h"
|
||||
#include "mapping/rval_evaluators.h"
|
||||
#include "mapping/context_flags.h"
|
||||
|
||||
// ================================================================
|
||||
// See comments in rval_evaluators.h
|
||||
// ================================================================
|
||||
|
||||
static rval_evaluator_t* rval_evaluator_alloc_from_ast_aux(mlr_dsl_ast_node_t* pnode,
|
||||
int type_inferencing, function_lookup_t* fcn_lookup_table);
|
||||
int type_inferencing, int context_flags, function_lookup_t* fcn_lookup_table);
|
||||
|
||||
// ================================================================
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t* pnode, int type_inferencing) {
|
||||
return rval_evaluator_alloc_from_ast_aux(pnode, type_inferencing, FUNCTION_LOOKUP_TABLE);
|
||||
// The grammar permits certain statements which are syntactically invalid, (a) because it's awkward to handle
|
||||
// there, and (b) because we get far better control over error messages here (vs. 'syntax error').
|
||||
// The context flags are used as the CST is built from the AST, for CST-build-time validation.
|
||||
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t* pnode, int type_inferencing, int context_flags) {
|
||||
return rval_evaluator_alloc_from_ast_aux(pnode, type_inferencing, context_flags, FUNCTION_LOOKUP_TABLE);
|
||||
}
|
||||
|
||||
static rval_evaluator_t* rval_evaluator_alloc_from_ast_aux(mlr_dsl_ast_node_t* pnode,
|
||||
int type_inferencing, function_lookup_t* fcn_lookup_table)
|
||||
int type_inferencing, int context_flags, function_lookup_t* fcn_lookup_table)
|
||||
{
|
||||
|
||||
// IN_BINDABLE
|
||||
// IN_BREAKABLE
|
||||
// IN_BEGIN_OR_END
|
||||
|
||||
if (pnode->pchildren == NULL) { // leaf node
|
||||
if (pnode->type == MD_AST_NODE_TYPE_FIELD_NAME) {
|
||||
// xxx functionize
|
||||
if ((context_flags & IN_BEGIN_OR_END)) {
|
||||
fprintf(stderr, "%s: statements involving $-variables are not valid within begin or end blocks.\n",
|
||||
MLR_GLOBALS.argv0);
|
||||
exit(1);
|
||||
}
|
||||
return rval_evaluator_alloc_from_field_name(pnode->text, type_inferencing);
|
||||
} else if (pnode->type == MD_AST_NODE_TYPE_STRNUM_LITERAL) {
|
||||
return rval_evaluator_alloc_from_strnum_literal(pnode->text, type_inferencing);
|
||||
|
|
@ -36,6 +52,11 @@ static rval_evaluator_t* rval_evaluator_alloc_from_ast_aux(mlr_dsl_ast_node_t* p
|
|||
} else if (pnode->type == MD_AST_NODE_TYPE_CONTEXT_VARIABLE) {
|
||||
return rval_evaluator_alloc_from_context_variable(pnode->text);
|
||||
} else if (pnode->type == MD_AST_NODE_TYPE_BOUND_VARIABLE) {
|
||||
if (!(context_flags & IN_BINDABLE)) {
|
||||
fprintf(stderr, "%s: statements involving bound variables are not valid outside for-loops.\n",
|
||||
MLR_GLOBALS.argv0);
|
||||
exit(1);
|
||||
}
|
||||
return rval_evaluator_alloc_from_bound_variable(pnode->text);
|
||||
} else {
|
||||
fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n",
|
||||
|
|
@ -44,13 +65,19 @@ static rval_evaluator_t* rval_evaluator_alloc_from_ast_aux(mlr_dsl_ast_node_t* p
|
|||
}
|
||||
|
||||
} else if (pnode->type == MD_AST_NODE_TYPE_INDIRECT_FIELD_NAME) {
|
||||
return rval_evaluator_alloc_from_indirect_field_name(pnode->pchildren->phead->pvvalue, type_inferencing);
|
||||
if ((context_flags & IN_BEGIN_OR_END)) {
|
||||
fprintf(stderr, "%s: statements involving $-variables are not valid within begin or end blocks.\n",
|
||||
MLR_GLOBALS.argv0);
|
||||
exit(1);
|
||||
}
|
||||
return rval_evaluator_alloc_from_indirect_field_name(pnode->pchildren->phead->pvvalue,
|
||||
type_inferencing, context_flags);
|
||||
|
||||
} else if (pnode->type == MD_AST_NODE_TYPE_OOSVAR_KEYLIST) {
|
||||
return rval_evaluator_alloc_from_oosvar_keylist(pnode, type_inferencing);
|
||||
return rval_evaluator_alloc_from_oosvar_keylist(pnode, type_inferencing, context_flags);
|
||||
|
||||
} else if (pnode->type == MD_AST_NODE_TYPE_ENV) {
|
||||
return rval_evaluator_alloc_from_environment(pnode, type_inferencing);
|
||||
return rval_evaluator_alloc_from_environment(pnode, type_inferencing, context_flags);
|
||||
|
||||
} else { // operator/function
|
||||
if ((pnode->type != MD_AST_NODE_TYPE_NON_SIGIL_NAME)
|
||||
|
|
@ -70,7 +97,8 @@ static rval_evaluator_t* rval_evaluator_alloc_from_ast_aux(mlr_dsl_ast_node_t* p
|
|||
pevaluator = rval_evaluator_alloc_from_zary_func_name(func_name);
|
||||
} else if (user_provided_arity == 1) {
|
||||
mlr_dsl_ast_node_t* parg1_node = pnode->pchildren->phead->pvvalue;
|
||||
rval_evaluator_t* parg1 = rval_evaluator_alloc_from_ast_aux(parg1_node, type_inferencing, fcn_lookup_table);
|
||||
rval_evaluator_t* parg1 = rval_evaluator_alloc_from_ast_aux(parg1_node, type_inferencing,
|
||||
context_flags, fcn_lookup_table);
|
||||
pevaluator = rval_evaluator_alloc_from_unary_func_name(func_name, parg1);
|
||||
} else if (user_provided_arity == 2) {
|
||||
mlr_dsl_ast_node_t* parg1_node = pnode->pchildren->phead->pvvalue;
|
||||
|
|
@ -79,12 +107,12 @@ static rval_evaluator_t* rval_evaluator_alloc_from_ast_aux(mlr_dsl_ast_node_t* p
|
|||
|
||||
if ((streq(func_name, "=~") || streq(func_name, "!=~")) && type2 == MD_AST_NODE_TYPE_STRNUM_LITERAL) {
|
||||
rval_evaluator_t* parg1 = rval_evaluator_alloc_from_ast_aux(parg1_node, type_inferencing,
|
||||
fcn_lookup_table);
|
||||
context_flags, fcn_lookup_table);
|
||||
pevaluator = rval_evaluator_alloc_from_binary_regex_arg2_func_name(func_name,
|
||||
parg1, parg2_node->text, FALSE);
|
||||
} else if ((streq(func_name, "=~") || streq(func_name, "!=~")) && type2 == MD_AST_NODE_TYPE_REGEXI) {
|
||||
rval_evaluator_t* parg1 = rval_evaluator_alloc_from_ast_aux(parg1_node, type_inferencing,
|
||||
fcn_lookup_table);
|
||||
context_flags, fcn_lookup_table);
|
||||
pevaluator = rval_evaluator_alloc_from_binary_regex_arg2_func_name(func_name, parg1, parg2_node->text,
|
||||
TYPE_INFER_STRING_FLOAT_INT);
|
||||
} else {
|
||||
|
|
@ -92,9 +120,9 @@ static rval_evaluator_t* rval_evaluator_alloc_from_ast_aux(mlr_dsl_ast_node_t* p
|
|||
// the regexes will be compiled record-by-record rather than once at alloc time, which will
|
||||
// be slower.
|
||||
rval_evaluator_t* parg1 = rval_evaluator_alloc_from_ast_aux(parg1_node, type_inferencing,
|
||||
fcn_lookup_table);
|
||||
context_flags, fcn_lookup_table);
|
||||
rval_evaluator_t* parg2 = rval_evaluator_alloc_from_ast_aux(parg2_node, type_inferencing,
|
||||
fcn_lookup_table);
|
||||
context_flags, fcn_lookup_table);
|
||||
pevaluator = rval_evaluator_alloc_from_binary_func_name(func_name, parg1, parg2);
|
||||
}
|
||||
|
||||
|
|
@ -107,18 +135,18 @@ static rval_evaluator_t* rval_evaluator_alloc_from_ast_aux(mlr_dsl_ast_node_t* p
|
|||
if ((streq(func_name, "sub") || streq(func_name, "gsub")) && type2 == MD_AST_NODE_TYPE_STRNUM_LITERAL) {
|
||||
// sub/gsub-regex special case:
|
||||
rval_evaluator_t* parg1 = rval_evaluator_alloc_from_ast_aux(parg1_node, type_inferencing,
|
||||
fcn_lookup_table);
|
||||
context_flags, fcn_lookup_table);
|
||||
rval_evaluator_t* parg3 = rval_evaluator_alloc_from_ast_aux(parg3_node, type_inferencing,
|
||||
fcn_lookup_table);
|
||||
context_flags, fcn_lookup_table);
|
||||
pevaluator = rval_evaluator_alloc_from_ternary_regex_arg2_func_name(func_name, parg1, parg2_node->text,
|
||||
FALSE, parg3);
|
||||
|
||||
} else if ((streq(func_name, "sub") || streq(func_name, "gsub")) && type2 == MD_AST_NODE_TYPE_REGEXI) {
|
||||
// sub/gsub-regex special case:
|
||||
rval_evaluator_t* parg1 = rval_evaluator_alloc_from_ast_aux(parg1_node, type_inferencing,
|
||||
fcn_lookup_table);
|
||||
context_flags, fcn_lookup_table);
|
||||
rval_evaluator_t* parg3 = rval_evaluator_alloc_from_ast_aux(parg3_node, type_inferencing,
|
||||
fcn_lookup_table);
|
||||
context_flags, fcn_lookup_table);
|
||||
pevaluator = rval_evaluator_alloc_from_ternary_regex_arg2_func_name(func_name, parg1, parg2_node->text,
|
||||
TYPE_INFER_STRING_FLOAT_INT, parg3);
|
||||
|
||||
|
|
@ -127,11 +155,11 @@ static rval_evaluator_t* rval_evaluator_alloc_from_ast_aux(mlr_dsl_ast_node_t* p
|
|||
// the regexes will be compiled record-by-record rather than once at alloc time, which will
|
||||
// be slower.
|
||||
rval_evaluator_t* parg1 = rval_evaluator_alloc_from_ast_aux(parg1_node, type_inferencing,
|
||||
fcn_lookup_table);
|
||||
context_flags, fcn_lookup_table);
|
||||
rval_evaluator_t* parg2 = rval_evaluator_alloc_from_ast_aux(parg2_node, type_inferencing,
|
||||
fcn_lookup_table);
|
||||
context_flags, fcn_lookup_table);
|
||||
rval_evaluator_t* parg3 = rval_evaluator_alloc_from_ast_aux(parg3_node, type_inferencing,
|
||||
fcn_lookup_table);
|
||||
context_flags, fcn_lookup_table);
|
||||
pevaluator = rval_evaluator_alloc_from_ternary_func_name(func_name, parg1, parg2, parg3);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -397,11 +425,13 @@ static void rval_evaluator_indirect_field_name_free(rval_evaluator_t* pevaluator
|
|||
free(pevaluator);
|
||||
}
|
||||
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_indirect_field_name(mlr_dsl_ast_node_t* pnamenode, int type_inferencing) {
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_indirect_field_name(mlr_dsl_ast_node_t* pnamenode,
|
||||
int type_inferencing, int context_flags)
|
||||
{
|
||||
rval_evaluator_indirect_field_name_state_t* pstate = mlr_malloc_or_die(
|
||||
sizeof(rval_evaluator_indirect_field_name_state_t));
|
||||
|
||||
pstate->pname_evaluator = rval_evaluator_alloc_from_ast(pnamenode, type_inferencing);
|
||||
pstate->pname_evaluator = rval_evaluator_alloc_from_ast(pnamenode, type_inferencing, context_flags);
|
||||
|
||||
rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
|
||||
pevaluator->pvstate = pstate;
|
||||
|
|
@ -481,7 +511,9 @@ static void rval_evaluator_oosvar_keylist_free(rval_evaluator_t* pevaluator) {
|
|||
// oosvar_keylist (oosvar_keylist):
|
||||
// 5 (string_literal).
|
||||
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_oosvar_keylist(mlr_dsl_ast_node_t* pnode, int type_inferencing) {
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_oosvar_keylist(mlr_dsl_ast_node_t* pnode,
|
||||
int type_inferencing, int context_flags)
|
||||
{
|
||||
rval_evaluator_oosvar_keylist_state_t* pstate = mlr_malloc_or_die(
|
||||
sizeof(rval_evaluator_oosvar_keylist_state_t));
|
||||
|
||||
|
|
@ -492,7 +524,7 @@ rval_evaluator_t* rval_evaluator_alloc_from_oosvar_keylist(mlr_dsl_ast_node_t* p
|
|||
if (pkeynode->type == MD_AST_NODE_TYPE_STRING_LITERAL) {
|
||||
sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_string(pkeynode->text));
|
||||
} else {
|
||||
sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_ast(pkeynode, type_inferencing));
|
||||
sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_ast(pkeynode, type_inferencing, context_flags));
|
||||
}
|
||||
}
|
||||
pstate->poosvar_rhs_keylist_evaluators = pkeylist_evaluators;
|
||||
|
|
@ -725,13 +757,15 @@ static void rval_evaluator_environment_free(rval_evaluator_t* pevaluator) {
|
|||
free(pevaluator);
|
||||
}
|
||||
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_environment(mlr_dsl_ast_node_t* pnode, int type_inferencing) {
|
||||
rval_evaluator_t* rval_evaluator_alloc_from_environment(mlr_dsl_ast_node_t* pnode,
|
||||
int type_inferencing, int context_flags)
|
||||
{
|
||||
rval_evaluator_environment_state_t* pstate = mlr_malloc_or_die(sizeof(rval_evaluator_environment_state_t));
|
||||
rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
|
||||
|
||||
mlr_dsl_ast_node_t* pnamenode = pnode->pchildren->phead->pnext->pvvalue;
|
||||
|
||||
pstate->pname_evaluator = rval_evaluator_alloc_from_ast(pnamenode, type_inferencing);
|
||||
pstate->pname_evaluator = rval_evaluator_alloc_from_ast(pnamenode, type_inferencing, context_flags);
|
||||
pevaluator->pprocess_func = rval_evaluator_environment_func;
|
||||
pevaluator->pfree_func = rval_evaluator_environment_free;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ TOP-OF-LIST SUMMARY
|
|||
-> find a more elegant way to do this but don't block 4.1.0
|
||||
|
||||
! CST-build-time invalidations:
|
||||
! propagate-back to caller
|
||||
! filter is oosless
|
||||
- $stuff inside begin/end
|
||||
- break/continue outside for/while/do-while
|
||||
- boundvars outside for
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ static char * test_numbers() {
|
|||
mlr_dsl_ast_node_t* p2logxnode = mlr_dsl_ast_node_alloc_binary("*", MD_AST_NODE_TYPE_OPERATOR,
|
||||
p2node, plogxnode);
|
||||
|
||||
rval_evaluator_t* pastr = rval_evaluator_alloc_from_ast(p2logxnode, TYPE_INFER_STRING_FLOAT_INT);
|
||||
rval_evaluator_t* pastr = rval_evaluator_alloc_from_ast(p2logxnode, TYPE_INFER_STRING_FLOAT_INT, 0);
|
||||
|
||||
lrec_t* prec = lrec_unbacked_alloc();
|
||||
lhmsv_t* ptyped_overlay = lhmsv_alloc();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue