+jedimatt42 Posted June 21, 2016 Share Posted June 21, 2016 I know there is no enforced notion of private words, but there does appear to be some convention to your naming scheme. A brief section in Appendix D, before D.2, that explained the mentality of the naming convention would make the language a bit more infer-able.Such as all those words that are encased in parenthesis. They seem to be internal in nature. There is a whole slew of words that begin with '?' and have no stack effect. Or is it not as consistent as it appears superficially? Some guidelines on interpreting the naming conventions would be useful, to refresh on before browsing through looking for a word that might do a thing... Some sets of those words encased in parenthesis seem to be internal, part of the implementation more than part of the tool set.. If that is the case, it might be worth breaking them out into their own section, instead of co-mingling them with the 'public API' if you will. The commented, neatly structured code equivalent of what is packed into the FBLOCKS files would be handy. This would serve as examples. Examples are always welcome.-M@ 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted June 21, 2016 Author Share Posted June 21, 2016 As usual, Matt, those are good suggestions. There certainly are naming conventions that I will delineate in the preamble to the glossary per your suggestion. Some have changed over the years. Naming any new words I define is influenced by what I think might be clear and informative at the time; but, many of the words in the glossary are inherited from the mostly figForth-influenced TI Forth. Your observation regarding ‘( )’ is correct. Such words (‘< >’ are also used) are the runtime words compiled/executed by words named similarly without the ‘( )’. Such higher-level words are often state-smart and use the runtime words to avoid redundant code. Similarly, ‘[ ]’ are used for compile-time words. A very good reference (which I will also note in the manual update) for explaining/recommending naming conventions is Leo Brodie’s THINKING FORTH: A Language and Philosophy for Solving Problems, available free in electronic format from SourceForge. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted June 21, 2016 Author Share Posted June 21, 2016 Here is a first draft of Appdendix D.2: fbForth_2.0_Manual_AppendixD.2.pdf Am I on the right track? ...lee 2 Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted June 23, 2016 Share Posted June 23, 2016 Here is a first draft of Appdendix D.2: fbForth_2.0_Manual_AppendixD.2.pdf Am I on the right track? ...lee That is on the money. This provides a good explanation of rationale, and the example sets illustrate the patterns and spirit of the symbolism. It shows how it is sort of a Forth conjugation. -M@ 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted June 23, 2016 Author Share Posted June 23, 2016 ... It shows how it is sort of a Forth conjugation. -M@ Clever! ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 5, 2016 Author Share Posted July 5, 2016 As I was working on adding DOES>CODE: ... ;CODE to do the same thing for DOES>ASM: ... ;ASM that I did for ASM: ... ;ASM with CODE: ... ;CODE , I realized that, by reversing the order of interpreting words and numbers in getCODE for both CODE: and DOES>CODE: , I had made it impossible to perform a calculation on the stack if any of the numbers was not a word. The instant a number, as such, is loaded, it is compiled rather than pushed to the stack. This results in a stack underflow for any calculations and a corruption of the word being defined! You may recall that CODE: ... ;CODE (see posts #1180 and #1214) is used to speed up defining words with machine code by first assuming the next token in the input stream is a number and, if it is, then compiling it into the word definition. This also obviates the necessity of using comma ( , ) to compile each and every number. This trick, however, causes the problem mentioned above. It can be overcome with the following definition: : N>S ( -- n ) ( IS:n ) BL WORD ( get text of 16-bit number from terminal to HERE) HERE NUMBER ( convert to 32-bit number on stack) DROP ; ( drop MSW [should be 0] making it a 16-bit number) Of course, the result of the calculation must be compiled with comma ( , ) because getCODE never sees it. I will give an example of its use in a later post because I have to run now. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 7, 2016 Author Share Posted September 7, 2016 I discovered a bug in M/ while working on adding a couple of words that would allow a user to have a choice of symmetric or floored integer division for words like /MOD / MOD */MOD */ The bug occurred when I converted M/ to Assembly Language Code a build or two back. Any remainder in symmetric integer division should have the sign of the dividend and M/ uses the sign of the divisor! I will fix it post haste. This bug fix will be part of the release of fbForth 2.0:9, which should happen before I get to the Chicago Faire next month. I will bring cartridges for sale ($30) or exchange. Speaking of fbForth 2.0:9, I will be adding a handful of words to the resident dictionary: N>S DOES>CODE: \ There are two or three other words I would like to add, but I may run out of room. We'll see... ...lee 4 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 13, 2016 Author Share Posted September 13, 2016 I am adding a user variable, S|F (for “Symmetric or Floored”) that will be a flag for M/ to act like one of the ANSI Forth words, SM/REM (symmetric M/ ) or FM/MOD (floored M/ ). All three of these words have the same stack signature: ( d n --- rem quot ) That is, they take a signed double number (32 bits) d as the dividend and a signed single number (16 bits) n as the divisor, leaving a signed single number remainder rem and a signed single number quotient quot. All of these words use signed integer division. Where they differ is whether the division is symmetric or floored when the signs of divisor and dividend differ. The question is whether to use symmetric (SID) or floored integer division (FID). There are good reasons to choose FID over SID, especially in processes like robotics, where symmetry around 0 is important. Probably the only reason (and, probably, not a good reason!) to choose SID is that most of us expect the answers it gives. Here is a good explanation of signed integer division from the September, 1983 issue of Dr. Dobb's Journal: Signed Integer Division by Robert L. Smith Originally appearing in Dr. Dobb's Journal September 1983 Not all methods of integer division produce a uniform result when the dividend and divisor have opposite signs. This may not be so important in the area of commerce where negative values are perhaps used less. When dealing with measurement and control, however, uniformity becomes more significant. The Forth-83 Standard adopts a method for signed integer division called "floored" division. While APL has used this method for the RES function for years and Small-Talk provides it as one of three methods for integer division, acceptance of the Standard makes Forth the first "popular" language to embrace this method based on its theoretical merits. The problem is one of mathematical purity versus user expectation. This article will attempt to clarify some of the issues involved. Integer division is a mathematical function of two integers (a dividend and a divisor) that yields an integer quotient and an integer remainder. That appears to be a fairly straightforward operation, but there is not universal agreement of the desired results when one or both arguments are negative. When an integer quotient is used in plotting or machine control, the desired function is usually _not_ the quotient given by the majority of computers. Most computers with a divide function produce a quotient that has a property of symmetry around zero when plotted as a function of the dividend, due to the fact that the quotient is rounded toward zero. Speaking mathematically, the property is actually one of anti-symmetry, where the sign of the quotient is reversed when the sign of the dividend (or numerator) is reversed. For integer division, this "symmetric" property leads to a sort of discontinuity around zero. In this case, the remainder is either zero or it takes the sign of the dividend. Figure 1a illustrates the quotient q as a function of a variable dividend, and a constant divisor 3. We readily see the discontinuity near zero. This may +-------------------------------------------------------+ | | | 3 + o o o | | + o o o | | -9 + o o o 9 | | +-+-+-+-+-+-+-+-+-o-o-o-o-o-+-+-+-+-+-+-+-+-+- | | o o o + | | o o o + | | o o o -3 + | | | | (a) Quotient for Symmetric Integer Division | | | | | | | | + | | 2 + o o o o | | -9 + o o o o | | +-+-o-+-+-o-+-+-o-+-+-o-+-+-o-+-+-o-+-+-o-+-+- | | o o o o + 9 | | o o o o + -2 | | + | | | | (b) Remainder for Symmetric Integer Division | | | | Figure 1. | |_______________________________________________________| be reasonably serious when this quotient function is used for plotting or moving robot arms. The integer quotient needs an associated remainder: r = n - q * d where n is the numerator or dividend, d is the denominator or divisor, q is the quotient, and r is the remainder. The remainder function for the constant divisor 3 is illustrated in Figure 1b. If we look at the case of positive dividends and divisors, we observe the cyclic property that r(n+d) = r(n) In other word, the remainder usually has a repeating or cyclical property as the dividend changes. For the remainder shown in Figure 1b, we see that this simple property is not maintained for dividends between -d and 0. If we require that the remainder be cyclical, then the quotient no longer has any unusual discontinuities. There are a number of possible choices here. One obvious choice is to make the remainder the same as the modulus or residue function (1). In this case the quotient is rounded toward minus infinity. This rounding procedure is called the "floor" function. Figure 2 shows the floored quotient and its related modulus for the same arguments used in Figure 1. Notice the quotient behaves in a more nearly continuous fashion around zero. This is the form used in the Forth-83 Standard, as well as some of the older versions of Forth. The National 16032 microprocessor produces floored division in addition to the older "rounded toward zero" variety. The modulus function is called MOD in Forth-83 and in the National 16032. It is called RES in APL. +-------------------------------------------------------+ | | | 3 + o o o | | + o o o | | -9 + o o o 9 | | +-+-+-+-+-+-+-+-+-+-+-o-o-o-+-+-+-+-+-+-+-+-+- | | o o o + | | o o o + | | o o o -3 + | | | | (a) Quotient for Floored Integer Division | | | | | | | | + | | o o o + o o o o | | -9 o o o + o o o o | | +-+-o-+-+-o-+-+-o-+-+-o-+-+-o-+-+-o-+-+-o-+-+- | | + 9 | | + -2 | | + | | | | (b) Remainder for Floored Integer Division | | | | Figure 1. | |_______________________________________________________| The "floored" quotient shown in Figure 2 is not anti-symmetric around zero. However, for odd divisors one may easily obtain a symmetric result by adding a correction factor to the dividend prior to division. Although the quotient is generally not defined when the divisor is zero, the modulus is usually defined to take the value of the dividend for this case. If infinities are not allowed in computer representations, and the product of any number and zero is always zero, then this definition preserves the equation n = q * d + r for all values of d, including zero. Alternative remainder functions include a positive modulus and a remainder that takes the sign of the quotient (2). Some other possibilities have the undesirable feature of negative remainders when the dividend and divisor are both positive. Floored division is simply more useful in the majority of applications programs. The major objection is that the results are not what most people expect: -1 divided by 4 gives 0 in the rounded-toward-zero division case, but -1 for floored division. Both cases give the same results when the dividend and divisor have the same sign. Timing efficiencies may play a small role in deciding which form of division to use, but generally the division process is sufficiently slow that additional tests for different forms of rounding take only a little extra time. Indeed, for some processors with built-in signed and unsigned divide functions, it may be faster in the common case of positive arguments to test signs and use the unsigned division than to just use the signed division function. If you have an older Forth system (such as 79-Standard or fig-FORTH), the screen in Figure 3 shows a high-level conversion from the older form of /MOD to the newer version. For those unfamiliar with Forth, /MOD takes two arguments, the dividend and the divisor, and returns two results: the quotient and the modulus, or remainder. The quotient is returned as the most accessible element on the stack. The appearance of floored division in some of the newer processor chips and languages indicates the increasing awareness of its utility. We might note in passing that even floating-point division will probably be different in the future than it was in the past due to the new Floating-Point Standard, which will require proper rounding of the quotient. References (1) Donald K. Knuth, _The Art of Computer Programming: Volume I, Fundamental Algorithms_, Second Edition, Menlo Park: Addison-Wesley, 1973, p. 127. (2) Robert Berkey, "Integer Division, Rounding and Remainders", 1982 FORML Conference Proceedings, San Jose, California: Forth Interest Group, 1983, pp. 13-23. +---------------------------------------------------------------+ | | | ( Define 83-Standard /MOD in terms of old /MOD ) | | : /MOD ( num den -- mod quot ) | | OVER OVER XOR 0< ( test signs of arguments ) | | IF ( signs are different ) | | >R R@ /MOD OVER ( divide and examine remainder ) | | IF ( non-zero remainder ) | | 1- SWAP R> + SWAP ( adjust results ) | | ELSE ( zero remainder ) | | R> DROP ( discard old den ) | | THEN | | ELSE ( signs just the same ) | | /MOD ( just divide normally ) | | THEN ; ( end of definition ) | | | | | | Figure 3. | | High Level Forth Code to Convert to Floored Division | |_______________________________________________________________| Currently, M/ uses SID since fbForth is based on fig-Forth, which uses SID. It will continue to be the default to support expectations of TI Forth programmers. However, S|F will make it easy for the user to change the behavior of M/ at will to accommodate FID. Doing so will change all of the following words to use FID because they are based on M/ : /MOD / MOD */MOD */ I should note that TurboForth uses FID by default because it complies with the Forth-83 Standard, which, as noted in the above article, was the first standard to make that move. I would actually prefer to make FID the fbForth default, but have chosen not to do so for the reasons in the last paragraph. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 14, 2016 Author Share Posted September 14, 2016 Though the fbForth 2.0:9 (posting soon!) implementation of SM/REM and FM/MOD is in Assembler, I thought some of you might be interested in the high-level Forth code for these words: Spoiler \ Symmetric Integer Division of signed 32-bit numerator by signed 16-bit denominator \ yielding signed 16-bit remainder and quotient. : SM/REM ( d n --- rem quot ) OVER >R >R \ copy MSB of numerator and move denominator to return stack DABS R ABS \ make numerator and denomitor both positive U/ R> R XOR \ divide to get remainder and quotient; get sign of quotient +- SWAP \ give quotient proper sign R> +- SWAP ; \ give any remainder sign of numerator \ Floored Integer Division of signed 32-bit numerator by signed 16-bit denominator, \ yielding signed 16-bit remainder and quotient. : FM/MOD ( d n --- rem quot ) OVER OVER XOR 0< \ den and num signs differ? IF \ signs differ >R R SM/REM OVER \ do symmetric division IF \ deal with remainder 1- SWAP R> + SWAP \ floor quotient;rem = rem + den ELSE \ no remainder R> DROP \ clean up return stack THEN ELSE \ den and num signs same SM/REM \ do symmetric division (same as floored here) THEN ; The code for FM/MOD is written in terms of SM/REM and is very similar to the Forth code for /MOD at the end of the article cited in my last post. ...lee Quote Link to comment Share on other sites More sharing options...
+jedimatt42 Posted September 14, 2016 Share Posted September 14, 2016 FID vs. SID, I remember being driven nuts by this a long time ago, but never knew the concepts behind it. I sadly brute forced my way through the problem at the time. It is awesome that you are squeezing the choice into fbForth! -M@ 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 14, 2016 Author Share Posted September 14, 2016 FID vs. SID, I remember being driven nuts by this a long time ago, but never knew the concepts behind it. I sadly brute forced my way through the problem at the time. It is awesome that you are squeezing the choice into fbForth! -M@ Thanks for that, Matt. I was not sure anyone but me cared about it (with the likely exception of Mark Wills). I will try to post fbForth 2.0:9 before the end of next week. As things stand at the moment, The spare room in the cartridge is Bank# Bytes Left ----- ---------- 0 120 1 228 2 236 3 50 ...lee 3 Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted September 15, 2016 Share Posted September 15, 2016 Space is starting to get tight again, Lee! I'm glad you took the bull by the horns with SID/FID as well--as that helps folks use the methods they want within a single Forth implementation. 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 15, 2016 Author Share Posted September 15, 2016 Wow! Yesterday, while converting FBLOCKS to run with fbForth 2.0:9, I discovered a nasty bug caused by my conversion, in a previous build, of ;CODE from a high-level colon definition to ALC. After I finally realized the bug was not caused by my recent changes, I figured out what was going wrong and fixed it. The fix was a bit convoluted, so I will defer explanation until someone actually wants to know. I should still be able to post this build by next week's end, barring discovery of another such bug. ...lee 1 Quote Link to comment Share on other sites More sharing options...
Sinphaltimus Posted September 15, 2016 Share Posted September 15, 2016 Where's the bug that frees up space after it's rooted out? That's a miniscule about of free space. Quote Link to comment Share on other sites More sharing options...
atrax27407 Posted September 15, 2016 Share Posted September 15, 2016 Are the entry points going to be unchanged? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 15, 2016 Author Share Posted September 15, 2016 Where's the bug that frees up space after it's rooted out? That's a miniscule about of free space. Hah! That would be nice. Talk to @Willsy about how little space is truly “minuscule”. fbForth 2.0:9 has loads of space compared to TurboForth! I have other options if I really need more space, but I don't see the resident dictionary growing that much from here on out. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 15, 2016 Author Share Posted September 15, 2016 Are the entry points going to be unchanged? If you mean where the opening menu choices start up in ROM, they are unchanged. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 24, 2016 Author Share Posted September 24, 2016 Files for the latest build, fbForth 2.0:9, have been uploaded to post #1 of this thread. Please let me know if you find anything awry. ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted November 29, 2016 Author Share Posted November 29, 2016 I am in the process of developing words to mount/unmount compact flash (CF) volumes as DSK1, DSK2 and/or DSK3 for the nanoPEB and CF7. Such words will obviate the necessity of swapping the fbForth 2.0 cartridge for the E/A cartridge, loading CF2K to make the mounting changes and swapping cartridges again to restart fbForth 2.0! Of course, the process could also be managed by exiting fbForth 2.0, starting TI Basic to execute the appropriate “CALL MOUNT” and “CALL UNMOUNT” commands Jaime provided with the hardware, exiting TI Basic and restarting fbForth 2.0—almost as bad. I am puzzling over a couple of ways to code these words. One is very simple but does not persist the mounts/unmounts after a reset. It involves writing the desired volume number to the desired virtual disk marker (16 bits) above the TI disk buffer space in VRAM—pretty simple. The other involves talking directly to the CF through IDE commands after setting up necessary buffers/variables and coding the commands. Fred Kaal (@F.G. Kaal) was kind enough to share the relevant code from his CF2K. This method would still need the small amount of code for the first option above. This second option is, obviously, a significantly greater programming effort. I am inclined to code option one and name the words something other than MOUNT and UNMOUNT to indicate the lack of persistence. This would provide some convenience while I work on the second option, if I do it at all. Just thinking out loud... ...lee 1 Quote Link to comment Share on other sites More sharing options...
Willsy Posted November 29, 2016 Share Posted November 29, 2016 When you've implemented it in fbForth... Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted November 29, 2016 Author Share Posted November 29, 2016 When you've implemented it in fbForth... Mais oui! ...lee Quote Link to comment Share on other sites More sharing options...
Sinphaltimus Posted November 29, 2016 Share Posted November 29, 2016 TEMPMOUNT/TEMPUNMOUNT Quote Link to comment Share on other sites More sharing options...
Asmusr Posted December 2, 2016 Share Posted December 2, 2016 How do you 'talk' to the nanoPEB from the TI at a lower level than the DSKx DSR, is it via subroutines in the ROM header, direct calls to ROM code, or something else? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 3, 2016 Author Share Posted December 3, 2016 How do you 'talk' to the nanoPEB from the TI at a lower level than the DSKx DSR, is it via subroutines in the ROM header, direct calls to ROM code, or something else? The CF card is managed pretty much as a standard IDE drive (master) with 512-byte sectors and a subset of the IDE commands available. You can talk to the nanoPEB/CF7 at the IDE command level through read/write ports in DSR memory space. The difficulty is that the nanoPEB's ports are different from the CF7's! This requires querying the DSR for unique device names. SIO is unique to the nanoPEB V1; COM1 is unique to the nanoPEB V2; and PIO is unique to all the CF7s. When a “disk” sector is read/written, only the first 256 bytes are used. This makes the DSR simpler because data are always accessed from the start of a sector, one word (usually) at a time. If all 512 bytes of a sector were used, odd TI sectors would require a 256-byte dummy read before the first byte of the odd TI sector would be reached. And, of course, a scheme would need to be devised for managing it, which would definitely complicate the DSR. That is why only half of the CF is used for the TI file system. But, I digress... ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 4, 2016 Author Share Posted December 4, 2016 Here is my offering for the nanoPEB/CF7 virtual disk mounting: HEX : CF? ( -- flag ) \ nanoPEB/CF7 present? 3FF8 VSBR SWPB 3FF9 VSBR + \ get magic number AA03 = ; \ leave TRUE if nanoPEB/CF7 0 VARIABLE CFVOL# 4 ALLOT \ volume # array for DSK1-DSK3 : CFVOLS ( -- volDSK1 volDSK2 volDSK3 ) \ get vol#s in DSKs CF? IF \ if CF, continue 3FFA CFVOL# 6 VMBR \ get vol#s to DSK array CFVOL# DUP 6 + SWAP DO I @ \ get vol#s to stack 2 +LOOP ELSE ." No CF detected!" \ else error message THEN ; : CFMOUNT ( vol# dsk# -- ) \ mount CF vol# in DSK<dsk#> CF? IF \ if CF, continue 3FFB SWAP \ stack:vol# 3FFB dsk# CASE 1 OF ENDOF \ DSK1 stack:vol# 3FFB 2 OF 2+ ENDOF \ DSK2 stack:vol# 3FFD 3 OF 4 + ENDOF \ DSK3 stack:vol# 3FFF ELSEOF ." DSK# must be 1-3!" ABORT ENDOF \ error! ENDCASE OVER SWPB OVER 1- \ stack:vol# 3FFB|3FFD|3FFF vol#[LSB-MSB] 3FFA|3FFC|3FFE VSBW VSBW \ copy bytes of vol# to DSK slot in VRAM ELSE ." No CF detected!" \ else error message THEN ; DECIMAL CF? checks for the magic number, >AA03, at VRAM >3FF8, where the nanoPEB/CF7 DSR places it. It leaves 1 (TRUE) if found and 0 (FALSE) if not. CFVOL# is an array of three 16-bit numbers representing the CF volume numbers mounted in DSK1, DSK2 and DSK3. CFVOLS populates the CFVOL# array and leaves on the stack the volume numbers associated with DSK1, DSK2 and DSK3. CFMOUNT mounts the volume supplied in the DSK# supplied. The following entry will mount volume #234 in DSK2: 234 2 CFMOUNT The volumes mounted by CFMOUNT will persist only through the current session of fbForth 2.0. This includes cycling through COLD and BOOT . A reset to the TI-99/4A title screen will mount the three volumes stored in the CF card before fbForth 2.0 was started. As you can see, you will need to use the TI Basic CALL MOUNT, CF2K or TI99Dir to write the volume mounts to the CF card. I am not sure I will change this anytime soon because of the significantly greater programming effort required. After some time for discussion and testing of these words, I will add them to FBLOCKS. ...lee 2 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.