chore: remove trailing whitespace from README.md formatting
This commit is contained in:
@@ -53,6 +53,7 @@ typedef enum {
|
||||
RAVA_OP_CALL,
|
||||
RAVA_OP_CALL_STATIC,
|
||||
RAVA_OP_CALL_VIRTUAL,
|
||||
RAVA_OP_CALL_SUPER,
|
||||
RAVA_OP_CALL_NATIVE,
|
||||
RAVA_OP_RETURN,
|
||||
RAVA_OP_RETURN_VOID,
|
||||
@@ -67,6 +68,8 @@ typedef enum {
|
||||
RAVA_OP_INSTANCEOF,
|
||||
|
||||
RAVA_OP_THROW,
|
||||
RAVA_OP_TRY_BEGIN,
|
||||
RAVA_OP_TRY_END,
|
||||
RAVA_OP_POP,
|
||||
RAVA_OP_DUP,
|
||||
|
||||
@@ -78,6 +81,13 @@ typedef enum {
|
||||
RAVA_OP_STRING_SUBSTRING,
|
||||
RAVA_OP_STRING_EQUALS,
|
||||
RAVA_OP_STRING_COMPARETO,
|
||||
RAVA_OP_STRING_INDEXOF,
|
||||
RAVA_OP_STRING_CONTAINS,
|
||||
RAVA_OP_STRING_STARTSWITH,
|
||||
RAVA_OP_STRING_ENDSWITH,
|
||||
RAVA_OP_STRING_TOLOWERCASE,
|
||||
RAVA_OP_STRING_TOUPPERCASE,
|
||||
RAVA_OP_STRING_TRIM,
|
||||
|
||||
RAVA_OP_LOAD_THIS,
|
||||
|
||||
@@ -96,7 +106,22 @@ typedef enum {
|
||||
RAVA_OP_LOAD_LOCAL_CONST_LE_JUMPFALSE,
|
||||
RAVA_OP_LOAD_TWO_LOCALS,
|
||||
RAVA_OP_ADD_LOCAL_TO_LOCAL,
|
||||
RAVA_OP_LOAD_LOCAL_LT_LOCAL_JUMPFALSE
|
||||
RAVA_OP_LOAD_LOCAL_LT_LOCAL_JUMPFALSE,
|
||||
|
||||
RAVA_OP_MATH_ABS,
|
||||
RAVA_OP_MATH_SQRT,
|
||||
RAVA_OP_MATH_POW,
|
||||
RAVA_OP_MATH_MIN,
|
||||
RAVA_OP_MATH_MAX,
|
||||
RAVA_OP_MATH_FLOOR,
|
||||
RAVA_OP_MATH_CEIL,
|
||||
RAVA_OP_MATH_ROUND,
|
||||
RAVA_OP_MATH_SIN,
|
||||
RAVA_OP_MATH_COS,
|
||||
RAVA_OP_MATH_TAN,
|
||||
RAVA_OP_MATH_LOG,
|
||||
RAVA_OP_MATH_EXP,
|
||||
RAVA_OP_MATH_RANDOM
|
||||
} RavaOpCode_e;
|
||||
|
||||
typedef union {
|
||||
@@ -135,6 +160,12 @@ typedef union {
|
||||
int local2;
|
||||
int label_id;
|
||||
} cmp_locals;
|
||||
struct {
|
||||
int catch_label;
|
||||
int finally_label;
|
||||
int end_label;
|
||||
int exception_local;
|
||||
} try_handler;
|
||||
} RavaOperand_u;
|
||||
|
||||
typedef struct {
|
||||
|
||||
+557
-8
@@ -35,6 +35,15 @@ static int _rava_ir_find_local(RavaIRGenerator_t *gen, const char *name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool _rava_ir_is_class_name(RavaIRGenerator_t *gen, const char *name) {
|
||||
for (size_t i = 0; i < gen->program->class_count; i++) {
|
||||
if (strcmp(gen->program->classes[i]->name, name) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RavaIRGenerator_t* rava_ir_generator_create(RavaSemanticAnalyzer_t *analyzer) {
|
||||
RavaIRGenerator_t *gen = calloc(1, sizeof(RavaIRGenerator_t));
|
||||
gen->program = rava_program_create();
|
||||
@@ -82,6 +91,12 @@ static void _rava_ir_gen_binary_expr(RavaIRGenerator_t *gen, RavaASTNode_t *expr
|
||||
case RAVA_BINOP_GE: instr.opcode = RAVA_OP_GE; break;
|
||||
case RAVA_BINOP_AND: instr.opcode = RAVA_OP_AND; break;
|
||||
case RAVA_BINOP_OR: instr.opcode = RAVA_OP_OR; break;
|
||||
case RAVA_BINOP_BITAND: instr.opcode = RAVA_OP_AND; break;
|
||||
case RAVA_BINOP_BITOR: instr.opcode = RAVA_OP_OR; break;
|
||||
case RAVA_BINOP_BITXOR: instr.opcode = RAVA_OP_XOR; break;
|
||||
case RAVA_BINOP_LSHIFT: instr.opcode = RAVA_OP_SHL; break;
|
||||
case RAVA_BINOP_RSHIFT: instr.opcode = RAVA_OP_SHR; break;
|
||||
case RAVA_BINOP_URSHIFT: instr.opcode = RAVA_OP_USHR; break;
|
||||
default: instr.opcode = RAVA_OP_NOP; break;
|
||||
}
|
||||
|
||||
@@ -190,6 +205,19 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
instr.opcode = RAVA_OP_STORE_ARRAY;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (expr->data.assign.target->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
|
||||
RavaASTNode_t *target_member = expr->data.assign.target;
|
||||
if (target_member->data.member_access.object->type == RAVA_AST_IDENTIFIER_EXPR) {
|
||||
const char *obj_name = target_member->data.member_access.object->data.identifier.name;
|
||||
if (_rava_ir_is_class_name(gen, obj_name) ||
|
||||
strcmp(obj_name, gen->current_class->name) == 0) {
|
||||
_rava_ir_gen_expression(gen, expr->data.assign.value);
|
||||
instr.opcode = RAVA_OP_STORE_STATIC;
|
||||
instr.operand.field.class_name = strdup(obj_name);
|
||||
instr.operand.field.field_name = strdup(target_member->data.member_access.member);
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_rava_ir_gen_expression(gen, expr->data.assign.target->data.member_access.object);
|
||||
_rava_ir_gen_expression(gen, expr->data.assign.value);
|
||||
instr.opcode = RAVA_OP_PUT_FIELD;
|
||||
@@ -210,6 +238,17 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
break;
|
||||
|
||||
case RAVA_AST_MEMBER_ACCESS_EXPR:
|
||||
if (expr->data.member_access.object->type == RAVA_AST_IDENTIFIER_EXPR) {
|
||||
const char *obj_name = expr->data.member_access.object->data.identifier.name;
|
||||
if (_rava_ir_is_class_name(gen, obj_name) ||
|
||||
strcmp(obj_name, gen->current_class->name) == 0) {
|
||||
instr.opcode = RAVA_OP_LOAD_STATIC;
|
||||
instr.operand.field.class_name = strdup(obj_name);
|
||||
instr.operand.field.field_name = strdup(expr->data.member_access.member);
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_rava_ir_gen_expression(gen, expr->data.member_access.object);
|
||||
instr.opcode = RAVA_OP_GET_FIELD;
|
||||
instr.operand.field.field_name = strdup(expr->data.member_access.member);
|
||||
@@ -251,13 +290,36 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
bool is_print = false;
|
||||
bool is_string_length = false;
|
||||
bool is_string_charat = false;
|
||||
bool is_string_substring = false;
|
||||
bool is_string_equals = false;
|
||||
bool is_string_compareto = false;
|
||||
bool is_string_indexof = false;
|
||||
bool is_string_contains = false;
|
||||
bool is_string_startswith = false;
|
||||
bool is_string_endswith = false;
|
||||
bool is_string_tolowercase = false;
|
||||
bool is_string_touppercase = false;
|
||||
bool is_string_trim = false;
|
||||
bool is_file_read = false;
|
||||
bool is_file_write = false;
|
||||
bool is_file_exists = false;
|
||||
bool is_file_delete = false;
|
||||
bool is_current_time_millis = false;
|
||||
bool is_nano_time = false;
|
||||
bool is_math_abs = false;
|
||||
bool is_math_sqrt = false;
|
||||
bool is_math_pow = false;
|
||||
bool is_math_min = false;
|
||||
bool is_math_max = false;
|
||||
bool is_math_floor = false;
|
||||
bool is_math_ceil = false;
|
||||
bool is_math_round = false;
|
||||
bool is_math_sin = false;
|
||||
bool is_math_cos = false;
|
||||
bool is_math_tan = false;
|
||||
bool is_math_log = false;
|
||||
bool is_math_exp = false;
|
||||
bool is_math_random = false;
|
||||
RavaASTNode_t *string_object = NULL;
|
||||
|
||||
if (expr->data.call.callee->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
|
||||
@@ -294,6 +356,39 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
is_file_delete = true;
|
||||
}
|
||||
}
|
||||
if (member->data.member_access.object->type == RAVA_AST_IDENTIFIER_EXPR &&
|
||||
strcmp(member->data.member_access.object->data.identifier.name, "Math") == 0) {
|
||||
const char *method = member->data.member_access.member;
|
||||
if (strcmp(method, "abs") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_abs = true;
|
||||
} else if (strcmp(method, "sqrt") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_sqrt = true;
|
||||
} else if (strcmp(method, "pow") == 0 && expr->data.call.arguments_count == 2) {
|
||||
is_math_pow = true;
|
||||
} else if (strcmp(method, "min") == 0 && expr->data.call.arguments_count == 2) {
|
||||
is_math_min = true;
|
||||
} else if (strcmp(method, "max") == 0 && expr->data.call.arguments_count == 2) {
|
||||
is_math_max = true;
|
||||
} else if (strcmp(method, "floor") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_floor = true;
|
||||
} else if (strcmp(method, "ceil") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_ceil = true;
|
||||
} else if (strcmp(method, "round") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_round = true;
|
||||
} else if (strcmp(method, "sin") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_sin = true;
|
||||
} else if (strcmp(method, "cos") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_cos = true;
|
||||
} else if (strcmp(method, "tan") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_tan = true;
|
||||
} else if (strcmp(method, "log") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_log = true;
|
||||
} else if (strcmp(method, "exp") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_math_exp = true;
|
||||
} else if (strcmp(method, "random") == 0 && expr->data.call.arguments_count == 0) {
|
||||
is_math_random = true;
|
||||
}
|
||||
}
|
||||
if (strcmp(member->data.member_access.member, "length") == 0 && expr->data.call.arguments_count == 0) {
|
||||
is_string_length = true;
|
||||
string_object = member->data.member_access.object;
|
||||
@@ -303,6 +398,33 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
} else if (strcmp(member->data.member_access.member, "equals") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_equals = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "substring") == 0 && expr->data.call.arguments_count == 2) {
|
||||
is_string_substring = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "compareTo") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_compareto = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "indexOf") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_indexof = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "contains") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_contains = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "startsWith") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_startswith = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "endsWith") == 0 && expr->data.call.arguments_count == 1) {
|
||||
is_string_endswith = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "toLowerCase") == 0 && expr->data.call.arguments_count == 0) {
|
||||
is_string_tolowercase = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "toUpperCase") == 0 && expr->data.call.arguments_count == 0) {
|
||||
is_string_touppercase = true;
|
||||
string_object = member->data.member_access.object;
|
||||
} else if (strcmp(member->data.member_access.member, "trim") == 0 && expr->data.call.arguments_count == 0) {
|
||||
is_string_trim = true;
|
||||
string_object = member->data.member_access.object;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,6 +465,107 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_EQUALS;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_substring) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[1]);
|
||||
instr.opcode = RAVA_OP_STRING_SUBSTRING;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_compareto) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_COMPARETO;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_indexof) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_INDEXOF;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_contains) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_CONTAINS;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_startswith) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_STARTSWITH;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_endswith) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_STRING_ENDSWITH;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_tolowercase) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
instr.opcode = RAVA_OP_STRING_TOLOWERCASE;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_touppercase) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
instr.opcode = RAVA_OP_STRING_TOUPPERCASE;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_string_trim) {
|
||||
_rava_ir_gen_expression(gen, string_object);
|
||||
instr.opcode = RAVA_OP_STRING_TRIM;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_abs) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_ABS;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_sqrt) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_SQRT;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_pow) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[1]);
|
||||
instr.opcode = RAVA_OP_MATH_POW;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_min) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[1]);
|
||||
instr.opcode = RAVA_OP_MATH_MIN;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_max) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[1]);
|
||||
instr.opcode = RAVA_OP_MATH_MAX;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_floor) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_FLOOR;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_ceil) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_CEIL;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_round) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_ROUND;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_sin) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_SIN;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_cos) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_COS;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_tan) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_TAN;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_log) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_LOG;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_exp) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[0]);
|
||||
instr.opcode = RAVA_OP_MATH_EXP;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_math_random) {
|
||||
instr.opcode = RAVA_OP_MATH_RANDOM;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (is_println || is_print) {
|
||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[i]);
|
||||
@@ -355,15 +578,28 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else if (expr->data.call.callee->type == RAVA_AST_MEMBER_ACCESS_EXPR) {
|
||||
RavaASTNode_t *member = expr->data.call.callee;
|
||||
_rava_ir_gen_expression(gen, member->data.member_access.object);
|
||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[i]);
|
||||
if (member->data.member_access.object->type == RAVA_AST_SUPER_EXPR) {
|
||||
instr.opcode = RAVA_OP_LOAD_THIS;
|
||||
_rava_ir_emit(gen, instr);
|
||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[i]);
|
||||
}
|
||||
instr.opcode = RAVA_OP_CALL_SUPER;
|
||||
instr.operand.call.class_name = gen->current_class->superclass ? strdup(gen->current_class->superclass) : NULL;
|
||||
instr.operand.call.method_name = strdup(member->data.member_access.member);
|
||||
instr.operand.call.arg_count = expr->data.call.arguments_count;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else {
|
||||
_rava_ir_gen_expression(gen, member->data.member_access.object);
|
||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[i]);
|
||||
}
|
||||
instr.opcode = RAVA_OP_CALL_VIRTUAL;
|
||||
instr.operand.call.class_name = strdup(gen->current_class->name);
|
||||
instr.operand.call.method_name = strdup(member->data.member_access.member);
|
||||
instr.operand.call.arg_count = expr->data.call.arguments_count;
|
||||
_rava_ir_emit(gen, instr);
|
||||
}
|
||||
instr.opcode = RAVA_OP_CALL_VIRTUAL;
|
||||
instr.operand.call.class_name = strdup(gen->current_class->name);
|
||||
instr.operand.call.method_name = strdup(member->data.member_access.member);
|
||||
instr.operand.call.arg_count = expr->data.call.arguments_count;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else {
|
||||
for (size_t i = 0; i < expr->data.call.arguments_count; i++) {
|
||||
_rava_ir_gen_expression(gen, expr->data.call.arguments[i]);
|
||||
@@ -384,6 +620,74 @@ static void _rava_ir_gen_expression(RavaIRGenerator_t *gen, RavaASTNode_t *expr)
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
|
||||
case RAVA_AST_CAST_EXPR:
|
||||
_rava_ir_gen_expression(gen, expr->data.cast.expression);
|
||||
instr.opcode = RAVA_OP_CAST;
|
||||
if (expr->data.cast.type && expr->data.cast.type->data.type.type_name) {
|
||||
instr.operand.var.type = rava_type_from_name(expr->data.cast.type->data.type.type_name);
|
||||
}
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
|
||||
case RAVA_AST_TERNARY_EXPR: {
|
||||
_rava_ir_gen_expression(gen, expr->data.ternary.condition);
|
||||
|
||||
int else_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
|
||||
instr.opcode = RAVA_OP_JUMP_IF_FALSE;
|
||||
instr.operand.label_id = else_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_expression(gen, expr->data.ternary.true_expr);
|
||||
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = else_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_expression(gen, expr->data.ternary.false_expr);
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_ARRAY_INIT_EXPR: {
|
||||
instr.opcode = RAVA_OP_LOAD_CONST;
|
||||
instr.operand.int_value = (int)expr->data.array_init.elements_count;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_NEW_ARRAY;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
for (size_t i = 0; i < expr->data.array_init.elements_count; i++) {
|
||||
instr.opcode = RAVA_OP_DUP;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_CONST;
|
||||
instr.operand.int_value = (int)i;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_expression(gen, expr->data.array_init.elements[i]);
|
||||
|
||||
instr.opcode = RAVA_OP_STORE_ARRAY;
|
||||
_rava_ir_emit(gen, instr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_INSTANCEOF_EXPR:
|
||||
_rava_ir_gen_expression(gen, expr->data.instanceof_expr.expression);
|
||||
instr.opcode = RAVA_OP_INSTANCEOF;
|
||||
instr.operand.string_value = strdup(expr->data.instanceof_expr.type_name);
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -463,6 +767,33 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_DO_WHILE_STMT: {
|
||||
int start_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
|
||||
RavaLoopContext_t loop_ctx = { .break_label = end_label, .continue_label = start_label, .parent = gen->loop_context };
|
||||
gen->loop_context = &loop_ctx;
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = start_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_statement(gen, stmt->data.while_stmt.body);
|
||||
|
||||
_rava_ir_gen_expression(gen, stmt->data.while_stmt.condition);
|
||||
|
||||
instr.opcode = RAVA_OP_JUMP_IF_TRUE;
|
||||
instr.operand.label_id = start_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
gen->loop_context = loop_ctx.parent;
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_FOR_STMT: {
|
||||
if (stmt->data.for_stmt.init) {
|
||||
if (stmt->data.for_stmt.init->type == RAVA_AST_VAR_DECL) {
|
||||
@@ -516,6 +847,93 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_ENHANCED_FOR_STMT: {
|
||||
size_t idx_local = gen->next_local++;
|
||||
size_t elem_local = gen->next_local++;
|
||||
gen->current_method->local_count = gen->next_local;
|
||||
|
||||
_rava_ir_add_local(gen, stmt->data.enhanced_for.var_name, elem_local);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_CONST;
|
||||
instr.operand.int_value = 0;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_STORE_LOCAL;
|
||||
instr.operand.var.index = idx_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
int start_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int continue_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
|
||||
RavaLoopContext_t loop_ctx = { .break_label = end_label, .continue_label = continue_label, .parent = gen->loop_context };
|
||||
gen->loop_context = &loop_ctx;
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = start_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_LOCAL;
|
||||
instr.operand.var.index = idx_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_expression(gen, stmt->data.enhanced_for.iterable);
|
||||
instr.opcode = RAVA_OP_ARRAY_LENGTH;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LT;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_JUMP_IF_FALSE;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_expression(gen, stmt->data.enhanced_for.iterable);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_LOCAL;
|
||||
instr.operand.var.index = idx_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_ARRAY;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_STORE_LOCAL;
|
||||
instr.operand.var.index = elem_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_statement(gen, stmt->data.enhanced_for.body);
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = continue_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_LOCAL;
|
||||
instr.operand.var.index = idx_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LOAD_CONST;
|
||||
instr.operand.int_value = 1;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_ADD;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_STORE_LOCAL;
|
||||
instr.operand.var.index = idx_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = start_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
gen->loop_context = loop_ctx.parent;
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_RETURN_STMT:
|
||||
if (stmt->data.return_stmt.value) {
|
||||
_rava_ir_gen_expression(gen, stmt->data.return_stmt.value);
|
||||
@@ -546,6 +964,67 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_SWITCH_STMT: {
|
||||
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
|
||||
RavaLoopContext_t switch_ctx = { .break_label = end_label, .continue_label = -1, .parent = gen->loop_context };
|
||||
gen->loop_context = &switch_ctx;
|
||||
|
||||
size_t case_count = stmt->children_count;
|
||||
int *case_labels = malloc(case_count * sizeof(int));
|
||||
int default_label = -1;
|
||||
|
||||
for (size_t i = 0; i < case_count; i++) {
|
||||
case_labels[i] = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
if (stmt->children[i]->data.case_stmt.is_default) {
|
||||
default_label = case_labels[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < case_count; i++) {
|
||||
RavaASTNode_t *case_node = stmt->children[i];
|
||||
if (!case_node->data.case_stmt.is_default) {
|
||||
_rava_ir_gen_expression(gen, stmt->data.switch_stmt.expression);
|
||||
_rava_ir_gen_expression(gen, case_node->data.case_stmt.value);
|
||||
instr.opcode = RAVA_OP_EQ;
|
||||
_rava_ir_emit(gen, instr);
|
||||
instr.opcode = RAVA_OP_JUMP_IF_TRUE;
|
||||
instr.operand.label_id = case_labels[i];
|
||||
_rava_ir_emit(gen, instr);
|
||||
}
|
||||
}
|
||||
|
||||
if (default_label >= 0) {
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = default_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else {
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < case_count; i++) {
|
||||
RavaASTNode_t *case_node = stmt->children[i];
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = case_labels[i];
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
for (size_t j = 0; j < case_node->children_count; j++) {
|
||||
_rava_ir_gen_statement(gen, case_node->children[j]);
|
||||
}
|
||||
}
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
free(case_labels);
|
||||
gen->loop_context = switch_ctx.parent;
|
||||
break;
|
||||
}
|
||||
|
||||
case RAVA_AST_BREAK_STMT:
|
||||
if (gen->loop_context) {
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
@@ -562,6 +1041,76 @@ static void _rava_ir_gen_statement(RavaIRGenerator_t *gen, RavaASTNode_t *stmt)
|
||||
}
|
||||
break;
|
||||
|
||||
case RAVA_AST_THROW_STMT:
|
||||
if (stmt->data.throw_stmt.expression) {
|
||||
_rava_ir_gen_expression(gen, stmt->data.throw_stmt.expression);
|
||||
} else {
|
||||
instr.opcode = RAVA_OP_LOAD_CONST;
|
||||
instr.operand.int_value = 1;
|
||||
_rava_ir_emit(gen, instr);
|
||||
}
|
||||
instr.opcode = RAVA_OP_THROW;
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
|
||||
case RAVA_AST_TRY_STMT: {
|
||||
int catch_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int finally_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
int end_label = rava_instruction_list_new_label(gen->current_method->instructions);
|
||||
|
||||
int exception_local = gen->next_local++;
|
||||
gen->current_method->local_count = gen->next_local;
|
||||
|
||||
instr.opcode = RAVA_OP_TRY_BEGIN;
|
||||
instr.operand.try_handler.catch_label = catch_label;
|
||||
instr.operand.try_handler.finally_label = stmt->data.try_stmt.finally_block ? finally_label : -1;
|
||||
instr.operand.try_handler.end_label = end_label;
|
||||
instr.operand.try_handler.exception_local = exception_local;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_statement(gen, stmt->data.try_stmt.try_block);
|
||||
|
||||
instr.opcode = RAVA_OP_TRY_END;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
if (stmt->data.try_stmt.finally_block) {
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = finally_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
} else {
|
||||
instr.opcode = RAVA_OP_JUMP;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
}
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = catch_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
for (size_t i = 0; i < stmt->data.try_stmt.catch_count; i++) {
|
||||
RavaASTNode_t *catch_node = stmt->data.try_stmt.catch_clauses[i];
|
||||
|
||||
if (catch_node->data.catch_clause.exception_name) {
|
||||
_rava_ir_add_local(gen, catch_node->data.catch_clause.exception_name, exception_local);
|
||||
}
|
||||
|
||||
_rava_ir_gen_statement(gen, catch_node->data.catch_clause.body);
|
||||
}
|
||||
|
||||
if (stmt->data.try_stmt.finally_block) {
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = finally_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
|
||||
_rava_ir_gen_statement(gen, stmt->data.try_stmt.finally_block);
|
||||
}
|
||||
|
||||
instr.opcode = RAVA_OP_LABEL;
|
||||
instr.operand.label_id = end_label;
|
||||
_rava_ir_emit(gen, instr);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user