implemented inline functions

This commit is contained in:
MCorange 2023-04-13 02:39:21 +03:00
parent b327756f4d
commit c8547af24c
8 changed files with 149 additions and 54 deletions

View File

@ -92,11 +92,12 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
writeln!(writer, " ;; -- {:?}", token.typ)?; writeln!(writer, " ;; -- {:?}", token.typ)?;
} }
} else { } else {
if ti > 0 {
if ti != 0 && tokens[ti-1].typ == OpType::Keyword(KeywordType::Else) || if tokens[ti-1].typ == OpType::Keyword(KeywordType::Else) ||
tokens[ti-1].typ == OpType::Keyword(KeywordType::End){ 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) { if ti + 1 < tokens.len() && tokens[ti+1].typ == OpType::Keyword(KeywordType::End) {
writeln!(writer, "addr_{ti}:")?; writeln!(writer, "addr_{ti}:")?;
@ -496,7 +497,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " mov qword [rbp], rbx")?; writeln!(writer, " mov qword [rbp], rbx")?;
writeln!(writer, " add rbp, 8")?; 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; ti += 1;
}, },
KeywordType::FunctionDone => { KeywordType::FunctionDone => {
@ -509,7 +510,9 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
KeywordType::FunctionThen => ti += 1, KeywordType::FunctionThen => ti += 1,
KeywordType::Function | KeywordType::Function |
KeywordType::Include | KeywordType::Include |
KeywordType::FunctionDefInline |
KeywordType::Constant => unreachable!(), KeywordType::Constant => unreachable!(),
KeywordType::Inline => todo!(),
} }
} }
} }

View File

@ -23,5 +23,6 @@ pub struct Memory {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Function { pub struct Function {
pub loc: Loc, pub loc: Loc,
pub name: String pub name: String,
pub exter: bool,
} }

View File

@ -84,8 +84,10 @@ pub enum KeywordType {
ConstantDef, ConstantDef,
Function, Function,
FunctionDef, FunctionDef,
FunctionDefInline,
FunctionThen, FunctionThen,
FunctionDone FunctionDone,
Inline
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -198,7 +200,9 @@ impl OpType {
KeywordType::FunctionThen => "then", KeywordType::FunctionThen => "then",
KeywordType::FunctionDone => "done", KeywordType::FunctionDone => "done",
KeywordType::ConstantDef => "constant Definition (internal)", KeywordType::ConstantDef => "constant Definition (internal)",
KeywordType::FunctionDef => "function definition (internal)" KeywordType::FunctionDef => "function definition (internal)",
KeywordType::FunctionDefInline => "inline function definition (internal)",
KeywordType::Inline => "inline"
} }
} }

View File

@ -362,6 +362,7 @@ pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
KeywordType::While | //* exept this one, this one should just skip over KeywordType::While | //* exept this one, this one should just skip over
KeywordType::Memory | KeywordType::Memory |
KeywordType::FunctionDef | KeywordType::FunctionDef |
KeywordType::FunctionDefInline |
KeywordType::ConstantDef => { KeywordType::ConstantDef => {
//? Disabled since we now pre run the whole program //? 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 }); // 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<i32>{
KeywordType::FunctionThen => ip += 1, KeywordType::FunctionThen => ip += 1,
KeywordType::Constant | KeywordType::Constant |
KeywordType::Function | KeywordType::Function |
KeywordType::Inline |
KeywordType::Include => unreachable!(), KeywordType::Include => unreachable!(),
} }
} }
@ -407,6 +409,7 @@ pub fn pre_run(ops: &[Operator]) -> Defineds {
OpType::Keyword(KeywordType::Memory) => { OpType::Keyword(KeywordType::Memory) => {
defineds.memories.insert(op.addr.unwrap(), Memory { size: op.value, loc: op.loc.clone(), id: op.addr.unwrap() }); defineds.memories.insert(op.addr.unwrap(), Memory { size: op.value, loc: op.loc.clone(), id: op.addr.unwrap() });
}, },
OpType::Keyword(KeywordType::FunctionDefInline) |
OpType::Keyword(KeywordType::FunctionDef) => { OpType::Keyword(KeywordType::FunctionDef) => {
defineds.functions.insert(op.text.clone(), Function { loc: op.loc.clone(), name: op.text.clone(), id: ip }); defineds.functions.insert(op.text.clone(), Function { loc: op.loc.clone(), name: op.text.clone(), id: ip });
}, },

View File

@ -44,9 +44,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
program[ip].jmp = program[block_ip].jmp; program[ip].jmp = program[block_ip].jmp;
program[block_ip].jmp = ip + 1; program[block_ip].jmp = ip + 1;
} }
OpType::Keyword(KeywordType::FunctionThen) => {
program[ip].typ = OpType::Instruction(InstructionType::Return);
}
OpType::Keyword(KeywordType::Memory | KeywordType::Constant) => (), OpType::Keyword(KeywordType::Memory | KeywordType::Constant) => (),
a => { a => {
@ -208,6 +206,7 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
"fn" => OpType::Keyword(KeywordType::Function), "fn" => OpType::Keyword(KeywordType::Function),
"then" => OpType::Keyword(KeywordType::FunctionThen), "then" => OpType::Keyword(KeywordType::FunctionThen),
"done" => OpType::Keyword(KeywordType::FunctionDone), "done" => OpType::Keyword(KeywordType::FunctionDone),
"inline" => OpType::Keyword(KeywordType::Inline),
"return" => OpType::Instruction(InstructionType::Return), "return" => OpType::Instruction(InstructionType::Return),
"returns" => OpType::Instruction(InstructionType::Returns), "returns" => OpType::Instruction(InstructionType::Returns),
"bool" => OpType::Instruction(InstructionType::TypeBool), "bool" => OpType::Instruction(InstructionType::TypeBool),

View File

@ -17,7 +17,9 @@ use crate::parser::lookup_word;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Function { pub struct Function {
pub loc: Loc, pub loc: Loc,
pub name: String pub name: String,
pub inline: bool,
pub tokens: Option<Vec<Operator>>
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -62,20 +64,21 @@ impl<'a> Preprocessor<'a> {
pub fn preprocess(&mut self) -> Result<&mut 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::<Vec<Option<&Operator>>>()); // println!("pre: has do tokens: {:?}", self.program.iter().map(|t| if t.typ == OpType::Keyword(KeywordType::Do) {Some(t)} else {None} ).collect::<Vec<Option<&Operator>>>());
let mut f_inline = false;
let mut f_extern = false;
let mut program: Vec<Operator> = Vec::new(); let mut program: Vec<Operator> = Vec::new();
let mut rtokens = self.program.clone(); let mut rtokens = self.program.clone();
rtokens.reverse(); rtokens.reverse();
while !rtokens.is_empty() { while !rtokens.is_empty() {
let mut token = rtokens.pop().unwrap(); let mut op = rtokens.pop().unwrap();
// println!("{token:?}"); // println!("{token:?}");
let op_type = token.typ.clone(); let op_type = op.typ.clone();
match token.clone() { match op_type {
OpType::Keyword(KeywordType::Include) => {
_ if op_type == OpType::Keyword(KeywordType::Include) => {
if rtokens.is_empty() { 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!("")); 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() { 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!("")); return Err(eyre!(""));
} }
@ -159,19 +163,20 @@ impl<'a> Preprocessor<'a> {
if res.len() != 1 { if res.len() != 1 {
lerror!(&token.loc, "Expected 1 number, got {:?}", res); lerror!(&op.loc, "Expected 1 number, got {:?}", res);
return Err(eyre!("")); return Err(eyre!(""));
} }
token.value = res[0]; op.value = res[0];
token.addr = Some(self.memories.len()); op.addr = Some(self.memories.len());
program.push(token.clone()); 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() { 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!("")); return Err(eyre!(""));
} }
@ -206,20 +211,85 @@ impl<'a> Preprocessor<'a> {
self.is_word_available(&name, KeywordType::Function)?; self.is_word_available(&name, KeywordType::Function)?;
if f_inline {
let mut prog: Vec<Operator> = Vec::new();
let mut depth = -1;
while !rtokens.is_empty() {
let op = rtokens.pop().unwrap();
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{ self.functions.insert(name.text.clone(), Function{
loc: name.loc.clone(), loc: name.loc.clone(),
name: name.text.clone(), name: name.text.clone(),
inline: true,
tokens: Some(prog)
}); });
let mut fn_def = token.clone(); } 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.typ = OpType::Keyword(KeywordType::FunctionDef);
fn_def.text = name.text; fn_def.text = name.text;
// println!("{:?}", token); // println!("{:?}", token);
program.push(fn_def); program.push(fn_def);
} }
_ if op_type == OpType::Keyword(KeywordType::Constant) => { }
OpType::Keyword(KeywordType::Constant) => {
if rtokens.is_empty() { 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!("")); return Err(eyre!(""));
} }
// println!("{token:?}"); // println!("{token:?}");
@ -263,7 +333,7 @@ impl<'a> Preprocessor<'a> {
// println!("{:?}", self.constants); // println!("{:?}", self.constants);
let mut const_def = token.clone(); let mut const_def = op.clone();
const_def.typ = OpType::Keyword(KeywordType::ConstantDef); const_def.typ = OpType::Keyword(KeywordType::ConstantDef);
const_def.text = name.text; const_def.text = name.text;
@ -271,14 +341,14 @@ impl<'a> Preprocessor<'a> {
if item.tok_typ == TokenType::Int { if item.tok_typ == TokenType::Int {
const_def.value = item.value; const_def.value = item.value;
} else { } 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!("")); return Err(eyre!(""));
} }
let posibly_end = rtokens.pop(); let posibly_end = rtokens.pop();
// println!("end: {posibly_end:?}"); // println!("end: {posibly_end:?}");
if posibly_end.is_none() || posibly_end.unwrap().typ != OpType::Keyword(KeywordType::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!("")); return Err(eyre!(""));
} }
// token.value = // token.value =
@ -286,9 +356,17 @@ impl<'a> Preprocessor<'a> {
program.push(const_def); 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 { if op.tok_typ == TokenType::Word {
match op_type { match op_type {
OpType::Instruction(InstructionType::None) => { 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 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 { if let Some(m) = m {
// println!("------ FOUND FUNCTION {} -----------", m.name); if m.inline {
program.append(&mut m.tokens.clone().unwrap());
} else {
let mut t = op.clone(); let mut t = op.clone();
t.typ = OpType::Instruction(InstructionType::FnCall); t.typ = OpType::Instruction(InstructionType::FnCall);
t.text = m.name.clone(); t.text = m.name.clone();
program.push(t.clone()); program.push(t.clone());
}
// println!("##### {:?}", t); // println!("##### {:?}", t);
} else if let Some(mem) = mem { } else if let Some(mem) = mem {

View File

@ -62,6 +62,7 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
stack_pop(&mut stack, &op, &[Types::Bool])?; stack_pop(&mut stack, &op, &[Types::Bool])?;
}, },
KeywordType::FunctionDefInline |
KeywordType::FunctionDef => { KeywordType::FunctionDef => {
let name = op.text.clone(); let name = op.text.clone();
@ -177,6 +178,7 @@ pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>
KeywordType::FunctionThen | KeywordType::FunctionThen |
KeywordType::FunctionDone | KeywordType::FunctionDone |
KeywordType::Function => unreachable!(), KeywordType::Function => unreachable!(),
KeywordType::Inline => (),
} }
}, },
OpType::Instruction(instruction) => { OpType::Instruction(instruction) => {

View File

@ -1,5 +1,7 @@
include "std.mcl" // include "std.mcl"
fn main with void returns void then fn main with void returns void then
"hi\n" puts 69 test
done done
inline fn test with void returns void then _dbg_print done