added support for macros inside macros
This commit is contained in:
parent
f5d8b3ebca
commit
0a61a599c1
5
include/compat.mcl
Normal file
5
include/compat.mcl
Normal file
|
@ -0,0 +1,5 @@
|
|||
macro __compat__
|
||||
macro !8 load8 end
|
||||
macro @8 store8 end
|
||||
|
||||
end
|
|
@ -1,27 +0,0 @@
|
|||
|
||||
macro load8 @8 end
|
||||
macro store8 !8 end
|
||||
|
||||
macro load64
|
||||
7 + 0
|
||||
8 shl over !8 + swap 1 - swap
|
||||
8 shl over !8 + swap 1 - swap
|
||||
8 shl over !8 + swap 1 - swap
|
||||
8 shl over !8 + swap 1 - swap
|
||||
8 shl over !8 + swap 1 - swap
|
||||
8 shl over !8 + swap 1 - swap
|
||||
8 shl over !8 + swap 1 - swap
|
||||
8 shl over !8 + swap drop
|
||||
end
|
||||
|
||||
macro store64
|
||||
2dup 255 band @8 shr swap 1 + swap
|
||||
2dup 255 band @8 shr swap 1 + swap
|
||||
2dup 255 band @8 shr swap 1 + swap
|
||||
2dup 255 band @8 shr swap 1 + swap
|
||||
2dup 255 band @8 shr swap 1 + swap
|
||||
2dup 255 band @8 shr swap 1 + swap
|
||||
2dup 255 band @8 shr swap 1 + swap
|
||||
2dup 255 band @8 shr swap 2drop
|
||||
end
|
||||
|
|
@ -2,4 +2,5 @@ include "linux.mcl"
|
|||
include "io.mcl"
|
||||
include "util.mcl"
|
||||
include "int.mcl"
|
||||
include "fs.mcl"
|
||||
include "fs.mcl"
|
||||
include "compat.mcl"
|
|
@ -156,7 +156,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " ;; -- load")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " xor rbx, rbx")?;
|
||||
writeln!(writer, " mov bl, [rax]")?;
|
||||
writeln!(writer, " mov bl, byte [rax]")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
}
|
||||
|
@ -165,7 +165,39 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " ;; -- store")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " mov [rax], bl")?;
|
||||
writeln!(writer, " mov byte [rax], bl")?;
|
||||
ti += 1;
|
||||
}
|
||||
InstructionType::Load32 => {
|
||||
writeln!(writer, " ;; -- load")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " xor rbx, rbx")?;
|
||||
writeln!(writer, " mov bl, dword [rax]")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
InstructionType::Store32 => {
|
||||
writeln!(writer, " ;; -- store")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " mov dword[rax], bl")?;
|
||||
ti += 1;
|
||||
}
|
||||
InstructionType::Load64 => {
|
||||
writeln!(writer, " ;; -- load")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " xor rbx, rbx")?;
|
||||
writeln!(writer, " mov bl, qword [rax]")?;
|
||||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
InstructionType::Store64 => {
|
||||
writeln!(writer, " ;; -- store")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " mov qword [rax], bl")?;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,10 @@ pub enum InstructionType {
|
|||
Mem,
|
||||
Load8,
|
||||
Store8,
|
||||
Load32,
|
||||
Store32,
|
||||
Load64,
|
||||
Store64,
|
||||
|
||||
// syscalls
|
||||
Syscall0,
|
||||
|
@ -129,8 +133,12 @@ impl OpType {
|
|||
InstructionType::DivMod => "divmod",
|
||||
InstructionType::Mul => "*",
|
||||
InstructionType::Mem => "mem",
|
||||
InstructionType::Load8 => "!8",
|
||||
InstructionType::Store8 => "@8",
|
||||
InstructionType::Load8 => "load8",
|
||||
InstructionType::Store8 => "store8",
|
||||
InstructionType::Load32 => "load32",
|
||||
InstructionType::Store32 => "store32",
|
||||
InstructionType::Load64 => "load64",
|
||||
InstructionType::Store64 => "store64",
|
||||
InstructionType::Syscall0 => "syscall0",
|
||||
InstructionType::Syscall1 => "syscall1",
|
||||
InstructionType::Syscall2 => "syscall2",
|
||||
|
|
|
@ -16,7 +16,7 @@ fn stack_pop(stack: &mut Vec<usize>, pos: &Loc) -> Result<usize> {
|
|||
pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
||||
let mut stack: Vec<usize> = Vec::new();
|
||||
let mut ti = 0;
|
||||
let mut mem: Vec<u8> = vec![0; crate::compile::MEM_SZ + crate::compile::STRING_SZ];
|
||||
let mut mem: Vec<u64> = vec![0; crate::compile::MEM_SZ + crate::compile::STRING_SZ];
|
||||
let mut string_idx = 0;
|
||||
|
||||
let mut memories: HashMap<usize, usize> = HashMap::new();
|
||||
|
@ -41,7 +41,7 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
|||
stack.push(string_idx + crate::compile::MEM_SZ);
|
||||
|
||||
for c in token.text.bytes() {
|
||||
mem[crate::compile::MEM_SZ + string_idx] = c;
|
||||
mem[crate::compile::MEM_SZ + string_idx] = c as u64;
|
||||
string_idx += 1;
|
||||
}
|
||||
} else {
|
||||
|
@ -102,7 +102,9 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
|||
stack.push(0);
|
||||
ti += 1;
|
||||
}
|
||||
InstructionType::Load8 => {
|
||||
InstructionType::Load8 |
|
||||
InstructionType::Load32 |
|
||||
InstructionType::Load64 => {
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
if a > crate::compile::MEM_SZ {
|
||||
lerror!(&token.loc, "Invalid memory address {a}");
|
||||
|
@ -122,7 +124,34 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
|||
return Ok(1);
|
||||
}
|
||||
|
||||
mem[addr] = (val & 0xFF) as u8;
|
||||
mem[addr] = val as u8 as u64;
|
||||
ti += 1;
|
||||
}
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
InstructionType::Store32 => {
|
||||
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 as u32 as u64;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
InstructionType::Store64 => {
|
||||
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 as u64;
|
||||
ti += 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
pub fn sys_write(sys_n: usize, fd: usize, buff: usize, count: usize, mem: &Vec<u8> ) -> usize {
|
||||
pub fn sys_write(sys_n: usize, fd: usize, buff: usize, count: usize, mem: &Vec<u64> ) -> usize {
|
||||
let mem = (*mem).clone();
|
||||
// println!("{:?}", &mem[buff..(buff + count)]);
|
||||
// return 0 ;
|
||||
let s = &mem[buff..(buff + count)].iter().map(|i| {
|
||||
char::from_u32(u32::from(*i)).unwrap_or('_').to_string()
|
||||
char::from_u32(u32::from(*i as u8)).unwrap_or('_').to_string()
|
||||
}).collect::<String>();
|
||||
|
||||
match fd {
|
||||
|
|
|
@ -122,7 +122,7 @@ pub fn lex<S: Into<String> + std::marker::Copy>(code: &str, file: S, args: &Args
|
|||
// println!("tok: {:?}", token.text);
|
||||
// }
|
||||
if preprocessing {
|
||||
tokens = preprocess(tokens, args)?;
|
||||
(tokens, _) = preprocess(tokens, args)?;
|
||||
}
|
||||
|
||||
Ok(tokens)
|
||||
|
|
|
@ -26,6 +26,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
|||
OpType::Keyword(KeywordType::End) => {
|
||||
let block_ip = stack.pop().unwrap();
|
||||
|
||||
|
||||
if program[block_ip].typ == OpType::Keyword(KeywordType::If) ||
|
||||
program[block_ip].typ == OpType::Keyword(KeywordType::Else) {
|
||||
|
||||
|
@ -51,6 +52,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
|||
|
||||
}
|
||||
if !stack.is_empty() {
|
||||
println!("{:?}", stack);
|
||||
lerror!(&program[stack.pop().expect("Empy stack")].clone().loc,"Unclosed block");
|
||||
return Err(eyre!("Unclosed block"));
|
||||
}
|
||||
|
@ -149,6 +151,10 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
|
|||
"mem" => OpType::Instruction(InstructionType::Mem),
|
||||
"load8" => OpType::Instruction(InstructionType::Load8),
|
||||
"store8" => OpType::Instruction(InstructionType::Store8),
|
||||
"load32" => OpType::Instruction(InstructionType::Load32),
|
||||
"store32" => OpType::Instruction(InstructionType::Store32),
|
||||
"load64" => OpType::Instruction(InstructionType::Load64),
|
||||
"store64" => OpType::Instruction(InstructionType::Store64),
|
||||
|
||||
"syscall0" => OpType::Instruction(InstructionType::Syscall0),
|
||||
"syscall1" => OpType::Instruction(InstructionType::Syscall1),
|
||||
|
|
|
@ -19,7 +19,7 @@ pub struct Macro {
|
|||
type Macros = HashMap<String, Macro>;
|
||||
type Memories = HashMap<String, usize>;
|
||||
|
||||
pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
|
||||
pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<(Vec<Token>, Macros)>{
|
||||
|
||||
|
||||
let mut program: Vec<Token> = Vec::new();
|
||||
|
@ -57,7 +57,7 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
|
|||
}
|
||||
|
||||
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();
|
||||
|
@ -67,7 +67,12 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
|
|||
} 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) {
|
||||
} 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 {
|
||||
|
@ -75,6 +80,9 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
|
|||
}
|
||||
}
|
||||
|
||||
if reprocess {
|
||||
(macr.tokens, macros) = preprocess(macr.tokens, args)?;
|
||||
}
|
||||
|
||||
macros.insert(macro_name.text, macr);
|
||||
|
||||
|
@ -205,13 +213,13 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
|
|||
}
|
||||
|
||||
|
||||
Ok(program)
|
||||
Ok((program, macros))
|
||||
}
|
||||
|
||||
pub fn expand(tokens: Vec<Token>, macros: &Macros, mems: &Memories) -> Result<Vec<Token>> {
|
||||
let mut program: Vec<Token> = Vec::new();
|
||||
|
||||
let mut rtokens = tokens;
|
||||
let mut rtokens = tokens.clone();
|
||||
rtokens.reverse();
|
||||
|
||||
while !rtokens.is_empty() {
|
||||
|
@ -223,7 +231,17 @@ pub fn expand(tokens: Vec<Token>, macros: &Macros, mems: &Memories) -> Result<Ve
|
|||
let m = macros.get(&op.text);
|
||||
let mem = mems.get(&op.text);
|
||||
if let Some(m) = m {
|
||||
program.append(&mut m.tokens.clone());
|
||||
// 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);
|
||||
} else
|
||||
if let Some(mem) = mem {
|
||||
let mut t = op;
|
||||
|
|
|
@ -155,6 +155,22 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result<Vec<Operator>>{
|
|||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
||||
},
|
||||
InstructionType::Load32 => {
|
||||
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
||||
stack.push(Types::Int);
|
||||
},
|
||||
InstructionType::Store32 => {
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
||||
},
|
||||
InstructionType::Load64 => {
|
||||
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
||||
stack.push(Types::Int);
|
||||
},
|
||||
InstructionType::Store64 => {
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
||||
},
|
||||
InstructionType::Syscall0 => {
|
||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||
stack.push(Types::Int);
|
||||
|
|
Loading…
Reference in New Issue
Block a user