aboutsummaryrefslogtreecommitdiff
path: root/src/check_stmt.c
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-02-26 00:44:26 +0000
committerGinger Bill <bill@gingerbill.org>2017-02-26 00:44:26 +0000
commitc59f6b7d0b582131bed4450bbb9aa1a71d5a01af (patch)
tree34957d43fa0241ffb6678302cae8e77fb7f8488b /src/check_stmt.c
parent67ed8a9a4ab8fdcfc77036c827b7dfa98025bc8b (diff)
++ -- statements; add strconv.odin (and replace some of the fmt procs); Fix ~ on 64 bit constants; Fix integer casts from smaller to larger size
Diffstat (limited to 'src/check_stmt.c')
-rw-r--r--src/check_stmt.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/src/check_stmt.c b/src/check_stmt.c
index 90cb6ff61..9c0b0c187 100644
--- a/src/check_stmt.c
+++ b/src/check_stmt.c
@@ -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);