Rotth is a stack based concatenative language highly inspired by Porth
0

Configure Feed

Select the types of activity you want to include in your feed.

Implement rest of intrinsics

Ivan Chinenov (Mar 8, 2022, 10:23 PM +0300) 09ff5a40 43f09fe0

+142 -81
+6 -2
justfile
··· 1 - rotthdir := (justfile_directory() + "/rotth-src") 1 + root := justfile_directory() 2 + rotthdir := (root + "/rotth-src") 2 3 3 4 default: 4 5 @just --list 5 6 6 7 build FILE: 7 8 cargo run -- --compile -- {{rotthdir}}/{{FILE}}.rh 9 + nasm -g -F dwarf -f elf64 {{root}}/print.asm -o {{root}}/print.o 8 10 nasm -g -F dwarf -f elf64 {{rotthdir}}/{{FILE}}.asm -o {{rotthdir}}/{{FILE}}.o 9 - ld -o {{rotthdir}}/{{FILE}} {{rotthdir}}/{{FILE}}.o 11 + ld -o {{rotthdir}}/{{FILE}} {{rotthdir}}/{{FILE}}.o {{root}}/print.o 10 12 11 13 run FILE: (build FILE) 12 14 {{rotthdir}}/{{FILE}} 15 + 16 + clean-run FILE: clean (run FILE) 13 17 14 18 clean: 15 19 find {{rotthdir}} -type f ! -name "*.rh" -delete
+7 -2
rotth-src/cond_loop.rh
··· 1 1 proc main : uint do 2 - 1 while dup 0 > do 2 + ;0 while dup 10 < do 3 + ; dup print 4 + ; 1 + 5 + ;end drop 6 + 10 while dup 0 > do 3 7 dup print 4 8 1 - 5 - end 9 + end drop 10 + 0 6 11 end
+2 -2
rotth-src/count.rh
··· 5 5 proc count uint : uint do 6 6 dup 0 = if 7 7 else 8 - &? 9 - 2 - count 8 + dup print 9 + 1 - count 10 10 end 11 11 end
+8
rotth-src/divmod.rh
··· 1 + proc main : uint do 2 + 5 2 div print 3 + 0 4 + end 5 + 6 + proc div uint uint : uint do 7 + divmod drop 8 + end
+2 -2
rotth-src/fib.rh
··· 1 1 proc main : uint do 2 - 1 fib print 2 + 25 fib print 3 3 0 4 4 end 5 5 6 6 proc fib uint : uint do 7 7 dup 3 <= if 8 - pop 1 8 + drop 1 9 9 else 10 10 dup 1 - swap 2 - swap fib swap fib + 11 11 end
+7
rotth-src/simpleprint.rh
··· 1 + proc main : uint do 2 + 1000 print 3 + 100 print 4 + 10 print 5 + 1 print 6 + 0 7 + end
+93 -56
src/emit.rs
··· 17 17 BITS 64 18 18 section .text 19 19 global _start 20 - 21 - __print__: 22 - mov r9, -368934881474191032 23 - sub rsp, 40 24 - mov BYTE [rsp+31], 10 25 - lea rcx, [rsp+30] 26 - .L2: 27 - mov rax, rdi 28 - lea r8, [rsp+32] 29 - mul r9 30 - mov rax, rdi 31 - sub r8, rcx 32 - shr rdx, 3 33 - lea rsi, [rdx+rdx*4] 34 - add rsi, rsi 35 - sub rax, rsi 36 - add eax, 48 37 - mov BYTE [rcx], al 38 - mov rax, rdi 39 - mov rdi, rdx 40 - mov rdx, rcx 41 - sub rcx, 1 42 - cmp rax, 9 43 - ja .L2 44 - lea rax, [rsp+32] 45 - mov edi, 1 46 - sub rdx, rax 47 - xor eax, eax 48 - lea rsi, [rsp+32+rdx] 49 - mov rdx, r8 50 - mov rax, 1 51 - syscall 52 - add rsp, 40 53 - ret 20 + extern print 54 21 55 22 _start: 23 + mov QWORD [ret_stack_rsp], ret_stack 56 24 "}, 57 25 )?; 58 26 for op in ops { ··· 63 31 ; {:?} 64 32 mov rax, {:?} 65 33 push rax 66 - 67 34 "}, 68 35 op, 69 36 c.bytes() ··· 75 42 pop rax 76 43 push rax 77 44 push rax 78 - 79 45 "}, 80 46 op 81 47 )?, ··· 87 53 pop rbx 88 54 push rax 89 55 push rbx 90 - 91 56 "}, 92 57 op 93 58 )?, ··· 100 65 push rbx 101 66 push rax 102 67 push rbx 103 - 104 68 "}, 105 69 op 106 70 )?, 107 - Pop => write!( 71 + Drop => write!( 108 72 sink, 109 73 indoc! {" 110 74 ; {:?} 111 75 pop rax 112 - 113 76 "}, 114 77 op 115 78 )?, ··· 119 82 indoc! {" 120 83 ; {:?} 121 84 pop rdi 122 - call __print__ 123 - 85 + call print 124 86 "}, 125 87 op 126 88 )?, ··· 133 95 pop rbx 134 96 sub rbx, rax 135 97 push rbx 136 - 137 98 "}, 138 99 op 139 100 )?, ··· 145 106 pop rbx 146 107 add rbx, rax 147 108 push rbx 109 + "}, 110 + op 111 + )?, 112 + Divmod => write!( 113 + sink, 114 + indoc! {" 115 + ; {:?} 116 + xor rdx, rdx 117 + pop rbx 118 + pop rax 119 + div rbx 120 + push rax 121 + push rdx 122 + "}, 123 + op 124 + )?, 125 + Mul => write!( 126 + sink, 127 + indoc! {" 128 + ; {:?} 129 + pop rax 130 + pop rbx 131 + mul rbx 132 + push rax 133 + "}, 134 + op 135 + )?, 148 136 137 + Ne => write!( 138 + sink, 139 + indoc! {" 140 + ; {:?} 141 + mov rcx, 0 142 + mov rdx, 1 143 + pop rbx 144 + pop rax 145 + cmp rax, rbx 146 + cmovne rcx, rdx 147 + push rcx 149 148 "}, 150 149 op 151 150 )?, 152 - 151 + Lt => write!( 152 + sink, 153 + indoc! {" 154 + ; {:?} 155 + mov rcx, 0 156 + mov rdx, 1 157 + pop rbx 158 + pop rax 159 + cmp rax, rbx 160 + cmovl rcx, rdx 161 + push rcx 162 + "}, 163 + op 164 + )?, 165 + Ge => write!( 166 + sink, 167 + indoc! {" 168 + ; {:?} 169 + mov rcx, 0 170 + mov rdx, 1 171 + pop rbx 172 + pop rax 173 + cmp rax, rbx 174 + cmovge rcx, rdx 175 + push rcx 176 + "}, 177 + op 178 + )?, 153 179 Le => write!( 154 180 sink, 155 181 indoc! {" ··· 161 187 cmp rax, rbx 162 188 cmovle rcx, rdx 163 189 push rcx 164 - 165 190 "}, 166 191 op 167 192 )?, ··· 176 201 cmp rax, rbx 177 202 cmovg rcx, rdx 178 203 push rcx 179 - 204 + "}, 205 + op 206 + )?, 207 + Eq => write!( 208 + sink, 209 + indoc! {" 210 + ; {:?} 211 + mov rcx, 0 212 + mov rdx, 1 213 + pop rbx 214 + pop rax 215 + cmp rax, rbx 216 + cmove rcx, rdx 217 + push rcx 180 218 "}, 181 219 op 182 220 )?, ··· 186 224 indoc! {" 187 225 ; {:?} 188 226 ret 189 - 190 227 "}, 191 228 op 192 229 )?, ··· 205 242 pop rdi 206 243 mov rax, 60 207 244 syscall 208 - 209 245 "}, 210 246 op 211 247 )?, ··· 215 251 {}: 216 252 ; save return address 217 253 pop rdi 218 - inc QWORD [ret_stack_rsp] 219 - mov QWORD [ret_stack_rsp], rdi 220 - 254 + mov rax, 8 255 + add [ret_stack_rsp], rax 256 + mov QWORD rax, [ret_stack_rsp] 257 + mov QWORD [rax], rdi 221 258 "}, 222 259 l 223 260 )?, ··· 225 262 sink, 226 263 indoc! {" 227 264 ; load return adderss 228 - mov QWORD rdi, [ret_stack_rsp] 229 - dec QWORD [ret_stack_rsp] 265 + mov QWORD rax, [ret_stack_rsp] 266 + mov QWORD rdi, [rax] 267 + mov rax, 8 268 + sub [ret_stack_rsp], rax 230 269 push rdi 231 270 "}, 232 271 )?, ··· 245 284 test rax, rax 246 285 syscall 247 286 jz {} 248 - 249 287 "}, 250 288 op, l 251 289 )?, ··· 254 292 indoc! {" 255 293 ; {:?} 256 294 jmp {} 257 - 258 295 "}, 259 296 op, l 260 297 )?, 261 298 Dump => {} 262 - op => todo!("{:?}", op), 299 + JumpT(_) => todo!(), // op => todo!("{:?}", op), 263 300 } 264 301 } 265 302 write!(
+2 -2
src/eval.rs
··· 26 26 println!("{}:\t{:?}", i, op); 27 27 match op { 28 28 Op::Push(c) => stack.push(c.bytes()), 29 - Op::Pop => { 29 + Op::Drop => { 30 30 stack.pop(); 31 31 } 32 32 Op::Dup => { ··· 68 68 let (b, a) = (stack.pop().unwrap(), stack.pop().unwrap()); 69 69 stack.push((a == b) as u64); 70 70 } 71 - Op::Neq => { 71 + Op::Ne => { 72 72 let (b, a) = (stack.pop().unwrap(), stack.pop().unwrap()); 73 73 stack.push((a != b) as u64); 74 74 }
+5 -5
src/hir.rs
··· 4 4 use somok::Somok; 5 5 6 6 use crate::{ 7 - parser::{KeyWord, Token}, 7 + lexer::{KeyWord, Token}, 8 8 span::Span, 9 9 }; 10 10 ··· 141 141 fn test_proc() { 142 142 use chumsky::Stream; 143 143 let src = "proc foo int : int do end"; 144 - let tokens = crate::parser::lexer() 144 + let tokens = crate::lexer::lexer() 145 145 .parse(Stream::from_iter( 146 146 Span::new(src.len(), src.len()), 147 147 src.chars().enumerate().map(|(i, c)| (c, Span::point(i))), ··· 264 264 fn test_body() { 265 265 use chumsky::Stream; 266 266 let src = "while true do end"; 267 - let tokens = crate::parser::lexer() 267 + let tokens = crate::lexer::lexer() 268 268 .parse(Stream::from_iter( 269 269 Span::new(src.len(), src.len()), 270 270 src.chars().enumerate().map(|(i, c)| (c, Span::point(i))), ··· 288 288 else 289 289 other 290 290 end"; 291 - let tokens = crate::parser::lexer() 291 + let tokens = crate::lexer::lexer() 292 292 .parse(Stream::from_iter( 293 293 Span::new(src.len(), src.len()), 294 294 src.chars().enumerate().map(|(i, c)| (c, Span::point(i))), ··· 311 311 use chumsky::Stream; 312 312 let src = "proc foo : int do 1 end 313 313 proc bar : int do 2 end"; 314 - let tokens = crate::parser::lexer() 314 + let tokens = crate::lexer::lexer() 315 315 .parse(Stream::from_iter( 316 316 Span::new(src.len(), src.len()), 317 317 src.chars().enumerate().map(|(i, c)| (c, Span::point(i))),
+1 -1
src/lib.rs
··· 3 3 pub mod emit; 4 4 pub mod eval; 5 5 pub mod hir; 6 + pub mod lexer; 6 7 pub mod lir; 7 - pub mod parser; 8 8 pub mod span; 9 9 pub mod typecheck;
+6 -6
src/lir.rs
··· 8 8 #[derive(Debug)] 9 9 pub enum Op { 10 10 Push(Const), 11 - Pop, 11 + Drop, 12 12 Dup, 13 13 Swap, 14 14 Over, ··· 22 22 Mul, 23 23 24 24 Eq, 25 - Neq, 25 + Ne, 26 26 Lt, 27 27 Le, 28 28 Gt, ··· 79 79 match node.ast { 80 80 AstKind::Literal(c) => self.emit(Push(c)), 81 81 AstKind::Word(w) => match w.as_str() { 82 - "pop" => self.emit(Pop), 82 + "drop" => self.emit(Drop), 83 83 "dup" => self.emit(Dup), 84 84 "swap" => self.emit(Swap), 85 85 "over" => self.emit(Over), 86 86 87 87 "+" => self.emit(Add), 88 88 "-" => self.emit(Sub), 89 - "%/" => self.emit(Divmod), 89 + "divmod" => self.emit(Divmod), 90 90 "*" => self.emit(Sub), 91 91 92 92 "=" => self.emit(Eq), 93 - "!=" => self.emit(Neq), 93 + "!=" => self.emit(Ne), 94 94 "<" => self.emit(Lt), 95 95 "<=" => self.emit(Le), 96 96 ">" => self.emit(Gt), ··· 142 142 } 143 143 144 144 fn gen_label(&mut self) -> String { 145 - let res = format!("{}{}", self.current_name, self.label); 145 + let res = format!(".{}{}", self.current_name, self.label); 146 146 self.label += 1; 147 147 res 148 148 }
+1 -1
src/main.rs
··· 1 1 use chumsky::{Parser, Stream}; 2 2 use clap::Parser as ClapParser; 3 3 use rotth::{ 4 - emit, eval::eval, hir::procs, lir, parser::lexer, span::Span, typecheck::typecheck_program, 4 + emit, eval::eval, hir::procs, lexer::lexer, lir, span::Span, typecheck::typecheck_program, 5 5 }; 6 6 use somok::Somok; 7 7 use std::{
src/parser.rs src/lexer.rs
+2 -2
src/typecheck.rs
··· 152 152 println!("{:?}", types); 153 153 return error(node.span, CompStop, ""); 154 154 } 155 - "print" | "pop" => { 155 + "print" | "drop" => { 156 156 stack.pop(heap).ok_or_else(|| { 157 157 Error::new(node.span, NotEnoughData, "Not enough data to pop") 158 158 })?; ··· 186 186 stack.push(heap, b); 187 187 } 188 188 "+" | "-" | "*" => typecheck_binop(stack, heap, node)?, 189 - "%/" => typecheck_divmod(stack, heap, node)?, 189 + "divmod" => typecheck_divmod(stack, heap, node)?, 190 190 "=" | "!=" | "<" | "<=" | ">" | ">=" => typecheck_boolean(stack, heap, node)?, 191 191 "&?" => (), 192 192 proc => {