implement /example/rule110.mcl and fix interpreting syscalls

This commit is contained in:
MCorange 2023-03-18 18:41:57 +02:00
parent 8a53271a91
commit 8421fbf379
16 changed files with 449 additions and 222 deletions

1
Cargo.lock generated
View File

@ -215,6 +215,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"color-eyre", "color-eyre",
"eyre",
] ]
[[package]] [[package]]

View File

@ -8,3 +8,4 @@ edition = "2021"
[dependencies] [dependencies]
clap = { version = "4.1.8", features = ["derive"] } clap = { version = "4.1.8", features = ["derive"] }
color-eyre = "0.6.2" color-eyre = "0.6.2"
eyre = "0.6.8"

38
examples/rule110.mcl Normal file → Executable file
View 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
View 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(())
}

View File

@ -28,12 +28,12 @@ pub fn linux_x86_64_compile_and_link(of_a: &PathBuf, of_o: &PathBuf, of_c: &Path
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.spawn()? .spawn()?
}; };
if !quiet{ if !quiet {
logger::info(format!("running 'nasm {}'", nasm_args.join(" ")).as_str()); logger::info(format!("running 'nasm {}'", nasm_args.join(" ")).as_str());
} }
let exit = proc.wait()?; let exit = proc.wait()?;
if (!quiet) { if !quiet {
logger::info(format!("nasm process exited with code {}", exit).as_str()); 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()) .stderr(Stdio::inherit())
.spawn()? .spawn()?
}; };
if (!quiet) { if !quiet {
logger::info(format!("running 'ld {}'", ld_args.join(" ")).as_str()); logger::info(format!("running 'ld {}'", ld_args.join(" ")).as_str());
} }
let exit2 = proc2.wait()?; let exit2 = proc2.wait()?;
if (!quiet) { if !quiet {
logger::info(format!("ld process exited with code {}", exit2).as_str()); 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(()) 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") { let mut proc = if cfg!(target_os = "windows") {
return Ok(()); return Ok(());
} else { } else {
Command::new(bin) Command::new(bin)
//.args(&nasm_args) .args(&args)
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.spawn()? .spawn()?
}; };
// println!("{}", quiet);
if (!quiet) { if !quiet {
logger::info(format!("running '{} {}'", bin.to_string_lossy() ,args.join(" ")).as_str()); logger::info(format!("running {} {}", _bin.to_string_lossy(), args.join(" ")).as_str());
} }
let exit = proc.wait()?; let exit = proc.wait()?;
if (!quiet) { if !quiet {
logger::info(format!("{} process exited with code {}", bin.to_string_lossy(), exit).as_str()); logger::info(format!("{} process exited with code {}", _bin.to_string_lossy(), exit).as_str());
} }
Ok(()) Ok(())

View File

@ -18,7 +18,9 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
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);
writeln!(writer, "global _start")?; // println!("{}", tokens.len());
writeln!(writer, "BITS 64")?;
writeln!(writer, "segment .text")?; writeln!(writer, "segment .text")?;
writeln!(writer, "print:")?; writeln!(writer, "print:")?;
@ -54,7 +56,8 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writeln!(writer, " syscall")?; writeln!(writer, " syscall")?;
writeln!(writer, " add rsp, 40")?; writeln!(writer, " add rsp, 40")?;
writeln!(writer, " ret")?; writeln!(writer, " ret")?;
writeln!(writer, "global _start")?;
writeln!(writer, "_start:")?; writeln!(writer, "_start:")?;
let mut ti = 0; let mut ti = 0;
@ -65,26 +68,26 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
match token.typ { match token.typ {
// stack // stack
OpType::Push => { OpType::Push => {
writeln!(writer, " ; -- PUSH {}", token.value)?; writeln!(writer, " ;; -- push {} --", 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::Pop => { OpType::Drop => {
writeln!(writer, " ; -- POP")?; writeln!(writer, " ;; -- drop --")?;
writeln!(writer, " pop")?; writeln!(writer, " pop rax")?;
ti += 1; ti += 1;
}, },
OpType::Print => { OpType::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::Dup => {
writeln!(writer, " ; -- DUP")?; writeln!(writer, " ;; -- dup --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
@ -92,19 +95,19 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
ti += 1; ti += 1;
}, },
OpType::Dup2 => { OpType::Dup2 => {
writeln!(writer, " ; -- DUP2")?; writeln!(writer, " ;; -- 2dup --")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " push rbx")?; writeln!(writer, " pop rax")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
writeln!(writer, " push rbx")?; writeln!(writer, " push rbx")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::Rot => { OpType::Rot => {
writeln!(writer, " ; -- DUP")?; writeln!(writer, " ;; -- rot --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " pop rcx")?; writeln!(writer, " pop rcx")?;
@ -115,16 +118,16 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
ti += 1; ti += 1;
}, },
OpType::Swap => { OpType::Swap => {
writeln!(writer, " ; -- DUP")?; writeln!(writer, " ;; -- swap --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " push rbx")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::Over => { OpType::Over => {
writeln!(writer, " ; -- DUP")?; writeln!(writer, " ;; -- over --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " push rbx")?; writeln!(writer, " push rbx")?;
@ -136,12 +139,12 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
//mem //mem
OpType::Mem => { OpType::Mem => {
writeln!(writer, " ; -- MEM")?; writeln!(writer, " ;; -- mem --")?;
writeln!(writer, " push mem")?; writeln!(writer, " push mem")?;
ti += 1; ti += 1;
} }
OpType::Load8 => { OpType::Load8 => {
writeln!(writer, " ; -- LOAD64")?; writeln!(writer, " ;; -- load --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " xor rbx, rbx")?; writeln!(writer, " xor rbx, rbx")?;
writeln!(writer, " mov bl, [rax]")?; writeln!(writer, " mov bl, [rax]")?;
@ -150,7 +153,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
} }
OpType::Store8 => { OpType::Store8 => {
writeln!(writer, " ; -- STORE64")?; writeln!(writer, " ;; -- store --")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " mov [rax], bl")?; writeln!(writer, " mov [rax], bl")?;
@ -159,7 +162,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
// math // math
OpType::Plus => { OpType::Plus => {
writeln!(writer, " ; -- PLUS")?; writeln!(writer, " ;; -- plus --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " add rax, rbx")?; writeln!(writer, " add rax, rbx")?;
@ -167,7 +170,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
ti += 1; ti += 1;
}, },
OpType::Minus => { OpType::Minus => {
writeln!(writer, " ; -- MINUS")?; writeln!(writer, " ;; -- minus --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " sub rbx, rax")?; writeln!(writer, " sub rbx, rax")?;
@ -175,7 +178,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
ti += 1; ti += 1;
}, },
OpType::Equals => { OpType::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")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
@ -187,7 +190,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
}, },
OpType::Lt => { OpType::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")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -199,7 +202,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
}, },
OpType::Gt => { OpType::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")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
@ -211,49 +214,49 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
}, },
OpType::Band => { OpType::Band => {
writeln!(writer, " ; -- BAND")?; writeln!(writer, " ;; -- band --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " and rax, rbx")?; writeln!(writer, " and rbx, rax")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::Bor => { OpType::Bor => {
writeln!(writer, " ; -- BOR")?; writeln!(writer, " ;; -- bor --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " or rax, rbx")?; writeln!(writer, " or rbx, rax")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::Shr => { OpType::Shr => {
writeln!(writer, " ; -- SHR")?; writeln!(writer, " ;; -- shr --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rcx")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " shr rax, rbx")?; writeln!(writer, " shr rbx, cl")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::Shl => { OpType::Shl => {
writeln!(writer, " ; -- SHL")?; writeln!(writer, " ;; -- shl --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rcx")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " shl rax, rbx")?; writeln!(writer, " shl rbx, cl")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::Div => { OpType::Div => {
writeln!(writer, " ; -- DIV")?; writeln!(writer, " ;; -- div --")?;
writeln!(writer, " xor rdx, rdx")?; writeln!(writer, " xor rdx, rdx")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " div rbx")?; writeln!(writer, " div rbx")?;
writeln!(writer, " push rax")?; writeln!(writer, " push rax")?;
//writeln!(writer, " push rdx")?; //writeln!(writer, " push rdx")?;
ti += 1; ti += 1;
}, },
OpType::Mul => { OpType::Mul => {
writeln!(writer, " ; -- MUL")?; writeln!(writer, " ;; -- mul --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " mul rbx")?; writeln!(writer, " mul rbx")?;
@ -265,42 +268,44 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
// block // block
OpType::If => { OpType::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::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::While => {
writeln!(writer, " ; -- WHILE")?; writeln!(writer, " ;; -- while --")?;
ti += 1; ti += 1;
} }
OpType::Do => { OpType::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::End => {
writeln!(writer, " ; -- END")?; writeln!(writer, " ;; -- end --")?;
writeln!(writer, " jmp addr_{}", token.jmp)?; if ti + 1 != token.jmp as usize {
writeln!(writer, " jmp addr_{}", token.jmp)?;
}
ti += 1; ti += 1;
}, },
OpType::Syscall0 => { OpType::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::Syscall1 => {
writeln!(writer, " ; -- SYSCALL1")?; writeln!(writer, " ;; -- syscall1 --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
writeln!(writer, " syscall")?; writeln!(writer, " syscall")?;
@ -308,7 +313,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
ti += 1; ti += 1;
}, },
OpType::Syscall2 => { OpType::Syscall2 => {
writeln!(writer, " ; -- SYSCALL2")?; writeln!(writer, " ;; -- syscall2 --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?; writeln!(writer, " pop rsi")?;
@ -317,7 +322,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
ti += 1; ti += 1;
}, },
OpType::Syscall3 => { OpType::Syscall3 => {
writeln!(writer, " ; -- SYSCALL3")?; writeln!(writer, " ;; -- syscall3 --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?; writeln!(writer, " pop rsi")?;
@ -328,7 +333,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
ti += 1; ti += 1;
}, },
OpType::Syscall4 => { OpType::Syscall4 => {
writeln!(writer, " ; -- SYSCALL4")?; writeln!(writer, " ;; -- syscall4 --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?; writeln!(writer, " pop rsi")?;
@ -339,7 +344,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
ti += 1; ti += 1;
}, },
OpType::Syscall5 => { OpType::Syscall5 => {
writeln!(writer, " ; -- SYSCALL5")?; writeln!(writer, " ;; -- syscall5 --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?; writeln!(writer, " pop rsi")?;
@ -351,7 +356,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
ti += 1; ti += 1;
}, },
OpType::Syscall6 => { OpType::Syscall6 => {
writeln!(writer, " ; -- SYSCALL6")?; writeln!(writer, " ;; -- syscall6 --")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?; writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?; writeln!(writer, " pop rsi")?;
@ -371,7 +376,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writeln!(writer, " syscall")?; writeln!(writer, " syscall")?;
writeln!(writer, "segment .bss")?; writeln!(writer, "segment .bss")?;
writeln!(writer, " mem: resb {}", crate::compile::MEM_SZ)?; writeln!(writer, "mem: resb {}", crate::compile::MEM_SZ)?;
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)?;

View File

@ -4,7 +4,7 @@ pub enum OpType {
// stack // stack
Push, Push,
Pop, Drop,
Print, Print,
Dup, Dup,
Dup2, // a b => a b a b Dup2, // a b => a b a b
@ -70,7 +70,7 @@ impl Operator {
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Token { pub struct Token {
pub file: String, pub file: String,
pub line: u32, pub line: u32,

View File

@ -1,45 +1,51 @@
use std::fmt::format; use crate::{constants::OpType, util::{logger, self}};
use crate::{constants::OpType, util::logger};
// use crate::util::logger; // use crate::util::logger;
use color_eyre::Result; use color_eyre::Result;
use eyre::eyre;
mod syscalls; 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() { match stack.pop() {
Some(i) => Ok(i), 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 stack: Vec<u64> = Vec::new();
let mut ti = 0; let mut ti = 0;
let mut mem: Vec<u8> = vec![0; crate::compile::MEM_SZ as usize]; 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() { while ti < tokens.len() {
let token = &tokens[ti]; let token = &tokens[ti];
let pos = token.pos.clone();
// println!("{:?}", token.typ);
match token.typ { match token.typ {
// stack // stack
OpType::Push => { OpType::Push => {
stack.push(token.value as u64); stack.push(token.value as u64);
ti += 1; ti += 1;
}, },
OpType::Pop => { OpType::Drop => {
stack.pop(); stack.pop();
ti += 1; ti += 1;
}, },
OpType::Dup => { OpType::Dup => {
let a = stack_pop(&mut stack)?; 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 => { OpType::Dup2 => {
let a = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push(b); stack.push(b);
stack.push(a); stack.push(a);
stack.push(b); stack.push(b);
@ -47,24 +53,24 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<(), &'static str>{
ti += 1; ti += 1;
} }
OpType::Rot => { OpType::Rot => {
let a = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
let c = stack_pop(&mut stack)?; let c = stack_pop(&mut stack, &pos)?;
stack.push(b); stack.push(b);
stack.push(a); stack.push(a);
stack.push(c); stack.push(c);
ti += 1; ti += 1;
} }
OpType::Swap => { OpType::Swap => {
let a = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push(b);
stack.push(a); stack.push(a);
stack.push(b);
ti += 1; ti += 1;
} }
OpType::Over => { OpType::Over => {
let a = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push(b); stack.push(b);
stack.push(a); stack.push(a);
stack.push(b); stack.push(b);
@ -72,7 +78,7 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<(), &'static str>{
} }
OpType::Print => { OpType::Print => {
let a = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
println!("{a}"); println!("{a}");
// let _ = io::stdout().flush(); // let _ = io::stdout().flush();
ti += 1; ti += 1;
@ -84,159 +90,162 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<(), &'static str>{
ti += 1; ti += 1;
} }
OpType::Load8 => { OpType::Load8 => {
let a = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let byte = mem[a as usize];
stack.push(mem[a as usize] as u64); stack.push(byte as u64);
ti += 1; ti += 1;
} }
OpType::Store8 => { OpType::Store8 => {
let a = stack_pop(&mut stack)?; let val = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack)?; let addr = stack_pop(&mut stack, &pos)?;
mem[b as usize] = a as u8; mem[addr as usize] = (val & 0xFF) as u8;
ti += 1; ti += 1;
} }
// math // math
OpType::Plus => { OpType::Plus => {
let a = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push(b + a); stack.push(b + a);
ti += 1; ti += 1;
}, },
OpType::Minus => { OpType::Minus => {
let a = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push(b - a); stack.push(b - a);
ti += 1; ti += 1;
}, },
OpType::Equals => { OpType::Equals => {
let a = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((a == b) as u64); stack.push((b == a) as u64);
ti += 1; ti += 1;
}, },
OpType::Gt => { OpType::Gt => {
let b = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let a = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((a > b) as u64); stack.push((b > a) as u64);
ti += 1; ti += 1;
}, },
OpType::Lt => { OpType::Lt => {
let b = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let a = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((a < b) as u64); stack.push((b < a) as u64);
ti += 1; ti += 1;
}, },
OpType::Band => { OpType::Band => {
let b = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let a = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((a & b) as u64); stack.push((a & b) as u64);
ti += 1; ti += 1;
} }
OpType::Bor => { OpType::Bor => {
let b = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let a = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((a | b) as u64); stack.push((a | b) as u64);
ti += 1; ti += 1;
} }
OpType::Shr => { OpType::Shr => {
let b = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let a = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((a >> b) as u64); stack.push((b >> a) as u64);
ti += 1; ti += 1;
} }
OpType::Shl => { OpType::Shl => {
let b = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let a = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((a << b) as u64); stack.push((b << a) as u64);
ti += 1; ti += 1;
} }
OpType::Div => { OpType::Div => {
let b = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let a = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((a / b) as u64); stack.push((b / a) as u64);
ti += 1; ti += 1;
} }
OpType::Mul => { OpType::Mul => {
let b = stack_pop(&mut stack)?; let a = stack_pop(&mut stack, &pos)?;
let a = stack_pop(&mut stack)?; let b = stack_pop(&mut stack, &pos)?;
stack.push((a * b) as u64); stack.push((b * a) as u64);
ti += 1; ti += 1;
} }
// blocks // blocks
OpType::If => { OpType::If => {
let a = stack_pop(&mut stack)?; 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);
ti = (token.jmp) as usize; ti = (token.jmp) as usize;
} else { } else {
ti += 1; ti += 1;
} }
}, },
OpType::Else => { 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 => { OpType::While => {
ti += 1; ti += 1;
} }
OpType::Do => { OpType::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) as usize;
} else { } else {
ti += 1; ti += 1;
} }
} }
OpType::End => {
ti = token.jmp as usize;
}
OpType::Syscall0 => { OpType::Syscall0 => {
todo!(); todo!();
ti += 1; // ti += 1;
}, },
OpType::Syscall1 => { OpType::Syscall1 => {
todo!(); todo!();
ti += 1; // ti += 1;
}, },
OpType::Syscall2 => { OpType::Syscall2 => {
todo!(); todo!();
ti += 1; // ti += 1;
}, },
OpType::Syscall3 => { OpType::Syscall3 => {
let rax = stack_pop(&mut stack)?; let rax = stack_pop(&mut stack, &pos)?;
let rdi = stack_pop(&mut stack)?; let rdi = stack_pop(&mut stack, &pos)?;
let rsi = stack_pop(&mut stack)?; let rsi = stack_pop(&mut stack, &pos)?;
let rdx = stack_pop(&mut stack)?; let rdx = stack_pop(&mut stack, &pos)?;
// 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),
_ => { _ => {
logger::error(format!("Syscall(3) #{} is not implemented", rax).as_str()); logger::error(format!("Syscall(3) #{} is not implemented", rax).as_str());
return Err("Exiting"); return Err(eyre!("Syscall not implemented"));
} }
}; };
stack.push(ret); stack.push(ret);
// println!("{}", stack.len());
ti += 1; ti += 1;
}, },
OpType::Syscall4 => { OpType::Syscall4 => {
todo!(); todo!();
ti += 1; // ti += 1;
}, },
OpType::Syscall5 => { OpType::Syscall5 => {
todo!(); todo!();
ti += 1; // ti += 1;
}, },
OpType::Syscall6 => { OpType::Syscall6 => {
todo!(); todo!();
ti += 1; // ti += 1;
}, },
} }
} }

View File

@ -1,13 +1,24 @@
pub fn sys_write(rax: u64, rdi: u64, rsi: u64, rdx: u64, mem: &Vec<u8> ) -> u64 { pub fn sys_write(sys_n: u64, fd: u64, buff: u64, count: u64, mem: &Vec<u8> ) -> u64 {
for c in rsi..rdx { let mem = (*mem).clone();
match rdi { let buff = buff as usize;
1 => print!("{}", unsafe { char::from_u32_unchecked((mem[(rsi + c) as usize]) as u32) }), let count = count as usize;
2 => eprint!("{}", unsafe { char::from_u32_unchecked((mem[(rsi + c) as usize]) as u32) }), // println!("{:?}", &mem[buff..(buff + count)]);
_ => panic!("Unknown file {}", rdi) // return 0 ;
}; let s = &mem[buff..(buff + count)].iter().map(|i| {
let _ = std::io::Write::flush(&mut std::io::stdout()); char::from_u32((*i) as u32).unwrap_or('_').to_string()
let _ = std::io::Write::flush(&mut std::io::stderr()); }).collect::<Vec<String>>().join("");
}
rax 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());
sys_n
} }

View File

@ -22,7 +22,14 @@ fn lex_line(text: String) -> Result<Vec<(u32, String)>> {
while col_end < text.clone().len() as u32 { while col_end < text.clone().len() as u32 {
col_end = find_col(text.clone(), col, |x| x.is_whitespace())?; col_end = find_col(text.clone(), col, |x| x.is_whitespace())?;
let t = &text[(col as usize)..((col_end as usize))]; let t = &text[(col as usize)..((col_end as usize))];
tokens.push((col, t.to_string()));
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())?; 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>> { pub fn lex(code: String, file: &String) -> Result<Vec<Token>> {
let lines: Vec<(usize, &str)> = code let lines: Vec<(usize, &str)> = code
.split("//").collect::<Vec<&str>>()[0]
.split(['\n', '\r']) .split(['\n', '\r'])
.enumerate() .enumerate()
.collect(); .collect();
@ -52,6 +58,10 @@ pub fn lex(code: String, file: &String) -> Result<Vec<Token>> {
tokens.push(t); tokens.push(t);
} }
} }
// println!("{}", tokens.len());
// for token in tokens.clone() {
// println!("tok: {:?}", token.text);
// }
Ok(tokens) Ok(tokens)
} }

View File

@ -39,28 +39,25 @@ pub struct Args {
} }
fn main() -> Result<(), ()> { fn main() -> Result<()> {
let args = Args::parse(); let args = Args::parse();
let code = fs::read_to_string(&args.in_file).unwrap(); let code = fs::read_to_string(&args.in_file)?;
let tokens = lexer::lex(code, &args.in_file).unwrap(); let tokens = lexer::lex(code, &args.in_file)?;
// for token in &tokens { // for token in &tokens {
// println!("(f: {}, l: {}, c: {}, t: {})", token.file, token.line, token.col, token.text); // println!("(f: {}, l: {}, c: {}, t: {})", token.file, token.line, token.col, token.text);
// } // }
let mut parser = parser::Parser::new(tokens); let mut parser = parser::Parser::new(tokens);
let tokens = match parser.parse(){ let tokens = parser.parse()?;
Ok(t) => t,
Err(_) => return Ok(())
};
if args.compile && args.interpret { if args.compile && args.interpret {
util::logger::error("Cannot compile and interpret at the same time"); util::logger::error("Cannot compile and interpret at the same time");
} else if args.interpret { } else if args.interpret {
let _ = interpret::linux_x86_64::run(tokens); interpret::linux_x86_64::run(tokens)?;
} else if args.compile { } else if args.compile {
let _ = compile::linux_x86_64::compile(tokens, args); compile::linux_x86_64::compile(tokens, args)?;
} else { } else {
util::logger::error("Did not choose to compile or to interpret, exiting"); util::logger::error("Did not choose to compile or to interpret, exiting");
} }

View File

@ -1,46 +1,39 @@
use crate::{constants::{Operator, OpType, Token}, util}; use crate::{constants::{Operator, OpType, Token}, util};
use color_eyre::Result; 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(); let mut stack: Vec<u32> = Vec::new();
for ip in 0..tokens.len() { for ip in 0..program.len() {
let op = &tokens.clone()[ip]; let op = &program.clone()[ip];
match op.typ { match op.typ {
OpType::If => { OpType::If => {
stack.push(ip as u32) stack.push(ip as u32)
} }
OpType::Else => { OpType::Else => {
let if_ip = stack.pop().unwrap(); let if_ip = stack.pop().unwrap();
let mut if_og = &mut tokens[if_ip as usize]; if program[if_ip as usize].typ != OpType::If {
if !vec![OpType::If].contains(&(*if_og).typ) {
util::logger::pos_error(op.clone().pos,"'end' can only close 'if' blocks"); util::logger::pos_error(op.clone().pos,"'end' can only close 'if' blocks");
std::process::exit(1); // idc 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); stack.push(ip as u32);
}, },
OpType::End => { OpType::End => {
let block_ip = stack.pop().unwrap(); let block_ip = stack.pop().unwrap();
let mut block_og = &mut tokens[block_ip as usize].clone(); // let mut block_og = &mut tokens[block_ip as usize].clone();
if vec![OpType::If, OpType::Else].contains(&(*block_og).typ) { if program[block_ip as usize].typ == OpType::If ||
program[block_ip as usize].typ == OpType::Else {
(*block_og).jmp = ip as i32; program[block_ip as usize].jmp = ip as i32;
tokens[block_ip as usize] = block_og.clone(); program[ip as usize].jmp = (ip + 1)as i32;
let do_og = &mut tokens[ip as usize].clone(); } else if program[block_ip as usize].typ == OpType::Do {
do_og.jmp = (ip + 1) as i32; program[ip].jmp = program[block_ip as usize].jmp;
program[block_ip as usize].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 { } else {
util::logger::pos_error(op.clone().pos,"'end' can only close 'if' blocks"); util::logger::pos_error(op.clone().pos,"'end' can only close 'if' blocks");
std::process::exit(1); // idc std::process::exit(1); // idc
@ -52,14 +45,19 @@ pub fn cross_ref(mut tokens: Vec<Operator>) -> Vec<Operator> {
} }
OpType::Do => { OpType::Do => {
let while_ip = stack.pop().unwrap(); 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); 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 { 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(); let mut tokens = Vec::new();
for token in &self.tokens { for token in &self.tokens {
@ -91,7 +89,7 @@ impl Parser {
// stack // stack
"dup" => tokens.push(Operator::new(OpType::Dup, 0, token.file.clone(), token.line, token.col)), "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)), "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)), "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)), "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)), "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)), "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::Div, 0, token.file.clone(), token.line, token.col)),
"*" => tokens.push(Operator::new(OpType::Mul, 0, token.file.clone(), token.line, token.col)),
// block // block
"if" => tokens.push(Operator::new(OpType::If, 0, token.file.clone(), token.line, token.col)), "if" => tokens.push(Operator::new(OpType::If, 0, token.file.clone(), token.line, token.col)),
@ -134,11 +133,11 @@ impl Parser {
t => { t => {
util::logger::pos_error(pos, format!("Unknown token '{}'", t).as_str()); 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)?)
} }
} }

View File

@ -1,18 +1 @@
1 2 3 2dup print print print print print
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

View File

@ -1,3 +0,0 @@
txt = "TODO: Make this!\n"
sp = list(txt)
print([ord(x) for x in sp])

View File

@ -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
View File

@ -0,0 +1,7 @@
34 35 + print
800 380 - print
10 5 * print
40 5 / print