Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modules #111

Merged
merged 26 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1d76f96
start work on modules
tertsdiepraam Jan 17, 2025
0818ca4
more modules work because I need to merge some changes in
tertsdiepraam Jan 29, 2025
855bdce
Merge branch 'testing-in-roto-scripts' into modules
tertsdiepraam Jan 29, 2025
b155b61
I feel like making a checkpoint
tertsdiepraam Feb 5, 2025
de25697
fix the full name for constants
tertsdiepraam Feb 5, 2025
ed1ab9c
modules work!
tertsdiepraam Feb 5, 2025
a74d291
implement a custom lexer
tertsdiepraam Feb 6, 2025
c610264
fix up examples from recent changes
tertsdiepraam Feb 6, 2025
9b372fa
modules seem to work!
tertsdiepraam Feb 12, 2025
284e61d
add `super` for module paths
tertsdiepraam Feb 12, 2025
47e4647
absolute paths
tertsdiepraam Feb 12, 2025
5b9c4bb
Merge branch 'main' into modules
tertsdiepraam Feb 12, 2025
eb78961
update some dependencies
tertsdiepraam Feb 12, 2025
cf41f60
lower enum match properly again
tertsdiepraam Feb 12, 2025
97c6bb4
parse import statements
tertsdiepraam Feb 12, 2025
492104f
make import statements functional
tertsdiepraam Feb 13, 2025
7ad0149
start testing imports and make them order independent
tertsdiepraam Feb 13, 2025
8926f74
document the imports checking
tertsdiepraam Feb 13, 2025
e2a3e1c
remove absolute paths, change lib to pkg
tertsdiepraam Feb 14, 2025
5282f29
more import tests
tertsdiepraam Feb 14, 2025
d378f48
type paths in more places and fix returning reference types
tertsdiepraam Feb 14, 2025
5071054
allow type paths in record declarations
tertsdiepraam Feb 14, 2025
b5ddca8
ergonomics improvements for blog post
tertsdiepraam Feb 24, 2025
0d8a9ac
add ipv4 check to addr_range script
tertsdiepraam Feb 25, 2025
f68c93a
address review comments by Arya
tertsdiepraam Feb 27, 2025
2c7ad3c
bump MSRV to 1.81
tertsdiepraam Feb 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ categories.workspace = true
[dependencies]
ariadne = "0.5.0"
clap = { version = "4.4.6", features = ["derive"] }
env_logger = "0.10"
log = "0.4"
logos = "0.14.0"
env_logger = "0.11"
icu = { version = "1.5.0", features = ["compiled_data"] }
inetnum = "0.1.0"
symbol_table = { version = "0.3.0", features = ["global"] }
string-interner = "0.17.0"
roto-macros = { workspace = true, version = "0.4.0" }
log = "0.4"
roto-macros = { workspace = true }
symbol_table = { version = "0.4.0", features = ["global"] }

[dependencies.cranelift]
version = "0.113.0"
Expand All @@ -38,7 +37,7 @@ rev = "1af294ea2d6c18c5a8fa9b4f272398b7c98e0c48"
[dev-dependencies]
bytes = "1"
routecore = { version = "0.5", features = ["bgp", "bmp", "serde"] }
tabled = { version = "0.17.0", default-features = false, features = ["std"] }
tabled = { version = "0.18.0", default-features = false, features = ["std"] }

[profile.profiling]
inherits = "release"
Expand All @@ -64,7 +63,7 @@ categories = ["network-programming"]
readme = "README.md"

[workspace.dependencies]
roto-macros = { path = "macros", version = "0.4.0" }
roto-macros = { path = "macros", version = "0.4.1-dev" }
proc-macro2 = "1.0.86"
quote = "1.0.37"
syn = { version = "2.0.77", features = ["full"] }
7 changes: 7 additions & 0 deletions examples/addr_range.roto
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
filtermap within_range(range: AddrRange, ip: IpAddr) {
if range.contains(ip) && ip.is_ipv4() {
accept ip
} else {
reject
}
}
49 changes: 49 additions & 0 deletions examples/addr_range.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::{net::IpAddr, path::Path};

use roto::{roto_method, FileTree, Runtime, Val, Verdict};

#[derive(Clone)]
struct AddrRange {
min: IpAddr,
max: IpAddr,
}

fn main() {
let path = Path::new("./examples/addr_range.roto");

// Create a runtime
let mut runtime = Runtime::new();

// Register the AddrRange type into Roto with a docstring
runtime
.register_clone_type::<AddrRange>("A range of IP addresses")
.unwrap();

// Register the contains method with a docstring
#[roto_method(runtime, AddrRange)]
fn contains(range: &AddrRange, addr: &IpAddr) -> bool {
range.min <= *addr && *addr <= range.max
}

// Compile the program with our runtime
let mut program = FileTree::read(path).compile(runtime).unwrap();

// Extract the function
let function = program
.get_function::<(), (Val<AddrRange>, IpAddr), Verdict<IpAddr, ()>>(
"within_range",
)
.unwrap();

let range = AddrRange {
min: "10.10.10.10".parse().unwrap(),
max: "10.10.10.12".parse().unwrap(),
};

// Run the function
let in_range = "10.10.10.11".parse().unwrap();
println!("{:?}", function.call(&mut (), Val(range.clone()), in_range));

let out_of_range = "20.20.20.20".parse().unwrap();
println!("{:?}", function.call(&mut (), Val(range), out_of_range));
}
18 changes: 18 additions & 0 deletions examples/modules.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use std::path::Path;

use roto::{FileTree, Runtime};

fn main() -> Result<(), roto::RotoReport> {
env_logger::init();

let runtime = Runtime::new();
let mut compiled = FileTree::directory(Path::new("examples/modules"))
.compile(runtime)
.inspect_err(|e| eprintln!("{e}"))?;

let f = compiled.get_function::<(), (i32,), i32>("main").unwrap();

let x = f.call(&mut (), 4i32);
println!("main(4) = {x}");
Ok(())
}
8 changes: 8 additions & 0 deletions examples/modules/foo.roto
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
function bar(x: i32) -> i32 {
import pkg.double;
let a = super.double(x);
let b = pkg.double(a);
let c = double(b);
c
}

8 changes: 8 additions & 0 deletions examples/modules/pkg.roto
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
function main(x: i32) -> i32 {
import foo.bar;
bar(bar(x))
}

function double(x: i32) -> i32 {
2 * x
}
21 changes: 8 additions & 13 deletions examples/presentation.roto
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
filter-map rib-in-pre(
filtermap rib_in_pre(
output: Log,
route: Route,
) {
define {
my_prefix = 100.40.0.0/17;
}

apply {
if route.prefix_matches(my_prefix) {
output.log_custom(10, 100);
reject
} else {
output.log_prefix(my_prefix);
accept
}
let my_prefix = 100.40.0.0/17;
if route.prefix_matches(my_prefix) {
output.log_custom(10, 100);
reject
} else {
output.log_prefix(my_prefix);
accept
}
}
11 changes: 6 additions & 5 deletions examples/presentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ type Log = *mut OutputStream<Output>;
type Func = TypedFunc<(), (Val<Log>, Val<RotondaRoute>), Verdict<(), ()>>;

fn main() -> Result<(), Box<dyn Error>> {
let mut rt = roto::Runtime::basic()?;
let mut rt = roto::Runtime::new();

// Registering types and their methods

Expand Down Expand Up @@ -122,11 +122,12 @@ fn main() -> Result<(), Box<dyn Error>> {
stream.push(Output::Custom(id, local));
}

let mut compiled = roto::read_files(["examples/presentation.roto"])?
.compile(rt, usize::BITS / 8)
.inspect_err(|e| eprintln!("{e}"))?;
let mut compiled =
roto::FileTree::single_file("examples/presentation.roto")
.compile(rt)
.inspect_err(|e| eprintln!("{e}"))?;

let function = compiled.get_function("rib-in-pre").unwrap();
let function = compiled.get_function("rib_in_pre").unwrap();

run_with_prefix(&function, "8.8.8.0/24")?;
run_with_prefix(&function, "100.40.0.0/17")?;
Expand Down
12 changes: 5 additions & 7 deletions examples/runtime.roto
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
filter-map main(bla: Bla) {
apply {
if bla.x() > 10 {
accept 2 * bla.x()
} else {
reject
}
filtermap main(bla: Bla) {
if bla.x() > 10 {
accept 2 * bla.x()
} else {
reject
}
}
8 changes: 4 additions & 4 deletions examples/runtime.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use roto::{read_files, Runtime, Val, Verdict};
use roto::{FileTree, Runtime, Val, Verdict};
use roto_macros::roto_method;

#[derive(Clone, Copy)]
Expand All @@ -9,7 +9,7 @@ struct Bla {
fn main() -> Result<(), roto::RotoReport> {
env_logger::init();

let mut runtime = Runtime::basic().unwrap();
let mut runtime = Runtime::new();

runtime
.register_copy_type::<Bla>("Some random type")
Expand All @@ -20,8 +20,8 @@ fn main() -> Result<(), roto::RotoReport> {
unsafe { &*bla }.x
}

let mut compiled = read_files(["examples/runtime.roto"])?
.compile(runtime, usize::BITS / 8)
let mut compiled = FileTree::single_file("examples/runtime.roto")
.compile(runtime)
.inspect_err(|e| eprintln!("{e}"))?;

let func = compiled
Expand Down
2 changes: 1 addition & 1 deletion examples/simple.roto
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ function is_zero(x: IpAddr) -> bool {
x == 0.0.0.0
}

filter-map main(x: IpAddr) {
filtermap main(x: IpAddr) {
if is_zero(x) {
accept
} else {
Expand Down
17 changes: 4 additions & 13 deletions examples/simple.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
use std::{env::args, net::IpAddr};

use roto::{read_files, Context, Runtime, Verdict};
use roto::{FileTree, Runtime, Verdict};

fn main() -> Result<(), roto::RotoReport> {
env_logger::init();

let mut runtime = Runtime::basic().unwrap();

// Adding a context is not necessary but done here for testing purposes
#[derive(Context)]
struct Ctx {
/// This is the foo usize
pub foo: u32,
}

runtime.register_context_type::<Ctx>().unwrap();
let runtime = Runtime::new();

let mut arguments = args();
let _program_name = arguments.next().unwrap();
Expand All @@ -25,8 +16,8 @@ fn main() -> Result<(), roto::RotoReport> {
return Ok(());
}

let mut compiled = read_files(["examples/simple.roto"])?
.compile(runtime, usize::BITS / 8)
let mut compiled = FileTree::single_file("examples/simple.roto")
.compile(runtime)
.inspect_err(|e| eprintln!("{e}"))?;

let func = compiled
Expand Down
36 changes: 33 additions & 3 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::ops::Deref;

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Token, Visibility};
Expand Down Expand Up @@ -248,7 +250,6 @@ fn generate_function(item: syn::ItemFn) -> Intermediate {
.collect();

let generics = sig.generics;
let inputs = sig.inputs.clone().into_iter();
let ret = match sig.output {
syn::ReturnType::Default => quote!(()),
syn::ReturnType::Type(_, t) => quote!(#t),
Expand All @@ -266,15 +267,44 @@ fn generate_function(item: syn::ItemFn) -> Intermediate {
})
.collect();

let mut transformed_types = Vec::new();
let mut transformed_args = Vec::new();

for (t, a) in input_types.iter().zip(&args) {
match t.deref() {
syn::Type::Reference(syn::TypeReference {
and_token: _,
lifetime,
mutability,
elem,
}) => {
if lifetime.is_some() {
panic!("lifetime not allowed")
};
if mutability.is_some() {
transformed_types.push(quote!(#a: *mut #elem));
transformed_args.push(quote!(unsafe { &mut *#a }));
} else {
transformed_types.push(quote!(#a: *const #elem));
transformed_args.push(quote!(unsafe { &*#a }));
}
}
_ => {
transformed_types.push(quote!(#a: #t));
transformed_args.push(quote!(#a));
}
}
}

let underscored_types = input_types.iter().map(|_| quote!(_));
let arg_types = quote!(_, #(#underscored_types,)*);

let function = quote! {
#(#attrs)*
#vis extern "C" fn #ident #generics ( out: *mut #ret, #(#inputs,)* ) {
#vis extern "C" fn #ident #generics ( out: *mut #ret, #(#transformed_types,)* ) {
#item

unsafe { std::ptr::write(out, #ident(#(#args),*)) };
unsafe { std::ptr::write(out, #ident(#(#transformed_args),*)) };
}
};

Expand Down
Loading