forked from koniifer/ableos
added example for struct patters
This commit is contained in:
parent
f9e7777968
commit
179b78bd07
|
@ -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
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
ev: Ecall
|
ev: Ecall
|
||||||
code size: 235
|
code size: 239
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
3
hblang/tests/codegen_tests_struct_patterns.txt
Normal file
3
hblang/tests/codegen_tests_struct_patterns.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
code size: 533
|
||||||
|
ret: 0
|
||||||
|
status: Ok(())
|
Loading…
Reference in a new issue