ChAoSUnItY/Ka-Pi

Migrate back to ASM's Core API

ChAoSUnItY opened this issue · 3 comments

Motivation

It's only few months after we disagree with ASM's implementation and trying to makes it better by using our own implementation. However, the reality is that it's because our attempt to makes generation and parsing fully compatible on each other is a total failure. And what's more, visitor pattern we have is not ideal to use for both structural traversal and writer generation.

Idea

Yes, I admit that Ka-Pi approach is based on a good motivation which is let people have most control over the generation, but this went out to be not very ideal and makes the overall implementation harder (just bc I'm the only one who is now brainstorming about the solution).

To overcome this, a few TODOs needs to be done:

  • Reworks visitor module, into ASM's form if possible.
  • Use ASM's logic to implement parser w/ writer

Additional Note

As I suggest in the idea part, what I really mean about reimplement ASM's parser logic is that to makes another even faster parser that is only useful for intermediate level transforming, which can be later used in newly implemented ASM writer.

Questions

  1. Will be parser module effected by this?
  • No.
  1. Will be visitor module effected by this?
  • Yes. Also, the nodes in node module will no longer have visitor implementations due to this proposal.
  1. How is this going to benefit the whole project?
  • This is meant to allow users that migrates from JVM that also have experience with ASM to have more familiarity with Ka-Pi's implementation, and to prevent reinventing the wheel (not just bc it's a bad practice but to not to makes things gone too far).

抱歉,我沒有使用微信,但我目前有使用Discord和TG,你也可以在這個issue下面進行討論。

使用mut dyn 返回值可以完全模拟asm的visitor接口,供参考:

pub trait ClassVisitor {
fn inner(&mut self) -> Option<&mut dyn ClassVisitor> {
None
}

fn visit(&mut self, access: u16, name: T, signature: T, super_name: T, interfaces: Vec<T>) {
    if let Some(v) = self.inner() {
        v.visit(access, name, signature, super_name, interfaces);
    }
}

fn visit_source(&mut self, source: T, debug: T) {
    if let Some(v) = self.inner() {
        v.visit_source(source, debug);
    }
}

fn visit_field(
    &mut self,
    access: u16,
    name: T,
    descriptor: T,
    signature: T,
    value: Option<ConstantValue>,
) -> Option<&mut dyn FieldVisitor<T>> {
    if let Some(cv) = self.inner() {
        return cv.visit_field(access, name, descriptor, signature, value);
    }
    None
}

fn visit_method(
    &mut self,
    access: u16,
    name: T,
    descriptor: T,
    signature: T,
    exceptions: Vec<T>,
) -> Option<&mut dyn MethodVisitor<T>> {
    if let Some(cv) = self.inner() {
        return cv.visit_method(access, name, descriptor, signature, exceptions);
    }
    None
}

fn visit_inner_class(&mut self, name: T, outer_name: T, inner_name: T, access: u16) {
    if let Some(v) = self.inner() {
        v.visit_inner_class(name, outer_name, inner_name, access);
    }
}

fn visit_annotation(
    &mut self,
    descriptor: T,
    visible: bool,
) -> Option<&mut dyn AnnotationVisitor<T>> {
    if let Some(v) = self.inner() {
        return v.visit_annotation(descriptor, visible);
    }
    None
}

fn visit_attribute(&mut self, attribute: Attribute<T>) {
    if let Some(v) = self.inner() {
        v.visit_attribute(attribute)
    }
}

fn visit_end(&mut self) {
    if let Some(v) = self.inner() {
        v.visit_end()
    }
}

}