diff --git a/big_int_c3.cpp b/big_int_c3.cpp index 43a691e..0482b89 100644 --- a/big_int_c3.cpp +++ b/big_int_c3.cpp @@ -3,9 +3,17 @@ // a copy of which can be found in the LICENSE file. struct Token; +Allocator *bigint_allocator; global S64 bigint_allocation_count; function void parsing_error(Token *token, const char *str, ...); -#define malloc_arena(x) (bigint_allocation_count++, exp_alloc(&pernament_arena, x)) + +#define Set_BigInt_Allocator(x) BigInt_Allocator bigint_allocator(x) +struct BigInt_Allocator{ + BigInt_Allocator(Allocator *allocator){bigint_allocator = allocator;} + ~BigInt_Allocator(){bigint_allocator = 0;} +}; + +#define malloc_arena(x) (bigint_allocation_count++, exp_alloc(bigint_allocator, x, AF_ZeroMemory)) #define ALLOC_DIGITS(_digits) (uint64_t *)((_digits) ? malloc_arena(sizeof(uint64_t) * (_digits)) : NULL) #define FATAL_ERROR(x) parsing_error(0, x) @@ -95,6 +103,33 @@ bigint_mul(const BigInt *a, const BigInt *b){ return result; } +function BigInt +bigint_add(const BigInt *a, const BigInt *b){ + BigInt result; + bigint_add(&result, a, b); + return result; +} + +function BigInt +bigint_copy(Allocator *allocator, BigInt *src){ + BigInt dest = {}; + if (src->digit_count == 0){ + bigint_init_unsigned(&dest, 0); + return dest; + } + if(src->digit_count == 1){ + dest.digit_count = 1; + dest.digit = src->digit; + dest.is_negative = src->is_negative; + return dest; + } + dest.is_negative = src->is_negative; + dest.digit_count = src->digit_count; + dest.digits = exp_alloc_array(allocator, uint64_t, dest.digit_count, AF_ZeroMemory); + memcpy(dest.digits, src->digits, sizeof(uint64_t) * dest.digit_count); + return dest; +} + //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- @@ -671,6 +706,8 @@ bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) { + assert(dest != op1); + assert(dest != op2); if (op1->digit_count == 0) { return bigint_init_bigint(dest, op2); @@ -893,6 +930,8 @@ static void mul_scalar(BigInt *dest, const BigInt *op, uint64_t scalar) void bigint_mul(BigInt *dest, const BigInt *op1, const BigInt *op2) { + assert(dest != op1); + assert(dest != op2); if (op1->digit_count == 0 || op2->digit_count == 0) { return bigint_init_unsigned(dest, 0); @@ -1958,6 +1997,7 @@ void bigint_print(BigInt *bigint, uint64_t base) const char *bigint_to_error_string(Allocator *allocator, const BigInt *bigint, uint64_t base) { + Set_BigInt_Allocator(allocator); if (bigint->digit_count == 0) { return "0"; @@ -2021,6 +2061,7 @@ const char *bigint_to_error_string(Allocator *allocator, const BigInt *bigint, u *(current++) = *ptr; } *(current++) = '\0'; + return out; } diff --git a/main.cpp b/main.cpp index 2955b17..8a1cf2f 100644 --- a/main.cpp +++ b/main.cpp @@ -108,7 +108,6 @@ For now I don't thing it should be overloadable. int main(){ // test_big_int(); - test_os_memory(); thread_ctx_init(); test_unicode(); diff --git a/new_ast.cpp b/new_ast.cpp index 1c88d8d..c3fe3b2 100644 --- a/new_ast.cpp +++ b/new_ast.cpp @@ -319,7 +319,7 @@ function Ast_Atom * ast_int(Token *pos, BigInt val){ AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM); result->type = untyped_int; - bigint_init_bigint(&result->big_int_val, &val); + result->big_int_val = bigint_copy(pctx->perm, &val); return result; } diff --git a/new_lex.cpp b/new_lex.cpp index 95e841f..2cd06c7 100644 --- a/new_lex.cpp +++ b/new_lex.cpp @@ -86,7 +86,7 @@ enum Token_Kind{ TK_Pointer = TK_Mul, TK_Dereference = TK_BitAnd, - + OPEN_SCOPE = 128, CLOSE_SCOPE, SAME_SCOPE, @@ -125,6 +125,7 @@ struct Lex_Stream{ }; struct Lexer{ + Allocator *arena; Lex_Stream stream; Array tokens; Intern_Table interns; @@ -205,17 +206,23 @@ token_error(Token *t, String error_val){ } function void -lex_parse_u64(Token *t){ +lex_parse_u64(Lexer *lexer, Token *t){ + Scratch scratch; + Set_BigInt_Allocator(scratch); + t->kind = TK_Integer; BigInt m = bigint_u64(1); // @leak, it accumulates and potentially needs allocation BigInt val10 = bigint_u64(10); + BigInt result = bigint_u64(0); for(S64 i = t->len - 1; i >= 0; --i){ BigInt val = bigint_u64(t->str[i] - '0'); // I dont think this is a leak, too small BigInt new_val = bigint_mul(&val, &m); // @leak - bigint_add(&t->int_val, &t->int_val, &new_val); - bigint_mul(&m, &m, &val10); + result = bigint_add(&result, &new_val); // @leak + m = bigint_mul(&m, &val10); // @leak } + + t->int_val = bigint_copy(lexer->arena, &result); } function void @@ -332,7 +339,10 @@ lex_unwind_indent_stack(Token *t, Lex_Stream *s, Array *array){ } function void -lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ +lex__stream(Lexer *lexer, Lex_Stream *s){ + Intern_Table *table = &lexer->interns; + Array *array = &lexer->tokens; + B32 beginning = true; for(;;){ if(lexc(s) == 0 || s->iter >= s->stream.len){ @@ -594,7 +604,7 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ } lex_set_len(s, &t); if(found_dot) lex_parse_f64(&t); - else lex_parse_u64(&t); + else lex_parse_u64(lexer, &t); } break; @@ -633,6 +643,7 @@ lex__stream(Intern_Table *table, Array *array, Lex_Stream *s){ function void lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){ + l->arena = token_string_arena; l->tokens = array_make(token_string_arena, 1024*2); l->interns= intern_table_make(token_string_arena, map_allocator, 1024); } @@ -657,7 +668,7 @@ lex_restream(Lexer *lexer, String istream, String file){ Scratch scratch; lexer->stream.indent_stack.allocator = scratch; lexer->stream.indent_stack.add(&token_null); - lex__stream(&lexer->interns, &lexer->tokens, &lexer->stream); + lex__stream(lexer, &lexer->stream); } function Lexer diff --git a/new_types.kl b/new_types.kl index 4a9c3ca..c817fa3 100644 --- a/new_types.kl +++ b/new_types.kl @@ -21,7 +21,7 @@ unary_test :: () // var := -true // var := +true -binary_test :: () +binary_test :: (thing: S32 = 1051514424242424242442424242424252525252) int_val :: 1000 add :: int_val + 10 + 2.242 + 124 mul :: 4 * 2 @@ -30,10 +30,13 @@ binary_test :: () bit_xor :: 8 ^ 7 character :: 'รณ + + boolean_equals :: true == false boolean_var: Bool = boolean_equals - cast_value :: cast(4242: S32) + cast_value :: 4242 + cast(32: S32) + cast(42: S32) + value: S32 = cast_value bvar2 := int_val > 1 if int_val < 1 diff --git a/typecheck.cpp b/typecheck.cpp index b30a4fe..5be8499 100644 --- a/typecheck.cpp +++ b/typecheck.cpp @@ -72,7 +72,7 @@ value_float(BigInt a){ } function void -check_value_boundaries(Token *pos, Value *a){ +check_value_bounds(Token *pos, Value *a){ if(!is_int(a->type)) return; Scratch scratch; @@ -101,25 +101,77 @@ convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){ else parsing_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type)); a.type = new_type; - check_value_boundaries(pos, &a); + check_value_bounds(pos, &a); return a; } +/* +Type resolution cases + +val := expr + convert untyped to typed default + check bounds + make new symbol + +CONST :: expr + make new symbol + +call(default:type = expr) +val: type = expr + convert untyped to typed based on type + make sure expr.type == type + check bounds + +expr == expr +expr * expr + make sure compatible types, floats with ints are ok(convert to float) + if only one of them is typed convert the untyped to typed + if both types typed make sure they are the same + check bounds + +!expr + make sure correct type + return bool + +call(expr, expr) + convert untyped to matching typed + check if types match + +cast(expr: type) + convert from untyped to typed + convert between typed to other typed + check if types compatible + +*/ + function void -match_values(Value *a, Value *b){ - // @todo: We want match values to convert when int and float => float - // but also we want to unify types when one of them is typed and other untyped??? - // Lastly maybe check if typed types are the same - if(is_int(a->type) && is_float(b->type)) +match_values(Token *pos, Value *a, Value *b){ + if(is_typed(a->type) && is_typed(b->type)){ + if(a->type != b->type){ + parsing_error(pos, "Type mismatch in match_values - left: %s right: %s", docname(a->type), docname(b->type)); + } + } + if(is_untyped(a->type) && is_typed(b->type)){ + assert(is_typed(b->type)); + *a = convert_untyped(pos, *a, b->type); + } + else if(is_typed(a->type) && is_untyped(b->type)){ + assert(is_typed(a->type)); + *b = convert_untyped(pos, *b, a->type); + } + + else if(is_int(a->type) && is_float(b->type)){ *a = value_float(a->big_int_val); - else if(is_float(a->type) && is_int(b->type)) + } + else if(is_float(a->type) && is_int(b->type)){ *b = value_float(b->big_int_val); + } } function Value compare_values(Token *pos, Token_Kind op, Value a, Value b){ if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(a.type)); - match_values(&a, &b); + match_values(pos, &a, &b); B32 result = 0; switch(a.type->kind){ @@ -137,8 +189,8 @@ compare_values(Token *pos, Token_Kind op, Value a, Value b){ }break; CASE_BOOL:{ switch(op){ - case TK_Equals: result = a.bool_val == b.bool_val; break; - case TK_NotEquals: result = a.bool_val != b.bool_val; break; + case TK_Equals: result = a.bool_val == b.bool_val; break; + case TK_NotEquals: result = a.bool_val != b.bool_val; break; invalid_default_case; } }break; @@ -164,13 +216,13 @@ compare_values(Token *pos, Token_Kind op, Value a, Value b){ function Value eval_binary(Token *pos, Token_Kind op, Value a, Value b){ - if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(a.type)); - match_values(&a, &b); - if(token_is_compare(op)){ return compare_values(pos, op, a, b); } + if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(a.type)); + match_values(pos, &a, &b); + Value result = {}; result.type = a.type; switch(a.type->kind){ @@ -285,6 +337,29 @@ try_untyping(Operand *op){ } } +function void +resolve_var(Token *pos, Operand *expr, Ast_Resolved_Type *type = 0){ + if(type == expr->type) { + assert(expr->type); + return; + } + + if(!type) + try_untyping(expr); + else if(!expr->type) + expr->type = type; + else if(is_untyped(expr->type)) + expr->value = convert_untyped(pos, expr->value, type); + + if(type && expr->type != type){ + parsing_error(pos, "Assigning but incompatible types, expression: %s expected var type: %s", docname(expr->type), docname(type)); + } + + type_complete(expr->type); + check_value_bounds(pos, &expr->value); + assert(expr->type); +} + #define rewrite_into_const(ast,T,s) _rewrite_into_const(ast,sizeof(T),s) function void _rewrite_into_const(Ast *node, U64 ast_size, Value value){ @@ -395,11 +470,7 @@ resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){ For(lambda->args){ Ast_Resolved_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL); Operand default_value = resolve_expr(it->default_value, type); - - if(default_value.type){ - default_value.value = convert_untyped(it->pos, default_value.value, type); - if(default_value.type != type) parsing_error(it->pos, "Default value type and type declaration differ, expected %s got instead %s", docname(type), docname(default_value.type)); - } + resolve_var(it->pos, &default_value, type); args.add(type); } @@ -422,6 +493,7 @@ resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){ For(lambda->args){ S64 i = lambda->args.get_index(&it); Ast_Resolved_Type *type = args[i]; + sym_var(it->name, type, it, INSERT_INTO_SCOPE); } For(lambda->block->stmts){ @@ -671,7 +743,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res } if(original_type != type) assert(expr.type == type); - check_value_boundaries(node->pos, &expr.value); + check_value_bounds(node->pos, &expr.value); return expr; BREAK(); } @@ -713,9 +785,10 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res assert(node->left->kind == AST_IDENT); Operand right = resolve_expr(node->right); - try_untyping(&right); + resolve_var(node->pos, &right); + assert(right.type); - Ast_Atom *atom = (Ast_Atom *)node->left; + auto atom = (Ast_Atom *)node->left; sym_var(atom->intern_val, right, node, INSERT_INTO_SCOPE); } //----------------------------------------------------------------------------- @@ -822,29 +895,12 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res else{ Operand left = resolve_expr(node->left); Operand right = resolve_expr(node->right); + Value value = eval_binary(node->pos, node->op, left.value, right.value); if(left.is_const && right.is_const){ - Value value = eval_binary(node->pos, node->op, left.value, right.value); rewrite_into_const(node, Ast_Binary, value); result = operand_const_rvalue(value); } - else{ - if(is_untyped(left.type)){ - assert(is_typed(right.type)); - left.value = convert_untyped(node->pos, left.value, right.type); - } - else if(is_untyped(right.type)){ - assert(is_typed(left.type)); - right.value = convert_untyped(node->pos, right.value, left.type); - } - - - if(left.type != right.type){ - parsing_error(node->pos, "Type mismatch in binary operation %s - left: %s right: %s", name(node->op), docname(left.type), docname(right.type)); - } - else{ - result = operand_rvalue(left.type); - } - } + else result = operand_rvalue(left.type); } //----------------------------------------------------------------------------- @@ -907,14 +963,8 @@ resolve_binding(Ast *ast, Sym *sym){ Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL); Operand expr = resolve_expr(node->expr, type); assert(expr.type != 0 || type != 0); - - if(!type) try_untyping(&expr); - else if(!expr.type) expr.type = type; - else if(type == expr.type); - else if(is_untyped(expr.type)) expr.value = convert_untyped(node->pos, expr.value, type); - else invalid_codepath; - - type_complete(expr.type); + resolve_var(node->pos, &expr, type); + assert(expr.type); return expr; BREAK(); } @@ -945,7 +995,6 @@ resolve_sym(Sym *sym){ sym->state = SYM_RESOLVING; { Operand op = resolve_binding(sym->ast, sym); - sym->type = op.type; sym->value = op.value; } sym->state = SYM_RESOLVED;