Skip to content

Commit

Permalink
jit: use an A-Normal Form ish thingie in code serializer
Browse files Browse the repository at this point in the history
Co-authored-by: Hoshino Tented <hoshinotented@qq.com>
  • Loading branch information
ice1000 and HoshinoTented committed Dec 14, 2024
1 parent f6e74b1 commit e42d413
Show file tree
Hide file tree
Showing 15 changed files with 351 additions and 265 deletions.
18 changes: 9 additions & 9 deletions base/src/main/java/org/aya/normalize/Normalizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import kala.collection.immutable.ImmutableSeq;
import kala.collection.immutable.ImmutableSet;
import kala.control.Either;
import kala.control.Option;
import kala.control.Result;
import org.aya.generic.Modifier;
import org.aya.syntax.compile.JitFn;
Expand All @@ -26,6 +25,7 @@
import org.aya.tyck.tycker.Stateful;
import org.aya.util.error.WithPos;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.function.UnaryOperator;

Expand Down Expand Up @@ -88,8 +88,8 @@ case FnCall(var fn, int ulift, var args) -> {
var result = tryUnfoldClauses(clauses.view().map(WithPos::data),
args, ulift, core.is(Modifier.Overlap));
// we may get stuck
if (result.isEmpty()) return defaultValue;
term = result.get();
if (result == null) return defaultValue;
term = result;
continue;
}
}
Expand Down Expand Up @@ -158,8 +158,8 @@ case ConCall(var head, _) when !head.ref().hasEq() -> {
}
case MatchTerm(var discr, _, var clauses) -> {
var result = tryUnfoldClauses(clauses.view(), discr, 0, false);
if (result.isEmpty()) return defaultValue;
term = result.get();
if (result == null) return defaultValue;
term = result;
continue;
}
default -> {
Expand All @@ -173,22 +173,22 @@ private boolean isOpaque(@NotNull FnDef fn) {
return opaque.contains(fn.ref()) || fn.is(Modifier.Opaque) || fn.is(Modifier.Partial);
}

public @NotNull Option<Term> tryUnfoldClauses(
public @Nullable Term tryUnfoldClauses(
@NotNull SeqView<Term.Matching> clauses, @NotNull ImmutableSeq<Term> args,
int ulift, boolean orderIndependent
) {
for (var matchy : clauses) {
var matcher = new PatMatcher(false, this);
switch (matcher.apply(matchy.patterns(), args)) {
case Result.Err(var st) -> {
if (!orderIndependent && st == Stuck) return Option.none();
if (!orderIndependent && st == Stuck) return null;
}
case Result.Ok(var subst) -> {
return Option.some(matchy.body().elevate(ulift).instantiateTele(subst.view()));
return matchy.body().elevate(ulift).instantiateTele(subst.view());
}
}
}
return Option.none();
return null;
}

private class Full implements UnaryOperator<Term> {
Expand Down
115 changes: 62 additions & 53 deletions jit-compiler/src/main/java/org/aya/compiler/SourceBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,59 +13,57 @@
import static org.aya.compiler.serializers.AyaSerializer.CLASS_PANIC;
import static org.aya.compiler.serializers.ExprializeUtil.makeString;

public interface SourceBuilder {
final class Default implements SourceBuilder {
private final @NotNull StringBuilder builder;
private int indent;
private final @NotNull NameGenerator nameGenerator;

public Default() {
this(new StringBuilder(), 0, new NameGenerator());
}
public final class SourceBuilder {
public final @NotNull StringBuilder builder;
public final @NotNull NameGenerator nameGen;
private int indent;
private boolean isLineBegin;

public SourceBuilder() {
this.builder = new StringBuilder();
this.nameGen = new NameGenerator();
this.indent = 0;
this.isLineBegin = true;
}

public record JitParam(@NotNull String name, @NotNull String type) { }

public Default(@NotNull StringBuilder builder, int indent, @NotNull NameGenerator nameGenerator) {
this.builder = builder;
this.indent = indent;
this.nameGenerator = nameGenerator;
}
@Override public @NotNull StringBuilder builder() { return builder; }
@Override public int indent() { return indent; }
@Override public @NotNull NameGenerator nameGen() { return nameGenerator; }
@Override public void runInside(@NotNull Runnable runnable) {
indent++;
runnable.run();
indent--;
}
private void assertLineBegin() {
assert isLineBegin;
}

record JitParam(@NotNull String name, @NotNull String type) { }
public void runInside(@NotNull Runnable runnable) {
indent++;
runnable.run();
indent--;
}

@NotNull StringBuilder builder();
int indent();
@NotNull NameGenerator nameGen();

default void fillIndent() {
if (indent() == 0) return;
builder().append(" ".repeat(indent()));
public int indent() {
return this.indent;
}

void runInside(@NotNull Runnable runnable);
private void fillIndent() {
assertLineBegin();
if (indent() == 0) return;
builder.append(" ".repeat(indent()));
}

default @NotNull String buildLocalVar(@NotNull String type, @NotNull String name, @Nullable String initial) {
public @NotNull String buildLocalVar(@NotNull String type, @NotNull String name, @Nullable String initial) {
var update = initial == null ? "" : " = " + initial;
appendLine(type + " " + name + update + ";");
return name;
}

default void buildUpdate(@NotNull String lhs, @NotNull String rhs) {
public void buildUpdate(@NotNull String lhs, @NotNull String rhs) {
appendLine(lhs + " = " + rhs + ";");
}

default void buildIf(@NotNull String condition, @NotNull Runnable onSucc) {
public void buildIf(@NotNull String condition, @NotNull Runnable onSucc) {
buildIfElse(condition, onSucc, null);
}

default void buildIfElse(@NotNull String condition, @NotNull Runnable onSucc, @Nullable Runnable onFailed) {
public void buildIfElse(@NotNull String condition, @NotNull Runnable onSucc, @Nullable Runnable onFailed) {
appendLine("if (" + condition + ") {");
runInside(onSucc);
if (onFailed == null) appendLine("}");
Expand All @@ -81,32 +79,33 @@ default void buildIfElse(@NotNull String condition, @NotNull Runnable onSucc, @N
*
* @param onSucc the argument is a local variable that has type {@param type} and identical equal to {@param term};
*/
default void buildIfInstanceElse(
public void buildIfInstanceElse(
@NotNull String term,
@NotNull String type,
@NotNull Consumer<String> onSucc,
@Nullable Runnable onFailed
) {
String name = nameGen().nextName();
String name = nameGen.nextName();
buildIfElse(term + " instanceof " + type + " " + name,
() -> onSucc.accept(name),
onFailed);
}

default void buildGoto(@NotNull Runnable continuation) {
public void buildGoto(@NotNull Runnable continuation) {
appendLine("do {");
runInside(continuation);
appendLine("} while (false);");
}
default void buildBreak() { appendLine("break;"); }
default void buildReturn(@NotNull String retWith) { appendLine("return " + retWith + ";"); }
default void buildComment(@NotNull String comment) { appendLine("// " + comment); }
default void buildPanic(@Nullable String message) {

public void buildBreak() { appendLine("break;"); }
public void buildReturn(@NotNull String retWith) { appendLine("return " + retWith + ";"); }
public void buildComment(@NotNull String comment) { appendLine("// " + comment); }
public void buildPanic(@Nullable String message) {
message = message == null ? "" : makeString(message);
appendLine("throw new " + CLASS_PANIC + "(" + message + ");");
}

default void buildClass(
public void buildClass(
@NotNull String className,
@Nullable String superClass,
boolean isStatic,
Expand All @@ -123,13 +122,23 @@ default void buildClass(
return ImmutableSeq.fill(size, idx -> term + ".get(" + idx + ")");
}

default void appendLine(@NotNull String string) {
public void appendLine(@NotNull String string) {
fillIndent();
builder().append(string);
builder().append('\n');
builder.append(string);
appendLine();
}

public void append(@NotNull String string) {
if (isLineBegin) fillIndent();
builder.append(string);
}
default void appendLine() { builder().append('\n'); }
default void buildConstantField(

public void appendLine() {
builder.append('\n');
isLineBegin = true;
}

public void buildConstantField(
@NotNull String type,
@NotNull String name,
@Nullable String value
Expand All @@ -143,14 +152,14 @@ default void buildConstantField(
appendLine("public static final " + type + " " + name + value + ";");
}

default void buildSwitch(
public void buildSwitch(
@NotNull String term,
@NotNull ImmutableIntSeq cases,
@NotNull IntConsumer continuation,
@NotNull Runnable defaultCase
@NotNull Runnable publicCase
) {
if (cases.isEmpty()) {
defaultCase.run();
publicCase.run();
return;
}
appendLine("switch (" + term + ") {");
Expand All @@ -161,14 +170,14 @@ default void buildSwitch(
appendLine("}");
});

appendLine("default -> {");
runInside(defaultCase);
appendLine("public -> {");
runInside(publicCase);
appendLine("}");
});
appendLine("}");
}

default void buildMethod(
public void buildMethod(
@NotNull String name,
@NotNull ImmutableSeq<JitParam> params,
@NotNull String returnType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
// Use of this source code is governed by the MIT license that can be found in the LICENSE.md file.
package org.aya.compiler.free;

import org.aya.compiler.free.data.LocalVariable;
import org.jetbrains.annotations.NotNull;

public interface ArgumentProvider {
interface Lambda extends ArgumentProvider {
@NotNull FreeJavaExpr capture(int nth);
}

@NotNull FreeJavaExpr arg(int nth);
@NotNull LocalVariable arg(int nth);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ default LocalVariable makeVar(@NotNull Class<?> type, @Nullable FreeJavaExpr ini

void updateField(@NotNull FieldRef field, @NotNull FreeJavaExpr owner, @NotNull FreeJavaExpr update);

void ifNotTrue(@NotNull FreeJavaExpr notTrue, @NotNull Consumer<FreeCodeBuilder> thenBlock, @Nullable Consumer<FreeCodeBuilder> elseBlock);
void ifNotTrue(@NotNull LocalVariable notTrue, @NotNull Consumer<FreeCodeBuilder> thenBlock, @Nullable Consumer<FreeCodeBuilder> elseBlock);

void ifTrue(@NotNull FreeJavaExpr theTrue, @NotNull Consumer<FreeCodeBuilder> thenBlock, @Nullable Consumer<FreeCodeBuilder> elseBlock);
void ifTrue(@NotNull LocalVariable theTrue, @NotNull Consumer<FreeCodeBuilder> thenBlock, @Nullable Consumer<FreeCodeBuilder> elseBlock);

void ifInstanceOf(@NotNull FreeJavaExpr lhs, @NotNull ClassDesc rhs, @NotNull BiConsumer<FreeCodeBuilder, LocalVariable> thenBlock, @Nullable Consumer<FreeCodeBuilder> elseBlock);

Expand All @@ -58,7 +58,7 @@ default LocalVariable makeVar(@NotNull Class<?> type, @Nullable FreeJavaExpr ini
* Build a switch statement on int
*/
void switchCase(
@NotNull FreeJavaExpr elim,
@NotNull LocalVariable elim,
@NotNull ImmutableIntSeq cases,
@NotNull ObjIntConsumer<FreeCodeBuilder> branch,
@NotNull Consumer<FreeCodeBuilder> defaultCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import org.jetbrains.annotations.NotNull;

import java.lang.constant.ClassDesc;
import java.util.function.Function;
import java.util.function.BiConsumer;

/**
* the result only depends on the {@link FreeCodeBuilder} that this builder derived from
Expand Down Expand Up @@ -52,7 +52,7 @@ public interface FreeExprBuilder {
@NotNull FreeJavaExpr mkLambda(
@NotNull ImmutableSeq<FreeJavaExpr> captures,
@NotNull MethodRef method,
@NotNull Function<ArgumentProvider.Lambda, FreeJavaExpr> builder
@NotNull BiConsumer<ArgumentProvider.Lambda, FreeCodeBuilder> builder
);

@NotNull FreeJavaExpr iconst(int i);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,16 @@
import org.jetbrains.annotations.NotNull;

public record SourceArgumentProvider(@NotNull ImmutableSeq<String> names) implements ArgumentProvider {
@Override
public @NotNull SourceFreeJavaExpr arg(int nth) {
return new SourceFreeJavaExpr(names.get(nth));
@Override public @NotNull SourceFreeJavaExpr.BlackBox arg(int nth) {
return new SourceFreeJavaExpr.BlackBox(names.get(nth));
}

record Lambda(@NotNull ImmutableSeq<String> captures,
record Lambda(@NotNull ImmutableSeq<FreeJavaExpr> captures,
@NotNull ImmutableSeq<String> names) implements ArgumentProvider.Lambda {
@Override
public @NotNull FreeJavaExpr capture(int nth) {
return new SourceFreeJavaExpr(captures.get(nth));
}
@Override public @NotNull FreeJavaExpr capture(int nth) { return captures.get(nth); }

@Override
public @NotNull FreeJavaExpr arg(int nth) {
return new SourceFreeJavaExpr(names.get(nth));
@Override public @NotNull SourceFreeJavaExpr.BlackBox arg(int nth) {
return new SourceFreeJavaExpr.BlackBox(names.get(nth));
}
}
}
Loading

0 comments on commit e42d413

Please sign in to comment.