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
- Will be
parser
module effected by this?
- No.
- Will be
visitor
module effected by this?
- Yes. Also, the nodes in
node
module will no longer have visitor implementations due to this proposal.
- 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()
}
}
}