Skip to content

Commit

Permalink
Check Lambda as coded value
Browse files Browse the repository at this point in the history
  • Loading branch information
mikera committed Dec 3, 2024
1 parent e3fc8ca commit f12c32d
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 37 deletions.
1 change: 1 addition & 0 deletions convex-core/src/main/java/convex/core/cvm/CVMTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public class CVMTag {
// General ops with byte flag
public static final byte OP_CODED = (byte) 0xC0;
public static final byte OPCODE_CONSTANT = (byte) 0xB0;
public static final byte OPCODE_LAMBDA = (byte) 0xBF;

public static final byte OP_DEF = (byte) 0xCD;

Expand Down
2 changes: 1 addition & 1 deletion convex-core/src/main/java/convex/core/cvm/Ops.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public static <T extends ACell> AOp<T> read(byte tag, Blob b, int pos) throws Ba
return Try.read(b,pos);
case Ops.LOOKUP:
return Lookup.read(b,pos);
case Ops.LAMBDA:
case CVMTag.OPCODE_LAMBDA:
return (AOp<T>) Lambda.read(b,pos);
case Ops.LET:
return Let.read(b,pos,false);
Expand Down
51 changes: 15 additions & 36 deletions convex-core/src/main/java/convex/core/cvm/ops/Lambda.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package convex.core.cvm.ops;

import convex.core.cvm.AOp;
import convex.core.cvm.CVMTag;
import convex.core.cvm.Context;
import convex.core.cvm.Juice;
import convex.core.cvm.Ops;
import convex.core.data.ACell;
import convex.core.data.AVector;
import convex.core.data.Blob;
import convex.core.data.Format;
import convex.core.data.IRefFunction;
import convex.core.data.Ref;
import convex.core.data.prim.ByteFlag;
import convex.core.data.util.BlobBuilder;
import convex.core.exceptions.BadFormatException;
import convex.core.exceptions.InvalidDataException;
import convex.core.lang.impl.AClosure;
import convex.core.lang.impl.Fn;
import convex.core.util.ErrorMessages;
import convex.core.util.Utils;

/**
Expand All @@ -27,12 +27,11 @@
*
* @param <T> Result type of Closure
*/
public class Lambda<T extends ACell> extends AOp<AClosure<T>> {
public class Lambda<T extends ACell> extends ACodedOp<T,ACell,AClosure<T>> {
private static final Ref<ACell> OPCODE = new ByteFlag(CVMTag.OPCODE_LAMBDA).getRef();

private Ref<AClosure<T>> function;

protected Lambda(Ref<AClosure<T>> newFunction) {
this.function=newFunction;
super(CVMTag.OP_CODED,OPCODE,newFunction);
}

public static <T extends ACell> Lambda<T> create(AVector<ACell> params, AOp<T> body) {
Expand All @@ -45,45 +44,19 @@ public static <T extends ACell> Lambda<T> create(AClosure<T> fn) {

@Override
public Context execute(Context context) {
AClosure<T> fn= function.getValue().withEnvironment(context.getLocalBindings());
AClosure<T> fn= value.getValue().withEnvironment(context.getLocalBindings());
return context.withResult(Juice.LAMBDA,fn);
}

@Override
public int getRefCount() {
return 1;
}

@SuppressWarnings("unchecked")
@Override
public <R extends ACell> Ref<R> getRef(int i) {
if (i==0) return (Ref<R>) function;
throw new IndexOutOfBoundsException(ErrorMessages.badIndex(i));
}

@Override
public Lambda<T> updateRefs(IRefFunction func) {
@SuppressWarnings("unchecked")
Ref<AClosure<T>> newFunction=(Ref<AClosure<T>>) func.apply(function);
if (function==newFunction) return this;
return new Lambda<T>(newFunction);
}

@Override
public boolean print(BlobBuilder sb, long limit) {
return function.getValue().print(sb,limit);
return value.getValue().print(sb,limit);
}

@Override
public byte opCode() {
return Ops.LAMBDA;
}

@Override
public int encodeAfterOpcode(byte[] bs, int pos) {
pos=function.encode(bs, pos);
return pos;
}

public static <T extends ACell> Lambda<T> read(Blob b, int pos) throws BadFormatException {
int epos=pos+Ops.OP_DATA_OFFSET; // skip tag and opcode to get to data
Expand All @@ -100,7 +73,7 @@ public static <T extends ACell> Lambda<T> read(Blob b, int pos) throws BadFormat
public void validate() throws InvalidDataException {
super.validate();

ACell fn=function.getValue();
ACell fn=value.getValue();
if (!(fn instanceof AClosure)) {
throw new InvalidDataException("Lambda child must be a closure but got: "+Utils.getClassName(fn),this);
}
Expand All @@ -112,6 +85,12 @@ public void validateCell() throws InvalidDataException {
}

public AClosure<T> getFunction() {
return function.getValue();
return value.getValue();
}

@Override
protected AOp<T> rebuild(Ref<ACell> newCode, Ref<AClosure<T>> newValue) {
if (newValue==value) return this;
return new Lambda<T>(newValue);
}
}

0 comments on commit f12c32d

Please sign in to comment.