Add false and lolcode for yacc-shaving hackathon. - brcon2024-hackathons - Bitreichcon 2024 Hackathons HTML git clone git://bitreich.org/brcon2024-hackathons git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/brcon2024-hackathons DIR Log DIR Files DIR Refs DIR Tags --- DIR commit a89e2604a1ca9afeece48f116aa4f9e41f53e6e6 DIR parent 94433adc0fdc6b209806ebff306230fd6a670210 HTML Author: Christoph Lohmann <20h@r-36.net> Date: Sat, 20 Jul 2024 07:31:57 +0200 Add false and lolcode for yacc-shaving hackathon. Diffstat: A yacc-shaving/false/false.txt | 672 +++++++++++++++++++++++++++++++ A yacc-shaving/lolcode/lolcode-spec | 1 + 2 files changed, 673 insertions(+), 0 deletions(-) --- DIR diff --git a/yacc-shaving/false/false.txt b/yacc-shaving/false/false.txt @@ -0,0 +1,672 @@ + + The FALSE Programming Language + + by Wouter van Oortmerssen + + Manual + + +WHAT'S NEW in v1.3 +- lots of new and exciting example source code by lots of people! + (have a look in `contrib/' for some amazing code) +- documentation in french too +- minor fixes and enhancements to the portable interpreter + (read comments in the source) +- new infos, ftp/www sites etc., read the last chapter + +WHAT'S NEW in v1.1 +- one bug fix in the 68k version +- other example sources (mainly written by Eelko, in the "other" dir.) +- Portable False Interpreter/Debugger! + (read comments in the source) + + ++-------------------------------+ +| Introduction: | ++-------------------------------+ + +The language FALSE and it's compiler were designed for only two reasons: +- building a working compiler in just 1k (!) +- designing a language that looks cryptic and fuzzy (in the APL tradition) + +the result is a language that is quite powerfull (for it's size). +It's a Forth type language with lambda abstraction and lots of other goodies. +I named the language after my favourite truthvalue. + +NOTE: a) the compiler as well as the generated code need kickstart v37+ + b) You're strongly advised to read this entire manual before + trying to operate the compiler. + ++-------------------------------+ +| The implementation: | ++-------------------------------+ + +To compile a FALSE program, type "false" followed by the source-code +name, like: + +1> false helloworld.f + +the compiler produces an executable called "a.out" in the same dir: + +1> a.out +Hello, World! +1> + +To squeeze the real compilation functions for all language elements in +1024 bytes, some things had to go: there are no error messages, and even +worse: there are no syntax error checks. Luckily, the language is +designed so that it's hard to make compile-time errors. + +the compiler only signals an error in the following events: +- it could not allocate memory +- it could not read the source file +- it could not write the executable +- it could not open dos.library (very unlikely) +- it found a symbol in the source, which isn't part of the language. + +an error is signalled by returning value 10 instead of 0, it is +therefore wise to have your cli-prompt display return values ("%R") + +note: the compiler will start acting weird as soon as you try +to compile sources or produce executables >32k + +Working with FALSE +------------------ +It is actually possible to write small utilities and stuff in FALSE, +and quite powerfull too once you see how to use stacks and lambda +functions etc. However, with a minimal compiler like this it's hard to +find errors, and I suppose you really have to be a Forth hacker or a +hardcore programmer to get the most of it. + +Helloworld in FALSE: +-------------------- + +"Hello, World! +" + +(yes, that's all...). +And this is the fac() function definition in FALSE: + +[$1=$[\%1\]?~[$1-f;!*]?]f: + +(fuzzy eh? we'll explain that later...) + + ++-------------------------------+ +| FALSE: The Language. | ++-------------------------------+ + +Format of the language: +----------------------- +FALSE sources are totally free-format, i.e you may have any number +of tabs/spaces/lf's between two symbols. comments start with "{", +end with "}" and may not be nested. + + +evaluation: +----------- +FALSE inherits its way of evaluating expressions from Forth, so it +really helps if you know that language, but for those who don't: + +All elements in the language are defined by what they push on and/or +pop from the stack. for example, a number like "1" or "100" simply +pushes it's own value on the stack. An operator like "+" takes the +two top elements of the stack, adds them, and pushes back the result: + +1 2 + 4 * { (1+2)*4 } + +the result of this expression is "12". We will use the notation +(<pops>-<pushes>) to signify what a function does, so "1" does (-num) +and "+" does (n1,n2-result) + +complex expressions will keep lots of intermediate results on the stack, +so mostly there's no need for local variables. FALSE doesn't even +have expressions or statements; more likely a program is one stream +of symbols that manipulate the stack. It's very helpfull when you +can imagine what the stack looks like in a particular part of the program +when programming. + + +elementary functions: +--------------------- + +available are: + +"+" "-" "*" "/" "_" + +these function as usual. "_" is the unary minus. + + +"=" ">" + +these result in 0 (false) or -1 (true) + +unequal is "=~", and smaller than etc. can be made by swapping arguments +and/or using "~" + +example: a;1_=~ { a<>-1 } + + +"&" "|" "~" + +"and", "or" and "not", as usual. + +example: a;0>a;99>~& { (a>0) and (a<100) } + + +values: +------- + +values are either integers like discussed before ("1", "100" etc.), +or characters precede by a quote: 'A (equals 65) (do not mix up with +backquote "`" !) +note that the 1k parser only parses integers up to 320000, it uses +full 32bit representation for them, however. + + +global variables: +----------------- +variables to store values are less needed in FALSE than in other +languages. in FALSE they are used mostly for functions, explained +below. + +a variable is a character "a" to "z" (just these). +":" is the assignment function, and ";" is contrary: it gets the +variable's value: + +1a: { a:=1 } +a;1+b: { b:=a+1 } + +i.e: "a;" is used where in other languages you would just write "a" + +all variables (and also stack-items) are 32bits. + +lambda functions: +----------------- +a FALSE lambda function is a piece of code between []. for example: + +[1+] + +is a function that adds 1 to it's argument. A function is really defined +by what it takes from the stack (in this case the first arg to "+"), and +what it puts back, just like builtin functions. Note that FALSE lambda +functions are not restricted to just one return value. + +what a [] expression really does, is push the function. this means in +practise that it can be given to yet another function as argument etc., +just like in functional languages. The symbol "!" is called "apply", +and applies a function to it's arguments, for example: + +2[1+]! + +would result in "3" +This wouldn't make much sense, since what you really want is define the +function once, and then use it all-over. this is easy: + +[1+]i: + +this defines the function "i" (actually, it assigns the function to "i"), +so that it can be used simply by applying "i" to it's arguments: + +2i;! + +WARNING: as with all other elements in FALSE, but even more important + with functions: the 1k compiler does not check if symbols like + "!" really get a function as argument (so "1!" means trouble), + the compiler may even crash if you don't balance your [ and ]. + + +stack functions: +---------------- + +"$" (x-x,x) dup: duplicate topmost stackitem +"%" (x-) drop: delete topmost stack item +"\" (x1,x2-x2,x1) swap: swap to topmost stack-items. +"@" (x,x1,x2-x1,x2,x) rot: rotate 3rd stack item to top. +"ø" (n-x) pick: copy n-th item to top (0ø equals $) + +examples: + +1$ equals 1 1 +1 2% equals 1 +1 2\ equals 2 1 +1 2 3@ equals 2 3 1 +7 8 9 2ø equals 7 8 9 7 + + +control structure: +------------------ +FALSE only has an IF and a WHILE. +if is "?", and looks like this: (bool,fun-). example: + +a;1=["hello!"]? { if a=1 then print "hello!" } + +the first argument is a boolean value, the second the lambda function +to be executed (see below for "") +there's no "else", so you'll have to mimic this with a second "?". +this can be easily done by copying the truthvalue: + +a;1=$["true"]?~["false"]? + +after the first "?" (wether it's executed or not), a copy of the truthvalue +is still on the stack, and we negate it for the else part. +Beware that if the first "if" needs arguments on the stack from before +the boolean expression, it's top is still the truthvalue. + +While is a "#", and gets two lambda functions as args, one that results in +a boolean, and the second as body: + +[a;1=][2f;!]# { while a=1 do f(2) } + +note that with while, if and lambda's, you can build virtually +any other control structure. + + +Input/Output: +------------- + watch out: all these are BUFFERED. + +- strings printing: strings simply print themselves. Special: strings in FALSE + may contain <lf>'s, that explains why in the helloworld program, the second + " is on the next line: + + "Hello, World! + " + +- integers: "." prints the topmost stack item as integer value: + + 123. { prints string "123" on console } + +- characters: "," + + 65, { prints "A" } + +- reading a character from stdin: "^" + + ^ { top stack is char read } + +- flush: "ß" + when stdin and stdout are different (i.e. you started your compiled + FALSE program with <infile >outfile you will hardly need to flush, however, + if you both use "^" and the output operations on the same console, + you may need to flush between input and output. + "ß" flushes both input and output. + + ß[^$1_=~][,]# { while c:=getc()<>EOF do putc(c) } + + for example, above program copies input to output until eof, + so no flushing is needed after every read when used with two + files, however: + + "press return:"ß^%ß"continuing..." + + it is, since we get input on the same console as the output. + + ++-------------------------------+ +| Example programming | ++-------------------------------+ + +How the $#%! am I going to write a decent program with all this, you may ask. +Well, the first barrier one has to take into account, is that FALSE doesn't +support any amiga-specific programming, some io-functions is as far as +it gets. However, with those, you can create some stunningly compact +utilities, for example the FALSE version of the "copy" command we saw above, +in just 13 bytes! + +ß[^$1_=~][,]# + +ok, what happens: first recognise the four main parts in this program, +we have a flush, then two arguments and then a while. The first [] +function is supposed to deliver the boolean for the while: it reads +a character, duplicates it, the compares it it with -1 (EOF). at the end +of this function, we do not only have a boolean, but also an extra copy +of the character we read. This immediately demonstrates a powerfull +feature of FALSE: we can have any number of interim-results on the +stack. the body of the while loop [,] just prints the character to +stdout. +Note that if the body is not executed, we leave with a non-empty stack. +This is no problem at the end of a program, however, doing this within an +iteration would be fatal. + + +another example of FALSE programming: the fac() function. + +[$1=$[\%1\]?~[$1-f;!*]?]f: + +thus we call fac(6) (=720) like: + +6f;! + +no range checking is done by the "f" function, that is what +is done by the fac.f example program. + +Well, how does it work? (does it?) First recognise the f;! within +the function implementation: that's the recursion. Let us recall what +fac() looks like in a hypotheticall procedural/functional programming +language: + +fac(n) = if n=1 then 1 else n*fac(n-1) + +our FALSE code goes just along these lines, only we use two "if"'s (hence +the two [] blocks) insteas of one if-then-else. +we start with (n-) on the stack: + +$1=$ + +duplicate the n, and compare it with 1, and leave a second truthvalue (t), +thus: (n,t,t-) + +[\%1\]? + +first push the [], and after the "if" (=?) we have (n,t-). we won't +be needing the lower n anymore, so we swap and drop. then we push the +final result "1", and swap it below the truthvalue for the second "if". +(1,t-) + +~[$1-f;!*]? + +we first have to negate the truthvalue, because this is the else part. +in the "if"-body, we have just (n-), and we add a "n-1" to that as argument +for the recusive call. after f;! we have (n,r-) (r is result of the call), +and we simply multiply the two together as result of the whole. + +this may look all awfully complicated, but infact, it isn't. it's +just a very different style of programming. once you fully understand +it's power, you won't want to live without it :-) + +if by now you haven't understood zip of how FALSE works, this probably +isn't the language for you. however, if you got the slightest feeling +that some things are getting clear to you, try understanding the examples, +and your on your way of becoming a real FALSE programmer ! :-). however, +the examples are not heavily commented, as that is considered bad-taste +in FALSE (see some section below). + + ++-------------------------------+ +| FALSE wizards corner | ++-------------------------------+ + +"Inline assembly" in FALSE: +--------------------------- + +one topic has been kept undiscussed (on purpose), and it's the +possibility to add assembly code to a FALSE program, to allow it to +be extended with custom functions. + +syntax: <integer>` + +any integer value 0..65535 folowed by a backquote. an expression like +this causes the a 16bit value to be put directly into the code. +A series of backquoted values may allow you a primitive form of +inline assembly. for example: + +[8221`29184`9336`4`50510`20142`65338`50510`11008`]a: { allocmem (size-mem) } +[8221`8797`9336`4`50510`20142`65326`50510`]f: { freemem (mem,size-) } + +are two assembly functions that allow you to allocate memory +from within FALSE (see example alloc.f) + +register conventions: +when writing assembly code for use with FALSE, use following registers: + +A6 = dosbase +A5 = evaluation stack. use MOVE.L (A5)+,D0 to read a paramenter into D0, + and MOVE.L D0,-(A5) to write one. +A4 = variables. 0(A4) = a, 4(A4) = b etc. +D6 = stdout +D5 = stdin + +example code for allocmem/freemem above: + +alloc: move.l (a5)+,d0 + moveq #0,d1 + move.l 4.w,a2 + exg a2,a6 ; we need to restore dosbase later. + jsr -198(a6) + exg a2,a6 + move.l d0,-(a5) ; no rts, that's done by [] + +free: move.l (a5)+,d0 ; second argument first! + move.l (a5)+,a1 + move.l 4.w,a2 + exg a2,a6 + jsr -210(a6) + exg a2,a6 + + +peek/poke: +---------- + +":" and ";" are operators to read and write variables, but they can be +(mis-)used to do arbitrary peek and poking, even array-indexing! +(see vcheck.f for an example: we read execbase) + +array indexing and structure reading: +if p is a pointer to an array/structure, then: + +p;<index>+; + +reads p[<index>]. + +unfortunately, this way you can only read 32bit values. + +cli arguments: +-------------- + +reading files is mostly done with redirection on the commandline, however, +for future extensability, a pointer to the command-line arguments is +passed in var a. see also "command line tips" below. + +stack: +------ + +you can use the stack as a buffer, and reverse-indexing the values +on it with ø. however, the FALSE stack is the lower-half of the normal +amigados stack, and thus normally only 2k. You can write programs +that need arbitrarily large stack-buffers by increasing the stack +size before running. + +command line tips: +------------------ + +- make sure you write an input redirection when testing some + programs: if the program simply does "nothing", than the + computer is not hung, but it's simply waiting for input. +- if you do not write a flush (ß) at the start of a program that + processes the input to the output, you will get a <lf> as + first input: this is actually the commandline. example: + + a.out blabla <in >out + + then a.out will first read "blabla" as a line, then the contents + of "in". + + +good style: +----------- + +programming in FALSE has a certain kind of taste: it's not easy, but +when it works, it works good, and the resulting sources look great. +Therefore, it may be tempting to "indent" while-loops in larger +programs, but remember: +- indentation, spacing and comments are for wimps :-) +- real FALSE programmmers: + - write dense code + - write only very "global" comments. + - use the stack intensively, and thus dislike to use variables + for other purposes than function definitions. + + + ++---------------------------------------+ +| FALSE language overview. | ++---------------------------------------+ + +syntax: pops: pushes: example: + -->top -->top +--------------- --------------- --------------- ------------------------------- + +{comment} - - { this is a comment } +[code] - function [1+] { (lambda (x) (+ x 1)) } +a .. z - varadr a { use a: or a; } +integer - value 1 +'char - value 'A { 65 } +num` - - 0` { emitword(0) } + +: n,varadr - 1a: { a:=1 } +; varadr varvalue a; { a } +! function - f;! { f() } + ++ n1,n1 n1+n2 1 2+ { 1+2 } +- n1,n2 n1-n2 1 2- +* n1,n2 n1*n2 1 2* +/ n1,n2 n1/n2 1 2/ +_ n -n 1_ { -1 } + += n1,n1 n1=n2 1 2=~ { 1<>2 } +> n1,n2 n1>n2 1 2> + +& n1,n2 n1 and n2 1 2& { 1 and 2 } +| n1,n2 n1 or n2 1 2| +~ n not n 0~ { -1,TRUE } + +$ n n,n 1$ { dupl. top stack } +% n - 1% { del. top stack } +\ n1,n2 n2,n1 1 2\ { swap } +@ n,n1,n2 n1,n2,n 1 2 3@ { rot } +ø (alt-o) n v 1 2 1ø { pick } + + +? bool,fun - a;2=[1f;!]? + { if a=2 then f(1) } +# boolf,fun - 1[$100<][1+]# + { while a<100 do a:=a+1 } + +. n - 1. { printnum(1) } +"string" - - "hi!" { printstr("hi!") } +, ch - 10, { putc(10) } +^ - ch ^ { getc() } +ß (alt-s) - - ß { flush() } + + + ++-----------------------------------------------+ +| additional infos & thank you's | ++-----------------------------------------------+ + +FALSE was created for fun, just to see how small a compiler I could +write while still compiling a relatively powerfull language. +The result is even better than I thought: it's great fun to +program in FALSE, and it looks even better. + +about the compiler source: note that throughout the program ALL +variables reside in registers without saving on the stack! +please: don't come and tell me you found a way to reduce +the size of the executable by 4 more bytes... I think it's small +enough as it is now. + +False has inspired other people to implement similarly perverse +languages. Some of them are: + +* "Brainfuck" by Urban Mueller. If you enjoy compilers just because + of their lenght, make sure you get a look at the this! (an + executable in less than 256 bytes!) [aminet:dev/lang/brainfuck2.lha] + This is helloworld: + + >+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] + <.#>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[ + <++++>-]<+.[-]++++++++++. + +* "Y" by Thomas Fischbacher. Very similar to False (syntax too), yet + with some more powerful constructs. Comes with (portable) interpreter + in C++ [aminet:dev/lang/Y.lha] + +* "Befunge" by Chris Pressey. Comes with interpreter and debugger in C. + Code is different from False, but looks equally beautiful. [bef.zip, + have a look at http://www.cats-eye.com/cet/soft/lang/befunge/]. + factorial looks like this: + + v + >v"Please enter a number (1-16) : "0< + ,: >$*99g1-:99p#v_.25*,@ + ^_&:1-99p>:1-:!|10 < + ^ < + +* "Bloop" by Ben Schaeffer <Yaxman@nesbbx.rain.com>. An as yet unreleased + language with features from False (and another pet language of mine, + "Yax"). Ben also made a true x86 version of False (by translating the + 68k code), but I lost the code (silly me). + + +Steinar Knutsen has been so friendly to set up an FTP site so +all you people can put your False related products there! + +ftp://ftp.nvg.unit.no/pub/lang/false/ for the distribution. +ftp://ftp.nvg.unit.no/pub/lang/false/src/ for sources not in the +distribution. + + +Chris Pressey has a False homepage at: + +http://www.cats-eye.com/cet/soft/lang/false/ + + + +I want to thank the people who contributed sourcecode, +among others: + +Ben Schaeffer, Ed Mackey, Eelko de Vos (and the rest of The TU-Delft +False Fanclub, Maarten and Rene), Herb Wollman, Lionel Vintenat, +Marcel van Kervinck, Peter Bengtsson, Steinar Knutsen, Thomas Fischbacher, +and Tomas Partl + +and the many more people that have shown their interest +in the language. one of them put it like this: + + #define FLAME ON + Dear Mr. Wouter van Oortmerssen, Sir, Bwana! + + We (FORTH enthusiasts of Southern German Banana Republic + of Bavaria) are not amused by your FALSE language. + + No Sir, not at all. + + Some of us are still jumping up and down in the coconut tree + muttering obscenities like "DUP RECURSE that *@! Oortmerssen!". + (Some are say even things like "'Oortmerssen EXECUTE") + + You have had the intention of writing an absolutely cryptic + while extreme terse & powerful language. In that you've + succeeded marvelously. + Yet why, Great Moore! have you taken FORTH for the template? + Forth is quite cryptic already, yet you must you render it + completely unreadable. In Bavaria this is regarded as a + grave public offense, sentenceable to not below of 3 years + of pure K&R C programming. You could plead for clemency by + pointing out your having introduced the lambda computational + concept into FORTH, though. + I will grant you that much. + +Donations? who would want to give something for a program that +has the size of a bootblock virus? anyway, the only thing I'd +like to receive is large and complex FALSE sources (of working +applications, of course). Please always put a comment at the +top of your source, otherwise you'll give me a hard time guessing +if it's FALSE or uuencoded. don't ask me to debug your code, as +understanding other peoples FALSE programs is horrible. + +If you want to contact me: + + + Wouter van Oortmerssen + Levendaal 87 + 2311 JG Leiden + HOLLAND + +or better if you have access to Email: + + Wouter@mars.let.uva.nl + W.v.Oortmerssen@let.uva.nl + Oortmers@fwi.uva.nl + DIR diff --git a/yacc-shaving/lolcode/lolcode-spec b/yacc-shaving/lolcode/lolcode-spec @@ -0,0 +1 @@ +Subproject commit b9abe0187b4fbaa49997992253f515b109b708f2