#const value procedure parameters; $N for polymorphic array lengths

This commit is contained in:
gingerBill
2017-11-05 18:26:24 +00:00
parent 1d4881cbbe
commit 66ee2cb6ed
9 changed files with 298 additions and 130 deletions

View File

@@ -16,9 +16,9 @@ EPSILON :: 1.19209290e-7;
τ :: TAU;
π :: PI;
Vec2 :: [vector 2]f32;
Vec3 :: [vector 3]f32;
Vec4 :: [vector 4]f32;
Vec2 :: [2]f32;
Vec3 :: [3]f32;
Vec4 :: [4]f32;
// Column major
Mat2 :: [2][2]f32;
@@ -122,38 +122,38 @@ to_degrees :: proc(radians: f32) -> f32 do return radians * 360 / TAU;
dot :: proc(a, b: $T/[vector 2]$E) -> E { c := a*b; return c.x + c.y; }
dot :: proc(a, b: $T/[vector 3]$E) -> E { c := a*b; return c.x + c.y + c.z; }
dot :: proc(a, b: $T/[vector 4]$E) -> E { c := a*b; return c.x + c.y + c.z + c.w; }
dot :: proc(a, b: $T/[2]$E) -> E { c := a*b; return c[0] + c[1]; }
dot :: proc(a, b: $T/[3]$E) -> E { c := a*b; return c[0] + c[1] + c[2]; }
dot :: proc(a, b: $T/[4]$E) -> E { c := a*b; return c[0] + c[1] + c[2] + c[3]; }
cross :: proc(x, y: $T/[vector 3]$E) -> T {
cross :: proc(x, y: $T/[3]$E) -> T {
a := swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1);
b := swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0);
return T(a - b);
}
mag :: proc(v: $T/[vector 2]$E) -> E do return sqrt(dot(v, v));
mag :: proc(v: $T/[vector 3]$E) -> E do return sqrt(dot(v, v));
mag :: proc(v: $T/[vector 4]$E) -> E do return sqrt(dot(v, v));
mag :: proc(v: $T/[2]$E) -> E do return sqrt(dot(v, v));
mag :: proc(v: $T/[3]$E) -> E do return sqrt(dot(v, v));
mag :: proc(v: $T/[4]$E) -> E do return sqrt(dot(v, v));
norm :: proc(v: $T/[vector 2]$E) -> T do return v / mag(v);
norm :: proc(v: $T/[vector 3]$E) -> T do return v / mag(v);
norm :: proc(v: $T/[vector 4]$E) -> T do return v / mag(v);
norm :: proc(v: $T/[2]$E) -> T do return v / mag(v);
norm :: proc(v: $T/[3]$E) -> T do return v / mag(v);
norm :: proc(v: $T/[4]$E) -> T do return v / mag(v);
norm0 :: proc(v: $T/[vector 2]$E) -> T {
norm0 :: proc(v: $T/[2]$E) -> T {
m := mag(v);
if m == 0 do return 0;
return v/m;
}
norm0 :: proc(v: $T/[vector 3]$E) -> T {
norm0 :: proc(v: $T/[3]$E) -> T {
m := mag(v);
if m == 0 do return 0;
return v/m;
}
norm0 :: proc(v: $T/[vector 4]$E) -> T {
norm0 :: proc(v: $T/[4]$E) -> T {
m := mag(v);
if m == 0 do return 0;
return v/m;
@@ -194,10 +194,10 @@ mul :: proc(a, b: Mat4) -> Mat4 {
mul :: proc(m: Mat4, v: Vec4) -> Vec4 {
return Vec4{
m[0][0]*v.x + m[1][0]*v.y + m[2][0]*v.z + m[3][0]*v.w,
m[0][1]*v.x + m[1][1]*v.y + m[2][1]*v.z + m[3][1]*v.w,
m[0][2]*v.x + m[1][2]*v.y + m[2][2]*v.z + m[3][2]*v.w,
m[0][3]*v.x + m[1][3]*v.y + m[2][3]*v.z + m[3][3]*v.w,
m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0]*v[3],
m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1]*v[3],
m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2]*v[3],
m[0][3]*v[0] + m[1][3]*v[1] + m[2][3]*v[2] + m[3][3]*v[3],
};
}
@@ -273,9 +273,9 @@ inverse :: proc(m: Mat4) -> Mat4 {
mat4_translate :: proc(v: Vec3) -> Mat4 {
m := mat4_identity();
m[3][0] = v.x;
m[3][1] = v.y;
m[3][2] = v.z;
m[3][0] = v[0];
m[3][1] = v[1];
m[3][2] = v[2];
m[3][3] = 1;
return m;
}
@@ -289,28 +289,28 @@ mat4_rotate :: proc(v: Vec3, angle_radians: f32) -> Mat4 {
rot := mat4_identity();
rot[0][0] = c + t.x*a.x;
rot[0][1] = 0 + t.x*a.y + s*a.z;
rot[0][2] = 0 + t.x*a.z - s*a.y;
rot[0][0] = c + t[0]*a[0];
rot[0][1] = 0 + t[0]*a[1] + s*a[2];
rot[0][2] = 0 + t[0]*a[2] - s*a[1];
rot[0][3] = 0;
rot[1][0] = 0 + t.y*a.x - s*a.z;
rot[1][1] = c + t.y*a.y;
rot[1][2] = 0 + t.y*a.z + s*a.x;
rot[1][0] = 0 + t[1]*a[0] - s*a[2];
rot[1][1] = c + t[1]*a[1];
rot[1][2] = 0 + t[1]*a[2] + s*a[0];
rot[1][3] = 0;
rot[2][0] = 0 + t.z*a.x + s*a.y;
rot[2][1] = 0 + t.z*a.y - s*a.x;
rot[2][2] = c + t.z*a.z;
rot[2][0] = 0 + t[2]*a[0] + s*a[1];
rot[2][1] = 0 + t[2]*a[1] - s*a[0];
rot[2][2] = c + t[2]*a[2];
rot[2][3] = 0;
return rot;
}
scale :: proc(m: Mat4, v: Vec3) -> Mat4 {
m[0][0] *= v.x;
m[1][1] *= v.y;
m[2][2] *= v.z;
m[0][0] *= v[0];
m[1][1] *= v[1];
m[2][2] *= v[2];
return m;
}
@@ -328,9 +328,9 @@ look_at :: proc(eye, centre, up: Vec3) -> Mat4 {
u := cross(s, f);
return Mat4{
{+s.x, +u.x, -f.x, 0},
{+s.y, +u.y, -f.y, 0},
{+s.z, +u.z, -f.z, 0},
{+s[0], +u[0], -f[0], 0},
{+s[1], +u[1], -f[1], 0},
{+s[2], +u[2], -f[2], 0},
{-dot(s, eye), -dot(u, eye), dot(f, eye), 1},
};
}

View File

@@ -755,8 +755,6 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
}
}
bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool compound, bool modify_type) {
Operand o = {Addressing_Value};
o.type = source;
@@ -792,9 +790,73 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
}
return false;
case Type_Array:
if (source->kind == Type_Array &&
poly->Array.count == source->Array.count) {
return is_polymorphic_type_assignable(c, poly->Array.elem, source->Array.elem, true, modify_type);
if (source->kind == Type_Array) {
if (poly->Array.generic_type && modify_type) {
Type *gt = poly->Array.generic_type;
GB_ASSERT(gt->kind == Type_Generic);
Entity *e = scope_lookup_entity(gt->Generic.scope, gt->Generic.name);
GB_ASSERT(e != nullptr);
if (e->kind == Entity_TypeName) {
poly->Array.generic_type = nullptr;
poly->Array.count = source->Array.count;
e->kind = Entity_Constant;
e->Constant.value = exact_value_i64(source->Array.count);
e->type = t_untyped_integer;
} else if (e->kind == Entity_Constant) {
poly->Array.generic_type = nullptr;
if (e->Constant.value.kind != ExactValue_Integer) {
return false;
}
i64 count = i128_to_i64(e->Constant.value.value_integer);
if (count != source->Array.count) {
return false;
}
poly->Array.count = source->Array.count;
} else {
return false;
}
return is_polymorphic_type_assignable(c, poly->Array.elem, source->Array.elem, true, modify_type);
}
if (poly->Array.count == source->Array.count) {
return is_polymorphic_type_assignable(c, poly->Array.elem, source->Array.elem, true, modify_type);
}
}
return false;
case Type_Vector:
if (source->kind == Type_Vector) {
if (poly->Vector.generic_type && modify_type) {
Type *gt = poly->Vector.generic_type;
GB_ASSERT(gt->kind == Type_Generic);
Entity *e = scope_lookup_entity(gt->Generic.scope, gt->Generic.name);
GB_ASSERT(e != nullptr);
if (e->kind == Entity_TypeName) {
poly->Vector.generic_type = nullptr;
poly->Vector.count = source->Vector.count;
e->kind = Entity_Constant;
e->Constant.value = exact_value_i64(source->Vector.count);
e->type = t_untyped_integer;
} else if (e->kind == Entity_Constant) {
poly->Vector.generic_type = nullptr;
if (e->Constant.value.kind != ExactValue_Integer) {
return false;
}
i64 count = i128_to_i64(e->Constant.value.value_integer);
if (count != source->Vector.count) {
return false;
}
poly->Vector.count = source->Vector.count;
} else {
return false;
}
return is_polymorphic_type_assignable(c, poly->Vector.elem, source->Vector.elem, true, modify_type);
}
if (poly->Vector.count == source->Vector.count) {
return is_polymorphic_type_assignable(c, poly->Vector.elem, source->Vector.elem, true, modify_type);
}
}
return false;
case Type_DynamicArray:
@@ -802,12 +864,6 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
return is_polymorphic_type_assignable(c, poly->DynamicArray.elem, source->DynamicArray.elem, true, modify_type);
}
return false;
case Type_Vector:
if (source->kind == Type_Vector &&
poly->Vector.count == source->Vector.count) {
return is_polymorphic_type_assignable(c, poly->Vector.elem, source->Vector.elem, true, modify_type);
}
return false;
case Type_Slice:
if (source->kind == Type_Slice) {
return is_polymorphic_type_assignable(c, poly->Slice.elem, source->Slice.elem, true, modify_type);
@@ -4109,12 +4165,13 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
break;
}
GB_ASSERT(e->kind == Entity_Variable);
if (e->Variable.default_value.kind != ExactValue_Invalid ||
e->Variable.default_is_nil ||
e->Variable.default_is_location) {
param_count_excluding_defaults--;
continue;
if (e->kind == Entity_Variable) {
if (e->Variable.default_value.kind != ExactValue_Invalid ||
e->Variable.default_is_nil ||
e->Variable.default_is_location) {
param_count_excluding_defaults--;
continue;
}
}
break;
}
@@ -4374,6 +4431,8 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
if (e->kind == Entity_TypeName) {
error(call, "Type parameter `%.*s` is missing in procedure call",
LIT(e->token.string));
} else if (e->kind == Entity_Constant && e->Constant.value.kind != ExactValue_Invalid) {
// Ignore
} else {
gbString str = type_to_string(e->type);
error(call, "Parameter `%.*s` of type `%s` is missing in procedure call",
@@ -5339,7 +5398,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
if (cl->type != nullptr) {
type = nullptr;
// [..]Type
// [...]Type
if (cl->type->kind == AstNode_ArrayType && cl->type->ArrayType.count != nullptr) {
AstNode *count = cl->type->ArrayType.count;
if (count->kind == AstNode_UnaryExpr &&

View File

@@ -686,7 +686,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
specialization = nullptr;
}
}
type = make_type_generic(c->allocator, 0, str_lit(""), specialization);
type = make_type_generic(c->allocator, c->context.scope, 0, str_lit(""), specialization);
} else {
type = check_type(c, type_expr);
if (is_type_polymorphic(type)) {
@@ -1270,6 +1270,9 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
bool detemine_type_from_operand = false;
Type *specialization = nullptr;
bool is_using = (p->flags&FieldFlag_using) != 0;
bool is_constant_value = (p->flags&FieldFlag_const) != 0;
if (type_expr == nullptr) {
if (default_value->kind == AstNode_BasicDirective &&
@@ -1338,7 +1341,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
detemine_type_from_operand = true;
type = t_invalid;
} else {
type = make_type_generic(c->allocator, 0, str_lit(""), specialization);
type = make_type_generic(c->allocator, c->context.scope, 0, str_lit(""), specialization);
}
} else {
bool prev = c->context.allow_polymorphic_types;
@@ -1357,6 +1360,8 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
if (default_value != nullptr) {
if (type_expr->kind == AstNode_TypeType) {
error(default_value, "A type parameter may not have a default value");
} else if (is_constant_value) {
error(default_value, "A constant parameter may not have a default value");
} else {
Operand o = {};
if (default_value->kind == AstNode_BasicDirective &&
@@ -1431,6 +1436,16 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
}
}
if (is_constant_value) {
if (is_type_param) {
error(p->type, "`$` is not needed for a `type` parameter");
}
if (p->flags&FieldFlag_no_alias) {
error(p->type, "`#no_alias` can only be applied to variable fields of pointer type");
p->flags &= ~FieldFlag_no_alias; // Remove the flag
}
}
for_array(j, p->names) {
AstNode *name = p->names[j];
@@ -1475,16 +1490,16 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
param = make_entity_type_name(c->allocator, scope, name->Ident.token, type);
param->TypeName.is_type_alias = true;
} else {
if (operands != nullptr && is_type_polymorphic_type &&
operands->count > variables.count) {
Operand op = (*operands)[variables.count];
type = determine_type_from_polymorphic(c, type, op);
if (type == t_invalid) {
success = false;
} else if (!c->context.no_polymorphic_errors) {
// NOTE(bill): The type should be determined now and thus, no need to determine the type any more
is_type_polymorphic_type = false;
// is_type_polymorphic_type = is_type_polymorphic(base_type(type));
if (operands != nullptr && variables.count < operands->count) {
if (is_type_polymorphic_type) {
Operand op = (*operands)[variables.count];
type = determine_type_from_polymorphic(c, type, op);
if (type == t_invalid) {
success = false;
} else if (!c->context.no_polymorphic_errors) {
// NOTE(bill): The type should be determined now and thus, no need to determine the type any more
is_type_polymorphic_type = false;
}
}
}
@@ -1495,11 +1510,33 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
}
}
param = make_entity_param(c->allocator, scope, name->Ident.token, type,
(p->flags&FieldFlag_using) != 0, false);
param->Variable.default_value = value;
param->Variable.default_is_nil = default_is_nil;
param->Variable.default_is_location = default_is_location;
if (is_constant_value) {
if (!is_type_constant_type(type)) {
gbString str = type_to_string(type);
error(params[i], "Invalid constant type, %s", str);
gb_string_free(str);
}
bool poly_const = true;
if (operands != nullptr) {
poly_const = false;
if (variables.count < operands->count) {
Operand op = (*operands)[variables.count];
if (op.mode != Addressing_Constant) {
error(op.expr, "Expected a constant parameter value");
} else {
value = op.value;
}
}
}
param = make_entity_const_param(c->allocator, scope, name->Ident.token, type, value, poly_const);
} else {
param = make_entity_param(c->allocator, scope, name->Ident.token, type, is_using, false);
param->Variable.default_value = value;
param->Variable.default_is_nil = default_is_nil;
param->Variable.default_is_location = default_is_location;
}
}
if (p->flags&FieldFlag_no_alias) {
@@ -1952,27 +1989,36 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
}
i64 check_array_count(Checker *c, AstNode *e) {
i64 check_array_count(Checker *c, Operand *o, AstNode *e) {
if (e == nullptr) {
return 0;
}
Operand o = {};
if (e->kind == AstNode_UnaryExpr &&
e->UnaryExpr.op.kind == Token_Ellipsis) {
return -1;
}
check_expr(c, &o, e);
if (o.mode != Addressing_Constant) {
if (o.mode != Addressing_Invalid) {
check_expr_or_type(c, o, e);
if (o->mode == Addressing_Type && o->type->kind == Type_Generic) {
if (c->context.allow_polymorphic_types) {
if (o->type->Generic.specialized) {
o->type->Generic.specialized = nullptr;
error(o->expr, "Polymorphic array length cannot have a specialization");
}
return 0;
}
}
if (o->mode != Addressing_Constant) {
if (o->mode != Addressing_Invalid) {
o->mode = Addressing_Invalid;
error(e, "Array count must be a constant");
}
return 0;
}
Type *type = base_type(o.type);
Type *type = base_type(o->type);
if (is_type_untyped(type) || is_type_integer(type)) {
if (o.value.kind == ExactValue_Integer) {
i64 count = i128_to_i64(o.value.value_integer);
if (o->value.kind == ExactValue_Integer) {
i64 count = i128_to_i64(o->value.value_integer);
if (count >= 0) {
return count;
}
@@ -2162,7 +2208,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
specific = nullptr;
}
}
Type *t = make_type_generic(c->allocator, 0, token.string, specific);
Type *t = make_type_generic(c->allocator, c->context.scope, 0, token.string, specific);
if (c->context.allow_polymorphic_types) {
Scope *ps = c->context.polymorphic_scope;
Scope *s = c->context.scope;
@@ -2176,7 +2222,7 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
add_entity(c, ps, ident, e);
add_entity(c, s, ident, e);
} else {
error(ident, "Invalid use of a polymorphic type `$%.*s`", LIT(token.string));
error(ident, "Invalid use of a polymorphic parameter `$%.*s`", LIT(token.string));
*type = t_invalid;
return false;
}
@@ -2233,13 +2279,18 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
case_ast_node(at, ArrayType, e);
if (at->count != nullptr) {
Type *elem = check_type(c, at->elem, nullptr);
i64 count = check_array_count(c, at->count);
Operand o = {};
i64 count = check_array_count(c, &o, at->count);
Type *generic_type = nullptr;
if (o.mode == Addressing_Type && o.type->kind == Type_Generic) {
generic_type = o.type;
}
if (count < 0) {
error(at->count, "... can only be used in conjuction with compound literals");
count = 0;
}
*type = make_type_array(c->allocator, elem, count);
Type *elem = check_type(c, at->elem, nullptr);
*type = make_type_array(c->allocator, elem, count, generic_type);
} else {
Type *elem = check_type(c, at->elem);
*type = make_type_slice(c->allocator, elem);
@@ -2256,15 +2307,25 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
case_ast_node(vt, VectorType, e);
Operand o = {};
i64 count = check_array_count(c, &o, vt->count);
Type *generic_type = nullptr;
if (o.mode == Addressing_Type && o.type->kind == Type_Generic) {
generic_type = o.type;
}
if (count < 0) {
count = 0;
}
Type *elem = check_type(c, vt->elem);
Type *be = base_type(elem);
i64 count = check_array_count(c, vt->count);
if (is_type_vector(be) || (!is_type_boolean(be) && !is_type_numeric(be) && be->kind != Type_Generic)) {
gbString err_str = type_to_string(elem);
error(vt->elem, "Vector element type must be numerical or a boolean, got `%s`", err_str);
gb_string_free(err_str);
}
*type = make_type_vector(c->allocator, elem, count);
*type = make_type_vector(c->allocator, elem, count, generic_type);
return true;
case_end;

View File

@@ -514,15 +514,15 @@ void scope_lookup_parent_entity (Scope *s, String name, Scope **scope_, Entit
Entity *scope_insert_entity (Scope *s, Entity *entity);
ExprInfo *check_get_expr_info(CheckerInfo *i, AstNode *expr);
void check_set_expr_info(CheckerInfo *i, AstNode *expr, ExprInfo info);
void check_remove_expr_info(CheckerInfo *i, AstNode *expr);
void add_untyped(CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value);
void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value);
void add_entity_use(Checker *c, AstNode *identifier, Entity *entity);
void add_implicit_entity(Checker *c, AstNode *node, Entity *e);
void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d);
void add_implicit_entity(Checker *c, AstNode *node, Entity *e);
ExprInfo *check_get_expr_info (CheckerInfo *i, AstNode *expr);
void check_set_expr_info (CheckerInfo *i, AstNode *expr, ExprInfo info);
void check_remove_expr_info (CheckerInfo *i, AstNode *expr);
void add_untyped (CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode mode, Type *basic_type, ExactValue value);
void add_type_and_value (CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value);
void add_entity_use (Checker *c, AstNode *identifier, Entity *entity);
void add_implicit_entity (Checker *c, AstNode *node, Entity *e);
void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d);
void add_implicit_entity (Checker *c, AstNode *node, Entity *e);
void check_add_import_decl(Checker *c, AstNodeImportDecl *id);
void check_add_export_decl(Checker *c, AstNodeExportDecl *ed);

View File

@@ -43,6 +43,7 @@ enum EntityFlag {
EntityFlag_Value = 1<<9,
EntityFlag_Sret = 1<<10,
EntityFlag_BitFieldValue = 1<<11,
EntityFlag_PolyConst = 1<<12,
EntityFlag_CVarArg = 1<<20,
};
@@ -207,6 +208,16 @@ Entity *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type,
return entity;
}
Entity *make_entity_const_param(gbAllocator a, Scope *scope, Token token, Type *type, ExactValue value, bool poly_const) {
Entity *entity = make_entity_constant(a, scope, token, type, value);
entity->flags |= EntityFlag_Used;
if (poly_const) entity->flags |= EntityFlag_PolyConst;
entity->flags |= EntityFlag_Param;
return entity;
}
Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type, bool is_using, i32 field_src_index) {
Entity *entity = make_entity_variable(a, scope, token, type, false);
entity->Variable.field_src_index = field_src_index;

View File

@@ -5012,6 +5012,8 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
Entity *e = pt->variables[i];
if (e->kind == Entity_TypeName) {
args[i] = ir_value_nil(proc->module->allocator, e->type);
} else if (e->kind == Entity_Constant) {
continue;
} else {
GB_ASSERT(e->kind == Entity_Variable);
if (args[i] == nullptr) {
@@ -5029,8 +5031,6 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
return ir_emit_call(proc, value, args, param_count);
}
isize arg_index = 0;
isize arg_count = 0;
for_array(i, ce->args) {
AstNode *a = ce->args[i];
@@ -5042,8 +5042,8 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
}
}
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, gb_max(type->param_count, arg_count));
Array<irValue *> args = {};
array_init(&args, proc->module->allocator, gb_max(type->param_count, arg_count));
bool variadic = type->variadic;
bool vari_expand = ce->ellipsis.pos.line != 0;
bool is_c_vararg = type->c_vararg;
@@ -5052,7 +5052,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
AstNode *arg = ce->args[i];
TypeAndValue arg_tv = type_and_value_of_expr(proc->module->info, arg);
if (arg_tv.mode == Addressing_Type) {
args[arg_index++] = ir_value_nil(proc->module->allocator, arg_tv.type);
array_add(&args, ir_value_nil(proc->module->allocator, arg_tv.type));
} else {
irValue *a = ir_build_expr(proc, arg);
Type *at = ir_type(a);
@@ -5060,10 +5060,10 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
for_array(i, at->Tuple.variables) {
Entity *e = at->Tuple.variables[i];
irValue *v = ir_emit_struct_ev(proc, a, cast(i32)i);
args[arg_index++] = v;
array_add(&args, v);
}
} else {
args[arg_index++] = a;
array_add(&args, a);
}
}
}
@@ -5081,15 +5081,15 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
if (variadic) {
end--;
}
while (arg_index < end) {
Entity *e = pt->variables[arg_index];
while (args.count < end) {
Entity *e = pt->variables[args.count];
GB_ASSERT(e->kind == Entity_Variable);
if (e->Variable.default_value.kind != ExactValue_Invalid) {
args[arg_index++] = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
array_add(&args, ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value));
} else if (e->Variable.default_is_location) {
args[arg_index++] = ir_emit_source_code_location(proc, procedure, pos);
array_add(&args, ir_emit_source_code_location(proc, procedure, pos));
} else {
args[arg_index++] = ir_value_nil(proc->module->allocator, e->type);
array_add(&args, ir_value_nil(proc->module->allocator, e->type));
}
}
}
@@ -5172,7 +5172,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
args[arg_count-1] = ir_emit_load(proc, slice);
}
return ir_emit_call(proc, value, args, final_count);
return ir_emit_call(proc, value, args.data, final_count);
case_end;
case_ast_node(se, SliceExpr, expr);

View File

@@ -126,8 +126,9 @@ enum FieldFlag {
FieldFlag_using = 1<<1,
FieldFlag_no_alias = 1<<2,
FieldFlag_c_vararg = 1<<3,
FieldFlag_const = 1<<4,
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg,
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_const,
FieldFlag_Struct = FieldFlag_using,
};
@@ -3314,6 +3315,10 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token) {
is_generic = true;
break;
}
if (f->flags&FieldFlag_const) {
is_generic = true;
break;
}
}
@@ -3357,6 +3362,7 @@ enum FieldPrefixKind {
FieldPrefix_Using,
FieldPrefix_NoAlias,
FieldPrefix_CVarArg,
FieldPrefix_Const,
};
FieldPrefixKind is_token_field_prefix(AstFile *f) {
@@ -3367,15 +3373,17 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) {
case Token_using:
return FieldPrefix_Using;
case Token_Hash: {
advance_token(f);
switch (f->curr_token.kind) {
case Token_Ident:
if (f->curr_token.string == "no_alias") {
return FieldPrefix_NoAlias;
}
if (f->curr_token.string == "c_vararg") {
} else if (f->curr_token.string == "c_vararg") {
return FieldPrefix_CVarArg;
} else if (f->curr_token.string == "const") {
return FieldPrefix_Const;
}
break;
}
@@ -3389,6 +3397,7 @@ u32 parse_field_prefixes(AstFile *f) {
i32 using_count = 0;
i32 no_alias_count = 0;
i32 c_vararg_count = 0;
i32 const_count = 0;
for (;;) {
FieldPrefixKind kind = is_token_field_prefix(f);
@@ -3396,20 +3405,23 @@ u32 parse_field_prefixes(AstFile *f) {
break;
}
switch (kind) {
case FieldPrefix_Using: using_count += 1; advance_token(f); break;
case FieldPrefix_NoAlias: no_alias_count += 1; advance_token(f); break;
case FieldPrefix_CVarArg: c_vararg_count += 1; advance_token(f); break;
case FieldPrefix_Using: using_count += 1; advance_token(f); break;
case FieldPrefix_NoAlias: no_alias_count += 1; advance_token(f); break;
case FieldPrefix_CVarArg: c_vararg_count += 1; advance_token(f); break;
case FieldPrefix_Const: const_count += 1; advance_token(f); break;
}
}
if (using_count > 1) syntax_error(f->curr_token, "Multiple `using` in this field list");
if (no_alias_count > 1) syntax_error(f->curr_token, "Multiple `#no_alias` in this field list");
if (c_vararg_count > 1) syntax_error(f->curr_token, "Multiple `#c_vararg` in this field list");
if (const_count > 1) syntax_error(f->curr_token, "Multiple `$` in this field list");
u32 field_flags = 0;
if (using_count > 0) field_flags |= FieldFlag_using;
if (no_alias_count > 0) field_flags |= FieldFlag_no_alias;
if (c_vararg_count > 0) field_flags |= FieldFlag_c_vararg;
if (const_count > 0) field_flags |= FieldFlag_const;
return field_flags;
}
@@ -3431,6 +3443,10 @@ u32 check_field_prefixes(AstFile *f, isize name_count, u32 allowed_flags, u32 se
syntax_error(f->curr_token, "`#c_vararg` is not allowed within this field list");
set_flags &= ~FieldFlag_c_vararg;
}
if ((allowed_flags&FieldFlag_const) == 0 && (set_flags&FieldFlag_const)) {
syntax_error(f->curr_token, "`$` is not allowed within this field list");
set_flags &= ~FieldFlag_const;
}
return set_flags;
}

View File

@@ -155,14 +155,13 @@ TokenPos token_pos(String file, isize line, isize column) {
}
i32 token_pos_cmp(TokenPos const &a, TokenPos const &b) {
if (a.line == b.line) {
if (a.column == b.column) {
isize min_len = gb_min(a.file.len, b.file.len);
return gb_memcompare(a.file.text, b.file.text, min_len);
}
if (a.line != b.line) {
return (a.line < b.line) ? -1 : +1;
}
if (a.column != b.column) {
return (a.column < b.column) ? -1 : +1;
}
return (a.line < b.line) ? -1 : +1;
return string_compare(a.file, b.file);
}
bool operator==(TokenPos const &a, TokenPos const &b) { return token_pos_cmp(a, b) == 0; }

View File

@@ -98,11 +98,20 @@ struct TypeStruct {
i64 id; \
String name; \
Type * specialized; \
Scope *scope; \
}) \
TYPE_KIND(Pointer, struct { Type *elem; }) \
TYPE_KIND(Array, struct { Type *elem; i64 count; }) \
TYPE_KIND(Array, struct { \
Type *elem; \
i64 count; \
Type *generic_type; \
}) \
TYPE_KIND(DynamicArray, struct { Type *elem; }) \
TYPE_KIND(Vector, struct { Type *elem; i64 count; }) \
TYPE_KIND(Vector, struct { \
Type *elem; \
i64 count; \
Type *generic_type; \
}) \
TYPE_KIND(Slice, struct { Type *elem; }) \
TYPE_KIND(Struct, TypeStruct) \
TYPE_KIND(Enum, struct { \
@@ -466,11 +475,12 @@ Type *make_type_basic(gbAllocator a, BasicType basic) {
return t;
}
Type *make_type_generic(gbAllocator a, i64 id, String name, Type *specialized) {
Type *make_type_generic(gbAllocator a, Scope *scope, i64 id, String name, Type *specialized) {
Type *t = alloc_type(a, Type_Generic);
t->Generic.id = id;
t->Generic.name = name;
t->Generic.specialized = specialized;
t->Generic.scope = scope;
return t;
}
@@ -480,10 +490,11 @@ Type *make_type_pointer(gbAllocator a, Type *elem) {
return t;
}
Type *make_type_array(gbAllocator a, Type *elem, i64 count) {
Type *make_type_array(gbAllocator a, Type *elem, i64 count, Type *generic_type = nullptr) {
Type *t = alloc_type(a, Type_Array);
t->Array.elem = elem;
t->Array.count = count;
t->Array.generic_type = generic_type;
return t;
}
@@ -493,10 +504,11 @@ Type *make_type_dynamic_array(gbAllocator a, Type *elem) {
return t;
}
Type *make_type_vector(gbAllocator a, Type *elem, i64 count) {
Type *make_type_vector(gbAllocator a, Type *elem, i64 count, Type *generic_type = nullptr) {
Type *t = alloc_type(a, Type_Vector);
t->Vector.elem = elem;
t->Vector.count = count;
t->Vector.generic_type = generic_type;
return t;
}
@@ -951,11 +963,14 @@ bool is_type_polymorphic(Type *t) {
case Type_Pointer:
return is_type_polymorphic(t->Pointer.elem);
case Type_Array:
if (t->Array.generic_type != nullptr) {
return true;
}
return is_type_polymorphic(t->Array.elem);
case Type_DynamicArray:
return is_type_polymorphic(t->DynamicArray.elem);
case Type_Vector:
return is_type_polymorphic(t->Vector.elem);
case Type_DynamicArray:
return is_type_polymorphic(t->DynamicArray.elem);
case Type_Slice:
return is_type_polymorphic(t->Slice.elem);
@@ -2415,12 +2430,19 @@ gbString write_type_to_string(gbString str, Type *type) {
case Type_Tuple:
if (type->Tuple.variables.count > 0) {
isize comma_index = 0;
for_array(i, type->Tuple.variables) {
Entity *var = type->Tuple.variables[i];
if (var != nullptr) {
if (i > 0) {
if (var->kind == Entity_Constant) {
// Ignore
continue;
}
if (comma_index++ > 0) {
str = gb_string_appendc(str, ", ");
}
if (var->kind == Entity_Variable) {
if (var->flags&EntityFlag_CVarArg) {
str = gb_string_appendc(str, "#c_vararg ");