predicate words experiment

This commit is contained in:
zeroflag 2021-07-11 18:56:55 +02:00
parent 6a9b8530db
commit 7fa71a71a9
7 changed files with 85 additions and 27 deletions

View file

@ -9,8 +9,10 @@ import java.util.Set;
public class Dictionary {
private final List<Word> dict = new ArrayList<>();
private final Fcl fcl;
public Dictionary() {
public Dictionary(Fcl fcl) {
this.fcl = fcl;
}
public void add(Word word) {
@ -20,7 +22,7 @@ public class Dictionary {
public Word at(String name) {
for (int i = dict.size() - 1; i >= 0; i--) {
Word each = dict.get(i);
if (each.visible() && name.equals(each.name()))
if (each.match(name, fcl))
return each;
}
return null;

View file

@ -29,7 +29,7 @@ public class Fcl {
private static final String EXIT = "exit";
private final int SCRATCH_SIZE = 1024;
private enum Mode { COMPILE, INTERPRET }
private final Dictionary dict = new Dictionary();
private final Dictionary dict;
private final FclStack rstack = new FclStack();
private final JvmInterOp interOp;
private final FclStack stack;
@ -47,6 +47,7 @@ public class Fcl {
private final String name;
private boolean visible = true;
private boolean immediate = false;
private Word predicate;
public ColonDef(int address, String name) {
this.address = address;
@ -70,11 +71,6 @@ public class Fcl {
this.visible = isVisible;
}
@Override
public boolean visible() {
return visible;
}
@Override
public boolean immediate() {
return immediate;
@ -85,6 +81,26 @@ public class Fcl {
immediate = isImmediate;
}
@Override
public void predicate(Word word) {
this.predicate = word;
}
@Override
public boolean match(String name, Fcl fcl) {
return visible && (this.name.equals(name) || predicateMatch(name, fcl));
}
private boolean predicateMatch(String name, Fcl fcl) {
if (predicate == null) return false;
fcl.push(new Str(name));
predicate.enter();
boolean match = fcl.pop().boolValue();
if (match)
fcl.push(new Str(name));
return match;
}
@Override
public String toString() {
return "xt_" + name + " (" + address + ")";
@ -155,11 +171,6 @@ public class Fcl {
this.visible = isVisible;
}
@Override
public boolean visible() {
return visible;
}
@Override
public boolean immediate() {
return false;
@ -170,6 +181,16 @@ public class Fcl {
throw new Aborted("Cannot make immediate val");
}
@Override
public void predicate(Word word) {
throw new Aborted("var does not support predicate");
}
@Override
public boolean match(String name, Fcl fcl) {
return visible && this.name.equals(name);
}
@Override
public void enter() {
stack.push(new Num(address));
@ -249,11 +270,6 @@ public class Fcl {
this.visible = isVisible;
}
@Override
public boolean visible() {
return visible;
}
@Override
public boolean immediate() {
return false;
@ -264,6 +280,16 @@ public class Fcl {
throw new Aborted("Cannot make immediate val");
}
@Override
public void predicate(Word word) {
throw new Aborted("val does not support predicate");
}
@Override
public boolean match(String name, Fcl fcl) {
return visible && this.name.equals(name);
}
@Override
public void enter() {
stack.push(value);
@ -329,6 +355,7 @@ public class Fcl {
}
public Fcl(FclStack stack, int heapSize, Transcript transcript) {
this.dict = new Dictionary(this);
this.stack = stack;
this.heap = new Object[heapSize];
this.interOp = new JvmInterOp(stack);
@ -386,6 +413,7 @@ public class Fcl {
addPrimitive("here", () -> stack.push(new Num(dp)));
addPrimitive("dp!", () -> dp = stack.pop().intValue() );
addPrimitive("interpret", () -> mode = Mode.INTERPRET);
addPrimitive("interpret?", () -> stack.push(mode == Mode.INTERPRET ? Bool.TRUE : Bool.FALSE));
addPrimitive("trace", () -> trace = stack.pop().boolValue());
addPrimitive("lit", () -> stack.push((Obj)heap[ip++]));
addPrimitive(">r", () -> rstack.push(stack.pop()));
@ -398,6 +426,8 @@ public class Fcl {
addPrimitive("[']", () -> stack.push((Word)heap[ip++]));
addPrimitive("`", () -> { Word word = dict.at(word()); stack.push(word == null ? Nil.INSTANCE : word); });
addPrimitive("immediate", () -> dict.lastWord().immediate(true), true);
addPrimitive("lastword", () -> stack.push(dict.lastWord()));
addPrimitive("set-predicate", () -> ((Word)stack.pop()).predicate((Word)stack.pop()));
addPrimitive(".", () -> show(stack.pop()));
addPrimitive("jvm-call-static", interOp::jvmCallStatic);
addPrimitive("jvm-call-method", interOp::jvmCallMethod);
@ -657,6 +687,10 @@ public class Fcl {
return stack.pop();
}
public void push(Obj obj) {
stack.push(obj);
}
public int stackSize() {
return stack.size();
}

View file

@ -1,5 +1,7 @@
package com.vectron.fcl.types;
import com.vectron.fcl.Fcl;
import com.vectron.fcl.exceptions.Aborted;
import com.vectron.fcl.exceptions.TypeMismatched;
import static com.vectron.fcl.Fcl.STRICT;
@ -21,13 +23,18 @@ public class Primitive implements Word {
}
@Override
public boolean visible() {
return visible;
public boolean immediate() {
return immediate;
}
@Override
public boolean immediate() {
return immediate;
public void predicate(Word word) {
throw new Aborted("primitive does not support predicate");
}
@Override
public boolean match(String name, Fcl fcl) {
return visible && this.name.equals(name);
}
@Override

View file

@ -1,10 +1,13 @@
package com.vectron.fcl.types;
import com.vectron.fcl.Fcl;
public interface Word extends Obj {
void enter();
String name();
void visible(boolean isVisible);
boolean visible();
boolean immediate();
void immediate(boolean isImmediate);
void predicate(Word word);
boolean match(String name, Fcl fcl);
}

View file

@ -13,7 +13,8 @@
} each
tbl ;
: ms ( n -- ) 'java.lang.Thread/sleep/l' jvm-call-static ;
: ms ( n -- ) :java.lang.Thread/sleep/l jvm-call-static ;
: tone ( hz ms -- ) swap :com.vectron.forthcalc.support.Tone/play/di jvm-call-static ;
: torch ( n -- ) :com.vectron.forthcalc.support.Torch/toggle/O jvm-call-static ;
: torch ( n -- ) :com.vectron.forthcalc.support.Torch/toggle/O jvm-call-static ;
: match: immediate ` lastword set-predicate ;

View file

@ -81,9 +81,10 @@ var: oy
2 LINE-COLOR paint
nil => px nil => py 1 => x
ls { -> y
x @ y trans 5 draw-circle
px @ nil != if
px @ py @ trans x @ y trans draw-line
x @ y trans 3 draw-circle
\ 0 x @ y trans 20 + y >str draw-text
then
x @ px ! y py !
x inc

View file

@ -1236,6 +1236,16 @@ public class FclTest {
assertEquals(true, evalPop(": tst :my-symbol :my-symbol = ; tst").boolValue());
}
@Test
public void testPredicateWords() {
eval(": octal? ( token -- ) 0 at '&' = ;\n" +
": lit-oct ( token -- n ) immediate match: octal?\n" +
" 1 over size substr 8 swap :java.lang.Long/parseLong/si jvm-call-static\n" +
" interpret? not if ['] lit , , then ;\n");
assertEquals(177, evalPop("&261").intValue());
assertEquals(169, evalPop(": tst &261 &10 - ; tst ").intValue());
}
private String transcript() {
return transcript.content();
}