diff --git a/ccodegen.cpp b/ccodegen.cpp index b6eb10c..93814d6 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -20,7 +20,7 @@ gen_indent(){ function void gen_simple_decl_prefix(Ast_Resolved_Type *ast){ switch(ast->kind){ - case TYPE_POINTER:{gen_simple_decl_prefix(ast->base); gen("*");} break; + case TYPE_POINTER: gen_simple_decl_prefix(ast->base); gen("*"); break; case TYPE_ARRAY: gen_simple_decl_prefix(ast->base); break; case TYPE_LAMBDA:break; case TYPE_ENUM: @@ -37,7 +37,12 @@ function void gen_simple_decl_postfix(Ast_Resolved_Type *ast){ switch(ast->kind){ case TYPE_POINTER: gen_simple_decl_postfix(ast->base); break; - case TYPE_ARRAY: gen("[%d]", (int)ast->arr.size); gen_simple_decl_postfix(ast->arr.base); break; + case TYPE_ARRAY: + gen("["); + if(ast->arr.size != ARRAY_SIZE_INFERRED) + gen("%d", (int)ast->arr.size); + gen("]"); + gen_simple_decl_postfix(ast->arr.base); break; case TYPE_LAMBDA:break; case TYPE_ENUM: case TYPE_STRUCT:break; default: name(ast); @@ -59,14 +64,13 @@ gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){ gen_simple_decl_prefix(ast); if(name.len) { gen("%s", name.str); - gen_simple_decl_postfix(ast); } + gen_simple_decl_postfix(ast); } } function void gen_value(Value a){ - // gen("%s", docname(a.type)); switch(a.type->kind){ CASE_INT: { Scratch scratch; @@ -94,13 +98,30 @@ gen_expr(Ast_Expr *ast){ } CASE(INDEX, Index){ - gen("("); - gen_expr(node->expr); + Sym *sym = resolved_get(node); + if(is_array(sym->type)){ + gen("("); + gen("("); - gen("["); - gen_expr(node->index); - gen("]"); - gen(")"); + gen("("); + gen_simple_decl(sym->type->arr.base, {}); + gen("*)"); + gen_expr(node->expr); + gen(".data)"); + + + gen("["); + gen_expr(node->index); + gen("]"); + gen(")"); + } else{ + gen("("); + gen_expr(node->expr); + gen("["); + gen_expr(node->index); + gen("]"); + gen(")"); + } BREAK(); } @@ -123,11 +144,11 @@ gen_expr(Ast_Expr *ast){ } } else{ - gen("("); + if(!token_is_assign(node->op)) gen("("); gen_expr(node->left); gen("%s", name(node->op)); gen_expr(node->right); - gen(")"); + if(!token_is_assign(node->op)) gen(")"); } BREAK(); } @@ -153,7 +174,10 @@ gen_expr(Ast_Expr *ast){ CASE(CALL, Call){ // @todo: Reach into map instead of direct lookup - if(is_struct(node->type) || is_array(node->type)){ // @todo: Should this be type_type maybe??? + if(is_struct(node->type) || is_array(node->type)){ + if(is_array(node->type)){ + gen("(Slice){%d, ", node->exprs.len); + } gen("("); gen_simple_decl(node->type, {}); gen(")"); @@ -177,6 +201,9 @@ gen_expr(Ast_Expr *ast){ if(!node->exprs.is_last(&it)) gen(", "); } gen("}"); + if(is_array(node->type)){ + gen("}"); + } } else{ gen_expr(node->name); @@ -240,10 +267,21 @@ gen_ast(Ast *ast){ CASE(VAR, Var){ Sym *sym = resolved_get(node); - gen_simple_decl(sym->type, node->name); + + if(is_array(sym->type)){ + gen("Slice %s", node->name.str); + } else{ + gen_simple_decl(sym->type, node->name); + } + if(node->expr){ gen(" = "); gen_expr(node->expr); + } else if(is_array(sym->type)){ + gen(" = (Slice){%d, (", sym->type->arr.size); + gen_simple_decl(sym->type, {}); + gen("){}"); + gen("}"); } gen(";"); BREAK(); @@ -498,3 +536,15 @@ compile_file(String filename){ String result = compile_string(filecontent, filename); return result; } + +typedef struct Custom_Data{ + S32 thing; +}Custom_Data; + + +typedef struct Slice{ + S64 len; + void *data; +}Slice; + +Slice thing = (Slice){2, (Custom_Data []){(Custom_Data ){1}, (Custom_Data ){2}}}; \ No newline at end of file diff --git a/new_ast.cpp b/new_ast.cpp index 01fb9c1..92212dd 100644 --- a/new_ast.cpp +++ b/new_ast.cpp @@ -409,7 +409,7 @@ function Ast_Array * ast_array(Token *pos, Ast_Expr *expr){ AST_NEW(Array, ARRAY, pos, AST_EXPR); result->expr = expr; - result->expr->parent = result; + if(result->expr) result->expr->parent = result; return result; } diff --git a/new_types.kl b/new_types.kl index d849b6b..941a7cd 100644 --- a/new_types.kl +++ b/new_types.kl @@ -84,4 +84,6 @@ Custom_Data :: struct thing: S32 array_test :: () - pass \ No newline at end of file + thing := []Custom_Data(Custom_Data(1), Custom_Data(2)) + reference := thing + length := reference.len \ No newline at end of file diff --git a/program.c b/program.c index 86ac567..22620ab 100644 --- a/program.c +++ b/program.c @@ -58,23 +58,23 @@ Bool is_numeric(U8 c){ } void entry(){ String string_to_lex = LIT("Identifier 2425525 Not_Number"); - Token token_array[32]; + Slice token_array = (Slice){32, (Token [32]){}}; S64 token_count = 0; Token t; - for(S64 i = 0;(ilen), tk->str); } } \ No newline at end of file diff --git a/typecheck.cpp b/typecheck.cpp index dd3fff3..593b103 100644 --- a/typecheck.cpp +++ b/typecheck.cpp @@ -509,7 +509,7 @@ resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){ } function Operand -field_access_string(Ast_Expr *right){ +field_access_builtin_string(Ast_Expr *right){ if(right->kind == AST_BINARY) invalid_codepath; // @todo entire field access needs a rework assert(right->kind == AST_IDENT); @@ -523,6 +523,19 @@ field_access_string(Ast_Expr *right){ else invalid_return; } +function Operand +field_access_builtin_array(Ast_Expr *right){ + if(right->kind == AST_BINARY) invalid_codepath; // @todo entire field access needs a rework + assert(right->kind == AST_IDENT); + + auto a = (Ast_Atom *)right; + if(a->intern_val == pctx->intern("len"_s)){ + return operand_lvalue(type_s64); + } + else invalid_return; +} + + function Operand resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_resolve){ if(!ast) return {}; // @todo: add option for better error prevention @@ -554,19 +567,14 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res // @todo: Arrays of inferred size [] Operand type = resolve_expr(node->base); if(type.type != type_type) parsing_error(node->pos, "Prefix array operator is only allowed on types"); - Operand expr = require_const_int(node->expr, AST_CANT_BE_NULL); + Operand expr = require_const_int(node->expr, AST_CAN_BE_NULL); - Ast_Resolved_Type *resolved = type_array(type.type_val, bigint_as_unsigned(&expr.big_int_val)); + Ast_Resolved_Type *resolved = type_array(type.type_val, node->expr ? 1 : 0, bigint_as_unsigned(&expr.big_int_val)); sym_type(resolved, node); return operand_type(resolved); BREAK(); } - CASE(LAMBDA, Lambda){ - return resolve_lambda(node); - BREAK(); - } - CASE(INDEX, Index){ Operand left = resolve_expr(node->expr); Operand index = resolve_expr(node->index); @@ -576,10 +584,17 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res if(!is_array(left.type) && !is_pointer(left.type)){ parsing_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %s instead", docname(left.type)); } + + sym_new_resolved(SYM_VAR, {}, left.value, node); return operand_lvalue(left.type->arr.base); BREAK(); } + CASE(LAMBDA, Lambda){ + return resolve_lambda(node); + BREAK(); + } + CASE(CALL, Call){ Operand name = resolve_expr(node->name); Ast_Resolved_Type *type = name.type; @@ -594,7 +609,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res node->type = type; if(type->kind == TYPE_ARRAY){ - if(node->exprs.len > type->arr.size) parsing_error(node->pos, "compound statement has too many items for this type"); + if(node->exprs.len > type->arr.size && type->arr.size != ARRAY_SIZE_INFERRED) + parsing_error(node->pos, "compound statement has too many items for this type"); Ast_Resolved_Type *item_type = type->arr.base; For(node->exprs){ @@ -850,7 +866,10 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res sym_var({}, resolved_ident.type, node->left); if(is_string(type) && !required_to_be_const){ - result = field_access_string(node->right); + result = field_access_builtin_string(node->right); + } + else if(is_array(type) && !required_to_be_const){ + result = field_access_builtin_array(node->right); } else{ type_complete(type); @@ -1094,9 +1113,9 @@ test_types(){ parse_init(&ctx, scratch, scratch); pctx = &ctx; - Ast_Resolved_Type *array_type1 = type_array(type_s64, 32); - Ast_Resolved_Type *array_type2 = type_array(type_s64, 32); - Ast_Resolved_Type *array_type3 = type_array(type_s64, 48); + Ast_Resolved_Type *array_type1 = type_array(type_s64, 1, 32); + Ast_Resolved_Type *array_type2 = type_array(type_s64, 1, 32); + Ast_Resolved_Type *array_type3 = type_array(type_s64, 1, 48); assert(array_type1 == array_type2); assert(array_type2 != array_type3); Ast_Resolved_Type *pointer_type1 = type_pointer(type_s64); @@ -1108,14 +1127,14 @@ test_types(){ assert(pointer_type3 == pointer_type4); Array types = {scratch}; - types.add(type_array(type_s64, 32)); + types.add(type_array(type_s64, 1, 32)); Ast_Resolved_Type *func_type1 = type_lambda(0, types[0], types); Ast_Resolved_Type *func_type2 = type_lambda(0, types[0], types); assert(func_type1 == func_type2); Array types2 = {scratch}; { - types2.add(type_array(type_s64, 32)); + types2.add(type_array(type_s64, 1, 32)); types2.add(type_s64); } types.add(type_s64); diff --git a/typecheck.h b/typecheck.h index 12fbbf0..8d1bc3a 100644 --- a/typecheck.h +++ b/typecheck.h @@ -287,7 +287,11 @@ type_pointer(Ast_Resolved_Type *base){ } function Ast_Resolved_Type * -type_array(Ast_Resolved_Type *base, SizeU size){ +type_array(Ast_Resolved_Type *base, B32 size_present, S64 size){ + if(!size_present){ + size = ARRAY_SIZE_INFERRED; + } + U64 hash = hash_mix(hash_ptr(base), hash_u64(size)); Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, hash); if(result){ diff --git a/types.h b/types.h index cf70b57..567d88a 100644 --- a/types.h +++ b/types.h @@ -88,6 +88,7 @@ struct Ast_Resolved_Member{ U64 offset; }; +#define ARRAY_SIZE_INFERRED (-1) struct Ast_Resolved_Type{ Ast_Resolved_Type_Kind kind; SizeU size; @@ -98,7 +99,7 @@ struct Ast_Resolved_Type{ Ast_Resolved_Type *base; struct{ Ast_Resolved_Type *base; - SizeU size; + S64 size; }arr; struct{ Array members;