ref: d5ff76398f8fb87284ea7b26121bf1262aaaae25
dir: /interp.myr/
use std use "types.use" pkg regex = const exec : (re : regex#, str : byte[:] -> bool) ;; const exec = {re, str var i re.str = str re.strp = 0 re.matched = `std.None mkthread(re, 0) while re.nthr > 0 for i = 0; i < re.nthr; i++ std.put("tid=%z, ip=%z, c=b\n", re.thr[i].uid, re.thr[i].ip, str[re.strp]) step(re, i) ;; if re.nthr > 0 re.strp++ ;; ;; match re.matched `std.Some thr: -> true;; `std.None: -> false;; ;; } const step = {re, tid var thr var str thr = re.thr[tid] str = re.str match re.prog[thr.ip] /* Char matching. Consume exactly one byte from the string. */ `Ibyte b: std.put("\t%i:\tByte %b\n", thr.ip, b) if !in(re, str) kill(re, tid, "end of string") elif b != str[re.strp] kill(re, tid, "not right char") else thr.ip++ std.put("\t\tmatched %b with %b\n", b, str[re.strp]) ;; ;; `Irange (start, end): std.put("\t%i:\tRange (%b, %b)\t", thr.ip, start, end) if !in(re, str) || start > str[re.strp] || end < str[re.strp] kill(re, tid, "bad range") else thr.ip++ ;; ;; `Idot: std.put("\t%i:\tDot\n", thr.ip) if in(re, str) kill(re, tid, "past end") else thr.ip++ ;; ;; /* Control flow. All of these recursively call step() until exactly one byte is consumed from the string. */ `Ifork (lip, rip): std.put("\t%i:\tFork (%z, %z)\n", thr.ip, rip, lip) jmp(re, tid, rip) spawn(re, lip) ;; `Ijmp ip: std.put("\t%i:\tJmp %z\n", thr.ip, ip) jmp(re, tid, ip) ;; `Imatch: std.put("\t%i:\tMatch\n", thr.ip) finish(re, tid) ;; ;; } const jmp = {re, tid, ip re.thr[tid].ip = ip step(re, tid) } const steptrace = { std.put("\t\tStepping\n") } var uid = 0 const mkthread = {re, ip var thr : rethread# var tid tid = re.nthr if re.nthr >= re.thr.len re.thr = std.slgrow(re.thr, std.max(1, re.nthr * 2)) ;; thr = std.alloc() thr.ip = ip thr.uid = uid++ re.thr[re.nthr] = thr re.nthr++ -> tid } const spawn = {re, ip step(re, mkthread(re, ip)) } const kill = {re, tid, msg /* free the dying thread, and shuffle the last thread into the it's place in the thread list */ std.put("\t\tkill %z: %s\n", re.thr[tid].uid, msg) std.free(re.thr[tid]) re.thr[tid] = re.thr[re.nthr - 1] re.nthr-- } const finish = {re, tid std.put("finish\n", tid) match re.matched `std.Some thr: std.free(thr);; `std.None: ;; ;; re.matched = `std.Some re.thr[tid] re.thr[tid] = re.thr[re.nthr - 1] re.nthr-- } const in = {re, str -> re.strp < str.len }