Skip to content

Commit 146a32b

Browse files
Millie Chenfacebook-github-bot
authored andcommitted
Clear Mismatch and PrintNotImpl
Summary: Fix bugs in `jump_targets`, `instruction_sequence`, `emit_statement` and add missing components to clear mismatches and 1 unimplemeted print Reviewed By: shiqicao Differential Revision: D20373730 fbshipit-source-id: 2cd7bdb4f4efad0916644f57e1453efca3839395
1 parent 121a53c commit 146a32b

File tree

5 files changed

+75
-14
lines changed

5 files changed

+75
-14
lines changed

hphp/hack/src/hhbc/emit_statement.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -314,17 +314,16 @@ pub fn emit_stmt(e: &mut Emitter, env: &mut Env, stmt: &tast::Stmt) -> Result {
314314
InstrSeq::make_throw(),
315315
])),
316316
a::Stmt_::Try(x) => {
317-
//TODO(hrust): Implement fail_if_goto_from_try_to_finally in tfr when visitor is updated
318-
// if env.jump_targets_gen().get_function_has_goto() {
319-
// tfr::fail_if_goto_from_try_to_finally(&x.0, &x.2)
320-
// }
317+
if env.jump_targets_gen.get_function_has_goto() {
318+
tfr::fail_if_goto_from_try_to_finally(&x.0, &x.2)?;
319+
}
321320
let (try_block, catch_list, finally_block) = &**x;
322321
if catch_list.is_empty() {
323322
emit_try_finally(e, env, pos, &try_block, &finally_block)
324323
} else if finally_block.is_empty() {
325324
emit_try_catch(e, env, pos, &try_block, &catch_list[..])
326325
} else {
327-
//TODO: avoid cloning block
326+
//TODO(hrust): avoid cloning block
328327
let try_catch_finally = tast::Stmt(
329328
pos.clone(),
330329
tast::Stmt_::mk_try(
@@ -498,7 +497,7 @@ fn emit_try_catch_(
498497
try_block: &tast::Block,
499498
catch_list: &[tast::Catch],
500499
) -> Result {
501-
if try_block.is_empty() {
500+
if is_empty_block(&try_block) {
502501
return Ok(InstrSeq::Empty);
503502
};
504503
let end_label = e.label_gen_mut().next_regular();

hphp/hack/src/hhbc/instruction_sequence.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,6 @@ impl InstrSeq {
214214
pub fn make_iter_break(label: Label, itrs: Vec<IterId>) -> Self {
215215
let mut instrs = itrs
216216
.into_iter()
217-
.rev()
218217
.map(|id| Instruct::IIterator(InstructIterator::IterFree(id)))
219218
.collect::<Vec<_>>();
220219
instrs.push(Instruct::IContFlow(InstructControlFlow::Jmp(label)));

hphp/hack/src/hhbc/jump_targets.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,13 @@ impl JumpTargets {
129129
// }
130130
for r in self.0.iter().rev() {
131131
match r {
132+
Region::Function(_) | Region::Finally(_) => return ResolvedJumpTarget::NotFound,
132133
Region::Using(finally_label, _) | Region::TryFinally(finally_label, _) => {
133134
// we need to jump out of try body in try/finally - in order to do this
134135
// we should go through the finally block first
135-
skip_try_finally = Some(finally_label);
136+
if skip_try_finally.is_none() {
137+
skip_try_finally = Some((finally_label, level, iters.clone()));
138+
}
136139
}
137140
Region::Switch(end_label, _) => {
138141
if level == 1 {
@@ -165,10 +168,9 @@ impl JumpTargets {
165168
level -= 1;
166169
}
167170
}
168-
_ => (),
169171
}
170172
}
171-
if let Some(finally_label) = skip_try_finally {
173+
if let Some((finally_label, level, iters)) = skip_try_finally {
172174
if let Some(target_label) = label {
173175
return ResolvedJumpTarget::ResolvedTryFinally(ResolvedTryFinally {
174176
target_label: target_label.clone(),

hphp/hack/src/hhbc/print.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ fn print_adata<W: Write>(ctx: &mut Context, w: &mut W, tv: &TypedValue) -> Resul
811811
TypedValue::VArray((values, loc)) => {
812812
print_adata_collection_argument(ctx, w, VARRAY_PREFIX, loc, values)
813813
}
814-
TypedValue::HhasAdata(_) => not_impl!(),
814+
TypedValue::HhasAdata(s) => not_impl!(),
815815
}
816816
}
817817

@@ -2003,7 +2003,13 @@ fn print_expr<W: Write>(
20032003
match expr {
20042004
E_::Id(id) => w.write(adjust_id(env, &id.1)),
20052005
E_::Lvar(lid) => w.write(escaper::escape(&(lid.1).1)),
2006-
E_::Float(f) => not_impl!(),
2006+
E_::Float(f) => {
2007+
w.write(if f.contains('E') || f.contains('e') {
2008+
format!("{:.1}E", f.parse::<f64>().map_err(|_| Error::fail(format!("ParseFloatError: {}", f)))?)
2009+
} else {
2010+
f.into()
2011+
})
2012+
}
20072013
E_::Int(i) => {
20082014
w.write(integer::to_decimal(i.as_str()).map_err(|_| Error::fail("ParseIntError"))?)
20092015
}

hphp/hack/src/hhbc/try_finally_rewriter.rs

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ use emit_fatal_rust as emit_fatal;
1414
use emit_pos_rust::emit_pos;
1515
use env::{emitter::Emitter, iterator, jump_targets as jt, local, Env};
1616
use hhbc_ast_rust::{self as hhbc_ast, Instruct};
17-
use instruction_sequence_rust::{InstrSeq, Result};
17+
use instruction_sequence_rust::{Error, InstrSeq, Result};
1818
use label::Label;
1919
use label_rust as label;
20-
use oxidized::pos::Pos;
20+
use oxidized::{
21+
aast_visitor::{visit, AstParams, Node, Visitor},
22+
ast as tast,
23+
pos::Pos,
24+
};
2125

2226
use bitflags::bitflags;
2327

@@ -184,6 +188,57 @@ pub fn emit_goto(
184188
}
185189
}
186190

191+
pub fn fail_if_goto_from_try_to_finally(
192+
try_block: &tast::Block,
193+
finally_block: &tast::Block,
194+
) -> Result<()> {
195+
fn find_gotos_in(block: &tast::Block) -> Vec<tast::Pstring> {
196+
struct State(Vec<tast::Pstring>);
197+
impl Visitor for State {
198+
type P = AstParams<(), ()>;
199+
200+
fn object(&mut self) -> &mut dyn Visitor<P = Self::P> {
201+
self
202+
}
203+
204+
fn visit_stmt_(&mut self, c: &mut (), s: &tast::Stmt_) -> std::result::Result<(), ()> {
205+
match s {
206+
tast::Stmt_::Goto(l) => Ok(self.0.push((&**l).clone())),
207+
_ => s.recurse(c, self),
208+
}
209+
}
210+
}
211+
let mut state = State(vec![]);
212+
visit(&mut state, &mut (), block).unwrap();
213+
state.0
214+
};
215+
216+
struct GotoVisitor {};
217+
impl Visitor for GotoVisitor {
218+
type P = AstParams<Vec<tast::Pstring>, Error>;
219+
220+
fn object(&mut self) -> &mut dyn Visitor<P = Self::P> {
221+
self
222+
}
223+
224+
fn visit_stmt_(&mut self, c: &mut Vec<tast::Pstring>, s: &tast::Stmt_) -> Result<()> {
225+
match s {
226+
tast::Stmt_::GotoLabel(l) => match c.iter().rev().find(|label| label.1 == l.1) {
227+
Some((pos, _)) => Err(emit_fatal::raise_fatal_parse(
228+
pos,
229+
"'goto' into finally statement is disallowed",
230+
)),
231+
_ => Ok(()),
232+
},
233+
_ => s.recurse(c, self.object()),
234+
}
235+
}
236+
}
237+
let mut visitor = GotoVisitor {};
238+
let mut goto_labels = find_gotos_in(try_block);
239+
visit(&mut visitor, &mut goto_labels, finally_block)
240+
}
241+
187242
pub(super) fn emit_return(e: &mut Emitter, in_finally_epilogue: bool, env: &mut Env) -> Result {
188243
// check if there are try/finally region
189244
let jt_gen = &env.jump_targets_gen;

0 commit comments

Comments
 (0)