Skip to content

Commit

Permalink
Support system functions, conversion between Idris list and Java coll…
Browse files Browse the repository at this point in the history
…ections
  • Loading branch information
mmhelloworld committed Jan 5, 2021
1 parent 22c7005 commit 983cca3
Show file tree
Hide file tree
Showing 9 changed files with 390 additions and 45 deletions.
34 changes: 26 additions & 8 deletions libs/base/System.idr
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ support fn = "C:" ++ fn ++ ", libidris2_support"
libc : String -> String
libc fn = "C:" ++ fn ++ ", libc 6"

%foreign support "idris2_sleep"
%foreign
support "idris2_sleep"
"jvm:sleep(int void),io/github/mmhelloworld/idris2boot/runtime/IdrisSystem"
prim_sleep : Int -> PrimIO ()
%foreign support "idris2_usleep"
%foreign
support "idris2_usleep"
"jvm:usleep(int void),io/github/mmhelloworld/idris2boot/runtime/IdrisSystem"
prim_usleep : Int -> PrimIO ()

export
Expand All @@ -25,20 +29,30 @@ usleep sec = primIO (prim_usleep sec)

-- This one is going to vary for different back ends. Probably needs a
-- better convention. Will revisit...
%foreign "scheme:blodwen-args"
%foreign
"scheme:blodwen-args"
"jvm:getProgramArgs(io/github/mmhelloworld/idris2boot/runtime/IdrisList),io/github/mmhelloworld/idris2boot/runtime/Runtime"
prim__getArgs : PrimIO (List String)

export
getArgs : IO (List String)
getArgs = primIO prim__getArgs

%foreign libc "getenv"
%foreign
libc "getenv"
"jvm:getEnv(java/lang/String java/lang/String),io/github/mmhelloworld/idris2boot/runtime/IdrisSystem"
prim_getEnv : String -> PrimIO (Ptr String)
%foreign support "idris2_getEnvPair"
%foreign
support "idris2_getEnvPair"
"jvm:getEnvPair(int java/lang/String),io/github/mmhelloworld/idris2boot/runtime/IdrisSystem"
prim_getEnvPair : Int -> PrimIO (Ptr String)
%foreign libc "setenv"
%foreign
libc "setenv"
"jvm:setEnv(java/lang/String java/lang/String int int),io/github/mmhelloworld/idris2boot/runtime/IdrisSystem"
prim_setEnv : String -> String -> Int -> PrimIO Int
%foreign libc "setenv"
%foreign
libc "setenv"
"jvm:clearEnv(java/lang/String int),io/github/mmhelloworld/idris2boot/runtime/IdrisSystem"
prim_unsetEnv : String -> PrimIO Int

export
Expand Down Expand Up @@ -84,6 +98,7 @@ unsetEnv var

%foreign libc "system"
"scheme:blodwen-system"
"jvm:runCommand(java/lang/String int),io/github/mmhelloworld/idris2boot/runtime/IdrisSystem"
prim_system : String -> PrimIO Int

export
Expand All @@ -92,13 +107,16 @@ system cmd = primIO (prim_system cmd)

%foreign support "idris2_time"
"scheme:blodwen-time"
"jvm:time(int),io/github/mmhelloworld/idris2boot/runtime/IdrisSystem"
prim_time : PrimIO Int

export
time : IO Integer
time = pure $ cast !(primIO prim_time)

%foreign libc "exit"
%foreign
libc "exit"
"jvm:exit(int void),io/github/mmhelloworld/idris2boot/runtime/IdrisSystem"
prim_exit : Int -> PrimIO ()

||| Programs can either terminate successfully, or end in a caught
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
import static java.nio.charset.StandardCharsets.UTF_8;

public final class Console {
private static BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in, UTF_8));

private static boolean isStdinEof = false;
private static final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in, UTF_8));

private Console() {
}
Expand All @@ -21,7 +19,6 @@ public static void printString(String string) {

public static String getString() throws IOException {
String line = stdin.readLine();
isStdinEof = line == null;
return isStdinEof ? "" : line;
return line == null ? "" : line;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package io.github.mmhelloworld.idris2boot.runtime;

import java.util.AbstractSequentialList;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.NoSuchElementException;

import static java.util.Collections.emptyListIterator;

public abstract class IdrisList extends AbstractSequentialList<Object> implements IdrisObject {
public abstract int getConstructorId();

public static IdrisList fromIterable(Iterable<Object> iterable) {
Iterator<Object> iterator = iterable.iterator();
IdrisList list = Nil.INSTANCE;
while (iterator.hasNext()) {
list = new Cons(iterator.next(), list);
}
return reverse(list);
}

public static IdrisList reverse(IdrisList list) {
IdrisList current = list;
IdrisList result = Nil.INSTANCE;
while (current != Nil.INSTANCE) {
Cons cons = ((Cons) current);
result = new Cons(cons.head, result);
current = cons.tail;
}
return result;
}

public static class Nil extends IdrisList {
public static final Nil INSTANCE = new Nil();

private Nil() {
}

@Override
public int size() {
return 0;
}

@Override
public Object get(int index) {
throw new IndexOutOfBoundsException("Index: " + index);
}

@Override
public ListIterator<Object> listIterator(int i) {
return emptyListIterator();
}

@Override
public int getConstructorId() {
return 0;
}
}

public static class Cons extends IdrisList {
private final Object head;
private final IdrisList tail;

public Cons(Object head, IdrisList tail) {
this.head = head;
this.tail = tail;
}

@Override
public int getConstructorId() {
return 1;
}

@Override
public Object getProperty(int index) {
switch (index) {
case 0:
return head;
case 1:
return tail;
default:
throw new NoSuchElementException("No property at " + index + " for an Idris list");
}
}

@Override
public ListIterator<Object> listIterator(int index) {
int size = size();
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
return new Iterator(index, this);
}

@Override
public int size() {
return 1 + tail.size();
}

private static class Node {
private Node previous;
private final Object element;
private Node next;

private Node(Node previous, Object element, Node next) {
this.previous = previous;
this.element = element;
this.next = next;
}

private Node(Object element) {
this(null, element, null);
}
}

private static class Iterator implements ListIterator<Object> {
private int index;
private Node node;

private Iterator(int index, IdrisList idrisList) {
this.index = index;
this.node = createNode(index, idrisList);
}

private static Node createNode(int index, IdrisList idrisList) {
if (idrisList == Nil.INSTANCE) {
return null;
}
Cons cons = (Cons) idrisList;
Node currNode = new Node(cons.head);
int startIndex = -1;
Node start = new Node(null, null, currNode);
for (IdrisList currList = cons.tail; currList != Nil.INSTANCE; currList = ((Cons) currList).tail) {
Cons newCons = (Cons) currList;
Node newNode = new Node(newCons.head);
currNode.next = newNode;
newNode.previous = currNode;
if (startIndex >= 0 && startIndex < index) {
start = currNode.previous;
}
currNode = currNode.next;
startIndex++;
}
return startIndex < index ? currNode : start;
}

@Override
public boolean hasNext() {
return node != null && node.next != null;
}

@Override
public Object next() {
if (node == null || node.next == null) {
throw new NoSuchElementException();
}
Object element = node.next.element;
node = node.next;
index++;
return element;
}

@Override
public boolean hasPrevious() {
return index > 0;
}

@Override
public Object previous() {
if (node == null) {
throw new NoSuchElementException();
}
Object element = node.element;
node = node.previous;
index--;
return element;
}

@Override
public int nextIndex() {
return index;
}

@Override
public int previousIndex() {
return index - 1;
}

@Override
public void remove() {
throw new UnsupportedOperationException("immutable list");
}

@Override
public void set(Object o) {
throw new UnsupportedOperationException("immutable list");
}

@Override
public void add(Object o) {
throw new UnsupportedOperationException("immutable list");
}
}
}
}
Loading

0 comments on commit 983cca3

Please sign in to comment.