diff --git a/Sources/compiler.c b/Sources/compiler.c index b935087..39f9fd5 100644 --- a/Sources/compiler.c +++ b/Sources/compiler.c @@ -425,7 +425,7 @@ variable emit_expression(opcodes *code, block *parent, expression *e) { return v; } - case EXPRESSION_NUMBER: { + case EXPRESSION_FLOAT: { type_ref t; init_type_ref(&t, NO_NAME); t.type = float_id; @@ -440,6 +440,21 @@ variable emit_expression(opcodes *code, block *parent, expression *e) { return v; } + case EXPRESSION_INT: { + type_ref t; + init_type_ref(&t, NO_NAME); + t.type = float_id; + variable v = allocate_variable(t, VARIABLE_LOCAL); + + opcode o; + o.type = OPCODE_LOAD_INT_CONSTANT; + o.size = OP_SIZE(o, op_load_float_constant); + o.op_load_int_constant.number = (int)e->number; + o.op_load_int_constant.to = v; + emit_op(code, &o); + + return v; + } // case EXPRESSION_STRING: // error("not implemented", 0, 0); case EXPRESSION_VARIABLE: { diff --git a/Sources/compiler.h b/Sources/compiler.h index 5e0d108..ee9c58a 100644 --- a/Sources/compiler.h +++ b/Sources/compiler.h @@ -29,6 +29,7 @@ typedef struct opcode { OPCODE_DIVIDE_AND_STORE_MEMBER, OPCODE_MULTIPLY_AND_STORE_MEMBER, OPCODE_LOAD_FLOAT_CONSTANT, + OPCODE_LOAD_INT_CONSTANT, OPCODE_LOAD_BOOL_CONSTANT, OPCODE_LOAD_MEMBER, OPCODE_RETURN, @@ -81,6 +82,10 @@ typedef struct opcode { float number; variable to; } op_load_float_constant; + struct { + int number; + variable to; + } op_load_int_constant; struct { bool boolean; variable to; diff --git a/Sources/kong.c b/Sources/kong.c index dcc3271..52ab154 100644 --- a/Sources/kong.c +++ b/Sources/kong.c @@ -164,6 +164,16 @@ static bool types_compatible(type_id left, type_id right) { return true; } + if ((left == float_id && right == float2_id) || (left == float_id && right == float3_id) || (left == float_id && right == float4_id) || + (left == float2_id && right == float_id) || (left == float3_id && right == float_id) || (left == float4_id && right == float_id)) { + return true; + } + + if ((left == int_id && right == int2_id) || (left == int_id && right == int3_id) || (left == int_id && right == int4_id) || + (left == int2_id && right == int_id) || (left == int3_id && right == int_id) || (left == int4_id && right == int_id)) { + return true; + } + return false; } @@ -250,6 +260,22 @@ static type_ref upgrade_type(type_ref left_type, type_ref right_type) { return left_type; } + if ((left == float2_id && right == float_id) || (left == float3_id && right == float_id) || (left == float4_id && right == float_id)) { + return left_type; + } + + if ((left == float_id && right == float2_id) || (left == float_id && right == float3_id) || (left == float_id && right == float4_id)) { + return right_type; + } + + if ((left == int2_id && right == int_id) || (left == int3_id && right == int_id) || (left == int4_id && right == int_id)) { + return left_type; + } + + if ((left == int_id && right == int2_id) || (left == int_id && right == int3_id) || (left == int_id && right == int4_id)) { + return right_type; + } + kong_log(LOG_LEVEL_WARNING, "Suspicious type upgrade"); return left_type; } @@ -360,10 +386,14 @@ void resolve_types_in_expression(statement *parent, expression *e) { e->type.type = bool_id; break; } - case EXPRESSION_NUMBER: { + case EXPRESSION_FLOAT: { e->type.type = float_id; break; } + case EXPRESSION_INT: { + e->type.type = int_id; + break; + } case EXPRESSION_VARIABLE: { global *g = find_global(e->variable); if (g != NULL && g->type != NO_TYPE) { diff --git a/Sources/parser.c b/Sources/parser.c index 2bc140c..c70bd08 100644 --- a/Sources/parser.c +++ b/Sources/parser.c @@ -198,7 +198,7 @@ static definition parse_definition(state_t *state) { current_attribute.paramters_count += 1; advance_state(state); } - else if (current(state).kind == TOKEN_NUMBER) { + else if (current(state).kind == TOKEN_FLOAT || current(state).kind == TOKEN_INT) { current_attribute.parameters[current_attribute.paramters_count] = current(state).number; current_attribute.paramters_count += 1; advance_state(state); @@ -276,7 +276,7 @@ static type_ref parse_type_ref(state_t *state) { uint32_t array_size = 0; if (current(state).kind == TOKEN_LEFT_SQUARE) { advance_state(state); - match_token(state, TOKEN_NUMBER, "Expected a number"); + match_token(state, TOKEN_INT, "Expected an integer"); array_size = (uint32_t)current(state).number; advance_state(state); match_token(state, TOKEN_RIGHT_SQUARE, "Expected a closing square bracket"); @@ -724,7 +724,7 @@ static expression *parse_member(state_t *state, bool square) { return var; } } - else if (current(state).kind == TOKEN_NUMBER && square) { + else if (current(state).kind == TOKEN_INT && square) { uint32_t index = (uint32_t)current(state).number; advance_state(state); match_token(state, TOKEN_RIGHT_SQUARE, "Expected a closing square bracket"); @@ -792,11 +792,19 @@ static expression *parse_primary(state_t *state) { left->boolean = value; break; } - case TOKEN_NUMBER: { + case TOKEN_FLOAT: { double value = current(state).number; advance_state(state); left = expression_allocate(); - left->kind = EXPRESSION_NUMBER; + left->kind = EXPRESSION_FLOAT; + left->number = value; + break; + } + case TOKEN_INT: { + double value = current(state).number; + advance_state(state); + left = expression_allocate(); + left->kind = EXPRESSION_INT; left->number = value; break; } @@ -842,7 +850,7 @@ static expression *parse_primary(state_t *state) { advance_state(state); - bool dynamic = square && current(state).kind != TOKEN_NUMBER; + bool dynamic = square && current(state).kind != TOKEN_INT; expression *right = parse_member(state, square); @@ -904,7 +912,7 @@ static expression *parse_call(state_t *state, name_id func_name) { advance_state(state); - bool dynamic = square && current(state).kind != TOKEN_NUMBER; + bool dynamic = square && current(state).kind != TOKEN_INT; expression *right = parse_member(state, square); @@ -959,7 +967,8 @@ static definition parse_struct_inner(state_t *state, name_id name) { if (current(state).kind == TOKEN_OPERATOR && current(state).op == OPERATOR_ASSIGN) { advance_state(state); - if (current(state).kind == TOKEN_BOOLEAN || current(state).kind == TOKEN_NUMBER || current(state).kind == TOKEN_IDENTIFIER) { + if (current(state).kind == TOKEN_BOOLEAN || current(state).kind == TOKEN_FLOAT || current(state).kind == TOKEN_INT || + current(state).kind == TOKEN_IDENTIFIER) { member_values[count] = current(state); advance_state(state); } @@ -997,9 +1006,12 @@ static definition parse_struct_inner(state_t *state, name_id name) { if (member.value.kind == TOKEN_BOOLEAN) { init_type_ref(&member.type, add_name("bool")); } - else if (member.value.kind == TOKEN_NUMBER) { + else if (member.value.kind == TOKEN_FLOAT) { init_type_ref(&member.type, add_name("float")); } + else if (member.value.kind == TOKEN_INT) { + init_type_ref(&member.type, add_name("int")); + } else if (member.value.kind == TOKEN_IDENTIFIER) { global *g = find_global(member.value.identifier); if (g != NULL && g->name != NO_NAME) { @@ -1142,7 +1154,7 @@ static definition parse_const(state_t *state, attribute_list attributes) { else if (type_name == add_name("float")) { debug_context context = {0}; check(value != NULL, context, "const float requires an initialization value"); - check(value->kind == EXPRESSION_NUMBER, context, "const float3 requires a number"); + check(value->kind == EXPRESSION_FLOAT || value->kind == EXPRESSION_INT, context, "const float3 requires a number"); global_value float_value; float_value.kind = GLOBAL_VALUE_FLOAT; @@ -1163,7 +1175,8 @@ static definition parse_const(state_t *state, attribute_list attributes) { float2_value.kind = GLOBAL_VALUE_FLOAT2; for (int i = 0; i < 2; ++i) { - check(value->call.parameters.e[i]->kind == EXPRESSION_NUMBER, context, "const float2 construtor parameters have to be numbers"); + check(value->call.parameters.e[i]->kind == EXPRESSION_FLOAT || value->call.parameters.e[i]->kind == EXPRESSION_INT, context, + "const float2 construtor parameters have to be numbers"); float2_value.value.floats[i] = (float)value->call.parameters.e[i]->number; } @@ -1181,7 +1194,8 @@ static definition parse_const(state_t *state, attribute_list attributes) { float3_value.kind = GLOBAL_VALUE_FLOAT3; for (int i = 0; i < 3; ++i) { - check(value->call.parameters.e[i]->kind == EXPRESSION_NUMBER, context, "const float3 construtor parameters have to be numbers"); + check(value->call.parameters.e[i]->kind == EXPRESSION_FLOAT || value->call.parameters.e[i]->kind == EXPRESSION_INT, context, + "const float3 construtor parameters have to be numbers"); float3_value.value.floats[i] = (float)value->call.parameters.e[i]->number; } @@ -1199,7 +1213,8 @@ static definition parse_const(state_t *state, attribute_list attributes) { float4_value.kind = GLOBAL_VALUE_FLOAT4; for (int i = 0; i < 4; ++i) { - check(value->call.parameters.e[i]->kind == EXPRESSION_NUMBER, context, "const float4 construtor parameters have to be numbers"); + check(value->call.parameters.e[i]->kind == EXPRESSION_FLOAT || value->call.parameters.e[i]->kind == EXPRESSION_INT, context, + "const float4 construtor parameters have to be numbers"); float4_value.value.floats[i] = (float)value->call.parameters.e[i]->number; } diff --git a/Sources/parser.h b/Sources/parser.h index 81989a1..e099263 100644 --- a/Sources/parser.h +++ b/Sources/parser.h @@ -21,7 +21,8 @@ typedef struct expression { EXPRESSION_BINARY, EXPRESSION_UNARY, EXPRESSION_BOOLEAN, - EXPRESSION_NUMBER, + EXPRESSION_FLOAT, + EXPRESSION_INT, // EXPRESSION_STRING, EXPRESSION_VARIABLE, EXPRESSION_GROUPING, diff --git a/Sources/tokenizer.c b/Sources/tokenizer.c index b8c3532..4e6a673 100644 --- a/Sources/tokenizer.c +++ b/Sources/tokenizer.c @@ -202,6 +202,7 @@ static void tokens_add_identifier(tokenizer_state *state, tokens *tokens, tokeni tokens tokenize(const char *filename, const char *source) { mode mode = MODE_SELECT; + bool number_has_dot = false; tokens tokens; tokens_init(&tokens); @@ -222,7 +223,7 @@ tokens tokenize(const char *filename, const char *source) { tokens_add_identifier(&state, &tokens, &buffer); break; case MODE_NUMBER: { - token token = token_create(TOKEN_NUMBER, &state); + token token = token_create(number_has_dot ? TOKEN_FLOAT : TOKEN_INT, &state); token.number = tokenizer_buffer_parse_number(&buffer); tokens_add(&tokens, token); break; @@ -264,6 +265,7 @@ tokens tokenize(const char *filename, const char *source) { } else if (is_num(ch, state.next_next)) { mode = MODE_NUMBER; + number_has_dot = false; tokenizer_buffer_reset(&buffer, &state); tokenizer_buffer_add(&buffer, ch); } @@ -342,11 +344,14 @@ tokens tokenize(const char *filename, const char *source) { } case MODE_NUMBER: { if (is_num(ch, 0) || ch == '.') { + if (ch == '.') { + number_has_dot = true; + } tokenizer_buffer_add(&buffer, ch); tokenizer_state_advance(&context, &state); } else { - token token = token_create(TOKEN_NUMBER, &state); + token token = token_create(number_has_dot ? TOKEN_FLOAT : TOKEN_INT, &state); token.number = tokenizer_buffer_parse_number(&buffer); tokens_add(&tokens, token); mode = MODE_SELECT; diff --git a/Sources/tokenizer.h b/Sources/tokenizer.h index 0649cec..fef1d1d 100644 --- a/Sources/tokenizer.h +++ b/Sources/tokenizer.h @@ -33,7 +33,8 @@ typedef struct token { enum { TOKEN_NONE, TOKEN_BOOLEAN, - TOKEN_NUMBER, + TOKEN_FLOAT, + TOKEN_INT, // TOKEN_STRING, TOKEN_IDENTIFIER, TOKEN_LEFT_PAREN,