putting tests as examples in readme

This commit is contained in:
mlokr 2024-06-15 10:37:50 +02:00
parent f4e7cc49c8
commit 36930ebd9b
14 changed files with 358 additions and 133 deletions

308
hblang/README.md Normal file
View file

@ -0,0 +1,308 @@
# HERE SHALL THE DOCUMENTATION RESIDE
#### directives
```hb
Type := struct {
brah: int,
blah: int,
}
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);
hardcoded_pointer := @as(^u8, @bitcast(10));
ecall_that_returns_int := @eca(int, 1, Type.(10, 20), 5, 6);
return 0;
}
```
#### if_statements
```hb
main := fn(): int {
return fib(10);
}
fib := fn(x: int): int {
if x <= 2 {
return 1;
} else {
return fib(x - 1) + fib(x - 2);
}
}
```
#### global_variables
```hb
global_var := 10;
complex_global_var := fib(global_var) - 5;
fib := fn(n: int): int {
if 2 > n {
return n;
}
return fib(n - 1) + fib(n - 2);
}
main := fn(): int {
return complex_global_var;
}
```
#### generic_types
```hb
Vec := fn($Elem: type): type {
return struct {
data: ^Elem,
len: uint,
cap: uint,
};
}
main := fn(): int {
i := 69;
vec := Vec(int).{
data: &i,
len: 1,
cap: 1,
};
return *vec.data;
}
```
#### fb_driver
```hb
arm_fb_ptr := fn(): int return 100;
x86_fb_ptr := fn(): int return 100;
check_platform := fn(): int {
return x86_fb_ptr();
}
set_pixel := fn(x: int, y: int, width: int): int {
pix_offset := y * width + x;
return 0;
}
main := fn(): int {
fb_ptr := check_platform();
width := 100;
height := 30;
x:= 0;
y:= 0;
loop {
if x <= height + 1 {
set_pixel(x,y,width);
x = x + 1;
} else {
set_pixel(x,y,width);
x = 0;
y = y + 1;
}
if y == width {
break;
}
}
return 0;
}
```
#### struct_operators
```hb
Point := struct {
x: int,
y: int,
}
Rect := struct {
a: Point,
b: Point,
}
main := fn(): int {
a := Point.(1, 2);
b := Point.(3, 4);
d := Rect.(a + b, b - a);
d2 := Rect.(Point.(0, 0) - b, a);
d2 = d2 + d;
c := d2.a + d2.b;
return c.x + c.y;
}
```
#### main_fn
```hb
main := fn(): int {
return 1;
}
```
#### structs
```hb
Ty := struct {
a: int,
b: int,
}
Ty2 := struct {
ty: Ty,
c: int,
}
main := fn(): int {
finst := Ty2.{ ty: Ty.{ a: 4, b: 1 }, c: 3 };
inst := odher_pass(finst);
if inst.c == 3 {
return pass(&inst.ty);
}
return 0;
}
pass := fn(t: ^Ty): int {
return t.a - t.b;
}
odher_pass := fn(t: Ty2): Ty2 {
return t;
}
```
#### pointers
```hb
main := fn(): int {
a := 1;
b := &a;
modify(b);
drop(a);
stack_reclamation_edge_case := 0;
return *b - 2;
}
modify := fn(a: ^int): void {
*a = 2;
return;
}
drop := fn(a: int): void {
return;
}
```
#### functions
```hb
main := fn(): int {
return add_one(10) + add_two(20);
}
add_two := fn(x: int): int {
return x + 2;
}
add_one := fn(x: int): int {
return x + 1;
}
```
#### variables
```hb
main := fn(): int {
a := 1;
b := 2;
a = a + 1;
return a - b;
}
```
#### loops
```hb
main := fn(): int {
return fib(10);
}
fib := fn(n: int): int {
a := 0;
b := 1;
loop {
if n == 0 {
break;
}
c := a + b;
a = b;
b = c;
n -= 1;
stack_reclamation_edge_case := 0;
continue;
}
return a;
}
```
#### different_types
```hb
Color := struct {
r: u8,
g: u8,
b: u8,
a: u8,
}
Point := struct {
x: u32,
y: u32,
}
Pixel := struct {
color: Color,
point: Point,
}
main := fn(): int {
pixel := Pixel.{
color: Color.{
r: 255,
g: 0,
b: 0,
a: 255,
},
point: Point.{
x: 0,
y: 2,
},
};
if *(&pixel.point.x + 1) != 2 {
return 0;
}
if *(&pixel.point.y - 1) != 0 {
return 64;
}
return pixel.point.x + pixel.point.y + pixel.color.r
+ pixel.color.g + pixel.color.b + pixel.color.a;
}
```
#### arithmetic
```hb
main := fn(): int {
return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + 1;
}
```

View file

@ -2366,7 +2366,34 @@ mod tests {
use super::parser;
fn generate(input: &'static str, output: &mut String) {
const README: &str = include_str!("../README.md");
fn generate(ident: &'static str, input: &'static str, output: &mut String) {
fn find_block(mut input: &'static str, test_name: &'static str) -> &'static str {
const CASE_PREFIX: &str = "#### ";
const CASE_SUFFIX: &str = "\n```hb";
loop {
let Some(pos) = input.find(CASE_PREFIX) else {
unreachable!("test {test_name} not found");
};
input = unsafe { input.get_unchecked(pos + CASE_PREFIX.len()..) };
if !input.starts_with(test_name) {
continue;
}
input = unsafe { input.get_unchecked(test_name.len()..) };
if !input.starts_with(CASE_SUFFIX) {
continue;
}
input = unsafe { input.get_unchecked(CASE_SUFFIX.len()..) };
let end = input.find("```").unwrap_or(input.len());
break unsafe { input.get_unchecked(..end) };
}
}
let input = find_block(input, ident);
let path = "test";
let mut codegen = super::Codegen::default();
codegen.files = vec![parser::Ast::new(path, input, &parser::no_loader)];
@ -2405,19 +2432,18 @@ mod tests {
}
crate::run_tests! { generate:
example => include_str!("../examples/main_fn.hb");
arithmetic => include_str!("../examples/arithmetic.hb");
variables => include_str!("../examples/variables.hb");
functions => include_str!("../examples/functions.hb");
if_statements => include_str!("../examples/if_statement.hb");
loops => include_str!("../examples/loops.hb");
fb_driver => include_str!("../examples/fb_driver.hb");
pointers => include_str!("../examples/pointers.hb");
structs => include_str!("../examples/structs.hb");
different_types => include_str!("../examples/different_types.hb");
struct_operators => include_str!("../examples/struct_operators.hb");
directives => include_str!("../examples/directives.hb");
global_variables => include_str!("../examples/global_variables.hb");
geneic_types => include_str!("../examples/generic_types.hb");
arithmetic => README;
variables => README;
functions => README;
if_statements => README;
loops => README;
fb_driver => README;
pointers => README;
structs => README;
different_types => README;
struct_operators => README;
directives => README;
global_variables => README;
generic_types => README;
}
}

View file

@ -388,45 +388,3 @@ impl LineMap {
}
}
}
#[cfg(test)]
mod tests {
fn map_lines(input: &'static str, _: &mut String) {
let line_map = super::LineMap::new(input);
for i in 0..input.len() {
assert_eq!(
line_map.line_col(i as u32),
//line_map.line_col(i as u32),
super::line_col(input.as_bytes(), i as u32)
);
}
}
crate::run_tests! { map_lines:
empty_file => "";
log_line => " ".repeat(1000).leak();
this_file => &include_str!("parser.rs")[..1000];
}
fn lex(input: &'static str, output: &mut String) {
use {
super::{Lexer, TokenKind as T},
std::fmt::Write,
};
let mut lexer = Lexer::new(input);
loop {
let token = lexer.next();
writeln!(output, "{:?} {:?}", token.kind, &input[token.range()],).unwrap();
if token.kind == T::Eof {
break;
}
}
}
crate::run_tests! { lex:
empty => "";
whitespace => " \t\n\r";
example => include_str!("../examples/main_fn.hb");
arithmetic => include_str!("../examples/arithmetic.hb");
}
}

View file

@ -1,4 +1,5 @@
#![feature(vec_pop_if)]
#![feature(pattern)]
#![feature(if_let_guard)]
#![feature(slice_partition_dedup)]
#![feature(noop_waker)]
@ -26,7 +27,7 @@ macro_rules! run_tests {
($runner:path: $($name:ident => $input:expr;)*) => {$(
#[test]
fn $name() {
$crate::tests::run_test(std::any::type_name_of_val(&$name), $input, $runner);
$crate::tests::run_test(std::any::type_name_of_val(&$name), stringify!($name), $input, $runner);
}
)*};
}

View file

@ -1077,21 +1077,3 @@ impl Drop for ArenaChunk {
}
}
}
#[cfg(test)]
mod tests {
fn parse(input: &'static str, output: &mut String) {
use std::fmt::Write;
let arena = super::Arena::default();
let mut symbols = Vec::new();
let mut parser = super::Parser::new(&arena, &mut symbols, &super::no_loader);
for expr in parser.file(input, "test") {
writeln!(output, "{}", expr).unwrap();
}
}
crate::run_tests! { parse:
example => include_str!("../examples/main_fn.hb");
arithmetic => include_str!("../examples/arithmetic.hb");
}
}

View file

@ -1,6 +1,11 @@
#![cfg(test)]
pub fn run_test(name: &'static str, input: &'static str, test: fn(&'static str, &mut String)) {
pub fn run_test(
name: &'static str,
ident: &'static str,
input: &'static str,
test: fn(&'static str, &'static str, &mut String),
) {
use std::{io::Write, path::PathBuf};
let filter = std::env::var("PT_FILTER").unwrap_or_default();
@ -9,7 +14,7 @@ pub fn run_test(name: &'static str, input: &'static str, test: fn(&'static str,
}
let mut output = String::new();
test(input, &mut output);
test(ident, input, &mut output);
let mut root = PathBuf::from(
std::env::var("PT_TEST_ROOT")

View file

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

View file

@ -1,31 +0,0 @@
Ident "main"
Decl ":="
Fn "fn"
LParen "("
RParen ")"
Colon ":"
Ident "int"
LBrace "{"
Return "return"
Number "10"
Sub "-"
Number "20"
Div "/"
Number "2"
Add "+"
Number "4"
Mul "*"
LParen "("
Number "2"
Add "+"
Number "2"
RParen ")"
Sub "-"
Number "4"
Mul "*"
Number "4"
Add "+"
Number "1"
Semi ";"
RBrace "}"
Eof ""

View file

@ -1 +0,0 @@
Eof ""

View file

@ -1,13 +0,0 @@
Ident "main"
Decl ":="
Fn "fn"
LParen "("
RParen ")"
Colon ":"
Ident "int"
LBrace "{"
Return "return"
Number "1"
Semi ";"
RBrace "}"
Eof ""

View file

@ -1 +0,0 @@
Eof ""

View file

@ -1,3 +0,0 @@
main := fn(): int {
return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + 1;
}

View file

@ -1,3 +0,0 @@
main := fn(): int {
return 1;
}