2023-03-20 11:39:04 +00:00
|
|
|
use std::collections::HashMap;
|
2023-04-01 10:20:35 +00:00
|
|
|
use std::path::{PathBuf, Path};
|
2023-03-20 11:39:04 +00:00
|
|
|
|
|
|
|
use color_eyre::Result;
|
|
|
|
use eyre::eyre;
|
|
|
|
|
2023-04-04 14:24:58 +00:00
|
|
|
use crate::constants::{Token, Loc, OpType, TokenType, KeywordType, InstructionType, Operator};
|
2023-03-20 12:36:38 +00:00
|
|
|
use crate::lexer::lex;
|
2023-04-01 13:54:02 +00:00
|
|
|
use crate::precompiler::precompile;
|
2023-04-04 14:24:58 +00:00
|
|
|
use crate::{lerror, lnote, Args, warn, linfo, parser};
|
2023-03-20 11:39:04 +00:00
|
|
|
use crate::parser::lookup_word;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2023-04-04 14:24:58 +00:00
|
|
|
pub struct Function {
|
2023-03-20 11:39:04 +00:00
|
|
|
pub loc: Loc,
|
2023-04-04 14:24:58 +00:00
|
|
|
pub name: String
|
2023-03-20 11:39:04 +00:00
|
|
|
}
|
|
|
|
|
2023-04-04 14:24:58 +00:00
|
|
|
type Functions = HashMap<String, Function>;
|
2023-04-01 13:54:02 +00:00
|
|
|
type Memories = HashMap<String, usize>;
|
|
|
|
|
2023-04-04 14:24:58 +00:00
|
|
|
pub fn preprocess(tokens: Vec<Operator>, args: &Args) -> Result<(Vec<Operator>, Functions)>{
|
2023-03-20 11:39:04 +00:00
|
|
|
|
2023-04-01 13:54:02 +00:00
|
|
|
|
2023-04-04 14:24:58 +00:00
|
|
|
let mut program: Vec<Operator> = Vec::new();
|
|
|
|
let mut functions: Functions = HashMap::new();
|
2023-04-01 13:54:02 +00:00
|
|
|
let mut memories: Memories = HashMap::new();
|
|
|
|
|
2023-03-21 18:12:24 +00:00
|
|
|
let mut rtokens = tokens;
|
2023-03-20 11:39:04 +00:00
|
|
|
rtokens.reverse();
|
2023-03-21 18:12:24 +00:00
|
|
|
while !rtokens.is_empty() {
|
2023-04-01 13:54:02 +00:00
|
|
|
let mut token = rtokens.pop().unwrap();
|
2023-03-20 11:39:04 +00:00
|
|
|
|
2023-04-04 14:24:58 +00:00
|
|
|
let op_type = token.typ.clone();
|
2023-03-20 11:39:04 +00:00
|
|
|
match token.clone() {
|
2023-04-04 14:24:58 +00:00
|
|
|
|
2023-03-20 11:39:04 +00:00
|
|
|
|
2023-03-22 12:58:11 +00:00
|
|
|
_ if op_type == OpType::Keyword(KeywordType::Include) => {
|
2023-03-21 18:12:24 +00:00
|
|
|
if rtokens.is_empty() {
|
2023-04-04 14:24:58 +00:00
|
|
|
lerror!(&token.loc, "Include path not found, expected {} but found nothing", TokenType::String.human());
|
2023-03-20 12:36:38 +00:00
|
|
|
return Err(eyre!(""));
|
|
|
|
}
|
|
|
|
|
|
|
|
let include_path = rtokens.pop().unwrap();
|
|
|
|
|
2023-04-04 14:24:58 +00:00
|
|
|
if include_path.tok_typ != TokenType::String {
|
|
|
|
lerror!(&include_path.loc, "Bad include path, expected {} but found {}", TokenType::String.human(), include_path.typ.human());
|
2023-03-20 12:36:38 +00:00
|
|
|
return Err(eyre!(""));
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut in_paths = args.include.clone();
|
2023-03-21 18:12:24 +00:00
|
|
|
in_paths.append(&mut crate::DEFAULT_INCLUDES.to_vec().clone().iter().map(|f| (*f).to_string()).collect::<Vec<String>>());
|
2023-03-20 12:36:38 +00:00
|
|
|
|
|
|
|
let mut include_code = String::new();
|
|
|
|
|
2023-04-01 10:20:35 +00:00
|
|
|
if include_path.text.chars().collect::<Vec<char>>()[0] == '.' {
|
2023-04-04 14:24:58 +00:00
|
|
|
let p = Path::new(include_path.loc.0.as_str());
|
2023-04-01 10:20:35 +00:00
|
|
|
let p = p.parent().unwrap();
|
|
|
|
let p = p.join(&include_path.text);
|
|
|
|
include_code = std::fs::read_to_string(p)?;
|
|
|
|
} else {
|
|
|
|
for path in in_paths {
|
|
|
|
let p = PathBuf::from(path);
|
|
|
|
let p = p.join(&include_path.text);
|
|
|
|
|
|
|
|
if p.exists() {
|
|
|
|
include_code = std::fs::read_to_string(p)?;
|
|
|
|
}
|
|
|
|
|
2023-03-20 12:36:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if include_code.is_empty() {
|
2023-04-04 14:24:58 +00:00
|
|
|
lerror!(&include_path.loc, "Include file in path '{}' was not found or is empty", include_path.text);
|
2023-03-20 12:36:38 +00:00
|
|
|
return Err(eyre!(""));
|
|
|
|
}
|
2023-04-04 14:24:58 +00:00
|
|
|
let code = lex(&include_code, &args.in_file, &args)?;
|
|
|
|
let mut p = parser::Parser::new(code);
|
|
|
|
let mut code = p.parse(args)?;
|
2023-03-20 12:36:38 +00:00
|
|
|
code.reverse();
|
|
|
|
rtokens.append(&mut code);
|
|
|
|
|
|
|
|
|
2023-04-01 13:54:02 +00:00
|
|
|
}
|
|
|
|
_ if op_type == OpType::Keyword(KeywordType::Memory) => {
|
|
|
|
if rtokens.is_empty() {
|
2023-04-04 14:24:58 +00:00
|
|
|
lerror!(&token.loc, "Memory name not found, expected {} but found nothing", TokenType::String.human());
|
2023-04-01 13:54:02 +00:00
|
|
|
return Err(eyre!(""));
|
|
|
|
}
|
|
|
|
|
|
|
|
let memory_name = rtokens.pop().unwrap();
|
|
|
|
|
2023-04-04 14:24:58 +00:00
|
|
|
if memory_name.tok_typ != TokenType::Word {
|
|
|
|
lerror!(&memory_name.loc, "Bad memory name, expected {} but found {}", TokenType::Word.human(), memory_name.typ.human());
|
2023-04-01 13:54:02 +00:00
|
|
|
return Err(eyre!(""));
|
|
|
|
}
|
|
|
|
|
2023-04-04 14:24:58 +00:00
|
|
|
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");
|
2023-04-01 13:54:02 +00:00
|
|
|
return Err(eyre!(""));
|
|
|
|
}
|
|
|
|
|
2023-04-04 14:24:58 +00:00
|
|
|
let mut code: Vec<Operator> = Vec::new();
|
2023-04-01 13:54:02 +00:00
|
|
|
|
|
|
|
let mut depth = 0;
|
|
|
|
while !rtokens.is_empty() {
|
|
|
|
let t = rtokens.pop().unwrap();
|
2023-04-04 14:24:58 +00:00
|
|
|
let typ = t.typ.clone();
|
2023-04-01 13:54:02 +00:00
|
|
|
if typ == OpType::Keyword(KeywordType::End) && depth == 0 {
|
|
|
|
break;
|
|
|
|
} else if typ == OpType::Keyword(KeywordType::End) && depth != 0 {
|
|
|
|
depth -= 1;
|
|
|
|
code.push(t);
|
|
|
|
} else if typ == OpType::Keyword(KeywordType::If) || typ == OpType::Keyword(KeywordType::Do) {
|
|
|
|
code.push(t);
|
|
|
|
depth += 1;
|
|
|
|
} else {
|
|
|
|
code.push(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let res = precompile(&code)?;
|
|
|
|
|
|
|
|
if res.len() != 1 {
|
2023-04-04 14:24:58 +00:00
|
|
|
lerror!(&token.loc, "Expected 1 number, got {:?}", res);
|
2023-04-01 13:54:02 +00:00
|
|
|
return Err(eyre!(""));
|
|
|
|
}
|
2023-04-04 14:24:58 +00:00
|
|
|
token.value = res[0];
|
2023-04-01 13:54:02 +00:00
|
|
|
token.addr = Some(memories.len());
|
|
|
|
program.push(token);
|
|
|
|
|
|
|
|
memories.insert(memory_name.text, memories.len());
|
|
|
|
|
2023-03-20 12:36:38 +00:00
|
|
|
}
|
2023-04-04 14:24:58 +00:00
|
|
|
_ 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);
|
|
|
|
}
|
|
|
|
|
2023-03-20 11:39:04 +00:00
|
|
|
_ => {
|
2023-04-04 14:24:58 +00:00
|
|
|
if op_type == OpType::Keyword(KeywordType::Do) {
|
|
|
|
println!("{:?}", token);
|
|
|
|
}
|
2023-03-20 11:39:04 +00:00
|
|
|
program.push(token);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-20 14:13:34 +00:00
|
|
|
//* Feel free to fix this horrifying shit
|
|
|
|
//* i wanna kms
|
|
|
|
let mut times = 0;
|
|
|
|
while program.iter().map(|f| {
|
2023-04-04 14:24:58 +00:00
|
|
|
if f.tok_typ == TokenType::Word && f.typ != OpType::Instruction(InstructionType::FnCall) && f.typ != OpType::Instruction(InstructionType::MemUse){
|
|
|
|
lookup_word(&f.text, &f.loc)
|
2023-03-20 14:13:34 +00:00
|
|
|
} else {
|
2023-03-22 12:58:11 +00:00
|
|
|
OpType::Instruction(InstructionType::PushInt) // i hate myself, this is a randomly picked optype so its happy and works
|
2023-03-20 14:13:34 +00:00
|
|
|
}
|
|
|
|
|
2023-03-22 12:58:11 +00:00
|
|
|
}).collect::<Vec<OpType>>().contains(&OpType::Instruction(InstructionType::None)){
|
2023-03-20 14:13:34 +00:00
|
|
|
|
|
|
|
if times >= 50 {
|
|
|
|
warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it");
|
|
|
|
break
|
|
|
|
}
|
2023-04-04 14:24:58 +00:00
|
|
|
program = expand(program, &functions, &memories)?;
|
2023-03-20 14:13:34 +00:00
|
|
|
times += 1;
|
|
|
|
}
|
|
|
|
|
2023-03-20 11:39:04 +00:00
|
|
|
|
2023-04-04 14:24:58 +00:00
|
|
|
Ok((program, functions))
|
2023-03-20 11:39:04 +00:00
|
|
|
}
|
|
|
|
|
2023-04-04 14:24:58 +00:00
|
|
|
pub fn expand(tokens: Vec<Operator>, funcs: &Functions, mems: &Memories) -> Result<Vec<Operator>> {
|
|
|
|
let mut program: Vec<Operator> = Vec::new();
|
2023-03-20 11:39:04 +00:00
|
|
|
|
2023-04-01 14:49:41 +00:00
|
|
|
let mut rtokens = tokens.clone();
|
2023-03-20 11:39:04 +00:00
|
|
|
rtokens.reverse();
|
|
|
|
|
2023-03-21 18:12:24 +00:00
|
|
|
while !rtokens.is_empty() {
|
2023-03-20 11:39:04 +00:00
|
|
|
let op = rtokens.pop().unwrap();
|
2023-04-04 14:24:58 +00:00
|
|
|
let op_type = op.typ.clone();
|
|
|
|
if op.tok_typ.clone() == TokenType::Word {
|
2023-03-20 11:39:04 +00:00
|
|
|
match op_type {
|
2023-03-22 12:58:11 +00:00
|
|
|
OpType::Instruction(InstructionType::None) => {
|
2023-04-04 14:24:58 +00:00
|
|
|
let m = funcs.get(&op.text);
|
2023-04-01 13:54:02 +00:00
|
|
|
let mem = mems.get(&op.text);
|
|
|
|
if let Some(m) = m {
|
2023-04-04 14:24:58 +00:00
|
|
|
let mut t = op.clone();
|
|
|
|
t.typ = OpType::Instruction(InstructionType::FnCall);
|
|
|
|
t.text = m.name.clone();
|
|
|
|
program.push(t);
|
2023-04-01 13:54:02 +00:00
|
|
|
} else
|
|
|
|
if let Some(mem) = mem {
|
2023-04-04 14:24:58 +00:00
|
|
|
let mut t = op.clone();
|
2023-04-01 13:54:02 +00:00
|
|
|
t.addr = Some(*mem);
|
2023-04-04 14:24:58 +00:00
|
|
|
t.typ = OpType::Instruction(InstructionType::MemUse);
|
2023-04-01 13:54:02 +00:00
|
|
|
program.push(t);
|
|
|
|
}
|
|
|
|
else {
|
2023-04-04 14:24:58 +00:00
|
|
|
lerror!(&op.loc, "expand: Unknown word '{}'", op.text.clone());
|
2023-03-20 11:39:04 +00:00
|
|
|
return Err(eyre!(""));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {
|
2023-04-04 14:24:58 +00:00
|
|
|
program.push(op.clone());
|
2023-03-20 11:39:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2023-04-04 14:24:58 +00:00
|
|
|
program.push(op.clone());
|
|
|
|
}
|
|
|
|
|
|
|
|
if op.typ == OpType::Keyword(KeywordType::Do) {
|
|
|
|
println!("expand: {:?}", op);
|
2023-03-20 11:39:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(program)
|
|
|
|
}
|