diff --git a/src/bytecode/builtin_functions/DivideFunction.cpp b/src/bytecode/builtin_functions/DivideFunction.cpp index aba3231..0385ae5 100644 --- a/src/bytecode/builtin_functions/DivideFunction.cpp +++ b/src/bytecode/builtin_functions/DivideFunction.cpp @@ -23,6 +23,30 @@ namespace Bytecode::BuiltinFunctions { instructions.push_back(new (Instruction){Instruction::Divide}); return; } + if (args[0]->type == SyntaxTreeNode::TokenNode && + args[1]->type == SyntaxTreeNode::TokenNode && + segment->find_variable(((TokenNode *) args[0])->getName()) != -1) { + if (((TokenNode *) args[0])->token.type == Token::Symbol && + ((TokenNode *) args[1])->token.type == Token::Number) { + instructions.push_back(new (Instruction){ + Instruction::DivideRI, + {.ri_params = { + segment->find_variable(((TokenNode *) args[0])->getName()), + StackObject(((TokenNode *) args[1])->token)}}, + }); + return; + } + if (((TokenNode *) args[0])->token.type == Token::Symbol && + ((TokenNode *) args[1])->token.type == Token::Symbol) { + instructions.push_back(new (Instruction){ + Instruction::DivideRR, + {.rr_params = { + segment->find_variable(((TokenNode *) args[0])->getName()), + segment->find_variable(((TokenNode *) args[1])->getName())}}, + }); + return; + } + } args[0]->compile(segment, program, instructions); args[1]->compile(segment, program, instructions); instructions.push_back(new (Instruction){Instruction::Divide}); diff --git a/src/bytecode/compiler/Instruction.h b/src/bytecode/compiler/Instruction.h index 852f9d9..eb22379 100644 --- a/src/bytecode/compiler/Instruction.h +++ b/src/bytecode/compiler/Instruction.h @@ -20,6 +20,8 @@ namespace Bytecode { MultiplyRI, MultiplyRR, Divide, + DivideRI, + DivideRR, Increment, Decrement, DecrementR, diff --git a/src/bytecode/vm/Interpreter.cpp b/src/bytecode/vm/Interpreter.cpp index 815610c..89f79de 100644 --- a/src/bytecode/vm/Interpreter.cpp +++ b/src/bytecode/vm/Interpreter.cpp @@ -132,6 +132,29 @@ void Bytecode::Interpreter::execute(const Program &program) { } vm.program_stack.push(object1.data.number / object2.data.number); } break; + case Instruction::DivideRI: { + const auto object2 = currentInstruction->params.ri_params.intermediate; + const auto object1 = vm.call_stack.getLocal(currentInstruction->params.ri_params.reg); + if (object1.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"/\", Expected number, got string"); + } + if (object2.data.number == 0) { + throw SyntaxError("Division by zero", 0, 0); + } + vm.program_stack.push(object1.data.number / object2.data.number); + } break; + case Instruction::DivideRR: { + const auto object1 = vm.call_stack.getLocal(currentInstruction->params.rr_params.reg1); + const auto object2 = vm.call_stack.getLocal(currentInstruction->params.rr_params.reg2); + if (object1.type != ObjectType::Number || + object2.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"/\", Expected number, got string"); + } + if (object2.data.number == 0) { + throw SyntaxError("Division by zero", 0, 0); + } + vm.program_stack.push(object1.data.number / object2.data.number); + } break; case Instruction::Equals: { const auto object2 = vm.program_stack.pop(); const auto object1 = vm.program_stack.pop(); diff --git a/src/utils/dump_bytecode.cpp b/src/utils/dump_bytecode.cpp index e15895b..897f3bd 100644 --- a/src/utils/dump_bytecode.cpp +++ b/src/utils/dump_bytecode.cpp @@ -47,6 +47,12 @@ void print_instruction(const Bytecode::Instruction &instruction) { case Bytecode::Instruction::Divide: std::cout << "Divide\n"; break; + case Bytecode::Instruction::DivideRI: + std::cout << "DivideRI $r" << instruction.params.ri_params.reg << " " << instruction.params.ri_params.intermediate.toString() << '\n'; + break; + case Bytecode::Instruction::DivideRR: + std::cout << "DivideRR $r" << instruction.params.rr_params.reg1 << " $r" << instruction.params.rr_params.reg2 << '\n'; + break; case Bytecode::Instruction::Increment: std::cout << "Increment\n"; break;