Rename of files, improved for handling, add cb hints

- Rename Test to Ink as main file
- Support more errors for for loops.
- Add hints to cbs
This commit is contained in:
2025-09-02 11:55:27 +02:00
parent 9e0728f952
commit 603b625e21
10 changed files with 114 additions and 35 deletions

View File

@@ -1,10 +1,14 @@
///////////////////////////////////// /////////////////////////////////////
//~ nbr: General improvements /*~ nbr: General improvements
// - [x] Print out all failed tests in a list at the end
// [x] Print out all failed tests in a list at the end - [x] Use new compiler API with Compile_Result and Compiled_File instead
// [ ] Use new compiler API with Compile_Result and Compiled_File instead - [ ] Use unix (posix? bash? ascii?) color codes for errors
// [ ] Use unix (posix? bash? ascii?) color codes for errors - [ ] Print golden file as green and new output as red
// [ ] Print golden file as green and new output as red - [ ] Rename to Ink.jai
- [ ] Add -test option. -test does the same as test.exe used to do
- [ ] Add -fuzz option to run fuzzer (add args later)
- [ ] Add -output option to output the compiled file. Issue with this is the generated data can't be output like that. Would require serialization.
*/
#import "Basic"; #import "Basic";
#import "File"; #import "File";
@@ -578,8 +582,6 @@ evaluate_result :: (result : Result) {
} }
main :: () { main :: () {
lexer : Lexer;
args := get_command_line_arguments(); args := get_command_line_arguments();
suites : [..]Test_Suite; suites : [..]Test_Suite;
@@ -587,6 +589,7 @@ main :: () {
Argument_Parse_State :: enum { Argument_Parse_State :: enum {
None; None;
Compile;
Run_Suite; Run_Suite;
Run_Test; Run_Test;
} }

View File

@@ -134,6 +134,7 @@ record_error :: (parse_state : *Parse_State, token : Token, message : string, re
source_location.begin.source = source_location.begin.source - source_location.begin.column; source_location.begin.source = source_location.begin.source - source_location.begin.column;
source_location.main_token = token; source_location.main_token = token;
snap := snapshot_state(parse_state);
advance_to_sync_point(parse_state); advance_to_sync_point(parse_state);
error.report_source_location = report_source_location; error.report_source_location = report_source_location;
@@ -142,6 +143,8 @@ record_error :: (parse_state : *Parse_State, token : Token, message : string, re
parse_state.result.had_error = true; parse_state.result.had_error = true;
array_add(*parse_state.result.messages, error); array_add(*parse_state.result.messages, error);
rewind_to_snapshot(parse_state, snap);
} }
generate_source_location_from_token :: (state : *Parse_State, token : Token) -> Source_Range { generate_source_location_from_token :: (state : *Parse_State, token : Token) -> Source_Range {
@@ -241,6 +244,26 @@ else_without_if :: (state : *Parse_State) {
record_error(state, token, final_message, false); record_error(state, token, final_message, false);
} }
unable_to_parse_statement :: (state : *Parse_State, token : Token, message : string = "") {
builder : String_Builder;
init_string_builder(*builder,, temp);
print_to_builder(*builder, "Unable to parse statement here. %\n", message);
location : Source_Range = generate_source_location_from_token(state, token);
indent(*builder, 1);
cyan(*builder);
print_to_builder(*builder, "%\n", print_from_source_location(location));
indent(*builder, 1);
print_token_pointer(*builder, token);
final_message := builder_to_string(*builder);
record_error(state, token, final_message, false);
}
expected_expression :: (state : *Parse_State, token : Token, message : string) { expected_expression :: (state : *Parse_State, token : Token, message : string) {
builder : String_Builder; builder : String_Builder;
init_string_builder(*builder,, temp); init_string_builder(*builder,, temp);
@@ -444,9 +467,9 @@ precedence :: (parse_state : *Parse_State, precedence : Precedence, message : st
tok_s.data = prev.source; tok_s.data = prev.source;
tok_s.count = prev.length; tok_s.count = prev.length;
if message { if message {
expected_expression(parse_state, parse_state.previous, tprint("Expected expression after '%'. %", tok_s, message)); expected_expression(parse_state, prev, tprint("Expected expression after '%'. %", tok_s, message));
} else { } else {
expected_expression(parse_state, parse_state.previous, tprint("Expected expression after '%'.", tok_s)); expected_expression(parse_state, prev, tprint("Expected expression after '%'.", tok_s));
} }
return error_node(parse_state, "Expected expression."); return error_node(parse_state, "Expected expression.");
@@ -859,9 +882,10 @@ statement :: (parse_state : *Parse_State) -> *AST_Node {
source_location : Source_Range; source_location : Source_Range;
source_location.begin = parse_state.previous; source_location.begin = parse_state.previous;
if_cond := expression(parse_state); if_cond := expression(parse_state, "Expected if condition.");
add_child(node, if_cond); add_child(node, if_cond);
source_location.end = parse_state.previous; source_location.end = parse_state.previous;
advance_to_sync_point(parse_state);
if_body := block(parse_state); if_body := block(parse_state);
add_child(node, if_body); add_child(node, if_body);
@@ -903,18 +927,42 @@ statement :: (parse_state : *Parse_State) -> *AST_Node {
advance(parse_state); advance(parse_state);
consume(parse_state, .TOKEN_COLON, "Expect ':' after for loop iterator."); consume(parse_state, .TOKEN_COLON, "Expect ':' after for loop iterator.");
snap := snapshot_state(parse_state);
begin_iter := expression(parse_state, "Expected beginning of iterator."); begin_iter := expression(parse_state, "Expected beginning of iterator.");
if begin_iter.kind == .Error {
unable_to_parse_statement(parse_state, source_location.begin);
rewind_to_snapshot(parse_state, snap);
if parse_state.current.kind == .TOKEN_LEFTBRACE {
block(parse_state);
}
return error_node(parse_state, "'for' without well-formed iterator expression.");
}
add_child(node, begin_iter); add_child(node, begin_iter);
consume(parse_state, .TOKEN_DOTDOT, "Expect '..' after for loop iter left hand side."); consume(parse_state, .TOKEN_DOTDOT, "Expect '..' after for loop iter left hand side.");
end_iter := expression(parse_state, "Expected end of iterator"); snap = snapshot_state(parse_state);
end_iter := expression(parse_state, "Expected end of iterator.");
if end_iter.kind == .Error {
unable_to_parse_statement(parse_state, source_location.begin);
rewind_to_snapshot(parse_state, snap);
if parse_state.current.kind == .TOKEN_LEFTBRACE {
block(parse_state);
}
return error_node(parse_state, "'for' without well-formed iterator expression.");
}
add_child(node, end_iter); add_child(node, end_iter);
if check(parse_state, .TOKEN_LEFTBRACE) {
for_body := block(parse_state); for_body := block(parse_state);
add_child(node, for_body); add_child(node, for_body);
} else {
// consume(parse_state, .TOKEN_RIGHTBRACE, "Expect '}' after for body."); unable_to_parse_statement(parse_state, source_location.begin, "'for' currently expects a brace-enclosed block as a body.");
return error_node(parse_state, "'for' currently expects a brace-enclosed block as a body.");
}
node.source_location = source_location; node.source_location = source_location;

View File

@@ -3,14 +3,14 @@
#import "Compiler"; #import "Compiler";
build :: () { build :: () {
w := compiler_create_workspace("Shader Compiler Test Build"); w := compiler_create_workspace("Ink Build");
if !w { if !w {
print("Workspace creation failed.\n"); print("Workspace creation failed.\n");
return; return;
} }
EXECUTABLE_NAME :: "test"; EXECUTABLE_NAME :: "ink";
MAIN_FILE :: "Test.jai"; MAIN_FILE :: "Ink.jai";
options := get_build_options(w); options := get_build_options(w);

View File

@@ -119,7 +119,8 @@ Constant_Buffer :: struct {
fields : Static_Array(Property_Field, 16); fields : Static_Array(Property_Field, 16);
hint : Field_Hint; // optional hint... // hints : Field_Hint; // optional hint...
hints : [..]Field_Hint;
buffer_index : u32; buffer_index : u32;
} }
@@ -358,7 +359,7 @@ type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope
} }
field_hint.kind = .Target; field_hint.kind = .Target;
} else { } else {
field_hint.custom_hint_name = copy_string(hint.ident_value); field_hint.custom_hint_name = hint.ident_value;
field_hint.kind = .Custom; field_hint.kind = .Custom;
} }
array_add(*field.hints, field_hint); array_add(*field.hints, field_hint);
@@ -414,6 +415,13 @@ generate_output_data :: (result : *Compile_Result) {
} }
cb.buffer_index = variable.resource_index; cb.buffer_index = variable.resource_index;
for hint : variable.source_node.hint_tokens {
field_hint : Field_Hint;
field_hint.custom_hint_name = hint.ident_value;
field_hint.kind = .Custom;
array_add(*cb.hints, field_hint);
}
} }
find_result := find_symbol(*result.scope_stack, result.property_name, xx 1); find_result := find_symbol(*result.scope_stack, result.property_name, xx 1);

View File

@@ -1,6 +1,6 @@
vertex main :: () { vertex main :: () {
x := 0.0; x := 0.0;
for i : { for i : 0.. {
x += 2.0; x += 2.0;
} }
} }

View File

@@ -0,0 +1,6 @@
(program
(fun vertex vs_main
[]
(:= x 0)
(for i : 0..10
(+= x 1))))

View File

@@ -0,0 +1,4 @@
test/for_i_one_liner.ink:3,0: error: Unable to parse statement here. 'for' currently expects a brace-enclosed block as a body.
for i : 0..10 x += 2.0;
^^^


View File

@@ -0,0 +1,9 @@
test/for_no_iter.ink:3,9: error: Expected expression after '..'. Expected end of iterator.
for i : 0.. {
x += 2.0;
^^
test/for_no_iter.ink:3,0: error: Unable to parse statement here.
for i : 0.. {
x += 2.0;
^^^


View File

@@ -1,4 +1,4 @@
test/if_if_if.ink:2,3: error: Expected expression after 'if'. test/if_if_if.ink:2,0: error: Expected expression after 'if'. Expected if condition.
if if if 0 > 100 { if if if 0 > 100 {
^^ ^^
 

View File

@@ -10,6 +10,7 @@ test/field_assignment.ink parse
test/field_without_type_specifier.ink parse test/field_without_type_specifier.ink parse
test/float_if_cond.ink parse test/float_if_cond.ink parse
test/float_suffix.ink parse test/float_suffix.ink parse
test/for_i_loop.ink parse
test/function_call.ink parse test/function_call.ink parse
test/function_call_out_of_order_declaration.ink parse test/function_call_out_of_order_declaration.ink parse
test/function_call_return.ink parse test/function_call_return.ink parse