implemented local memory

This commit is contained in:
MCorange 2023-04-01 16:54:02 +03:00
parent 09bccc8079
commit f5d8b3ebca
11 changed files with 431 additions and 127 deletions

6
.gitignore vendored
View File

@ -1,2 +1,6 @@
/target
/a
/a
test
test.nasm
test.o

View File

@ -26,7 +26,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
let file = fs::File::create(&of_a)?;
let mut writer = BufWriter::new(&file);
let mut memories: Vec<(usize, usize)> = Vec::new();
// println!("{}", tokens.len());
let mut strings: Vec<String> = Vec::new();
@ -373,6 +373,11 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
writeln!(writer, " push rax")?;
ti += 1;
},
InstructionType::MemUse => {
writeln!(writer, " ;; -- MemUse")?;
writeln!(writer, " push mem_{}", token.addr.unwrap())?;
ti += 1;
},
InstructionType::None => unreachable!(),
InstructionType::CastBool => ti += 1,
InstructionType::CastPtr => ti += 1,
@ -415,6 +420,10 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
}
ti += 1;
},
KeywordType::Memory => {
memories.push((token.addr.unwrap(), token.value));
ti += 1;
}
KeywordType::Macro |
KeywordType::Include
=> unreachable!()
@ -432,9 +441,12 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
let s_list = s_chars.join(",");
writeln!(writer, " str_{}: db {} ; {}", i, s_list, s.escape_default())?;
}
writeln!(writer, "segment .bss")?;
writeln!(writer, "mem: resb {}", crate::compile::MEM_SZ)?;
for (_, s) in memories.iter().enumerate() {
writeln!(writer, " mem_{}: resb {}", s.0, s.1)?;
}
writeln!(writer, " mem: resb {}", crate::compile::MEM_SZ)?;
writer.flush()?;
linux_x86_64_compile_and_link(&of_a, &of_o, &of_c, args.quiet)?;

View File

@ -4,7 +4,7 @@ pub const ALLOW_MACRO_REDEFINITION: bool = true;
#[derive(Debug, Clone, PartialEq)]
pub enum InstructionType {
// stack
PushInt,
PushStr,
@ -30,13 +30,13 @@ pub enum InstructionType {
Shl, // <<
DivMod, // /
Mul,
// mem
Mem,
Load8,
Store8,
// syscalls
Syscall0,
Syscall1,
@ -48,8 +48,9 @@ pub enum InstructionType {
CastBool,
CastPtr,
CastInt,
CastInt,
MemUse,
None // Used for macros and any other non built in word definitions
}
@ -62,6 +63,7 @@ pub enum KeywordType {
Do,
Macro,
Include,
Memory
}
#[derive(Debug, Clone, PartialEq)]
@ -77,7 +79,7 @@ pub struct Operator{
pub text: String, //? only used for OpType::PushStr
pub addr: Option<usize>, //? only used for OpType::PushStr
pub jmp: usize,
pub loc: (String, usize, usize)
pub loc: Loc
}
impl Operator {
@ -91,55 +93,71 @@ impl Operator {
loc: (file, row, col)
}
}
pub fn set_addr(mut self, addr: usize) -> Self {
self.addr = Some(addr);
self
}
}
impl OpType {
pub fn human(&self) -> String {
match *self {
OpType::Instruction(InstructionType::PushInt) => "Number",
OpType::Instruction(InstructionType::PushStr) => "String",
OpType::Instruction(InstructionType::Print) => "print",
OpType::Instruction(InstructionType::Dup) => "dup",
OpType::Instruction(InstructionType::Drop) => "drop",
OpType::Instruction(InstructionType::Rot) => "rot",
OpType::Instruction(InstructionType::Over) => "over",
OpType::Instruction(InstructionType::Swap) => "swap",
OpType::Instruction(InstructionType::Plus) => "+",
OpType::Instruction(InstructionType::Minus) => "-",
OpType::Instruction(InstructionType::Equals) => "=",
OpType::Instruction(InstructionType::Gt) => ">",
OpType::Instruction(InstructionType::Lt) => "<",
OpType::Instruction(InstructionType::NotEquals) => "!=",
OpType::Instruction(InstructionType::Le) => "<=",
OpType::Instruction(InstructionType::Ge) => ">=",
OpType::Instruction(InstructionType::Band) => "band",
OpType::Instruction(InstructionType::Bor) => "bor",
OpType::Instruction(InstructionType::Shr) => "shr",
OpType::Instruction(InstructionType::Shl) => "shl",
OpType::Instruction(InstructionType::DivMod) => "divmod",
OpType::Instruction(InstructionType::Mul) => "*",
OpType::Keyword(KeywordType::If) => "if",
OpType::Keyword(KeywordType::Else) => "else",
OpType::Keyword(KeywordType::End) => "end",
OpType::Keyword(KeywordType::While) => "while",
OpType::Keyword(KeywordType::Do) => "do",
OpType::Keyword(KeywordType::Macro) => "macro",
OpType::Keyword(KeywordType::Include) => "include",
OpType::Instruction(InstructionType::Mem) => "mem",
OpType::Instruction(InstructionType::Load8) => "!8",
OpType::Instruction(InstructionType::Store8) => "@8",
OpType::Instruction(InstructionType::Syscall0) => "syscall0",
OpType::Instruction(InstructionType::Syscall1) => "syscall1",
OpType::Instruction(InstructionType::Syscall2) => "syscall2",
OpType::Instruction(InstructionType::Syscall3) => "syscall3",
OpType::Instruction(InstructionType::Syscall4) => "syscall4",
OpType::Instruction(InstructionType::Syscall5) => "syscall5",
OpType::Instruction(InstructionType::Syscall6) => "syscall6",
OpType::Instruction(InstructionType::CastBool) => "cast(bool",
OpType::Instruction(InstructionType::CastPtr) => "cast(ptr)",
OpType::Instruction(InstructionType::CastInt) => "cast(int)",
OpType::Instruction(InstructionType::None) => "None",
match (*self).clone() {
OpType::Instruction(instruction) => {
match instruction {
InstructionType::PushInt => "Number",
InstructionType::PushStr => "String",
InstructionType::Print => "print",
InstructionType::Dup => "dup",
InstructionType::Drop => "drop",
InstructionType::Rot => "rot",
InstructionType::Over => "over",
InstructionType::Swap => "swap",
InstructionType::Plus => "+",
InstructionType::Minus => "-",
InstructionType::Equals => "=",
InstructionType::Gt => ">",
InstructionType::Lt => "<",
InstructionType::NotEquals => "!=",
InstructionType::Le => "<=",
InstructionType::Ge => ">=",
InstructionType::Band => "band",
InstructionType::Bor => "bor",
InstructionType::Shr => "shr",
InstructionType::Shl => "shl",
InstructionType::DivMod => "divmod",
InstructionType::Mul => "*",
InstructionType::Mem => "mem",
InstructionType::Load8 => "!8",
InstructionType::Store8 => "@8",
InstructionType::Syscall0 => "syscall0",
InstructionType::Syscall1 => "syscall1",
InstructionType::Syscall2 => "syscall2",
InstructionType::Syscall3 => "syscall3",
InstructionType::Syscall4 => "syscall4",
InstructionType::Syscall5 => "syscall5",
InstructionType::Syscall6 => "syscall6",
InstructionType::CastBool => "cast(bool",
InstructionType::CastPtr => "cast(ptr)",
InstructionType::CastInt => "cast(int)",
InstructionType::MemUse => "MemUse",
InstructionType::None => "None",
}
}
OpType::Keyword(keyword) => {
match keyword {
KeywordType::If => "if",
KeywordType::Else => "else",
KeywordType::End => "end",
KeywordType::While => "while",
KeywordType::Do => "do",
KeywordType::Macro => "macro",
KeywordType::Include => "include",
KeywordType::Memory => "memory"
}
}
}.to_string()
}
}
@ -150,7 +168,10 @@ pub struct Token {
pub line: usize,
pub col: usize,
pub text: String,
pub typ: TokenType
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
}
#[derive(Debug, Clone, PartialEq, Copy)]

View File

@ -1,3 +1,5 @@
use std::collections::HashMap;
use crate::{constants::{OpType, Loc, InstructionType, KeywordType}, lerror, error};
// use crate::util::logger;
use color_eyre::Result;
@ -16,6 +18,8 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
let mut ti = 0;
let mut mem: Vec<u8> = vec![0; crate::compile::MEM_SZ + crate::compile::STRING_SZ];
let mut string_idx = 0;
let mut memories: HashMap<usize, usize> = HashMap::new();
// for token in &tokens {
// println!("{{typ: \"{:?}\", val: {}, jmp: {}}}", token.typ, token.value, token.jmp);
@ -100,6 +104,10 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
}
InstructionType::Load8 => {
let a = stack_pop(&mut stack, &pos)?;
if a > crate::compile::MEM_SZ {
lerror!(&token.loc, "Invalid memory address {a}");
return Ok(1);
}
let byte = mem[a];
stack.push(byte as usize);
ti += 1;
@ -108,7 +116,12 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
InstructionType::Store8 => {
let val = stack_pop(&mut stack, &pos)?;
let addr = stack_pop(&mut stack, &pos)?;
if addr > crate::compile::MEM_SZ {
lerror!(&token.loc, "Invalid memory address {addr}");
return Ok(1);
}
mem[addr] = (val & 0xFF) as u8;
ti += 1;
}
@ -246,39 +259,53 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
todo!();
// ti += 1;
},
InstructionType::MemUse => {
let m = memories.get(&token.addr.unwrap()).unwrap();
stack.push(*m);
ti += 1;
},
InstructionType::CastBool => ti += 1,
InstructionType::CastPtr => ti += 1,
InstructionType::CastInt => ti += 1,
InstructionType::None => unreachable!()
InstructionType::None => unreachable!(),
}
}
// blocks
OpType::Keyword(KeywordType::If) => {
let a = stack_pop(&mut stack, &pos)?;
if a == 0 {
// println!("If({ti}) => t: {:?} j: {}", tokens[token.jmp as usize].typ, token.jmp);
ti = token.jmp;
} else {
ti += 1;
}
},
OpType::Keyword(KeywordType::Else) | OpType::Keyword(KeywordType::End) => {
ti = token.jmp;
}
OpType::Keyword(KeywordType::While) => {
ti += 1;
}
OpType::Keyword(KeywordType::Do) => {
let a = stack.pop().unwrap();
if a == 0 {
ti = token.jmp;
} else {
ti += 1;
OpType::Keyword(k) => {
match k {
// blocks
KeywordType::If => {
let a = stack_pop(&mut stack, &pos)?;
if a == 0 {
// println!("If({ti}) => t: {:?} j: {}", tokens[token.jmp as usize].typ, token.jmp);
ti = token.jmp;
} else {
ti += 1;
}
},
KeywordType::Else | KeywordType::End => {
ti = token.jmp;
}
KeywordType::While => {
ti += 1;
}
KeywordType::Do => {
let a = stack.pop().unwrap();
if a == 0 {
ti = token.jmp;
} else {
ti += 1;
}
}
KeywordType::Memory => {
memories.insert(token.addr.unwrap(), token.value);
ti += 1;
},
KeywordType::Macro | KeywordType::Include => unreachable!(),
}
}
| OpType::Keyword(KeywordType::Macro) | OpType::Keyword(KeywordType::Include) => unreachable!()
}
}

View File

@ -108,7 +108,10 @@ pub fn lex<S: Into<String> + std::marker::Copy>(code: &str, file: S, args: &Args
line: row + 1,
col,
text: tok,
typ: tok_type
typ: tok_type,
value: None,
addr: None,
op_typ: crate::constants::InstructionType::None
};
tokens.push(t);
}

View File

@ -6,6 +6,7 @@ mod parser;
mod lexer;
mod preprocessor;
mod typechecker;
mod precompiler;
use std::fs;
@ -17,6 +18,8 @@ pub const DEFAULT_INCLUDES: [&str;2] = [
"~/.mclang/include",
];
#[derive(Parser, Debug, Clone)]
#[command(author, version, about, long_about = None)]
pub struct Args {
@ -48,6 +51,9 @@ pub struct Args {
#[arg(long, short='I')]
include: Vec<String>,
/// Unsafe mode, disables typechecking
#[arg(long="unsafe", default_value_t = false)]
unsaf: bool
//#[arg(long, short='F')]
//features: Vec<String>,

View File

@ -79,8 +79,13 @@ impl Parser {
let pos = (token.file.clone(), token.line, token.col);
match token.typ {
TokenType::Word => {
let word_type = lookup_word(&token.text, &pos);
tokens.push(Operator::new(word_type, 0, token.text.clone(), token.file.clone(), token.line, token.col));
let word_type = if token.op_typ == 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)));
},
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));
@ -109,6 +114,10 @@ impl Parser {
pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
let n = s.parse::<usize>();
if let Ok(_) = n {
return OpType::Instruction(InstructionType::PushInt);
}
match s {
//stack
"print" => OpType::Instruction(InstructionType::Print),
@ -135,20 +144,12 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
"divmod" => OpType::Instruction(InstructionType::DivMod),
"*" => OpType::Instruction(InstructionType::Mul),
// block
"if" => OpType::Keyword(KeywordType::If),
"else" => OpType::Keyword(KeywordType::Else),
"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),
// mem
"mem" => OpType::Instruction(InstructionType::Mem),
"!8" => OpType::Instruction(InstructionType::Load8),
"@8" => OpType::Instruction(InstructionType::Store8),
"load8" => OpType::Instruction(InstructionType::Load8),
"store8" => OpType::Instruction(InstructionType::Store8),
"syscall0" => OpType::Instruction(InstructionType::Syscall0),
"syscall1" => OpType::Instruction(InstructionType::Syscall1),
"syscall2" => OpType::Instruction(InstructionType::Syscall2),
@ -159,6 +160,15 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
"cast(bool" => OpType::Instruction(InstructionType::CastBool),
"cast(ptr)" => OpType::Instruction(InstructionType::CastPtr),
"cast(int)" => OpType::Instruction(InstructionType::CastInt),
// block
"if" => OpType::Keyword(KeywordType::If),
"else" => OpType::Keyword(KeywordType::Else),
"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),
_ => OpType::Instruction(InstructionType::None)
}

154
src/precompiler.rs Normal file
View File

@ -0,0 +1,154 @@
use color_eyre::Result;
use eyre::eyre;
use crate::{constants::{Token, OpType, InstructionType, Loc}, parser::lookup_word, lerror};
fn stack_pop(stack: &mut Vec<usize>, loc: &Loc) -> Result<usize> {
if let Some(i) = stack.pop() { Ok(i) } else {
lerror!(&loc.clone(), "Stack underflow");
Err(eyre!("Stack underflow"))
}
}
pub fn precompile(tokens: &Vec<Token>) -> 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 {
OpType::Instruction(i) => {
let loc = token.loc();
match i {
InstructionType::PushInt => {
if let Ok(i) = token.text.parse::<usize>() {
stack.push(i);
} else {
lerror!(&token.loc(), "Bad number");
return Err(eyre!(""));
}
},
InstructionType::Plus => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(b + a);
},
InstructionType::Minus => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(b - a);
},
InstructionType::Equals => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(usize::from(b == a));
},
InstructionType::Gt => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(usize::from(b > a));
},
InstructionType::Lt => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(usize::from(b < a));
},
InstructionType::NotEquals => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(usize::from(b != a));
},
InstructionType::Ge => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(usize::from(b >= a));
},
InstructionType::Le => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(usize::from(b <= a));
},
InstructionType::Band => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(a & b);
}
InstructionType::Bor => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(a | b);
}
InstructionType::Shr => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(b >> a);
}
InstructionType::Shl => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(b << a);
}
InstructionType::DivMod => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(b / a);
stack.push(b % a);
}
InstructionType::Mul => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(b * a);
}
InstructionType::Drop => {
stack.pop();
},
InstructionType::Dup => {
let a = stack_pop(&mut stack, &loc)?;
stack.push(a);
stack.push(a);
},
InstructionType::Rot => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
let c = stack_pop(&mut stack, &loc)?;
stack.push(b);
stack.push(a);
stack.push(c);
}
InstructionType::Swap => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(a);
stack.push(b);
}
InstructionType::Over => {
let a = stack_pop(&mut stack, &loc)?;
let b = stack_pop(&mut stack, &loc)?;
stack.push(b);
stack.push(a);
stack.push(b);
}
_ => {
lerror!(&token.loc(), "Unsupported precompiler instruction {:?}", i);
dbg!(tokens);
return Err(eyre!(""));
}
}
}
_ => {
lerror!(&token.loc(), "Unsupported precompiler keyword {:?}", typ);
dbg!(tokens);
return Err(eyre!(""));
}
}
}
Ok(stack)
}

View File

@ -6,7 +6,8 @@ use eyre::eyre;
use crate::constants::{Token, Loc, OpType, TokenType, KeywordType, InstructionType};
use crate::lexer::lex;
use crate::{lerror, lnote, Args, warn};
use crate::precompiler::precompile;
use crate::{lerror, lnote, Args, warn, linfo};
use crate::parser::lookup_word;
#[derive(Debug)]
@ -15,14 +16,20 @@ pub struct Macro {
pub tokens: Vec<Token>
}
type Macros = HashMap<String, Macro>;
type Memories = HashMap<String, usize>;
pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
let mut program: Vec<Token> = Vec::new();
let mut macros: HashMap<String, Macro> = HashMap::new();
let mut program: Vec<Token> = Vec::new();
let mut macros: Macros = HashMap::new();
let mut memories: Memories = HashMap::new();
let mut rtokens = tokens;
rtokens.reverse();
while !rtokens.is_empty() {
let token = rtokens.pop().unwrap();
let mut token = rtokens.pop().unwrap();
let op_type = lookup_word(&token.text, &token.loc());
match token.clone() {
@ -66,7 +73,6 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
} else {
macr.tokens.push(t);
}
}
@ -120,6 +126,57 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
rtokens.append(&mut code);
}
_ 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());
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());
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");
return Err(eyre!(""));
}
let mut code: Vec<Token> = Vec::new();
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;
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 {
lerror!(&token.loc(), "Expected 1 number, got {:?}", res);
return Err(eyre!(""));
}
token.value = Some(res[0]);
token.addr = Some(memories.len());
program.push(token);
memories.insert(memory_name.text, memories.len());
}
_ => {
program.push(token);
@ -131,7 +188,7 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
//* i wanna kms
let mut times = 0;
while program.iter().map(|f| {
if f.typ == TokenType::Word {
if f.typ == TokenType::Word && f.op_typ != 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
@ -143,7 +200,7 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it");
break
}
program = expand_macros(program, &macros)?;
program = expand(program, &macros, &memories)?;
times += 1;
}
@ -151,7 +208,7 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
Ok(program)
}
pub fn expand_macros(tokens: Vec<Token>, macros: &HashMap<String, Macro>) -> Result<Vec<Token>> {
pub fn expand(tokens: Vec<Token>, macros: &Macros, mems: &Memories) -> Result<Vec<Token>> {
let mut program: Vec<Token> = Vec::new();
let mut rtokens = tokens;
@ -164,11 +221,17 @@ pub fn expand_macros(tokens: Vec<Token>, macros: &HashMap<String, Macro>) -> Res
match op_type {
OpType::Instruction(InstructionType::None) => {
let m = macros.get(&op.text);
if m.is_some() {
if let Some(m) = m {
program.append(&mut m.tokens.clone());
}
} else {
let mem = mems.get(&op.text);
if let Some(m) = m {
program.append(&mut m.tokens.clone());
} else
if let Some(mem) = mem {
let mut t = op;
t.addr = Some(*mem);
t.op_typ = InstructionType::MemUse;
program.push(t);
}
else {
lerror!(&op.loc(), "Unknown word '{}'", op.text.clone());
return Err(eyre!(""));
}

View File

@ -1,9 +1,15 @@
use crate::{constants::{Operator, Types, OpType, KeywordType, InstructionType}, Args, lerror};
use crate::{constants::{Operator, Types, OpType, KeywordType, InstructionType}, Args, lerror, warn};
use color_eyre::Result;
use eyre::eyre;
pub fn typecheck(ops: &[Operator], args: &Args) -> Result<Vec<Operator>>{
if args.unsaf {
if !args.quiet {
warn!("Unsafe mode enabled, disabling typechecker, goodluck");
}
return Ok(ops.to_vec());
}
let mut stack: Vec<Types> = Vec::new();
@ -13,25 +19,17 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result<Vec<Operator>>{
match keyword {
KeywordType::If => {
stack_pop(&mut stack, &op, &[Types::Bool])?;
},
KeywordType::Else => {
},
KeywordType::End => {
},
KeywordType::While => {
},
KeywordType::Do => {
stack_pop(&mut stack, &op, &[Types::Bool])?;
},
KeywordType::Macro => {
},
KeywordType::Include => {
},
KeywordType::Else |
KeywordType::End |
KeywordType::While |
KeywordType::Macro |
KeywordType::Include |
KeywordType::Memory => (),
}
},
OpType::Instruction(instruction) => {
@ -218,6 +216,9 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result<Vec<Operator>>{
stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(Types::Int);
},
InstructionType::MemUse => {
stack.push(Types::Ptr);
},
InstructionType::None => {},
}
},

View File

@ -1,3 +1,6 @@
include "./asd.mcl"
memory m 10 end
1 test
m 69 store8
m load8 print