diff --git a/AST.jai b/AST.jai index b96c86a..9f28ea4 100644 --- a/AST.jai +++ b/AST.jai @@ -20,6 +20,7 @@ AST_Kind :: enum { If; For; CBuffer; + Buffer; FieldList; ArgList; Variable; @@ -473,18 +474,20 @@ pretty_print_declaration :: (declaration : *AST_Node, indentation : int, builder append(builder, "struct "); } else if declaration.kind == .CBuffer { append(builder, "constant_buffer "); + } else if declaration.kind == .Buffer { + append(builder, "buffer "); } print_to_builder(builder, "%", declaration.name); - if declaration.kind == .CBuffer { + if declaration.kind == .CBuffer || declaration.kind == .Buffer{ for hint : declaration.hint_tokens { if hint.string_value.count > 0 { print_to_builder(builder, " (@%)", hint.string_value); } } - if declaration.kind != .If_Directive { - print_to_builder(builder, "%", declaration.name); - } + // if declaration.kind != .If_Directive { + // print_to_builder(builder, "%", declaration.name); + // } } if declaration.kind == .Function && declaration.token.kind == .TOKEN_IDENTIFIER{ diff --git a/Check.jai b/Check.jai index 95a7103..9f62d2d 100644 --- a/Check.jai +++ b/Check.jai @@ -36,6 +36,7 @@ Type_Kind :: enum { Struct; CBuffer; + Buffer; Array; } @@ -64,6 +65,8 @@ Type_Variable :: struct { name : string; + + //@Note(niels) For functions return_type_variable : Type_Variable_Handle; @@ -74,9 +77,8 @@ Type_Variable :: struct { struct_field_parent : *AST_Node; typename : string; - // is_array : bool; - element_type : Type_Kind; - element_typename : string; + element_type : Type_Variable_Handle; + element_count : int; MAX_TYPE_VARIABLE_CHILDREN :: 32; children : Static_Array(Type_Variable_Handle, MAX_TYPE_VARIABLE_CHILDREN); @@ -109,6 +111,7 @@ Scope_Kind :: enum { Global; Function; Struct; + Block; } Scope :: struct { @@ -539,11 +542,11 @@ type_mismatch :: (checker : *Checker, usage_site : *AST_Node, expect_node : *AST child_handle := got_var.children[i]; child := from_handle(checker, child_handle); - print_to_builder(*builder, "% : %", child.name, type_to_string(child)); + print_to_builder(*builder, "% : %", child.name, type_to_string(checker.ctx.type_variables, child)); } } - print_to_builder(*builder, "Type mismatch. Expected % got %\n", type_to_string(expect_var), type_to_string(got_var)); + print_to_builder(*builder, "Type mismatch. Expected % got %\n", type_to_string(checker.ctx.type_variables, expect_var), type_to_string(checker.ctx.type_variables, got_var)); cyan(*builder); location := usage_site.source_location; @@ -813,7 +816,16 @@ new_builtin_function :: (checker : *Checker, name : string, args : []Arg, return if return_arg.typename.count > 0 { return_var, return_handle := new_type_variable(checker); - return_var.type = lookup_type(checker, checker.current_scope, return_arg.typename, *return_var.typename); + symb : Defined_Symbol; + return_var.type = lookup_type(checker, checker.current_scope, return_arg.typename, *return_var.typename, *symb); + if symb.type_variable > 0 { + symb_var := from_handle(checker, symb.type_variable); + if symb_var.type == .Array || symb_var.type == .Buffer { + return_var.element_type = symb_var.element_type; + // return_var.element_typename = symb_var.element_typename; + return_var.element_count = symb_var.element_count; + } + } from_handle(checker, handle).return_type_variable = return_handle; } @@ -911,7 +923,6 @@ proper_type_to_string :: (ctx : *Compiler_Context, builder : *String_Builder, va } append(builder, ")"); - if var.return_type_variable > 0 { append(builder, " -> ", ); return_var := from_handle(variables, var.return_type_variable); @@ -955,7 +966,7 @@ proper_type_to_string :: (ctx : *Compiler_Context, variables : []Type_Variable, return "______not proper type______"; } -lookup_type :: (checker : *Checker, scope : Scope_Handle, type_string : string, typename : *string = null) -> Type_Kind { +lookup_type :: (scope_stack : Scope_Stack, variables : []Type_Variable, scope : Scope_Handle, type_string : string, typename : *string = null, out_symbol : *Defined_Symbol = null) -> Type_Kind { if type_string == { case Typenames[Type_Kind.Int]; return .Int; case Typenames[Type_Kind.Half]; return .Half; @@ -964,10 +975,13 @@ lookup_type :: (checker : *Checker, scope : Scope_Handle, type_string : string, case Typenames[Type_Kind.Sampler]; return .Sampler; case Typenames[Type_Kind.Texture2D]; return .Texture2D; } - - symbol := find_symbol(checker, type_string, scope); + + symbol := find_symbol(scope_stack, type_string, scope); if symbol { - symbol_var := from_handle(checker, symbol.type_variable); + if out_symbol { + out_symbol.* = symbol.*; + } + symbol_var := from_handle(variables, symbol.type_variable); if symbol_var.type == .Struct { if typename { typename.* = symbol_var.typename; @@ -981,15 +995,21 @@ lookup_type :: (checker : *Checker, scope : Scope_Handle, type_string : string, return .Invalid; } +lookup_type :: (checker : *Checker, scope : Scope_Handle, type_string : string, typename : *string = null, out_symbol : *Defined_Symbol = null) -> Type_Kind { + return lookup_type(checker.ctx.scope_stack, checker.ctx.type_variables, scope, type_string, typename, out_symbol); +} + 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 : *Checker, node : *AST_Node) { + push_scope(checker, kind = Scope_Kind.Block); for child : node.children { check_node(checker, child); } + pop_scope(checker); } declare_struct :: (checker : *Checker, node : *AST_Node, name : string) -> Type_Variable_Handle { @@ -1049,6 +1069,20 @@ declare_cbuffer :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handl return type_var; } +declare_buffer :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle { + variable, handle := new_type_variable(checker); + variable.type = .Buffer; + variable.source_kind = .Declaration; + variable.name = node.name; + + variable.element_type = declare_struct(checker, node); // Won't work entirely like this. At least we're going to need some access changes + + variable.resource_index = checker.current_buffer_index; + checker.current_buffer_index += 1; + array_add(*checker.ctx.buffers, handle); + return handle; +} + get_actual_function_name :: (node : *AST_Node) -> string { name_to_check := node.name; if node.vertex_entry_point { @@ -1256,7 +1290,7 @@ check_variable :: (checker : *Checker, node : *AST_Node, struct_field_parent : * } if node.children.count > 0 { - if variable.type != .Struct && variable.type != .CBuffer { + 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 { @@ -1303,11 +1337,14 @@ check_field :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle { variable.name = node.name; typename : string; - - // variable.is_array = node.array_field; if node.array_field { variable.type = .Array; - variable.element_type = lookup_type(checker, checker.current_scope, node, *variable.element_typename); + element_type, element_handle := new_type_variable(checker); + element_type.type = lookup_type(checker, checker.current_scope, node, *element_type.typename); + element_type.scope = checker.current_scope; + + variable.element_type = element_handle; + variable.element_count = node.children[0].integer_value; } else { variable.type = lookup_type(checker, checker.current_scope, node, *typename); } @@ -1553,6 +1590,11 @@ check_node :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle { add_child(variable, rhs_var); if node.token.kind == { + case .TOKEN_LEFTBRACKET; { + element := from_handle(checker, lhs_type.element_type); + variable.type = element.type; + variable.typename = element.typename; + } case .TOKEN_PLUS; #through; case .TOKEN_MINUS; #through; case .TOKEN_STAR; #through; @@ -1598,10 +1640,13 @@ check_node :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle { case .For; { loop_iterator := node.token; + scope, scope_handle := push_scope(checker, kind = .Block); + symbol : Defined_Symbol; symbol.name = loop_iterator.ident_value; symbol.source_node = node; variable, handle := new_type_variable(checker); + variable.scope = scope_handle; variable.name = symbol.name; typename : string; variable.type = .Int; @@ -1621,6 +1666,7 @@ check_node :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle { } check_block(checker, node.children[2]); + pop_scope(checker); } case .If; { cond_var := check_node(checker, node.children[0]); @@ -1774,6 +1820,8 @@ check_declaration :: (checker : *Checker, declaration : *AST_Node) { declare_cbuffer(checker, declaration); } else if declaration.kind == .If_Directive { check_if_directive(checker, declaration); + } else if declaration.kind == .Buffer { + declare_buffer(checker, declaration); } } @@ -2242,8 +2290,7 @@ check :: (ctx : *Compiler_Context, allocator : Allocator = temp) { // Pretty printing #scope_file - -type_to_string :: (type_variable : Type_Variable) -> string { +type_to_string :: (variables : []Type_Variable, type_variable : Type_Variable, allocator := context.allocator) -> string { if type_variable.type == { case .Invalid; return "{{invalid}}"; @@ -2261,8 +2308,10 @@ type_to_string :: (type_variable : Type_Variable) -> string { case .Struct; { return type_variable.typename; } + case .Buffer; #through; case .Array; - // return "array"; + element_type := from_handle(variables, type_variable.element_type); + return sprint("[%].%", type_variable.element_count, type_to_string(variables, element_type)); } return ""; } @@ -2295,7 +2344,7 @@ pretty_print_function :: (scope_stack : *Scope_Stack, current_scope : Scope_Hand if tv.builtin { print_to_builder(builder, "%", tv.name); } else { - print_to_builder(builder, "% : %", tv.name, type_to_string(tv)); + print_to_builder(builder, "% : %", tv.name, type_to_string(variables, tv)); } } else { pretty_print_function(scope_stack, current_scope, variables, builder, "", tv, 0); @@ -2309,30 +2358,35 @@ pretty_print_function :: (scope_stack : *Scope_Stack, current_scope : Scope_Hand } if function.return_type_variable> 0 { - print_to_builder(builder, ") -> %\n", type_to_string(from_handle(variables, function.return_type_variable))); + print_to_builder(builder, ") -> %\n", type_to_string(variables, from_handle(variables, function.return_type_variable))); } else { append(builder, ")\n"); } } -pretty_print_struct :: (scope_stack : *Scope_Stack, current_scope : Scope_Handle, variables : []Type_Variable, builder : *String_Builder, name : string, struct_type : Type_Variable, indentation : int) { +pretty_print_struct :: (ctx : *Compiler_Context, scope_stack : *Scope_Stack, current_scope : Scope_Handle, variables : []Type_Variable, builder : *String_Builder, name : string, struct_field : Type_Variable, indentation : int) { indent(builder, indentation); print_key(scope_stack, current_scope, builder, name); + append(builder, "{"); + struct_symbol : Defined_Symbol; + lookup_type(scope_stack, variables, current_scope, struct_field.typename, null, *struct_symbol); + struct_type := from_handle(variables, struct_symbol.type_variable); + for 0..struct_type.children.count - 1 { child_handle := struct_type.children[it]; child := from_handle(variables, child_handle); print_to_builder(builder, child.name); append(builder, " : "); - print_to_builder(builder, type_to_string(child)); + print_to_builder(builder, type_to_string(variables, child)); if it < struct_type.children.count - 1 { append(builder, ", "); } } - append(builder, "}\n"); + append(builder, "}"); } 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) { @@ -2347,7 +2401,20 @@ pretty_print_scope :: (ctx : *Compiler_Context, current_scope : Scope_Handle, sc if scope.name.count > 0 { print_to_builder(builder, "%", scope.name); } else { - append(builder, "global"); + if scope.kind == { + case .Global; { + append(builder, "global"); + } + case .Block; { + append(builder, "block"); + } + case .Function; { + append(builder, "function"); + } + case .Struct; { + append(builder, "struct"); + } + } } append(builder, ") ["); if scope.table.count > 0 { @@ -2365,23 +2432,6 @@ pretty_print_scope :: (ctx : *Compiler_Context, current_scope : Scope_Handle, sc case .Function; { pretty_print_function(*scope_stack, current_scope, variables, builder, key, type_variable, 1); } - case .CBuffer; #through; - case .Struct; { - 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(ctx, builder, variables, type_variable); - append(builder, "\n"); - // print_to_builder(builder, "%\n", type_variable.typename); - } else { - pretty_print_struct(*scope_stack, current_scope, variables, builder, key, type_variable, 1); - } - } - case; { - indent(builder, indentation + 1); - print_key(*scope_stack, current_scope, builder, key); - print_to_builder(builder, "%\n", type_to_string(type_variable)); - } } } } else { @@ -2390,32 +2440,35 @@ pretty_print_scope :: (ctx : *Compiler_Context, current_scope : Scope_Handle, sc case .Function; { pretty_print_function(*scope_stack, current_scope, variables, builder, key, type_variable, 1); } - case .CBuffer; #through; + case .CBuffer; { + pretty_print_struct(ctx, *scope_stack, current_scope, variables, builder, key, type_variable, 1); + append(builder, "\n"); + } case .Struct; { - if type_variable.typename.count > 0 && type_variable.source_kind != .Declaration { + if type_variable.typename.count > 0 && !type_variable.builtin && (type_variable.source_kind != .Declaration || type_variable.source_node.kind != .Struct) { indent(builder, indentation + 1); print_key(*scope_stack, current_scope, builder, key); print_to_builder(builder, "%\n", type_variable.typename); } else { - pretty_print_struct(*scope_stack, current_scope, variables, builder, key, type_variable, 1); + pretty_print_struct(ctx, *scope_stack, current_scope, variables, builder, key, type_variable, indentation); + append(builder, "\n"); } } case; { indent(builder, indentation + 1); print_key(*scope_stack, current_scope, builder, key); - print_to_builder(builder, "%\n", type_to_string(type_variable)); + print_to_builder(builder, "%\n", type_to_string(variables, type_variable)); } } } - } - + for child : scope.children { child_scope := *scope_stack.stack[child - 1]; pretty_print_scope(ctx, current_scope, *scope_stack, variables, child_scope, builder, indentation + 1); } - if scope.table.count > 0 { + if (scope.table.count > 0 || scope.children.count > 0) { indent(builder, indentation); } append(builder, "]\n"); @@ -2424,7 +2477,7 @@ pretty_print_scope :: (ctx : *Compiler_Context, current_scope : Scope_Handle, sc 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)); + print_to_builder(builder, "%", type_to_string(variables, variable)); } else { print_to_builder(builder, "%", variable.name); } diff --git a/Codegen.jai b/Codegen.jai index 1f22e0b..8ba13f8 100644 --- a/Codegen.jai +++ b/Codegen.jai @@ -22,7 +22,7 @@ Codegen_State :: struct { builder : String_Builder; - result : *Compiler_Context; + ctx : *Compiler_Context; } Reserved_HLSL_Words :: string.[ @@ -44,7 +44,7 @@ Reserved_GLSL_Words :: string.[ "" ]; -init_codegen_state :: (state : *Codegen_State, result : *Compiler_Context, output_language : Output_Language) { +init_codegen_state :: (state : *Codegen_State, ctx : *Compiler_Context, output_language : Output_Language) { state.current_scope = cast(Scope_Handle)1; state.output_language = output_language; init_string_builder(*state.builder); @@ -54,7 +54,11 @@ indent :: (state : *Codegen_State, indentation : int) { for 1..indentation append(*state.builder, " "); } -hlsl_type_to_string :: (type_variable : Type_Variable) -> string { +hlsl_type_to_string :: (variables : []Type_Variable, type_handle : Type_Variable_Handle) -> string { + return hlsl_type_to_string(variables, from_handle(variables, type_handle)); +} + +hlsl_type_to_string :: (variables : []Type_Variable, type_variable : Type_Variable) -> string { if type_variable.type == { case .Invalid; return "{{invalid}}"; @@ -83,20 +87,20 @@ hlsl_type_to_string :: (type_variable : Type_Variable) -> string { return type_variable.typename; } case .Array; - return "array"; + return hlsl_type_to_string(variables, type_variable.element_type); } return ""; } emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) { - find_result := find_symbol(state.result.scope_stack, node.name, state.current_scope); + find_result := find_symbol(state.ctx.scope_stack, node.name, state.current_scope); - field := from_handle(state.result.type_variables, find_result.type_variable); + field := from_handle(state.ctx.type_variables, find_result.type_variable); indent(state, indentation); - print_to_builder(*state.builder, "% ", hlsl_type_to_string(field)); + print_to_builder(*state.builder, "% ", hlsl_type_to_string(state.ctx.type_variables, field)); print_to_builder(*state.builder, "%", node.name); @@ -111,8 +115,14 @@ emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) { if node.children.count == 1 { child := node.children[0]; - print_to_builder(*state.builder, " = "); - emit_node(state, child, 0); + if field.type == .Array { + append(*state.builder, "["); + emit_node(state, child, 0); + append(*state.builder, "]"); + } else { + print_to_builder(*state.builder, " = "); + emit_node(state, child, 0); + } } if node.parent.kind == .Block { @@ -120,7 +130,7 @@ emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) { } for i :0..field.children.count - 1 { - child := from_handle(state.result.type_variables, field.children[i]); + child := from_handle(state.ctx.type_variables, field.children[i]); emit_node(state, child.source_node, 0); } @@ -206,7 +216,7 @@ emit_call :: (state : *Codegen_State, node : *AST_Node, indentation : int) { emit_function :: (state : *Codegen_State, node : *AST_Node, indentation : int, emit_body := true) { name := get_actual_function_name(node); - find_result := find_symbol(state.result.scope_stack, name, state.current_scope); + find_result := find_symbol(state.ctx.scope_stack, name, state.current_scope); assert(find_result != null, "Attempting to generate undeclared function. This should never happen at this stage."); if !find_result { @@ -214,17 +224,17 @@ emit_function :: (state : *Codegen_State, node : *AST_Node, indentation : int, e message.message_kind = .Internal_Error; message.path = state.path; message.message = "Attempting to generate undeclared function. This should never happen at this stage."; - array_add(*state.result.messages, message); + array_add(*state.ctx.messages, message); } for func : find_result.functions { - function_variable := from_handle(state.result.type_variables, func.type_variable); + function_variable := from_handle(state.ctx.type_variables, func.type_variable); indent(state, indentation); if function_variable.return_type_variable { - return_variable := from_handle(state.result.type_variables, function_variable.return_type_variable); - print_to_builder(*state.builder, "% ", hlsl_type_to_string(return_variable)); + return_variable := from_handle(state.ctx.type_variables, function_variable.return_type_variable); + print_to_builder(*state.builder, "% ", hlsl_type_to_string(state.ctx.type_variables, return_variable)); } else { append(*state.builder, "void "); } @@ -360,7 +370,7 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) { case .Variable; { indent(*state.builder, indentation); - type_var := from_handle(state.result.type_variables, node.type_variable); + type_var := from_handle(state.ctx.type_variables, node.type_variable); print_to_builder(*state.builder, "%", node.name); @@ -372,19 +382,29 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) { case .Binary; { indent(*state.builder, indentation); - if node.token.kind != .TOKEN_ASSIGN { + if node.token.kind != .TOKEN_ASSIGN && node.token.kind != .TOKEN_LEFTBRACKET { append(*state.builder, "("); } lhs := node.children[0]; rhs := node.children[1]; - emit_node(state, lhs, 0); - append(*state.builder, " "); - emit_operator(state, node.token.kind); - append(*state.builder, " "); - emit_node(state, rhs, 0); - if node.token.kind != .TOKEN_ASSIGN { + if node.token.kind == .TOKEN_LEFTBRACKET { + emit_node(state, lhs, 0); + append(*state.builder, "["); + emit_node(state, rhs, 0); + append(*state.builder, "]"); + } else { + emit_node(state, lhs, 0); + append(*state.builder, " "); + emit_operator(state, node.token.kind); + append(*state.builder, " "); + emit_node(state, rhs, 0); + } + + + + if node.token.kind != .TOKEN_ASSIGN && node.token.kind != .TOKEN_LEFTBRACKET { append(*state.builder, ")"); } } @@ -486,7 +506,7 @@ emit_struct :: (state : *Codegen_State, node : *AST_Node, indentation : int) { print_to_builder(*state.builder, "struct %", node.name); current_scope := state.current_scope; - state.current_scope = from_handle(state.result.type_variables, node.type_variable).scope; + state.current_scope = from_handle(state.ctx.type_variables, node.type_variable).scope; field_list := node.children[0]; @@ -503,11 +523,11 @@ emit_struct :: (state : *Codegen_State, node : *AST_Node, indentation : int) { } emit_cbuffer :: (state : *Codegen_State, node : *AST_Node, indentation : int) { - variable := from_handle(state.result.type_variables, node.type_variable); + variable := from_handle(state.ctx.type_variables, node.type_variable); print_to_builder(*state.builder, "cbuffer % : register(b%)", variable.name, variable.resource_index); current_scope := state.current_scope; - state.current_scope = from_handle(state.result.type_variables, node.type_variable).scope; + state.current_scope = from_handle(state.ctx.type_variables, node.type_variable).scope; field_list := node.children[0]; @@ -553,7 +573,7 @@ codegen :: (result : *Compiler_Context, output_language : Output_Language, alloc defer clear_context_allocators(); state : Codegen_State; - state.result = result; + state.ctx = result; state.current_scope = cast(Scope_Handle)1; state.output_language = output_language; init_string_builder(*state.builder); @@ -567,7 +587,7 @@ codegen :: (state : *Codegen_State) { found_function : bool = false; // found_struct : bool = false; - // for variable : state.result.type_variables { + // for variable : state.ctx.type_variables { // if variable.type == .Struct && variable.kind == .Declaration && !variable.builtin { // if variable.source_node.kind == .Properties continue; // if variable.source_node.kind == .Meta continue; @@ -580,7 +600,7 @@ codegen :: (state : *Codegen_State) { // append(*state.builder, "\n"); // } - for variable : state.result.type_variables { + for variable : state.ctx.type_variables { if variable.type == .Function && !variable.builtin && !variable.source_node.vertex_entry_point && !variable.source_node.pixel_entry_point { emit_function(state, variable.source_node, 0, false); @@ -591,14 +611,14 @@ codegen :: (state : *Codegen_State) { append(*state.builder, "\n"); } - for declaration : state.result.root.children { + for declaration : state.ctx.root.children { if declaration.foreign_declaration { continue; } emit_declaration(state, declaration); } - state.result.codegen_result_text = builder_to_string(*state.builder); + state.ctx.codegen_result_text = builder_to_string(*state.builder); } #scope_module diff --git a/Lexing.jai b/Lexing.jai index 20b62bf..b4669e3 100644 --- a/Lexing.jai +++ b/Lexing.jai @@ -92,6 +92,7 @@ Token_Kind :: enum { TOKEN_OUT; TOKEN_PIXEL; + TOKEN_PLEX; TOKEN_RETURN; TOKEN_REGISTER; @@ -247,6 +248,7 @@ identifier_kind :: (using lexer : *Lexer) -> Token_Kind { if identifier == "return" return .TOKEN_RETURN; if identifier == "register" return .TOKEN_REGISTER; if identifier == "struct" return .TOKEN_STRUCT; + if identifier == "plex" return .TOKEN_STRUCT; if identifier == "switch" return .TOKEN_SWITCH; if identifier == "true" return .TOKEN_TRUE; if identifier == "unorm" return .TOKEN_UNORM; @@ -758,35 +760,31 @@ print_from_source_location :: (ctx : *Compiler_Context, builder : *String_Builde text.count = tok.length; print_to_builder(builder, "%", text); } - return; } else { + begin_pos := 0; + token_string : string; + count := end.index - begin.index + end.length; - } - + if indentation > 0 { + indent(builder, indentation); + for 0..count - 1 { + c := begin.source[it]; + if c == #char "\n" { + append(builder, "\n"); + indent(builder, indentation); + } else { + s : string; + s.count = 1; + s.data = *c; + print_to_builder(builder, "%", s); + } - begin_pos := 0; - token_string : string; - count := end.index - begin.index + end.length; - - if indentation > 0 { - indent(builder, indentation); - for 0..count - 1 { - c := begin.source[it]; - if c == #char "\n" { - append(builder, "\n"); - indent(builder, indentation); - } else { - s : string; - s.count = 1; - s.data = *c; - print_to_builder(builder, "%", s); } - + } else { + token_string = .{ count = count, data = begin.source }; + indent(builder, indentation); + print_to_builder(builder, "%", token_string); } - } else { - token_string = .{ count = count, data = begin.source }; - indent(builder, indentation); - print_to_builder(builder, "%", token_string); } } diff --git a/Parsing.jai b/Parsing.jai index e2124ca..8e09a92 100644 --- a/Parsing.jai +++ b/Parsing.jai @@ -1368,8 +1368,35 @@ function_declaration :: (parse_state : *Parse_State, identifier_token : *Token, } buffer :: (state : *Parse_State, identifier_token : *Token = null) -> *AST_Node { - internal_error_message(*state.ctx.messages, "Buffers are not yet implemented in the language.", state.ctx.file.path); - return null; + node : *AST_Node = make_node(state, .Buffer); + source_location : Source_Range; + source_location.begin = state.current; + + if check(state, .TOKEN_AT) { + while check(state, .TOKEN_AT) { + advance(state); + // @Incomplete(niels): this is a mapping + if check(state, .TOKEN_IDENTIFIER) { + array_add(*node.hint_tokens, state.current); + advance(state); + } + } + } + + consume(state, .TOKEN_LEFTBRACE, "Expect '{' after 'buffer' keyword"); + buffer := field_list(state, .Semicolon); + node.array_field = true; + + if identifier_token { + node.name = identifier_token.ident_value; + } + add_child(node, buffer); + + consume(state, .TOKEN_RIGHTBRACE, "Expect '}' after 'buffer' block"); + source_location.end = state.previous; + node.source_location = source_location; + + return node; } constant_buffer :: (parse_state : *Parse_State, identifier_token : *Token = null) -> *AST_Node { @@ -1484,7 +1511,7 @@ declaration :: (parse_state : *Parse_State) -> *AST_Node { error := error_node(parse_state, tprint("Expected a declaration or function call. '%' not allowed as a declaration name.", parse_state.current.kind)); advance(parse_state); decl_node = error; - } + } if !decl_node && !skip_statement { decl_node = statement(parse_state); diff --git a/module.jai b/module.jai index ee699fa..db89a1f 100644 --- a/module.jai +++ b/module.jai @@ -150,6 +150,7 @@ Compiler_Context :: struct { codegen_result_text : string; constant_buffers : Static_Array(Type_Variable_Handle, 16); + buffers : Static_Array(Type_Variable_Handle, 16); scope_stack : Scope_Stack; type_variables : [..]Type_Variable; @@ -316,11 +317,7 @@ pretty_print_field :: (builder : *String_Builder, field : *Field) { } } -type_variable_to_field :: (checker : *Checker, variable : Type_Variable_Handle) -> Field { - return type_variable_to_field(checker, from_handle(checker, variable)); -} - -type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope_Stack, variable : *Type_Variable) -> Field { +type_variable_to_field :: (ctx : *Compiler_Context, variable : *Type_Variable) -> Field { field : Field; field.name = variable.name; @@ -353,14 +350,14 @@ type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope case .Struct; { type.kind = Field_Kind.Struct; - find_result := find_symbol(scope_stack, variable.typename, xx 1); + find_result := find_symbol(ctx.scope_stack, variable.typename, xx 1); assert(find_result != null, "Internal compiler error\n"); - type_var := from_handle(type_variables, find_result.type_variable); + type_var := from_handle(ctx.type_variables, find_result.type_variable); for i : 0..type_var.children.count - 1 { child := type_var.children[i]; - child_field := type_variable_to_field(type_variables, scope_stack, child); + child_field := type_variable_to_field(ctx, child); array_add(*type.children, child_field); } @@ -397,12 +394,8 @@ type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope return field; } -type_variable_to_field :: (type_variables : []Type_Variable, scope_stack : Scope_Stack, variable : Type_Variable_Handle) -> Field { - return type_variable_to_field(type_variables, scope_stack, from_handle(type_variables, variable)); -} - -type_variable_to_field :: (checker : *Checker, variable : *Type_Variable) -> Field { - return type_variable_to_field(checker.ctx.type_variables, checker.ctx.scope_stack, variable); +type_variable_to_field :: (ctx : *Compiler_Context, variable : Type_Variable_Handle) -> Field { + return type_variable_to_field(ctx, from_handle(ctx.type_variables, variable)); } generate_output_data :: (ctx : *Compiler_Context) { @@ -422,7 +415,7 @@ generate_output_data :: (ctx : *Compiler_Context) { field_list := node.children[0]; for child : field_list.children { tv := from_handle(ctx.type_variables, child.type_variable); - field := type_variable_to_field(ctx.type_variables, ctx.scope_stack, tv); + field := type_variable_to_field(ctx, tv); array_add(*ctx.vertex_entry_point.input, field); } } @@ -437,7 +430,7 @@ generate_output_data :: (ctx : *Compiler_Context) { for i : 0..variable.children.count - 1 { child := variable.children[i]; - field : Field = type_variable_to_field(ctx.type_variables, ctx.scope_stack, from_handle(ctx.type_variables, child)); + field : Field = type_variable_to_field(ctx, from_handle(ctx.type_variables, child)); array_add(*cb.fields, field); } @@ -458,7 +451,7 @@ generate_output_data :: (ctx : *Compiler_Context) { assert(type_variable.type == .Function); if type_variable.return_type_variable > 0 { - field := type_variable_to_field(ctx.type_variables, ctx.scope_stack, type_variable.return_type_variable); + field := type_variable_to_field(ctx, type_variable.return_type_variable); for hint : type_variable.source_node.hint_tokens { field_hint : Field_Hint; diff --git a/test/buffers.ink b/test/buffers.ink new file mode 100644 index 0000000..284777d --- /dev/null +++ b/test/buffers.ink @@ -0,0 +1,11 @@ +property_buffer :: buffer { + color : float4; +} + +cbuffer :: constant_buffer { + color : float4; +} + +pixel main :: (index : int) { + return property_buffer[index].color; +} diff --git a/test/check/empty_struct.golden b/test/check/empty_struct.golden index 883a0b6..2886129 100644 --- a/test/check/empty_struct.golden +++ b/test/check/empty_struct.golden @@ -1,4 +1,4 @@ scope (global) [ - [Foo] : {} +[Foo] : {} scope (Foo) [] ] diff --git a/test/check/for_i_loop.golden b/test/check/for_i_loop.golden index 47663f8..51a5d76 100644 --- a/test/check/for_i_loop.golden +++ b/test/check/for_i_loop.golden @@ -1,7 +1,10 @@ scope (global) [ [vertex__vs_main] : () scope (vertex__vs_main) [ - [i] : int [x] : int + scope (block) [ + [i] : int + scope (block) [] + ] ] ] diff --git a/test/check/if_def_block.golden b/test/check/if_def_block.golden index 8002469..9dd53c6 100644 --- a/test/check/if_def_block.golden +++ b/test/check/if_def_block.golden @@ -1,7 +1,8 @@ scope (global) [ [pixel__ps_main] : () - scope (pixel__ps_main) [ - [alpha_color] : float4 - [f] : float + scope (pixel__ps_main) [ scope (block) [ + [alpha_color] : float4 + [f] : float + ] ] ] diff --git a/test/check/nested_if.golden b/test/check/nested_if.golden index 7d9b85d..a4ed3c6 100644 --- a/test/check/nested_if.golden +++ b/test/check/nested_if.golden @@ -2,5 +2,8 @@ scope (global) [ [vertex__vs_main] : (pos : float3) -> float4 scope (vertex__vs_main) [ [pos] : float3 + scope (block) [ scope (block) [] + scope (block) [] + ] ] ] diff --git a/test/check/pass_and_access_struct_fields_in_functions.golden b/test/check/pass_and_access_struct_fields_in_functions.golden index a048c59..27a0920 100644 --- a/test/check/pass_and_access_struct_fields_in_functions.golden +++ b/test/check/pass_and_access_struct_fields_in_functions.golden @@ -1,7 +1,7 @@ scope (global) [ [foo] : (f : Foo) -> float [vertex__vs_main] : () - [Foo] : {some_data : float} +[Foo] : {some_data : float} scope (Foo) [ [some_data] : float ] diff --git a/test/check/simple_else_if.golden b/test/check/simple_else_if.golden index 7d9b85d..d73d2fa 100644 --- a/test/check/simple_else_if.golden +++ b/test/check/simple_else_if.golden @@ -2,5 +2,8 @@ scope (global) [ [vertex__vs_main] : (pos : float3) -> float4 scope (vertex__vs_main) [ [pos] : float3 + scope (block) [] + scope (block) [] + scope (block) [] ] ] diff --git a/test/check/simple_if.golden b/test/check/simple_if.golden index 7d9b85d..a368773 100644 --- a/test/check/simple_if.golden +++ b/test/check/simple_if.golden @@ -2,5 +2,6 @@ scope (global) [ [vertex__vs_main] : (pos : float3) -> float4 scope (vertex__vs_main) [ [pos] : float3 + scope (block) [] ] ] diff --git a/test/check/simple_if_else.golden b/test/check/simple_if_else.golden index 7d9b85d..04e1bf1 100644 --- a/test/check/simple_if_else.golden +++ b/test/check/simple_if_else.golden @@ -2,5 +2,7 @@ scope (global) [ [vertex__vs_main] : (pos : float3) -> float4 scope (vertex__vs_main) [ [pos] : float3 + scope (block) [] + scope (block) [] ] ] diff --git a/test/check/simple_struct_access.golden b/test/check/simple_struct_access.golden index 41a65bd..a2fbc11 100644 --- a/test/check/simple_struct_access.golden +++ b/test/check/simple_struct_access.golden @@ -1,5 +1,5 @@ scope (global) [ - [Data] : {color : float4} +[Data] : {color : float4} [vertex__vs_main] : () scope (Data) [ [color] : float4 diff --git a/test/check/struct_within_struct.golden b/test/check/struct_within_struct.golden index c7339f0..47164d1 100644 --- a/test/check/struct_within_struct.golden +++ b/test/check/struct_within_struct.golden @@ -1,7 +1,7 @@ scope (global) [ - [Bar] : {t : Foo} +[Bar] : {t : Foo} [vertex__vs_main] : () - [Foo] : {color : float4} +[Foo] : {color : float4} scope (Foo) [ [color] : float4 ] diff --git a/test/codegen/arrays.golden b/test/codegen/arrays.golden new file mode 100644 index 0000000..5347981 --- /dev/null +++ b/test/codegen/arrays.golden @@ -0,0 +1,6 @@ +float4 vs_main() : SV_POSITION +{ + float4 arr[16]; + return arr[0]; +} +