First declosure impl
This commit is contained in:
@@ -10,6 +10,9 @@
|
||||
//! `get_field "prototype" ; put_field @meth`; the field-initialiser tail is
|
||||
//! dropped. Detection (`find_class_seqs`) records the ranges; replacement
|
||||
//! (`ClassSequence::emit_prototype`) reads operands out of each matched range.
|
||||
//!
|
||||
//! Derived classes (`extends`) are unsupported and panic: prototype form would
|
||||
//! have to flatten the parent's prototype in and lower `super`.
|
||||
|
||||
use std::range::Range;
|
||||
|
||||
@@ -160,6 +163,16 @@ fn find_class_seqs(mut ins: &[RegInstr]) -> Vec<ClassSequence> {
|
||||
|
||||
fn match_class_seq(ins: &[RegInstr]) -> Result<(&[RegInstr], usize), &[RegInstr]> {
|
||||
let ins = match_one(ins, |i| i.op == OpCode::PushConst8)?;
|
||||
|
||||
// A class build is `push_const8 ; define_class`. Derived classes (`extends`)
|
||||
// are unsupported: prototype form would have to flatten the parent's
|
||||
// prototype in and lower `super`, neither of which is implemented.
|
||||
if let Some(i) = ins.first() {
|
||||
if i.op == OpCode::DefineClass && is_derived(i) {
|
||||
panic!("declass: derived classes (extends) are not supported");
|
||||
}
|
||||
}
|
||||
|
||||
let ins = match_one(ins, |i| i.op == OpCode::DefineClass)?;
|
||||
let (ins, num_methods) = match_many(ins, match_method_seq);
|
||||
let ins = match_opt(ins, match_field_init_seq);
|
||||
@@ -167,6 +180,15 @@ fn match_class_seq(ins: &[RegInstr]) -> Result<(&[RegInstr], usize), &[RegInstr]
|
||||
Ok((ins, num_methods))
|
||||
}
|
||||
|
||||
/// A derived class: `define_class` with the derived flag set.
|
||||
fn is_derived(i: &RegInstr) -> bool {
|
||||
matches!(i.imm, ImmOperand::AtomU8 { arg, .. } if arg & 1 == 1)
|
||||
}
|
||||
|
||||
// TODO: accessors are not handled. A getter/setter is a `define_method` with a
|
||||
// non-zero kind in `arg`; this matcher takes it for an ordinary method, so it
|
||||
// is wrongly lowered to a `put_field` (a data property) instead of an accessor
|
||||
// property. It should instead make the whole class pass through untouched.
|
||||
fn match_method_seq(ins: &[RegInstr]) -> Result<&[RegInstr], &[RegInstr]> {
|
||||
let ins = match_one(ins, |i| i.op == OpCode::Fclosure8)?;
|
||||
let ins = match_one(ins, |i| i.op == OpCode::DefineMethod)?;
|
||||
@@ -177,7 +199,12 @@ fn match_field_init_seq(ins: &[RegInstr]) -> Result<&[RegInstr], &[RegInstr]> {
|
||||
let is_put_loc = |op| {
|
||||
matches!(
|
||||
op,
|
||||
OpCode::PutLoc | OpCode::PutLoc0 | OpCode::PutLoc1 | OpCode::PutLoc2 | OpCode::PutLoc3
|
||||
OpCode::PutLoc
|
||||
| OpCode::PutLoc8
|
||||
| OpCode::PutLoc0
|
||||
| OpCode::PutLoc1
|
||||
| OpCode::PutLoc2
|
||||
| OpCode::PutLoc3
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user