diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c41cc9e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..1e9ba2d
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/whython-8.iml b/.idea/whython-8.iml
new file mode 100644
index 0000000..bbe0a70
--- /dev/null
+++ b/.idea/whython-8.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..4acd214
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,512 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "anstream"
+version = "0.6.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
+[[package]]
+name = "arrayvec"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
+
+[[package]]
+name = "b-box"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79a7873ba5be66516cc71605969989bea6de94f2a3b5215bcd8c60169ce2e268"
+
+[[package]]
+name = "brownstone"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c5839ee4f953e811bfdcf223f509cb2c6a3e1447959b0bff459405575bc17f22"
+dependencies = [
+ "arrayvec",
+]
+
+[[package]]
+name = "bytecount"
+version = "0.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205"
+
+[[package]]
+name = "clap"
+version = "4.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f"
+dependencies = [
+ "heck 0.5.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.53",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+
+[[package]]
+name = "color-print"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a858372ff14bab9b1b30ea504f2a4bc534582aee3e42ba2d41d2a7baba63d5d"
+dependencies = [
+ "color-print-proc-macro",
+]
+
+[[package]]
+name = "color-print-proc-macro"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57e37866456a721d0a404439a1adae37a31be4e0055590d053dfe6981e05003f"
+dependencies = [
+ "nom",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
+name = "either"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
+
+[[package]]
+name = "fs2"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "indent_write"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3"
+
+[[package]]
+name = "itertools"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "joinery"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.153"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+
+[[package]]
+name = "memchr"
+version = "2.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "nom-supreme"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bd3ae6c901f1959588759ff51c95d24b491ecb9ff91aa9c2ef4acc5b1dcab27"
+dependencies = [
+ "brownstone",
+ "indent_write",
+ "joinery",
+ "memchr",
+ "nom",
+]
+
+[[package]]
+name = "nom_locate"
+version = "4.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e3c83c053b0713da60c5b8de47fe8e494fe3ece5267b2f23090a07a053ba8f3"
+dependencies = [
+ "bytecount",
+ "memchr",
+ "nom",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
+
+[[package]]
+name = "strum"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29"
+
+[[package]]
+name = "strum_macros"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946"
+dependencies = [
+ "heck 0.4.1",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.53",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.53"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.53",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "unique-type-id"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0462fbf31a136eb58d768f742ff34d9de41fe8b167aed5821f59163a9527a6b"
+dependencies = [
+ "unique-type-id-derive",
+]
+
+[[package]]
+name = "unique-type-id-derive"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "407e1420003f468eb3b9b7dafbed105a2add06b6a18e1291ea00ec81ee2de406"
+dependencies = [
+ "fs2",
+ "quote",
+ "syn 2.0.53",
+]
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "whython-7"
+version = "0.1.0"
+dependencies = [
+ "b-box",
+ "clap",
+ "color-print",
+ "either",
+ "itertools",
+ "lazy_static",
+ "nom",
+ "nom-supreme",
+ "nom_locate",
+ "same-file",
+ "strum",
+ "strum_macros",
+ "thiserror",
+ "unique-type-id",
+ "walkdir",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..68ae409
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,28 @@
+[package]
+name = "whython-7"
+version = "0.1.0"
+edition = "2021"
+
+
+[dependencies]
+clap = { version = "4.5.3", features = ["derive"] }
+thiserror = "1.0.58"
+itertools = "0.12.1"
+strum = "0.26.2"
+strum_macros = "0.26.2"
+unique-type-id = "1.3.0"
+either = "1.10.0"
+lazy_static = "1.4.0"
+b-box = "0.1.0"
+same-file = "1.0.6"
+walkdir = "2.5.0"
+color-print = "0.3.5"
+nom = "7.1.3"
+nom_locate = "4.2.0"
+nom-supreme = "0.8.0"
+
+[profile.release]
+opt-level = 3
+codegen-units = 1
+lto = "fat"
+panic = "abort"
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bcf247c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+# Whython-8
+
+Requires `link.exe` (MSVC) and `nasm.exe` to be in `PATH`. `main.why` will be compiled
+into the binary found in `out.exe`.
+
+When on Linux, `gcc` will be used for linking and `wine` for execution (both of which need to be in `PATH`).
+`nasm.exe` is still required.
+
+Designed to work on Windows linking with `kernel32.lib` for system calls.
+
+The `master` branch should now contain a semi-stable version whereas
+the latest version can be found on `dev`. I also use `dev` to sync
+my work so expect constant breaking changes on that branch.
\ No newline at end of file
diff --git a/build/out.asm b/build/out.asm
new file mode 100644
index 0000000..569b3e0
--- /dev/null
+++ b/build/out.asm
@@ -0,0 +1,222 @@
+ global main
+ extern ExitProcess
+ extern GetStdHandle
+ extern WriteFile
+ extern HeapAlloc
+ extern HeapFree
+ extern GetProcessHeap
+ extern printf
+ section .text
+
+__2: ; printi
+ push rbp
+ mov rbp, rsp
+ sub rsp, 16
+ ; [inline asm]
+ mov dword [rbp-4], 0x000a
+ mov dword [rbp-8], 0x646C6C25
+ mov rcx, rbp
+ sub rcx, 8
+ mov rdx, qword [rbp+16]
+ sub rsp, 40
+ call printf
+ add rsp, 40
+ leave
+ ret
+
+__3: ; printb
+ push rbp
+ mov rbp, rsp
+ sub rsp, 32
+ ; [inline asm]
+ mov dword [rbp-8], 0x65757274
+ mov dword [rbp-4], 0x0D0A
+ mov rax, qword [rbp+16]
+ cmp rax, 0
+ jz ._3.true
+ mov dword [rbp-8], 0x736C6166
+ mov dword [rbp-4], 0x0D0A65
+ ._3.true:
+ mov rcx, rbp
+ sub rcx, 8
+ mov rdx, qword [rbp+16]
+ sub rsp, 40
+ call printf
+ add rsp, 40
+ leave
+ ret
+
+__37: ; printf
+ push rbp
+ mov rbp, rsp
+ sub rsp, 16
+ ; [inline asm]
+ mov dword [rbp-4], 0x00
+ mov dword [rbp-8], 0x0a664C25
+ mov rcx, rbp
+ sub rcx, 8
+ movsd xmm1, qword [rbp+16]
+ mov rdx, qword [rbp+16]
+ sub rsp, 40
+ call printf
+ add rsp, 40
+ leave
+ ret
+
+main: ; main
+ push rbp
+ mov rbp, rsp
+ sub rsp, 160
+ ; ' printb(true);'
+ ; [inline asm]
+ mov qword [rbp-8], 0
+ ; [no return call] -3 , [(-8, 8)]
+ sub rsp, 8
+ mov rax, qword [rbp-8]
+ mov qword [rbp-168], rax
+ call __3
+ add rsp, 8
+ ; ' printb(true);'
+ ; [inline asm]
+ mov qword [rbp-16], 0
+ ; [no return call] -3 , [(-16, 8)]
+ sub rsp, 8
+ mov rax, qword [rbp-16]
+ mov qword [rbp-168], rax
+ call __3
+ add rsp, 8
+ ; ' printb(false);'
+ ; [inline asm]
+ mov qword [rbp-24], 1
+ ; [no return call] -3 , [(-24, 8)]
+ sub rsp, 8
+ mov rax, qword [rbp-24]
+ mov qword [rbp-168], rax
+ call __3
+ add rsp, 8
+ ; ' printb(false);'
+ ; [inline asm]
+ mov qword [rbp-32], 1
+ ; [no return call] -3 , [(-32, 8)]
+ sub rsp, 8
+ mov rax, qword [rbp-32]
+ mov qword [rbp-168], rax
+ call __3
+ add rsp, 8
+ ; ' printi(9223372036854775808);'
+ ; [inline asm]
+ mov dword [rbp-40], 0x00000000
+ mov dword [rbp-36], 0x80000000
+ ; [no return call] -2 , [(-40, 8)]
+ sub rsp, 8
+ mov rax, qword [rbp-40]
+ mov qword [rbp-168], rax
+ call __2
+ add rsp, 8
+ ; ' printi(-9223372036854775807);'
+ ; [inline asm]
+ mov dword [rbp-48], 0xffffffff
+ mov dword [rbp-44], 0x7fffffff
+ ; [inline asm]
+ mov dword [rbp-56], 0x00000000
+ mov dword [rbp-52], 0x00000000
+ ; [inline asm]
+ ; [inline asm]
+ mov rax, qword [rbp-56]
+ sub rax, [rbp-48]
+ mov [rbp-64], rax
+ ; [no return call] -2 , [(-64, 8)]
+ sub rsp, 8
+ mov rax, qword [rbp-64]
+ mov qword [rbp-168], rax
+ call __2
+ add rsp, 8
+ ; ' printf(1.12351234123);'
+ ; [inline asm]
+ mov rax, __float64__(1.12351234123)
+ mov qword [rbp-72], rax
+ ; [no return call] -37 , [(-72, 8)]
+ sub rsp, 8
+ mov rax, qword [rbp-72]
+ mov qword [rbp-168], rax
+ call __37
+ add rsp, 8
+ ; ' printf(1.12351234124);'
+ ; [inline asm]
+ mov rax, __float64__(1.12351234124)
+ mov qword [rbp-80], rax
+ ; [no return call] -37 , [(-80, 8)]
+ sub rsp, 8
+ mov rax, qword [rbp-80]
+ mov qword [rbp-168], rax
+ call __37
+ add rsp, 8
+ ; ' printf(-1.12351234123);'
+ ; [inline asm]
+ mov rax, __float64__(1.12351234123)
+ mov qword [rbp-88], rax
+ ; [inline asm]
+ mov rax, __float64__(0.0)
+ mov qword [rbp-96], rax
+ ; [inline asm]
+ ; [inline asm]
+ movsd xmm0, qword [rbp-96]
+ subsd xmm0, qword [rbp-88]
+ movsd qword [rbp-104], xmm0
+ ; [no return call] -37 , [(-104, 8)]
+ sub rsp, 8
+ mov rax, qword [rbp-104]
+ mov qword [rbp-168], rax
+ call __37
+ add rsp, 8
+ ; ''
+ ; ' printb(1.12351234123 == 1.12351234124);'
+ ; [inline asm]
+ mov rax, __float64__(1.12351234123)
+ mov qword [rbp-112], rax
+ ; [inline asm]
+ mov rax, __float64__(1.12351234124)
+ mov qword [rbp-120], rax
+ ; [inline asm]
+ ; [inline asm]
+ movsd xmm0, qword [rbp-112]
+ ucomisd xmm0, qword [rbp-120]
+ mov qword [rbp-128], 0
+ setne [rbp-128]
+ ; [no return call] -3 , [(-128, 8)]
+ sub rsp, 8
+ mov rax, qword [rbp-128]
+ mov qword [rbp-168], rax
+ call __3
+ add rsp, 8
+ ; ' printb(1.12351234123 == 1.12351234123);'
+ ; [inline asm]
+ mov rax, __float64__(1.12351234123)
+ mov qword [rbp-136], rax
+ ; [inline asm]
+ mov rax, __float64__(1.12351234123)
+ mov qword [rbp-144], rax
+ ; [inline asm]
+ ; [inline asm]
+ movsd xmm0, qword [rbp-136]
+ ucomisd xmm0, qword [rbp-144]
+ mov qword [rbp-152], 0
+ setne [rbp-152]
+ ; [no return call] -3 , [(-152, 8)]
+ sub rsp, 8
+ mov rax, qword [rbp-152]
+ mov qword [rbp-168], rax
+ call __3
+ add rsp, 8
+ ; ''
+ ; ''
+ ; ' return 7;'
+ ; [inline asm]
+ mov dword [rbp-160], 0x00000007
+ mov dword [rbp-156], 0x00000000
+ ; [return] Some((-160, 8))
+ mov rcx, qword [rbp-160]
+ call ExitProcess
+
+formatStr:
+ db `The int is %d\n`,0
\ No newline at end of file
diff --git a/build/out.exe b/build/out.exe
new file mode 100755
index 0000000..97a2203
Binary files /dev/null and b/build/out.exe differ
diff --git a/build/out.obj b/build/out.obj
new file mode 100644
index 0000000..5d2cb3c
Binary files /dev/null and b/build/out.obj differ
diff --git a/hex_formatter.py b/hex_formatter.py
new file mode 100644
index 0000000..d3b2e6f
--- /dev/null
+++ b/hex_formatter.py
@@ -0,0 +1,11 @@
+from ast import literal_eval
+from itertools import batched
+
+i = input("Enter string: ")
+string = literal_eval("'" + i + "'")
+hex = ["".join(x) for x in batched(string.encode('ascii').hex().upper(), 2)]
+hex_groups = batched(hex, 4)
+
+print("In groups of reversed 8s:")
+for group in hex_groups:
+ print("0x" + "".join(reversed(group)))
diff --git a/libs/kernel32.lib b/libs/kernel32.lib
new file mode 100644
index 0000000..a5db285
Binary files /dev/null and b/libs/kernel32.lib differ
diff --git a/libs/legacy_stdio_definitions.lib b/libs/legacy_stdio_definitions.lib
new file mode 100644
index 0000000..adbd07b
Binary files /dev/null and b/libs/legacy_stdio_definitions.lib differ
diff --git a/libs/legacy_stdio_wide_specifiers.lib b/libs/legacy_stdio_wide_specifiers.lib
new file mode 100644
index 0000000..0de905f
Binary files /dev/null and b/libs/legacy_stdio_wide_specifiers.lib differ
diff --git a/libs/msvcrt.lib b/libs/msvcrt.lib
new file mode 100644
index 0000000..5f58764
Binary files /dev/null and b/libs/msvcrt.lib differ
diff --git a/libs/ucrt.lib b/libs/ucrt.lib
new file mode 100644
index 0000000..fd88b49
Binary files /dev/null and b/libs/ucrt.lib differ
diff --git a/libs/vcruntime.lib b/libs/vcruntime.lib
new file mode 100644
index 0000000..2c2ba22
Binary files /dev/null and b/libs/vcruntime.lib differ
diff --git a/main.why b/main.why
new file mode 100644
index 0000000..5c08917
--- /dev/null
+++ b/main.why
@@ -0,0 +1,17 @@
+fn main() ~ int {
+ printb(true);
+ printb(true);
+ printb(false);
+ printb(false);
+ printi(9223372036854775808);
+ printi(-9223372036854775807);
+ printf(1.12351234123);
+ printf(1.12351234124);
+ printf(-1.12351234123);
+
+ printb(1.12351234123 == 1.12351234124);
+ printb(1.12351234123 == 1.12351234123);
+
+
+ return 7;
+}
\ No newline at end of file
diff --git a/parse_test.why b/parse_test.why
new file mode 100644
index 0000000..f768d4a
--- /dev/null
+++ b/parse_test.why
@@ -0,0 +1,4 @@
+struct A {
+ a: A::B.C
+}
+
diff --git a/reference/currently working b/reference/currently working
new file mode 100644
index 0000000..3f74e6a
--- /dev/null
+++ b/reference/currently working
@@ -0,0 +1,22 @@
+Working
+- struct definition
+- functions
+- static struct functions
+- non-static struct functions
+- return
+- while
+- break
+- if/elif/else
+- int type w/ most operators
+- bool type w/ some operator
+- variable initialisation
+- variable assignments
+- recursion
+- showing
+
+Silent Fail
+- None (yet :D)
+
+Error
+- instantiating custom structs
+- comments (for the weak)
\ No newline at end of file
diff --git a/reference/e.why b/reference/e.why
new file mode 100644
index 0000000..b8605f5
--- /dev/null
+++ b/reference/e.why
@@ -0,0 +1,31 @@
+fn fact(x: float) ~ float {
+ if (x == 0.0) {
+ return 1.0;
+ };
+
+ let f: float = 1.0;
+ let i: float = 1.0;
+
+ while (i < (x + 0.99)) {
+ f *= i;
+ i += 1.0;
+ };
+
+ return f;
+}
+
+fn main() ~ int {
+ let e: float = 0.0;
+
+ let i: float = 0.0;
+ while (i < 10.0) {
+ e += 1.0 / fact(i);
+ printf(e);
+ i += 1.0;
+ };
+
+ printf(e);
+
+ return 7;
+}
+
diff --git a/reference/example 2.why b/reference/example 2.why
new file mode 100644
index 0000000..2bf7c16
--- /dev/null
+++ b/reference/example 2.why
@@ -0,0 +1,34 @@
+struct Fib {
+ a: int,
+ b: int,
+ n: int
+}
+
+impl Fib {
+ fn start(self) {
+ if ((*self.n) == 0) {
+ printi(*self.a);
+ }
+ else {
+ let temp: int = (*self.a) + (*self.b);
+ *self.a = *self.b;
+ *self.b = temp;
+ *self.n -= 1;
+ self.start();
+ };
+ }
+}
+
+
+fn main() ~ int {
+ let i: int = 1;
+
+ while (i < 10) {
+ let f: Fib = @ Fib { 0, 1, i };
+ f.start();
+ i += 1;
+ };
+
+ return 0;
+}
+
diff --git a/reference/example.why b/reference/example.why
new file mode 100644
index 0000000..3fe316f
--- /dev/null
+++ b/reference/example.why
@@ -0,0 +1,31 @@
+mod test.why;
+
+fn main() ~ int {
+ printi(true + false);
+ let a: bool = true;
+ printi(a.add(false));
+ printi(bool#add(true, false));
+
+ extern();
+
+ let i: int = 0;
+ while (i < 90) {
+ printi(fibb(0, 1, i));
+ i += 1;
+ };
+ return fibb(0, 1, 20);
+}
+
+fn fibb(a: int, b: int, n: int) ~ int {
+ if (n <= 0) { return a; };
+ return fibb(b, a + b, n - 1);
+}
+
+impl bool {
+ fn add(lhs: bool, rhs: bool) ~ int {
+ let out: int = 0;
+ if (lhs) { out += 1; };
+ if (rhs) { out += 1; };
+ return out;
+ }
+}
\ No newline at end of file
diff --git a/reference/linked_list_example.why b/reference/linked_list_example.why
new file mode 100644
index 0000000..27c7c55
--- /dev/null
+++ b/reference/linked_list_example.why
@@ -0,0 +1,75 @@
+struct Node {
+ cur: int,
+ last: bool,
+ next: $Node
+}
+
+struct LL {
+ base: $Node,
+ has_first: bool
+}
+
+impl LL {
+ fn new() ~ LL {
+ return @LL {
+ 0,
+ false
+ };
+ }
+
+ fn add(self, next: int) {
+ let new_node: Node = @Node {
+ next,
+ true,
+ 0
+ };
+
+ if (!(*self.has_first)) {
+ *self.base = ^new_node;
+ *self.has_first = true;
+ return;
+ };
+
+ let curr: $Node = *self.base;
+ while (!(*curr.last)) {
+ curr = *curr.next;
+ };
+
+ *curr.last = false;
+ *curr.next = ^new_node;
+ }
+
+ fn print(self) {
+ if (!(*self.has_first)) {
+ return;
+ };
+
+ let curr: $Node = *self.base;
+ printi(*curr.cur);
+ while (!(*curr.last)) {
+ curr = *curr.next;
+ printi(*curr.cur);
+ };
+ }
+}
+
+fn test_two() {
+ let ll: LL = LL#new();
+
+ ll.add(12);
+
+ ll.add(18);
+
+ ll.print();
+ printi(123123);
+}
+
+fn test() {
+ test_two();
+}
+
+fn main() ~ int {
+ test();
+
+ return 7;
+}
\ No newline at end of file
diff --git a/reference/main - c.why b/reference/main - c.why
new file mode 100644
index 0000000..e046ff9
--- /dev/null
+++ b/reference/main - c.why
@@ -0,0 +1,81 @@
+struct Node {
+ cur: int,
+ last: bool,
+ next: $Node
+}
+
+struct LL {
+ base: $Node,
+ has_first: bool
+}
+
+impl LL {
+ fn new() ~ LL {
+ return @LL {
+ 0,
+ false
+ };
+ }
+
+ fn add(self, next: int) {
+ printb(true);
+
+ let new_node: Node = @Node {
+ next,
+ true,
+ 0
+ };
+
+ printb(false);
+
+ if (!(*self.has_first)) {
+ printb(false);
+
+ self.base = ^new_node;
+ return;
+ };
+
+ printb(true);
+
+ let curr: $Node = self.base;
+ while (!(*curr.last)) {
+ curr = curr.next;
+ };
+
+ *curr.last = false;
+ curr.next = ^new_node;
+ }
+
+ fn print(self) {
+ if (!(*self.has_first)) {
+ return;
+ };
+
+ let curr: $Node = self.base;
+ printi(*curr.cur);
+ while (!(*curr.last)) {
+ curr = curr.next;
+ printi(*curr.cur);
+ };
+ }
+}
+
+fn main() ~ int {
+ let ll: LL = LL#new();
+
+ printb(true);
+
+ ll.add(12);
+
+ printb(false);
+
+ ll.add(18);
+
+ printb(true);
+
+ ll.print();
+
+ printb(false);
+
+ return 7;
+}
\ No newline at end of file
diff --git a/reference/out3.asm b/reference/out3.asm
new file mode 100644
index 0000000..06d31cf
--- /dev/null
+++ b/reference/out3.asm
@@ -0,0 +1,51 @@
+ global main
+ extern ExitProcess
+ extern GetStdHandle
+ extern WriteFile
+ extern WriteConsoleA
+ extern WriteConsoleW
+ section .text
+
+__14:
+ push rbp
+ mov rbp, rsp
+ sub rsp, 64
+
+ mov qword [rbp-8], 0D0Ah
+ mov qword [rbp-16], "true"
+ mov rax, [rbp+16]
+ cmp rax, 0
+ jz ._14.true
+ mov qword [rbp-8], `0D0A0065h`
+ mov qword [rbp-16], "fals"
+ ._14.true:
+
+ mov ecx, -11
+ call GetStdHandle
+
+ ; You have to reserve space for these despite not being on the stack!
+ mov rcx, rax ; STD Handle
+ mov rdx, rbp ; Data pointer
+ sub rdx, 16 ; cont.
+ mov r8, 16 ; Bytes to write
+ mov qword [rbp - 24], 0 ; optional out bytes written
+ mov r9, rbp
+ sub r9, 24 ; contd.
+ mov qword [rbp - 32], 0 ; optional lpOverlapped
+ call WriteFile
+ leave
+ ret
+
+main:
+ push rbp
+ mov rbp, rsp
+ sub rsp, 16
+ mov qword [rbp-8], 1
+ mov rax, qword [rbp-8]
+ push qword 0
+ push rax
+ call __14
+ add rsp, 16
+ mov qword [rbp-16], 1
+ mov rcx, [rbp-16]
+ call ExitProcess
\ No newline at end of file
diff --git a/reference/out4.asm b/reference/out4.asm
new file mode 100644
index 0000000..5a5b1b7
--- /dev/null
+++ b/reference/out4.asm
@@ -0,0 +1,70 @@
+ global main
+ extern ExitProcess
+ extern GetStdHandle
+ extern WriteFile
+ extern WriteConsoleA
+ extern WriteConsoleW
+ section .text
+
+__4:
+ push rbp
+ mov rbp, rsp
+ sub rsp, 80
+
+ mov rcx, rbp
+ mov rax, qword [rbp+16]
+ mov qword [rbp-24], ""
+ mov qword [rbp-16], ""
+ mov qword [rbp-8], ""
+ cmp rax, 0
+ jg ._test
+ mov dword [rbp-20], "-"
+ mov r8, rax
+ mov rax, 0
+ sub rax, r8
+ ._test
+ mov rbx, 10
+ mov r8, rbp
+ sub r8, 24
+ ._4.loop:
+ xor rdx, rdx
+ div rbx
+ dec rcx
+ add rdx, '0'
+ mov [rcx], dl
+ cmp rcx, r8
+ jz ._4.loop
+ test rax, rax
+ jnz ._4.loop
+
+ mov ecx, -11
+ call GetStdHandle
+
+ ; You have to reserve space for these despite not being on the stack!
+ mov rcx, rax ; STD Handle
+ mov rdx, rbp ; Data pointer
+ sub rdx, 24 ; cont.
+ mov r8, 24 ; Bytes to write
+ mov qword [rbp - 40], 0 ; optional out bytes written
+ mov r9, rbp
+ sub r9, 24 ; contd.
+ mov qword [rbp - 48], 0 ; optional lpOverlapped
+ call WriteFile
+
+ leave
+ ret
+
+main:
+ push rbp
+ mov rbp, rsp
+ sub rsp, 16
+ mov rax, qword -18446744073709515615
+ mov qword [rbp-8], rax
+ push qword 0
+ mov rax, qword [rbp-8]
+ push rax
+ call __4
+ add rsp, 8
+ mov qword [rbp-16], 1
+ mov rcx, [rbp-8]
+ call ExitProcess
diff --git a/reference/print.asm b/reference/print.asm
new file mode 100644
index 0000000..ec94494
--- /dev/null
+++ b/reference/print.asm
@@ -0,0 +1,29 @@
+
+; set up the .text segment for the code
+section .text
+
+; global main is the entry point
+global main
+; note that there is no _ before printf here, unlike in OS X
+extern printf
+
+main:
+ mov rcx, qword textformat
+ movq xmm0, qword [pi]
+ mov rax, qword 1 ; need to tell printf how many floats
+ call printf
+
+ ; note next step - this puts a zero in rax
+ xor rax, rax
+ ret ; this returns to the OS based on how Windows calls programs.
+ ; this return causes a delay then the program exits.
+
+textformat:
+ db "hello, %lf!",0x0a, 0x00 ; friendly greeting
+
+
+; data segment
+section .data
+
+pi dq __float64__(3.14159)
+
diff --git a/reference/print2.asm b/reference/print2.asm
new file mode 100644
index 0000000..cfe2e0c
--- /dev/null
+++ b/reference/print2.asm
@@ -0,0 +1,9 @@
+mov dword [rbp-44], 0x00
+ mov dword [rbp-48], 0x0a666C25
+ mov rcx, rbp
+ sub rcx, 48
+ movq xmm1, qword [rbp-32]
+ movq rdx, xmm1 ; duplicate into the integer register
+ sub rsp, 40 ; allocate shadow space and alignment (32+8)
+ call printf
+ add rsp, 40 ; restore stack
\ No newline at end of file
diff --git a/reference/reference implementation.txt b/reference/reference implementation.txt
new file mode 100644
index 0000000..7a8e2b3
--- /dev/null
+++ b/reference/reference implementation.txt
@@ -0,0 +1,10 @@
+ - Have refs as special cases for types with same underlying type - how
+ - Cast from **type to *type follows ref
+ - Cast from *type to type copies
+ - Impls accept *self
+ - Impl non-static functions only accessible through *type
+ - *type.attrib accessed through fixed offset from r9 i.e. mov r9, qword [rbp - *type addr]; mov rax, qword [r9 + x]
+
+Implementing special case:
+ - Have first part of names (and types) store indirection amount
+
diff --git a/reference/test.asm b/reference/test.asm
new file mode 100644
index 0000000..fbf0873
--- /dev/null
+++ b/reference/test.asm
@@ -0,0 +1,34 @@
+ global _main
+ extern _GetStdHandle@4
+ extern _WriteFile@20
+ extern _ExitProcess@4
+
+ section .text
+_main:
+ ; DWORD bytes;
+ mov ebp, esp
+ sub esp, 4
+
+ ; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
+ push -11
+ call _GetStdHandle@4
+ mov ebx, eax
+
+ ; WriteFile( hstdOut, message, length(message), &bytes, 0);
+ push 0
+ lea eax, [ebp-4]
+ push eax
+ push (message_end - message)
+ push message
+ push ebx
+ call _WriteFile@20
+
+ ; ExitProcess(0)
+ push 0
+ call _ExitProcess@4
+
+ ; never here
+ hlt
+message:
+ db 'Hello, World', 10
+message_end:
\ No newline at end of file
diff --git a/reference/test.why b/reference/test.why
new file mode 100644
index 0000000..5bb873a
--- /dev/null
+++ b/reference/test.why
@@ -0,0 +1,3 @@
+fn extern() {
+ printi(101);
+}
\ No newline at end of file
diff --git a/reference/test2.asm b/reference/test2.asm
new file mode 100644
index 0000000..f98e9c1
--- /dev/null
+++ b/reference/test2.asm
@@ -0,0 +1,27 @@
+global main
+extern GetStdHandle
+extern WriteFile
+
+section .text
+main:
+ sub rsp, 40 ; reserve shadow spaceand align the stack by 16
+ mov ecx, -11 ; GetStdHandle takes a DWORD arg, write it as 32-bit. This is STD_OUTPUT_HANDLE
+ call GetStdHandle
+
+ mov rcx, rax
+ mov rdx, NtlpBuffer ; or better, lea rdx, [rel NtlpBuffer]
+ mov r8, [NtnNBytesToWrite] ; or better, make it an EQU constant for mov r8d, bytes_to_write
+ mov r9, NtlpNBytesWritten ; first 4 args in regs
+ mov qword [rsp + 32], 00h ; fifth arg on the stack above the shadow space. Also, this is a pointer so it needs to be a qword store.
+ call WriteFile
+ add rsp, 40
+ExitProgram:
+ xor eax, eax
+ ret
+
+section .data
+NtlpBuffer: db 'Hello, World!', 00h
+NtnNBytesToWrite: dq 0eh
+
+section .bss
+NtlpNBytesWritten: resd 01h
\ No newline at end of file
diff --git a/reference/test2.exe b/reference/test2.exe
new file mode 100644
index 0000000..00843a4
Binary files /dev/null and b/reference/test2.exe differ
diff --git a/reference/test2.obj b/reference/test2.obj
new file mode 100644
index 0000000..7fc30bd
Binary files /dev/null and b/reference/test2.obj differ
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..dec16f3
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1 @@
+pub mod root;
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..ea21d62
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,5 @@
+mod root;
+
+fn main() {
+ root::main();
+}
diff --git a/src/root.rs b/src/root.rs
new file mode 100644
index 0000000..9343927
--- /dev/null
+++ b/src/root.rs
@@ -0,0 +1,142 @@
+use std::fs;
+use std::io::ErrorKind;
+use crate::root::assembler::assemble::generate_assembly;
+use crate::root::parser::parse::parse;
+use crate::root::name_resolver::processor::process;
+use crate::time;
+use clap::Parser;
+use std::path::PathBuf;
+use color_print::cprintln;
+use runner::assemble;
+use crate::root::utils::AnyError;
+
+#[cfg(target_os = "windows")]
+use runner::link;
+#[cfg(target_os = "windows")]
+use crate::root::runner::run;
+
+#[cfg(target_os = "linux")]
+use runner::link_gcc_experimental;
+#[cfg(target_os = "linux")]
+use crate::root::runner::run_wine_experimental;
+
+mod assembler;
+mod ast;
+mod basic_ast;
+mod compiler;
+mod custom;
+mod parser;
+mod nom_parser;
+mod name_resolver;
+mod utils;
+mod runner;
+
+/// Compiler for Whython files (.why)
+#[derive(Parser)]
+#[command(version, about, long_about = None)]
+pub struct Args {
+ /// Main input file
+ #[arg(short, long, default_value = "main.why")]
+ pub input: String,
+ /// Output files name without extension
+ /// Main input file
+ #[arg(short, long, default_value = "build/out")]
+ pub output: String,
+ /// Only build - don't run
+ #[arg(short, long)]
+ pub build: bool,
+}
+
+pub fn main() {
+ nom_parser::parse::parse(PathBuf::from("parse_test.why")).ok();
+ return;
+
+ // assemble("build/out").unwrap();
+ // link_gcc_experimental("build/out").unwrap();
+ // run_wine_experimental("build/out").unwrap();
+ // return;
+
+ let args = Args::parse();
+ let _ = main_args(args);
+}
+
+pub fn main_args(args: Args) -> Result<(), AnyError> {
+ if let Some(path) = PathBuf::from(&args.output).parent() {
+ if let Err(e) = fs::create_dir_all(path) {
+ if !matches!(e.kind(), ErrorKind::AlreadyExists) {
+ cprintln!("Failed to create directories for output files>");
+ return Err(AnyError::Other);
+ }
+ }
+ }
+
+ let mut asts = Vec::new();
+ let mut files_followed = Vec::new();
+ print!("Parsing... ");
+ time!(
+ if let Err(e) = parse(PathBuf::from(&args.input), &mut asts, &mut files_followed) {
+ cprintln!("\n{}>", e);
+ return Err(e.into());
+ }
+ );
+
+ print!("Processing... ");
+ time!(
+ let functions = match process(asts) {
+ Err(e) => {
+ cprintln!("\n{}>", e);
+ return Err(e.into());
+ }
+ Ok(functions) => functions
+ };
+ );
+
+ print!("Compiling... ");
+ time!(generate_assembly(&args.output, functions););
+
+ print!("Assembling (NASM)... ");
+ time!(
+ if assemble(&args.output).is_err() {
+ return Err(AnyError::Other);
+ }
+ );
+
+ #[cfg(target_os = "windows")]
+ {
+ println!("Linking (MSVC - link.exe)... ");
+ time!(
+ if link(&args.output).is_err() {
+ return Err(AnyError::Other);
+ }
+ );
+ if args.build {
+ println!("Skipping execution")
+ } else {
+ println!("Executing... ");
+ run(&args.output);
+ }
+ }
+ #[cfg(target_os = "linux")]
+ {
+ cprintln!("Compilation and execution on Linux may be buggy!>");
+ println!("Linking (gcc)... ");
+ time!(
+ let res = link_gcc_experimental(&args.output);
+ if res.is_err() {
+ return Err(AnyError::Other);
+ }
+ );
+
+ if args.build {
+ println!("Skipping execution")
+ } else {
+ println!("Executing (wine)... ");
+ if run_wine_experimental(&args.output).is_err() {
+ return Err(AnyError::Other);
+ }
+ }
+ }
+
+ cprintln!("Done!>");
+ Ok(())
+}
diff --git a/src/root/assembler/assemble.rs b/src/root/assembler/assemble.rs
new file mode 100644
index 0000000..1047bdc
--- /dev/null
+++ b/src/root/assembler/assemble.rs
@@ -0,0 +1,25 @@
+use crate::root::compiler::compile_functions::Function;
+use std::fs;
+
+pub fn generate_assembly(output: &str, functions: Vec>) {
+ let mut out = String::from(
+ " global main
+ extern ExitProcess
+ extern GetStdHandle
+ extern WriteFile
+ extern HeapAlloc
+ extern HeapFree
+ extern GetProcessHeap
+ extern printf
+ section .text\n",
+ );
+ for f in functions {
+ out += "\r\n";
+ out += &(f.get_asm());
+ }
+
+ out += "\nformatStr:
+ db `The int is %d\\n`,0";
+
+ fs::write(format!("{output}.asm"), out).expect("Failed to write assembly to file");
+}
diff --git a/src/root/assembler/mod.rs b/src/root/assembler/mod.rs
new file mode 100644
index 0000000..3c372be
--- /dev/null
+++ b/src/root/assembler/mod.rs
@@ -0,0 +1 @@
+pub mod assemble;
diff --git a/src/root/ast/builtin.rs b/src/root/ast/builtin.rs
new file mode 100644
index 0000000..d7c5ded
--- /dev/null
+++ b/src/root/ast/builtin.rs
@@ -0,0 +1,2 @@
+#[derive(PartialEq, Clone, strum_macros::Display, Debug)]
+pub enum Builtin {}
diff --git a/src/root/ast/keywords.rs b/src/root/ast/keywords.rs
new file mode 100644
index 0000000..5cc5828
--- /dev/null
+++ b/src/root/ast/keywords.rs
@@ -0,0 +1,37 @@
+#[derive(PartialEq, Copy, Clone, strum_macros::Display, Debug, strum_macros::EnumIter)]
+pub enum Keyword {
+ Mod,
+ Struct,
+ Impl,
+ Fn,
+ If,
+ Elif,
+ Else,
+ While,
+ Break,
+ Continue,
+ Let,
+ Return,
+}
+
+pub const MOD_KEYWORD: &str = "mod";
+
+impl Keyword {
+ pub fn get_enum(name: &str) -> Option {
+ match name {
+ MOD_KEYWORD => Some(Keyword::Mod),
+ "struct" => Some(Keyword::Struct),
+ "impl" => Some(Keyword::Impl),
+ "fn" => Some(Keyword::Fn),
+ "if" => Some(Keyword::If),
+ "elif" => Some(Keyword::Elif),
+ "else" => Some(Keyword::Else),
+ "while" => Some(Keyword::While),
+ "break" => Some(Keyword::Break),
+ "continue" => Some(Keyword::Continue),
+ "let" => Some(Keyword::Let),
+ "return" => Some(Keyword::Return),
+ _ => None,
+ }
+ }
+}
diff --git a/src/root/ast/literals.rs b/src/root/ast/literals.rs
new file mode 100644
index 0000000..fa113c5
--- /dev/null
+++ b/src/root/ast/literals.rs
@@ -0,0 +1,38 @@
+use crate::root::basic_ast::symbol::BasicSymbol;
+use crate::root::compiler::local_variable::TypeInfo;
+use crate::root::custom::types::bool::Bool;
+use crate::root::custom::types::float::Float;
+use crate::root::custom::types::int::Int;
+use crate::root::parser::line_info::LineInfo;
+use crate::root::name_resolver::processor::ProcessorError;
+use crate::root::name_resolver::type_builder::TypeTable;
+
+#[derive(Clone, strum_macros::Display, Debug)]
+#[allow(dead_code)]
+pub enum Literal {
+ String(String),
+ Char(char),
+ Int(i128),
+ Bool(bool),
+ Float(f64),
+ Initialiser(String, Vec>),
+ Null,
+ None,
+}
+
+impl Literal {
+ pub fn get_type_id(&self, type_table: &TypeTable, line_info: &LineInfo) -> Result {
+ Ok(match &self {
+ Literal::Int(_) => TypeInfo::new(Int::get_id(), 0),
+ Literal::Bool(_) => TypeInfo::new(Bool::get_id(), 0),
+ Literal::Float(_) => TypeInfo::new(Float::get_id(), 0),
+ Literal::Null => TypeInfo::new(-1, 1),
+ Literal::Initialiser(name, _) => TypeInfo::new(
+ type_table.get_id_by_name(name).ok_or_else(||
+ ProcessorError::TypeNotFound(line_info.clone(), name.clone())
+ )?,
+ 0),
+ _ => todo!(),
+ })
+ }
+}
diff --git a/src/root/ast/mod.rs b/src/root/ast/mod.rs
new file mode 100644
index 0000000..0cdef6c
--- /dev/null
+++ b/src/root/ast/mod.rs
@@ -0,0 +1,5 @@
+pub mod builtin;
+pub mod keywords;
+pub mod literals;
+pub mod operators;
+mod symbol;
diff --git a/src/root/ast/operators.rs b/src/root/ast/operators.rs
new file mode 100644
index 0000000..572b8f4
--- /dev/null
+++ b/src/root/ast/operators.rs
@@ -0,0 +1,47 @@
+#[derive(PartialEq, Clone, strum_macros::Display, Debug)]
+pub enum Operator {
+ Add,
+ Subtract,
+ Product,
+ Divide,
+ Greater,
+ Less,
+ GreaterEqual,
+ LessEqual,
+ Equal,
+ NotEqual,
+ Modulo,
+ Or,
+ And,
+ Not,
+ HeapAlloc,
+ HeapDealloc,
+}
+
+pub const ALL_SYMBOLS: [char; 13] = [
+ '+', '-', '*', '/', '>', '<', '=', '|', '&', '!', '%', '^', '¬',
+];
+
+impl Operator {
+ pub fn get_operator(string: &str) -> Option {
+ match string {
+ "+" => Some(Operator::Add),
+ "-" => Some(Operator::Subtract),
+ "*" => Some(Operator::Product),
+ "/" => Some(Operator::Divide),
+ ">" => Some(Operator::Greater),
+ "<" => Some(Operator::Less),
+ ">=" => Some(Operator::GreaterEqual),
+ "<=" => Some(Operator::LessEqual),
+ "==" => Some(Operator::Equal),
+ "!=" => Some(Operator::NotEqual),
+ "|" => Some(Operator::Or),
+ "&" => Some(Operator::And),
+ "!" => Some(Operator::Not),
+ "%" => Some(Operator::Modulo),
+ "^" => Some(Operator::HeapAlloc),
+ "¬" => Some(Operator::HeapDealloc),
+ _ => None,
+ }
+ }
+}
diff --git a/src/root/ast/symbol.rs b/src/root/ast/symbol.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/root/ast/symbol.rs
@@ -0,0 +1 @@
+
diff --git a/src/root/basic_ast/mod.rs b/src/root/basic_ast/mod.rs
new file mode 100644
index 0000000..7e10413
--- /dev/null
+++ b/src/root/basic_ast/mod.rs
@@ -0,0 +1,2 @@
+pub mod punctuation;
+pub mod symbol;
diff --git a/src/root/basic_ast/punctuation.rs b/src/root/basic_ast/punctuation.rs
new file mode 100644
index 0000000..71b2ab4
--- /dev/null
+++ b/src/root/basic_ast/punctuation.rs
@@ -0,0 +1,7 @@
+#[derive(PartialEq, Clone, strum_macros::Display, Debug)]
+pub enum Punctuation {
+ ListSeparator,
+ Colon,
+ Semicolon,
+ Tilda,
+}
diff --git a/src/root/basic_ast/symbol.rs b/src/root/basic_ast/symbol.rs
new file mode 100644
index 0000000..85e6402
--- /dev/null
+++ b/src/root/basic_ast/symbol.rs
@@ -0,0 +1,70 @@
+use crate::root::ast::keywords::Keyword;
+use crate::root::ast::literals::Literal;
+use crate::root::ast::operators::Operator;
+use crate::root::basic_ast::punctuation::Punctuation;
+use crate::root::parser::line_info::LineInfo;
+
+pub type BasicAbstractSyntaxTree = Vec<(BasicSymbol, LineInfo)>;
+
+#[derive(PartialEq, Clone, strum_macros::Display, Debug)]
+pub enum NameAccessType {
+ Base,
+ Static,
+ Normal,
+}
+
+#[derive(Clone, strum_macros::Display, Debug)]
+pub enum NameType {
+ Normal,
+ Function(Vec>),
+}
+
+#[derive(Clone, strum_macros::Display, Debug)]
+pub enum BasicSymbol {
+ AbstractSyntaxTree(Vec<(BasicSymbol, LineInfo)>),
+ Literal(Literal),
+ Operator(Operator),
+ Assigner(Option),
+ BracedSection(Vec<(BasicSymbol, LineInfo)>),
+ BracketedSection(Vec<(BasicSymbol, LineInfo)>),
+ SquareBracketedSection(Vec<(BasicSymbol, LineInfo)>),
+ Punctuation(Punctuation),
+ Keyword(Keyword),
+ Name(Vec<(String, NameAccessType, NameType, usize)>),
+}
+
+pub const NAME_VALID_CHARS: [char; 63] = [
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
+ 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', '1', '2', '3', '4',
+ '5', '6', '7', '8', '9', '0',
+];
+
+impl BasicSymbol {
+ pub fn get_name_contents(&self) -> &Vec<(String, NameAccessType, NameType, usize)> {
+ match self {
+ BasicSymbol::Name(inside) => inside,
+ _ => panic!(),
+ }
+ }
+}
+
+impl BasicSymbol {
+ #[allow(dead_code)]
+ pub fn instead_found(&self) -> String {
+ match &self {
+ BasicSymbol::AbstractSyntaxTree(_) => panic!(),
+ BasicSymbol::Literal(_literal) => "Literal (or initialiser)".to_string(),
+ BasicSymbol::Operator(_) => "Operator".to_string(),
+ BasicSymbol::Assigner(_) => "Assigner".to_string(),
+ BasicSymbol::BracedSection(_) => "BracedSection".to_string(),
+ BasicSymbol::BracketedSection(_) => "BracketedSection".to_string(),
+ BasicSymbol::SquareBracketedSection(_) => "SquareBracketedSection".to_string(),
+ BasicSymbol::Punctuation(punctuation) => {
+ format!("{punctuation}")
+ }
+ BasicSymbol::Name(_) => "Name".to_string(),
+ BasicSymbol::Keyword(_) => "Keyword".to_string(),
+ }
+ }
+}
diff --git a/src/root/compiler/compile_functions.rs b/src/root/compiler/compile_functions.rs
new file mode 100644
index 0000000..b9fa9d7
--- /dev/null
+++ b/src/root/compiler/compile_functions.rs
@@ -0,0 +1,164 @@
+mod assignment;
+mod call_function;
+mod evaluate;
+mod evaluate_symbol;
+mod instantiate_literal;
+mod name_handler;
+mod operators;
+mod process_lines;
+mod reference;
+
+use crate::root::basic_ast::symbol::BasicSymbol;
+use crate::root::custom::get::{
+ get_custom_function_implementations, get_custom_function_signatures,
+};
+use crate::root::compiler::generate_asm::compile_user_function;
+use crate::root::parser::line_info::LineInfo;
+use crate::root::name_resolver::processor::ProcessorError;
+use crate::root::name_resolver::type_builder::{TypeTable, TypedFunction};
+use name_handler::NameHandler;
+use std::collections::HashMap;
+use crate::root::compiler::local_variable::TypeInfo;
+
+pub enum Line {
+ ReturnCall(isize, isize, Vec<(isize, usize)>, usize, isize),
+ NoReturnCall(isize, isize, Vec<(isize, usize)>, usize),
+ Copy(isize, isize, usize),
+ DynFromCopy(isize, isize, usize),
+ DynToCopy(isize, isize, usize),
+ Return(Option<(isize, usize)>),
+ HeapAlloc(usize, isize),
+ HeapDealloc(isize, isize),
+ InlineAsm(Vec),
+ #[cfg(debug_assertions)]
+ Annotation(String),
+}
+
+pub struct UserFunction {
+ pub id: isize,
+ pub name: String,
+ pub local_variable_size: usize,
+ pub arg_count: usize,
+ pub lines: Vec,
+}
+
+impl Function for UserFunction {
+ fn get_asm(&self) -> String {
+ compile_user_function(self)
+ }
+
+ fn get_id(&self) -> isize {
+ self.id
+ }
+}
+
+pub trait Function {
+ fn get_asm(&self) -> String;
+ fn get_id(&self) -> isize;
+}
+
+pub struct FunctionHolder {
+ functions: HashMap>,
+ functions_table: HashMap