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

Add elim for Simpl Indexed Type #1263

Merged
merged 5 commits into from
Dec 29, 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
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public ImmutableSeq<ResolvingStmt> resolveStmt(@NotNull ImmutableSeq<Stmt> stmts
return switch (predecl) {
case DataDecl decl -> {
var ctx = resolveTopLevelDecl(decl, context);
var innerCtx = resolveChildren(decl, ctx, d -> d.body.view(), (con, mCtx) -> {
var innerCtx = resolveChildren(decl, ctx, d -> d.body.clauses.view(), (con, mCtx) -> {
setupModule(mCtx, con.ref);
mCtx.defineSymbol(con.ref(), Stmt.Accessibility.Public, con.sourcePos());
});
Expand Down
40 changes: 26 additions & 14 deletions base/src/main/java/org/aya/resolve/visitor/StmtResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,14 @@
// Generalized works for simple bodies and signatures
var resolver = resolveDeclSignature(info, new ExprResolver(ctx, true), decl, where);
switch (decl.body) {
case FnBody.BlockBody(var cls, var elims, var rawElims) -> {
assert elims == null;
case FnBody.BlockBody body -> {
assert body.elims() == null;
// introducing generalized variable is not allowed in clauses, hence we insert them before body resolving
insertGeneralizedVars(decl, resolver);
var finalElims = rawElims.map(elim -> {
var result = resolver.resolve(new QualifiedID(elim.sourcePos(), elim.data()));
if (!(result instanceof LocalVar localVar)) {
return resolver.ctx().reportAndThrow(new NameProblem.UnqualifiedNameNotFoundError(resolver.ctx(),
elim.data(), elim.sourcePos()));
}
// result is LocalVar -> result in telescope
return localVar;
});

resolveElim(resolver, body.inner());
var clausesResolver = resolver.deriveRestrictive();
clausesResolver.reference().append(new TyckOrder.Head(decl));
decl.body = new FnBody.BlockBody(cls.map(clausesResolver::clause), finalElims, rawElims);
decl.body = body.map(clausesResolver::clause);
addReferences(info, new TyckOrder.Body(decl), clausesResolver);
}
case FnBody.ExprBody(var expr) -> {
Expand All @@ -87,6 +78,7 @@
case ResolvingStmt.TopDecl(DataDecl data, var ctx) -> {
var resolver = resolveDeclSignature(info, new ExprResolver(ctx, true), data, Where.Head);
insertGeneralizedVars(data, resolver);
resolveElim(resolver, data.body);
data.body.forEach(con -> {
var bodyResolver = resolver.deriveRestrictive();
var mCtx = MutableValue.create(resolver.ctx());
Expand All @@ -98,8 +90,9 @@
addReferences(info, new TyckOrder.Head(con), bodyResolver);
// No body no body but you!
});

addReferences(info, new TyckOrder.Body(data), resolver.reference().view()
.concat(data.body.map(TyckOrder.Body::new)));
.concat(data.body.clauses.map(TyckOrder.Body::new)));
}
case ResolvingStmt.TopDecl(ClassDecl decl, var ctx) -> {
var resolver = new ExprResolver(ctx, false);
Expand Down Expand Up @@ -172,4 +165,23 @@
private static void insertGeneralizedVars(@NotNull TeleDecl decl, @NotNull ExprResolver resolver) {
decl.telescope = decl.telescope.prependedAll(resolver.allowedGeneralizes().valuesView());
}

private static <Cls> void resolveElim(@NotNull ExprResolver resolver, @NotNull MatchBody<Cls> body) {
if (body.elims() != null) {
// TODO: panic or just return?
return;

Check warning on line 172 in base/src/main/java/org/aya/resolve/visitor/StmtResolver.java

View check run for this annotation

Codecov / codecov/patch

base/src/main/java/org/aya/resolve/visitor/StmtResolver.java#L172

Added line #L172 was not covered by tests
}

var resolved = body.rawElims.map(elim -> {
var result = resolver.resolve(new QualifiedID(elim.sourcePos(), elim.data()));
if (!(result instanceof LocalVar localVar)) {
return resolver.ctx().reportAndThrow(new NameProblem.UnqualifiedNameNotFoundError(resolver.ctx(),
elim.data(), elim.sourcePos()));
}
// result is LocalVar -> result in telescope
return localVar;
});

body.resolve(resolved);
}
}
18 changes: 12 additions & 6 deletions base/src/main/java/org/aya/tyck/StmtTycker.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,11 @@ yield switch (fnDecl.body) {
fnRef.signature = fnRef.signature.descent(zonker::zonk);
yield factory.apply(Either.left(resultTerm));
}
case FnBody.BlockBody(var clauses, var elims, _) -> {
case FnBody.BlockBody body -> {
var clauses = body.clauses();
var elims = body.elims();
assert elims != null;

var signature = fnRef.signature;
// we do not load signature here, so we need a fresh ExprTycker
var clauseTycker = new ClauseTycker.Worker(new ClauseTycker(tycker = mkTycker()),
Expand Down Expand Up @@ -137,8 +140,8 @@ yield switch (fnDecl.body) {
}
case DataDecl data -> {
assert data.ref.signature != null;
for (var kon : data.body) checkHeader(kon);
yield new DataDef(data.ref, data.body.map(kon -> kon.ref.core));
for (var kon : data.body.clauses) checkHeader(kon);
yield new DataDef(data.ref, data.body.clauses.map(kon -> kon.ref.core));
}
};
reporter.clearSuppress();
Expand Down Expand Up @@ -174,11 +177,11 @@ else fail(BadTypeError.doNotLike(tycker.state, result, signature.result(),
fnRef.signature = teleTycker.checkSignature(fn.telescope, result);

// For ExprBody, they will be zonked later
if (fn.body instanceof FnBody.BlockBody(var cls, _, _)) {
if (fn.body instanceof FnBody.BlockBody body) {
tycker.solveMetas();
var zonker = new Finalizer.Zonk<>(tycker);
fnRef.signature = fnRef.signature.pusheen(tycker::whnf).descent(zonker::zonk);
if (fnRef.signature.params().isEmpty() && cls.isEmpty())
if (fnRef.signature.params().isEmpty() && body.clauses().isEmpty())
fail(new NobodyError(decl.sourcePos(), fn.ref));
}
}
Expand Down Expand Up @@ -239,8 +242,11 @@ private void checkKitsune(@NotNull DataCon con, @NotNull ExprTycker tycker) {

var wellPats = ImmutableSeq.<Pat>empty();
if (con.patterns.isNotEmpty()) {
var resolvedElim = dataRef.concrete.body.elims();
assert resolvedElim != null;
var indicies = ClauseTycker.Worker.computeIndices(ownerBinds, resolvedElim);
// do not do coverage check
var lhsResult = new ClauseTycker(tycker = mkTycker()).checkLhs(dataSig, null,
var lhsResult = new ClauseTycker(tycker = mkTycker()).checkLhs(dataSig, indicies,
new Pattern.Clause(con.entireSourcePos(), con.patterns, Option.none()), false);
if (lhsResult.hasError()) {
return;
Expand Down
72 changes: 48 additions & 24 deletions base/src/main/java/org/aya/tyck/pat/ClauseTycker.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,29 @@ public record Worker(
cl.paramSubst, cl.asSubst, cl.clause, cl.hasError));
return parent.checkAllRhs(teleVars, lhsResult);
}

private @Nullable ImmutableIntSeq computeIndices() {
return elims.isEmpty() ? null : elims.mapToInt(ImmutableIntSeq.factory(),
teleVars::indexOf);
return computeIndices(teleVars, elims);
}

public @NotNull TyckResult checkNoClassify() {
return parent.checkAllRhs(teleVars, parent.checkAllLhs(computeIndices(), signature, clauses.view(), isFn));
}

public static @Nullable ImmutableIntSeq computeIndices(
@NotNull ImmutableSeq<LocalVar> teleVars,
@NotNull ImmutableSeq<LocalVar> elims
) {
return elims.isEmpty() ? null : elims.mapToInt(ImmutableIntSeq.factory(),
teleVars::indexOf);
}
}

@Override public @NotNull Reporter reporter() { return exprTycker.reporter; }
@Override public @NotNull TyckState state() { return exprTycker.state; }

// region tycking

public @NotNull ImmutableSeq<LhsResult> checkAllLhs(
@Nullable ImmutableIntSeq indices, @NotNull Signature signature,
@NotNull SeqView<Pattern.Clause> clauses, boolean isFn
Expand All @@ -134,20 +148,6 @@ public record Worker(
return new TyckResult(rhsResult, lhsError);
}

@Override public @NotNull Reporter reporter() { return exprTycker.reporter; }
@Override public @NotNull TyckState state() { return exprTycker.state; }
private @NotNull PatternTycker newPatternTycker(
@Nullable ImmutableIntSeq indices,
@NotNull SeqView<Param> telescope
) {
telescope = indices != null
? telescope.mapIndexed((idx, p) -> indices.contains(idx) ? p.explicitize() : p.implicitize())
: telescope;

return new PatternTycker(exprTycker, telescope, new LocalLet(), indices == null,
new Renamer());
}

public @NotNull LhsResult checkLhs(
@NotNull Signature signature,
@Nullable ImmutableIntSeq indices,
Expand Down Expand Up @@ -226,6 +226,36 @@ else if (result.hasError) {
}
}

// endregion tycking

// region util

private @NotNull PatternTycker newPatternTycker(
@Nullable ImmutableIntSeq indices,
@NotNull SeqView<Param> telescope
) {
telescope = indices != null
? telescope.mapIndexed((idx, p) -> indices.contains(idx) ? p.explicitize() : p.implicitize())
: telescope;

return new PatternTycker(exprTycker, telescope, new LocalLet(), indices == null,
new Renamer());
}

private static boolean hasAbsurdity(@NotNull Pattern term) {
return hasAbsurdity(term, MutableBooleanValue.create());
}

private static boolean hasAbsurdity(@NotNull Pattern term, @NotNull MutableBooleanValue b) {
if (term == Pattern.Absurd.INSTANCE) b.set(true);
else term.forEach((_, p) -> b.set(b.get() || hasAbsurdity(p, b)));
return b.get();
}

// endregion util

// region post tycking

private static final class TermInline implements UnaryOperator<Term> {
@Override public @NotNull Term apply(@NotNull Term term) {
if (term instanceof MetaPatTerm metaPat) {
Expand All @@ -239,14 +269,6 @@ private static final class TermInline implements UnaryOperator<Term> {
}
}

private static boolean hasAbsurdity(@NotNull Pattern term) {
return hasAbsurdity(term, MutableBooleanValue.create());
}
private static boolean hasAbsurdity(@NotNull Pattern term, @NotNull MutableBooleanValue b) {
if (term == Pattern.Absurd.INSTANCE) b.set(true);
else term.forEach((_, p) -> b.set(b.get() || hasAbsurdity(p, b)));
return b.get();
}

/**
* Inline terms which in pattern
Expand Down Expand Up @@ -285,4 +307,6 @@ public static void apply(@NotNull Pattern pat) {

return new PatternTycker.TyckResult(wellTyped, paramSubst, result.asSubst(), result.newBody(), result.hasError());
}

// endregion post tycking
}
2 changes: 1 addition & 1 deletion base/src/main/java/org/aya/tyck/pat/PatternTycker.java
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ private record Selection(
case DataDef.Delegate delegate -> {
// the core may be unchecked!
var concrete = (DataDecl) delegate.ref.concrete;
yield concrete.body.view()
yield concrete.body.clauses.view()
.filter(it -> it.telescope.isEmpty())
.map(it -> it.ref.name());
}
Expand Down
3 changes: 3 additions & 0 deletions base/src/test/java/org/aya/syntax/concrete/SyntaxTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ def bar (A : Type 0) : A -> A => fn x => {? x ?}
open inductive Fin Nat
| S n => FZ
| S n => FS (Fin n)
open inductive Vec (A : Type) (n : Nat) elim n
| O => vnil
| S m => vcons A (Vec A m)
def infixl + Nat Nat : Nat
| 0, a => a
| S a, b as b' => S (a + b')
Expand Down
7 changes: 4 additions & 3 deletions cli-impl/src/test/resources/shared/src/data/vec/base.aya
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
open import prelude hiding (++)

open inductive Vec Nat Type
| 0, A => []
| suc n, A => infixr :> A (Vec n A)
@suppress(Shadowing)
open inductive Vec (n : Nat) (A : Type) elim n
| 0 => []
| suc n => infixr :> A (Vec n A)

variable A B : Type
variable n m o : Nat
Expand Down
2 changes: 1 addition & 1 deletion ide/src/main/java/org/aya/ide/Resolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public interface Resolver {

static @NotNull SeqView<DefVar<?, ?>> withChildren(@NotNull Decl def) {
return switch (def) {
case DataDecl data -> SeqView.<DefVar<?, ?>>of(data.ref).appendedAll(data.body.map(DataCon::ref));
case DataDecl data -> SeqView.<DefVar<?, ?>>of(data.ref).appendedAll(data.body.clauses.map(DataCon::ref));
// case ClassDecl struct ->
// SeqView.<DefVar<?, ?>>of(struct.ref).appendedAll(struct.members.map(TeleDecl.ClassMember::ref));
default -> SeqView.of(def.ref());
Expand Down
1 change: 1 addition & 0 deletions parser/src/main/gen/org/aya/parser/AyaPsiElementTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public interface AyaPsiElementTypes {
IElementType DO_BINDING = new AyaPsiElementType("DO_BINDING");
IElementType DO_BLOCK_CONTENT = new AyaPsiElementType("DO_BLOCK_CONTENT");
IElementType DO_EXPR = new AyaPsiElementType("DO_EXPR");
IElementType ELIM_DATA_BODY = new AyaPsiElementType("ELIM_DATA_BODY");
IElementType EXPR = new AyaPsiElementType("EXPR");
IElementType FN_BODY = new AyaPsiElementType("FN_BODY");
IElementType FN_DECL = new AyaPsiElementType("FN_DECL");
Expand Down
45 changes: 32 additions & 13 deletions parser/src/main/gen/org/aya/parser/AyaPsiParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ public static boolean dataConClause(PsiBuilder b, int l) {
/* ********************************************************** */
// pragma* declModifier*
// KW_DATA declNameOrInfix?
// tele* type? bindBlock? dataBody*
// tele* type? bindBlock? elimDataBody
public static boolean dataDecl(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "dataDecl")) return false;
boolean r, p;
Expand All @@ -706,7 +706,7 @@ public static boolean dataDecl(PsiBuilder b, int l) {
r = p && report_error_(b, dataDecl_4(b, l + 1)) && r;
r = p && report_error_(b, dataDecl_5(b, l + 1)) && r;
r = p && report_error_(b, dataDecl_6(b, l + 1)) && r;
r = p && dataDecl_7(b, l + 1) && r;
r = p && elimDataBody(b, l + 1) && r;
exit_section_(b, l, m, r, p, null);
return r || p;
}
Expand Down Expand Up @@ -765,17 +765,6 @@ private static boolean dataDecl_6(PsiBuilder b, int l) {
return true;
}

// dataBody*
private static boolean dataDecl_7(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "dataDecl_7")) return false;
while (true) {
int c = current_position_(b);
if (!dataBody(b, l + 1)) break;
if (!empty_element_parsed_guard_(b, "dataDecl_7", c)) break;
}
return true;
}

/* ********************************************************** */
// fnDecl | primDecl | classDecl | dataDecl
public static boolean decl(PsiBuilder b, int l) {
Expand Down Expand Up @@ -862,6 +851,36 @@ public static boolean doBlockContent(PsiBuilder b, int l) {
return r;
}

/* ********************************************************** */
// elims? dataBody*
public static boolean elimDataBody(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "elimDataBody")) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, ELIM_DATA_BODY, "<elim data body>");
r = elimDataBody_0(b, l + 1);
r = r && elimDataBody_1(b, l + 1);
exit_section_(b, l, m, r, false, null);
return r;
}

// elims?
private static boolean elimDataBody_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "elimDataBody_0")) return false;
elims(b, l + 1);
return true;
}

// dataBody*
private static boolean elimDataBody_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "elimDataBody_1")) return false;
while (true) {
int c = current_position_(b);
if (!dataBody(b, l + 1)) break;
if (!empty_element_parsed_guard_(b, "elimDataBody_1", c)) break;
}
return true;
}

/* ********************************************************** */
// KW_ELIM weakId+
static boolean elims(PsiBuilder b, int l) {
Expand Down
4 changes: 3 additions & 1 deletion parser/src/main/grammar/AyaPsiParser.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,9 @@ classMember

dataDecl ::= pragma* declModifier*
KW_DATA declNameOrInfix?
tele* type? bindBlock? dataBody* { pin=3 }
tele* type? bindBlock? elimDataBody { pin=3 }

elimDataBody ::= elims? dataBody*

dataBody ::= BAR (dataConClause | dataCon) {
mixin="org.aya.intellij.psi.impl.AyaPsiGenericDeclImpl"
Expand Down
Loading
Loading