Compare commits
3 Commits
new-builti
...
8b2141df16
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b2141df16 | |||
| 7fefe0ecf6 | |||
| f99f86bc37 |
44
AST.jai
44
AST.jai
@@ -356,6 +356,29 @@ pretty_print_node :: (node : *AST_Node, indentation : int, builder : *String_Bui
|
|||||||
case .If; {
|
case .If; {
|
||||||
pretty_print_if(node, indentation, builder, skip_indent);
|
pretty_print_if(node, indentation, builder, skip_indent);
|
||||||
}
|
}
|
||||||
|
case .If_Directive; {
|
||||||
|
if !skip_indent {
|
||||||
|
indent(builder, indentation);
|
||||||
|
}
|
||||||
|
append(builder, "(#if ");
|
||||||
|
|
||||||
|
condition := node.children[0];
|
||||||
|
pretty_print_node(condition, 0, builder);
|
||||||
|
append(builder, "\n");
|
||||||
|
|
||||||
|
body := node.children[1];
|
||||||
|
// indent(builder,indentation + 4);
|
||||||
|
// append(builder, "(");
|
||||||
|
pretty_print_node(body, indentation + 4, builder);
|
||||||
|
// append(builder, ")");
|
||||||
|
|
||||||
|
if node.children.count == 3 { //@Note: Else branch
|
||||||
|
append(builder, "\n");
|
||||||
|
pretty_print_node(node.children[2], indentation + 4, builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
append(builder, ")");
|
||||||
|
}
|
||||||
case .For; {
|
case .For; {
|
||||||
pretty_print_for(node, indentation, builder, skip_indent);
|
pretty_print_for(node, indentation, builder, skip_indent);
|
||||||
}
|
}
|
||||||
@@ -462,8 +485,10 @@ pretty_print_declaration :: (declaration : *AST_Node, indentation : int, builder
|
|||||||
} else if declaration.kind == .CBuffer {
|
} else if declaration.kind == .CBuffer {
|
||||||
append(builder, "constant_buffer ");
|
append(builder, "constant_buffer ");
|
||||||
}
|
}
|
||||||
|
if declaration.kind != .If_Directive {
|
||||||
print_to_builder(builder, "%", declaration.name);
|
print_to_builder(builder, "%", declaration.name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if declaration.kind == .Function && declaration.token.kind == .TOKEN_IDENTIFIER{
|
if declaration.kind == .Function && declaration.token.kind == .TOKEN_IDENTIFIER{
|
||||||
print_to_builder(builder, " -> %", declaration.token.ident_value);
|
print_to_builder(builder, " -> %", declaration.token.ident_value);
|
||||||
@@ -479,9 +504,26 @@ pretty_print_declaration :: (declaration : *AST_Node, indentation : int, builder
|
|||||||
pretty_print_node(declaration.children[0], 0, builder);
|
pretty_print_node(declaration.children[0], 0, builder);
|
||||||
append(builder, "\n");
|
append(builder, "\n");
|
||||||
pretty_print_node(declaration.children[1], indentation + 5, builder);
|
pretty_print_node(declaration.children[1], indentation + 5, builder);
|
||||||
|
|
||||||
|
if declaration.children.count > 2 {
|
||||||
|
append(builder, "\n");
|
||||||
|
if declaration.children[2].kind == .If_Directive {
|
||||||
|
pretty_print_declaration(declaration.children[2], indentation + 5, builder);
|
||||||
|
} else {
|
||||||
|
pretty_print_node(declaration.children[2], indentation + 5, builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
print_to_builder(builder, "\n");
|
print_to_builder(builder, "\n");
|
||||||
pretty_print_children(declaration, indentation + 1, builder, flags = .NewLine);
|
|
||||||
|
flags := Children_Print_Flags.NewLine;
|
||||||
|
|
||||||
|
if declaration.parent && declaration.parent.parent {
|
||||||
|
if declaration.parent.parent.kind == .If_Directive {
|
||||||
|
indent(builder, indentation - 1); //@Note: Hack the indent for now... Wow this is stupid, but it works!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pretty_print_children(declaration, indentation + 1, builder, flags = flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ Checker_State :: enum {
|
|||||||
Adding_Builtins;
|
Adding_Builtins;
|
||||||
}
|
}
|
||||||
|
|
||||||
Semantic_Checker :: struct {
|
Checker :: struct {
|
||||||
program_root : *AST_Node;
|
program_root : *AST_Node;
|
||||||
path : string;
|
path : string;
|
||||||
|
|
||||||
@@ -152,17 +152,17 @@ Semantic_Checker :: struct {
|
|||||||
had_error : bool;
|
had_error : bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
record_error :: (checker : *Semantic_Checker, message : string, source_location : Source_Range, report_source_location : bool = true) {
|
record_error :: (checker : *Checker, message : string, source_location : Source_Range, report_source_location : bool = true) {
|
||||||
locations : [1]Source_Range;
|
locations : [1]Source_Range;
|
||||||
locations[0] = source_location;
|
locations[0] = source_location;
|
||||||
record_error(checker, message, locations, report_source_location);
|
record_error(checker, message, locations, report_source_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid_symbol_name :: (checker : *Semantic_Checker, node : *AST_Node, type : string) {
|
invalid_symbol_name :: (checker : *Checker, node : *AST_Node, type : string) {
|
||||||
record_error(checker, tprint("Invalid % name '%'", type, node.name), node.source_location);
|
record_error(checker, tprint("Invalid % name '%'", type, node.name), node.source_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
symbol_redeclaration :: (checker : *Semantic_Checker, redeclared_node : *AST_Node, symbol : *Defined_Symbol) {
|
symbol_redeclaration :: (checker : *Checker, redeclared_node : *AST_Node, symbol : *Defined_Symbol) {
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Redeclaration of '%':
|
Redeclaration of '%':
|
||||||
@@ -184,7 +184,7 @@ symbol_redeclaration :: (checker : *Semantic_Checker, redeclared_node : *AST_Nod
|
|||||||
|
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(redeclared_node.source_location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, redeclared_node.source_location));
|
||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_token_pointer(*builder, redeclared_node.source_location.main_token);
|
print_token_pointer(*builder, redeclared_node.source_location.main_token);
|
||||||
@@ -205,7 +205,7 @@ symbol_redeclaration :: (checker : *Semantic_Checker, redeclared_node : *AST_Nod
|
|||||||
|
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, location));
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_token_pointer(*builder, symbol.source_node.source_location.main_token);
|
print_token_pointer(*builder, symbol.source_node.source_location.main_token);
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ symbol_redeclaration :: (checker : *Semantic_Checker, redeclared_node : *AST_Nod
|
|||||||
record_error(checker, message, redeclared_node.source_location, false);
|
record_error(checker, message, redeclared_node.source_location, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
symbol_undeclared :: (checker : *Semantic_Checker, node : *AST_Node) {
|
symbol_undeclared :: (checker : *Checker, node : *AST_Node) {
|
||||||
/*
|
/*
|
||||||
Use of undeclard symbol '%'.
|
Use of undeclard symbol '%'.
|
||||||
b = f;
|
b = f;
|
||||||
@@ -231,7 +231,7 @@ Use of undeclard symbol '%'.
|
|||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
|
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(node.source_location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, node.source_location));
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_token_pointer(*builder, node.source_location.main_token);
|
print_token_pointer(*builder, node.source_location.main_token);
|
||||||
|
|
||||||
@@ -240,7 +240,7 @@ Use of undeclard symbol '%'.
|
|||||||
record_error(checker, message, node.source_location, false);
|
record_error(checker, message, node.source_location, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, overloads : *Defined_Symbol, arg_node : *AST_Node = null) {
|
no_matching_overload_found :: (checker : *Checker, call : *AST_Node, overloads : *Defined_Symbol, arg_node : *AST_Node = null) {
|
||||||
builder : String_Builder;
|
builder : String_Builder;
|
||||||
init_string_builder(*builder,, temp);
|
init_string_builder(*builder,, temp);
|
||||||
|
|
||||||
@@ -250,7 +250,7 @@ no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, ov
|
|||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
append(*builder, "found:\n");
|
append(*builder, "found:\n");
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(call.source_location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, call.source_location));
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
print_token_pointer(*builder, call.source_location.main_token);
|
print_token_pointer(*builder, call.source_location.main_token);
|
||||||
newline(*builder);
|
newline(*builder);
|
||||||
@@ -275,7 +275,7 @@ no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, ov
|
|||||||
|
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, location));
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
print_token_pointer(*builder, arg_node.source_location.main_token);
|
print_token_pointer(*builder, arg_node.source_location.main_token);
|
||||||
newline(*builder);
|
newline(*builder);
|
||||||
@@ -293,9 +293,14 @@ no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, ov
|
|||||||
func_location := func_var.source_node.source_location;
|
func_location := func_var.source_node.source_location;
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
|
|
||||||
// @Incomplete(niels): We need a way to properly save the path of the declaration
|
if func.builtin {
|
||||||
print_to_builder(*builder, "% (%:%)\n", print_from_source_location(func_location), checker.path,
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, func_location));
|
||||||
|
} else {
|
||||||
|
print_to_builder(*builder, "% (%:%)\n", print_from_source_location(checker.ctx, func_location), checker.path,
|
||||||
func_location.main_token.line);
|
func_location.main_token.line);
|
||||||
|
}
|
||||||
|
// @Incomplete(niels): We need a way to properly save the path of the declaration
|
||||||
|
|
||||||
|
|
||||||
if !arg_node {
|
if !arg_node {
|
||||||
white(*builder);
|
white(*builder);
|
||||||
@@ -318,7 +323,7 @@ no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, ov
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
not_all_control_paths_return_value :: (checker : *Semantic_Checker, node : *AST_Node) {
|
not_all_control_paths_return_value :: (checker : *Checker, node : *AST_Node) {
|
||||||
builder : String_Builder;
|
builder : String_Builder;
|
||||||
init_string_builder(*builder,, temp);
|
init_string_builder(*builder,, temp);
|
||||||
|
|
||||||
@@ -328,7 +333,7 @@ not_all_control_paths_return_value :: (checker : *Semantic_Checker, node : *AST_
|
|||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
|
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(node.source_location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, node.source_location));
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_token_pointer(*builder, node.token);
|
print_token_pointer(*builder, node.token);
|
||||||
|
|
||||||
@@ -339,7 +344,7 @@ not_all_control_paths_return_value :: (checker : *Semantic_Checker, node : *AST_
|
|||||||
record_error(checker, message, node.source_location, false);
|
record_error(checker, message, node.source_location, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
mismatched_arguments :: (checker : *Semantic_Checker, call : *AST_Node, symbol : *Defined_Symbol, args_call : int, args_def : int) {
|
mismatched_arguments :: (checker : *Checker, call : *AST_Node, symbol : *Defined_Symbol, args_call : int, args_def : int) {
|
||||||
builder : String_Builder;
|
builder : String_Builder;
|
||||||
init_string_builder(*builder,, temp);
|
init_string_builder(*builder,, temp);
|
||||||
|
|
||||||
@@ -364,7 +369,7 @@ Too many arguments: Expected %, got %.
|
|||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
append(*builder, "found:\n");
|
append(*builder, "found:\n");
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(call.source_location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, call.source_location));
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
print_token_pointer(*builder, call.source_location.main_token);
|
print_token_pointer(*builder, call.source_location.main_token);
|
||||||
append(*builder, "\n\n");
|
append(*builder, "\n\n");
|
||||||
@@ -372,7 +377,7 @@ Too many arguments: Expected %, got %.
|
|||||||
append(*builder, "expected:\n");
|
append(*builder, "expected:\n");
|
||||||
|
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(symbol.source_node.source_location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, symbol.source_node.source_location));
|
||||||
|
|
||||||
locations : [1]Source_Range;
|
locations : [1]Source_Range;
|
||||||
locations[0] = call.source_location;
|
locations[0] = call.source_location;
|
||||||
@@ -381,7 +386,7 @@ Too many arguments: Expected %, got %.
|
|||||||
record_error(checker, message, locations, false);
|
record_error(checker, message, locations, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function_undeclared :: (checker : *Semantic_Checker, node : *AST_Node) {
|
function_undeclared :: (checker : *Checker, node : *AST_Node) {
|
||||||
/*
|
/*
|
||||||
Error: Undeclared identifier 'name'.
|
Error: Undeclared identifier 'name'.
|
||||||
|
|
||||||
@@ -395,7 +400,7 @@ Error: Undeclared identifier 'name'.
|
|||||||
print_to_builder(*builder, "Attempt to call undeclared function '%'.\n\n", node.name);
|
print_to_builder(*builder, "Attempt to call undeclared function '%'.\n\n", node.name);
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(node.source_location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, node.source_location));
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_token_pointer(*builder, node.source_location.main_token);
|
print_token_pointer(*builder, node.source_location.main_token);
|
||||||
newline(*builder);
|
newline(*builder);
|
||||||
@@ -404,7 +409,7 @@ Error: Undeclared identifier 'name'.
|
|||||||
record_error(checker, message, node.source_location, false);
|
record_error(checker, message, node.source_location, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
field_not_defined_on_struct :: (checker : *Semantic_Checker, node : *AST_Node, struct_symbol : *Defined_Symbol) {
|
field_not_defined_on_struct :: (checker : *Checker, node : *AST_Node, struct_symbol : *Defined_Symbol) {
|
||||||
/*
|
/*
|
||||||
Field '%' is not defined in struct '%'.
|
Field '%' is not defined in struct '%'.
|
||||||
b.t = f;
|
b.t = f;
|
||||||
@@ -423,7 +428,7 @@ Field '%' is not defined in struct '%'.
|
|||||||
|
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(node.source_location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, node.source_location));
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_token_pointer(*builder, node.source_location.main_token);
|
print_token_pointer(*builder, node.source_location.main_token);
|
||||||
newline(*builder);
|
newline(*builder);
|
||||||
@@ -431,13 +436,13 @@ Field '%' is not defined in struct '%'.
|
|||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
append(*builder, "declaration:\n");
|
append(*builder, "declaration:\n");
|
||||||
print_from_source_location(*builder, struct_symbol.source_node.source_location, 2);
|
print_from_source_location(checker.ctx, *builder, struct_symbol.source_node.source_location, 2);
|
||||||
|
|
||||||
message := builder_to_string(*builder);
|
message := builder_to_string(*builder);
|
||||||
record_error(checker, message, node.source_location, false);
|
record_error(checker, message, node.source_location, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
field_access_on_primitive_type :: (checker : *Semantic_Checker, node : *AST_Node, handle : Type_Variable_Handle) {
|
field_access_on_primitive_type :: (checker : *Checker, node : *AST_Node, handle : Type_Variable_Handle) {
|
||||||
/*
|
/*
|
||||||
Attempting to access a field on a primitive type '%'.
|
Attempting to access a field on a primitive type '%'.
|
||||||
x.d = 5;
|
x.d = 5;
|
||||||
@@ -451,11 +456,11 @@ Attempting to access a field on a primitive type '%'.
|
|||||||
init_string_builder(*builder,, temp);
|
init_string_builder(*builder,, temp);
|
||||||
|
|
||||||
variable := from_handle(checker, handle);
|
variable := from_handle(checker, handle);
|
||||||
print_to_builder(*builder, "Attempting to access a field on a primitive type '%'.\n", proper_type_to_string(checker.ctx.type_variables, variable));
|
print_to_builder(*builder, "Attempting to access a field on a primitive type '%'.\n", proper_type_to_string(checker.ctx, checker.ctx.type_variables, variable));
|
||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(node.source_location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, node.source_location));
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
|
|
||||||
node_variable := from_handle(checker, node.type_variable);
|
node_variable := from_handle(checker, node.type_variable);
|
||||||
@@ -471,7 +476,7 @@ Attempting to access a field on a primitive type '%'.
|
|||||||
append(*builder, "declaration:\n");
|
append(*builder, "declaration:\n");
|
||||||
|
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
print_to_builder(*builder, "%", print_from_source_location(variable.source_node.source_location));
|
print_to_builder(*builder, "%", print_from_source_location(checker.ctx, variable.source_node.source_location));
|
||||||
|
|
||||||
message := builder_to_string(*builder,, temp);
|
message := builder_to_string(*builder,, temp);
|
||||||
record_error(checker, message, node.source_location, false);
|
record_error(checker, message, node.source_location, false);
|
||||||
@@ -479,7 +484,7 @@ Attempting to access a field on a primitive type '%'.
|
|||||||
white(*builder);
|
white(*builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if_condition_has_to_be_boolean_type :: (checker : *Semantic_Checker, usage_site : *AST_Node, handle : Type_Variable_Handle) {
|
if_condition_has_to_be_boolean_type :: (checker : *Checker, usage_site : *AST_Node, handle : Type_Variable_Handle) {
|
||||||
/*
|
/*
|
||||||
Type of expression in if condition has to be bool.
|
Type of expression in if condition has to be bool.
|
||||||
if 100.0
|
if 100.0
|
||||||
@@ -499,7 +504,7 @@ if_condition_has_to_be_boolean_type :: (checker : *Semantic_Checker, usage_site
|
|||||||
|
|
||||||
location := usage_site.source_location;
|
location := usage_site.source_location;
|
||||||
|
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, location));
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
|
|
||||||
print_token_pointer(*builder, usage_site.children[0].source_location.begin);
|
print_token_pointer(*builder, usage_site.children[0].source_location.begin);
|
||||||
@@ -512,7 +517,7 @@ if_condition_has_to_be_boolean_type :: (checker : *Semantic_Checker, usage_site
|
|||||||
usage_child := usage_site.children[0];
|
usage_child := usage_site.children[0];
|
||||||
usage_loc := usage_child.source_location;
|
usage_loc := usage_child.source_location;
|
||||||
|
|
||||||
print_to_builder(*builder, "% has type %\n", print_from_source_location(*usage_loc), proper_type_to_string(checker.ctx.type_variables, var));
|
print_to_builder(*builder, "% has type %\n", print_from_source_location(checker.ctx, *usage_loc), proper_type_to_string(checker.ctx, checker.ctx.type_variables, var));
|
||||||
|
|
||||||
message := builder_to_string(*builder,, temp);
|
message := builder_to_string(*builder,, temp);
|
||||||
record_error(checker, message, usage_site.source_location, false);
|
record_error(checker, message, usage_site.source_location, false);
|
||||||
@@ -520,7 +525,7 @@ if_condition_has_to_be_boolean_type :: (checker : *Semantic_Checker, usage_site
|
|||||||
white(*builder);
|
white(*builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_mismatch :: (checker : *Semantic_Checker, usage_site : *AST_Node, expect_node : *AST_Node, expect : Type_Variable_Handle, got : Type_Variable_Handle) {
|
type_mismatch :: (checker : *Checker, usage_site : *AST_Node, expect_node : *AST_Node, expect : Type_Variable_Handle, got : Type_Variable_Handle) {
|
||||||
expect_var := from_handle(checker, expect);
|
expect_var := from_handle(checker, expect);
|
||||||
got_var := from_handle(checker, got);
|
got_var := from_handle(checker, got);
|
||||||
|
|
||||||
@@ -545,7 +550,7 @@ type_mismatch :: (checker : *Semantic_Checker, usage_site : *AST_Node, expect_no
|
|||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
append(*builder, "found:\n");
|
append(*builder, "found:\n");
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, location));
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
|
|
||||||
print_token_pointer(*builder, location.main_token);
|
print_token_pointer(*builder, location.main_token);
|
||||||
@@ -554,7 +559,7 @@ type_mismatch :: (checker : *Semantic_Checker, usage_site : *AST_Node, expect_no
|
|||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_to_builder(*builder, "expected:\n");
|
print_to_builder(*builder, "expected:\n");
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
proper_type_to_string(*builder, checker.ctx.type_variables, expect_var);
|
proper_type_to_string(checker.ctx, *builder, checker.ctx.type_variables, expect_var);
|
||||||
append(*builder, "\n");
|
append(*builder, "\n");
|
||||||
|
|
||||||
// indent(*builder, 2);
|
// indent(*builder, 2);
|
||||||
@@ -572,14 +577,14 @@ type_mismatch :: (checker : *Semantic_Checker, usage_site : *AST_Node, expect_no
|
|||||||
|
|
||||||
indent(*builder, 2);
|
indent(*builder, 2);
|
||||||
|
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(got_var.source_node.source_location));
|
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, got_var.source_node.source_location));
|
||||||
|
|
||||||
message := builder_to_string(*builder);
|
message := builder_to_string(*builder);
|
||||||
|
|
||||||
record_error(checker, message, Source_Range.[usage_site.source_location], false);
|
record_error(checker, message, Source_Range.[usage_site.source_location], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
record_error :: (checker : *Semantic_Checker, error_string : string, locations : []Source_Range, report_source_location : bool = true) {
|
record_error :: (checker : *Checker, error_string : string, locations : []Source_Range, report_source_location : bool = true) {
|
||||||
error : Compiler_Message;
|
error : Compiler_Message;
|
||||||
error.message_kind = .Error;
|
error.message_kind = .Error;
|
||||||
error.report_source_location = report_source_location;
|
error.report_source_location = report_source_location;
|
||||||
@@ -607,7 +612,7 @@ is_proper :: (var : Type_Variable) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
use_scope :: (checker : *Semantic_Checker, handle : Scope_Handle) -> Scope_Handle {
|
use_scope :: (checker : *Checker, handle : Scope_Handle) -> Scope_Handle {
|
||||||
assert(handle > 0, "Invalid scope handle: %", handle);
|
assert(handle > 0, "Invalid scope handle: %", handle);
|
||||||
previous_scope := checker.current_scope;
|
previous_scope := checker.current_scope;
|
||||||
checker.current_scope = handle;
|
checker.current_scope = handle;
|
||||||
@@ -615,7 +620,7 @@ use_scope :: (checker : *Semantic_Checker, handle : Scope_Handle) -> Scope_Handl
|
|||||||
return previous_scope;
|
return previous_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
push_scope :: (checker : *Semantic_Checker, name := "", kind : Scope_Kind = .Global) -> *Scope, Scope_Handle {
|
push_scope :: (checker : *Checker, name := "", kind : Scope_Kind = .Global) -> *Scope, Scope_Handle {
|
||||||
new_scope : Scope;
|
new_scope : Scope;
|
||||||
array_add(*checker.ctx.scope_stack.stack, new_scope);
|
array_add(*checker.ctx.scope_stack.stack, new_scope);
|
||||||
|
|
||||||
@@ -641,7 +646,7 @@ push_scope :: (checker : *Semantic_Checker, name := "", kind : Scope_Kind = .Glo
|
|||||||
return scope, xx count;
|
return scope, xx count;
|
||||||
}
|
}
|
||||||
|
|
||||||
pop_scope :: (checker : *Semantic_Checker) -> Scope_Handle {
|
pop_scope :: (checker : *Checker) -> Scope_Handle {
|
||||||
scope := get_scope(checker, checker.current_scope);
|
scope := get_scope(checker, checker.current_scope);
|
||||||
if !scope.parent {
|
if !scope.parent {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -652,7 +657,7 @@ pop_scope :: (checker : *Semantic_Checker) -> Scope_Handle {
|
|||||||
return checker.current_scope;
|
return checker.current_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
peek_scope :: (checker : *Semantic_Checker) -> *Scope, Scope_Handle {
|
peek_scope :: (checker : *Checker) -> *Scope, Scope_Handle {
|
||||||
if checker.ctx.scope_stack.stack.count == 0 {
|
if checker.ctx.scope_stack.stack.count == 0 {
|
||||||
return null, 0;
|
return null, 0;
|
||||||
}
|
}
|
||||||
@@ -662,7 +667,7 @@ peek_scope :: (checker : *Semantic_Checker) -> *Scope, Scope_Handle {
|
|||||||
return scope, xx count;
|
return scope, xx count;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_current_scope :: (checker : *Semantic_Checker) -> *Scope {
|
get_current_scope :: (checker : *Checker) -> *Scope {
|
||||||
return get_scope(checker, checker.current_scope);
|
return get_scope(checker, checker.current_scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -674,7 +679,7 @@ get_scope :: (scope_stack : Scope_Stack, handle : Scope_Handle) -> *Scope {
|
|||||||
return *scope_stack.stack[handle - 1];
|
return *scope_stack.stack[handle - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
get_scope :: (checker : *Semantic_Checker, handle : Scope_Handle) -> *Scope {
|
get_scope :: (checker : *Checker, handle : Scope_Handle) -> *Scope {
|
||||||
return get_scope(*checker.ctx.scope_stack, handle);
|
return get_scope(*checker.ctx.scope_stack, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -695,7 +700,7 @@ add_symbol_to_scope :: (state : Checker_State, scope_stack : *Scope_Stack, scope
|
|||||||
return table_set(*scope.table, name, symbol_to_add);
|
return table_set(*scope.table, name, symbol_to_add);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_type_variable :: (checker : *Semantic_Checker) -> *Type_Variable, Type_Variable_Handle {
|
new_type_variable :: (checker : *Checker) -> *Type_Variable, Type_Variable_Handle {
|
||||||
variable : Type_Variable;
|
variable : Type_Variable;
|
||||||
handle := cast(Type_Variable_Handle)checker.ctx.type_variables.count + 1;
|
handle := cast(Type_Variable_Handle)checker.ctx.type_variables.count + 1;
|
||||||
array_add(*checker.ctx.type_variables, variable);
|
array_add(*checker.ctx.type_variables, variable);
|
||||||
@@ -703,7 +708,7 @@ new_type_variable :: (checker : *Semantic_Checker) -> *Type_Variable, Type_Varia
|
|||||||
return from_handle(checker, handle), handle;
|
return from_handle(checker, handle), handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_builtin_type_variable :: (checker : *Semantic_Checker, type : Type_Kind, source : Source_Kind, name : string, typename : string = "") -> *Type_Variable, Type_Variable_Handle {
|
new_builtin_type_variable :: (checker : *Checker, type : Type_Kind, source : Source_Kind, name : string, typename : string = "") -> *Type_Variable, Type_Variable_Handle {
|
||||||
tv, handle := new_type_variable(checker);
|
tv, handle := new_type_variable(checker);
|
||||||
|
|
||||||
tv.name = name;
|
tv.name = name;
|
||||||
@@ -720,7 +725,7 @@ Arg :: struct {
|
|||||||
typename : string;
|
typename : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_builtin_struct :: (checker : *Semantic_Checker, name : string, members : []Arg) -> *Type_Variable, Type_Variable_Handle {
|
new_builtin_struct :: (checker : *Checker, name : string, members : []Arg) -> *Type_Variable, Type_Variable_Handle {
|
||||||
tv, handle := new_builtin_type_variable(checker, .Struct, .Declaration, name, name);
|
tv, handle := new_builtin_type_variable(checker, .Struct, .Declaration, name, name);
|
||||||
|
|
||||||
builtin_node := new_builtin_struct_node(checker.ctx, name, members);
|
builtin_node := new_builtin_struct_node(checker.ctx, name, members);
|
||||||
@@ -762,7 +767,7 @@ new_builtin_struct :: (checker : *Semantic_Checker, name : string, members : []A
|
|||||||
return from_handle(checker, handle), handle;
|
return from_handle(checker, handle), handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_builtin_function :: (checker : *Semantic_Checker, name : string, args : []Arg, return_arg : Arg) -> *Type_Variable, Type_Variable_Handle {
|
new_builtin_function :: (checker : *Checker, name : string, args : []Arg, return_arg : Arg) -> *Type_Variable, Type_Variable_Handle {
|
||||||
tv, handle := new_builtin_type_variable(checker, .Function, .Declaration, name);
|
tv, handle := new_builtin_type_variable(checker, .Function, .Declaration, name);
|
||||||
|
|
||||||
builtin_node := new_builtin_function_node(checker.ctx, name, args, return_arg);
|
builtin_node := new_builtin_function_node(checker.ctx, name, args, return_arg);
|
||||||
@@ -771,7 +776,7 @@ new_builtin_function :: (checker : *Semantic_Checker, name : string, args : []Ar
|
|||||||
function.name = name;
|
function.name = name;
|
||||||
function.source_node = builtin_node;
|
function.source_node = builtin_node;
|
||||||
function.type_variable = handle;
|
function.type_variable = handle;
|
||||||
|
function.builtin = true;
|
||||||
|
|
||||||
find_result := find_symbol(checker, name, checker.current_scope);
|
find_result := find_symbol(checker, name, checker.current_scope);
|
||||||
if !find_result {
|
if !find_result {
|
||||||
@@ -822,13 +827,13 @@ add_child :: (variable : *Type_Variable, child : Type_Variable_Handle) {
|
|||||||
// variable.children.count += 1;
|
// variable.children.count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_child :: (checker : *Semantic_Checker, handle : Type_Variable_Handle, child : Type_Variable_Handle) {
|
add_child :: (checker : *Checker, handle : Type_Variable_Handle, child : Type_Variable_Handle) {
|
||||||
variable := from_handle(checker, handle);
|
variable := from_handle(checker, handle);
|
||||||
assert(variable.children.count < Type_Variable.MAX_TYPE_VARIABLE_CHILDREN);
|
assert(variable.children.count < Type_Variable.MAX_TYPE_VARIABLE_CHILDREN);
|
||||||
array_add(*variable.children, child);
|
array_add(*variable.children, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_semantic_checker :: (checker : *Semantic_Checker, root : *AST_Node, path : string) {
|
init_semantic_checker :: (checker : *Checker, root : *AST_Node, path : string) {
|
||||||
checker.current_buffer_index = 0;
|
checker.current_buffer_index = 0;
|
||||||
checker.current_sampler_index = 0;
|
checker.current_sampler_index = 0;
|
||||||
checker.current_texture_index = 0;
|
checker.current_texture_index = 0;
|
||||||
@@ -864,11 +869,11 @@ find_symbol :: (scope_stack : Scope_Stack, name : string, current_scope : Scope_
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
find_symbol :: (checker : *Semantic_Checker, name : string, current_scope : Scope_Handle, containing_scope : *Scope_Handle = null) -> *Defined_Symbol {
|
find_symbol :: (checker : *Checker, name : string, current_scope : Scope_Handle, containing_scope : *Scope_Handle = null) -> *Defined_Symbol {
|
||||||
return find_symbol(checker.ctx.scope_stack, name, current_scope, containing_scope);
|
return find_symbol(checker.ctx.scope_stack, name, current_scope, containing_scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
find_symbol :: (name : string, checker : *Semantic_Checker, containing_scope : *Scope_Handle = null) -> *Defined_Symbol {
|
find_symbol :: (name : string, checker : *Checker, containing_scope : *Scope_Handle = null) -> *Defined_Symbol {
|
||||||
return find_symbol(checker, name, checker.current_scope, containing_scope);
|
return find_symbol(checker, name, checker.current_scope, containing_scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -877,11 +882,11 @@ from_handle :: (variables : []Type_Variable, handle : Type_Variable_Handle) -> *
|
|||||||
return *variables[handle - 1];
|
return *variables[handle - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
from_handle :: (checker : *Semantic_Checker, handle : Type_Variable_Handle) -> *Type_Variable {
|
from_handle :: (checker : *Checker, handle : Type_Variable_Handle) -> *Type_Variable {
|
||||||
return from_handle(checker.ctx.type_variables, handle);
|
return from_handle(checker.ctx.type_variables, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
proper_type_to_string :: (builder : *String_Builder, variables : []Type_Variable, var : Type_Variable) {
|
proper_type_to_string :: (ctx : *Compiler_Context, builder : *String_Builder, variables : []Type_Variable, var : Type_Variable) {
|
||||||
if var.type == {
|
if var.type == {
|
||||||
case .Int; #through;
|
case .Int; #through;
|
||||||
case .Half; #through;
|
case .Half; #through;
|
||||||
@@ -900,7 +905,7 @@ proper_type_to_string :: (builder : *String_Builder, variables : []Type_Variable
|
|||||||
if child.kind == .FieldList {
|
if child.kind == .FieldList {
|
||||||
for field : child.children {
|
for field : child.children {
|
||||||
var := field.type_variable;
|
var := field.type_variable;
|
||||||
print_type_variable(builder, variables, var);
|
print_type_variable(ctx, builder, variables, var);
|
||||||
|
|
||||||
if it_index != child.children.count - 1 {
|
if it_index != child.children.count - 1 {
|
||||||
append(builder, ", ");
|
append(builder, ", ");
|
||||||
@@ -915,10 +920,10 @@ proper_type_to_string :: (builder : *String_Builder, variables : []Type_Variable
|
|||||||
append(builder, " -> ", );
|
append(builder, " -> ", );
|
||||||
return_var := from_handle(variables, var.return_type_variable);
|
return_var := from_handle(variables, var.return_type_variable);
|
||||||
if is_proper(return_var) {
|
if is_proper(return_var) {
|
||||||
proper_type_to_string(builder, variables, return_var);
|
proper_type_to_string(ctx, builder, variables, return_var);
|
||||||
} else {
|
} else {
|
||||||
append(builder, "[[");
|
append(builder, "[[");
|
||||||
print_type_variable(builder, variables, var.return_type_variable);
|
print_type_variable(ctx, builder, variables, var.return_type_variable);
|
||||||
append(builder, "]]", );
|
append(builder, "]]", );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -931,7 +936,7 @@ proper_type_to_string :: (builder : *String_Builder, variables : []Type_Variable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proper_type_to_string :: (variables : []Type_Variable, var : Type_Variable, allocator := context.allocator) -> string {
|
proper_type_to_string :: (ctx : *Compiler_Context, variables : []Type_Variable, var : Type_Variable, allocator := context.allocator) -> string {
|
||||||
if var.type == {
|
if var.type == {
|
||||||
case .Int; #through;
|
case .Int; #through;
|
||||||
case .Half; #through;
|
case .Half; #through;
|
||||||
@@ -943,7 +948,7 @@ proper_type_to_string :: (variables : []Type_Variable, var : Type_Variable, allo
|
|||||||
builder : String_Builder;
|
builder : String_Builder;
|
||||||
init_string_builder(*builder,, allocator);
|
init_string_builder(*builder,, allocator);
|
||||||
|
|
||||||
proper_type_to_string(*builder, variables, var);
|
proper_type_to_string(ctx, *builder, variables, var);
|
||||||
return builder_to_string(*builder,, allocator);
|
return builder_to_string(*builder,, allocator);
|
||||||
}
|
}
|
||||||
case .Struct; {
|
case .Struct; {
|
||||||
@@ -954,7 +959,7 @@ proper_type_to_string :: (variables : []Type_Variable, var : Type_Variable, allo
|
|||||||
return "______not proper type______";
|
return "______not proper type______";
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup_type :: (checker : *Semantic_Checker, scope : Scope_Handle, type_string : string, typename : *string = null) -> Type_Kind {
|
lookup_type :: (checker : *Checker, scope : Scope_Handle, type_string : string, typename : *string = null) -> Type_Kind {
|
||||||
if type_string == {
|
if type_string == {
|
||||||
case Typenames[Type_Kind.Int]; return .Int;
|
case Typenames[Type_Kind.Int]; return .Int;
|
||||||
case Typenames[Type_Kind.Half]; return .Half;
|
case Typenames[Type_Kind.Half]; return .Half;
|
||||||
@@ -980,18 +985,18 @@ lookup_type :: (checker : *Semantic_Checker, scope : Scope_Handle, type_string :
|
|||||||
return .Invalid;
|
return .Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup_type :: (checker : *Semantic_Checker, scope : Scope_Handle, node : *AST_Node, typename : *string = null) -> Type_Kind {
|
lookup_type :: (checker : *Checker, scope : Scope_Handle, node : *AST_Node, typename : *string = null) -> Type_Kind {
|
||||||
type_string := node.token.ident_value;
|
type_string := node.token.ident_value;
|
||||||
return lookup_type(checker, scope, type_string, typename);
|
return lookup_type(checker, scope, type_string, typename);
|
||||||
}
|
}
|
||||||
|
|
||||||
check_block :: (checker : *Semantic_Checker, node : *AST_Node) {
|
check_block :: (checker : *Checker, node : *AST_Node) {
|
||||||
for child : node.children {
|
for child : node.children {
|
||||||
check_node(checker, child);
|
check_node(checker, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_struct :: (checker : *Semantic_Checker, node : *AST_Node, name : string) -> Type_Variable_Handle {
|
declare_struct :: (checker : *Checker, node : *AST_Node, name : string) -> Type_Variable_Handle {
|
||||||
variable, handle := new_type_variable(checker);
|
variable, handle := new_type_variable(checker);
|
||||||
variable.type = .Struct;
|
variable.type = .Struct;
|
||||||
variable.source_kind = .Declaration;
|
variable.source_kind = .Declaration;
|
||||||
@@ -1034,15 +1039,17 @@ declare_struct :: (checker : *Semantic_Checker, node : *AST_Node, name : string)
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_struct :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle {
|
declare_struct :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
|
||||||
return declare_struct(checker, node, node.name);
|
return declare_struct(checker, node, node.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_properties :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle {
|
declare_properties :: (checker : *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 {
|
if node.name.count > 0 {
|
||||||
checker.ctx.property_name = name;
|
checker.ctx.property_name = name;
|
||||||
|
} else {
|
||||||
|
checker.ctx.property_name = "properties";
|
||||||
}
|
}
|
||||||
type_var := declare_struct(checker, node, name);
|
type_var := declare_struct(checker, node, name);
|
||||||
var := from_handle(checker, type_var);
|
var := from_handle(checker, type_var);
|
||||||
@@ -1053,7 +1060,7 @@ declare_properties :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Va
|
|||||||
return type_var;
|
return type_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_cbuffer :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle {
|
declare_cbuffer :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
|
||||||
type_var := declare_struct(checker, node);
|
type_var := declare_struct(checker, node);
|
||||||
var := from_handle(checker, type_var);
|
var := from_handle(checker, type_var);
|
||||||
var.type = .CBuffer;
|
var.type = .CBuffer;
|
||||||
@@ -1073,11 +1080,11 @@ get_actual_function_name :: (node : *AST_Node) -> string {
|
|||||||
return name_to_check;
|
return name_to_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_foreign_function :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle {
|
declare_foreign_function :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
|
||||||
return declare_function(checker, node, true);
|
return declare_function(checker, node, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bool = false) -> Type_Variable_Handle {
|
declare_function :: (checker : *Checker, node : *AST_Node, builtin : bool = false) -> Type_Variable_Handle {
|
||||||
if !node.foreign_declaration && !can_declare(checker, node.name) {
|
if !node.foreign_declaration && !can_declare(checker, node.name) {
|
||||||
invalid_symbol_name(checker, node, "function");
|
invalid_symbol_name(checker, node, "function");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1204,7 +1211,7 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_function :: (checker : *Semantic_Checker, node : *AST_Node) {
|
check_function :: (checker : *Checker, node : *AST_Node) {
|
||||||
name_to_check := get_actual_function_name(node);
|
name_to_check := get_actual_function_name(node);
|
||||||
find_result := find_symbol(checker, name_to_check, checker.current_scope);
|
find_result := find_symbol(checker, name_to_check, checker.current_scope);
|
||||||
|
|
||||||
@@ -1238,6 +1245,10 @@ check_function :: (checker : *Semantic_Checker, node : *AST_Node) {
|
|||||||
stm := from_handle(checker, result_var);
|
stm := from_handle(checker, result_var);
|
||||||
add_child(variable, result_var);
|
add_child(variable, result_var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if statement.kind == .If_Directive {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1251,7 +1262,7 @@ check_function :: (checker : *Semantic_Checker, node : *AST_Node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check_variable :: (checker : *Semantic_Checker, node : *AST_Node, struct_field_parent : *AST_Node = null) -> Type_Variable_Handle {
|
check_variable :: (checker : *Checker, node : *AST_Node, struct_field_parent : *AST_Node = null) -> Type_Variable_Handle {
|
||||||
find_result := find_symbol(checker, node.name, checker.current_scope);
|
find_result := find_symbol(checker, node.name, checker.current_scope);
|
||||||
// x : int;
|
// x : int;
|
||||||
// x.d = 5;
|
// x.d = 5;
|
||||||
@@ -1296,7 +1307,7 @@ check_variable :: (checker : *Semantic_Checker, node : *AST_Node, struct_field_p
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
can_declare :: (checker : *Semantic_Checker, name : string) -> bool {
|
can_declare :: (checker : *Checker, name : string) -> bool {
|
||||||
max_value := Type_Kind.Max_Builtin;
|
max_value := Type_Kind.Max_Builtin;
|
||||||
|
|
||||||
for i : 0..max_value - 1 {
|
for i : 0..max_value - 1 {
|
||||||
@@ -1309,7 +1320,7 @@ can_declare :: (checker : *Semantic_Checker, name : string) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//@Incomplete(niels): Handle meta stuff here
|
//@Incomplete(niels): Handle meta stuff here
|
||||||
check_field :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle {
|
check_field :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
|
||||||
variable, handle := new_type_variable(checker);
|
variable, handle := new_type_variable(checker);
|
||||||
variable.name = node.name;
|
variable.name = node.name;
|
||||||
typename : string;
|
typename : string;
|
||||||
@@ -1393,7 +1404,7 @@ check_field :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_call :: (checker : *Semantic_Checker, node : *AST_Node, type_var : Type_Variable_Handle) -> error : bool {
|
check_call :: (checker : *Checker, node : *AST_Node, type_var : Type_Variable_Handle) -> error : bool {
|
||||||
find_result := find_symbol(checker, node.name, checker.current_scope);
|
find_result := find_symbol(checker, node.name, checker.current_scope);
|
||||||
|
|
||||||
if !find_result {
|
if !find_result {
|
||||||
@@ -1505,7 +1516,7 @@ check_call :: (checker : *Semantic_Checker, node : *AST_Node, type_var : Type_Va
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle {
|
check_node :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
|
||||||
if node.kind == {
|
if node.kind == {
|
||||||
case .Function; {
|
case .Function; {
|
||||||
check_function(checker, node);
|
check_function(checker, node);
|
||||||
@@ -1645,8 +1656,7 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .If_Directive; {
|
case .If_Directive; {
|
||||||
cond_var := check_node(checker, node.children[0]);
|
check_if_directive(checker, node);
|
||||||
assert(false, "Not implemented yet\n");
|
|
||||||
}
|
}
|
||||||
case .Variable; {
|
case .Variable; {
|
||||||
return check_variable(checker, node);
|
return check_variable(checker, node);
|
||||||
@@ -1686,9 +1696,85 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
traverse :: (checker : *Semantic_Checker, root : *AST_Node) {
|
is_valid_define :: (checker : *Checker, def : string) -> bool {
|
||||||
declarations := root.children;
|
for env_def : checker.ctx.environment.defines {
|
||||||
for declaration : declarations {
|
if env_def == def {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_env_expression :: (checker : *Checker, expr : *AST_Node, directive : *AST_Node) -> bool {
|
||||||
|
if expr.kind == .Binary {
|
||||||
|
lhs := expr.children[0];
|
||||||
|
rhs := expr.children[1];
|
||||||
|
|
||||||
|
lhs_valid := check_env_expression(checker, lhs, directive);
|
||||||
|
rhs_valid := check_env_expression(checker, rhs, directive);
|
||||||
|
|
||||||
|
if expr.token.kind == .TOKEN_LOGICALOR {
|
||||||
|
return lhs_valid || rhs_valid;
|
||||||
|
} else if expr.token.kind == .TOKEN_LOGICALAND {
|
||||||
|
return lhs_valid && rhs_valid;
|
||||||
|
}
|
||||||
|
} else if expr.kind == .Variable {
|
||||||
|
if expr.name == "Env" {
|
||||||
|
child := expr.children[0]; // The variable in the environment
|
||||||
|
|
||||||
|
return is_valid_define(checker, child.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_if_directive :: (checker : *Checker, directive : *AST_Node) {
|
||||||
|
cond := directive.children[0];
|
||||||
|
is_valid := check_env_expression(checker, cond, directive);
|
||||||
|
|
||||||
|
if is_valid {
|
||||||
|
parent := directive.parent;
|
||||||
|
first_child : *AST_Node = directive.children[1];
|
||||||
|
|
||||||
|
if checker.current_scope == 1 {
|
||||||
|
traverse(checker, first_child);
|
||||||
|
} else {
|
||||||
|
check_block(checker, first_child);
|
||||||
|
}
|
||||||
|
|
||||||
|
for child : directive.children[1].children {
|
||||||
|
add_child(parent, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
if directive.children.count > 2 {
|
||||||
|
directive.children.count = 0;
|
||||||
|
}
|
||||||
|
} else if directive.children.count > 2 {
|
||||||
|
parent := directive.parent;
|
||||||
|
|
||||||
|
else_branch := directive.children[2];
|
||||||
|
if else_branch.kind == .If_Directive {
|
||||||
|
check_if_directive(checker, else_branch);
|
||||||
|
} else {
|
||||||
|
for child : else_branch.children {
|
||||||
|
add_child(parent, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
if checker.current_scope == 1 {
|
||||||
|
if else_branch.kind == .If_Directive {
|
||||||
|
check_declaration(checker, else_branch);
|
||||||
|
} else {
|
||||||
|
traverse(checker, else_branch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
directive.children.count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check_declaration :: (checker : *Checker, declaration : *AST_Node) {
|
||||||
if declaration.kind == .Function {
|
if declaration.kind == .Function {
|
||||||
if declaration.foreign_declaration {
|
if declaration.foreign_declaration {
|
||||||
fun_handle := declare_foreign_function(checker, declaration);
|
fun_handle := declare_foreign_function(checker, declaration);
|
||||||
@@ -1701,23 +1787,35 @@ traverse :: (checker : *Semantic_Checker, root : *AST_Node) {
|
|||||||
declare_struct(checker, declaration);
|
declare_struct(checker, declaration);
|
||||||
} else if declaration.kind == .CBuffer {
|
} else if declaration.kind == .CBuffer {
|
||||||
declare_cbuffer(checker, declaration);
|
declare_cbuffer(checker, declaration);
|
||||||
|
} else if declaration.kind == .If_Directive {
|
||||||
|
check_if_directive(checker, declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
traverse :: (checker : *Checker, root : *AST_Node) {
|
||||||
|
declarations := root.children;
|
||||||
|
for declaration : declarations {
|
||||||
|
check_declaration(checker, declaration);
|
||||||
|
}
|
||||||
|
|
||||||
if checker.had_error {
|
if checker.had_error {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for declaration : declarations {
|
for declaration : declarations {
|
||||||
|
if declaration.kind == .If_Directive {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
check_node(checker, declaration);
|
check_node(checker, declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
traverse :: (checker : *Semantic_Checker) {
|
traverse :: (checker : *Checker) {
|
||||||
traverse(checker, checker.program_root);
|
traverse(checker, checker.program_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
types_compatible :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rhs : Type_Variable_Handle, param_matching : bool = false) -> bool {
|
types_compatible :: (checker : *Checker, lhs : Type_Variable_Handle, rhs : Type_Variable_Handle, param_matching : bool = false) -> bool {
|
||||||
lhs_var := from_handle(checker, lhs);
|
lhs_var := from_handle(checker, lhs);
|
||||||
rhs_var := from_handle(checker, rhs);
|
rhs_var := from_handle(checker, rhs);
|
||||||
|
|
||||||
@@ -1797,7 +1895,7 @@ types_compatible :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rh
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_builtins_new :: (checker : *Semantic_Checker) {
|
add_builtins_new :: (checker : *Checker) {
|
||||||
|
|
||||||
checker.state = .Adding_Builtins;
|
checker.state = .Adding_Builtins;
|
||||||
float_name := Typenames[Type_Kind.Float];
|
float_name := Typenames[Type_Kind.Float];
|
||||||
@@ -2065,7 +2163,7 @@ add_builtins_new :: (checker : *Semantic_Checker) {
|
|||||||
checker.state = .Type_Checking;
|
checker.state = .Type_Checking;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_builtins :: (checker : *Semantic_Checker) {
|
add_builtins :: (checker : *Checker) {
|
||||||
source_location := #location().fully_pathed_filename;
|
source_location := #location().fully_pathed_filename;
|
||||||
path_array := split(source_location, "/");
|
path_array := split(source_location, "/");
|
||||||
|
|
||||||
@@ -2084,7 +2182,7 @@ add_builtins :: (checker : *Semantic_Checker) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
messages : [..]Compiler_Message;
|
messages : [..]Compiler_Message;
|
||||||
internal_error_message(*messages, "Error loading builtin functions.", checker.path);
|
internal_error_message(*messages, "Error loading builtin functions.", checker.path);
|
||||||
print("%\n", report_messages(messages));
|
print("%\n", report_messages(checker.ctx, messages));
|
||||||
assert(false);
|
assert(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2123,7 +2221,7 @@ add_builtins :: (checker : *Semantic_Checker) {
|
|||||||
checker.ctx.tokens = prev_tokens;
|
checker.ctx.tokens = prev_tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_check :: (checker : *Semantic_Checker, root : *AST_Node) {
|
type_check :: (checker : *Checker, root : *AST_Node) {
|
||||||
traverse(checker, root);
|
traverse(checker, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2138,7 +2236,7 @@ check :: (ctx : *Compiler_Context, allocator : Allocator = temp) {
|
|||||||
init_context_allocators();
|
init_context_allocators();
|
||||||
defer clear_context_allocators();
|
defer clear_context_allocators();
|
||||||
|
|
||||||
checker : Semantic_Checker;
|
checker : Checker;
|
||||||
|
|
||||||
checker.current_buffer_index = 0;
|
checker.current_buffer_index = 0;
|
||||||
checker.current_sampler_index = 0;
|
checker.current_sampler_index = 0;
|
||||||
@@ -2255,7 +2353,7 @@ pretty_print_struct :: (scope_stack : *Scope_Stack, current_scope : Scope_Handle
|
|||||||
append(builder, "}\n");
|
append(builder, "}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
pretty_print_scope :: (current_scope : Scope_Handle, scope_stack : Scope_Stack, variables : []Type_Variable, scope : *Scope, builder : *String_Builder, indentation : int = 0) {
|
pretty_print_scope :: (ctx : *Compiler_Context, current_scope : Scope_Handle, scope_stack : Scope_Stack, variables : []Type_Variable, scope : *Scope, builder : *String_Builder, indentation : int = 0) {
|
||||||
if scope.builtin {
|
if scope.builtin {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2291,7 +2389,7 @@ pretty_print_scope :: (current_scope : Scope_Handle, scope_stack : Scope_Stack,
|
|||||||
if type_variable.typename.count > 0 && type_variable.source_kind != .Declaration {
|
if type_variable.typename.count > 0 && type_variable.source_kind != .Declaration {
|
||||||
indent(builder, indentation + 1);
|
indent(builder, indentation + 1);
|
||||||
print_key(*scope_stack, current_scope, builder, key);
|
print_key(*scope_stack, current_scope, builder, key);
|
||||||
print_type_variable(builder, variables, type_variable);
|
print_type_variable(ctx, builder, variables, type_variable);
|
||||||
append(builder, "\n");
|
append(builder, "\n");
|
||||||
// print_to_builder(builder, "%\n", type_variable.typename);
|
// print_to_builder(builder, "%\n", type_variable.typename);
|
||||||
} else {
|
} else {
|
||||||
@@ -2334,7 +2432,7 @@ pretty_print_scope :: (current_scope : Scope_Handle, scope_stack : Scope_Stack,
|
|||||||
|
|
||||||
for child : scope.children {
|
for child : scope.children {
|
||||||
child_scope := *scope_stack.stack[child - 1];
|
child_scope := *scope_stack.stack[child - 1];
|
||||||
pretty_print_scope(current_scope, *scope_stack, variables, child_scope, builder, indentation + 1);
|
pretty_print_scope(ctx, current_scope, *scope_stack, variables, child_scope, builder, indentation + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if scope.table.count > 0 {
|
if scope.table.count > 0 {
|
||||||
@@ -2343,7 +2441,7 @@ pretty_print_scope :: (current_scope : Scope_Handle, scope_stack : Scope_Stack,
|
|||||||
append(builder, "]\n");
|
append(builder, "]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
print_type_variable :: (builder : *String_Builder, variables : []Type_Variable, variable : Type_Variable) {
|
print_type_variable :: (ctx : *Compiler_Context, builder : *String_Builder, variables : []Type_Variable, variable : Type_Variable) {
|
||||||
if variable.builtin {
|
if variable.builtin {
|
||||||
if variable.type != .Function || variable.type != .Struct {
|
if variable.type != .Function || variable.type != .Struct {
|
||||||
print_to_builder(builder, "%", type_to_string(variable));
|
print_to_builder(builder, "%", type_to_string(variable));
|
||||||
@@ -2391,13 +2489,13 @@ print_type_variable :: (builder : *String_Builder, variables : []Type_Variable,
|
|||||||
source_location.end = right_most.source_location.main_token;
|
source_location.end = right_most.source_location.main_token;
|
||||||
source_location.main_token = node.source_location.main_token;
|
source_location.main_token = node.source_location.main_token;
|
||||||
|
|
||||||
print("%\n", print_from_source_location(builder, source_location,, temp));
|
print("%\n", print_from_source_location(ctx, builder, source_location,, temp));
|
||||||
}
|
}
|
||||||
case .Call; {
|
case .Call; {
|
||||||
if variable.return_type_variable{
|
if variable.return_type_variable{
|
||||||
assert(false);
|
assert(false);
|
||||||
print_to_builder(builder, "%", variable.typename);
|
print_to_builder(builder, "%", variable.typename);
|
||||||
print_type_variable(builder, variables, variable.return_type_variable);
|
print_type_variable(ctx, builder, variables, variable.return_type_variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
print_to_builder(builder, "%(", node.name);
|
print_to_builder(builder, "%(", node.name);
|
||||||
@@ -2406,7 +2504,7 @@ print_type_variable :: (builder : *String_Builder, variables : []Type_Variable,
|
|||||||
for child : node.children {
|
for child : node.children {
|
||||||
if child.kind == .ArgList {
|
if child.kind == .ArgList {
|
||||||
for arg : child.children {
|
for arg : child.children {
|
||||||
print_type_variable(builder, variables, arg.type_variable);
|
print_type_variable(ctx, builder, variables, arg.type_variable);
|
||||||
|
|
||||||
if it_index < child.children.count - 1 {
|
if it_index < child.children.count - 1 {
|
||||||
append(builder, ", ");
|
append(builder, ", ");
|
||||||
@@ -2418,23 +2516,23 @@ print_type_variable :: (builder : *String_Builder, variables : []Type_Variable,
|
|||||||
append(builder, ")");
|
append(builder, ")");
|
||||||
}
|
}
|
||||||
case; {
|
case; {
|
||||||
print("%\n", print_from_source_location(builder, node.source_location,, temp));
|
print("%\n", print_from_source_location(ctx, builder, node.source_location,, temp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print_type_variable :: (builder : *String_Builder, variables : []Type_Variable, handle : Type_Variable_Handle) {
|
print_type_variable :: (ctx : *Compiler_Context, builder : *String_Builder, variables : []Type_Variable, handle : Type_Variable_Handle) {
|
||||||
variable := from_handle(variables, handle);
|
variable := from_handle(variables, handle);
|
||||||
print_type_variable(builder, variables, variable);
|
print_type_variable(ctx, builder, variables, variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
pretty_print_symbol_table :: (checker : *Semantic_Checker, allocator : Allocator) -> string {
|
pretty_print_symbol_table :: (checker : *Checker, allocator : Allocator) -> string {
|
||||||
builder : String_Builder;
|
builder : String_Builder;
|
||||||
init_string_builder(*builder,, allocator);
|
init_string_builder(*builder,, allocator);
|
||||||
|
|
||||||
pretty_print_scope(xx checker.current_scope, checker.ctx.scope_stack, checker.ctx.type_variables, *checker.ctx.scope_stack.stack[0], *builder);
|
pretty_print_scope(checker.ctx, xx checker.current_scope, checker.ctx.scope_stack, checker.ctx.type_variables, *checker.ctx.scope_stack.stack[0], *builder);
|
||||||
|
|
||||||
return builder_to_string(*builder,, allocator);
|
return builder_to_string(*builder,, allocator);
|
||||||
}
|
}
|
||||||
@@ -2444,7 +2542,7 @@ pretty_print_symbol_table :: (ctx : *Compiler_Context, allocator : Allocator) ->
|
|||||||
init_string_builder(*builder,, allocator);
|
init_string_builder(*builder,, allocator);
|
||||||
|
|
||||||
current_scope := cast(Scope_Handle)1;
|
current_scope := cast(Scope_Handle)1;
|
||||||
pretty_print_scope(current_scope, ctx.scope_stack, ctx.type_variables, *ctx.scope_stack.stack[0], *builder);
|
pretty_print_scope(ctx, current_scope, ctx.scope_stack, ctx.type_variables, *ctx.scope_stack.stack[0], *builder);
|
||||||
|
|
||||||
return builder_to_string(*builder,, allocator);
|
return builder_to_string(*builder,, allocator);
|
||||||
}
|
}
|
||||||
22
Codegen.jai
22
Codegen.jai
@@ -11,17 +11,14 @@ Output_Language :: enum {
|
|||||||
HLSL;
|
HLSL;
|
||||||
GLSL; // @Incomplete
|
GLSL; // @Incomplete
|
||||||
MLSL; // @Incomplete
|
MLSL; // @Incomplete
|
||||||
|
// SPIRV; // @Incomplete: Should we do this?
|
||||||
}
|
}
|
||||||
|
|
||||||
Codegen_State :: struct {
|
Codegen_State :: struct {
|
||||||
path : string;
|
path : string;
|
||||||
|
|
||||||
// scope_stack : Scope_Stack;
|
|
||||||
current_scope : Scope_Handle;
|
current_scope : Scope_Handle;
|
||||||
|
|
||||||
// type_variables : []Type_Variable;
|
|
||||||
// root : *AST_Node;
|
|
||||||
|
|
||||||
output_language : Output_Language;
|
output_language : Output_Language;
|
||||||
|
|
||||||
builder : String_Builder;
|
builder : String_Builder;
|
||||||
@@ -29,14 +26,6 @@ Codegen_State :: struct {
|
|||||||
result : *Compiler_Context;
|
result : *Compiler_Context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Codegen_Result :: struct {
|
|
||||||
// messages : [..]Compiler_Message;
|
|
||||||
|
|
||||||
// had_error : bool;
|
|
||||||
|
|
||||||
// result_text : string; // @Incomplete(nb): Result for now, should likely be far more sophisticated.
|
|
||||||
// }
|
|
||||||
|
|
||||||
Reserved_HLSL_Words :: string.[
|
Reserved_HLSL_Words :: string.[
|
||||||
"texture",
|
"texture",
|
||||||
"sampler",
|
"sampler",
|
||||||
@@ -132,26 +121,23 @@ emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
|
|||||||
|
|
||||||
print_to_builder(*state.builder, " = ");
|
print_to_builder(*state.builder, " = ");
|
||||||
emit_node(state, child, 0);
|
emit_node(state, child, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.parent.kind == .Block {
|
if node.parent.kind == .Block {
|
||||||
append(*state.builder, ";");
|
append(*state.builder, ";");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for i :0..field.children.count - 1 {
|
for i :0..field.children.count - 1 {
|
||||||
child := from_handle(state.result.type_variables, field.children[i]);
|
child := from_handle(state.result.type_variables, field.children[i]);
|
||||||
emit_node(state, child.source_node, 0);
|
emit_node(state, child.source_node, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for hint : node.hint_tokens {
|
for hint : node.hint_tokens {
|
||||||
if hint.ident_value == "position" {
|
if lookup_hint(hint.ident_value) == .Position {
|
||||||
// @Incomplete(nb): Should be a lookup table somewhere
|
|
||||||
append(*state.builder, " : POSITION");
|
append(*state.builder, " : POSITION");
|
||||||
} else if hint.ident_value == "uv" {
|
} else if lookup_hint(hint.ident_value) == .UV {
|
||||||
append(*state.builder, " : TEXCOORD0");
|
append(*state.builder, " : TEXCOORD0");
|
||||||
} else if hint.ident_value == "outposition" {
|
} else if lookup_hint(hint.ident_value) == .Output_Position {
|
||||||
append(*state.builder, " : SV_POSITION");
|
append(*state.builder, " : SV_POSITION");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
Error.jai
12
Error.jai
@@ -102,20 +102,20 @@ copy_messages :: (source : []Compiler_Message, dest : *[..]Compiler_Message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
report_messages :: (messages : []Compiler_Message) -> string {
|
report_messages :: (ctx : *Compiler_Context, messages : []Compiler_Message) -> string {
|
||||||
builder : String_Builder;
|
builder : String_Builder;
|
||||||
init_string_builder(*builder);
|
init_string_builder(*builder);
|
||||||
for message : messages {
|
for message : messages {
|
||||||
report_message(*builder, message);
|
report_message(ctx, *builder, message);
|
||||||
}
|
}
|
||||||
return builder_to_string(*builder);
|
return builder_to_string(*builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
report_message :: (builder : *String_Builder, message : Compiler_Message) {
|
report_message :: (ctx : *Compiler_Context, builder : *String_Builder, message : Compiler_Message) {
|
||||||
report_message(builder, message.path, message.message, message.source_locations, message.message_kind, message.report_source_location);
|
report_message(ctx, builder, message.path, message.message, message.source_locations, message.message_kind, message.report_source_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
report_message :: (builder : *String_Builder, path : string, message : string, source_locations : []Source_Range, kind : Message_Kind, report_source_location : bool = false) {
|
report_message :: (ctx : *Compiler_Context, builder : *String_Builder, path : string, message : string, source_locations : []Source_Range, kind : Message_Kind, report_source_location : bool = false) {
|
||||||
append(builder, "\x1b[1;37m");
|
append(builder, "\x1b[1;37m");
|
||||||
if path.count > 0 {
|
if path.count > 0 {
|
||||||
print_to_builder(builder, "%:", path);
|
print_to_builder(builder, "%:", path);
|
||||||
@@ -140,7 +140,7 @@ report_message :: (builder : *String_Builder, path : string, message : string, s
|
|||||||
if report_source_location {
|
if report_source_location {
|
||||||
for location : source_locations {
|
for location : source_locations {
|
||||||
append(builder, "\t");
|
append(builder, "\t");
|
||||||
print_from_source_location(builder, location);
|
print_from_source_location(ctx, builder, location);
|
||||||
append(builder, "\n\t");
|
append(builder, "\n\t");
|
||||||
begin := location.begin;
|
begin := location.begin;
|
||||||
|
|
||||||
|
|||||||
60
Ink.jai
60
Ink.jai
@@ -23,7 +23,7 @@ LEXER_FOLDER :: "lex";
|
|||||||
PARSER_FOLDER :: "parse";
|
PARSER_FOLDER :: "parse";
|
||||||
CODEGEN_FOLDER :: "codegen";
|
CODEGEN_FOLDER :: "codegen";
|
||||||
COMPILED_FOLDER :: "compiled";
|
COMPILED_FOLDER :: "compiled";
|
||||||
SEMANTIC_ANALYSIS_FOLDER :: "semant";
|
CHECK_FOLDER :: "check";
|
||||||
TESTS_FOLDER :: "test";
|
TESTS_FOLDER :: "test";
|
||||||
|
|
||||||
SHADER_EXTENSION :: "ink";
|
SHADER_EXTENSION :: "ink";
|
||||||
@@ -32,7 +32,7 @@ SUITE_EXTENSION :: "suite";
|
|||||||
Stage_Flags :: enum_flags u16 {
|
Stage_Flags :: enum_flags u16 {
|
||||||
Lexer :: 0x1;
|
Lexer :: 0x1;
|
||||||
Parser :: 0x2;
|
Parser :: 0x2;
|
||||||
Semantic_Analysis :: 0x4;
|
Check :: 0x4;
|
||||||
Codegen :: 0x8;
|
Codegen :: 0x8;
|
||||||
Compile :: 0x10;
|
Compile :: 0x10;
|
||||||
}
|
}
|
||||||
@@ -97,10 +97,10 @@ get_golden_path :: (file_path : string, stage : Stage_Flags) -> string {
|
|||||||
make_directory_if_it_does_not_exist(dir);
|
make_directory_if_it_does_not_exist(dir);
|
||||||
array_add(*path.words, PARSER_FOLDER);
|
array_add(*path.words, PARSER_FOLDER);
|
||||||
}
|
}
|
||||||
case .Semantic_Analysis; {
|
case .Check; {
|
||||||
dir := tprint("%/%", TESTS_FOLDER, SEMANTIC_ANALYSIS_FOLDER);
|
dir := tprint("%/%", TESTS_FOLDER, CHECK_FOLDER);
|
||||||
make_directory_if_it_does_not_exist(dir);
|
make_directory_if_it_does_not_exist(dir);
|
||||||
array_add(*path.words, SEMANTIC_ANALYSIS_FOLDER);
|
array_add(*path.words, CHECK_FOLDER);
|
||||||
}
|
}
|
||||||
case .Codegen; {
|
case .Codegen; {
|
||||||
dir := tprint("%/%", TESTS_FOLDER, CODEGEN_FOLDER);
|
dir := tprint("%/%", TESTS_FOLDER, CODEGEN_FOLDER);
|
||||||
@@ -189,7 +189,7 @@ run_codegen_test :: (ctx : *Compiler_Context, output_type : Output_Type = 0) ->
|
|||||||
|
|
||||||
if ctx.had_error {
|
if ctx.had_error {
|
||||||
result.type = .Failed;
|
result.type = .Failed;
|
||||||
result_text = report_messages(ctx.messages);
|
result_text = report_messages(ctx, ctx.messages);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +227,22 @@ run_compile_test :: (path : string, output_type : Output_Type = 0) -> Result, Co
|
|||||||
print_to_builder(*sb, "[pixel entry point] - %\n", ctx.pixel_entry_point.name);
|
print_to_builder(*sb, "[pixel entry point] - %\n", ctx.pixel_entry_point.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctx.properties.fields.count > 0{
|
||||||
|
|
||||||
|
props := ctx.properties;
|
||||||
|
append(*sb, "[");
|
||||||
|
if ctx.property_name.count > 0 {
|
||||||
|
print_to_builder(*sb, "% :: ", ctx.property_name);
|
||||||
|
}
|
||||||
|
print_to_builder(*sb, "properties] - %\n", props.buffer_index);
|
||||||
|
|
||||||
|
indent(*sb, 1);
|
||||||
|
for field : props.fields {
|
||||||
|
append(*sb, "[field] - ");
|
||||||
|
pretty_print_field(*sb, *field.base_field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for cb : ctx.cbuffers {
|
for cb : ctx.cbuffers {
|
||||||
print_to_builder(*sb, "[constant_buffer] - % - %\n", cb.name, cb.buffer_index);
|
print_to_builder(*sb, "[constant_buffer] - % - %\n", cb.name, cb.buffer_index);
|
||||||
|
|
||||||
@@ -261,7 +277,7 @@ run_lexer_test :: (file_path : string, ctx : *Compiler_Context, output_type : Ou
|
|||||||
lex(ctx);
|
lex(ctx);
|
||||||
if ctx.had_error {
|
if ctx.had_error {
|
||||||
result.type = .Failed;
|
result.type = .Failed;
|
||||||
result_text = report_messages(ctx.messages);
|
result_text = report_messages(ctx, ctx.messages);
|
||||||
} else {
|
} else {
|
||||||
result_text = pretty_print_tokens(ctx.tokens, context.allocator);
|
result_text = pretty_print_tokens(ctx.tokens, context.allocator);
|
||||||
}
|
}
|
||||||
@@ -300,7 +316,7 @@ run_parser_test :: (ctx : *Compiler_Context, output_type : Output_Type = 0) -> R
|
|||||||
|
|
||||||
if ctx.had_error {
|
if ctx.had_error {
|
||||||
result.type = .Failed;
|
result.type = .Failed;
|
||||||
result_text = report_messages(ctx.messages);
|
result_text = report_messages(ctx, ctx.messages);
|
||||||
} else {
|
} else {
|
||||||
result_text = pretty_print_ast(ctx.root, context.allocator);
|
result_text = pretty_print_ast(ctx.root, context.allocator);
|
||||||
}
|
}
|
||||||
@@ -316,7 +332,7 @@ run_parser_test :: (ctx : *Compiler_Context, output_type : Output_Type = 0) -> R
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
run_semantic_analysis_test :: (ctx : *Compiler_Context, output_type : Output_Type = 0) -> Result {
|
run_check_test :: (ctx : *Compiler_Context, output_type : Output_Type = 0) -> Result {
|
||||||
result : Result;
|
result : Result;
|
||||||
result.path = ctx.file.path;
|
result.path = ctx.file.path;
|
||||||
result_text : string;
|
result_text : string;
|
||||||
@@ -325,7 +341,7 @@ run_semantic_analysis_test :: (ctx : *Compiler_Context, output_type : Output_Typ
|
|||||||
|
|
||||||
if ctx.had_error {
|
if ctx.had_error {
|
||||||
result.type = .Failed;
|
result.type = .Failed;
|
||||||
result_text = report_messages(ctx.messages);
|
result_text = report_messages(ctx, ctx.messages);
|
||||||
} else {
|
} else {
|
||||||
result_text = pretty_print_symbol_table(ctx, context.allocator);
|
result_text = pretty_print_symbol_table(ctx, context.allocator);
|
||||||
}
|
}
|
||||||
@@ -336,12 +352,12 @@ run_semantic_analysis_test :: (ctx : *Compiler_Context, output_type : Output_Typ
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
golden_path := get_golden_path(ctx.file.path, .Semantic_Analysis);
|
golden_path := get_golden_path(ctx.file.path, .Check);
|
||||||
do_golden_comparison(golden_path, result_text, *result, output_type);
|
do_golden_comparison(golden_path, result_text, *result, output_type);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
run_semantic_analysis_test :: (file_path : string, ctx : *Compiler_Context, output_type : Output_Type = 0) -> Result {
|
run_check_test :: (file_path : string, ctx : *Compiler_Context, output_type : Output_Type = 0) -> Result {
|
||||||
result : Result;
|
result : Result;
|
||||||
result.path = file_path;
|
result.path = file_path;
|
||||||
|
|
||||||
@@ -352,7 +368,7 @@ run_semantic_analysis_test :: (file_path : string, ctx : *Compiler_Context, outp
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = run_semantic_analysis_test(ctx, output_type);
|
result = run_check_test(ctx, output_type);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -389,17 +405,17 @@ run_test_new :: (file_path : string, stage_flags : Stage_Flags, results : *[..]R
|
|||||||
record_result(results, result);
|
record_result(results, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if stage_flags & .Semantic_Analysis {
|
if stage_flags & .Check {
|
||||||
if stage_flags & .Parser && (result.type == .Passed || result.type == .Golden_Output) {
|
if stage_flags & .Parser && (result.type == .Passed || result.type == .Golden_Output) {
|
||||||
result = run_semantic_analysis_test(*ctx, output_type);
|
result = run_check_test(*ctx, output_type);
|
||||||
} else {
|
} else {
|
||||||
result = run_semantic_analysis_test(file_path, *ctx, output_type);
|
result = run_check_test(file_path, *ctx, output_type);
|
||||||
}
|
}
|
||||||
record_result(results, result);
|
record_result(results, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if stage_flags & .Codegen {
|
if stage_flags & .Codegen {
|
||||||
if stage_flags & .Semantic_Analysis && (result.type == .Passed || result.type == .Golden_Output) {
|
if stage_flags & .Check && (result.type == .Passed || result.type == .Golden_Output) {
|
||||||
result = run_codegen_test(*ctx, output_type);
|
result = run_codegen_test(*ctx, output_type);
|
||||||
} else {
|
} else {
|
||||||
result = run_codegen_test(file_path, *ctx, output_type);
|
result = run_codegen_test(file_path, *ctx, output_type);
|
||||||
@@ -554,8 +570,8 @@ read_suite :: (file_path : string, suite : *Test_Suite, allocator := temp) -> bo
|
|||||||
stage_flags |= .Lexer;
|
stage_flags |= .Lexer;
|
||||||
} else if equal(trimmed, "parse") {
|
} else if equal(trimmed, "parse") {
|
||||||
stage_flags |= .Parser;
|
stage_flags |= .Parser;
|
||||||
} else if equal(trimmed, "semant") {
|
} else if equal(trimmed, "check") {
|
||||||
stage_flags |= .Semantic_Analysis;
|
stage_flags |= .Check;
|
||||||
} else if equal(trimmed, "codegen") {
|
} else if equal(trimmed, "codegen") {
|
||||||
stage_flags |= .Codegen;
|
stage_flags |= .Codegen;
|
||||||
} else if equal(trimmed, "compile") {
|
} else if equal(trimmed, "compile") {
|
||||||
@@ -577,7 +593,7 @@ stage_to_string :: (stage : Stage_Flags) -> string {
|
|||||||
if #complete stage == {
|
if #complete stage == {
|
||||||
case .Lexer; return "lexing";
|
case .Lexer; return "lexing";
|
||||||
case .Parser; return "parsing";
|
case .Parser; return "parsing";
|
||||||
case .Semantic_Analysis; return "semantic checking";
|
case .Check; return "checking";
|
||||||
case .Codegen; return "codegen";
|
case .Codegen; return "codegen";
|
||||||
case .Compile; return "compiled";
|
case .Compile; return "compiled";
|
||||||
case; return "";
|
case; return "";
|
||||||
@@ -671,8 +687,8 @@ main :: () {
|
|||||||
current_suite.test_cases[cases - 1].stage_flags |= .Lexer;
|
current_suite.test_cases[cases - 1].stage_flags |= .Lexer;
|
||||||
} else if arg == "-parse" {
|
} else if arg == "-parse" {
|
||||||
current_suite.test_cases[cases - 1].stage_flags |= .Parser;
|
current_suite.test_cases[cases - 1].stage_flags |= .Parser;
|
||||||
} else if arg == "-semant" {
|
} else if arg == "-check" {
|
||||||
current_suite.test_cases[cases - 1].stage_flags |= .Semantic_Analysis;
|
current_suite.test_cases[cases - 1].stage_flags |= .Check;
|
||||||
} else if arg == "-codegen" {
|
} else if arg == "-codegen" {
|
||||||
current_suite.test_cases[cases - 1].stage_flags |= .Codegen;
|
current_suite.test_cases[cases - 1].stage_flags |= .Codegen;
|
||||||
} else if arg == "-compile" {
|
} else if arg == "-compile" {
|
||||||
|
|||||||
29
Lexing.jai
29
Lexing.jai
@@ -11,6 +11,7 @@ Lexer :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Token_Kind :: enum {
|
Token_Kind :: enum {
|
||||||
|
TOKEN_INVALID :: 0;
|
||||||
TOKEN_FLOATLITERAL;
|
TOKEN_FLOATLITERAL;
|
||||||
TOKEN_INTLITERAL;
|
TOKEN_INTLITERAL;
|
||||||
|
|
||||||
@@ -386,7 +387,12 @@ make_directive :: (lexer : *Lexer) -> *Token {
|
|||||||
for tok : ctx.tokens {
|
for tok : ctx.tokens {
|
||||||
lexer.ctx.tokens[it_index] = tok;
|
lexer.ctx.tokens[it_index] = tok;
|
||||||
}
|
}
|
||||||
return scan_next_token(lexer);;
|
return scan_next_token(lexer);
|
||||||
|
} else if ident.ident_value == "add_define" {
|
||||||
|
new_define := scan_next_token(lexer);
|
||||||
|
add_define(*lexer.ctx.environment, new_define.ident_value);
|
||||||
|
lexer.ctx.tokens.count -= 2;
|
||||||
|
return scan_next_token(lexer);
|
||||||
}
|
}
|
||||||
return ident;
|
return ident;
|
||||||
}
|
}
|
||||||
@@ -739,10 +745,25 @@ print_token_pointer :: (builder : *String_Builder, token : Token) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print_from_source_location :: (builder : *String_Builder, source_location : Source_Range, indentation : int = 0) {
|
print_from_source_location :: (ctx : *Compiler_Context, builder : *String_Builder, source_location : Source_Range, indentation : int = 0) {
|
||||||
current := source_location.begin;
|
current := source_location.begin;
|
||||||
begin := source_location.begin;
|
begin := source_location.begin;
|
||||||
end := source_location.end;
|
end := source_location.end;
|
||||||
|
|
||||||
|
if begin.builtin {
|
||||||
|
for i : begin.index..end.index - 1 {
|
||||||
|
tok := ctx.tokens[i];
|
||||||
|
text : string;
|
||||||
|
text.data = tok.source;
|
||||||
|
text.count = tok.length;
|
||||||
|
print_to_builder(builder, "%", text);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
begin_pos := 0;
|
begin_pos := 0;
|
||||||
token_string : string;
|
token_string : string;
|
||||||
count := end.index - begin.index + end.length;
|
count := end.index - begin.index + end.length;
|
||||||
@@ -769,12 +790,12 @@ print_from_source_location :: (builder : *String_Builder, source_location : Sour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print_from_source_location :: (source_location : Source_Range, allocator := context.allocator, indentation : int = 0) -> string {
|
print_from_source_location :: (ctx : *Compiler_Context, source_location : Source_Range, allocator := context.allocator, indentation : int = 0) -> string {
|
||||||
sc := get_scratch();
|
sc := get_scratch();
|
||||||
defer scratch_end(sc);
|
defer scratch_end(sc);
|
||||||
builder : String_Builder;
|
builder : String_Builder;
|
||||||
init_string_builder(*builder,, sc.allocator);
|
init_string_builder(*builder,, sc.allocator);
|
||||||
print_from_source_location(*builder, source_location,, sc.allocator);
|
print_from_source_location(ctx, *builder, source_location,, sc.allocator);
|
||||||
return builder_to_string(*builder,, allocator);
|
return builder_to_string(*builder,, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
168
Parsing.jai
168
Parsing.jai
@@ -186,7 +186,7 @@ unexpected_token :: (state : *Parse_State, token : Token, message : string) {
|
|||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(state.ctx, location));
|
||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_token_pointer(*builder, token);
|
print_token_pointer(*builder, token);
|
||||||
@@ -207,7 +207,7 @@ else_if_without_if :: (state : *Parse_State) {
|
|||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(state.ctx, location));
|
||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_token_pointer(*builder, token);
|
print_token_pointer(*builder, token);
|
||||||
@@ -229,7 +229,7 @@ else_without_if :: (state : *Parse_State) {
|
|||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(state.ctx, location));
|
||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_token_pointer(*builder, token);
|
print_token_pointer(*builder, token);
|
||||||
@@ -249,7 +249,7 @@ unable_to_parse_statement :: (state : *Parse_State, token : Token, message : str
|
|||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(state.ctx, location));
|
||||||
|
|
||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
@@ -269,7 +269,7 @@ expected_expression :: (state : *Parse_State, token : Token, message : string) {
|
|||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(state.ctx, location));
|
||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
print_token_pointer(*builder, token);
|
print_token_pointer(*builder, token);
|
||||||
@@ -288,7 +288,7 @@ missing_type_specifier :: (state : *Parse_State, token : Token, message : string
|
|||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(state.ctx, location));
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
|
|
||||||
loc := location.begin;
|
loc := location.begin;
|
||||||
@@ -312,7 +312,7 @@ empty_block :: (state : *Parse_State, token : Token, message : string) {
|
|||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(state.ctx, location));
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
|
|
||||||
loc := location.begin;
|
loc := location.begin;
|
||||||
@@ -336,7 +336,26 @@ unable_to_open_file :: (state : *Parse_State, path : string, token : Token) {
|
|||||||
|
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
cyan(*builder);
|
cyan(*builder);
|
||||||
print_to_builder(*builder, "%\n", print_from_source_location(location));
|
print_to_builder(*builder, "%\n", print_from_source_location(state.ctx, location));
|
||||||
|
indent(*builder, 1);
|
||||||
|
|
||||||
|
loc := location.begin;
|
||||||
|
print_token_pointer(*builder, loc);
|
||||||
|
|
||||||
|
final_message := builder_to_string(*builder);
|
||||||
|
record_error(state, token, final_message, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry_point_requires_return_value :: (state : *Parse_State, token : Token) {
|
||||||
|
builder : String_Builder;
|
||||||
|
init_string_builder(*builder,, temp);
|
||||||
|
|
||||||
|
print_to_builder(*builder, "Entry point '%' requires return value\n\n", token.ident_value);
|
||||||
|
|
||||||
|
location := generate_source_location_from_token(state, token);
|
||||||
|
indent(*builder, 1);
|
||||||
|
cyan(*builder);
|
||||||
|
print_to_builder(*builder, "%\n", print_from_source_location(state.ctx, location));
|
||||||
indent(*builder, 1);
|
indent(*builder, 1);
|
||||||
|
|
||||||
loc := location.begin;
|
loc := location.begin;
|
||||||
@@ -383,29 +402,14 @@ make_node :: (parse_state : *Parse_State, kind : AST_Kind) -> *AST_Node {
|
|||||||
return make_node(*parse_state.ctx.nodes, kind);
|
return make_node(*parse_state.ctx.nodes, kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
// new_builtin_node :: (nodes : *[..]AST_Node, kind : AST_Kind) -> *AST_Node {
|
make_builtin_token :: (tokens : *[..]Token, kind : Token_Kind, text : string, col : *int, line : *int) -> *Token {
|
||||||
// node := make_node(parse_state, kind);
|
|
||||||
// node.builtin = true;
|
|
||||||
// return node;
|
|
||||||
// }
|
|
||||||
|
|
||||||
make_builtin_token :: (tokens : *[..]Token, builder : *String_Builder, kind : Token_Kind, text : string, col : *int, line : *int) -> *Token {
|
|
||||||
tok : Token;
|
tok : Token;
|
||||||
tok.kind = kind;
|
tok.kind = kind;
|
||||||
|
|
||||||
start := 0;
|
start := 0;
|
||||||
|
|
||||||
buffer := get_current_buffer(builder);
|
|
||||||
|
|
||||||
if buffer {
|
|
||||||
start := buffer.count;
|
|
||||||
}
|
|
||||||
tok.column = col.*;
|
tok.column = col.*;
|
||||||
|
|
||||||
print_to_builder(builder, "%", text);
|
|
||||||
buffer = get_current_buffer(builder);
|
|
||||||
end := buffer.count;
|
|
||||||
|
|
||||||
for c : text {
|
for c : text {
|
||||||
if c == #char "\n" {
|
if c == #char "\n" {
|
||||||
line.* ++ 1;
|
line.* ++ 1;
|
||||||
@@ -415,9 +419,11 @@ make_builtin_token :: (tokens : *[..]Token, builder : *String_Builder, kind : To
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tok.index = buffer.count - text.count;
|
tok.index = tokens.count;
|
||||||
tok.length = text.count;
|
tok.length = text.count;
|
||||||
tok.builtin = true;
|
tok.builtin = true;
|
||||||
|
tok.source = text.data;
|
||||||
|
tok.ident_value = text;
|
||||||
|
|
||||||
array_add(tokens, tok);
|
array_add(tokens, tok);
|
||||||
|
|
||||||
@@ -427,9 +433,6 @@ make_builtin_token :: (tokens : *[..]Token, builder : *String_Builder, kind : To
|
|||||||
new_builtin_struct_node :: (ctx : *Compiler_Context, name : string, members : []Arg) -> *AST_Node {
|
new_builtin_struct_node :: (ctx : *Compiler_Context, name : string, members : []Arg) -> *AST_Node {
|
||||||
sc := get_scratch(context.allocator);
|
sc := get_scratch(context.allocator);
|
||||||
defer scratch_end(sc);
|
defer scratch_end(sc);
|
||||||
builder : String_Builder;
|
|
||||||
builder.allocator = sc.allocator; // I want to find a good way to use scratch here...
|
|
||||||
|
|
||||||
node := make_node(*ctx.nodes, .Struct);
|
node := make_node(*ctx.nodes, .Struct);
|
||||||
|
|
||||||
source_location : Source_Range;
|
source_location : Source_Range;
|
||||||
@@ -439,17 +442,13 @@ new_builtin_struct_node :: (ctx : *Compiler_Context, name : string, members : []
|
|||||||
|
|
||||||
tok_index := ctx.tokens.count;
|
tok_index := ctx.tokens.count;
|
||||||
|
|
||||||
ident_token := make_builtin_token(*ctx.tokens, *builder, .TOKEN_IDENTIFIER, tprint("%", name), *col, *line);
|
ident_token := make_builtin_token(*ctx.tokens, .TOKEN_IDENTIFIER, name, *col, *line);
|
||||||
ident_token.ident_value = name;
|
ident_token.ident_value = name;
|
||||||
source_location.begin = ident_token;
|
source_location.begin = ident_token;
|
||||||
|
|
||||||
append(*builder, " ");
|
make_builtin_token(*ctx.tokens, .TOKEN_DOUBLECOLON, " :: ", *col, *line);
|
||||||
make_builtin_token(*ctx.tokens, *builder, .TOKEN_DOUBLECOLON, "::", *col, *line);
|
make_builtin_token(*ctx.tokens, .TOKEN_STRUCT, "struct ", *col, *line);
|
||||||
append(*builder, " ");
|
make_builtin_token(*ctx.tokens, .TOKEN_LEFTBRACE, "{\n\t", *col, *line);
|
||||||
make_builtin_token(*ctx.tokens, *builder, .TOKEN_STRUCT, "struct", *col, *line);
|
|
||||||
append(*builder, " ");
|
|
||||||
make_builtin_token(*ctx.tokens, *builder, .TOKEN_LEFTBRACE, "{", *col, *line);
|
|
||||||
append(*builder, "\n");
|
|
||||||
line += 1;
|
line += 1;
|
||||||
col = 0;
|
col = 0;
|
||||||
|
|
||||||
@@ -460,18 +459,14 @@ new_builtin_struct_node :: (ctx : *Compiler_Context, name : string, members : []
|
|||||||
field := make_node(*ctx.nodes, .Field);
|
field := make_node(*ctx.nodes, .Field);
|
||||||
field_source_loc : Source_Range;
|
field_source_loc : Source_Range;
|
||||||
|
|
||||||
indent(*builder, 1);
|
field_ident := make_builtin_token(*ctx.tokens, .TOKEN_IDENTIFIER, member.name, *col, *line);
|
||||||
field_ident := make_builtin_token(*ctx.tokens, *builder, .TOKEN_IDENTIFIER, tprint("%", member.name), *col, *line);
|
|
||||||
field_source_loc.begin = field_ident;
|
field_source_loc.begin = field_ident;
|
||||||
field.token = field_ident;
|
field.token = field_ident;
|
||||||
field.name = member.name;
|
field.name = member.name;
|
||||||
|
|
||||||
append(*builder, " ");
|
make_builtin_token(*ctx.tokens, .TOKEN_COLON, ": ", *col, *line);
|
||||||
make_builtin_token(*ctx.tokens, *builder, .TOKEN_COLON, ":", *col, *line);
|
make_builtin_token(*ctx.tokens, .TOKEN_IDENTIFIER, member.typename, *col, *line);
|
||||||
append(*builder, " ");
|
semicolon_tok := make_builtin_token(*ctx.tokens, .TOKEN_SEMICOLON, ";", *col, *line);
|
||||||
make_builtin_token(*ctx.tokens, *builder, .TOKEN_IDENTIFIER, tprint("%", member.typename), *col, *line);
|
|
||||||
semicolon_tok := make_builtin_token(*ctx.tokens, *builder, .TOKEN_SEMICOLON, ";", *col, *line);
|
|
||||||
append(*builder, "\n");
|
|
||||||
col = 0;
|
col = 0;
|
||||||
line += 1;
|
line += 1;
|
||||||
|
|
||||||
@@ -481,27 +476,10 @@ new_builtin_struct_node :: (ctx : *Compiler_Context, name : string, members : []
|
|||||||
add_child(field_list, field);
|
add_child(field_list, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
brace_token := make_builtin_token(*ctx.tokens, *builder, .TOKEN_RIGHTBRACE, "}", *col, *line);
|
brace_token := make_builtin_token(*ctx.tokens, .TOKEN_RIGHTBRACE, "\n}", *col, *line);
|
||||||
append(*builder, "\n");
|
|
||||||
|
|
||||||
source_location.end = brace_token;
|
source_location.end = brace_token;
|
||||||
|
|
||||||
source := builder_to_string(*builder,, context.allocator);
|
|
||||||
|
|
||||||
source_location.begin.source = *source.data[source_location.begin.column];
|
|
||||||
source_location.end.source = *source.data[source_location.end.column];
|
|
||||||
|
|
||||||
for i : tok_index..ctx.tokens.count - 1 {
|
|
||||||
tok := ctx.tokens[i];
|
|
||||||
tok.source = *source.data[tok.column];
|
|
||||||
}
|
|
||||||
|
|
||||||
for field : field_list.children {
|
|
||||||
field.source_location.begin.source = *source.data[field.source_location.begin.column];
|
|
||||||
field.source_location.end.source = *source.data[field.source_location.end.column];
|
|
||||||
// field.source_location.main_token.source = *source.data[tok.column];
|
|
||||||
}
|
|
||||||
|
|
||||||
node.source_location = source_location;
|
node.source_location = source_location;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@@ -510,8 +488,6 @@ new_builtin_struct_node :: (ctx : *Compiler_Context, name : string, members : []
|
|||||||
new_builtin_function_node :: (ctx : *Compiler_Context, name : string, members : []Arg, return_var : Arg) -> *AST_Node {
|
new_builtin_function_node :: (ctx : *Compiler_Context, name : string, members : []Arg, return_var : Arg) -> *AST_Node {
|
||||||
sc := get_scratch(context.allocator);
|
sc := get_scratch(context.allocator);
|
||||||
defer scratch_end(sc);
|
defer scratch_end(sc);
|
||||||
builder : String_Builder;
|
|
||||||
builder.allocator = sc.allocator; // I want to find a good way to use scratch here...
|
|
||||||
|
|
||||||
node := make_node(*ctx.nodes, .Function);
|
node := make_node(*ctx.nodes, .Function);
|
||||||
|
|
||||||
@@ -522,13 +498,11 @@ new_builtin_function_node :: (ctx : *Compiler_Context, name : string, members :
|
|||||||
|
|
||||||
tok_index := ctx.tokens.count;
|
tok_index := ctx.tokens.count;
|
||||||
|
|
||||||
ident_token := make_builtin_token(*ctx.tokens, *builder, .TOKEN_IDENTIFIER, tprint("%", name), *col, *line);
|
ident_token := make_builtin_token(*ctx.tokens, .TOKEN_IDENTIFIER, name, *col, *line);
|
||||||
source_location.begin = ident_token;
|
source_location.begin = ident_token;
|
||||||
|
|
||||||
append(*builder, " ");
|
make_builtin_token(*ctx.tokens, .TOKEN_DOUBLECOLON, " :: ", *col, *line);
|
||||||
make_builtin_token(*ctx.tokens, *builder, .TOKEN_DOUBLECOLON, "::", *col, *line);
|
make_builtin_token(*ctx.tokens, .TOKEN_LEFTPAREN, "(", *col, *line);
|
||||||
append(*builder, " ");
|
|
||||||
make_builtin_token(*ctx.tokens, *builder, .TOKEN_LEFTPAREN, "(", *col, *line);
|
|
||||||
field_list := make_node(*ctx.nodes, .FieldList);
|
field_list := make_node(*ctx.nodes, .FieldList);
|
||||||
add_child(node, field_list);
|
add_child(node, field_list);
|
||||||
|
|
||||||
@@ -536,14 +510,12 @@ new_builtin_function_node :: (ctx : *Compiler_Context, name : string, members :
|
|||||||
field := make_node(*ctx.nodes, .Field);
|
field := make_node(*ctx.nodes, .Field);
|
||||||
field_source_loc : Source_Range;
|
field_source_loc : Source_Range;
|
||||||
|
|
||||||
// field_ident := make_builtin_token(*ctx.tokens, *builder, .TOKEN_IDENTIFIER, tprint("%", member.name), *col, *line);
|
type_tok := make_builtin_token(*ctx.tokens, .TOKEN_IDENTIFIER, member.typename, *col, *line);
|
||||||
type_tok := make_builtin_token(*ctx.tokens, *builder, .TOKEN_IDENTIFIER, tprint("%", member.typename), *col, *line);
|
|
||||||
field_source_loc.begin = type_tok;
|
field_source_loc.begin = type_tok;
|
||||||
field.token = type_tok;
|
field.token = type_tok;
|
||||||
|
|
||||||
if it_index < members.count - 1 {
|
if it_index < members.count - 1 {
|
||||||
make_builtin_token(*ctx.tokens, *builder, .TOKEN_COMMA, ",", *col, *line);
|
make_builtin_token(*ctx.tokens, .TOKEN_COMMA, ", ", *col, *line);
|
||||||
append(*builder, " ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
field_source_loc.end = type_tok;
|
field_source_loc.end = type_tok;
|
||||||
@@ -552,27 +524,11 @@ new_builtin_function_node :: (ctx : *Compiler_Context, name : string, members :
|
|||||||
add_child(field_list, field);
|
add_child(field_list, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
make_builtin_token(*ctx.tokens, *builder, .TOKEN_RIGHTPAREN, ")", *col, *line);
|
make_builtin_token(*ctx.tokens, .TOKEN_RIGHTPAREN, ")", *col, *line);
|
||||||
semicolon_tok := make_builtin_token(*ctx.tokens, *builder, .TOKEN_SEMICOLON, ";", *col, *line);
|
semicolon_tok := make_builtin_token(*ctx.tokens, .TOKEN_SEMICOLON, ";", *col, *line);
|
||||||
|
|
||||||
source_location.end = semicolon_tok;
|
source_location.end = semicolon_tok;
|
||||||
|
|
||||||
source := builder_to_string(*builder,, context.allocator);
|
|
||||||
|
|
||||||
source_location.begin.source = *source.data[source_location.begin.column];
|
|
||||||
source_location.end.source = *source.data[source_location.end.column];
|
|
||||||
|
|
||||||
for i : tok_index..ctx.tokens.count - 1 {
|
|
||||||
tok := ctx.tokens[i];
|
|
||||||
tok.source = *source.data[tok.column];
|
|
||||||
}
|
|
||||||
|
|
||||||
for field : field_list.children {
|
|
||||||
field.source_location.begin.source = *source.data[field.source_location.begin.column];
|
|
||||||
field.source_location.end.source = *source.data[field.source_location.end.column];
|
|
||||||
// field.source_location.main_token.source = *source.data[tok.column];
|
|
||||||
}
|
|
||||||
|
|
||||||
node.source_location = source_location;
|
node.source_location = source_location;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@@ -838,16 +794,28 @@ directive :: (state : *Parse_State) -> *AST_Node {
|
|||||||
if_directive := make_node(state, .If_Directive);
|
if_directive := make_node(state, .If_Directive);
|
||||||
|
|
||||||
source_location : Source_Range;
|
source_location : Source_Range;
|
||||||
// source_location.begin = state.previous;
|
if state.previous {
|
||||||
|
source_location.begin = state.previous;
|
||||||
|
} else {
|
||||||
|
source_location.begin = state.current;
|
||||||
|
}
|
||||||
|
|
||||||
advance(state);
|
advance(state);
|
||||||
|
|
||||||
cond := expression(state);
|
cond := expression(state);
|
||||||
add_child(if_directive, cond);
|
add_child(if_directive, cond);
|
||||||
|
|
||||||
|
source_location.end = state.previous;
|
||||||
|
advance_to_sync_point(state);
|
||||||
|
|
||||||
if_body := block(state);
|
if_body := block(state);
|
||||||
add_child(if_directive, if_body);
|
add_child(if_directive, if_body);
|
||||||
|
|
||||||
|
if match(state, .TOKEN_ELSE) {
|
||||||
|
else_node := else_statement(state);
|
||||||
|
add_child(if_directive, else_node);
|
||||||
|
}
|
||||||
|
|
||||||
if_directive.source_location = source_location;
|
if_directive.source_location = source_location;
|
||||||
|
|
||||||
return if_directive;
|
return if_directive;
|
||||||
@@ -1256,13 +1224,15 @@ statement :: (parse_state : *Parse_State) -> *AST_Node {
|
|||||||
else_statement :: (parse_state : *Parse_State) -> *AST_Node {
|
else_statement :: (parse_state : *Parse_State) -> *AST_Node {
|
||||||
if check(parse_state, .TOKEN_IF) {
|
if check(parse_state, .TOKEN_IF) {
|
||||||
return statement(parse_state);
|
return statement(parse_state);
|
||||||
|
} else if check(parse_state, .TOKEN_DIRECTIVE) && parse_state.current.ident_value == "if" {
|
||||||
|
return directive(parse_state);
|
||||||
}
|
}
|
||||||
return block(parse_state);
|
return block(parse_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
array_reserve(*node.children, 32);
|
||||||
|
|
||||||
source_location : Source_Range;
|
source_location : Source_Range;
|
||||||
|
|
||||||
@@ -1361,10 +1331,22 @@ function_declaration :: (parse_state : *Parse_State, identifier_token : *Token,
|
|||||||
case .Vertex; {
|
case .Vertex; {
|
||||||
node.vertex_entry_point = true;
|
node.vertex_entry_point = true;
|
||||||
name = sprint("vs_%", function_name_token.ident_value);
|
name = sprint("vs_%", function_name_token.ident_value);
|
||||||
|
|
||||||
|
// if return_type_token.kind == .TOKEN_INVALID {
|
||||||
|
// entry_point_requires_return_value(parse_state, function_name_token);
|
||||||
|
// advance_to_sync_point(parse_state);
|
||||||
|
// return error_node(parse_state, "");
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
case .Pixel; {
|
case .Pixel; {
|
||||||
node.pixel_entry_point = true;
|
node.pixel_entry_point = true;
|
||||||
name = sprint("ps_%", function_name_token.ident_value);
|
name = sprint("ps_%", function_name_token.ident_value);
|
||||||
|
|
||||||
|
// if return_type_token.kind == .TOKEN_INVALID {
|
||||||
|
// entry_point_requires_return_value(parse_state, function_name_token);
|
||||||
|
// advance_to_sync_point(parse_state);
|
||||||
|
// return error_node(parse_state, "");
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
76
README.md
76
README.md
@@ -20,15 +20,15 @@ There is basic support for most HLSL built-in math functions for the following t
|
|||||||
- Vector types: float2, float3, float4, int2, int3, int4
|
- Vector types: float2, float3, float4, int2, int3, int4
|
||||||
- Matrices: float4x4
|
- Matrices: float4x4
|
||||||
All of the above can be constructed with their namesake constructors i.e. `float4(x, y, z, w);`.
|
All of the above can be constructed with their namesake constructors i.e. `float4(x, y, z, w);`.
|
||||||
We don't yet support textures and samplers.
|
We also support Samplers and Texture2D
|
||||||
|
|
||||||
If you want to declare and use variables you can do it as follows
|
If you want to declare and use variables you can do it as follows
|
||||||
```hlsl
|
```hlsl
|
||||||
x : float = 2.0; // no 'f' suffix required or even supported (it gives an error)
|
x : float = 2.0; // no 'f' suffix required or even supported (it gives an error)
|
||||||
y : float = 4.0;
|
y : float = 4.0;
|
||||||
v : float2 = float2(x, y);
|
v : float2 = float2(x, y);
|
||||||
|
v2 := float2(x, y);
|
||||||
```
|
```
|
||||||
For now it is required to specify the type of the variable (no type inference).
|
|
||||||
|
|
||||||
You can also do arithmetic as you would expect
|
You can also do arithmetic as you would expect
|
||||||
```
|
```
|
||||||
@@ -43,6 +43,7 @@ Camera_Data :: struct {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
And there is a special struct called `properties`, which is used for custom data you want to pass in.
|
And there is a special struct called `properties`, which is used for custom data you want to pass in.
|
||||||
|
#### ** Note: Properties will likely be deprecated, since the language now supports `@` hints to easily mark buffers and values with metadata.**
|
||||||
```hlsl
|
```hlsl
|
||||||
properties {
|
properties {
|
||||||
projection : float4x4;
|
projection : float4x4;
|
||||||
@@ -53,13 +54,14 @@ which will be exposed in the compiled result. `properties` can be renamed to a c
|
|||||||
```
|
```
|
||||||
p :: properties {
|
p :: properties {
|
||||||
...
|
...
|
||||||
}
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also define constant buffers
|
You can also define constant buffers
|
||||||
|
|
||||||
```
|
```
|
||||||
camera :: Constant_Buffer {
|
camera :: constant_buffer {
|
||||||
projection : float4x4;
|
projection : float4x4;
|
||||||
view : float4x4;
|
view : float4x4;
|
||||||
}
|
}
|
||||||
@@ -70,69 +72,68 @@ camera :: Constant_Buffer {
|
|||||||
To compile a shader and use the result, you can do the following in jai
|
To compile a shader and use the result, you can do the following in jai
|
||||||
```jai
|
```jai
|
||||||
|
|
||||||
parse_shader :: (path : string, allocator : Allocator) -> Compilation_Result {
|
|
||||||
// In the future, you can pass environment defines to the compiler.
|
// In the future, you can pass environment defines to the compiler.
|
||||||
compiler : Shader_Compiler;
|
ctx : Compiler_Context;
|
||||||
|
compile_file(*compiler, "shader.shd", allocator);
|
||||||
|
|
||||||
return compile_file(*compiler, path,, allocator);
|
if ctx.had_error {
|
||||||
}
|
log_error("%\n", report_messages(ctx.messages),, temp);
|
||||||
|
|
||||||
result := parse_shader("shader.shd", allocator);
|
|
||||||
if result.had_error {
|
|
||||||
log_error("%\n", report_messages(result.messages),, temp);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
collection := result.collection;
|
// The ctx now contains all the needed information like the source text, entry points, constant buffers etc.
|
||||||
variant := collection.variants[0];
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
When parsing a shader you get the following struct as a result
|
When parsing a shader you get the following struct as a result
|
||||||
```
|
```
|
||||||
Compilation_Result :: struct {
|
Compiler_Context :: struct {
|
||||||
messages : [..]Compiler_Message;
|
file : Input_File;
|
||||||
|
|
||||||
had_error : bool;
|
environment : Environment;
|
||||||
|
|
||||||
collection : Shader_Variant_Collection;
|
tokens : [..]Token;;
|
||||||
}
|
root : *AST_Node;
|
||||||
```
|
nodes : [..]AST_Node;
|
||||||
|
|
||||||
A `Shader_Variant_Collection` looks as follows
|
codegen_result_text : string;
|
||||||
```
|
|
||||||
Shader_Variant_Collection :: struct {
|
|
||||||
properties : Properties;
|
|
||||||
|
|
||||||
max_constant_buffers :: 16;
|
constant_buffers : Static_Array(Type_Variable_Handle, 16);
|
||||||
cbuffers : Static_Array(Constant_Buffer, max_constant_buffers);
|
|
||||||
|
|
||||||
variants : [..]Shader_Variant;
|
scope_stack : Scope_Stack;
|
||||||
}
|
type_variables : [..]Type_Variable;
|
||||||
|
|
||||||
Shader_Variant :: struct {
|
property_name : string;
|
||||||
text : string;
|
|
||||||
|
|
||||||
vertex_entry_point : struct {
|
vertex_entry_point : struct {
|
||||||
|
node : *AST_Node;
|
||||||
name : string;
|
name : string;
|
||||||
|
|
||||||
input : [..]Field;
|
input : [..]Field;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixel_entry_point : struct {
|
pixel_entry_point : struct {
|
||||||
|
node : *AST_Node;
|
||||||
name : string;
|
name : string;
|
||||||
|
|
||||||
return_value : Field;
|
return_value : Field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
properties : Properties;
|
||||||
|
|
||||||
|
max_constant_buffers :: 16;
|
||||||
|
|
||||||
|
cbuffers : Static_Array(Constant_Buffer, max_constant_buffers);
|
||||||
|
|
||||||
|
had_error : bool;
|
||||||
|
messages : [..]Compiler_Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant_Buffer :: struct {
|
Constant_Buffer :: struct {
|
||||||
register : int;
|
|
||||||
|
|
||||||
name : string;
|
name : string;
|
||||||
|
|
||||||
fields : Static_Array(Property_Field, 16);
|
fields : Static_Array(Property_Field, 16);
|
||||||
|
|
||||||
|
// hints : Field_Hint; // optional hint...
|
||||||
|
hints : [..]Field_Hint;
|
||||||
|
|
||||||
buffer_index : u32;
|
buffer_index : u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,11 +193,10 @@ Hint_Kind :: enum {
|
|||||||
|
|
||||||
## Notable missing features
|
## Notable missing features
|
||||||
|
|
||||||
- Control flow: if/else, for, while, switch etc.
|
- While
|
||||||
- Arrays
|
- Arrays
|
||||||
- Textures and samplers
|
|
||||||
- Multiple render targets
|
- Multiple render targets
|
||||||
- Custom buffers/structured buffers
|
- Custom buffers/structured buffers
|
||||||
- Interpolation specifiers
|
- Interpolation specifiers
|
||||||
- Proper variant handling with environment defines
|
- Proper variant handling with environment defines
|
||||||
- Include/importing files such as shared utils etc.
|
- Importing files such as shared utils etc. with something other than textual `#load`
|
||||||
96
module.jai
96
module.jai
@@ -1,11 +1,29 @@
|
|||||||
#load "Lexing.jai";
|
#load "Lexing.jai";
|
||||||
#load "Error.jai";
|
#load "Error.jai";
|
||||||
#load "Parsing.jai";
|
#load "Parsing.jai";
|
||||||
#load "Semantic_Analysis.jai";
|
#load "Check.jai";
|
||||||
#load "Codegen.jai";
|
#load "Codegen.jai";
|
||||||
|
|
||||||
#import "File_Utilities";
|
#import "File_Utilities";
|
||||||
|
|
||||||
|
/* TODO
|
||||||
|
- [x] Remove builtin stringbuilding and replace it with ad-hoc string building when error reporting. In that case we are already building a string anyway, so we can just pass in the string builder
|
||||||
|
- [ ] Support structured buffers (ro, rw, w)
|
||||||
|
- [ ] Support mesh and amplification shaders
|
||||||
|
- [ ] Support compute shaders
|
||||||
|
- [x] Support #if at top level
|
||||||
|
- [x] Support #if at block level
|
||||||
|
- [ ] Remove properties block and just use hinted constant buffers instead
|
||||||
|
```
|
||||||
|
props :: constant_buffer @properties {
|
||||||
|
[...]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- [ ] while loops
|
||||||
|
- [ ] for-each loops
|
||||||
|
- [ ]
|
||||||
|
*/
|
||||||
|
|
||||||
add_define :: (env : *Environment, key : string) {
|
add_define :: (env : *Environment, key : string) {
|
||||||
for define : env.defines {
|
for define : env.defines {
|
||||||
if define == key {
|
if define == key {
|
||||||
@@ -55,10 +73,33 @@ Hint_Kind :: enum {
|
|||||||
Position;
|
Position;
|
||||||
UV;
|
UV;
|
||||||
Target;
|
Target;
|
||||||
|
Output_Position;
|
||||||
|
|
||||||
Custom;
|
Custom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Hint_Names :: #run -> [(cast(int)Hint_Kind.Target) + 1]string {
|
||||||
|
names : [(cast(int)Hint_Kind.Target) + 1]string;
|
||||||
|
names[Hint_Kind.Position] = "position";
|
||||||
|
names[Hint_Kind.UV] = "uv";
|
||||||
|
names[Hint_Kind.Target] = "target";
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
lookup_hint :: (name : string) -> Hint_Kind {
|
||||||
|
if name == "position" {
|
||||||
|
return Hint_Kind.Position;
|
||||||
|
} else if name == "uv" {
|
||||||
|
return Hint_Kind.UV;
|
||||||
|
} else if starts_with(name, "target") {
|
||||||
|
return Hint_Kind.Target;
|
||||||
|
} else if name == "outposition" {
|
||||||
|
return Hint_Kind.Output_Position;
|
||||||
|
}
|
||||||
|
return .None;
|
||||||
|
}
|
||||||
|
|
||||||
Field_Hint :: struct {
|
Field_Hint :: struct {
|
||||||
kind : Hint_Kind;
|
kind : Hint_Kind;
|
||||||
|
|
||||||
@@ -81,22 +122,6 @@ Entry_Point :: struct {
|
|||||||
return_value : Field;
|
return_value : Field;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader_Variant :: struct {
|
|
||||||
text : string;
|
|
||||||
|
|
||||||
vertex_entry_point : struct {
|
|
||||||
name : string;
|
|
||||||
|
|
||||||
input : [..]Field;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixel_entry_point : struct {
|
|
||||||
name : string;
|
|
||||||
|
|
||||||
return_value : Field;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Property_Field :: struct {
|
Property_Field :: struct {
|
||||||
base_field : Field;
|
base_field : Field;
|
||||||
|
|
||||||
@@ -111,27 +136,15 @@ Properties :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Constant_Buffer :: struct {
|
Constant_Buffer :: struct {
|
||||||
register : int;
|
|
||||||
|
|
||||||
name : string;
|
name : string;
|
||||||
|
|
||||||
fields : Static_Array(Property_Field, 16);
|
fields : Static_Array(Property_Field, 16);
|
||||||
|
|
||||||
// hints : Field_Hint; // optional hint...
|
|
||||||
hints : [..]Field_Hint;
|
hints : [..]Field_Hint;
|
||||||
|
|
||||||
buffer_index : u32;
|
buffer_index : u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader_Variant_Collection :: struct {
|
|
||||||
properties : Properties;
|
|
||||||
|
|
||||||
max_constant_buffers :: 16;
|
|
||||||
cbuffers : Static_Array(Constant_Buffer, max_constant_buffers);
|
|
||||||
|
|
||||||
variants : [..]Shader_Variant;
|
|
||||||
}
|
|
||||||
|
|
||||||
Input_File :: struct {
|
Input_File :: struct {
|
||||||
source : string;
|
source : string;
|
||||||
path : string;
|
path : string;
|
||||||
@@ -167,7 +180,7 @@ Compiler_Context :: struct {
|
|||||||
return_value : Field;
|
return_value : Field;
|
||||||
}
|
}
|
||||||
|
|
||||||
properties : Properties;
|
properties : Properties; //@Note(niels): We'll deprecate this in favor of just marking a constant buffer with a hint on how you'd want to use it
|
||||||
|
|
||||||
max_constant_buffers :: 16;
|
max_constant_buffers :: 16;
|
||||||
|
|
||||||
@@ -312,7 +325,7 @@ pretty_print_field :: (builder : *String_Builder, field : *Field) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type_variable_to_field :: (checker : *Semantic_Checker, variable : Type_Variable_Handle) -> Field {
|
type_variable_to_field :: (checker : *Checker, variable : Type_Variable_Handle) -> Field {
|
||||||
return type_variable_to_field(checker, from_handle(checker, variable));
|
return type_variable_to_field(checker, from_handle(checker, variable));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,13 +380,11 @@ type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope
|
|||||||
for hint : variable.source_node.hint_tokens {
|
for hint : variable.source_node.hint_tokens {
|
||||||
field_hint : Field_Hint;
|
field_hint : Field_Hint;
|
||||||
|
|
||||||
if hint.ident_value == "position" {
|
if lookup_hint(hint.ident_value) == .Position {
|
||||||
// @Incomplete(nb): Should be a lookup table somewhere
|
|
||||||
field_hint.kind = .Position;
|
field_hint.kind = .Position;
|
||||||
} else if hint.ident_value == "uv" {
|
} else if lookup_hint(hint.ident_value) == .UV {
|
||||||
field_hint.kind = .UV;
|
field_hint.kind = .UV;
|
||||||
} else if starts_with(hint.ident_value, "target") {
|
} else if lookup_hint(hint.ident_value) == .Target {
|
||||||
// @Incomplete(nb): Should be a lookup table somewhere
|
|
||||||
index_str : string;
|
index_str : string;
|
||||||
index_str.data = *hint.ident_value.data[7];
|
index_str.data = *hint.ident_value.data[7];
|
||||||
index_str.count = 1;
|
index_str.count = 1;
|
||||||
@@ -399,7 +410,7 @@ type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope
|
|||||||
return type_variable_to_field(type_variables, scope_stack, from_handle(type_variables, variable));
|
return type_variable_to_field(type_variables, scope_stack, from_handle(type_variables, variable));
|
||||||
}
|
}
|
||||||
|
|
||||||
type_variable_to_field :: (checker : *Semantic_Checker, variable : *Type_Variable) -> Field {
|
type_variable_to_field :: (checker : *Checker, variable : *Type_Variable) -> Field {
|
||||||
return type_variable_to_field(checker.ctx.type_variables, checker.ctx.scope_stack, variable);
|
return type_variable_to_field(checker.ctx.type_variables, checker.ctx.scope_stack, variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,6 +462,7 @@ generate_output_data :: (ctx : *Compiler_Context) {
|
|||||||
|
|
||||||
find_result := find_symbol(*ctx.scope_stack, ctx.property_name, xx 1);
|
find_result := find_symbol(*ctx.scope_stack, ctx.property_name, xx 1);
|
||||||
if find_result {
|
if find_result {
|
||||||
|
|
||||||
property_variable := from_handle(ctx.type_variables, find_result.type_variable);
|
property_variable := from_handle(ctx.type_variables, find_result.type_variable);
|
||||||
|
|
||||||
for i : 0..property_variable.children.count - 1 {
|
for i : 0..property_variable.children.count - 1 {
|
||||||
@@ -463,22 +475,20 @@ generate_output_data :: (ctx : *Compiler_Context) {
|
|||||||
ctx.properties.buffer_index = property_variable.resource_index;
|
ctx.properties.buffer_index = property_variable.resource_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ctx.pixel_entry_point.node {
|
if ctx.pixel_entry_point.node {
|
||||||
ctx.pixel_entry_point.name = ctx.pixel_entry_point.node.name;
|
ctx.pixel_entry_point.name = ctx.pixel_entry_point.node.name;
|
||||||
|
|
||||||
type_variable := from_handle(ctx.type_variables, ctx.pixel_entry_point.node.type_variable);
|
type_variable := from_handle(ctx.type_variables, ctx.pixel_entry_point.node.type_variable);
|
||||||
assert(type_variable.type == .Function);
|
assert(type_variable.type == .Function);
|
||||||
|
|
||||||
|
if type_variable.return_type_variable > 0 {
|
||||||
field := type_variable_to_field(ctx.type_variables, ctx.scope_stack, type_variable.return_type_variable);
|
field := type_variable_to_field(ctx.type_variables, ctx.scope_stack, type_variable.return_type_variable);
|
||||||
for hint : type_variable.source_node.hint_tokens {
|
for hint : type_variable.source_node.hint_tokens {
|
||||||
field_hint : Field_Hint;
|
field_hint : Field_Hint;
|
||||||
|
|
||||||
if hint.ident_value == "position" {
|
if lookup_hint(hint.ident_value) == .Position {
|
||||||
// @Incomplete(nb): Should be a lookup table somewhere
|
|
||||||
field_hint.kind = .Position;
|
field_hint.kind = .Position;
|
||||||
} else if starts_with(hint.ident_value, "target") {
|
} else if lookup_hint(hint.ident_value) == .Target {
|
||||||
// @Incomplete(nb): Should be a lookup table somewhere
|
|
||||||
index_str : string;
|
index_str : string;
|
||||||
index_str.data = *hint.ident_value.data[7];
|
index_str.data = *hint.ident_value.data[7];
|
||||||
index_str.count = 1;
|
index_str.count = 1;
|
||||||
@@ -493,10 +503,10 @@ generate_output_data :: (ctx : *Compiler_Context) {
|
|||||||
}
|
}
|
||||||
array_add(*field.hints, field_hint);
|
array_add(*field.hints, field_hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.pixel_entry_point.return_value = field;
|
ctx.pixel_entry_point.return_value = field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
compile_file :: (ctx : *Compiler_Context, path : string, allocator : Allocator = temp) {
|
compile_file :: (ctx : *Compiler_Context, path : string, allocator : Allocator = temp) {
|
||||||
new_context := context;
|
new_context := context;
|
||||||
|
|||||||
7
test/check/if_def_block.golden
Normal file
7
test/check/if_def_block.golden
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
scope (global) [
|
||||||
|
[pixel__ps_main] : ()
|
||||||
|
scope (pixel__ps_main) [
|
||||||
|
[alpha_color] : float4
|
||||||
|
[f] : float
|
||||||
|
]
|
||||||
|
]
|
||||||
4
test/check/if_def_expression.golden
Normal file
4
test/check/if_def_expression.golden
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
scope (global) [
|
||||||
|
[vertex__vs_console_main] : ()
|
||||||
|
scope (vertex__vs_console_main) []
|
||||||
|
]
|
||||||
8
test/check/ifdefs.golden
Normal file
8
test/check/ifdefs.golden
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
scope (global) [
|
||||||
|
[vertex__vs_skinning_main] : ()
|
||||||
|
[pixel__ps_main] : ()
|
||||||
|
scope (vertex__vs_skinning_main) [
|
||||||
|
[x] : float
|
||||||
|
]
|
||||||
|
scope (pixel__ps_main) []
|
||||||
|
]
|
||||||
@@ -7,15 +7,15 @@
|
|||||||
[96m result : float4 = float4(1.0, foo * res, 0.0, 1.0);
|
[96m result : float4 = float4(1.0, foo * res, 0.0, 1.0);
|
||||||
^
|
^
|
||||||
[97m Possible overloads:
|
[97m Possible overloads:
|
||||||
[96m float4 :: (float, float, float, float); (test/wrong_multiply.ink:0)
|
[96m float4 :: (float, float, float, float)
|
||||||
[96m float4 :: (float2, float2); (test/wrong_multiply.ink:0)
|
[96m float4 :: (float2, float2)
|
||||||
[96m float4 :: (float2, float, float); (test/wrong_multiply.ink:0)
|
[96m float4 :: (float2, float, float)
|
||||||
[96m float4 :: (float, float2, float); (test/wrong_multiply.ink:0)
|
[96m float4 :: (float, float2, float)
|
||||||
[96m float4 :: (float, float, float2); (test/wrong_multiply.ink:0)
|
[96m float4 :: (float, float, float2)
|
||||||
[96m float4 :: (float, float3); (test/wrong_multiply.ink:0)
|
[96m float4 :: (float, float3)
|
||||||
[96m float4 :: (float3, float); (test/wrong_multiply.ink:0)
|
[96m float4 :: (float3, float)
|
||||||
[96m float4 :: (float4); (test/wrong_multiply.ink:0)
|
[96m float4 :: (float4)
|
||||||
[96m float4 :: (float); (test/wrong_multiply.ink:0)
|
[96m float4 :: (float)
|
||||||
|
|
||||||
[36m[37m[1;37mtest/wrong_multiply.ink:4,34: [31merror: [37mType mismatch. Expected float got float2
|
[36m[37m[1;37mtest/wrong_multiply.ink:4,34: [31merror: [37mType mismatch. Expected float got float2
|
||||||
[96m found:
|
[96m found:
|
||||||
30
test/check/wrong_type_for_function.golden
Normal file
30
test/check/wrong_type_for_function.golden
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
[1;37mtest/wrong_type_for_function.ink:11,17: [31merror: [37mProcedure call did not match any of the possible overloads for 'float4'
|
||||||
|
[96m found:
|
||||||
|
color : float4 = float4(y, 1.0, 1.0, 1.0);
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
[97m While matching argument 1 in function call.
|
||||||
|
[96m color : float4 = float4(y, 1.0, 1.0, 1.0);
|
||||||
|
^
|
||||||
|
[97m Possible overloads:
|
||||||
|
[96m float4 :: (float, float, float, float)
|
||||||
|
[96m float4 :: (float2, float2)
|
||||||
|
[96m float4 :: (float2, float, float)
|
||||||
|
[96m float4 :: (float, float2, float)
|
||||||
|
[96m float4 :: (float, float, float2)
|
||||||
|
[96m float4 :: (float, float3)
|
||||||
|
[96m float4 :: (float3, float)
|
||||||
|
[96m float4 :: (float4)
|
||||||
|
[96m float4 :: (float)
|
||||||
|
|
||||||
|
[36m[37m[1;37mtest/wrong_type_for_function.ink:11,24: [31merror: [37mType mismatch. Expected float got float2
|
||||||
|
[96m found:
|
||||||
|
color : float4 = float4(y, 1.0, 1.0, 1.0);
|
||||||
|
^
|
||||||
|
expected:
|
||||||
|
float
|
||||||
|
|
||||||
|
got:
|
||||||
|
y : float2 = foo()
|
||||||
|
|
||||||
|
[36m[37m
|
||||||
43
test/check_all.suite
Normal file
43
test/check_all.suite
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
test/assign_arithmetic_expression.ink check
|
||||||
|
test/basic_property_and_return_value.ink check
|
||||||
|
test/builtin_types.ink check
|
||||||
|
test/complicated_computation.ink check
|
||||||
|
test/constant_buffer.ink check
|
||||||
|
test/empty_struct.ink check
|
||||||
|
test/empty_vertex_main.ink check
|
||||||
|
test/empty_vertex_main_with_position_parameter.ink check
|
||||||
|
test/field_assignment.ink check
|
||||||
|
test/for_i_loop.ink check
|
||||||
|
test/function_call.ink check
|
||||||
|
test/function_call_out_of_order_declaration.ink check
|
||||||
|
test/function_call_return.ink check
|
||||||
|
test/functions_with_same_name.ink check
|
||||||
|
test/function_with_int_return.ink check
|
||||||
|
test/if_cond_assign.ink check
|
||||||
|
test/ifdefs.ink check
|
||||||
|
test/if_def_block.ink check
|
||||||
|
test/if_def_expression.ink check
|
||||||
|
test/inferred_types.ink check
|
||||||
|
test/multiple_functions.ink check
|
||||||
|
test/multiple_semicolons_everywhere.ink check
|
||||||
|
test/nested_if.ink check
|
||||||
|
test/non_bool_cond.ink check
|
||||||
|
test/pass_and_access_struct_fields_in_functions.ink check
|
||||||
|
test/passthrough.ink check
|
||||||
|
test/property_rename.ink check
|
||||||
|
test/redeclared_variable.ink check
|
||||||
|
test/simple_else_if.ink check
|
||||||
|
test/simple_if_else.ink check
|
||||||
|
test/simple_if.ink check
|
||||||
|
test/simple_struct_access.ink check
|
||||||
|
test/struct_access_primitive_type.ink check
|
||||||
|
test/struct_within_struct.ink check
|
||||||
|
test/type_as_variable_name.ink check
|
||||||
|
test/unary.ink check
|
||||||
|
test/undeclared_function.ink check
|
||||||
|
test/undeclared_symbol.ink check
|
||||||
|
test/unknown_overload.ink check
|
||||||
|
test/use_builtin_functions.ink check
|
||||||
|
test/wrong_argument_count.ink check
|
||||||
|
test/wrong_multiply.ink check
|
||||||
|
test/wrong_type_for_function.ink check
|
||||||
7
test/codegen/if_def_block.golden
Normal file
7
test/codegen/if_def_block.golden
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
void ps_main()
|
||||||
|
{
|
||||||
|
|
||||||
|
float4 alpha_color = float4(1, 0, 0, 1);
|
||||||
|
float f = 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
4
test/codegen/if_def_expression.golden
Normal file
4
test/codegen/if_def_expression.golden
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
void vs_console_main()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
9
test/codegen/ifdefs.golden
Normal file
9
test/codegen/ifdefs.golden
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
void ps_main()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void vs_skinning_main()
|
||||||
|
{
|
||||||
|
float x = 5.0f;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -10,6 +10,9 @@ test/field_assignment.ink codegen
|
|||||||
test/function_call.ink codegen
|
test/function_call.ink codegen
|
||||||
test/function_call_out_of_order_declaration.ink codegen
|
test/function_call_out_of_order_declaration.ink codegen
|
||||||
test/function_call_return.ink codegen
|
test/function_call_return.ink codegen
|
||||||
|
test/ifdefs.ink codegen
|
||||||
|
test/if_def_block.ink codegen
|
||||||
|
test/if_def_expression.ink codegen
|
||||||
test/inferred_types.ink codegen
|
test/inferred_types.ink codegen
|
||||||
test/meta_block.ink codegen
|
test/meta_block.ink codegen
|
||||||
test/multiple_functions.ink codegen
|
test/multiple_functions.ink codegen
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ test/function_call.ink compile
|
|||||||
test/function_call_out_of_order_declaration.ink compile
|
test/function_call_out_of_order_declaration.ink compile
|
||||||
test/function_call_return.ink compile
|
test/function_call_return.ink compile
|
||||||
test/functions_with_same_name.ink compile
|
test/functions_with_same_name.ink compile
|
||||||
|
test/ifdefs.ink compile
|
||||||
|
test/if_def_block.ink compile
|
||||||
|
test/if_def_expression.ink compile
|
||||||
test/inferred_types.ink compile
|
test/inferred_types.ink compile
|
||||||
test/meta_block.ink compile
|
test/meta_block.ink compile
|
||||||
test/multiple_functions.ink compile
|
test/multiple_functions.ink compile
|
||||||
|
|||||||
1
test/compiled/assign_arithmetic_expression.golden
Normal file
1
test/compiled/assign_arithmetic_expression.golden
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[vertex entry point] - vs_main
|
||||||
1
test/compiled/if_def_block.golden
Normal file
1
test/compiled/if_def_block.golden
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[pixel entry point] - ps_main
|
||||||
1
test/compiled/if_def_expression.golden
Normal file
1
test/compiled/if_def_expression.golden
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[vertex entry point] - vs_console_main
|
||||||
2
test/compiled/ifdefs.golden
Normal file
2
test/compiled/ifdefs.golden
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[vertex entry point] - vs_skinning_main
|
||||||
|
[pixel entry point] - ps_main
|
||||||
11
test/if_def_block.ink
Normal file
11
test/if_def_block.ink
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#add_define Alpha
|
||||||
|
|
||||||
|
pixel main :: () {
|
||||||
|
#if Env.Alpha {
|
||||||
|
alpha_color := float4(1, 0, 0, 1);
|
||||||
|
f := 2.0;
|
||||||
|
} else {
|
||||||
|
color := float3(0, 0, 0);
|
||||||
|
g := 5.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
test/if_def_expression.ink
Normal file
13
test/if_def_expression.ink
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#add_define PS5
|
||||||
|
#add_define XSX
|
||||||
|
#add_define Switch2
|
||||||
|
|
||||||
|
#if (Env.PS5 && Env.XSX) || Env.Switch2 {
|
||||||
|
vertex console_main :: () {
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vertex windows_main :: () {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,17 @@
|
|||||||
#if Defines.Skinning {
|
#add_define Skinning
|
||||||
vertex main :: () {
|
#add_define UV
|
||||||
// Stub
|
|
||||||
|
|
||||||
|
#if Env.Skinning {
|
||||||
|
vertex skinning_main :: () {
|
||||||
|
x : float = 5.0;
|
||||||
|
}
|
||||||
|
} else #if Env.UV {
|
||||||
|
vertex texture_mapping_main :: () {
|
||||||
|
x : float2 = float2(2.0, 2.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pixel main :: () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
53
test/lex/if_def_block.golden
Normal file
53
test/lex/if_def_block.golden
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{kind = TOKEN_PIXEL; ; index = 21 ; length = 5 line = 3 ; column = 0 ; value ='pixel'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 27 ; length = 4 line = 3 ; column = 6 ; value ='main'; }
|
||||||
|
{kind = TOKEN_DOUBLECOLON; ; index = 32 ; length = 2 line = 3 ; column = 11 ; value ='::'; }
|
||||||
|
{kind = TOKEN_LEFTPAREN; ; index = 35 ; length = 1 line = 3 ; column = 14 ; value ='('; }
|
||||||
|
{kind = TOKEN_RIGHTPAREN; ; index = 36 ; length = 1 line = 3 ; column = 15 ; value =')'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 38 ; length = 1 line = 3 ; column = 17 ; value ='{'; }
|
||||||
|
{kind = TOKEN_DIRECTIVE; ; index = 42 ; length = 2 line = 4 ; column = 0 ; value ='if'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 45 ; length = 3 line = 4 ; column = 3 ; value ='Env'; }
|
||||||
|
{kind = TOKEN_DOT; ; index = 48 ; length = 1 line = 4 ; column = 6 ; value ='.'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 49 ; length = 5 line = 4 ; column = 7 ; value ='Alpha'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 55 ; length = 1 line = 4 ; column = 13 ; value ='{'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 59 ; length = 11 line = 5 ; column = 0 ; value ='alpha_color'; }
|
||||||
|
{kind = TOKEN_COLON; ; index = 71 ; length = 1 line = 5 ; column = 12 ; value =':'; }
|
||||||
|
{kind = TOKEN_ASSIGN; ; index = 72 ; length = 1 line = 5 ; column = 13 ; value ='='; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 74 ; length = 6 line = 5 ; column = 15 ; value ='float4'; }
|
||||||
|
{kind = TOKEN_LEFTPAREN; ; index = 80 ; length = 1 line = 5 ; column = 21 ; value ='('; }
|
||||||
|
{kind = TOKEN_INTLITERAL; ; index = 81 ; length = 1 line = 5 ; column = 22 ; value ='1'; }
|
||||||
|
{kind = TOKEN_COMMA; ; index = 82 ; length = 1 line = 5 ; column = 23 ; value =','; }
|
||||||
|
{kind = TOKEN_INTLITERAL; ; index = 84 ; length = 1 line = 5 ; column = 25 ; value ='0'; }
|
||||||
|
{kind = TOKEN_COMMA; ; index = 85 ; length = 1 line = 5 ; column = 26 ; value =','; }
|
||||||
|
{kind = TOKEN_INTLITERAL; ; index = 87 ; length = 1 line = 5 ; column = 28 ; value ='0'; }
|
||||||
|
{kind = TOKEN_COMMA; ; index = 88 ; length = 1 line = 5 ; column = 29 ; value =','; }
|
||||||
|
{kind = TOKEN_INTLITERAL; ; index = 90 ; length = 1 line = 5 ; column = 31 ; value ='1'; }
|
||||||
|
{kind = TOKEN_RIGHTPAREN; ; index = 91 ; length = 1 line = 5 ; column = 32 ; value =')'; }
|
||||||
|
{kind = TOKEN_SEMICOLON; ; index = 92 ; length = 1 line = 5 ; column = 33 ; value =';'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 96 ; length = 1 line = 6 ; column = 0 ; value ='f'; }
|
||||||
|
{kind = TOKEN_COLON; ; index = 98 ; length = 1 line = 6 ; column = 2 ; value =':'; }
|
||||||
|
{kind = TOKEN_ASSIGN; ; index = 99 ; length = 1 line = 6 ; column = 3 ; value ='='; }
|
||||||
|
{kind = TOKEN_FLOATLITERAL; ; index = 101 ; length = 3 line = 6 ; column = 5 ; value ='2'; }
|
||||||
|
{kind = TOKEN_SEMICOLON; ; index = 104 ; length = 1 line = 6 ; column = 8 ; value =';'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 107 ; length = 1 line = 7 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_ELSE; ; index = 109 ; length = 4 line = 7 ; column = 2 ; value ='else'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 114 ; length = 1 line = 7 ; column = 7 ; value ='{'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 118 ; length = 5 line = 8 ; column = 0 ; value ='color'; }
|
||||||
|
{kind = TOKEN_COLON; ; index = 124 ; length = 1 line = 8 ; column = 6 ; value =':'; }
|
||||||
|
{kind = TOKEN_ASSIGN; ; index = 125 ; length = 1 line = 8 ; column = 7 ; value ='='; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 127 ; length = 6 line = 8 ; column = 9 ; value ='float3'; }
|
||||||
|
{kind = TOKEN_LEFTPAREN; ; index = 133 ; length = 1 line = 8 ; column = 15 ; value ='('; }
|
||||||
|
{kind = TOKEN_INTLITERAL; ; index = 134 ; length = 1 line = 8 ; column = 16 ; value ='0'; }
|
||||||
|
{kind = TOKEN_COMMA; ; index = 135 ; length = 1 line = 8 ; column = 17 ; value =','; }
|
||||||
|
{kind = TOKEN_INTLITERAL; ; index = 137 ; length = 1 line = 8 ; column = 19 ; value ='0'; }
|
||||||
|
{kind = TOKEN_COMMA; ; index = 138 ; length = 1 line = 8 ; column = 20 ; value =','; }
|
||||||
|
{kind = TOKEN_INTLITERAL; ; index = 140 ; length = 1 line = 8 ; column = 22 ; value ='0'; }
|
||||||
|
{kind = TOKEN_RIGHTPAREN; ; index = 141 ; length = 1 line = 8 ; column = 23 ; value =')'; }
|
||||||
|
{kind = TOKEN_SEMICOLON; ; index = 142 ; length = 1 line = 8 ; column = 24 ; value =';'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 146 ; length = 1 line = 9 ; column = 0 ; value ='g'; }
|
||||||
|
{kind = TOKEN_COLON; ; index = 148 ; length = 1 line = 9 ; column = 2 ; value =':'; }
|
||||||
|
{kind = TOKEN_ASSIGN; ; index = 149 ; length = 1 line = 9 ; column = 3 ; value ='='; }
|
||||||
|
{kind = TOKEN_FLOATLITERAL; ; index = 151 ; length = 3 line = 9 ; column = 5 ; value ='5'; }
|
||||||
|
{kind = TOKEN_SEMICOLON; ; index = 154 ; length = 1 line = 9 ; column = 8 ; value =';'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 157 ; length = 1 line = 10 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 160 ; length = 1 line = 11 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_EOF; ; index = 163 ; length = 0 line = 12 ; column = 0 ; value =''; }
|
||||||
34
test/lex/if_def_expression.golden
Normal file
34
test/lex/if_def_expression.golden
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{kind = TOKEN_DIRECTIVE; ; index = 58 ; length = 2 line = 5 ; column = 0 ; value ='if'; }
|
||||||
|
{kind = TOKEN_LEFTPAREN; ; index = 61 ; length = 1 line = 5 ; column = 3 ; value ='('; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 62 ; length = 3 line = 5 ; column = 4 ; value ='Env'; }
|
||||||
|
{kind = TOKEN_DOT; ; index = 65 ; length = 1 line = 5 ; column = 7 ; value ='.'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 66 ; length = 3 line = 5 ; column = 8 ; value ='PS5'; }
|
||||||
|
{kind = TOKEN_LOGICALAND; ; index = 70 ; length = 2 line = 5 ; column = 12 ; value ='&&'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 73 ; length = 3 line = 5 ; column = 15 ; value ='Env'; }
|
||||||
|
{kind = TOKEN_DOT; ; index = 76 ; length = 1 line = 5 ; column = 18 ; value ='.'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 77 ; length = 3 line = 5 ; column = 19 ; value ='XSX'; }
|
||||||
|
{kind = TOKEN_RIGHTPAREN; ; index = 80 ; length = 1 line = 5 ; column = 22 ; value =')'; }
|
||||||
|
{kind = TOKEN_LOGICALOR; ; index = 82 ; length = 2 line = 5 ; column = 24 ; value ='||'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 85 ; length = 3 line = 5 ; column = 27 ; value ='Env'; }
|
||||||
|
{kind = TOKEN_DOT; ; index = 88 ; length = 1 line = 5 ; column = 30 ; value ='.'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 89 ; length = 7 line = 5 ; column = 31 ; value ='Switch2'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 97 ; length = 1 line = 5 ; column = 39 ; value ='{'; }
|
||||||
|
{kind = TOKEN_VERTEX; ; index = 101 ; length = 6 line = 6 ; column = 0 ; value ='vertex'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 108 ; length = 12 line = 6 ; column = 7 ; value ='console_main'; }
|
||||||
|
{kind = TOKEN_DOUBLECOLON; ; index = 121 ; length = 2 line = 6 ; column = 20 ; value ='::'; }
|
||||||
|
{kind = TOKEN_LEFTPAREN; ; index = 124 ; length = 1 line = 6 ; column = 23 ; value ='('; }
|
||||||
|
{kind = TOKEN_RIGHTPAREN; ; index = 125 ; length = 1 line = 6 ; column = 24 ; value =')'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 127 ; length = 1 line = 6 ; column = 26 ; value ='{'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 133 ; length = 1 line = 8 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 136 ; length = 1 line = 9 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_ELSE; ; index = 138 ; length = 4 line = 9 ; column = 2 ; value ='else'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 143 ; length = 1 line = 9 ; column = 7 ; value ='{'; }
|
||||||
|
{kind = TOKEN_VERTEX; ; index = 147 ; length = 6 line = 10 ; column = 0 ; value ='vertex'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 154 ; length = 12 line = 10 ; column = 7 ; value ='windows_main'; }
|
||||||
|
{kind = TOKEN_DOUBLECOLON; ; index = 167 ; length = 2 line = 10 ; column = 20 ; value ='::'; }
|
||||||
|
{kind = TOKEN_LEFTPAREN; ; index = 170 ; length = 1 line = 10 ; column = 23 ; value ='('; }
|
||||||
|
{kind = TOKEN_RIGHTPAREN; ; index = 171 ; length = 1 line = 10 ; column = 24 ; value =')'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 173 ; length = 1 line = 10 ; column = 26 ; value ='{'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 179 ; length = 1 line = 12 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 182 ; length = 1 line = 13 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_EOF; ; index = 185 ; length = 0 line = 14 ; column = 0 ; value =''; }
|
||||||
52
test/lex/ifdefs.golden
Normal file
52
test/lex/ifdefs.golden
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{kind = TOKEN_DIRECTIVE; ; index = 43 ; length = 2 line = 5 ; column = 0 ; value ='if'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 46 ; length = 3 line = 5 ; column = 3 ; value ='Env'; }
|
||||||
|
{kind = TOKEN_DOT; ; index = 49 ; length = 1 line = 5 ; column = 6 ; value ='.'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 50 ; length = 8 line = 5 ; column = 7 ; value ='Skinning'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 59 ; length = 1 line = 5 ; column = 16 ; value ='{'; }
|
||||||
|
{kind = TOKEN_VERTEX; ; index = 63 ; length = 6 line = 6 ; column = 0 ; value ='vertex'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 70 ; length = 13 line = 6 ; column = 7 ; value ='skinning_main'; }
|
||||||
|
{kind = TOKEN_DOUBLECOLON; ; index = 84 ; length = 2 line = 6 ; column = 21 ; value ='::'; }
|
||||||
|
{kind = TOKEN_LEFTPAREN; ; index = 87 ; length = 1 line = 6 ; column = 24 ; value ='('; }
|
||||||
|
{kind = TOKEN_RIGHTPAREN; ; index = 88 ; length = 1 line = 6 ; column = 25 ; value =')'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 90 ; length = 1 line = 6 ; column = 27 ; value ='{'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 95 ; length = 1 line = 7 ; column = 0 ; value ='x'; }
|
||||||
|
{kind = TOKEN_COLON; ; index = 97 ; length = 1 line = 7 ; column = 2 ; value =':'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 99 ; length = 5 line = 7 ; column = 4 ; value ='float'; }
|
||||||
|
{kind = TOKEN_ASSIGN; ; index = 105 ; length = 1 line = 7 ; column = 10 ; value ='='; }
|
||||||
|
{kind = TOKEN_FLOATLITERAL; ; index = 107 ; length = 3 line = 7 ; column = 12 ; value ='5'; }
|
||||||
|
{kind = TOKEN_SEMICOLON; ; index = 110 ; length = 1 line = 7 ; column = 15 ; value =';'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 114 ; length = 1 line = 8 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 117 ; length = 1 line = 9 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_ELSE; ; index = 119 ; length = 4 line = 9 ; column = 2 ; value ='else'; }
|
||||||
|
{kind = TOKEN_DIRECTIVE; ; index = 125 ; length = 2 line = 9 ; column = 7 ; value ='if'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 128 ; length = 3 line = 9 ; column = 10 ; value ='Env'; }
|
||||||
|
{kind = TOKEN_DOT; ; index = 131 ; length = 1 line = 9 ; column = 13 ; value ='.'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 132 ; length = 2 line = 9 ; column = 14 ; value ='UV'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 135 ; length = 1 line = 9 ; column = 17 ; value ='{'; }
|
||||||
|
{kind = TOKEN_VERTEX; ; index = 139 ; length = 6 line = 10 ; column = 0 ; value ='vertex'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 146 ; length = 20 line = 10 ; column = 7 ; value ='texture_mapping_main'; }
|
||||||
|
{kind = TOKEN_DOUBLECOLON; ; index = 167 ; length = 2 line = 10 ; column = 28 ; value ='::'; }
|
||||||
|
{kind = TOKEN_LEFTPAREN; ; index = 170 ; length = 1 line = 10 ; column = 31 ; value ='('; }
|
||||||
|
{kind = TOKEN_RIGHTPAREN; ; index = 171 ; length = 1 line = 10 ; column = 32 ; value =')'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 173 ; length = 1 line = 10 ; column = 34 ; value ='{'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 178 ; length = 1 line = 11 ; column = 0 ; value ='x'; }
|
||||||
|
{kind = TOKEN_COLON; ; index = 180 ; length = 1 line = 11 ; column = 2 ; value =':'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 182 ; length = 6 line = 11 ; column = 4 ; value ='float2'; }
|
||||||
|
{kind = TOKEN_ASSIGN; ; index = 189 ; length = 1 line = 11 ; column = 11 ; value ='='; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 191 ; length = 6 line = 11 ; column = 13 ; value ='float2'; }
|
||||||
|
{kind = TOKEN_LEFTPAREN; ; index = 197 ; length = 1 line = 11 ; column = 19 ; value ='('; }
|
||||||
|
{kind = TOKEN_FLOATLITERAL; ; index = 198 ; length = 3 line = 11 ; column = 20 ; value ='2'; }
|
||||||
|
{kind = TOKEN_COMMA; ; index = 201 ; length = 1 line = 11 ; column = 23 ; value =','; }
|
||||||
|
{kind = TOKEN_FLOATLITERAL; ; index = 203 ; length = 3 line = 11 ; column = 25 ; value ='2'; }
|
||||||
|
{kind = TOKEN_RIGHTPAREN; ; index = 206 ; length = 1 line = 11 ; column = 28 ; value =')'; }
|
||||||
|
{kind = TOKEN_SEMICOLON; ; index = 207 ; length = 1 line = 11 ; column = 29 ; value =';'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 211 ; length = 1 line = 12 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 214 ; length = 1 line = 13 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_PIXEL; ; index = 219 ; length = 5 line = 15 ; column = 0 ; value ='pixel'; }
|
||||||
|
{kind = TOKEN_IDENTIFIER; ; index = 225 ; length = 4 line = 15 ; column = 6 ; value ='main'; }
|
||||||
|
{kind = TOKEN_DOUBLECOLON; ; index = 230 ; length = 2 line = 15 ; column = 11 ; value ='::'; }
|
||||||
|
{kind = TOKEN_LEFTPAREN; ; index = 233 ; length = 1 line = 15 ; column = 14 ; value ='('; }
|
||||||
|
{kind = TOKEN_RIGHTPAREN; ; index = 234 ; length = 1 line = 15 ; column = 15 ; value =')'; }
|
||||||
|
{kind = TOKEN_LEFTBRACE; ; index = 236 ; length = 1 line = 15 ; column = 17 ; value ='{'; }
|
||||||
|
{kind = TOKEN_RIGHTBRACE; ; index = 241 ; length = 1 line = 17 ; column = 0 ; value ='}'; }
|
||||||
|
{kind = TOKEN_EOF; ; index = 244 ; length = 0 line = 18 ; column = 0 ; value =''; }
|
||||||
@@ -20,6 +20,9 @@ test/function_call_return.ink lex
|
|||||||
test/functions_with_same_name.ink lex
|
test/functions_with_same_name.ink lex
|
||||||
test/function_with_int_return.ink lex
|
test/function_with_int_return.ink lex
|
||||||
test/if_cond_assign.ink lex
|
test/if_cond_assign.ink lex
|
||||||
|
test/ifdefs.ink lex
|
||||||
|
test/if_def_block.ink lex
|
||||||
|
test/if_def_expression.ink lex
|
||||||
test/if_if_if.ink lex
|
test/if_if_if.ink lex
|
||||||
test/inferred_types.ink lex
|
test/inferred_types.ink lex
|
||||||
test/large_block.ink lex
|
test/large_block.ink lex
|
||||||
|
|||||||
8
test/parse/if_def_block.golden
Normal file
8
test/parse/if_def_block.golden
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
(program
|
||||||
|
(fun pixel ps_main
|
||||||
|
[]
|
||||||
|
(#if Env.Alpha
|
||||||
|
(:= alpha_color (float4 1 0 0 1))
|
||||||
|
(:= f 2)
|
||||||
|
(:= color (float3 0 0 0))
|
||||||
|
(:= g 5))))
|
||||||
6
test/parse/if_def_expression.golden
Normal file
6
test/parse/if_def_expression.golden
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
(program
|
||||||
|
(#if (|| (&& Env.PS5 Env.XSX) Env.Switch2)
|
||||||
|
(fun vertex vs_console_main
|
||||||
|
[])
|
||||||
|
(fun vertex vs_windows_main
|
||||||
|
[])))
|
||||||
12
test/parse/ifdefs.golden
Normal file
12
test/parse/ifdefs.golden
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
(program
|
||||||
|
(#if Env.Skinning
|
||||||
|
(fun vertex vs_skinning_main
|
||||||
|
[]
|
||||||
|
(:= x float 5))
|
||||||
|
(#if Env.UV
|
||||||
|
(fun vertex vs_texture_mapping_main
|
||||||
|
[]
|
||||||
|
(:= x float2 (float2 2 2)))))
|
||||||
|
|
||||||
|
(fun pixel ps_main
|
||||||
|
[]))
|
||||||
@@ -20,6 +20,9 @@ test/function_call_return.ink parse
|
|||||||
test/functions_with_same_name.ink parse
|
test/functions_with_same_name.ink parse
|
||||||
test/function_with_int_return.ink parse
|
test/function_with_int_return.ink parse
|
||||||
test/if_cond_assign.ink parse
|
test/if_cond_assign.ink parse
|
||||||
|
test/ifdefs.ink parse
|
||||||
|
test/if_def_block.ink parse
|
||||||
|
test/if_def_expression.ink parse
|
||||||
test/if_if_if.ink parse
|
test/if_if_if.ink parse
|
||||||
test/inferred_types.ink parse
|
test/inferred_types.ink parse
|
||||||
test/large_block.ink parse
|
test/large_block.ink parse
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
[1;37mtest/wrong_type_for_function.ink:11,17: [31merror: [37mProcedure call did not match any of the possible overloads for 'float4'
|
|
||||||
[96m found:
|
|
||||||
color : float4 = float4(y, 1.0, 1.0, 1.0);
|
|
||||||
^^^^^^
|
|
||||||
|
|
||||||
[97m While matching argument 1 in function call.
|
|
||||||
[96m color : float4 = float4(y, 1.0, 1.0, 1.0);
|
|
||||||
^
|
|
||||||
[97m Possible overloads:
|
|
||||||
[96m float4 :: (float, float, float, float); (test/wrong_type_for_function.ink:0)
|
|
||||||
[96m float4 :: (float2, float2); (test/wrong_type_for_function.ink:0)
|
|
||||||
[96m float4 :: (float2, float, float); (test/wrong_type_for_function.ink:0)
|
|
||||||
[96m float4 :: (float, float2, float); (test/wrong_type_for_function.ink:0)
|
|
||||||
[96m float4 :: (float, float, float2); (test/wrong_type_for_function.ink:0)
|
|
||||||
[96m float4 :: (float, float3); (test/wrong_type_for_function.ink:0)
|
|
||||||
[96m float4 :: (float3, float); (test/wrong_type_for_function.ink:0)
|
|
||||||
[96m float4 :: (float4); (test/wrong_type_for_function.ink:0)
|
|
||||||
[96m float4 :: (float); (test/wrong_type_for_function.ink:0)
|
|
||||||
|
|
||||||
[36m[37m[1;37mtest/wrong_type_for_function.ink:11,24: [31merror: [37mType mismatch. Expected float got float2
|
|
||||||
[96m found:
|
|
||||||
color : float4 = float4(y, 1.0, 1.0, 1.0);
|
|
||||||
^
|
|
||||||
expected:
|
|
||||||
float
|
|
||||||
|
|
||||||
got:
|
|
||||||
y : float2 = foo()
|
|
||||||
|
|
||||||
[36m[37m
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
test/assign_arithmetic_expression.ink semant
|
|
||||||
test/basic_property_and_return_value.ink semant
|
|
||||||
test/builtin_types.ink semant
|
|
||||||
test/complicated_computation.ink semant
|
|
||||||
test/constant_buffer.ink semant
|
|
||||||
test/empty_struct.ink semant
|
|
||||||
test/empty_vertex_main.ink semant
|
|
||||||
test/empty_vertex_main_with_position_parameter.ink semant
|
|
||||||
test/field_assignment.ink semant
|
|
||||||
test/for_i_loop.ink semant
|
|
||||||
test/function_call.ink semant
|
|
||||||
test/function_call_out_of_order_declaration.ink semant
|
|
||||||
test/function_call_return.ink semant
|
|
||||||
test/functions_with_same_name.ink semant
|
|
||||||
test/function_with_int_return.ink semant
|
|
||||||
test/if_cond_assign.ink semant
|
|
||||||
test/inferred_types.ink semant
|
|
||||||
test/multiple_functions.ink semant
|
|
||||||
test/multiple_semicolons_everywhere.ink semant
|
|
||||||
test/nested_if.ink semant
|
|
||||||
test/non_bool_cond.ink semant
|
|
||||||
test/pass_and_access_struct_fields_in_functions.ink semant
|
|
||||||
test/passthrough.ink semant
|
|
||||||
test/property_rename.ink semant
|
|
||||||
test/redeclared_variable.ink semant
|
|
||||||
test/simple_else_if.ink semant
|
|
||||||
test/simple_if_else.ink semant
|
|
||||||
test/simple_if.ink semant
|
|
||||||
test/simple_struct_access.ink semant
|
|
||||||
test/struct_access_primitive_type.ink semant
|
|
||||||
test/struct_within_struct.ink semant
|
|
||||||
test/type_as_variable_name.ink semant
|
|
||||||
test/unary.ink semant
|
|
||||||
test/undeclared_function.ink semant
|
|
||||||
test/undeclared_symbol.ink semant
|
|
||||||
test/unknown_overload.ink semant
|
|
||||||
test/use_builtin_functions.ink semant
|
|
||||||
test/wrong_argument_count.ink semant
|
|
||||||
test/wrong_multiply.ink semant
|
|
||||||
test/wrong_type_for_function.ink semant
|
|
||||||
Reference in New Issue
Block a user