diff --git a/hblang/README.md b/hblang/README.md index 9a1a5cf..ef71bec 100644 --- a/hblang/README.md +++ b/hblang/README.md @@ -228,24 +228,30 @@ note: values of global variables are evaluated at compile time #### directives ```hb -Type := struct { - brah: int, - blah: int, -} +foo := @use("foo.hb"); main := fn(): int { byte := @as(u8, 10); same_type_as_byte := @as(@TypeOf(byte), 30); wide_uint := @as(u32, 40); truncated_uint := @as(u8, @intcast(wide_uint)); - size_of_Type_in_bytes := @sizeof(Type); - align_of_Type_in_bytes := @alignof(Type); + size_of_Type_in_bytes := @sizeof(foo.Type); + align_of_Type_in_bytes := @alignof(foo.Type); hardcoded_pointer := @as(^u8, @bitcast(10)); - ecall_that_returns_int := @eca(int, 1, Type.(10, 20), 5, 6); + ecall_that_returns_int := @eca(int, 1, foo.Type.(10, 20), 5, 6); return 0; } + +// in module: foo.hb + +Type := struct { + brah: int, + blah: int, +} ``` +- `@use()`: imports a module based of string, the string is passed to a loader that can be customized, default loader uses following syntax: + - `((rel:|)()|git::)`: `rel:` and `''` prefixes both mean module is located at `path` relavive to the current file, `git:` takes a git url without `https://` passed as `git-addr`, `path` then refers to file within the repository - `@TypeOf()`: results into literal type of whatever the type of `` is, `` is not included in final binary - `@as(, )`: hint to the compiler that `@TypeOf() == ` - `@intcast()`: needs to be used when conversion of `@TypeOf()` would loose precision (widening of integers is implicit) @@ -255,7 +261,6 @@ main := fn(): int { #### c_strings ```hb - str_len := fn(str: ^u8): int { len := 0; loop if *str == 0 break else { @@ -275,6 +280,38 @@ main := fn(): int { } ``` +#### struct_patterns +```hb +.{ fib, fib_iter, Fiber } := @use("fibs.hb"); + +main := fn(): int { + .{ a, b } := Fiber.{ a: 10, b: 10 }; + return fib(a) - fib_iter(b); +} + +// in module: fibs.hb + +Fiber := struct { a: u8, b: u8 }; + +fib := fn(n: int): int if n < 2 { + return n; +} else { + return fib(n - 1) + fib(n - 2); +}; + +fib_iter := fn(n: int): int { + a := 0; + b := 1; + loop if n == 0 break else { + c := a + b; + a = b; + b = c; + n -= 1; + } + return a; +} +``` + ### Incomplete Examples #### generic_types diff --git a/hblang/command-help.txt b/hblang/command-help.txt index 9850393..ce9ee5d 100644 --- a/hblang/command-help.txt +++ b/hblang/command-help.txt @@ -1,3 +1,4 @@ --fmt - format all source files --fmt-current - format mentioned file --fmt-stdout - dont write the formatted file but print it +--threads <1...> - number of threads compiler can use [default: 1] diff --git a/hblang/src/codegen.rs b/hblang/src/codegen.rs index b5cb9f9..5eb3795 100644 --- a/hblang/src/codegen.rs +++ b/hblang/src/codegen.rs @@ -2841,7 +2841,8 @@ impl Codegen { mod tests { use { super::parser, - crate::{codegen::LoggedMem, log}, + crate::{codegen::LoggedMem, log, parser::FileId}, + std::io, }; const README: &str = include_str!("../README.md"); @@ -2872,9 +2873,30 @@ mod tests { let input = find_block(input, ident); - let path = "test"; + let mut module_map = Vec::new(); + let mut last_start = 0; + let mut last_module_name = "test"; + for (i, m) in input.match_indices("// in module: ") { + module_map.push((last_module_name, &input[last_start..i])); + let (module_name, _) = input[i + m.len()..].split_once('\n').unwrap(); + last_module_name = module_name; + last_start = i + m.len() + module_name.len() + 1; + } + module_map.push((last_module_name, &input[last_start..])); + + let loader = |path: &str, _: &str| { + module_map + .iter() + .position(|&(name, _)| name == path) + .map(|i| i as FileId) + .ok_or(io::Error::from(io::ErrorKind::NotFound)) + }; + let mut codegen = super::Codegen { - files: vec![parser::Ast::new(path, input, &parser::no_loader)], + files: module_map + .iter() + .map(|&(path, content)| parser::Ast::new(path, content, &loader)) + .collect(), ..Default::default() }; codegen.generate(); @@ -2947,5 +2969,6 @@ mod tests { generic_types => README; generic_functions => README; c_strings => README; + struct_patterns => README; } } diff --git a/hblang/src/main.rs b/hblang/src/main.rs index 593035e..6065f66 100644 --- a/hblang/src/main.rs +++ b/hblang/src/main.rs @@ -1,3 +1,5 @@ +use std::num::NonZeroUsize; + fn main() -> std::io::Result<()> { let args = std::env::args().collect::>(); let args = args.iter().map(String::as_str).collect::>(); @@ -13,6 +15,12 @@ fn main() -> std::io::Result<()> { hblang::Options { fmt: args.contains(&"--fmt"), fmt_current: args.contains(&"--fmt-current"), + extra_threads: args + .iter() + .position(|&a| a == "--threads") + .map(|i| args[i + 1].parse::().expect("--threads expects integer")) + .map_or(1, NonZeroUsize::get) + - 1, }, &mut std::io::stdout(), ) diff --git a/hblang/tests/codegen_tests_directives.txt b/hblang/tests/codegen_tests_directives.txt index 831d048..871c629 100644 --- a/hblang/tests/codegen_tests_directives.txt +++ b/hblang/tests/codegen_tests_directives.txt @@ -1,4 +1,4 @@ ev: Ecall -code size: 235 +code size: 239 ret: 0 status: Ok(()) diff --git a/hblang/tests/codegen_tests_struct_patterns.txt b/hblang/tests/codegen_tests_struct_patterns.txt new file mode 100644 index 0000000..05768a8 --- /dev/null +++ b/hblang/tests/codegen_tests_struct_patterns.txt @@ -0,0 +1,3 @@ +code size: 533 +ret: 0 +status: Ok(())