NOT WORKING initial

This commit is contained in:
MCorange
2023-03-12 22:51:21 +02:00
commit cfcea89dac
19 changed files with 1029 additions and 0 deletions

54
src/compile/commands.rs Normal file
View File

@@ -0,0 +1,54 @@
use std::path::PathBuf;
use std::process::{Command, Stdio};
use color_eyre::Result;
use crate::compile::logger;
pub fn linux_x86_64_compile_and_link(of_a: PathBuf, of_o: PathBuf, of_c: PathBuf) -> Result<()> {
let nasm_args = [
"-felf64",
of_a.to_str().unwrap(),
"-o",
of_o.to_str().unwrap()
];
let ld_args = [
of_o.to_str().unwrap(),
"-o",
of_c.to_str().unwrap()
];
let mut proc = if cfg!(target_os = "windows") {
todo!("Windows compiling");
} else {
Command::new("nasm")
.args(&nasm_args)
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn()?
};
logger::info(format!("running 'nasm {}'", nasm_args.join(" ")).as_str());
let exit = proc.wait()?;
logger::info(format!("nasm process exited with code {}", exit).as_str());
let mut proc2 = if cfg!(target_os = "windows") {
todo!("Windows compiling");
} else {
Command::new("ld")
.args(&ld_args)
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn()?
};
logger::info(format!("running 'ld {}'", ld_args.join(" ")).as_str());
let exit2 = proc2.wait()?;
logger::info(format!("ld process exited with code {}", exit2).as_str());
Ok(())
}

View File

@@ -0,0 +1,98 @@
use std::{fs, path::PathBuf, io::{Write, BufWriter}};
use crate::{constants::{Operator, OpType}, Args};
use color_eyre::Result;
use crate::compile::commands;
use super::commands::linux_x86_64_compile_and_link;
pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
let mut of_c = PathBuf::from(&args.out_file);
let mut of_o = PathBuf::from(&args.out_file);
let mut of_a = PathBuf::from(&args.out_file);
of_c.set_extension("");
of_o.set_extension("o");
of_a.set_extension("nasm");
let file = fs::File::create(&of_a)?;
let mut writer = BufWriter::new(&file);
writeln!(writer, "global _start")?;
writeln!(writer, "segment .text")?;
writeln!(writer, " print:")?;
writeln!(writer, " mov r8, -3689348814741910323")?;
writeln!(writer, " sub rsp, 40")?;
writeln!(writer, " mov BYTE [rsp+32], 10")?;
writeln!(writer, " lea rcx, [rsp+31]")?;
writeln!(writer, ".L2:")?;
writeln!(writer, " mov rax, rdi")?;
writeln!(writer, " mul r8")?;
writeln!(writer, " mov rax, rdi")?;
writeln!(writer, " shr rdx, 3")?;
writeln!(writer, " lea rsi, [rdx+rdx*4]")?;
writeln!(writer, " add rsi, rsi")?;
writeln!(writer, " sub rax, rsi")?;
writeln!(writer, " add eax, 48")?;
writeln!(writer, " mov BYTE [rcx], al")?;
writeln!(writer, " mov rax, rdi")?;
writeln!(writer, " mov rdi, rdx")?;
writeln!(writer, " mov rdx, rcx")?;
writeln!(writer, " sub rcx, 1")?;
writeln!(writer, " cmp rax, 9")?;
writeln!(writer, " ja .L2")?;
writeln!(writer, " lea rcx, [rsp+32]")?;
writeln!(writer, " lea rax, [rsp+32]")?;
writeln!(writer, " mov edi, 1")?;
writeln!(writer, " sub rax, rdx")?;
writeln!(writer, " sub rdx, rcx")?;
writeln!(writer, " lea rsi, [rsp+32+rdx]")?;
writeln!(writer, " mov rdx, rax")?;
writeln!(writer, " mov rax, 1")?;
writeln!(writer, " syscall")?;
writeln!(writer, " add rsp, 40")?;
writeln!(writer, " ret")?;
writeln!(writer, "_start:")?;
for token in tokens {
match token.typ {
OpType::Push => {
writeln!(writer, " ; -- PUSH {}", token.value)?;
writeln!(writer, " mov rax, {}", token.value)?;
writeln!(writer, " push rax")?;
},
OpType::Pop => {
writeln!(writer, " ; -- POP")?;
writeln!(writer, " pop")?;
},
OpType::Plus => {
writeln!(writer, " ; -- PLUS")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?;
writeln!(writer, " add rax, rbx")?;
writeln!(writer, " push rax")?;
},
OpType::Minus => {
writeln!(writer, " ; -- MINUS")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?;
writeln!(writer, " sub rbx, rax")?;
writeln!(writer, " push rax")?;
},
OpType::Print => {
writeln!(writer, " ; -- PRINT")?;
writeln!(writer, " pop rdi")?;
writeln!(writer, " call print")?;
},
}
}
writeln!(writer, " mov rax, 60")?;
writeln!(writer, " mov rdi, 0")?;
writeln!(writer, " syscall")?;
writer.flush()?;
linux_x86_64_compile_and_link(of_a, of_o, of_c)?;
Ok(())
}

9
src/compile/logger.rs Normal file
View File

@@ -0,0 +1,9 @@
use crate::util::color;
pub fn error(msg: &str) {
eprintln!("{red}error{r}: {msg}", red=color::FG_RED, r=color::RESET);
}
pub fn info(msg: &str) {
println!("{green}info{r}: {msg}", green=color::FG_GREEN, r=color::RESET);
}

4
src/compile/mod.rs Normal file
View File

@@ -0,0 +1,4 @@
pub mod linux_x86_64;
pub mod commands;
pub mod logger;

32
src/constants.rs Normal file
View File

@@ -0,0 +1,32 @@
#[derive(Debug)]
pub enum OpType {
Push,
Pop,
Minus,
Plus,
Print
}
#[derive(Debug)]
pub struct Operator {
pub typ: OpType,
pub value: i32,
}
impl Operator {
pub fn new(typ: OpType, value: i32) -> Self {
Self {
typ,
value
}
}
}
pub struct Token {
file: String,
line: u32,
col: u32,
text: String
}

View File

@@ -0,0 +1,42 @@
use crate::constants::OpType;
use crate::interpret::logger;
use std::io::{self, Write};
use color_eyre::Result;
fn stack_pop(mut stack: &mut Vec<i32>) -> Result<i32, &'static str> {
match stack.pop() {
Some(i) => Ok(i),
None => Err("Stack underflow"),
}
}
pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<(), &'static str>{
let mut stack: Vec<i32> = Vec::new();
for token in tokens {
match token.typ {
OpType::Push => {
stack.push(token.value);
},
OpType::Pop => {
stack.pop();
},
OpType::Plus => {
let a = stack_pop(&mut stack)?;
let b = stack_pop(&mut stack)?;
stack.push(b + a);
},
OpType::Minus => {
let a = stack_pop(&mut stack)?;
let b = stack_pop(&mut stack)?;
stack.push(b - a);
},
OpType::Print => {
let a = stack_pop(&mut stack)?;
println!("{a}");
// let _ = io::stdout().flush();
},
}
}
Ok(())
}

5
src/interpret/logger.rs Normal file
View File

@@ -0,0 +1,5 @@
use crate::util::color;
pub fn error(msg: &str) {
println!("{red}error{r}: {msg}", red=color::FG_RED, r=color::RESET);
}

2
src/interpret/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod linux_x86_64;
mod logger;

28
src/lexer.rs Normal file
View File

@@ -0,0 +1,28 @@
use crate::constants::Token;
use color_eyre::Result;
use crate::util::StringExtra;
pub fn strip_col(text: String, mut col: u32) -> Result<u32> {
while (col as usize) < text.len() && text.chars().nth(col as usize).unwrap().is_whitespace() {
col += 1;
}
Ok(32)
}
pub fn lex(code: String) -> Result<Vec<Token>> {
let lines: Vec<(usize, &str)> = code.split(['\n', '\r']).enumerate().collect();
let lines: Vec<(u32, String)> = lines.iter().map(|i| (i.0 as u32, i.1.to_string())).collect();
let mut tokens: Vec<Token> = Vec::new();
let mut col = strip_col(code, 0)?;
for line in lines {
let col_end = code.find_idx(' ', col);
col = strip_col(code, 0)?;
}
Ok(tokens)
}

62
src/main.rs Normal file
View File

@@ -0,0 +1,62 @@
mod constants;
mod interpret;
mod util;
mod compile;
mod parser;
mod lexer;
use std::fs;
use color_eyre::Result;
use clap::Parser;
#[derive(Parser, Debug, Clone)]
#[command(author, version, about, long_about = None)]
pub struct Args {
/// Input source file
#[arg(long, short)]
in_file: String,
/// Output compiled file
#[arg(long, short, default_value_t=String::from("a.out"))]
out_file: String,
/// Compile
#[arg(long, short)]
compile: bool,
/// Interpert
#[arg(long, short='s')]
interpret: bool
}
use constants::{
OpType,
Operator
};
fn main() -> Result<(), &'static str> {
let args = Args::parse();
println!("MClang2 0.0.1");
let code = fs::read_to_string(&args.in_file).unwrap();
let tokens = lexer::lex(code);
dbg!(tokens);
return Ok(());
let mut parser = parser::Parser::new(code.clone());
let tokens = parser.parse()?;
if args.compile && args.interpret {
util::logger::error("Cannot compile and interpret at the same time");
} else if args.interpret {
interpret::linux_x86_64::run(tokens)?;
} else if args.compile {
if let Err(e) = compile::linux_x86_64::compile(tokens, args) {
println!("{}", e);
}
} else {
util::logger::error("Did not choose to compile or to interpret, exiting");
}
Ok(())
}

46
src/parser.rs Normal file
View File

@@ -0,0 +1,46 @@
use crate::{constants::{Operator, OpType}, util};
use color_eyre::{Result, Report};
pub struct Parser {
file: String
}
impl Parser {
pub fn new(file: String) -> Self {
Self{
file
}
}
pub fn parse(&mut self) -> Result<Vec<Operator>, &'static str> {
let mut tokens = Vec::new();
for tok in self.file.split([' ', '\n', '\t', '\r']) {
if tok == "" {
continue;
}
match tok {
t if t.parse::<i32>().is_ok() => {
let num = t.parse::<i32>().unwrap();
tokens.push(Operator::new(OpType::Push, num));
},
"pop" => tokens.push(Operator::new(OpType::Pop, 0)),
"+" => tokens.push(Operator::new(OpType::Plus, 0)),
"-" => tokens.push(Operator::new(OpType::Minus, 0)),
"print" => tokens.push(Operator::new(OpType::Print, 0)),
t => {
util::logger::error("Unknown token '{t}'");
return Err("");
}
}
}
dbg!(&tokens);
Ok(tokens)
}
}

53
src/util.rs Normal file
View File

@@ -0,0 +1,53 @@
pub mod color {
#[allow(dead_code)] pub const NONE: &str = "\x1b[0m";
#[allow(dead_code)] pub const RESET: &str = "\x1b[0m";
#[allow(dead_code)] pub const BRIGHT: &str = "\x1b[1m";
#[allow(dead_code)] pub const DIM: &str = "\x1b[2m";
#[allow(dead_code)] pub const UNDERSCORE: &str = "\x1b[4m";
#[allow(dead_code)] pub const BLINK: &str = "\x1b[5m";
#[allow(dead_code)] pub const REVERSE: &str = "\x1b[7m";
#[allow(dead_code)] pub const HIDDEN: &str = "\x1b[8m";
#[allow(dead_code)] pub const FG_BLACK: &str = "\x1b[30m";
#[allow(dead_code)] pub const FG_RED: &str = "\x1b[31m";
#[allow(dead_code)] pub const FG_GREEN: &str = "\x1b[32m";
#[allow(dead_code)] pub const FG_YELLOW: &str = "\x1b[33m";
#[allow(dead_code)] pub const FG_BLUE: &str = "\x1b[34m";
#[allow(dead_code)] pub const FG_MAGENTA: &str = "\x1b[35m";
#[allow(dead_code)] pub const FG_CYAN: &str = "\x1b[36m";
#[allow(dead_code)] pub const FG_WHITE: &str = "\x1b[37m";
#[allow(dead_code)] pub const BG_BLACK: &str = "\x1b[40m";
#[allow(dead_code)] pub const BG_RED: &str = "\x1b[41m";
#[allow(dead_code)] pub const BG_GREEN: &str = "\x1b[42m";
#[allow(dead_code)] pub const BG_YELLOW: &str = "\x1b[43m";
#[allow(dead_code)] pub const BG_BLUE: &str = "\x1b[44m";
#[allow(dead_code)] pub const BG_MAGENTA: &str = "\x1b[45m";
#[allow(dead_code)] pub const BG_CYAN: &str = "\x1b[46m";
#[allow(dead_code)] pub const BG_WHITE: &str = "\x1b[47m";
}
pub mod logger {
use crate::util::color;
pub fn error(msg: &str) {
println!("{red}error{r}: {msg}", red=color::FG_RED, r=color::RESET);
}
}
pub trait StringExtra{
fn find_idx(&self, pat: char, start: u32) -> u32;
}
impl StringExtra for String {
fn find_idx(&self, pat: char, start: u32) -> u32 {
let mut col = start;
for c in self.chars() {
if c == pat {
break;
}
col += 1;
}
col
}
}