# SPDX-License-Identifier: BSD-2-Clause BEGIN { _IMAGE_BEGIN = "# IMAGE BEGINS QMGFAMRISGQJ48IWDOWPHOOGW3MLKKGSPXD4DTFIG0" } function awkescape(string) { gsub(/\\/, "\\\\", string) gsub(/"/, "\\\"", string) gsub(/\n/, "\\n", string) return string } function awkrepr(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 { v = awkescape(v) return "\"" v "\"" } } function _dump(filename, append, main, i, t, v, s, line) { # This is what code to execute when this image is started. It has # to be a glotawk form with no parameters. Usually it is the repl # special form, so that when we start we'll do the REPL. But maybe # you want some other function to happen at startup. if(!main) main = "repl" logg_dbg("_dump", "dumping " (append ? ">> " : "> ") filename ". main symbol is " main) if(append) print _IMAGE_BEGIN >>filename else print _IMAGE_BEGIN >filename print "BEGIN {" >>filename print " N = " N " # next cell number" >>filename print " N_at_last_gc = " N_at_last_gc >> 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 because _TYPE[# 123] is not valid awk syntax. if((i+0)!=i) continue t = _TYPE[i] line = " _TYPE[" i "] = \"" t "\"; " if(t == "'") { v = _SYM_NUMBERS[i] v = awkescape(v) line = line \ "_SYM_NUMBERS[" i "] = \"" v "\"; " \ "_SYM_NAMES[\"" v "\"] = " i "; " } else if(t == "s") { v = _STRING[i] v = awkescape(v) line = line "_STRING[" i "] = \"" v "\"; " } else if(t == "(") { line = line \ "_CAR[" i "] = " awkrepr(_CAR[i]) "; " \ "_CDR[" i "] = " awkrepr(_CDR[i]) "; " } print line >>filename } print " _GLOBALS = " _GLOBALS " # global environment " >>filename print " _MACROS = " _MACROS >>filename print " _COMPARED_SYMBOLS = " _COMPARED_SYMBOLS >>filename # we are storing here the name of the _MAIN symbol as an awk # string, which we may have received in the main parameter. that's # why it's a little awkward print " _MAIN = \"" awkescape(main) "\"" >>filename print " main_expression = _cons(_symbol(_MAIN), _nil())" >>filename print " _eval(main_expression)" >>filename print "}" >>filename close(filename) return _true() } function _dump_overwrite(filename) { return _dump(filename) } function _dump_append(filename) { logg_dbg("_dump_append", "filename is " filename) return _dump(filename, 1) } function _dump_append_changing_main(g_filename, g_main, filename, main) { if(_TYPE[g_filename] == "s") { if(_TYPE[g_main] == "'") { filename = _STRING[g_filename] main = _SYM_NUMBERS[g_main] logg_dbg("_dump_append_changing_main", "filename is " filename " and the form to evaluate at startup will be " main) return _dump(filename, 1, main) } else { logg_err("_dump_append_changing_main", "the value of the second parameter, main, must be a symbol") return _nil() } } else { logg_err("_dump_append_changing_main", "the value of the first parameter, filename, must be a string") return _nil() } } 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] " [constraint=false];" } 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 [color=blue];" } print node >>filename print edge >>filename print edge2 >>filename } else if(t == "'") { print " n" i " [shape=Mrecord,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) logg_dbg("_dump_dot", "done") return _true() }