Compare commits

10 Commits

66 changed files with 956 additions and 400 deletions

49
AST.jai
View File

@@ -12,14 +12,13 @@ AST_Kind :: enum {
// Directives
If_Directive;
// Hint;
// Type;
// Operator;
Access;
Call;
Struct;
If;
For;
CBuffer;
Buffer;
FieldList;
ArgList;
Variable;
@@ -256,16 +255,35 @@ pretty_print_binary :: (node : *AST_Node, indentation : int, builder : *String_B
if !skip_indent {
indent(builder, indentation);
}
append(builder, "(");
op := node.token;
print_to_builder(builder, op_to_string(op));
append(builder, " ");
if node.token.kind == .TOKEN_LEFTBRACKET {
pretty_print_node(node.children[0], 0, builder);
append(builder, "[");
pretty_print_node(node.children[1], 0, builder);
append(builder, "]");
} else {
append(builder, "(");
op := node.token;
print_to_builder(builder, op_to_string(op));
append(builder, " ");
pretty_print_node(node.children[0], 0, builder);
append(builder, " ");
pretty_print_node(node.children[1], 0, builder);
append(builder, ")");
}
}
pretty_print_access :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) {
if !skip_indent {
indent(builder, indentation);
}
pretty_print_node(node.children[0], 0, builder);
append(builder, " ");
append(builder, ".");
pretty_print_node(node.children[1], 0, builder);
append(builder, ")");
}
pretty_print_unary :: (node : *AST_Node, indentation : int, builder : *String_Builder, skip_indent := false) {
@@ -396,6 +414,9 @@ pretty_print_node :: (node : *AST_Node, indentation : int, builder : *String_Bui
case .Binary; {
pretty_print_binary(node, indentation, builder, skip_indent);
}
case .Access; {
pretty_print_access(node, indentation, builder, skip_indent);
}
case .Unary; {
pretty_print_unary(node, indentation, builder, skip_indent);
}
@@ -468,18 +489,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{

407
Check.jai
View File

@@ -5,7 +5,11 @@
/////////////////////////////////////
//~ nbr: Error reporting TODOs
//
// [ ] 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
// [ ] 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.
// [x] Improve error reporting for type mismatches in general. It seems like the expect node is not always correct.
@@ -35,14 +39,14 @@ Type_Kind :: enum {
Unresolved_Expression;
Struct;
Properties;
CBuffer;
Buffer;
Array;
}
Source_Kind :: enum {
Expression;
Declaration; // struct, properties, function, etc.
Declaration; // struct, cbuffers, function, etc.
}
Typenames :: string.[
@@ -65,6 +69,8 @@ Type_Variable :: struct {
name : string;
//@Note(niels) For functions
return_type_variable : Type_Variable_Handle;
@@ -75,11 +81,16 @@ Type_Variable :: struct {
struct_field_parent : *AST_Node;
typename : string;
is_array : bool;
element_type : Type_Variable_Handle;
element_count : int;
MAX_TYPE_VARIABLE_CHILDREN :: 32;
children : Static_Array(Type_Variable_Handle, MAX_TYPE_VARIABLE_CHILDREN);
//@Incomplete: Should we remove this and do it in the output generation instead?
// Seems kind of superfluous considering we auto-generate it.
// Otherwise if we want to specify it, it should be specified as a hint @binding(index)
// In the case of using hints, we can just have it on the AST node.
//@Note(niels): For constant buffers
resource_index : u32;
@@ -108,7 +119,7 @@ Scope_Kind :: enum {
Global;
Function;
Struct;
Properties;
Block;
}
Scope :: struct {
@@ -145,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;
@@ -409,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 '%'.
@@ -463,12 +513,10 @@ Attempting to access a field on a primitive type '%'.
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);
for 0..node.name.count - 1 {
append(*builder, " ");
}
print_token_pointer(*builder, node.source_location.begin);
// for 0..variable.source_node.name.count - 1 {
// append(*builder, " ");
// }
print_token_pointer(*builder, node.source_location.main_token);
append(*builder, "\n");
@@ -539,11 +587,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 +861,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;
}
@@ -834,10 +891,6 @@ add_child :: (checker : *Checker, handle : Type_Variable_Handle, child : Type_Va
}
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;
checker.program_root = root;
checker.path = path;
@@ -915,7 +968,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);
@@ -959,7 +1011,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;
@@ -969,9 +1021,12 @@ lookup_type :: (checker : *Checker, scope : Scope_Handle, type_string : string,
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;
@@ -985,15 +1040,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,10 +1110,46 @@ 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;
}
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.source_node = node;
find_result := find_symbol(checker, node.name, checker.current_scope);
if !find_result {
symbol : Defined_Symbol;
symbol.name = node.name;
symbol.source_node = node;
symbol.type_variable = handle;
add_symbol_to_scope(checker.state, *checker.ctx.scope_stack, checker.current_scope, node.name, symbol);
} else {
symbol_redeclaration(checker, node, find_result);
return 0;
}
buffer_struct_name := sprint("__buffer_substruct__%_%", random_get(), node.name);
variable.element_type = declare_struct(checker, node, buffer_struct_name);
variable.resource_index = checker.current_texture_index;
element := from_handle(checker, variable.element_type);
scope := get_scope(checker, element.scope);
scope.builtin = true;
variable.scope = element.scope;
checker.current_texture_index += 1;
node.type_variable = handle;
array_add(*checker.ctx.typed_buffers, handle);
return handle;
}
get_actual_function_name :: (node : *AST_Node) -> string {
name_to_check := node.name;
if node.vertex_entry_point {
@@ -1103,7 +1200,7 @@ declare_function :: (checker : *Checker, node : *AST_Node, builtin : bool = fals
symbol.source_node = node;
symbol.type_variable = 0;
symbol.functions.allocator = get_current_scope(checker).allocator;
array_reserve(*symbol.functions, 32);
array_reserve(*symbol.functions, 4);
array_add(*symbol.functions, function);
add_symbol_to_scope(checker.state, *checker.ctx.scope_stack, checker.current_scope, name_to_check, symbol);
@@ -1166,7 +1263,8 @@ declare_function :: (checker : *Checker, node : *AST_Node, builtin : bool = fals
variable.scope = scope_handle;
}
for child : node.children {
for i : 0..node.children.count - 1 {
child := node.children[i];
if child.kind == .FieldList {
for field : child.children {
type_var := check_node(checker, field);
@@ -1245,44 +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 != .Properties && variable.type != .CBuffer {
field_access_on_primitive_type(checker, node, find_result.type_variable);
return 0;
} else {
lookup_name : string = variable.typename;
if variable.typename == "properties" {
lookup_name = variable.name;
}
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;
}
@@ -1307,11 +1374,20 @@ check_field :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
variable, handle := new_type_variable(checker);
variable.name = node.name;
typename : string;
variable.type = lookup_type(checker, checker.current_scope, node, *typename);
variable.is_array = node.array_field;
if node.array_field {
variable.type = .Array;
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;
if variable.is_array {
variable.element_type = element_handle;
variable.element_count = node.children[0].integer_value;
} else {
variable.type = lookup_type(checker, checker.current_scope, node, *typename);
}
if variable.type == .Array {
size_node := node.children[0];
size_var := check_node(checker, size_node);
if from_handle(checker, size_var).type != .Int {
@@ -1319,16 +1395,6 @@ check_field :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
}
}
if variable.source_kind == .Declaration && variable.type == .Sampler {
variable.resource_index = checker.current_sampler_index;
checker.current_sampler_index += 1;
}
if variable.source_kind == .Declaration && variable.type == .Texture2D {
variable.resource_index = checker.current_texture_index;
checker.current_texture_index += 1;
}
variable.typename = typename;
variable.source_node = node;
variable.scope = checker.current_scope;
@@ -1348,20 +1414,33 @@ check_field :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
symbol.source_node = node;
symbol.type_variable = handle;
add_symbol_to_scope(checker.state, *checker.ctx.scope_stack, checker.current_scope, node.name, symbol);
variable.source_kind = .Declaration;
} else {
symbol_redeclaration(checker, node, find_result);
return 0;
}
}
if node.token.ident_value.count > 0 {
variable.type = lookup_type(checker, checker.current_scope, node);
if variable.source_kind == .Declaration && variable.type == .Sampler {
variable.resource_index = checker.current_sampler_index;
checker.current_sampler_index += 1;
}
if node.children.count > 0 {
if variable.source_kind == .Declaration && variable.type == .Texture2D {
variable.resource_index = checker.current_texture_index;
checker.current_texture_index += 1;
}
if variable.type != .Array && node.children.count > 0 || variable.type == .Array && node.children.count > 1 {
rhs : Type_Variable_Handle;
assert(node.children.count == 1);
for child : node.children {
start_index := 0;
if variable.type == .Array {
start_index += 1;
}
for i : start_index..node.children.count - 1 {
child := node.children[i];
rhs = check_node(checker, child);
}
@@ -1526,8 +1605,46 @@ check_node :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
return handle;
}
case .Access; {
lhs_handle := check_node(checker, node.children[0]);
if lhs_handle == 0 {
return 0;
}
lhs_variable := from_handle(checker, lhs_handle);
if lhs_variable.type != .Struct && lhs_variable.type != .CBuffer {
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);
previous_scope := use_scope(checker, type_variable.scope);
member := node.children[1];
var := find_symbol(checker, member.name, type_variable.scope);
if var == null {
field_not_defined_on_struct(checker, member, struct_symbol);
return 0;
}
access := check_node(checker, member);
use_scope(checker, previous_scope);
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;
}
@@ -1540,7 +1657,14 @@ check_node :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
lhs_type := from_handle(checker, lhs_var);
rhs_type := from_handle(checker, rhs_var);
variable.type = lhs_type.type;
if lhs_type.type == .Array {
element := from_handle(checker, lhs_type.element_type);
variable.type = element.type;
variable.typename = element.typename;
} else {
variable.type = lhs_type.type;
}
variable.typename = lhs_type.typename;
variable.scope = lhs_type.scope;
variable.source_node = node;
@@ -1549,6 +1673,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;
@@ -1569,9 +1698,16 @@ check_node :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
}
}
case .TOKEN_ASSIGN; {
if !types_compatible(checker, lhs_var, rhs_var) {
type_mismatch(checker, node.parent, node.children[1], lhs_var, rhs_var);
return 0;
if lhs_type.type == .Array {
if !types_compatible(checker, lhs_type.element_type, rhs_var) {
type_mismatch(checker, node.parent, node.children[1], lhs_var, rhs_var);
return 0;
}
} else {
if !types_compatible(checker, lhs_var, rhs_var) {
type_mismatch(checker, node.parent, node.children[1], lhs_var, rhs_var);
return 0;
}
}
}
case .TOKEN_GREATER; #through;
@@ -1593,11 +1729,15 @@ check_node :: (checker : *Checker, node : *AST_Node) -> Type_Variable_Handle {
}
case .For; {
loop_iterator := node.token;
// @Incomplete: Missing scope here?
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;
@@ -1617,6 +1757,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]);
@@ -1689,7 +1830,17 @@ is_valid_define :: (checker : *Checker, def : string) -> bool {
}
check_env_expression :: (checker : *Checker, expr : *AST_Node, directive : *AST_Node) -> bool {
if expr.kind == .Binary {
if expr.kind == .Access {
lhs := expr.children[0];
if lhs.kind == .Variable && lhs.name == "Env" {
rhs := expr.children[1];
return is_valid_define(checker, rhs.name);
} else {
return check_env_expression(checker, lhs, directive);
}
}
else if expr.kind == .Binary {
lhs := expr.children[0];
rhs := expr.children[1];
@@ -1702,6 +1853,7 @@ check_env_expression :: (checker : *Checker, expr : *AST_Node, directive : *AST_
return lhs_valid && rhs_valid;
}
} else if expr.kind == .Variable {
assert(false, "");
if expr.name == "Env" {
child := expr.children[0]; // The variable in the environment
@@ -1770,6 +1922,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);
}
}
@@ -1824,8 +1978,6 @@ types_compatible :: (checker : *Checker, lhs : Type_Variable_Handle, rhs : Type_
return rhs_var.type == lhs_var.type;
}
case .Struct; {
lhs_node := lhs_var.source_node;
rhs_node := rhs_var.source_node;
if rhs_var.type != .Struct && !param_matching {
if lhs_var.typename == {
case "float2"; #through;
@@ -2219,9 +2371,6 @@ check :: (ctx : *Compiler_Context, allocator : Allocator = temp) {
checker : Checker;
checker.current_buffer_index = 0;
checker.current_sampler_index = 0;
checker.current_texture_index = 0;
checker.ctx = ctx;
init_semantic_checker(*checker, ctx.root, ctx.file.path);
@@ -2241,8 +2390,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}}";
@@ -2260,8 +2408,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 "";
}
@@ -2294,7 +2444,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);
@@ -2308,30 +2458,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) {
@@ -2346,7 +2501,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 {
@@ -2364,24 +2532,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 .Properties; #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,25 +2540,34 @@ 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 .Properties; #through;
case .CBuffer; {
pretty_print_struct(ctx, *scope_stack, current_scope, variables, builder, key, type_variable, 1);
append(builder, "\n");
}
case .Buffer; {
element := from_handle(variables, type_variable.element_type);
pretty_print_struct(ctx, *scope_stack, current_scope, variables, builder, key, element, 1);
append(builder, "\n");
}
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_to_builder(builder, "%\n", type_variable.typename);
} else {
pretty_print_struct(*scope_stack, current_scope, variables, builder, key, type_variable, 1);
if type_variable.source_node.kind != .Buffer {
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(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 {
@@ -2416,7 +2575,7 @@ pretty_print_scope :: (ctx : *Compiler_Context, current_scope : Scope_Handle, sc
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");
@@ -2425,7 +2584,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);
}
@@ -2442,6 +2601,9 @@ print_type_variable :: (ctx : *Compiler_Context, builder : *String_Builder, vari
}
print_to_builder(builder, "%", node.name);
}
case .Access; {
}
case .Binary; {
left_most := node.children[0];
@@ -2523,3 +2685,4 @@ pretty_print_symbol_table :: (ctx : *Compiler_Context, allocator : Allocator) ->
#import "ncore";
#import "Hash_Table";
#import "String";
#import "Random";

View File

@@ -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);
}
@@ -136,13 +146,20 @@ emit_field :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
}
emit_block :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
previous_scope := state.current_scope;
for statement : node.children {
if statement.type_variable {
state.current_scope = from_handle(state.ctx.type_variables, statement.type_variable).scope;
}
emit_node(state, statement, indentation);
if it_index < node.children.count {
append(*state.builder, "\n");
}
}
state.current_scope = previous_scope;
}
emit_call :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
@@ -206,7 +223,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 +231,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 +377,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);
@@ -369,23 +386,46 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
emit_node(state, node.children[0], 0);
}
}
case .Access; {
indent(*state.builder, indentation);
lhs := node.children[0];
rhs := node.children[1];
emit_node(state, lhs, 0);
print_to_builder(*state.builder, "%.", node.name);
emit_node(state, rhs, 0);
}
case .Binary; {
indent(*state.builder, indentation);
if node.token.kind != .TOKEN_ASSIGN {
append(*state.builder, "(");
if node.token.kind != .TOKEN_ASSIGN && node.token.kind != .TOKEN_LEFTBRACKET {
if (node.parent.kind == .Binary && node.parent.token.kind != .TOKEN_ASSIGN) || node.parent.kind == .Access {
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 {
append(*state.builder, ")");
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 {
if (node.parent.kind == .Binary && node.parent.token.kind != .TOKEN_ASSIGN) || node.parent.kind == .Access {
append(*state.builder, ")");
}
}
}
case .Unary; {
@@ -435,7 +475,9 @@ emit_node :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
append(*state.builder, "if ");
cond := node.children[0];
append(*state.builder, "(");
emit_node(state, cond, 0);
append(*state.builder, ")");
body := node.children[1];
append(*state.builder, "\n");
@@ -482,11 +524,16 @@ emit_field_list :: (state : *Codegen_State, field_list : *AST_Node, indentation
}
}
emit_struct :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
print_to_builder(*state.builder, "struct %", node.name);
emit_struct :: (state : *Codegen_State, node : *AST_Node, indentation : int, name : string = "") {
if name.count > 0 {
print_to_builder(*state.builder, "struct %", name);
} else {
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 +550,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];
@@ -523,6 +570,15 @@ emit_cbuffer :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
state.current_scope = current_scope;
}
emit_buffer :: (state : *Codegen_State, node : *AST_Node, indentation : int) {
variable := from_handle(state.ctx.type_variables, node.type_variable);
element := from_handle(state.ctx.type_variables, variable.element_type);
emit_struct(state, node, indentation, element.typename);
print_to_builder(*state.builder, "StructuredBuffer<%> % : register(t%);\n\n", element.typename, variable.name, variable.resource_index);
}
emit_declaration :: (state : *Codegen_State, node : *AST_Node) {
if node.kind == {
case .Function; {
@@ -531,6 +587,9 @@ emit_declaration :: (state : *Codegen_State, node : *AST_Node) {
case .CBuffer; {
emit_cbuffer(state, node, 0);
}
case .Buffer; {
emit_buffer(state, node, 0);
}
case .Struct; {
emit_struct(state, node, 0);
}
@@ -553,7 +612,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 +626,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 +639,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 +650,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

47
Ink.jai
View File

@@ -227,40 +227,33 @@ run_compile_test :: (path : string, output_type : Output_Type = 0) -> Result, Co
print_to_builder(*sb, "[pixel entry point] - %\n", ctx.pixel_entry_point.name);
}
if ctx.properties.fields.count > 0{
for buf : ctx.buffers {
if buf.kind == {
case .Constant; {
print_to_builder(*sb, "[constant_buffer] - % - %", buf.name, buf.buffer_index);
props := ctx.properties;
append(*sb, "[");
if ctx.property_name.count > 0 {
print_to_builder(*sb, "% :: ", ctx.property_name);
}
print_to_builder(*sb, "properties] - %\n", props.buffer_index);
}
case .Structured; {
print_to_builder(*sb, "[buffer] - % - %", buf.name, buf.buffer_index);
}
indent(*sb, 1);
for field : props.fields {
append(*sb, "[field] - ");
pretty_print_field(*sb, *field.base_field);
}
}
if buf.hints.count > 0 {
for hint : buf.hints {
print_to_builder(*sb, " (@%)", hint.custom_hint_name);
}
}
for cb : ctx.cbuffers {
print_to_builder(*sb, "[constant_buffer] - % - %", cb.name, cb.buffer_index);
append(*sb, "\n");
if cb.hints.count > 0 {
for hint : cb.hints {
print_to_builder(*sb, " (@%)", hint.custom_hint_name);
indent(*sb, 1);
for field : buf.fields {
append(*sb, "[field] - ");
pretty_print_field(*sb, *field);
append(*sb, "\n");
indent(*sb, 1);
}
}
append(*sb, "\n");
indent(*sb, 1);
for field : cb.fields {
append(*sb, "[field] - ");
pretty_print_field(*sb, *field);
append(*sb, "\n");
indent(*sb, 1);
}
}
result.info_text = builder_to_string(*sb);

View File

@@ -55,6 +55,7 @@ Token_Kind :: enum {
// Keywords
TOKEN_BOOL;
TOKEN_BUFFER;
TOKEN_CASE;
TOKEN_CBUFFER;
@@ -91,7 +92,7 @@ Token_Kind :: enum {
TOKEN_OUT;
TOKEN_PIXEL;
// TOKEN_PROPERTIES;
TOKEN_PLEX;
TOKEN_RETURN;
TOKEN_REGISTER;
@@ -216,10 +217,11 @@ identifier_kind :: (using lexer : *Lexer) -> Token_Kind {
identifier.count = length;
if identifier == "bool" return .TOKEN_BOOL;
if identifier == "Buffer" return .TOKEN_BUFFER;
if identifier == "case" return .TOKEN_CASE;
if identifier == "columnmajor" return .TOKEN_COLUMNMAJOR;
if identifier == "const" return .TOKEN_CONST;
if identifier == "constant_buffer" return .TOKEN_CONSTANT_BUFFER;
if identifier == "Constant_Buffer" return .TOKEN_CONSTANT_BUFFER;
if identifier == "continue" return .TOKEN_CONTINUE;
if identifier == "default" return .TOKEN_DEFAULT;
if identifier == "directive" return .TOKEN_DIRECTIVE;
@@ -243,10 +245,10 @@ identifier_kind :: (using lexer : *Lexer) -> Token_Kind {
if identifier == "optional" return .TOKEN_OPTIONAL;
if identifier == "out" return .TOKEN_OUT;
if identifier == "pixel" return .TOKEN_PIXEL;
// if identifier == "properties" return .TOKEN_PROPERTIES;
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);
}
}

View File

@@ -1,13 +1,3 @@
#import "Flat_Pool";
// #load "qpwodkqopwkd.jai";
/**
* TODO:
* if parsing
* for/while loop parsing
**/
////////////////////////////
//@nb - Parse_state state
Parse_State :: struct {
@@ -19,15 +9,6 @@ Parse_State :: struct {
ctx : *Compiler_Context;
}
////////////////////////////
//@nb - Result and error handling
Parse_Error_Kind :: enum {
Parse_Error_Type_Missing;
Parse_Error_Expected_Expression;
Parse_Error_Empty_Block;
Parse_Error_Unexpected_Token;
}
////////////////////////////
//@nb - Parsing helper types
Separator_Type :: enum {
@@ -727,13 +708,12 @@ array_access :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node {
identifier := parse_state.ctx.tokens[parse_state.current_token_index - 3];
left_bracket := parse_state.ctx.tokens[parse_state.current_token_index - 2];
array_access := make_node(parse_state, .Unary);
array_access := make_node(parse_state, .Binary);
array_access.token = left_bracket;
array_index := expression(parse_state);
add_child(array_access, left);
add_child(array_access, array_index);
add_child(left, array_access);
consume(parse_state, .TOKEN_RIGHTBRACKET, "Expected ']' after array index.");
source_location : Source_Range;
@@ -750,8 +730,8 @@ array_access :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node {
}
source_location.end = parse_state.previous;
left.source_location = source_location;
return left;
array_access.source_location = source_location;
return array_access;
}
unary :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node {
@@ -819,49 +799,6 @@ directive :: (state : *Parse_State) -> *AST_Node {
if_directive.source_location = source_location;
return if_directive;
} else if state.current.ident_value == "load" {
advance(state);
if check(state, .TOKEN_STRING) {
// path_tok := state.current;
// path := path_tok.string_value;
// advance(state);
// result : Compiler_Context;
// ctx.allocator = state.ctx.allocator;
// ctx.environment = state.ctx.environment;
// ctx.file = make_file(*result, path);
// if ctx.file.source.count == 0 {
// unable_to_open_file(state, path, path_tok);
// advance_to_sync_point(state);
// advance(state);
// return null;
// }
// consume(state, .TOKEN_SEMICOLON, "Expected ';' after #load directive");
// lex(*result);
// count := state.ctx.tokens..count;
// current_idx := state.current_token_index;
// result_count := ctx.tokens..count;
// // state.ctx.tokens..count -= 1;
// array_resize(*state.ctx.tokens., count + result_count - 1);
// memcpy(*state.ctx.tokens[current_idx + result_count - 1], *state.ctx.tokens[current_idx], size_of(Token) * (count - current_idx));
// for *tok : ctx.tokens. {
// if tok.kind == .TOKEN_EOF {
// break;
// }
// tok.builtin = true;
// state.ctx.tokens[it_index] = tok.*;
// }
}
}
return null;
@@ -899,34 +836,31 @@ dot :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node {
source_location : Source_Range;
source_location.begin = left.source_location.begin;
source_location.main_token = identifier;
if check_any(parse_state, .TOKEN_ASSIGN, .TOKEN_MINUSEQUALS, .TOKEN_PLUSEQUALS, .TOKEN_DIVEQUALS, .TOKEN_MODEQUALS, .TOKEN_TIMESEQUALS) {
advance(parse_state);
variable := make_node(parse_state, .Variable);
variable.source_location = generate_source_location_from_token(parse_state, identifier);
variable.name = identifier.ident_value;
access := make_node(parse_state, .Access);
add_child(left, variable);
node := make_node(parse_state, .Binary);
node.token = parse_state.previous;
add_child(node, left);
add_child(node, expression(parse_state));
return node;
}
variable := make_node(parse_state, .Variable);
variable.name = identifier.ident_value;
if check(parse_state, .TOKEN_DOT) {
add_child(access, left);
add_child(access, variable);
if check_any(parse_state, .TOKEN_ASSIGN, .TOKEN_MINUSEQUALS, .TOKEN_PLUSEQUALS, .TOKEN_DIVEQUALS, .TOKEN_MODEQUALS, .TOKEN_TIMESEQUALS) {
advance(parse_state);
dot(parse_state, variable);
access.source_location = generate_source_location_from_token(parse_state, identifier);
node := make_node(parse_state, .Binary);
node.token = parse_state.previous;
node.source_location = generate_source_location_from_token(parse_state, node.token);
add_child(node, access);
add_child(node, expression(parse_state));
return node;
}
add_child(left, variable);
source_location.end = parse_state.previous;
variable.source_location = source_location;
return left;
source_location.end = parse_state.current;
access.source_location = source_location;
return access;
}
integer :: (parse_state : *Parse_State, left : *AST_Node) -> *AST_Node {
@@ -1368,6 +1302,38 @@ function_declaration :: (parse_state : *Parse_State, identifier_token : *Token,
return node;
}
buffer :: (state : *Parse_State, identifier_token : *Token = null) -> *AST_Node {
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 {
node : *AST_Node = make_node(parse_state, .CBuffer);
source_location : Source_Range;
@@ -1430,6 +1396,8 @@ const_declaration :: (parse_state : *Parse_State, identifier_token : *Token) ->
return function_declaration(parse_state, identifier_token, .None);
} else if match(parse_state, .TOKEN_CONSTANT_BUFFER) {
return constant_buffer(parse_state, identifier_token);
} else if match(parse_state, .TOKEN_BUFFER) {
return buffer(parse_state, identifier_token);
}
return error_node(parse_state, tprint("Couldn't parse constant declaration at token %\n", parse_state.current.*));
}
@@ -1453,8 +1421,6 @@ declaration :: (parse_state : *Parse_State) -> *AST_Node {
consume(parse_state, .TOKEN_DOUBLECOLON, "Expect '::' after pixel entry point declaration.");
decl_node = function_declaration(parse_state, identifier, .Pixel);
} else if check(parse_state, .TOKEN_LEFTPAREN) {
decl_node = call(parse_state, null);
} else if check(parse_state, .TOKEN_DIRECTIVE) {
decl_node = directive(parse_state);
skip_statement = true;
@@ -1524,4 +1490,4 @@ parse :: (ctx : *Compiler_Context, allocator := temp) {
}
}
#load "AST.jai";
#load "ast.jai";

View File

@@ -13,12 +13,10 @@ build :: () {
}
EXECUTABLE_NAME :: "ink";
MAIN_FILE :: "Ink.jai";
MAIN_FILE :: "ink.jai";
options := get_build_options(w);
options.write_added_strings = true;
args := options.compile_time_command_line;
profile : bool = false;

View File

@@ -1,8 +1,8 @@
#load "Lexing.jai";
#load "Error.jai";
#load "Parsing.jai";
#load "Check.jai";
#load "Codegen.jai";
#load "lexing.jai";
#load "error.jai";
#load "parsing.jai";
#load "check.jai";
#load "codegen.jai";
#import "File_Utilities";
@@ -13,7 +13,7 @@
- [ ] Support compute shaders
- [x] Support #if at top level
- [x] Support #if at block level
- [ ] Remove properties block and just use hinted constant buffers instead
- [x] Remove properties block and just use hinted constant buffers instead
```
props :: constant_buffer @properties {
[...]
@@ -21,7 +21,13 @@
```
- [ ] while loops
- [ ] for-each loops
- [ ]
- [ ] add parameters to hints (meta properties, resource binding indices if needed)
- [ ] consider @entry(stage) syntax instead of the forced keyword
- [ ] Add flags to compiler
- [ ] Generate output flag(s)
- [ ] Possibly final stage flag, so you can just call compile_file and it only does what you need.
- Probably this flag is about which stage you need as the _last_ and not which stages to do, as that doesn't make sense.
- [ ] Multiple output languages?
*/
add_define :: (env : *Environment, key : string) {
@@ -122,7 +128,13 @@ Entry_Point :: struct {
return_value : Field;
}
Constant_Buffer :: struct {
Buffer_Kind :: enum {
Constant;
Structured;
}
Buffer :: struct {
kind : Buffer_Kind;
name : string;
fields : Static_Array(Field, 16);
@@ -148,7 +160,8 @@ Compiler_Context :: struct {
codegen_result_text : string;
constant_buffers : Static_Array(Type_Variable_Handle, 16);
typed_buffers : Static_Array(Type_Variable_Handle, 32);
// structured_buffers : Static_Array(Type_Variable_Handle, 16);
scope_stack : Scope_Stack;
type_variables : [..]Type_Variable;
@@ -165,9 +178,9 @@ Compiler_Context :: struct {
return_value : Field;
}
max_constant_buffers :: 16;
max_buffers :: 32;
cbuffers : Static_Array(Constant_Buffer, max_constant_buffers);
buffers : Static_Array(Buffer, max_buffers);
had_error : bool;
messages : [..]Compiler_Message;
@@ -315,11 +328,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;
@@ -352,14 +361,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);
}
@@ -396,12 +405,39 @@ 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 :: (ctx : *Compiler_Context, variable : Type_Variable_Handle) -> Field {
return type_variable_to_field(ctx, from_handle(ctx.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);
generate_buffer :: (ctx : *Compiler_Context, type_handle : Type_Variable_Handle, buffers : *Static_Array) {
variable := from_handle(ctx.type_variables, type_handle);
buffer := array_add(buffers);
if variable.type == {
case .CBuffer; {
buffer.kind = .Constant;
}
case .Buffer; {
buffer.kind = .Structured;
}
}
buffer.name = variable.name;
for i : 0..variable.children.count - 1 {
child := variable.children[i];
field : Field = type_variable_to_field(ctx, from_handle(ctx.type_variables, child));
array_add(*buffer.fields, field);
}
buffer.buffer_index = variable.resource_index;
for hint : variable.source_node.hint_tokens {
field_hint : Field_Hint;
field_hint.custom_hint_name = hint.ident_value;
field_hint.kind = .Custom;
array_add(*buffer.hints, field_hint);
}
}
generate_output_data :: (ctx : *Compiler_Context) {
@@ -421,33 +457,15 @@ 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);
}
}
}
}
for buffer_variable : ctx.constant_buffers {
variable := from_handle(ctx.type_variables, buffer_variable);
cb := array_add(*ctx.cbuffers);
cb.name = variable.name;
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));
array_add(*cb.fields, field);
}
cb.buffer_index = variable.resource_index;
for hint : variable.source_node.hint_tokens {
field_hint : Field_Hint;
field_hint.custom_hint_name = hint.ident_value;
field_hint.kind = .Custom;
array_add(*cb.hints, field_hint);
}
for buffer_variable : ctx.typed_buffers {
generate_buffer(ctx, buffer_variable, *ctx.buffers);
}
if ctx.pixel_entry_point.node {
@@ -457,7 +475,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;

View File

@@ -0,0 +1,4 @@
vertex main :: () {
v : float2;
v.x = (2.0 + ((4.0 - 2.0) * 1.5)) * 3.0;
}

View File

@@ -1,5 +1,6 @@
vertex main :: () -> float4 @position {
arr : [16].float4;
arr[0] = float4(1,1,1);
return arr[0];
arr[0] = float4(1, 1, 1, 1);
pos := arr[1];
return pos;
}

View File

@@ -0,0 +1,5 @@
vertex main :: () {
a : float2;
b : float2;
(a + b).x = 2.0;
}

View File

@@ -0,0 +1,10 @@
P :: struct {
v : float2;
}
vertex main :: () {
p : P;
p.v.x.y = 2.0;
// v : float2;
// v.x.y.z = 2.0;
}

View File

@@ -1,4 +1,4 @@
properties :: constant_buffer @properties {
properties :: Constant_Buffer @properties {
color : float4;
}

11
test/buffers.ink Normal file
View File

@@ -0,0 +1,11 @@
property_buffer :: Buffer {
color : float4;
}
const_buffer :: Constant_Buffer {
color : float4;
}
pixel main :: (index : int) {
return property_buffer[index].color;
}

View File

@@ -0,0 +1,6 @@
scope (global) [
[vertex__vs_main] : ()
scope (vertex__vs_main) [
[v] : float2
]
]

7
test/check/arrays.golden Normal file
View File

@@ -0,0 +1,7 @@
scope (global) [
[vertex__vs_main] : () -> float4
scope (vertex__vs_main) [
[pos] : float4
[arr] : [16].float4
]
]

View File

@@ -0,0 +1,6 @@
test/bad_double_access.ink:7,4: error: Attempting to access a field on a primitive type 'float'.
p.v.x.
^
declaration:
x: float


View File

@@ -0,0 +1,10 @@
scope (global) [
[vertex__vs_main] : ()
[p] : {v : float2}
scope (p) [
[v] : float2
]
scope (vertex__vs_main) [
[x] : float
]
]

View File

@@ -1,4 +1,4 @@
scope (global) [
[Foo] : {}
[Foo] : {}
scope (Foo) []
]

View File

@@ -1,7 +1,10 @@
scope (global) [
[vertex__vs_main] : ()
scope (vertex__vs_main) [
[i] : int
[x] : int
scope (block) [
[i] : int
scope (block) []
]
]
]

View File

@@ -0,0 +1,4 @@
test/for_index_outside.ink:6,0: error: Use of undeclared symbol 'i'
 i += 1;
^


View File

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

View File

@@ -2,5 +2,8 @@ scope (global) [
[vertex__vs_main] : (pos : float3) -> float4
scope (vertex__vs_main) [
[pos] : float3
scope (block) [ scope (block) []
scope (block) []
]
]
]

View File

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

View File

@@ -0,0 +1,8 @@
scope (global) [
[vertex__vs_main] : ()
scope (vertex__vs_main) [
[b] : float2
[x] : float
[a] : float2
]
]

View File

@@ -2,5 +2,8 @@ scope (global) [
[vertex__vs_main] : (pos : float3) -> float4
scope (vertex__vs_main) [
[pos] : float3
scope (block) []
scope (block) []
scope (block) []
]
]

View File

@@ -2,5 +2,6 @@ scope (global) [
[vertex__vs_main] : (pos : float3) -> float4
scope (vertex__vs_main) [
[pos] : float3
scope (block) []
]
]

View File

@@ -2,5 +2,7 @@ scope (global) [
[vertex__vs_main] : (pos : float3) -> float4
scope (vertex__vs_main) [
[pos] : float3
scope (block) []
scope (block) []
]
]

View File

@@ -1,5 +1,5 @@
scope (global) [
[Data] : {color : float4}
[Data] : {color : float4}
[vertex__vs_main] : ()
scope (Data) [
[color] : float4

View File

@@ -1,6 +1,6 @@
test/struct_access_primitive_type.ink:3,0: error: Attempting to access a field on a primitive type 'int'.
x.d = 4;
^
^
declaration:
x : int = 5


View File

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

View File

@@ -0,0 +1,6 @@
test/temp_access.ink:5,10: error: Cannot assign to an lvalue.
 (a + b).x = 2.0;
^^^^^^^^^^^


View File

@@ -1,8 +1,11 @@
test/assign_arithmetic_expression.ink check
test/arithmetic_parens.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/bad_double_access.ink check
test/double_access.ink check
test/empty_struct.ink check
test/empty_vertex_main.ink check
test/empty_vertex_main_with_position_parameter.ink check
@@ -25,12 +28,14 @@ test/non_bool_cond.ink check
test/pass_and_access_struct_fields_in_functions.ink check
test/passthrough.ink check
test/redeclared_variable.ink check
test/rvalue_binary.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/temp_access.ink check
test/type_as_variable_name.ink check
test/unary.ink check
test/undeclared_function.ink check

View File

@@ -0,0 +1,6 @@
void vs_main()
{
float2 v;
v.x = (2.0f + ((4.0f - 2.0f) * 1.5f)) * 3.0f;
}

View File

@@ -0,0 +1,6 @@
float4 vs_main() : SV_POSITION
{
float4 arr[16];
return arr[0];
}

View File

@@ -1,5 +1,5 @@
void vs_main()
{
float x = (2.0f + 5.0f);
float x = 2.0f + 5.0f;
}

View File

@@ -1,9 +1,8 @@
cbuffer __PROPERTIES : register(b0)
cbuffer properties : register(b0)
{
float4 __PROPERTIES__color;
float4 color;
}
float3 vs_main(float3 pos : POSITION) : SV_POSITION
{
return pos;
@@ -11,6 +10,6 @@ float3 vs_main(float3 pos : POSITION) : SV_POSITION
float4 ps_main() : SV_TARGET
{
return __PROPERTIES__color;
return properties.color;
}

View File

@@ -21,8 +21,8 @@ void vs_main()
v4 = float4(2.0f, 2.0f, 2.0f, 2.0f);
v2.x = 2.0f;
v2.y = 2.0f;
float p = (v2.x + v3.z);
float q = (v4.w + v2.x);
float p = v2.x + v3.z;
float q = v4.w + v2.x;
float4x4 m;
}

View File

@@ -2,6 +2,6 @@ void vs_main()
{
float x = 5.0f;
float y = 3000.0f;
float z = ((y * y) + x);
float z = (y * y) + x;
}

View File

@@ -8,7 +8,7 @@ int foo()
float bar()
{
return (1235.0f * 500);
return 1235.0f * 500;
}
void vs_main()

View File

@@ -7,7 +7,7 @@ struct Foo
float foo(Foo f)
{
return (f.some_data * 2.0f);
return f.some_data * 2.0f;
}
void vs_main()

View File

@@ -0,0 +1,7 @@
void vs_main()
{
float2 a;
float2 b;
float x = (a + b).x;
}

View File

@@ -1,4 +1,5 @@
test/assign_arithmetic_expression.ink codegen
test/arithmetic_parens.ink codegen
test/basic_property_and_return_value.ink codegen
test/builtin_types.ink codegen
test/complicated_computation.ink codegen
@@ -19,6 +20,7 @@ test/multiple_semicolons_everywhere.ink codegen
test/nested_if.ink codegen
test/pass_and_access_struct_fields_in_functions.ink codegen
test/passthrough.ink codegen
test/rvalue_binary.ink codegen
test/simple_else_if.ink codegen
test/simple_if_else.ink codegen
test/simple_if.ink codegen

View File

@@ -1,4 +1,5 @@
test/assign_arithmetic_expression.ink compile
test/arithmetic_parens.ink compile
test/basic_property_and_return_value.ink compile
test/builtin_types.ink compile
test/complicated_computation.ink compile
@@ -19,6 +20,7 @@ test/multiple_functions.ink compile
test/multiple_semicolons_everywhere.ink compile
test/pass_and_access_struct_fields_in_functions.ink compile
test/passthrough.ink compile
test/rvalue_binary.ink compile
test/simple_else_if.ink compile
test/simple_if_else.ink compile
test/simple_if.ink compile

View File

@@ -1,4 +1,4 @@
camera :: constant_buffer {
camera :: Constant_Buffer {
projection : float4x4;
view : float4x4;
}

View File

@@ -1,4 +1,4 @@
p :: properties {
p :: Constant_Buffer {
v : float2;
}

View File

@@ -0,0 +1,7 @@
vertex main :: () {
for i : 0..10 {
x : float;
}
i += 1;
}

View File

@@ -1,4 +1,4 @@
p :: constant_buffer @properties {
p :: Constant_Buffer @properties {
color : float4;
rect_position : float2;
rect_scale : float2;

View File

@@ -0,0 +1,32 @@
{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 16 ; length = 1 line = 1 ; column = 16 ; value =')'; }
{kind = TOKEN_LEFTBRACE; ; index = 18 ; length = 1 line = 1 ; column = 18 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 1 line = 2 ; column = 0 ; value ='v'; }
{kind = TOKEN_COLON; ; index = 24 ; length = 1 line = 2 ; column = 2 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 26 ; length = 6 line = 2 ; column = 4 ; value ='float2'; }
{kind = TOKEN_SEMICOLON; ; index = 32 ; length = 1 line = 2 ; column = 10 ; value =';'; }
{kind = TOKEN_IDENTIFIER; ; index = 36 ; length = 1 line = 3 ; column = 0 ; value ='v'; }
{kind = TOKEN_DOT; ; index = 37 ; length = 1 line = 3 ; column = 1 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 38 ; length = 1 line = 3 ; column = 2 ; value ='x'; }
{kind = TOKEN_ASSIGN; ; index = 40 ; length = 1 line = 3 ; column = 4 ; value ='='; }
{kind = TOKEN_LEFTPAREN; ; index = 42 ; length = 1 line = 3 ; column = 6 ; value ='('; }
{kind = TOKEN_FLOATLITERAL; ; index = 43 ; length = 3 line = 3 ; column = 7 ; value ='2'; }
{kind = TOKEN_PLUS; ; index = 47 ; length = 1 line = 3 ; column = 11 ; value ='+'; }
{kind = TOKEN_LEFTPAREN; ; index = 49 ; length = 1 line = 3 ; column = 13 ; value ='('; }
{kind = TOKEN_LEFTPAREN; ; index = 50 ; length = 1 line = 3 ; column = 14 ; value ='('; }
{kind = TOKEN_FLOATLITERAL; ; index = 51 ; length = 3 line = 3 ; column = 15 ; value ='4'; }
{kind = TOKEN_MINUS; ; index = 55 ; length = 1 line = 3 ; column = 19 ; value ='-'; }
{kind = TOKEN_FLOATLITERAL; ; index = 57 ; length = 3 line = 3 ; column = 21 ; value ='2'; }
{kind = TOKEN_RIGHTPAREN; ; index = 60 ; length = 1 line = 3 ; column = 24 ; value =')'; }
{kind = TOKEN_STAR; ; index = 62 ; length = 1 line = 3 ; column = 26 ; value ='*'; }
{kind = TOKEN_FLOATLITERAL; ; index = 64 ; length = 3 line = 3 ; column = 28 ; value ='1.5'; }
{kind = TOKEN_RIGHTPAREN; ; index = 67 ; length = 1 line = 3 ; column = 31 ; value =')'; }
{kind = TOKEN_RIGHTPAREN; ; index = 68 ; length = 1 line = 3 ; column = 32 ; value =')'; }
{kind = TOKEN_STAR; ; index = 70 ; length = 1 line = 3 ; column = 34 ; value ='*'; }
{kind = TOKEN_FLOATLITERAL; ; index = 72 ; length = 3 line = 3 ; column = 36 ; value ='3'; }
{kind = TOKEN_SEMICOLON; ; index = 75 ; length = 1 line = 3 ; column = 39 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 78 ; length = 1 line = 4 ; column = 0 ; value ='}'; }
{kind = TOKEN_EOF; ; index = 81 ; length = 0 line = 5 ; column = 0 ; value =''; }

View File

@@ -0,0 +1,31 @@
{kind = TOKEN_IDENTIFIER; ; index = 0 ; length = 1 line = 1 ; column = 0 ; value ='P'; }
{kind = TOKEN_DOUBLECOLON; ; index = 2 ; length = 2 line = 1 ; column = 2 ; value ='::'; }
{kind = TOKEN_STRUCT; ; index = 5 ; length = 6 line = 1 ; column = 5 ; value ='struct'; }
{kind = TOKEN_LEFTBRACE; ; index = 12 ; length = 1 line = 1 ; column = 12 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 16 ; length = 1 line = 2 ; column = 0 ; value ='v'; }
{kind = TOKEN_COLON; ; index = 18 ; length = 1 line = 2 ; column = 2 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 20 ; length = 6 line = 2 ; column = 4 ; value ='float2'; }
{kind = TOKEN_SEMICOLON; ; index = 26 ; length = 1 line = 2 ; column = 10 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 29 ; length = 1 line = 3 ; column = 0 ; value ='}'; }
{kind = TOKEN_VERTEX; ; index = 34 ; length = 6 line = 5 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 41 ; length = 4 line = 5 ; column = 7 ; value ='main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 46 ; length = 2 line = 5 ; column = 12 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 49 ; length = 1 line = 5 ; column = 15 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 50 ; length = 1 line = 5 ; column = 16 ; value =')'; }
{kind = TOKEN_LEFTBRACE; ; index = 52 ; length = 1 line = 5 ; column = 18 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 56 ; length = 1 line = 6 ; column = 0 ; value ='p'; }
{kind = TOKEN_COLON; ; index = 58 ; length = 1 line = 6 ; column = 2 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 60 ; length = 1 line = 6 ; column = 4 ; value ='P'; }
{kind = TOKEN_SEMICOLON; ; index = 61 ; length = 1 line = 6 ; column = 5 ; value =';'; }
{kind = TOKEN_IDENTIFIER; ; index = 65 ; length = 1 line = 7 ; column = 0 ; value ='p'; }
{kind = TOKEN_DOT; ; index = 66 ; length = 1 line = 7 ; column = 1 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 67 ; length = 1 line = 7 ; column = 2 ; value ='v'; }
{kind = TOKEN_DOT; ; index = 68 ; length = 1 line = 7 ; column = 3 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 69 ; length = 1 line = 7 ; column = 4 ; value ='x'; }
{kind = TOKEN_DOT; ; index = 70 ; length = 1 line = 7 ; column = 5 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 71 ; length = 1 line = 7 ; column = 6 ; value ='y'; }
{kind = TOKEN_ASSIGN; ; index = 73 ; length = 1 line = 7 ; column = 8 ; value ='='; }
{kind = TOKEN_FLOATLITERAL; ; index = 75 ; length = 3 line = 7 ; column = 10 ; value ='2'; }
{kind = TOKEN_SEMICOLON; ; index = 78 ; length = 1 line = 7 ; column = 13 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 118 ; length = 1 line = 10 ; column = 0 ; value ='}'; }
{kind = TOKEN_EOF; ; index = 121 ; length = 0 line = 11 ; column = 0 ; value =''; }

View File

@@ -1,6 +1,6 @@
{kind = TOKEN_IDENTIFIER; ; index = 0 ; length = 10 line = 1 ; column = 0 ; value ='properties'; }
{kind = TOKEN_DOUBLECOLON; ; index = 11 ; length = 2 line = 1 ; column = 11 ; value ='::'; }
{kind = TOKEN_CONSTANT_BUFFER; ; index = 14 ; length = 15 line = 1 ; column = 14 ; value ='constant_buffer'; }
{kind = TOKEN_CONSTANT_BUFFER; ; index = 14 ; length = 15 line = 1 ; column = 14 ; value ='Constant_Buffer'; }
{kind = TOKEN_AT; ; index = 30 ; length = 1 line = 1 ; column = 30 ; value ='@'; }
{kind = TOKEN_IDENTIFIER; ; index = 31 ; length = 10 line = 1 ; column = 31 ; value ='properties'; }
{kind = TOKEN_LEFTBRACE; ; index = 42 ; length = 1 line = 1 ; column = 42 ; value ='{'; }

View File

@@ -1,6 +1,6 @@
{kind = TOKEN_IDENTIFIER; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='camera'; }
{kind = TOKEN_DOUBLECOLON; ; index = 7 ; length = 2 line = 1 ; column = 7 ; value ='::'; }
{kind = TOKEN_CONSTANT_BUFFER; ; index = 10 ; length = 15 line = 1 ; column = 10 ; value ='constant_buffer'; }
{kind = TOKEN_CONSTANT_BUFFER; ; index = 10 ; length = 15 line = 1 ; column = 10 ; value ='Constant_Buffer'; }
{kind = TOKEN_LEFTBRACE; ; index = 26 ; length = 1 line = 1 ; column = 26 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 30 ; length = 10 line = 2 ; column = 0 ; value ='projection'; }
{kind = TOKEN_COLON; ; index = 41 ; length = 1 line = 2 ; column = 11 ; value =':'; }

View File

@@ -0,0 +1,33 @@
{kind = TOKEN_IDENTIFIER; ; index = 0 ; length = 1 line = 1 ; column = 0 ; value ='p'; }
{kind = TOKEN_DOUBLECOLON; ; index = 2 ; length = 2 line = 1 ; column = 2 ; value ='::'; }
{kind = TOKEN_CONSTANT_BUFFER; ; index = 5 ; length = 15 line = 1 ; column = 5 ; value ='Constant_Buffer'; }
{kind = TOKEN_LEFTBRACE; ; index = 21 ; length = 1 line = 1 ; column = 21 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 25 ; length = 1 line = 2 ; column = 0 ; value ='v'; }
{kind = TOKEN_COLON; ; index = 27 ; length = 1 line = 2 ; column = 2 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 29 ; length = 6 line = 2 ; column = 4 ; value ='float2'; }
{kind = TOKEN_SEMICOLON; ; index = 35 ; length = 1 line = 2 ; column = 10 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 38 ; length = 1 line = 3 ; column = 0 ; value ='}'; }
{kind = TOKEN_VERTEX; ; index = 43 ; length = 6 line = 5 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 50 ; length = 4 line = 5 ; column = 7 ; value ='main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 55 ; length = 2 line = 5 ; column = 12 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 57 ; length = 1 line = 5 ; column = 14 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 58 ; length = 1 line = 5 ; column = 15 ; value =')'; }
{kind = TOKEN_LEFTBRACE; ; index = 60 ; length = 1 line = 5 ; column = 17 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 64 ; length = 1 line = 6 ; column = 0 ; value ='x'; }
{kind = TOKEN_COLON; ; index = 66 ; length = 1 line = 6 ; column = 2 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 68 ; length = 5 line = 6 ; column = 4 ; value ='float'; }
{kind = TOKEN_ASSIGN; ; index = 74 ; length = 1 line = 6 ; column = 10 ; value ='='; }
{kind = TOKEN_IDENTIFIER; ; index = 76 ; length = 1 line = 6 ; column = 12 ; value ='p'; }
{kind = TOKEN_DOT; ; index = 77 ; length = 1 line = 6 ; column = 13 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 78 ; length = 1 line = 6 ; column = 14 ; value ='v'; }
{kind = TOKEN_DOT; ; index = 79 ; length = 1 line = 6 ; column = 15 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 80 ; length = 1 line = 6 ; column = 16 ; value ='x'; }
{kind = TOKEN_SLASH; ; index = 82 ; length = 1 line = 6 ; column = 18 ; value ='/'; }
{kind = TOKEN_IDENTIFIER; ; index = 84 ; length = 1 line = 6 ; column = 20 ; value ='p'; }
{kind = TOKEN_DOT; ; index = 85 ; length = 1 line = 6 ; column = 21 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 86 ; length = 1 line = 6 ; column = 22 ; value ='v'; }
{kind = TOKEN_DOT; ; index = 87 ; length = 1 line = 6 ; column = 23 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 88 ; length = 1 line = 6 ; column = 24 ; value ='y'; }
{kind = TOKEN_SEMICOLON; ; index = 89 ; length = 1 line = 6 ; column = 25 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 92 ; length = 1 line = 7 ; column = 0 ; value ='}'; }
{kind = TOKEN_EOF; ; index = 95 ; length = 0 line = 8 ; column = 0 ; value =''; }

View File

@@ -1,6 +1,6 @@
{kind = TOKEN_IDENTIFIER; ; index = 0 ; length = 1 line = 1 ; column = 0 ; value ='p'; }
{kind = TOKEN_DOUBLECOLON; ; index = 2 ; length = 2 line = 1 ; column = 2 ; value ='::'; }
{kind = TOKEN_CONSTANT_BUFFER; ; index = 5 ; length = 15 line = 1 ; column = 5 ; value ='constant_buffer'; }
{kind = TOKEN_CONSTANT_BUFFER; ; index = 5 ; length = 15 line = 1 ; column = 5 ; value ='Constant_Buffer'; }
{kind = TOKEN_AT; ; index = 21 ; length = 1 line = 1 ; column = 21 ; value ='@'; }
{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 10 line = 1 ; column = 22 ; value ='properties'; }
{kind = TOKEN_LEFTBRACE; ; index = 33 ; length = 1 line = 1 ; column = 33 ; value ='{'; }

View File

@@ -0,0 +1,27 @@
{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 16 ; length = 1 line = 1 ; column = 16 ; value =')'; }
{kind = TOKEN_LEFTBRACE; ; index = 18 ; length = 1 line = 1 ; column = 18 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 1 line = 2 ; column = 0 ; value ='a'; }
{kind = TOKEN_COLON; ; index = 24 ; length = 1 line = 2 ; column = 2 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 26 ; length = 6 line = 2 ; column = 4 ; value ='float2'; }
{kind = TOKEN_SEMICOLON; ; index = 32 ; length = 1 line = 2 ; column = 10 ; value =';'; }
{kind = TOKEN_IDENTIFIER; ; index = 36 ; length = 1 line = 3 ; column = 0 ; value ='b'; }
{kind = TOKEN_COLON; ; index = 38 ; length = 1 line = 3 ; column = 2 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 40 ; length = 6 line = 3 ; column = 4 ; value ='float2'; }
{kind = TOKEN_SEMICOLON; ; index = 46 ; length = 1 line = 3 ; column = 10 ; value =';'; }
{kind = TOKEN_IDENTIFIER; ; index = 52 ; length = 1 line = 5 ; column = 0 ; value ='x'; }
{kind = TOKEN_COLON; ; index = 54 ; length = 1 line = 5 ; column = 2 ; value =':'; }
{kind = TOKEN_ASSIGN; ; index = 55 ; length = 1 line = 5 ; column = 3 ; value ='='; }
{kind = TOKEN_LEFTPAREN; ; index = 57 ; length = 1 line = 5 ; column = 5 ; value ='('; }
{kind = TOKEN_IDENTIFIER; ; index = 58 ; length = 1 line = 5 ; column = 6 ; value ='a'; }
{kind = TOKEN_PLUS; ; index = 60 ; length = 1 line = 5 ; column = 8 ; value ='+'; }
{kind = TOKEN_IDENTIFIER; ; index = 62 ; length = 1 line = 5 ; column = 10 ; value ='b'; }
{kind = TOKEN_RIGHTPAREN; ; index = 63 ; length = 1 line = 5 ; column = 11 ; value =')'; }
{kind = TOKEN_DOT; ; index = 64 ; length = 1 line = 5 ; column = 12 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 65 ; length = 1 line = 5 ; column = 13 ; value ='x'; }
{kind = TOKEN_SEMICOLON; ; index = 66 ; length = 1 line = 5 ; column = 14 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 69 ; length = 1 line = 6 ; column = 0 ; value ='}'; }
{kind = TOKEN_EOF; ; index = 72 ; length = 0 line = 7 ; column = 0 ; value =''; }

View File

@@ -0,0 +1,26 @@
{kind = TOKEN_VERTEX; ; index = 0 ; length = 6 line = 1 ; column = 0 ; value ='vertex'; }
{kind = TOKEN_IDENTIFIER; ; index = 7 ; length = 4 line = 1 ; column = 7 ; value ='main'; }
{kind = TOKEN_DOUBLECOLON; ; index = 12 ; length = 2 line = 1 ; column = 12 ; value ='::'; }
{kind = TOKEN_LEFTPAREN; ; index = 15 ; length = 1 line = 1 ; column = 15 ; value ='('; }
{kind = TOKEN_RIGHTPAREN; ; index = 16 ; length = 1 line = 1 ; column = 16 ; value =')'; }
{kind = TOKEN_LEFTBRACE; ; index = 18 ; length = 1 line = 1 ; column = 18 ; value ='{'; }
{kind = TOKEN_IDENTIFIER; ; index = 22 ; length = 1 line = 2 ; column = 0 ; value ='a'; }
{kind = TOKEN_COLON; ; index = 24 ; length = 1 line = 2 ; column = 2 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 26 ; length = 6 line = 2 ; column = 4 ; value ='float2'; }
{kind = TOKEN_SEMICOLON; ; index = 32 ; length = 1 line = 2 ; column = 10 ; value =';'; }
{kind = TOKEN_IDENTIFIER; ; index = 36 ; length = 1 line = 3 ; column = 0 ; value ='b'; }
{kind = TOKEN_COLON; ; index = 38 ; length = 1 line = 3 ; column = 2 ; value =':'; }
{kind = TOKEN_IDENTIFIER; ; index = 40 ; length = 6 line = 3 ; column = 4 ; value ='float2'; }
{kind = TOKEN_SEMICOLON; ; index = 46 ; length = 1 line = 3 ; column = 10 ; value =';'; }
{kind = TOKEN_LEFTPAREN; ; index = 52 ; length = 1 line = 5 ; column = 0 ; value ='('; }
{kind = TOKEN_IDENTIFIER; ; index = 53 ; length = 1 line = 5 ; column = 1 ; value ='a'; }
{kind = TOKEN_PLUS; ; index = 55 ; length = 1 line = 5 ; column = 3 ; value ='+'; }
{kind = TOKEN_IDENTIFIER; ; index = 57 ; length = 1 line = 5 ; column = 5 ; value ='b'; }
{kind = TOKEN_RIGHTPAREN; ; index = 58 ; length = 1 line = 5 ; column = 6 ; value =')'; }
{kind = TOKEN_DOT; ; index = 59 ; length = 1 line = 5 ; column = 7 ; value ='.'; }
{kind = TOKEN_IDENTIFIER; ; index = 60 ; length = 1 line = 5 ; column = 8 ; value ='x'; }
{kind = TOKEN_ASSIGN; ; index = 62 ; length = 1 line = 5 ; column = 10 ; value ='='; }
{kind = TOKEN_FLOATLITERAL; ; index = 64 ; length = 3 line = 5 ; column = 12 ; value ='2'; }
{kind = TOKEN_SEMICOLON; ; index = 67 ; length = 1 line = 5 ; column = 15 ; value =';'; }
{kind = TOKEN_RIGHTBRACE; ; index = 70 ; length = 1 line = 6 ; column = 0 ; value ='}'; }
{kind = TOKEN_EOF; ; index = 73 ; length = 0 line = 7 ; column = 0 ; value =''; }

View File

@@ -1,8 +1,11 @@
test/assign_arithmetic_expression.ink lex
test/arithmetic_parens.ink lex
test/bad_double_access.ink lex
test/basic_property_and_return_value.ink lex
test/builtin_types.ink lex
test/complicated_computation.ink lex
test/constant_buffer.ink lex
test/double_access.ink lex
test/else_if_after_else.ink lex
test/empty_struct.ink lex
test/empty_vertex_main.ink lex
@@ -33,12 +36,14 @@ test/non_bool_cond.ink lex
test/pass_and_access_struct_fields_in_functions.ink lex
test/passthrough.ink lex
test/redeclared_variable.ink lex
test/rvalue_binary.ink lex
test/simple_else_if.ink lex
test/simple_if_else.ink lex
test/simple_if.ink lex
test/simple_struct_access.ink lex
test/struct_access_primitive_type.ink lex
test/struct_within_struct.ink lex
test/temp_access.ink lex
test/type_as_variable_name.ink lex
test/unary.ink lex
test/undeclared_function.ink lex

View File

@@ -0,0 +1,5 @@
(program
(fun vertex vs_main
[]
(:= v float2)
(= v.x (* (+ 2 (* (- 4 2) 1.5)) 3))))

View File

@@ -0,0 +1,8 @@
(program
(struct P
[(:= v float2)])
(fun vertex vs_main
[]
(:= p P)
(= p.v.x.y 2)))

10
test/parse/buffers.golden Normal file
View File

@@ -0,0 +1,10 @@
(program
(buffer property_buffer
[(:= color float4)])
(constant_buffer cbuffer
[(:= color float4)])
(fun pixel ps_main
[(:= index int)]
(return property_buffer[index].color)))

View File

@@ -0,0 +1,7 @@
(program
(constant_buffer p
[(:= v float2)])
(fun vertex vs_main
[]
(:= x float (/ p.v.x p.v.y))))

View File

@@ -0,0 +1,6 @@
(program
(fun vertex vs_main
[]
(:= a float2)
(:= b float2)
(:= x (+ a b).x)))

View File

@@ -0,0 +1,6 @@
(program
(fun vertex vs_main
[]
(:= a float2)
(:= b float2)
(= (+ a b).x 2)))

View File

@@ -1,8 +1,11 @@
test/assign_arithmetic_expression.ink parse
test/arithmetic_parens.ink parse
test/bad_double_access.ink parse
test/basic_property_and_return_value.ink parse
test/builtin_types.ink parse
test/complicated_computation.ink parse
test/constant_buffer.ink parse
test/double_access.ink parse
test/else_if_after_else.ink parse
test/empty_struct.ink parse
test/empty_vertex_main.ink parse
@@ -33,12 +36,14 @@ test/non_bool_cond.ink parse
test/pass_and_access_struct_fields_in_functions.ink parse
test/passthrough.ink parse
test/redeclared_variable.ink parse
test/rvalue_binary.ink parse
test/simple_else_if.ink parse
test/simple_if_else.ink parse
test/simple_if.ink parse
test/simple_struct_access.ink parse
test/struct_access_primitive_type.ink parse
test/struct_within_struct.ink parse
test/temp_access.ink parse
test/type_as_variable_name.ink parse
test/unary.ink parse
test/undeclared_function.ink parse

6
test/rvalue_binary.ink Normal file
View File

@@ -0,0 +1,6 @@
vertex main :: () {
a : float2;
b : float2;
x := (a + b).x;
}

6
test/temp_access.ink Normal file
View File

@@ -0,0 +1,6 @@
vertex main :: () {
a : float2;
b : float2;
(a + b).x = 2.0;
}