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 "io.mcl"
|
||||||
include "util.mcl"
|
include "util.mcl"
|
||||||
include "int.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, " ;; -- load")?;
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " pop rax")?;
|
||||||
writeln!(writer, " xor rbx, rbx")?;
|
writeln!(writer, " xor rbx, rbx")?;
|
||||||
writeln!(writer, " mov bl, [rax]")?;
|
writeln!(writer, " mov bl, byte [rax]")?;
|
||||||
writeln!(writer, " push rbx")?;
|
writeln!(writer, " push rbx")?;
|
||||||
ti += 1;
|
ti += 1;
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,39 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
||||||
writeln!(writer, " ;; -- store")?;
|
writeln!(writer, " ;; -- store")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
writeln!(writer, " pop rbx")?;
|
||||||
writeln!(writer, " pop rax")?;
|
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;
|
ti += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,10 @@ pub enum InstructionType {
|
||||||
Mem,
|
Mem,
|
||||||
Load8,
|
Load8,
|
||||||
Store8,
|
Store8,
|
||||||
|
Load32,
|
||||||
|
Store32,
|
||||||
|
Load64,
|
||||||
|
Store64,
|
||||||
|
|
||||||
// syscalls
|
// syscalls
|
||||||
Syscall0,
|
Syscall0,
|
||||||
|
@ -129,8 +133,12 @@ impl OpType {
|
||||||
InstructionType::DivMod => "divmod",
|
InstructionType::DivMod => "divmod",
|
||||||
InstructionType::Mul => "*",
|
InstructionType::Mul => "*",
|
||||||
InstructionType::Mem => "mem",
|
InstructionType::Mem => "mem",
|
||||||
InstructionType::Load8 => "!8",
|
InstructionType::Load8 => "load8",
|
||||||
InstructionType::Store8 => "@8",
|
InstructionType::Store8 => "store8",
|
||||||
|
InstructionType::Load32 => "load32",
|
||||||
|
InstructionType::Store32 => "store32",
|
||||||
|
InstructionType::Load64 => "load64",
|
||||||
|
InstructionType::Store64 => "store64",
|
||||||
InstructionType::Syscall0 => "syscall0",
|
InstructionType::Syscall0 => "syscall0",
|
||||||
InstructionType::Syscall1 => "syscall1",
|
InstructionType::Syscall1 => "syscall1",
|
||||||
InstructionType::Syscall2 => "syscall2",
|
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>{
|
pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
||||||
let mut stack: Vec<usize> = Vec::new();
|
let mut stack: Vec<usize> = Vec::new();
|
||||||
let mut ti = 0;
|
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 string_idx = 0;
|
||||||
|
|
||||||
let mut memories: HashMap<usize, usize> = HashMap::new();
|
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);
|
stack.push(string_idx + crate::compile::MEM_SZ);
|
||||||
|
|
||||||
for c in token.text.bytes() {
|
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;
|
string_idx += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -102,7 +102,9 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
||||||
stack.push(0);
|
stack.push(0);
|
||||||
ti += 1;
|
ti += 1;
|
||||||
}
|
}
|
||||||
InstructionType::Load8 => {
|
InstructionType::Load8 |
|
||||||
|
InstructionType::Load32 |
|
||||||
|
InstructionType::Load64 => {
|
||||||
let a = stack_pop(&mut stack, &pos)?;
|
let a = stack_pop(&mut stack, &pos)?;
|
||||||
if a > crate::compile::MEM_SZ {
|
if a > crate::compile::MEM_SZ {
|
||||||
lerror!(&token.loc, "Invalid memory address {a}");
|
lerror!(&token.loc, "Invalid memory address {a}");
|
||||||
|
@ -122,7 +124,34 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
||||||
return Ok(1);
|
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;
|
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();
|
let mem = (*mem).clone();
|
||||||
// println!("{:?}", &mem[buff..(buff + count)]);
|
// println!("{:?}", &mem[buff..(buff + count)]);
|
||||||
// return 0 ;
|
// return 0 ;
|
||||||
let s = &mem[buff..(buff + count)].iter().map(|i| {
|
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>();
|
}).collect::<String>();
|
||||||
|
|
||||||
match fd {
|
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);
|
// println!("tok: {:?}", token.text);
|
||||||
// }
|
// }
|
||||||
if preprocessing {
|
if preprocessing {
|
||||||
tokens = preprocess(tokens, args)?;
|
(tokens, _) = preprocess(tokens, args)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(tokens)
|
Ok(tokens)
|
||||||
|
|
|
@ -26,6 +26,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
|
||||||
OpType::Keyword(KeywordType::End) => {
|
OpType::Keyword(KeywordType::End) => {
|
||||||
let block_ip = stack.pop().unwrap();
|
let block_ip = stack.pop().unwrap();
|
||||||
|
|
||||||
|
|
||||||
if program[block_ip].typ == OpType::Keyword(KeywordType::If) ||
|
if program[block_ip].typ == OpType::Keyword(KeywordType::If) ||
|
||||||
program[block_ip].typ == OpType::Keyword(KeywordType::Else) {
|
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() {
|
if !stack.is_empty() {
|
||||||
|
println!("{:?}", stack);
|
||||||
lerror!(&program[stack.pop().expect("Empy stack")].clone().loc,"Unclosed block");
|
lerror!(&program[stack.pop().expect("Empy stack")].clone().loc,"Unclosed block");
|
||||||
return Err(eyre!("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),
|
"mem" => OpType::Instruction(InstructionType::Mem),
|
||||||
"load8" => OpType::Instruction(InstructionType::Load8),
|
"load8" => OpType::Instruction(InstructionType::Load8),
|
||||||
"store8" => OpType::Instruction(InstructionType::Store8),
|
"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),
|
"syscall0" => OpType::Instruction(InstructionType::Syscall0),
|
||||||
"syscall1" => OpType::Instruction(InstructionType::Syscall1),
|
"syscall1" => OpType::Instruction(InstructionType::Syscall1),
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub struct Macro {
|
||||||
type Macros = HashMap<String, Macro>;
|
type Macros = HashMap<String, Macro>;
|
||||||
type Memories = HashMap<String, usize>;
|
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();
|
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 macr = Macro{ loc: macro_name.loc(), tokens: Vec::new() };
|
||||||
|
let mut reprocess = false;
|
||||||
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();
|
||||||
|
@ -67,7 +67,12 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
|
||||||
} else if typ == OpType::Keyword(KeywordType::End) && depth != 0 {
|
} else if typ == OpType::Keyword(KeywordType::End) && depth != 0 {
|
||||||
depth -= 1;
|
depth -= 1;
|
||||||
macr.tokens.push(t);
|
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);
|
macr.tokens.push(t);
|
||||||
depth += 1;
|
depth += 1;
|
||||||
} else {
|
} 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);
|
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>> {
|
pub fn expand(tokens: Vec<Token>, macros: &Macros, mems: &Memories) -> Result<Vec<Token>> {
|
||||||
let mut program: Vec<Token> = Vec::new();
|
let mut program: Vec<Token> = Vec::new();
|
||||||
|
|
||||||
let mut rtokens = tokens;
|
let mut rtokens = tokens.clone();
|
||||||
rtokens.reverse();
|
rtokens.reverse();
|
||||||
|
|
||||||
while !rtokens.is_empty() {
|
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 m = macros.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 {
|
||||||
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
|
} else
|
||||||
if let Some(mem) = mem {
|
if let Some(mem) = mem {
|
||||||
let mut t = op;
|
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::Int])?;
|
||||||
stack_pop(&mut stack, &op, &[Types::Ptr])?;
|
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 => {
|
InstructionType::Syscall0 => {
|
||||||
stack_pop(&mut stack, &op, &[Types::Int])?;
|
stack_pop(&mut stack, &op, &[Types::Int])?;
|
||||||
stack.push(Types::Int);
|
stack.push(Types::Int);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user