Skip to content

Commit

Permalink
[java-truffle] step A!
Browse files Browse the repository at this point in the history
  • Loading branch information
mmcgill authored and kanaka committed May 31, 2021
1 parent 26d9e6e commit d2069e9
Show file tree
Hide file tree
Showing 7 changed files with 1,092 additions and 10 deletions.
215 changes: 209 additions & 6 deletions impls/java-truffle/src/main/java/truffle/mal/Core.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package truffle.mal;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -85,6 +87,17 @@ class Core {
NS.put("contains?", ContainsBuiltinFactory.getInstance());
NS.put("keys", KeysBuiltinFactory.getInstance());
NS.put("vals", ValsBuiltinFactory.getInstance());

NS.put("readline", ReadlineBuiltinFactory.getInstance());
NS.put("meta", MetaBuiltinFactory.getInstance());
NS.put("with-meta", WithMetaBuiltinFactory.getInstance());
NS.put("time-ms", TimeMsBuiltinFactory.getInstance());
NS.put("conj", ConjBuiltinFactory.getInstance());
NS.put("string?", IsStringBuiltinFactory.getInstance());
NS.put("number?", IsNumberBuiltinFactory.getInstance());
NS.put("fn?", IsFnBuiltinFactory.getInstance());
NS.put("macro?", IsMacroBuiltinFactory.getInstance());
NS.put("seq", SeqBuiltinFactory.getInstance());
}

static MalEnv newGlobalEnv(Class<? extends TruffleLanguage<?>> languageClass, TruffleLanguage<?> language) {
Expand All @@ -101,11 +114,13 @@ static MalEnv newGlobalEnv(Class<? extends TruffleLanguage<?>> languageClass, Tr
abstract class AbstractInvokeNode extends Node {
abstract Object invoke(CallTarget target, Object[] args);
}
/** A hack to make the EvalBuiltin sharable across languages.
/** A hack to make certain nodes sharable across languages.
*/
interface IMalLanguage {
CallTarget evalForm(Object form);
AbstractInvokeNode invokeNode();
PrintStream out();
BufferedReader in();
}

abstract class BuiltinNode extends Node {
Expand Down Expand Up @@ -285,10 +300,7 @@ protected Object prn(Object[] args) {
buf.append(' ');
Printer.prStr(buf, args[i], true);
}
// The correct thing is to use the output stream associated with our language context.
// However, since each step is effectively its own language, and we wish
// to share this node among them, we'll just cheat and call System.out directly.
System.out.println(buf.toString());
language.out().println(buf.toString());
return MalNil.NIL;
}
}
Expand Down Expand Up @@ -351,7 +363,7 @@ protected MalNil println(Object... args) {
// The correct thing is to use the output stream associated with our language context.
// However, since each step is effectively its own language, and we wish
// to share this node among them, we'll just cheat and call System.out directly.
System.out.println(buf.toString());
language.out().println(buf.toString());
return MalNil.NIL;
}
}
Expand Down Expand Up @@ -755,6 +767,67 @@ public MalVector vector(Object[] args) {
}
}

@NodeChild(value="col", type=ReadArgNode.class)
@NodeChild(value="elems", type=ReadArgsNode.class)
@GenerateNodeFactory
abstract class ConjBuiltin extends BuiltinNode {

protected ConjBuiltin() { super("conj"); }

@Specialization
protected MalList conj(MalList list, Object[] elems) {
for (int i=0; i < elems.length; i++) {
list = list.cons(elems[i]);
}
return list;
}

@Specialization
protected MalVector conj(MalVector vec, Object[] elems) {
for (int i=0; i < elems.length; i++) {
vec = vec.append(elems[i]);
}
return vec;
}
}

@NodeChild(value="arg", type=ReadArgNode.class)
@GenerateNodeFactory
abstract class SeqBuiltin extends BuiltinNode {

protected SeqBuiltin() { super("seq"); }

@Specialization
protected Object seq(MalList list) {
if (list.length == 0) {
return MalNil.NIL;
}
return list;
}
@Specialization
protected Object seq(MalVector vec) {
if (vec.size() == 0) {
return MalNil.NIL;
}
return vec.toList();
}
@Specialization
protected Object seq(String str) {
if (str.isEmpty()) {
return MalNil.NIL;
}
MalList l = MalList.EMPTY;
for (int i=str.length()-1; i >= 0; i--) {
l = l.cons(str.substring(i, i+1));
}
return l;
}
@Specialization
protected MalNil seq(MalNil nil) {
return nil;
}
}

/************* Maps ********************/

@NodeChild(value="args", type=ReadArgsNode.class)
Expand Down Expand Up @@ -1238,6 +1311,74 @@ protected boolean isMap(Object obj) {
}
}

@NodeChild(value="arg", type=ReadArgNode.class)
@GenerateNodeFactory
abstract class IsStringBuiltin extends BuiltinNode {

protected IsStringBuiltin() { super("string?"); }

@Specialization
protected boolean isString(String val) {
return true;
}

@Fallback
protected boolean isString(Object obj) {
return false;
}
}

@NodeChild(value="arg", type=ReadArgNode.class)
@GenerateNodeFactory
abstract class IsNumberBuiltin extends BuiltinNode {

protected IsNumberBuiltin() { super("number?"); }

@Specialization
protected boolean isNumber(long n) {
return true;
}

@Fallback
protected boolean isNumber(Object obj) {
return false;
}
}

@NodeChild(value="arg", type=ReadArgNode.class)
@GenerateNodeFactory
abstract class IsFnBuiltin extends BuiltinNode {

protected IsFnBuiltin() { super("fn?"); }

@Specialization
protected boolean isFn(MalFunction fn) {
return !fn.isMacro;
}

@Fallback
protected boolean isFn(Object obj) {
return false;
}
}

@NodeChild(value="arg", type=ReadArgNode.class)
@GenerateNodeFactory
abstract class IsMacroBuiltin extends BuiltinNode {

protected IsMacroBuiltin() { super("macro?"); }

@Specialization
protected boolean isMacro(MalFunction fn) {
return fn.isMacro;
}

@Fallback
protected boolean isMacro(Object obj) {
return false;
}
}

/*************** Other ********************/

@NodeChild(value="ast", type=ReadArgNode.class)
Expand Down Expand Up @@ -1301,4 +1442,66 @@ protected MalKeyword keyword(String arg) {
protected MalKeyword keyword(MalKeyword kw) {
return kw;
}
}

@NodeChild(value="prompt", type=ReadArgNode.class)
@GenerateNodeFactory
abstract class ReadlineBuiltin extends BuiltinNode {

protected ReadlineBuiltin() { super("readline"); }

@Specialization
@TruffleBoundary
protected Object readline(String prompt) {
language.out().print(prompt);
language.out().flush();
try {
String s = language.in().readLine();
return s == null ? MalNil.NIL : s;
} catch (IOException ex) {
throw new MalException(ex.getMessage());
}
}
}

@NodeChild(value="arg", type=ReadArgNode.class)
@GenerateNodeFactory
abstract class MetaBuiltin extends BuiltinNode {

protected MetaBuiltin() { super("meta"); }

@Specialization
protected <T> Object meta(MetaHolder<T> arg) {
return arg.getMeta();
}

@Fallback
protected Object meta(Object obj) {
return MalNil.NIL;
}
}

@NodeChild(value="arg", type=ReadArgNode.class)
@NodeChild(value="meta", type=ReadArgNode.class)
@GenerateNodeFactory
abstract class WithMetaBuiltin extends BuiltinNode {

protected WithMetaBuiltin() { super("with-meta"); }

@Specialization
protected <T> Object withMeta(MetaHolder<T> holder, Object meta) {
return holder.withMeta(meta);
}
}

@GenerateNodeFactory
abstract class TimeMsBuiltin extends BuiltinNode {

protected TimeMsBuiltin() { super("time-ms"); }

@TruffleBoundary
@Specialization
protected long timeMs() {
return System.nanoTime() / 1000000;
}
}
Loading

0 comments on commit d2069e9

Please sign in to comment.