/*
* tuProlog - Copyright (C) 2001-2002 aliCE team at deis.unibo.it
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package alice.tuprolog.lib;
import static alice.tuprolog.Agent.loadText;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Random;
import alice.tuprolog.Int;
import alice.tuprolog.Library;
import alice.tuprolog.Predicate;
import alice.tuprolog.Struct;
import alice.tuprolog.Term;
/**
* This class provides basic I/O predicates.
*
* Library/Theory Dependency: BasicLibrary
*/
public class IOLibrary extends Library {
protected String inputStreamName = "stdin";
protected InputStream inputStream = System.in;
protected String outputStreamName = "stdout";
protected OutputStream outputStream = System.out;
private Random gen = new Random();
public IOLibrary() {
gen.setSeed(System.currentTimeMillis());
}
@Predicate("see/1")
public boolean see(Term arg) throws Exception {
Struct arg0 = (Struct) arg.getTerm();
if (!arg0.isAtom())
return false;
if (inputStream != System.in)
inputStream.close();
if (arg0.getName().equals("stdin"))
inputStream = System.in;
else
inputStream = new FileInputStream(((Struct) arg0).getName());
inputStreamName = ((Struct) arg0).getName();
return true;
}
@Predicate("seen/0")
public boolean seen() throws Exception {
if (inputStream != System.in) {
inputStream.close();
inputStream = System.in;
inputStreamName = "stdin";
}
return true;
}
@Predicate("seeing/1")
public boolean seeing(Term t) {
return unify(t, new Struct(inputStreamName));
}
@Predicate("tell/1")
public boolean tell(Term arg) throws Exception {
Struct arg0 = (Struct) arg.getTerm();
if (!arg0.isAtom())
return false;
if (outputStream != System.out)
outputStream.close();
if (arg0.getName().equals("stdout"))
outputStream = System.out;
else
outputStream = new FileOutputStream(((Struct) arg0).getName());
outputStreamName = ((Struct) arg0).getName();
return true;
}
@Predicate("told/0")
public boolean told() throws Exception {
if (outputStream != System.out) {
outputStream.close();
outputStream = System.out;
outputStreamName = "stdout";
}
return true;
}
@Predicate("telling/1")
public boolean telling(Term arg0) {
return unify(arg0, new Struct(outputStreamName));
}
@Predicate("put/1")
public boolean put(Term arg) throws Exception {
Struct arg0 = (Struct) arg.getTerm();
if (!arg0.isAtom())
return false;
else {
String ch = arg0.getName();
if (ch.length() > 1)
return false;
else {
if (outputStreamName.equals("stdout"))
getEngine().stdOutput(ch);
else
outputStream.write((byte) ch.charAt(0));
return true;
}
}
}
@Predicate("get0/1")
public boolean get0(Term arg0) throws Exception {
int ch = inputStream.read();
if (ch == -1)
return unify(arg0, new Int(-1));
else
return unify(arg0, new Struct(new Character((char) ch).toString()));
}
@Predicate("get/1")
public boolean get(Term arg0) throws Exception {
int ch = 0;
do {
ch = inputStream.read();
} while (ch < 0x20 && ch >= 0);
if (ch == -1)
return unify(arg0, new Int(-1));
else
return unify(arg0, new Struct(new Character(((char) ch)).toString()));
}
@Predicate("tab/1")
public boolean tab(alice.tuprolog.Number arg) throws Exception {
int n = arg.intValue();
if (outputStreamName.equals("stdout"))
for (int i = 0; i < n; i++)
getEngine().stdOutput(" ");
else
for (int i = 0; i < n; i++)
outputStream.write(0x20);
return true;
}
@Predicate("read/1")
public boolean read(Term arg0) throws Exception {
arg0 = arg0.getTerm();
try {
int ch = 0;
boolean open_apices = false;
//boolean just_open_apices = false;
boolean open_apices2 = false;
//boolean just_open_apices2 = false;
String st = "";
do {
ch = inputStream.read();
if (ch == -1)
break;
boolean can_add = true;
if (ch=='\'') {
if (!open_apices)
open_apices = true;
else
open_apices = false;
} else if (ch=='\"') {
if (!open_apices2)
open_apices2 = true;
else
open_apices2 = false;
} else {
if (ch=='.') {
if (!open_apices && !open_apices2)
break;
}
}
if (can_add)
st += new Character(((char) ch)).toString();
} while (true);
return unify(arg0, getEngine().toTerm(st));
} catch (Exception ex) {
return false;
}
}
@Predicate("write/1")
public boolean write(Term arg0) throws Exception {
arg0 = arg0.getTerm();
try {
if (outputStreamName.equals("stdout"))
getEngine().stdOutput(arg0.toString());
else
outputStream.write(arg0.toString().getBytes());
return true;
} catch (Exception ex) {
return false;
}
}
@Predicate("print/1")
public boolean print(Term arg0) throws Exception {
arg0 = arg0.getTerm();
try {
if (outputStreamName.equals("stdout"))
getEngine().stdOutput(arg0.toStringWithoutApices());
else
outputStream.write(arg0.toStringWithoutApices().getBytes());
return true;
} catch (Exception ex){
return false;
}
}
@Predicate("nl/0")
public boolean nl() throws Exception {
if (outputStreamName.equals("stdout"))
getEngine().stdOutput("\n");
else
outputStream.write('\n');
return true;
}
/**
* reads a source text from a file.
* <p>
* It's useful used with agent predicate:
* text_from_file(File,Source), agent(Source).
*/
@Predicate("text_from_file/2")
public boolean textFromFile(Term file_name, Term text) {
Struct fileName = (Struct) file_name.getTerm();
try {
Struct goal = new Struct(loadText(
((Struct) fileName).toStringWithoutApices()));
return unify(text, goal);
} catch (Exception ex) {
//ex.printStackTrace();
return false;
}
}
// miscellaneous
@Predicate("rand_float/1")
public boolean randFloat(Term t) {
return unify(t, new alice.tuprolog.Double(gen.nextFloat()));
}
@Predicate("rand_int/2")
public boolean randInt(Term argNum, Term num) {
alice.tuprolog.Number arg = (alice.tuprolog.Number) argNum.getTerm();
return unify(num, new Int(gen.nextInt(arg.intValue())));
}
@Override
public String getTheory() {
return
"consult(File) :- text_from_file(File,Text), add_theory(Text).\n" +
"reconsult(File) :- text_from_file(File,Text), set_theory(Text).\n" +
"solve_file(File,Goal) :- text_from_file(File,Text),text_term(Text,Goal),call(Goal).\n" +
"agent_file(X) :- text_from_file(X,Y),agent(Y).\n";
}
}