started implementing stdlib

This commit is contained in:
MCorange 2023-03-20 16:13:34 +02:00
parent 2d5e94608c
commit d536bfcf31
11 changed files with 445 additions and 38 deletions

42
include/io.mcl Normal file
View File

@ -0,0 +1,42 @@
include "linux.mcl"
// Write to a file descriptor using the SYS_write syscall
// args: [str_size, str_ptr, fd]
// @arg str_size: Int
// @arg str_ptr: Ptr
// @arg fd: Int
// @ret Int
macro write
SYS_write syscall3
end
// Print a string to STDOUT
// args: [str_size, str_ptr]
// @arg str_size: Int
// @arg str_ptr: Ptr
// @ret NULL
macro puts
STDOUT write drop
end
// Print a string to STDERR
// args: [str_size, str_ptr]
// @arg str_size: Int
// @arg str_ptr: Ptr
// @ret NULL
macro eputs
STDOUT write drop
end
// TODO: make putc and eputc after we make local mem
// Exit the program with exit_code
// args: [exit_code]
// @arg exit_code: Int
// @ret NULL/NEVER
macro exit
SYS_exit syscall1 drop
end

322
include/linux.mcl Normal file
View File

@ -0,0 +1,322 @@
// file descriptors
macro STDIN 0 end
macro STDOUT 1 end
macro STDERR 2 end
// syscalls
macro SYS_read 0 end
macro SYS_write 1 end
macro SYS_open 2 end
macro SYS_close 3 end
macro SYS_stat 4 end
macro SYS_fstat 5 end
macro SYS_lstat 6 end
macro SYS_poll 7 end
macro SYS_lseek 8 end
macro SYS_mmap 9 end
macro SYS_mprotect 10 end
macro SYS_munmap 11 end
macro SYS_brk 12 end
macro SYS_rt_sigaction 13 end
macro SYS_rt_sigprocmask 14 end
macro SYS_rt_sigreturn 15 end
macro SYS_ioctl 16 end
macro SYS_pread64 17 end
macro SYS_pwrite64 18 end
macro SYS_readv 19 end
macro SYS_writev 20 end
macro SYS_access 21 end
macro SYS_pipe 22 end
macro SYS_select 23 end
macro SYS_sched_yield 24 end
macro SYS_mremap 25 end
macro SYS_msync 26 end
macro SYS_mincore 27 end
macro SYS_madvise 28 end
macro SYS_shmget 29 end
macro SYS_shmat 30 end
macro SYS_shmctl 31 end
macro SYS_dup 32 end
macro SYS_dup2 33 end
macro SYS_pause 34 end
macro SYS_nanosleep 35 end
macro SYS_getitimer 36 end
macro SYS_alarm 37 end
macro SYS_setitimer 38 end
macro SYS_getpid 39 end
macro SYS_sendfile 40 end
macro SYS_socket 41 end
macro SYS_connect 42 end
macro SYS_accept 43 end
macro SYS_sendto 44 end
macro SYS_recvfrom 45 end
macro SYS_sendmsg 46 end
macro SYS_recvmsg 47 end
macro SYS_shutdown 48 end
macro SYS_bind 49 end
macro SYS_listen 50 end
macro SYS_getsockname 51 end
macro SYS_getpeername 52 end
macro SYS_socketpair 53 end
macro SYS_setsockopt 54 end
macro SYS_getsockopt 55 end
macro SYS_clone 56 end
macro SYS_fork 57 end
macro SYS_vfork 58 end
macro SYS_execve 59 end
macro SYS_exit 60 end
macro SYS_wait4 61 end
macro SYS_kill 62 end
macro SYS_uname 63 end
macro SYS_semget 64 end
macro SYS_semop 65 end
macro SYS_semctl 66 end
macro SYS_shmdt 67 end
macro SYS_msgget 68 end
macro SYS_msgsnd 69 end
macro SYS_msgrcv 70 end
macro SYS_msgctl 71 end
macro SYS_fcntl 72 end
macro SYS_flock 73 end
macro SYS_fsync 74 end
macro SYS_fdatasync 75 end
macro SYS_truncate 76 end
macro SYS_ftruncate 77 end
macro SYS_getdents 78 end
macro SYS_getcwd 79 end
macro SYS_chdir 80 end
macro SYS_fchdir 81 end
macro SYS_rename 82 end
macro SYS_mkdir 83 end
macro SYS_rmdir 84 end
macro SYS_creat 85 end
macro SYS_link 86 end
macro SYS_unlink 87 end
macro SYS_symlink 88 end
macro SYS_readlink 89 end
macro SYS_chmod 90 end
macro SYS_fchmod 91 end
macro SYS_chown 92 end
macro SYS_fchown 93 end
macro SYS_lchown 94 end
macro SYS_umask 95 end
macro SYS_gettimeofday 96 end
macro SYS_getrlimit 97 end
macro SYS_getrusage 98 end
macro SYS_sysinfo 99 end
macro SYS_times 100 end
macro SYS_ptrace 101 end
macro SYS_getuid 102 end
macro SYS_syslog 103 end
macro SYS_getgid 104 end
macro SYS_setuid 105 end
macro SYS_setgid 106 end
macro SYS_geteuid 107 end
macro SYS_getegid 108 end
macro SYS_setpgid 109 end
macro SYS_getppid 110 end
macro SYS_getpgrp 111 end
macro SYS_setsid 112 end
macro SYS_setreuid 113 end
macro SYS_setregid 114 end
macro SYS_getgroups 115 end
macro SYS_setgroups 116 end
macro SYS_setresuid 117 end
macro SYS_getresuid 118 end
macro SYS_setresgid 119 end
macro SYS_getresgid 120 end
macro SYS_getpgid 121 end
macro SYS_setfsuid 122 end
macro SYS_setfsgid 123 end
macro SYS_getsid 124 end
macro SYS_capget 125 end
macro SYS_capset 126 end
macro SYS_rt_sigpending 127 end
macro SYS_rt_sigtimedwait 128 end
macro SYS_rt_sigqueueinfo 129 end
macro SYS_rt_sigsuspend 130 end
macro SYS_sigaltstack 131 end
macro SYS_utime 132 end
macro SYS_mknod 133 end
macro SYS_uselib 134 end
macro SYS_personality 135 end
macro SYS_ustat 136 end
macro SYS_statfs 137 end
macro SYS_fstatfs 138 end
macro SYS_sysfs 139 end
macro SYS_getpriority 140 end
macro SYS_setpriority 141 end
macro SYS_sched_setparam 142 end
macro SYS_sched_getparam 143 end
macro SYS_sched_setscheduler 144 end
macro SYS_sched_getscheduler 145 end
macro SYS_sched_get_priority_max 146 end
macro SYS_sched_get_priority_min 147 end
macro SYS_sched_rr_get_interval 148 end
macro SYS_mlock 149 end
macro SYS_munlock 150 end
macro SYS_mlockall 151 end
macro SYS_munlockall 152 end
macro SYS_vhangup 153 end
macro SYS_modify_ldt 154 end
macro SYS_pivot_root 155 end
macro SYS__sysctl 156 end
macro SYS_prctl 157 end
macro SYS_arch_prctl 158 end
macro SYS_adjtimex 159 end
macro SYS_setrlimit 160 end
macro SYS_chroot 161 end
macro SYS_sync 162 end
macro SYS_acct 163 end
macro SYS_settimeofday 164 end
macro SYS_mount 165 end
macro SYS_umount2 166 end
macro SYS_swapon 167 end
macro SYS_swapoff 168 end
macro SYS_reboot 169 end
macro SYS_sethostname 170 end
macro SYS_setdomainname 171 end
macro SYS_iopl 172 end
macro SYS_ioperm 173 end
macro SYS_create_module 174 end
macro SYS_init_module 175 end
macro SYS_delete_module 176 end
macro SYS_get_kernel_syms 177 end
macro SYS_query_module 178 end
macro SYS_quotactl 179 end
macro SYS_nfsservctl 180 end
macro SYS_getpmsg 181 end
macro SYS_putpmsg 182 end
macro SYS_afs_syscall 183 end
macro SYS_tuxcall 184 end
macro SYS_security 185 end
macro SYS_gettid 186 end
macro SYS_readahead 187 end
macro SYS_setxattr 188 end
macro SYS_lsetxattr 189 end
macro SYS_fsetxattr 190 end
macro SYS_getxattr 191 end
macro SYS_lgetxattr 192 end
macro SYS_fgetxattr 193 end
macro SYS_listxattr 194 end
macro SYS_llistxattr 195 end
macro SYS_flistxattr 196 end
macro SYS_removexattr 197 end
macro SYS_lremovexattr 198 end
macro SYS_fremovexattr 199 end
macro SYS_tkill 200 end
macro SYS_time 201 end
macro SYS_futex 202 end
macro SYS_sched_setaffinity 203 end
macro SYS_sched_getaffinity 204 end
macro SYS_set_thread_area 205 end
macro SYS_io_setup 206 end
macro SYS_io_destroy 207 end
macro SYS_io_getevents 208 end
macro SYS_io_submit 209 end
macro SYS_io_cancel 210 end
macro SYS_get_thread_area 211 end
macro SYS_lookup_dcookie 212 end
macro SYS_epoll_create 213 end
macro SYS_epoll_ctl_old 214 end
macro SYS_epoll_wait_old 215 end
macro SYS_remap_file_pages 216 end
macro SYS_getdents64 217 end
macro SYS_set_tid_address 218 end
macro SYS_restart_syscall 219 end
macro SYS_semtimedop 220 end
macro SYS_fadvise64 221 end
macro SYS_timer_create 222 end
macro SYS_timer_settime 223 end
macro SYS_timer_gettime 224 end
macro SYS_timer_getoverrun 225 end
macro SYS_timer_delete 226 end
macro SYS_clock_settime 227 end
macro SYS_clock_gettime 228 end
macro SYS_clock_getres 229 end
macro SYS_clock_nanosleep 230 end
macro SYS_exit_group 231 end
macro SYS_epoll_wait 232 end
macro SYS_epoll_ctl 233 end
macro SYS_tgkill 234 end
macro SYS_utimes 235 end
macro SYS_vserver 236 end
macro SYS_mbind 237 end
macro SYS_set_mempolicy 238 end
macro SYS_get_mempolicy 239 end
macro SYS_mq_open 240 end
macro SYS_mq_unlink 241 end
macro SYS_mq_timedsend 242 end
macro SYS_mq_timedreceive 243 end
macro SYS_mq_notify 244 end
macro SYS_mq_getsetattr 245 end
macro SYS_kexec_load 246 end
macro SYS_waitid 247 end
macro SYS_add_key 248 end
macro SYS_request_key 249 end
macro SYS_keyctl 250 end
macro SYS_ioprio_set 251 end
macro SYS_ioprio_get 252 end
macro SYS_inotify_init 253 end
macro SYS_inotify_add_watch 254 end
macro SYS_inotify_rm_watch 255 end
macro SYS_migrate_pages 256 end
macro SYS_openat 257 end
macro SYS_mkdirat 258 end
macro SYS_mknodat 259 end
macro SYS_fchownat 260 end
macro SYS_futimesat 261 end
macro SYS_newfstatat 262 end
macro SYS_unlinkat 263 end
macro SYS_renameat 264 end
macro SYS_linkat 265 end
macro SYS_symlinkat 266 end
macro SYS_readlinkat 267 end
macro SYS_fchmodat 268 end
macro SYS_faccessat 269 end
macro SYS_pselect6 270 end
macro SYS_ppoll 271 end
macro SYS_unshare 272 end
macro SYS_set_robust_list 273 end
macro SYS_get_robust_list 274 end
macro SYS_splice 275 end
macro SYS_tee 276 end
macro SYS_sync_file_range 277 end
macro SYS_vmsplice 278 end
macro SYS_move_pages 279 end
macro SYS_utimensat 280 end
macro SYS_epoll_pwait 281 end
macro SYS_signalfd 282 end
macro SYS_timerfd_create 283 end
macro SYS_eventfd 284 end
macro SYS_fallocate 285 end
macro SYS_timerfd_settime 286 end
macro SYS_timerfd_gettime 287 end
macro SYS_accept4 288 end
macro SYS_signalfd4 289 end
macro SYS_eventfd2 290 end
macro SYS_epoll_create1 291 end
macro SYS_dup3 292 end
macro SYS_pipe2 293 end
macro SYS_inotify_init1 294 end
macro SYS_preadv 295 end
macro SYS_pwritev 296 end
macro SYS_rt_tgsigqueueinfo 297 end
macro SYS_perf_event_open 298 end
macro SYS_recvmmsg 299 end
macro SYS_fanotify_init 300 end
macro SYS_fanotify_mark 301 end
macro SYS_prlimit64 302 end
macro SYS_name_to_handle_at 303 end
macro SYS_open_by_handle_at 304 end
macro SYS_clock_adjtime 305 end
macro SYS_syncfs 306 end
macro SYS_sendmmsg 307 end
macro SYS_setns 308 end
macro SYS_getcpu 309 end
macro SYS_process_vm_readv 310 end
macro SYS_process_vm_writev 311 end
macro SYS_kcmp 312 end
macro SYS_finit_module 313 end

15
include/util.mcl Normal file
View File

@ -0,0 +1,15 @@
// Assert implementation
// args: [condition, str_len, str_ptr]
// @arg condition: Bool
// @arg str_len: Int
// @arg str_ptr: Ptr
// @ret NULL/NEVER
macro assert
rot
if else
"Assert failed: \"" eputs eputs
"\". Exiting!\n" eputs
1 exit
end
end

View File

@ -6,7 +6,7 @@ use crate::compile::commands::linux_x86_64_compile_and_link;
use super::commands::linux_x86_64_run; use super::commands::linux_x86_64_run;
pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<i32>{
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.to_string() { let (mut of_o, mut of_a) = if &args.out_file == &crate::DEFAULT_OUT_FILE.to_string() {
let of_o = PathBuf::from("/tmp/mclang_comp.o"); let of_o = PathBuf::from("/tmp/mclang_comp.o");
@ -405,8 +405,9 @@ pub fn compile(tokens: Vec<Operator>, args: Args) -> Result<()>{
writer.flush()?; writer.flush()?;
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 {
linux_x86_64_run(&of_c, vec![], args.quiet)?; let c = linux_x86_64_run(&of_c, vec![], args.quiet)?;
return Ok(c);
} }
Ok(()) Ok(0)
} }

View File

@ -64,7 +64,7 @@ pub struct Operator {
pub text: String, //? only used for OpType::PushStr pub text: String, //? only used for OpType::PushStr
pub addr: i64, //? only used for OpType::PushStr pub addr: i64, //? only used for OpType::PushStr
pub jmp: i32, pub jmp: i32,
pub pos: (String, u32, u32) pub loc: (String, u32, u32)
} }
impl Operator { impl Operator {
@ -75,7 +75,7 @@ impl Operator {
jmp: 0, jmp: 0,
addr: -1, addr: -1,
text, text,
pos: (file, row, col) loc: (file, row, col)
} }
} }

View File

@ -14,7 +14,7 @@ fn stack_pop(stack: &mut Vec<u64>, pos: &(String, u32, u32)) -> Result<u64> {
} }
} }
pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<()>{ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<i32>{
let mut stack: Vec<u64> = Vec::new(); let mut stack: Vec<u64> = Vec::new();
let mut ti = 0; let mut ti = 0;
let mut mem: Vec<u8> = vec![0; crate::compile::MEM_SZ as usize + crate::compile::STRING_SZ as usize]; let mut mem: Vec<u8> = vec![0; crate::compile::MEM_SZ as usize + crate::compile::STRING_SZ as usize];
@ -25,7 +25,7 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<()>{
// } // }
while ti < tokens.len() { while ti < tokens.len() {
let token = &tokens[ti]; let token = &tokens[ti];
let pos = token.pos.clone(); let pos = token.loc.clone();
// println!("{:?}", token.typ); // println!("{:?}", token.typ);
match token.typ { match token.typ {
@ -272,5 +272,5 @@ pub fn run(tokens: Vec<crate::constants::Operator>) -> Result<()>{
} }
Ok(()) Ok(0)
} }

View File

@ -44,6 +44,8 @@ fn lex_line(text: String) -> Result<Vec<(u32, String, TokenType)>> {
let t = t.replace("\\n", "\n") let t = t.replace("\\n", "\n")
.replace("\\t", "\t") .replace("\\t", "\t")
.replace("\\r", "\r") .replace("\\r", "\r")
.replace("\\\'", "\'")
.replace("\\\"", "\"")
.replace("\\0", "\0"); .replace("\\0", "\0");
if !t.is_empty() { if !t.is_empty() {
tokens.push((col, t.to_string(), TokenType::String)); tokens.push((col, t.to_string(), TokenType::String));
@ -100,5 +102,6 @@ pub fn lex(code: String, file: &String, args: Args, preprocessing: bool) -> Resu
if preprocessing { if preprocessing {
tokens = preprocess(tokens, args)?; tokens = preprocess(tokens, args)?;
} }
Ok(tokens) Ok(tokens)
} }

View File

@ -72,10 +72,7 @@ fn main() -> Result<()> {
} }
}; };
// for token in &tokens {
// println!("(f: {}, l: {}, c: {}, t: {})", token.file, token.line, token.col, token.text);
// }
let mut parser = parser::Parser::new(tokens); let mut parser = parser::Parser::new(tokens);
let tokens = match parser.parse() { let tokens = match parser.parse() {
Ok(t) => t, Ok(t) => t,
@ -84,26 +81,29 @@ fn main() -> Result<()> {
return Ok(()); return Ok(());
} }
}; };
if args.compile && args.interpret {
let c = if args.compile && args.interpret {
error!("Cannot compile and interpret at the same time"); error!("Cannot compile and interpret at the same time");
0
} else if args.interpret { } else if args.interpret {
match interpret::linux_x86_64::run(tokens) { match interpret::linux_x86_64::run(tokens) {
Ok(_) => (), Ok(c) => c,
Err(_) => { Err(_) => {
error!("Interpretation failed, exiting!"); error!("Interpretation failed, exiting!");
return Ok(()); 1
} }
}; }
} else if args.compile { } else if args.compile {
match compile::linux_x86_64::compile(tokens, args) { match compile::linux_x86_64::compile(tokens, args) {
Ok(_) => (), Ok(c) => c,
Err(_) => { Err(_) => {
error!("Compilation failed, exiting!"); error!("Compilation failed, exiting!");
return Ok(()); 1
} }
}; }
} else { } else {
error!("Did not choose to compile or to interpret, exiting"); error!("Did not choose to compile or to interpret, exiting");
} 0
Ok(()) };
std::process::exit(c);
} }

View File

@ -15,7 +15,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
OpType::Else => { OpType::Else => {
let if_ip = stack.pop().unwrap(); let if_ip = stack.pop().unwrap();
if program[if_ip as usize].typ != OpType::If { if program[if_ip as usize].typ != OpType::If {
lerror!(&op.clone().pos,"'end' can only close 'if' blocks"); lerror!(&op.clone().loc,"'end' can only close 'if' blocks");
return Err(eyre!("Bad block")); return Err(eyre!("Bad block"));
} }
@ -37,7 +37,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
program[ip].jmp = program[block_ip as usize].jmp; program[ip].jmp = program[block_ip as usize].jmp;
program[block_ip as usize].jmp = (ip + 1) as i32; program[block_ip as usize].jmp = (ip + 1) as i32;
} else { } else {
lerror!(&op.clone().pos,"'end' can only close 'if' blocks"); lerror!(&op.clone().loc,"'end' can only close 'if' blocks");
return Err(eyre!("")); return Err(eyre!(""));
} }
@ -55,7 +55,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
} }
if stack.len() > 0 { if stack.len() > 0 {
lerror!(&program[stack.pop().expect("Empy stack") as usize].clone().pos,"Unclosed block"); lerror!(&program[stack.pop().expect("Empy stack") as usize].clone().loc,"Unclosed block");
return Err(eyre!("Unclosed block")); return Err(eyre!("Unclosed block"));
} }
@ -83,7 +83,7 @@ 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 = lookup_word(token.text.clone(), &pos)?; let word_type = lookup_word(token.text.clone(), &pos);
tokens.push(Operator::new(word_type, 0, token.text.clone(), token.file.clone(), token.line, token.col)); tokens.push(Operator::new(word_type, 0, token.text.clone(), token.file.clone(), token.line, token.col));
}, },
TokenType::Int => {// negative numbers not yet implemented TokenType::Int => {// negative numbers not yet implemented
@ -103,7 +103,7 @@ impl Parser {
} }
pub fn lookup_word<P: Deref<Target = (String, u32, u32)>>(s: String, _pos: P) -> Result<OpType>{ pub fn lookup_word<P: Deref<Target = (String, u32, u32)>>(s: String, _pos: P) -> OpType {
let lookup_table: HashMap<&str, OpType> = HashMap::from([ let lookup_table: HashMap<&str, OpType> = HashMap::from([
//stack //stack
("print", OpType::Print), ("print", OpType::Print),
@ -151,9 +151,9 @@ pub fn lookup_word<P: Deref<Target = (String, u32, u32)>>(s: String, _pos: P) ->
]); ]);
match lookup_table.get(s.as_str()) { match lookup_table.get(s.as_str()) {
Some(v) => Ok(v.clone()), Some(v) => v.clone(),
None => { None => {
Ok(OpType::None) OpType::None
} }
} }
} }

View File

@ -6,7 +6,7 @@ use eyre::eyre;
use crate::constants::{Token, Loc, OpType, TokenType}; use crate::constants::{Token, Loc, OpType, TokenType};
use crate::lexer::lex; use crate::lexer::lex;
use crate::{lerror, lnote, Args}; use crate::{lerror, lnote, Args, warn};
use crate::parser::lookup_word; use crate::parser::lookup_word;
#[derive(Debug)] #[derive(Debug)]
@ -24,7 +24,7 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
while rtokens.len() > 0 { while rtokens.len() > 0 {
let token = rtokens.pop().unwrap(); let token = rtokens.pop().unwrap();
let op_type = lookup_word(token.text.clone(), &token.loc())?; let op_type = lookup_word(token.text.clone(), &token.loc());
match token.clone() { match token.clone() {
_ if op_type == OpType::Macro => { _ if op_type == OpType::Macro => {
if rtokens.len() == 0 { if rtokens.len() == 0 {
@ -37,17 +37,19 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
lerror!(&macro_name.loc(), "Bad macro name, expected {} but found {}", TokenType::Word.human(), macro_name.typ.human()); lerror!(&macro_name.loc(), "Bad macro name, expected {} but found {}", TokenType::Word.human(), macro_name.typ.human());
return Err(eyre!("")); return Err(eyre!(""));
} }
let word = lookup_word(macro_name.text.clone(), &macro_name.loc())?; let word = lookup_word(macro_name.text.clone(), &macro_name.loc());
if word != OpType::None { if word != OpType::None {
lerror!(&macro_name.loc(), "Macro name cannot be a built in word, got '{}'", word.human()); lerror!(&macro_name.loc(), "Macro name cannot be a built in word, got '{}'", word.human());
return Err(eyre!("")); return Err(eyre!(""));
} }
if crate::constants::ALLOW_MACRO_REDEFINITION { if macros.get(&macro_name.text.clone()).is_some() {
if macros.get(&macro_name.text.clone()).is_some() { if crate::constants::ALLOW_MACRO_REDEFINITION {
lerror!(&macro_name.loc(), "Macro redefinition is not allowed"); lerror!(&macro_name.loc(), "Macro redefinition is not allowed");
lnote!(&macros.get(&macro_name.text.clone()).unwrap().loc, "First definition here"); lnote!(&macros.get(&macro_name.text.clone()).unwrap().loc, "First definition here");
return Err(eyre!("")); return Err(eyre!(""));
} else {
//TODO: somehow warn about redefinition of only built in macros
} }
} }
@ -56,7 +58,7 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
let mut depth = 0; let mut depth = 0;
while rtokens.len() > 0 { while rtokens.len() > 0 {
let t = rtokens.pop().unwrap(); let t = rtokens.pop().unwrap();
let typ = lookup_word(t.text.clone(), &t.loc())?; let typ = lookup_word(t.text.clone(), &t.loc());
if typ == OpType::End && depth == 0 { if typ == OpType::End && depth == 0 {
break; break;
} else if typ == OpType::End && depth != 0 { } else if typ == OpType::End && depth != 0 {
@ -123,12 +125,31 @@ pub fn preprocess(tokens: Vec<Token>, args: Args) -> Result<Vec<Token>>{
} }
} }
program = expand_macros(program, macros)?; //* Feel free to fix this horrifying shit
//* i wanna kms
let mut times = 0;
while program.iter().map(|f| {
if f.typ == TokenType::Word {
lookup_word(f.text.clone(), &f.loc())
} else {
OpType::PushInt // i hate myself, this is a randomly picked optype so its happy and works
}
}).collect::<Vec<OpType>>().contains(&OpType::None){
if times >= 50 {
warn!("File import depth maxed out, if the program crashes try reducing the import depth, good luck youll need it");
break
}
program = expand_macros(program, &macros)?;
times += 1;
}
Ok(program) Ok(program)
} }
pub fn expand_macros(tokens: Vec<Token>, macros: HashMap<String, Macro>) -> Result<Vec<Token>> { pub fn expand_macros(tokens: Vec<Token>, macros: &HashMap<String, Macro>) -> Result<Vec<Token>> {
let mut program: Vec<Token> = Vec::new(); let mut program: Vec<Token> = Vec::new();
let mut rtokens = tokens.clone(); let mut rtokens = tokens.clone();
@ -136,7 +157,7 @@ pub fn expand_macros(tokens: Vec<Token>, macros: HashMap<String, Macro>) -> Resu
while rtokens.len() > 0 { while rtokens.len() > 0 {
let op = rtokens.pop().unwrap(); let op = rtokens.pop().unwrap();
let op_type = lookup_word(op.text.clone(), &op.loc())?; let op_type = lookup_word(op.text.clone(), &op.loc());
if op.typ == TokenType::Word { if op.typ == TokenType::Word {
match op_type { match op_type {
OpType::None => { OpType::None => {

View File

@ -1,3 +1,6 @@
include "io.mcl" include "io.mcl"
include "util.mcl"
"HEnlo world!\n" write "HEnlo world!\n" puts
2 2 = "i suck at math" assert