Added simple C preprocessor style macros to enable support for multiple system types
This commit is contained in:
parent
db83d6d9c1
commit
4213986202
|
@ -391,7 +391,10 @@ pub fn compile(tokens: &[Operator], args: &Args, folders: &Folders) -> Result<i3
|
|||
writeln!(writer, " push rax")?;
|
||||
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!()
|
||||
}
|
||||
}
|
||||
writeln!(writer, "addr_{ti}:")?;
|
||||
|
|
|
@ -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"
|
||||
];
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ use crate::constants::InstructionType;
|
|||
use super::Folders;
|
||||
|
||||
pub fn compile(tokens: &[Operator], args: &Args, folders: &Folders) -> Result<i32>{
|
||||
|
||||
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<i3
|
|||
writeln!(writer, " push rax")?;
|
||||
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!()
|
||||
}
|
||||
}
|
||||
writeln!(writer, "addr_{ti}:")?;
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,7 +272,10 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
|||
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!()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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<P: Deref<Target = Loc>>(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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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<String> {
|
||||
let mut a: Vec<String> = 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<Token>, args: &Args) -> Result<Vec<Token>>{
|
||||
let mut program: Vec<Token> = Vec::new();
|
||||
let mut macros: HashMap<String, Macro> = HashMap::new();
|
||||
|
||||
let mut basic_macros: Vec<String> = 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<Token>, args: &Args) -> Result<Vec<Token>>{
|
|||
|
||||
|
||||
macros.insert(macro_name.text, macr);
|
||||
|
||||
|
||||
}
|
||||
|
||||
_ if op_type == OpType::Keyword(KeywordType::Include) => {
|
||||
|
@ -114,6 +127,141 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
|
|||
|
||||
|
||||
}
|
||||
|
||||
_ 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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
gftdesd5ryutfgyhibugtf6r4
|
|
@ -1,7 +0,0 @@
|
|||
34 35 + print
|
||||
|
||||
800 380 - print
|
||||
|
||||
10 5 * print
|
||||
|
||||
40 5 / print
|
Loading…
Reference in New Issue
Block a user