From sjudd at ffd2.com Fri Nov 18 20:26:40 2005 From: sjudd at ffd2.com (Steve Judd) Date: Fri, 18 Nov 2005 19:26:40 -0700 (MST) Subject: [Slackers] Test post Message-ID: Testing... 1... 2... 3... sibilance... sibilance... From sjudd at ffd2.com Sun Nov 27 12:05:00 2005 From: sjudd at ffd2.com (Steve Judd) Date: Sun, 27 Nov 2005 11:05:00 -0700 (MST) Subject: [Slackers] Array implementation in Slang Message-ID: Well folks, as far as I can tell a grand total of three people (besides myself) have subscribed to the slackers list. But what the heck, might as well make it interesting. I am starting on the technical documentation for Slang. The goal is to start documenting the innards, explain the code that's being generated, and get to the point of explaining how to use the compiler to design new languages. What I'll do is post them here, and after a while post them to the forum. So: arrays. In keeping with the principle of doing things the way a 6502 coder would, arrays are implemented using lookup tables. Moreover, arrays are optimized to use LDA xxxx,X or LDA(zp),y where appropriate, again more like a 6502 programmer would. When an array definition like int c(10,20) is encountered, the compiler does the following: 1) Allocate space at the end of the program for the array tables and the array storage (2 bytes/int * 10*20 = 400 bytes). One consequence of this is that the program size gets large quickly. If an @-address is found array storage will not be allocated, only the lookup tables. Therefore, for large arrays which do not need to be pre-initialized it is better to define them as @-arrays, to keep file sizes down. 2) Set up the array lookup tables. In the above example there are two lookup tables, one for each dimension. Each table is a table of offsets; adding the offsets for each dimension together gives the element address. The elements are stored in memory as: 0,0 0,1 0,2 ... 0,19 1,0 1,1 1,2 ... 1,19 ... 9,0 9,1 9,2 ... 9,19 That is, arrays are in (row,column) order, with the last element corresponding to adjacent addresses in memory. In this example, each column consists of two bytes (since this is an int array), and each row consists of 20 columns = 40 bytes. The lookup tables are therefore: table 1 (dimension 1): base row 0 address base+40 row 1 base+80 row 2 ... base+360 row 9 table 2 (dimension 2): 0 column 0 offset 2 col 1 offset 4 ... 38 The lookup process is then: lookup dimension 1 address; store in zp lookup dimension 2 address; add to zp, store to zp array element may now be fetched by LDA (zp),Y Note in the above example that the array base is added in to the first table. This means that the lookup may still be performed if fewer array elements are supplied in a piece of code. For example, c(4) is the same as c(4,0), and the compiler will allow this. This is to help optimize code, by not adding in extra zero offsets. Special cases: In the above example, LDA (zp),Y is used to fetch array elements. When the total array size is less than 256 bytes, it is possible to use LDA xxxx,X. If the above example is changed to int c(10,10) then lookup tables are still used, but because the total array size is now 200 bytes LDA xxxx,X addressing is used. Now the lookup tables will be: table 1 (dim 1): 0 ;row 0 _offset_ 20 ;row 1 40 ;row 2 ... 180 ;row 9 table 2 (dim 2): 0 ;col 0 offset 2 ;col 1 ... 18 ;col 9 and the lookup process becomes: fetch dim 1 (row) offset; store in zp fetch dim 2 (col) offset; add to zp array element is now given by LDX zp LDA base,X Further optimizations may now be done for byte arrays: - 1D byte arrays with less than 256 elements: no lookup table required, can index directly. - byte arrays with last dimension < 256: no lookup table required for last dimension and so forth. In the future, futher optimizations will hopefully be done for arrays along the lines of the evaluation optimizer, discussed later.