From c811a743a1528db1d05970e1aa14162ef7c70b75 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 21 Sep 2019 13:59:39 +0200 Subject: Implement vararg, verify arguments to parameters --- src/parser.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 20 deletions(-) (limited to 'src/parser.c') diff --git a/src/parser.c b/src/parser.c index 9da9147..dc39a6a 100644 --- a/src/parser.c +++ b/src/parser.c @@ -119,31 +119,45 @@ static void parser_parse_struct_body_loop(Parser *self, StructDecl *struct_decl) } /* -FUNC_PARAM = TOK_IDENTIFIER VAR_TYPE_DEF +FUNC_PARAM = (TOK_IDENTIFIER VAR_TYPE_DEF)|'...' */ static CHECK_RESULT bool parser_parse_function_parameter(Parser *self, FunctionParameter *result) { bool match; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IDENTIFIER, &match)); - if(!match) - return bool_false; + if(match) { + result->name = self->tokenizer.value.identifier; + parser_parse_var_type_def(self, &result->type); + if(result->type.type == VARIABLE_TYPE_NONE) { + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_error_index(&self->tokenizer), + "Expected ':' after parameter name"); + throw(PARSER_UNEXPECTED_TOKEN); + } + return bool_true; + } - result->name = self->tokenizer.value.identifier; - parser_parse_var_type_def(self, &result->type); - if(result->type.type == VARIABLE_TYPE_NONE) { - self->error = tokenizer_create_error(&self->tokenizer, - tokenizer_get_error_index(&self->tokenizer), - "Expected ':' after parameter name"); - throw(PARSER_UNEXPECTED_TOKEN); + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_C_VARARGS, &match)); + if(match) { + result->name = self->tokenizer.value.identifier; + result->type.variable_type_flags = VARIABLE_TYPE_FLAG_NONE; + result->type.type = VARIABLE_TYPE_VARIABLE; + throw_if_error(arena_allocator_alloc(self->allocator, sizeof(Variable), (void**)&result->type.value.variable)); + variable_init(result->type.value.variable, result->name); + return bool_true; } - return bool_true; + return bool_false; } /* FUNC_PARAMS = FUNC_PARAM (',' FUNC_PARAM)* */ static void parser_parse_function_parameters(Parser *self, FunctionSignature *func_sig) { + amal_default_type *vararg_type = self->compiler->default_types.c_varargs; + int vararg_index = -1; + int index = 0; + for(;;) { FunctionParameter func_param; bool match; @@ -157,6 +171,13 @@ static void parser_parse_function_parameters(Parser *self, FunctionSignature *fu throw(PARSER_UNEXPECTED_TOKEN); } + if(vararg_index != -1) { + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_error_index(&self->tokenizer), + "A closure can't have parameters after a vararg"); + throw(PARSER_UNEXPECTED_TOKEN); + } + result = function_signature_add_parameter(func_sig, &func_param); if(result == AST_ERR_DEF_DUP) { self->error = tokenizer_create_error(&self->tokenizer, @@ -169,7 +190,19 @@ static void parser_parse_function_parameters(Parser *self, FunctionSignature *fu } throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_COMMA, &match)); if(!match) - return; + break; + + if (vararg_index == -1 && buffer_view_equals(&func_param.name, &vararg_type->lhs_expr.var_name)) + vararg_index = index; + + ++index; + } + + if (index > FUNC_MAX_PARAMS) { + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_error_index(&self->tokenizer), + "A closure can't have more than %d parameters", FUNC_MAX_PARAMS); + throw(PARSER_ERR); } } @@ -192,19 +225,19 @@ static void parser_parse_function_return_types(Parser *self, FunctionSignature * tokenizer_get_error_index(&self->tokenizer), "Expected type or closure signature"); throw(PARSER_UNEXPECTED_TOKEN); + } else if(var_type.variable_type_flags & VARIABLE_TYPE_FLAG_BORROW) { + self->error = tokenizer_create_error(&self->tokenizer, + tokenizer_get_error_index(&self->tokenizer), + "A closure can't return a value as borrowed"); + throw(PARSER_ERR); } + throw_if_error(function_signature_add_return_type(func_sig, &var_type)); throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_COMMA, &match)); if(!match) break; - ++return_type_index; - } - if (buffer_get_size(&func_sig->parameters, FunctionParameter) > FUNC_MAX_PARAMS) { - self->error = tokenizer_create_error(&self->tokenizer, - tokenizer_get_error_index(&self->tokenizer), - "A closure can't have more than %d parameters", FUNC_MAX_PARAMS); - throw(PARSER_ERR); + ++return_type_index; } if (buffer_get_size(&func_sig->return_types, FunctionReturnType) > FUNC_MAX_RETURN_TYPES) { @@ -244,13 +277,27 @@ static CHECK_RESULT FunctionSignature* parser_parse_function_signature(Parser *s } /* -VAR_TYPE = TOK_IDENTIFIER|FUNC_SIGNATURE +VAR_TYPE = '?'? TOK_IDENTIFIER|FUNC_SIGNATURE */ void parser_parse_var_type(Parser *self, VariableType *result) { bool match; result->type = VARIABLE_TYPE_NONE; result->value.variable = NULL; + result->variable_type_flags = VARIABLE_TYPE_FLAG_NONE; + + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_QUESTION_MARK, &match)); + if(match) + result->variable_type_flags |= VARIABLE_TYPE_FLAG_OPTIONAL; + + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &match)); + if(match) { + if(self->tokenizer.value.binop_type != BINOP_MUL) { + self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_error_index(&self->tokenizer), "Expected '*', type or closure signature"); + throw(PARSER_UNEXPECTED_TOKEN); + } + result->variable_type_flags |= VARIABLE_TYPE_FLAG_BORROW; + } throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IDENTIFIER, &match)); if(match) { -- cgit v1.2.3