aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn O. Pearce <sop@google.com>2011-06-15 10:08:52 -0700
committerShawn O. Pearce <sop@google.com>2011-06-15 10:08:52 -0700
commitd268150ba47810d2da574be756a4489edf48fd72 (patch)
treeb430a498b0d34e3b321f57206466f0a97f90eec0
parent5c47a23d2d0b42195c007890ea5bcd89dd9fc8e0 (diff)
downloadprolog-cafe-d268150ba47810d2da574be756a4489edf48fd72.tar.gz
Use Prolog.Feature to control reflection, IO
The Prolog.Feature settings now control what features are available to the running interpreter. Currently there are: * JAVA_REFLECTION: Use the java_* predicates. * IO: Access to the local filesystem and console.
-rw-r--r--src/builtin/PRED_close_2.java1
-rw-r--r--src/builtin/PRED_current_input_1.java1
-rw-r--r--src/builtin/PRED_current_output_1.java1
-rw-r--r--src/builtin/PRED_exists_directory_1.java1
-rw-r--r--src/builtin/PRED_exists_file_1.java1
-rw-r--r--src/builtin/PRED_file_directory_name_2.java1
-rw-r--r--src/builtin/PRED_java_constructor0_2.java3
-rw-r--r--src/builtin/PRED_java_declared_constructor0_2.java3
-rw-r--r--src/builtin/PRED_java_declared_method0_3.java3
-rw-r--r--src/builtin/PRED_java_get_declared_field0_3.java3
-rw-r--r--src/builtin/PRED_java_get_field0_3.java3
-rw-r--r--src/builtin/PRED_java_method0_3.java3
-rw-r--r--src/builtin/PRED_java_set_declared_field0_3.java3
-rw-r--r--src/builtin/PRED_java_set_field0_3.java3
-rw-r--r--src/builtin/PRED_make_directory_1.java1
-rw-r--r--src/builtin/PRED_open_4.java1
-rw-r--r--src/lang/Prolog.java104
-rw-r--r--src/lang/PrologControl.java26
18 files changed, 115 insertions, 47 deletions
diff --git a/src/builtin/PRED_close_2.java b/src/builtin/PRED_close_2.java
index 4d7237c..e028100 100644
--- a/src/builtin/PRED_close_2.java
+++ b/src/builtin/PRED_close_2.java
@@ -20,6 +20,7 @@ public class PRED_close_2 extends Predicate.P2 {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.IO, this, arg1);
engine.setB0();
Term a1, a2;
a1 = arg1;
diff --git a/src/builtin/PRED_current_input_1.java b/src/builtin/PRED_current_input_1.java
index fc1f2a2..fc4a0b9 100644
--- a/src/builtin/PRED_current_input_1.java
+++ b/src/builtin/PRED_current_input_1.java
@@ -13,6 +13,7 @@ public class PRED_current_input_1 extends Predicate.P1 {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.IO, this, arg1);
engine.setB0();
Term a1;
a1 = arg1;
diff --git a/src/builtin/PRED_current_output_1.java b/src/builtin/PRED_current_output_1.java
index 0741e4a..4638118 100644
--- a/src/builtin/PRED_current_output_1.java
+++ b/src/builtin/PRED_current_output_1.java
@@ -13,6 +13,7 @@ public class PRED_current_output_1 extends Predicate.P1 {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.IO, this, arg1);
engine.setB0();
Term a1;
a1 = arg1;
diff --git a/src/builtin/PRED_exists_directory_1.java b/src/builtin/PRED_exists_directory_1.java
index c63fff2..16ecaee 100644
--- a/src/builtin/PRED_exists_directory_1.java
+++ b/src/builtin/PRED_exists_directory_1.java
@@ -20,6 +20,7 @@ public class PRED_exists_directory_1 extends Predicate.P1 {
@Override
public Operation exec(Prolog engine) throws PrologException {
+ engine.requireFeature(Prolog.Feature.IO, this, arg1);
engine.setB0();
Term a1 = arg1.dereference();
diff --git a/src/builtin/PRED_exists_file_1.java b/src/builtin/PRED_exists_file_1.java
index 4703824..1aaebc0 100644
--- a/src/builtin/PRED_exists_file_1.java
+++ b/src/builtin/PRED_exists_file_1.java
@@ -20,6 +20,7 @@ public class PRED_exists_file_1 extends Predicate.P1 {
@Override
public Operation exec(Prolog engine) throws PrologException {
+ engine.requireFeature(Prolog.Feature.IO, this, arg1);
engine.setB0();
Term a1 = arg1.dereference();
diff --git a/src/builtin/PRED_file_directory_name_2.java b/src/builtin/PRED_file_directory_name_2.java
index 49aad15..739c223 100644
--- a/src/builtin/PRED_file_directory_name_2.java
+++ b/src/builtin/PRED_file_directory_name_2.java
@@ -22,6 +22,7 @@ public class PRED_file_directory_name_2 extends Predicate.P2 {
@Override
public Operation exec(Prolog engine) throws PrologException {
+ engine.requireFeature(Prolog.Feature.IO, this, arg1);
engine.setB0();
Term a1 = arg1.dereference();
diff --git a/src/builtin/PRED_java_constructor0_2.java b/src/builtin/PRED_java_constructor0_2.java
index c6da4c8..e76e22c 100644
--- a/src/builtin/PRED_java_constructor0_2.java
+++ b/src/builtin/PRED_java_constructor0_2.java
@@ -17,9 +17,8 @@ public class PRED_java_constructor0_2 extends JavaPredicate {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.JAVA_REFLECTION, this, arg1);
engine.setB0();
- if (!engine.control.getEnableReflection())
- throw new PermissionException(this, "reflection", "call", arg1, "disabled");
Term a1, a2;
a1 = arg1;
diff --git a/src/builtin/PRED_java_declared_constructor0_2.java b/src/builtin/PRED_java_declared_constructor0_2.java
index 7e1a596..64e8836 100644
--- a/src/builtin/PRED_java_declared_constructor0_2.java
+++ b/src/builtin/PRED_java_declared_constructor0_2.java
@@ -17,9 +17,8 @@ public class PRED_java_declared_constructor0_2 extends JavaPredicate {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.JAVA_REFLECTION, this, arg1);
engine.setB0();
- if (!engine.control.getEnableReflection())
- throw new PermissionException(this, "reflection", "call", arg1, "disabled");
Term a1, a2;
a1 = arg1;
diff --git a/src/builtin/PRED_java_declared_method0_3.java b/src/builtin/PRED_java_declared_method0_3.java
index e1fa3e6..37877df 100644
--- a/src/builtin/PRED_java_declared_method0_3.java
+++ b/src/builtin/PRED_java_declared_method0_3.java
@@ -18,9 +18,8 @@ public class PRED_java_declared_method0_3 extends JavaPredicate {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.JAVA_REFLECTION, this, arg1);
engine.setB0();
- if (!engine.control.getEnableReflection())
- throw new PermissionException(this, "reflection", "call", arg1, "disabled");
Term a1, a2, a3;
a1 = arg1;
diff --git a/src/builtin/PRED_java_get_declared_field0_3.java b/src/builtin/PRED_java_get_declared_field0_3.java
index 0a76452..0e8265f 100644
--- a/src/builtin/PRED_java_get_declared_field0_3.java
+++ b/src/builtin/PRED_java_get_declared_field0_3.java
@@ -18,9 +18,8 @@ public class PRED_java_get_declared_field0_3 extends JavaPredicate {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.JAVA_REFLECTION, this, arg1);
engine.setB0();
- if (!engine.control.getEnableReflection())
- throw new PermissionException(this, "reflection", "call", arg1, "disabled");
Term a1, a2, a3;
a1 = arg1;
diff --git a/src/builtin/PRED_java_get_field0_3.java b/src/builtin/PRED_java_get_field0_3.java
index 3c8a7b0..ff4d084 100644
--- a/src/builtin/PRED_java_get_field0_3.java
+++ b/src/builtin/PRED_java_get_field0_3.java
@@ -18,9 +18,8 @@ public class PRED_java_get_field0_3 extends JavaPredicate {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.JAVA_REFLECTION, this, arg1);
engine.setB0();
- if (!engine.control.getEnableReflection())
- throw new PermissionException(this, "reflection", "call", arg1, "disabled");
Term a1, a2, a3;
a1 = arg1;
diff --git a/src/builtin/PRED_java_method0_3.java b/src/builtin/PRED_java_method0_3.java
index b9a83c7..5fc6fad 100644
--- a/src/builtin/PRED_java_method0_3.java
+++ b/src/builtin/PRED_java_method0_3.java
@@ -18,9 +18,8 @@ public class PRED_java_method0_3 extends JavaPredicate {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.JAVA_REFLECTION, this, arg1);
engine.setB0();
- if (!engine.control.getEnableReflection())
- throw new PermissionException(this, "reflection", "call", arg1, "disabled");
Term a1, a2, a3;
a1 = arg1;
diff --git a/src/builtin/PRED_java_set_declared_field0_3.java b/src/builtin/PRED_java_set_declared_field0_3.java
index 1fcc6c0..451851e 100644
--- a/src/builtin/PRED_java_set_declared_field0_3.java
+++ b/src/builtin/PRED_java_set_declared_field0_3.java
@@ -18,9 +18,8 @@ public class PRED_java_set_declared_field0_3 extends JavaPredicate {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.JAVA_REFLECTION, this, arg1);
engine.setB0();
- if (!engine.control.getEnableReflection())
- throw new PermissionException(this, "reflection", "call", arg1, "disabled");
Term a1, a2, a3;
a1 = arg1;
diff --git a/src/builtin/PRED_java_set_field0_3.java b/src/builtin/PRED_java_set_field0_3.java
index 1aca99f..133d8ff 100644
--- a/src/builtin/PRED_java_set_field0_3.java
+++ b/src/builtin/PRED_java_set_field0_3.java
@@ -18,9 +18,8 @@ public class PRED_java_set_field0_3 extends JavaPredicate {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.JAVA_REFLECTION, this, arg1);
engine.setB0();
- if (!engine.control.getEnableReflection())
- throw new PermissionException(this, "reflection", "call", arg1, "disabled");
Term a1, a2, a3;
a1 = arg1;
diff --git a/src/builtin/PRED_make_directory_1.java b/src/builtin/PRED_make_directory_1.java
index fa9a463..fc4b678 100644
--- a/src/builtin/PRED_make_directory_1.java
+++ b/src/builtin/PRED_make_directory_1.java
@@ -21,6 +21,7 @@ public class PRED_make_directory_1 extends Predicate.P1 {
@Override
public Operation exec(Prolog engine) throws PrologException {
+ engine.requireFeature(Prolog.Feature.IO, this, arg1);
engine.setB0();
Term a1 = arg1.dereference();
diff --git a/src/builtin/PRED_open_4.java b/src/builtin/PRED_open_4.java
index 24e482c..438df3c 100644
--- a/src/builtin/PRED_open_4.java
+++ b/src/builtin/PRED_open_4.java
@@ -29,6 +29,7 @@ public class PRED_open_4 extends Predicate.P4 {
}
public Operation exec(Prolog engine) {
+ engine.requireFeature(Prolog.Feature.IO, this, arg1);
engine.setB0();
File file;
Term alias = null;
diff --git a/src/lang/Prolog.java b/src/lang/Prolog.java
index b74bfd8..1510732 100644
--- a/src/lang/Prolog.java
+++ b/src/lang/Prolog.java
@@ -1,6 +1,15 @@
package com.googlecode.prolog_cafe.lang;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.PushbackReader;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.EnumSet;
import java.util.HashMap;
-import java.io.*;
/**
* Prolog engine.
*
@@ -111,6 +120,15 @@ public final class Prolog {
static final SymbolTerm SYM_USEROUTPUT = SymbolTerm.makeSymbol("user_output");
static final SymbolTerm SYM_USERERROR = SymbolTerm.makeSymbol("user_error");
+ public static enum Feature {
+ /** Enable the {@code java_*} predicates, supporting reflection in Prolog. */
+ JAVA_REFLECTION,
+
+ /** Access to the local filesystem and console. */
+ IO;
+ }
+ protected final EnumSet<Feature> features = EnumSet.allOf(Feature.class);
+
/** Constructs new Prolog engine. */
public Prolog(PrologControl c) {
control = c;
@@ -120,7 +138,7 @@ public final class Prolog {
hashManager = new HashtableOfTerm();
}
- /**
+ /**
* Initializes some local instances only once.
* This <code>initOnce</code> method is invoked in the constructor
* and initializes the following instances:
@@ -132,30 +150,59 @@ public final class Prolog {
* <li><code>streamManager</code>
* </ul>
*/
- protected void initOnce() {
- aregs = new Term[Math.max(0, maxArity - 8)];
- if (pcl == null)
- pcl = new PrologClassLoader();
- if (internalDB == null)
- internalDB = new InternalDatabase();
-
- userInput = new PushbackReader(new BufferedReader(new InputStreamReader(System.in)), PUSHBACK_SIZE);
- userOutput = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)), true);
- userError = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err)), true);
-
- copyHash = new HashMap<VariableTerm,VariableTerm>();
- streamManager = new HashtableOfTerm();
-
- streamManager.put(SYM_USERINPUT, new JavaObjectTerm(userInput));
- streamManager.put(new JavaObjectTerm(userInput),
- makeStreamProperty(SYM_READ, SYM_INPUT, SYM_USERINPUT, SYM_TEXT));
- streamManager.put(SYM_USEROUTPUT, new JavaObjectTerm(userOutput));
- streamManager.put(new JavaObjectTerm(userOutput),
- makeStreamProperty(SYM_APPEND, SYM_OUTPUT, SYM_USEROUTPUT, SYM_TEXT));
- streamManager.put(SYM_USERERROR, new JavaObjectTerm(userError));
- streamManager.put(new JavaObjectTerm(userError),
- makeStreamProperty(SYM_APPEND, SYM_OUTPUT, SYM_USERERROR, SYM_TEXT));
+ protected void initOnce() {
+ aregs = new Term[Math.max(0, maxArity - 8)];
+ if (pcl == null) pcl = new PrologClassLoader();
+ if (internalDB == null) internalDB = new InternalDatabase();
+
+ copyHash = new HashMap<VariableTerm, VariableTerm>();
+ streamManager = new HashtableOfTerm();
+
+ if (features.contains(Feature.IO)) {
+ userInput = new PushbackReader(new BufferedReader(new InputStreamReader(System.in)), PUSHBACK_SIZE);
+ userOutput = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)), true);
+ userError = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err)), true);
+
+ streamManager.put(SYM_USERINPUT, new JavaObjectTerm(userInput));
+ streamManager.put(new JavaObjectTerm(userInput),
+ makeStreamProperty(SYM_READ, SYM_INPUT, SYM_USERINPUT, SYM_TEXT));
+
+ streamManager.put(SYM_USEROUTPUT, new JavaObjectTerm(userOutput));
+ streamManager.put(new JavaObjectTerm(userOutput),
+ makeStreamProperty(SYM_APPEND, SYM_OUTPUT, SYM_USEROUTPUT, SYM_TEXT));
+
+ streamManager.put(SYM_USERERROR, new JavaObjectTerm(userError));
+ streamManager.put(new JavaObjectTerm(userError),
+ makeStreamProperty(SYM_APPEND, SYM_OUTPUT, SYM_USERERROR, SYM_TEXT));
+ } else {
+ userInput = new PushbackReader(new Reader() {
+ @Override
+ public int read(char[] cbuf, int off, int len) throws IOException {
+ return -1;
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+ });
+
+ userOutput = new PrintWriter(new Writer() {
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ throw new IOException("Prolog.Feature.IO disabled");
+ }
+
+ @Override
+ public void flush() throws IOException {
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+ });
+ userError = userOutput;
}
+ }
/** Initializes this Prolog engine. */
public void init() {
@@ -194,6 +241,13 @@ public final class Prolog {
currentOutput = userOutput;
}
+ /** Ensure a feature is enabled, throwing if not. */
+ public void requireFeature(Prolog.Feature f, Operation goal, Term arg) {
+ if (!features.contains(f)) {
+ throw new PermissionException(goal, "use", f.toString().toLowerCase(), arg, "disabled");
+ }
+ }
+
/** Sets B0 to the top of the choice point stack.. */
public void setB0() { B0 = stack.top(); }
diff --git a/src/lang/PrologControl.java b/src/lang/PrologControl.java
index 91b1834..cb4d5b0 100644
--- a/src/lang/PrologControl.java
+++ b/src/lang/PrologControl.java
@@ -1,4 +1,7 @@
package com.googlecode.prolog_cafe.lang;
+
+import java.util.Set;
+
/**
* Tracks current evaluation goal and results.
* <p>
@@ -18,18 +21,29 @@ public abstract class PrologControl {
/** Holds a Prolog goal to be executed. */
protected Operation code;
- /** Should Java reflection be permitted. */
- private boolean enableReflection;
-
/** Constructs a new <code>PrologControl</code>. */
public PrologControl() {
engine = new Prolog(this);
code = null;
- enableReflection = true;
}
- public boolean getEnableReflection() { return enableReflection; }
- public void setEnableReflection(boolean on) { enableReflection = on; }
+ public boolean isEnabled(Prolog.Feature f) {
+ return engine.features.contains(f);
+ }
+
+ public void setEnabled(Prolog.Feature f, boolean on) {
+ if (on)
+ engine.features.add(f);
+ else
+ engine.features.remove(f);
+ }
+
+ public void setEnabled(Set<Prolog.Feature> f, boolean on) {
+ if (on)
+ engine.features.addAll(f);
+ else
+ engine.features.removeAll(f);
+ }
public int getMaxDatabaseSize() {
if (engine.internalDB != null)