aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c87
1 files changed, 67 insertions, 20 deletions
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) {