8
0
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:
asfernandes 2011-01-22 21:32:29 +00:00
parent f0586b01eb
commit 23ae9f62e8
7 changed files with 41 additions and 99 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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