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 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

View File

@ -69,11 +69,14 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
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<i32>{
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<i32>{
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")?;

View File

@ -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<usize>, //? 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<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)]

View File

@ -298,6 +298,8 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
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<i32>{
memories.insert(token.addr.unwrap(), token.value);
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
}
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
.split(['\n', '\r'])
.enumerate()
@ -111,7 +111,7 @@ pub fn lex<S: Into<String> + 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<S: Into<String> + 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)
}

View File

@ -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;
};

View File

@ -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<Operator>) -> Result<Vec<Operator>> {
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<Operator>) -> Result<Vec<Operator>> {
} 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<Operator>) -> Result<Vec<Operator>> {
}
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<Vec<Operator>> {
pub fn parse(&mut self, args: &Args) -> Result<Vec<Operator>> {
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::<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 => {
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<P: Deref<Target = Loc>>(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)
}

View File

@ -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<usize>, loc: &Loc) -> Result<usize> {
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();
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::<usize>() {
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<Token>) -> Result<Vec<usize>>{
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!(""));
}

View File

@ -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<Token>
pub name: String
}
type Macros = HashMap<String, Macro>;
type Functions = HashMap<String, Function>;
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 macros: Macros = HashMap::new();
let mut program: Vec<Operator> = 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<Token>, args: &Args) -> Result<(Vec<Token>, 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!(&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 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<Token>, args: &Args) -> Result<(Vec<Token>, Macros
let mut include_code = String::new();
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.join(&include_path.text);
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() {
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<Token>, args: &Args) -> Result<(Vec<Token>, 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<Token> = Vec::new();
let mut code: Vec<Operator> = 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<Token>, args: &Args) -> Result<(Vec<Token>, 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<Token>, args: &Args) -> Result<(Vec<Token>, 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<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");
break
}
program = expand(program, &macros, &memories)?;
program = expand(program, &functions, &memories)?;
times += 1;
}
Ok((program, macros))
Ok((program, functions))
}
pub fn expand(tokens: Vec<Token>, macros: &Macros, mems: &Memories) -> Result<Vec<Token>> {
let mut program: Vec<Token> = Vec::new();
pub fn expand(tokens: Vec<Operator>, funcs: &Functions, mems: &Memories) -> Result<Vec<Operator>> {
let mut program: Vec<Operator> = 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::<Vec<bool>>().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);
}
}

View File

@ -27,8 +27,9 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result<Vec<Operator>>{
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<Vec<Operator>>{
InstructionType::MemUse => {
stack.push(Types::Ptr);
},
InstructionType::FnCall |
InstructionType::Return |
InstructionType::None => {},
}
},

View File

@ -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
end