mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-14 15:11:25 -07:00
++ -- statements; add strconv.odin (and replace some of the fmt procs); Fix ~ on 64 bit constants; Fix integer casts from smaller to larger size
This commit is contained in:
+19
-8
@@ -197,11 +197,11 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
|
||||
}
|
||||
}
|
||||
|
||||
// if (is_type_proc(dst)) {
|
||||
// if (are_types_identical(src, dst)) {
|
||||
// return 1;
|
||||
// }
|
||||
// }
|
||||
if (is_type_proc(dst)) {
|
||||
if (are_types_identical(src, dst)) {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_type_any(dst)) {
|
||||
// NOTE(bill): Anything can cast to `Any`
|
||||
@@ -2827,6 +2827,16 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (entity == NULL &&
|
||||
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->type = t_untyped_integer;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (entity == NULL) {
|
||||
gbString op_str = expr_to_string(op_expr);
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
@@ -5445,9 +5455,10 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
||||
|
||||
case_ast_node(at, ArrayType, node);
|
||||
str = gb_string_appendc(str, "[");
|
||||
if (at->count->kind == AstNode_UnaryExpr &&
|
||||
at->count->UnaryExpr.op.kind == Token_Hash) {
|
||||
str = gb_string_appendc(str, "#");
|
||||
if (at->count != NULL &&
|
||||
at->count->kind == AstNode_UnaryExpr &&
|
||||
at->count->UnaryExpr.op.kind == Token_Ellipsis) {
|
||||
str = gb_string_appendc(str, "...");
|
||||
} else {
|
||||
str = write_expr_to_string(str, at->count);
|
||||
}
|
||||
|
||||
+46
-2
@@ -421,6 +421,49 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
check_stmt(c, ts->stmt, flags);
|
||||
case_end;
|
||||
|
||||
case_ast_node(s, IncDecStmt, node);
|
||||
TokenKind op = s->op.kind;
|
||||
switch (op) {
|
||||
case Token_Inc: op = Token_Add; break;
|
||||
case Token_Dec: op = Token_Sub; break;
|
||||
default:
|
||||
error_node(node, "Invalid inc/dec operation");
|
||||
return;
|
||||
}
|
||||
|
||||
Operand x = {0};
|
||||
check_expr(c, &x, s->expr);
|
||||
if (x.mode == Addressing_Invalid) {
|
||||
return;
|
||||
}
|
||||
if (!is_type_integer(x.type) && !is_type_float(x.type)) {
|
||||
gbString e = expr_to_string(s->expr);
|
||||
gbString t = type_to_string(x.type);
|
||||
error_node(node, "%s%.*s used on non-numeric type %s", e, LIT(s->op.string), t);
|
||||
gb_string_free(t);
|
||||
gb_string_free(e);
|
||||
return;
|
||||
}
|
||||
AstNode *left = s->expr;
|
||||
AstNode *right = gb_alloc_item(c->allocator, AstNode);
|
||||
right->kind = AstNode_BasicLit;
|
||||
right->BasicLit.pos = s->op.pos;
|
||||
right->BasicLit.kind = Token_Integer;
|
||||
right->BasicLit.string = str_lit("1");
|
||||
|
||||
AstNode *be = gb_alloc_item(c->allocator, AstNode);
|
||||
be->kind = AstNode_BinaryExpr;
|
||||
be->BinaryExpr.op = s->op;
|
||||
be->BinaryExpr.op.kind = op;
|
||||
be->BinaryExpr.left = left;
|
||||
be->BinaryExpr.right = right;
|
||||
check_binary_expr(c, &x, be);
|
||||
if (x.mode == Addressing_Invalid) {
|
||||
return;
|
||||
}
|
||||
check_assignment_variable(c, &x, left);
|
||||
case_end;
|
||||
|
||||
case_ast_node(as, AssignStmt, node);
|
||||
switch (as->op.kind) {
|
||||
case Token_Eq: {
|
||||
@@ -591,8 +634,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
if (fs->post != NULL) {
|
||||
check_stmt(c, fs->post, 0);
|
||||
|
||||
if (fs->post->kind != AstNode_AssignStmt) {
|
||||
error_node(fs->post, "`for` statement post statement must be an assignment");
|
||||
if (fs->post->kind != AstNode_AssignStmt &&
|
||||
fs->post->kind != AstNode_IncDecStmt) {
|
||||
error_node(fs->post, "`for` statement post statement must be a simple statement");
|
||||
}
|
||||
}
|
||||
check_stmt(c, fs->body, new_flags);
|
||||
|
||||
+4
-3
@@ -274,8 +274,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
|
||||
case ExactValue_Invalid:
|
||||
return v;
|
||||
case ExactValue_Integer:
|
||||
i = v.value_integer;
|
||||
i = ~i;
|
||||
i = ~v.value_integer;
|
||||
break;
|
||||
default:
|
||||
goto failure;
|
||||
@@ -283,8 +282,10 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
|
||||
|
||||
// NOTE(bill): unsigned integers will be negative and will need to be
|
||||
// limited to the types precision
|
||||
if (precision > 0)
|
||||
// IMPORTANT NOTE(bill): Max precision is 64 bits as that's how integers are stored
|
||||
if (0 < precision && precision < 64) {
|
||||
i &= ~((~0ll)<<precision);
|
||||
}
|
||||
|
||||
return make_exact_value_integer(i);
|
||||
} break;
|
||||
|
||||
@@ -233,6 +233,7 @@ struct irProcedure {
|
||||
#define IR_CONV_KINDS \
|
||||
IR_CONV_KIND(trunc) \
|
||||
IR_CONV_KIND(zext) \
|
||||
IR_CONV_KIND(sext) \
|
||||
IR_CONV_KIND(fptrunc) \
|
||||
IR_CONV_KIND(fpext) \
|
||||
IR_CONV_KIND(fptoui) \
|
||||
@@ -2240,12 +2241,23 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
||||
i64 sz = type_size_of(proc->module->allocator, src);
|
||||
i64 dz = type_size_of(proc->module->allocator, dst);
|
||||
irConvKind kind = irConv_trunc;
|
||||
if (sz == dz) {
|
||||
if (dz == sz) {
|
||||
// NOTE(bill): In LLVM, all integers are signed and rely upon 2's compliment
|
||||
// NOTE(bill): Copy the value just for type correctness
|
||||
kind = irConv_bitcast;
|
||||
} else if (dz > sz) {
|
||||
kind = irConv_zext;
|
||||
|
||||
// TODO(bill): figure out the rules completely
|
||||
bool ss = !is_type_unsigned(src);
|
||||
bool ds = !is_type_unsigned(dst);
|
||||
if (ss && ds) {
|
||||
kind = irConv_sext;
|
||||
} else if (ss) {
|
||||
kind = irConv_sext;
|
||||
} else {
|
||||
kind = irConv_zext;
|
||||
}
|
||||
}
|
||||
|
||||
return ir_emit(proc, ir_make_instr_conv(proc, kind, value, src, dst));
|
||||
@@ -4769,6 +4781,15 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
ir_build_when_stmt(proc, ws);
|
||||
case_end;
|
||||
|
||||
case_ast_node(s, IncDecStmt, node);
|
||||
TokenKind op = Token_Add;
|
||||
if (s->op.kind == Token_Dec) {
|
||||
op = Token_Sub;
|
||||
}
|
||||
irAddr addr = ir_build_addr(proc, s->expr);
|
||||
ir_build_assign_op(proc, addr, v_one, op);
|
||||
case_end;
|
||||
|
||||
case_ast_node(vd, ValueDecl, node);
|
||||
if (vd->is_var) {
|
||||
irModule *m = proc->module;
|
||||
|
||||
@@ -186,6 +186,10 @@ AST_NODE_KIND(_StmtBegin, "", i32) \
|
||||
Token op; \
|
||||
AstNodeArray lhs, rhs; \
|
||||
}) \
|
||||
AST_NODE_KIND(IncDecStmt, "increment decrement statement", struct { \
|
||||
Token op; \
|
||||
AstNode *expr; \
|
||||
}) \
|
||||
AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
|
||||
AST_NODE_KIND(BlockStmt, "block statement", struct { \
|
||||
AstNodeArray stmts; \
|
||||
@@ -467,6 +471,7 @@ Token ast_node_token(AstNode *node) {
|
||||
case AstNode_ExprStmt: return ast_node_token(node->ExprStmt.expr);
|
||||
case AstNode_TagStmt: return node->TagStmt.token;
|
||||
case AstNode_AssignStmt: return node->AssignStmt.op;
|
||||
case AstNode_IncDecStmt: return ast_node_token(node->IncDecStmt.expr);
|
||||
case AstNode_BlockStmt: return node->BlockStmt.open;
|
||||
case AstNode_IfStmt: return node->IfStmt.token;
|
||||
case AstNode_WhenStmt: return node->WhenStmt.token;
|
||||
@@ -802,6 +807,16 @@ AstNode *ast_assign_stmt(AstFile *f, Token op, AstNodeArray lhs, AstNodeArray rh
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AstNode *ast_inc_dec_stmt(AstFile *f, Token op, AstNode *expr) {
|
||||
AstNode *result = make_ast_node(f, AstNode_IncDecStmt);
|
||||
result->IncDecStmt.op = op;
|
||||
result->IncDecStmt.expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AstNode *ast_block_stmt(AstFile *f, AstNodeArray stmts, Token open, Token close) {
|
||||
AstNode *result = make_ast_node(f, AstNode_BlockStmt);
|
||||
result->BlockStmt.stmts = stmts;
|
||||
@@ -2272,6 +2287,13 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
|
||||
return ast_bad_stmt(f, token, f->curr_token);
|
||||
}
|
||||
|
||||
switch (token.kind) {
|
||||
case Token_Inc:
|
||||
case Token_Dec:
|
||||
next_token(f);
|
||||
return ast_inc_dec_stmt(f, token, lhs.e[0]);
|
||||
}
|
||||
|
||||
return ast_expr_stmt(f, lhs.e[0]);
|
||||
}
|
||||
|
||||
|
||||
+9
-9
@@ -51,8 +51,8 @@ TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \
|
||||
TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \
|
||||
TOKEN_KIND(Token_ArrowRight, "->"), \
|
||||
TOKEN_KIND(Token_ArrowLeft, "<-"), \
|
||||
TOKEN_KIND(Token_Increment, "++"), \
|
||||
TOKEN_KIND(Token_Decrement, "--"), \
|
||||
TOKEN_KIND(Token_Inc, "++"), \
|
||||
TOKEN_KIND(Token_Dec, "--"), \
|
||||
\
|
||||
TOKEN_KIND(Token__ComparisonBegin, "_ComparisonBegin"), \
|
||||
TOKEN_KIND(Token_CmpEq, "=="), \
|
||||
@@ -859,13 +859,13 @@ Token tokenizer_get_token(Tokenizer *t) {
|
||||
case '{': token.kind = Token_OpenBrace; break;
|
||||
case '}': token.kind = Token_CloseBrace; break;
|
||||
|
||||
case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break;
|
||||
case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq); break;
|
||||
case '=': token.kind = token_kind_variant2(t, Token_Eq, Token_CmpEq); break;
|
||||
case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break;
|
||||
case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break;
|
||||
case '+': token.kind = token_kind_variant3(t, Token_Add, Token_AddEq, '+', Token_Increment); break;
|
||||
case '-': token.kind = token_kind_variant4(t, Token_Sub, Token_SubEq, '-', Token_Decrement, '>', Token_ArrowRight); break;
|
||||
case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break;
|
||||
case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq); break;
|
||||
case '=': token.kind = token_kind_variant2(t, Token_Eq, Token_CmpEq); break;
|
||||
case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break;
|
||||
case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break;
|
||||
case '+': token.kind = token_kind_variant3(t, Token_Add, Token_AddEq, '+', Token_Inc); break;
|
||||
case '-': token.kind = token_kind_variant4(t, Token_Sub, Token_SubEq, '-', Token_Dec, '>', Token_ArrowRight); break;
|
||||
case '/': {
|
||||
if (t->curr_rune == '/') {
|
||||
while (t->curr_rune != '\n' && t->curr_rune != GB_RUNE_EOF) {
|
||||
|
||||
Reference in New Issue
Block a user