From 6520d3694e1e3d67e8d867c9c6814a39d5bae15e Mon Sep 17 00:00:00 2001 From: Ibrahim KAIKAA Date: Mon, 22 Apr 2024 18:09:27 +0100 Subject: [PATCH] refactor: huge code refactor --- .../builtin_functions/AddFunction.cpp | 43 ++-- .../builtin_functions/AndFunction.cpp | 5 +- .../builtin_functions/DefineFunction.cpp | 6 +- .../builtin_functions/DivideFunction.cpp | 16 +- .../builtin_functions/EqualsFunction.cpp | 25 +- .../builtin_functions/GreaterThanFunction.cpp | 22 +- src/bytecode/builtin_functions/IfFunction.cpp | 17 +- .../builtin_functions/LessThanFunction.cpp | 26 +- .../builtin_functions/MultiplyFunction.cpp | 26 +- .../builtin_functions/NotFunction.cpp | 3 +- src/bytecode/builtin_functions/OrFunction.cpp | 5 +- .../builtin_functions/PrintFunction.cpp | 11 +- .../builtin_functions/ReadFunction.cpp | 3 +- .../builtin_functions/SubtractFunction.cpp | 36 +-- src/bytecode/compiler/Optimizer.cpp | 15 +- src/bytecode/instructions/Add.h | 21 -- src/bytecode/instructions/AddRI.h | 26 -- src/bytecode/instructions/AddRR.h | 27 -- src/bytecode/instructions/And.h | 23 -- src/bytecode/instructions/Call.h | 22 -- src/bytecode/instructions/CallLambda.h | 23 -- src/bytecode/instructions/CondJumpIfNot.h | 21 -- src/bytecode/instructions/Decrement.h | 12 - src/bytecode/instructions/DecrementR.h | 23 -- src/bytecode/instructions/Divide.h | 24 -- src/bytecode/instructions/Equals.h | 21 -- src/bytecode/instructions/EqualsRI.h | 26 -- src/bytecode/instructions/GreaterThan.h | 21 -- src/bytecode/instructions/GreaterThanRI.h | 25 -- src/bytecode/instructions/Increment.h | 12 - src/bytecode/instructions/Instruction.h | 44 ++-- src/bytecode/instructions/Jump.h | 18 -- src/bytecode/instructions/LessThan.h | 21 -- src/bytecode/instructions/LessThanRI.h | 24 -- src/bytecode/instructions/LoadGlobal.h | 19 -- src/bytecode/instructions/LoadLiteral.h | 37 --- src/bytecode/instructions/LoadLocal.h | 19 -- src/bytecode/instructions/Multiply.h | 21 -- src/bytecode/instructions/MultiplyRI.h | 26 -- src/bytecode/instructions/Not.h | 18 -- src/bytecode/instructions/Or.h | 23 -- src/bytecode/instructions/ReadFromStdin.h | 22 -- src/bytecode/instructions/Return.h | 14 -- src/bytecode/instructions/SendToStdout.h | 15 -- src/bytecode/instructions/StoreGlobal.h | 20 -- src/bytecode/instructions/StoreLocal.h | 20 -- src/bytecode/instructions/Subtract.h | 21 -- src/bytecode/instructions/SubtractRI.h | 25 -- src/bytecode/vm/Interpreter.cpp | 238 +++++++++++++++++- src/lexer/Token.cpp | 4 - src/lexer/Token.h | 1 - src/main.cpp | 17 +- src/parser/SyntaxTreeNode.cpp | 91 ++++--- 53 files changed, 454 insertions(+), 890 deletions(-) delete mode 100644 src/bytecode/instructions/Add.h delete mode 100644 src/bytecode/instructions/AddRI.h delete mode 100644 src/bytecode/instructions/AddRR.h delete mode 100644 src/bytecode/instructions/And.h delete mode 100644 src/bytecode/instructions/Call.h delete mode 100644 src/bytecode/instructions/CallLambda.h delete mode 100644 src/bytecode/instructions/CondJumpIfNot.h delete mode 100644 src/bytecode/instructions/Decrement.h delete mode 100644 src/bytecode/instructions/DecrementR.h delete mode 100644 src/bytecode/instructions/Divide.h delete mode 100644 src/bytecode/instructions/Equals.h delete mode 100644 src/bytecode/instructions/EqualsRI.h delete mode 100644 src/bytecode/instructions/GreaterThan.h delete mode 100644 src/bytecode/instructions/GreaterThanRI.h delete mode 100644 src/bytecode/instructions/Increment.h delete mode 100644 src/bytecode/instructions/Jump.h delete mode 100644 src/bytecode/instructions/LessThan.h delete mode 100644 src/bytecode/instructions/LessThanRI.h delete mode 100644 src/bytecode/instructions/LoadGlobal.h delete mode 100644 src/bytecode/instructions/LoadLiteral.h delete mode 100644 src/bytecode/instructions/LoadLocal.h delete mode 100644 src/bytecode/instructions/Multiply.h delete mode 100644 src/bytecode/instructions/MultiplyRI.h delete mode 100644 src/bytecode/instructions/Not.h delete mode 100644 src/bytecode/instructions/Or.h delete mode 100644 src/bytecode/instructions/ReadFromStdin.h delete mode 100644 src/bytecode/instructions/Return.h delete mode 100644 src/bytecode/instructions/SendToStdout.h delete mode 100644 src/bytecode/instructions/StoreGlobal.h delete mode 100644 src/bytecode/instructions/StoreLocal.h delete mode 100644 src/bytecode/instructions/Subtract.h delete mode 100644 src/bytecode/instructions/SubtractRI.h diff --git a/src/bytecode/builtin_functions/AddFunction.cpp b/src/bytecode/builtin_functions/AddFunction.cpp index 403c926..d54208f 100644 --- a/src/bytecode/builtin_functions/AddFunction.cpp +++ b/src/bytecode/builtin_functions/AddFunction.cpp @@ -1,9 +1,5 @@ #include "AddFunction.h" -#include "bytecode/instructions/Add.h" -#include "bytecode/instructions/AddRI.h" -#include "bytecode/instructions/AddRR.h" -#include "bytecode/instructions/Increment.h" #include "exceptions/SyntaxError.h" namespace Bytecode::BuiltinFunctions { @@ -25,14 +21,14 @@ namespace Bytecode::BuiltinFunctions { if (args[1]->type == SyntaxTreeNode::TokenNode && ((TokenNode *) args[1])->getName() == "1") { args[0]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Increment()); + instructions.push_back(new (Instruction){Instruction::Increment}); return; } if (args[0]->type == SyntaxTreeNode::TokenNode && ((TokenNode *) args[0])->getName() == "1") { args[1]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Increment()); + instructions.push_back(new (Instruction){Instruction::Increment}); return; } @@ -41,40 +37,47 @@ namespace Bytecode::BuiltinFunctions { if (((TokenNode *) args[0])->token.type == Token::Symbol && ((TokenNode *) args[1])->token.type == Token::Number && segment->find_variable(((TokenNode *) args[0])->getName()) != -1) { - instructions.push_back( - new Bytecode::AddRI( - segment->find_variable(((TokenNode *) args[0])->getName()), - ((TokenNode *) args[1])->token.asNumber())); + instructions.push_back(new (Instruction){ + Instruction::AddRI, + {.ri_params = { + segment->find_variable(((TokenNode *) args[0])->getName()), + StackObject(((TokenNode *) args[1])->token)}}, + }); return; } if (((TokenNode *) args[0])->token.type == Token::Number && ((TokenNode *) args[1])->token.type == Token::Symbol && segment->find_variable(((TokenNode *) args[1])->getName()) != -1) { - instructions.push_back( - new Bytecode::AddRI( - segment->find_variable(((TokenNode *) args[1])->getName()), - ((TokenNode *) args[0])->token.asNumber())); + instructions.push_back(new (Instruction){ + Instruction::AddRI, + {.ri_params = { + segment->find_variable(((TokenNode *) args[1])->getName()), + StackObject(((TokenNode *) args[0])->token)}}, + }); return; } if (((TokenNode *) args[0])->token.type == Token::Symbol && ((TokenNode *) args[1])->token.type == Token::Symbol && segment->find_variable(((TokenNode *) args[0])->getName()) != -1 && segment->find_variable(((TokenNode *) args[1])->getName()) != -1) { - instructions.push_back( - new Bytecode::AddRR( - segment->find_variable(((TokenNode *) args[0])->getName()), - segment->find_variable(((TokenNode *) args[1])->getName()))); + instructions.push_back(new (Instruction){ + Instruction::AddRR, + {.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 Bytecode::Add()); + instructions.push_back(new (Instruction){Instruction::Add}); for (int i = 2; i < args.size(); i++) { args[i]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Add()); + instructions.push_back(new (Instruction){Instruction::Add}); } } }// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/AndFunction.cpp b/src/bytecode/builtin_functions/AndFunction.cpp index 76a9d95..0b27368 100644 --- a/src/bytecode/builtin_functions/AndFunction.cpp +++ b/src/bytecode/builtin_functions/AndFunction.cpp @@ -1,5 +1,4 @@ #include "AndFunction.h" -#include "bytecode/instructions/And.h" #include "exceptions/SyntaxError.h" namespace Bytecode::BuiltinFunctions { @@ -12,10 +11,10 @@ namespace Bytecode::BuiltinFunctions { args[0]->compile(segment, program, instructions); if (args.size() == 1) return; args[1]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::And()); + instructions.push_back(new (Instruction){Instruction::And}); for (int i = 2; i < args.size(); i++) { args[i]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::And()); + instructions.push_back(new (Instruction){Instruction::And}); } } }// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/DefineFunction.cpp b/src/bytecode/builtin_functions/DefineFunction.cpp index a572790..596006e 100644 --- a/src/bytecode/builtin_functions/DefineFunction.cpp +++ b/src/bytecode/builtin_functions/DefineFunction.cpp @@ -1,6 +1,4 @@ #include "DefineFunction.h" -#include "bytecode/instructions/Return.h" -#include "bytecode/instructions/StoreGlobal.h" namespace Bytecode::BuiltinFunctions { void Define::compile( @@ -19,14 +17,14 @@ namespace Bytecode::BuiltinFunctions { return; } args[1]->compile(result, program, instructions); - instructions.push_back(new StoreGlobal(reg)); + instructions.push_back(new (Instruction){Instruction::StoreGlobal, {.r_param = {reg}}}); } else if (args[0]->type == SyntaxTreeNode::Expression) { auto segment = new Segment({}); program.declare_function(((Expression *) args[0])->getName(), segment); for (auto argument: ((Expression *) args[0])->getArgs()) segment->declare_variable(((TokenNode *) argument)->getName()); args[1]->compile(segment, program, segment->instructions); - segment->instructions.push_back(new Bytecode::Return()); + segment->instructions.push_back(new (Instruction){Instruction::Return}); } } }// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/DivideFunction.cpp b/src/bytecode/builtin_functions/DivideFunction.cpp index 4133ca2..aba3231 100644 --- a/src/bytecode/builtin_functions/DivideFunction.cpp +++ b/src/bytecode/builtin_functions/DivideFunction.cpp @@ -1,7 +1,5 @@ #include "DivideFunction.h" -#include "bytecode/instructions/Divide.h" -#include "bytecode/instructions/LoadLiteral.h" #include "exceptions/SyntaxError.h" namespace Bytecode::BuiltinFunctions { @@ -16,17 +14,21 @@ namespace Bytecode::BuiltinFunctions { 0, 0); if (args.size() == 1) { - instructions.push_back(new LoadLiteral((double) 1)); - args[0]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Divide()); + instructions.push_back(new (Instruction){ + Instruction::LoadLiteral, + {.i_param = {StackObject((double) 1)}}, + }); + args[0] + ->compile(segment, program, instructions); + instructions.push_back(new (Instruction){Instruction::Divide}); return; } args[0]->compile(segment, program, instructions); args[1]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Divide()); + instructions.push_back(new (Instruction){Instruction::Divide}); for (int i = 2; i < args.size(); i++) { args[i]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Divide()); + instructions.push_back(new (Instruction){Instruction::Divide}); } } }// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/EqualsFunction.cpp b/src/bytecode/builtin_functions/EqualsFunction.cpp index da33786..356078d 100644 --- a/src/bytecode/builtin_functions/EqualsFunction.cpp +++ b/src/bytecode/builtin_functions/EqualsFunction.cpp @@ -1,11 +1,7 @@ #include "EqualsFunction.h" -#include "bytecode/instructions/Equals.h" -#include "bytecode/instructions/EqualsRI.h" -#include "bytecode/instructions/LoadLiteral.h" #include "exceptions/SyntaxError.h" namespace Bytecode::BuiltinFunctions { - void Equals::compile( const std::vector &args, Program &program, @@ -15,7 +11,10 @@ namespace Bytecode::BuiltinFunctions { throw SyntaxError("Invalid number of arguments for function \"=\", Expected at least 1, got 0"); } if (args.size() == 1) { - instructions.push_back(new LoadLiteral(new StackObject(true))); + instructions.push_back(new (Instruction){ + Instruction::LoadLiteral, + {.i_param = {StackObject(true)}}, + }); return; } if (args[0]->type == SyntaxTreeNode::TokenNode && @@ -23,20 +22,22 @@ namespace Bytecode::BuiltinFunctions { 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 Bytecode::EqualsRI( - segment->find_variable(((TokenNode *) args[0])->getName()), - ((TokenNode *) args[1])->token.asNumber())); + instructions.push_back(new (Instruction){ + Instruction::EqualsRI, + {.ri_params = { + segment->find_variable(((TokenNode *) args[0])->getName()), + StackObject(((TokenNode *) args[1])->token), + }}}); return; } } args[0]->compile(segment, program, instructions); args[1]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Equals()); + instructions.push_back(new (Instruction){Instruction::Equals}); for (int i = 2; i < args.size(); i++) { args[i]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Equals()); + instructions.push_back(new (Instruction){Instruction::Equals}); } } -} \ No newline at end of file +}// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/GreaterThanFunction.cpp b/src/bytecode/builtin_functions/GreaterThanFunction.cpp index 3076dea..6c28fe7 100644 --- a/src/bytecode/builtin_functions/GreaterThanFunction.cpp +++ b/src/bytecode/builtin_functions/GreaterThanFunction.cpp @@ -1,7 +1,4 @@ #include "GreaterThanFunction.h" -#include "bytecode/instructions/GreaterThan.h" -#include "bytecode/instructions/GreaterThanRI.h" -#include "bytecode/instructions/LoadLiteral.h" #include "exceptions/SyntaxError.h" namespace Bytecode::BuiltinFunctions { @@ -14,7 +11,10 @@ namespace Bytecode::BuiltinFunctions { throw SyntaxError("Invalid number of arguments for function \">\", Expected at least 1, got 0"); } if (args.size() == 1) { - instructions.push_back(new LoadLiteral(new StackObject(true))); + instructions.push_back(new (Instruction){ + Instruction::LoadLiteral, + {.i_param = {StackObject(true)}}, + }); return; } if (args[0]->type == SyntaxTreeNode::TokenNode && @@ -22,20 +22,22 @@ namespace Bytecode::BuiltinFunctions { 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 Bytecode::GreaterThanRI( - segment->find_variable(((TokenNode *) args[0])->getName()), - ((TokenNode *) args[1])->token.asNumber())); + instructions.push_back(new (Instruction){ + Instruction::GreaterThanRI, + {.ri_params = { + segment->find_variable(((TokenNode *) args[0])->getName()), + StackObject(((TokenNode *) args[1])->token)}}, + }); return; } } args[0]->compile(segment, program, instructions); args[1]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::GreaterThan()); + instructions.push_back(new (Instruction){Instruction::GreaterThan}); for (int i = 2; i < args.size(); i++) { args[i]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::GreaterThan()); + instructions.push_back(new (Instruction){Instruction::GreaterThan}); } } }// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/IfFunction.cpp b/src/bytecode/builtin_functions/IfFunction.cpp index 3574fe5..238d7aa 100644 --- a/src/bytecode/builtin_functions/IfFunction.cpp +++ b/src/bytecode/builtin_functions/IfFunction.cpp @@ -1,6 +1,4 @@ #include "IfFunction.h" -#include "bytecode/instructions/CondJumpIfNot.h" -#include "bytecode/instructions/Jump.h" namespace Bytecode::BuiltinFunctions { void If::compile( @@ -15,15 +13,18 @@ namespace Bytecode::BuiltinFunctions { args[1]->compile(result, program, condition_success); if (args.size() == 3) args[2]->compile(result, program, condition_failure); - - result->instructions.push_back( - new CondJumpIfNot( - result->instructions.size() + condition_success.size() + - (condition_failure.empty() ? 1 : 2))); + result->instructions.push_back(new (Instruction){ + Instruction::CondJumpIfNot, + {.r_param = {result->instructions.size() + condition_success.size() + + (condition_failure.empty() ? 1 : 2)}}, + }); for (const auto instruction: condition_success) instructions.push_back(instruction); if (!condition_failure.empty()) - instructions.push_back(new Jump(instructions.size() + condition_failure.size() + 1)); + instructions.push_back(new (Instruction) { + Instruction::Jump, + {.r_param = {instructions.size() + condition_failure.size() + 1}}, + }); for (const auto instruction: condition_failure) instructions.push_back(instruction); diff --git a/src/bytecode/builtin_functions/LessThanFunction.cpp b/src/bytecode/builtin_functions/LessThanFunction.cpp index b8ab6d4..0881a73 100644 --- a/src/bytecode/builtin_functions/LessThanFunction.cpp +++ b/src/bytecode/builtin_functions/LessThanFunction.cpp @@ -1,7 +1,4 @@ #include "LessThanFunction.h" -#include "bytecode/instructions/LessThan.h" -#include "bytecode/instructions/LessThanRI.h" -#include "bytecode/instructions/LoadLiteral.h" #include "exceptions/SyntaxError.h" namespace Bytecode::BuiltinFunctions { @@ -9,12 +6,15 @@ namespace Bytecode::BuiltinFunctions { const std::vector &args, Program &program, std::vector &instructions, - Segment *segment) { + Segment *segment) { if (args.empty()) { throw SyntaxError("Invalid number of arguments for function \"<\", Expected at least 1, got 0"); } if (args.size() == 1) { - instructions.push_back(new LoadLiteral(new StackObject(true))); + instructions.push_back(new (Instruction){ + Instruction::LoadLiteral, + {.i_param = {StackObject(true)}}, + }); return; } if (args[0]->type == SyntaxTreeNode::TokenNode && @@ -22,20 +22,22 @@ namespace Bytecode::BuiltinFunctions { 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 Bytecode::LessThanRI( - segment->find_variable(((TokenNode *) args[0])->getName()), - ((TokenNode *) args[1])->token.asNumber())); + instructions.push_back(new (Instruction){ + Instruction::LessThanRI, + {.ri_params = { + segment->find_variable(((TokenNode *) args[0])->getName()), + StackObject(((TokenNode *) args[1])->token)}}, + }); return; } } args[0]->compile(segment, program, instructions); args[1]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::LessThan()); + instructions.push_back(new (Instruction){Instruction::LessThan}); for (int i = 2; i < args.size(); i++) { args[i]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::LessThan()); + instructions.push_back(new (Instruction){Instruction::LessThan}); } } -} \ No newline at end of file +}// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/MultiplyFunction.cpp b/src/bytecode/builtin_functions/MultiplyFunction.cpp index f3cd353..3fafee9 100644 --- a/src/bytecode/builtin_functions/MultiplyFunction.cpp +++ b/src/bytecode/builtin_functions/MultiplyFunction.cpp @@ -1,6 +1,4 @@ #include "MultiplyFunction.h" -#include "bytecode/instructions/Multiply.h" -#include "bytecode/instructions/MultiplyRI.h" #include "exceptions/SyntaxError.h" namespace Bytecode::BuiltinFunctions { @@ -23,29 +21,33 @@ namespace Bytecode::BuiltinFunctions { if (((TokenNode *) args[0])->token.type == Token::Symbol && ((TokenNode *) args[1])->token.type == Token::Number && segment->find_variable(((TokenNode *) args[0])->getName()) != -1) { - instructions.push_back( - new Bytecode::MultiplyRI( - segment->find_variable(((TokenNode *) args[0])->getName()), - ((TokenNode *) args[1])->token.asNumber())); + instructions.push_back(new (Instruction){ + Instruction::MultiplyRI, + {.ri_params = { + segment->find_variable(((TokenNode *) args[0])->getName()), + StackObject(((TokenNode *) args[1])->token), + }}}); return; } if (((TokenNode *) args[0])->token.type == Token::Number && ((TokenNode *) args[1])->token.type == Token::Symbol && segment->find_variable(((TokenNode *) args[1])->getName()) != -1) { - instructions.push_back( - new Bytecode::MultiplyRI( - segment->find_variable(((TokenNode *) args[1])->getName()), - ((TokenNode *) args[0])->token.asNumber())); + instructions.push_back(new (Instruction){ + Instruction::MultiplyRI, + {.ri_params = { + segment->find_variable(((TokenNode *) args[1])->getName()), + StackObject(((TokenNode *) args[0])->token), + }}}); return; } } args[0]->compile(segment, program, instructions); args[1]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Multiply()); + instructions.push_back(new (Instruction){Instruction::Multiply}); for (int i = 2; i < args.size(); i++) { args[i]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Multiply()); + instructions.push_back(new (Instruction){Instruction::Multiply}); } } }// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/NotFunction.cpp b/src/bytecode/builtin_functions/NotFunction.cpp index 6ca0a63..b6de588 100644 --- a/src/bytecode/builtin_functions/NotFunction.cpp +++ b/src/bytecode/builtin_functions/NotFunction.cpp @@ -1,5 +1,4 @@ #include "NotFunction.h" -#include "bytecode/instructions/Not.h" #include "exceptions/SyntaxError.h" namespace Bytecode::BuiltinFunctions { @@ -12,6 +11,6 @@ namespace Bytecode::BuiltinFunctions { + std::to_string(args.size())); } args[0]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Not()); + instructions.push_back(new (Instruction){Instruction::Not}); } }// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/OrFunction.cpp b/src/bytecode/builtin_functions/OrFunction.cpp index b63d19a..d6c2c3f 100644 --- a/src/bytecode/builtin_functions/OrFunction.cpp +++ b/src/bytecode/builtin_functions/OrFunction.cpp @@ -1,5 +1,4 @@ #include "OrFunction.h" -#include "bytecode/instructions/Or.h" #include "exceptions/SyntaxError.h" namespace Bytecode::BuiltinFunctions { @@ -13,10 +12,10 @@ namespace Bytecode::BuiltinFunctions { args[0]->compile(segment, program, instructions); if (args.size() == 1) return; args[1]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Or()); + instructions.push_back(new (Instruction){Instruction::Or}); for (int i = 2; i < args.size(); i++) { args[i]->compile(segment, program, instructions); - instructions.push_back(new Bytecode::Or()); + instructions.push_back(new (Instruction){Instruction::Or}); } } }// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/PrintFunction.cpp b/src/bytecode/builtin_functions/PrintFunction.cpp index 6b41146..63e0be2 100644 --- a/src/bytecode/builtin_functions/PrintFunction.cpp +++ b/src/bytecode/builtin_functions/PrintFunction.cpp @@ -1,6 +1,4 @@ #include "PrintFunction.h" -#include "bytecode/instructions/LoadLiteral.h" -#include "bytecode/instructions/SendToStdout.h" namespace Bytecode::BuiltinFunctions { void Print::compile( @@ -10,9 +8,12 @@ namespace Bytecode::BuiltinFunctions { Segment *segment) { for (const auto arg: args) { arg->compile(segment, program, instructions); - instructions.push_back(new SendToStdout()); + instructions.push_back(new (Instruction){Instruction::SendToStdout}); } - instructions.push_back(new LoadLiteral("\n")); - instructions.push_back(new SendToStdout()); + instructions.push_back(new (Instruction){ + Instruction::LoadLiteral, + {.i_param = {StackObject(std::string("\n"))}}, + }); + instructions.push_back(new (Instruction){Instruction::SendToStdout}); }; }// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/ReadFunction.cpp b/src/bytecode/builtin_functions/ReadFunction.cpp index f9669ea..3a974ee 100644 --- a/src/bytecode/builtin_functions/ReadFunction.cpp +++ b/src/bytecode/builtin_functions/ReadFunction.cpp @@ -1,5 +1,4 @@ #include "ReadFunction.h" -#include "bytecode/instructions/ReadFromStdin.h" #include "exceptions/SyntaxError.h" namespace Bytecode::BuiltinFunctions { @@ -13,6 +12,6 @@ namespace Bytecode::BuiltinFunctions { "Invalid number of arguments for function \"read\", Expected 0, got " + std::to_string(args.size())); } - instructions.push_back(new ReadFromStdin()); + instructions.push_back(new (Instruction){Instruction::ReadFromStdin}); }; }// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/builtin_functions/SubtractFunction.cpp b/src/bytecode/builtin_functions/SubtractFunction.cpp index 4f54068..18f0b26 100644 --- a/src/bytecode/builtin_functions/SubtractFunction.cpp +++ b/src/bytecode/builtin_functions/SubtractFunction.cpp @@ -1,10 +1,4 @@ #include "SubtractFunction.h" -#include "bytecode/instructions/AddRI.h" -#include "bytecode/instructions/Decrement.h" -#include "bytecode/instructions/DecrementR.h" -#include "bytecode/instructions/LoadLiteral.h" -#include "bytecode/instructions/Subtract.h" -#include "bytecode/instructions/SubtractRI.h" #include "exceptions/SyntaxError.h" namespace Bytecode::BuiltinFunctions { @@ -18,9 +12,12 @@ namespace Bytecode::BuiltinFunctions { 0, 0); } else if (args.size() == 1) { - instructions.push_back(new LoadLiteral((double) 0)); + instructions.push_back(new (Instruction){ + Instruction::LoadLiteral, + {.i_param = {StackObject((double) 0)}}, + }); args[0]->compile(result, program, instructions); - instructions.push_back(new Bytecode::Subtract()); + instructions.push_back(new (Instruction){Instruction::Subtract}); return; } @@ -28,18 +25,21 @@ namespace Bytecode::BuiltinFunctions { ((TokenNode *) args[1])->getName() == "1") { if (args[0]->type == SyntaxTreeNode::TokenNode && result->find_variable(((TokenNode *) args[0])->getName()) != -1) { - instructions.push_back(new Bytecode::DecrementR(result->find_variable(((TokenNode *) args[0])->getName()))); + instructions.push_back(new (Instruction){ + Instruction::DecrementR, + {.r_param = {result->find_variable(((TokenNode *) args[0])->getName())}}, + }); return; } args[0]->compile(result, program, instructions); - instructions.push_back(new Bytecode::Decrement()); + instructions.push_back(new (Instruction){Instruction::Decrement}); return; } if (args[0]->type == SyntaxTreeNode::TokenNode && ((TokenNode *) args[0])->getName() == "1") { args[1]->compile(result, program, instructions); - instructions.push_back(new Bytecode::Decrement()); + instructions.push_back(new (Instruction){Instruction::Decrement}); return; } @@ -49,20 +49,22 @@ namespace Bytecode::BuiltinFunctions { result->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 Bytecode::SubtractRI( - result->find_variable(((TokenNode *) args[0])->getName()), - ((TokenNode *) args[1])->token.asNumber())); + instructions.push_back(new (Instruction){ + Instruction::SubtractRI, + {.ri_params = { + result->find_variable(((TokenNode *) args[0])->getName()), + StackObject(((TokenNode *) args[1])->token)}}, + }); return; } } args[0]->compile(result, program, instructions); args[1]->compile(result, program, instructions); - instructions.push_back(new Bytecode::Subtract()); + instructions.push_back(new (Instruction){Instruction::Subtract}); for (int i = 2; i < args.size(); i++) { args[i]->compile(result, program, instructions); - instructions.push_back(new Bytecode::Subtract()); + instructions.push_back(new (Instruction){Instruction::Subtract}); } } }// namespace Bytecode::BuiltinFunctions \ No newline at end of file diff --git a/src/bytecode/compiler/Optimizer.cpp b/src/bytecode/compiler/Optimizer.cpp index 07709b4..4fa514b 100644 --- a/src/bytecode/compiler/Optimizer.cpp +++ b/src/bytecode/compiler/Optimizer.cpp @@ -1,7 +1,4 @@ #include "Optimizer.h" -#include "bytecode/instructions/Jump.h" -#include "bytecode/instructions/Return.h" -#include "bytecode/instructions/StoreLocal.h" bool Bytecode::Optimizer::is_tail_recursive(const Bytecode::Segment &segment, size_t id) { const auto &instructions = segment.instructions; @@ -18,9 +15,15 @@ void Bytecode::Optimizer::optimize_tail_calls(Segment &segment) { instructions.pop_back();// Remove the Return instruction instructions.pop_back();// Remove the Call instruction for (size_t i = number_of_args - 1; i != -1; i--) - instructions.push_back(new Bytecode::StoreLocal(i)); - instructions.push_back(new Bytecode::Jump(0)); - instructions.push_back(new Bytecode::Return()); + instructions.push_back(new (Instruction) { + Instruction::StoreGlobal, + {.r_param = {i}}, + }); + instructions.push_back(new (Instruction){ + Instruction::Jump, + {.r_param = {1}}, + }); + instructions.push_back(new (Instruction){Instruction::Return}); // Update jump locations for (auto &instruction: instructions) { diff --git a/src/bytecode/instructions/Add.h b/src/bytecode/instructions/Add.h deleted file mode 100644 index 857b448..0000000 --- a/src/bytecode/instructions/Add.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "bytecode/instructions/Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class Add final : public Instruction { - public: - Add() { type = InstructionType::Add; } - void execute(Bytecode::VM &vm) override { - const auto object2 = vm.program_stack.pop(); - const auto object1 = vm.program_stack.pop(); - if (object1.type != ObjectType::Number || - object2.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"+\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number + object2.data.number); - } - [[nodiscard]] std::string toString() const override { return "Add"; } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/AddRI.h b/src/bytecode/instructions/AddRI.h deleted file mode 100644 index 680f69a..0000000 --- a/src/bytecode/instructions/AddRI.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class AddRI final : public Instruction { - public: - AddRI(size_t rg, double number) { - type = InstructionType::AddRI; - params = {rg, StackObject(number)}; - } - void execute(Bytecode::VM &vm) override { - const auto object1 = params.ri_params.intermediate; - const auto object2 = vm.call_stack.getLocal(params.ri_params.reg); - if (object2.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"+\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number + object2.data.number); - } - [[nodiscard]] std::string toString() const override { - return "AddRI $r" + std::to_string(params.ri_params.reg) + - ", " + params.ri_params.intermediate.toString(); - } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/AddRR.h b/src/bytecode/instructions/AddRR.h deleted file mode 100644 index 9cb24e4..0000000 --- a/src/bytecode/instructions/AddRR.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class AddRR final : public Instruction { - public: - AddRR(size_t reg1, size_t reg2) { - type = InstructionType::AddRR; - params.rr_params = {reg1, reg2}; - } - void execute(Bytecode::VM &vm) override { - const auto object1 = vm.call_stack.getLocal(params.rr_params.reg1); - const auto object2 = vm.call_stack.getLocal(params.rr_params.reg2); - if (object1.type != ObjectType::Number || - object2.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"+\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number + object2.data.number); - } - [[nodiscard]] std::string toString() const override { - return "AddRR $r" + std::to_string(params.rr_params.reg1) + - ", $r" + std::to_string(params.rr_params.reg2); - } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/And.h b/src/bytecode/instructions/And.h deleted file mode 100644 index 93b6e86..0000000 --- a/src/bytecode/instructions/And.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class And final : public Instruction { - public: - And() {type = InstructionType::And;} - void execute(Bytecode::VM &vm) override { - const auto object2 = vm.program_stack.pop(); - const auto object1 = vm.program_stack.pop(); - if (object1.type != ObjectType::Boolean || - object2.type != ObjectType::Boolean) { - throw SyntaxError("Invalid argument type for function \"and\", Expected boolean, got string"); - } - vm.program_stack.push(object1.data.boolean && object2.data.boolean); - } - [[nodiscard]] std::string toString() const override { - return "And"; - } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/Call.h b/src/bytecode/instructions/Call.h deleted file mode 100644 index ee723e8..0000000 --- a/src/bytecode/instructions/Call.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "Instruction.h" -namespace Bytecode { - class Call final : public Instruction { - public: - explicit Call(const size_t segment, const size_t args) { - params.ri_params = {.reg = segment, .intermediate = StackObject(args)}; - type = InstructionType::Call; - } - void execute(Bytecode::VM &vm) override { - vm.call_stack.newStackFrame( - params.ri_params.reg, - params.ri_params.intermediate.data.reg, - &vm.program_stack); - } - [[nodiscard]] std::string toString() const override { - return "Call :" + std::to_string(params.ri_params.reg) + - ", " + params.ri_params.intermediate.toString(); - } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/CallLambda.h b/src/bytecode/instructions/CallLambda.h deleted file mode 100644 index 84b3451..0000000 --- a/src/bytecode/instructions/CallLambda.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "Instruction.h" - -namespace Bytecode { - class CallLambda final : public Instruction { - public: - explicit CallLambda(const size_t args) { - params.r_param = {args}; - type = InstructionType::CallLambda; - } - void execute(Bytecode::VM &vm) override { - const auto lambda = vm.program_stack.pop(); - vm.call_stack.newStackFrame( - lambda.data.reg, - params.r_param.reg, - &vm.program_stack); - } - [[nodiscard]] std::string toString() const override { - return "CallLambda " + std::to_string(params.r_param.reg); - } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/CondJumpIfNot.h b/src/bytecode/instructions/CondJumpIfNot.h deleted file mode 100644 index 90012c2..0000000 --- a/src/bytecode/instructions/CondJumpIfNot.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "Instruction.h" - -namespace Bytecode { - class CondJumpIfNot final : public Instruction { - public: - explicit CondJumpIfNot(const size_t line) { - params.r_param = {line}; - type = InstructionType::CondJumpIfNot; - } - void execute(Bytecode::VM &vm) override { - if (const auto cond = vm.program_stack.pop(); - !cond.data.boolean) - vm.call_stack.stackTop->current_line = params.r_param.reg - 1; - } - [[nodiscard]] std::string toString() const override { - return "CondJumpIfNot " + std::to_string(params.r_param.reg); - } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/Decrement.h b/src/bytecode/instructions/Decrement.h deleted file mode 100644 index 400be78..0000000 --- a/src/bytecode/instructions/Decrement.h +++ /dev/null @@ -1,12 +0,0 @@ -#include "Instruction.h" - -namespace Bytecode { - class Decrement final : public Instruction { - public: - Decrement() { type = InstructionType::Decrement; }; - void execute(Bytecode::VM &vm) override { - vm.program_stack.push(vm.program_stack.pop().data.number - 1); - } - [[nodiscard]] std::string toString() const override { return "Decrement"; } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/DecrementR.h b/src/bytecode/instructions/DecrementR.h deleted file mode 100644 index f3dfb12..0000000 --- a/src/bytecode/instructions/DecrementR.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "Instruction.h" - -namespace Bytecode { - class DecrementR final : public Instruction { - public: - explicit DecrementR(size_t reg) { - params.r_param = {reg}; - type = InstructionType::DecrementR; - } - void execute(Bytecode::VM &vm) override { - const auto number = vm.call_stack.getLocal(params.r_param.reg); - if (number.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"-\", Expected number, got string"); - } - vm.program_stack.push(number.data.number - 1); - } - [[nodiscard]] std::string toString() const override { - return "DecrementR $r" + std::to_string(params.r_param.reg); - } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/Divide.h b/src/bytecode/instructions/Divide.h deleted file mode 100644 index 50ae0a0..0000000 --- a/src/bytecode/instructions/Divide.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "bytecode/instructions/Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class Divide final : public Instruction { - public: - Divide() { type = InstructionType::Divide; }; - void execute(Bytecode::VM &vm) override { - const auto object2 = vm.program_stack.pop(); - const auto object1 = vm.program_stack.pop(); - 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); - } - [[nodiscard]] std::string toString() const override { return "Divide"; } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/Equals.h b/src/bytecode/instructions/Equals.h deleted file mode 100644 index 9f6f007..0000000 --- a/src/bytecode/instructions/Equals.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "bytecode/instructions/Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class Equals final : public Instruction { - public: - Equals() { type = InstructionType::Equals; }; - void execute(Bytecode::VM &vm) override { - const auto object2 = vm.program_stack.pop(); - const auto object1 = vm.program_stack.pop(); - if (object1.type != ObjectType::Number || - object2.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"=\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number == object2.data.number); - } - [[nodiscard]] std::string toString() const override { return "Equals"; } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/EqualsRI.h b/src/bytecode/instructions/EqualsRI.h deleted file mode 100644 index 901012e..0000000 --- a/src/bytecode/instructions/EqualsRI.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class EqualsRI final : public Instruction { - public: - EqualsRI(size_t rg, double number) { - type = InstructionType::EqualsRI; - params = {rg, StackObject(number)}; - } - void execute(Bytecode::VM &vm) override { - const auto object1 = params.ri_params.intermediate; - const auto object2 = vm.call_stack.getLocal(params.ri_params.reg); - if (object2.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"=\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number == object2.data.number); - } - [[nodiscard]] std::string toString() const override { - return "EqualsRI $r" + std::to_string(params.ri_params.reg) + - ", " + params.ri_params.intermediate.toString(); - } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/GreaterThan.h b/src/bytecode/instructions/GreaterThan.h deleted file mode 100644 index a82b283..0000000 --- a/src/bytecode/instructions/GreaterThan.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "bytecode/instructions/Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class GreaterThan final : public Instruction { - public: - GreaterThan() { type = InstructionType::GreaterThan; }; - void execute(Bytecode::VM &vm) override { - const auto object2 = vm.program_stack.pop(); - const auto object1 = vm.program_stack.pop(); - if (object1.type != ObjectType::Number || - object2.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \">\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number > object2.data.number); - } - [[nodiscard]] std::string toString() const override { return "GreaterThan"; } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/GreaterThanRI.h b/src/bytecode/instructions/GreaterThanRI.h deleted file mode 100644 index 39b980b..0000000 --- a/src/bytecode/instructions/GreaterThanRI.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "Instruction.h" -#include "exceptions/SyntaxError.h" -namespace Bytecode { - class GreaterThanRI final : public Instruction { - public: - GreaterThanRI(size_t rg, double number) { - params.ri_params = {.reg = rg, .intermediate = StackObject(number)}; - type = InstructionType::GreaterThanRI; - } - void execute(Bytecode::VM &vm) override { - const auto object2 = params.ri_params.intermediate; - const auto object1 = vm.call_stack.getLocal(params.ri_params.reg); - if (object1.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \">\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number > object2.data.number); - } - [[nodiscard]] std::string toString() const override { - return "GreaterThanRI $r" + std::to_string(params.ri_params.reg) + - ", " + params.ri_params.intermediate.toString(); - } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/Increment.h b/src/bytecode/instructions/Increment.h deleted file mode 100644 index 393e420..0000000 --- a/src/bytecode/instructions/Increment.h +++ /dev/null @@ -1,12 +0,0 @@ -#include "Instruction.h" - -namespace Bytecode { - class Increment final : public Instruction { - public: - Increment() { type = InstructionType::Increment; }; - void execute(Bytecode::VM &vm) override { - vm.program_stack.push(vm.program_stack.pop().data.number + 1); - } - [[nodiscard]] std::string toString() const override { return "Increment"; } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/Instruction.h b/src/bytecode/instructions/Instruction.h index 71bf175..852f9d9 100644 --- a/src/bytecode/instructions/Instruction.h +++ b/src/bytecode/instructions/Instruction.h @@ -6,18 +6,30 @@ namespace Bytecode { struct Instruction { enum InstructionType : uint8_t { - Unknown, + Invalid, LoadLiteral, - LoadLocal, LoadGlobal, + LoadLocal, Add, + AddRI, + AddRR, Subtract, - Divide, + SubtractRI, + SubtractRR, Multiply, - Not, + MultiplyRI, + MultiplyRR, + Divide, + Increment, + Decrement, + DecrementR, Equals, - GreaterThan, + EqualsRI, LessThan, + LessThanRI, + GreaterThan, + GreaterThanRI, + Not, Call, CallLambda, CondJumpIfNot, @@ -28,20 +40,10 @@ namespace Bytecode { Or, And, Return, - Increment, - Decrement, - AddRI, - SubtractRI, - LessThanRI, - DecrementR, - EqualsRI, - GreaterThanRI, - MultiplyRI, - AddRR, StoreLocal, - } type; - union params { - struct RI_Params { + } type = Invalid; + union { + struct RI_PARAMS { size_t reg; StackObject intermediate; } ri_params; @@ -52,14 +54,10 @@ namespace Bytecode { struct R_Param { size_t reg; } r_param; - struct I_param { + struct I_Param { StackObject intermediate; } i_param; void *none; } params{.none = nullptr}; - Instruction() : type(InstructionType::Unknown){}; - virtual ~Instruction() = default; - virtual void execute(VM &vm) = 0; - [[nodiscard]] virtual std::string toString() const = 0; }; }// namespace Bytecode diff --git a/src/bytecode/instructions/Jump.h b/src/bytecode/instructions/Jump.h deleted file mode 100644 index ea82fdd..0000000 --- a/src/bytecode/instructions/Jump.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "Instruction.h" -namespace Bytecode { - class Jump final : public Instruction { - public: - explicit Jump(const size_t line) { - params.r_param.reg = line; - type = InstructionType::Jump; - } - void execute(Bytecode::VM &vm) override { - vm.call_stack.stackTop->current_line = params.r_param.reg - 1; - } - [[nodiscard]] std::string toString() const override { - return "Jump " + std::to_string(params.r_param.reg); - } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/LessThan.h b/src/bytecode/instructions/LessThan.h deleted file mode 100644 index cc9c940..0000000 --- a/src/bytecode/instructions/LessThan.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "bytecode/instructions/Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class LessThan final : public Instruction { - public: - LessThan() { type = InstructionType::LessThan; }; - void execute(Bytecode::VM &vm) override { - const auto object2 = vm.program_stack.pop(); - const auto object1 = vm.program_stack.pop(); - if (object1.type != ObjectType::Number || - object2.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"<\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number < object2.data.number); - } - [[nodiscard]] std::string toString() const override { return "LessThan"; } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/LessThanRI.h b/src/bytecode/instructions/LessThanRI.h deleted file mode 100644 index f52a23d..0000000 --- a/src/bytecode/instructions/LessThanRI.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "Instruction.h" -namespace Bytecode { - class LessThanRI final : public Instruction { - public: - LessThanRI(size_t rg, double number) { - params.ri_params = {.reg = rg, .intermediate = StackObject(number)}; - type = InstructionType::LessThanRI; - } - void execute(Bytecode::VM &vm) override { - const auto object2 = params.ri_params.intermediate; - const auto object1 = vm.call_stack.getLocal(params.ri_params.reg); - if (object1.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"<\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number < object2.data.number); - } - [[nodiscard]] std::string toString() const override { - return "LessThanRI $r" + std::to_string(params.ri_params.reg) + - ", " + params.ri_params.intermediate.toString(); - } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/LoadGlobal.h b/src/bytecode/instructions/LoadGlobal.h deleted file mode 100644 index e324a81..0000000 --- a/src/bytecode/instructions/LoadGlobal.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "Instruction.h" - -namespace Bytecode { - class LoadGlobal final : public Instruction { - public: - explicit LoadGlobal(const uint32_t reg) { - params.r_param = {reg}; - type = InstructionType::LoadGlobal; - } - void execute(Bytecode::VM &vm) override { - vm.program_stack.push(vm.getGlobal(params.r_param.reg)); - } - [[nodiscard]] std::string toString() const override { - return "LoadGlobal $g" + std::to_string(params.r_param.reg); - } - }; -} \ No newline at end of file diff --git a/src/bytecode/instructions/LoadLiteral.h b/src/bytecode/instructions/LoadLiteral.h deleted file mode 100644 index bf92fb3..0000000 --- a/src/bytecode/instructions/LoadLiteral.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "bytecode/instructions/Instruction.h" -#include - -namespace Bytecode { - class LoadLiteral final : public Instruction { - public: - explicit LoadLiteral(const double value) { - type = Instruction::LoadLiteral; - params.i_param = {StackObject(value)}; - }; - - explicit LoadLiteral(const std::string &value) { - type = InstructionType::LoadLiteral; - params.i_param = {StackObject(value)}; - }; - - explicit LoadLiteral(const StackObject *literal) { - params.i_param = {*literal}; - type = InstructionType::LoadLiteral; - } - - void execute(Bytecode::VM &vm) override { - vm.program_stack.push(params.i_param.intermediate); - } - - [[nodiscard]] std::string toString() const override { - if (params.i_param.intermediate.type == ObjectType::String) { - std::string str = params.i_param.intermediate.toString(); - if (str == "\n") str = "\\n"; - return "LoadLiteral " + std::string("\"") + str + std::string("\""); - } - return "LoadLiteral " + params.i_param.intermediate.toString(); - } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/LoadLocal.h b/src/bytecode/instructions/LoadLocal.h deleted file mode 100644 index 8559c84..0000000 --- a/src/bytecode/instructions/LoadLocal.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "Instruction.h" - -namespace Bytecode { - class LoadLocal final : public Instruction { - public: - explicit LoadLocal(const size_t reg) { - type = InstructionType::LoadLocal; - params.r_param = {reg}; - } - void execute(Bytecode::VM &vm) override { - vm.program_stack.push(vm.call_stack.getLocal(params.r_param.reg)); - } - [[nodiscard]] std::string toString() const override { - return "LoadLocal $r" + std::to_string(params.r_param.reg); - } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/Multiply.h b/src/bytecode/instructions/Multiply.h deleted file mode 100644 index f17b1f1..0000000 --- a/src/bytecode/instructions/Multiply.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "bytecode/instructions/Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class Multiply final : public Instruction { - public: - Multiply() { type = InstructionType::Multiply; }; - void execute(VM &vm) override { - const auto object2 = vm.program_stack.pop(); - const auto object1 = vm.program_stack.pop(); - if (object1.type != ObjectType::Number || - object2.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"*\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number * object2.data.number); - } - [[nodiscard]] std::string toString() const override { return "Multiply"; } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/MultiplyRI.h b/src/bytecode/instructions/MultiplyRI.h deleted file mode 100644 index 3a1c30c..0000000 --- a/src/bytecode/instructions/MultiplyRI.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class MultiplyRI final : public Instruction { - public: - MultiplyRI(size_t rg, double number) { - type = InstructionType::MultiplyRI; - params = {rg, StackObject(number)}; - } - void execute(Bytecode::VM &vm) override { - const auto object1 = params.ri_params.intermediate; - const auto object2 = vm.call_stack.getLocal(params.ri_params.reg); - if (object2.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"*\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number * object2.data.number); - } - [[nodiscard]] std::string toString() const override { - return "MultiplyRI $r" + std::to_string(params.ri_params.reg) + - ", " + params.ri_params.intermediate.toString(); - } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/Not.h b/src/bytecode/instructions/Not.h deleted file mode 100644 index 3e3abc3..0000000 --- a/src/bytecode/instructions/Not.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "Instruction.h" - -namespace Bytecode { - class Not final : public Instruction { - public: - Not() { type = InstructionType::Not; } - void execute(Bytecode::VM &vm) override { - const auto object = vm.program_stack.pop(); - if (object.type != ObjectType::Boolean) - vm.program_stack.push(false); - else - vm.program_stack.push(!object.data.boolean); - } - [[nodiscard]] std::string toString() const override { return "Not"; } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/Or.h b/src/bytecode/instructions/Or.h deleted file mode 100644 index 60f9896..0000000 --- a/src/bytecode/instructions/Or.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class Or final : public Instruction { - public: - Or() { type = InstructionType::Or; } - void execute(Bytecode::VM &vm) override { - const auto object2 = vm.program_stack.pop(); - const auto object1 = vm.program_stack.pop(); - if (object1.type != ObjectType::Boolean || - object2.type != ObjectType::Boolean) { - throw SyntaxError("Invalid argument type for function \"or\", Expected boolean, got string"); - } - vm.program_stack.push(object1.data.boolean || object2.data.boolean); - } - [[nodiscard]] std::string toString() const override { - return "Or"; - } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/ReadFromStdin.h b/src/bytecode/instructions/ReadFromStdin.h deleted file mode 100644 index 91da18b..0000000 --- a/src/bytecode/instructions/ReadFromStdin.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "Instruction.h" - -namespace Bytecode { - class ReadFromStdin final : public Instruction { - public: - explicit ReadFromStdin() { - type = InstructionType::ReadFromStdin; - } - void execute(Bytecode::VM &vm) override { - std::string input; - std::getline(std::cin, input); - char *p; - double number = std::strtod(input.c_str(), &p); - if (*p) - vm.program_stack.push(input); - else - vm.program_stack.push(number); - } - [[nodiscard]] std::string toString() const override { return "ReadFromStdin"; } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/Return.h b/src/bytecode/instructions/Return.h deleted file mode 100644 index c404c4f..0000000 --- a/src/bytecode/instructions/Return.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Instruction.h" - -namespace Bytecode { - class Return final : public Instruction { - public: - Return() { type = InstructionType::Return; } - void execute(Bytecode::VM &vm) override { - vm.call_stack.popStackFrame(); - } - [[nodiscard]] std::string toString() const override { return "Return"; } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/SendToStdout.h b/src/bytecode/instructions/SendToStdout.h deleted file mode 100644 index 24869f3..0000000 --- a/src/bytecode/instructions/SendToStdout.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "Instruction.h" - -namespace Bytecode { - class SendToStdout final : public Instruction { - public: - explicit SendToStdout() { - type = InstructionType::SendToStdout; - } - void execute(Bytecode::VM &vm) override { - std::cout << vm.program_stack.pop().toString(); - } - [[nodiscard]] std::string toString() const override { return "SendToStdout"; } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/instructions/StoreGlobal.h b/src/bytecode/instructions/StoreGlobal.h deleted file mode 100644 index e777e23..0000000 --- a/src/bytecode/instructions/StoreGlobal.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "Instruction.h" -#include - -namespace Bytecode { - class StoreGlobal final : public Instruction { - public: - explicit StoreGlobal(const size_t reg) { - params.r_param = {reg}; - type = InstructionType::StoreGlobal; - } - void execute(Bytecode::VM &vm) override { - vm.setGlobal(params.r_param.reg, vm.program_stack.pop()); - } - [[nodiscard]] std::string toString() const override { - return "Store $r" + std::to_string(params.r_param.reg); - } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/StoreLocal.h b/src/bytecode/instructions/StoreLocal.h deleted file mode 100644 index 1e7d5ad..0000000 --- a/src/bytecode/instructions/StoreLocal.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "Instruction.h" -#include - -namespace Bytecode { - class StoreLocal final : public Instruction { - public: - explicit StoreLocal(const size_t reg) { - params.r_param = {reg}; - type = InstructionType::StoreLocal; - } - void execute(Bytecode::VM &vm) override { - vm.call_stack.setLocal(params.r_param.reg, vm.program_stack.pop()); - } - [[nodiscard]] std::string toString() const override { - return "StoreLocal $r" + std::to_string(params.r_param.reg); - } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/Subtract.h b/src/bytecode/instructions/Subtract.h deleted file mode 100644 index 0c31388..0000000 --- a/src/bytecode/instructions/Subtract.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "bytecode/instructions/Instruction.h" -#include "exceptions/SyntaxError.h" - -namespace Bytecode { - class Subtract final : public Instruction { - public: - Subtract() { type = InstructionType::Subtract; }; - void execute(Bytecode::VM &vm) override { - const auto object2 = vm.program_stack.pop(); - const auto object1 = vm.program_stack.pop(); - if (object1.type != ObjectType::Number || - object2.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"-\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number - object2.data.number); - } - [[nodiscard]] std::string toString() const override { return "Subtract"; } - }; -}// namespace Bytecode diff --git a/src/bytecode/instructions/SubtractRI.h b/src/bytecode/instructions/SubtractRI.h deleted file mode 100644 index 13b19b8..0000000 --- a/src/bytecode/instructions/SubtractRI.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "Instruction.h" - -namespace Bytecode { - class SubtractRI final : public Instruction { - public: - SubtractRI(uint32_t rg, double number) { - params.ri_params = {.reg = rg, .intermediate = StackObject(number)}; - type = InstructionType::SubtractRI; - } - void execute(VM &vm) override { - const auto object2 = params.ri_params.intermediate; - const auto object1 = vm.call_stack.getLocal(params.ri_params.reg); - if (object1.type != ObjectType::Number) { - throw SyntaxError("Invalid argument type for function \"-\", Expected number, got string"); - } - vm.program_stack.push(object1.data.number - object2.data.number); - } - [[nodiscard]] std::string toString() const override { - return "SubtractRI $r" + std::to_string(params.ri_params.reg) + - ", " + params.ri_params.intermediate.toString(); - } - }; -}// namespace Bytecode \ No newline at end of file diff --git a/src/bytecode/vm/Interpreter.cpp b/src/bytecode/vm/Interpreter.cpp index 9f05df4..f3b343d 100644 --- a/src/bytecode/vm/Interpreter.cpp +++ b/src/bytecode/vm/Interpreter.cpp @@ -1,9 +1,6 @@ #include "Interpreter.h" #include "exceptions/SyntaxError.h" -#include -#include - void Bytecode::Interpreter::execute(const Program &program) { const auto &stackTop = vm.call_stack.stackTop; for (;; stackTop->current_line++) { @@ -12,6 +9,239 @@ void Bytecode::Interpreter::execute(const Program &program) { if (stackTop->segment == 0 && stackTop->current_line == currentSegment->instructions.size()) return; - currentSegment->instructions[stackTop->current_line]->execute(vm); + const auto currentInstruction = + *currentSegment->instructions[stackTop->current_line]; + switch (currentInstruction.type) { + case Instruction::Invalid: + throw SyntaxError("Invalid instruction"); + case Instruction::LoadLiteral: + vm.program_stack.push(currentInstruction.params.i_param.intermediate); + break; + case Instruction::LoadGlobal: + vm.program_stack.push(vm.getGlobal(currentInstruction.params.r_param.reg)); + break; + case Instruction::LoadLocal: + vm.program_stack.push(vm.call_stack.getLocal(currentInstruction.params.r_param.reg)); + break; + case Instruction::StoreLocal: + vm.call_stack.setLocal(currentInstruction.params.r_param.reg, vm.program_stack.pop()); + break; + case Instruction::StoreGlobal: + vm.setGlobal(currentInstruction.params.r_param.reg, vm.program_stack.pop()); + break; + case Instruction::Add: { + const auto object2 = vm.program_stack.pop(); + const auto object1 = vm.program_stack.pop(); + if (object1.type != ObjectType::Number || + object2.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"+\", Expected number, got string"); + } + vm.program_stack.push(object1.data.number + object2.data.number); + } break; + case Instruction::AddRI: { + const auto object1 = currentInstruction.params.ri_params.intermediate; + const auto object2 = vm.call_stack.getLocal(currentInstruction.params.ri_params.reg); + if (object2.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"+\", Expected number, got string"); + } + vm.program_stack.push(object1.data.number + object2.data.number); + } break; + case Instruction::AddRR: { + 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"); + } + vm.program_stack.push(object1.data.number + object2.data.number); + } break; + case Instruction::Subtract: { + const auto object2 = vm.program_stack.pop(); + const auto object1 = vm.program_stack.pop(); + if (object1.type != ObjectType::Number || + object2.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"-\", Expected number, got string"); + } + vm.program_stack.push(object1.data.number - object2.data.number); + } break; + case Instruction::SubtractRI: { + 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"); + } + vm.program_stack.push(object1.data.number - object2.data.number); + } break; + case Instruction::SubtractRR: { + 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"); + } + vm.program_stack.push(object1.data.number - object2.data.number); + } break; + case Instruction::Multiply: { + const auto object2 = vm.program_stack.pop(); + const auto object1 = vm.program_stack.pop(); + if (object1.type != ObjectType::Number || + object2.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"*\", Expected number, got string"); + } + vm.program_stack.push(object1.data.number * object2.data.number); + } break; + case Instruction::MultiplyRI: { + const auto object1 = currentInstruction.params.ri_params.intermediate; + const auto object2 = vm.call_stack.getLocal(currentInstruction.params.ri_params.reg); + if (object2.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"*\", Expected number, got string"); + } + vm.program_stack.push(object1.data.number * object2.data.number); + } break; + case Instruction::MultiplyRR: { + 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"); + } + vm.program_stack.push(object1.data.number * object2.data.number); + } break; + case Instruction::Increment: + vm.program_stack.push(vm.program_stack.pop().data.number + 1); + break; + case Instruction::Decrement: + vm.program_stack.push(vm.program_stack.pop().data.number - 1); + break; + case Instruction::DecrementR: { + const auto number = vm.call_stack.getLocal(currentInstruction.params.r_param.reg); + if (number.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"-\", Expected number, got string"); + } + vm.program_stack.push(number.data.number - 1); + } break; + case Instruction::Divide: { + const auto object2 = vm.program_stack.pop(); + const auto object1 = vm.program_stack.pop(); + if (object1.type != ObjectType::Number || + object2.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"/\", Expected number, got string"); + } + 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(); + if (object1.type != ObjectType::Number || + object2.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"=\", Expected number, got string"); + } + vm.program_stack.push(object1.data.number == object2.data.number); + } break; + case Instruction::EqualsRI: { + const auto object1 = currentInstruction.params.ri_params.intermediate; + const auto object2 = vm.call_stack.getLocal(currentInstruction.params.ri_params.reg); + if (object2.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"=\", Expected number, got string"); + } + vm.program_stack.push(object1.data.number == object2.data.number); + } break; + case Instruction::LessThan: { + const auto object2 = vm.program_stack.pop(); + const auto object1 = vm.program_stack.pop(); + if (object1.type != ObjectType::Number || + object2.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \"<\", Expected number, got string"); + } + vm.program_stack.push(object1.data.number < object2.data.number); + } break; + case Instruction::LessThanRI: { + 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"); + } + vm.program_stack.push(object1.data.number < object2.data.number); + } break; + case Instruction::GreaterThan: { + const auto object2 = vm.program_stack.pop(); + const auto object1 = vm.program_stack.pop(); + if (object1.type != ObjectType::Number || + object2.type != ObjectType::Number) { + throw SyntaxError("Invalid argument type for function \">\", Expected number, got string"); + } + vm.program_stack.push(object1.data.number > object2.data.number); + } break; + case Instruction::GreaterThanRI: { + 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"); + } + vm.program_stack.push(object1.data.number > object2.data.number); + } break; + case Instruction::And: { + const auto object2 = vm.program_stack.pop(); + const auto object1 = vm.program_stack.pop(); + if (object1.type != ObjectType::Boolean || + object2.type != ObjectType::Boolean) { + throw SyntaxError("Invalid argument type for function \"and\", Expected boolean, got string"); + } + vm.program_stack.push(object1.data.boolean && object2.data.boolean); + } break; + case Instruction::Or: { + const auto object2 = vm.program_stack.pop(); + const auto object1 = vm.program_stack.pop(); + if (object1.type != ObjectType::Boolean || + object2.type != ObjectType::Boolean) { + throw SyntaxError("Invalid argument type for function \"or\", Expected boolean, got string"); + } + vm.program_stack.push(object1.data.boolean || object2.data.boolean); + } break; + case Instruction::Not: { + const auto object = vm.program_stack.pop(); + if (object.type != ObjectType::Boolean) + vm.program_stack.push(false); + else + vm.program_stack.push(!object.data.boolean); + } break; + case Instruction::CondJumpIfNot: { + const auto cond = vm.program_stack.pop(); + if (!cond.data.boolean) + vm.call_stack.stackTop->current_line = currentInstruction.params.r_param.reg - 1; + } break; + case Instruction::Jump: { + vm.call_stack.stackTop->current_line = currentInstruction.params.r_param.reg - 1; + } break; + case Instruction::Call: { + vm.call_stack.newStackFrame( + currentInstruction.params.ri_params.reg, + currentInstruction.params.ri_params.intermediate.data.reg, + &vm.program_stack); + } break; + case Instruction::CallLambda: { + const auto lambda = vm.program_stack.pop(); + vm.call_stack.newStackFrame( + lambda.data.reg, + currentInstruction.params.r_param.reg, + &vm.program_stack); + } break; + case Instruction::Return: + vm.call_stack.popStackFrame(); + break; + case Instruction::ReadFromStdin: { + std::string input; + std::getline(std::cin, input); + char *p; + double number = std::strtod(input.c_str(), &p); + if (*p) + vm.program_stack.push(input); + else + vm.program_stack.push(number); + } break; + case Instruction::SendToStdout: + std::cout << vm.program_stack.pop().toString(); + break; + } } } diff --git a/src/lexer/Token.cpp b/src/lexer/Token.cpp index 7d7a70f..495efdc 100644 --- a/src/lexer/Token.cpp +++ b/src/lexer/Token.cpp @@ -16,10 +16,6 @@ Token::Token( : type(type), token(std::move(token)) {} -std::string Token::asString() const { - return token; -} - double Token::asNumber() const { return std::stod(token); } diff --git a/src/lexer/Token.h b/src/lexer/Token.h index 5981033..c4e3bc1 100644 --- a/src/lexer/Token.h +++ b/src/lexer/Token.h @@ -27,7 +27,6 @@ class Token { int line, int column); [[nodiscard]] double asNumber() const; - [[nodiscard]] std::string asString() const; bool operator==(const Token &object) const; diff --git a/src/main.cpp b/src/main.cpp index 234f5d8..e936625 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,4 @@ #include "bytecode/compiler/Optimizer.h" -#include "bytecode/instructions/Return.h" #include "bytecode/vm/Interpreter.h" #include "exceptions/SyntaxError.h" #include "lexer/Lexer.h" @@ -42,14 +41,14 @@ void exec_program(const std::string &program, struct options opts) { } - if (opts.dumpBytecode) { - for (size_t i = 0; i < compiled_bytecode.segments.size(); i++) { - std::cout << ':' << i << '\n'; - for (size_t j = 0; j < compiled_bytecode.segments[i]->instructions.size(); j++) - std::cout << j << '\t' << compiled_bytecode.segments[i]->instructions[j]->toString() << '\n'; - std::cout << '\n'; - } - } +// if (opts.dumpBytecode) { +// for (size_t i = 0; i < compiled_bytecode.segments.size(); i++) { +// std::cout << ':' << i << '\n'; +// for (size_t j = 0; j < compiled_bytecode.segments[i]->instructions.size(); j++) +// std::cout << j << '\t' << compiled_bytecode.segments[i]->instructions[j]->toString() << '\n'; +// std::cout << '\n'; +// } +// } interpreter.execute(compiled_bytecode); const auto stackTop = interpreter.vm.program_stack.top(); diff --git a/src/parser/SyntaxTreeNode.cpp b/src/parser/SyntaxTreeNode.cpp index 5a4191e..7e05c63 100644 --- a/src/parser/SyntaxTreeNode.cpp +++ b/src/parser/SyntaxTreeNode.cpp @@ -14,14 +14,6 @@ #include "bytecode/builtin_functions/PrintFunction.h" #include "bytecode/builtin_functions/ReadFunction.h" #include "bytecode/builtin_functions/SubtractFunction.h" -#include "bytecode/instructions/Call.h" -#include "bytecode/instructions/CallLambda.h" -#include "bytecode/instructions/CondJumpIfNot.h" -#include "bytecode/instructions/Jump.h" -#include "bytecode/instructions/LoadGlobal.h" -#include "bytecode/instructions/LoadLiteral.h" -#include "bytecode/instructions/LoadLocal.h" -#include "bytecode/instructions/Return.h" #include "exceptions/SyntaxError.h" void TokenNode::compile( @@ -30,23 +22,29 @@ void TokenNode::compile( std::vector &instructions) { switch (token.type) { case Token::Number: - instructions.push_back( - new Bytecode::LoadLiteral(token.asNumber())); - break; case Token::String: - instructions.push_back( - new Bytecode::LoadLiteral(token.asString())); + case Token::Boolean: + instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::LoadLiteral, + {.i_param = {Bytecode::StackObject(token)}}, + }); break; case Token::Symbol: if (program.find_constant(token.token) != nullptr) { - instructions.push_back(new Bytecode::LoadLiteral( - program.find_constant(token.token))); + instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::LoadLiteral, + {.i_param = {*program.find_constant(token.token)}}, + }); } else if (segment->find_variable(token.token) != -1) { - instructions.push_back(new Bytecode::LoadLocal( - segment->find_variable(token.asString()))); + instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::LoadLocal, + {.r_param = {segment->find_variable(token.token)}}, + }); } else if (program.find_global(token.token) != -1) { - instructions.push_back(new Bytecode::LoadGlobal( - program.find_global(token.asString()))); + instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::LoadGlobal, + {.r_param = {program.find_global(token.token)}}, + }); } else { throw SyntaxError( "Undefined variable -> " + token.token, @@ -86,16 +84,26 @@ void Expression::compile( if (program.find_global(function.token) != -1) { for (const auto &argument: args) argument->compile(segment, program, instructions); - instructions.push_back(new Bytecode::LoadGlobal( - program.find_global(function.token))); - instructions.push_back(new Bytecode::CallLambda(args.size())); + instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::LoadGlobal, + {.r_param = {program.find_global(function.token)}}, + }); + instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::CallLambda, + {.r_param = {args.size()}}, + }); return; } else if (segment->find_variable(function.token) != -1) { for (const auto &argument: args) argument->compile(segment, program, instructions); - instructions.push_back(new Bytecode::LoadLocal( - segment->find_variable(function.token))); - instructions.push_back(new Bytecode::CallLambda(args.size())); + instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::LoadLocal, + {.r_param = {program.find_global(function.token)}}, + }); + instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::CallLambda, + {.r_param = {args.size()}}, + }); return; } else if (program.find_function(function.token) != -1) { if (args.size() != program.segments[program.find_function(function.token)]->variables_table.size()) @@ -107,9 +115,12 @@ void Expression::compile( function.column); for (const auto &argument: args) argument->compile(segment, program, instructions); - const auto called_segment = program.find_function(function.asString()); + const auto called_segment = program.find_function(function.token); const auto arguments = program.segments[called_segment]->variables_table.size(); - instructions.push_back(new Bytecode::Call(called_segment, arguments)); + instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::Call, + {.ri_params = {called_segment, Bytecode::StackObject(arguments)}}, + }); return; } else if (builtin_instructions.find(function.token) != builtin_instructions.end()) { builtin_instructions[function.token]->compile( @@ -172,17 +183,21 @@ void CondExpression::compile( for (size_t i = 0; i < conditions_instructions.size(); i++) { for (const auto instruction: conditions_instructions[i]) result->instructions.push_back(instruction); - result->instructions.push_back( - new Bytecode::CondJumpIfNot( - result->instructions.size() + - cond_success_instructions[i].size() + - 2 - default_case_instructions.empty())); + result->instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::CondJumpIfNot, + {.r_param = {result->instructions.size() + + cond_success_instructions[i].size() + + 2 - default_case_instructions.empty()}}, + }); for (const auto instruction: cond_success_instructions[i]) result->instructions.push_back(instruction); if (!default_case_instructions.empty()) - result->instructions.push_back(new Bytecode::Jump(end)); + result->instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::Jump, + {.r_param = {end}}, + }); } for (const auto instruction: default_case_instructions) @@ -233,7 +248,11 @@ void LambdaExpression::compile( for (auto argument: args) segment->declare_variable(((class TokenNode *) argument)->getName()); definition->compile(segment, program, segment->instructions); - segment->instructions.push_back(new Bytecode::Return()); - instructions.push_back( - new Bytecode::LoadLiteral(new Bytecode::StackObject(reg))); + segment->instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::Return, + }); + instructions.push_back(new (Bytecode::Instruction){ + Bytecode::Instruction::LoadLiteral, + {.i_param = {Bytecode::StackObject(reg)}}, + }); } \ No newline at end of file