Merge pull request #1 from mc-lang/refractor

Refractor
This commit is contained in:
MCorange99 2023-03-26 19:36:52 +03:00 committed by GitHub
commit 747c4e59d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 468 additions and 462 deletions

View File

@ -1,18 +1,4 @@
include "std.mcl"
mem dup 72 @8 "Henlo World! :3\n" puts
1 + dup 101 @8
1 + dup 110 @8
1 + dup 108 @8
1 + dup 111 @8
1 + dup 32 @8
1 + dup 119 @8
1 + dup 111 @8
1 + dup 114 @8
1 + dup 108 @8
1 + dup 100 @8
1 + dup 33 @8
1 + dup 10 @8
1 +
mem - mem 1 1 syscall3

View File

@ -1,4 +1,4 @@
include "io.mcl" include "std.mcl"
macro BOARD_SIZE 100 end macro BOARD_SIZE 100 end

19
include/fs.mcl Normal file
View File

@ -0,0 +1,19 @@
macro FS_O_APPEND 1024 end // append to existing file
macro FS_O_ASYNC 8192 end // use signal-driven IO
macro FS_O_CLOEXEC 524288 end // use close-on-exec (avoid race conditions and lock contentions)
macro FS_O_CREAT 64 end // create file if it doesnt exist
macro FS_O_DIRECT 16384 end // bypass cache (slower)
macro FS_O_DIRECTORY 65536 end // fail if pathname isnt a directory
macro FS_O_DSYNC 4096 end // ensure output is sent to hardware and metadata written before return
macro FS_O_EXCL 128 end // ensure creation of file
macro FS_O_LARGEFILE 0 end // allows use of file sizes represented by off64_t
macro FS_O_NOATIME 262144 end // do not increment access time upon open
macro FS_O_NOCTTY 256 end // if pathname is a terminal device, dont become controlling terminal
macro FS_O_NOFOLLOW 131072 end // fail if pathname is symbolic link
macro FS_O_NONBLOCK 2048 end // if possible, open file with non-blocking IO
macro FS_O_NDELAY 2048 end // same as O_NONBLOCK
macro FS_O_PATH 2097152 end // open descriptor for obtaining permissions and status of a file but does not allow read/write operations
macro FS_O_SYNC 1052672 end // wait for IO to complete before returning
macro FS_O_TMPFILE 4259840 end // create an unnamed, unreachable (via any other open call) temporary file
macro FS_O_TRUNC 512 end // if file exists, ovewrite it (careful!)

View File

@ -1,5 +1,16 @@
macro NULL 0 end macro NULL 0 end
macro false 0 end macro false 0 end
macro true 1 end macro true 1 end
macro div divmod drop end macro div divmod drop end
macro mod divmod swap drop end macro mod divmod swap drop end
macro / div end
macro % mod end
macro 2dup over over end
macro 2drop drop drop end
macro sizeof(u64) 8 end
macro sizeof(u32) 4 end
macro sizeof(u16) 2 end
macro sizeof(u8) 1 end

View File

@ -1,21 +1,29 @@
include "linux.mcl"
// Write to a file descriptor using the SYS_write syscall // Write to a file descriptor using the SYS_write syscall
// args: [str_size, str_ptr, fd] // args: [buff_size, buff_ptr, fd]
// @arg str_size: Int // @arg buff_size: Int - number of bytes to write
// @arg str_ptr: Ptr // @arg buff_ptr: Ptr - pointer to the buffer to write
// @arg fd: Int // @arg fd: Int - file descriptor
// @ret Int // @ret Int
macro write macro write
SYS_write syscall3 SYS_write syscall3
end end
// Write to a file descriptor using the SYS_write syscall
// args: [buff_size, buff_ptr, fd]
// @arg buff_size: Int - number of bytes to write
// @arg buff_ptr: Ptr - pointer to the buffer to write
// @arg fd: Int - file descriptor
// @ret Int
macro read
SYS_read syscall3
end
// Print a string to STDOUT // Print a string to STDOUT
// args: [str_size, str_ptr] // args: [str_size, str_ptr]
// @arg str_size: Int // @arg buff_size: Int - number of bytes to write
// @arg str_ptr: Ptr // @arg buff_ptr: Ptr - pointer to the buffer to write
// @ret NULL // @ret NULL
macro puts macro puts
STDOUT write drop STDOUT write drop
@ -23,8 +31,8 @@ end
// Print a string to STDERR // Print a string to STDERR
// args: [str_size, str_ptr] // args: [str_size, str_ptr]
// @arg str_size: Int // @arg buff_size: Int - number of bytes to write
// @arg str_ptr: Ptr // @arg buff_ptr: Ptr - pointer to the buffer to write
// @ret NULL // @ret NULL
macro eputs macro eputs
STDOUT write drop STDOUT write drop

27
include/mem.mcl Normal file
View File

@ -0,0 +1,27 @@
macro load8 @8 end
macro store8 !8 end
macro load64
7 + 0
8 shl over !8 + swap 1 - swap
8 shl over !8 + swap 1 - swap
8 shl over !8 + swap 1 - swap
8 shl over !8 + swap 1 - swap
8 shl over !8 + swap 1 - swap
8 shl over !8 + swap 1 - swap
8 shl over !8 + swap 1 - swap
8 shl over !8 + swap drop
end
macro store64
2dup 255 band @8 shr swap 1 + swap
2dup 255 band @8 shr swap 1 + swap
2dup 255 band @8 shr swap 1 + swap
2dup 255 band @8 shr swap 1 + swap
2dup 255 band @8 shr swap 1 + swap
2dup 255 band @8 shr swap 1 + swap
2dup 255 band @8 shr swap 1 + swap
2dup 255 band @8 shr swap 2drop
end

5
include/std.mcl Normal file
View File

@ -0,0 +1,5 @@
include "linux.mcl"
include "io.mcl"
include "util.mcl"
include "int.mcl"
include "fs.mcl"

View File

@ -1,5 +1,5 @@
use std::path::PathBuf; use std::path::{PathBuf, Path};
use std::process::Stdio; use std::process::Stdio;
use std::{process, fs}; use std::{process, fs};
use clap::Parser; use clap::Parser;
@ -47,10 +47,10 @@ fn run_test<P: Into<PathBuf> + std::convert::AsRef<std::ffi::OsStr>>(f_in: PathB
let mut command = process::Command::new(compiler); let mut command = process::Command::new(compiler);
command.stdout(Stdio::piped()); command.stdout(Stdio::piped());
command.stderr(Stdio::piped()); command.stderr(Stdio::piped());
if !compile_mode { if compile_mode {
command.arg("-sq");
} else {
command.arg("-cqr"); command.arg("-cqr");
} else {
command.arg("-sq");
} }
command.arg("-i"); command.arg("-i");
@ -63,18 +63,18 @@ fn run_test<P: Into<PathBuf> + std::convert::AsRef<std::ffi::OsStr>>(f_in: PathB
let out = child.wait_with_output()?; let out = child.wait_with_output()?;
let stdout = out.stdout.iter().map(|c| { let stdout = out.stdout.iter().map(|c| {
char::from_u32((*c) as u32).expect("Failed to parse stdout char").to_string() char::from_u32(u32::from(*c)).expect("Failed to parse stdout char").to_string()
}).collect::<String>(); }).collect::<String>();
let stderr = out.stderr.iter().map(|c| { let stderr = out.stderr.iter().map(|c| {
char::from_u32((*c) as u32).expect("Failed to parse stderr char").to_string() char::from_u32(u32::from(*c)).expect("Failed to parse stderr char").to_string()
}).collect::<String>(); }).collect::<String>();
Ok(TestOutput { Ok(TestOutput {
stdout: stdout, stdout,
stderr: stderr, stderr,
stdin: stdin, stdin,
status: out.status.code().unwrap() status: out.status.code().unwrap()
}) })
} }
@ -91,14 +91,14 @@ fn run_tests(args: Args) -> Result<()>{
let intp = run_test(file.path(), &f_out, &args.compiler_path, false, String::new())?; let intp = run_test(file.path(), &f_out, &args.compiler_path, false, String::new())?;
let comp = run_test(file.path(), &f_out, &args.compiler_path, true, String::new())?; let comp = run_test(file.path(), &f_out, &args.compiler_path, true, String::new())?;
compare_results(intp, comp, file.path())?; compare_results(&intp, &comp, &file.path())?;
} }
Ok(()) Ok(())
} }
fn compare_results(intp: TestOutput, comp: TestOutput, f_in: PathBuf) -> Result<()> { fn compare_results(intp: &TestOutput, comp: &TestOutput, f_in: &Path) -> Result<()> {
if intp.stdout != comp.stdout { if intp.stdout != comp.stdout {
println!("{b}[ {r}ERR{rs}{b} ]{rs} {f} compiled and interpreted stdout versions differ", r=color::FG_RED, rs=color::RESET, b=color::BRIGHT, f=f_in.display()); println!("{b}[ {r}ERR{rs}{b} ]{rs} {f} compiled and interpreted stdout versions differ", r=color::FG_RED, rs=color::RESET, b=color::BRIGHT, f=f_in.display());

View File

@ -1,9 +1,9 @@
use std::path::PathBuf; use std::path::{PathBuf, Path};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use color_eyre::Result; use color_eyre::Result;
use crate::info; use crate::info;
pub fn linux_x86_64_compile_and_link(of_a: &PathBuf, of_o: &PathBuf, of_c: &PathBuf, quiet: bool) -> Result<()> { pub fn linux_x86_64_compile_and_link(of_a: &Path, of_o: &Path, of_c: &Path, quiet: bool) -> Result<()> {
let nasm_args = [ let nasm_args = [
"-felf64", "-felf64",
@ -23,7 +23,7 @@ pub fn linux_x86_64_compile_and_link(of_a: &PathBuf, of_o: &PathBuf, of_c: &Path
return Ok(()); return Ok(());
} else { } else {
Command::new("nasm") Command::new("nasm")
.args(&nasm_args) .args(nasm_args)
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.spawn()? .spawn()?
@ -42,7 +42,7 @@ pub fn linux_x86_64_compile_and_link(of_a: &PathBuf, of_o: &PathBuf, of_c: &Path
return Ok(()); return Ok(());
} else { } else {
Command::new("ld") Command::new("ld")
.args(&ld_args) .args(ld_args)
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.spawn()? .spawn()?
@ -60,28 +60,28 @@ pub fn linux_x86_64_compile_and_link(of_a: &PathBuf, of_o: &PathBuf, of_c: &Path
Ok(()) Ok(())
} }
pub fn linux_x86_64_run(_bin: &PathBuf, args: Vec<String>, quiet: bool) -> Result<i32> { pub fn linux_x86_64_run(bin: &Path, args: &[String], quiet: bool) -> Result<i32> {
let bin = PathBuf::from( let bin = PathBuf::from(
format!("./{}", _bin.to_string_lossy()) format!("./{}", bin.to_string_lossy())
); );
let mut proc = if cfg!(target_os = "windows") { let mut proc = if cfg!(target_os = "windows") {
return Ok(0); return Ok(0);
} else { } else {
Command::new(bin) Command::new(bin.clone())
.args(&args) .args(args)
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.spawn()? .spawn()?
}; };
// println!("{}", quiet); // println!("{}", quiet);
if !quiet { if !quiet {
info!("running {} {}", _bin.to_string_lossy(), args.join(" ")); info!("running {} {}", bin.to_string_lossy(), args.join(" "));
} }
let exit = proc.wait()?; let exit = proc.wait()?;
if !quiet { if !quiet {
info!("{} process exited with code {}", _bin.to_string_lossy(), exit); info!("{} process exited with code {}", bin.to_string_lossy(), exit);
} }
Ok(exit.code().unwrap_or(0)) Ok(exit.code().unwrap_or(0))

View File

@ -1,14 +1,14 @@
use std::{fs, path::PathBuf, io::{Write, BufWriter}}; use std::{fs, path::PathBuf, io::{Write, BufWriter}};
use crate::{constants::{Operator, OpType}, Args}; use crate::{constants::{Operator, OpType, KeywordType}, Args};
use color_eyre::Result; use color_eyre::Result;
use crate::compile::commands::linux_x86_64_compile_and_link; use crate::compile::commands::linux_x86_64_compile_and_link;
use crate::constants::InstructionType;
use super::commands::linux_x86_64_run; use super::commands::linux_x86_64_run;
pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
let mut of_c = PathBuf::from(&args.out_file); let mut of_c = PathBuf::from(&args.out_file);
let (mut of_o, mut of_a) = if &args.out_file == &crate::DEFAULT_OUT_FILE.to_string() { let (mut of_o, mut of_a) = if args.out_file == *crate::DEFAULT_OUT_FILE {
let of_o = PathBuf::from("/tmp/mclang_comp.o"); let of_o = PathBuf::from("/tmp/mclang_comp.o");
let of_a = PathBuf::from("/tmp/mclang_comp.nasm"); let of_a = PathBuf::from("/tmp/mclang_comp.nasm");
(of_o, of_a) (of_o, of_a)
@ -22,6 +22,8 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
of_o.set_extension("o"); of_o.set_extension("o");
of_a.set_extension("nasm"); of_a.set_extension("nasm");
let file = fs::File::create(&of_a)?; let file = fs::File::create(&of_a)?;
let mut writer = BufWriter::new(&file); let mut writer = BufWriter::new(&file);
@ -72,16 +74,16 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
while ti < tokens.len() { while ti < tokens.len() {
let token = &tokens[ti]; let token = &tokens[ti];
writeln!(writer, "addr_{}:", ti)?; writeln!(writer, "addr_{ti}:")?;
match token.typ { match token.typ {
// stack // stack
OpType::PushInt => { OpType::Instruction(InstructionType::PushInt) => {
writeln!(writer, " ;; -- push int {}", token.value)?; writeln!(writer, " ;; -- push int {}", token.value)?;
writeln!(writer, " mov rax, {}", token.value)?; writeln!(writer, " mov rax, {}", token.value)?;
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
ti += 1; ti += 1;
}, },
OpType::PushStr => { OpType::Instruction(InstructionType::PushStr) => {
writeln!(writer, " ;; -- push str \"{}\"", token.text.escape_default())?; writeln!(writer, " ;; -- push str \"{}\"", token.text.escape_default())?;
writeln!(writer, " mov rax, {}", token.text.len())?; writeln!(writer, " mov rax, {}", token.text.len())?;
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
@ -89,19 +91,19 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
strings.push(token.text.clone()); strings.push(token.text.clone());
ti += 1; ti += 1;
} }
OpType::Drop => { OpType::Instruction(InstructionType::Drop) => {
writeln!(writer, " ;; -- drop")?; writeln!(writer, " ;; -- drop")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
ti += 1; ti += 1;
}, },
OpType::Print => { OpType::Instruction(InstructionType::Print) => {
writeln!(writer, " ;; -- print")?; writeln!(writer, " ;; -- print")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
writeln!(writer, " call print")?; writeln!(writer, " call print")?;
ti += 1; ti += 1;
}, },
OpType::Dup => { OpType::Instruction(InstructionType::Dup) => {
writeln!(writer, " ;; -- dup")?; writeln!(writer, " ;; -- dup")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
@ -109,19 +111,8 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
ti += 1; ti += 1;
}, },
OpType::Dup2 => {
writeln!(writer, " ;; -- 2dup")?;
writeln!(writer, " pop rbx")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " push rax")?;
writeln!(writer, " push rbx")?;
writeln!(writer, " push rax")?;
writeln!(writer, " push rbx")?;
ti += 1; OpType::Instruction(InstructionType::Rot) => {
},
OpType::Rot => {
writeln!(writer, " ;; -- rot")?; writeln!(writer, " ;; -- rot")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -132,7 +123,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
ti += 1; ti += 1;
}, },
OpType::Swap => { OpType::Instruction(InstructionType::Swap) => {
writeln!(writer, " ;; -- swap")?; writeln!(writer, " ;; -- swap")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -141,7 +132,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
ti += 1; ti += 1;
}, },
OpType::Over => { OpType::Instruction(InstructionType::Over) => {
writeln!(writer, " ;; -- over")?; writeln!(writer, " ;; -- over")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -153,12 +144,12 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
}, },
//mem //mem
OpType::Mem => { OpType::Instruction(InstructionType::Mem) => {
writeln!(writer, " ;; -- mem")?; writeln!(writer, " ;; -- mem")?;
writeln!(writer, " push mem")?; writeln!(writer, " push mem")?;
ti += 1; ti += 1;
} }
OpType::Load8 => { OpType::Instruction(InstructionType::Load8) => {
writeln!(writer, " ;; -- load")?; writeln!(writer, " ;; -- load")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " xor rbx, rbx")?; writeln!(writer, " xor rbx, rbx")?;
@ -167,7 +158,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
ti += 1; ti += 1;
} }
OpType::Store8 => { OpType::Instruction(InstructionType::Store8) => {
writeln!(writer, " ;; -- store")?; writeln!(writer, " ;; -- store")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
@ -176,7 +167,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
} }
// math // math
OpType::Plus => { OpType::Instruction(InstructionType::Plus) => {
writeln!(writer, " ;; -- plus")?; writeln!(writer, " ;; -- plus")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -184,7 +175,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
ti += 1; ti += 1;
}, },
OpType::Minus => { OpType::Instruction(InstructionType::Minus) => {
writeln!(writer, " ;; -- minus")?; writeln!(writer, " ;; -- minus")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -192,7 +183,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rbx")?; writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::Equals => { OpType::Instruction(InstructionType::Equals) => {
writeln!(writer, " ;; -- equals")?; writeln!(writer, " ;; -- equals")?;
writeln!(writer, " mov rcx, 0")?; writeln!(writer, " mov rcx, 0")?;
writeln!(writer, " mov rdx, 1")?; writeln!(writer, " mov rdx, 1")?;
@ -203,7 +194,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rcx")?; writeln!(writer, " push rcx")?;
ti += 1; ti += 1;
}, },
OpType::Lt => { OpType::Instruction(InstructionType::Lt) => {
writeln!(writer, " ;; -- lt")?; writeln!(writer, " ;; -- lt")?;
writeln!(writer, " mov rcx, 0")?; writeln!(writer, " mov rcx, 0")?;
writeln!(writer, " mov rdx, 1")?; writeln!(writer, " mov rdx, 1")?;
@ -214,7 +205,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rcx")?; writeln!(writer, " push rcx")?;
ti += 1; ti += 1;
}, },
OpType::Gt => { OpType::Instruction(InstructionType::Gt) => {
writeln!(writer, " ;; -- gt")?; writeln!(writer, " ;; -- gt")?;
writeln!(writer, " mov rcx, 0")?; writeln!(writer, " mov rcx, 0")?;
writeln!(writer, " mov rdx, 1")?; writeln!(writer, " mov rdx, 1")?;
@ -225,7 +216,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rcx")?; writeln!(writer, " push rcx")?;
ti += 1; ti += 1;
}, },
OpType::NotEquals => { OpType::Instruction(InstructionType::NotEquals) => {
writeln!(writer, " ;; -- not equals")?; writeln!(writer, " ;; -- not equals")?;
writeln!(writer, " mov rcx, 1")?; writeln!(writer, " mov rcx, 1")?;
writeln!(writer, " mov rdx, 0")?; writeln!(writer, " mov rdx, 0")?;
@ -236,7 +227,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rcx")?; writeln!(writer, " push rcx")?;
ti += 1; ti += 1;
}, },
OpType::Le => { OpType::Instruction(InstructionType::Le) => {
writeln!(writer, " ;; -- lt")?; writeln!(writer, " ;; -- lt")?;
writeln!(writer, " mov rcx, 0")?; writeln!(writer, " mov rcx, 0")?;
writeln!(writer, " mov rdx, 1")?; writeln!(writer, " mov rdx, 1")?;
@ -247,7 +238,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rcx")?; writeln!(writer, " push rcx")?;
ti += 1; ti += 1;
}, },
OpType::Ge => { OpType::Instruction(InstructionType::Ge) => {
writeln!(writer, " ;; -- gt")?; writeln!(writer, " ;; -- gt")?;
writeln!(writer, " mov rcx, 0")?; writeln!(writer, " mov rcx, 0")?;
writeln!(writer, " mov rdx, 1")?; writeln!(writer, " mov rdx, 1")?;
@ -258,7 +249,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rcx")?; writeln!(writer, " push rcx")?;
ti += 1; ti += 1;
}, },
OpType::Band => { OpType::Instruction(InstructionType::Band) => {
writeln!(writer, " ;; -- band")?; writeln!(writer, " ;; -- band")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -266,7 +257,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rbx")?; writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::Bor => { OpType::Instruction(InstructionType::Bor) => {
writeln!(writer, " ;; -- bor")?; writeln!(writer, " ;; -- bor")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -274,7 +265,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rbx")?; writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::Shr => { OpType::Instruction(InstructionType::Shr) => {
writeln!(writer, " ;; -- shr")?; writeln!(writer, " ;; -- shr")?;
writeln!(writer, " pop rcx")?; writeln!(writer, " pop rcx")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -282,7 +273,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rbx")?; writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::Shl => { OpType::Instruction(InstructionType::Shl) => {
writeln!(writer, " ;; -- shl")?; writeln!(writer, " ;; -- shl")?;
writeln!(writer, " pop rcx")?; writeln!(writer, " pop rcx")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -290,7 +281,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rbx")?; writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::DivMod => { OpType::Instruction(InstructionType::DivMod) => {
writeln!(writer, " ;; -- div")?; writeln!(writer, " ;; -- div")?;
writeln!(writer, " xor rdx, rdx")?; writeln!(writer, " xor rdx, rdx")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -300,7 +291,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rdx")?; writeln!(writer, " push rdx")?;
ti += 1; ti += 1;
}, },
OpType::Mul => { OpType::Instruction(InstructionType::Mul) => {
writeln!(writer, " ;; -- mul")?; writeln!(writer, " ;; -- mul")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -311,44 +302,44 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
// block // block
OpType::If => { OpType::Keyword(KeywordType::If) => {
writeln!(writer, " ;; -- if")?; writeln!(writer, " ;; -- if")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " test rax, rax")?; writeln!(writer, " test rax, rax")?;
writeln!(writer, " jz addr_{}", token.jmp)?; writeln!(writer, " jz addr_{}", token.jmp)?;
ti += 1; ti += 1;
}, },
OpType::Else => { OpType::Keyword(KeywordType::Else) => {
writeln!(writer, " ;; -- else")?; writeln!(writer, " ;; -- else")?;
writeln!(writer, " jmp addr_{}", token.jmp)?; writeln!(writer, " jmp addr_{}", token.jmp)?;
ti += 1; ti += 1;
}, },
OpType::While => { OpType::Keyword(KeywordType::While) => {
writeln!(writer, " ;; -- while")?; writeln!(writer, " ;; -- while")?;
ti += 1; ti += 1;
} }
OpType::Do => { OpType::Keyword(KeywordType::Do) => {
writeln!(writer, " ;; -- do")?; writeln!(writer, " ;; -- do")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " test rax, rax")?; writeln!(writer, " test rax, rax")?;
writeln!(writer, " jz addr_{}", token.jmp)?; writeln!(writer, " jz addr_{}", token.jmp)?;
ti += 1; ti += 1;
} }
OpType::End => { OpType::Keyword(KeywordType::End) => {
writeln!(writer, " ;; -- end")?; writeln!(writer, " ;; -- end")?;
if ti + 1 != token.jmp as usize { if ti + 1 != token.jmp {
writeln!(writer, " jmp addr_{}", token.jmp)?; writeln!(writer, " jmp addr_{}", token.jmp)?;
} }
ti += 1; ti += 1;
}, },
OpType::Syscall0 => { OpType::Instruction(InstructionType::Syscall0) => {
writeln!(writer, " ;; -- syscall0")?; writeln!(writer, " ;; -- syscall0")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " syscall")?; writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
ti += 1; ti += 1;
}, },
OpType::Syscall1 => { OpType::Instruction(InstructionType::Syscall1) => {
writeln!(writer, " ;; -- syscall1")?; writeln!(writer, " ;; -- syscall1")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
@ -356,7 +347,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
ti += 1; ti += 1;
}, },
OpType::Syscall2 => { OpType::Instruction(InstructionType::Syscall2) => {
writeln!(writer, " ;; -- syscall2")?; writeln!(writer, " ;; -- syscall2")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
@ -365,7 +356,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
ti += 1; ti += 1;
}, },
OpType::Syscall3 => { OpType::Instruction(InstructionType::Syscall3) => {
writeln!(writer, " ;; -- syscall3")?; writeln!(writer, " ;; -- syscall3")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
@ -376,7 +367,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
ti += 1; ti += 1;
}, },
OpType::Syscall4 => { OpType::Instruction(InstructionType::Syscall4) => {
writeln!(writer, " ;; -- syscall4")?; writeln!(writer, " ;; -- syscall4")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
@ -387,7 +378,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
ti += 1; ti += 1;
}, },
OpType::Syscall5 => { OpType::Instruction(InstructionType::Syscall5) => {
writeln!(writer, " ;; -- syscall5")?; writeln!(writer, " ;; -- syscall5")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
@ -399,7 +390,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
ti += 1; ti += 1;
}, },
OpType::Syscall6 => { OpType::Instruction(InstructionType::Syscall6) => {
writeln!(writer, " ;; -- syscall6")?; writeln!(writer, " ;; -- syscall6")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
@ -412,20 +403,18 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
ti += 1; ti += 1;
}, },
OpType::None => unreachable!(), OpType::Instruction(InstructionType::None) | OpType::Keyword(KeywordType::Macro) | OpType::Keyword(KeywordType::Include) => unreachable!()
OpType::Macro => unreachable!(),
OpType::Include => unreachable!()
} }
} }
writeln!(writer, "addr_{}:", ti)?; writeln!(writer, "addr_{ti}:")?;
writeln!(writer, " mov rax, 60")?; writeln!(writer, " mov rax, 60")?;
writeln!(writer, " mov rdi, 0")?; writeln!(writer, " mov rdi, 0")?;
writeln!(writer, " syscall")?; writeln!(writer, " syscall")?;
writeln!(writer, "segment .data")?; writeln!(writer, "segment .data")?;
for s in 0..strings.len() { for (_, s) in strings.iter().enumerate() {
let s_chars = strings[s].chars().map(|c| (c as u32).to_string()).collect::<Vec<String>>(); let s_chars = s.chars().map(|c| (c as u32).to_string()).collect::<Vec<String>>();
let s_list = s_chars.join(","); let s_list = s_chars.join(",");
writeln!(writer, " str_{}: db {} ; {}", s, s_list, strings[s].escape_default())?; writeln!(writer, " str_{}: db {} ; {}", s, s_list, s.escape_default())?;
} }
writeln!(writer, "segment .bss")?; writeln!(writer, "segment .bss")?;
@ -434,7 +423,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
writer.flush()?; writer.flush()?;
linux_x86_64_compile_and_link(&of_a, &of_o, &of_c, args.quiet)?; linux_x86_64_compile_and_link(&of_a, &of_o, &of_c, args.quiet)?;
if args.run { if args.run {
let c = linux_x86_64_run(&of_c, vec![], args.quiet)?; let c = linux_x86_64_run(&of_c, &[], args.quiet)?;
return Ok(c); return Ok(c);
} }

View File

@ -1,5 +1,5 @@
pub mod linux_x86_64; pub mod linux_x86_64;
pub mod commands; pub mod commands;
pub const MEM_SZ: u32 = 640 * 1000; // 4kb pub const MEM_SZ: usize = 640 * 1000; // 4kb
pub const STRING_SZ: u32 = 640 * 1000; // 4kb pub const STRING_SZ: usize = 640 * 1000; // 4kb

View File

@ -3,7 +3,7 @@ pub const ALLOW_MACRO_REDEFINITION: bool = true;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum OpType { pub enum InstructionType {
// stack // stack
PushInt, PushInt,
@ -11,7 +11,6 @@ pub enum OpType {
Drop, Drop,
Print, Print,
Dup, Dup,
Dup2, // a b => a b a b
Rot, // a b c => b c a Rot, // a b c => b c a
Over, // a b => a b a Over, // a b => a b a
Swap, // a b => b a Swap, // a b => b a
@ -37,15 +36,6 @@ pub enum OpType {
Mem, Mem,
Load8, Load8,
Store8, Store8,
// block
If,
Else,
End,
While,
Do,
Macro,
Include,
// syscalls // syscalls
Syscall0, Syscall0,
@ -59,24 +49,40 @@ pub enum OpType {
None // Used for macros and any other non built in word definitions None // Used for macros and any other non built in word definitions
} }
#[derive(Debug, Clone, PartialEq)]
pub enum KeywordType {
If,
Else,
End,
While,
Do,
Macro,
Include,
}
#[derive(Debug, Clone, PartialEq)]
pub enum OpType {
Keyword(KeywordType),
Instruction(InstructionType)
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Operator { pub struct Operator{
pub typ: OpType, pub typ: OpType,
pub value: i64, pub value: usize,
pub text: String, //? only used for OpType::PushStr pub text: String, //? only used for OpType::PushStr
pub addr: i64, //? only used for OpType::PushStr pub addr: Option<usize>, //? only used for OpType::PushStr
pub jmp: i32, pub jmp: usize,
pub loc: (String, u32, u32) pub loc: (String, usize, usize)
} }
impl Operator { impl Operator {
pub fn new(typ: OpType, value: i64, text: String, file: String, row: u32, col: u32) -> Self { pub fn new(typ: OpType, value: usize, text: String, file: String, row: usize, col: usize) -> Self {
Self { Self {
typ, typ,
value, value,
jmp: 0, jmp: 0,
addr: -1, addr: None,
text, text,
loc: (file, row, col) loc: (file, row, col)
} }
@ -86,48 +92,47 @@ impl Operator {
impl OpType { impl OpType {
pub fn human(&self) -> String { pub fn human(&self) -> String {
match self { match *self {
&OpType::PushInt => "Number", OpType::Instruction(InstructionType::PushInt) => "Number",
&OpType::PushStr => "String", OpType::Instruction(InstructionType::PushStr) => "String",
&OpType::Print => "print", OpType::Instruction(InstructionType::Print) => "print",
&OpType::Dup => "dup", OpType::Instruction(InstructionType::Dup) => "dup",
&OpType::Drop => "drop", OpType::Instruction(InstructionType::Drop) => "drop",
&OpType::Dup2 => "2dup", OpType::Instruction(InstructionType::Rot) => "rot",
&OpType::Rot => "rot", OpType::Instruction(InstructionType::Over) => "over",
&OpType::Over => "over", OpType::Instruction(InstructionType::Swap) => "swap",
&OpType::Swap => "swap", OpType::Instruction(InstructionType::Plus) => "+",
&OpType::Plus => "+", OpType::Instruction(InstructionType::Minus) => "-",
&OpType::Minus => "-", OpType::Instruction(InstructionType::Equals) => "=",
&OpType::Equals => "=", OpType::Instruction(InstructionType::Gt) => ">",
&OpType::Gt => ">", OpType::Instruction(InstructionType::Lt) => "<",
&OpType::Lt => "<", OpType::Instruction(InstructionType::NotEquals) => "!=",
&OpType::NotEquals => "!=", OpType::Instruction(InstructionType::Le) => "<=",
&OpType::Le => "<=", OpType::Instruction(InstructionType::Ge) => ">=",
&OpType::Ge => ">=", OpType::Instruction(InstructionType::Band) => "band",
&OpType::Band => "band", OpType::Instruction(InstructionType::Bor) => "bor",
&OpType::Bor => "bor", OpType::Instruction(InstructionType::Shr) => "shr",
&OpType::Shr => "shr", OpType::Instruction(InstructionType::Shl) => "shl",
&OpType::Shl => "shl", OpType::Instruction(InstructionType::DivMod) => "divmod",
&OpType::DivMod => "divmod", OpType::Instruction(InstructionType::Mul) => "*",
&OpType::Mul => "*", OpType::Keyword(KeywordType::If) => "if",
&OpType::If => "if", OpType::Keyword(KeywordType::Else) => "else",
&OpType::Else => "else", OpType::Keyword(KeywordType::End) => "end",
&OpType::End => "end", OpType::Keyword(KeywordType::While) => "while",
&OpType::While => "while", OpType::Keyword(KeywordType::Do) => "do",
&OpType::Do => "do", OpType::Keyword(KeywordType::Macro) => "macro",
&OpType::Macro => "macro", OpType::Keyword(KeywordType::Include) => "include",
&OpType::Include => "include", OpType::Instruction(InstructionType::Mem) => "mem",
&OpType::Mem => "mem", OpType::Instruction(InstructionType::Load8) => "!8",
&OpType::Load8 => "!8", OpType::Instruction(InstructionType::Store8) => "@8",
&OpType::Store8 => "@8", OpType::Instruction(InstructionType::Syscall0) => "syscall0",
&OpType::Syscall0 => "syscall0", OpType::Instruction(InstructionType::Syscall1) => "syscall1",
&OpType::Syscall1 => "syscall1", OpType::Instruction(InstructionType::Syscall2) => "syscall2",
&OpType::Syscall2 => "syscall2", OpType::Instruction(InstructionType::Syscall3) => "syscall3",
&OpType::Syscall3 => "syscall3", OpType::Instruction(InstructionType::Syscall4) => "syscall4",
&OpType::Syscall4 => "syscall4", OpType::Instruction(InstructionType::Syscall5) => "syscall5",
&OpType::Syscall5 => "syscall5", OpType::Instruction(InstructionType::Syscall6) => "syscall6",
&OpType::Syscall6 => "syscall6", OpType::Instruction(InstructionType::None) => "None"
&OpType::None => "None"
}.to_string() }.to_string()
} }
} }
@ -135,13 +140,13 @@ impl OpType {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Token { pub struct Token {
pub file: String, pub file: String,
pub line: u32, pub line: usize,
pub col: u32, pub col: usize,
pub text: String, pub text: String,
pub typ: TokenType pub typ: TokenType
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, Copy)]
pub enum TokenType { pub enum TokenType {
Word, Word,
Int, Int,
@ -160,7 +165,7 @@ impl Token {
} }
impl TokenType { impl TokenType {
pub fn human(&self) -> String { pub fn human(self) -> String {
match self { match self {
TokenType::Word => "Word", TokenType::Word => "Word",
TokenType::Int => "Int", TokenType::Int => "Int",
@ -170,4 +175,4 @@ impl TokenType {
} }
} }
pub type Loc = (String, u32, u32); pub type Loc = (String, usize, usize);

View File

@ -1,23 +1,20 @@
use crate::{constants::OpType, lerror, error}; use crate::{constants::{OpType, Loc, InstructionType, KeywordType}, lerror, error};
// use crate::util::logger; // use crate::util::logger;
use color_eyre::Result; use color_eyre::Result;
use eyre::eyre; use eyre::eyre;
mod syscalls; mod syscalls;
fn stack_pop(stack: &mut Vec<u64>, pos: &(String, u32, u32)) -> Result<u64> { fn stack_pop(stack: &mut Vec<usize>, pos: &Loc) -> Result<usize> {
match stack.pop() { if let Some(i) = stack.pop() { Ok(i) } else {
Some(i) => Ok(i), lerror!(&pos.clone(), "Stack underflow");
None => { Err(eyre!("Stack underflow"))
lerror!(&pos.clone(), "Stack underflow");
Err(eyre!("Stack underflow"))
},
} }
} }
pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<i32>{ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
let mut stack: Vec<u64> = Vec::new(); let mut stack: Vec<usize> = Vec::new();
let mut ti = 0; let mut ti = 0;
let mut mem: Vec<u8> = vec![0; crate::compile::MEM_SZ as usize + crate::compile::STRING_SZ as usize]; let mut mem: Vec<u8> = vec![0; crate::compile::MEM_SZ + crate::compile::STRING_SZ];
let mut string_idx = 0; let mut string_idx = 0;
// for token in &tokens { // for token in &tokens {
// println!("{{typ: \"{:?}\", val: {}, jmp: {}}}", token.typ, token.value, token.jmp); // println!("{{typ: \"{:?}\", val: {}, jmp: {}}}", token.typ, token.value, token.jmp);
@ -30,47 +27,41 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<i32>{
match token.typ { match token.typ {
// stack // stack
OpType::PushInt => { OpType::Instruction(InstructionType::PushInt) => {
stack.push(token.value as u64); stack.push(token.value);
ti += 1; ti += 1;
}, },
OpType::PushStr => { OpType::Instruction(InstructionType::PushStr) => {
if token.addr < 0 { if token.addr.is_none() {
stack.push(token.text.len() as u64); // string len stack.push(token.text.len()); // string len
stack.push(string_idx + crate::compile::MEM_SZ as u64); stack.push(string_idx + crate::compile::MEM_SZ);
for c in token.text.bytes() { for c in token.text.bytes() {
mem[crate::compile::MEM_SZ as usize + string_idx as usize] = c; mem[crate::compile::MEM_SZ + string_idx] = c;
string_idx += 1; string_idx += 1;
} }
} else { } else {
stack.push(token.text.len() as u64); stack.push(token.text.len());
stack.push(token.addr as u64); if let Some(addr) = token.addr {
stack.push(addr);
}
} }
ti += 1; ti += 1;
}, },
OpType::Drop => { OpType::Instruction(InstructionType::Drop) => {
stack.pop(); stack.pop();
ti += 1; ti += 1;
}, },
OpType::Dup => { OpType::Instruction(InstructionType::Dup) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
stack.push(a); stack.push(a);
stack.push(a); stack.push(a);
ti += 1; ti += 1;
}, },
OpType::Dup2 => {
let a = stack_pop(&mut stack, &pos)?; OpType::Instruction(InstructionType::Rot) => {
let b = stack_pop(&mut stack, &pos)?;
stack.push(b);
stack.push(a);
stack.push(b);
stack.push(a);
ti += 1;
}
OpType::Rot => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
let c = stack_pop(&mut stack, &pos)?; let c = stack_pop(&mut stack, &pos)?;
@ -79,14 +70,14 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<i32>{
stack.push(c); stack.push(c);
ti += 1; ti += 1;
} }
OpType::Swap => { OpType::Instruction(InstructionType::Swap) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push(a); stack.push(a);
stack.push(b); stack.push(b);
ti += 1; ti += 1;
} }
OpType::Over => { OpType::Instruction(InstructionType::Over) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push(b); stack.push(b);
@ -95,7 +86,7 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<i32>{
ti += 1; ti += 1;
} }
OpType::Print => { OpType::Instruction(InstructionType::Print) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
println!("{a}"); println!("{a}");
// let _ = io::stdout().flush(); // let _ = io::stdout().flush();
@ -103,159 +94,155 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<i32>{
}, },
// mem // mem
OpType::Mem => { OpType::Instruction(InstructionType::Mem) => {
stack.push(0); stack.push(0);
ti += 1; ti += 1;
} }
OpType::Load8 => { OpType::Instruction(InstructionType::Load8) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let byte = mem[a as usize]; let byte = mem[a];
stack.push(byte as u64); stack.push(byte as usize);
ti += 1; ti += 1;
} }
OpType::Store8 => { #[allow(clippy::cast_possible_truncation)]
OpType::Instruction(InstructionType::Store8) => {
let val = stack_pop(&mut stack, &pos)?; let val = stack_pop(&mut stack, &pos)?;
let addr = stack_pop(&mut stack, &pos)?; let addr = stack_pop(&mut stack, &pos)?;
mem[addr as usize] = (val & 0xFF) as u8; mem[addr] = (val & 0xFF) as u8;
ti += 1; ti += 1;
} }
// math // math
OpType::Plus => { OpType::Instruction(InstructionType::Plus) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push(b + a); stack.push(b + a);
ti += 1; ti += 1;
}, },
OpType::Minus => { OpType::Instruction(InstructionType::Minus) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push(b - a); stack.push(b - a);
ti += 1; ti += 1;
}, },
OpType::Equals => { OpType::Instruction(InstructionType::Equals) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((b == a) as u64); stack.push(usize::from(b == a));
ti += 1; ti += 1;
}, },
OpType::Gt => { OpType::Instruction(InstructionType::Gt) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((b > a) as u64); stack.push(usize::from(b > a));
ti += 1; ti += 1;
}, },
OpType::Lt => { OpType::Instruction(InstructionType::Lt) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((b < a) as u64); stack.push(usize::from(b < a));
ti += 1; ti += 1;
}, },
OpType::NotEquals => { OpType::Instruction(InstructionType::NotEquals) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((b != a) as u64); stack.push(usize::from(b != a));
ti += 1; ti += 1;
}, },
OpType::Ge => { OpType::Instruction(InstructionType::Ge) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((b >= a) as u64); stack.push(usize::from(b >= a));
ti += 1; ti += 1;
}, },
OpType::Le => { OpType::Instruction(InstructionType::Le) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((b <= a) as u64); stack.push(usize::from(b <= a));
ti += 1; ti += 1;
}, },
OpType::Band => { OpType::Instruction(InstructionType::Band) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((a & b) as u64); stack.push(a & b);
ti += 1; ti += 1;
} }
OpType::Bor => { OpType::Instruction(InstructionType::Bor) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((a | b) as u64); stack.push(a | b);
ti += 1; ti += 1;
} }
OpType::Shr => { OpType::Instruction(InstructionType::Shr) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((b >> a) as u64); stack.push(b >> a);
ti += 1; ti += 1;
} }
OpType::Shl => { OpType::Instruction(InstructionType::Shl) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((b << a) as u64); stack.push(b << a);
ti += 1; ti += 1;
} }
OpType::DivMod => { OpType::Instruction(InstructionType::DivMod) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((b / a) as u64); stack.push(b / a);
stack.push((b % a) as u64); stack.push(b % a);
ti += 1; ti += 1;
} }
OpType::Mul => { OpType::Instruction(InstructionType::Mul) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((b * a) as u64); stack.push(b * a);
ti += 1; ti += 1;
} }
// blocks // blocks
OpType::If => { OpType::Keyword(KeywordType::If) => {
let a = stack_pop(&mut stack, &pos)?; let a = stack_pop(&mut stack, &pos)?;
if a == 0 { if a == 0 {
// println!("If({ti}) => t: {:?} j: {}", tokens[token.jmp as usize].typ, token.jmp); // println!("If({ti}) => t: {:?} j: {}", tokens[token.jmp as usize].typ, token.jmp);
ti = (token.jmp) as usize; ti = token.jmp;
} else { } else {
ti += 1; ti += 1;
} }
}, },
OpType::Else => { OpType::Keyword(KeywordType::Else) | OpType::Keyword(KeywordType::End) => {
// println!("Else({ti}) => t: {:?} j: {}", tokens[token.jmp as usize].typ, token.jmp); ti = token.jmp;
ti = (token.jmp) as usize;
},
OpType::End => {
// println!("End({ti}) => t: {:?} j: {}", tokens[token.jmp as usize].typ, token.jmp);
ti = (token.jmp) as usize;
} }
OpType::While => { OpType::Keyword(KeywordType::While) => {
ti += 1; ti += 1;
} }
OpType::Do => { OpType::Keyword(KeywordType::Do) => {
let a = stack.pop().unwrap(); let a = stack.pop().unwrap();
if a == 0 { if a == 0 {
ti = (token.jmp) as usize; ti = token.jmp;
} else { } else {
ti += 1; ti += 1;
} }
} }
OpType::Syscall0 => { OpType::Instruction(InstructionType::Syscall0) => {
todo!(); todo!();
// ti += 1; // ti += 1;
}, },
OpType::Syscall1 => { OpType::Instruction(InstructionType::Syscall1) => {
todo!(); todo!();
// ti += 1; // ti += 1;
}, },
OpType::Syscall2 => { OpType::Instruction(InstructionType::Syscall2) => {
todo!(); todo!();
// ti += 1; // ti += 1;
}, },
OpType::Syscall3 => { OpType::Instruction(InstructionType::Syscall3) => {
let rax = stack_pop(&mut stack, &pos)?; let rax = stack_pop(&mut stack, &pos)?;
let rdi = stack_pop(&mut stack, &pos)?; let rdi = stack_pop(&mut stack, &pos)?;
let rsi = stack_pop(&mut stack, &pos)?; let rsi = stack_pop(&mut stack, &pos)?;
@ -263,6 +250,7 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<i32>{
// println!("yes"); // println!("yes");
let ret = match rax { let ret = match rax {
1 => syscalls::sys_write(rax, rdi, rsi, rdx, &mem), 1 => syscalls::sys_write(rax, rdi, rsi, rdx, &mem),
0 => 0, //? temp, so clippy doesnt complain
_ => { _ => {
error!("Syscall(3) #{} is not implemented", rax); error!("Syscall(3) #{} is not implemented", rax);
return Err(eyre!("Syscall not implemented")); return Err(eyre!("Syscall not implemented"));
@ -272,21 +260,19 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<i32>{
// println!("{}", stack.len()); // println!("{}", stack.len());
ti += 1; ti += 1;
}, },
OpType::Syscall4 => { OpType::Instruction(InstructionType::Syscall4) => {
todo!(); todo!();
// ti += 1; // ti += 1;
}, },
OpType::Syscall5 => { OpType::Instruction(InstructionType::Syscall5) => {
todo!(); todo!();
// ti += 1; // ti += 1;
}, },
OpType::Syscall6 => { OpType::Instruction(InstructionType::Syscall6) => {
todo!(); todo!();
// ti += 1; // ti += 1;
}, },
OpType::None => unreachable!(), OpType::Instruction(InstructionType::None) | OpType::Keyword(KeywordType::Macro) | OpType::Keyword(KeywordType::Include) => unreachable!()
OpType::Macro => unreachable!(),
OpType::Include => unreachable!()
} }
} }

View File

@ -1,22 +1,20 @@
pub fn sys_write(sys_n: u64, fd: u64, buff: u64, count: u64, mem: &Vec<u8> ) -> u64 { pub fn sys_write(sys_n: usize, fd: usize, buff: usize, count: usize, mem: &Vec<u8> ) -> usize {
let mem = (*mem).clone(); let mem = (*mem).clone();
let buff = buff as usize;
let count = count as usize;
// println!("{:?}", &mem[buff..(buff + count)]); // println!("{:?}", &mem[buff..(buff + count)]);
// return 0 ; // return 0 ;
let s = &mem[buff..(buff + count)].iter().map(|i| { let s = &mem[buff..(buff + count)].iter().map(|i| {
char::from_u32((*i) as u32).unwrap_or('_').to_string() char::from_u32(u32::from(*i)).unwrap_or('_').to_string()
}).collect::<Vec<String>>().join(""); }).collect::<String>();
match fd { match fd {
1 => { 1 => {
print!("{}", s); print!("{s}");
}, },
2 => { 2 => {
eprint!("{}", s); eprint!("{s}");
}, },
_ => panic!("Unknown file {}", fd) _ => panic!("Unknown file {fd}")
}; };
let _ = std::io::Write::flush(&mut std::io::stdout()); let _ = std::io::Write::flush(&mut std::io::stdout());
let _ = std::io::Write::flush(&mut std::io::stderr()); let _ = std::io::Write::flush(&mut std::io::stderr());

View File

@ -5,45 +5,45 @@ use color_eyre::Result;
fn lex_word(s: String, tok_type: TokenType) -> (TokenType, String) { fn lex_word(s: String, tok_type: TokenType) -> (TokenType, String) {
match s { match s {
s if s.parse::<u64>().is_ok() && tok_type == TokenType::Word => { // negative numbers not yet implemented s if s.parse::<u64>().is_ok() && tok_type == TokenType::Word => { // negative numbers not yet implemented
return (TokenType::Int, s); (TokenType::Int, s)
}, },
s if tok_type == TokenType::Word => { s if tok_type == TokenType::Word => {
return (TokenType::Word, s); (TokenType::Word, s)
}, },
s if tok_type == TokenType::String => { s if tok_type == TokenType::String => {
return (TokenType::String, s); (TokenType::String, s)
} }
s if tok_type == TokenType::Char=> { s if tok_type == TokenType::Char => {
return (TokenType::Char, s); (TokenType::Char, s)
} }
_ => unreachable!() _ => unreachable!()
} }
} }
pub fn find_col<F>(text: String, mut col: u32, predicate: F) -> Result<u32> where F: Fn(char, char) -> bool { pub fn find_col<F>(text: &str, mut col: usize, predicate: F) -> usize where F: Fn(char, char) -> bool {
let mut last = '\0'; let mut last = '\0';
while (col as usize) < text.len() && !predicate(text.chars().nth(col as usize).unwrap(), last) { while col < text.len() && !predicate(text.chars().nth(col).unwrap(), last) {
last = text.chars().nth(col as usize).unwrap(); last = text.chars().nth(col).unwrap();
col += 1; col += 1;
} }
Ok(col) col
} }
// TODO: Implement multiline strings // TODO: Implement multiline strings
fn lex_line(text: String) -> Result<Vec<(u32, String, TokenType)>> { fn lex_line(text: &str) -> Vec<(usize, String, TokenType)> {
let mut tokens: Vec<(u32, String, TokenType)> = Vec::new(); let mut tokens: Vec<(usize, String, TokenType)> = Vec::new();
let mut col = find_col(text.clone(), 0, |x, _| !x.is_whitespace())?; let mut col = find_col(text, 0, |x, _| !x.is_whitespace());
let mut col_end: u32 = 0; let mut col_end: usize = 0;
while col_end < text.clone().len() as u32 { while col_end < text.to_string().len() {
if (text.len() - col as usize) < 1 { if (text.len() - col) < 1 {
return Ok(tokens); return tokens;
} }
if &text[(col as usize)..(col + 1) as usize] == "\"" { if &text[col..=col] == "\"" {
col_end = find_col(text.clone(), col + 1, |x, x2| x == '"' && x2 != '\\')?; col_end = find_col(text, col + 1, |x, x2| x == '"' && x2 != '\\');
let t = &text[((col + 1) as usize)..(col_end as usize)]; let t = &text[(col + 1)..col_end];
let t = t.replace("\\n", "\n") let t = t.replace("\\n", "\n")
.replace("\\t", "\t") .replace("\\t", "\t")
.replace("\\r", "\r") .replace("\\r", "\r")
@ -53,11 +53,11 @@ fn lex_line(text: String) -> Result<Vec<(u32, String, TokenType)>> {
if !t.is_empty() { if !t.is_empty() {
tokens.push((col, t.to_string(), TokenType::String)); tokens.push((col, t.to_string(), TokenType::String));
} }
col = find_col(text.clone(), col_end + 1, |x, _| !x.is_whitespace())?; col = find_col(text, col_end + 1, |x, _| !x.is_whitespace());
} else if &text[(col as usize)..(col + 1) as usize] == "'"{ } else if &text[col..=col] == "'"{
col_end = find_col(text.clone(), col + 1, |x, x2| x == '\'' && x2 != '\\')?; col_end = find_col(text, col + 1, |x, x2| x == '\'' && x2 != '\\');
let t = &text[((col + 1) as usize)..(col_end as usize)]; let t = &text[(col + 1)..col_end];
let t = t.replace("\\n", "\n") let t = t.replace("\\n", "\n")
.replace("\\t", "\t") .replace("\\t", "\t")
.replace("\\r", "\r") .replace("\\r", "\r")
@ -69,44 +69,44 @@ fn lex_line(text: String) -> Result<Vec<(u32, String, TokenType)>> {
if !t.is_empty() { if !t.is_empty() {
tokens.push((col, t.to_string(), TokenType::Char)); tokens.push((col, t.to_string(), TokenType::Char));
} }
col = find_col(text.clone(), col_end + 1, |x, _| !x.is_whitespace())?; col = find_col(text, col_end + 1, |x, _| !x.is_whitespace());
} else { } else {
col_end = find_col(text.clone(), col, |x, _| x.is_whitespace())?; col_end = find_col(text, col, |x, _| x.is_whitespace());
let t = &text[(col as usize)..((col_end as usize))]; let t = &text[col..col_end];
if t == "//" { if t == "//" {
return Ok(tokens); return tokens;
} }
if !t.is_empty() { if !t.is_empty() {
tokens.push((col, t.to_string(), TokenType::Word)); tokens.push((col, t.to_string(), TokenType::Word));
} }
col = find_col(text.clone(), col_end, |x, _| !x.is_whitespace())?; col = find_col(text, col_end, |x, _| !x.is_whitespace());
} }
} }
Ok(tokens) tokens
} }
pub fn lex(code: String, file: &String, args: Args, preprocessing: bool) -> Result<Vec<Token>> { pub fn lex<S: Into<String> + std::marker::Copy>(code: &str, file: S, args: &Args, preprocessing: bool) -> Result<Vec<Token>> {
let lines: Vec<(usize, &str)> = code let lines: Vec<(usize, &str)> = code
.split(['\n', '\r']) .split(['\n', '\r'])
.enumerate() .enumerate()
.collect(); .collect();
let lines: Vec<(u32, String)> = lines.iter().map(|i| (i.0 as u32, i.1.to_string())).collect(); let lines: Vec<(usize, String)> = lines.iter().map(|i| (i.0, i.1.to_string())).collect();
let mut tokens: Vec<Token> = Vec::new(); let mut tokens: Vec<Token> = Vec::new();
for (row, line) in lines { for (row, line) in lines {
let lt = lex_line(line)?; let lt = lex_line(&line);
for (col, tok, tok_type) in lt { for (col, tok, tok_type) in lt {
let (tok_type, tok) = lex_word(tok, tok_type); let (tok_type, tok) = lex_word(tok, tok_type);
let t = Token{ let t = Token{
file: file.clone(), file: file.into(),
line: row + 1, line: row + 1,
col: col, col,
text: tok, text: tok,
typ: tok_type typ: tok_type
}; };

View File

@ -8,7 +8,6 @@ mod preprocessor;
use std::fs; use std::fs;
use color_eyre::Result;
use clap::Parser; use clap::Parser;
pub const DEFAULT_OUT_FILE: &str = "a.out"; pub const DEFAULT_OUT_FILE: &str = "a.out";
@ -54,52 +53,38 @@ pub struct Args {
} }
fn main() -> Result<()> { fn main() {
let args = Args::parse(); let args = Args::parse();
let code = match fs::read_to_string(&args.in_file) { let Ok(code) = fs::read_to_string(&args.in_file) else {
Ok(t) => t, error!("Failed to read file {}, exiting!", &args.in_file);
Err(_) => { return;
error!("Failed to read file {}, exiting!", &args.in_file);
return Ok(());
}
}; };
let tokens = match lexer::lex(code, &args.in_file, args.clone(), true) { let Ok(tokens) = lexer::lex(&code, &args.in_file, &args, true) else {
Ok(t) => t, error!("Lexing failed, exiting!");
Err(_) => { return;
error!("Lexing failed, exiting!");
return Ok(());
}
}; };
let mut parser = parser::Parser::new(tokens); let mut parser = parser::Parser::new(tokens);
let tokens = match parser.parse() { let Ok(tokens) = parser.parse() else {
Ok(t) => t, error!("Parsing failed, exiting!");
Err(_) => { return;
error!("Parsing failed, exiting!");
return Ok(());
}
}; };
let c = if args.compile && args.interpret { let c = if args.compile && args.interpret {
error!("Cannot compile and interpret at the same time"); error!("Cannot compile and interpret at the same time");
0 0
} else if args.interpret { } else if args.interpret {
match interpret::linux_x86_64::run(tokens) { if let Ok(c) = interpret::linux_x86_64::run(&tokens) { c } else {
Ok(c) => c, error!("Interpretation failed, exiting!");
Err(_) => { 1
error!("Interpretation failed, exiting!");
1
}
} }
} else if args.compile { } else if args.compile {
match compile::linux_x86_64::compile(tokens, args) { if let Ok(c) = compile::linux_x86_64::compile(&tokens, &args) { c } else {
Ok(c) => c, error!("Compilation failed, exiting!");
Err(_) => { 1
error!("Compilation failed, exiting!");
1
}
} }
} else { } else {
error!("Did not choose to compile or to interpret, exiting"); error!("Did not choose to compile or to interpret, exiting");

View File

@ -1,61 +1,57 @@
use std::{collections::HashMap, ops::Deref}; use std::ops::Deref;
use crate::{constants::{Operator, OpType, Token, TokenType}, lerror}; use crate::{constants::{Operator, OpType, Token, TokenType, Loc, KeywordType, InstructionType}, lerror};
use color_eyre::Result; use color_eyre::Result;
use eyre::eyre; use eyre::eyre;
pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> { pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
let mut stack: Vec<u32> = Vec::new(); let mut stack: Vec<usize> = Vec::new();
for ip in 0..program.len() { for ip in 0..program.len() {
let op = &program.clone()[ip]; let op = &program.clone()[ip];
match op.typ { match op.typ {
OpType::If => { OpType::Keyword(KeywordType::If) |
stack.push(ip as u32) OpType::Keyword(KeywordType::While) => {
stack.push(ip);
} }
OpType::Else => { OpType::Keyword(KeywordType::Else) => {
let if_ip = stack.pop().unwrap(); let if_ip = stack.pop().unwrap();
if program[if_ip as usize].typ != OpType::If { if program[if_ip].typ != OpType::Keyword(KeywordType::If) {
lerror!(&op.clone().loc,"'end' can only close 'if' blocks"); lerror!(&op.clone().loc,"'end' can only close 'if' blocks");
return Err(eyre!("Bad block")); return Err(eyre!("Bad block"));
} }
// let mut if_og = &mut tokens[if_ip as usize]; program[if_ip].jmp = ip + 1;
// (*if_og).jmp = (ip + 1) as i32; stack.push(ip);
program[if_ip as usize].jmp = (ip + 1) as i32;
stack.push(ip as u32);
}, },
OpType::End => { OpType::Keyword(KeywordType::End) => {
let block_ip = stack.pop().unwrap(); let block_ip = stack.pop().unwrap();
// let mut block_og = &mut tokens[block_ip as usize].clone();
if program[block_ip as usize].typ == OpType::If ||
program[block_ip as usize].typ == OpType::Else {
program[block_ip as usize].jmp = ip as i32;
program[ip as usize].jmp = (ip + 1)as i32;
} else if program[block_ip as usize].typ == OpType::Do { if program[block_ip].typ == OpType::Keyword(KeywordType::If) ||
program[ip].jmp = program[block_ip as usize].jmp; program[block_ip].typ == OpType::Keyword(KeywordType::Else) {
program[block_ip as usize].jmp = (ip + 1) as i32;
program[block_ip].jmp = ip;
program[ip].jmp = ip + 1;
} else if program[block_ip].typ == OpType::Keyword(KeywordType::Do) {
program[ip].jmp = program[block_ip].jmp;
program[block_ip].jmp = ip + 1;
} else { } else {
lerror!(&op.clone().loc,"'end' can only close 'if' blocks"); lerror!(&op.clone().loc,"'end' can only close 'if' blocks");
return Err(eyre!("")); return Err(eyre!(""));
} }
} }
OpType::While => { OpType::Keyword(KeywordType::Do) => {
stack.push(ip as u32);
}
OpType::Do => {
let while_ip = stack.pop().unwrap(); let while_ip = stack.pop().unwrap();
program[ip as usize].jmp = while_ip as i32; program[ip].jmp = while_ip;
stack.push(ip as u32); stack.push(ip);
} }
_ => () _ => ()
} }
} }
if stack.len() > 0 { if !stack.is_empty() {
lerror!(&program[stack.pop().expect("Empy stack") as usize].clone().loc,"Unclosed block"); lerror!(&program[stack.pop().expect("Empy stack")].clone().loc,"Unclosed block");
return Err(eyre!("Unclosed block")); return Err(eyre!("Unclosed block"));
} }
@ -83,14 +79,14 @@ impl Parser {
let pos = (token.file.clone(), token.line, token.col); let pos = (token.file.clone(), token.line, token.col);
match token.typ { match token.typ {
TokenType::Word => { TokenType::Word => {
let word_type = lookup_word(token.text.clone(), &pos); let word_type = lookup_word(&token.text, &pos);
tokens.push(Operator::new(word_type, 0, token.text.clone(), token.file.clone(), token.line, token.col)); tokens.push(Operator::new(word_type, 0, token.text.clone(), token.file.clone(), token.line, token.col));
}, },
TokenType::Int => {// negative numbers not yet implemented TokenType::Int => {// negative numbers not yet implemented
tokens.push(Operator::new(OpType::PushInt, token.text.parse::<i64>()?, String::new(), token.file.clone(), token.line, token.col)); tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.text.parse::<usize>()?, String::new(), token.file.clone(), token.line, token.col));
}, },
TokenType::String => { TokenType::String => {
tokens.push(Operator::new(OpType::PushStr, 0, token.text.clone(), token.file.clone(), token.line, token.col)); tokens.push(Operator::new(OpType::Instruction(InstructionType::PushStr), 0, token.text.clone(), token.file.clone(), token.line, token.col));
} }
TokenType::Char => { TokenType::Char => {
let c = token.text.clone(); let c = token.text.clone();
@ -99,7 +95,7 @@ impl Parser {
return Err(eyre!("")); return Err(eyre!(""));
} }
tokens.push(Operator::new(OpType::PushInt, token.text.chars().next().unwrap() as i64, String::new(), token.file.clone(), token.line, token.col)); tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.text.chars().next().unwrap() as usize, String::new(), token.file.clone(), token.line, token.col));
} }
}; };
@ -107,66 +103,60 @@ impl Parser {
//"print" => tokens.push(Operator::new(OpType::Print, 0, token.file.clone(), token.line, token.col)), //"print" => tokens.push(Operator::new(OpType::Print, 0, token.file.clone(), token.line, token.col)),
} }
Ok(cross_ref(tokens)?) cross_ref(tokens)
} }
} }
pub fn lookup_word<P: Deref<Target = (String, u32, u32)>>(s: String, _pos: P) -> OpType { pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
let lookup_table: HashMap<&str, OpType> = HashMap::from([ match s {
//stack //stack
("print", OpType::Print), "print" => OpType::Instruction(InstructionType::Print),
("dup", OpType::Dup), "dup" => OpType::Instruction(InstructionType::Dup),
("drop", OpType::Drop), "drop" => OpType::Instruction(InstructionType::Drop),
("2dup", OpType::Dup2), "rot" => OpType::Instruction(InstructionType::Rot),
("rot", OpType::Rot), "over" => OpType::Instruction(InstructionType::Over),
("over", OpType::Over), "swap" => OpType::Instruction(InstructionType::Swap),
("swap", OpType::Swap),
// comp and math // comp and math
("+", OpType::Plus), "+" => OpType::Instruction(InstructionType::Plus),
("-", OpType::Minus), "-" => OpType::Instruction(InstructionType::Minus),
("=", OpType::Equals), "=" => OpType::Instruction(InstructionType::Equals),
("!=", OpType::NotEquals), "!=" => OpType::Instruction(InstructionType::NotEquals),
(">", OpType::Gt), ">" => OpType::Instruction(InstructionType::Gt),
("<", OpType::Lt), "<" => OpType::Instruction(InstructionType::Lt),
(">=", OpType::Ge), ">=" => OpType::Instruction(InstructionType::Ge),
("<=", OpType::Le), "<=" => OpType::Instruction(InstructionType::Le),
("band", OpType::Band), "band" => OpType::Instruction(InstructionType::Band),
("bor", OpType::Bor), "bor" => OpType::Instruction(InstructionType::Bor),
("shr", OpType::Shr), "shr" => OpType::Instruction(InstructionType::Shr),
("shl", OpType::Shl), "shl" => OpType::Instruction(InstructionType::Shl),
("divmod", OpType::DivMod), "divmod" => OpType::Instruction(InstructionType::DivMod),
("*", OpType::Mul), "*" => OpType::Instruction(InstructionType::Mul),
// block // block
("if", OpType::If), "if" => OpType::Keyword(KeywordType::If),
("else", OpType::Else), "else" => OpType::Keyword(KeywordType::Else),
("end", OpType::End), "end" => OpType::Keyword(KeywordType::End),
("while", OpType::While), "while" => OpType::Keyword(KeywordType::While),
("do", OpType::Do), "do" => OpType::Keyword(KeywordType::Do),
("macro", OpType::Macro), "macro" => OpType::Keyword(KeywordType::Macro),
("include", OpType::Include), // technically not but it fits next to macros "include" => OpType::Keyword(KeywordType::Include),
// mem // mem
("mem", OpType::Mem), "mem" => OpType::Instruction(InstructionType::Mem),
("!8", OpType::Load8), "!8" => OpType::Instruction(InstructionType::Load8),
("@8", OpType::Store8), "@8" => OpType::Instruction(InstructionType::Store8),
("syscall0", OpType::Syscall0), "syscall0" => OpType::Instruction(InstructionType::Syscall0),
("syscall1", OpType::Syscall1), "syscall1" => OpType::Instruction(InstructionType::Syscall1),
("syscall2", OpType::Syscall2), "syscall2" => OpType::Instruction(InstructionType::Syscall2),
("syscall3", OpType::Syscall3), "syscall3" => OpType::Instruction(InstructionType::Syscall3),
("syscall4", OpType::Syscall4), "syscall4" => OpType::Instruction(InstructionType::Syscall4),
("syscall5", OpType::Syscall5), "syscall5" => OpType::Instruction(InstructionType::Syscall5),
("syscall6", OpType::Syscall6), "syscall6" => OpType::Instruction(InstructionType::Syscall6),
]); _ => OpType::Instruction(InstructionType::None)
match lookup_table.get(s.as_str()) {
Some(v) => v.clone(),
None => {
OpType::None
}
} }
} }

View File

@ -4,7 +4,7 @@ use std::path::PathBuf;
use color_eyre::Result; use color_eyre::Result;
use eyre::eyre; use eyre::eyre;
use crate::constants::{Token, Loc, OpType, TokenType}; use crate::constants::{Token, Loc, OpType, TokenType, KeywordType, InstructionType};
use crate::lexer::lex; use crate::lexer::lex;
use crate::{lerror, lnote, Args, warn}; use crate::{lerror, lnote, Args, warn};
use crate::parser::lookup_word; use crate::parser::lookup_word;
@ -15,19 +15,19 @@ pub struct Macro {
pub tokens: Vec<Token> pub tokens: Vec<Token>
} }
pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
let mut program: Vec<Token> = Vec::new(); let mut program: Vec<Token> = Vec::new();
let mut macros: HashMap<String, Macro> = HashMap::new(); let mut macros: HashMap<String, Macro> = HashMap::new();
let mut rtokens = tokens.clone(); let mut rtokens = tokens;
rtokens.reverse(); rtokens.reverse();
while rtokens.len() > 0 { while !rtokens.is_empty() {
let token = rtokens.pop().unwrap(); let token = rtokens.pop().unwrap();
let op_type = lookup_word(token.text.clone(), &token.loc()); let op_type = lookup_word(&token.text, &token.loc());
match token.clone() { match token.clone() {
_ if op_type == OpType::Macro => { _ if op_type == OpType::Keyword(KeywordType::Macro) => {
if rtokens.len() == 0 { if rtokens.is_empty(){
lerror!(&token.loc(), "Macro name not found, expected {} but found nothing", TokenType::Word.human()); lerror!(&token.loc(), "Macro name not found, expected {} but found nothing", TokenType::Word.human());
return Err(eyre!("")); return Err(eyre!(""));
} }
@ -37,41 +37,36 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
lerror!(&macro_name.loc(), "Bad macro name, expected {} but found {}", TokenType::Word.human(), macro_name.typ.human()); lerror!(&macro_name.loc(), "Bad macro name, expected {} but found {}", TokenType::Word.human(), macro_name.typ.human());
return Err(eyre!("")); return Err(eyre!(""));
} }
let word = lookup_word(macro_name.text.clone(), &macro_name.loc()); let word = lookup_word(&macro_name.text, &macro_name.loc());
if word != OpType::None { if word != OpType::Instruction(InstructionType::None) {
lerror!(&macro_name.loc(), "Macro name cannot be a built in word, got '{}'", word.human()); lerror!(&macro_name.loc(), "Macro name cannot be a built in word, got '{}'", word.human());
return Err(eyre!("")); return Err(eyre!(""));
} }
if macros.get(&macro_name.text.clone()).is_some() { if macros.get(&macro_name.text.clone()).is_some() && crate::constants::ALLOW_MACRO_REDEFINITION {
if crate::constants::ALLOW_MACRO_REDEFINITION { lerror!(&macro_name.loc(), "Macro redefinition is not allowed");
lerror!(&macro_name.loc(), "Macro redefinition is not allowed"); lnote!(&macros.get(&macro_name.text).unwrap().loc, "First definition here");
lnote!(&macros.get(&macro_name.text.clone()).unwrap().loc, "First definition here"); return Err(eyre!(""));
return Err(eyre!(""));
} else {
//TODO: somehow warn about redefinition of only built in macros
}
} }
let mut macr = Macro{ loc: macro_name.loc(), tokens: Vec::new() }; let mut macr = Macro{ loc: macro_name.loc(), tokens: Vec::new() };
let mut depth = 0; let mut depth = 0;
while rtokens.len() > 0 { while !rtokens.is_empty() {
let t = rtokens.pop().unwrap(); let t = rtokens.pop().unwrap();
let typ = lookup_word(t.text.clone(), &t.loc()); let typ = lookup_word(&t.text, &t.loc());
if typ == OpType::End && depth == 0 { if typ == OpType::Keyword(KeywordType::End) && depth == 0 {
break; break;
} else if typ == OpType::End && depth != 0 { } else if typ == OpType::Keyword(KeywordType::End) && depth != 0 {
depth -= 1; depth -= 1;
macr.tokens.push(t); macr.tokens.push(t);
} else if typ == OpType::Keyword(KeywordType::If) || typ == OpType::Keyword(KeywordType::Do) {
macr.tokens.push(t);
depth += 1;
} else { } else {
if typ == OpType::If || typ == OpType::Do { macr.tokens.push(t);
macr.tokens.push(t);
depth += 1;
} else {
macr.tokens.push(t);
}
} }
} }
@ -80,8 +75,8 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
} }
_ if op_type == OpType::Include => { _ if op_type == OpType::Keyword(KeywordType::Include) => {
if rtokens.len() == 0 { if rtokens.is_empty() {
lerror!(&token.loc(), "Include path not found, expected {} but found nothing", TokenType::String.human()); lerror!(&token.loc(), "Include path not found, expected {} but found nothing", TokenType::String.human());
return Err(eyre!("")); return Err(eyre!(""));
} }
@ -94,7 +89,7 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
} }
let mut in_paths = args.include.clone(); let mut in_paths = args.include.clone();
in_paths.append(&mut crate::DEFAULT_INCLUDES.to_vec().clone().iter().map(|f| f.to_string()).collect::<Vec<String>>()); in_paths.append(&mut crate::DEFAULT_INCLUDES.to_vec().clone().iter().map(|f| (*f).to_string()).collect::<Vec<String>>());
let mut include_code = String::new(); let mut include_code = String::new();
@ -113,7 +108,7 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
return Err(eyre!("")); return Err(eyre!(""));
} }
let mut code = lex(include_code, &include_path.text, args.clone(), false)?; let mut code = lex(&include_code, &include_path.text, args, false)?;
code.reverse(); code.reverse();
rtokens.append(&mut code); rtokens.append(&mut code);
@ -130,12 +125,12 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
let mut times = 0; let mut times = 0;
while program.iter().map(|f| { while program.iter().map(|f| {
if f.typ == TokenType::Word { if f.typ == TokenType::Word {
lookup_word(f.text.clone(), &f.loc()) lookup_word(&f.text, &f.loc())
} else { } else {
OpType::PushInt // i hate myself, this is a randomly picked optype so its happy and works OpType::Instruction(InstructionType::PushInt) // i hate myself, this is a randomly picked optype so its happy and works
} }
}).collect::<Vec<OpType>>().contains(&OpType::None){ }).collect::<Vec<OpType>>().contains(&OpType::Instruction(InstructionType::None)){
if times >= 50 { if times >= 50 {
warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it"); warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it");
@ -152,18 +147,20 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
pub fn expand_macros(tokens: Vec<Token>, macros: &HashMap<String, Macro>) -> Result<Vec<Token>> { pub fn expand_macros(tokens: Vec<Token>, macros: &HashMap<String, Macro>) -> Result<Vec<Token>> {
let mut program: Vec<Token> = Vec::new(); let mut program: Vec<Token> = Vec::new();
let mut rtokens = tokens.clone(); let mut rtokens = tokens;
rtokens.reverse(); rtokens.reverse();
while rtokens.len() > 0 { while !rtokens.is_empty() {
let op = rtokens.pop().unwrap(); let op = rtokens.pop().unwrap();
let op_type = lookup_word(op.text.clone(), &op.loc()); let op_type = lookup_word(&op.text, &op.loc());
if op.typ == TokenType::Word { if op.typ == TokenType::Word {
match op_type { match op_type {
OpType::None => { OpType::Instruction(InstructionType::None) => {
let m = macros.get(&op.text); let m = macros.get(&op.text);
if m.is_some() { if m.is_some() {
program.append(&mut m.unwrap().tokens.clone()) if let Some(m) = m {
program.append(&mut m.tokens.clone());
}
} else { } else {
lerror!(&op.loc(), "Unknown word '{}'", op.text.clone()); lerror!(&op.loc(), "Unknown word '{}'", op.text.clone());
return Err(eyre!("")); return Err(eyre!(""));