started implementing stdlib
This commit is contained in:
@@ -6,7 +6,7 @@ use crate::compile::commands::linux_x86_64_compile_and_link;
|
||||
use super::commands::linux_x86_64_run;
|
||||
|
||||
|
||||
pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
||||
pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
|
||||
let mut of_c = PathBuf::from(&args.out_file);
|
||||
let (mut of_o, mut of_a) = if &args.out_file == &crate::DEFAULT_OUT_FILE.to_string() {
|
||||
let of_o = PathBuf::from("/tmp/mclang_comp.o");
|
||||
@@ -405,8 +405,9 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
|
||||
writer.flush()?;
|
||||
linux_x86_64_compile_and_link(&of_a, &of_o, &of_c, args.quiet)?;
|
||||
if args.run {
|
||||
linux_x86_64_run(&of_c, vec![], args.quiet)?;
|
||||
let c = linux_x86_64_run(&of_c, vec![], args.quiet)?;
|
||||
return Ok(c);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(0)
|
||||
}
|
||||
@@ -64,7 +64,7 @@ pub struct Operator {
|
||||
pub text: String, //? only used for OpType::PushStr
|
||||
pub addr: i64, //? only used for OpType::PushStr
|
||||
pub jmp: i32,
|
||||
pub pos: (String, u32, u32)
|
||||
pub loc: (String, u32, u32)
|
||||
}
|
||||
|
||||
impl Operator {
|
||||
@@ -75,7 +75,7 @@ impl Operator {
|
||||
jmp: 0,
|
||||
addr: -1,
|
||||
text,
|
||||
pos: (file, row, col)
|
||||
loc: (file, row, col)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ fn stack_pop(stack: &mut Vec<u64>, pos: &(String, u32, u32)) -> Result<u64> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<()>{
|
||||
pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<i32>{
|
||||
let mut stack: Vec<u64> = Vec::new();
|
||||
let mut ti = 0;
|
||||
let mut mem: Vec<u8> = vec![0; crate::compile::MEM_SZ as usize + crate::compile::STRING_SZ as usize];
|
||||
@@ -25,7 +25,7 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<()>{
|
||||
// }
|
||||
while ti < tokens.len() {
|
||||
let token = &tokens[ti];
|
||||
let pos = token.pos.clone();
|
||||
let pos = token.loc.clone();
|
||||
// println!("{:?}", token.typ);
|
||||
match token.typ {
|
||||
|
||||
@@ -272,5 +272,5 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<()>{
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
Ok(0)
|
||||
}
|
||||
@@ -44,6 +44,8 @@ fn lex_line(text: String) -> Result<Vec<(u32, String, TokenType)>> {
|
||||
let t = t.replace("\\n", "\n")
|
||||
.replace("\\t", "\t")
|
||||
.replace("\\r", "\r")
|
||||
.replace("\\\'", "\'")
|
||||
.replace("\\\"", "\"")
|
||||
.replace("\\0", "\0");
|
||||
if !t.is_empty() {
|
||||
tokens.push((col, t.to_string(), TokenType::String));
|
||||
@@ -100,5 +102,6 @@ pub fn lex(code: String, file: &String, args: Args, preprocessing: bool) -> Resu
|
||||
if preprocessing {
|
||||
tokens = preprocess(tokens, args)?;
|
||||
}
|
||||
|
||||
Ok(tokens)
|
||||
}
|
||||
26
src/main.rs
26
src/main.rs
@@ -72,10 +72,7 @@ fn main() -> Result<()> {
|
||||
}
|
||||
};
|
||||
|
||||
// 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 = match parser.parse() {
|
||||
Ok(t) => t,
|
||||
@@ -84,26 +81,29 @@ fn main() -> Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
if args.compile && args.interpret {
|
||||
|
||||
let c = if args.compile && args.interpret {
|
||||
error!("Cannot compile and interpret at the same time");
|
||||
0
|
||||
} else if args.interpret {
|
||||
match interpret::linux_x86_64::run(tokens) {
|
||||
Ok(_) => (),
|
||||
Ok(c) => c,
|
||||
Err(_) => {
|
||||
error!("Interpretation failed, exiting!");
|
||||
return Ok(());
|
||||
1
|
||||
}
|
||||
};
|
||||
}
|
||||
} else if args.compile {
|
||||
match compile::linux_x86_64::compile(tokens, args) {
|
||||
Ok(_) => (),
|
||||
Ok(c) => c,
|
||||
Err(_) => {
|
||||
error!("Compilation failed, exiting!");
|
||||
return Ok(());
|
||||
1
|
||||
}
|
||||
};
|
||||
}
|
||||
} else {
|
||||
error!("Did not choose to compile or to interpret, exiting");
|
||||
}
|
||||
Ok(())
|
||||
0
|
||||
};
|
||||
std::process::exit(c);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||
OpType::Else => {
|
||||
let if_ip = stack.pop().unwrap();
|
||||
if program[if_ip as usize].typ != OpType::If {
|
||||
lerror!(&op.clone().pos,"'end' can only close 'if' blocks");
|
||||
lerror!(&op.clone().loc,"'end' can only close 'if' blocks");
|
||||
return Err(eyre!("Bad block"));
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||
program[ip].jmp = program[block_ip as usize].jmp;
|
||||
program[block_ip as usize].jmp = (ip + 1) as i32;
|
||||
} else {
|
||||
lerror!(&op.clone().pos,"'end' can only close 'if' blocks");
|
||||
lerror!(&op.clone().loc,"'end' can only close 'if' blocks");
|
||||
return Err(eyre!(""));
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||
|
||||
}
|
||||
if stack.len() > 0 {
|
||||
lerror!(&program[stack.pop().expect("Empy stack") as usize].clone().pos,"Unclosed block");
|
||||
lerror!(&program[stack.pop().expect("Empy stack") as usize].clone().loc,"Unclosed block");
|
||||
return Err(eyre!("Unclosed block"));
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ impl Parser {
|
||||
let pos = (token.file.clone(), token.line, token.col);
|
||||
match token.typ {
|
||||
TokenType::Word => {
|
||||
let word_type = lookup_word(token.text.clone(), &pos)?;
|
||||
let word_type = lookup_word(token.text.clone(), &pos);
|
||||
tokens.push(Operator::new(word_type, 0, token.text.clone(), token.file.clone(), token.line, token.col));
|
||||
},
|
||||
TokenType::Int => {// negative numbers not yet implemented
|
||||
@@ -103,7 +103,7 @@ impl Parser {
|
||||
}
|
||||
|
||||
|
||||
pub fn lookup_word<P: Deref<Target = (String, u32, u32)>>(s: String, _pos: P) -> Result<OpType>{
|
||||
pub fn lookup_word<P: Deref<Target = (String, u32, u32)>>(s: String, _pos: P) -> OpType {
|
||||
let lookup_table: HashMap<&str, OpType> = HashMap::from([
|
||||
//stack
|
||||
("print", OpType::Print),
|
||||
@@ -151,9 +151,9 @@ pub fn lookup_word<P: Deref<Target = (String, u32, u32)>>(s: String, _pos: P) ->
|
||||
]);
|
||||
|
||||
match lookup_table.get(s.as_str()) {
|
||||
Some(v) => Ok(v.clone()),
|
||||
Some(v) => v.clone(),
|
||||
None => {
|
||||
Ok(OpType::None)
|
||||
OpType::None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use eyre::eyre;
|
||||
|
||||
use crate::constants::{Token, Loc, OpType, TokenType};
|
||||
use crate::lexer::lex;
|
||||
use crate::{lerror, lnote, Args};
|
||||
use crate::{lerror, lnote, Args, warn};
|
||||
use crate::parser::lookup_word;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -24,7 +24,7 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
|
||||
while rtokens.len() > 0 {
|
||||
let token = rtokens.pop().unwrap();
|
||||
|
||||
let op_type = lookup_word(token.text.clone(), &token.loc())?;
|
||||
let op_type = lookup_word(token.text.clone(), &token.loc());
|
||||
match token.clone() {
|
||||
_ if op_type == OpType::Macro => {
|
||||
if rtokens.len() == 0 {
|
||||
@@ -37,17 +37,19 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
|
||||
lerror!(¯o_name.loc(), "Bad macro name, expected {} but found {}", TokenType::Word.human(), macro_name.typ.human());
|
||||
return Err(eyre!(""));
|
||||
}
|
||||
let word = lookup_word(macro_name.text.clone(), ¯o_name.loc())?;
|
||||
let word = lookup_word(macro_name.text.clone(), ¯o_name.loc());
|
||||
if word != OpType::None {
|
||||
lerror!(¯o_name.loc(), "Macro name cannot be a built in word, got '{}'", word.human());
|
||||
return Err(eyre!(""));
|
||||
}
|
||||
|
||||
if crate::constants::ALLOW_MACRO_REDEFINITION {
|
||||
if macros.get(¯o_name.text.clone()).is_some() {
|
||||
if macros.get(¯o_name.text.clone()).is_some() {
|
||||
if crate::constants::ALLOW_MACRO_REDEFINITION {
|
||||
lerror!(¯o_name.loc(), "Macro redefinition is not allowed");
|
||||
lnote!(¯os.get(¯o_name.text.clone()).unwrap().loc, "First definition here");
|
||||
return Err(eyre!(""));
|
||||
} else {
|
||||
//TODO: somehow warn about redefinition of only built in macros
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +58,7 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
|
||||
let mut depth = 0;
|
||||
while rtokens.len() > 0 {
|
||||
let t = rtokens.pop().unwrap();
|
||||
let typ = lookup_word(t.text.clone(), &t.loc())?;
|
||||
let typ = lookup_word(t.text.clone(), &t.loc());
|
||||
if typ == OpType::End && depth == 0 {
|
||||
break;
|
||||
} else if typ == OpType::End && depth != 0 {
|
||||
@@ -123,12 +125,31 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
|
||||
}
|
||||
}
|
||||
|
||||
program = expand_macros(program, macros)?;
|
||||
//* Feel free to fix this horrifying shit
|
||||
//* i wanna kms
|
||||
let mut times = 0;
|
||||
while program.iter().map(|f| {
|
||||
if f.typ == TokenType::Word {
|
||||
lookup_word(f.text.clone(), &f.loc())
|
||||
} else {
|
||||
OpType::PushInt // i hate myself, this is a randomly picked optype so its happy and works
|
||||
}
|
||||
|
||||
}).collect::<Vec<OpType>>().contains(&OpType::None){
|
||||
|
||||
if times >= 50 {
|
||||
warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it");
|
||||
break
|
||||
}
|
||||
program = expand_macros(program, ¯os)?;
|
||||
times += 1;
|
||||
}
|
||||
|
||||
|
||||
Ok(program)
|
||||
}
|
||||
|
||||
pub fn expand_macros(tokens: Vec<Token>, macros: HashMap<String, Macro>) -> Result<Vec<Token>> {
|
||||
pub fn expand_macros(tokens: Vec<Token>, macros: &HashMap<String, Macro>) -> Result<Vec<Token>> {
|
||||
let mut program: Vec<Token> = Vec::new();
|
||||
|
||||
let mut rtokens = tokens.clone();
|
||||
@@ -136,7 +157,7 @@ pub fn expand_macros(tokens: Vec<Token>, macros: HashMap<String, Macro>) -> Resu
|
||||
|
||||
while rtokens.len() > 0 {
|
||||
let op = rtokens.pop().unwrap();
|
||||
let op_type = lookup_word(op.text.clone(), &op.loc())?;
|
||||
let op_type = lookup_word(op.text.clone(), &op.loc());
|
||||
if op.typ == TokenType::Word {
|
||||
match op_type {
|
||||
OpType::None => {
|
||||
|
||||
Reference in New Issue
Block a user