package nativeLib;

import code.lang.*;
import code.instr.Instruction;
import code.instr.Replace;
import code.modules.CurryModule;
import code.space.Computation;
import code.space.Space;
import code.symbols.*;
import code.table.*;
import code.term.*;
import code.type.*;
import code.stuff.Tracer;		
import code.stuff.Logger;
import static code.type.PredefinedTypes.*;

import java.io.*;
import java.util.Vector;

/**
 * @author Sunita Marathe
 * @since 8/09/05
 */
public class IOExts_prim extends CurryModule {
    public static final String moduleName = "IOExts_prim";
    
    public IOExts_prim() {
        super(moduleName, new Vector(), null, 0, createSymbols(), false);
    }

    private static Vector createSymbols() {
        Vector v = new Vector();
	v.add(execCmdOperation);
        return v;
    }

    // ------------------------------------------------------------------

    public static final String execCmdName = "execCmd";
    private static final int execCmdID 
	= ModuleTable.getId(moduleName, execCmdName);

    private static final int ioID = 
	ModuleTable.getId(IOModule.moduleName, IOModule.ioConstructorName);
    private static final int tripleID = 
	ModuleTable.getId("prelude", "(,,)");

    // ------------------------------------------------------------------

    private static class execCmdInstruction implements Instruction {
      public void execute(Computation computation) {
	Term term = computation.getTerm();
	Term[] argument = term.getArgument();
	Term reduct;
	String cmdName = IOauxModule.convertTermToString(argument[0]);
	try {
	  Runtime runtime = Runtime.getRuntime();
	  Process p = runtime.exec(cmdName);
	  OutputStream os = p.getOutputStream();
	  InputStream is = p.getInputStream();
	  InputStream es = p.getErrorStream();

	  // construct the return value : IO ((,,) int,int,int)
	  int oh = IO_prim.FileTable.getHandle (os);
	  int ih = IO_prim.FileTable.getHandle (is);
	  int eh = IO_prim.FileTable.getHandle (es);
	  Term oTerm = new Term (oh);
	  Term iTerm = new Term (ih);
	  Term eTerm = new Term (eh);
	  Term triple = new Term (tripleID, new Term[] {oTerm, iTerm, eTerm});
	  Term[] tmp = new Term[] {triple};
	  reduct = new Term(ioID, tmp);
	} 
	catch (Exception e) {
	  reduct = SuccessModule.termFail;
	}
	Space.instance.current = reduct;
      }

        public String printAsTxtLoadable() {
            return "external function \"execCmd\"";
        }
    }

    private final static DataSymbol execCmdOperation
	= new OperationSymbol
	(moduleName,
	 "execCmd",
	 DataSymbol.toplevel,
	 1,
	 DataSymbol.NonInfix,
	 DataSymbol.NonInfix,
	 Symbol.Public,
	 // -> ([](Char), IO ((,,)(int,int,int)))
	 new FunctionType
	 (stringType,
	  new TypeConstructorApplication (
	    ioTypeName, 
	    new TypeConstructorApplication (
		"prelude.(,,)", 
		IO_prim.FileTable.handleType, IO_prim.FileTable.handleType, IO_prim.FileTable.handleType))),
	 new Instruction[]{
	    new execCmdInstruction(),
	    Replace.singleton,
	});

    // ------------------------------------------------------------------

}

