Compare commits

36 Commits

Author SHA1 Message Date
90fb1a035e Add Properties prefix. Fix semantic check regression. 2024-09-26 16:47:34 +02:00
e365067354 Changed type var children to static array. 2024-09-25 13:01:56 +02:00
243d83663a Simplified shader test output 2024-09-20 13:00:17 +02:00
3f93e1a92d Add double access shader test 2024-09-20 12:48:47 +02:00
fca325b761 Deleted some stuff 2024-09-12 07:18:27 +02:00
d3aa4fffeb Quick fix for binary expr codegen. Add uv hint 2024-09-11 13:21:03 +02:00
6eba51cc8c Fix position output hint. 2024-09-11 12:42:59 +02:00
5b237d34de Merge branch 'dev' of git.nbross.com:nielsbross/Shader-Compiler into dev 2024-09-11 07:25:21 +02:00
ff668b6c95 Fix type checker not promoting ints. Fix some issues in the codegen. 2024-09-11 07:24:50 +02:00
c84516d39f Fix type checker not promoting ints. Fix some issues in the codegen. 2024-09-11 07:24:10 +02:00
517209c886 A bunch of allocator stuff 2024-09-10 07:21:27 +02:00
d01fca146c Opened pandoras box 2024-09-09 22:32:36 +02:00
d9dfcc6354 Beginning of better API 2024-09-02 12:34:48 +02:00
c8cd15456d Update ncore reference 2024-09-02 12:34:40 +02:00
c225217676 NCore update 2024-08-12 07:17:41 +02:00
b2ee560145 Fix build.bat file. 2024-07-18 23:13:01 +02:00
b475357cf9 Fix ncore import 2024-07-17 16:24:33 +02:00
76994b2567 Rename nbrutil to ncore 2024-07-17 16:21:09 +02:00
0471dbe7d7 Add nbrutil to modules. Move static array to nbrutil 2024-07-16 14:31:54 +02:00
c5758bd023 Add array parsing. Missing rest of pipeline. 2024-07-13 11:46:14 +02:00
ae54f1374e Merge branch 'dev' of git.nbross.com:nielsbross/Shader-Compiler into dev 2024-07-02 22:52:06 +02:00
22b70f88b6 Fix builtin parsing 2024-07-02 22:51:55 +02:00
7a07c32cd2 Fix cbuffer pretty printing. 2024-07-01 08:02:10 +02:00
92c1f593c2 Fixes for texture and sampler codegen
- Moved textures and samplers out of property cbuffer for hlsl
- Fixed register indices for resources
2024-07-01 07:58:13 +02:00
274cb379b4 Merge branch 'dev' of git.nbross.com:nielsbross/Shader-Compiler into dev 2024-06-28 08:56:29 +02:00
884444d25b Multiple small fixes
- Foreign functions can now have names for parameters
- Fix property renaming crash
- Properly output texture sampling calls
2024-06-28 08:56:13 +02:00
be4115b502 Added constant buffers 2024-06-27 09:32:25 +00:00
402d9d67a4 Change typenames. Bug in hlsl builtins 2024-06-26 13:49:39 +02:00
1bf829d42f Fix static array. Add constant buffers. Beginning of textures. 2024-06-26 13:42:13 +02:00
3bbbc1d556 Fix function overload resolution. Add static array not working. 2024-06-25 08:54:02 +02:00
d2614b3ba9 Almost fix function overloading. Return var issues. 2024-06-22 17:03:38 +02:00
d5fdaca1ca Fix indexing issue breaking function declarations. 2024-06-22 09:44:15 +02:00
98f979a368 Remove some unused stuff 2024-06-21 15:43:30 +02:00
781f63cd69 Merge branch 'main' into dev
# Conflicts:
#	Semantic_Analysis.jai
2024-06-20 07:01:38 +02:00
1be5072cbe Try some things to figure out why overload resolution is broken. 2024-06-20 07:00:46 +02:00
a9a67e3fac Add lexing, parsing and some semantic checking for constant buffers. 2024-06-14 19:56:28 +02:00
78 changed files with 2700 additions and 1675 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "modules/nbrutil"]
path = modules/ncore
url = git@git.nbross.com:nielsbross/NCore.git

25
AST.jai
View File

@@ -20,6 +20,7 @@ AST_Kind :: enum {
// Operator; // Operator;
Call; Call;
Struct; Struct;
CBuffer;
FieldList; FieldList;
ArgList; ArgList;
Variable; Variable;
@@ -39,7 +40,8 @@ AST_Node :: struct {
// @Note(niels): Children nodes can be interpreted as anything useful. // @Note(niels): Children nodes can be interpreted as anything useful.
// for an if-statement we would have at most 2 children // for an if-statement we would have at most 2 children
// a property block has a child node for each field declaration etc. // a property block has a field list child node which has
// a child node for each field declaration etc.
children : [..]*AST_Node; children : [..]*AST_Node;
parent : *AST_Node; parent : *AST_Node;
@@ -52,7 +54,7 @@ AST_Node :: struct {
token : Token; token : Token;
assignment : bool; array_field : bool;
source_location : Source_Range; source_location : Source_Range;
@@ -105,7 +107,15 @@ pretty_print_field :: (node : *AST_Node, indentation : int, builder : *String_Bu
print_to_builder(builder, tprint("(:= %", node.name)); print_to_builder(builder, tprint("(:= %", node.name));
if node.kind != .Unnamed_Field && node.token.ident_value.count > 0 { if node.kind != .Unnamed_Field && node.token.ident_value.count > 0 {
print_to_builder(builder, tprint(" %", node.token.ident_value)); if node.array_field {
append(builder, " [");
pretty_print_node(node.children[0], 0, builder);
append(builder, "].");
print_to_builder(builder, "%", node.token.ident_value);
} else {
print_to_builder(builder, " %", node.token.ident_value);
}
} }
for hint : node.hint_tokens { for hint : node.hint_tokens {
@@ -114,7 +124,7 @@ pretty_print_field :: (node : *AST_Node, indentation : int, builder : *String_Bu
} }
} }
if node.children.count > 0 { if !node.array_field && node.children.count > 0 {
append(builder, " "); append(builder, " ");
pretty_print_children(node, indentation, builder); pretty_print_children(node, indentation, builder);
} }
@@ -271,10 +281,15 @@ pretty_print_node :: (node : *AST_Node, indentation : int, builder : *String_Bui
pretty_print_variable :: (node : *AST_Node, indentation : int, builder : *String_Builder) { pretty_print_variable :: (node : *AST_Node, indentation : int, builder : *String_Builder) {
indent(builder, indentation); indent(builder, indentation);
print_to_builder(builder, "%", node.name); print_to_builder(builder, "%", node.name);
for child : node.children { for child : node.children {
if child.kind == .Variable { if child.kind == .Variable {
append(builder, "."); append(builder, ".");
pretty_print_variable(child, indentation, builder); pretty_print_variable(child, indentation, builder);
} else if child.kind == .Unary {
append(builder, "[");
pretty_print_node(child.children[0], 0, builder);
append(builder, "]");
} }
} }
} }
@@ -312,6 +327,8 @@ pretty_print_declaration :: (declaration : *AST_Node, indentation : int, builder
else { else {
if declaration.kind == .Struct { if declaration.kind == .Struct {
append(builder, "struct "); append(builder, "struct ");
} else if declaration.kind == .CBuffer {
append(builder, "constant_buffer ");
} }
print_to_builder(builder, "%", declaration.name); print_to_builder(builder, "%", declaration.name);
} }

View File

@@ -1,6 +1,16 @@
/////////////////////////////////////
//~ nbr:
//
/////////////////////////////////////
//~ nbr: Codegen TODOs
//
// [ ] Prefix output of property values with __PROPERTIES so we don't get name clashes
Output_Language :: enum { Output_Language :: enum {
HLSL; HLSL;
GLSL; GLSL; // @Incomplete
MLSL; // @Incomplete
} }
Codegen_State :: struct { Codegen_State :: struct {
@@ -32,6 +42,7 @@ init_codegen_state :: (state : *Codegen_State, root : *AST_Node, checker_result
state.scope_stack = checker_result.scope_stack; state.scope_stack = checker_result.scope_stack;
state.type_variables = checker_result.type_variables; state.type_variables = checker_result.type_variables;
state.current_scope = cast(Scope_Handle)1; state.current_scope = cast(Scope_Handle)1;
state.output_language = output_language;
init_string_builder(*state.builder); init_string_builder(*state.builder);
} }
@@ -39,15 +50,67 @@ indent :: (state : *Codegen_State, indentation : int) {
for 1..indentation append(*state.builder, " "); for 1..indentation append(*state.builder, " ");
} }
dx11_type_to_string :: (type_variable : Type_Variable) -> string {
if type_variable.type == {
case .Invalid;
return "{{invalid}}";
case .Unit;
return "()";
case .Int; {
return "int";
}
case .Half; {
return "half";
}
case .Float; {
return "float";
}
case .Double; {
return "double";
}
case .Sampler; {
return "SamplerState";
}
case .Texture2D; {
return "Texture2D";
}
case .Function; #through;
case .Struct; {
return type_variable.typename;
}
case .Array;
return "array";
}
return "";
}
emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) { emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
find_result := find_symbol(state.scope_stack, node.name, state.current_scope); find_result := find_symbol(state.scope_stack, node.name, state.current_scope);
field := h2tv(state.type_variables, find_result.type_variable); field := h2tv(state.type_variables, find_result.type_variable);
indent(state, indentation); indent(state, indentation);
print_to_builder(*state.builder, "% ", type_to_string(field));
print_to_builder(*state.builder, "% ", dx11_type_to_string(field));
if field.struct_field_parent {
parent_tv := h2tv(state.type_variables, field.struct_field_parent.type_variable);
if parent_tv.typename == "properties" {
append(*state.builder, "__PROPERTIES__");
}
}
print_to_builder(*state.builder, "%", node.name); print_to_builder(*state.builder, "%", node.name);
if field.type == .Sampler {
print_to_builder(*state.builder, " : register(s%)", field.resource_index);
}
if field.type == .Texture2D {
print_to_builder(*state.builder, " : register(t%)", field.resource_index);
}
for i :0..node.children.count - 1 { for i :0..node.children.count - 1 {
child := node.children[i]; child := node.children[i];
@@ -55,7 +118,7 @@ emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
emit_node(state, child, 0); emit_node(state, child, 0);
} }
for i :0..field.child_count - 1 { for i :0..field.children.count - 1 {
child := h2tv(state.type_variables, field.children[i]); child := h2tv(state.type_variables, field.children[i]);
emit_node(state, child.source_node, 0); emit_node(state, child.source_node, 0);
} }
@@ -64,6 +127,10 @@ emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
if hint.ident_value == "position" { if hint.ident_value == "position" {
// @Incomplete(nb): Should be a lookup table somewhere // @Incomplete(nb): Should be a lookup table somewhere
append(*state.builder, " : POSITION"); append(*state.builder, " : POSITION");
} else if hint.ident_value == "uv" {
append(*state.builder, " : TEXCOORD0");
} else if hint.ident_value == "outposition" {
append(*state.builder, " : SV_POSITION");
} }
} }
} }
@@ -80,6 +147,26 @@ emit_block :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
emit_call :: (state : *Codegen_State, node : *AST_Node, indentation : int) { emit_call :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
indent(state, indentation); indent(state, indentation);
if node.name == "sample" {
assert(node.children.count > 0);
args := node.children[0];
emit_node(state, args.children[0], 0);
append(*state.builder, ".");
print_to_builder(*state.builder, "Sample(");
for i : 1..args.children.count - 1 {
child := args.children[i];
emit_node(state, child, 0);
if i != args.children.count - 1 {
append(*state.builder, ", ");
}
}
} else {
print_to_builder(*state.builder, "%(", node.name); print_to_builder(*state.builder, "%(", node.name);
if node.children.count > 0 { if node.children.count > 0 {
@@ -94,6 +181,8 @@ emit_call :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
} }
} }
}
append(*state.builder, ")"); append(*state.builder, ")");
} }
@@ -111,26 +200,40 @@ emit_properties :: (state : *Codegen_State, node : *AST_Node, indentation : int)
variable := h2tv(state.type_variables, find_result.type_variable); variable := h2tv(state.type_variables, find_result.type_variable);
print_to_builder(*state.builder, "cbuffer __PROPERTIES : register(b%) \n{\n", variable.buffer_index); print_to_builder(*state.builder, "cbuffer __PROPERTIES : register(b%) \n{\n", variable.resource_index);
previous_scope := state.current_scope; previous_scope := state.current_scope;
state.current_scope = variable.scope; state.current_scope = variable.scope;
resources : Static_Array(*AST_Node, 8);
for child : node.children { for child : node.children {
if child.kind == .FieldList { if child.kind == .FieldList {
for field : child.children { for field : child.children {
tv := h2tv(state.type_variables, field.type_variable);
if tv.type == .Sampler || tv.type == .Texture2D {
array_add(*resources, field);
continue;
}
emit_node(state, field, 1); emit_node(state, field, 1);
append(*state.builder, ";\n"); append(*state.builder, ";\n");
} }
} }
} }
state.current_scope = previous_scope;
append(*state.builder, "}\n\n"); append(*state.builder, "}\n\n");
for i : 0..resources.count - 1 {
resource := resources[i];
emit_node(state, resource, 0);
append(*state.builder, ";\n");
}
append(*state.builder, "\n");
state.current_scope = previous_scope;
} }
emit_function :: (state : *Codegen_State, node : *AST_Node, indentation : int, emit_body := true) { emit_function :: (state : *Codegen_State, node : *AST_Node, indentation : int, emit_body := true) {
@@ -151,9 +254,9 @@ emit_function :: (state : *Codegen_State, node : *AST_Node, indentation : int, e
indent(state, indentation); indent(state, indentation);
if function_variable.return_var { if function_variable.return_type_variable {
return_variable := h2tv(state.type_variables, function_variable.return_var); return_variable := h2tv(state.type_variables, function_variable.return_type_variable);
print_to_builder(*state.builder, "% ", type_to_string(return_variable)); print_to_builder(*state.builder, "% ", dx11_type_to_string(return_variable));
} else { } else {
append(*state.builder, "void "); append(*state.builder, "void ");
} }
@@ -280,6 +383,13 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
is_properties := type_var.typename == "properties"; is_properties := type_var.typename == "properties";
if !is_properties { if !is_properties {
if type_var.struct_field_parent {
parent_tv := h2tv(state.type_variables, type_var.struct_field_parent.type_variable);
if parent_tv.typename == "properties" {
append(*state.builder, "__PROPERTIES__");
}
}
print_to_builder(*state.builder, "%", node.name); print_to_builder(*state.builder, "%", node.name);
} }
@@ -292,6 +402,11 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
} }
case .Binary; { case .Binary; {
indent(*state.builder, indentation); indent(*state.builder, indentation);
if node.token.kind != .TOKEN_ASSIGN {
append(*state.builder, "(");
}
lhs := node.children[0]; lhs := node.children[0];
rhs := node.children[1]; rhs := node.children[1];
emit_node(state, lhs, 0); emit_node(state, lhs, 0);
@@ -300,6 +415,9 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
emit_operator(state, node.token.kind); emit_operator(state, node.token.kind);
append(*state.builder, " "); append(*state.builder, " ");
emit_node(state, rhs, 0); emit_node(state, rhs, 0);
if node.token.kind != .TOKEN_ASSIGN {
append(*state.builder, ")");
}
} }
case .Unary; { case .Unary; {
assert(false, "Not implemented yet: unary"); assert(false, "Not implemented yet: unary");
@@ -318,15 +436,17 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
} }
} }
emit_declaration :: (state : *Codegen_State, node : *AST_Node) { emit_field_list :: (state : *Codegen_State, field_list : *AST_Node, indentation : int) {
if node.kind == { for child : field_list.children {
case .Function; { emit_node(state, child, 1);
emit_function(state, node, 0);
if it_index < field_list.children.count {
append(*state.builder, ";\n");
} }
case .Properties; {
emit_properties(state, node, 0);
} }
case .Struct; { }
emit_struct :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
print_to_builder(*state.builder, "struct %", node.name); print_to_builder(*state.builder, "struct %", node.name);
current_scope := state.current_scope; current_scope := state.current_scope;
@@ -340,37 +460,66 @@ emit_declaration :: (state : *Codegen_State, node : *AST_Node) {
append(*state.builder, " {"); append(*state.builder, " {");
} }
emit_field_list(state, field_list, indentation);
for child : field_list.children { append(*state.builder, "};\n\n");
emit_node(state, child, 1); state.current_scope = current_scope;
}
if it_index < field_list.children.count { emit_cbuffer :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
append(*state.builder, ";\n"); variable := h2tv(state.type_variables, node.type_variable);
} print_to_builder(*state.builder, "cbuffer % : register(b%)", variable.name, variable.resource_index);
current_scope := state.current_scope;
state.current_scope = h2tv(state.type_variables, node.type_variable).scope;
field_list := node.children[0];
if field_list.children.count > 0 {
append(*state.builder, "\n{\n");
} else {
append(*state.builder, " {");
} }
emit_field_list(state, field_list, indentation);
append(*state.builder, "}\n\n"); append(*state.builder, "}\n\n");
state.current_scope = current_scope; state.current_scope = current_scope;
}
emit_declaration :: (state : *Codegen_State, node : *AST_Node) {
if node.kind == {
case .Function; {
emit_function(state, node, 0);
}
case .Properties; {
emit_properties(state, node, 0);
}
case .CBuffer; {
emit_cbuffer(state, node, 0);
}
case .Struct; {
emit_struct(state, node, 0);
} }
} }
} }
codegen :: (state : *Codegen_State) -> Codegen_Result { codegen :: (state : *Codegen_State) -> Codegen_Result {
found_function : bool = false; found_function : bool = false;
found_struct : bool = false; // found_struct : bool = false;
for variable : state.type_variables { // for variable : state.type_variables {
if variable.type == .Struct && variable.kind == .Declaration && !variable.builtin { // if variable.type == .Struct && variable.kind == .Declaration && !variable.builtin {
if variable.source_node.kind == .Properties continue; // if variable.source_node.kind == .Properties continue;
if variable.source_node.kind == .Meta continue; // if variable.source_node.kind == .Meta continue;
print_to_builder(*state.builder, "struct %;\n", variable.source_node.name); // print_to_builder(*state.builder, "struct %;\n", variable.source_node.name);
found_struct = true; // found_struct = true;
} // }
} // }
if found_struct { // if found_struct {
append(*state.builder, "\n"); // append(*state.builder, "\n");
} // }
for variable : state.type_variables { for variable : state.type_variables {
if variable.type == .Function && !variable.builtin if variable.type == .Function && !variable.builtin
@@ -400,3 +549,6 @@ codegen :: (ast_root : *AST_Node, checker_result : Semantic_Check_Result, output
init_codegen_state(*codegen_state, ast_root, checker_result, output_language); init_codegen_state(*codegen_state, ast_root, checker_result, output_language);
return codegen(*codegen_state); return codegen(*codegen_state);
} }
#scope_module
#import "ncore";

View File

@@ -122,7 +122,10 @@ report_message :: (builder : *String_Builder, path : string, message : string, s
} else { } else {
append(builder, "internal:"); append(builder, "internal:");
} }
if source_locations.count > 0 {
print_to_builder(builder, "%,%: ", source_locations[0].main_token.line, source_locations[0].main_token.column); print_to_builder(builder, "%,%: ", source_locations[0].main_token.line, source_locations[0].main_token.column);
}
if kind == .Log { if kind == .Log {
append(builder, "\x1b[31mlog: "); append(builder, "\x1b[31mlog: ");

View File

@@ -64,6 +64,7 @@ Token_Kind :: enum {
TOKEN_CBUFFER; TOKEN_CBUFFER;
TOKEN_COLUMNMAJOR; TOKEN_COLUMNMAJOR;
TOKEN_CONST; TOKEN_CONST;
TOKEN_CONSTANT_BUFFER;
TOKEN_CONTINUE; TOKEN_CONTINUE;
TOKEN_DEFAULT; TOKEN_DEFAULT;
@@ -129,6 +130,7 @@ Token :: struct {
source : *u8; source : *u8;
// This could all be derived on demand
line : int; line : int;
length : int; length : int;
column : int; column : int;
@@ -218,6 +220,7 @@ identifier_kind :: (using lexer : *Lexer) -> Token_Kind {
if identifier == "case" return .TOKEN_CASE; if identifier == "case" return .TOKEN_CASE;
if identifier == "columnmajor" return .TOKEN_COLUMNMAJOR; if identifier == "columnmajor" return .TOKEN_COLUMNMAJOR;
if identifier == "const" return .TOKEN_CONST; if identifier == "const" return .TOKEN_CONST;
if identifier == "constant_buffer" return .TOKEN_CONSTANT_BUFFER;
if identifier == "continue" return .TOKEN_CONTINUE; if identifier == "continue" return .TOKEN_CONTINUE;
if identifier == "default" return .TOKEN_DEFAULT; if identifier == "default" return .TOKEN_DEFAULT;
if identifier == "directive" return .TOKEN_DIRECTIVE; if identifier == "directive" return .TOKEN_DIRECTIVE;
@@ -496,8 +499,85 @@ scan_next_token :: (lexer : *Lexer) -> *Token {
// return error_token(lexer, tprint("Invalid token: %", s)); // return error_token(lexer, tprint("Invalid token: %", s));
} }
lex :: (result : *Compile_Result) {
if result.had_error {
return;
}
for file : result.files {
lexer : Lexer;
init_lexer_from_string(*lexer, file.file.source);
token : *Token = scan_next_token(*lexer);
while token && token.kind != .TOKEN_EOF {
token = scan_next_token(*lexer);
}
// @Incomplete(nb): Temporary until we figure out a good way of passing this stuff around
copy_messages(lexer.result.messages, *result.messages);
}
}
lex :: (lexer : *Lexer, allocator : Allocator = context.allocator) -> Lexing_Result {
lexer.result.tokens.allocator = allocator;
token : *Token = scan_next_token(lexer);
while token && token.kind != .TOKEN_EOF {
token = scan_next_token(lexer);
}
return lexer.result;
}
init_lexer_from_string :: (lexer : *Lexer, input : string) {
ok := read_input_from_string(lexer, input);
if !ok {
record_error(lexer, "Unable to initialize from string\n");
lexer.result.had_error = true;
}
}
init_lexer_from_file :: (lexer : *Lexer, file_path : string) {
ok := read_input_from_file(lexer, file_path);
if !ok {
record_error(lexer, tprint("Unable to read file: %\n", file_path));
lexer.result.had_error = true;
}
}
read_input_from_string :: (lexer : *Lexer, input : string) -> bool {
lexer.input = input;
lexer.cursor = 0;
lexer.start = 0;
lexer.current_line = 1;
lexer.current_column = 0;
return true;
}
read_input_from_file :: (lexer : *Lexer, file_path : string) -> bool {
assert(file_path != "");
value, success := read_entire_file(file_path, true, true);
if !success {
free(value);
return false;
}
lexer.path = copy_string(file_path);
lexer.input = value;
lexer.cursor = 0;
lexer.start = 0;
lexer.current_line = 1;
lexer.current_column = 0;
return true;
}
// ===========================================================
// Pretty printing
pretty_print_token :: (token : *Token, builder : *String_Builder) { pretty_print_token :: (token : *Token, builder : *String_Builder) {
MAX :: 18; MAX :: 21;
kind_name := enum_names(Token_Kind)[cast(int)token.kind]; kind_name := enum_names(Token_Kind)[cast(int)token.kind];
diff := MAX - kind_name.count; diff := MAX - kind_name.count;
@@ -637,59 +717,6 @@ print_from_source_location :: (source_location : Source_Range, allocator := cont
return builder_to_string(*builder,, allocator); return builder_to_string(*builder,, allocator);
} }
lex :: (lexer : *Lexer, allocator : Allocator = context.allocator) -> Lexing_Result {
lexer.result.tokens.allocator = allocator;
token : *Token = scan_next_token(lexer);
while token && token.kind != .TOKEN_EOF {
token = scan_next_token(lexer);
}
return lexer.result;
}
init_lexer_from_string :: (lexer : *Lexer, input : string) {
ok := read_input_from_string(lexer, input);
if !ok {
record_error(lexer, "Unable to initialize from string\n");
lexer.result.had_error = true;
}
}
init_lexer_from_file :: (lexer : *Lexer, file_path : string) {
ok := read_input_from_file(lexer, file_path);
if !ok {
record_error(lexer, tprint("Unable to read file: %\n", file_path));
lexer.result.had_error = true;
}
}
read_input_from_string :: (lexer : *Lexer, input : string) -> bool {
lexer.input = input;
lexer.cursor = 0;
lexer.start = 0;
lexer.current_line = 1;
lexer.current_column = 0;
return true;
}
read_input_from_file :: (lexer : *Lexer, file_path : string) -> bool {
assert(file_path != "");
value, success := read_entire_file(file_path, true, true);
if !success {
free(value);
return false;
}
lexer.path = copy_string(file_path);
lexer.input = value;
lexer.cursor = 0;
lexer.start = 0;
lexer.current_line = 1;
lexer.current_column = 0;
return true;
}
#import "Basic"; #import "Basic";
#import "File";

View File

@@ -14,7 +14,12 @@ Parse_State :: struct {
tokens : [..]Token; tokens : [..]Token;
current_token_index : int; current_token_index : int;
allocator : Allocator;
node_allocator : Allocator;
node_arena : Arena;
child_allocator : Allocator;
child_arena : Arena;
had_error : bool; had_error : bool;
@@ -84,6 +89,8 @@ parse_rules :: #run -> [(cast(int)Token_Kind.TOKEN_ERROR) + 1]Parse_Rule {
rules[Token_Kind.TOKEN_RIGHTPAREN] = .{null, null, .PREC_NONE}; rules[Token_Kind.TOKEN_RIGHTPAREN] = .{null, null, .PREC_NONE};
rules[Token_Kind.TOKEN_LEFTBRACE] = .{null, null, .PREC_NONE}; rules[Token_Kind.TOKEN_LEFTBRACE] = .{null, null, .PREC_NONE};
rules[Token_Kind.TOKEN_RIGHTBRACE] = .{null, null, .PREC_NONE}; rules[Token_Kind.TOKEN_RIGHTBRACE] = .{null, null, .PREC_NONE};
rules[Token_Kind.TOKEN_LEFTBRACKET] = .{null, array_access, .PREC_CALL};
rules[Token_Kind.TOKEN_RIGHTBRACKET] = .{null, null, .PREC_NONE};
rules[Token_Kind.TOKEN_COMMA] = .{null, null, .PREC_NONE}; rules[Token_Kind.TOKEN_COMMA] = .{null, null, .PREC_NONE};
rules[Token_Kind.TOKEN_DOT] = .{null, dot, .PREC_CALL}; rules[Token_Kind.TOKEN_DOT] = .{null, dot, .PREC_CALL};
rules[Token_Kind.TOKEN_PROPERTIES] = .{named_variable, null, .PREC_CALL}; rules[Token_Kind.TOKEN_PROPERTIES] = .{named_variable, null, .PREC_CALL};
@@ -117,11 +124,12 @@ parse_rules :: #run -> [(cast(int)Token_Kind.TOKEN_ERROR) + 1]Parse_Rule {
return rules; return rules;
} }
init_parse_state :: (parse_state : *Parse_State, tokens : [..]Token, path : string, allocator : Allocator) { init_parse_state :: (parse_state : *Parse_State, tokens : [..]Token, path : string) {
parse_state.tokens = tokens; parse_state.tokens = tokens;
parse_state.path = path; parse_state.path = path;
parse_state.allocator = allocator; parse_state.node_allocator = make_arena(*parse_state.node_arena);
parse_state.result.nodes.allocator = parse_state.allocator; parse_state.child_allocator = make_arena(*parse_state.child_arena);
parse_state.result.nodes.allocator = parse_state.node_allocator;
array_reserve(*parse_state.result.nodes, 4096); array_reserve(*parse_state.result.nodes, 4096);
parse_state.current_token_index = 0; parse_state.current_token_index = 0;
} }
@@ -272,6 +280,7 @@ make_node :: (parse_state : *Parse_State, kind : AST_Kind) -> *AST_Node {
node : AST_Node; node : AST_Node;
node.kind = kind; node.kind = kind;
node.children.allocator = parse_state.child_allocator;
array_add(*parse_state.result.nodes, node); array_add(*parse_state.result.nodes, node);
return *parse_state.result.nodes[parse_state.result.nodes.count - 1]; return *parse_state.result.nodes[parse_state.result.nodes.count - 1];
@@ -313,6 +322,7 @@ advance :: (parse_state : *Parse_State) {
err := tprint("unknown token \x1b[1;37m'%'\x1b[0m", parse_state.current.string_value); err := tprint("unknown token \x1b[1;37m'%'\x1b[0m", parse_state.current.string_value);
unexpected_token(parse_state, parse_state.current, err); unexpected_token(parse_state, parse_state.current, err);
return;
} }
} }
@@ -340,7 +350,9 @@ consume :: (parse_state : *Parse_State, kind : Token_Kind, message : string) {
return; return;
} }
advance(parse_state);
unexpected_token(parse_state, parse_state.current, message); unexpected_token(parse_state, parse_state.current, message);
consume(parse_state, kind, message);
} }
//////////////////////////// ////////////////////////////
@@ -426,6 +438,36 @@ binary :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node {
return binary_expression; return binary_expression;
} }
array_access :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node {
identifier := parse_state.tokens[parse_state.current_token_index - 3];
left_bracket := parse_state.tokens[parse_state.current_token_index - 2];
array_access := make_node(parse_state, .Unary);
array_access.token = left_bracket;
array_index := expression(parse_state);
add_child(array_access, array_index);
add_child(left, array_access);
consume(parse_state, .TOKEN_RIGHTBRACKET, "Expected ']' after array index.");
source_location : Source_Range;
source_location.begin = left.source_location.begin;
if check(parse_state, .TOKEN_ASSIGN) {
advance(parse_state);
node := make_node(parse_state, .Binary);
node.token = parse_state.previous;
add_child(node, left);
add_child(node, expression(parse_state));
return node;
}
source_location.end = parse_state.previous;
return left;
}
unary :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node { unary :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node {
op := parse_state.previous.*; op := parse_state.previous.*;
rule := get_rule(op.kind); rule := get_rule(op.kind);
@@ -438,6 +480,10 @@ unary :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node {
case .TOKEN_MINUS; { case .TOKEN_MINUS; {
unary_expression.token = op; unary_expression.token = op;
} }
case .TOKEN_LEFTBRACKET; {
unary_expression.token = op;
consume(parse_state, .TOKEN_RIGHTBRACKET, "Expect ']' after array access.");
}
} }
return unary_expression; return unary_expression;
@@ -585,6 +631,17 @@ field_declaration :: (parse_state : *Parse_State, identifier_token : *Token) ->
type_identifier := parse_state.current; type_identifier := parse_state.current;
node.token = type_identifier; node.token = type_identifier;
advance(parse_state); advance(parse_state);
} else if check(parse_state, .TOKEN_LEFTBRACKET) {
advance(parse_state);
array_size_expression := expression(parse_state);
add_child(node, array_size_expression);
consume(parse_state, .TOKEN_RIGHTBRACKET, "Expected closing ']' in array declaration.");
consume(parse_state, .TOKEN_DOT, "Expected '.' before array type.");
type_identifier := parse_state.current;
node.token = type_identifier;
advance(parse_state);
node.array_field = true;
} else { } else {
missing_type_specifier(parse_state, identifier_token, "Expected type specifier after field name."); missing_type_specifier(parse_state, identifier_token, "Expected type specifier after field name.");
return node; return node;
@@ -701,6 +758,7 @@ statement :: (parse_state : *Parse_State) -> *AST_Node {
block :: (parse_state : *Parse_State) -> *AST_Node { block :: (parse_state : *Parse_State) -> *AST_Node {
node : *AST_Node = make_node(parse_state, .Block); node : *AST_Node = make_node(parse_state, .Block);
array_reserve(*node.children, 1024);
source_location : Source_Range; source_location : Source_Range;
@@ -731,7 +789,7 @@ field_list :: (parse_state : *Parse_State, separator : Separator_Type, require_f
field : *AST_Node; field : *AST_Node;
identifier := parse_state.current; identifier := parse_state.current;
advance(parse_state); advance(parse_state);
if require_field_names { if require_field_names || check(parse_state, .TOKEN_COLON) {
field = field_declaration(parse_state, identifier); field = field_declaration(parse_state, identifier);
} else { } else {
field = make_node(parse_state, .Unnamed_Field); field = make_node(parse_state, .Unnamed_Field);
@@ -883,6 +941,26 @@ property_block :: (parse_state : *Parse_State, identifier_token : *Token = null)
return node; return node;
} }
constant_buffer :: (parse_state : *Parse_State, identifier_token : *Token = null) -> *AST_Node {
node : *AST_Node;
source_location : Source_Range;
source_location.begin = parse_state.current;
consume(parse_state, .TOKEN_LEFTBRACE, "Expect '{' after 'constant_buffer' keyword");
buffer := field_list(parse_state, .Semicolon);
node = make_node(parse_state, .CBuffer);
if identifier_token {
node.name = identifier_token.ident_value;
}
add_child(node, buffer);
consume(parse_state, .TOKEN_RIGHTBRACE, "Expect '}' after 'constant_buffer' block");
source_location.end = parse_state.previous;
node.source_location = source_location;
return node;
}
struct_declaration :: (parse_state : *Parse_State, identifier_token : *Token) -> *AST_Node { struct_declaration :: (parse_state : *Parse_State, identifier_token : *Token) -> *AST_Node {
source_location := generate_source_location_from_token(parse_state, identifier_token); source_location := generate_source_location_from_token(parse_state, identifier_token);
@@ -914,6 +992,8 @@ const_declaration :: (parse_state : *Parse_State, identifier_token : *Token) ->
return function_declaration(parse_state, identifier_token, .None); return function_declaration(parse_state, identifier_token, .None);
} else if match(parse_state, .TOKEN_PROPERTIES) { } else if match(parse_state, .TOKEN_PROPERTIES) {
return property_block(parse_state, identifier_token); return property_block(parse_state, identifier_token);
} else if match(parse_state, .TOKEN_CONSTANT_BUFFER) {
return constant_buffer(parse_state, identifier_token);
} }
return error_node(parse_state, tprint("Couldn't parse constant declaration at token %\n", parse_state.current.*)); return error_node(parse_state, tprint("Couldn't parse constant declaration at token %\n", parse_state.current.*));
} }
@@ -979,6 +1059,33 @@ declaration :: (parse_state : *Parse_State) -> *AST_Node {
return decl_node; return decl_node;
} }
parse :: (result : *Compile_Result) {
for *file : result.files {
parse_state : Parse_State;
init_parse_state(*parse_state, file.tokens.tokens, file.file.path);
advance(*parse_state);
if !match(*parse_state, .TOKEN_EOF) {
parse_state.result.root = make_node(*parse_state, .Program);
array_reserve(*parse_state.result.root.children, 1024);
program := parse_state.result.root;
while !check(*parse_state, .TOKEN_EOF) {
decl := declaration(*parse_state);
if decl {
add_child(program, decl);
}
}
}
//@Incomplete(nb): will this straight copy just work?
// Might need to rething how we do this.
file.ast_root = parse_state.result.root;
file.ast_nodes = parse_state.result.nodes;
copy_messages(parse_state.result.messages, *result.messages);
}
}
parse :: (parse_state : *Parse_State) -> Parse_Result { parse :: (parse_state : *Parse_State) -> Parse_Result {
advance(parse_state); advance(parse_state);

View File

@@ -49,13 +49,22 @@ properties {
view : float4x4; view : float4x4;
} }
``` ```
which will be exposed in the compiled result. In the future `properties` can be renamed to a custom/shorter name like which will be exposed in the compiled result. `properties` can be renamed to a custom/shorter name like
``` ```
p :: properties { p :: properties {
... ...
} }
``` ```
You can also define constant buffers
```
camera :: Constant_Buffer {
projection : float4x4;
view : float4x4;
}
```
## Jai Usage Example ## Jai Usage Example
To compile a shader and use the result, you can do the following in jai To compile a shader and use the result, you can do the following in jai
@@ -95,6 +104,9 @@ A `Shader_Variant_Collection` looks as follows
Shader_Variant_Collection :: struct { Shader_Variant_Collection :: struct {
properties : Properties; properties : Properties;
max_constant_buffers :: 16;
cbuffers : Static_Array(Constant_Buffer, max_constant_buffers);
variants : [..]Shader_Variant; variants : [..]Shader_Variant;
} }
@@ -114,6 +126,16 @@ Shader_Variant :: struct {
} }
} }
Constant_Buffer :: struct {
register : int;
name : string;
fields : Static_Array(Property_Field, 16);
buffer_index : u32;
}
Properties :: struct { Properties :: struct {
fields : [..]Property_Field; fields : [..]Property_Field;

View File

@@ -5,10 +5,9 @@
///////////////////////////////////// /////////////////////////////////////
//~ nbr: Error reporting TODOs //~ nbr: Error reporting TODOs
// //
// [x] Improve error reporting on mismatched overloads when types don't match, but arity does // [ ] Add and error for using keywords as names, or rename the dx11 keywords in the resulting hlsl shader.
// [ ] Improve error reporting for type mismatches in general. It seems like the expect node is no always correct. // [x] Improve error reporting on mismatched overloads when types don't match, but arity does.
// [x] Improve error reporting for type mismatches in general. It seems like the expect node is not always correct.
#import "Hash_Table";
VERTEX_MAIN_FUNCTION_PREFIX :: "vertex"; VERTEX_MAIN_FUNCTION_PREFIX :: "vertex";
PIXEL_MAIN_FUNCTION_PREFIX :: "pixel"; PIXEL_MAIN_FUNCTION_PREFIX :: "pixel";
@@ -21,8 +20,8 @@ Semantic_Type :: enum {
Half :: 1; Half :: 1;
Float :: 2; Float :: 2;
Double :: 3; Double :: 3;
Texture2D :: 8; Texture2D :: 4;
Sampler :: 9; Sampler :: 5;
Max_Builtin :: Sampler + 1; Max_Builtin :: Sampler + 1;
@@ -34,6 +33,8 @@ Semantic_Type :: enum {
Unresolved_Expression; Unresolved_Expression;
Struct; Struct;
Properties;
CBuffer;
Array; Array;
} }
@@ -47,12 +48,8 @@ Typenames :: string.[
"half" , "half" ,
"float" , "float" ,
"double" , "double" ,
"float2" , "Texture2D",
"float3" , "Sampler" ,
"float4" ,
"float4x4" ,
"sampler" ,
"texture2D",
]; ];
Type_Variable :: struct { Type_Variable :: struct {
@@ -63,22 +60,22 @@ Type_Variable :: struct {
name : string; name : string;
//@Note(niels) For functions //@Note(niels) For functions
return_var : Type_Variable_Handle; return_type_variable : Type_Variable_Handle;
//@Note(niels) The scope this variable creates (function, struct, global) //@Note(niels) The scope this variable creates (function, struct, global)
scope : Scope_Handle; scope : Scope_Handle;
//@Note(niels): For struct members //@Note(niels): For struct members
field_parent : *AST_Node; struct_field_parent : *AST_Node;
typename : string; typename : string;
is_array : bool;
MAX_TYPE_VARIABLE_CHILDREN :: 16; MAX_TYPE_VARIABLE_CHILDREN :: 32;
children : [MAX_TYPE_VARIABLE_CHILDREN]Type_Variable_Handle; children : Static_Array(Type_Variable_Handle, MAX_TYPE_VARIABLE_CHILDREN);
child_count : int;
//@Note(niels): For constant buffers //@Note(niels): For constant buffers
buffer_index : u32; resource_index : u32;
uf_parent : Type_Variable_Handle; uf_parent : Type_Variable_Handle;
@@ -93,7 +90,6 @@ Type_Constraint_Kind :: enum {
Float_Literal; // [[F]] = float Float_Literal; // [[F]] = float
Equivalence; // [[X]] = int/float Equivalence; // [[X]] = int/float
Equality; // E1 == E2: [[E1]] = [[E2]] && [[E1 == E2]] = bool Equality; // E1 == E2: [[E1]] = [[E2]] && [[E1 == E2]] = bool
Boolean_Condition; // while/if (E): [[E]] == bool
Function_Decl; // X(X1, ..., Xn) { return E; }: [[X]] = ([[X1]], ..., [[Xn]]) -> [[E]] Function_Decl; // X(X1, ..., Xn) { return E; }: [[X]] = ([[X1]], ..., [[Xn]]) -> [[E]]
Function_Call; // E(E1, ..., En): [[E]] = ([[E1]], ..., [[En]]) -> [[E(E1, ..., En)]] Function_Call; // E(E1, ..., En): [[E]] = ([[E1]], ..., [[En]]) -> [[E(E1, ..., En)]]
} }
@@ -130,6 +126,7 @@ Type_Constraint :: struct {
Scope_Stack :: struct { Scope_Stack :: struct {
allocator : Allocator; allocator : Allocator;
arena : Arena;
stack : [..]Scope; stack : [..]Scope;
} }
@@ -140,7 +137,7 @@ Defined_Symbol :: struct {
type_variable : Type_Variable_Handle; type_variable : Type_Variable_Handle;
source_node : *AST_Node; source_node : *AST_Node;
functions :[..]Defined_Symbol; functions : [..]Defined_Symbol;
builtin : bool; builtin : bool;
} }
@@ -171,10 +168,21 @@ Scope_Handle :: #type, distinct u32;
Semantic_Check_Result :: struct { Semantic_Check_Result :: struct {
messages : [..]Compiler_Message; messages : [..]Compiler_Message;
message_arena : Arena;
message_allocator : Allocator;
had_error : bool; had_error : bool;
vertex_entry_point : *AST_Node;
pixel_entry_point : *AST_Node;
constant_buffers : Static_Array(Type_Variable_Handle, 16);
scope_stack : Scope_Stack; scope_stack : Scope_Stack;
type_variables : [..]Type_Variable; type_variables : [..]Type_Variable;
type_var_arena : Arena;
type_var_allocator : Allocator;
property_name : string;
} }
Checker_State :: enum { Checker_State :: enum {
@@ -190,12 +198,13 @@ Semantic_Checker :: struct {
current_scope : Scope_Handle; current_scope : Scope_Handle;
vertex_entry_point : *AST_Node;
pixel_entry_point : *AST_Node;
// type_variables : [..]Type_Variable; // type_variables : [..]Type_Variable;
constraints : [..]Type_Constraint; constraints : [..]Type_Constraint;
current_buffer_index : u32 = 0;
current_sampler_index : u32 = 0;
current_texture_index : u32 = 0;
result : Semantic_Check_Result; result : Semantic_Check_Result;
} }
@@ -287,9 +296,6 @@ Use of undeclard symbol '%'.
record_error(checker, message, node.source_location, false); record_error(checker, message, node.source_location, false);
} }
foo :: (i : int, p : int) {}
foo :: (i : int, p : int, t : int) {}
no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, overloads : *Defined_Symbol, arg_node : *AST_Node = null) { no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, overloads : *Defined_Symbol, arg_node : *AST_Node = null) {
builder : String_Builder; builder : String_Builder;
init_string_builder(*builder,, temp); init_string_builder(*builder,, temp);
@@ -342,6 +348,8 @@ no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, ov
// foo :: (f : float) {} (file_path:line_num) // foo :: (f : float) {} (file_path:line_num)
func_location := func_var.source_node.source_location; func_location := func_var.source_node.source_location;
indent(*builder, 2); indent(*builder, 2);
// @Incomplete(niels): We need a way to properly save the path of the declaration
print_to_builder(*builder, "% (%:%)\n", print_from_source_location(func_location), checker.path, print_to_builder(*builder, "% (%:%)\n", print_from_source_location(func_location), checker.path,
func_location.main_token.line); func_location.main_token.line);
@@ -353,10 +361,9 @@ no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, ov
func_var := h2tv(checker, func.type_variable); func_var := h2tv(checker, func.type_variable);
if arg_list.children.count != func_var.child_count { if arg_list.children.count != func_var.children.count {
print_to_builder(*builder, "Not enough arguments: Wanted %, got %.\n\n", func_var.child_count, arg_list.children.count); print_to_builder(*builder, "Not enough arguments: Wanted %, got %.\n\n", func_var.children.count, arg_list.children.count);
} }
} }
} }
@@ -535,7 +542,7 @@ type_mismatch :: (checker : *Semantic_Checker, usage_site : *AST_Node, expect_no
if got_var.builtin { if got_var.builtin {
print_to_builder(*builder, "% :: (", got_var.name); print_to_builder(*builder, "% :: (", got_var.name);
for i: 0..got_var.child_count - 1{ for i: 0..got_var.children.count - 1{
child_handle := got_var.children[i]; child_handle := got_var.children[i];
child := h2tv(checker, child_handle); child := h2tv(checker, child_handle);
@@ -576,7 +583,8 @@ type_mismatch :: (checker : *Semantic_Checker, usage_site : *AST_Node, expect_no
print_to_builder(*builder, "got:\n"); print_to_builder(*builder, "got:\n");
indent(*builder, 2); indent(*builder, 2);
print_to_builder(*builder, "%\n", print_from_source_location(got_var.source_node.parent.source_location));
print_to_builder(*builder, "%\n", print_from_source_location(got_var.source_node.source_location));
message := builder_to_string(*builder); message := builder_to_string(*builder);
@@ -632,6 +640,8 @@ push_scope :: (checker : *Semantic_Checker, name := "", kind : Scope_Kind = .Glo
scope.builtin = true; scope.builtin = true;
} }
scope.children.allocator = checker.result.scope_stack.allocator;
if checker.current_scope { if checker.current_scope {
scope := get_current_scope(checker); scope := get_current_scope(checker);
array_add(*scope.children, xx count); array_add(*scope.children, xx count);
@@ -704,24 +714,28 @@ new_type_variable :: (checker : *Semantic_Checker) -> *Type_Variable, Type_Varia
return h2tv(checker, handle), handle; return h2tv(checker, handle), handle;
} }
add_child :: (variable : *Type_Variable, child : Type_Variable_Handle) { add_child :: (variable : *Type_Variable, child : Type_Variable_Handle) {
assert(variable.child_count < Type_Variable.MAX_TYPE_VARIABLE_CHILDREN); assert(variable.children.count < Type_Variable.MAX_TYPE_VARIABLE_CHILDREN);
variable.children[variable.child_count] = child; array_add(*variable.children, child);
variable.child_count += 1; // variable.children[variable.children.count] = child;
// variable.children.count += 1;
} }
add_child :: (checker : *Semantic_Checker, handle : Type_Variable_Handle, child : Type_Variable_Handle) { add_child :: (checker : *Semantic_Checker, handle : Type_Variable_Handle, child : Type_Variable_Handle) {
variable := h2tv(checker, handle); variable := h2tv(checker, handle);
assert(variable.child_count < Type_Variable.MAX_TYPE_VARIABLE_CHILDREN); assert(variable.children.count < Type_Variable.MAX_TYPE_VARIABLE_CHILDREN);
variable.children[variable.child_count] = child; array_add(*variable.children, child);
variable.child_count += 1;
} }
init_semantic_checker :: (checker : *Semantic_Checker, root : *AST_Node, path : string) { init_semantic_checker :: (checker : *Semantic_Checker, root : *AST_Node, path : string) {
checker.program_root = root; checker.program_root = root;
checker.path = path; checker.path = path;
// @Incomplete(niels): Use other allocator and/or add static array with convenience functions
checker.result.type_var_allocator = make_arena(*checker.result.type_var_arena);
array_reserve(*checker.result.type_variables, 2048); array_reserve(*checker.result.type_variables, 2048);
checker.result.scope_stack.allocator = make_arena(*checker.result.scope_stack.arena);
array_reserve(*checker.result.scope_stack.stack, 256); array_reserve(*checker.result.scope_stack.stack, 256);
global_scope, global_handle := push_scope(checker, kind = .Global); global_scope, global_handle := push_scope(checker, kind = .Global);
@@ -794,14 +808,14 @@ proper_type_to_string :: (builder : *String_Builder, checker : *Semantic_Checker
append(builder, ")"); append(builder, ")");
if var.return_var > 0 { if var.return_type_variable > 0 {
append(builder, " -> ", ); append(builder, " -> ", );
return_var := h2tv(checker, var.return_var); return_var := h2tv(checker, var.return_type_variable);
if is_proper(return_var) { if is_proper(return_var) {
proper_type_to_string(builder, checker, return_var); proper_type_to_string(builder, checker, return_var);
} else { } else {
append(builder, "[["); append(builder, "[[");
print_type_variable(builder, checker, var.return_var); print_type_variable(builder, checker, var.return_type_variable);
append(builder, "]]", ); append(builder, "]]", );
} }
} else { } else {
@@ -829,6 +843,9 @@ proper_type_to_string :: (checker : *Semantic_Checker, var : Type_Variable, allo
proper_type_to_string(*builder, checker, var); proper_type_to_string(*builder, checker, var);
return builder_to_string(*builder,, allocator); return builder_to_string(*builder,, allocator);
} }
case .Struct; {
return var.typename;
}
} }
return "______not proper type______"; return "______not proper type______";
@@ -838,10 +855,14 @@ proper_type_to_string :: (checker : *Semantic_Checker, var : Type_Variable, allo
get_type_from_identifier :: (checker : *Semantic_Checker, scope : Scope_Handle, node : *AST_Node, typename : *string = null) -> Semantic_Type { get_type_from_identifier :: (checker : *Semantic_Checker, scope : Scope_Handle, node : *AST_Node, typename : *string = null) -> Semantic_Type {
type_string := node.token.ident_value; type_string := node.token.ident_value;
if type_string == Typenames[Semantic_Type.Int] return .Int; if type_string == {
if type_string == Typenames[Semantic_Type.Half] return .Half; case Typenames[Semantic_Type.Int]; return .Int;
if type_string == Typenames[Semantic_Type.Float] return .Float; case Typenames[Semantic_Type.Half]; return .Half;
if type_string == Typenames[Semantic_Type.Double] return .Double; case Typenames[Semantic_Type.Float]; return .Float;
case Typenames[Semantic_Type.Double]; return .Double;
case Typenames[Semantic_Type.Sampler]; return .Sampler;
case Typenames[Semantic_Type.Texture2D]; return .Texture2D;
}
symbol := find_symbol(checker, type_string, scope); symbol := find_symbol(checker, type_string, scope);
if symbol { if symbol {
@@ -898,9 +919,9 @@ declare_struct :: (checker : *Semantic_Checker, node : *AST_Node, name : string)
if child.kind == .FieldList { if child.kind == .FieldList {
for field : child.children { for field : child.children {
type_var := check_node(checker, field); type_var := check_node(checker, field);
h2tv(checker, type_var).scope = scope_handle;
if type_var > 0 { if type_var > 0 {
h2tv(checker, type_var).scope = scope_handle;
add_child(checker, handle, type_var); add_child(checker, handle, type_var);
} }
} }
@@ -918,19 +939,26 @@ declare_struct :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variab
declare_properties :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle { declare_properties :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle {
name := ifx node.name.count == 0 then "properties" else node.name; name := ifx node.name.count == 0 then "properties" else node.name;
if node.name.count > 0 {
checker.result.property_name = name;
}
type_var := declare_struct(checker, node, name); type_var := declare_struct(checker, node, name);
var := h2tv(checker, type_var); var := h2tv(checker, type_var);
var.type = .Properties;
var.typename = "properties"; var.typename = "properties";
var.buffer_index = 0; var.resource_index = checker.current_buffer_index;
checker.current_buffer_index += 1;
return type_var; return type_var;
} }
declare_meta :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle { declare_cbuffer :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle {
name := ifx node.name.count == 0 then "meta" else node.name; type_var := declare_struct(checker, node);
type_var := declare_struct(checker, node, name);
var := h2tv(checker, type_var); var := h2tv(checker, type_var);
var.typename = name; var.type = .CBuffer;
var.buffer_index = 0; var.resource_index = checker.current_buffer_index;
checker.current_buffer_index += 1;
array_add(*checker.result.constant_buffers, type_var);
return type_var; return type_var;
} }
@@ -966,11 +994,11 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo
name_to_check := get_actual_function_name(node); name_to_check := get_actual_function_name(node);
if node.vertex_entry_point { if node.vertex_entry_point {
checker.vertex_entry_point = node; checker.result.vertex_entry_point = node;
} }
if node.pixel_entry_point { if node.pixel_entry_point {
checker.pixel_entry_point = node; checker.result.pixel_entry_point = node;
} }
find_result := find_symbol(checker, name_to_check, checker.current_scope); find_result := find_symbol(checker, name_to_check, checker.current_scope);
@@ -984,29 +1012,27 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo
symbol.name = name_to_check; symbol.name = name_to_check;
symbol.source_node = node; symbol.source_node = node;
symbol.type_variable = 0; symbol.type_variable = 0;
array_reserve(*symbol.functions, 16); array_reserve(*symbol.functions, 32);
array_add(*symbol.functions, function); array_add(*symbol.functions, function);
add_symbol_to_scope(checker, checker.current_scope, name_to_check, symbol); add_symbol_to_scope(checker, checker.current_scope, name_to_check, symbol);
} else { } else {
//@Note(niels): This is some ugly code, but it's probably fine for now. //@Note(niels): This is some ugly code, but it's probably fine for now.
for child : node.children { field_list := node.children[0];
if child.kind != .FieldList {
continue;
}
for function : find_result.functions { for function : find_result.functions {
func_var := h2tv(checker, function.type_variable); func_var := h2tv(checker, function.type_variable);
if func_var.child_count != child.children.count { if func_var.source_node.children[0].children.count != field_list.children.count {
continue; continue;
} }
all_same : bool = true; all_same : bool = true;
for i : 0..func_var.child_count - 1 { for i : 0..func_var.children.count - 1 {
arg := func_var.children[i]; arg := func_var.children[i];
node_child := child.children[it_index]; node_child := field_list.children[i];
arg_type := get_type_from_identifier(checker, checker.current_scope, node_child);
typename : string;
arg_type := get_type_from_identifier(checker, checker.current_scope, node_child, *typename);
other_arg := h2tv(checker, arg); other_arg := h2tv(checker, arg);
if arg_type != other_arg.type { if arg_type != other_arg.type {
@@ -1014,7 +1040,7 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo
break; break;
} else { } else {
if arg_type == .Struct && other_arg.type == .Struct { if arg_type == .Struct && other_arg.type == .Struct {
if node_child.token.ident_value != other_arg.typename { if typename != other_arg.typename {
all_same = false; all_same = false;
break; break;
} }
@@ -1043,7 +1069,6 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo
array_add(*find_result.functions, function); array_add(*find_result.functions, function);
} }
}
if !builtin { if !builtin {
scope, scope_handle := push_scope(checker, name_to_check, .Function); scope, scope_handle := push_scope(checker, name_to_check, .Function);
@@ -1068,7 +1093,7 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo
if builtin && node.token.ident_value.count > 0 { if builtin && node.token.ident_value.count > 0 {
return_var, return_handle := new_type_variable(checker); return_var, return_handle := new_type_variable(checker);
return_var.type = get_type_from_identifier(checker, checker.current_scope, node, *return_var.typename); return_var.type = get_type_from_identifier(checker, checker.current_scope, node, *return_var.typename);
h2tv(checker, handle).return_var = return_handle; h2tv(checker, handle).return_type_variable= return_handle;
} }
if !builtin { if !builtin {
@@ -1086,18 +1111,6 @@ create_function_constraint :: (checker : *Semantic_Checker, node : *AST_Node) {
assert(false, "Compiler error. Functions should all be declared at this point in time."); assert(false, "Compiler error. Functions should all be declared at this point in time.");
} }
//@Note(niels): Constraint should be:
// X(X1, ..., Xn) { return E; }: [[X]] = ([[X1]], ..., [[Xn]]) -> [[E]]
// We return the type variable handle for X (the function name)
// @Incomplete(niels): In this case we will have a list of function overloads
// The list is most often of size 1, but in the case it is > 1
// we have overloads that we have to match against.
// This means our constraint gets slightly more complicated.
// At this point we could consider cheating and already matching the types
// at this point and finding the correct function variable.
// We can do this because technically we have already declared all functions at this point.
// So we don't have any unresolved types as of this point.
handle := find_result.type_variable; handle := find_result.type_variable;
if node.foreign_declaration { if node.foreign_declaration {
return; return;
@@ -1114,7 +1127,7 @@ create_function_constraint :: (checker : *Semantic_Checker, node : *AST_Node) {
constraint.kind = .Function_Decl; constraint.kind = .Function_Decl;
constraint.function.symbol_variable = function.type_variable; constraint.function.symbol_variable = function.type_variable;
for i : 0..variable.child_count - 1 { for i : 0..variable.children.count - 1 {
arg_var := variable.children[i]; arg_var := variable.children[i];
if arg_var > 0 { if arg_var > 0 {
@@ -1129,8 +1142,8 @@ create_function_constraint :: (checker : *Semantic_Checker, node : *AST_Node) {
if statement.kind == .Return { if statement.kind == .Return {
result_var := check_node(checker, statement); result_var := check_node(checker, statement);
if result_var > 0 { if result_var > 0 {
variable.return_var = result_var; variable.return_type_variable= result_var;
constraint.function.return_variable = variable.return_var; constraint.function.return_variable = variable.return_type_variable;
} }
} else { } else {
result_var := check_node(checker, statement); result_var := check_node(checker, statement);
@@ -1143,7 +1156,7 @@ create_function_constraint :: (checker : *Semantic_Checker, node : *AST_Node) {
} }
} }
if node.token.ident_value.count > 0 && !variable.return_var { if node.token.ident_value.count > 0 && !variable.return_type_variable{
not_all_control_paths_return_value(checker, node); not_all_control_paths_return_value(checker, node);
} }
@@ -1185,7 +1198,7 @@ create_equivalence_constraint :: (checker : *Semantic_Checker, lhs : Type_Variab
return cast(Type_Constraint_Handle)checker.constraints.count; return cast(Type_Constraint_Handle)checker.constraints.count;
} }
create_variable :: (checker : *Semantic_Checker, node : *AST_Node, field_parent : *AST_Node = null) -> Type_Variable_Handle { create_variable :: (checker : *Semantic_Checker, node : *AST_Node, struct_field_parent : *AST_Node = null) -> Type_Variable_Handle {
find_result := find_symbol(checker, node.name, checker.current_scope); find_result := find_symbol(checker, node.name, checker.current_scope);
// x : int; // x : int;
// x.d = 5; // x.d = 5;
@@ -1193,14 +1206,14 @@ create_variable :: (checker : *Semantic_Checker, node : *AST_Node, field_parent
if find_result { if find_result {
node.type_variable = find_result.type_variable; node.type_variable = find_result.type_variable;
variable := h2tv(checker, find_result.type_variable); variable := h2tv(checker, find_result.type_variable);
variable.field_parent = field_parent; variable.struct_field_parent = struct_field_parent;
if get_scope(checker, checker.current_scope).kind == .Struct { if get_scope(checker, checker.current_scope).kind == .Struct {
variable.scope = checker.current_scope; variable.scope = checker.current_scope;
} }
if node.children.count > 0 { if node.children.count > 0 {
if variable.type != .Struct { if variable.type != .Struct && variable.type != .Properties && variable.type != .CBuffer {
field_access_on_primitive_type(checker, node, find_result.type_variable); field_access_on_primitive_type(checker, node, find_result.type_variable);
return 0; return 0;
} else { } else {
@@ -1248,6 +1261,27 @@ create_field :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable
variable.name = node.name; variable.name = node.name;
typename : string; typename : string;
variable.type = get_type_from_identifier(checker, checker.current_scope, node, *typename); variable.type = get_type_from_identifier(checker, checker.current_scope, node, *typename);
variable.is_array = node.array_field;
if variable.is_array {
size_node := node.children[0];
size_var := check_node(checker, size_node);
if h2tv(checker, size_var).type != .Int {
//@Incomplete(niels): Type mismatch here. With integral type required message.
}
}
if variable.kind == .Declaration && variable.type == .Sampler {
variable.resource_index = checker.current_sampler_index;
checker.current_sampler_index += 1;
}
if variable.kind == .Declaration && variable.type == .Texture2D {
variable.resource_index = checker.current_texture_index;
checker.current_texture_index += 1;
}
variable.typename = typename; variable.typename = typename;
variable.source_node = node; variable.source_node = node;
variable.scope = checker.current_scope; variable.scope = checker.current_scope;
@@ -1297,15 +1331,45 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
return; return;
} }
// @Incomplete(niels): Fix overload resolution.
// Currently we don't have proper resolution. We don't even pick a proper function.
// We need to run through all functions in this find result, and match the arguments.
// If no overload is found, we have to print out all overloads and post mismatched arguments.
// If an overload is found we proceed as usual.
overload_found := false; overload_found := false;
arg_node : *AST_Node = null; arg_node : *AST_Node = null;
Result :: struct {
var : Type_Variable_Handle;
node : *AST_Node;
}
arg_vars : [..]Result;
// @incomplete(niels): Should be some kind of scratch allocator instead probably?
arg_vars.allocator = temp;
arg_count := 0;
for child : node.children {
if child.kind == {
case .ArgList; {
arg_count = child.children.count;
for arg_child : child.children {
arg_var := check_node(checker, arg_child);
if arg_var != 0 {
array_add(*arg_vars, .{ arg_var, arg_child });
}
}
}
}
}
if arg_vars.count != arg_count {
return;
}
Type_Mismatch_Data :: struct {
lhs : Result;
rhs : Result;
}
mismatches : [..]Type_Mismatch_Data;
mismatches.allocator = temp;
for *func : find_result.functions { for *func : find_result.functions {
if overload_found { if overload_found {
break; break;
@@ -1313,59 +1377,53 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
function := h2tv(checker, func.type_variable); function := h2tv(checker, func.type_variable);
if function.return_var > 0 { if arg_count != function.children.count {
return_var := h2tv(checker, function.return_var); continue;
constrained_var := h2tv(checker, type_var);
constrained_var.type = return_var.type;
constrained_var.typename = return_var.typename;
} }
if node.children.count == 0 && function.child_count == 0 { if node.children.count == 0 && function.children.count == 0 {
overload_found = true; overload_found = true;
break; break;
} }
all_args_match : bool = true; all_args_match : bool = true;
for child : node.children { for arg : arg_vars {
if child.kind == {
case .ArgList; {
if child.children.count != function.child_count {
// mismatched_arguments(checker, node, func, child.children.count, function.child_count);
break;
}
for arg_child : child.children {
arg_var := check_node(checker, arg_child);
function_param := function.children[it_index]; function_param := function.children[it_index];
// @Incomplete(nb): Improve the error handling of this constraint. if !types_compatible(checker, arg.var, function_param, true) {
// The usage site might be the call, but really the usage site
// is the variable, with the call around it.
// We could probably expand source locations to always include the whole line
// That is unlikely to be annoying now that I think about it.
// So maybe we just always do that? Then we always have the complete information
// and the actual token we want to focus on is just the one we have?
// @Update(nb): We actually do this now for a bunch of places, but not all.
// Error reporting in this case is still not great, since it doesn't properly mark the
// faulty variable.
create_equivalence_constraint(checker, arg_var, function_param, arg_child);
if !types_compatible(checker, arg_var, function_param) {
if all_args_match { if all_args_match {
arg_node = arg_child; arg_node = arg.node;
} }
fun_param := h2tv(checker, function_param);
mismatch : Type_Mismatch_Data;
mismatch.lhs = arg;
mismatch.rhs = .{ function_param, fun_param.source_node };
array_add(*mismatches, mismatch);
all_args_match = false; all_args_match = false;
overload_found = false;
} else { } else {
overload_found = all_args_match; overload_found = all_args_match;
} }
} }
}
if overload_found {
if function.return_type_variable> 0 {
return_var := h2tv(checker, function.return_type_variable);
constrained_var := h2tv(checker, type_var);
constrained_var.type = return_var.type;
constrained_var.typename = return_var.typename;
} }
} }
} }
if !overload_found { if !overload_found {
no_matching_overload_found(checker, node, find_result, arg_node); no_matching_overload_found(checker, node, find_result, arg_node);
for mismatch : mismatches {
type_mismatch(checker, mismatch.lhs.node, mismatch.rhs.node, mismatch.rhs.var, mismatch.lhs.var);
}
} }
} }
@@ -1396,6 +1454,7 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H
variable, handle := new_type_variable(checker); variable, handle := new_type_variable(checker);
lhs_type := h2tv(checker, lhs_var); lhs_type := h2tv(checker, lhs_var);
variable.type = lhs_type.type; variable.type = lhs_type.type;
variable.typename = lhs_type.typename;
variable.scope = lhs_type.scope; variable.scope = lhs_type.scope;
variable.source_node = node; variable.source_node = node;
node.type_variable = handle; node.type_variable = handle;
@@ -1410,9 +1469,11 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H
create_equivalence_constraint(checker, rhs_var, lhs_var, node); create_equivalence_constraint(checker, rhs_var, lhs_var, node);
proper_variable, rhs_handle := new_type_variable(checker); proper_variable, rhs_handle := new_type_variable(checker);
proper_variable.type = h2tv(checker, lhs_var).type; lhs_type_var := h2tv(checker, lhs_var);
proper_variable.type = lhs_type_var.type;
proper_variable.typename = lhs_type_var.typename;
proper_variable.source_node = h2tv(checker, lhs_var).source_node; proper_variable.source_node = h2tv(checker, lhs_var).source_node;
proper_variable.field_parent = h2tv(checker, lhs_var).field_parent; proper_variable.struct_field_parent = h2tv(checker, lhs_var).struct_field_parent;
create_equivalence_constraint(checker, handle, rhs_handle, node); create_equivalence_constraint(checker, handle, rhs_handle, node);
} }
@@ -1476,8 +1537,8 @@ traverse :: (checker : *Semantic_Checker, root : *AST_Node) {
declare_properties(checker, declaration); declare_properties(checker, declaration);
} else if declaration.kind == .Struct { } else if declaration.kind == .Struct {
declare_struct(checker, declaration); declare_struct(checker, declaration);
} else if declaration.kind == .Meta { } else if declaration.kind == .CBuffer {
declare_meta(checker, declaration); declare_cbuffer(checker, declaration);
} }
} }
@@ -1510,7 +1571,7 @@ Unification_Result :: enum {
Unification_Failure; Unification_Failure;
} }
types_compatible :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rhs : Type_Variable_Handle) -> bool { types_compatible :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rhs : Type_Variable_Handle, param_matching : bool = false) -> bool {
lhs_var := h2tv(checker, lhs); lhs_var := h2tv(checker, lhs);
rhs_var := h2tv(checker, rhs); rhs_var := h2tv(checker, rhs);
@@ -1519,9 +1580,24 @@ types_compatible :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rh
case .Half; #through; case .Half; #through;
case .Float; #through; case .Float; #through;
case .Double; { case .Double; {
if !param_matching {
if rhs_var.type == .Struct {
if rhs_var.typename == {
case "float2"; #through;
case "float3"; #through;
case "float4"; {
return true;
}
}
}
}
return rhs_var.type == .Int || rhs_var.type == .Half || return rhs_var.type == .Int || rhs_var.type == .Half ||
rhs_var.type == .Float || rhs_var.type == .Double; rhs_var.type == .Float || rhs_var.type == .Double;
} }
case .Sampler; #through;
case .Texture2D; {
return rhs_var.type == lhs_var.type;
}
case .Struct; { case .Struct; {
if rhs_var.type != .Struct { if rhs_var.type != .Struct {
return false; return false;
@@ -1530,6 +1606,16 @@ types_compatible :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rh
lhs_node := lhs_var.source_node; lhs_node := lhs_var.source_node;
rhs_node := rhs_var.source_node; rhs_node := rhs_var.source_node;
if rhs_var.type != .Struct {
if lhs_var.typename == {
case "float2"; #through;
case "float3"; #through;
case "float4"; {
return rhs_var.type == .Int || rhs_var.type == .Half || rhs_var.type == .Double || rhs_var.type == .Float;
}
}
}
lhs_struct := find_symbol(checker, lhs_var.typename, xx 1); lhs_struct := find_symbol(checker, lhs_var.typename, xx 1);
rhs_struct := find_symbol(checker, rhs_var.typename, xx 1); rhs_struct := find_symbol(checker, rhs_var.typename, xx 1);
@@ -1544,14 +1630,16 @@ types_compatible :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rh
lhs_struct_var := h2tv(checker, lhs_struct.type_variable); lhs_struct_var := h2tv(checker, lhs_struct.type_variable);
rhs_struct_var := h2tv(checker, rhs_struct.type_variable); rhs_struct_var := h2tv(checker, rhs_struct.type_variable);
if lhs_struct_var.child_count != rhs_struct_var.child_count { if lhs_struct_var.children.count != rhs_struct_var.children.count {
return false; return false;
} }
for i : 0..lhs_struct_var.child_count - 1 { for i : 0..lhs_struct_var.children.count - 1 {
lhs_child := lhs_struct_var.children[i]; lhs_child := lhs_struct_var.children[i];
rhs_child := rhs_struct_var.children[i]; rhs_child := rhs_struct_var.children[i];
if !types_compatible(checker, lhs_child, rhs_child) return false; if !types_compatible(checker, lhs_child, rhs_child) {
return false;
}
} }
return true; return true;
@@ -1576,11 +1664,7 @@ union_terms :: (checker : *Semantic_Checker, lhs_handle : Type_Variable_Handle,
} else { } else {
type_mismatch(checker, lhs_var.source_node.parent, rhs_var.source_node.parent, rhs_handle, lhs_handle); type_mismatch(checker, lhs_var.source_node.parent, rhs_var.source_node.parent, rhs_handle, lhs_handle);
} }
} else if lhs_handle != rhs_handle {
return;
}
if lhs_handle != rhs_handle {
lhs := h2tv(checker, lhs_handle); lhs := h2tv(checker, lhs_handle);
lhs.uf_parent = rhs_handle; lhs.uf_parent = rhs_handle;
} }
@@ -1641,14 +1725,41 @@ union_find :: (checker : *Semantic_Checker) -> bool {
return true; return true;
} }
// HLSL_BUILTIN :: #run -> string {
// T := #load "hlsl_builtin.jai";
// return "";
// };
add_hlsl_builtins :: (checker : *Semantic_Checker) { add_hlsl_builtins :: (checker : *Semantic_Checker) {
#load "hlsl_builtin.jai"; source_location := #location().fully_pathed_filename;
path_array := split(source_location, "/");
sb : String_Builder;
for i : 0..path_array.count - 2 {
print_to_builder(*sb, path_array[i]);
append(*sb, "/");
}
append(*sb, "hlsl_builtin.shd");
path := builder_to_string(*sb);
HLSL_BUILTIN, ok := read_entire_file(path);
if !ok {
messages : [..]Compiler_Message;
internal_error_message(*messages, "Error loading builtin functions.", checker.path);
print("%\n", report_messages(messages));
assert(false);
return;
}
checker.state = .Adding_Builtins; checker.state = .Adding_Builtins;
lexer : Lexer; lexer : Lexer;
init_lexer_from_string(*lexer, HLSL_BULTIN); init_lexer_from_string(*lexer, HLSL_BUILTIN);
if lexer.result.had_error { if lexer.result.had_error {
print("%\n", report_messages(lexer.result.messages)); print("%\n", report_messages(lexer.result.messages));
return; return;
@@ -1661,7 +1772,7 @@ add_hlsl_builtins :: (checker : *Semantic_Checker) {
} }
parse_state : Parse_State; parse_state : Parse_State;
init_parse_state(*parse_state, lex_result.tokens, lexer.path, context.allocator); init_parse_state(*parse_state, lex_result.tokens, lexer.path);
parse_result := parse(*parse_state); parse_result := parse(*parse_state);
if parse_result.had_error { if parse_result.had_error {
@@ -1706,6 +1817,9 @@ type_check :: (checker : *Semantic_Checker, root : *AST_Node) {
} }
check :: (checker : *Semantic_Checker, root : *AST_Node) -> Semantic_Check_Result { check :: (checker : *Semantic_Checker, root : *AST_Node) -> Semantic_Check_Result {
checker.current_buffer_index = 0;
checker.current_sampler_index = 0;
checker.current_texture_index = 0;
array_reserve(*checker.result.messages, 16); array_reserve(*checker.result.messages, 16);
array_reserve(*checker.constraints, 1024); array_reserve(*checker.constraints, 1024);
add_hlsl_builtins(checker); add_hlsl_builtins(checker);
@@ -1722,18 +1836,7 @@ check :: (checker : *Semantic_Checker) -> Semantic_Check_Result {
// =========================================================== // ===========================================================
// Pretty printing // Pretty printing
pretty_print_children :: (checker : *Semantic_Checker, builder : *String_Builder, type : Type_Variable, indentation : int) { #scope_file
indent(builder, indentation);
for 0..type.child_count - 1 {
child_handle := type.children[it];
child := h2tv(checker, child_handle);
// if child.kind != .Function {
// print_to_builder(builder, "% : %", child.name, type_to_string(child));
// } else {
// pretty_print_function(checker, builder, "", child, 0);
// }
}
}
type_to_string :: (type_variable : Type_Variable) -> string { type_to_string :: (type_variable : Type_Variable) -> string {
if type_variable.type == { if type_variable.type == {
@@ -1744,18 +1847,24 @@ type_to_string :: (type_variable : Type_Variable) -> string {
case .Int; #through; case .Int; #through;
case .Half; #through; case .Half; #through;
case .Float; #through; case .Float; #through;
case .Sampler; #through;
case .Texture2D; #through;
case .Double; { case .Double; {
return Typenames[type_variable.type]; return Typenames[type_variable.type];
} }
case .Function; #through; case .Function; #through;
case .Struct; case .Struct; {
return type_variable.typename; return type_variable.typename;
}
case .Array; case .Array;
return "array"; return "array";
} }
return ""; return "";
} }
#scope_export
print_key :: (checker : *Semantic_Checker, builder : *String_Builder, name : string) { print_key :: (checker : *Semantic_Checker, builder : *String_Builder, name : string) {
scope := get_current_scope(checker); scope := get_current_scope(checker);
target_length := scope.longest_key_length + 1; target_length := scope.longest_key_length + 1;
@@ -1795,8 +1904,8 @@ pretty_print_function :: (checker : *Semantic_Checker, builder : *String_Builder
} }
} }
if function.return_var > 0 { if function.return_type_variable> 0 {
print_to_builder(builder, ") -> %\n", type_to_string(h2tv(checker, function.return_var))); print_to_builder(builder, ") -> %\n", type_to_string(h2tv(checker, function.return_type_variable)));
} else { } else {
append(builder, ")\n"); append(builder, ")\n");
} }
@@ -1807,19 +1916,18 @@ pretty_print_struct :: (checker : *Semantic_Checker, builder : *String_Builder,
print_key(checker, builder, name); print_key(checker, builder, name);
append(builder, "{"); append(builder, "{");
for 0..struct_type.child_count - 1 { for 0..struct_type.children.count - 1 {
child_handle := struct_type.children[it]; child_handle := struct_type.children[it];
child := h2tv(checker, child_handle); child := h2tv(checker, child_handle);
print_to_builder(builder, child.name); print_to_builder(builder, child.name);
append(builder, " : "); append(builder, " : ");
print_to_builder(builder, type_to_string(child)); print_to_builder(builder, type_to_string(child));
if it < struct_type.child_count - 1 { if it < struct_type.children.count - 1 {
append(builder, ", "); append(builder, ", ");
} }
} }
pretty_print_children(checker, builder, struct_type, 0);
append(builder, "}\n"); append(builder, "}\n");
} }
@@ -1853,6 +1961,8 @@ pretty_print_scope :: (checker : *Semantic_Checker, scope : *Scope, builder : *S
case .Function; { case .Function; {
pretty_print_function(checker, builder, key, type_variable, 1); pretty_print_function(checker, builder, key, type_variable, 1);
} }
case .CBuffer; #through;
case .Properties; #through;
case .Struct; { case .Struct; {
if type_variable.typename.count > 0 && type_variable.kind != .Declaration { if type_variable.typename.count > 0 && type_variable.kind != .Declaration {
indent(builder, indentation + 1); indent(builder, indentation + 1);
@@ -1877,6 +1987,8 @@ pretty_print_scope :: (checker : *Semantic_Checker, scope : *Scope, builder : *S
case .Function; { case .Function; {
pretty_print_function(checker, builder, key, type_variable, 1); pretty_print_function(checker, builder, key, type_variable, 1);
} }
case .CBuffer; #through;
case .Properties; #through;
case .Struct; { case .Struct; {
if type_variable.typename.count > 0 && type_variable.kind != .Declaration { if type_variable.typename.count > 0 && type_variable.kind != .Declaration {
indent(builder, indentation + 1); indent(builder, indentation + 1);
@@ -1988,9 +2100,10 @@ print_type_variable :: (builder : *String_Builder, variable : Type_Variable, che
} }
case .Function; #through; case .Function; #through;
case .Struct; #through; case .Struct; #through;
case .CBuffer; #through;
case .Field; { case .Field; {
if variable.field_parent { if variable.struct_field_parent {
print_to_builder(builder, "%.", variable.field_parent.name); print_to_builder(builder, "%.", variable.struct_field_parent.name);
} }
print_to_builder(builder, "%", node.name); print_to_builder(builder, "%", node.name);
@@ -2015,10 +2128,10 @@ print_type_variable :: (builder : *String_Builder, variable : Type_Variable, che
print_from_source_location(builder, source_location); print_from_source_location(builder, source_location);
} }
case .Call; { case .Call; {
if variable.return_var { if variable.return_type_variable{
assert(false); assert(false);
print_to_builder(builder, "%", variable.typename); print_to_builder(builder, "%", variable.typename);
print_type_variable(builder, checker, variable.return_var); print_type_variable(builder, checker, variable.return_type_variable);
} }
print_to_builder(builder, "%(", node.name); print_to_builder(builder, "%(", node.name);
@@ -2069,18 +2182,19 @@ pretty_print_type_variable :: (checker : *Semantic_Checker, type_variable : *Typ
rep_var := h2tv(checker, rep); rep_var := h2tv(checker, rep);
if is_proper(type_variable) { if is_proper(type_variable) {
print_to_builder(builder, proper_type_to_string(checker, type_variable, temp)); print_to_builder(builder, proper_type_to_string(checker, type_variable, temp));
} else if type_variable.type == .Struct { } else if type_variable.type == .Struct || type_variable.type == .Properties ||
type_variable.type == .CBuffer {
if type_variable.kind == .Declaration { if type_variable.kind == .Declaration {
append(builder, "{"); append(builder, "{");
for 0..type_variable.child_count - 1 { for 0..type_variable.children.count - 1 {
child_handle := type_variable.children[it]; child_handle := type_variable.children[it];
child := h2tv(checker, child_handle); child := h2tv(checker, child_handle);
print_to_builder(builder, child.name); print_to_builder(builder, child.name);
append(builder, " : "); append(builder, " : ");
print_to_builder(builder, type_to_string(child)); print_to_builder(builder, type_to_string(child));
if it < type_variable.child_count - 1 { if it < type_variable.children.count - 1 {
append(builder, ", "); append(builder, ", ");
} }
} }
@@ -2120,3 +2234,9 @@ pretty_print_type_constraints :: (checker : *Semantic_Checker, allocator : Alloc
return builder_to_string(*builder,, allocator); return builder_to_string(*builder,, allocator);
} }
#scope_module
#import "ncore";
#import "Hash_Table";
#import "String";

View File

@@ -216,7 +216,7 @@ run_parser_test :: (lexer : *Lexer, output_type : Output_Type = 0) -> Result, *A
result_data : Result; result_data : Result;
result_data.path = lexer.path; result_data.path = lexer.path;
result_data.stage = .Parser; result_data.stage = .Parser;
init_parse_state(*parse_state, lexer.result.tokens, lexer.path, context.allocator); init_parse_state(*parse_state, lexer.result.tokens, lexer.path);
result := parse(*parse_state); result := parse(*parse_state);
result_node : *AST_Node; result_node : *AST_Node;
@@ -272,7 +272,7 @@ run_semantic_analysis_test :: (file_path : string, output_type : Output_Type = 0
parse_state : Parse_State; parse_state : Parse_State;
result_data.stage = .Parser; result_data.stage = .Parser;
init_parse_state(*parse_state, lex_result.tokens, lexer.path, context.allocator); init_parse_state(*parse_state, lex_result.tokens, lexer.path);
parse_result := parse(*parse_state); parse_result := parse(*parse_state);
if parse_result.had_error { if parse_result.had_error {
@@ -310,8 +310,8 @@ run_semantic_analysis_test :: (file_path : string, root : *AST_Node, output_type
result_text = pretty_print_symbol_table(*checker, temp); result_text = pretty_print_symbol_table(*checker, temp);
constraints := pretty_print_type_constraints(*checker, temp); constraints := pretty_print_type_constraints(*checker, temp);
type_vars := pretty_print_type_variables(*checker, temp); type_vars := pretty_print_type_variables(*checker, temp);
print("Constraints\n%\n", constraints); // print("Constraints\n%\n", constraints);
print("Solution\n%\n", type_vars); // print("Solution\n%\n", type_vars);
} }
if output_type & .StdOut { if output_type & .StdOut {
@@ -398,7 +398,7 @@ run_codegen_test :: (path : string, output_type : Output_Type = 0) -> Result, Co
parse_state : Parse_State; parse_state : Parse_State;
result_data.stage = .Parser; result_data.stage = .Parser;
init_parse_state(*parse_state, lex_result.tokens, lexer.path, context.allocator); init_parse_state(*parse_state, lex_result.tokens, lexer.path);
parse_result := parse(*parse_state); parse_result := parse(*parse_state);
if parse_result.had_error { if parse_result.had_error {
@@ -477,7 +477,23 @@ run_test :: (file_path : string, stage_flags : Stage_Flags, results : *[..]Resul
} }
run_test :: (test_case : Test_Case, results : *[..]Result, output_type : Output_Type = 0) { run_test :: (test_case : Test_Case, results : *[..]Result, output_type : Output_Type = 0) {
print("%Running test: %\n", cyan(), test_case.path); print("%Running test: %......", cyan(), test_case.path);
// path 30
// len 35
// == 5
// path 20
// len = 35
// == 15
len := 50;
rest := len - test_case.path.count;
for i: 0..rest {
print(" ");
}
run_test(test_case.path, test_case.stage_flags, results, output_type); run_test(test_case.path, test_case.stage_flags, results, output_type);
} }
@@ -525,7 +541,7 @@ run_test_suite :: (using suite : *Test_Suite, output_type : Output_Type = 0) {
} }
} }
print("\n"); // print("\n");
} }
print("\n"); print("\n");
@@ -620,26 +636,26 @@ evaluate_result :: (result : Result) {
if #complete result.type == { if #complete result.type == {
case .File_Read_Failed; { case .File_Read_Failed; {
print("%", red()); print(" %", red());
print("% failed with File_Read_Failed\n", result.path); print("failed with File_Read_Failed\n");
} }
case .Golden_File_Not_Found; { case .Golden_File_Not_Found; {
print("%", red()); print(" %", red());
print("% failed with Golden File Not Found for stage %\n", result.path, stage); print("failed with Golden File Not Found for stage %\n", stage);
} }
case .StdOut; { case .StdOut; {
} }
case .Golden_Output; { case .Golden_Output; {
print("%", yellow()); print(" %", yellow());
print("% output new golden file at %\n", result.path, result.golden_path); print("output new golden file at %\n", result.golden_path);
} }
case .Passed; { case .Passed; {
print("%", green()); print(" %", green());
print("% passed %\n", result.path, stage); print("passed %\n", stage);
} }
case .Failed; { case .Failed; {
print("%", red()); print(" %", red());
print("% failed %\n", result.path, stage); print("failed %\n", stage);
} }
} }

View File

@@ -1,3 +1,3 @@
@echo off @echo off
jai Test.jai jai first.jai -natvis

42
first.jai Normal file
View File

@@ -0,0 +1,42 @@
#import "Basic";
#import "File";
#import "Compiler";
build :: () {
w := compiler_create_workspace("Shader Compiler Test Build");
if !w {
print("Workspace creation failed.\n");
return;
}
EXECUTABLE_NAME :: "test";
MAIN_FILE :: "Test.jai";
options := get_build_options(w);
options.write_added_strings = true;
new_path: [..] string;
array_add(*new_path, ..options.import_path);
array_add(*new_path, "modules");
// array_add(*new_path, "modules/shader_parsing");
options.import_path = new_path;
options.output_executable_name = EXECUTABLE_NAME;
wd := get_working_directory();
set_build_options(options, w);
compiler_begin_intercept(w);
add_build_file(MAIN_FILE, w);
compiler_end_intercept(w);
print("\nDone!\n\n");
set_build_options_dc(.{do_output=false});
}
#run build();

View File

@@ -1,252 +1,5 @@
HLSL_BULTIN :: #string DONE HLSL_BUILTIN :: #run -> string {
// return read_entire_file("./hlsl_builtin.shd");
return "";
};
float2 :: struct {
x : float;
y : float;
}
float3 :: struct {
x : float;
y : float;
z : float;
}
float4 :: struct {
x : float;
y : float;
z : float;
w : float;
}
float4x4 :: struct {
m11 : float;
m12 : float;
m13 : float;
m14 : float;
m21 : float;
m22 : float;
m23 : float;
m24 : float;
m31 : float;
m32 : float;
m33 : float;
m34 : float;
m41 : float;
m42 : float;
m43 : float;
m44 : float;
}
int2 :: struct {
x : int;
y : int;
}
int3 :: struct {
x : int;
y : int;
z : int;
}
int4 :: struct {
x : int;
y : int;
z : int;
w : int;
}
int4x4 :: struct {
m11 : int;
m12 : int;
m13 : int;
m14 : int;
m21 : int;
m22 : int;
m23 : int;
m24 : int;
m31 : int;
m32 : int;
m33 : int;
m34 : int;
m41 : int;
m42 : int;
m43 : int;
m44 : int;
}
//~ nbr: Constructors
#foreign float2 :: (float, float) -> float2;
#foreign float3 :: (float, float, float) -> float3;
#foreign float4 :: (float, float, float, float) -> float4;
//~ nbr: Vectors
#foreign cross :: (float3, float3) -> float3;
#foreign distance :: (float2, float2) -> float;
#foreign distance :: (float3, float3) -> float;
#foreign distance :: (float4, float4) -> float;
#foreign dot :: (float2, float2) -> float;
#foreign dot :: (float3, float3) -> float;
#foreign dot :: (float4, float4) -> float;
#foreign normalize :: (float2) -> float2;
#foreign normalize :: (float3) -> float3;
#foreign normalize :: (float4) -> float4;
#foreign transpose :: (float4x4) -> float4x4;
//~ nbr: Multiplies
#foreign mul :: (float2, float2) -> float2;
#foreign mul :: (float3, float3) -> float3;
#foreign mul :: (float4, float4) -> float4;
#foreign mul :: (float4x4, float4x4) -> float4x4;
//~ nbr: General
#foreign abs :: (float) -> float;
#foreign abs :: (float2) -> float2;
#foreign abs :: (float3) -> float3;
#foreign abs :: (float4) -> float4;
#foreign abs :: (float4x4) -> float4x4;
#foreign min :: (float) -> float;
#foreign min :: (float2) -> float2;
#foreign min :: (float3) -> float3;
#foreign min :: (float4) -> float4;
#foreign min :: (float4x4) -> float4x4;
#foreign max :: (float) -> float;
#foreign max :: (float2) -> float2;
#foreign max :: (float3) -> float3;
#foreign max :: (float4) -> float4;
#foreign max :: (float4x4) -> float4x4;
#foreign ceil :: (float) -> float;
#foreign ceil :: (float2) -> float2;
#foreign ceil :: (float3) -> float3;
#foreign ceil :: (float4) -> float4;
#foreign ceil :: (float4x4) -> float4x4;
#foreign floor :: (float) -> float;
#foreign floor :: (float2) -> float2;
#foreign floor :: (float3) -> float3;
#foreign floor :: (float4) -> float4;
#foreign floor :: (float4x4) -> float4x4;
#foreign round :: (float) -> float;
#foreign round :: (float2) -> float2;
#foreign round :: (float3) -> float3;
#foreign round :: (float4) -> float4;
#foreign round :: (float4x4) -> float4x4;
#foreign clamp :: (float, float, float) -> float;
#foreign clamp :: (float2, float2, float2) -> float2;
#foreign clamp :: (float3, float3, float3) -> float3;
#foreign clamp :: (float4, float4, float4) -> float4;
#foreign clamp :: (float4x4, float4x4, float4x4) -> float4x4;
#foreign log :: (float) -> float;
#foreign log :: (float2) -> float2;
#foreign log :: (float3) -> float3;
#foreign log :: (float4) -> float4;
#foreign log :: (float4x4) -> float4x4;
#foreign log2 :: (float) -> float;
#foreign log2 :: (float2) -> float2;
#foreign log2 :: (float3) -> float3;
#foreign log2 :: (float4) -> float4;
#foreign log2 :: (float4x4) -> float4x4;
#foreign log10 :: (float) -> float;
#foreign log10 :: (float2) -> float2;
#foreign log10 :: (float3) -> float3;
#foreign log10 :: (float4) -> float4;
#foreign log10 :: (float4x4) -> float4x4;
#foreign pow :: (float, float, float) -> float;
#foreign pow :: (float2, float2, float2) -> float2;
#foreign pow :: (float3, float3, float3) -> float3;
#foreign pow :: (float4, float4, float4) -> float4;
#foreign pow :: (float4x4, float4x4, float4x4) -> float4x4;
#foreign smoothstep :: (float, float, float) -> float;
#foreign smoothstep :: (float2, float2, float2) -> float2;
#foreign smoothstep :: (float3, float3, float3) -> float3;
#foreign smoothstep :: (float4, float4, float4) -> float4;
#foreign smoothstep :: (float4x4, float4x4, float4x4) -> float4x4;
#foreign step :: (float, float) -> float;
#foreign step :: (float2, float2) -> float2;
#foreign step :: (float3, float3) -> float3;
#foreign step :: (float4, float4) -> float4;
#foreign step :: (float4x4, float4x4) -> float4x4;
#foreign sqrt :: (float) -> float;
#foreign sqrt :: (float2) -> float2;
#foreign sqrt :: (float3) -> float3;
#foreign sqrt :: (float4) -> float4;
#foreign sqrt :: (float4x4) -> float4x4;
//~ nbr: Trigonometry
#foreign cos :: (float) -> float;
#foreign cos :: (float2) -> float2;
#foreign cos :: (float3) -> float3;
#foreign cos :: (float4) -> float4;
#foreign cos :: (float4x4) -> float4x4;
#foreign cosh :: (float) -> float;
#foreign cosh :: (float2) -> float2;
#foreign cosh :: (float3) -> float3;
#foreign cosh :: (float4) -> float4;
#foreign cosh :: (float4x4) -> float4x4;
#foreign acos :: (float) -> float;
#foreign acos :: (float2) -> float2;
#foreign acos :: (float3) -> float3;
#foreign acos :: (float4) -> float4;
#foreign acos :: (float4x4) -> float4x4;
#foreign sin :: (float) -> float;
#foreign sin :: (float2) -> float2;
#foreign sin :: (float3) -> float3;
#foreign sin :: (float4) -> float4;
#foreign sin :: (float4x4) -> float4x4;
#foreign sinh :: (float) -> float;
#foreign sinh :: (float2) -> float2;
#foreign sinh :: (float3) -> float3;
#foreign sinh :: (float4) -> float4;
#foreign sinh :: (float4x4) -> float4x4;
#foreign asin :: (float) -> float;
#foreign asin :: (float2) -> float2;
#foreign asin :: (float3) -> float3;
#foreign asin :: (float4) -> float4;
#foreign asin :: (float4x4) -> float4x4;
#foreign tan :: (float) -> float;
#foreign tan :: (float2) -> float2;
#foreign tan :: (float3) -> float3;
#foreign tan :: (float4) -> float4;
#foreign tan :: (float4x4) -> float4x4;
#foreign tanh :: (float) -> float;
#foreign tanh :: (float2) -> float2;
#foreign tanh :: (float3) -> float3;
#foreign tanh :: (float4) -> float4;
#foreign tanh :: (float4x4) -> float4x4;
#foreign atan :: (float) -> float;
#foreign atan :: (float2) -> float2;
#foreign atan :: (float3) -> float3;
#foreign atan :: (float4) -> float4;
#foreign atan :: (float4x4) -> float4x4;
#foreign atan2 :: (float, float) -> float;
#foreign atan2 :: (float2, float2) -> float2;
#foreign atan2 :: (float3, float3) -> float3;
#foreign atan2 :: (float4, float4) -> float4;
#foreign atan2 :: (float4x4, float4x4) -> float4x4;
DONE

262
hlsl_builtin.shd Normal file
View File

@@ -0,0 +1,262 @@
float2 :: struct {
x : float;
y : float;
}
float3 :: struct {
x : float;
y : float;
z : float;
}
float4 :: struct {
x : float;
y : float;
z : float;
w : float;
}
float4x4 :: struct {
m11 : float;
m12 : float;
m13 : float;
m14 : float;
m21 : float;
m22 : float;
m23 : float;
m24 : float;
m31 : float;
m32 : float;
m33 : float;
m34 : float;
m41 : float;
m42 : float;
m43 : float;
m44 : float;
}
int2 :: struct {
x : int;
y : int;
}
int3 :: struct {
x : int;
y : int;
z : int;
}
int4 :: struct {
x : int;
y : int;
z : int;
w : int;
}
int4x4 :: struct {
m11 : int;
m12 : int;
m13 : int;
m14 : int;
m21 : int;
m22 : int;
m23 : int;
m24 : int;
m31 : int;
m32 : int;
m33 : int;
m34 : int;
m41 : int;
m42 : int;
m43 : int;
m44 : int;
}
//~ nbr: Constructors
#foreign float2 :: (float, float) -> float2;
#foreign float3 :: (float, float, float) -> float3;
#foreign float4 :: (float, float, float, float) -> float4;
//~ nbr: Vectors
#foreign cross :: (float3, float3) -> float3;
#foreign distance :: (float2, float2) -> float;
#foreign distance :: (float3, float3) -> float;
#foreign distance :: (float4, float4) -> float;
#foreign dot :: (float2, float2) -> float;
#foreign dot :: (float3, float3) -> float;
#foreign dot :: (float4, float4) -> float;
#foreign normalize :: (float2) -> float2;
#foreign normalize :: (float3) -> float3;
#foreign normalize :: (float4) -> float4;
#foreign transpose :: (float4x4) -> float4x4;
//~ nbr: Multiplies
#foreign mul :: (float2, float2) -> float;
#foreign mul :: (float3, float3) -> float;
#foreign mul :: (float4, float4) -> float;
#foreign mul :: (float4x4, float4x4) -> float4x4;
#foreign mul :: (float, float2) -> float2;
#foreign mul :: (float, float3) -> float3;
#foreign mul :: (float, float4) -> float4;
#foreign mul :: (float, float4x4) -> float4x4;
#foreign mul :: (float4x4, float) -> float4x4;
#foreign mul :: (float4x4, float4) -> float4;
#foreign mul :: (float2, float) -> float2;
#foreign mul :: (float3, float) -> float3;
#foreign mul :: (float4, float) -> float4;
#foreign mul :: (float4, float4x4) -> float4x4;
//~ nbr: General
#foreign abs :: (float) -> float;
#foreign abs :: (float2) -> float2;
#foreign abs :: (float3) -> float3;
#foreign abs :: (float4) -> float4;
#foreign abs :: (float4x4) -> float4x4;
#foreign min :: (float) -> float;
#foreign min :: (float2) -> float2;
#foreign min :: (float3) -> float3;
#foreign min :: (float4) -> float4;
#foreign min :: (float4x4) -> float4x4;
#foreign max :: (float) -> float;
#foreign max :: (float2) -> float2;
#foreign max :: (float3) -> float3;
#foreign max :: (float4) -> float4;
#foreign max :: (float4x4) -> float4x4;
#foreign ceil :: (float) -> float;
#foreign ceil :: (float2) -> float2;
#foreign ceil :: (float3) -> float3;
#foreign ceil :: (float4) -> float4;
#foreign ceil :: (float4x4) -> float4x4;
#foreign floor :: (float) -> float;
#foreign floor :: (float2) -> float2;
#foreign floor :: (float3) -> float3;
#foreign floor :: (float4) -> float4;
#foreign floor :: (float4x4) -> float4x4;
#foreign round :: (float) -> float;
#foreign round :: (float2) -> float2;
#foreign round :: (float3) -> float3;
#foreign round :: (float4) -> float4;
#foreign round :: (float4x4) -> float4x4;
#foreign clamp :: (float, float, float) -> float;
#foreign clamp :: (float2, float2, float2) -> float2;
#foreign clamp :: (float3, float3, float3) -> float3;
#foreign clamp :: (float4, float4, float4) -> float4;
#foreign clamp :: (float4x4, float4x4, float4x4) -> float4x4;
#foreign log :: (float) -> float;
#foreign log :: (float2) -> float2;
#foreign log :: (float3) -> float3;
#foreign log :: (float4) -> float4;
#foreign log :: (float4x4) -> float4x4;
#foreign log2 :: (float) -> float;
#foreign log2 :: (float2) -> float2;
#foreign log2 :: (float3) -> float3;
#foreign log2 :: (float4) -> float4;
#foreign log2 :: (float4x4) -> float4x4;
#foreign log10 :: (float) -> float;
#foreign log10 :: (float2) -> float2;
#foreign log10 :: (float3) -> float3;
#foreign log10 :: (float4) -> float4;
#foreign log10 :: (float4x4) -> float4x4;
#foreign pow :: (float, float, float) -> float;
#foreign pow :: (float2, float2, float2) -> float2;
#foreign pow :: (float3, float3, float3) -> float3;
#foreign pow :: (float4, float4, float4) -> float4;
#foreign pow :: (float4x4, float4x4, float4x4) -> float4x4;
#foreign smoothstep :: (float, float, float) -> float;
#foreign smoothstep :: (float2, float2, float2) -> float2;
#foreign smoothstep :: (float3, float3, float3) -> float3;
#foreign smoothstep :: (float4, float4, float4) -> float4;
#foreign smoothstep :: (float4x4, float4x4, float4x4) -> float4x4;
#foreign step :: (float, float) -> float;
#foreign step :: (float2, float2) -> float2;
#foreign step :: (float3, float3) -> float3;
#foreign step :: (float4, float4) -> float4;
#foreign step :: (float4x4, float4x4) -> float4x4;
#foreign sqrt :: (float) -> float;
#foreign sqrt :: (float2) -> float2;
#foreign sqrt :: (float3) -> float3;
#foreign sqrt :: (float4) -> float4;
#foreign sqrt :: (float4x4) -> float4x4;
//~ nbr: Trigonometry
#foreign cos :: (float) -> float;
#foreign cos :: (float2) -> float2;
#foreign cos :: (float3) -> float3;
#foreign cos :: (float4) -> float4;
#foreign cos :: (float4x4) -> float4x4;
#foreign cosh :: (float) -> float;
#foreign cosh :: (float2) -> float2;
#foreign cosh :: (float3) -> float3;
#foreign cosh :: (float4) -> float4;
#foreign cosh :: (float4x4) -> float4x4;
#foreign acos :: (float) -> float;
#foreign acos :: (float2) -> float2;
#foreign acos :: (float3) -> float3;
#foreign acos :: (float4) -> float4;
#foreign acos :: (float4x4) -> float4x4;
#foreign sin :: (float) -> float;
#foreign sin :: (float2) -> float2;
#foreign sin :: (float3) -> float3;
#foreign sin :: (float4) -> float4;
#foreign sin :: (float4x4) -> float4x4;
#foreign sinh :: (float) -> float;
#foreign sinh :: (float2) -> float2;
#foreign sinh :: (float3) -> float3;
#foreign sinh :: (float4) -> float4;
#foreign sinh :: (float4x4) -> float4x4;
#foreign asin :: (float) -> float;
#foreign asin :: (float2) -> float2;
#foreign asin :: (float3) -> float3;
#foreign asin :: (float4) -> float4;
#foreign asin :: (float4x4) -> float4x4;
#foreign tan :: (float) -> float;
#foreign tan :: (float2) -> float2;
#foreign tan :: (float3) -> float3;
#foreign tan :: (float4) -> float4;
#foreign tan :: (float4x4) -> float4x4;
#foreign tanh :: (float) -> float;
#foreign tanh :: (float2) -> float2;
#foreign tanh :: (float3) -> float3;
#foreign tanh :: (float4) -> float4;
#foreign tanh :: (float4x4) -> float4x4;
#foreign atan :: (float) -> float;
#foreign atan :: (float2) -> float2;
#foreign atan :: (float3) -> float3;
#foreign atan :: (float4) -> float4;
#foreign atan :: (float4x4) -> float4x4;
#foreign atan2 :: (float, float) -> float;
#foreign atan2 :: (float2, float2) -> float2;
#foreign atan2 :: (float3, float3) -> float3;
#foreign atan2 :: (float4, float4) -> float4;
#foreign atan2 :: (float4x4, float4x4) -> float4x4;
#foreign sample :: (Texture2D, Sampler, float2) -> float4;

View File

@@ -56,6 +56,7 @@ Hint_Kind :: enum {
None; None;
Position; Position;
UV;
Target; Target;
Custom; Custom;
@@ -72,6 +73,7 @@ Field :: struct {
name : string; name : string;
type : Field_Type; type : Field_Type;
resource_index : u32;
hints : [..]Field_Hint; hints : [..]Field_Hint;
} }
@@ -111,12 +113,87 @@ Properties :: struct {
buffer_index : u32; buffer_index : u32;
} }
Constant_Buffer :: struct {
register : int;
name : string;
fields : Static_Array(Property_Field, 16);
buffer_index : u32;
}
Shader_Variant_Collection :: struct { Shader_Variant_Collection :: struct {
properties : Properties; properties : Properties;
max_constant_buffers :: 16;
cbuffers : Static_Array(Constant_Buffer, max_constant_buffers);
variants : [..]Shader_Variant; variants : [..]Shader_Variant;
} }
Input_File :: struct {
source : string;
path : string;
}
Token_Stream :: struct {
tokens : [..]Token;
}
Compiled_File :: struct {
file : Input_File;
tokens : Token_Stream;
ast_root : *AST_Node;
ast_nodes : [..]AST_Node;
}
Compile_Result :: struct {
files : [..]Compiled_File;
had_error : bool;
messages : [..]Compiler_Message;
allocator : Allocator;
arena : Arena;
}
//@Incomplete(niels): need to consider allocation
add_file :: (result : *Compile_Result, path : string) {
file_string, ok := read_entire_file(path);
if !ok {
// record_error(.File_Load_Failed, "Unable to load file: %", path);
return;
}
input_file : Input_File;
input_file.source = file_string;
input_file.path = path;
compiled_file : Compiled_File;
compiled_file.file = input_file;
array_add(*result.files, compiled_file);
}
// @Incomplete(nb): Will we ever even use this?
from_file :: (path : string) -> Compile_Result {
arr : [1]string;
arr[0] = path;
return from_files(arr);
}
from_files :: (paths : []string) -> Compile_Result {
result : Compile_Result;
for path : paths {
add_file(*result, path);
}
return result;
}
Compilation_Result :: struct { Compilation_Result :: struct {
messages : [..]Compiler_Message; messages : [..]Compiler_Message;
@@ -227,9 +304,13 @@ type_variable_to_field :: (checker : *Semantic_Checker, variable : *Type_Variabl
} }
case .Texture2D; { case .Texture2D; {
type.kind = Field_Kind.Texture2D; type.kind = Field_Kind.Texture2D;
field.resource_index = variable.resource_index;
} }
case .Sampler; { case .Sampler; {
type.kind = Field_Kind.Sampler; type.kind = Field_Kind.Sampler;
field.resource_index = variable.resource_index;
} }
case .Struct; { case .Struct; {
type.kind = Field_Kind.Struct; type.kind = Field_Kind.Struct;
@@ -239,7 +320,7 @@ type_variable_to_field :: (checker : *Semantic_Checker, variable : *Type_Variabl
type_var := h2tv(checker, find_result.type_variable); type_var := h2tv(checker, find_result.type_variable);
for i : 0..type_var.child_count - 1 { for i : 0..type_var.children.count - 1 {
child := type_var.children[i]; child := type_var.children[i];
child_field := type_variable_to_field(checker, h2tv(checker, child)); child_field := type_variable_to_field(checker, h2tv(checker, child));
array_add(*type.children, child_field); array_add(*type.children, child_field);
@@ -255,6 +336,8 @@ type_variable_to_field :: (checker : *Semantic_Checker, variable : *Type_Variabl
if hint.ident_value == "position" { if hint.ident_value == "position" {
// @Incomplete(nb): Should be a lookup table somewhere // @Incomplete(nb): Should be a lookup table somewhere
field_hint.kind = .Position; field_hint.kind = .Position;
} else if hint.ident_value == "uv" {
field_hint.kind = .UV;
} else if starts_with(hint.ident_value, "target") { } else if starts_with(hint.ident_value, "target") {
// @Incomplete(nb): Should be a lookup table somewhere // @Incomplete(nb): Should be a lookup table somewhere
index_str : string; index_str : string;
@@ -277,6 +360,21 @@ type_variable_to_field :: (checker : *Semantic_Checker, variable : *Type_Variabl
return field; return field;
} }
compile_file :: (compiler : *Shader_Compiler, paths : []string) -> Compile_Result {
result : Compile_Result;
for path : paths {
add_file(*result, path);
}
lex(*result);
// parse(*result);
// check(*result);
// codegen(*result);
return result;
}
compile_file :: (compiler : *Shader_Compiler, path : string) -> Compilation_Result { compile_file :: (compiler : *Shader_Compiler, path : string) -> Compilation_Result {
result : Compilation_Result; result : Compilation_Result;
@@ -297,7 +395,7 @@ compile_file :: (compiler : *Shader_Compiler, path : string) -> Compilation_Resu
} }
parse_state : Parse_State; parse_state : Parse_State;
init_parse_state(*parse_state, lex_result.tokens, lexer.path, context.allocator); init_parse_state(*parse_state, lex_result.tokens, lexer.path);
parse_result := parse(*parse_state); parse_result := parse(*parse_state);
if parse_result.had_error { if parse_result.had_error {
@@ -334,10 +432,10 @@ compile_file :: (compiler : *Shader_Compiler, path : string) -> Compilation_Resu
variant : Shader_Variant; variant : Shader_Variant;
variant.text = codegen_result.result_text; variant.text = codegen_result.result_text;
if checker.vertex_entry_point { if checker.result.vertex_entry_point {
variant.vertex_entry_point.name = checker.vertex_entry_point.name; variant.vertex_entry_point.name = checker.result.vertex_entry_point.name;
type_variable := h2tv(*checker, checker.vertex_entry_point.type_variable); type_variable := h2tv(*checker, checker.result.vertex_entry_point.type_variable);
assert(type_variable.type == .Function); assert(type_variable.type == .Function);
node := type_variable.source_node; node := type_variable.source_node;
@@ -347,34 +445,48 @@ compile_file :: (compiler : *Shader_Compiler, path : string) -> Compilation_Resu
for child : field_list.children { for child : field_list.children {
tv := h2tv(*checker, child.type_variable); tv := h2tv(*checker, child.type_variable);
field := type_variable_to_field(*checker, tv); field := type_variable_to_field(*checker, tv);
print("%\n", pretty_print_field(*field));
array_add(*variant.vertex_entry_point.input, field); array_add(*variant.vertex_entry_point.input, field);
} }
} }
} }
} }
find_result := find_symbol(*check_result.scope_stack, "properties", xx 1); for buffer_variable : to_array(*check_result.constant_buffers) {
variable := h2tv(check_result.type_variables, buffer_variable);
cb := array_add(*result.collection.cbuffers);
for i : 0..variable.children.count - 1 {
child := variable.children[i];
field : Property_Field;
field.base_field = type_variable_to_field(*checker, h2tv(*checker, child));;
array_add(*cb.fields, field);
}
cb.buffer_index = variable.resource_index;
}
find_result := find_symbol(*check_result.scope_stack, check_result.property_name, xx 1);
if find_result { if find_result {
property_variable := h2tv(check_result.type_variables, find_result.type_variable); property_variable := h2tv(check_result.type_variables, find_result.type_variable);
for i : 0..property_variable.child_count - 1 { for i : 0..property_variable.children.count - 1 {
child := property_variable.children[i]; child := property_variable.children[i];
field := type_variable_to_field(*checker, h2tv(*checker, child)); field := type_variable_to_field(*checker, h2tv(*checker, child));
prop_field : Property_Field; prop_field : Property_Field;
prop_field.base_field = field; prop_field.base_field = field;
array_add(*result.collection.properties.fields, prop_field); array_add(*result.collection.properties.fields, prop_field);
} }
result.collection.properties.buffer_index = property_variable.buffer_index; result.collection.properties.buffer_index = property_variable.resource_index;
} }
if checker.pixel_entry_point { if checker.result.pixel_entry_point {
variant.pixel_entry_point.name = checker.pixel_entry_point.name; variant.pixel_entry_point.name = checker.result.pixel_entry_point.name;
type_variable := h2tv(*checker, checker.pixel_entry_point.type_variable); type_variable := h2tv(*checker, checker.result.pixel_entry_point.type_variable);
assert(type_variable.type == .Function); assert(type_variable.type == .Function);
field := type_variable_to_field(*checker, type_variable.return_var); field := type_variable_to_field(*checker, type_variable.return_type_variable);
for hint : type_variable.source_node.hint_tokens { for hint : type_variable.source_node.hint_tokens {
field_hint : Field_Hint; field_hint : Field_Hint;
@@ -399,7 +511,6 @@ compile_file :: (compiler : *Shader_Compiler, path : string) -> Compilation_Resu
} }
variant.pixel_entry_point.return_value = field; variant.pixel_entry_point.return_value = field;
print("%\n", pretty_print_field(*field));
} }
array_add(*result.collection.variants, variant); array_add(*result.collection.variants, variant);

1
modules/ncore Submodule

Submodule modules/ncore added at 9db7ff0940

5
test/arrays.shd Normal file
View File

@@ -0,0 +1,5 @@
vertex main :: () -> float4 @position {
arr : [16].float4;
arr[0] = float4(1,1,1);
return arr[0];
}

View File

@@ -1,5 +1,5 @@
void vs_main() void vs_main()
{ {
float x = 2.0f + 5.0f; float x = (2.0f + 5.0f);
} }

View File

@@ -1,8 +1,9 @@
cbuffer __PROPERTIES : register(b0) cbuffer __PROPERTIES : register(b0)
{ {
float4 color; float4 __PROPERTIES__color;
} }
float3 vs_main(float3 pos : POSITION) : SV_POSITION float3 vs_main(float3 pos : POSITION) : SV_POSITION
{ {
return pos; return pos;
@@ -10,6 +11,6 @@ float3 vs_main(float3 pos : POSITION) : SV_POSITION
float4 ps_main() : SV_TARGET float4 ps_main() : SV_TARGET
{ {
return color; return __PROPERTIES__color;
} }

View File

@@ -2,6 +2,6 @@ void vs_main()
{ {
float x = 5.0f; float x = 5.0f;
float y = 3000.0f; float y = 3000.0f;
float z = y * y + x; float z = ((y * y) + x);
} }

View File

@@ -1,4 +1,2 @@
struct Foo; struct Foo {};
struct Foo {}

View File

@@ -1,15 +1,16 @@
cbuffer __PROPERTIES : register(b0) cbuffer __PROPERTIES : register(b0)
{ {
float4 color; float4 __PROPERTIES__color;
} }
float3 vs_main(float3 pos : POSITION, float2 uv) : SV_POSITION
float3 vs_main(float3 pos : POSITION, float2 uv : TEXCOORD0) : SV_POSITION
{ {
return pos; return pos;
} }
float4 ps_main() : SV_TARGET float4 ps_main() : SV_TARGET
{ {
return color; return __PROPERTIES__color;
} }

View File

@@ -8,7 +8,7 @@ int foo()
float bar() float bar()
{ {
return 1235.0f * 500; return (1235.0f * 500);
} }
void vs_main() void vs_main()

View File

@@ -1,15 +1,13 @@
struct Foo;
float foo(Foo f); float foo(Foo f);
struct Foo struct Foo
{ {
float some_data; float some_data;
} };
float foo(Foo f) float foo(Foo f)
{ {
return f.some_data * 2.0f; return (f.some_data * 2.0f);
} }
void vs_main() void vs_main()

View File

@@ -1,9 +1,7 @@
struct Data;
struct Data struct Data
{ {
float4 color; float4 color;
} };
void vs_main() void vs_main()
{ {

View File

@@ -1,15 +1,12 @@
struct Foo;
struct Bar;
struct Foo struct Foo
{ {
float4 color; float4 color;
} };
struct Bar struct Bar
{ {
Foo t; Foo t;
} };
void vs_main() void vs_main()
{ {

View File

@@ -0,0 +1,29 @@
struct PS_Input;
cbuffer __PROPERTIES : register(b0)
{
}
Texture2D texture : register(t0);
Sampler sampler : register(s0);
struct PS_Input
{
float2 uv;
float4 pos : POSITION;
}
PS_Input vs_main(float4 pos : POSITION, float2 uv)
{
PS_Input result;
result.uv = uv;
result.pos = pos;
return result;
}
float4 ps_main(PS_Input input) : SV_TARGET
{
float4 color = texture.sample(input.uv, sampler);
return color;
}

View File

@@ -1,6 +1,7 @@
test/assign_arithmetic_expression.shd codegen test/assign_arithmetic_expression.shd codegen
test/basic_property_and_return_value.shd codegen test/basic_property_and_return_value.shd codegen
test/complicated_computation.shd codegen test/complicated_computation.shd codegen
test/constant_buffer.shd codegen
test/empty_struct.shd codegen test/empty_struct.shd codegen
test/empty_vertex_main.shd codegen test/empty_vertex_main.shd codegen
test/empty_vertex_main_with_position_parameter.shd codegen test/empty_vertex_main_with_position_parameter.shd codegen

14
test/constant_buffer.shd Normal file
View File

@@ -0,0 +1,14 @@
camera :: constant_buffer {
projection : float4x4;
view : float4x4;
}
vertex main :: (pos : float4 @position) -> float4 @position {
mv : float4 = mul(camera.view, pos);
mvp : float4 = mul(camera.projection, mv);
return mvp;
}
pixel main :: () -> float4 @target {
return float4(0.5, 0.5, 0.5, 1.0);
}

7
test/double_access.shd Normal file
View File

@@ -0,0 +1,7 @@
p :: properties {
v : float2;
}
vertex main ::() {
x : float = p.v.x / p.v.y;
}

View File

@@ -1,3 +1,3 @@
vertex main :: (pos : float3) -> int { vertex main :: (pos : float3) -> int {
return 0;
} }

42
test/large_block.shd Normal file
View File

@@ -0,0 +1,42 @@
p :: properties {
color : float4;
rect_position : float2;
rect_scale : float2;
resolution : float2;
texture : Texture2D;
sampler : Sampler;
}
PS_Input :: struct {
uv : float2 @uv;
pos : float4 @pos;
}
vertex main :: (pos : float4 @position) -> PS_Input {
res : float2 = p.resolution;
scale : float2 = p.rect_scale;
rect_pos : float2 = p.rect_position;;
center : float2 = rect_pos;
half_size : float2 = float2(scale.x / 2, scale.y / 2);
dst_pos : float4 = float4(pos.x * half_size.x + center.x, pos.y * half_size.y + center.y, 0.0, 1.0);
result : PS_Input;
src_p0 : float2 = float2(0.0, 1.0);
src_p1 : float2 = float2(1.0, 0.0);
src_half_size : float2 = (src_p1 - src_p0) / 2;
src_center : float2 = (src_p1 + src_p0) / 2;
src_pos : float2 = float2(pos.x, pos.y) * src_half_size + src_center;
result.uv = float2(1, 1);
result.pos = float4(2.0 * dst_pos.x / res.x - 1, 2.0 * dst_pos.y / res.y - 1, 0.0, 1.0);
return result;
}
pixel main :: (input : PS_Input) -> float4 @target0 {
color : float4 = p.color;
return color;
}

40
test/lex/arrays.golden Normal file
View File

@@ -0,0 +1,40 @@
{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 16 ; length = 1 line = 1 ; column = 16 ; value =')'; }
{kind = TOKEN_ARROW; ; index = 18 ; length = 2 line = 1 ; column = 18 ; value ='->'; }
{kind = TOKEN_IDENTIFIER; ; index = 21 ; length = 6 line = 1 ; column = 21 ; value ='float4'; }
{kind = TOKEN_AT; ; index = 28 ; length = 1 line = 1 ; column = 28 ; value ='@'; }
{kind = TOKEN_IDENTIFIER; ; index = 29 ; length = 8 line = 1 ; column = 29 ; value ='position'; }
{kind = TOKEN_LEFTBRACE; ; index = 38 ; length = 1 line = 1 ; column = 38 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 42 ; length = 3 line = 2 ; column = 0 ; value ='arr'; }
{kind = TOKEN_COLON; ; index = 46 ; length = 1 line = 2 ; column = 4 ; value =':'; }
{kind = TOKEN_LEFTBRACKET; ; index = 48 ; length = 1 line = 2 ; column = 6 ; value ='['; }
{kind = TOKEN_INTLITERAL; ; index = 49 ; length = 2 line = 2 ; column = 7 ; value ='16'; }
{kind = TOKEN_RIGHTBRACKET; ; index = 51 ; length = 1 line = 2 ; column = 9 ; value =']'; }
{kind = TOKEN_DOT; ; index = 52 ; length = 1 line = 2 ; column = 10 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 53 ; length = 6 line = 2 ; column = 11 ; value ='float4'; }
{kind = TOKEN_SEMICOLON; ; index = 59 ; length = 1 line = 2 ; column = 17 ; value =';'; }
{kind = TOKEN_IDENTIFIER; ; index = 63 ; length = 3 line = 3 ; column = 0 ; value ='arr'; }
{kind = TOKEN_LEFTBRACKET; ; index = 66 ; length = 1 line = 3 ; column = 3 ; value ='['; }
{kind = TOKEN_INTLITERAL; ; index = 67 ; length = 1 line = 3 ; column = 4 ; value ='0'; }
{kind = TOKEN_RIGHTBRACKET; ; index = 68 ; length = 1 line = 3 ; column = 5 ; value =']'; }
{kind = TOKEN_ASSIGN; ; index = 70 ; length = 1 line = 3 ; column = 7 ; value ='='; }
{kind = TOKEN_IDENTIFIER; ; index = 72 ; length = 6 line = 3 ; column = 9 ; value ='float4'; }
{kind = TOKEN_LEFTPAREN; ; index = 78 ; length = 1 line = 3 ; column = 15 ; value ='('; }
{kind = TOKEN_INTLITERAL; ; index = 79 ; length = 1 line = 3 ; column = 16 ; value ='1'; }
{kind = TOKEN_COMMA; ; index = 80 ; length = 1 line = 3 ; column = 17 ; value =','; }
{kind = TOKEN_INTLITERAL; ; index = 81 ; length = 1 line = 3 ; column = 18 ; value ='1'; }
{kind = TOKEN_COMMA; ; index = 82 ; length = 1 line = 3 ; column = 19 ; value =','; }
{kind = TOKEN_INTLITERAL; ; index = 83 ; length = 1 line = 3 ; column = 20 ; value ='1'; }
{kind = TOKEN_RIGHTPAREN; ; index = 84 ; length = 1 line = 3 ; column = 21 ; value =')'; }
{kind = TOKEN_SEMICOLON; ; index = 85 ; length = 1 line = 3 ; column = 22 ; value =';'; }
{kind = TOKEN_RETURN; ; index = 89 ; length = 6 line = 4 ; column = 0 ; value ='return'; }
{kind = TOKEN_IDENTIFIER; ; index = 96 ; length = 3 line = 4 ; column = 7 ; value ='arr'; }
{kind = TOKEN_LEFTBRACKET; ; index = 99 ; length = 1 line = 4 ; column = 10 ; value ='['; }
{kind = TOKEN_INTLITERAL; ; index = 100 ; length = 1 line = 4 ; column = 11 ; value ='0'; }
{kind = TOKEN_RIGHTBRACKET; ; index = 101 ; length = 1 line = 4 ; column = 12 ; value =']'; }
{kind = TOKEN_SEMICOLON; ; index = 102 ; length = 1 line = 4 ; column = 13 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 105 ; length = 1 line = 5 ; column = 0 ; value ='}'; }
{kind = TOKEN_EOF; ; index = 108 ; length = 0 line = 6 ; column = 0 ; value =''; }

View File

@@ -0,0 +1,66 @@
{kind = TOKEN_IDENTIFIER; ; index = 0 ; length = 11 line = 1 ; column = 0 ; value ='Camera_Data'; }
{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; }
{kind = TOKEN_CONSTANT_BUFFER; ; index = 15 ; length = 15 line = 1 ; column = 15 ; value ='constant_buffer'; }
{kind = TOKEN_LEFTBRACE; ; index = 31 ; length = 1 line = 1 ; column = 31 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 35 ; length = 10 line = 2 ; column = 0 ; value ='projection'; }
{kind = TOKEN_COLON; ; index = 46 ; length = 1 line = 2 ; column = 11 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 48 ; length = 8 line = 2 ; column = 13 ; value ='float4x4'; }
{kind = TOKEN_SEMICOLON; ; index = 56 ; length = 1 line = 2 ; column = 21 ; value =';'; }
{kind = TOKEN_IDENTIFIER; ; index = 60 ; length = 4 line = 3 ; column = 0 ; value ='view'; }
{kind = TOKEN_COLON; ; index = 71 ; length = 1 line = 3 ; column = 11 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 73 ; length = 8 line = 3 ; column = 13 ; value ='float4x4'; }
{kind = TOKEN_SEMICOLON; ; index = 81 ; length = 1 line = 3 ; column = 21 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 84 ; length = 1 line = 4 ; column = 0 ; value ='}'; }
{kind = TOKEN_VERTEX; ; index = 89 ; length = 6 line = 6 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 96 ; length = 4 line = 6 ; column = 7 ; value ='main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 101 ; length = 2 line = 6 ; column = 12 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 104 ; length = 1 line = 6 ; column = 15 ; value ='('; }
{kind = TOKEN_IDENTIFIER; ; index = 105 ; length = 3 line = 6 ; column = 16 ; value ='pos'; }
{kind = TOKEN_COLON; ; index = 109 ; length = 1 line = 6 ; column = 20 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 111 ; length = 6 line = 6 ; column = 22 ; value ='float4'; }
{kind = TOKEN_AT; ; index = 118 ; length = 1 line = 6 ; column = 29 ; value ='@'; }
{kind = TOKEN_IDENTIFIER; ; index = 119 ; length = 8 line = 6 ; column = 30 ; value ='position'; }
{kind = TOKEN_RIGHTPAREN; ; index = 127 ; length = 1 line = 6 ; column = 38 ; value =')'; }
{kind = TOKEN_ARROW; ; index = 129 ; length = 2 line = 6 ; column = 40 ; value ='->'; }
{kind = TOKEN_IDENTIFIER; ; index = 132 ; length = 6 line = 6 ; column = 43 ; value ='float4'; }
{kind = TOKEN_AT; ; index = 139 ; length = 1 line = 6 ; column = 50 ; value ='@'; }
{kind = TOKEN_IDENTIFIER; ; index = 140 ; length = 8 line = 6 ; column = 51 ; value ='position'; }
{kind = TOKEN_LEFTBRACE; ; index = 149 ; length = 1 line = 6 ; column = 60 ; value ='{'; }
{kind = TOKEN_RETURN; ; index = 153 ; length = 6 line = 7 ; column = 0 ; value ='return'; }
{kind = TOKEN_IDENTIFIER; ; index = 160 ; length = 3 line = 7 ; column = 7 ; value ='mul'; }
{kind = TOKEN_LEFTPAREN; ; index = 163 ; length = 1 line = 7 ; column = 10 ; value ='('; }
{kind = TOKEN_IDENTIFIER; ; index = 164 ; length = 10 line = 7 ; column = 11 ; value ='projection'; }
{kind = TOKEN_COMMA; ; index = 174 ; length = 1 line = 7 ; column = 21 ; value =','; }
{kind = TOKEN_IDENTIFIER; ; index = 176 ; length = 3 line = 7 ; column = 23 ; value ='mul'; }
{kind = TOKEN_LEFTPAREN; ; index = 179 ; length = 1 line = 7 ; column = 26 ; value ='('; }
{kind = TOKEN_IDENTIFIER; ; index = 180 ; length = 4 line = 7 ; column = 27 ; value ='view'; }
{kind = TOKEN_COMMA; ; index = 184 ; length = 1 line = 7 ; column = 31 ; value =','; }
{kind = TOKEN_IDENTIFIER; ; index = 186 ; length = 3 line = 7 ; column = 33 ; value ='pos'; }
{kind = TOKEN_RIGHTPAREN; ; index = 189 ; length = 1 line = 7 ; column = 36 ; value =')'; }
{kind = TOKEN_RIGHTPAREN; ; index = 190 ; length = 1 line = 7 ; column = 37 ; value =')'; }
{kind = TOKEN_SEMICOLON; ; index = 191 ; length = 1 line = 7 ; column = 38 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 194 ; length = 1 line = 8 ; column = 0 ; value ='}'; }
{kind = TOKEN_PIXEL; ; index = 199 ; length = 5 line = 10 ; column = 0 ; value ='pixel'; }
{kind = TOKEN_IDENTIFIER; ; index = 205 ; length = 4 line = 10 ; column = 6 ; value ='main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 210 ; length = 2 line = 10 ; column = 11 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 213 ; length = 1 line = 10 ; column = 14 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 214 ; length = 1 line = 10 ; column = 15 ; value =')'; }
{kind = TOKEN_ARROW; ; index = 216 ; length = 2 line = 10 ; column = 17 ; value ='->'; }
{kind = TOKEN_IDENTIFIER; ; index = 219 ; length = 6 line = 10 ; column = 20 ; value ='float4'; }
{kind = TOKEN_AT; ; index = 226 ; length = 1 line = 10 ; column = 27 ; value ='@'; }
{kind = TOKEN_IDENTIFIER; ; index = 227 ; length = 6 line = 10 ; column = 28 ; value ='target'; }
{kind = TOKEN_LEFTBRACE; ; index = 234 ; length = 1 line = 10 ; column = 35 ; value ='{'; }
{kind = TOKEN_RETURN; ; index = 238 ; length = 6 line = 11 ; column = 0 ; value ='return'; }
{kind = TOKEN_IDENTIFIER; ; index = 245 ; length = 5 line = 11 ; column = 7 ; value ='float'; }
{kind = TOKEN_LEFTPAREN; ; index = 250 ; length = 1 line = 11 ; column = 12 ; value ='('; }
{kind = TOKEN_FLOATLITERAL; ; index = 251 ; length = 3 line = 11 ; column = 13 ; value ='0.5'; }
{kind = TOKEN_COMMA; ; index = 254 ; length = 1 line = 11 ; column = 16 ; value =','; }
{kind = TOKEN_FLOATLITERAL; ; index = 256 ; length = 3 line = 11 ; column = 18 ; value ='0.5'; }
{kind = TOKEN_COMMA; ; index = 259 ; length = 1 line = 11 ; column = 21 ; value =','; }
{kind = TOKEN_FLOATLITERAL; ; index = 261 ; length = 3 line = 11 ; column = 23 ; value ='0.5'; }
{kind = TOKEN_COMMA; ; index = 264 ; length = 1 line = 11 ; column = 26 ; value =','; }
{kind = TOKEN_FLOATLITERAL; ; index = 266 ; length = 3 line = 11 ; column = 28 ; value ='1'; }
{kind = TOKEN_RIGHTPAREN; ; index = 269 ; length = 1 line = 11 ; column = 31 ; value =')'; }
{kind = TOKEN_SEMICOLON; ; index = 270 ; length = 1 line = 11 ; column = 32 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 273 ; length = 1 line = 12 ; column = 0 ; value ='}'; }
{kind = TOKEN_EOF; ; index = 276 ; length = 0 line = 13 ; column = 0 ; value =''; }

View File

@@ -9,5 +9,8 @@
{kind = TOKEN_ARROW; ; index = 30 ; length = 2 line = 1 ; column = 30 ; value ='->'; } {kind = TOKEN_ARROW; ; index = 30 ; length = 2 line = 1 ; column = 30 ; value ='->'; }
{kind = TOKEN_IDENTIFIER; ; index = 33 ; length = 3 line = 1 ; column = 33 ; value ='int'; } {kind = TOKEN_IDENTIFIER; ; index = 33 ; length = 3 line = 1 ; column = 33 ; value ='int'; }
{kind = TOKEN_LEFTBRACE; ; index = 37 ; length = 1 line = 1 ; column = 37 ; value ='{'; } {kind = TOKEN_LEFTBRACE; ; index = 37 ; length = 1 line = 1 ; column = 37 ; value ='{'; }
{kind = TOKEN_RIGHTBRACE; ; index = 43 ; length = 1 line = 3 ; column = 0 ; value ='}'; } {kind = TOKEN_RETURN; ; index = 41 ; length = 6 line = 2 ; column = 0 ; value ='return'; }
{kind = TOKEN_EOF; ; index = 46 ; length = 0 line = 4 ; column = 0 ; value =''; } {kind = TOKEN_INTLITERAL; ; index = 48 ; length = 1 line = 2 ; column = 7 ; value ='0'; }
{kind = TOKEN_SEMICOLON; ; index = 49 ; length = 1 line = 2 ; column = 8 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 52 ; length = 1 line = 3 ; column = 0 ; value ='}'; }
{kind = TOKEN_EOF; ; index = 55 ; length = 0 line = 4 ; column = 0 ; value =''; }

View File

@@ -0,0 +1,107 @@
{kind = TOKEN_IDENTIFIER; ; index = 0 ; length = 1 line = 1 ; column = 0 ; value ='p'; }
{kind = TOKEN_DOUBLECOLON; ; index = 2 ; length = 2 line = 1 ; column = 2 ; value ='::'; }
{kind = TOKEN_PROPERTIES; ; index = 5 ; length = 10 line = 1 ; column = 5 ; value ='properties'; }
{kind = TOKEN_DOUBLECOLON; ; index = 16 ; length = 2 line = 1 ; column = 16 ; value ='::'; }
{kind = TOKEN_LEFTBRACE; ; index = 19 ; length = 1 line = 1 ; column = 19 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 23 ; length = 7 line = 2 ; column = 0 ; value ='texture'; }
{kind = TOKEN_COLON; ; index = 31 ; length = 1 line = 2 ; column = 8 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 33 ; length = 9 line = 2 ; column = 10 ; value ='texture2D'; }
{kind = TOKEN_SEMICOLON; ; index = 42 ; length = 1 line = 2 ; column = 19 ; value =';'; }
{kind = TOKEN_IDENTIFIER; ; index = 46 ; length = 7 line = 3 ; column = 0 ; value ='sampler'; }
{kind = TOKEN_COLON; ; index = 54 ; length = 1 line = 3 ; column = 8 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 56 ; length = 7 line = 3 ; column = 10 ; value ='sampler'; }
{kind = TOKEN_SEMICOLON; ; index = 63 ; length = 1 line = 3 ; column = 17 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 66 ; length = 1 line = 4 ; column = 0 ; value ='}'; }
{kind = TOKEN_IDENTIFIER; ; index = 71 ; length = 8 line = 6 ; column = 0 ; value ='PS_Input'; }
{kind = TOKEN_DOUBLECOLON; ; index = 80 ; length = 2 line = 6 ; column = 9 ; value ='::'; }
{kind = TOKEN_STRUCT; ; index = 83 ; length = 6 line = 6 ; column = 12 ; value ='struct'; }
{kind = TOKEN_LEFTBRACE; ; index = 90 ; length = 1 line = 6 ; column = 19 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 94 ; length = 2 line = 7 ; column = 0 ; value ='uv'; }
{kind = TOKEN_COLON; ; index = 98 ; length = 1 line = 7 ; column = 4 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 100 ; length = 6 line = 7 ; column = 6 ; value ='float2'; }
{kind = TOKEN_AT; ; index = 107 ; length = 1 line = 7 ; column = 13 ; value ='@'; }
{kind = TOKEN_IDENTIFIER; ; index = 108 ; length = 2 line = 7 ; column = 14 ; value ='uv'; }
{kind = TOKEN_SEMICOLON; ; index = 110 ; length = 1 line = 7 ; column = 16 ; value =';'; }
{kind = TOKEN_IDENTIFIER; ; index = 114 ; length = 3 line = 8 ; column = 0 ; value ='pos'; }
{kind = TOKEN_COLON; ; index = 118 ; length = 1 line = 8 ; column = 4 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 120 ; length = 6 line = 8 ; column = 6 ; value ='float4'; }
{kind = TOKEN_AT; ; index = 127 ; length = 1 line = 8 ; column = 13 ; value ='@'; }
{kind = TOKEN_IDENTIFIER; ; index = 128 ; length = 8 line = 8 ; column = 14 ; value ='position'; }
{kind = TOKEN_SEMICOLON; ; index = 136 ; length = 1 line = 8 ; column = 22 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 139 ; length = 1 line = 9 ; column = 0 ; value ='}'; }
{kind = TOKEN_VERTEX; ; index = 144 ; length = 6 line = 11 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 151 ; length = 4 line = 11 ; column = 7 ; value ='main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 156 ; length = 2 line = 11 ; column = 12 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 159 ; length = 1 line = 11 ; column = 15 ; value ='('; }
{kind = TOKEN_IDENTIFIER; ; index = 160 ; length = 3 line = 11 ; column = 16 ; value ='pos'; }
{kind = TOKEN_COLON; ; index = 164 ; length = 1 line = 11 ; column = 20 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 166 ; length = 6 line = 11 ; column = 22 ; value ='float4'; }
{kind = TOKEN_AT; ; index = 173 ; length = 1 line = 11 ; column = 29 ; value ='@'; }
{kind = TOKEN_IDENTIFIER; ; index = 174 ; length = 8 line = 11 ; column = 30 ; value ='position'; }
{kind = TOKEN_COMMA; ; index = 182 ; length = 1 line = 11 ; column = 38 ; value =','; }
{kind = TOKEN_IDENTIFIER; ; index = 184 ; length = 2 line = 11 ; column = 40 ; value ='uv'; }
{kind = TOKEN_COLON; ; index = 187 ; length = 1 line = 11 ; column = 43 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 189 ; length = 6 line = 11 ; column = 45 ; value ='float2'; }
{kind = TOKEN_AT; ; index = 196 ; length = 1 line = 11 ; column = 52 ; value ='@'; }
{kind = TOKEN_IDENTIFIER; ; index = 197 ; length = 2 line = 11 ; column = 53 ; value ='uv'; }
{kind = TOKEN_RIGHTPAREN; ; index = 199 ; length = 1 line = 11 ; column = 55 ; value =')'; }
{kind = TOKEN_ARROW; ; index = 201 ; length = 2 line = 11 ; column = 57 ; value ='->'; }
{kind = TOKEN_IDENTIFIER; ; index = 204 ; length = 8 line = 11 ; column = 60 ; value ='PS_Input'; }
{kind = TOKEN_LEFTBRACE; ; index = 213 ; length = 1 line = 11 ; column = 69 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 217 ; length = 6 line = 12 ; column = 0 ; value ='result'; }
{kind = TOKEN_COLON; ; index = 224 ; length = 1 line = 12 ; column = 7 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 226 ; length = 8 line = 12 ; column = 9 ; value ='PS_Input'; }
{kind = TOKEN_SEMICOLON; ; index = 234 ; length = 1 line = 12 ; column = 17 ; value =';'; }
{kind = TOKEN_IDENTIFIER; ; index = 240 ; length = 6 line = 14 ; column = 0 ; value ='result'; }
{kind = TOKEN_DOT; ; index = 246 ; length = 1 line = 14 ; column = 6 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 247 ; length = 2 line = 14 ; column = 7 ; value ='uv'; }
{kind = TOKEN_ASSIGN; ; index = 250 ; length = 1 line = 14 ; column = 10 ; value ='='; }
{kind = TOKEN_IDENTIFIER; ; index = 252 ; length = 2 line = 14 ; column = 12 ; value ='uv'; }
{kind = TOKEN_SEMICOLON; ; index = 254 ; length = 1 line = 14 ; column = 14 ; value =';'; }
{kind = TOKEN_IDENTIFIER; ; index = 258 ; length = 6 line = 15 ; column = 0 ; value ='result'; }
{kind = TOKEN_DOT; ; index = 264 ; length = 1 line = 15 ; column = 6 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 265 ; length = 3 line = 15 ; column = 7 ; value ='pos'; }
{kind = TOKEN_ASSIGN; ; index = 269 ; length = 1 line = 15 ; column = 11 ; value ='='; }
{kind = TOKEN_IDENTIFIER; ; index = 271 ; length = 3 line = 15 ; column = 13 ; value ='pos'; }
{kind = TOKEN_SEMICOLON; ; index = 274 ; length = 1 line = 15 ; column = 16 ; value =';'; }
{kind = TOKEN_RETURN; ; index = 280 ; length = 6 line = 17 ; column = 0 ; value ='return'; }
{kind = TOKEN_IDENTIFIER; ; index = 287 ; length = 6 line = 17 ; column = 7 ; value ='result'; }
{kind = TOKEN_SEMICOLON; ; index = 293 ; length = 1 line = 17 ; column = 13 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 296 ; length = 1 line = 18 ; column = 0 ; value ='}'; }
{kind = TOKEN_PIXEL; ; index = 301 ; length = 5 line = 20 ; column = 0 ; value ='pixel'; }
{kind = TOKEN_IDENTIFIER; ; index = 307 ; length = 4 line = 20 ; column = 6 ; value ='main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 312 ; length = 2 line = 20 ; column = 11 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 315 ; length = 1 line = 20 ; column = 14 ; value ='('; }
{kind = TOKEN_IDENTIFIER; ; index = 316 ; length = 5 line = 20 ; column = 15 ; value ='input'; }
{kind = TOKEN_COLON; ; index = 322 ; length = 1 line = 20 ; column = 21 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 324 ; length = 8 line = 20 ; column = 23 ; value ='PS_Input'; }
{kind = TOKEN_RIGHTPAREN; ; index = 332 ; length = 1 line = 20 ; column = 31 ; value =')'; }
{kind = TOKEN_ARROW; ; index = 334 ; length = 2 line = 20 ; column = 33 ; value ='->'; }
{kind = TOKEN_IDENTIFIER; ; index = 337 ; length = 6 line = 20 ; column = 36 ; value ='float4'; }
{kind = TOKEN_AT; ; index = 344 ; length = 1 line = 20 ; column = 43 ; value ='@'; }
{kind = TOKEN_IDENTIFIER; ; index = 345 ; length = 6 line = 20 ; column = 44 ; value ='target'; }
{kind = TOKEN_LEFTBRACE; ; index = 352 ; length = 1 line = 20 ; column = 51 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 356 ; length = 5 line = 21 ; column = 0 ; value ='color'; }
{kind = TOKEN_COLON; ; index = 362 ; length = 1 line = 21 ; column = 6 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 364 ; length = 6 line = 21 ; column = 8 ; value ='float4'; }
{kind = TOKEN_ASSIGN; ; index = 371 ; length = 1 line = 21 ; column = 15 ; value ='='; }
{kind = TOKEN_IDENTIFIER; ; index = 373 ; length = 6 line = 21 ; column = 17 ; value ='sample'; }
{kind = TOKEN_LEFTPAREN; ; index = 379 ; length = 1 line = 21 ; column = 23 ; value ='('; }
{kind = TOKEN_IDENTIFIER; ; index = 380 ; length = 1 line = 21 ; column = 24 ; value ='p'; }
{kind = TOKEN_DOT; ; index = 381 ; length = 1 line = 21 ; column = 25 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 382 ; length = 7 line = 21 ; column = 26 ; value ='texture'; }
{kind = TOKEN_COMMA; ; index = 389 ; length = 1 line = 21 ; column = 33 ; value =','; }
{kind = TOKEN_IDENTIFIER; ; index = 391 ; length = 5 line = 21 ; column = 35 ; value ='input'; }
{kind = TOKEN_DOT; ; index = 396 ; length = 1 line = 21 ; column = 40 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 397 ; length = 2 line = 21 ; column = 41 ; value ='uv'; }
{kind = TOKEN_COMMA; ; index = 399 ; length = 1 line = 21 ; column = 43 ; value =','; }
{kind = TOKEN_IDENTIFIER; ; index = 401 ; length = 1 line = 21 ; column = 45 ; value ='p'; }
{kind = TOKEN_DOT; ; index = 402 ; length = 1 line = 21 ; column = 46 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 403 ; length = 7 line = 21 ; column = 47 ; value ='sampler'; }
{kind = TOKEN_RIGHTPAREN; ; index = 410 ; length = 1 line = 21 ; column = 54 ; value =')'; }
{kind = TOKEN_SEMICOLON; ; index = 411 ; length = 1 line = 21 ; column = 55 ; value =';'; }
{kind = TOKEN_RETURN; ; index = 415 ; length = 6 line = 22 ; column = 0 ; value ='return'; }
{kind = TOKEN_IDENTIFIER; ; index = 422 ; length = 5 line = 22 ; column = 7 ; value ='color'; }
{kind = TOKEN_SEMICOLON; ; index = 427 ; length = 1 line = 22 ; column = 12 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 430 ; length = 1 line = 23 ; column = 0 ; value ='}'; }
{kind = TOKEN_EOF; ; index = 433 ; length = 0 line = 24 ; column = 0 ; value =''; }

View File

@@ -1,6 +1,7 @@
test/assign_arithmetic_expression.shd lex test/assign_arithmetic_expression.shd lex
test/basic_property_and_return_value.shd lex test/basic_property_and_return_value.shd lex
test/complicated_computation.shd lex test/complicated_computation.shd lex
test/constant_buffer.shd lex
test/empty_struct.shd lex test/empty_struct.shd lex
test/empty_vertex_main.shd lex test/empty_vertex_main.shd lex
test/empty_vertex_main_with_position_parameter.shd lex test/empty_vertex_main_with_position_parameter.shd lex

6
test/parse/arrays.golden Normal file
View File

@@ -0,0 +1,6 @@
(program
(fun vertex vs_main -> float4 (@position)
[]
(:= arr [16].float4)
(= arr[0] (float4 1 1 1))
(return arr[0])))

View File

@@ -2,4 +2,5 @@
(fun vertex vs_main -> float4 (@position) (fun vertex vs_main -> float4 (@position)
[(:= pos float4 (@position))] [(:= pos float4 (@position))]
(:= x float 5) (:= x float 5)
(= x 7))) (= x 7)
(return pos)))

View File

@@ -1,3 +1,4 @@
(program (program
(fun vertex vs_main -> int (fun vertex vs_main -> int
[(:= pos float3)])) [(:= pos float3)]
(return 0)))

View File

@@ -0,0 +1,21 @@
(program
(properties p
[(:= texture texture2D)
(:= sampler sampler)])
(struct PS_Input
[(:= uv float2 (@uv))
(:= pos float4 (@position))])
(fun vertex vs_main -> PS_Input
[(:= pos float4 (@position))
(:= uv float2 (@uv))]
(:= result PS_Input)
(= result.uv uv)
(= result.pos pos)
(return result))
(fun pixel ps_main -> float4 (@target)
[(:= input PS_Input)]
(:= color float4 (sample p.texture input.uv p.sampler))
(return color)))

View File

@@ -1,6 +1,7 @@
test/assign_arithmetic_expression.shd parse test/assign_arithmetic_expression.shd parse
test/basic_property_and_return_value.shd parse test/basic_property_and_return_value.shd parse
test/complicated_computation.shd parse test/complicated_computation.shd parse
test/constant_buffer.shd parse
test/empty_struct.shd parse test/empty_struct.shd parse
test/empty_vertex_main.shd parse test/empty_vertex_main.shd parse
test/empty_vertex_main_with_position_parameter.shd parse test/empty_vertex_main_with_position_parameter.shd parse

View File

@@ -0,0 +1,15 @@
scope (global) [
[pixel__ps_main] : () -> float4
[vertex__vs_main] : (pos : float4) -> float4
[camera] : {projection : float4x4, view : float4x4}
scope (camera) [
[projection] : float4x4
[view] : float4x4
]
scope (vertex__vs_main) [
[pos] : float4
[mv] : float4
[mvp] : float4
]
scope (pixel__ps_main) []
]

View File

@@ -1,5 +1,5 @@
scope (global) [ scope (global) [
[vertex__vs_main] : (pos : float4) [vertex__vs_main] : (pos : float4) -> float4
scope (vertex__vs_main) [ scope (vertex__vs_main) [
[x] : float [x] : float
[pos] : float4 [pos] : float4

View File

@@ -1,5 +1,5 @@
scope (global) [ scope (global) [
[vertex__vs_main] : (pos : float3) [vertex__vs_main] : (pos : float3) -> int
scope (vertex__vs_main) [ scope (vertex__vs_main) [
[pos] : float3 [pos] : float3
] ]

View File

@@ -6,6 +6,6 @@
float float
got: got:
res : float2 = float2(2.0, 2.0) res : float2 = float2(2.0, 2.0);
 

View File

@@ -7,7 +7,7 @@
 color : float4 = float4(y, 1.0, 1.0, 1.0);  color : float4 = float4(y, 1.0, 1.0, 1.0);
^ ^
 Possible overloads:  Possible overloads:
 foreign float4 :: (float, float, float, float) -> float4; (test/wrong_type_for_function.shd:79)  foreign float4 :: (float, float, float, float) -> float4; (test/wrong_type_for_function.shd:78)
test/wrong_type_for_function.shd:11,24: error: Type mismatch. Expected float got float2 test/wrong_type_for_function.shd:11,24: error: Type mismatch. Expected float got float2
 found:  found:

View File

@@ -1,12 +1,11 @@
test/assign_arithmetic_expression.shd semant test/assign_arithmetic_expression.shd semant
test/basic_property_and_return_value.shd semant test/basic_property_and_return_value.shd semant
test/complicated_computation.shd semant test/complicated_computation.shd semant
test/constant_buffer.shd semant
test/empty_struct.shd semant test/empty_struct.shd semant
test/empty_vertex_main.shd semant test/empty_vertex_main.shd semant
test/empty_vertex_main_with_position_parameter.shd semant test/empty_vertex_main_with_position_parameter.shd semant
test/field_assignment.shd semant test/field_assignment.shd semant
test/field_without_type_specifier.shd semant
test/float_suffix.shd semant
test/function_call.shd semant test/function_call.shd semant
test/function_call_out_of_order_declaration.shd semant test/function_call_out_of_order_declaration.shd semant
test/function_call_return.shd semant test/function_call_return.shd semant

View File

@@ -0,0 +1,14 @@
vertex main :: (pos : float4 @position) -> float4 @position {
src_p0 : float2 = float2(0.0, 1.0);
src_p1 : float2 = float2(1.0, 0.0);
src_half_size : float2 = (src_p1 - src_p0) / 2;
src_center : float2 = (src_p1 + src_p0) / 2;
src_pos : float2 = float2(pos.x, pos.y) * src_half_size + src_center;
return float4(1, 1, 1, 1);
}
pixel main :: () -> float4 @target0 {
return float4(1, 1, 1, 1);
}

23
test/texture_sample.shd Normal file
View File

@@ -0,0 +1,23 @@
p :: properties {
texture : Texture2D;
sampler : Sampler;
}
PS_Input :: struct {
uv : float2 @uv;
pos : float4 @position;
}
vertex main :: (pos : float4 @position, uv : float2 @uv) -> PS_Input {
result : PS_Input;
result.uv = uv;
result.pos = pos;
return result;
}
pixel main :: (input : PS_Input) -> float4 @target {
color : float4 = sample(p.texture, input.uv, p.sampler);
return color;
}