*_of as keyords; Allow constant aliasing for user/built-in procedures, import names, and library names

This commit is contained in:
Ginger Bill
2017-07-04 11:23:48 +01:00
parent bc16b290ba
commit 689a0c0b49
9 changed files with 232 additions and 49 deletions
+6 -4
View File
@@ -1,6 +1,5 @@
import (
"fmt.odin";
/*
"atomics.odin";
"bits.odin";
"decimal.odin";
@@ -16,6 +15,7 @@ import (
"types.odin";
"utf8.odin";
"utf16.odin";
/*
*/
)
@@ -370,9 +370,11 @@ main :: proc() {
foo :: proc(x: type, y: f32) do fmt.println("#2", type_info(x), y);
foo :: proc(x: type) do fmt.println("#3", type_info(x));
foo(y = 3785.1546, x = 123);
foo(x = int, y = 897.513);
foo(x = f32);
f :: foo;
f(y = 3785.1546, x = 123);
f(x = int, y = 897.513);
f(x = f32);
/*
general_stuff();
foreign_blocks();
+14 -2
View File
@@ -504,8 +504,20 @@ __mem_compare :: proc(a, b: ^u8, n: int) -> int #cc_contextless {
}
foreign __llvm_core {
__sqrt_f32 :: proc(x: f32) -> f32 #link_name "llvm.sqrt.f32" ---;
__sqrt_f64 :: proc(x: f64) -> f64 #link_name "llvm.sqrt.f64" ---;
__sqrt_f32 :: proc(x: f32) -> f32 #link_name "llvm.sqrt.f32" ---;
__sqrt_f64 :: proc(x: f64) -> f64 #link_name "llvm.sqrt.f64" ---;
__sin_f32 :: proc(θ: f32) -> f32 #link_name "llvm.sin.f32" ---;
__sin_f64 :: proc(θ: f64) -> f64 #link_name "llvm.sin.f64" ---;
__cos_f32 :: proc(θ: f32) -> f32 #link_name "llvm.cos.f32" ---;
__cos_f64 :: proc(θ: f64) -> f64 #link_name "llvm.cos.f64" ---;
__pow_f32 :: proc(x, power: f32) -> f32 #link_name "llvm.pow.f32" ---;
__pow_f64 :: proc(x, power: f64) -> f64 #link_name "llvm.pow.f64" ---;
fmuladd32 :: proc(a, b, c: f32) -> f32 #link_name "llvm.fmuladd.f32" ---;
fmuladd64 :: proc(a, b, c: f64) -> f64 #link_name "llvm.fmuladd.f64" ---;
}
__abs_complex64 :: proc(x: complex64) -> f32 #inline #cc_contextless {
r, i := real(x), imag(x);
+67 -12
View File
@@ -191,25 +191,80 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
}
Operand operand = {};
if (init != NULL) {
check_expr_or_type(c, &operand, init);
}
#if 1
if (operand.mode == Addressing_Type) {
e->kind = Entity_TypeName;
DeclInfo *d = c->context.decl;
d->type_expr = d->init_expr;
check_type_decl(c, e, d->type_expr, named_type);
return;
if (init != NULL) {
Entity *entity = NULL;
if (init->kind == AstNode_Ident) {
entity = check_ident(c, &operand, init, NULL, e->type, true);
} else if (init->kind == AstNode_SelectorExpr) {
entity = check_selector(c, &operand, init, e->type);
} else {
check_expr_or_type(c, &operand, init, e->type);
}
switch (operand.mode) {
case Addressing_Type: {
e->kind = Entity_TypeName;
DeclInfo *d = c->context.decl;
d->type_expr = d->init_expr;
check_type_decl(c, e, d->type_expr, named_type);
return;
} break;
case Addressing_Builtin:
if (e->type != NULL) {
error(type_expr, "A constant alias of a built-in procedure may not have a type initializer");
}
e->kind = Entity_Builtin;
e->Builtin.id = operand.builtin_id;
e->type = t_invalid;
return;
case Addressing_Overload:
e->kind = Entity_Alias;
e->Alias.base = operand.overload_entities[0];
e->type = t_invalid;
return;
}
if (entity != NULL) {
switch (entity->kind) {
case Entity_Procedure:
e->kind = Entity_Alias;
e->type = entity->type;
e->Alias.base = entity;
return;
case Entity_ImportName:
e->kind = Entity_ImportName;
e->type = entity->type;
e->ImportName.path = entity->ImportName.path;
e->ImportName.name = entity->ImportName.path;
e->ImportName.scope = entity->ImportName.scope;
e->ImportName.used = false;
return;
case Entity_LibraryName:
e->kind = Entity_LibraryName;
e->type = entity->type;
e->LibraryName.path = entity->LibraryName.path;
e->LibraryName.name = entity->LibraryName.path;
e->LibraryName.used = false;
return;
}
}
}
if (init != NULL) {
check_expr_or_type(c, &operand, init, e->type);
}
#endif
check_init_constant(c, e, &operand);
if (operand.mode == Addressing_Invalid ||
base_type(operand.type) == t_invalid) {
error(e->token, "Invalid declaration type");
gbString str = expr_to_string(init);
error(e->token, "Invalid declaration type `%s`", str);
gb_string_free(str);
}
}
+44 -8
View File
@@ -33,7 +33,7 @@ typedef CALL_ARGUMENT_CHECKER(CallArgumentCheckerType);
void check_expr (Checker *c, Operand *operand, AstNode *expression);
void check_multi_expr (Checker *c, Operand *operand, AstNode *expression);
void check_expr_or_type (Checker *c, Operand *operand, AstNode *expression);
void check_expr_or_type (Checker *c, Operand *operand, AstNode *expression, Type *type_hint = NULL);
ExprKind check_expr_base (Checker *c, Operand *operand, AstNode *expression, Type *type_hint);
void check_expr_with_type_hint (Checker *c, Operand *o, AstNode *e, Type *t);
Type * check_type (Checker *c, AstNode *expression, Type *named_type = NULL);
@@ -1260,7 +1260,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
success = false;
}
}
if (type_expr->kind == AstNode_HelperType) {
if (type_expr->kind == AstNode_TypeType) {
is_type_param = true;
if (operands != NULL) {
detemine_type_from_operand = true;
@@ -1283,7 +1283,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
}
if (default_value != NULL) {
if (type_expr->kind == AstNode_HelperType) {
if (type_expr->kind == AstNode_TypeType) {
error(default_value, "A type parameter may not have a default value");
} else {
Operand o = {};
@@ -1817,7 +1817,16 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
bool is_overloaded = false;
isize overload_count = 0;
HashKey key = hash_string(name);
bool is_alias = false;
while (e->kind == Entity_Alias) {
GB_ASSERT(e->Alias.base != NULL);
e = e->Alias.base;
is_alias = true;
}
HashKey key = hash_string(e->token.string);
if (e->kind == Entity_Procedure) {
// NOTE(bill): Overloads are only allowed with the same scope
@@ -2135,6 +2144,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
}
case_end;
case_ast_node(ht, HelperType, e);
return check_type_internal(c, ht->type, type, named_type);
case_end;
case_ast_node(pt, PolyType, e);
AstNode *ident = pt->type;
if (ident->kind != AstNode_Ident) {
@@ -6047,6 +6060,24 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
o->mode = Addressing_Value;
o->type = t_context;
break;
case Token_size_of:
o->mode = Addressing_Builtin;
o->builtin_id = BuiltinProc_size_of;
break;
case Token_align_of:
o->mode = Addressing_Builtin;
o->builtin_id = BuiltinProc_align_of;
break;
case Token_offset_of:
o->mode = Addressing_Builtin;
o->builtin_id = BuiltinProc_offset_of;
break;
case Token_type_of:
o->mode = Addressing_Builtin;
o->builtin_id = BuiltinProc_type_of;
break;
default:
error(node, "Illegal implicit name `%.*s`", LIT(i->string));
return kind;
@@ -6916,7 +6947,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
}
case_end;
case AstNode_HelperType:
case AstNode_TypeType:
case AstNode_ProcType:
case AstNode_PointerType:
case AstNode_ArrayType:
@@ -7001,8 +7032,8 @@ void check_expr(Checker *c, Operand *o, AstNode *e) {
}
void check_expr_or_type(Checker *c, Operand *o, AstNode *e) {
check_expr_base(c, o, e, NULL);
void check_expr_or_type(Checker *c, Operand *o, AstNode *e, Type *type_hint) {
check_expr_base(c, o, e, type_hint);
check_not_tuple(c, o);
error_operand_no_value(o);
}
@@ -7148,6 +7179,11 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = write_expr_to_string(str, fv->value);
case_end;
case_ast_node(ht, HelperType, node);
str = gb_string_appendc(str, "#type ");
str = write_expr_to_string(str, ht->type);
case_end;
case_ast_node(pt, PointerType, node);
str = gb_string_appendc(str, "^");
str = write_expr_to_string(str, pt->type);
@@ -7271,7 +7307,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = gb_string_appendc(str, ")");
case_end;
case_ast_node(ht, HelperType, node);
case_ast_node(ht, TypeType, node);
str = gb_string_appendc(str, "type");
case_end;
+14
View File
@@ -61,6 +61,12 @@ enum BuiltinProcId {
BuiltinProc_abs,
BuiltinProc_clamp,
/* BuiltinProc_sqrt,
BuiltinProc_sin,
BuiltinProc_cos,
BuiltinProc_tan,
BuiltinProc_pow, */
BuiltinProc_transmute,
BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures
@@ -107,6 +113,14 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("abs"), 1, false, Expr_Expr},
{STR_LIT("clamp"), 3, false, Expr_Expr},
/*
{STR_LIT("__sqrt"), 1, false, Expr_Expr},
{STR_LIT("__sin"), 1, false, Expr_Expr},
{STR_LIT("__cos"), 1, false, Expr_Expr},
{STR_LIT("__tan"), 1, false, Expr_Expr},
{STR_LIT("__pow"), 2, false, Expr_Expr},
*/
{STR_LIT("transmute"), 2, false, Expr_Expr},
{STR_LIT(""), 0, true, Expr_Expr}, // DIRECTIVE
+10
View File
@@ -12,6 +12,7 @@ struct DeclInfo;
ENTITY_KIND(TypeName) \
ENTITY_KIND(Procedure) \
ENTITY_KIND(Builtin) \
ENTITY_KIND(Alias) \
ENTITY_KIND(ImportName) \
ENTITY_KIND(LibraryName) \
ENTITY_KIND(Nil) \
@@ -108,6 +109,9 @@ struct Entity {
struct {
i32 id;
} Builtin;
struct {
Entity *base;
} Alias;
struct {
String path;
String name;
@@ -232,6 +236,12 @@ Entity *make_entity_builtin(gbAllocator a, Scope *scope, Token token, Type *type
return entity;
}
Entity *make_entity_alias(gbAllocator a, Scope *scope, Token token, Type *type, Entity *base) {
Entity *entity = alloc_entity(a, Entity_Alias, scope, token, type);
entity->Alias.base = base;
return entity;
}
Entity *make_entity_import_name(gbAllocator a, Scope *scope, Token token, Type *type,
String path, String name, Scope *import_scope) {
Entity *entity = alloc_entity(a, Entity_ImportName, scope, token, type);
+7
View File
@@ -5639,6 +5639,13 @@ void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) {
GB_ASSERT(ident->kind == AstNode_Ident);
Entity *e = entity_of_ident(proc->module->info, ident);
GB_ASSERT(e != NULL);
switch (e->kind) {
case Entity_TypeName:
case Entity_Procedure:
break;
default:
continue;
}
bool polymorphic = is_type_polymorphic(e->type);
+66 -23
View File
@@ -375,9 +375,13 @@ AST_NODE_KIND(_DeclEnd, "", i32) \
AstNode *list; \
}) \
AST_NODE_KIND(_TypeBegin, "", i32) \
AST_NODE_KIND(HelperType, "type", struct { \
AST_NODE_KIND(TypeType, "type", struct { \
Token token; \
}) \
AST_NODE_KIND(HelperType, "helper type", struct { \
Token token; \
AstNode *type; \
}) \
AST_NODE_KIND(PolyType, "polymorphic type", struct { \
Token token; \
AstNode *type; \
@@ -585,6 +589,7 @@ Token ast_node_token(AstNode *node) {
case AstNode_UnionField:
return ast_node_token(node->UnionField.name);
case AstNode_TypeType: return node->TypeType.token;
case AstNode_HelperType: return node->HelperType.token;
case AstNode_PolyType: return node->PolyType.token;
case AstNode_ProcType: return node->ProcType.token;
@@ -829,7 +834,10 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
n->UnionField.list = clone_ast_node(a, n->UnionField.list);
break;
case AstNode_TypeType:
break;
case AstNode_HelperType:
n->HelperType.type = clone_ast_node(a, n->HelperType.type);
break;
case AstNode_ProcType:
n->ProcType.params = clone_ast_node(a, n->ProcType.params);
@@ -1367,12 +1375,20 @@ AstNode *ast_union_field(AstFile *f, AstNode *name, AstNode *list) {
}
AstNode *ast_helper_type(AstFile *f, Token token) {
AstNode *result = make_ast_node(f, AstNode_HelperType);
result->HelperType.token = token;
AstNode *ast_type_type(AstFile *f, Token token) {
AstNode *result = make_ast_node(f, AstNode_TypeType);
result->TypeType.token = token;
return result;
}
AstNode *ast_helper_type(AstFile *f, Token token, AstNode *type) {
AstNode *result = make_ast_node(f, AstNode_HelperType);
result->HelperType.token = token;
result->HelperType.type = type;
return result;
}
AstNode *ast_poly_type(AstFile *f, Token token, AstNode *type) {
AstNode *result = make_ast_node(f, AstNode_PolyType);
result->PolyType.token = token;
@@ -2187,6 +2203,14 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
next_token(f);
return operand;
case Token_size_of:
case Token_align_of:
case Token_offset_of: {
operand = ast_implicit(f, f->curr_token); next_token(f);
return parse_call_expr(f, operand);
}
case Token_String: {
Token token = f->curr_token;
next_token(f);
@@ -2228,6 +2252,9 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
case Token_Hash: {
Token token = expect_token(f, Token_Hash);
if (allow_token(f, Token_type)) {
return ast_helper_type(f, token, parse_type(f));
}
Token name = expect_token(f, Token_Ident);
if (name.string == "run") {
AstNode *expr = parse_expr(f, false);
@@ -3162,7 +3189,7 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) {
break;
}
if (f->type != NULL &&
f->type->kind == AstNode_HelperType) {
f->type->kind == AstNode_TypeType) {
is_generic = true;
break;
}
@@ -3186,7 +3213,7 @@ AstNode *parse_var_type(AstFile *f, bool allow_ellipsis, bool allow_type_token)
AstNode *type = NULL;
if (allow_type_token &&
f->curr_token.kind == Token_type) {
type = ast_helper_type(f, expect_token(f, Token_type));
type = ast_type_type(f, expect_token(f, Token_type));
} else {
type = parse_type_attempt(f);
}
@@ -3473,8 +3500,6 @@ AstNode *parse_record_fields(AstFile *f, isize *field_count_, u32 flags, String
}
AstNode *parse_type_or_ident(AstFile *f) {
AstNode *type = NULL;
switch (f->curr_token.kind) {
case Token_Dollar: {
Token token = expect_token(f, Token_Dollar);
@@ -3482,8 +3507,19 @@ AstNode *parse_type_or_ident(AstFile *f) {
return ast_poly_type(f, token, type);
} break;
case Token_Ident:
{
case Token_type_of: {
AstNode *i = ast_implicit(f, expect_token(f, Token_type_of));
AstNode *type = parse_call_expr(f, i);
while (f->curr_token.kind == Token_Period) {
Token token = f->curr_token;
next_token(f);
AstNode *sel = parse_ident(f);
type = ast_selector_expr(f, token, type, sel);
}
return type;
} break;
case Token_Ident: {
AstNode *e = parse_ident(f);
while (f->curr_token.kind == Token_Period) {
Token token = f->curr_token;
@@ -3496,21 +3532,28 @@ AstNode *parse_type_or_ident(AstFile *f) {
// HACK NOTE(bill): For type_of_val(expr) et al.
// e = parse_call_expr(f, e);
// }
type = e;
return e;
} break;
case Token_Pointer: {
Token token = expect_token(f, Token_Pointer);
AstNode *elem = parse_type(f);
type = ast_pointer_type(f, token, elem);
return ast_pointer_type(f, token, elem);
} break;
case Token_atomic: {
Token token = expect_token(f, Token_atomic);
AstNode *elem = parse_type(f);
type = ast_atomic_type(f, token, elem);
return ast_atomic_type(f, token, elem);
} break;
case Token_Hash: {
Token hash_token = expect_token(f, Token_Hash);
Token type_token = expect_token(f, Token_type);
AstNode *type = parse_type(f);
return ast_helper_type(f, hash_token, type);
}
case Token_OpenBracket: {
Token token = expect_token(f, Token_OpenBracket);
AstNode *count_expr = NULL;
@@ -3541,7 +3584,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
if (is_vector) {
return ast_vector_type(f, token, count_expr, parse_type(f));
}
type = ast_array_type(f, token, count_expr, parse_type(f));
return ast_array_type(f, token, count_expr, parse_type(f));
} break;
case Token_map: {
@@ -3559,7 +3602,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
Token close = expect_token(f, Token_CloseBracket);
value = parse_type(f);
type = ast_map_type(f, token, count, key, value);
return ast_map_type(f, token, count, key, value);
} break;
case Token_struct: {
@@ -3610,7 +3653,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
decls = fields->FieldList.list;
}
type = 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;
case Token_union: {
@@ -3664,7 +3707,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
Token close = expect_token(f, Token_CloseBrace);
type = ast_union_type(f, token, decls, total_decl_name_count, variants);
return ast_union_type(f, token, decls, total_decl_name_count, variants);
} break;
case Token_raw_union: {
@@ -3680,7 +3723,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
decls = fields->FieldList.list;
}
type = ast_raw_union_type(f, token, decls, decl_count);
return ast_raw_union_type(f, token, decls, decl_count);
} break;
case Token_enum: {
@@ -3694,7 +3737,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
Array<AstNode *> values = parse_element_list(f);
Token close = expect_token(f, Token_CloseBrace);
type = ast_enum_type(f, token, base_type, values);
return ast_enum_type(f, token, base_type, values);
} break;
case Token_bit_field: {
@@ -3739,7 +3782,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
close = expect_token(f, Token_CloseBrace);
type = ast_bit_field_type(f, token, fields, align);
return ast_bit_field_type(f, token, fields, align);
} break;
case Token_proc: {
@@ -3748,18 +3791,18 @@ AstNode *parse_type_or_ident(AstFile *f) {
if (pt->ProcType.tags != 0) {
syntax_error(token, "A procedure type cannot have tags");
}
type = pt;
return pt;
} break;
case Token_OpenParen: {
Token open = expect_token(f, Token_OpenParen);
AstNode *type = parse_type(f);
Token close = expect_token(f, Token_CloseParen);
type = ast_paren_expr(f, type, open, close);
return ast_paren_expr(f, type, open, close);
} break;
}
return type;
return NULL;
}
+4
View File
@@ -118,6 +118,10 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
TOKEN_KIND(Token_context, "context"), \
TOKEN_KIND(Token_push_context, "push_context"), \
TOKEN_KIND(Token_push_allocator, "push_allocator"), \
TOKEN_KIND(Token_size_of, "size_of"), \
TOKEN_KIND(Token_align_of, "align_of"), \
TOKEN_KIND(Token_offset_of, "offset_of"), \
TOKEN_KIND(Token_type_of, "type_of"), \
TOKEN_KIND(Token_asm, "asm"), \
TOKEN_KIND(Token_yield, "yield"), \
TOKEN_KIND(Token_await, "await"), \