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,15 +75,18 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
let token = &tokens[ti];
|
||||
|
||||
writeln!(writer, "addr_{ti}:")?;
|
||||
match token.typ {
|
||||
match token.typ.clone() {
|
||||
// stack
|
||||
OpType::Instruction(InstructionType::PushInt) => {
|
||||
|
||||
OpType::Instruction(instruction) => {
|
||||
match 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) => {
|
||||
InstructionType::PushStr => {
|
||||
writeln!(writer, " ;; -- push str \"{}\"", token.text.escape_default())?;
|
||||
writeln!(writer, " mov rax, {}", token.text.len())?;
|
||||
writeln!(writer, " push rax")?;
|
||||
|
@ -91,19 +94,19 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
strings.push(token.text.clone());
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Instruction(InstructionType::Drop) => {
|
||||
InstructionType::Drop => {
|
||||
writeln!(writer, " ;; -- drop")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Print) => {
|
||||
InstructionType::Print => {
|
||||
writeln!(writer, " ;; -- print")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
writeln!(writer, " call print")?;
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
OpType::Instruction(InstructionType::Dup) => {
|
||||
InstructionType::Dup => {
|
||||
writeln!(writer, " ;; -- dup")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
|
@ -112,7 +115,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
ti += 1;
|
||||
},
|
||||
|
||||
OpType::Instruction(InstructionType::Rot) => {
|
||||
InstructionType::Rot => {
|
||||
writeln!(writer, " ;; -- rot")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -123,7 +126,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Swap) => {
|
||||
InstructionType::Swap => {
|
||||
writeln!(writer, " ;; -- swap")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -132,7 +135,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Over) => {
|
||||
InstructionType::Over => {
|
||||
writeln!(writer, " ;; -- over")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -144,12 +147,12 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
},
|
||||
|
||||
//mem
|
||||
OpType::Instruction(InstructionType::Mem) => {
|
||||
InstructionType::Mem => {
|
||||
writeln!(writer, " ;; -- mem")?;
|
||||
writeln!(writer, " push mem")?;
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Instruction(InstructionType::Load8) => {
|
||||
InstructionType::Load8 => {
|
||||
writeln!(writer, " ;; -- load")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " xor rbx, rbx")?;
|
||||
|
@ -158,7 +161,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
ti += 1;
|
||||
}
|
||||
|
||||
OpType::Instruction(InstructionType::Store8) => {
|
||||
InstructionType::Store8 => {
|
||||
writeln!(writer, " ;; -- store")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
|
@ -167,7 +170,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
}
|
||||
|
||||
// math
|
||||
OpType::Instruction(InstructionType::Plus) => {
|
||||
InstructionType::Plus => {
|
||||
writeln!(writer, " ;; -- plus")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -175,7 +178,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Minus) => {
|
||||
InstructionType::Minus => {
|
||||
writeln!(writer, " ;; -- minus")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -183,7 +186,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Equals) => {
|
||||
InstructionType::Equals => {
|
||||
writeln!(writer, " ;; -- equals")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
|
@ -194,7 +197,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Lt) => {
|
||||
InstructionType::Lt => {
|
||||
writeln!(writer, " ;; -- lt")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
|
@ -205,7 +208,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Gt) => {
|
||||
InstructionType::Gt => {
|
||||
writeln!(writer, " ;; -- gt")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
|
@ -216,7 +219,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::NotEquals) => {
|
||||
InstructionType::NotEquals => {
|
||||
writeln!(writer, " ;; -- not equals")?;
|
||||
writeln!(writer, " mov rcx, 1")?;
|
||||
writeln!(writer, " mov rdx, 0")?;
|
||||
|
@ -227,7 +230,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Le) => {
|
||||
InstructionType::Le => {
|
||||
writeln!(writer, " ;; -- lt")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
|
@ -238,7 +241,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Ge) => {
|
||||
InstructionType::Ge => {
|
||||
writeln!(writer, " ;; -- gt")?;
|
||||
writeln!(writer, " mov rcx, 0")?;
|
||||
writeln!(writer, " mov rdx, 1")?;
|
||||
|
@ -249,7 +252,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rcx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Band) => {
|
||||
InstructionType::Band => {
|
||||
writeln!(writer, " ;; -- band")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -257,7 +260,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Bor) => {
|
||||
InstructionType::Bor => {
|
||||
writeln!(writer, " ;; -- bor")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -265,7 +268,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Shr) => {
|
||||
InstructionType::Shr => {
|
||||
writeln!(writer, " ;; -- shr")?;
|
||||
writeln!(writer, " pop rcx")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -273,7 +276,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Shl) => {
|
||||
InstructionType::Shl => {
|
||||
writeln!(writer, " ;; -- shl")?;
|
||||
writeln!(writer, " pop rcx")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -281,7 +284,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rbx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::DivMod) => {
|
||||
InstructionType::DivMod => {
|
||||
writeln!(writer, " ;; -- div")?;
|
||||
writeln!(writer, " xor rdx, rdx")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -291,7 +294,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rdx")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Mul) => {
|
||||
InstructionType::Mul => {
|
||||
writeln!(writer, " ;; -- mul")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rbx")?;
|
||||
|
@ -299,47 +302,14 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
|
||||
// block
|
||||
OpType::Keyword(KeywordType::If) => {
|
||||
writeln!(writer, " ;; -- if")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " test rax, rax")?;
|
||||
writeln!(writer, " jz addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Keyword(KeywordType::Else) => {
|
||||
writeln!(writer, " ;; -- else")?;
|
||||
writeln!(writer, " jmp addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Keyword(KeywordType::While) => {
|
||||
writeln!(writer, " ;; -- while")?;
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Keyword(KeywordType::Do) => {
|
||||
writeln!(writer, " ;; -- do")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " test rax, rax")?;
|
||||
writeln!(writer, " jz addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Keyword(KeywordType::End) => {
|
||||
writeln!(writer, " ;; -- end")?;
|
||||
if ti + 1 != token.jmp {
|
||||
writeln!(writer, " jmp addr_{}", token.jmp)?;
|
||||
}
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall0) => {
|
||||
InstructionType::Syscall0 => {
|
||||
writeln!(writer, " ;; -- syscall0")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall1) => {
|
||||
InstructionType::Syscall1 => {
|
||||
writeln!(writer, " ;; -- syscall1")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
|
@ -347,7 +317,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall2) => {
|
||||
InstructionType::Syscall2 => {
|
||||
writeln!(writer, " ;; -- syscall2")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
|
@ -356,7 +326,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall3) => {
|
||||
InstructionType::Syscall3 => {
|
||||
writeln!(writer, " ;; -- syscall3")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
|
@ -367,7 +337,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall4) => {
|
||||
InstructionType::Syscall4 => {
|
||||
writeln!(writer, " ;; -- syscall4")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
|
@ -378,7 +348,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall5) => {
|
||||
InstructionType::Syscall5 => {
|
||||
writeln!(writer, " ;; -- syscall5")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
|
@ -390,7 +360,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Syscall6) => {
|
||||
InstructionType::Syscall6 => {
|
||||
writeln!(writer, " ;; -- syscall6")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " pop rdi")?;
|
||||
|
@ -403,7 +373,53 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " push rax")?;
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::None) | OpType::Keyword(KeywordType::Macro) | OpType::Keyword(KeywordType::Include) => unreachable!()
|
||||
InstructionType::None => unreachable!(),
|
||||
InstructionType::CastBool => ti += 1,
|
||||
InstructionType::CastPtr => ti += 1,
|
||||
InstructionType::CastInt => ti += 1,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OpType::Keyword(keyword) => {
|
||||
match keyword {
|
||||
|
||||
// block
|
||||
KeywordType::If => {
|
||||
writeln!(writer, " ;; -- if")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " test rax, rax")?;
|
||||
writeln!(writer, " jz addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
},
|
||||
KeywordType::Else => {
|
||||
writeln!(writer, " ;; -- else")?;
|
||||
writeln!(writer, " jmp addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
},
|
||||
KeywordType::While => {
|
||||
writeln!(writer, " ;; -- while")?;
|
||||
ti += 1;
|
||||
}
|
||||
KeywordType::Do => {
|
||||
writeln!(writer, " ;; -- do")?;
|
||||
writeln!(writer, " pop rax")?;
|
||||
writeln!(writer, " test rax, rax")?;
|
||||
writeln!(writer, " jz addr_{}", token.jmp)?;
|
||||
ti += 1;
|
||||
}
|
||||
KeywordType::End => {
|
||||
writeln!(writer, " ;; -- end")?;
|
||||
if ti + 1 != token.jmp {
|
||||
writeln!(writer, " jmp addr_{}", token.jmp)?;
|
||||
}
|
||||
ti += 1;
|
||||
},
|
||||
KeywordType::Macro |
|
||||
KeywordType::Include
|
||||
=> unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
writeln!(writer, "addr_{ti}:")?;
|
||||
|
@ -411,10 +427,10 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
|
|||
writeln!(writer, " mov rdi, 0")?;
|
||||
writeln!(writer, " syscall")?;
|
||||
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_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")?;
|
||||
|
|
|
@ -46,6 +46,10 @@ pub enum InstructionType {
|
|||
Syscall5,
|
||||
Syscall6,
|
||||
|
||||
CastBool,
|
||||
CastPtr,
|
||||
CastInt,
|
||||
|
||||
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::Syscall5) => "syscall5",
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
@ -176,3 +183,17 @@ impl TokenType {
|
|||
}
|
||||
|
||||
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,14 +24,14 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
|||
let token = &tokens[ti];
|
||||
let pos = token.loc.clone();
|
||||
// println!("{:?}", token.typ);
|
||||
match token.typ {
|
||||
|
||||
// stack
|
||||
OpType::Instruction(InstructionType::PushInt) => {
|
||||
match token.typ.clone() {
|
||||
OpType::Instruction(instruction) => {
|
||||
match instruction {
|
||||
InstructionType::PushInt => {
|
||||
stack.push(token.value);
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::PushStr) => {
|
||||
InstructionType::PushStr => {
|
||||
if token.addr.is_none() {
|
||||
stack.push(token.text.len()); // string len
|
||||
stack.push(string_idx + crate::compile::MEM_SZ);
|
||||
|
@ -50,18 +50,18 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
|||
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Drop) => {
|
||||
InstructionType::Drop => {
|
||||
stack.pop();
|
||||
ti += 1;
|
||||
},
|
||||
OpType::Instruction(InstructionType::Dup) => {
|
||||
InstructionType::Dup => {
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
stack.push(a);
|
||||
stack.push(a);
|
||||
ti += 1;
|
||||
},
|
||||
|
||||
OpType::Instruction(InstructionType::Rot) => {
|
||||
InstructionType::Rot => {
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
let c = stack_pop(&mut stack, &pos)?;
|
||||
|
@ -70,14 +70,14 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
|||
stack.push(c);
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Instruction(InstructionType::Swap) => {
|
||||
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) => {
|
||||
InstructionType::Over => {
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
let b = stack_pop(&mut stack, &pos)?;
|
||||
stack.push(b);
|
||||
|
@ -86,7 +86,7 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
|||
ti += 1;
|
||||
}
|
||||
|
||||
OpType::Instruction(InstructionType::Print) => {
|
||||
InstructionType::Print => {
|
||||
let a = stack_pop(&mut stack, &pos)?;
|
||||
println!("{a}");
|
||||
// let _ = io::stdout().flush();
|
||||
|
@ -94,18 +94,18 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
|||
},
|
||||
// mem
|
||||
|
||||
OpType::Instruction(InstructionType::Mem) => {
|
||||
InstructionType::Mem => {
|
||||
stack.push(0);
|
||||
ti += 1;
|
||||
}
|
||||
OpType::Instruction(InstructionType::Load8) => {
|
||||
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) => {
|
||||
InstructionType::Store8 => {
|
||||
let val = stack_pop(&mut stack, &pos)?;
|
||||
let addr = stack_pop(&mut stack, &pos)?;
|
||||
|
||||
|
@ -114,97 +114,145 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
|||
}
|
||||
|
||||
// math
|
||||
OpType::Instruction(InstructionType::Plus) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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) => {
|
||||
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!()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// blocks
|
||||
OpType::Keyword(KeywordType::If) => {
|
||||
|
@ -230,49 +278,7 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
|
|||
ti += 1;
|
||||
}
|
||||
}
|
||||
OpType::Instruction(InstructionType::Syscall0) => {
|
||||
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!()
|
||||
| OpType::Keyword(KeywordType::Macro) | OpType::Keyword(KeywordType::Include) => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ mod compile;
|
|||
mod parser;
|
||||
mod lexer;
|
||||
mod preprocessor;
|
||||
mod typechecker;
|
||||
|
||||
use std::fs;
|
||||
|
||||
|
@ -54,6 +55,8 @@ pub struct Args {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
|
||||
let args = Args::parse();
|
||||
|
||||
let Ok(code) = fs::read_to_string(&args.in_file) else {
|
||||
|
@ -73,6 +76,11 @@ fn main() {
|
|||
return;
|
||||
};
|
||||
|
||||
let Ok(tokens) = typechecker::typecheck(&tokens, &args) else {
|
||||
error!("Typechecking failed, exiting!");
|
||||
return;
|
||||
};
|
||||
|
||||
let c = if args.compile && args.interpret {
|
||||
error!("Cannot compile and interpret at the same time");
|
||||
0
|
||||
|
|
|
@ -156,6 +156,9 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
|
|||
"syscall4" => OpType::Instruction(InstructionType::Syscall4),
|
||||
"syscall5" => OpType::Instruction(InstructionType::Syscall5),
|
||||
"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)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{PathBuf, Path};
|
||||
|
||||
use color_eyre::Result;
|
||||
use eyre::eyre;
|
||||
|
@ -93,18 +93,25 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
|
|||
|
||||
let mut include_code = String::new();
|
||||
|
||||
if include_path.text.chars().collect::<Vec<char>>()[0] == '.' {
|
||||
let p = Path::new(include_path.file.as_str());
|
||||
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.clone());
|
||||
let p = p.join(&include_path.text);
|
||||
|
||||
if p.exists() {
|
||||
include_code = std::fs::read_to_string(p)?;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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!(""));
|
||||
}
|
||||
|
||||
|
|
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