package org.shedlang.compiler.shid.instructions; import org.pcollections.PVector; import org.shedlang.compiler.ast.typed.FreeVariables; import org.shedlang.compiler.sources.Source; import org.shedlang.compiler.sources.Sources; import org.shedlang.compiler.util.P; import java.util.List; /** * Push a function value onto the temporary value stack with the given * definition. */ public record ShidDefineFunction( String name, List positionalParams, List namedParams, FreeVariables freeVariables, ShidBlock body, Variant variant, Source source ) implements ShidInstruction { public enum Variant { EFFECT_HANDLER_METHOD, FUNCTION, } @Override public boolean isBlockTerminator() { return false; } public static Builder builder() { return new Builder( "f", P.vector(), P.vector(), FreeVariables.builder(), P.vector(), Variant.FUNCTION ); } public record Builder( String name, PVector positionalParams, PVector namedParams, FreeVariables.Builder freeVariables, PVector body, ShidDefineFunction.Variant variant ) { public ShidDefineFunction build() { return new ShidDefineFunction( name, positionalParams, namedParams, freeVariables.build(), new ShidBlock(List.of(), body, Sources.NULL), variant, Sources.NULL ); } public Builder withName(String name) { return new Builder( name, this.positionalParams, this.namedParams, this.freeVariables, this.body, this.variant ); } public Builder addPositionalParam(String name) { return new Builder( this.name, this.positionalParams.plus(new ShidParam(name, Sources.NULL)), this.namedParams, this.freeVariables, this.body, this.variant ); } public Builder addNamedParam(String name) { return new Builder( this.name, this.positionalParams, this.namedParams.plus(new ShidParam(name, Sources.NULL)), this.freeVariables, this.body, this.variant ); } public Builder addFreeVariable(String name) { return new Builder( this.name, this.positionalParams, this.namedParams, this.freeVariables.plus(name, Sources.NULL), this.body, this.variant ); } public Builder addBodyInstruction(ShidInstruction instruction) { return new Builder( this.name, this.positionalParams, this.namedParams, this.freeVariables, this.body.plus(instruction), this.variant ); } } }