Compare commits
26 Commits
be4115b502
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 90fb1a035e | |||
| e365067354 | |||
| 243d83663a | |||
| 3f93e1a92d | |||
| fca325b761 | |||
| d3aa4fffeb | |||
| 6eba51cc8c | |||
| 5b237d34de | |||
| ff668b6c95 | |||
| c84516d39f | |||
| 517209c886 | |||
| d01fca146c | |||
| d9dfcc6354 | |||
| c8cd15456d | |||
| c225217676 | |||
| b2ee560145 | |||
| b475357cf9 | |||
| 76994b2567 | |||
| 0471dbe7d7 | |||
| c5758bd023 | |||
| ae54f1374e | |||
| 22b70f88b6 | |||
| 7a07c32cd2 | |||
| 92c1f593c2 | |||
| 274cb379b4 | |||
| 884444d25b |
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "modules/nbrutil"]
|
||||||
|
path = modules/ncore
|
||||||
|
url = git@git.nbross.com:nielsbross/NCore.git
|
||||||
19
AST.jai
19
AST.jai
@@ -54,6 +54,8 @@ AST_Node :: struct {
|
|||||||
|
|
||||||
token : Token;
|
token : Token;
|
||||||
|
|
||||||
|
array_field : bool;
|
||||||
|
|
||||||
source_location : Source_Range;
|
source_location : Source_Range;
|
||||||
|
|
||||||
type_variable : Type_Variable_Handle;
|
type_variable : Type_Variable_Handle;
|
||||||
@@ -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, "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
183
Codegen.jai
183
Codegen.jai
@@ -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 {
|
||||||
@@ -28,10 +38,11 @@ Codegen_Result :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init_codegen_state :: (state : *Codegen_State, root : *AST_Node, checker_result : Semantic_Check_Result, output_language : Output_Language) {
|
init_codegen_state :: (state : *Codegen_State, root : *AST_Node, checker_result : Semantic_Check_Result, output_language : Output_Language) {
|
||||||
state.root = root;
|
state.root = root;
|
||||||
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,18 +147,40 @@ 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);
|
||||||
print_to_builder(*state.builder, "%(", node.name);
|
|
||||||
|
|
||||||
if node.children.count > 0 {
|
if node.name == "sample" {
|
||||||
|
assert(node.children.count > 0);
|
||||||
args := node.children[0];
|
args := node.children[0];
|
||||||
|
|
||||||
for child : args.children {
|
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);
|
emit_node(state, child, 0);
|
||||||
|
|
||||||
if it_index != args.children.count - 1 {
|
if i != args.children.count - 1 {
|
||||||
append(*state.builder, ", ");
|
append(*state.builder, ", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
print_to_builder(*state.builder, "%(", node.name);
|
||||||
|
|
||||||
|
if node.children.count > 0 {
|
||||||
|
args := node.children[0];
|
||||||
|
|
||||||
|
for child : args.children {
|
||||||
|
emit_node(state, child, 0);
|
||||||
|
|
||||||
|
if it_index != args.children.count - 1 {
|
||||||
|
append(*state.builder, ", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
@@ -153,7 +256,7 @@ emit_function :: (state : *Codegen_State, node : *AST_Node, indentation : int, e
|
|||||||
|
|
||||||
if function_variable.return_type_variable {
|
if function_variable.return_type_variable {
|
||||||
return_variable := h2tv(state.type_variables, function_variable.return_type_variable);
|
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");
|
||||||
@@ -344,13 +462,13 @@ emit_struct :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
|
|||||||
|
|
||||||
emit_field_list(state, field_list, indentation);
|
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_cbuffer :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
|
emit_cbuffer :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
|
||||||
variable := h2tv(state.type_variables, node.type_variable);
|
variable := h2tv(state.type_variables, node.type_variable);
|
||||||
print_to_builder(*state.builder, "cbuffer % : register(b%)", variable.name, variable.buffer_index);
|
print_to_builder(*state.builder, "cbuffer % : register(b%)", variable.name, variable.resource_index);
|
||||||
|
|
||||||
current_scope := state.current_scope;
|
current_scope := state.current_scope;
|
||||||
state.current_scope = h2tv(state.type_variables, node.type_variable).scope;
|
state.current_scope = h2tv(state.type_variables, node.type_variable).scope;
|
||||||
@@ -388,20 +506,20 @@ emit_declaration :: (state : *Codegen_State, node : *AST_Node) {
|
|||||||
|
|
||||||
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
|
||||||
@@ -431,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";
|
||||||
|
|||||||
@@ -122,7 +122,10 @@ report_message :: (builder : *String_Builder, path : string, message : string, s
|
|||||||
} else {
|
} else {
|
||||||
append(builder, "internal:");
|
append(builder, "internal:");
|
||||||
}
|
}
|
||||||
print_to_builder(builder, "%,%: ", source_locations[0].main_token.line, source_locations[0].main_token.column);
|
|
||||||
|
if source_locations.count > 0 {
|
||||||
|
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: ");
|
||||||
|
|||||||
20
Lexing.jai
20
Lexing.jai
@@ -500,6 +500,25 @@ scan_next_token :: (lexer : *Lexer) -> *Token {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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 {
|
lex :: (lexer : *Lexer, allocator : Allocator = context.allocator) -> Lexing_Result {
|
||||||
lexer.result.tokens.allocator = allocator;
|
lexer.result.tokens.allocator = allocator;
|
||||||
token : *Token = scan_next_token(lexer);
|
token : *Token = scan_next_token(lexer);
|
||||||
@@ -700,3 +719,4 @@ print_from_source_location :: (source_location : Source_Range, allocator := cont
|
|||||||
|
|
||||||
|
|
||||||
#import "Basic";
|
#import "Basic";
|
||||||
|
#import "File";
|
||||||
|
|||||||
92
Parsing.jai
92
Parsing.jai
@@ -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];
|
||||||
@@ -429,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);
|
||||||
@@ -441,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;
|
||||||
@@ -588,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;
|
||||||
@@ -704,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;
|
||||||
|
|
||||||
@@ -734,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);
|
||||||
@@ -1004,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);
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,10 @@
|
|||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
//~ 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.
|
||||||
|
// [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.
|
// [x] Improve error reporting for type mismatches in general. It seems like the expect node is not always correct.
|
||||||
|
|
||||||
#load "static_array.jai";
|
|
||||||
#import "Hash_Table";
|
|
||||||
|
|
||||||
VERTEX_MAIN_FUNCTION_PREFIX :: "vertex";
|
VERTEX_MAIN_FUNCTION_PREFIX :: "vertex";
|
||||||
PIXEL_MAIN_FUNCTION_PREFIX :: "pixel";
|
PIXEL_MAIN_FUNCTION_PREFIX :: "pixel";
|
||||||
PROPERTIES_PREFIX :: "properties";
|
PROPERTIES_PREFIX :: "properties";
|
||||||
@@ -71,13 +69,13 @@ Type_Variable :: struct {
|
|||||||
struct_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;
|
||||||
|
|
||||||
@@ -128,6 +126,7 @@ Type_Constraint :: struct {
|
|||||||
|
|
||||||
Scope_Stack :: struct {
|
Scope_Stack :: struct {
|
||||||
allocator : Allocator;
|
allocator : Allocator;
|
||||||
|
arena : Arena;
|
||||||
|
|
||||||
stack : [..]Scope;
|
stack : [..]Scope;
|
||||||
}
|
}
|
||||||
@@ -138,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;
|
||||||
}
|
}
|
||||||
@@ -168,8 +167,10 @@ Scope :: struct {
|
|||||||
Scope_Handle :: #type, distinct u32;
|
Scope_Handle :: #type, distinct u32;
|
||||||
|
|
||||||
Semantic_Check_Result :: struct {
|
Semantic_Check_Result :: struct {
|
||||||
messages : [..]Compiler_Message;
|
messages : [..]Compiler_Message;
|
||||||
had_error : bool;
|
message_arena : Arena;
|
||||||
|
message_allocator : Allocator;
|
||||||
|
had_error : bool;
|
||||||
|
|
||||||
vertex_entry_point : *AST_Node;
|
vertex_entry_point : *AST_Node;
|
||||||
pixel_entry_point : *AST_Node;
|
pixel_entry_point : *AST_Node;
|
||||||
@@ -178,6 +179,10 @@ Semantic_Check_Result :: struct {
|
|||||||
|
|
||||||
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 {
|
||||||
@@ -196,6 +201,10 @@ Semantic_Checker :: struct {
|
|||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,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);
|
||||||
|
|
||||||
@@ -596,7 +604,7 @@ record_error :: (checker : *Semantic_Checker, error_string : string, locations :
|
|||||||
error.message = error_string;
|
error.message = error_string;
|
||||||
|
|
||||||
checker.result.had_error = true;
|
checker.result.had_error = true;
|
||||||
array_add(*checker.result.messages, error);
|
array_add(*checker.result.messages, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
is_proper :: (var : Type_Variable) -> bool {
|
is_proper :: (var : Type_Variable) -> bool {
|
||||||
@@ -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);
|
||||||
@@ -705,16 +715,16 @@ new_type_variable :: (checker : *Semantic_Checker) -> *Type_Variable, Type_Varia
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
@@ -722,7 +732,10 @@ init_semantic_checker :: (checker : *Semantic_Checker, root : *AST_Node, path :
|
|||||||
checker.path = path;
|
checker.path = path;
|
||||||
|
|
||||||
// @Incomplete(niels): Use other allocator and/or add static array with convenience functions
|
// @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);
|
||||||
@@ -842,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 {
|
||||||
@@ -920,16 +937,18 @@ declare_struct :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variab
|
|||||||
return declare_struct(checker, node, node.name);
|
return declare_struct(checker, node, node.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_buffer_index : u32 = 0;
|
|
||||||
|
|
||||||
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.type = .Properties;
|
||||||
var.typename = "properties";
|
var.typename = "properties";
|
||||||
var.buffer_index = current_buffer_index;
|
var.resource_index = checker.current_buffer_index;
|
||||||
current_buffer_index += 1;
|
checker.current_buffer_index += 1;
|
||||||
return type_var;
|
return type_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -937,8 +956,8 @@ declare_cbuffer :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Varia
|
|||||||
type_var := declare_struct(checker, node);
|
type_var := declare_struct(checker, node);
|
||||||
var := h2tv(checker, type_var);
|
var := h2tv(checker, type_var);
|
||||||
var.type = .CBuffer;
|
var.type = .CBuffer;
|
||||||
var.buffer_index = current_buffer_index;
|
var.resource_index = checker.current_buffer_index;
|
||||||
current_buffer_index += 1;
|
checker.current_buffer_index += 1;
|
||||||
array_add(*checker.result.constant_buffers, type_var);
|
array_add(*checker.result.constant_buffers, type_var);
|
||||||
return type_var;
|
return type_var;
|
||||||
}
|
}
|
||||||
@@ -993,7 +1012,7 @@ 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);
|
||||||
@@ -1008,7 +1027,7 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 := field_list.children[i];
|
node_child := field_list.children[i];
|
||||||
|
|
||||||
@@ -1108,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 {
|
||||||
@@ -1199,6 +1218,9 @@ create_variable :: (checker : *Semantic_Checker, node : *AST_Node, struct_field_
|
|||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
lookup_name : string = variable.typename;
|
lookup_name : string = variable.typename;
|
||||||
|
if variable.typename == "properties" {
|
||||||
|
lookup_name = variable.name;
|
||||||
|
}
|
||||||
struct_symbol := find_symbol(checker, lookup_name, checker.current_scope);
|
struct_symbol := find_symbol(checker, lookup_name, checker.current_scope);
|
||||||
type_variable := h2tv(checker, struct_symbol.type_variable);
|
type_variable := h2tv(checker, struct_symbol.type_variable);
|
||||||
|
|
||||||
@@ -1239,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;
|
||||||
@@ -1334,11 +1377,11 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
|
|||||||
|
|
||||||
function := h2tv(checker, func.type_variable);
|
function := h2tv(checker, func.type_variable);
|
||||||
|
|
||||||
if arg_count != function.child_count {
|
if arg_count != function.children.count {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -1348,7 +1391,7 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
|
|||||||
for arg : arg_vars {
|
for arg : arg_vars {
|
||||||
function_param := function.children[it_index];
|
function_param := function.children[it_index];
|
||||||
|
|
||||||
if !types_compatible(checker, arg.var, function_param) {
|
if !types_compatible(checker, arg.var, function_param, true) {
|
||||||
if all_args_match {
|
if all_args_match {
|
||||||
arg_node = arg.node;
|
arg_node = arg.node;
|
||||||
}
|
}
|
||||||
@@ -1411,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;
|
||||||
@@ -1425,7 +1469,9 @@ 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.struct_field_parent = h2tv(checker, lhs_var).struct_field_parent;
|
proper_variable.struct_field_parent = h2tv(checker, lhs_var).struct_field_parent;
|
||||||
|
|
||||||
@@ -1525,18 +1571,33 @@ 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);
|
||||||
|
|
||||||
if lhs_var.type == {
|
if lhs_var.type == {
|
||||||
case .Int; #through;
|
case .Int; #through;
|
||||||
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;
|
||||||
@@ -1544,6 +1605,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);
|
||||||
@@ -1559,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;
|
||||||
@@ -1652,14 +1725,41 @@ union_find :: (checker : *Semantic_Checker) -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_hlsl_builtins :: (checker : *Semantic_Checker) {
|
// HLSL_BUILTIN :: #run -> string {
|
||||||
#load "hlsl_builtin.jai";
|
// T := #load "hlsl_builtin.jai";
|
||||||
|
|
||||||
|
// return "";
|
||||||
|
// };
|
||||||
|
|
||||||
|
add_hlsl_builtins :: (checker : *Semantic_Checker) {
|
||||||
|
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;
|
||||||
@@ -1672,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 {
|
||||||
@@ -1717,7 +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 {
|
||||||
current_buffer_index = 0;
|
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);
|
||||||
@@ -1734,6 +1836,7 @@ check :: (checker : *Semantic_Checker) -> Semantic_Check_Result {
|
|||||||
// ===========================================================
|
// ===========================================================
|
||||||
// Pretty printing
|
// Pretty printing
|
||||||
|
|
||||||
|
#scope_file
|
||||||
|
|
||||||
type_to_string :: (type_variable : Type_Variable) -> string {
|
type_to_string :: (type_variable : Type_Variable) -> string {
|
||||||
if type_variable.type == {
|
if type_variable.type == {
|
||||||
@@ -1741,21 +1844,27 @@ type_to_string :: (type_variable : Type_Variable) -> string {
|
|||||||
return "{{invalid}}";
|
return "{{invalid}}";
|
||||||
case .Unit;
|
case .Unit;
|
||||||
return "()";
|
return "()";
|
||||||
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;
|
||||||
@@ -1807,14 +1916,14 @@ 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, ", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1991,6 +2100,7 @@ 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.struct_field_parent {
|
if variable.struct_field_parent {
|
||||||
print_to_builder(builder, "%.", variable.struct_field_parent.name);
|
print_to_builder(builder, "%.", variable.struct_field_parent.name);
|
||||||
@@ -2077,14 +2187,14 @@ pretty_print_type_variable :: (checker : *Semantic_Checker, type_variable : *Typ
|
|||||||
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, ", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2124,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";
|
||||||
|
|||||||
50
Test.jai
50
Test.jai
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
42
first.jai
Normal file
42
first.jai
Normal 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();
|
||||||
269
hlsl_builtin.jai
269
hlsl_builtin.jai
@@ -1,266 +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) -> 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 :: (texture : Texture2D, uv : float2, sampler : Sampler) -> float4;
|
|
||||||
|
|
||||||
DONE
|
|
||||||
|
|||||||
262
hlsl_builtin.shd
Normal file
262
hlsl_builtin.shd
Normal 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;
|
||||||
103
module.jai
103
module.jai
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +132,68 @@ Shader_Variant_Collection :: struct {
|
|||||||
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;
|
||||||
|
|
||||||
@@ -240,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;
|
||||||
@@ -252,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);
|
||||||
@@ -268,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;
|
||||||
@@ -290,9 +360,24 @@ 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;
|
||||||
|
|
||||||
lexer : Lexer;
|
lexer : Lexer;
|
||||||
|
|
||||||
init_lexer_from_file(*lexer, path);
|
init_lexer_from_file(*lexer, path);
|
||||||
@@ -310,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 {
|
||||||
@@ -371,28 +456,28 @@ compile_file :: (compiler : *Shader_Compiler, path : string) -> Compilation_Resu
|
|||||||
|
|
||||||
cb := array_add(*result.collection.cbuffers);
|
cb := array_add(*result.collection.cbuffers);
|
||||||
|
|
||||||
for i : 0..variable.child_count - 1 {
|
for i : 0..variable.children.count - 1 {
|
||||||
child := variable.children[i];
|
child := variable.children[i];
|
||||||
field : Property_Field;
|
field : Property_Field;
|
||||||
field.base_field = type_variable_to_field(*checker, h2tv(*checker, child));;
|
field.base_field = type_variable_to_field(*checker, h2tv(*checker, child));;
|
||||||
array_add(*cb.fields, field);
|
array_add(*cb.fields, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
cb.buffer_index = variable.buffer_index;
|
cb.buffer_index = variable.resource_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
find_result := find_symbol(*check_result.scope_stack, "properties", xx 1);
|
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.result.pixel_entry_point {
|
if checker.result.pixel_entry_point {
|
||||||
|
|||||||
1
modules/ncore
Submodule
1
modules/ncore
Submodule
Submodule modules/ncore added at 9db7ff0940
@@ -1,43 +0,0 @@
|
|||||||
Static_Array :: struct (T : Type, N : int) {
|
|
||||||
array : [N] T;
|
|
||||||
|
|
||||||
count : int;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator *[] :: (sa : *Static_Array, index : int) -> *sa.T {
|
|
||||||
assert(index < sa.count);
|
|
||||||
return *sa.array[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
array_add :: (sa : *Static_Array, item : sa.T) {
|
|
||||||
assert(sa.count + 1 < sa.N);
|
|
||||||
|
|
||||||
sa.array[sa.count] = item;
|
|
||||||
sa.count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
array_add :: (sa : *Static_Array) -> *sa.T {
|
|
||||||
assert(sa.count + 1 < sa.N);
|
|
||||||
|
|
||||||
ptr := *sa.array[sa.count];
|
|
||||||
sa.count += 1;
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
pop :: (sa : *Static_Array) -> sa.T {
|
|
||||||
assert(sa.count > 0);
|
|
||||||
elem := sa.array[sa.count - 1];
|
|
||||||
sa.count -= 1;
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
clear :: (sa : *Static_Array) {
|
|
||||||
sa.count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
to_array :: (sa : *Static_Array) -> []sa.T {
|
|
||||||
array : []sa.T;
|
|
||||||
array.count = sa.count;
|
|
||||||
array.data = sa.array.data;
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
5
test/arrays.shd
Normal file
5
test/arrays.shd
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
vertex main :: () -> float4 @position {
|
||||||
|
arr : [16].float4;
|
||||||
|
arr[0] = float4(1,1,1);
|
||||||
|
return arr[0];
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
void vs_main()
|
void vs_main()
|
||||||
{
|
{
|
||||||
float x = 2.0f + 5.0f;
|
float x = (2.0f + 5.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,2 @@
|
|||||||
struct Foo;
|
struct Foo {};
|
||||||
|
|
||||||
struct Foo {}
|
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ int foo()
|
|||||||
|
|
||||||
float bar()
|
float bar()
|
||||||
{
|
{
|
||||||
return 1235.0f * 500;
|
return (1235.0f * 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vs_main()
|
void vs_main()
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
struct Data;
|
|
||||||
|
|
||||||
struct Data
|
struct Data
|
||||||
{
|
{
|
||||||
float4 color;
|
float4 color;
|
||||||
}
|
};
|
||||||
|
|
||||||
void vs_main()
|
void vs_main()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
29
test/codegen/texture_sample.golden
Normal file
29
test/codegen/texture_sample.golden
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
7
test/double_access.shd
Normal file
7
test/double_access.shd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
p :: properties {
|
||||||
|
v : float2;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex main ::() {
|
||||||
|
x : float = p.v.x / p.v.y;
|
||||||
|
}
|
||||||
42
test/large_block.shd
Normal file
42
test/large_block.shd
Normal 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
40
test/lex/arrays.golden
Normal 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 =''; }
|
||||||
6
test/parse/arrays.golden
Normal file
6
test/parse/arrays.golden
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
(program
|
||||||
|
(fun vertex vs_main -> float4 (@position)
|
||||||
|
[]
|
||||||
|
(:= arr [16].float4)
|
||||||
|
(= arr[0] (float4 1 1 1))
|
||||||
|
(return arr[0])))
|
||||||
15
test/semant/constant_buffer.golden
Normal file
15
test/semant/constant_buffer.golden
Normal 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) []
|
||||||
|
]
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
[96m color : float4 = float4(y, 1.0, 1.0, 1.0);
|
[96m color : float4 = float4(y, 1.0, 1.0, 1.0);
|
||||||
^
|
^
|
||||||
[97m Possible overloads:
|
[97m Possible overloads:
|
||||||
[96m foreign float4 :: (float, float, float, float) -> float4; (test/wrong_type_for_function.shd:79)
|
[96m foreign float4 :: (float, float, float, float) -> float4; (test/wrong_type_for_function.shd:78)
|
||||||
|
|
||||||
[36m[37m[1;37mtest/wrong_type_for_function.shd:11,24: [31merror: [37mType mismatch. Expected float got float2
|
[36m[37m[1;37mtest/wrong_type_for_function.shd:11,24: [31merror: [37mType mismatch. Expected float got float2
|
||||||
[96m found:
|
[96m found:
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ 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
|
||||||
|
|||||||
14
test/simple_float2_expressions.shd
Normal file
14
test/simple_float2_expressions.shd
Normal 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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user