Skip to main content

jvm_assembler/program/
entities.rs

1use super::{
2    instructions::JvmInstruction,
3    pool::JvmConstantPool,
4    types::{JvmAccessFlags, JvmAttribute, JvmBootstrapMethod, JvmField, JvmInnerClass, JvmVersion},
5};
6
7/// High-level representation of a JVM program
8#[derive(Debug, Clone)]
9pub struct JvmProgram {
10    /// Program name (class name)
11    pub name: String,
12    /// Access flags
13    pub access_flags: JvmAccessFlags,
14    /// Super class name
15    pub super_class: Option<String>,
16    /// List of implemented interfaces
17    pub interfaces: Vec<String>,
18    /// List of fields
19    pub fields: Vec<JvmField>,
20    /// List of methods
21    pub methods: Vec<JvmMethod>,
22    /// List of attributes
23    pub attributes: Vec<JvmAttribute>,
24    /// Constant pool (high-level representation)
25    pub constant_pool: JvmConstantPool,
26    /// Version information
27    pub version: JvmVersion,
28    /// Source file information
29    pub source_file: Option<String>,
30    /// List of inner classes
31    pub inner_classes: Vec<JvmInnerClass>,
32    /// Enclosing method information
33    pub enclosing_method: Option<(String, Option<String>, Option<String>)>, // (class_name, method_name, method_descriptor)
34}
35
36impl JvmProgram {
37    /// Creates a new JVM program with given name
38    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    /// Sets JVM version
56    pub fn set_version(&mut self, major: u16, minor: u16) {
57        self.version = JvmVersion::new(major, minor);
58    }
59
60    /// Sets super class name
61    pub fn set_super_class(&mut self, super_class: String) {
62        self.super_class = Some(super_class);
63    }
64
65    /// Adds an interface to the program
66    pub fn add_interface(&mut self, interface: String) {
67        self.interfaces.push(interface);
68    }
69
70    /// Adds a method to the program
71    pub fn add_method(&mut self, method: JvmMethod) {
72        self.methods.push(method);
73    }
74
75    /// Adds a field to the program
76    pub fn add_field(&mut self, field: JvmField) {
77        self.fields.push(field);
78    }
79
80    /// Adds an attribute to the program
81    pub fn add_attribute(&mut self, attribute: JvmAttribute) {
82        self.attributes.push(attribute);
83    }
84
85    /// Sets source file name and adds SourceFile attribute
86    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    /// Validates the program
92    pub fn validate(&self) -> bool {
93        // Basic validation logic
94        if self.name.is_empty() {
95            return false;
96        }
97        true
98    }
99
100    /// Adds a bootstrap method to the program
101    pub fn add_bootstrap_method(&mut self, method_ref: u16, arguments: Vec<u16>) {
102        // Check if BootstrapMethods attribute already exists
103        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            // Create new BootstrapMethods attribute
109            let bootstrap_method = JvmBootstrapMethod { method_ref, arguments };
110            self.add_attribute(JvmAttribute::BootstrapMethods { methods: vec![bootstrap_method] });
111        }
112    }
113
114    /// Creates a synthetic method for lambda expression
115    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; // Default value, should be calculated properly
122        method.max_locals = 10; // Default value, should be calculated properly
123        method
124    }
125
126    /// Creates a method reference bootstrap method
127    pub fn create_method_reference_bootstrap(&mut self, method_ref: u16, method_type: u16) {
128        // Create bootstrap method for method reference
129        let arguments = vec![method_type];
130        self.add_bootstrap_method(method_ref, arguments);
131    }
132
133    /// Adds an inner class to the program
134    pub fn add_inner_class(&mut self, inner_class: JvmInnerClass) {
135        self.inner_classes.push(inner_class);
136    }
137
138    /// Adds InnerClasses attribute to the program
139    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    /// Sets enclosing method information
146    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    /// Adds EnclosingMethod attribute to the program
151    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/// JVM method information
163#[derive(Debug, Clone)]
164pub struct JvmMethod {
165    /// Method name
166    pub name: String,
167    /// Method descriptor
168    pub descriptor: String,
169    /// Access flags
170    pub access_flags: JvmAccessFlags,
171    /// Method instructions
172    pub instructions: Vec<JvmInstruction>,
173    /// Maximum stack size
174    pub max_stack: u16,
175    /// Maximum local variables
176    pub max_locals: u16,
177    /// Exception handler table
178    pub exception_handlers: Vec<JvmExceptionHandler>,
179    /// Exceptions thrown by the method
180    pub exceptions: Vec<String>,
181    /// Method attributes
182    pub attributes: Vec<JvmAttribute>,
183}
184
185impl JvmMethod {
186    /// Creates a new JVM method
187    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    /// Adds an instruction to the method
202    pub fn add_instruction(&mut self, inst: JvmInstruction) {
203        self.instructions.push(inst);
204    }
205
206    /// Adds an exception handler to the method
207    pub fn add_exception_handler(&mut self, handler: JvmExceptionHandler) {
208        self.exception_handlers.push(handler);
209    }
210
211    /// Adds an exception to the method
212    pub fn add_exception(&mut self, exception: String) {
213        self.exceptions.push(exception);
214    }
215
216    /// Adds an attribute to the method
217    pub fn add_attribute(&mut self, attribute: JvmAttribute) {
218        self.attributes.push(attribute);
219    }
220}
221
222/// JVM exception handler
223#[derive(Debug, Clone)]
224pub struct JvmExceptionHandler {
225    /// Start label
226    pub start_label: String,
227    /// End label
228    pub end_label: String,
229    /// Handler label
230    pub handler_label: String,
231    /// Catch type (class name)
232    pub catch_type: Option<String>,
233}