Default result values for procedure types; Named result values in return statements

This commit is contained in:
Ginger Bill
2017-06-22 01:14:45 +01:00
parent 9faf0020cc
commit 8197c02dcf
10 changed files with 484 additions and 194 deletions
+72 -7
View File
@@ -1221,15 +1221,64 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) {
isize variable_index = 0;
for_array(i, results) {
ast_node(field, Field, results[i]);
Type *type = check_type(c, field->type);
AstNode *default_value = unparen_expr(field->default_value);
ExactValue value = {};
bool default_is_nil = false;
Type *type = NULL;
if (field->type == NULL) {
Operand o = {};
check_expr(c, &o, default_value);
if (is_operand_nil(o)) {
default_is_nil = true;
} else if (o.mode != Addressing_Constant) {
error(default_value, "Default parameter must be a constant");
} else {
value = o.value;
}
type = default_type(o.type);
} else {
type = check_type(c, field->type);
if (default_value != NULL) {
Operand o = {};
check_expr_with_type_hint(c, &o, default_value, type);
if (is_operand_nil(o)) {
default_is_nil = true;
} else if (o.mode != Addressing_Constant) {
error(default_value, "Default parameter must be a constant");
} else {
value = o.value;
}
check_is_assignable_to(c, &o, type);
}
}
if (type == NULL) {
error(results[i], "Invalid parameter type");
type = t_invalid;
}
if (is_type_untyped(type)) {
error(results[i], "Cannot determine parameter type from a nil");
type = t_invalid;
}
if (field->names.count == 0) {
Token token = ast_node_token(field->type);
token.string = str_lit("");
Entity *param = make_entity_param(c->allocator, scope, token, type, false, false);
param->Variable.default_value = value;
param->Variable.default_is_nil = default_is_nil;
variables[variable_index++] = param;
} else {
for_array(j, field->names) {
Token token = ast_node_token(field->type);
Token token = ast_node_token(results[i]);
if (field->type != NULL) {
token = ast_node_token(field->type);
}
token.string = str_lit("");
AstNode *name = field->names[j];
@@ -1240,6 +1289,8 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) {
}
Entity *param = make_entity_param(c->allocator, scope, token, type, false, false);
param->Variable.default_value = value;
param->Variable.default_is_nil = default_is_nil;
variables[variable_index++] = param;
}
}
@@ -5002,6 +5053,20 @@ isize lookup_procedure_parameter(TypeProc *pt, String parameter_name) {
}
return -1;
}
isize lookup_procedure_result(TypeProc *pt, String result_name) {
isize result_count = pt->result_count;
for (isize i = 0; i < result_count; i++) {
Entity *e = pt->results->Tuple.variables[i];
String name = e->token.string;
if (name == "_") {
continue;
}
if (name == result_name) {
return i;
}
}
return -1;
}
CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
ast_node(ce, CallExpr, call);
@@ -5013,7 +5078,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
CallArgumentError err = CallArgumentError_None;
isize param_count = pt->param_count;
bool *params_visited = gb_alloc_array(c->allocator, bool, param_count);
bool *visited = gb_alloc_array(c->allocator, bool, param_count);
for_array(i, ce->args) {
AstNode *arg = ce->args[i];
@@ -5036,7 +5101,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
err = CallArgumentError_ParameterNotFound;
continue;
}
if (params_visited[index]) {
if (visited[index]) {
if (show_error) {
error(arg, "Duplicate parameter `%.*s` in procedure call", LIT(name));
}
@@ -5044,7 +5109,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
continue;
}
params_visited[index] = true;
visited[index] = true;
Operand *o = &operands[i];
Entity *e = pt->params->Tuple.variables[index];
@@ -5076,7 +5141,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
param_count_to_check--;
}
for (isize i = 0; i < param_count_to_check; i++) {
if (!params_visited[i]) {
if (!visited[i]) {
Entity *e = pt->params->Tuple.variables[i];
if (e->token.string == "_") {
continue;
@@ -5095,7 +5160,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
if (show_error) {
gbString str = type_to_string(e->type);
error(call, "Parameter `%.*s` of type `%s` is missing in procedure call",
LIT(e->token.string), str);
LIT(e->token.string), str);
gb_string_free(str);
}
err = CallArgumentError_ParameterMissing;
+126 -22
View File
@@ -786,37 +786,141 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
break;
}
bool first_is_field_value = false;
if (rs->results.count > 0) {
bool fail = false;
first_is_field_value = (rs->results[0]->kind == AstNode_FieldValue);
for_array(i, rs->results) {
AstNode *arg = rs->results[i];
bool mix = false;
if (first_is_field_value) {
mix = arg->kind != AstNode_FieldValue;
} else {
mix = arg->kind == AstNode_FieldValue;
}
if (mix) {
error(arg, "Mixture of `field = value` and value elements in a procedure all is not allowed");
fail = true;
}
}
if (fail) {
return;
}
}
Type *proc_type = c->proc_stack[c->proc_stack.count-1];
TypeProc *pt = &proc_type->Proc;
isize result_count = 0;
if (proc_type->Proc.results) {
if (pt->results) {
result_count = proc_type->Proc.results->Tuple.variable_count;
}
if (result_count > 0) {
Entity **variables = NULL;
if (proc_type->Proc.results != NULL) {
TypeTuple *tuple = &proc_type->Proc.results->Tuple;
variables = tuple->variables;
isize result_count_excluding_defaults = result_count;
for (isize i = result_count-1; i >= 0; i--) {
Entity *e = pt->results->Tuple.variables[i];
if (e->kind == Entity_TypeName) {
break;
}
if (rs->results.count == 0) {
error(node, "Expected %td return values, got 0", result_count);
} else {
// TokenPos pos = rs->token.pos;
// if (pos.line == 10) {
// gb_printf_err("%s\n", type_to_string(variables[0]->type));
// }
check_init_variables(c, variables, result_count,
rs->results, str_lit("return statement"));
// if (pos.line == 10) {
// AstNode *x = rs->results[0];
// gb_printf_err("%s\n", expr_to_string(x));
// gb_printf_err("%s\n", type_to_string(type_of_expr(&c->info, x)));
// }
GB_ASSERT(e->kind == Entity_Variable);
if (e->Variable.default_value.kind != ExactValue_Invalid ||
e->Variable.default_is_nil) {
result_count_excluding_defaults--;
continue;
}
} else if (rs->results.count > 0) {
error(rs->results[0], "No return values expected");
break;
}
Array<Operand> operands = {};
defer (array_free(&operands));
if (first_is_field_value) {
array_init_count(&operands, heap_allocator(), rs->results.count);
for_array(i, rs->results) {
AstNode *arg = rs->results[i];
ast_node(fv, FieldValue, arg);
check_expr(c, &operands[i], fv->value);
}
} else {
array_init(&operands, heap_allocator(), 2*rs->results.count);
check_unpack_arguments(c, -1, &operands, rs->results, false);
}
if (first_is_field_value) {
bool *visited = gb_alloc_array(c->allocator, bool, result_count);
for_array(i, rs->results) {
AstNode *arg = rs->results[i];
ast_node(fv, FieldValue, arg);
if (fv->field->kind != AstNode_Ident) {
gbString expr_str = expr_to_string(fv->field);
error(arg, "Invalid parameter name `%s` in return statement", expr_str);
gb_string_free(expr_str);
continue;
}
String name = fv->field->Ident.string;
isize index = lookup_procedure_result(pt, name);
if (index < 0) {
error(arg, "No result named `%.*s` for this procedure type", LIT(name));
continue;
}
if (visited[index]) {
error(arg, "Duplicate result `%.*s` in return statement", LIT(name));
continue;
}
visited[index] = true;
Operand *o = &operands[i];
Entity *e = pt->results->Tuple.variables[index];
check_assignment(c, &operands[i], e->type, str_lit("return statement"));
}
for (isize i = 0; i < result_count; i++) {
if (!visited[i]) {
Entity *e = pt->results->Tuple.variables[i];
if (e->token.string == "_") {
continue;
}
GB_ASSERT(e->kind == Entity_Variable);
if (e->Variable.default_value.kind != ExactValue_Invalid) {
continue;
}
if (e->Variable.default_is_nil) {
continue;
}
gbString str = type_to_string(e->type);
error(node, "Return value `%.*s` of type `%s` is missing in return statement",
LIT(e->token.string), str);
gb_string_free(str);
}
}
} else {
// TODO(bill): Cleanup this checking of variables
if (result_count == 0 && rs->results.count > 0) {
error(rs->results[0], "No return values expected");
} else if (operands.count > result_count) {
error(node, "Expected a maximum of %td return values, got %td", result_count, operands.count);
} else if (operands.count < result_count_excluding_defaults) {
error(node, "Expected %td return values, got %td", result_count_excluding_defaults, operands.count);
} else if (result_count_excluding_defaults == 0) {
return;
} else if (rs->results.count == 0) {
error(node, "Expected %td return values, got 0", result_count_excluding_defaults);
} else {
isize max_count = rs->results.count;
for (isize i = 0; i < max_count; i++) {
Entity *e = pt->results->Tuple.variables[i];
check_assignment(c, &operands[i], e->type, str_lit("return statement"));
}
}
}
case_end;
case_ast_node(fs, ForStmt, node);
+33
View File
@@ -117,6 +117,39 @@ f64 float_from_string(String string) {
i++;
}
#if 0
if (len-i > 2 &&
str[i] == '0' &&
str[i+1] == 'h') {
i += 2;
u8 *text = string.text;
isize len = string.len;
if (has_prefix) {
text += 2;
len -= 2;
}
u64 base = 16;
u64 result = {0};
for (isize i = 0; i < len; i++) {
Rune r = cast(Rune)text[i];
if (r == '_') {
continue;
}
u64 v = bit128__digit_value(r);
if (v >= base) {
break;
}
result *= base;
result += v;
}
return *cast(f64 *)&result;
}
#endif
f64 value = 0.0;
for (; i < len; i++) {
Rune r = cast(Rune)str[i];
+82 -8
View File
@@ -6120,21 +6120,81 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
case_ast_node(rs, ReturnStmt, node);
ir_emit_comment(proc, str_lit("ReturnStmt"));
irValue *v = NULL;
TypeTuple *return_type_tuple = &proc->type->Proc.results->Tuple;
TypeTuple *tuple = &proc->type->Proc.results->Tuple;
isize return_count = proc->type->Proc.result_count;
if (return_count == 0) {
isize res_count = rs->results.count;
if (res_count > 0 &&
rs->results[0]->kind == AstNode_FieldValue) {
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
defer (gb_temp_arena_memory_end(tmp));
Array<irValue *> results;
array_init_count(&results, proc->module->tmp_allocator, return_count);
for_array(arg_index, rs->results) {
AstNode *arg = rs->results[arg_index];
ast_node(fv, FieldValue, arg);
GB_ASSERT(fv->field->kind == AstNode_Ident);
String name = fv->field->Ident.string;
isize index = lookup_procedure_result(&proc->type->Proc, name);
GB_ASSERT(index >= 0);
irValue *expr = ir_build_expr(proc, fv->value);
results[index] = expr;
}
for (isize i = 0; i < return_count; i++) {
Entity *e = tuple->variables[i];
GB_ASSERT(e->kind == Entity_Variable);
if (results[i] == NULL) {
if (e->Variable.default_value.kind != ExactValue_Invalid) {
results[i] = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
} else {
results[i] = ir_value_nil(proc->module->allocator, e->type);
}
} else {
results[i] = ir_emit_conv(proc, results[i], e->type);
}
}
if (results.count == 1) {
v = results[0];
} else {
GB_ASSERT(results.count == return_count);
Type *ret_type = proc->type->Proc.results;
v = ir_add_local_generated(proc, ret_type);
for_array(i, results) {
irValue *field = ir_emit_struct_ep(proc, v, i);
irValue *res = results[i];
ir_emit_store(proc, field, res);
}
v = ir_emit_load(proc, v);
}
} else if (return_count == 0) {
// No return values
} else if (return_count == 1) {
Entity *e = return_type_tuple->variables[0];
v = ir_build_expr(proc, rs->results[0]);
v = ir_emit_conv(proc, v, e->type);
Entity *e = tuple->variables[0];
if (res_count == 0) {
if (e->Variable.default_value.kind != ExactValue_Invalid) {
v = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
} else {
v = ir_value_nil(proc->module->allocator, e->type);
}
} else {
v = ir_build_expr(proc, rs->results[0]);
v = ir_emit_conv(proc, v, e->type);
}
} else {
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
defer (gb_temp_arena_memory_end(tmp));
Array<irValue *> results;
array_init(&results, proc->module->tmp_allocator, return_count);
for_array(res_index, rs->results) {
isize total_index = 0;
isize res_index = 0;
for (; res_index < res_count; res_index++) {
irValue *res = ir_build_expr(proc, rs->results[res_index]);
Type *t = ir_type(res);
if (t->kind == Type_Tuple) {
@@ -6142,16 +6202,31 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
Entity *e = t->Tuple.variables[i];
irValue *v = ir_emit_struct_ev(proc, res, i);
array_add(&results, v);
total_index++;
}
} else {
array_add(&results, res);
total_index++;
}
}
while (total_index < return_count) {
Entity *e = tuple->variables[total_index];
irValue *res = NULL;
if (e->Variable.default_value.kind != ExactValue_Invalid) {
res = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
} else {
res = ir_value_nil(proc->module->allocator, e->type);
}
array_add(&results, res);
total_index++;
}
GB_ASSERT(results.count == return_count);
Type *ret_type = proc->type->Proc.results;
v = ir_add_local_generated(proc, ret_type);
for_array(i, results) {
Entity *e = return_type_tuple->variables[i];
Entity *e = tuple->variables[i];
irValue *res = ir_emit_conv(proc, results[i], e->type);
irValue *field = ir_emit_struct_ep(proc, v, i);
ir_emit_store(proc, field, res);
@@ -6159,7 +6234,6 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
v = ir_emit_load(proc, v);
gb_temp_arena_memory_end(tmp);
}
ir_emit_return(proc, v);
+90 -25
View File
@@ -3158,7 +3158,7 @@ AstNode *parse_block_stmt(AstFile *f, b32 is_when) {
return parse_body(f);
}
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow);
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow, bool allow_default_parameters);
AstNode *parse_results(AstFile *f) {
@@ -3170,7 +3170,7 @@ AstNode *parse_results(AstFile *f) {
CommentGroup empty_group = {};
Token begin_token = f->curr_token;
Array<AstNode *> empty_names = {};
Array<AstNode *> list = make_ast_node_array(f);
Array<AstNode *> list = make_ast_node_array(f, 1);
AstNode *type = parse_type(f);
array_add(&list, ast_field(f, empty_names, type, NULL, 0, empty_group, empty_group));
return ast_field_list(f, begin_token, list);
@@ -3178,7 +3178,7 @@ AstNode *parse_results(AstFile *f) {
AstNode *list = NULL;
expect_token(f, Token_OpenParen);
list = parse_field_list(f, NULL, 0, Token_CloseParen);
list = parse_field_list(f, NULL, 0, Token_CloseParen, true);
expect_token_after(f, Token_CloseParen, "parameter list");
return list;
}
@@ -3188,7 +3188,7 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) {
AstNode *results = NULL;
expect_token(f, Token_OpenParen);
params = parse_field_list(f, NULL, FieldFlag_Signature, Token_CloseParen);
params = parse_field_list(f, NULL, FieldFlag_Signature, Token_CloseParen, true);
expect_token_after(f, Token_CloseParen, "parameter list");
results = parse_results(f);
@@ -3357,7 +3357,7 @@ bool parse_expect_field_separator(AstFile *f, AstNode *param) {
return false;
}
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow) {
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow, bool allow_default_parameters) {
TokenKind separator = Token_Comma;
Token start_token = f->curr_token;
@@ -3370,13 +3370,12 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
isize total_name_count = 0;
bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis;
bool is_procedure = allowed_flags == FieldFlag_Signature;
while (f->curr_token.kind != follow &&
f->curr_token.kind != Token_Colon &&
f->curr_token.kind != Token_EOF) {
u32 flags = parse_field_prefixes(f);
AstNode *param = parse_var_type(f, allow_ellipsis, is_procedure);
AstNode *param = parse_var_type(f, allow_ellipsis, allow_default_parameters);
AstNodeAndFlags naf = {param, flags};
array_add(&list, naf);
if (f->curr_token.kind != Token_Comma) {
@@ -3403,12 +3402,12 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
if (f->curr_token.kind != Token_Eq) {
expect_token_after(f, Token_Colon, "field list");
type = parse_var_type(f, allow_ellipsis, is_procedure);
type = parse_var_type(f, allow_ellipsis, allow_default_parameters);
}
if (allow_token(f, Token_Eq)) {
// TODO(bill): Should this be true==lhs or false==rhs?
default_value = parse_expr(f, false);
if (!is_procedure) {
if (!allow_default_parameters) {
syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
}
}
@@ -3439,12 +3438,12 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
AstNode *default_value = NULL;
if (f->curr_token.kind != Token_Eq) {
expect_token_after(f, Token_Colon, "field list");
type = parse_var_type(f, allow_ellipsis, is_procedure);
type = parse_var_type(f, allow_ellipsis, allow_default_parameters);
}
if (allow_token(f, Token_Eq)) {
// TODO(bill): Should this be true==lhs or false==rhs?
default_value = parse_expr(f, false);
if (!is_procedure) {
if (!allow_default_parameters) {
syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
}
}
@@ -3486,7 +3485,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
AstNode *parse_record_fields(AstFile *f, isize *field_count_, u32 flags, String context) {
return parse_field_list(f, field_count_, flags, Token_CloseBrace);
return parse_field_list(f, field_count_, flags, Token_CloseBrace, false);
}
AstNode *parse_type_or_ident(AstFile *f) {
@@ -3821,7 +3820,14 @@ AstNode *parse_if_stmt(AstFile *f) {
syntax_error(f->curr_token, "Expected condition for if statement");
}
body = parse_block_stmt(f, false);
if (allow_token(f, Token_ArrowRight)) {
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
}
} else {
body = parse_block_stmt(f, false);
}
if (allow_token(f, Token_else)) {
switch (f->curr_token.kind) {
@@ -3831,6 +3837,13 @@ AstNode *parse_if_stmt(AstFile *f) {
case Token_OpenBrace:
else_stmt = parse_block_stmt(f, false);
break;
case Token_ArrowRight: {
Token arrow = expect_token(f, Token_ArrowRight);
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
}
} break;
default:
syntax_error(f->curr_token, "Expected if statement block statement");
else_stmt = ast_bad_stmt(f, f->curr_token, f->tokens[f->curr_token_index+1]);
@@ -3858,7 +3871,14 @@ AstNode *parse_when_stmt(AstFile *f) {
syntax_error(f->curr_token, "Expected condition for when statement");
}
body = parse_block_stmt(f, true);
if (allow_token(f, Token_ArrowRight)) {
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
}
} else {
body = parse_block_stmt(f, true);
}
if (allow_token(f, Token_else)) {
switch (f->curr_token.kind) {
@@ -3868,6 +3888,13 @@ AstNode *parse_when_stmt(AstFile *f) {
case Token_OpenBrace:
else_stmt = parse_block_stmt(f, true);
break;
case Token_ArrowRight: {
Token arrow = expect_token(f, Token_ArrowRight);
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
}
} break;
default:
syntax_error(f->curr_token, "Expected when statement block statement");
else_stmt = ast_bad_stmt(f, f->curr_token, f->tokens[f->curr_token_index+1]);
@@ -3890,11 +3917,22 @@ AstNode *parse_return_stmt(AstFile *f) {
}
Token token = expect_token(f, Token_return);
Array<AstNode *> results;
if (f->curr_token.kind != Token_Semicolon && f->curr_token.kind != Token_CloseBrace) {
results = parse_rhs_expr_list(f);
} else {
results = make_ast_node_array(f);
Array<AstNode *> results = make_ast_node_array(f);
while (f->curr_token.kind != Token_Semicolon) {
AstNode *arg = parse_expr(f, false);
if (f->curr_token.kind == Token_Eq) {
Token eq = expect_token(f, Token_Eq);
AstNode *value = parse_value(f);
arg = ast_field_value(f, arg, value, eq);
}
array_add(&results, arg);
if (f->curr_token.kind != Token_Comma ||
f->curr_token.kind == Token_EOF) {
break;
}
next_token(f);
}
AstNode *end = NULL;
@@ -3952,7 +3990,8 @@ AstNode *parse_for_stmt(AstFile *f) {
}
}
if (!is_range && f->curr_token.kind == Token_Semicolon) {
if (!is_range && (f->curr_token.kind == Token_Semicolon ||
f->curr_token.kind == Token_ArrowRight)) {
next_token(f);
init = cond;
cond = NULL;
@@ -3960,7 +3999,8 @@ AstNode *parse_for_stmt(AstFile *f) {
cond = parse_simple_stmt(f, StmtAllowFlag_None);
}
expect_semicolon(f, cond);
if (f->curr_token.kind != Token_OpenBrace) {
if (f->curr_token.kind != Token_OpenBrace &&
f->curr_token.kind != Token_ArrowRight) {
post = parse_simple_stmt(f, StmtAllowFlag_None);
}
}
@@ -3968,7 +4008,14 @@ AstNode *parse_for_stmt(AstFile *f) {
f->expr_level = prev_level;
}
body = parse_block_stmt(f, false);
if (allow_token(f, Token_ArrowRight)) {
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
}
} else {
body = parse_block_stmt(f, false);
}
if (is_range) {
GB_ASSERT(cond->kind == AstNode_AssignStmt);
@@ -4002,7 +4049,7 @@ AstNode *parse_for_stmt(AstFile *f) {
AstNode *parse_case_clause(AstFile *f, bool is_type) {
Token token = f->curr_token;
Array<AstNode *> list = make_ast_node_array(f);
Array<AstNode *> list = {};
expect_token(f, Token_case);
bool prev_allow_range = f->allow_range;
f->allow_range = !is_type;
@@ -4224,23 +4271,41 @@ AstNode *parse_stmt(AstFile *f) {
case Token_push_allocator: {
next_token(f);
AstNode *body = NULL;
isize prev_level = f->expr_level;
f->expr_level = -1;
AstNode *expr = parse_expr(f, false);
f->expr_level = prev_level;
AstNode *body = parse_block_stmt(f, false);
if (allow_token(f, Token_ArrowRight)) {
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
}
} else {
body = parse_block_stmt(f, false);
}
return ast_push_allocator(f, token, expr, body);
} break;
case Token_push_context: {
next_token(f);
AstNode *body = NULL;
isize prev_level = f->expr_level;
f->expr_level = -1;
AstNode *expr = parse_expr(f, false);
f->expr_level = prev_level;
AstNode *body = parse_block_stmt(f, false);
if (allow_token(f, Token_ArrowRight)) {
body = parse_stmt(f);
if (body->kind == AstNode_BlockStmt) {
syntax_error(body, "Expected a normal statement rather than a block statement");
}
} else {
body = parse_block_stmt(f, false);
}
return ast_push_context(f, token, expr, body);
} break;
+8 -1
View File
@@ -546,7 +546,14 @@ Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
}
} else {
} /* else if (t->curr_rune == 'h') { // Hexadecimal Float
token.kind = Token_Float;
advance_to_next_rune(t);
scan_mantissa(t, 16);
if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
}
} */ else {
seen_decimal_point = false;
scan_mantissa(t, 10);