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")?;
|
writeln!(writer, " push rax")?;
|
||||||
ti += 1;
|
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}:")?;
|
writeln!(writer, "addr_{ti}:")?;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::info;
|
||||||
pub fn linux_x86_64_compile_and_link(folders: &Folders, quiet: bool) -> Result<()> {
|
pub fn linux_x86_64_compile_and_link(folders: &Folders, quiet: bool) -> Result<()> {
|
||||||
|
|
||||||
let nasm_args = [
|
let nasm_args = [
|
||||||
"-felf64",
|
"-fwin32",
|
||||||
folders.of_a.to_str().unwrap(),
|
folders.of_a.to_str().unwrap(),
|
||||||
"-o",
|
"-o",
|
||||||
folders.of_o.to_str().unwrap()
|
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 = [
|
let ld_args = [
|
||||||
folders.of_o.to_str().unwrap(),
|
folders.of_o.to_str().unwrap(),
|
||||||
"-o",
|
"-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;
|
use super::Folders;
|
||||||
|
|
||||||
pub fn compile(tokens: &[Operator], args: &Args, folders: &Folders) -> Result<i32>{
|
pub fn compile(tokens: &[Operator], args: &Args, folders: &Folders) -> Result<i32>{
|
||||||
|
|
||||||
let file = fs::File::create(&folders.of_a)?;
|
let file = fs::File::create(&folders.of_a)?;
|
||||||
let mut writer = BufWriter::new(&file);
|
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")?;
|
writeln!(writer, " push rax")?;
|
||||||
ti += 1;
|
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}:")?;
|
writeln!(writer, "addr_{ti}:")?;
|
||||||
|
|
|
@ -60,10 +60,20 @@ pub enum KeywordType {
|
||||||
Include,
|
Include,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum PreprocessorType {
|
||||||
|
IfDefined,
|
||||||
|
IfNotDefined,
|
||||||
|
Else,
|
||||||
|
EndIf,
|
||||||
|
Define
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum OpType {
|
pub enum OpType {
|
||||||
Keyword(KeywordType),
|
Keyword(KeywordType),
|
||||||
Instruction(InstructionType)
|
Instruction(InstructionType),
|
||||||
|
Preprocessor(PreprocessorType)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -132,7 +142,12 @@ impl OpType {
|
||||||
OpType::Instruction(InstructionType::Syscall4) => "syscall4",
|
OpType::Instruction(InstructionType::Syscall4) => "syscall4",
|
||||||
OpType::Instruction(InstructionType::Syscall5) => "syscall5",
|
OpType::Instruction(InstructionType::Syscall5) => "syscall5",
|
||||||
OpType::Instruction(InstructionType::Syscall6) => "syscall6",
|
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()
|
}.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -272,7 +272,10 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
||||||
todo!();
|
todo!();
|
||||||
// ti += 1;
|
// 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;
|
mod preprocessor;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use constants::targets;
|
use constants::targets;
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: add simple macro support on vscode syntax highlighting
|
||||||
|
*/
|
||||||
|
|
||||||
pub const DEFAULT_OUT_FILE: &str = "a.out";
|
pub const DEFAULT_OUT_FILE: &str = "a.out";
|
||||||
pub const DEFAULT_INCLUDES: [&str;2] = [
|
pub const DEFAULT_INCLUDES: [&str;2] = [
|
||||||
"./include",
|
"./include",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::Deref;
|
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 color_eyre::Result;
|
||||||
use eyre::eyre;
|
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),
|
"syscall4" => OpType::Instruction(InstructionType::Syscall4),
|
||||||
"syscall5" => OpType::Instruction(InstructionType::Syscall5),
|
"syscall5" => OpType::Instruction(InstructionType::Syscall5),
|
||||||
"syscall6" => OpType::Instruction(InstructionType::Syscall6),
|
"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)
|
_ => OpType::Instruction(InstructionType::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,22 @@ use std::path::PathBuf;
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use eyre::eyre;
|
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::lexer::lex;
|
||||||
use crate::{lerror, lnote, Args, warn};
|
use crate::{lerror, lnote, Args, warn};
|
||||||
use crate::parser::lookup_word;
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct Macro {
|
pub struct Macro {
|
||||||
pub loc: Loc,
|
pub loc: Loc,
|
||||||
|
@ -18,6 +29,10 @@ pub struct Macro {
|
||||||
pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
|
pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
|
||||||
let mut program: Vec<Token> = Vec::new();
|
let mut program: Vec<Token> = Vec::new();
|
||||||
let mut macros: HashMap<String, Macro> = HashMap::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;
|
let mut rtokens = tokens;
|
||||||
rtokens.reverse();
|
rtokens.reverse();
|
||||||
|
@ -71,8 +86,6 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
|
||||||
|
|
||||||
|
|
||||||
macros.insert(macro_name.text, macr);
|
macros.insert(macro_name.text, macr);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ if op_type == OpType::Keyword(KeywordType::Include) => {
|
_ 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);
|
program.push(token);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,14 +36,10 @@ print:
|
||||||
global _start
|
global _start
|
||||||
_start:
|
_start:
|
||||||
addr_0:
|
addr_0:
|
||||||
;; -- push int 32
|
;; -- push int 69
|
||||||
mov rax, 32
|
mov rax, 69
|
||||||
push rax
|
push rax
|
||||||
addr_1:
|
addr_1:
|
||||||
;; -- print
|
|
||||||
pop rdi
|
|
||||||
call print
|
|
||||||
addr_2:
|
|
||||||
mov rax, 60
|
mov rax, 60
|
||||||
mov rdi, 0
|
mov rdi, 0
|
||||||
syscall
|
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