ref: 8c0eb9f56edefcc15a206f8e165056803f9f5b99
author: Ori Bernstein <[email protected]>
date: Mon Oct 21 21:10:26 EDT 2013
Initial commit
--- /dev/null
+++ b/Makefile
@@ -1,0 +1,9 @@
+MYRLIB=regex
+MYRSRC= \
+ compile.myr \
+ interp.myr \
+ types.myr \
+
+include config.mk
+include mk/myr.mk
+
--- /dev/null
+++ b/compile.myr
@@ -1,0 +1,22 @@
+use std
+
+use "types.use"
+
+pkg regex =
+ const compile : (re : byte[:] -> regex#)
+;;
+
+const compile = {re
+ var re
+ re = std.zalloc()
+ re.prog = std.slalloc(4)
+ /* compiled regex for a* */
+ re.prog[0] = `Byte ('a' castto(byte))
+ re.prog[1] = `Byte ('a' castto(byte))
+ re.prog[2] = `Split (0, 3)
+ re.prog[3] = `Match
+
+ -> re
+}
+
+
--- /dev/null
+++ b/configure
@@ -1,0 +1,52 @@
+#!/bin/sh
+
+prefix="/usr/local"
+
+for i in `seq 300`; do
+ echo "Lots of output to emulate automake... ok"
+ echo "Testing for things you'll never use... fail"
+ echo "Satisfying the fortran77 lobby... ok"
+ echo "Burning CPU time checking for the bloody obvious... ok"
+done
+echo "Automake emulated successfully"
+
+INST_ROOT='/usr/local'
+
+for arg in $*; do
+ shift 1
+ case $arg in
+ "--prefix" | "-p")
+ prefix=shift $*
+ ;;
+ --prefix=*)
+ prefix=`echo $arg | sed 's/^--prefix=//g'`
+ ;;
+ "--help" | "-h")
+ echo "Usage:"
+ echo " --prefix | -p: The prefix to install to"
+ break;
+ ;;
+ *) echo "Unrecognized argument $arg";;
+ esac
+done
+
+OS=`uname`
+
+echo export INST_ROOT=$prefix > config.mk
+case $OS in
+ *Linux*)
+ echo 'export SYS=linux' >> config.mk
+ ;;
+ *Darwin*)
+ echo 'export SYS=osx' >> config.mk
+ ;;
+ *)
+ echo 'Unknown architecture.'
+ ;;
+esac
+
+cat << EOF
+ Building with:
+ prefix=$prefix
+EOF
+
--- /dev/null
+++ b/interp.myr
@@ -1,0 +1,122 @@
+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
+ spawn(re, 0)
+ while re.nthr > 0
+ for i = 0; i < re.nthr; i++
+ std.put("tid %z, ip %z, strp %z\n", re.thr[i].uid, re.thr[i].ip, 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 */
+ `Byte b:
+ if !in(re, str) || b != str[re.strp]
+ kill(re, tid, "not char")
+ else
+ std.put("matched %b with %b\n", b, str[re.strp])
+ ;;
+ ;;
+ `Range (start, end):
+ if !in(re, str) || start > str[re.strp] || end < str[re.strp]
+ kill(re, tid, "bad range")
+ ;;
+ ;;
+ `Dot:
+ if !in(re, str)
+ kill(re, tid, "past end")
+ ;;
+ ;;
+ /* Control flow */
+ `Split (lip, rip):
+ spawn(re, lip)
+ jmp(re, tid, rip)
+ ;;
+ `Jmp ip:
+ jmp(re, tid, ip)
+ ;;
+ `Match:
+ finish(re, tid)
+ ;;
+ ;;
+ thr.ip++
+}
+
+const jmp = {re, tid, ip
+ std.put("jmp %z\n", ip)
+ re.thr[tid].ip = ip
+ step(re, tid)
+}
+
+var uid = 0
+const spawn = {re, ip
+ var thr : rethread#
+ var tid
+
+ std.put("spawn %z\n", re.nthr)
+ 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++
+
+ step(re, tid)
+}
+
+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("kill %z: %s\n", tid, 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
+}
--- /dev/null
+++ b/mk/myr.mk
@@ -1,0 +1,42 @@
+ifneq ($(MYRLIB),)
+ _LIBNAME=lib$(MYRLIB).a
+endif
+
+all: $(_LIBNAME) $(MYRBIN)
+
+$(_LIBNAME): $(MYRSRC) $(ASMSRC)
+ myrbuild -l $(MYRLIB) $^
+
+$(MYRBIN): $(MYRSRC) $(ASMSRC)
+ myrbuild -b $(MYRBIN) $^
+
+OBJ=$(MYRSRC:.myr=.o) $(ASMSRC:.s=.o)
+JUNKASM=$(MYRSRC:.myr=.s)
+USE=$(MYRSRC:.myr=.use) $(MYRLIB)
+.PHONY: clean
+clean:
+ rm -f $(OBJ)
+ rm -f $(USE)
+ rm -f $(JUNKASM)
+ rm -f lib$(MYRLIB).a
+
+install: install-bin install-lib
+
+install-bin: $(MYRBIN)
+ @if [ ! -z "$(MYRBIN)" ]; then \
+ echo install $(MYRBIN) $(INST_ROOT)/bin; \
+ mkdir -p $(INST_ROOT)/bin; \
+ install $(MYRBIN) $(INST_ROOT)/bin; \
+ fi
+
+install-lib: $(_LIBNAME)
+ @if [ ! -z "$(_LIBNAME)" ]; then \
+ echo install -m 644 $(_LIBNAME) $(INST_ROOT)/lib/myr; \
+ echo install -m 644 $(MYRLIB) $(INST_ROOT)/lib/myr; \
+ mkdir -p $(INST_ROOT)/lib/myr; \
+ install -m 644 $(_LIBNAME) $(INST_ROOT)/lib/myr; \
+ install -m 644 $(MYRLIB) $(INST_ROOT)/lib/myr; \
+ fi
+
+config.mk:
+ ./configure
--- /dev/null
+++ b/types.myr
@@ -1,0 +1,29 @@
+use std
+
+pkg regex =
+ type regex = struct
+ prog : reinst[:]
+ nthr : std.size
+ thr : rethread#[:]
+ str : byte[:]
+ strp : std.size
+ matched : std.option(rethread#)
+ ;;
+
+ type rethread = struct
+ uid : std.size
+ ip : std.size
+ ;;
+
+ type reinst = union
+ /* direct consumers */
+ `Byte byte
+ `Range [byte, byte]
+ `Dot
+
+ `Match /* found the end of the expr */
+
+ `Split [std.size, std.size]
+ `Jmp std.size
+ ;;
+;;