putting tests as examples in readme
This commit is contained in:
parent
002a7df509
commit
61ecbbd304
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;
|
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 path = "test";
|
||||||
let mut codegen = super::Codegen::default();
|
let mut codegen = super::Codegen::default();
|
||||||
codegen.files = vec![parser::Ast::new(path, input, &parser::no_loader)];
|
codegen.files = vec![parser::Ast::new(path, input, &parser::no_loader)];
|
||||||
|
@ -2405,19 +2432,18 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::run_tests! { generate:
|
crate::run_tests! { generate:
|
||||||
example => include_str!("../examples/main_fn.hb");
|
arithmetic => README;
|
||||||
arithmetic => include_str!("../examples/arithmetic.hb");
|
variables => README;
|
||||||
variables => include_str!("../examples/variables.hb");
|
functions => README;
|
||||||
functions => include_str!("../examples/functions.hb");
|
if_statements => README;
|
||||||
if_statements => include_str!("../examples/if_statement.hb");
|
loops => README;
|
||||||
loops => include_str!("../examples/loops.hb");
|
fb_driver => README;
|
||||||
fb_driver => include_str!("../examples/fb_driver.hb");
|
pointers => README;
|
||||||
pointers => include_str!("../examples/pointers.hb");
|
structs => README;
|
||||||
structs => include_str!("../examples/structs.hb");
|
different_types => README;
|
||||||
different_types => include_str!("../examples/different_types.hb");
|
struct_operators => README;
|
||||||
struct_operators => include_str!("../examples/struct_operators.hb");
|
directives => README;
|
||||||
directives => include_str!("../examples/directives.hb");
|
global_variables => README;
|
||||||
global_variables => include_str!("../examples/global_variables.hb");
|
generic_types => README;
|
||||||
geneic_types => include_str!("../examples/generic_types.hb");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(vec_pop_if)]
|
||||||
|
#![feature(pattern)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(slice_partition_dedup)]
|
#![feature(slice_partition_dedup)]
|
||||||
#![feature(noop_waker)]
|
#![feature(noop_waker)]
|
||||||
|
@ -26,7 +27,7 @@ macro_rules! run_tests {
|
||||||
($runner:path: $($name:ident => $input:expr;)*) => {$(
|
($runner:path: $($name:ident => $input:expr;)*) => {$(
|
||||||
#[test]
|
#[test]
|
||||||
fn $name() {
|
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)]
|
#![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};
|
use std::{io::Write, path::PathBuf};
|
||||||
|
|
||||||
let filter = std::env::var("PT_FILTER").unwrap_or_default();
|
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();
|
let mut output = String::new();
|
||||||
test(input, &mut output);
|
test(ident, input, &mut output);
|
||||||
|
|
||||||
let mut root = PathBuf::from(
|
let mut root = PathBuf::from(
|
||||||
std::env::var("PT_TEST_ROOT")
|
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