diff --git a/Sources/backends/glsl.c b/Sources/backends/glsl.c index 085c950..a7e314e 100644 --- a/Sources/backends/glsl.c +++ b/Sources/backends/glsl.c @@ -166,7 +166,7 @@ static void write_types(char *glsl, size_t *offset, shader_stage stage, type_id for (size_t i = 0; i < types_size; ++i) { type *t = get_type(types[i]); - if (!t->built_in && t->attribute != add_name("pipe")) { + if (!t->built_in && !has_attribute(&t->attributes, add_name("pipe"))) { if (stage == SHADER_STAGE_VERTEX && types[i] == input) { for (size_t j = 0; j < t->members.size; ++j) { *offset += sprintf(&glsl[*offset], "layout(location = %zu) in %s %s_%s;\n", j, type_string(t->members.m[j].type.type), get_name(t->name), @@ -197,7 +197,7 @@ static void write_types(char *glsl, size_t *offset, shader_stage stage, type_id for (size_t i = 0; i < types_size; ++i) { type *t = get_type(types[i]); - if (!t->built_in && t->attribute != add_name("pipe")) { + if (!t->built_in && !has_attribute(&t->attributes, add_name("pipe"))) { *offset += sprintf(&glsl[*offset], "struct %s {\n", get_name(t->name)); for (size_t j = 0; j < t->members.size; ++j) { @@ -559,7 +559,7 @@ void glsl_export(char *directory) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute == add_name("pipe")) { + if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) { name_id vertex_shader_name = NO_NAME; name_id fragment_shader_name = NO_NAME; diff --git a/Sources/backends/hlsl.c b/Sources/backends/hlsl.c index 3269936..9879f5b 100644 --- a/Sources/backends/hlsl.c +++ b/Sources/backends/hlsl.c @@ -187,7 +187,7 @@ static void write_types(char *hlsl, size_t *offset, shader_stage stage, type_id for (size_t i = 0; i < types_size; ++i) { type *t = get_type(types[i]); - if (!t->built_in && t->attribute != add_name("pipe")) { + if (!t->built_in && !has_attribute(&t->attributes, add_name("pipe"))) { *offset += sprintf(&hlsl[*offset], "struct %s {\n", get_name(t->name)); if (stage == SHADER_STAGE_VERTEX && types[i] == input) { @@ -345,7 +345,13 @@ static void write_functions(char *hlsl, size_t *offset, shader_stage stage, func } } else if (stage == SHADER_STAGE_COMPUTE) { - *offset += sprintf(&hlsl[*offset], "[numthreads(64, 1, 1)] %s main(", type_string(f->return_type.type)); + attribute *threads_attribute = find_attribute(&f->attributes, add_name("threads")); + if (threads_attribute == NULL || threads_attribute->paramters_count != 3) { + debug_context context = {0}; + error(context, "Compute function requires a threads attribute with three parameters"); + } + *offset += sprintf(&hlsl[*offset], "[numthreads(%i, %i, %i)] %s main(", (int)threads_attribute->parameters[0], + (int)threads_attribute->parameters[1], (int)threads_attribute->parameters[2], type_string(f->return_type.type)); for (uint8_t parameter_index = 0; parameter_index < f->parameters_size; ++parameter_index) { if (parameter_index == 0) { *offset += @@ -625,7 +631,7 @@ void hlsl_export(char *directory, api_kind d3d) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute == add_name("pipe")) { + if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) { name_id vertex_shader_name = NO_NAME; name_id fragment_shader_name = NO_NAME; @@ -661,7 +667,7 @@ void hlsl_export(char *directory, api_kind d3d) { for (function_id i = 0; get_function(i) != NULL; ++i) { function *f = get_function(i); - if (f->attribute == add_name("compute")) { + if (has_attribute(&f->attributes, add_name("compute"))) { compute_shaders[compute_shaders_size] = f; compute_shaders_size += 1; } diff --git a/Sources/backends/metal.c b/Sources/backends/metal.c index 54d1170..ae4055e 100644 --- a/Sources/backends/metal.c +++ b/Sources/backends/metal.c @@ -148,7 +148,7 @@ static void write_types(char *metal, size_t *offset) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute != add_name("pipe")) { + if (!t->built_in && !has_attribute(&t->attributes, add_name("pipe"))) { if (t->name == NO_NAME) { char name[256]; @@ -483,7 +483,7 @@ void metal_export(char *directory) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute == add_name("pipe")) { + if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) { name_id vertex_shader_name = NO_NAME; name_id fragment_shader_name = NO_NAME; diff --git a/Sources/backends/spirv.c b/Sources/backends/spirv.c index b93f21f..4a40f6c 100644 --- a/Sources/backends/spirv.c +++ b/Sources/backends/spirv.c @@ -490,7 +490,7 @@ static void write_types(instructions_buffer *constants, function *main) { for (size_t i = 0; i < types_size; ++i) { type *t = get_type(types[i]); - if (!t->built_in && t->attribute != add_name("pipe")) { + if (!t->built_in && !has_attribute(&t->attributes, add_name("pipe"))) { spirv_id member_types[256]; uint16_t member_types_size = 0; for (size_t j = 0; j < t->members.size; ++j) { @@ -1265,7 +1265,7 @@ void spirv_export(char *directory) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute == add_name("pipe")) { + if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) { name_id vertex_shader_name = NO_NAME; name_id fragment_shader_name = NO_NAME; diff --git a/Sources/backends/wgsl.c b/Sources/backends/wgsl.c index aa4f898..38c5a28 100644 --- a/Sources/backends/wgsl.c +++ b/Sources/backends/wgsl.c @@ -190,7 +190,7 @@ static void write_types(char *wgsl, size_t *offset) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute != add_name("pipe")) { + if (!t->built_in && !has_attribute(&t->attributes, add_name("pipe"))) { if (t->name == NO_NAME) { char name[256]; @@ -664,7 +664,7 @@ void wgsl_export(char *directory) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute == add_name("pipe")) { + if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) { name_id vertex_shader_name = NO_NAME; name_id fragment_shader_name = NO_NAME; diff --git a/Sources/functions.c b/Sources/functions.c index 75a3f02..baf1294 100644 --- a/Sources/functions.c +++ b/Sources/functions.c @@ -100,7 +100,7 @@ function_id add_function(name_id name) { ++next_function_index; functions[f].name = name; - functions[f].attribute = NO_NAME; + functions[f].attributes.attributes_count = 0; init_type_ref(&functions[f].return_type, NO_NAME); functions[f].parameters_size = 0; functions[f].block = NULL; diff --git a/Sources/functions.h b/Sources/functions.h index 5552f5f..8e24c6f 100644 --- a/Sources/functions.h +++ b/Sources/functions.h @@ -11,7 +11,7 @@ typedef uint32_t function_id; struct statement; typedef struct function { - name_id attribute; + attribute_list attributes; name_id name; type_ref return_type; name_id parameter_names[256]; diff --git a/Sources/integrations/kinc.c b/Sources/integrations/kinc.c index 6c4ef72..574ae75 100644 --- a/Sources/integrations/kinc.c +++ b/Sources/integrations/kinc.c @@ -303,7 +303,7 @@ void kinc_export(char *directory, api_kind api) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute == add_name("pipe")) { + if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) { name_id vertex_shader_name = NO_NAME; for (size_t j = 0; j < t->members.size; ++j) { @@ -404,14 +404,14 @@ void kinc_export(char *directory, api_kind api) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute == add_name("pipe")) { + if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) { fprintf(output, "extern kinc_g4_pipeline_t %s;\n\n", get_name(t->name)); } } for (function_id i = 0; get_function(i) != NULL; ++i) { function *f = get_function(i); - if (f->attribute == add_name("compute")) { + if (has_attribute(&f->attributes, add_name("compute"))) { fprintf(output, "extern kinc_g4_compute_shader %s;\n\n", get_name(f->name)); } } @@ -438,7 +438,7 @@ void kinc_export(char *directory, api_kind api) { else { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute == add_name("pipe")) { + if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) { for (size_t j = 0; j < t->members.size; ++j) { debug_context context = {0}; if (t->members.m[j].name == add_name("vertex")) { @@ -455,7 +455,7 @@ void kinc_export(char *directory, api_kind api) { for (function_id i = 0; get_function(i) != NULL; ++i) { function *f = get_function(i); - if (f->attribute == add_name("compute")) { + if (has_attribute(&f->attributes, add_name("compute"))) { fprintf(output, "#include \"kong_%s.h\"\n", get_name(f->name)); } } @@ -474,7 +474,7 @@ void kinc_export(char *directory, api_kind api) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute == add_name("pipe")) { + if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) { fprintf(output, "kinc_g4_pipeline_t %s;\n\n", get_name(t->name)); } } @@ -534,7 +534,7 @@ void kinc_export(char *directory, api_kind api) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute == add_name("pipe")) { + if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) { for (size_t j = 0; j < t->members.size; ++j) { if (t->members.m[j].name == add_name("vertex") || t->members.m[j].name == add_name("fragment")) { debug_context context = {0}; @@ -547,7 +547,7 @@ void kinc_export(char *directory, api_kind api) { for (function_id i = 0; get_function(i) != NULL; ++i) { function *f = get_function(i); - if (f->attribute == add_name("compute")) { + if (has_attribute(&f->attributes, add_name("compute"))) { fprintf(output, "kinc_g4_compute_shader %s;\n", get_name(f->name)); } } @@ -568,7 +568,7 @@ void kinc_export(char *directory, api_kind api) { for (type_id i = 0; get_type(i) != NULL; ++i) { type *t = get_type(i); - if (!t->built_in && t->attribute == add_name("pipe")) { + if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) { fprintf(output, "\tkinc_g4_pipeline_init(&%s);\n\n", get_name(t->name)); name_id vertex_shader_name = NO_NAME; @@ -747,7 +747,7 @@ void kinc_export(char *directory, api_kind api) { for (function_id i = 0; get_function(i) != NULL; ++i) { function *f = get_function(i); - if (f->attribute == add_name("compute")) { + if (has_attribute(&f->attributes, add_name("compute"))) { fprintf(output, "\tkinc_g4_compute_shader_init(&%s, %s_code, %s_code_size);\n", get_name(f->name), get_name(f->name), get_name(f->name)); } } diff --git a/Sources/parser.c b/Sources/parser.c index 65e0ab9..1317947 100644 --- a/Sources/parser.c +++ b/Sources/parser.c @@ -145,114 +145,80 @@ static void modifiers_add(modifiers_t *modifiers, modifier_t modifier) { modifiers->size += 1; } -/*static statement_t *parse_declaration(state_t *state, modifiers_t modifiers) { - switch (current(state).type) { - case TOKEN_IN: { - advance_state(state); - modifiers_add(&modifiers, MODIFIER_IN); - return parse_declaration(state, modifiers); - } - case TOKEN_IDENTIFIER: { - // type name - advance_state(state); - break; - } - case TOKEN_VOID: { - advance_state(state); - break; - } - default: - error("Expected a variable declaration"); - } - - token_t identifier; - if (current(state).type == TOKEN_IDENTIFIER) { - identifier = current(state); - advance_state(state); - } - else { - error("Expected an identifier"); - } - - switch (current(state).type) { - case TOKEN_OPERATOR: { - operator_t op = current(state).op; - switch (op) { - case OPERATOR_ASSIGN: { - advance_state(state); - expression_t *expr = parse_expression(state); - switch (current(state).type) { - case TOKEN_SEMICOLON: { - advance_state(state); - statement_t *statement = statement_allocate(); - statement->type = STATEMENT_DECLARATION; - strcpy(statement->declaration.name, identifier.identifier); - statement->declaration.init = expr; - return statement; - } - default: - error("Expected a semicolon"); - return NULL; - } - } - default: - error("Expected an assignment operator"); - return NULL; - }; - } - case TOKEN_SEMICOLON: { - advance_state(state); - statement_t *statement = statement_allocate(); - statement->type = STATEMENT_DECLARATION; - strcpy(statement->declaration.name, identifier.identifier); - statement->declaration.init = NULL; - return statement; - } - case TOKEN_LEFT_PAREN: { - advance_state(state); - switch (current(state).type) { - case TOKEN_RIGHT_PAREN: { - advance_state(state); - statement_t *statement = statement_allocate(); - statement->type = STATEMENT_FUNCTION; - statement->function.parameters.size = 0; - statement->function.block = parse_block(state); - return statement; - } - default: - error("Expected right paren"); - return NULL; - } - } - default: - error("Expected an assign or a semicolon"); - return NULL; - } -}*/ - static definition parse_struct(state_t *state); static definition parse_function(state_t *state); static definition parse_const(state_t *state); +static double attribute_parameter_to_number(name_id attribute_name, name_id parameter_name) { + debug_context context = {0}; + error(context, "Unknown attribute parameter %s", get_name(parameter_name)); + return 0; +} + static definition parse_definition(state_t *state) { - name_id attribute = NO_NAME; + attribute_list attributes = {0}; - if (current(state).kind == TOKEN_ATTRIBUTE) { - token token = current(state); - attribute = token.attribute; + if (current(state).kind == TOKEN_HASH) { + advance_state(state); + match_token(state, TOKEN_LEFT_SQUARE, "Expected left square"); + advance_state(state); + + while (current(state).kind != TOKEN_RIGHT_SQUARE) { + attribute current_attribute = {0}; + + match_token(state, TOKEN_IDENTIFIER, "Expected an identifier"); + current_attribute.name = current(state).identifier; + + advance_state(state); + + if (current(state).kind == TOKEN_LEFT_PAREN) { + advance_state(state); + + while (current(state).kind != TOKEN_RIGHT_PAREN) { + if (current(state).kind == TOKEN_IDENTIFIER) { + current_attribute.parameters[current_attribute.paramters_count] = attribute_parameter_to_number(current_attribute.name, current(state).identifier); + current_attribute.paramters_count += 1; + advance_state(state); + } + else if (current(state).kind == TOKEN_NUMBER) { + current_attribute.parameters[current_attribute.paramters_count] = current(state).number; + current_attribute.paramters_count += 1; + advance_state(state); + } + else { + debug_context context = {0}; + error(context, "Expected an identifier or a number"); + } + + if (current(state).kind != TOKEN_RIGHT_PAREN){ + match_token(state, TOKEN_COMMA, "Expected a comma"); + advance_state(state); + } + } + advance_state(state); + } + + attributes.attributes[attributes.attributes_count] = current_attribute; + attributes.attributes_count += 1; + + if (current(state).kind != TOKEN_RIGHT_SQUARE) { + match_token(state, TOKEN_COMMA, "Expected a comma"); + advance_state(state); + } + } advance_state(state); } switch (current(state).kind) { case TOKEN_STRUCT: { definition structy = parse_struct(state); - get_type(structy.type)->attribute = attribute; + get_type(structy.type)->attributes = attributes; return structy; } case TOKEN_FUNCTION: { definition d = parse_function(state); function *f = get_function(d.function); - f->attribute = attribute; + f->attributes = attributes; return d; } case TOKEN_CONST: { diff --git a/Sources/tokenizer.c b/Sources/tokenizer.c index e380a98..5de1bd7 100644 --- a/Sources/tokenizer.c +++ b/Sources/tokenizer.c @@ -31,8 +31,7 @@ typedef enum mode { MODE_OPERATOR, MODE_IDENTIFIER, MODE_LINE_COMMENT, - MODE_COMMENT, - MODE_ATTRIBUTE, + MODE_COMMENT } mode; typedef struct tokenizer_state { @@ -122,8 +121,8 @@ static name_id tokenizer_buffer_to_name(tokenizer_buffer *buffer) { } static double tokenizer_buffer_parse_number(tokenizer_buffer *buffer) { - char *end = &buffer->buf[buffer->current_size]; - return strtod(buffer->buf, &end); + buffer->buf[buffer->current_size] = 0; + return strtod(buffer->buf, NULL); } token token_create(int kind, tokenizer_state *state) { @@ -201,14 +200,6 @@ static void tokens_add_identifier(tokenizer_state *state, tokens *tokens, tokeni tokens_add(tokens, token); } -static void tokens_add_attribute(tokenizer_state *state, tokens *tokens, tokenizer_buffer *buffer) { - token token = token_create(TOKEN_ATTRIBUTE, state); - token.attribute = tokenizer_buffer_to_name(buffer); - token.column = buffer->column; - token.line = buffer->line; - tokens_add(tokens, token); -} - tokens tokenize(const char *filename, const char *source) { mode mode = MODE_SELECT; @@ -230,9 +221,6 @@ tokens tokenize(const char *filename, const char *source) { case MODE_IDENTIFIER: tokens_add_identifier(&state, &tokens, &buffer); break; - case MODE_ATTRIBUTE: - tokens_add_attribute(&state, &tokens, &buffer); - break; case MODE_NUMBER: { token token = token_create(TOKEN_NUMBER, &state); token.number = tokenizer_buffer_parse_number(&buffer); @@ -274,21 +262,6 @@ tokens tokenize(const char *filename, const char *source) { } } } - else if (ch == '#') { - tokenizer_state_advance(&context, &state); - if (state.next >= 0) { - char ch = state.next; - if (ch != '[') { - error(context, "Expected ["); - } - } - else { - error(context, "Expected ["); - } - - mode = MODE_ATTRIBUTE; - tokenizer_buffer_reset(&buffer, &state); - } else if (is_num(ch)) { mode = MODE_NUMBER; tokenizer_buffer_reset(&buffer, &state); @@ -313,6 +286,9 @@ tokens tokenize(const char *filename, const char *source) { else if (ch == '}') { tokens_add(&tokens, token_create(TOKEN_RIGHT_CURLY, &state)); } + else if (ch == '#') { + tokens_add(&tokens, token_create(TOKEN_HASH, &state)); + } else if (ch == '[') { tokens_add(&tokens, token_create(TOKEN_LEFT_SQUARE, &state)); } @@ -524,18 +500,6 @@ tokens tokenize(const char *filename, const char *source) { } break; } - case MODE_ATTRIBUTE: { - if (ch == ']') { - tokens_add_attribute(&state, &tokens, &buffer); - tokenizer_state_advance(&context, &state); - mode = MODE_SELECT; - } - else { - tokenizer_buffer_add(&buffer, ch); - tokenizer_state_advance(&context, &state); - } - break; - } } } } diff --git a/Sources/tokenizer.h b/Sources/tokenizer.h index 0820406..0649cec 100644 --- a/Sources/tokenizer.h +++ b/Sources/tokenizer.h @@ -36,13 +36,13 @@ typedef struct token { TOKEN_NUMBER, // TOKEN_STRING, TOKEN_IDENTIFIER, - TOKEN_ATTRIBUTE, TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN, TOKEN_LEFT_CURLY, TOKEN_RIGHT_CURLY, TOKEN_LEFT_SQUARE, TOKEN_RIGHT_SQUARE, + TOKEN_HASH, TOKEN_IF, TOKEN_ELSE, TOKEN_WHILE, @@ -66,7 +66,6 @@ typedef struct token { double number; // char string[MAX_IDENTIFIER_SIZE]; name_id identifier; - name_id attribute; operatorr op; }; } token; diff --git a/Sources/types.c b/Sources/types.c index 293bedd..520f107 100644 --- a/Sources/types.c +++ b/Sources/types.c @@ -233,7 +233,7 @@ type_id add_type(name_id name) { ++next_type_index; types[s].name = name; - types[s].attribute = NO_NAME; + types[s].attributes.attributes_count = 0; types[s].members.size = 0; types[s].built_in = false; diff --git a/Sources/types.h b/Sources/types.h index d49fcbf..a4260ca 100644 --- a/Sources/types.h +++ b/Sources/types.h @@ -31,8 +31,37 @@ typedef struct members { size_t size; } members; +typedef struct attribute { + name_id name; + double parameters[16]; + uint8_t paramters_count; +} attribute; + +typedef struct attributes { + attribute attributes[64]; + uint8_t attributes_count; +} attribute_list; + +static bool has_attribute(attribute_list *attributes, name_id name) { + for (uint8_t index = 0; index < attributes->attributes_count; ++index) { + if (attributes->attributes[index].name == name) { + return true; + } + } + return false; +} + +static attribute *find_attribute(attribute_list *attributes, name_id name) { + for (uint8_t index = 0; index < attributes->attributes_count; ++index) { + if (attributes->attributes[index].name == name) { + return &attributes->attributes[index]; + } + } + return NULL; +} + typedef struct type { - name_id attribute; + attribute_list attributes; name_id name; members members; bool built_in;