org.aya.concrete.stmt.Decl Maven / Gradle / Ivy
// Copyright (c) 2020-2021 Yinsen (Tesla) Zhang.
// Use of this source code is governed by the MIT license that can be found in the LICENSE.md file.
package org.aya.concrete.stmt;
import kala.collection.immutable.ImmutableSeq;
import kala.collection.mutable.DynamicSeq;
import kala.control.Either;
import kala.control.Option;
import org.aya.api.concrete.ConcreteDecl;
import org.aya.api.ref.DefVar;
import org.aya.concrete.Expr;
import org.aya.concrete.Pattern;
import org.aya.concrete.resolve.context.Context;
import org.aya.core.def.*;
import org.aya.core.sort.Sort;
import org.aya.core.term.Term;
import org.aya.generic.Modifier;
import org.aya.util.binop.OpDecl;
import org.aya.util.error.SourcePos;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
import java.util.function.BiFunction;
/**
* Concrete definition, corresponding to {@link Def}.
*
* @author re-xyr
*/
public sealed abstract class Decl extends Signatured implements Stmt, ConcreteDecl {
public final @NotNull Accessibility accessibility;
public @Nullable Context ctx = null;
public @NotNull Expr result;
@Override public @NotNull Accessibility accessibility() {
return accessibility;
}
protected Decl(
@NotNull SourcePos sourcePos, @NotNull SourcePos entireSourcePos,
@NotNull Accessibility accessibility,
@Nullable OpInfo opInfo,
@NotNull BindBlock bindBlock,
@NotNull ImmutableSeq telescope,
@NotNull Expr result
) {
super(sourcePos, entireSourcePos, opInfo, bindBlock, telescope);
this.accessibility = accessibility;
this.result = result;
}
@Contract(pure = true) public abstract @NotNull DefVar extends Def, ? extends Decl> ref();
protected abstract R doAccept(@NotNull Visitor
visitor, P p);
@Override public final
R accept(Stmt.@NotNull Visitor
visitor, P p) {
return accept((Visitor super P, ? extends R>) visitor, p);
}
public final
R accept(@NotNull Visitor
visitor, P p) {
visitor.traceEntrance(this, p);
var ret = doAccept(visitor, p);
visitor.traceExit(p, ret);
return ret;
}
@ApiStatus.NonExtendable
public final @Override
R doAccept(Stmt.@NotNull Visitor
visitor, P p) {
return doAccept((Decl.Visitor
) visitor, p);
}
public interface Visitor
{
default void traceEntrance(@NotNull Signatured item, P p) {
}
default void traceExit(P p, R r) {
}
@ApiStatus.NonExtendable
default RR traced(@NotNull T yeah, P p, @NotNull BiFunction f) {
traceEntrance(yeah, p);
var r = f.apply(yeah, p);
traceExit(p, r);
return r;
}
@ApiStatus.OverrideOnly R visitCtor(Decl.@NotNull DataCtor ctor, P p);
@ApiStatus.OverrideOnly R visitField(Decl.@NotNull StructField field, P p);
R visitData(Decl.@NotNull DataDecl decl, P p);
R visitStruct(Decl.@NotNull StructDecl decl, P p);
R visitFn(Decl.@NotNull FnDecl decl, P p);
R visitPrim(Decl.@NotNull PrimDecl decl, P p);
}
/**
* @author ice1000
* @implSpec the result field of {@link PrimDecl} might be {@link org.aya.concrete.Expr.ErrorExpr},
* which means it's unspecified in the concrete syntax.
* @see PrimDef
*/
public static final class PrimDecl extends Decl implements OpDecl {
public final @NotNull DefVar ref;
public PrimDecl(
@NotNull SourcePos sourcePos, @NotNull SourcePos entireSourcePos,
@Nullable OpDecl.OpInfo opInfo,
@NotNull DefVar ref,
@NotNull ImmutableSeq telescope,
@NotNull Expr result
) {
super(sourcePos, entireSourcePos, Accessibility.Public, opInfo, BindBlock.EMPTY, telescope, result);
ref.concrete = this;
this.ref = ref;
}
@Override public boolean needTyck() {
return ref.concrete.signature == null;
}
@Override public @NotNull DefVar ref() {
return ref;
}
@Override protected R doAccept(@NotNull Decl.Visitor
visitor, P p) {
return visitor.visitPrim(this, p);
}
}
public static final class DataCtor extends Signatured implements OpDecl {
public final @NotNull DefVar ref;
public DefVar dataRef;
/** Similar to {@link Signatured#signature}, but stores the bindings in {@link DataCtor#patterns} */
public ImmutableSeq patternTele;
public @NotNull ImmutableSeq clauses;
public @NotNull ImmutableSeq patterns;
public final boolean coerce;
public DataCtor(
@NotNull SourcePos sourcePos, @NotNull SourcePos entireSourcePos,
@Nullable OpInfo opInfo,
@NotNull String name,
@NotNull ImmutableSeq telescope,
@NotNull ImmutableSeq clauses,
@NotNull ImmutableSeq patterns,
boolean coerce,
@NotNull BindBlock bindBlock
) {
super(sourcePos, entireSourcePos, opInfo, bindBlock, telescope);
this.clauses = clauses;
this.coerce = coerce;
this.patterns = patterns;
this.ref = DefVar.concrete(this, name);
}
@Override public @NotNull DefVar ref() {
return ref;
}
}
/**
* Concrete data definition
*
* @author kiva
* @see DataDef
*/
public static final class DataDecl extends Decl implements OpDecl {
public final @NotNull DefVar ref;
public final @NotNull ImmutableSeq body;
/** Yet type-checked constructors */
public final @NotNull DynamicSeq<@NotNull CtorDef> checkedBody = DynamicSeq.create();
public Sort sort;
public DataDecl(
@NotNull SourcePos sourcePos, @NotNull SourcePos entireSourcePos,
@NotNull Accessibility accessibility,
@Nullable OpInfo opInfo,
@NotNull String name,
@NotNull ImmutableSeq telescope,
@NotNull Expr result,
@NotNull ImmutableSeq body,
@NotNull BindBlock bindBlock
) {
super(sourcePos, entireSourcePos, accessibility, opInfo, bindBlock, telescope, result);
this.body = body;
this.ref = DefVar.concrete(this, name);
body.forEach(ctors -> ctors.dataRef = ref);
}
@Override protected R doAccept(@NotNull Decl.Visitor
visitor, P p) {
return visitor.visitData(this, p);
}
@Override public @NotNull DefVar ref() {
return this.ref;
}
}
/**
* Concrete structure definition
*
* @author vont
*/
public static final class StructDecl extends Decl implements OpDecl {
public final @NotNull DefVar ref;
public @NotNull
final ImmutableSeq fields;
public Sort sort;
public StructDecl(
@NotNull SourcePos sourcePos, @NotNull SourcePos entireSourcePos,
@NotNull Accessibility accessibility,
@Nullable OpInfo opInfo,
@NotNull String name,
@NotNull ImmutableSeq telescope,
@NotNull Expr result,
// @NotNull ImmutableSeq superClassNames,
@NotNull ImmutableSeq fields,
@NotNull BindBlock bindBlock
) {
super(sourcePos, entireSourcePos, accessibility, opInfo, bindBlock, telescope, result);
this.fields = fields;
this.ref = DefVar.concrete(this, name);
fields.forEach(field -> field.structRef = ref);
}
@Override public @NotNull DefVar ref() {
return ref;
}
@Override protected R doAccept(Decl.@NotNull Visitor
visitor, P p) {
return visitor.visitStruct(this, p);
}
}
public static final class StructField extends Signatured implements OpDecl {
public final @NotNull DefVar ref;
public DefVar structRef;
public @NotNull ImmutableSeq clauses;
public @NotNull Expr result;
public @NotNull Option body;
public final boolean coerce;
public StructField(
@NotNull SourcePos sourcePos, @NotNull SourcePos entireSourcePos,
@Nullable OpInfo opInfo,
@NotNull String name,
@NotNull ImmutableSeq telescope,
@NotNull Expr result,
@NotNull Option body,
@NotNull ImmutableSeq clauses,
boolean coerce,
@NotNull BindBlock bindBlock
) {
super(sourcePos, entireSourcePos, opInfo, bindBlock, telescope);
this.coerce = coerce;
this.result = result;
this.clauses = clauses;
this.body = body;
this.ref = DefVar.concrete(this, name);
}
@Override public @NotNull DefVar ref() {
return ref;
}
@Override public @Nullable OpDecl.OpInfo opInfo() {
return opInfo;
}
}
/**
* Concrete function definition
*
* @author re-xyr
* @see FnDef
*/
public static final class FnDecl extends Decl implements OpDecl {
public final @NotNull EnumSet modifiers;
public final @NotNull DefVar ref;
public @NotNull Either> body;
public FnDecl(
@NotNull SourcePos sourcePos, @NotNull SourcePos entireSourcePos,
@NotNull Accessibility accessibility,
@NotNull EnumSet modifiers,
@Nullable OpDecl.OpInfo opInfo,
@NotNull String name,
@NotNull ImmutableSeq telescope,
@NotNull Expr result,
@NotNull Either> body,
@NotNull BindBlock bindBlock
) {
super(sourcePos, entireSourcePos, accessibility, opInfo, bindBlock, telescope, result);
this.modifiers = modifiers;
this.ref = DefVar.concrete(this, name);
this.body = body;
}
@Override protected R doAccept(@NotNull Decl.Visitor
visitor, P p) {
return visitor.visitFn(this, p);
}
@Override public @NotNull DefVar ref() {
return this.ref;
}
}
}