commit
						c40934c052
					
				
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								editor/vscode/mclang-0.0.2.vsix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								editor/vscode/mclang-0.0.2.vsix
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
  "name": "mclang",
 | 
					  "name": "mclang",
 | 
				
			||||||
  "displayName": "mclang",
 | 
					  "displayName": "mclang",
 | 
				
			||||||
  "description": "Code highlighting for mclang",
 | 
					  "description": "Code highlighting for mclang",
 | 
				
			||||||
  "version": "0.0.1",
 | 
					  "version": "0.0.2",
 | 
				
			||||||
  "repository": {
 | 
					  "repository": {
 | 
				
			||||||
    "type": "git",
 | 
					    "type": "git",
 | 
				
			||||||
    "url": "git@github.com:mc-lang/mclang2.git"
 | 
					    "url": "git@github.com:mc-lang/mclang2.git"
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,6 @@
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "generator-code": "^1.7.4",
 | 
					    "generator-code": "^1.7.4",
 | 
				
			||||||
    "vsce": "^2.15.0"
 | 
					    "@vscode/vsce": "^2.15.0"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								include/compat.mcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								include/compat.mcl
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					// todo: add some sort of macrow
 | 
				
			||||||
| 
						 | 
					@ -1,19 +1,18 @@
 | 
				
			||||||
 | 
					const FS_O_APPEND 1024 end // append to existing file
 | 
				
			||||||
macro FS_O_APPEND 1024 end // append to existing file
 | 
					const FS_O_ASYNC 8192 end // use signal-driven IO
 | 
				
			||||||
macro FS_O_ASYNC 8192 end // use signal-driven IO
 | 
					const FS_O_CLOEXEC 524288 end // use close-on-exec (avoid race conditions and lock contentions)
 | 
				
			||||||
macro FS_O_CLOEXEC 524288 end // use close-on-exec (avoid race conditions and lock contentions)
 | 
					const FS_O_CREAT 64 end // create file if it doesn’t exist
 | 
				
			||||||
macro FS_O_CREAT 64 end // create file if it doesn’t exist
 | 
					const FS_O_DIRECT 16384 end // bypass cache (slower)
 | 
				
			||||||
macro FS_O_DIRECT 16384 end // bypass cache (slower)
 | 
					const FS_O_DIRECTORY 65536 end // fail if pathname isn’t a directory
 | 
				
			||||||
macro FS_O_DIRECTORY 65536 end // fail if pathname isn’t a directory
 | 
					const FS_O_DSYNC 4096 end // ensure output is sent to hardware and metadata written before return
 | 
				
			||||||
macro FS_O_DSYNC 4096 end // ensure output is sent to hardware and metadata written before return
 | 
					const FS_O_EXCL 128 end // ensure creation of file
 | 
				
			||||||
macro FS_O_EXCL 128 end // ensure creation of file
 | 
					const FS_O_LARGEFILE 0 end // allows use of file sizes represented by off64_t
 | 
				
			||||||
macro FS_O_LARGEFILE 0 end // allows use of file sizes represented by off64_t
 | 
					const FS_O_NOATIME 262144 end // do not increment access time upon open
 | 
				
			||||||
macro FS_O_NOATIME 262144 end // do not increment access time upon open
 | 
					const FS_O_NOCTTY 256 end // if pathname is a terminal device, don’t become controlling terminal
 | 
				
			||||||
macro FS_O_NOCTTY 256 end // if pathname is a terminal device, don’t become controlling terminal
 | 
					const FS_O_NOFOLLOW 131072 end // fail if pathname is symbolic link
 | 
				
			||||||
macro FS_O_NOFOLLOW 131072 end // fail if pathname is symbolic link
 | 
					const FS_O_NONBLOCK 2048 end // if possible, open file with non-blocking IO
 | 
				
			||||||
macro FS_O_NONBLOCK 2048 end // if possible, open file with non-blocking IO
 | 
					const FS_O_NDELAY 2048 end // same as O_NONBLOCK
 | 
				
			||||||
macro FS_O_NDELAY 2048 end // same as O_NONBLOCK
 | 
					const FS_O_PATH 2097152 end // open descriptor for obtaining permissions and status of a file but does not allow read/write operations
 | 
				
			||||||
macro FS_O_PATH 2097152 end // open descriptor for obtaining permissions and status of a file but does not allow read/write operations
 | 
					const FS_O_SYNC 1052672 end // wait for IO to complete before returning
 | 
				
			||||||
macro FS_O_SYNC 1052672 end // wait for IO to complete before returning
 | 
					const FS_O_TMPFILE 4259840 end // create an unnamed, unreachable (via any other open call) temporary file
 | 
				
			||||||
macro FS_O_TMPFILE 4259840 end // create an unnamed, unreachable (via any other open call) temporary file
 | 
					const FS_O_TRUNC 512 end // if file exists, ovewrite it (careful!)
 | 
				
			||||||
macro FS_O_TRUNC 512 end // if file exists, ovewrite it (careful!)
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,16 +1,15 @@
 | 
				
			||||||
macro NULL 0 end
 | 
					const NULL 0 end
 | 
				
			||||||
macro false 0 end
 | 
					const false 0 end
 | 
				
			||||||
macro true 1 end
 | 
					const true 1 end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro div divmod drop end
 | 
					fn div with int int returns int then divmod drop done
 | 
				
			||||||
macro mod divmod swap drop end
 | 
					fn mod with int int returns int then divmod swap drop done
 | 
				
			||||||
macro / div end
 | 
					 | 
				
			||||||
macro % mod end
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro 2dup over over end
 | 
					 | 
				
			||||||
macro 2drop drop drop end
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
macro sizeof(u64) 8 end
 | 
					fn dup2 with any any returns any any any any then over over done
 | 
				
			||||||
macro sizeof(u32) 4 end
 | 
					fn drop2 with any any returns void then drop drop done
 | 
				
			||||||
macro sizeof(u16) 2 end
 | 
					
 | 
				
			||||||
macro sizeof(u8)  1 end
 | 
					const sizeof(u64) 8 end
 | 
				
			||||||
 | 
					const sizeof(u32) 4 end
 | 
				
			||||||
 | 
					const sizeof(u16) 2 end
 | 
				
			||||||
 | 
					const sizeof(u8)  1 end
 | 
				
			||||||
| 
						 | 
					@ -5,9 +5,9 @@
 | 
				
			||||||
// @arg buff_ptr: Ptr - pointer to the buffer to write
 | 
					// @arg buff_ptr: Ptr - pointer to the buffer to write
 | 
				
			||||||
// @arg fd: Int - file descriptor
 | 
					// @arg fd: Int - file descriptor
 | 
				
			||||||
// @ret Int
 | 
					// @ret Int
 | 
				
			||||||
macro write
 | 
					fn write with int ptr int returns int then
 | 
				
			||||||
    SYS_write syscall3
 | 
					    SYS_write syscall3
 | 
				
			||||||
end
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Write to a file descriptor using the SYS_write syscall
 | 
					// Write to a file descriptor using the SYS_write syscall
 | 
				
			||||||
// args: [buff_size, buff_ptr, fd]
 | 
					// args: [buff_size, buff_ptr, fd]
 | 
				
			||||||
| 
						 | 
					@ -15,9 +15,9 @@ end
 | 
				
			||||||
// @arg buff_ptr: Ptr - pointer to the buffer to write
 | 
					// @arg buff_ptr: Ptr - pointer to the buffer to write
 | 
				
			||||||
// @arg fd: Int - file descriptor
 | 
					// @arg fd: Int - file descriptor
 | 
				
			||||||
// @ret Int
 | 
					// @ret Int
 | 
				
			||||||
macro read
 | 
					fn read with int ptr int returns int then
 | 
				
			||||||
    SYS_read syscall3
 | 
					    SYS_read syscall3
 | 
				
			||||||
end
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Print a string to STDOUT
 | 
					// Print a string to STDOUT
 | 
				
			||||||
| 
						 | 
					@ -25,18 +25,18 @@ end
 | 
				
			||||||
// @arg buff_size: Int - number of bytes to write
 | 
					// @arg buff_size: Int - number of bytes to write
 | 
				
			||||||
// @arg buff_ptr: Ptr - pointer to the buffer to write
 | 
					// @arg buff_ptr: Ptr - pointer to the buffer to write
 | 
				
			||||||
// @ret NULL
 | 
					// @ret NULL
 | 
				
			||||||
macro puts
 | 
					fn puts with int ptr returns void then
 | 
				
			||||||
    STDOUT write drop
 | 
					    STDOUT write drop
 | 
				
			||||||
end
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Print a string to STDERR
 | 
					// Print a string to STDERR
 | 
				
			||||||
// args: [str_size, str_ptr]
 | 
					// args: [str_size, str_ptr]
 | 
				
			||||||
// @arg buff_size: Int - number of bytes to write
 | 
					// @arg buff_size: Int - number of bytes to write
 | 
				
			||||||
// @arg buff_ptr: Ptr - pointer to the buffer to write
 | 
					// @arg buff_ptr: Ptr - pointer to the buffer to write
 | 
				
			||||||
// @ret NULL
 | 
					// @ret NULL
 | 
				
			||||||
macro eputs
 | 
					fn eputs with int ptr returns void then
 | 
				
			||||||
    STDOUT write drop
 | 
					    STDOUT write drop
 | 
				
			||||||
end
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: make putc and eputc after we make local mem
 | 
					// TODO: make putc and eputc after we make local mem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ end
 | 
				
			||||||
// args: [exit_code]
 | 
					// args: [exit_code]
 | 
				
			||||||
// @arg exit_code: Int
 | 
					// @arg exit_code: Int
 | 
				
			||||||
// @ret NULL/NEVER
 | 
					// @ret NULL/NEVER
 | 
				
			||||||
macro exit
 | 
					fn exit with int returns void then
 | 
				
			||||||
    SYS_exit syscall1 drop
 | 
					    SYS_exit syscall1 drop
 | 
				
			||||||
end
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,322 +1,322 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// file descriptors
 | 
					// file descriptors
 | 
				
			||||||
macro STDIN  0 end
 | 
					const STDIN  0 end
 | 
				
			||||||
macro STDOUT 1 end
 | 
					const STDOUT 1 end
 | 
				
			||||||
macro STDERR 2 end
 | 
					const STDERR 2 end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// syscalls
 | 
					// syscalls
 | 
				
			||||||
macro SYS_read                   0 end
 | 
					const SYS_read                   0 end
 | 
				
			||||||
macro SYS_write                  1 end
 | 
					const SYS_write                  1 end
 | 
				
			||||||
macro SYS_open                   2 end
 | 
					const SYS_open                   2 end
 | 
				
			||||||
macro SYS_close                  3 end
 | 
					const SYS_close                  3 end
 | 
				
			||||||
macro SYS_stat                   4 end
 | 
					const SYS_stat                   4 end
 | 
				
			||||||
macro SYS_fstat                  5 end
 | 
					const SYS_fstat                  5 end
 | 
				
			||||||
macro SYS_lstat                  6 end
 | 
					const SYS_lstat                  6 end
 | 
				
			||||||
macro SYS_poll                   7 end
 | 
					const SYS_poll                   7 end
 | 
				
			||||||
macro SYS_lseek                  8 end
 | 
					const SYS_lseek                  8 end
 | 
				
			||||||
macro SYS_mmap                   9 end
 | 
					const SYS_mmap                   9 end
 | 
				
			||||||
macro SYS_mprotect               10 end
 | 
					const SYS_mprotect               10 end
 | 
				
			||||||
macro SYS_munmap                 11 end
 | 
					const SYS_munmap                 11 end
 | 
				
			||||||
macro SYS_brk                    12 end
 | 
					const SYS_brk                    12 end
 | 
				
			||||||
macro SYS_rt_sigaction           13 end
 | 
					const SYS_rt_sigaction           13 end
 | 
				
			||||||
macro SYS_rt_sigprocmask         14 end
 | 
					const SYS_rt_sigprocmask         14 end
 | 
				
			||||||
macro SYS_rt_sigreturn           15 end
 | 
					const SYS_rt_sigreturn           15 end
 | 
				
			||||||
macro SYS_ioctl                  16 end
 | 
					const SYS_ioctl                  16 end
 | 
				
			||||||
macro SYS_pread64                17 end
 | 
					const SYS_pread64                17 end
 | 
				
			||||||
macro SYS_pwrite64               18 end
 | 
					const SYS_pwrite64               18 end
 | 
				
			||||||
macro SYS_readv                  19 end
 | 
					const SYS_readv                  19 end
 | 
				
			||||||
macro SYS_writev                 20 end
 | 
					const SYS_writev                 20 end
 | 
				
			||||||
macro SYS_access                 21 end
 | 
					const SYS_access                 21 end
 | 
				
			||||||
macro SYS_pipe                   22 end
 | 
					const SYS_pipe                   22 end
 | 
				
			||||||
macro SYS_select                 23 end
 | 
					const SYS_select                 23 end
 | 
				
			||||||
macro SYS_sched_yield            24 end
 | 
					const SYS_sched_yield            24 end
 | 
				
			||||||
macro SYS_mremap                 25 end
 | 
					const SYS_mremap                 25 end
 | 
				
			||||||
macro SYS_msync                  26 end
 | 
					const SYS_msync                  26 end
 | 
				
			||||||
macro SYS_mincore                27 end
 | 
					const SYS_mincore                27 end
 | 
				
			||||||
macro SYS_madvise                28 end
 | 
					const SYS_madvise                28 end
 | 
				
			||||||
macro SYS_shmget                 29 end
 | 
					const SYS_shmget                 29 end
 | 
				
			||||||
macro SYS_shmat                  30 end
 | 
					const SYS_shmat                  30 end
 | 
				
			||||||
macro SYS_shmctl                 31 end
 | 
					const SYS_shmctl                 31 end
 | 
				
			||||||
macro SYS_dup                    32 end
 | 
					const SYS_dup                    32 end
 | 
				
			||||||
macro SYS_dup2                   33 end
 | 
					const SYS_dup2                   33 end
 | 
				
			||||||
macro SYS_pause                  34 end
 | 
					const SYS_pause                  34 end
 | 
				
			||||||
macro SYS_nanosleep              35 end
 | 
					const SYS_nanosleep              35 end
 | 
				
			||||||
macro SYS_getitimer              36 end
 | 
					const SYS_getitimer              36 end
 | 
				
			||||||
macro SYS_alarm                  37 end
 | 
					const SYS_alarm                  37 end
 | 
				
			||||||
macro SYS_setitimer              38 end
 | 
					const SYS_setitimer              38 end
 | 
				
			||||||
macro SYS_getpid                 39 end
 | 
					const SYS_getpid                 39 end
 | 
				
			||||||
macro SYS_sendfile               40 end
 | 
					const SYS_sendfile               40 end
 | 
				
			||||||
macro SYS_socket                 41 end
 | 
					const SYS_socket                 41 end
 | 
				
			||||||
macro SYS_connect                42 end
 | 
					const SYS_connect                42 end
 | 
				
			||||||
macro SYS_accept                 43 end
 | 
					const SYS_accept                 43 end
 | 
				
			||||||
macro SYS_sendto                 44 end
 | 
					const SYS_sendto                 44 end
 | 
				
			||||||
macro SYS_recvfrom               45 end
 | 
					const SYS_recvfrom               45 end
 | 
				
			||||||
macro SYS_sendmsg                46 end
 | 
					const SYS_sendmsg                46 end
 | 
				
			||||||
macro SYS_recvmsg                47 end
 | 
					const SYS_recvmsg                47 end
 | 
				
			||||||
macro SYS_shutdown               48 end
 | 
					const SYS_shutdown               48 end
 | 
				
			||||||
macro SYS_bind                   49 end
 | 
					const SYS_bind                   49 end
 | 
				
			||||||
macro SYS_listen                 50 end
 | 
					const SYS_listen                 50 end
 | 
				
			||||||
macro SYS_getsockname            51 end
 | 
					const SYS_getsockname            51 end
 | 
				
			||||||
macro SYS_getpeername            52 end
 | 
					const SYS_getpeername            52 end
 | 
				
			||||||
macro SYS_socketpair             53 end
 | 
					const SYS_socketpair             53 end
 | 
				
			||||||
macro SYS_setsockopt             54 end
 | 
					const SYS_setsockopt             54 end
 | 
				
			||||||
macro SYS_getsockopt             55 end
 | 
					const SYS_getsockopt             55 end
 | 
				
			||||||
macro SYS_clone                  56 end
 | 
					const SYS_clone                  56 end
 | 
				
			||||||
macro SYS_fork                   57 end
 | 
					const SYS_fork                   57 end
 | 
				
			||||||
macro SYS_vfork                  58 end
 | 
					const SYS_vfork                  58 end
 | 
				
			||||||
macro SYS_execve                 59 end
 | 
					const SYS_execve                 59 end
 | 
				
			||||||
macro SYS_exit                   60 end
 | 
					const SYS_exit                   60 end
 | 
				
			||||||
macro SYS_wait4                  61 end
 | 
					const SYS_wait4                  61 end
 | 
				
			||||||
macro SYS_kill                   62 end
 | 
					const SYS_kill                   62 end
 | 
				
			||||||
macro SYS_uname                  63 end
 | 
					const SYS_uname                  63 end
 | 
				
			||||||
macro SYS_semget                 64 end
 | 
					const SYS_semget                 64 end
 | 
				
			||||||
macro SYS_semop                  65 end
 | 
					const SYS_semop                  65 end
 | 
				
			||||||
macro SYS_semctl                 66 end
 | 
					const SYS_semctl                 66 end
 | 
				
			||||||
macro SYS_shmdt                  67 end
 | 
					const SYS_shmdt                  67 end
 | 
				
			||||||
macro SYS_msgget                 68 end
 | 
					const SYS_msgget                 68 end
 | 
				
			||||||
macro SYS_msgsnd                 69 end
 | 
					const SYS_msgsnd                 69 end
 | 
				
			||||||
macro SYS_msgrcv                 70 end
 | 
					const SYS_msgrcv                 70 end
 | 
				
			||||||
macro SYS_msgctl                 71 end
 | 
					const SYS_msgctl                 71 end
 | 
				
			||||||
macro SYS_fcntl                  72 end
 | 
					const SYS_fcntl                  72 end
 | 
				
			||||||
macro SYS_flock                  73 end
 | 
					const SYS_flock                  73 end
 | 
				
			||||||
macro SYS_fsync                  74 end
 | 
					const SYS_fsync                  74 end
 | 
				
			||||||
macro SYS_fdatasync              75 end
 | 
					const SYS_fdatasync              75 end
 | 
				
			||||||
macro SYS_truncate               76 end
 | 
					const SYS_truncate               76 end
 | 
				
			||||||
macro SYS_ftruncate              77 end
 | 
					const SYS_ftruncate              77 end
 | 
				
			||||||
macro SYS_getdents               78 end
 | 
					const SYS_getdents               78 end
 | 
				
			||||||
macro SYS_getcwd                 79 end
 | 
					const SYS_getcwd                 79 end
 | 
				
			||||||
macro SYS_chdir                  80 end
 | 
					const SYS_chdir                  80 end
 | 
				
			||||||
macro SYS_fchdir                 81 end
 | 
					const SYS_fchdir                 81 end
 | 
				
			||||||
macro SYS_rename                 82 end
 | 
					const SYS_rename                 82 end
 | 
				
			||||||
macro SYS_mkdir                  83 end
 | 
					const SYS_mkdir                  83 end
 | 
				
			||||||
macro SYS_rmdir                  84 end
 | 
					const SYS_rmdir                  84 end
 | 
				
			||||||
macro SYS_creat                  85 end
 | 
					const SYS_creat                  85 end
 | 
				
			||||||
macro SYS_link                   86 end
 | 
					const SYS_link                   86 end
 | 
				
			||||||
macro SYS_unlink                 87 end
 | 
					const SYS_unlink                 87 end
 | 
				
			||||||
macro SYS_symlink                88 end
 | 
					const SYS_symlink                88 end
 | 
				
			||||||
macro SYS_readlink               89 end
 | 
					const SYS_readlink               89 end
 | 
				
			||||||
macro SYS_chmod                  90 end
 | 
					const SYS_chmod                  90 end
 | 
				
			||||||
macro SYS_fchmod                 91 end
 | 
					const SYS_fchmod                 91 end
 | 
				
			||||||
macro SYS_chown                  92 end
 | 
					const SYS_chown                  92 end
 | 
				
			||||||
macro SYS_fchown                 93 end
 | 
					const SYS_fchown                 93 end
 | 
				
			||||||
macro SYS_lchown                 94 end
 | 
					const SYS_lchown                 94 end
 | 
				
			||||||
macro SYS_umask                  95 end
 | 
					const SYS_umask                  95 end
 | 
				
			||||||
macro SYS_gettimeofday           96 end
 | 
					const SYS_gettimeofday           96 end
 | 
				
			||||||
macro SYS_getrlimit              97 end
 | 
					const SYS_getrlimit              97 end
 | 
				
			||||||
macro SYS_getrusage              98 end
 | 
					const SYS_getrusage              98 end
 | 
				
			||||||
macro SYS_sysinfo                99 end
 | 
					const SYS_sysinfo                99 end
 | 
				
			||||||
macro SYS_times                  100 end
 | 
					const SYS_times                  100 end
 | 
				
			||||||
macro SYS_ptrace                 101 end
 | 
					const SYS_ptrace                 101 end
 | 
				
			||||||
macro SYS_getuid                 102 end
 | 
					const SYS_getuid                 102 end
 | 
				
			||||||
macro SYS_syslog                 103 end
 | 
					const SYS_syslog                 103 end
 | 
				
			||||||
macro SYS_getgid                 104 end
 | 
					const SYS_getgid                 104 end
 | 
				
			||||||
macro SYS_setuid                 105 end
 | 
					const SYS_setuid                 105 end
 | 
				
			||||||
macro SYS_setgid                 106 end
 | 
					const SYS_setgid                 106 end
 | 
				
			||||||
macro SYS_geteuid                107 end
 | 
					const SYS_geteuid                107 end
 | 
				
			||||||
macro SYS_getegid                108 end
 | 
					const SYS_getegid                108 end
 | 
				
			||||||
macro SYS_setpgid                109 end
 | 
					const SYS_setpgid                109 end
 | 
				
			||||||
macro SYS_getppid                110 end
 | 
					const SYS_getppid                110 end
 | 
				
			||||||
macro SYS_getpgrp                111 end
 | 
					const SYS_getpgrp                111 end
 | 
				
			||||||
macro SYS_setsid                 112 end
 | 
					const SYS_setsid                 112 end
 | 
				
			||||||
macro SYS_setreuid               113 end
 | 
					const SYS_setreuid               113 end
 | 
				
			||||||
macro SYS_setregid               114 end
 | 
					const SYS_setregid               114 end
 | 
				
			||||||
macro SYS_getgroups              115 end
 | 
					const SYS_getgroups              115 end
 | 
				
			||||||
macro SYS_setgroups              116 end
 | 
					const SYS_setgroups              116 end
 | 
				
			||||||
macro SYS_setresuid              117 end
 | 
					const SYS_setresuid              117 end
 | 
				
			||||||
macro SYS_getresuid              118 end
 | 
					const SYS_getresuid              118 end
 | 
				
			||||||
macro SYS_setresgid              119 end
 | 
					const SYS_setresgid              119 end
 | 
				
			||||||
macro SYS_getresgid              120 end
 | 
					const SYS_getresgid              120 end
 | 
				
			||||||
macro SYS_getpgid                121 end
 | 
					const SYS_getpgid                121 end
 | 
				
			||||||
macro SYS_setfsuid               122 end
 | 
					const SYS_setfsuid               122 end
 | 
				
			||||||
macro SYS_setfsgid               123 end
 | 
					const SYS_setfsgid               123 end
 | 
				
			||||||
macro SYS_getsid                 124 end
 | 
					const SYS_getsid                 124 end
 | 
				
			||||||
macro SYS_capget                 125 end
 | 
					const SYS_capget                 125 end
 | 
				
			||||||
macro SYS_capset                 126 end
 | 
					const SYS_capset                 126 end
 | 
				
			||||||
macro SYS_rt_sigpending          127 end
 | 
					const SYS_rt_sigpending          127 end
 | 
				
			||||||
macro SYS_rt_sigtimedwait        128 end
 | 
					const SYS_rt_sigtimedwait        128 end
 | 
				
			||||||
macro SYS_rt_sigqueueinfo        129 end
 | 
					const SYS_rt_sigqueueinfo        129 end
 | 
				
			||||||
macro SYS_rt_sigsuspend          130 end
 | 
					const SYS_rt_sigsuspend          130 end
 | 
				
			||||||
macro SYS_sigaltstack            131 end
 | 
					const SYS_sigaltstack            131 end
 | 
				
			||||||
macro SYS_utime                  132 end
 | 
					const SYS_utime                  132 end
 | 
				
			||||||
macro SYS_mknod                  133 end
 | 
					const SYS_mknod                  133 end
 | 
				
			||||||
macro SYS_uselib                 134 end
 | 
					const SYS_uselib                 134 end
 | 
				
			||||||
macro SYS_personality            135 end
 | 
					const SYS_personality            135 end
 | 
				
			||||||
macro SYS_ustat                  136 end
 | 
					const SYS_ustat                  136 end
 | 
				
			||||||
macro SYS_statfs                 137 end
 | 
					const SYS_statfs                 137 end
 | 
				
			||||||
macro SYS_fstatfs                138 end
 | 
					const SYS_fstatfs                138 end
 | 
				
			||||||
macro SYS_sysfs                  139 end
 | 
					const SYS_sysfs                  139 end
 | 
				
			||||||
macro SYS_getpriority            140 end
 | 
					const SYS_getpriority            140 end
 | 
				
			||||||
macro SYS_setpriority            141 end
 | 
					const SYS_setpriority            141 end
 | 
				
			||||||
macro SYS_sched_setparam         142 end
 | 
					const SYS_sched_setparam         142 end
 | 
				
			||||||
macro SYS_sched_getparam         143 end
 | 
					const SYS_sched_getparam         143 end
 | 
				
			||||||
macro SYS_sched_setscheduler     144 end
 | 
					const SYS_sched_setscheduler     144 end
 | 
				
			||||||
macro SYS_sched_getscheduler     145 end
 | 
					const SYS_sched_getscheduler     145 end
 | 
				
			||||||
macro SYS_sched_get_priority_max 146 end
 | 
					const SYS_sched_get_priority_max 146 end
 | 
				
			||||||
macro SYS_sched_get_priority_min 147 end
 | 
					const SYS_sched_get_priority_min 147 end
 | 
				
			||||||
macro SYS_sched_rr_get_interval  148 end
 | 
					const SYS_sched_rr_get_interval  148 end
 | 
				
			||||||
macro SYS_mlock                  149 end
 | 
					const SYS_mlock                  149 end
 | 
				
			||||||
macro SYS_munlock                150 end
 | 
					const SYS_munlock                150 end
 | 
				
			||||||
macro SYS_mlockall               151 end
 | 
					const SYS_mlockall               151 end
 | 
				
			||||||
macro SYS_munlockall             152 end
 | 
					const SYS_munlockall             152 end
 | 
				
			||||||
macro SYS_vhangup                153 end
 | 
					const SYS_vhangup                153 end
 | 
				
			||||||
macro SYS_modify_ldt             154 end
 | 
					const SYS_modify_ldt             154 end
 | 
				
			||||||
macro SYS_pivot_root             155 end
 | 
					const SYS_pivot_root             155 end
 | 
				
			||||||
macro SYS__sysctl                156 end
 | 
					const SYS__sysctl                156 end
 | 
				
			||||||
macro SYS_prctl                  157 end
 | 
					const SYS_prctl                  157 end
 | 
				
			||||||
macro SYS_arch_prctl             158 end
 | 
					const SYS_arch_prctl             158 end
 | 
				
			||||||
macro SYS_adjtimex               159 end
 | 
					const SYS_adjtimex               159 end
 | 
				
			||||||
macro SYS_setrlimit              160 end
 | 
					const SYS_setrlimit              160 end
 | 
				
			||||||
macro SYS_chroot                 161 end
 | 
					const SYS_chroot                 161 end
 | 
				
			||||||
macro SYS_sync                   162 end
 | 
					const SYS_sync                   162 end
 | 
				
			||||||
macro SYS_acct                   163 end
 | 
					const SYS_acct                   163 end
 | 
				
			||||||
macro SYS_settimeofday           164 end
 | 
					const SYS_settimeofday           164 end
 | 
				
			||||||
macro SYS_mount                  165 end
 | 
					const SYS_mount                  165 end
 | 
				
			||||||
macro SYS_umount2                166 end
 | 
					const SYS_umount2                166 end
 | 
				
			||||||
macro SYS_swapon                 167 end
 | 
					const SYS_swapon                 167 end
 | 
				
			||||||
macro SYS_swapoff                168 end
 | 
					const SYS_swapoff                168 end
 | 
				
			||||||
macro SYS_reboot                 169 end
 | 
					const SYS_reboot                 169 end
 | 
				
			||||||
macro SYS_sethostname            170 end
 | 
					const SYS_sethostname            170 end
 | 
				
			||||||
macro SYS_setdomainname          171 end
 | 
					const SYS_setdomainname          171 end
 | 
				
			||||||
macro SYS_iopl                   172 end
 | 
					const SYS_iopl                   172 end
 | 
				
			||||||
macro SYS_ioperm                 173 end
 | 
					const SYS_ioperm                 173 end
 | 
				
			||||||
macro SYS_create_module          174 end
 | 
					const SYS_create_module          174 end
 | 
				
			||||||
macro SYS_init_module            175 end
 | 
					const SYS_init_module            175 end
 | 
				
			||||||
macro SYS_delete_module          176 end
 | 
					const SYS_delete_module          176 end
 | 
				
			||||||
macro SYS_get_kernel_syms        177 end
 | 
					const SYS_get_kernel_syms        177 end
 | 
				
			||||||
macro SYS_query_module           178 end
 | 
					const SYS_query_module           178 end
 | 
				
			||||||
macro SYS_quotactl               179 end
 | 
					const SYS_quotactl               179 end
 | 
				
			||||||
macro SYS_nfsservctl             180 end
 | 
					const SYS_nfsservctl             180 end
 | 
				
			||||||
macro SYS_getpmsg                181 end
 | 
					const SYS_getpmsg                181 end
 | 
				
			||||||
macro SYS_putpmsg                182 end
 | 
					const SYS_putpmsg                182 end
 | 
				
			||||||
macro SYS_afs_syscall            183 end
 | 
					const SYS_afs_syscall            183 end
 | 
				
			||||||
macro SYS_tuxcall                184 end
 | 
					const SYS_tuxcall                184 end
 | 
				
			||||||
macro SYS_security               185 end
 | 
					const SYS_security               185 end
 | 
				
			||||||
macro SYS_gettid                 186 end
 | 
					const SYS_gettid                 186 end
 | 
				
			||||||
macro SYS_readahead              187 end
 | 
					const SYS_readahead              187 end
 | 
				
			||||||
macro SYS_setxattr               188 end
 | 
					const SYS_setxattr               188 end
 | 
				
			||||||
macro SYS_lsetxattr              189 end
 | 
					const SYS_lsetxattr              189 end
 | 
				
			||||||
macro SYS_fsetxattr              190 end
 | 
					const SYS_fsetxattr              190 end
 | 
				
			||||||
macro SYS_getxattr               191 end
 | 
					const SYS_getxattr               191 end
 | 
				
			||||||
macro SYS_lgetxattr              192 end
 | 
					const SYS_lgetxattr              192 end
 | 
				
			||||||
macro SYS_fgetxattr              193 end
 | 
					const SYS_fgetxattr              193 end
 | 
				
			||||||
macro SYS_listxattr              194 end
 | 
					const SYS_listxattr              194 end
 | 
				
			||||||
macro SYS_llistxattr             195 end
 | 
					const SYS_llistxattr             195 end
 | 
				
			||||||
macro SYS_flistxattr             196 end
 | 
					const SYS_flistxattr             196 end
 | 
				
			||||||
macro SYS_removexattr            197 end
 | 
					const SYS_removexattr            197 end
 | 
				
			||||||
macro SYS_lremovexattr           198 end
 | 
					const SYS_lremovexattr           198 end
 | 
				
			||||||
macro SYS_fremovexattr           199 end
 | 
					const SYS_fremovexattr           199 end
 | 
				
			||||||
macro SYS_tkill                  200 end
 | 
					const SYS_tkill                  200 end
 | 
				
			||||||
macro SYS_time                   201 end
 | 
					const SYS_time                   201 end
 | 
				
			||||||
macro SYS_futex                  202 end
 | 
					const SYS_futex                  202 end
 | 
				
			||||||
macro SYS_sched_setaffinity      203 end
 | 
					const SYS_sched_setaffinity      203 end
 | 
				
			||||||
macro SYS_sched_getaffinity      204 end
 | 
					const SYS_sched_getaffinity      204 end
 | 
				
			||||||
macro SYS_set_thread_area        205 end
 | 
					const SYS_set_thread_area        205 end
 | 
				
			||||||
macro SYS_io_setup               206 end
 | 
					const SYS_io_setup               206 end
 | 
				
			||||||
macro SYS_io_destroy             207 end
 | 
					const SYS_io_destroy             207 end
 | 
				
			||||||
macro SYS_io_getevents           208 end
 | 
					const SYS_io_getevents           208 end
 | 
				
			||||||
macro SYS_io_submit              209 end
 | 
					const SYS_io_submit              209 end
 | 
				
			||||||
macro SYS_io_cancel              210 end
 | 
					const SYS_io_cancel              210 end
 | 
				
			||||||
macro SYS_get_thread_area        211 end
 | 
					const SYS_get_thread_area        211 end
 | 
				
			||||||
macro SYS_lookup_dcookie         212 end
 | 
					const SYS_lookup_dcookie         212 end
 | 
				
			||||||
macro SYS_epoll_create           213 end
 | 
					const SYS_epoll_create           213 end
 | 
				
			||||||
macro SYS_epoll_ctl_old          214 end
 | 
					const SYS_epoll_ctl_old          214 end
 | 
				
			||||||
macro SYS_epoll_wait_old         215 end
 | 
					const SYS_epoll_wait_old         215 end
 | 
				
			||||||
macro SYS_remap_file_pages       216 end
 | 
					const SYS_remap_file_pages       216 end
 | 
				
			||||||
macro SYS_getdents64             217 end
 | 
					const SYS_getdents64             217 end
 | 
				
			||||||
macro SYS_set_tid_address        218 end
 | 
					const SYS_set_tid_address        218 end
 | 
				
			||||||
macro SYS_restart_syscall        219 end
 | 
					const SYS_restart_syscall        219 end
 | 
				
			||||||
macro SYS_semtimedop             220 end
 | 
					const SYS_semtimedop             220 end
 | 
				
			||||||
macro SYS_fadvise64              221 end
 | 
					const SYS_fadvise64              221 end
 | 
				
			||||||
macro SYS_timer_create           222 end
 | 
					const SYS_timer_create           222 end
 | 
				
			||||||
macro SYS_timer_settime          223 end
 | 
					const SYS_timer_settime          223 end
 | 
				
			||||||
macro SYS_timer_gettime          224 end
 | 
					const SYS_timer_gettime          224 end
 | 
				
			||||||
macro SYS_timer_getoverrun       225 end
 | 
					const SYS_timer_getoverrun       225 end
 | 
				
			||||||
macro SYS_timer_delete           226 end
 | 
					const SYS_timer_delete           226 end
 | 
				
			||||||
macro SYS_clock_settime          227 end
 | 
					const SYS_clock_settime          227 end
 | 
				
			||||||
macro SYS_clock_gettime          228 end
 | 
					const SYS_clock_gettime          228 end
 | 
				
			||||||
macro SYS_clock_getres           229 end
 | 
					const SYS_clock_getres           229 end
 | 
				
			||||||
macro SYS_clock_nanosleep        230 end
 | 
					const SYS_clock_nanosleep        230 end
 | 
				
			||||||
macro SYS_exit_group             231 end
 | 
					const SYS_exit_group             231 end
 | 
				
			||||||
macro SYS_epoll_wait             232 end
 | 
					const SYS_epoll_wait             232 end
 | 
				
			||||||
macro SYS_epoll_ctl              233 end
 | 
					const SYS_epoll_ctl              233 end
 | 
				
			||||||
macro SYS_tgkill                 234 end
 | 
					const SYS_tgkill                 234 end
 | 
				
			||||||
macro SYS_utimes                 235 end
 | 
					const SYS_utimes                 235 end
 | 
				
			||||||
macro SYS_vserver                236 end
 | 
					const SYS_vserver                236 end
 | 
				
			||||||
macro SYS_mbind                  237 end
 | 
					const SYS_mbind                  237 end
 | 
				
			||||||
macro SYS_set_mempolicy          238 end
 | 
					const SYS_set_mempolicy          238 end
 | 
				
			||||||
macro SYS_get_mempolicy          239 end
 | 
					const SYS_get_mempolicy          239 end
 | 
				
			||||||
macro SYS_mq_open                240 end
 | 
					const SYS_mq_open                240 end
 | 
				
			||||||
macro SYS_mq_unlink              241 end
 | 
					const SYS_mq_unlink              241 end
 | 
				
			||||||
macro SYS_mq_timedsend           242 end
 | 
					const SYS_mq_timedsend           242 end
 | 
				
			||||||
macro SYS_mq_timedreceive        243 end
 | 
					const SYS_mq_timedreceive        243 end
 | 
				
			||||||
macro SYS_mq_notify              244 end
 | 
					const SYS_mq_notify              244 end
 | 
				
			||||||
macro SYS_mq_getsetattr          245 end
 | 
					const SYS_mq_getsetattr          245 end
 | 
				
			||||||
macro SYS_kexec_load             246 end
 | 
					const SYS_kexec_load             246 end
 | 
				
			||||||
macro SYS_waitid                 247 end
 | 
					const SYS_waitid                 247 end
 | 
				
			||||||
macro SYS_add_key                248 end
 | 
					const SYS_add_key                248 end
 | 
				
			||||||
macro SYS_request_key            249 end
 | 
					const SYS_request_key            249 end
 | 
				
			||||||
macro SYS_keyctl                 250 end
 | 
					const SYS_keyctl                 250 end
 | 
				
			||||||
macro SYS_ioprio_set             251 end
 | 
					const SYS_ioprio_set             251 end
 | 
				
			||||||
macro SYS_ioprio_get             252 end
 | 
					const SYS_ioprio_get             252 end
 | 
				
			||||||
macro SYS_inotify_init           253 end
 | 
					const SYS_inotify_init           253 end
 | 
				
			||||||
macro SYS_inotify_add_watch      254 end
 | 
					const SYS_inotify_add_watch      254 end
 | 
				
			||||||
macro SYS_inotify_rm_watch       255 end
 | 
					const SYS_inotify_rm_watch       255 end
 | 
				
			||||||
macro SYS_migrate_pages          256 end
 | 
					const SYS_migrate_pages          256 end
 | 
				
			||||||
macro SYS_openat                 257 end
 | 
					const SYS_openat                 257 end
 | 
				
			||||||
macro SYS_mkdirat                258 end
 | 
					const SYS_mkdirat                258 end
 | 
				
			||||||
macro SYS_mknodat                259 end
 | 
					const SYS_mknodat                259 end
 | 
				
			||||||
macro SYS_fchownat               260 end
 | 
					const SYS_fchownat               260 end
 | 
				
			||||||
macro SYS_futimesat              261 end
 | 
					const SYS_futimesat              261 end
 | 
				
			||||||
macro SYS_newfstatat             262 end
 | 
					const SYS_newfstatat             262 end
 | 
				
			||||||
macro SYS_unlinkat               263 end
 | 
					const SYS_unlinkat               263 end
 | 
				
			||||||
macro SYS_renameat               264 end
 | 
					const SYS_renameat               264 end
 | 
				
			||||||
macro SYS_linkat                 265 end
 | 
					const SYS_linkat                 265 end
 | 
				
			||||||
macro SYS_symlinkat              266 end
 | 
					const SYS_symlinkat              266 end
 | 
				
			||||||
macro SYS_readlinkat             267 end
 | 
					const SYS_readlinkat             267 end
 | 
				
			||||||
macro SYS_fchmodat               268 end
 | 
					const SYS_fchmodat               268 end
 | 
				
			||||||
macro SYS_faccessat              269 end
 | 
					const SYS_faccessat              269 end
 | 
				
			||||||
macro SYS_pselect6               270 end
 | 
					const SYS_pselect6               270 end
 | 
				
			||||||
macro SYS_ppoll                  271 end
 | 
					const SYS_ppoll                  271 end
 | 
				
			||||||
macro SYS_unshare                272 end
 | 
					const SYS_unshare                272 end
 | 
				
			||||||
macro SYS_set_robust_list        273 end
 | 
					const SYS_set_robust_list        273 end
 | 
				
			||||||
macro SYS_get_robust_list        274 end
 | 
					const SYS_get_robust_list        274 end
 | 
				
			||||||
macro SYS_splice                 275 end
 | 
					const SYS_splice                 275 end
 | 
				
			||||||
macro SYS_tee                    276 end
 | 
					const SYS_tee                    276 end
 | 
				
			||||||
macro SYS_sync_file_range        277 end
 | 
					const SYS_sync_file_range        277 end
 | 
				
			||||||
macro SYS_vmsplice               278 end
 | 
					const SYS_vmsplice               278 end
 | 
				
			||||||
macro SYS_move_pages             279 end
 | 
					const SYS_move_pages             279 end
 | 
				
			||||||
macro SYS_utimensat              280 end
 | 
					const SYS_utimensat              280 end
 | 
				
			||||||
macro SYS_epoll_pwait            281 end
 | 
					const SYS_epoll_pwait            281 end
 | 
				
			||||||
macro SYS_signalfd               282 end
 | 
					const SYS_signalfd               282 end
 | 
				
			||||||
macro SYS_timerfd_create         283 end
 | 
					const SYS_timerfd_create         283 end
 | 
				
			||||||
macro SYS_eventfd                284 end
 | 
					const SYS_eventfd                284 end
 | 
				
			||||||
macro SYS_fallocate              285 end
 | 
					const SYS_fallocate              285 end
 | 
				
			||||||
macro SYS_timerfd_settime        286 end
 | 
					const SYS_timerfd_settime        286 end
 | 
				
			||||||
macro SYS_timerfd_gettime        287 end
 | 
					const SYS_timerfd_gettime        287 end
 | 
				
			||||||
macro SYS_accept4                288 end
 | 
					const SYS_accept4                288 end
 | 
				
			||||||
macro SYS_signalfd4              289 end
 | 
					const SYS_signalfd4              289 end
 | 
				
			||||||
macro SYS_eventfd2               290 end
 | 
					const SYS_eventfd2               290 end
 | 
				
			||||||
macro SYS_epoll_create1          291 end
 | 
					const SYS_epoll_create1          291 end
 | 
				
			||||||
macro SYS_dup3                   292 end
 | 
					const SYS_dup3                   292 end
 | 
				
			||||||
macro SYS_pipe2                  293 end
 | 
					const SYS_pipe2                  293 end
 | 
				
			||||||
macro SYS_inotify_init1          294 end
 | 
					const SYS_inotify_init1          294 end
 | 
				
			||||||
macro SYS_preadv                 295 end
 | 
					const SYS_preadv                 295 end
 | 
				
			||||||
macro SYS_pwritev                296 end
 | 
					const SYS_pwritev                296 end
 | 
				
			||||||
macro SYS_rt_tgsigqueueinfo      297 end
 | 
					const SYS_rt_tgsigqueueinfo      297 end
 | 
				
			||||||
macro SYS_perf_event_open        298 end
 | 
					const SYS_perf_event_open        298 end
 | 
				
			||||||
macro SYS_recvmmsg               299 end
 | 
					const SYS_recvmmsg               299 end
 | 
				
			||||||
macro SYS_fanotify_init          300 end
 | 
					const SYS_fanotify_init          300 end
 | 
				
			||||||
macro SYS_fanotify_mark          301 end
 | 
					const SYS_fanotify_mark          301 end
 | 
				
			||||||
macro SYS_prlimit64              302 end
 | 
					const SYS_prlimit64              302 end
 | 
				
			||||||
macro SYS_name_to_handle_at      303 end
 | 
					const SYS_name_to_handle_at      303 end
 | 
				
			||||||
macro SYS_open_by_handle_at      304 end
 | 
					const SYS_open_by_handle_at      304 end
 | 
				
			||||||
macro SYS_clock_adjtime          305 end
 | 
					const SYS_clock_adjtime          305 end
 | 
				
			||||||
macro SYS_syncfs                 306 end
 | 
					const SYS_syncfs                 306 end
 | 
				
			||||||
macro SYS_sendmmsg               307 end
 | 
					const SYS_sendmmsg               307 end
 | 
				
			||||||
macro SYS_setns                  308 end
 | 
					const SYS_setns                  308 end
 | 
				
			||||||
macro SYS_getcpu                 309 end
 | 
					const SYS_getcpu                 309 end
 | 
				
			||||||
macro SYS_process_vm_readv       310 end
 | 
					const SYS_process_vm_readv       310 end
 | 
				
			||||||
macro SYS_process_vm_writev      311 end
 | 
					const SYS_process_vm_writev      311 end
 | 
				
			||||||
macro SYS_kcmp                   312 end
 | 
					const SYS_kcmp                   312 end
 | 
				
			||||||
macro SYS_finit_module           313 end
 | 
					const SYS_finit_module           313 end
 | 
				
			||||||
| 
						 | 
					@ -1,27 +0,0 @@
 | 
				
			||||||
 | 
					 | 
				
			||||||
macro load8 @8 end
 | 
					 | 
				
			||||||
macro store8 !8 end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
macro load64
 | 
					 | 
				
			||||||
    7 + 0
 | 
					 | 
				
			||||||
    8 shl over !8 + swap 1 - swap 
 | 
					 | 
				
			||||||
    8 shl over !8 + swap 1 - swap 
 | 
					 | 
				
			||||||
    8 shl over !8 + swap 1 - swap 
 | 
					 | 
				
			||||||
    8 shl over !8 + swap 1 - swap 
 | 
					 | 
				
			||||||
    8 shl over !8 + swap 1 - swap 
 | 
					 | 
				
			||||||
    8 shl over !8 + swap 1 - swap 
 | 
					 | 
				
			||||||
    8 shl over !8 + swap 1 - swap 
 | 
					 | 
				
			||||||
    8 shl over !8 + swap drop
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
macro store64
 | 
					 | 
				
			||||||
    2dup 255 band @8 shr swap 1 + swap
 | 
					 | 
				
			||||||
    2dup 255 band @8 shr swap 1 + swap
 | 
					 | 
				
			||||||
    2dup 255 band @8 shr swap 1 + swap
 | 
					 | 
				
			||||||
    2dup 255 band @8 shr swap 1 + swap
 | 
					 | 
				
			||||||
    2dup 255 band @8 shr swap 1 + swap
 | 
					 | 
				
			||||||
    2dup 255 band @8 shr swap 1 + swap
 | 
					 | 
				
			||||||
    2dup 255 band @8 shr swap 1 + swap
 | 
					 | 
				
			||||||
    2dup 255 band @8 shr swap 2drop
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -3,3 +3,4 @@ include "io.mcl"
 | 
				
			||||||
include "util.mcl"
 | 
					include "util.mcl"
 | 
				
			||||||
include "int.mcl"
 | 
					include "int.mcl"
 | 
				
			||||||
include "fs.mcl"
 | 
					include "fs.mcl"
 | 
				
			||||||
 | 
					include "compat.mcl"
 | 
				
			||||||
| 
						 | 
					@ -5,11 +5,11 @@
 | 
				
			||||||
// @arg str_len: Int
 | 
					// @arg str_len: Int
 | 
				
			||||||
// @arg str_ptr: Ptr
 | 
					// @arg str_ptr: Ptr
 | 
				
			||||||
// @ret NULL/NEVER
 | 
					// @ret NULL/NEVER
 | 
				
			||||||
macro assert
 | 
					fn assert with bool int ptr returns void then
 | 
				
			||||||
    rot
 | 
					    rot
 | 
				
			||||||
    if else
 | 
					    if else
 | 
				
			||||||
    "Assert failed: \"" eputs eputs
 | 
					    "Assert failed: \"" eputs eputs
 | 
				
			||||||
    "\". Exiting!\n" eputs
 | 
					    "\". Exiting!\n" eputs
 | 
				
			||||||
    1 exit
 | 
					    1 exit
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
end
 | 
					done
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,15 @@
 | 
				
			||||||
use std::{fs, path::PathBuf, io::{Write, BufWriter}};
 | 
					use std::{fs, path::PathBuf, io::{Write, BufWriter}, collections::HashMap};
 | 
				
			||||||
use crate::{constants::{Operator, OpType, KeywordType}, Args};
 | 
					use crate::{constants::{Operator, OpType, KeywordType}, Args};
 | 
				
			||||||
use color_eyre::Result;
 | 
					use color_eyre::Result;
 | 
				
			||||||
use crate::compile::commands::linux_x86_64_compile_and_link;
 | 
					use crate::compile::commands::linux_x86_64_compile_and_link;
 | 
				
			||||||
use crate::constants::InstructionType;
 | 
					use crate::constants::InstructionType;
 | 
				
			||||||
use super::commands::linux_x86_64_run;
 | 
					use super::{commands::linux_x86_64_run, Constant, Memory, Function};
 | 
				
			||||||
 | 
					use eyre::eyre;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
					pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
 | 
					    let debug = args.get_opt_level()? < 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut of_c = PathBuf::from(&args.out_file);
 | 
					    let mut of_c = PathBuf::from(&args.out_file);
 | 
				
			||||||
    let (mut of_o, mut of_a) = if args.out_file == *crate::DEFAULT_OUT_FILE {
 | 
					    let (mut of_o, mut of_a) = if args.out_file == *crate::DEFAULT_OUT_FILE {
 | 
				
			||||||
        let of_o = PathBuf::from("/tmp/mclang_comp.o");
 | 
					        let of_o = PathBuf::from("/tmp/mclang_comp.o");
 | 
				
			||||||
| 
						 | 
					@ -23,17 +26,18 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
    of_a.set_extension("nasm");
 | 
					    of_a.set_extension("nasm");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    let file = fs::File::create(&of_a)?;
 | 
					    let file = fs::File::create(&of_a)?;
 | 
				
			||||||
    let mut writer = BufWriter::new(&file);
 | 
					    let mut writer = BufWriter::new(&file);
 | 
				
			||||||
    let mut memories:  Vec<(usize, usize)> = Vec::new();
 | 
					    let mut memories:  Vec<Memory> = Vec::new();
 | 
				
			||||||
 | 
					    let mut constants:  HashMap<String, Constant> = HashMap::new();
 | 
				
			||||||
 | 
					    let mut functions: Vec<Function> = Vec::new();
 | 
				
			||||||
    // println!("{}", tokens.len());
 | 
					    // println!("{}", tokens.len());
 | 
				
			||||||
    let mut strings: Vec<String> = Vec::new();
 | 
					    let mut strings: Vec<String> = Vec::new();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    writeln!(writer, "BITS 64")?;
 | 
					    writeln!(writer, "BITS 64")?;
 | 
				
			||||||
    writeln!(writer, "segment .text")?;
 | 
					    writeln!(writer, "segment .text")?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    writeln!(writer, "print:")?;
 | 
					    writeln!(writer, "_dbg_print:")?;
 | 
				
			||||||
    writeln!(writer, "    mov     r9, -3689348814741910323")?;
 | 
					    writeln!(writer, "    mov     r9, -3689348814741910323")?;
 | 
				
			||||||
    writeln!(writer, "    sub     rsp, 40")?;
 | 
					    writeln!(writer, "    sub     rsp, 40")?;
 | 
				
			||||||
    writeln!(writer, "    mov     BYTE [rsp+31], 10")?;
 | 
					    writeln!(writer, "    mov     BYTE [rsp+31], 10")?;
 | 
				
			||||||
| 
						 | 
					@ -69,45 +73,75 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    writeln!(writer, "global _start")?;
 | 
					    writeln!(writer, "global _start")?;
 | 
				
			||||||
    writeln!(writer, "_start:")?; 
 | 
					    writeln!(writer, "_start:")?; 
 | 
				
			||||||
 | 
					    writeln!(writer, "    lea rbp, [rel ret_stack]")?;
 | 
				
			||||||
 | 
					    writeln!(writer, "    call main")?;
 | 
				
			||||||
 | 
					    writeln!(writer, "    jmp end")?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut ti = 0;
 | 
					    let mut ti = 0;
 | 
				
			||||||
    while ti < tokens.len() {
 | 
					    while ti < tokens.len() {
 | 
				
			||||||
        let token = &tokens[ti];
 | 
					        let token = &tokens[ti];
 | 
				
			||||||
 | 
					        // println!("{:?}", token);
 | 
				
			||||||
 | 
					        if debug {
 | 
				
			||||||
            writeln!(writer, "addr_{ti}:")?;
 | 
					            writeln!(writer, "addr_{ti}:")?;
 | 
				
			||||||
 | 
					            if token.typ == OpType::Instruction(InstructionType::PushInt) {
 | 
				
			||||||
 | 
					                writeln!(writer, "    ;; -- {:?} {}", token.typ, token.value)?;
 | 
				
			||||||
 | 
					            } else if token.typ == OpType::Instruction(InstructionType::PushStr) {
 | 
				
			||||||
 | 
					                writeln!(writer, "    ;; -- {:?} {}", token.typ, token.text.escape_debug())?;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                writeln!(writer, "    ;; -- {:?}", token.typ)?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ti != 0 && tokens[ti-1].typ == OpType::Keyword(KeywordType::Else) ||
 | 
				
			||||||
 | 
					                tokens[ti-1].typ == OpType::Keyword(KeywordType::End){
 | 
				
			||||||
 | 
					                writeln!(writer, "addr_{ti}:")?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ti + 1 < tokens.len() && tokens[ti+1].typ == OpType::Keyword(KeywordType::End) {
 | 
				
			||||||
 | 
					                writeln!(writer, "addr_{ti}:")?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if let OpType::Keyword(keyword) = &token.typ {
 | 
				
			||||||
 | 
					                match keyword {
 | 
				
			||||||
 | 
					                    &KeywordType::End |
 | 
				
			||||||
 | 
					                    &KeywordType::While => {
 | 
				
			||||||
 | 
					                        writeln!(writer, "addr_{ti}:")?;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    _ => ()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        match token.typ.clone() {
 | 
					        match token.typ.clone() {
 | 
				
			||||||
            // stack
 | 
					            // stack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            OpType::Instruction(instruction) => {
 | 
					            OpType::Instruction(instruction) => {
 | 
				
			||||||
                match instruction {
 | 
					                match instruction {
 | 
				
			||||||
                    InstructionType::PushInt => {
 | 
					                    InstructionType::PushInt => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- push int {}", token.value)?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    mov rax, {}", token.value)?;
 | 
					                        writeln!(writer, "    mov rax, {}", token.value)?;
 | 
				
			||||||
                        writeln!(writer, "    push rax")?;
 | 
					                        writeln!(writer, "    push rax")?;
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::PushStr => {
 | 
					                    InstructionType::PushStr => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- push str \"{}\"", token.text.escape_default())?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    mov rax, {}", token.text.len())?;
 | 
					                        writeln!(writer, "    mov rax, {}", token.text.len())?;
 | 
				
			||||||
                        writeln!(writer, "    push rax")?;
 | 
					                        writeln!(writer, "    push rax")?;
 | 
				
			||||||
                        writeln!(writer, "    push str_{}", strings.len())?;
 | 
					                        writeln!(writer, "    mov rax, str_{}", strings.len())?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    push rax")?;
 | 
				
			||||||
                        strings.push(token.text.clone());
 | 
					                        strings.push(token.text.clone());
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    InstructionType::Drop => {
 | 
					                    InstructionType::Drop => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- drop")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Print => {
 | 
					                    InstructionType::Print => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- print")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rdi")?;
 | 
					                        writeln!(writer, "    pop rdi")?;
 | 
				
			||||||
                        writeln!(writer, "    call print")?;
 | 
					                        writeln!(writer, "    call _dbg_print")?;
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    InstructionType::Dup => {
 | 
					                    InstructionType::Dup => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- dup")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    push rax")?;
 | 
					                        writeln!(writer, "    push rax")?;
 | 
				
			||||||
                        writeln!(writer, "    push rax")?;
 | 
					                        writeln!(writer, "    push rax")?;
 | 
				
			||||||
| 
						 | 
					@ -116,7 +150,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    InstructionType::Rot => {
 | 
					                    InstructionType::Rot => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- rot")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rcx")?;
 | 
					                        writeln!(writer, "    pop rcx")?;
 | 
				
			||||||
| 
						 | 
					@ -127,7 +160,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Swap => {
 | 
					                    InstructionType::Swap => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- swap")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    push rax")?;
 | 
					                        writeln!(writer, "    push rax")?;
 | 
				
			||||||
| 
						 | 
					@ -136,7 +168,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Over => {
 | 
					                    InstructionType::Over => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- over")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    push rbx")?;
 | 
					                        writeln!(writer, "    push rbx")?;
 | 
				
			||||||
| 
						 | 
					@ -145,33 +176,51 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
                    //mem
 | 
					 | 
				
			||||||
                    InstructionType::Mem => {
 | 
					 | 
				
			||||||
                        writeln!(writer, "    ;; -- mem")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    push mem")?;
 | 
					 | 
				
			||||||
                        ti += 1;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    InstructionType::Load8 => {
 | 
					                    InstructionType::Load8 => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- load")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    xor rbx, rbx")?;
 | 
					                        writeln!(writer, "    xor rbx, rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    mov bl, [rax]")?;
 | 
					                        writeln!(writer, "    mov bl, byte [rax]")?;
 | 
				
			||||||
                        writeln!(writer, "    push rbx")?;
 | 
					                        writeln!(writer, "    push rbx")?;
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    InstructionType::Store8 => {
 | 
					                    InstructionType::Store8 => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- store")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    mov [rax], bl")?;
 | 
					                        writeln!(writer, "    mov byte [rax], bl")?;
 | 
				
			||||||
 | 
					                        ti += 1;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    InstructionType::Load32 => {
 | 
				
			||||||
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    xor rbx, rbx")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    mov bl, dword [rax]")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    push rbx")?;
 | 
				
			||||||
 | 
					                        ti += 1;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					                    InstructionType::Store32 => {
 | 
				
			||||||
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    mov dword[rax], bl")?;
 | 
				
			||||||
 | 
					                        ti += 1;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    InstructionType::Load64 => {
 | 
				
			||||||
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    xor rbx, rbx")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    mov bl, qword [rax]")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    push rbx")?;
 | 
				
			||||||
 | 
					                        ti += 1;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					                    InstructionType::Store64 => {
 | 
				
			||||||
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    mov qword [rax], bl")?;
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    // math
 | 
					                    // math
 | 
				
			||||||
                    InstructionType::Plus => {
 | 
					                    InstructionType::Plus => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- plus")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    add rax, rbx")?;
 | 
					                        writeln!(writer, "    add rax, rbx")?;
 | 
				
			||||||
| 
						 | 
					@ -179,7 +228,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Minus => {
 | 
					                    InstructionType::Minus => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- minus")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    sub rbx, rax")?;
 | 
					                        writeln!(writer, "    sub rbx, rax")?;
 | 
				
			||||||
| 
						 | 
					@ -187,7 +235,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Equals => {
 | 
					                    InstructionType::Equals => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- equals")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    mov rcx, 0")?;
 | 
					                        writeln!(writer, "    mov rcx, 0")?;
 | 
				
			||||||
                        writeln!(writer, "    mov rdx, 1")?;
 | 
					                        writeln!(writer, "    mov rdx, 1")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
| 
						 | 
					@ -198,7 +245,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Lt => {
 | 
					                    InstructionType::Lt => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- lt")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    mov rcx, 0")?;
 | 
					                        writeln!(writer, "    mov rcx, 0")?;
 | 
				
			||||||
                        writeln!(writer, "    mov rdx, 1")?;
 | 
					                        writeln!(writer, "    mov rdx, 1")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
| 
						 | 
					@ -209,7 +255,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Gt => {
 | 
					                    InstructionType::Gt => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- gt")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    mov rcx, 0")?;
 | 
					                        writeln!(writer, "    mov rcx, 0")?;
 | 
				
			||||||
                        writeln!(writer, "    mov rdx, 1")?;
 | 
					                        writeln!(writer, "    mov rdx, 1")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
| 
						 | 
					@ -220,7 +265,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::NotEquals => {
 | 
					                    InstructionType::NotEquals => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- not equals")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    mov rcx, 1")?;
 | 
					                        writeln!(writer, "    mov rcx, 1")?;
 | 
				
			||||||
                        writeln!(writer, "    mov rdx, 0")?;
 | 
					                        writeln!(writer, "    mov rdx, 0")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
| 
						 | 
					@ -231,7 +275,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Le => {
 | 
					                    InstructionType::Le => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- lt")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    mov rcx, 0")?;
 | 
					                        writeln!(writer, "    mov rcx, 0")?;
 | 
				
			||||||
                        writeln!(writer, "    mov rdx, 1")?;
 | 
					                        writeln!(writer, "    mov rdx, 1")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
| 
						 | 
					@ -242,7 +285,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Ge => {
 | 
					                    InstructionType::Ge => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- gt")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    mov rcx, 0")?;
 | 
					                        writeln!(writer, "    mov rcx, 0")?;
 | 
				
			||||||
                        writeln!(writer, "    mov rdx, 1")?;
 | 
					                        writeln!(writer, "    mov rdx, 1")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
| 
						 | 
					@ -253,7 +295,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Band => {
 | 
					                    InstructionType::Band => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- band")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    and rbx, rax")?;
 | 
					                        writeln!(writer, "    and rbx, rax")?;
 | 
				
			||||||
| 
						 | 
					@ -261,7 +302,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Bor => {
 | 
					                    InstructionType::Bor => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- bor")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    or rbx, rax")?;
 | 
					                        writeln!(writer, "    or rbx, rax")?;
 | 
				
			||||||
| 
						 | 
					@ -269,7 +309,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Shr => {
 | 
					                    InstructionType::Shr => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- shr")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rcx")?;
 | 
					                        writeln!(writer, "    pop rcx")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    shr rbx, cl")?;
 | 
					                        writeln!(writer, "    shr rbx, cl")?;
 | 
				
			||||||
| 
						 | 
					@ -277,7 +316,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Shl => {
 | 
					                    InstructionType::Shl => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- shl")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rcx")?;
 | 
					                        writeln!(writer, "    pop rcx")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    shl rbx, cl")?;
 | 
					                        writeln!(writer, "    shl rbx, cl")?;
 | 
				
			||||||
| 
						 | 
					@ -285,7 +323,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::DivMod => {
 | 
					                    InstructionType::DivMod => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- div")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    xor rdx, rdx")?;
 | 
					                        writeln!(writer, "    xor rdx, rdx")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
| 
						 | 
					@ -295,7 +332,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Mul => {
 | 
					                    InstructionType::Mul => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- mul")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rbx")?;
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
                        writeln!(writer, "    mul rbx")?;
 | 
					                        writeln!(writer, "    mul rbx")?;
 | 
				
			||||||
| 
						 | 
					@ -303,14 +339,12 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Syscall0 => {
 | 
					                    InstructionType::Syscall0 => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- syscall0")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    syscall")?;
 | 
					                        writeln!(writer, "    syscall")?;
 | 
				
			||||||
                        writeln!(writer, "    push rax")?;
 | 
					                        writeln!(writer, "    push rax")?;
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Syscall1 => {
 | 
					                    InstructionType::Syscall1 => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- syscall1")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rdi")?;
 | 
					                        writeln!(writer, "    pop rdi")?;
 | 
				
			||||||
                        writeln!(writer, "    syscall")?;
 | 
					                        writeln!(writer, "    syscall")?;
 | 
				
			||||||
| 
						 | 
					@ -318,7 +352,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Syscall2 => {
 | 
					                    InstructionType::Syscall2 => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- syscall2")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rdi")?;
 | 
					                        writeln!(writer, "    pop rdi")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rsi")?;
 | 
					                        writeln!(writer, "    pop rsi")?;
 | 
				
			||||||
| 
						 | 
					@ -327,7 +360,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Syscall3 => {
 | 
					                    InstructionType::Syscall3 => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- syscall3")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rdi")?;
 | 
					                        writeln!(writer, "    pop rdi")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rsi")?;
 | 
					                        writeln!(writer, "    pop rsi")?;
 | 
				
			||||||
| 
						 | 
					@ -338,7 +370,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Syscall4 => {
 | 
					                    InstructionType::Syscall4 => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- syscall4")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rdi")?;
 | 
					                        writeln!(writer, "    pop rdi")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rsi")?;
 | 
					                        writeln!(writer, "    pop rsi")?;
 | 
				
			||||||
| 
						 | 
					@ -349,7 +380,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Syscall5 => {
 | 
					                    InstructionType::Syscall5 => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- syscall5")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rdi")?;
 | 
					                        writeln!(writer, "    pop rdi")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rsi")?;
 | 
					                        writeln!(writer, "    pop rsi")?;
 | 
				
			||||||
| 
						 | 
					@ -361,7 +391,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Syscall6 => {
 | 
					                    InstructionType::Syscall6 => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- syscall6")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rdi")?;
 | 
					                        writeln!(writer, "    pop rdi")?;
 | 
				
			||||||
                        writeln!(writer, "    pop rsi")?;
 | 
					                        writeln!(writer, "    pop rsi")?;
 | 
				
			||||||
| 
						 | 
					@ -374,14 +403,48 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::MemUse => {
 | 
					                    InstructionType::MemUse => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- MemUse")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    push mem_{}", token.addr.unwrap())?;
 | 
					                        writeln!(writer, "    push mem_{}", token.addr.unwrap())?;
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::None => unreachable!(),
 | 
					                    InstructionType::None => {
 | 
				
			||||||
                    InstructionType::CastBool => ti += 1,
 | 
					                        println!("{token:?}");
 | 
				
			||||||
                    InstructionType::CastPtr => ti += 1,
 | 
					                        unreachable!()
 | 
				
			||||||
                    InstructionType::CastInt => ti += 1,
 | 
					                    },
 | 
				
			||||||
 | 
					                    InstructionType::FnCall => {
 | 
				
			||||||
 | 
					                        writeln!(writer, "    call {}", token.text)?;
 | 
				
			||||||
 | 
					                        ti += 1;
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    InstructionType::Return => {
 | 
				
			||||||
 | 
					                        writeln!(writer, "    sub rbp, 8")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    mov rbx, qword [rbp]")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    push rbx")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    ret")?;
 | 
				
			||||||
 | 
					                        ti += 1;
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    InstructionType::CastBool |
 | 
				
			||||||
 | 
					                    InstructionType::CastPtr |
 | 
				
			||||||
 | 
					                    InstructionType::CastInt |
 | 
				
			||||||
 | 
					                    InstructionType::CastVoid |
 | 
				
			||||||
 | 
					                    InstructionType::TypeBool |
 | 
				
			||||||
 | 
					                    InstructionType::TypePtr |
 | 
				
			||||||
 | 
					                    InstructionType::TypeInt |
 | 
				
			||||||
 | 
					                    InstructionType::TypeVoid |
 | 
				
			||||||
 | 
					                    InstructionType::TypeStr |
 | 
				
			||||||
 | 
					                    InstructionType::TypeAny |
 | 
				
			||||||
 | 
					                    InstructionType::Returns |
 | 
				
			||||||
 | 
					                    InstructionType::With => {
 | 
				
			||||||
 | 
					                        ti += 1;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    InstructionType::ConstUse => {
 | 
				
			||||||
 | 
					                        writeln!(writer, "    mov rax, qword [const_{}]", token.text)?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    push rax")?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        let mut c = constants.get(&token.text).unwrap().clone();
 | 
				
			||||||
 | 
					                        c.used = true;
 | 
				
			||||||
 | 
					                        constants.remove(&token.text);
 | 
				
			||||||
 | 
					                        constants.insert(token.text.clone(), c);
 | 
				
			||||||
 | 
					                        ti += 1;
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -390,48 +453,69 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
                match keyword {
 | 
					                match keyword {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // block
 | 
					                    // block
 | 
				
			||||||
                    KeywordType::If => {
 | 
					                    KeywordType::If |
 | 
				
			||||||
                        writeln!(writer, "    ;; -- if")?;
 | 
					                    KeywordType::Do => {
 | 
				
			||||||
                        writeln!(writer, "    pop rax")?;
 | 
					                        writeln!(writer, "    pop rax")?;
 | 
				
			||||||
                        writeln!(writer, "    test rax, rax")?;
 | 
					                        writeln!(writer, "    test rax, rax")?;
 | 
				
			||||||
                        writeln!(writer, "    jz addr_{}", token.jmp)?;
 | 
					                        writeln!(writer, "    jz addr_{}", token.jmp)?;
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    }
 | 
				
			||||||
                    KeywordType::Else => {
 | 
					                    KeywordType::Else => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- else")?;
 | 
					 | 
				
			||||||
                        writeln!(writer, "    jmp addr_{}", token.jmp)?;
 | 
					                        writeln!(writer, "    jmp addr_{}", token.jmp)?;
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    KeywordType::While => {
 | 
					                    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;
 | 
					                        ti += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    KeywordType::End => {
 | 
					                    KeywordType::End => {
 | 
				
			||||||
                        writeln!(writer, "    ;; -- end")?;
 | 
					 | 
				
			||||||
                        if ti + 1 != token.jmp {
 | 
					                        if ti + 1 != token.jmp {
 | 
				
			||||||
                            writeln!(writer, "    jmp addr_{}", token.jmp)?;
 | 
					                            // writeln!(writer, "    jmp addr_{}", token.jmp)?;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    KeywordType::Memory => {
 | 
					                    KeywordType::Memory => {
 | 
				
			||||||
                        memories.push((token.addr.unwrap(), token.value));
 | 
					                        memories.push(Memory { size: token.value, loc: token.loc.clone(), id: token.addr.unwrap() });
 | 
				
			||||||
                        ti += 1;
 | 
					                        ti += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    KeywordType::Macro |
 | 
					                    KeywordType::ConstantDef => {
 | 
				
			||||||
                    KeywordType::Include
 | 
					                        // TODO: after we add c style strings add supoort for them in constants
 | 
				
			||||||
                        => unreachable!()
 | 
					                        let a = args.get_opt_level()? < 1;
 | 
				
			||||||
 | 
					                        let c = Constant{
 | 
				
			||||||
 | 
					                            loc: token.loc.clone(),
 | 
				
			||||||
 | 
					                            name: token.text.clone(),
 | 
				
			||||||
 | 
					                            value_i: Some(token.value),
 | 
				
			||||||
 | 
					                            value_s: None,
 | 
				
			||||||
 | 
					                            used: a,
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        constants.insert(token.text.clone(), c);
 | 
				
			||||||
 | 
					                        ti += 1;
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    KeywordType::FunctionDef => {
 | 
				
			||||||
 | 
					                        writeln!(writer, "{}:", token.text)?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    pop rbx")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    mov qword [rbp], rbx")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    add rbp, 8")?;
 | 
				
			||||||
 | 
					                        functions.push(Function { loc: token.loc.clone(), name: token.text.clone() });
 | 
				
			||||||
 | 
					                        ti += 1;
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    KeywordType::FunctionDone => {
 | 
				
			||||||
 | 
					                        writeln!(writer, "    sub rbp, 8")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    mov rbx, qword [rbp]")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    push rbx")?;
 | 
				
			||||||
 | 
					                        writeln!(writer, "    ret")?;
 | 
				
			||||||
 | 
					                        ti += 1;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    KeywordType::FunctionThen => ti += 1,
 | 
				
			||||||
 | 
					                    KeywordType::Function |
 | 
				
			||||||
 | 
					                    KeywordType::Include |
 | 
				
			||||||
 | 
					                    KeywordType::Constant => unreachable!(),
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    writeln!(writer, "addr_{ti}:")?;
 | 
					    writeln!(writer, "addr_{ti}:")?;
 | 
				
			||||||
 | 
					    writeln!(writer, "end:")?;
 | 
				
			||||||
    writeln!(writer, "    mov rax, 60")?;
 | 
					    writeln!(writer, "    mov rax, 60")?;
 | 
				
			||||||
    writeln!(writer, "    mov rdi, 0")?;
 | 
					    writeln!(writer, "    mov rdi, 0")?;
 | 
				
			||||||
    writeln!(writer, "    syscall")?;
 | 
					    writeln!(writer, "    syscall")?;
 | 
				
			||||||
| 
						 | 
					@ -442,18 +526,65 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result<i32>{
 | 
				
			||||||
        writeln!(writer, "    str_{}: db {} ; {}", i, s_list, s.escape_default())?;
 | 
					        writeln!(writer, "    str_{}: db {} ; {}", i, s_list, s.escape_default())?;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    writeln!(writer, "segment .bss")?;
 | 
					    for (_, c) in constants {
 | 
				
			||||||
    for (_, s) in memories.iter().enumerate() {
 | 
					        if !c.used {
 | 
				
			||||||
        writeln!(writer, "    mem_{}: resb {}", s.0, s.1)?;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    writeln!(writer, "    mem: resb {}", crate::compile::MEM_SZ)?;
 | 
					
 | 
				
			||||||
 | 
					        if let Some(v) = &c.value_i {
 | 
				
			||||||
 | 
					            writeln!(writer, "    const_{}: dq {}", c.name, v)?;
 | 
				
			||||||
 | 
					        } else if let Some(_v) = &c.value_s {
 | 
				
			||||||
 | 
					            todo!();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            unreachable!();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    writeln!(writer, "segment .bss")?;
 | 
				
			||||||
 | 
					    for s in memories {
 | 
				
			||||||
 | 
					        writeln!(writer, "    mem_{}: resb {}", s.id, s.size)?;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    writeln!(writer, "    ret_stack: resq 256")?;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // for t in tokens {
 | 
				
			||||||
 | 
					    //     println!("{t:?}");
 | 
				
			||||||
 | 
					    // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    writer.flush()?;
 | 
					    writer.flush()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    pre_compile_steps(
 | 
				
			||||||
 | 
					        String::from_utf8_lossy(writer.buffer()).to_string().as_str(),
 | 
				
			||||||
 | 
					        functions
 | 
				
			||||||
 | 
					    )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    linux_x86_64_compile_and_link(&of_a, &of_o, &of_c, args.quiet)?;
 | 
					    linux_x86_64_compile_and_link(&of_a, &of_o, &of_c, args.quiet)?;
 | 
				
			||||||
    if args.run {
 | 
					    if args.run {
 | 
				
			||||||
        let c = linux_x86_64_run(&of_c, &[], args.quiet)?;
 | 
					        let c = linux_x86_64_run(&of_c, &[], args.quiet)?;
 | 
				
			||||||
        return Ok(c);
 | 
					        return Ok(c);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(0)
 | 
					    Ok(0)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn pre_compile_steps(_code: &str, functions: Vec<Function>) -> Result<()> {
 | 
				
			||||||
 | 
					    let mut has_main = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for func in functions {
 | 
				
			||||||
 | 
					        if func.name == "main" {
 | 
				
			||||||
 | 
					            has_main = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if !has_main {
 | 
				
			||||||
 | 
					        crate::errors::missing_main_fn();
 | 
				
			||||||
 | 
					        return Err(eyre!(""));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,27 @@
 | 
				
			||||||
 | 
					use crate::constants::Loc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod linux_x86_64;
 | 
					pub mod linux_x86_64;
 | 
				
			||||||
pub mod commands;
 | 
					pub mod commands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const MEM_SZ: usize = 640 * 1000; // 4kb
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
pub const STRING_SZ: usize = 640 * 1000; // 4kb
 | 
					pub struct Constant {
 | 
				
			||||||
 | 
					    pub loc: Loc,
 | 
				
			||||||
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    pub value_i: Option<usize>,
 | 
				
			||||||
 | 
					    pub value_s: Option<String>,
 | 
				
			||||||
 | 
					    pub used: bool
 | 
				
			||||||
 | 
					    // extern: bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Memory {
 | 
				
			||||||
 | 
					    pub size: usize,
 | 
				
			||||||
 | 
					    pub loc: Loc,
 | 
				
			||||||
 | 
					    pub id: usize
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Function {
 | 
				
			||||||
 | 
					    pub loc: Loc,
 | 
				
			||||||
 | 
					    pub name: String
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/config.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/config.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Prints out extra information
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					pub const DEV_MODE: bool = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const DEFAULT_OUT_FILE: &str = "a.out";
 | 
				
			||||||
 | 
					pub const DEFAULT_INCLUDES: [&str;1] = [
 | 
				
			||||||
 | 
					    "./include",
 | 
				
			||||||
 | 
					    // "~/.mclang/include",
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Interpreting configs
 | 
				
			||||||
 | 
					 * `MEM_SZ` is the buffer size for memory
 | 
				
			||||||
 | 
					 * `STRING_SZ` is the buffer size for strings
 | 
				
			||||||
 | 
					 * if you have buffer overflow consider increasing these
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					pub const MEM_SZ: usize = 640 * 1000; // 4kb
 | 
				
			||||||
 | 
					pub const STRING_SZ: usize = 640 * 1000; // 4kb
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,4 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const ALLOW_MACRO_REDEFINITION: bool = true;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Clone, PartialEq)]
 | 
				
			||||||
| 
						 | 
					@ -33,9 +32,12 @@ pub enum InstructionType {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // mem
 | 
					    // mem
 | 
				
			||||||
    Mem,
 | 
					 | 
				
			||||||
    Load8,
 | 
					    Load8,
 | 
				
			||||||
    Store8,
 | 
					    Store8,
 | 
				
			||||||
 | 
					    Load32,
 | 
				
			||||||
 | 
					    Store32,
 | 
				
			||||||
 | 
					    Load64,
 | 
				
			||||||
 | 
					    Store64,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // syscalls
 | 
					    // syscalls
 | 
				
			||||||
    Syscall0,
 | 
					    Syscall0,
 | 
				
			||||||
| 
						 | 
					@ -49,21 +51,41 @@ pub enum InstructionType {
 | 
				
			||||||
    CastBool,
 | 
					    CastBool,
 | 
				
			||||||
    CastPtr,
 | 
					    CastPtr,
 | 
				
			||||||
    CastInt,
 | 
					    CastInt,
 | 
				
			||||||
 | 
					    CastVoid,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // typing
 | 
				
			||||||
 | 
					    TypeBool,
 | 
				
			||||||
 | 
					    TypePtr,
 | 
				
			||||||
 | 
					    TypeInt,
 | 
				
			||||||
 | 
					    TypeVoid,
 | 
				
			||||||
 | 
					    TypeStr,
 | 
				
			||||||
 | 
					    TypeAny,
 | 
				
			||||||
 | 
					    Returns,
 | 
				
			||||||
 | 
					    With,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FnCall,
 | 
				
			||||||
    MemUse,
 | 
					    MemUse,
 | 
				
			||||||
 | 
					    ConstUse,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Return,
 | 
				
			||||||
    None // Used for macros and any other non built in word definitions
 | 
					    None // Used for macros and any other non built in word definitions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Clone, Copy, PartialEq)]
 | 
				
			||||||
pub enum KeywordType {
 | 
					pub enum KeywordType {
 | 
				
			||||||
    If,
 | 
					    If,
 | 
				
			||||||
    Else,
 | 
					    Else,
 | 
				
			||||||
    End,
 | 
					    End,
 | 
				
			||||||
    While,
 | 
					    While,
 | 
				
			||||||
    Do,
 | 
					    Do,
 | 
				
			||||||
    Macro,
 | 
					 | 
				
			||||||
    Include,
 | 
					    Include,
 | 
				
			||||||
    Memory
 | 
					    Memory,
 | 
				
			||||||
 | 
					    Constant,
 | 
				
			||||||
 | 
					    ConstantDef,
 | 
				
			||||||
 | 
					    Function,
 | 
				
			||||||
 | 
					    FunctionDef,
 | 
				
			||||||
 | 
					    FunctionThen,
 | 
				
			||||||
 | 
					    FunctionDone
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq)]
 | 
					#[derive(Debug, Clone, PartialEq)]
 | 
				
			||||||
| 
						 | 
					@ -75,6 +97,7 @@ pub enum OpType {
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
pub struct Operator{
 | 
					pub struct Operator{
 | 
				
			||||||
    pub typ: OpType,
 | 
					    pub typ: OpType,
 | 
				
			||||||
 | 
					    pub tok_typ: TokenType,
 | 
				
			||||||
    pub value: usize,
 | 
					    pub value: usize,
 | 
				
			||||||
    pub text: String, //? only used for OpType::PushStr
 | 
					    pub text: String, //? only used for OpType::PushStr
 | 
				
			||||||
    pub addr: Option<usize>, //? only used for OpType::PushStr
 | 
					    pub addr: Option<usize>, //? only used for OpType::PushStr
 | 
				
			||||||
| 
						 | 
					@ -83,14 +106,15 @@ pub struct Operator{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Operator {
 | 
					impl Operator {
 | 
				
			||||||
    pub fn new(typ: OpType, value: usize, text: String, file: String, row: usize, col: usize) -> Self {
 | 
					    pub fn new(typ: OpType, tok_typ: TokenType, value: usize, text: String, file: String, row: usize, col: usize) -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            typ,
 | 
					            typ,
 | 
				
			||||||
            value,
 | 
					            value,
 | 
				
			||||||
            jmp: 0,
 | 
					            jmp: 0,
 | 
				
			||||||
            addr: None,
 | 
					            addr: None,
 | 
				
			||||||
            text,
 | 
					            text,
 | 
				
			||||||
            loc: (file, row, col)
 | 
					            loc: (file, row, col),
 | 
				
			||||||
 | 
					            tok_typ,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    pub fn set_addr(mut self, addr: usize) -> Self {
 | 
					    pub fn set_addr(mut self, addr: usize) -> Self {
 | 
				
			||||||
| 
						 | 
					@ -108,7 +132,7 @@ impl OpType {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    InstructionType::PushInt => "Number",
 | 
					                    InstructionType::PushInt => "Number",
 | 
				
			||||||
                    InstructionType::PushStr => "String",
 | 
					                    InstructionType::PushStr => "String",
 | 
				
			||||||
                    InstructionType::Print => "print",
 | 
					                    InstructionType::Print => "_dbg_print",
 | 
				
			||||||
                    InstructionType::Dup => "dup",
 | 
					                    InstructionType::Dup => "dup",
 | 
				
			||||||
                    InstructionType::Drop => "drop",
 | 
					                    InstructionType::Drop => "drop",
 | 
				
			||||||
                    InstructionType::Rot => "rot",
 | 
					                    InstructionType::Rot => "rot",
 | 
				
			||||||
| 
						 | 
					@ -128,9 +152,12 @@ impl OpType {
 | 
				
			||||||
                    InstructionType::Shl => "shl",
 | 
					                    InstructionType::Shl => "shl",
 | 
				
			||||||
                    InstructionType::DivMod => "divmod",
 | 
					                    InstructionType::DivMod => "divmod",
 | 
				
			||||||
                    InstructionType::Mul => "*",
 | 
					                    InstructionType::Mul => "*",
 | 
				
			||||||
                    InstructionType::Mem => "mem",
 | 
					                    InstructionType::Load8 => "load8",
 | 
				
			||||||
                    InstructionType::Load8 => "!8",
 | 
					                    InstructionType::Store8 => "store8",
 | 
				
			||||||
                    InstructionType::Store8 => "@8",
 | 
					                    InstructionType::Load32 => "load32",
 | 
				
			||||||
 | 
					                    InstructionType::Store32 => "store32",
 | 
				
			||||||
 | 
					                    InstructionType::Load64 => "load64",
 | 
				
			||||||
 | 
					                    InstructionType::Store64 => "store64",
 | 
				
			||||||
                    InstructionType::Syscall0 => "syscall0",
 | 
					                    InstructionType::Syscall0 => "syscall0",
 | 
				
			||||||
                    InstructionType::Syscall1 => "syscall1",
 | 
					                    InstructionType::Syscall1 => "syscall1",
 | 
				
			||||||
                    InstructionType::Syscall2 => "syscall2",
 | 
					                    InstructionType::Syscall2 => "syscall2",
 | 
				
			||||||
| 
						 | 
					@ -141,8 +168,20 @@ impl OpType {
 | 
				
			||||||
                    InstructionType::CastBool => "cast(bool",
 | 
					                    InstructionType::CastBool => "cast(bool",
 | 
				
			||||||
                    InstructionType::CastPtr => "cast(ptr)",
 | 
					                    InstructionType::CastPtr => "cast(ptr)",
 | 
				
			||||||
                    InstructionType::CastInt => "cast(int)",
 | 
					                    InstructionType::CastInt => "cast(int)",
 | 
				
			||||||
                    InstructionType::MemUse => "MemUse",
 | 
					                    InstructionType::CastVoid => "cast(void)",
 | 
				
			||||||
                    InstructionType::None => "None",
 | 
					                    InstructionType::None => "None",
 | 
				
			||||||
 | 
					                    InstructionType::MemUse => "Memory use (internal)",
 | 
				
			||||||
 | 
					                    InstructionType::FnCall => "Function Call (Internal)",
 | 
				
			||||||
 | 
					                    InstructionType::ConstUse => "Constant Use (Internal)",
 | 
				
			||||||
 | 
					                    InstructionType::Return => "return",
 | 
				
			||||||
 | 
					                    InstructionType::TypeBool => "bool",
 | 
				
			||||||
 | 
					                    InstructionType::TypePtr => "ptr",
 | 
				
			||||||
 | 
					                    InstructionType::TypeInt => "int",
 | 
				
			||||||
 | 
					                    InstructionType::TypeVoid => "void",
 | 
				
			||||||
 | 
					                    InstructionType::TypeStr => "str",
 | 
				
			||||||
 | 
					                    InstructionType::Returns => "returns",
 | 
				
			||||||
 | 
					                    InstructionType::With => "with",
 | 
				
			||||||
 | 
					                    InstructionType::TypeAny => "any",
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            OpType::Keyword(keyword) => {
 | 
					            OpType::Keyword(keyword) => {
 | 
				
			||||||
| 
						 | 
					@ -152,9 +191,14 @@ impl OpType {
 | 
				
			||||||
                    KeywordType::End => "end",
 | 
					                    KeywordType::End => "end",
 | 
				
			||||||
                    KeywordType::While => "while",
 | 
					                    KeywordType::While => "while",
 | 
				
			||||||
                    KeywordType::Do => "do",
 | 
					                    KeywordType::Do => "do",
 | 
				
			||||||
                    KeywordType::Macro => "macro",
 | 
					 | 
				
			||||||
                    KeywordType::Include => "include",
 | 
					                    KeywordType::Include => "include",
 | 
				
			||||||
                    KeywordType::Memory => "memory"
 | 
					                    KeywordType::Memory => "memory",
 | 
				
			||||||
 | 
					                    KeywordType::Function => "fn",
 | 
				
			||||||
 | 
					                    KeywordType::Constant => "const",
 | 
				
			||||||
 | 
					                    KeywordType::FunctionThen => "then",
 | 
				
			||||||
 | 
					                    KeywordType::FunctionDone => "done",
 | 
				
			||||||
 | 
					                    KeywordType::ConstantDef => "constant Definition (internal)",
 | 
				
			||||||
 | 
					                    KeywordType::FunctionDef => "function definition (internal)"
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
| 
						 | 
					@ -171,7 +215,7 @@ pub struct Token {
 | 
				
			||||||
    pub typ: TokenType,
 | 
					    pub typ: TokenType,
 | 
				
			||||||
    pub value: Option<usize>, //* only used for Memories
 | 
					    pub value: Option<usize>, //* only used for Memories
 | 
				
			||||||
    pub addr: Option<usize>, //* only used for Memories
 | 
					    pub addr: Option<usize>, //* only used for Memories
 | 
				
			||||||
    pub op_typ: InstructionType //* only used for Memories
 | 
					    pub op_typ: OpType //* only used for Memories
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq, Copy)]
 | 
					#[derive(Debug, Clone, PartialEq, Copy)]
 | 
				
			||||||
| 
						 | 
					@ -210,6 +254,8 @@ pub enum Types {
 | 
				
			||||||
    Bool,
 | 
					    Bool,
 | 
				
			||||||
    Ptr,
 | 
					    Ptr,
 | 
				
			||||||
    Int,
 | 
					    Int,
 | 
				
			||||||
 | 
					    Void,
 | 
				
			||||||
 | 
					    Str,
 | 
				
			||||||
    Any
 | 
					    Any
 | 
				
			||||||
    // U8,
 | 
					    // U8,
 | 
				
			||||||
    // U16,
 | 
					    // U16,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								src/errors/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/errors/mod.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					use crate::{error, help, code_block};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn missing_main_fn() {
 | 
				
			||||||
 | 
					    error!("Main function not found, please create one lol");
 | 
				
			||||||
 | 
					    help!("Heres a basic main function with code that prints hello world:\n{}", 
 | 
				
			||||||
 | 
					        code_block!(
 | 
				
			||||||
 | 
					            concat!(
 | 
				
			||||||
 | 
					                "include \"std.mcl\"\n",
 | 
				
			||||||
 | 
					                "\n",
 | 
				
			||||||
 | 
					                "fn main with void retuns void then\n",
 | 
				
			||||||
 | 
					                "    \"Hello world!\\n\" puts\n",
 | 
				
			||||||
 | 
					                "done\n"
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,11 @@
 | 
				
			||||||
use std::collections::HashMap;
 | 
					use std::collections::HashMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{constants::{OpType, Loc, InstructionType, KeywordType}, lerror, error};
 | 
					use crate::{constants::{OpType, Loc, InstructionType, KeywordType, Operator}, lerror, error};
 | 
				
			||||||
// use crate::util::logger;
 | 
					// use crate::util::logger;
 | 
				
			||||||
use color_eyre::Result;
 | 
					use color_eyre::Result;
 | 
				
			||||||
use eyre::eyre;
 | 
					use eyre::eyre;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use super::{Memory, Function, Constant};
 | 
				
			||||||
mod syscalls;
 | 
					mod syscalls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn stack_pop(stack: &mut Vec<usize>, pos: &Loc) -> Result<usize> {
 | 
					fn stack_pop(stack: &mut Vec<usize>, pos: &Loc) -> Result<usize> {
 | 
				
			||||||
| 
						 | 
					@ -13,56 +15,66 @@ fn stack_pop(stack: &mut Vec<usize>, pos: &Loc) -> Result<usize> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
 | 
					pub fn run(ops: &[crate::constants::Operator]) -> Result<i32>{
 | 
				
			||||||
    let mut stack: Vec<usize> = Vec::new();
 | 
					    let mut stack: Vec<usize> = Vec::new();
 | 
				
			||||||
    let mut ti = 0;
 | 
					    let mut mem: Vec<u64> = vec![0; crate::MEM_SZ + crate::STRING_SZ];
 | 
				
			||||||
    let mut mem: Vec<u8> = vec![0; crate::compile::MEM_SZ + crate::compile::STRING_SZ];
 | 
					 | 
				
			||||||
    let mut string_idx = 0;
 | 
					    let mut string_idx = 0;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    let mut memories: HashMap<usize, usize> = HashMap::new();
 | 
					    let prerunned = pre_run(ops);
 | 
				
			||||||
 | 
					    let functions = prerunned.functions;
 | 
				
			||||||
 | 
					    let constants = prerunned.constants;
 | 
				
			||||||
 | 
					    let memories = prerunned.memories;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut ret_stack: Vec<usize> = Vec::new();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    // for token in &tokens {
 | 
					    // for token in &tokens {
 | 
				
			||||||
    //     println!("{{typ: \"{:?}\", val: {}, jmp: {}}}", token.typ, token.value, token.jmp);
 | 
					    //     println!("{{typ: \"{:?}\", val: {}, jmp: {}}}", token.typ, token.value, token.jmp);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // }
 | 
					    // }
 | 
				
			||||||
    while ti < tokens.len() {
 | 
					        
 | 
				
			||||||
        let token = &tokens[ti];
 | 
					    // jump to main func    
 | 
				
			||||||
        let pos = token.loc.clone();
 | 
					    let mut ip = if let Some(i) = functions.get("main") {i.id} else {
 | 
				
			||||||
        // println!("{:?}", token.typ);
 | 
					        crate::errors::missing_main_fn();
 | 
				
			||||||
        match token.typ.clone() {
 | 
					        return Err(eyre!(""));
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    while ip < ops.len() {
 | 
				
			||||||
 | 
					        let op = &ops[ip];
 | 
				
			||||||
 | 
					        let pos = op.loc.clone();
 | 
				
			||||||
 | 
					        match op.typ.clone() {
 | 
				
			||||||
            OpType::Instruction(instruction) => {
 | 
					            OpType::Instruction(instruction) => {
 | 
				
			||||||
                match instruction {
 | 
					                match instruction {
 | 
				
			||||||
                    InstructionType::PushInt => {
 | 
					                    InstructionType::PushInt => {
 | 
				
			||||||
                        stack.push(token.value);
 | 
					                        stack.push(op.value);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::PushStr => {
 | 
					                    InstructionType::PushStr => {
 | 
				
			||||||
                        if  token.addr.is_none() {
 | 
					                        if  op.addr.is_none() {
 | 
				
			||||||
                            stack.push(token.text.len()); // string len
 | 
					                            stack.push(op.text.len()); // string len
 | 
				
			||||||
                            stack.push(string_idx + crate::compile::MEM_SZ);
 | 
					                            stack.push(string_idx + crate::MEM_SZ);
 | 
				
			||||||
                            
 | 
					                            
 | 
				
			||||||
                            for c in token.text.bytes() {
 | 
					                            for c in op.text.bytes() {
 | 
				
			||||||
                                mem[crate::compile::MEM_SZ + string_idx] = c;
 | 
					                                mem[crate::MEM_SZ + string_idx] = u64::from(c);
 | 
				
			||||||
                                string_idx += 1;
 | 
					                                string_idx += 1;
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            stack.push(token.text.len()); 
 | 
					                            stack.push(op.text.len()); 
 | 
				
			||||||
                            if let Some(addr) = token.addr {
 | 
					                            if let Some(addr) = op.addr {
 | 
				
			||||||
                                stack.push(addr);
 | 
					                                stack.push(addr);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Drop => {
 | 
					                    InstructionType::Drop => {
 | 
				
			||||||
                        stack.pop();
 | 
					                        stack.pop();
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Dup => {
 | 
					                    InstructionType::Dup => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(a);
 | 
					                        stack.push(a);
 | 
				
			||||||
                        stack.push(a);
 | 
					                        stack.push(a);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    InstructionType::Rot => {
 | 
					                    InstructionType::Rot => {
 | 
				
			||||||
| 
						 | 
					@ -72,14 +84,14 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
 | 
				
			||||||
                        stack.push(b);
 | 
					                        stack.push(b);
 | 
				
			||||||
                        stack.push(a);
 | 
					                        stack.push(a);
 | 
				
			||||||
                        stack.push(c);
 | 
					                        stack.push(c);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    InstructionType::Swap => {
 | 
					                    InstructionType::Swap => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(a);
 | 
					                        stack.push(a);
 | 
				
			||||||
                        stack.push(b);
 | 
					                        stack.push(b);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    InstructionType::Over => {
 | 
					                    InstructionType::Over => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
| 
						 | 
					@ -87,43 +99,67 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
 | 
				
			||||||
                        stack.push(b);
 | 
					                        stack.push(b);
 | 
				
			||||||
                        stack.push(a);
 | 
					                        stack.push(a);
 | 
				
			||||||
                        stack.push(b);
 | 
					                        stack.push(b);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    InstructionType::Print => {
 | 
					                    InstructionType::Print => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        println!("{a}");
 | 
					                        println!("{a}");
 | 
				
			||||||
                        // let _ = io::stdout().flush();
 | 
					                        // let _ = io::stdout().flush();
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    // mem
 | 
					                    #[allow(clippy::cast_possible_truncation)]
 | 
				
			||||||
        
 | 
					                    InstructionType::Load8 |
 | 
				
			||||||
                    InstructionType::Mem => {
 | 
					                    InstructionType::Load32 |
 | 
				
			||||||
                        stack.push(0);
 | 
					                    InstructionType::Load64 => {
 | 
				
			||||||
                        ti += 1;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    InstructionType::Load8 => {
 | 
					 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        if a > crate::compile::MEM_SZ {
 | 
					                        if a > crate::MEM_SZ {
 | 
				
			||||||
                            lerror!(&token.loc, "Invalid memory address {a}");
 | 
					                            lerror!(&op.loc, "Invalid memory address {a}");
 | 
				
			||||||
                            return Ok(1);
 | 
					                            return Ok(1);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        let byte = mem[a];
 | 
					                        let byte = mem[a];
 | 
				
			||||||
                        stack.push(byte as usize);
 | 
					                        stack.push(byte as usize);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    #[allow(clippy::cast_possible_truncation)]
 | 
					                    #[allow(clippy::cast_possible_truncation)]
 | 
				
			||||||
                    InstructionType::Store8 => {
 | 
					                    InstructionType::Store8 => {
 | 
				
			||||||
                        let val = stack_pop(&mut stack, &pos)?;
 | 
					                        let val = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let addr = stack_pop(&mut stack, &pos)?;
 | 
					                        let addr = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        
 | 
					                        
 | 
				
			||||||
                        if addr > crate::compile::MEM_SZ {
 | 
					                        if addr > crate::MEM_SZ {
 | 
				
			||||||
                            lerror!(&token.loc, "Invalid memory address {addr}");
 | 
					                            lerror!(&op.loc, "Invalid memory address {addr}");
 | 
				
			||||||
                            return Ok(1);
 | 
					                            return Ok(1);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        mem[addr] = (val & 0xFF) as u8;
 | 
					                        mem[addr] = u64::from(val as u8);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    #[allow(clippy::cast_possible_truncation)]
 | 
				
			||||||
 | 
					                    InstructionType::Store32 => {
 | 
				
			||||||
 | 
					                        let val = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
 | 
					                        let addr = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        if addr > crate::MEM_SZ {
 | 
				
			||||||
 | 
					                            lerror!(&op.loc, "Invalid memory address {addr}");
 | 
				
			||||||
 | 
					                            return Ok(1);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        mem[addr] = u64::from(val as u32);
 | 
				
			||||||
 | 
					                        ip += 1;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    #[allow(clippy::cast_possible_truncation)]
 | 
				
			||||||
 | 
					                    InstructionType::Store64 => {
 | 
				
			||||||
 | 
					                        let val = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
 | 
					                        let addr = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        if addr > crate::MEM_SZ {
 | 
				
			||||||
 | 
					                            lerror!(&op.loc, "Invalid memory address {addr}");
 | 
				
			||||||
 | 
					                            return Ok(1);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        mem[addr] = val as u64;
 | 
				
			||||||
 | 
					                        ip += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    // math
 | 
					                    // math
 | 
				
			||||||
| 
						 | 
					@ -131,77 +167,77 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(b + a);
 | 
					                        stack.push(b + a);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Minus => {
 | 
					                    InstructionType::Minus => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(b - a);
 | 
					                        stack.push(b - a);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Equals => {
 | 
					                    InstructionType::Equals => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(usize::from(b == a));
 | 
					                        stack.push(usize::from(b == a));
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Gt => {
 | 
					                    InstructionType::Gt => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(usize::from(b > a));
 | 
					                        stack.push(usize::from(b > a));
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Lt => {
 | 
					                    InstructionType::Lt => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(usize::from(b < a));
 | 
					                        stack.push(usize::from(b < a));
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::NotEquals => {
 | 
					                    InstructionType::NotEquals => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(usize::from(b != a));
 | 
					                        stack.push(usize::from(b != a));
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Ge => {
 | 
					                    InstructionType::Ge => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(usize::from(b >= a));
 | 
					                        stack.push(usize::from(b >= a));
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Le => {
 | 
					                    InstructionType::Le => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(usize::from(b <= a));
 | 
					                        stack.push(usize::from(b <= a));
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    InstructionType::Band => {
 | 
					                    InstructionType::Band => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(a & b);
 | 
					                        stack.push(a & b);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    InstructionType::Bor => {
 | 
					                    InstructionType::Bor => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(a | b);
 | 
					                        stack.push(a | b);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    InstructionType::Shr => {
 | 
					                    InstructionType::Shr => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(b >> a);
 | 
					                        stack.push(b >> a);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                    InstructionType::Shl => {
 | 
					                    InstructionType::Shl => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(b << a);
 | 
					                        stack.push(b << a);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    InstructionType::DivMod => {
 | 
					                    InstructionType::DivMod => {
 | 
				
			||||||
| 
						 | 
					@ -209,13 +245,13 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(b / a);
 | 
					                        stack.push(b / a);
 | 
				
			||||||
                        stack.push(b % a);
 | 
					                        stack.push(b % a);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    InstructionType::Mul => {
 | 
					                    InstructionType::Mul => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        let b = stack_pop(&mut stack, &pos)?;
 | 
					                        let b = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        stack.push(b * a);
 | 
					                        stack.push(b * a);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    InstructionType::Syscall0 => {
 | 
					                    InstructionType::Syscall0 => {
 | 
				
			||||||
                        todo!();
 | 
					                        todo!();
 | 
				
			||||||
| 
						 | 
					@ -245,7 +281,7 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
 | 
				
			||||||
                        };
 | 
					                        };
 | 
				
			||||||
                        stack.push(ret);
 | 
					                        stack.push(ret);
 | 
				
			||||||
                        // println!("{}", stack.len());
 | 
					                        // println!("{}", stack.len());
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Syscall4 => {
 | 
					                    InstructionType::Syscall4 => {
 | 
				
			||||||
                        todo!();
 | 
					                        todo!();
 | 
				
			||||||
| 
						 | 
					@ -261,13 +297,41 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::MemUse => {
 | 
					                    InstructionType::MemUse => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        let m = memories.get(&token.addr.unwrap()).unwrap();
 | 
					                        let m = memories.get(&op.addr.unwrap()).unwrap();
 | 
				
			||||||
                        stack.push(*m);
 | 
					                        stack.push(m.id);
 | 
				
			||||||
                        ti += 1;
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::CastBool => ti += 1,
 | 
					                    InstructionType::FnCall => {
 | 
				
			||||||
                    InstructionType::CastPtr => ti += 1,
 | 
					                        ret_stack.push(ip);
 | 
				
			||||||
                    InstructionType::CastInt => ti += 1,
 | 
					                        let f = functions.get(&op.text).unwrap();
 | 
				
			||||||
 | 
					                        ip = f.id;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    InstructionType::Return => {
 | 
				
			||||||
 | 
					                        ip = ret_stack.pop().unwrap();
 | 
				
			||||||
 | 
					                        ip += 1;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    InstructionType::ConstUse => {
 | 
				
			||||||
 | 
					                        let a = constants.get(&op.text).unwrap();
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        if let Some(i) = a.value_i {
 | 
				
			||||||
 | 
					                            stack.push(i);
 | 
				
			||||||
 | 
					                        } else if let Some(_s) = a.value_s.clone() {
 | 
				
			||||||
 | 
					                            unimplemented!();
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        ip += 1;
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    InstructionType::CastBool |
 | 
				
			||||||
 | 
					                    InstructionType::CastPtr |
 | 
				
			||||||
 | 
					                    InstructionType::CastInt |
 | 
				
			||||||
 | 
					                    InstructionType::CastVoid |
 | 
				
			||||||
 | 
					                    InstructionType::TypeBool |
 | 
				
			||||||
 | 
					                    InstructionType::TypePtr |
 | 
				
			||||||
 | 
					                    InstructionType::TypeInt |
 | 
				
			||||||
 | 
					                    InstructionType::TypeVoid |
 | 
				
			||||||
 | 
					                    InstructionType::TypeStr |
 | 
				
			||||||
 | 
					                    InstructionType::TypeAny |
 | 
				
			||||||
 | 
					                    InstructionType::Returns |
 | 
				
			||||||
 | 
					                    InstructionType::With => ip += 1,
 | 
				
			||||||
                    InstructionType::None => unreachable!(),
 | 
					                    InstructionType::None => unreachable!(),
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -279,30 +343,42 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &pos)?;
 | 
					                        let a = stack_pop(&mut stack, &pos)?;
 | 
				
			||||||
                        if a == 0 {
 | 
					                        if a == 0 {
 | 
				
			||||||
                            // println!("If({ti}) => t: {:?} j: {}", tokens[token.jmp as usize].typ, token.jmp);
 | 
					                            // println!("If({ti}) => t: {:?} j: {}", tokens[token.jmp as usize].typ, token.jmp);
 | 
				
			||||||
                            ti = token.jmp;
 | 
					                            ip = op.jmp;
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            ti += 1;
 | 
					                            ip += 1;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    KeywordType::Else | KeywordType::End => {
 | 
					                    KeywordType::Else | KeywordType::End => {
 | 
				
			||||||
                        ti = token.jmp;
 | 
					                        ip = op.jmp;
 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    KeywordType::While => {
 | 
					 | 
				
			||||||
                        ti += 1;
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    KeywordType::Do => {
 | 
					                    KeywordType::Do => {
 | 
				
			||||||
                        let a = stack.pop().unwrap();
 | 
					                        let a = stack.pop().unwrap();
 | 
				
			||||||
                        if a == 0 {
 | 
					                        if a == 0 {
 | 
				
			||||||
                            ti = token.jmp;
 | 
					                            ip = op.jmp;
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            ti += 1;
 | 
					                            ip += 1;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    KeywordType::Memory => {
 | 
					                    KeywordType::While | //* exept this one, this one should just skip over
 | 
				
			||||||
                        memories.insert(token.addr.unwrap(), token.value);
 | 
					                    KeywordType::Memory |
 | 
				
			||||||
                        ti += 1;
 | 
					                    KeywordType::FunctionDef |
 | 
				
			||||||
 | 
					                    KeywordType::ConstantDef => {
 | 
				
			||||||
 | 
					                        //? Disabled since we now pre run the whole program
 | 
				
			||||||
 | 
					                        // constants.insert(op.text.clone(), Constant { loc: op.loc.clone(), name: op.text.clone(), value_i: Some(op.value), value_s: None, used: false });
 | 
				
			||||||
 | 
					                        ip += 1;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    KeywordType::Macro | KeywordType::Include => unreachable!(),
 | 
					                    KeywordType::FunctionDone => {
 | 
				
			||||||
 | 
					                        if let Some(i) = ret_stack.pop() {
 | 
				
			||||||
 | 
					                            ip = i + 1;
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            break;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    KeywordType::FunctionThen  => ip += 1,
 | 
				
			||||||
 | 
					                    KeywordType::Constant |
 | 
				
			||||||
 | 
					                    KeywordType::Function |
 | 
				
			||||||
 | 
					                    KeywordType::Include => unreachable!(),
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
| 
						 | 
					@ -312,3 +388,33 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result<i32>{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(0)
 | 
					    Ok(0)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct Defineds {
 | 
				
			||||||
 | 
					    pub memories: HashMap<usize, Memory>,
 | 
				
			||||||
 | 
					    pub functions: HashMap<String, Function>,
 | 
				
			||||||
 | 
					    pub constants: HashMap<String, Constant>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn pre_run(ops: &[Operator]) -> Defineds {
 | 
				
			||||||
 | 
					    let mut defineds = Defineds{
 | 
				
			||||||
 | 
					        memories: HashMap::new(),
 | 
				
			||||||
 | 
					        functions: HashMap::new(),
 | 
				
			||||||
 | 
					        constants: HashMap::new(),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    for (ip, op) in ops.iter().enumerate() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match op.typ {
 | 
				
			||||||
 | 
					            OpType::Keyword(KeywordType::Memory) => {
 | 
				
			||||||
 | 
					                defineds.memories.insert(op.addr.unwrap(), Memory { size: op.value, loc: op.loc.clone(), id: op.addr.unwrap() });
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            OpType::Keyword(KeywordType::FunctionDef) => {
 | 
				
			||||||
 | 
					                defineds.functions.insert(op.text.clone(), Function { loc: op.loc.clone(), name: op.text.clone(), id: ip });
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            OpType::Keyword(KeywordType::ConstantDef) => {
 | 
				
			||||||
 | 
					                defineds.constants.insert(op.text.clone(), Constant { loc: op.loc.clone(), name: op.text.clone(), value_i: Some(op.value), value_s: None, used: false });
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            _ => ()   
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    defineds
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,10 @@
 | 
				
			||||||
 | 
					#[allow(clippy::cast_possible_truncation)]
 | 
				
			||||||
pub fn sys_write(sys_n: usize, fd: usize, buff: usize, count: usize, mem: &Vec<u8> ) -> usize {
 | 
					pub fn sys_write(sys_n: usize, fd: usize, buff: usize, count: usize, mem: &Vec<u64> ) -> usize {
 | 
				
			||||||
    let mem = (*mem).clone();
 | 
					    let mem = (*mem).clone();
 | 
				
			||||||
    // println!("{:?}", &mem[buff..(buff + count)]);
 | 
					    // println!("{:?}", &mem[buff..(buff + count)]);
 | 
				
			||||||
    // return 0 ;
 | 
					    // return 0 ;
 | 
				
			||||||
    let s = &mem[buff..(buff + count)].iter().map(|i| {
 | 
					    let s = &mem[buff..(buff + count)].iter().map(|i| {
 | 
				
			||||||
        char::from_u32(u32::from(*i)).unwrap_or('_').to_string()
 | 
					        char::from_u32(u32::from(*i as u8)).unwrap_or('_').to_string()
 | 
				
			||||||
    }).collect::<String>();
 | 
					    }).collect::<String>();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    match fd {
 | 
					    match fd {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +1,27 @@
 | 
				
			||||||
 | 
					use crate::constants::Loc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod linux_x86_64;
 | 
					pub mod linux_x86_64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Constant {
 | 
				
			||||||
 | 
					    pub loc: Loc,
 | 
				
			||||||
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    pub value_i: Option<usize>,
 | 
				
			||||||
 | 
					    pub value_s: Option<String>,
 | 
				
			||||||
 | 
					    pub used: bool
 | 
				
			||||||
 | 
					    // extern: bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Memory {
 | 
				
			||||||
 | 
					    pub size: usize,
 | 
				
			||||||
 | 
					    pub loc: Loc,
 | 
				
			||||||
 | 
					    pub id: usize
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Function {
 | 
				
			||||||
 | 
					    pub loc: Loc,
 | 
				
			||||||
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    pub id: usize
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								src/lexer.rs
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/lexer.rs
									
									
									
									
									
								
							| 
						 | 
					@ -1,6 +1,5 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{constants::{Token, TokenType}, preprocessor::preprocess, Args};
 | 
					use crate::{constants::{Token, TokenType}, Args};
 | 
				
			||||||
use color_eyre::Result;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn lex_word(s: String, tok_type: TokenType) -> (TokenType, String) {
 | 
					fn lex_word(s: String, tok_type: TokenType) -> (TokenType, String) {
 | 
				
			||||||
    match s {
 | 
					    match s {
 | 
				
			||||||
| 
						 | 
					@ -89,7 +88,7 @@ fn lex_line(text: &str) -> Vec<(usize, String, TokenType)> {
 | 
				
			||||||
    tokens
 | 
					    tokens
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn lex<S: Into<String> + std::marker::Copy>(code: &str, file: S, args: &Args, preprocessing: bool) -> Result<Vec<Token>> {
 | 
					pub fn lex(code: &str, file: &str, _args: &Args) -> Vec<Token> {
 | 
				
			||||||
    let lines: Vec<(usize, &str)> = code
 | 
					    let lines: Vec<(usize, &str)> = code
 | 
				
			||||||
        .split(['\n', '\r'])
 | 
					        .split(['\n', '\r'])
 | 
				
			||||||
        .enumerate()
 | 
					        .enumerate()
 | 
				
			||||||
| 
						 | 
					@ -104,14 +103,14 @@ pub fn lex<S: Into<String> + std::marker::Copy>(code: &str, file: S, args: &Args
 | 
				
			||||||
        for (col, tok, tok_type) in lt {
 | 
					        for (col, tok, tok_type) in lt {
 | 
				
			||||||
            let (tok_type, tok) = lex_word(tok, tok_type);
 | 
					            let (tok_type, tok) = lex_word(tok, tok_type);
 | 
				
			||||||
            let t = Token{
 | 
					            let t = Token{
 | 
				
			||||||
                file: file.into(),
 | 
					                file: file.to_string(),
 | 
				
			||||||
                line: row + 1,
 | 
					                line: row + 1,
 | 
				
			||||||
                col,
 | 
					                col,
 | 
				
			||||||
                text: tok,
 | 
					                text: tok,
 | 
				
			||||||
                typ: tok_type,
 | 
					                typ: tok_type,
 | 
				
			||||||
                value: None,
 | 
					                value: None,
 | 
				
			||||||
                addr: None,
 | 
					                addr: None,
 | 
				
			||||||
                op_typ: crate::constants::InstructionType::None
 | 
					                op_typ: crate::constants::OpType::Instruction(crate::constants::InstructionType::None)
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            tokens.push(t);
 | 
					            tokens.push(t);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -121,9 +120,7 @@ pub fn lex<S: Into<String> + std::marker::Copy>(code: &str, file: S, args: &Args
 | 
				
			||||||
    // for token in tokens.clone() {
 | 
					    // for token in tokens.clone() {
 | 
				
			||||||
    //     println!("tok: {:?}", token.text);
 | 
					    //     println!("tok: {:?}", token.text);
 | 
				
			||||||
    // }
 | 
					    // }
 | 
				
			||||||
    if preprocessing {
 | 
					 | 
				
			||||||
        tokens = preprocess(tokens, args)?;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    Ok(tokens)
 | 
					
 | 
				
			||||||
 | 
					    tokens
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										76
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								src/main.rs
									
									
									
									
									
								
							| 
						 | 
					@ -1,3 +1,5 @@
 | 
				
			||||||
 | 
					#![allow(clippy::wildcard_imports)]
 | 
				
			||||||
 | 
					#![allow(clippy::too_many_lines)]
 | 
				
			||||||
mod constants;
 | 
					mod constants;
 | 
				
			||||||
mod interpret;
 | 
					mod interpret;
 | 
				
			||||||
mod util;
 | 
					mod util;
 | 
				
			||||||
| 
						 | 
					@ -7,18 +9,14 @@ mod lexer;
 | 
				
			||||||
mod preprocessor;
 | 
					mod preprocessor;
 | 
				
			||||||
mod typechecker;
 | 
					mod typechecker;
 | 
				
			||||||
mod precompiler;
 | 
					mod precompiler;
 | 
				
			||||||
 | 
					mod config;
 | 
				
			||||||
use std::fs;
 | 
					mod errors;
 | 
				
			||||||
 | 
					use config::*;
 | 
				
			||||||
 | 
					use std::{fs, collections::HashMap};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use clap::Parser;
 | 
					use clap::Parser;
 | 
				
			||||||
 | 
					use color_eyre::Result;
 | 
				
			||||||
pub const DEFAULT_OUT_FILE: &str = "a.out";
 | 
					use eyre::eyre;
 | 
				
			||||||
pub const DEFAULT_INCLUDES: [&str;2] = [
 | 
					 | 
				
			||||||
    "./include",
 | 
					 | 
				
			||||||
    "~/.mclang/include",
 | 
					 | 
				
			||||||
];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Parser, Debug, Clone)]
 | 
					#[derive(Parser, Debug, Clone)]
 | 
				
			||||||
#[command(author, version, about, long_about = None)]
 | 
					#[command(author, version, about, long_about = None)]
 | 
				
			||||||
| 
						 | 
					@ -53,38 +51,70 @@ pub struct Args {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Unsafe mode, disables typechecking
 | 
					    /// Unsafe mode, disables typechecking
 | 
				
			||||||
    #[arg(long="unsafe", default_value_t = false)]
 | 
					    #[arg(long="unsafe", default_value_t = false)]
 | 
				
			||||||
    unsaf: bool
 | 
					    unsaf: bool,
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /// Optimisation level, available levels: 'D': debug, '0': No optimisations
 | 
				
			||||||
 | 
					    #[arg(long, short='O', default_value_t=String::from("0"))]
 | 
				
			||||||
 | 
					    optimisation: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //#[arg(long, short='F')]
 | 
					    //#[arg(long, short='F')]
 | 
				
			||||||
    //features: Vec<String>,
 | 
					    //features: Vec<String>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() {
 | 
					impl Args {
 | 
				
			||||||
 | 
					    /// Get optimisation level
 | 
				
			||||||
 | 
					    /// 0 => no optimisations
 | 
				
			||||||
 | 
					    /// 1 => slight optimisations, mostly size ones
 | 
				
			||||||
 | 
					    /// # Errors
 | 
				
			||||||
 | 
					    /// 
 | 
				
			||||||
 | 
					    /// Throws when the opt level is not known
 | 
				
			||||||
 | 
					    pub fn get_opt_level(&self) -> Result<usize>{
 | 
				
			||||||
 | 
					        match self.optimisation.as_str() {
 | 
				
			||||||
 | 
					            "D" | "d" => Ok(0),
 | 
				
			||||||
 | 
					            "0" | "" => Ok(1),
 | 
				
			||||||
 | 
					            o => {
 | 
				
			||||||
 | 
					                error!("Unknown optimisation level {o}");
 | 
				
			||||||
 | 
					                Err(eyre!(""))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() -> Result<()>{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let args = Args::parse();
 | 
					    let args = Args::parse();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let Ok(code) = fs::read_to_string(&args.in_file) else {
 | 
					    let Ok(code) = fs::read_to_string(&args.in_file) else {
 | 
				
			||||||
        error!("Failed to read file {}, exiting!", &args.in_file);
 | 
					        error!("Failed to read file {}, exiting!", &args.in_file);
 | 
				
			||||||
        return;
 | 
					        return Ok(());
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    let Ok(tokens) = lexer::lex(&code, &args.in_file, &args, true) else {
 | 
					 | 
				
			||||||
        error!("Lexing failed, exiting!");
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    let tokens = lexer::lex(&code, args.in_file.as_str(), &args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut parser = parser::Parser::new(tokens);
 | 
					    
 | 
				
			||||||
    let Ok(tokens) = parser.parse() else {
 | 
					    let mut parser = parser::Parser::new(tokens, &args, None);
 | 
				
			||||||
 | 
					    let tokens = match parser.parse(){
 | 
				
			||||||
 | 
					        Ok(t) => t,
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
            error!("Parsing failed, exiting!");
 | 
					            error!("Parsing failed, exiting!");
 | 
				
			||||||
        return;
 | 
					            if crate::DEV_MODE {
 | 
				
			||||||
 | 
					                return Err(e)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return Ok(());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let Ok(tokens) = typechecker::typecheck(&tokens, &args) else {
 | 
					    match typechecker::typecheck(tokens.clone(), &args, None, HashMap::new(), HashMap::new()) {
 | 
				
			||||||
 | 
					        Ok(_) => (),
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
            error!("Typechecking failed, exiting!");
 | 
					            error!("Typechecking failed, exiting!");
 | 
				
			||||||
        return;
 | 
					            if crate::DEV_MODE {
 | 
				
			||||||
 | 
					                return Err(e);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return Ok(());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let c = if args.compile && args.interpret {
 | 
					    let c = if args.compile && args.interpret {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										112
									
								
								src/parser.rs
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								src/parser.rs
									
									
									
									
									
								
							| 
						 | 
					@ -1,22 +1,27 @@
 | 
				
			||||||
use std::ops::Deref;
 | 
					use std::ops::Deref;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{constants::{Operator, OpType, Token, TokenType, Loc, KeywordType, InstructionType}, lerror};
 | 
					use crate::{constants::{Operator, OpType, Token, TokenType, Loc, KeywordType, InstructionType}, lerror, preprocessor::Preprocessor, Args};
 | 
				
			||||||
use color_eyre::Result;
 | 
					use color_eyre::Result;
 | 
				
			||||||
use eyre::eyre;
 | 
					use eyre::eyre;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
 | 
					pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
 | 
				
			||||||
    let mut stack: Vec<usize> = Vec::new();
 | 
					    let mut stack: Vec<usize> = Vec::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for ip in 0..program.len() {
 | 
					    for ip in 0..program.len() {
 | 
				
			||||||
        let op = &program.clone()[ip];
 | 
					        let op = &program.clone()[ip];
 | 
				
			||||||
 | 
					        // println!("{op:?}");
 | 
				
			||||||
        match op.typ {
 | 
					        match op.typ {
 | 
				
			||||||
            OpType::Keyword(KeywordType::If) | 
 | 
					            // OpType::Keyword(KeywordType::FunctionDef) |
 | 
				
			||||||
            OpType::Keyword(KeywordType::While) => {
 | 
					            OpType::Keyword(KeywordType::If | KeywordType::While) => {
 | 
				
			||||||
                stack.push(ip);
 | 
					                stack.push(ip);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            OpType::Keyword(KeywordType::Else) => {
 | 
					            OpType::Keyword(KeywordType::Else) => {
 | 
				
			||||||
                let if_ip = stack.pop().unwrap();
 | 
					                let Some(if_ip) = stack.pop() else {
 | 
				
			||||||
 | 
					                    lerror!(&op.loc, "Unclosed-if else block");
 | 
				
			||||||
 | 
					                    return Err(eyre!("Cross referencing"));
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
                if program[if_ip].typ != OpType::Keyword(KeywordType::If) {
 | 
					                if program[if_ip].typ != OpType::Keyword(KeywordType::If) {
 | 
				
			||||||
                    lerror!(&op.clone().loc,"'end' can only close 'if' blocks");
 | 
					                    lerror!(&op.clone().loc,"'else' can only close 'if' blocks");
 | 
				
			||||||
                    return Err(eyre!("Bad block"));
 | 
					                    return Err(eyre!("Bad block"));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
| 
						 | 
					@ -24,26 +29,41 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
 | 
				
			||||||
                stack.push(ip);
 | 
					                stack.push(ip);
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            OpType::Keyword(KeywordType::End) => {
 | 
					            OpType::Keyword(KeywordType::End) => {
 | 
				
			||||||
                let block_ip = stack.pop().unwrap();
 | 
					                let Some(block_ip) = stack.pop() else {
 | 
				
			||||||
 | 
					                    lerror!(&op.loc, "Unclosed if, if-else, while-do, function, memory, or constant");
 | 
				
			||||||
                if program[block_ip].typ == OpType::Keyword(KeywordType::If) || 
 | 
					                    return Err(eyre!("Cross referencing"));
 | 
				
			||||||
                   program[block_ip].typ == OpType::Keyword(KeywordType::Else) {
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                match &program[block_ip].typ {
 | 
				
			||||||
 | 
					                    OpType::Keyword(KeywordType::If | KeywordType::Else) => {
 | 
				
			||||||
                        program[block_ip].jmp = ip;
 | 
					                        program[block_ip].jmp = ip;
 | 
				
			||||||
                        program[ip].jmp = ip + 1;
 | 
					                        program[ip].jmp = ip + 1;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                } else if program[block_ip].typ == OpType::Keyword(KeywordType::Do) {
 | 
					                    OpType::Keyword(KeywordType::Do) => {
 | 
				
			||||||
                        program[ip].jmp = program[block_ip].jmp;
 | 
					                        program[ip].jmp = program[block_ip].jmp;
 | 
				
			||||||
                        program[block_ip].jmp = ip + 1;
 | 
					                        program[block_ip].jmp = ip + 1;
 | 
				
			||||||
                } else {
 | 
					                    }
 | 
				
			||||||
                    lerror!(&op.clone().loc,"'end' can only close 'if' blocks");
 | 
					                    OpType::Keyword(KeywordType::FunctionThen) => {
 | 
				
			||||||
 | 
					                        program[ip].typ = OpType::Instruction(InstructionType::Return);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    OpType::Keyword(KeywordType::Memory | KeywordType::Constant) => (),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    a => {
 | 
				
			||||||
 | 
					                        println!("{a:?}");
 | 
				
			||||||
 | 
					                        lerror!(&op.clone().loc,"'end' can only close if, if-else, while-do, function, memory, or constant blocks");
 | 
				
			||||||
                        return  Err(eyre!(""));
 | 
					                        return  Err(eyre!(""));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            OpType::Keyword(KeywordType::Do) => {
 | 
					            OpType::Keyword(KeywordType::Do) => {
 | 
				
			||||||
                let while_ip = stack.pop().unwrap();
 | 
					                let Some(block_ip) = stack.pop() else {
 | 
				
			||||||
                program[ip].jmp = while_ip;
 | 
					                    lerror!(&op.loc, "Unclosed while-do block");
 | 
				
			||||||
 | 
					                    return Err(eyre!("Cross referencing"));
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                program[ip].jmp = block_ip;
 | 
				
			||||||
                stack.push(ip);
 | 
					                stack.push(ip);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => ()
 | 
					            _ => ()
 | 
				
			||||||
| 
						 | 
					@ -51,21 +71,31 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if !stack.is_empty() {
 | 
					    if !stack.is_empty() {
 | 
				
			||||||
        lerror!(&program[stack.pop().expect("Empy stack")].clone().loc,"Unclosed block");
 | 
					        // println!("{:?}", stack);
 | 
				
			||||||
 | 
					        lerror!(&program[stack.pop().expect("Empy stack")].clone().loc,"Unclosed block, {:?}", program[stack.pop().expect("Empy stack")].clone());
 | 
				
			||||||
        return Err(eyre!("Unclosed block"));
 | 
					        return Err(eyre!("Unclosed block"));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(program.clone())
 | 
					    Ok(program.clone())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct Parser {
 | 
					pub struct Parser<'a> {
 | 
				
			||||||
    tokens: Vec<Token>
 | 
					    tokens: Vec<Token>,
 | 
				
			||||||
 | 
					    pub preprocessor: Preprocessor<'a>,
 | 
				
			||||||
 | 
					    #[allow(dead_code)]
 | 
				
			||||||
 | 
					    args: &'a Args
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Parser {
 | 
					impl<'a> Parser<'a> {
 | 
				
			||||||
    pub fn new(file: Vec<Token>) -> Self {
 | 
					    pub fn new(file: Vec<Token>, args: &'a Args, p: Option<Preprocessor<'a>>) -> Self {
 | 
				
			||||||
 | 
					        let pre = if let Some(p) = p {p} else {
 | 
				
			||||||
 | 
					            Preprocessor::new(Vec::new(), args)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Self{
 | 
					        Self{
 | 
				
			||||||
            tokens: file
 | 
					            tokens: file,
 | 
				
			||||||
 | 
					            preprocessor: pre,
 | 
				
			||||||
 | 
					            args
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,19 +109,19 @@ impl Parser {
 | 
				
			||||||
            let pos = (token.file.clone(), token.line, token.col);
 | 
					            let pos = (token.file.clone(), token.line, token.col);
 | 
				
			||||||
            match token.typ {
 | 
					            match token.typ {
 | 
				
			||||||
                TokenType::Word => {
 | 
					                TokenType::Word => {
 | 
				
			||||||
                    let word_type = if token.op_typ == InstructionType::MemUse {
 | 
					                    let word_type = if token.op_typ == OpType::Instruction(InstructionType::MemUse) {
 | 
				
			||||||
                        OpType::Instruction(InstructionType::MemUse)
 | 
					                        OpType::Instruction(InstructionType::MemUse)
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        lookup_word(&token.text, &pos)
 | 
					                        lookup_word(&token.text, &pos)
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    tokens.push(Operator::new(word_type, token.value.unwrap_or(0), token.text.clone(), token.file.clone(), token.line, token.col).set_addr(token.addr.unwrap_or(0)));
 | 
					                    tokens.push(Operator::new(word_type, token.typ, token.value.unwrap_or(0), token.text.clone(), token.file.clone(), token.line, token.col).set_addr(token.addr.unwrap_or(0)));
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                TokenType::Int => {// negative numbers not yet implemented
 | 
					                TokenType::Int => {// negative numbers not yet implemented
 | 
				
			||||||
                    tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.text.parse::<usize>()?, String::new(), token.file.clone(), token.line, token.col));
 | 
					                    tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.typ, token.text.parse::<usize>()?, String::new(), token.file.clone(), token.line, token.col));
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                TokenType::String => {
 | 
					                TokenType::String => {
 | 
				
			||||||
                    tokens.push(Operator::new(OpType::Instruction(InstructionType::PushStr), 0, token.text.clone(), token.file.clone(), token.line, token.col));
 | 
					                    tokens.push(Operator::new(OpType::Instruction(InstructionType::PushStr), token.typ, 0, token.text.clone(), token.file.clone(), token.line, token.col));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                TokenType::Char => {
 | 
					                TokenType::Char => {
 | 
				
			||||||
                    let c = token.text.clone();
 | 
					                    let c = token.text.clone();
 | 
				
			||||||
| 
						 | 
					@ -100,27 +130,29 @@ impl Parser {
 | 
				
			||||||
                        return Err(eyre!(""));
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.text.chars().next().unwrap() as usize, String::new(), token.file.clone(), token.line, token.col));
 | 
					                    tokens.push(Operator::new(OpType::Instruction(InstructionType::PushInt), token.typ, token.text.chars().next().unwrap() as usize, String::new(), token.file.clone(), token.line, token.col));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //"print" => tokens.push(Operator::new(OpType::Print, 0, token.file.clone(), token.line, token.col)),
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        self.preprocessor.program = tokens;
 | 
				
			||||||
 | 
					        let t = self.preprocessor.preprocess()?.get_ops();
 | 
				
			||||||
 | 
					        let t = cross_ref(t)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cross_ref(tokens)
 | 
					        Ok(t)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
 | 
					pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
 | 
				
			||||||
    let n = s.parse::<usize>();
 | 
					    let n = s.parse::<usize>();
 | 
				
			||||||
    if let Ok(_) = n {
 | 
					    if n.is_ok() {
 | 
				
			||||||
        return OpType::Instruction(InstructionType::PushInt);
 | 
					        return OpType::Instruction(InstructionType::PushInt);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    match s {
 | 
					    match s {
 | 
				
			||||||
        //stack
 | 
					        //stack
 | 
				
			||||||
        "print" => OpType::Instruction(InstructionType::Print),
 | 
					        "_dbg_print" => OpType::Instruction(InstructionType::Print),
 | 
				
			||||||
        "dup" => OpType::Instruction(InstructionType::Dup),
 | 
					        "dup" => OpType::Instruction(InstructionType::Dup),
 | 
				
			||||||
        "drop" => OpType::Instruction(InstructionType::Drop),
 | 
					        "drop" => OpType::Instruction(InstructionType::Drop),
 | 
				
			||||||
        "rot" => OpType::Instruction(InstructionType::Rot),
 | 
					        "rot" => OpType::Instruction(InstructionType::Rot),
 | 
				
			||||||
| 
						 | 
					@ -146,9 +178,12 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // mem
 | 
					        // mem
 | 
				
			||||||
        "mem" => OpType::Instruction(InstructionType::Mem),
 | 
					 | 
				
			||||||
        "load8" => OpType::Instruction(InstructionType::Load8),
 | 
					        "load8" => OpType::Instruction(InstructionType::Load8),
 | 
				
			||||||
        "store8" => OpType::Instruction(InstructionType::Store8),
 | 
					        "store8" => OpType::Instruction(InstructionType::Store8),
 | 
				
			||||||
 | 
					        "load32" => OpType::Instruction(InstructionType::Load32),
 | 
				
			||||||
 | 
					        "store32" => OpType::Instruction(InstructionType::Store32),
 | 
				
			||||||
 | 
					        "load64" => OpType::Instruction(InstructionType::Load64),
 | 
				
			||||||
 | 
					        "store64" => OpType::Instruction(InstructionType::Store64),
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        "syscall0" => OpType::Instruction(InstructionType::Syscall0),
 | 
					        "syscall0" => OpType::Instruction(InstructionType::Syscall0),
 | 
				
			||||||
        "syscall1" => OpType::Instruction(InstructionType::Syscall1),
 | 
					        "syscall1" => OpType::Instruction(InstructionType::Syscall1),
 | 
				
			||||||
| 
						 | 
					@ -157,18 +192,31 @@ pub fn lookup_word<P: Deref<Target = Loc>>(s: &str, _pos: P) -> OpType {
 | 
				
			||||||
        "syscall4" => OpType::Instruction(InstructionType::Syscall4),
 | 
					        "syscall4" => OpType::Instruction(InstructionType::Syscall4),
 | 
				
			||||||
        "syscall5" => OpType::Instruction(InstructionType::Syscall5),
 | 
					        "syscall5" => OpType::Instruction(InstructionType::Syscall5),
 | 
				
			||||||
        "syscall6" => OpType::Instruction(InstructionType::Syscall6),
 | 
					        "syscall6" => OpType::Instruction(InstructionType::Syscall6),
 | 
				
			||||||
        "cast(bool" => OpType::Instruction(InstructionType::CastBool),
 | 
					        "cast(bool)" => OpType::Instruction(InstructionType::CastBool),
 | 
				
			||||||
        "cast(ptr)" => OpType::Instruction(InstructionType::CastPtr),
 | 
					        "cast(ptr)" => OpType::Instruction(InstructionType::CastPtr),
 | 
				
			||||||
        "cast(int)" => OpType::Instruction(InstructionType::CastInt),
 | 
					        "cast(int)" => OpType::Instruction(InstructionType::CastInt),
 | 
				
			||||||
 | 
					        "cast(void)" => OpType::Instruction(InstructionType::CastVoid),
 | 
				
			||||||
        // block
 | 
					        // block
 | 
				
			||||||
        "if" => OpType::Keyword(KeywordType::If),
 | 
					        "if" => OpType::Keyword(KeywordType::If),
 | 
				
			||||||
        "else" => OpType::Keyword(KeywordType::Else),
 | 
					        "else" => OpType::Keyword(KeywordType::Else),
 | 
				
			||||||
        "end" => OpType::Keyword(KeywordType::End),
 | 
					        "end" => OpType::Keyword(KeywordType::End),
 | 
				
			||||||
        "while" => OpType::Keyword(KeywordType::While),
 | 
					        "while" => OpType::Keyword(KeywordType::While),
 | 
				
			||||||
        "do" => OpType::Keyword(KeywordType::Do),
 | 
					        "do" => OpType::Keyword(KeywordType::Do),
 | 
				
			||||||
        "macro" => OpType::Keyword(KeywordType::Macro),
 | 
					 | 
				
			||||||
        "include" => OpType::Keyword(KeywordType::Include),
 | 
					        "include" => OpType::Keyword(KeywordType::Include),
 | 
				
			||||||
        "memory" => OpType::Keyword(KeywordType::Memory),
 | 
					        "memory" => OpType::Keyword(KeywordType::Memory),
 | 
				
			||||||
 | 
					        "const" => OpType::Keyword(KeywordType::Constant),
 | 
				
			||||||
 | 
					        "fn" => OpType::Keyword(KeywordType::Function),
 | 
				
			||||||
 | 
					        "then" => OpType::Keyword(KeywordType::FunctionThen),
 | 
				
			||||||
 | 
					        "done" => OpType::Keyword(KeywordType::FunctionDone),
 | 
				
			||||||
 | 
					        "return" => OpType::Instruction(InstructionType::Return),
 | 
				
			||||||
 | 
					        "returns" => OpType::Instruction(InstructionType::Returns),
 | 
				
			||||||
 | 
					        "bool" => OpType::Instruction(InstructionType::TypeBool),
 | 
				
			||||||
 | 
					        "int" => OpType::Instruction(InstructionType::TypeInt),
 | 
				
			||||||
 | 
					        "ptr" => OpType::Instruction(InstructionType::TypePtr),
 | 
				
			||||||
 | 
					        "void" => OpType::Instruction(InstructionType::TypeVoid),
 | 
				
			||||||
 | 
					        "any" => OpType::Instruction(InstructionType::TypeAny),
 | 
				
			||||||
 | 
					        "str" => OpType::Instruction(InstructionType::TypeStr),
 | 
				
			||||||
 | 
					        "with" => OpType::Instruction(InstructionType::With),
 | 
				
			||||||
        _ => OpType::Instruction(InstructionType::None)
 | 
					        _ => OpType::Instruction(InstructionType::None)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
use color_eyre::Result;
 | 
					use color_eyre::Result;
 | 
				
			||||||
use eyre::eyre;
 | 
					use eyre::eyre;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{constants::{Token, OpType, InstructionType, Loc}, parser::lookup_word, lerror};
 | 
					use crate::{constants::{ OpType, InstructionType, Loc, Operator}, lerror};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn stack_pop(stack: &mut Vec<usize>, loc: &Loc) -> Result<usize> {
 | 
					fn stack_pop(stack: &mut Vec<usize>, loc: &Loc) -> Result<usize> {
 | 
				
			||||||
    if let Some(i) = stack.pop() { Ok(i) } else {
 | 
					    if let Some(i) = stack.pop() { Ok(i) } else {
 | 
				
			||||||
| 
						 | 
					@ -11,23 +11,16 @@ fn stack_pop(stack: &mut Vec<usize>, loc: &Loc) -> Result<usize> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn precompile(tokens: &Vec<Token>) -> Result<Vec<usize>>{
 | 
					pub fn precompile(tokens: &Vec<Operator>) -> Result<Vec<usize>>{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut stack: Vec<usize> = Vec::new();
 | 
					    let mut stack: Vec<usize> = Vec::new();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    for token in tokens.iter() {
 | 
					    for token in tokens.iter() {
 | 
				
			||||||
        let typ = lookup_word(&token.text, &token.loc());
 | 
					        match token.typ.clone() {
 | 
				
			||||||
        match typ {
 | 
					 | 
				
			||||||
            OpType::Instruction(i) => {
 | 
					            OpType::Instruction(i) => {
 | 
				
			||||||
                let loc = token.loc();
 | 
					                let loc = token.loc.clone();
 | 
				
			||||||
                match i {
 | 
					                match i {
 | 
				
			||||||
                    InstructionType::PushInt => {
 | 
					                    InstructionType::PushInt => {
 | 
				
			||||||
                        if let Ok(i) = token.text.parse::<usize>() {
 | 
					                        stack.push(token.value);
 | 
				
			||||||
                            stack.push(i);
 | 
					 | 
				
			||||||
                        } else {
 | 
					 | 
				
			||||||
                            lerror!(&token.loc(), "Bad number");
 | 
					 | 
				
			||||||
                            return Err(eyre!(""));
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Plus => {
 | 
					                    InstructionType::Plus => {
 | 
				
			||||||
                        let a = stack_pop(&mut stack, &loc)?;
 | 
					                        let a = stack_pop(&mut stack, &loc)?;
 | 
				
			||||||
| 
						 | 
					@ -136,14 +129,14 @@ pub fn precompile(tokens: &Vec<Token>) -> Result<Vec<usize>>{
 | 
				
			||||||
                        stack.push(b);
 | 
					                        stack.push(b);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    _ => {
 | 
					                    _ => {
 | 
				
			||||||
                        lerror!(&token.loc(), "Unsupported precompiler instruction {:?}", i);
 | 
					                        lerror!(&token.loc, "Unsupported precompiler instruction {:?}", i);
 | 
				
			||||||
                        dbg!(tokens);
 | 
					                        dbg!(tokens);
 | 
				
			||||||
                        return Err(eyre!(""));
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => {
 | 
					            OpType::Keyword(_) => {
 | 
				
			||||||
                lerror!(&token.loc(), "Unsupported precompiler keyword {:?}", typ);
 | 
					                lerror!(&token.loc, "Unsupported precompiler keyword {:?}", token.typ);
 | 
				
			||||||
                dbg!(tokens);
 | 
					                dbg!(tokens);
 | 
				
			||||||
                return Err(eyre!(""));
 | 
					                return Err(eyre!(""));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,113 +1,107 @@
 | 
				
			||||||
use std::collections::HashMap;
 | 
					use std::collections::HashMap;
 | 
				
			||||||
 | 
					use std::ops::Deref;
 | 
				
			||||||
use std::path::{PathBuf, Path};
 | 
					use std::path::{PathBuf, Path};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use color_eyre::Result;
 | 
					use color_eyre::Result;
 | 
				
			||||||
use eyre::eyre;
 | 
					use eyre::eyre;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::constants::{Token, Loc, OpType, TokenType, KeywordType, InstructionType};
 | 
					use crate::constants::{Loc, OpType, TokenType, KeywordType, InstructionType, Operator};
 | 
				
			||||||
use crate::lexer::lex;
 | 
					use crate::lexer::lex;
 | 
				
			||||||
use crate::precompiler::precompile;
 | 
					use crate::precompiler::precompile;
 | 
				
			||||||
use crate::{lerror, lnote, Args, warn, linfo};
 | 
					use crate::{lerror, Args, warn, linfo, parser};
 | 
				
			||||||
use crate::parser::lookup_word;
 | 
					use crate::parser::lookup_word;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					
 | 
				
			||||||
pub struct Macro {
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Function {
 | 
				
			||||||
    pub loc: Loc,
 | 
					    pub loc: Loc,
 | 
				
			||||||
    pub tokens: Vec<Token>
 | 
					    pub name: String
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Macros = HashMap<String, Macro>;
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
type Memories = HashMap<String, usize>;
 | 
					pub struct Constant {
 | 
				
			||||||
 | 
					    pub loc: Loc,
 | 
				
			||||||
 | 
					    pub name: String
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Memory {
 | 
				
			||||||
 | 
					    pub loc: Loc,
 | 
				
			||||||
 | 
					    pub id: usize
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Functions = HashMap<String, Function>;
 | 
				
			||||||
 | 
					type Memories = HashMap<String, Memory>;
 | 
				
			||||||
 | 
					type Constants = HashMap<String, Constant>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Preprocessor<'a> {
 | 
				
			||||||
 | 
					    pub program: Vec<Operator>,
 | 
				
			||||||
 | 
					    pub functions: Functions,
 | 
				
			||||||
 | 
					    pub memories: Memories,
 | 
				
			||||||
 | 
					    pub constants: Constants,
 | 
				
			||||||
 | 
					    args: &'a Args
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut program: Vec<Token> = Vec::new();
 | 
					impl<'a> Preprocessor<'a> {
 | 
				
			||||||
    let mut macros: Macros = HashMap::new();
 | 
					    pub fn new(prog: Vec<Operator>, args: &'a Args) -> Self {
 | 
				
			||||||
    let mut memories: Memories = HashMap::new();
 | 
					        Self {
 | 
				
			||||||
 | 
					            program: prog,
 | 
				
			||||||
 | 
					            args,
 | 
				
			||||||
 | 
					            functions: HashMap::new(),
 | 
				
			||||||
 | 
					            memories: HashMap::new(),
 | 
				
			||||||
 | 
					            constants: HashMap::new(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut rtokens = tokens;
 | 
					
 | 
				
			||||||
 | 
					    pub fn preprocess(&mut self) -> Result<&mut Preprocessor<'a>>{
 | 
				
			||||||
 | 
					        // println!("pre: has do tokens: {:?}", self.program.iter().map(|t| if t.typ == OpType::Keyword(KeywordType::Do) {Some(t)} else {None} ).collect::<Vec<Option<&Operator>>>());
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        let mut program: Vec<Operator> = Vec::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut rtokens = self.program.clone();
 | 
				
			||||||
        rtokens.reverse();
 | 
					        rtokens.reverse();
 | 
				
			||||||
        while !rtokens.is_empty() {
 | 
					        while !rtokens.is_empty() {
 | 
				
			||||||
            let mut token = rtokens.pop().unwrap();
 | 
					            let mut token = rtokens.pop().unwrap();
 | 
				
			||||||
        
 | 
					            // println!("{token:?}");
 | 
				
			||||||
        let op_type = lookup_word(&token.text, &token.loc());
 | 
					            let op_type = token.typ.clone();
 | 
				
			||||||
            match token.clone() {
 | 
					            match token.clone() {
 | 
				
			||||||
            _ if op_type == OpType::Keyword(KeywordType::Macro) => {
 | 
					 | 
				
			||||||
                if rtokens.is_empty(){
 | 
					 | 
				
			||||||
                    lerror!(&token.loc(), "Macro name not found, expected {} but found nothing", TokenType::Word.human());
 | 
					 | 
				
			||||||
                    return Err(eyre!(""));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                let macro_name = rtokens.pop().unwrap();
 | 
					 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                if macro_name.typ != TokenType::Word {
 | 
					 | 
				
			||||||
                    lerror!(¯o_name.loc(), "Bad macro name, expected {} but found {}", TokenType::Word.human(), macro_name.typ.human());
 | 
					 | 
				
			||||||
                    return Err(eyre!(""));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                let word = lookup_word(¯o_name.text, ¯o_name.loc());
 | 
					 | 
				
			||||||
                if word != OpType::Instruction(InstructionType::None) {
 | 
					 | 
				
			||||||
                    lerror!(¯o_name.loc(), "Macro name cannot be a built in word, got '{}'", word.human());
 | 
					 | 
				
			||||||
                    return Err(eyre!(""));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if macros.get(¯o_name.text.clone()).is_some() && crate::constants::ALLOW_MACRO_REDEFINITION {
 | 
					 | 
				
			||||||
                    lerror!(¯o_name.loc(), "Macro redefinition is not allowed");
 | 
					 | 
				
			||||||
                    lnote!(¯os.get(¯o_name.text).unwrap().loc, "First definition here");
 | 
					 | 
				
			||||||
                    return Err(eyre!(""));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let mut macr = Macro{ loc: macro_name.loc(), tokens: Vec::new() };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let mut depth = 0;
 | 
					 | 
				
			||||||
                while !rtokens.is_empty() {
 | 
					 | 
				
			||||||
                    let t = rtokens.pop().unwrap();
 | 
					 | 
				
			||||||
                    let typ = lookup_word(&t.text, &t.loc());
 | 
					 | 
				
			||||||
                    if typ == OpType::Keyword(KeywordType::End) && depth == 0 {
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    } else if typ == OpType::Keyword(KeywordType::End) && depth != 0 {
 | 
					 | 
				
			||||||
                        depth -= 1;
 | 
					 | 
				
			||||||
                        macr.tokens.push(t);
 | 
					 | 
				
			||||||
                    } else if typ == OpType::Keyword(KeywordType::If) || typ == OpType::Keyword(KeywordType::Do) {
 | 
					 | 
				
			||||||
                        macr.tokens.push(t);
 | 
					 | 
				
			||||||
                        depth += 1;
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        macr.tokens.push(t);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                macros.insert(macro_name.text, macr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                _ if op_type == OpType::Keyword(KeywordType::Include) => {
 | 
					                _ if op_type == OpType::Keyword(KeywordType::Include) => {
 | 
				
			||||||
                    if rtokens.is_empty() {
 | 
					                    if rtokens.is_empty() {
 | 
				
			||||||
                    lerror!(&token.loc(), "Include path not found, expected {} but found nothing", TokenType::String.human());
 | 
					                        lerror!(&token.loc, "Include path not found, expected {} but found nothing", TokenType::String.human());
 | 
				
			||||||
                        return Err(eyre!(""));
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    let include_path = rtokens.pop().unwrap();
 | 
					                    let include_path = rtokens.pop().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if include_path.typ != TokenType::String {
 | 
					                    if include_path.tok_typ != TokenType::String {
 | 
				
			||||||
                    lerror!(&include_path.loc(), "Bad include path, expected {} but found {}", TokenType::String.human(), include_path.typ.human());
 | 
					                        lerror!(&include_path.loc, "Bad include path, expected {} but found {}", TokenType::String.human(), include_path.typ.human());
 | 
				
			||||||
                        return Err(eyre!(""));
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let mut in_paths = args.include.clone();
 | 
					                    let mut in_paths = self.args.include.clone();
 | 
				
			||||||
                    in_paths.append(&mut crate::DEFAULT_INCLUDES.to_vec().clone().iter().map(|f| (*f).to_string()).collect::<Vec<String>>());
 | 
					                    in_paths.append(&mut crate::DEFAULT_INCLUDES.to_vec().clone().iter().map(|f| (*f).to_string()).collect::<Vec<String>>());
 | 
				
			||||||
                    
 | 
					                    
 | 
				
			||||||
                    let mut include_code = String::new();
 | 
					                    let mut include_code = String::new();
 | 
				
			||||||
                
 | 
					                    let mut pth = PathBuf::new();
 | 
				
			||||||
                    if include_path.text.chars().collect::<Vec<char>>()[0] == '.' {
 | 
					                    if include_path.text.chars().collect::<Vec<char>>()[0] == '.' {
 | 
				
			||||||
                    let p = Path::new(include_path.file.as_str());
 | 
					                        let p = Path::new(include_path.loc.0.as_str());
 | 
				
			||||||
                        let p = p.parent().unwrap();
 | 
					                        let p = p.parent().unwrap();
 | 
				
			||||||
                        let p = p.join(&include_path.text);
 | 
					                        let p = p.join(&include_path.text);
 | 
				
			||||||
 | 
					                        pth = p.clone();
 | 
				
			||||||
                        include_code = std::fs::read_to_string(p)?;
 | 
					                        include_code = std::fs::read_to_string(p)?;
 | 
				
			||||||
                    } else {   
 | 
					                    } else {   
 | 
				
			||||||
                        for path in in_paths {
 | 
					                        for path in in_paths {
 | 
				
			||||||
                            let p = PathBuf::from(path);
 | 
					                            let p = PathBuf::from(path);
 | 
				
			||||||
                            let p = p.join(&include_path.text);
 | 
					                            let p = p.join(&include_path.text);
 | 
				
			||||||
 | 
					                            pth = p.clone();
 | 
				
			||||||
                            
 | 
					                            
 | 
				
			||||||
                            if p.exists() {
 | 
					                            if p.exists() {
 | 
				
			||||||
                                include_code = std::fs::read_to_string(p)?;
 | 
					                                include_code = std::fs::read_to_string(p)?;
 | 
				
			||||||
| 
						 | 
					@ -117,11 +111,17 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if include_code.is_empty() {
 | 
					                    if include_code.is_empty() {
 | 
				
			||||||
                    lerror!(&include_path.loc(), "Include file in path '{}' was not found or is empty", include_path.text);
 | 
					                        lerror!(&include_path.loc, "Include file in path '{}' was not found or is empty", include_path.text);
 | 
				
			||||||
                        return Err(eyre!(""));
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    let a = pth.to_str().unwrap().to_string();
 | 
				
			||||||
 | 
					                    let code = lex(&include_code, a.as_str(), self.args);
 | 
				
			||||||
 | 
					                    let mut p = parser::Parser::new(code, self.args, Some(self.clone()));
 | 
				
			||||||
 | 
					                    let mut code = p.parse()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let mut code = lex(&include_code, &include_path.text, args, false)?;
 | 
					                    self.set_constants(p.preprocessor.get_constants());
 | 
				
			||||||
 | 
					                    self.set_functions(p.preprocessor.get_functions());
 | 
				
			||||||
 | 
					                    self.set_memories(p.preprocessor.get_memories());
 | 
				
			||||||
                    code.reverse();
 | 
					                    code.reverse();
 | 
				
			||||||
                    rtokens.append(&mut code);
 | 
					                    rtokens.append(&mut code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,30 +129,20 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                _ if op_type == OpType::Keyword(KeywordType::Memory) => {
 | 
					                _ if op_type == OpType::Keyword(KeywordType::Memory) => {
 | 
				
			||||||
                    if rtokens.is_empty() {
 | 
					                    if rtokens.is_empty() {
 | 
				
			||||||
                    lerror!(&token.loc(), "Memory name not found, expected {} but found nothing", TokenType::String.human());
 | 
					                        lerror!(&token.loc, "Memory name not found, expected {} but found nothing", TokenType::String.human());
 | 
				
			||||||
                        return Err(eyre!(""));
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let memory_name = rtokens.pop().unwrap();
 | 
					                    let name = rtokens.pop().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if memory_name.typ != TokenType::Word {
 | 
					                    self.is_word_available(&name, KeywordType::Memory)?;
 | 
				
			||||||
                    lerror!(&memory_name.loc(), "Bad memory name, expected {} but found {}", TokenType::Word.human(), memory_name.typ.human());
 | 
					 | 
				
			||||||
                    return Err(eyre!(""));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if macros.get(&memory_name.text).is_some() {
 | 
					                    let mut code: Vec<Operator> = Vec::new();
 | 
				
			||||||
                    lerror!(&memory_name.loc(), "Memory name cannot replace macro name, got {}", memory_name.text);
 | 
					 | 
				
			||||||
                    let m = macros.get(&memory_name.text).unwrap();
 | 
					 | 
				
			||||||
                    linfo!(&m.loc, "Macro found here");
 | 
					 | 
				
			||||||
                    return Err(eyre!(""));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let mut code: Vec<Token> = Vec::new();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    let mut depth = 0;
 | 
					                    let mut depth = 0;
 | 
				
			||||||
                    while !rtokens.is_empty() {
 | 
					                    while !rtokens.is_empty() {
 | 
				
			||||||
                        let t = rtokens.pop().unwrap();
 | 
					                        let t = rtokens.pop().unwrap();
 | 
				
			||||||
                    let typ = lookup_word(&t.text, &t.loc());
 | 
					                        let typ = t.typ.clone();
 | 
				
			||||||
                        if typ == OpType::Keyword(KeywordType::End) && depth == 0 {
 | 
					                        if typ == OpType::Keyword(KeywordType::End) && depth == 0 {
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        } else if typ == OpType::Keyword(KeywordType::End) && depth != 0 {
 | 
					                        } else if typ == OpType::Keyword(KeywordType::End) && depth != 0 {
 | 
				
			||||||
| 
						 | 
					@ -167,29 +157,155 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    let res = precompile(&code)?;
 | 
					                    let res = precompile(&code)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if res.len() != 1 {
 | 
					                    if res.len() != 1 {
 | 
				
			||||||
                    lerror!(&token.loc(), "Expected 1 number, got {:?}", res);
 | 
					                        lerror!(&token.loc, "Expected 1 number, got {:?}", res);
 | 
				
			||||||
                        return Err(eyre!(""));
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                token.value = Some(res[0]);
 | 
					                    token.value = res[0];
 | 
				
			||||||
                token.addr = Some(memories.len());
 | 
					                    token.addr = Some(self.memories.len());
 | 
				
			||||||
                program.push(token);
 | 
					                    program.push(token.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                memories.insert(memory_name.text, memories.len());
 | 
					                    self.memories.insert(name.text, Memory { loc: token.loc, id: self.memories.len() });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                _ if op_type == OpType::Keyword(KeywordType::Function) => {
 | 
				
			||||||
 | 
					                    if rtokens.is_empty() {
 | 
				
			||||||
 | 
					                        lerror!(&token.loc, "Function name not found, expected {} but found nothing", TokenType::Word.human());
 | 
				
			||||||
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let mut name = rtokens.pop().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if let '0'..='9' = name.text.chars().next().unwrap() {
 | 
				
			||||||
 | 
					                        lerror!(&name.loc, "Function name starts with a number which is not allowed");
 | 
				
			||||||
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // let mut should_warn = false;
 | 
				
			||||||
 | 
					                    for c in name.text.clone().chars() {
 | 
				
			||||||
 | 
					                        match c {
 | 
				
			||||||
 | 
					                            'a'..='z' |
 | 
				
			||||||
 | 
					                            'A'..='Z' |
 | 
				
			||||||
 | 
					                            '0'..='9' |
 | 
				
			||||||
 | 
					                            '-' | '_' => (),
 | 
				
			||||||
 | 
					                            '(' | ')' => {
 | 
				
			||||||
 | 
					                                name.text = name.text.clone().replace('(', "__OP_PAREN__").replace(')', "__CL_PAREN__");
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
                            _ => {
 | 
					                            _ => {
 | 
				
			||||||
 | 
					                                lerror!(&name.loc, "Function name contains '{c}', which is unsupported");
 | 
				
			||||||
 | 
					                                return Err(eyre!(""));
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    // if should_warn {
 | 
				
			||||||
 | 
					                        //TODO: add -W option in cli args to enable more warnings
 | 
				
			||||||
 | 
					                        //lwarn!(&function_name.loc, "Function name contains '(' or ')', this character is not supported but will be replaced with '__OP_PAREN__' or '__CL_PAREN__' respectively ");
 | 
				
			||||||
 | 
					                    // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    self.is_word_available(&name, KeywordType::Function)?;
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    self.functions.insert(name.text.clone(), Function{
 | 
				
			||||||
 | 
					                        loc: name.loc.clone(),
 | 
				
			||||||
 | 
					                        name: name.text.clone(),
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let mut fn_def = token.clone();
 | 
				
			||||||
 | 
					                    fn_def.typ = OpType::Keyword(KeywordType::FunctionDef);
 | 
				
			||||||
 | 
					                    fn_def.text = name.text;
 | 
				
			||||||
 | 
					                    // println!("{:?}", token);
 | 
				
			||||||
 | 
					                    program.push(fn_def);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                _ if op_type == OpType::Keyword(KeywordType::Constant) => {
 | 
				
			||||||
 | 
					                    if rtokens.is_empty() {
 | 
				
			||||||
 | 
					                        lerror!(&token.loc, "Constant name not found, expected {} but found nothing", TokenType::Word.human());
 | 
				
			||||||
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    // println!("{token:?}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let mut name = rtokens.pop().unwrap();
 | 
				
			||||||
 | 
					                    // let mut should_warn = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if let '0'..='9' = name.text.chars().next().unwrap() {
 | 
				
			||||||
 | 
					                        lerror!(&name.loc, "Constant name starts with a number which is not allowed");
 | 
				
			||||||
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    for c in name.text.clone().chars() {
 | 
				
			||||||
 | 
					                        match c {
 | 
				
			||||||
 | 
					                            'a'..='z' |
 | 
				
			||||||
 | 
					                            'A'..='Z' |
 | 
				
			||||||
 | 
					                            '0'..='9' |
 | 
				
			||||||
 | 
					                            '-' | '_' => (),
 | 
				
			||||||
 | 
					                            '(' | ')' => {
 | 
				
			||||||
 | 
					                                // should_warn = true;
 | 
				
			||||||
 | 
					                                name.text = name.text.clone().replace('(', "__OP_PAREN__").replace(')', "__CL_PAREN__");
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            _ => {
 | 
				
			||||||
 | 
					                                lerror!(&name.loc, "Constant name contains '{c}', which is unsupported");
 | 
				
			||||||
 | 
					                                return Err(eyre!(""));
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    // if should_warn {
 | 
				
			||||||
 | 
					                        //TODO: add -W option in cli args to enable more warnings
 | 
				
			||||||
 | 
					                        //lwarn!(&name.loc, "Constant name contains '(' or ')', this character is not supported but will be replaced with '__OP_PAREN__' or '__CL_PAREN__' respectively ");
 | 
				
			||||||
 | 
					                    // }
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    self.is_word_available(&name, KeywordType::Constant)?;
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    self.constants.insert(name.text.clone(), Constant{
 | 
				
			||||||
 | 
					                        loc: name.loc.clone(),
 | 
				
			||||||
 | 
					                        name: name.text.clone(),
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // println!("{:?}", self.constants);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let mut const_def = token.clone();
 | 
				
			||||||
 | 
					                    const_def.typ = OpType::Keyword(KeywordType::ConstantDef);
 | 
				
			||||||
 | 
					                    const_def.text = name.text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let item = rtokens.pop().unwrap();
 | 
				
			||||||
 | 
					                    if item.tok_typ == TokenType::Int {
 | 
				
			||||||
 | 
					                        const_def.value = item.value;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        lerror!(&token.loc, "For now only {:?} is allowed in constants", TokenType::Int);
 | 
				
			||||||
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let posibly_end = rtokens.pop();
 | 
				
			||||||
 | 
					                    // println!("end: {posibly_end:?}");
 | 
				
			||||||
 | 
					                    if posibly_end.is_none() || posibly_end.unwrap().typ != OpType::Keyword(KeywordType::End) {
 | 
				
			||||||
 | 
					                        lerror!(&token.loc, "Constant was not closed with an 'end' instruction, expected 'end' but found nothing");
 | 
				
			||||||
 | 
					                        return Err(eyre!(""));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    // token.value = 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    program.push(const_def);
 | 
				
			||||||
 | 
					                }  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                _ => {
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
                    program.push(token);
 | 
					                    program.push(token);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        self.program = program;
 | 
				
			||||||
 | 
					        // println!("has do tokens: {:?}", self.program.iter().map(|t| if t.typ == OpType::Keyword(KeywordType::Do) {Some(t)} else {None} ).collect::<Vec<Option<&Operator>>>());
 | 
				
			||||||
        //* Feel free to fix this horrifying shit
 | 
					        //* Feel free to fix this horrifying shit
 | 
				
			||||||
        //* i wanna kms
 | 
					        //* i wanna kms
 | 
				
			||||||
        let mut times = 0;
 | 
					        let mut times = 0;
 | 
				
			||||||
    while program.iter().map(|f| {
 | 
					        // dbg!(program.clone());
 | 
				
			||||||
        if f.typ == TokenType::Word && f.op_typ != InstructionType::MemUse {
 | 
					        while self.program.iter().map(|f| {
 | 
				
			||||||
            lookup_word(&f.text, &f.loc())
 | 
					            if f.tok_typ == TokenType::Word && 
 | 
				
			||||||
 | 
					                f.typ != OpType::Instruction(InstructionType::FnCall) && 
 | 
				
			||||||
 | 
					                f.typ != OpType::Instruction(InstructionType::MemUse) &&
 | 
				
			||||||
 | 
					                f.typ != OpType::Keyword(KeywordType::FunctionDef) &&
 | 
				
			||||||
 | 
					                f.typ != OpType::Keyword(KeywordType::ConstantDef) &&
 | 
				
			||||||
 | 
					                f.typ != OpType::Instruction(InstructionType::ConstUse) {
 | 
				
			||||||
 | 
					                lookup_word(&f.text, &f.loc)
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                OpType::Instruction(InstructionType::PushInt) // i hate myself, this is a randomly picked optype so its happy and works
 | 
					                OpType::Instruction(InstructionType::PushInt) // i hate myself, this is a randomly picked optype so its happy and works
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -200,56 +316,160 @@ pub fn preprocess(tokens: Vec<Token>, args: &Args) -> Result<Vec<Token>>{
 | 
				
			||||||
                warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it");
 | 
					                warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it");
 | 
				
			||||||
                break
 | 
					                break
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        program = expand(program, ¯os, &memories)?;
 | 
					            self.expand()?;
 | 
				
			||||||
            times += 1;
 | 
					            times += 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        Ok(self)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn expand(&mut self) -> Result<()> {
 | 
				
			||||||
    Ok(program)
 | 
					        let mut program: Vec<Operator> = Vec::new();
 | 
				
			||||||
}
 | 
					        // println!("{:?}", self.functions);
 | 
				
			||||||
 | 
					        let mut rtokens = self.program.clone();
 | 
				
			||||||
pub fn expand(tokens: Vec<Token>, macros: &Macros, mems: &Memories) -> Result<Vec<Token>> {
 | 
					 | 
				
			||||||
    let mut program: Vec<Token> = Vec::new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let mut rtokens = tokens;
 | 
					 | 
				
			||||||
        rtokens.reverse();
 | 
					        rtokens.reverse();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while !rtokens.is_empty() {
 | 
					        while !rtokens.is_empty() {
 | 
				
			||||||
            let op = rtokens.pop().unwrap();
 | 
					            let op = rtokens.pop().unwrap();
 | 
				
			||||||
        let op_type = lookup_word(&op.text, &op.loc());
 | 
					            let op_type = op.typ.clone();
 | 
				
			||||||
        if op.typ == TokenType::Word {
 | 
					            if op.tok_typ == TokenType::Word {
 | 
				
			||||||
                match op_type {
 | 
					                match op_type {
 | 
				
			||||||
                    OpType::Instruction(InstructionType::None) => {
 | 
					                    OpType::Instruction(InstructionType::None) => {
 | 
				
			||||||
                    let m = macros.get(&op.text);
 | 
					                        let m = self.functions.get(&op.text);
 | 
				
			||||||
                    let mem = mems.get(&op.text);
 | 
					                        let mem = self.memories.get(&op.text);
 | 
				
			||||||
 | 
					                        let cons = self.constants.get(&op.text);
 | 
				
			||||||
                        if let Some(m) = m {
 | 
					                        if let Some(m) = m {
 | 
				
			||||||
                        program.append(&mut m.tokens.clone());
 | 
					                            // println!("------ FOUND FUNCTION {} -----------", m.name);
 | 
				
			||||||
                    } else 
 | 
					                            let mut t = op.clone();
 | 
				
			||||||
                    if let Some(mem) = mem {
 | 
					                            t.typ = OpType::Instruction(InstructionType::FnCall);
 | 
				
			||||||
                        let mut t = op;
 | 
					                            t.text = m.name.clone();
 | 
				
			||||||
                        t.addr = Some(*mem);
 | 
					                            program.push(t.clone());
 | 
				
			||||||
                        t.op_typ = InstructionType::MemUse;
 | 
					
 | 
				
			||||||
 | 
					                            // println!("##### {:?}", t);
 | 
				
			||||||
 | 
					                        } else if let Some(mem) = mem {
 | 
				
			||||||
 | 
					                            let mut t = op.clone();
 | 
				
			||||||
 | 
					                            t.addr = Some(mem.deref().id);
 | 
				
			||||||
 | 
					                            t.typ = OpType::Instruction(InstructionType::MemUse);
 | 
				
			||||||
                            program.push(t);
 | 
					                            program.push(t);
 | 
				
			||||||
                    }
 | 
					                        } else if let Some(cons) = cons {
 | 
				
			||||||
                    else {
 | 
					                            let mut t = op.clone();
 | 
				
			||||||
                        lerror!(&op.loc(), "Unknown word '{}'", op.text.clone());
 | 
					                            t.text = cons.deref().name.clone();
 | 
				
			||||||
 | 
					                            t.typ = OpType::Instruction(InstructionType::ConstUse);
 | 
				
			||||||
 | 
					                            program.push(t);
 | 
				
			||||||
 | 
					                            
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            lerror!(&op.loc, "Preprocess: Unknown word '{}'", op.text.clone());
 | 
				
			||||||
                            return Err(eyre!(""));
 | 
					                            return Err(eyre!(""));
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    _ => {
 | 
					                    _ => {
 | 
				
			||||||
                    program.push(op);
 | 
					                        program.push(op.clone());
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
            program.push(op);
 | 
					                program.push(op.clone());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
 | 
					            // if op.typ == OpType::Keyword(KeywordType::Do) {
 | 
				
			||||||
 | 
					            //     println!("expand: {:?}", op);
 | 
				
			||||||
 | 
					            //     program.push(op.clone());
 | 
				
			||||||
 | 
					            // }
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        // println!("expand: has do tokens: {:?}", program.iter().map(|t| if t.typ == OpType::Keyword(KeywordType::Do) {Some(t)} else {None} ).collect::<Vec<Option<&Operator>>>());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.program = program;
 | 
				
			||||||
 | 
					        // println!("{:#?}", self.program);
 | 
				
			||||||
 | 
					        // println!("{:?}", self.program.last().unwrap());
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn get_ops(&mut self) -> Vec<Operator> {
 | 
				
			||||||
 | 
					        self.program.clone()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn is_word_available(&self, word: &Operator, typ: KeywordType) -> Result<bool> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match typ {
 | 
				
			||||||
 | 
					            KeywordType::Memory |
 | 
				
			||||||
 | 
					            KeywordType::Constant |
 | 
				
			||||||
 | 
					            KeywordType::Function => (),
 | 
				
			||||||
 | 
					            _ => panic!()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    Ok(program)
 | 
					        if word.tok_typ != TokenType::Word {
 | 
				
			||||||
 | 
					            lerror!(&word.loc, "Bad {typ:?}, expected {} but found {}", TokenType::Word.human(), word.typ.human());
 | 
				
			||||||
 | 
					            if crate::DEV_MODE {println!("{word:?}")}
 | 
				
			||||||
 | 
					            return Err(eyre!(""));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let w = lookup_word(&word.text, &word.loc);
 | 
				
			||||||
 | 
					        if w != OpType::Instruction(InstructionType::None) {
 | 
				
			||||||
 | 
					            lerror!(&word.loc, "Bad {typ:?}, {typ:?} definition cannot be builtin word, got {:?}", word.text);
 | 
				
			||||||
 | 
					            if crate::DEV_MODE {println!("{word:?}")}
 | 
				
			||||||
 | 
					            return Err(eyre!(""));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let m = self.memories.get(&word.text);
 | 
				
			||||||
 | 
					        if let Some(m) = m {
 | 
				
			||||||
 | 
					            if typ == KeywordType::Memory {
 | 
				
			||||||
 | 
					                lerror!(&word.loc, "Memories cannot be redefined, got {}", word.text);
 | 
				
			||||||
 | 
					                linfo!(&m.loc, "first definition here"); 
 | 
				
			||||||
 | 
					                if crate::DEV_MODE {println!("{word:?}")}
 | 
				
			||||||
 | 
					                return Err(eyre!(""));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            lerror!(&word.loc, "{typ:?} cannot replace memory, got {}", word.text);
 | 
				
			||||||
 | 
					            linfo!(&m.loc, "first definition here"); 
 | 
				
			||||||
 | 
					            if crate::DEV_MODE {println!("{word:?}")}
 | 
				
			||||||
 | 
					            return Err(eyre!(""));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        let f = self.functions.get(&word.text);
 | 
				
			||||||
 | 
					        if let Some(f) = f {
 | 
				
			||||||
 | 
					            if typ == KeywordType::Function {
 | 
				
			||||||
 | 
					                lerror!(&word.loc, "Functions cannot be redefined, got {}", word.text);
 | 
				
			||||||
 | 
					                linfo!(&f.loc, "first definition here"); 
 | 
				
			||||||
 | 
					                if crate::DEV_MODE {println!("{word:?}")}
 | 
				
			||||||
 | 
					                return Err(eyre!(""));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            lerror!(&word.loc, "{typ:?} cannot replace function, got {}", word.text);
 | 
				
			||||||
 | 
					            linfo!(&f.loc, "first definition here"); 
 | 
				
			||||||
 | 
					            if crate::DEV_MODE {println!("{word:?}")}
 | 
				
			||||||
 | 
					            return Err(eyre!(""));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        let c = self.constants.get(&word.text);
 | 
				
			||||||
 | 
					        if let Some(c) = c {
 | 
				
			||||||
 | 
					            if typ == KeywordType::Constant {
 | 
				
			||||||
 | 
					                lerror!(&word.loc, "Constants cannot be redefined, got {}", word.text);
 | 
				
			||||||
 | 
					                linfo!(&c.loc, "first definition here"); 
 | 
				
			||||||
 | 
					                if crate::DEV_MODE {println!("{word:?}")}
 | 
				
			||||||
 | 
					                return Err(eyre!(""));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            lerror!(&word.loc, "{typ:?} cannot replace constant, got {}", word.text);
 | 
				
			||||||
 | 
					            linfo!(&c.loc, "first definition here"); 
 | 
				
			||||||
 | 
					            if crate::DEV_MODE {println!("{word:?}")}
 | 
				
			||||||
 | 
					            return Err(eyre!(""));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(true)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn set_functions(&mut self, f: Functions) {
 | 
				
			||||||
 | 
					        self.functions = f;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn set_constants(&mut self, f: Constants) {
 | 
				
			||||||
 | 
					        self.constants = f;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn set_memories(&mut self, f: Memories) {
 | 
				
			||||||
 | 
					        self.memories = f;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn get_functions(&mut self) -> Functions {
 | 
				
			||||||
 | 
					        self.functions.clone()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn get_constants(&mut self) -> Constants {
 | 
				
			||||||
 | 
					        self.constants.clone()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn get_memories(&mut self) -> Memories{
 | 
				
			||||||
 | 
					        self.memories.clone()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,35 +1,182 @@
 | 
				
			||||||
use crate::{constants::{Operator, Types, OpType, KeywordType, InstructionType}, Args, lerror, warn};
 | 
					use std::collections::HashMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::{constants::{Operator, Types, OpType, KeywordType, InstructionType, Loc}, Args, lerror, warn};
 | 
				
			||||||
use color_eyre::Result;
 | 
					use color_eyre::Result;
 | 
				
			||||||
use eyre::eyre;
 | 
					use eyre::eyre;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[allow(dead_code)]
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Function {
 | 
				
			||||||
 | 
					    loc: Loc,
 | 
				
			||||||
 | 
					    args: Vec<Types>,
 | 
				
			||||||
 | 
					    returns: Vec<Types>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn typecheck(ops: &[Operator], args: &Args) -> Result<Vec<Operator>>{
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Constant {
 | 
				
			||||||
 | 
					    #[allow(dead_code)]
 | 
				
			||||||
 | 
					    loc: Loc,
 | 
				
			||||||
 | 
					    types: Vec<Types>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Function {
 | 
				
			||||||
 | 
					    #[allow(dead_code)]
 | 
				
			||||||
 | 
					    pub fn default() -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            args: Vec::new(),
 | 
				
			||||||
 | 
					            returns: Vec::new(),
 | 
				
			||||||
 | 
					            loc: (String::new(), 0, 0)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Functions = HashMap<String, Function>;
 | 
				
			||||||
 | 
					type Constants = HashMap<String, Constant>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn typecheck(ops: Vec<Operator>, args: &Args, init_types: Option<Vec<Types>>,  funcs: HashMap<String, Function>, consts:  HashMap<String, Constant>) -> Result<(Vec<Types>, Functions, Constants)>{
 | 
				
			||||||
    if args.unsaf {
 | 
					    if args.unsaf {
 | 
				
			||||||
        if !args.quiet {
 | 
					        if !args.quiet {
 | 
				
			||||||
            warn!("Unsafe mode enabled, disabling typechecker, goodluck");
 | 
					            warn!("Unsafe mode enabled, disabling typechecker, goodluck");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return Ok(ops.to_vec());
 | 
					        return Ok((Vec::new(), HashMap::new(), HashMap::new()));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    let mut stack: Vec<Types> = Vec::new();
 | 
					    let mut functions: HashMap<String, Function> = funcs;
 | 
				
			||||||
 | 
					    let mut constants: HashMap<String, Constant> = consts;
 | 
				
			||||||
    for op in ops {
 | 
					    // let mut in_function: (String, Function, Loc) = (String::new(), Function::default(), (String::new(), 0, 0));
 | 
				
			||||||
 | 
					    let mut stack: Vec<Types> = if let Some(i) = init_types {i} else {Vec::new()};
 | 
				
			||||||
 | 
					    let mut stack_snapshots: Vec<Vec<Types>> = Vec::new();
 | 
				
			||||||
 | 
					    let mut rtokens = ops;
 | 
				
			||||||
 | 
					    rtokens.reverse();
 | 
				
			||||||
 | 
					    // println!("{:#?}", ops);
 | 
				
			||||||
 | 
					    while !rtokens.is_empty() {
 | 
				
			||||||
 | 
					        let op = rtokens.pop().unwrap();
 | 
				
			||||||
 | 
					        // println!("{:?}", stack.clone());
 | 
				
			||||||
 | 
					        // println!("{:?}", op);
 | 
				
			||||||
 | 
					        // println!("{}", ops.len());
 | 
				
			||||||
        match op.typ.clone() {
 | 
					        match op.typ.clone() {
 | 
				
			||||||
            OpType::Keyword(keyword) => {
 | 
					            OpType::Keyword(keyword) => {
 | 
				
			||||||
                match keyword {
 | 
					                match keyword {
 | 
				
			||||||
                    KeywordType::If => {
 | 
					                    KeywordType::If |
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Bool])?;
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    KeywordType::Do => {
 | 
					                    KeywordType::Do => {
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Bool])?;
 | 
					                        stack_pop(&mut stack, &op, &[Types::Bool])?;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    KeywordType::FunctionDef => {
 | 
				
			||||||
 | 
					                        let name = op.text.clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if let Some(p) = rtokens.pop() {
 | 
				
			||||||
 | 
					                            if p.typ != OpType::Instruction(InstructionType::With){
 | 
				
			||||||
 | 
					                                lerror!(&op.loc, "Expected {:?}, got {:?}", OpType::Instruction(InstructionType::With), p.typ);
 | 
				
			||||||
 | 
					                                return Err(eyre!(""));
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            lerror!(&op.loc, "Expected {:?}, got nothing", OpType::Instruction(InstructionType::With));
 | 
				
			||||||
 | 
					                            return Err(eyre!(""));
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        let mut p = rtokens.pop();
 | 
				
			||||||
 | 
					                        let mut func = Function {
 | 
				
			||||||
 | 
					                            args: Vec::new(),
 | 
				
			||||||
 | 
					                            returns: Vec::new(),
 | 
				
			||||||
 | 
					                            loc: op.loc
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        let mut return_args = false;
 | 
				
			||||||
 | 
					                        while p.as_ref().is_some() {
 | 
				
			||||||
 | 
					                            let op = p.as_ref().unwrap();
 | 
				
			||||||
 | 
					                            if op.typ == OpType::Instruction(InstructionType::TypeBool) ||
 | 
				
			||||||
 | 
					                                op.typ == OpType::Instruction(InstructionType::TypeInt) ||
 | 
				
			||||||
 | 
					                                op.typ == OpType::Instruction(InstructionType::TypePtr) ||
 | 
				
			||||||
 | 
					                                op.typ == OpType::Instruction(InstructionType::TypeAny) ||
 | 
				
			||||||
 | 
					                                op.typ == OpType::Instruction(InstructionType::TypeVoid) {
 | 
				
			||||||
 | 
					                                    let t = if op.typ == OpType::Instruction(InstructionType::TypeInt) {
 | 
				
			||||||
 | 
					                                        Types::Int
 | 
				
			||||||
 | 
					                                    } else if op.typ == OpType::Instruction(InstructionType::TypeBool) {
 | 
				
			||||||
 | 
					                                        Types::Bool
 | 
				
			||||||
 | 
					                                    } else if op.typ == OpType::Instruction(InstructionType::TypePtr) {
 | 
				
			||||||
 | 
					                                        Types::Ptr
 | 
				
			||||||
 | 
					                                    } else if op.typ == OpType::Instruction(InstructionType::TypeVoid) {
 | 
				
			||||||
 | 
					                                        if return_args {
 | 
				
			||||||
 | 
					                                            func.returns = vec![Types::Void];
 | 
				
			||||||
 | 
					                                        } else {
 | 
				
			||||||
 | 
					                                            func.args = vec![Types::Void];
 | 
				
			||||||
 | 
					                                            return_args = true;
 | 
				
			||||||
 | 
					                                            continue;
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                        Types::Void
 | 
				
			||||||
 | 
					                                    } else if op.typ == OpType::Instruction(InstructionType::TypeStr) {
 | 
				
			||||||
 | 
					                                        Types::Str
 | 
				
			||||||
 | 
					                                    } else if op.typ == OpType::Instruction(InstructionType::TypeAny) {
 | 
				
			||||||
 | 
					                                        Types::Any
 | 
				
			||||||
 | 
					                                    } else {
 | 
				
			||||||
 | 
					                                        panic!()
 | 
				
			||||||
 | 
					                                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                    if return_args {
 | 
				
			||||||
 | 
					                                        func.returns.push(t);
 | 
				
			||||||
 | 
					                                    } else {
 | 
				
			||||||
 | 
					                                        func.args.push(t);
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                                
 | 
				
			||||||
 | 
					                            if op.typ == OpType::Instruction(InstructionType::Returns) {
 | 
				
			||||||
 | 
					                                return_args = true;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            if op.typ == OpType::Keyword(KeywordType::FunctionThen) {
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            p = rtokens.pop();
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        let mut code: Vec<Operator> = Vec::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        while !rtokens.is_empty() {
 | 
				
			||||||
 | 
					                            let op = rtokens.pop().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            if op.typ == OpType::Keyword(KeywordType::FunctionDone) {
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            code.push(op);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        let ts = if func.args.clone() == vec![Types::Void] {
 | 
				
			||||||
 | 
					                            Vec::new()
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            func.args.clone()
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if ts.contains(&Types::Void) {
 | 
				
			||||||
 | 
					                            continue;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        functions.insert(name.clone(), func.clone());
 | 
				
			||||||
 | 
					                        let (ret_typs, _, _) = typecheck(code, args, Some(ts.clone()), functions.clone(), constants.clone())?;
 | 
				
			||||||
 | 
					                        if ret_typs != func.returns && !func.returns.contains(&Types::Void){
 | 
				
			||||||
 | 
					                            lerror!(&func.loc, "Expected {:?}, but got {:?}", func.returns, ret_typs);
 | 
				
			||||||
 | 
					                            return Err(eyre!(""))
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if !func.args.contains(&Types::Void) {
 | 
				
			||||||
 | 
					                            stack.append(&mut func.args);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        stack_snapshots.push(stack.clone());
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    KeywordType::Else |
 | 
					                    KeywordType::Else |
 | 
				
			||||||
                    KeywordType::End |
 | 
					                    KeywordType::End |
 | 
				
			||||||
                    KeywordType::While |
 | 
					                    KeywordType::While |
 | 
				
			||||||
                    KeywordType::Macro |
 | 
					 | 
				
			||||||
                    KeywordType::Include |
 | 
					                    KeywordType::Include |
 | 
				
			||||||
 | 
					                    KeywordType::Constant |
 | 
				
			||||||
                    KeywordType::Memory => (),
 | 
					                    KeywordType::Memory => (),
 | 
				
			||||||
 | 
					                    KeywordType::ConstantDef => {
 | 
				
			||||||
 | 
					                        // println!("defined constant");
 | 
				
			||||||
 | 
					                        constants.insert(op.text, Constant { loc: op.loc.clone(), types: vec![Types::Int] });
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    KeywordType::FunctionThen |
 | 
				
			||||||
 | 
					                    KeywordType::FunctionDone |
 | 
				
			||||||
 | 
					                    KeywordType::Function => unreachable!(),
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            OpType::Instruction(instruction) => {
 | 
					            OpType::Instruction(instruction) => {
 | 
				
			||||||
| 
						 | 
					@ -73,85 +220,42 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result<Vec<Operator>>{
 | 
				
			||||||
                        stack.push(a);
 | 
					                        stack.push(a);
 | 
				
			||||||
                        stack.push(b);
 | 
					                        stack.push(b);
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Minus => {
 | 
					                    InstructionType::Minus |
 | 
				
			||||||
 | 
					                    InstructionType::Plus |
 | 
				
			||||||
 | 
					                    InstructionType::Band |
 | 
				
			||||||
 | 
					                    InstructionType::Bor |
 | 
				
			||||||
 | 
					                    InstructionType::Shr |
 | 
				
			||||||
 | 
					                    InstructionType::Shl |
 | 
				
			||||||
 | 
					                    InstructionType::Mul => {
 | 
				
			||||||
 | 
					                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
					                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
 | 
					 | 
				
			||||||
                        stack.push(Types::Int);
 | 
					                        stack.push(Types::Int);
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Plus => {
 | 
					                    InstructionType::Equals |
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
					                    InstructionType::Gt |
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
 | 
					                    InstructionType::Lt |
 | 
				
			||||||
                        stack.push(Types::Int);
 | 
					                    InstructionType::Ge |
 | 
				
			||||||
                    },
 | 
					                    InstructionType::Le |
 | 
				
			||||||
                    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 => {
 | 
					                    InstructionType::NotEquals => {
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
 | 
					                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?;
 | 
					                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
				
			||||||
                        stack.push(Types::Bool);
 | 
					                        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 => {
 | 
					                    InstructionType::DivMod => {
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
					                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
					                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
				
			||||||
                        stack.push(Types::Int);
 | 
					                        stack.push(Types::Int);
 | 
				
			||||||
                        stack.push(Types::Int);
 | 
					                        stack.push(Types::Int);
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Mul => {
 | 
					                    InstructionType::Load8 |
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
					                    InstructionType::Load32 |
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
					                    InstructionType::Load64 => {
 | 
				
			||||||
                        stack.push(Types::Int);
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    InstructionType::Mem => {
 | 
					 | 
				
			||||||
                        stack.push(Types::Ptr);
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    InstructionType::Load8 => {
 | 
					 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Ptr])?;
 | 
					                        stack_pop(&mut stack, &op, &[Types::Ptr])?;
 | 
				
			||||||
                        stack.push(Types::Int);
 | 
					                        stack.push(Types::Int);
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::Store8 => {
 | 
					                    InstructionType::Store8 |
 | 
				
			||||||
 | 
					                    InstructionType::Store32 |
 | 
				
			||||||
 | 
					                    InstructionType::Store64 => {
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
					                        stack_pop(&mut stack, &op, &[Types::Int])?;
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Ptr])?;
 | 
					                        stack_pop(&mut stack, &op, &[Types::Ptr])?;
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
| 
						 | 
					@ -216,16 +320,63 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result<Vec<Operator>>{
 | 
				
			||||||
                        stack_pop(&mut stack, &op, &[Types::Any])?;
 | 
					                        stack_pop(&mut stack, &op, &[Types::Any])?;
 | 
				
			||||||
                        stack.push(Types::Int);
 | 
					                        stack.push(Types::Int);
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
 | 
					                    InstructionType::CastVoid => {
 | 
				
			||||||
 | 
					                        stack_pop(&mut stack, &op, &[Types::Any])?;
 | 
				
			||||||
 | 
					                        stack.push(Types::Any);
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
                    InstructionType::MemUse => {
 | 
					                    InstructionType::MemUse => {
 | 
				
			||||||
                        stack.push(Types::Ptr);
 | 
					                        stack.push(Types::Ptr);
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    InstructionType::None => {},
 | 
					                    InstructionType::FnCall  => {
 | 
				
			||||||
 | 
					                        stack_snapshots.push(stack.clone());
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        let f = functions.get(&op.text).unwrap().clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // in_function = (op.text.clone(), f.clone(), op.loc.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        let mut s = stack.clone();
 | 
				
			||||||
 | 
					                        let mut a = f.args.clone();
 | 
				
			||||||
 | 
					                        // s.reverse();
 | 
				
			||||||
 | 
					                        a.reverse();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        for t in a{
 | 
				
			||||||
 | 
					                            if let Some(s2) = s.pop(){
 | 
				
			||||||
 | 
					                                if t != s2 {
 | 
				
			||||||
 | 
					                                    lerror!(&op.loc, "Expected {:?}, but got {:?}", t, s2);
 | 
				
			||||||
 | 
					                                    return Err(eyre!(""));
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
            },
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                lerror!(&op.loc, "Expected {:?}, but got nothing", t);
 | 
				
			||||||
 | 
					                                return Err(eyre!(""));
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(ops.to_vec())
 | 
					                        
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    InstructionType::Return |
 | 
				
			||||||
 | 
					                    InstructionType::None |
 | 
				
			||||||
 | 
					                    InstructionType::TypeBool |
 | 
				
			||||||
 | 
					                    InstructionType::TypePtr |
 | 
				
			||||||
 | 
					                    InstructionType::TypeInt |
 | 
				
			||||||
 | 
					                    InstructionType::TypeVoid |
 | 
				
			||||||
 | 
					                    InstructionType::TypeAny |
 | 
				
			||||||
 | 
					                    InstructionType::TypeStr |
 | 
				
			||||||
 | 
					                    InstructionType::Returns |
 | 
				
			||||||
 | 
					                    InstructionType::With => (),
 | 
				
			||||||
 | 
					                    InstructionType::ConstUse => {
 | 
				
			||||||
 | 
					                        // println!("{constants:?}");
 | 
				
			||||||
 | 
					                        let mut c = constants.get(&op.text).unwrap().clone();
 | 
				
			||||||
 | 
					                        stack.append(&mut c.types);
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    Ok((stack, functions, constants))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								src/util.rs
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/util.rs
									
									
									
									
									
								
							| 
						 | 
					@ -66,6 +66,21 @@ pub mod logger {
 | 
				
			||||||
    pub fn lnote<P: Deref<Target = Loc>>(loc: P, msg: &str) {
 | 
					    pub fn lnote<P: Deref<Target = Loc>>(loc: P, msg: &str) {
 | 
				
			||||||
        println!("{f}:{r}:{c} {blue}note{rs}: {msg}", blue=color::FG_BLUE, rs=color::RESET, f=loc.0, r=loc.1, c=loc.2);
 | 
					        println!("{f}:{r}:{c} {blue}note{rs}: {msg}", blue=color::FG_BLUE, rs=color::RESET, f=loc.0, r=loc.1, c=loc.2);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn help(msg: &str) {
 | 
				
			||||||
 | 
					        println!("{blue}help{r}: {msg}", blue=color::FG_CYAN, r=color::RESET);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn code_block(code: &str) -> String {
 | 
				
			||||||
 | 
					        let mut ret = String::new();
 | 
				
			||||||
 | 
					        let lines = code.lines();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (i, line) in lines.enumerate() {
 | 
				
			||||||
 | 
					            use std::fmt::Write;
 | 
				
			||||||
 | 
					            writeln!(ret, "{}{} | {}{}",color::FG_BLUE, i + 1, line, color::RESET).unwrap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        ret
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    pub mod macros {
 | 
					    pub mod macros {
 | 
				
			||||||
        #[macro_export] macro_rules! error { ($($arg:tt)*) => { $crate::util::logger::error(std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
					        #[macro_export] macro_rules! error { ($($arg:tt)*) => { $crate::util::logger::error(std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
				
			||||||
        #[macro_export] macro_rules! warn { ($($arg:tt)*) => {  $crate::util::logger::warn( std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
					        #[macro_export] macro_rules! warn { ($($arg:tt)*) => {  $crate::util::logger::warn( std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
				
			||||||
| 
						 | 
					@ -76,6 +91,9 @@ pub mod logger {
 | 
				
			||||||
        #[macro_export] macro_rules! lwarn { ($dst:expr, $($arg:tt)*) => {  $crate::util::logger::lwarn($dst, std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
					        #[macro_export] macro_rules! lwarn { ($dst:expr, $($arg:tt)*) => {  $crate::util::logger::lwarn($dst, std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
				
			||||||
        #[macro_export] macro_rules! linfo { ($dst:expr, $($arg:tt)*) => {  $crate::util::logger::linfo($dst, std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
					        #[macro_export] macro_rules! linfo { ($dst:expr, $($arg:tt)*) => {  $crate::util::logger::linfo($dst, std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
				
			||||||
        #[macro_export] macro_rules! lnote { ($dst:expr, $($arg:tt)*) => {  $crate::util::logger::lnote($dst, std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
					        #[macro_export] macro_rules! lnote { ($dst:expr, $($arg:tt)*) => {  $crate::util::logger::lnote($dst, std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #[macro_export] macro_rules! help { ($($arg:tt)*) => {  $crate::util::logger::help( std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
				
			||||||
 | 
					        #[macro_export] macro_rules! code_block { ($($arg:tt)*) => {  $crate::util::logger::code_block( std::format_args!($($arg)*).to_string().as_str()) }; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user