Skip to content

Commit

Permalink
Thinkin about how to format slices by writing reference implementatio…
Browse files Browse the repository at this point in the history
…n in C and Penne. Revealed bug in slice pointer autoderef.
  • Loading branch information
SLiV9 committed Apr 14, 2024
1 parent 4a0fd20 commit 9bdc9cc
Show file tree
Hide file tree
Showing 11 changed files with 177 additions and 9 deletions.
66 changes: 66 additions & 0 deletions examples/format_slice_implementation.pn
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@

// Of course print_slice needs to be generic over the element type (here i32).
fn print_slice(data: []i32)
{
if |data| == 0
{
print!("[]\n");
goto end;
}

var buf: &&[]char8 = 0x0;
var buflen: usize = 0;
var real: usize = 0;

{
var i: usize = 0;
var writlen: usize = 0;
{
var fmt0 = "[%d\0\0";
var fmt1 = ", %d\0";
var fmt: &[5]char8 = &fmt1;
if i == 0
{
&fmt = &fmt0;
}
var head: &[...]char8 = add_offset(&buf, real * writlen);
var len: usize = buflen - real * writlen;
writlen = writlen + snprintf(&head, len, fmt, data[i]);

if i == |data|
{
goto terminator;
}
loop;
}

terminator:
var head: &[...]char8 = add_offset(&buf, real * writlen);
var len: usize = buflen - real * writlen;
writlen = writlen + snprintf(&head, len, "]\0", 0);

if real > 0
{
goto print;
}

buflen = writlen;
&&buf = alloc(buflen);
real = 1;
loop;
}

print:
print!(buf, "\n");

end:
}

// This is not the correct signature because variadics.
extern fn snprintf(buf: &[]char8, buflen: usize, fmt: []char8, value: i32) -> usize;

// This is not a real function.
fn alloc(len: usize) -> &&[]char8;

// This is not a real function.
extern fn add_offset(buf: &[]char8, offset: usize) -> &[]char8;
1 change: 1 addition & 0 deletions penne.todo
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Functionality:
✔ Cast between pointer types (specifically from &T to &[]u8 and back) @done (2023-08-05 17:40)
✘ And check that the alignment is safe (i.e. no &[3]u8 to &u32) @cancelled (2023-08-06 12:12)
☐ Error if using 0x0 to initialize a view or non-optional pointer
☐ Think about storing a pointer to a view in a variable, then reassigning with a pointer to a different view
✔ Pass array by const-reference (slice) by default @done (2022-09-04 18:06)
☐ A [3]i32 parameter is typechecked as [3]i32 but implemented as []i32
✔ In extern functions, use pointers instead of slice structs @done (2022-09-08 12:09)
Expand Down
4 changes: 4 additions & 0 deletions src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2640,6 +2640,9 @@ fn format_slice(
}
else
{
let slice = argument.generate(llvm)?;
let (slice_ptr, slice_len) =
generate_ptr_and_len_from_slice(slice, llvm)?;
// let n = ?
// for i in 0..n {
//
Expand All @@ -2649,6 +2652,7 @@ fn format_slice(
// TODO call the same llvm IR snippet for multiple Expressions
// TODO my Generator currently doesn't have a nice way to do that
// }
// LLVMBuildArrayAlloca
buffer.add_text("[");
// TODO print elements
// buffer.add_specifier("%.*s");
Expand Down
20 changes: 19 additions & 1 deletion tests/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ fn fail_to_analyze_var_in_naked_branch()
#[test]
fn fail_to_analyze_missing_address()
{
compile_to_fail(&[513, 513], "tests/samples/invalid/missing_address.pn");
compile_to_fail(&[513], "tests/samples/invalid/missing_address.pn");
}

#[test]
Expand All @@ -209,6 +209,24 @@ fn fail_to_analyze_missing_address_get_from_pointer()
);
}

#[test]
fn fail_to_analyze_missing_address_array()
{
compile_to_fail(
&[513, 513, 513, 513, 513, 513],
"tests/samples/invalid/missing_address_array.pn",
);
}

#[test]
fn fail_to_analyze_missing_address_slice_pointer()
{
compile_to_fail(
&[513, 513],
"tests/samples/invalid/missing_address_slice_pointer.pn",
);
}

#[test]
fn fail_to_analyze_missing_address_variable()
{
Expand Down
12 changes: 12 additions & 0 deletions tests/resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ fn allow_explicit_view_constant()
allow_to_compile("tests/samples/valid/explicit_view_constant.pn")
}

#[test]
fn allow_autoderef_edge_cases()
{
allow_to_compile("tests/samples/valid/autoderef_edge_cases.pn")
}

#[test]
fn allow_sketch_of_listen_to_client()
{
Expand All @@ -126,6 +132,12 @@ fn allow_wasm4_header()
allow_to_compile("vendor/wasm4/wasm4.pn")
}

#[test]
fn allow_sketch_of_format_slice_implementation()
{
allow_to_compile("examples/format_slice_implementation.pn")
}

#[test]
fn investigate_nominal_typing()
{
Expand Down
8 changes: 0 additions & 8 deletions tests/samples/invalid/missing_address.pn
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,3 @@ fn main() -> u8
var result = foo(ten);
return: result
}

fn read_into_buffer(buffer: &[]u8);

fn bar()
{
var databuffer: [1024]u8;
read_into_buffer(databuffer);
}
18 changes: 18 additions & 0 deletions tests/samples/invalid/missing_address_array.pn
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
fn foo()
{
var databuffer: [1024]u8;
read_into_buffer(databuffer);
read_into_fixed_buffer(databuffer);
read_into_extern_buffer(databuffer);
}

fn bar(databuffer: &[1024]u8)
{
read_into_buffer(databuffer);
read_into_fixed_buffer(databuffer);
read_into_extern_buffer(databuffer);
}

fn read_into_buffer(buffer: &[]u8);
fn read_into_fixed_buffer(buffer: &[1024]u8);
extern fn read_into_extern_buffer(buffer: &[]u8);
8 changes: 8 additions & 0 deletions tests/samples/invalid/missing_address_slice_pointer.pn
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn use_slice_ptr(data: &[]i32)
{
use_slice_ptr_2(data);
use_ptr_to_endless(data);
}

fn use_slice_ptr_2(data: &[]i32);
extern fn use_ptr_to_endless(data: &[]i32);
15 changes: 15 additions & 0 deletions tests/samples/invalid/pointer_to_coerced.pn
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

fn all_uses_invalid()
{
var five_zeroes: [5]i32 = [0, 0, 0, 0, 0];
var ptr_to_five_zeroes: &[5]i32 = &five_zeroes;
// Invalid because use_ptr_to_ptr_to_endless might assign &[...]i32 to it.
use_ptr_to_ptr_to_endless(&&ptr_to_five_zeroes);

var ptr_to_ptr_to_five_zeroes: &&[5]i32 = &&ptr_to_five_zeroes;
use_ptr_to_ptr_to_endless(&&ptr_to_ptr_to_five_zeroes);
use_ptr_to_ptr_to_ptr_to_endless(&&&ptr_to_ptr_to_five_zeroes);
}

extern fn use_ptr_to_ptr_to_endless(data: &&[]i32);
extern fn use_ptr_to_ptr_to_ptr_to_endless(data: &&&[]i32);
25 changes: 25 additions & 0 deletions tests/samples/valid/autoderef_edge_cases.pn
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

fn all_valid()
{
var five_zeroes: [5]i32 = [0, 0, 0, 0, 0];
use_ptr_to_endless(&five_zeroes);
use_slice_ptr(&five_zeroes);
var ptr_to_five_zeroes: &[5]i32 = &five_zeroes;
use_ptr_to_endless(&ptr_to_five_zeroes);
use_slice_ptr(&ptr_to_five_zeroes);
var ptr_to_ptr_to_five_zeroes: &&[5]i32 = &&ptr_to_five_zeroes;
use_ptr_to_endless(&ptr_to_ptr_to_five_zeroes);
use_slice_ptr(&ptr_to_ptr_to_five_zeroes);
}

fn use_slice_ptr(data: &[]i32)
{
use_slice(data);
use_slice_ptr_2(&data);
use_ptr_to_endless(&data);
}

fn use_slice(data: []i32);
fn use_slice_ptr_2(data: &[]i32);

extern fn use_ptr_to_endless(data: &[]i32);
9 changes: 9 additions & 0 deletions tests/typing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,3 +335,12 @@ fn fail_to_type_size_of_slice()
{
compile_to_fail(&[359], "tests/samples/invalid/size_of_slice.pn")
}

#[test]
fn fail_to_type_pointer_to_coerced()
{
compile_to_fail(
&[512, 512, 512],
"tests/samples/invalid/pointer_to_coerced.pn",
)
}

0 comments on commit 9bdc9cc

Please sign in to comment.