From 9c84033d3f8eb4ff350625ab37e39822e65d7e10 Mon Sep 17 00:00:00 2001 From: MCorange Date: Tue, 4 Apr 2023 17:24:58 +0300 Subject: [PATCH] functions --- include/io.mcl | 10 +- src/compile/linux_x86_64.rs | 25 +++- src/constants.rs | 22 ++-- src/interpret/linux_x86_64/mod.rs | 6 +- src/lexer.rs | 8 +- src/main.rs | 4 +- src/parser.rs | 36 ++++-- src/precompiler.rs | 15 ++- src/preprocessor.rs | 194 +++++++++++++----------------- src/typechecker.rs | 5 +- test.mcl | 9 +- 11 files changed, 177 insertions(+), 157 deletions(-) diff --git a/include/io.mcl b/include/io.mcl index 76b7ae5..3d7f05e 100644 --- a/include/io.mcl +++ b/include/io.mcl @@ -5,7 +5,7 @@ // @arg buff_ptr: Ptr - pointer to the buffer to write // @arg fd: Int - file descriptor // @ret Int -macro write +fn write do SYS_write syscall3 end @@ -15,7 +15,7 @@ end // @arg buff_ptr: Ptr - pointer to the buffer to write // @arg fd: Int - file descriptor // @ret Int -macro read +fn read do SYS_read syscall3 end @@ -25,7 +25,7 @@ end // @arg buff_size: Int - number of bytes to write // @arg buff_ptr: Ptr - pointer to the buffer to write // @ret NULL -macro puts +fn puts do STDOUT write drop end @@ -34,7 +34,7 @@ end // @arg buff_size: Int - number of bytes to write // @arg buff_ptr: Ptr - pointer to the buffer to write // @ret NULL -macro eputs +fn eputs do STDOUT write drop end @@ -44,7 +44,7 @@ end // args: [exit_code] // @arg exit_code: Int // @ret NULL/NEVER -macro exit +fn exit do SYS_exit syscall1 drop end diff --git a/src/compile/linux_x86_64.rs b/src/compile/linux_x86_64.rs index 286c170..2cb0b9c 100644 --- a/src/compile/linux_x86_64.rs +++ b/src/compile/linux_x86_64.rs @@ -69,11 +69,14 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ writeln!(writer, "global _start")?; writeln!(writer, "_start:")?; + writeln!(writer, " call func_main")?; + writeln!(writer, " jmp end")?; + let mut ti = 0; while ti < tokens.len() { let token = &tokens[ti]; - + println!("{:?}", token); writeln!(writer, "addr_{ti}:")?; match token.typ.clone() { // stack @@ -414,6 +417,16 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ InstructionType::CastBool => ti += 1, InstructionType::CastPtr => ti += 1, InstructionType::CastInt => ti += 1, + InstructionType::FnCall => { + writeln!(writer, " ;; -- FnCall")?; + writeln!(writer, " call func_{}", token.text)?; + ti += 1; + }, + InstructionType::Return => { + writeln!(writer, " ;; -- Return")?; + writeln!(writer, " ret")?; + ti += 1; + }, } } @@ -456,14 +469,18 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ memories.push((token.addr.unwrap(), token.value)); ti += 1; } - KeywordType::Macro | - KeywordType::Include - => unreachable!() + KeywordType::Include => unreachable!(), + KeywordType::Constant => todo!(), + KeywordType::Function => { + writeln!(writer, "func_{}:", token.text)?; + ti += 1; + }, } } } } writeln!(writer, "addr_{ti}:")?; + writeln!(writer, "end:")?; writeln!(writer, " mov rax, 60")?; writeln!(writer, " mov rdi, 0")?; writeln!(writer, " syscall")?; diff --git a/src/constants.rs b/src/constants.rs index d4f2cf2..cc08dbb 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -54,6 +54,8 @@ pub enum InstructionType { CastPtr, CastInt, + FnCall, + Return, MemUse, None // Used for macros and any other non built in word definitions @@ -65,9 +67,10 @@ pub enum KeywordType { End, While, Do, - Macro, Include, - Memory + Memory, + Constant, + Function } #[derive(Debug, Clone, PartialEq)] @@ -79,6 +82,7 @@ pub enum OpType { #[derive(Debug, Clone)] pub struct Operator{ pub typ: OpType, + pub tok_typ: TokenType, pub value: usize, pub text: String, //? only used for OpType::PushStr pub addr: Option, //? only used for OpType::PushStr @@ -87,14 +91,15 @@ pub struct Operator{ } impl Operator { - pub fn new(typ: OpType, value: usize, text: String, file: String, row: usize, col: usize) -> Self { + pub fn new(typ: OpType, tok_typ: TokenType, value: usize, text: String, file: String, row: usize, col: usize) -> Self { Self { typ, value, jmp: 0, addr: None, text, - loc: (file, row, col) + loc: (file, row, col), + tok_typ, } } pub fn set_addr(mut self, addr: usize) -> Self { @@ -151,6 +156,8 @@ impl OpType { InstructionType::CastInt => "cast(int)", InstructionType::MemUse => "MemUse", InstructionType::None => "None", + InstructionType::FnCall => "Function Call", + InstructionType::Return => "return", } } OpType::Keyword(keyword) => { @@ -160,9 +167,10 @@ impl OpType { KeywordType::End => "end", KeywordType::While => "while", KeywordType::Do => "do", - KeywordType::Macro => "macro", KeywordType::Include => "include", - KeywordType::Memory => "memory" + KeywordType::Memory => "memory", + KeywordType::Function => "fn", + KeywordType::Constant => "const", } } @@ -179,7 +187,7 @@ pub struct Token { pub typ: TokenType, pub value: Option, //* only used for Memories pub addr: Option, //* only used for Memories - pub op_typ: InstructionType //* only used for Memories + pub op_typ: OpType //* only used for Memories } #[derive(Debug, Clone, PartialEq, Copy)] diff --git a/src/interpret/linux_x86_64/mod.rs b/src/interpret/linux_x86_64/mod.rs index 8052461..51107c0 100644 --- a/src/interpret/linux_x86_64/mod.rs +++ b/src/interpret/linux_x86_64/mod.rs @@ -298,6 +298,8 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result{ InstructionType::CastPtr => ti += 1, InstructionType::CastInt => ti += 1, InstructionType::None => unreachable!(), + InstructionType::FnCall => todo!(), + InstructionType::Return => todo!(), } } @@ -331,7 +333,9 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result{ memories.insert(token.addr.unwrap(), token.value); ti += 1; }, - KeywordType::Macro | KeywordType::Include => unreachable!(), + KeywordType::Include => unreachable!(), + KeywordType::Constant => todo!(), + KeywordType::Function => todo!(), } } diff --git a/src/lexer.rs b/src/lexer.rs index 8c39140..7c36c3b 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -89,7 +89,7 @@ fn lex_line(text: &str) -> Vec<(usize, String, TokenType)> { tokens } -pub fn lex + std::marker::Copy>(code: &str, file: S, args: &Args, preprocessing: bool) -> Result> { +pub fn lex + std::marker::Copy>(code: &str, file: S, args: &Args) -> Result> { let lines: Vec<(usize, &str)> = code .split(['\n', '\r']) .enumerate() @@ -111,7 +111,7 @@ pub fn lex + std::marker::Copy>(code: &str, file: S, args: &Args typ: tok_type, value: None, addr: None, - op_typ: crate::constants::InstructionType::None + op_typ: crate::constants::OpType::Instruction(crate::constants::InstructionType::None) }; tokens.push(t); } @@ -121,9 +121,7 @@ pub fn lex + std::marker::Copy>(code: &str, file: S, args: &Args // for token in tokens.clone() { // println!("tok: {:?}", token.text); // } - if preprocessing { - (tokens, _) = preprocess(tokens, args)?; - } + Ok(tokens) } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c85c814..52f7e55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -70,14 +70,14 @@ fn main() { return; }; - let Ok(tokens) = lexer::lex(&code, &args.in_file, &args, true) else { + let Ok(tokens) = lexer::lex(&code, &args.in_file, &args) else { error!("Lexing failed, exiting!"); return; }; let mut parser = parser::Parser::new(tokens); - let Ok(tokens) = parser.parse() else { + let Ok(tokens) = parser.parse(&args) else { error!("Parsing failed, exiting!"); return; }; diff --git a/src/parser.rs b/src/parser.rs index 243d3da..f4b21c4 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -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}, lerror, preprocessor::preprocess, Args}; use color_eyre::Result; use eyre::eyre; @@ -10,6 +10,7 @@ pub fn cross_ref(mut program: Vec) -> Result> { let op = &program.clone()[ip]; match op.typ { OpType::Keyword(KeywordType::If) | + OpType::Keyword(KeywordType::Function) | OpType::Keyword(KeywordType::While) => { stack.push(ip); } @@ -36,6 +37,9 @@ pub fn cross_ref(mut program: Vec) -> Result> { } else if program[block_ip].typ == OpType::Keyword(KeywordType::Do) { program[ip].jmp = program[block_ip].jmp; program[block_ip].jmp = ip + 1; + } else if program[block_ip].typ == OpType::Keyword(KeywordType::Function) { + program[ip].typ = OpType::Instruction(InstructionType::Return); + program[block_ip].typ = OpType::Keyword(KeywordType::Do); } else { lerror!(&op.clone().loc,"'end' can only close 'if' blocks"); return Err(eyre!("")); @@ -43,8 +47,14 @@ pub fn cross_ref(mut program: Vec) -> Result> { } OpType::Keyword(KeywordType::Do) => { - let while_ip = stack.pop().unwrap(); - program[ip].jmp = while_ip; + let block_ip = stack.pop().unwrap(); + + if program[block_ip].typ == OpType::Keyword(KeywordType::Function) { + program[ip].typ = OpType::Keyword(KeywordType::Function); + } + + program[ip].jmp = block_ip; + // println!("{}", block_ip); stack.push(ip); } _ => () @@ -71,7 +81,7 @@ impl Parser { } } - pub fn parse(&mut self) -> Result> { + pub fn parse(&mut self, args: &Args) -> Result> { let mut tokens = Vec::new(); for token in &self.tokens { @@ -81,19 +91,19 @@ impl Parser { let pos = (token.file.clone(), token.line, token.col); match token.typ { TokenType::Word => { - let word_type = if token.op_typ == InstructionType::MemUse { + let word_type = if token.op_typ == OpType::Instruction(InstructionType::MemUse) { OpType::Instruction(InstructionType::MemUse) } else { lookup_word(&token.text, &pos) }; - tokens.push(Operator::new(word_type, token.value.unwrap_or(0), token.text.clone(), token.file.clone(), token.line, token.col).set_addr(token.addr.unwrap_or(0))); + tokens.push(Operator::new(word_type, token.typ, token.value.unwrap_or(0), token.text.clone(), token.file.clone(), token.line, token.col).set_addr(token.addr.unwrap_or(0))); }, TokenType::Int => {// negative numbers not yet implemented - tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.text.parse::()?, String::new(), token.file.clone(), token.line, token.col)); + tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.typ, token.text.parse::()?, String::new(), token.file.clone(), token.line, token.col)); }, TokenType::String => { - tokens.push(Operator::new(OpType::Instruction(InstructionType::PushStr), 0, token.text.clone(), token.file.clone(), token.line, token.col)); + tokens.push(Operator::new(OpType::Instruction(InstructionType::PushStr), token.typ, 0, token.text.clone(), token.file.clone(), token.line, token.col)); } TokenType::Char => { let c = token.text.clone(); @@ -102,7 +112,7 @@ impl Parser { return Err(eyre!("")); } - tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.text.chars().next().unwrap() as usize, String::new(), token.file.clone(), token.line, token.col)); + tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.typ, token.text.chars().next().unwrap() as usize, String::new(), token.file.clone(), token.line, token.col)); } }; @@ -110,7 +120,10 @@ impl Parser { //"print" => tokens.push(Operator::new(OpType::Print, 0, token.file.clone(), token.line, token.col)), } - cross_ref(tokens) + + tokens = cross_ref(tokens.clone())?; + let t = preprocess(tokens, args)?; + Ok(t.0) } } @@ -172,9 +185,10 @@ pub fn lookup_word>(s: &str, _pos: P) -> OpType { "end" => OpType::Keyword(KeywordType::End), "while" => OpType::Keyword(KeywordType::While), "do" => OpType::Keyword(KeywordType::Do), - "macro" => OpType::Keyword(KeywordType::Macro), "include" => OpType::Keyword(KeywordType::Include), "memory" => OpType::Keyword(KeywordType::Memory), + "const" => OpType::Keyword(KeywordType::Constant), + "fn" => OpType::Keyword(KeywordType::Function), _ => OpType::Instruction(InstructionType::None) } diff --git a/src/precompiler.rs b/src/precompiler.rs index 7b60624..b8bffa0 100644 --- a/src/precompiler.rs +++ b/src/precompiler.rs @@ -2,7 +2,7 @@ use color_eyre::Result; use eyre::eyre; -use crate::{constants::{Token, OpType, InstructionType, Loc}, parser::lookup_word, lerror}; +use crate::{constants::{Token, OpType, InstructionType, Loc, Operator}, parser::lookup_word, lerror}; fn stack_pop(stack: &mut Vec, loc: &Loc) -> Result { if let Some(i) = stack.pop() { Ok(i) } else { @@ -11,21 +11,20 @@ fn stack_pop(stack: &mut Vec, loc: &Loc) -> Result { } } -pub fn precompile(tokens: &Vec) -> Result>{ +pub fn precompile(tokens: &Vec) -> Result>{ let mut stack: Vec = Vec::new(); for token in tokens.iter() { - let typ = lookup_word(&token.text, &token.loc()); - match typ { + match token.typ.clone() { OpType::Instruction(i) => { - let loc = token.loc(); + let loc = token.loc.clone(); match i { InstructionType::PushInt => { if let Ok(i) = token.text.parse::() { stack.push(i); } else { - lerror!(&token.loc(), "Bad number"); + lerror!(&token.loc, "Bad number"); return Err(eyre!("")); } }, @@ -136,14 +135,14 @@ pub fn precompile(tokens: &Vec) -> Result>{ stack.push(b); } _ => { - lerror!(&token.loc(), "Unsupported precompiler instruction {:?}", i); + lerror!(&token.loc, "Unsupported precompiler instruction {:?}", i); dbg!(tokens); return Err(eyre!("")); } } } _ => { - lerror!(&token.loc(), "Unsupported precompiler keyword {:?}", typ); + lerror!(&token.loc, "Unsupported precompiler keyword {:?}", token.typ); dbg!(tokens); return Err(eyre!("")); } diff --git a/src/preprocessor.rs b/src/preprocessor.rs index 29aa55f..5754bf4 100644 --- a/src/preprocessor.rs +++ b/src/preprocessor.rs @@ -4,26 +4,26 @@ use std::path::{PathBuf, Path}; 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, Operator}; use crate::lexer::lex; use crate::precompiler::precompile; -use crate::{lerror, lnote, Args, warn, linfo}; +use crate::{lerror, lnote, Args, warn, linfo, parser}; use crate::parser::lookup_word; #[derive(Debug)] -pub struct Macro { +pub struct Function { pub loc: Loc, - pub tokens: Vec + pub name: String } -type Macros = HashMap; +type Functions = HashMap; type Memories = HashMap; -pub fn preprocess(tokens: Vec, args: &Args) -> Result<(Vec, Macros)>{ +pub fn preprocess(tokens: Vec, args: &Args) -> Result<(Vec, Functions)>{ - let mut program: Vec = Vec::new(); - let mut macros: Macros = HashMap::new(); + let mut program: Vec = Vec::new(); + let mut functions: Functions = HashMap::new(); let mut memories: Memories = HashMap::new(); let mut rtokens = tokens; @@ -31,74 +31,20 @@ pub fn preprocess(tokens: Vec, args: &Args) -> Result<(Vec, Macros while !rtokens.is_empty() { let mut token = rtokens.pop().unwrap(); - let op_type = lookup_word(&token.text, &token.loc()); + let op_type = token.typ.clone(); match token.clone() { - _ if op_type == OpType::Keyword(KeywordType::Macro) => { - if rtokens.is_empty(){ - lerror!(&token.loc(), "Macro name not found, expected {} but found nothing", TokenType::Word.human()); - return Err(eyre!("")); - } - let macro_name = rtokens.pop().unwrap(); - - if macro_name.typ != TokenType::Word { - lerror!(¯o_name.loc(), "Bad macro name, expected {} but found {}", TokenType::Word.human(), macro_name.typ.human()); - return Err(eyre!("")); - } - let word = lookup_word(¯o_name.text, ¯o_name.loc()); - if word != OpType::Instruction(InstructionType::None) { - lerror!(¯o_name.loc(), "Macro name cannot be a built in word, got '{}'", word.human()); - return Err(eyre!("")); - } - - if macros.get(¯o_name.text.clone()).is_some() && crate::constants::ALLOW_MACRO_REDEFINITION { - lerror!(¯o_name.loc(), "Macro redefinition is not allowed"); - lnote!(¯os.get(¯o_name.text).unwrap().loc, "First definition here"); - return Err(eyre!("")); - } - - let mut macr = Macro{ loc: macro_name.loc(), tokens: Vec::new() }; - let mut reprocess = false; - let mut depth = 0; - while !rtokens.is_empty() { - let t = rtokens.pop().unwrap(); - let typ = lookup_word(&t.text, &t.loc()); - if typ == OpType::Keyword(KeywordType::End) && depth == 0 { - break; - } else if typ == OpType::Keyword(KeywordType::End) && depth != 0 { - depth -= 1; - macr.tokens.push(t); - } else if typ == OpType::Keyword(KeywordType::If) || - typ == OpType::Keyword(KeywordType::Do) { - macr.tokens.push(t); - depth += 1; - } else if typ == OpType::Keyword(KeywordType::Macro) { - reprocess = true; - macr.tokens.push(t); - depth += 1; - } else { - macr.tokens.push(t); - } - } - - if reprocess { - (macr.tokens, macros) = preprocess(macr.tokens, args)?; - } - - macros.insert(macro_name.text, macr); - - - } + _ if 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!(&token.loc, "Include path not found, expected {} but found nothing", TokenType::String.human()); return Err(eyre!("")); } let include_path = rtokens.pop().unwrap(); - if include_path.typ != TokenType::String { - lerror!(&include_path.loc(), "Bad include path, expected {} but found {}", TokenType::String.human(), include_path.typ.human()); + if include_path.tok_typ != TokenType::String { + lerror!(&include_path.loc, "Bad include path, expected {} but found {}", TokenType::String.human(), include_path.typ.human()); return Err(eyre!("")); } @@ -108,7 +54,7 @@ pub fn preprocess(tokens: Vec, args: &Args) -> Result<(Vec, Macros let mut include_code = String::new(); if include_path.text.chars().collect::>()[0] == '.' { - let p = Path::new(include_path.file.as_str()); + let p = Path::new(include_path.loc.0.as_str()); let p = p.parent().unwrap(); let p = p.join(&include_path.text); include_code = std::fs::read_to_string(p)?; @@ -125,11 +71,12 @@ pub fn preprocess(tokens: Vec, args: &Args) -> Result<(Vec, Macros } if include_code.is_empty() { - lerror!(&include_path.loc(), "Include file in path '{}' was not found or is empty", include_path.text); + lerror!(&include_path.loc, "Include file in path '{}' was not found or is empty", include_path.text); return Err(eyre!("")); } - - let mut code = lex(&include_code, &include_path.text, args, false)?; + let code = lex(&include_code, &args.in_file, &args)?; + let mut p = parser::Parser::new(code); + let mut code = p.parse(args)?; code.reverse(); rtokens.append(&mut code); @@ -137,30 +84,30 @@ pub fn preprocess(tokens: Vec, args: &Args) -> Result<(Vec, Macros } _ if op_type == OpType::Keyword(KeywordType::Memory) => { if rtokens.is_empty() { - lerror!(&token.loc(), "Memory name not found, expected {} but found nothing", TokenType::String.human()); + lerror!(&token.loc, "Memory name not found, expected {} but found nothing", TokenType::String.human()); return Err(eyre!("")); } let memory_name = rtokens.pop().unwrap(); - if memory_name.typ != TokenType::Word { - lerror!(&memory_name.loc(), "Bad memory name, expected {} but found {}", TokenType::Word.human(), memory_name.typ.human()); + if memory_name.tok_typ != TokenType::Word { + lerror!(&memory_name.loc, "Bad memory name, expected {} but found {}", TokenType::Word.human(), memory_name.typ.human()); return Err(eyre!("")); } - if macros.get(&memory_name.text).is_some() { - lerror!(&memory_name.loc(), "Memory name cannot replace macro name, got {}", memory_name.text); - let m = macros.get(&memory_name.text).unwrap(); - linfo!(&m.loc, "Macro found here"); + if functions.get(&memory_name.text).is_some() { + lerror!(&memory_name.loc, "Memory name cannot replace function name, got {}", memory_name.text); + let m = functions.get(&memory_name.text).unwrap(); + linfo!(&m.loc, "Function found here"); return Err(eyre!("")); } - let mut code: Vec = Vec::new(); + let mut code: Vec = Vec::new(); let mut depth = 0; while !rtokens.is_empty() { let t = rtokens.pop().unwrap(); - let typ = lookup_word(&t.text, &t.loc()); + let typ = t.typ.clone(); if typ == OpType::Keyword(KeywordType::End) && depth == 0 { break; } else if typ == OpType::Keyword(KeywordType::End) && depth != 0 { @@ -176,17 +123,52 @@ pub fn preprocess(tokens: Vec, args: &Args) -> Result<(Vec, Macros let res = precompile(&code)?; if res.len() != 1 { - lerror!(&token.loc(), "Expected 1 number, got {:?}", res); + lerror!(&token.loc, "Expected 1 number, got {:?}", res); return Err(eyre!("")); } - token.value = Some(res[0]); + token.value = res[0]; token.addr = Some(memories.len()); program.push(token); memories.insert(memory_name.text, memories.len()); } + _ if op_type == OpType::Keyword(KeywordType::Function) => { + if rtokens.is_empty() { + lerror!(&token.loc, "Function name not found, expected {} but found nothing", TokenType::Word.human()); + return Err(eyre!("")); + } + + let function_name = rtokens.pop().unwrap(); + + if function_name.tok_typ != TokenType::Word { + lerror!(&function_name.loc, "Bad Function name, expected {} but found {}", TokenType::Word.human(), function_name.typ.human()); + return Err(eyre!("")); + } + + if memories.get(&function_name.text).is_some() { + lerror!(&function_name.loc, "Function name cannot replace memory name, got {}", function_name.text); + return Err(eyre!("")); + } + + if functions.get(&function_name.text).is_some() { + lerror!(&function_name.loc, "Functions cannot be redefined, got {}", function_name.text); + return Err(eyre!("")); + } + + functions.insert(function_name.text.clone(), Function{ + loc: function_name.loc.clone(), + name: function_name.text.clone(), + }); + token.text = function_name.text; + rtokens.pop(); + program.push(token); + } + _ => { + if op_type == OpType::Keyword(KeywordType::Do) { + println!("{:?}", token); + } program.push(token); } } @@ -196,8 +178,8 @@ pub fn preprocess(tokens: Vec, args: &Args) -> Result<(Vec, Macros //* i wanna kms let mut times = 0; while program.iter().map(|f| { - if f.typ == TokenType::Word && f.op_typ != InstructionType::MemUse { - lookup_word(&f.text, &f.loc()) + if f.tok_typ == TokenType::Word && f.typ != OpType::Instruction(InstructionType::FnCall) && f.typ != OpType::Instruction(InstructionType::MemUse){ + lookup_word(&f.text, &f.loc) } else { OpType::Instruction(InstructionType::PushInt) // i hate myself, this is a randomly picked optype so its happy and works } @@ -208,60 +190,56 @@ pub fn preprocess(tokens: Vec, args: &Args) -> Result<(Vec, Macros warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it"); break } - program = expand(program, ¯os, &memories)?; + program = expand(program, &functions, &memories)?; times += 1; } - Ok((program, macros)) + Ok((program, functions)) } -pub fn expand(tokens: Vec, macros: &Macros, mems: &Memories) -> Result> { - let mut program: Vec = Vec::new(); +pub fn expand(tokens: Vec, funcs: &Functions, mems: &Memories) -> Result> { + let mut program: Vec = Vec::new(); let mut rtokens = tokens.clone(); rtokens.reverse(); while !rtokens.is_empty() { let op = rtokens.pop().unwrap(); - let op_type = lookup_word(&op.text, &op.loc()); - if op.typ == TokenType::Word { + let op_type = op.typ.clone(); + if op.tok_typ.clone() == TokenType::Word { match op_type { OpType::Instruction(InstructionType::None) => { - let m = macros.get(&op.text); + let m = funcs.get(&op.text); let mem = mems.get(&op.text); if let Some(m) = m { - // println!("{:#?}", macros); - let mut toks = m.tokens.clone(); - // if toks.iter().map(|t| { - // let w = lookup_word(&t.text, &t.loc()); - // w == OpType::Keyword(KeywordType::Macro) - // }).collect::>().contains(&true) { - // println!("yas"); - // toks = preprocess(toks, args)?; - // } - program.append(&mut toks); - // println!("{:?}", program); + let mut t = op.clone(); + t.typ = OpType::Instruction(InstructionType::FnCall); + t.text = m.name.clone(); + program.push(t); } else if let Some(mem) = mem { - let mut t = op; + let mut t = op.clone(); t.addr = Some(*mem); - t.op_typ = InstructionType::MemUse; + t.typ = OpType::Instruction(InstructionType::MemUse); program.push(t); } else { - lerror!(&op.loc(), "Unknown word '{}'", op.text.clone()); + lerror!(&op.loc, "expand: Unknown word '{}'", op.text.clone()); return Err(eyre!("")); } } _ => { - program.push(op); + program.push(op.clone()); } } } else { - program.push(op); + program.push(op.clone()); + } + + if op.typ == OpType::Keyword(KeywordType::Do) { + println!("expand: {:?}", op); } - } diff --git a/src/typechecker.rs b/src/typechecker.rs index 5fd36c7..3647bbb 100644 --- a/src/typechecker.rs +++ b/src/typechecker.rs @@ -27,8 +27,9 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result>{ KeywordType::Else | KeywordType::End | KeywordType::While | - KeywordType::Macro | + KeywordType::Function | KeywordType::Include | + KeywordType::Constant | KeywordType::Memory => (), } }, @@ -235,6 +236,8 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result>{ InstructionType::MemUse => { stack.push(Types::Ptr); }, + InstructionType::FnCall | + InstructionType::Return | InstructionType::None => {}, } }, diff --git a/test.mcl b/test.mcl index e20706d..956debb 100644 --- a/test.mcl +++ b/test.mcl @@ -1,8 +1,7 @@ -include "compat.mcl" -__compat__ -memory m 10 end +include "std.mcl" -m 69 @8 +fn main do +"henlo" puts -m load8 print \ No newline at end of file +end