diff options
author | Shawn O. Pearce <sop@google.com> | 2011-06-15 10:08:52 -0700 |
---|---|---|
committer | Shawn O. Pearce <sop@google.com> | 2011-06-15 10:08:52 -0700 |
commit | d268150ba47810d2da574be756a4489edf48fd72 (patch) | |
tree | b430a498b0d34e3b321f57206466f0a97f90eec0 | |
parent | 5c47a23d2d0b42195c007890ea5bcd89dd9fc8e0 (diff) | |
download | prolog-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.java | 1 | ||||
-rw-r--r-- | src/builtin/PRED_current_input_1.java | 1 | ||||
-rw-r--r-- | src/builtin/PRED_current_output_1.java | 1 | ||||
-rw-r--r-- | src/builtin/PRED_exists_directory_1.java | 1 | ||||
-rw-r--r-- | src/builtin/PRED_exists_file_1.java | 1 | ||||
-rw-r--r-- | src/builtin/PRED_file_directory_name_2.java | 1 | ||||
-rw-r--r-- | src/builtin/PRED_java_constructor0_2.java | 3 | ||||
-rw-r--r-- | src/builtin/PRED_java_declared_constructor0_2.java | 3 | ||||
-rw-r--r-- | src/builtin/PRED_java_declared_method0_3.java | 3 | ||||
-rw-r--r-- | src/builtin/PRED_java_get_declared_field0_3.java | 3 | ||||
-rw-r--r-- | src/builtin/PRED_java_get_field0_3.java | 3 | ||||
-rw-r--r-- | src/builtin/PRED_java_method0_3.java | 3 | ||||
-rw-r--r-- | src/builtin/PRED_java_set_declared_field0_3.java | 3 | ||||
-rw-r--r-- | src/builtin/PRED_java_set_field0_3.java | 3 | ||||
-rw-r--r-- | src/builtin/PRED_make_directory_1.java | 1 | ||||
-rw-r--r-- | src/builtin/PRED_open_4.java | 1 | ||||
-rw-r--r-- | src/lang/Prolog.java | 104 | ||||
-rw-r--r-- | src/lang/PrologControl.java | 26 |
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) |