added relative imports

This commit is contained in:
MCorange 2023-04-01 13:20:35 +03:00
parent 747c4e59d4
commit 09bccc8079
13 changed files with 1102 additions and 557 deletions

23
README.md Normal file
View File

@ -0,0 +1,23 @@
# mclang rev2
This is the second revision of [MCLang](https://github.com/mc-lang/mclang) now written in rust!
## Goals
✅ - relatevely usable by normal programmers
✅ - speed comparable to unoptimised C (sometimes)
❌ - static typing
❌ - self hosted (maybe better if not? Since rust is fast asf)
❌ - multiplatform (~~windows~~, linux and mac)
❌ - interop with other languages
❌ - package manager
❌ - installer
## Documentation
The docs are currently are just made in MarkDown.
You can find the docs [here](/docs/index.md)
## Credits
[MCotange](https://github.com/MCorange99) - The one and only me, the creator and current maintainer or mclang rev1 and rev2

2
docs/index.md Normal file
View File

@ -0,0 +1,2 @@
# Docs

View File

@ -0,0 +1,212 @@
# Instructions And Keywords
This explains all of the instructions and keywords
## Instructions
Instructions modify the stack, the stack is an array, i will be using typescript to show how each instruction works
```ts
let stack: number[] = [];
```
### PushInt ("Any Number")
PushInt pushes one number on the stack.
Usage:
```forth
420
```
How it works:
```ts
// num = 420
stack.push(num);
console.assert(stack == [420]);
```
### PushStr ("Any String")
PushStr pushes 2 things on the stack, string length and string pointer
Usage:
```forth
"Henlo world!\n"
```
How it works:
```ts
stack.push(str_len);
stack.push(str_ptr);
```
### Print ("print")
Print just prints a number from the top of the stack into stdout
Usage:
```forth
69 print
```
How it works:
```ts
num = stack.pop()
console.log(num);
```
### Dup ("dup")
Dup duplicates the top most number on the stack
Usage:
```forth
69 dup
```
How it works:
```ts
stack = [12];
a = stack.pop();
stack.push(a);
stack.push(a);
console.assert(stack == [12, 12]);
```
### Drop ("drop")
Drop removes the top most number on the stack
Usage:
```forth
69 drop
```
How it works:
```ts
stack = [69];
stack.pop();
console.assert(stack == []);
```
### Rot ("rot")
Rot moves the third number from the top of the stack and moves it to the top
Usage:
```forth
1 2 3 rot
```
How it works:
```ts
stack = [1, 2, 3];
let a = stack.pop();
let b = stack.pop();
let c = stack.pop();
stack.push(b);
stack.push(a);
stack.push(c);
console.assert(stack == [3, 1, 2]);
```
### Over ("over")
Over takes the second number from the top of the stack and copies it to the top
Usage:
```forth
1 2 over
```
How it works:
```ts
stack = [1, 2];
let a = stack.pop();
let b = stack.pop();
stack.push(b);
stack.push(a);
stack.push(b);
console.assert(stack == [1, 2, 1]);
```
### Swap ("swap")
Swap swaps the first and second numbers from the stack
Usage:
```forth
1 2 stack
```
How it works:
```ts
stack = [1, 2];
let a = stack.pop();
let b = stack.pop();
stack.push(a);
stack.push(b);
console.assert(stack == [2, 1]);
```
### Plus ("+")
### Minus ("-")
### Mul ("*")
### Equals ("=")
### Gt (">")
### Lt ("<")
### NotEquals ("!=")
### Le ("<=")
### Ge (">=")
### Band ("band")
### Bor ("bor")
### Shr ("shr")
### Shl ("shl")
### DivMod ("divmod")
### Mem ("mem")
### Load8 ("@8")
### Store8 ("!8")
### Syscall0 ("syscall0")
### Syscall1 ("syscall1")
### Syscall2 ("syscall2")
### Syscall3 ("syscall3")
### Syscall4 ("syscall4")
### Syscall5 ("syscall5")
### Syscall6 ("syscall6")
### None ("None")
## Keywords
### If ("if")
### Else ("else")
### End ("end")
### While ("while")
### Do ("do")
### Macro ("macro")
### Include ("include")

View File

@ -75,335 +75,351 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
let token = &tokens[ti]; let token = &tokens[ti];
writeln!(writer, "addr_{ti}:")?; writeln!(writer, "addr_{ti}:")?;
match token.typ { match token.typ.clone() {
// stack // stack
OpType::Instruction(InstructionType::PushInt) => {
writeln!(writer, " ;; -- push int {}", token.value)?;
writeln!(writer, " mov rax, {}", token.value)?;
writeln!(writer, " push rax")?;
ti += 1;
},
OpType::Instruction(InstructionType::PushStr) => {
writeln!(writer, " ;; -- push str \"{}\"", token.text.escape_default())?;
writeln!(writer, " mov rax, {}", token.text.len())?;
writeln!(writer, " push rax")?;
writeln!(writer, " push str_{}", strings.len())?;
strings.push(token.text.clone());
ti += 1;
}
OpType::Instruction(InstructionType::Drop) => {
writeln!(writer, " ;; -- drop")?;
writeln!(writer, " pop rax")?;
ti += 1;
},
OpType::Instruction(InstructionType::Print) => {
writeln!(writer, " ;; -- print")?;
writeln!(writer, " pop rdi")?;
writeln!(writer, " call print")?;
ti += 1;
},
OpType::Instruction(InstructionType::Dup) => { OpType::Instruction(instruction) => {
writeln!(writer, " ;; -- dup")?; match instruction {
writeln!(writer, " pop rax")?; InstructionType::PushInt => {
writeln!(writer, " push rax")?; writeln!(writer, " ;; -- push int {}", token.value)?;
writeln!(writer, " push rax")?; writeln!(writer, " mov rax, {}", token.value)?;
writeln!(writer, " push rax")?;
ti += 1; ti += 1;
}, },
InstructionType::PushStr => {
OpType::Instruction(InstructionType::Rot) => { writeln!(writer, " ;; -- push str \"{}\"", token.text.escape_default())?;
writeln!(writer, " ;; -- rot")?; writeln!(writer, " mov rax, {}", token.text.len())?;
writeln!(writer, " pop rax")?; writeln!(writer, " push rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " push str_{}", strings.len())?;
writeln!(writer, " pop rcx")?; strings.push(token.text.clone());
writeln!(writer, " push rbx")?; ti += 1;
writeln!(writer, " push rax")?; }
writeln!(writer, " push rcx")?; InstructionType::Drop => {
writeln!(writer, " ;; -- drop")?;
ti += 1; writeln!(writer, " pop rax")?;
}, ti += 1;
OpType::Instruction(InstructionType::Swap) => { },
writeln!(writer, " ;; -- swap")?; InstructionType::Print => {
writeln!(writer, " pop rax")?; writeln!(writer, " ;; -- print")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rdi")?;
writeln!(writer, " push rax")?; writeln!(writer, " call print")?;
writeln!(writer, " push rbx")?; ti += 1;
},
ti += 1;
}, InstructionType::Dup => {
OpType::Instruction(InstructionType::Over) => { writeln!(writer, " ;; -- dup")?;
writeln!(writer, " ;; -- over")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rax")?; writeln!(writer, " push rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " push rax")?;
writeln!(writer, " push rbx")?;
writeln!(writer, " push rax")?; ti += 1;
writeln!(writer, " push rbx")?; },
ti += 1; InstructionType::Rot => {
}, writeln!(writer, " ;; -- rot")?;
writeln!(writer, " pop rax")?;
//mem writeln!(writer, " pop rbx")?;
OpType::Instruction(InstructionType::Mem) => { writeln!(writer, " pop rcx")?;
writeln!(writer, " ;; -- mem")?; writeln!(writer, " push rbx")?;
writeln!(writer, " push mem")?; writeln!(writer, " push rax")?;
ti += 1; writeln!(writer, " push rcx")?;
}
OpType::Instruction(InstructionType::Load8) => { ti += 1;
writeln!(writer, " ;; -- load")?; },
writeln!(writer, " pop rax")?; InstructionType::Swap => {
writeln!(writer, " xor rbx, rbx")?; writeln!(writer, " ;; -- swap")?;
writeln!(writer, " mov bl, [rax]")?; writeln!(writer, " pop rax")?;
writeln!(writer, " push rbx")?; writeln!(writer, " pop rbx")?;
ti += 1; writeln!(writer, " push rax")?;
} writeln!(writer, " push rbx")?;
OpType::Instruction(InstructionType::Store8) => { ti += 1;
writeln!(writer, " ;; -- store")?; },
writeln!(writer, " pop rbx")?; InstructionType::Over => {
writeln!(writer, " pop rax")?; writeln!(writer, " ;; -- over")?;
writeln!(writer, " mov [rax], bl")?; writeln!(writer, " pop rax")?;
ti += 1; writeln!(writer, " pop rbx")?;
} writeln!(writer, " push rbx")?;
writeln!(writer, " push rax")?;
// math writeln!(writer, " push rbx")?;
OpType::Instruction(InstructionType::Plus) => {
writeln!(writer, " ;; -- plus")?; ti += 1;
writeln!(writer, " pop rax")?; },
writeln!(writer, " pop rbx")?;
writeln!(writer, " add rax, rbx")?; //mem
writeln!(writer, " push rax")?; InstructionType::Mem => {
ti += 1; writeln!(writer, " ;; -- mem")?;
}, writeln!(writer, " push mem")?;
OpType::Instruction(InstructionType::Minus) => { ti += 1;
writeln!(writer, " ;; -- minus")?; }
writeln!(writer, " pop rax")?; InstructionType::Load8 => {
writeln!(writer, " pop rbx")?; writeln!(writer, " ;; -- load")?;
writeln!(writer, " sub rbx, rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " push rbx")?; writeln!(writer, " xor rbx, rbx")?;
ti += 1; writeln!(writer, " mov bl, [rax]")?;
}, writeln!(writer, " push rbx")?;
OpType::Instruction(InstructionType::Equals) => { ti += 1;
writeln!(writer, " ;; -- equals")?; }
writeln!(writer, " mov rcx, 0")?;
writeln!(writer, " mov rdx, 1")?; InstructionType::Store8 => {
writeln!(writer, " pop rax")?; writeln!(writer, " ;; -- store")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " cmp rax, rbx")?; writeln!(writer, " pop rax")?;
writeln!(writer, " cmove rcx, rdx")?; writeln!(writer, " mov [rax], bl")?;
writeln!(writer, " push rcx")?; ti += 1;
ti += 1; }
},
OpType::Instruction(InstructionType::Lt) => { // math
writeln!(writer, " ;; -- lt")?; InstructionType::Plus => {
writeln!(writer, " mov rcx, 0")?; writeln!(writer, " ;; -- plus")?;
writeln!(writer, " mov rdx, 1")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " pop rax")?; writeln!(writer, " add rax, rbx")?;
writeln!(writer, " cmp rax, rbx")?; writeln!(writer, " push rax")?;
writeln!(writer, " cmovl rcx, rdx")?; ti += 1;
writeln!(writer, " push rcx")?; },
ti += 1; InstructionType::Minus => {
}, writeln!(writer, " ;; -- minus")?;
OpType::Instruction(InstructionType::Gt) => { writeln!(writer, " pop rax")?;
writeln!(writer, " ;; -- gt")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " mov rcx, 0")?; writeln!(writer, " sub rbx, rax")?;
writeln!(writer, " mov rdx, 1")?; writeln!(writer, " push rbx")?;
writeln!(writer, " pop rbx")?; ti += 1;
writeln!(writer, " pop rax")?; },
writeln!(writer, " cmp rax, rbx")?; InstructionType::Equals => {
writeln!(writer, " cmovg rcx, rdx")?; writeln!(writer, " ;; -- equals")?;
writeln!(writer, " push rcx")?; writeln!(writer, " mov rcx, 0")?;
ti += 1; writeln!(writer, " mov rdx, 1")?;
}, writeln!(writer, " pop rax")?;
OpType::Instruction(InstructionType::NotEquals) => { writeln!(writer, " pop rbx")?;
writeln!(writer, " ;; -- not equals")?; writeln!(writer, " cmp rax, rbx")?;
writeln!(writer, " mov rcx, 1")?; writeln!(writer, " cmove rcx, rdx")?;
writeln!(writer, " mov rdx, 0")?; writeln!(writer, " push rcx")?;
writeln!(writer, " pop rax")?; ti += 1;
writeln!(writer, " pop rbx")?; },
writeln!(writer, " cmp rax, rbx")?; InstructionType::Lt => {
writeln!(writer, " cmove rcx, rdx")?; writeln!(writer, " ;; -- lt")?;
writeln!(writer, " push rcx")?; writeln!(writer, " mov rcx, 0")?;
ti += 1; writeln!(writer, " mov rdx, 1")?;
}, writeln!(writer, " pop rbx")?;
OpType::Instruction(InstructionType::Le) => { writeln!(writer, " pop rax")?;
writeln!(writer, " ;; -- lt")?; writeln!(writer, " cmp rax, rbx")?;
writeln!(writer, " mov rcx, 0")?; writeln!(writer, " cmovl rcx, rdx")?;
writeln!(writer, " mov rdx, 1")?; writeln!(writer, " push rcx")?;
writeln!(writer, " pop rbx")?; ti += 1;
writeln!(writer, " pop rax")?; },
writeln!(writer, " cmp rax, rbx")?; InstructionType::Gt => {
writeln!(writer, " cmovle rcx, rdx")?; writeln!(writer, " ;; -- gt")?;
writeln!(writer, " push rcx")?; writeln!(writer, " mov rcx, 0")?;
ti += 1; writeln!(writer, " mov rdx, 1")?;
}, writeln!(writer, " pop rbx")?;
OpType::Instruction(InstructionType::Ge) => { writeln!(writer, " pop rax")?;
writeln!(writer, " ;; -- gt")?; writeln!(writer, " cmp rax, rbx")?;
writeln!(writer, " mov rcx, 0")?; writeln!(writer, " cmovg rcx, rdx")?;
writeln!(writer, " mov rdx, 1")?; writeln!(writer, " push rcx")?;
writeln!(writer, " pop rbx")?; ti += 1;
writeln!(writer, " pop rax")?; },
writeln!(writer, " cmp rax, rbx")?; InstructionType::NotEquals => {
writeln!(writer, " cmovge rcx, rdx")?; writeln!(writer, " ;; -- not equals")?;
writeln!(writer, " push rcx")?; writeln!(writer, " mov rcx, 1")?;
ti += 1; writeln!(writer, " mov rdx, 0")?;
}, writeln!(writer, " pop rax")?;
OpType::Instruction(InstructionType::Band) => { writeln!(writer, " pop rbx")?;
writeln!(writer, " ;; -- band")?; writeln!(writer, " cmp rax, rbx")?;
writeln!(writer, " pop rax")?; writeln!(writer, " cmove rcx, rdx")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " push rcx")?;
writeln!(writer, " and rbx, rax")?; ti += 1;
writeln!(writer, " push rbx")?; },
ti += 1; InstructionType::Le => {
}, writeln!(writer, " ;; -- lt")?;
OpType::Instruction(InstructionType::Bor) => { writeln!(writer, " mov rcx, 0")?;
writeln!(writer, " ;; -- bor")?; writeln!(writer, " mov rdx, 1")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " pop rax")?;
writeln!(writer, " or rbx, rax")?; writeln!(writer, " cmp rax, rbx")?;
writeln!(writer, " push rbx")?; writeln!(writer, " cmovle rcx, rdx")?;
ti += 1; writeln!(writer, " push rcx")?;
}, ti += 1;
OpType::Instruction(InstructionType::Shr) => { },
writeln!(writer, " ;; -- shr")?; InstructionType::Ge => {
writeln!(writer, " pop rcx")?; writeln!(writer, " ;; -- gt")?;
writeln!(writer, " pop rbx")?; writeln!(writer, " mov rcx, 0")?;
writeln!(writer, " shr rbx, cl")?; writeln!(writer, " mov rdx, 1")?;
writeln!(writer, " push rbx")?; writeln!(writer, " pop rbx")?;
ti += 1; writeln!(writer, " pop rax")?;
}, writeln!(writer, " cmp rax, rbx")?;
OpType::Instruction(InstructionType::Shl) => { writeln!(writer, " cmovge rcx, rdx")?;
writeln!(writer, " ;; -- shl")?; writeln!(writer, " push rcx")?;
writeln!(writer, " pop rcx")?; ti += 1;
writeln!(writer, " pop rbx")?; },
writeln!(writer, " shl rbx, cl")?; InstructionType::Band => {
writeln!(writer, " push rbx")?; writeln!(writer, " ;; -- band")?;
ti += 1; writeln!(writer, " pop rax")?;
}, writeln!(writer, " pop rbx")?;
OpType::Instruction(InstructionType::DivMod) => { writeln!(writer, " and rbx, rax")?;
writeln!(writer, " ;; -- div")?; writeln!(writer, " push rbx")?;
writeln!(writer, " xor rdx, rdx")?; ti += 1;
writeln!(writer, " pop rbx")?; },
writeln!(writer, " pop rax")?; InstructionType::Bor => {
writeln!(writer, " div rbx")?; writeln!(writer, " ;; -- bor")?;
writeln!(writer, " push rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " push rdx")?; writeln!(writer, " pop rbx")?;
ti += 1; writeln!(writer, " or rbx, rax")?;
}, writeln!(writer, " push rbx")?;
OpType::Instruction(InstructionType::Mul) => { ti += 1;
writeln!(writer, " ;; -- mul")?; },
writeln!(writer, " pop rax")?; InstructionType::Shr => {
writeln!(writer, " pop rbx")?; writeln!(writer, " ;; -- shr")?;
writeln!(writer, " mul rbx")?; writeln!(writer, " pop rcx")?;
writeln!(writer, " push rax")?; writeln!(writer, " pop rbx")?;
ti += 1; writeln!(writer, " shr rbx, cl")?;
}, writeln!(writer, " push rbx")?;
ti += 1;
},
// block InstructionType::Shl => {
OpType::Keyword(KeywordType::If) => { writeln!(writer, " ;; -- shl")?;
writeln!(writer, " ;; -- if")?; writeln!(writer, " pop rcx")?;
writeln!(writer, " pop rax")?; writeln!(writer, " pop rbx")?;
writeln!(writer, " test rax, rax")?; writeln!(writer, " shl rbx, cl")?;
writeln!(writer, " jz addr_{}", token.jmp)?; writeln!(writer, " push rbx")?;
ti += 1; ti += 1;
}, },
OpType::Keyword(KeywordType::Else) => { InstructionType::DivMod => {
writeln!(writer, " ;; -- else")?; writeln!(writer, " ;; -- div")?;
writeln!(writer, " jmp addr_{}", token.jmp)?; writeln!(writer, " xor rdx, rdx")?;
ti += 1; writeln!(writer, " pop rbx")?;
}, writeln!(writer, " pop rax")?;
OpType::Keyword(KeywordType::While) => { writeln!(writer, " div rbx")?;
writeln!(writer, " ;; -- while")?; writeln!(writer, " push rax")?;
ti += 1; writeln!(writer, " push rdx")?;
} ti += 1;
OpType::Keyword(KeywordType::Do) => { },
writeln!(writer, " ;; -- do")?; InstructionType::Mul => {
writeln!(writer, " pop rax")?; writeln!(writer, " ;; -- mul")?;
writeln!(writer, " test rax, rax")?; writeln!(writer, " pop rax")?;
writeln!(writer, " jz addr_{}", token.jmp)?; writeln!(writer, " pop rbx")?;
ti += 1; writeln!(writer, " mul rbx")?;
} writeln!(writer, " push rax")?;
OpType::Keyword(KeywordType::End) => { ti += 1;
writeln!(writer, " ;; -- end")?; },
if ti + 1 != token.jmp { InstructionType::Syscall0 => {
writeln!(writer, " jmp addr_{}", token.jmp)?; writeln!(writer, " ;; -- syscall0")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
},
InstructionType::Syscall1 => {
writeln!(writer, " ;; -- syscall1")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
},
InstructionType::Syscall2 => {
writeln!(writer, " ;; -- syscall2")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
},
InstructionType::Syscall3 => {
writeln!(writer, " ;; -- syscall3")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?;
writeln!(writer, " pop rdx")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
},
InstructionType::Syscall4 => {
writeln!(writer, " ;; -- syscall4")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?;
writeln!(writer, " pop rdx")?;
writeln!(writer, " pop r10")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
},
InstructionType::Syscall5 => {
writeln!(writer, " ;; -- syscall5")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?;
writeln!(writer, " pop rdx")?;
writeln!(writer, " pop r10")?;
writeln!(writer, " pop r8")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
},
InstructionType::Syscall6 => {
writeln!(writer, " ;; -- syscall6")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?;
writeln!(writer, " pop rdx")?;
writeln!(writer, " pop r10")?;
writeln!(writer, " pop r8")?;
writeln!(writer, " pop r9")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
},
InstructionType::None => unreachable!(),
InstructionType::CastBool => ti += 1,
InstructionType::CastPtr => ti += 1,
InstructionType::CastInt => ti += 1,
} }
ti += 1; }
},
OpType::Instruction(InstructionType::Syscall0) => {
writeln!(writer, " ;; -- syscall0")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
},
OpType::Instruction(InstructionType::Syscall1) => {
writeln!(writer, " ;; -- syscall1")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
},
OpType::Instruction(InstructionType::Syscall2) => {
writeln!(writer, " ;; -- syscall2")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
},
OpType::Instruction(InstructionType::Syscall3) => {
writeln!(writer, " ;; -- syscall3")?;
writeln!(writer, " pop rax")?;
writeln!(writer, " pop rdi")?;
writeln!(writer, " pop rsi")?;
writeln!(writer, " pop rdx")?;
writeln!(writer, " syscall")?;
writeln!(writer, " push rax")?;
ti += 1;
}, OpType::Keyword(keyword) => {
OpType::Instruction(InstructionType::Syscall4) => { match keyword {
writeln!(writer, " ;; -- syscall4")?;
writeln!(writer, " pop rax")?; // block
writeln!(writer, " pop rdi")?; KeywordType::If => {
writeln!(writer, " pop rsi")?; writeln!(writer, " ;; -- if")?;
writeln!(writer, " pop rdx")?; writeln!(writer, " pop rax")?;
writeln!(writer, " pop r10")?; writeln!(writer, " test rax, rax")?;
writeln!(writer, " syscall")?; writeln!(writer, " jz addr_{}", token.jmp)?;
writeln!(writer, " push rax")?; ti += 1;
ti += 1; },
}, KeywordType::Else => {
OpType::Instruction(InstructionType::Syscall5) => { writeln!(writer, " ;; -- else")?;
writeln!(writer, " ;; -- syscall5")?; writeln!(writer, " jmp addr_{}", token.jmp)?;
writeln!(writer, " pop rax")?; ti += 1;
writeln!(writer, " pop rdi")?; },
writeln!(writer, " pop rsi")?; KeywordType::While => {
writeln!(writer, " pop rdx")?; writeln!(writer, " ;; -- while")?;
writeln!(writer, " pop r10")?; ti += 1;
writeln!(writer, " pop r8")?; }
writeln!(writer, " syscall")?; KeywordType::Do => {
writeln!(writer, " push rax")?; writeln!(writer, " ;; -- do")?;
ti += 1; writeln!(writer, " pop rax")?;
}, writeln!(writer, " test rax, rax")?;
OpType::Instruction(InstructionType::Syscall6) => { writeln!(writer, " jz addr_{}", token.jmp)?;
writeln!(writer, " ;; -- syscall6")?; ti += 1;
writeln!(writer, " pop rax")?; }
writeln!(writer, " pop rdi")?; KeywordType::End => {
writeln!(writer, " pop rsi")?; writeln!(writer, " ;; -- end")?;
writeln!(writer, " pop rdx")?; if ti + 1 != token.jmp {
writeln!(writer, " pop r10")?; writeln!(writer, " jmp addr_{}", token.jmp)?;
writeln!(writer, " pop r8")?; }
writeln!(writer, " pop r9")?; ti += 1;
writeln!(writer, " syscall")?; },
writeln!(writer, " push rax")?; KeywordType::Macro |
ti += 1; KeywordType::Include
}, => unreachable!()
OpType::Instruction(InstructionType::None) | OpType::Keyword(KeywordType::Macro) | OpType::Keyword(KeywordType::Include) => unreachable!() }
}
} }
} }
writeln!(writer, "addr_{ti}:")?; writeln!(writer, "addr_{ti}:")?;
@ -411,10 +427,10 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
writeln!(writer, " mov rdi, 0")?; writeln!(writer, " mov rdi, 0")?;
writeln!(writer, " syscall")?; writeln!(writer, " syscall")?;
writeln!(writer, "segment .data")?; writeln!(writer, "segment .data")?;
for (_, s) in strings.iter().enumerate() { for (i, s) in strings.iter().enumerate() {
let s_chars = s.chars().map(|c| (c as u32).to_string()).collect::<Vec<String>>(); let s_chars = s.chars().map(|c| (c as u32).to_string()).collect::<Vec<String>>();
let s_list = s_chars.join(","); let s_list = s_chars.join(",");
writeln!(writer, " str_{}: db {} ; {}", s, s_list, s.escape_default())?; writeln!(writer, " str_{}: db {} ; {}", i, s_list, s.escape_default())?;
} }
writeln!(writer, "segment .bss")?; writeln!(writer, "segment .bss")?;

View File

@ -46,6 +46,10 @@ pub enum InstructionType {
Syscall5, Syscall5,
Syscall6, Syscall6,
CastBool,
CastPtr,
CastInt,
None // Used for macros and any other non built in word definitions None // Used for macros and any other non built in word definitions
} }
@ -132,7 +136,10 @@ impl OpType {
OpType::Instruction(InstructionType::Syscall4) => "syscall4", OpType::Instruction(InstructionType::Syscall4) => "syscall4",
OpType::Instruction(InstructionType::Syscall5) => "syscall5", OpType::Instruction(InstructionType::Syscall5) => "syscall5",
OpType::Instruction(InstructionType::Syscall6) => "syscall6", OpType::Instruction(InstructionType::Syscall6) => "syscall6",
OpType::Instruction(InstructionType::None) => "None" OpType::Instruction(InstructionType::CastBool) => "cast(bool",
OpType::Instruction(InstructionType::CastPtr) => "cast(ptr)",
OpType::Instruction(InstructionType::CastInt) => "cast(int)",
OpType::Instruction(InstructionType::None) => "None",
}.to_string() }.to_string()
} }
} }
@ -175,4 +182,18 @@ impl TokenType {
} }
} }
pub type Loc = (String, usize, usize); pub type Loc = (String, usize, usize);
#[derive(Debug, PartialEq, Clone)]
pub enum Types {
Bool,
Ptr,
Int,
Any
// U8,
// U16,
// U32,
// U64,
// todo: add signed numbers since we dont have them yet lol
}

View File

@ -24,187 +24,235 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
let token = &tokens[ti]; let token = &tokens[ti];
let pos = token.loc.clone(); let pos = token.loc.clone();
// println!("{:?}", token.typ); // println!("{:?}", token.typ);
match token.typ { match token.typ.clone() {
OpType::Instruction(instruction) => {
// stack match instruction {
OpType::Instruction(InstructionType::PushInt) => { InstructionType::PushInt => {
stack.push(token.value); stack.push(token.value);
ti += 1; ti += 1;
}, },
OpType::Instruction(InstructionType::PushStr) => { InstructionType::PushStr => {
if token.addr.is_none() { if token.addr.is_none() {
stack.push(token.text.len()); // string len stack.push(token.text.len()); // string len
stack.push(string_idx + crate::compile::MEM_SZ); stack.push(string_idx + crate::compile::MEM_SZ);
for c in token.text.bytes() {
mem[crate::compile::MEM_SZ + string_idx] = c;
string_idx += 1;
}
} else {
stack.push(token.text.len());
if let Some(addr) = token.addr {
stack.push(addr);
}
}
ti += 1;
},
InstructionType::Drop => {
stack.pop();
ti += 1;
},
InstructionType::Dup => {
let a = stack_pop(&mut stack, &pos)?;
stack.push(a);
stack.push(a);
ti += 1;
},
InstructionType::Rot => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
let c = stack_pop(&mut stack, &pos)?;
stack.push(b);
stack.push(a);
stack.push(c);
ti += 1;
}
InstructionType::Swap => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(a);
stack.push(b);
ti += 1;
}
InstructionType::Over => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b);
stack.push(a);
stack.push(b);
ti += 1;
}
InstructionType::Print => {
let a = stack_pop(&mut stack, &pos)?;
println!("{a}");
// let _ = io::stdout().flush();
ti += 1;
},
// mem
InstructionType::Mem => {
stack.push(0);
ti += 1;
}
InstructionType::Load8 => {
let a = stack_pop(&mut stack, &pos)?;
let byte = mem[a];
stack.push(byte as usize);
ti += 1;
}
#[allow(clippy::cast_possible_truncation)]
InstructionType::Store8 => {
let val = stack_pop(&mut stack, &pos)?;
let addr = stack_pop(&mut stack, &pos)?;
mem[addr] = (val & 0xFF) as u8;
ti += 1;
}
// math
InstructionType::Plus => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b + a);
ti += 1;
},
InstructionType::Minus => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b - a);
ti += 1;
},
InstructionType::Equals => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b == a));
ti += 1;
},
InstructionType::Gt => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b > a));
ti += 1;
},
InstructionType::Lt => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b < a));
ti += 1;
},
InstructionType::NotEquals => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b != a));
ti += 1;
},
InstructionType::Ge => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b >= a));
ti += 1;
},
InstructionType::Le => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b <= a));
ti += 1;
},
InstructionType::Band => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(a & b);
ti += 1;
}
InstructionType::Bor => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(a | b);
ti += 1;
}
InstructionType::Shr => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b >> a);
ti += 1;
}
InstructionType::Shl => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b << a);
ti += 1;
}
for c in token.text.bytes() { InstructionType::DivMod => {
mem[crate::compile::MEM_SZ + string_idx] = c; let a = stack_pop(&mut stack, &pos)?;
string_idx += 1; let b = stack_pop(&mut stack, &pos)?;
stack.push(b / a);
stack.push(b % a);
ti += 1;
} }
} else { InstructionType::Mul => {
stack.push(token.text.len()); let a = stack_pop(&mut stack, &pos)?;
if let Some(addr) = token.addr { let b = stack_pop(&mut stack, &pos)?;
stack.push(addr); stack.push(b * a);
ti += 1;
} }
InstructionType::Syscall0 => {
todo!();
// ti += 1;
},
InstructionType::Syscall1 => {
todo!();
// ti += 1;
},
InstructionType::Syscall2 => {
todo!();
// ti += 1;
},
InstructionType::Syscall3 => {
let rax = stack_pop(&mut stack, &pos)?;
let rdi = stack_pop(&mut stack, &pos)?;
let rsi = stack_pop(&mut stack, &pos)?;
let rdx = stack_pop(&mut stack, &pos)?;
// println!("yes");
let ret = match rax {
1 => syscalls::sys_write(rax, rdi, rsi, rdx, &mem),
0 => 0, //? temp, so clippy doesnt complain
_ => {
error!("Syscall(3) #{} is not implemented", rax);
return Err(eyre!("Syscall not implemented"));
}
};
stack.push(ret);
// println!("{}", stack.len());
ti += 1;
},
InstructionType::Syscall4 => {
todo!();
// ti += 1;
},
InstructionType::Syscall5 => {
todo!();
// ti += 1;
},
InstructionType::Syscall6 => {
todo!();
// ti += 1;
},
InstructionType::CastBool => ti += 1,
InstructionType::CastPtr => ti += 1,
InstructionType::CastInt => ti += 1,
InstructionType::None => unreachable!()
} }
ti += 1;
},
OpType::Instruction(InstructionType::Drop) => {
stack.pop();
ti += 1;
},
OpType::Instruction(InstructionType::Dup) => {
let a = stack_pop(&mut stack, &pos)?;
stack.push(a);
stack.push(a);
ti += 1;
},
OpType::Instruction(InstructionType::Rot) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
let c = stack_pop(&mut stack, &pos)?;
stack.push(b);
stack.push(a);
stack.push(c);
ti += 1;
} }
OpType::Instruction(InstructionType::Swap) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(a);
stack.push(b);
ti += 1;
}
OpType::Instruction(InstructionType::Over) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b);
stack.push(a);
stack.push(b);
ti += 1;
}
OpType::Instruction(InstructionType::Print) => {
let a = stack_pop(&mut stack, &pos)?;
println!("{a}");
// let _ = io::stdout().flush();
ti += 1;
},
// mem
OpType::Instruction(InstructionType::Mem) => {
stack.push(0);
ti += 1;
}
OpType::Instruction(InstructionType::Load8) => {
let a = stack_pop(&mut stack, &pos)?;
let byte = mem[a];
stack.push(byte as usize);
ti += 1;
}
#[allow(clippy::cast_possible_truncation)]
OpType::Instruction(InstructionType::Store8) => {
let val = stack_pop(&mut stack, &pos)?;
let addr = stack_pop(&mut stack, &pos)?;
mem[addr] = (val & 0xFF) as u8;
ti += 1;
}
// math
OpType::Instruction(InstructionType::Plus) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b + a);
ti += 1;
},
OpType::Instruction(InstructionType::Minus) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b - a);
ti += 1;
},
OpType::Instruction(InstructionType::Equals) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b == a));
ti += 1;
},
OpType::Instruction(InstructionType::Gt) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b > a));
ti += 1;
},
OpType::Instruction(InstructionType::Lt) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b < a));
ti += 1;
},
OpType::Instruction(InstructionType::NotEquals) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b != a));
ti += 1;
},
OpType::Instruction(InstructionType::Ge) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b >= a));
ti += 1;
},
OpType::Instruction(InstructionType::Le) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(usize::from(b <= a));
ti += 1;
},
OpType::Instruction(InstructionType::Band) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(a & b);
ti += 1;
}
OpType::Instruction(InstructionType::Bor) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(a | b);
ti += 1;
}
OpType::Instruction(InstructionType::Shr) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b >> a);
ti += 1;
}
OpType::Instruction(InstructionType::Shl) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b << a);
ti += 1;
}
OpType::Instruction(InstructionType::DivMod) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b / a);
stack.push(b % a);
ti += 1;
}
OpType::Instruction(InstructionType::Mul) => {
let a = stack_pop(&mut stack, &pos)?;
let b = stack_pop(&mut stack, &pos)?;
stack.push(b * a);
ti += 1;
}
// blocks // blocks
OpType::Keyword(KeywordType::If) => { OpType::Keyword(KeywordType::If) => {
@ -230,49 +278,7 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
ti += 1; ti += 1;
} }
} }
OpType::Instruction(InstructionType::Syscall0) => { | OpType::Keyword(KeywordType::Macro) | OpType::Keyword(KeywordType::Include) => unreachable!()
todo!();
// ti += 1;
},
OpType::Instruction(InstructionType::Syscall1) => {
todo!();
// ti += 1;
},
OpType::Instruction(InstructionType::Syscall2) => {
todo!();
// ti += 1;
},
OpType::Instruction(InstructionType::Syscall3) => {
let rax = stack_pop(&mut stack, &pos)?;
let rdi = stack_pop(&mut stack, &pos)?;
let rsi = stack_pop(&mut stack, &pos)?;
let rdx = stack_pop(&mut stack, &pos)?;
// println!("yes");
let ret = match rax {
1 => syscalls::sys_write(rax, rdi, rsi, rdx, &mem),
0 => 0, //? temp, so clippy doesnt complain
_ => {
error!("Syscall(3) #{} is not implemented", rax);
return Err(eyre!("Syscall not implemented"));
}
};
stack.push(ret);
// println!("{}", stack.len());
ti += 1;
},
OpType::Instruction(InstructionType::Syscall4) => {
todo!();
// ti += 1;
},
OpType::Instruction(InstructionType::Syscall5) => {
todo!();
// ti += 1;
},
OpType::Instruction(InstructionType::Syscall6) => {
todo!();
// ti += 1;
},
OpType::Instruction(InstructionType::None) | OpType::Keyword(KeywordType::Macro) | OpType::Keyword(KeywordType::Include) => unreachable!()
} }
} }

View File

@ -5,6 +5,7 @@ mod compile;
mod parser; mod parser;
mod lexer; mod lexer;
mod preprocessor; mod preprocessor;
mod typechecker;
use std::fs; use std::fs;
@ -54,6 +55,8 @@ pub struct Args {
} }
fn main() { fn main() {
let args = Args::parse(); let args = Args::parse();
let Ok(code) = fs::read_to_string(&args.in_file) else { let Ok(code) = fs::read_to_string(&args.in_file) else {
@ -73,6 +76,11 @@ fn main() {
return; return;
}; };
let Ok(tokens) = typechecker::typecheck(&tokens, &args) else {
error!("Typechecking failed, exiting!");
return;
};
let c = if args.compile && args.interpret { let c = if args.compile && args.interpret {
error!("Cannot compile and interpret at the same time"); error!("Cannot compile and interpret at the same time");
0 0

View File

@ -156,6 +156,9 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
"syscall4" => OpType::Instruction(InstructionType::Syscall4), "syscall4" => OpType::Instruction(InstructionType::Syscall4),
"syscall5" => OpType::Instruction(InstructionType::Syscall5), "syscall5" => OpType::Instruction(InstructionType::Syscall5),
"syscall6" => OpType::Instruction(InstructionType::Syscall6), "syscall6" => OpType::Instruction(InstructionType::Syscall6),
"cast(bool" => OpType::Instruction(InstructionType::CastBool),
"cast(ptr)" => OpType::Instruction(InstructionType::CastPtr),
"cast(int)" => OpType::Instruction(InstructionType::CastInt),
_ => OpType::Instruction(InstructionType::None) _ => OpType::Instruction(InstructionType::None)
} }

View File

@ -1,5 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::path::PathBuf; use std::path::{PathBuf, Path};
use color_eyre::Result; use color_eyre::Result;
use eyre::eyre; use eyre::eyre;
@ -93,18 +93,25 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
let mut include_code = String::new(); let mut include_code = String::new();
for path in in_paths { if include_path.text.chars().collect::<Vec<char>>()[0] == '.' {
let p = PathBuf::from(path); let p = Path::new(include_path.file.as_str());
let p = p.join(include_path.text.clone()); let p = p.parent().unwrap();
let p = p.join(&include_path.text);
if p.exists() { include_code = std::fs::read_to_string(p)?;
include_code = std::fs::read_to_string(p)?; } else {
for path in in_paths {
let p = PathBuf::from(path);
let p = p.join(&include_path.text);
if p.exists() {
include_code = std::fs::read_to_string(p)?;
}
} }
} }
if include_code.is_empty() { if include_code.is_empty() {
lerror!(&include_path.loc(), "Include file in path '{}' was not found", include_path.text); lerror!(&include_path.loc(), "Include file in path '{}' was not found or is empty", include_path.text);
return Err(eyre!("")); return Err(eyre!(""));
} }

245
src/typechecker.rs Normal file
View File

@ -0,0 +1,245 @@
use crate::{constants::{Operator, Types, OpType, KeywordType, InstructionType}, Args, lerror};
use color_eyre::Result;
use eyre::eyre;
pub fn typecheck(ops: &[Operator], args: &Args) -> Result<Vec<Operator>>{
let mut stack: Vec<Types> = Vec::new();
for op in ops {
match op.typ.clone() {
OpType::Keyword(keyword) => {
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 => {
},
}
},
OpType::Instruction(instruction) => {
match instruction {
InstructionType::PushInt => {
stack.push(Types::Int);
},
InstructionType::PushStr => {
stack.push(Types::Int);
stack.push(Types::Ptr);
},
InstructionType::Drop => {
stack_pop(&mut stack, &op, &[Types::Any])?;
},
InstructionType::Print => {
stack_pop(&mut stack, &op, &[Types::Int])?;
},
InstructionType::Dup => {
let a = stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(a);
},
InstructionType::Rot => {
let a = stack_pop(&mut stack, &op, &[Types::Any])?;
let b = stack_pop(&mut stack, &op, &[Types::Any])?;
let c = stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(b);
stack.push(a);
stack.push(c);
},
InstructionType::Over => {
let a = stack_pop(&mut stack, &op, &[Types::Any])?;
let b = stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(b.clone());
stack.push(a);
stack.push(b);
},
InstructionType::Swap => {
let a = stack_pop(&mut stack, &op, &[Types::Any])?;
let b = stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(a);
stack.push(b);
},
InstructionType::Minus => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack.push(Types::Int);
},
InstructionType::Plus => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack.push(Types::Int);
},
InstructionType::Equals => {
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack.push(Types::Bool);
},
InstructionType::Gt => {
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack.push(Types::Bool);
},
InstructionType::Lt => {
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack.push(Types::Bool);
},
InstructionType::Ge => {
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack.push(Types::Bool);
},
InstructionType::Le => {
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack.push(Types::Bool);
},
InstructionType::NotEquals => {
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
stack.push(Types::Bool);
},
InstructionType::Band => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Int])?;
stack.push(Types::Int);
},
InstructionType::Bor => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Int])?;
stack.push(Types::Int);
},
InstructionType::Shr => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Int])?;
stack.push(Types::Int);
},
InstructionType::Shl => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Int])?;
stack.push(Types::Int);
},
InstructionType::DivMod => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Int])?;
stack.push(Types::Int);
stack.push(Types::Int);
},
InstructionType::Mul => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Int])?;
stack.push(Types::Int);
},
InstructionType::Mem => {
stack.push(Types::Ptr);
},
InstructionType::Load8 => {
stack_pop(&mut stack, &op, &[Types::Ptr])?;
stack.push(Types::Int);
},
InstructionType::Store8 => {
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);
},
InstructionType::Syscall1 => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(Types::Int);
},
InstructionType::Syscall2 => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(Types::Int);
},
InstructionType::Syscall3 => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(Types::Int);
},
InstructionType::Syscall4 => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(Types::Int);
},
InstructionType::Syscall5 => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(Types::Int);
},
InstructionType::Syscall6 => {
stack_pop(&mut stack, &op, &[Types::Int])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(Types::Int);
},
InstructionType::CastBool => {
stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(Types::Bool);
},
InstructionType::CastPtr => {
stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(Types::Ptr);
},
InstructionType::CastInt => {
stack_pop(&mut stack, &op, &[Types::Any])?;
stack.push(Types::Int);
},
InstructionType::None => {},
}
},
}
}
Ok(ops.to_vec())
}
fn stack_pop(v: &mut Vec<Types>, op: &Operator, t: &[Types]) -> Result<Types> {
if v.is_empty() {
lerror!(&op.loc, "Expected {:?}, but got nothing", t);
return Err(eyre!(""));
}
let r = v.pop().unwrap();
if !t.contains(&r) && t[0] != Types::Any {
lerror!(&op.loc, "Expected {:?}, but got {:?}", t, r);
return Err(eyre!(""));
}
Ok(r)
}

View File

@ -1 +1,3 @@
' ' print include "./asd.mcl"
1 test