added example for struct patters

This commit is contained in:
mlokr 2024-07-08 11:00:35 +02:00
parent f9e7777968
commit 179b78bd07
6 changed files with 84 additions and 12 deletions

View file

@ -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(<string>)`: imports a module based of string, the string is passed to a loader that can be customized, default loader uses following syntax:
- `((rel:|)(<path>)|git:<git-addr>:<path>)`: `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(<expr>)`: results into literal type of whatever the type of `<expr>` is, `<expr>` is not included in final binary
- `@as(<ty>, <expr>)`: hint to the compiler that `@TypeOf(<expr>) == <ty>`
- `@intcast(<expr>)`: needs to be used when conversion of `@TypeOf(<expr>)` 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

View file

@ -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]

View file

@ -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;
}
}

View file

@ -1,3 +1,5 @@
use std::num::NonZeroUsize;
fn main() -> std::io::Result<()> {
let args = std::env::args().collect::<Vec<_>>();
let args = args.iter().map(String::as_str).collect::<Vec<_>>();
@ -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::<NonZeroUsize>().expect("--threads expects integer"))
.map_or(1, NonZeroUsize::get)
- 1,
},
&mut std::io::stdout(),
)

View file

@ -1,4 +1,4 @@
ev: Ecall
code size: 235
code size: 239
ret: 0
status: Ok(())

View file

@ -0,0 +1,3 @@
code size: 533
ret: 0
status: Ok(())