implement /example/rule110.mcl and fix interpreting syscalls
This commit is contained in:
parent
8a53271a91
commit
8421fbf379
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -215,6 +215,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"clap",
|
||||
"color-eyre",
|
||||
"eyre",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -8,3 +8,4 @@ edition = "2021"
|
|||
[dependencies]
|
||||
clap = { version = "4.1.8", features = ["derive"] }
|
||||
color-eyre = "0.6.2"
|
||||
eyre = "0.6.8"
|
||||
|
|
38
examples/rule110.mcl
Normal file → Executable file
38
examples/rule110.mcl
Normal file → Executable file
|
@ -1 +1,37 @@
|
|||
// TODO: Make this
|
||||
mem 98 + 1 @8
|
||||
|
||||
0 while dup 98 < do
|
||||
0 while dup 100 < do
|
||||
dup mem + !8 if
|
||||
mem 100 + 42 @8
|
||||
else
|
||||
mem 100 + 32 @8
|
||||
end
|
||||
1 mem 100 + 1 1 syscall3 drop
|
||||
|
||||
1 +
|
||||
end
|
||||
drop
|
||||
|
||||
mem 100 + 10 @8
|
||||
1 mem 100 + 1 1 syscall3 drop
|
||||
|
||||
// pattern
|
||||
mem !8 1 shl
|
||||
mem 1 + !8
|
||||
bor
|
||||
|
||||
1 while dup 98 < do
|
||||
swap 1 shl 7 band
|
||||
over mem + 1 + !8 bor
|
||||
2dup 110 swap shr 1 band
|
||||
swap mem + swap @8
|
||||
swap
|
||||
|
||||
1 +
|
||||
end
|
||||
drop drop
|
||||
|
||||
1 +
|
||||
end
|
||||
drop
|
172
src/bin/mcl_test_dev.rs
Normal file
172
src/bin/mcl_test_dev.rs
Normal file
|
@ -0,0 +1,172 @@
|
|||
|
||||
use std::path::PathBuf;
|
||||
use std::process::Stdio;
|
||||
use std::{process, fs};
|
||||
use clap::Parser;
|
||||
use color_eyre::Result;
|
||||
use eyre::eyre;
|
||||
|
||||
pub mod color {
|
||||
#![allow(dead_code)]
|
||||
pub const NONE: &str = "\x1b[0m";
|
||||
pub const RESET: &str = "\x1b[0m";
|
||||
pub const BRIGHT: &str = "\x1b[1m";
|
||||
pub const DIM: &str = "\x1b[2m";
|
||||
pub const UNDERSCORE: &str = "\x1b[4m";
|
||||
pub const BLINK: &str = "\x1b[5m";
|
||||
pub const REVERSE: &str = "\x1b[7m";
|
||||
pub const HIDDEN: &str = "\x1b[8m";
|
||||
pub const FG_BLACK: &str = "\x1b[30m";
|
||||
pub const FG_RED: &str = "\x1b[31m";
|
||||
pub const FG_GREEN: &str = "\x1b[32m";
|
||||
pub const FG_YELLOW: &str = "\x1b[33m";
|
||||
pub const FG_BLUE: &str = "\x1b[34m";
|
||||
pub const FG_MAGENTA: &str = "\x1b[35m";
|
||||
pub const FG_CYAN: &str = "\x1b[36m";
|
||||
pub const FG_WHITE: &str = "\x1b[37m";
|
||||
pub const BG_BLACK: &str = "\x1b[40m";
|
||||
pub const BG_RED: &str = "\x1b[41m";
|
||||
pub const BG_GREEN: &str = "\x1b[42m";
|
||||
pub const BG_YELLOW: &str = "\x1b[43m";
|
||||
pub const BG_BLUE: &str = "\x1b[44m";
|
||||
pub const BG_MAGENTA: &str = "\x1b[45m";
|
||||
pub const BG_CYAN: &str = "\x1b[46m";
|
||||
pub const BG_WHITE: &str = "\x1b[47m";
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
struct TestOutput {
|
||||
stdout: String,
|
||||
stderr: String,
|
||||
stdin: String,
|
||||
status: i32
|
||||
}
|
||||
|
||||
fn run_test<P: Into<PathBuf> + std::convert::AsRef<std::ffi::OsStr>>(f_in: PathBuf, f_out: &PathBuf, compiler: P, compile_mode: bool, stdin: String) -> Result<TestOutput> {
|
||||
let mut command = process::Command::new(compiler);
|
||||
command.stdout(Stdio::piped());
|
||||
command.stderr(Stdio::piped());
|
||||
if !compile_mode {
|
||||
command.arg("-sq");
|
||||
} else {
|
||||
command.arg("-cqr");
|
||||
}
|
||||
|
||||
command.arg("-i");
|
||||
command.arg(f_in);
|
||||
command.arg("-o");
|
||||
command.arg(f_out);
|
||||
|
||||
let child = command.spawn()?;
|
||||
|
||||
let out = child.wait_with_output()?;
|
||||
|
||||
let stdout = out.stdout.iter().map(|c| {
|
||||
char::from_u32((*c) as u32).expect("Failed to parse stdout char").to_string()
|
||||
}).collect::<String>();
|
||||
|
||||
let stderr = out.stderr.iter().map(|c| {
|
||||
char::from_u32((*c) as u32).expect("Failed to parse stderr char").to_string()
|
||||
}).collect::<String>();
|
||||
|
||||
|
||||
Ok(TestOutput {
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
stdin: stdin,
|
||||
status: out.status.code().unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
fn run_tests(args: Args) -> Result<()>{
|
||||
|
||||
let files = fs::read_dir(args.input)?;
|
||||
|
||||
for file in files {
|
||||
let file = file?;
|
||||
let f_name = file.file_name().to_string_lossy().to_string();
|
||||
let f_out = PathBuf::from(&args.output).join(f_name);
|
||||
|
||||
|
||||
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())?;
|
||||
compare_results(intp, comp, file.path())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
fn compare_results(intp: TestOutput, comp: TestOutput, f_in: PathBuf) -> Result<()> {
|
||||
|
||||
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!("compiled:\n{}", comp.stdout);
|
||||
println!("interpreted:\n{}", intp.stdout);
|
||||
return Err(eyre!("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"));
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
println!("{b}[ {g}OK{rs}{b} ]{rs} {f} ", g=color::FG_GREEN, rs=color::RESET, b=color::BRIGHT, f=f_in.display());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
|
||||
/// Mode, allowed modes: test, record
|
||||
#[arg(long, short)]
|
||||
mode: String,
|
||||
|
||||
/// Use compile mode
|
||||
#[arg(long, short)]
|
||||
compile: bool,
|
||||
|
||||
/// Use interpret mode
|
||||
#[arg(long, short='s')]
|
||||
interpret: bool,
|
||||
|
||||
/// Output folder
|
||||
#[arg(long, short, default_value_t=String::from("./target/mcl_test_dev"))]
|
||||
output: String,
|
||||
|
||||
/// Input folder
|
||||
#[arg(long, short, default_value_t=String::from("./tests"))]
|
||||
input: String,
|
||||
|
||||
/// Compiler path
|
||||
#[arg(long, short, default_value_t=String::from("./target/release/mclang"))]
|
||||
compiler_path: String
|
||||
|
||||
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let args = Args::parse();
|
||||
fs::create_dir_all(&args.output)?;
|
||||
match args.mode.as_str() {
|
||||
"test" => run_tests(args),
|
||||
"record" => todo!("Implement test result recording"),
|
||||
s => {
|
||||
eprintln!("Unknown mode '{s}'");
|
||||
return Err(eyre!("Bad subcommand"));
|
||||
}
|
||||
}?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -28,12 +28,12 @@ pub fn linux_x86_64_compile_and_link(of_a: &PathBuf, of_o: &PathBuf, of_c: &Path
|
|||
.stderr(Stdio::inherit())
|
||||
.spawn()?
|
||||
};
|
||||
if !quiet{
|
||||
if !quiet {
|
||||
logger::info(format!("running 'nasm {}'", nasm_args.join(" ")).as_str());
|
||||
}
|
||||
let exit = proc.wait()?;
|
||||
|
||||
if (!quiet) {
|
||||
if !quiet {
|
||||
logger::info(format!("nasm process exited with code {}", exit).as_str());
|
||||
}
|
||||
|
||||
|
@ -47,11 +47,11 @@ pub fn linux_x86_64_compile_and_link(of_a: &PathBuf, of_o: &PathBuf, of_c: &Path
|
|||
.stderr(Stdio::inherit())
|
||||
.spawn()?
|
||||
};
|
||||
if (!quiet) {
|
||||
if !quiet {
|
||||
logger::info(format!("running 'ld {}'", ld_args.join(" ")).as_str());
|
||||
}
|
||||
let exit2 = proc2.wait()?;
|
||||
if (!quiet) {
|
||||
if !quiet {
|
||||
logger::info(format!("ld process exited with code {}", exit2).as_str());
|
||||
}
|
||||
|
||||
|
@ -60,23 +60,28 @@ pub fn linux_x86_64_compile_and_link(of_a: &PathBuf, of_o: &PathBuf, of_c: &Path
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn linux_x86_64_run(bin: &PathBuf, args: Vec<String>, quiet: bool) -> Result<()> {
|
||||
pub fn linux_x86_64_run(_bin: &PathBuf, args: Vec<String>, quiet: bool) -> Result<()> {
|
||||
|
||||
let bin = PathBuf::from(
|
||||
format!("./{}", _bin.to_string_lossy())
|
||||
);
|
||||
|
||||
let mut proc = if cfg!(target_os = "windows") {
|
||||
return Ok(());
|
||||
} else {
|
||||
Command::new(bin)
|
||||
//.args(&nasm_args)
|
||||
.args(&args)
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.spawn()?
|
||||
};
|
||||
|
||||
if (!quiet) {
|
||||
logger::info(format!("running '{} {}'", bin.to_string_lossy() ,args.join(" ")).as_str());
|
||||
// println!("{}", quiet);
|
||||
if !quiet {
|
||||
logger::info(format!("running {} {}", _bin.to_string_lossy(), args.join(" ")).as_str());
|
||||
}
|
||||
let exit = proc.wait()?;
|
||||
if (!quiet) {
|
||||
logger::info(format!("{} process exited with code {}", bin.to_string_lossy(), exit).as_str());
|
||||
if !quiet {
|
||||
logger::info(format!("{} process exited with code {}", _bin.to_string_lossy(), exit).as_str());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -18,7 +18,9 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
let file = fs::File::create(&of_a)?;
|
||||
let mut writer = BufWriter::new(&file);
|
||||
|
||||
writeln!(writer, "global _start")?;
|
||||
// println!("{}", tokens.len());
|
||||
|
||||
writeln!(writer, "BITS 64")?;
|
||||
writeln!(writer, "segment .text")?;
|
||||
|
||||
writeln!(writer, "print:")?;
|
||||
|
@ -55,6 +57,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
writeln!(writer, " add rsp, 40")?;
|
||||
writeln!(writer, " ret")?;
|
||||
|
||||
writeln!(writer, "global _start")?;
|
||||
writeln!(writer, "_start:")?;
|
||||
|
||||
let mut ti = 0;
|
||||
|
@ -65,26 +68,26 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
match token.typ {
|
||||
// stack
|
||||
OpType::Push => {
|
||||
writeln!(writer, " ; -- PUSH {}", token.value)?;
|
||||
writeln!(writer, " ;; -- push {} --", token.value)?;
|
||||
writeln!(writer, " mov rax, {}", token.value)?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
|
||||
},
|
||||
OpType::Pop => {
|
||||
writeln!(writer, " ; -- POP")?;
|
||||
writeln!(writer, " pop")?;
|
||||
OpType::Drop => {
|
||||
writeln!(writer, " ;; -- drop --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Print => {
|
||||
writeln!(writer, " ; -- PRINT")?;
|
||||
writeln!(writer, " ;; -- print --")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " call print")?;
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
OpType::Dup => {
|
||||
writeln!(writer, " ; -- DUP")?;
|
||||
writeln!(writer, " ;; -- dup --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
|
@ -92,19 +95,19 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
ti += 1;
|
||||
},
|
||||
OpType::Dup2 => {
|
||||
writeln!(writer, " ; -- DUP2")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " ;; -- 2dup --")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
OpType::Rot => {
|
||||
writeln!(writer, " ; -- DUP")?;
|
||||
writeln!(writer, " ;; -- rot --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rcx")?;
|
||||
|
@ -115,16 +118,16 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
ti += 1;
|
||||
},
|
||||
OpType::Swap => {
|
||||
writeln!(writer, " ; -- DUP")?;
|
||||
writeln!(writer, " ;; -- swap --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Over => {
|
||||
writeln!(writer, " ; -- DUP")?;
|
||||
writeln!(writer, " ;; -- over --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
|
@ -136,12 +139,12 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
|
||||
//mem
|
||||
OpType::Mem => {
|
||||
writeln!(writer, " ; -- MEM")?;
|
||||
writeln!(writer, " ;; -- mem --")?;
|
||||
writeln!(writer, " push mem")?;
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Load8 => {
|
||||
writeln!(writer, " ; -- LOAD64")?;
|
||||
writeln!(writer, " ;; -- load --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " xor rbx, rbx")?;
|
||||
writeln!(writer, " mov bl, [rax]")?;
|
||||
|
@ -150,7 +153,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
}
|
||||
|
||||
OpType::Store8 => {
|
||||
writeln!(writer, " ; -- STORE64")?;
|
||||
writeln!(writer, " ;; -- store --")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " mov [rax], bl")?;
|
||||
|
@ -159,7 +162,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
|
||||
// math
|
||||
OpType::Plus => {
|
||||
writeln!(writer, " ; -- PLUS")?;
|
||||
writeln!(writer, " ;; -- plus --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " add rax, rbx")?;
|
||||
|
@ -167,7 +170,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
ti += 1;
|
||||
},
|
||||
OpType::Minus => {
|
||||
writeln!(writer, " ; -- MINUS")?;
|
||||
writeln!(writer, " ;; -- minus --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " sub rbx, rax")?;
|
||||
|
@ -175,7 +178,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
ti += 1;
|
||||
},
|
||||
OpType::Equals => {
|
||||
writeln!(writer, " ; -- EQUALS")?;
|
||||
writeln!(writer, " ;; -- equals --")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
|
@ -187,7 +190,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
|
||||
},
|
||||
OpType::Lt => {
|
||||
writeln!(writer, " ; -- LT")?;
|
||||
writeln!(writer, " ;; -- lt --")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -199,7 +202,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
|
||||
},
|
||||
OpType::Gt => {
|
||||
writeln!(writer, " ; -- GT")?;
|
||||
writeln!(writer, " ;; -- gt --")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -211,49 +214,49 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
|
||||
},
|
||||
OpType::Band => {
|
||||
writeln!(writer, " ; -- BAND")?;
|
||||
writeln!(writer, " ;; -- band --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " and rax, rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " and rbx, rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Bor => {
|
||||
writeln!(writer, " ; -- BOR")?;
|
||||
writeln!(writer, " ;; -- bor --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " or rax, rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " or rbx, rax")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Shr => {
|
||||
writeln!(writer, " ; -- SHR")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " ;; -- shr --")?;
|
||||
writeln!(writer, " pop rcx")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " shr rax, rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " shr rbx, cl")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Shl => {
|
||||
writeln!(writer, " ; -- SHL")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " ;; -- shl --")?;
|
||||
writeln!(writer, " pop rcx")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " shl rax, rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
writeln!(writer, " shl rbx, cl")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Div => {
|
||||
writeln!(writer, " ; -- DIV")?;
|
||||
writeln!(writer, " ;; -- div --")?;
|
||||
writeln!(writer, " xor rdx, rdx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " div rbx")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
//writeln!(writer, " push rdx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Mul => {
|
||||
writeln!(writer, " ; -- MUL")?;
|
||||
writeln!(writer, " ;; -- mul --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " mul rbx")?;
|
||||
|
@ -265,42 +268,44 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
|
||||
// block
|
||||
OpType::If => {
|
||||
writeln!(writer, " ; -- IF")?;
|
||||
writeln!(writer, " ;; -- if --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " test rax, rax")?;
|
||||
writeln!(writer, " jz addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Else => {
|
||||
writeln!(writer, " ; -- ELSE")?;
|
||||
writeln!(writer, " ;; -- else --")?;
|
||||
writeln!(writer, " jmp addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::While => {
|
||||
writeln!(writer, " ; -- WHILE")?;
|
||||
writeln!(writer, " ;; -- while --")?;
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Do => {
|
||||
writeln!(writer, " ; -- DO")?;
|
||||
writeln!(writer, " ;; -- do --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " test rax, rax")?;
|
||||
writeln!(writer, " jz addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
}
|
||||
OpType::End => {
|
||||
writeln!(writer, " ; -- END")?;
|
||||
writeln!(writer, " ;; -- end --")?;
|
||||
if ti + 1 != token.jmp as usize {
|
||||
writeln!(writer, " jmp addr_{}", token.jmp)?;
|
||||
}
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Syscall0 => {
|
||||
writeln!(writer, " ; -- SYSCALL0")?;
|
||||
writeln!(writer, " ;; -- syscall0 --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Syscall1 => {
|
||||
writeln!(writer, " ; -- SYSCALL1")?;
|
||||
writeln!(writer, " ;; -- syscall1 --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
|
@ -308,7 +313,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
ti += 1;
|
||||
},
|
||||
OpType::Syscall2 => {
|
||||
writeln!(writer, " ; -- SYSCALL2")?;
|
||||
writeln!(writer, " ;; -- syscall2 --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
|
@ -317,7 +322,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
ti += 1;
|
||||
},
|
||||
OpType::Syscall3 => {
|
||||
writeln!(writer, " ; -- SYSCALL3")?;
|
||||
writeln!(writer, " ;; -- syscall3 --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
|
@ -328,7 +333,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
ti += 1;
|
||||
},
|
||||
OpType::Syscall4 => {
|
||||
writeln!(writer, " ; -- SYSCALL4")?;
|
||||
writeln!(writer, " ;; -- syscall4 --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
|
@ -339,7 +344,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
ti += 1;
|
||||
},
|
||||
OpType::Syscall5 => {
|
||||
writeln!(writer, " ; -- SYSCALL5")?;
|
||||
writeln!(writer, " ;; -- syscall5 --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
|
@ -351,7 +356,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
ti += 1;
|
||||
},
|
||||
OpType::Syscall6 => {
|
||||
writeln!(writer, " ; -- SYSCALL6")?;
|
||||
writeln!(writer, " ;; -- syscall6 --")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " pop rsi")?;
|
||||
|
@ -371,7 +376,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
|||
writeln!(writer, " syscall")?;
|
||||
|
||||
writeln!(writer, "segment .bss")?;
|
||||
writeln!(writer, " mem: resb {}", crate::compile::MEM_SZ)?;
|
||||
writeln!(writer, "mem: resb {}", crate::compile::MEM_SZ)?;
|
||||
|
||||
writer.flush()?;
|
||||
linux_x86_64_compile_and_link(&of_a, &of_o, &of_c, args.quiet)?;
|
||||
|
|
|
@ -4,7 +4,7 @@ pub enum OpType {
|
|||
|
||||
// stack
|
||||
Push,
|
||||
Pop,
|
||||
Drop,
|
||||
Print,
|
||||
Dup,
|
||||
Dup2, // a b => a b a b
|
||||
|
@ -70,7 +70,7 @@ impl Operator {
|
|||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Token {
|
||||
pub file: String,
|
||||
pub line: u32,
|
||||
|
|
|
@ -1,45 +1,51 @@
|
|||
use std::fmt::format;
|
||||
|
||||
use crate::{constants::OpType, util::logger};
|
||||
use crate::{constants::OpType, util::{logger, self}};
|
||||
// use crate::util::logger;
|
||||
use color_eyre::Result;
|
||||
|
||||
use eyre::eyre;
|
||||
mod syscalls;
|
||||
|
||||
fn stack_pop(stack: &mut Vec<u64>) -> Result<u64, &'static str> {
|
||||
fn stack_pop(stack: &mut Vec<u64>, pos: &(String, u32, u32)) -> Result<u64> {
|
||||
match stack.pop() {
|
||||
Some(i) => Ok(i),
|
||||
None => Err("Stack underflow"),
|
||||
None => {
|
||||
util::logger::pos_error(pos.clone(), "Stack underflow");
|
||||
Err(eyre!("Stack underflow"))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<(), &'static str>{
|
||||
pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<()>{
|
||||
let mut stack: Vec<u64> = Vec::new();
|
||||
let mut ti = 0;
|
||||
let mut mem: Vec<u8> = vec![0; crate::compile::MEM_SZ as usize];
|
||||
// for token in &tokens {
|
||||
// println!("{{typ: \"{:?}\", val: {}, jmp: {}}}", token.typ, token.value, token.jmp);
|
||||
|
||||
// }
|
||||
while ti < tokens.len() {
|
||||
let token = &tokens[ti];
|
||||
|
||||
let pos = token.pos.clone();
|
||||
// println!("{:?}", token.typ);
|
||||
match token.typ {
|
||||
|
||||
// stack
|
||||
OpType::Push => {
|
||||
stack.push(token.value as u64);
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Pop => {
|
||||
OpType::Drop => {
|
||||
stack.pop();
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Dup => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
stack.push(a);
|
||||
stack.push(a);
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Dup2 => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push(b);
|
||||
stack.push(a);
|
||||
stack.push(b);
|
||||
|
@ -47,24 +53,24 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<(), &'static str>{
|
|||
ti += 1;
|
||||
}
|
||||
OpType::Rot => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let c = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
let c = stack_pop(&mut stack, &pos)?;
|
||||
stack.push(b);
|
||||
stack.push(a);
|
||||
stack.push(c);
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Swap => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let b = stack_pop(&mut stack)?;
|
||||
stack.push(b);
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push(a);
|
||||
stack.push(b);
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Over => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push(b);
|
||||
stack.push(a);
|
||||
stack.push(b);
|
||||
|
@ -72,7 +78,7 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<(), &'static str>{
|
|||
}
|
||||
|
||||
OpType::Print => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
println!("{a}");
|
||||
// let _ = io::stdout().flush();
|
||||
ti += 1;
|
||||
|
@ -84,159 +90,162 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<(), &'static str>{
|
|||
ti += 1;
|
||||
}
|
||||
OpType::Load8 => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
|
||||
stack.push(mem[a as usize] as u64);
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let byte = mem[a as usize];
|
||||
stack.push(byte as u64);
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Store8 => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let val = stack_pop(&mut stack, &pos)?;
|
||||
let addr = stack_pop(&mut stack, &pos)?;
|
||||
|
||||
mem[b as usize] = a as u8;
|
||||
mem[addr as usize] = (val & 0xFF) as u8;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
// math
|
||||
OpType::Plus => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push(b + a);
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Minus => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push(b - a);
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Equals => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let b = stack_pop(&mut stack)?;
|
||||
stack.push((a == b) as u64);
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push((b == a) as u64);
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Gt => {
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack)?;
|
||||
stack.push((a > b) as u64);
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push((b > a) as u64);
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Lt => {
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack)?;
|
||||
stack.push((a < b) as u64);
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push((b < a) as u64);
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
OpType::Band => {
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push((a & b) as u64);
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
OpType::Bor => {
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push((a | b) as u64);
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
OpType::Shr => {
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack)?;
|
||||
stack.push((a >> b) as u64);
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push((b >> a) as u64);
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
OpType::Shl => {
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack)?;
|
||||
stack.push((a << b) as u64);
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push((b << a) as u64);
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
OpType::Div => {
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack)?;
|
||||
stack.push((a / b) as u64);
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push((b / a) as u64);
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Mul => {
|
||||
let b = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack)?;
|
||||
stack.push((a * b) as u64);
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push((b * a) as u64);
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
|
||||
// blocks
|
||||
OpType::If => {
|
||||
let a = stack_pop(&mut stack)?;
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
if a == 0 {
|
||||
// println!("If({ti}) => t: {:?} j: {}", tokens[token.jmp as usize].typ, token.jmp);
|
||||
ti = (token.jmp) as usize;
|
||||
} else {
|
||||
ti += 1;
|
||||
}
|
||||
},
|
||||
OpType::Else => {
|
||||
ti = token.jmp as usize;
|
||||
// println!("Else({ti}) => t: {:?} j: {}", tokens[token.jmp as usize].typ, 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 => {
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Do => {
|
||||
let a = stack.pop().unwrap();
|
||||
if a == 0 {
|
||||
ti = token.jmp as usize;
|
||||
ti = (token.jmp) as usize;
|
||||
} else {
|
||||
ti += 1;
|
||||
}
|
||||
}
|
||||
OpType::End => {
|
||||
ti = token.jmp as usize;
|
||||
}
|
||||
OpType::Syscall0 => {
|
||||
todo!();
|
||||
ti += 1;
|
||||
// ti += 1;
|
||||
},
|
||||
OpType::Syscall1 => {
|
||||
todo!();
|
||||
ti += 1;
|
||||
// ti += 1;
|
||||
},
|
||||
OpType::Syscall2 => {
|
||||
todo!();
|
||||
ti += 1;
|
||||
// ti += 1;
|
||||
},
|
||||
OpType::Syscall3 => {
|
||||
let rax = stack_pop(&mut stack)?;
|
||||
let rdi = stack_pop(&mut stack)?;
|
||||
let rsi = stack_pop(&mut stack)?;
|
||||
let rdx = stack_pop(&mut stack)?;
|
||||
|
||||
let rax = stack_pop(&mut stack, &pos)?;
|
||||
let rdi = stack_pop(&mut stack, &pos)?;
|
||||
let rsi = stack_pop(&mut stack, &pos)?;
|
||||
let rdx = stack_pop(&mut stack, &pos)?;
|
||||
// println!("yes");
|
||||
let ret = match rax {
|
||||
1 => syscalls::sys_write(rax, rdi, rsi, rdx, &mem),
|
||||
_ => {
|
||||
logger::error(format!("Syscall(3) #{} is not implemented", rax).as_str());
|
||||
return Err("Exiting");
|
||||
return Err(eyre!("Syscall not implemented"));
|
||||
}
|
||||
};
|
||||
stack.push(ret);
|
||||
// println!("{}", stack.len());
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Syscall4 => {
|
||||
todo!();
|
||||
ti += 1;
|
||||
// ti += 1;
|
||||
},
|
||||
OpType::Syscall5 => {
|
||||
todo!();
|
||||
ti += 1;
|
||||
// ti += 1;
|
||||
},
|
||||
OpType::Syscall6 => {
|
||||
todo!();
|
||||
ti += 1;
|
||||
// ti += 1;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,24 @@
|
|||
|
||||
pub fn sys_write(rax: u64, rdi: u64, rsi: u64, rdx: u64, mem: &Vec<u8> ) -> u64 {
|
||||
for c in rsi..rdx {
|
||||
match rdi {
|
||||
1 => print!("{}", unsafe { char::from_u32_unchecked((mem[(rsi + c) as usize]) as u32) }),
|
||||
2 => eprint!("{}", unsafe { char::from_u32_unchecked((mem[(rsi + c) as usize]) as u32) }),
|
||||
_ => panic!("Unknown file {}", rdi)
|
||||
pub fn sys_write(sys_n: u64, fd: u64, buff: u64, count: u64, mem: &Vec<u8> ) -> u64 {
|
||||
let mem = (*mem).clone();
|
||||
let buff = buff as usize;
|
||||
let count = count as usize;
|
||||
// println!("{:?}", &mem[buff..(buff + count)]);
|
||||
// return 0 ;
|
||||
let s = &mem[buff..(buff + count)].iter().map(|i| {
|
||||
char::from_u32((*i) as u32).unwrap_or('_').to_string()
|
||||
}).collect::<Vec<String>>().join("");
|
||||
|
||||
match fd {
|
||||
1 => {
|
||||
print!("{}", s);
|
||||
},
|
||||
2 => {
|
||||
eprint!("{}", s);
|
||||
},
|
||||
_ => panic!("Unknown file {}", fd)
|
||||
};
|
||||
let _ = std::io::Write::flush(&mut std::io::stdout());
|
||||
let _ = std::io::Write::flush(&mut std::io::stderr());
|
||||
}
|
||||
rax
|
||||
sys_n
|
||||
}
|
12
src/lexer.rs
12
src/lexer.rs
|
@ -22,7 +22,14 @@ fn lex_line(text: String) -> Result<Vec<(u32, String)>> {
|
|||
while col_end < text.clone().len() as u32 {
|
||||
col_end = find_col(text.clone(), col, |x| x.is_whitespace())?;
|
||||
let t = &text[(col as usize)..((col_end as usize))];
|
||||
|
||||
if t == "//" {
|
||||
return Ok(tokens);
|
||||
}
|
||||
|
||||
if !t.is_empty() {
|
||||
tokens.push((col, t.to_string()));
|
||||
}
|
||||
col = find_col(text.clone(), col_end, |x| !x.is_whitespace())?;
|
||||
}
|
||||
|
||||
|
@ -31,7 +38,6 @@ fn lex_line(text: String) -> Result<Vec<(u32, String)>> {
|
|||
|
||||
pub fn lex(code: String, file: &String) -> Result<Vec<Token>> {
|
||||
let lines: Vec<(usize, &str)> = code
|
||||
.split("//").collect::<Vec<&str>>()[0]
|
||||
.split(['\n', '\r'])
|
||||
.enumerate()
|
||||
.collect();
|
||||
|
@ -52,6 +58,10 @@ pub fn lex(code: String, file: &String) -> Result<Vec<Token>> {
|
|||
tokens.push(t);
|
||||
}
|
||||
}
|
||||
// println!("{}", tokens.len());
|
||||
|
||||
// for token in tokens.clone() {
|
||||
// println!("tok: {:?}", token.text);
|
||||
// }
|
||||
Ok(tokens)
|
||||
}
|
15
src/main.rs
15
src/main.rs
|
@ -39,28 +39,25 @@ pub struct Args {
|
|||
|
||||
}
|
||||
|
||||
fn main() -> Result<(), ()> {
|
||||
fn main() -> Result<()> {
|
||||
let args = Args::parse();
|
||||
|
||||
|
||||
let code = fs::read_to_string(&args.in_file).unwrap();
|
||||
let tokens = lexer::lex(code, &args.in_file).unwrap();
|
||||
let code = fs::read_to_string(&args.in_file)?;
|
||||
let tokens = lexer::lex(code, &args.in_file)?;
|
||||
|
||||
// for token in &tokens {
|
||||
// println!("(f: {}, l: {}, c: {}, t: {})", token.file, token.line, token.col, token.text);
|
||||
// }
|
||||
|
||||
let mut parser = parser::Parser::new(tokens);
|
||||
let tokens = match parser.parse(){
|
||||
Ok(t) => t,
|
||||
Err(_) => return Ok(())
|
||||
};
|
||||
let tokens = parser.parse()?;
|
||||
if args.compile && args.interpret {
|
||||
util::logger::error("Cannot compile and interpret at the same time");
|
||||
} else if args.interpret {
|
||||
let _ = interpret::linux_x86_64::run(tokens);
|
||||
interpret::linux_x86_64::run(tokens)?;
|
||||
} else if args.compile {
|
||||
let _ = compile::linux_x86_64::compile(tokens, args);
|
||||
compile::linux_x86_64::compile(tokens, args)?;
|
||||
} else {
|
||||
util::logger::error("Did not choose to compile or to interpret, exiting");
|
||||
}
|
||||
|
|
|
@ -1,46 +1,39 @@
|
|||
use crate::{constants::{Operator, OpType, Token}, util};
|
||||
use color_eyre::Result;
|
||||
use eyre::eyre;
|
||||
|
||||
pub fn cross_ref(mut tokens: Vec<Operator>) -> Vec<Operator> {
|
||||
pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||
let mut stack: Vec<u32> = Vec::new();
|
||||
for ip in 0..tokens.len() {
|
||||
let op = &tokens.clone()[ip];
|
||||
for ip in 0..program.len() {
|
||||
let op = &program.clone()[ip];
|
||||
match op.typ {
|
||||
OpType::If => {
|
||||
stack.push(ip as u32)
|
||||
}
|
||||
OpType::Else => {
|
||||
let if_ip = stack.pop().unwrap();
|
||||
let mut if_og = &mut tokens[if_ip as usize];
|
||||
if !vec![OpType::If].contains(&(*if_og).typ) {
|
||||
if program[if_ip as usize].typ != OpType::If {
|
||||
util::logger::pos_error(op.clone().pos,"'end' can only close 'if' blocks");
|
||||
std::process::exit(1); // idc
|
||||
}
|
||||
|
||||
(*if_og).jmp = (ip + 1) as i32;
|
||||
// let mut if_og = &mut tokens[if_ip as usize];
|
||||
// (*if_og).jmp = (ip + 1) as i32;
|
||||
program[if_ip as usize].jmp = (ip + 1) as i32;
|
||||
stack.push(ip as u32);
|
||||
},
|
||||
OpType::End => {
|
||||
let block_ip = stack.pop().unwrap();
|
||||
let mut block_og = &mut tokens[block_ip as usize].clone();
|
||||
if vec![OpType::If, OpType::Else].contains(&(*block_og).typ) {
|
||||
// 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 {
|
||||
|
||||
(*block_og).jmp = ip as i32;
|
||||
tokens[block_ip as usize] = block_og.clone();
|
||||
program[block_ip as usize].jmp = ip as i32;
|
||||
program[ip as usize].jmp = (ip + 1)as i32;
|
||||
|
||||
let do_og = &mut tokens[ip as usize].clone();
|
||||
do_og.jmp = (ip + 1) as i32;
|
||||
|
||||
tokens[ip as usize] = (*do_og).clone();
|
||||
|
||||
} else if (*block_og).typ == OpType::Do {
|
||||
let do_og = &mut tokens[ip as usize];
|
||||
do_og.jmp = block_og.jmp;
|
||||
|
||||
tokens[ip as usize] = (*do_og).clone();
|
||||
let mut block_og = block_og.clone();
|
||||
block_og.jmp = (ip + 1) as i32;
|
||||
tokens[block_ip as usize] = block_og.clone();
|
||||
} else if program[block_ip as usize].typ == OpType::Do {
|
||||
program[ip].jmp = program[block_ip as usize].jmp;
|
||||
program[block_ip as usize].jmp = (ip + 1) as i32;
|
||||
} else {
|
||||
util::logger::pos_error(op.clone().pos,"'end' can only close 'if' blocks");
|
||||
std::process::exit(1); // idc
|
||||
|
@ -52,14 +45,19 @@ pub fn cross_ref(mut tokens: Vec<Operator>) -> Vec<Operator> {
|
|||
}
|
||||
OpType::Do => {
|
||||
let while_ip = stack.pop().unwrap();
|
||||
(&mut tokens[ip as usize]).jmp = while_ip as i32;
|
||||
program[ip as usize].jmp = while_ip as i32;
|
||||
stack.push(ip as u32);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
}
|
||||
tokens.clone()
|
||||
if stack.len() > 0 {
|
||||
util::logger::pos_error(program[stack.pop().expect("Empy stack") as usize].clone().pos,"Unclosed block");
|
||||
return Err(eyre!("Unclosed block"));
|
||||
}
|
||||
|
||||
Ok(program.clone())
|
||||
}
|
||||
|
||||
pub struct Parser {
|
||||
|
@ -73,7 +71,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(&mut self) -> Result<Vec<Operator>, ()> {
|
||||
pub fn parse(&mut self) -> Result<Vec<Operator>> {
|
||||
let mut tokens = Vec::new();
|
||||
|
||||
for token in &self.tokens {
|
||||
|
@ -91,7 +89,7 @@ impl Parser {
|
|||
|
||||
// stack
|
||||
"dup" => tokens.push(Operator::new(OpType::Dup, 0, token.file.clone(), token.line, token.col)),
|
||||
"drop" => tokens.push(Operator::new(OpType::Pop, 0, token.file.clone(), token.line, token.col)),
|
||||
"drop" => tokens.push(Operator::new(OpType::Drop, 0, token.file.clone(), token.line, token.col)),
|
||||
"2dup" => tokens.push(Operator::new(OpType::Dup2, 0, token.file.clone(), token.line, token.col)),
|
||||
"rot" => tokens.push(Operator::new(OpType::Rot, 0, token.file.clone(), token.line, token.col)),
|
||||
"over" => tokens.push(Operator::new(OpType::Over, 0, token.file.clone(), token.line, token.col)),
|
||||
|
@ -108,6 +106,7 @@ impl Parser {
|
|||
"shr" => tokens.push(Operator::new(OpType::Shr, 0, token.file.clone(), token.line, token.col)),
|
||||
"shl" => tokens.push(Operator::new(OpType::Shl, 0, token.file.clone(), token.line, token.col)),
|
||||
"/" => tokens.push(Operator::new(OpType::Div, 0, token.file.clone(), token.line, token.col)),
|
||||
"*" => tokens.push(Operator::new(OpType::Mul, 0, token.file.clone(), token.line, token.col)),
|
||||
|
||||
// block
|
||||
"if" => tokens.push(Operator::new(OpType::If, 0, token.file.clone(), token.line, token.col)),
|
||||
|
@ -134,11 +133,11 @@ impl Parser {
|
|||
|
||||
t => {
|
||||
util::logger::pos_error(pos, format!("Unknown token '{}'", t).as_str());
|
||||
return Err(());
|
||||
return Err(eyre!("Unknown token"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(cross_ref(tokens))
|
||||
Ok(cross_ref(tokens)?)
|
||||
}
|
||||
}
|
19
test.mcl
19
test.mcl
|
@ -1,18 +1 @@
|
|||
|
||||
mem dup 72 @8
|
||||
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
|
||||
|
||||
1 2 3 2dup print print print print print
|
3
test.py
3
test.py
|
@ -1,3 +0,0 @@
|
|||
txt = "TODO: Make this!\n"
|
||||
sp = list(txt)
|
||||
print([ord(x) for x in sp])
|
|
@ -1,6 +0,0 @@
|
|||
//we dont have text yet, its so early stages still
|
||||
//cant it do putchar(getchar())
|
||||
// not yet
|
||||
// ;-; ;-; ;-; ;-; ;-;
|
||||
// ping me on dsc
|
||||
//..., im working on it, rn im gonna make elif i think, you can watch, lemme clean my table gimme 5 mins
|
7
tests/math.mcl
Normal file
7
tests/math.mcl
Normal file
|
@ -0,0 +1,7 @@
|
|||
34 35 + print
|
||||
|
||||
800 380 - print
|
||||
|
||||
10 5 * print
|
||||
|
||||
40 5 / print
|
Loading…
Reference in New Issue
Block a user