From 61ecbbd304a7dad35e1fd7ce1979aeac027e10fb Mon Sep 17 00:00:00 2001 From: mlokr Date: Sat, 15 Jun 2024 10:37:50 +0200 Subject: [PATCH] putting tests as examples in readme --- hblang/README.md | 308 ++++++++++++++++++ hblang/src/codegen.rs | 56 +++- hblang/src/lexer.rs | 42 --- hblang/src/lib.rs | 3 +- hblang/src/parser.rs | 18 - hblang/src/tests.rs | 9 +- hblang/tests/codegen_tests_example.txt | 3 - ...es.txt => codegen_tests_generic_types.txt} | 0 hblang/tests/lexer_tests_arithmetic.txt | 31 -- hblang/tests/lexer_tests_empty.txt | 1 - hblang/tests/lexer_tests_example.txt | 13 - hblang/tests/lexer_tests_whitespace.txt | 1 - hblang/tests/parser_tests_arithmetic.txt | 3 - hblang/tests/parser_tests_example.txt | 3 - 14 files changed, 358 insertions(+), 133 deletions(-) create mode 100644 hblang/README.md delete mode 100644 hblang/tests/codegen_tests_example.txt rename hblang/tests/{codegen_tests_geneic_types.txt => codegen_tests_generic_types.txt} (100%) delete mode 100644 hblang/tests/lexer_tests_arithmetic.txt delete mode 100644 hblang/tests/lexer_tests_empty.txt delete mode 100644 hblang/tests/lexer_tests_example.txt delete mode 100644 hblang/tests/lexer_tests_whitespace.txt delete mode 100644 hblang/tests/parser_tests_arithmetic.txt delete mode 100644 hblang/tests/parser_tests_example.txt diff --git a/hblang/README.md b/hblang/README.md new file mode 100644 index 0000000..8500faf --- /dev/null +++ b/hblang/README.md @@ -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; +} +``` + diff --git a/hblang/src/codegen.rs b/hblang/src/codegen.rs index b610399..b972441 100644 --- a/hblang/src/codegen.rs +++ b/hblang/src/codegen.rs @@ -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; } } diff --git a/hblang/src/lexer.rs b/hblang/src/lexer.rs index 75c8936..9e531c7 100644 --- a/hblang/src/lexer.rs +++ b/hblang/src/lexer.rs @@ -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"); - } -} diff --git a/hblang/src/lib.rs b/hblang/src/lib.rs index 0abc4db..336915d 100644 --- a/hblang/src/lib.rs +++ b/hblang/src/lib.rs @@ -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); } )*}; } diff --git a/hblang/src/parser.rs b/hblang/src/parser.rs index 09cba22..f5633fe 100644 --- a/hblang/src/parser.rs +++ b/hblang/src/parser.rs @@ -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"); - } -} diff --git a/hblang/src/tests.rs b/hblang/src/tests.rs index 0efafbd..b0b5633 100644 --- a/hblang/src/tests.rs +++ b/hblang/src/tests.rs @@ -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") diff --git a/hblang/tests/codegen_tests_example.txt b/hblang/tests/codegen_tests_example.txt deleted file mode 100644 index b1b92cc..0000000 --- a/hblang/tests/codegen_tests_example.txt +++ /dev/null @@ -1,3 +0,0 @@ -code size: 82 -ret: 1 -status: Ok(()) diff --git a/hblang/tests/codegen_tests_geneic_types.txt b/hblang/tests/codegen_tests_generic_types.txt similarity index 100% rename from hblang/tests/codegen_tests_geneic_types.txt rename to hblang/tests/codegen_tests_generic_types.txt diff --git a/hblang/tests/lexer_tests_arithmetic.txt b/hblang/tests/lexer_tests_arithmetic.txt deleted file mode 100644 index 26de539..0000000 --- a/hblang/tests/lexer_tests_arithmetic.txt +++ /dev/null @@ -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 "" diff --git a/hblang/tests/lexer_tests_empty.txt b/hblang/tests/lexer_tests_empty.txt deleted file mode 100644 index 3f67107..0000000 --- a/hblang/tests/lexer_tests_empty.txt +++ /dev/null @@ -1 +0,0 @@ -Eof "" diff --git a/hblang/tests/lexer_tests_example.txt b/hblang/tests/lexer_tests_example.txt deleted file mode 100644 index 7df9f67..0000000 --- a/hblang/tests/lexer_tests_example.txt +++ /dev/null @@ -1,13 +0,0 @@ -Ident "main" -Decl ":=" -Fn "fn" -LParen "(" -RParen ")" -Colon ":" -Ident "int" -LBrace "{" -Return "return" -Number "1" -Semi ";" -RBrace "}" -Eof "" diff --git a/hblang/tests/lexer_tests_whitespace.txt b/hblang/tests/lexer_tests_whitespace.txt deleted file mode 100644 index 3f67107..0000000 --- a/hblang/tests/lexer_tests_whitespace.txt +++ /dev/null @@ -1 +0,0 @@ -Eof "" diff --git a/hblang/tests/parser_tests_arithmetic.txt b/hblang/tests/parser_tests_arithmetic.txt deleted file mode 100644 index 5a9d1e6..0000000 --- a/hblang/tests/parser_tests_arithmetic.txt +++ /dev/null @@ -1,3 +0,0 @@ -main := fn(): int { - return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + 1; -} diff --git a/hblang/tests/parser_tests_example.txt b/hblang/tests/parser_tests_example.txt deleted file mode 100644 index fa54eb1..0000000 --- a/hblang/tests/parser_tests_example.txt +++ /dev/null @@ -1,3 +0,0 @@ -main := fn(): int { - return 1; -}