Skip to content

Commit 063d394

Browse files
committed
Add HERE , C, ALLOT and ALIGN plus tests.
1 parent 32f9903 commit 063d394

File tree

6 files changed

+153
-13
lines changed

6 files changed

+153
-13
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,8 @@ error if it cannot be cannot be cross compiled.
449449
* `+`
450450
* `+!`
451451
* `+LOOP`
452+
* `,`
453+
* Can only run on host.
452454
* `-`
453455
* `.`
454456
* `."`
@@ -479,12 +481,18 @@ error if it cannot be cannot be cross compiled.
479481
* `?DUP`
480482
* `@`
481483
* `ABS`
484+
* `ALIGN`
485+
* Can only run on host.
482486
* `ALIGNED`
487+
* `ALLOT`
488+
* Can only run on host.
483489
* `AND`
484490
* `BASE`
485491
* `BEGIN`
486492
* `BL`
487493
* `C!`
494+
* `C,`
495+
* Can only run on host.
488496
* `C@`
489497
* `CELL+`
490498
* `CELLS`
@@ -507,6 +515,7 @@ error if it cannot be cannot be cross compiled.
507515
* `EXIT`
508516
* `FIND`
509517
* Can only run on host.
518+
* `HERE`
510519
* `I`
511520
* `IF`
512521
* `IMMEDIATE`

pkg/forth/basic_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ func TestPrimitives(t *testing.T) {
5454
asm: wrapMain("3 1 - u."),
5555
expect: "2 ",
5656
},
57+
{
58+
name: "subtract address",
59+
asm: wrapMain("here 1+ char+ here - u. here here 1+ char+ - u. here 1+ here - u."),
60+
expect: "32769 32767 1 ",
61+
},
5762
{
5863
name: "LSHIFT",
5964
asm: wrapMain("1 0 LSHIFT u. 1 1 LSHIFT u. 1 2 LSHIFT u."),

pkg/forth/builtin/02_core.f

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,3 +369,56 @@
369369
DROP 0 \ drop the result, return 0
370370
;
371371

372+
0 BUFFER: DATASPACE \ create a buffer starting at size 0 to hold the data space
373+
VARIABLE DATAPOINTER \ create a variable to keep track of the data space pointer
374+
DATASPACE DATAPOINTER ! \ set the data space pointer
375+
376+
: HERE ( -- addr )
377+
DATAPOINTER @ \ return the dataspace pointer plus the size
378+
;
379+
380+
: DATASIZE
381+
DATAPOINTER @ DATASPACE - \ find the size difference
382+
0x7FFF AND
383+
;
384+
385+
: ALLOT ( n -- )
386+
DUP DATASIZE + ( n newSize )
387+
DUP 0> 0= IF ( n newSize )
388+
\ an ambiguous condition exists if we attempt to create a negative data space size
389+
\ or exit immediately if 0
390+
2DROP
391+
EXIT
392+
THEN ( n newSize )
393+
SWAP DATAPOINTER +! ( newSize ) \ update the data space pointer
394+
DATASPACE SWAP ( dataspace newSize )
395+
RESIZE ( newaddress 0 ) \ resize the dataspace
396+
2DROP \ remove the extra values from the resize
397+
;
398+
399+
: , ( n -- )
400+
HERE ( n here ) \ get the current address pointer
401+
1 ALLOT \ increment the dataspace by 1
402+
! \ store the value
403+
;
404+
405+
: C, ( char -- )
406+
HERE DATASPACE - \ find the size difference
407+
0< IF \ if the upper bit is set then we don't need to allocate
408+
409+
ELSE
410+
1 ALLOT \ allocate one more space
411+
HERE 1- DATAPOINTER ! \ fix the data pointer
412+
THEN
413+
HERE C! \ store the data
414+
HERE CHAR+ DATAPOINTER ! \ update the data pointer
415+
;
416+
417+
: ALIGN ( )
418+
HERE HERE \ get the current address pointer
419+
ALIGNED ( here here+n ) \ align the address pointer
420+
- ( diff ) \ get the difference between them
421+
0x7FFF AND \ shave off the extra bit
422+
ALLOT \ change the data space accordingly
423+
;
424+

pkg/forth/primitive.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,7 @@ func PrimitiveSetup(vm *VirtualMachine) error {
12731273
}
12741274
return nil
12751275
case CellAddress:
1276-
err = vm.Stack.Push(CellAddress{l.Entry, l.Offset + int(r.Number), false})
1276+
err = vm.Stack.Push(CellAddress{l.Entry, l.Offset + int(int16(r.Number)), false})
12771277
if err != nil {
12781278
return PushError(err, entry)
12791279
}
@@ -1284,7 +1284,7 @@ func PrimitiveSetup(vm *VirtualMachine) error {
12841284
case CellAddress:
12851285
switch l := left.(type) {
12861286
case CellNumber:
1287-
err = vm.Stack.Push(CellAddress{r.Entry, int(l.Number) + r.Offset, false})
1287+
err = vm.Stack.Push(CellAddress{r.Entry, int(int16(l.Number)) + r.Offset, false})
12881288
if err != nil {
12891289
return PushError(err, entry)
12901290
}
@@ -1352,7 +1352,13 @@ func PrimitiveSetup(vm *VirtualMachine) error {
13521352
switch l := left.(type) {
13531353
case CellAddress:
13541354
if l.Entry == r.Entry {
1355-
err = vm.Stack.Push(CellNumber{uint16(l.Offset) - uint16(r.Offset)})
1355+
val := int16(l.Offset) - int16(r.Offset)
1356+
if l.UpperByte && !r.UpperByte {
1357+
val += -0x8000
1358+
} else if !l.UpperByte && r.UpperByte {
1359+
val -= -0x8000
1360+
}
1361+
err = vm.Stack.Push(CellNumber{uint16(val)})
13561362
if err != nil {
13571363
return PushError(err, entry)
13581364
}

pkg/forth/suite_test.go

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,37 @@ func TestSuite(t *testing.T) {
6666
`,
6767
},
6868
// AGAIN does not have test cases
69-
// ALIGN
69+
{
70+
name: "ALIGN",
71+
setup: `
72+
ALIGN 1 ALLOT HERE ALIGN HERE 3 CELLS ALLOT
73+
CONSTANT A-ADDR CONSTANT UA-ADDR
74+
T{ UA-ADDR ALIGNED -> A-ADDR }T
75+
`,
76+
code: `
77+
T{ 1 A-ADDR C! A-ADDR C@ -> 1 }T
78+
T{ 1234 A-ADDR ! A-ADDR @ -> 1234 }T
79+
T{ 123 456 A-ADDR 2! A-ADDR 2@ -> 123 456 }T
80+
T{ 2 A-ADDR CHAR+ C! A-ADDR CHAR+ C@ -> 2 }T
81+
T{ 3 A-ADDR CELL+ C! A-ADDR CELL+ C@ -> 3 }T
82+
T{ 1234 A-ADDR CELL+ ! A-ADDR CELL+ @ -> 1234 }T
83+
T{ 123 456 A-ADDR CELL+ 2! A-ADDR CELL+ 2@ -> 123 456 }T
84+
`,
85+
},
7086
// ALIGNED does not have test cases
71-
// ALLOT
87+
{
88+
name: "ALLOT",
89+
setup: `
90+
HERE 1 ALLOT
91+
HERE
92+
CONSTANT 2NDA
93+
CONSTANT 1STA
94+
`,
95+
code: `
96+
T{ 1STA 2NDA - 0< -> <TRUE> }T \ HERE MUST GROW WITH ALLOT
97+
T{ 1STA 1+ -> 2NDA }T \ ... BY ONE ADDRESS UNIT
98+
`,
99+
},
72100
{
73101
name: "AND",
74102
code: `
@@ -195,7 +223,25 @@ func TestSuite(t *testing.T) {
195223
T{ 0 2 cs2 -> 299 }T
196224
`,
197225
},
198-
// C,
226+
{
227+
name: "C,",
228+
setup: `
229+
HERE 1 C,
230+
HERE 2 C,
231+
CONSTANT 2NDC
232+
CONSTANT 1STC
233+
`,
234+
code: `
235+
T{ 1STC 2NDC - 0< -> <TRUE> }T \ HERE MUST GROW WITH ALLOT
236+
T{ 1STC CHAR+ -> 2NDC }T \ ... BY ONE CHAR
237+
// T{ 1STC 1 CHARS + -> 2NDC }T \ this test is incorrect
238+
T{ 1STC C@ 2NDC C@ -> 1 2 }T
239+
T{ 3 1STC C! -> }T
240+
T{ 1STC C@ 2NDC C@ -> 3 2 }T
241+
T{ 4 2NDC C! -> }T
242+
T{ 1STC C@ 2NDC C@ -> 3 4 }T
243+
`,
244+
},
199245
// CELL+ doesn't have regular tests
200246
{
201247
name: "CELLS",
@@ -281,7 +327,23 @@ func TestSuite(t *testing.T) {
281327
T{ nn2 @ EXECUTE -> 9876 }T
282328
`,
283329
},
284-
// ,
330+
{
331+
name: ",",
332+
code: `
333+
T{ 1ST 2ND - 0< -> <TRUE> }T \ HERE MUST GROW WITH ALLOT
334+
T{ 1ST CELL+ -> 2ND }T \ ... BY ONE CELL
335+
T{ 1ST 1 CELLS + -> 2ND }T
336+
T{ 1ST @ 2ND @ -> 1 2 }T
337+
T{ 5 1ST ! -> }T
338+
T{ 1ST @ 2ND @ -> 5 2 }T
339+
T{ 6 2ND ! -> }T
340+
T{ 1ST @ 2ND @ -> 5 6 }T
341+
T{ 1ST 2@ -> 6 5 }T
342+
T{ 2 1 1ST 2! -> }T
343+
T{ 1ST 2@ -> 2 1 }T
344+
T{ 1S 1ST ! 1ST @ -> 1S }T \ CAN STORE CELL-WIDE VALUE
345+
`,
346+
},
285347
// C"
286348
// DECIMAL does not have any tests
287349
{
@@ -419,7 +481,7 @@ func TestSuite(t *testing.T) {
419481
// FIND
420482
// FM/MOD
421483
// @ does not have any tests
422-
// HERE
484+
// HERE does not have any tests
423485
// HEX does not have any tests
424486
// HOLD
425487
// HOLDS
@@ -452,6 +514,8 @@ func TestSuite(t *testing.T) {
452514
T{ VARIABLE iw3 IMMEDIATE 234 iw3 ! iw3 @ -> 234 }T
453515
T{ : iw4 iw3 [ @ ] LITERAL ; iw4 -> 234 }T
454516
T{ :NONAME [ 345 ] iw3 [ ! ] ; DROP iw3 @ -> 345 }T
517+
\ The rest of these tests fail because CREATE does not
518+
\ put the newly created definition on the data space.
455519
\ T{ CREATE iw5 456 , IMMEDIATE -> }T
456520
\ T{ :NONAME iw5 [ @ iw3 ! ] ; DROP iw3 @ -> 456 }T
457521
\ T{ : iw6 CREATE , IMMEDIATE DOES> @ 1+ ; -> }T
@@ -1515,15 +1579,15 @@ func TestSuite(t *testing.T) {
15151579
setup: `
15161580
T{ 50 CELLS ALLOCATE SWAP addr ! -> 0 }T
15171581
T{ addr @ ALIGNED -> addr @ }T \ Test address is aligned
1518-
// T{ HERE -> datsp @ }T \ Check data space pointer is unaffected
1582+
T{ HERE -> datsp @ }T \ Check data space pointer is unaffected
15191583
addr @ 50 write-cell-mem
15201584
addr @ 50 check-cell-mem \ Check we can access the heap
15211585
T{ addr @ FREE -> 0 }T
15221586
15231587
T{ 99 ALLOCATE SWAP addr ! -> 0 }T
15241588
T{ addr @ ALIGNED -> addr @ }T \ Test address is aligned
15251589
T{ addr @ FREE -> 0 }T
1526-
// T{ HERE -> datsp @ }T \ Data space pointer unaffected by FREE
1590+
T{ HERE -> datsp @ }T \ Data space pointer unaffected by FREE
15271591
T{ -1 ALLOCATE SWAP DROP 0= -> <TRUE> }T \ Memory allocation works with max size
15281592
`,
15291593
},
@@ -1544,7 +1608,7 @@ func TestSuite(t *testing.T) {
15441608
T{ addr @ -1 RESIZE 0= -> addr @ <TRUE> }T
15451609
15461610
T{ addr @ FREE -> 0 }T
1547-
// T{ HERE -> datsp @ }T \ Data space pointer is unaffected
1611+
T{ HERE -> datsp @ }T \ Data space pointer is unaffected
15481612
`,
15491613
code: ``,
15501614
},

pkg/forth/test/suite_test.f

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,14 @@
119119
\ from the ['] test, used in many
120120
T{ : GT2 ['] GT1 ; IMMEDIATE -> }T
121121

122-
\ ' EXIT CONSTANT 1ST
123-
T{ VARIABLE 1ST -> }T \ not the same as the test suite
122+
HERE 1 ,
123+
HERE 2 ,
124+
CONSTANT 2ND
125+
CONSTANT 1ST
124126

125127
VARIABLE addr
126128
VARIABLE datsp
129+
HERE datsp !
127130
: write-char-mem ( address n -- )
128131
\ from 0 to n
129132
0 ?DO

0 commit comments

Comments
 (0)