diff --git a/src/compile/linux_x86_64/mod.rs b/src/compile/linux_x86_64/mod.rs index f7e3bc2..d861492 100644 --- a/src/compile/linux_x86_64/mod.rs +++ b/src/compile/linux_x86_64/mod.rs @@ -391,7 +391,10 @@ pub fn compile(tokens: &[Operator], args: &Args, folders: &Folders) -> Result unreachable!() + OpType::Instruction(InstructionType::None) | + OpType::Keyword(KeywordType::Macro) | + OpType::Keyword(KeywordType::Include) | + OpType::Preprocessor(_) => unreachable!() } } writeln!(writer, "addr_{ti}:")?; diff --git a/src/compile/win32_x86_64/commands.rs b/src/compile/win32_x86_64/commands.rs index 3dddff7..2b20a41 100644 --- a/src/compile/win32_x86_64/commands.rs +++ b/src/compile/win32_x86_64/commands.rs @@ -7,7 +7,7 @@ use crate::info; pub fn linux_x86_64_compile_and_link(folders: &Folders, quiet: bool) -> Result<()> { let nasm_args = [ - "-felf64", + "-fwin32", folders.of_a.to_str().unwrap(), "-o", folders.of_o.to_str().unwrap() @@ -16,7 +16,11 @@ pub fn linux_x86_64_compile_and_link(folders: &Folders, quiet: bool) -> Result<( let ld_args = [ folders.of_o.to_str().unwrap(), "-o", - folders.of_c.to_str().unwrap() + folders.of_c.to_str().unwrap(), + "-L", + "C:\\Program Files\\Microsoft SDKs\\Windows\\v6.0\\Lib", + "-l", + "kernel32" ]; diff --git a/src/compile/win32_x86_64/mod.rs b/src/compile/win32_x86_64/mod.rs index b72541a..3e1526a 100644 --- a/src/compile/win32_x86_64/mod.rs +++ b/src/compile/win32_x86_64/mod.rs @@ -9,7 +9,6 @@ use crate::constants::InstructionType; use super::Folders; pub fn compile(tokens: &[Operator], args: &Args, folders: &Folders) -> Result{ - let file = fs::File::create(&folders.of_a)?; let mut writer = BufWriter::new(&file); @@ -389,7 +388,10 @@ pub fn compile(tokens: &[Operator], args: &Args, folders: &Folders) -> Result unreachable!() + OpType::Instruction(InstructionType::None) | + OpType::Keyword(KeywordType::Macro) | + OpType::Keyword(KeywordType::Include) | + OpType::Preprocessor(_) => unreachable!() } } writeln!(writer, "addr_{ti}:")?; diff --git a/src/constants.rs b/src/constants.rs index d9b13ff..6d57931 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -60,10 +60,20 @@ pub enum KeywordType { Include, } +#[derive(Debug, Clone, PartialEq)] +pub enum PreprocessorType { + IfDefined, + IfNotDefined, + Else, + EndIf, + Define +} + #[derive(Debug, Clone, PartialEq)] pub enum OpType { Keyword(KeywordType), - Instruction(InstructionType) + Instruction(InstructionType), + Preprocessor(PreprocessorType) } #[derive(Debug, Clone)] @@ -132,7 +142,12 @@ impl OpType { OpType::Instruction(InstructionType::Syscall4) => "syscall4", OpType::Instruction(InstructionType::Syscall5) => "syscall5", OpType::Instruction(InstructionType::Syscall6) => "syscall6", - OpType::Instruction(InstructionType::None) => "None" + OpType::Instruction(InstructionType::None) => "None", + OpType::Preprocessor(PreprocessorType::IfDefined) => "#ifdef", + OpType::Preprocessor(PreprocessorType::IfNotDefined) => "#ifndef", + OpType::Preprocessor(PreprocessorType::Else) => "#else", + OpType::Preprocessor(PreprocessorType::EndIf) => "#endif", + OpType::Preprocessor(PreprocessorType::Define) => "#define", }.to_string() } } diff --git a/src/interpret/linux_x86_64/mod.rs b/src/interpret/linux_x86_64/mod.rs index a53f34d..89be2c3 100644 --- a/src/interpret/linux_x86_64/mod.rs +++ b/src/interpret/linux_x86_64/mod.rs @@ -272,7 +272,10 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result{ todo!(); // ti += 1; }, - OpType::Instruction(InstructionType::None) | OpType::Keyword(KeywordType::Macro) | OpType::Keyword(KeywordType::Include) => unreachable!() + OpType::Instruction(InstructionType::None) | + OpType::Keyword(KeywordType::Macro) | + OpType::Keyword(KeywordType::Include) | + OpType::Preprocessor(_) => unreachable!() } } diff --git a/src/main.rs b/src/main.rs index 8c9493b..15d5b80 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,10 +7,13 @@ mod lexer; mod preprocessor; use std::fs; - use clap::Parser; use constants::targets; +/* + TODO: add simple macro support on vscode syntax highlighting + */ + pub const DEFAULT_OUT_FILE: &str = "a.out"; pub const DEFAULT_INCLUDES: [&str;2] = [ "./include", diff --git a/src/parser.rs b/src/parser.rs index 9c8f444..c0ca927 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use crate::{constants::{Operator, OpType, Token, TokenType, Loc, KeywordType, InstructionType}, lerror}; +use crate::{constants::{Operator, OpType, Token, TokenType, Loc, KeywordType, InstructionType, PreprocessorType}, lerror}; use color_eyre::Result; use eyre::eyre; @@ -156,6 +156,12 @@ pub fn lookup_word>(s: &str, _pos: P) -> OpType { "syscall4" => OpType::Instruction(InstructionType::Syscall4), "syscall5" => OpType::Instruction(InstructionType::Syscall5), "syscall6" => OpType::Instruction(InstructionType::Syscall6), + + "#ifdef" => OpType::Preprocessor(PreprocessorType::IfDefined), + "#ifndef" => OpType::Preprocessor(PreprocessorType::IfNotDefined), + "#else" => OpType::Preprocessor(PreprocessorType::Else), + "#endif" => OpType::Preprocessor(PreprocessorType::EndIf), + "#define" => OpType::Preprocessor(PreprocessorType::Define), _ => OpType::Instruction(InstructionType::None) } diff --git a/src/preprocessor.rs b/src/preprocessor.rs index d539ee0..da2a110 100644 --- a/src/preprocessor.rs +++ b/src/preprocessor.rs @@ -4,11 +4,22 @@ use std::path::PathBuf; use color_eyre::Result; use eyre::eyre; -use crate::constants::{Token, Loc, OpType, TokenType, KeywordType, InstructionType}; +use crate::constants::{Token, Loc, OpType, TokenType, KeywordType, InstructionType, PreprocessorType}; use crate::lexer::lex; use crate::{lerror, lnote, Args, warn}; use crate::parser::lookup_word; +fn get_predefined_basic_macros(args: &Args) -> Vec { + let mut a: Vec = Vec::new(); + if args.target.as_str() == crate::constants::targets::WIN32_X86_64 { + a.push("__win32__".to_string()); + } else + if args.target.as_str() == crate::constants::targets::LINUX_X86_64 { + a.push("__linux__".to_string()); + } + a +} + #[derive(Debug)] pub struct Macro { pub loc: Loc, @@ -18,7 +29,11 @@ pub struct Macro { pub fn preprocess(tokens: Vec, args: &Args) -> Result>{ let mut program: Vec = Vec::new(); let mut macros: HashMap = HashMap::new(); - + let mut basic_macros: Vec = get_predefined_basic_macros(args); + + //* predefined basic macros + + let mut rtokens = tokens; rtokens.reverse(); while !rtokens.is_empty() { @@ -71,8 +86,6 @@ pub fn preprocess(tokens: Vec, args: &Args) -> Result>{ macros.insert(macro_name.text, macr); - - } _ if op_type == OpType::Keyword(KeywordType::Include) => { @@ -114,6 +127,141 @@ pub fn preprocess(tokens: Vec, args: &Args) -> Result>{ } + + _ if op_type == OpType::Preprocessor(PreprocessorType::Define) => { + if rtokens.is_empty(){ + lerror!(&token.loc(), "Basic macro contents not found, expected {} but found nothing", TokenType::Word.human()); + return Err(eyre!("")); + } + + let basic_macro_name = rtokens.pop().unwrap(); + + if basic_macro_name.typ != TokenType::Word { + lerror!(&basic_macro_name.loc(), "Bad basic macro contents, expected {} but found {}", TokenType::Word.human(), basic_macro_name.typ.human()); + return Err(eyre!("")); + } + + let word = lookup_word(&basic_macro_name.text, &basic_macro_name.loc()); + if word != OpType::Instruction(InstructionType::None) { + lerror!(&basic_macro_name.loc(), "Basic macro contents cannot be a built in word, got '{}'", word.human()); + return Err(eyre!("")); + } + + basic_macros.push(basic_macro_name.text); + } + _ if op_type == OpType::Preprocessor(PreprocessorType::IfDefined) => { + if rtokens.is_empty(){ + lerror!(&token.loc(), "Basic macro contents not found, expected {} but found nothing", TokenType::Word.human()); + return Err(eyre!("")); + } + + let basic_macro_name = rtokens.pop().unwrap(); + + let exists = basic_macros.contains(&basic_macro_name.text); + + #[allow(unused_assignments)] + let mut skip = false; + let mut skip_this = false; + let mut els = false; + skip = if !exists { true } else { false }; + while !rtokens.is_empty() { + let token = rtokens.pop().unwrap(); + let op_typ = lookup_word(&token.text, &token.loc()); + if exists { + if op_typ == OpType::Preprocessor(PreprocessorType::Else) { + if els { + todo!(); + } + els = true; + skip = true; + } + } else { + if op_typ == OpType::Preprocessor(PreprocessorType::Else) { + if els { + todo!(); + } + els = true; + skip = false; + skip_this = true; + } + } + + if op_typ == OpType::Preprocessor(PreprocessorType::EndIf) { + break; + } + + if !skip { + #[allow(unused_assignments)] + if skip_this { + skip_this = false; + } else { + program.push(token); + } + } + + } + + }, + + _ if op_type == OpType::Preprocessor(PreprocessorType::IfNotDefined) => { + if rtokens.is_empty(){ + lerror!(&token.loc(), "Basic macro contents not found, expected {} but found nothing", TokenType::Word.human()); + return Err(eyre!("")); + } + + let basic_macro_name = rtokens.pop().unwrap(); + + let exists = basic_macros.contains(&basic_macro_name.text); + + #[allow(unused_assignments)] + let mut skip = false; + let mut skip_this = false; + let mut els = false; + skip = if exists { true } else { false }; + while !rtokens.is_empty() { + let token = rtokens.pop().unwrap(); + let op_typ = lookup_word(&token.text, &token.loc()); + if !exists { + if op_typ == OpType::Preprocessor(PreprocessorType::Else) { + if els { + todo!(); + } + els = true; + skip = true; + } + } else { + if op_typ == OpType::Preprocessor(PreprocessorType::Else) { + if els { + todo!(); + } + els = true; + skip = false; + skip_this = true; + } + } + + if op_typ == OpType::Preprocessor(PreprocessorType::EndIf) { + break; + } + + if !skip { + #[allow(unused_assignments)] + if skip_this { + skip_this = false; + } else { + program.push(token); + } + } + + } + + + }, + _ if op_type == OpType::Preprocessor(PreprocessorType::Else) || + op_type == OpType::Preprocessor(PreprocessorType::EndIf) => { + + unreachable!() + }, _ => { program.push(token); } diff --git a/test b/test deleted file mode 100644 index 06a6588..0000000 Binary files a/test and /dev/null differ diff --git a/test.exe b/test.exe deleted file mode 100644 index 50b8025..0000000 Binary files a/test.exe and /dev/null differ diff --git a/test.mcl b/test.mcl index 1613b36..c23c68e 100644 --- a/test.mcl +++ b/test.mcl @@ -1 +1,3 @@ -' ' print \ No newline at end of file +#ifdef __win32__ + 69 +#endif \ No newline at end of file diff --git a/test.nasm b/test.nasm index 73029a5..f222410 100644 --- a/test.nasm +++ b/test.nasm @@ -36,14 +36,10 @@ print: global _start _start: addr_0: - ;; -- push int 32 - mov rax, 32 + ;; -- push int 69 + mov rax, 69 push rax addr_1: - ;; -- print - pop rdi - call print -addr_2: mov rax, 60 mov rdi, 0 syscall diff --git a/test.o b/test.o deleted file mode 100644 index a62d83f..0000000 Binary files a/test.o and /dev/null differ diff --git a/tests/fail_unknown_word.mcl b/tests/fail_unknown_word.mcl deleted file mode 100644 index 13724a0..0000000 --- a/tests/fail_unknown_word.mcl +++ /dev/null @@ -1 +0,0 @@ -gftdesd5ryutfgyhibugtf6r4 \ No newline at end of file diff --git a/tests/math.mcl b/tests/math.mcl deleted file mode 100644 index 89d4cd5..0000000 --- a/tests/math.mcl +++ /dev/null @@ -1,7 +0,0 @@ -34 35 + print - -800 380 - print - -10 5 * print - -40 5 / print \ No newline at end of file