Add lexing, parsing and some semantic checking for constant buffers.
This commit is contained in:
@@ -829,8 +829,11 @@ proper_type_to_string :: (checker : *Semantic_Checker, var : Type_Variable, allo
|
||||
proper_type_to_string(*builder, checker, var);
|
||||
return builder_to_string(*builder,, allocator);
|
||||
}
|
||||
case .Struct; {
|
||||
return var.typename;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return "______not proper type______";
|
||||
}
|
||||
|
||||
@@ -916,12 +919,25 @@ declare_struct :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variab
|
||||
return declare_struct(checker, node, node.name);
|
||||
}
|
||||
|
||||
PROPERTIES_BUFFER_INDEX : u32 : 0;
|
||||
META_BUFFER_INDEX : u32 : PROPERTIES_BUFFER_INDEX + 1;
|
||||
current_custom_buffer_index : u32 = META_BUFFER_INDEX + 1;
|
||||
|
||||
declare_properties :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle {
|
||||
name := ifx node.name.count == 0 then "properties" else node.name;
|
||||
type_var := declare_struct(checker, node, name);
|
||||
var := h2tv(checker, type_var);
|
||||
var.typename = "properties";
|
||||
var.buffer_index = 0;
|
||||
var.buffer_index = PROPERTIES_BUFFER_INDEX;
|
||||
return type_var;
|
||||
}
|
||||
|
||||
declare_cbuffer :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable_Handle {
|
||||
type_var := declare_struct(checker, node);
|
||||
var := h2tv(checker, type_var);
|
||||
var.typename = "constant_buffer";
|
||||
current_custom_buffer_index += 1;
|
||||
var.buffer_index = current_custom_buffer_index;
|
||||
return type_var;
|
||||
}
|
||||
|
||||
@@ -930,7 +946,7 @@ declare_meta :: (checker : *Semantic_Checker, node : *AST_Node) -> Type_Variable
|
||||
type_var := declare_struct(checker, node, name);
|
||||
var := h2tv(checker, type_var);
|
||||
var.typename = name;
|
||||
var.buffer_index = 0;
|
||||
var.buffer_index = META_BUFFER_INDEX;
|
||||
return type_var;
|
||||
}
|
||||
|
||||
@@ -1204,7 +1220,7 @@ create_variable :: (checker : *Semantic_Checker, node : *AST_Node, field_parent
|
||||
field_access_on_primitive_type(checker, node, find_result.type_variable);
|
||||
return 0;
|
||||
} else {
|
||||
lookup_name : string;
|
||||
lookup_name : string = variable.typename;
|
||||
if variable.typename == "properties" {
|
||||
lookup_name = variable.name;
|
||||
}
|
||||
@@ -1306,6 +1322,34 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
|
||||
overload_found := false;
|
||||
arg_node : *AST_Node = null;
|
||||
|
||||
Result :: struct {
|
||||
var : Type_Variable_Handle;
|
||||
node : *AST_Node;
|
||||
}
|
||||
arg_vars : [..]Result;
|
||||
|
||||
// @incomplete(niels): Should be some kind of scratch allocator instead probably?
|
||||
arg_vars.allocator = temp;
|
||||
arg_count := 0;
|
||||
|
||||
for child : node.children {
|
||||
if child.kind == {
|
||||
case .ArgList; {
|
||||
arg_count = child.children.count;
|
||||
for arg_child : child.children {
|
||||
arg_var := check_node(checker, arg_child);
|
||||
if arg_var != 0 {
|
||||
array_add(*arg_vars, .{ arg_var, arg_child });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if arg_vars.count != arg_count {
|
||||
return;
|
||||
}
|
||||
|
||||
for *func : find_result.functions {
|
||||
if overload_found {
|
||||
break;
|
||||
@@ -1313,6 +1357,10 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
|
||||
|
||||
function := h2tv(checker, func.type_variable);
|
||||
|
||||
if arg_count != function.child_count {
|
||||
continue;
|
||||
}
|
||||
|
||||
if function.return_var > 0 {
|
||||
return_var := h2tv(checker, function.return_var);
|
||||
constrained_var := h2tv(checker, type_var);
|
||||
@@ -1327,39 +1375,27 @@ create_call_constraint :: (checker : *Semantic_Checker, node : *AST_Node, type_v
|
||||
|
||||
all_args_match : bool = true;
|
||||
|
||||
for child : node.children {
|
||||
if child.kind == {
|
||||
case .ArgList; {
|
||||
if child.children.count != function.child_count {
|
||||
// mismatched_arguments(checker, node, func, child.children.count, function.child_count);
|
||||
break;
|
||||
}
|
||||
for arg : arg_vars {
|
||||
function_param := function.children[it_index];
|
||||
|
||||
for arg_child : child.children {
|
||||
arg_var := check_node(checker, arg_child);
|
||||
function_param := function.children[it_index];
|
||||
|
||||
// @Incomplete(nb): Improve the error handling of this constraint.
|
||||
// The usage site might be the call, but really the usage site
|
||||
// is the variable, with the call around it.
|
||||
// We could probably expand source locations to always include the whole line
|
||||
// That is unlikely to be annoying now that I think about it.
|
||||
// So maybe we just always do that? Then we always have the complete information
|
||||
// and the actual token we want to focus on is just the one we have?
|
||||
// @Update(nb): We actually do this now for a bunch of places, but not all.
|
||||
// Error reporting in this case is still not great, since it doesn't properly mark the
|
||||
// faulty variable.
|
||||
create_equivalence_constraint(checker, arg_var, function_param, arg_child);
|
||||
if !types_compatible(checker, arg_var, function_param) {
|
||||
if all_args_match {
|
||||
arg_node = arg_child;
|
||||
}
|
||||
all_args_match = false;
|
||||
} else {
|
||||
overload_found = all_args_match;
|
||||
}
|
||||
}
|
||||
// @Incomplete(nb): Improve the error handling of this constraint.
|
||||
// The usage site might be the call, but really the usage site
|
||||
// is the variable, with the call around it.
|
||||
// We could probably expand source locations to always include the whole line
|
||||
// That is unlikely to be annoying now that I think about it.
|
||||
// So maybe we just always do that? Then we always have the complete information
|
||||
// and the actual token we want to focus on is just the one we have?
|
||||
// @Update(nb): We actually do this now for a bunch of places, but not all.
|
||||
// Error reporting in this case is still not great, since it doesn't properly mark the
|
||||
// faulty variable.
|
||||
create_equivalence_constraint(checker, arg.var, function_param, arg.node);
|
||||
if !types_compatible(checker, arg.var, function_param) {
|
||||
if all_args_match {
|
||||
arg_node = arg.node;
|
||||
}
|
||||
all_args_match = false;
|
||||
} else {
|
||||
overload_found = all_args_match;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1478,6 +1514,8 @@ traverse :: (checker : *Semantic_Checker, root : *AST_Node) {
|
||||
declare_struct(checker, declaration);
|
||||
} else if declaration.kind == .Meta {
|
||||
declare_meta(checker, declaration);
|
||||
} else if declaration.kind == .CBuffer {
|
||||
declare_cbuffer(checker, declaration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user