Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Serial-ATA committed Nov 24, 2024
1 parent c002dbb commit 543a726
Show file tree
Hide file tree
Showing 31 changed files with 1,779 additions and 652 deletions.
2 changes: 1 addition & 1 deletion classfile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub use attribute::{
Annotation, Attribute, AttributeTag, AttributeType, BootstrapMethod, Code, CodeException,
ElementValue, ElementValuePair, ElementValueTag, ElementValueType, InnerClass, LineNumber,
LocalVariable, LocalVariableType, MethodParameter, ModuleExport, ModuleOpen, ModuleProvide,
ModuleRequire, RecordComponentInfo, StackMapFrame, VerificationTypeInfo,
ModuleRequire, RecordComponentInfo, StackMapFrame, StackMapTable, VerificationTypeInfo,
};
pub use constant_pool::{ConstantPool, ConstantPoolRef, ConstantPoolTag, ConstantPoolValueInfo};
pub use fieldinfo::{FieldInfo, FieldType};
Expand Down
1 change: 1 addition & 0 deletions generators/native_methods/src/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ fn generate_methods_for_class(class: &Class, definitions_file: &mut File) {
}
}

// TODO: static methods should have a `class` argument
let mut method_call = String::new();
write!(
method_call,
Expand Down
1 change: 0 additions & 1 deletion generators/vm_symbols/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ edition = "2021"
proc-macro = true

[dependencies]
walkdir = "2.3.3"
syn = { version = "2", features = ["full"] }
proc-macro2 = "1"
quote = "1"
100 changes: 74 additions & 26 deletions generators/vm_symbols/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::path::PathBuf;
use std::str::FromStr;
use std::collections::HashSet;
use std::hash::Hash;

use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::quote;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::{Ident, LitStr, Token};
use syn::{Ident, LitStr, LitByteStr, Token};

/// A symbol, as defined in runtime/src/symbols
struct SymbolDefinition {
Expand All @@ -15,9 +18,23 @@ struct SymbolDefinition {
value: Option<LitStr>,
}

impl Hash for SymbolDefinition {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.variant_name.hash(state);
}
}

impl PartialEq for SymbolDefinition {
fn eq(&self, other: &Self) -> bool {
self.variant_name == other.variant_name
}
}

impl Eq for SymbolDefinition {}

impl Parse for SymbolDefinition {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let variant_name = input.parse()?;
let variant_name: Ident = input.parse()?;
let value = match input.parse::<Token![:]>() {
Ok(_) => Some(input.parse()?),
Err(_) => None,
Expand All @@ -30,40 +47,65 @@ impl Parse for SymbolDefinition {
}
}

struct Symbols(Punctuated<SymbolDefinition, Token![,]>);
struct Symbols(HashSet<SymbolDefinition>);

impl Parse for Symbols {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
Ok(Self(Punctuated::parse_terminated(input)?))
let symbols: Punctuated<SymbolDefinition, Token![,]> = Punctuated::parse_terminated(input)?;
Ok(Self(symbols.into_iter().collect()))
}
}

const CRATE_ROOT: &str = env!("CARGO_MANIFEST_DIR");

#[proc_macro]
pub fn define_symbols(mut input: TokenStream) -> TokenStream {
let project_root = PathBuf::from_str(CRATE_ROOT).unwrap();
let generated_dir = project_root
.parent()
.unwrap()
.parent()
.unwrap()
.join("generated");

let symbols_files = walkdir::WalkDir::new(generated_dir)
fn get_generated_dir() -> syn::Result<PathBuf> {
let project_root = PathBuf::from(CRATE_ROOT);
let Some(workspace_root) = project_root.ancestors().nth(2) else {
return Err(syn::Error::new(Span::call_site(), "Failed to find workspace root"));
};

Ok(workspace_root.join("generated").join("native").to_path_buf())
}

fn collect_symbols_from_files(input: &mut TokenStream) -> syn::Result<()> {
let generated_dir = get_generated_dir()?;
if !generated_dir.exists() {
return Err(syn::Error::new(Span::call_site(), format!("Generated directory `{}` does not exist", generated_dir.display())));
}

let entries = match std::fs::read_dir(&generated_dir) {
Ok(entries) => entries,
Err(e) => return Err(syn::Error::new(Span::call_site(), format!("Unable to read symbols from `{}`: {e}", generated_dir.display())))
};

let symbols_files = entries
.into_iter()
.map(Result::unwrap)
.filter(|entry| {
entry.file_type().is_file()
entry.file_type().unwrap().is_file()
&& entry.path().extension().map(std::ffi::OsStr::to_str) == Some(Some("symbols"))
});

for file in symbols_files {
let content = match std::fs::read_to_string(file.path()) {
Ok(content) => content,
Err(e) => return Err(syn::Error::new(Span::call_site(), format!("Unable to read symbols from `{}`: {e}", file.path().display()))),
};

input.extend(TokenStream::from_str(
&std::fs::read_to_string(file.path()).unwrap(),
&content,
))
}

Ok(())
}

#[proc_macro]
pub fn define_symbols(mut input: TokenStream) -> TokenStream {
if let Err(err) = collect_symbols_from_files(&mut input) {
return err.to_compile_error().into();
}

let symbols: Symbols = match syn::parse2(input.into()) {
Ok(input) => input,
Err(e) => {
Expand All @@ -73,23 +115,29 @@ pub fn define_symbols(mut input: TokenStream) -> TokenStream {

let mut index = 0u32;

// TODO: Remove duplicates
// TODO: Sort alphabetically

let mut symbol_value_stream = quote! {};
let mut symbol_const_stream = quote! {};
for symbol in symbols.0 {
let name = &symbol.variant_name;
let value = symbol
.value
.map_or_else(|| name.to_string(), |value| value.value());
let name = symbol.variant_name;
let value_bstr;
let value_str;
match symbol.value {
Some(value) => {
value_str = value.value();
value_bstr = LitByteStr::new(value_str.as_bytes(), value.span());
},
None => {
value_str = name.to_string();
value_bstr = LitByteStr::new(value_str.as_bytes(), name.span())
}
}

symbol_value_stream.extend(quote! {
#value,
&#value_bstr[..],
});

symbol_const_stream.extend(quote! {
#[doc = #value]
#[doc = #value_str]
pub const #name: Symbol = Symbol::new(#index);
});

Expand Down
Loading

0 comments on commit 543a726

Please sign in to comment.