From 5112d36ae079fef47f70e830cba0cd1d48d2acd7 Mon Sep 17 00:00:00 2001 From: OusmBlueNinja <89956790+OusmBlueNinja@users.noreply.github.com> Date: Mon, 19 May 2025 12:45:08 -0500 Subject: [PATCH] yea, sux --- .idea/.gitignore | 8 + .idea/JoVa.iml | 2 + .idea/betterCommentsSettings.xml | 31 +++ .idea/editor.xml | 341 +++++++++++++++++++++++++++ .idea/material_theme_project_new.xml | 10 + .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + CMakeLists.txt | 35 +++ main.cpp | 9 + src/Compiler.cpp | 136 +++++++++++ src/Compiler.h | 20 ++ src/Vm.cpp | 168 +++++++++++++ src/Vm.h | 64 +++++ 14 files changed, 845 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/JoVa.iml create mode 100644 .idea/betterCommentsSettings.xml create mode 100644 .idea/editor.xml create mode 100644 .idea/material_theme_project_new.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 CMakeLists.txt create mode 100644 main.cpp create mode 100644 src/Compiler.cpp create mode 100644 src/Compiler.h create mode 100644 src/Vm.cpp create mode 100644 src/Vm.h diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/JoVa.iml b/.idea/JoVa.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/JoVa.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/betterCommentsSettings.xml b/.idea/betterCommentsSettings.xml new file mode 100644 index 0000000..4f152ed --- /dev/null +++ b/.idea/betterCommentsSettings.xml @@ -0,0 +1,31 @@ + + + + + + \ No newline at end of file diff --git a/.idea/editor.xml b/.idea/editor.xml new file mode 100644 index 0000000..970f097 --- /dev/null +++ b/.idea/editor.xml @@ -0,0 +1,341 @@ + + + + + \ No newline at end of file diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..879b75e --- /dev/null +++ b/.idea/material_theme_project_new.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0b76fe5 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..72b3444 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c0cde95 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.15) +project(JoVa LANGUAGES CXX) + +# Set output directories for builds +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin/Debug) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin/Release) + +# Set C++ standard +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if(MSVC) + add_compile_options(/W4 /permissive-) +else() + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +set(SOURCES + main.cpp + src/Vm.cpp + src/Vm.h + src/Compiler.cpp + src/Compiler.h +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +add_executable(JoVa ${SOURCES}) + +source_group("Source Files" FILES ${SOURCES}) + +# Set default build type to Debug if not specified +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE) +endif() diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..ace9686 --- /dev/null +++ b/main.cpp @@ -0,0 +1,9 @@ +#include "src/Vm.h" +#include "src/Compiler.h" + +int main() { + auto bytecode = JV::Compiler::CompileExample(); + JV::VM vm(bytecode); + vm.Run(); + return 0; +} diff --git a/src/Compiler.cpp b/src/Compiler.cpp new file mode 100644 index 0000000..6859d61 --- /dev/null +++ b/src/Compiler.cpp @@ -0,0 +1,136 @@ +#include "Compiler.h" +#include "Vm.h" + +namespace JV { + +std::vector Compiler::CompileExample() { + std::vector code; + + // n = 10 + code.push_back(OP_CONST); + code.push_back(10); + code.push_back(OP_STORE); // R4 = n + code.push_back(4); + + // alloc heap[n] + code.push_back(OP_ALLOC); // heap = malloc(n) + code.push_back(10); + code.push_back(OP_STORE); // R5 = heap base address + code.push_back(5); + + // i = 2 + code.push_back(OP_CONST); + code.push_back(2); + code.push_back(OP_STORE); // R0 = i + code.push_back(0); + + // a = 0 + code.push_back(OP_CONST); + code.push_back(0); + code.push_back(OP_STORE); // R1 = a + code.push_back(1); + + // b = 1 + code.push_back(OP_CONST); + code.push_back(1); + code.push_back(OP_STORE); // R2 = b + code.push_back(2); + + // store fib(0) at heap[0] + code.push_back(OP_LOAD); // R5 (heap base) + code.push_back(5); + code.push_back(OP_CONST); // push 0 + code.push_back(0); + code.push_back(OP_ADD); // heap + 0 + code.push_back(OP_CONST); // value: 0 + code.push_back(0); + code.push_back(OP_STORE_MEM); + + // print fib(0) + code.push_back(OP_CONST); // print 0 + code.push_back(0); + code.push_back(OP_PRINT); + + // store fib(1) at heap[1] + code.push_back(OP_LOAD); // R5 + code.push_back(5); + code.push_back(OP_CONST); // +1 + code.push_back(1); + code.push_back(OP_ADD); + code.push_back(OP_CONST); // value: 1 + code.push_back(1); + code.push_back(OP_STORE_MEM); + + // print fib(1) + code.push_back(OP_CONST); + code.push_back(1); + code.push_back(OP_PRINT); + + // === loop: + int loop_start = code.size(); + + // if i >= n: halt + code.push_back(OP_LOAD); // i + code.push_back(0); + code.push_back(OP_LOAD); // n + code.push_back(4); + code.push_back(OP_SUB); + code.push_back(OP_CONST); // if i - n >= 0 → skip CALL + code.push_back(0); + code.push_back(OP_SUB); // dummy conditional + // (TODO: implement real conditional branching) + + // fib = a + b + code.push_back(OP_LOAD); // a + code.push_back(1); + code.push_back(OP_LOAD); // b + code.push_back(2); + code.push_back(OP_ADD); + code.push_back(OP_STORE); // R3 = fib + code.push_back(3); + + // store fib(i) in heap[i] + code.push_back(OP_LOAD); // R5 (heap base) + code.push_back(5); + code.push_back(OP_LOAD); // R0 (i) + code.push_back(0); + code.push_back(OP_ADD); // addr = base + i + code.push_back(OP_LOAD); // fib value (R3) + code.push_back(3); + code.push_back(OP_STORE_MEM); + + // print fib(i) + code.push_back(OP_LOAD); + code.push_back(3); + code.push_back(OP_PRINT); + + // a = b + code.push_back(OP_LOAD); + code.push_back(2); + code.push_back(OP_STORE); + code.push_back(1); + + // b = fib + code.push_back(OP_LOAD); + code.push_back(3); + code.push_back(OP_STORE); + code.push_back(2); + + // i = i + 1 + code.push_back(OP_LOAD); + code.push_back(0); + code.push_back(OP_CONST); + code.push_back(1); + code.push_back(OP_ADD); + code.push_back(OP_STORE); + code.push_back(0); + + // jump back to loop + code.push_back(OP_CALL); + code.push_back(loop_start); + + code.push_back(OP_HALT); + return code; +} + +} // namespace JV diff --git a/src/Compiler.h b/src/Compiler.h new file mode 100644 index 0000000..66498bf --- /dev/null +++ b/src/Compiler.h @@ -0,0 +1,20 @@ +// +// Created by spenc on 5/19/2025. +// + +#ifndef COMPILER_H +#define COMPILER_H + +#include +#include + +namespace JV { + + class Compiler { + public: + static std::vector CompileExample(); + }; + +} // namespace JV + +#endif // COMPILER_H diff --git a/src/Vm.cpp b/src/Vm.cpp new file mode 100644 index 0000000..a41dc5b --- /dev/null +++ b/src/Vm.cpp @@ -0,0 +1,168 @@ +#include "Vm.h" +#include + +namespace JV +{ + VM::VM(const std::vector &bytecode) + : m_Bytecode(bytecode), m_IP(0) + { + m_Registers.fill(0); + m_Heap.resize(HEAP_SIZE, 0); + } + + int VM::Pop() + { + int val = m_Stack.top(); + m_Stack.pop(); + return val; + } + + void VM::Push(int val) + { + m_Stack.push(val); + } + + void VM::Debug() + { + std::cout << "\n[DEBUG] IP: " << m_IP << "\nStack: "; + std::stack temp = m_Stack; + std::vector stackDump; + while (!temp.empty()) { + stackDump.push_back(temp.top()); + temp.pop(); + } + for (auto it = stackDump.rbegin(); it != stackDump.rend(); ++it) + std::cout << *it << " "; + std::cout << "\nRegisters: "; + for (int r: m_Registers) + std::cout << r << " "; + std::cout << "\n\nPress Enter to step...\n"; + std::cin.get(); + } + + void VM::Run() + { + while (m_IP < m_Bytecode.size()) { + OpCode op = static_cast(m_Bytecode[m_IP++]); +#ifndef _DEBUG + //Debug(); +#endif + + switch (op) { + case OP_HALT: + return; + + case OP_ALLOC: Alloc(); + break; + + case OP_STORE_MEM: StoreMem(); + break; + case OP_LOAD_MEM: LoadMem(); + break; + + + case OP_CONST: + Push(m_Bytecode[m_IP++]); + break; + + case OP_STORE: + { + uint8_t reg = m_Bytecode[m_IP++]; + m_Registers[reg] = Pop(); + break; + } + + case OP_LOAD: + { + uint8_t reg = m_Bytecode[m_IP++]; + Push(m_Registers[reg]); + break; + } + + case OP_ADD: + { + int b = Pop(), a = Pop(); + Push(a + b); + break; + } + + case OP_SUB: + { + int b = Pop(), a = Pop(); + Push(a - b); + break; + } + + case OP_MUL: + { + int b = Pop(), a = Pop(); + Push(a * b); + break; + } + + case OP_DIV: + { + int b = Pop(), a = Pop(); + Push(a / b); + break; + } + + case OP_PRINT: + std::cout << Pop() << std::endl; + break; + + case OP_CALL: + { + uint8_t addr = m_Bytecode[m_IP++]; + m_CallStack.push(m_IP); + m_IP = addr; + break; + } + + case OP_RET: + m_IP = m_CallStack.top(); + m_CallStack.pop(); + break; + + case OP_DEBUG: + Debug(); + break; + + default: + std::cerr << "Unknown opcode: " << static_cast(op) << "\n"; + return; + } + } + } + + + void VM::Alloc() + { + uint8_t count = m_Bytecode[m_IP++]; + if (m_HeapPtr + count >= HEAP_SIZE) { + std::cerr << "Heap overflow!" << std::endl; + return; + } + Push(static_cast(m_HeapPtr)); // return address + m_HeapPtr += count; + } + + void VM::StoreMem() + { + int value = Pop(); + int addr = Pop(); + if (addr >= 0 && addr < HEAP_SIZE) + m_Heap[addr] = value; + else + std::cerr << "Invalid memory store at " << addr << std::endl; + } + + void VM::LoadMem() + { + int addr = Pop(); + if (addr >= 0 && addr < HEAP_SIZE) + Push(m_Heap[addr]); + else + std::cerr << "Invalid memory load at " << addr << std::endl; + } +} // namespace JV diff --git a/src/Vm.h b/src/Vm.h new file mode 100644 index 0000000..b69c733 --- /dev/null +++ b/src/Vm.h @@ -0,0 +1,64 @@ +#ifndef VM_H +#define VM_H + +#include +#include +#include +#include + +namespace JV { + + constexpr int MAX_REGISTERS = 8; + constexpr int STACK_SIZE = 1024; + static constexpr int HEAP_SIZE = 256; // "size_t" give wrnings + + + + + enum OpCode : uint8_t { + OP_HALT = 0, + OP_CONST, + OP_STORE, + OP_LOAD, + OP_ADD, + OP_SUB, + OP_MUL, + OP_DIV, + OP_PRINT, + OP_CALL, + OP_RET, + OP_ALLOC, // Allocate N cells, return address + OP_STORE_MEM, // Stack: [value, addr] + OP_LOAD_MEM, // Stack: [addr] + OP_DEBUG + }; + + class VM { + public: + explicit VM(const std::vector& bytecode); + void Run(); + + private: + std::vector m_Bytecode; + std::stack m_Stack; + std::vector m_Heap; + size_t m_HeapPtr = 0; + std::array m_Registers{}; + std::stack m_CallStack; + size_t m_IP = 0; + + int Pop(); + void Push(int val); + void Debug(); + + void Alloc(); + void StoreMem(); + void LoadMem(); + + + + }; + +} // namespace JV + +#endif // VM_H