diff --git a/src/compile/linux_x86_64.rs b/src/compile/linux_x86_64.rs index a87969e..79418af 100644 --- a/src/compile/linux_x86_64.rs +++ b/src/compile/linux_x86_64.rs @@ -92,10 +92,11 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ writeln!(writer, " ;; -- {:?}", token.typ)?; } } else { - - if ti != 0 && tokens[ti-1].typ == OpType::Keyword(KeywordType::Else) || + if ti > 0 { + if tokens[ti-1].typ == OpType::Keyword(KeywordType::Else) || tokens[ti-1].typ == OpType::Keyword(KeywordType::End){ - writeln!(writer, "addr_{ti}:")?; + writeln!(writer, "addr_{ti}:")?; + } } if ti + 1 < tokens.len() && tokens[ti+1].typ == OpType::Keyword(KeywordType::End) { @@ -496,7 +497,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ writeln!(writer, " pop rbx")?; writeln!(writer, " mov qword [rbp], rbx")?; writeln!(writer, " add rbp, 8")?; - functions.push(Function { loc: token.loc.clone(), name: token.text.clone() }); + functions.push(Function { loc: token.loc.clone(), name: token.text.clone(), exter: false}); ti += 1; }, KeywordType::FunctionDone => { @@ -509,7 +510,9 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ KeywordType::FunctionThen => ti += 1, KeywordType::Function | KeywordType::Include | + KeywordType::FunctionDefInline | KeywordType::Constant => unreachable!(), + KeywordType::Inline => todo!(), } } } diff --git a/src/compile/mod.rs b/src/compile/mod.rs index 8391aa0..542e6ed 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -23,5 +23,6 @@ pub struct Memory { #[derive(Debug, Clone)] pub struct Function { pub loc: Loc, - pub name: String + pub name: String, + pub exter: bool, } \ No newline at end of file diff --git a/src/constants.rs b/src/constants.rs index ea7d9e2..b87b3f1 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -84,8 +84,10 @@ pub enum KeywordType { ConstantDef, Function, FunctionDef, + FunctionDefInline, FunctionThen, - FunctionDone + FunctionDone, + Inline } #[derive(Debug, Clone, PartialEq)] @@ -198,7 +200,9 @@ impl OpType { KeywordType::FunctionThen => "then", KeywordType::FunctionDone => "done", KeywordType::ConstantDef => "constant Definition (internal)", - KeywordType::FunctionDef => "function definition (internal)" + KeywordType::FunctionDef => "function definition (internal)", + KeywordType::FunctionDefInline => "inline function definition (internal)", + KeywordType::Inline => "inline" } } diff --git a/src/interpret/linux_x86_64/mod.rs b/src/interpret/linux_x86_64/mod.rs index 7ed383f..08f89d4 100644 --- a/src/interpret/linux_x86_64/mod.rs +++ b/src/interpret/linux_x86_64/mod.rs @@ -362,6 +362,7 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result{ KeywordType::While | //* exept this one, this one should just skip over KeywordType::Memory | KeywordType::FunctionDef | + KeywordType::FunctionDefInline | KeywordType::ConstantDef => { //? Disabled since we now pre run the whole program // constants.insert(op.text.clone(), Constant { loc: op.loc.clone(), name: op.text.clone(), value_i: Some(op.value), value_s: None, used: false }); @@ -378,6 +379,7 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result{ KeywordType::FunctionThen => ip += 1, KeywordType::Constant | KeywordType::Function | + KeywordType::Inline | KeywordType::Include => unreachable!(), } } @@ -407,7 +409,8 @@ pub fn pre_run(ops: &[Operator]) -> Defineds { OpType::Keyword(KeywordType::Memory) => { defineds.memories.insert(op.addr.unwrap(), Memory { size: op.value, loc: op.loc.clone(), id: op.addr.unwrap() }); }, - OpType::Keyword(KeywordType::FunctionDef) => { + OpType::Keyword(KeywordType::FunctionDefInline) | + OpType::Keyword(KeywordType::FunctionDef) => { defineds.functions.insert(op.text.clone(), Function { loc: op.loc.clone(), name: op.text.clone(), id: ip }); }, OpType::Keyword(KeywordType::ConstantDef) => { diff --git a/src/parser.rs b/src/parser.rs index cd9d395..0fa7abe 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -44,9 +44,7 @@ pub fn cross_ref(mut program: Vec) -> Result> { program[ip].jmp = program[block_ip].jmp; program[block_ip].jmp = ip + 1; } - OpType::Keyword(KeywordType::FunctionThen) => { - program[ip].typ = OpType::Instruction(InstructionType::Return); - } + OpType::Keyword(KeywordType::Memory | KeywordType::Constant) => (), a => { @@ -208,6 +206,7 @@ pub fn lookup_word>(s: &str, _pos: P) -> OpType { "fn" => OpType::Keyword(KeywordType::Function), "then" => OpType::Keyword(KeywordType::FunctionThen), "done" => OpType::Keyword(KeywordType::FunctionDone), + "inline" => OpType::Keyword(KeywordType::Inline), "return" => OpType::Instruction(InstructionType::Return), "returns" => OpType::Instruction(InstructionType::Returns), "bool" => OpType::Instruction(InstructionType::TypeBool), diff --git a/src/preprocessor.rs b/src/preprocessor.rs index 719bc89..1a68f6b 100644 --- a/src/preprocessor.rs +++ b/src/preprocessor.rs @@ -17,7 +17,9 @@ use crate::parser::lookup_word; #[derive(Debug, Clone)] pub struct Function { pub loc: Loc, - pub name: String + pub name: String, + pub inline: bool, + pub tokens: Option> } #[derive(Debug, Clone)] @@ -62,20 +64,21 @@ impl<'a> Preprocessor<'a> { pub fn preprocess(&mut self) -> Result<&mut Preprocessor<'a>>{ // println!("pre: has do tokens: {:?}", self.program.iter().map(|t| if t.typ == OpType::Keyword(KeywordType::Do) {Some(t)} else {None} ).collect::>>()); + let mut f_inline = false; + let mut f_extern = false; + let mut program: Vec = Vec::new(); let mut rtokens = self.program.clone(); rtokens.reverse(); while !rtokens.is_empty() { - let mut token = rtokens.pop().unwrap(); + let mut op = rtokens.pop().unwrap(); // println!("{token:?}"); - let op_type = token.typ.clone(); - match token.clone() { - - - _ if op_type == OpType::Keyword(KeywordType::Include) => { + let op_type = op.typ.clone(); + match op_type { + OpType::Keyword(KeywordType::Include) => { if rtokens.is_empty() { - lerror!(&token.loc, "Include path not found, expected {} but found nothing", TokenType::String.human()); + lerror!(&op.loc, "Include path not found, expected {} but found nothing", TokenType::String.human()); return Err(eyre!("")); } @@ -127,9 +130,10 @@ impl<'a> Preprocessor<'a> { } - _ if op_type == OpType::Keyword(KeywordType::Memory) => { + + OpType::Keyword(KeywordType::Memory) => { if rtokens.is_empty() { - lerror!(&token.loc, "Memory name not found, expected {} but found nothing", TokenType::String.human()); + lerror!(&op.loc, "Memory name not found, expected {} but found nothing", TokenType::String.human()); return Err(eyre!("")); } @@ -159,19 +163,20 @@ impl<'a> Preprocessor<'a> { if res.len() != 1 { - lerror!(&token.loc, "Expected 1 number, got {:?}", res); + lerror!(&op.loc, "Expected 1 number, got {:?}", res); return Err(eyre!("")); } - token.value = res[0]; - token.addr = Some(self.memories.len()); - program.push(token.clone()); + op.value = res[0]; + op.addr = Some(self.memories.len()); + program.push(op.clone()); - self.memories.insert(name.text, Memory { loc: token.loc, id: self.memories.len() }); + self.memories.insert(name.text, Memory { loc: op.loc, id: self.memories.len() }); } - _ if op_type == OpType::Keyword(KeywordType::Function) => { + + OpType::Keyword(KeywordType::Function) => { if rtokens.is_empty() { - lerror!(&token.loc, "Function name not found, expected {} but found nothing", TokenType::Word.human()); + lerror!(&op.loc, "Function name not found, expected {} but found nothing", TokenType::Word.human()); return Err(eyre!("")); } @@ -206,20 +211,85 @@ impl<'a> Preprocessor<'a> { self.is_word_available(&name, KeywordType::Function)?; - self.functions.insert(name.text.clone(), Function{ - loc: name.loc.clone(), - name: name.text.clone(), - }); + if f_inline { + let mut prog: Vec = Vec::new(); + let mut depth = -1; + while !rtokens.is_empty() { + let op = rtokens.pop().unwrap(); - let mut fn_def = token.clone(); - fn_def.typ = OpType::Keyword(KeywordType::FunctionDef); - fn_def.text = name.text; - // println!("{:?}", token); - program.push(fn_def); + match op.typ.clone() { + OpType::Instruction(i) => { + match i { + InstructionType::TypeAny | + InstructionType::TypeBool | + InstructionType::TypeInt | + InstructionType::TypePtr | + InstructionType::TypeStr | + InstructionType::With | + InstructionType::Returns | + InstructionType::TypeVoid => { + if depth >= 0 { + prog.push(op); + } + }, + _ => prog.push(op) + } + } + OpType::Keyword(k) => { + match k { + KeywordType::Inline | + KeywordType::Include => { + todo!("make error") + }, + KeywordType::FunctionThen => { + if depth >= 0 { + prog.push(op); + } + depth += 1; + }, + KeywordType::FunctionDone => { + if depth == 0 { + break; + } + + depth -= 1; + }, + _ => prog.push(op) + } + } + } + } + let mut pre = self.clone(); + pre.program = prog; + pre.preprocess()?; + prog = pre.get_ops(); + + self.functions.insert(name.text.clone(), Function{ + loc: name.loc.clone(), + name: name.text.clone(), + inline: true, + tokens: Some(prog) + }); + + } else { + self.functions.insert(name.text.clone(), Function{ + loc: name.loc.clone(), + name: name.text.clone(), + inline: false, + tokens: None + }); + + let mut fn_def = op.clone(); + fn_def.typ = OpType::Keyword(KeywordType::FunctionDef); + fn_def.text = name.text; + // println!("{:?}", token); + program.push(fn_def); + } } - _ if op_type == OpType::Keyword(KeywordType::Constant) => { + + OpType::Keyword(KeywordType::Constant) => { if rtokens.is_empty() { - lerror!(&token.loc, "Constant name not found, expected {} but found nothing", TokenType::Word.human()); + lerror!(&op.loc, "Constant name not found, expected {} but found nothing", TokenType::Word.human()); return Err(eyre!("")); } // println!("{token:?}"); @@ -263,7 +333,7 @@ impl<'a> Preprocessor<'a> { // println!("{:?}", self.constants); - let mut const_def = token.clone(); + let mut const_def = op.clone(); const_def.typ = OpType::Keyword(KeywordType::ConstantDef); const_def.text = name.text; @@ -271,14 +341,14 @@ impl<'a> Preprocessor<'a> { if item.tok_typ == TokenType::Int { const_def.value = item.value; } else { - lerror!(&token.loc, "For now only {:?} is allowed in constants", TokenType::Int); + lerror!(&op.loc, "For now only {:?} is allowed in constants", TokenType::Int); return Err(eyre!("")); } let posibly_end = rtokens.pop(); // println!("end: {posibly_end:?}"); if posibly_end.is_none() || posibly_end.unwrap().typ != OpType::Keyword(KeywordType::End) { - lerror!(&token.loc, "Constant was not closed with an 'end' instruction, expected 'end' but found nothing"); + lerror!(&op.loc, "Constant was not closed with an 'end' instruction, expected 'end' but found nothing"); return Err(eyre!("")); } // token.value = @@ -286,9 +356,17 @@ impl<'a> Preprocessor<'a> { program.push(const_def); } + OpType::Keyword(KeywordType::Inline) => { + if f_inline { + lerror!(&op.loc, "Function is already marked as inline, remove this inline Keyword"); + return Err(eyre!("")); + } else { + f_inline = true; + } + } + _ => { - - program.push(token); + program.push(op); } } } @@ -334,15 +412,18 @@ impl<'a> Preprocessor<'a> { if op.tok_typ == TokenType::Word { match op_type { OpType::Instruction(InstructionType::None) => { - let m = self.functions.get(&op.text); + let m = self.functions.get(&op.text.clone().replace('(', "__OP_PAREN__").replace(')', "__CL_PAREN__")); let mem = self.memories.get(&op.text); - let cons = self.constants.get(&op.text); + let cons = self.constants.get(&op.text.clone().replace('(', "__OP_PAREN__").replace(')', "__CL_PAREN__")); if let Some(m) = m { - // println!("------ FOUND FUNCTION {} -----------", m.name); - let mut t = op.clone(); - t.typ = OpType::Instruction(InstructionType::FnCall); - t.text = m.name.clone(); - program.push(t.clone()); + if m.inline { + program.append(&mut m.tokens.clone().unwrap()); + } else { + let mut t = op.clone(); + t.typ = OpType::Instruction(InstructionType::FnCall); + t.text = m.name.clone(); + program.push(t.clone()); + } // println!("##### {:?}", t); } else if let Some(mem) = mem { diff --git a/src/typechecker.rs b/src/typechecker.rs index a32c653..2716ded 100644 --- a/src/typechecker.rs +++ b/src/typechecker.rs @@ -62,6 +62,7 @@ pub fn typecheck(ops: Vec, args: &Args, init_types: Option> stack_pop(&mut stack, &op, &[Types::Bool])?; }, + KeywordType::FunctionDefInline | KeywordType::FunctionDef => { let name = op.text.clone(); @@ -177,6 +178,7 @@ pub fn typecheck(ops: Vec, args: &Args, init_types: Option> KeywordType::FunctionThen | KeywordType::FunctionDone | KeywordType::Function => unreachable!(), + KeywordType::Inline => (), } }, OpType::Instruction(instruction) => { diff --git a/test.mcl b/test.mcl index c2cfa73..c6336ff 100644 --- a/test.mcl +++ b/test.mcl @@ -1,5 +1,7 @@ -include "std.mcl" +// include "std.mcl" fn main with void returns void then - "hi\n" puts -done \ No newline at end of file + 69 test +done + +inline fn test with void returns void then _dbg_print done \ No newline at end of file