mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Merge pull request #24 from c3lang/develop
Support named parameters, default parameters and varargs.
This commit is contained in:
@@ -326,7 +326,7 @@ func int boba(int y, int j)
|
||||
}
|
||||
return x;
|
||||
}
|
||||
func int test(int x)
|
||||
func int test(int x = 100)
|
||||
{
|
||||
x = x + 1;
|
||||
x = x +% 1;
|
||||
@@ -512,10 +512,16 @@ func int testPointers(int x, int j = 0, double foo = 3.2)
|
||||
z - &y > 0 ? 1 : z - &y;
|
||||
return 1;
|
||||
}
|
||||
|
||||
func void testDefault(int x = 2, int y = 100, int z = -100)
|
||||
{
|
||||
printf("x = %d, y = %d, z = %d\n", x, y, z);
|
||||
}
|
||||
func int main(int x)
|
||||
{
|
||||
printf("Helo!\n");
|
||||
testPointers(2, 3, 2.3);
|
||||
testDefault(y = 99);
|
||||
testPointers(2, 3);
|
||||
int efd = 9;
|
||||
uint fefoek = 1;
|
||||
printf("Helo: %d\n", efd + cast(fefoek, int));
|
||||
|
||||
@@ -281,6 +281,7 @@ typedef struct _FunctionSignature
|
||||
{
|
||||
CallConvention convention : 4;
|
||||
bool variadic : 1;
|
||||
bool has_default : 1;
|
||||
bool throw_any : 1;
|
||||
TypeInfo *rtype;
|
||||
Decl** params;
|
||||
|
||||
@@ -300,7 +300,7 @@ static Expr *parse_call_expr(Context *context, Expr *left)
|
||||
Expr *call = EXPR_NEW_EXPR(EXPR_CALL, left);
|
||||
call->call_expr.function = left;
|
||||
call->call_expr.arguments = params;
|
||||
|
||||
RANGE_EXTEND_PREV(call);
|
||||
return call;
|
||||
}
|
||||
|
||||
|
||||
@@ -161,8 +161,9 @@ static inline bool sema_analyse_struct_union(Context *context, Decl *decl)
|
||||
}
|
||||
|
||||
|
||||
static inline bool sema_analyse_function_param(Context *context, Decl *param, bool is_function)
|
||||
static inline bool sema_analyse_function_param(Context *context, Decl *param, bool is_function, bool *has_default)
|
||||
{
|
||||
*has_default = false;
|
||||
assert(param->decl_kind == DECL_VAR);
|
||||
assert(param->var.kind == VARDECL_PARAM);
|
||||
if (!sema_resolve_type_info(context, param->var.type_info))
|
||||
@@ -184,6 +185,7 @@ static inline bool sema_analyse_function_param(Context *context, Decl *param, bo
|
||||
SEMA_ERROR(expr, "Only constant expressions may be used as default values.");
|
||||
return false;
|
||||
}
|
||||
*has_default = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -212,12 +214,14 @@ static inline Type *sema_analyse_function_signature(Context *context, FunctionSi
|
||||
Decl *param = signature->params[i];
|
||||
assert(param->resolve_status == RESOLVE_NOT_DONE);
|
||||
param->resolve_status = RESOLVE_RUNNING;
|
||||
if (!sema_analyse_function_param(context, param, is_function))
|
||||
bool has_default;
|
||||
if (!sema_analyse_function_param(context, param, is_function, &has_default))
|
||||
{
|
||||
decl_poison(param);
|
||||
all_ok = false;
|
||||
continue;
|
||||
}
|
||||
signature->has_default = signature->has_default || has_default;
|
||||
param->resolve_status = RESOLVE_DONE;
|
||||
if (i > 0 && all_ok)
|
||||
{
|
||||
|
||||
@@ -223,30 +223,94 @@ static inline bool sema_expr_analyse_var_call(Context *context, Type *to, Expr *
|
||||
static inline bool sema_expr_analyse_generic_call(Context *context, Type *to, Expr *expr) { TODO };
|
||||
|
||||
|
||||
static inline int find_index_of_named_parameter(Decl** func_params, Expr *expr)
|
||||
{
|
||||
if (expr->expr_kind != EXPR_IDENTIFIER || expr->identifier_expr.path)
|
||||
{
|
||||
SEMA_ERROR(expr, "Expected the name of a function parameter here, enclose the assignment expression in ().");
|
||||
return -1;
|
||||
}
|
||||
const char *name = expr->identifier_expr.identifier;
|
||||
VECEACH(func_params, i)
|
||||
{
|
||||
if (func_params[i]->name == name) return (int)i;
|
||||
}
|
||||
SEMA_ERROR(expr, "There's no parameter with the name '%s', if you want an assignment expression, enclose it in ().", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_func_call(Context *context, Type *to, Expr *expr, Decl *decl)
|
||||
{
|
||||
Expr **args =expr->call_expr.arguments;
|
||||
Decl **func_params = decl->func.function_signature.params;
|
||||
unsigned error_params = decl->func.function_signature.throw_any || decl->func.function_signature.throws;
|
||||
Expr **args = expr->call_expr.arguments;
|
||||
FunctionSignature *signature = &decl->func.function_signature;
|
||||
Decl **func_params = signature->params;
|
||||
unsigned error_params = signature->throw_any || signature->throws;
|
||||
if (error_params)
|
||||
{
|
||||
TODO
|
||||
}
|
||||
unsigned num_args = vec_size(args);
|
||||
// unsigned num_params = vec_size(func_params);
|
||||
// TODO handle named parameters, handle default parameters, varargs etc
|
||||
unsigned func_param_count = vec_size(func_params);
|
||||
unsigned num_args = vec_size(args);
|
||||
unsigned entries_needed = func_param_count > num_args ? func_param_count : num_args;
|
||||
Expr **actual_args = VECNEW(Expr*, entries_needed);
|
||||
for (unsigned i = 0; i < entries_needed; i++) vec_add(actual_args, NULL);
|
||||
memset(actual_args, 0, entries_needed * sizeof(Expr*));
|
||||
bool uses_named_parameters = false;
|
||||
|
||||
for (unsigned i = 0; i < num_args; i++)
|
||||
{
|
||||
Expr *arg = args[i];
|
||||
if (func_param_count >= i)
|
||||
// Named parameters
|
||||
if (arg->expr_kind == EXPR_BINARY && arg->binary_expr.operator == BINARYOP_ASSIGN)
|
||||
{
|
||||
if (!sema_analyse_expr_of_required_type(context, NULL, arg)) return false;
|
||||
uses_named_parameters = true;
|
||||
int index = find_index_of_named_parameter(func_params, arg->binary_expr.left);
|
||||
if (index < 0) return false;
|
||||
if (actual_args[index])
|
||||
{
|
||||
SEMA_ERROR(arg, "The parameter '%s' was already set once.", func_params[index]->name);
|
||||
return false;
|
||||
}
|
||||
if (!sema_analyse_expr_of_required_type(context, func_params[index]->type, arg->binary_expr.right)) return false;
|
||||
actual_args[index] = arg->binary_expr.right;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i >= func_param_count)
|
||||
{
|
||||
if (!signature->variadic)
|
||||
{
|
||||
SEMA_ERROR(expr, "Too many parameters for this function.");
|
||||
return false;
|
||||
}
|
||||
if (!sema_analyse_expr_of_required_type(context, NULL, arg)) return false;
|
||||
actual_args[i] = arg;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uses_named_parameters)
|
||||
{
|
||||
SEMA_ERROR(expr, "A regular parameter cannot follow a named parameter.");
|
||||
return false;
|
||||
}
|
||||
if (!sema_analyse_expr_of_required_type(context, func_params[i]->type, arg)) return false;
|
||||
actual_args[i] = arg;
|
||||
}
|
||||
for (unsigned i = 0; i < entries_needed; i++)
|
||||
{
|
||||
if (actual_args[i]) continue;
|
||||
|
||||
if (func_params[i]->var.init_expr)
|
||||
{
|
||||
actual_args[i] = func_params[i]->var.init_expr;
|
||||
continue;
|
||||
}
|
||||
|
||||
SEMA_ERROR(expr, "Parameter '%s' was not set.", func_params[i]->name);
|
||||
return false;
|
||||
}
|
||||
expr->type = decl->func.function_signature.rtype->type;
|
||||
expr->call_expr.arguments = actual_args;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user