diff --git a/editor/vscode/mclang-0.0.1.vsix b/editor/vscode/mclang-0.0.1.vsix index 9845bce..107fb62 100644 Binary files a/editor/vscode/mclang-0.0.1.vsix and b/editor/vscode/mclang-0.0.1.vsix differ diff --git a/editor/vscode/package.json b/editor/vscode/package.json index bae061c..7b1e156 100644 --- a/editor/vscode/package.json +++ b/editor/vscode/package.json @@ -37,6 +37,6 @@ }, "dependencies": { "generator-code": "^1.7.4", - "vsce": "^2.15.0" + "@vscode/vsce": "^2.15.0" } } diff --git a/editor/vscode/syntaxes/mclang.tmLanguage.json b/editor/vscode/syntaxes/mclang.tmLanguage.json index 6fa3308..a1cb47c 100644 --- a/editor/vscode/syntaxes/mclang.tmLanguage.json +++ b/editor/vscode/syntaxes/mclang.tmLanguage.json @@ -53,7 +53,7 @@ { "name": "keyword.declaration.mclang", - "match": "(?<=\\s|^)(macro|memory|fn|const|in|inline|include|assert|offset|addr-of|call-like|reset|int|ptr|bool|addr|--|let|peek)(?:\\s|$)" + "match": "(?<=\\s|^)(macro|memory|fn|const|in|inline|include|assert|offset|addr-of|call-like|reset|let|peek|with|returns)(?:\\s|$)" }, { "name": "keyword.control.mclang", @@ -123,7 +123,7 @@ "patterns": [ { "name": "variable.name.source.mclang", - "match": "(?<=^|\\s)(\\+|-|\\*|max|divmod|print|=|>|<|>=|<=|!=|>>|<<|\\||&|not|dup|swap|drop|over|rot|argc|argv|here|syscall0|syscall1|syscall2|syscall3|syscall4|syscall5|syscall6|mem|\\?\\?\\?)(?=>$|\\s)" + "match": "(?<=^|\\s)(\\+|-|\\*|int|ptr|bool|addr|max|divmod|print|=|>|<|>=|<=|!=|>>|<<|\\||&|not|dup|swap|drop|over|rot|argc|argv|here|syscall0|syscall1|syscall2|syscall3|syscall4|syscall5|syscall6|mem|\\?\\?\\?)(?=>$|\\s)" } ] }, diff --git a/include/compat.mcl b/include/compat.mcl index 2630b05..bee2a49 100644 --- a/include/compat.mcl +++ b/include/compat.mcl @@ -1,5 +1 @@ -macro __compat__ - macro !8 load8 end - macro @8 store8 end - -end \ No newline at end of file +// todo: add some sort of macro \ No newline at end of file diff --git a/include/fs.mcl b/include/fs.mcl index 2060661..3268996 100644 --- a/include/fs.mcl +++ b/include/fs.mcl @@ -1,19 +1,18 @@ - -macro FS_O_APPEND 1024 end // append to existing file -macro FS_O_ASYNC 8192 end // use signal-driven IO -macro FS_O_CLOEXEC 524288 end // use close-on-exec (avoid race conditions and lock contentions) -macro FS_O_CREAT 64 end // create file if it doesn’t exist -macro FS_O_DIRECT 16384 end // bypass cache (slower) -macro FS_O_DIRECTORY 65536 end // fail if pathname isn’t a directory -macro FS_O_DSYNC 4096 end // ensure output is sent to hardware and metadata written before return -macro FS_O_EXCL 128 end // ensure creation of file -macro FS_O_LARGEFILE 0 end // allows use of file sizes represented by off64_t -macro FS_O_NOATIME 262144 end // do not increment access time upon open -macro FS_O_NOCTTY 256 end // if pathname is a terminal device, don’t become controlling terminal -macro FS_O_NOFOLLOW 131072 end // fail if pathname is symbolic link -macro FS_O_NONBLOCK 2048 end // if possible, open file with non-blocking IO -macro FS_O_NDELAY 2048 end // same as O_NONBLOCK -macro 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_SYNC 1052672 end // wait for IO to complete before returning -macro FS_O_TMPFILE 4259840 end // create an unnamed, unreachable (via any other open call) temporary file -macro FS_O_TRUNC 512 end // if file exists, ovewrite it (careful!) +const FS_O_APPEND 1024 end // append to existing file +const 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) +const FS_O_CREAT 64 end // create file if it doesn’t exist +const FS_O_DIRECT 16384 end // bypass cache (slower) +const 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 +const FS_O_EXCL 128 end // ensure creation of file +const 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 +const 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 +const FS_O_NONBLOCK 2048 end // if possible, open file with non-blocking IO +const 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 +const 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 +const FS_O_TRUNC 512 end // if file exists, ovewrite it (careful!) diff --git a/include/int.mcl b/include/int.mcl index c74ee7e..4a234b5 100644 --- a/include/int.mcl +++ b/include/int.mcl @@ -1,16 +1,16 @@ -macro NULL 0 end -macro false 0 end -macro true 1 end +const NULL 0 end +const false 0 end +const true 1 end -macro div divmod drop end -macro mod divmod swap drop end -macro / div end -macro % mod end +fn div with int int returns int int divmod drop end +fn mod with int int returns int int divmod swap drop end +fn / with int int returns int int div end +fn % with int int returns int int mod end -macro 2dup over over end -macro 2drop drop drop end +fn 2dup with any any returns any over over end +fn 2drop with any any returns any drop drop end -macro sizeof(u64) 8 end -macro sizeof(u32) 4 end -macro sizeof(u16) 2 end -macro sizeof(u8) 1 end \ No newline at end of file +const sizeof(u64) 8 end +const sizeof(u32) 4 end +const sizeof(u16) 2 end +const sizeof(u8) 1 end \ No newline at end of file diff --git a/include/io.mcl b/include/io.mcl index 3d7f05e..99b0bcf 100644 --- a/include/io.mcl +++ b/include/io.mcl @@ -5,7 +5,7 @@ // @arg buff_ptr: Ptr - pointer to the buffer to write // @arg fd: Int - file descriptor // @ret Int -fn write do +fn write with int ptr int returns int do SYS_write syscall3 end @@ -15,7 +15,7 @@ end // @arg buff_ptr: Ptr - pointer to the buffer to write // @arg fd: Int - file descriptor // @ret Int -fn read do +fn read with int ptr int returns int do SYS_read syscall3 end @@ -25,7 +25,7 @@ end // @arg buff_size: Int - number of bytes to write // @arg buff_ptr: Ptr - pointer to the buffer to write // @ret NULL -fn puts do +fn puts with int ptr returns null do STDOUT write drop end @@ -34,7 +34,7 @@ end // @arg buff_size: Int - number of bytes to write // @arg buff_ptr: Ptr - pointer to the buffer to write // @ret NULL -fn eputs do +fn eputs with int ptr returns null do STDOUT write drop end @@ -44,7 +44,7 @@ end // args: [exit_code] // @arg exit_code: Int // @ret NULL/NEVER -fn exit do +fn exit with int returns null do SYS_exit syscall1 drop end diff --git a/include/linux.mcl b/include/linux.mcl index 5292b65..6b459b9 100644 --- a/include/linux.mcl +++ b/include/linux.mcl @@ -1,322 +1,322 @@ // file descriptors -macro STDIN 0 end -macro STDOUT 1 end -macro STDERR 2 end +const STDIN 0 end +const STDOUT 1 end +const STDERR 2 end // syscalls -macro SYS_read 0 end -macro SYS_write 1 end -macro SYS_open 2 end -macro SYS_close 3 end -macro SYS_stat 4 end -macro SYS_fstat 5 end -macro SYS_lstat 6 end -macro SYS_poll 7 end -macro SYS_lseek 8 end -macro SYS_mmap 9 end -macro SYS_mprotect 10 end -macro SYS_munmap 11 end -macro SYS_brk 12 end -macro SYS_rt_sigaction 13 end -macro SYS_rt_sigprocmask 14 end -macro SYS_rt_sigreturn 15 end -macro SYS_ioctl 16 end -macro SYS_pread64 17 end -macro SYS_pwrite64 18 end -macro SYS_readv 19 end -macro SYS_writev 20 end -macro SYS_access 21 end -macro SYS_pipe 22 end -macro SYS_select 23 end -macro SYS_sched_yield 24 end -macro SYS_mremap 25 end -macro SYS_msync 26 end -macro SYS_mincore 27 end -macro SYS_madvise 28 end -macro SYS_shmget 29 end -macro SYS_shmat 30 end -macro SYS_shmctl 31 end -macro SYS_dup 32 end -macro SYS_dup2 33 end -macro SYS_pause 34 end -macro SYS_nanosleep 35 end -macro SYS_getitimer 36 end -macro SYS_alarm 37 end -macro SYS_setitimer 38 end -macro SYS_getpid 39 end -macro SYS_sendfile 40 end -macro SYS_socket 41 end -macro SYS_connect 42 end -macro SYS_accept 43 end -macro SYS_sendto 44 end -macro SYS_recvfrom 45 end -macro SYS_sendmsg 46 end -macro SYS_recvmsg 47 end -macro SYS_shutdown 48 end -macro SYS_bind 49 end -macro SYS_listen 50 end -macro SYS_getsockname 51 end -macro SYS_getpeername 52 end -macro SYS_socketpair 53 end -macro SYS_setsockopt 54 end -macro SYS_getsockopt 55 end -macro SYS_clone 56 end -macro SYS_fork 57 end -macro SYS_vfork 58 end -macro SYS_execve 59 end -macro SYS_exit 60 end -macro SYS_wait4 61 end -macro SYS_kill 62 end -macro SYS_uname 63 end -macro SYS_semget 64 end -macro SYS_semop 65 end -macro SYS_semctl 66 end -macro SYS_shmdt 67 end -macro SYS_msgget 68 end -macro SYS_msgsnd 69 end -macro SYS_msgrcv 70 end -macro SYS_msgctl 71 end -macro SYS_fcntl 72 end -macro SYS_flock 73 end -macro SYS_fsync 74 end -macro SYS_fdatasync 75 end -macro SYS_truncate 76 end -macro SYS_ftruncate 77 end -macro SYS_getdents 78 end -macro SYS_getcwd 79 end -macro SYS_chdir 80 end -macro SYS_fchdir 81 end -macro SYS_rename 82 end -macro SYS_mkdir 83 end -macro SYS_rmdir 84 end -macro SYS_creat 85 end -macro SYS_link 86 end -macro SYS_unlink 87 end -macro SYS_symlink 88 end -macro SYS_readlink 89 end -macro SYS_chmod 90 end -macro SYS_fchmod 91 end -macro SYS_chown 92 end -macro SYS_fchown 93 end -macro SYS_lchown 94 end -macro SYS_umask 95 end -macro SYS_gettimeofday 96 end -macro SYS_getrlimit 97 end -macro SYS_getrusage 98 end -macro SYS_sysinfo 99 end -macro SYS_times 100 end -macro SYS_ptrace 101 end -macro SYS_getuid 102 end -macro SYS_syslog 103 end -macro SYS_getgid 104 end -macro SYS_setuid 105 end -macro SYS_setgid 106 end -macro SYS_geteuid 107 end -macro SYS_getegid 108 end -macro SYS_setpgid 109 end -macro SYS_getppid 110 end -macro SYS_getpgrp 111 end -macro SYS_setsid 112 end -macro SYS_setreuid 113 end -macro SYS_setregid 114 end -macro SYS_getgroups 115 end -macro SYS_setgroups 116 end -macro SYS_setresuid 117 end -macro SYS_getresuid 118 end -macro SYS_setresgid 119 end -macro SYS_getresgid 120 end -macro SYS_getpgid 121 end -macro SYS_setfsuid 122 end -macro SYS_setfsgid 123 end -macro SYS_getsid 124 end -macro SYS_capget 125 end -macro SYS_capset 126 end -macro SYS_rt_sigpending 127 end -macro SYS_rt_sigtimedwait 128 end -macro SYS_rt_sigqueueinfo 129 end -macro SYS_rt_sigsuspend 130 end -macro SYS_sigaltstack 131 end -macro SYS_utime 132 end -macro SYS_mknod 133 end -macro SYS_uselib 134 end -macro SYS_personality 135 end -macro SYS_ustat 136 end -macro SYS_statfs 137 end -macro SYS_fstatfs 138 end -macro SYS_sysfs 139 end -macro SYS_getpriority 140 end -macro SYS_setpriority 141 end -macro SYS_sched_setparam 142 end -macro SYS_sched_getparam 143 end -macro SYS_sched_setscheduler 144 end -macro SYS_sched_getscheduler 145 end -macro SYS_sched_get_priority_max 146 end -macro SYS_sched_get_priority_min 147 end -macro SYS_sched_rr_get_interval 148 end -macro SYS_mlock 149 end -macro SYS_munlock 150 end -macro SYS_mlockall 151 end -macro SYS_munlockall 152 end -macro SYS_vhangup 153 end -macro SYS_modify_ldt 154 end -macro SYS_pivot_root 155 end -macro SYS__sysctl 156 end -macro SYS_prctl 157 end -macro SYS_arch_prctl 158 end -macro SYS_adjtimex 159 end -macro SYS_setrlimit 160 end -macro SYS_chroot 161 end -macro SYS_sync 162 end -macro SYS_acct 163 end -macro SYS_settimeofday 164 end -macro SYS_mount 165 end -macro SYS_umount2 166 end -macro SYS_swapon 167 end -macro SYS_swapoff 168 end -macro SYS_reboot 169 end -macro SYS_sethostname 170 end -macro SYS_setdomainname 171 end -macro SYS_iopl 172 end -macro SYS_ioperm 173 end -macro SYS_create_module 174 end -macro SYS_init_module 175 end -macro SYS_delete_module 176 end -macro SYS_get_kernel_syms 177 end -macro SYS_query_module 178 end -macro SYS_quotactl 179 end -macro SYS_nfsservctl 180 end -macro SYS_getpmsg 181 end -macro SYS_putpmsg 182 end -macro SYS_afs_syscall 183 end -macro SYS_tuxcall 184 end -macro SYS_security 185 end -macro SYS_gettid 186 end -macro SYS_readahead 187 end -macro SYS_setxattr 188 end -macro SYS_lsetxattr 189 end -macro SYS_fsetxattr 190 end -macro SYS_getxattr 191 end -macro SYS_lgetxattr 192 end -macro SYS_fgetxattr 193 end -macro SYS_listxattr 194 end -macro SYS_llistxattr 195 end -macro SYS_flistxattr 196 end -macro SYS_removexattr 197 end -macro SYS_lremovexattr 198 end -macro SYS_fremovexattr 199 end -macro SYS_tkill 200 end -macro SYS_time 201 end -macro SYS_futex 202 end -macro SYS_sched_setaffinity 203 end -macro SYS_sched_getaffinity 204 end -macro SYS_set_thread_area 205 end -macro SYS_io_setup 206 end -macro SYS_io_destroy 207 end -macro SYS_io_getevents 208 end -macro SYS_io_submit 209 end -macro SYS_io_cancel 210 end -macro SYS_get_thread_area 211 end -macro SYS_lookup_dcookie 212 end -macro SYS_epoll_create 213 end -macro SYS_epoll_ctl_old 214 end -macro SYS_epoll_wait_old 215 end -macro SYS_remap_file_pages 216 end -macro SYS_getdents64 217 end -macro SYS_set_tid_address 218 end -macro SYS_restart_syscall 219 end -macro SYS_semtimedop 220 end -macro SYS_fadvise64 221 end -macro SYS_timer_create 222 end -macro SYS_timer_settime 223 end -macro SYS_timer_gettime 224 end -macro SYS_timer_getoverrun 225 end -macro SYS_timer_delete 226 end -macro SYS_clock_settime 227 end -macro SYS_clock_gettime 228 end -macro SYS_clock_getres 229 end -macro SYS_clock_nanosleep 230 end -macro SYS_exit_group 231 end -macro SYS_epoll_wait 232 end -macro SYS_epoll_ctl 233 end -macro SYS_tgkill 234 end -macro SYS_utimes 235 end -macro SYS_vserver 236 end -macro SYS_mbind 237 end -macro SYS_set_mempolicy 238 end -macro SYS_get_mempolicy 239 end -macro SYS_mq_open 240 end -macro SYS_mq_unlink 241 end -macro SYS_mq_timedsend 242 end -macro SYS_mq_timedreceive 243 end -macro SYS_mq_notify 244 end -macro SYS_mq_getsetattr 245 end -macro SYS_kexec_load 246 end -macro SYS_waitid 247 end -macro SYS_add_key 248 end -macro SYS_request_key 249 end -macro SYS_keyctl 250 end -macro SYS_ioprio_set 251 end -macro SYS_ioprio_get 252 end -macro SYS_inotify_init 253 end -macro SYS_inotify_add_watch 254 end -macro SYS_inotify_rm_watch 255 end -macro SYS_migrate_pages 256 end -macro SYS_openat 257 end -macro SYS_mkdirat 258 end -macro SYS_mknodat 259 end -macro SYS_fchownat 260 end -macro SYS_futimesat 261 end -macro SYS_newfstatat 262 end -macro SYS_unlinkat 263 end -macro SYS_renameat 264 end -macro SYS_linkat 265 end -macro SYS_symlinkat 266 end -macro SYS_readlinkat 267 end -macro SYS_fchmodat 268 end -macro SYS_faccessat 269 end -macro SYS_pselect6 270 end -macro SYS_ppoll 271 end -macro SYS_unshare 272 end -macro SYS_set_robust_list 273 end -macro SYS_get_robust_list 274 end -macro SYS_splice 275 end -macro SYS_tee 276 end -macro SYS_sync_file_range 277 end -macro SYS_vmsplice 278 end -macro SYS_move_pages 279 end -macro SYS_utimensat 280 end -macro SYS_epoll_pwait 281 end -macro SYS_signalfd 282 end -macro SYS_timerfd_create 283 end -macro SYS_eventfd 284 end -macro SYS_fallocate 285 end -macro SYS_timerfd_settime 286 end -macro SYS_timerfd_gettime 287 end -macro SYS_accept4 288 end -macro SYS_signalfd4 289 end -macro SYS_eventfd2 290 end -macro SYS_epoll_create1 291 end -macro SYS_dup3 292 end -macro SYS_pipe2 293 end -macro SYS_inotify_init1 294 end -macro SYS_preadv 295 end -macro SYS_pwritev 296 end -macro SYS_rt_tgsigqueueinfo 297 end -macro SYS_perf_event_open 298 end -macro SYS_recvmmsg 299 end -macro SYS_fanotify_init 300 end -macro SYS_fanotify_mark 301 end -macro SYS_prlimit64 302 end -macro SYS_name_to_handle_at 303 end -macro SYS_open_by_handle_at 304 end -macro SYS_clock_adjtime 305 end -macro SYS_syncfs 306 end -macro SYS_sendmmsg 307 end -macro SYS_setns 308 end -macro SYS_getcpu 309 end -macro SYS_process_vm_readv 310 end -macro SYS_process_vm_writev 311 end -macro SYS_kcmp 312 end -macro SYS_finit_module 313 end \ No newline at end of file +const SYS_read 0 end +const SYS_write 1 end +const SYS_open 2 end +const SYS_close 3 end +const SYS_stat 4 end +const SYS_fstat 5 end +const SYS_lstat 6 end +const SYS_poll 7 end +const SYS_lseek 8 end +const SYS_mmap 9 end +const SYS_mprotect 10 end +const SYS_munmap 11 end +const SYS_brk 12 end +const SYS_rt_sigaction 13 end +const SYS_rt_sigprocmask 14 end +const SYS_rt_sigreturn 15 end +const SYS_ioctl 16 end +const SYS_pread64 17 end +const SYS_pwrite64 18 end +const SYS_readv 19 end +const SYS_writev 20 end +const SYS_access 21 end +const SYS_pipe 22 end +const SYS_select 23 end +const SYS_sched_yield 24 end +const SYS_mremap 25 end +const SYS_msync 26 end +const SYS_mincore 27 end +const SYS_madvise 28 end +const SYS_shmget 29 end +const SYS_shmat 30 end +const SYS_shmctl 31 end +const SYS_dup 32 end +const SYS_dup2 33 end +const SYS_pause 34 end +const SYS_nanosleep 35 end +const SYS_getitimer 36 end +const SYS_alarm 37 end +const SYS_setitimer 38 end +const SYS_getpid 39 end +const SYS_sendfile 40 end +const SYS_socket 41 end +const SYS_connect 42 end +const SYS_accept 43 end +const SYS_sendto 44 end +const SYS_recvfrom 45 end +const SYS_sendmsg 46 end +const SYS_recvmsg 47 end +const SYS_shutdown 48 end +const SYS_bind 49 end +const SYS_listen 50 end +const SYS_getsockname 51 end +const SYS_getpeername 52 end +const SYS_socketpair 53 end +const SYS_setsockopt 54 end +const SYS_getsockopt 55 end +const SYS_clone 56 end +const SYS_fork 57 end +const SYS_vfork 58 end +const SYS_execve 59 end +const SYS_exit 60 end +const SYS_wait4 61 end +const SYS_kill 62 end +const SYS_uname 63 end +const SYS_semget 64 end +const SYS_semop 65 end +const SYS_semctl 66 end +const SYS_shmdt 67 end +const SYS_msgget 68 end +const SYS_msgsnd 69 end +const SYS_msgrcv 70 end +const SYS_msgctl 71 end +const SYS_fcntl 72 end +const SYS_flock 73 end +const SYS_fsync 74 end +const SYS_fdatasync 75 end +const SYS_truncate 76 end +const SYS_ftruncate 77 end +const SYS_getdents 78 end +const SYS_getcwd 79 end +const SYS_chdir 80 end +const SYS_fchdir 81 end +const SYS_rename 82 end +const SYS_mkdir 83 end +const SYS_rmdir 84 end +const SYS_creat 85 end +const SYS_link 86 end +const SYS_unlink 87 end +const SYS_symlink 88 end +const SYS_readlink 89 end +const SYS_chmod 90 end +const SYS_fchmod 91 end +const SYS_chown 92 end +const SYS_fchown 93 end +const SYS_lchown 94 end +const SYS_umask 95 end +const SYS_gettimeofday 96 end +const SYS_getrlimit 97 end +const SYS_getrusage 98 end +const SYS_sysinfo 99 end +const SYS_times 100 end +const SYS_ptrace 101 end +const SYS_getuid 102 end +const SYS_syslog 103 end +const SYS_getgid 104 end +const SYS_setuid 105 end +const SYS_setgid 106 end +const SYS_geteuid 107 end +const SYS_getegid 108 end +const SYS_setpgid 109 end +const SYS_getppid 110 end +const SYS_getpgrp 111 end +const SYS_setsid 112 end +const SYS_setreuid 113 end +const SYS_setregid 114 end +const SYS_getgroups 115 end +const SYS_setgroups 116 end +const SYS_setresuid 117 end +const SYS_getresuid 118 end +const SYS_setresgid 119 end +const SYS_getresgid 120 end +const SYS_getpgid 121 end +const SYS_setfsuid 122 end +const SYS_setfsgid 123 end +const SYS_getsid 124 end +const SYS_capget 125 end +const SYS_capset 126 end +const SYS_rt_sigpending 127 end +const SYS_rt_sigtimedwait 128 end +const SYS_rt_sigqueueinfo 129 end +const SYS_rt_sigsuspend 130 end +const SYS_sigaltstack 131 end +const SYS_utime 132 end +const SYS_mknod 133 end +const SYS_uselib 134 end +const SYS_personality 135 end +const SYS_ustat 136 end +const SYS_statfs 137 end +const SYS_fstatfs 138 end +const SYS_sysfs 139 end +const SYS_getpriority 140 end +const SYS_setpriority 141 end +const SYS_sched_setparam 142 end +const SYS_sched_getparam 143 end +const SYS_sched_setscheduler 144 end +const SYS_sched_getscheduler 145 end +const SYS_sched_get_priority_max 146 end +const SYS_sched_get_priority_min 147 end +const SYS_sched_rr_get_interval 148 end +const SYS_mlock 149 end +const SYS_munlock 150 end +const SYS_mlockall 151 end +const SYS_munlockall 152 end +const SYS_vhangup 153 end +const SYS_modify_ldt 154 end +const SYS_pivot_root 155 end +const SYS__sysctl 156 end +const SYS_prctl 157 end +const SYS_arch_prctl 158 end +const SYS_adjtimex 159 end +const SYS_setrlimit 160 end +const SYS_chroot 161 end +const SYS_sync 162 end +const SYS_acct 163 end +const SYS_settimeofday 164 end +const SYS_mount 165 end +const SYS_umount2 166 end +const SYS_swapon 167 end +const SYS_swapoff 168 end +const SYS_reboot 169 end +const SYS_sethostname 170 end +const SYS_setdomainname 171 end +const SYS_iopl 172 end +const SYS_ioperm 173 end +const SYS_create_module 174 end +const SYS_init_module 175 end +const SYS_delete_module 176 end +const SYS_get_kernel_syms 177 end +const SYS_query_module 178 end +const SYS_quotactl 179 end +const SYS_nfsservctl 180 end +const SYS_getpmsg 181 end +const SYS_putpmsg 182 end +const SYS_afs_syscall 183 end +const SYS_tuxcall 184 end +const SYS_security 185 end +const SYS_gettid 186 end +const SYS_readahead 187 end +const SYS_setxattr 188 end +const SYS_lsetxattr 189 end +const SYS_fsetxattr 190 end +const SYS_getxattr 191 end +const SYS_lgetxattr 192 end +const SYS_fgetxattr 193 end +const SYS_listxattr 194 end +const SYS_llistxattr 195 end +const SYS_flistxattr 196 end +const SYS_removexattr 197 end +const SYS_lremovexattr 198 end +const SYS_fremovexattr 199 end +const SYS_tkill 200 end +const SYS_time 201 end +const SYS_futex 202 end +const SYS_sched_setaffinity 203 end +const SYS_sched_getaffinity 204 end +const SYS_set_thread_area 205 end +const SYS_io_setup 206 end +const SYS_io_destroy 207 end +const SYS_io_getevents 208 end +const SYS_io_submit 209 end +const SYS_io_cancel 210 end +const SYS_get_thread_area 211 end +const SYS_lookup_dcookie 212 end +const SYS_epoll_create 213 end +const SYS_epoll_ctl_old 214 end +const SYS_epoll_wait_old 215 end +const SYS_remap_file_pages 216 end +const SYS_getdents64 217 end +const SYS_set_tid_address 218 end +const SYS_restart_syscall 219 end +const SYS_semtimedop 220 end +const SYS_fadvise64 221 end +const SYS_timer_create 222 end +const SYS_timer_settime 223 end +const SYS_timer_gettime 224 end +const SYS_timer_getoverrun 225 end +const SYS_timer_delete 226 end +const SYS_clock_settime 227 end +const SYS_clock_gettime 228 end +const SYS_clock_getres 229 end +const SYS_clock_nanosleep 230 end +const SYS_exit_group 231 end +const SYS_epoll_wait 232 end +const SYS_epoll_ctl 233 end +const SYS_tgkill 234 end +const SYS_utimes 235 end +const SYS_vserver 236 end +const SYS_mbind 237 end +const SYS_set_mempolicy 238 end +const SYS_get_mempolicy 239 end +const SYS_mq_open 240 end +const SYS_mq_unlink 241 end +const SYS_mq_timedsend 242 end +const SYS_mq_timedreceive 243 end +const SYS_mq_notify 244 end +const SYS_mq_getsetattr 245 end +const SYS_kexec_load 246 end +const SYS_waitid 247 end +const SYS_add_key 248 end +const SYS_request_key 249 end +const SYS_keyctl 250 end +const SYS_ioprio_set 251 end +const SYS_ioprio_get 252 end +const SYS_inotify_init 253 end +const SYS_inotify_add_watch 254 end +const SYS_inotify_rm_watch 255 end +const SYS_migrate_pages 256 end +const SYS_openat 257 end +const SYS_mkdirat 258 end +const SYS_mknodat 259 end +const SYS_fchownat 260 end +const SYS_futimesat 261 end +const SYS_newfstatat 262 end +const SYS_unlinkat 263 end +const SYS_renameat 264 end +const SYS_linkat 265 end +const SYS_symlinkat 266 end +const SYS_readlinkat 267 end +const SYS_fchmodat 268 end +const SYS_faccessat 269 end +const SYS_pselect6 270 end +const SYS_ppoll 271 end +const SYS_unshare 272 end +const SYS_set_robust_list 273 end +const SYS_get_robust_list 274 end +const SYS_splice 275 end +const SYS_tee 276 end +const SYS_sync_file_range 277 end +const SYS_vmsplice 278 end +const SYS_move_pages 279 end +const SYS_utimensat 280 end +const SYS_epoll_pwait 281 end +const SYS_signalfd 282 end +const SYS_timerfd_create 283 end +const SYS_eventfd 284 end +const SYS_fallocate 285 end +const SYS_timerfd_settime 286 end +const SYS_timerfd_gettime 287 end +const SYS_accept4 288 end +const SYS_signalfd4 289 end +const SYS_eventfd2 290 end +const SYS_epoll_create1 291 end +const SYS_dup3 292 end +const SYS_pipe2 293 end +const SYS_inotify_init1 294 end +const SYS_preadv 295 end +const SYS_pwritev 296 end +const SYS_rt_tgsigqueueinfo 297 end +const SYS_perf_event_open 298 end +const SYS_recvmmsg 299 end +const SYS_fanotify_init 300 end +const SYS_fanotify_mark 301 end +const SYS_prlimit64 302 end +const SYS_name_to_handle_at 303 end +const SYS_open_by_handle_at 304 end +const SYS_clock_adjtime 305 end +const SYS_syncfs 306 end +const SYS_sendmmsg 307 end +const SYS_setns 308 end +const SYS_getcpu 309 end +const SYS_process_vm_readv 310 end +const SYS_process_vm_writev 311 end +const SYS_kcmp 312 end +const SYS_finit_module 313 end \ No newline at end of file diff --git a/include/util.mcl b/include/util.mcl index 605bc8b..855ea32 100644 --- a/include/util.mcl +++ b/include/util.mcl @@ -5,7 +5,7 @@ // @arg str_len: Int // @arg str_ptr: Ptr // @ret NULL/NEVER -macro assert +fn assert with bool int ptr returns null do rot if else "Assert failed: \"" eputs eputs diff --git a/src/compile/linux_x86_64.rs b/src/compile/linux_x86_64.rs index 2cb0b9c..e4d647f 100644 --- a/src/compile/linux_x86_64.rs +++ b/src/compile/linux_x86_64.rs @@ -7,6 +7,8 @@ use super::commands::linux_x86_64_run; pub fn compile(tokens: &[Operator], args: &Args) -> Result{ + let debug = args.optimisation == "D"; + 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 of_o = PathBuf::from("/tmp/mclang_comp.o"); @@ -27,6 +29,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ let file = fs::File::create(&of_a)?; let mut writer = BufWriter::new(&file); let mut memories: Vec<(usize, usize)> = Vec::new(); + let mut constants: Vec<(String, Option, Option)> = Vec::new(); // println!("{}", tokens.len()); let mut strings: Vec = Vec::new(); @@ -68,7 +71,8 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ writeln!(writer, " ret")?; writeln!(writer, "global _start")?; - writeln!(writer, "_start:")?; + writeln!(writer, "_start:")?; + writeln!(writer, " lea rbp, [rel ret_stack]")?; writeln!(writer, " call func_main")?; writeln!(writer, " jmp end")?; @@ -76,41 +80,73 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ let mut ti = 0; while ti < tokens.len() { let token = &tokens[ti]; - println!("{:?}", token); - writeln!(writer, "addr_{ti}:")?; + // println!("{:?}", token); + if debug { + 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, strings[token.value].escape_debug())?; + } else { + writeln!(writer, " ;; -- {:?}", token.typ)?; + } + } else { + if ti != 0{ + + if &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}:")?; + } + + match &token.typ { + OpType::Keyword(keyword) => { + match keyword { + &KeywordType::End | + &KeywordType::While => { + writeln!(writer, "addr_{ti}:")?; + } + _ => () + } + } + _ => () + } + + } match token.typ.clone() { // stack OpType::Instruction(instruction) => { match instruction { InstructionType::PushInt => { - writeln!(writer, " ;; -- push int {}", token.value)?; writeln!(writer, " mov rax, {}", token.value)?; writeln!(writer, " push rax")?; ti += 1; }, InstructionType::PushStr => { - writeln!(writer, " ;; -- push str \"{}\"", token.text.escape_default())?; writeln!(writer, " mov rax, {}", token.text.len())?; writeln!(writer, " push rax")?; - writeln!(writer, " push str_{}", strings.len())?; + writeln!(writer, " mov rax, str_{}", strings.len())?; + writeln!(writer, " push rax")?; strings.push(token.text.clone()); ti += 1; } InstructionType::Drop => { - writeln!(writer, " ;; -- drop")?; writeln!(writer, " pop rax")?; ti += 1; }, InstructionType::Print => { - writeln!(writer, " ;; -- print")?; writeln!(writer, " pop rdi")?; writeln!(writer, " call print")?; ti += 1; }, InstructionType::Dup => { - writeln!(writer, " ;; -- dup")?; writeln!(writer, " pop rax")?; writeln!(writer, " push rax")?; writeln!(writer, " push rax")?; @@ -119,7 +155,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ }, InstructionType::Rot => { - writeln!(writer, " ;; -- rot")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rbx")?; writeln!(writer, " pop rcx")?; @@ -130,7 +165,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Swap => { - writeln!(writer, " ;; -- swap")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rbx")?; writeln!(writer, " push rax")?; @@ -139,7 +173,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Over => { - writeln!(writer, " ;; -- over")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rbx")?; writeln!(writer, " push rbx")?; @@ -148,15 +181,7 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, - - //mem - InstructionType::Mem => { - writeln!(writer, " ;; -- mem")?; - writeln!(writer, " push mem")?; - ti += 1; - } InstructionType::Load8 => { - writeln!(writer, " ;; -- load")?; writeln!(writer, " pop rax")?; writeln!(writer, " xor rbx, rbx")?; writeln!(writer, " mov bl, byte [rax]")?; @@ -165,14 +190,12 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ } InstructionType::Store8 => { - writeln!(writer, " ;; -- store")?; writeln!(writer, " pop rbx")?; writeln!(writer, " pop rax")?; writeln!(writer, " mov byte [rax], bl")?; ti += 1; } InstructionType::Load32 => { - writeln!(writer, " ;; -- load")?; writeln!(writer, " pop rax")?; writeln!(writer, " xor rbx, rbx")?; writeln!(writer, " mov bl, dword [rax]")?; @@ -181,14 +204,12 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ } InstructionType::Store32 => { - writeln!(writer, " ;; -- store")?; writeln!(writer, " pop rbx")?; writeln!(writer, " pop rax")?; writeln!(writer, " mov dword[rax], bl")?; ti += 1; } InstructionType::Load64 => { - writeln!(writer, " ;; -- load")?; writeln!(writer, " pop rax")?; writeln!(writer, " xor rbx, rbx")?; writeln!(writer, " mov bl, qword [rax]")?; @@ -197,7 +218,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ } InstructionType::Store64 => { - writeln!(writer, " ;; -- store")?; writeln!(writer, " pop rbx")?; writeln!(writer, " pop rax")?; writeln!(writer, " mov qword [rax], bl")?; @@ -206,7 +226,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ // math InstructionType::Plus => { - writeln!(writer, " ;; -- plus")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rbx")?; writeln!(writer, " add rax, rbx")?; @@ -214,7 +233,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Minus => { - writeln!(writer, " ;; -- minus")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rbx")?; writeln!(writer, " sub rbx, rax")?; @@ -222,7 +240,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Equals => { - writeln!(writer, " ;; -- equals")?; writeln!(writer, " mov rcx, 0")?; writeln!(writer, " mov rdx, 1")?; writeln!(writer, " pop rax")?; @@ -233,7 +250,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Lt => { - writeln!(writer, " ;; -- lt")?; writeln!(writer, " mov rcx, 0")?; writeln!(writer, " mov rdx, 1")?; writeln!(writer, " pop rbx")?; @@ -244,7 +260,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Gt => { - writeln!(writer, " ;; -- gt")?; writeln!(writer, " mov rcx, 0")?; writeln!(writer, " mov rdx, 1")?; writeln!(writer, " pop rbx")?; @@ -255,7 +270,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::NotEquals => { - writeln!(writer, " ;; -- not equals")?; writeln!(writer, " mov rcx, 1")?; writeln!(writer, " mov rdx, 0")?; writeln!(writer, " pop rax")?; @@ -266,7 +280,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Le => { - writeln!(writer, " ;; -- lt")?; writeln!(writer, " mov rcx, 0")?; writeln!(writer, " mov rdx, 1")?; writeln!(writer, " pop rbx")?; @@ -277,7 +290,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Ge => { - writeln!(writer, " ;; -- gt")?; writeln!(writer, " mov rcx, 0")?; writeln!(writer, " mov rdx, 1")?; writeln!(writer, " pop rbx")?; @@ -288,7 +300,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Band => { - writeln!(writer, " ;; -- band")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rbx")?; writeln!(writer, " and rbx, rax")?; @@ -296,7 +307,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Bor => { - writeln!(writer, " ;; -- bor")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rbx")?; writeln!(writer, " or rbx, rax")?; @@ -304,7 +314,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Shr => { - writeln!(writer, " ;; -- shr")?; writeln!(writer, " pop rcx")?; writeln!(writer, " pop rbx")?; writeln!(writer, " shr rbx, cl")?; @@ -312,7 +321,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Shl => { - writeln!(writer, " ;; -- shl")?; writeln!(writer, " pop rcx")?; writeln!(writer, " pop rbx")?; writeln!(writer, " shl rbx, cl")?; @@ -320,7 +328,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::DivMod => { - writeln!(writer, " ;; -- div")?; writeln!(writer, " xor rdx, rdx")?; writeln!(writer, " pop rbx")?; writeln!(writer, " pop rax")?; @@ -330,7 +337,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Mul => { - writeln!(writer, " ;; -- mul")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rbx")?; writeln!(writer, " mul rbx")?; @@ -338,14 +344,12 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Syscall0 => { - writeln!(writer, " ;; -- syscall0")?; writeln!(writer, " pop rax")?; writeln!(writer, " syscall")?; writeln!(writer, " push rax")?; ti += 1; }, InstructionType::Syscall1 => { - writeln!(writer, " ;; -- syscall1")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rdi")?; writeln!(writer, " syscall")?; @@ -353,7 +357,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Syscall2 => { - writeln!(writer, " ;; -- syscall2")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rdi")?; writeln!(writer, " pop rsi")?; @@ -362,7 +365,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Syscall3 => { - writeln!(writer, " ;; -- syscall3")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rdi")?; writeln!(writer, " pop rsi")?; @@ -373,7 +375,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Syscall4 => { - writeln!(writer, " ;; -- syscall4")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rdi")?; writeln!(writer, " pop rsi")?; @@ -384,7 +385,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Syscall5 => { - writeln!(writer, " ;; -- syscall5")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rdi")?; writeln!(writer, " pop rsi")?; @@ -396,7 +396,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::Syscall6 => { - writeln!(writer, " ;; -- syscall6")?; writeln!(writer, " pop rax")?; writeln!(writer, " pop rdi")?; writeln!(writer, " pop rsi")?; @@ -409,24 +408,65 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; }, InstructionType::MemUse => { - writeln!(writer, " ;; -- MemUse")?; writeln!(writer, " push mem_{}", token.addr.unwrap())?; ti += 1; }, - InstructionType::None => unreachable!(), - InstructionType::CastBool => ti += 1, - InstructionType::CastPtr => ti += 1, - InstructionType::CastInt => ti += 1, + InstructionType::None => { + println!("{:?}", token); + unreachable!() + }, InstructionType::FnCall => { - writeln!(writer, " ;; -- FnCall")?; writeln!(writer, " call func_{}", token.text)?; ti += 1; }, InstructionType::Return => { - writeln!(writer, " ;; -- Return")?; + writeln!(writer, " sub rbp, 8")?; + writeln!(writer, " mov rbx, qword [rbp]")?; + writeln!(writer, " push rbx")?; writeln!(writer, " ret")?; ti += 1; }, + InstructionType::CastBool => { + ti += 1; + } + InstructionType::CastPtr => { + ti += 1; + } + InstructionType::CastInt => { + ti += 1; + } + InstructionType::CastVoid => { + ti += 1; + } + InstructionType::TypeBool => { + ti += 1; + } + InstructionType::TypePtr => { + ti += 1; + } + InstructionType::TypeInt => { + ti += 1; + } + InstructionType::TypeVoid => { + ti += 1; + } + InstructionType::TypeStr => { + ti += 1; + } + InstructionType::TypeAny => { + ti += 1; + } + InstructionType::Returns => { + ti += 1; + } + InstructionType::With => { + ti += 1; + } + InstructionType::ConstUse => { + writeln!(writer, " mov rax, qword [const_{}]", token.text)?; + writeln!(writer, " push rax")?; + ti += 1; + }, } } @@ -436,32 +476,27 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ // block KeywordType::If => { - writeln!(writer, " ;; -- if")?; writeln!(writer, " pop rax")?; writeln!(writer, " test rax, rax")?; writeln!(writer, " jz addr_{}", token.jmp)?; ti += 1; }, KeywordType::Else => { - writeln!(writer, " ;; -- else")?; writeln!(writer, " jmp addr_{}", token.jmp)?; ti += 1; }, KeywordType::While => { - writeln!(writer, " ;; -- while")?; ti += 1; } KeywordType::Do => { - writeln!(writer, " ;; -- do")?; writeln!(writer, " pop rax")?; writeln!(writer, " test rax, rax")?; writeln!(writer, " jz addr_{}", token.jmp)?; ti += 1; } KeywordType::End => { - writeln!(writer, " ;; -- end")?; if ti + 1 != token.jmp { - writeln!(writer, " jmp addr_{}", token.jmp)?; + // writeln!(writer, " jmp addr_{}", token.jmp)?; } ti += 1; }, @@ -470,11 +505,19 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ ti += 1; } KeywordType::Include => unreachable!(), - KeywordType::Constant => todo!(), - KeywordType::Function => { - writeln!(writer, "func_{}:", token.text)?; + KeywordType::Constant => { + // TODO: after we add c style strings add supoort for them in constants + constants.push((token.text.clone(), Some(token.value), None)); ti += 1; }, + KeywordType::Function => { + writeln!(writer, "func_{}:", token.text)?; + writeln!(writer, " pop rbx")?; + writeln!(writer, " mov qword [rbp], rbx")?; + writeln!(writer, " add rbp, 8")?; + ti += 1; + }, + KeywordType::FunctionDo => ti += 1, } } } @@ -491,11 +534,27 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ writeln!(writer, " str_{}: db {} ; {}", i, s_list, s.escape_default())?; } + for (_, s) in constants.iter().enumerate() { + if let Some(v) = &s.1 { + writeln!(writer, " const_{}: dq {}", s.0, v)?; + } else if let Some(_v) = &s.2 { + todo!(); + } else { + unreachable!(); + } + + } + + writeln!(writer, "segment .bss")?; for (_, s) in memories.iter().enumerate() { writeln!(writer, " mem_{}: resb {}", s.0, s.1)?; } - writeln!(writer, " mem: resb {}", crate::compile::MEM_SZ)?; + writeln!(writer, " ret_stack: resq 256")?; + + // for t in tokens { + // println!("{t:?}"); + // } writer.flush()?; linux_x86_64_compile_and_link(&of_a, &of_o, &of_c, args.quiet)?; @@ -504,5 +563,6 @@ pub fn compile(tokens: &[Operator], args: &Args) -> Result{ return Ok(c); } + Ok(0) } \ No newline at end of file diff --git a/src/constants.rs b/src/constants.rs index cc08dbb..9f2c3ee 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,5 +1,4 @@ -pub const ALLOW_MACRO_REDEFINITION: bool = true; #[derive(Debug, Clone, PartialEq)] @@ -33,7 +32,6 @@ pub enum InstructionType { // mem - Mem, Load8, Store8, Load32, @@ -53,10 +51,23 @@ pub enum InstructionType { CastBool, CastPtr, CastInt, + CastVoid, + + // typing + TypeBool, + TypePtr, + TypeInt, + TypeVoid, + TypeStr, + TypeAny, + Returns, + With, FnCall, - Return, MemUse, + ConstUse, + + Return, None // Used for macros and any other non built in word definitions } @@ -70,7 +81,8 @@ pub enum KeywordType { Include, Memory, Constant, - Function + Function, + FunctionDo } #[derive(Debug, Clone, PartialEq)] @@ -137,7 +149,6 @@ impl OpType { InstructionType::Shl => "shl", InstructionType::DivMod => "divmod", InstructionType::Mul => "*", - InstructionType::Mem => "mem", InstructionType::Load8 => "load8", InstructionType::Store8 => "store8", InstructionType::Load32 => "load32", @@ -154,10 +165,20 @@ impl OpType { InstructionType::CastBool => "cast(bool", InstructionType::CastPtr => "cast(ptr)", InstructionType::CastInt => "cast(int)", - InstructionType::MemUse => "MemUse", + InstructionType::CastVoid => "cast(void)", InstructionType::None => "None", - InstructionType::FnCall => "Function Call", + 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) => { @@ -171,6 +192,7 @@ impl OpType { KeywordType::Memory => "memory", KeywordType::Function => "fn", KeywordType::Constant => "const", + KeywordType::FunctionDo => "do", } } @@ -226,6 +248,8 @@ pub enum Types { Bool, Ptr, Int, + Void, + Str, Any // U8, // U16, diff --git a/src/interpret/linux_x86_64/mod.rs b/src/interpret/linux_x86_64/mod.rs index 51107c0..358edaf 100644 --- a/src/interpret/linux_x86_64/mod.rs +++ b/src/interpret/linux_x86_64/mod.rs @@ -96,12 +96,6 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result{ // let _ = io::stdout().flush(); ti += 1; }, - // mem - - InstructionType::Mem => { - stack.push(0); - ti += 1; - } InstructionType::Load8 | InstructionType::Load32 | InstructionType::Load64 => { @@ -294,12 +288,22 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result{ stack.push(*m); ti += 1; }, - InstructionType::CastBool => ti += 1, - InstructionType::CastPtr => ti += 1, - InstructionType::CastInt => ti += 1, + InstructionType::CastBool | + InstructionType::CastPtr | + InstructionType::CastInt | + InstructionType::FnCall | + InstructionType::Return | + InstructionType::CastVoid | + InstructionType::TypeBool | + InstructionType::TypePtr | + InstructionType::TypeInt | + InstructionType::TypeVoid | + InstructionType::TypeStr | + InstructionType::TypeAny | + InstructionType::Returns | + InstructionType::With => ti += 1, InstructionType::None => unreachable!(), - InstructionType::FnCall => todo!(), - InstructionType::Return => todo!(), + InstructionType::ConstUse => todo!(), } } @@ -336,6 +340,7 @@ pub fn run(tokens: &[crate::constants::Operator]) -> Result{ KeywordType::Include => unreachable!(), KeywordType::Constant => todo!(), KeywordType::Function => todo!(), + KeywordType::FunctionDo => todo!(), } } diff --git a/src/lexer.rs b/src/lexer.rs index 7c36c3b..09931aa 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -1,5 +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) { @@ -89,7 +89,7 @@ fn lex_line(text: &str) -> Vec<(usize, String, TokenType)> { tokens } -pub fn lex + std::marker::Copy>(code: &str, file: S, args: &Args) -> Result> { +pub fn lex + std::marker::Copy>(code: &str, file: S, _args: &Args) -> Result> { let lines: Vec<(usize, &str)> = code .split(['\n', '\r']) .enumerate() diff --git a/src/main.rs b/src/main.rs index 52f7e55..c2080c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -53,8 +53,12 @@ pub struct Args { /// Unsafe mode, disables typechecking #[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')] //features: Vec, @@ -82,7 +86,7 @@ fn main() { return; }; - let Ok(tokens) = typechecker::typecheck(&tokens, &args) else { + let Ok(tokens) = typechecker::typecheck(tokens, &args) else { error!("Typechecking failed, exiting!"); return; }; diff --git a/src/parser.rs b/src/parser.rs index f4b21c4..f173137 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,11 +1,12 @@ use std::ops::Deref; -use crate::{constants::{Operator, OpType, Token, TokenType, Loc, KeywordType, InstructionType}, lerror, preprocessor::preprocess, Args}; +use crate::{constants::{Operator, OpType, Token, TokenType, Loc, KeywordType, InstructionType}, lerror, preprocessor::Preprocessor, Args}; use color_eyre::Result; use eyre::eyre; pub fn cross_ref(mut program: Vec) -> Result> { let mut stack: Vec = Vec::new(); + for ip in 0..program.len() { let op = &program.clone()[ip]; match op.typ { @@ -15,9 +16,12 @@ pub fn cross_ref(mut program: Vec) -> Result> { stack.push(ip); } OpType::Keyword(KeywordType::Else) => { - let if_ip = stack.pop().unwrap(); + let if_ip = if let Some(x) = stack.pop() { x } else { + lerror!(&op.loc, "Unclosed-if else block"); + return Err(eyre!("Cross referencing")); + }; 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")); } @@ -25,36 +29,48 @@ pub fn cross_ref(mut program: Vec) -> Result> { stack.push(ip); }, OpType::Keyword(KeywordType::End) => { - let block_ip = stack.pop().unwrap(); + let block_ip = if let Some(block_ip) = stack.pop() { block_ip } else { + lerror!(&op.loc, "Unclosed if, if-else, while-do, function, memory, or constant"); + return Err(eyre!("Cross referencing")); + }; + match &program[block_ip].typ { + OpType::Keyword(KeywordType::If) | + OpType::Keyword(KeywordType::Else) => { + program[block_ip].jmp = ip; + program[ip].jmp = ip + 1; + } - if program[block_ip].typ == OpType::Keyword(KeywordType::If) || - program[block_ip].typ == OpType::Keyword(KeywordType::Else) { - - program[block_ip].jmp = ip; - program[ip].jmp = ip + 1; + OpType::Keyword(KeywordType::Do) => { + program[ip].jmp = program[block_ip].jmp; + program[block_ip].jmp = ip + 1; + } + OpType::Keyword(KeywordType::FunctionDo) => { + program[ip].typ = OpType::Instruction(InstructionType::Return); + } + OpType::Keyword(KeywordType::Memory) | + OpType::Keyword(KeywordType::Function) | + OpType::Keyword(KeywordType::Constant) => (), - } else if program[block_ip].typ == OpType::Keyword(KeywordType::Do) { - program[ip].jmp = program[block_ip].jmp; - program[block_ip].jmp = ip + 1; - } else if program[block_ip].typ == OpType::Keyword(KeywordType::Function) { - program[ip].typ = OpType::Instruction(InstructionType::Return); - program[block_ip].typ = OpType::Keyword(KeywordType::Do); - } else { - lerror!(&op.clone().loc,"'end' can only close 'if' blocks"); - return Err(eyre!("")); + a => { + println!("{a:?}"); + lerror!(&op.clone().loc,"'end' can only close if, if-else, while-do, function, memory, or constant blocks"); + return Err(eyre!("")); + } } } OpType::Keyword(KeywordType::Do) => { - let block_ip = stack.pop().unwrap(); + let block_ip = if let Some(x) = stack.pop() { x } else { + lerror!(&op.loc, "Unclosed while-do block"); + return Err(eyre!("Cross referencing")); + }; if program[block_ip].typ == OpType::Keyword(KeywordType::Function) { - program[ip].typ = OpType::Keyword(KeywordType::Function); + program[ip].typ = OpType::Keyword(KeywordType::FunctionDo); } program[ip].jmp = block_ip; - // println!("{}", block_ip); stack.push(ip); } _ => () @@ -63,7 +79,7 @@ pub fn cross_ref(mut program: Vec) -> Result> { } if !stack.is_empty() { println!("{:?}", stack); - lerror!(&program[stack.pop().expect("Empy stack")].clone().loc,"Unclosed block"); + lerror!(&program[stack.pop().expect("Empy stack")].clone().loc,"Unclosed block, {:?}", program[stack.pop().expect("Empy stack")].clone()); return Err(eyre!("Unclosed block")); } @@ -116,14 +132,13 @@ impl Parser { } }; - - //"print" => tokens.push(Operator::new(OpType::Print, 0, token.file.clone(), token.line, token.col)), + } - - tokens = cross_ref(tokens.clone())?; - let t = preprocess(tokens, args)?; - Ok(t.0) + let t = Preprocessor::new(tokens.clone(), args).preprocess()?.get_ops(); + let t = cross_ref(t.clone())?; + + Ok(t) } } @@ -161,7 +176,6 @@ pub fn lookup_word>(s: &str, _pos: P) -> OpType { // mem - "mem" => OpType::Instruction(InstructionType::Mem), "load8" => OpType::Instruction(InstructionType::Load8), "store8" => OpType::Instruction(InstructionType::Store8), "load32" => OpType::Instruction(InstructionType::Load32), @@ -176,9 +190,10 @@ pub fn lookup_word>(s: &str, _pos: P) -> OpType { "syscall4" => OpType::Instruction(InstructionType::Syscall4), "syscall5" => OpType::Instruction(InstructionType::Syscall5), "syscall6" => OpType::Instruction(InstructionType::Syscall6), - "cast(bool" => OpType::Instruction(InstructionType::CastBool), + "cast(bool)" => OpType::Instruction(InstructionType::CastBool), "cast(ptr)" => OpType::Instruction(InstructionType::CastPtr), "cast(int)" => OpType::Instruction(InstructionType::CastInt), + "cast(void)" => OpType::Instruction(InstructionType::CastVoid), // block "if" => OpType::Keyword(KeywordType::If), "else" => OpType::Keyword(KeywordType::Else), @@ -189,6 +204,15 @@ pub fn lookup_word>(s: &str, _pos: P) -> OpType { "memory" => OpType::Keyword(KeywordType::Memory), "const" => OpType::Keyword(KeywordType::Constant), "fn" => OpType::Keyword(KeywordType::Function), + "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) } diff --git a/src/precompiler.rs b/src/precompiler.rs index b8bffa0..9c13343 100644 --- a/src/precompiler.rs +++ b/src/precompiler.rs @@ -2,7 +2,7 @@ use color_eyre::Result; use eyre::eyre; -use crate::{constants::{Token, OpType, InstructionType, Loc, Operator}, parser::lookup_word, lerror}; +use crate::{constants::{ OpType, InstructionType, Loc, Operator}, lerror}; fn stack_pop(stack: &mut Vec, loc: &Loc) -> Result { if let Some(i) = stack.pop() { Ok(i) } else { @@ -14,19 +14,13 @@ fn stack_pop(stack: &mut Vec, loc: &Loc) -> Result { pub fn precompile(tokens: &Vec) -> Result>{ let mut stack: Vec = Vec::new(); - for token in tokens.iter() { match token.typ.clone() { OpType::Instruction(i) => { let loc = token.loc.clone(); match i { InstructionType::PushInt => { - if let Ok(i) = token.text.parse::() { - stack.push(i); - } else { - lerror!(&token.loc, "Bad number"); - return Err(eyre!("")); - } + stack.push(token.value); }, InstructionType::Plus => { let a = stack_pop(&mut stack, &loc)?; diff --git a/src/preprocessor.rs b/src/preprocessor.rs index 5754bf4..c737d0c 100644 --- a/src/preprocessor.rs +++ b/src/preprocessor.rs @@ -1,251 +1,364 @@ use std::collections::HashMap; +use std::ops::Deref; use std::path::{PathBuf, Path}; use color_eyre::Result; use eyre::eyre; -use crate::constants::{Token, Loc, OpType, TokenType, KeywordType, InstructionType, Operator}; +use crate::constants::{Loc, OpType, TokenType, KeywordType, InstructionType, Operator}; use crate::lexer::lex; use crate::precompiler::precompile; -use crate::{lerror, lnote, Args, warn, linfo, parser}; +use crate::{lerror, Args, warn, linfo, parser}; use crate::parser::lookup_word; + + #[derive(Debug)] pub struct Function { pub loc: Loc, pub name: String } -type Functions = HashMap; -type Memories = HashMap; - -pub fn preprocess(tokens: Vec, args: &Args) -> Result<(Vec, Functions)>{ - - - let mut program: Vec = Vec::new(); - let mut functions: Functions = HashMap::new(); - let mut memories: Memories = HashMap::new(); - - let mut rtokens = tokens; - rtokens.reverse(); - while !rtokens.is_empty() { - let mut token = rtokens.pop().unwrap(); - - let op_type = token.typ.clone(); - match token.clone() { - - - _ if op_type == OpType::Keyword(KeywordType::Include) => { - if rtokens.is_empty() { - lerror!(&token.loc, "Include path not found, expected {} but found nothing", TokenType::String.human()); - return Err(eyre!("")); - } - - let include_path = rtokens.pop().unwrap(); - - if include_path.tok_typ != TokenType::String { - lerror!(&include_path.loc, "Bad include path, expected {} but found {}", TokenType::String.human(), include_path.typ.human()); - return Err(eyre!("")); - } - - let mut in_paths = args.include.clone(); - in_paths.append(&mut crate::DEFAULT_INCLUDES.to_vec().clone().iter().map(|f| (*f).to_string()).collect::>()); - - let mut include_code = String::new(); - - if include_path.text.chars().collect::>()[0] == '.' { - let p = Path::new(include_path.loc.0.as_str()); - let p = p.parent().unwrap(); - let p = p.join(&include_path.text); - include_code = std::fs::read_to_string(p)?; - } else { - for path in in_paths { - let p = PathBuf::from(path); - let p = p.join(&include_path.text); - - if p.exists() { - include_code = std::fs::read_to_string(p)?; - } - - } - } - - if include_code.is_empty() { - lerror!(&include_path.loc, "Include file in path '{}' was not found or is empty", include_path.text); - return Err(eyre!("")); - } - let code = lex(&include_code, &args.in_file, &args)?; - let mut p = parser::Parser::new(code); - let mut code = p.parse(args)?; - code.reverse(); - rtokens.append(&mut code); - - - } - _ if op_type == OpType::Keyword(KeywordType::Memory) => { - if rtokens.is_empty() { - lerror!(&token.loc, "Memory name not found, expected {} but found nothing", TokenType::String.human()); - return Err(eyre!("")); - } - - let memory_name = rtokens.pop().unwrap(); - - if memory_name.tok_typ != TokenType::Word { - lerror!(&memory_name.loc, "Bad memory name, expected {} but found {}", TokenType::Word.human(), memory_name.typ.human()); - return Err(eyre!("")); - } - - if functions.get(&memory_name.text).is_some() { - lerror!(&memory_name.loc, "Memory name cannot replace function name, got {}", memory_name.text); - let m = functions.get(&memory_name.text).unwrap(); - linfo!(&m.loc, "Function found here"); - return Err(eyre!("")); - } - - let mut code: Vec = Vec::new(); - - let mut depth = 0; - while !rtokens.is_empty() { - let t = rtokens.pop().unwrap(); - let typ = t.typ.clone(); - if typ == OpType::Keyword(KeywordType::End) && depth == 0 { - break; - } else if typ == OpType::Keyword(KeywordType::End) && depth != 0 { - depth -= 1; - code.push(t); - } else if typ == OpType::Keyword(KeywordType::If) || typ == OpType::Keyword(KeywordType::Do) { - code.push(t); - depth += 1; - } else { - code.push(t); - } - } - let res = precompile(&code)?; - - if res.len() != 1 { - lerror!(&token.loc, "Expected 1 number, got {:?}", res); - return Err(eyre!("")); - } - token.value = res[0]; - token.addr = Some(memories.len()); - program.push(token); - - memories.insert(memory_name.text, 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 function_name = rtokens.pop().unwrap(); - - if function_name.tok_typ != TokenType::Word { - lerror!(&function_name.loc, "Bad Function name, expected {} but found {}", TokenType::Word.human(), function_name.typ.human()); - return Err(eyre!("")); - } - - if memories.get(&function_name.text).is_some() { - lerror!(&function_name.loc, "Function name cannot replace memory name, got {}", function_name.text); - return Err(eyre!("")); - } - - if functions.get(&function_name.text).is_some() { - lerror!(&function_name.loc, "Functions cannot be redefined, got {}", function_name.text); - return Err(eyre!("")); - } - - functions.insert(function_name.text.clone(), Function{ - loc: function_name.loc.clone(), - name: function_name.text.clone(), - }); - token.text = function_name.text; - rtokens.pop(); - program.push(token); - } - - _ => { - if op_type == OpType::Keyword(KeywordType::Do) { - println!("{:?}", token); - } - program.push(token); - } - } - } - - //* Feel free to fix this horrifying shit - //* i wanna kms - let mut times = 0; - while program.iter().map(|f| { - if f.tok_typ == TokenType::Word && f.typ != OpType::Instruction(InstructionType::FnCall) && f.typ != OpType::Instruction(InstructionType::MemUse){ - lookup_word(&f.text, &f.loc) - } else { - OpType::Instruction(InstructionType::PushInt) // i hate myself, this is a randomly picked optype so its happy and works - } - - }).collect::>().contains(&OpType::Instruction(InstructionType::None)){ - - if times >= 50 { - warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it"); - break - } - program = expand(program, &functions, &memories)?; - times += 1; - } - - - Ok((program, functions)) +#[derive(Debug)] +pub struct Constant { + pub loc: Loc, + pub name: String } -pub fn expand(tokens: Vec, funcs: &Functions, mems: &Memories) -> Result> { - let mut program: Vec = Vec::new(); +#[derive(Debug)] +pub struct Memory { + pub loc: Loc, + pub id: usize + +} - let mut rtokens = tokens.clone(); - rtokens.reverse(); +type Functions = HashMap; +type Memories = HashMap; +type Constants = HashMap; - while !rtokens.is_empty() { - let op = rtokens.pop().unwrap(); - let op_type = op.typ.clone(); - if op.tok_typ.clone() == TokenType::Word { - match op_type { - OpType::Instruction(InstructionType::None) => { - let m = funcs.get(&op.text); - let mem = mems.get(&op.text); - if let Some(m) = m { - let mut t = op.clone(); - t.typ = OpType::Instruction(InstructionType::FnCall); - t.text = m.name.clone(); - program.push(t); - } else - if let Some(mem) = mem { - let mut t = op.clone(); - t.addr = Some(*mem); - t.typ = OpType::Instruction(InstructionType::MemUse); - program.push(t); - } - else { - lerror!(&op.loc, "expand: Unknown word '{}'", op.text.clone()); - return Err(eyre!("")); - } - } - _ => { - program.push(op.clone()); - } - } - } else { - program.push(op.clone()); +pub struct Preprocessor<'a> { + program: Vec, + functions: Functions, + memories: Memories, + constants: Constants, + args: &'a Args +} + + +impl<'a> Preprocessor<'a> { + pub fn new(prog: Vec, args: &'a Args) -> Self { + Self { + program: prog, + args: args, + functions: HashMap::new(), + memories: HashMap::new(), + constants: HashMap::new(), } - - if op.typ == OpType::Keyword(KeywordType::Do) { - println!("expand: {:?}", op); - } - } + 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::>>()); + + let mut program: Vec = Vec::new(); + + let mut rtokens = self.program.clone(); + rtokens.reverse(); + while !rtokens.is_empty() { + let mut token = rtokens.pop().unwrap(); + // println!("{token:?}"); + let op_type = token.typ.clone(); + match token.clone() { + + + _ if op_type == OpType::Keyword(KeywordType::Include) => { + if rtokens.is_empty() { + lerror!(&token.loc, "Include path not found, expected {} but found nothing", TokenType::String.human()); + return Err(eyre!("")); + } + + let include_path = rtokens.pop().unwrap(); + + if include_path.tok_typ != TokenType::String { + lerror!(&include_path.loc, "Bad include path, expected {} but found {}", TokenType::String.human(), include_path.typ.human()); + return Err(eyre!("")); + } + + 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::>()); + + let mut include_code = String::new(); + + if include_path.text.chars().collect::>()[0] == '.' { + let p = Path::new(include_path.loc.0.as_str()); + let p = p.parent().unwrap(); + let p = p.join(&include_path.text); + include_code = std::fs::read_to_string(p)?; + } else { + for path in in_paths { + let p = PathBuf::from(path); + let p = p.join(&include_path.text); + + if p.exists() { + include_code = std::fs::read_to_string(p)?; + } + + } + } + + if include_code.is_empty() { + lerror!(&include_path.loc, "Include file in path '{}' was not found or is empty", include_path.text); + return Err(eyre!("")); + } + let code = lex(&include_code, &self.args.in_file, &self.args)?; + let mut p = parser::Parser::new(code); + let mut code = p.parse(self.args)?; + code.reverse(); + rtokens.append(&mut code); + } + _ if op_type == OpType::Keyword(KeywordType::Memory) => { + if rtokens.is_empty() { + lerror!(&token.loc, "Memory name not found, expected {} but found nothing", TokenType::String.human()); + return Err(eyre!("")); + } - Ok(program) + let memory_name = rtokens.pop().unwrap(); + + self.is_word_available(&memory_name, KeywordType::Function)?; + + let mut code: Vec = Vec::new(); + + let mut depth = 0; + while !rtokens.is_empty() { + let t = rtokens.pop().unwrap(); + let typ = t.typ.clone(); + if typ == OpType::Keyword(KeywordType::End) && depth == 0 { + break; + } else if typ == OpType::Keyword(KeywordType::End) && depth != 0 { + depth -= 1; + code.push(t); + } else if typ == OpType::Keyword(KeywordType::If) || typ == OpType::Keyword(KeywordType::Do) { + code.push(t); + depth += 1; + } else { + code.push(t); + } + } + let res = precompile(&code)?; + + + if res.len() != 1 { + lerror!(&token.loc, "Expected 1 number, got {:?}", res); + return Err(eyre!("")); + } + token.value = res[0]; + token.addr = Some(self.memories.len()); + program.push(token.clone()); + + self.memories.insert(memory_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 function_name = rtokens.pop().unwrap(); + + self.is_word_available(&function_name, KeywordType::Function)?; + + + self.functions.insert(function_name.text.clone(), Function{ + loc: function_name.loc.clone(), + name: function_name.text.clone(), + }); + token.text = function_name.text; + // println!("{:?}", token); + program.push(token); + } + _ 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!("")); + } + + let const_name = rtokens.pop().unwrap(); + + self.is_word_available(&const_name, KeywordType::Function)?; + + + self.constants.insert(const_name.text.clone(), Constant{ + loc: const_name.loc.clone(), + name: const_name.text.clone(), + }); + token.text = const_name.text; + let item = rtokens.pop().unwrap(); + if item.tok_typ == TokenType::Int { + token.value = item.value; + } + + if let None = rtokens.pop() { + lerror!(&token.loc, "Constant was not closed with an 'end' instruction, expected 'end' but found nothing"); + return Err(eyre!("")); + } + // token.value = + + 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::>>()); + //* Feel free to fix this horrifying shit + //* i wanna kms + let mut times = 0; + // dbg!(program.clone()); + while self.program.iter().map(|f| { + if f.tok_typ == TokenType::Word && f.typ != OpType::Instruction(InstructionType::FnCall) && f.typ != OpType::Instruction(InstructionType::MemUse) && f.typ != OpType::Keyword(KeywordType::Function) && f.typ != OpType::Keyword(KeywordType::Constant) && f.typ != OpType::Instruction(InstructionType::ConstUse) { + lookup_word(&f.text, &f.loc) + } else { + OpType::Instruction(InstructionType::PushInt) // i hate myself, this is a randomly picked optype so its happy and works + } + + }).collect::>().contains(&OpType::Instruction(InstructionType::None)){ + + if times >= 50 { + warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it"); + break + } + self.expand()?; + times += 1; + } + + Ok(self) + } + + pub fn expand(&mut self) -> Result<()> { + let mut program: Vec = Vec::new(); + // println!("{:?}", self.functions); + let mut rtokens = self.program.clone(); + rtokens.reverse(); + + while !rtokens.is_empty() { + let op = rtokens.pop().unwrap(); + let op_type = op.typ.clone(); + if op.tok_typ.clone() == TokenType::Word { + match op_type { + OpType::Instruction(InstructionType::None) => { + let m = self.functions.get(&op.text); + let mem = self.memories.get(&op.text); + let cons = self.constants.get(&op.text); + if let Some(m) = m { + // println!("------ FOUND FUNCTION {} -----------", m.name); + let mut t = op.clone(); + t.typ = OpType::Instruction(InstructionType::FnCall); + t.text = m.name.clone(); + program.push(t.clone()); + + // 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); + } else if let Some(cons) = cons { + let mut t = op.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!("")); + } + } + _ => { + program.push(op.clone()); + } + } + } else { + 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::>>()); + + self.program = program; + // println!("{:#?}", self.program); + println!("{:?}", self.program.last().unwrap()); + Ok(()) + } + + + + pub fn get_ops(&mut self) -> Vec { + self.program.clone() + } + pub fn is_word_available(&self, word: &Operator, typ: KeywordType) -> Result { + + match typ { + KeywordType::Memory | + KeywordType::Constant | + KeywordType::Function => (), + _ => panic!() + } + + if word.tok_typ != TokenType::Word { + lerror!(&word.loc, "Bad Function name, expected {} but found {}", TokenType::Word.human(), word.typ.human()); + return Err(eyre!("")); + } + + let m = self.memories.get(&word.text); + if let Some(m) = m { + if typ != KeywordType::Memory { + lerror!(&word.loc, "{typ:?} cannot replace memory, got {}", word.text); + linfo!(&m.loc, "first definition here"); + return Err(eyre!("")); + } else { + lerror!(&word.loc, "Memories cannot be redefined, got {}", word.text); + linfo!(&m.loc, "first definition here"); + return Err(eyre!("")); + } + } + let f = self.functions.get(&word.text); + if let Some(f) = f { + if typ != KeywordType::Function { + lerror!(&word.loc, "{typ:?} cannot replace function, got {}", word.text); + linfo!(&f.loc, "first definition here"); + return Err(eyre!("")); + } else { + lerror!(&word.loc, "Functions cannot be redefined, got {}", word.text); + linfo!(&f.loc, "first definition here"); + return Err(eyre!("")); + } + } + let c = self.constants.get(&word.text); + if let Some(c) = c { + if typ != KeywordType::Constant { + lerror!(&word.loc, "{typ:?} cannot replace constant, got {}", word.text); + linfo!(&c.loc, "first definition here"); + return Err(eyre!("")); + } else { + lerror!(&word.loc, "Constants cannot be redefined, got {}", word.text); + linfo!(&c.loc, "first definition here"); + return Err(eyre!("")); + } + } + + Ok(true) + } } \ No newline at end of file diff --git a/src/typechecker.rs b/src/typechecker.rs index 3647bbb..e95ed10 100644 --- a/src/typechecker.rs +++ b/src/typechecker.rs @@ -1,19 +1,43 @@ -use crate::{constants::{Operator, Types, OpType, KeywordType, InstructionType}, Args, lerror, warn}; +use std::collections::HashMap; + +use crate::{constants::{Operator, Types, OpType, KeywordType, InstructionType}, Args, lerror, warn, note}; use color_eyre::Result; use eyre::eyre; +#[derive(Debug, Clone)] +struct Function { + args: Vec, + returns: Vec, +} +impl Function { + pub fn default() -> Self { + Self { + args: Vec::new(), + returns: Vec::new(), + } + } +} -pub fn typecheck(ops: &[Operator], args: &Args) -> Result>{ +pub fn typecheck(ops: Vec, args: &Args) -> Result>{ if args.unsaf { if !args.quiet { warn!("Unsafe mode enabled, disabling typechecker, goodluck"); } return Ok(ops.to_vec()); } - + + let mut functions: HashMap = HashMap::new(); + // let mut in_function: (String, Function) = (String::new(), Function::default()); let mut stack: Vec = Vec::new(); - - for op in ops { + let mut stack_snapshots: Vec> = Vec::new(); + let mut rtokens = ops.clone(); + 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() { OpType::Keyword(keyword) => { match keyword { @@ -24,13 +48,94 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result>{ stack_pop(&mut stack, &op, &[Types::Bool])?; }, + KeywordType::Function => { + 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(), + }; + 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::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::FunctionDo) { + break; + } + p = rtokens.pop(); + }; + functions.insert(name.clone(), func.clone()); + + // if name == "main" { + // in_function = (name, func.clone()); + // } + if func.args != vec![Types::Void] { + stack.append(&mut func.args); + } + stack_snapshots.push(stack.clone()); + } + KeywordType::Else | KeywordType::End | KeywordType::While | - KeywordType::Function | KeywordType::Include | KeywordType::Constant | KeywordType::Memory => (), + KeywordType::FunctionDo => (), } }, OpType::Instruction(instruction) => { @@ -76,42 +181,42 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result>{ }, InstructionType::Minus => { 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::Int); }, InstructionType::Plus => { 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::Int); }, InstructionType::Equals => { - stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?; - stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?; + stack_pop(&mut stack, &op, &[Types::Int])?; + stack_pop(&mut stack, &op, &[Types::Int])?; 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_pop(&mut stack, &op, &[Types::Int])?; + stack_pop(&mut stack, &op, &[Types::Int])?; 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_pop(&mut stack, &op, &[Types::Int])?; + stack_pop(&mut stack, &op, &[Types::Int])?; 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_pop(&mut stack, &op, &[Types::Int])?; + stack_pop(&mut stack, &op, &[Types::Int])?; 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_pop(&mut stack, &op, &[Types::Int])?; + stack_pop(&mut stack, &op, &[Types::Int])?; stack.push(Types::Bool); }, InstructionType::NotEquals => { - stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?; - stack_pop(&mut stack, &op, &[Types::Int, Types::Ptr])?; + stack_pop(&mut stack, &op, &[Types::Int])?; + stack_pop(&mut stack, &op, &[Types::Int])?; stack.push(Types::Bool); }, InstructionType::Band => { @@ -145,9 +250,6 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result>{ stack_pop(&mut stack, &op, &[Types::Int])?; stack.push(Types::Int); }, - InstructionType::Mem => { - stack.push(Types::Ptr); - }, InstructionType::Load8 => { stack_pop(&mut stack, &op, &[Types::Ptr])?; stack.push(Types::Int); @@ -233,18 +335,73 @@ pub fn typecheck(ops: &[Operator], args: &Args) -> Result>{ stack_pop(&mut stack, &op, &[Types::Any])?; stack.push(Types::Int); }, + InstructionType::CastVoid => { + stack_pop(&mut stack, &op, &[Types::Any])?; + stack.push(Types::Any); + }, InstructionType::MemUse => { stack.push(Types::Ptr); }, - InstructionType::FnCall | - InstructionType::Return | + InstructionType::FnCall => { + stack_snapshots.push(stack.clone()); + + let f = functions.get(&op.text).unwrap(); + + 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!("")); + } + } + + + } + InstructionType::Return => { + let snap = stack_snapshots.pop().unwrap(); + // snap.append(&mut f.returns.clone()); + let mut st = stack.clone(); + for s in snap{ + if let Some(sn) = st.pop(){ + if s != sn { + lerror!(&op.loc, "Expected {:?}, but got {:?}", s, sn); + return Err(eyre!("")); + } + } else { + lerror!(&op.loc, "Expected {:?}, but got nothing", s); + return Err(eyre!("")); + } + } + } InstructionType::None => {}, + + InstructionType::TypeBool | + InstructionType::TypePtr | + InstructionType::TypeInt | + InstructionType::TypeVoid | + InstructionType::TypeAny | + InstructionType::TypeStr | + InstructionType::Returns | + InstructionType::With => (), + InstructionType::ConstUse => todo!(), } }, + } - } - Ok(ops.to_vec()) + + } + + Ok(ops.clone()) } diff --git a/test.mcl b/test.mcl index 956debb..4d7f2a1 100644 --- a/test.mcl +++ b/test.mcl @@ -1,7 +1,5 @@ include "std.mcl" -fn main do - -"henlo" puts - -end +fn main with void returns void do + 69 putd +end \ No newline at end of file