Fix lvalue/rvalue binaries. Fix structured buffer output.

This commit is contained in:
2025-09-29 22:22:00 +02:00
parent 2e23b37405
commit 0c0e31db38
23 changed files with 244 additions and 103 deletions

View File

@@ -8,7 +8,6 @@
// [ ] Add a sentinel variable that works for from_handle
// [ ] Add and error for using keywords as names, or rename the dx11 keywords in the resulting hlsl shader.
// [ ] Add missing scope in for loop for loop iterator
// [ ] Maybe we remove the resource index on type variables, seems like we don't need it there.
// [ ] Add swizzling
// [ ] Add temp assignment fail check: (a + b).x = float2(0, 0);
// [x] Improve error reporting on mismatched overloads when types don't match, but arity does.
@@ -157,6 +156,8 @@ Checker :: struct {
ctx : *Compiler_Context;
checking_lvalue : bool;
current_buffer_index : u32 = 0;
current_sampler_index : u32 = 0;
current_texture_index : u32 = 0;
@@ -421,6 +422,43 @@ Error: Undeclared identifier 'name'.
record_error(checker, message, node.source_location, false);
}
cannot_assign_to_lvalue :: (checker : *Checker, node : *AST_Node) {
/*
Cannot assign to an lvalue.
(a + b).x = 2.0;
*/
builder : String_Builder;
init_string_builder(*builder,, temp);
append(*builder, "Cannot assign to an lvalue.\n");
cyan(*builder);
indent(*builder, 1);
location := node.source_location;
begin : Token = node.token;
begin.index -= begin.column;
begin.length += begin.column;
begin.source -= begin.column;
begin.column = 0;
location.begin = begin;
print("%\n", location.main_token.kind);
print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, location));
// print_to_builder(*builder, "%\n", print_from_source_location(checker.ctx, node.source_location));
indent(*builder, 1);
print_token_pointer(*builder, location.begin);
newline(*builder);
newline(*builder);
message := builder_to_string(*builder);
record_error(checker, message, node.source_location, false);
}
field_not_defined_on_struct :: (checker : *Checker, node : *AST_Node, struct_symbol : *Defined_Symbol) {
/*
Field '%' is not defined in struct '%'.
@@ -1072,7 +1110,7 @@ declare_cbuffer :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handl
var.type = .CBuffer;
var.resource_index = checker.current_buffer_index;
checker.current_buffer_index += 1;
array_add(*checker.ctx.constant_buffers, type_var);
array_add(*checker.ctx.typed_buffers, type_var);
return type_var;
}
@@ -1081,6 +1119,7 @@ declare_buffer :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle
variable.type = .Buffer;
variable.source_kind = .Declaration;
variable.name = node.name;
variable.source_node = node;
find_result := find_symbol(checker, node.name, checker.current_scope);
if !find_result {
@@ -1107,7 +1146,7 @@ declare_buffer :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle
node.type_variable = handle;
array_add(*checker.ctx.buffers, handle);
array_add(*checker.ctx.typed_buffers, handle);
return handle;
}
@@ -1304,43 +1343,13 @@ check_function :: (checker : *Checker, node : *AST_Node) {
}
}
check_variable :: (checker : *Checker, node : *AST_Node, struct_field_parent : *AST_Node = null) -> Type_Variable_Handle {
check_variable :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
find_result := find_symbol(checker, node.name, checker.current_scope);
// x : int;
// x.d = 5;
if find_result {
node.type_variable = find_result.type_variable;
variable := from_handle(checker, find_result.type_variable);
variable.struct_field_parent = struct_field_parent;
if get_scope(checker, checker.current_scope).kind == .Struct {
variable.scope = checker.current_scope;
}
if node.children.count > 0 {
if variable.type != .Struct && variable.type != .CBuffer && variable.type != .Buffer {
field_access_on_primitive_type(checker, node, find_result.type_variable);
return 0;
} else if variable.type == .Array {
} else {
lookup_name : string = variable.typename;
struct_symbol := find_symbol(checker, lookup_name, checker.current_scope);
type_variable := from_handle(checker, struct_symbol.type_variable);
previous_scope := use_scope(checker, type_variable.scope);
child := node.children[0];
var := find_symbol(checker, child.name, type_variable.scope);
if var == null {
field_not_defined_on_struct(checker, child, struct_symbol);
return 0;
}
access := check_variable(checker, child, node);
use_scope(checker, previous_scope);
return access;
}
}
return find_result.type_variable;
}
@@ -1607,6 +1616,7 @@ check_node :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
field_access_on_primitive_type(checker, node.children[0], lhs_handle);
return 0;
}
lookup_name := lhs_variable.typename;
struct_symbol := find_symbol(checker, lookup_name, checker.current_scope);
type_variable := from_handle(checker, struct_symbol.type_variable);
@@ -1624,7 +1634,17 @@ check_node :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
return access;
}
case .Binary; {
if checker.checking_lvalue {
cannot_assign_to_lvalue(checker, node.parent.parent);
return 0;
}
prev_checking_lvalue := checker.checking_lvalue;
if node.token.kind == .TOKEN_ASSIGN {
checker.checking_lvalue = true;
}
lhs_var := check_node(checker, node.children[0]);
checker.checking_lvalue = prev_checking_lvalue;
if lhs_var == 0 {
return 0;
}