/*
TestForthCompF99b.java
(c) 2010-2014 Edward Swartz
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
*/
package v9t9.tools.forthcomp.test;
import static v9t9.machine.f99b.asm.InstF99b.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import ejs.base.utils.Pair;
import v9t9.machine.f99b.asm.InstF99b;
import v9t9.tools.forthcomp.AbortException;
import v9t9.tools.forthcomp.ITargetWord;
import v9t9.tools.forthcomp.IWord;
import v9t9.tools.forthcomp.words.TargetColonWord;
public class TestForthCompF99b extends BaseF99bTest {
@Test
public void testLiteral() throws Exception {
parseString("123");
assertEquals(123, hostCtx.popData());
}
@Test
public void testLiteral2() throws Exception {
parseString("123 456");
assertEquals(456, hostCtx.popData());
assertEquals(123, hostCtx.popData());
}
@Test
public void testVariable1() throws Exception {
targCtx.clearDict();
startDP = targCtx.getDP();
parseString("Variable t");
dumpDict();
ITargetWord var = targCtx.require("T");
var.getExecutionSemantics().execute(hostCtx, targCtx);
assertEquals(var.getEntry().getParamAddr(), hostCtx.popData());
//assertEquals(-1, hostCtx.popData());
//assertEquals(((ITargetWord)var).getEntry().getContentAddr(), targCtx.resolveAddr(-1));
assertTrue(startDP == 0 || startDP > targCtx.readCell(startDP));
assertEquals((byte)0x81, targCtx.readChar(startDP + 2));
assertEquals('t', targCtx.readChar(startDP + 3));
}
@Test
public void testVariable2() throws Exception {
targCtx.clearDict();
startDP = targCtx.getDP();
parseString("Variable t Variable ud");
ITargetWord tvar = targCtx.require("T");
tvar.getExecutionSemantics().execute(hostCtx, targCtx);
ITargetWord uvar = targCtx.require("Ud");
uvar.getExecutionSemantics().execute(hostCtx, targCtx);
int ud = hostCtx.popData();
int t = hostCtx.popData();
assertEquals(tvar.getEntry().getParamAddr(), t);
assertEquals(uvar.getEntry().getParamAddr(), ud);
assertEquals(0, tvar.getEntry().getAddr() & 1);
assertEquals(0, tvar.getEntry().getContentAddr() & 1);
assertEquals(0, uvar.getEntry().getAddr() & 1);
assertEquals(0, uvar.getEntry().getContentAddr() & 1);
}
@Test
public void testCompileTimeVariableLoadStore() throws Exception {
targCtx.clearDict();
parseString("Variable t Variable u 123 t ! t @ u ! u @");
IWord uvar = targCtx.require("U");
assertEquals(123, targCtx.readCell(((ITargetWord)uvar).getEntry().getParamAddr()));
assertEquals(123, hostCtx.popData());
}
@Test
public void testColon1() throws Exception {
ITargetWord semiS = targCtx.require(";S");
assertNotNull(semiS);
parseString(": foo ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("foo");
assertNotNull(foo);
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, Iexit);
assertEquals(dp + 1, targCtx.getDP());
}
@Test
public void testColon2() throws Exception {
parseString(": foo ; : b ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("foo");
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, Iexit);
// b should be aligned after foo
TargetColonWord bword = (TargetColonWord) targCtx.require("b");
assertEquals(dp + targCtx.getCellSize(), bword.getEntry().getAddr());
dp = bword.getEntry().getContentAddr();
assertOpcodes(dp, Iexit);
assertEquals(dp + 1, targCtx.getDP());
}
protected void assertOpcodes(int dp, int... opcodes) {
int start = dp;
for (int i = 0; i < opcodes.length; i++) {
if (opcodes[i] < 256) {
assertEquals((dp-start)+":"+(i)+"", opcodes[i], targCtx.readChar(dp) & 0xff);
dp++;
}
else {
assertEquals((dp-start)+":"+(i)+"", (opcodes[i] >> 8) & 0xff, targCtx.readChar(dp) & 0xff);
assertEquals((dp-start)+":"+(i+1)+"", (opcodes[i] & 0xff), targCtx.readChar(dp+1) & 0xff);
dp += 2;
}
}
}
@Test
public void testPrimPacking1() throws Exception {
parseString(": foo @ ! 0 dup ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("foo");
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, Iload, Istore, IlitX, Idup, Iexit);
assertEquals(dp + 5, targCtx.getDP());
}
@Test
public void testLiterals1() throws Exception {
parseString(": eq 7 3 - 0= ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("eq");
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, IlitX | 7, IlitX | 3, Isub, I0equ, Iexit);
assertEquals(dp + 5, targCtx.getDP());
}
@Test
public void testLiterals2() throws Exception {
parseString(": eq 15 456 = ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("eq");
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, IlitB, 15, IlitW, 456, Iequ, Iexit);
assertEquals(dp + 7, targCtx.getDP());
}
@Test
public void testLiterals3() throws Exception {
parseString(": eq -3 5 4 ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("eq");
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, IlitX | (-3& 0xf), IlitX | 5, IlitX | 4, Iexit);
assertEquals(dp + 4, targCtx.getDP());
}
@Test
public void testLiterals3Ex() throws Exception {
parseString(": eq -3 5 3 ;");
interpret("eq");
assertEquals(3, hostCtx.popData());
assertEquals(5, hostCtx.popData());
assertEquals(-3, hostCtx.popData());
}
@Test
public void testLiterals6() throws Exception {
parseString(": eq 11. $ffff.aaaa ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("eq");
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, IlitB_d, 11, IlitD_d, 0xaaaa, 0xffff, Iexit);
}
@Test
public void testLiterals7Ex() throws Exception {
parseString("14 constant INT_NMI : foo ; : eq 0 ['] foo INT_NMI foo ;");
interpret("eq");
assertEquals(14, hostCtx.popData());
}
@Test
public void testLiterals4() throws Exception {
parseString(": eq 122 @ 456 ! 789 dup ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("eq");
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, IlitB, 122, Iload, IlitW, 456, Istore, IlitW, 789, Idup, Iexit);
assertEquals(dp + 12, targCtx.getDP());
}
@Test
public void testLiterals4Ex() throws Exception {
parseString(": eq 1020 1456 ! 789 dup ;");
targCtx.writeCell(1456, 1000);
interpret("eq");
assertEquals(1020, targCtx.readCell(1456));
assertEquals(789, hostCtx.popData());
}
@Test
public void testLiterals5Ex() throws Exception {
parseString(": num $1234.5678 ;");
interpret("num");
assertEquals(0x1234, hostCtx.popData());
assertEquals(0x5678, hostCtx.popData());
}
@Test
public void testBeginAgain0() throws Exception {
parseString(": true begin again ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("true");
dumpDict();
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, IbranchX|(-1 & 0xf), Iexit);
//interpret("true");
}
@Test
public void testBeginAgain1() throws Exception {
parseString(": true begin 0 0 0 0 0 0 0 0 0 0 again ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("true");
dumpDict();
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp,
0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20,
IbranchB, (-11 & 0xff), // 0:next, -1: branch, -2...-11
Iexit);
//interpret("true");
}
@Test
public void testIfBranch0() throws Exception {
parseString(": true if else then ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("true");
dumpDict();
int dp = foo.getEntry().getContentAddr();
// currently, always assuming byte jump, so 0's are IbranchX|0
assertOpcodes(dp, I0branchX | 3, 0, IbranchX | 1, 0, Iexit);
hostCtx.pushData(12);
hostCtx.pushData(0);
interpret("true");
assertEquals(12, hostCtx.popData());
hostCtx.pushData(12);
hostCtx.pushData(1);
interpret("true");
assertEquals(12, hostCtx.popData());
}
@Test
public void testIfBranch1() throws Exception {
parseString(": true if -1 else 0 then ;");
TargetColonWord foo = (TargetColonWord) targCtx.require("true");
dumpDict();
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, I0branchX | 4, 0, IlitX | (-1&0xf), IbranchX | 2, 0, IlitX, Iexit);
hostCtx.pushData(12);
interpret("true");
assertEquals(-1, hostCtx.popData());
hostCtx.pushData(0);
interpret("true");
assertEquals(0, hostCtx.popData());
}
@Test
public void testIfBranch1Ex() throws Exception {
parseString(": true if -1 else 0 then ;");
hostCtx.pushData(5);
interpret("true");
assertEquals(-1, hostCtx.popData());
hostCtx.pushData(0);
interpret("true");
assertEquals(0, hostCtx.popData());
}
@Test
public void testIfBranch() throws Exception {
parseString(": sgn dup 0< if drop -1 else 0= if 0 else 1 then then ;");
dumpDict();
TargetColonWord foo = (TargetColonWord) targCtx.require("sgn");
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, Idup, IlitX, Icmp+InstF99b.CMP_LT, I0branchX | 5, 0,
Idrop, IlitX|(-1&0xf), IbranchB, 7,
I0equ, I0branchX | 4, 0, IlitX, IbranchX | 2, 0, IlitX | 1,
Iexit);
}
@Test
public void testIfBranchEx() throws Exception {
parseString(": sgn dup 0< if drop -1 else 0= if 0 else 1 then then ;");
hostCtx.pushData(5);
interpret("sgn");
assertEquals(1, hostCtx.popData());
hostCtx.pushData(-102);
interpret("sgn");
assertEquals(-1, hostCtx.popData());
hostCtx.pushData(0);
interpret("sgn");
assertEquals(0, hostCtx.popData());
}
@Test
public void testColonCall() throws Exception {
parseString(": sub negate 10 + ; : outer 100 sub -50 sub + ;");
dumpDict();
TargetColonWord sub = (TargetColonWord) targCtx.require("sub");
TargetColonWord outer = (TargetColonWord) targCtx.require("outer");
int dp = outer.getEntry().getContentAddr();
assertOpcodes(dp, IlitB, 100);
assertEquals(sub.getEntry().getContentAddr(), targCtx.findReloc(dp + 2));
}
@Test
public void testColonCallEx() throws Exception {
parseString(": sub negate 10 + ; : outer 100 sub -50 sub + ;");
interpret("outer");
assertEquals(-30, hostCtx.popData());
}
@Test
public void testMultiplyDivide() throws Exception {
parseString(
//": */ ( n1 n2 n3 -- n4 ) >r um* r> um/mod swap drop ;\n" +
": */mod ( n1 n2 n3 -- rem quot ) >r um* r> um/mod ;\n" +
": */ ( n1 n2 n3 -- n4 ) */mod swap drop ;\n" +
": percent ( val p -- prod ) 100 */ ;\n" +
": outer 500 25 percent ;");
dumpDict();
interpret("outer");
assertEquals(125, hostCtx.popData());
}
@Test
public void testDoubleMath1Ex() throws Exception {
parseString(
": outer $8888 $ffff um* $8887.7778 d= ;");
interpret("outer");
assertEquals(-1, hostCtx.popData());
}
@Test
public void testDoubleMath2Ex() throws Exception {
parseString(
": outer $8887.7778 2>r $8887 r> = $7778 r> = + ;");
interpret("outer");
assertEquals(-2, hostCtx.popData());
}
@Test
public void testShifts1Ex() throws Exception {
parseString(
": outer $8887 12 urshift $8887 8 rshift $ffff 15 lshift ;");
interpret("outer");
assertEquals((short)0x8000, hostCtx.popData());
assertEquals((short)0xff88, hostCtx.popData());
assertEquals((short)0x0008, hostCtx.popData());
}
@Test
public void testShifts2Ex() throws Exception {
parseString(
": outer $8887 12U urshift $8887 8U rshift $ffff 15U lshift ;");
interpret("outer");
assertEquals((short)0x8000, hostCtx.popData());
assertEquals((short)0xff88, hostCtx.popData());
assertEquals((short)0x0008, hostCtx.popData());
}
@Test
public void testDoublShifts1Ex() throws Exception {
parseString(
": outer $8887.7778 16. durshift $8887.7778 8. drshift ;");
interpret("outer");
assertEquals((short)0xff88, hostCtx.popData());
assertEquals((short)0x8777, hostCtx.popData());
assertEquals(0, hostCtx.popData());
assertEquals((short)0x8887, hostCtx.popData());
}
@Test
public void testDoublShifts2Ex() throws Exception {
parseString(
": outer $8887.7778 16.U durshift $8887.7778 8.U drshift ;");
interpret("outer");
assertEquals((short)0xff88, hostCtx.popData());
assertEquals((short)0x8777, hostCtx.popData());
assertEquals(0, hostCtx.popData());
assertEquals((short)0x8887, hostCtx.popData());
}
@Test
public void testDoLoop() throws Exception {
parseString(": stack 0 do i loop ;");
dumpDict();
TargetColonWord foo = (TargetColonWord) targCtx.require("stack");
int dp = foo.getEntry().getContentAddr();
assertOpcodes(dp, IlitX, ItoR_d, IatR, IloopUp, I0branchX | 0xd, Irdrop_d, Iexit);
}
@Test
public void testDoLoopEx() throws Exception {
parseString(": stack 0 do i loop ;");
hostCtx.pushData(5);
interpret("stack");
assertEquals(4, hostCtx.popData());
assertEquals(3, hostCtx.popData());
assertEquals(2, hostCtx.popData());
assertEquals(1, hostCtx.popData());
assertEquals(0, hostCtx.popData());
}
/*
@Test
public void testQDoLoop() throws Exception {
parseString(": stack 0 ?do i loop ;");
dumpDict();
TargetColonWord foo = (TargetColonWord) targCtx.require("stack");
// 2dup copy vals
// 2>r place init/lim on rstack
// = compare init/lim
// 0branch if not equal, go into loop
// xx
// branch go to leave
// yy
// i
// loop
// -zz
// << leave point >>
// rdrop
// rdrop
int dp = foo.getEntry().getContentAddr();
int word = targCtx.readAddr(dp);
assertOpword(word, IfieldLit, 0, Iext);
word = targCtx.readAddr(dp + 2);
assertOpword(word, Idup_d - _Iext, Iext, ItoR_d - _Iext);
word = targCtx.readAddr(dp + 4);
assertOpword(word, Ibinop, OP_SUB, I0branch); // [if] 0branch to skip loop
word = targCtx.readAddr(dp + 6);
assertEquals(8 & 0xffff, word); // past loop
word = targCtx.readAddr(dp + 8); // body
assertOpword(word, Iext, IatR - _Iext , Iloop);
word = targCtx.readAddr(dp + 10);
assertEquals(0 & 0xffff, word);
word = targCtx.readAddr(dp + 12);
assertOpword(word, Irdrop, Irdrop, Iexit);
}*/
@Test
public void testDoQLoopEx() throws Exception {
parseString(": stack 3 ?do i loop ;");
hostCtx.pushData(5);
interpret("stack");
assertEquals(4, hostCtx.popData());
assertEquals(3, hostCtx.popData());
hostCtx.pushData(-10); // sentinel
hostCtx.pushData(3);
interpret("stack");
assertEquals(-10, hostCtx.popData());
}
@Test
public void testDoLoopLeaveEx() throws Exception {
parseString(": stack 10 3 do i 5 = if leave then i loop ;");
interpret("stack");
assertEquals(4, hostCtx.popData());
assertEquals(3, hostCtx.popData());
}
@Test
public void testDoPlusLoopEx() throws Exception {
parseString(": stack 0 do i 3 +loop ;");
hostCtx.pushData(10);
interpret("stack");
assertEquals(9, hostCtx.popData());
assertEquals(6, hostCtx.popData());
assertEquals(3, hostCtx.popData());
assertEquals(0, hostCtx.popData());
hostCtx.pushData(9);
interpret("stack");
assertEquals(6, hostCtx.popData());
assertEquals(3, hostCtx.popData());
assertEquals(0, hostCtx.popData());
}
@Test
public void testDoPlusLoopEx2() throws Exception {
parseString(": stack 0 do i 16384 +loop ;");
hostCtx.pushData(0);
interpret("stack");
assertEquals((short)49152, hostCtx.popData());
assertEquals((short)32768, hostCtx.popData());
assertEquals(16384, hostCtx.popData());
assertEquals(0, hostCtx.popData());
}
@Test
public void testDoPlusLoopEx3() throws Exception {
parseString(": stack 10 -10 do i 4 +loop ;");
interpret("stack");
assertEquals(6, hostCtx.popData());
assertEquals(2, hostCtx.popData());
assertEquals(-2, hostCtx.popData());
assertEquals(-6, hostCtx.popData());
assertEquals(-10, hostCtx.popData());
}
@Test
public void testStackAccessorsEx() throws Exception {
parseString(
"$76 constant IcontextFrom\n"+
": depth [ IcontextFrom c, CTX_SP0 field, ] [ IcontextFrom c, CTX_SP field, ] - 2/ 1- ;\n"+
": rdepth [ IcontextFrom c, CTX_RP0 field, ] [ IcontextFrom c, CTX_RP field, ] - 2/ 1- ; \n" +
": stack 1 2 4 5 >r depth rdepth rdrop ;");
interpret("stack");
assertEquals(2, hostCtx.popData());
assertEquals(3, hostCtx.popData());
}
@Test
public void testLogOpsEx1() throws Exception {
parseString(
": tst 1 2 < 1 2 > 1 -2 < 1 -2 > 6 6 >= -8 6 <= ;\n" +
": utst 1 2 u< 1 2 u> 1 -2 u< 1 -2 u> 6 6 u>= -8 6 u<= ;"
);
interpret("tst");
assertEquals(-1, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
assertEquals(0, hostCtx.popData());
assertEquals(0, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
interpret("utst");
assertEquals(0, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
assertEquals(0, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
assertEquals(0, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
}
@Test
public void testLogOpsEx2() throws Exception {
parseString(
": tst 1. 2. d< 1. 2. d> 1. -2. d< 1. -2. d> 6. 6. d>= -8. 6. d<= ;\n" +
": utst 1. 2. du< 1. 2. du> 1. -2. du< 1. -2. du> 6. 6. du>= -8. 6. du<= ;"
);
interpret("tst");
assertEquals(-1, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
assertEquals(0, hostCtx.popData());
assertEquals(0, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
interpret("utst");
assertEquals(0, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
assertEquals(0, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
assertEquals(0, hostCtx.popData());
assertEquals(-1, hostCtx.popData());
}
@Test
public void testMemOps1Ex() throws Exception {
parseString(
"Variable x\n" +
"Variable y\n" +
": tst 55 y ! x +! x @ y +! ;"
);
IWord x = targCtx.require("X");
IWord y = targCtx.require("Y");
dumpDict();
int xaddr = ((ITargetWord)x).getEntry().getParamAddr();
targCtx.writeCell(xaddr, 100);
int yaddr = ((ITargetWord)y).getEntry().getParamAddr();
targCtx.writeCell(yaddr, 200);
hostCtx.pushData(-10);
interpret("tst");
dumpCompiledMemory();
assertEquals(90, targCtx.readCell(xaddr));
assertEquals(145, targCtx.readCell(yaddr));
}
@Test
public void testMemOps2Ex() throws Exception {
parseString(
"Create str\n" +
"3 c, 65 c, 172 c, 90 c,\n" +
": [] ( addr idx -- val addr ) over + c@ swap ; \n"+
": tst str 0 [] 1 [] 2 [] 3 [] drop ;"
);
dumpDict();
interpret("tst");
assertEquals(90, hostCtx.popData());
assertEquals(172, hostCtx.popData());
assertEquals(65, hostCtx.popData());
assertEquals(3, hostCtx.popData());
}
@Test
public void testMemOps3Ex() throws Exception {
parseString(
"DVariable counter\n" +
": tst 123. counter D! 1000. counter D+! counter d@ ;"
);
dumpDict();
interpret("tst");
assertEquals(0, hostCtx.popData());
assertEquals(1123, hostCtx.popData());
}
@Test
public void testMemOps4Ex() throws Exception {
parseString(
// low high
"Create counter $1234 , $5678 , \n" +
": tst counter D@ ;"
);
dumpDict();
interpret("tst");
assertEquals(0x5678, hostCtx.popData());
assertEquals(0x1234, hostCtx.popData());
}
@Test
public void testBeginAgain() throws Exception {
parseString(
"variable idx\n"+
": loopit\n"+
"begin \n" +
" 1 idx +! "+
" idx @ 23 = if exit then\n"+
"again ;");
dumpDict();
interpret("loopit");
IWord idx = targCtx.require("Idx");
int idxAddr = ((ITargetWord)idx).getEntry().getParamAddr();
assertEquals((short)23, targCtx.readCell(idxAddr));
}
@Test
public void testBeginUntil() throws Exception {
parseString(
"variable idx\n"+
": loopit\n"+
"begin \n" +
" 1 idx +! "+
" idx @ 23 = \n"+
"until ;");
dumpDict();
interpret("loopit");
IWord idx = targCtx.require("Idx");
int idxAddr = ((ITargetWord)idx).getEntry().getParamAddr();
assertEquals((short)23, targCtx.readCell(idxAddr));
}
@Test
public void testBeginWhileRepeat() throws Exception {
parseString(
"create TextModeRegs\n" +
" $8000 , $81B0 , $8200 , $8400 , 0 , \n"+
"create Copy 50 allot\n"+
"variable copyidx\n"+
": >copy Copy copyidx @ + ! 2 copyidx +! ;\n"+
": readList\n"+
" TextModeRegs\n"+
"begin \n" +
" dup @ dup\n" +
" while\n" +
" >copy \n" +
" 2+\n" +
" repeat \n" +
" drop ;");
dumpDict();
interpret("readList");
IWord copy = targCtx.require("Copy");
IWord copyIdx = targCtx.require("CopyIdx");
int copyIdxAddr = ((ITargetWord)copyIdx).getEntry().getParamAddr();
assertEquals((short)8, targCtx.readCell(copyIdxAddr));
int copyAddr = ((ITargetWord)copy).getEntry().getParamAddr();
assertEquals((short)0x8400, targCtx.readCell(copyAddr + 6));
assertEquals((short)0x8200, targCtx.readCell(copyAddr + 4));
assertEquals((short)0x81b0, targCtx.readCell(copyAddr + 2));
assertEquals((short)0x8000, targCtx.readCell(copyAddr));
}
@Test
public void testConstants() throws Exception {
parseString(
"12 constant Speed\n" +
"50 constant Distance\n"+
": foo Speed Distance * ;\n");
dumpDict();
interpret("foo");
assertEquals(50*12, hostCtx.popData());
}
@Test
public void testStacks() throws Exception {
parseString(
": foo rot ;\n");
dumpDict();
hostCtx.pushData(1); hostCtx.pushData(2); hostCtx.pushData(3);
interpret("foo");
assertEquals(1, hostCtx.popData()); assertEquals(3, hostCtx.popData()); assertEquals(2, hostCtx.popData());
}
@Test
public void testForwards() throws Exception {
parseString(
": vfill 1 2 3 ; \n"+
": foo cls cls cls ;\n" +
": cls vfill drop drop drop ;\n");
dumpDict();
TargetColonWord foo = (TargetColonWord) targCtx.require("foo");
int dp = foo.getEntry().getContentAddr();
int word;
word = targCtx.readAddr(dp);
assertCall("cls", word);
word = targCtx.readAddr(dp + 2);
assertCall("cls", word);
word = targCtx.readAddr(dp + 4);
assertCall("cls", word);
assertOpcodes(dp + 6, Iexit);
}
@Test
public void testRedef() throws Exception {
parseString(
": vfill ; \n"+
": foo cls ;\n" +
": cls vfill ;\n");
ITargetWord origCls = targCtx.require("cls");
ITargetWord origVfill = targCtx.require("vfill");
parseString(
": vfill ; \n"+
": foo2 vfill ;\n"+
": cls drop ;\n"+
": lala cls ;\n"+
"");
dumpDict();
TargetColonWord foo = (TargetColonWord) targCtx.require("foo");
int dp = foo.getEntry().getContentAddr();
int word;
word = targCtx.readAddr(dp);
assertCall(origCls, word);
dp = origCls.getEntry().getContentAddr();
word = targCtx.readAddr(dp);
assertCall(origVfill, word);
dp = (targCtx.require("foo2")).getEntry().getContentAddr();
word = targCtx.readAddr(dp );
assertCall("vfill", word);
dp = (targCtx.require("lala")).getEntry().getContentAddr();
word = targCtx.readAddr(dp);
assertCall("cls", word);
}
@Test
public void testWriteProgram() throws Exception {
parseString(
": num [ 123 (literal) ] ;\n" + // forces 16-bit
": foo num 456 ['] num 1+ ! num ;\n");
dumpDict();
interpret("foo");
assertEquals(456, hostCtx.popData());
assertEquals(123, hostCtx.popData());
}
@Test
public void testWriteProgram2() throws Exception {
parseString(
": num [ 123. (DLITERAL) ] ;\n" +
": foo num 456 ['] num 2+ 2+ ! num ;\n");
dumpDict();
interpret("foo");
assertEquals(456, hostCtx.popData());
assertEquals(123, hostCtx.popData());
assertEquals(0, hostCtx.popData());
assertEquals(123, hostCtx.popData());
}
@Test
public void testUserVars() throws Exception {
parseString(
"User a\n"+
"User b\n"+
": foo 10 a ! 5 b ! a @ b @ ;"
);
dumpDict();
interpret("foo");
assertEquals(5, hostCtx.popData());
assertEquals(10, hostCtx.popData());
}
@Test
public void testLocals1() throws Exception {
parseString(
":: rev4 ( a b c d -- d c b a x )\n"+
" d c b a " +
" a b c d + + + " +
";"
);
hostCtx.pushData(1);
hostCtx.pushData(2);
hostCtx.pushData(3);
hostCtx.pushData(4);
dumpDict();
interpret("rev4");
assertEquals(10, hostCtx.popData());
assertEquals(1, hostCtx.popData());
assertEquals(2, hostCtx.popData());
assertEquals(3, hostCtx.popData());
assertEquals(4, hostCtx.popData());
}
@Test
public void testLocals2() throws Exception {
parseString(
":: strcmp ( addr1 c1 addr2 c2 -- f )\n"+
"begin\n"+
" c1 0= c2 0= and not \n"+
"while\n"+
" addr1 dup 1+ to addr1 c1 1- to c1 c@\n"+
" addr2 dup 1+ to addr2 c2 1- to c2 c@\n"+
" - dup if exit else drop then\n"+
"repeat\n"+
"c1 c2 - \\ length dictates winner\n" +
";");
doStrCmpTest();
}
@Test
public void testLocals3() throws Exception {
parseString(
":: strcmp ( addr1 c1 addr2 c2 -- f )\n"+
"begin\n"+
" c1 0= c2 0= and not \n"+
"while\n"+
//" 'addr1 dup @ 1 rot +! -1 'c1 +! c@\n"+
//" 'addr2 dup @ 1 rot +! -1 'c2 +! c@\n"+
" addr1 dup 1+ to addr1 c1 -1 + to c1 c@\n"+
" addr2 dup 1+ to addr2 c2 -1 + to c2 c@\n"+
" - dup if exit else drop then\n"+
"repeat\n"+
"c1 c2 - \\ length dictates winner\n" +
";");
doStrCmpTest();
}
private void doStrCmpTest() throws AbortException {
Pair<Integer, Integer> str1;
Pair<Integer, Integer> str2;
int cycles1 = cpu.getCurrentCycleCount();
str1 = targCtx.writeLengthPrefixedString("This is first");
targCtx.setDP(targCtx.getDP()+str1.second);
str2 = targCtx.writeLengthPrefixedString("This is second");
targCtx.setDP(targCtx.getDP()+str2.second);
dumpDict();
hostCtx.pushData(str1.first + 1);
hostCtx.pushData(targCtx.readChar(str1.first));
hostCtx.pushData(str2.first + 1);
hostCtx.pushData(targCtx.readChar(str2.first));
interpret("strcmp");
int ret;
ret = hostCtx.popData();
assertEquals(ret+"", ('f' - 's'), ret);
str1 = targCtx.writeLengthPrefixedString("Yet, bigger.");
targCtx.setDP(targCtx.getDP()+str1.second);
str2 = targCtx.writeLengthPrefixedString("And smaller.");
targCtx.setDP(targCtx.getDP()+str2.second);
dumpDict();
hostCtx.pushData(str1.first + 1);
hostCtx.pushData(targCtx.readChar(str1.first));
hostCtx.pushData(str2.first + 1);
hostCtx.pushData(targCtx.readChar(str2.first));
interpret("strcmp");
ret = hostCtx.popData();
assertEquals(ret+"", ('Y' - 'A'), ret);
str1 = targCtx.writeLengthPrefixedString("Another plain old copy?");
targCtx.setDP(targCtx.getDP()+str1.second);
str2 = targCtx.writeLengthPrefixedString("Another plain old copy?");
targCtx.setDP(targCtx.getDP()+str2.second);
dumpDict();
hostCtx.pushData(str1.first + 1);
hostCtx.pushData(targCtx.readChar(str1.first));
hostCtx.pushData(str2.first + 1);
hostCtx.pushData(targCtx.readChar(str2.first));
interpret("strcmp");
ret = hostCtx.popData();
assertTrue(ret+"", ret == 0);
int cycles2 = cpu.getCurrentCycleCount();
System.out.println("cycles: " + (cycles2 - cycles1));
}
@Test
public void testLocalNesting() throws Exception {
parseString(
": trash 111 222 333 >r >r >r rdrop rdrop rdrop 444 ;\n" +
":: addsub ( a b ) a b + trash drop a b - ; \n"+
":: silly ( cnt bias )\n"+
"cnt 0 do\n"+
" i bias addsub \n" +
"loop\n"+
";");
hostCtx.pushData(3);
hostCtx.pushData(10);
interpret("silly");
// 10, -10; 11, -9; 12, -8
assertEquals(-8, hostCtx.popData());
assertEquals(12, hostCtx.popData());
assertEquals(-9, hostCtx.popData());
assertEquals(11, hostCtx.popData());
assertEquals(-10, hostCtx.popData());
assertEquals(10, hostCtx.popData());
}
@Test
public void testLocals4() throws Exception {
parseString(
":: locals ( addr1 addr2 -- )\n"+
" addr2 addr1 - :> diff \n"+
" addr1 diff - addr2 diff - - :> diff2 \n"+
" diff diff2 \n" +
";");
hostCtx.pushData(10);
hostCtx.pushData(18);
interpret("locals");
assertEquals(-8, hostCtx.popData());
assertEquals(8, hostCtx.popData());
}
@Test
public void testLocals5() throws Exception {
parseString(
": locals ( addr1 addr2 -- )\n"+
" swap 2dup - :> diff\n"+
" diff - swap diff - - :> diff2 \n"+
" diff diff2 \n" +
";");
hostCtx.pushData(10);
hostCtx.pushData(18);
interpret("locals");
assertEquals(-8, hostCtx.popData());
assertEquals(8, hostCtx.popData());
}
@Test
public void testValues() throws Exception {
parseString(
"88 Value grade\n"+
"7 to grade\n"+
": fool\n"+
" grade 90 + to grade ;\n");
interpret("fool");
ITargetWord var = targCtx.require("grade");
assertEquals(97, targCtx.readCell(var.getEntry().getParamAddr()));
}
@Test
public void testCompiledLit() throws Exception {
parseString(
"Create buffer 100 allot\n"+
": fool [ buffer 50 + LITERAL ] ;\n");
interpret("fool");
ITargetWord var = targCtx.require("buffer");
assertEquals(var.getEntry().getParamAddr() + 50, hostCtx.popData());
}
@Test
public void testNoExportValuesAndVars() throws Exception {
parseString(
"0 <export\n"+
"Variable vy\n" +
"\n" +
"10 Value win-x\n" +
": fool 1 vy ! win-x ;\n");
interpret("fool");
assertEquals(10, hostCtx.popData());
}
@Test
public void testDictCompileLiteral() throws Exception {
hostCtx.pushData(123);
parseString(
stockDictDefs +
": mklit ( n -- ) dup -8 >= over 8 < and if\n" +
" $f and $20 or c, else\n" +
"dup -128 >= over 128 < and if\n" +
" $78 c, c,\n" +
"else\n" +
" $79 c, ,\n" +
"then then\n"+
"; \n"
);
int dp = targCtx.getDP();
hostCtx.pushData(10);
interpret("mklit");
hostCtx.pushData(-3);
interpret("mklit");
hostCtx.pushData(0x1234);
interpret("mklit");
dumpDict();
assertEquals(0x78, targCtx.readChar(dp++));
assertEquals(10, targCtx.readChar(dp++));
assertEquals(0x2D, targCtx.readChar(dp++));
assertEquals(0x79, targCtx.readChar(dp++));
assertEquals(0x12, targCtx.readChar(dp++));
assertEquals(0x34, targCtx.readChar(dp++));
}
@Test
public void testBracketIfEtc1() throws Exception {
hostCtx.pushData(123);
parseString(
"[if] 1 2 3\n"+
"[then]"
);
assertEquals(3, hostCtx.popData());
assertEquals(2, hostCtx.popData());
assertEquals(1, hostCtx.popData());
assertEquals(0, hostCtx.getDataStack().size());
hostCtx.pushData(123);
parseString(
"0= [if] 1 2 3\n"+
"[then]"
);
assertEquals(0, hostCtx.getDataStack().size());
hostCtx.pushData(123);
parseString(
"[if] 1 2 3 [else] 4 5 6\n"+
"[then]"
);
assertEquals(3, hostCtx.popData());
assertEquals(2, hostCtx.popData());
assertEquals(1, hostCtx.popData());
assertEquals(0, hostCtx.getDataStack().size());
hostCtx.pushData(0);
parseString(
"[if] 1 2 3 [else] 4 5 6\n"+
"[then]"
);
assertEquals(6, hostCtx.popData());
assertEquals(5, hostCtx.popData());
assertEquals(4, hostCtx.popData());
assertEquals(0, hostCtx.getDataStack().size());
}
@Test
public void testBracketIfdefEtc1() throws Exception {
hostCtx.pushData(123);
parseString(
"[ifundef] 0\n"+
": 0 [ $20 c, ] ; target-only\n"+
"[then]\n" +
"[ifundef] 0\n"+
": 0 bogus \n"+
"[then]"
);
assertEquals(123, hostCtx.popData());
dumpDict();
ITargetWord var = targCtx.require("0");
int dp = var.getEntry().getContentAddr();
assertEquals(IlitX, targCtx.readChar(dp++));
assertEquals(Iexit, targCtx.readChar(dp++));
}
@Test
public void testBracketIfEtc2() throws Exception {
hostCtx.pushData(123);
parseString(
"[if] 1 2 3 3 = [if] 10 + [then]\n"+
"[then]"
);
assertEquals(12, hostCtx.popData());
assertEquals(1, hostCtx.popData());
assertEquals(0, hostCtx.getDataStack().size());
hostCtx.pushData(123);
hostCtx.pushData(0);
parseString(
"[if] 1 2 3 3 = " +
" [if] 10 + [else] 1999 [then] " +
"[else] -23 + [then]"
);
assertEquals(100, hostCtx.popData());
assertEquals(0, hostCtx.getDataStack().size());
}
@Test
public void testBracketIfEtc3() throws Exception {
hostCtx.pushData(123);
hostCtx.pushData(1);
parseString(
"[if] 1 2 3 6 = " +
"[if] 10 + [else] 1999 [then] " +
"[else] -23 + [then]"
);
assertEquals(1999, hostCtx.popData());
assertEquals(2, hostCtx.popData());
assertEquals(1, hostCtx.popData());
assertEquals(123, hostCtx.popData());
assertEquals(0, hostCtx.getDataStack().size());
}
@Test
public void testPick() throws Exception {
parseString(
"$76 constant IcontextFrom \n"+
": pick ( n -- v )\n" +
" 1+ cells [ IcontextFrom c, CTX_SP field, ] + @ \n" +
"; target-only\n"+
"1 2 3 4 3 \n");
interpret("pick");
assertEquals(1, hostCtx.popData());
assertEquals(4, hostCtx.popData());
assertEquals(3, hostCtx.popData());
assertEquals(2, hostCtx.popData());
assertEquals(1, hostCtx.popData());
}
@Test
public void testMaxMin() throws Exception {
parseString(
": NIP ( a b -- b )\n" +
" swap drop\n" +
";\n" +
"\n" +
": MAX\n" +
" 2dup >= if drop else nip then\n" +
";\n" +
": MIN\n" +
" 2dup <= if drop else nip then\n" +
";\n");
hostCtx.pushData(100);
hostCtx.pushData(200);
interpret("max");
assertEquals(200, hostCtx.popData());
assertTrue(hostCtx.getDataStack().isEmpty());
hostCtx.pushData(200);
hostCtx.pushData(100);
interpret("max");
assertEquals(200, hostCtx.popData());
assertTrue(hostCtx.getDataStack().isEmpty());
}
}