create new project

This commit is contained in:
falsycat 2022-05-21 09:54:33 +09:00
parent fbb0631ca6
commit 8a07d83b0d
11 changed files with 821 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build/

54
CMakeLists.txt Normal file
View File

@ -0,0 +1,54 @@
cmake_minimum_required(VERSION 3.18)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
# ---- configuration ----
project(nf7 CXX)
option(NF7_STATIC "link all libs statically" ON)
set(NF7_GENERATED_INCLUDE_DIR "${PROJECT_BINARY_DIR}/include/generated")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(NF7_CXX_FLAGS
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
-Wall -Werror -pedantic-errors -Wextra -Wconversion -Wsign-conversion>
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
-Wno-overloaded-virtual>
$<$<CXX_COMPILER_ID:MSVC>:
/W4 /WX>
)
add_subdirectory(thirdparty EXCLUDE_FROM_ALL)
# ---- application ----
add_executable(nf7)
target_compile_options(nf7 PRIVATE ${NF7_CXX_FLAGS})
target_include_directories(nf7 PRIVATE . "${PROJECT_BINARY_DIR}/include")
target_compile_definitions(nf7
PRIVATE
IMGUI_DEFINE_MATH_OPERATORS
$<$<PLATFORM_ID:Darwin>:GL_SILENCE_DEPRECATION>
$<$<PLATFORM_ID:Darwin>:_GNU_SOURCE>
)
target_sources(nf7
PRIVATE
main.cc
nf7.cc
nf7.hh
)
target_link_libraries(nf7
PRIVATE
cereal::cereal
glew
glfw
imgui
imnodes
implot
linalg.h
luajit
source_location
)

13
LICENSE Normal file
View File

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

8
README.md Normal file
View File

@ -0,0 +1,8 @@
nf7
====
node-based programming language
## LICENSE
WTFPLv2

86
main.cc Normal file
View File

@ -0,0 +1,86 @@
#include <GL/glew.h>
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include <implot.h>
#include "nf7.hh"
#include <GLFW/glfw3.h>
int main(int, char**) {
// init display
glfwSetErrorCallback(
[](int, const char* msg) {
std::cout << "GLFW error: " << msg << std::endl;
});
if (!glfwInit()) return 1;
GLFWwindow* window;
const char* glsl_version;
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
# if defined(__APPLE__)
glsl_version = "#version 150";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
# else
glsl_version = "#version 130";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
# endif
window = glfwCreateWindow(1280, 720, "Nf7", NULL, NULL);
if (window == NULL) return 1;
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
if (glewInit() != GLEW_OK) return 1;
// init ImGUI
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImPlot::CreateContext();
auto& io = ImGui::GetIO();
io.IniFilename = nullptr;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init(glsl_version);
// main loop
while (true) {
// new frame
glfwPollEvents();
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// TODO: update
// render windows
ImGui::Render();
int w, h;
glfwGetFramebufferSize(window, &w, &h);
glViewport(0, 0, w, h);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
// TODO: handle queue
}
// teardown ImGUI
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImPlot::DestroyContext();
ImGui::DestroyContext();
// teardown display
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}

124
nf7.cc Normal file
View File

@ -0,0 +1,124 @@
#include "nf7.hh"
#include <cassert>
#include <map>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
#include <imgui.h>
using namespace std::literals;
namespace nf7 {
static inline auto& registry_() noexcept {
static std::map<std::string, File::TypeInfo*> registry_;
return registry_;
}
void Exception::UpdatePanic() const noexcept {
ImGui::TextUnformatted(msg_.c_str());
ImGui::Text("from %s:%d", srcloc_.file_name(), srcloc_.line());
}
File::File(Env& env) noexcept : env_(&env) {
}
File::~File() noexcept {
assert(id_ == 0);
}
std::unique_ptr<File> File::Deserialize(Env& env, Deserializer& d) {
std::string type;
d(type);
const auto& reg = registry_();
auto itr = reg.find(type);
if (itr == reg.end()) {
throw DeserializeException("unknown actor type: "s+type);
}
return itr->second->Deserialize(env, d);
}
void File::Serialize(Serializer& s) const noexcept {
s(std::string(type().name()));
SerializeParam(s);
}
void File::MoveUnder(Id parent) noexcept {
if (parent) {
assert(parent_ == 0);
assert(id_ == 0);
parent_ = parent;
id_ = env_->AddFile(*this);
} else {
assert(parent_ != 0);
assert(id_ != 0);
env_->RemoveFile(id_);
id_ = 0;
parent_ = 0;
}
}
File& File::FindOrThrow(std::string_view name) const {
if (auto ret = Find(name)) return *ret;
throw NotFoundException("missing child: "+std::string(name));
}
File& File::ResolveOrThrow(const Path& p) const
try {
assert(parent_ != 0);
assert(id_ != 0);
auto ret = const_cast<File*>(this);
for (const auto& term : p.terms()) {
if (term == "..") {
ret = &env_->GetFile(parent_);
} else if (term == ".") {
// do nothing
} else {
ret = &ret->FindOrThrow(term);
}
}
return *ret;
} catch (Exception&) {
throw NotFoundException("failed to resolve path: "+p.Stringify());
}
File& File::ResolveOrThrow(std::string_view p) const {
return ResolveOrThrow(Path::Parse(p));
}
File::TypeInfo::TypeInfo(const char* name) noexcept : name_(name) {
auto& reg = registry_();
auto [itr, uniq] = reg.emplace(std::string(name_), this);
assert(uniq);
}
File::TypeInfo::~TypeInfo() noexcept {
auto& reg = registry_();
reg.erase(std::string(name_));
}
File::Path File::Path::Deserialize(Deserializer& d) {
Path p;
d(p.terms_);
return p;
}
void File::Path::Serialize(Serializer& s) const noexcept {
s(terms_);
}
File::Path File::Path::Parse(std::string_view) {
return {}; // TODO
}
std::string File::Path::Stringify() const noexcept {
std::string ret;
for (const auto& term : terms_) {
ret += "/"+term;
}
return ret;
}
Context::Context(Env& env, File::Id initiator, Context::Id parent) noexcept :
env_(&env), initiator_(initiator), id_(env_->AddContext(*this)), parent_(parent) {
}
Context::~Context() noexcept {
env_->RemoveContext(id_);
}
} // namespace nf7

215
nf7.hh Normal file
View File

@ -0,0 +1,215 @@
#pragma once
#include <cstdint>
#include <exception>
#include <filesystem>
#include <functional>
#include <memory>
#include <span>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include <cereal/archives/binary.hpp>
#include <source_location.hh>
namespace nf7 {
class Exception;
class File;
class Context;
class Env;
using Deserializer = cereal::BinaryInputArchive;
using Serializer = cereal::BinaryOutputArchive;
class Exception {
public:
Exception() = delete;
Exception(std::string_view msg,
std::exception_ptr reason = std::current_exception(),
std::source_location loc = std::source_location::current()) noexcept :
msg_(msg), reason_(reason), srcloc_(loc) {
}
virtual ~Exception() = default;
Exception(const Exception&) = delete;
Exception(Exception&&) = delete;
Exception& operator=(const Exception&) = delete;
Exception& operator=(Exception&&) = delete;
virtual void UpdatePanic() const noexcept;
const std::string& msg() const noexcept { return msg_; }
const std::exception_ptr reason() const noexcept { return reason_; }
const std::source_location& srcloc() const noexcept { return srcloc_; }
private:
const std::string msg_;
const std::exception_ptr reason_;
const std::source_location srcloc_;
};
class DeserializeException : public Exception {
public:
using Exception::Exception;
};
class ExpiredException : public Exception {
public:
using Exception::Exception;
};
class File {
public:
class TypeInfo;
class Path;
class NotFoundException;
using Id = uint64_t;
File() = delete;
File(Env&) noexcept;
virtual ~File() noexcept;
File(const File&) = delete;
File(File&&) = delete;
File& operator=(const File&) = delete;
File& operator=(File&&) = delete;
static std::unique_ptr<File> Deserialize(Env&, Deserializer&);
void Serialize(Serializer&) const noexcept;
virtual void SerializeParam(Serializer&) const noexcept = 0;
virtual std::unique_ptr<File> Clone(Env&) const noexcept = 0;
virtual void MoveUnder(Id) noexcept;
virtual void Update() noexcept = 0;
virtual File* Find(std::string_view) const noexcept { return nullptr; }
File& FindOrThrow(std::string_view name) const;
File& ResolveOrThrow(const Path&) const;
File& ResolveOrThrow(std::string_view) const;
virtual const TypeInfo& type() const noexcept = 0;
virtual Id id() const noexcept = 0;
virtual Id parent() const noexcept = 0;
virtual void* iface(const std::type_info&) noexcept = 0;
Env& env() const noexcept { return *env_; }
private:
Env* const env_;
Id id_ = 0, parent_ = 0;
};
class File::TypeInfo {
public:
TypeInfo() = delete;
TypeInfo(const char* name) noexcept;
~TypeInfo() noexcept;
TypeInfo(const TypeInfo&) = delete;
TypeInfo(TypeInfo&&) = delete;
TypeInfo& operator=(const TypeInfo&) = delete;
TypeInfo& operator=(TypeInfo&&) = delete;
virtual void Create(Env&) const noexcept = 0;
virtual std::unique_ptr<File> Deserialize(Env&, Deserializer&) const = 0;
const char* name() const noexcept { return name_; }
private:
const char* name_;
};
class File::Path final {
public:
Path() = default;
Path(std::initializer_list<std::string> terms) noexcept :
terms_(terms.begin(), terms.end()) {
}
Path(std::vector<std::string>&& terms) noexcept : terms_(std::move(terms)) {
}
Path(const Path&) = default;
Path(Path&&) = default;
Path& operator=(const Path&) = default;
Path& operator=(Path&&) = default;
bool operator==(const Path& p) const noexcept { return terms_ == p.terms_; }
bool operator!=(const Path& p) const noexcept { return terms_ != p.terms_; }
static Path Deserialize(Deserializer&);
void Serialize(Serializer&) const noexcept;
static Path Parse(std::string_view);
std::string Stringify() const noexcept;
std::span<const std::string> terms() const noexcept { return terms_; }
const std::string& terms(size_t i) const noexcept { return terms_[i]; }
private:
std::vector<std::string> terms_;
};
class File::NotFoundException : public Exception {
public:
using Exception::Exception;
};
class Context {
public:
using Id = uint64_t;
Context() = delete;
Context(Env&, File::Id, Context::Id = 0) noexcept;
virtual ~Context() noexcept;
virtual void CleanUp() noexcept = 0;
virtual void Abort() noexcept = 0;
virtual size_t GetMemoryUsage() const noexcept = 0;
virtual std::string GetDescription() const noexcept = 0;
Env& env() const noexcept { return *env_; }
File::Id initiator() const noexcept { return initiator_; }
Id id() const noexcept { return id_; }
Id parent() const noexcept { return parent_; }
private:
Env* const env_;
const File::Id initiator_;
const Id id_, parent_;
};
class Env {
public:
class Watcher;
using Task = std::function<void()>;
Env() = delete;
Env(const std::filesystem::path& npath) noexcept : npath_(npath) {
}
virtual ~Env() = default;
Env(const Env&) = delete;
Env(Env&&) = delete;
Env& operator=(const Env&) = delete;
Env& operator=(Env&&) = delete;
virtual File::Id AddFile(File&) noexcept = 0;
virtual File& RemoveFile(File::Id) noexcept = 0;
virtual File& GetFile(File::Id) = 0;
virtual Context::Id AddContext(Context&) noexcept = 0;
virtual Context& RemoveContext(Context::Id) noexcept = 0;
virtual Context& GetContext(Context::Id) = 0;
// thread-safe
virtual void ExecMain(Context::Id, Task&&) noexcept = 0;
virtual void ExecSub(Context::Id, Task&&) noexcept = 0;
virtual void ExecAsync(Context::Id, Task&&) noexcept = 0;
const std::filesystem::path& npath() const noexcept { return npath_; }
private:
std::filesystem::path npath_;
};
} // namespace nf7

201
thirdparty/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,201 @@
include(FetchContent)
if (KINGTAKER_STATIC)
set(BUILD_SHARED_LIBS OFF)
else()
set(BUILD_SHARED_LIBS ON)
endif()
# ---- cereal ----
# repository: https://github.com/USCiLab/cereal
# license : BSD-3
FetchContent_Declare(
cereal
URL "https://github.com/USCiLab/cereal/archive/refs/tags/v1.3.2.zip"
)
function (include_cereal)
set(BUILD_DOC OFF)
set(BUILD_SANDBOX OFF)
set(SKIP_PERFORMANCE_COMPARISON OFF)
FetchContent_MakeAvailable(cereal)
endfunction()
include_cereal()
# ---- GLEW ----
# repository: https://github.com/Perlmint/glew-cmake
# license : Modified BSD License, the Mesa 3-D License (MIT) and the Khronos License (MIT).
FetchContent_Declare(
glew
URL "https://github.com/Perlmint/glew-cmake/archive/refs/tags/glew-cmake-2.2.0.zip"
)
FetchContent_MakeAvailable(glew)
if (KINGTAKER_STATIC)
add_library(glew ALIAS libglew_static)
else()
add_library(glew ALIAS libglew_shared)
endif()
# ---- GLFW ----
# repository: https://github.com/glfw/glfw
# license : zlib
FetchContent_Declare(
glfw
URL "https://github.com/glfw/glfw/archive/refs/tags/3.3.4.zip"
)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(glfw)
# ---- ImGUI (docking branch) ----
# repository: https://github.com/ocornut/imgui/
# license : MIT
FetchContent_Declare(
imgui
URL "https://github.com/ocornut/imgui/archive/9b0c26b0b2adae3ccf66dc9552fae4945d735a0c.zip"
)
FetchContent_Populate(imgui)
add_library(imgui)
target_sources(imgui
PRIVATE
"${imgui_SOURCE_DIR}/imgui.cpp"
"${imgui_SOURCE_DIR}/imgui_demo.cpp"
"${imgui_SOURCE_DIR}/imgui_draw.cpp"
"${imgui_SOURCE_DIR}/imgui_internal.h"
"${imgui_SOURCE_DIR}/imgui_tables.cpp"
"${imgui_SOURCE_DIR}/imgui_widgets.cpp"
"${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp"
"${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp"
"${imgui_SOURCE_DIR}/misc/cpp/imgui_stdlib.cpp"
PUBLIC
"${imgui_SOURCE_DIR}/imgui.h"
"${imgui_SOURCE_DIR}/imstb_rectpack.h"
"${imgui_SOURCE_DIR}/imstb_textedit.h"
"${imgui_SOURCE_DIR}/imstb_truetype.h"
"${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.h"
"${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.h"
"${imgui_SOURCE_DIR}/misc/cpp/imgui_stdlib.h"
)
target_include_directories(imgui SYSTEM
PUBLIC
"${imgui_SOURCE_DIR}"
"${imgui_SOURCE_DIR}/backends"
"${imgui_SOURCE_DIR}/misc/cpp"
)
target_link_libraries(imgui
PRIVATE glfw
)
# ---- ImNodes ----
# repository: https://github.com/rokups/ImNodes
# license : MIT
FetchContent_Declare(
imnodes
URL "https://github.com/rokups/ImNodes/archive/50f845875760517289b27ca265a9ad72057a644c.zip"
)
FetchContent_Populate(imnodes)
add_library(imnodes)
target_link_libraries(imnodes
PRIVATE
imgui
)
target_include_directories(imnodes SYSTEM
PUBLIC
"${imnodes_SOURCE_DIR}"
)
target_sources(imnodes
PUBLIC
"${imnodes_SOURCE_DIR}/ImNodes.h"
PRIVATE
"${imnodes_SOURCE_DIR}/ImNodes.cpp"
)
# ---- ImPlot ----
# repository: https://github.com/epezent/implot
# license : MIT
FetchContent_Declare(
implot
URL "https://github.com/epezent/implot/archive/refs/heads/master.zip"
)
FetchContent_Populate(implot)
add_library(implot)
target_link_libraries(implot
PRIVATE
imgui
)
target_include_directories(implot SYSTEM
PUBLIC
"${implot_SOURCE_DIR}"
)
target_sources(implot
PUBLIC
"${implot_SOURCE_DIR}/implot.h"
"${implot_SOURCE_DIR}/implot_internal.h"
PRIVATE
"${implot_SOURCE_DIR}/implot.cpp"
"${implot_SOURCE_DIR}/implot_items.cpp"
)
# ---- linalg.h ----
# repository: https://github.com/sgorsten/linalg
# license : Unlicense
FetchContent_Declare(
linalg_h
URL "https://github.com/sgorsten/linalg/archive/a3e87da35e32b781a4b6c01cdd5efbe7ae51c737.zip"
)
FetchContent_Populate(linalg_h)
add_library(linalg.h INTERFACE)
target_include_directories(linalg.h SYSTEM
INTERFACE . "${linalg_h_SOURCE_DIR}"
)
target_sources(linalg.h
INTERFACE
"${linalg_h_SOURCE_DIR}/linalg.h"
linalg.hh
)
# ---- luajit ----
# repository: https://github.com/LuaJIT/LuaJIT
# license : MIT
FetchContent_Declare(
luajit
URL "https://github.com/LuaJIT/LuaJIT/archive/1d7b5029c5ba36870d25c67524034d452b761d27.zip"
)
FetchContent_Populate(luajit)
function (include_luajit)
include(luajit.cmake)
endfunction()
include_luajit()
# ---- source_location ----
add_library(source_location INTERFACE)
target_include_directories(source_location SYSTEM INTERFACE .)
target_sources(source_location INTERFACE source_location.hh)

20
thirdparty/linalg.hh vendored Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <imgui.h>
#include <linalg.h>
namespace linalg {
using namespace aliases;
template <>
struct converter<float2, ImVec2> {
float2 operator() (const ImVec2& v) const { return {v.x, v.y}; }
};
template <>
struct converter<ImVec2, float2> {
ImVec2 operator() (const float2& v) const { return {v.x, v.y}; }
};
} // namespace linalg

50
thirdparty/luajit.cmake vendored Normal file
View File

@ -0,0 +1,50 @@
set(src "${luajit_SOURCE_DIR}/src")
if (UNIX)
find_program(MAKE make REQUIRED)
set(lib "${src}/libluajit.a")
add_custom_target(luajit-build
COMMAND
${MAKE} -j BUILDMODE=static CFLAGS=-fPIC
WORKING_DIRECTORY "${luajit_SOURCE_DIR}"
VERBATIM
)
elseif (MINGW)
find_program(MAKE mingw32-make REQUIRED)
set(lib "${src}/libluajit.a")
add_custom_target(luajit-build
COMMAND ${MAKE} -j BUILDMODE=static CFLAGS=-fPIC
WORKING_DIRECTORY "${luajit_SOURCE_DIR}/src"
VERBATIM
)
elseif (MSVC)
set(lib "${src}/lua51.lib")
add_custom_target(luajit-build
COMMAND msvcbuild.bat static
WORKING_DIRECTORY "${luajit_SOURCE_DIR}/src"
VERBATIM
)
else()
message(ERROR "unknown environment")
endif()
add_library(luajit-imported STATIC IMPORTED)
set_target_properties(luajit-imported PROPERTIES
IMPORTED_LOCATION "${lib}"
)
add_dependencies(luajit-imported luajit-build)
add_library(luajit INTERFACE)
target_link_libraries(luajit
INTERFACE luajit-imported $<$<PLATFORM_ID:Linux>:m>
)
target_include_directories(luajit SYSTEM BEFORE
INTERFACE "${src}"
)

49
thirdparty/source_location.hh vendored Normal file
View File

@ -0,0 +1,49 @@
#pragma once
#include <version>
#if defined(__cpp_lib_source_location)
# include <source_location>
#else
#include <cstdint>
namespace std {
// source_location impl for Clang
// reference:
// https://github.com/paweldac/source_location/blob/ff0002f92cdde3576ce02048dd9eb7823cabdc7b/include/source_location/source_location.hpp
struct source_location {
public:
static constexpr source_location current(
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION(),
uint_least32_t line = __builtin_LINE(),
uint_least32_t col = 0) noexcept {
return source_location(file, func, line, col);
}
source_location(const source_location&) = default;
source_location(source_location&&) = default;
source_location& operator=(const source_location&) = default;
source_location& operator=(source_location&&) = default;
constexpr const char* file_name() const noexcept { return file_; }
constexpr const char* function_name() const noexcept { return func_; }
constexpr uint_least32_t line() const noexcept { return line_; }
constexpr std::uint_least32_t column() const noexcept { return col_; }
private:
constexpr source_location(
const char* file, const char* func, uint_least32_t line, uint_least32_t col) noexcept :
file_(file), func_(func), line_(line), col_(col) {
}
const char* file_;
const char* func_;
uint_least32_t line_;
uint_least32_t col_;
};
} // namespace std
#endif