diff --git a/README.md b/README.md new file mode 100644 index 0000000..f081e7a --- /dev/null +++ b/README.md @@ -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 diff --git a/docs/linux_syscalls_x86_64.md b/docs/dev/linux_syscalls_x86_64.md similarity index 100% rename from docs/linux_syscalls_x86_64.md rename to docs/dev/linux_syscalls_x86_64.md diff --git a/docs/x86_64-intel-manual.pdf b/docs/dev/x86_64-intel-manual.pdf similarity index 100% rename from docs/x86_64-intel-manual.pdf rename to docs/dev/x86_64-intel-manual.pdf diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..4a2b981 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,2 @@ +# Docs + diff --git a/docs/instructions_and_keywords.md b/docs/instructions_and_keywords.md new file mode 100644 index 0000000..68fd989 --- /dev/null +++ b/docs/instructions_and_keywords.md @@ -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") \ No newline at end of file diff --git a/src/compile/linux_x86_64.rs b/src/compile/linux_x86_64.rs index 5b1a7b9..c4dea5d 100644 --- a/src/compile/linux_x86_64.rs +++ b/src/compile/linux_x86_64.rs @@ -75,335 +75,351 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ let token = &tokens[ti]; writeln!(writer, "addr_{ti}:")?; - match token.typ { + match token.typ.clone() { // 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) => { - writeln!(writer, " ;; -- dup")?; - writeln!(writer, " pop rax")?; - writeln!(writer, " push rax")?; - writeln!(writer, " push rax")?; - - ti += 1; - }, - - OpType::Instruction(InstructionType::Rot) => { - 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; - }, - OpType::Instruction(InstructionType::Swap) => { - writeln!(writer, " ;; -- swap")?; - writeln!(writer, " pop rax")?; - writeln!(writer, " pop rbx")?; - writeln!(writer, " push rax")?; - writeln!(writer, " push rbx")?; - - ti += 1; - }, - OpType::Instruction(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")?; - - ti += 1; - }, - - //mem - 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) => { - writeln!(writer, " ;; -- store")?; - writeln!(writer, " pop rbx")?; - writeln!(writer, " pop rax")?; - writeln!(writer, " mov [rax], bl")?; - ti += 1; - } - - // math - OpType::Instruction(InstructionType::Plus) => { - writeln!(writer, " ;; -- plus")?; - writeln!(writer, " pop rax")?; - writeln!(writer, " pop rbx")?; - writeln!(writer, " add rax, rbx")?; - 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; - }, - - - // 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)?; + 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; + }, + 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; + }, + + InstructionType::Dup => { + writeln!(writer, " ;; -- dup")?; + writeln!(writer, " pop rax")?; + writeln!(writer, " push rax")?; + writeln!(writer, " push rax")?; + + ti += 1; + }, + + InstructionType::Rot => { + 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::Swap => { + writeln!(writer, " ;; -- swap")?; + writeln!(writer, " pop rax")?; + writeln!(writer, " pop rbx")?; + writeln!(writer, " push rax")?; + writeln!(writer, " push rbx")?; + + 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")?; + + ti += 1; + }, + + //mem + InstructionType::Mem => { + writeln!(writer, " ;; -- mem")?; + writeln!(writer, " push mem")?; + 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; + } + + InstructionType::Store8 => { + writeln!(writer, " ;; -- store")?; + writeln!(writer, " pop rbx")?; + writeln!(writer, " pop rax")?; + writeln!(writer, " mov [rax], bl")?; + 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")?; + + ti += 1; + }, + InstructionType::Syscall4 => { + writeln!(writer, " ;; -- syscall4")?; + writeln!(writer, " pop rax")?; + writeln!(writer, " pop rdi")?; + writeln!(writer, " pop rsi")?; + writeln!(writer, " pop rdx")?; + writeln!(writer, " pop r10")?; + writeln!(writer, " syscall")?; + writeln!(writer, " push rax")?; + ti += 1; + }, + InstructionType::Syscall5 => { + writeln!(writer, " ;; -- syscall5")?; + writeln!(writer, " pop rax")?; + writeln!(writer, " pop rdi")?; + writeln!(writer, " pop rsi")?; + writeln!(writer, " pop rdx")?; + writeln!(writer, " pop r10")?; + writeln!(writer, " pop r8")?; + writeln!(writer, " syscall")?; + writeln!(writer, " push rax")?; + ti += 1; + }, + InstructionType::Syscall6 => { + writeln!(writer, " ;; -- syscall6")?; + writeln!(writer, " pop rax")?; + writeln!(writer, " pop rdi")?; + writeln!(writer, " pop rsi")?; + writeln!(writer, " pop rdx")?; + writeln!(writer, " pop r10")?; + writeln!(writer, " pop r8")?; + writeln!(writer, " pop r9")?; + writeln!(writer, " syscall")?; + writeln!(writer, " push rax")?; + ti += 1; + }, + InstructionType::None => unreachable!(), + InstructionType::CastBool => ti += 1, + InstructionType::CastPtr => ti += 1, + InstructionType::CastInt => ti += 1, } - ti += 1; - }, - OpType::Instruction(InstructionType::Syscall0) => { - writeln!(writer, " ;; -- syscall0")?; - writeln!(writer, " pop rax")?; - writeln!(writer, " syscall")?; - writeln!(writer, " push rax")?; - ti += 1; - }, - OpType::Instruction(InstructionType::Syscall1) => { - writeln!(writer, " ;; -- syscall1")?; - writeln!(writer, " pop rax")?; - writeln!(writer, " pop rdi")?; - writeln!(writer, " syscall")?; - writeln!(writer, " push rax")?; - ti += 1; - }, - OpType::Instruction(InstructionType::Syscall2) => { - writeln!(writer, " ;; -- syscall2")?; - writeln!(writer, " pop rax")?; - writeln!(writer, " pop rdi")?; - writeln!(writer, " pop rsi")?; - writeln!(writer, " syscall")?; - writeln!(writer, " push rax")?; - ti += 1; - }, - OpType::Instruction(InstructionType::Syscall3) => { - writeln!(writer, " ;; -- syscall3")?; - writeln!(writer, " pop rax")?; - writeln!(writer, " pop rdi")?; - writeln!(writer, " pop rsi")?; - writeln!(writer, " pop rdx")?; - writeln!(writer, " syscall")?; - writeln!(writer, " push rax")?; + } - ti += 1; - }, - OpType::Instruction(InstructionType::Syscall4) => { - writeln!(writer, " ;; -- syscall4")?; - writeln!(writer, " pop rax")?; - writeln!(writer, " pop rdi")?; - writeln!(writer, " pop rsi")?; - writeln!(writer, " pop rdx")?; - writeln!(writer, " pop r10")?; - writeln!(writer, " syscall")?; - writeln!(writer, " push rax")?; - ti += 1; - }, - OpType::Instruction(InstructionType::Syscall5) => { - writeln!(writer, " ;; -- syscall5")?; - writeln!(writer, " pop rax")?; - writeln!(writer, " pop rdi")?; - writeln!(writer, " pop rsi")?; - writeln!(writer, " pop rdx")?; - writeln!(writer, " pop r10")?; - writeln!(writer, " pop r8")?; - writeln!(writer, " syscall")?; - writeln!(writer, " push rax")?; - ti += 1; - }, - OpType::Instruction(InstructionType::Syscall6) => { - writeln!(writer, " ;; -- syscall6")?; - writeln!(writer, " pop rax")?; - writeln!(writer, " pop rdi")?; - writeln!(writer, " pop rsi")?; - writeln!(writer, " pop rdx")?; - writeln!(writer, " pop r10")?; - writeln!(writer, " pop r8")?; - writeln!(writer, " pop r9")?; - writeln!(writer, " syscall")?; - writeln!(writer, " push rax")?; - ti += 1; - }, - OpType::Instruction(InstructionType::None) | OpType::Keyword(KeywordType::Macro) | OpType::Keyword(KeywordType::Include) => unreachable!() + + 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{ 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::>(); 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")?; diff --git a/src/constants.rs b/src/constants.rs index aa203bf..9cd7c91 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -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() } } @@ -175,4 +182,18 @@ impl TokenType { } } -pub type Loc = (String, usize, usize); \ No newline at end of file +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 +} + diff --git a/src/interpret/linux_x86_64/mod.rs b/src/interpret/linux_x86_64/mod.rs index a53f34d..597d410 100644 --- a/src/interpret/linux_x86_64/mod.rs +++ b/src/interpret/linux_x86_64/mod.rs @@ -24,187 +24,235 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result{ let token = &tokens[ti]; let pos = token.loc.clone(); // println!("{:?}", token.typ); - match token.typ { - - // stack - OpType::Instruction(InstructionType::PushInt) => { - stack.push(token.value); - ti += 1; - }, - OpType::Instruction(InstructionType::PushStr) => { - if token.addr.is_none() { - stack.push(token.text.len()); // string len - stack.push(string_idx + crate::compile::MEM_SZ); + 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); + + for c in token.text.bytes() { + mem[crate::compile::MEM_SZ + string_idx] = c; + string_idx += 1; + } + } else { + stack.push(token.text.len()); + if let Some(addr) = token.addr { + stack.push(addr); + } + } + + + ti += 1; + }, + InstructionType::Drop => { + stack.pop(); + ti += 1; + }, + InstructionType::Dup => { + let a = stack_pop(&mut stack, &pos)?; + stack.push(a); + stack.push(a); + ti += 1; + }, + + InstructionType::Rot => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + let c = stack_pop(&mut stack, &pos)?; + stack.push(b); + stack.push(a); + stack.push(c); + ti += 1; + } + InstructionType::Swap => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(a); + stack.push(b); + ti += 1; + } + InstructionType::Over => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(b); + stack.push(a); + stack.push(b); + ti += 1; + } + + InstructionType::Print => { + let a = stack_pop(&mut stack, &pos)?; + println!("{a}"); + // let _ = io::stdout().flush(); + ti += 1; + }, + // mem + + InstructionType::Mem => { + stack.push(0); + ti += 1; + } + InstructionType::Load8 => { + let a = stack_pop(&mut stack, &pos)?; + let byte = mem[a]; + stack.push(byte as usize); + ti += 1; + } + #[allow(clippy::cast_possible_truncation)] + InstructionType::Store8 => { + let val = stack_pop(&mut stack, &pos)?; + let addr = stack_pop(&mut stack, &pos)?; + + mem[addr] = (val & 0xFF) as u8; + ti += 1; + } + + // math + InstructionType::Plus => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(b + a); + ti += 1; + }, + InstructionType::Minus => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(b - a); + ti += 1; + }, + InstructionType::Equals => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(usize::from(b == a)); + ti += 1; + }, + InstructionType::Gt => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(usize::from(b > a)); + ti += 1; + }, + InstructionType::Lt => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(usize::from(b < a)); + ti += 1; + }, + InstructionType::NotEquals => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(usize::from(b != a)); + ti += 1; + }, + InstructionType::Ge => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(usize::from(b >= a)); + ti += 1; + }, + InstructionType::Le => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(usize::from(b <= a)); + ti += 1; + }, + + InstructionType::Band => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(a & b); + ti += 1; + } + + InstructionType::Bor => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(a | b); + ti += 1; + } + + InstructionType::Shr => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(b >> a); + ti += 1; + } + + InstructionType::Shl => { + let a = stack_pop(&mut stack, &pos)?; + let b = stack_pop(&mut stack, &pos)?; + stack.push(b << a); + ti += 1; + } - for c in token.text.bytes() { - mem[crate::compile::MEM_SZ + string_idx] = c; - string_idx += 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; } - } else { - stack.push(token.text.len()); - if let Some(addr) = token.addr { - stack.push(addr); + 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 OpType::Keyword(KeywordType::If) => { @@ -230,49 +278,7 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result{ 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!() } } diff --git a/src/main.rs b/src/main.rs index b5b0bfa..bbcb2d5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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 diff --git a/src/parser.rs b/src/parser.rs index 9c8f444..e14b0b1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -156,6 +156,9 @@ pub fn lookup_word>(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) } diff --git a/src/preprocessor.rs b/src/preprocessor.rs index d539ee0..848f06e 100644 --- a/src/preprocessor.rs +++ b/src/preprocessor.rs @@ -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, args: &Args) -> Result>{ let mut include_code = String::new(); - for path in in_paths { - let p = PathBuf::from(path); - let p = p.join(include_path.text.clone()); - - if p.exists() { - include_code = std::fs::read_to_string(p)?; + if include_path.text.chars().collect::>()[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); + + 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!("")); } diff --git a/src/typechecker.rs b/src/typechecker.rs new file mode 100644 index 0000000..47597f9 --- /dev/null +++ b/src/typechecker.rs @@ -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>{ + + let mut stack: Vec = 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, op: &Operator, t: &[Types]) -> Result { + 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) +} diff --git a/test.mcl b/test.mcl index 1613b36..b8645c6 100644 --- a/test.mcl +++ b/test.mcl @@ -1 +1,3 @@ -' ' print \ No newline at end of file +include "./asd.mcl" + +1 test \ No newline at end of file