"Fixed" a proc overload bug. Still needs a *real* fix.
This commit is contained in:
Zac Pierson
2017-03-21 14:16:42 -05:00
47 changed files with 4896 additions and 2413 deletions
+2 -8
View File
@@ -87,14 +87,8 @@ void array__set_capacity(void *ptr, isize capacity, isize element_size) {
x->count = capacity;
}
{
// TODO(bill): Resize rather than copy and delete
void *new_data = gb_alloc(x->allocator, element_size*capacity);
gb_memmove(new_data, x->e, element_size*x->count);
gb_free(x->allocator, x->e);
x->capacity = capacity;
x->e = new_data;
}
x->e = gb_resize(x->allocator, x->e, element_size*x->capacity, element_size*capacity);
x->capacity = capacity;
}
+1 -1
View File
@@ -264,7 +264,7 @@ String get_fullpath_core(gbAllocator a, String path) {
void init_build_context(void) {
BuildContext *bc = &build_context;
bc->ODIN_VENDOR = str_lit("odin");
bc->ODIN_VERSION = str_lit("0.1.1");
bc->ODIN_VERSION = str_lit("0.1.3");
bc->ODIN_ROOT = odin_root_dir();
#if defined(GB_SYSTEM_WINDOWS)
+54 -6
View File
@@ -12,6 +12,7 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
gbString expr_str = expr_to_string(operand->expr);
// TODO(bill): is this a good enough error message?
// TODO(bill): Actually allow built in procedures to be passed around and thus be created on use
error_node(operand->expr,
"Cannot assign builtin procedure `%s` in %.*s",
expr_str,
@@ -276,12 +277,6 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body");
}
// TODO(bill): Is this the best option? What about passing to external shit?!
// if (proc_type->Proc.calling_convention != ProcCC_Odin) {
// error_node(d->proc_lit, "An internal procedure may only have the Odin calling convention");
// proc_type->Proc.calling_convention = ProcCC_Odin;
// }
d->scope = c->context.scope;
GB_ASSERT(pd->body->kind == AstNode_BlockStmt);
@@ -408,6 +403,56 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
}
void check_alias_decl(Checker *c, Entity *e, AstNode *expr) {
GB_ASSERT(e->type == NULL);
GB_ASSERT(e->kind == Entity_Alias);
if (e->flags & EntityFlag_Visited) {
e->type = t_invalid;
return;
}
e->flags |= EntityFlag_Visited;
e->type = t_invalid;
expr = unparen_expr(expr);
if (expr->kind == AstNode_Alias) {
error_node(expr, "#alias of an #alias is not allowed");
return;
}
if (expr->kind == AstNode_Ident) {
Operand o = {0};
Entity *f = check_ident(c, &o, expr, NULL, NULL, true);
if (f != NULL) {
e->Alias.original = f;
e->type = f->type;
}
return;
} else if (expr->kind == AstNode_SelectorExpr) {
Operand o = {0};
Entity *f = check_selector(c, &o, expr, NULL);
if (f != NULL) {
e->Alias.original = f;
e->type = f->type;
}
return;
}
Operand o = {0};
check_expr_or_type(c, &o, expr);
if (o.mode == Addressing_Invalid) {
return;
}
switch (o.mode) {
case Addressing_Type:
e->type = o.type;
break;
default:
error_node(expr, "#alias declarations only allow types");
}
}
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
if (e->type != NULL) {
return;
@@ -443,6 +488,9 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
case Entity_Procedure:
check_proc_lit(c, e, d);
break;
case Entity_Alias:
check_alias_decl(c, e, d->init_expr);
break;
}
c->context = prev;
+117 -188
View File
@@ -272,6 +272,7 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
if (operand->mode == Addressing_Builtin) {
// TODO(bill): is this a good enough error message?
// TODO(bill): Actually allow built in procedures to be passed around and thus be created on use
error_node(operand->expr,
"Cannot assign builtin procedure `%s` in %.*s",
expr_str,
@@ -379,7 +380,8 @@ isize check_fields(Checker *c, AstNode *node, AstNodeArray decls,
Entity **found = map_entity_get(&entity_map, key);
if (found != NULL) {
Entity *e = *found;
// TODO(bill): Scope checking already checks the declaration
// NOTE(bill): Scope checking already checks the declaration but in many cases, this can happen so why not?
// This may be a little janky but it's not really that much of a problem
error(name_token, "`%.*s` is already declared in this type", LIT(name_token.string));
error(e->token, "\tpreviously declared");
} else {
@@ -604,16 +606,11 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
{
ast_node(fl, FieldList, f->list);
// TODO(bill): Just do a gb_memcopy here
// NOTE(bill): Copy the contents for the common fields for now
AstNodeArray list = {0};
array_init_count(&list, c->allocator, ut->fields.count+fl->list.count);
for (isize j = 0; j < ut->fields.count; j++) {
list.e[j] = ut->fields.e[j];
}
for (isize j = 0; j < fl->list.count; j++) {
list.e[j+ut->fields.count] = fl->list.e[j];
}
gb_memmove_array(list.e, ut->fields.e, ut->fields.count);
gb_memmove_array(list.e+ut->fields.count, fl->list.e, fl->list.count);
isize list_count = 0;
for_array(j, list) {
@@ -654,7 +651,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
HashKey key = hash_string(name_token.string);
if (map_entity_get(&entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
// NOTE(bill): Scope checking already checks the declaration
error(name_token, "`%.*s` is already declared in this union", LIT(name_token.string));
} else {
map_entity_set(&entity_map, key, e);
@@ -746,9 +743,9 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
constant_type = named_type;
}
ExactValue iota = make_exact_value_integer(-1);
ExactValue min_value = make_exact_value_integer(0);
ExactValue max_value = make_exact_value_integer(0);
ExactValue iota = exact_value_integer(-1);
ExactValue min_value = exact_value_integer(0);
ExactValue max_value = exact_value_integer(0);
for_array(i, et->fields) {
AstNode *field = et->fields.e[i];
@@ -783,10 +780,10 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
if (o.mode != Addressing_Invalid) {
iota = o.value;
} else {
iota = exact_binary_operator_value(Token_Add, iota, make_exact_value_integer(1));
iota = exact_binary_operator_value(Token_Add, iota, exact_value_integer(1));
}
} else {
iota = exact_binary_operator_value(Token_Add, iota, make_exact_value_integer(1));
iota = exact_binary_operator_value(Token_Add, iota, exact_value_integer(1));
}
@@ -839,7 +836,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
enum_type->Record.field_count = field_count;
enum_type->Record.enum_count = make_entity_constant(c->allocator, c->context.scope,
make_token_ident(str_lit("count")), t_int, make_exact_value_integer(field_count));
make_token_ident(str_lit("count")), t_int, exact_value_integer(field_count));
enum_type->Record.enum_min_value = make_entity_constant(c->allocator, c->context.scope,
make_token_ident(str_lit("min_value")), constant_type, min_value);
enum_type->Record.enum_max_value = make_entity_constant(c->allocator, c->context.scope,
@@ -1028,7 +1025,7 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
}
void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint) {
Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint, bool allow_import_name) {
GB_ASSERT(n->kind == AstNode_Ident);
o->mode = Addressing_Invalid;
o->expr = n;
@@ -1046,7 +1043,7 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
if (named_type != NULL) {
set_base_type(named_type, t_invalid);
}
return;
return NULL;
}
bool is_overloaded = false;
@@ -1095,7 +1092,7 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
o->type = t_invalid;
o->overload_count = overload_count;
o->overload_entities = procs;
return;
return NULL;
}
gb_free(heap_allocator(), procs);
}
@@ -1106,20 +1103,26 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
if (e->type == NULL) {
compiler_error("Compiler error: How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(name));
return;
return NULL;
}
e->flags |= EntityFlag_Used;
Entity *original_e = e;
while (e != NULL && e->kind == Entity_Alias && e->Alias.original != NULL) {
e = e->Alias.original;
}
Type *type = e->type;
switch (e->kind) {
case Entity_Constant:
if (type == t_invalid) {
o->type = t_invalid;
return;
return e;
}
o->value = e->Constant.value;
if (o->value.kind == ExactValue_Invalid) {
return;
return e;
}
o->mode = Addressing_Constant;
break;
@@ -1128,7 +1131,7 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
e->flags |= EntityFlag_Used;
if (type == t_invalid) {
o->type = t_invalid;
return;
return e;
}
o->mode = Addressing_Variable;
if (e->Variable.is_immutable) {
@@ -1136,10 +1139,10 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
}
break;
case Entity_TypeName: {
case Entity_TypeName:
// NOTE(bill): Cyclical dependency checking is handled in the "type system" not here
o->mode = Addressing_Type;
// TODO(bill): Fix cyclical dependancy checker
} break;
break;
case Entity_Procedure:
o->mode = Addressing_Value;
@@ -1151,22 +1154,29 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
break;
case Entity_ImportName:
error_node(n, "Use of import `%.*s` not in selector", LIT(e->ImportName.name));
return;
if (!allow_import_name) {
error_node(n, "Use of import `%.*s` not in selector", LIT(name));
}
return e;
case Entity_LibraryName:
error_node(n, "Use of library `%.*s` not in #foreign tag", LIT(e->LibraryName.name));
return;
error_node(n, "Use of library `%.*s` not in #foreign tag", LIT(name));
return e;
case Entity_Label:
o->mode = Addressing_NoValue;
break;
case Entity_Nil:
o->mode = Addressing_Value;
break;
default:
compiler_error("Compiler error: Unknown EntityKind");
compiler_error("Unknown EntityKind");
break;
}
o->type = type;
return e;
}
i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) {
@@ -1342,7 +1352,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
switch (e->kind) {
case_ast_node(i, Ident, e);
Operand o = {0};
check_ident(c, &o, e, named_type, NULL);
check_ident(c, &o, e, named_type, NULL, false);
switch (o.mode) {
case Addressing_Invalid:
@@ -1663,7 +1673,7 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
return true;
}
type = base_type(base_enum_type(type));
type = core_type(type);
if (is_type_boolean(type)) {
return in_value.kind == ExactValue_Bool;
@@ -1682,7 +1692,7 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type
if (s < 64) {
umax = (1ull << s) - 1ull;
} else {
// TODO(bill): I NEED A PROPER BIG NUMBER LIBRARY THAT CAN SUPPORT 128 bit integers and floats
// IMPORTANT TODO(bill): I NEED A PROPER BIG NUMBER LIBRARY THAT CAN SUPPORT 128 bit integers and floats
s = 64;
}
i64 imax = (1ll << (s-1ll));
@@ -1860,7 +1870,7 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) {
}
x->mode = Addressing_Constant;
x->type = t_untyped_bool;
x->value = make_exact_value_bool(comp);
x->value = exact_value_bool(comp);
return;
}
@@ -1913,10 +1923,11 @@ void check_comparison(Checker *c, Operand *x, Operand *y, TokenKind op) {
} else {
if (x->mode == Addressing_Constant &&
y->mode == Addressing_Constant) {
x->value = make_exact_value_bool(compare_exact_values(op, x->value, y->value));
x->value = exact_value_bool(compare_exact_values(op, x->value, y->value));
} else {
x->mode = Addressing_Value;
update_expr_type(c, x->expr, default_type(x->type), true);
update_expr_type(c, y->expr, default_type(y->type), true);
}
@@ -1995,7 +2006,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
x->type = t_untyped_integer;
}
x->value = exact_value_shift(be->op.kind, x_val, make_exact_value_integer(amount));
x->value = exact_value_shift(be->op.kind, x_val, exact_value_integer(amount));
if (is_type_typed(x->type)) {
check_is_expressible(c, x, base_type(x->type));
@@ -2094,7 +2105,7 @@ Operand check_ptr_addition(Checker *c, TokenKind op, Operand *ptr, Operand *offs
new_ptr_val -= elem_size*offset_val;
}
operand.mode = Addressing_Constant;
operand.value = make_exact_value_pointer(new_ptr_val);
operand.value = exact_value_pointer(new_ptr_val);
}
return operand;
@@ -2108,8 +2119,8 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
}
Type *x = operand->type;
Type *src = base_type(base_enum_type(x));
Type *dst = base_type(base_enum_type(y));
Type *src = core_type(x);
Type *dst = core_type(y);
if (are_types_identical(src, dst)) {
return true;
}
@@ -2372,7 +2383,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
GB_ASSERT(op.kind == Token_Sub);
i64 bytes = a.value_pointer - b.value_pointer;
i64 diff = bytes/type_size_of(c->allocator, type);
x->value = make_exact_value_pointer(diff);
x->value = exact_value_pointer(diff);
return;
}
@@ -2517,7 +2528,7 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
return;
}
Type *t = base_type(base_enum_type(target_type));
Type *t = core_type(target_type);
switch (t->kind) {
case Type_Basic:
if (operand->mode == Addressing_Constant) {
@@ -2678,6 +2689,11 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
add_entity_use(c, op_expr, e);
expr_entity = e;
Entity *original_e = e;
while (e != NULL && e->kind == Entity_Alias && e->Alias.original != NULL) {
e = e->Alias.original;
}
if (e != NULL && e->kind == Entity_ImportName && selector->kind == AstNode_Ident) {
// IMPORTANT NOTE(bill): This is very sloppy code but it's also very fragile
// It pretty much needs to be in this order and this way
@@ -2832,7 +2848,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
operand->type != NULL && is_type_untyped(operand->type) && is_type_string(operand->type)) {
String s = operand->value.value_string;
operand->mode = Addressing_Constant;
operand->value = make_exact_value_integer(s.len);
operand->value = exact_value_integer(s.len);
operand->type = t_untyped_integer;
return NULL;
}
@@ -2869,7 +2885,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
operand->value = entity->Constant.value;
break;
case Entity_Variable:
// TODO(bill): This is the rule I need?
// TODO(bill): Is this the rule I need?
if (operand->mode == Addressing_Immutable) {
// Okay
} else if (sel.indirect || operand->mode != Addressing_Value) {
@@ -3058,9 +3074,11 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
case BuiltinProc_clear: {
Type *type = operand->type;
if (!is_type_dynamic_array(type) && !is_type_map(type)) {
bool is_pointer = is_type_pointer(type);
type = base_type(type_deref(type));
if (!is_type_dynamic_array(type) && !is_type_map(type) && !is_type_slice(type)) {
gbString str = type_to_string(type);
error_node(operand->expr, "Expected a map or dynamic array, got `%s`", str);
error_node(operand->expr, "Invalid type for `clear`, got `%s`", str);
gb_string_free(str);
return false;
}
@@ -3092,14 +3110,12 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
}
Type *elem = NULL;
Type *slice_elem = NULL;
if (is_type_dynamic_array(type)) {
// TODO(bill): Semi-memory leaks
elem = type->DynamicArray.elem;
} else {
elem = type->Slice.elem;
}
slice_elem = make_type_slice(c->allocator, elem);
Type *slice_elem = make_type_slice(c->allocator, elem);
Type *proc_type_params = make_type_tuple(c->allocator);
proc_type_params->Tuple.variables = gb_alloc_array(c->allocator, Entity *, 2);
@@ -3158,7 +3174,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
}
operand->mode = Addressing_Constant;
operand->value = make_exact_value_integer(type_size_of(c->allocator, type));
operand->value = exact_value_integer(type_size_of(c->allocator, type));
operand->type = t_untyped_integer;
} break;
@@ -3171,7 +3187,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
}
operand->mode = Addressing_Constant;
operand->value = make_exact_value_integer(type_size_of(c->allocator, operand->type));
operand->value = exact_value_integer(type_size_of(c->allocator, operand->type));
operand->type = t_untyped_integer;
break;
@@ -3183,7 +3199,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
return false;
}
operand->mode = Addressing_Constant;
operand->value = make_exact_value_integer(type_align_of(c->allocator, type));
operand->value = exact_value_integer(type_align_of(c->allocator, type));
operand->type = t_untyped_integer;
} break;
@@ -3195,7 +3211,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
}
operand->mode = Addressing_Constant;
operand->value = make_exact_value_integer(type_align_of(c->allocator, operand->type));
operand->value = exact_value_integer(type_align_of(c->allocator, operand->type));
operand->type = t_untyped_integer;
break;
@@ -3239,7 +3255,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
}
operand->mode = Addressing_Constant;
operand->value = make_exact_value_integer(type_offset_of_from_selection(c->allocator, type, sel));
operand->value = exact_value_integer(type_offset_of_from_selection(c->allocator, type, sel));
operand->type = t_untyped_integer;
} break;
@@ -3288,7 +3304,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
operand->mode = Addressing_Constant;
// IMPORTANT TODO(bill): Fix for anonymous fields
operand->value = make_exact_value_integer(type_offset_of_from_selection(c->allocator, type, sel));
operand->value = exact_value_integer(type_offset_of_from_selection(c->allocator, type, sel));
operand->type = t_untyped_integer;
} break;
@@ -3486,113 +3502,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
operand->mode = Addressing_Value;
} break;
#if 0
case BuiltinProc_ptr_offset: {
// ptr_offset :: proc(ptr: ^T, offset: int) -> ^T
// ^T cannot be rawptr
Type *ptr_type = base_type(operand->type);
if (!is_type_pointer(ptr_type)) {
gbString type_str = type_to_string(operand->type);
defer (gb_string_free(type_str));
error_node(call,
"Expected a pointer to `ptr_offset`, got `%s`",
type_str);
return false;
}
if (ptr_type == t_rawptr) {
error_node(call,
"`rawptr` cannot have pointer arithmetic");
return false;
}
AstNode *offset = ce->args.e[1];
Operand op = {0};
check_expr(c, &op, offset);
if (op.mode == Addressing_Invalid)
return false;
Type *offset_type = base_type(op.type);
if (!is_type_integer(offset_type)) {
error_node(op.expr, "Pointer offsets for `ptr_offset` must be an integer");
return false;
}
if (operand->mode == Addressing_Constant &&
op.mode == Addressing_Constant) {
i64 ptr = operand->value.value_pointer;
i64 elem_size = type_size_of(c->allocator, ptr_type->Pointer.elem);
ptr += elem_size * op.value.value_integer;
operand->value.value_pointer = ptr;
} else {
operand->mode = Addressing_Value;
}
} break;
case BuiltinProc_ptr_sub: {
// ptr_sub :: proc(a, b: ^T) -> int
// ^T cannot be rawptr
Type *ptr_type = base_type(operand->type);
if (!is_type_pointer(ptr_type)) {
gbString type_str = type_to_string(operand->type);
defer (gb_string_free(type_str));
error_node(call,
"Expected a pointer to `ptr_add`, got `%s`",
type_str);
return false;
}
if (ptr_type == t_rawptr) {
error_node(call,
"`rawptr` cannot have pointer arithmetic");
return false;
}
AstNode *offset = ce->args[1];
Operand op = {0};
check_expr(c, &op, offset);
if (op.mode == Addressing_Invalid)
return false;
if (!is_type_pointer(op.type)) {
gbString type_str = type_to_string(operand->type);
defer (gb_string_free(type_str));
error_node(call,
"Expected a pointer to `ptr_add`, got `%s`",
type_str);
return false;
}
if (base_type(op.type) == t_rawptr) {
error_node(call,
"`rawptr` cannot have pointer arithmetic");
return false;
}
if (!are_types_identical(operand->type, op.type)) {
gbString a = type_to_string(operand->type);
gbString b = type_to_string(op.type);
defer (gb_string_free(a));
defer (gb_string_free(b));
error_node(op.expr,
"`ptr_sub` requires to pointer of the same type. Got `%s` and `%s`.", a, b);
return false;
}
operand->type = t_int;
if (operand->mode == Addressing_Constant &&
op.mode == Addressing_Constant) {
u8 *ptr_a = cast(u8 *)operand->value.value_pointer;
u8 *ptr_b = cast(u8 *)op.value.value_pointer;
isize elem_size = type_size_of(c->allocator, ptr_type->Pointer.elem);
operand->value = make_exact_value_integer((ptr_a - ptr_b) / elem_size);
} else {
operand->mode = Addressing_Value;
}
} break;
#endif
case BuiltinProc_slice_ptr: {
// slice_ptr :: proc(a: ^T, len: int) -> []T
// slice_ptr :: proc(a: ^T, len, cap: int) -> []T
// ^T cannot be rawptr
Type *ptr_type = base_type(operand->type);
if (!is_type_pointer(ptr_type)) {
@@ -3610,21 +3522,28 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
return false;
}
AstNode *len = ce->args.e[1];
isize arg_count = ce->args.count;
if (arg_count < 2 || 3 < arg_count) {
error_node(ce->args.e[0], "`slice_ptr` expects 2 or 3 arguments, found %td", arg_count);
// NOTE(bill): Return the correct type to reduce errors
} else {
// If any are constant
i64 sizes[2] = {0};
isize size_count = 0;
for (isize i = 1; i < arg_count; i++) {
i64 val = 0;
bool ok = check_index_value(c, ce->args.e[i], -1, &val);
if (ok && val >= 0) {
GB_ASSERT(size_count < gb_count_of(sizes));
sizes[size_count++] = val;
}
}
Operand op = {0};
check_expr(c, &op, len);
if (op.mode == Addressing_Invalid)
return false;
if (!is_type_integer(op.type)) {
gbString type_str = type_to_string(operand->type);
error_node(call,
"Length for `slice_ptr` must be an integer, got `%s`",
type_str);
gb_string_free(type_str);
return false;
if (size_count == 2 && sizes[0] > sizes[1]) {
error_node(ce->args.e[1], "`slice_ptr` count and capacity are swapped");
// No need quit
}
}
operand->type = make_type_slice(c->allocator, ptr_type->Pointer.elem);
operand->mode = Addressing_Value;
} break;
@@ -4412,7 +4331,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
case_end;
case_ast_node(i, Ident, node);
check_ident(c, o, node, NULL, type_hint);
check_ident(c, o, node, NULL, type_hint, false);
case_end;
case_ast_node(bl, BasicLit, node);
@@ -4426,24 +4345,24 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
}
o->mode = Addressing_Constant;
o->type = t;
o->value = make_exact_value_from_basic_literal(*bl);
o->value = exact_value_from_basic_literal(*bl);
case_end;
case_ast_node(bd, BasicDirective, node);
if (str_eq(bd->name, str_lit("file"))) {
o->type = t_untyped_string;
o->value = make_exact_value_string(bd->token.pos.file);
o->value = exact_value_string(bd->token.pos.file);
} else if (str_eq(bd->name, str_lit("line"))) {
o->type = t_untyped_integer;
o->value = make_exact_value_integer(bd->token.pos.line);
o->value = exact_value_integer(bd->token.pos.line);
} else if (str_eq(bd->name, str_lit("procedure"))) {
if (c->proc_stack.count == 0) {
error_node(node, "#procedure may only be used within procedures");
o->type = t_untyped_string;
o->value = make_exact_value_string(str_lit(""));
o->value = exact_value_string(str_lit(""));
} else {
o->type = t_untyped_string;
o->value = make_exact_value_string(c->context.proc_name);
o->value = exact_value_string(c->context.proc_name);
}
} else {
@@ -4476,13 +4395,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
case_end;
case_ast_node(te, TernaryExpr, node);
if (c->proc_stack.count == 0) {
error_node(node, "A ternary expression is only allowed within a procedure");
goto error;
}
Operand operand = {Addressing_Invalid};
check_expr(c, &operand, te->cond);
if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) {
Operand cond = {Addressing_Invalid};
check_expr(c, &cond, te->cond);
if (cond.mode != Addressing_Invalid && !is_type_boolean(cond.type)) {
error_node(te->cond, "Non-boolean condition in if expression");
}
@@ -4524,6 +4439,20 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
o->type = x.type;
o->mode = Addressing_Value;
if (cond.mode == Addressing_Constant && is_type_boolean(cond.type) &&
x.mode == Addressing_Constant &&
y.mode == Addressing_Constant) {
o->mode = Addressing_Constant;
if (cond.value.value_bool) {
o->value = x.value;
} else {
o->value = y.value;
}
}
case_end;
case_ast_node(cl, CompoundLit, node);
@@ -4850,7 +4779,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
if (is_constant) {
o->mode = Addressing_Constant;
o->value = make_exact_value_compound(node);
o->value = exact_value_compound(node);
} else {
o->mode = Addressing_Value;
}
@@ -5625,7 +5554,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
case_end;
case_ast_node(ht, HelperType, node);
str = gb_string_appendc(str, "type ");
str = gb_string_appendc(str, "#type ");
str = write_expr_to_string(str, ht->type);
case_end;
}
+143 -84
View File
@@ -307,16 +307,21 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
return rhs->type;
}
bool check_valid_type_match_type(Type *type, bool *is_union_ptr, bool *is_any) {
if (is_type_pointer(type)) {
*is_union_ptr = is_type_union(type_deref(type));
return *is_union_ptr;
typedef enum MatchTypeKind {
MatchType_Invalid,
MatchType_Union,
MatchType_Any,
} MatchTypeKind;
MatchTypeKind check_valid_type_match_type(Type *type) {
type = type_deref(type);
if (is_type_union(type)) {
return MatchType_Union;
}
if (is_type_any(type)) {
*is_any = true;
return *is_any;
return MatchType_Any;
}
return false;
return MatchType_Invalid;
}
void check_stmt_internal(Checker *c, AstNode *node, u32 flags);
@@ -385,6 +390,47 @@ void check_when_stmt(Checker *c, AstNodeWhenStmt *ws, u32 flags) {
}
}
void check_label(Checker *c, AstNode *label) {
if (label == NULL) {
return;
}
ast_node(l, Label, label);
if (l->name->kind != AstNode_Ident) {
error_node(l->name, "A label's name must be an identifier");
return;
}
String name = l->name->Ident.string;
if (str_eq(name, str_lit("_"))) {
error_node(l->name, "A label's name cannot be a blank identifier");
return;
}
if (c->proc_stack.count == 0) {
error_node(l->name, "A label is only allowed within a procedure");
return;
}
GB_ASSERT(c->context.decl != NULL);
bool ok = true;
for_array(i, c->context.decl->labels) {
BlockLabel bl = c->context.decl->labels.e[i];
if (str_eq(bl.name, name)) {
error_node(label, "Duplicate label with the name `%.*s`", LIT(name));
ok = false;
break;
}
}
Entity *e = make_entity_label(c->allocator, c->context.scope, l->name->Ident, t_invalid, label);
add_entity(c, c->context.scope, l->name, e);
if (ok) {
BlockLabel bl = {name, label};
array_add(&c->context.decl->labels, bl);
}
}
void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
u32 mod_flags = flags & (~Stmt_FallthroughAllowed);
switch (node->kind) {
@@ -475,9 +521,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
return;
}
// TODO(bill): This is a very similar to check_init_variables, should I merge the two some how or just
// leave it?
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
@@ -515,7 +558,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
error(op, "Unknown Assignment operation `%.*s`", LIT(op.string));
return;
}
// TODO(bill): Check if valid assignment operator
Operand operand = {Addressing_Invalid};
AstNode binary_expr = {AstNode_BinaryExpr};
ast_node(be, BinaryExpr, &binary_expr);
@@ -580,7 +622,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (c->context.in_defer) {
error(rs->token, "You cannot `return` within a defer statement");
// TODO(bill): Should I break here?
break;
}
@@ -619,7 +660,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
case_ast_node(fs, ForStmt, node);
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
check_open_scope(c, node);
check_label(c, fs->label); // TODO(bill): What should the label's "scope" be?
if (fs->init != NULL) {
check_stmt(c, fs->init, 0);
@@ -648,6 +691,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
check_open_scope(c, node);
check_label(c, rs->label);
Type *val = NULL;
Type *idx = NULL;
Entity *entities[2] = {0};
@@ -718,7 +763,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
case Token_Ellipsis: op = Token_Lt; break;
default: error(ie->op, "Invalid range operator"); break;
}
bool ok = compare_exact_values(Token_Lt, a, b);
bool ok = compare_exact_values(op, a, b);
if (!ok) {
// TODO(bill): Better error message
error(ie->op, "Invalid interval range");
@@ -850,7 +895,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
} else {
x.mode = Addressing_Constant;
x.type = t_bool;
x.value = make_exact_value_bool(true);
x.value = exact_value_bool(true);
Token token = {0};
token.pos = ast_node_token(ms->body).pos;
@@ -897,7 +942,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
ast_node(cc, CaseClause, stmt);
for_array(j, cc->list) {
AstNode *expr = cc->list.e[j];
Operand y = {0};
@@ -982,8 +1026,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
mod_flags |= Stmt_BreakAllowed;
check_open_scope(c, node);
bool is_union_ptr = false;
bool is_any = false;
MatchTypeKind match_type_kind = MatchType_Invalid;
if (ms->tag->kind != AstNode_AssignStmt) {
error_node(ms->tag, "Expected an `in` assignment for this type match statement");
@@ -1005,7 +1048,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
check_expr(c, &x, rhs);
check_assignment(c, &x, NULL, str_lit("type match expression"));
if (!check_valid_type_match_type(x.type, &is_union_ptr, &is_any)) {
match_type_kind = check_valid_type_match_type(x.type);
if (check_valid_type_match_type(x.type) == MatchType_Invalid) {
gbString str = type_to_string(x.type);
error_node(x.expr,
"Invalid type for this type match expression, got `%s`", str);
@@ -1013,7 +1057,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
break;
}
// NOTE(bill): Check for multiple defaults
AstNode *first_default = NULL;
ast_node(bs, BlockStmt, ms->body);
@@ -1048,7 +1091,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
MapBool seen = {0};
MapBool seen = {0}; // Multimap
map_bool_init(&seen, heap_allocator());
for_array(i, bs->stmts) {
@@ -1062,74 +1105,68 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
// TODO(bill): Make robust
Type *bt = base_type(type_deref(x.type));
AstNode *type_expr = cc->list.count > 0 ? cc->list.e[0] : NULL;
Type *case_type = NULL;
if (type_expr != NULL) { // Otherwise it's a default expression
Operand y = {0};
check_expr_or_type(c, &y, type_expr);
for_array(type_index, cc->list) {
AstNode *type_expr = cc->list.e[type_index];
if (type_expr != NULL) { // Otherwise it's a default expression
Operand y = {0};
check_expr_or_type(c, &y, type_expr);
if (is_union_ptr) {
GB_ASSERT(is_type_union(bt));
bool tag_type_found = false;
for (isize i = 0; i < bt->Record.variant_count; i++) {
Entity *f = bt->Record.variants[i];
if (are_types_identical(f->type, y.type)) {
tag_type_found = true;
break;
if (match_type_kind == MatchType_Union) {
GB_ASSERT(is_type_union(bt));
bool tag_type_found = false;
for (isize i = 0; i < bt->Record.variant_count; i++) {
Entity *f = bt->Record.variants[i];
if (are_types_identical(f->type, y.type)) {
tag_type_found = true;
break;
}
}
if (!tag_type_found) {
gbString type_str = type_to_string(y.type);
error_node(y.expr, "Unknown tag type, got `%s`", type_str);
gb_string_free(type_str);
continue;
}
case_type = y.type;
} else if (match_type_kind == MatchType_Any) {
case_type = y.type;
} else {
GB_PANIC("Unknown type to type match statement");
}
if (!tag_type_found) {
gbString type_str = type_to_string(y.type);
error_node(y.expr, "Unknown tag type, got `%s`", type_str);
gb_string_free(type_str);
continue;
}
case_type = y.type;
} else if (is_any) {
case_type = y.type;
} else {
GB_PANIC("Unknown type to type match statement");
}
HashKey key = hash_pointer(y.type);
bool *found = map_bool_get(&seen, key);
if (found) {
TokenPos pos = cc->token.pos;
gbString expr_str = expr_to_string(y.expr);
error_node(y.expr,
"Duplicate type case `%s`\n"
"\tprevious type case at %.*s(%td:%td)",
expr_str,
LIT(pos.file), pos.line, pos.column);
gb_string_free(expr_str);
break;
HashKey key = hash_pointer(y.type);
bool *found = map_bool_get(&seen, key);
if (found) {
TokenPos pos = cc->token.pos;
gbString expr_str = expr_to_string(y.expr);
error_node(y.expr,
"Duplicate type case `%s`\n"
"\tprevious type case at %.*s(%td:%td)",
expr_str,
LIT(pos.file), pos.line, pos.column);
gb_string_free(expr_str);
break;
}
map_bool_set(&seen, key, cast(bool)true);
}
map_bool_set(&seen, key, cast(bool)true);
}
check_open_scope(c, stmt);
if (cc->list.count > 1) {
case_type = NULL;
}
if (case_type == NULL) {
if (is_union_ptr) {
case_type = type_deref(x.type);
} else {
case_type = x.type;
}
case_type = x.type;
}
add_type_info_type(c, case_type);
check_open_scope(c, stmt);
{
// NOTE(bill): Dummy type
Type *tt = case_type;
if (is_union_ptr) {
tt = make_type_pointer(c->allocator, case_type);
add_type_info_type(c, tt);
}
Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, lhs->Ident, tt, true);
Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, lhs->Ident, case_type, true);
tag_var->flags |= EntityFlag_Used;
add_entity(c, c->context.scope, lhs, tag_var);
add_entity_use(c, lhs, tag_var);
add_implicit_entity(c, stmt, tag_var);
}
check_stmt_list(c, cc->stmts, mod_flags);
check_close_scope(c);
@@ -1173,20 +1210,38 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
error(token, "Invalid AST: Branch Statement `%.*s`", LIT(token.string));
break;
}
if (bs->label != NULL) {
if (bs->label->kind != AstNode_Ident) {
error_node(bs->label, "A branch statement's label name must be an identifier");
return;
}
AstNode *ident = bs->label;
String name = ident->Ident.string;
Entity *e = scope_lookup_entity(c->context.scope, name);
if (e == NULL) {
error_node(ident, "Undeclared label name: %.*s", LIT(name));
return;
}
add_entity_use(c, ident, e);
if (e->kind != Entity_Label) {
error_node(ident, "`%.*s` is not a label", LIT(name));
return;
}
}
case_end;
case_ast_node(us, UsingStmt, node);
switch (us->node->kind) {
default:
// TODO(bill): Better error message for invalid using statement
error(us->token, "Invalid `using` statement");
break;
case_ast_node(es, ExprStmt, us->node);
// TODO(bill): Allow for just a LHS expression list rather than this silly code
if (us->list.count == 0) {
error(us->token, "Empty `using` list");
return;
}
for_array(i, us->list) {
AstNode *expr = unparen_expr(us->list.e[0]);
Entity *e = NULL;
bool is_selector = false;
AstNode *expr = unparen_expr(es->expr);
if (expr->kind == AstNode_Ident) {
String name = expr->Ident.string;
e = scope_lookup_entity(c->context.scope, name);
@@ -1194,11 +1249,14 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
Operand o = {0};
e = check_selector(c, &o, expr, NULL);
is_selector = true;
} else if (expr->kind == AstNode_Implicit) {
error(us->token, "`using` applied to an implicit value");
continue;
}
if (e == NULL) {
error(us->token, "`using` applied to an unknown entity");
return;
continue;
}
switch (e->kind) {
@@ -1296,6 +1354,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
error(us->token, "`using` cannot be applied to `nil`");
break;
case Entity_Label:
error(us->token, "`using` cannot be applied to a label");
break;
case Entity_Invalid:
error(us->token, "`using` cannot be applied to an invalid entity");
break;
@@ -1303,13 +1365,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
default:
GB_PANIC("TODO(bill): `using` other expressions?");
}
case_end;
}
case_end;
case_ast_node(pa, PushAllocator, node);
Operand op = {0};
check_expr(c, &op, pa->expr);
+56 -30
View File
@@ -98,7 +98,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
// {STR_LIT("ptr_offset"), 2, false, Expr_Expr},
// {STR_LIT("ptr_sub"), 2, false, Expr_Expr},
{STR_LIT("slice_ptr"), 2, false, Expr_Expr},
{STR_LIT("slice_ptr"), 2, true, Expr_Expr},
{STR_LIT("slice_to_bytes"), 1, false, Expr_Stmt},
{STR_LIT("min"), 2, false, Expr_Expr},
@@ -163,6 +163,11 @@ bool is_operand_nil(Operand o) {
}
typedef struct BlockLabel {
String name;
AstNode *label; // AstNode_Label;
} BlockLabel;
// DeclInfo is used to store information of certain declarations to allow for "any order" usage
typedef struct DeclInfo {
Scope *scope;
@@ -175,16 +180,19 @@ typedef struct DeclInfo {
AstNode *proc_lit; // AstNode_ProcLit
MapBool deps; // Key: Entity *
Array(BlockLabel) labels;
} DeclInfo;
// ProcedureInfo stores the information needed for checking a procedure
typedef struct ProcedureInfo {
AstFile * file;
Token token;
DeclInfo *decl;
Type * type; // Type_Procedure
AstNode * body; // AstNode_BlockStmt
u32 tags;
AstFile * file;
Token token;
DeclInfo * decl;
Type * type; // Type_Procedure
AstNode * body; // AstNode_BlockStmt
u32 tags;
} ProcedureInfo;
// ExprInfo stores information used for "untyped" expressions
@@ -208,21 +216,21 @@ ExprInfo make_expr_info(bool is_lhs, AddressingMode mode, Type *type, ExactValue
#include "map.c"
typedef struct Scope {
Scope * parent;
Scope * prev, *next;
Scope * first_child;
Scope * last_child;
MapEntity elements; // Key: String
MapBool implicit; // Key: Entity *
Scope * parent;
Scope * prev, *next;
Scope * first_child;
Scope * last_child;
MapEntity elements; // Key: String
MapBool implicit; // Key: Entity *
Array(Scope *) shared;
Array(Scope *) imported;
bool is_proc;
bool is_global;
bool is_file;
bool is_init;
bool has_been_imported; // This is only applicable to file scopes
AstFile * file;
Array(Scope *) shared;
Array(Scope *) imported;
bool is_proc;
bool is_global;
bool is_file;
bool is_init;
bool has_been_imported; // This is only applicable to file scopes
AstFile * file;
} Scope;
gb_global Scope *universal_scope = NULL;
@@ -278,6 +286,7 @@ typedef struct CheckerInfo {
MapScope scopes; // Key: AstNode * | Node -> Scope
MapExprInfo untyped; // Key: AstNode * | Expression -> ExprInfo
MapDeclInfo entities; // Key: Entity *
MapEntity implicits; // Key: AstNode *
MapEntity foreigns; // Key: String
MapAstFile files; // Key: String (full path)
MapIsize type_info_map; // Key: Type *
@@ -320,6 +329,7 @@ typedef Array(DelayedEntity) DelayedEntities;
void init_declaration_info(DeclInfo *d, Scope *scope) {
d->scope = scope;
map_bool_init(&d->deps, heap_allocator());
array_init(&d->labels, heap_allocator());
}
DeclInfo *make_declaration_info(gbAllocator a, Scope *scope) {
@@ -357,9 +367,9 @@ Scope *make_scope(Scope *parent, gbAllocator allocator) {
Scope *s = gb_alloc_item(allocator, Scope);
s->parent = parent;
map_entity_init(&s->elements, heap_allocator());
map_bool_init(&s->implicit, heap_allocator());
array_init(&s->shared, heap_allocator());
array_init(&s->imported, heap_allocator());
map_bool_init(&s->implicit, heap_allocator());
array_init(&s->shared, heap_allocator());
array_init(&s->imported, heap_allocator());
if (parent != NULL && parent != universal_scope) {
DLIST_APPEND(parent->first_child, parent->last_child, s);
@@ -455,6 +465,9 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit
if (found) {
Entity *e = *found;
if (gone_thru_proc) {
if (e->kind == Entity_Label) {
continue;
}
if (e->kind == Entity_Variable &&
!e->scope->is_file &&
!e->scope->is_global) {
@@ -596,7 +609,7 @@ void add_global_constant(gbAllocator a, String name, Type *type, ExactValue valu
void add_global_string_constant(gbAllocator a, String name, String value) {
add_global_constant(a, name, t_untyped_string, make_exact_value_string(value));
add_global_constant(a, name, t_untyped_string, exact_value_string(value));
}
@@ -616,8 +629,8 @@ void init_universal_scope(void) {
}
// Constants
add_global_constant(a, str_lit("true"), t_untyped_bool, make_exact_value_bool(true));
add_global_constant(a, str_lit("false"), t_untyped_bool, make_exact_value_bool(false));
add_global_constant(a, str_lit("true"), t_untyped_bool, exact_value_bool(true));
add_global_constant(a, str_lit("false"), t_untyped_bool, exact_value_bool(false));
add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil));
add_global_entity(make_entity_library_name(a, universal_scope,
@@ -662,6 +675,7 @@ void init_checker_info(CheckerInfo *i) {
map_decl_info_init(&i->entities, a);
map_expr_info_init(&i->untyped, a);
map_entity_init(&i->foreigns, a);
map_entity_init(&i->implicits, a);
map_isize_init(&i->type_info_map, a);
map_ast_file_init(&i->files, a);
i->type_info_count = 0;
@@ -676,6 +690,7 @@ void destroy_checker_info(CheckerInfo *i) {
map_decl_info_destroy(&i->entities);
map_expr_info_destroy(&i->untyped);
map_entity_destroy(&i->foreigns);
map_entity_destroy(&i->implicits);
map_isize_destroy(&i->type_info_map);
map_ast_file_destroy(&i->files);
}
@@ -816,7 +831,7 @@ bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
return false;
}
error(entity->token,
"Redeclararation of `%.*s` in this scope through `using`\n"
"Redeclaration of `%.*s` in this scope through `using`\n"
"\tat %.*s(%td:%td)",
LIT(name),
LIT(up->token.pos.file), up->token.pos.line, up->token.pos.column);
@@ -827,7 +842,7 @@ bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
return false;
}
error(entity->token,
"Redeclararation of `%.*s` in this scope\n"
"Redeclaration of `%.*s` in this scope\n"
"\tat %.*s(%td:%td)",
LIT(name),
LIT(pos.file), pos.line, pos.column);
@@ -861,6 +876,12 @@ void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclIn
}
void add_implicit_entity(Checker *c, AstNode *node, Entity *e) {
GB_ASSERT(node != NULL);
GB_ASSERT(e != NULL);
map_entity_set(&c->info.implicits, hash_pointer(node), e);
}
void add_type_info_type(Checker *c, Type *t) {
if (t == NULL) {
@@ -1467,7 +1488,12 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope)
// TODO(bill): What if vd->type != NULL??? How to handle this case?
d->type_expr = init;
d->init_expr = init;
} else if (init != NULL && up_init->kind == AstNode_ProcLit) {
} else if (up_init != NULL && up_init->kind == AstNode_Alias) {
error_node(up_init, "#alias declarations are not yet supported");
continue;
// e = make_entity_alias(c->allocator, d->scope, name->Ident, NULL, NULL);
// d->init_expr = init->Alias.expr;
}else if (init != NULL && up_init->kind == AstNode_ProcLit) {
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
d->proc_lit = up_init;
d->type_expr = vd->type;
+26 -1
View File
@@ -13,13 +13,15 @@ typedef struct Type Type;
ENTITY_KIND(Builtin) \
ENTITY_KIND(ImportName) \
ENTITY_KIND(LibraryName) \
ENTITY_KIND(Alias) \
ENTITY_KIND(Nil) \
ENTITY_KIND(Count)
ENTITY_KIND(Label)
typedef enum EntityKind {
#define ENTITY_KIND(k) GB_JOIN2(Entity_, k),
ENTITY_KINDS
#undef ENTITY_KIND
Entity_Count,
} EntityKind;
String const entity_strings[] = {
@@ -95,7 +97,14 @@ struct Entity {
String name;
bool used;
} LibraryName;
struct {
Entity *original;
} Alias;
i32 Nil;
struct {
String name;
AstNode *node;
} Label;
};
};
@@ -218,12 +227,28 @@ Entity *make_entity_library_name(gbAllocator a, Scope *scope, Token token, Type
return entity;
}
Entity *make_entity_alias(gbAllocator a, Scope *scope, Token token, Type *type,
Entity *original) {
Entity *entity = alloc_entity(a, Entity_Alias, scope, token, type);
entity->Alias.original = original;
return entity;
}
Entity *make_entity_nil(gbAllocator a, String name, Type *type) {
Token token = make_token_ident(name);
Entity *entity = alloc_entity(a, Entity_Nil, NULL, token, type);
return entity;
}
Entity *make_entity_label(gbAllocator a, Scope *scope, Token token, Type *type,
AstNode *node) {
Entity *entity = alloc_entity(a, Entity_Label, scope, token, type);
entity->Label.node = node;
return entity;
}
Entity *make_entity_dummy_variable(gbAllocator a, Scope *scope, Token token) {
token.string = str_lit("_");
return make_entity_variable(a, scope, token, NULL, false);
+52 -46
View File
@@ -35,45 +35,45 @@ HashKey hash_exact_value(ExactValue v) {
}
ExactValue make_exact_value_compound(AstNode *node) {
ExactValue exact_value_compound(AstNode *node) {
ExactValue result = {ExactValue_Compound};
result.value_compound = node;
return result;
}
ExactValue make_exact_value_bool(bool b) {
ExactValue exact_value_bool(bool b) {
ExactValue result = {ExactValue_Bool};
result.value_bool = (b != 0);
return result;
}
ExactValue make_exact_value_string(String string) {
ExactValue exact_value_string(String string) {
// TODO(bill): Allow for numbers with underscores in them
ExactValue result = {ExactValue_String};
result.value_string = string;
return result;
}
ExactValue make_exact_value_integer(i64 i) {
ExactValue exact_value_integer(i64 i) {
ExactValue result = {ExactValue_Integer};
result.value_integer = i;
return result;
}
ExactValue make_exact_value_float(f64 f) {
ExactValue exact_value_float(f64 f) {
ExactValue result = {ExactValue_Float};
result.value_float = f;
return result;
}
ExactValue make_exact_value_pointer(i64 ptr) {
ExactValue exact_value_pointer(i64 ptr) {
ExactValue result = {ExactValue_Pointer};
result.value_pointer = ptr;
return result;
}
ExactValue make_exact_value_integer_from_string(String string) {
ExactValue exact_value_integer_from_string(String string) {
// TODO(bill): Allow for numbers with underscores in them
i32 base = 10;
bool has_prefix = false;
@@ -82,6 +82,7 @@ ExactValue make_exact_value_integer_from_string(String string) {
case 'b': base = 2; has_prefix = true; break;
case 'o': base = 8; has_prefix = true; break;
case 'd': base = 10; has_prefix = true; break;
case 'z': base = 12; has_prefix = true; break;
case 'x': base = 16; has_prefix = true; break;
}
}
@@ -100,25 +101,21 @@ ExactValue make_exact_value_integer_from_string(String string) {
continue;
}
i64 v = 0;
if (gb_char_is_digit(r)) {
v = r - '0';
} else if (gb_char_is_hex_digit(r)) {
v = gb_hex_digit_to_int(r);
} else {
v = digit_value(r);
if (v >= base) {
break;
}
result *= base;
result += v;
}
return make_exact_value_integer(result);
return exact_value_integer(result);
}
ExactValue make_exact_value_float_from_string(String string) {
ExactValue exact_value_float_from_string(String string) {
isize i = 0;
u8 *str = string.text;
isize len = string.len;
@@ -137,10 +134,10 @@ ExactValue make_exact_value_float_from_string(String string) {
if (r == '_') {
continue;
}
if (!gb_char_is_digit(r)) {
i64 v = digit_value(r);
if (v >= 10) {
break;
}
i64 v = r - '0';
value *= 10.0;
value += v;
}
@@ -153,29 +150,38 @@ ExactValue make_exact_value_float_from_string(String string) {
if (r == '_') {
continue;
}
if (!gb_char_is_digit(r)) {
i64 v = digit_value(r);
if (v >= 10) {
break;
}
value += (r-'0')/pow10;
value += v/pow10;
pow10 *= 10.0;
}
}
f64 frac = 0;
bool frac = false;
f64 scale = 1.0;
if ((str[i] == 'e') || (str[i] == 'E')) {
i++;
if (str[i] == '-') {
frac = 1;
frac = true;
i++;
} else if (str[i] == '+') {
i++;
}
u32 exp;
for (exp = 0; gb_char_is_digit(str[i]); i++) {
exp = exp * 10 + (str[i]-'0');
u32 exp = 0;
for (; i < len; i++) {
Rune r = cast(Rune)str[i];
if (r == '_') {
continue;
}
u32 d = cast(u32)digit_value(r);
if (d >= 10) {
break;
}
exp = exp * 10 + d;
}
if (exp > 308) exp = 308;
@@ -185,20 +191,20 @@ ExactValue make_exact_value_float_from_string(String string) {
}
f64 result = sign * (frac ? (value / scale) : (value * scale));
return make_exact_value_float(result);
return exact_value_float(result);
}
ExactValue make_exact_value_from_basic_literal(Token token) {
ExactValue exact_value_from_basic_literal(Token token) {
switch (token.kind) {
case Token_String: return make_exact_value_string(token.string);
case Token_Integer: return make_exact_value_integer_from_string(token.string);
case Token_Float: return make_exact_value_float_from_string(token.string);
case Token_String: return exact_value_string(token.string);
case Token_Integer: return exact_value_integer_from_string(token.string);
case Token_Float: return exact_value_float_from_string(token.string);
case Token_Rune: {
Rune r = GB_RUNE_INVALID;
gb_utf8_decode(token.string.text, token.string.len, &r);
// gb_printf("%.*s rune: %d\n", LIT(token.string), r);
return make_exact_value_integer(r);
return exact_value_integer(r);
}
default:
GB_PANIC("Invalid token for basic literal");
@@ -217,12 +223,12 @@ ExactValue exact_value_to_integer(ExactValue v) {
i64 i = cast(i64)v.value_float;
f64 f = cast(f64)i;
if (f == v.value_float) {
return make_exact_value_integer(i);
return exact_value_integer(i);
}
} break;
case ExactValue_Pointer:
return make_exact_value_integer(cast(i64)cast(intptr)v.value_pointer);
return exact_value_integer(cast(i64)cast(intptr)v.value_pointer);
}
ExactValue r = {ExactValue_Invalid};
return r;
@@ -231,7 +237,7 @@ ExactValue exact_value_to_integer(ExactValue v) {
ExactValue exact_value_to_float(ExactValue v) {
switch (v.kind) {
case ExactValue_Integer:
return make_exact_value_float(cast(i64)v.value_integer);
return exact_value_float(cast(i64)v.value_integer);
case ExactValue_Float:
return v;
}
@@ -287,14 +293,14 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
i &= ~((~0ll)<<precision);
}
return make_exact_value_integer(i);
return exact_value_integer(i);
} break;
case Token_Not: {
switch (v.kind) {
case ExactValue_Invalid: return v;
case ExactValue_Bool:
return make_exact_value_bool(!v.value_bool);
return exact_value_bool(!v.value_bool);
}
} break;
}
@@ -348,7 +354,7 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
return;
case ExactValue_Float:
// TODO(bill): Is this good enough?
*x = make_exact_value_float(cast(f64)x->value_integer);
*x = exact_value_float(cast(f64)x->value_integer);
return;
}
break;
@@ -372,10 +378,10 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
case ExactValue_Bool:
switch (op) {
case Token_CmpAnd: return make_exact_value_bool(x.value_bool && y.value_bool);
case Token_CmpOr: return make_exact_value_bool(x.value_bool || y.value_bool);
case Token_And: return make_exact_value_bool(x.value_bool & y.value_bool);
case Token_Or: return make_exact_value_bool(x.value_bool | y.value_bool);
case Token_CmpAnd: return exact_value_bool(x.value_bool && y.value_bool);
case Token_CmpOr: return exact_value_bool(x.value_bool || y.value_bool);
case Token_And: return exact_value_bool(x.value_bool & y.value_bool);
case Token_Or: return exact_value_bool(x.value_bool | y.value_bool);
default: goto error;
}
break;
@@ -388,7 +394,7 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
case Token_Add: c = a + b; break;
case Token_Sub: c = a - b; break;
case Token_Mul: c = a * b; break;
case Token_Quo: return make_exact_value_float(fmod(cast(f64)a, cast(f64)b));
case Token_Quo: return exact_value_float(fmod(cast(f64)a, cast(f64)b));
case Token_QuoEq: c = a / b; break; // NOTE(bill): Integer division
case Token_Mod: c = a % b; break;
case Token_And: c = a & b; break;
@@ -400,17 +406,17 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
default: goto error;
}
return make_exact_value_integer(c);
return exact_value_integer(c);
} break;
case ExactValue_Float: {
f64 a = x.value_float;
f64 b = y.value_float;
switch (op) {
case Token_Add: return make_exact_value_float(a + b);
case Token_Sub: return make_exact_value_float(a - b);
case Token_Mul: return make_exact_value_float(a * b);
case Token_Quo: return make_exact_value_float(a / b);
case Token_Add: return exact_value_float(a + b);
case Token_Sub: return exact_value_float(a - b);
case Token_Mul: return exact_value_float(a * b);
case Token_Quo: return exact_value_float(a / b);
default: goto error;
}
} break;
+314 -124
View File
File diff suppressed because it is too large Load Diff
+608 -544
View File
File diff suppressed because it is too large Load Diff
+8 -12
View File
@@ -306,7 +306,7 @@ void ir_print_compound_element(irFileBuffer *f, irModule *m, ExactValue v, Type
}
void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *type) {
type = base_type(base_enum_type(type));
type = core_type(type);
if (is_type_float(type)) {
value = exact_value_to_float(value);
} else if (is_type_integer(type)) {
@@ -942,7 +942,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
switch (uo->op) {
case Token_Sub:
if (is_type_float(elem_type)) {
ir_print_exact_value(f, m, make_exact_value_float(0), type);
ir_print_exact_value(f, m, exact_value_float(0), type);
} else {
ir_fprintf(f, "0");
}
@@ -1197,17 +1197,17 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
ir_fprintf(f, "call void ");
ir_print_encoded_global(f, str_lit("__bounds_check_error"), false);
ir_fprintf(f, "(");
ir_print_compound_element(f, m, make_exact_value_string(bc->pos.file), t_string);
ir_print_compound_element(f, m, exact_value_string(bc->pos.file), t_string);
ir_fprintf(f, ", ");
ir_print_type(f, m, t_int);
ir_fprintf(f, " ");
ir_print_exact_value(f, m, make_exact_value_integer(bc->pos.line), t_int);
ir_print_exact_value(f, m, exact_value_integer(bc->pos.line), t_int);
ir_fprintf(f, ", ");
ir_print_type(f, m, t_int);
ir_fprintf(f, " ");
ir_print_exact_value(f, m, make_exact_value_integer(bc->pos.column), t_int);
ir_print_exact_value(f, m, exact_value_integer(bc->pos.column), t_int);
ir_fprintf(f, ", ");
ir_print_type(f, m, t_int);
@@ -1232,17 +1232,17 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
}
ir_fprintf(f, "(");
ir_print_compound_element(f, m, make_exact_value_string(bc->pos.file), t_string);
ir_print_compound_element(f, m, exact_value_string(bc->pos.file), t_string);
ir_fprintf(f, ", ");
ir_print_type(f, m, t_int);
ir_fprintf(f, " ");
ir_print_exact_value(f, m, make_exact_value_integer(bc->pos.line), t_int);
ir_print_exact_value(f, m, exact_value_integer(bc->pos.line), t_int);
ir_fprintf(f, ", ");
ir_print_type(f, m, t_int);
ir_fprintf(f, " ");
ir_print_exact_value(f, m, make_exact_value_integer(bc->pos.column), t_int);
ir_print_exact_value(f, m, exact_value_integer(bc->pos.column), t_int);
ir_fprintf(f, ", ");
ir_print_type(f, m, t_int);
@@ -1408,10 +1408,6 @@ void print_llvm_ir(irGen *ir) {
irFileBuffer buf = {0}, *f = &buf;
ir_file_buffer_init(f, &ir->output_file);
if (m->layout.len > 0) {
ir_fprintf(f, "target datalayout = \"%.*s\"\n", LIT(m->layout));
}
ir_print_encoded_local(f, str_lit("..string"));
ir_fprintf(f, " = type {i8*, ");
ir_print_type(f, m, t_int);
+5 -4
View File
@@ -2,15 +2,15 @@
extern "C" {
#endif
#define USE_CUSTOM_BACKEND false
#include "common.c"
#include "timings.c"
#include "build_settings.c"
#include "tokenizer.c"
#include "parser.c"
// #include "printer.c"
#include "checker.c"
// #include "ssa.c"
#include "ssa.c"
#include "ir.c"
#include "ir_opt.c"
#include "ir_print.c"
@@ -151,6 +151,7 @@ int main(int argc, char **argv) {
init_scratch_memory(gb_megabytes(10));
init_global_error_collector();
#if 1
init_build_context();
@@ -215,7 +216,7 @@ int main(int argc, char **argv) {
#endif
#if 0
#if USE_CUSTOM_BACKEND
if (global_error_collector.count != 0) {
return 1;
}
@@ -224,7 +225,7 @@ int main(int argc, char **argv) {
return 1;
}
if (!ssa_generate(&checker.info)) {
if (!ssa_generate(&parser, &checker.info)) {
return 1;
}
#else
+124 -98
View File
@@ -139,6 +139,10 @@ AstNodeArray make_ast_node_array(AstFile *f) {
AstNodeArray elems; \
Token open, close; \
}) \
AST_NODE_KIND(Alias, "alias", struct { \
Token token; \
AstNode *expr; \
}) \
AST_NODE_KIND(_ExprBegin, "", i32) \
AST_NODE_KIND(BadExpr, "bad expression", struct { Token begin, end; }) \
AST_NODE_KIND(TagExpr, "tag expression", struct { Token token, name; AstNode *expr; }) \
@@ -215,6 +219,7 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
}) \
AST_NODE_KIND(ForStmt, "for statement", struct { \
Token token; \
AstNode *label; \
AstNode *init; \
AstNode *cond; \
AstNode *post; \
@@ -222,6 +227,7 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
}) \
AST_NODE_KIND(RangeStmt, "range statement", struct { \
Token token; \
AstNode *label; \
AstNode *value; \
AstNode *index; \
Token in_token; \
@@ -235,20 +241,22 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
}) \
AST_NODE_KIND(MatchStmt, "match statement", struct { \
Token token; \
AstNode *label; \
AstNode *init; \
AstNode *tag; \
AstNode *body; \
}) \
AST_NODE_KIND(TypeMatchStmt, "type match statement", struct { \
Token token; \
AstNode *label; \
AstNode *tag; \
AstNode *body; \
}) \
AST_NODE_KIND(DeferStmt, "defer statement", struct { Token token; AstNode *stmt; }) \
AST_NODE_KIND(BranchStmt, "branch statement", struct { Token token; }) \
AST_NODE_KIND(BranchStmt, "branch statement", struct { Token token; AstNode *label; }) \
AST_NODE_KIND(UsingStmt, "using statement", struct { \
Token token; \
AstNode *node; \
AstNodeArray list; \
}) \
AST_NODE_KIND(AsmOperand, "assembly operand", struct { \
Token string; \
@@ -301,6 +309,10 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
AstNode *cond; \
bool is_system; \
}) \
AST_NODE_KIND(Label, "label", struct { \
Token token; \
AstNode *name; \
}) \
AST_NODE_KIND(_DeclEnd, "", i32) \
AST_NODE_KIND(Field, "field", struct { \
AstNodeArray names; \
@@ -398,7 +410,6 @@ String const ast_node_strings[] = {
typedef struct AstNode {
AstNodeKind kind;
// AstNode *prev, *next; // NOTE(bill): allow for Linked list
u32 stmt_state_flags;
union {
#define AST_NODE_KIND(_kind_name_, name, ...) GB_JOIN2(AstNode, _kind_name_) _kind_name_;
@@ -410,7 +421,9 @@ typedef struct AstNode {
#define ast_node(n_, Kind_, node_) GB_JOIN2(AstNode, Kind_) *n_ = &(node_)->Kind_; GB_ASSERT((node_)->kind == GB_JOIN2(AstNode_, Kind_))
#define case_ast_node(n_, Kind_, node_) case GB_JOIN2(AstNode_, Kind_): { ast_node(n_, Kind_, node_);
#ifndef case_end
#define case_end } break;
#endif
gb_inline bool is_ast_node_expr(AstNode *node) {
@@ -445,6 +458,8 @@ Token ast_node_token(AstNode *node) {
return ast_node_token(node->CompoundLit.type);
}
return node->CompoundLit.open;
case AstNode_Alias: return node->Alias.token;
case AstNode_TagExpr: return node->TagExpr.token;
case AstNode_RunExpr: return node->RunExpr.token;
case AstNode_BadExpr: return node->BadExpr.begin;
@@ -492,6 +507,7 @@ Token ast_node_token(AstNode *node) {
case AstNode_ValueDecl: return ast_node_token(node->ValueDecl.names.e[0]);
case AstNode_ImportDecl: return node->ImportDecl.token;
case AstNode_ForeignLibrary: return node->ForeignLibrary.token;
case AstNode_Label: return node->Label.token;
case AstNode_Field:
@@ -771,6 +787,13 @@ AstNode *ast_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token o
result->CompoundLit.close = close;
return result;
}
AstNode *ast_alias(AstFile *f, Token token, AstNode *expr) {
AstNode *result = make_ast_node(f, AstNode_Alias);
result->Alias.token = token;
result->Alias.expr = expr;
return result;
}
AstNode *ast_ternary_expr(AstFile *f, AstNode *cond, AstNode *x, AstNode *y) {
AstNode *result = make_ast_node(f, AstNode_TernaryExpr);
@@ -910,19 +933,21 @@ AstNode *ast_defer_stmt(AstFile *f, Token token, AstNode *stmt) {
return result;
}
AstNode *ast_branch_stmt(AstFile *f, Token token) {
AstNode *ast_branch_stmt(AstFile *f, Token token, AstNode *label) {
AstNode *result = make_ast_node(f, AstNode_BranchStmt);
result->BranchStmt.token = token;
result->BranchStmt.label = label;
return result;
}
AstNode *ast_using_stmt(AstFile *f, Token token, AstNode *node) {
AstNode *ast_using_stmt(AstFile *f, Token token, AstNodeArray list) {
AstNode *result = make_ast_node(f, AstNode_UsingStmt);
result->UsingStmt.token = token;
result->UsingStmt.node = node;
result->UsingStmt.list = list;
return result;
}
AstNode *ast_asm_operand(AstFile *f, Token string, AstNode *operand) {
AstNode *result = make_ast_node(f, AstNode_AsmOperand);
result->AsmOperand.string = string;
@@ -1124,6 +1149,13 @@ AstNode *ast_foreign_library(AstFile *f, Token token, Token filepath, Token libr
return result;
}
AstNode *ast_label_decl(AstFile *f, Token token, AstNode *name) {
AstNode *result = make_ast_node(f, AstNode_Label);
result->Label.token = token;
result->Label.name = name;
return result;
}
bool next_token(AstFile *f) {
Token prev = f->curr_token;
@@ -1762,6 +1794,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
} else if (str_eq(name.string, str_lit("line"))) { return ast_basic_directive(f, token, name.string);
} else if (str_eq(name.string, str_lit("procedure"))) { return ast_basic_directive(f, token, name.string);
} else if (str_eq(name.string, str_lit("type"))) { return ast_helper_type(f, token, parse_type(f));
} else if (!lhs && str_eq(name.string, str_lit("alias"))) { return ast_alias(f, token, parse_expr(f, false));
} else {
operand = ast_tag_expr(f, token, name, parse_expr(f, false));
}
@@ -2129,7 +2162,7 @@ AstNode *parse_expr(AstFile *f, bool lhs) {
AstNodeArray parse_expr_list(AstFile *f, bool lhs) {
AstNodeArray list = make_ast_node_array(f);
do {
for (;;) {
AstNode *e = parse_expr(f, lhs);
array_add(&list, e);
if (f->curr_token.kind != Token_Comma ||
@@ -2137,7 +2170,7 @@ AstNodeArray parse_expr_list(AstFile *f, bool lhs) {
break;
}
next_token(f);
} while (true);
}
return list;
}
@@ -2320,7 +2353,7 @@ AstNode *parse_block_stmt(AstFile *f, b32 is_when) {
return parse_body(f);
}
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind separator, TokenKind follow);
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow);
AstNode *parse_results(AstFile *f) {
@@ -2339,7 +2372,7 @@ AstNode *parse_results(AstFile *f) {
AstNode *list = NULL;
expect_token(f, Token_OpenParen);
list = parse_field_list(f, NULL, 0, Token_Comma, Token_CloseParen);
list = parse_field_list(f, NULL, 0, Token_CloseParen);
expect_token_after(f, Token_CloseParen, "parameter list");
return list;
}
@@ -2350,7 +2383,7 @@ AstNode *parse_proc_type(AstFile *f, AstNode **foreign_library_, String *foreign
Token proc_token = expect_token(f, Token_proc);
expect_token(f, Token_OpenParen);
params = parse_field_list(f, NULL, FieldFlag_Signature, Token_Comma, Token_CloseParen);
params = parse_field_list(f, NULL, FieldFlag_Signature, Token_CloseParen);
expect_token_after(f, Token_CloseParen, "parameter list");
results = parse_results(f);
@@ -2369,17 +2402,6 @@ AstNode *parse_proc_type(AstFile *f, AstNode **foreign_library_, String *foreign
return ast_proc_type(f, proc_token, params, results, tags, cc);
}
bool parse_expect_separator(AstFile *f, TokenKind separator, AstNode *param) {
if (separator == Token_Semicolon) {
expect_semicolon(f, param);
} else {
if (!allow_token(f, separator)) {
return true;
}
}
return false;
}
AstNode *parse_var_type(AstFile *f, bool allow_ellipsis) {
if (allow_ellipsis && f->curr_token.kind == Token_Ellipsis) {
Token tok = f->curr_token;
@@ -2490,7 +2512,22 @@ AstNodeArray convert_to_ident_list(AstFile *f, AstNodeAndFlagsArray list, bool i
return idents;
}
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind separator, TokenKind follow) {
bool parse_expect_field_separator(AstFile *f, AstNode *param) {
Token token = f->curr_token;
if (allow_token(f, Token_Comma)) {
return true;
}
if (token.kind == Token_Semicolon) {
next_token(f);
error(f->curr_token, "Expected a comma, got a semicolon");
return true;
}
return false;
}
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow) {
TokenKind separator = Token_Comma;
Token start_token = f->curr_token;
AstNodeArray params = make_ast_node_array(f);
@@ -2528,7 +2565,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
AstNode *param = ast_field(f, names, type, set_flags);
array_add(&params, param);
parse_expect_separator(f, separator, type);
parse_expect_field_separator(f, type);
while (f->curr_token.kind != follow &&
f->curr_token.kind != Token_EOF) {
@@ -2546,7 +2583,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
AstNode *param = ast_field(f, names, type, set_flags);
array_add(&params, param);
if (parse_expect_separator(f, separator, param)) {
if (!parse_expect_field_separator(f, param)) {
break;
}
}
@@ -2575,7 +2612,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
AstNode *parse_record_fields(AstFile *f, isize *field_count_, u32 flags, String context) {
return parse_field_list(f, field_count_, flags, Token_Comma, Token_CloseBrace);
return parse_field_list(f, field_count_, flags, Token_CloseBrace);
}
AstNode *parse_type_or_ident(AstFile *f) {
@@ -3041,46 +3078,6 @@ AstNode *parse_for_stmt(AstFile *f) {
cond = convert_stmt_to_expr(f, cond, str_lit("boolean expression"));
return ast_for_stmt(f, token, init, cond, post, body);
#if 0
Token token = expect_token(f, Token_for);
AstNodeArray names = parse_ident_list(f);
parse_check_name_list_for_reserves(f, names);
Token colon = expect_token_after(f, Token_in, "for name list");
isize prev_level = f->expr_level;
f->expr_level = -1;
AstNode *expr = parse_expr(f, false);
switch (f->curr_token.kind) {
case Token_HalfOpenRange:
case Token_Ellipsis: {
Token op = f->curr_token;
next_token(f);
AstNode *right = parse_expr(f, false);
expr = ast_interval_expr(f, op, expr, right);
} break;
}
f->expr_level = prev_level;
AstNode *value = NULL;
AstNode *index = NULL;
AstNode *body = parse_block_stmt(f, false);
switch (names.count) {
case 1:
value = names.e[0];
break;
case 2:
value = names.e[0];
index = names.e[1];
break;
default:
error(token, "Expected at 1 or 2 identifiers");
return ast_bad_stmt(f, token, f->curr_token);
}
return ast_range_stmt(f, token, value, index, expr, body);
#endif
}
@@ -3102,9 +3099,17 @@ AstNode *parse_case_clause(AstFile *f) {
AstNode *parse_type_case_clause(AstFile *f) {
Token token = f->curr_token;
AstNodeArray clause = make_ast_node_array(f);
AstNodeArray list = make_ast_node_array(f);
if (allow_token(f, Token_case)) {
array_add(&clause, parse_type(f));
for (;;) {
AstNode *t = parse_type(f);
array_add(&list, t);
if (f->curr_token.kind != Token_Comma ||
f->curr_token.kind == Token_EOF) {
break;
}
next_token(f);
}
} else {
expect_token(f, Token_default);
}
@@ -3112,7 +3117,7 @@ AstNode *parse_type_case_clause(AstFile *f) {
// expect_token(f, Token_ArrowRight); // TODO(bill): Is this the best syntax?
AstNodeArray stmts = parse_stmt_list(f);
return ast_case_clause(f, token, clause, stmts);
return ast_case_clause(f, token, list, stmts);
}
@@ -3256,43 +3261,47 @@ AstNode *parse_stmt(AstFile *f) {
case Token_break:
case Token_continue:
case Token_fallthrough:
case Token_fallthrough: {
AstNode *label = NULL;
next_token(f);
s = ast_branch_stmt(f, token);
if (token.kind != Token_fallthrough &&
f->curr_token.kind == Token_Ident) {
label = parse_ident(f);
}
s = ast_branch_stmt(f, token, label);
expect_semicolon(f, s);
return s;
}
case Token_using: {
// TODO(bill): Make using statements better
Token token = expect_token(f, Token_using);
AstNode *node = parse_stmt(f);
AstNodeArray list = parse_lhs_expr_list(f);
if (list.count == 0) {
syntax_error(token, "Illegal use of `using` statement");
expect_semicolon(f, NULL);
return ast_bad_stmt(f, token, f->curr_token);
}
switch (node->kind) {
case AstNode_ValueDecl:
if (!node->ValueDecl.is_var) {
if (f->curr_token.kind != Token_Colon) {
expect_semicolon(f, list.e[list.count-1]);
return ast_using_stmt(f, token, list);
}
AstNode *decl = parse_simple_stmt(f, false);
expect_semicolon(f, decl);
if (decl->kind == AstNode_ValueDecl) {
if (!decl->ValueDecl.is_var) {
syntax_error(token, "`using` may not be applied to constant declarations");
return decl;
}
if (f->curr_proc == NULL) {
syntax_error(token, "`using` is not allowed at the file scope");
} else {
if (f->curr_proc == NULL) {
syntax_error(token, "`using` is not allowed at the file scope");
} else {
node->ValueDecl.flags |= VarDeclFlag_using;
}
decl->ValueDecl.flags |= VarDeclFlag_using;
}
return node;
case AstNode_ExprStmt: {
AstNode *e = unparen_expr(node->ExprStmt.expr);
while (e->kind == AstNode_SelectorExpr) {
e = unparen_expr(e->SelectorExpr.selector);
}
if (e->kind == AstNode_Ident) {
return ast_using_stmt(f, token, node);
} else if (e->kind == AstNode_Implicit) {
syntax_error(token, "Illegal use of `using` statement with implicit value `%.*s`", LIT(e->Implicit.string));
return ast_bad_stmt(f, token, f->curr_token);
}
} break;
return decl;
}
syntax_error(token, "Illegal use of `using` statement");
@@ -3345,7 +3354,25 @@ AstNode *parse_stmt(AstFile *f) {
Token name = expect_token(f, Token_Ident);
String tag = name.string;
if (str_eq(tag, str_lit("import"))) {
if (str_eq(tag, str_lit("label"))) {
AstNode *name = parse_ident(f);
AstNode *label = ast_label_decl(f, token, name);
AstNode *stmt = parse_stmt(f);
#define _SET_LABEL(Kind_, label_) case GB_JOIN2(AstNode_, Kind_): (stmt->Kind_).label = label_; break
switch (stmt->kind) {
_SET_LABEL(ForStmt, label);
_SET_LABEL(RangeStmt, label);
_SET_LABEL(MatchStmt, label);
_SET_LABEL(TypeMatchStmt, label);
default:
syntax_error(token, "#label may only be applied to a loop");
break;
}
#undef _SET_LABEL
return stmt;
} else if (str_eq(tag, str_lit("import"))) {
AstNode *cond = NULL;
Token import_name = {0};
@@ -3505,7 +3532,6 @@ AstNode *parse_stmt(AstFile *f) {
return s;
}
if (str_eq(tag, str_lit("include"))) {
syntax_error(token, "#include is not a valid import declaration kind. Use #load instead");
s = ast_bad_stmt(f, token, f->curr_token);
@@ -3827,7 +3853,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
gb_printf_err("File permissions problem");
break;
case ParseFile_NotFound:
gb_printf_err("File cannot be found");
gb_printf_err("File cannot be found (`%.*s`)", LIT(import_path));
break;
case ParseFile_InvalidToken:
gb_printf_err("Invalid token found in file");
+2269
View File
File diff suppressed because it is too large Load Diff
+277
View File
@@ -0,0 +1,277 @@
#define SSA_OPS \
SSA_OP(Invalid)\
\
SSA_OP(Unknown)\
\
SSA_OP(Comment) /* Does nothing */\
\
SSA_OP(SP) /* Stack Pointer */\
SSA_OP(SB) /* Stack Base */\
SSA_OP(Addr) /* Address of something - special rules for certain types when loading and storing (e.g. Maps) */\
\
SSA_OP(Local)\
SSA_OP(Global)\
SSA_OP(Proc)\
\
SSA_OP(Load)\
SSA_OP(Store)\
SSA_OP(Move)\
SSA_OP(LoadReg)\
SSA_OP(StoreReg)\
SSA_OP(Zero) /* Zero initialize */\
\
SSA_OP(ArrayIndex) /* Index for a fixed array */\
SSA_OP(PtrIndex) /* Index for a struct/tuple/etc */\
SSA_OP(PtrOffset)\
SSA_OP(ValueIndex) /* Extract for a value from a register */\
\
SSA_OP(Phi)\
SSA_OP(Copy)\
\
/* TODO(bill): calling conventions */\
SSA_OP(CallOdin)\
SSA_OP(CallC)\
SSA_OP(CallStd)\
SSA_OP(CallFast)\
\
SSA_OP(BoundsCheck)\
SSA_OP(SliceBoundsCheck)\
\
/* Built in operations/procedures */\
SSA_OP(Bswap16)\
SSA_OP(Bswap32)\
SSA_OP(Bswap64)\
\
SSA_OP(Assume)\
SSA_OP(DebugTrap)\
SSA_OP(Trap)\
SSA_OP(ReadCycleCounter)\
\
\
SSA_OP(ConstBool)\
SSA_OP(ConstString)\
SSA_OP(ConstSlice)\
SSA_OP(ConstNil)\
SSA_OP(Const8)\
SSA_OP(Const16)\
SSA_OP(Const32)\
SSA_OP(Const64)\
SSA_OP(Const32F)\
SSA_OP(Const64F)\
\
/* These should be all the operations I could possibly need for the mean time */\
SSA_OP(Add8)\
SSA_OP(Add16)\
SSA_OP(Add32)\
SSA_OP(Add64)\
SSA_OP(AddPtr)\
SSA_OP(Add32F)\
SSA_OP(Add64F)\
SSA_OP(Sub8)\
SSA_OP(Sub16)\
SSA_OP(Sub32)\
SSA_OP(Sub64)\
SSA_OP(SubPtr)\
SSA_OP(Sub32F)\
SSA_OP(Sub64F)\
SSA_OP(Mul8)\
SSA_OP(Mul16)\
SSA_OP(Mul32)\
SSA_OP(Mul64)\
SSA_OP(Mul32F)\
SSA_OP(Mul64F)\
SSA_OP(Div8)\
SSA_OP(Div8U)\
SSA_OP(Div16)\
SSA_OP(Div16U)\
SSA_OP(Div32)\
SSA_OP(Div32U)\
SSA_OP(Div64)\
SSA_OP(Div64U)\
SSA_OP(Div32F)\
SSA_OP(Div64F)\
SSA_OP(Mod8)\
SSA_OP(Mod8U)\
SSA_OP(Mod16)\
SSA_OP(Mod16U)\
SSA_OP(Mod32)\
SSA_OP(Mod32U)\
SSA_OP(Mod64)\
SSA_OP(Mod64U)\
\
SSA_OP(And8)\
SSA_OP(And16)\
SSA_OP(And32)\
SSA_OP(And64)\
SSA_OP(Or8)\
SSA_OP(Or16)\
SSA_OP(Or32)\
SSA_OP(Or64)\
SSA_OP(Xor8)\
SSA_OP(Xor16)\
SSA_OP(Xor32)\
SSA_OP(Xor64)\
SSA_OP(AndNot8)\
SSA_OP(AndNot16)\
SSA_OP(AndNot32)\
SSA_OP(AndNot64)\
\
SSA_OP(Lsh8x8)\
SSA_OP(Lsh8x16)\
SSA_OP(Lsh8x32)\
SSA_OP(Lsh8x64)\
SSA_OP(Lsh16x8)\
SSA_OP(Lsh16x16)\
SSA_OP(Lsh16x32)\
SSA_OP(Lsh16x64)\
SSA_OP(Lsh32x8)\
SSA_OP(Lsh32x16)\
SSA_OP(Lsh32x32)\
SSA_OP(Lsh32x64)\
SSA_OP(Lsh64x8)\
SSA_OP(Lsh64x16)\
SSA_OP(Lsh64x32)\
SSA_OP(Lsh64x64)\
SSA_OP(Rsh8x8)\
SSA_OP(Rsh8x16)\
SSA_OP(Rsh8x32)\
SSA_OP(Rsh8x64)\
SSA_OP(Rsh16x8)\
SSA_OP(Rsh16x16)\
SSA_OP(Rsh16x32)\
SSA_OP(Rsh16x64)\
SSA_OP(Rsh32x8)\
SSA_OP(Rsh32x16)\
SSA_OP(Rsh32x32)\
SSA_OP(Rsh32x64)\
SSA_OP(Rsh64x8)\
SSA_OP(Rsh64x16)\
SSA_OP(Rsh64x32)\
SSA_OP(Rsh64x64)\
SSA_OP(Rsh8Ux8)\
SSA_OP(Rsh8Ux16)\
SSA_OP(Rsh8Ux32)\
SSA_OP(Rsh8Ux64)\
SSA_OP(Rsh16Ux8)\
SSA_OP(Rsh16Ux16)\
SSA_OP(Rsh16Ux32)\
SSA_OP(Rsh16Ux64)\
SSA_OP(Rsh32Ux8)\
SSA_OP(Rsh32Ux16)\
SSA_OP(Rsh32Ux32)\
SSA_OP(Rsh32Ux64)\
SSA_OP(Rsh64Ux8)\
SSA_OP(Rsh64Ux16)\
SSA_OP(Rsh64Ux32)\
SSA_OP(Rsh64Ux64)\
\
SSA_OP(Eq8)\
SSA_OP(Eq16)\
SSA_OP(Eq32)\
SSA_OP(Eq64)\
SSA_OP(EqPtr)\
SSA_OP(Eq32F)\
SSA_OP(Eq64F)\
SSA_OP(Ne8)\
SSA_OP(Ne16)\
SSA_OP(Ne32)\
SSA_OP(Ne64)\
SSA_OP(NePtr)\
SSA_OP(Ne32F)\
SSA_OP(Ne64F)\
SSA_OP(Lt8)\
SSA_OP(Lt16)\
SSA_OP(Lt32)\
SSA_OP(Lt64)\
SSA_OP(LtPtr)\
SSA_OP(Lt32F)\
SSA_OP(Lt64F)\
SSA_OP(Gt8)\
SSA_OP(Gt16)\
SSA_OP(Gt32)\
SSA_OP(Gt64)\
SSA_OP(GtPtr)\
SSA_OP(Gt32F)\
SSA_OP(Gt64F)\
SSA_OP(Le8)\
SSA_OP(Le16)\
SSA_OP(Le32)\
SSA_OP(Le64)\
SSA_OP(LePtr)\
SSA_OP(Le32F)\
SSA_OP(Le64F)\
SSA_OP(Ge8)\
SSA_OP(Ge16)\
SSA_OP(Ge32)\
SSA_OP(Ge64)\
SSA_OP(GePtr)\
SSA_OP(Ge32F)\
SSA_OP(Ge64F)\
\
SSA_OP(NotB)\
SSA_OP(EqB)\
SSA_OP(NeB)\
\
SSA_OP(Neg8)\
SSA_OP(Neg16)\
SSA_OP(Neg32)\
SSA_OP(Neg64)\
SSA_OP(Neg32F)\
SSA_OP(Neg64F)\
\
SSA_OP(Not8)\
SSA_OP(Not16)\
SSA_OP(Not32)\
SSA_OP(Not64)\
\
SSA_OP(SignExt8to16)\
SSA_OP(SignExt8to32)\
SSA_OP(SignExt8to64)\
SSA_OP(SignExt16to32)\
SSA_OP(SignExt16to64)\
SSA_OP(SignExt32to64)\
SSA_OP(ZeroExt8to16)\
SSA_OP(ZeroExt8to32)\
SSA_OP(ZeroExt8to64)\
SSA_OP(ZeroExt16to32)\
SSA_OP(ZeroExt16to64)\
SSA_OP(ZeroExt32to64)\
SSA_OP(Trunc16to8)\
SSA_OP(Trunc32to8)\
SSA_OP(Trunc32to16)\
SSA_OP(Trunc64to8)\
SSA_OP(Trunc64to16)\
SSA_OP(Trunc64to32)\
\
SSA_OP(Cvt32to32F)\
SSA_OP(Cvt32to64F)\
SSA_OP(Cvt64to32F)\
SSA_OP(Cvt64to64F)\
SSA_OP(Cvt32Fto32)\
SSA_OP(Cvt32Fto64)\
SSA_OP(Cvt64Fto32)\
SSA_OP(Cvt64Fto64)\
SSA_OP(Cvt32Fto64F)\
SSA_OP(Cvt64Fto32F)\
SSA_OP(Cvt32Uto32F)\
SSA_OP(Cvt32Uto64F)\
SSA_OP(Cvt32Fto32U)\
SSA_OP(Cvt64Fto32U)\
SSA_OP(Cvt64Uto32F)\
SSA_OP(Cvt64Uto64F)\
SSA_OP(Cvt32Fto64U)\
SSA_OP(Cvt64Fto64U)\
enum ssaOp {
#define SSA_OP(k) GB_JOIN2(ssaOp_, k),
SSA_OPS
#undef SSA_OP
};
typedef enum ssaOp ssaOp;
String const ssa_op_strings[] = {
#define SSA_OP(k) {cast(u8 *)#k, gb_size_of(#k)-1},
SSA_OPS
#undef SSA_OP
};
+18 -18
View File
@@ -484,15 +484,9 @@ gb_inline i32 digit_value(Rune r) {
return 16; // NOTE(bill): Larger than highest possible
}
gb_inline void scan_mantissa(Tokenizer *t, i32 base, bool allow_underscore) {
if (allow_underscore) {
while (digit_value(t->curr_rune) < base || t->curr_rune == '_') {
advance_to_next_rune(t);
}
} else {
while (digit_value(t->curr_rune) < base) {
advance_to_next_rune(t);
}
gb_inline void scan_mantissa(Tokenizer *t, i32 base) {
while (digit_value(t->curr_rune) < base || t->curr_rune == '_') {
advance_to_next_rune(t);
}
}
@@ -506,7 +500,7 @@ Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
if (seen_decimal_point) {
token.kind = Token_Float;
scan_mantissa(t, 10, true);
scan_mantissa(t, 10);
goto exponent;
}
@@ -515,31 +509,37 @@ Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
advance_to_next_rune(t);
if (t->curr_rune == 'b') { // Binary
advance_to_next_rune(t);
scan_mantissa(t, 2, true);
scan_mantissa(t, 2);
if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
}
} else if (t->curr_rune == 'o') { // Octal
advance_to_next_rune(t);
scan_mantissa(t, 8, true);
scan_mantissa(t, 8);
if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
}
} else if (t->curr_rune == 'd') { // Decimal
advance_to_next_rune(t);
scan_mantissa(t, 10, true);
scan_mantissa(t, 10);
if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
}
} else if (t->curr_rune == 'z') { // Dozenal
advance_to_next_rune(t);
scan_mantissa(t, 12);
if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
}
} else if (t->curr_rune == 'x') { // Hexadecimal
advance_to_next_rune(t);
scan_mantissa(t, 16, true);
scan_mantissa(t, 16);
if (t->curr - prev <= 2) {
token.kind = Token_Invalid;
}
} else {
seen_decimal_point = false;
scan_mantissa(t, 10, true);
scan_mantissa(t, 10);
if (t->curr_rune == '.' || t->curr_rune == 'e' || t->curr_rune == 'E') {
seen_decimal_point = true;
@@ -551,7 +551,7 @@ Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
return token;
}
scan_mantissa(t, 10, true);
scan_mantissa(t, 10);
fraction:
if (t->curr_rune == '.') {
@@ -564,7 +564,7 @@ fraction:
goto end;
}
token.kind = Token_Float;
scan_mantissa(t, 10, true);
scan_mantissa(t, 10);
}
exponent:
@@ -574,7 +574,7 @@ exponent:
if (t->curr_rune == '-' || t->curr_rune == '+') {
advance_to_next_rune(t);
}
scan_mantissa(t, 10, false);
scan_mantissa(t, 10);
}
end:
+31 -13
View File
@@ -375,6 +375,10 @@ Type *base_enum_type(Type *t) {
return t;
}
Type *core_type(Type *t) {
return base_type(base_enum_type(t));
}
void set_base_type(Type *t, Type *base) {
if (t && t->kind == Type_Named) {
t->Named.base = base;
@@ -530,28 +534,28 @@ bool is_type_named(Type *t) {
return t->kind == Type_Named;
}
bool is_type_boolean(Type *t) {
t = base_type(base_enum_type(t));
t = core_type(t);
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Boolean) != 0;
}
return false;
}
bool is_type_integer(Type *t) {
t = base_type(base_enum_type(t));
t = core_type(t);
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Integer) != 0;
}
return false;
}
bool is_type_unsigned(Type *t) {
t = base_type(base_enum_type(t));
t = core_type(t);
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Unsigned) != 0;
}
return false;
}
bool is_type_numeric(Type *t) {
t = base_type(base_enum_type(t));
t = core_type(t);
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Numeric) != 0;
}
@@ -586,7 +590,7 @@ bool is_type_untyped(Type *t) {
return false;
}
bool is_type_ordered(Type *t) {
t = base_type(base_enum_type(t));
t = core_type(t);
switch (t->kind) {
case Type_Basic:
return (t->Basic.flags & BasicFlag_Ordered) != 0;
@@ -598,28 +602,28 @@ bool is_type_ordered(Type *t) {
return false;
}
bool is_type_constant_type(Type *t) {
t = base_type(base_enum_type(t));
t = core_type(t);
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_ConstantType) != 0;
}
return false;
}
bool is_type_float(Type *t) {
t = base_type(base_enum_type(t));
t = core_type(t);
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Float) != 0;
}
return false;
}
bool is_type_f32(Type *t) {
t = base_type(base_enum_type(t));
t = core_type(t);
if (t->kind == Type_Basic) {
return t->Basic.kind == Basic_f32;
}
return false;
}
bool is_type_f64(Type *t) {
t = base_type(base_enum_type(t));
t = core_type(t);
if (t->kind == Type_Basic) {
return t->Basic.kind == Basic_f64;
}
@@ -737,7 +741,7 @@ bool is_type_untyped_nil(Type *t) {
bool is_type_valid_for_keys(Type *t) {
t = base_type(base_enum_type(t));
t = core_type(t);
if (is_type_untyped(t)) {
return false;
}
@@ -798,7 +802,7 @@ bool is_type_comparable(Type *t) {
return true;
case Type_Record: {
if (is_type_enum(t)) {
return is_type_comparable(base_enum_type(t));
return is_type_comparable(core_type(t));
}
return false;
} break;
@@ -1032,7 +1036,21 @@ typedef enum ProcTypeOverloadKind {
} ProcTypeOverloadKind;
bool has_encountered_null_proc_type = false;
ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
if(x == NULL && y == NULL) {
if(!has_encountered_null_proc_type) {
printf("The compiler has encountered a NULL proc type.\n"
" This is probably not an error in your code, and\n"
" the compile is probably still successful.\n"
" This does mean that (at least once), there could be a\n"
" bad procedure overload in your program, and Odin wouldn't catch it.\n"
" As far as I know, this is a porting bug, and doesn't occur on mainline Odin.\n"
" Be careful, and sorry about this bug :(\n");
has_encountered_null_proc_type = true;
}
return ProcOverload_ParamCount;
}
if (!is_type_proc(x)) return ProcOverload_NotProcedure;
if (!is_type_proc(y)) return ProcOverload_NotProcedure;
TypeProc px = base_type(x)->Proc;
@@ -1215,7 +1233,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
// NOTE(bill): Underlying memory address cannot be changed
if (str_eq(field_name, count_str)) {
// HACK(bill): Memory leak
sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, make_exact_value_integer(type->Array.count));
sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, exact_value_integer(type->Array.count));
return sel;
}
} else if (type->kind == Type_Vector) {
@@ -1223,7 +1241,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
// NOTE(bill): Vectors are not addressable
if (str_eq(field_name, count_str)) {
// HACK(bill): Memory leak
sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, make_exact_value_integer(type->Vector.count));
sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, exact_value_integer(type->Vector.count));
return sel;
}
+1
View File
@@ -6,6 +6,7 @@
#pragma warning(pop)
bool rune_is_letter(Rune r) {
if ((r < 0x80 && gb_char_is_alpha(cast(char)r)) ||
r == '_') {
+66 -44
View File
@@ -166,24 +166,24 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_encode_char(utf8proc_int32_t uc, ut
if (uc < 0x00) {
return 0;
} else if (uc < 0x80) {
dst[0] = uc;
dst[0] = (utf8proc_uint8_t) uc;
return 1;
} else if (uc < 0x800) {
dst[0] = 0xC0 + (uc >> 6);
dst[1] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6));
dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 2;
// Note: we allow encoding 0xd800-0xdfff here, so as not to change
// the API, however, these are actually invalid in UTF-8
} else if (uc < 0x10000) {
dst[0] = 0xE0 + (uc >> 12);
dst[1] = 0x80 + ((uc >> 6) & 0x3F);
dst[2] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12));
dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 3;
} else if (uc < 0x110000) {
dst[0] = 0xF0 + (uc >> 18);
dst[1] = 0x80 + ((uc >> 12) & 0x3F);
dst[2] = 0x80 + ((uc >> 6) & 0x3F);
dst[3] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18));
dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F));
dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 4;
} else return 0;
}
@@ -193,28 +193,28 @@ static utf8proc_ssize_t unsafe_encode_char(utf8proc_int32_t uc, utf8proc_uint8_t
if (uc < 0x00) {
return 0;
} else if (uc < 0x80) {
dst[0] = uc;
dst[0] = (utf8proc_uint8_t)uc;
return 1;
} else if (uc < 0x800) {
dst[0] = 0xC0 + (uc >> 6);
dst[1] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6));
dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 2;
} else if (uc == 0xFFFF) {
dst[0] = 0xFF;
dst[0] = (utf8proc_uint8_t)0xFF;
return 1;
} else if (uc == 0xFFFE) {
dst[0] = 0xFE;
dst[0] = (utf8proc_uint8_t)0xFE;
return 1;
} else if (uc < 0x10000) {
dst[0] = 0xE0 + (uc >> 12);
dst[1] = 0x80 + ((uc >> 6) & 0x3F);
dst[2] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12));
dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 3;
} else if (uc < 0x110000) {
dst[0] = 0xF0 + (uc >> 18);
dst[1] = 0x80 + ((uc >> 12) & 0x3F);
dst[2] = 0x80 + ((uc >> 6) & 0x3F);
dst[3] = 0x80 + (uc & 0x3F);
dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18));
dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F));
dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F));
dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F));
return 4;
} else return 0;
}
@@ -383,7 +383,7 @@ UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t c) {
}
UTF8PROC_DLLEXPORT utf8proc_category_t utf8proc_category(utf8proc_int32_t c) {
return (utf8proc_category_t)utf8proc_get_property(c)->category;
return utf8proc_get_property(c)->category;
}
UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) {
@@ -391,11 +391,9 @@ UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) {
return s[utf8proc_category(c)];
}
#define utf8proc_decompose_lump(replacement_uc) \
return utf8proc_decompose_char((utf8proc_int32_t)(replacement_uc), dst, bufsize, \
(utf8proc_option_t)((utf8proc_int32_t)options & ~UTF8PROC_LUMP), last_boundclass)
return utf8proc_decompose_char((replacement_uc), dst, bufsize, \
options & ~UTF8PROC_LUMP, last_boundclass)
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) {
const utf8proc_property_t *property;
@@ -458,12 +456,12 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc,
category == UTF8PROC_CATEGORY_ME) return 0;
}
if (options & UTF8PROC_CASEFOLD) {
if ((utf8proc_int16_t)property->casefold_seqindex != UINT16_MAX) {
if (property->casefold_seqindex != UINT16_MAX) {
return seqindex_write_char_decomposed(property->casefold_seqindex, dst, bufsize, options, last_boundclass);
}
}
if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) {
if ((utf8proc_int16_t)property->decomp_seqindex != UINT16_MAX &&
if (property->decomp_seqindex != UINT16_MAX &&
(!property->decomp_type || (options & UTF8PROC_COMPAT))) {
return seqindex_write_char_decomposed(property->decomp_seqindex, dst, bufsize, options, last_boundclass);
}
@@ -485,6 +483,14 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc,
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen,
utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options
) {
return utf8proc_decompose_custom(str, strlen, buffer, bufsize, options, NULL, NULL);
}
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen,
utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options,
utf8proc_custom_func custom_func, void *custom_data
) {
/* strlen will be ignored, if UTF8PROC_NULLTERM is set in options */
utf8proc_ssize_t wpos = 0;
@@ -511,6 +517,9 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
rpos += utf8proc_iterate(str + rpos, strlen - rpos, &uc);
if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8;
}
if (custom_func != NULL) {
uc = custom_func(uc, custom_data); /* user-specified custom mapping */
}
decomp_result = utf8proc_decompose_char(
uc, buffer + wpos, (bufsize > wpos) ? (bufsize - wpos) : 0, options,
&boundclass
@@ -545,9 +554,8 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
return wpos;
}
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) {
/* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored
ASSERT: 'buffer' has one spare byte of free space at the end! */
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) {
/* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored */
if (options & (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS | UTF8PROC_STRIPCC)) {
utf8proc_ssize_t rpos;
utf8proc_ssize_t wpos = 0;
@@ -621,7 +629,7 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer,
starter_property = unsafe_get_property(*starter);
}
if (starter_property->comb_index < 0x8000 &&
(utf8proc_int16_t)current_property->comb_index != UINT16_MAX &&
current_property->comb_index != UINT16_MAX &&
current_property->comb_index >= 0x8000) {
int sidx = starter_property->comb_index;
int idx = (current_property->comb_index & 0x3FFF) - utf8proc_combinations[sidx];
@@ -655,6 +663,14 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer,
}
length = wpos;
}
return length;
}
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) {
/* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored
ASSERT: 'buffer' has one spare byte of free space at the end! */
length = utf8proc_normalize_utf32(buffer, length, options);
if (length < 0) return length;
{
utf8proc_ssize_t rpos, wpos = 0;
utf8proc_int32_t uc;
@@ -676,15 +692,22 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer,
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options
) {
return utf8proc_map_custom(str, strlen, dstptr, options, NULL, NULL);
}
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options,
utf8proc_custom_func custom_func, void *custom_data
) {
utf8proc_int32_t *buffer;
utf8proc_ssize_t result;
*dstptr = NULL;
result = utf8proc_decompose(str, strlen, NULL, 0, options);
result = utf8proc_decompose_custom(str, strlen, NULL, 0, options, custom_func, custom_data);
if (result < 0) return result;
buffer = (utf8proc_int32_t *) malloc(result * sizeof(utf8proc_int32_t) + 1);
if (!buffer) return UTF8PROC_ERROR_NOMEM;
result = utf8proc_decompose(str, strlen, buffer, result, options);
result = utf8proc_decompose_custom(str, strlen, buffer, result, options, custom_func, custom_data);
if (result < 0) {
free(buffer);
return result;
@@ -705,29 +728,28 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map(
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_DECOMPOSE));
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_DECOMPOSE);
return retval;
}
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_COMPOSE));
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_COMPOSE);
return retval;
}
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT));
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT);
return retval;
}
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_COMPOSE | UTF8PROC_COMPAT));
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_COMPOSE | UTF8PROC_COMPAT);
return retval;
}
+81 -25
View File
@@ -71,14 +71,15 @@
/** The MAJOR version number (increased when backwards API compatibility is broken). */
#define UTF8PROC_VERSION_MAJOR 2
/** The MINOR version number (increased when new functionality is added in a backwards-compatible manner). */
#define UTF8PROC_VERSION_MINOR 0
#define UTF8PROC_VERSION_MINOR 1
/** The PATCH version (increased for fixes that do not change the API). */
#define UTF8PROC_VERSION_PATCH 2
#define UTF8PROC_VERSION_PATCH 0
/** @} */
#include <stdlib.h>
#include <sys/types.h>
#ifdef _MSC_VER
#if defined(_MSC_VER) && _MSC_VER < 1800
// MSVC prior to 2013 lacked stdbool.h and inttypes.h
typedef signed char utf8proc_int8_t;
typedef unsigned char utf8proc_uint8_t;
typedef short utf8proc_int16_t;
@@ -93,12 +94,18 @@ typedef int utf8proc_ssize_t;
typedef unsigned int utf8proc_size_t;
# endif
# ifndef __cplusplus
// emulate C99 bool
typedef unsigned char utf8proc_bool;
// enum {false, true};
# ifndef __bool_true_false_are_defined
# define false 0
# define true 1
# define __bool_true_false_are_defined 1
# endif
# else
typedef bool utf8proc_bool;
# endif
#else
# include <stddef.h>
# include <stdbool.h>
# include <inttypes.h>
typedef int8_t utf8proc_int8_t;
@@ -108,22 +115,12 @@ typedef uint16_t utf8proc_uint16_t;
typedef int32_t utf8proc_int32_t;
typedef uint32_t utf8proc_uint32_t;
typedef size_t utf8proc_size_t;
typedef ssize_t utf8proc_ssize_t;
typedef ptrdiff_t utf8proc_ssize_t;
typedef bool utf8proc_bool;
#endif
#include <limits.h>
#ifdef _WIN32
# ifdef UTF8PROC_EXPORTS
# define UTF8PROC_DLLEXPORT __declspec(dllexport)
# else
# define UTF8PROC_DLLEXPORT /*__declspec(dllimport)*/
# endif
#elif __GNUC__ >= 4
# define UTF8PROC_DLLEXPORT __attribute__ ((visibility("default")))
#else
# define UTF8PROC_DLLEXPORT
#endif
#define UTF8PROC_DLLEXPORT
#ifdef __cplusplus
extern "C" {
@@ -134,7 +131,7 @@ extern "C" {
#endif
#ifndef UINT16_MAX
# define UINT16_MAX ~(utf8proc_uint16_t)0
# define UINT16_MAX 65535U
#endif
/**
@@ -373,6 +370,13 @@ typedef enum {
UTF8PROC_BOUNDCLASS_E_BASE_GAZ = 18, /**< E_BASE + GLUE_AFTER_ZJW */
} utf8proc_boundclass_t;
/**
* Function pointer type passed to @ref utf8proc_map_custom and
* @ref utf8proc_decompose_custom, which is used to specify a user-defined
* mapping of codepoints to be applied in conjunction with other mappings.
*/
typedef utf8proc_int32_t (*utf8proc_custom_func)(utf8proc_int32_t codepoint, void *data);
/**
* Array containing the byte lengths of a UTF-8 encoded codepoint based
* on the first byte.
@@ -480,6 +484,7 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(
* `buffer` (which must contain at least `bufsize` entries). In case of
* success, the number of codepoints written is returned; in case of an
* error, a negative error code is returned (@ref utf8proc_errmsg).
* See @ref utf8proc_decompose_custom to supply additional transformations.
*
* If the number of written codepoints would be bigger than `bufsize`, the
* required buffer size is returned, while the buffer will be overwritten with
@@ -491,8 +496,20 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
);
/**
* Reencodes the sequence of `length` codepoints pointed to by `buffer`
* UTF-8 data in-place (i.e., the result is also stored in `buffer`).
* The same as @ref utf8proc_decompose, but also takes a `custom_func` mapping function
* that is called on each codepoint in `str` before any other transformations
* (along with a `custom_data` pointer that is passed through to `custom_func`).
* The `custom_func` argument is ignored if it is `NULL`. See also @ref utf8proc_map_custom.
*/
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen,
utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options,
utf8proc_custom_func custom_func, void *custom_data
);
/**
* Normalizes the sequence of `length` codepoints pointed to by `buffer`
* in-place (i.e., the result is also stored in `buffer`).
*
* @param buffer the (native-endian UTF-32) unicode codepoints to re-encode.
* @param length the length (in codepoints) of the buffer.
@@ -507,9 +524,37 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose(
* the unicode versioning stability
*
* @return
* In case of success, the length (in bytes) of the resulting UTF-8 string is
* In case of success, the length (in codepoints) of the normalized UTF-32 string is
* returned; otherwise, a negative error code is returned (@ref utf8proc_errmsg).
*
* @warning The entries of the array pointed to by `str` have to be in the
* range `0x0000` to `0x10FFFF`. Otherwise, the program might crash!
*/
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options);
/**
* Reencodes the sequence of `length` codepoints pointed to by `buffer`
* UTF-8 data in-place (i.e., the result is also stored in `buffer`).
* Can optionally normalize the UTF-32 sequence prior to UTF-8 conversion.
*
* @param buffer the (native-endian UTF-32) unicode codepoints to re-encode.
* @param length the length (in codepoints) of the buffer.
* @param options a bitwise or (`|`) of one or more of the following flags:
* - @ref UTF8PROC_NLF2LS - convert LF, CRLF, CR and NEL into LS
* - @ref UTF8PROC_NLF2PS - convert LF, CRLF, CR and NEL into PS
* - @ref UTF8PROC_NLF2LF - convert LF, CRLF, CR and NEL into LF
* - @ref UTF8PROC_STRIPCC - strip or convert all non-affected control characters
* - @ref UTF8PROC_COMPOSE - try to combine decomposed codepoints into composite
* codepoints
* - @ref UTF8PROC_STABLE - prohibit combining characters that would violate
* the unicode versioning stability
* - @ref UTF8PROC_CHARBOUND - insert 0xFF bytes before each grapheme cluster
*
* @return
* In case of success, the length (in bytes) of the resulting nul-terminated
* UTF-8 string is returned; otherwise, a negative error code is returned
* (@ref utf8proc_errmsg).
*
* @warning The amount of free space pointed to by `buffer` must
* exceed the amount of the input data by one byte, and the
* entries of the array pointed to by `str` have to be in the
@@ -595,7 +640,8 @@ UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t codepoi
* in any case the result will be NULL terminated (though it might
* contain NULL characters with the string if `str` contained NULL
* characters). Other flags in the `options` field are passed to the
* functions defined above, and regarded as described.
* functions defined above, and regarded as described. See also
* @ref utfproc_map_custom to supply a custom codepoint transformation.
*
* In case of success the length of the new string is returned,
* otherwise a negative error code is returned.
@@ -607,6 +653,17 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options
);
/**
* Like @ref utf8proc_map, but also takes a `custom_func` mapping function
* that is called on each codepoint in `str` before any other transformations
* (along with a `custom_data` pointer that is passed through to `custom_func`).
* The `custom_func` argument is ignored if it is `NULL`.
*/
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom(
const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options,
utf8proc_custom_func custom_func, void *custom_data
);
/** @name Unicode normalization
*
* Returns a pointer to newly allocated memory of a NFD, NFC, NFKD or NFKC
@@ -619,9 +676,9 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map(
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str);
/** NFC normalization (@ref UTF8PROC_COMPOSE). */
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str);
/** NFD normalization (@ref UTF8PROC_DECOMPOSE and @ref UTF8PROC_COMPAT). */
/** NFKD normalization (@ref UTF8PROC_DECOMPOSE and @ref UTF8PROC_COMPAT). */
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str);
/** NFD normalization (@ref UTF8PROC_COMPOSE and @ref UTF8PROC_COMPAT). */
/** NFKC normalization (@ref UTF8PROC_COMPOSE and @ref UTF8PROC_COMPAT). */
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str);
/** @} */
@@ -630,4 +687,3 @@ UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str);
#endif
#endif
+10 -15
View File
@@ -1,7 +1,4 @@
#pragma warning(push)
#pragma warning(disable: 4838)
const utf8proc_uint16_t utf8proc_sequences[] = {
static const utf8proc_uint16_t utf8proc_sequences[] = {
97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
@@ -1179,7 +1176,7 @@ const utf8proc_uint16_t utf8proc_sequences[] = {
56603, 55354, 56604, 55354, 56605, 55354, 56606, 55354,
56607, 55354, 56608, 55354, 56609, };
const utf8proc_uint16_t utf8proc_stage1table[] = {
static const utf8proc_uint16_t utf8proc_stage1table[] = {
0, 256, 512, 768, 1024, 1280, 1536,
1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
@@ -1726,7 +1723,7 @@ const utf8proc_uint16_t utf8proc_stage1table[] = {
18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432,
38656, };
const utf8proc_uint16_t utf8proc_stage2table[] = {
static const utf8proc_uint16_t utf8proc_stage2table[] = {
1, 2, 2, 2, 2, 2, 2,
2, 2, 3, 4, 3, 5, 6, 2,
2, 2, 2, 2, 2, 2, 2, 2,
@@ -5899,7 +5896,7 @@ const utf8proc_uint16_t utf8proc_stage2table[] = {
540, 540, 540, 1180, 0, 0, 0, 0,
0, 1154, 1154, 1154, 1154, 1154, 1154, 1154,
1154, 1154, 1154, 0, 0, 0, 0, 1103,
1158, 0, 0, 0, 0, 0, 0, 0,
1103, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -6593,7 +6590,7 @@ const utf8proc_uint16_t utf8proc_stage2table[] = {
3984, 3984, 3984, 3984, 3984, 3984, 3984, 0,
0, };
const utf8proc_property_t utf8proc_properties[] = {
static const utf8proc_property_t utf8proc_properties[] = {
{0, 0, 0, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false,false,false,false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL},
{UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL},
@@ -7850,7 +7847,7 @@ const utf8proc_property_t utf8proc_properties[] = {
{UTF8PROC_CATEGORY_MN, 122, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND},
{UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NOBREAK, 1335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NOBREAK, 1335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND},
{UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
@@ -10478,7 +10475,7 @@ const utf8proc_property_t utf8proc_properties[] = {
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1470, UINT16_MAX, 1470, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1478, UINT16_MAX, 1478, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5132, UINT16_MAX, 5132, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1480, UINT16_MAX, 1480, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1480, UINT16_MAX, 1480, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5133, UINT16_MAX, 5133, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5134, UINT16_MAX, 5134, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1482, UINT16_MAX, 1482, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
@@ -12168,7 +12165,7 @@ const utf8proc_property_t utf8proc_properties[] = {
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6787, UINT16_MAX, 6787, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6789, UINT16_MAX, 6789, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6791, UINT16_MAX, 6791, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6793, UINT16_MAX, 6793, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6793, UINT16_MAX, 6793, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6795, UINT16_MAX, 6795, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6797, UINT16_MAX, 6797, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6799, UINT16_MAX, 6799, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
@@ -12204,7 +12201,7 @@ const utf8proc_property_t utf8proc_properties[] = {
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9104, UINT16_MAX, 9104, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9106, UINT16_MAX, 9106, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9108, UINT16_MAX, 9108, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9110, UINT16_MAX, 9110, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9110, UINT16_MAX, 9110, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9112, UINT16_MAX, 9112, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9114, UINT16_MAX, 9114, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
{UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9116, UINT16_MAX, 9116, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER},
@@ -13423,7 +13420,7 @@ const utf8proc_property_t utf8proc_properties[] = {
{UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER},
};
const utf8proc_uint16_t utf8proc_combinations[] = {
static const utf8proc_uint16_t utf8proc_combinations[] = {
0, 46, 192, 193, 194, 195, 196, 197, 0,
256, 258, 260, 550, 461, 0, 0, 512,
514, 0, 0, 0, 0, 0, 0, 0,
@@ -14386,5 +14383,3 @@ const utf8proc_uint16_t utf8proc_combinations[] = {
72, 75,
1, 53694, 1, 53696,
};
#pragma warning(pop)