added relative imports
This commit is contained in:
parent
747c4e59d4
commit
09bccc8079
23
README.md
Normal file
23
README.md
Normal 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
2
docs/index.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Docs
|
||||||
|
|
212
docs/instructions_and_keywords.md
Normal file
212
docs/instructions_and_keywords.md
Normal 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")
|
|
@ -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;
|
||||||
|
},
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
InstructionType::Drop => {
|
||||||
|
writeln!(writer, " ;; -- drop")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Print => {
|
||||||
|
writeln!(writer, " ;; -- print")?;
|
||||||
|
writeln!(writer, " pop rdi")?;
|
||||||
|
writeln!(writer, " call print")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
|
||||||
ti += 1;
|
InstructionType::Dup => {
|
||||||
},
|
writeln!(writer, " ;; -- dup")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " push rax")?;
|
||||||
|
writeln!(writer, " push rax")?;
|
||||||
|
|
||||||
OpType::Instruction(InstructionType::Rot) => {
|
ti += 1;
|
||||||
writeln!(writer, " ;; -- rot")?;
|
},
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rcx")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
|
|
||||||
ti += 1;
|
InstructionType::Rot => {
|
||||||
},
|
writeln!(writer, " ;; -- rot")?;
|
||||||
OpType::Instruction(InstructionType::Swap) => {
|
writeln!(writer, " pop rax")?;
|
||||||
writeln!(writer, " ;; -- swap")?;
|
writeln!(writer, " pop rbx")?;
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " pop rcx")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
writeln!(writer, " push rbx")?;
|
||||||
writeln!(writer, " push rax")?;
|
writeln!(writer, " push rax")?;
|
||||||
writeln!(writer, " push rbx")?;
|
writeln!(writer, " push rcx")?;
|
||||||
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
OpType::Instruction(InstructionType::Over) => {
|
InstructionType::Swap => {
|
||||||
writeln!(writer, " ;; -- over")?;
|
writeln!(writer, " ;; -- swap")?;
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " pop rax")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
writeln!(writer, " pop rbx")?;
|
||||||
writeln!(writer, " push rbx")?;
|
writeln!(writer, " push rax")?;
|
||||||
writeln!(writer, " push rax")?;
|
writeln!(writer, " push rbx")?;
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
|
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
|
InstructionType::Over => {
|
||||||
|
writeln!(writer, " ;; -- over")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " push rbx")?;
|
||||||
|
writeln!(writer, " push rax")?;
|
||||||
|
writeln!(writer, " push rbx")?;
|
||||||
|
|
||||||
//mem
|
ti += 1;
|
||||||
OpType::Instruction(InstructionType::Mem) => {
|
},
|
||||||
writeln!(writer, " ;; -- mem")?;
|
|
||||||
writeln!(writer, " push mem")?;
|
|
||||||
ti += 1;
|
|
||||||
}
|
|
||||||
OpType::Instruction(InstructionType::Load8) => {
|
|
||||||
writeln!(writer, " ;; -- load")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " xor rbx, rbx")?;
|
|
||||||
writeln!(writer, " mov bl, [rax]")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
OpType::Instruction(InstructionType::Store8) => {
|
//mem
|
||||||
writeln!(writer, " ;; -- store")?;
|
InstructionType::Mem => {
|
||||||
writeln!(writer, " pop rbx")?;
|
writeln!(writer, " ;; -- mem")?;
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " push mem")?;
|
||||||
writeln!(writer, " mov [rax], bl")?;
|
ti += 1;
|
||||||
ti += 1;
|
}
|
||||||
}
|
InstructionType::Load8 => {
|
||||||
|
writeln!(writer, " ;; -- load")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " xor rbx, rbx")?;
|
||||||
|
writeln!(writer, " mov bl, [rax]")?;
|
||||||
|
writeln!(writer, " push rbx")?;
|
||||||
|
ti += 1;
|
||||||
|
}
|
||||||
|
|
||||||
// math
|
InstructionType::Store8 => {
|
||||||
OpType::Instruction(InstructionType::Plus) => {
|
writeln!(writer, " ;; -- store")?;
|
||||||
writeln!(writer, " ;; -- plus")?;
|
writeln!(writer, " pop rbx")?;
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " pop rax")?;
|
||||||
writeln!(writer, " pop rbx")?;
|
writeln!(writer, " mov [rax], bl")?;
|
||||||
writeln!(writer, " add rax, rbx")?;
|
ti += 1;
|
||||||
writeln!(writer, " push rax")?;
|
}
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::Minus) => {
|
|
||||||
writeln!(writer, " ;; -- minus")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " sub rbx, rax")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::Equals) => {
|
|
||||||
writeln!(writer, " ;; -- equals")?;
|
|
||||||
writeln!(writer, " mov rcx, 0")?;
|
|
||||||
writeln!(writer, " mov rdx, 1")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmove rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::Lt) => {
|
|
||||||
writeln!(writer, " ;; -- lt")?;
|
|
||||||
writeln!(writer, " mov rcx, 0")?;
|
|
||||||
writeln!(writer, " mov rdx, 1")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmovl rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::Gt) => {
|
|
||||||
writeln!(writer, " ;; -- gt")?;
|
|
||||||
writeln!(writer, " mov rcx, 0")?;
|
|
||||||
writeln!(writer, " mov rdx, 1")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmovg rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::NotEquals) => {
|
|
||||||
writeln!(writer, " ;; -- not equals")?;
|
|
||||||
writeln!(writer, " mov rcx, 1")?;
|
|
||||||
writeln!(writer, " mov rdx, 0")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmove rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::Le) => {
|
|
||||||
writeln!(writer, " ;; -- lt")?;
|
|
||||||
writeln!(writer, " mov rcx, 0")?;
|
|
||||||
writeln!(writer, " mov rdx, 1")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmovle rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::Ge) => {
|
|
||||||
writeln!(writer, " ;; -- gt")?;
|
|
||||||
writeln!(writer, " mov rcx, 0")?;
|
|
||||||
writeln!(writer, " mov rdx, 1")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " cmp rax, rbx")?;
|
|
||||||
writeln!(writer, " cmovge rcx, rdx")?;
|
|
||||||
writeln!(writer, " push rcx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::Band) => {
|
|
||||||
writeln!(writer, " ;; -- band")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " and rbx, rax")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::Bor) => {
|
|
||||||
writeln!(writer, " ;; -- bor")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " or rbx, rax")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::Shr) => {
|
|
||||||
writeln!(writer, " ;; -- shr")?;
|
|
||||||
writeln!(writer, " pop rcx")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " shr rbx, cl")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::Shl) => {
|
|
||||||
writeln!(writer, " ;; -- shl")?;
|
|
||||||
writeln!(writer, " pop rcx")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " shl rbx, cl")?;
|
|
||||||
writeln!(writer, " push rbx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::DivMod) => {
|
|
||||||
writeln!(writer, " ;; -- div")?;
|
|
||||||
writeln!(writer, " xor rdx, rdx")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " div rbx")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
writeln!(writer, " push rdx")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
OpType::Instruction(InstructionType::Mul) => {
|
|
||||||
writeln!(writer, " ;; -- mul")?;
|
|
||||||
writeln!(writer, " pop rax")?;
|
|
||||||
writeln!(writer, " pop rbx")?;
|
|
||||||
writeln!(writer, " mul rbx")?;
|
|
||||||
writeln!(writer, " push rax")?;
|
|
||||||
ti += 1;
|
|
||||||
},
|
|
||||||
|
|
||||||
|
// math
|
||||||
|
InstructionType::Plus => {
|
||||||
|
writeln!(writer, " ;; -- plus")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " add rax, rbx")?;
|
||||||
|
writeln!(writer, " push rax")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Minus => {
|
||||||
|
writeln!(writer, " ;; -- minus")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " sub rbx, rax")?;
|
||||||
|
writeln!(writer, " push rbx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Equals => {
|
||||||
|
writeln!(writer, " ;; -- equals")?;
|
||||||
|
writeln!(writer, " mov rcx, 0")?;
|
||||||
|
writeln!(writer, " mov rdx, 1")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " cmp rax, rbx")?;
|
||||||
|
writeln!(writer, " cmove rcx, rdx")?;
|
||||||
|
writeln!(writer, " push rcx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Lt => {
|
||||||
|
writeln!(writer, " ;; -- lt")?;
|
||||||
|
writeln!(writer, " mov rcx, 0")?;
|
||||||
|
writeln!(writer, " mov rdx, 1")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " cmp rax, rbx")?;
|
||||||
|
writeln!(writer, " cmovl rcx, rdx")?;
|
||||||
|
writeln!(writer, " push rcx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Gt => {
|
||||||
|
writeln!(writer, " ;; -- gt")?;
|
||||||
|
writeln!(writer, " mov rcx, 0")?;
|
||||||
|
writeln!(writer, " mov rdx, 1")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " cmp rax, rbx")?;
|
||||||
|
writeln!(writer, " cmovg rcx, rdx")?;
|
||||||
|
writeln!(writer, " push rcx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::NotEquals => {
|
||||||
|
writeln!(writer, " ;; -- not equals")?;
|
||||||
|
writeln!(writer, " mov rcx, 1")?;
|
||||||
|
writeln!(writer, " mov rdx, 0")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " cmp rax, rbx")?;
|
||||||
|
writeln!(writer, " cmove rcx, rdx")?;
|
||||||
|
writeln!(writer, " push rcx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Le => {
|
||||||
|
writeln!(writer, " ;; -- lt")?;
|
||||||
|
writeln!(writer, " mov rcx, 0")?;
|
||||||
|
writeln!(writer, " mov rdx, 1")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " cmp rax, rbx")?;
|
||||||
|
writeln!(writer, " cmovle rcx, rdx")?;
|
||||||
|
writeln!(writer, " push rcx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Ge => {
|
||||||
|
writeln!(writer, " ;; -- gt")?;
|
||||||
|
writeln!(writer, " mov rcx, 0")?;
|
||||||
|
writeln!(writer, " mov rdx, 1")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " cmp rax, rbx")?;
|
||||||
|
writeln!(writer, " cmovge rcx, rdx")?;
|
||||||
|
writeln!(writer, " push rcx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Band => {
|
||||||
|
writeln!(writer, " ;; -- band")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " and rbx, rax")?;
|
||||||
|
writeln!(writer, " push rbx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Bor => {
|
||||||
|
writeln!(writer, " ;; -- bor")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " or rbx, rax")?;
|
||||||
|
writeln!(writer, " push rbx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Shr => {
|
||||||
|
writeln!(writer, " ;; -- shr")?;
|
||||||
|
writeln!(writer, " pop rcx")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " shr rbx, cl")?;
|
||||||
|
writeln!(writer, " push rbx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Shl => {
|
||||||
|
writeln!(writer, " ;; -- shl")?;
|
||||||
|
writeln!(writer, " pop rcx")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " shl rbx, cl")?;
|
||||||
|
writeln!(writer, " push rbx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::DivMod => {
|
||||||
|
writeln!(writer, " ;; -- div")?;
|
||||||
|
writeln!(writer, " xor rdx, rdx")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " div rbx")?;
|
||||||
|
writeln!(writer, " push rax")?;
|
||||||
|
writeln!(writer, " push rdx")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Mul => {
|
||||||
|
writeln!(writer, " ;; -- mul")?;
|
||||||
|
writeln!(writer, " pop rax")?;
|
||||||
|
writeln!(writer, " pop rbx")?;
|
||||||
|
writeln!(writer, " mul rbx")?;
|
||||||
|
writeln!(writer, " push rax")?;
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::Syscall0 => {
|
||||||
|
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")?;
|
||||||
|
|
||||||
// block
|
ti += 1;
|
||||||
OpType::Keyword(KeywordType::If) => {
|
},
|
||||||
writeln!(writer, " ;; -- if")?;
|
InstructionType::Syscall4 => {
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " ;; -- syscall4")?;
|
||||||
writeln!(writer, " test rax, rax")?;
|
writeln!(writer, " pop rax")?;
|
||||||
writeln!(writer, " jz addr_{}", token.jmp)?;
|
writeln!(writer, " pop rdi")?;
|
||||||
ti += 1;
|
writeln!(writer, " pop rsi")?;
|
||||||
},
|
writeln!(writer, " pop rdx")?;
|
||||||
OpType::Keyword(KeywordType::Else) => {
|
writeln!(writer, " pop r10")?;
|
||||||
writeln!(writer, " ;; -- else")?;
|
writeln!(writer, " syscall")?;
|
||||||
writeln!(writer, " jmp addr_{}", token.jmp)?;
|
writeln!(writer, " push rax")?;
|
||||||
ti += 1;
|
ti += 1;
|
||||||
},
|
},
|
||||||
OpType::Keyword(KeywordType::While) => {
|
InstructionType::Syscall5 => {
|
||||||
writeln!(writer, " ;; -- while")?;
|
writeln!(writer, " ;; -- syscall5")?;
|
||||||
ti += 1;
|
writeln!(writer, " pop rax")?;
|
||||||
}
|
writeln!(writer, " pop rdi")?;
|
||||||
OpType::Keyword(KeywordType::Do) => {
|
writeln!(writer, " pop rsi")?;
|
||||||
writeln!(writer, " ;; -- do")?;
|
writeln!(writer, " pop rdx")?;
|
||||||
writeln!(writer, " pop rax")?;
|
writeln!(writer, " pop r10")?;
|
||||||
writeln!(writer, " test rax, rax")?;
|
writeln!(writer, " pop r8")?;
|
||||||
writeln!(writer, " jz addr_{}", token.jmp)?;
|
writeln!(writer, " syscall")?;
|
||||||
ti += 1;
|
writeln!(writer, " push rax")?;
|
||||||
}
|
ti += 1;
|
||||||
OpType::Keyword(KeywordType::End) => {
|
},
|
||||||
writeln!(writer, " ;; -- end")?;
|
InstructionType::Syscall6 => {
|
||||||
if ti + 1 != token.jmp {
|
writeln!(writer, " ;; -- syscall6")?;
|
||||||
writeln!(writer, " jmp addr_{}", token.jmp)?;
|
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")?;
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,3 +183,17 @@ 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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) => {
|
||||||
|
match instruction {
|
||||||
|
InstructionType::PushInt => {
|
||||||
|
stack.push(token.value);
|
||||||
|
ti += 1;
|
||||||
|
},
|
||||||
|
InstructionType::PushStr => {
|
||||||
|
if token.addr.is_none() {
|
||||||
|
stack.push(token.text.len()); // string len
|
||||||
|
stack.push(string_idx + crate::compile::MEM_SZ);
|
||||||
|
|
||||||
// stack
|
for c in token.text.bytes() {
|
||||||
OpType::Instruction(InstructionType::PushInt) => {
|
mem[crate::compile::MEM_SZ + string_idx] = c;
|
||||||
stack.push(token.value);
|
string_idx += 1;
|
||||||
ti += 1;
|
}
|
||||||
},
|
} else {
|
||||||
OpType::Instruction(InstructionType::PushStr) => {
|
stack.push(token.text.len());
|
||||||
if token.addr.is_none() {
|
if let Some(addr) = token.addr {
|
||||||
stack.push(token.text.len()); // string len
|
stack.push(addr);
|
||||||
stack.push(string_idx + crate::compile::MEM_SZ);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for c in token.text.bytes() {
|
|
||||||
mem[crate::compile::MEM_SZ + string_idx] = c;
|
ti += 1;
|
||||||
string_idx += 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;
|
||||||
}
|
}
|
||||||
} else {
|
InstructionType::Swap => {
|
||||||
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(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
InstructionType::Mul => {
|
||||||
|
let a = stack_pop(&mut stack, &pos)?;
|
||||||
|
let b = stack_pop(&mut stack, &pos)?;
|
||||||
|
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!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
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 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
245
src/typechecker.rs
Normal 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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user