Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #1151 #1168

Merged
merged 8 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 30 additions & 16 deletions base/src/main/java/org/aya/primitive/PrimFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
import kala.control.Option;
import kala.tuple.Tuple;
import org.aya.normalize.Normalizer;
import org.aya.syntax.compile.JitPrim;
import org.aya.syntax.concrete.stmt.decl.PrimDecl;
import org.aya.syntax.core.Closure;
import org.aya.syntax.core.def.PrimDef;
import org.aya.syntax.core.def.PrimDefLike;
import org.aya.syntax.core.term.*;
import org.aya.syntax.core.term.call.PrimCall;
import org.aya.syntax.core.term.repr.StringTerm;
Expand All @@ -33,7 +35,7 @@

public class PrimFactory {
private final @NotNull Map<@NotNull ID, @NotNull PrimSeed> seeds;
private final @NotNull EnumMap<@NotNull ID, @NotNull PrimDef> defs = new EnumMap<>(ID.class);
private final @NotNull EnumMap<@NotNull ID, @NotNull PrimDefLike> defs = new EnumMap<>(ID.class);

public PrimFactory() {
seeds = ImmutableMap.from(ImmutableSeq.of(
Expand All @@ -45,6 +47,11 @@
).map(seed -> Tuple.of(seed.name, seed)));
}

public void definePrim(PrimDefLike prim) {
assert !isForbiddenRedefinition(prim.id(), prim instanceof JitPrim);
defs.put(prim.id(), prim);
}

@FunctionalInterface
public interface Unfolder extends BiFunction<@NotNull PrimCall, @NotNull TyckState, @NotNull Term> { }

Expand Down Expand Up @@ -96,7 +103,7 @@
}

final @NotNull PrimSeed stringType =
new PrimSeed(ID.STRING, this::primCall,
new PrimSeed(ID.STRING, (prim, _) -> prim,
ref -> new PrimDef(ref, Type0, ID.STRING), ImmutableSeq.empty());

final @NotNull PrimSeed stringConcat =
Expand Down Expand Up @@ -153,41 +160,48 @@
}
*/

private @NotNull PrimCall primCall(@NotNull PrimCall prim, @NotNull TyckState tyckState) { return prim; }

public final @NotNull PrimSeed intervalType = new PrimSeed(ID.I,
((_, _) -> DimTyTerm.INSTANCE),
ref -> new PrimDef(ref, SortTerm.ISet, ID.I),
ImmutableSeq.empty());

public @NotNull PrimDef factory(@NotNull ID name, @NotNull DefVar<PrimDef, PrimDecl> ref) {
assert suppressRedefinition() || !have(name);
var rst = seeds.get(name).supply(ref);
defs.put(name, rst);
public @NotNull PrimDefLike factory(@NotNull ID name, @NotNull DefVar<PrimDef, PrimDecl> ref) {
var rst = new PrimDef.Delegate(seeds.get(name).supply(ref).ref);
definePrim(rst);
return rst;
}

public @NotNull PrimCall getCall(@NotNull ID id, @NotNull ImmutableSeq<Term> args) {
return new PrimCall(getOption(id).get().ref(), 0, args);
return new PrimCall(getOption(id).get(), 0, args);

Check warning on line 175 in base/src/main/java/org/aya/primitive/PrimFactory.java

View check run for this annotation

Codecov / codecov/patch

base/src/main/java/org/aya/primitive/PrimFactory.java#L175

Added line #L175 was not covered by tests
}

public @NotNull PrimCall getCall(@NotNull ID id) {
return getCall(id, ImmutableSeq.empty());
return new PrimCall(getOption(id).get());
}

public @NotNull Option<PrimDef> getOption(@NotNull ID name) {
public @NotNull Option<PrimDefLike> getOption(@NotNull ID name) {
return Option.ofNullable(defs.get(name));
}

public boolean have(@NotNull ID name) {
return defs.containsKey(name);
}

/** whether redefinition should be treated as error */
@ForLSP public boolean suppressRedefinition() { return false; }

public @NotNull PrimDef getOrCreate(@NotNull ID name, @NotNull DefVar<PrimDef, PrimDecl> ref) {
return getOption(name).getOrElse(() -> factory(name, ref));
/**
* Whether this definition is a redefinition that should be treated as error.
* There are two cases where a redefinition is allowed:
* <ul>
* <li>When we are working in an LSP, and users can reload a file to redefine things.</li>
* <li>When we are serializing a file, which we will deserialize immediately, and this will
* replace the existing PrimDefs with their JIT-compiled version.</li>
* </ul>
*
* @return true if redefinition is forbidden.
*/
@ForLSP public boolean isForbiddenRedefinition(@NotNull PrimDef.ID id, boolean isJit) {
if (isJit)
return have(id) && defs.get(id) instanceof JitPrim;
else return have(id);
}

public @NotNull Option<ImmutableSeq<@NotNull ID>> checkDependency(@NotNull ID name) {
Expand Down
4 changes: 4 additions & 0 deletions base/src/main/java/org/aya/resolve/ResolveInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ public void open(@NotNull ResolveInfo other, @NotNull SourcePos sourcePos, @NotN
});
}

public @NotNull Reporter reporter() {
return this.opSet.reporter;
}

@Debug.Renderer(text = "opInfo.name()")
public record RenamedOpDecl(@NotNull OpInfo opInfo) implements OpDecl { }
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@

@FunctionalInterface
public interface ModuleCallback<E extends Exception> {
void onModuleTycked(@NotNull ResolveInfo moduleResolve, @NotNull ImmutableSeq<TyckDef> defs)
void onModuleTycked(@NotNull ResolveInfo resolveInfo, @NotNull ImmutableSeq<TyckDef> defs)
throws E;
}
5 changes: 3 additions & 2 deletions base/src/main/java/org/aya/resolve/visitor/StmtBinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.aya.syntax.concrete.stmt.decl.DataDecl;
import org.aya.syntax.concrete.stmt.decl.FnDecl;
import org.aya.syntax.concrete.stmt.decl.PrimDecl;
import org.aya.syntax.ref.AnyDefVar;
import org.aya.syntax.ref.DefVar;
import org.aya.util.binop.OpDecl;
import org.aya.util.error.Panic;
Expand All @@ -37,15 +38,15 @@ public void bind(@NotNull Context ctx, @NotNull BindBlock bindBlock, OpDecl self
bind(self, ctx, OpDecl.BindPred.Tighter, tighter)));
}

private @Nullable DefVar<?, ?> bind(
private @Nullable AnyDefVar bind(
@NotNull OpDecl self, @NotNull Context ctx,
@NotNull OpDecl.BindPred pred, @NotNull QualifiedID id
) throws Context.ResolvingInterruptedException {
var var = ctx.get(id);
var opDecl = info.resolveOpDecl(var);
if (opDecl != null) {
info.opSet().bind(self, pred, opDecl, id.sourcePos());
return var instanceof DefVar<?, ?> defVar ? defVar : null;
return var instanceof AnyDefVar defVar ? defVar : null;
}

// make compiler happy 😥
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public ImmutableSeq<ResolvingStmt> resolveStmt(@NotNull ImmutableSeq<Stmt> stmts
var lack = factory.checkDependency(primID);
if (lack.isNotEmpty() && lack.get().isNotEmpty())
context.reportAndThrow(new PrimResolveError.Dependency(name, lack.get(), sourcePos));
else if (factory.have(primID) && !factory.suppressRedefinition())
else if (factory.isForbiddenRedefinition(primID, false))
context.reportAndThrow(new PrimResolveError.Redefinition(name, sourcePos));
factory.factory(primID, decl.ref);
var resolvedCtx = resolveTopLevelDecl(decl, context);
Expand Down
4 changes: 2 additions & 2 deletions base/src/main/java/org/aya/unify/TermComparator.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

import kala.collection.immutable.ImmutableSeq;
import org.aya.generic.Renamer;
import org.aya.generic.term.DTKind;
import org.aya.generic.term.SortKind;
import org.aya.prettier.AyaPrettierOptions;
import org.aya.syntax.core.term.*;
import org.aya.generic.term.DTKind;
import org.aya.syntax.core.term.call.*;
import org.aya.syntax.core.term.marker.Formation;
import org.aya.syntax.core.term.repr.IntegerTerm;
Expand Down Expand Up @@ -339,7 +339,7 @@ case ProjTerm(var lof, var ldx) -> {
// We already compare arguments in compareApprox, if we arrive here,
// it means their arguments don't match (even the ref don't match),
// so we are unable to do more if we can't normalize them.
case FnCall _ -> null;
case FnCall _, PrimCall _ -> null;

default -> throw noRules(lhs);
};
Expand Down
2 changes: 1 addition & 1 deletion base/src/test/java/org/aya/tyck/TyckTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ public static TyckResult tyck(@Language("Aya") @NotNull String code) {
var moduleLoader = SyntaxTestUtil.moduleLoader();
var callback = new ModuleCallback<RuntimeException>() {
ImmutableSeq<TyckDef> ok;
@Override public void onModuleTycked(@NotNull ResolveInfo x, @NotNull ImmutableSeq<TyckDef> defs) { ok = defs; }
@Override public void onModuleTycked(@NotNull ResolveInfo resolveInfo, @NotNull ImmutableSeq<TyckDef> defs) { ok = defs; }
};
var info = moduleLoader.tyckModule(moduleLoader.resolve(SyntaxTestUtil.parse(code)), callback);
return new TyckResult(callback.ok, info);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.aya.syntax.GenericAyaFile;
import org.aya.syntax.concrete.Expr;
import org.aya.syntax.concrete.stmt.Stmt;
import org.aya.syntax.core.def.PrimDef;
import org.aya.syntax.core.def.TyckDef;
import org.aya.syntax.core.term.Term;
import org.aya.syntax.literate.CodeOptions.NormalizeMode;
Expand Down Expand Up @@ -75,7 +76,9 @@ public ReplCompiler(
reporter = CountingReporter.delegate(delegateReporter);
this.locator = locator != null ? locator : new SourceFileLocator.Module(this.modulePaths);
this.primFactory = new PrimFactory() {
@Override public boolean suppressRedefinition() { return true; }
@Override public boolean isForbiddenRedefinition(PrimDef.@NotNull ID id, boolean isJit) {
return false;
}
};
this.shapeFactory = new ReplShapeFactory();
this.opSet = new AyaBinOpSet(reporter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,22 @@
assert program != null;
var context = new EmptyContext(reporter, sourcePath).derive(mod);
var resolveInfo = resolveModule(states.primFactory, context, program, recurseLoader);
source.resolveInfo().set(resolveInfo);
return tyckModule(resolveInfo, (moduleResolve, defs) -> {
tyckModule(resolveInfo, (moduleResolve, defs) -> {
source.notifyTycked(moduleResolve, defs);
if (reporter.noError()) saveCompiledCore(source, moduleResolve, defs);
if (reporter.noError()) saveCompiledCore(source, moduleResolve, defs, recurseLoader);
});

@Nullable var tyckedInfo = source.resolveInfo().get();
// I know we can set resolveInfo before the tyckModule, but that doesn't tell the goal of the code.
if (tyckedInfo == null) {
// this happens if [saveCompiledCore] meets an exception, use fallback ResolveInfo
tyckedInfo = resolveInfo;

Check warning on line 86 in cli-impl/src/main/java/org/aya/cli/library/LibraryModuleLoader.java

View check run for this annotation

Codecov / codecov/patch

cli-impl/src/main/java/org/aya/cli/library/LibraryModuleLoader.java#L86

Added line #L86 was not covered by tests
}

return tyckedInfo;
}

@Override
public boolean existsFileLevelModule(@NotNull ModulePath path) {
@Override public boolean existsFileLevelModule(@NotNull ModulePath path) {
return owner.findModule(path) != null;
}

Expand All @@ -94,11 +101,11 @@
}

private void saveCompiledCore(
@NotNull LibrarySource file,
@NotNull ResolveInfo resolveInfo,
@NotNull ImmutableSeq<TyckDef> defs
@NotNull LibrarySource file, @NotNull ResolveInfo resolveInfo,
@NotNull ImmutableSeq<TyckDef> defs, @NotNull ModuleLoader recurseLoader
) {
advisor.saveCompiledCore(file, resolveInfo, defs);
var info = advisor.saveCompiledCore(file, resolveInfo, defs, recurseLoader);
file.resolveInfo().set(info);
}

record United(@NotNull PrimFactory primFactory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,19 @@
@NotNull ModuleLoader recurseLoader
) throws IOException, ClassNotFoundException;

void doSaveCompiledCore(
/**
* Save the well-typed defs as compiled defs
*
* @param file the source file
* @param resolveInfo the resolve info of the module
* @param defs the well-typed definitions
*/
@NotNull ResolveInfo doSaveCompiledCore(
@NotNull LibrarySource file,
@NotNull ResolveInfo resolveInfo,
@NotNull ImmutableSeq<TyckDef> defs
) throws IOException;
@NotNull ImmutableSeq<TyckDef> defs,
@NotNull ModuleLoader recurseLoader
) throws IOException, ClassNotFoundException;

@ApiStatus.NonExtendable
default @Nullable ResolveInfo loadCompiledCore(
Expand All @@ -91,17 +99,25 @@
}
}

/**
* @return possibly the compiled version of the {@link ResolveInfo}
* @see #doSaveCompiledCore
*/
@ApiStatus.NonExtendable
default void saveCompiledCore(
default @NotNull ResolveInfo saveCompiledCore(
@NotNull LibrarySource file,
@NotNull ResolveInfo resolveInfo,
@NotNull ImmutableSeq<TyckDef> defs
@NotNull ImmutableSeq<TyckDef> defs,
@NotNull ModuleLoader recurseLoader
) {
assert recurseLoader instanceof CachedModuleLoader<?>;
try {
doSaveCompiledCore(file, resolveInfo, defs);
var info = doSaveCompiledCore(file, resolveInfo, defs, recurseLoader);
updateLastModified(file);
} catch (IOException e) {
return info;
} catch (IOException | ClassNotFoundException e) {

Check warning on line 118 in cli-impl/src/main/java/org/aya/cli/library/incremental/CompilerAdvisor.java

View check run for this annotation

Codecov / codecov/patch

cli-impl/src/main/java/org/aya/cli/library/incremental/CompilerAdvisor.java#L118

Added line #L118 was not covered by tests
e.printStackTrace();
return resolveInfo;

Check warning on line 120 in cli-impl/src/main/java/org/aya/cli/library/incremental/CompilerAdvisor.java

View check run for this annotation

Codecov / codecov/patch

cli-impl/src/main/java/org/aya/cli/library/incremental/CompilerAdvisor.java#L120

Added line #L120 was not covered by tests
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ public void notifyIncrementalJob(@NotNull ImmutableSeq<LibrarySource> modified,
return delegate.doLoadCompiledCore(reporter, owner, mod, sourcePath, corePath, recurseLoader);
}

@Override public void
doSaveCompiledCore(@NotNull LibrarySource file, @NotNull ResolveInfo resolveInfo, @NotNull ImmutableSeq<TyckDef> defs) throws IOException {
delegate.doSaveCompiledCore(file, resolveInfo, defs);
@Override public @NotNull ResolveInfo
doSaveCompiledCore(@NotNull LibrarySource file, @NotNull ResolveInfo resolveInfo, @NotNull ImmutableSeq<TyckDef> defs, @NotNull ModuleLoader recurseLoader) throws IOException, ClassNotFoundException {
return delegate.doSaveCompiledCore(file, resolveInfo, defs, recurseLoader);
}
@Override public void close() throws Exception {
delegate.close();
Expand Down
Loading
Loading