Skip to content

Commit

Permalink
Multiple classes support
Browse files Browse the repository at this point in the history
  • Loading branch information
hextriclosan committed Sep 4, 2024
1 parent 042e0c2 commit 6b08645
Show file tree
Hide file tree
Showing 18 changed files with 315 additions and 92 deletions.
174 changes: 174 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ edition = "2021"
members = ["jclass", "vm"]

[dependencies]
clap = "4.5.16"
vm = {path = "vm"}

54 changes: 29 additions & 25 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,44 @@
use std::env;
use clap::{arg, Arg, ArgAction, Command};
use std::process;
use vm::vm::VM;

fn print_usage() -> Result<(), String> {
let current_exe = env::current_exe()
.map_err(|err| format!("Failed to get the current executable path: {}", err))?;
let file_name = current_exe
.file_name()
.and_then(|name| name.to_str())
.ok_or_else(|| "Failed to determine the executable name".to_string())?;
println!("Usage: {} <class file>", file_name);
Ok(())
}

fn main() {
let args: Vec<String> = env::args().collect();

if args.len() < 2 {
if let Err(err) = print_usage() {
eprintln!("{}", err);
process::exit(1);
}
process::exit(1);
}

let filename = &args[1];
let matches = Command::new("rusty-jvm")
.arg(
arg!(--"std-dir" <dir>)
.help("Path to Java Standard libraries dir")
.required(true),
)
.arg(
arg!(--"entry-point" <main_class>)
.help("Class to run")
.required(true),
)
.arg(
Arg::new("classes")
.action(ArgAction::Append)
.help("Java classes to load")
.required(true),
)
.get_matches();

let vm = match VM::new(filename, "std") {
let std_dir = matches.get_one::<String>("std-dir").unwrap();
let entry_point = matches.get_one::<String>("entry-point").unwrap();
let classes = matches
.get_many::<String>("classes")
.unwrap()
.into_iter()
.map(|s| s.as_str())
.collect();
let vm = match VM::new(classes, std_dir) {
Ok(vm) => vm,
Err(err) => {
eprintln!("Failed to create VM: {}", err);
process::exit(1);
}
};

let result = match vm.run() {
let result = match vm.run(entry_point) {
Ok(output) => output,
Err(err) => {
eprintln!("VM execution failed: {}", err);
Expand Down
42 changes: 26 additions & 16 deletions tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,75 @@ use vm::vm::VM;

#[test]
fn should_do_adding() {
let vm = VM::new("tests/test_data/Adder.class", "tests/test_data/std").unwrap();
let last_frame_value = vm.run().unwrap();
let vm = VM::new(vec!["tests/test_data/Adder.class"], "tests/test_data/std").unwrap();
let last_frame_value = vm.run("Adder").unwrap();
assert_eq!(55, last_frame_value.unwrap())
}

#[test]
fn should_do_subtraction() {
let vm = VM::new("tests/test_data/Sub.class", "tests/test_data/std").unwrap();
let last_frame_value = vm.run().unwrap();
let vm = VM::new(vec!["tests/test_data/Sub.class"], "tests/test_data/std").unwrap();
let last_frame_value = vm.run("Sub").unwrap();
assert_eq!(-999, last_frame_value.unwrap())
}

#[test]
fn should_write_read_instance_fields() {
let vm = VM::new(
"tests/test_data/InstanceFields.class",
vec![
"tests/test_data/InstanceFieldsUser.class",
"tests/test_data/InstanceFields.class",
],
"tests/test_data/std",
)
.unwrap();
let last_frame_value = vm.run().unwrap();
assert_eq!(11022, last_frame_value.unwrap())
let last_frame_value = vm.run("InstanceFieldsUser").unwrap();
assert_eq!(110022, last_frame_value.unwrap())
}

#[test]
fn should_write_read_static_fields() {
let vm = VM::new("tests/test_data/StaticFields.class", "tests/test_data/std").unwrap();
let last_frame_value = vm.run().unwrap();
assert_eq!(11022, last_frame_value.unwrap())
let vm = VM::new(
vec![
"tests/test_data/StaticFieldsUser.class",
"tests/test_data/StaticFields.class",
],
"tests/test_data/std",
)
.unwrap();
let last_frame_value = vm.run("StaticFieldsUser").unwrap();
assert_eq!(110022, last_frame_value.unwrap())
}

#[test]
fn should_do_extreme_stack_operations() {
let vm = VM::new(
"tests/test_data/ExtremeStackTest.class",
vec!["tests/test_data/ExtremeStackTest.class"],
"tests/test_data/std",
)
.unwrap();
let last_frame_value = vm.run().unwrap();
let last_frame_value = vm.run("ExtremeStackTest").unwrap();
assert_eq!(454, last_frame_value.unwrap())
}

#[test]
fn should_do_calculate_fibonacci_iteratively() {
let vm = VM::new(
"tests/test_data/FibonacciIterative.class",
vec!["tests/test_data/FibonacciIterative.class"],
"tests/test_data/std",
)
.unwrap();
let last_frame_value = vm.run().unwrap();
let last_frame_value = vm.run("FibonacciIterative").unwrap();
assert_eq!(55, last_frame_value.unwrap())
}

#[test]
fn should_do_calculate_fibonacci_recursively() {
let vm = VM::new(
"tests/test_data/FibonacciRecursive.class",
vec!["tests/test_data/FibonacciRecursive.class"],
"tests/test_data/std",
)
.unwrap();
let last_frame_value = vm.run().unwrap();
let last_frame_value = vm.run("FibonacciRecursive").unwrap();
assert_eq!(55, last_frame_value.unwrap())
}
Binary file modified tests/test_data/InstanceFields.class
Binary file not shown.
10 changes: 0 additions & 10 deletions tests/test_data/InstanceFields.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@ public class InstanceFields {
private int resultAdd;
private int resultMul;

public static void main(String[] args) {
int first = 11;
int second = 1000;
InstanceFields instance = new InstanceFields();
instance.sub(first, second);
instance.add(first, second);
instance.mul(first, second);
int result = instance.resultSub + instance.resultAdd + instance.resultMul;
}

public void sub(int first, int second) {
resultSub = first - second;
}
Expand Down
Binary file added tests/test_data/InstanceFieldsUser.class
Binary file not shown.
12 changes: 12 additions & 0 deletions tests/test_data/InstanceFieldsUser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

public class InstanceFieldsUser {
public static void main(String[] args) {
int first = 11;
int second = 10000;
InstanceFields instance = new InstanceFields();
instance.sub(first, second);
instance.add(first, second);
instance.mul(first, second);
int result = instance.getResultSub() + instance.getResultAdd() + instance.getResultMul();
}
}
Binary file modified tests/test_data/StaticFields.class
Binary file not shown.
Loading

0 comments on commit 6b08645

Please sign in to comment.