,---------------. | Contributions | `---------------´ ,------------------------------------------ | 2024-06-11 15:56:58 ruv wrote: | requestClarification - Data type of a parameters in `c!` | see: https://forth-standard.org/standard/core/CStore#contribution-342 `------------------------------------------ Is the following fragment standard compliant? ``` -1 pad c! ``` The glossary entry for `c!` says: > _( char c-addr -- )_ > When character size is smaller than cell size, only the number of low-order bits corresponding to character size are transferred. It seems, the text description implies a stack diagram _( x c-addr -- )_ or _( char|x c-addr -- )_. ,---------. | Replies | `---------´ ,------------------------------------------ | 2024-06-02 05:19:13 BerndPaysan replies: | requestClarification - Usage of the `n|u` data type | see: https://forth-standard.org/standard/core/Plus#reply-1225 `------------------------------------------ See A.3.2.1 how deeply the assumptions of two's complement are rooted into Forth. Therefore, the operations `+` and `-` work interchangeable for unsigned and signed, and even mixed. If your system is not two's complement, unsigned is restricted to +n. IIRC, not using two's complement is no longer an option. ,------------------------------------------ | 2024-06-03 15:04:14 bfox9900 replies: | referenceImplementation - Possible Reference Implementation | see: https://forth-standard.org/standard/string/SEARCH#reply-1226 `------------------------------------------ I should read the specification more closely. This correction gives the correct output if search fails to find the string. Reduced some stack juggling with the dreaded PICK. ``` : SEARCH ( caddr1 u1 caddr2 u2 -- caddr3 u3 flag) BEGIN DUP WHILE 2OVER 3 PICK OVER COMPARE WHILE 1 /STRING REPEAT 2NIP TRUE EXIT THEN 2DROP FALSE ; ``` ``` ,------------------------------------------ | 2024-06-04 15:40:50 ruv replies: | comment - Data object notion usage | see: https://forth-standard.org/standard/usage#reply-1227 `------------------------------------------ As I see it, to solve the mentioned problem with the notion and definition of "data type", a more detailed formalization is required. The main premise: every data object is _formally_ associated with a set of data types. Thus, we can talk about "typed data objects" (an abstraction), data objects that are associated with data types: A _typed data object_ is an ordered pair of a data object and a set of data types. Consequently, every data type determines an _abstract_ set of _typed data objects_. And it's possible to determine where a _typed data object_ is a member of a data type (namely, a member of the set that is determined by that data type). So where are "values"? A value for a typed data object is determined by data types. And since a typed data object may belong to several data types (for example, to _n_ and to _flag_), it may have a set of different values. But one data type determines only one value for one data object (that is allowed to be associated with this data type). > A data type identifies the set of permissible values for a data object. So, a variant that seems more correct: **A data type identifies a set of data objects and a value for each data object from that set.** If somebody interested, see [my attempt](https://gist.github.com/ruv/76ac54cf3bb520f65fd31de02db0cf17) of a more detailed formalization, a feedback is welcome. ,------------------------------------------ | 2024-06-04 16:01:55 AntonErtl replies: | requestClarification - Usage of the `n|u` data type | see: https://forth-standard.org/standard/core/Plus#reply-1228 `------------------------------------------ For the moment, let's take the Forth-94/2012 position that the result on integer overflow (i.e. where a mathematical integer addition produces a result outside the target range) is implementation-defined. Let's say I want to avoid that; even then I can construct cases for various combinations of n and u; to make things more concrete, let's assume that the range of n is -32768..32767 and for u it is 0..65535: ``` 1 1 + \ gives 2; +n1 +n2 -- +n (where +n is both u and n) 33000 -1 + \ gives 32999; u1 n2 -- u 33000 -1000 + \ gives 32000; u1 n2 -- +n 1 -2 + \ gives -1; +n1 n2 -- n -1 -1 + \ gives -2; n1 n2 -- n 20000 20000 + \ gives 40000; +n1 +n2 -- u ``` For the stack diagrams with +n, you could produce either one with n or with u instead of the +n, which means that in the first case you can have all 8 combinations. These are all standard Forth programs where the mathematical integer result is in the target range, so no, the diagram is not limited to be equivalent to `( n1 n2 -- n3 | u1 u2 -- u3 )`. My take is that n|u means a range of -32768..65535 for the example ranges above, just as +n (i.e., n&u) means 0..32767. In 2015 the committee accepted [2s-Complement Wrap-Around Integers](http://www.forth200x.org/twos-complement.html), which defines what happens in those cases where the result does not fit in the target range; with that it is up to the programmer in all cases how to interpret the arguments and the results of `+`; e.g., the `-1 -1 +` case for the ranges given above can also be interpreted as: ``` 65535 65535 + \ gives 65534; u1 u2 -- u ``` ,------------------------------------------ | 2024-06-05 16:25:57 ruv replies: | comment - Data object notion usage | see: https://forth-standard.org/standard/usage#reply-1229 `------------------------------------------ >> Moving a data object shall not affect its type. (2) > Granted, I also find (2) confusing. In my case, it's because it implies that objects somehow "know" their type. I think, a purpose of this statement is to guarantee a property that can be illustrated by the following examples. Let's consider the word `swap ( x1 x2 -- x3 x4 )`. It moves (in some sense) the data objects, but this shall not affect their data types (NB: a data object may be a member of several data types, not only the data type _x_). That is, not only the data objects in the stack parameters _x3_ and _x2_ are equal, but also their sets of data types are equal. I.e., they are equal as _typed data objects_. Ditto for _x4_ and _x1_. Ditto for the sequential operations `! ( x1 a-addr -- )` and `@ ( a-addr -- x2 )` for the same address: the typed data objects in the stack parameters _x2_ and _x1_ are equal. Ditto for the result of the `move` operation, etc (when you write data objects into one location, then copy them into another location, and then read from another location). ,------------------------------------------ | 2024-06-05 16:49:53 ruv replies: | requestClarification - Usage of the `n|u` data type | see: https://forth-standard.org/standard/core/Plus#reply-1230 `------------------------------------------ One idea, why the operations `+` and `-` should be defined when one argument in _u_, and the other argument in _n_ is that these operations on any integer arguments should be equal to a series of operations on `0` and `1`. Any number in _u_ that is outside of the _n_ range can be represented as the sum of several numbers in _n_. For example, `max-uint` is the sum of numbers (`max-int`, `max-int`, `1`), (supposing two's complement). Thus, an operation on numbers in _n_ and _u_ should be equivalent to several operations in _n_ only, resulting in _n_ (taking into account the overflow rule) (1). Any number in _n_ that is outside of the _u_ range can be represented as the subtraction of two numbers in _u_. For example, `min-int` is the subtraction of unsigned( `max-int` + `1`) from `0` (assuming two's complement). Thus, an operation on numbers in _n_ and _u_ should be equivalent to several operations in _u_ only, resulting in _u_ (taking into account the overflow rule) (2). I don't sure whether (1) and (2) both are always true for one's complement and sign-magnitude representations, but they are true for two's complement representation. It means, that the result of `+` and `-` , when one argument in _n_, and the other in _u_, always belongs to **both** _u_ and _n_ data types, and in some cases it also belongs to the _+n_ data type. Also, if one (and not the other) of the arguments is in _addr_, the result (in the general case) is in _u_ and in _addr_ , but not in _n_. ----- It seems, (1) and (2) are also true for `* ( n1|u1 n2|u2 -- n3|u3 ) `. ,------------------------------------------ | 2024-06-06 17:05:04 AntonErtl replies: | proposal - Fix stack comments for N>R and NR> | see: https://forth-standard.org/proposals/fix-stack-comments-for-n-r-and-nr-#reply-1231 `------------------------------------------ ## Author: * Anton Ertl * Leon Wagner ## Change Log * 2024-06-06 replaced some `n` with `+n`; formatting changes (AE) * 2023-09-14 Revision after discussion (AE) * 2023-09-13 Initial proposal ## Problem: The stack comments for N>R and NR> don't make it clear that _+n_ items are moved between the data and return stacks. ## Solution: The stack comments should more clearly indicate that _+n_ data stack items are moved to or from the return stack. ## Proposal: In the definition of [`N>R`](https://forth-standard.org/standard/tools/NtoR), replace > `( i * n +n -- ) ( R: -- j * x +n )` with > `( x_n ... x_1 +n -- ) ( R: -- j*x +n )` In the definition of [`NR>`](https://forth-standard.org/standard/tools/NRfrom), replace > `( -- i * x +n ) ( R: j * x +n -- )` with > `( -- x_n ... x_1 +n ) ( R: j*x +n -- )` ## Discussion On the return stack, `j*x +n` because the data may be in a separate buffer and only the address and `+n` on the return stack. `+n` on the return stack because the original specified that, and changing that would be a substantial change. On the data stack `x_n ... x_1 +n` because that is the way we usually specify a numbered number of cells (even for `+n=0`). See, e.g., [`get-order`](https://forth-standard.org/standard/search/GET-ORDER).