Skip to content

Commit

Permalink
Update book to reflect new module path system
Browse files Browse the repository at this point in the history
  • Loading branch information
naalit committed Jan 8, 2024
1 parent 2283908 commit cd168bc
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 16 deletions.
2 changes: 1 addition & 1 deletion guide/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ extern fn bytecodeNum(): i32 = "Clock.getBytecodeNum";

You'll need to use the Battlecode API to do anything useful, and unfortunately this is a little bit harder than in Java, because ByteC isn't smart enough to find and read the API by itself. You'll probably have a file called something like `Common.bt` or `API.bt` shared by all your bots, which has a bunch of `extern` declarations for the entire Battlecode API - an example is at the end of this page. My API bindings were 300 lines of code in 2022, and automatically generating this from the Javadoc isn't too hard; I may write a dedicated script to do this and include it with ByteC at some point.

Also, most functions will probably require `throws GameActionException`. The `throws` clause is actually entirely ignored by ByteC and just passed on to the Java code, but the Java compiler will complain if you leave these out (that does mean you don't need them for inline functions, though).
Also, most functions will probably require `throws GameActionException`. The `throws` clause is actually entirely ignored by ByteC and just passed on to the Java code, but the Java compiler will complain if you leave these out (that does mean you don't need them for inline functions, though). There's also a command-line flag `-T` to add a `throws` clause to every function - for example, `-TGameActionException` - but it's probably best to annotate individual functions.

You'll also need the RobotPlayer class, but this is actually easier than in Java, since every ByteC file ("module") turns into a Java class with static members. Just make sure you have a file called `RobotPlayer.bt`, with something like this:

Expand Down
2 changes: 1 addition & 1 deletion guide/src/language.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Loops are not expressions, and there are about three types:

```rust
// The simplest kind of loop, loops infinitely until a `break`
let a = 0;
let mut a = 0;
loop {
a += 1;
if a > 12 {
Expand Down
32 changes: 28 additions & 4 deletions guide/src/modules.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# Modules

Using multiple source files ("modules") is generally a good idea. In ByteC, the directory that files are in doesn't matter, only the file name.
Circular dependencies are allowed (at least, *almost* all the time).
Items from other files can be accessed with `use` or with `::`, the same as Rust:
Using multiple source files ("modules") is generally a good idea.
Items from other files can be accessed with `::` or with `use` (wildcards `Mod::*` are supported!), the same as Rust:

```rust
// One.bt
Expand All @@ -17,4 +16,29 @@ extern fn println(x: str) = "System.out.println";
fn doStuff() {
println("two: " + (one + one));
}
```
```

Circular dependencies are allowed (at least, *almost* all the time).
Modules can be nested in directories, and module paths are defined relative to the root `bytec` directory that all your source files are in - this lets the compiler search the filesystem for a module when you use it for the first time.
So with the example layout from earlier:
- `bytec`
- `common`
- `Common.bt`
- `Paths.bt`
- `bot_one`
- `RobotPlayer.bt`
- `Soldier.bt`
- `bot_two`
- `RobotPlayer.bt`
- `Miner.bt`

We can use items like so:
```rust
// bot_one/RobotPlayer.bt
use common::Common::RobotController;
use bot_one::Soldier;

fn turn(rc: RobotController) {
Soldier::turn(rc);
}
```
4 changes: 2 additions & 2 deletions guide/src/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ The project structure for a ByteC-based Battlecode bot should look something lik
- ...
- ...

Then, the CLI syntax for `bytec` looks like `bytec source-path1 source-path2... dest-path`, so here it would be:
Then, the CLI syntax for `bytec` looks like `bytec source-path dest-path`, so here it would be (note that files in `bot_one` can still use files in `common`, even though it's not in the command-line arguments):

```
bytec bytec/common bytec/bot_one src/bot_one
bytec bytec/bot_one src/bot_one
```

This is intended to make it easy to test against alternate versions of your bot - simply compile to a certain output package (the names don't need to match, `bytec` will insert the necessary `package` declarations), make a change, and then compile it again to a different output package and run them against each other. The ability to override [constants](./constants.md) from the command line (`-CModule::SOME_CONST=12`, along the lines of C's `-DSOME_CONST=12`) also helps with that, especially with scripts that might test many possible parameters automatically.
Expand Down
13 changes: 6 additions & 7 deletions src/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl Bindings {

pub fn resolve_path_jm(&self, raw: &RawPath) -> String {
let mut s = String::new();
if self.root_mod_path.as_ref() != Some(raw) {
if self.root_mod_path.as_ref() != Some(&raw.stem()) {
for i in &raw.0 {
s.push_str(self.resolve_raw(**i));
s.push_str("$$");
Expand All @@ -186,13 +186,12 @@ impl Bindings {
s
}
pub fn resolve_path_j(&self, raw: &RawPath) -> String {
let mut s = String::new();
for i in &raw.0 {
s.push_str(self.resolve_raw(**i));
s.push_str("$$");
}
let mut s = if raw.len() > 1 {
self.resolve_path_jm(&raw.stem())
} else {
String::new()
};
if raw.len() > 1 {
s.truncate(s.len() - 2);
s.push('.');
}
s.push_str(self.resolve_raw(*raw.1));
Expand Down
2 changes: 1 addition & 1 deletion src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ impl Driver {
self.root.as_ref().unwrap().display()
);
if i == 0 {
bindings.root_mod_path = Some(mod_path.clone());
bindings.root_mod_path = Some(mod_path.stem());
}
self.mods_base.push(ModStatusBase {
pre_items,
Expand Down

0 comments on commit cd168bc

Please sign in to comment.