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}:")?;
|
||||||
|
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 {
|
||||||
|
|
||||||
writeln!(writer, "addr_{ti}:")?;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, " mem: resb {}", crate::compile::MEM_SZ)?;
|
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
80
src/main.rs
80
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);
|
||||||
error!("Parsing failed, exiting!");
|
let tokens = match parser.parse(){
|
||||||
return;
|
Ok(t) => t,
|
||||||
|
Err(e) => {
|
||||||
|
error!("Parsing failed, exiting!");
|
||||||
|
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()) {
|
||||||
error!("Typechecking failed, exiting!");
|
Ok(_) => (),
|
||||||
return;
|
Err(e) => {
|
||||||
|
error!("Typechecking failed, exiting!");
|
||||||
|
if crate::DEV_MODE {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let c = if args.compile && args.interpret {
|
let c = if args.compile && args.interpret {
|
||||||
|
|
120
src/parser.rs
120
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");
|
||||||
|
return Err(eyre!("Cross referencing"));
|
||||||
|
};
|
||||||
|
|
||||||
if program[block_ip].typ == OpType::Keyword(KeywordType::If) ||
|
match &program[block_ip].typ {
|
||||||
program[block_ip].typ == OpType::Keyword(KeywordType::Else) {
|
OpType::Keyword(KeywordType::If | KeywordType::Else) => {
|
||||||
|
program[block_ip].jmp = ip;
|
||||||
|
program[ip].jmp = ip + 1;
|
||||||
|
}
|
||||||
|
|
||||||
program[block_ip].jmp = ip;
|
OpType::Keyword(KeywordType::Do) => {
|
||||||
program[ip].jmp = ip + 1;
|
program[ip].jmp = program[block_ip].jmp;
|
||||||
|
program[block_ip].jmp = ip + 1;
|
||||||
|
}
|
||||||
|
OpType::Keyword(KeywordType::FunctionThen) => {
|
||||||
|
program[ip].typ = OpType::Instruction(InstructionType::Return);
|
||||||
|
}
|
||||||
|
OpType::Keyword(KeywordType::Memory | KeywordType::Constant) => (),
|
||||||
|
|
||||||
} else if program[block_ip].typ == OpType::Keyword(KeywordType::Do) {
|
a => {
|
||||||
program[ip].jmp = program[block_ip].jmp;
|
println!("{a:?}");
|
||||||
program[block_ip].jmp = ip + 1;
|
lerror!(&op.clone().loc,"'end' can only close if, if-else, while-do, function, memory, or constant blocks");
|
||||||
} else {
|
return Err(eyre!(""));
|
||||||
lerror!(&op.clone().loc,"'end' can only close 'if' blocks");
|
}
|
||||||
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,255 +1,475 @@
|
||||||
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,
|
||||||
let mut rtokens = tokens;
|
args,
|
||||||
rtokens.reverse();
|
functions: HashMap::new(),
|
||||||
while !rtokens.is_empty() {
|
memories: HashMap::new(),
|
||||||
let mut token = rtokens.pop().unwrap();
|
constants: HashMap::new(),
|
||||||
|
|
||||||
let op_type = lookup_word(&token.text, &token.loc());
|
|
||||||
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 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.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::<Vec<String>>());
|
|
||||||
|
|
||||||
let mut include_code = String::new();
|
|
||||||
|
|
||||||
if include_path.text.chars().collect::<Vec<char>>()[0] == '.' {
|
|
||||||
let p = Path::new(include_path.file.as_str());
|
|
||||||
let p = p.parent().unwrap();
|
|
||||||
let p = p.join(&include_path.text);
|
|
||||||
include_code = std::fs::read_to_string(p)?;
|
|
||||||
} else {
|
|
||||||
for path in in_paths {
|
|
||||||
let p = PathBuf::from(path);
|
|
||||||
let p = p.join(&include_path.text);
|
|
||||||
|
|
||||||
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 mut code = lex(&include_code, &include_path.text, args, false)?;
|
|
||||||
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.typ != TokenType::Word {
|
|
||||||
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() {
|
|
||||||
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;
|
|
||||||
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;
|
|
||||||
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 = Some(res[0]);
|
|
||||||
token.addr = Some(memories.len());
|
|
||||||
program.push(token);
|
|
||||||
|
|
||||||
memories.insert(memory_name.text, memories.len());
|
|
||||||
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
program.push(token);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//* Feel free to fix this horrifying shit
|
|
||||||
//* i wanna kms
|
|
||||||
let mut times = 0;
|
|
||||||
while program.iter().map(|f| {
|
|
||||||
if f.typ == TokenType::Word && f.op_typ != 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::<Vec<OpType>>().contains(&OpType::Instruction(InstructionType::None)){
|
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>>>());
|
||||||
|
|
||||||
if times >= 50 {
|
let mut program: Vec<Operator> = Vec::new();
|
||||||
warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it");
|
|
||||||
break
|
let mut rtokens = self.program.clone();
|
||||||
}
|
rtokens.reverse();
|
||||||
program = expand(program, ¯os, &memories)?;
|
while !rtokens.is_empty() {
|
||||||
times += 1;
|
let mut token = rtokens.pop().unwrap();
|
||||||
}
|
// println!("{token:?}");
|
||||||
|
let op_type = token.typ.clone();
|
||||||
|
match token.clone() {
|
||||||
|
|
||||||
|
|
||||||
Ok(program)
|
_ 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());
|
||||||
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();
|
|
||||||
|
|
||||||
while !rtokens.is_empty() {
|
|
||||||
let op = rtokens.pop().unwrap();
|
|
||||||
let op_type = lookup_word(&op.text, &op.loc());
|
|
||||||
if op.typ == TokenType::Word {
|
|
||||||
match op_type {
|
|
||||||
OpType::Instruction(InstructionType::None) => {
|
|
||||||
let m = macros.get(&op.text);
|
|
||||||
let mem = mems.get(&op.text);
|
|
||||||
if let Some(m) = m {
|
|
||||||
program.append(&mut m.tokens.clone());
|
|
||||||
} else
|
|
||||||
if let Some(mem) = mem {
|
|
||||||
let mut t = op;
|
|
||||||
t.addr = Some(*mem);
|
|
||||||
t.op_typ = InstructionType::MemUse;
|
|
||||||
program.push(t);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lerror!(&op.loc(), "Unknown word '{}'", op.text.clone());
|
|
||||||
return Err(eyre!(""));
|
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::<Vec<String>>());
|
||||||
|
|
||||||
|
let mut include_code = String::new();
|
||||||
|
let mut pth = PathBuf::new();
|
||||||
|
if include_path.text.chars().collect::<Vec<char>>()[0] == '.' {
|
||||||
|
let p = Path::new(include_path.loc.0.as_str());
|
||||||
|
let p = p.parent().unwrap();
|
||||||
|
let p = p.join(&include_path.text);
|
||||||
|
pth = p.clone();
|
||||||
|
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);
|
||||||
|
pth = p.clone();
|
||||||
|
|
||||||
|
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 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()?;
|
||||||
|
|
||||||
|
self.set_constants(p.preprocessor.get_constants());
|
||||||
|
self.set_functions(p.preprocessor.get_functions());
|
||||||
|
self.set_memories(p.preprocessor.get_memories());
|
||||||
|
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 name = rtokens.pop().unwrap();
|
||||||
|
|
||||||
|
self.is_word_available(&name, KeywordType::Memory)?;
|
||||||
|
|
||||||
|
let mut code: Vec<Operator> = 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(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(op);
|
|
||||||
|
program.push(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
program.push(op);
|
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
//* 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::FunctionDef) &&
|
||||||
|
f.typ != OpType::Keyword(KeywordType::ConstantDef) &&
|
||||||
|
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::<Vec<OpType>>().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<Operator> = 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 == 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::<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!(""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
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(ops.to_vec())
|
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