This project defines Phoron
, a Jasmin-compatible assembler for the JVM Instruction Set..
For the specification, please refer to the specification document.
For the testable grammar for Phoron
, please refer to the grammar.
For the design, please refer to the Design doc.
``` $ cargo build --release
```
For the sample source file HelloWorld.pho:
``` .class public HelloWorld .super java/lang/Object
.method public
.method public static main([Ljava/lang/String;)V .limit stack 2 getstatic java/lang/System/out Ljava/io/PrintStream; ldc "Hello, world" invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V return .end method ```
We generate the class
file:
$ cargo run --release -- -f samples/HelloWorld.pho
Sanity-check to ensure that the generated class
file is valid:
```
$ javap -v HelloWorld.class
Classfile /Users/z0ltan/dev/oyi-lang/phoronasm/samples/HelloWorld.class
Last modified 19-Mar-2023; size 389 bytes
SHA-256 checksum 533a66c051831cba84a32b20d38c4bb20d68b78aabc137d7c7fb3cc864ff8bf9
Compiled from "./samples/HelloWorld.pho"
public class HelloWorld
minor version: 3
major version: 45
flags: (0x0021) ACCPUBLIC, ACCSUPER
thisclass: #4 // HelloWorld
superclass: #6 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
#1 = Utf8 SourceFile
#2 = Utf8 ./samples/HelloWorld.pho
#3 = Utf8 HelloWorld
#4 = Class #3 // HelloWorld
#5 = Utf8 java/lang/Object
#6 = Class #5 // java/lang/Object
#7 = Utf8
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACCPUBLIC, ACCSTATIC Code: stack=2, locals=1, args_size=1 0: getstatic #19 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #21 // String Hello, world 5: invokevirtual #27 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return } SourceFile: "./samples/HelloWorld.pho" ```
and then we can test it out by running the class
file:
``` $ java -cp . HelloWorld Hello, world
```
The same example, but using the API instead.
``` use std::{ error::Error, fmt, fs, io::BufWriter, path::{Path, PathBuf}, };
use phoronasm::{ codegen::Codegen, cpanalyzer::ConstantPoolAnalyzer, lexer::Lexer, parser::Parser, sourcefile::SourceFile, };
pub struct RunError { message: String, }
impl Error for RunError {}
impl fmt::Display for RunError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.message) } }
fn processfile(srcfile: &PathBuf) -> Result<(), Box
let source_file = SourceFile::new(src_file).map_err(|err| RunError {
message: err.to_string(),
})?;
let mut parser = Parser::new(Lexer::new(&source_file));
let ast = parser.parse().unwrap();
if parser.errored() {
return Err(Box::new(RunError {
message: "errors encountered during parsing and typ-checking".into(),
}));
}
let mut cp_analyzer = ConstantPoolAnalyzer::new();
let cp = cp_analyzer.analyze(&ast).map_err(|err| RunError {
message: err.to_string(),
})?;
let mut outfile_w = BufWriter::new(fs::File::create(&outfile)?);
let mut codegen = Codegen::new(&mut outfile_w);
codegen.gen_bytecode(&ast, &cp).map_err(|err| RunError {
message: err.to_string(),
})?;
Ok(())
}
fn main() { let srcfile = Path::new("./samples/").join("HelloWorld.pho"); match processfile(&srcfile) { Err(err) => eprintln!("{err}"), Ok() => println!("Class file generated"), } }
```
Running it:
``` $ cargo run --release Class file generated
:$ javap -v samples/HelloWorld.class
Classfile /Users/z0ltan/dev/playground/phoronasmdemo/samples/HelloWorld.class
Last modified 19-Mar-2023; size 389 bytes
SHA-256 checksum 533a66c051831cba84a32b20d38c4bb20d68b78aabc137d7c7fb3cc864ff8bf9
Compiled from "./samples/HelloWorld.pho"
public class HelloWorld
minor version: 3
major version: 45
flags: (0x0021) ACCPUBLIC, ACCSUPER
thisclass: #4 // HelloWorld
superclass: #6 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
#1 = Utf8 SourceFile
#2 = Utf8 ./samples/HelloWorld.pho
#3 = Utf8 HelloWorld
#4 = Class #3 // HelloWorld
#5 = Utf8 java/lang/Object
#6 = Class #5 // java/lang/Object
#7 = Utf8
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACCPUBLIC, ACCSTATIC Code: stack=2, locals=1, args_size=1 0: getstatic #19 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #21 // String Hello, world 5: invokevirtual #27 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return } SourceFile: "./samples/HelloWorld.pho"
~/dev/playground/phoronasmdemo:$ java -cp "./samples" HelloWorld Hello, world
```