added example for struct patters

This commit is contained in:
mlokr 2024-07-08 11:00:35 +02:00
parent ab41d49a3d
commit 25bbe247e9
No known key found for this signature in database
GPG key ID: DEA147DDEE644993
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 #### directives
```hb ```hb
Type := struct { foo := @use("foo.hb");
brah: int,
blah: int,
}
main := fn(): int { main := fn(): int {
byte := @as(u8, 10); byte := @as(u8, 10);
same_type_as_byte := @as(@TypeOf(byte), 30); same_type_as_byte := @as(@TypeOf(byte), 30);
wide_uint := @as(u32, 40); wide_uint := @as(u32, 40);
truncated_uint := @as(u8, @intcast(wide_uint)); truncated_uint := @as(u8, @intcast(wide_uint));
size_of_Type_in_bytes := @sizeof(Type); size_of_Type_in_bytes := @sizeof(foo.Type);
align_of_Type_in_bytes := @alignof(Type); align_of_Type_in_bytes := @alignof(foo.Type);
hardcoded_pointer := @as(^u8, @bitcast(10)); 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; 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 - `@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>` - `@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) - `@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 #### c_strings
```hb ```hb
str_len := fn(str: ^u8): int { str_len := fn(str: ^u8): int {
len := 0; len := 0;
loop if *str == 0 break else { 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 ### Incomplete Examples
#### generic_types #### generic_types

View file

@ -1,3 +1,4 @@
--fmt - format all source files --fmt - format all source files
--fmt-current - format mentioned file --fmt-current - format mentioned file
--fmt-stdout - dont write the formatted file but print it --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 { mod tests {
use { use {
super::parser, super::parser,
crate::{codegen::LoggedMem, log}, crate::{codegen::LoggedMem, log, parser::FileId},
std::io,
}; };
const README: &str = include_str!("../README.md"); const README: &str = include_str!("../README.md");
@ -2872,9 +2873,30 @@ mod tests {
let input = find_block(input, ident); 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 { 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() ..Default::default()
}; };
codegen.generate(); codegen.generate();
@ -2947,5 +2969,6 @@ mod tests {
generic_types => README; generic_types => README;
generic_functions => README; generic_functions => README;
c_strings => README; c_strings => README;
struct_patterns => README;
} }
} }

View file

@ -1,3 +1,5 @@
use std::num::NonZeroUsize;
fn main() -> std::io::Result<()> { fn main() -> std::io::Result<()> {
let args = std::env::args().collect::<Vec<_>>(); let args = std::env::args().collect::<Vec<_>>();
let args = args.iter().map(String::as_str).collect::<Vec<_>>(); let args = args.iter().map(String::as_str).collect::<Vec<_>>();
@ -13,6 +15,12 @@ fn main() -> std::io::Result<()> {
hblang::Options { hblang::Options {
fmt: args.contains(&"--fmt"), fmt: args.contains(&"--fmt"),
fmt_current: args.contains(&"--fmt-current"), 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(), &mut std::io::stdout(),
) )

View file

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

View file

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