1use super::{
2 instructions::JvmInstruction,
3 pool::JvmConstantPool,
4 types::{JvmAccessFlags, JvmAttribute, JvmBootstrapMethod, JvmField, JvmInnerClass, JvmVersion},
5};
6
7#[derive(Debug, Clone)]
9pub struct JvmProgram {
10 pub name: String,
12 pub access_flags: JvmAccessFlags,
14 pub super_class: Option<String>,
16 pub interfaces: Vec<String>,
18 pub fields: Vec<JvmField>,
20 pub methods: Vec<JvmMethod>,
22 pub attributes: Vec<JvmAttribute>,
24 pub constant_pool: JvmConstantPool,
26 pub version: JvmVersion,
28 pub source_file: Option<String>,
30 pub inner_classes: Vec<JvmInnerClass>,
32 pub enclosing_method: Option<(String, Option<String>, Option<String>)>, }
35
36impl JvmProgram {
37 pub fn new(name: String) -> Self {
39 Self {
40 name,
41 access_flags: JvmAccessFlags::public(),
42 super_class: None,
43 interfaces: Vec::new(),
44 fields: Vec::new(),
45 methods: Vec::new(),
46 attributes: Vec::new(),
47 constant_pool: JvmConstantPool::new(),
48 version: JvmVersion::java_8(),
49 source_file: None,
50 inner_classes: Vec::new(),
51 enclosing_method: None,
52 }
53 }
54
55 pub fn set_version(&mut self, major: u16, minor: u16) {
57 self.version = JvmVersion::new(major, minor);
58 }
59
60 pub fn set_super_class(&mut self, super_class: String) {
62 self.super_class = Some(super_class);
63 }
64
65 pub fn add_interface(&mut self, interface: String) {
67 self.interfaces.push(interface);
68 }
69
70 pub fn add_method(&mut self, method: JvmMethod) {
72 self.methods.push(method);
73 }
74
75 pub fn add_field(&mut self, field: JvmField) {
77 self.fields.push(field);
78 }
79
80 pub fn add_attribute(&mut self, attribute: JvmAttribute) {
82 self.attributes.push(attribute);
83 }
84
85 pub fn set_source_file(&mut self, filename: String) {
87 self.source_file = Some(filename.clone());
88 self.add_attribute(JvmAttribute::SourceFile { filename });
89 }
90
91 pub fn validate(&self) -> bool {
93 if self.name.is_empty() {
95 return false;
96 }
97 true
98 }
99
100 pub fn add_bootstrap_method(&mut self, method_ref: u16, arguments: Vec<u16>) {
102 if let Some(JvmAttribute::BootstrapMethods { methods }) = self.attributes.iter_mut().find(|attr| {
104 matches!(attr, JvmAttribute::BootstrapMethods { .. })
105 }) {
106 methods.push(JvmBootstrapMethod { method_ref, arguments });
107 } else {
108 let bootstrap_method = JvmBootstrapMethod { method_ref, arguments };
110 self.add_attribute(JvmAttribute::BootstrapMethods { methods: vec![bootstrap_method] });
111 }
112 }
113
114 pub fn create_lambda_method(&mut self, name: String, descriptor: String, instructions: Vec<JvmInstruction>) -> JvmMethod {
116 let mut method = JvmMethod::new(name, descriptor);
117 method.access_flags.is_private = true;
118 method.access_flags.is_static = true;
119 method.access_flags.is_synthetic = true;
120 method.instructions = instructions;
121 method.max_stack = 10; method.max_locals = 10; method
124 }
125
126 pub fn create_method_reference_bootstrap(&mut self, method_ref: u16, method_type: u16) {
128 let arguments = vec![method_type];
130 self.add_bootstrap_method(method_ref, arguments);
131 }
132
133 pub fn add_inner_class(&mut self, inner_class: JvmInnerClass) {
135 self.inner_classes.push(inner_class);
136 }
137
138 pub fn add_inner_classes_attribute(&mut self) {
140 if !self.inner_classes.is_empty() {
141 self.add_attribute(JvmAttribute::InnerClasses { classes: self.inner_classes.clone() });
142 }
143 }
144
145 pub fn set_enclosing_method(&mut self, class_name: String, method_name: Option<String>, method_descriptor: Option<String>) {
147 self.enclosing_method = Some((class_name, method_name, method_descriptor));
148 }
149
150 pub fn add_enclosing_method_attribute(&mut self) {
152 if let Some((class_name, method_name, method_descriptor)) = &self.enclosing_method {
153 self.add_attribute(JvmAttribute::EnclosingMethod {
154 class_name: class_name.clone(),
155 method_name: method_name.clone(),
156 method_descriptor: method_descriptor.clone(),
157 });
158 }
159 }
160}
161
162#[derive(Debug, Clone)]
164pub struct JvmMethod {
165 pub name: String,
167 pub descriptor: String,
169 pub access_flags: JvmAccessFlags,
171 pub instructions: Vec<JvmInstruction>,
173 pub max_stack: u16,
175 pub max_locals: u16,
177 pub exception_handlers: Vec<JvmExceptionHandler>,
179 pub exceptions: Vec<String>,
181 pub attributes: Vec<JvmAttribute>,
183}
184
185impl JvmMethod {
186 pub fn new(name: String, descriptor: String) -> Self {
188 Self {
189 name,
190 descriptor,
191 access_flags: JvmAccessFlags::public(),
192 instructions: Vec::new(),
193 max_stack: 0,
194 max_locals: 0,
195 exception_handlers: Vec::new(),
196 exceptions: Vec::new(),
197 attributes: Vec::new(),
198 }
199 }
200
201 pub fn add_instruction(&mut self, inst: JvmInstruction) {
203 self.instructions.push(inst);
204 }
205
206 pub fn add_exception_handler(&mut self, handler: JvmExceptionHandler) {
208 self.exception_handlers.push(handler);
209 }
210
211 pub fn add_exception(&mut self, exception: String) {
213 self.exceptions.push(exception);
214 }
215
216 pub fn add_attribute(&mut self, attribute: JvmAttribute) {
218 self.attributes.push(attribute);
219 }
220}
221
222#[derive(Debug, Clone)]
224pub struct JvmExceptionHandler {
225 pub start_label: String,
227 pub end_label: String,
229 pub handler_label: String,
231 pub catch_type: Option<String>,
233}