Adding len() builtin and TYPE_SLICE

This commit is contained in:
Krzosa Karol
2022-06-14 09:33:46 +02:00
parent 1a6d2598a3
commit f189ca381e
6 changed files with 65 additions and 19 deletions

View File

@@ -60,7 +60,7 @@ gen_simple_decl_postfix(Ast_Type *ast, bool scope_names){
case TYPE_POINTER: gen_simple_decl_postfix(ast->base, scope_names); break; case TYPE_POINTER: gen_simple_decl_postfix(ast->base, scope_names); break;
case TYPE_ARRAY: case TYPE_ARRAY:
gen("["); gen("[");
if(ast->arr.size != ARRAY_SIZE_INFERRED) if(ast->arr.size != ARRAY_SIZE_SLICE)
gen("%d", (int)ast->arr.size); gen("%d", (int)ast->arr.size);
gen("]"); gen("]");
gen_simple_decl_postfix(ast->arr.base, scope_names); break; gen_simple_decl_postfix(ast->arr.base, scope_names); break;

View File

@@ -1,8 +1,16 @@
#import "base.kl" #import "base.kl"
test_arrays :: ()
array := [4]int{1,2,3,4}
item := array[0]
length := len(array)
slice: []int = array
slice_length := len(slice)
main :: (argc: int, argv: **char): int main :: (argc: int, argv: **char): int
memory := reserve(size = 10000) memory := reserve(size = 10000)
handle := Windows.GetStdHandle(Windows.STD_OUTPUT_HANDLE) handle := Windows.GetStdHandle(Windows.STD_OUTPUT_HANDLE)
string: *char = "hello world" string: *char = "hello world"
Windows.WriteConsoleA(handle, string->*void, 11, 0, 0) Windows.WriteConsoleA(handle, string->*void, 11, 0, 0)

View File

@@ -5,9 +5,9 @@ test_types(){
parse_init(&ctx, scratch, scratch); parse_init(&ctx, scratch, scratch);
pctx = &ctx; pctx = &ctx;
Ast_Type *array_type1 = type_array(type_s64, 1, 32); Ast_Type *array_type1 = type_array(type_s64, 32);
Ast_Type *array_type2 = type_array(type_s64, 1, 32); Ast_Type *array_type2 = type_array(type_s64, 32);
Ast_Type *array_type3 = type_array(type_s64, 1, 48); Ast_Type *array_type3 = type_array(type_s64, 48);
assert(array_type1 == array_type2); assert(array_type1 == array_type2);
assert(array_type2 != array_type3); assert(array_type2 != array_type3);
Ast_Type *pointer_type1 = type_pointer(type_s64); Ast_Type *pointer_type1 = type_pointer(type_s64);
@@ -19,14 +19,14 @@ test_types(){
assert(pointer_type3 == pointer_type4); assert(pointer_type3 == pointer_type4);
Array<Ast_Type*> types = {scratch}; Array<Ast_Type*> types = {scratch};
types.add(type_array(type_s64, 1, 32)); types.add(type_array(type_s64, 32));
Ast_Type *func_type1 = type_lambda(0, types[0], types); Ast_Type *func_type1 = type_lambda(0, types[0], types);
Ast_Type *func_type2 = type_lambda(0, types[0], types); Ast_Type *func_type2 = type_lambda(0, types[0], types);
assert(func_type1 == func_type2); assert(func_type1 == func_type2);
Array<Ast_Type*> types2 = {scratch}; Array<Ast_Type*> types2 = {scratch};
{ {
types2.add(type_array(type_s64, 1, 32)); types2.add(type_array(type_s64, 32));
types2.add(type_s64); types2.add(type_s64);
} }
types.add(type_s64); types.add(type_s64);

View File

@@ -288,8 +288,8 @@ make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Type *typ
else if(is_untyped(expr->type)){ else if(is_untyped(expr->type)){
expr->value = convert_untyped_to_typed(pos, expr->value, type); expr->value = convert_untyped_to_typed(pos, expr->value, type);
} }
else if(is_array(type) && type->arr.size == ARRAY_SIZE_INFERRED){ else if(is_slice(type) && is_array(expr->type)){
if(type->arr.inferred_size_hash == expr->type->arr.inferred_size_hash) if(type->arr.slice_hash == expr->type->arr.slice_hash)
expr->type = type; expr->type = type;
} }
@@ -322,8 +322,8 @@ _search_for_decl(Ast_Scope *scope, Intern_String name, S32 level){
For(scope->implicit_imports){ For(scope->implicit_imports){
Ast_Decl *result = 0; Ast_Decl *result = 0;
if(scope->kind == AST_MODULE && level > 1); if(scope->kind != AST_MODULE || level < 2)
else result = _search_for_decl(it, name, level+1); result = _search_for_decl(it, name, level+1);
if(result) return result; if(result) return result;
} }
@@ -507,7 +507,6 @@ try_resolving_lambda_scope(Operand *op, Ast_Lambda *lambda, Ast_Type *lambda_typ
*op = operand_lambda(lambda_type); *op = operand_lambda(lambda_type);
} }
else if(is_flag_set(lambda->flags, AST_FOREIGN)){ else if(is_flag_set(lambda->flags, AST_FOREIGN)){
// @todo: Add foreign
*op = operand_lambda(lambda_type); *op = operand_lambda(lambda_type);
} }
} }
@@ -692,7 +691,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
} }
CASE(VALUE, Atom){ CASE(VALUE, Atom){
// @todo: More propagation of typed values to untyped values // @todo: More propagation of const char to sub values
if(compound_context && is_string(node->value.type) && is_string(compound_context)){ if(compound_context && is_string(node->value.type) && is_string(compound_context)){
node->value.type = compound_context; node->value.type = compound_context;
} }
@@ -705,8 +704,13 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
Operand type = resolve_expr(node->base, AST_CANT_BE_NULL); Operand type = resolve_expr(node->base, AST_CANT_BE_NULL);
Operand expr = require_const_int(node->expr, AST_CAN_BE_NULL); Operand expr = require_const_int(node->expr, AST_CAN_BE_NULL);
if(type.type != type_type) compiler_error(node->pos, "Prefix array operator is only allowed on types"); if(type.type != type_type) compiler_error(node->pos, "Prefix array operator is only allowed on types");
if(node->expr){
node->type = type_array(type.type_val, bigint_as_unsigned(&expr.big_int_val));
} else{
node->type = type_slice(type.type_val);
}
node->type = type_array(type.type_val, node->expr ? 1 : 0, bigint_as_unsigned(&expr.big_int_val));
return operand_type(node->type); return operand_type(node->type);
BREAK(); BREAK();
} }
@@ -835,6 +839,23 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
} }
CASE(CALL, Call){ CASE(CALL, Call){
// Handle builtin calls
if(node->name->kind == AST_IDENT){
auto ident = (Ast_Atom *)node->name;
if(ident->intern_val == pctx->intern("len"_s)){
if(node->exprs.len > 1) compiler_error(node->pos, "Expected 1 argument");
Ast_Call_Item *arg = node->exprs[0];
if(arg->name || arg->index) compiler_error(node->pos, "No named or indexed arguments expected");
Operand op = resolve_expr(arg->item, AST_CANT_BE_NULL);
if(is_array(op.type)){
Value val = value_int(op.type->arr.size);
rewrite_into_const(node, Ast_Call, val);
return operand_const_rvalue(val);
} else compiler_error(node->pos, "Invalid argument");
}
}
// Handle calls
Operand name = resolve_expr(node->name, AST_CANT_BE_NULL); Operand name = resolve_expr(node->name, AST_CANT_BE_NULL);
if(name.type->kind != TYPE_LAMBDA) if(name.type->kind != TYPE_LAMBDA)
compiler_error(node->pos, "Calling %s which is not a [Lambda]", docname(name.type)); compiler_error(node->pos, "Calling %s which is not a [Lambda]", docname(name.type));

View File

@@ -134,11 +134,25 @@ type_pointer(Ast_Type *base){
} }
function Ast_Type * function Ast_Type *
type_array(Ast_Type *base, B32 size_present, S64 size){ type_slice(Ast_Type *base){
if(!size_present){ U64 hash_base = hash_ptr(base);
size = ARRAY_SIZE_INFERRED; U64 hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE));
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
if(result){
assert(result->kind == TYPE_ARRAY);
assert(result->arr.base == base);
return result;
} }
struct Slice{void *p; S64 len;};
result = type_new(pctx->perm, TYPE_SLICE, sizeof(Slice), alignof(Slice));
result->arr.base = base;
result->arr.slice_hash = hash;
return result;
}
function Ast_Type *
type_array(Ast_Type *base, S64 size){
U64 hash_base = hash_ptr(base); U64 hash_base = hash_ptr(base);
U64 hash = hash_mix(hash_base, hash_u64(size)); U64 hash = hash_mix(hash_base, hash_u64(size));
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
@@ -152,7 +166,7 @@ type_array(Ast_Type *base, B32 size_present, S64 size){
result = type_new(pctx->perm, TYPE_ARRAY, pointer_size, pointer_align); result = type_new(pctx->perm, TYPE_ARRAY, pointer_size, pointer_align);
result->arr.base = base; result->arr.base = base;
result->arr.size = size; result->arr.size = size;
result->arr.inferred_size_hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_INFERRED)); result->arr.slice_hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE));
map_insert(&pctx->type_map, hash, result); map_insert(&pctx->type_map, hash, result);
return result; return result;
} }

View File

@@ -31,6 +31,7 @@ enum Ast_Type_Kind{
TYPE_UNION, TYPE_UNION,
TYPE_ENUM, TYPE_ENUM,
TYPE_TYPE, TYPE_TYPE,
TYPE_SLICE,
TYPE_UNTYPED_FIRST = TYPE_UNTYPED_BOOL, TYPE_UNTYPED_FIRST = TYPE_UNTYPED_BOOL,
TYPE_UNTYPED_LAST = TYPE_UNTYPED_STRING, TYPE_UNTYPED_LAST = TYPE_UNTYPED_STRING,
@@ -59,7 +60,7 @@ struct Ast_Resolved_Member{
B32 visited; B32 visited;
}; };
#define ARRAY_SIZE_INFERRED (-1) #define ARRAY_SIZE_SLICE (-1)
struct Ast_Type{ struct Ast_Type{
Ast_Type_Kind kind; Ast_Type_Kind kind;
SizeU size; SizeU size;
@@ -76,7 +77,7 @@ struct Ast_Type{
// you still want to pass that array into // you still want to pass that array into
// a function that expects an array of size "[]" // a function that expects an array of size "[]"
// so we want also should check this // so we want also should check this
U64 inferred_size_hash; U64 slice_hash;
}arr; }arr;
struct{ struct{
Array<Ast_Resolved_Member> members; Array<Ast_Resolved_Member> members;
@@ -120,6 +121,7 @@ docname(Ast_Type *type){
case TYPE_UNION: return "[Union]"; case TYPE_UNION: return "[Union]";
case TYPE_ENUM: return "[Enum]"; case TYPE_ENUM: return "[Enum]";
case TYPE_TYPE: return "[Type]"; case TYPE_TYPE: return "[Type]";
case TYPE_SLICE: return "[Slice]";
invalid_default_case; invalid_default_case;
} }
return "<Unknown_Type>"; return "<Unknown_Type>";
@@ -211,6 +213,7 @@ global Ast_Type *untyped_float = &type__untyped_float;
force_inline B32 is_struct(Ast_Type *a){return a->kind == TYPE_STRUCT;} force_inline B32 is_struct(Ast_Type *a){return a->kind == TYPE_STRUCT;}
force_inline B32 is_lambda(Ast_Type *a){return a->kind == TYPE_LAMBDA;} force_inline B32 is_lambda(Ast_Type *a){return a->kind == TYPE_LAMBDA;}
force_inline B32 is_array(Ast_Type *a){return a->kind == TYPE_ARRAY;} force_inline B32 is_array(Ast_Type *a){return a->kind == TYPE_ARRAY;}
force_inline B32 is_slice(Ast_Type *a){return a->kind == TYPE_SLICE;}
force_inline B32 is_enum(Ast_Type *a){return a->kind == TYPE_ENUM;} force_inline B32 is_enum(Ast_Type *a){return a->kind == TYPE_ENUM;}
force_inline B32 is_pointer(Ast_Type *a){return a->kind == TYPE_POINTER;} force_inline B32 is_pointer(Ast_Type *a){return a->kind == TYPE_POINTER;}
force_inline B32 is_string(Ast_Type *a){return a->kind == TYPE_STRING || a->kind == TYPE_UNTYPED_STRING || a == type_pointer_to_char;} force_inline B32 is_string(Ast_Type *a){return a->kind == TYPE_STRING || a->kind == TYPE_UNTYPED_STRING || a == type_pointer_to_char;}