Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
5b51430df1 | ||
|
9625256554 |
20
.gitignore
vendored
20
.gitignore
vendored
|
@ -1,6 +1,18 @@
|
||||||
/target
|
/target
|
||||||
/a
|
/*
|
||||||
|
|
||||||
test
|
# files
|
||||||
test.nasm
|
!/.gitignore
|
||||||
test.o
|
!/cargo.lock
|
||||||
|
!/cargo.toml
|
||||||
|
!/README.md
|
||||||
|
|
||||||
|
# folders
|
||||||
|
!/.github
|
||||||
|
!/editor
|
||||||
|
!/examples
|
||||||
|
!/include
|
||||||
|
!/playground
|
||||||
|
!/src
|
||||||
|
!/tests
|
||||||
|
!/tools
|
205
Cargo.lock
generated
205
Cargo.lock
generated
|
@ -3,34 +3,10 @@
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "anyhow"
|
||||||
version = "0.19.0"
|
version = "1.0.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
|
||||||
dependencies = [
|
|
||||||
"gimli",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "adler"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "backtrace"
|
|
||||||
version = "0.3.67"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
|
|
||||||
dependencies = [
|
|
||||||
"addr2line",
|
|
||||||
"cc",
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"miniz_oxide",
|
|
||||||
"object",
|
|
||||||
"rustc-demangle",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
|
@ -44,12 +20,6 @@ version = "1.0.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.1.8"
|
version = "4.1.8"
|
||||||
|
@ -87,33 +57,6 @@ dependencies = [
|
||||||
"os_str_bytes",
|
"os_str_bytes",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "color-eyre"
|
|
||||||
version = "0.6.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204"
|
|
||||||
dependencies = [
|
|
||||||
"backtrace",
|
|
||||||
"color-spantrace",
|
|
||||||
"eyre",
|
|
||||||
"indenter",
|
|
||||||
"once_cell",
|
|
||||||
"owo-colors",
|
|
||||||
"tracing-error",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "color-spantrace"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce"
|
|
||||||
dependencies = [
|
|
||||||
"once_cell",
|
|
||||||
"owo-colors",
|
|
||||||
"tracing-core",
|
|
||||||
"tracing-error",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
@ -135,22 +78,6 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "eyre"
|
|
||||||
version = "0.6.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb"
|
|
||||||
dependencies = [
|
|
||||||
"indenter",
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gimli"
|
|
||||||
version = "0.27.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -163,12 +90,6 @@ version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "indenter"
|
|
||||||
version = "0.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-lifetimes"
|
name = "io-lifetimes"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
|
@ -191,12 +112,6 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazy_static"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.140"
|
version = "0.2.140"
|
||||||
|
@ -210,36 +125,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mclang"
|
name = "mclangc"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
|
||||||
"eyre",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "miniz_oxide"
|
|
||||||
version = "0.6.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
|
||||||
dependencies = [
|
|
||||||
"adler",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "object"
|
|
||||||
version = "0.30.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -254,18 +144,6 @@ version = "6.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "owo-colors"
|
|
||||||
version = "3.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pin-project-lite"
|
|
||||||
version = "0.2.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error"
|
name = "proc-macro-error"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
@ -308,12 +186,6 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc-demangle"
|
|
||||||
version = "0.1.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.36.9"
|
version = "0.36.9"
|
||||||
|
@ -328,15 +200,6 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sharded-slab"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
|
|
||||||
dependencies = [
|
|
||||||
"lazy_static",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
@ -363,70 +226,12 @@ dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thread_local"
|
|
||||||
version = "1.1.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tracing"
|
|
||||||
version = "0.1.37"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"pin-project-lite",
|
|
||||||
"tracing-core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tracing-core"
|
|
||||||
version = "0.1.30"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
|
||||||
dependencies = [
|
|
||||||
"once_cell",
|
|
||||||
"valuable",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tracing-error"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
|
|
||||||
dependencies = [
|
|
||||||
"tracing",
|
|
||||||
"tracing-subscriber",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tracing-subscriber"
|
|
||||||
version = "0.3.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
|
|
||||||
dependencies = [
|
|
||||||
"sharded-slab",
|
|
||||||
"thread_local",
|
|
||||||
"tracing-core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.8"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "valuable"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
[package]
|
[package]
|
||||||
name = "mclangc"
|
name = "mclangc"
|
||||||
|
description="The McLang Programming language compiler"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
authors=[
|
||||||
|
"MCorange <mcorangecodes@gmail.com> (https://mcorangehq.xyz/)"
|
||||||
|
]
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0.79"
|
||||||
clap = { version = "4.1.8", features = ["derive"] }
|
clap = { version = "4.1.8", features = ["derive"] }
|
||||||
color-eyre = "0.6.2"
|
|
||||||
eyre = "0.6.8"
|
|
||||||
|
|
|
@ -18,6 +18,14 @@ This is the second revision of [MCLang](https://github.com/mc-lang/mclang) now w
|
||||||
The docs are currently are just made in MarkDown.
|
The docs are currently are just made in MarkDown.
|
||||||
You can find the docs [here](/docs/index.md)
|
You can find the docs [here](/docs/index.md)
|
||||||
|
|
||||||
|
## Cheatsheet
|
||||||
|
|
||||||
|
Usefull things that i search for a lot in the sourcecode so i added them here
|
||||||
|
|
||||||
|
add them in reverse order in mclang
|
||||||
|
|
||||||
|
Syscall arg order: \[rax ,rdi ,rsi ,rdx ,r10 ,r8 ,r9\]
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
[MCotange](https://github.com/MCorange99) - The one and only me, the creator and current maintainer or mclang rev1 and rev2
|
[MCotange](https://github.com/MCorange99) - The one and only me, the creator and current maintainer or mclang rev1 and rev2
|
||||||
|
|
3
examples/.gitignore
vendored
Normal file
3
examples/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/*
|
||||||
|
!/.gitignore
|
||||||
|
!/*.mcl
|
|
@ -1,7 +1,13 @@
|
||||||
|
const FS_O_RDONLY 0 end
|
||||||
|
const FS_O_WRONLY 1 end
|
||||||
|
const FS_O_RDWR 2 end
|
||||||
|
|
||||||
const FS_O_APPEND 1024 end // append to existing file
|
const FS_O_APPEND 1024 end // append to existing file
|
||||||
|
const FS_O_TRUNC 512 end // if file exists, ovewrite it (careful!)
|
||||||
|
const FS_O_CREAT 64 end // create file if it doesn’t exist
|
||||||
|
|
||||||
const FS_O_ASYNC 8192 end // use signal-driven IO
|
const FS_O_ASYNC 8192 end // use signal-driven IO
|
||||||
const FS_O_CLOEXEC 524288 end // use close-on-exec (avoid race conditions and lock contentions)
|
const FS_O_CLOEXEC 524288 end // use close-on-exec (avoid race conditions and lock contentions)
|
||||||
const FS_O_CREAT 64 end // create file if it doesn’t exist
|
|
||||||
const FS_O_DIRECT 16384 end // bypass cache (slower)
|
const FS_O_DIRECT 16384 end // bypass cache (slower)
|
||||||
const FS_O_DIRECTORY 65536 end // fail if pathname isn’t a directory
|
const FS_O_DIRECTORY 65536 end // fail if pathname isn’t a directory
|
||||||
const FS_O_DSYNC 4096 end // ensure output is sent to hardware and metadata written before return
|
const FS_O_DSYNC 4096 end // ensure output is sent to hardware and metadata written before return
|
||||||
|
@ -15,4 +21,9 @@ const FS_O_NDELAY 2048 end // same as O_NONBLOCK
|
||||||
const FS_O_PATH 2097152 end // open descriptor for obtaining permissions and status of a file but does not allow read/write operations
|
const FS_O_PATH 2097152 end // open descriptor for obtaining permissions and status of a file but does not allow read/write operations
|
||||||
const FS_O_SYNC 1052672 end // wait for IO to complete before returning
|
const FS_O_SYNC 1052672 end // wait for IO to complete before returning
|
||||||
const FS_O_TMPFILE 4259840 end // create an unnamed, unreachable (via any other open call) temporary file
|
const FS_O_TMPFILE 4259840 end // create an unnamed, unreachable (via any other open call) temporary file
|
||||||
const FS_O_TRUNC 512 end // if file exists, ovewrite it (careful!)
|
|
||||||
|
|
||||||
|
fn fs_read_to_string with int ptr returns int ptr then
|
||||||
|
|
||||||
|
|
||||||
|
done
|
|
@ -12,4 +12,9 @@ inline fn drop2 with any any returns void then drop drop done
|
||||||
const sizeof(u64) 8 end
|
const sizeof(u64) 8 end
|
||||||
const sizeof(u32) 4 end
|
const sizeof(u32) 4 end
|
||||||
const sizeof(u16) 2 end
|
const sizeof(u16) 2 end
|
||||||
const sizeof(u8) 1 end
|
const sizeof(u8) 1 end
|
||||||
|
|
||||||
|
const u64 8 end
|
||||||
|
const u32 4 end
|
||||||
|
const u16 2 end
|
||||||
|
const u8 1 end
|
|
@ -5,7 +5,7 @@
|
||||||
// @arg buff_ptr: Ptr - pointer to the buffer to write
|
// @arg buff_ptr: Ptr - pointer to the buffer to write
|
||||||
// @arg fd: Int - file descriptor
|
// @arg fd: Int - file descriptor
|
||||||
// @ret Int
|
// @ret Int
|
||||||
inline fn write with int ptr int returns int then
|
inline fn fwrite with int ptr int returns int then
|
||||||
SYS_write syscall3
|
SYS_write syscall3
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -15,18 +15,29 @@ done
|
||||||
// @arg buff_ptr: Ptr - pointer to the buffer to write
|
// @arg buff_ptr: Ptr - pointer to the buffer to write
|
||||||
// @arg fd: Int - file descriptor
|
// @arg fd: Int - file descriptor
|
||||||
// @ret Int
|
// @ret Int
|
||||||
inline fn read with int ptr int returns int then
|
inline fn fread with int ptr int returns int then
|
||||||
SYS_read syscall3
|
SYS_read syscall3
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
// Write to a file descriptor using the SYS_write syscall
|
||||||
|
// args: [buff_ptr, flags, mode]
|
||||||
|
// @arg buff_ptr: Ptr - File to open
|
||||||
|
// @arg flags: Int - Flags
|
||||||
|
// @arg mode: Int - Mode
|
||||||
|
// @ret Int - Fd
|
||||||
|
inline fn fopen with int ptr int returns int then
|
||||||
|
SYS_open syscall3
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
// Print a string to STDOUT
|
// Print a string to STDOUT
|
||||||
// args: [str_size, str_ptr]
|
// args: [str_size, str_ptr]
|
||||||
// @arg buff_size: Int - number of bytes to write
|
// @arg buff_size: Int - number of bytes to write
|
||||||
// @arg buff_ptr: Ptr - pointer to the buffer to write
|
// @arg buff_ptr: Ptr - pointer to the buffer to write
|
||||||
// @ret NULL
|
// @ret NULL
|
||||||
inline fn puts with int ptr returns void then
|
inline fn puts with int ptr returns void then
|
||||||
STDOUT write drop
|
STDOUT fwrite drop
|
||||||
done
|
done
|
||||||
|
|
||||||
// Print a string to STDERR
|
// Print a string to STDERR
|
||||||
|
@ -35,10 +46,10 @@ done
|
||||||
// @arg buff_ptr: Ptr - pointer to the buffer to write
|
// @arg buff_ptr: Ptr - pointer to the buffer to write
|
||||||
// @ret NULL
|
// @ret NULL
|
||||||
inline fn eputs with int ptr returns void then
|
inline fn eputs with int ptr returns void then
|
||||||
STDOUT write drop
|
STDOUT fwrite drop
|
||||||
done
|
done
|
||||||
|
|
||||||
// TODO: make putc and eputc after we make local mem
|
// TODO: make putc, eputc, putd, and eputd after we make local mem
|
||||||
|
|
||||||
// Exit the program with exit_code
|
// Exit the program with exit_code
|
||||||
// args: [exit_code]
|
// args: [exit_code]
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
5
include/string.mcl
Normal file
5
include/string.mcl
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
fn cstr_len with ptr returns int then
|
||||||
|
dup while dup load8 '\0' != do 1 + end swap -
|
||||||
|
done
|
4
playground/.gitignore
vendored
Normal file
4
playground/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
/*
|
||||||
|
!/.gitignore
|
||||||
|
!/*.mcl
|
||||||
|
!/mclangc
|
13
playground/mclangc
Executable file
13
playground/mclangc
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
#? This is just a passthrough for the compiled mclangc binary for ease of use
|
||||||
|
#? It also compiles mclangc every time its ran
|
||||||
|
|
||||||
|
pushd ../ > /dev/null
|
||||||
|
|
||||||
|
cargo build --release -q
|
||||||
|
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
|
||||||
|
../target/release/mclangc -I../include ${@:1}
|
35
playground/test.mcl
Normal file
35
playground/test.mcl
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
include "std.mcl"
|
||||||
|
|
||||||
|
|
||||||
|
struct StatDef do
|
||||||
|
val -> u32
|
||||||
|
val2 -> i8
|
||||||
|
end
|
||||||
|
|
||||||
|
alloc Stat StatDef end
|
||||||
|
|
||||||
|
fn main with int ptr returns void then
|
||||||
|
// p l
|
||||||
|
"Hello!\n" puts
|
||||||
|
|
||||||
|
Stat.val 69 write32
|
||||||
|
|
||||||
|
Stat.val read32 _dbg_print
|
||||||
|
Stat.__size read32 _dbg_print
|
||||||
|
|
||||||
|
// memory fd 4 end
|
||||||
|
|
||||||
|
// NULL
|
||||||
|
// FS_O_RDWR
|
||||||
|
// c"/home/mcorange/@Projects/rust/programming_languages/mclang/mclangc/playground/test.mcl"
|
||||||
|
// fopen
|
||||||
|
// dup _dbg_print
|
||||||
|
// fd swap write32
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
done
|
|
@ -3,8 +3,7 @@ use std::path::{PathBuf, Path};
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
use std::{process, fs};
|
use std::{process, fs};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use color_eyre::Result;
|
use anyhow::{Result, bail};
|
||||||
use eyre::eyre;
|
|
||||||
|
|
||||||
pub mod color {
|
pub mod color {
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
@ -104,21 +103,21 @@ fn compare_results(intp: &TestOutput, comp: &TestOutput, f_in: &Path) -> Result<
|
||||||
println!("{b}[ {r}ERR{rs}{b} ]{rs} {f} compiled and interpreted stdout versions differ", r=color::FG_RED, rs=color::RESET, b=color::BRIGHT, f=f_in.display());
|
println!("{b}[ {r}ERR{rs}{b} ]{rs} {f} compiled and interpreted stdout versions differ", r=color::FG_RED, rs=color::RESET, b=color::BRIGHT, f=f_in.display());
|
||||||
println!("compiled:\n{}", comp.stdout);
|
println!("compiled:\n{}", comp.stdout);
|
||||||
println!("interpreted:\n{}", intp.stdout);
|
println!("interpreted:\n{}", intp.stdout);
|
||||||
return Err(eyre!("Testing failed"));
|
bail!("Testing failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if intp.stderr != comp.stderr {
|
if intp.stderr != comp.stderr {
|
||||||
println!("{b}[ {r}ERR{rs}{b} ]{rs} {f} compiled and interpreted stderr versions differ", r=color::FG_RED, rs=color::RESET, b=color::BRIGHT, f=f_in.display());
|
println!("{b}[ {r}ERR{rs}{b} ]{rs} {f} compiled and interpreted stderr versions differ", r=color::FG_RED, rs=color::RESET, b=color::BRIGHT, f=f_in.display());
|
||||||
println!("compiled:\n{}", comp.stderr);
|
println!("compiled:\n{}", comp.stderr);
|
||||||
println!("interpreted:\n{}", intp.stderr);
|
println!("interpreted:\n{}", intp.stderr);
|
||||||
return Err(eyre!("Testing failed"));
|
bail!("Testing failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if intp.status != comp.status {
|
if intp.status != comp.status {
|
||||||
println!("{b}[ {r}ERR{rs}{b} ]{rs} {f} compiled and interpreted status codes differ", r=color::FG_RED, rs=color::RESET, b=color::BRIGHT, f=f_in.display());
|
println!("{b}[ {r}ERR{rs}{b} ]{rs} {f} compiled and interpreted status codes differ", r=color::FG_RED, rs=color::RESET, b=color::BRIGHT, f=f_in.display());
|
||||||
println!("compiled:\n{}", comp.status);
|
println!("compiled:\n{}", comp.status);
|
||||||
println!("interpreted:\n{}", intp.status);
|
println!("interpreted:\n{}", intp.status);
|
||||||
return Err(eyre!("Testing failed"));
|
bail!("Testing failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{b}[ {g}OK{rs}{b} ]{rs} {f} ", g=color::FG_GREEN, rs=color::RESET, b=color::BRIGHT, f=f_in.display());
|
println!("{b}[ {g}OK{rs}{b} ]{rs} {f} ", g=color::FG_GREEN, rs=color::RESET, b=color::BRIGHT, f=f_in.display());
|
||||||
|
@ -164,7 +163,7 @@ fn main() -> Result<()> {
|
||||||
"record" => todo!("Implement test result recording"),
|
"record" => todo!("Implement test result recording"),
|
||||||
s => {
|
s => {
|
||||||
eprintln!("Unknown mode '{s}'");
|
eprintln!("Unknown mode '{s}'");
|
||||||
return Err(eyre!("Bad subcommand"));
|
bail!("Bad subcommand");
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::path::{PathBuf, Path};
|
use std::path::{PathBuf, Path};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use color_eyre::Result;
|
use anyhow::Result;
|
||||||
use crate::info;
|
use crate::{info, error};
|
||||||
|
|
||||||
pub fn linux_x86_64_compile_and_link(of_a: &Path, of_o: &Path, of_c: &Path, quiet: bool) -> Result<()> {
|
pub fn linux_x86_64_compile_and_link(of_a: &Path, of_o: &Path, of_c: &Path, quiet: bool) -> Result<()> {
|
||||||
|
|
||||||
|
@ -22,11 +22,16 @@ pub fn linux_x86_64_compile_and_link(of_a: &Path, of_o: &Path, of_c: &Path, quie
|
||||||
let mut proc = if cfg!(target_os = "windows") {
|
let mut proc = if cfg!(target_os = "windows") {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
Command::new("nasm")
|
let ret = Command::new("nasm")
|
||||||
.args(nasm_args)
|
.args(nasm_args)
|
||||||
.stdout(Stdio::inherit())
|
.stdout(Stdio::inherit())
|
||||||
.stderr(Stdio::inherit())
|
.stderr(Stdio::inherit())
|
||||||
.spawn()?
|
.spawn();
|
||||||
|
|
||||||
|
if ret.is_err() {
|
||||||
|
error!("Nasm not installed")
|
||||||
|
}
|
||||||
|
ret?
|
||||||
};
|
};
|
||||||
if !quiet {
|
if !quiet {
|
||||||
info!("running 'nasm {}'", nasm_args.join(" "));
|
info!("running 'nasm {}'", nasm_args.join(" "));
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use std::{fs, path::PathBuf, io::{Write, BufWriter}, collections::HashMap};
|
use std::{fs, path::PathBuf, io::{Write, BufWriter}, collections::HashMap};
|
||||||
use crate::{constants::{Operator, OpType, KeywordType}, Args, warn, lerror};
|
use crate::{definitions::*, Args, warn, lerror};
|
||||||
use color_eyre::Result;
|
|
||||||
use crate::compile::commands::linux_x86_64_compile_and_link;
|
use crate::compile::commands::linux_x86_64_compile_and_link;
|
||||||
use crate::constants::InstructionType;
|
use crate::definitions::InstructionType;
|
||||||
use super::{commands::linux_x86_64_run, Constant, Memory, Function};
|
use super::{commands::linux_x86_64_run, Constant, Memory, Function};
|
||||||
use eyre::eyre;
|
|
||||||
|
use anyhow::{Result, bail};
|
||||||
|
|
||||||
|
|
||||||
pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
pub fn compile(program: &Program, args: &Args) -> Result<i32>{
|
||||||
let debug = args.get_opt_level()? < 1;
|
let debug = args.get_opt_level()? < 1;
|
||||||
|
|
||||||
let mut of_c = PathBuf::from(&args.out_file);
|
let mut of_c = PathBuf::from(&args.out_file);
|
||||||
|
@ -32,60 +32,30 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
let mut memories: Vec<Memory> = Vec::new();
|
let mut memories: Vec<Memory> = Vec::new();
|
||||||
let mut constants: HashMap<String, Constant> = HashMap::new();
|
let mut constants: HashMap<String, Constant> = HashMap::new();
|
||||||
let mut functions: Vec<Function> = Vec::new();
|
let mut functions: Vec<Function> = Vec::new();
|
||||||
|
|
||||||
|
let mut alloced_structs: Vec<(String, String)> = Vec::new();
|
||||||
// println!("{}", tokens.len());
|
// println!("{}", tokens.len());
|
||||||
let mut strings: Vec<String> = Vec::new();
|
let mut strings: Vec<String> = Vec::new();
|
||||||
|
|
||||||
writeln!(writer, "BITS 64")?;
|
writeln!(writer, "BITS 64")?;
|
||||||
writeln!(writer, "segment .text")?;
|
writeln!(writer, "segment .text")?;
|
||||||
|
|
||||||
writeln!(writer, "_dbg_print:")?;
|
writeln!(writer, "{}", super::MACRO_DEFINITIONS)?;
|
||||||
writeln!(writer, " mov r9, -3689348814741910323")?;
|
writeln!(writer, "{}", super::DBG_PRINT)?;
|
||||||
writeln!(writer, " sub rsp, 40")?;
|
|
||||||
writeln!(writer, " mov BYTE [rsp+31], 10")?;
|
|
||||||
writeln!(writer, " lea rcx, [rsp+30]")?;
|
|
||||||
writeln!(writer, ".L2:")?;
|
|
||||||
writeln!(writer, " mov rax, rdi")?;
|
|
||||||
writeln!(writer, " lea r8, [rsp+32]")?;
|
|
||||||
writeln!(writer, " mul r9")?;
|
|
||||||
writeln!(writer, " mov rax, rdi")?;
|
|
||||||
writeln!(writer, " sub r8, rcx")?;
|
|
||||||
writeln!(writer, " shr rdx, 3")?;
|
|
||||||
writeln!(writer, " lea rsi, [rdx+rdx*4]")?;
|
|
||||||
writeln!(writer, " add rsi, rsi")?;
|
|
||||||
writeln!(writer, " sub rax, rsi")?;
|
|
||||||
writeln!(writer, " add eax, 48")?;
|
|
||||||
writeln!(writer, " mov BYTE [rcx], al")?;
|
|
||||||
writeln!(writer, " mov rax, rdi")?;
|
|
||||||
writeln!(writer, " mov rdi, rdx")?;
|
|
||||||
writeln!(writer, " mov rdx, rcx")?;
|
|
||||||
writeln!(writer, " sub rcx, 1")?;
|
|
||||||
writeln!(writer, " cmp rax, 9")?;
|
|
||||||
writeln!(writer, " ja .L2")?;
|
|
||||||
writeln!(writer, " lea rax, [rsp+32]")?;
|
|
||||||
writeln!(writer, " mov edi, 1")?;
|
|
||||||
writeln!(writer, " sub rdx, rax")?;
|
|
||||||
writeln!(writer, " xor eax, eax")?;
|
|
||||||
writeln!(writer, " lea rsi, [rsp+32+rdx]")?;
|
|
||||||
writeln!(writer, " mov rdx, r8")?;
|
|
||||||
writeln!(writer, " mov rax, 1")?;
|
|
||||||
writeln!(writer, " syscall")?;
|
|
||||||
writeln!(writer, " add rsp, 40")?;
|
|
||||||
writeln!(writer, " ret")?;
|
|
||||||
|
|
||||||
if crate::config::ENABLE_EXPORTED_FUNCTIONS && !args.lib_mode {
|
if !crate::config::ENABLE_EXPORTED_FUNCTIONS && !args.lib_mode {
|
||||||
writeln!(writer, "global _start")?;
|
writeln!(writer, "global _start")?;
|
||||||
writeln!(writer, "_start:")?;
|
writeln!(writer, "_start:")?;
|
||||||
writeln!(writer, " lea rbp, [rel ret_stack]")?;
|
writeln!(writer, " lea rbp, [rel ret_stack]")?;
|
||||||
writeln!(writer, " call main")?;
|
writeln!(writer, " call main")?;
|
||||||
writeln!(writer, " jmp end")?;
|
writeln!(writer, " jmp end")?;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let mut ti = 0;
|
let mut ti = 0;
|
||||||
while ti < tokens.len() {
|
while ti < program.ops.len() {
|
||||||
let token = &tokens[ti];
|
let token = &program.ops[ti];
|
||||||
// println!("{:?}", token);
|
|
||||||
if debug {
|
if debug {
|
||||||
writeln!(writer, "addr_{ti}:")?;
|
writeln!(writer, "addr_{ti}:")?;
|
||||||
if token.typ == OpType::Instruction(InstructionType::PushInt) {
|
if token.typ == OpType::Instruction(InstructionType::PushInt) {
|
||||||
|
@ -97,13 +67,13 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ti > 0 {
|
if ti > 0 {
|
||||||
if tokens[ti-1].typ == OpType::Keyword(KeywordType::Else) ||
|
if program.ops[ti-1].typ == OpType::Keyword(KeywordType::Else) ||
|
||||||
tokens[ti-1].typ == OpType::Keyword(KeywordType::End){
|
program.ops[ti-1].typ == OpType::Keyword(KeywordType::End){
|
||||||
writeln!(writer, "addr_{ti}:")?;
|
writeln!(writer, "addr_{ti}:")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ti + 1 < tokens.len() && tokens[ti+1].typ == OpType::Keyword(KeywordType::End) {
|
if ti + 1 < program.ops.len() && program.ops[ti+1].typ == OpType::Keyword(KeywordType::End) {
|
||||||
writeln!(writer, "addr_{ti}:")?;
|
writeln!(writer, "addr_{ti}:")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,299 +86,168 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match token.typ.clone() {
|
match token.typ.clone() {
|
||||||
// stack
|
// stack
|
||||||
|
|
||||||
OpType::Instruction(instruction) => {
|
OpType::Instruction(instruction) => {
|
||||||
match instruction {
|
match instruction {
|
||||||
InstructionType::PushInt => {
|
InstructionType::PushInt => {
|
||||||
writeln!(writer, " mov rax, {}", token.value)?;
|
writeln!(writer, " OP_PushInt {}", token.value)?;
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::PushStr => {
|
InstructionType::PushStr => {
|
||||||
writeln!(writer, " mov rax, {}", token.text.len())?;
|
writeln!(writer, " OP_PushStr {}, str_{}", token.text.len(), strings.len())?;
|
||||||
writeln!(writer, " push rax")?;
|
strings.push(token.text.clone());
|
||||||
writeln!(writer, " mov rax, str_{}", strings.len())?;
|
ti += 1;
|
||||||
writeln!(writer, " push rax")?;
|
}
|
||||||
|
InstructionType::PushCStr => {
|
||||||
|
writeln!(writer, " OP_PushCStr str_{}", strings.len())?;
|
||||||
strings.push(token.text.clone());
|
strings.push(token.text.clone());
|
||||||
ti += 1;
|
ti += 1;
|
||||||
}
|
}
|
||||||
InstructionType::Drop => {
|
InstructionType::Drop => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Drop")?;
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Print => {
|
InstructionType::Print => {
|
||||||
writeln!(writer, " pop rdi")?;
|
writeln!(writer, " OP_Print")?;
|
||||||
writeln!(writer, " call _dbg_print")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
|
|
||||||
InstructionType::Dup => {
|
InstructionType::Dup => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Dup")?;
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
|
|
||||||
InstructionType::Rot => {
|
InstructionType::Rot => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Rot")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rcx")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Swap => {
|
InstructionType::Swap => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Swap")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Over => {
|
InstructionType::Over => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Over")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Load8 => {
|
InstructionType::Read8 => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Load8")?;
|
||||||
writeln!(writer, " xor rbx, rbx")?;
|
|
||||||
writeln!(writer, " mov bl, byte [rax]")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionType::Store8 => {
|
InstructionType::Write8 => {
|
||||||
writeln!(writer, " pop rbx")?;
|
writeln!(writer, " OP_Store8")?;
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " mov byte [rax], bl")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
}
|
}
|
||||||
InstructionType::Load32 => {
|
InstructionType::Read32 => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Load32")?;
|
||||||
writeln!(writer, " xor rbx, rbx")?;
|
|
||||||
writeln!(writer, " mov bl, dword [rax]")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionType::Store32 => {
|
InstructionType::Write32 => {
|
||||||
writeln!(writer, " pop rbx")?;
|
writeln!(writer, " OP_Store32")?;
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " mov dword[rax], bl")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
}
|
}
|
||||||
InstructionType::Load64 => {
|
InstructionType::Read64 => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Load64")?;
|
||||||
writeln!(writer, " xor rbx, rbx")?;
|
|
||||||
writeln!(writer, " mov bl, qword [rax]")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionType::Store64 => {
|
InstructionType::Write64 => {
|
||||||
writeln!(writer, " pop rbx")?;
|
writeln!(writer, " OP_Store64")?;
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " mov qword [rax], bl")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// math
|
// math
|
||||||
InstructionType::Plus => {
|
InstructionType::Plus => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Plus")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " add rax, rbx")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Minus => {
|
InstructionType::Minus => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Minus")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " sub rbx, rax")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Equals => {
|
InstructionType::Equals => {
|
||||||
writeln!(writer, " mov rcx, 0")?;
|
writeln!(writer, " OP_Equals")?;
|
||||||
writeln!(writer, " mov rdx, 1")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmove rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Lt => {
|
InstructionType::Lt => {
|
||||||
writeln!(writer, " mov rcx, 0")?;
|
writeln!(writer, " OP_Lt")?;
|
||||||
writeln!(writer, " mov rdx, 1")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmovl rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Gt => {
|
InstructionType::Gt => {
|
||||||
writeln!(writer, " mov rcx, 0")?;
|
writeln!(writer, " OP_Gt")?;
|
||||||
writeln!(writer, " mov rdx, 1")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmovg rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::NotEquals => {
|
InstructionType::NotEquals => {
|
||||||
writeln!(writer, " mov rcx, 1")?;
|
writeln!(writer, " OP_NotEquals")?;
|
||||||
writeln!(writer, " mov rdx, 0")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmove rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Le => {
|
InstructionType::Le => {
|
||||||
writeln!(writer, " mov rcx, 0")?;
|
writeln!(writer, " OP_Le")?;
|
||||||
writeln!(writer, " mov rdx, 1")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmovle rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Ge => {
|
InstructionType::Ge => {
|
||||||
writeln!(writer, " mov rcx, 0")?;
|
writeln!(writer, " OP_Ge")?;
|
||||||
writeln!(writer, " mov rdx, 1")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmovge rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Band => {
|
InstructionType::Band => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Band")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " and rbx, rax")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Bor => {
|
InstructionType::Bor => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Bor")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " or rbx, rax")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Shr => {
|
InstructionType::Shr => {
|
||||||
writeln!(writer, " pop rcx")?;
|
writeln!(writer, " OP_Shr")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " shr rbx, cl")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Shl => {
|
InstructionType::Shl => {
|
||||||
writeln!(writer, " pop rcx")?;
|
writeln!(writer, " OP_Shl")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " shl rbx, cl")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::DivMod => {
|
InstructionType::DivMod => {
|
||||||
writeln!(writer, " xor rdx, rdx")?;
|
writeln!(writer, " OP_DivMod")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " div rbx")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
writeln!(writer, " push rdx")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Mul => {
|
InstructionType::Mul => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Mul")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " mul rbx")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Syscall0 => {
|
InstructionType::Syscall0 => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Syscall0")?;
|
||||||
writeln!(writer, " syscall")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Syscall1 => {
|
InstructionType::Syscall1 => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Syscall1")?;
|
||||||
writeln!(writer, " pop rdi")?;
|
|
||||||
writeln!(writer, " syscall")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Syscall2 => {
|
InstructionType::Syscall2 => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Syscall2")?;
|
||||||
writeln!(writer, " pop rdi")?;
|
|
||||||
writeln!(writer, " pop rsi")?;
|
|
||||||
writeln!(writer, " syscall")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Syscall3 => {
|
InstructionType::Syscall3 => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Syscall3")?;
|
||||||
writeln!(writer, " pop rdi")?;
|
|
||||||
writeln!(writer, " pop rsi")?;
|
|
||||||
writeln!(writer, " pop rdx")?;
|
|
||||||
writeln!(writer, " syscall")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Syscall4 => {
|
InstructionType::Syscall4 => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Syscall4")?;
|
||||||
writeln!(writer, " pop rdi")?;
|
|
||||||
writeln!(writer, " pop rsi")?;
|
|
||||||
writeln!(writer, " pop rdx")?;
|
|
||||||
writeln!(writer, " pop r10")?;
|
|
||||||
writeln!(writer, " syscall")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Syscall5 => {
|
InstructionType::Syscall5 => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Syscall5")?;
|
||||||
writeln!(writer, " pop rdi")?;
|
|
||||||
writeln!(writer, " pop rsi")?;
|
|
||||||
writeln!(writer, " pop rdx")?;
|
|
||||||
writeln!(writer, " pop r10")?;
|
|
||||||
writeln!(writer, " pop r8")?;
|
|
||||||
writeln!(writer, " syscall")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Syscall6 => {
|
InstructionType::Syscall6 => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " OP_Syscall6")?;
|
||||||
writeln!(writer, " pop rdi")?;
|
|
||||||
writeln!(writer, " pop rsi")?;
|
|
||||||
writeln!(writer, " pop rdx")?;
|
|
||||||
writeln!(writer, " pop r10")?;
|
|
||||||
writeln!(writer, " pop r8")?;
|
|
||||||
writeln!(writer, " pop r9")?;
|
|
||||||
writeln!(writer, " syscall")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::MemUse => {
|
InstructionType::MemUse => {
|
||||||
writeln!(writer, " push mem_{}", token.addr.unwrap())?;
|
writeln!(writer, " OP_MemUse {}", token.addr.unwrap())?;
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::None => {
|
InstructionType::None => {
|
||||||
|
@ -416,11 +255,12 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
unreachable!()
|
unreachable!()
|
||||||
},
|
},
|
||||||
InstructionType::FnCall => {
|
InstructionType::FnCall => {
|
||||||
writeln!(writer, " call {}", token.text)?;
|
writeln!(writer, " OP_FnCall {}", token.text)?;
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Return => {
|
InstructionType::Return => {
|
||||||
|
|
||||||
|
// Experimental feature exported functions
|
||||||
if crate::config::ENABLE_EXPORTED_FUNCTIONS && should_push_ret {
|
if crate::config::ENABLE_EXPORTED_FUNCTIONS && should_push_ret {
|
||||||
writeln!(writer, " pop rdx")?;
|
writeln!(writer, " pop rdx")?;
|
||||||
should_push_ret = false;
|
should_push_ret = false;
|
||||||
|
@ -446,8 +286,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
ti += 1;
|
ti += 1;
|
||||||
}
|
}
|
||||||
InstructionType::ConstUse => {
|
InstructionType::ConstUse => {
|
||||||
writeln!(writer, " mov rax, qword [const_{}]", token.text)?;
|
writeln!(writer, " OP_ConstUse {}", token.text)?;
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
|
|
||||||
let mut c = constants.get(&token.text).unwrap().clone();
|
let mut c = constants.get(&token.text).unwrap().clone();
|
||||||
c.used = true;
|
c.used = true;
|
||||||
|
@ -455,6 +294,10 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
constants.insert(token.text.clone(), c);
|
constants.insert(token.text.clone(), c);
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
|
InstructionType::StructUse => {
|
||||||
|
writeln!(writer, " OP_StructUse {}", token.text)?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,7 +322,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
}
|
}
|
||||||
KeywordType::End => {
|
KeywordType::End => {
|
||||||
if ti + 1 != token.jmp {
|
if ti + 1 != token.jmp {
|
||||||
// writeln!(writer, " jmp addr_{}", token.jmp)?;
|
writeln!(writer, " jmp addr_{}", token.jmp)?;
|
||||||
}
|
}
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
|
@ -523,16 +366,11 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
ti += 1;
|
ti += 1;
|
||||||
}
|
}
|
||||||
KeywordType::FunctionThen => ti += 1,
|
KeywordType::FunctionThen => ti += 1,
|
||||||
KeywordType::Function |
|
|
||||||
KeywordType::Include |
|
|
||||||
KeywordType::Inline |
|
|
||||||
KeywordType::Export |
|
|
||||||
KeywordType::Constant => unreachable!(),
|
|
||||||
KeywordType::FunctionDefExported => {
|
KeywordType::FunctionDefExported => {
|
||||||
|
|
||||||
if !crate::config::ENABLE_EXPORTED_FUNCTIONS {
|
if !crate::config::ENABLE_EXPORTED_FUNCTIONS {
|
||||||
lerror!(&token.loc, "Experimental feature 'exported functions' is not enabled");
|
lerror!(&token.loc, "Experimental feature 'exported functions' is not enabled");
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(writer, "global {}", token.text)?;
|
writeln!(writer, "global {}", token.text)?;
|
||||||
|
@ -565,7 +403,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
}
|
}
|
||||||
if token.types.0 >= 7 {
|
if token.types.0 >= 7 {
|
||||||
lerror!(&token.loc, "More than 6 arguments in an external function is not supported");
|
lerror!(&token.loc, "More than 6 arguments in an external function is not supported");
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,18 +411,33 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
should_push_ret = true;
|
should_push_ret = true;
|
||||||
} else if token.types.1 > 1 {
|
} else if token.types.1 > 1 {
|
||||||
lerror!(&token.loc, "More than 1 return arguments in an external function is not supported");
|
lerror!(&token.loc, "More than 1 return arguments in an external function is not supported");
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
functions.push(Function { loc: token.loc.clone(), name: token.text.clone(), exter: false});
|
functions.push(Function { loc: token.loc.clone(), name: token.text.clone(), exter: false});
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
|
KeywordType::Function |
|
||||||
|
KeywordType::Include |
|
||||||
|
KeywordType::Inline |
|
||||||
|
KeywordType::Export |
|
||||||
|
KeywordType::Struct |
|
||||||
|
KeywordType::Constant => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
OpType::Internal(t) => {
|
||||||
|
match t {
|
||||||
|
InternalType::StructAlloc{name} => {
|
||||||
|
alloced_structs.push((name, token.text.clone()));
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InternalType::Arrow => panic!("{t:?}"),
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeln!(writer, "addr_{ti}:")?;
|
writeln!(writer, "addr_{ti}:")?;
|
||||||
if crate::config::ENABLE_EXPORTED_FUNCTIONS && !args.lib_mode {
|
if !crate::config::ENABLE_EXPORTED_FUNCTIONS && !args.lib_mode {
|
||||||
writeln!(writer, "end:")?;
|
writeln!(writer, "end:")?;
|
||||||
writeln!(writer, " mov rax, 60")?;
|
writeln!(writer, " mov rax, 60")?;
|
||||||
writeln!(writer, " mov rdi, 0")?;
|
writeln!(writer, " mov rdi, 0")?;
|
||||||
|
@ -609,16 +462,37 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
writeln!(writer, "segment .bss")?;
|
writeln!(writer, "segment .bss")?;
|
||||||
for s in memories {
|
for m in memories {
|
||||||
writeln!(writer, " mem_{}: resb {}", s.id, s.size)?;
|
writeln!(writer, " mem_{}: resb {}", m.id, m.size)?;
|
||||||
}
|
}
|
||||||
writeln!(writer, " ret_stack: resq 256")?;
|
|
||||||
|
|
||||||
|
|
||||||
|
for s in alloced_structs {
|
||||||
|
let Some(st) = program.struct_defs.get(&s.0) else {
|
||||||
|
// TODO: Make better error
|
||||||
|
panic!("Couldn find struct in struct defs");
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = &s.1;
|
||||||
|
let mut st_size = 0;
|
||||||
|
|
||||||
|
writeln!(writer, " struct_{name}:")?;
|
||||||
|
for f in &st.fields {
|
||||||
|
let size = f.1.get_size();
|
||||||
|
writeln!(writer, " struct_{name}.{}: resb {}", f.0, size)?;
|
||||||
|
st_size += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeln!(writer, " struct_{name}.__size: db {}", st_size)?;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
writeln!(writer, " ret_stack: resq 256")?;
|
||||||
// for t in tokens {
|
// for t in tokens {
|
||||||
// println!("{t:?}");
|
// println!("{t:?}");
|
||||||
// }
|
// }
|
||||||
|
@ -631,7 +505,8 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
functions
|
functions
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
linux_x86_64_compile_and_link(&of_a, &of_o, &of_c, args.quiet)?;
|
linux_x86_64_compile_and_link(&of_a, &of_o, &of_c, args.quiet);
|
||||||
|
|
||||||
if args.run {
|
if args.run {
|
||||||
let c = linux_x86_64_run(&of_c, &[], args.quiet)?;
|
let c = linux_x86_64_run(&of_c, &[], args.quiet)?;
|
||||||
return Ok(c);
|
return Ok(c);
|
||||||
|
@ -654,7 +529,7 @@ fn pre_compile_steps(_code: &str, functions: Vec<Function>) -> Result<()> {
|
||||||
|
|
||||||
if !has_main {
|
if !has_main {
|
||||||
crate::errors::missing_main_fn();
|
crate::errors::missing_main_fn();
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::constants::Loc;
|
use crate::definitions::Loc;
|
||||||
|
|
||||||
pub mod linux_x86_64;
|
pub mod linux_x86_64;
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
|
@ -25,4 +25,338 @@ pub struct Function {
|
||||||
pub loc: Loc,
|
pub loc: Loc,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub exter: bool,
|
pub exter: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DBG_PRINT: &'static str = "
|
||||||
|
_dbg_print:
|
||||||
|
mov r9, -3689348814741910323
|
||||||
|
sub rsp, 40
|
||||||
|
mov BYTE [rsp+31], 10
|
||||||
|
lea rcx, [rsp+30]
|
||||||
|
.L2:
|
||||||
|
mov rax, rdi
|
||||||
|
lea r8, [rsp+32]
|
||||||
|
mul r9
|
||||||
|
mov rax, rdi
|
||||||
|
sub r8, rcx
|
||||||
|
shr rdx, 3
|
||||||
|
lea rsi, [rdx+rdx*4]
|
||||||
|
add rsi, rsi
|
||||||
|
sub rax, rsi
|
||||||
|
add eax, 48
|
||||||
|
mov BYTE [rcx], al
|
||||||
|
mov rax, rdi
|
||||||
|
mov rdi, rdx
|
||||||
|
mov rdx, rcx
|
||||||
|
sub rcx, 1
|
||||||
|
cmp rax, 9
|
||||||
|
ja .L2
|
||||||
|
lea rax, [rsp+32]
|
||||||
|
mov edi, 1
|
||||||
|
sub rdx, rax
|
||||||
|
xor eax, eax
|
||||||
|
lea rsi, [rsp+32+rdx]
|
||||||
|
mov rdx, r8
|
||||||
|
mov rax, 1
|
||||||
|
syscall
|
||||||
|
add rsp, 40
|
||||||
|
ret
|
||||||
|
";
|
||||||
|
|
||||||
|
const MACRO_DEFINITIONS: &'static str = "\
|
||||||
|
%macro OP_PushInt 1
|
||||||
|
mov rax, %1
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
; str_len, str_id
|
||||||
|
%macro OP_PushStr 2
|
||||||
|
mov rax, %1
|
||||||
|
push rax
|
||||||
|
mov rax, %2
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
; str_id
|
||||||
|
%macro OP_PushCStr 1
|
||||||
|
push rax
|
||||||
|
mov rax, %1
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Drop 0
|
||||||
|
pop rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Print 0
|
||||||
|
pop rdi
|
||||||
|
call _dbg_print
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Dup 0
|
||||||
|
pop rax
|
||||||
|
push rax
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Rot 0
|
||||||
|
pop rax
|
||||||
|
pop rbx
|
||||||
|
pop rcx
|
||||||
|
push rbx
|
||||||
|
push rax
|
||||||
|
push rcx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Swap 0
|
||||||
|
pop rax
|
||||||
|
pop rbx
|
||||||
|
push rax
|
||||||
|
push rbx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Over 0
|
||||||
|
pop rax
|
||||||
|
pop rbx
|
||||||
|
push rbx
|
||||||
|
push rax
|
||||||
|
push rbx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Load8 0
|
||||||
|
pop rax
|
||||||
|
xor rbx, rbx
|
||||||
|
mov bl, byte [rax]
|
||||||
|
push rbx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Store8 0
|
||||||
|
pop rbx
|
||||||
|
pop rax
|
||||||
|
mov byte [rax], bl
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Load32 0
|
||||||
|
pop rax
|
||||||
|
xor rbx, rbx
|
||||||
|
mov ebx, dword [rax]
|
||||||
|
push rbx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Store32 0
|
||||||
|
pop rbx
|
||||||
|
pop rax
|
||||||
|
mov dword[rax], ebx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Load64 0
|
||||||
|
pop rax
|
||||||
|
xor rbx, rbx
|
||||||
|
mov rbx, qword [rax]
|
||||||
|
push rbx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Store64 0
|
||||||
|
pop rbx
|
||||||
|
pop rax
|
||||||
|
mov qword [rax], rbx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Plus 0
|
||||||
|
pop rax
|
||||||
|
pop rbx
|
||||||
|
add rax, rbx
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Minus 0
|
||||||
|
pop rax
|
||||||
|
pop rbx
|
||||||
|
sub rbx, rax
|
||||||
|
push rbx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Equals 0
|
||||||
|
mov rcx, 0
|
||||||
|
mov rdx, 1
|
||||||
|
pop rax
|
||||||
|
pop rbx
|
||||||
|
cmp rax, rbx
|
||||||
|
cmove rcx, rdx
|
||||||
|
push rcx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Lt 0
|
||||||
|
mov rcx, 0
|
||||||
|
mov rdx, 1
|
||||||
|
pop rbx
|
||||||
|
pop rax
|
||||||
|
cmp rax, rbx
|
||||||
|
cmovl rcx, rdx
|
||||||
|
push rcx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Gt 0
|
||||||
|
mov rcx, 0
|
||||||
|
mov rdx, 1
|
||||||
|
pop rbx
|
||||||
|
pop rax
|
||||||
|
cmp rax, rbx
|
||||||
|
cmovg rcx, rdx
|
||||||
|
push rcx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_NotEquals 0
|
||||||
|
mov rcx, 1
|
||||||
|
mov rdx, 0
|
||||||
|
pop rax
|
||||||
|
pop rbx
|
||||||
|
cmp rax, rbx
|
||||||
|
cmove rcx, rdx
|
||||||
|
push rcx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Le 0
|
||||||
|
mov rcx, 0
|
||||||
|
mov rdx, 1
|
||||||
|
pop rbx
|
||||||
|
pop rax
|
||||||
|
cmp rax, rbx
|
||||||
|
cmovle rcx, rdx
|
||||||
|
push rcx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Ge 0
|
||||||
|
mov rcx, 0
|
||||||
|
mov rdx, 1
|
||||||
|
pop rbx
|
||||||
|
pop rax
|
||||||
|
cmp rax, rbx
|
||||||
|
cmovge rcx, rdx
|
||||||
|
push rcx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Band 0
|
||||||
|
pop rax
|
||||||
|
pop rbx
|
||||||
|
and rbx, rax
|
||||||
|
push rbx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Bor 0
|
||||||
|
pop rax
|
||||||
|
pop rbx
|
||||||
|
or rbx, rax
|
||||||
|
push rbx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Shr 0
|
||||||
|
pop rcx
|
||||||
|
pop rbx
|
||||||
|
shr rbx, cl
|
||||||
|
push rbx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Shl 0
|
||||||
|
pop rcx
|
||||||
|
pop rbx
|
||||||
|
shl rbx, cl
|
||||||
|
push rbx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_DivMod 0
|
||||||
|
xor rdx, rdx
|
||||||
|
pop rbx
|
||||||
|
pop rax
|
||||||
|
div rbx
|
||||||
|
push rax
|
||||||
|
push rdx
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Mul 0
|
||||||
|
pop rax
|
||||||
|
pop rbx
|
||||||
|
mul rbx
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Syscall0 0
|
||||||
|
pop rax
|
||||||
|
syscall
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Syscall1 0
|
||||||
|
pop rax
|
||||||
|
pop rdi
|
||||||
|
syscall
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Syscall2 0
|
||||||
|
pop rax
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
syscall
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Syscall3 0
|
||||||
|
pop rax
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
pop rdx
|
||||||
|
syscall
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Syscall4 0
|
||||||
|
pop rax
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
pop rdx
|
||||||
|
pop r10
|
||||||
|
syscall
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Syscall5 0
|
||||||
|
pop rax
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
pop rdx
|
||||||
|
pop r10
|
||||||
|
pop r8
|
||||||
|
syscall
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_Syscall6 0
|
||||||
|
pop rax
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
pop rdx
|
||||||
|
pop r10
|
||||||
|
pop r8
|
||||||
|
pop r9
|
||||||
|
syscall
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_MemUse 1
|
||||||
|
push mem_%1
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_FnCall 1
|
||||||
|
call %1
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_ConstUse 1
|
||||||
|
mov rax, qword [const_%1]
|
||||||
|
push rax
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro OP_StructUse 1
|
||||||
|
push struct_%1
|
||||||
|
%endmacro
|
||||||
|
";
|
|
@ -1,25 +1,15 @@
|
||||||
/**
|
/**
|
||||||
* Prints out extra information
|
* Prints out extra information
|
||||||
*/
|
*/
|
||||||
pub const DEV_MODE: bool = false;
|
pub const DEV_MODE: bool = true;
|
||||||
|
|
||||||
pub const DEFAULT_OUT_FILE: &str = "a.out";
|
pub const DEFAULT_OUT_FILE: &str = "a.out";
|
||||||
pub const DEFAULT_INCLUDES: [&str;1] = [
|
pub const DEFAULT_INCLUDES: [&str;2] = [
|
||||||
"./include",
|
"./include",
|
||||||
// "~/.mclang/include",
|
"~/.mclang/include",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interpreting configs
|
|
||||||
* `MEM_SZ` is the buffer size for memory
|
|
||||||
* `STRING_SZ` is the buffer size for strings
|
|
||||||
* if you have buffer overflow consider increasing these
|
|
||||||
*/
|
|
||||||
pub const MEM_SZ: usize = 640 * 1000; // 4kb
|
|
||||||
pub const STRING_SZ: usize = 640 * 1000; // 4kb
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Experimental options
|
* Experimental options
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -7,6 +7,7 @@ pub enum InstructionType {
|
||||||
// stack
|
// stack
|
||||||
PushInt,
|
PushInt,
|
||||||
PushStr,
|
PushStr,
|
||||||
|
PushCStr,
|
||||||
Drop,
|
Drop,
|
||||||
Print,
|
Print,
|
||||||
Dup,
|
Dup,
|
||||||
|
@ -32,12 +33,12 @@ pub enum InstructionType {
|
||||||
|
|
||||||
|
|
||||||
// mem
|
// mem
|
||||||
Load8,
|
Read8,
|
||||||
Store8,
|
Write8,
|
||||||
Load32,
|
Read32,
|
||||||
Store32,
|
Write32,
|
||||||
Load64,
|
Read64,
|
||||||
Store64,
|
Write64,
|
||||||
|
|
||||||
// syscalls
|
// syscalls
|
||||||
Syscall0,
|
Syscall0,
|
||||||
|
@ -88,7 +89,8 @@ pub enum KeywordType {
|
||||||
FunctionThen,
|
FunctionThen,
|
||||||
FunctionDone,
|
FunctionDone,
|
||||||
Inline,
|
Inline,
|
||||||
Export
|
Export,
|
||||||
|
Struct
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -131,7 +133,7 @@ impl Operator {
|
||||||
// self.types = (args, rets);
|
// self.types = (args, rets);
|
||||||
// (*self).clone()
|
// (*self).clone()
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpType {
|
impl OpType {
|
||||||
|
@ -139,9 +141,10 @@ impl OpType {
|
||||||
match (*self).clone() {
|
match (*self).clone() {
|
||||||
OpType::Instruction(instruction) => {
|
OpType::Instruction(instruction) => {
|
||||||
match instruction {
|
match instruction {
|
||||||
|
|
||||||
InstructionType::PushInt => "Number",
|
InstructionType::PushInt => "Number",
|
||||||
InstructionType::PushStr => "String",
|
InstructionType::PushStr => "String",
|
||||||
|
InstructionType::PushCStr => "CString",
|
||||||
InstructionType::Print => "_dbg_print",
|
InstructionType::Print => "_dbg_print",
|
||||||
InstructionType::Dup => "dup",
|
InstructionType::Dup => "dup",
|
||||||
InstructionType::Drop => "drop",
|
InstructionType::Drop => "drop",
|
||||||
|
@ -162,12 +165,12 @@ impl OpType {
|
||||||
InstructionType::Shl => "shl",
|
InstructionType::Shl => "shl",
|
||||||
InstructionType::DivMod => "divmod",
|
InstructionType::DivMod => "divmod",
|
||||||
InstructionType::Mul => "*",
|
InstructionType::Mul => "*",
|
||||||
InstructionType::Load8 => "load8",
|
InstructionType::Read8 => "read8",
|
||||||
InstructionType::Store8 => "store8",
|
InstructionType::Write8 => "write8",
|
||||||
InstructionType::Load32 => "load32",
|
InstructionType::Read32 => "read32",
|
||||||
InstructionType::Store32 => "store32",
|
InstructionType::Write32 => "write32",
|
||||||
InstructionType::Load64 => "load64",
|
InstructionType::Read64 => "read64",
|
||||||
InstructionType::Store64 => "store64",
|
InstructionType::Write64 => "write64",
|
||||||
InstructionType::Syscall0 => "syscall0",
|
InstructionType::Syscall0 => "syscall0",
|
||||||
InstructionType::Syscall1 => "syscall1",
|
InstructionType::Syscall1 => "syscall1",
|
||||||
InstructionType::Syscall2 => "syscall2",
|
InstructionType::Syscall2 => "syscall2",
|
||||||
|
@ -211,6 +214,7 @@ impl OpType {
|
||||||
KeywordType::FunctionDefExported => "extern function definition (internal)",
|
KeywordType::FunctionDefExported => "extern function definition (internal)",
|
||||||
KeywordType::Inline => "inline",
|
KeywordType::Inline => "inline",
|
||||||
KeywordType::Export => "export",
|
KeywordType::Export => "export",
|
||||||
|
KeywordType::Struct => "struct",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +239,7 @@ pub enum TokenType {
|
||||||
Word,
|
Word,
|
||||||
Int,
|
Int,
|
||||||
String,
|
String,
|
||||||
|
CString,
|
||||||
Char
|
Char
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,6 +259,7 @@ impl TokenType {
|
||||||
TokenType::Word => "Word",
|
TokenType::Word => "Word",
|
||||||
TokenType::Int => "Int",
|
TokenType::Int => "Int",
|
||||||
TokenType::String => "String",
|
TokenType::String => "String",
|
||||||
|
TokenType::CString => "CString",
|
||||||
TokenType::Char => "Char"
|
TokenType::Char => "Char"
|
||||||
}.to_string()
|
}.to_string()
|
||||||
}
|
}
|
||||||
|
|
392
src/definitions/mod.rs
Normal file
392
src/definitions/mod.rs
Normal file
|
@ -0,0 +1,392 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use anyhow::{Result, bail};
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum InstructionType {
|
||||||
|
|
||||||
|
// stack
|
||||||
|
PushInt,
|
||||||
|
PushStr,
|
||||||
|
PushCStr,
|
||||||
|
Drop,
|
||||||
|
Print,
|
||||||
|
Dup,
|
||||||
|
Rot, // a b c => b c a
|
||||||
|
Over, // a b => a b a
|
||||||
|
Swap, // a b => b a
|
||||||
|
|
||||||
|
// math
|
||||||
|
Minus,
|
||||||
|
Plus,
|
||||||
|
Equals,
|
||||||
|
Gt,
|
||||||
|
Lt,
|
||||||
|
Ge,
|
||||||
|
Le,
|
||||||
|
NotEquals,
|
||||||
|
Band, // &
|
||||||
|
Bor, // |
|
||||||
|
Shr, // >>
|
||||||
|
Shl, // <<
|
||||||
|
DivMod, // /
|
||||||
|
Mul,
|
||||||
|
|
||||||
|
|
||||||
|
// mem
|
||||||
|
Read8,
|
||||||
|
Write8,
|
||||||
|
Read32,
|
||||||
|
Write32,
|
||||||
|
Read64,
|
||||||
|
Write64,
|
||||||
|
|
||||||
|
// syscalls
|
||||||
|
Syscall0,
|
||||||
|
Syscall1,
|
||||||
|
Syscall2,
|
||||||
|
Syscall3,
|
||||||
|
Syscall4,
|
||||||
|
Syscall5,
|
||||||
|
Syscall6,
|
||||||
|
|
||||||
|
CastBool,
|
||||||
|
CastPtr,
|
||||||
|
CastInt,
|
||||||
|
CastVoid,
|
||||||
|
|
||||||
|
// typing
|
||||||
|
TypeBool,
|
||||||
|
TypePtr,
|
||||||
|
TypeInt,
|
||||||
|
TypeVoid,
|
||||||
|
// TypeStr,
|
||||||
|
TypeAny,
|
||||||
|
Returns,
|
||||||
|
With,
|
||||||
|
|
||||||
|
FnCall,
|
||||||
|
MemUse,
|
||||||
|
ConstUse,
|
||||||
|
StructUse,
|
||||||
|
|
||||||
|
Return,
|
||||||
|
None // Used for macros and any other non built in word definitions
|
||||||
|
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub enum KeywordType {
|
||||||
|
If,
|
||||||
|
Else,
|
||||||
|
End,
|
||||||
|
While,
|
||||||
|
Do,
|
||||||
|
Include,
|
||||||
|
Memory,
|
||||||
|
Constant,
|
||||||
|
ConstantDef,
|
||||||
|
Function,
|
||||||
|
FunctionDef,
|
||||||
|
FunctionDefExported,
|
||||||
|
FunctionThen,
|
||||||
|
FunctionDone,
|
||||||
|
Inline,
|
||||||
|
Export,
|
||||||
|
Struct,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum InternalType {
|
||||||
|
Arrow,
|
||||||
|
StructAlloc {
|
||||||
|
name: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum OpType {
|
||||||
|
Keyword(KeywordType),
|
||||||
|
Instruction(InstructionType),
|
||||||
|
Internal(InternalType)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Operator{
|
||||||
|
pub typ: OpType,
|
||||||
|
pub tok_typ: TokenType,
|
||||||
|
pub value: usize,
|
||||||
|
pub text: String, //? only used for OpType::PushStr
|
||||||
|
pub addr: Option<usize>, //? only used for OpType::PushStr
|
||||||
|
pub jmp: usize,
|
||||||
|
pub loc: Loc,
|
||||||
|
pub types: (usize, usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Operator {
|
||||||
|
pub fn new(typ: OpType, tok_typ: TokenType, value: usize, text: String, file: String, row: usize, col: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
typ,
|
||||||
|
value,
|
||||||
|
jmp: 0,
|
||||||
|
addr: None,
|
||||||
|
text,
|
||||||
|
loc: (file, row, col),
|
||||||
|
tok_typ,
|
||||||
|
types: (0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn set_addr(&mut self, addr: usize) -> Self {
|
||||||
|
self.addr = Some(addr);
|
||||||
|
(*self).clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn set_types(&mut self, args: usize, rets: usize) -> Self {
|
||||||
|
// self.types = (args, rets);
|
||||||
|
// (*self).clone()
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OpType {
|
||||||
|
pub fn human(&self) -> String {
|
||||||
|
match (*self).clone() {
|
||||||
|
OpType::Instruction(instruction) => {
|
||||||
|
match instruction {
|
||||||
|
|
||||||
|
InstructionType::PushInt => "Number",
|
||||||
|
InstructionType::PushStr => "String",
|
||||||
|
InstructionType::PushCStr => "CString",
|
||||||
|
InstructionType::Print => "_dbg_print",
|
||||||
|
InstructionType::Dup => "dup",
|
||||||
|
InstructionType::Drop => "drop",
|
||||||
|
InstructionType::Rot => "rot",
|
||||||
|
InstructionType::Over => "over",
|
||||||
|
InstructionType::Swap => "swap",
|
||||||
|
InstructionType::Plus => "+",
|
||||||
|
InstructionType::Minus => "-",
|
||||||
|
InstructionType::Equals => "=",
|
||||||
|
InstructionType::Gt => ">",
|
||||||
|
InstructionType::Lt => "<",
|
||||||
|
InstructionType::NotEquals => "!=",
|
||||||
|
InstructionType::Le => "<=",
|
||||||
|
InstructionType::Ge => ">=",
|
||||||
|
InstructionType::Band => "band",
|
||||||
|
InstructionType::Bor => "bor",
|
||||||
|
InstructionType::Shr => "shr",
|
||||||
|
InstructionType::Shl => "shl",
|
||||||
|
InstructionType::DivMod => "divmod",
|
||||||
|
InstructionType::Mul => "*",
|
||||||
|
InstructionType::Read8 => "read8",
|
||||||
|
InstructionType::Write8 => "write8",
|
||||||
|
InstructionType::Read32 => "read32",
|
||||||
|
InstructionType::Write32 => "write32",
|
||||||
|
InstructionType::Read64 => "read64",
|
||||||
|
InstructionType::Write64 => "write64",
|
||||||
|
InstructionType::Syscall0 => "syscall0",
|
||||||
|
InstructionType::Syscall1 => "syscall1",
|
||||||
|
InstructionType::Syscall2 => "syscall2",
|
||||||
|
InstructionType::Syscall3 => "syscall3",
|
||||||
|
InstructionType::Syscall4 => "syscall4",
|
||||||
|
InstructionType::Syscall5 => "syscall5",
|
||||||
|
InstructionType::Syscall6 => "syscall6",
|
||||||
|
InstructionType::CastBool => "cast(bool",
|
||||||
|
InstructionType::CastPtr => "cast(ptr)",
|
||||||
|
InstructionType::CastInt => "cast(int)",
|
||||||
|
InstructionType::CastVoid => "cast(void)",
|
||||||
|
InstructionType::None => "None",
|
||||||
|
InstructionType::MemUse => "Memory use (internal)",
|
||||||
|
InstructionType::FnCall => "Function Call (Internal)",
|
||||||
|
InstructionType::ConstUse => "Constant Use (Internal)",
|
||||||
|
InstructionType::StructUse => "Struct Use (Internal)",
|
||||||
|
InstructionType::Return => "return",
|
||||||
|
InstructionType::TypeBool => "bool",
|
||||||
|
InstructionType::TypePtr => "ptr",
|
||||||
|
InstructionType::TypeInt => "int",
|
||||||
|
InstructionType::TypeVoid => "void",
|
||||||
|
InstructionType::Returns => "returns",
|
||||||
|
InstructionType::With => "with",
|
||||||
|
InstructionType::TypeAny => "any",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OpType::Keyword(keyword) => {
|
||||||
|
match keyword {
|
||||||
|
KeywordType::If => "if",
|
||||||
|
KeywordType::Else => "else",
|
||||||
|
KeywordType::End => "end",
|
||||||
|
KeywordType::While => "while",
|
||||||
|
KeywordType::Do => "do",
|
||||||
|
KeywordType::Include => "include",
|
||||||
|
KeywordType::Memory => "memory",
|
||||||
|
KeywordType::Function => "fn",
|
||||||
|
KeywordType::Constant => "const",
|
||||||
|
KeywordType::FunctionThen => "then",
|
||||||
|
KeywordType::FunctionDone => "done",
|
||||||
|
KeywordType::ConstantDef => "constant Definition (internal)",
|
||||||
|
KeywordType::FunctionDef => "function definition (internal)",
|
||||||
|
KeywordType::FunctionDefExported => "extern function definition (internal)",
|
||||||
|
KeywordType::Inline => "inline",
|
||||||
|
KeywordType::Export => "export",
|
||||||
|
KeywordType::Struct => "struct",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OpType::Internal(t) => {
|
||||||
|
match t {
|
||||||
|
InternalType::Arrow => "->",
|
||||||
|
InternalType::StructAlloc{..} => "Struct alloc ( internal )",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
}.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Token {
|
||||||
|
pub file: String,
|
||||||
|
pub line: usize,
|
||||||
|
pub col: usize,
|
||||||
|
pub text: String,
|
||||||
|
pub typ: TokenType,
|
||||||
|
pub value: Option<usize>, //* only used for Memories
|
||||||
|
pub addr: Option<usize>, //* only used for Memories
|
||||||
|
pub op_typ: OpType //* only used for Memories
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||||
|
pub enum TokenType {
|
||||||
|
Word,
|
||||||
|
Int,
|
||||||
|
String,
|
||||||
|
CString,
|
||||||
|
Char
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Token {
|
||||||
|
pub fn loc(&self) -> Loc {
|
||||||
|
(
|
||||||
|
self.file.clone(),
|
||||||
|
self.line,
|
||||||
|
self.col
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TokenType {
|
||||||
|
pub fn human(self) -> String {
|
||||||
|
match self {
|
||||||
|
TokenType::Word => "Word",
|
||||||
|
TokenType::Int => "Int",
|
||||||
|
TokenType::String => "String",
|
||||||
|
TokenType::CString => "CString",
|
||||||
|
TokenType::Char => "Char"
|
||||||
|
}.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Loc = (String, usize, usize);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum Types {
|
||||||
|
Any,
|
||||||
|
Bool,
|
||||||
|
Ptr,
|
||||||
|
Void,
|
||||||
|
U8,
|
||||||
|
U16,
|
||||||
|
U32,
|
||||||
|
U64,
|
||||||
|
I8,
|
||||||
|
I16,
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
|
||||||
|
#[allow(dead_code)] //TODO: Implement custom types
|
||||||
|
Custom{
|
||||||
|
size: u64 // in bytes
|
||||||
|
},
|
||||||
|
// todo: add signed numbers since we dont have them yet lol
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Types {
|
||||||
|
pub fn get_size(&self) -> u64 {
|
||||||
|
match *self {
|
||||||
|
Types::Any => 0, // any cant be a known size
|
||||||
|
Types::Void => 0,
|
||||||
|
Types::Bool => 1,
|
||||||
|
Types::U8 |
|
||||||
|
Types::I8 => 1,
|
||||||
|
Types::U16 |
|
||||||
|
Types::I16 => 2,
|
||||||
|
Types::U32 |
|
||||||
|
Types::I32 => 4,
|
||||||
|
Types::Ptr |
|
||||||
|
Types::U64 |
|
||||||
|
Types::I64 => 8,
|
||||||
|
Types::Custom { size } => size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn from_string<S: Into<String> + std::fmt::Display>(s: &S) -> Result<Self> {
|
||||||
|
match s.to_string().as_str() {
|
||||||
|
"any" => Ok(Types::Any),
|
||||||
|
"void" => Ok(Types::Void),
|
||||||
|
"bool" => Ok(Types::Bool),
|
||||||
|
"u8" => Ok(Types::U8),
|
||||||
|
"i8" => Ok(Types::I8),
|
||||||
|
"u16" => Ok(Types::U16),
|
||||||
|
"i16" => Ok(Types::I16),
|
||||||
|
"u32" => Ok(Types::U32),
|
||||||
|
"i32" => Ok(Types::I32),
|
||||||
|
"ptr" => Ok(Types::Ptr),
|
||||||
|
"u64" => Ok(Types::U64),
|
||||||
|
"i64" => Ok(Types::I64),
|
||||||
|
_ => bail!("Unknown type {s}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Function {
|
||||||
|
pub loc: Loc,
|
||||||
|
pub name: String,
|
||||||
|
pub inline: bool,
|
||||||
|
pub tokens: Option<Vec<Operator>>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Constant {
|
||||||
|
pub loc: Loc,
|
||||||
|
pub name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Memory {
|
||||||
|
pub loc: Loc,
|
||||||
|
pub id: usize
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct StructDef {
|
||||||
|
pub loc: Loc,
|
||||||
|
pub name: String,
|
||||||
|
pub fields: Vec<(String, Types)>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Functions = HashMap<String, Function>;
|
||||||
|
pub type Memories = HashMap<String, Memory>;
|
||||||
|
pub type Constants = HashMap<String, Constant>;
|
||||||
|
pub type StructDefs = HashMap<String, StructDef>;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Program {
|
||||||
|
pub ops: Vec<Operator>,
|
||||||
|
pub functions: Functions,
|
||||||
|
pub memories: Memories,
|
||||||
|
pub constants: Constants,
|
||||||
|
pub struct_defs: StructDefs,
|
||||||
|
pub struct_allocs: HashMap<String, String>
|
||||||
|
}
|
|
@ -48,7 +48,7 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
|
||||||
ip += 1;
|
ip += 1;
|
||||||
},
|
},
|
||||||
InstructionType::PushStr => {
|
InstructionType::PushStr => {
|
||||||
if op.addr.is_none() {
|
if op.addr.is_none() {
|
||||||
stack.push(op.text.len()); // string len
|
stack.push(op.text.len()); // string len
|
||||||
stack.push(string_idx + crate::MEM_SZ);
|
stack.push(string_idx + crate::MEM_SZ);
|
||||||
|
|
||||||
|
@ -64,6 +64,23 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ip += 1;
|
||||||
|
},
|
||||||
|
InstructionType::PushCStr => {
|
||||||
|
if op.addr.is_none() {
|
||||||
|
stack.push(string_idx + crate::MEM_SZ);
|
||||||
|
|
||||||
|
for c in op.text.bytes() {
|
||||||
|
mem[crate::MEM_SZ + string_idx] = u64::from(c);
|
||||||
|
string_idx += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(addr) = op.addr {
|
||||||
|
stack.push(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ip += 1;
|
ip += 1;
|
||||||
},
|
},
|
||||||
InstructionType::Drop => {
|
InstructionType::Drop => {
|
||||||
|
@ -109,11 +126,11 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
|
||||||
ip += 1;
|
ip += 1;
|
||||||
},
|
},
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
InstructionType::Load8 |
|
InstructionType::Read8 |
|
||||||
InstructionType::Load32 |
|
InstructionType::Read32 |
|
||||||
InstructionType::Load64 => {
|
InstructionType::Read64 => {
|
||||||
let a = stack_pop(&mut stack, &pos)?;
|
let a = stack_pop(&mut stack, &pos)?;
|
||||||
if a > crate::MEM_SZ {
|
if a > crate::MEM_SZ + crate::STRING_SZ {
|
||||||
lerror!(&op.loc, "Invalid memory address {a}");
|
lerror!(&op.loc, "Invalid memory address {a}");
|
||||||
return Ok(1);
|
return Ok(1);
|
||||||
}
|
}
|
||||||
|
@ -122,7 +139,7 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
|
||||||
ip += 1;
|
ip += 1;
|
||||||
}
|
}
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
InstructionType::Store8 => {
|
InstructionType::Write8 => {
|
||||||
let val = stack_pop(&mut stack, &pos)?;
|
let val = stack_pop(&mut stack, &pos)?;
|
||||||
let addr = stack_pop(&mut stack, &pos)?;
|
let addr = stack_pop(&mut stack, &pos)?;
|
||||||
|
|
||||||
|
@ -135,7 +152,7 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
|
||||||
ip += 1;
|
ip += 1;
|
||||||
}
|
}
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
InstructionType::Store32 => {
|
InstructionType::Write32 => {
|
||||||
let val = stack_pop(&mut stack, &pos)?;
|
let val = stack_pop(&mut stack, &pos)?;
|
||||||
let addr = stack_pop(&mut stack, &pos)?;
|
let addr = stack_pop(&mut stack, &pos)?;
|
||||||
|
|
||||||
|
@ -149,7 +166,7 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
InstructionType::Store64 => {
|
InstructionType::Write64 => {
|
||||||
let val = stack_pop(&mut stack, &pos)?;
|
let val = stack_pop(&mut stack, &pos)?;
|
||||||
let addr = stack_pop(&mut stack, &pos)?;
|
let addr = stack_pop(&mut stack, &pos)?;
|
||||||
|
|
||||||
|
|
45
src/lexer.rs
45
src/lexer.rs
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
use crate::{constants::{Token, TokenType}, Args};
|
use crate::{definitions::{Token, TokenType}, Args};
|
||||||
|
|
||||||
fn lex_word(s: String, tok_type: TokenType) -> (TokenType, String) {
|
fn lex_word(s: String, tok_type: TokenType) -> (TokenType, String) {
|
||||||
match s {
|
match s {
|
||||||
|
@ -12,6 +12,9 @@ fn lex_word(s: String, tok_type: TokenType) -> (TokenType, String) {
|
||||||
s if tok_type == TokenType::String => {
|
s if tok_type == TokenType::String => {
|
||||||
(TokenType::String, s)
|
(TokenType::String, s)
|
||||||
}
|
}
|
||||||
|
s if tok_type == TokenType::CString => {
|
||||||
|
(TokenType::CString, s)
|
||||||
|
}
|
||||||
s if tok_type == TokenType::Char => {
|
s if tok_type == TokenType::Char => {
|
||||||
(TokenType::Char, s)
|
(TokenType::Char, s)
|
||||||
}
|
}
|
||||||
|
@ -72,17 +75,35 @@ fn lex_line(text: &str) -> Vec<(usize, String, TokenType)> {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
col_end = find_col(text, col, |x, _| x.is_whitespace());
|
if &text[col..=col] == "c" && text.len() - 1 + col > 0 && &text[col+1..=col+1] == "\"" {
|
||||||
let t = &text[col..col_end];
|
col_end = find_col(text, col + 2, |x, x2| x == '"' && x2 != '\\');
|
||||||
|
let t = &text[(col + 2)..col_end];
|
||||||
if t == "//" {
|
let mut t = t.replace("\\n", "\n")
|
||||||
return tokens;
|
.replace("\\t", "\t")
|
||||||
|
.replace("\\r", "\r")
|
||||||
|
.replace("\\\'", "\'")
|
||||||
|
.replace("\\\"", "\"")
|
||||||
|
.replace("\\0", "\0");
|
||||||
|
|
||||||
|
if !t.is_empty() {
|
||||||
|
t.push('\0');
|
||||||
|
tokens.push((col, t.to_string(), TokenType::CString));
|
||||||
|
}
|
||||||
|
col = find_col(text, col_end + 1, |x, _| !x.is_whitespace());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
col_end = find_col(text, col, |x, _| x.is_whitespace());
|
||||||
|
let t = &text[col..col_end];
|
||||||
|
|
||||||
|
if t == "//" {
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !t.is_empty() {
|
||||||
|
tokens.push((col, t.to_string(), TokenType::Word));
|
||||||
|
}
|
||||||
|
col = find_col(text, col_end, |x, _| !x.is_whitespace());
|
||||||
}
|
}
|
||||||
|
|
||||||
if !t.is_empty() {
|
|
||||||
tokens.push((col, t.to_string(), TokenType::Word));
|
|
||||||
}
|
|
||||||
col = find_col(text, col_end, |x, _| !x.is_whitespace());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tokens
|
tokens
|
||||||
|
@ -110,7 +131,7 @@ pub fn lex(code: &str, file: &str, _args: &Args) -> Vec<Token> {
|
||||||
typ: tok_type,
|
typ: tok_type,
|
||||||
value: None,
|
value: None,
|
||||||
addr: None,
|
addr: None,
|
||||||
op_typ: crate::constants::OpType::Instruction(crate::constants::InstructionType::None)
|
op_typ: crate::definitions::OpType::Instruction(crate::definitions::InstructionType::None)
|
||||||
};
|
};
|
||||||
tokens.push(t);
|
tokens.push(t);
|
||||||
}
|
}
|
||||||
|
|
38
src/main.rs
38
src/main.rs
|
@ -1,7 +1,6 @@
|
||||||
#![allow(clippy::wildcard_imports)]
|
#![allow(clippy::wildcard_imports)]
|
||||||
#![allow(clippy::too_many_lines)]
|
#![allow(clippy::too_many_lines)]
|
||||||
mod constants;
|
mod definitions;
|
||||||
mod interpret;
|
|
||||||
mod util;
|
mod util;
|
||||||
mod compile;
|
mod compile;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
@ -11,28 +10,23 @@ mod typechecker;
|
||||||
mod precompiler;
|
mod precompiler;
|
||||||
mod config;
|
mod config;
|
||||||
mod errors;
|
mod errors;
|
||||||
|
pub mod test;
|
||||||
use config::*;
|
use config::*;
|
||||||
use std::{fs, collections::HashMap};
|
use std::{fs, collections::HashMap};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use color_eyre::Result;
|
use anyhow::{Result, bail};
|
||||||
use eyre::eyre;
|
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author=env!("CARGO_PKG_AUTHORS"), version=env!("CARGO_PKG_VERSION"), about=env!("CARGO_PKG_DESCRIPTION"), long_about=env!("CARGO_PKG_DESCRIPTION"))]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
/// Input source file
|
/// Input source file
|
||||||
#[arg(long, short)]
|
|
||||||
in_file: String,
|
in_file: String,
|
||||||
|
|
||||||
/// Output compiled file
|
/// Output compiled file
|
||||||
#[arg(long, short, default_value_t=String::from(DEFAULT_OUT_FILE))]
|
#[arg(long, short, default_value_t=String::from(DEFAULT_OUT_FILE))]
|
||||||
out_file: String,
|
out_file: String,
|
||||||
|
|
||||||
/// Compile
|
|
||||||
#[arg(long, short)]
|
|
||||||
compile: bool,
|
|
||||||
|
|
||||||
/// Interpert
|
/// Interpert
|
||||||
#[arg(long, short='s')]
|
#[arg(long, short='s')]
|
||||||
interpret: bool,
|
interpret: bool,
|
||||||
|
@ -78,7 +72,7 @@ impl Args {
|
||||||
"0" | "" => Ok(1),
|
"0" | "" => Ok(1),
|
||||||
o => {
|
o => {
|
||||||
error!("Unknown optimisation level {o}");
|
error!("Unknown optimisation level {o}");
|
||||||
Err(eyre!(""))
|
bail!("")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +92,7 @@ fn main() -> Result<()>{
|
||||||
|
|
||||||
|
|
||||||
let mut parser = parser::Parser::new(tokens, &args, None);
|
let mut parser = parser::Parser::new(tokens, &args, None);
|
||||||
let tokens = match parser.parse(){
|
let program = match parser.parse(){
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Parsing failed, exiting!");
|
error!("Parsing failed, exiting!");
|
||||||
|
@ -109,7 +103,7 @@ fn main() -> Result<()>{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match typechecker::typecheck(tokens.clone(), &args, None, HashMap::new(), HashMap::new()) {
|
match typechecker::typecheck(program.ops.clone(), &args, None, HashMap::new(), HashMap::new()) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Typechecking failed, exiting!");
|
error!("Typechecking failed, exiting!");
|
||||||
|
@ -120,22 +114,14 @@ fn main() -> Result<()>{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let c = if args.compile && args.interpret {
|
let c =match compile::linux_x86_64::compile(&program, &args) {
|
||||||
error!("Cannot compile and interpret at the same time");
|
Ok(c) => c,
|
||||||
0
|
Err(e) => {
|
||||||
} else if args.interpret {
|
|
||||||
if let Ok(c) = interpret::linux_x86_64::run(&tokens) { c } else {
|
|
||||||
error!("Interpretation failed, exiting!");
|
|
||||||
1
|
|
||||||
}
|
|
||||||
} else if args.compile {
|
|
||||||
if let Ok(c) = compile::linux_x86_64::compile(&tokens, &args) { c } else {
|
|
||||||
error!("Compilation failed, exiting!");
|
error!("Compilation failed, exiting!");
|
||||||
|
println!("{e}");
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
error!("Did not choose to compile or to interpret, exiting");
|
|
||||||
0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::process::exit(c);
|
std::process::exit(c);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use crate::{constants::{Operator, OpType, Token, TokenType, Loc, KeywordType, InstructionType}, lerror, preprocessor::Preprocessor, Args};
|
use crate::{definitions::{Operator, OpType, Token, TokenType, Loc, KeywordType, InstructionType, InternalType, Program}, lerror, preprocessor::Preprocessor, Args};
|
||||||
use color_eyre::Result;
|
use anyhow::{Result, bail};
|
||||||
use eyre::eyre;
|
|
||||||
|
|
||||||
pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||||
let mut stack: Vec<usize> = Vec::new();
|
let mut stack: Vec<usize> = Vec::new();
|
||||||
|
@ -18,11 +17,11 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||||
OpType::Keyword(KeywordType::Else) => {
|
OpType::Keyword(KeywordType::Else) => {
|
||||||
let Some(if_ip) = stack.pop() else {
|
let Some(if_ip) = stack.pop() else {
|
||||||
lerror!(&op.loc, "Unclosed-if else block");
|
lerror!(&op.loc, "Unclosed-if else block");
|
||||||
return Err(eyre!("Cross referencing"));
|
bail!("Cross referencing")
|
||||||
};
|
};
|
||||||
if program[if_ip].typ != OpType::Keyword(KeywordType::If) {
|
if program[if_ip].typ != OpType::Keyword(KeywordType::If) {
|
||||||
lerror!(&op.clone().loc,"'else' can only close 'if' blocks");
|
lerror!(&op.clone().loc,"'else' can only close 'if' blocks");
|
||||||
return Err(eyre!("Bad block"));
|
bail!("Bad block")
|
||||||
}
|
}
|
||||||
|
|
||||||
program[if_ip].jmp = ip + 1;
|
program[if_ip].jmp = ip + 1;
|
||||||
|
@ -31,7 +30,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||||
OpType::Keyword(KeywordType::End) => {
|
OpType::Keyword(KeywordType::End) => {
|
||||||
let Some(block_ip) = stack.pop() else {
|
let Some(block_ip) = stack.pop() else {
|
||||||
lerror!(&op.loc, "Unclosed if, if-else, while-do, function, memory, or constant");
|
lerror!(&op.loc, "Unclosed if, if-else, while-do, function, memory, or constant");
|
||||||
return Err(eyre!("Cross referencing"));
|
bail!("Cross referencing")
|
||||||
};
|
};
|
||||||
|
|
||||||
match &program[block_ip].typ {
|
match &program[block_ip].typ {
|
||||||
|
@ -50,7 +49,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||||
a => {
|
a => {
|
||||||
println!("{a:?}");
|
println!("{a:?}");
|
||||||
lerror!(&op.clone().loc,"'end' can only close if, if-else, while-do, function, memory, or constant blocks");
|
lerror!(&op.clone().loc,"'end' can only close if, if-else, while-do, function, memory, or constant blocks");
|
||||||
return Err(eyre!(""));
|
bail!("")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +57,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||||
OpType::Keyword(KeywordType::Do) => {
|
OpType::Keyword(KeywordType::Do) => {
|
||||||
let Some(block_ip) = stack.pop() else {
|
let Some(block_ip) = stack.pop() else {
|
||||||
lerror!(&op.loc, "Unclosed while-do block");
|
lerror!(&op.loc, "Unclosed while-do block");
|
||||||
return Err(eyre!("Cross referencing"));
|
bail!("Cross referencing")
|
||||||
};
|
};
|
||||||
|
|
||||||
program[ip].jmp = block_ip;
|
program[ip].jmp = block_ip;
|
||||||
|
@ -70,8 +69,9 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||||
}
|
}
|
||||||
if !stack.is_empty() {
|
if !stack.is_empty() {
|
||||||
// println!("{:?}", stack);
|
// println!("{:?}", stack);
|
||||||
lerror!(&program[stack.pop().expect("Empy stack")].clone().loc,"Unclosed block, {:?}", program[stack.pop().expect("Empy stack")].clone());
|
let i = stack.pop().expect("Empy stack");
|
||||||
return Err(eyre!("Unclosed block"));
|
lerror!(&program[i].clone().loc,"Unclosed block, {:?}", program[i].clone());
|
||||||
|
bail!("Unclosed block")
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(program.clone())
|
Ok(program.clone())
|
||||||
|
@ -97,7 +97,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(&mut self) -> Result<Vec<Operator>> {
|
pub fn parse(&mut self) -> Result<Program> {
|
||||||
let mut tokens = Vec::new();
|
let mut tokens = Vec::new();
|
||||||
|
|
||||||
for token in &self.tokens {
|
for token in &self.tokens {
|
||||||
|
@ -120,12 +120,15 @@ impl<'a> Parser<'a> {
|
||||||
},
|
},
|
||||||
TokenType::String => {
|
TokenType::String => {
|
||||||
tokens.push(Operator::new(OpType::Instruction(InstructionType::PushStr), token.typ, 0, token.text.clone(), token.file.clone(), token.line, token.col));
|
tokens.push(Operator::new(OpType::Instruction(InstructionType::PushStr), token.typ, 0, token.text.clone(), token.file.clone(), token.line, token.col));
|
||||||
}
|
},
|
||||||
|
TokenType::CString => {
|
||||||
|
tokens.push(Operator::new(OpType::Instruction(InstructionType::PushCStr), token.typ, 0, token.text.clone(), token.file.clone(), token.line, token.col));
|
||||||
|
},
|
||||||
TokenType::Char => {
|
TokenType::Char => {
|
||||||
let c = token.text.clone();
|
let c = token.text.clone();
|
||||||
if c.len() != 1 {
|
if c.len() != 1 {
|
||||||
lerror!(&token.loc(), "Chars can only be of lenght 1, got {}", c.len());
|
lerror!(&token.loc(), "Chars can only be of lenght 1, got {}", c.len());
|
||||||
return Err(eyre!(""));
|
bail!("")
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.typ, token.text.chars().next().unwrap() as usize, String::new(), token.file.clone(), token.line, token.col));
|
tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.typ, token.text.chars().next().unwrap() as usize, String::new(), token.file.clone(), token.line, token.col));
|
||||||
|
@ -134,9 +137,9 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
self.preprocessor.program = tokens;
|
self.preprocessor.program.ops = tokens;
|
||||||
let t = self.preprocessor.preprocess()?.get_ops();
|
let mut t = self.preprocessor.preprocess()?.get_program();
|
||||||
let t = cross_ref(t)?;
|
t.ops = cross_ref(t.ops)?;
|
||||||
|
|
||||||
Ok(t)
|
Ok(t)
|
||||||
}
|
}
|
||||||
|
@ -176,12 +179,12 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
|
||||||
|
|
||||||
|
|
||||||
// mem
|
// mem
|
||||||
"load8" => OpType::Instruction(InstructionType::Load8),
|
"read8" => OpType::Instruction(InstructionType::Read8),
|
||||||
"store8" => OpType::Instruction(InstructionType::Store8),
|
"write8" => OpType::Instruction(InstructionType::Write8),
|
||||||
"load32" => OpType::Instruction(InstructionType::Load32),
|
"read32" => OpType::Instruction(InstructionType::Read32),
|
||||||
"store32" => OpType::Instruction(InstructionType::Store32),
|
"write32" => OpType::Instruction(InstructionType::Write32),
|
||||||
"load64" => OpType::Instruction(InstructionType::Load64),
|
"read64" => OpType::Instruction(InstructionType::Read64),
|
||||||
"store64" => OpType::Instruction(InstructionType::Store64),
|
"write64" => OpType::Instruction(InstructionType::Write64),
|
||||||
|
|
||||||
"syscall0" => OpType::Instruction(InstructionType::Syscall0),
|
"syscall0" => OpType::Instruction(InstructionType::Syscall0),
|
||||||
"syscall1" => OpType::Instruction(InstructionType::Syscall1),
|
"syscall1" => OpType::Instruction(InstructionType::Syscall1),
|
||||||
|
@ -208,6 +211,7 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
|
||||||
"done" => OpType::Keyword(KeywordType::FunctionDone),
|
"done" => OpType::Keyword(KeywordType::FunctionDone),
|
||||||
"inline" => OpType::Keyword(KeywordType::Inline),
|
"inline" => OpType::Keyword(KeywordType::Inline),
|
||||||
"export" => OpType::Keyword(KeywordType::Export),
|
"export" => OpType::Keyword(KeywordType::Export),
|
||||||
|
"struct" => OpType::Keyword(KeywordType::Struct),
|
||||||
"return" => OpType::Instruction(InstructionType::Return),
|
"return" => OpType::Instruction(InstructionType::Return),
|
||||||
"returns" => OpType::Instruction(InstructionType::Returns),
|
"returns" => OpType::Instruction(InstructionType::Returns),
|
||||||
"bool" => OpType::Instruction(InstructionType::TypeBool),
|
"bool" => OpType::Instruction(InstructionType::TypeBool),
|
||||||
|
@ -216,6 +220,9 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
|
||||||
"void" => OpType::Instruction(InstructionType::TypeVoid),
|
"void" => OpType::Instruction(InstructionType::TypeVoid),
|
||||||
"any" => OpType::Instruction(InstructionType::TypeAny),
|
"any" => OpType::Instruction(InstructionType::TypeAny),
|
||||||
"with" => OpType::Instruction(InstructionType::With),
|
"with" => OpType::Instruction(InstructionType::With),
|
||||||
|
|
||||||
|
"->" => OpType::Internal(InternalType::Arrow),
|
||||||
|
|
||||||
_ => OpType::Instruction(InstructionType::None)
|
_ => OpType::Instruction(InstructionType::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
|
|
||||||
use color_eyre::Result;
|
use anyhow::{Result, bail};
|
||||||
use eyre::eyre;
|
|
||||||
|
|
||||||
use crate::{constants::{ OpType, InstructionType, Loc, Operator}, lerror};
|
use crate::{definitions::{ OpType, InstructionType, Loc, Operator}, lerror};
|
||||||
|
|
||||||
fn stack_pop(stack: &mut Vec<usize>, loc: &Loc) -> Result<usize> {
|
fn stack_pop(stack: &mut Vec<usize>, loc: &Loc) -> Result<usize> {
|
||||||
if let Some(i) = stack.pop() { Ok(i) } else {
|
if let Some(i) = stack.pop() { Ok(i) } else {
|
||||||
lerror!(&loc.clone(), "Stack underflow");
|
lerror!(&loc.clone(), "Stack underflow");
|
||||||
Err(eyre!("Stack underflow"))
|
bail!("Stack underflow")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,15 +130,16 @@ pub fn precompile(tokens: &Vec<Operator>) -> Result<Vec<usize>>{
|
||||||
_ => {
|
_ => {
|
||||||
lerror!(&token.loc, "Unsupported precompiler instruction {:?}", i);
|
lerror!(&token.loc, "Unsupported precompiler instruction {:?}", i);
|
||||||
dbg!(tokens);
|
dbg!(tokens);
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OpType::Keyword(_) => {
|
OpType::Keyword(_) => {
|
||||||
lerror!(&token.loc, "Unsupported precompiler keyword {:?}", token.typ);
|
lerror!(&token.loc, "Unsupported precompiler keyword {:?}", token.typ);
|
||||||
dbg!(tokens);
|
dbg!(tokens);
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
|
OpType::Internal(t) => panic!("{t:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,7 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{constants::{Operator, Types, OpType, KeywordType, InstructionType, Loc}, Args, lerror, warn};
|
use crate::{definitions::{Operator, Types, OpType, KeywordType, InstructionType, Loc}, Args, lerror, warn};
|
||||||
use color_eyre::Result;
|
use anyhow::{Result, bail};
|
||||||
use eyre::eyre;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -69,12 +68,12 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
if let Some(p) = rtokens.pop() {
|
if let Some(p) = rtokens.pop() {
|
||||||
if p.typ != OpType::Instruction(InstructionType::With){
|
if p.typ != OpType::Instruction(InstructionType::With){
|
||||||
lerror!(&op.loc, "Expected {:?}, got {:?}", OpType::Instruction(InstructionType::With), p.typ);
|
lerror!(&op.loc, "Expected {:?}, got {:?}", OpType::Instruction(InstructionType::With), p.typ);
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
lerror!(&op.loc, "Expected {:?}, got nothing", OpType::Instruction(InstructionType::With));
|
lerror!(&op.loc, "Expected {:?}, got nothing", OpType::Instruction(InstructionType::With));
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut p = rtokens.pop();
|
let mut p = rtokens.pop();
|
||||||
|
@ -92,7 +91,7 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
op.typ == OpType::Instruction(InstructionType::TypeAny) ||
|
op.typ == OpType::Instruction(InstructionType::TypeAny) ||
|
||||||
op.typ == OpType::Instruction(InstructionType::TypeVoid) {
|
op.typ == OpType::Instruction(InstructionType::TypeVoid) {
|
||||||
let t = if op.typ == OpType::Instruction(InstructionType::TypeInt) {
|
let t = if op.typ == OpType::Instruction(InstructionType::TypeInt) {
|
||||||
Types::Int
|
Types::U64
|
||||||
} else if op.typ == OpType::Instruction(InstructionType::TypeBool) {
|
} else if op.typ == OpType::Instruction(InstructionType::TypeBool) {
|
||||||
Types::Bool
|
Types::Bool
|
||||||
} else if op.typ == OpType::Instruction(InstructionType::TypePtr) {
|
} else if op.typ == OpType::Instruction(InstructionType::TypePtr) {
|
||||||
|
@ -153,7 +152,7 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
let (ret_typs, _, _) = typecheck(code, args, Some(ts.clone()), functions.clone(), constants.clone())?;
|
let (ret_typs, _, _) = typecheck(code, args, Some(ts.clone()), functions.clone(), constants.clone())?;
|
||||||
if ret_typs != func.returns && !func.returns.contains(&Types::Void){
|
if ret_typs != func.returns && !func.returns.contains(&Types::Void){
|
||||||
lerror!(&func.loc, "Expected {:?}, but got {:?}", func.returns, ret_typs);
|
lerror!(&func.loc, "Expected {:?}, but got {:?}", func.returns, ret_typs);
|
||||||
return Err(eyre!(""))
|
bail!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !func.args.contains(&Types::Void) {
|
if !func.args.contains(&Types::Void) {
|
||||||
|
@ -170,7 +169,7 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
KeywordType::Memory => (),
|
KeywordType::Memory => (),
|
||||||
KeywordType::ConstantDef => {
|
KeywordType::ConstantDef => {
|
||||||
// println!("defined constant");
|
// println!("defined constant");
|
||||||
constants.insert(op.text, Constant { loc: op.loc.clone(), types: vec![Types::Int] });
|
constants.insert(op.text, Constant { loc: op.loc.clone(), types: vec![Types::U64] });
|
||||||
|
|
||||||
},
|
},
|
||||||
KeywordType::FunctionThen |
|
KeywordType::FunctionThen |
|
||||||
|
@ -181,23 +180,27 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
println!("{:?}", op);
|
println!("{:?}", op);
|
||||||
unreachable!()
|
unreachable!()
|
||||||
},
|
},
|
||||||
|
KeywordType::Struct => todo!(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OpType::Instruction(instruction) => {
|
OpType::Instruction(instruction) => {
|
||||||
match instruction {
|
match instruction {
|
||||||
InstructionType::PushInt => {
|
InstructionType::PushInt => {
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::PushStr => {
|
InstructionType::PushStr => {
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
|
stack.push(Types::Ptr);
|
||||||
|
},
|
||||||
|
InstructionType::PushCStr => {
|
||||||
|
stack.push(Types::U64);
|
||||||
stack.push(Types::Ptr);
|
stack.push(Types::Ptr);
|
||||||
|
|
||||||
},
|
},
|
||||||
InstructionType::Drop => {
|
InstructionType::Drop => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
},
|
},
|
||||||
InstructionType::Print => {
|
InstructionType::Print => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
},
|
},
|
||||||
InstructionType::Dup => {
|
InstructionType::Dup => {
|
||||||
let a = stack_pop(&mut stack, &op, &[Types::Any])?;
|
let a = stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
|
@ -231,9 +234,9 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
InstructionType::Shr |
|
InstructionType::Shr |
|
||||||
InstructionType::Shl |
|
InstructionType::Shl |
|
||||||
InstructionType::Mul => {
|
InstructionType::Mul => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::Equals |
|
InstructionType::Equals |
|
||||||
InstructionType::Gt |
|
InstructionType::Gt |
|
||||||
|
@ -241,76 +244,76 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
InstructionType::Ge |
|
InstructionType::Ge |
|
||||||
InstructionType::Le |
|
InstructionType::Le |
|
||||||
InstructionType::NotEquals => {
|
InstructionType::NotEquals => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack.push(Types::Bool);
|
stack.push(Types::Bool);
|
||||||
},
|
},
|
||||||
InstructionType::DivMod => {
|
InstructionType::DivMod => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::Load8 |
|
InstructionType::Read8 |
|
||||||
InstructionType::Load32 |
|
InstructionType::Read32 |
|
||||||
InstructionType::Load64 => {
|
InstructionType::Read64 => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::Store8 |
|
InstructionType::Write8 |
|
||||||
InstructionType::Store32 |
|
InstructionType::Write32 |
|
||||||
InstructionType::Store64 => {
|
InstructionType::Write64 => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
||||||
},
|
},
|
||||||
InstructionType::Syscall0 => {
|
InstructionType::Syscall0 => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::Syscall1 => {
|
InstructionType::Syscall1 => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::Syscall2 => {
|
InstructionType::Syscall2 => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::Syscall3 => {
|
InstructionType::Syscall3 => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::Syscall4 => {
|
InstructionType::Syscall4 => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::Syscall5 => {
|
InstructionType::Syscall5 => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::Syscall6 => {
|
InstructionType::Syscall6 => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::CastBool => {
|
InstructionType::CastBool => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
|
@ -322,7 +325,7 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
},
|
},
|
||||||
InstructionType::CastInt => {
|
InstructionType::CastInt => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::U64);
|
||||||
},
|
},
|
||||||
InstructionType::CastVoid => {
|
InstructionType::CastVoid => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||||
|
@ -336,7 +339,7 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
|
|
||||||
let f = if let Some(f) = functions.get(&op.text) {f} else {
|
let f = if let Some(f) = functions.get(&op.text) {f} else {
|
||||||
lerror!(&op.loc, "Could not find function {}", op.text);
|
lerror!(&op.loc, "Could not find function {}", op.text);
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
};
|
};
|
||||||
|
|
||||||
// in_function = (op.text.clone(), f.clone(), op.loc.clone());
|
// in_function = (op.text.clone(), f.clone(), op.loc.clone());
|
||||||
|
@ -350,11 +353,11 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
if let Some(s2) = s.pop(){
|
if let Some(s2) = s.pop(){
|
||||||
if t != s2 {
|
if t != s2 {
|
||||||
lerror!(&op.loc, "Expected {:?}, but got {:?}", t, s2);
|
lerror!(&op.loc, "Expected {:?}, but got {:?}", t, s2);
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lerror!(&op.loc, "Expected {:?}, but got nothing", t);
|
lerror!(&op.loc, "Expected {:?}, but got nothing", t);
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,8 +377,10 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
let mut c = constants.get(&op.text).unwrap().clone();
|
let mut c = constants.get(&op.text).unwrap().clone();
|
||||||
stack.append(&mut c.types);
|
stack.append(&mut c.types);
|
||||||
},
|
},
|
||||||
|
InstructionType::StructUse => todo!(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
OpType::Internal(t) => panic!("{t:?}"),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,13 +395,13 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
||||||
fn stack_pop(v: &mut Vec<Types>, op: &Operator, t: &[Types]) -> Result<Types> {
|
fn stack_pop(v: &mut Vec<Types>, op: &Operator, t: &[Types]) -> Result<Types> {
|
||||||
if v.is_empty() {
|
if v.is_empty() {
|
||||||
lerror!(&op.loc, "Expected {:?}, but got nothing", t);
|
lerror!(&op.loc, "Expected {:?}, but got nothing", t);
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
let r = v.pop().unwrap();
|
let r = v.pop().unwrap();
|
||||||
|
|
||||||
if !t.contains(&r) && t[0] != Types::Any {
|
if !t.contains(&r) && t[0] != Types::Any {
|
||||||
lerror!(&op.loc, "Expected {:?}, but got {:?}", t, r);
|
lerror!(&op.loc, "Expected {:?}, but got {:?}", t, r);
|
||||||
return Err(eyre!(""));
|
bail!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(r)
|
Ok(r)
|
||||||
|
|
392
src/types.rs
Normal file
392
src/types.rs
Normal file
|
@ -0,0 +1,392 @@
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use eyre::bail;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum InstructionType {
|
||||||
|
|
||||||
|
// stack
|
||||||
|
PushInt,
|
||||||
|
PushStr,
|
||||||
|
PushCStr,
|
||||||
|
Drop,
|
||||||
|
Print,
|
||||||
|
Dup,
|
||||||
|
Rot, // a b c => b c a
|
||||||
|
Over, // a b => a b a
|
||||||
|
Swap, // a b => b a
|
||||||
|
|
||||||
|
// math
|
||||||
|
Minus,
|
||||||
|
Plus,
|
||||||
|
Equals,
|
||||||
|
Gt,
|
||||||
|
Lt,
|
||||||
|
Ge,
|
||||||
|
Le,
|
||||||
|
NotEquals,
|
||||||
|
Band, // &
|
||||||
|
Bor, // |
|
||||||
|
Shr, // >>
|
||||||
|
Shl, // <<
|
||||||
|
DivMod, // /
|
||||||
|
Mul,
|
||||||
|
|
||||||
|
|
||||||
|
// mem
|
||||||
|
Read8,
|
||||||
|
Write8,
|
||||||
|
Read32,
|
||||||
|
Write32,
|
||||||
|
Read64,
|
||||||
|
Write64,
|
||||||
|
|
||||||
|
// syscalls
|
||||||
|
Syscall0,
|
||||||
|
Syscall1,
|
||||||
|
Syscall2,
|
||||||
|
Syscall3,
|
||||||
|
Syscall4,
|
||||||
|
Syscall5,
|
||||||
|
Syscall6,
|
||||||
|
|
||||||
|
CastBool,
|
||||||
|
CastPtr,
|
||||||
|
CastInt,
|
||||||
|
CastVoid,
|
||||||
|
|
||||||
|
// typing
|
||||||
|
TypeBool,
|
||||||
|
TypePtr,
|
||||||
|
TypeInt,
|
||||||
|
TypeVoid,
|
||||||
|
// TypeStr,
|
||||||
|
TypeAny,
|
||||||
|
Returns,
|
||||||
|
With,
|
||||||
|
|
||||||
|
FnCall,
|
||||||
|
MemUse,
|
||||||
|
ConstUse,
|
||||||
|
|
||||||
|
Return,
|
||||||
|
None // Used for macros and any other non built in word definitions
|
||||||
|
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub enum KeywordType {
|
||||||
|
If,
|
||||||
|
Else,
|
||||||
|
End,
|
||||||
|
While,
|
||||||
|
Do,
|
||||||
|
Include,
|
||||||
|
Memory,
|
||||||
|
Constant,
|
||||||
|
ConstantDef,
|
||||||
|
Function,
|
||||||
|
FunctionDef,
|
||||||
|
FunctionDefExported,
|
||||||
|
FunctionThen,
|
||||||
|
FunctionDone,
|
||||||
|
Inline,
|
||||||
|
Export,
|
||||||
|
Struct,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub enum InternalType {
|
||||||
|
Arrow
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum OpType {
|
||||||
|
Keyword(KeywordType),
|
||||||
|
Instruction(InstructionType),
|
||||||
|
Internal(InternalType)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Operator{
|
||||||
|
pub typ: OpType,
|
||||||
|
pub tok_typ: TokenType,
|
||||||
|
pub value: usize,
|
||||||
|
pub text: String, //? only used for OpType::PushStr
|
||||||
|
pub addr: Option<usize>, //? only used for OpType::PushStr
|
||||||
|
pub jmp: usize,
|
||||||
|
pub loc: Loc,
|
||||||
|
pub types: (usize, usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Operator {
|
||||||
|
pub fn new(typ: OpType, tok_typ: TokenType, value: usize, text: String, file: String, row: usize, col: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
typ,
|
||||||
|
value,
|
||||||
|
jmp: 0,
|
||||||
|
addr: None,
|
||||||
|
text,
|
||||||
|
loc: (file, row, col),
|
||||||
|
tok_typ,
|
||||||
|
types: (0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn set_addr(&mut self, addr: usize) -> Self {
|
||||||
|
self.addr = Some(addr);
|
||||||
|
(*self).clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn set_types(&mut self, args: usize, rets: usize) -> Self {
|
||||||
|
// self.types = (args, rets);
|
||||||
|
// (*self).clone()
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OpType {
|
||||||
|
pub fn human(&self) -> String {
|
||||||
|
match (*self).clone() {
|
||||||
|
OpType::Instruction(instruction) => {
|
||||||
|
match instruction {
|
||||||
|
|
||||||
|
InstructionType::PushInt => "Number",
|
||||||
|
InstructionType::PushStr => "String",
|
||||||
|
InstructionType::PushCStr => "CString",
|
||||||
|
InstructionType::Print => "_dbg_print",
|
||||||
|
InstructionType::Dup => "dup",
|
||||||
|
InstructionType::Drop => "drop",
|
||||||
|
InstructionType::Rot => "rot",
|
||||||
|
InstructionType::Over => "over",
|
||||||
|
InstructionType::Swap => "swap",
|
||||||
|
InstructionType::Plus => "+",
|
||||||
|
InstructionType::Minus => "-",
|
||||||
|
InstructionType::Equals => "=",
|
||||||
|
InstructionType::Gt => ">",
|
||||||
|
InstructionType::Lt => "<",
|
||||||
|
InstructionType::NotEquals => "!=",
|
||||||
|
InstructionType::Le => "<=",
|
||||||
|
InstructionType::Ge => ">=",
|
||||||
|
InstructionType::Band => "band",
|
||||||
|
InstructionType::Bor => "bor",
|
||||||
|
InstructionType::Shr => "shr",
|
||||||
|
InstructionType::Shl => "shl",
|
||||||
|
InstructionType::DivMod => "divmod",
|
||||||
|
InstructionType::Mul => "*",
|
||||||
|
InstructionType::Read8 => "read8",
|
||||||
|
InstructionType::Write8 => "write8",
|
||||||
|
InstructionType::Read32 => "read32",
|
||||||
|
InstructionType::Write32 => "write32",
|
||||||
|
InstructionType::Read64 => "read64",
|
||||||
|
InstructionType::Write64 => "write64",
|
||||||
|
InstructionType::Syscall0 => "syscall0",
|
||||||
|
InstructionType::Syscall1 => "syscall1",
|
||||||
|
InstructionType::Syscall2 => "syscall2",
|
||||||
|
InstructionType::Syscall3 => "syscall3",
|
||||||
|
InstructionType::Syscall4 => "syscall4",
|
||||||
|
InstructionType::Syscall5 => "syscall5",
|
||||||
|
InstructionType::Syscall6 => "syscall6",
|
||||||
|
InstructionType::CastBool => "cast(bool",
|
||||||
|
InstructionType::CastPtr => "cast(ptr)",
|
||||||
|
InstructionType::CastInt => "cast(int)",
|
||||||
|
InstructionType::CastVoid => "cast(void)",
|
||||||
|
InstructionType::None => "None",
|
||||||
|
InstructionType::MemUse => "Memory use (internal)",
|
||||||
|
InstructionType::FnCall => "Function Call (Internal)",
|
||||||
|
InstructionType::ConstUse => "Constant Use (Internal)",
|
||||||
|
InstructionType::Return => "return",
|
||||||
|
InstructionType::TypeBool => "bool",
|
||||||
|
InstructionType::TypePtr => "ptr",
|
||||||
|
InstructionType::TypeInt => "int",
|
||||||
|
InstructionType::TypeVoid => "void",
|
||||||
|
InstructionType::Returns => "returns",
|
||||||
|
InstructionType::With => "with",
|
||||||
|
InstructionType::TypeAny => "any",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OpType::Keyword(keyword) => {
|
||||||
|
match keyword {
|
||||||
|
KeywordType::If => "if",
|
||||||
|
KeywordType::Else => "else",
|
||||||
|
KeywordType::End => "end",
|
||||||
|
KeywordType::While => "while",
|
||||||
|
KeywordType::Do => "do",
|
||||||
|
KeywordType::Include => "include",
|
||||||
|
KeywordType::Memory => "memory",
|
||||||
|
KeywordType::Function => "fn",
|
||||||
|
KeywordType::Constant => "const",
|
||||||
|
KeywordType::FunctionThen => "then",
|
||||||
|
KeywordType::FunctionDone => "done",
|
||||||
|
KeywordType::ConstantDef => "constant Definition (internal)",
|
||||||
|
KeywordType::FunctionDef => "function definition (internal)",
|
||||||
|
KeywordType::FunctionDefExported => "extern function definition (internal)",
|
||||||
|
KeywordType::Inline => "inline",
|
||||||
|
KeywordType::Export => "export",
|
||||||
|
KeywordType::Struct => "struct",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OpType::Internal(t) => panic!("{t:?}"),
|
||||||
|
|
||||||
|
}.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Token {
|
||||||
|
pub file: String,
|
||||||
|
pub line: usize,
|
||||||
|
pub col: usize,
|
||||||
|
pub text: String,
|
||||||
|
pub typ: TokenType,
|
||||||
|
pub value: Option<usize>, //* only used for Memories
|
||||||
|
pub addr: Option<usize>, //* only used for Memories
|
||||||
|
pub op_typ: OpType //* only used for Memories
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||||
|
pub enum TokenType {
|
||||||
|
Word,
|
||||||
|
Int,
|
||||||
|
String,
|
||||||
|
CString,
|
||||||
|
Char
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Token {
|
||||||
|
pub fn loc(&self) -> Loc {
|
||||||
|
(
|
||||||
|
self.file.clone(),
|
||||||
|
self.line,
|
||||||
|
self.col
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TokenType {
|
||||||
|
pub fn human(self) -> String {
|
||||||
|
match self {
|
||||||
|
TokenType::Word => "Word",
|
||||||
|
TokenType::Int => "Int",
|
||||||
|
TokenType::String => "String",
|
||||||
|
TokenType::CString => "CString",
|
||||||
|
TokenType::Char => "Char"
|
||||||
|
}.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Loc = (String, usize, usize);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum Types {
|
||||||
|
Any,
|
||||||
|
Bool,
|
||||||
|
Ptr,
|
||||||
|
Void,
|
||||||
|
U8,
|
||||||
|
U16,
|
||||||
|
U32,
|
||||||
|
U64,
|
||||||
|
I8,
|
||||||
|
I16,
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
Custom{
|
||||||
|
size: u64 // in bytes
|
||||||
|
},
|
||||||
|
// todo: add signed numbers since we dont have them yet lol
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Types {
|
||||||
|
pub fn get_size(&self) -> u64 {
|
||||||
|
match *self {
|
||||||
|
Types::Any => 0, // any cant be a known size
|
||||||
|
Types::Void => 0,
|
||||||
|
Types::Bool => 1,
|
||||||
|
Types::U8 |
|
||||||
|
Types::I8 => 1,
|
||||||
|
Types::U16 |
|
||||||
|
Types::I16 => 2,
|
||||||
|
Types::U32 |
|
||||||
|
Types::I32 => 4,
|
||||||
|
Types::Ptr |
|
||||||
|
Types::U64 |
|
||||||
|
Types::I64 => 8,
|
||||||
|
Types::Custom { size } => size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryInto<Types> for &str {
|
||||||
|
type Error = color_eyre::eyre::Error;
|
||||||
|
|
||||||
|
fn try_into(self) -> Result<Types, Self::Error> {
|
||||||
|
match self {
|
||||||
|
"Any" => Ok(Types::Any),
|
||||||
|
"Void" => Ok(Types::Void),
|
||||||
|
"Bool" => Ok(Types::Bool),
|
||||||
|
"U8" => Ok(Types::U8),
|
||||||
|
"I8" => Ok(Types::I8),
|
||||||
|
"U16" => Ok(Types::U16),
|
||||||
|
"I16" => Ok(Types::I16),
|
||||||
|
"U32" => Ok(Types::U32),
|
||||||
|
"I32" => Ok(Types::I32),
|
||||||
|
"Ptr" => Ok(Types::Ptr),
|
||||||
|
"U64" => Ok(Types::U64),
|
||||||
|
"I64" => Ok(Types::I64),
|
||||||
|
_ => bail!("Unknown type {self}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryInto<Types> for String {
|
||||||
|
type Error = color_eyre::eyre::Error;
|
||||||
|
|
||||||
|
fn try_into(self) -> Result<Types, Self::Error> {
|
||||||
|
self.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Function {
|
||||||
|
pub loc: Loc,
|
||||||
|
pub name: String,
|
||||||
|
pub inline: bool,
|
||||||
|
pub tokens: Option<Vec<Operator>>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Constant {
|
||||||
|
pub loc: Loc,
|
||||||
|
pub name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Memory {
|
||||||
|
pub loc: Loc,
|
||||||
|
pub id: usize
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct StructDef {
|
||||||
|
pub loc: Loc,
|
||||||
|
pub name: String,
|
||||||
|
pub fields: HashSet<(String, Types)>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Functions = HashMap<String, Function>;
|
||||||
|
pub type Memories = HashMap<String, Memory>;
|
||||||
|
pub type Constants = HashMap<String, Constant>;
|
||||||
|
pub type StructDefs = HashMap<String, StructDef>;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Program {
|
||||||
|
pub ops: Vec<Operator>,
|
||||||
|
pub functions: Functions,
|
||||||
|
pub memories: Memories,
|
||||||
|
pub constants: Constants,
|
||||||
|
pub struct_defs: StructDefs
|
||||||
|
}
|
29
src/types/common/loc.rs
Normal file
29
src/types/common/loc.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Loc {
|
||||||
|
pub ln: usize,
|
||||||
|
pub col: usize,
|
||||||
|
pub file: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Loc {
|
||||||
|
pub fn new(file: String, ln: usize, col: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
ln,
|
||||||
|
col,
|
||||||
|
file,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for Loc {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
format!("{}:{}:{}", self.file, self.ln, self.col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<String> for Loc {
|
||||||
|
fn into(self) -> String {
|
||||||
|
self.to_string()
|
||||||
|
}
|
||||||
|
}
|
4
src/types/common/mod.rs
Normal file
4
src/types/common/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
mod loc;
|
||||||
|
|
||||||
|
|
||||||
|
pub use loc::*;
|
4
src/types/mod.rs
Normal file
4
src/types/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
|
||||||
|
pub mod common;
|
||||||
|
pub mod token;
|
65
src/types/token.rs
Normal file
65
src/types/token.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
use super::common::Loc;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Token {
|
||||||
|
loc: Loc,
|
||||||
|
typ: TokenType,
|
||||||
|
val: TokenValue
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TokenValue {
|
||||||
|
Int(usize),
|
||||||
|
Str(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TokenType {
|
||||||
|
DbgPrint,
|
||||||
|
Keyword(TokenKeyword),
|
||||||
|
Syscall(u8),
|
||||||
|
|
||||||
|
//? Literal
|
||||||
|
PushInt,
|
||||||
|
PushStr,
|
||||||
|
|
||||||
|
//? Stack manipulation
|
||||||
|
Dup,
|
||||||
|
Rot, // a b c => b c a
|
||||||
|
Over, // a b => a b a
|
||||||
|
Swap, // a b => b a
|
||||||
|
|
||||||
|
//? Math
|
||||||
|
Plus,
|
||||||
|
Minus,
|
||||||
|
Mul,
|
||||||
|
Div,
|
||||||
|
Mod,
|
||||||
|
|
||||||
|
//? Logical
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
Eq,
|
||||||
|
Gt,
|
||||||
|
Lt,
|
||||||
|
Ge,
|
||||||
|
Le,
|
||||||
|
Ne,
|
||||||
|
|
||||||
|
//? Bitwise
|
||||||
|
Shr,
|
||||||
|
Shl,
|
||||||
|
Bor,
|
||||||
|
Band,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TokenKeyword {
|
||||||
|
Function,
|
||||||
|
If,
|
||||||
|
Else,
|
||||||
|
End,
|
||||||
|
Done,
|
||||||
|
Macro,
|
||||||
|
While,
|
||||||
|
Do
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ pub mod logger {
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use crate::{util::color, constants::Loc};
|
use crate::{util::color, definitions::Loc};
|
||||||
|
|
||||||
pub fn error(msg: &str) {
|
pub fn error(msg: &str) {
|
||||||
println!("{red}error{r}: {msg}", red=color::FG_RED, r=color::RESET);
|
println!("{red}error{r}: {msg}", red=color::FG_RED, r=color::RESET);
|
||||||
|
|
21
test.mcl
21
test.mcl
|
@ -1,12 +1,13 @@
|
||||||
// include "std.mcl"
|
include "std.mcl"
|
||||||
fn mcl_print with int ptr returns void then
|
|
||||||
1 1 syscall3 drop
|
|
||||||
done
|
|
||||||
|
|
||||||
fn mcl_dump with int returns void then
|
|
||||||
_dbg_print
|
|
||||||
done
|
|
||||||
|
|
||||||
fn main with void returns void then
|
fn main with int ptr returns void then
|
||||||
"hi\n" mcl_print
|
// p l
|
||||||
done
|
"Hello!\n" puts
|
||||||
|
|
||||||
|
// memory fd 4 end
|
||||||
|
|
||||||
|
// c"./test.mcl" FS_O_SYNC 0 fopen
|
||||||
|
// dup _dbg_print
|
||||||
|
// fd swap write32
|
||||||
|
done
|
4
tools/.gitignore
vendored
Normal file
4
tools/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
/*
|
||||||
|
!/.gitignore
|
||||||
|
!/*.c
|
||||||
|
!/build_tools.sh
|
3
tools/build_tools.sh
Normal file
3
tools/build_tools.sh
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
gcc intcnv.c -o intcnv
|
47
tools/intcnv.c
Normal file
47
tools/intcnv.c
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#include<stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
if (argc < 3) {
|
||||||
|
printf("Usage: intcnv i32 134\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* typ = argv[1];
|
||||||
|
__uint64_t num = atoi(argv[2]);
|
||||||
|
|
||||||
|
if (strcmp(typ, "u8") == 0) {
|
||||||
|
__uint8_t num2 = (__uint8_t)num;
|
||||||
|
printf("%d\n", num2);
|
||||||
|
}
|
||||||
|
if (strcmp(typ, "i8") == 0) {
|
||||||
|
__int8_t num2 = (__int8_t)num;
|
||||||
|
printf("%d\n", num2);
|
||||||
|
}
|
||||||
|
if (strcmp(typ, "u16") == 0) {
|
||||||
|
__uint16_t num2 = (__uint16_t)num;
|
||||||
|
printf("%d\n", num2);
|
||||||
|
}
|
||||||
|
if (strcmp(typ, "i16") == 0) {
|
||||||
|
__int16_t num2 = (__int16_t)num;
|
||||||
|
printf("%d\n", num2);
|
||||||
|
}
|
||||||
|
if (strcmp(typ, "u32") == 0) {
|
||||||
|
__uint32_t num2 = (__uint32_t)num;
|
||||||
|
printf("%d\n", num2);
|
||||||
|
}
|
||||||
|
if (strcmp(typ, "i32") == 0) {
|
||||||
|
__int32_t num2 = (__int32_t)num;
|
||||||
|
printf("%d\n", num2);
|
||||||
|
}
|
||||||
|
if (strcmp(typ, "u64") == 0) {
|
||||||
|
__uint64_t num2 = (__uint64_t)num;
|
||||||
|
printf("%d\n", num2);
|
||||||
|
}
|
||||||
|
if (strcmp(typ, "i64") == 0) {
|
||||||
|
__int64_t num2 = (__int64_t)num;
|
||||||
|
printf("%d\n", num2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user