diff --git a/.gitignore b/.gitignore index 24b876e..5533052 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,5 @@ .vscode/ .idea/ -src/Installer/node_modules/ -src/Installer/dist/ -src/Installer/src-tauri/resources/* \ No newline at end of file +src/Neoluma.Compiler/bin +src/Neoluma.Compiler/obj \ No newline at end of file diff --git a/.idea/neoluma.iml b/.idea/neoluma.iml deleted file mode 100644 index 74258b3..0000000 --- a/.idea/neoluma.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/Neoluma.slnx b/Neoluma.slnx new file mode 100644 index 0000000..116d464 --- /dev/null +++ b/Neoluma.slnx @@ -0,0 +1,5 @@ + + + + + diff --git a/build.bat b/build.bat deleted file mode 100644 index 2b5ea1f..0000000 --- a/build.bat +++ /dev/null @@ -1,63 +0,0 @@ -@echo off -setlocal EnableExtensions -for /f %%A in ('echo prompt $E ^| cmd') do set "ESC=%%A" - -set "MODE=%~1" -if "%MODE%"=="" set "MODE=release" - -set "CFG_PRESET=release-ninja" -set "BUILD_PRESET=release" -set "CONFIG=Release" - -if /I "%MODE%"=="debug" ( - set "CFG_PRESET=debug-ninja" - set "BUILD_PRESET=debug" - set "CONFIG=Debug" -) - -echo %ESC%[38;2;232;75;133m[INFO]%ESC%[0m Configure preset: %CFG_PRESET% -echo %ESC%[38;2;232;75;133m[INFO]%ESC%[0m Build preset: %BUILD_PRESET% - -echo %ESC%[38;2;232;75;133m[INFO]%ESC%[0m Configuring... -cmake --preset "%CFG_PRESET%" -if errorlevel 1 goto :cfg_fail - -goto :build - -:build -echo %ESC%[38;2;232;75;133m[INFO]%ESC%[0m Building neoluma... -cmake --build --preset "%BUILD_PRESET%" --target install -if errorlevel 1 goto :build_fail -echo %ESC%[38;2;232;75;133m[INFO]%ESC%[0m Building payload... -cmake --build --preset "%BUILD_PRESET%" --target payload -if errorlevel 1 goto :build_fail -goto :after_build - -:after_build -set "EXE=.build\.executables\%CONFIG%\neoluma.exe" -set "RUNTIME=.build\.runtime\%CONFIG%\" -if exist "%EXE%" ( - echo %ESC%[38;2;117;255;135m[SUCCESS]%ESC%[0m Built: %EXE% -) else ( - echo %ESC%[38;2;255;80;80m[ERROR]%ESC%[0m Can't find built exe at: %EXE% - exit /b 1 -) -if exist "%RUNTIME%" ( - echo %ESC%[38;2;117;255;135m[SUCCESS]%ESC%[0m Runtime built at: %RUNTIME% -) else ( - echo %ESC%[38;2;255;80;80m[ERROR]%ESC%[0m Can't find built runtime at: %RUNTIME% - exit /b 1 -) -goto :done - -:cfg_fail -echo %ESC%[38;2;255;80;80m[ERROR]%ESC%[0m CMake configure failed. -exit /b 1 - -:build_fail -echo %ESC%[38;2;255;80;80m[ERROR]%ESC%[0m Build failed. -exit /b 1 - -:done -echo %ESC%[38;2;117;255;135m[DONE]%ESC%[0m -exit /b 0 \ No newline at end of file diff --git a/CMakeLists.txt b/deprecated/CMakeLists.txt similarity index 100% rename from CMakeLists.txt rename to deprecated/CMakeLists.txt diff --git a/CMakePresets.json b/deprecated/CMakePresets.json similarity index 100% rename from CMakePresets.json rename to deprecated/CMakePresets.json diff --git a/build.sh b/deprecated/build.sh similarity index 100% rename from build.sh rename to deprecated/build.sh diff --git a/crowdin.yml b/deprecated/crowdin.yml similarity index 100% rename from crowdin.yml rename to deprecated/crowdin.yml diff --git a/resources/app.icns b/deprecated/resources/app.icns similarity index 100% rename from resources/app.icns rename to deprecated/resources/app.icns diff --git a/resources/app.ico b/deprecated/resources/app.ico similarity index 100% rename from resources/app.ico rename to deprecated/resources/app.ico diff --git a/resources/app.rc b/deprecated/resources/app.rc similarity index 100% rename from resources/app.rc rename to deprecated/resources/app.rc diff --git a/src/CLI/CLI.cpp b/deprecated/src/CLI/CLI.cpp similarity index 100% rename from src/CLI/CLI.cpp rename to deprecated/src/CLI/CLI.cpp diff --git a/src/CLI/CLIHelperFunctions.cpp b/deprecated/src/CLI/CLIHelperFunctions.cpp similarity index 100% rename from src/CLI/CLIHelperFunctions.cpp rename to deprecated/src/CLI/CLIHelperFunctions.cpp diff --git a/src/CLI/CLIHelperFunctions.hpp b/deprecated/src/CLI/CLIHelperFunctions.hpp similarity index 100% rename from src/CLI/CLIHelperFunctions.hpp rename to deprecated/src/CLI/CLIHelperFunctions.hpp diff --git a/src/Core/Backend/Codegen/filler b/deprecated/src/Core/Backend/Codegen/filler similarity index 100% rename from src/Core/Backend/Codegen/filler rename to deprecated/src/Core/Backend/Codegen/filler diff --git a/src/Core/Compiler.cpp b/deprecated/src/Core/Compiler.cpp similarity index 100% rename from src/Core/Compiler.cpp rename to deprecated/src/Core/Compiler.cpp diff --git a/src/Core/Compiler.hpp b/deprecated/src/Core/Compiler.hpp similarity index 100% rename from src/Core/Compiler.hpp rename to deprecated/src/Core/Compiler.hpp diff --git a/src/Core/Extras/ErrorManager/ErrorManager.cpp b/deprecated/src/Core/Extras/ErrorManager/ErrorManager.cpp similarity index 100% rename from src/Core/Extras/ErrorManager/ErrorManager.cpp rename to deprecated/src/Core/Extras/ErrorManager/ErrorManager.cpp diff --git a/src/Core/Extras/ErrorManager/ErrorManager.hpp b/deprecated/src/Core/Extras/ErrorManager/ErrorManager.hpp similarity index 100% rename from src/Core/Extras/ErrorManager/ErrorManager.hpp rename to deprecated/src/Core/Extras/ErrorManager/ErrorManager.hpp diff --git a/src/Core/Extras/LangPacks/filler b/deprecated/src/Core/Extras/LangPacks/filler similarity index 100% rename from src/Core/Extras/LangPacks/filler rename to deprecated/src/Core/Extras/LangPacks/filler diff --git a/src/Core/Extras/ProjectManager/ProjectManager.hpp b/deprecated/src/Core/Extras/ProjectManager/ProjectManager.hpp similarity index 100% rename from src/Core/Extras/ProjectManager/ProjectManager.hpp rename to deprecated/src/Core/Extras/ProjectManager/ProjectManager.hpp diff --git a/src/Core/Frontend/Lexer/Lexer.cpp b/deprecated/src/Core/Frontend/Lexer/Lexer.cpp similarity index 100% rename from src/Core/Frontend/Lexer/Lexer.cpp rename to deprecated/src/Core/Frontend/Lexer/Lexer.cpp diff --git a/src/Core/Frontend/Lexer/Lexer.hpp b/deprecated/src/Core/Frontend/Lexer/Lexer.hpp similarity index 100% rename from src/Core/Frontend/Lexer/Lexer.hpp rename to deprecated/src/Core/Frontend/Lexer/Lexer.hpp diff --git a/src/Core/Frontend/Nodes.cpp b/deprecated/src/Core/Frontend/Nodes.cpp similarity index 100% rename from src/Core/Frontend/Nodes.cpp rename to deprecated/src/Core/Frontend/Nodes.cpp diff --git a/src/Core/Frontend/Nodes.hpp b/deprecated/src/Core/Frontend/Nodes.hpp similarity index 100% rename from src/Core/Frontend/Nodes.hpp rename to deprecated/src/Core/Frontend/Nodes.hpp diff --git a/src/Core/Frontend/Orchestrator/Orchestrator.cpp b/deprecated/src/Core/Frontend/Orchestrator/Orchestrator.cpp similarity index 100% rename from src/Core/Frontend/Orchestrator/Orchestrator.cpp rename to deprecated/src/Core/Frontend/Orchestrator/Orchestrator.cpp diff --git a/src/Core/Frontend/Orchestrator/Orchestrator.hpp b/deprecated/src/Core/Frontend/Orchestrator/Orchestrator.hpp similarity index 100% rename from src/Core/Frontend/Orchestrator/Orchestrator.hpp rename to deprecated/src/Core/Frontend/Orchestrator/Orchestrator.hpp diff --git a/src/Core/Frontend/Parser/ASTBuilder.hpp b/deprecated/src/Core/Frontend/Parser/ASTBuilder.hpp similarity index 100% rename from src/Core/Frontend/Parser/ASTBuilder.hpp rename to deprecated/src/Core/Frontend/Parser/ASTBuilder.hpp diff --git a/src/Core/Frontend/Parser/Parser.cpp b/deprecated/src/Core/Frontend/Parser/Parser.cpp similarity index 100% rename from src/Core/Frontend/Parser/Parser.cpp rename to deprecated/src/Core/Frontend/Parser/Parser.cpp diff --git a/src/Core/Frontend/Parser/Parser.hpp b/deprecated/src/Core/Frontend/Parser/Parser.hpp similarity index 100% rename from src/Core/Frontend/Parser/Parser.hpp rename to deprecated/src/Core/Frontend/Parser/Parser.hpp diff --git a/src/Core/Frontend/SemanticAnalysis/SemanticAnalysis.cpp b/deprecated/src/Core/Frontend/SemanticAnalysis/SemanticAnalysis.cpp similarity index 100% rename from src/Core/Frontend/SemanticAnalysis/SemanticAnalysis.cpp rename to deprecated/src/Core/Frontend/SemanticAnalysis/SemanticAnalysis.cpp diff --git a/src/Core/Frontend/SemanticAnalysis/SemanticAnalysis.hpp b/deprecated/src/Core/Frontend/SemanticAnalysis/SemanticAnalysis.hpp similarity index 100% rename from src/Core/Frontend/SemanticAnalysis/SemanticAnalysis.hpp rename to deprecated/src/Core/Frontend/SemanticAnalysis/SemanticAnalysis.hpp diff --git a/src/Core/Frontend/Token.cpp b/deprecated/src/Core/Frontend/Token.cpp similarity index 100% rename from src/Core/Frontend/Token.cpp rename to deprecated/src/Core/Frontend/Token.cpp diff --git a/src/Core/Frontend/Token.hpp b/deprecated/src/Core/Frontend/Token.hpp similarity index 100% rename from src/Core/Frontend/Token.hpp rename to deprecated/src/Core/Frontend/Token.hpp diff --git a/src/Core/Middleend/IRGenerator/IRGenerator.cpp b/deprecated/src/Core/Middleend/IRGenerator/IRGenerator.cpp similarity index 100% rename from src/Core/Middleend/IRGenerator/IRGenerator.cpp rename to deprecated/src/Core/Middleend/IRGenerator/IRGenerator.cpp diff --git a/src/Core/Middleend/IRGenerator/IRGenerator.hpp b/deprecated/src/Core/Middleend/IRGenerator/IRGenerator.hpp similarity index 100% rename from src/Core/Middleend/IRGenerator/IRGenerator.hpp rename to deprecated/src/Core/Middleend/IRGenerator/IRGenerator.hpp diff --git a/src/Core/Middleend/Optimizer/filler b/deprecated/src/Core/Middleend/Optimizer/filler similarity index 100% rename from src/Core/Middleend/Optimizer/filler rename to deprecated/src/Core/Middleend/Optimizer/filler diff --git a/src/Libraries/Json/Json.cpp b/deprecated/src/Libraries/Json/Json.cpp similarity index 100% rename from src/Libraries/Json/Json.cpp rename to deprecated/src/Libraries/Json/Json.cpp diff --git a/src/Libraries/Json/Json.hpp b/deprecated/src/Libraries/Json/Json.hpp similarity index 100% rename from src/Libraries/Json/Json.hpp rename to deprecated/src/Libraries/Json/Json.hpp diff --git a/src/Libraries/Json/JsonGet.hpp b/deprecated/src/Libraries/Json/JsonGet.hpp similarity index 100% rename from src/Libraries/Json/JsonGet.hpp rename to deprecated/src/Libraries/Json/JsonGet.hpp diff --git a/src/Libraries/Localization/Localization.cpp b/deprecated/src/Libraries/Localization/Localization.cpp similarity index 100% rename from src/Libraries/Localization/Localization.cpp rename to deprecated/src/Libraries/Localization/Localization.cpp diff --git a/src/Libraries/Localization/Localization.hpp b/deprecated/src/Libraries/Localization/Localization.hpp similarity index 100% rename from src/Libraries/Localization/Localization.hpp rename to deprecated/src/Libraries/Localization/Localization.hpp diff --git a/src/Libraries/Paths/Paths.cpp b/deprecated/src/Libraries/Paths/Paths.cpp similarity index 100% rename from src/Libraries/Paths/Paths.cpp rename to deprecated/src/Libraries/Paths/Paths.cpp diff --git a/src/Libraries/Paths/Paths.hpp b/deprecated/src/Libraries/Paths/Paths.hpp similarity index 100% rename from src/Libraries/Paths/Paths.hpp rename to deprecated/src/Libraries/Paths/Paths.hpp diff --git a/src/Libraries/Toml/Toml.cpp b/deprecated/src/Libraries/Toml/Toml.cpp similarity index 100% rename from src/Libraries/Toml/Toml.cpp rename to deprecated/src/Libraries/Toml/Toml.cpp diff --git a/src/Libraries/Toml/Toml.hpp b/deprecated/src/Libraries/Toml/Toml.hpp similarity index 100% rename from src/Libraries/Toml/Toml.hpp rename to deprecated/src/Libraries/Toml/Toml.hpp diff --git a/src/main.cpp b/deprecated/src/main.cpp similarity index 100% rename from src/main.cpp rename to deprecated/src/main.cpp diff --git a/tests/.gitignore b/deprecated/tests/.gitignore similarity index 100% rename from tests/.gitignore rename to deprecated/tests/.gitignore diff --git a/tests/README.md b/deprecated/tests/README.md similarity index 100% rename from tests/README.md rename to deprecated/tests/README.md diff --git a/tests/cases/orchestrator/invalid/empty_project/expect.json b/deprecated/tests/cases/orchestrator/invalid/empty_project/expect.json similarity index 100% rename from tests/cases/orchestrator/invalid/empty_project/expect.json rename to deprecated/tests/cases/orchestrator/invalid/empty_project/expect.json diff --git a/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/bar.nm b/deprecated/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/bar.nm similarity index 100% rename from tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/bar.nm rename to deprecated/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/bar.nm diff --git a/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/expect.json b/deprecated/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/expect.json similarity index 100% rename from tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/expect.json rename to deprecated/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/expect.json diff --git a/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/foo.nm b/deprecated/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/foo.nm similarity index 100% rename from tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/foo.nm rename to deprecated/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/foo.nm diff --git a/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/main.nm b/deprecated/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/main.nm similarity index 100% rename from tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/main.nm rename to deprecated/tests/cases/orchestrator/invalid/import_alias_conflict_native_resolved/main.nm diff --git a/tests/cases/orchestrator/invalid/no_entrypoint/expect.json b/deprecated/tests/cases/orchestrator/invalid/no_entrypoint/expect.json similarity index 100% rename from tests/cases/orchestrator/invalid/no_entrypoint/expect.json rename to deprecated/tests/cases/orchestrator/invalid/no_entrypoint/expect.json diff --git a/tests/cases/orchestrator/invalid/no_entrypoint/main.nm b/deprecated/tests/cases/orchestrator/invalid/no_entrypoint/main.nm similarity index 100% rename from tests/cases/orchestrator/invalid/no_entrypoint/main.nm rename to deprecated/tests/cases/orchestrator/invalid/no_entrypoint/main.nm diff --git a/tests/cases/parser/invalid/malformed_array/expect.json b/deprecated/tests/cases/parser/invalid/malformed_array/expect.json similarity index 100% rename from tests/cases/parser/invalid/malformed_array/expect.json rename to deprecated/tests/cases/parser/invalid/malformed_array/expect.json diff --git a/tests/cases/parser/invalid/malformed_array/main.nm b/deprecated/tests/cases/parser/invalid/malformed_array/main.nm similarity index 100% rename from tests/cases/parser/invalid/malformed_array/main.nm rename to deprecated/tests/cases/parser/invalid/malformed_array/main.nm diff --git a/tests/cases/parser/invalid/malformed_dict/expect.json b/deprecated/tests/cases/parser/invalid/malformed_dict/expect.json similarity index 100% rename from tests/cases/parser/invalid/malformed_dict/expect.json rename to deprecated/tests/cases/parser/invalid/malformed_dict/expect.json diff --git a/tests/cases/parser/invalid/malformed_dict/main.nm b/deprecated/tests/cases/parser/invalid/malformed_dict/main.nm similarity index 100% rename from tests/cases/parser/invalid/malformed_dict/main.nm rename to deprecated/tests/cases/parser/invalid/malformed_dict/main.nm diff --git a/tests/cases/parser/invalid/malformed_set/expect.json b/deprecated/tests/cases/parser/invalid/malformed_set/expect.json similarity index 100% rename from tests/cases/parser/invalid/malformed_set/expect.json rename to deprecated/tests/cases/parser/invalid/malformed_set/expect.json diff --git a/tests/cases/parser/invalid/malformed_set/main.nm b/deprecated/tests/cases/parser/invalid/malformed_set/main.nm similarity index 100% rename from tests/cases/parser/invalid/malformed_set/main.nm rename to deprecated/tests/cases/parser/invalid/malformed_set/main.nm diff --git a/tests/cases/parser/valid/decorator_entry/expect.json b/deprecated/tests/cases/parser/valid/decorator_entry/expect.json similarity index 100% rename from tests/cases/parser/valid/decorator_entry/expect.json rename to deprecated/tests/cases/parser/valid/decorator_entry/expect.json diff --git a/tests/cases/parser/valid/decorator_entry/main.nm b/deprecated/tests/cases/parser/valid/decorator_entry/main.nm similarity index 100% rename from tests/cases/parser/valid/decorator_entry/main.nm rename to deprecated/tests/cases/parser/valid/decorator_entry/main.nm diff --git a/tests/cases/semantic/invalid/break_outside_loop/expect.json b/deprecated/tests/cases/semantic/invalid/break_outside_loop/expect.json similarity index 100% rename from tests/cases/semantic/invalid/break_outside_loop/expect.json rename to deprecated/tests/cases/semantic/invalid/break_outside_loop/expect.json diff --git a/tests/cases/semantic/invalid/break_outside_loop/main.nm b/deprecated/tests/cases/semantic/invalid/break_outside_loop/main.nm similarity index 100% rename from tests/cases/semantic/invalid/break_outside_loop/main.nm rename to deprecated/tests/cases/semantic/invalid/break_outside_loop/main.nm diff --git a/tests/cases/semantic/invalid/const_reassignment/expect.json b/deprecated/tests/cases/semantic/invalid/const_reassignment/expect.json similarity index 100% rename from tests/cases/semantic/invalid/const_reassignment/expect.json rename to deprecated/tests/cases/semantic/invalid/const_reassignment/expect.json diff --git a/tests/cases/semantic/invalid/const_reassignment/main.nm b/deprecated/tests/cases/semantic/invalid/const_reassignment/main.nm similarity index 100% rename from tests/cases/semantic/invalid/const_reassignment/main.nm rename to deprecated/tests/cases/semantic/invalid/const_reassignment/main.nm diff --git a/tests/cases/semantic/invalid/continue_outside_loop/expect.json b/deprecated/tests/cases/semantic/invalid/continue_outside_loop/expect.json similarity index 100% rename from tests/cases/semantic/invalid/continue_outside_loop/expect.json rename to deprecated/tests/cases/semantic/invalid/continue_outside_loop/expect.json diff --git a/tests/cases/semantic/invalid/continue_outside_loop/main.nm b/deprecated/tests/cases/semantic/invalid/continue_outside_loop/main.nm similarity index 100% rename from tests/cases/semantic/invalid/continue_outside_loop/main.nm rename to deprecated/tests/cases/semantic/invalid/continue_outside_loop/main.nm diff --git a/tests/cases/semantic/invalid/duplicate_parameter/expect.json b/deprecated/tests/cases/semantic/invalid/duplicate_parameter/expect.json similarity index 100% rename from tests/cases/semantic/invalid/duplicate_parameter/expect.json rename to deprecated/tests/cases/semantic/invalid/duplicate_parameter/expect.json diff --git a/tests/cases/semantic/invalid/duplicate_parameter/main.nm b/deprecated/tests/cases/semantic/invalid/duplicate_parameter/main.nm similarity index 100% rename from tests/cases/semantic/invalid/duplicate_parameter/main.nm rename to deprecated/tests/cases/semantic/invalid/duplicate_parameter/main.nm diff --git a/tests/cases/semantic/invalid/return_outside_function/expect.json b/deprecated/tests/cases/semantic/invalid/return_outside_function/expect.json similarity index 100% rename from tests/cases/semantic/invalid/return_outside_function/expect.json rename to deprecated/tests/cases/semantic/invalid/return_outside_function/expect.json diff --git a/tests/cases/semantic/invalid/return_outside_function/main.nm b/deprecated/tests/cases/semantic/invalid/return_outside_function/main.nm similarity index 100% rename from tests/cases/semantic/invalid/return_outside_function/main.nm rename to deprecated/tests/cases/semantic/invalid/return_outside_function/main.nm diff --git a/tests/cases/semantic/invalid/undefined_function/expect.json b/deprecated/tests/cases/semantic/invalid/undefined_function/expect.json similarity index 100% rename from tests/cases/semantic/invalid/undefined_function/expect.json rename to deprecated/tests/cases/semantic/invalid/undefined_function/expect.json diff --git a/tests/cases/semantic/invalid/undefined_function/main.nm b/deprecated/tests/cases/semantic/invalid/undefined_function/main.nm similarity index 100% rename from tests/cases/semantic/invalid/undefined_function/main.nm rename to deprecated/tests/cases/semantic/invalid/undefined_function/main.nm diff --git a/tests/cases/semantic/invalid/undefined_variable/expect.json b/deprecated/tests/cases/semantic/invalid/undefined_variable/expect.json similarity index 100% rename from tests/cases/semantic/invalid/undefined_variable/expect.json rename to deprecated/tests/cases/semantic/invalid/undefined_variable/expect.json diff --git a/tests/cases/semantic/invalid/undefined_variable/main.nm b/deprecated/tests/cases/semantic/invalid/undefined_variable/main.nm similarity index 100% rename from tests/cases/semantic/invalid/undefined_variable/main.nm rename to deprecated/tests/cases/semantic/invalid/undefined_variable/main.nm diff --git a/tests/runner/testrunner.py b/deprecated/tests/runner/testrunner.py similarity index 100% rename from tests/runner/testrunner.py rename to deprecated/tests/runner/testrunner.py diff --git a/example.nm b/example.nm deleted file mode 100644 index af13346..0000000 --- a/example.nm +++ /dev/null @@ -1,134 +0,0 @@ -#unsafe - // Marks the code as unsafe for low-level operations - -// Line comment -/* - Block comment - spanning multiple lines -*/ - -// Variables -a = 20 -b: string = "Hello!" // Type is optional -const c = 42; - -myarray = [1, 2, 3] -mydict = {"x": 1, "y": 2} -myset = (true, "apple", 1.5) -mybool = false -nullable: int = null - -// Enums and Interfaces -enum Color { Red, Green, Blue } -interface IShape { name: string, area: float } - -// Class and method declaration -class Animal { - init() {} - - public fn speak() { - print("Sound") - } -} - -class Dog <- Animal { - @override - public static fn speak() { - print("Bark") - } -} - -// Lambda and concise syntax -lambda x, y: x + y -(x, y) => x * y - -''' -Entry point of program -''' -public function main(args: string[], number) { - print("Hello, ${args[0]}!") - - result = add(10, 5) - print("Sum: ${result}") -} - -private fn add(a, b) -> int { - return a + b -} - -public fn subtract(a, b) -> int => a - b - -// Unsafe memory access -#import "memory" - -ptr = &map(memory.allocate(4 * size(int))) -*ptr = 123 -print(*ptr) -memory.free(ptr) - -// Imports from Neoluma modules -#import "math" -#import "random" as rnd - -num = rnd.random(1, 100) -print(num) - -a = input("Say something: ") -with open("log.txt", "w") as file { - file.write(a) -} - -// Control flow -for (i in range(5)) { - print(i) -} - -while (true) { - break -} - -if (num > 50) { - print("Big number") -} else { - print("Small number") -} - -switch (num) { - case 1: - print("One") - case 2: - print("Two") - default: - print("Other") -} - -// Namespace -namespace app.tools - -// Generators (list comprehension) -squares = [x * x for x in range(10)] - -// Importing external language pack -#import "cpp:mathlib" as math - -public fn calc() -> int { - return math.sqrt(144) -} - -// Try/catch/throw -try { - risky() -} catch (err) { - print("Error: ${err}") - throw err -} - -fn risky() -> result { - return result.error("Oops!") -} - -// Decorator usage -@decorator -fn decorated_func() { - print("I'm decorated!") -} diff --git a/run.bat b/run.bat deleted file mode 100644 index 5dcd372..0000000 --- a/run.bat +++ /dev/null @@ -1 +0,0 @@ -.\.build\.runtime\Debug\bin\neoluma.exe check --project "TestProject/testproject.nlp" \ No newline at end of file diff --git a/run.ps1 b/run.ps1 new file mode 100644 index 0000000..a21e258 --- /dev/null +++ b/run.ps1 @@ -0,0 +1 @@ +dotnet build && .\src\Neoluma.Compiler\bin\Debug\net10.0\neoluma.exe check --project "TestProject/TestProject.nlp" \ No newline at end of file diff --git a/src/CLI/CLI.hpp b/src/CLI/CLI.hpp deleted file mode 100644 index 6580735..0000000 --- a/src/CLI/CLI.hpp +++ /dev/null @@ -1,180 +0,0 @@ -#pragma once -#include "CLIHelperFunctions.hpp" -#include "HelperFunctions.hpp" - -#include "Libraries/Asker/Asker.hpp" - -#include -#include -#include - -// CLIArgs is a struct that allows me to parse CLI arguments -struct CLIArgs { - std::string command; // parses commands like new, build, run, check and help - std::map options; // parses --arguments with_values.nlp - std::vector positional; // anything that is not an --argument -}; - -// Argument parsing -CLIArgs parseArgs(int argc, char** argv); - -// ==== Main functions ==== - -void build(const std::string& nlpFile); // Compiles Neoluma program into a binary executable -void run(const std::string& nlpFile); // Runs the code interpreted way. Useful for testing. -void check(const std::string& nlpFile, bool jsonOutput = false); // Checks code on errors. Doesn't generate any binaries -void createProject(ProjectConfig config); // Creates a project -void createProject(); // Creates a project (Without ProjectConfig) - -// Help function that just tells details about compiler and it's CLI. -void printHelp(); - -// Licenses templates -class Licenses { - static inline const std::string MIT_TEMPLATE = { - #embed "LicenseTemplates/MIT.txt" - }; - static inline const std::string APACHE_TEMPLATE = { - #embed "LicenseTemplates/Apache.txt" - }; - static inline const std::string GNUGPLv3_TEMPLATE = { - #embed "LicenseTemplates/GNUGPLv3.txt" - }; - static inline const std::string BSDv2Simplified_TEMPLATE = { - #embed "LicenseTemplates/BSDv2Simplified.txt" - }; - static inline const std::string BSDv3NewRevised_TEMPLATE = { - #embed "LicenseTemplates/BSDv3NewRevised.txt" - }; - static inline const std::string BoostV1_TEMPLATE = { - #embed "LicenseTemplates/BoostV1.txt" - }; - static inline const std::string CC0v1_TEMPLATE = { - #embed "LicenseTemplates/CC0v1.txt" - }; - static inline const std::string EclipseV2_TEMPLATE = { - #embed "LicenseTemplates/EclipseV2.txt" - }; - static inline const std::string GNUAGPLv3_TEMPLATE = { - #embed "LicenseTemplates/GNUAGPLv3.txt" - }; - static inline const std::string GNUGPLv2_TEMPLATE = { - #embed "LicenseTemplates/GNUGPLv2.txt" - }; - static inline const std::string GNULGPLv2_1_TEMPLATE = { - #embed "LicenseTemplates/GNULGPLv2_1.txt" - }; - static inline const std::string MozillaV2_TEMPLATE = { - #embed "LicenseTemplates/MozillaV2.txt" - }; - static inline const std::string Unlicense_TEMPLATE = { - #embed "LicenseTemplates/Unlicense.txt" - }; -public: - // Available identifiers: mit, apache, gpl2, gpl3, bsd2, bsd3, boost, cc0, eclipse, agpl, lgpl, mozilla, unlicense. Otherwise returns specific message - static std::string checkLicense(ProjectConfig config, License license) { - if (license == License::MIT) return MIT(listAuthors(config.author)); - if (license == License::Apache) return Apachev2(); - if (license == License::GPL2) return GNUGPLv2(); - if (license == License::GPL3) return GNUGPLv3(); - if (license == License::BSD2) return BSDv2Simplified(listAuthors(config.author)); - if (license == License::BSD3) return BSDv3NewRevised(listAuthors(config.author)); - if (license == License::Boost) return Boostv1(); - if (license == License::CC0) return CC0v1(); - if (license == License::Eclipse) return Eclipsev2(); - if (license == License::AGPL) return GNUAGPLv3(); - if (license == License::LGPL) return GNULGPLv2_1(); - if (license == License::Mozilla) return Mozillav2(); - if (license == License::Unlicense) return Unlicense(); - return "We haven't found licenses for your case. Please delete this text and insert your license here, or delete the license file completely."; - } - - /* A short and simple permissive license with conditions only requiring preservation of copyright and license notices. - Licensed works, modifications, and larger works may be distributed under different terms and without source code. */ - static std::string MIT(std::string author) { - const auto year = formatStr("{:%Y}", std::chrono::system_clock::now()); - return formatStr(MIT_TEMPLATE, year, author); - } - - /* A permissive license whose main conditions require preservation of copyright and license notices. - Contributors provide an express grant of patent rights. Licensed works, modifications, and larger works may be - distributed under different terms and without source code. */ - static std::string Apachev2() { - return APACHE_TEMPLATE; - } - - /*Permissions of this strong copyleft license are conditioned on making available complete source code of licensed works - and modifications, which include larger works using a licensed workunder the same license. Copyright and license notices - must be preserved. Contributors provide an express grant of patent rights.*/ - static std::string GNUGPLv3() { - return GNUGPLv3_TEMPLATE; - } - - /*A permissive license that comes in two variants, the BSD 2-Clause and BSD 3-Clause. - Both have very minute differences to the MIT license.*/ - static std::string BSDv2Simplified(std::string author){ - const auto year = formatStr("{:%Y}", std::chrono::system_clock::now()); - return formatStr(BSDv2Simplified_TEMPLATE, year, author); - } - - /*A permissive license similar to the BSD 2-Clause License, but with a 3rd clause that prohibits others from using the name - of the copyright holder or its contributors to promote derived products without written consent.*/ - static std::string BSDv3NewRevised(std::string author) { - const auto year = formatStr("{:%Y}", std::chrono::system_clock::now()); - return formatStr(BSDv3NewRevised_TEMPLATE, year, author); - } - - /*A simple permissive license only requiring preservation of copyright and license notices for source (and not binary) distribution. - Licensed works, modifications, and larger works may be distributed under different terms and without source code.*/ - static std::string Boostv1() { - return BoostV1_TEMPLATE; - } - - /*The Creative Commons CC0 Public Domain Dedication waives copyright interest in a work you've created and dedicates - it to the world-wide public domain. Use CC0 to opt out of copyright entirely and ensure your work has the widest reach. - As with the Unlicense and typical software licenses, CC0 disclaims warranties. CC0 is very similar to the Unlicense.*/ - static std::string CC0v1() { - return CC0v1_TEMPLATE; - } - - /*This commercially-friendly copyleft license provides the ability to commercially license binaries; a modern royalty-free patent - license grant; and the ability for linked works to use other licenses, including commercial ones.*/ - static std::string Eclipsev2() { - return EclipseV2_TEMPLATE; - } - - /*Permissions of this strongest copyleft license are conditioned on making available complete source code of licensed works - and modifications, which include larger works using a licensed work, under the same license. Copyright and license notices - must be preserved. Contributors provide an express grant of patent rights. When a modified version is used to provide - a service over a network, the complete source code of the modified version must be made available.*/ - static std::string GNUAGPLv3() { - return GNUAGPLv3_TEMPLATE; - } - - /* The GNU GPL is the most widely used free software license and has a strong copyleft requirement. - When distributing derived works, the source code of the work must be made available under the same license. - There are multiple variants of the GNU GPL, each with different requirements. */ - static std::string GNUGPLv2() { - return GNUGPLv2_TEMPLATE; - } - - /* Primarily used for software libraries, the GNU LGPL requires that derived works be licensed under the same license, but works that - only link to it do not fall under this restriction. There are two commonly used versions of the GNU LGPL.*/ - static std::string GNULGPLv2_1() { - return GNULGPLv2_1_TEMPLATE; - } - - /*Permissions of this weak copyleft license are conditioned on making available source code of licensed files and modifications of those - files under the same license (or in certain cases, one of the GNU licenses). Copyright and license notices must be preserved. - Contributors provide an express grant of patent rights. However, a larger work using the licensed work may be distributed under - different terms and without source code for files added in the larger work.*/ - static std::string Mozillav2() { - return MozillaV2_TEMPLATE; - } - - /*A license with no conditions whatsoever which dedicates works to the public domain. Unlicensed works, modifications, - and larger works may be distributed under different terms and without source code.*/ - static std::string Unlicense() { - return Unlicense_TEMPLATE; - } -}; \ No newline at end of file diff --git a/src/HelperFunctions.cpp b/src/HelperFunctions.cpp deleted file mode 100644 index 2ba1755..0000000 --- a/src/HelperFunctions.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "HelperFunctions.hpp" -#include "Libraries/Color/Color.hpp" -#include -#include -#include - - -// Reads the file -String readFile(const String& filePath) { - std::ifstream file(filePath); - if (!file.is_open()) { - std::println(std::cerr, "{}[Neoluma/HelperFunctions] Failed to open file: {}", Color::TextHex("#ff5050"), filePath); - return ""; - } - std::stringstream buffer; - buffer << file.rdbuf(); - return buffer.str(); -} - -String normalizePath(String path) { - size_t pos = 0; - while ((pos = path.find("\\", pos)) != String::npos) { - path.replace(pos, 1, "/"); - pos += 1; - } - return path; -} \ No newline at end of file diff --git a/src/HelperFunctions.hpp b/src/HelperFunctions.hpp deleted file mode 100644 index e6e3ce7..0000000 --- a/src/HelperFunctions.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -// Alias of std::unique_ptr -template -using MemoryPtr = std::unique_ptr; - -// Alias of std::variant -template -using Option = std::variant; - -template -constexpr bool optionIs(const Option& value) { - return std::holds_alternative(value); -} - -template -constexpr T& getOption(Option& value) { - return std::get(value); -} - -template -constexpr const T& getOption(const Option& value) { - return std::get(value); -} - -template -constexpr T* tryGetOption(Option* value) { - return std::get_if(value); -} - -template -constexpr const T* tryGetOption(const Option* value) { - return std::get_if(value); -} - -template -MemoryPtr makeMemoryPtr(Args&&... args) { - return std::make_unique(std::forward(args)...); -} - -template -MemoryPtr makeSharedPtr(Args&&... args) { - return std::make_shared(std::forward(args)...); -} - -template -MemoryPtr as(MemoryPtr ptr) { - static_assert(std::is_base_of_v, "[Neoluma/HelperFunctions] as(ptr): T must derive from U"); - - if constexpr (std::is_polymorphic_v) { - if (T* casted = dynamic_cast(ptr.get())) { - ptr.release(); - return MemoryPtr(casted); - } - return nullptr; - } else { - return MemoryPtr(static_cast(ptr.release())); - } -} - -// Other -// Reads the file -std::string readFile(const std::string& filePath); - -// turns \\ into / cuz screw how windows is made -std::string normalizePath(const std::string& path); diff --git a/src/Libraries/Asker/Asker.cpp b/src/Libraries/Asker/Asker.cpp deleted file mode 100644 index ee69809..0000000 --- a/src/Libraries/Asker/Asker.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "Asker.hpp" - -#include - -#ifdef _WIN32 -#include - -Key getKey() { - int c = _getch(); - if (c == 13) return ENTER; - if (c == 8) return BACKSPACE; - if (c == 224 || c == 0) { - c = _getch(); - if (c == 72) return UP; - if (c == 80) return DOWN; - } - return NONE; -} - -void enableRaw() {} // do nothing on windows -void disableRaw() {} - -#else -#include -#include -void enableRaw() { - tcgetattr(STDIN_FILENO, &term); - struct termios raw = term; - raw.c_lflag &= ~(ICANON | ECHO); - tcsetattr(STDIN_FILENO, TCSANOW, &raw); -} - -void disableRaw() { - tcsetattr(STDIN_FILENO, TCSAFLUSH, &term); -} - -Key getKey() { - int c = getchar(); - if (c == '\n') return ENTER; - if (c == 127) return BACKSPACE; - if (c == 27) { - char sequence[2]; - if (read(STDIN_FILENO, sequence, 2) == 2 && sequence[0] == '[') { - if (sequence[1] == 'A') return UP; - if (sequence[1] == 'B') return DOWN; - } - } - return NONE; -} -#endif - -void clearBlock(int lines) { - for (int i = 0; i < lines; i++) { - std::cout << "\033[1A"; // up - std::cout << "\033[2K"; // clear whole line - std::cout << "\r"; - } -} - -namespace asker { - std::string input(const std::string& question, bool required) { - std::cout << Color::TextHex("#75b5ff") << ">> " << question << ' ' << Color::TextHex("#ff28e6"); - std::string response; - while (std::getline(std::cin, response)) { - if (required && response.length() == 0) {} - else break; - } - std::cout << Color::Reset; - return response; - } - - bool confirm(const std::string& question) { - bool result = true; - std::string response; - response = input(question + Color::TextHex("#e84b85") + " (y/n) " + Color::TextHex("#ff28e6")); - if (response[0] != 'y' && response[0] != 'Y' && response[0] != '\0' ) result = false; - std::cout << Color::Reset; - return result; - } -} \ No newline at end of file diff --git a/src/Libraries/Asker/Asker.hpp b/src/Libraries/Asker/Asker.hpp deleted file mode 100644 index ac4e164..0000000 --- a/src/Libraries/Asker/Asker.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once -/* -* Asker is an internal Neoluma library for handling CLI input -*/ -#include -#include -#include "../Color/Color.hpp" -enum Key { NONE, UP, DOWN, ENTER, BACKSPACE }; - -#ifdef _WIN32 -#include -Key getKey(); -void enableRaw(); // do nothing on windows -void disableRaw(); -#else -#include -#include -static struct termios term; -void enableRaw(); -void disableRaw(); -Key getKey(); -#endif - -void clearBlock(int lines); - -namespace asker { - constexpr const char* Clear = "\033[0m\033[2J\033[H"; - - std::string input(const std::string& question, bool required=false); - - bool confirm(const std::string& question); - - template - std::string selectList(const std::string& question, const std::string (&options)[n]) { - enableRaw(); - - int pos = 0; - Key key = NONE; - int lines = n + 2; - - while (true) { - clearBlock(lines); - - std::cout << Color::TextHex("#75b5ff") << ">> " << question << '\n'; - - for (int i = 0; i < n; i++) { - if (i == pos) { - std::cout << Color::TextHex("#00ff48ffff") << "> " << Color::TextHex("#ff28e6") << options[i] << '\n'; - } - else { - std::cout << Color::TextHex("#ff28e6") << " " << options[i] << '\n'; - } - } - - key = getKey(); - if (key == UP && pos > 0) pos--; - else if (key == DOWN && pos < n - 1) pos++; - else if (key == ENTER) break; - } - - disableRaw(); - std::cout << Color::Reset << "\n"; - return options[pos]; - } -}; \ No newline at end of file diff --git a/src/Libraries/Color/Color.cpp b/src/Libraries/Color/Color.cpp deleted file mode 100644 index 8e60b55..0000000 --- a/src/Libraries/Color/Color.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "Color.hpp" -#include -#ifdef _WIN32 - #define Neoluma_sscanf sscanf_s -#else - #define Neoluma_sscanf sscanf -#endif - -namespace Color { - std::string TextRGB(uint8_t r, uint8_t g, uint8_t b) { - return std::format("\033[38;2;{};{};{}m", r, g, b); - } - - std::string BackgroundRGB(uint8_t r, uint8_t g, uint8_t b) { - return std::format("\033[48;2;{};{};{}m", r, g, b); - } - - std::string TextHex(const std::string& hex) { - unsigned int r, g, b; - if (hex[0] == '#') { - Neoluma_sscanf(hex.c_str(), "#%02x%02x%02x", &r, &g, &b); - return TextRGB(r, g, b); - } - return ""; - } - - std::string BackgroundHex(const std::string& hex) { - unsigned int r, g, b; - if (hex[0] == '#') { - Neoluma_sscanf(hex.c_str(), "#%02x%02x%02x", &r, &g, &b); - return BackgroundRGB(r, g, b); - } - return ""; - } -} \ No newline at end of file diff --git a/src/Libraries/Color/Color.hpp b/src/Libraries/Color/Color.hpp deleted file mode 100644 index da9a19c..0000000 --- a/src/Libraries/Color/Color.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include - -namespace Color { - std::string TextRGB(uint8_t r, uint8_t g, uint8_t b); - - std::string BackgroundRGB(uint8_t r, uint8_t g, uint8_t b); - - std::string TextHex(const std::string& hex); - - std::string BackgroundHex(const std::string& hex); - - namespace Effect { - constexpr std::string BoldOn = "\033[1m"; - constexpr std::string DimOn = "\033[2m"; - constexpr std::string UnderlineOn = "\033[4m"; - constexpr std::string BlinkOn = "\033[5m"; - constexpr std::string ReverseOn = "\033[7m"; - constexpr std::string HideOn = "\033[8m"; - - constexpr std::string BoldOff = "\033[21m"; - constexpr std::string DimOff = "\033[22m"; - constexpr std::string UnderlineOff = "\033[24m"; - constexpr std::string BlinkOff = "\033[25m"; - constexpr std::string ReverseOff = "\033[27m"; - constexpr std::string HideOff = "\033[28m"; - } - - constexpr std::string Reset = "\033[0m"; -} diff --git a/src/Libraries/Utils/Types/Array.hpp b/src/Libraries/Utils/Types/Array.hpp deleted file mode 100644 index 3b116f1..0000000 --- a/src/Libraries/Utils/Types/Array.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -template -class Array { - std::vector data; -public: - Array() = default; - Array(std::initializer_list values) : data(values) {} - - void add(const T& value) { data.push_back(value); } - void add(T&& value) { data.push_back(std::move(value)); } - std::size_t len() const { return data.size(); } - void clear() { data.clear(); } - T& first() { return data[0]; } - T& last() { return data[data.size() - 1]; } - void reverse() { std::reverse(begin(), end()); } - bool empty() const { return data.empty(); } - T& operator[](std::size_t index) { return data[index]; } - const T& operator[](std::size_t index) const { return data[index]; } - - // evil ass rape functions - auto begin() const { return data.begin(); } - auto end() const { return data.end(); } - auto begin() { return data.begin(); } - auto end() { return data.end(); } -}; diff --git a/src/Libraries/Utils/Types/Hashmap.hpp b/src/Libraries/Utils/Types/Hashmap.hpp deleted file mode 100644 index 83a7c7e..0000000 --- a/src/Libraries/Utils/Types/Hashmap.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -template -class HashMap { - std::unordered_map map; -public: - HashMap() = default; - - void set(K key, V value) { map[key] = value; } - V get(K key) const { return map.at(key); } - const V& get(const K& key) const { return map.at(key); } - V& operator[](K key) { return map[key]; } - - bool contains(K key) const { return map.find(key) != map.end(); } - bool empty() const { return map.empty(); } - void remove(const K& key) { map.erase(key); } - void clear() { map.clear(); } - size_t len() const { return map.size(); } -}; diff --git a/src/Libraries/Utils/Types/String.cpp b/src/Libraries/Utils/Types/String.cpp deleted file mode 100644 index 843c61a..0000000 --- a/src/Libraries/Utils/Types/String.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "String.hpp" - -String::String() = default; -String::String(const char* value) : str(value) {} -String::String(const std::string& value) : str(value) {} -String::String(std::string_view value) : str(value) {} - -String::operator const std::string&() const { return str; } -String::operator std::string&() { return str; } - -String& String::operator=(const std::string& value) { str = value; return *this; } -String& String::operator=(std::string&& value) { str = std::move(value); return *this; } -String& String::operator=(const char* value) { str = value; return *this; } -String& String::operator+=(const std::string& value) { str += value; return *this; } -String& String::operator+=(const char* value) { str += value; return *this; } -String& String::operator+=(char value) { str += value; return *this; } -bool String::operator==(const std::string& value) const { return str == value; } -bool String::operator!=(const std::string& value) const { return str != value; } -char& String::operator[](std::size_t index) { return str[index]; } -const char& String::operator[](std::size_t index) const { return str[index]; } - -std::size_t String::len() const { return str.length(); } -bool String::empty() const { return str.empty(); } -void String::clear() { str.clear(); } - -void String::trim() { str.erase(0, str.find_first_not_of(' ')); } - -Array String::split(char delimiter) const { - Array result; - String current; - for (const char c : str) { - if (c == delimiter) { - current.trim(); - result.add(current); - current.clear(); - } else current += c; - } - current.trim(); - result.add(current); - return result; -} diff --git a/src/Libraries/Utils/Types/String.hpp b/src/Libraries/Utils/Types/String.hpp deleted file mode 100644 index b3bbd0d..0000000 --- a/src/Libraries/Utils/Types/String.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include "Array.hpp" - -class String { - std::string str; - - template - String anyToStr(T&& v) { - std::ostringstream oss; - oss << std::forward(v); - return String(oss.str()); - } - - String formatStrVec(const std::string& value, const Array& args) { - String out; - size_t argCount = 0; - for (size_t i = 0; i < value.size(); i++) { - char c = value[i]; - if (c == '{') { - if (i + 1 >= value.size()) throw std::runtime_error("[Neoluma/String] Invalid '{'"); - char next = value[i + 1]; - if (next == '{') { out += '{'; i++; } - else { - size_t j = i + 1; - - // {} case - if (value[j] == '}') { - if (argCount >= args.len()) throw std::runtime_error("[Neoluma/String] Not enough format arguments"); - out += args[argCount++]; - i = j; - } - // {number} case - else if (isDigit(value[j])) { - size_t index = 0; - - while (j < value.size() && isDigit(value[j])) { - index = index * 10 + (value[j] - '0'); - j++; - } - - if (j >= value.size() || value[j] != '}') throw std::runtime_error("[Neoluma/String] Invalid positional format"); - if (index >= args.len()) throw std::runtime_error("[Neoluma/String] Positional argument out of range"); - - out += args[index]; - i = j; - } - else throw std::runtime_error("[Neoluma/String] Invalid '{'"); - } - } - else if (c == '}') { - if (i + 1 < value.size() && value[i + 1] == '}') { out += '}'; i++; } - else throw std::runtime_error("[Neoluma/String] Invalid '}'"); - } - else out += c; - } - if (argCount < args.len()) throw std::runtime_error("[Neoluma/String] Too many format arguments"); - return out; - } - - bool isDigit(char c) { return c >= '0' && c <= '9'; } -public: - String(); - String(const char* value); - String(const std::string& value); - String(std::string_view value); - // TODO for later: fix this, i absolutely hate how this looks - template - String(const std::string& value, Args&&... args) { - Array collectedArgs = { anyToStr(args)... }; - formatStrVec(value, collectedArgs); - } - String(const std::string& value, const Array& args) { formatStrVec(value, args); } - - String& operator=(const std::string& value); - String& operator=(std::string&& value); - String& operator=(const char* value); - String& operator+=(const std::string& value); - String& operator+=(const char* value); - String& operator+=(char value); - bool operator==(const std::string& value) const; - bool operator!=(const std::string& value) const; - char& operator[](std::size_t index); - const char& operator[](std::size_t index) const; - operator const std::string&() const; - operator std::string&(); - - std::size_t len() const; - bool empty() const; - void clear(); - - void trim(); - Array split(char delimiter) const; -}; - -namespace std { - template<> - struct hash { - size_t operator()(const String& value) const noexcept { return hash()(value); } - }; -} \ No newline at end of file diff --git a/src/Libraries/Utils/Utils.hpp b/src/Libraries/Utils/Utils.hpp deleted file mode 100644 index c128a04..0000000 --- a/src/Libraries/Utils/Utils.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "Types/Array.hpp" -#include "Types/String.hpp" -#include "Types/Hashmap.hpp" \ No newline at end of file diff --git a/src/Neoluma.Compiler/CLI/ArgumentParser.cs b/src/Neoluma.Compiler/CLI/ArgumentParser.cs new file mode 100644 index 0000000..2fcf40f --- /dev/null +++ b/src/Neoluma.Compiler/CLI/ArgumentParser.cs @@ -0,0 +1,34 @@ +namespace Neoluma.CLI; + +/// CLIArgs is a struct that allows me to parse CLI arguments +public struct CLIArgs { + public string command; // parses commands like new, build, run, check and help + public Dictionary options; // parses --arguments with_values.nlp + public List positional; // anything that is not an --argument + + /// Argument parsing + public static CLIArgs parseArgs(string[] args) { + CLIArgs arguments = new CLIArgs(); + if (args.Length > 0) arguments.command = args[0]; + + arguments.options = new(); arguments.positional = new(); + + for (int i = 1; i < args.Length; i++) { + string token = args[i]; + + if (token.StartsWith("--")) { + string key = token.Substring(2); + string value = ""; + + if (i + 1 < args.Length && !args[i + 1].StartsWith("--")) { + value = args[i + 1]; + i++; + } + + arguments.options[key] = value; + } + else arguments.positional.Add(token); + } + return arguments; + } +}; \ No newline at end of file diff --git a/src/Neoluma.Compiler/CLI/CLI.cs b/src/Neoluma.Compiler/CLI/CLI.cs new file mode 100644 index 0000000..3f70297 --- /dev/null +++ b/src/Neoluma.Compiler/CLI/CLI.cs @@ -0,0 +1,57 @@ +using Neoluma.Core.Extras; +using Neoluma.Libraries.Utils; + +namespace Neoluma.CLI; + +public static class CLI { + /// Compiles Neoluma program into target output + public static void build(string nlpFile) {} + /// Runs the code interpreted way. Useful for testing. + public static void run(string nlpFile) {} + /// Checks code on errors. Doesn't generate any binaries + public static void check(string nlpFile, bool jsonOutput = false) {} + /// Creates a project + public static void createProject(ProjectConfig config) {} + /// Creates a project (Without ProjectConfig) + public static void createProject() {} + + /// Help function that just tells details about compiler and it's CLI. + public static void printHelp() {} +} + +class Licenses { + private static string Apache = FileEmbed.readEmbeddedFile("LicenseTemplates.Apache"); + private static string BoostV1 = FileEmbed.readEmbeddedFile("LicenseTemplates.BoostV1"); + private static string BSDv2Simplified = FileEmbed.readEmbeddedFile("LicenseTemplates.BSDv2Simplified"); + private static string BSDv3NewRevised = FileEmbed.readEmbeddedFile("LicenseTemplates.BSDv3NewRevised"); + private static string CC0v1 = FileEmbed.readEmbeddedFile("LicenseTemplates.CC0v1"); + private static string EclipseV2 = FileEmbed.readEmbeddedFile("LicenseTemplates.EclipseV2"); + private static string GNUAGPLv3 = FileEmbed.readEmbeddedFile("LicenseTemplates.GNUAGPLv3"); + private static string GNUGPLv2 = FileEmbed.readEmbeddedFile("LicenseTemplates.GNUGPLv2"); + private static string GNUGPLv3 = FileEmbed.readEmbeddedFile("LicenseTemplates.GNUGPLv3"); + private static string GNULGPLv2_1 = FileEmbed.readEmbeddedFile("LicenseTemplates.GNULGPLv2_1"); + private static string MIT = FileEmbed.readEmbeddedFile("LicenseTemplates.MIT"); + private static string MozillaV2 = FileEmbed.readEmbeddedFile("LicenseTemplates.MozillaV2"); + private static string Unlicense = FileEmbed.readEmbeddedFile("LicenseTemplates.Unlicense"); + + /// Available identifiers: mit, apache, gpl2, gpl3, bsd2, bsd3, boost, cc0, eclipse, agpl, lgpl, mozilla, unlicense. Otherwise returns specific message + public static string getLicenseText(ProjectConfig config, string license) { + switch (config.license) { + case "mit": return String.Format(MIT, DateTime.Today.Year, ProjectConfig.listAuthors(config.author)); + case "apache": return Apache; + case "gpl2": return GNUGPLv2; + case "gpl3": return GNUGPLv3; + case "bsd2": return String.Format(BSDv2Simplified, DateTime.Today.Year, ProjectConfig.listAuthors(config.author)); + case "bsd3": return String.Format(BSDv3NewRevised, DateTime.Today.Year, ProjectConfig.listAuthors(config.author)); + case "boost": return BoostV1; + case "cc0": return CC0v1; + case "eclipse": return EclipseV2; + case "agpl": return GNUAGPLv3; + case "lgpl": return GNULGPLv2_1; + case "mozilla": return MozillaV2; + case "unlicense": return Unlicense; + default: return "We haven't found licenses for your case. Please delete this text and insert your license here, or delete the license file completely."; + } + } +} + diff --git a/src/CLI/LicenseTemplates/Apache.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/Apache.txt similarity index 100% rename from src/CLI/LicenseTemplates/Apache.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/Apache.txt diff --git a/src/CLI/LicenseTemplates/BSDv2Simplified.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/BSDv2Simplified.txt similarity index 100% rename from src/CLI/LicenseTemplates/BSDv2Simplified.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/BSDv2Simplified.txt diff --git a/src/CLI/LicenseTemplates/BSDv3NewRevised.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/BSDv3NewRevised.txt similarity index 100% rename from src/CLI/LicenseTemplates/BSDv3NewRevised.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/BSDv3NewRevised.txt diff --git a/src/CLI/LicenseTemplates/BoostV1.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/BoostV1.txt similarity index 100% rename from src/CLI/LicenseTemplates/BoostV1.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/BoostV1.txt diff --git a/src/CLI/LicenseTemplates/CC0v1.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/CC0v1.txt similarity index 100% rename from src/CLI/LicenseTemplates/CC0v1.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/CC0v1.txt diff --git a/src/CLI/LicenseTemplates/EclipseV2.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/EclipseV2.txt similarity index 100% rename from src/CLI/LicenseTemplates/EclipseV2.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/EclipseV2.txt diff --git a/src/CLI/LicenseTemplates/GNUAGPLv3.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/GNUAGPLv3.txt similarity index 100% rename from src/CLI/LicenseTemplates/GNUAGPLv3.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/GNUAGPLv3.txt diff --git a/src/CLI/LicenseTemplates/GNUGPLv2.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/GNUGPLv2.txt similarity index 100% rename from src/CLI/LicenseTemplates/GNUGPLv2.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/GNUGPLv2.txt diff --git a/src/CLI/LicenseTemplates/GNUGPLv3.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/GNUGPLv3.txt similarity index 100% rename from src/CLI/LicenseTemplates/GNUGPLv3.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/GNUGPLv3.txt diff --git a/src/CLI/LicenseTemplates/GNULGPLv2_1.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/GNULGPLv2_1.txt similarity index 100% rename from src/CLI/LicenseTemplates/GNULGPLv2_1.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/GNULGPLv2_1.txt diff --git a/src/CLI/LicenseTemplates/MIT.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/MIT.txt similarity index 100% rename from src/CLI/LicenseTemplates/MIT.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/MIT.txt diff --git a/src/CLI/LicenseTemplates/MozillaV2.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/MozillaV2.txt similarity index 100% rename from src/CLI/LicenseTemplates/MozillaV2.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/MozillaV2.txt diff --git a/src/CLI/LicenseTemplates/Unlicense.txt b/src/Neoluma.Compiler/CLI/LicenseTemplates/Unlicense.txt similarity index 100% rename from src/CLI/LicenseTemplates/Unlicense.txt rename to src/Neoluma.Compiler/CLI/LicenseTemplates/Unlicense.txt diff --git a/src/Neoluma.Compiler/Core/Compiler.cs b/src/Neoluma.Compiler/Core/Compiler.cs new file mode 100644 index 0000000..d17b94a --- /dev/null +++ b/src/Neoluma.Compiler/Core/Compiler.cs @@ -0,0 +1,25 @@ +namespace Neoluma.Core; + +/// Compiler settings for the project tell the compiler what to set up before building +public class CompilerSettings { + ///Verbose is an option that allows extra keywords, syntactic sugar. Not recommended for people who loves keeping shape of a language. Recommended for people who don't give a heck and love copypasting answers from StackOverflow. + ///
true - enables this option + ///
false - disables this option + public bool verbose = false; + + ///Baremetal is an option that toggles the ability to develop software for bare metal hardware. It disables platform-based ABI (including std) and compiles into binary. + ///
true - enables this option + ///
false - disables this option + public bool baremetal = false; + + public class Memory { + public enum MemoryOptions { None, Rusty, ARC, Default }; + + ///level is an option of Memory class that goes through types of Memory options and, depending on chosen option, will manage the memory in the application the preferred way. + ///
Default - enables default Garbage Collector (Java, C#, others) + ///
ARC - enables Automatic Reference Counter (Python, JS, others) + ///
Rusty - enables Borrow Checker (Rust) + ///
None - No memory management tools (C, C++, maybe others) + public MemoryOptions level = MemoryOptions.Default; + }; +} \ No newline at end of file diff --git a/src/Neoluma.Compiler/Core/Extras/ProjectManager.cs b/src/Neoluma.Compiler/Core/Extras/ProjectManager.cs new file mode 100644 index 0000000..031b1fa --- /dev/null +++ b/src/Neoluma.Compiler/Core/Extras/ProjectManager.cs @@ -0,0 +1,60 @@ +namespace Neoluma.Core.Extras; + +public sealed class PlatformTarget { + private enum Platform { Windows, Linux, MacOS, iOS, Android, Other }; + private Platform platform; + private string arch; // x86_64, arm64, wasm32 + + public string toString() { + string s = arch + "-"; + + switch (platform) { + case Platform.Windows: s += "windows"; break; + case Platform.Linux: s += "linux"; break; + case Platform.MacOS: s += "macos"; break; + case Platform.iOS: s += "ios"; break; + case Platform.Android: s += "android"; break; + default: s += "unknown"; break; + } + + return s; + } +}; + +/// ProjectConfig is a class that allows me to determine project structure. +public class ProjectConfig { + public string name = "Untitled Project"; + public string version = "1.0.0"; + public List author = new(){ "Untitled Author" }; + public required List targets; + public string license = "mit"; + public string output = "exe"; + public string sourceFolder = "src/"; + public string buildFolder = "build/"; + public Dictionary? dependencies; + public Dictionary? tasks; + public Dictionary? tests; + public Dictionary? languagePacks; + + public CompilerSettings? settings; + public required List filesList; // List of files inside the project to feed to compiler. + public required string sourcePath; // Absolute path to locate the project + + + // Lists authors by comma. If author is only mentioned once, just author name is inputted + public static string listAuthors(List authors) { + string authorList = ""; + bool first = true; + + foreach (string author in authors) { + string name = author.Trim(); + if (name.Length == 0) continue; + + if (!first) authorList += ", "; + authorList += name; + first = false; + } + + return authorList; + } +}; \ No newline at end of file diff --git a/src/IntrinsicModules/std/LICENSE b/src/Neoluma.Compiler/IntrinsicModules/std/LICENSE similarity index 100% rename from src/IntrinsicModules/std/LICENSE rename to src/Neoluma.Compiler/IntrinsicModules/std/LICENSE diff --git a/src/IntrinsicModules/std/src/fs.nm b/src/Neoluma.Compiler/IntrinsicModules/std/src/fs.nm similarity index 100% rename from src/IntrinsicModules/std/src/fs.nm rename to src/Neoluma.Compiler/IntrinsicModules/std/src/fs.nm diff --git a/src/IntrinsicModules/std/src/io.nm b/src/Neoluma.Compiler/IntrinsicModules/std/src/io.nm similarity index 100% rename from src/IntrinsicModules/std/src/io.nm rename to src/Neoluma.Compiler/IntrinsicModules/std/src/io.nm diff --git a/src/IntrinsicModules/std/src/iter.nm b/src/Neoluma.Compiler/IntrinsicModules/std/src/iter.nm similarity index 100% rename from src/IntrinsicModules/std/src/iter.nm rename to src/Neoluma.Compiler/IntrinsicModules/std/src/iter.nm diff --git a/src/IntrinsicModules/std/src/math.nm b/src/Neoluma.Compiler/IntrinsicModules/std/src/math.nm similarity index 100% rename from src/IntrinsicModules/std/src/math.nm rename to src/Neoluma.Compiler/IntrinsicModules/std/src/math.nm diff --git a/src/IntrinsicModules/std/src/random.nm b/src/Neoluma.Compiler/IntrinsicModules/std/src/random.nm similarity index 100% rename from src/IntrinsicModules/std/src/random.nm rename to src/Neoluma.Compiler/IntrinsicModules/std/src/random.nm diff --git a/src/IntrinsicModules/std/src/time.nm b/src/Neoluma.Compiler/IntrinsicModules/std/src/time.nm similarity index 100% rename from src/IntrinsicModules/std/src/time.nm rename to src/Neoluma.Compiler/IntrinsicModules/std/src/time.nm diff --git a/src/IntrinsicModules/std/std.nlp b/src/Neoluma.Compiler/IntrinsicModules/std/std.nlp similarity index 100% rename from src/IntrinsicModules/std/std.nlp rename to src/Neoluma.Compiler/IntrinsicModules/std/std.nlp diff --git a/src/Neoluma.Compiler/Libraries/Asker.cs b/src/Neoluma.Compiler/Libraries/Asker.cs new file mode 100644 index 0000000..8f72273 --- /dev/null +++ b/src/Neoluma.Compiler/Libraries/Asker.cs @@ -0,0 +1,56 @@ +/* + * Asker is an internal Neoluma library for handling CLI input + */ + +namespace Neoluma.Libraries; + +public static class Asker { + private static void clearBlock(int lines) { + for (int i = 0; i < lines; i++) Console.Write("\u001b[1A\u001b[2K\r"); + } + + public static string input(string question, bool required = false) { + Console.Write($"{Color.TextHex("#75b5ff")}>> {question} {Color.TextHex("#ff28e6")}"); + while (true) { + string? response = Console.ReadLine(); + if (!required) { Console.Write(Color.Reset); + return response ?? ""; + } + if (!string.IsNullOrEmpty(response)) { Console.Write(Color.Reset); + return response; + } + } + } + + public static bool confirm(string question) { + bool result = true; + string response = input($"{question} {Color.TextHex("#e84b85")} (y/n) {Color.TextHex("#ff28e6")}"); + if (response != "y" && response != "Y") result = false; + Console.Write(Color.Reset); + return result; + } + + public static string selectList(string question, List options) { + int pos = 0; + int lines = options.Count + 2; + + while (true) { + clearBlock(lines); + + Console.WriteLine($"{Color.TextHex("#75b5ff")}>> {question}"); + + for (int i = 0; i < options.Count; i++) { + if (i == pos) Console.WriteLine($"{Color.TextHex("#00ff48")}> {Color.TextHex("#ff28e6")}{options[i]}"); + else Console.WriteLine($"{Color.TextHex("#ff28e6")} {options[i]}"); + } + + ConsoleKey key = Console.ReadKey(true).Key; + if ((key == ConsoleKey.UpArrow || key == ConsoleKey.NumPad8 || key == ConsoleKey.W) && pos > 0) pos--; + else if ((key == ConsoleKey.DownArrow || key == ConsoleKey.NumPad2 || key == ConsoleKey.S) && pos < options.Count - 1) pos++; + else if (key == ConsoleKey.Enter) break; + } + + Console.WriteLine(Color.Reset); + return options[pos]; + } +} \ No newline at end of file diff --git a/src/Neoluma.Compiler/Libraries/Color.cs b/src/Neoluma.Compiler/Libraries/Color.cs new file mode 100644 index 0000000..a5db5fb --- /dev/null +++ b/src/Neoluma.Compiler/Libraries/Color.cs @@ -0,0 +1,47 @@ +/* + * Color is an internal Neoluma library used for handling terminal colors + */ +namespace Neoluma.Libraries; + +public static class Color { + public static string TextRGB(int r, int g, int b) => $"\u001b[38;2;{r};{g};{b}m"; + public static string BackgroundRGB(int r, int g, int b) => $"\u001b[48;2;{r};{g};{b}m"; + + public static string TextHex(string hex) { + if (hex.StartsWith("#")) { + int r = Convert.ToInt32(hex.Substring(1, 2), 16); + int g = Convert.ToInt32(hex.Substring(3, 2), 16); + int b = Convert.ToInt32(hex.Substring(5, 2), 16); + return TextRGB(r, g, b); + } + return ""; + } + + public static string BackgroundHex(string hex) { + if (hex.StartsWith("#")) { + int r = Convert.ToInt32(hex.Substring(1, 2), 16); + int g = Convert.ToInt32(hex.Substring(3, 2), 16); + int b = Convert.ToInt32(hex.Substring(5, 2), 16); + return BackgroundRGB(r, g, b); + } + return ""; + } + + public static class Effect { + public static string BoldOn = "\u001b[1m"; + public static string DimOn = "\u001b[2m"; + public static string UnderlineOn = "\u001b[4m"; + public static string BlinkOn = "\u001b[5m"; + public static string ReverseOn = "\u001b[7m"; + public static string HideOn = "\u001b[8m"; + + public static string BoldOff = "\u001b[21m"; + public static string DimOff = "\u001b[22m"; + public static string UnderlineOff = "\u001b[24m"; + public static string BlinkOff = "\u001b[25m"; + public static string ReverseOff = "\u001b[27m"; + public static string HideOff = "\u001b[28m"; + } + + public static string Reset = "\u001b[0m"; +} diff --git a/src/Neoluma.Compiler/Libraries/JSON.cs b/src/Neoluma.Compiler/Libraries/JSON.cs new file mode 100644 index 0000000..4ab4d51 --- /dev/null +++ b/src/Neoluma.Compiler/Libraries/JSON.cs @@ -0,0 +1,376 @@ +/* + * Json is an internal Neoluma library that allows to read or write JSON data (with comments) + +Quick usage + +1) Parse JSON / JSONC +-------------------- +JSON.Value root = JSON.parse(text); +// or +JSON.Value root = JSON.parseFile("config.jsonc"); + +Throws JSON.ParseError on invalid input (never loops or hangs). + +2) Read values (safe pattern) +----------------------------- +if (root.isObject()) { + string name = root["name"].isString() + ? root["name"].asString() + : "default"; + + int w = (root["window"].isObject() && root["window"]["w"].isInt()) + ? (int)root["window"]["w"].asInt() + : 800; +} + +3) Modify / create values +------------------------- +root["enabled"] = true; +root["count"] = Console.ToInt64(42); +root["list"] = JSON.Array{ 1, 2, 3 }; + +JSON.Object obj; +obj.add("a", 1); +obj.add("b", "text"); +root["sub"] = obj; + +4) Comments +----------- +root.commentsBefore.add("Root comment"); +root["enabled"].commentsBefore.add("Toggle feature"); +root["enabled"].commentsAfter = "do not touch"; + +5) Write back +------------- +string out = JSON.stringify(root, { + pretty = true, + emit_comments = true +}); + +// or +JSON.writeFile("out.jsonc", root); + +Notes: +- Supports // and /.* *./ comments (without dots) +- Supports trailing commas +- Supports single-quoted strings +- Duplicate keys: last one wins +- Always throws on invalid JSON (no infinite loops) +*/ +namespace Neoluma.Libraries; + +public static class JSON { + // ====== Error ====== + class ParseError : Exception { + public int line { get; } + public int col { get; } + + public ParseError(string message, int line, int col) + : base($"{message} at line {line}, col {col}") { this.line = line; this.col = col; } + } + + // a pair of key and value + public class Property { public string Key; public Value Value; } + + // Custom JSON types + public class Array : List {} + public class Object : List {} + + // ====== JSON Value ====== + public class Value { + // Comment strings attached to this node + List commentsBefore = new(); + List commentsAfter = new(); + + // int (long) | string | bool | double | Array | Object + private object? storage; + + // Constructors + public Value() { storage = null; } + public Value(long i) { storage = i; } + public Value(string s) { storage = s; } + public Value(bool b) { storage = b; } + public Value(double d) { storage = d; } + public Value(Array array) { storage = array; } + public Value(Object obj) { storage = obj; } + + // Type checks + bool isNull() { return storage == null; } + bool isInt() { return storage is long; } + bool isBool() { return storage is bool; } + bool isDouble() { return storage is double; } + bool isString() { return storage is string; } + bool isArray() { return storage is Array; } + bool isObject() { return storage is Object; } + } + + // Convenience indexing + //public Value this[string key] { get; set; } // creates if missing + //public Value this[int index] { get; set; } // returns null Value if missing + + // ====== Parsing Options ====== + public class ParseOptions { + public bool allowComments = true; + public bool allowTrailingCommas = true; // [1,2,] { "a":1, } + public bool allowBom = true; // UTF-8 BOM + public bool allowSingleQuotes = true; + public bool duplicateKeysLastWins = true; + } + + // ====== Stringifying Options ====== + public class StringifyOptions { + public bool pretty = true; + public int indent = 2; + public bool emitComments = true; + public bool escapeNonASCII = false; // if true, escape real Unicode as \uXXXX / surrogate pairs + public bool sortKeys = false; // optional stable output + } + + // ====== Main API ====== + public static Value parse(string text, ParseOptions? options = null) {} + public static Value parseFile(string filePath, ParseOptions? options = null) {} + public static string stringify(Value value, StringifyOptions? options = null) {} + public static void writeFile(string filePath, Value value, StringifyOptions? options = null) {} + + // ====== Lexer (needed for parser) ====== + enum TokenType {Integer, String, Boolean, Double, Identifier, Null, Comment, Delimiter, Newline, Unknown, EndOfFile} + + struct Token { + public readonly TokenType type; + public readonly string token; + public readonly int line; + public readonly int col; + + public Token(TokenType type, string token, int line, int col) { + this.type = type; + this.token = token; + this.line = line; + this.col = col; + } + } + + class Lexer { + private string src; + private int line = 1; + private int col = 1; + private int pos; + + // Helper + char curChar() { return peek(); } + char move() { + char c = src[pos++]; + if (c=='\n') { line++; col = 1; } + else col++; + return c; + } + char peek(int offset = 0) { + int index = pos + offset; + return index < src.Length ? src[index] : '\0'; + } + bool isAtEnd() { return pos >= src.Length; } + // meant for watching strings from ahead + bool match(string text) { + if (pos + text.Length > src.Length) return false; + return src.Substring(pos, text.Length) == text; + } + + // Main function + public List tokenize(string source) { + src = source; + List tokens = new(); + + char[] delimiters = ['{', '}', '[', ']', ':', ',']; + + while (!isAtEnd()) { + char c = curChar(); + + if (c == '\n') { + int sl = line; + int sc = col; + move(); + tokens.Add(new Token(TokenType.Newline, "\\n", sl, sc)); + } + else if (char.IsWhiteSpace(c) && c == ' ') move(); + else if (char.IsDigit(c) || c == '.' || c == '+' || c == '-' + || match("Infinity") || match("NaN")) lexNumber(tokens); + else if (c == '"' || c == '\'') lexString(tokens); + else if (delimiters.Contains(c)) { + int sl = line; int sc = col; + tokens.Add(new Token(TokenType.Delimiter, move().ToString(), sl, sc)); + } + else if (c == '/') lexComment(tokens); + else if (char.IsLetter(c) || c == '_' || c == '$') lexIdentifier(tokens); + else tokens.Add(new Token(TokenType.Unknown, move().ToString(), line, col)); + } + + tokens.Add(new Token(TokenType.EndOfFile, "", line, col)); + return tokens; + } + + void lexNumber(List tokens) { + int sl = line; int sc = col; + string number = ""; + bool isFloat = false; + + // Optional sign + if (!isAtEnd() && (curChar() == '+' || curChar() == '-')) number += move(); + + // Infinity | -Infinity + if (match("Infinity")) { + number += move(); + for (int i = 0; i < 7; i++) number += move(); + tokens.Add(new Token(TokenType.Double, number, sl, sc)); + return; + } + + // NaN + if (match("NaN")) { + number += move(); + for (int i = 0; i < 2; i++) number += move(); + tokens.Add(new Token(TokenType.Double, number, sl, sc)); + return; + } + + // Hexadecimal numbers + if (pos + 1 < src.Length && curChar() == '0' && src[pos + 1] == 'x') { + number += move(); number += move(); // 0x + if (!char.IsAsciiHexDigit(curChar())) throw new ParseError("Haven't found a hexadecimal digit after 'x'", sl, sc); + while (!isAtEnd() && char.IsAsciiHexDigit(curChar())) number += move(); + tokens.Add(new Token(TokenType.Integer, number, sl, sc)); + return; + } + + // Digits + while (!isAtEnd() && char.IsDigit(curChar())) number += move(); + + // Floating point numbers + if (!isAtEnd() && curChar() == '.') { + isFloat = true; + + bool digitBeforeDot = false; + if (number.Length != 0 && char.IsBetween(number.Last(), '0', '9')) digitBeforeDot = true; + number += move(); // '.' + + if (!digitBeforeDot && (isAtEnd() || !char.IsDigit(curChar()))) + throw new ParseError("A number value has only a dot", sl, sc); + while (!isAtEnd() && char.IsDigit(curChar())) number += move(); + } + + // Exponents + if (!isAtEnd() && (curChar() == 'e' || curChar() == 'E')) { + isFloat = true; + number += move(); + + if (!isAtEnd() && (curChar() == '+' || curChar() == '-')) number += move(); + if (isAtEnd() || !char.IsDigit(curChar())) + throw new ParseError("Number's exponent has no degree", sl, sc); + + while (!isAtEnd() && char.IsDigit(curChar())) number += move(); + } + + // If number is nothing but a sign + if (number == "+" || number == "-") throw new ParseError("Number doesn't have any digit but a positive or a negative sign", sl, sc); + + tokens.Add(new Token(isFloat ? TokenType.Double : TokenType.Integer, number, sl, sc)); + } + + void lexString(List tokens) { + int sl = line; int sc = col; + string str = ""; + char openingQuote = curChar(); + move(); + + while (!isAtEnd()) { + if (curChar() == '\\') { + str += move(); + if (!isAtEnd()) str += move(); + continue; + } + if (curChar() == openingQuote) { + move(); + tokens.Add(new Token(TokenType.String, str, sl, sc)); + return; + } + if (curChar() == '\n') throw new ParseError("No backslash character before newline", sl, sc); + str += move(); + } + + throw new ParseError("String doesn't have any closing quote", sl, sc); + } + + void lexComment(List tokens) { + int sl = line; int sc = col; + string comment = ""; + move(); + + // Single-line comment + if (!isAtEnd() && curChar() == '/') { + move(); + while (!isAtEnd() && curChar() != '\n') comment += move(); + + tokens.Add(new Token(TokenType.Comment, comment, sl, sc)); + return; + } + + // Multi-line comment + if (!isAtEnd() && curChar() == '*') { + move(); + while (!isAtEnd()) { + if (curChar() == '*' && peek(1) == '/') { + move(); move(); + tokens.Add(new Token(TokenType.Comment, comment, sl, sc)); + return; + } + + comment += move(); + } + throw new ParseError("Unterminated comment", sl, sc); + } + + throw new ParseError("Expected comment after '/'", sl, sc); + } + + void lexIdentifier(List tokens) { + int sl = line; int sc = col; + string value = ""; + + while (!isAtEnd() && (char.IsLetterOrDigit(curChar()) || curChar() == '_' || curChar() == '$')) + value += move(); + + if (value == "true" || value == "false") tokens.Add(new Token(TokenType.Boolean, value, sl, sc)); + else if (value == "null") tokens.Add(new Token(TokenType.Null, value, sl, sc)); + else tokens.Add(new Token(TokenType.Identifier, value, sl, sc)); + } + } +} + // ====== Parser ====== + // class JSONParser { + // private Object root; + // private ParseOptions parseOptions; + // private string source; + // private int pos = 0; + // + // // Main function + // void parseRoot(string text, ParseOptions? options) { + // root = new(); + // parseOptions = options ?? new(); + // source = text; + // + // if (source.StartsWith("[")) parseArray(); + // else if (source.StartsWith("{")) parseObject(); + // } + // + // // Parse JSON types + // void parseInt() {} + // void parseBool() {} + // void parseDouble() {} + // void parseString() {} + // void parseArray() { + // pos++; + // while (pos < source.Length || source[pos] == ']') { + // + // } + // if (source[pos] != ']') throw ParseError("") + // } + // void parseObject() {} + // } \ No newline at end of file diff --git a/src/Neoluma.Compiler/Libraries/Utils/FileEmbed.cs b/src/Neoluma.Compiler/Libraries/Utils/FileEmbed.cs new file mode 100644 index 0000000..dadd909 --- /dev/null +++ b/src/Neoluma.Compiler/Libraries/Utils/FileEmbed.cs @@ -0,0 +1,15 @@ +using System.Text; + +namespace Neoluma.Libraries.Utils; + +public class FileEmbed { + public static string readEmbeddedFile(string name) { + var assembly = typeof(Program).Assembly; + + using Stream stream = assembly.GetManifestResourceStream(name) + ?? throw new InvalidOperationException($"Embedded resource not found: {name}"); + + using var reader = new StreamReader(stream, Encoding.UTF8); + return reader.ReadToEnd(); + } +} \ No newline at end of file diff --git a/src/Localization/CLI/ar_SA.jsonc b/src/Neoluma.Compiler/Localization/CLI/ar_SA.jsonc similarity index 100% rename from src/Localization/CLI/ar_SA.jsonc rename to src/Neoluma.Compiler/Localization/CLI/ar_SA.jsonc diff --git a/src/Localization/CLI/de_DE.jsonc b/src/Neoluma.Compiler/Localization/CLI/de_DE.jsonc similarity index 100% rename from src/Localization/CLI/de_DE.jsonc rename to src/Neoluma.Compiler/Localization/CLI/de_DE.jsonc diff --git a/src/Localization/CLI/en_US.jsonc b/src/Neoluma.Compiler/Localization/CLI/en_US.jsonc similarity index 100% rename from src/Localization/CLI/en_US.jsonc rename to src/Neoluma.Compiler/Localization/CLI/en_US.jsonc diff --git a/src/Localization/CLI/it_IT.jsonc b/src/Neoluma.Compiler/Localization/CLI/it_IT.jsonc similarity index 100% rename from src/Localization/CLI/it_IT.jsonc rename to src/Neoluma.Compiler/Localization/CLI/it_IT.jsonc diff --git a/src/Localization/CLI/ru_RU.jsonc b/src/Neoluma.Compiler/Localization/CLI/ru_RU.jsonc similarity index 100% rename from src/Localization/CLI/ru_RU.jsonc rename to src/Neoluma.Compiler/Localization/CLI/ru_RU.jsonc diff --git a/src/Localization/ErrorManager/en_US.jsonc b/src/Neoluma.Compiler/Localization/ErrorManager/en_US.jsonc similarity index 100% rename from src/Localization/ErrorManager/en_US.jsonc rename to src/Neoluma.Compiler/Localization/ErrorManager/en_US.jsonc diff --git a/src/Localization/ErrorManager/ru_RU.jsonc b/src/Neoluma.Compiler/Localization/ErrorManager/ru_RU.jsonc similarity index 100% rename from src/Localization/ErrorManager/ru_RU.jsonc rename to src/Neoluma.Compiler/Localization/ErrorManager/ru_RU.jsonc diff --git a/src/Localization/Libraries/ar_SA.jsonc b/src/Neoluma.Compiler/Localization/Libraries/ar_SA.jsonc similarity index 100% rename from src/Localization/Libraries/ar_SA.jsonc rename to src/Neoluma.Compiler/Localization/Libraries/ar_SA.jsonc diff --git a/src/Localization/Libraries/de_DE.jsonc b/src/Neoluma.Compiler/Localization/Libraries/de_DE.jsonc similarity index 100% rename from src/Localization/Libraries/de_DE.jsonc rename to src/Neoluma.Compiler/Localization/Libraries/de_DE.jsonc diff --git a/src/Localization/Libraries/en_US.jsonc b/src/Neoluma.Compiler/Localization/Libraries/en_US.jsonc similarity index 100% rename from src/Localization/Libraries/en_US.jsonc rename to src/Neoluma.Compiler/Localization/Libraries/en_US.jsonc diff --git a/src/Localization/Libraries/ru_RU.jsonc b/src/Neoluma.Compiler/Localization/Libraries/ru_RU.jsonc similarity index 100% rename from src/Localization/Libraries/ru_RU.jsonc rename to src/Neoluma.Compiler/Localization/Libraries/ru_RU.jsonc diff --git a/src/Neoluma.Compiler/Neoluma.Compiler.csproj b/src/Neoluma.Compiler/Neoluma.Compiler.csproj new file mode 100644 index 0000000..4e48ef3 --- /dev/null +++ b/src/Neoluma.Compiler/Neoluma.Compiler.csproj @@ -0,0 +1,40 @@ + + + Exe + net10.0 + + Neoluma + neoluma + + enable + enable + latest + + + + true + true + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Neoluma.Compiler/Program.cs b/src/Neoluma.Compiler/Program.cs new file mode 100644 index 0000000..263d818 --- /dev/null +++ b/src/Neoluma.Compiler/Program.cs @@ -0,0 +1,20 @@ +using Neoluma.CLI; +using Neoluma.Libraries; + +class Program { + public static void Main(string[] args) { + CLIArgs arguments = CLIArgs.parseArgs(args); + + switch (arguments.command) { + case "new": break; + case "build": break; + case "run": break; + case "check": break; + case "version": break; + default: CLI.printHelp(); break; + } + + Console.WriteLine($"{Color.TextHex("#34FF25")} Hello! {Color.Reset}"); + } +} +