Amethyst Source Code Analysis


(Benjamin Bäumler) #1

The idea is it to write a tool that parses an amethyst projects for specific things, that output can than be used by other tools. For e.g. we could look for all types that implement System, this can than be used to generate documentation Issue #986 or by the editor to create a main method where the application gets build with specified systems.

There are two ways to implement it. Either as a “rustc drop-in replacement” see this example.
Or with the syn crate that is also used for proc macros.

Advantages of the drop-in approach are probably better type-resolution as it based on rustc, but requires nightly and is probably more likely to break.
Syn works on stable, but here we have only the ast to work with. Which may be enough, but if not would require to re-implement part of the rust compiler.

@torkleyy also mentioned that there where similar plans/ideas regarding scripting support.


(Thomas Schaller) #2

Yes, I’m also gonna leave the link here:

It’s based on the same concept you linked in your comment (stupidstats), and it was an expirement how to make cbindgen better. My idea was to make a general purpose metadata generation library that can be used for

  1. generating respective bindings for other languages scripting and / or registering them with the runtime
  2. generating C / C++ bindings
  3. generating documentation, as you suggested

One potential issue that might come up here is that currently everything can be used as resource, so there’s no type metadata for such a detection. So in that case we’d have to make sure there is some kind of trait impl we can use.


(Benjamin Bäumler) #3

My idea to detect Resources was to check SystemData in Systems. That should be fairly easy. Resources that are only used by states are a bit harder, because there we have to parse the function for world.add_resource etc. but should also be possible. So I don’t think that we need a trait for them.

But we probably want a new trait for Systems or extend the existing one to add some additional meta data, like dependencies on other systems.

trait SystemInfo {
    fn run_before() -> Vec<SystemInfo>;
    fn run_after() -> Vec<SystemInfo>;
}

Or we could integrated it into SystemData, with type likes ReadEarly and ReadLate to indicate that we want to access data before or a after it was modified.

I’m all for a general generation library, would be really cool to generated script bindings by just tagging them.

For now I would try to test both approaches to find Systems in amethyst projects and compare them a bit more. Also I wanted to check out clippy as it has many helper functions to analyze code, so maybe we could reuse them.


(Benjamin Bäumler) #4

I wrote a small prototype using syn. It took some time to get into syn, but it is working now at least rudimentary, because it is only checking the trait name, so it can’t differentiate between std::fmt::Default and std::default::Default.

Code can be found at https://github.com/qqwa/amethyst_parser_syn and here is a gist of the output, checking all files in the amethyst repo.
Needs to be started with cargo run or rustup run, because of the dependency on proc_macro2. So it doesn’t really have an advantage over using a rustc drop-in replacement, maybe runtime…

rustup run nightly amethyst_parser_syn implementor --impls System `find . -not -path "*/examples/*" -not -path "*/tests/*" -type f -name "*.rs"` > system.txt

I will implement it again as a rustc drop-in replacement later to have a better comparison.