mirror of
https://github.com/usatiuk/psil.git
synced 2025-10-28 10:47:49 +01:00
init
This commit is contained in:
77
.gitignore
vendored
Normal file
77
.gitignore
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -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
|
||||
8
.idea/cmake.xml
generated
Normal file
8
.idea/cmake.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeSharedSettings">
|
||||
<configurations>
|
||||
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DSANITIZE=YES" />
|
||||
</configurations>
|
||||
</component>
|
||||
</project>
|
||||
4
.idea/misc.xml
generated
Normal file
4
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/psil.iml" filepath="$PROJECT_DIR$/.idea/psil.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
2
.idea/psil.iml
generated
Normal file
2
.idea/psil.iml
generated
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
||||
27
CMakeLists.txt
Normal file
27
CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
cmake_minimum_required(VERSION 3.27)
|
||||
project(psil)
|
||||
|
||||
if (SANITIZE STREQUAL "YES")
|
||||
message(WARNING "Enabling sanitizers!")
|
||||
add_compile_options(-Wall -Wextra -pedantic -Wshadow -Wformat=2 -Wfloat-equal -D_GLIBCXX_DEBUG -Wconversion -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2)
|
||||
add_compile_options(-fsanitize=address -fsanitize=undefined -fno-sanitize-recover)
|
||||
add_link_options(-fsanitize=address -fsanitize=undefined -fno-sanitize-recover)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
add_compile_options(-flto)
|
||||
add_link_options(-flto)
|
||||
endif ()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_compile_options(-O3)
|
||||
add_link_options(-O3)
|
||||
endif ()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_subdirectory(test)
|
||||
8
src/CMakeLists.txt
Normal file
8
src/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_subdirectory(vm)
|
||||
|
||||
add_executable(psil main.cpp)
|
||||
|
||||
target_link_libraries(psil PRIVATE vm)
|
||||
6
src/main.cpp
Normal file
6
src/main.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <iostream>
|
||||
#include "vm/includes/VM.h"
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
3
src/vm/CMakeLists.txt
Normal file
3
src/vm/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
add_library(vm src/VM.cpp src/Cell.cpp)
|
||||
|
||||
target_include_directories(vm PUBLIC includes)
|
||||
74
src/vm/includes/Cell.h
Normal file
74
src/vm/includes/Cell.h
Normal file
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 22.12.2023.
|
||||
//
|
||||
|
||||
#ifndef PSIL_CELL_H
|
||||
#define PSIL_CELL_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
|
||||
enum class CellType {
|
||||
INT,
|
||||
CONS
|
||||
};
|
||||
|
||||
struct Cell {
|
||||
explicit Cell(CellType type) : _type(type) {}
|
||||
|
||||
virtual ~Cell() = 0;
|
||||
|
||||
CellType _type;
|
||||
};
|
||||
|
||||
struct IntCell : public Cell {
|
||||
IntCell() : Cell(CellType::INT) {}
|
||||
|
||||
IntCell(int64_t val) : Cell(CellType::INT), _val(val) {}
|
||||
|
||||
int64_t _val{};
|
||||
};
|
||||
|
||||
struct CommandCell : public IntCell {
|
||||
enum class CommandNum {
|
||||
NIL = 1,
|
||||
LDC = 2,
|
||||
LD = 3,
|
||||
SEL = 4,
|
||||
JOIN = 5,
|
||||
LDF = 6,
|
||||
AP = 7,
|
||||
RET = 8,
|
||||
DUM = 9,
|
||||
RAP = 10,
|
||||
STOP = 11,
|
||||
|
||||
ADD = 100,
|
||||
SUB = 101,
|
||||
|
||||
READCHAR = 201,
|
||||
PUTCHAR = 202,
|
||||
END = 1000
|
||||
};
|
||||
|
||||
CommandCell(CommandNum cmd) : IntCell(static_cast<int64_t>(cmd)) {}
|
||||
|
||||
CommandNum intToCmd() {
|
||||
assert((_val > 0 && static_cast<CommandNum>(_val) <= CommandNum::END));
|
||||
return static_cast<CommandNum>(_val);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct ConsCell : public Cell {
|
||||
ConsCell() : Cell(CellType::CONS) {}
|
||||
|
||||
ConsCell(Cell *car) : Cell(CellType::CONS), _car(car) {}
|
||||
|
||||
ConsCell(Cell *car, Cell *cdr) : Cell(CellType::CONS), _car(car), _cdr(cdr) {}
|
||||
|
||||
Cell *_car = nullptr;
|
||||
Cell *_cdr = nullptr;
|
||||
};
|
||||
|
||||
#endif //PSIL_CELL_H
|
||||
73
src/vm/includes/VM.h
Normal file
73
src/vm/includes/VM.h
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 22.12.2023.
|
||||
//
|
||||
|
||||
#ifndef PSIL_VM_H
|
||||
#define PSIL_VM_H
|
||||
|
||||
#include <vector>
|
||||
#include<utility>
|
||||
#include <iostream>
|
||||
|
||||
#include "Cell.h"
|
||||
|
||||
class VM {
|
||||
public:
|
||||
VM(std::istream &instream = std::cin, std::ostream &outstream = std::cout);
|
||||
|
||||
void run();
|
||||
|
||||
void step();
|
||||
|
||||
// template<typename T>
|
||||
// void appendCommand(T cell) {
|
||||
// push(_c, makeCell<T>(std::move(cell)));
|
||||
// }
|
||||
|
||||
template<typename T>
|
||||
void appendCommand(T *cell) {
|
||||
push(_c, cell);
|
||||
}
|
||||
|
||||
template<typename CT, typename... Args>
|
||||
CT *makeCell(Args... args) {
|
||||
return static_cast<CT *>(_cells.emplace_back(new CT(std::forward<Args>(args)...)));
|
||||
}
|
||||
|
||||
Cell *car(ConsCell *cell) {
|
||||
return cell->_car;
|
||||
}
|
||||
|
||||
Cell *cdr(ConsCell *cell) {
|
||||
return cell->_cdr;
|
||||
}
|
||||
|
||||
ConsCell *cons(Cell *car, Cell *cdr) {
|
||||
return dynamic_cast<ConsCell *>(makeCell<ConsCell>(car, cdr));
|
||||
}
|
||||
|
||||
Cell *pop(ConsCell *&what) {
|
||||
Cell *ret = what->_car;
|
||||
what = dynamic_cast<ConsCell *>(cdr(what));
|
||||
return ret;
|
||||
}
|
||||
|
||||
Cell *push(ConsCell *&what, Cell *toAppend) {
|
||||
what = cons(toAppend, what);
|
||||
return what;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Cell *> _cells;
|
||||
ConsCell *_s = nullptr;
|
||||
ConsCell *_e = nullptr;
|
||||
ConsCell *_c = nullptr;
|
||||
ConsCell *_d = nullptr;
|
||||
bool _stop = false;
|
||||
|
||||
std::istream &_instream;
|
||||
std::ostream &_outstream;
|
||||
};
|
||||
|
||||
|
||||
#endif //PSIL_VM_H
|
||||
7
src/vm/src/Cell.cpp
Normal file
7
src/vm/src/Cell.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 22.12.2023.
|
||||
//
|
||||
|
||||
#include "../includes/Cell.h"
|
||||
|
||||
Cell::~Cell() = default;
|
||||
101
src/vm/src/VM.cpp
Normal file
101
src/vm/src/VM.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 22.12.2023.
|
||||
//
|
||||
|
||||
#include "../includes/VM.h"
|
||||
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
|
||||
void VM::run() {
|
||||
while (!_stop) step();
|
||||
}
|
||||
|
||||
void VM::step() {
|
||||
CommandCell *popped = dynamic_cast<CommandCell *>(pop(_c));
|
||||
|
||||
switch (popped->intToCmd()) {
|
||||
case CommandCell::CommandNum::NIL: {
|
||||
push(_s, nullptr);
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::LDC: {
|
||||
IntCell *popped2 = dynamic_cast<IntCell *>(pop(_c));
|
||||
push(_s, popped2);
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::LD: {
|
||||
ConsCell *popped2 = dynamic_cast<ConsCell *>(pop(_c));
|
||||
|
||||
int64_t frame = dynamic_cast<IntCell *>(popped2->_car)->_val;
|
||||
int64_t arg = dynamic_cast<IntCell *>(popped2->_cdr)->_val;
|
||||
// todo
|
||||
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::SEL: {
|
||||
IntCell *popped2 = dynamic_cast<IntCell *>(pop(_s));
|
||||
ConsCell *ct = dynamic_cast<ConsCell *>(pop(_c));
|
||||
ConsCell *cf = dynamic_cast<ConsCell *>(pop(_c));
|
||||
ConsCell *ret = _c;
|
||||
push(_d, ret);
|
||||
if (popped2->_val > 0) {
|
||||
_c = ct;
|
||||
} else {
|
||||
_c = cf;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::JOIN: {
|
||||
ConsCell *ret = dynamic_cast<ConsCell *>(pop(_d));
|
||||
_c = ret;
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::LDF: {
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::AP: {
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::RET: {
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::DUM: {
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::RAP: {
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::STOP: {
|
||||
_stop = true;
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::ADD: {
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::SUB: {
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::END: {
|
||||
break;
|
||||
}
|
||||
case CommandCell::CommandNum::READCHAR:
|
||||
char c;
|
||||
_instream >> c;
|
||||
push(_s, makeCell<IntCell>(c));
|
||||
break;
|
||||
case CommandCell::CommandNum::PUTCHAR:
|
||||
IntCell *popped2 = dynamic_cast<IntCell *>(pop(_s));
|
||||
_outstream << (char) popped2->_val;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VM::VM(std::istream &instream, std::ostream &outstream) : _instream(instream), _outstream(outstream) {
|
||||
_s = dynamic_cast<ConsCell *>(makeCell<ConsCell>(nullptr));
|
||||
_e = dynamic_cast<ConsCell *>(makeCell<ConsCell>(nullptr));
|
||||
_c = dynamic_cast<ConsCell *>(makeCell<ConsCell>(nullptr));
|
||||
_d = dynamic_cast<ConsCell *>(makeCell<ConsCell>(nullptr));
|
||||
}
|
||||
13
test/CMakeLists.txt
Normal file
13
test/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
||||
)
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
add_subdirectory(vm)
|
||||
12
test/vm/CMakeLists.txt
Normal file
12
test/vm/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
add_executable(
|
||||
VMTest
|
||||
VMTest.cpp
|
||||
)
|
||||
target_link_libraries(
|
||||
VMTest
|
||||
vm
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(VMTest)
|
||||
66
test/vm/VMTest.cpp
Normal file
66
test/vm/VMTest.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "VM.h"
|
||||
|
||||
TEST(VMTest, BasicHello) {
|
||||
std::stringstream ssin;
|
||||
std::stringstream ssout;
|
||||
{
|
||||
VM vm(ssin, ssout);
|
||||
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::STOP));
|
||||
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
|
||||
vm.appendCommand(vm.makeCell<IntCell>('h'));
|
||||
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
|
||||
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::NIL));
|
||||
vm.run();
|
||||
}
|
||||
ssout.flush();
|
||||
EXPECT_EQ(ssout.str(), "h");
|
||||
}
|
||||
|
||||
TEST(VMTest, SelTest) {
|
||||
std::stringstream ssin;
|
||||
std::stringstream ssout;
|
||||
{
|
||||
VM vm(ssin, ssout);
|
||||
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::STOP));
|
||||
|
||||
// True branch true test
|
||||
ConsCell *tbtt = vm.makeCell<ConsCell>(vm.makeCell<CommandCell>(CommandCell::CommandNum::JOIN));
|
||||
vm.push(tbtt, vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
|
||||
vm.push(tbtt, vm.makeCell<IntCell>('1'));
|
||||
vm.push(tbtt, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
|
||||
|
||||
// False branch true test
|
||||
ConsCell *fbtt = vm.makeCell<ConsCell>(vm.makeCell<CommandCell>(CommandCell::CommandNum::JOIN));
|
||||
vm.push(fbtt, vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
|
||||
vm.push(fbtt, vm.makeCell<IntCell>('2'));
|
||||
vm.push(fbtt, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
|
||||
|
||||
// True branch false test
|
||||
ConsCell *tbft = vm.makeCell<ConsCell>(vm.makeCell<CommandCell>(CommandCell::CommandNum::JOIN));
|
||||
vm.push(tbft, vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
|
||||
vm.push(tbft, vm.makeCell<IntCell>('3'));
|
||||
vm.push(tbft, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
|
||||
|
||||
// False branch false test
|
||||
ConsCell *fbft = vm.makeCell<ConsCell>(vm.makeCell<CommandCell>(CommandCell::CommandNum::JOIN));
|
||||
vm.push(fbft, vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
|
||||
vm.push(fbft, vm.makeCell<IntCell>('4'));
|
||||
vm.push(fbft, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
|
||||
|
||||
vm.appendCommand(fbft);
|
||||
vm.appendCommand(tbft);
|
||||
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::SEL));
|
||||
vm.appendCommand(vm.makeCell<IntCell>(0));
|
||||
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
|
||||
vm.appendCommand(fbtt);
|
||||
vm.appendCommand(tbtt);
|
||||
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::SEL));
|
||||
vm.appendCommand(vm.makeCell<IntCell>(1));
|
||||
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
|
||||
vm.run();
|
||||
}
|
||||
ssout.flush();
|
||||
EXPECT_EQ(ssout.str(), "14");
|
||||
}
|
||||
Reference in New Issue
Block a user