+Lee Stewart Posted December 21, 2015 Author Share Posted December 21, 2015 Please note correction of code for Asm? in my last post (just in case you already copied it). The test was not discriminating ALC-based words from those defined in high-level Forth—everything was passing! ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 21, 2015 Author Share Posted December 21, 2015 I need to do more work on ASM>CODE to make it more useful. Right now, it emits the proper code; but, it cannot be used to load the relevant machine-coded words without adding , after each hex number (machine code) to compile said numbers into the definition (see notes added to post #1175). ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 23, 2015 Author Share Posted December 23, 2015 I get excited about little victories in Forth coding; but, they are lonely victories because there is simply not a lot of interest in Forth, here. Sometimes that is a little discouraging; but, for the most part, the fun I have developing the fbForth system in high-level Forth and TMS9900 Assembler is all I need. Anyway, my current little victory has to do with making it possible to use the same words as TurboForth for incorporating machine code in the body of an fbForth definition, viz., CODE: and ;CODE . The reason I thought I could not use ;CODE was that fbForth already has such a word for another purpose and I feel the need to keep that use for compatibility with TI Forth. I have managed to define ;CODE as a dual use word. That is, it can now be used for both CODE: ... ;CODE as well as its original use in writing defining words with : DEFINING-WORD <BUILDS … ;CODE ... NEXT, . The discriminator turns out to be the compilation state of the word being defined. CODE: ... ;CODE is executing during the definition; whereas, : DEFINING-WORD <BUILDS … ;CODE ... NEXT, is compiling from : until after ;CODE . The commented definitions of CODE: and ;CODE follow: ( Machine coded ALC words..LES22DEC2015) HEX : CODE: ( -- ) ?EXEC ( check that we are not compiling) CREATE SMUDGE ( create word header and make word visible) BEGIN ( infinite loop that is exited by ;CODE) IN @ ( save our place in the input stream, IS) BL WORD ( get next token to HERE) 0 0 HERE (NUMBER) ( see if it's a number) C@ BL - IF ( conversion failed? see if it's a word) DROP DROP ( discard double number) IN ! ( restore IN for ' ) [COMPILE] ' CFA EXECUTE ( execute found word) ELSE ( successful conversion) DROP , ( make it a 16-bit number and compile it) DROP ( drop previous value of IN) THEN AGAIN ; ( get next number in input stream) ( ;CODE is now a synonym for DOES>ASM: and terminator for CODE:) : ;CODE ( -- ) STATE @ IF ( are we compiling?) [COMPILE] DOES>ASM: ( invoke DOES>ASM: ) ELSE ( are we executing?) 045F , ( compile B *NEXT ) R> R> DROP >R ( do not return to CODE:) THEN ; IMMEDIATE Basically, CODE: is an interpreter with an infinite loop, just like INTERPRET , the Forth outer (text) interpreter. Whereas INTERPRET first checks whether the next token is a Forth word, CODE: first tries to convert the next token to a number. If CODE: fails number conversion, it looks up the word and executes it if it is found. The only way out of CODE: 's infinite loop is to execute ;CODE , which removes the return to CODE: from the return stack. The only problem I have now is that I must whittle down some fbForth system code if I am ever to fit these two words into ROM! They require about 100 bytes. In the meantime, they can be loaded each time they are needed. I think I will modify ASM>CODE to presume their use. The resulting word definitions will load much faster than the current CODE ... NEXT, solution (from TI Forth) because each and every number after CODE causes INTERPRET to look through more than 400 words before it gives up and converts it to a number. Then, of course, there is the need for , after each number to compile the number into the definition. ...lee Quote Link to comment Share on other sites More sharing options...
Willsy Posted December 23, 2015 Share Posted December 23, 2015 Keep on hacking. I read all your posts and enjoy following the progress! 3 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 23, 2015 Author Share Posted December 23, 2015 (edited) Posting the code for CODE: ... ;CODE in post #1178 was a little premature. It will only work for a single line. | As soon as the definition goes to another line, CODE: loses control of the input and execution of ;CODE puts fbForth into the weeds! The following version works for multiple lines as well as when loaded from a blocks file: ( Machine coded ALC words revised..LES07APR2016) HEX : getCODE ( -- ) BEGIN ( infinite loop that is exited by ;CODE) IN @ ( save our place in the input stream, IS) BL WORD ( get next token to HERE) 0 0 HERE (NUMBER) ( see if it's a number) C@ BL - IF ( conversion failed? see if it's a word) DROP DROP ( discard double number) IN ! ( restore IN for ' ) [COMPILE] ' ( get word's PFA) CFA EXECUTE ( no; execute found word) ELSE ( successful conversion) DROP , ( make it a 16-bit number and compile it) DROP ( drop previous value of IN) THEN AGAIN ; ( get next number in input stream) : CODE: ( -- C0DEh) ?EXEC ( check that we are not compiling) CREATE SMUDGE ( create word header and make word visible) C0DE ( leave magic number, C0DEh, on stack for ;CODE) BEGIN getCODE ( get code until ;CODE) BLK @ 0= IF ." ok:" DEPTH . CR QUERY THEN AGAIN ; IMMEDIATE ( ;CODE is now a synonym for DOES>ASM: and terminator for CODE:) : ;CODE ( -- ) STATE @ IF ( are we compiling?) [COMPILE] DOES>ASM: ( invoke DOES>ASM: ) ELSE ( are we executing?) DEPTH IF ( DEPTH > 0?) C0DE = IF ( magic number, C0DEh, on stack?) 045F , ( compile B *NEXT ) R> R> DROP DROP ( do not return to getCODE or CODE:) ELSE 0 ERROR ( ERROR!! not paired with CODE:) THEN ELSE 0 ERROR ( ERROR!! not paired with CODE:) THEN THEN ; IMMEDIATE DECIMAL In the above code, getCODE acts like INTERPRET , as explained in my previous post for CODE: . The infinite loop in CODE: now acts like QUIT and LOAD . Because ;CODE 's execution now occurs two levels down, it must pop two return addresses from the return stack to exit CODE: . Multi-line CODE: ... ;CODE definitions entered from the terminal or loaded from a blocks file now compile successfully. The code for these words is now up to 160 bytes, which makes it less likely I will find enough room to shoehorn it into ROM space. One way I might get away with it would be to remove the default font from ROM and load it from a font file as is done now for user fonts. This would save 1024 bytes! The obvious question is, “Should I do it?” ...lee [EDIT: Corrected the above code to have ;CODE check that CODE: was how ;CODE was executed. Otherwise, ;CODE issued at the command line will hang the system. Also, the penultimate line of ;CODE was not dropping the correct addresses from the return stack!] Edited April 7, 2016 by Lee Stewart Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted December 24, 2015 Share Posted December 24, 2015 That depends on how much you need that 1024 bytes, Lee. I'd say if you need more than half of that space, do it for sure--otherwise, you could go either way with it and it won't cause much in the way of problems, especially since the User fonts are already being loaded that way. . . Quote Link to comment Share on other sites More sharing options...
atrax27407 Posted December 24, 2015 Share Posted December 24, 2015 It might be better as a BLOCK that the user can load should he/she need it. Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted December 24, 2015 Share Posted December 24, 2015 I personally like that the fbForth cartridge doesn't require any of the other files distributed with it. The blocks file I use is usually on the HDX1. drive/pc. It is nice that I can get into forth without loading anything from disk. From what I can tell of the CODE: and ;CODE words, they optimize compiling words that are mostly composed of numbers as in machine code. So I would be cautious of trading an always used thing for a sometimes used thing. I'm hoping to get more time for fbForth after the new year. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 24, 2015 Author Share Posted December 24, 2015 That depends on how much you need that 1024 bytes, Lee. I'd say if you need more than half of that space, do it for sure--otherwise, you could go either way with it and it won't cause much in the way of problems, especially since the User fonts are already being loaded that way. . . I would probably only need about 20% right now. And, I agree about fonts. If I go that route, I should probably try to load the default font from the same disk where the user loads FBLOCKS if s/he holds down a key for a drive other than DSK1. In the event the font file cannot be found, lowercase would be the classic, small-caps font in console GROM #0. It might be better as a BLOCK that the user can load should he/she need it. What “might be better as a BLOCK that the user can load,” the default font (would only require one block!—H-m-m-m...) or the CODE: ... ;CODE words? ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 24, 2015 Author Share Posted December 24, 2015 I personally like that the fbForth cartridge doesn't require any of the other files distributed with it. The blocks file I use is usually on the HDX1. drive/pc. It is nice that I can get into forth without loading anything from disk. Good point. From what I can tell of the CODE: and ;CODE words, they optimize compiling words that are mostly composed of numbers as in machine code. That is true. I could certainly manage machine-code loading, such as the CRU words in block #5 of FBLOCKS, by including a conditional load of a block with the requisite CODE: ... ;CODE words. In Classic99, block #5 takes just over 7 seconds to load. Coded with CODE: and ;CODE , it takes only 2.5 seconds. Though nearly 3 times faster, the slower time is not very significant. It would only really matter with multi-block loads of blocks dense with machine code—like @Willsy's double-precision-integer-math library for TurboForth. ...lee Quote Link to comment Share on other sites More sharing options...
atrax27407 Posted December 24, 2015 Share Posted December 24, 2015 If you try to stuff every word definition into the Forth kernel, you end up with surplusage that most users will only infrequently use at best. Users should have the option of NOT having every word loaded at start-up but still have the facility to load the infrequently used ones from FBLOCKS if needed. The current 4 ROMs is at the limit for the HSGPL, for example, and anything above that size would make FbForth a cartridge-only effort. That might be a bit esoteric to most but it would be a minor consideration to me. Quote Link to comment Share on other sites More sharing options...
mister35mm Posted December 31, 2015 Share Posted December 31, 2015 I find it a constant source of amazement that machine with such a tiny amount of memory and resources STILL has so many unknowns. I was curious to see if there was any insight, anywhere, as to who the Ti-99/4a design team was, but no luck, so far. Just curious, really. Stephen Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted December 31, 2015 Share Posted December 31, 2015 One name that I know was in there was Mike Bunyard. If you look at the schematic for the sidecar 32K device, his name is in the designer's position (I recognize the signature). Those schematics also identify other team members, as different people were in different roles, depending on which item it was. If you look at all of the documents on WHT, you will eventually be able to identify other people too. The initial set MLB (which shows up in many of the documents), is Michael L. Bunyard. I know that a guy named Pete Jaden was also on the 99/8 team with Mike Bunyard. Mike mentioned several other folks that were involved back then, but I failed to write them down during our long phone conversations. . . Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 8, 2016 Author Share Posted January 8, 2016 I have not been doing much Forth, lately; so, I thought I would revisit the CODE: ... ;CODE words of post #1180 to see whether they needed any improvement. The only problem I see (so far) is with ;CODE when pasting Forth code using it into an emulator at the command line. If an error occurs after CODE: and the closing ;CODE is not on the same line, the later execution of ;CODE will send fbForth into the weeds. This is not a problem with loading the same code from a blocks file because the error will cause the load to abort before ;CODE can be executed. It should also not be a problem on the command line because the programmer will see the error and should see that it is pointless to continue with the ALC definition until s/he has fixed it. If ;CODE gets typed on the same line as the code that will cause the error, the line’s interpretation will be aborted before ;CODE can get executed. The additional code to trap the pasting error for an emulator is 22 bytes (currently, the code is 160 bytes). Since the problem should not occur on the real iron, I am wondering whether I should bother with it. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 13, 2016 Author Share Posted January 13, 2016 Well...With no one commenting on my last post, I guess I should leave CODE: ... ;CODE as coded in post #1180. Pasting code, after all, is not a real-iron option. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 13, 2016 Author Share Posted January 13, 2016 I personally like that the fbForth cartridge doesn't require any of the other files distributed with it. The blocks file I use is usually on the HDX1. drive/pc. It is nice that I can get into forth without loading anything from disk. I am thinking seriously of putting the default font in a block in FBLOCKS. If I go that route, I will, upon failure to find FBLOCKS, load the console font with its small caps for lowercase as shown here ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 14, 2016 Author Share Posted January 14, 2016 If you try to stuff every word definition into the Forth kernel, you end up with surplusage that most users will only infrequently use at best. Users should have the option of NOT having every word loaded at start-up but still have the facility to load the infrequently used ones from FBLOCKS if needed. The current 4 ROMs is at the limit for the HSGPL, for example, and anything above that size would make FbForth a cartridge-only effort. That might be a bit esoteric to most but it would be a minor consideration to me. The advantage to having as many words in the kernel as possible is that there is more room in CPU RAM for user words. It is certainly true that a given user might not need, say, the floating point library; but, for those who do, it would mean losing RAM space because it was left out of the ROM kernel. The disadvantage to having so many words in the kernel is the increased search time during interpretation at the command line or when loading blocks. The only way I can think of to mitigate this situation for those who do not need the full dictionary is to devise a system of compartmentalizing the dictionary such that optional segments can be linked in and out of the search space. I am not sure it is worth the effort, but ... ...lee Quote Link to comment Share on other sites More sharing options...
Willsy Posted January 14, 2016 Share Posted January 14, 2016 Just put them in vocabularies. So, if you had the float library in ROM, for example, it would be invisible until you invoke the float vocabulary. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 14, 2016 Author Share Posted January 14, 2016 Just put them in vocabularies. So, if you had the float library in ROM, for example, it would be invisible until you invoke the float vocabulary. I did think of that. And, that is probably the best way to do it. The only problem with using vocabularies is their order. If they are set up to all be connected to the FORTH vocabulary, they will not be directly available without invoking each vocabulary in turn. Let us say that we define the following vocabularies: FLOAT , for the floating point (FP) library and GRAPH , for the graphics primitives. If we need any FP operations while in the GRAPH vocabulary, FLOAT would need to be invoked for the FP operation(s) and then GRAPH , as soon as a continuation of graphics commands is needed. That might get messy. They could, of course, be chained; but then, the vocabulary order chosen by Yours Truly might be inconvenient for any given user. I would also need to rewrite BSAVE and BLOAD to explicitly save/restore the state of all cartridge-resident vocabularies. ...food for thought, certainly. ...lee Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted March 24, 2016 Share Posted March 24, 2016 I am thinking seriously of putting the default font in a block in FBLOCKS. If I go that route, I will, upon failure to find FBLOCKS, load the console font with its small caps for lowercase as shown here SmCaps.png ...lee That is a seriously good alternative 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 24, 2016 Author Share Posted March 24, 2016 I am thinking seriously of putting the default font in a block in FBLOCKS. If I go that route, I will, upon failure to find FBLOCKS, load the console font with its small caps for lowercase as shown here SmCaps.png That is a seriously good alternative We’re on the same wavelength this week! I was just going through code to see where I could rearrange things to make room in bank 0 for the additional code fields and parameter fields I will need. Once I free up enough space, I need to work out the best way to manage the default font. If I expect it to be in the current blocks file in, say, block #5, it would need to be in block #5 in every blocks file the user invokes—much as the requirement in TI Forth for system messages to be in blocks #4 and $5 for any disk in DSK1. I don’t like to hardwire block numbers into ROM code (except for block #1), so I would probably set up a user variable for this purpose. Because I don’t need the first 256 bytes of the current default font, I could set up a validation code at the start of the block and fail over to the console font if is not found. Or—I could use a default font file on the boot disk—DEF_FONT, or some such. Or—? ...lee Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted March 24, 2016 Share Posted March 24, 2016 We’re on the same wavelength this week! I was just going through code to see where I could rearrange things to make room in bank 0 for the additional code fields and parameter fields I will need. Once I free up enough space, I need to work out the best way to manage the default font. If I expect it to be in the current blocks file in, say, block #5, it would need to be in block #5 in every blocks file the user invokes—much as the requirement in TI Forth for system messages to be in blocks #4 and $5 for any disk in DSK1. I don’t like to hardwire block numbers into ROM code (except for block #1), so I would probably set up a user variable for this purpose. Because I don’t need the first 256 bytes of the current default font, I could set up a validation code at the start of the block and fail over to the console font if is not found. Or—I could use a default font file on the boot disk—DEF_FONT, or some such. Or—? ...lee A user variable wouldn't be set until after getting into block #1 so I'm not sure how that would be used. A word that loads the font from a specified block, would be just as easy to call. Would that user variable be preserved through a cold or something? Or used during the call to graphics or text? I like the idea of checking the block for a header as a little validation. -M@ Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 24, 2016 Author Share Posted March 24, 2016 A user variable wouldn't be set until after getting into block #1 so I'm not sure how that would be used. A word that loads the font from a specified block, would be just as easy to call. Would that user variable be preserved through a cold or something? Or used during the call to graphics or text? I like the idea of checking the block for a header as a little validation. -M@ Actually, a user variable that is defined in the kernel (which is how I would do it) usually has a default value assigned before ever loading a block. I will set it up like the VDP mode colors to survive COLD . FNT is called for every change in VDP mode so, yes, this particular user variable would get used. ...lee Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted March 24, 2016 Share Posted March 24, 2016 Actually, a user variable that is defined in the kernel (which is how I would do it) usually has a default value assigned before ever loading a block. I will set it up like the VDP mode colors to survive COLD . FNT is called for every change in VDP mode so, yes, this particular user variable would get used. ...lee Nice! I get now. If I'm using your fblocks, I just don't worry about it. If I'm creating an standalone blocks file, and I have have the font block in block #5, I don't have to do anything... If I want the font block in block #2 or something, I just set the user variable in block #1, then set my graphics mode like I already do and away we go. If I don't want the runtime cost of loading from disk, (maybe I change graphics modes frequently) I just set the user variable to block #1 ( not a font block ) and we'll get the console font when changing graphics modes. In development workflow, where I switch between the editor in text80, and mode 2 graphics, it might be nice to be able to effectively disable the behavior of FNT, maybe if the user variable can be set to indicate no font change, or explicitly set to load console font, behavior can be more deliberate. The last one doesn't eliminate the need to fallback if a valid block number is specified. Just offering an idea: maybe -1 is disables the behavior of FNT, and 0 explicitly loads the console font, and any other value attempts to load from the block file, falling back on console font if the block isn't a font block. -M@ Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted March 24, 2016 Share Posted March 24, 2016 I had another interesting idea, I expect everyone has thought of before, but with carts like the ubergrom, fbForth could be in the eeprom, and what if there was a bit in the rom that could be set so it would bload a range of blocks from GROM in the ubergrom atmega chip? I'm not (hopefully) proposing any major change in structure to fbForth. It could continue to own the ROM and ROM banking. The ubergrom seems like nice development aid. Given that it has GRAM space that could be used during development, something like having GSAVE tools on the fblocks tool set that would be like a BSAVE to GRAM, to test with. I haven't thought this through too deeply, but large things could be built using BSAVE swapping techniques Lee outlined in the fbForth manual, and all loaded fast off of cartridge. I imagine the GRAM space would be handy during development, but the GROM space would make more sense to solidify the code into. The GRAM could be useful for an individual app too. I suppose something similar could be done from from extended banks on the ROM side itself, but I imagine that is complicated by the bank switching already in fbForth. I imagine the only change required to fbForth would be a setting in the rom that can be set indicating to bload block 1 or a range of blocks from a grom address instead of from disk. Then the loaded block(s) can take control. ( maybe bload for block 1 isn't right, cause you problably want to execute some word(s) automatically. ) But hopefully I've communicated the concept. Just an idea. -M@ Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.