Ifdefs, moved semantic to check, fixed error reporting for builtins

This commit is contained in:
2025-09-16 11:04:57 +02:00
parent f99f86bc37
commit 7fefe0ecf6
71 changed files with 739 additions and 385 deletions

42
AST.jai
View File

@@ -356,6 +356,29 @@ pretty_print_node :: (node : *AST_Node, indentation : int, builder : *String_Bui
case .If; {
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 {
append(builder, "\n");
pretty_print_node(node.children[2], indentation + 4, builder);
}
append(builder, ")");
}
case .For; {
pretty_print_for(node, indentation, builder, skip_indent);
}
@@ -479,9 +502,26 @@ pretty_print_declaration :: (declaration : *AST_Node, indentation : int, builder
pretty_print_node(declaration.children[0], 0, builder);
append(builder, "\n");
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 {
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);
}
}

View File

@@ -135,7 +135,7 @@ Checker_State :: enum {
Adding_Builtins;
}
Semantic_Checker :: struct {
Checker :: struct {
program_root : *AST_Node;
path : string;
@@ -152,17 +152,17 @@ Semantic_Checker :: struct {
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[0] = 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);
}
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 '%':
@@ -184,7 +184,7 @@ symbol_redeclaration :: (checker : *Semantic_Checker, redeclared_node : *AST_Nod
cyan(*builder);
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);
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);
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);
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);
}
symbol_undeclared :: (checker : *Semantic_Checker, node : *AST_Node) {
symbol_undeclared :: (checker : *Checker, node : *AST_Node) {
/*
Use of undeclard symbol '%'.
b = f;
@@ -231,7 +231,7 @@ Use of undeclard symbol '%'.
cyan(*builder);
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);
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);
}
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;
init_string_builder(*builder,, temp);
@@ -250,7 +250,7 @@ no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, ov
indent(*builder, 1);
append(*builder, "found:\n");
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);
print_token_pointer(*builder, call.source_location.main_token);
newline(*builder);
@@ -275,7 +275,7 @@ no_matching_overload_found :: (checker : *Semantic_Checker, call : *AST_Node, ov
cyan(*builder);
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);
print_token_pointer(*builder, arg_node.source_location.main_token);
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;
indent(*builder, 2);
// @Incomplete(niels): We need a way to properly save the path of the declaration
print_to_builder(*builder, "% (%:%)\n", print_from_source_location(func_location), checker.path,
if func.builtin {
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);
}
// @Incomplete(niels): We need a way to properly save the path of the declaration
if !arg_node {
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;
init_string_builder(*builder,, temp);
@@ -328,7 +333,7 @@ not_all_control_paths_return_value :: (checker : *Semantic_Checker, node : *AST_
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);
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);
}
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;
init_string_builder(*builder,, temp);
@@ -364,7 +369,7 @@ Too many arguments: Expected %, got %.
indent(*builder, 1);
append(*builder, "found:\n");
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);
print_token_pointer(*builder, call.source_location.main_token);
append(*builder, "\n\n");
@@ -372,7 +377,7 @@ Too many arguments: Expected %, got %.
append(*builder, "expected:\n");
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[0] = call.source_location;
@@ -381,7 +386,7 @@ Too many arguments: Expected %, got %.
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'.
@@ -395,7 +400,7 @@ Error: Undeclared identifier 'name'.
print_to_builder(*builder, "Attempt to call undeclared function '%'.\n\n", node.name);
cyan(*builder);
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);
print_token_pointer(*builder, node.source_location.main_token);
newline(*builder);
@@ -404,7 +409,7 @@ Error: Undeclared identifier 'name'.
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 '%'.
b.t = f;
@@ -423,7 +428,7 @@ Field '%' is not defined in struct '%'.
cyan(*builder);
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);
print_token_pointer(*builder, node.source_location.main_token);
newline(*builder);
@@ -431,13 +436,13 @@ Field '%' is not defined in struct '%'.
indent(*builder, 1);
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);
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 '%'.
x.d = 5;
@@ -451,11 +456,11 @@ Attempting to access a field on a primitive type '%'.
init_string_builder(*builder,, temp);
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);
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);
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");
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);
record_error(checker, message, node.source_location, false);
@@ -479,7 +484,7 @@ Attempting to access a field on a primitive type '%'.
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.
if 100.0
@@ -499,7 +504,7 @@ if_condition_has_to_be_boolean_type :: (checker : *Semantic_Checker, usage_site
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);
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_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);
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);
}
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);
got_var := from_handle(checker, got);
@@ -545,7 +550,7 @@ type_mismatch :: (checker : *Semantic_Checker, usage_site : *AST_Node, expect_no
indent(*builder, 1);
append(*builder, "found:\n");
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);
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);
print_to_builder(*builder, "expected:\n");
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");
// indent(*builder, 2);
@@ -572,14 +577,14 @@ type_mismatch :: (checker : *Semantic_Checker, usage_site : *AST_Node, expect_no
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);
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.message_kind = .Error;
error.report_source_location = report_source_location;
@@ -607,7 +612,7 @@ is_proper :: (var : Type_Variable) -> bool {
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);
previous_scope := checker.current_scope;
checker.current_scope = handle;
@@ -615,7 +620,7 @@ use_scope :: (checker : *Semantic_Checker, handle : Scope_Handle) -> Scope_Handl
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;
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;
}
pop_scope :: (checker : *Semantic_Checker) -> Scope_Handle {
pop_scope :: (checker : *Checker) -> Scope_Handle {
scope := get_scope(checker, checker.current_scope);
if !scope.parent {
return 0;
@@ -652,7 +657,7 @@ pop_scope :: (checker : *Semantic_Checker) -> Scope_Handle {
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 {
return null, 0;
}
@@ -662,7 +667,7 @@ peek_scope :: (checker : *Semantic_Checker) -> *Scope, Scope_Handle {
return scope, xx count;
}
get_current_scope :: (checker : *Semantic_Checker) -> *Scope {
get_current_scope :: (checker : *Checker) -> *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];
}
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);
}
@@ -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);
}
new_type_variable :: (checker : *Semantic_Checker) -> *Type_Variable, Type_Variable_Handle {
new_type_variable :: (checker : *Checker) -> *Type_Variable, Type_Variable_Handle {
variable : Type_Variable;
handle := cast(Type_Variable_Handle)checker.ctx.type_variables.count + 1;
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;
}
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.name = name;
@@ -720,7 +725,7 @@ Arg :: struct {
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);
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;
}
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);
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.source_node = builtin_node;
function.type_variable = handle;
function.builtin = true;
find_result := find_symbol(checker, name, checker.current_scope);
if !find_result {
@@ -822,13 +827,13 @@ add_child :: (variable : *Type_Variable, child : Type_Variable_Handle) {
// 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);
assert(variable.children.count < Type_Variable.MAX_TYPE_VARIABLE_CHILDREN);
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_sampler_index = 0;
checker.current_texture_index = 0;
@@ -864,11 +869,11 @@ find_symbol :: (scope_stack : Scope_Stack, name : string, current_scope : Scope_
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);
}
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);
}
@@ -877,11 +882,11 @@ from_handle :: (variables : []Type_Variable, handle : Type_Variable_Handle) -> *
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);
}
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 == {
case .Int; #through;
case .Half; #through;
@@ -900,7 +905,7 @@ proper_type_to_string :: (builder : *String_Builder, variables : []Type_Variable
if child.kind == .FieldList {
for field : child.children {
var := field.type_variable;
print_type_variable(builder, variables, var);
print_type_variable(ctx, builder, variables, var);
if it_index != child.children.count - 1 {
append(builder, ", ");
@@ -915,10 +920,10 @@ proper_type_to_string :: (builder : *String_Builder, variables : []Type_Variable
append(builder, " -> ", );
return_var := from_handle(variables, var.return_type_variable);
if is_proper(return_var) {
proper_type_to_string(builder, variables, return_var);
proper_type_to_string(ctx, builder, variables, return_var);
} else {
append(builder, "[[");
print_type_variable(builder, variables, var.return_type_variable);
print_type_variable(ctx, builder, variables, var.return_type_variable);
append(builder, "]]", );
}
} 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 == {
case .Int; #through;
case .Half; #through;
@@ -943,7 +948,7 @@ proper_type_to_string :: (variables : []Type_Variable, var : Type_Variable, allo
builder : String_Builder;
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);
}
case .Struct; {
@@ -954,7 +959,7 @@ proper_type_to_string :: (variables : []Type_Variable, var : Type_Variable, allo
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 == {
case Typenames[Type_Kind.Int]; return .Int;
case Typenames[Type_Kind.Half]; return .Half;
@@ -980,18 +985,18 @@ lookup_type :: (checker : *Semantic_Checker, scope : Scope_Handle, type_string :
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;
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 {
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.type = .Struct;
variable.source_kind = .Declaration;
@@ -1034,11 +1039,11 @@ declare_struct :: (checker : *Semantic_Checker, node : *AST_Node, name : string)
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);
}
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;
if node.name.count > 0 {
@@ -1053,7 +1058,7 @@ declare_properties :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Va
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);
var := from_handle(checker, type_var);
var.type = .CBuffer;
@@ -1073,11 +1078,11 @@ get_actual_function_name :: (node : *AST_Node) -> string {
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);
}
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) {
invalid_symbol_name(checker, node, "function");
return 0;
@@ -1204,7 +1209,7 @@ declare_function :: (checker : *Semantic_Checker, node : *AST_Node, builtin : bo
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);
find_result := find_symbol(checker, name_to_check, checker.current_scope);
@@ -1238,6 +1243,10 @@ check_function :: (checker : *Semantic_Checker, node : *AST_Node) {
stm := from_handle(checker, result_var);
add_child(variable, result_var);
}
if statement.kind == .If_Directive {
break;
}
}
}
}
@@ -1251,7 +1260,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);
// x : int;
// x.d = 5;
@@ -1296,7 +1305,7 @@ check_variable :: (checker : *Semantic_Checker, node : *AST_Node, struct_field_p
return 0;
}
can_declare :: (checker : *Semantic_Checker, name : string) -> bool {
can_declare :: (checker : *Checker, name : string) -> bool {
max_value := Type_Kind.Max_Builtin;
for i : 0..max_value - 1 {
@@ -1309,7 +1318,7 @@ can_declare :: (checker : *Semantic_Checker, name : string) -> bool {
}
//@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.name = node.name;
typename : string;
@@ -1393,7 +1402,7 @@ check_field :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_
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);
if !find_result {
@@ -1505,7 +1514,7 @@ check_call :: (checker : *Semantic_Checker, node : *AST_Node, type_var : Type_Va
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 == {
case .Function; {
check_function(checker, node);
@@ -1645,8 +1654,7 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H
}
}
case .If_Directive; {
cond_var := check_node(checker, node.children[0]);
assert(false, "Not implemented yet\n");
check_if_directive(checker, node);
}
case .Variable; {
return check_variable(checker, node);
@@ -1686,9 +1694,85 @@ check_node :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_H
return 0;
}
traverse :: (checker : *Semantic_Checker, root : *AST_Node) {
declarations := root.children;
for declaration : declarations {
is_valid_define :: (checker : *Checker, def : string) -> bool {
for env_def : checker.ctx.environment.defines {
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.foreign_declaration {
fun_handle := declare_foreign_function(checker, declaration);
@@ -1701,23 +1785,35 @@ traverse :: (checker : *Semantic_Checker, root : *AST_Node) {
declare_struct(checker, declaration);
} else if declaration.kind == .CBuffer {
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 {
return;
}
for declaration : declarations {
if declaration.kind == .If_Directive {
continue;
}
check_node(checker, declaration);
}
}
traverse :: (checker : *Semantic_Checker) {
traverse :: (checker : *Checker) {
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);
rhs_var := from_handle(checker, rhs);
@@ -1797,7 +1893,7 @@ types_compatible :: (checker : *Semantic_Checker, lhs : Type_Variable_Handle, rh
return false;
}
add_builtins_new :: (checker : *Semantic_Checker) {
add_builtins_new :: (checker : *Checker) {
checker.state = .Adding_Builtins;
float_name := Typenames[Type_Kind.Float];
@@ -2065,7 +2161,7 @@ add_builtins_new :: (checker : *Semantic_Checker) {
checker.state = .Type_Checking;
}
add_builtins :: (checker : *Semantic_Checker) {
add_builtins :: (checker : *Checker) {
source_location := #location().fully_pathed_filename;
path_array := split(source_location, "/");
@@ -2084,7 +2180,7 @@ add_builtins :: (checker : *Semantic_Checker) {
if !ok {
messages : [..]Compiler_Message;
internal_error_message(*messages, "Error loading builtin functions.", checker.path);
print("%\n", report_messages(messages));
print("%\n", report_messages(checker.ctx, messages));
assert(false);
return;
}
@@ -2123,7 +2219,7 @@ add_builtins :: (checker : *Semantic_Checker) {
checker.ctx.tokens = prev_tokens;
}
type_check :: (checker : *Semantic_Checker, root : *AST_Node) {
type_check :: (checker : *Checker, root : *AST_Node) {
traverse(checker, root);
}
@@ -2138,7 +2234,7 @@ check :: (ctx : *Compiler_Context, allocator : Allocator = temp) {
init_context_allocators();
defer clear_context_allocators();
checker : Semantic_Checker;
checker : Checker;
checker.current_buffer_index = 0;
checker.current_sampler_index = 0;
@@ -2255,7 +2351,7 @@ pretty_print_struct :: (scope_stack : *Scope_Stack, current_scope : Scope_Handle
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 {
return;
}
@@ -2291,7 +2387,7 @@ pretty_print_scope :: (current_scope : Scope_Handle, scope_stack : Scope_Stack,
if type_variable.typename.count > 0 && type_variable.source_kind != .Declaration {
indent(builder, indentation + 1);
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");
// print_to_builder(builder, "%\n", type_variable.typename);
} else {
@@ -2334,7 +2430,7 @@ pretty_print_scope :: (current_scope : Scope_Handle, scope_stack : Scope_Stack,
for child : scope.children {
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 {
@@ -2343,7 +2439,7 @@ pretty_print_scope :: (current_scope : Scope_Handle, scope_stack : Scope_Stack,
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.type != .Function || variable.type != .Struct {
print_to_builder(builder, "%", type_to_string(variable));
@@ -2391,13 +2487,13 @@ print_type_variable :: (builder : *String_Builder, variables : []Type_Variable,
source_location.end = right_most.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; {
if variable.return_type_variable{
assert(false);
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);
@@ -2406,7 +2502,7 @@ print_type_variable :: (builder : *String_Builder, variables : []Type_Variable,
for child : node.children {
if child.kind == .ArgList {
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 {
append(builder, ", ");
@@ -2418,23 +2514,23 @@ print_type_variable :: (builder : *String_Builder, variables : []Type_Variable,
append(builder, ")");
}
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);
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;
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);
}
@@ -2444,7 +2540,7 @@ pretty_print_symbol_table :: (ctx : *Compiler_Context, allocator : Allocator) ->
init_string_builder(*builder,, allocator);
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);
}

View File

@@ -11,17 +11,14 @@ Output_Language :: enum {
HLSL;
GLSL; // @Incomplete
MLSL; // @Incomplete
// SPIRV; // @Incomplete: Should we do this?
}
Codegen_State :: struct {
path : string;
// scope_stack : Scope_Stack;
current_scope : Scope_Handle;
// type_variables : []Type_Variable;
// root : *AST_Node;
output_language : Output_Language;
builder : String_Builder;
@@ -29,14 +26,6 @@ Codegen_State :: struct {
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.[
"texture",
"sampler",
@@ -132,26 +121,23 @@ emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
print_to_builder(*state.builder, " = ");
emit_node(state, child, 0);
}
if node.parent.kind == .Block {
append(*state.builder, ";");
}
for i :0..field.children.count - 1 {
child := from_handle(state.result.type_variables, field.children[i]);
emit_node(state, child.source_node, 0);
}
for hint : node.hint_tokens {
if hint.ident_value == "position" {
// @Incomplete(nb): Should be a lookup table somewhere
if lookup_hint(hint.ident_value) == .Position {
append(*state.builder, " : POSITION");
} else if hint.ident_value == "uv" {
} else if lookup_hint(hint.ident_value) == .UV {
append(*state.builder, " : TEXCOORD0");
} else if hint.ident_value == "outposition" {
} else if lookup_hint(hint.ident_value) == .Output_Position {
append(*state.builder, " : SV_POSITION");
}
}

View File

@@ -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;
init_string_builder(*builder);
for message : messages {
report_message(*builder, message);
report_message(ctx, *builder, message);
}
return builder_to_string(*builder);
}
report_message :: (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 : *Compiler_Context, builder : *String_Builder, message : Compiler_Message) {
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");
if path.count > 0 {
print_to_builder(builder, "%:", path);
@@ -140,7 +140,7 @@ report_message :: (builder : *String_Builder, path : string, message : string, s
if report_source_location {
for location : source_locations {
append(builder, "\t");
print_from_source_location(builder, location);
print_from_source_location(ctx, builder, location);
append(builder, "\n\t");
begin := location.begin;

44
Ink.jai
View File

@@ -23,7 +23,7 @@ LEXER_FOLDER :: "lex";
PARSER_FOLDER :: "parse";
CODEGEN_FOLDER :: "codegen";
COMPILED_FOLDER :: "compiled";
SEMANTIC_ANALYSIS_FOLDER :: "semant";
CHECK_FOLDER :: "check";
TESTS_FOLDER :: "test";
SHADER_EXTENSION :: "ink";
@@ -32,7 +32,7 @@ SUITE_EXTENSION :: "suite";
Stage_Flags :: enum_flags u16 {
Lexer :: 0x1;
Parser :: 0x2;
Semantic_Analysis :: 0x4;
Check :: 0x4;
Codegen :: 0x8;
Compile :: 0x10;
}
@@ -97,10 +97,10 @@ get_golden_path :: (file_path : string, stage : Stage_Flags) -> string {
make_directory_if_it_does_not_exist(dir);
array_add(*path.words, PARSER_FOLDER);
}
case .Semantic_Analysis; {
dir := tprint("%/%", TESTS_FOLDER, SEMANTIC_ANALYSIS_FOLDER);
case .Check; {
dir := tprint("%/%", TESTS_FOLDER, CHECK_FOLDER);
make_directory_if_it_does_not_exist(dir);
array_add(*path.words, SEMANTIC_ANALYSIS_FOLDER);
array_add(*path.words, CHECK_FOLDER);
}
case .Codegen; {
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 {
result.type = .Failed;
result_text = report_messages(ctx.messages);
result_text = report_messages(ctx, ctx.messages);
return result;
}
@@ -261,7 +261,7 @@ run_lexer_test :: (file_path : string, ctx : *Compiler_Context, output_type : Ou
lex(ctx);
if ctx.had_error {
result.type = .Failed;
result_text = report_messages(ctx.messages);
result_text = report_messages(ctx, ctx.messages);
} else {
result_text = pretty_print_tokens(ctx.tokens, context.allocator);
}
@@ -300,7 +300,7 @@ run_parser_test :: (ctx : *Compiler_Context, output_type : Output_Type = 0) -> R
if ctx.had_error {
result.type = .Failed;
result_text = report_messages(ctx.messages);
result_text = report_messages(ctx, ctx.messages);
} else {
result_text = pretty_print_ast(ctx.root, context.allocator);
}
@@ -316,7 +316,7 @@ run_parser_test :: (ctx : *Compiler_Context, output_type : Output_Type = 0) -> R
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.path = ctx.file.path;
result_text : string;
@@ -325,7 +325,7 @@ run_semantic_analysis_test :: (ctx : *Compiler_Context, output_type : Output_Typ
if ctx.had_error {
result.type = .Failed;
result_text = report_messages(ctx.messages);
result_text = report_messages(ctx, ctx.messages);
} else {
result_text = pretty_print_symbol_table(ctx, context.allocator);
}
@@ -336,12 +336,12 @@ run_semantic_analysis_test :: (ctx : *Compiler_Context, output_type : Output_Typ
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);
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.path = file_path;
@@ -352,7 +352,7 @@ run_semantic_analysis_test :: (file_path : string, ctx : *Compiler_Context, outp
return result;
}
result = run_semantic_analysis_test(ctx, output_type);
result = run_check_test(ctx, output_type);
return result;
}
@@ -389,17 +389,17 @@ run_test_new :: (file_path : string, stage_flags : Stage_Flags, results : *[..]R
record_result(results, result);
}
if stage_flags & .Semantic_Analysis {
if stage_flags & .Check {
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 {
result = run_semantic_analysis_test(file_path, *ctx, output_type);
result = run_check_test(file_path, *ctx, output_type);
}
record_result(results, result);
}
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);
} else {
result = run_codegen_test(file_path, *ctx, output_type);
@@ -554,8 +554,8 @@ read_suite :: (file_path : string, suite : *Test_Suite, allocator := temp) -> bo
stage_flags |= .Lexer;
} else if equal(trimmed, "parse") {
stage_flags |= .Parser;
} else if equal(trimmed, "semant") {
stage_flags |= .Semantic_Analysis;
} else if equal(trimmed, "check") {
stage_flags |= .Check;
} else if equal(trimmed, "codegen") {
stage_flags |= .Codegen;
} else if equal(trimmed, "compile") {
@@ -577,7 +577,7 @@ stage_to_string :: (stage : Stage_Flags) -> string {
if #complete stage == {
case .Lexer; return "lexing";
case .Parser; return "parsing";
case .Semantic_Analysis; return "semantic checking";
case .Check; return "checking";
case .Codegen; return "codegen";
case .Compile; return "compiled";
case; return "";
@@ -671,8 +671,8 @@ main :: () {
current_suite.test_cases[cases - 1].stage_flags |= .Lexer;
} else if arg == "-parse" {
current_suite.test_cases[cases - 1].stage_flags |= .Parser;
} else if arg == "-semant" {
current_suite.test_cases[cases - 1].stage_flags |= .Semantic_Analysis;
} else if arg == "-check" {
current_suite.test_cases[cases - 1].stage_flags |= .Check;
} else if arg == "-codegen" {
current_suite.test_cases[cases - 1].stage_flags |= .Codegen;
} else if arg == "-compile" {

View File

@@ -11,6 +11,7 @@ Lexer :: struct {
}
Token_Kind :: enum {
TOKEN_INVALID :: 0;
TOKEN_FLOATLITERAL;
TOKEN_INTLITERAL;
@@ -386,7 +387,12 @@ make_directive :: (lexer : *Lexer) -> *Token {
for tok : ctx.tokens {
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;
}
@@ -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;
begin := source_location.begin;
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;
token_string : string;
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();
defer scratch_end(sc);
builder : String_Builder;
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);
}

View File

@@ -186,7 +186,7 @@ unexpected_token :: (state : *Parse_State, token : Token, message : string) {
indent(*builder, 1);
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);
print_token_pointer(*builder, token);
@@ -207,7 +207,7 @@ else_if_without_if :: (state : *Parse_State) {
indent(*builder, 1);
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);
print_token_pointer(*builder, token);
@@ -229,7 +229,7 @@ else_without_if :: (state : *Parse_State) {
indent(*builder, 1);
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);
print_token_pointer(*builder, token);
@@ -249,7 +249,7 @@ unable_to_parse_statement :: (state : *Parse_State, token : Token, message : str
indent(*builder, 1);
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);
@@ -269,7 +269,7 @@ expected_expression :: (state : *Parse_State, token : Token, message : string) {
indent(*builder, 1);
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);
print_token_pointer(*builder, token);
@@ -288,7 +288,7 @@ missing_type_specifier :: (state : *Parse_State, token : Token, message : string
indent(*builder, 1);
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;
@@ -312,7 +312,7 @@ empty_block :: (state : *Parse_State, token : Token, message : string) {
indent(*builder, 1);
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;
@@ -336,7 +336,26 @@ unable_to_open_file :: (state : *Parse_State, path : string, token : Token) {
indent(*builder, 1);
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);
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);
}
// new_builtin_node :: (nodes : *[..]AST_Node, kind : AST_Kind) -> *AST_Node {
// 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 {
make_builtin_token :: (tokens : *[..]Token, kind : Token_Kind, text : string, col : *int, line : *int) -> *Token {
tok : Token;
tok.kind = kind;
start := 0;
buffer := get_current_buffer(builder);
if buffer {
start := buffer.count;
}
tok.column = col.*;
print_to_builder(builder, "%", text);
buffer = get_current_buffer(builder);
end := buffer.count;
for c : text {
if c == #char "\n" {
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.builtin = true;
tok.source = text.data;
tok.ident_value = text;
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 {
sc := get_scratch(context.allocator);
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);
source_location : Source_Range;
@@ -439,17 +442,13 @@ new_builtin_struct_node :: (ctx : *Compiler_Context, name : string, members : []
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;
source_location.begin = ident_token;
append(*builder, " ");
make_builtin_token(*ctx.tokens, *builder, .TOKEN_DOUBLECOLON, "::", *col, *line);
append(*builder, " ");
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");
make_builtin_token(*ctx.tokens, .TOKEN_DOUBLECOLON, " :: ", *col, *line);
make_builtin_token(*ctx.tokens, .TOKEN_STRUCT, "struct ", *col, *line);
make_builtin_token(*ctx.tokens, .TOKEN_LEFTBRACE, "{\n\t", *col, *line);
line += 1;
col = 0;
@@ -460,18 +459,14 @@ new_builtin_struct_node :: (ctx : *Compiler_Context, name : string, members : []
field := make_node(*ctx.nodes, .Field);
field_source_loc : Source_Range;
indent(*builder, 1);
field_ident := make_builtin_token(*ctx.tokens, *builder, .TOKEN_IDENTIFIER, tprint("%", member.name), *col, *line);
field_ident := make_builtin_token(*ctx.tokens, .TOKEN_IDENTIFIER, member.name, *col, *line);
field_source_loc.begin = field_ident;
field.token = field_ident;
field.name = member.name;
append(*builder, " ");
make_builtin_token(*ctx.tokens, *builder, .TOKEN_COLON, ":", *col, *line);
append(*builder, " ");
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");
make_builtin_token(*ctx.tokens, .TOKEN_COLON, ": ", *col, *line);
make_builtin_token(*ctx.tokens, .TOKEN_IDENTIFIER, member.typename, *col, *line);
semicolon_tok := make_builtin_token(*ctx.tokens, .TOKEN_SEMICOLON, ";", *col, *line);
col = 0;
line += 1;
@@ -481,27 +476,10 @@ new_builtin_struct_node :: (ctx : *Compiler_Context, name : string, members : []
add_child(field_list, field);
}
brace_token := make_builtin_token(*ctx.tokens, *builder, .TOKEN_RIGHTBRACE, "}", *col, *line);
append(*builder, "\n");
brace_token := make_builtin_token(*ctx.tokens, .TOKEN_RIGHTBRACE, "\n}", *col, *line);
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;
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 {
sc := get_scratch(context.allocator);
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);
@@ -522,13 +498,11 @@ new_builtin_function_node :: (ctx : *Compiler_Context, name : string, members :
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;
append(*builder, " ");
make_builtin_token(*ctx.tokens, *builder, .TOKEN_DOUBLECOLON, "::", *col, *line);
append(*builder, " ");
make_builtin_token(*ctx.tokens, *builder, .TOKEN_LEFTPAREN, "(", *col, *line);
make_builtin_token(*ctx.tokens, .TOKEN_DOUBLECOLON, " :: ", *col, *line);
make_builtin_token(*ctx.tokens, .TOKEN_LEFTPAREN, "(", *col, *line);
field_list := make_node(*ctx.nodes, .FieldList);
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_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, *builder, .TOKEN_IDENTIFIER, tprint("%", member.typename), *col, *line);
type_tok := make_builtin_token(*ctx.tokens, .TOKEN_IDENTIFIER, member.typename, *col, *line);
field_source_loc.begin = type_tok;
field.token = type_tok;
if it_index < members.count - 1 {
make_builtin_token(*ctx.tokens, *builder, .TOKEN_COMMA, ",", *col, *line);
append(*builder, " ");
make_builtin_token(*ctx.tokens, .TOKEN_COMMA, ", ", *col, *line);
}
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);
}
make_builtin_token(*ctx.tokens, *builder, .TOKEN_RIGHTPAREN, ")", *col, *line);
semicolon_tok := make_builtin_token(*ctx.tokens, *builder, .TOKEN_SEMICOLON, ";", *col, *line);
make_builtin_token(*ctx.tokens, .TOKEN_RIGHTPAREN, ")", *col, *line);
semicolon_tok := make_builtin_token(*ctx.tokens, .TOKEN_SEMICOLON, ";", *col, *line);
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;
return node;
@@ -838,16 +794,28 @@ directive :: (state : *Parse_State) -> *AST_Node {
if_directive := make_node(state, .If_Directive);
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);
cond := expression(state);
add_child(if_directive, cond);
source_location.end = state.previous;
advance_to_sync_point(state);
if_body := block(state);
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;
return if_directive;
@@ -1256,13 +1224,15 @@ statement :: (parse_state : *Parse_State) -> *AST_Node {
else_statement :: (parse_state : *Parse_State) -> *AST_Node {
if check(parse_state, .TOKEN_IF) {
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);
}
block :: (parse_state : *Parse_State) -> *AST_Node {
node : *AST_Node = make_node(parse_state, .Block);
array_reserve(*node.children, 1024);
array_reserve(*node.children, 32);
source_location : Source_Range;
@@ -1361,10 +1331,22 @@ function_declaration :: (parse_state : *Parse_State, identifier_token : *Token,
case .Vertex; {
node.vertex_entry_point = true;
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; {
node.pixel_entry_point = true;
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, "");
// }
}
}

View File

@@ -1,11 +1,20 @@
#load "Lexing.jai";
#load "Error.jai";
#load "Parsing.jai";
#load "Semantic_Analysis.jai";
#load "Check.jai";
#load "Codegen.jai";
#import "File_Utilities";
/* TODO
- [ ] 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
- [ ] Support #if
*/
add_define :: (env : *Environment, key : string) {
for define : env.defines {
if define == key {
@@ -55,10 +64,33 @@ Hint_Kind :: enum {
Position;
UV;
Target;
Output_Position;
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 {
kind : Hint_Kind;
@@ -99,21 +131,11 @@ Constant_Buffer :: struct {
fields : Static_Array(Property_Field, 16);
// hints : Field_Hint; // optional hint...
hints : [..]Field_Hint;
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 {
source : string;
path : string;
@@ -149,7 +171,7 @@ Compiler_Context :: struct {
return_value : Field;
}
properties : Properties; //@Note(niels): We'll deprecate this in favor of just marking a constant buffer how you'd want to use it
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;
@@ -294,7 +316,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));
}
@@ -349,13 +371,11 @@ type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope
for hint : variable.source_node.hint_tokens {
field_hint : Field_Hint;
if hint.ident_value == "position" {
// @Incomplete(nb): Should be a lookup table somewhere
if lookup_hint(hint.ident_value) == .Position {
field_hint.kind = .Position;
} else if hint.ident_value == "uv" {
} else if lookup_hint(hint.ident_value) == .UV {
field_hint.kind = .UV;
} else if starts_with(hint.ident_value, "target") {
// @Incomplete(nb): Should be a lookup table somewhere
} else if lookup_hint(hint.ident_value) == .Target {
index_str : string;
index_str.data = *hint.ident_value.data[7];
index_str.count = 1;
@@ -381,7 +401,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));
}
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);
}
@@ -445,22 +465,20 @@ generate_output_data :: (ctx : *Compiler_Context) {
ctx.properties.buffer_index = property_variable.resource_index;
}
if ctx.pixel_entry_point.node {
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);
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);
for hint : type_variable.source_node.hint_tokens {
field_hint : Field_Hint;
if hint.ident_value == "position" {
// @Incomplete(nb): Should be a lookup table somewhere
if lookup_hint(hint.ident_value) == .Position {
field_hint.kind = .Position;
} else if starts_with(hint.ident_value, "target") {
// @Incomplete(nb): Should be a lookup table somewhere
} else if lookup_hint(hint.ident_value) == .Target {
index_str : string;
index_str.data = *hint.ident_value.data[7];
index_str.count = 1;
@@ -475,10 +493,10 @@ generate_output_data :: (ctx : *Compiler_Context) {
}
array_add(*field.hints, field_hint);
}
ctx.pixel_entry_point.return_value = field;
}
}
}
compile_file :: (ctx : *Compiler_Context, path : string, allocator : Allocator = temp) {
new_context := context;

View File

@@ -7,15 +7,15 @@
 result : float4 = float4(1.0, foo * res, 0.0, 1.0);
^
 Possible overloads:
 float4 :: (float, float, float, float); (test/wrong_multiply.ink:0)
 float4 :: (float2, float2); (test/wrong_multiply.ink:0)
 float4 :: (float2, float, float); (test/wrong_multiply.ink:0)
 float4 :: (float, float2, float); (test/wrong_multiply.ink:0)
 float4 :: (float, float, float2); (test/wrong_multiply.ink:0)
 float4 :: (float, float3); (test/wrong_multiply.ink:0)
 float4 :: (float3, float); (test/wrong_multiply.ink:0)
 float4 :: (float4); (test/wrong_multiply.ink:0)
 float4 :: (float); (test/wrong_multiply.ink:0)
 float4 :: (float, float, float, float)
 float4 :: (float2, float2)
 float4 :: (float2, float, float)
 float4 :: (float, float2, float)
 float4 :: (float, float, float2)
 float4 :: (float, float3)
 float4 :: (float3, float)
 float4 :: (float4)
 float4 :: (float)
test/wrong_multiply.ink:4,34: error: Type mismatch. Expected float got float2
 found:

View File

@@ -0,0 +1,30 @@
test/wrong_type_for_function.ink:11,17: error: Procedure call did not match any of the possible overloads for 'float4'
 found:
color : float4 = float4(y, 1.0, 1.0, 1.0);
^^^^^^
 While matching argument 1 in function call.
 color : float4 = float4(y, 1.0, 1.0, 1.0);
^
 Possible overloads:
 float4 :: (float, float, float, float)
 float4 :: (float2, float2)
 float4 :: (float2, float, float)
 float4 :: (float, float2, float)
 float4 :: (float, float, float2)
 float4 :: (float, float3)
 float4 :: (float3, float)
 float4 :: (float4)
 float4 :: (float)
test/wrong_type_for_function.ink:11,24: error: Type mismatch. Expected float got float2
 found:
color : float4 = float4(y, 1.0, 1.0, 1.0);
^
expected:
float
got:
y : float2 = foo()


43
test/check_all.suite Normal file
View 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

View File

@@ -0,0 +1,7 @@
void ps_main()
{
float4 color = float4(1, 0, 0, 1);
float f = 2.0f;
}

View File

@@ -10,6 +10,9 @@ test/field_assignment.ink codegen
test/function_call.ink codegen
test/function_call_out_of_order_declaration.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/meta_block.ink codegen
test/multiple_functions.ink codegen

View File

@@ -11,6 +11,9 @@ test/function_call.ink compile
test/function_call_out_of_order_declaration.ink compile
test/function_call_return.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/meta_block.ink compile
test/multiple_functions.ink compile

11
test/if_def_block.ink Normal file
View 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;
}
}

View 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 :: () {
}
}

View File

@@ -1,5 +1,17 @@
#if Defines.Skinning {
vertex main :: () {
// Stub
//#add_define Skinning
#add_define UV
#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 :: () {
}

View 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 =''; }

View File

@@ -0,0 +1,34 @@
{kind = TOKEN_DIRECTIVE; ; index = 62 ; length = 2 line = 5 ; column = 0 ; value ='if'; }
{kind = TOKEN_LEFTPAREN; ; index = 65 ; length = 1 line = 5 ; column = 3 ; value ='('; }
{kind = TOKEN_IDENTIFIER; ; index = 66 ; length = 3 line = 5 ; column = 4 ; value ='Env'; }
{kind = TOKEN_DOT; ; index = 69 ; length = 1 line = 5 ; column = 7 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 70 ; length = 3 line = 5 ; column = 8 ; value ='PS5'; }
{kind = TOKEN_LOGICALAND; ; index = 74 ; length = 2 line = 5 ; column = 12 ; value ='&&'; }
{kind = TOKEN_IDENTIFIER; ; index = 77 ; length = 3 line = 5 ; column = 15 ; value ='Env'; }
{kind = TOKEN_DOT; ; index = 80 ; length = 1 line = 5 ; column = 18 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 81 ; length = 3 line = 5 ; column = 19 ; value ='XSX'; }
{kind = TOKEN_RIGHTPAREN; ; index = 84 ; length = 1 line = 5 ; column = 22 ; value =')'; }
{kind = TOKEN_LOGICALOR; ; index = 86 ; length = 2 line = 5 ; column = 24 ; value ='||'; }
{kind = TOKEN_IDENTIFIER; ; index = 89 ; length = 3 line = 5 ; column = 27 ; value ='Env'; }
{kind = TOKEN_DOT; ; index = 92 ; length = 1 line = 5 ; column = 30 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 93 ; length = 7 line = 5 ; column = 31 ; value ='Switch2'; }
{kind = TOKEN_LEFTBRACE; ; index = 101 ; length = 1 line = 5 ; column = 39 ; value ='{'; }
{kind = TOKEN_VERTEX; ; index = 105 ; length = 6 line = 6 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 112 ; length = 12 line = 6 ; column = 7 ; value ='console_main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 125 ; length = 2 line = 6 ; column = 20 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 128 ; length = 1 line = 6 ; column = 23 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 129 ; length = 1 line = 6 ; column = 24 ; value =')'; }
{kind = TOKEN_LEFTBRACE; ; index = 131 ; length = 1 line = 6 ; column = 26 ; value ='{'; }
{kind = TOKEN_RIGHTBRACE; ; index = 137 ; length = 1 line = 8 ; column = 0 ; value ='}'; }
{kind = TOKEN_RIGHTBRACE; ; index = 140 ; length = 1 line = 9 ; column = 0 ; value ='}'; }
{kind = TOKEN_ELSE; ; index = 142 ; length = 4 line = 9 ; column = 2 ; value ='else'; }
{kind = TOKEN_LEFTBRACE; ; index = 147 ; length = 1 line = 9 ; column = 7 ; value ='{'; }
{kind = TOKEN_VERTEX; ; index = 151 ; length = 6 line = 10 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 158 ; length = 12 line = 10 ; column = 7 ; value ='windows_main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 171 ; length = 2 line = 10 ; column = 20 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 174 ; length = 1 line = 10 ; column = 23 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 175 ; length = 1 line = 10 ; column = 24 ; value =')'; }
{kind = TOKEN_LEFTBRACE; ; index = 177 ; length = 1 line = 10 ; column = 26 ; value ='{'; }
{kind = TOKEN_RIGHTBRACE; ; index = 183 ; length = 1 line = 12 ; column = 0 ; value ='}'; }
{kind = TOKEN_RIGHTBRACE; ; index = 186 ; length = 1 line = 13 ; column = 0 ; value ='}'; }
{kind = TOKEN_EOF; ; index = 189 ; length = 0 line = 14 ; column = 0 ; value =''; }

52
test/lex/ifdefs.golden Normal file
View File

@@ -0,0 +1,52 @@
{kind = TOKEN_DIRECTIVE; ; index = 45 ; length = 2 line = 5 ; column = 0 ; value ='if'; }
{kind = TOKEN_IDENTIFIER; ; index = 48 ; length = 3 line = 5 ; column = 3 ; value ='Env'; }
{kind = TOKEN_DOT; ; index = 51 ; length = 1 line = 5 ; column = 6 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 52 ; length = 8 line = 5 ; column = 7 ; value ='Skinning'; }
{kind = TOKEN_LEFTBRACE; ; index = 61 ; length = 1 line = 5 ; column = 16 ; value ='{'; }
{kind = TOKEN_VERTEX; ; index = 65 ; length = 6 line = 6 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 72 ; length = 13 line = 6 ; column = 7 ; value ='skinning_main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 86 ; length = 2 line = 6 ; column = 21 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 89 ; length = 1 line = 6 ; column = 24 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 90 ; length = 1 line = 6 ; column = 25 ; value =')'; }
{kind = TOKEN_LEFTBRACE; ; index = 92 ; length = 1 line = 6 ; column = 27 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 97 ; length = 1 line = 7 ; column = 0 ; value ='x'; }
{kind = TOKEN_COLON; ; index = 99 ; length = 1 line = 7 ; column = 2 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 101 ; length = 5 line = 7 ; column = 4 ; value ='float'; }
{kind = TOKEN_ASSIGN; ; index = 107 ; length = 1 line = 7 ; column = 10 ; value ='='; }
{kind = TOKEN_FLOATLITERAL; ; index = 109 ; length = 3 line = 7 ; column = 12 ; value ='5'; }
{kind = TOKEN_SEMICOLON; ; index = 112 ; length = 1 line = 7 ; column = 15 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 116 ; length = 1 line = 8 ; column = 0 ; value ='}'; }
{kind = TOKEN_RIGHTBRACE; ; index = 119 ; length = 1 line = 9 ; column = 0 ; value ='}'; }
{kind = TOKEN_ELSE; ; index = 121 ; length = 4 line = 9 ; column = 2 ; value ='else'; }
{kind = TOKEN_DIRECTIVE; ; index = 127 ; length = 2 line = 9 ; column = 7 ; value ='if'; }
{kind = TOKEN_IDENTIFIER; ; index = 130 ; length = 3 line = 9 ; column = 10 ; value ='Env'; }
{kind = TOKEN_DOT; ; index = 133 ; length = 1 line = 9 ; column = 13 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 134 ; length = 2 line = 9 ; column = 14 ; value ='UV'; }
{kind = TOKEN_LEFTBRACE; ; index = 137 ; length = 1 line = 9 ; column = 17 ; value ='{'; }
{kind = TOKEN_VERTEX; ; index = 141 ; length = 6 line = 10 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 148 ; length = 20 line = 10 ; column = 7 ; value ='texture_mapping_main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 169 ; length = 2 line = 10 ; column = 28 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 172 ; length = 1 line = 10 ; column = 31 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 173 ; length = 1 line = 10 ; column = 32 ; value =')'; }
{kind = TOKEN_LEFTBRACE; ; index = 175 ; length = 1 line = 10 ; column = 34 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 180 ; length = 1 line = 11 ; column = 0 ; value ='x'; }
{kind = TOKEN_COLON; ; index = 182 ; length = 1 line = 11 ; column = 2 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 184 ; length = 6 line = 11 ; column = 4 ; value ='float2'; }
{kind = TOKEN_ASSIGN; ; index = 191 ; length = 1 line = 11 ; column = 11 ; value ='='; }
{kind = TOKEN_IDENTIFIER; ; index = 193 ; length = 6 line = 11 ; column = 13 ; value ='float2'; }
{kind = TOKEN_LEFTPAREN; ; index = 199 ; length = 1 line = 11 ; column = 19 ; value ='('; }
{kind = TOKEN_FLOATLITERAL; ; index = 200 ; length = 3 line = 11 ; column = 20 ; value ='2'; }
{kind = TOKEN_COMMA; ; index = 203 ; length = 1 line = 11 ; column = 23 ; value =','; }
{kind = TOKEN_FLOATLITERAL; ; index = 205 ; length = 3 line = 11 ; column = 25 ; value ='2'; }
{kind = TOKEN_RIGHTPAREN; ; index = 208 ; length = 1 line = 11 ; column = 28 ; value =')'; }
{kind = TOKEN_SEMICOLON; ; index = 209 ; length = 1 line = 11 ; column = 29 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 213 ; length = 1 line = 12 ; column = 0 ; value ='}'; }
{kind = TOKEN_RIGHTBRACE; ; index = 216 ; length = 1 line = 13 ; column = 0 ; value ='}'; }
{kind = TOKEN_PIXEL; ; index = 221 ; length = 5 line = 15 ; column = 0 ; value ='pixel'; }
{kind = TOKEN_IDENTIFIER; ; index = 227 ; length = 4 line = 15 ; column = 6 ; value ='main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 232 ; length = 2 line = 15 ; column = 11 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 235 ; length = 1 line = 15 ; column = 14 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 236 ; length = 1 line = 15 ; column = 15 ; value =')'; }
{kind = TOKEN_LEFTBRACE; ; index = 238 ; length = 1 line = 15 ; column = 17 ; value ='{'; }
{kind = TOKEN_RIGHTBRACE; ; index = 243 ; length = 1 line = 17 ; column = 0 ; value ='}'; }
{kind = TOKEN_EOF; ; index = 246 ; length = 0 line = 18 ; column = 0 ; value =''; }

View File

@@ -20,6 +20,9 @@ test/function_call_return.ink lex
test/functions_with_same_name.ink lex
test/function_with_int_return.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/inferred_types.ink lex
test/large_block.ink lex

View 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))))

View File

@@ -0,0 +1,6 @@
(program
(#if (|| (&& Env.PS5 Env.XSX) Env.Switch2)
(fun vertex vs_console_main
[])
(fun vertex vs_windows_main
[])))

View File

@@ -20,6 +20,9 @@ test/function_call_return.ink parse
test/functions_with_same_name.ink parse
test/function_with_int_return.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/inferred_types.ink parse
test/large_block.ink parse

View File

@@ -1,30 +0,0 @@
test/wrong_type_for_function.ink:11,17: error: Procedure call did not match any of the possible overloads for 'float4'
 found:
color : float4 = float4(y, 1.0, 1.0, 1.0);
^^^^^^
 While matching argument 1 in function call.
 color : float4 = float4(y, 1.0, 1.0, 1.0);
^
 Possible overloads:
 float4 :: (float, float, float, float); (test/wrong_type_for_function.ink:0)
 float4 :: (float2, float2); (test/wrong_type_for_function.ink:0)
 float4 :: (float2, float, float); (test/wrong_type_for_function.ink:0)
 float4 :: (float, float2, float); (test/wrong_type_for_function.ink:0)
 float4 :: (float, float, float2); (test/wrong_type_for_function.ink:0)
 float4 :: (float, float3); (test/wrong_type_for_function.ink:0)
 float4 :: (float3, float); (test/wrong_type_for_function.ink:0)
 float4 :: (float4); (test/wrong_type_for_function.ink:0)
 float4 :: (float); (test/wrong_type_for_function.ink:0)
test/wrong_type_for_function.ink:11,24: error: Type mismatch. Expected float got float2
 found:
color : float4 = float4(y, 1.0, 1.0, 1.0);
^
expected:
float
got:
y : float2 = foo()


View File

@@ -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