added including of files

This commit is contained in:
MCorange 2023-03-20 14:36:38 +02:00
parent 30214808e5
commit 2d5e94608c
8 changed files with 127 additions and 57 deletions

View File

@ -17,7 +17,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
let of_a = PathBuf::from(&args.out_file);
(of_o, of_a)
};
of_c.set_extension("");
of_o.set_extension("o");
of_a.set_extension("nasm");
@ -30,7 +30,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writeln!(writer, "BITS 64")?;
writeln!(writer, "segment .text")?;
writeln!(writer, "print:")?;
writeln!(writer, " mov r9, -3689348814741910323")?;
writeln!(writer, " sub rsp, 40")?;
@ -64,14 +64,14 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writeln!(writer, " syscall")?;
writeln!(writer, " add rsp, 40")?;
writeln!(writer, " ret")?;
writeln!(writer, "global _start")?;
writeln!(writer, "_start:")?;
let mut ti = 0;
while ti < tokens.len() {
let token = &tokens[ti];
writeln!(writer, "addr_{}:", ti)?;
match token.typ {
// stack
@ -106,7 +106,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writeln!(writer, " pop rax")?;
writeln!(writer, " push rax")?;
writeln!(writer, " push rax")?;
ti += 1;
},
OpType::Dup2 => {
@ -117,7 +117,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writeln!(writer, " push rbx")?;
writeln!(writer, " push rax")?;
writeln!(writer, " push rbx")?;
ti += 1;
},
@ -129,7 +129,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writeln!(writer, " push rbx")?;
writeln!(writer, " push rax")?;
writeln!(writer, " push rcx")?;
ti += 1;
},
OpType::Swap => {
@ -138,7 +138,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writeln!(writer, " pop rbx")?;
writeln!(writer, " push rax")?;
writeln!(writer, " push rbx")?;
ti += 1;
},
OpType::Over => {
@ -148,7 +148,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writeln!(writer, " push rbx")?;
writeln!(writer, " push rax")?;
writeln!(writer, " push rbx")?;
ti += 1;
},
@ -279,7 +279,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
//writeln!(writer, " push rdx")?;
ti += 1;
},
// block
OpType::If => {
@ -312,10 +312,6 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
}
ti += 1;
},
OpType::Macro => {
panic!();
}
OpType::Syscall0 => {
writeln!(writer, " ;; -- syscall0")?;
writeln!(writer, " pop rax")?;
@ -348,7 +344,7 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writeln!(writer, " pop rdx")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
},
OpType::Syscall4 => {
@ -387,7 +383,9 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writeln!(writer, " push rax")?;
ti += 1;
},
OpType::None => unreachable!()
OpType::None => unreachable!(),
OpType::Macro => unreachable!(),
OpType::Include => unreachable!()
}
}
writeln!(writer, "addr_{}:", ti)?;

View File

@ -1,4 +1,7 @@
pub const ALLOW_MACRO_REDEFINITION: bool = true;
#[derive(Debug, Clone, PartialEq)]
pub enum OpType {
@ -39,6 +42,7 @@ pub enum OpType {
While,
Do,
Macro,
Include,
// syscalls
Syscall0,
@ -49,7 +53,7 @@ pub enum OpType {
Syscall5,
Syscall6,
None
None // Used for macros and any other non built in word definitions
}
@ -106,6 +110,7 @@ impl OpType {
&OpType::While => "while",
&OpType::Do => "do",
&OpType::Macro => "macro",
&OpType::Include => "include",
&OpType::Mem => "mem",
&OpType::Load8 => "!8",
&OpType::Store8 => "@8",

View File

@ -223,11 +223,7 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<()>{
} else {
ti += 1;
}
}
OpType::Macro => {
panic!();
}
OpType::Syscall0 => {
todo!();
// ti += 1;
@ -269,7 +265,9 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<()>{
todo!();
// ti += 1;
},
OpType::None => unreachable!()
OpType::None => unreachable!(),
OpType::Macro => unreachable!(),
OpType::Include => unreachable!()
}
}

View File

@ -1,5 +1,5 @@
use crate::{constants::{Token, TokenType}, preprocessor::preprocess};
use crate::{constants::{Token, TokenType}, preprocessor::preprocess, Args};
use color_eyre::Result;
fn lex_word(s: String, tok_type: TokenType) -> (TokenType, String) {
@ -68,22 +68,7 @@ fn lex_line(text: String) -> Result<Vec<(u32, String, TokenType)>> {
Ok(tokens)
}
// fn lex_text(text: String) -> Result<Vec<Token>>{
// let tokens: Vec<Token> = Vec::new();
// let mut row = 0;
// let mut col = 0;
// let mut index = find_col(text.clone(), 0, |x| x.is_whitespace())?;
// while index < text.len() as u32 {
// }
// Ok(tokens)
// }
pub fn lex(code: String, file: &String) -> Result<Vec<Token>> {
pub fn lex(code: String, file: &String, args: Args, preprocessing: bool) -> Result<Vec<Token>> {
let lines: Vec<(usize, &str)> = code
.split(['\n', '\r'])
.enumerate()
@ -112,6 +97,8 @@ pub fn lex(code: String, file: &String) -> Result<Vec<Token>> {
// for token in tokens.clone() {
// println!("tok: {:?}", token.text);
// }
tokens = preprocess(tokens)?;
if preprocessing {
tokens = preprocess(tokens, args)?;
}
Ok(tokens)
}

View File

@ -12,6 +12,10 @@ use color_eyre::Result;
use clap::Parser;
pub const DEFAULT_OUT_FILE: &str = "a.out";
pub const DEFAULT_INCLUDES: [&str;2] = [
"./include",
"~/.mclang/include",
];
#[derive(Parser, Debug, Clone)]
#[command(author, version, about, long_about = None)]
@ -39,28 +43,65 @@ pub struct Args {
/// Dont print any output exept the actual running codes output
#[arg(long, short)]
quiet: bool,
/// Add an include directory [default: ["./include", "~/.mclang/include"]]
#[arg(long, short='I')]
include: Vec<String>,
//#[arg(long, short='F')]
//features: Vec<String>,
}
fn main() -> Result<()> {
let args = Args::parse();
let code = fs::read_to_string(&args.in_file)?;
let tokens = lexer::lex(code, &args.in_file)?;
let code = match fs::read_to_string(&args.in_file) {
Ok(t) => t,
Err(_) => {
error!("Failed to read file {}, exiting!", &args.in_file);
return Ok(());
}
};
let tokens = match lexer::lex(code, &args.in_file, args.clone(), true) {
Ok(t) => t,
Err(_) => {
error!("Lexing failed, exiting!");
return Ok(());
}
};
// 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 = parser.parse()?;
let tokens = match parser.parse() {
Ok(t) => t,
Err(_) => {
error!("Parsing failed, exiting!");
return Ok(());
}
};
if args.compile && args.interpret {
error!("Cannot compile and interpret at the same time");
} else if args.interpret {
interpret::linux_x86_64::run(tokens)?;
match interpret::linux_x86_64::run(tokens) {
Ok(_) => (),
Err(_) => {
error!("Interpretation failed, exiting!");
return Ok(());
}
};
} else if args.compile {
compile::linux_x86_64::compile(tokens, args)?;
match compile::linux_x86_64::compile(tokens, args) {
Ok(_) => (),
Err(_) => {
error!("Compilation failed, exiting!");
return Ok(());
}
};
} else {
error!("Did not choose to compile or to interpret, exiting");
}

View File

@ -134,6 +134,7 @@ pub fn lookup_word<P: Deref<Target = (String, u32, u32)>>(s: String, _pos: P) ->
("while", OpType::While),
("do", OpType::Do),
("macro", OpType::Macro),
("include", OpType::Include), // technically not but it fits next to macros
// mem
("mem", OpType::Mem),

View File

@ -1,10 +1,12 @@
use std::collections::HashMap;
use std::path::PathBuf;
use color_eyre::Result;
use eyre::eyre;
use crate::constants::{Token, Loc, OpType, TokenType};
use crate::{lerror, lnote};
use crate::lexer::lex;
use crate::{lerror, lnote, Args};
use crate::parser::lookup_word;
#[derive(Debug)]
@ -13,7 +15,7 @@ pub struct Macro {
pub tokens: Vec<Token>
}
pub fn preprocess(tokens: Vec<Token>) -> Result<Vec<Token>>{
pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
let mut program: Vec<Token> = Vec::new();
let mut macros: HashMap<String, Macro> = HashMap::new();
@ -41,11 +43,12 @@ pub fn preprocess(tokens: Vec<Token>) -> Result<Vec<Token>>{
return Err(eyre!(""));
}
if macros.get(&macro_name.text.clone()).is_some() { //? Maybe allow?
lerror!(&macro_name.loc(), "Macro redefinition is not allowed");
lnote!(&macros.get(&macro_name.text.clone()).unwrap().loc, "First definition here");
return Err(eyre!(""));
if crate::constants::ALLOW_MACRO_REDEFINITION {
if macros.get(&macro_name.text.clone()).is_some() {
lerror!(&macro_name.loc(), "Macro redefinition is not allowed");
lnote!(&macros.get(&macro_name.text.clone()).unwrap().loc, "First definition here");
return Err(eyre!(""));
}
}
let mut macr = Macro{ loc: macro_name.loc(), tokens: Vec::new() };
@ -75,6 +78,45 @@ pub fn preprocess(tokens: Vec<Token>) -> Result<Vec<Token>>{
}
_ if op_type == OpType::Include => {
if rtokens.len() == 0 {
lerror!(&token.loc(), "Include path not found, expected {} but found nothing", TokenType::String.human());
return Err(eyre!(""));
}
let include_path = rtokens.pop().unwrap();
if include_path.typ != TokenType::String {
lerror!(&include_path.loc(), "Bad include path, expected {} but found {}", TokenType::String.human(), include_path.typ.human());
return Err(eyre!(""));
}
let mut in_paths = args.include.clone();
in_paths.append(&mut crate::DEFAULT_INCLUDES.to_vec().clone().iter().map(|f| f.to_string()).collect::<Vec<String>>());
let mut include_code = String::new();
for path in in_paths {
let p = PathBuf::from(path);
let p = p.join(include_path.text.clone());
if p.exists() {
include_code = std::fs::read_to_string(p)?;
}
}
if include_code.is_empty() {
lerror!(&include_path.loc(), "Include file in path '{}' was not found", include_path.text);
return Err(eyre!(""));
}
let mut code = lex(include_code, &include_path.text, args.clone(), false)?;
code.reverse();
rtokens.append(&mut code);
}
_ => {
program.push(token);
}

View File

@ -1,5 +1,3 @@
macro write
1 1 syscall3 drop
end
include "io.mcl"
"HEnlo world!\n" write