5XO7IKBGCVXGVWMDJDE5MELS4FWRITKAU6NNV36NQ4TOZRR7UQ7QC
7BYMVBE225GXMGCZIPBE7XAGZ3FMO2NF75PSTBYQT3ZQ3ZK6YKOAC
JDZASPALXSFZOL3MXCKBPX74CUD3W743ZJ6W2422FIJ7NJOD67ZAC
A2JAXDJWT2FAKADYOY6QOQ7LQRMTTCDIOYT7STSESVHLZQEQJBMAC
O6PFGAUDYCMK6SC6V5RB5ELXZ7W54OB7XPYCMECCA4BSBUVLFAPAC
UW27LKXM2BJ77FQLTY4WPKDSSWI2RFNFRJ7CB4U3TS7KYVIV72LQC
NBEO3TPNOUG7MRFYRSDDFB5TQKTEDL6GHHFQVOB5MXVPIBKFNZKAC
GW4AAYNF7I66D72G5PMFTQRK7B4KZVYKAHKRPC2IY7IX37JKEHJQC
6XHALMLUA5B5BBYFSWIFHSJ2BXCL6RSAW5TCKRGJEI2LURH2TQ4AC
MPN7OJSZD5CS5N7WWS3ZSOYE7ZRCABIBHZDMHVS6IT25EO2INK7AC
function _gc_mark_list(lis, car, tv, t, v, i) {
logg_dbg("_gc_mark_list", "cons number " lis)
i = 0
function _gc_mark_cell(n, dot_filename, d) {
logg_dbg("_gc_mark_cell", n, d)
_MARK[n] = 1
if(dot_filename)
print " n" n " [fillcolor=green];" >>dot_filename
return 1
}
function _gc_mark_list(lis, dot_filename, d, i) {
car = _car(lis)
lis = _cdr(lis)
if(_falsy(car)) continue
t = _TYPE[car]
_MARK[car] = 1
if(t == "(") {
i += _gc_mark_list(car)
i += _gc_mark_cell(lis, dot_filename, d)
if(!_is_literal(_car(lis))) {
if(_TYPE[_car(lis)] == "(") {
i += _gc_mark_list(_car(lis), dot_filename, d+1)
} else {
i += _gc_mark_cell(_car(lis), dot_filename, d)
}
i += 1
}
if(_is_literal(_cdr(lis))) {
if(_is_null(_cdr(lis))) {
lis = _nil()
} else {
# pair
logg_dbg("_gc_mark_list", "cdr is a literal. pair?", d)
i += _gc_mark_cell(_cdr(lis), dot_filename, d)
lis = _nil()
}
} else {
if(_TYPE[_cdr(lis)] == "(") {
# move along lis
lis = _cdr(lis)
} else {
# a pair with a non-literal
logg_dbg("_gc_mark_list",
"cdr " _cdr(lis) " is not a cons. pair?", d)
i += _gc_mark_cell(_cdr(lis), dot_filename, d)
}
}
}
function _gc(envs, i, t, name, ngcd, nmarks) {
# y'know... the envs given had better add up to everything, not
# just globals and not just one stack of envs. hmm
delete _MARK
ngcd = 0
logg_dbg("_gc", "marking")
nmarks = _gc_mark_list(envs)
logg_dbg("_gc", "sweeping")
function _gc_sweep(dot_filename, ngcd) {
}
}
}
function _gc_dot(envs, mark_filename, sweep_filename, i, t, name, ngcd, nmarks) {
# y'know... the envs given had better add up to everything, not
# just globals and not just one stack of envs. hmm
delete _MARK
ngcd = 0
logg_dbg("_gc", "marking")
if(mark_filename) print "" >mark_filename
if(sweep_filename) print "" >sweep_filename
nmarks = _gc_mark_list(envs, mark_filename, 0)
logg_dbg("_gc", "sweeping")
ngcd = _gc_sweep(sweep_filename)
# _dump("post-gc")
function _gc(envs) {
return _gc_dot(envs)
}
# make list of these percent symbols because _eval3 compares the
# address of the operator being eval'd against them, in order to
# reduce the number of if-elseif-elseif-elseif... cases if the
# operator isn't one of the most common ones.
_COMPARED_SYMBOLS = _cons(_symbol("%other-lispy%"),
_cons(_symbol("%math%"),
_cons(_symbol("%last-special-form%"),
_nil())))
# i is not a number but a string. somewhere in the code we
# ask if _TYPE[something] == bla, where something may be
# true, or false, or nil, or a literal number ("# 123");
# and by asking about _TYPE[something], we make
# _TYPE[something] exist, and be "". we don't want to dump
# those here because _TYPE[# 123] is not valid awk syntax.
if((i+0)!=i) continue
}
function dotescape(string) {
gsub(/\\/, "\\\\", string)
gsub(/"/, "\\\"", string)
return string
}
function dotrepr(v) {
if(v == _nil())
return _nil()
else if(v == _true())
return _true()
else if(v == _false())
return _false()
else if(v+0 == v)
return v
else {
dotescape(v)
return v
}
function _dump_dot(filename, i, t, v, s, n, node, edge, edge2) {
logg_dbg("_dump_dot", "dumping Graphviz to " filename)
print "digraph g {" >filename
print " rankdir=LR" >>filename
print " overlap=false" >>filename
print " node [style=filled]" >>filename
for(i in _TYPE) {
# i is not a number but a string. somewhere in the code we
# ask if _TYPE[something] == bla, where something may be
# true, or false, or nil, or a literal number ("# 123");
# and by asking about _TYPE[something], we make
# _TYPE[something] exist, and be "". we don't want to dump
# those here.
if((i+0)!=i) continue
t = _TYPE[i]
print "/* " i " is a " _TYPE[i] " : " _repr(i) " */" >>filename
if(t == "(") {
print "/* -- " _CAR[i] " is a " _TYPE[_CAR[i]] " : " _repr(_CAR[i]) " */" >>filename
t = _TYPE[_CAR[i]]
node = " n" i " [shape=record,label=\"{<n> " i "|"
edge = ""
edge2 = ""
if(t == "(") {
node = node "<car> ·|"
edge = " n" i ":car -> n" _CAR[i] ":n;"
} else if(t == "'") {
v = _SYM_NUMBERS[_CAR[i]]
dotescape(v)
node = node v "|"
#edge =" n" i ":car -> n" _CAR[i] ";"
} else if(t == "s") {
v = _STRING[_CAR[i]]
dotescape(v)
node = node "\\\"" v "\\\"|"
} else {
node = node dotrepr(_CAR[i]) "|"
}
if(_is_null(_CDR[i])) {
node = node "<cdr> X}\"];"
} else {
node = node "<cdr> ·}\"];"
edge2 = " n" i ":cdr -> n" _CDR[i] ":n;"
}
print node >>filename
print edge >>filename
print edge2 >>filename
} else if(t == "'") {
#print " n" i " [shape=record,label=\"{<n> " i "|" _SYM_NUMBERS[i] "}\"];" >>filename
} else if(t == "s") {
print " n" i " [shape=record,label=\"{<n> " i "|" _STRING[i] "}\"];" >>filename
}
}
print " nGlobals [label=\"_GLOBALS\"];" >>filename
print " nGlobals -> n" _GLOBALS ";" >>filename
print " nMacros [label=\"_MACROS\"];" >>filename
print " nMacros -> n" _MACROS ";" >>filename
print " nCompared [label=\"_COMPARED_SYMBOLS\"];" >>filename
print " nCompared -> n" _COMPARED_SYMBOLS ";" >>filename
print "/*sweep colors*/" >>filename
print "/*mark colors*/" >>filename
print "}" >>filename
close(filename)
return _true()
}
help = "\n\
Targets:\n\
glotawk: build the interpreter, a single large\n\
executable AWK script\n\
check: run tests\n\
benchmark: run a few benchmarks\n\
all (default): glotawk, check, and benchmark\n\
clean: get rid of build products\n\
heapviz: fancy Graphviz view of initial heap and GC\n\
"
help:
@echo ${help} >&2
.PHONY: all depend check test clean benchmark
heap-nomarks.dot: glotawk
echo "(dump-dot \"$@\")" | ./glotawk
gc-marks.dot gc-sweeps.dot: glotawk
echo "(gc-dot \"gc-marks.dot\" \"gc-sweeps.dot\")" | ./glotawk -v LOG_LEVEL=3
heap.dot: glotawk heap-nomarks.dot gc-marks.dot gc-sweeps.dot
cat heap-nomarks.dot | \
sed -e '/^\/\*mark colors\*\/$$/r gc-marks.dot' | \
sed -e '/^\/\*sweep colors\*\/$$/r gc-sweeps.dot' > $@
heapviz: heap.dot
dot -Tx11 heap.dot
.PHONY: all depend check test clean benchmark heapviz