mirror of
https://github.com/zeroflag/fcl.git
synced 2025-01-11 20:01:10 +01:00
predicate words experiment
This commit is contained in:
parent
6a9b8530db
commit
7fa71a71a9
7 changed files with 85 additions and 27 deletions
|
@ -9,8 +9,10 @@ import java.util.Set;
|
||||||
|
|
||||||
public class Dictionary {
|
public class Dictionary {
|
||||||
private final List<Word> dict = new ArrayList<>();
|
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) {
|
public void add(Word word) {
|
||||||
|
@ -20,7 +22,7 @@ public class Dictionary {
|
||||||
public Word at(String name) {
|
public Word at(String name) {
|
||||||
for (int i = dict.size() - 1; i >= 0; i--) {
|
for (int i = dict.size() - 1; i >= 0; i--) {
|
||||||
Word each = dict.get(i);
|
Word each = dict.get(i);
|
||||||
if (each.visible() && name.equals(each.name()))
|
if (each.match(name, fcl))
|
||||||
return each;
|
return each;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class Fcl {
|
||||||
private static final String EXIT = "exit";
|
private static final String EXIT = "exit";
|
||||||
private final int SCRATCH_SIZE = 1024;
|
private final int SCRATCH_SIZE = 1024;
|
||||||
private enum Mode { COMPILE, INTERPRET }
|
private enum Mode { COMPILE, INTERPRET }
|
||||||
private final Dictionary dict = new Dictionary();
|
private final Dictionary dict;
|
||||||
private final FclStack rstack = new FclStack();
|
private final FclStack rstack = new FclStack();
|
||||||
private final JvmInterOp interOp;
|
private final JvmInterOp interOp;
|
||||||
private final FclStack stack;
|
private final FclStack stack;
|
||||||
|
@ -47,6 +47,7 @@ public class Fcl {
|
||||||
private final String name;
|
private final String name;
|
||||||
private boolean visible = true;
|
private boolean visible = true;
|
||||||
private boolean immediate = false;
|
private boolean immediate = false;
|
||||||
|
private Word predicate;
|
||||||
|
|
||||||
public ColonDef(int address, String name) {
|
public ColonDef(int address, String name) {
|
||||||
this.address = address;
|
this.address = address;
|
||||||
|
@ -70,11 +71,6 @@ public class Fcl {
|
||||||
this.visible = isVisible;
|
this.visible = isVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean visible() {
|
|
||||||
return visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean immediate() {
|
public boolean immediate() {
|
||||||
return immediate;
|
return immediate;
|
||||||
|
@ -85,6 +81,26 @@ public class Fcl {
|
||||||
immediate = isImmediate;
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "xt_" + name + " (" + address + ")";
|
return "xt_" + name + " (" + address + ")";
|
||||||
|
@ -155,11 +171,6 @@ public class Fcl {
|
||||||
this.visible = isVisible;
|
this.visible = isVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean visible() {
|
|
||||||
return visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean immediate() {
|
public boolean immediate() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -170,6 +181,16 @@ public class Fcl {
|
||||||
throw new Aborted("Cannot make immediate val");
|
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
|
@Override
|
||||||
public void enter() {
|
public void enter() {
|
||||||
stack.push(new Num(address));
|
stack.push(new Num(address));
|
||||||
|
@ -249,11 +270,6 @@ public class Fcl {
|
||||||
this.visible = isVisible;
|
this.visible = isVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean visible() {
|
|
||||||
return visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean immediate() {
|
public boolean immediate() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -264,6 +280,16 @@ public class Fcl {
|
||||||
throw new Aborted("Cannot make immediate val");
|
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
|
@Override
|
||||||
public void enter() {
|
public void enter() {
|
||||||
stack.push(value);
|
stack.push(value);
|
||||||
|
@ -329,6 +355,7 @@ public class Fcl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Fcl(FclStack stack, int heapSize, Transcript transcript) {
|
public Fcl(FclStack stack, int heapSize, Transcript transcript) {
|
||||||
|
this.dict = new Dictionary(this);
|
||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
this.heap = new Object[heapSize];
|
this.heap = new Object[heapSize];
|
||||||
this.interOp = new JvmInterOp(stack);
|
this.interOp = new JvmInterOp(stack);
|
||||||
|
@ -386,6 +413,7 @@ public class Fcl {
|
||||||
addPrimitive("here", () -> stack.push(new Num(dp)));
|
addPrimitive("here", () -> stack.push(new Num(dp)));
|
||||||
addPrimitive("dp!", () -> dp = stack.pop().intValue() );
|
addPrimitive("dp!", () -> dp = stack.pop().intValue() );
|
||||||
addPrimitive("interpret", () -> mode = Mode.INTERPRET);
|
addPrimitive("interpret", () -> mode = Mode.INTERPRET);
|
||||||
|
addPrimitive("interpret?", () -> stack.push(mode == Mode.INTERPRET ? Bool.TRUE : Bool.FALSE));
|
||||||
addPrimitive("trace", () -> trace = stack.pop().boolValue());
|
addPrimitive("trace", () -> trace = stack.pop().boolValue());
|
||||||
addPrimitive("lit", () -> stack.push((Obj)heap[ip++]));
|
addPrimitive("lit", () -> stack.push((Obj)heap[ip++]));
|
||||||
addPrimitive(">r", () -> rstack.push(stack.pop()));
|
addPrimitive(">r", () -> rstack.push(stack.pop()));
|
||||||
|
@ -398,6 +426,8 @@ public class Fcl {
|
||||||
addPrimitive("[']", () -> stack.push((Word)heap[ip++]));
|
addPrimitive("[']", () -> stack.push((Word)heap[ip++]));
|
||||||
addPrimitive("`", () -> { Word word = dict.at(word()); stack.push(word == null ? Nil.INSTANCE : word); });
|
addPrimitive("`", () -> { Word word = dict.at(word()); stack.push(word == null ? Nil.INSTANCE : word); });
|
||||||
addPrimitive("immediate", () -> dict.lastWord().immediate(true), true);
|
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(".", () -> show(stack.pop()));
|
||||||
addPrimitive("jvm-call-static", interOp::jvmCallStatic);
|
addPrimitive("jvm-call-static", interOp::jvmCallStatic);
|
||||||
addPrimitive("jvm-call-method", interOp::jvmCallMethod);
|
addPrimitive("jvm-call-method", interOp::jvmCallMethod);
|
||||||
|
@ -657,6 +687,10 @@ public class Fcl {
|
||||||
return stack.pop();
|
return stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void push(Obj obj) {
|
||||||
|
stack.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
public int stackSize() {
|
public int stackSize() {
|
||||||
return stack.size();
|
return stack.size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.vectron.fcl.types;
|
package com.vectron.fcl.types;
|
||||||
|
|
||||||
|
import com.vectron.fcl.Fcl;
|
||||||
|
import com.vectron.fcl.exceptions.Aborted;
|
||||||
import com.vectron.fcl.exceptions.TypeMismatched;
|
import com.vectron.fcl.exceptions.TypeMismatched;
|
||||||
|
|
||||||
import static com.vectron.fcl.Fcl.STRICT;
|
import static com.vectron.fcl.Fcl.STRICT;
|
||||||
|
@ -21,13 +23,18 @@ public class Primitive implements Word {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean visible() {
|
public boolean immediate() {
|
||||||
return visible;
|
return immediate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean immediate() {
|
public void predicate(Word word) {
|
||||||
return immediate;
|
throw new Aborted("primitive does not support predicate");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean match(String name, Fcl fcl) {
|
||||||
|
return visible && this.name.equals(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package com.vectron.fcl.types;
|
package com.vectron.fcl.types;
|
||||||
|
|
||||||
|
import com.vectron.fcl.Fcl;
|
||||||
|
|
||||||
public interface Word extends Obj {
|
public interface Word extends Obj {
|
||||||
void enter();
|
void enter();
|
||||||
String name();
|
String name();
|
||||||
void visible(boolean isVisible);
|
void visible(boolean isVisible);
|
||||||
boolean visible();
|
|
||||||
boolean immediate();
|
boolean immediate();
|
||||||
void immediate(boolean isImmediate);
|
void immediate(boolean isImmediate);
|
||||||
|
void predicate(Word word);
|
||||||
|
boolean match(String name, Fcl fcl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
} each
|
} each
|
||||||
tbl ;
|
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 ;
|
: 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 ;
|
|
@ -81,9 +81,10 @@ var: oy
|
||||||
2 LINE-COLOR paint
|
2 LINE-COLOR paint
|
||||||
nil => px nil => py 1 => x
|
nil => px nil => py 1 => x
|
||||||
ls { -> y
|
ls { -> y
|
||||||
x @ y trans 5 draw-circle
|
|
||||||
px @ nil != if
|
px @ nil != if
|
||||||
px @ py @ trans x @ y trans draw-line
|
px @ py @ trans x @ y trans draw-line
|
||||||
|
x @ y trans 3 draw-circle
|
||||||
|
\ 0 x @ y trans 20 + y >str draw-text
|
||||||
then
|
then
|
||||||
x @ px ! y py !
|
x @ px ! y py !
|
||||||
x inc
|
x inc
|
||||||
|
|
|
@ -1236,6 +1236,16 @@ public class FclTest {
|
||||||
assertEquals(true, evalPop(": tst :my-symbol :my-symbol = ; tst").boolValue());
|
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() {
|
private String transcript() {
|
||||||
return transcript.content();
|
return transcript.content();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue