diff --git a/include/vm.h b/include/vm.h index 548b2cc..02afb74 100644 --- a/include/vm.h +++ b/include/vm.h @@ -48,6 +48,8 @@ struct Instruction { Return, Call, JumpIfFalse, + JumpIfLessOrEqualsI32, + JumpIfGreaterOrEqualsI32, Jump, } type{}; union { diff --git a/src/ast.cpp b/src/ast.cpp index 69680b0..01617e9 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -388,10 +388,37 @@ bool IfStatement::operator==(const AbstractSyntaxTree &other) const { elseBody.has_value() == otherIfStatement.elseBody.has_value(); } void IfStatement::compile(Program &program, Segment &segment) const { - condition->compile(program, segment); - size_t jumpIndex = segment.instructions.size(); - segment.instructions.push_back( - Instruction{.type = Instruction::InstructionType::JumpIfFalse}); + size_t jumpIndex; + bool unOptimized = false; + if (condition->nodeType == AbstractSyntaxTree::Type::BinaryExpression && + dynamic_cast(condition)->op.type == Less) { + auto binaryExpression = dynamic_cast(condition); + binaryExpression->left->compile(program, segment); + binaryExpression->right->compile(program, segment); + jumpIndex = segment.instructions.size(); + segment.instructions.push_back( + Instruction{.type = Instruction::InstructionType::JumpIfGreaterOrEqualsI32}); + } else if (condition->nodeType == AbstractSyntaxTree::Type::BinaryExpression && + dynamic_cast(condition)->op.type == Greater) { + auto binaryExpression = dynamic_cast(condition); + binaryExpression->left->compile(program, segment); + binaryExpression->right->compile(program, segment); + jumpIndex = segment.instructions.size(); + segment.instructions.push_back( + Instruction{.type = Instruction::InstructionType::JumpIfLessOrEqualsI32}); + } else if (condition->nodeType == AbstractSyntaxTree::Type::BinaryExpression && + dynamic_cast(condition)->op.type == Equal) { + auto binaryExpression = dynamic_cast(condition); + binaryExpression->left->compile(program, segment); + binaryExpression->right->compile(program, segment); + jumpIndex = segment.instructions.size(); + segment.instructions.push_back( + Instruction{.type = Instruction::InstructionType::JumpIfFalse}); + } else { + condition->compile(program, segment); + jumpIndex = segment.instructions.size(); + unOptimized = true; + } thenBody->compile(program, segment); segment.instructions[jumpIndex].params.index = segment.instructions.size() + elseBody.has_value(); if (elseBody.has_value()) { @@ -399,7 +426,7 @@ void IfStatement::compile(Program &program, Segment &segment) const { segment.instructions.push_back( Instruction{.type = Instruction::InstructionType::Jump}); elseBody.value()->compile(program, segment); - segment.instructions[jumpIndex].params.index = segment.instructions.size() + 1; + segment.instructions[jumpIndex].params.index = segment.instructions.size() + unOptimized; } } diff --git a/src/vm.cpp b/src/vm.cpp index fad8a22..8034894 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -201,6 +201,30 @@ void VM::run(const Program &program) { } free(val); } break; + case Instruction::InstructionType::JumpIfLessOrEqualsI32: { + auto b = static_cast(popStack(sizeof(int32_t))); + auto a = static_cast(popStack(sizeof(int32_t))); + if (*a <= *b) { + callStack.back().currentInstruction = instruction.params.index; + free(a); + free(b); + continue; + } + free(a); + free(b); + } break; + case Instruction::InstructionType::JumpIfGreaterOrEqualsI32: { + auto b = static_cast(popStack(sizeof(int32_t))); + auto a = static_cast(popStack(sizeof(int32_t))); + if (*a >= *b) { + callStack.back().currentInstruction = instruction.params.index; + free(a); + free(b); + continue; + } + free(a); + free(b); + } break; case Instruction::InstructionType::Jump: callStack.back().currentInstruction = instruction.params.index; continue;