Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement the various nqp:: IO ops.
  • Loading branch information
jnthn committed Feb 27, 2013
1 parent a04e5a6 commit d6a55c4
Show file tree
Hide file tree
Showing 9 changed files with 353 additions and 1 deletion.
13 changes: 13 additions & 0 deletions lib/QAST/JASTCompiler.nqp
Expand Up @@ -1510,6 +1510,19 @@ QAST::OperationsJAST.map_classlib_core_op('associative_bind', $TYPE_OPS, 'bindke
QAST::OperationsJAST.map_classlib_core_op('print', $TYPE_OPS, 'print', [$RT_STR], $RT_STR);
QAST::OperationsJAST.map_classlib_core_op('say', $TYPE_OPS, 'say', [$RT_STR], $RT_STR);
QAST::OperationsJAST.map_classlib_core_op('stat', $TYPE_OPS, 'stat', [$RT_STR, $RT_INT], $RT_INT);
QAST::OperationsJAST.map_classlib_core_op('open', $TYPE_OPS, 'open', [$RT_STR, $RT_STR], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('getstdin', $TYPE_OPS, 'getstdin', [], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('getstdout', $TYPE_OPS, 'getstdout', [], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('getstderr', $TYPE_OPS, 'getstderr', [], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('setencoding', $TYPE_OPS, 'setencoding', [$RT_OBJ, $RT_STR], $RT_OBJ, :tc);
QAST::OperationsJAST.map_classlib_core_op('tellfh', $TYPE_OPS, 'tellfh', [$RT_OBJ], $RT_INT, :tc);
QAST::OperationsJAST.map_classlib_core_op('printfh', $TYPE_OPS, 'printfh', [$RT_OBJ, $RT_STR], $RT_STR, :tc);
QAST::OperationsJAST.map_classlib_core_op('sayfh', $TYPE_OPS, 'sayfh', [$RT_OBJ, $RT_STR], $RT_STR, :tc);
QAST::OperationsJAST.map_classlib_core_op('readlinefh', $TYPE_OPS, 'readlinefh', [$RT_OBJ], $RT_STR, :tc);
QAST::OperationsJAST.map_classlib_core_op('readlineintfh', $TYPE_OPS, 'readlineintfh', [$RT_OBJ, $RT_STR], $RT_STR, :tc);
QAST::OperationsJAST.map_classlib_core_op('readallfh', $TYPE_OPS, 'readallfh', [$RT_OBJ], $RT_STR, :tc);
QAST::OperationsJAST.map_classlib_core_op('eoffh', $TYPE_OPS, 'eoffh', [$RT_OBJ], $RT_INT, :tc);
QAST::OperationsJAST.map_classlib_core_op('closefh', $TYPE_OPS, 'closefh', [$RT_OBJ], $RT_OBJ, :tc);

# terms
QAST::OperationsJAST.map_classlib_core_op('time_i', $TYPE_OPS, 'time_i', [], $RT_INT);
Expand Down
5 changes: 4 additions & 1 deletion src/org/perl6/nqp/runtime/ExceptionHandling.java
Expand Up @@ -70,6 +70,9 @@ private static SixModelObject invokeHandler(ThreadContext tc, long[] handlerInfo
/* Unahndled exception. */
private static SixModelObject panic(ThreadContext tc, long category,
VMExceptionInstance exObj) {
throw new RuntimeException("Unhandled exception; category = " + category);
if (exObj.message != null)
throw new RuntimeException("Unhandled exception: " + exObj.message);
else
throw new RuntimeException("Unhandled exception; category = " + category);
}
}
6 changes: 6 additions & 0 deletions src/org/perl6/nqp/runtime/GlobalContext.java
Expand Up @@ -73,6 +73,11 @@ public class GlobalContext {
*/
public SixModelObject BOOTException;

/**
* BOOTIO type; a basic, method-less type with the IOHandle REPR.
*/
public SixModelObject BOOTIO;

/**
* Typed VMArrays.
*/
Expand Down Expand Up @@ -154,5 +159,6 @@ private void setupConfig(HLLConfig config) {
config.arrayIteratorType = BOOTIter;
config.hashIteratorType = BOOTIter;
config.exceptionType = BOOTException;
config.ioType = BOOTIO;
}
}
5 changes: 5 additions & 0 deletions src/org/perl6/nqp/runtime/HLLConfig.java
Expand Up @@ -37,4 +37,9 @@ public class HLLConfig {
* The type to construct for exceptions (should have VMException REPR).
*/
public SixModelObject exceptionType;

/**
* The type to construct for IO handles.
*/
public SixModelObject ioType;
}
265 changes: 265 additions & 0 deletions src/org/perl6/nqp/runtime/Ops.java
@@ -1,7 +1,15 @@
package org.perl6.nqp.runtime;

import java.math.BigInteger;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
Expand Down Expand Up @@ -204,6 +212,263 @@ public static long stat(String filename, long status) {
return rval;
}

public static SixModelObject open(String path, String mode, ThreadContext tc) {
SixModelObject IOType = tc.curFrame.codeRef.staticInfo.compUnit.hllConfig.ioType;
IOHandleInstance h = (IOHandleInstance)IOType.st.REPR.allocate(tc, IOType.st);
h.initialize(tc);

try {
if (mode.equals("r")) {
h.is = new FileInputStream(path);
}
else if (mode.equals("w")) {
h.os = new FileOutputStream(path);
}
else if (mode.equals("wa")) {
h.os = new FileOutputStream(path, true);
}
else {
die_s("Unhandled file open mode '" + mode + "'", tc);
}
}
catch (FileNotFoundException e) {
die_s(e.getMessage(), tc);
}

return h;
}

public static SixModelObject getstdin(ThreadContext tc) {
SixModelObject IOType = tc.curFrame.codeRef.staticInfo.compUnit.hllConfig.ioType;
IOHandleInstance h = (IOHandleInstance)IOType.st.REPR.allocate(tc, IOType.st);
h.initialize(tc);
h.is = System.in;
return h;
}

public static SixModelObject getstdout(ThreadContext tc) {
SixModelObject IOType = tc.curFrame.codeRef.staticInfo.compUnit.hllConfig.ioType;
IOHandleInstance h = (IOHandleInstance)IOType.st.REPR.allocate(tc, IOType.st);
h.initialize(tc);
h.os = System.out;
return h;
}

public static SixModelObject getstderr(ThreadContext tc) {
SixModelObject IOType = tc.curFrame.codeRef.staticInfo.compUnit.hllConfig.ioType;
IOHandleInstance h = (IOHandleInstance)IOType.st.REPR.allocate(tc, IOType.st);
h.initialize(tc);
h.os = System.err;
return h;
}

public static SixModelObject setencoding(SixModelObject obj, String encoding, ThreadContext tc) {
if (obj instanceof IOHandleInstance) {
IOHandleInstance h = (IOHandleInstance)obj;
if (h.isr != null || h.osw != null)
die_s("Too late to set file handle encoding", tc);

String charset = null;
if (encoding.equals("ascii"))
charset = "US-ASCII";
else if (encoding.equals("iso-8859-1"))
charset = "ISO-8859-1";
else if (encoding.equals("utf8"))
charset = "UTF-8";
else if (encoding.equals("utf16"))
charset = "UTF-16";
else if (encoding.equals("binary"))
charset = "ISO-8859-1"; /* Byte oriented... */
else
die_s("Unsupported encoding " + encoding, tc);

try {
if (h.is != null)
h.isr = new InputStreamReader(h.is, charset);
if (h.os != null)
h.osw = new OutputStreamWriter(h.os, charset);
}
catch (UnsupportedEncodingException e) {
die_s(e.getMessage(), tc);
}
}
else {
die_s("setencoding requires an object with the IOHandle REPR", tc);
}
return obj;
}

public static long tellfh(SixModelObject obj, String data, ThreadContext tc) {
if (obj instanceof IOHandleInstance) {
/* TODO */
return 0;
}
else {
die_s("printfh requires an object with the IOHandle REPR", tc);
return 0; /* Unreachable */
}
}

public static String printfh(SixModelObject obj, String data, ThreadContext tc) {
if (obj instanceof IOHandleInstance) {
IOHandleInstance h = (IOHandleInstance)obj;
if (h.os == null)
die_s("File handle is not opened for write", tc);
try {
if (h.osw == null)
h.osw = new OutputStreamWriter(h.os, "UTF-8");
if (h.bw == null)
h.bw = new BufferedWriter(h.osw);
h.bw.write(data);
}
catch (IOException e) {
die_s(e.getMessage(), tc);
}
}
else {
die_s("printfh requires an object with the IOHandle REPR", tc);
}
return data;
}

public static String sayfh(SixModelObject obj, String data, ThreadContext tc) {
printfh(obj, data, tc);
printfh(obj, "\n", tc);
return data;
}

public static String readlinefh(SixModelObject obj, ThreadContext tc) {
if (obj instanceof IOHandleInstance) {
IOHandleInstance h = (IOHandleInstance)obj;
if (h.is == null)
die_s("File handle is not opened for read", tc);
try {
if (h.isr == null)
h.isr = new InputStreamReader(h.is, "UTF-8");
if (h.br == null)
h.br = new BufferedReader(h.isr);
return h.br.readLine();
}
catch (IOException e) {
die_s(e.getMessage(), tc);
return null; /* Unreachable */
}
}
else {
die_s("readlinefh requires an object with the IOHandle REPR", tc);
return null; /* Unreachable */
}
}

/* We don't have proper readline support yet. */
public static String readlineintfh(SixModelObject obj, String prompt, ThreadContext tc) {
if (obj instanceof IOHandleInstance) {
IOHandleInstance h = (IOHandleInstance)obj;
if (h.is == null)
die_s("File handle is not opened for read", tc);
try {
if (h.isr == null)
h.isr = new InputStreamReader(h.is, "UTF-8");
if (h.br == null)
h.br = new BufferedReader(h.isr);
System.out.print(prompt);
return h.br.readLine();
}
catch (IOException e) {
die_s(e.getMessage(), tc);
return null; /* Unreachable */
}
}
else {
die_s("readlineintfh requires an object with the IOHandle REPR", tc);
return null; /* Unreachable */
}
}

public static String readallfh(SixModelObject obj, ThreadContext tc) {
if (obj instanceof IOHandleInstance) {
IOHandleInstance h = (IOHandleInstance)obj;
if (h.is == null)
die_s("File handle is not opened for read", tc);
try {
if (h.isr == null)
h.isr = new InputStreamReader(h.is, "UTF-8");
if (h.br == null)
h.br = new BufferedReader(h.isr);

StringBuffer data = new StringBuffer();
char[] buf = new char[4096];
int read = 0;
while((read = h.br.read(buf)) != -1)
data.append(String.valueOf(buf, 0, read));
return data.toString();
}
catch (IOException e) {
die_s(e.getMessage(), tc);
return null; /* Unreachable */
}
}
else {
die_s("readallfh requires an object with the IOHandle REPR", tc);
return null; /* Unreachable */
}
}

public static long eoffh(SixModelObject obj, ThreadContext tc) {
if (obj instanceof IOHandleInstance) {
IOHandleInstance h = (IOHandleInstance)obj;
if (h.is == null)
die_s("File handle is not opened for read", tc);
try {
if (h.isr == null)
h.isr = new InputStreamReader(h.is, "UTF-8");
if (h.br == null)
h.br = new BufferedReader(h.isr);

char[] buf = new char[1];
h.br.mark(1);
int res = h.br.read(buf);
h.br.reset();
return res == 1 ? 1 : 0;
}
catch (IOException e) {
die_s(e.getMessage(), tc);
return 0; /* Unreachable */
}
}
else {
die_s("eoffh requires an object with the IOHandle REPR", tc);
return 0; /* Unreachable */
}
}

public static SixModelObject closefh(SixModelObject obj, ThreadContext tc) {
if (obj instanceof IOHandleInstance) {
IOHandleInstance h = (IOHandleInstance)obj;
try {
if (h.br != null)
h.br.close();
else if (h.bw != null)
h.bw.close();
else if (h.isr != null)
h.isr.close();
else if (h.osw != null)
h.osw.close();
else if (h.is != null)
h.is.close();
else if (h.os != null)
h.os.close();
}
catch (IOException e) {
die_s(e.getMessage(), tc);
}
}
else {
die_s("closefh requires an object with the IOHandle REPR", tc);
}
return obj;
}

/* Lexical lookup in current scope. */
public static long getlex_i(CallFrame cf, int i) { return cf.iLex[i]; }
public static double getlex_n(CallFrame cf, int i) { return cf.nLex[i]; }
Expand Down
1 change: 1 addition & 0 deletions src/org/perl6/nqp/sixmodel/KnowHOWBootstrapper.java
Expand Up @@ -22,6 +22,7 @@ public static void bootstrap(ThreadContext tc)
tc.gc.ContextRef = bootType(tc, "ContextRef", "ContextRef");
tc.gc.CallCapture = bootType(tc, "CallCapture", "CallCapture");
tc.gc.BOOTException = bootType(tc, "BOOTException", "VMException");
tc.gc.BOOTIO = bootType(tc, "BOOTIO", "IOHandle");

tc.gc.BOOTIntArray = bootTypedArray(tc, "BOOTIntArray", tc.gc.BOOTInt);
tc.gc.BOOTNumArray = bootTypedArray(tc, "BOOTNumArray", tc.gc.BOOTNum);
Expand Down
1 change: 1 addition & 0 deletions src/org/perl6/nqp/sixmodel/REPRRegistry.java
Expand Up @@ -45,5 +45,6 @@ public static void setup() {
addREPR("CallCapture", new CallCapture());
addREPR("NFA", new NFA());
addREPR("VMException", new VMException());
addREPR("IOHandle", new IOHandle());
}
}
33 changes: 33 additions & 0 deletions src/org/perl6/nqp/sixmodel/reprs/IOHandle.java
@@ -0,0 +1,33 @@
package org.perl6.nqp.sixmodel.reprs;

import org.perl6.nqp.runtime.ThreadContext;
import org.perl6.nqp.sixmodel.REPR;
import org.perl6.nqp.sixmodel.STable;
import org.perl6.nqp.sixmodel.SerializationReader;
import org.perl6.nqp.sixmodel.SixModelObject;
import org.perl6.nqp.sixmodel.TypeObject;

public class IOHandle extends REPR {
public SixModelObject type_object_for(ThreadContext tc, SixModelObject HOW) {
STable st = new STable(this, HOW);
SixModelObject obj = new TypeObject();
obj.st = st;
st.WHAT = obj;
return st.WHAT;
}

public SixModelObject allocate(ThreadContext tc, STable st) {
IOHandleInstance obj = new IOHandleInstance();
obj.st = st;
return obj;
}

public SixModelObject deserialize_stub(ThreadContext tc, STable st) {
throw new RuntimeException("Cannot deserialize an IO handle");
}

public void deserialize_finish(ThreadContext tc, STable st,
SerializationReader reader, SixModelObject obj) {
throw new RuntimeException("Cannot deserialize an IO handle");
}
}

0 comments on commit d6a55c4

Please sign in to comment.