Skip to content

Commit

Permalink
fix prelude reloading
Browse files Browse the repository at this point in the history
  • Loading branch information
arvyy committed Dec 2, 2023
1 parent a4ff236 commit 1da44ab
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 26 deletions.
17 changes: 17 additions & 0 deletions language/src/main/java/com/github/arvyy/islisp/ISLISPContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public static ISLISPContext get(Node node) {

private HandlerChain handlerChain;

private boolean preludeInitialized;

/**
* Create islisp context.
*
Expand Down Expand Up @@ -581,4 +583,19 @@ public Symbol getT() {
public int gensymIndex() {
return gensymIndex++;
}

/**
* @return has prelude been loaded.
*/
public boolean isPreludeInitialized() {
return preludeInitialized;
}

/**
* Inform that prelude had been loaded.
*/
public void setPreludeInitialized() {
this.preludeInitialized = true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,29 @@ public ISLISPContext createContext(Env env) {

@Override
public CallTarget parse(ParsingRequest request) throws Exception {
var ctx = ISLISPContext.get(null);
var sourceMap = new HashMap<EqWrapper, SourceSection>();
var preludeSource = Source
.newBuilder(
"islisp",
new InputStreamReader(ISLISPTruffleLanguage.class.getResourceAsStream("/islispprelude.lisp")),
"islispprelude.lisp")
.build();
var preludeContent = new Reader(preludeSource, sourceMap).readAll();
var content = new ArrayList<>();
if (ctx.isPreludeInitialized()) {
ctx.setPreludeInitialized();
var preludeSource = Source
.newBuilder(
"islisp",
new InputStreamReader(ISLISPTruffleLanguage.class.getResourceAsStream("/islispprelude.lisp")),
"islispprelude.lisp")
.build();
var preludeContent = new Reader(preludeSource, sourceMap).readAll();
content.addAll(preludeContent);
}
var userContent = new Reader(request.getSource(), sourceMap).readAll();
var content = new ArrayList<>(preludeContent.size() + userContent.size());
content.addAll(preludeContent);
content.addAll(userContent);
var parser = new Parser(sourceMap);
var rootNode = parser.parseRootNode(this, content, request.getSource().isInteractive());
return rootNode.getCallTarget();
}

@Override
protected Object getLanguageView(ISLISPContext context, Object value) {
return new ISLISPTruffleLanguageView(context, value);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,33 @@
package com.github.arvyy.islisp;

public class ISLISPTruffleLanguageView {
import com.github.arvyy.islisp.functions.ISLISPFormatObject;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;

/**
* ISLISP language view.
*/
@ExportLibrary(value = InteropLibrary.class)
public class ISLISPTruffleLanguageView implements TruffleObject {

private final ISLISPContext context;
private final Object object;

/**
* Create language view.
*
* @param context islisp context
* @param object value being viewed
*/
public ISLISPTruffleLanguageView(ISLISPContext context, Object object) {
this.context = context;
this.object = object;
}

@ExportMessage
Object toDisplayString(boolean ignored) {
return ISLISPFormatObject.format(object);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public Object execute(VirtualFrame frame) {
/**
* Construct LispFunction using this root node.
* @param lang truffle language reference
* @param isInteractive if true, do not exit on unexpected exception
* @return lisp function
*/
public static LispFunction makeLispFunction(TruffleLanguage<?> lang, boolean isInteractive) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.io.*;

/**
* Implements `format-object` function, that writes a given object to output stream.
Expand Down Expand Up @@ -61,7 +58,19 @@ void doPrint(OutputStream os, Object value, boolean escape) {
}
}

void doPrint(Writer writer, Object value, boolean escape) {
/**
* Util java procedure to give same string representation as what format-object produces.
*
* @param o value
* @return display string
*/
public static String format(Object o) {
var sw = new StringWriter();
doPrint(sw, o, false);
return sw.toString();
}

static void doPrint(Writer writer, Object value, boolean escape) {
try {
if (value instanceof LispChar c) {
if (escape) {
Expand Down Expand Up @@ -116,7 +125,7 @@ void doPrint(Writer writer, Object value, boolean escape) {
return;
}
} catch (IOException e) {
throw new ISLISPError(e.getMessage(), this);
throw new ISLISPError(e.getMessage(), null);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ void executeOutsideTruffle() {
myslots.put(slot.getName().identityReference(), newSlot);
}
var newClass = new StandardClass(
name.name(),
superclasses.toArray(LispClass[]::new),
shapeBuilder.build(),
myslots.values().toArray(StandardClass.Slot[]::new),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,15 @@ public final Object execute(VirtualFrame frame) {
}
var arguments = new Object[frame.getArguments().length - 1];
System.arraycopy(frame.getArguments(), 1, arguments, 0, arguments.length);
return executeGeneric(frame, argumentTypes, arguments);
return executeGeneric(argumentTypes, arguments);
}

abstract Object executeGeneric(VirtualFrame frame, LispClass[] classes, Object[] arguments);
abstract Object executeGeneric(LispClass[] classes, Object[] arguments);

@Specialization(
guards = "classesEqual(classes, lastClasses)",
assumptions = "genericFunctionDescriptor.getAssumption()")
Object doSpecial(
VirtualFrame frame,
Object doCached(
LispClass[] classes,
Object[] arguments,
@Cached(value = "classes", dimensions = 0) LispClass[] lastClasses,
Expand All @@ -106,6 +105,14 @@ Object doSpecial(
return dispatchNode.executeDispatch(applicableMethods, arguments);
}

@Specialization
Object doUncached(
LispClass[] classes,
Object[] arguments
) {
return dispatchNode.executeDispatch(getApplicableMethods(classes), arguments);
}

GenericMethodApplicableMethods getApplicableMethods(LispClass[] classes) {
return genericFunctionDescriptor.getApplicableMethods(classes);
}
Expand All @@ -123,4 +130,9 @@ boolean classesEqual(LispClass[] classes1, LispClass[] classes2) {
public SourceSection getSourceSection() {
return sourceSection;
}

@Override
public boolean isCloningAllowed() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,10 @@ public Object execute(VirtualFrame frame) {
public boolean isCaptureFramesForTrace() {
return true;
}

@Override
public boolean isCloningAllowed() {
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public Parser(Map<EqWrapper, SourceSection> sourceSectionMap) {
*
* @param language language reference
* @param content list of top level sexprs
* @param isInteractive whether the execution is done as part of a repl loop.
* If true, in case of unexpected error do not exit with status code
* @return root node
*/
public ISLISPRootNode parseRootNode(ISLISPTruffleLanguage language, List<Object> content, boolean isInteractive) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;

/**
* ISLISP invocable function object.
Expand All @@ -11,8 +14,20 @@
* @param callTarget function implementation
* @param isGeneric whether this is plain or generic function.
*/
@ExportLibrary(InteropLibrary.class)
public record LispFunction(Closure closure, CallTarget callTarget, boolean isGeneric) implements TruffleObject {

@ExportMessage
String toDisplayString(boolean ignored) {
if (isGeneric) {
return "#<generic function>";
}
if (closure != null) {
return "#<closure>";
}
return "#<function>";
}

/**
* Create plain lisp function.
* @param callTarget call target
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.github.arvyy.islisp.runtime;

import com.oracle.truffle.api.interop.TruffleObject;

/**
* Lisp vector.
* @param values vector content
*/
//TODO remove and use Object[] directly?
public record LispVector(Object[] values) { }
public record LispVector(Object[] values) implements TruffleObject { }
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
/**
* Represents class created through defclass.
*
* @param name class name
* @param parents parent classes
* @param shape truffle shape to create instances from
* @param slots defclass slots
* @param isAbstract abstract flag
*/
public record StandardClass(
String name,
LispClass[] parents,
StaticShape<DefaultStaticObjectFactory> shape,
Slot[] slots,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,10 @@ public static void main(String[] args) throws IOException, ParseException {
w.write("> ");
w.flush();
var line = r.readLine();
if (line == null)
if (line == null) {
break;
if (line.equals(",h")) {
//TODO
} else {
}
if (!line.equals(",h")) {
try {
var source = Source.newBuilder("islisp", line, "<repl>").interactive(true).buildLiteral();
context.eval(source);
Expand Down

0 comments on commit 1da44ab

Please sign in to comment.