if (actual_number < 0) {
number = actual_number + 65536;
}
- buf[1] = number >> 8;
- buf[2] = number & 0xFF;
+ buf[1] = (number >> 8) & 0xFF;
+ buf[2] = (number >> 0) & 0xFF;
sbVmCompiler_write_code(cm, buf, 3);
} else if (-(1L << 31) < actual_number && actual_number < (1L << 31)) {
buf[0] = BC_VLONG_NUM;
if (actual_number < 0) {
number = actual_number + (1LL << 32);
}
- buf[1] = (number >> 24) & 0xFF;;
+ buf[1] = (number >> 24) & 0xFF;
buf[2] = (number >> 16) & 0xFF;
- buf[3] = (number >> 8) & 0xFF;
- buf[4] = number & 0xFF;
+ buf[3] = (number >> 8) & 0xFF;
+ buf[4] = (number >> 0) & 0xFF;
sbVmCompiler_write_code(cm, buf, 5);
} else {
buf[0] = BC_VVLONG_NUM;
number = (u64)actual_number;
- buf[1] = (number >> 56) & 0xFF;;
- buf[2] = (number >> 48) & 0xFF;;
- buf[3] = (number >> 40) & 0xFF;;
- buf[4] = (number >> 32) & 0xFF;;
- buf[5] = (number >> 24) & 0xFF;;
+ buf[1] = (number >> 56) & 0xFF;
+ buf[2] = (number >> 48) & 0xFF;
+ buf[3] = (number >> 40) & 0xFF;
+ buf[4] = (number >> 32) & 0xFF;
+ buf[5] = (number >> 24) & 0xFF;
buf[6] = (number >> 16) & 0xFF;
- buf[7] = (number >> 8) & 0xFF;
- buf[8] = number & 0xFF;
+ buf[7] = (number >> 8) & 0xFF;
+ buf[8] = (number >> 0) & 0xFF;
sbVmCompiler_write_code(cm, buf, 9);
}
}
if (stmt->jump.label->found_yet) {
EARG(stmt->jump.label->block_position);
} else {
- debug("<forward jump>\n");
EMIT(BC_VLONG_NUM);
/* we have to remember to come back and fill in the address later when we
* know where this label is! */
EMIT(BC_LD_TRUE);
} else if (expr->value.type == IT_BOOLEAN) {
EMIT(BC_LD_FALSE);
- } else if (expr->value.type == IT_INTEGER && expr->value.integer < (2 << 16)) {
+ } else if (expr->value.type == IT_INTEGER && expr->value.integer < (2 << 8)) {
EMIT(BC_LD_IMM);
EARG(expr->value.integer);
} else {
/* --- */
+static sbIrExpr SENTINEL_NIL_EXPR = {
+ .type = IR_E_VALUE,
+ .value = (hV) { .type = IT_NIL }
+};
+static sbIrStmt SENTINEL_NO_STMT = {0};
+static sbIrVariable SENTINEL_NO_VAR = {0};
+static sbIrExpr *NIL_EXPR = &SENTINEL_NIL_EXPR;
+static sbIrStmt *NO_STMT = &SENTINEL_NO_STMT;
+static sbIrVariable *NO_VAR = &SENTINEL_NO_VAR;
+
static void vprogram_error(hIrProgram ir, const char *error, va_list args) {
ir->error_count ++;
fprintf(stderr, "error: ");
/* TODO do a different thing here */
chunk_error(ck, "unknown variable name! '%s'\n", name);
- return NULL;
+ return NO_VAR;
}
-static sbIrExpr SENTINEL_NIL_EXPR = {
- .type = IR_E_VALUE,
- .value = (hV) { .type = IT_NIL }
-};
-static sbIrExpr *NIL_EXPR = &SENTINEL_NIL_EXPR;
-static sbIrStmt SENTINEL_NO_STMT = {0};
-static sbIrStmt *NO_STMT = &SENTINEL_NO_STMT;
-
static sbIrLabel *new_label(hIrChunk ck) {
sbIrLabel *l = sbArena_alloc(&ck->program->arena, sizeof(sbIrLabel));
ck->label_count ++;
});
}
+static flag int_constant_fold(sbAstOp op, hInteger left, hInteger right, hInteger *result) {
+ switch (op) {
+ case AST_OP_ADD:
+ *result = left + right;
+ break;
+ case AST_OP_SUB:
+ *result = left - right;
+ break;
+ case AST_OP_MUL:
+ *result = left * right;
+ break;
+ case AST_OP_FLDIV:
+ *result = left / right;
+ break;
+ case AST_OP_MOD:
+ *result = left % right;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
static sbIrExpr *expr_op(hIrChunk ck, sbAstOp op, sbIrExpr *left, sbIrExpr *right) {
+ if (left->type == IR_E_VALUE && left->value.type == IT_INTEGER
+ && right->type == IR_E_VALUE && right->value.type == IT_INTEGER) {
+ /* Try constant folding */
+ hInteger result;
+ flag folded = int_constant_fold(op, left->value.integer, right->value.integer, &result);
+ if (folded) {
+ return new_expr(ck, &(sbIrExpr) {
+ .type = IR_E_VALUE,
+ .value = HVINT(result),
+ });
+ }
+ }
+
return new_expr(ck, &(sbIrExpr) {
.type = IR_E_OP,
.op.type = op,
compile_ast_stmt(ck, considering->seq.left, implicit_return && is_last_stmt);
considering = considering->seq.right;
+
+ if (ck->program->error_count > 0) {
+ return;
+ }
}
if (implicit_return) {
} else {
/* TODO make errors not bad */
chunk_error(ck, "Only a variable name is permitted here. (got %d)\n", node->type);
- return NULL;
+ return NO_VAR;
}
}
return expr_op(ck, node->op.type, left, right);
} else if (node->type == AST_VAL_INT) {
return expr_value(ck, &HVINT(node->i));
+ } else if (node->type == AST_VAL_STRING) {
+ return expr_value(ck, &HVSTR(node->str));
} else if (node->type == AST_NODE_NAME) {
/* TODO: I don't want to use strlen. Can we remember the lengths of symbols? */
sbIrVariable *var = compile_ast_var(ck, node);