mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 19:23:03 +01:00
Refactor DSQL's BREAK, LEAVE and CONTINUE.
This commit is contained in:
parent
f0586b01eb
commit
23ae9f62e8
@ -677,6 +677,18 @@ DmlNode* ContinueLeaveNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, Compile
|
||||
|
||||
ContinueLeaveNode* ContinueLeaveNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
const char* cmd = blrOp == blr_continue_loop ? "CONTINUE" : "BREAK/LEAVE";
|
||||
|
||||
if (!dsqlScratch->loopLevel)
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
||||
// Token unknown
|
||||
Arg::Gds(isc_token_err) <<
|
||||
Arg::Gds(isc_random) << cmd);
|
||||
}
|
||||
|
||||
dsqlLabel = PASS1_label(dsqlScratch, true, dsqlLabel);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -687,6 +699,8 @@ void ContinueLeaveNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
|
||||
|
||||
void ContinueLeaveNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
dsqlScratch->appendUChar(blrOp);
|
||||
dsqlScratch->appendUChar((int)(IPTR) dsqlLabel->nod_arg[Dsql::e_label_number]);
|
||||
}
|
||||
|
||||
const StmtNode* ContinueLeaveNode::execute(thread_db* /*tdbb*/, jrd_req* request, ExeState* /*exeState*/) const
|
||||
@ -2087,7 +2101,7 @@ StmtNode* ExecStatementNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
if (dsqlInnerStmt)
|
||||
{
|
||||
++dsqlScratch->loopLevel;
|
||||
node->dsqlLabel = PASS1_label2(dsqlScratch, NULL, dsqlLabel);
|
||||
node->dsqlLabel = PASS1_label(dsqlScratch, false, dsqlLabel);
|
||||
node->dsqlInnerStmt = PASS1_statement(dsqlScratch, dsqlInnerStmt);
|
||||
--dsqlScratch->loopLevel;
|
||||
dsqlScratch->labels.pop();
|
||||
@ -3389,7 +3403,7 @@ StmtNode* ForNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
// CVC: Let's add the ability to BREAK the for_select same as the while,
|
||||
// but only if the command is FOR SELECT, otherwise we have singular SELECT
|
||||
dsqlScratch->loopLevel++;
|
||||
node->dsqlLabel = PASS1_label2(dsqlScratch, NULL, dsqlLabel);
|
||||
node->dsqlLabel = PASS1_label(dsqlScratch, false, dsqlLabel);
|
||||
node->dsqlAction = PASS1_statement(dsqlScratch, dsqlAction);
|
||||
dsqlScratch->loopLevel--;
|
||||
dsqlScratch->labels.pop();
|
||||
|
@ -138,7 +138,8 @@ public:
|
||||
explicit ContinueLeaveNode(MemoryPool& pool, UCHAR aBlrOp)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_CONTINUE_LEAVE>(pool),
|
||||
blrOp(aBlrOp),
|
||||
labelNumber(0)
|
||||
labelNumber(0),
|
||||
dsqlLabel(NULL)
|
||||
{
|
||||
fb_assert(blrOp == blr_continue_loop || blrOp == blr_leave);
|
||||
}
|
||||
@ -165,6 +166,7 @@ public:
|
||||
public:
|
||||
UCHAR blrOp;
|
||||
USHORT labelNumber;
|
||||
dsql_nod* dsqlLabel;
|
||||
};
|
||||
|
||||
|
||||
|
@ -668,16 +668,6 @@ void GEN_statement( DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
|
||||
GEN_statement(dsqlScratch, node->nod_arg[e_err_action]);
|
||||
return;
|
||||
|
||||
case nod_breakleave:
|
||||
dsqlScratch->appendUChar(blr_leave);
|
||||
dsqlScratch->appendUChar((int)(IPTR) node->nod_arg[e_breakleave_label]->nod_arg[e_label_number]);
|
||||
return;
|
||||
|
||||
case nod_continue:
|
||||
dsqlScratch->appendUChar(blr_continue_loop);
|
||||
dsqlScratch->appendUChar((int)(IPTR) node->nod_arg[e_continue_label]->nod_arg[e_label_number]);
|
||||
return;
|
||||
|
||||
case nod_start_savepoint:
|
||||
dsqlScratch->appendUChar(blr_start_savepoint);
|
||||
return;
|
||||
|
@ -165,7 +165,6 @@ enum nod_t
|
||||
nod_mod_field_name,
|
||||
nod_mod_field_type,
|
||||
nod_mod_field_pos,
|
||||
nod_breakleave,
|
||||
nod_udf_param, // there should be a way to signal a param by descriptor!
|
||||
nod_searched_case, // searched CASE function
|
||||
nod_simple_case, // simple CASE function
|
||||
@ -202,7 +201,6 @@ enum nod_t
|
||||
nod_package_name,
|
||||
nod_package_obj,
|
||||
nod_mod_field_null_flag,
|
||||
nod_continue,
|
||||
nod_func_obj,
|
||||
nod_function_name
|
||||
};
|
||||
@ -529,10 +527,6 @@ enum node_args {
|
||||
e_mod_fld_pos_new_position,
|
||||
e_mod_fld_pos_count,
|
||||
|
||||
// CVC: blr_leave used to emulate break
|
||||
e_breakleave_label = 0, // nod_breakleave
|
||||
e_breakleave_count,
|
||||
|
||||
e_udf_param_field = 0,
|
||||
e_udf_param_type, // Basically, by_reference or by_descriptor
|
||||
e_udf_param_count,
|
||||
@ -591,10 +585,7 @@ enum node_args {
|
||||
|
||||
e_mod_fld_null_flag_field = 0, // nod_mod_field_null_flag
|
||||
e_mod_fld_null_flag_value,
|
||||
e_mod_fld_null_flag_count,
|
||||
|
||||
e_continue_label = 0, // nod_continue
|
||||
e_continue_count
|
||||
e_mod_fld_null_flag_count
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -2596,22 +2596,27 @@ label_opt : symbol_label_name ':'
|
||||
{ $$ = NULL; }
|
||||
;
|
||||
|
||||
breakleave : KW_BREAK
|
||||
{ $$ = make_node (nod_breakleave, (int) e_breakleave_count, NULL); }
|
||||
| LEAVE
|
||||
{ $$ = make_node (nod_breakleave, (int) e_breakleave_count, NULL); }
|
||||
| LEAVE symbol_label_name
|
||||
{ $$ = make_node (nod_breakleave, (int) e_breakleave_count,
|
||||
make_node (nod_label, (int) e_label_count, $2, NULL)); }
|
||||
;
|
||||
breakleave
|
||||
: KW_BREAK
|
||||
{ $$ = makeClassNode(newNode<ContinueLeaveNode>(blr_leave)); }
|
||||
| LEAVE
|
||||
{ $$ = makeClassNode(newNode<ContinueLeaveNode>(blr_leave)); }
|
||||
| LEAVE symbol_label_name
|
||||
{
|
||||
ContinueLeaveNode* node = newNode<ContinueLeaveNode>(blr_leave);
|
||||
node->dsqlLabel = make_node(nod_label, (int) e_label_count, $2, NULL);
|
||||
$$ = makeClassNode(node);
|
||||
}
|
||||
;
|
||||
|
||||
continue
|
||||
: CONTINUE
|
||||
{ $$ = make_node(nod_continue, (int) e_continue_count, NULL); }
|
||||
{ $$ = makeClassNode(newNode<ContinueLeaveNode>(blr_continue_loop)); }
|
||||
| CONTINUE symbol_label_name
|
||||
{
|
||||
$$ = make_node(nod_continue, (int) e_continue_count,
|
||||
make_node(nod_label, (int) e_label_count, $2, NULL));
|
||||
ContinueLeaveNode* node = newNode<ContinueLeaveNode>(blr_continue_loop);
|
||||
node->dsqlLabel = make_node(nod_label, (int) e_label_count, $2, NULL);
|
||||
$$ = makeClassNode(node);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -1275,28 +1275,6 @@ dsql_nod* PASS1_statement(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
|
||||
node->nod_arg[e_err_action] = PASS1_statement(dsqlScratch, input->nod_arg[e_err_action]);
|
||||
return node;
|
||||
|
||||
case nod_breakleave:
|
||||
if (!dsqlScratch->loopLevel)
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
||||
// Token unknown
|
||||
Arg::Gds(isc_token_err) <<
|
||||
Arg::Gds(isc_random) << Arg::Str("BREAK/LEAVE"));
|
||||
}
|
||||
input->nod_arg[e_breakleave_label] = PASS1_label(dsqlScratch, input);
|
||||
return input;
|
||||
|
||||
case nod_continue:
|
||||
if (!dsqlScratch->loopLevel)
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
||||
// Token unknown
|
||||
Arg::Gds(isc_token_err) <<
|
||||
Arg::Gds(isc_random) << Arg::Str("CONTINUE"));
|
||||
}
|
||||
input->nod_arg[e_continue_label] = PASS1_label(dsqlScratch, input);
|
||||
return input;
|
||||
|
||||
case nod_select:
|
||||
{
|
||||
node = PASS1_rse(dsqlScratch, input->nod_arg[e_select_expr], input->nod_arg[e_select_lock]);
|
||||
@ -1339,7 +1317,7 @@ dsql_nod* PASS1_statement(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
|
||||
// CVC: loop numbers should be incremented before analyzing the body
|
||||
// to preserve nesting <==> increasing level number
|
||||
dsqlScratch->loopLevel++;
|
||||
node->nod_arg[e_while_label] = PASS1_label(dsqlScratch, input);
|
||||
node->nod_arg[e_while_label] = PASS1_label(dsqlScratch, false, input->nod_arg[e_while_label]);
|
||||
node->nod_arg[e_while_action] = PASS1_statement(dsqlScratch, input->nod_arg[e_while_action]);
|
||||
dsqlScratch->loopLevel--;
|
||||
dsqlScratch->labels.pop();
|
||||
@ -3853,39 +3831,9 @@ static dsql_nod* pass1_insert( DsqlCompilerScratch* dsqlScratch, dsql_nod* input
|
||||
|
||||
|
||||
// Process loop interruption.
|
||||
dsql_nod* PASS1_label(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
|
||||
dsql_nod* PASS1_label(DsqlCompilerScratch* dsqlScratch, bool breakContinue, dsql_nod* label)
|
||||
{
|
||||
DEV_BLKCHK(dsqlScratch, dsql_type_req);
|
||||
DEV_BLKCHK(input, dsql_type_nod);
|
||||
|
||||
dsql_nod* label = NULL;
|
||||
|
||||
// retrieve a label
|
||||
|
||||
switch (input->nod_type)
|
||||
{
|
||||
case nod_breakleave:
|
||||
label = input->nod_arg[e_breakleave_label];
|
||||
break;
|
||||
case nod_continue:
|
||||
label = input->nod_arg[e_continue_label];
|
||||
break;
|
||||
case nod_while:
|
||||
label = input->nod_arg[e_while_label];
|
||||
break;
|
||||
default:
|
||||
fb_assert(false);
|
||||
}
|
||||
|
||||
return PASS1_label2(dsqlScratch, input, label);
|
||||
}
|
||||
|
||||
|
||||
// Process loop interruption.
|
||||
dsql_nod* PASS1_label2(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, dsql_nod* label)
|
||||
{
|
||||
DEV_BLKCHK(dsqlScratch, dsql_type_req);
|
||||
DEV_BLKCHK(input, dsql_type_nod);
|
||||
DEV_BLKCHK(label, dsql_type_nod);
|
||||
|
||||
// look for a label, if specified
|
||||
@ -3916,7 +3864,8 @@ dsql_nod* PASS1_label2(DsqlCompilerScratch* dsqlScratch, dsql_nod* input, dsql_n
|
||||
}
|
||||
|
||||
USHORT number = 0;
|
||||
if (input && (input->nod_type == nod_breakleave || input->nod_type == nod_continue))
|
||||
|
||||
if (breakContinue)
|
||||
{
|
||||
if (position > 0)
|
||||
{
|
||||
@ -7778,14 +7727,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
|
||||
verb = "end_backup";
|
||||
break;
|
||||
|
||||
case nod_breakleave:
|
||||
verb = "breakleave";
|
||||
break;
|
||||
|
||||
case nod_continue:
|
||||
verb = "continue";
|
||||
break;
|
||||
|
||||
case nod_while:
|
||||
verb = "while";
|
||||
break;
|
||||
|
@ -35,8 +35,7 @@ Jrd::dsql_nod* PASS1_compose(Jrd::dsql_nod*, Jrd::dsql_nod*, UCHAR);
|
||||
Jrd::dsql_nod* PASS1_cursor_name(Jrd::DsqlCompilerScratch*, const Firebird::MetaName&, USHORT, bool);
|
||||
void PASS1_expand_select_node(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*, Jrd::DsqlNodStack&, bool);
|
||||
void PASS1_field_unknown(const TEXT*, const TEXT*, const Jrd::dsql_nod*);
|
||||
Jrd::dsql_nod* PASS1_label(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
|
||||
Jrd::dsql_nod* PASS1_label2(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*, Jrd::dsql_nod*);
|
||||
Jrd::dsql_nod* PASS1_label(Jrd::DsqlCompilerScratch*, bool, Jrd::dsql_nod*);
|
||||
Jrd::dsql_nod* PASS1_lookup_alias(Jrd::DsqlCompilerScratch*, const Jrd::dsql_str*, Jrd::dsql_nod*, bool);
|
||||
Jrd::dsql_ctx* PASS1_make_context(Jrd::DsqlCompilerScratch* statement, const Jrd::dsql_nod* relation_node);
|
||||
Jrd::dsql_nod* PASS1_node(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
|
||||
|
Loading…
Reference in New Issue
Block a user