Named return values but do not affect other declarations

This commit is contained in:
Ginger Bill
2017-02-18 12:02:11 +00:00
parent d2f9d20833
commit 9ff474f387
4 changed files with 177 additions and 124 deletions
+7 -2
View File
@@ -293,7 +293,7 @@ sprintf :: proc(buf: []byte, fmt: string, args: ...any) -> string {
parse_int :: proc(s: string, offset: int) -> (int, int, bool) { parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: bool) {
is_digit :: proc(r: rune) -> bool #inline { is_digit :: proc(r: rune) -> bool #inline {
return '0' <= r && r <= '9'; return '0' <= r && r <= '9';
} }
@@ -316,7 +316,12 @@ parse_int :: proc(s: string, offset: int) -> (int, int, bool) {
return result, offset+i, i != 0; return result, offset+i, i != 0;
} }
_arg_number :: proc(fi: ^Fmt_Info, arg_index: int, format: string, offset: int, arg_count: int) -> (int, int, bool) { _arg_number :: proc(fi: ^Fmt_Info,
arg_index: int,
format: string,
offset: int,
arg_count: int,
) -> (index: int, offset: int, ok: bool) {
parse_arg_number :: proc(format: string) -> (int, int, bool) { parse_arg_number :: proc(format: string) -> (int, int, bool) {
if format.count < 3 { if format.count < 3 {
return 0, 1, false; return 0, 1, false;
+92 -27
View File
@@ -798,7 +798,13 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
} }
Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_variadic_) { Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_variadic_) {
if (_params == NULL) {
return NULL;
}
ast_node(field_list, FieldList, _params);
AstNodeArray params = field_list->list;
if (params.count == 0) { if (params.count == 0) {
return NULL; return NULL;
} }
@@ -808,7 +814,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_v
AstNode *field = params.e[i]; AstNode *field = params.e[i];
if (ast_node_expect(field, AstNode_Field)) { if (ast_node_expect(field, AstNode_Field)) {
ast_node(f, Field, field); ast_node(f, Field, field);
variable_count += f->names.count; variable_count += max(f->names.count, 1);
} }
} }
@@ -877,26 +883,73 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_v
return tuple; return tuple;
} }
Type *check_get_results(Checker *c, Scope *scope, AstNodeArray results) { Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) {
if (_results == NULL) {
return NULL;
}
ast_node(field_list, FieldList, _results);
AstNodeArray results = field_list->list;
if (results.count == 0) { if (results.count == 0) {
return NULL; return NULL;
} }
Type *tuple = make_type_tuple(c->allocator); Type *tuple = make_type_tuple(c->allocator);
Entity **variables = gb_alloc_array(c->allocator, Entity *, results.count); isize variable_count = 0;
for_array(i, results) {
AstNode *field = results.e[i];
if (ast_node_expect(field, AstNode_Field)) {
ast_node(f, Field, field);
variable_count += max(f->names.count, 1);
}
}
Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count);
isize variable_index = 0; isize variable_index = 0;
for_array(i, results) { for_array(i, results) {
AstNode *item = results.e[i]; ast_node(field, Field, results.e[i]);
Type *type = check_type(c, item); Type *type = check_type(c, field->type);
Token token = ast_node_token(item); if (field->names.count == 0) {
token.string = str_lit(""); // NOTE(bill): results are not named Token token = ast_node_token(field->type);
// TODO(bill): Should I have named results? token.string = str_lit("");
Entity *param = make_entity_param(c->allocator, scope, token, type, false, false); Entity *param = make_entity_param(c->allocator, scope, token, type, false, false);
// NOTE(bill): No need to record variables[variable_index++] = param;
variables[variable_index++] = param; } else {
for_array(j, field->names) {
Token token = ast_node_token(field->type);
token.string = str_lit("");
AstNode *name = field->names.e[j];
if (name->kind != AstNode_Ident) {
error_node(name, "Expected an identifer for as the field name");
} else {
token = name->Ident;
}
Entity *param = make_entity_param(c->allocator, scope, token, type, false, false);
variables[variable_index++] = param;
}
}
} }
for (isize i = 0; i < variable_index; i++) {
String x = variables[i]->token.string;
if (x.len == 0 || str_eq(x, str_lit("_"))) {
continue;
}
for (isize j = i+1; j < variable_index; j++) {
String y = variables[j]->token.string;
if (y.len == 0 || str_eq(y, str_lit("_"))) {
continue;
}
if (str_eq(x, y)) {
error(variables[j]->token, "Duplicate return value name `%.*s`", LIT(y));
}
}
}
tuple->Tuple.variables = variables; tuple->Tuple.variables = variables;
tuple->Tuple.variable_count = results.count; tuple->Tuple.variable_count = variable_index;
return tuple; return tuple;
} }
@@ -5126,16 +5179,6 @@ void check_expr_or_type(Checker *c, Operand *o, AstNode *e) {
gbString write_expr_to_string(gbString str, AstNode *node); gbString write_expr_to_string(gbString str, AstNode *node);
gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) {
for_array(i, params) {
if (i > 0) {
str = gb_string_appendc(str, sep);
}
str = write_expr_to_string(str, params.e[i]);
}
return str;
}
gbString write_record_fields_to_string(gbString str, AstNodeArray params) { gbString write_record_fields_to_string(gbString str, AstNodeArray params) {
for_array(i, params) { for_array(i, params) {
if (i > 0) { if (i > 0) {
@@ -5301,6 +5344,13 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
if (f->flags&FieldFlag_using) { if (f->flags&FieldFlag_using) {
str = gb_string_appendc(str, "using "); str = gb_string_appendc(str, "using ");
} }
if (f->flags&FieldFlag_immutable) {
str = gb_string_appendc(str, "immutable ");
}
if (f->flags&FieldFlag_no_alias) {
str = gb_string_appendc(str, "no_alias ");
}
for_array(i, f->names) { for_array(i, f->names) {
AstNode *name = f->names.e[i]; AstNode *name = f->names.e[i];
if (i > 0) { if (i > 0) {
@@ -5308,14 +5358,24 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
} }
str = write_expr_to_string(str, name); str = write_expr_to_string(str, name);
} }
if (f->names.count > 0) {
str = gb_string_appendc(str, ": "); str = gb_string_appendc(str, ": ");
}
if (f->flags&FieldFlag_ellipsis) { if (f->flags&FieldFlag_ellipsis) {
str = gb_string_appendc(str, "..."); str = gb_string_appendc(str, "...");
} }
str = write_expr_to_string(str, f->type); str = write_expr_to_string(str, f->type);
case_end; case_end;
case_ast_node(f, FieldList, node);
for_array(i, f->list) {
if (i > 0) {
str = gb_string_appendc(str, ", ");
}
str = write_expr_to_string(str, f->list.e[i]);
}
case_end;
case_ast_node(ce, CallExpr, node); case_ast_node(ce, CallExpr, node);
str = write_expr_to_string(str, ce->proc); str = write_expr_to_string(str, ce->proc);
str = gb_string_appendc(str, "("); str = gb_string_appendc(str, "(");
@@ -5332,7 +5392,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
case_ast_node(pt, ProcType, node); case_ast_node(pt, ProcType, node);
str = gb_string_appendc(str, "proc("); str = gb_string_appendc(str, "proc(");
str = write_params_to_string(str, pt->params, ", "); str = write_expr_to_string(str, pt->params);
str = gb_string_appendc(str, ")"); str = gb_string_appendc(str, ")");
case_end; case_end;
@@ -5366,7 +5426,12 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = gb_string_appendc(str, " "); str = gb_string_appendc(str, " ");
} }
str = gb_string_appendc(str, "{"); str = gb_string_appendc(str, "{");
str = write_params_to_string(str, et->fields, ", "); for_array(i, et->fields) {
if (i > 0) {
str = gb_string_appendc(str, ", ");
}
str = write_expr_to_string(str, et->fields.e[i]);
}
str = gb_string_appendc(str, "}"); str = gb_string_appendc(str, "}");
case_end; case_end;
+5 -3
View File
@@ -5600,12 +5600,14 @@ void ir_begin_procedure_body(irProcedure *proc) {
TypeTuple *params = &proc->type->Proc.params->Tuple; TypeTuple *params = &proc->type->Proc.params->Tuple;
for (isize i = 0; i < params->variable_count; i++) { for (isize i = 0; i < params->variable_count; i++) {
GB_ASSERT(pt->params.e[0]->kind == AstNode_Field); ast_node(fl, FieldList, pt->params);
if (q_index == pt->params.e[param_index]->Field.names.count) { GB_ASSERT(fl->list.count > 0);
GB_ASSERT(fl->list.e[0]->kind == AstNode_Field);
if (q_index == fl->list.e[param_index]->Field.names.count) {
q_index = 0; q_index = 0;
param_index++; param_index++;
} }
ast_node(field, Field, pt->params.e[param_index]); ast_node(field, Field, fl->list.e[param_index]);
AstNode *name = field->names.e[q_index++]; AstNode *name = field->names.e[q_index++];
Entity *e = params->variables[i]; Entity *e = params->variables[i];
+73 -92
View File
@@ -302,16 +302,20 @@ AST_NODE_KIND(_DeclEnd, "", i32) \
AstNode * type; \ AstNode * type; \
u32 flags; \ u32 flags; \
}) \ }) \
AST_NODE_KIND(FieldList, "field list", struct { \
Token token; \
AstNodeArray list; \
}) \
AST_NODE_KIND(_TypeBegin, "", i32) \ AST_NODE_KIND(_TypeBegin, "", i32) \
AST_NODE_KIND(HelperType, "type", struct { \ AST_NODE_KIND(HelperType, "type", struct { \
Token token; \ Token token; \
AstNode *type; \ AstNode *type; \
}) \ }) \
AST_NODE_KIND(ProcType, "procedure type", struct { \ AST_NODE_KIND(ProcType, "procedure type", struct { \
Token token; \ Token token; \
AstNodeArray params; \ AstNode *params; \
AstNodeArray results; \ AstNode *results; \
u64 tags; \ u64 tags; \
ProcCallingConvention calling_convention; \ ProcCallingConvention calling_convention; \
}) \ }) \
AST_NODE_KIND(PointerType, "pointer type", struct { \ AST_NODE_KIND(PointerType, "pointer type", struct { \
@@ -478,11 +482,14 @@ Token ast_node_token(AstNode *node) {
case AstNode_ImportDecl: return node->ImportDecl.token; case AstNode_ImportDecl: return node->ImportDecl.token;
case AstNode_ForeignLibrary: return node->ForeignLibrary.token; case AstNode_ForeignLibrary: return node->ForeignLibrary.token;
case AstNode_Field: case AstNode_Field:
if (node->Field.names.count > 0) { if (node->Field.names.count > 0) {
return ast_node_token(node->Field.names.e[0]); return ast_node_token(node->Field.names.e[0]);
} }
return ast_node_token(node->Field.type); return ast_node_token(node->Field.type);
case AstNode_FieldList:
return node->FieldList.token;
case AstNode_HelperType: return node->HelperType.token; case AstNode_HelperType: return node->HelperType.token;
case AstNode_ProcType: return node->ProcType.token; case AstNode_ProcType: return node->ProcType.token;
@@ -952,6 +959,13 @@ AstNode *ast_field(AstFile *f, AstNodeArray names, AstNode *type, u32 flags) {
return result; return result;
} }
AstNode *ast_field_list(AstFile *f, Token token, AstNodeArray list) {
AstNode *result = make_ast_node(f, AstNode_FieldList);
result->FieldList.token = token;
result->FieldList.list = list;
return result;
}
AstNode *ast_helper_type(AstFile *f, Token token, AstNode *type) { AstNode *ast_helper_type(AstFile *f, Token token, AstNode *type) {
AstNode *result = make_ast_node(f, AstNode_HelperType); AstNode *result = make_ast_node(f, AstNode_HelperType);
@@ -961,7 +975,7 @@ AstNode *ast_helper_type(AstFile *f, Token token, AstNode *type) {
} }
AstNode *ast_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArray results, u64 tags, ProcCallingConvention calling_convention) { AstNode *ast_proc_type(AstFile *f, Token token, AstNode *params, AstNode *results, u64 tags, ProcCallingConvention calling_convention) {
AstNode *result = make_ast_node(f, AstNode_ProcType); AstNode *result = make_ast_node(f, AstNode_ProcType);
result->ProcType.token = token; result->ProcType.token = token;
result->ProcType.params = params; result->ProcType.params = params;
@@ -1308,7 +1322,6 @@ AstNode * parse_proc_type(AstFile *f, AstNode **foreign_library, String *fore
AstNodeArray parse_stmt_list(AstFile *f); AstNodeArray parse_stmt_list(AstFile *f);
AstNode * parse_stmt(AstFile *f); AstNode * parse_stmt(AstFile *f);
AstNode * parse_body(AstFile *f); AstNode * parse_body(AstFile *f);
void parse_proc_signature(AstFile *f, AstNodeArray *params, AstNodeArray *results);
@@ -2258,15 +2271,39 @@ AstNode *parse_block_stmt(AstFile *f, b32 is_when) {
return parse_body(f); return parse_body(f);
} }
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind separator, TokenKind follow);
AstNode *parse_results(AstFile *f) {
if (!allow_token(f, Token_ArrowRight)) {
return NULL;
}
if (f->curr_token.kind != Token_OpenParen) {
Token begin_token = f->curr_token;
AstNodeArray empty_names = {0};
AstNodeArray list = make_ast_node_array(f);
AstNode *type = parse_type(f);
array_add(&list, ast_field(f, empty_names, type, 0));
return ast_field_list(f, begin_token, list);
}
AstNode *list = NULL;
expect_token(f, Token_OpenParen);
list = parse_field_list(f, NULL, 0, Token_Comma, Token_CloseParen);
expect_token_after(f, Token_CloseParen, "parameter list");
return list;
}
AstNode *parse_proc_type(AstFile *f, AstNode **foreign_library_, String *foreign_name_, String *link_name_) { AstNode *parse_proc_type(AstFile *f, AstNode **foreign_library_, String *foreign_name_, String *link_name_) {
AstNodeArray params = {0}; AstNode *params = {0};
AstNodeArray results = {0}; AstNode *results = {0};
Token proc_token = expect_token(f, Token_proc); Token proc_token = expect_token(f, Token_proc);
parse_proc_signature(f, &params, &results); expect_token(f, Token_OpenParen);
params = parse_field_list(f, NULL, FieldFlag_Signature, Token_Comma, Token_CloseParen);
expect_token_after(f, Token_CloseParen, "parameter list");
results = parse_results(f);
u64 tags = 0; u64 tags = 0;
String foreign_name = {0}; String foreign_name = {0};
@@ -2404,8 +2441,9 @@ AstNodeArray convert_to_ident_list(AstFile *f, AstNodeAndFlagsArray list, bool i
return idents; return idents;
} }
AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind separator, TokenKind follow) {
TokenKind separator, TokenKind follow) { Token start_token = f->curr_token;
AstNodeArray params = make_ast_node_array(f); AstNodeArray params = make_ast_node_array(f);
AstNodeAndFlagsArray list = {0}; array_init(&list, heap_allocator()); // LEAK(bill): AstNodeAndFlagsArray list = {0}; array_init(&list, heap_allocator()); // LEAK(bill):
isize total_name_count = 0; isize total_name_count = 0;
@@ -2465,7 +2503,7 @@ AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags,
} }
if (name_count_) *name_count_ = total_name_count; if (name_count_) *name_count_ = total_name_count;
return params; return ast_field_list(f, start_token, params);
} }
for_array(i, list) { for_array(i, list) {
@@ -2483,11 +2521,11 @@ AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags,
} }
if (name_count_) *name_count_ = total_name_count; if (name_count_) *name_count_ = total_name_count;
return params; return ast_field_list(f, start_token, params);
} }
AstNodeArray parse_record_fields(AstFile *f, isize *field_count_, u32 flags, String context) { AstNode *parse_record_fields(AstFile *f, isize *field_count_, u32 flags, String context) {
return parse_field_list(f, field_count_, flags, Token_Comma, Token_CloseBrace); return parse_field_list(f, field_count_, flags, Token_Comma, Token_CloseBrace);
} }
@@ -2617,9 +2655,15 @@ AstNode *parse_type_or_ident(AstFile *f) {
Token open = expect_token_after(f, Token_OpenBrace, "struct"); Token open = expect_token_after(f, Token_OpenBrace, "struct");
isize decl_count = 0; isize decl_count = 0;
AstNodeArray decls = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("struct")); AstNode *fields = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("struct"));
Token close = expect_token(f, Token_CloseBrace); Token close = expect_token(f, Token_CloseBrace);
AstNodeArray decls = {0};
if (fields != NULL) {
GB_ASSERT(fields->kind == AstNode_FieldList);
decls = fields->FieldList.list;
}
return ast_struct_type(f, token, decls, decl_count, is_packed, is_ordered, align); return ast_struct_type(f, token, decls, decl_count, is_packed, is_ordered, align);
} break; } break;
@@ -2627,9 +2671,15 @@ AstNode *parse_type_or_ident(AstFile *f) {
Token token = expect_token(f, Token_union); Token token = expect_token(f, Token_union);
Token open = expect_token_after(f, Token_OpenBrace, "union"); Token open = expect_token_after(f, Token_OpenBrace, "union");
isize decl_count = 0; isize decl_count = 0;
AstNodeArray decls = parse_record_fields(f, &decl_count, 0, str_lit("union")); AstNode *fields = parse_record_fields(f, &decl_count, 0, str_lit("union"));
Token close = expect_token(f, Token_CloseBrace); Token close = expect_token(f, Token_CloseBrace);
AstNodeArray decls = {0};
if (fields != NULL) {
GB_ASSERT(fields->kind == AstNode_FieldList);
decls = fields->FieldList.list;
}
return ast_union_type(f, token, decls, decl_count); return ast_union_type(f, token, decls, decl_count);
} }
@@ -2637,9 +2687,15 @@ AstNode *parse_type_or_ident(AstFile *f) {
Token token = expect_token(f, Token_raw_union); Token token = expect_token(f, Token_raw_union);
Token open = expect_token_after(f, Token_OpenBrace, "raw_union"); Token open = expect_token_after(f, Token_OpenBrace, "raw_union");
isize decl_count = 0; isize decl_count = 0;
AstNodeArray decls = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("raw_union")); AstNode *fields = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("raw_union"));
Token close = expect_token(f, Token_CloseBrace); Token close = expect_token(f, Token_CloseBrace);
AstNodeArray decls = {0};
if (fields != NULL) {
GB_ASSERT(fields->kind == AstNode_FieldList);
decls = fields->FieldList.list;
}
return ast_raw_union_type(f, token, decls, decl_count); return ast_raw_union_type(f, token, decls, decl_count);
} }
@@ -2679,39 +2735,6 @@ AstNode *parse_type_or_ident(AstFile *f) {
} }
AstNodeArray parse_results(AstFile *f) {
AstNodeArray results = make_ast_node_array(f);
if (allow_token(f, Token_ArrowRight)) {
if (f->curr_token.kind == Token_OpenParen) {
expect_token(f, Token_OpenParen);
while (f->curr_token.kind != Token_CloseParen &&
f->curr_token.kind != Token_EOF) {
array_add(&results, parse_type(f));
if (f->curr_token.kind != Token_Comma) {
break;
}
next_token(f);
}
expect_token(f, Token_CloseParen);
return results;
}
array_add(&results, parse_type(f));
return results;
}
return results;
}
void parse_proc_signature(AstFile *f,
AstNodeArray *params,
AstNodeArray *results) {
expect_token(f, Token_OpenParen);
*params = parse_field_list(f, NULL, FieldFlag_Signature, Token_Comma, Token_CloseParen);
expect_token_after(f, Token_CloseParen, "parameter list");
*results = parse_results(f);
}
AstNode *parse_body(AstFile *f) { AstNode *parse_body(AstFile *f) {
AstNodeArray stmts = {0}; AstNodeArray stmts = {0};
Token open, close; Token open, close;
@@ -2727,48 +2750,6 @@ AstNode *parse_body(AstFile *f) {
return ast_block_stmt(f, stmts, open, close); return ast_block_stmt(f, stmts, open, close);
} }
/*
AstNode *parse_proc_decl(AstFile *f) {
if (look_ahead_token_kind(f, 1) == Token_OpenParen) {
// NOTE(bill): It's an anonymous procedure
// NOTE(bill): This look-ahead technically makes the grammar LALR(2)
// but is that a problem in practice?
return ast_expr_stmt(f, parse_expr(f, true));
}
AstNodeArray params = {0};
AstNodeArray results = {0};
Token proc_token = expect_token(f, Token_proc);
AstNode *name = parse_ident(f);
parse_proc_signature(f, &params, &results);
u64 tags = 0;
String foreign_name = {0};
String link_name = {0};
ProcCallingConvention cc = ProcCC_Odin;
parse_proc_tags(f, &tags, &foreign_name, &link_name, &cc);
AstNode *proc_type = ast_proc_type(f, proc_token, params, results, tags, cc);
AstNode *body = NULL;
if (f->curr_token.kind == Token_OpenBrace) {
if ((tags & ProcTag_foreign) != 0) {
syntax_error(proc_token, "A procedure tagged as `#foreign` cannot have a body");
}
AstNode *curr_proc = f->curr_proc;
f->curr_proc = proc_type;
body = parse_body(f);
f->curr_proc = curr_proc;
} else if ((tags & ProcTag_foreign) == 0) {
syntax_error(proc_token, "Only a procedure tagged as `#foreign` cannot have a body");
}
return ast_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name);
} */
AstNode *parse_if_stmt(AstFile *f) { AstNode *parse_if_stmt(AstFile *f) {
if (f->curr_proc == NULL) { if (f->curr_proc == NULL) {
syntax_error(f->curr_token, "You cannot use an if statement in the file scope"); syntax_error(f->curr_token, "You cannot use an if statement in the file scope");