IDK
This commit is contained in:
parent
9625256554
commit
5b51430df1
20
.gitignore
vendored
20
.gitignore
vendored
|
@ -1,6 +1,18 @@
|
|||
/target
|
||||
/a
|
||||
/*
|
||||
|
||||
test
|
||||
test.nasm
|
||||
test.o
|
||||
# files
|
||||
!/.gitignore
|
||||
!/cargo.lock
|
||||
!/cargo.toml
|
||||
!/README.md
|
||||
|
||||
# folders
|
||||
!/.github
|
||||
!/editor
|
||||
!/examples
|
||||
!/include
|
||||
!/playground
|
||||
!/src
|
||||
!/tests
|
||||
!/tools
|
203
Cargo.lock
generated
203
Cargo.lock
generated
|
@ -3,34 +3,10 @@
|
|||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.19.0"
|
||||
name = "anyhow"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
||||
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",
|
||||
]
|
||||
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
|
@ -44,12 +20,6 @@ version = "1.0.79"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.1.8"
|
||||
|
@ -87,33 +57,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "errno"
|
||||
version = "0.2.8"
|
||||
|
@ -135,22 +78,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
|
@ -163,12 +90,6 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||
|
||||
[[package]]
|
||||
name = "indenter"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.6"
|
||||
|
@ -191,12 +112,6 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.140"
|
||||
|
@ -213,33 +128,8 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
|||
name = "mclangc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"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]]
|
||||
|
@ -254,18 +144,6 @@ version = "6.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
|
@ -308,12 +186,6 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.9"
|
||||
|
@ -328,15 +200,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
|
@ -363,70 +226,12 @@ dependencies = [
|
|||
"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]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
|
|
|
@ -9,6 +9,5 @@ authors=[
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.79"
|
||||
clap = { version = "4.1.8", features = ["derive"] }
|
||||
color-eyre = "0.6.2"
|
||||
eyre = "0.6.8"
|
||||
|
|
|
@ -22,6 +22,8 @@ You can find the docs [here](/docs/index.md)
|
|||
|
||||
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
|
||||
|
|
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_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_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_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
|
||||
|
@ -15,7 +21,6 @@ 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_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_TRUNC 512 end // if file exists, ovewrite it (careful!)
|
||||
|
||||
|
||||
fn fs_read_to_string with int ptr returns int ptr then
|
||||
|
|
|
@ -12,4 +12,9 @@ inline fn drop2 with any any returns void then drop drop done
|
|||
const sizeof(u64) 8 end
|
||||
const sizeof(u32) 4 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
|
|
@ -49,7 +49,7 @@ inline fn eputs with int ptr returns void then
|
|||
STDOUT fwrite drop
|
||||
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
|
||||
// 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, fs};
|
||||
use clap::Parser;
|
||||
use color_eyre::Result;
|
||||
use eyre::eyre;
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
pub mod color {
|
||||
#![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!("compiled:\n{}", comp.stdout);
|
||||
println!("interpreted:\n{}", intp.stdout);
|
||||
return Err(eyre!("Testing failed"));
|
||||
bail!("Testing failed");
|
||||
}
|
||||
|
||||
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!("compiled:\n{}", comp.stderr);
|
||||
println!("interpreted:\n{}", intp.stderr);
|
||||
return Err(eyre!("Testing failed"));
|
||||
bail!("Testing failed");
|
||||
}
|
||||
|
||||
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!("compiled:\n{}", comp.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());
|
||||
|
@ -164,7 +163,7 @@ fn main() -> Result<()> {
|
|||
"record" => todo!("Implement test result recording"),
|
||||
s => {
|
||||
eprintln!("Unknown mode '{s}'");
|
||||
return Err(eyre!("Bad subcommand"));
|
||||
bail!("Bad subcommand");
|
||||
}
|
||||
}?;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::path::{PathBuf, Path};
|
||||
use std::process::{Command, Stdio};
|
||||
use color_eyre::Result;
|
||||
use crate::info;
|
||||
use anyhow::Result;
|
||||
use crate::{info, error};
|
||||
|
||||
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") {
|
||||
return Ok(());
|
||||
} else {
|
||||
Command::new("nasm")
|
||||
let ret = Command::new("nasm")
|
||||
.args(nasm_args)
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.spawn()?
|
||||
.spawn();
|
||||
|
||||
if ret.is_err() {
|
||||
error!("Nasm not installed")
|
||||
}
|
||||
ret?
|
||||
};
|
||||
if !quiet {
|
||||
info!("running 'nasm {}'", nasm_args.join(" "));
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use std::{fs, path::PathBuf, io::{Write, BufWriter}, collections::HashMap};
|
||||
use crate::{constants::{Operator, OpType, KeywordType}, Args, warn, lerror};
|
||||
use color_eyre::Result;
|
||||
use crate::{definitions::*, Args, warn, lerror};
|
||||
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 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 mut of_c = PathBuf::from(&args.out_file);
|
||||
|
@ -32,45 +32,17 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
let mut memories: Vec<Memory> = Vec::new();
|
||||
let mut constants: HashMap<String, Constant> = HashMap::new();
|
||||
let mut functions: Vec<Function> = Vec::new();
|
||||
|
||||
let mut alloced_structs: Vec<(String, String)> = Vec::new();
|
||||
// println!("{}", tokens.len());
|
||||
let mut strings: Vec<String> = Vec::new();
|
||||
|
||||
writeln!(writer, "BITS 64")?;
|
||||
writeln!(writer, "segment .text")?;
|
||||
|
||||
writeln!(writer, "_dbg_print:")?;
|
||||
writeln!(writer, " mov r9, -3689348814741910323")?;
|
||||
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")?;
|
||||
writeln!(writer, "{}", super::MACRO_DEFINITIONS)?;
|
||||
writeln!(writer, "{}", super::DBG_PRINT)?;
|
||||
|
||||
|
||||
if !crate::config::ENABLE_EXPORTED_FUNCTIONS && !args.lib_mode {
|
||||
writeln!(writer, "global _start")?;
|
||||
|
@ -82,8 +54,8 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
|
||||
|
||||
let mut ti = 0;
|
||||
while ti < tokens.len() {
|
||||
let token = &tokens[ti];
|
||||
while ti < program.ops.len() {
|
||||
let token = &program.ops[ti];
|
||||
if debug {
|
||||
writeln!(writer, "addr_{ti}:")?;
|
||||
if token.typ == OpType::Instruction(InstructionType::PushInt) {
|
||||
|
@ -95,13 +67,13 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
}
|
||||
} else {
|
||||
if ti > 0 {
|
||||
if tokens[ti-1].typ == OpType::Keyword(KeywordType::Else) ||
|
||||
tokens[ti-1].typ == OpType::Keyword(KeywordType::End){
|
||||
if program.ops[ti-1].typ == OpType::Keyword(KeywordType::Else) ||
|
||||
program.ops[ti-1].typ == OpType::Keyword(KeywordType::End){
|
||||
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}:")?;
|
||||
}
|
||||
|
||||
|
@ -122,298 +94,160 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
OpType::Instruction(instruction) => {
|
||||
match instruction {
|
||||
InstructionType::PushInt => {
|
||||
writeln!(writer, " mov rax, {}", token.value)?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " OP_PushInt {}", token.value)?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::PushStr => {
|
||||
writeln!(writer, " mov rax, {}", token.text.len())?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " mov rax, str_{}", strings.len())?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " OP_PushStr {}, str_{}", token.text.len(), strings.len())?;
|
||||
strings.push(token.text.clone());
|
||||
ti += 1;
|
||||
}
|
||||
InstructionType::PushCStr => {
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " mov rax, str_{}", strings.len())?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " OP_PushCStr str_{}", strings.len())?;
|
||||
strings.push(token.text.clone());
|
||||
ti += 1;
|
||||
}
|
||||
InstructionType::Drop => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " OP_Drop")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Print => {
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " call _dbg_print")?;
|
||||
writeln!(writer, " OP_Print")?;
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
InstructionType::Dup => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
|
||||
writeln!(writer, " OP_Dup")?;
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
InstructionType::Rot => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rcx")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rcx")?;
|
||||
|
||||
writeln!(writer, " OP_Rot")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Swap => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
|
||||
writeln!(writer, " OP_Swap")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Over => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
|
||||
writeln!(writer, " OP_Over")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Load8 => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " xor rbx, rbx")?;
|
||||
writeln!(writer, " mov bl, byte [rax]")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
InstructionType::Read8 => {
|
||||
writeln!(writer, " OP_Load8")?;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
InstructionType::Store8 => {
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " mov byte [rax], bl")?;
|
||||
InstructionType::Write8 => {
|
||||
writeln!(writer, " OP_Store8")?;
|
||||
ti += 1;
|
||||
}
|
||||
InstructionType::Load32 => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " xor rbx, rbx")?;
|
||||
writeln!(writer, " mov ebx, dword [rax]")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
InstructionType::Read32 => {
|
||||
writeln!(writer, " OP_Load32")?;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
InstructionType::Store32 => {
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " mov dword[rax], ebx")?;
|
||||
InstructionType::Write32 => {
|
||||
writeln!(writer, " OP_Store32")?;
|
||||
ti += 1;
|
||||
}
|
||||
InstructionType::Load64 => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " xor rbx, rbx")?;
|
||||
writeln!(writer, " mov rbx, qword [rax]")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
InstructionType::Read64 => {
|
||||
writeln!(writer, " OP_Load64")?;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
InstructionType::Store64 => {
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " mov qword [rax], rbx")?;
|
||||
InstructionType::Write64 => {
|
||||
writeln!(writer, " OP_Store64")?;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
// math
|
||||
InstructionType::Plus => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " add rax, rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " OP_Plus")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Minus => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " sub rbx, rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " OP_Minus")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Equals => {
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
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")?;
|
||||
writeln!(writer, " OP_Equals")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Lt => {
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
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")?;
|
||||
writeln!(writer, " OP_Lt")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Gt => {
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
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")?;
|
||||
writeln!(writer, " OP_Gt")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::NotEquals => {
|
||||
writeln!(writer, " mov rcx, 1")?;
|
||||
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")?;
|
||||
writeln!(writer, " OP_NotEquals")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Le => {
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
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")?;
|
||||
writeln!(writer, " OP_Le")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Ge => {
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
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")?;
|
||||
writeln!(writer, " OP_Ge")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Band => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " and rbx, rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " OP_Band")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Bor => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " or rbx, rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " OP_Bor")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Shr => {
|
||||
writeln!(writer, " pop rcx")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " shr rbx, cl")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " OP_Shr")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Shl => {
|
||||
writeln!(writer, " pop rcx")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " shl rbx, cl")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " OP_Shl")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::DivMod => {
|
||||
writeln!(writer, " xor rdx, rdx")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " div rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rdx")?;
|
||||
writeln!(writer, " OP_DivMod")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Mul => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " mul rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " OP_Mul")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Syscall0 => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " OP_Syscall0")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Syscall1 => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " OP_Syscall1")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Syscall2 => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " OP_Syscall2")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Syscall3 => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
writeln!(writer, " pop rdx")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
|
||||
writeln!(writer, " OP_Syscall3")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Syscall4 => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
writeln!(writer, " pop rdx")?;
|
||||
writeln!(writer, " pop r10")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " OP_Syscall4")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Syscall5 => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
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")?;
|
||||
writeln!(writer, " OP_Syscall5")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Syscall6 => {
|
||||
writeln!(writer, " pop rax")?;
|
||||
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")?;
|
||||
writeln!(writer, " OP_Syscall6")?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::MemUse => {
|
||||
writeln!(writer, " push mem_{}", token.addr.unwrap())?;
|
||||
writeln!(writer, " OP_MemUse {}", token.addr.unwrap())?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::None => {
|
||||
|
@ -421,7 +255,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
unreachable!()
|
||||
},
|
||||
InstructionType::FnCall => {
|
||||
writeln!(writer, " call {}", token.text)?;
|
||||
writeln!(writer, " OP_FnCall {}", token.text)?;
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::Return => {
|
||||
|
@ -452,8 +286,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
ti += 1;
|
||||
}
|
||||
InstructionType::ConstUse => {
|
||||
writeln!(writer, " mov rax, qword [const_{}]", token.text)?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " OP_ConstUse {}", token.text)?;
|
||||
|
||||
let mut c = constants.get(&token.text).unwrap().clone();
|
||||
c.used = true;
|
||||
|
@ -461,6 +294,10 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
constants.insert(token.text.clone(), c);
|
||||
ti += 1;
|
||||
},
|
||||
InstructionType::StructUse => {
|
||||
writeln!(writer, " OP_StructUse {}", token.text)?;
|
||||
ti += 1;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -529,16 +366,11 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
ti += 1;
|
||||
}
|
||||
KeywordType::FunctionThen => ti += 1,
|
||||
KeywordType::Function |
|
||||
KeywordType::Include |
|
||||
KeywordType::Inline |
|
||||
KeywordType::Export |
|
||||
KeywordType::Constant => unreachable!(),
|
||||
KeywordType::FunctionDefExported => {
|
||||
|
||||
if !crate::config::ENABLE_EXPORTED_FUNCTIONS {
|
||||
lerror!(&token.loc, "Experimental feature 'exported functions' is not enabled");
|
||||
return Err(eyre!(""));
|
||||
bail!("");
|
||||
}
|
||||
|
||||
writeln!(writer, "global {}", token.text)?;
|
||||
|
@ -571,7 +403,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
}
|
||||
if token.types.0 >= 7 {
|
||||
lerror!(&token.loc, "More than 6 arguments in an external function is not supported");
|
||||
return Err(eyre!(""));
|
||||
bail!("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -579,14 +411,29 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
should_push_ret = true;
|
||||
} else if token.types.1 > 1 {
|
||||
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});
|
||||
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}:")?;
|
||||
|
@ -615,16 +462,37 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
writeln!(writer, "segment .bss")?;
|
||||
for s in memories {
|
||||
writeln!(writer, " mem_{}: resb {}", s.id, s.size)?;
|
||||
for m in memories {
|
||||
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 {
|
||||
// println!("{t:?}");
|
||||
// }
|
||||
|
@ -637,7 +505,8 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
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 {
|
||||
let c = linux_x86_64_run(&of_c, &[], args.quiet)?;
|
||||
return Ok(c);
|
||||
|
@ -660,7 +529,7 @@ fn pre_compile_steps(_code: &str, functions: Vec<Function>) -> Result<()> {
|
|||
|
||||
if !has_main {
|
||||
crate::errors::missing_main_fn();
|
||||
return Err(eyre!(""));
|
||||
bail!("");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::constants::Loc;
|
||||
use crate::definitions::Loc;
|
||||
|
||||
pub mod linux_x86_64;
|
||||
pub mod commands;
|
||||
|
@ -25,4 +25,338 @@ pub struct Function {
|
|||
pub loc: Loc,
|
||||
pub name: String,
|
||||
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,7 +1,7 @@
|
|||
/**
|
||||
* 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_INCLUDES: [&str;2] = [
|
||||
|
@ -10,16 +10,6 @@ pub const DEFAULT_INCLUDES: [&str;2] = [
|
|||
];
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -33,12 +33,12 @@ pub enum InstructionType {
|
|||
|
||||
|
||||
// mem
|
||||
Load8,
|
||||
Store8,
|
||||
Load32,
|
||||
Store32,
|
||||
Load64,
|
||||
Store64,
|
||||
Read8,
|
||||
Write8,
|
||||
Read32,
|
||||
Write32,
|
||||
Read64,
|
||||
Write64,
|
||||
|
||||
// syscalls
|
||||
Syscall0,
|
||||
|
@ -89,7 +89,8 @@ pub enum KeywordType {
|
|||
FunctionThen,
|
||||
FunctionDone,
|
||||
Inline,
|
||||
Export
|
||||
Export,
|
||||
Struct
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
@ -164,12 +165,12 @@ impl OpType {
|
|||
InstructionType::Shl => "shl",
|
||||
InstructionType::DivMod => "divmod",
|
||||
InstructionType::Mul => "*",
|
||||
InstructionType::Load8 => "load8",
|
||||
InstructionType::Store8 => "store8",
|
||||
InstructionType::Load32 => "load32",
|
||||
InstructionType::Store32 => "store32",
|
||||
InstructionType::Load64 => "load64",
|
||||
InstructionType::Store64 => "store64",
|
||||
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",
|
||||
|
@ -213,6 +214,7 @@ impl OpType {
|
|||
KeywordType::FunctionDefExported => "extern function definition (internal)",
|
||||
KeywordType::Inline => "inline",
|
||||
KeywordType::Export => "export",
|
||||
KeywordType::Struct => "struct",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
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>
|
||||
}
|
|
@ -126,9 +126,9 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
|
|||
ip += 1;
|
||||
},
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
InstructionType::Load8 |
|
||||
InstructionType::Load32 |
|
||||
InstructionType::Load64 => {
|
||||
InstructionType::Read8 |
|
||||
InstructionType::Read32 |
|
||||
InstructionType::Read64 => {
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
if a > crate::MEM_SZ + crate::STRING_SZ {
|
||||
lerror!(&op.loc, "Invalid memory address {a}");
|
||||
|
@ -139,7 +139,7 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
|
|||
ip += 1;
|
||||
}
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
InstructionType::Store8 => {
|
||||
InstructionType::Write8 => {
|
||||
let val = stack_pop(&mut stack, &pos)?;
|
||||
let addr = stack_pop(&mut stack, &pos)?;
|
||||
|
||||
|
@ -152,7 +152,7 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
|
|||
ip += 1;
|
||||
}
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
InstructionType::Store32 => {
|
||||
InstructionType::Write32 => {
|
||||
let val = stack_pop(&mut stack, &pos)?;
|
||||
let addr = stack_pop(&mut stack, &pos)?;
|
||||
|
||||
|
@ -166,7 +166,7 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
|
|||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
InstructionType::Store64 => {
|
||||
InstructionType::Write64 => {
|
||||
let val = stack_pop(&mut stack, &pos)?;
|
||||
let addr = stack_pop(&mut stack, &pos)?;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
match s {
|
||||
|
@ -131,7 +131,7 @@ pub fn lex(code: &str, file: &str, _args: &Args) -> Vec<Token> {
|
|||
typ: tok_type,
|
||||
value: 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);
|
||||
}
|
||||
|
|
36
src/main.rs
36
src/main.rs
|
@ -1,7 +1,6 @@
|
|||
#![allow(clippy::wildcard_imports)]
|
||||
#![allow(clippy::too_many_lines)]
|
||||
mod constants;
|
||||
mod interpret;
|
||||
mod definitions;
|
||||
mod util;
|
||||
mod compile;
|
||||
mod parser;
|
||||
|
@ -11,28 +10,23 @@ mod typechecker;
|
|||
mod precompiler;
|
||||
mod config;
|
||||
mod errors;
|
||||
pub mod test;
|
||||
use config::*;
|
||||
use std::{fs, collections::HashMap};
|
||||
|
||||
use clap::Parser;
|
||||
use color_eyre::Result;
|
||||
use eyre::eyre;
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
#[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 {
|
||||
/// Input source file
|
||||
#[arg(long, short)]
|
||||
in_file: String,
|
||||
|
||||
/// Output compiled file
|
||||
#[arg(long, short, default_value_t=String::from(DEFAULT_OUT_FILE))]
|
||||
out_file: String,
|
||||
|
||||
/// Compile
|
||||
#[arg(long, short)]
|
||||
compile: bool,
|
||||
|
||||
/// Interpert
|
||||
#[arg(long, short='s')]
|
||||
interpret: bool,
|
||||
|
@ -78,7 +72,7 @@ impl Args {
|
|||
"0" | "" => Ok(1),
|
||||
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 tokens = match parser.parse(){
|
||||
let program = match parser.parse(){
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
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(_) => (),
|
||||
Err(e) => {
|
||||
error!("Typechecking failed, exiting!");
|
||||
|
@ -120,22 +114,14 @@ fn main() -> Result<()>{
|
|||
}
|
||||
};
|
||||
|
||||
let c = if args.compile && args.interpret {
|
||||
error!("Cannot compile and interpret at the same time");
|
||||
0
|
||||
} 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 {
|
||||
let c =match compile::linux_x86_64::compile(&program, &args) {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
error!("Compilation failed, exiting!");
|
||||
println!("{e}");
|
||||
1
|
||||
}
|
||||
} else {
|
||||
error!("Did not choose to compile or to interpret, exiting");
|
||||
0
|
||||
};
|
||||
|
||||
std::process::exit(c);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use crate::{constants::{Operator, OpType, Token, TokenType, Loc, KeywordType, InstructionType}, lerror, preprocessor::Preprocessor, Args};
|
||||
use color_eyre::Result;
|
||||
use eyre::eyre;
|
||||
use crate::{definitions::{Operator, OpType, Token, TokenType, Loc, KeywordType, InstructionType, InternalType, Program}, lerror, preprocessor::Preprocessor, Args};
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||
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) => {
|
||||
let Some(if_ip) = stack.pop() else {
|
||||
lerror!(&op.loc, "Unclosed-if else block");
|
||||
return Err(eyre!("Cross referencing"));
|
||||
bail!("Cross referencing")
|
||||
};
|
||||
if program[if_ip].typ != OpType::Keyword(KeywordType::If) {
|
||||
lerror!(&op.clone().loc,"'else' can only close 'if' blocks");
|
||||
return Err(eyre!("Bad block"));
|
||||
bail!("Bad block")
|
||||
}
|
||||
|
||||
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) => {
|
||||
let Some(block_ip) = stack.pop() else {
|
||||
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 {
|
||||
|
@ -50,7 +49,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
|||
a => {
|
||||
println!("{a:?}");
|
||||
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) => {
|
||||
let Some(block_ip) = stack.pop() else {
|
||||
lerror!(&op.loc, "Unclosed while-do block");
|
||||
return Err(eyre!("Cross referencing"));
|
||||
bail!("Cross referencing")
|
||||
};
|
||||
|
||||
program[ip].jmp = block_ip;
|
||||
|
@ -72,7 +71,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
|||
// println!("{:?}", stack);
|
||||
let i = stack.pop().expect("Empy stack");
|
||||
lerror!(&program[i].clone().loc,"Unclosed block, {:?}", program[i].clone());
|
||||
return Err(eyre!("Unclosed block"));
|
||||
bail!("Unclosed block")
|
||||
}
|
||||
|
||||
Ok(program.clone())
|
||||
|
@ -98,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();
|
||||
|
||||
for token in &self.tokens {
|
||||
|
@ -129,7 +128,7 @@ impl<'a> Parser<'a> {
|
|||
let c = token.text.clone();
|
||||
if c.len() != 1 {
|
||||
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));
|
||||
|
@ -138,9 +137,9 @@ impl<'a> Parser<'a> {
|
|||
|
||||
|
||||
}
|
||||
self.preprocessor.program = tokens;
|
||||
let t = self.preprocessor.preprocess()?.get_ops();
|
||||
let t = cross_ref(t)?;
|
||||
self.preprocessor.program.ops = tokens;
|
||||
let mut t = self.preprocessor.preprocess()?.get_program();
|
||||
t.ops = cross_ref(t.ops)?;
|
||||
|
||||
Ok(t)
|
||||
}
|
||||
|
@ -180,12 +179,12 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
|
|||
|
||||
|
||||
// mem
|
||||
"load8" => OpType::Instruction(InstructionType::Load8),
|
||||
"store8" => OpType::Instruction(InstructionType::Store8),
|
||||
"load32" => OpType::Instruction(InstructionType::Load32),
|
||||
"store32" => OpType::Instruction(InstructionType::Store32),
|
||||
"load64" => OpType::Instruction(InstructionType::Load64),
|
||||
"store64" => OpType::Instruction(InstructionType::Store64),
|
||||
"read8" => OpType::Instruction(InstructionType::Read8),
|
||||
"write8" => OpType::Instruction(InstructionType::Write8),
|
||||
"read32" => OpType::Instruction(InstructionType::Read32),
|
||||
"write32" => OpType::Instruction(InstructionType::Write32),
|
||||
"read64" => OpType::Instruction(InstructionType::Read64),
|
||||
"write64" => OpType::Instruction(InstructionType::Write64),
|
||||
|
||||
"syscall0" => OpType::Instruction(InstructionType::Syscall0),
|
||||
"syscall1" => OpType::Instruction(InstructionType::Syscall1),
|
||||
|
@ -212,6 +211,7 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
|
|||
"done" => OpType::Keyword(KeywordType::FunctionDone),
|
||||
"inline" => OpType::Keyword(KeywordType::Inline),
|
||||
"export" => OpType::Keyword(KeywordType::Export),
|
||||
"struct" => OpType::Keyword(KeywordType::Struct),
|
||||
"return" => OpType::Instruction(InstructionType::Return),
|
||||
"returns" => OpType::Instruction(InstructionType::Returns),
|
||||
"bool" => OpType::Instruction(InstructionType::TypeBool),
|
||||
|
@ -220,6 +220,9 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
|
|||
"void" => OpType::Instruction(InstructionType::TypeVoid),
|
||||
"any" => OpType::Instruction(InstructionType::TypeAny),
|
||||
"with" => OpType::Instruction(InstructionType::With),
|
||||
|
||||
"->" => OpType::Internal(InternalType::Arrow),
|
||||
|
||||
_ => OpType::Instruction(InstructionType::None)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
|
||||
use color_eyre::Result;
|
||||
use eyre::eyre;
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
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> {
|
||||
if let Some(i) = stack.pop() { Ok(i) } else {
|
||||
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);
|
||||
dbg!(tokens);
|
||||
return Err(eyre!(""));
|
||||
bail!("");
|
||||
}
|
||||
}
|
||||
}
|
||||
OpType::Keyword(_) => {
|
||||
lerror!(&token.loc, "Unsupported precompiler keyword {:?}", token.typ);
|
||||
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 crate::{constants::{Operator, Types, OpType, KeywordType, InstructionType, Loc}, Args, lerror, warn};
|
||||
use color_eyre::Result;
|
||||
use eyre::eyre;
|
||||
use crate::{definitions::{Operator, Types, OpType, KeywordType, InstructionType, Loc}, Args, lerror, warn};
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[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 p.typ != OpType::Instruction(InstructionType::With){
|
||||
lerror!(&op.loc, "Expected {:?}, got {:?}", OpType::Instruction(InstructionType::With), p.typ);
|
||||
return Err(eyre!(""));
|
||||
bail!("");
|
||||
}
|
||||
|
||||
} else {
|
||||
lerror!(&op.loc, "Expected {:?}, got nothing", OpType::Instruction(InstructionType::With));
|
||||
return Err(eyre!(""));
|
||||
bail!("");
|
||||
}
|
||||
|
||||
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::TypeVoid) {
|
||||
let t = if op.typ == OpType::Instruction(InstructionType::TypeInt) {
|
||||
Types::Int
|
||||
Types::U64
|
||||
} else if op.typ == OpType::Instruction(InstructionType::TypeBool) {
|
||||
Types::Bool
|
||||
} 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())?;
|
||||
if ret_typs != func.returns && !func.returns.contains(&Types::Void){
|
||||
lerror!(&func.loc, "Expected {:?}, but got {:?}", func.returns, ret_typs);
|
||||
return Err(eyre!(""))
|
||||
bail!("");
|
||||
}
|
||||
|
||||
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::ConstantDef => {
|
||||
// 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 |
|
||||
|
@ -181,26 +180,27 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
|||
println!("{:?}", op);
|
||||
unreachable!()
|
||||
},
|
||||
KeywordType::Struct => todo!(),
|
||||
}
|
||||
},
|
||||
OpType::Instruction(instruction) => {
|
||||
match instruction {
|
||||
InstructionType::PushInt => {
|
||||
stack.push(Types::Int);
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
InstructionType::PushStr => {
|
||||
stack.push(Types::Int);
|
||||
stack.push(Types::U64);
|
||||
stack.push(Types::Ptr);
|
||||
},
|
||||
InstructionType::PushCStr => {
|
||||
stack.push(Types::Int);
|
||||
stack.push(Types::U64);
|
||||
stack.push(Types::Ptr);
|
||||
},
|
||||
InstructionType::Drop => {
|
||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||
},
|
||||
InstructionType::Print => {
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||
},
|
||||
InstructionType::Dup => {
|
||||
let a = stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||
|
@ -234,9 +234,9 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
|||
InstructionType::Shr |
|
||||
InstructionType::Shl |
|
||||
InstructionType::Mul => {
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack.push(Types::Int);
|
||||
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
InstructionType::Equals |
|
||||
InstructionType::Gt |
|
||||
|
@ -244,76 +244,76 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
|||
InstructionType::Ge |
|
||||
InstructionType::Le |
|
||||
InstructionType::NotEquals => {
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||
stack.push(Types::Bool);
|
||||
},
|
||||
InstructionType::DivMod => {
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack.push(Types::Int);
|
||||
stack.push(Types::Int);
|
||||
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||
stack.push(Types::U64);
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
InstructionType::Load8 |
|
||||
InstructionType::Load32 |
|
||||
InstructionType::Load64 => {
|
||||
InstructionType::Read8 |
|
||||
InstructionType::Read32 |
|
||||
InstructionType::Read64 => {
|
||||
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
||||
stack.push(Types::Int);
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
InstructionType::Store8 |
|
||||
InstructionType::Store32 |
|
||||
InstructionType::Store64 => {
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
InstructionType::Write8 |
|
||||
InstructionType::Write32 |
|
||||
InstructionType::Write64 => {
|
||||
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
||||
},
|
||||
InstructionType::Syscall0 => {
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack.push(Types::Int);
|
||||
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
InstructionType::Syscall1 => {
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack_pop(&mut stack, &op, &[Types::U64])?;
|
||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||
stack.push(Types::Int);
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
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.push(Types::Int);
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
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.push(Types::Int);
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
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.push(Types::Int);
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
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.push(Types::Int);
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
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.push(Types::Int);
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
InstructionType::CastBool => {
|
||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||
|
@ -325,7 +325,7 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
|||
},
|
||||
InstructionType::CastInt => {
|
||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||
stack.push(Types::Int);
|
||||
stack.push(Types::U64);
|
||||
},
|
||||
InstructionType::CastVoid => {
|
||||
stack_pop(&mut stack, &op, &[Types::Any])?;
|
||||
|
@ -339,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 {
|
||||
lerror!(&op.loc, "Could not find function {}", op.text);
|
||||
return Err(eyre!(""));
|
||||
bail!("");
|
||||
};
|
||||
|
||||
// in_function = (op.text.clone(), f.clone(), op.loc.clone());
|
||||
|
@ -353,11 +353,11 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
|
|||
if let Some(s2) = s.pop(){
|
||||
if t != s2 {
|
||||
lerror!(&op.loc, "Expected {:?}, but got {:?}", t, s2);
|
||||
return Err(eyre!(""));
|
||||
bail!("");
|
||||
}
|
||||
} else {
|
||||
lerror!(&op.loc, "Expected {:?}, but got nothing", t);
|
||||
return Err(eyre!(""));
|
||||
bail!("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,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();
|
||||
stack.append(&mut c.types);
|
||||
},
|
||||
InstructionType::StructUse => todo!(),
|
||||
}
|
||||
},
|
||||
OpType::Internal(t) => panic!("{t:?}"),
|
||||
|
||||
}
|
||||
|
||||
|
@ -393,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> {
|
||||
if v.is_empty() {
|
||||
lerror!(&op.loc, "Expected {:?}, but got nothing", t);
|
||||
return Err(eyre!(""));
|
||||
bail!("");
|
||||
}
|
||||
let r = v.pop().unwrap();
|
||||
|
||||
if !t.contains(&r) && t[0] != Types::Any {
|
||||
lerror!(&op.loc, "Expected {:?}, but got {:?}", t, r);
|
||||
return Err(eyre!(""));
|
||||
bail!("");
|
||||
}
|
||||
|
||||
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)]
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::{util::color, constants::Loc};
|
||||
use crate::{util::color, definitions::Loc};
|
||||
|
||||
pub fn error(msg: &str) {
|
||||
println!("{red}error{r}: {msg}", red=color::FG_RED, r=color::RESET);
|
||||
|
|
8
test.mcl
8
test.mcl
|
@ -1,7 +1,13 @@
|
|||
include "std.mcl"
|
||||
|
||||
|
||||
fn main with int ptr returns void then
|
||||
// p l
|
||||
c"bad, wait no, good\n\0" dup cstr_len swap puts
|
||||
"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