forked from AbleOS/ableos
putting tests as examples in readme
This commit is contained in:
parent
f4e7cc49c8
commit
36930ebd9b
308
hblang/README.md
Normal file
308
hblang/README.md
Normal 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;
|
||||
}
|
||||
```
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
)*};
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
code size: 82
|
||||
ret: 1
|
||||
status: Ok(())
|
|
@ -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 ""
|
|
@ -1 +0,0 @@
|
|||
Eof ""
|
|
@ -1,13 +0,0 @@
|
|||
Ident "main"
|
||||
Decl ":="
|
||||
Fn "fn"
|
||||
LParen "("
|
||||
RParen ")"
|
||||
Colon ":"
|
||||
Ident "int"
|
||||
LBrace "{"
|
||||
Return "return"
|
||||
Number "1"
|
||||
Semi ";"
|
||||
RBrace "}"
|
||||
Eof ""
|
|
@ -1 +0,0 @@
|
|||
Eof ""
|
|
@ -1,3 +0,0 @@
|
|||
main := fn(): int {
|
||||
return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + 1;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
main := fn(): int {
|
||||
return 1;
|
||||
}
|
Loading…
Reference in a new issue