LISA GJ2 FIC3 -- INITIAL REFERENCE MANUAL ========================================= THE 2011 RELEASE, WITH THE DECEMBER 15 2010 VERSION OF FIC3.TXT, WHICH IS, IT SEEMS, ENTIRELY THE NORM -- future updates of fic3.zip will contain other documents and other programs which indicate interesting developments, such as new games written with LIGHT3D.TXT, while this document will be stable. WRITTEN BY ARISTO TACOMA, REDISTRIBUTION & COPYRIGHT SEE yoga4d.org/cfdl.txt Available as part of norskesites.org/fic3 }Hello world!} ( (( }Hello world!} => POP )) (LET HWORLD BE (( (( GJ-ON )) (( SHOWMOUSE )) (( }Hello world!} ; 10 ; 10 => B9-POP )) (( A-KEY )) (( GJ-DONE )) )) OK) (( LOOKSTK )) (LET AUTOSTART BE HWORLD OK) ************************************************** ************************************************** ************************************************** THE 2011 (MOST RECENT) UPDATE INFO JUST HERE: The main changes are that FIC3.TXT -- with all the high-level functions, including B9 editor, automatically started by the F3 command -- is faster as for B9, still more robust than it was, has some new (in-documented) short-cut keys to existing functions (CTR-keys), and, in general, the FIC3.TXT loads faster for some no-longer-used- very-much code has been deleted in it, notably the very early and non-robust image editor I9. In addition, there is a change towards simplicity and trust in the Dosbox approach (and its analogies) where we find that any programming for the net is of a different nature, where security concerns must come before the joy of prestine clear lovely fun thinking along the lines of 'the art of programming'. To emphasize the importance of the art of programming -- programming as thinking, as insight, as artistic inspiring, we advice the Dosbox as a 'shielding' from the somewhat over-complicated security considerations connected to networking, as the primary think-tank and game-platform for the Lisa GJ2 Fic3 language. See also norskesites.org/f3 and moscowsites.org/f3 Earlier F3DOCS.TXT document continues here, unchanged, but where there are any questions about the content, see if it is corrected either in the note above, or in the norskesites.org/fic3 general info page. The adviced use of the main bulk of the following is by means of the CTR-F (or F4) scan / find function, with CTR-L for repeat of it, in order to pinpoint comments about a particular function. For instance, if you want to find out whether there is more MULtiplication functions with some important whole numbers like 4 or 8, press CTR-F and type in (( MUL and voila! you are there. GOOD LUCK! -- AT, with LAH, 2011 ************************************************** ************************************************** ************************************************** NOTE ON SOME DEVELOPMENTS 2006--2010 AND LINUX: Firth -- with through Lisamode became Firth Lisa, then Lisa Gj2, then Lisa GJ2 FIC3, I made in its first full form in 2006, and KINGLINE.TXT can be started directly by FIC3 without loading higher-level functions first, as they go back to those early days. The Red Hat 8.0 F3 automatically loads FIC3, in its quiet fashion -- no particular welcome nor goodbye greeting when you start the ./F3 for it has a future use also in generating and reading internet pages also server- side, and so must be as quiet as Perl is around its actions (all it does is to generate some lineshifts and blanks when it starts up and when it completes). Still, even with the higher-level functions loaded, ./F3 can start :KINGLINE IN without complaints (for more recently defined functions overrides earlier ones, when they are not part of the absolute foundational part but a higher-level part). That is to say, you can use KINGLINE to do text-mode editing in Linux before you start any screen -- of short config files and such. For that reason, I have not changed its way of treating file-names: uppercase and lowercase must be typed correctly when used in Unix, and they can even be longer than 8 characters, and suffix must be typed also. In addition, since it is called KINGLINE.TXT, and since ./F3 is sensitive as for filenames to uppercase/lowercase -- assuming .TXT in uppercase -- you must do :KINGLINE IN rather than something like :kingline IN to start it. The ./F3 in graphical mode is only for 1024*768 monitor, or 4 times 3 in height times width, full-screen, when used e.g. for the B9 editor. It requires a little bit installation, and it starts and quits far more rapidly in the Firth. See installation info a couple of pages ahead or something like that -- at least in the beginning of this document. The Firth is at the CD called Lisa found in 10 MB-bundles in a link given at yoga4d.org/download, and these 10 MB-bundles are sewn together by a program also listed there which I call DOGGY; they can then be unzipped, and the resulting .IMG file can be renamed .ISO and burned to a standard CD by a standard ISO-burner program on several platforms, and be used to boot a blank standard PC and install all the 100 and more standard DOS-goodies that is part of what I called then Lisacode, where Freedos elements play an essential role. This Lisacode -- or 'Firth dos' -- I remake in the CPU I make in my own hardware in the future. Linux has a valuable transitional use, though -- thereby also the present ./F3; but I refuse to go along with the types of monitors which have too non-squarish shapes merely to pack many popup-screens together in a restless, over-networkized way; so I affirm that the only Linux I REALLY support STRONGLY within the Linux realm is the Red Hat 8.0 and then only when run on a 4"3 near-squarish monitor (3 * 4 = height * width). For the reason of the fact that the Red Hat 8.0 is free software (unlike the later versions named same), combined with the fact that people run away from simple earlier versions to over-complexified slower later versions, you find the original free Red Hat 8.0 CDs also at yoga4d.org/download. At the time, I just used this Linux for its capacity, unlike Freedos, to access USB flashdisks and such, and so I called it 'USB utility partition' or the like. They are CD R1, R2, and R3 at yoga4d.org/download, and they are to be 'dogged' together into three CDs, where R1 is the installation CD. The ideal way to install it is by spending lots of time trying to make sense of the INSTALL.TXT you also find at yoga4d.org/download, reading it from bottom-up -- but noticing corrections at top -- and it IS chaotic, I know, but the portions that ought to be correct are correct. At the time, I wanted the privacy of working to refine this further at the same time as I wanted to publish what I had done, and so the INSTALL.TXT there is a compromise between holding back and publishing widely. But if you follow it, you will FIRST install the Lisa CD (also called Firth CD), and THEN install the Red Hat 8, or RH, on a blank PC with at least 10 GB to each of the two parts. On top of all this, you can then put the FIC3 stuff in the suitable folders and it will run wonderfully. A program can detect the multitasking network type of context by checking on the whether the function RH_ENABLED returns y. You will see that TIMING, the internal program in FIC3 which rings the DOS PcSpeaker after the amount of minutes you want, checks on this function and if it is in Red Hat, the TIMING program will tell that it works currently only in D.O.S. All my internet work, by and large, is done at present by RH8 with all the extensions as I list at yoga4d.org and its links to sublevels of yoga6d.org, with some kind of ethernet card plugged into the PC and broadband cable from this. And every day I do all sorts of things with Lisa GJ2 FIC3 running both in RH8 and in the 'native Firth' mode. The COPYSCREEN and similar which makes .BMP on the fly inside D.O.S.-mode has an issue inside Linux but this is not an active part of what Lisa GJ2 FIC3 is supposed to do -- to import .BMP is allright, but any screen-output should either be by a matrix or, if you must have it, by a screen capture done in GIMP over a DOSBOX frame or the like. As I get my own hardware more and more running, with its own Lisacode, and its own connections to Internet, I expect this to take over from both this 'native Firth' and also from Red Hat 8.0. But still I regard both these favourably, and far more favourably than all other platforms -- where I suppose I could make some plugins some day, at most, but I do not cater for them very much. (The Dosboxes do however provide a frame also on very wide monitors doing Windows or the like.) All right? :-) So: In any Firth Lisacode or DOSBOX environment, you can start the programming language by command F3 or possibly FIC3 FIC3 when you have unzipped fic3.zip which is at www.norskesites.org/fic3 into the boehm/boehmian folder, overwriting any same-named files. Take a backup of all your earlier stuff first! Exit the language by command XO when you have used it interactively. Exit the Dosbox by command exit and there are also some wierdy function-key combinations to switch between full-screen and frame mode if you look into its documentation somewhere (inside /dbx folder, where all acknowledgements for original contributions to this projects is included; same for Allegro.) The fic3.zip has is a lot lot of files, due to the Linux version -- hardly any of the Linux graph files are necessary, but I hadn't the heart to exclude anything of this classic Allegro which has inspired so many to do independent good work, -- I included it. So you do unzip fic3 when you have done a cd /dosdisk/boehm/boehmian or when you have done a cd \boehm\boehmian -- in the Firth case. In the dosdisk case, they might be folders you just created. It CAN be other than boehm/boehmian as folder-names but there is a name-convention stemming back to the Firth development phase which is more tightly affirmed by the Firth FIC3.EXE, so for compatibility cross-platform stick to these two folders, which means all and nothing and all, afresh. In the Firth Lisa environment (unlike Dosbox in Linux) the filenames will be automatically shortened and so it will ask for rename or the like, just answer with a letter A which means, replace All -- for same-named files are either the new ones that you want, e.g. the new FIC3.TXT and new FIC3.EXE -- or they are same-named within the group of the new due to shortening of filenames to that excellent standard of 8 characters. In Red Hat 8.0, see below for installation if this is the first time you bless your Red Hat with Lisa GJ2 FIC3 to run natively there, at great speed. Once F3 is up, start eg the in-built editor B9 by typing B9 and press ENTER. Inside this, try the super-simple spreadsheet SPC by pressing CTR-D. You return to B9 by pressing ESC a couple of times. You leave B9 by pressing ESC again. All this requires a bit of speed and a bit of ram if you use something like a Dosbox. (Native Firth goes fastest. Requires the right dimensions if you use Firth on your monitor: it must be the classical squarish format (3 in height, 4 units in width, such as 768*1024 with 256 colors as a minimum on a Vesa-compatible videocard, 20 GB harddisk, Intel386-compatible CPU, a gigabyte RAM.) Will make hardware in particular for this language called Lisa GJ2 Fic3 LT computer. For DOSBOX info see also yoga4d.org/talks and the uppermost links at yoga4d.org. The former cover page of yoga6d.org, now English search engine, is what is the coverpage still at yoga4d.org. Before March 22, 2010, the yoga4d.org and yoga6d.org were called yoga4d.com and yoga6d.com but I no longer have these names (due to a chaotic webhotel I had at that time). F3: The Red Hat 8.0 version for those who have the right monitor proportions (or who use it in text mode only): F3, which we can also write as ./F3 since that's how we start it after we have done a cd over to cd /dosdrive/boehm/boehmian, is the partial port of Lisa GJ2 FIC3 to Red Hat 8.0 when monitor is proper. It hasn't got sound, is not as compatible as Dosbox, but nearly ten times faster and in some circumstances much more -- and indeed it approximates the full Firth/native DOS speed. Many folks have the liballeg.so.4.0 installed -- which is even freer software than GNU GPL -- the author Hargreaves calls it 'giftware' -- do what you want with it, nice if you mention it! If so, after you have asserted that F3 is a program e.g. by typing chmod 777 F3 or whatever, when you have administrator powers in Red Hat 8.0 (this affects security settings and a Red Hat 8.0 program like gftp can show more correctly what those settings are, and also change them, also for files at your disk), it is startable by command ./F3 when cd /dosdrive/boehm/boehmian is done first, when the fic3.zip has been unzipped just there. To make sure that you have the background liballeg.so.4.0 when you don't have it from earlier on, you just do this (still within that /dosdrive/boehm/boehmian) -- type these lines and overlook the masses of cryptic messages, just wait them out, when it comes to a couple of the lines. If you have a PC, as I often have, with a completely different date than most people, make it standard just when you compile this stuff by the command date --set=mm/dd/yyyy with a suitable mm, dd and yyyy, since the compile commands check what files are newer etc. Then do this (that's lowercase LD, letter L): gedit /etc/ld.so.conf This shows the content of that text file and it is vital that it is correct or the Red Hat 8.0 may not function, so edit carefully if at all!!! Check that /usr/local/lib is a line among the dozen of so lines in this file. If not, carefully type it in as line number 1, save, and reboot before you do the next thingies; otherwise quit without changing anything. cd /dosdisk/boehm/boehmian cd allegro* ./configure make su -c "make install" Then you can go back to cd /dosdisk/boehm/boehmian and you can try it all: ./F3 To get up this documentation, type :F3DOCS B9 while inside it. See images by IMGS. Etc. Note that F3 loads FIC3.TXT automatically and always. Its text mode is entirely primitive but that is part of the point: for this very primitive Linux functionality is driving the whole HTML page swapping in Internet. It just about manages to get the backspace to work, and it keeps repeating the names of programs typed in, and such things. The text mode has no functionality for such as KEYTOUCH or CLS, but KINGLINE works, file handling works, and apart from its starting-up and its completion, it compiles fast and runs as fast as anything does when you do multitasking in Linux. Anything very DOS-like such as command LISACODE when it runs in the RH8 mode, naturally. MUCH but NOT ALL graphics, and also not all large (I think) memory handling works as it should in the current RH8 version of Lisa GJ2 FIC3, but after all there are relatively few issues. In all cases it is necessary that the monitor is the 4"3 type, works well -- and THERE you get all sorts of KEYTOUCH and CLS and you name it. For any other type of monitor, and for more compatibility, use the (much slower, but good enough in many cases) Dosbox alternative when you do it on Linux or on other machines altogether. The "Dosbox" is not Dos but an emulation of a CPU which runs Dos, that's why Firth/Freedos is twenty times faster; but the RH8 version of Lisa GJ2 FIC3 is about as fast, in many ways, as the Firth/Freedos version (depending on what else is run in the background on the same machine). Try the :WETCHICK IN command, the girl is a well-trained rhythmic sports gymnastics girl in bathing suit lying half-way into the water -- it is a 200x200 GJP image but the program WETCHICK.TXT doubles the pixels. See how much information is actually in 200x200, it is a whole rich gestalt. [[[Acknowledgements: The image is rotated and an excerpt of a photo I sometime found in an archive, wildly mixed of all and everything without any much censorship and certainly much that is classified in the 'Above 18' / 'Family filter' category in a search engine, imgsrc.ru.]]] WORKAROUNDS FOR ./F3, THE RED HAT 8.0 VERSION: I have mentioned that all keyboard input and screen output in the text mode is primitive. So test anything made for the text mode carefully. In particular, GOTOXY, CLS, KEYTOUCH and such do not do things and so there is less control over the text screen. This is natural anyway in Linux programs. When any file is read in, be sure that the program itself does the uppercase-thingy before getting the file, as I have allowed the Unix-case-sensitivity to stay on with the file-read and file-write commands. This in order to communicate better with other programs inside Unix-like systems. The LOG2R function, unlike LOGR and LOG10R, isn't at present in the RH8 version, but is merely set to a somewhat higher number -- ten times LOG10R. It is not really any much used except to calculate size of a small extra-stack for quicksort, that's why it is set to a bigger value. SOMEWHAT IMPORTANT WORKAROUND FOR RH8 LISA GJ2 FIC3 AND A SOMEWHAT EASY SOLUTION: The handling of text file lineshifts in the background of unix-like platforms and dos-like platforms is different enough that on occasion, this issue might arise: certain extra blanks at the completion of lines as generated by the normal editing process of B9 in Firth/Dos may suddenly, with or without further editing in Red Hat 8.0 in such as gedit, cause 'mysterious' extra blank lines in the middle of the text when opened inside B9 in the RH8 ./F9 command. Also, when pushing the CTR-PgDn which should go to the completing line, it doesn't go to the completing line, for it doesn't count those extra mysterious blank lines. EASY FAST SOLUTION: Start ./F3 and type the word WORDWRAP and specify the file, if you have a backup of the original file. Then specify linelength 76 or so. Save it and try it. Then open it in ./F9 and type the :FILENAME B9 as usual, and go quickly through it, doing a CTR-DEL 1 [LINESHIFT] on each remaining blank line. There are more such workarounds quite possibly, as this RH8 version ./F3 is quite new. I have to say that ./F3 works really well compared to what I initially thought. SOME QUIRKS IN GOING TO THE RH8 VERSION: As said, not all graphics work -- so be prepared to continue to use the Dosbox for its increased graphics and its well-done thinking on memory handling. It is slower but it really COMPLEMENTS the ./F3. There is for some large matrices in some heavy arithmetic connections some issue about the first eight or ten rows or possibly the first hundred bytes, which does not at all exist in the Firth/Dos-version, and which must have something to do with the more (over-)complicated way memory is handled in Linux. This has only arisen once, and I haven't quite pinpointed what it is yet, and have merely incorporated it into the LIGHT3D.TXT so that, since it is a very large matrix relative to what's typical and with a lot lot of calculation, decided that it begins on row 9, rather than on row 1. But I liked what this by and large unexpected change did to how VIEW came about in the LIGHT3D -- with one of the presents 'unpacked', one of the gifts 'opened' -- so I didn't redo the VIEW but allowed it to be the way it now is in both versions. As for graphics, the SPRING which used to write so happily to a much larger area of the screen than the existing portion, and other such routines also using LOGOMODE, had to be rewritten to utilize less sprightly (ie, wild) parameters to the line- drawing routines (in other words, more meaningful parameters are required in Linux; but that's okay). Anything about timing, seconds counting and such has to be checked in each case in the ./F3 version. The SF32008 has to be run in the Firth native mode or, if PC is fast enough, in the Dosbox, for it uses SECONDS, not merely the slightly more implemented GOODPAUSE. SOME PRACTICAL HINTS WHILE FIXING THINGS: Compilation can usually be stopped by pressing Q or by pressing CTR-C or the like if there is a message; the messages might be a bit funny but they usually have a correct line number, especially when the word LOOKSTK has been inserted. When you use a lot rich stack, put in the word RICHSTK after the GJ-DONE, to see any left-over content printed in text form (it should usually be none, and it's a good test). Any wild behaviour during compilation, check the COMPILEDPAUSED-series of words and VISIBLECOMPILATION. Any wild behaviour during performance, usually it makes sense to put in check-points -- A-KEY is useful together with CLS and some print-out statements of the B9-POP type -- but sometimes it might happen that performance goes wild due to an issue which is quite subtle. For that reason, especially when new to this programming environment, add a little only each time to a program you build, so that if there are any wild things, you know they are in what you most recently added, and that simplifies enormously. Still, when going from one platform or machine type to another something might show which hardly can be blamed on your program -- it may be you touch on a peculiar sensitivity in one platform. Type XO to exit the text mode of ./F3 or F3. This also if a program exits without having its proper (( RAM-REFRESH )) or, for graphics mode, its (( GJ-DONE )). A program which exits a lot for no reason, make a copy of it under a new name and comment out or delete more and more of it until it ceases to exit then take a break, go for a walk, and look at what it might be if it is not obvious at first. Make lots of backups. Listen to good music. Eat vitamins. MAIN DICTIONARY OF LISA GJ2 FIC3 FOLLOWS ASCII SEQUENCE 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ where 32 counts as space, and 13 as the enter (lineshift key), whereas 13 and/or 10 are used as lineshifts inside text files. 37 is percentage sign e.g. in Linux, while 37 is a branch or bucket of three sprouting flowers up and to the right in the B9 font and similar as I have made it. IN-BUILT PROGRAMS -- PART OF FIC3.TXT -- TRY: SPRING PING IMGS I9 (workaround: save after Zing) B9 (workdaround: paste on maximum second to last line) (This is, by the way, an eminent utterly simple editor.) LAB and, if you backup copy B9FONT.TXT first, you you can make new fonts and such for Lisa by the command MOREFONT -- it saves when you press ESC button to B9FONT.TXT, which is used e.g. by the B9 editor and by in fact most programs. WORDWRAP CONVBAT TIMING The beginner programmer in Lisa GJ2 FIc3 might find some useful hints in the completing section of this document, and other useful comments here and there on yoga4d.org; but this is more something such as a manual meant for searching through in a text editor looking for a relevant comment on how to make sense of something you've seen either in an example program, or in FIC3.TXT -- the higher-level function source code -- or which you remember exists as a function but which you're unsure about. But at the present stage this manual is a bit coarse and a bit early and a bit too incomplete and so example programs and a bit of experimentation is -- before other documents arrive on the scene -- of great import. COMMENTS ON LISA GJ2 FIC3 AND ON WHAT THE FOLLOWING DICTIONARY -- AND THE GENERAL INFO ON PROGRAMMING IN LISA AFTER THEM -- COVERS Essentially, much of the dictionary and the comments after them in this document, which is by and large exactly the same in the MTDOC.TXT found in the GJ2.ZIP, must be considered 'process documentation'. You have to pick up hints from it and not always read it literally. More literally, naturally, are the example programs you find working. At the moment of writing I don't have any other big piece of documentation of Lisa GJ2 Fic3, though. This I suppose will improve in upcoming decades. And some further refinements of FIC3 is to be expected. The example programs include much which is not for the beginner, but even the beginner might pick up hints from them. Note that the startup of Fic3 is by command F3 or FIC3 FIC3 and this means that FIC3.EXE, which is free software, startable in the Firth CD as you can get at yoga4d.org/download, and you can install the yoga4d.org/city -- the GJ2.ZIP before this if you like -- just unzip all these extensions to C:\BOEHM\BOEHMIAN. This is easy if you have done this thing many times; but a beginner will surely want to put aside a lot of time to get this right. Simpler, though, to start in Dosbox, if the computer is fast enough. See yoga4d.org info on this including yoga4d.org/talks. Expect to spend some time tweaking stuff to get it right the first time -- correctly memory settings in Dosbox is one thing. Getting use to the right mount is another. Dosbox can be funny as to mouse pointer moving in and out and so it is an advantage that mouse pointer is only used when it is important, in Lisa GJ2 Fic3 programming (not during text editing with B9 editor, because in my opinion text editing is purer without it when the editing options are few and pure). You will find programs of great interest to those who want to understand more about bits, about how to make fonts, about how to enlarge fonts, about how to do a little 3d arithmetic here -- but this is not a set of programs which is designed to impress somone wanting to squeeze the most out of their computer or anything like that -- and many programs are given elsewhere, which could be more interesting if it is about impressing. This is more for instruction. LIGHT3D IT READCOUR OMNI as example programs which can be started. These can be started by :LIGHT3D IN :IT IN :READCOUR IN :OMNI IN The F8 will open up DOC-NAME for READCOUR and OMNI. The READCOUR is actually possible to learn to read really, really fast with -- after some initial moments learning the font by looking at it. The more complicated way is to attach them to the completing part of the FIC3.TXT and autostart them that way. The LIGHT3D, try pressing ENTER then R then Y, type the word VIEW, press ENTER, and press TABL (tabulator-key, or ctr-i). Press Q and Y to exit after you have seen the rotation of two-three cubes rotating among themselves and study the code if you like. Or ESC for a very, very brief info-page. Contains much powerful ideas which are here only hinted at. Expect an assembly-expanded LISA GJ2 FIC3 (also for Intel CPU) which has more of this where the background stuff here done on the real number stack, or RICHSTK, is done by assembly. And in which we have done stuff on moving bodies. I'd like to emphasize what I always emphasize, that the mind may stay far more awake by avoiding too much over-smoothing: I tried to take away the blinking and discovered that the mind got drowsy compared to when the blinking is there -- do you find the same for your mind? This is part of the neopopperian exploration. See yoga6d.org/super and the yoga4d.org/updated.htm list for encyclopaedia and also example programs. I insert here the comments I wrote for www.norskesites.org/fic3 as for this version of LIGHT3D, as they provide an entry-point to understand the code for a programmer wanting to spend several hours with it, interpreting it, perhaps varying it: <<.. The LIGHT3D.TXT code next works for what it is at present intended to do (see F3DOCS for a quick way to see that which it can do). It is important not for the uniqueness in turning cubes around but for the fact that the code is ENTIRELY simple, if one analyzes it function by function and spends time with it. There is no reliance on any strange matrices which do strange things to other strange matrices miraculously resulting in a 'rotation' or the like. You have here a simple long matrix of triangles -- three times three coordinates, x, y, z, with the z of the triangles put first in it for ease of sorting it, or a copy of it rather, when we want to show it to the screen so that the triangles nearest are all grouped together at one part of the matrix. Each triangle has a green-tone color to it. As you know, or you will know if you try to sketch it on paper, any flat surface with straight lines outlining it can be divided into triangles. So a circle can be approximated by small enough triangles in one or another way. By having a z coordinate, we have a room/depth system in which that which is further away gets more and more tightly woven around the center of the view, similar to the in manifest reality that that which is far away is more tightly together in the visual field than that which is very near to you. For instance, five buildings near you may cover the whole visual field, while five buildings seen at a distance in front of you may cover just a small part of the visual field, right in the centre. To navigate, we would like to turn around, not just move linearly forward and back and sideways; and we would also like to turn around objects -- here called records, or groups, if there are composite objects -- and do more such things. The functions sine, cosine, and their inverse neatly summarized in the arc-tangens, together with the square root, the capacity to multiply something with itself, as well as go back and forth between degrees of the psychologically intuitive easy natural kind of 0..360 and the arithmetically faster version of 0..two times pi, is ALL we need to rotate any triangle in the two dimensions of, say, X and Y. For with the square root of the sum of the squares, we can find the length from the center of the coordinate system to any point. We can, by sine, cosine and arc-tangens, find the existing angle between any line and the zero-degree line, and add any value to it, and calculate the new points when we also have the length of the line. And this we can do ENTIRELY by these utterly simple, and fast, decimal-dot functions. And, when we can do it for two dimensions, we can do it also for three, simply by doing it twice over -- say, when we have X, Y and Z, we can do X and Z, and then we can do Y and Z. One can surely gain a few petty percentages of increase of speed by making excessively complicated, second-code over this, but it is the more luxurious approach of first-hand programming to do things clearly rather than to pump every little bit out of the computer. At no point have we invoked dubvious mathematical theorems. So the turning around of any coordinates x1, y1, z1 by a certain angle a1, resulting in another set of coordinates x2, y2, z2, is the type of thing done at the decimal dot stack, which is called RICHSTK. Frankly, I haven't all that much experience in using this feature of my own programming language, and for the sake of speed I wanted to minimize the use of variables. So what I used, for the first time in such profusion, was the deeper-level stack routines named such things as YANTRA and MANTRA and all that, with an R at the completing part of them -- YANTRAR, MANTRAR -- to copy deep into the rich stack and get the value on to the top. I decided to throw in those semicolons ; to indicate just how many are on the rich stack at any time, -- these semicolons are psychological features of the programming language, we might say optional punctuation -- they don't do anything in terms of what is performed. Once I got it to work, it worked really well, and I just copied the whole sequence and modified it for other dimensions and for loops through the main matrix and such things. So, what I am aiming at pointing out, is the by first-handedness in feeling and in approach to programming you can ALSO do such things as evoke a sense of room/depth and do rotations and such; and while this is but an initial version of LIGHT3D.TXT, in which portions (the First In, First Out, or FIFO routines in particular) are not tested, and other portions (those hinting at spherical things and such) are not implemented yet, this will go all the way to anatomically sweet humans doing things with a slender grace in tantric games, and I will give some games of this kind all with source for this. In fact, the plan is that the LIGHT3D.TXT code you see as follows will be extended all the way as it is a kind of perfume of excellence, as I see it (I hope it is), relative to what first-hand programming can be for artists, who seek to get an impressionistic, BI spring like STIMULUS of mind rather than a mere simulation or imitation of manifest reality. Whatever elements there will be of smoothing out such and such there will be no more smoothing out than that which is necessary to give a sense of beauty, charm and youth to the beings on-screen. When you watch the classical well-known photo of Birgitte Bardot as treated in Red Hat 8.0's Gimp in the way I have done it with many images, you see that the computer-generated impressionistic brush-stroke-like patches are quite rough and NEVERTHELESS the mind is ENTIRELY SURE that her skin is as smooth as the golden sun of any young girl. In fact, smoother than any so-called high resolution photo can ever indicate: because the image becomes a story for the mind to interpret, rather than an over-fixed over-smoothed attempt to copy glamour of manifest reality onto a board of pixels on-screen or on-paper. The rough patches which are however artistically fine-tuned requires a certain artistic background education and it is my postulate that work with the Lisa GJ2 FIC3 language is eminently good in all artistic education. The approach of LIGHT3D.TXT, as I program it from scratch in this our language as I've made it, is to blaze a new, wide, two-way trail from the artistic spirit to the technological world, in which we are not stupidly impressed by imitation of reality, but rather sophisticated in our yearning for encountering that which raises our inmost feelings as to the objects depicted. Each triangle, by the way, is marked as having a group number and a record number. You can then imagine that a longlegged girl, like the one indicated in the SM-like situation in the very crude, but also very glamorous, black-and-white photo rendering at the completion of this page, can move her long legs by having the legs being a group composed of several records; her whole body being indeed a group. We can work out in a first-hand way what movement ranges and what combinations we consider as having a radiance of good health and store a number of these and play on these as an alphabeth somehow when we make the vocabulary of a tantric game. The g-and-r-warps (ground and record warps) is a way to connect algorithms doing such movements to either a specific record in a specific group, or to a group as a whole. When the record is not specified, it is taken to mean that it applies to the group as a whole. This g-and-r warp table is stored on top of the matrix when the matrix is stored to a file. The file VIEW.TXT which can be loaded into LIGHT3D contains three cubes and there is a g-and-r table saying that we want rotation for each of the records -- each record being a cube -- and also for the whole group. The result is that we get a rotation of self-rotating cubes, going on and on rather like a stimulating background graphics effects. The dozen lines or so completing the LIGHT3D.TXT in the present version is all that is necessary to set up a warp-table so that a number 1 and a number 2 refers to a simple example rotation and shifting of position; and there is a function key letter (indicated in the help info screen which comes up when one presses ESC) which allows you to manually type in, in a few seconds, which records connect to which functions. By pressing the TABL, the tabulator key, you can test how the warp works out -- and this is approaching the game situation. So at present this is but a beginning but I think it is valuable also to see LIGHT3D.TXT in this early stage in order to get into a fuller understanding of it when we have it as a considerably larger Lisa GJ2 FIC3 program capable of getting you tantrically stimulated in a fully artistic way. (I am at present preparing a Norwegian book about this, oriented towards young artists who want to engage this programming language, and also another Norwegian book about the years I worked with Arne Naess, the logician and eco philosopher, and how I shifted in 1996 and 1997 to working more with these themes and ceased the publication activity as editor of a magazine that I co-founded and ran at the time, in Norway, called Flux; but I also plan, without concretely having laid it out at present what book context that will be, to come up with really good gripping English writing on the Lisa GJ2 FIC3 language to be used by artists for making games and computer installations and such, after the LIGHT3D.TXT and my children with it have come fully to birth.) Put simply, stay tuned. There's a lot more to come about this. This language is here to stay and it is doing more and more what I wanted it to do. It is a package of goodness. I have got to say it myself, even though I look forward to others saying it, too.. We're there, soon! ..>> That quote, from the norskesites.org/fic3, is here completed. Note that the QSORT2 is faster than in original GJ2 as it is inside the assembly-nearer level here. Also notice MATRIXSORT which sorts a matrix staright-forward, and MATRIXSORT2 AND MATRIXSORT3 includes more than one column -- see LIGHT3D as example. This is the kind of stuff that makes FIC3 into FIC3. The IT command starts by typing :IT IN and after ENTER, you type IT and press ENTER again -- one can load additional algorithms, though. One can then press CTR-A for a menu. By pressing CTR-D (or CTR-B) and having prepared a 256-colored 200 times 200 pixels .BMP image and having it in the c:\boehm\boehmian (or similar if you use dosbox, perhaps /backup4/boehm/bohemian), you can type the whole image name -- filename.bmp -- and it loads. Set a name by CTR-F, max 8 characters, no blanks, that you are sure is not already used, and it can be saved as .GJP file. Watch out! This program is for the expert and there are absolutely no checks on what is typed and so there are plenty of possibilities for overwriting files unintentially. Before you save the file, you should usually press CTR-R for Rotate and CTR-X to mirror it, several times, as it is a bit quickly written. You can press ENTER to clip it and by combining with CTR-R you can clip various parts of it. SAMPLE1.BMP you can start with to check. After setting current filename by CTR-F to TEST or something, you can save it by CTR-S. You can retrieve by CTR-G. There are no messages -- it just acts. The extra menu comes up by pressing CTR-T. If you want to exit that menu press SPACE. You can connect to a font matcher program. For this, press CTR-T CTR-P. This brings up the same menu as the which independently is called MCPLNTX.TXT and included. Press 1 to do matching, then T do start the process, wait and see the font of the example .GJP is interpreted, by pattern matching routines I've written and optimized in Fic3.exe, -- then press ESC and the option is to save the text. Press ESC on the menu and you're back at the IT main menu. Press ESC to exit also this. A batch series of routines can then handle several .BMP-files which results from clipping up a larger book page and read in the right font. When you have a font which is different from one that you have made a matching font matrix about before, then you can start up another program -- :MCMAKER IN -- where you describe by keyboard presses how various characters or even phrases of several characters are to be interpreted, given that you have proper .GJPs. You will find that you can move by arrows around on a .GJP to focus on bits of it. These are displayed very large and higher up, also smaller. You can mask a portion of the 14x14 matrix you see there, in two ways. Either, by ctr-key together with arrow, to shrink or widen the area shown. Or, by clicking R, then moving arrows at individual pixels, and toggling view and nonview by letter X, and clicking R to return to normal mode again. In normal mode, by the way, the SPACE toggles quickness of movement through the .GJP. Each time you press ENTER you can give a letter -- uppercase or lowercase -- or other type of sign, such as a number -- as 'name' of the pixel in focus, and anything ROUGHLY like this will match up to this in the main matching program. Be sure you backup the existing match MC*.* files before you make new ones so you have good examples. The matching will naturally make a little bit mistakes or what we shall call it on such as space when a font is not monospaced, as typically there are ambiguities that only a dictionary or a grammar book or matching over several interpreted examples can solve -- or else one spends more time on matching on phrases, not just individual characters. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" general comment:::: The lovely double-quote token in informal english is best left to its own devices; it is the feeling of this writer that it is important for a good programming language, and formalism, that the formal language does not try to overtake the meaning of the quote. For that reason, we can with simplicity formally quote, using the }..} notation, an informal sentence containing the normal double quotes, e.g. as in: (( }Let's print an exclamation like "Hello world!", after this line.} => POP )) (( }Hello world!} => POP )) To repeat, the double quote " sign has no particular formal effect. You see in the above }..}-quoted sentence the use of the single quote ' sign (the one with ascii 39, whereas the 'back-tick' ascii 96 is rarely used), and it, too, can be included in a }..}-quote without further ado. There is but one use of the '-sign, and that is, when it stands on its own, and we put an ascii number inside it, like here: (( }This is the back-tick: } => POPS )) (( '96' => POP )) ############################################################################ # (( # )) Get a copy of top of the variable stack to the main stack ---> V1 (( ## )) Get a copy of the number two on the variable stack to the main stack ---> V2 (( ### )) Get a copy of the third item on varstack, to main stack ---> V3 (( #### )) Get a copy of fourth on varstack to main stack ---> V4 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $ general comment:::: Numbers preceeded with a dollar sign, like $3.14 or $0.1239 goes straight to the decimal number stack, also called RICHSTK, where they can be treated e.g. by trigonometric numbers like cosr and sinr. Since the dollar sign in the beginning normally indicates that a number is about to be read in by the compiler, it is usually nonsuitable to preceed a function one defines by this sign. Note that after the $ sign must come a number, and please avoid writing anything like $.1239, rather write $0.1239. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % general comment:::: This was, on the earlier PC keyboard, traditionally the percentage sign, but we engage it here in the radical sense of the array -- warp and matrix relevant sign -- thus the branches, because an array can have many arrays. So, whenever you see a word beginning with a % sign it means that we are dealing with something which handles arrays. Matrices are usually defined as arrays of arrays. But when you see the % in the beginning of a word, it means that we are dealing with a word, like %GET (in contrast to GM for matrices) which handles, typically -- in this particular context -- the array in terms of an array, perhaps of ordinary numbers, perhaps of warps to whatever. (( %EMPTY )) Zeroes to that array ---> RAM-PM (see comment there) ---> %MAKE (( %FACTORADD )) Add a factor to that array (( %FACTORDIV )) Divide the numbers in that array by a factor (( %FACTORMOD )) Find the MOD of the numbers in that array by a factor (( %FACTORMUL )) Multiply the numbers in that array by a number (( %FACTORSUB )) Substract a number from the numbers in that array (( %FREE )) Let completely go of this array for good, release that RAM note1>>>> The use of %FREE is enormously important on occasion, but one must also do it with equally enormous precision. On the premise that one always configures a program so that plenty of RAM is left, one can certainly neglect doing %FREE once in a while as long as the percentage of RAM reasonably adopted to these bits is fairly small. If, however, one does a loop millions of times with a %MAKE in it, then, for God's and your peace's sake, do a %FREE also. But let me show when it makes sense to be leisurely about it. In making the F9 editor [[[note: the F9 editor is what became the B9 editor when I took the text-mode editor I had made and put it into the graphical mode, making the B9 font at the same time -- and I then dropped the F9-editor from the list. This manual, written in the main long before Lisa GJ2 FIC3 was ready, has several such references to ideas, approaches, programs and even functions which are not up-to-date, but I hope somehow the manual is more instructive than it is misguiding even so.--Aristo.]]], I intuitively felt that a large background work-space of thousands of lines, indeed up to 35000, made sense, and I experimented so that I saw that in fact more could have been handled with fair ease and elegance. After some feeling it over, I came to the decision that I wanted a tiny clipboard in comparison -- a mere 270 lines or so, but certainly much more than it is practical to deal with when clipping and putting in text bits in most cases. Having made this decision, it occured to me that when one insert lines, remove lines etc, one should also have a similar limit. That would be a premise for going into the program. One can make a particular program to do cropping of tens of thousands of lines when necessary. The fact that F9 (and B9, implicitly) has these limits then encouraged a way of programming in which I rather let a little RAM be left over here and there without a proper %FREE, than risking one too much %FREE. For one too much %FREE, say, inside the line of a matrix, is something entirely altogether different than a couple of, or hundreds of, %MAKEs too many. One too much %FREE means that, perhaps during PM2FILE, the machine will have one of its moments of indigestion. Here's an example from F9: (Whether or not it corresponds to F9 as it is when you use it now I'm not sure) (LET F9-NEW-LINES BE (( >N7 >N6 )) (( (( N6 ; F9-MAX-LINE-USED >>> => INTGREATER = EXIT === )) (( F9-WORK-SPACE >>> => & )) (( N7 ; F9-MAX-LINE-USED >>> => ADD => >N9 )) (( (( F9-MAX-LINE-USED >>> ; N6 => DEC => SUB )) => NOZ (MATCHED (( (( N6 => INC => MUL4 ; # => ADD )) ; (( (( N6 => INC ; N7 => ADD )) => MUL4 ; # => ADD )) ; (( F9-MAX-LINE-USED >>> ; N6 => DEC => SUB )) => COPYNUMSHIGH )) MATCHED) )) (( N7 (COUNT (( F9-PAGE-WIDTH >>> => INC => %MAKE => & )) (( 32 ; 1 ; # => %PUT )) (( GETV ; (( N1 ; N8 => ADD )) ; # => %PUT )) COUNTUP) )) (( N7 ; F9-MAX-LINE-USED => ADDVAR )) (( && )) )) OK) (LET F9-FUNCTR-INS BE (( )) (( (( F9-LINE-NUM >>> ; F9-MAX-LINE-USED >>> => INTGTOREQUAL = EXIT === )) (( F9-MAX-LINE-USED >>> ; F9-TOP-LINE-NUM >>> => INTGTOREQUAL (MATCHED (( FREE-CLS )) (( CRLN ; CRLN ; CRLN )) (( } AT THE MOMENT, THE AMOUNT OF LINES IN THIS TEXT} => POP )) (( } SEEMS TO MATCH THE MAXIMUM AMOUNT OF LINES CURRENTLY} => POP )) (( } RESERVED, NAMELY 35000. THE ADVICE, WITH SUCH A GRAND TEXT} => POP )) (( } IS TO SEE IF IT IS POSSIBLE TO WORK WITH CONSIDERABLY} => POP )) (( } MORE HANDABLE SECTIONS OF IT. OR MANUALLY DELETE LINES} => POP )) (( } TO GIVE ROOM FOR MORE. THANK YOU.} => POP ; CRLN )) (( ENTERPLS )) (( FREE-CLS )) (( F9-STD-FRAME )) (( F9-REDISPLAY-ALL-TEXT-HERE )) (( F9-UNDERLINECURRENT-POS )) (( EXIT )) MATCHED) )) (( CLS )) (( CRLN )) (( } AFTER THE PRESENT LINE, WHICH IS LINE NUMBER} => POPS )) (( F9-LINE-NUM >>> => POP )) (( } DO YOU WANT TO INSERT A CERTAIN NUMBER OF NEW LINES?} => POP )) (( CRLN ; CRLN )) (( } (THIS IS THE CTR-INS KEY; THE CONVERSE IS CTR-DEL KEY.)} => POP )) (( CRLN ; CRLN )) (( } =========> PLEASE STORE OFTEN UNDER NEW NAMES WHEN BIG CHANGES ===========>} => POP )) (( } =========> LARGER NUMBERS THAN 270 AUTOMATICALLY CORRECTED ===========>} => POP )) (( } =========> LINES ARE CREATED AFTER THE PRESENT LINE ===========>} => POP )) (( } HOW MANY LINES INSERT HERE (MAX 270)? (ENTER=GO BACK)} => POPS )) (( MANUAL-CLEAR-KEYBUF )) (( READLN => HEAL => >N1 )) (( MANUAL-CLEAR-KEYBUF )) (( N1 => ISBASIS = GOFORWARD4 === )) (( N1 ; 1 ; 270 => SET-RANGE => >N1 )) (( F9-MAX-LINE-USED >>> ; N1 => ADD ; F9-TOP-LINE-NUM >>> => INTGREATER (MATCHED (( CRLN )) (( } THIS WOULD RESULT IN A TEXT BIGGER THAN 35000 LINES.} => POP )) (( } TRY WITH A SMALLER NUMBER. CONSIDER WORKING WITH A PORTION} => POP )) (( } OF THE TEXT AT A TIME. THANK YOU.} => POP )) (( ENTERPLS )) (( F9-STD-FRAME )) (( F9-REDISPLAY-ALL-TEXT-HERE )) (( F9-UNDERLINECURRENT-POS )) (( EXIT )) MATCHED) )) (( N1 => ISPRO (MATCHED (( F9-LINE-NUM >>> ; N1 => F9-NEW-LINES )) (( F9-LINE-POS => SETDANCE )) (( F9-LINE-NUM >>> F9-TOP-OF-PAGE-LINE-NUMBER-SHOWN < SETDANCE )) (( GOLABEL4: )) (( F9-STD-FRAME )) (( F9-REDISPLAY-ALL-TEXT-HERE )) (( F9-UNDERLINECURRENT-POS )) )) OK) (( %GET )) The main function to get one value from the array to the mainstk (( %LENGTH )) Retrieve the value which tells the length of this array ---> %MAKE ---> %GET ---> %PUT ---> %FREE ---> >MEM ---> MEM> note1:::: This gives the length of the array. But in this open world, warp-friendly and all, we find that the length of the array is simply a number which is stored right where the warp address says that the array begins. The %GET and %PUT skips lightly over this one, then. And this happens to be on occasion a very valuable asset. It means that you can preinitialize an array to, say, 10000 members, then fill up the first 5000, and sort on only these, and then put the 10000 number back in place. Something like this: (( 10000 ; 500 => MAKETWO => & ; & )) (( }SORTING..} => POPS )) (( 5000 ; # => >MEM )) (( 5000 ; ## => >MEM )) (( # ; ## => QSORT2 )) (( ## => %REVERSE )) (( }SORTED, 5000 FIRST OF THE LIST, IN REVERSE:} => POPS )) (( # ; ## => SEEBYINDEX )) (( 10000 ; # => >MEM )) (( 10000 ; ## => >MEM )) (( && ; && )) You see? (( %MAKE )) Request a segment of RAM for a totally fresh new array ---> %LENGTH (important comment on size adjustment there) ---> %EMPTY (see comment at ---> RAM-PM )) ---> %RFFG ---> %NEWRFFG ---> %GET ---> %PUT ---> %FREE ---> %REVERSE ---> %RFFGRANGE ---> MOD (important calculation) note1:::: The %MAKE produces a warp which gives the array, the array is consequitive, in other words, a big beautiful block in memory, or a small one, and within it one can use such eminent inventions as ---> COPYNUMS and ---> COPYNUMSHIGH. If you look into the %MAKE array with PEEK or MEM> (which are synonyms) do a MUL4 and go beyond the header which is basically only the %LENGTH number. With %MAKE one can make assembly also, doing some INC4 to the proper beginning above the %LENGTH byte. You can make a 50-dimensional structure as a single %MAKE. Of course, if you make rows and columns like with RAM-PM you have a great benefit, namely that the FILENUM2PM and PM2FILENUM, and FORVPM2 and such, are all there to serve you. But the trick could be to have the whole array as but one or two long rows if the matrix format doesn't suit. It is very flexible, you see, because of the warp notion. note2:::: Remember that with all things connected to these wonderful 32-bit numbers we call 'warps', though accessed as whole units, one by one, in the PC environment (as planned), and the %GET and %PUT functions, as well as the GM and PM mimicks this, must be handled by means of multiplying the index into the array by four if you do it by ---> PEEK and ---> POKE. [[[At some places in this manual mostly written before the Lisa GJ2 Fic3 was, in all its youth, mature, I indicate that such and such feature might not exist in the future version but -- e.g. the above-mentioned feature of four and four bytes -- WILL INDEED continue to exist. Some new features will be added for the transistor-based LT computer I'm working on -- 2010, June, Aristo Tacoma.]]] I'll say some more about this here, as pedagogics. So. When you are going to the next warp position, the warps are made out of four and four bytes -- each position being then something to which you want to add four, to progress from such a thing as one position in an array of warps to the next. Just one byte can have 8 bit. 8 bit is 2*2*2*2*2*2*2*2=256 possible numbers. Four of these possible numbers beside one another is 256*256*256*256 and that amounts to 4,294,967,296. The so-called 'signed' byte goes up to about half of 256, which is 128. The so-called 'signed' 32-bit number or integer, which is the usual thing here, goes up to about half of the whole variation possibility, which is 2,147,483,648 (from about that number minus one on the other side of the zero). So here we are talking of, roughly, but it is precise enough: minus two billion up to two billion. Usually, then, one to two billion. In practise, the memory available for a program is, although huge, into dozens of megabytes as a rule of thumb. The warps you get from such inventions as %MAKE and RAM-PM and the clue is to use exactly the right warps and leave the others in peace -- I mean, if you want your program to function. But please remember: if you do warp-arithmetic, adding four is like proceeding from one warp-neighbour to the next. (So you have INC4 and MUL4 and such niceties doing it quickly and snappily.) On the other hand, when you have an array and go through the most obvious functions such as %GET and %PUT, or for a matrix, GM and PM, then these do that four-multiplication thingy for you. note3:::: In contrary to what I have indicated several places as the recommended practise concerning matrices (that they should be wider by at least a couple of columns when doing FILE2PM and PM2FILE), there are clear cases where exact definitions make more sense, and that is where FILENUM2PM and PM2FILENUM are used for matrices, and where, for arrays, their sizes (unless adjusted manually, see %LENGTH) are indeed a factor in how they are used -- in which case it is important that the sizes don't overflow. (( %NEWRFFG )) Give RFFG (viz., freely fluctuating) values to this array ---> %RFFG (( %REVERSE )) Reverse the sequence of values in this array (( %RFFG )) Create a totally new array like %MAKE, but with RFFG values ---> %NEWRFFG ---> %RFFGRANGE ---> RFFG ---> FR (( %RFFGRANGE )) Fix on the values of this array to this range of RFFG ---> %RFFG (( %PUT )) The main function for putting a value from mainstk to this array (( %SEE )) An informal programmer's word to watch numbers in a tiny array (( %SWITCH )) A quick internal way to swap the content of two array positions &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& & (( & )) The main function to put a value from the main stack to the varstack ---> && ---> # ---> ## ---> >>V ---> GETV (( && )) The main function to get rid of the value which & gave to varstack ---> & ---> V>> '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ( (( ( )) In the textmode put these characters to display and nothing else ---> POPS ---> POP note1:::: This is one character to make it easy to use Lisa as a practical calculator e.g. when you want to type something along the lines of 234 8 MUL 15 MOD ( and the ( is a quick way of printing. Of course, ( is also very valuable when doing things which require that there is no blank afterwards. (( (( )) To group ideas, (( .. )) is used, but only to enhance readability (( ((DATA )) To define a new variable for whole numbers or warps or flags ---> (( VARSTRING )) to store text lines, including filenames note1:::: It is strongly recommended that each program begins with ((DATA .. )) and (( VARSTRING .. )) definitions before the first function definitions, for clarity. Actions (viz., functions) must be divided from storage places. (( (COUNT )) Inside a function only: count from 1..value given. ---> COUNTUP) ---> N1 ---> N2 ---> EXIT ---> GOFORWARD1 .. 4 ---> RMS note1:::: See comment at (( N1 )) on use of EXIT / GOFORWARDn inside a (COUNT .. COUNTUP) loop, and more. (( (LET )) Oh la la. This is the main way to define a new function in Lisa. ---> OK) (( (LNR )) In textmode, put value from decimal stack to monitor with lineshift (( (LNS )) In textmode, put value from simple stack to monitor with lineshift (( (LNV )) In textmode, put value from varstack to monitor with lineshift (( (MATCHED .. )(OTHER .. MATCHED) )) This is the main way in Lisa to (( (MATCHED .. MATCHED) )) create a 'conditional statement' ---> = (perfect synonyms in = .. == .. === and = .. ===) note1:::: Make sure the structure inside a function has the right number of these, esp. when you 'nest' one group of these inside another. There can be many dozens as long as you count them. If there is a structure mismatch the compiler may exit suddenly, so in case do a ---> COMPILEPAUSED and ---> VISIBLECOMPILATION to spot where it is if it is uncertain which function it may be. note2:::: Use the = .. == .. === and = .. === format to freshen up the look of a function which has a lot of the other syntax, but also when there are very short expressions which can fit in a single line. (( (S )) Print to monitor from simplestack in textmode (( (R )) Print to monitor from richstack (decimal stack) in textmode (( (V )) Print to monitor from variable stack in textmode )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) ) (( )) )) Part of the (( .. )) idea of grouping statements for readability ---> (( (( )) note1:::: This has a semantic organising function rather than a strictly computational function, an aid in suggesting ideas, and an analogous function to punctuation marks of various kinds in written normal english language. **************************************************************************** * (( * )) Multiply with attention to decimals but using main stack (( *R )) Multiply at the decimal (rich) stack ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + general comment:::: Since numbers can be preceeded with a plus sign, like +3 or +3.14, it is usually nonsuitable to name a function anything which begins with + or - however the single signs + and - do have definitions which in some cases might be useful (though prefer the RICHSTK for decimal operations if these have to be decimal as a rule of thumb, see comment at (( - )).) (( + )) Addition of possibly decimal numbers on the main stack. ---> (( - )) for some important comments and further ---> connections. ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, , general comment:::: The idea of the comma is that when you want to specify a free-floating amount of input parameters, you can quote both numbers and blankless words/phrases by postfixing with a comma, instead of prefixing with a colon, like john, 3.14, 12, , , new, What you then want is to know how many commas has been typed. The amount of commas you will get with the function (( LISTOK )) and the amount of commas counted will be reset to zero when you call the function (( MAKENEWLIST )). In the Lisa GJ editions and onwards, [ and ] are defined to be synonyms with MAKENEWLIST and LISTOK. How to use this depends on what you like, quite simply. These are made for generating lists and matrixes and such at compile-time (ie, outside of functions). You can interchange with the ordinary form of quoting, that is, the colon and the curly brackets form, as well as numbers entered without comma, in which case the comma counter won't be increased. It is possible to enter [ 3.14, }Warm welcome!}, 17, 20000, ] but beware that this is parsed exactly as [ 3.14, }Warm welcome!} , 17, 20000, ] which is to say, there will be an empty (null-length) string after the Warm welcome! quote. If you like, you can develop a syntax, as it were, for entering a variety of types of items by utilizing the notion that an empty string follows a quote which is possibly long. Then you can make a routine to easily parse [ }John R. Smidth}, }12 First Hampton Road}, }}, }0417}, }Oslo}, }This is our main and best-paying customer, please}, }make sure that he receives priority one treatment}, }whenever he calls on us.}, }See our VIP phone list for further info} ] => CUSTOMER-DB Note that given a certain way to write the database input which is standardized, one has no need to have the accurate amount of commas. The CUSTOMER-DB can figure this out if the input scheme is fairly, approximately, the same for one or two or some types. A .TXT file can in this way be a highly well-organized database, which is read in as a program! [[[Note: this functionality has just about never been used at the moment of writing, in any real big Lisa GJ2 FIC3 program that I know about -- so check whether there aren't other ways of doing it than using this if you are unsure that you need just this functionality, to avoid running into issues.]]] ---------------------------------------------------------------------------- - general comment:::: Since numbers can be preceeded with a minus sign, like -2 or -2.86, it is usually nonsuitable to name a function anything which begins with -. However, there is a single function, -, with the following description: (( - )) Substracts, using the main stack, a possibly decimal number in: number1 number2 produces: number3 ---> + ---> * ---> \ ---> ADD ---> RICHSTK (and the ---> $ section for how to put numbers to that stack) note1:::: For whole numbers prefer SUB, which also is faster. For decimal numbers usually prefer the rich stack, with such a routine as SUBR (not +R) or ADDR (not -R). note2:::: The amount of decimals are not all that great; the emphasis on Lisa, except for obvious trigonometric numbers, is (as a shared characteristic with Forth) to try and do things by whole numbers when that is possible, e.g. using 0--3599 instead of 0.0--359.9 as a way of storing a degree in a ((DATA variable. This turns out to give the program a stronger algorithmic / binary / digital feel and is often easier than what it might seem at first sight, and leads to a consistent approach. note3:::: Beware that the RICHSTK has a functionality in actually treating the results of decimal number operations which is more worked through; for some results of decimal operations, the result, while present as a string on the main stack, may have features, such as an exponential letters, which is not normally parsed when a number is fetched from the main stack even by decimal routines. In other words, check the range for the use of decimal numbers on the main stack clearly. ............................................................................ . general comment:::: Since numbers can be preceeded with a dot sign, like .55 or .00032, it is usually nonsuitable to name a function anything which begins with a dot. However, it is a convention in Lisa to write numbers of the decimal kind so that they begin with a digit, so prefer the style 0.55 or 0.00032 to the just mentioned style, normally. Numbers written like this goes to main stack, and can be treated e.g. with ---> CONCAT. It may be advisable to put decimal numbers straight to RICHSTK by typing a ---> $ in front of them, like $0.55 or $0.00032, depending on what functions are to be used next (the 'rich stack' has trigonometric arithmetic). If used with care, ---> + and ---> - can do some decimal arithmetic on the main stack, along with ---> * and ---> \. //////////////////////////////////////////////////////////////////////////// / general comment:::: No extant functions in Lisa formalism begins with the slash (and for division please see such as DIV and the backslash \ which, as sign, more properly represent the reduction of value rather than the upward-pointing slash). However, synonyms which are used at a more Firth-near level, such as, for (COUNT, the function //F, use these. It is a convention in Lisa to stay to alphanumeric uppercase and dashes unless there are very good reasons to divert from this; there is nothing in principle against using the slash to define your own words however. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: : general comment:::: A word preceeded with a colon is treated as if it is quoted in the Lisa formalism. The advantage of this notation, like :THIS, is that a single word, or a single letter, does not need to be un-quoted since the space or the lineshift will indicate how long the quote is. For instance, when a program is started, one may write :PROGRAM IN which is basically equivalent to writing }PROGRAM} IN (the other way of quoting). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; (( ; )) Like (( )), this has only a role in increasing readability <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< < (( <>> )) Get the value of a variable, whose warp is at the variable stack in: ^number produces: number ---> < ((DATA ..)) ---> VARSTR> ---> >VARSTR ---> INCVAR ---> VISDANCE ---> VISBASIS ---> SETDANCE ---> SETBASIS (flag operations) ---> ((DATA ---> VARSTK ---> VARSTRING ---> PEEK ---> POKE ---> >MEM ---> MEM> note1:::: BE INTENSELY AWARE OF A POSSIBLE INCREDIBLY COMPLEX STRANGE BEHAVIOUR OF A PROGRAM TO CORRECT -- NAMELY, THAT MYSTERIOUS ITEMS SUDDENLY APPEAR ON THE MAIN STACK, OR THE LIKE, AS A RESULT OF THE USE OF >>> OR ITS SYNONYMS WITHOUT ANYTHING CORRECT BEING ON THE VARSTACK. MAKE SURE YOU UNAMBIGIOUSLY DEFINE ((DATA .. )) NAMES COMPLETELY DIFFERENT THAN ALGORITHM NAMES WHICH HAVE NOTHING TO DO WITH ((DATA .. )) AND, AS SUCH, SHOULD NOT BE CALLED WITH THE >>> AFTER THEM. RATHER STAY TO CONCRETE NUMBERS THAN OVER-DO THE AMOUNT OF ((DATA .. )) IN A PROGRAM. After all, the compiled text is available, as text, as readable text, and there is an advantage in seeing the concrete numbers, listening to them, and allowing those who must to change the text directly. The advantage of not checking whether it is appropriate to call >>> is that the programmer gets much more control over the computer environment in being called on to have responsibility to check this himself/ herself. Also, the computer works fast. note2:::: If you have the name of a variable as a text, perhaps input via the comma ---> (( , )) operator, then, at least during startup of a program (in which some initialisation duration may be quite okay), you can fetch the value of the variable by thinking of the variable rather as a little program, and apply the (( ; => ? => H => >>> => ; )) approach. The question-mark fetches the warp for the variable based on its name, H warps or hyperconnects to that little program, resulting in proper state of the variable stack to allow the value of the variable to be fetched and retrieved to the main stack. (( = )) These synonyms to (MATCHED .. )(OTHER .. MATCHED) work to create (( == )) a conditional statement. The = .. == .. === takes a flag as input. (( === )) The first .. is performed if it's 'y', the second if it is 'n'. ---> (MATCHED .. )(OTHER .. MATCHED) ---> LOOKSTK (read note here) note1:::: Very abrupt exits of programs can occur if one tries to perform an algorithm with improper control structures like these. Look at them carefully! note2:::: In some highly interactive large functions with many (MATCHED .. )(OTHER .. MATCHED) the use of the synonyms = .. == .. === may greatly improve the overview over the code. note3:::: You can have many dozens of these when e.g. looking at input from keyboard. Just count that the amount of completing === fits the amount of starting = inside each part of the function. note4:::: The compilation of = == === and (MATCHED .. )(OTHER .. MATCHED) is pretty complex and if there is extra )(OTHERs or ==s or things like that the function may not even compile without causing some abrupt exit of the compiler. Don't panick. Fix it. Just get the structure right. note5:::: Alternative ways of writing >>> is =-> and IS. (( => )) As (( )) and semicolon (;), this helps readability only. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> > general comment:::: In the LISA formalism, each unit of something or other is basically, unless quoted, separated by those before and those after (whenever there are any before and/or after) by at least one blank, possibly a lineshift. That means that something like ((DATA is one unit or word or body in the language, while something like (( VARSTRING are two such units (because of the blank). This also means that any word like >N1 is not at all anything like > N1 but rather a unit, the unit >N1, which has a particular meaning. The => is an entirely different unit, although it has a character in common. So is >>> an entirely different unit -- and so on. This very easy, clear-cut way of doing things allows for a clear thinking about the programming language and its syntax and what it does, and a predictable -- as well as speedy -- compilation. (( >>V )) Another way (than &) of moving from main stack to varstack ---> & (an alternative form) ---> V>> (see comment) (( >MEM )) This puts a new value into RAM if this part of RAM is acquired. (( >N1 )) Inside a function, >N1 .. >N11 are the main, typical ways of (( >N2 )) putting a whole number into the eleven slots which are, (( >N3 )) unique to the Lisa language (as also the main stack technicality), (( >N4 )) automatically allocated on top of the simple number stack, (( >N5 )) for use of what we can call a 'short-term' memory for the (( >N6 )) function. These storage locations have neutral names, N1..N11, (( >N7 )) so that it is normally very easy to see what indeed are the (( >N8 )) actions in the function, and what is merely a storage room. (( >N9 )) If however used outside of a function, they will automatically (( >N10 )) allot extra slots in simple stack if the stack is not already (( >N11 )) initialized with that many. (( >VARSTR )) Put this line/word/number/letter into the VARSTRING variable ???????????????????????????????????????????????????????????????????????????? ? (( ? )) Important function! It finds the warp of any function whatsoever. ---> %MAKE (important comment on warps between the versions) ---> FORVPM2 ---> FORVPM ---> H ---> HYPERCONNECT (synonym w/H) ---> >MEM ---> MEM> ---> PEEK ---> POKE ---> INC4 ---> INC8 ---> INC12 .. INC48 (for speedy motion of the pointer to a suitable point inside the procedure) ---> SETWARPADDRESS ---> GETFUNCNUM note1:::: This is looping through the name-list, and if there is any chance of the result of this being used in a loop, where computional efficiency might be important, it is best to call on ? once, at first, perhaps during compilation of program or during its startup, and store the value in a variable. Such variables are sometimes called XXXX-HOUSE, where XXXX is replaced with the name of that which the search was for. When a function is defined so as to be at once put into a house, it is a convention in Lisa often to define it with the suffix -ESSENCE, in order to make room for other definitions utilizing perhaps the same initial name in some way. The FIC3.TXT has several examples of this praxis, which emerged after Firth was completed from my hand, when I worked out all that which came to be called the Lisa programming language. This is however a convention and one may perfectly well also apply other types of naming conventions, including, for a variable containing a warp, something like XXXX-WARP. note2:::: If there are several definitions of a function, and it is not a primary (Firth) function, the most recent definition will be picked. note3:::: Since the looping through the namelist happen through the most recent words first, with the first letters in the name matched on first, it is possible to tune the making of new functions so as to faciliate the use of ? when jumping between these (something which is typically used e.g. in erotic game programs, when the interactor wit the game indicates that a particular game situation is completed -- in which case it is reasonable to use the ? because of the natural duration which is allowable when the progression from one function / node to the next function / node is correlated to interactor keyboard input rather than repeated millions of times inside a loop outside of keyboard interactions). @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA A (( A )) If number is positive, give also 'y'; if not, remove number, give 'n' (( AT )) When typed in directly at compiler (or at Lisacode), it renews, rejuvenates. The Lisa-time-schedule is 2006 => 2026, from April 10th, 10.00am, after which a new cycle begins -- instead of linear time (( ABS )) Remove any sign of any (whole) number ---> ISPRO ---> SG ---> A ---> NOZ ---> ABSR ---> ABSV ---> ABSS (( ABSR )) Remove sign (ie, 'absolute value') of number at richstack (( ABSS )) Remove sign of top number at simplestack (( ABSV )) Remove sign of top number at varstack (( ADD )) The main whole number addition (( ADD4 )) Increase the whole number value by four (( ADDITIONAL-IN-LIST )) Are there more in the list, beyond present position? ---> LIST (which has a lot more ---> connections for lists) (( ADDR )) Add using the decimal number stack, using decimal addition (( ADDS )) Add on the simple stack (( ADDV )) Add on the variable stack (( ADDVAR-WITHIN )) Add value to the variable if result within given range (( AFFIRM )) Leave number and give 'y' flag if positive; otherwise just 'n' ---> TEST ---> TEQ ---> NOZ ---> ISPRO ---> ISBASIS ---> VISDANCE (( ALIGNR )) Align to the right at the main stack (( AMOUNT-IN-LIST )) Tell amount in a list ---> LIST (which has a lot more ---> connections for lists) (( AND )) The main boolean AND function, takes two flags, gives one flag (( ANGEL )) Be a sweet angel and get the third item on stack moved up to top (( ANGELR )) As ANGEL, but richstk (( ANGELS )) As ANGEL, but simplestk (( ANGELV )) As ANGEL, but varstk (( ARRAY>STR )) Converse of STR>ARRAY, makes a stack string based on array (( ARCCOS )) The converse of cosinus note1:::: See comment at ---> SIN as for decimals on main stack (( ARCCOSR )) The converse of cosinus at the proper decimal stack (( ARCSIN )) The converse of sinus note1:::: See comment at ---> SIN as for decimals on main stack (( ARCSINR )) The converse of sinus at the richstk (( ARCTAN )) The converse of tangens note1:::: See comment at ---> SIN as for decimals on main stack (( ARCTANR )) The converse of tangens at richstk (( ASCII )) Make the character which corresponds to this ascii7 number ---> GETASCII note1:::: See table right before the first entry in this dictionary which gives the 7-bit ascii values note2:::: The 'nn' is a syntax which can also be used inside functions in which nn is replaced with the ascii number, e.g. '64' for @ and '65' for A, to quickly enter ascii numbers, including control chars such as '8' for backspace. An example of a sequence which prints the backspace after printing a char (this you can expand into a READLN-alike if you make it handle backspace as well): (LET MY-UNUSAL-READLN BE (( )) (( (( SOLIDCURSOR )) (( }} ; )) (( GOLABEL4: )) (( '64' => ( ; '8' => ( )) (( KEYNUM => >N1 )) (( N1 ; KEY-ENTER >>> => EQN (MATCHED ; => => EXIT MATCHED) )) (( N1 => ASCII => ( )) (( ; N1 => ASCII => CONCAT )) (( GOUP4 )) )) OK) It will enable a blinking cursor atop a @ sign while you type in. I don't mind saying that the world of Lisa programming always welcomes fresh-feeling unusual style editors, esp. in a more Lisa-oriented new GJ PC world. ('GJ' referring to the new trademark of Yoga4d:VRGM in which we standardize around the Lisa formalism with more and more hardware.) (( AT-LEAST-NUMBER-1-IN-LIST )) If empty list, add the number 1 to it ---> LIST (which has a lot more ---> connections for lists) BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB B (( BE )) This is part of the convention (LET my-new-word BE (( )) .. OK) (( BEYOND-LIST )) Put pointer beyond the present values in the list ---> LIST (which has a lot more ---> connections for lists) (( BRIDGE )) Creates an extra copy of the next to topmost item (( BRIDGES )) (( BRIDGER )) (( BRIDGEV )) in: item1 item2 produces: item1 item2 item1 ---> ANGEL ---> TANTRA ---> YANTRA ---> MANTRA ---> DHYANA ---> PURUSHA ---> NIRVANA ---> ONE ---> TWO ---> THREE ---> FOUR ---> FIVE ---> SIX ---> SELECT ---> REMOVE ---> RM ---> ANGELS ---> TANTRAS ---> YANTRAS ---> MANTRAS ---> DHYANAS ---> PURUSHAS ---> NIRVANAS ---> ONES ---> TWOS ---> THREES ---> FOURS ---> FIVES ---> SIXS ---> SELECTS ---> REMOVES ---> RMS ---> ANGELR ---> TANTRAR ---> YANTRAR ---> MANTRAR ---> DHYANAR ---> PURUSHAR ---> NIRVANAR ---> ONER ---> TWOR ---> THREER ---> FOURR ---> FIVER ---> SIXR ---> SELECTR ---> REMOVER ---> RMR ---> ANGELV ---> TANTRAV ---> YANTRAV ---> MANTRAV ---> DHYANAV ---> PURUSHAV ---> NIRVANAV ---> ONEV ---> TWOV ---> THREEV ---> FOURV ---> FIVEV ---> SIXV ---> SELECTV ---> REMOVEV ---> RMV note1:::: Please check functionality when calling on any one of these which has not been extensively used e.g. in FIC3.TXT. It should in each case in which there is an issue with a word be easy to find a substitute sequence of calls. This esp. so with those which do not operate on the main stack. It should be comparatively easy, using such as ---> STK ---> RICHSTK ---> VARSTK and ---> SIMPLESTK to discover whether any word does something other than claimed, perhaps operating on several stacks in a confused manner, if you put a sufficent amount of items on every stack in the interactive mode of the compiler and, after each operation, check all results; repeating with a different set of items, rather in the sense of generating instances of confirmation and disconfirmation, in which, for one word, only one disconfirmation instance of a clear-cut, repeatable kind is enough for a work-around to have to be created. note2:::: Of course there are still more ways to change the stacks, and many more to move between the stacks, including such as ---> >N1 ---> N1 ---> >>V ---> V>> ---> V1 ---> >V1 ---> # ---> & etc. note3:::: Whereas the ONE, TWO, THREE etc in general replicates several items, keeping the original sequence intact, and ANGEL changes the sequence of the uppermost three, those with a sanskrit-like name work rather like BRIDGE, in copying one element from deeper in the stack, but all deeper than BRIDGE (akin to Patanjali's notes on meditation etc). CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC C (( B9-POP )) Given text, x coordinate, y coordinate, print to display in B9 (( CRLN )) Produce a lineshift in the textmode (carriage return/new line) (( CIRCLE )) Make a circle on the screen in graphics mode (GJ-ON .. GJ-DONE) (( CIRCLEFILL )) Same as CIRCLE above, but fill it up with the color (( CH )) Get this individual character out of the text/number (( CHN )) Same as CH, but get it in terms of its ascii value (( CLEAR-MATRIX )) Important! To make a used matrix fresh again ---> FORVPM2 ---> FORVPM ---> RAM-PM ---> PM ---> GM ---> FILE2PM ---> PM2FILE ---> FILENUM2PM ---> PM2FILENUM ---> RELEASE-MATRIX note1:::: This is superbly fast because it clears only and all that which is nonzero, setting it to zero, throughout a matrix, without fail; and so this is what is done when RELEASE-MATRIX followed by a new RAM-PM seems either inconvenient somehow, or because such a RAM-PM would take too much time as can be the case where we're talking of e.g. a text document matrix with tens of thousands of lines on a typical computer. (( CLEAR_KEYBUF )) Clear the keyboard buffer in an elementary way note1:::: The computer world has one challenge which always involves a little bit experimentation and which simple-minded rule-based perfectionism is not going to be enough, because something transcend those rules: and that is interaction with hardware elements in which duration plays a role. Duration means that we need a togetherness of events, or a proper sequence of things which, due to the internal tick of the CPU of the computer, may seem to be rather simultaneous. Such things means that you will always find territories where one has to feel one's way into it, and where there are heuristics more than strict recipies. So please make room for this also when it comes to the not unimportant issue of clearing the keyboard buffer, so that one is able to have a control over such things as how many repetitions are indeed stored in the computer when a button is hold down -- so that things don't overloop, or run out of line width, or the like. In the text mode, there is no use of FKEYNUM but rather: a single event of a function key pressed leads to, first, a zero, then another character. This second character is nonzero. They are considered a unit. They should be read as a unit. The use of the native Firth function CLEAR_KEYBUF will not clear a half-read such unit. This, however, will. Something similar can surely be worked out if there are different interaction protocols and e.g. a similar (but not the same) issue in graphical modes: In the text mode (at least) it may happen that the use of a repeat-action on a function key, which is such that the ---> KEYNUM would produce a zero, will have a residue which turns up on ---> KEYTOUCH but is not cleared with CLEAR_KEYBUF. Test this and here is a solution which works to clear it up -- this is a word which is defined inside the GJ2 FIC3 edition of Lisa, and it is ideal not after ordinary input of text -- because it may slow it down -- but it is ideal after input of a function-key, in case the interactor inadvertedly presses it too many times: LET MANUAL-CLEAR-KEYBUF BE (( )) (( (( GOLABEL4: )) (( KEYTOUCH (MATCHED (( KEYNUM => ISBASIS (MATCHED (( KEYNUM ; RM )) MATCHED) )) (( GOUP4 )) MATCHED) )) )) OK) (( CLS )) Clear screen in an elementary way note1:::: Amazingly, the clear-screen CLS works superbly both in text mode and in most configurations of the palette in the graphics mode. It may be an idea, though, in graphical mode, to re-assert the presence or the invisibility of the pointer, by subsequent use of ---> FT or ---> FEET, see also ---> FT-CLS. See also ---> RECTFILL which quickly can do this in other ways. In text mode, ---> TEXTCOLORBG and ---> TEXTCOLOR before CLS. (( COMPILEFAST )) Normal quick compilation mode (not COMPILEPAUSED..) ---> VISIBLECOMPILATION ---> INVISIBLECOMPILATION ---> COMPILEPAUSED --> COMPILEPAUSEDALITTLE ---> COMPILEPAUSEDATINYBIT (( COMPILEPAUSED )) Very slow compilation, combine with VISIBLECOMPILATION note1:::: If you are compiling a program and something strange happens, leading the computer screen to come up with nothing meaningful at a point in the compilation, perhaps, which the computer doesn't even inform about, then pick a spot where you think it is okay and put in COMPILEPAUSED and VISIBLECOMPILATION outside any function, and watch it next time you compile. note2:::: If you get the issue during startup of program, do the obvious thing: put a comment, perhaps of the **** .. { kind, or the }* .. }* kind (the latter only for one line at a time, whereas the four asterix can do as many lines as you please as long as they don't have that { sign in them before they complete the comment), and see if you can find, to a greater and greater precision, the exact line. Then fix it! ---> VISIBLECOMPILATION ---> INVISIBLECOMPILATION ---> COMPILEFAST --> COMPILEPAUSEDALITTLE ---> COMPILEPAUSEDATINYBIT (( COMPILEPAUSEDALITTLE )) A bit quicker than COMPILEPAUSED ---> VISIBLECOMPILATION ---> INVISIBLECOMPILATION ---> COMPILEFAST --> COMPILEPAUSED ---> COMPILEPAUSEDATINYBIT (( COMPILEPAUSEDATINYBIT )) Quicker than COMPILEPAUSED ---> VISIBLECOMPILATION ---> INVISIBLECOMPILATION ---> COMPILEFAST --> COMPILEPAUSEDALITTLE ---> COMPILEPAUSED (( CONCAT )) Make a beautiful union of two separate items on stack (( CONVERSE-THROUGH-LIST )) Through the list, but start with completing item. ---> LIST (which has a lot more ---> connections for lists) (( COPYNUMS )) Move quickly and internally a bunch of numbers to elsewhere ---> COPYNUMSHIGH note1:::: Use COPYNUMS esp. within huge arrays where (COUNT .. COUNTUP) is not quite the thing. If it is a long (perhaps enormously long) row inside a matrix, this row is of course an array, and, if you ---> %GET the array (instead of merely getting its numbers with ---> GM), then you can also relate directly to its warp addresses and use this. note2:::: For matrices, either use, when appropriate, something like ---> FORVPM2, but you can also make tremendously efficient (speaking in terms of computational duration) functions by appreciating the fact that a matrix is really an array of warps to arrays -- and these warps to arrays can be freely moved about! That is to say, each row in a matrix can be moved to a different place in the matrix by simply moving a number from position A to position B. That is a matter of using ---> %PUT and ---> %GET and some temporary storage and such. note3:::: Building on the insight in note2, you can in fact use COPYNUMS and COPYNUMSHIGH on a matrix after all, if you do it row-wise, and calculate the beginning warp by doing ---> MUL4 with the row number start, and also with the row amount, and the new row number. note4:::: Whether to use COPYNUMS or COPYNUMSHIGH is a matter of whether or not the area copied to and the area copied from overlap. If they don't, as a rule of thumb then use COPYNUMS. If they do overlap, then you must find out which of them work -- it is a question of sequence. COPYNUMSHIGH begins at the highest position. Here is an example of overlapping positions: AAAAAAAAAABBBBBBBBCCCCCCCCCCDDDDDDDDD Suppose half of this is to be copied ten to the right to give room for new creative stuff in between. We want something like this as a result: AAAAAAAAAABBBBBBBBCCCCCCCCCCCCCCCCCCCCDDDDDDDDD Obviously, if we propell the C's in the middle to the right, they will overrun the D's. But if we begin with getting the D's on the right still further right, and progress towards the C's, we'll get it. In going the other way, from the second string to the first, it matters that we begin on the C's and then proceed to the D's, it seems. That's why it is important that both COPYNUMS and COPYNUMSHIGH exist. (( COPYNUMSHIGH )) As COPYNUMS, but start with the highest addresses ---> COPYNUMS (see plenty notes here) (( COS )) Cosine function on main stack ---> ISEQUAL ---> NOT_ISEQUAL note1:::: See comment at ---> SIN as for decimals on main stack (( COSR )) Normal cosine function using decimal stack ---> SINR ---> TANR ---> ARCCOSR ---> COS (( COUNTUP) )) Completing the important (COUNT .. COUNTUP) counting loop. ---> (COUNT ---> N1 ---> N2 (( CTRL-P )) These are some variables for some much-used function keys, (( CTRL-O )) in sequence (PONQUERIF) which they may be easy to reach, (( CTRL-N )) and avoiding those which go near that which might have (( CTRL-Q )) an associated function (except the CTRL-I, indent, keytab ->l)) (( CTRL-E )) (( CTRL-R )) (( CTRL-I )) (( CTRL-F )) ---> FUNC-KEY-F1 (which has a lot more of ---> connections) DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD D (( DEC )) A quick way on the main stack to reduce a whole number by one (( DEC4 )) Reduce a number by four (on the main stack, treat as whole number) (( DEC4R )) On the rich stack, as DEC4 (( DEC4S )) On the simple stack, as DEC4 in: produces: comment on in:::: comment on produces:::: (( DECN1 )) A quick way to reduce N1..N11 by one. (( DECN2 )) (( DECN3 )) (( DECN4 )) (( DECN5 )) (( DECN6 )) (( DECN7 )) (( DECN8 )) (( DECN9 )) (( DECN10 )) (( DECN11 )) (( DECV1 )) A quick way to reduce the number on variable stack by 1. (( DECV2 )) (( DECV3 )) (( DECV4 )) (( DECV5 )) (( DECV6 )) (( DECV7 )) (( DECV8 )) (( DECV9 )) (( DECV10 )) (( DECV11 )) ---> INCV1 .. INCV11 (( DECS )) Reducing a number on simplestack by one. (( DECR )) Reducing a decimal number at richstack by one. (( DHYANA )) Create a copy of the 5th item under the topmost and put on top (( DHYANAR )) As DHYANA, but richstk (( DHYANAS )) As DHYANA, but simplestack (( DHYANAV )) As DHYANA, but varstack in: it1 it2 it3 it4 it5 it6 produces: it1 it2 it3 it4 it5 it6 it1 comment on in:::: DHYANA works on the main stack, for item 1, item 2 etc, while DHYANAR on the RICHSTK, DHYANAS on the SIMPLESTK, DHYANAV on VARSTK. comment on produces:::: Count five items under the topmost item and that's the number that is copied -- it is produced on the same stack as it is copied from (e.g., DHYANA copies from the main stack, to the main stack). ---> BRIDGE (this has many more ---> connections) (( DIV )) Whole number standard division of one number by another in: number1 number2 produces: number3 comment on produces:::: the result of dividing number1 by number2 (( DIV2 )) Quick cut in half (( DIV4 )) Quick cut in four (( DIV8 )) Divide by 8 (( DIV16 )) Divide by 16 ( DIVS )) Division at simple stack (( DOTTED_RECT )) A quick way to produce a stipled line and/or rectangle note1:::: You can use this instead of a series of calls to ---> PUTPIXEL to very efficiently sketch a dotted line, not just a dotted rectangle, by suitable adjustment of the x1, y1, x2, y2 and the two colors. EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE E (( EMPTY-LIST )) Make a list defined by LIST empty of values again. ---> LIST (which has a lot more ---> connections for lists) (( ENTERPLS )) In text mode, produce Press ENTER, pls, and wait for enter. ---> YNIN ---> KEY ---> KEYNUM ---> KEY-ENTER ---> READLN ---> RM (( EQ )) Compare two texts apart from blanks and apart from upper/lower-case ---> EQSTART ---> TXTEQUAL (must be precise, unlike EQ) ---> TEQ (( EQN )) Compare two numbers in the whole number sense, on main stack (( EQSTART )) Compare beginning of two texts (or numbers) on main stack ---> EQ ---> TXTEQUAL (( EXIT )) Immediate exit from presently performing function to calling func note1:::: When I implemented the EXIT in Firth I did not dare hoping for something which would be even nearly as errorless and useful as EXIT indeed turned out to be -- in which one can EXIT from virtually any point inside any function, generally inside a (MATCHED .. MATCHED) or = .. === (and there may be many such), as long as one treats the stacks right -- RMS RMS is the usual thing to do if inside a (COUNT loop. You might say that the word EXIT mimicks what happens when the function comes near its completing line and the OK). If there is a natural closure of a function by means of several lines which need to be done one can also do something like GOFORWARD4 with a GOLABEL4: in front of that latter part. But in order to minimize the amount of criss-crossing GOUPs and GOLABELs there is a condition that for each GOLABEL there is going to be but one GOUP or GOLABEL statement (either one or the other, exclusive or). So EXIT is a freer way which one can have multiple of. (( EXP )) Exponential using the main stack (but prefer rich stack) note1:::: Use ---> EXPR or check very carefully when doing decimal operations on main stack, because the result may contain the E-notion and this result is not suitable input number except when already on the richstack. The main stack is standardized towards whole numbers of the 32-bit kind. (( EXPR )) Find exponential using rich stack ---> EXP (( EXTEND-LIST )) Extend a list defined by LIST with a new number ---> LIST (which has a lot more ---> connections for lists) (( EXTEND-LIST-IF-WITH )) As EXTEND-LIST, but on condition number is right ---> LIST (which has a lot more ---> connections for lists) (( EXTRACTLETTERS )) Filter nonletters away from the text on the main stack (( EXTRACTNUMBER )) Filter nondigits away from the text on the main stack ---> EXTRACTNUMBERSTUFF ---> EXTRACTLETTERS ---> RICH ---> HEAL ---> FIX-NUMBER ---> RMBL (( EXTRACTNUMBERSTUFF )) Filter that which is certainly not a number away ---> RICH (synonym, and well explained; exactly identical) FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF F (( F2Y )) Replace positive number with y, replace 0 or neg. number with n (( FACT )) Replace positive number with 1, replace 0 or neg. number with -1 (( FEET )) Put on pointer device symbol on screen (remove it before PUTPIXEL) (( FILE2PM )) Given a .TXT file in directory, fill up a matrix with values ---> CLEAR-MATRIX (because the PM should be clear before putting anything onto it) ---> PM2FILE (which contains a very important note relative to uses of columns; in general, make sure that the rows are always at least two characters wider than that which is actually used, whether as file written to or file read!) ---> FILENUM2PM (when it is other than 32..126 ascii characters, such as a sketch made in LAB) ---> PM2FILENUM ---> FORVPM2 (( FILENUM2PM )) Given a .TXT file produced with PM2FILENUM, retrieve it note1:::: FILENUM2PM and PM2FILENUM for matrices created by exactly (( 200 ; 200 => RAM-PM )) and which have exactly 0..255 as number values are infinitely faster treated with --> GJPFILE2PM and PM2GJPFILE binary form. (( FILLNUMS )) Fill up a sequence in RAM (inside an array) with a value note1:::: It is quite possible to fill an array which is made by ---> %MAKE by figuring out the beginning of it, using the warp rather as in ---> PEEK -- jumping over the initial length number, and the like. However if a matrix of many rows and columns is what you've got (e.g. initiated by ---> RAM-PM), then only one segment of it, which is seamless, unbroken, a whole -- like a single row -- can have FILLNUMS applied to it. However, if you have got to have it in the matrix form e.g. because you want it to work with ---> PM2FILENUM then have the whole lot of information as one giant row -- nothing wrong with that at all. (( FITTING )) A simple way to search in a sorted index over values ---> QSORT2 for example (( FIVE )) Copy the topmost five on main stack and make five more (( FIVER )) Copy five topmost on rich stack and put them there (( FIVES )) Copy five topmost on simple stack and put them there (( FIVEV )) Copy five topmost on varstack and put them there (( FIX-NUMBER )) Make a number look budget-smart, on main stack (( FKEYNUM )) Only for graphical mode! Extra info in addition to KEYNUM ---> NEWKEY (with many more ---> connections there) (( FKEYCTRL )) Only for graphical mode! Extra info in addition to KEYNUM (( FKEYSHIFT )) Only for graphical mode! Extra info in addition to KEYNUM (( FKEYALT )) Only for graphical mode! Extra info in addition to KEYNUM ---> NEWKEY (with many more ---> connections there) (( FOUR )) Produce a copy of topmost four members to top (at mainstack) (( FOURR )) Produce a copy of topmost four members to top (at richstk) (( FOURS )) Produce a copy of topmost four members to top (at simplestk) (( FOURV )) Produce a copy of topmost four members to top (at varstk) (( FREE-CLS )) Clear screen to natural preferred color GJ style in textmode ---> RAM-REFRESH note1:::: This is for text-mode, a good way to start a text mode program. For graphical programs, use ---> GJ-ON instead. To complete the text mode program, use ---> RAM-REFRESH. (( FORVPM )) Go quickly through all nonzero values of the whole matrix ---> FORVPM2 (full info) (( FORVPM2 )) Go quickly through all nonzero values in a range of the matrix ---> FORVPM ---> FILENUM2PM ---> FILE2PM ---> PM2FILENUM ---> PM2FILE note1:::: This pearl of a function allows a matrix to be traversed with immense speed and flexibility. It calls on the best of warp functionality. It utilizes the principle that the zeroes of the matrix can be ignored, and a program which intends to use this functions, or its sibling FORVPM, should construct the matrix on this basis. note2:::: Hope you forgive a complicated example, but it illustrates various points. See comment after it: (LET B9-POP-CHN-ESSENCE BE (( )) (( (( B9-FONT-X >>> ; V2 50 MOD => ADD ; B9-FONT-Y >>> ; V2 50 DIV => ADD ; B9-FONT-CURRENT-COLOR >>> => PUTPIXEL )) )) OK) (( }B9-POP-CHN-ESSENCE} => ? B9-POP-CHN-HOUSE <N1 )) (( (( N1 ; 5 => EQN (MATCHED (( B9-FONT-X >>> 14 ADD ; B9-FONT-Y >>> 6 ADD ; BRIDGE B9-FONT-WIDTH >>> => ADD 21 ADD ; BRIDGE B9-FONT-HEIGHT >>> => ADD INC8 ; B9-POP-BG >>> => RECTFILL )) )(OTHER (( VLOTS )) (( 1 => TOV2 )) (( N1 => TOV3 )) (( N1 => TOV4 )) (( VFREE )) (( B9-POP-CHN-HOUSE >>> ; THEFONT >>> => FORVPM2 )) MATCHED) )) (( B9-FONT-WIDTH >>> ; B9-FONT-X => ADDVAR )) )) OK) note3:::: The convention is to name a function with the -ESSENCE suffix when it is made so as to be used by something like FORVPM, and then a same-named variable with -HOUSE instead of -ESSENCE will keep the function warp. Note that the line (( }B9-POP-CHN-ESSENCE} => ? B9-POP-CHN-HOUSE < TOV2 )) (( N1 => TOV3 )) (( N1 => TOV4 )) (( VFREE )) (( B9-POP-CHN-HOUSE >>> ; THEFONT >>> => FORVPM2 )) You see that the -HOUSE and the matrix itself, in this case, THEFONT, are the two inputs to FORVPM2, in the obvious, normal sense. But the very swift loop uses the variable stack in an unusual way, rather as a simple stack, and to get values into it prior to FORVPM2 is a necessity (otherwise we must use FORVPM). The THEFONT matrix is so that it has one character as one row -- essentially, then, since each character is a matrix, it is a three-dimensional matrix. We want FORVPM2 only to print one character at a time. So prior to FORVPM2 one sees the (( VLOTS )) (( 1 => TOV2 )) (( N1 => TOV3 )) (( N1 => TOV4 )) (( VFREE )) type of thing. The 1 => TOV2 gives the signal to start on column 1. The N1 => TOV3 gives the signal to start on column N1. And, in fact, the N1 => TOV4 gives the signal to also complete on this column. Why not simply use (COUNT .. COUNTUP)? We could; but the advantage of FORVPM and FORVPM2 above an ordinary loop is that they call on the content of the loop only for nonzero values. That means that, for all practical purposes, zero values count as 'transparency'. When we want to fill up with good colors in exactly the right way and with minimum of fuss and maximum of speed and computational beauty and joy, then, take the time to construct a FORVPM or FORVPM2. The values, found in V11, may not be important when it is just a question, like here, of finding the nonzero ones (they are all 1 anyway in this case). Rather, what is interesting in this case is to find the column number, which is in V2. One of the beautiful things of FORVPM and FORVPM2 is that you can control the process entirely by putting values back into that which you read out of the loop essence. In that way, you can make it branch quickly. Look at this, which uses FORVPM, but with the flexibility typical of use of FORVPM2. The idea of the suffix -ESSENCE is that it is not the entire algorithm as much as an essential part of it; as a convention. (LET FIND-MAX-LINE-NUM-ESSENCE BE (( )) (( (( V3 FIND-MAX-LINE-NUM-DATA < TOV2 )) )) OK) (LET FIND-MAX-LINE-NUM BE (( & )) (( (( FIND-MAX-LINE-NUM-DATA => SETBASIS )) (( }FIND-MAX-LINE-NUM-ESSENCE} => ? ; # => FORVPM )) (( FIND-MAX-LINE-NUM-DATA >>> => => )) (( && )) )) OK) This use of FORVPM utilizes information stored in V5, viz., the length of the current row, to move the column counter to beyond the completion of the row by the (( V5 INC => TOV2 )) line. It updates with the current row number, the V3, to a variable -- and the function will be able to, in an enormously swift way, tell which is the highest row number in possibly a giant matrix which has any nonzero data at all on it, skipping the others. The next one could have been made by FORVPM, but for very large matrices, the input, to >N1, tells the highest row number to look at, thus saving time -- you can call on this, by the way, when you load dubvious text files -- F9 does this, I think (replacing strange characters with ascii 42, which is the * sign): ((DATA FILTER-NON7ASCII-CHARS-HOUSE )) (LET FILTER-NON7ASCII-CHARS-ESSENCE BE (( )) (( (( 32 ; V11 => INTGREATER (MATCHED (( 42 => TOV11 )) )(OTHER (( V11 ; 126 => INTGREATER (MATCHED (( 42 => TOV11 )) MATCHED) )) MATCHED) )) )) OK) (( }FILTER-NON7ASCII-CHARS-ESSENCE} => ? FILTER-NON7ASCII-CHARS-HOUSE <N1 )) (( (( VLOTS )) (( 1 => TOV2 )) (( 1 => TOV3 )) (( N1 => TOV4 )) (( VFREE )) (( FILTER-NON7ASCII-CHARS-HOUSE >>> ; # => FORVPM2 )) (( && )) )) OK) For those who feel that they have go way too little information on FORVPM and FORVPM2, they are hereby warned, they will get a lot more information than they bargained for. They will get it all. In toto. In the mysterious macro-based language I wrote the first Firth in, developing the concept of FORVPM and FORVPM2 as an enthusiastic afterthought which has turned out to be so central. Decode this and apply for a diploma: TRULYRICH SUPERLUCKforvpm YOUNG KISSED AFFIRM well YOUNG morenow > DANCING KISSED AFFIRM varstkptr IS varstkptr HIGHER 11; openfreepornforall22 IS strstk HIGHER 4*morenow YES V1 IS tolongint YOUNG WARP openfreepornforall22 KISSED YES free YOUNG WARP openfreepornforall22 KISSED YES morenow IS morenow - 1 YES openfreepornforall18 IS strstk HIGHER 4*morenow YES V6 IS tolongint YOUNG WARP openfreepornforall18 KISSED YES free YOUNG WARP openfreepornforall18 KISSED YES morenow IS morenow - 1 YES well ((V1 == BASIS) || (V6 == BASIS)) AFFIRM varstkptr IS varstkptr HIGHER -11 YES rejuvenate YES HEALING V4 IS *(int*)( V1 ) YES FLOWER ( V3 = 1; V3 <= V4 ; V3 ++) AFFIRM V5 IS *(int*)((int)((*(int*)( (int)( V1 + V3 * 4))))) YES FLOWER ( V2 = 1; V2 <= V5 ; V2 ++) AFFIRM tantra21 IS *(int*)((int)((*(int*)( (int)( V1 + V3 * 4))) + V2 * 4)) YES well (tantra21 ISNT BASIS) AFFIRM V11 IS tantra21 YES returnstackptr IS returnstackptr HIGHER DANCING YES returnstack[returnstackptr] IS performingaddress YES performingaddress IS V6 YES tantra14 IS prettylonglegged YOUNG APPRAISE prettylonglegged KISSED performingaddress YES boehmian_performer IS YOUNG TRULYRICH* KISSED tantra14 YES YOUNG *boehmian_performer KISSED YOUNG KISSED YES performingaddress IS performingaddress - 4 YES *(int*)((int)((*(int*)((int)(V1 + V3*4))) + V2*4)) IS V11 YES HEALING HEALING HEALING varstkptr IS varstkptr HIGHER -11 YES HEALING HEALING TRULYRICH SUPERLUCKforvpm2 YOUNG KISSED AFFIRM well YOUNG morenow > DANCING KISSED AFFIRM varstkptr IS varstkptr HIGHER 11; openfreepornforall22 IS strstk HIGHER 4*morenow YES V1 IS tolongint YOUNG WARP openfreepornforall22 KISSED YES free YOUNG WARP openfreepornforall22 KISSED YES morenow IS morenow - 1 YES openfreepornforall18 IS strstk HIGHER 4*morenow YES V6 IS tolongint YOUNG WARP openfreepornforall18 KISSED YES free YOUNG WARP openfreepornforall18 KISSED YES morenow IS morenow - 1 YES well ((V1 == BASIS) || (V6 == BASIS)) AFFIRM varstkptr IS varstkptr HIGHER -11 YES rejuvenate YES HEALING FLOWER (; V3 <= V4 ; V3 ++) AFFIRM V5 IS *(int*)((int)((*(int*)( (int)( V1 + V3 * 4))))) YES FLOWER ( V2 = 1; V2 <= V5 ; V2 ++) AFFIRM tantra21 IS *(int*)((int)((*(int*)( (int)( V1 + V3 * 4))) + V2 * 4)) YES well (tantra21 ISNT BASIS) AFFIRM V11 IS tantra21 YES returnstackptr IS returnstackptr HIGHER DANCING YES returnstack[returnstackptr] IS performingaddress YES performingaddress IS V6 YES tantra14 IS prettylonglegged YOUNG APPRAISE prettylonglegged KISSED performingaddress YES boehmian_performer IS YOUNG TRULYRICH* KISSED tantra14 YES YOUNG *boehmian_performer KISSED YOUNG KISSED YES performingaddress IS performingaddress - 4 YES *(int*)((int)((*(int*)((int)(V1 + V3*4))) + V2*4)) IS V11 YES HEALING HEALING HEALING varstkptr IS varstkptr HIGHER -11 YES HEALING HEALING Okay, the above, a kind of C-like code (indeed initially compiled with DJGPP before the GJ2 edition), is pretty complicated. However, if you focus on the parts which give meaning rather than those which don't, one of the things which come clearly forward is that some of the V1 .. V11 are not used. This means that they are free to be used for whatever you like for swift transfer to the inmost -ESSENCE of the loop. Say, you can use V7 or V8. And the following should be pretty clear, huh? FLOWER (; V3 <= V4 ; V3 ++) .. FLOWER ( V2 = 1; V2 <= V5 ; V2 ++) .. HEALING HEALING This means that V3 goes up to V4 (inclusive), and it is the row -- the outermost loop. Inside it, V2 goes from 1 and up to V5 which is initialized by means of this incredibly simple line ;) V5 IS *(int*)((int)((*(int*)( (int)( V1 + V3 * 4))))) YES which just simply means, V5 is the warp -- which is the V1, the matrix, the # value -- plus the V3, ie, the row number -- and what's there as value, in other words the length of the row. So V5 is the length of the row in each case. You also see another incredibly simple ;) (which surely could have been written simpler, but it works and is fast) line inside that loop, namely *(int*)((int)((*(int*)((int)(V1 + V3*4))) + V2*4)) IS V11 YES which is to say -- get the V11 back in place, in case it has been changed. Notice also that FORVPM and FORVPM2 simply do not use any local variables outside of the V1 .. V11, and these are indeed initialized with 11 slots during startup and freed at the completion of the loop. This means something. What does it mean? It means that you can loop several FORVPM2 inside another. Frankly, I haven't tried that yet at the moment of writing this, but I'd pay fifty thousand dollars to somebody who can prove that this cannot be done. Or make somebody eat their pink silken handmade hat. Alright, I apologize for all the complexity. You deserve still another example. I've fetched this from my F9 editor work, scanning for text, with/without the case-sensitive option on. Many lines repeat themselves but, as I say at the completion of this document, I prefer clarity over conciseness inside a program when there's a priority to be made. Let me assert something which is something one might have to handle in some cases: the beginning column number is 1, no matter how much one can adjust the beginning and completing row number in FORVPM2. You see that of the loop construct. If it is important, one can make a variable which instructs it to leap forward the very first time it is started. This is done here, inside V10. Also V7 and V8 are used for 'private' stuff for the algorithm (again, this may or may not be how F9 is implemented in practise): ((DATA F9-SCAN-ARRAY )) ((DATA F9-SCAN-ACTION-HOUSE )) ((DATA F9-SCAN-ACTION-UPC-HOUSE )) ((DATA F9-WORK-SPACE )) (( }} ; F9-CLIPBOARD-FIRST-LINE => >VARSTR )) (( 300 => %MAKE F9-SCAN-ARRAY < NOZ (MATCHED (( V10 => TOV2 )) (( V10 ; V3 ; # => GM => TOV11 )) (( 0 => TOV10 )) MATCHED) )) (( V8 ; V11 => INTEQUAL (MATCHED (( V7 => %LENGTH => DEC (COUNT (( (( N1 ; V2 => ADD )) ; V3 ; # => GM => A (MATCHED (( ; N1 => INC ; V7 => %GET => NOT_INTEQUAL (MATCHED RMS RMS GOFORWARD3 MATCHED) )) )(OTHER RMS RMS GOFORWARD4 MATCHED) )) COUNTUP) )) (( V2 ; F9-LINE-POS < INC ; F9-EDIT-X < INC => TOV2 )) (( 1 => TOV4 )) (( CRLN )) (( }* * * * * * * * * * * * * * FOUND IT!} => SPOP )) (( }* * * * * * $ * * * * * * * FOUND IT!} => SPOP )) (( }* * * * * * * * * * * * * * FOUND IT!} => SPOP )) (( EXIT )) (( GOLABEL3: )) (( GOLABEL4: )) MATCHED) )) )) OK) (LET F9-SCAN-ACTION BE (( )) (( (( }SCANNING THE TEXT >>>>CASE-EXACT<<< SPOP )) (( }SCANNING FROM PRESENT POSITION ONWARDS FOR:} => SPOP )) (( }>>} => ( )) (( F9-SCAN-ARRAY >>> => ARRAY>STR => POP )) (( VLOTS )) (( F9-LINE-POS >>> => TOV10 )) (( F9-LINE-NUM >>> => TOV3 )) (( F9-MAX-LINE-USED >>> => TOV4 )) (( F9-SCAN-ARRAY >>> => TOV7 )) (( 1 ; V7 => %GET => TOV8 )) (( VFREE )) (( F9-SCAN-ACTION-HOUSE >>> ; F9-WORK-SPACE >>> => FORVPM2 )) (( CRLN ; CRLN ; (( }DONE!} => SPOPS )) (( A-KEY )) )) OK) (( }F9-SCAN-ACTION-ESSENCE} => ? F9-SCAN-ACTION-HOUSE < NOZ (MATCHED (( V10 => TOV2 )) (( V10 ; V3 ; # => GM => TOV11 )) (( 0 => TOV10 )) MATCHED) )) (( V8 ; V11 => UPCNUM => INTEQUAL (MATCHED (( V7 => %LENGTH => DEC (COUNT (( (( N1 ; V2 => ADD )) ; V3 ; # => GM => A (MATCHED (( ; => UPCNUM ; N1 => INC ; V7 => %GET => NOT_INTEQUAL (MATCHED RMS RMS GOFORWARD3 MATCHED) )) )(OTHER RMS RMS GOFORWARD4 MATCHED) )) COUNTUP) )) (( V2 ; F9-LINE-POS < INC ; F9-EDIT-X < INC => TOV2 )) (( 1 => TOV4 )) (( CRLN )) (( }* * * * * * * * * * * * * * FOUND IT!} => SPOP )) (( }* * * * * * $ * * * * * * * FOUND IT!} => SPOP )) (( }* * * * * * * * * * * * * * FOUND IT!} => SPOP )) (( EXIT )) (( GOLABEL3: )) (( GOLABEL4: )) MATCHED) )) )) OK) (LET F9-SCAN-ACTION-UPC BE (( )) (( (( }SCANNING THE TEXT >>>>CASE-LIBERAL<<< SPOP )) (( }SCANNING FROM PRESENT POSITION ONWARDS FOR:} => SPOP )) (( }>>} => ( )) (( F9-SCAN-ARRAY >>> => ARRAY>STR => POP )) (( VLOTS )) (( F9-LINE-POS >>> => TOV10 )) (( F9-LINE-NUM >>> => TOV3 )) (( F9-MAX-LINE-USED >>> => TOV4 )) (( F9-SCAN-ARRAY >>> => TOV7 )) (( 1 ; V7 => %GET => TOV8 )) (( VFREE )) (( F9-SCAN-ACTION-UPC-HOUSE >>> ; F9-WORK-SPACE >>> => FORVPM2 )) (( CRLN ; CRLN ; (( }DONE!} => SPOPS )) (( A-KEY )) )) OK) (( }F9-SCAN-ACTION-UPC-ESSENCE} => ? F9-SCAN-ACTION-UPC-HOUSE < VISBASIS (MATCHED (( EXIT )) MATCHED) )) (( CLS ; CRLN ; CRLN )) (( }MOVING AHEAD ONE!} => SPOP )) (( CRLN ; CRLN ; CRLN )) (( F9-EDIT-X >>> ; 77 => INTGREATER (MATCHED (( F9-MAX-LINE-USED >>> ; F9-LINE-NUM >>> => INTGREATER (MATCHED (( F9-LINE-NUM => INCVAR )) (( F9-LINE-NUM >>> F9-TOP-OF-PAGE-LINE-NUMBER-SHOWN < SETDANCE )) (( 2 ; F9-EDIT-X < INCVAR )) (( F9-EDIT-X => INCVAR )) MATCHED) (( F9-RECENT-SCAN-REPL-WARP >>> H )) (( F9-STD-FRAME )) (( F9-REDISPLAY-ALL-TEXT-HERE )) (( F9-MAYBE-UNDERLINE )) )) OK) (LET F9-FUNF4 BE (( )) (( (( CLS )) (( CRLN )) (( } HERE YOU CAN SCAN FOR ANY SIMPLE TEXT MATCH} => POP )) (( } -- STARTING FROM WHERE THE TEXT MARKER IS POSITIONED NOW,} => POP )) (( } AND -- IF YOU PRESS CTR-L YOU CAN LOOP MOST RECENT SCAN/REPL,} => POP )) (( } BUT CTR-L (LOOK) IS SOMETHING YOU PRESS WHEN THE TEXT IS SHOWING.} => POP )) (( } ONCE YOU HAVE PRESSED THIS KEY, YOU MUST TYPE IN TEXT --} => POP )) (( } -- OR PRESS ENTER TO GET A LINE/WORD WHICH YOU HAVE CLIPPED} => POP )) (( } TO SEARCH FOR. THE TEXT SCAN/REPL IS NOW IN MODE:} => POPS )) (( F9-CASE-SCAN => VISDANCE (MATCHED (( }>>>>UP/LCASE-STRICT} => POP )) )(OTHER (( }>>>>UP/LCASE-LIBERAL} => POP )) MATCHED) )) (( } CLICK CTR-U DURING ORDINARY TEXT VIEWING MODE TO SWITCH BETWEEN} => POP )) (( } HAVING SCAN/REPL CASE SENSITIVE OR MATCHING ON BOTH CASES.} => POP )) (( CRLN ; CRLN )) (( } TEXT TO MATCH FOR: (OR ENTER FOR WORDS FROM RECENT CLIPBOARD IF ANY)} => POP )) (( } ==>} => ( )) (( READLN => LENGTH => ISBASIS (MATCHED (( RM )) (( F9-CLIPBOARD-FIRST-LINE => VARSTR> ; )) MATCHED) )) (( ; => TOSTANDARDSPACE ; )) }* Converts asciinum under 32 to space }* (( ; => LENGTH => ISBASIS (MATCHED (( RM )) (( GOFORWARD4 )) MATCHED) )) (( CLS ; CRLN ; CRLN )) (( F9-CASE-SCAN => VISDANCE (MATCHED (( ; F9-SCAN-ARRAY >>> ; STR>EXISTING-ARRAY )) (( }F9-SCAN-ACTION} => ? F9-RECENT-SCAN-REPL-WARP < UPCM ; F9-SCAN-ARRAY >>> ; STR>EXISTING-ARRAY )) (( }F9-SCAN-ACTION-UPC} => ? F9-RECENT-SCAN-REPL-WARP < FLAGFLIP )) )) OK) }* then more procedures, and here's an example of the main loop: }* (LET F9-TYPEWRITER-NORMAL BE (( )) (( (( GOLABEL4: )) (( MANUAL-CLEAR-KEYBUF )) (( KEYNUM => >N1 )) (( N1 ; 32 ; 126 => WITH (MATCHED (( N1 => ASCII => ( )) (( F9-FILE-SHOULD-BE-STORED => SETDANCE )) (( F9-CLARIFY-STATUS-LINE-IF-NEED-BE )) (( F9-LINE-NUM ; F9-MAX-LINE-USED => INCREASE-VAR-IF-THIS-IS-HIGHER )) (( F9-MAYBE-UN-UNDERLINE )) (( F9-EDIT-X => INCVAR )) (( F9-LINE-POS => INCVAR )) (( F9-EDIT-RANGE-CONTROL )) (( F9-MAYBE-UNDERLINE )) )(OTHER (( N1 ; KEY-ENTER >>> => EQN (MATCHED (( F9-MAYBE-UN-UNDERLINE )) (( F9-FILE-SHOULD-BE-STORED => SETDANCE )) (( F9-EDIT-NEXTER )) (( F9-EDIT-LEFTMOST )) (( F9-LINE-NUM => INCVAR )) (( F9-LINE-NUM ; F9-MAX-LINE-USED => INCREASE-VAR-IF-THIS-IS-HIGHER )) (( F9-LINE-POS => SETDANCE )) (( F9-EDIT-RANGE-CONTROL )) (( F9-CLARIFY-STATUS-LINE-IF-NEED-BE )) (( F9-MAYBE-UNDERLINE )) )(OTHER (( N1 ; KEY-ESC >>> => EQN = EXIT === )) (( N1 => ISBASIS = F9-FUN-KEYS == N1 ; CTRL-I >>> => EQN = F9-FUNCTR-I == N1 ; 8 => EQN = F9-FUNBP == N1 ; 21 => EQN = F9-FUNCTR-U == N1 ; 23 => EQN = F9-FUNCTR-W == N1 ; 12 => EQN = F9-FUNCTR-L === === === === === === )) MATCHED) )) MATCHED) )) (( GOUP4 )) )) OK) (( FR )) With input from varstack (like ^99999), produce, to varstk, RFFG (( FREE-ACTION )) Just a function which, for your convenience, does nothing note1:::: You can set a warp to this when you have nothing else to set it to, e.g. }FREE-ACTION} => ? NEXT-ACTION <>> H it will not cause a great stir. (( FREE-B )) Produce a number 1..255 (a 'byte') on RFFG basis ---> FR ---> RFFG ---> %RFFG note1:::: Some others like this exist but the GJ hardware will have different screenformat, and they were graphically oriented (FREE-V, FREE-H) (( FREE-LIST )) Dissolve, release RAM, of a list made earlier by LIST ---> LIST (which has a lot more ---> connections for lists) (( FT )) This is used to make sure graphical pointer symbol is not on screen (( FT-CLS )) This is a CLS which also does an FT, when in graphical mode (( FUNC-KEY-INS )) A variable containing this function key when in graph mode ---> FUNC-KEY-F1 (which has a lot more of ---> connections) (( FUNC-KEY-DEL )) A variable containing this function key when in graph mode ---> FUNC-KEY-F1 (which has a lot more of ---> connections) (( FUNC-KEY-F1 )) Variables containing these function key when in graph mode (( FUNC-KEY-F2 )) (( FUNC-KEY-F3 )) (( FUNC-KEY-F4 )) (( FUNC-KEY-F5 )) (( FUNC-KEY-F6 )) (( FUNC-KEY-F7 )) (( FUNC-KEY-F8 )) (( FUNC-KEY-F9 )) (( FUNC-KEY-F10 )) (( FUNC-KEY-F11 )) (( FUNC-KEY-F12 )) ---> CTRL-P ---> CTRL-O ---> CTRL-N ---> CTRL-Q ---> CTRL-E ---> CTRL-R ---> CTRL-I ---> CTRL-F ---> FUNC-KEY-HOME ---> FUNC-KEY-PGUP ---> FUNC-KEY-END ---> FUNC-KEY-PGDN ---> NEWKEY ---> KEYTOUCH ---> KEYNUM ---> FKEYNUM ---> FKEYCTRL ---> FKEYALT ---> FKEYSHIFT note1:::: the ctr-values are selected to be particularly free of other possibly predefined functions in some os contexts while, rather in order of the PONQERIF sequence given, may be said to be easy to press, with both hands resting in leisure on the keyboard, one finger pressing on CTR and the other on P, or O beside it, or N etc. The CTRL-I though has also a use in the indent ->| key. note2:::: the FUNC-KEY- differs from the CTRL- variables in that whereas the CTRL- values are consistent across the text and graphical modes for keynum, the FUNC-KEY- values as here given work in the graphical mode for FKEYNUM and which is put to the V8 position when NEWKEY is used, when KEYNUM / V9 is zero. You may find the LAB in FIC3.TXT an excellent example of how one might use these variables so as to have an elegant layout on deciding what operation to call on given a variety of options for input. Be sure to notice that the KEYNUM is used only once for each keypress, while, in the graphical mode, some data overflows from KEYNUM into FKEYNUM, FKEYALT and so on when special keys are pressed, like HOME. In other words, access FKEYNUM, if at all, after KEYNUM has been performed, but KEYNUM is the essential action of picking stuff from the keyboard buffer, and, during a program with many processes in parallel, KEYNUM is only used when KEYTOUCH gives an affirmative value. The little program KEYGRAPH.TXT, performed when KEYGRAPH is written as command in $$$ Lisacode $$$, illustrates all this easily enough. Note that when, in the text mode, a function key like F1 is pressed, an entirely different action occurs, which must be treated in a different way: namely, KEYNUM will first report zero, then a suitable number, while FKEYNUM and so on are not to be called on at all in text mode. Make a little loop with KEYNUM => POP while trying out combinations on the keyboard to see what's what. Note that only the standard PC keys (excluding some possible later additions) will have values. (( FUNC-KEY-HOME )) A variable containing this func key when in graph mode ---> FUNC-KEY-F1 (which has a lot more of ---> connections) (( FUNC-KEY-PGUP )) A variable containing this func key when in graph mode ---> FUNC-KEY-F1 (which has a lot more of ---> connections) (( FUNC-KEY-END )) A variable containing this function key when in graph mode ---> FUNC-KEY-F1 (which has a lot more of ---> connections) (( FUNC-KEY-PGDN )) A variable containing this func key when in graph mode ---> FUNC-KEY-F1 (which has a lot more of ---> connections) GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG G (( GET-CURRENT-POS-IN-LIST )) Show current position in the LIST array ---> LIST (which has a lot more ---> connections for lists) (( GETASCII )) Where ascii produces the character, GETASCII gets the asciinum ---> ASCII (( GETFUNCNUM )) To change meaning of a defined func., use w/SETWARPADDRESS ---> SETWARPADDRESS (( GETV )) Often used with ^99999 FR GETV to move value over from varstk ---> VARTOSTK (synonym with GETV) ---> # ---> & ---> && ---> V>> ---> RMV note1:::: It is often very clear and easy to write (( # => => )) on the second-to-completing line of a function which produces the variable stack content as its output, and then the conventional (( && )) on the completing line, although, in principle, GETV would be minuscle faster. (( GJ-DONE )) Always completing a graphical program (start it with GJ-ON) --> GJ-ON ---> RAM-REFRESH (for text mode) note1:::: Typical, normal, recommended, standard way of completing a graphical program; the same has usually been initialized via ---> GJ-ON. (( GJ-ON )) Always start a graphical program with this (complete w/GJ-DONE) ---> GJ-DONE ---> FREE-CLS note1:::: For text programs, ---> FREE-CLS. (( GJPFILE2PM )) As FILENUM2PM, but binary 200x200 format for 0..255 values note1:::: Any (( 200 ; 200 => RAM-PM )) matrix can be saved by ---> PM2FILEGJP and then retrieved by this. Prefer suffix .GJP then. (( GM )) The main function to Get a value from a Matrix ---> PM ---> RAM-PM ---> FORVPM ---> FORVPM2 note1:::: Synonym with GMATRIX, but GM is the typical convention note2:::: GM, like ---> PM, and a number of warp-oriented functions, including also ---> PEEK, ---> POKE, ---> PM2FILE, ---> FORVPM2, etc, offer you unparalleled freedom and complete access to the defined segments of the machine's RAM and does so without slowing down the processes by lots of checks and conditions, which in any case can't really cover all the situations if one wanted to do it as safe as possible. A well-corrected Lisa program is far more stable than any program in any other programming language that I know of because the programmer has worked in attunement with the machine hardware. But then you must be prepared during program performance on all such direct warp-addressing functions that you give them the right value or else a pull-the-plug like event occurs -- which is fun, of course -- but you might as well know that that is the likely location if something goes well up to a point and then it goes haywire. Get the parameters right and esp. watch it when you've done copy/paste with a little bit of modification of warp-relevant code. (( GOFOWARD1 )) Within a function, where there is a GOLABELn: under this (( GOFOWARD2 )) line, go to that GOLABEL. ALWAYS USE BUT ONE GOFORWARD (( GOFOWARD3 )) OR GOUP ASSOCIATED WITH ONE GOLABELn. PROGRAM WILL ONLY (( GOFOWARD4 )) WORK PROPERLY THEN. This restriction helps clarity. (( GOLABEL1: )) An entry-point inside the function for one single (( GOLABEL2: )) GOxxxxx call to this point (either one GOUPn or one (( GOLABEL3: )) GOFORWARDn, cannot be more than one such for each (( GOLABEL4: )) labelled entry-point, and all of it inside the function) (( GOODPAUSE )) Wait this many milliseconds in very approximate terms in: number produces: comment on in:::: Too small numbers may have no real effects, depends on PC ---> SECS ---> LOOKSTK (see comment here on a typical use of it also in that context) note1:::: While tuning of time sensitively is a tremendously significant part of all good programming, one must nevertheless not be a control-maniac on timing but allow natural fluctuations (( GOUP1 )) This is how to loop up to a higher point in a function when (( GOUP2 )) there is a corresponding GOLABELn: inside that function. (( GOUP3 )) To exit such a function, make sure that there is something (( GOUP4 )) like a .. (MATCHED .. MATCHED) or .. = .. ===, perhaps with EXIT. (( GOTOXY )) In textmode, position at this column, at this row note1:::: Note that max values for this will differ in future GJ PCs (( GREATER )) Decimal comparison but at the main stack ---> STKTORICH ---> RICHTOSTK note1:::: Decimal numbers should be dealt with at the decimal stack; there are numbers which can be produced in a 'textual' sense by some trigonometric or exponential functions (ie, with E-notation) which have no meaning whatsoever when occuring on the main stack except as input to a textual word like POP. The fact that some decimal number algorithms exist for the main stack should not strongly encourage anyone to engage the main stack for such metaphysically dubvious entities as decimal numbers. Use richstack, normally, when it is fairly obvious how. However, better still: convert the situation to a whole-number paradigm, which is easy when you try. Most situations can be re-analyzed to a whole number approach. You will find that there are more and better functions dealing with whole numbers generally speaking. If you need trigonometrics, it is quite possible also to do this entirely by whole numbers by suitable arrays with suitable factors and indeed this is very common in high-performing trigonometric computational paradigms. HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH H (( H )) Hyperimportant hyperconnecting function, use with a ? value ---> ? ---> %MAKE (important comment) (( HEAL )) This is how the text/number looks from a whole number perspective (( HEX )) Convert to hex (( HEX2DEC )) Convert hex to decimal IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII I (( IMGS )) A small program which shows .GJP images. (( INTEQUAL )) As EQN, this compares the whole number aspect of two numbers (( INVISIBLECOMPILATION )) Normal quick smart mode of compilation (( INCR )) As INC, but this one works with decimal numbers on richstk (( INC )) The main way to increase a number on main stack by one (( INC4 )) Increase by 4 (( INC4R )) Increase by 4 on the richstk (( INC8 )) Increase by 8 (( INC12 )) Increase by 12 (( INC16 )) Increase by 16 (( INC20 )) Increase by 20 (( INC24 )) Increase by 24 (( INC28 )) Increase by 28 (( INC32 )) Increase by 32 (( INC36 )) Increase by 36 (( INC40 )) Increase by 40 (( INC44 )) Increase by 44 (( INC48 )) Increase by 48 (( INCVAR )) Increase the variable value by one (given a ((DATA XXX )) var) ---> ADDVAR ---> INCREASE-VAR-IF-THIS-IS-HIGHER ---> SETDANCE ---> SETBASIS ---> < >>> ---> VISDANCE ---> VISBASIS (( INTGREATER )) The main way to compare two numbers for size ---> WITH ---> SET-RANGE ---> INCREASE-VAR-IF-THIS-IS-HIGHER ---> NAME-GREATER ---> INTGTOREQUAL ---> EQN ---> INTEQUAL (( INTGTOREQUAL )) The main way to compare for equal or greater ---> INTGREATER (( INTO-LIST-AT-THIS-POS )) Put into list at arbitrary given position ---> LIST (which has a lot more ---> connections for lists) (( INTO-LIST-HERE )) Put new value into list at present position ---> LIST (which has a lot more ---> connections for lists) (( IS )) Synonym with ---> >>> and with ---> =-> (prefer >>> usually) (( IS-ANY-IN-LIST )) Flag which tells if any in this list ---> LIST (which has a lot more ---> connections for lists) (( IS-THIS-IN-LIST )) Roll through the list and scan for this value ---> LIST (which has a lot more ---> connections for lists) (( IS-ANYTHING-ON-MAIN-STACK )) An elegant check during startup of programs note1>>>> We like textual control in first-hand environments -- short, snappy meaningful commands which provides an opportunity for the tool to feel professional. But to facilitate easy startup of loading of file or input of startup-parameters, we would like sometimes to start with empty stack, and at other times with something. Note that this function only works when it is entirely the top-mode -- you start the program from a truly empty stack, directly after F3 is given as command. One might imagine a startup like this: (LET SHOWFILE BE (( ; )) (( (( IS-ANYTHING-ON-MAIN-STACK => NOT (MATCHED (( }NEW-TEXT} ; )) MATCHED) )) (( ; => TOSTANDARDSPACE => RMBL => UPCM FILE-TO-START-SHOWING => >VARSTR )) (( SHOWFILE-START )) )) OK) (LET AUTOSTART BE SHOWFILE OK) The TOSTANDARDSPACE converts to space character if there is a strange control character with ascii-num 0..31 in it. (( ISBASIS )) Flag which checks if value is zero, using a good idea: basis ---> VISBASIS ---> ISDANCE ---> VISDANCE ---> EQN ---> ISPRO ---> A ---> T ---> NOZ ---> INTEQUAL note1:::: As for program correction, the V in VISBASIS means that it assumes that a warp has been put on the varstack, whereas the ISBASIS assumes that the number to be checked is already on the main stack. Substituting one for the other garantees rather interesting ways of generating computer collapse.. (( ISDANCE )) Flag which checks if value is one ---> VISBASIS ---> ISBASIS ---> VISDANCE ---> EQN ---> ISPRO ---> A ---> T ---> NOZ ---> INTEQUAL (( ISNT-BEFORE-LIST )) Flag true if it isn't anyone before this position ---> LIST (which has a lot more ---> connections for lists) (( ISPRO )) This wonderful function tells if number is positive (( ISSIGNED )) This tells if number is signed JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ J general comment:::: A number of the new words in the GJ edition will begin with the letter J (also for other medias etc). It signifies perhaps a journey, a good (warpcraft) journey. FOR REAL. KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK K (( KEEPDIGITSLETTERS )) Well, need any explanation? (( KEEPDIGITSLETTERSALPHA )) Keep a little more (( KEEPLETTERS )) Keep letters, discard rest of a main stack item (( KEY )) Read one character and fetch it as letter, digit, or whatever ---> CLEAR_KEYBUF (important comment) (( KEY-ENTER )) A variable, equal to the value which ENTER key gives variable (use with >>>) produces: number comment on produces:::: the number value of this variable is the ascii number which corresponds to the enter or lineshift button as retrieved e.g. with keynum ---> FUNC-KEY-F1 (which has a lot more of ---> connections) (( KEY-ESC )) A variable, equal to the value which ESC key gives ---> FUNC-KEY-F1 (which has a lot more of ---> connections) (( KEYNUM )) As KEY, but this read keyboard as ascii number instead ---> CLEAR_KEYBUF (important comment) (( KEYTOUCH )) Checks if anything is available to KEY or KEYNUM ---> MMOTION ---> CLEAR_KEYBUF (important comment) LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL L (( LENGTH )) Let item remain on stack, and tell in addition its length (( LINE )) Produce a line of pixels in the graphical mode ---> DOTTED_RECT (see comment) ---> PUTPIXEL ---> RECT ---> CIRCLEFILL ---> RECTFILL ---> CIRCLE ---> MOUSEXY note1:::: It is no secret that I am absolutely intrigued by quantum phenomena and the larger questions of understanding the universe. In having produced a theory encompassing all phenomena in a vast scope, I have done much work recently on illustrating features of this theory. In so beginning I first made a sketch on paper of how I would like a Lisa formalism to appear graphically on the computer monitor. I then proceeded to make the following text, which is a very, very early form -- containing more NOD501 edition words than GJ words proper (such as XO instead of GJ-DONE, and START-GRAPHICS instead of GJ-ON, and so on) -- of what is fully open source printed in my 2007 book with the completed, correct version, mentioned elsewhere -- the book with the title which begins with 'The supermodel theory illustrated in the lisa programming language', and which I have produced properly with ISBN and sent to libraries and so on to get this work established in a sense which is more official and public and which can take my mind off worrying about exactly where I will publish that work further on. So I give you this very early version for several reasons. One, it shows just how LINE can be used to sketch something you want to illustrate. Two, it shows you how you can erect a lot of structure which does nothing except to prompt you to make more -- a lot of empty functions which sketchily indicate where you want to go -- but in the form of a real program which performs and which gives you something very visible on-screen. Third, I sort of acknowledge the branch of neopopperian science called physics for how it constantly propells me to think of programming afresh, by including this. I hope by the inclusion of this also -- which is, I think, the completing addition to this MTDOC.TXT (although it is in the middle) -- that we have enough to let go completely of the earlier MTDOC.TXT, which needed a replacement. ((DATA MODEL-LENGTH 72 MODEL-LENGTH < MUL => MUL => MUL TWICE SPACE-4D < MUL => MUL SPACE-3D < MUL SPACE-2D < %LENGTH (COUNT (( N1 ; N1 ; # => %PUT )) COUNTUP) )) (( && )) )) OK) (LET INDEX-MAKE BE (( >N1 )) (( (( N1 => %MAKE => ONE => INDEX-REFRESH ; => => )) )) OK) (LET MANIFEST-UNIV BE (( ; ; ; )) (( (( DEC ; SPACE-2D >>> MUL )) (( SWITCH => DEC ; SPACE-1D >>> MUL )) (( ; ; ; => ADD => ADD => => )) )) OK) (LET MOMENT BE (( ; ; ; ; )) (( (( DEC ; SPACE-3D >>> MUL )) (( SWITCH => DEC ; SPACE-2D >>> MUL )) (( ANGEL => DEC ; SPACE-1D >>> MUL )) (( ; ; ; ; => ADD => ADD => ADD => => )) )) OK) (LET INIT-SUPERM BE (( )) (( (( SPACE-4D >>> => %MAKE SIMILARITY-ARRAY <>> => INDEX-MAKE SIMILARITY-ARRAY-I <>> => %MAKE CONTRAST-ARRAY <>> => INDEX-MAKE CONTRAST-ARRAY-I <>> ; SPACE-4D >>> => RAM-PM SUPERM-MATRIX < POPS )) (( SPACE-4D >>> => POPS )) (( }SUPERMODELS.} => POP )) )) OK) ((DATA WARP-PMW-EMULATE )) ((DATA ACTIVATION-LIST )) ((DATA AMOUNT-SUPERM )) ((DATA SIGNAL-STATUS-EXIT )) ((DATA THIS-RUN )) ((DATA SUITABLE-WAIT )) ((DATA ERASE-LIST )) ((DATA COORDINATES-RECTANGLES-HOUSE )) ((DATA COORDINATES-CIRCLES-HOUSE )) ((DATA CURRENT-SUPERM )) ((DATA ALGORITHM-NUMBER-STD )) (LET LOCALE-SYMBOL BE (( >N2 >N1 )) (( (( N1 ; N2 ; 4 ; 1 => CIRCLE )) )) OK) (LET SET-CURRENT-SUPERM BE (( ; )) (( (( ; CURRENT-SUPERM < ? ALGORITHM-NUMBER-STD < ? WARP-PMW-EMULATE < ? COORDINATES-RECTANGLES-HOUSE < ? COORDINATES-CIRCLES-HOUSE < %GET )) (( && )) )) OK) (LET MAG BE (( & )) (( (( 8 ; # => %GET )) (( && )) )) OK) (LET LITE BE (( & )) (( (( # => ELECT => => )) (( # => MAG => => )) (( && )) )) OK) (LET IS-TYPE-LITE BE (( & )) (( (( 9 ; # => %GET ; 24 => EQN => => )) (( && )) )) OK) (LET IS-TYPE-ELECTON BE (( & )) (( (( 9 ; # => %GET ; 17 => EQN => => )) (( && )) )) OK) (LET IS-LITE-LIKE BE (( & )) (( (( 9 ; # => %GET => MOD2 => ISBASIS => => )) (( && )) )) OK) (LET IS-MATTER-LIKE BE (( & )) (( (( 9 ; # => %GET => MOD2 => ISDANCE => => )) (( && )) )) OK) (LET PERFORM-ALGORITHM-NUMBER (( & )) (( (( # => SET-CURRENT-SUPERM )) (( 5 ; # => %GET => >N1 )) (( N1 => ISPRO (MATCHED N1 => H MATCHED) )) (( && )) )) OK) (LET ENER-CONS BE (( )) (( )) OK) (LET ADD-ANGULAR BE (( & >N1 )) (( (( 6 ; # => %GET ; N1 => ADD => ONE ; 3599 => INTGREATER = 3600 => SUB === 6 ; # => %PUT )) (( && )) )) OK) (LET ADD-INTENSITY BE (( & >N1 )) (( (( 3 ; # => %GET ; N1 => ADD ; 0 ; 1000 => SET-RANGE ; 3 ; # => %PUT )) (( && )) )) OK) (LET STANDARD-RFFG BE (( )) (( (( CURRENT-SUPERM >>> => & )) (( ^3 FR V>> => DEC ; # => ADD-ANGULAR )) (( ^50 FR V>> ; -25 => ADD ; # => ADD-INTENSITY )) )) OK) (LET POS-FREE-ACT BE (( )) (( (( 1000 (COUNT (( N1 ; ACTIVATION-LIST >>> => %GET => ISBASIS (MATCHED (( N1 => => ; RMS RMS ; EXIT )) MATCHED) )) COUNTUP) )) (( 1 => => )) )) OK) (LET INC-AMOUNT-SUPERM BE (( )) (( (( AMOUNT-SUPERM >>> => INC ; 1 ; 1000 => SET-RANGE AMOUNT-SUPERM <>> => DEC ; 0 ; 1000 => SET-RANGE AMOUNT-SUPERM <>> ; 5 ; # => %PUT )) (( 0 ; 2 ; # => %PUT )) (( 1 ; 3 ; # => %PUT )) (( 1 ; 4 ; # => %PUT )) (( 1 ; 6 ; # => %PUT )) (( 1 ; 7 ; # => %PUT )) (( 1 ; 8 ; # => %PUT )) (( 1 ; 9 ; # => %PUT )) (( 0 ; 70 ; # => %PUT )) (( 0 ; 71 ; # => %PUT )) (( )) OK) (LET NEW-SUPERM BE (( )) (( (( 156 => %MAKE => & )) (( INC-AMOUNT-SUPERM )) (( POS-FREE-ACT => >N1 )) (( # ; N1 ; ACTIVATION-LIST >>> => %PUT )) (( N1 ; 1 ; # => %PUT )) (( # => STANDARD-VALUES )) (( # => => )) (( && )) )) OK) (LET MARK-AS-GROUND-STRUCTURE (( & )) (( (( 1 ; 2 ; # => %PUT )) (( && )) )) OK) (LET SET-MAIN-NUMBER (( & >N1 )) (( (( N1 ; 9 ; # => %PUT )) (( && )) )) OK) (LET RELEASE-SUPERM BE (( & )) (( (( 0 ; (( 1 ; # => %GET )) ; ACTIVATION-LIST >>> => %PUT )) (( # => %FREE )) (( DEC-AMOUNT-SUPERM )) (( && )) )) OK) (LET POS-FREE-COH BE (( & )) (( (( 20 (COUNT (( N1 DEC ; 10 => MUL ; 72 => ADD => >N8 )) (( N8 ; # => %GET => ISBASIS = N8 => => ; RMS RMS ; && ; EXIT === COUNTUP) )) (( && )) (( 0 => => )) )) OK) (LET AMOUNT-COH BE (( & )) (( (( 71 ; # => %GET )) (( && )) )) OK) (LET DEC-AMOUNT-COH BE (( & )) (( (( 71 ; # => %GET => DEC => >N1 )) (( N1 ; -1 => INTGREATER = N1 ; 71 ; # => %PUT === )) (( && )) )) OK) (LET INC-AMOUNT-COH BE (( & )) (( (( 71 ; # => %GET => INC ; 71 ; # => %PUT )) (( && )) )) OK) (LET ROOM-FOR-MORE-COH (( & )) (( (( 20 ; # => AMOUNT-COH => INTGREATER => => )) (( && )) )) OK) (LET ERASE-THIS-COH BE (( & >N1 )) (( (( 0 ; N1 ; # => %PUT )) (( # => DEC-AMOUNT-COH )) (( && )) )) OK) (LET ADD-NEW-COH BE (( & >N1 )) (( (( # => POS-FREE-COH => >N2 )) (( N2 => ISPRO (MATCHED (( N1 ; N2 ; # => %PUT )) (( N2 ; 70 ; # => %PUT )) (( # => INC-AMOUNT-COH )) MATCHED) )) (( && )) )) OK) (LET THIS-COH BE (( ; )) (( (( ; => DEC ; 10 => MUL ; 71 ADD => => )) )) OK) (LET SET-THIS-COH BE (( & >N1 )) (( (( N1 ; 70 ; # => %PUT )) (( && )) )) OK) (LET GET-THIS-COH BE (( & )) (( (( 70 ; # => %GET )) (( && )) )) OK) (LET SET-TYPE-COH BE (( & >N1 )) (( (( GET-THIS-COH => >N2 )) (( N2 => ISPRO (MATCHED (( N2 => THIS-COH => >N2 )) (( N1 ; N2 INC ; # => %PUT )) MATCHED) )) (( && )) )) OK) (LET GET-TYPE-COH BE (( & >N1 )) (( (( GET-THIS-COH => >N2 )) (( N2 => ISPRO (MATCHED (( N2 => THIS-COH => >N2 )) (( N1 ; N2 INC ; # => %PUT )) MATCHED) )) (( && )) )) OK) (LET INCREASE-TICK BE (( )) (( (( THIS-RUN => INCVAR )) (( THIS-RUN >>> ; 8 => INTGREATER (MATCHED THIS-RUN => SETDANCE MATCHED) )) )) OK) (LET DISP-3D BE (( )) (( (( 430 ; 4 ; 430 ; 328 ; 1 => LINE )) (( 422 ; 4 ; 422 ; 328 ; 1 => LINE )) (( 12 ; 328 ; 430 ; 328 ; 1 => LINE )) )) OK) (LET DISP-2D-IF-ANY BE (( )) (( (( 680 ; 118 ; 922 ; 439 ; 1 => RECT )) )) OK) (LET DISP-BIRDS-VIEW BE (( )) (( (( 12 ; 338 ; 430 ; 760 ; 1 => RECT )) )) OK) (LET DISP-NUMBERS BE (( )) (( (( 450 ; 250 ; 650 ; 626 ; 1 => RECT )) )) OK) (LET DISP-MENU BE (( )) (( (( }SUPERMODEL THEORY BY A.TACOMA} ; 623 ; 8 => LUCIDWRITE )) (( }FORMAL ILLUSTRATION IN LISA} ; 623 ; 26 => LUCIDWRITE )) (( }P PRINT DATA TO FILE} ; 523 ; 664 => LUCIDWRITE )) (( }N NUMERICAL DATA TO FILE} ; 753 ; 664 => LUCIDWRITE )) (( }T CHANGE TIMESCALE} ; 523 ; 682 => LUCIDWRITE )) (( }M CHANGE EMULATED TIMESCALE} ; 753 ; 682 => LUCIDWRITE )) (( }S CHANGE EMULATED SPACES} ; 753 ; 700 => LUCIDWRITE )) (( }C CRITERION FOR GRAPH} ; 523 ; 718 => LUCIDWRITE )) (( }D CRITERION FOR 3D VIEW} ; 753 ; 718 => LUCIDWRITE )) (( }Q QUIT} ; 753 ; 736 => LUCIDWRITE )) )) OK) (LET DISP-SUPERM-VIEW BE (( )) (( (( 680 ; 456 ; 922 ; 626 ; 1 => RECT )) (( }SUPERMODEL NETWORK EMULATION} ; 700 ; 632 => LUCIDWRITE )) (( 701 ; 642 ; 923 ; 642 ; 1 => LINE )) )) OK) (LET UPDATE-DISPLAY BE (( )) (( (( FT )) (( DISP-3D )) (( DISP-2D-IF-ANY )) (( DISP-BIRDS-VIEW )) (( DISP-NUMBERS )) (( DISP-MENU )) (( DISP-SUPERM-VIEW )) )) OK) (LET ACTIVATE BE (( ; )) (( (( ; ACTIVATION-LIST >>> => %GET => & )) (( && )) )) OK) (LET ENHANCE-POSSIBILITIES-SIMILARITY BE (( )) (( )) OK) (LET ENHANCE-POSSIBILITIES-CONTRAST BE (( )) (( )) OK) (LET CONTRAST-ANGLE BE (( & )) (( (( && )) )) OK) (LET CONTRAST-INTENSITY BE (( & )) (( (( && )) )) OK) (LET CONTRAST-MAIN BE (( & )) (( (( && )) )) OK) (LET SIMILARITY-ANGLE BE (( & )) (( (( && )) )) OK) (LET SIMILARITY-INTENSITY BE (( & )) (( (( && )) )) OK) (LET SIMILARITY-MAIN BE (( & )) (( (( && )) )) OK) (LET ENHANCE-FOR-CONTRASTS BE (( ; )) (( (( ; ACTIVATION-LIST >>> => %GET => & )) (( # => CONTRAST-ANGLE )) (( # => CONTRAST-INTENSITY )) (( # => CONTRAST-MAIN )) (( && )) )) OK) (LET ENHANCE-FOR-SIMILARITIES BE (( ; )) (( (( ; ACTIVATION-LIST >>> => %GET => & )) (( # => SIMILARITY-ANGLE )) (( # => SIMILARITY-INTENSITY )) (( # => SIMILARITY-MAIN )) (( && )) )) OK) (LET PMW-EMULATE BE (( )) (( (( ACTIVATION-LIST >>> => & )) (( 8192 (COUNT (( N1 ; # => %GET => NOZ (MATCHED (( N1 ; # => %GET => PERFORM-ALGORITHM-NUMBER )) MATCHED) )) COUNTUP) )) (( ENHANCE-POSSIBILITIES-SIMILARITY )) (( ENHANCE-POSSIBILITIES-CONTRAST )) (( 8192 (COUNT (( N1 ; # => %GET => NOZ (MATCHED (( N1 => ENHANCE-FOR-CONTRASTS )) (( N1 => ENHANCE-FOR-SIMILARITIES )) MATCHED) )) COUNTUP) )) (( && )) (( ERASE-LIST >>> & )) (( 1 ; # => %GET (COUNT (( N1 INC ; # => %GET => RELEASE-SUPERM )) COUNTUP) )) (( 0 ; 1 ; # => %PUT )) (( && )) )) OK) (LET BASIS-3D BE (( )) (( (( 8 (COUNT (( 225 N1 17 MUL SUB ; 80 N1 15 MUL ADD ; BRIDGE 158 ADD ; BRIDGE 83 ADD ; 1 => LINE )) (( 68 N1 22 MUL ADD ; 187 N1 12 MUL ADD ; BRIDGE 121 ADD ; BRIDGE 105 SUB ; 1 => LINE )) COUNTUP) )) )) OK) ((DATA SCALE-3D-HEIGHT SCALE-3D-HEIGHT => SETDANCE )) (LET CUBE-3D-COOR BE (( >N3 >N2 >N1 )) (( (( 120 N1 17 MUL ADD ; )) (( 220 N2 12 MUL SUB ; (( N3 ; (( 11 ; SCALE-3D-HEIGHT >>> ADD )) => MUL )) => SUB ; )) )) OK) (LET A-CIRCLE BE (( ; ; ; )) (( (( => CUBE-3D-COOR => LOCALE-SYMBOL )) )) OK) (LET HANDLE-KEYBOARD BE (( )) (( (( KEYTOUCH (MATCHED (( KEY => UPC ; :P => TEQ = PRINT-TO-FILE == :Q => EQ = SIGNAL-STATUS-EXIT => SETDANCE === === )) (( CLEAR_KEYBUF )) MATCHED) )) )) OK) (LET ACTIVATION-ARRAY-LOOP BE (( )) (( (( GOLABEL4: )) (( WARP-PMW-EMULATE >>> H )) (( UPDATE-DISPLAY )) (( INCREASE-TICK )) (( SUITABLE-WAIT >>> => GOODPAUSE )) (( HANDLE-KEYBOARD )) (( SIGNAL-STATUS-EXIT => VISBASIS = GOUP4 === )) )) OK) (LET INIT-SUPERM-2 BE (( )) (( (( THIS-RUN => SETDANCE )) (( SIGNAL-STATUS-EXIT => SETBASIS )) (( AMOUNT-SUPERM => SETBASIS )) (( 100 SUITABLE-WAIT < %MAKE ACTIVATION-LIST < %MAKE ERASE-LIST <>> => %PUT )) (( GETVARIABLES )) (( START-GRAPHICS )) (( LISAMENU-PALETTE )) (( SAVE-SCREEN => SETDANCE )) (( PC-GREEN )) (( UPDATE-DISPLAY )) )) OK) (LET ON-WITH-SUPERM BE (( )) (( (( ACTIVATION-ARRAY-LOOP )) (( DONE-GRAPHICS )) (( CLS )) (( } IF ANY MESSAGES ABOVE FROM THE LISA (ALSO CALLED FIRTH MT) LANGUAGE,} => POP )) (( } TYPE STK OR THE LIKE, CORRECT YOUR INPUT PARAMETERS, AND TRY AGAIN!} => POP )) (( VARSTK ; LOOKSTK )) (( } NEXT, PLS TYPE XO AND PRESS ENTER TO REFRESH RAM. THANKS.} => POP )) (( } THIS PROGRAM IS RESTARTED, WHEN IT IS AT C:\, WITH :/SUPERM IN} => POP )) (( } YOUR INPUT PARAMETERS, IF AT C:\FILE1.TXT, ARE THEN LOADED BY} => POP )) (( } THE COMMAND :/FILE1 IN CFR BOOK PUBLISHED IN 2007 WITH} => POP )) (( } ISBN 82-996977-0-1 ABOUT THIS, 'THE SUPERMODEL THEORY ILLUSTRATED} => POP )) (( } IN THE LISA PROGRAMMING LANGUAGE: UNDERSTANDING QUANTUM PHENOMENA,} => POP )) (( } GRAVITATION AND BIOLOGICAL COHERENCE ON A COMMON FOOTING'} => POP )) (( } PUBL. BY YOGA4D:VRGM, OSLO AND NYC, FOUND ALSO AT NB.NO, THE} => POP )) (( } NATIONAL LIBRARY OF NORWAY, AS PRINTED BOOK, FROM AUTUMN 2007.} => POP )) (( } THIS PROGRAM / FORMALISM IS COPYRIGHT (C) ARISTO TACOMA 2007} => POP )) (( } BUT, WHEN YOU FOLLOW THE OUTLINES INDICATED IN YOGA4D.ORG/cfdl.txt} => POP )) (( } LICENSE TEXT, YOU CAN USE THIS PROGRAM IN YOUR NEOPOPPERIAN RESEARCH.} => POP )) (( CRLN )) (( CRLN )) )) OK) (LET SUPERM BE (( )) (( (( INIT-SUPERM-2 )) (( BASIS-3D )) (( 1 2 1 => A-CIRCLE )) (( 5 5 1 => A-CIRCLE )) (( 5 5 5 => A-CIRCLE )) (( 8 8 1 => A-CIRCLE )) (( 8 8 5 => A-CIRCLE )) (( ACTIVATION-ARRAY-LOOP )) (( DONE-GRAPHICS )) (( LOOKSTK ; VARSTK )) (( XO )) )) OK) (( LOOKSTK )) (LET AUTOSTART BE SUPERM OK) (( LISA-PAINT )) Paint a Lisa smart painting from matrix to screen in: x y # produces: comment on in:::: Numbers x and y are added to coordinates (( LIST )) allocates ram for a new list in: number produces: warp comment on in:::: the number in is the initial size of the list, which should be comfortable relative to any obvious initial requirement, at least, so that extension and copying over to a larger list size doesn't have to happen initially during ordinary circumstances. comment on produces:::: the warp it produces is the address of the list ---> IS-ANY-IN-LIST ---> IS-THIS-IN-LIST ---> AT-LEAST-NUMBER-1-IN-LIST ---> AMOUNT-IN-LIST ---> START-IN-LIST ---> RECENT-IN-LIST ---> BEYOND-LIST ---> SLENDER-LIST ---> EMPTY-LIST ---> THIS-IN-LIST ---> SET-CURRENT-POS-IN-LIST ---> GET-CURRENT-POS-IN-LIST )) ---> INTO-LIST-AT-THIS-POS ---> INTO-LIST-HERE ---> ISNT-BEFORE-LIST ---> ADDITIONAL-IN-LIST ---> LIST-EXTRA-SPACE ---> YOUNGER-IN-LIST ---> NEXT-IN-LIST ---> FREE-LIST ---> EXTEND-LIST ---> EXTEND-LIST-IF-WITH ---> NUMBERS-TO-LIST ---> LOOP-THROUGH-LIST ---> SHOW-LIST ---> CONVERSE-THROUGH-LIST ---> SHOW-LIST-REVERSE ---> FRAME-ENTER-NUMBERS note1:::: in contrast to ---> LISTOK, the above are defined in FIC3.TXT. It should be relatively easy to extend the functions, e.g. with sorting which perhaps uses qsort2, if you peek into some of these and see the very simple way in which they are made -- with a couple of extra positions initially in an array to designate used length so far, and present position. note2:::: not all of these words, which are really simple because after all they are just minor obvious extensions of the %MAKE array routines, have been fully tested. It should be easy to spot an issue, though, and then build a similar- but not identical-named function which fixes it. note3:::: The memory structure of a list is that it is a perfectly normal array, slightly longer than required, with the initial values telling how big it is and what is the current position of it. This is how it can be implemented: (LET EMPTY-LIST BE (( & )) (( (( 0 ; 1 ; # => %PUT )) (( # => START-IN-LIST )) (( && )) )) OK) (LET LIST BE (( >N1 )) (( (( N1 5 ADD => %MAKE => & )) (( # => EMPTY-LIST )) (( # => => )) (( && )) )) OK) And this is how we get the value of the present position of it: (LET THIS-IN-LIST BE (( & )) (( (( 2 ; # => %GET ; # => %GET )) (( && )) )) OK) Use ---> COPYNUMS to move over to a larger list. note4:::: the FRAME-ENTER-NUMBERS is a high-level graphical input routine (( LIST-EXTRA-SPACE )) Tells how many more there's room for in list ---> LIST (which has a lot more ---> connections for lists) (( LOG2R )) At richstack, logarithm base 2 stuff ---> SINR ---> COSR (( LOOP-THROUGH-LIST )) Do this warp through each value in list ---> LIST (which has a lot more ---> connections for lists) (( LISTOK )) Retrieves the counter from a comma list and puts on stack in: produces: number ---> MAKENEWLIST ---> , (see comment under comma) note1:::: These two functions, and the comma, belong to firth proper, and merely concern ways of handling a variation of number of elements on the stack. There are many ways of creating lists in Lisa. A completely independent development is e.g. seen in the ---> LIST functions. (( LOOKSTK )) Throw in to increase compilator watch-dog activity ---> VARSTK ---> = .. == .. === (VERY USEFUL AFTER MANY ===s IN SEQUENCE) ---> XO ---> VISIBLECOMPILATION ---> COMPILEPAUSEDALITTLE note1:::: WHEN A PROGRAM IS COMPLETED WITH ---> RAM-REFRESH, ---> LOOKSTK IS AUTOMATICALLY CALLED, AS WELL AS A CALL TO ---> VARSTK. THIS MEANS THAT PROGRAMS SHOULD AIM TO HAVE CLEARED UP BASICALLY ALL THE STACKS BEFORE IT COMPLETES (RATHER LIKE P.G.WODEHOUSE NOVELS). note2:::: When LOOKSTK is outside of a function, it works during compilation to tell if there are any left-overs at the various stacks. Throw in tons of these to figure out what's what when correcting a program, especially after clusters of = .. == .. === stuff, and it's okay to leave a couple of LOOKSTKs in the finished program as well, to welcome an open source spirit of the community of programmers who may want to experiment with changes. The LOOKSTK is the increased watchdog mechanism of the compiler, we might say. MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM M (( MAKE-SAFE-8-SIZE-FILENAME )) Do this after READLN on a filename note1>>>> It has been found, by repeated experiments and variations, that quick good working presumes a stability of the computer responses given coherent keyboard input. The responsibility to know the right filename, to have them in one folder, to accept the standard suffix .TXT, and to know and admit that overwrite automatically happens if the file already exist, encourages attention and clarity. If the computer varies response depending on internal storage the sense of control over the program and over the session is psychologically diminished in a way that is inacceptable to the professional, coherent worker. The computer is to obey if a filename is given; it should have the form of a code, not an explanation; and whether or not directory in some sense is to be listed by a program and whether or not it should be consulted is something which is, while up to the programmer, not encouraged by these constructs. This is not a toy but a professional working-tool, encouraging meditation. (( MAKEBL )) Make this many space characters in a main stack item (( MAKECH )) As MAKEBL, but can be another ascii number than 32 or space (( MAKENEWLIST )) Resets the counter for a comma list ---> LISTOK ---> , (see comment under comma) (( MANTRA )) Fifth member is copied to top (( MANTRAR )) Fifth member is copied to top (richstk) (( MANTRAS )) Fifth member is copied to top (simplestack) (( MANTRAV )) Fifth member is copied to top (varstk) (( MATR>TEXT )) Make a stack item out of this line in a FILE2PM-style matrix (( MEM> )) As POKE, this reads from inside an array through warp address (( MMOTION )) Flag if pointer device is on the move (do think about duration) ---> Y-TO-1 ---> MOUSECLICK ---> MOUSECLICKR ---> MMOTION ---> FEET ---> FT (( MOD )) A very important function ('reminder') together with DIV ---> UP-TO-EVEN ---> UP-TO-HIGHER-EVEN ---> FLOOR-EVEN ---> FR ---> DIV ---> MOD2 ---> MOD4 ---> MOD8 ---> MOD16 note1:::: In connection with ---> RFFG functions of various kinds, MOD has the highly applicant functionality in that given any 32-bit number N1, applying a phrase like (( N1 ; 1000 => MOD => POP )) results in a number between zero and one less than this number (it is therefore customary to apply something like (( N1 ; 1000 => MOD => INC => POP )) in most cases). This functionality is incorporated as a blend between RFFG and MOD at what we can call an assembly level, rather, in the function FR, which, in cases of big loops, works eminently fast (since it also happens to work on the VARSTK). note2:::: For those who want to go between something like sequential arrays and two-dimensional matrices, there is a joy in elegant simple arithmetic in understanding the following relationships if there something like 200 times 200 we're talking about, and the first row number is 1 (not zero), and the first column number is 1 (not zero): (( ARRAY-POS >>> => DEC ; 200 => MOD => INC ROW-NUMBER <>> => DEC ; 200 => DIV => INC COL-NUMBER <>> => DEC ; 200 => MUL ; ROW-NUMBER >>> => ADD ARRAY-POS < Y-TO-1 ---> MMOTION ---> FEET ---> FT ---> MOUSECLICKR (( MOUSECLICKR )) Tells if rightbutton on pointer has been clicked ---> Y-TO-1 ---> MMOTION ---> MOUSECLICK ---> MOUSEXY ---> FEET ---> FT (( MOUSEXY )) Tells x, y 'coordinate' of mouse pointer (only graphical mode) ---> MOUSECLICK ---> MOUSECLICKR ---> MMOTION ---> FEET ---> FT (( MUL )) Multiplication using whole numbers on main stack (( MUL2 )) Multiplication using 2, 4, 8, or 16, at main stack (( MUL4 )) (( MUL8 )) (( MUL16 )) NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN N (( N )) in: produces: flag comment on produces:::: the flag is the lowercase single-sized 'n' text which is, along with the corresponding 'y' flag, the right type of input not only to (MATCHED .. MATCHED) and = .. ===, but also to such routines as AND, ORR, XOR, NOT. ---> Y ---> YES (Y is a synonym to YES, and more often used) note1:::: One can make functions, rather than numerical variables, which can easily be changed by means of warps, which produces these flags directly on the stack (( N1 )) This is how to get the values of the local 11 topmost values (( N2 )) of simple stack (( N3 )) (( N4 )) (( N5 )) (( N6 )) (( N7 )) (( N8 )) (( N9 )) (( N10 )) (( N11 )) note1:::: N1 and N2 have very important functions in that they are an integral part of the way one does a (COUNT .. COUNTUP) loop. During such a loop, N1 refers to the present counter value, usually 1 and up to the maximum value, of the inmost (COUNT .. COUNTUP) loop. If there are several loops inside one another, one can get hold of the counter value of the next level by adding two to the index of N: N3 and N4 refers to the next level, N5 and N6 to the level outside there again -- on the premise that these (COUNT .. COUNTUP) loops are inside one another inside a single function definition. The N1 has, as said, the counter value. It can be adjusted by >N1 although that is rather uncommon to see inside typical (COUNT .. COUNTUP) loops. The N2 is its highest value, ie, the number given to (COUNT on entrance. This, too, can be changed, by >N2, but again that is rather uncommon to see inside typical (COUNT .. COUNTUP) loops. It is easy to exit a loop earlier than the highest value by having it inside a function which doesn't have much more around it, and call for the EXIT for the function together with a .. = .. === or (MATCHED .. MATCHED) syntax; or, if it is a function which has an important completing part, one can do a GOFORWARD4 if one does a GOLABEL4: further down inside the loop (as an example). However, when one does exit from inside the loop either by EXIT or GOFORWARD4 or in some similar way, one must do something like (( RMS RMS )) in order to reset the simple stack to its normal state -- before the counter and the maximum-value were put on top of it by the (COUNT .. COUNTUP) loop. If one does an EXIT or a GOFORWARD4 out of several loops inside one another, more RMS RMS are called for. There are of course ways of employing the simple stack in which one wouldn't need to do RMS RMS but this is at least the usual way. (( NAME-EQUAL )) in: row-1 row-2 start-column maximum-length matrix-warp produces: flag ---> NAME-GREATER (more connections and example program there) (( NAME-GREATER )) in: row-1 row-2 start-column maximum-length matrix-warp produces: flag comment on produces:::: in analogy with ---> INTGREATER ---> NAME-GTOREQUAL (in analogy to ---> INTGTOREQUAL), ---> NAME-EQUAL (in analogy to ---> INTEQUAL and ---> EQN) note1:::: The concept of 'NAME' in the Lisa formalism (except in the context of file name) is a very versatile and flexible one. It refers not just to any series of ascii 7-bit signs like the ones of which this list is composed, but to any series of columns of 32-bit signed numbers which can vary from about minus two billion to plus two billion as part of a matrix, in which you give the initial column number and a maximum length; and the series of numbers are considered to constitute a 'name' when they have either reached a zero in the next column, or have reached the maximum length (of course not beyond the maximum length, but it is important to always define matrices so that they have a couple of extra columns to the right to be consistent with the leisurely, luxurious approach in first-hand programming, and sometimes this has an algorithmic value, e.g. in using a matrix with file-saving/retrieval functions like ---> FILE2PM). note2:::: If you wish to store a very long decimal number with e.g. fourteen initial positions written in ascii zeroes, then a dot, and then fifteen decimal positions (God forbid!), then you can store these numbers inside column positions in a matrix and, in having many of them, instead of INTGREATER you use NAME-GREATER. note3:::: If you need to compare numbers of a wide range which also have optional zeroes in their middle which should not stop comparison you will have to play around in each case to find a suitable solution to this; it is the nature of first-hand programming languages to avoid too much zero-friendliness; if the numbers are all unsigned but very huge you might as well use a signed number to represent zero for no number will be lower than it anyway; doing such tricks is part of programming, you know -- relating to the boundaries: (LET NAME-GREATER-TEST BE (( )) (( (( }HI. WE ARE GOING TO TEST NAME-GREATER, AN ELEMENTARY NAME COMPARISON} => POP )) (( }ALGORITHM. CHANGE TO NAME-GTOREQUAL AND NAME-EQUAL FOR VARIATIONS.} => POP )) (( }WHAT WE ARE GOING TO DO IS TO MAKE A COUPLE OF LINES} => POP )) (( }INSIDE A SMALL MATRIX. THEN WE ARE GOING TO COMPARE} => POP )) (( }WHAT'S IN THESE LINES. OKAY ALL RIGHT. YES MAN.} => POP )) (( 105 ; 1000 => RAM-PM => & )) (( }THIS IS THE FIRST LINE} ; 1 ; # => TEXT>MATRIX )) (( }THIS IS ANOTHER LINE} ; 2 ; # => TEXT>MATRIX )) (( }THIS IS ANOTHER LINE} ; 3 ; # => TEXT>MATRIX )) (( }THIS IS ANOTHER} ; 4 ; # => TEXT>MATRIX )) (( STK )) (( }HERE ARE THE LINES IN THIS LITTLE TEST-MATRIX:} => POP )) (( 1 ; # => MATR>TEXT => POP )) (( 2 ; # => MATR>TEXT => POP )) (( 3 ; # => MATR>TEXT => POP )) (( 4 ; # => MATR>TEXT => POP )) (( }WE RUN THE TEST NAME-GREATER ON LINE 1 AND 2 (SHOULD SAY y):} => POPS )) (( ENTERPLS )) (( }TEST RESULT:} => POPS )) (( 1 ; 2 ; 1 ; 30 ; # => NAME-GREATER => POP )) (( }THEN WE RUN THE TEST NAME-GREATER ON LINE 3 AND 1 (SHOULD SAY n):} => POPS )) (( ENTERPLS )) (( }TEST RESULT:} => POPS )) (( 3 ; 1 ; 1 ; 100 ; # => NAME-GREATER => POP )) (( STK )) (( }HERE ARE AGAIN THE LINES IN THIS LITTLE TEST-MATRIX:} => POP )) (( 1 ; # => MATR>TEXT => POP )) (( 2 ; # => MATR>TEXT => POP )) (( 3 ; # => MATR>TEXT => POP )) (( 4 ; # => MATR>TEXT => POP )) (( }THEN WE RUN THE TEST NAME-GREATER ON LINE 2 AND 3 (SHOULD SAY n):} => POPS )) (( ENTERPLS )) (( }TEST RESULT:} => POPS )) (( 2 ; 3 ; 1 ; 100 ; # => NAME-GREATER => POP )) (( }THEN WE RUN THE TEST ON PARTS OF LINE 2 AND 3 (SHOULD SAY n):} => POPS )) (( ENTERPLS )) (( }TEST RESULT:} => POPS )) (( 2 ; 3 ; 3 ; 7 ; # => NAME-GREATER => POP )) (( && )) (( }PROGRAM COMPLETED.} => POP )) (( STK )) )) OK) (( LOOKSTK )) (( NAME-GTOREQUAL )) in: row-1 row-2 start-column maximum-length matrix-warp produces: flag ---> NAME-GREATER (more connections and example program there) (( NEXT-IN-LIST )) Move current pointer in list to next one ---> LIST (which has a lot more ---> connections for lists) (( NIRVANA )) As MANTRA, but copies up the 8th one instead (( NIRVANAR )) As MANTRAR, but copies up the 8th one instead (( NIRVANAS )) As MANTRAS, but copies up the 8th one instead (( NIRVANAV )) As MANTRAV, but copies up the 8th one instead (( NO )) ---> N (synonym, more often used) ---> AND ---> XOR ---> ORR note1:::: The use of N is clearer, because that is a static value, represented on the stack as lowercase single-letter 'n', whereas the word NOT is an operation, which inverts the static value 'n' to 'y' and back. So we don't use the word NO normally in Lisa. (( NOT )) Boolean, oh yeah ---> AND ---> ORR ---> XOR (( NOZ )) Nonzero check, but do we want to spell the ugly word 'zero'? nix. (( NUMBERS-TO-LIST )) Fetch numbers within a range from a text-line to LIST ---> LIST (which has a lot more ---> connections for lists) note1:::: Here is how it can be implemented: (LET NUMBERS-TO-LIST BE (( & >N7 >N8 ; )) (( (( ; } } => CONCAT )) (( ; => LENGTH )) (( }} => ANGEL ANGEL (COUNT (( N1 => CH => ISDIGIT (MATCHED (( ANGEL => SWITCH => CONCAT => SWITCH )) )(OTHER (( RM )) (( BRIDGE => TOLEN => NOZ (MATCHED (( SWITCH ; N10 ; N9 ; # => EXTEND-LIST-IF-WITH )) (( }} => SWITCH )) MATCHED) )) MATCHED) )) COUNTUP) )) (( RM RM )) (( && )) )) OK) OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO O (( ONE )) Copy the topmost on main stack (( ONER )) As ONE, but richstk (( ONES )) As ONE, but simplestack (( ONEV )) As ONE, but varstack (( ORR )) This three-letter word complements XOR, AND, NOT PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP P (( PEEK )) As MEM>, this goes by warp value directly into an array ---> %MAKE (important comment) (( PICK )) Picks the item as indicated by a number, and copy to top of stack (( PICKR )) For richstack (( PICKS )) For simplestack (( PICKV )) For varstack (( PM )) The prime minister of putting a value to a matrix ---> GM ---> %PUT (for GM is a compact form of %GET %PUT ) ---> RAM-PM ---> FORVPM ---> FORVPM2 note1:::: Synonym with PMATRIX in Firth, but that word rarely used (( PM2GJPFILE )) Parameters as PM2FILENUM, but for 200x200 byte matrices. note1:::: The .GJP format, GJ edition Packed format, involves 40.000 bytes instead of over half a megabyte which PM2FILENUM would make, and is standard. The notion of having resonance with a fixed vocabulary of fonts, images, art styles, music tapes, books and so on in a coherent civilisation is also dependent on a good file standard for art media. The suffix .GJP is to be used to indicate one such. Put maybe very many (for video documentaries) in a folder with a numbering/index approach to have a sequence. This is so native to the GJ2 etc LISACODE that it is handled with superb ease; and instead of making complicated long files, we just have many of these when we need more storage space, for larger images, for music, video, etc. Note that you can convert between .GJP and .TXT easily simply by using GJPFILE2PM and then, in some context, PM2FILENUM, and vice versa, but since .GJP is the binary format (ie, very packed), and only uses 0..255 number values, and only for 200x200 matrices, it is important to sustain also the original, full .TXT flexible forms, used e.g. for fonts, artgames etc. Please be careful with suffix and do not use .TXT command on .GJP or opposite. (( PM2FILE )) Put text-like matrix to file, give a number-like flag (do RM) ---> FILE2PM ---> PM2FILENUM ---> FILENUM2PM ---> FORVPM2 ---> CLEAR-MATRIX ---> FORVPM2 ---> (GJ editions) GJPFILE2PM ---> PM2GJPFILE note1:::: Many routines which one easily can make, along the lines of ---> MATR>TEXT, for instance, assumes that the first zero number encountered signals the completion of the text line in each row. Now the deep-level functions operating directly on the matrices, including this one, and ---> FORVPM2 and similar, contain no such assumption. So if there are rest-characters to the right of a zero number, you'd better clear them up before doing a PM2FILE; and the same before retrieving a new file with ---> FILE2PM. (( PM2FILENUM )) Store e.g. an image or sound matrix to a particular file note1:::: See practical comment at FILLNUMS. note2:::: See comment at ---> FORVPM2 for organising things so that this and ---> FILENUM2PM will work, as well as the very fast FORVPM2. note3:::: See ---> PM2GJPFILE if you have exactly 200x200 matrix of 0..255. (( POKE )) As >MEM, pokes by warp directly into an array ---> %MAKE (important comment) (( POP )) Put this item from mainstack to screen in textmode with CRLN after (( POPS )) As POP, but one space instead of line after (( POWERR )) The arithmetic power function at the rich stack (( PURUSHA )) As MANTRA, but seventh (( PURUSHAR )) As MANTRAR, but seventh (( PURUSHAS )) As MANTRAS, but seventh (( PURUSHAV )) As MANTRAV, but seventh (( PUTPAL )) After many WRITEPALs, this puts them into sudden effect (( PUTPIXEL )) This changes one pixel on the monitor QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ Q (( QSORT2 )) Sort an index over numerical values note1:::: By suitable use of NAME-SORT, you can adapt the version to work for texts. The advantage of an index is that it leaves all structure you may have associated with the values involved completely intact. For instance, you may have several matrices which are coordinated, row-wise. The indexes can then be made for this and that column. Having made such an index vastly facilitates searching on the content. I will spell out the QSORT2 which came from correcting the earlier QSORT on one point and remaking it to sort index rather than sorting the values directly and also give an exceptionally simplistic example, which should give you enough to go on. The QSORT2 is huge not because it is just what in conventional earlier computer science is called 'quicksort' (by Donald E. Knuth and earlier folks) but also because it incorporates a different type of sort once the subset is small enough, which works faster than quick sort for the small sort. This program, I must confess, is for me a cathedral. I go to it for meditation. I do not presume that it is easy to understand. Indeed, I am willing to go so far as to say that I do not presume it can be understood. It is a particularly nasty -- as well as beautiful -- example of just how most algorithms never should be written, and just for that reason, since it nevertheless stands erect, beautiful, and works so splendidly, with solidity, and the perfume of much computer science history incorporated into it -- it breaks with the categories: (LET THE-QSORT2-VERBOSE BE (( & & )) (( (( # => %LENGTH => STKTORICH => LOG2R => RICHTOSTK => TWICE ; 50 => ADD => MAKE_AUXSTK )) (( QS_BASIS => SETDANCE )) (( # => %LENGTH QS_UPPER <>> ; QS_BASIS >>> => SUB => INTGREATER (MATCHED (( QS_BASIS >>> ; QS_UPPER >>> => NOT_INTEQUAL (MATCHED (( QS_BASIS >>> => INC => >N2 )) O// (( N2 ; ## => %GET => >N8 )) (( N8 ; # => %GET => >N10 )) (( N2 => DEC => >N1 )) O// (( N1 ; ## => %GET => >N9 )) (( N9 ; # => %GET => >N11 )) (( N10 ; N11 => INTGTOREQUAL = GOFORWARD2 === )) (( N9 ; N1 => INC ; ## => %PUT )) (( N1 ; 1 => INTGREATER |C| )) (( DECN1 )) |A (( 0 >N1 )) (( GOLABEL2: )) (( N8 ; N1 => INC ; ## => %PUT )) (( QS_UPPER >>> ; N2 => INTGREATER |C| )) (( INCN2 )) |A MATCHED) (( HAS_AUXSTK_ELEMENTS => NOT = GOFORWARD4 === )) (( AUXSTK_FROM QS_BASIS <>> => INC ; QS_BASIS >>> ; QS_UPPER >>> => ADD => DIV2 ; ## => %SWITCH )) (( QS_UPPER >>> ; QS_BASIS >>> => INC => TWO ; ; ## => %GET ; # => %GET => SWITCH ; ## => %GET ; # => %GET => INTGREATER (MATCHED (( ; ; ## => %SWITCH )) )(OTHER (( RM RM )) MATCHED) (( QS_UPPER >>> ; QS_BASIS >>> => TWO ; ; ## => %GET ; # => %GET => SWITCH ; ## => %GET ; # => %GET INTGREATER (MATCHED (( ; ; ## => %SWITCH )) )(OTHER (( RM RM )) MATCHED) (( QS_BASIS >>> ; QS_BASIS >>> => INC => TWO ; ; ## => %GET ; # => %GET => SWITCH ; ## => %GET => # %GET => INTGREATER (MATCHED (( ; ; ## => %SWITCH )) )(OTHER (( RM RM )) MATCHED) (( QS_BASIS >>> => INC => >N1 )) (( QS_UPPER >>> => >N2 )) (( QS_BASIS >>> ; ## => %GET ; # => %GET => >N10 )) T// O// (( INCN1 )) (( N10 ; N1 ; ## => %GET ; # => %GET => INTGREATER |C| )) |A O// (( DECN2 )) (( N2 ; ## => %GET ; # => %GET ; N10 => INTGREATER |C| )) |A (( N1 ; N2 => INTGREATER (MATCHED |GNT| MATCHED) )) (( N1 ; N2 ; ## => %SWITCH )) |GT (( N2 ; QS_BASIS >>> ; ## => %SWITCH )) (( QS_UPPER >>> => INC ; N1 => SUB ; N2 => DEC => INTGTOREQUAL (MATCHED (( QS_UPPER >>> ; N1 => TO_AUXSTK )) (( N2 => DEC QS_UPPER < DEC ; QS_BASIS >>> => TO_AUXSTK )) (( N1 ; QS_BASIS <>> => %FREE )) (( && ; && )) )) OK) (LET THE-FITTING-VERBOSE BE (( => & ; & ; >N1 )) (( (( SWITCHV )) (( ## => %LENGTH => >N8 )) (( N8 => ISBASIS (MATCHED 0 ; && && ; EXIT MATCHED) )) (( 1 >N6 )) (( N8 ; N6 => SUB => INC => >N9 )) (( N9 => ISBASIS (MATCHED (( 0 ; && && ; EXIT )) MATCHED) )) (( GOLABEL4: (( N9 ; 2 => INTGREATER (MATCHED (( N1 ; N6 VALUE => INTGREATER ; N8 VALUE ; N1 => INTGREATER => AND (MATCHED (( N9 => DIV2 ; N6 => ADD => >N5 )) (( N5 VALUE ; N1 => INTGREATER (MATCHED N5 => >N8 )(OTHER N5 => >N6 MATCHED) )) (( N8 ; N6 => SUB => INC => >N9 )) (( GOUP4 )) )(OTHER (( N8 VALUE ; N1 => EQN (MATCHED (( N8 ; && && ; EXIT )) )(OTHER (( N6 VALUE ; N1 => EQN (MATCHED (( N6 ; && && ; EXIT )) )(OTHER (( 0 ; && && ; EXIT )) MATCHED) )) MATCHED) )) MATCHED) )) )(OTHER (( N9 => ISDANCE (MATCHED (( N6 VALUE ; N1 => EQN (MATCHED (( N6 ; && && ; EXIT )) )(OTHER (( 0 ; && && ; EXIT )) MATCHED) )) )(OTHER (( N8 VALUE ; N1 => EQN (MATCHED (( N8 ; && && ; EXIT )) )(OTHER (( N6 VALUE ; N1 => EQN (MATCHED (( N6 ; && && ; EXIT )) )(OTHER (( 0 ; && && ; EXIT )) MATCHED) )) MATCHED) )) MATCHED) )) MATCHED) )) )) )) OK) (LET INDEX-REFRESH BE (( & )) (( (( # => %LENGTH (COUNT (( N1 ; # => %PUT )) COUNTUP) )) (( && )) )) OK) (LET INDEX-MAKE BE (( >N1 )) (( (( N1 => %MAKE => ONE => INDEX-REFRESH ; => => )) )) OK) (LET FITTING-TEST BE (( )) (( (( 72 ; 100000 => MAKETWO => & ; & )) (( }UNSORTED LIST OF 30 ITEMS:} => POPS )) (( # ; ## => SEEBYINDEX )) (( ENTERPLS )) (( }SORTING..} => POPS )) (( # ; ## => THE-QSORT2-VERBOSE )) (( ENTERPLS )) (( }SORTED LIST OF 30 ITEMS:} => POPS )) (( # ; ## => SEEBYINDEX )) (( ENTERPLS )) (( GOLABEL4: )) (( }ENTER ITEM TO SEARCH FOR (0 TO QUIT):} => POPS )) (( READLN => >N1 )) (( N1 => ISBASIS (MATCHED (( # => %FREE )) (( ## => %FREE )) (( && ; && )) (( LOOKSTK ; VARSTK )) (( EXIT )) MATCHED) )) (( N1 ; # ; ## => THE-FITTING-VERBOSE => >N2 )) (( }ANSWER FROM BINARY SEARCH:} => POPS )) (( N2 => POP )) (( GOUP4 )) )) OK) (( LOOKSTK )) So, the above is a performable program. Since you have this document presumably as part of your Lisa platform, you can copy and put it to a separate new document (in the F9 editor, you do this by opening the editor by the F9 command instead of the WORD command, so it is in read/write mode, then mark and clip, open up a new document with a name which doesn't yet exist, and put it in there -- or something like that). The word FITTING-TEST will run the program, which should work eminently by using the word QSORT2 and the word FITTING instead of the two -VERBOSE versions included here. The B9 editor is more than F9 for it takes us, in the GJ2 edition, towards a more cautious, well-controlled, meaningful form of browsing between new types of hardware, using a NAME-GREATER type of comparison with a NAME-QSORT2 and NAME-FITTING RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR R (( RAM-PM )) in: number1 number2 produces: warp comment on in:::: number1 is amount of columns, number2 is amount of rows comment on produces:::: warp is the matrix, one often calls & after it ---> CLEAR-MATRIX (after PM and GM when you want it like a newborn baby) ---> %EMPTY (can be used to clear row, e.g. (( N1 ; # => %GET => %EMPTY )) ---> PM ---> GM ---> FILENUM2PM ---> PM2FILENUM ---> FILE2PM ---> PM2FILE ---> RELEASE-MATRIX ---> FITTING (for associated value arrays etc) ---> FORVPM2 (for very efficient looping using warps) note1:::: Here's an example (which may or may not be accurate relative to how the textmode-based F9 editor is implemented in practise): (LET F9-START BE (( )) (( (( FREE-CLS )) (( CRLN ; CRLN )) } This textmode typewriter / in-PC browser F9, is an integral part of Lisa} => POP )) (( F9-INIT-VARS )) (( F9-FILE-TO-START-SHOWING => VARSTR> ; F9-DOC-NAME => >VARSTR )) (( } ****INITRAM*****} => POP )) (( 79 ; 280 => RAM-PM F9-CLIPBOARD < POP )) (( 79 ; 35005 => RAM-PM F9-WORK-SPACE < POP )) (( F9-FETCH-FILE )) (( } ***} => POP )) (( F9-LINE-NUM => SETDANCE )) (( F9-LINE-POS => SETDANCE )) (( F9-TOP-OF-PAGE-LINE-NUMBER-SHOWN => SETDANCE )) (( F9-EDIT-TOP-LEFT )) (( CLEAR_KEYBUF )) (( F9-STD-FRAME )) (( F9-REDISPLAY-ALL-TEXT-HERE )) (( F9-MAYBE-UNDERLINE )) (( F9-TYPEWRITER-NORMAL )) (( F9-MAYBE-STORE-FILE )) (( RAM-REFRESH )) )) OK) note2:::: You can make 50-dimensional structures if you like and somehow get them to look like something matrix-like anyway. For instance, it can be but one or two long rows. See comment at ---> %MAKE. You can make the matrix yourself by looking into how RAM-PM is made. Here it is: (LET RAM-PM BE (( >N5 >N4 )) (( (( N5 %MAKE => & )) (( N5 (COUNT (( N6 => %MAKE => ; N1 ; # => %PUT )) COUNTUP) )) (( # => => )) (( && )) )) OK) If that is not simple, then nothing is. note3:::: For very large matrices, e.g. tens of thousands of rows with a hundred or so columns, do pls check the duration it requires to perform a RAM-PM. Instead of doing RELEASE-MATRIX followed by a new RAM-PM for huge matrices it is probably much, much faster to do CLEAR-MATRIX when a program needs to sustain a large work space (such as the F9 editor), and it is a good praxis to advise the interactor with the computer during program startup that the initialisation is taking place -- so that if a too tiny computer is being used, one will know that it is its tininess rather than the program syntax which is causing the program to stop or be inconveniently slow. note4:::: An easy example: (( 200 ; 1000 => RAM-PM => & )) (( 234234 ; 1 ; 1 ; # => PM )) (( 345435 ; 1 ; 2 ; # => PM )) (( 2334599 ; 200 ; 1000 ; # => PM )) (( 1 ; 2 ; # => GM => POP )) (( 200 ; 1000 ; # => GM => POP )) (( # => RELEASE-MATRIX )) note5:::: One may call RAM-PM directly and outside of a function, which may mean, if it is in a program .TXT file, that the RAM is allocated while the program compiles. This is fine. For very very large matrices this will mean some pause, esp. at some machines; it can be a great idea to make sure that the matrix is always big, and it is a law that it should be wider than necessary by at least two columns, and yet think through how big it really needs to be. note6:::: It is a good programming practise to either reuse a matrix or array once it has been created, or call RELEASE-MATRIX (or for arrays, %FREE), before one creates a new one of the same kind. It is in Lisa assumed that one wants the computer to refresh RAM completely at program exit. It is as such completely normal to not call on RELEASE-MATRIX and/or %FREE right before one does XO, completing the program; but it is of great importance to do so if one creates many large matrices inside program run, each of which are used only once then not more. note7:::: A matrix is a convenient way to describe an array of arrays. Since the warps of all things between heaven and earth are directly available to the programmer one can create other types of matrices than just an array full of same-length arrays. For instance, one can have an array of variable length arrays, or an array of an array of an array of an array of matrices. In such cases, one will perhaps use some of the convenient algorithms PM, GM, RAM-PM, RELEASE-MATRIX and so on, but in a natural way one will use %MAKE and %FREE and %GET and %PUT and such to make these algorithms and connect them up to one another. However, when one uses PM2FILE or other functions which presume a certain matrix structure one must check whether one can indeed do so in each case where one has made an unconventional matrix. (( RAM-REFRESH )) Completing the run of a textmode program ---> XO ---> GJ-DONE note1:::: GJ-DONE is the proper completion of a graphical program, but RAM-REFRESH is called on for textmode programs (( READLN )) Read, in textmode, one line of whatever up until ENTER (( READPAL )) This fetches the value from the current monitor palette ---> WRITEPAL ---> PUTPAL (( RECENT-IN-LIST )) Put pointer in list to the completing value in it ---> LIST (which has a lot more ---> connections for lists) note1:::: This is how it might be implemented: (LET RECENT-IN-LIST BE (( & )) (( (( 1 ; # => %GET => INC => INC ; 2 ; # => %PUT )) (( && )) )) OK) (( RECT )) Makes a rectangle, in the graphical mode (( RECTFILL )) Like RECT, but fills up with a color (( RELEASE-MATRIX )) Completely let go of a RAM-PM style of matrix, free RAM ---> %MAKE ---> CLEAR-MATRIX ---> %FREE (( REMOVEDOT )) Remove dots (.) inside a main stack item (( REMOVE )) Remove a particular numbered item on the main stack (( REMOVER )) For richstk (( REMOVES )) For simplestack (( REMOVEV )) For varstk (( RFFG )) Produce a relatively free fluctuation generated number ---> %RFFG ---> FR ---> MOD ---> FREE-B note1:::: Don't overuse artificial noise-making, ever. (( RICH )) Clear up a number in: text produces: text comment on in:::: The text input is of the kind +100,000, in other words, an ordinary number but with additional characters beyond the ordinary comment on produces:::: The text output is exactly similar but with anything beyond ordinary number signs removed; this might be a number but it can also be a larger series of digits than a 32-bit number, that's why we write 'text' also as its output. ---> EXTRACTNUMBERSTUFF (synonym) ---> EXTRACTNUMBER ---> HEAL ---> RMBL ---> FIX-NUMBER ---> REMOVEDOT note1:::: The word reflects a relaxed, leisurely, affluence oriented way of writing numbers when compactness and speed of the particular position in a function is not an issue, in which one can write e.g. (( 1,000,000,000 => RICH MY-INCOME < RICHSTK. In the case of the RICHSTK, we are talking of decimal numbers which can be written like $234234.33 whereas in the case of the translator RICH we are talking of getting rid of syntactically useless commas in large numbers like 3,333,123. Of course, the word is a positive one -- we want affluence, wealth, the sense of the richness and abundance, both of love and as availability of material goods of various sorts, and LISA likes positive affirmations. note3:::: This is an alternative way of writing ---> EXTRACTNUMBERSTUFF note4:::: The 32-bit number range, plus/minus 2,000,0000,000, applies of course to any 32-bit whole number variable defined with ((DATA .. )) but the RICH function can handle up to a whole textline of digits. You can store this sequence, if you like, e.g. in a (( VARSTRING .. )) or, digit by digit, in an array made with ---> %MAKE or a matrix with ---> RAM-PM. You can then also make routines, of course, which does some kind of operations on these digits such as addition. (( RICHSTK )) A programmer's informal tool, show the rich stack content ---> STK ---> VARSTK ---> LOOKSTK ---> STKTORICH ---> RICHTOSIMPLE (( RICHTOSIMPLE )) Move from richstk to simplestk note1:::: Prepare the number before translating it towards 32-bit whole number stack. (( RICHTOSTK )) Move from richstk to main stack ---> STKTORICH (( RICHTOVAR )) Move from richstk to varstk (( RM )) Discard topmost item on main stack ---> SEVERALRM (( RMR )) For richstk (( RMV )) For variable stack (( RMBL )) Remove blanks in text on main stack (( ROUNDR )) Round number on rich stack ---> UP-TO-EVEN ---> UP-TO-HIGHER-EVEN ---> UP-TO-EVEN8 SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS S (( SELECTR )) Get this numbered item on rich stack moved to the top (( SELECTS )) Get this numbered item on simple stack moved to the top (( SELECTV )) Get this numbered item on var stack moved to the top (( SET-CURRENT-POS-IN-LIST )) Change current pos in list to this ---> LIST (which has a lot more ---> connections for lists) (( SET-RANGE )) Ensure that whole number value is within n..m, incl. n and m (( SETBASIS )) Change the value of variable to zero (avoiding that word) (( SETDANCE )) Change the value of variable to one (( SETLENGTH )) Change length of main stack item to this (( SETWARPADDRESS )) After GETFUNCNUM for a defined word, redefines action ---> GETFUNCNUM ---> ? ---> H note1:::: The basic integrity of the most native words of Lisa (and Lisa firth) is preserved by not trying to apply it to Lisa; and it is not programmed to function if applied it to the Firth level. Use it for your own highlevel words. (( SEVERALRM )) A quicker way when many RM should be done ---> RM note1:::: When speed is an issue, e.g. in sorting or searching over very many tens of thousands of items, each perhaps involving subloops, then nuances can make a noticable difference. Normally, in first-hand programming, one affirms that one should stay well within the boundaries of the rapid natural speed of the more or less Y2000-similar computer, or the GJ computer as standardized hardware for the Lisa programming language in the future GJ editions. But due to to the nature of number conversion between the text-oriented main stack and e.g. the number-oriented simple-stack, an operation like 33333 >N1 has a different speed than 33333 ONE. As for an operation like 5 => SEVERALRM, it is probably faster than five RM after one another, yet probably much the same as three or four RM. In any case, 5 => SEVERALRM, and even more so when higher, looks a great deal better than RM five or more times after one another. Goodlookingness is part of first-hand programming, too. In the case of 3 => SEVERALRM, I suppose RM RM RM and it is about the same. note2:::: If you do some advanced correction of a program which is a bit complicated and you notice something which indicates that a command like (( 5 => SEVERALRM )) doesn't have an effect, whereas, if you substitute with (( RM ; RM ; RM ; RM ; RM )), then it is probably a simple explanation: the (( 5 => SEVERALRM )) is a unit of a command which has either the asserted, normal effect, or, if it does not find enough items on the main stack to has this effect, has no effect whatsoever. Plenty but not all of the functions in Lisa are made in this fashion -- and certainly most of the Firth basis subset of Lisa -- they do nothing at all (not even complain) if there is insufficient amounts of parameters on the stacks. To make this a bit more precise in this context, a succession of RM commands are not the exact identical thing as a suitable SEVERALRM, for each RM will attempt to remove but one item on the stack at the time. If there are fewer item than assumed, the succession of RM will remove what it can remove but not more. However, using SEVERALRM will help you to correct the program so it does not have such confusing elements as functions which do not have enough parameters, in such a case. (( SG )) Change positive to negative or negative to positive on main stack (( SHOW-LIST )) Programmer's tool for checking content of a list ---> LIST (which has a lot more ---> connections for lists) note1:::: This is how it might be implemented: (LET SHOW-LIST BE (( & )) (( (( }POPS} => ? ; # => LOOP-THROUGH-LIST )) (( && )) )) OK) (( SHOW-LIST-REVERSE )) As SHOW-LIST, but opposite way ---> LIST (which has a lot more ---> connections for lists) note1:::: This is how it might be implemented: (LET SHOW-LIST-REVERSE BE (( & )) (( (( }POPS} => ? ; # => CONVERSE-THROUGH-LIST )) (( && )) )) OK) (( SIMPLETORICH )) Move from simplestack to richstk (( SIMPLETOVAR )) Move from simplestack to varstack (( SEVERAL( )) Print many of these characters directly on monitor in textmode (( SIMPLESTK )) Informal tool for the programmer to see simplestack (txtmode) (( SIN )) Sinus function operating on the main stack note1:::: Use ---> SINR or check very carefully when doing decimal operations on main stack, because the result may contain the E-notion and this result is not suitable input number except when already on the richstack. The main stack is standardized towards whole numbers of the 32-bit kind. (( SINR )) Sinus function on its proper decimal stack (( SIX )) Copy six topmost items (( SIXR )) For richstk (( SIXS )) For simplestk (( SIXV )) For varstk (( SLENDER-LIST )) Make list one shorter and possibly update current position ---> LIST (which has a lot more ---> connections for lists) (( SOLIDCURSOR )) Affirms a solid blinking cursor in textmode (normally on) (( SPACE )) Make one space in text-mode come to monitor (( SPACES )) Make this many spaces to monitor in text-mode (( SPOP )) Print a bunch of left-margin-like spaces then do an ordinary POP (( SPOPS )) Like SPOP, but an ordinary POPS instead of POP is done (( SQUARE )) Square of that number (( SQUARES )) On simplestack (( START-IN-LIST )) Puts current position in a LIST defined list to beginning ---> LIST (which has a lot more ---> connections for lists) note1:::: This is how it might be defined: (LET START-IN-LIST BE (( & )) (( (( 3 ; 2 ; # => %PUT )) (( && )) )) OK) (( STKTORICH )) Move from main stack to rich number stack (for decimals) ---> RICHTOSTK (( SQRT )) Square root at main stack ---> SQRTR (often preferrable to go through richstk for decimal operators) (( SQRTR )) Square root at rich stack ---> SINR ---> COSR ---> TANR ---> SQRT ---> RICHTOSTK (( SQUARER )) Square at rich stack (( STK )) A programmer's tool to look at present main stack content (txtmode) (( STKTOVAR )) Moving from stack to variable stack ---> >>V ---> & (( STR>ARRAY )) Make a new array of same length & content as text string note1:::: This one removes the text after making the array. It can be implemented as follows: (LET STR>ARRAY BE (( ; )) (( (( ; => LENGTH => %MAKE => & )) (( LENGTH (COUNT (( ; N1 => CHN ; N1 ; # => %PUT )) COUNTUP) )) (( # => => )) (( && )) )) OK) (( STR>EXISTING-ARRAY )) Put content to preinitialized array, adjust %length note1:::: It removes the text after making the array. It presupposes that there is plenty of space in the array. The %LENGTH is adjusted to fit with the size of the string (can be zero, too). It can be implemented as follows: (LET STR>EXISTING-ARRAY BE (( & ; )) (( (( LENGTH ; # => >MEM )) (( # => %LENGTH (COUNT (( ; N1 => CHN ; N1 ; # => %PUT )) COUNTUP) )) (( RM )) (( && )) )) OK) (( SUB )) To substract one from the other on main stack, use this (( SUBR )) Decimal number substraction on the rich stack (( SWITCH )) A vital function: On the mainstk, switch the two uppermost (( SWITCHR )) For richstk (( SWITCHV )) For variable stack TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT T (( TAN )) Tangens, but on main stack ---> TANR (( TANR )) Tangens arithmetic function on the proper rich stack ---> SINR ---> COSR ---> ARCTANR ---> ARCSINR ---> ARCCOSR ---> TAN (( TANTRA )) Make a copy of third on the stack and put it to the top (( TANTRAR )) For richstk (( TANTRAS )) guess what, for simplestack (( TANTRAV )) is this dictionary soon done? For varstack (how long from T->Z?) (( TEQ )) As for TEST, but this one works with texts. See example ---> EQ ---> TEST (for numbers) note1:::: (LET I9-MODIFY-IMAGE BE (( )) (( (( I9-IMAGE >>> => & )) (( CLS )) (( }Anarchistic mutations which can be friendly towards first-hand photoart work} ; 50 ; 75 => B9-POP )) }Images respond somewhat differently; use your intuition; have fun!!!} ; 50 ; 100 => B9-POP )) (( }B brighten colors} ; 25 ; 150 => B9-POP )) (( }D deeper colors} ; 25 ; 175 => B9-POP )) (( }E enhance contrast} ; 25 ; 225 => B9-POP )) (( }Y focus top left} ; 25 ; 275 => B9-POP )) (( }R rotate 90 degrees} ; 25 ; 300 => B9-POP )) (( }I invert colors} ; 25 ; 250 => B9-POP )) (( }M mirror image} ; 25 ; 325 => B9-POP )) (( }X exclude transparent} ; 25 ; 425 => B9-POP )) (( }1 one tone only} 50 ; 475 => B9-POP )) (( }Z matt & smooth} 275 ; 475 => B9-POP )) (( }U permute up} ; 50 ; 500 => B9-POP )) (( }P permute other} ; 50 ; 525 => B9-POP )) (( }A add texture} ; 50 ; 550 => B9-POP )) (( }C collect} ; 275 ; 500 => B9-POP )) (( }O collect other} ; 275 ; 525 => B9-POP )) (( }S shift} ; 275 ; 550 => B9-POP )) (( }2 zing} ; 50 ; 575 => B9-POP )) (( }3 only texture} ; 50 ; 600 => B9-POP )) (( }W wild edges} ; 275 ; 575 => B9-POP )) (( }4 odd lucidity} ; 275 ; 600 => B9-POP )) (( }V vaguer} ; 50 ; 625 => B9-POP )) (( }The spring-art color light green} ; 575 ; 500 => B9-POP )) (( }is preferred in these actions} ; 575 ; 530 => B9-POP )) (( }because of angelic assocations} ; 575 ; 560 => B9-POP )) (( }Listen to your heart beyond theory; sense} ; 480 ; 615 => B9-POP )) (( }the rich variety of free associations;} ; 480 ; 645 => B9-POP )) (( }have the intent of harmony and health.} ; 480 ; 675 => B9-POP )) (( }Save only that which you feel good about.} ; 480 ; 705 => B9-POP )) (( }*} ; 973 ; 10 => B9-POP )) (( }Q to main menu} ; 50 ; 700 => B9-POP )) (( I9-NEW )) (( GOLABEL1: )) (( CLEAR_KEYBUF )) (( KEY => UPCM ; )) (( }***} ; 571 ; 450 => B9-POP )) (( ; :U TEQ => = I9-IMAGEPERMUTE-UP == :P TEQ => = I9-IMAGEPERMUTE == :A TEQ => = I9-IMAGEADD-TEXTURE == :C TEQ => = I9-IMAGECOLLECT == :O TEQ => = I9-IMAGECOLLECT-OTHER == :S TEQ => = I9-IMAGESHIFT == :B TEQ => = I9-IMAGEBRIGHTEN-COLORS == :D TEQ => = I9-IMAGEDEEPER-COLORS == :Z TEQ => = I9-IMAGEMATT-SMOOTH == :E TEQ => = I9-IMAGEENHANCE-CONTRAST == :I TEQ => = I9-IMAGEINVERT-COLORS == :R TEQ => = I9-IMAGEROTATE-90 == :M TEQ => = I9-IMAGEMIRROR-IMAGE == :X TEQ => = I9-IMAGEEXCLUDE-TRANSPARENT == :1 TEQ => = I9-IMAGEONE-TONE-ONLY == :2 TEQ => = I9-IMAGEZING == :3 TEQ => = I9-MAKE-TEXTURE-LINES == :W TEQ => = I9-IMAGEWILD-EDGES == :4 TEQ => = I9-IMAGEODD-LUCIDITY == :V TEQ => = I9-IMAGEVAGUER == :Y TEQ => = I9-IMAGEFOCUS == :Q EQ => = GOFORWARD4 === === === === === === === === === === === === === === === === === === === === === === )) (( } } ; 571 ; 450 => B9-POP )) (( GOUP1 )) (( GOLABEL4: )) (( && )) )) OK) (( TEST )) As TEQ, but for numbers: copies when it is not equal (see example) ---> AFFIRM ---> TEQ note1:::: Here's the example, with a lot of other words which may or may not be defined in this way in a future edition of GJ: (LET PALETTE-EDITOR BE (( )) (( (( VLOTS )) (( 1 => TOV9 )) (( 2 => TOV10 )) (( 800 ; 600 => GET-CENTERED-FRAME-COOR => >N4 >N3 >N2 >N1 )) (( N1 N2 N3 N4 => DO-MAYBE-SAVE-SCREEN )) (( }PALETTE EDITOR -- CYCLIC COLORS} N1 N2 N3 N4 => FT MAKE-FRAME FEET )) (( N1 502 ADD => >N7 )) (( N2 79 ADD => >N8 )) (( }R} ; 25 ; N7 ; N8 ; 220 => FT SKETCH-SLIDER FEET )) (( }G} ; 25 ; N7 ; N8 50 ADD ; 220 => FT SKETCH-SLIDER FEET )) (( }B} ; 25 ; N7 ; N8 100 ADD ; 220 => FT SKETCH-SLIDER FEET )) (( SLIDER-NORMALIZE-VALUE >>> PALETTE-EDITOR-R <>> PALETTE-EDITOR-G <>> PALETTE-EDITOR-B < FT FRAME-XY-POP FEET )) (( }CLICK, OR RIGHT-CLICK TO MOVE} ; N1 20 ADD ; N2 525 ADD => FT FRAME-XY-POP FEET )) (( }OR CLICK TO SELECT COLOR} ; N1 20 ADD ; N2 550 ADD => FT FRAME-XY-POP FEET )) (( }COLORS:} ; N1 425 ADD ; N8 150 ADD => FT FRAME-XY-POP FEET )) (( }#64 MOUSE OUTLINE} ; N1 425 ADD ; N8 175 ADD => FT FRAME-XY-POP FEET )) (( }#255 IS ITS COLOR} ; N1 425 ADD ; N8 200 ADD => FT FRAME-XY-POP FEET )) (( }#0 IS BACKGROUND} ; N1 425 ADD ; N8 225 ADD => FT FRAME-XY-POP FEET )) (( }#1 IS FOREGROUND} ; N1 425 ADD ; N8 250 ADD => FT FRAME-XY-POP FEET )) (( }CLICK P TO RANDOMIZE} ; N1 20 ADD ; N2 450 ADD => FT FRAME-XY-POP FEET )) (( 16 (COUNT 16 (COUNT N5 N1 22 MUL ADD INC16 INC8 ; N6 N3 22 MUL ADD INC32 INC8 ; BRIDGE 21 ADD ; BRIDGE 21 ADD ; N3 DEC ; 16 => MUL ; N1 DEC => ADD => FT RECTFILL FEET COUNTUP) COUNTUP) (( GOLABEL1: )) (( }SELECTED COLOR NOW: #} V10 } } CONCAT CONCAT ; N1 20 ADD ; N2 475 ADD => FT FRAME-XY-POP FEET )) (( N1 N2 V10 => PALETTE-EDITOR-UPDATE-RGB-INFO )) (( N1 640 ADD ; N8 320 ADD ; BRIDGE 120 ADD ; BRIDGE 120 ADD ; V10 => FT RECTFILL FEET )) (( GOLABEL4: (( KEYTOUCH = KEYNUM 13 TEST = GOFORWARD3 == 27 TEST = GOFORWARD2 == 82 TEST = 1 => TOV9 == 71 TEST = 2 => TOV9 == 66 TEST = 3 => TOV9 == 80 TEST = RANDOMIZE-PALETTE == 114 TEST = 1 => TOV9 == 103 TEST = 2 => TOV9 == 98 TEST = 3 => TOV9 == 112 EQN = RANDOMIZE-PALETTE == === === === === === === === === === === === )) (( MOUSECLICK => Y-TO-1 => TOV4 )) (( MOUSECLICKR => Y-TO-1 => TOV6 )) (( V4 ISDANCE ; V6 ISDANCE => ORR (MATCHED (( MOUSEXY => TOV2 ; TOV1 )) (( V4 => ISDANCE (MATCHED (( V1 ; N1 49 ADD ; ONE 16 22 MUL ADD => WITH ; V2 ; N2 60 ADD ; ONE 16 22 MUL ADD => WITH => AND (MATCHED (( V2 N2 SUB 40 SUB ; 22 DIV => DEC => 16 MUL ; V1 N1 SUB 24 SUB ; 22 DIV => DEC => ADD => TOV7 )) (( V7 0 255 => WITH (MATCHED V7 => TOV10 ; GOUP1 MATCHED) )) )(OTHER (( V10 ; V9 1 TEST = MORE-RED == 2 EQN = MORE-GREEN == MORE-BLUE === === )) (( 2 => TOV8 )) MATCHED) )) )(OTHER V6 => ISDANCE (MATCHED (( V10 ; V9 1 TEST = RM-RED == 2 EQN = RM-GREEN == RM-BLUE === === )) (( -2 => TOV8 )) MATCHED) MATCHED) (( PUTPAL )) (( V9 1 TEST = (( PALETTE-EDITOR-R >>> )) (( SLIDER-FULL-VALUE >>> ; V8 ; PALETTE-EDITOR-R => ADDVAR-WITHIN )) (( PALETTE-EDITOR-R >>> )) == 2 EQN = (( PALETTE-EDITOR-G >>> )) (( SLIDER-FULL-VALUE >>> ; V8 ; PALETTE-EDITOR-G => ADDVAR-WITHIN )) (( PALETTE-EDITOR-G >>> )) == (( PALETTE-EDITOR-B >>> )) (( SLIDER-FULL-VALUE >>> ; V8 ; PALETTE-EDITOR-B => ADDVAR-WITHIN )) (( PALETTE-EDITOR-B >>> )) === === )) (( => ; => ; 25 ; N7 ; N8 V9 DEC 50 MUL ADD ; 220 => NEW-SLIDER-VALUE )) (( N1 N2 V10 => PALETTE-EDITOR-UPDATE-RGB-INFO )) (( CLICK-DURATION >>> GOODPAUSE )) MATCHED) )) GOUP4 )) (( GOLABEL2: (( N1 N2 N3 N4 => DO-MAYBE-RESTORE-SCREEN-AND-PAL )) (( FEET )) (( VFREE ; EXIT )) )) (( GOLABEL3: (( N1 N2 N3 N4 => DO-MAYBE-RESTORE-SCREEN )) (( FEET )) (( VFREE ; EXIT )) )) )) OK) (( TEXT>MATRIX )) Put a line at main stack ascii-num by ascii-num into a PM ---> NAME-GREATER provides a good example of this. (( THIS-IN-LIST )) Get value from the present position in the LIST. in: warp produces: comment on in:::: comment on produces:::: ---> LIST (which has a lot more ---> connections for lists) (( THREE )) Copy three topmost on main stack and put back to main stack (( THREEV )) As THREE, but for varstk (( TICKS )) Show (the perhaps not very precise) CPU oscillator timing device ---> GOODPAUSE (( THREER )) As THREE, but for richstk (( THREES )) As THREE, but for simplestk (( TOCH )) Put a character into something on the main stack (text/number) (( TOCHN )) Put the character corresponding to this asciinum into text (( TOLEN )) As LENGTH, but removes the item which LENGTH preserves (( TOV1 )) These are practical inside FORVPM2 to get new values quickly (( TOV2 )) into particular positions of the varstack (which are ordinarly (( TOV3 )) already allocated -- this happens automatically for FORVPM2); (( TOV4 )) if they are called in a context where such allocation has not (( TOV5 )) already occurred, the varstack will be filled up with extra (( TOV6 )) values to accomodate this, and one is advised to, as a rule, (( TOV7 )) only use these on carefully pre-allocated slots on the varstack -- (( TOV8 )) due to resulting program clarity, of course. (( TOV9 )) (( TOV10 )) (( TOV11 )) (( TRIPLEAND )) As AND, but takes three input flags instead of two (( TRIPLEORR )) As ORR, but takes three input flags instead of two (( TWICE )) Doubles the whole number value on stack (( TWICER )) As TWICE, but for richstk (( TWICES )) As TWICE, but for simplestack (( TWO )) Copy the topmost pair of mainstack, and put back to mainstack (( TWOR )) As TWO, but for richstk (( TWOS )) As TWO, but for simplestk (( TWOV )) As TWO, but for varstk (( TXTEQUAL )) Are the main stack items exactly equal? ---> NAME-EQUAL ---> INTEQUAL ---> EQ UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU U (( UNCOMPUTER )) Look at how defined functions are compiled (( UP-TO-EVEN )) Move value up to even number, if it is not there already ---> UP-TO-EVEN8 (( UP-TO-EVEN8 )) Move value up to a still higher even, divisble by eight (( UP-TO-HIGHER-EVEN )) Move value up to 'higher even', divisible by four ---> UP-TO-EVEN ---> UP-TO-EVEN8 (( UPCM )) UPerCase on Mainstack, viz., abcdefghijklmnopqrustuvwxyz to upper (( UPCNUM )) An individual asciinum on stack is uppercased VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV V (( V>> )) Delete value from varstack, normally put there by >>V note1:::: Despite its appearance, it just removes from the varstack, rather than retrieves from it. To retrieve from it, try # to copy from the stack, or GETV to move it over. Yet it is the feeling of this author that the symmetry is very nice, when >>V is used instead of &, that, instead of && to remove from the stack, V>> looks darn good. (( V1 )) When many values of varstack have been initialized, these (( V2 )) fetches them, and produces a copy on main stack (( V3 )) (( V4 )) (( V5 )) (( V6 )) (( V7 )) (( V8 )) (( V9 )) (( V10 )) (( V11 )) ---> # ---> ## ---> ### ---> #### ---> & ---> >>V ---> V>> ---> V1UP (( V1UP )) Add to V1 or V2 etc. (( V2UP )) (( V3UP )) (( V4UP )) (( V5UP )) (( V6UP )) (( V7UP )) (( V8UP )) (( V9UP )) (( V10UP )) (( V11UP )) (( VARSTK )) An informal tool for the programmer, to see values at varstack ---> LOOKSTK (see comment here) (( VARSTR-CHN )) Fetch this ascii number from this position in VARSTRING var (( VARSTR-DECLEN )) Take one char off the VARSTRING variable (( VARSTR-EXPAND )) Expand length of VARSTRING variable with this asciinum (( VARSTR-INCLEN )) Increase the length of a varstring variable (( VARSTR-LEN )) Fetch length directly from a VARSTRING variable (( VARSTR-SETBASIS )) Set length to zero of a VARSTRING variable (( VARSTR-SETLEN )) Fix on the length directly in an initialized VARSTRING (( VARSTR-TOCHN )) Put this ascii number straight into a VARSTRING variable (( VARSTR> )) Fetch value from this variable which has been made by VARSTRING (( VARSTRING )) VARSTRING XXX a variable of variable length 0-250 characters ---> >VARSTR ---> VARSTR> ---> ((DATA ---> PEEK ---> POKE ---> VARSTR-CHN ---> VARSTR-DECLEN ---> VARSTR-EXPAND ---> VARSTR-INCLEN ---> VARSTR-LEN ---> VARSTR-SETBASIS ---> VARSTR-SETLEN ---> VARSTR-TOCHN ---> %MAKE ---> RAM-PM (when longer texts are called for) ---> (( VARSTRING )) to store text lines, including filenames note1:::: It is strongly recommended that each program begins with ((DATA .. )) and (( VARSTRING .. )) definitions before the first function definitions, for clarity. Actions (viz., functions) must be divided from storage places. (( VARTORICH )) Moves from variable stack to rich stack (( VARTOSTK )) Moves from variable stack to main stack ---> GETV ---> # (the latter but copies) (( VARTOSIMPLE )) Move directly from variable stack to simple stack (( VFREE )) Used after VLOTS, prior to FORVPM2, and the like. note1:::: When VLOTS .. VFREE have been used, go directly to the function which makes its own VLOTS .. VFREE zone; if you call on other things in between, you have got to do a lot of careful checking on what's really occurring to the varstack then. (( VISBASIS )) A main function: it checks whether variable equals 0 (basis) ---> ISBASIS (see note on program correction) ---> VISDANCE (( VISDANCE )) A main function: it checks whether variable equals 1 (dance) ---> ISDANCE ---> ISBASIS (see note on program correction) (( VISIBLECOMPILATION )) Let program text be visible while it's compiled ---> INVISIBLECOMPILATION ---> COMPILEFAST ---> COMPILEPAUSED ---> LOOKSTK ---> AUTOSTART (( VLOTS )) Use VLOTS .. VFREE prior to calls to FORVPM2 to set startvalues WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW W (( WITH )) Is the present whole number within the range n..m? ---> SET-RANGE ---> EXTEND-LIST-IF-WITH (( WRITEPAL )) Before PUTPAL, a group of WRITEPAL affects the monitorpalette ---> PUTPAL XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X (( XOR )) One of the key four or five boolean operations, exclusive or (( XY-POP )) One of the systemic background thingies for system font note1:::: It is recommended to use the coherently harmonious and pleasantly artistic/anarchistic B9 font and let only things which has the flavour of operating system use the uppercase standard lisafont YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY Y (( Y )) Synonym with YES, this produce lowercase single-char 'y' on stack ---> N (the complementary value) ---> YES (a synonym, but Y is more often used) ---> AND ---> ORR ---> TRIPLEORR ---> TRIPLEAND ---> (MATCHED .. MATCHED) ---> = .. == .. === ---> NOT (( Y-TO-1 )) A 'y' flag on main stack is converted to number 1, else, to 0 note1:::: In storing a flag such as from a flag-producing algorithm like MOUSECLICK in a number-storing place like >N1 or >>V then this provides an elegant translation, the 'y' becomes a 1, and the 'n' becomes a 0. These can later be investigated by means of ISDANCE and ISBASIS prior to a (MATCHED, or be stored in a ((DATA .. )) type of variable, but the latter can also be altered directly with SETDANCE and SETBASIS as for flags. note2:::: The notion of SETDANCE and SETBASIS is to avoid too many negative affirmations (or preposterous-sounding statements), compared to what some earlier languages have resulted in (as regards 'true', -1, 0, 'false') and so on. Y-TO-1 provides ---> MMOTION ---> MOUSECLICK ---> MOUSECLICKR ---> >N1 ---> SETDANCE ---> SETBASIS ---> AND --> ORR --> XOR (( YANTRA )) Fourth on main stack copied to top (( YANTRAR )) Fourth on rich stack copied to top (( YANTRAS )) Fourth on simple stack copied to top (( YANTRAV )) Fourth on variable stack copied to top (( YES )) An absolutely incredibly wonderful way of making 'y' on the stack ---> Y (synonym) note1:::: The YES produces, as said, the letter y on the main stack, and the corresponding NO procedure lays the n there instead, and so does the function Y and the function N. Now one of the psychological great features when it comes to relating to what the program actually does when it comes to this Lisa programming language is that one can look into the stack and see what's on it during program run, e.g. by putting in the word ---> STK, or by manually typing in words which look into the stack or other variables. The lowercase y and the lowercase n have a distinct shape and form and ascii value and at once, when one sees this on the stack, one knows what is going on -- one knows what functions they come out of, or what they go into, etc. In contrast, languages which uses great clumsy words like TRUE which perhaps translate to the even more clumsy number -1 do not properly provide values which stand out so as to explain what's going on in a psychological clear format. For if FALSE would be a zero, then how would one distinguish between that zero and other zeroes when they crop up as part of program design? (( YNIN )) In text mode, asks for yes(=lineshift) or no, and produces flag in: produces: flag ---> ENTERPLS ---> OK-BUTTON (in graphics mode) note1:::: The flag is lowercase y or lowercase n on the main stack, and can e.g. be used as input to ---> (MATCHED .. )(OTHER .. MATCHED). However the interactor may type in a couple of more alternatives, such as a capital Y. (( YOUNGER-IN-LIST )) Proceed to one earlier in list ---> LIST (which has a lot more ---> connections for lists) ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ Z [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ [ (( [ )) Same meaning as ---> MAKENEWLIST \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ (( \ )) Division of a decimal number kind, using the main stack ---> GREATER (see comment) (( \R )) Division of a decimal number kind using the proper rich stack ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] ] (( ] )) Same meaning as ---> LISTOK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ general comment:::: A number beginning with the ^ or hat sign, which can look like a v when turned 180 degrees, like ^3333, goes to the variable stack, or VARSTK. This it does in a way which can play a time factor role if inside a loop which repeats itself many thousands of times, in that the variable stack is pure whole number and does not need the extra facilities of the main stack. Some functions, such as WRITEPAL, which are more often than not intended for usage inside a loop, have therefore input taken specifically via the variable stack. See also e.g. ONEV, TWOV, RMV. Some words completing with V refer to variable stack, some words completing with R refers to rich or decimal number stack, some words completing with S refers to the simple stack. ____________________________________________________________________________ _ general comment:::: Some words, like CLEAR_KEYBUF, which are basic in the language, use the hyphen, _, but not many. ```````````````````````````````````````````````````````````````````````````` ` {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ { **** syntax for commentary over several lines is like this { note1:::: The advise is to be sparse on comments inside the program itself so as to let the structure stand out -- and apply your best intents of goodness and beauty and esthetical healing functionalism in the formal language, and rather write a separate piece of documentation in a somewhat separate duration. But when you do have comments inside the program, then prefer the }* .. }* because they stand strongly out, and all the more so since they are repeated with each line. But there is an additional reason that you avoid the **** .. { type of commentary as a rule of thumb for ordinary program design and formalism writing -- and that is that during program correction you can sweepingly comment out a whole section of the program, even thousands of lines, by suddenly adding four stars and completing with a { sign (as long as no other { sign in any context is used in that section, in which case you have to temporarily get rid of it and put it back when program is corrected). |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | general comment:::: The extant words of Lisa do not begin with a bar | sign, however some of the synonyms nearer the Firth level do begin with a | sign. It is the convention of Lisa normally to begin with alphabetic signs, and continue alphanumerically, and with dashes, but the sign might be used. }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} } general comment:::: In Lisa formalism, anything, from zero characters and up to a full line of text, and in principle up to about 250 characters, can be quoted by both preceeding and concluding the quote with a } character. The 'forward-looking' appearance of }a quote like this} indicates the flow of parameter transfer. The importance of program standing forth as program and pure data standing there looking like data is the reason that } .. } is preferred as a device in contrast to things which syntactically span several lines. It is important, then, for readability of program / formalism, that what is quoted is shown to be quoted. Use CONCAT if you like up to 250 chars, or add by TEXT>MATRIX or similar device to have many lines stored. ---> " (see comment under double-quote sign ", in start of this listing) general comment:::: A quote of the just-mentioned kind if immediately, before blank, after the completing }, equipped with an asterix, *, is treated as a comment. }* This is an example of such a comment, and for convenience of reading,}* }* the convention is to put the asterix in also after the first curly- }* }* bracket. The advantage of this type of comment is that one very }* }* clearly sees what is a comment as distinct entitity from the rest }* }* of the program. Another advantage is that the other main type of }* }* comment, which begins with ****, can sweep over and include this }* }* type of comment without problem, in cases where it is important }* }* to preserve a whole section of code as untouched as possible. In }* }* other words, if you write your formalism either without quotes, or }* }* with quotes of this type, another person can, e.g. using the CFDL }* }* license as at yoga4d.org/cfdl.txt (outlining copyright conditions, }* }* and possibilities for open source quoting of your program), }* }* quote with ****-style of comment all your program without changing }* }* a comma, and then proceed to implement a variation of your program }* }* after that. However, if you mix the two types of comments, one would }* }* have to modify the commentary style to this style in order to comment}* }* a larger section. The point of a good formalism is not at all to aim }* }* at minimum of characters, but maximum of natural psychological }* }* readability, and you see the standing row of asterix can give rise }* }* to an elegant feeling of symmetry when printed with courier. }* }* See also the comment under the **** .. { type of commentary. }* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ general comment:::: A number preceeded with a ~ or 'wave' sign, which also may look like a s which has rotated on its axis some 90 degrees, like ~5, goes to the top of the simple stack with the result that the existing N1 becomes N2, the existing N2 becomes N3, and so forth (it can be removed by RMS). While this is part of my Firth language definition, it is a convention in Lisa to normally use the >N1 .. >N11 and N1 .. N11 and such things as INCN1 to modify elements on the simple stack. The reason for this is that the simple stack plays, roughly, the role of active (or 'short term') memory for many algorithms, in which 11 empty slots are automatically allocated on entry, and unallocated on exit from the function. Using a notation like ~63 inside an algorithm would mean that one more slot would be used, 12 instead of 11, and that adds to the sense of complexity unless there are good reasons for doing so. (Of course, there are other events which also can affect the amount used on the simplestack, notably (COUNT .. COUNTUP), but this latter pair is by definition always used together, as a pair, within a function, with the overall result that there are still only 11 slots used.) //////////////////////////////////////////////////////////////////// EXTRA-LIST: EXCERPTS FROM MY FIRST MTDOC //////////////////////////////////////////////////////////////////// x1 y1 x2 y2 color RECT x1 y1 x2 y2 color RECTFILL x1 y1 r color CIRCLEFILL x1 y1 x2 y2 col1 col2 DOTTED_RECT And here are some more: x1 y1 r color CIRCLE x1 y1 x2 y2 color LINE x1 y1 length color HLINE x1 y1 length color VLINE }LOVELY BABE} 5 2 SUBSTR POP POP and you get this poem LY LOVE BABE If the input is TEXT NUM1 NUM2 then NUM1 is taken to be startposition and NUM2 is taken to be length. The output is then TEXT1 TEXT2 where TEXT2 is on top of stack and has the length specified, where TEXT1 is the rest of the original text. If you need a copy of the original whole before SUBSTR, just do a ONE first. The advantage of dealing with short texts at a time is that one can do such things and the program is still fast and smooth. If the assumption had been that each text can be from a character up to, say, millions of of characters then, given the context of a pretty 32-bit PC, one couldn't have had this effortlessness in providing such extra facilities to the essential text handling tools or programs. And we like pretty 32-bit PCs, and want to keep on considering them useful, thank you very much all you who research on quantum bullshit computers. INSERT inserts in a way which is pretty much the converse of substr: it can put a thingy in the middle of another thingy. For instance, }LOVE BABE} }LY} 5 INSERT POP ==> LOVELY BABE OVERWRITE overwrites existing content }LOVELY BABE} :CUMCUM 1 OVERWRITE POP ==> CUMCUMBABE Ehm, I like this text better than Hello world. :FIRSTTEXT :SECONDTEXT CONCAT POP ==> FIRSTTEXTSECONDTEXT In most cases = == === usage is pretty straightforward. You can nest like = == = == = == = == with a number of === at the end equalling exactly the number of = before. We're talking now inside a function, inside a body algebra. You can also do something like = .. = == === .. === and it should still be readable. As for intricacies connected to = == === pls notice that in no case will it perform well (although it will compile well, perhaps) to have two == == beside one another or near one another -- it should be = = == === == === but not anything like = = == == === ===. For instance, the following is correct -- a useless example, but you might want to put a READLN instead of the YES in each place and run it several time to see what happens: //BT TESTINGS YES = }DOING STH.} SPOPS READLN RM YES = }DOING STH MORE.} SPOPS READLN RM == }ELSE STH MORE.} SPOPS READLN RM === == }ELSE STH.} SPOPS READLN RM === }DONE STHS.} SPOPS READLN RM BT| This is correct. The logic is pretty straightforward, like this: //BT TESTINGS YES = }DOING STH.} SPOPS READLN RM YES = }DOING STH MORE.} SPOPS READLN RM == }ELSE STH MORE.} SPOPS READLN RM === == }ELSE STH.} SPOPS READLN RM === }DONE STHS.} SPOPS READLN RM BT| For those who want to spend time on inserting indents, here is a fantastically unreadable working loop example, where we use my Firth words natively instead of the higher level Lisa GJ2 Fic3 words -- e.g. //BT instead of (LET and so on: //BT LOOPEX1 }NOW WE BEGIN A LOOP.} POP 5 >N5 O// }NOW WE ARE INSIDE THE LOOP.} POP }HERE IS THE COUNTER VALUE: } POPS N5 POP }PLEASE PRESS ENTER TO CONTINUE.} POPS READLN RM CRLN 10 N5 INTGREATER |C| }WE ARE STILL WITHIN LOOP, PASSED CHECK.} POP }NOW INCREASE COUNTER VALUE.} POP }NOW ENTERING SUBLOOP: } POP 1 >N6 O// }*} POPS N5 N6 INTGREATER |C| INCN6 |A CRLN }NOW LEFT SUBLOOP.} POP INCN5 |A CRLN }WE ARE OUTSIDE THE OUTER LOOP.} POP BT| //BT AUTOSTART LOOPEX1 BT| VISIBLECOMPILATION COMPILEPAUSEDATINYBIT //BT YESORENTER **** THIS ONE MAKES y Y YES AND SO FORTH, WITH OR WITHOUT BLANKS, INTO A STANDARD CONVENTIONAL LOWERCASE y FLAG, INCLUDING ALSO JUST AN EMPTY ANSWER, BUT EVERYTHING ELSE INTO AN n FLAG.****{ RMBLUPC KEEPLETTERS LENGTH 0 EQN = RM Y EXIT === ONE :Y EQ SWITCH :YES EQ ORR BT| //BT LOOPEX2 }NOW WE BEGIN A T// LOOP.} POP 5 >N5 T// }NOW WE ARE INSIDE THE LOOP.} POP INCN5 }HERE IS THE INCREMENTED COUNTER: } POPS N5 POP }SHOULD LOOP RENEW ITSELF? (ENTER=YES) } POPS READLN YESORENTER = }YES. OKAY.} POP |NT| == }NO, OKAY, WE GO ON.} POP === }NOW ENTERING SUBLOOP: } POP 1 >N6 O// }****} POPS N5 N6 INTGREATER |C| INCN6 |A CRLN }NOW LEFT SUBLOOP.} POP }SHOULD LOOP NOW EXIT? (ENTER=YES) } POPS READLN YESORENTER = }YES, OK. } POP |GNT| == }I GUESS NOT EXIT YET.} POP CRLN === |GT CRLN }WE ARE DONE WITH TESTING.} POP BT| //BT AUTOSTART LOOPEX2 BT| To put texts into the stack: :ONEWORD }several words} When you write }...} to make a string, you can always put double }} inside the string in order to quote }. Like, }Here is a right-curl: }} And here are two of them:}}}}.} POP This displays on the screen: Here is a right-curl: } And here are two of them:}} Type STK to see the content of the main stack. To put things into the other stacks: ~989 ~982394 ~9893248 SIMPLESTK ^23477 ^87324 ^87234 VARSTK $3489.234 $2343e5 $-23434.23 RICHSTK To see what's on the stack in each case, type STK and press ENTER. Or pop it out of the stack so it's deleted by typing POP and press ENTER (in other words, the ===> thingy is not a word in itself, it merely is to say something in this technical manual about what's on the stack). 234233 HEX ===> 392F9 POP 753664 HEX ===> B8000 STK POP -32 HEX ===> -20 POP The simple body HEX converts a number of a straight usual ten-digit kind (not dotted) to a hexadecimal number, where 16 digits, 0123456789ABCDEF, are used. This is easy to use in combination with the above tools but we do not push HEX much in either YOGA4d or FIRTH234 contexts. To calculate, put it back. From hereon in this doc you'll have to write the POP or STK or RICHSTK or VARSTK or SIMPLESTK or whatever it is yourself. :392F9 HEX2DEC ===> 234233 :B8000 HEX2DEC ===> 753664 -20 HEX2DEC ===> -32 :FF HEX2DEC ===> 255 HEX2DEC converts hexadecimal well-formed texts -- no leading or trailing blanks, no fuss -- but they can be uppercase or lowercase -- to the numeric form, within the roughly 2 billion (32 bit) range. Note that since the main stack in fact stores numbers just as it stores strings then when you enter a hex number like 20 which does not have A..F inside it you do not even have to put }s around it or preceed it with colon. EQN can be written instead of INTEQUAL, to check for equality of the whole number part of two numbers. TXTEQUAL checks for exact character-after-character identity of two texts on the main stack. EQ, like the text-analogy to TEST, namely TEQ, employs a more luxurious type of comparison: } X } }x} EQ POP would give a confirmative reply. EQ checks for equality beyond such petty issues as spaces before or after the letter or word or phrase and its case. However if there is space in between the phrase, and you want to ignore this space also, do an RMBL on the phrase first, to remove each and every blank. For if you just run EQ, }hi honey} }HI honey} EQ POP would not come out as the same, not because of the uppercase HI but because of the two spaces after it, but }hi honey} }HI honey} RMBL2 EQ POP would get the confirmative y reply. RMBL2 does twice what RMBL does -- for two elements on stack rather than one, so that you don't have to do something like RMBL SWITCH RMBL SWITCH. In connection with these, you might want to use such as EXTRACTNUMBER, HEAL, EQSTART and SETLENGTH to mention some -- do search on these if you have this info text up in an editor now, and need some extra transfigurations of small texts. While you can, with GETMEM and FREEMEM and suitable use of such constructs as MUL4 and PEEK easily make a 32-bit number array (that is, a sequence of numbers each being up to roughly two billion, perhaps signed), FIRTH234 offers easier ways of doing things. 10 10000 %RFFG TOV1 This makes a new array and load it with values 1..10000, it has its pointer temporarily stored in V1 (top of varstack). Let me insert a comment right here on the use of TOV1. TOV1 replaces the value of V1 given that it exists; or else it fills it up with a value. The rule of thumb is: use such as TOV1 as much as you please when doing things to learn them, by typing them in, interactively -- but inside a function, be courteous enough to callers of a program to do STKTOVAR or >>V or & -- which all mean the same thing -- before doing TOV1. Then empty the value afterwards with RMV or V>> or && which also all mean the same thing. Instead of VARTOSTK you can write GETV. What does the array now pointed to at V1 look like? An informal way of seeing it is: V1 %SEE So, amount_of_values highest_value %RFFG ==> warp_address_of_array_this_long Note that %RFFG can perfectly well accept a zero as highest value and thus create an array of zeroes. However a negative highest value to %RFFG has no other effect than giving it a zero value. If you want to nullify all values under 5000 try V1 5000 %LEVELBENEATH And in each case, try V1 %SEE to see the change. You can also create a new range of values by V1 1000000 %NEWRFFG On the other hand, V1 %EMPTY would put it all to zeroes, fast, as right after %MAKE. Anyway, you can also create a series of values beginning with a value and going up to a certain value, like, from 500 to 3500: V1 500 3500 %RFFGRANGE And you can reverse the sequence: V1 %REVERSE More with arrays. If you want to add a factor to all values, say, you add 1000000 after initializing with values 10..20, you can do something like: 10 %MAKE TOV1 10 20 V1 %RFFGRANGE 1000000 V1 %FACTORADD V1 %SEE If you want to multiply with a million instead, try: 10 %MAKE TOV2 10 20 V2 %RFFGRANGE 1000000 V2 %FACTORMUL V2 %SEE And in the same way, with factor first, and (on top), the address, %FACTORSUB, %FACTORDIV, %FACTORMOD can also be used for fast changes of these values. }HALO} 2 CH ==> }HALO} }A} }HALO} 2 CHN ==> }HALO} 65 In addition to CHN, CH. CH leaves intact a text while picking a character out it as requested. CHN does the same but provides the ascii number instead of the letter itself, which can be full 8 bit. If the number is outside of the range 1..length of string, the returned number is 0 from CHN, and the returned string is the empty string }} from CH. And to change texts character by character, TOCHN and TOCH are useful. }LOV@ SUPERIOR} 69 4 TOCHN POPS ==> Displays LOVE SUPERIOR TOCHN appreciates a position on top of stack, an ascii value second to top, and this changes the text. The text is the only output, and left on top of stack. TOCH is exactly equal just use a letter instead of a number, or it takes the first letter if it is a longer thingy. Here I have put EU instead of E to show, in the example, that the first letter is being used when there are more as second input: }LOV@ SUPERIOR} :EU 4 TOCH POPS ==> Displays LOVE SUPERIOR You can also do a lineshift tricks with TOCH. The standard lineshift character will be inserted if the second input to TOCH has zero length. For instance, }LOVELY,BABE} }} 7 TOCH POPS ==> Displays LOVELY, BABE Only in some situations is it advisable to break up the notion of the whole line as one item on the main stack into something itself involving lineshifts like this; make sure you really want it this way if you utilize this feature. Though displayed on two lines, it is still considered one item on stack. STK will show this over two lines, though it is still one item on stack -- and so forth. CRLN is the advised way to display a lineshift; and to keep each line as one item is what is the ideal in the case with texts of this maximum size, 250. More numerical functions. 888 400 1200 RANGE ==> 888 y 888 400 500 RANGE ==> 888 n RANGE leaves the third-to-the-top-of-stack value intact while it detects whether it is within the range given from the second-to-top to the top. It will give y flag if it is within this range, and also an y flag if it is equal to either of the values. The second to top value should be less than the top value. If you used signed values, be sure that you watch what you're doing. If the two values given as bottom and upper range are negative, it still holds that the upper range is going to be upper -- in this case in the sense that its numeric value needs to be less negative! 5 7 10 WITH ==> n 8 7 10 WITH ==> y WITH is like RANGE only that only a flag comes out of it; the compare-values are deleted, saving the need for a SWITCH and a RM in such cases where only the flag is needed after a RANGE comparison. FOR// .. |NEXT (in which a count value is fed to FOR//, and it counts 1..n) ONWARDS// .. |CHECK| .. |AFRESH (in which a y/n is fed to |CHECK|, it loops) MAYBE// .. |OR| .. |ON (in which a y/n is fed to MAYBE// and |OR| is optional) To make a new body (also called 'to define a function'): //BT .. BT| 3333 AFFIRM =====> 3333 y 0 AFFIRM =====> n -1 AFFIRM =====> n +1 F2Y ==> y -1 F2Y ==> n 0 F2Y ==> n +2349 FACT ==> 1 -2342345 FACT ==> -1 0 FACT ==> -1 3333 2222 TEST ====> 3333 n 5555 5555 TEST ====> y YES YES AND ===> y YES NO AND ===> n NO YES AND ===> n NO NO AND ===> n YES YES ORR ===> y YES NO ORR ===> y NO YES ORR ===> y NO NO ORR ===> n YES YES XOR ===> n YES NO XOR ===> y NO YES ORR ===> y NO NO ORR ===> n YES NOT ===> n NO NOT ===> y YES YES YES TRIPLEAND ===> y YES NO YES TRIPLEAND ===> n NO YES YES TRIPLEAND ===> n NO NO YES TRIPLEAND ===> n YES NO NO TRIPLEAND ===> n YES YES NO TRIPLEAND ===> n NO YES YES TRIPLEAND ===> n NO NO NO TRIPLEAND ===> n TRIPLEAND is tough to satisfy, huh. (As Arne Naess pointed out, if you have a theory which can somehow be reduced to a series of, let's say, ten assumptions, then you can put NOT in front of each of these assumptions and permute and produce 1023 theories since 2 x 2 x 2 etc ten times is 1024. Think of this during arguments as to 'which theory is right, Darwin or Moses'.) YES YES YES TRIPLEORR ===> y YES NO YES TRIPLEORR ===> y NO YES YES TRIPLEORR ===> y NO NO YES TRIPLEORR ===> y YES NO NO TRIPLEORR ===> y YES YES NO TRIPLEORR ===> y NO YES YES TRIPLEORR ===> y NO NO NO TRIPLEORR ===> n The world isn't complete without ORR. TRIPLEORR is like a lady who comes no matter what you do -- the stark opposite of the diva TRIPLEAND. (Or perhaps it is three babes; you can figure out the metaphor yourself.) Now of course you can do AND AND instead of TRIPLEAND and you can do ORR ORR instead of TRIPLEORR but it is good to have one primary body for something which might be terrifically interesting in certain contexts to do really often. 33.34 33.33 ISEQUAL ==> n 33.34 33.34 ISEQUAL ==> y So whereas INTEQUAL overrules the decimals, ISEQUAL does not. However whereas INTEQUAL doesn't bother about translating the number into a real number, ISEQUAL does, so it is plausible that given billions of loop rounds that there are percentages of speed difference -- intequal getting better out of it, at least just slightly, if in fact the decimals can be ignored. 324324.1 2342346.3 NOT_ISEQUAL ==> y 777 777 NOT_ISEQUAL ==> n NOT_ISEQUAL is simply the compressed form of ISEQUAL NOT. It can be used on whole numbers but for that you have NOT_INTEQUAL. #1 HYPERCONNECT Warp, given the warpaddress. In bt, you can say H or WARP instead. :A WARPADDRESS #1 With name of program (function) on stack, you can find its warp (pointer) address. In bt, you can say WHERE instead. #1 #2 SETWARPADDRESS #1 from GETFUNCNUM, #2 WARPADDRESS change #1 function to #2 behaviour Use for unsigned (new) functions :A GETFUNCNUM #1 :A is the name of a program. (If a basic func, it's a signed number.) Use in SETWARPADDRESS SIMPLEADDADD Summarizes the five topmost members at the simple stack and puts it to N6. Must be at least six members there already. SIMPLEADDSUB N3 + N1 goes to N5 (at simplestk) N3 - N1 goes to N7 (at simplestk) Must be at least 7 nums on simplestk SIMPLESUBS N1 - (N2 + N3 + N8 + N5) is calculated. The result is put to N6, at simplestk. Must be at least six members there. SIMPLEMUL N5 * N3 goes to N7 (at simplestk) Must be at least 7 nums on simplestk FRESHSIMPLE Clears simplestack. When a defined func is entered, 11 'local variables' N1 to N11 is given to it; these are released as it exits :A IN compiles textfile :A (and looks for 'autostart') Try :elves IN :A (LN If something is in stack, like a number or a text, (LN will write it out NEWS list all higher functions AMI list all basic and higher functions, basic funcs first MAKENEWLIST for use outside of functions only. sets a counter for a list of bodies to be entered to stack via comma xxx, :A puts text xxx to stack outside of functions, xxx contains no blanks but may contain a hyphen and such LISTOK #1 retrieves counter for comma-list (can be used repeatedly) #1 GETMEM #1 #2 allocates #1 bytes, leaves this on stack, leaves also the address #2 #1 #2 FREEMEM #2 is address, #1 is count, tells the OS that this memory region is free for other purposes #1 FOR// count from 1 to #1, step 1, until |NEXT where N1 is topmost counter |NEXT completes a FOR// |NEXT loop N2 is maximum within it, N3 is next level counter etc N1 #1 retrieves the top of simple stack (which, within FOR/NEXT, usually is the counter) N2 #1 retrieves the second in simplestk (which, within FOR/NEXT, usually is the maximum value of loop) N3 #1 if a second level FOR/NEXT, this is second level counter (and third value on simplestk) N4 #1 and so on for N5 up to N11 You may perfectly well use these in other connections also V1 #1 retrieves the top of varstack The varstack is stable between funcs whereas simplestack shifts 11 positions V2 #1 retrieves the second in varstk V3 #1 retrieves the third in varstk V4 #1 and so on for V5 up to V11 RFFG #1 get a relatively free fluctuation number #1 #2 ADD #3 add numbers on a whole number basis #1 #2 SUB #3 substract #2 from #1 on a whole number basis #1 #2 MUL #3 multiplies on a whole number basis #1 MUL4 #2 multiplies with 4, as whole numbers #1 #2 DIV #3 divides #1 on #2 on a whole number basis #1 #2 MOD #3 gives remainder of #1 div #2 that is, #1-(#1/#2)*#2 where division is rounded off #1 TWICE #2 twice the (rounded) number #1 SQUARE #2 square the (rounded) number #1 HUNDRETH #2 hundreth times the (rounded) number :A :B SWITCH :B :A change sequence of top two SWITCHS For simplestk SWITCHV For varstk SWITCHR For richstk :A :B :C ANGEL :B :C :A reorder top three ANGELS For simplestk ANGELV For varstk ANGELR For richstk :A :B BRIDGE :A :B :A make a copy of second BRIDGES For simplestk BRIDGEV For varstk BRIDGER For richstk :A :B :C TANTRA :A :B :C :A make a copy of third TANTRAS For simplestk TANTRAV For varstk TANTRAR For richstk ... YANTRA :A copies fourth on stk YANTRAS For simplestk YANTRAV For varstk YANTRAR For richstk ... MANTRA :A copies fifth on stk MANTRAS For simplestk MANTRAV For varstk MANTRAR For richstk ... DHYANA :A copies sixth on stk DHYANAS For simplestk DHYANAV For varstk DHYANAR For richstk ... PURUSHA :A copies seventh on stk PURUSHAS For simplestk PURUSHAV For varstk PURUSHAR For richstk ... NIRVANA :A copies eighth on stk NIRVANAS For simplestk NIRVANAV For varstk NIRVANAR For richstk :A RM removes top item on stk RMS For simplestk RMV For varstk RMR For richstk :A :A :A N PICK :A :A :A :A copies the item pointed to by N and puts it on top (compare BRIDGE) #1 PICKS For simplestk (item # on mainstk) #1 PICKV For varstk (item # on mainstk) #1 PICKR For richstk (item # on mainstk) :A :A :A #1 SELECT :A :A :A extracts the item pointed to by N and puts it on top instead of where it was (compare ANGEL) #1 SELECTS For simplestk (item # on mainstk) #1 SELECTV For varstk (item # on mainstk) #1 SELECTR For richstk (item # on mainstk) :A :A :A #1 REMOVE :A :A removes the item pointed to by N, where 1=top, 2=second to top etc In contrast, see SEVERALRM #1 REMOVES For simplestk (item # on mainstk) #1 REMOVEV For varstk (item # on mainstk) #1 REMOVER For richstk (item # on mainstk) ONWARDS// starts a loop area inside a function which is completed with |CHECK| and |AFRESH :F |CHECK| the loop exits here if flag :F is not y, a flag which can come from 'greater' etc |AFRESH completes the ONWARDS// |CHECK| loop by jumping to the onwards area KEY :A retrieve invisibly a character from the keyboard as a one-size text CRLN write a line shift to the screen :A (SP as (, but write a blank also READLN :A retrieve visibly a text line completed by an enter (lineshift) #1 SPACES print this number of spaces at the current place of text screen SPACE equivalent to 1 spaces, it prints a space on text screen :A1 :A2 FDCOPY :A1 is a single existing file and :A2 the name of a copy to be created VAR xxx xxx will after this give on varstk the address to store a whole number (Cfr also GETMEM / FREEMEM) #1 ^#2 >VAR With #1 on main and ^#2 on var stack, put #1 into position #2 ^#1 VAR> #1 With #1 on varstk, retrieve value at this position to main stack VARSTRING xxx xxx will after this give on varstk the address of a preallocated space for a textline, up to size 250. :A1 ^#1 >VARSTR With :A1 on main and ^#1 on var stack, put :A1 into position #1 ^#1 VARSTR> :A1 With #1 on varstk, retrieve text at this position and copy to main stack #1 #2 >MEM Put #1 into position #2, this time all at main stack #1 MEM> #2 Retrieve the value at postion #1 and put on main stack ^#1 ^#2 TOVAR With both numbers on varstk, let ^#1 be stored at address ^#2 ^#1 VARTO ^#2 The value at address ^#1 is put to the varstk ^#1 INCVAR The value at address ^#1 is increased by one ^#1 INC4VAR The value at address ^#1 is increased by 4 #1 ^#2 ADDVAR The value at address ^#2 is increased by the value #1 ^#1 ABSV ^#2 Sign is removed from varstk-value ^#1 NEGATEV ^#2 Varstk-value negated ~#1 ABSS ~#2 Sign is removed from simplestk-value ~#1 NEGATES ~#2 Simplestk-value negated $#1 ABSR $#2 Sign is removed from richstk-value $#1 NEGATER $#2 richstk-value negated #1 AFFIRM (#1)flag Flag is y and value #1 is kept when value is positive or flag is n and value removed #1 ABS #2 Sign is removed #1 NEGATE #2 Value negated :A ONE :A :A a copy of the top item is put to the top ONEV As one, but for varstk ONES As one, but for simplestk :A :B TWO :A :B :A :B a copy of the top pair is put to the top TWOV As two, but for varstk TWOS As one, but for simplestk THREE a copy of the top threesome is put to the top THREEV As three, but for varstk THREES As three, but for simplestk FOUR a copy of the top foursome is put to the top FOURV As four, but for varstk FIVE a copy of the top fivesome is put to the top FIVEV As five, but for varstk RETURNSTK write a list of the contents of the very internal returnstk TRUST// start a loop area which is completed by gototrust (like FOR/NEXT but count yourself.) |GOTONEXTTRUST| Goes to the NEXT point AFTER the TRUST loop. Must use this rather than EXIT inside a loop! |NEWTRUST| When you want to jump up to TRUST// in the middle of the loop, use this Use only after TRUST//, before |GOTOTRUST |GOTOTRUST go back to the top of the loop, as set by TRUST// This signals the finish of the loop :F MAYBE// when flag is 'y' do what's next, else go to |OR| area or |ON area |OR| this is optional between if and then, the area done if flag above is 'n' |ON this signifies the completion of an 'if' or 'if/else' structure N1. N2. ISEQUAL F given two decimal numbers on main stack, or whole, check for equality YES F give the 'y' flag to the stack NO F give the 'n' flag to the stack A1 A2 TXTEQUAL F checks for exact equivalence between two texts A LENGTH A N gives the length of the text A, leaving A intact N1 N2 INTEQUAL F check the numbers (considered as whole numbers) for equality (so, eg, 7.3 7.8 INTEQUAL gives y) A1 A2 CFEQUAL F convert to similar Ascii case and replace them with equality flag N1. N2. GREATER F compare two (decimal) numbers, flag = 'y' if N1 > N2 N1. N2. GTOREQUAL F compare two (decimal) numbers, flag = 'y' if N1 >= N2 N1. N2. LESSTHAN F compare two (decimal) numbers, flag = 'y' if N1 < N2 N1. N2. LTOREQUAL F compare two (decimal) numbers, flag = 'y' if N1 <= N2 A1 UPPERCASE A2 convert text to ascii uppercase A1 LOWERCASE A2 convert text to ascii lowercase ^#1 UPC ^#2 convert ascii num at varstk to ascii uppercase fast (if within range a..z) ^#1 LPC ^#2 convert num at varstk to ascii uppercase fast (if within range A..Z) A1 A2 TXTGREATER F compare two texts, flag = 'y' if A1 > A2 A1 A2 TXTGTOREQUAL F compare two texts, flag = 'y' if A1 >= A2 :A1 :A2 TXTLESSTHAN :F compare two texts, flag F is 'y' if A1 < A2 :A1 :A2 TXTLTOREQUAL :F compare two texts, flag F is 'y' if A1 <= A2 :A #1 FROMCH :A #1 Get asciinum from text as ascii value, keeping the text intact (cfr bytemem>). :A #1 #2 INTOCH :B Put asciinum into :A at position #2 (cfr >bytemem) YES :F Put the affirmative flag (the letter 'y') to the stack NO :F Put the letter 'n' to the stack :A :B CFGREATER :F Compare two texts on the stack in a 'casefree' way :A :B CFGTOREQUAL :F Compare 'greater or equal' in a 'casefree' way. :A :B CFLESSTHAN :F Compare 'less than' in a 'casefree' way :A :B CFLTOREQUAL :F Compare 'less than or equal' in a 'casefree' way #1 #2 INTGREATER :F Compare whole numbers #1 #2 TEST #1_if_no :F Compare two whole numbers If equal, give 'y' flag. If unequal, retain #1, give 'n'. #1 #2 INTGTOREQUAL :F Compare whole numbers for 'greater than or equal' #1 #2 INTLESSTHAN :F Compare whole numbers for 'less than' #1 #2 INTLTOREQUAL :F Compare whole numbers for 'less than or equal' #1 #2 NOT_ISEQUAL :F Check whether two numbers are in contrast #1 #2 NOT_TXTEQUAL :F Check whether two texts are in contrast NOT_INTEQUAL :F Check whether two whole numbers are in contrast :A :B NOT_CFEQUAL :F Check whether two texts are in contrast even if equalized with regard to case ^#1 (V As ( but for varstk ^#1 (LNV As (LN but for varstk ^#1 VARTOSTK #1 Move from varstk to stk #1 STKTOVAR ^#1 Move from stk to varstk (Please watch that you give only numbers to numfuncs) >N1 Put number into simplestk so as to replace its top, if it exists (or create it) >N2 Put number into simplestk, so as to replace the second, if it exists (or create it) >N3 >N4 >N5 >N6 >N7 >N8 >N9 >N10 >N11 incN1 Increase value N1 by 1, if it exists. inc4N1 Increase value N1 by 4, if it exists. decN1 Decrease value N1 by 1, if it exists. incN2 Increase value N2 by 1, if it exists. decN2 Decrease value N2 by 1, if it exists. incN3 decN3 incN4 decN4 incN5 decN5 ... incN11 decN11 toV1 Put number into varstk so as to replace its top, if it exists (or create it) toV2 Put number into varstk, so as to replace the second, if it exists (or create it) toV3 toV4 toV5 toV6 toV7 toV8 toV9 toV10 toV11 incV1 Increase value V1 by 1, if it exists. decV1 Decrease value V1 by 1, if it exists. incV2 Increase value V2 by 1, if it exists. decV2 Decrease value V2 by 1, if it exists. incV3 decV3 incV4 decV4 incV5 decV5 ... incV11 decV11 '99' A number quoted with ' will produce, as a single/ length text, this Ascii char :A :B CONCAT :C Add two texts (or numbers conceived as texts) and make one longer (cropped at len=255) #1. * #2. Multiply the numbers at mainstk considered as scientific notation numbers #1. + #2. Scientific notation addition like 3e10 4e11 + (ln #1. - #2. Scientific notation substraction #1. \ #2. Scientific notation division Use of richstk is faster #1 INC #2 Whole number increase by one (floors it first, like 30000000.5 inc gives 30000001) #1 INC4 #2 Whole number increase by four, very important for 32-bit pointer usage #1 DEC #2 Whole number decrease (floors it first, that is, crops decimals first) #1 DEC4 #2 Whole number decrease by 4 #1. SIN #2. Sine function #1. ARCSIN #2. Inverse sine #1. COS #2. Cosine function #1. ARCCOS #2. Inverse cosine #1. TAN #2. Tangent function #1. ARCTAN #2. Inverse tangent #1. EXP #2. 2.718281828 ^ #1 #1. #2. LOGN Natural logarithm, pay attention to what numbers you give it #1. #2. POWER #1 ^ #2 in scientific notation #1 SQRT #2 Square root $#1 INCR $#2 Adds 1.0 to num at richstk $#1 DECR $#2 Subs 1.0 from num at richstk $#1 INC4R $#2 Adds 4.0 to num at richstk $#1 DEC4R $#2 Subs 4.0 from num at richstk $#1 TWICER $#2 Times 2 at rich stk $#1 SQUARER $#2 Itself times itself at richstk $#1 HUNDRETHR $#2 Times 100 at richstk Note: to prettify the r looks move to simplestk then mainstk $#1 SINR $#2 Sine func at richstk $#1 COSR $#2 Cosine func at richstk $#1 TANR $#2 Tangent func at richstk $#1 ARCSINR $#2 Inverse tangent at richstk $#1 ARCCOSR $#2 Inverse cosine at richstk $#1 ARCTANR $#2 Inverse tangent at richstk $#1 SQRTR $#2 Square root at richstk $#1 EXPR $#2 2.718281828 ^ # at richstk $#1 $#2 LOGNR $#3 Nat.log at richstk $#1 $#2 POWERR $#3 $#1 ^ $#2 $#1 ABSR $#2 Take away sign, richstk Good for debt treatment $#1 ROUNDR $#2 Round, richstk #1 #2 #3 COPYNUMS Copy from #1, to #2, amount 4-byte numbers #3 beginning at lowest position #1 #2 #3 COPYNUMSHIGH Copy from #1, to #2, amount 4-byte numbers #3 beginning at highest position #1 #2 #3 BYTES2NUMS Copy chars from #1, to nums #2, amount bytes #3 Note: unpacks chars to big numbers #1 #2 #3 NUMS2BYTES Copy from #1, to #2, amount byte #3 (see also >bytemem) Note: packs big numbers as chars $#1 FLOORR $#2 Floor, richstk $#1 (R As ( but for richstk $#1 (LNR As (LN but for richstk #1 STKTORICH $#1 Number from main to rich stk $#1 RICHTOSTK #1 Number from rich to main stk EXIT Leave this procedure (Inside loops:Very careful! Inside TRUST, use |GOTONEXTTRUST|) #1 PEEK #2 Look into a memory position if it comes from GETMEM or is a WARPADDRESS or sth' #1 #2 POKE Put #1 into the memory address #2 (synonomous with >MEM) #1 BYTEMEM> #2 As PEEK, but for bytes (8-bit) #1 #2 >BYTEMEM As POKE, but for bytes (8-bit) Note: to move lots of bytes or convert them, see bytes2nums etc ^#1 ^#2 ^#3 FILLCHAR 1:Address, 2:count, 3:character In a GETMEM area, you can fill it fast up with a character (uses varstk) ^#1 ^#2 ^#3 FILLNUMS 1:Address, 2:amount4bytes, 3:bignumber In a GETMEM area, you can fill it fast up with a number (uses varstk) ^#1 FASTRFFG ^#2 As RFFG but both input and output comes on varstk and this is fast in big loops :A #1 PUTTEXT GETMEM gives you a free mem area, say, at least 256 characters. Then you can store it (watch it!) there. #1 GETTEXT :A After PUTTEXT has stored :A at #1 you can retrieve :A by giving exact same position (cfr >BYTEMEM / NUMS2BYTES) #1 #2 BITSRIGHT #3 Move #1 #2 bits right so that the number #1 is decreased #1 #2 BITSLEFT #3 Move #1 #2 bits left so that the number #1 is increased ^#1 ^#2 BITSRIGHTS ^#3 On simplestk ^#1 ^#2 BITSLEFTS ^#3 On simplestk SOME COMMENTS [based on earlier versions, though, of the language -- before Lisa GJ2 FIC3 was really clear] (( )) Acknowledgements -- please see MTDOC.TXT in GJ2.ZIP and in the earliest Firth version from March 2006 as eg at yoga6d.org/minigj2.htm. (( )) The symbol (( )) is used to indicate a distinction between paragraphs here, in a way which is somewhat stronger than a mere lineshift with indent, like in the next line: But the symbol (( )) also of course reminds us of waves and wholeness and the tantric, as well as of parameter transfer in the Lisa programming language. (( )) (( )) In programming, we are instructing a machine to act for us. Why? Why not just drawings in colored sand, as it is said that some meditators do? The machine is a meditation device when programmed well, with a human instinct, a warmth of hearth, a respect for mind, and in this perspective, we allow all the activities of the machine, practical in an office set or not, to be guided by such an artistic, esthetical intent, and with a life-affirming, nonreductionistic sense of life. So, we are careful in using unnecessary frames or unnecessarily much grey, but rather emphasize young spring life, as light green and other colors, and meditative blue on writing; and while we allow of course for some photo-resemblancy and/or video like segments we do not encourage too much mimicking of nature, or simulation of natural beings, but rather focus more on what we can call 'psychedelic computer graphics' than on '3d computer graphics' (thus the Yoga - 4 - d). So the vector/polygon/transformation exercises as part of the earlier works in Firth234.c we have not bothered to on with. It is important to emphasize that computation should never, never be everything. It is not a moot point to ask whether we need any computers at all, apart from all hype and fashion. It is a refreshing question. But I think it is quite clear that programming computers involves a very economical kind of inventiveness -- which, as soon as you have one solid good computer (and its programming language) going, allows for infinitely many variations. And being inventive, with an ethical, good intent, encourages enlightenment, meditative living, holistic feeling of freshness -- we are at our most happy when we do youthful creationship. First-hand hardware, first-hand software, first-hand mechanics, first-hand photography, even first-hand music -- these are but some of the innumerable terms we may coin on the basis of having a human heart and a direct perceptive relationship to what we do. In emphasizing psychology, we must negate too many things which are merely habitual and ask for the warm minimalism -- the essence -- which brings content in focus. Is it necessary to have a pointer device (e.g. like mouse or a pressure tablet) active e.g. when one does typewriting? And if it is not necessary, let it go away; and rather let the remaining elements on-screen have a healing functional esthetics, a kind of functionalism in which the meditative function is combined with the practical. The functionality of the large library of available functions and also available data variables encourages, I hope, a sense of affluence rather than a sense of confusion. You can perfectly well build up a large number of algorithms based on a small subset; but why not use most of these, when they are there? When you find a variable which is used only in connection to a particular function, you might use it for your own functions; but in some cases, just to be free to call on that function in the future from within that program in some future version of it, you might want to make a new variable specially for your program. In encouraging tiny program names for the main programs -- so that they coalesce with filenames, 8 chars in size (ie, 8 letters and/or digits with hyphen and/or dash also, completed by the compulsory .TXT), you can simply preceede the variable name with the program name to indicate which is which. Start up LISA and simply type in a name to check if it is already defined. If it says something about looking in a manual, it is not defined. If there is either no action (because nothing is on the stack for it, perhaps) or some action connected to it, then it is defined, and you may want to look it up and get familiar with it. (( )) On program correction, there is a right and a wrong way to do it. Beginners, with all respect, please decode what I say in this paragraph. While you work on getting a totally new program to perform as it should, put a VISIBLECOMPILATION and maybe also a COMPILEPAUSED (in one of its versions) sometimes, and put a number of LOOKSTK around in the program, test a little by little, stay tuned and be a perfectionist in getting it all to work. When LOOKSTK is used, the compiler / performer tries to be as polite as it can be and there is a message like 'Hello, this is just a hi from the MT language', this being one of its earlier ideas for names. Don't push the PC nor try to squeeze the utmost of computational efficiency or RAM because it is a tendency of well-made program that they have a sense of leisure and luxury in how they are made; but sometimes make them go faster, because it is sensitive to do so; and sometimes think anew what type of data structure you really need if it gets so huge it makes the program rather slowish (for instance, if you are doing a four-dimensional matrix, really think about its size, think about how much you actually need to model along each dimensional aspect). Always keep in mind that the computer is a psychological, or semantic, object, and so should the programs be, and so also its data space: don't let us try to make computers too ultra-this or ultra-that, but let's keep them on a level where we feel we are communicating and collaborating with them in our program development and in our program performaces and interactions, also when we bridge computers in Lisa networks and such. Unless there are very good reasons for it, a function should be tiny and work on each function with a number of tests -- pushing the limits of the types of inputs (if any) that the function can accept, and watching how it behaves, through simple example programs. Lisa is eminently suitable for testing since it allows you to keep the program going in RAM and do manual checks on variables by simply omitting the 'XO' call after the program has run. One can put in several extra 'LOOKSTK' calls to check on the stack ('look at the stack'). A really good program documents itself simply by the beauty of how it is built. One of the great advantages of not having too many new named local variables but to stay on using standard local variables like N1, N2 up to N11, and such, is that one is led to think about what in fact these variables do refer to, and not merely stay on what they are intended to refer to. For when one need to understand a program, one should pay attention to its actions, and the storage-locations should not look like actions on their own. Lisa is made also on the premise of easy of program design & correction. And program correction is part of making a program. One calculates not only how to get the ideas sketched, and the time involved to get them translated to a formal expression of an initial kind, but one calculates also the time to fix 'em up, and this often takes the major bulk of the time. And it is part of the flow to expect this and enjoy this. And, so, I think one can say this: The right way to do program correction is to understand what the function is supposed to do, and compare with a full understanding of what it does, and then correct how it is made so it does what it is supposed to do; or else change what it is supposed to do as well as how the function is used. Put very simply, the wrong way is add a little or substract a little to a function which almost works until it works without looking into what is substracted or added or why it is so that it seems to work a little better when something is added or substracted in this way. For that which is a tiny anomaly of a function, like the left-over of an extra stack item after it has performed, can be something which is like Aristotle said -- 'a small error in the beginning can become a big error eventually' -- it can be a sign of something much more serious than a mere extra item. It may be, of course, that all it takes is to count the amount of items better and do something like adding an extra RM towards the completion of the function. But it may also be something much more intricate. For instance, it may be a leftover from one of the functions it calls on; and this left-over may propell itself into the millions if another function calls on that erroneous function by means of a loop; doing that loop is then likely to cause the PC to have to reboot, and one must spend time on tracking down why it does so. If one at once addresses each slight element of confusion clearly, and pays attention to it until one has healed it fully, one is able to build programs which has a stability, a robustness, and a coherence with what they are supposed to do, which is excellent; and this is how Lisa programs are all supposed to be. Of course there are situations in which speedy action is called for and a quick hack, socalled, which makes a program which nearly works apparently working, will be the only type of action that there is time for, at first; but one should never make such quick hacks into a habit when it comes to program correction. The right idea on program correction is to assume that which seems to be a universal phenomenon, namely that, given any perceptive task of complexity which is to be given a proper formalism, then, no matter how appropriate the language of the formalism is, the initial expression must be corrected and the duration it takes to correct it is typically at least as long (and usually significantly longer) than the initial expression. It is of value to give one's ideas a speedy and somewhat sketchy initial expression; but then one must also be realistic and assert that program correction is going to be given real serious time. It is also often the case that entirely new program challenges involves a vast number of various alternatives in just how these can be expressed, and that one should not too quickly go into a consolidation phase and specify the algorithms one likes to have and all that; rather, one should sketch/express, and maybe dissolve that, and sketch/express in another way, and maybe dissolve that; then maybe wait; then sketch/express and do some program correction and testing -- and maybe go another round, saving portions of that and combining with a blend of fresh ideas sketches and expressed and corrected -- and in that way manufacture the various aspects of the program as a coherent whole. This, then, is, in succinct form, the art of programming -- not a mechanism. In neopopperian science, we regard the interaction with Lisa GJ2 Fic3 as a form of sensory feedback which refers to the quality, content, quantitative finesses and so and so forth of the Lisa formalism. The word 'Lisa' is appropriate also because it rhymes with formalism, and is a genuine essence of what it means to do anything in terms of a formalism. The personal computer, the PC (of Y2000-compliant kind or the special GJ kind we make sometime in the future to run a GJ2 edition of the Lisa, largely as here), provides then a kind of empirics which of course must not be confused with the empirics of the universe, -- it must not be confused, of course, with experiences of Nature, of people, of stars, etc. Nevertheless, it comes into the category of empirics. But it is an empirics which is shaped directly by our thoughts, and that's the beauty of formalism as it merges with hardware in this way. Now, any complex expression is likely to entail very many unforeseen implications. When these implications work on each other, we have something more than our mere intentionality; we have an unfoldment of order (to lend a terminology from my physics mentor David Bohm). And this order may have results which are not quite in obvious alignment with our intentions; and so we stay attuned to our intentions with this feedback -- and this happens during program correction -- that we thereby correct our formalism. This is a highly creative and fantastic process; and all the more so since it does not depend on the corrobation of a corrupt board of quasiscientists who happens, by means of mutual bribery and misunderstood notions of loyality as confused with science, -- but it simply depends on the lucidity of your own thinking-feeling/process as you communicate and interact with the computer in getting that which you have visualized to occur, to occur, and more things around it which you maybe didn't intend, but which seems to be fully coherent with it in a substantial way. In short, the making of a program means not only to leap forth with some expressions from an intentionality, but also to explore the implications of these expressions and correct on them until the structures are so as to be coherent with a deeper intent. This will be a process in which we do not need a derailing term as 'debug'. We may, for instance, print out temporary variable results, and dots or stars each time there is a loop, and so participate in a neopopperian open-minded exploration of what the computer does when it encounters our formalism, our program. Then we also learn more about the programming language, and this enables us to do certain things faster in the future. But there will always be elements of exploration of new and nonobvious implications of our formalisms. Ultimately, this is an endless process. If you have a zest for harmony and beauty, then you have a zest for programming. It is a form of meditative unfoldment, and encourages the best of all the young aspects of you, forever, as rejuvenation. Wodehouse reputedly said, there are two ways of writing, one is to merely write deep down into reality and not care, and the other way is to think like music, write like music -- harmonious music. You may have noticed that in Wodehouse's comedies EVERYTHING WORKS OUT WELL for just about everyone. You can therefore allow yourself to identify with the important elements of the story, to some extent. This means that Wodehouse writes based on an intent of harmonious, happy completion, and creates events so as to fulfill this effortlessly and elegantly. THIS IS EXACTLY WHAT A PROGRAMMER MUST DO. This is geometry, geotechnology, genius, the myth of coherence -- the real myth of peace, of harmony. Bringing wholeness to what you are doing. Taking responsibility to be a good citizen. At each stage, ask: what is effortless and elegant to do as the one next step, and which is relevant to where you are going? And sometimes lean back in your bathtub and simply visualize the whole result, enjoy it, and then look into the particulars you have to create this result with, and enjoy the spectacle of visualizing how individual issues might have to be resolved. But just as with real writing, it is a journey, and, for instance when you do a visual expression involving thousands of pixels it will be an emergent quality of a new perception which is not obvious from what you put into it -- and which 'suggests things', by itself, -- and which can lead to new leaps; and then you must ask whether it is coherent with the result. If you are lucky enough to make money on products you develop yourself, hardware as software, perhaps you can branch fruitfully into new projects by developing ideas you get when you permute algorithms together. (( )) One makes Lisa programs is by making new functions and associated data structures. These functions can, unlike e.g. classical Algol or classical Pascal, but like more object-oriented inspired languages including Free Pascal and the variations of C / C++, be addressed directly e.g. through lists or through variables which can hold what is in some languages called 'pointers' to them; this is also shared with Forth from the 1960s by Chuck Moore, which has the sequence of parameter transfer found here; the use of the arrow => is as the textual output of the COPY command when entered in Lisacode which is based on FREEDOS in a modified early form as GNU GPL kernel from www.freedos.org (vastly expanded on in this context, and standardized in a way not found there). The command LISA is in general followed by the command :MYPROG IN where MYPROG.TXT is the name of the program put to the C:\BOEHM\BOEHMIAN directory, or :/MYPROG IN when MYPROG.TXT (max 8 characters, plus dot, plus TXT, no blanks, usually only letters and digits and a few more types of signs) is at the top directory, or :MYFOLD/MYPROG IN when it is a folder called MYFOLD (or the like) under the standard folder C:\BOEHM\BOEHMIAN. In $$$ Lisacode $$$ the reference is with backslash; in Lisa, the proper reference is with forwardslash for all internal functions. (However Lisa can call on Lisacode in which case backslash should be used.) (( )) The comments above indicates that the Lisa language is not merely algorithmic or functional, nor merely class/object oriented as in the language Simula67 by Ole-Johan Dahl and Kristen Nygaard (which led to the varieties of class/object-oriented languages), but of a kind which is implicit in all language in which functions can be handled through memory pointers, but explicit here in terms of standardisation and semantic ease. Since the word 'pointer' seems to emphasize a distinction which is strong, and since it does not properly convey the near-assembly immediacy with which this language is handling the issue, there is the suggestion in Lisa to call the immediacy of connecting to a function by means of a number holding its position in RAM by a 32-bit structure for a 'warp'. The ease and optimism with which Lisa have been crafted around the notion of warps lends power to the assertion that Lisa can be said to be a warp-friendly language, then. This phrase, coined by this writer, implies that warps are an option but not a necessity (thus it is not as much a direction as a warm welcoming route of action for those who like it). (As acknowledged plenty earlier on, this writer recalls affectionately the many warms conversations with one of the authors of Simula67 up to the very beginning of the third millenium, namely with Kristen Nygaard, known through family since in the 1960s my father Stein Braten worked with Nygaard's language doing simulation of a theory on behaviour relative to voting with the version of Simula before it achieved inheritance classes, and in which objects were called 'activities'.) (( )) To make a new function in the Lisa language, the typical format (although other formats with essentially or exactly the same result are available) is: (LET function-name BE (( input-parameter-indications.. )) (( (( general-action-1 )) (( general-action-2 )) (( .. )) )) OK) Note: The compiler won't protest if one tries to define something which one cannot define but generally it won't be available unless the name makes sense and is not a native word. In this case, the lower-case words indicates something which should be replaced with proper content, which, in the general convention, except in quotes, is uppercase. The parameter flow is generally from left to right, and from one line to the next line, but moves not directly from a function or value to the next function or variable, but through stacks, of which there are four major: the main stack, holding letters, words, as well as numbers, and even long text lines up to 250 characters, the simple stack, which offers local variable treatment for whole numbers and warps, the variable stack, which is a convenient way to store warps, sometimes also between functions, and the decimal number stack, called also rich stack, metaphorically also because one can enter numbers to it directly rather than through the main stack by prefixing with a dollar sign. Prefixing with ~ puts a number on top to the simple stack. Prefixing with a ^ puts a number on top to the variable stack (which is more used than the ~, by the way). No prefix of a number means that it goes to the main stack. So does a word which is quoted; quoted either by prefixing with a colon, completing with a comma (see also LISTOK because this affects a counter), or, in the case of something such as a sentence which can contain blanks, prefixing with a right curly bracket } and also completing the quote with the same, as in (( }Hello world!} => POP )) The role of the (( and )) is in giving a semantic idea as to what constitutes some kind of whole in action. Only in the case of (LET and OK) and some other words in which the parenthesis are 'melted together' with the word are they of necessity to write just there. The arrow, too, is a semantic device, rather like comma in a language like English which normally can be omitted but which it is part of the definition of the Lisa language, alongside the (( and )), to assert as an important semantic device. Of the same nature is the semicolon, for instance as in (( 2 ; 3 => ADD => POP )) which is used basically to say -- there is something on stack after this operation and for the time being we leave it there. This can also sometimes be useful after a (( .. )) operation has logically completed but with a residue handled a couple of lines further down in the function. It can also often be used right after the (( starting a statement when one picks up what is on the stacks referring to above in the function. For instance in this function (LET THREE-POP BE (( ; ; ; )) (( (( ; ; ; => POP => POP => POP )) )) OK) there is nothing really that should be done about the stacks initially in the first (( )) so three semicolons there are used to indicate that this function is made with the intention to receive three input parameters. On the first line inside the function we see again the three ; ; ; to indicate that within this (( .. )) clause we handle all three of them in some way. A use of the arrow is also to indicate an output from the function, in which case the arrow is generally used twice -- again as a semantic device which strictly technically could be ommitted but it is asserted as part of the Lisa formalism (which obviously have, on the use of parentheses and uppercases and dashes, esthetical similarities with the noteworthy Lisp formalism from the 1950s, but which is otherwise inspired in essence more by Forth yet the main stack and the simple stack are completely novel developments relative to Forth, of course; the word 'hybrid' is sometimes used to indicate what Lisa is -- a hybrid between two languages, Forth and Lisp, in some way, and a hybrid between a language and an operating platform / system as a standard; however the Firth and the Lisa are written entirely from scratch near assembly level of memory handling, of course, with the assistance of the eminently made DJGPP tool and handled by the versatile open source SETEDIT editor by Salvador E Tropea, started by the command TEXT, or E, at $$$ Lisacode $$$ and extremely competently made even for vast-sized documents of a standard 7-bit ascii form). An example of output from a function, which also shows how input can be handled in two ways: (LET MUL3-VER-1 BE (( >N3 >N2 >N1 )) (( (( N1 ; N2 => MUL ; N3 => MUL => => )) )) OK) (LET MUL3-VER-2 BE (( ; ; ; )) (( (( ; ; ; => MUL => MUL => => )) )) OK) When it is known that the use of the function in general tends to be not that time-critical, the MUL3-VER-1 handles numbers with an ease which tends to pay off in somewhat more complicated functions, in which N1..N11 can leisurely be used to indicate the input in the sequence it was given, e.g. will (( 3 ; 5 ; 8 => MUL3-VER-1 => POP )) lead to 3 going to N1, 5 going to N2 and 8 going to N3. The convention in Lisa is therefore, when we have to do with plain number input, to put a sequence of up to 11 >Nnn in reverse order (since the topmost number is going to the highest-numbered Nnn). It is to be noted that the >N1..>N11 and the readings of them, N1..N11, refer to 11 free slots always automatically and speedily allocated to a function on its entrance and unallocated on its exit, -- a feature evolved on the journey away from Forth and over to a new type of language in which the sense of clutterings about stack handling is reduced to a comfortable minimum. (It is for this reason the ~ operator to push new numbers on top of the simple stack is rarely used.) However, when the operation is rediculously simple and the amount of numbers in are many, and/or the operation is known to be called on in a time-critical fashion, the MUL3-VER-2 is a perfectly meaningful format also. In the cases of inputs such as texts, it is a convention to most often use a semicolon for each of these inputs so as to show the reader of the definition the intended amount of items in, but in some cases it makes sense to do a light operation on the text already in the first (( )) clause, which is after all fully capable of having any sort operation since the (( )) divisions are semantic entities not precluding any type of algorithmic operation. A good example of this can be this, which tells, in text mode, on-screen, the length of an input text: (LET TELL-LENGTH (( ; => LENGTH => >N1 )) (( (( ; => RM )) (( }The length of the text is} => POPS )) (( N1 => POP )) )) OK) This is but one example of very many ways in which this could have been written. The single semicolon indicates that it is but one input expected; moreover, the length of it (the amount of characters, blank included), is stored in position N1. At the first line after this, the text itself is removed, since we are only interested in the length in this particular case. The POPS prints a line without lineshift but with a space character afterwards instead; and N1 => POP ensures that the length is printed out. If we have need for the text we give to TELL-LENGTH we can copy it first; since the main stack of Lisa is relatively fast and since it is a well-known boundary of size of the elements, that these are generally not longer than a textline, there is a number of quick operations, including ONE to copy the topmost item, TWO to copy the two topmost items, keeping their sequence, THREE to copy the three topmost items, also keeping their sequence, ANGEL to switch around the sequence of the three topmost items, and many more such. For instance, we might do this, either outside a function or typed directly in at the interactive compiler after the above function is typed in (this interactive feature a friendliness and a "You-ness" also found in Forth, Basic and which some languages including Perl can give if they are made to work like this with a little input loop and parsing, and this encourages a learning intimacy which also proves to be a quick way of exploring any half-known algorithm and to find out whether a word is previously undefined or not -- and many more things besides). Here is the example, using ONE, which makes an extra copy of a text before giving it to TELL-LENGTH, so that it can be used by a function after that, in this case POP: (( }This is a text} => ONE => TELL-LENGTH ; POP )) The suggested convention of sign-use in this situation is to use a semicolon to indicate that there is more left on the stack. Though => TELL-LENGTH => POP would in some sense be meaningful, it seems to indicate that TELL-LENGTH is generating the output which is then given to POP; but the above sign-approach solves that. To store a whole number, one can write ((DATA variable-name )) where the lowercase is replaced by a proper uppercase. In this case, there is no initialization value. There is a variety of ways of initializing values, of course, and that is why the beginning ((DATA is defined clearly whereas what comes before the completing )) is rather open. It is an implemented syntax in Lisa to speak of two very often-used values in programming, namely zero and 1, by the poetically friendly word 'basis' and 'dance'. For instance, ((DATA AMOUNT-ALLOCATED AMOUNT-ALLOCATED => SETBASIS )) would put it to zero while ((DATA PAGE-NUMBER PAGE-NUMBER => SETDANCE )) would enable page-number to start at 1. Please initialize rather during program-startup if it may be that the program is restarted without exiting by XO so that RAM is refreshed as any ((DATA .. )) statement happens outside of function definitions, and is performed actually while the program text is compiled. Although syntactically you can make new numerical variables with ((DATA .. )) and new text variables with (( VARSTRING .. )) (and the numerical variables can point to, or warp to, as we say, whole long documents of texts, or images, or even sound files or programs...) anywhere in the program text, after much experimentation it has come to be the recommended practise (anyhow from this author) to put all of these data definitions to the beginning in the program -- right after the commentaries setting forth who and what and when -- and right before the first function. I can give a lot of logical reasons for this. But there is one big reason for it: good programming needs a focus on action. What is action must stand clearly forth. A function is action. They should refer to storage locations under neutral names so that attention is not diverted (nor mislead by funny names -- for instance, if a variable is call CORRECT-DATE-TODAY but contains something entirely different this is less informative than a variable called DATE-1 or even just N1). But if we distribute ((DATA ..)) and (( VARSTRING .. )) definitions here and there, say, before the first couple of functions which might use each, then that clear distinction is getting spoiled. Putting them up front prepares the mind for them: okay, folks, here are the storage rooms -- use them as you please, but know that these are but storage rooms and there is nothing much more about them. Then, folks, here is what the program really is doing. I have elsewhere spoken strongly out against the notion that programming is improved by dividing it in blocks with different naming conventions, localized names, and hierarchies of schemes of assigning functions to groups of data -- it may work best in extremely hierarchical, factory-like companies when these work bureacratically with with rigid, bank-like system practise for collaboration between people and also collaboration between programmers. But such object/class/ hierarchy of programming tends to consume hours if not months of attention to petty details of rigid structure rather than to the perfection of a program. The program text is compiled each time during startup because this is fast enough and because this asserts that there is a minimum of cluttering of files present on disk, a maximum of open source readability, and more advantages of this type. Another common way of initializing is by means of <>> is used, and >>> actually has a computational function. In the earlier edition of Lisa, the =-> was its appearance, and that version can still be used, but >>> is clearer, I find. (( }The right margin is now} => POPS )) (( RIGHT-MARGIN >>> => POP )) A predefined function, of so-called the basic (historically, by me, called Firth) kind, is the function ( which is like POPS except that there is no blank after. This is useful also when quick checking on stack content is sought e.g. during program correction, when one can type such as RIGHT-MARGIN >>> ( at the interactive compiler, in such cases consciously and deliberately using a syntax completely without any extra semantic elements in order to get an as quick and prompt response from the compiler as possible with the minimum of typing. The text line can be stored in such a variable as (( VARSTRING DAY }Monday} DAY => >VARSTR )) and this can be retrieved e.g. by (( DAY => VARSTR> => POP )) In cases where many text lines is sought to be stored, the typical way is by means of a matrix which is defined by means of the Lisa word RAM-PM, which has as input the amount of rows and the amount of columns. It is a programming praxis in Lisa to always give some extra room to variables and always have some extra amount of columns beyond what's strictly necessary. This praxis is an advised feature, and in some cases, as when a matrix is put to, or retrieved from, disk file, a necessity; but sometimes, for very large matrices (and in such cases where the disk file operators FILE2PM and PM2FILE are not used) containing a very large amount of numbers one might be more precise in allocation. In general, 32-bit numbers, typically within the range of plus minus two billion, should be used in preference to decimal numbers or other number types whenever it is suitable in this context. Such a whole number also happens to be the kind of number that a warp is. Thus, if we make a variable like ((DATA CLS-HOUSE }CLS} => ? CLS-HOUSE <>> => H )) would do. If we rather make a new function which e.g. paints half the screen blue and wants a sudden change in the program which calls on the line just given each time the screen is to be changed all we have to do is something like this -- while the program is running, inside the program, to change the defined functionality: (( }PAINT-HALF-BLUE} => ? CLS-HOUSE < VISBASIS (MATCHED (( HAS-BUILT-COLOR-TABLE => SETDANCE )) (( GETPAL )) (( ^0 => READPAL ; ; ; )) (( ### ; 1 ; 256 ; THE-COLOR-LIST >>> => PM )) (( ## ; 2 ; 256 ; THE-COLOR-LIST >>> => PM )) (( # ; 3 ; 256 ; THE-COLOR-LIST >>> => PM )) (( && && && )) (( 255 (COUNT (( N1 => & => READPAL ; ; ; )) (( ### ; 1 ; N1 ; THE-COLOR-LIST >>> => PM )) (( ## ; 2 ; N1 ; THE-COLOR-LIST >>> => PM )) (( # ; 3 ; N1 ; THE-COLOR-LIST >>> => PM )) (( && && && )) COUNTUP) )) MATCHED) )) )) OK) (LET MAXIMUM-OF-THREE BE (( >N3 >N2 >N1 )) (( (( N1 ; N2 => INTGREATER (MATCHED (( N3 ; N1 => INTGREATER (MATCHED N3 => => )(OTHER N1 => => MATCHED) )) )(OTHER (( N3 ; N2 => INTGREATER (MATCHED N3 => => )(OTHER N2 => => MATCHED) )) MATCHED) )) )) OK) (LET NEAREST-GREEN BE (( >N1 )) (( (( THE-COLOR-LIST >>> => & )) (( (( 1 ; N1 ; # => GM )) ; (( 2 ; N1 ; # => GM )) ; (( 3 ; N1 ; # => GM )) => MAXIMUM-OF-THREE => 64 MOD ; 128 => ADD => => )) (( && )) )) OK) (LET CENTER-I9-IMAGEESSENCE BE (( )) (( (( V11 => NEAREST-GREEN => TOV11 )) )) OK) (LET CENTER-IMAGE BE (( & )) (( (( I9-IMAGEIS-CENTERED => SETDANCE )) (( ASSERT-HAS-BUILT-COLOR-TABLE )) (( CENTER-I9-IMAGEHOUSE >>> ; # => FORVPM )) (( && )) )) OK) (( }CENTER-I9-IMAGEESSENCE} => ? CENTER-I9-IMAGEHOUSE < MAKEBL ; B9-READLN-LINE => >VARSTR )) )) OK) (LET %ADDPUT BE (( & ; ; )) (( (( ; ; => ONE ; # => %GET ; ANGEL => ADD ; SWITCH ; # => %PUT )) (( && )) )) OK) (LET I9-INIT-VARS BE (( )) (( (( I9-IMAGEIS-CENTERED => SETBASIS )) (( HAS-BUILT-COLOR-TABLE => SETBASIS )) (( 3 ; 256 => RAM-PM THE-COLOR-LIST < >VARSTR )) (( 200 ; 200 => RAM-PM I9-IMAGE < %MAKE I9-AUX-ARRAY < %MAKE I9-AUX-ARRAY-PM <>> ; 1 ; I9-AUX-ARRAY-PM >>> => %PUT )) )) OK) (LET I9-NEW BE (( )) (( (( I9-IMAGE >>> => & )) (( 480 ; 180 ; 719 ; 423 ; 1 => RECTFILL )) (( 500 ; 200 ; # => LISA-PAINT )) (( && )) )) OK) (LET I9-MAKE-TEXTURE-LINES BE (( )) (( (( I9-IMAGE >>> => RELEASE-MATRIX )) (( 200 => %MAKE ; I9-IMAGE < MOD4 => ISBASIS (MATCHED (( 200 ; 255 => %RFFG ; N1 ; I9-IMAGE >>> => %PUT )) )(OTHER (( 200 => %MAKE ; N1 ; I9-IMAGE >>> => %PUT )) MATCHED) )) COUNTUP) )) (( I9-NEW )) )) OK) (( LOOKSTK )) (LET I9-FRONTPAGE-MENU BE (( )) (( (( }i9 image editor Created by Aristo Tacoma in Lisa } ; 180 ; 80 => B9-POP )) (( }Please indicate your wish:} ; 180 ; 120 => B9-POP )) (( }1. Open file} ; 100 ; 240 => B9-POP )) (( }2. Save file} ; 100 ; 280 => B9-POP )) (( }3. Modify} ; 100 ; 320 => B9-POP )) (( }Honor the tantric;} ; 150 ; 503 => B9-POP )) (( }Thank you.} ; 150 ; 600 => B9-POP )) (( }Or [ESC] to exit.} ; 700 ; 650 => B9-POP )) (( I9-NEW )) (( I9-IMAGEFILENAME => VARSTR> ; }.TXT} => CONCAT ; 510 ; 450 => B9-POP )) )) OK) (LET I9-OPEN-FILE BE (( )) (( (( I9-IMAGE >>> => & )) (( CLS )) (( }O P E N e.g. SAMPLE or SAMPLE2} ; 50 ; 100 => B9-POP )) (( }The format: 'Lisa smart painting', GJ-COLORS, 200 x 200 std.} ; 50 ; 140 => B9-POP )) (( }See manuals incl. Study handbook in neopopperian science.} ; 50 ; 180 => B9-POP )) (( }Please make sure the .TXT format is right (or prog will exit!!!)} ; 50 ; 220 => B9-POP )) (( }Filename, thank you (not including .TXT): } ; 50 ; 300 => B9-POP )) (( 17 ; 550 ; 300 => B9-READLN )) (( ; => RMBL => UPCM => LENGTH => ISPRO (MATCHED (( ; I9-IMAGEFILENAME => >VARSTR )) (( # => CLEAR-MATRIX )) (( I9-IMAGEFILENAME => VARSTR> ; }.TXT} => CONCAT ; # => FILENUM2PM ; RM )) (( I9-IMAGEIS-CENTERED => SETBASIS )) )(OTHER (( RM )) MATCHED) )) (( && )) )) OK) (LET I9-SAVE-FILE BE (( )) (( (( (( I9-IMAGE >>> => & )) (( CLS )) (( }Here we *****save***** the file. If filename already exists,} ; 50 ; 100 => B9-POP )) (( }it is overwritten directly, so >>>make sure it is right<< B9-POP )) (( }Only letters, digits, hyphen (_), and dash (-), and max 8.} 50 ; 180 => B9-POP )) (( }If you press ENTER, this name is used>>> } ; 50 ; 220 => B9-POP )) (( I9-IMAGEFILENAME => VARSTR> ; 600 ; 220 => B9-POP )) (( }S A V E N A M E (not including .TXT): } ; 50 ; 300 => B9-POP )) (( 17 ; 550 ; 300 => B9-READLN ; )) (( ; => RMBL => UPCM => LENGTH => ISPRO (MATCHED (( ; I9-IMAGEFILENAME => >VARSTR )) )(OTHER (( RM )) MATCHED) )) (( I9-IMAGEFILENAME => VARSTR> ; }.TXT} => CONCAT ; # => PM2FILENUM ; RM )) (( && )) )) OK) (LET I9-IMAGEPERMUTE-UP-ESSENCE BE (( )) (( (( INCV11 )) )) OK) (LET I9-IMAGEPERMUTE-UP BE (( )) (( (( I9-IMAGE >>> => & )) (( I9-IMAGEPERMUTE-UP-HOUSE >>> ; # => FORVPM )) (( I9-NEW )) (( && )) )) OK) (( }I9-IMAGEPERMUTE-UP-ESSENCE} => ? I9-IMAGEPERMUTE-UP-HOUSE <>> => & )) (( I9-IMAGEPERMUTE-HOUSE >>> ; # => FORVPM )) (( I9-NEW )) (( && )) )) OK) (( }I9-IMAGEPERMUTE-ESSENCE} => ? I9-IMAGEPERMUTE-HOUSE < MOD ; 129 => ADD => TOV11 )) )) OK) (LET I9-IMAGECOLLECT BE (( )) (( (( I9-IMAGE >>> => & )) (( I9-IMAGECOLLECT-HOUSE >>> ; # => FORVPM )) (( I9-NEW )) (( && )) )) OK) (( }I9-IMAGECOLLECT-ESSENCE} => ? I9-IMAGECOLLECT-HOUSE < MOD ; 147 => ADD => TOV11 )) )) OK) (LET I9-IMAGECOLLECT-OTHER BE (( )) (( (( I9-IMAGE >>> => & )) (( I9-IMAGECOLLECT-OTHER-HOUSE >>> ; # => FORVPM )) (( I9-NEW )) (( && )) )) OK) (( }I9-IMAGECOLLECT-OTHER-ESSENCE} => ? I9-IMAGECOLLECT-OTHER-HOUSE < MOD ; 100 => ADD => TOV11 )) )) OK) (LET I9-IMAGESHIFT BE (( )) (( (( I9-IMAGE >>> => & )) (( I9-IMAGESHIFT-HOUSE >>> ; # => FORVPM )) (( I9-NEW )) (( && )) )) OK) (( }I9-IMAGESHIFT-ESSENCE} => ? I9-IMAGESHIFT-HOUSE < ISBASIS (MATCHED (( V5 INC => TOV2 )) )(OTHER (( ^19 FR GETV => ISDANCE (MATCHED (( ^30 FR GETV 30 ADD ; 128 => ADD => TOV11 )) MATCHED) )) MATCHED) )) )) OK) (LET I9-IMAGEADD-TEXTURE BE (( )) (( (( I9-IMAGE >>> => & )) (( I9-IMAGEADD-TEXTURE-HOUSE >>> ; # => FORVPM )) (( I9-NEW )) (( && )) )) OK) (( }I9-IMAGEADD-TEXTURE-ESSENCE} => ? I9-IMAGEADD-TEXTURE-HOUSE < SET-RANGE )) ; (( V2 ; (( V3 => DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) )) OK) (LET I9-IMAGEVAGUER-2-ESSENCE BE (( )) (( (( (( (( V2 ; 200 => MOD )) ; 1 => INTGREATER )) ; (( 199 ; (( V2 ; 200 => DIV )) => INTGREATER )) => AND (MATCHED (( V11 ; 64 => MOD => -45 ADD => 16 DIV => >N1 )) (( N1 ; V2 DEC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 INC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 ADD ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 SUB ; I9-AUX-ARRAY >>> => %ADDPUT )) MATCHED) )) )) OK) (LET I9-IMAGEVAGUER-3-ESSENCE BE (( )) (( (( V11 ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEVAGUER BE (( )) (( (( I9-IMAGEIS-CENTERED => VISBASIS (MATCHED (( I9-IMAGE >>> => CENTER-IMAGE ; I9-NEW )) MATCHED) )) (( I9-AUX-ARRAY >>> => %EMPTY )) (( I9-IMAGEVAGUER-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGE >>> => CLEAR-MATRIX )) (( I9-IMAGEVAGUER-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-IMAGEVAGUER-3-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEVAGUER-1-ESSENCE} => ? I9-IMAGEVAGUER-1-HOUSE < ? I9-IMAGEVAGUER-2-HOUSE < ? I9-IMAGEVAGUER-3-HOUSE < SET-RANGE )) ; (( V2 ; (( V3 => DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) )) OK) (LET I9-IMAGEBRIGHTEN-COLORS-2-ESSENCE BE (( )) (( (( (( (( V2 ; 200 => MOD )) ; 1 => INTGREATER )) ; (( 199 ; (( V2 ; 200 => DIV )) => INTGREATER )) => AND (MATCHED (( V11 ; 64 => MOD => -5 ADD => >N1 )) (( N1 => ISPRO (MATCHED (( N1 ; 17 => DIV => >N1 )) (( N1 ; V2 DEC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 INC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 ADD ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 SUB ; I9-AUX-ARRAY >>> => %ADDPUT )) MATCHED) )) MATCHED) )) )) OK) (LET I9-IMAGEBRIGHTEN-COLORS-3-ESSENCE BE (( )) (( (( V11 ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEBRIGHTEN-COLORS BE (( )) (( (( I9-IMAGEIS-CENTERED => VISBASIS (MATCHED (( I9-IMAGE >>> => CENTER-IMAGE ; I9-NEW )) MATCHED) )) (( I9-AUX-ARRAY >>> => %EMPTY )) (( I9-IMAGEBRIGHTEN-COLORS-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGE >>> => CLEAR-MATRIX )) (( I9-IMAGEBRIGHTEN-COLORS-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-IMAGEBRIGHTEN-COLORS-3-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEBRIGHTEN-COLORS-1-ESSENCE} => ? I9-IMAGEBRIGHTEN-COLORS-1-HOUSE < ? I9-IMAGEBRIGHTEN-COLORS-2-HOUSE < ? I9-IMAGEBRIGHTEN-COLORS-3-HOUSE < SET-RANGE )) ; (( V2 ; (( V3 => DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) )) OK) (LET I9-IMAGEMATT-SMOOTH-2-ESSENCE BE (( )) (( (( (( (( V2 ; 200 => MOD )) ; 1 => INTGREATER )) ; (( 199 ; (( V2 ; 200 => DIV )) => INTGREATER )) => AND (MATCHED (( V11 ; 64 => MOD => -32 ADD => >N1 )) (( N1 => ISPRO (MATCHED (( N1 => 16 DIV => >N1 )) (( N1 ; V2 DEC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 INC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 ADD ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 SUB ; I9-AUX-ARRAY >>> => %ADDPUT )) MATCHED) )) MATCHED) )) )) OK) (LET I9-IMAGEMATT-SMOOTH-3-ESSENCE BE (( )) (( (( V11 ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEMATT-SMOOTH BE (( )) (( (( I9-IMAGEIS-CENTERED => VISBASIS (MATCHED (( I9-IMAGE >>> => CENTER-IMAGE ; I9-NEW )) MATCHED) )) (( I9-AUX-ARRAY >>> => %EMPTY )) (( I9-IMAGEMATT-SMOOTH-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGE >>> => CLEAR-MATRIX )) (( I9-IMAGEMATT-SMOOTH-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-IMAGEMATT-SMOOTH-3-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEMATT-SMOOTH-1-ESSENCE} => ? I9-IMAGEMATT-SMOOTH-1-HOUSE < ? I9-IMAGEMATT-SMOOTH-2-HOUSE < ? I9-IMAGEMATT-SMOOTH-3-HOUSE < SET-RANGE )) ; (( V2 ; (( V3 => DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) )) OK) (LET I9-IMAGEODD-LUCIDITY-2-ESSENCE BE (( )) (( (( (( (( V2 ; 200 => MOD )) ; 1 => INTGREATER )) ; (( 199 ; (( V2 ; 200 => DIV )) => INTGREATER )) => AND (MATCHED (( V11 ; 64 => MOD => -48 ADD ; 16 DIV => >N1 )) (( N1 ; V2 DEC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 INC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 ADD ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 SUB ; I9-AUX-ARRAY >>> => %ADDPUT )) MATCHED) )) )) OK) (LET I9-IMAGEODD-LUCIDITY-3-ESSENCE BE (( )) (( (( V11 INC ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEODD-LUCIDITY BE (( )) (( (( I9-IMAGEIS-CENTERED => VISBASIS (MATCHED (( I9-IMAGE >>> => CENTER-IMAGE ; I9-NEW )) MATCHED) )) (( I9-AUX-ARRAY >>> => %EMPTY )) (( I9-IMAGEODD-LUCIDITY-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGE >>> => CLEAR-MATRIX )) (( I9-IMAGEODD-LUCIDITY-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-IMAGEODD-LUCIDITY-3-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEODD-LUCIDITY-1-ESSENCE} => ? I9-IMAGEODD-LUCIDITY-1-HOUSE < ? I9-IMAGEODD-LUCIDITY-2-HOUSE < ? I9-IMAGEODD-LUCIDITY-3-HOUSE < SET-RANGE )) ; (( V2 ; (( V3 => DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) )) OK) (LET I9-IMAGEENHANCE-CONTRAST-2-ESSENCE BE (( )) (( (( (( (( V2 ; 200 => MOD )) ; 1 => INTGREATER )) ; (( 199 ; (( V2 ; 200 => DIV )) => INTGREATER )) => AND (MATCHED (( V11 ; 64 => MOD => -48 ADD ; 32 DIV => >N1 )) (( N1 ; V2 DEC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 INC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 ADD ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 SUB ; I9-AUX-ARRAY >>> => %ADDPUT )) MATCHED) )) )) OK) (LET I9-IMAGEENHANCE-CONTRAST-3-ESSENCE BE (( )) (( (( (( V11 => INC ; 128 ; 191 => SET-RANGE )) ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEENHANCE-CONTRAST BE (( )) (( (( I9-IMAGEIS-CENTERED => VISBASIS (MATCHED (( I9-IMAGE >>> => CENTER-IMAGE ; I9-NEW )) MATCHED) )) (( I9-AUX-ARRAY >>> => %EMPTY )) (( I9-IMAGEENHANCE-CONTRAST-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGE >>> => CLEAR-MATRIX )) (( I9-IMAGEENHANCE-CONTRAST-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-IMAGEENHANCE-CONTRAST-3-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEENHANCE-CONTRAST-1-ESSENCE} => ? I9-IMAGEENHANCE-CONTRAST-1-HOUSE < ? I9-IMAGEENHANCE-CONTRAST-2-HOUSE < ? I9-IMAGEENHANCE-CONTRAST-3-HOUSE < DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) )) OK) (LET I9-IMAGEINVERT-COLORS-2-ESSENCE BE (( )) (( (( 64 ; (( V11 ; 64 => MOD )) => SUB ; 128 => ADD TOV11 )) )) OK) (LET I9-IMAGEINVERT-COLORS-3-ESSENCE BE (( )) (( (( V11 ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEINVERT-COLORS BE (( )) (( (( I9-IMAGEIS-CENTERED => VISBASIS (MATCHED (( I9-IMAGE >>> => CENTER-IMAGE ; I9-NEW )) MATCHED) )) (( I9-AUX-ARRAY >>> => %EMPTY )) (( I9-IMAGEINVERT-COLORS-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGE >>> => CLEAR-MATRIX )) (( I9-IMAGEINVERT-COLORS-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-IMAGEINVERT-COLORS-3-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEINVERT-COLORS-1-ESSENCE} => ? I9-IMAGEINVERT-COLORS-1-HOUSE < ? I9-IMAGEINVERT-COLORS-2-HOUSE < ? I9-IMAGEINVERT-COLORS-3-HOUSE < SET-RANGE )) ; (( V2 ; (( V3 => DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) )) OK) (LET I9-IMAGEDEEPER-COLORS-2-ESSENCE BE (( )) (( (( (( (( V2 ; 200 => MOD )) ; 1 => INTGREATER )) ; (( 199 ; (( V2 ; 200 => DIV )) => INTGREATER )) => AND (MATCHED (( V11 ; 64 => MOD => -48 ADD ; 32 DIV => >N1 )) (( N1 ; V2 DEC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 INC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 ADD ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 200 SUB ; I9-AUX-ARRAY >>> => %ADDPUT )) MATCHED) )) )) OK) (LET I9-IMAGEDEEPER-COLORS-3-ESSENCE BE (( )) (( (( V11 ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEDEEPER-COLORS BE (( )) (( (( I9-IMAGEIS-CENTERED => VISBASIS (MATCHED (( I9-IMAGE >>> => CENTER-IMAGE ; I9-NEW )) MATCHED) )) (( I9-AUX-ARRAY >>> => %EMPTY )) (( I9-IMAGEDEEPER-COLORS-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGE >>> => CLEAR-MATRIX )) (( I9-IMAGEDEEPER-COLORS-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-IMAGEDEEPER-COLORS-3-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEDEEPER-COLORS-1-ESSENCE} => ? I9-IMAGEDEEPER-COLORS-1-HOUSE < ? I9-IMAGEDEEPER-COLORS-2-HOUSE < ? I9-IMAGEDEEPER-COLORS-3-HOUSE < SET-RANGE )) ; (( V2 ; (( V3 => DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) )) OK) (LET I9-IMAGEWILD-EDGES-2-ESSENCE BE (( )) (( (( (( (( V2 ; 200 => MOD )) ; 1 => INTGREATER )) ; (( 199 ; (( V2 ; 200 => DIV )) => INTGREATER )) => AND (MATCHED (( V11 ; 64 => MOD => -32 ADD => DIV4 => >N1 )) (( N1 ; V2 DEC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 INC ; I9-AUX-ARRAY >>> => %ADDPUT )) MATCHED) )) )) OK) (LET I9-IMAGEWILD-EDGES-3-ESSENCE BE (( )) (( (( V11 ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEWILD-EDGES BE (( )) (( (( I9-IMAGEIS-CENTERED => VISBASIS (MATCHED (( I9-IMAGE >>> => CENTER-IMAGE ; I9-NEW )) MATCHED) )) (( I9-AUX-ARRAY >>> => %EMPTY )) (( I9-IMAGEWILD-EDGES-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGE >>> => CLEAR-MATRIX )) (( I9-IMAGEWILD-EDGES-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-IMAGEWILD-EDGES-3-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEWILD-EDGES-1-ESSENCE} => ? I9-IMAGEWILD-EDGES-1-HOUSE < ? I9-IMAGEWILD-EDGES-2-HOUSE < ? I9-IMAGEWILD-EDGES-3-HOUSE < DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) )) OK) (LET I9-IMAGEZING-2-ESSENCE BE (( )) (( (( (( (( V2 ; 200 => MOD )) ; 1 => INTGREATER )) ; (( 199 ; (( V2 ; 200 => DIV )) => INTGREATER )) => AND (MATCHED (( V11 ; 64 => MOD => -32 ADD => DIV2 => >N1 )) (( N1 ; V2 DEC ; I9-AUX-ARRAY >>> => %ADDPUT )) (( N1 ; V2 INC ; I9-AUX-ARRAY >>> => %ADDPUT )) MATCHED) )) )) OK) (LET I9-IMAGEZING-3-ESSENCE BE (( )) (( (( V11 ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEZING BE (( )) (( (( I9-AUX-ARRAY >>> => %EMPTY )) (( I9-IMAGEZING-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGE >>> => CLEAR-MATRIX )) (( I9-IMAGEZING-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-IMAGEZING-3-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEZING-1-ESSENCE} => ? I9-IMAGEZING-1-HOUSE < ? I9-IMAGEZING-2-HOUSE < ? I9-IMAGEZING-3-HOUSE < INTGREATER )) ; (( 101 ; V3 => INTGREATER )) => AND (MATCHED (( V11 ; (( V2 TWICE DEC ; (( V3 TWICE DEC DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) (( V11 ; (( V2 TWICE DEC ; (( V3 TWICE DEC DEC ; 200 => MUL )) => ADD => INC ; I9-AUX-ARRAY >>> => %PUT )) (( V11 ; (( V2 TWICE ; (( V3 TWICE DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) (( V11 ; (( V2 TWICE ; (( V3 TWICE DEC ; 200 => MUL )) => ADD => INC ; I9-AUX-ARRAY >>> => %PUT )) MATCHED) )) )) OK) (LET I9-IMAGEFOCUS-2-ESSENCE BE (( )) (( (( V11 ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEFOCUS BE (( )) (( (( I9-AUX-ARRAY >>> => %EMPTY )) (( I9-IMAGEFOCUS-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGE >>> => CLEAR-MATRIX )) (( I9-IMAGEFOCUS-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEFOCUS-1-ESSENCE} => ? I9-IMAGEFOCUS-1-HOUSE < ? I9-IMAGEFOCUS-2-HOUSE < DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) )) OK) (LET I9-IMAGEROTATE-90-2-ESSENCE BE (( )) (( (( V11 ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEROTATE-90 BE (( )) (( (( I9-AUX-ARRAY >>> => %EMPTY )) (( I9-IMAGEROTATE-90-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGE >>> => CLEAR-MATRIX )) (( I9-IMAGEROTATE-90-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEROTATE-90-1-ESSENCE} => ? I9-IMAGEROTATE-90-1-HOUSE < ? I9-IMAGEROTATE-90-2-HOUSE <>> => & )) (( 200 (COUNT (( N1 ; # => %GET => %REVERSE )) COUNTUP) )) (( I9-NEW )) (( && )) )) OK) (LET I9-IMAGEEXCLUDE-TRANSPARENT-1-ESSENCE BE (( )) (( (( 0 ; (( V2 ; (( V3 => DEC ; 200 => MUL )) => ADD ; I9-AUX-ARRAY >>> => %PUT )) )) OK) (LET I9-IMAGEEXCLUDE-TRANSPARENT-2-ESSENCE BE (( )) (( (( 9 ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEEXCLUDE-TRANSPARENT BE (( )) (( (( I9-AUX-ARRAY >>> ; 1 ; 1 => %RFFGRANGE )) (( I9-IMAGEEXCLUDE-TRANSPARENT-1-HOUSE >>> ; I9-IMAGE >>> => FORVPM )) (( I9-IMAGEEXCLUDE-TRANSPARENT-2-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEEXCLUDE-TRANSPARENT-1-ESSENCE} => ? I9-IMAGEEXCLUDE-TRANSPARENT-1-HOUSE < ? I9-IMAGEEXCLUDE-TRANSPARENT-2-HOUSE <>> ; (( V2 => DEC ; 200 => MOD => INC )) ; (( V2 => DEC ; 200 => DIV => INC )) ; I9-IMAGE >>> => PM )) )) OK) (LET I9-IMAGEONE-TONE-ONLY BE (( )) (( (( ^255 FR GETV I9-IMAGEWHICH-NEW-ONE-TONE <>> ; 1 ; 1 => %RFFGRANGE )) (( I9-IMAGEONE-TONE-ONLY-HOUSE >>> ; I9-AUX-ARRAY-PM >>> => FORVPM )) (( I9-NEW )) )) OK) (( }I9-IMAGEONE-TONE-ONLY-ESSENCE} => ? I9-IMAGEONE-TONE-ONLY-HOUSE <>> => & )) (( CLS )) (( }Anarchistic mutations which can be friendly towards first-hand photoart work} ; 50 ; 75 => B9-POP )) }Images respond somewhat differently; use your intuition; have fun!!!} ; 50 ; 100 => B9-POP )) (( }B brighten colors} ; 25 ; 150 => B9-POP )) (( }D deeper colors} ; 25 ; 175 => B9-POP )) (( }E enhance contrast} ; 25 ; 225 => B9-POP )) (( }Y focus top left} ; 25 ; 275 => B9-POP )) (( }R rotate 90 degrees} ; 25 ; 300 => B9-POP )) (( }I invert colors} ; 25 ; 250 => B9-POP )) (( }M mirror image} ; 25 ; 325 => B9-POP )) (( }X exclude transparent} ; 25 ; 425 => B9-POP )) (( }1 one tone only} 50 ; 475 => B9-POP )) (( }Z matt & smooth} 275 ; 475 => B9-POP )) (( }U permute up} ; 50 ; 500 => B9-POP )) (( }P permute other} ; 50 ; 525 => B9-POP )) (( }A add texture} ; 50 ; 550 => B9-POP )) (( }C collect} ; 275 ; 500 => B9-POP )) (( }O collect other} ; 275 ; 525 => B9-POP )) (( }S shift} ; 275 ; 550 => B9-POP )) (( }2 zing} ; 50 ; 575 => B9-POP )) (( }3 only texture} ; 50 ; 600 => B9-POP )) (( }W wild edges} ; 275 ; 575 => B9-POP )) (( }4 odd lucidity} ; 275 ; 600 => B9-POP )) (( }V vaguer} ; 50 ; 625 => B9-POP )) (( }The spring-art color light green} ; 575 ; 500 => B9-POP )) (( }is preferred in these actions} ; 575 ; 530 => B9-POP )) (( }because of angelic assocations} ; 575 ; 560 => B9-POP )) (( }Listen to your heart beyond theory; sense} ; 480 ; 615 => B9-POP )) (( }the rich variety of free associations;} ; 480 ; 645 => B9-POP )) (( }have the intent of harmony and health.} ; 480 ; 675 => B9-POP )) (( }Save only that which you feel good about.} ; 480 ; 705 => B9-POP )) (( }*} ; 973 ; 10 => B9-POP )) (( }Q to main menu} ; 50 ; 700 => B9-POP )) (( I9-NEW )) (( GOLABEL1: )) (( CLEAR_KEYBUF )) (( KEY => UPCM ; )) (( }***} ; 571 ; 450 => B9-POP )) (( ; :U TEQ => = I9-IMAGEPERMUTE-UP == :P TEQ => = I9-IMAGEPERMUTE == :A TEQ => = I9-IMAGEADD-TEXTURE == :C TEQ => = I9-IMAGECOLLECT == :O TEQ => = I9-IMAGECOLLECT-OTHER == :S TEQ => = I9-IMAGESHIFT == :B TEQ => = I9-IMAGEBRIGHTEN-COLORS == :D TEQ => = I9-IMAGEDEEPER-COLORS == :Z TEQ => = I9-IMAGEMATT-SMOOTH == :E TEQ => = I9-IMAGEENHANCE-CONTRAST == :I TEQ => = I9-IMAGEINVERT-COLORS == :R TEQ => = I9-IMAGEROTATE-90 == :M TEQ => = I9-IMAGEMIRROR-IMAGE == :X TEQ => = I9-IMAGEEXCLUDE-TRANSPARENT == :1 TEQ => = I9-IMAGEONE-TONE-ONLY == :2 TEQ => = I9-IMAGEZING == :3 TEQ => = I9-MAKE-TEXTURE-LINES == :W TEQ => = I9-IMAGEWILD-EDGES == :4 TEQ => = I9-IMAGEODD-LUCIDITY == :V TEQ => = I9-IMAGEVAGUER == :Y TEQ => = I9-IMAGEFOCUS == :Q EQ => = GOFORWARD4 === === === === === === === === === === === === === === === === === === === === === === )) (( } } ; 571 ; 450 => B9-POP )) (( GOUP1 )) (( GOLABEL4: )) (( && )) )) OK) (( LOOKSTK )) (LET I9 BE (( )) (( (( GJ-ON )) (( I9-INIT-VARS )) (( }SAMPLE.TXT} ; I9-IMAGE >>> => FILENUM2PM ; RM )) (( GOLABEL1: )) (( CLS ; FT )) (( I9-FRONTPAGE-MENU )) (( KEYNUM => >N1 )) (( N1 ; 49 => EQN = I9-OPEN-FILE == N1 ; 50 => EQN = I9-SAVE-FILE == N1 ; 51 => EQN = I9-MODIFY-IMAGE == N1 ; 27 => EQN = GOFORWARD4 === === === === )) (( GOUP1 )) (( GOLABEL4: )) (( GJ-DONE )) )) OK) (( LOOKSTK )) (( )) (( )) (( )) (( )) (( )) (( )) The above, in some perhaps in-compiled form, is part of the Lisa. So, above was a program, the I9 image editor, which, although pretty hefty going at many points (and using some undocumented words here and there), should provide a pretty good context of use of many of the words as discussed above. It is not included because of its simplicity as much as for its completeness. Don't worry if it means absolutely nothing to you at first; the point is that if you searches on a word in this dictionary and want to see at least ONE SINGLE LINE in which it is actually used the chances are, if it is reasonably central, that it is there, and that single line may fulfill the questions the above list doesn't answer in terms of sequences of parameters. See other programs for more answers. (( )) The way to do conditional performance of some lines rather than others is done by means of (MATCHED .. MATCHED), in an intuitively rather obvious way which is given inside the following dictionary. Synonyms for these are = and ===. The alternative condition can be written as, respectively, (MATCHED .. )(OTHER .. MATCHED) and =, == and ===. The so-called boolean flag, or 'flag', which indicates whether a condition has been met, is generated by such functions as EQN, which compares two numbers, and EQ, which compares two texts, and is a unit-sized lowercase y for 'yes' or n for 'no', where other values should not be used, in general, as for input for (MATCHED or =. On these one can have boolean operators such as AND and the negation, NOT, and, another three-letter function, ORR. One can generate a number of highly easy-to-read looking loops by the up-to-four GOLABEL1: .. GOLABEL4: marks inside each function, in which a single -- and only a single -- call to each one, either by GOUP1 .. GOUP4 or GOFORWARD1 .. GOFORWARD4 has been found by this author as fruitful in well-structured programming. This is a moderate version of the notorious 'goto' command in Fortran and Basic. It is only used inside a function. Some other loop commands are implemented in basic Firth but the combination of (MATCHED or = with these simple GOxxx commands suit eminently, and the only one used in addition, in most cases, is the enormously simple (COUNT .. COUNTUP) command which takes a single argument -- the highest number which the count, which starts on 1, will go up to, within a 32-bit boundary as normal. As with GOxxx commands, (MATCHED and (COUNT belong inside functions only. When (COUNT .. COUNTUP) loop is used, it is often the case that something like >N8 >N7 >N6 is written inside the input parameter clause instead of >N3 >N2 >N1, for the (COUNT .. COUNTUP) uses the simple stack itself to add a couple of new values on top of it. For during a (COUNT .. COUNTUP) phase, one will find that N1 inevitably holds the current count value, while N2 holds the value it goes up towards. What was before N1 will be accessible within that loop as N3. In short, then, one adds 2 to the number n in the Nn variable used, so that N8 becomes, inside the loop, N10, and N7 becomes N9, and so on. To remind the reader of the program of this, therefore, it is often convenient to use a much higher numbering of the N-variables when such a loop is just about to be encountered inside the function. For instance, (LET MANY-TIMES BE (( >N8 >N7 )) (( (( N7 (COUNT (( N10 => H )) COUNTUP) )) )) OK) This is a loop which performs the operation requested that many times, by means of a warp which is given at the top-most location at the main stack. For instance, one could do something like (( 10 ; (( }CRLN} => ? )) => MANY-TIMES )) to get ten lineshifts. When the .. COUNTUP) part is reached, then, when the loop has completed itself, the use of the simple stack returns to normal, and the N8 -- which inside the loop will be accessed as N10 -- will again be N8. One can nest several (COUNT .. (COUNT .. COUNTUP) .. COUNTUP) inside one another in a function -- if one doesn't overdo it, for each function should be psychologically pleasant to read, if possible -- and then one will find that each nesting level adds another 2 to the N-numbers used. After the function completes, the eleven slots in the simple stack are released, of course. One will therefore find the variable stack sometimes exceedingly welcome when using the (COUNT .. COUNTUP) type of loop, since it is not touched by this phenomenon of adding two new members on top; the variable stack is often initialized in the beginning of a function, perhaps with a & function, and released towards the end of the function, perhaps with a && function, but it can also, in such cases where one does so with clarity, be used to carry over values in between (a group of) functions. The word 'program' can refer to the collection of functions leading up to the highest-level function which calls on all the others, with suitable initialization of variables and completing procedures, or it can, when the context makes it clear, refer to a single function -- perhaps together with its variables. It is noteworthy that also the variables are in some sense to be seen as small programs (see comment on this in connection with >>> function). Finally, as the program exits, it can either exit straight to Lisacode, by including the word XO, and often also including the word LOOKSTK VARSTK to check both on main stack and VARSTK for leftovers; perhaps also with half a second's pause with something like a (( 500 => GOODPAUSE )) phrase there, or it can exit to the interactive compiler mode where the interactor herself must type XO to leave the compiler entirely for refresh of RAM and the performance of other Lisa programs and other Lisacode programs. As the very completing line or lines, you can either include the calling on a function which gives some textual info as to the success of the compilation, and perhaps what one might type next to start this or that, or you can start the program itself by means of a particular phrase, which in general goes like this: (LET AUTOSTART BE my-program-name OK) You would type in, usually in uppercase, the real program name where it says my-program-name. Sometimes it will also say XO on this line; that's okay, but AUTOSTART should, as a convention, normally be nothing but a line long because of its very unusual features and because of the importance of being sure that the definition of AUTOSTART is devoid of any and all syntatical complications whatsoever, since, once it is defined, it will be started no matter what -- speaking generally. It is important to take advantage of this function rather than writing your program name at the bottom of the program, since the compiler will still be in compilating program mode when the completing line is reached. So, if the completing line is something like (( PROGRAM-INFO )) which just prints a few lines then exits there is no trouble at all. But if you have a program which is going to have an endurance and a duration in performance you will want the compiler to have done with all compilation. When it has done, it will check whether AUTOSTART has been defined, and if so, it will start it. This line should in almost all cases be the very completing line or only blank lines should be after it for the definition of AUTOSTART will cause the compiler to run it even if there is a detected syntax error after it; and so all syntax error should be dealt with, and corrected, before the compiler comes to any AUTOSTART definition. (Again, you have freedom here to do it otherwise if you are consciously aware of a positive option and see that it all works out.) Often, the C:\BOEHM\BOEHMIAN\FIC3.TXT will have several useful examples. Among the many names of Firth and Firth Lisa called on for inspiration during the decade-long development 1997-2007 was BOEHM, MT, BOEHMIAN, and of course FIRTH234. These, and more, play back on work I once did on Forth in a version called Knit directly written in assembler for CP/M 1.2 as a kid, and I am grateful for Kolbjoern Braa for the possibility of making good money of programs done in Knit. A long phase of philosophical, logical and physical explorations, often through conversations in dialogue with writings, followed, before I took it up again with renewed ambition; in 2006 Firth was done and in 2007 Lisa GJ2, while Lisa GJ2 Fic3 is the mature edition. (( )) When we write something like 100 5 DIV or, with punctuation, (( 100 ; 5 => DIV )) we mean to divide 100 by 5, and since this is the natural way of talking about it, 100 -- then 5 -- then the instruction to the computer to do the great arithmetic work -- DIV -- that is how the parameters go. So, for DIV, number1 would be 100, number2 would be 5, and this produces number3, which would be 20 (and in this case, there would be no text as input). When we write something like (( 10 ; 5 => INTGREATER )) then this is meant by me to reflect the question 'is 10 a greater integer than 5?', in other words, with these comparison operators, we imagine that they are slipped in between the two parameters. The answer is 'y', of course, to (( 10 ; 5 => INTGREATER )). People new to programming might wonder while eg use of THE-WEEK-DAY-VARIABLE while you defined THE-WEEKDAY-VARIABLE doesn't at all work out. Imagine a person being as silly as the computer -- you wouldn't count that person for a friend. It would be awkward to live in a conversation context of absolute precision. But the whole point about the computer is that, although it is seems pettily perfect, it allows for a grand harmony in which even the entirely absurd can be swiftly rendered -- if only it can be programmed. If it once begins to slip into evaluating the possible semantics or content of what you are saying, instead of looking purely at the textual pattern, then it is no longer a rule-performer, but something which eventually you'll have to bribe by nice compliments before it will do anything for you. The silliness of computer encourages your own perfection. (( )) (( )) (( )) (( )) (( )) (( )) (( )) (( )) (( )) (( )) (( )) (( )) (( )) (( )) (( )) """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " (( )) (( )) (( )) Note that you can check whether a function exists e.g. by typing }XXX} ? ( and see if the value is positive; if it is, it exists; and if so, even if it is not listed above, please avoid defining that word in your own programs. Let me again point out that Lisa GJ2 FIC3 has a set of functions that is more accurately pointed out by looking at the 'official example programs' than by this document as a whole. Be sure that if you use any functions inside the IT.TXT that you realize that it calls on a range of functions which allocate GJP-space differently than the rest of the typical GJP-functions found in this manual. Check with LIGHT3D.TXT for some concrete functions, including in particular MATRIXSORT3, not mentioned here; note also how parameters are given to TRIANGLE there; and note such particulars as how many decimal digits ought to be included -- neither more, nor less, in this author's opinion -- in Lisa GJ2 FIC3, of the number pi, to ensure minimal loss of precision during repeated calls on transformations incl. rotations, and of recommended way of using trigonometric functions. Be sure you also see that with SPC, the spreadsheet or business space, as included as higher-level functions inside FIC3.TXT, we got better versions of such as PRETTIFY-NUMBER or whatever it is called, and LIGHT3D.TXT, again, provide examples of the use of such functions. If you want to publish your program at the Internet, I usually find that inside an HTML page, you can copy and paste a whole program directly if you do three things: 1. Replace every < (used in words such as < before the code, with optional font description of Courier New with such and such size inside, often also and 3. Put a after the code (and complete, just before this, the and and any ). And that's it! Remember that there's possibilities for getting your program official listed so it can be found by keywords, when you have published it on your website, by checking with the option 'wine-and-cigar' at yoga4d.org/updated.htm, and registering it there, for free (you can also advertise for it, there, naturally, for a meaningful price!). GOOD LUCK!!!