scope-validation iterate

This commit is contained in:
John Kerl 2016-05-24 18:07:52 -04:00
parent b6b1ea5950
commit e0bf2bf54e
7 changed files with 165 additions and 80 deletions

View file

@ -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);
}
// ================================================================

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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

View file

@ -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();