GNXMAQY6IMH7NW7XUGLJ2T4S7JYAMDSAEB66FYPRJNZSRRZ3H5JAC ** ~save-lisp-and-die~This function takes two parameters: (1) the filename of a glotawkinterpreter; (2) a filename to which to write a new interpreter. TheAWK code from glotawk is written into the new file, and then a dump ofthe current heap. In this way, you can construct a single-fileinterpreter containing not only glotawk's base library, but alsodefinitions of your own, which will be instantly available when yourun the new interpreter, without the overhead of parsing and withoutthe need to place copies of the files containing the definitions onmachines where the code needs to run.So, previous to this change, you could put a built copy of ~glotawk~on the machine where you need to run the code, plus copies of thefiles where you define all your functions, ~a.glotawk~, ~b.glotawk~,and ~c.glotawk~, and the file where you call them, ~end-use.glotawk~.Then you'd run =glotawk a.glotawk b.glotawk c.glotawkend-use.glotawk=. All the expressions in each file would be parsed andevaluated. Most of the code by volume would be definitions. Not alldefined functions would be called. Startup time would be slower.
As of this change, instead, you could run ~/wherever/glotawk~, tell itto =(load "a.glotawk")= and etc., and =(save-lisp-and-die"/wherever/glotawk" "/wherever-else/my-new-interpreter")=. Then~my-new-interpreter~ will contain the definitions inside it.Maybe I was a little too excited when naming this function, because itdoesn't yet support changing which code runs at startup.** Parsing across linesThe reader is retooled to support forms spanning multiple lines, whichlets the user write Lisp source in the commonly expected fashion.
them using ~string-join~, and then runs ~unsafe-system~ with that.
them using ~string-join~, and then runs ~unsafe-system~ with that. Butthen you can't do redirections using ~system~, so as a workaround,when there are any symbols among the arguments, their names areinserted into the shell command without quoting. So you cansrc_glotawk{ (system "echo" "hi" '> "/dev/null") } for example.** Bugs fixed*** Backslash escapes in stringsInside strings, the usual backslash escapes act how you would expectthem to. That's ~\a \b \f \n \r \t \v \\ \"~ for the bell, backspace,formfeed, newline, carriage return, horizontal tab, vertical tab,backslash and double quotes, respectively. This means when thecharacters ~\a~ are found in your string literal, they mean a singlecharacter inside the resultant string: ASCII code 7; when that stringis printed using ~print~, which prints the readable representation ofa thing, it will come back out as the characters ~\a~; when thatstring is printed using ~printf~, the ASCII code 7 will be sent to theoutput.*** ~strcat~, ~printf~, ~sprintf~ infinite loops
** ~quasiquote~ works
Evaluation environments were not being passed into these specialforms, causing infinite loops. This is fixed.*** Strings now ~equal~ by contentsDue to a bug, ~equal~ was comparing strings using their identities(e.g. is string a /stored at the same place as/ string b?), not theircontents (e.g. would awk consider them ~==~ ?). This is fixed.*** ~quasiquote~ works
*** Some infinite loops squashedAs well as bugfixes mentioned above to prevent infinite loops, inseveral places where infinite loops can possibly happen, they arechecked for, and we print an error and exit instead.*** match functionThe ~match~ special form had a wrong variable name that kept it fromever working right; this is fixed. In cases where there was no match,previously this special form would return ~(0 -1)~, hewing closely toAWK. It has been modified to return ~nil~ if there is no match, so youcan more easily use its results in conditional checks.** Other changes*** Library moved to lib.glotawk~lib-eval.awk~ contained the upper-level parts of glotawk, written inglotawk. With the ability to parse across lines, and the addition ofthe ~load~ function, the library is now moved to ~lib.glotawk~ andis loaded in by ~lib-eval.awk~.*** Busybox awk compatibility attempted; failedBusybox's awk was barfing on the regular expressions used in thetokenizer. That's fixed, but you can't take the length() of an arrayin Busybox awk. POSIX does not specify this behavior, so Busybox isnot in the wrong here; but glotawk takes the length of many arrays.Perhaps the next version of POSIX will require awk to support the useof length() on arrays.*** GC_DEBUG
If you run glotawk like ~awk -v GC_DEBUG=1 -f glotawk~, then uponevery garbage collection, the heap before and after are written toGraphviz ~dot~ files, as well as the GC marks. You may wish to avoidusing the ~dot~ algorithm to visualize these: with thousands of nodes,~dot~ thinks for a long time, and makes an inscrutable drawing. ~fdp~and ~sfdp~ can render an inscrutable drawing much faster.*** awk flexibilityThree awks are specified in the Makefile now: the one used to buildglotawk (~BUILD_AWK~), the one used to run the tests (~TEST_AWK~), andthe one expected to exist when glotawk is run (~TARGET_AWK_F~). Theseall default to the value of ~AWK~, which in turn defaults to~/usr/bin/awk~.