functions

This commit is contained in:
MCorange 2023-04-04 17:24:58 +03:00
parent 0a61a599c1
commit 9c84033d3f
11 changed files with 177 additions and 157 deletions

View File

@ -5,7 +5,7 @@
// @arg buff_ptr: Ptr - pointer to the buffer to write // @arg buff_ptr: Ptr - pointer to the buffer to write
// @arg fd: Int - file descriptor // @arg fd: Int - file descriptor
// @ret Int // @ret Int
macro write fn write do
SYS_write syscall3 SYS_write syscall3
end end
@ -15,7 +15,7 @@ end
// @arg buff_ptr: Ptr - pointer to the buffer to write // @arg buff_ptr: Ptr - pointer to the buffer to write
// @arg fd: Int - file descriptor // @arg fd: Int - file descriptor
// @ret Int // @ret Int
macro read fn read do
SYS_read syscall3 SYS_read syscall3
end end
@ -25,7 +25,7 @@ end
// @arg buff_size: Int - number of bytes to write // @arg buff_size: Int - number of bytes to write
// @arg buff_ptr: Ptr - pointer to the buffer to write // @arg buff_ptr: Ptr - pointer to the buffer to write
// @ret NULL // @ret NULL
macro puts fn puts do
STDOUT write drop STDOUT write drop
end end
@ -34,7 +34,7 @@ end
// @arg buff_size: Int - number of bytes to write // @arg buff_size: Int - number of bytes to write
// @arg buff_ptr: Ptr - pointer to the buffer to write // @arg buff_ptr: Ptr - pointer to the buffer to write
// @ret NULL // @ret NULL
macro eputs fn eputs do
STDOUT write drop STDOUT write drop
end end
@ -44,7 +44,7 @@ end
// args: [exit_code] // args: [exit_code]
// @arg exit_code: Int // @arg exit_code: Int
// @ret NULL/NEVER // @ret NULL/NEVER
macro exit fn exit do
SYS_exit syscall1 drop SYS_exit syscall1 drop
end end

View File

@ -69,11 +69,14 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
writeln!(writer, "global _start")?; writeln!(writer, "global _start")?;
writeln!(writer, "_start:")?; writeln!(writer, "_start:")?;
writeln!(writer, " call func_main")?;
writeln!(writer, " jmp end")?;
let mut ti = 0; let mut ti = 0;
while ti < tokens.len() { while ti < tokens.len() {
let token = &tokens[ti]; let token = &tokens[ti];
println!("{:?}", token);
writeln!(writer, "addr_{ti}:")?; writeln!(writer, "addr_{ti}:")?;
match token.typ.clone() { match token.typ.clone() {
// stack // stack
@ -414,6 +417,16 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
InstructionType::CastBool => ti += 1, InstructionType::CastBool => ti += 1,
InstructionType::CastPtr => ti += 1, InstructionType::CastPtr => ti += 1,
InstructionType::CastInt => 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<i32>{
memories.push((token.addr.unwrap(), token.value)); memories.push((token.addr.unwrap(), token.value));
ti += 1; ti += 1;
} }
KeywordType::Macro | KeywordType::Include => unreachable!(),
KeywordType::Include KeywordType::Constant => todo!(),
=> unreachable!() KeywordType::Function => {
writeln!(writer, "func_{}:", token.text)?;
ti += 1;
},
} }
} }
} }
} }
writeln!(writer, "addr_{ti}:")?; writeln!(writer, "addr_{ti}:")?;
writeln!(writer, "end:")?;
writeln!(writer, " mov rax, 60")?; writeln!(writer, " mov rax, 60")?;
writeln!(writer, " mov rdi, 0")?; writeln!(writer, " mov rdi, 0")?;
writeln!(writer, " syscall")?; writeln!(writer, " syscall")?;

View File

@ -54,6 +54,8 @@ pub enum InstructionType {
CastPtr, CastPtr,
CastInt, CastInt,
FnCall,
Return,
MemUse, MemUse,
None // Used for macros and any other non built in word definitions None // Used for macros and any other non built in word definitions
@ -65,9 +67,10 @@ pub enum KeywordType {
End, End,
While, While,
Do, Do,
Macro,
Include, Include,
Memory Memory,
Constant,
Function
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -79,6 +82,7 @@ pub enum OpType {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Operator{ pub struct Operator{
pub typ: OpType, pub typ: OpType,
pub tok_typ: TokenType,
pub value: usize, pub value: usize,
pub text: String, //? only used for OpType::PushStr pub text: String, //? only used for OpType::PushStr
pub addr: Option<usize>, //? only used for OpType::PushStr pub addr: Option<usize>, //? only used for OpType::PushStr
@ -87,14 +91,15 @@ pub struct Operator{
} }
impl 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 { Self {
typ, typ,
value, value,
jmp: 0, jmp: 0,
addr: None, addr: None,
text, text,
loc: (file, row, col) loc: (file, row, col),
tok_typ,
} }
} }
pub fn set_addr(mut self, addr: usize) -> Self { pub fn set_addr(mut self, addr: usize) -> Self {
@ -151,6 +156,8 @@ impl OpType {
InstructionType::CastInt => "cast(int)", InstructionType::CastInt => "cast(int)",
InstructionType::MemUse => "MemUse", InstructionType::MemUse => "MemUse",
InstructionType::None => "None", InstructionType::None => "None",
InstructionType::FnCall => "Function Call",
InstructionType::Return => "return",
} }
} }
OpType::Keyword(keyword) => { OpType::Keyword(keyword) => {
@ -160,9 +167,10 @@ impl OpType {
KeywordType::End => "end", KeywordType::End => "end",
KeywordType::While => "while", KeywordType::While => "while",
KeywordType::Do => "do", KeywordType::Do => "do",
KeywordType::Macro => "macro",
KeywordType::Include => "include", 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 typ: TokenType,
pub value: Option<usize>, //* only used for Memories pub value: Option<usize>, //* only used for Memories
pub addr: Option<usize>, //* only used for Memories pub addr: Option<usize>, //* 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)] #[derive(Debug, Clone, PartialEq, Copy)]

View File

@ -298,6 +298,8 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
InstructionType::CastPtr => ti += 1, InstructionType::CastPtr => ti += 1,
InstructionType::CastInt => ti += 1, InstructionType::CastInt => ti += 1,
InstructionType::None => unreachable!(), InstructionType::None => unreachable!(),
InstructionType::FnCall => todo!(),
InstructionType::Return => todo!(),
} }
} }
@ -331,7 +333,9 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
memories.insert(token.addr.unwrap(), token.value); memories.insert(token.addr.unwrap(), token.value);
ti += 1; ti += 1;
}, },
KeywordType::Macro | KeywordType::Include => unreachable!(), KeywordType::Include => unreachable!(),
KeywordType::Constant => todo!(),
KeywordType::Function => todo!(),
} }
} }

View File

@ -89,7 +89,7 @@ fn lex_line(text: &str) -> Vec<(usize, String, TokenType)> {
tokens tokens
} }
pub fn lex<S: Into<String> + std::marker::Copy>(code: &str, file: S, args: &Args, preprocessing: bool) -> Result<Vec<Token>> { pub fn lex<S: Into<String> + std::marker::Copy>(code: &str, file: S, args: &Args) -> Result<Vec<Token>> {
let lines: Vec<(usize, &str)> = code let lines: Vec<(usize, &str)> = code
.split(['\n', '\r']) .split(['\n', '\r'])
.enumerate() .enumerate()
@ -111,7 +111,7 @@ pub fn lex<S: Into<String> + std::marker::Copy>(code: &str, file: S, args: &Args
typ: tok_type, typ: tok_type,
value: None, value: None,
addr: None, addr: None,
op_typ: crate::constants::InstructionType::None op_typ: crate::constants::OpType::Instruction(crate::constants::InstructionType::None)
}; };
tokens.push(t); tokens.push(t);
} }
@ -121,9 +121,7 @@ pub fn lex<S: Into<String> + std::marker::Copy>(code: &str, file: S, args: &Args
// for token in tokens.clone() { // for token in tokens.clone() {
// println!("tok: {:?}", token.text); // println!("tok: {:?}", token.text);
// } // }
if preprocessing {
(tokens, _) = preprocess(tokens, args)?;
}
Ok(tokens) Ok(tokens)
} }

View File

@ -70,14 +70,14 @@ fn main() {
return; 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!"); error!("Lexing failed, exiting!");
return; return;
}; };
let mut parser = parser::Parser::new(tokens); let mut parser = parser::Parser::new(tokens);
let Ok(tokens) = parser.parse() else { let Ok(tokens) = parser.parse(&args) else {
error!("Parsing failed, exiting!"); error!("Parsing failed, exiting!");
return; return;
}; };

View File

@ -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}, lerror, preprocessor::preprocess, Args};
use color_eyre::Result; use color_eyre::Result;
use eyre::eyre; use eyre::eyre;
@ -10,6 +10,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
let op = &program.clone()[ip]; let op = &program.clone()[ip];
match op.typ { match op.typ {
OpType::Keyword(KeywordType::If) | OpType::Keyword(KeywordType::If) |
OpType::Keyword(KeywordType::Function) |
OpType::Keyword(KeywordType::While) => { OpType::Keyword(KeywordType::While) => {
stack.push(ip); stack.push(ip);
} }
@ -36,6 +37,9 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
} else if program[block_ip].typ == OpType::Keyword(KeywordType::Do) { } else if program[block_ip].typ == OpType::Keyword(KeywordType::Do) {
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;
} 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 { } else {
lerror!(&op.clone().loc,"'end' can only close 'if' blocks"); lerror!(&op.clone().loc,"'end' can only close 'if' blocks");
return Err(eyre!("")); return Err(eyre!(""));
@ -43,8 +47,14 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
} }
OpType::Keyword(KeywordType::Do) => { OpType::Keyword(KeywordType::Do) => {
let while_ip = stack.pop().unwrap(); let block_ip = stack.pop().unwrap();
program[ip].jmp = while_ip;
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); stack.push(ip);
} }
_ => () _ => ()
@ -71,7 +81,7 @@ impl Parser {
} }
} }
pub fn parse(&mut self) -> Result<Vec<Operator>> { pub fn parse(&mut self, args: &Args) -> Result<Vec<Operator>> {
let mut tokens = Vec::new(); let mut tokens = Vec::new();
for token in &self.tokens { for token in &self.tokens {
@ -81,19 +91,19 @@ impl Parser {
let pos = (token.file.clone(), token.line, token.col); let pos = (token.file.clone(), token.line, token.col);
match token.typ { match token.typ {
TokenType::Word => { 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) OpType::Instruction(InstructionType::MemUse)
} else { } else {
lookup_word(&token.text, &pos) 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 TokenType::Int => {// negative numbers not yet implemented
tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.text.parse::<usize>()?, String::new(), token.file.clone(), token.line, token.col)); tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.typ, token.text.parse::<usize>()?, String::new(), token.file.clone(), token.line, token.col));
}, },
TokenType::String => { 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 => { TokenType::Char => {
let c = token.text.clone(); let c = token.text.clone();
@ -102,7 +112,7 @@ impl Parser {
return Err(eyre!("")); 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)), //"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<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
"end" => OpType::Keyword(KeywordType::End), "end" => OpType::Keyword(KeywordType::End),
"while" => OpType::Keyword(KeywordType::While), "while" => OpType::Keyword(KeywordType::While),
"do" => OpType::Keyword(KeywordType::Do), "do" => OpType::Keyword(KeywordType::Do),
"macro" => OpType::Keyword(KeywordType::Macro),
"include" => OpType::Keyword(KeywordType::Include), "include" => OpType::Keyword(KeywordType::Include),
"memory" => OpType::Keyword(KeywordType::Memory), "memory" => OpType::Keyword(KeywordType::Memory),
"const" => OpType::Keyword(KeywordType::Constant),
"fn" => OpType::Keyword(KeywordType::Function),
_ => OpType::Instruction(InstructionType::None) _ => OpType::Instruction(InstructionType::None)
} }

View File

@ -2,7 +2,7 @@
use color_eyre::Result; use color_eyre::Result;
use eyre::eyre; 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<usize>, loc: &Loc) -> Result<usize> { fn stack_pop(stack: &mut Vec<usize>, loc: &Loc) -> Result<usize> {
if let Some(i) = stack.pop() { Ok(i) } else { if let Some(i) = stack.pop() { Ok(i) } else {
@ -11,21 +11,20 @@ fn stack_pop(stack: &mut Vec<usize>, loc: &Loc) -> Result<usize> {
} }
} }
pub fn precompile(tokens: &Vec<Token>) -> Result<Vec<usize>>{ pub fn precompile(tokens: &Vec<Operator>) -> Result<Vec<usize>>{
let mut stack: Vec<usize> = Vec::new(); let mut stack: Vec<usize> = Vec::new();
for token in tokens.iter() { for token in tokens.iter() {
let typ = lookup_word(&token.text, &token.loc()); match token.typ.clone() {
match typ {
OpType::Instruction(i) => { OpType::Instruction(i) => {
let loc = token.loc(); let loc = token.loc.clone();
match i { match i {
InstructionType::PushInt => { InstructionType::PushInt => {
if let Ok(i) = token.text.parse::<usize>() { if let Ok(i) = token.text.parse::<usize>() {
stack.push(i); stack.push(i);
} else { } else {
lerror!(&token.loc(), "Bad number"); lerror!(&token.loc, "Bad number");
return Err(eyre!("")); return Err(eyre!(""));
} }
}, },
@ -136,14 +135,14 @@ pub fn precompile(tokens: &Vec<Token>) -> Result<Vec<usize>>{
stack.push(b); stack.push(b);
} }
_ => { _ => {
lerror!(&token.loc(), "Unsupported precompiler instruction {:?}", i); lerror!(&token.loc, "Unsupported precompiler instruction {:?}", i);
dbg!(tokens); dbg!(tokens);
return Err(eyre!("")); return Err(eyre!(""));
} }
} }
} }
_ => { _ => {
lerror!(&token.loc(), "Unsupported precompiler keyword {:?}", typ); lerror!(&token.loc, "Unsupported precompiler keyword {:?}", token.typ);
dbg!(tokens); dbg!(tokens);
return Err(eyre!("")); return Err(eyre!(""));
} }

View File

@ -4,26 +4,26 @@ use std::path::{PathBuf, Path};
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, Operator};
use crate::lexer::lex; use crate::lexer::lex;
use crate::precompiler::precompile; use crate::precompiler::precompile;
use crate::{lerror, lnote, Args, warn, linfo}; use crate::{lerror, lnote, Args, warn, linfo, parser};
use crate::parser::lookup_word; use crate::parser::lookup_word;
#[derive(Debug)] #[derive(Debug)]
pub struct Macro { pub struct Function {
pub loc: Loc, pub loc: Loc,
pub tokens: Vec<Token> pub name: String
} }
type Macros = HashMap<String, Macro>; type Functions = HashMap<String, Function>;
type Memories = HashMap<String, usize>; type Memories = HashMap<String, usize>;
pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<(Vec<Token>, Macros)>{ pub fn preprocess(tokens: Vec<Operator>, args: &Args) -> Result<(Vec<Operator>, Functions)>{
let mut program: Vec<Token> = Vec::new(); let mut program: Vec<Operator> = Vec::new();
let mut macros: Macros = HashMap::new(); let mut functions: Functions = HashMap::new();
let mut memories: Memories = HashMap::new(); let mut memories: Memories = HashMap::new();
let mut rtokens = tokens; let mut rtokens = tokens;
@ -31,74 +31,20 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<(Vec<Token>, Macros
while !rtokens.is_empty() { while !rtokens.is_empty() {
let mut token = rtokens.pop().unwrap(); let mut token = rtokens.pop().unwrap();
let op_type = lookup_word(&token.text, &token.loc()); let op_type = token.typ.clone();
match token.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!(&macro_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, &macro_name.loc());
if word != OpType::Instruction(InstructionType::None) {
lerror!(&macro_name.loc(), "Macro name cannot be a built in word, got '{}'", word.human());
return Err(eyre!(""));
}
if macros.get(&macro_name.text.clone()).is_some() && crate::constants::ALLOW_MACRO_REDEFINITION {
lerror!(&macro_name.loc(), "Macro redefinition is not allowed");
lnote!(&macros.get(&macro_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 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!(&token.loc, "Include path not found, expected {} but found nothing", TokenType::String.human());
return Err(eyre!("")); return Err(eyre!(""));
} }
let include_path = rtokens.pop().unwrap(); let include_path = rtokens.pop().unwrap();
if include_path.typ != TokenType::String { if include_path.tok_typ != TokenType::String {
lerror!(&include_path.loc(), "Bad include path, expected {} but found {}", TokenType::String.human(), include_path.typ.human()); lerror!(&include_path.loc, "Bad include path, expected {} but found {}", TokenType::String.human(), include_path.typ.human());
return Err(eyre!("")); return Err(eyre!(""));
} }
@ -108,7 +54,7 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<(Vec<Token>, Macros
let mut include_code = String::new(); let mut include_code = String::new();
if include_path.text.chars().collect::<Vec<char>>()[0] == '.' { if include_path.text.chars().collect::<Vec<char>>()[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.parent().unwrap();
let p = p.join(&include_path.text); let p = p.join(&include_path.text);
include_code = std::fs::read_to_string(p)?; include_code = std::fs::read_to_string(p)?;
@ -125,11 +71,12 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<(Vec<Token>, Macros
} }
if include_code.is_empty() { 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!("")); return Err(eyre!(""));
} }
let code = lex(&include_code, &args.in_file, &args)?;
let mut code = lex(&include_code, &include_path.text, args, false)?; let mut p = parser::Parser::new(code);
let mut code = p.parse(args)?;
code.reverse(); code.reverse();
rtokens.append(&mut code); rtokens.append(&mut code);
@ -137,30 +84,30 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<(Vec<Token>, Macros
} }
_ if op_type == OpType::Keyword(KeywordType::Memory) => { _ if op_type == 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!(&token.loc, "Memory name not found, expected {} but found nothing", TokenType::String.human());
return Err(eyre!("")); return Err(eyre!(""));
} }
let memory_name = rtokens.pop().unwrap(); let memory_name = rtokens.pop().unwrap();
if memory_name.typ != TokenType::Word { if memory_name.tok_typ != TokenType::Word {
lerror!(&memory_name.loc(), "Bad memory name, expected {} but found {}", TokenType::Word.human(), memory_name.typ.human()); lerror!(&memory_name.loc, "Bad memory name, expected {} but found {}", TokenType::Word.human(), memory_name.typ.human());
return Err(eyre!("")); return Err(eyre!(""));
} }
if macros.get(&memory_name.text).is_some() { if functions.get(&memory_name.text).is_some() {
lerror!(&memory_name.loc(), "Memory name cannot replace macro name, got {}", memory_name.text); lerror!(&memory_name.loc, "Memory name cannot replace function name, got {}", memory_name.text);
let m = macros.get(&memory_name.text).unwrap(); let m = functions.get(&memory_name.text).unwrap();
linfo!(&m.loc, "Macro found here"); linfo!(&m.loc, "Function found here");
return Err(eyre!("")); return Err(eyre!(""));
} }
let mut code: Vec<Token> = Vec::new(); let mut code: Vec<Operator> = Vec::new();
let mut depth = 0; let mut depth = 0;
while !rtokens.is_empty() { while !rtokens.is_empty() {
let t = rtokens.pop().unwrap(); 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 { if typ == OpType::Keyword(KeywordType::End) && depth == 0 {
break; break;
} else if typ == OpType::Keyword(KeywordType::End) && depth != 0 { } else if typ == OpType::Keyword(KeywordType::End) && depth != 0 {
@ -176,17 +123,52 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<(Vec<Token>, Macros
let res = precompile(&code)?; let res = precompile(&code)?;
if res.len() != 1 { if res.len() != 1 {
lerror!(&token.loc(), "Expected 1 number, got {:?}", res); lerror!(&token.loc, "Expected 1 number, got {:?}", res);
return Err(eyre!("")); return Err(eyre!(""));
} }
token.value = Some(res[0]); token.value = res[0];
token.addr = Some(memories.len()); token.addr = Some(memories.len());
program.push(token); program.push(token);
memories.insert(memory_name.text, memories.len()); 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); program.push(token);
} }
} }
@ -196,8 +178,8 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<(Vec<Token>, Macros
//* i wanna kms //* i wanna kms
let mut times = 0; let mut times = 0;
while program.iter().map(|f| { while program.iter().map(|f| {
if f.typ == TokenType::Word && f.op_typ != InstructionType::MemUse { if f.tok_typ == TokenType::Word && f.typ != OpType::Instruction(InstructionType::FnCall) && f.typ != OpType::Instruction(InstructionType::MemUse){
lookup_word(&f.text, &f.loc()) lookup_word(&f.text, &f.loc)
} else { } else {
OpType::Instruction(InstructionType::PushInt) // i hate myself, this is a randomly picked optype so its happy and works 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<Token>, args: &Args) -> Result<(Vec<Token>, Macros
warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it"); warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it");
break break
} }
program = expand(program, &macros, &memories)?; program = expand(program, &functions, &memories)?;
times += 1; times += 1;
} }
Ok((program, macros)) Ok((program, functions))
} }
pub fn expand(tokens: Vec<Token>, macros: &Macros, mems: &Memories) -> Result<Vec<Token>> { pub fn expand(tokens: Vec<Operator>, funcs: &Functions, mems: &Memories) -> Result<Vec<Operator>> {
let mut program: Vec<Token> = Vec::new(); let mut program: Vec<Operator> = Vec::new();
let mut rtokens = tokens.clone(); let mut rtokens = tokens.clone();
rtokens.reverse(); rtokens.reverse();
while !rtokens.is_empty() { while !rtokens.is_empty() {
let op = rtokens.pop().unwrap(); let op = rtokens.pop().unwrap();
let op_type = lookup_word(&op.text, &op.loc()); let op_type = op.typ.clone();
if op.typ == TokenType::Word { if op.tok_typ.clone() == TokenType::Word {
match op_type { match op_type {
OpType::Instruction(InstructionType::None) => { OpType::Instruction(InstructionType::None) => {
let m = macros.get(&op.text); let m = funcs.get(&op.text);
let mem = mems.get(&op.text); let mem = mems.get(&op.text);
if let Some(m) = m { if let Some(m) = m {
// println!("{:#?}", macros); let mut t = op.clone();
let mut toks = m.tokens.clone(); t.typ = OpType::Instruction(InstructionType::FnCall);
// if toks.iter().map(|t| { t.text = m.name.clone();
// let w = lookup_word(&t.text, &t.loc()); program.push(t);
// w == OpType::Keyword(KeywordType::Macro)
// }).collect::<Vec<bool>>().contains(&true) {
// println!("yas");
// toks = preprocess(toks, args)?;
// }
program.append(&mut toks);
// println!("{:?}", program);
} else } else
if let Some(mem) = mem { if let Some(mem) = mem {
let mut t = op; let mut t = op.clone();
t.addr = Some(*mem); t.addr = Some(*mem);
t.op_typ = InstructionType::MemUse; t.typ = OpType::Instruction(InstructionType::MemUse);
program.push(t); program.push(t);
} }
else { else {
lerror!(&op.loc(), "Unknown word '{}'", op.text.clone()); lerror!(&op.loc, "expand: Unknown word '{}'", op.text.clone());
return Err(eyre!("")); return Err(eyre!(""));
} }
} }
_ => { _ => {
program.push(op); program.push(op.clone());
} }
} }
} else { } else {
program.push(op); program.push(op.clone());
}
if op.typ == OpType::Keyword(KeywordType::Do) {
println!("expand: {:?}", op);
} }
} }

View File

@ -27,8 +27,9 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result<Vec<Operator>>{
KeywordType::Else | KeywordType::Else |
KeywordType::End | KeywordType::End |
KeywordType::While | KeywordType::While |
KeywordType::Macro | KeywordType::Function |
KeywordType::Include | KeywordType::Include |
KeywordType::Constant |
KeywordType::Memory => (), KeywordType::Memory => (),
} }
}, },
@ -235,6 +236,8 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result<Vec<Operator>>{
InstructionType::MemUse => { InstructionType::MemUse => {
stack.push(Types::Ptr); stack.push(Types::Ptr);
}, },
InstructionType::FnCall |
InstructionType::Return |
InstructionType::None => {}, InstructionType::None => {},
} }
}, },

View File

@ -1,8 +1,7 @@
include "compat.mcl" include "std.mcl"
__compat__
memory m 10 end
m 69 @8 fn main do
"henlo" puts
m load8 print end