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