Skip to content

Commit

Permalink
added OpDefaultUnknown
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinOnFrontEnd committed Jan 21, 2024
1 parent a3d6bc1 commit 01b0792
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 6 deletions.
110 changes: 108 additions & 2 deletions CLVMDotNet/src/CLVM/CoreOps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,117 @@ namespace CLVMDotNet.CLVM
{
public class CoreOps
{
public static Tuple<BigInteger, SExp> OpDefaultUnknwon(SExp args)

public static IEnumerable<int> ArgsLen(string opName, SExp args)
{
throw new Exception("Not Implemented!");
foreach (var arg in args.AsIter())
{
if (arg.Pair != null)
{
throw new EvalError(string.Format("{0} requires int args", opName), arg);
}
yield return arg.AsAtom().Length;
}
}

public static Tuple<BigInteger, SExp> OpDefaultUnknwon(byte[] op, SExp args)
{
// Any opcode starting with 0xFFFF is reserved (i.e., fatal error).
// Opcodes are not allowed to be empty.
if (op.Length == 0 || (op[0] == 0xFF && op[1] == 0xFF))
{
throw new EvalError("reserved operator", SExp.To(op));
}

// All other unknown opcodes are no-ops.
// The cost of the no-ops is determined by the opcode number, except the
// 6 least significant bits.

int costFunction = (op[op.Length - 1] & 0b11000000) >> 6;
// The multiplier cannot be 0. It starts at 1.

if (op.Length > 5)
{
throw new EvalError("invalid operator", SExp.To(op));
}

BigInteger costMultiplier = new BigInteger(op.Take(op.Length - 1).ToArray()) + 1;

// 0 = constant
// 1 = like op_add/op_sub
// 2 = like op_multiply
// 3 = like op_concat
BigInteger cost;
switch (costFunction)
{
case 0:
cost = 1;
break;
case 1:
// Like op_add
cost = Costs.ARITH_BASE_COST;
int argSize = 0;
foreach (int l in ArgsLen("unknown op", args))
{
argSize += l;
cost += Costs.ARITH_COST_PER_ARG;
}

cost += argSize * Costs.ARITH_COST_PER_BYTE;
break;
case 2:
// Like op_multiply
cost = Costs.MUL_BASE_COST;
var operands = ArgsLen("unknown op", args).GetEnumerator();
try
{
int vs = operands.MoveNext() ? operands.Current : 0;
while (operands.MoveNext())
{
int rs = operands.Current;
cost += Costs.MUL_COST_PER_OP;
cost += (rs + vs) * Costs.MUL_LINEAR_COST_PER_BYTE;
cost += (rs * vs) / Costs.MUL_SQUARE_COST_PER_BYTE_DIVIDER;
// This is an estimate, since we don't want to actually multiply the values.
vs += rs;
}
}
catch (Exception)
{
// Handle StopIteration
}

break;
case 3:
// Like concat
cost = Costs.CONCAT_BASE_COST;
int length = 0;
foreach (var arg in args.AsIter())
{
if (arg.Pair != null)
{
throw new EvalError("unknown op on list", arg);
}

cost += Costs.CONCAT_COST_PER_ARG;
length += arg.Atom.Length;
}

cost += length * Costs.CONCAT_COST_PER_BYTE;
break;
default:
throw new EvalError("invalid operator", SExp.To(op));
}

cost *= (int)costMultiplier;
if (cost >= (BigInteger)1 << 32)
{
throw new EvalError("invalid operator", SExp.To(op));
}

return Tuple.Create(cost, SExp.NULL);
}

public static Tuple<BigInteger, SExp> OpIf(SExp args)
{
if (args.ListLength() != 3)
Expand Down
6 changes: 3 additions & 3 deletions CLVMDotNet/src/CLVM/Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ public static Tuple<BigInteger, SExp> ApplyOperator(byte[] atom, SExp args)
if (atom.AsSpan().SequenceEqual(new byte[] { 0x23 }))
{
//. (#)
return CoreOps.OpDefaultUnknwon(args);
return CoreOps.OpDefaultUnknwon(atom,args);
}
else if (atom.AsSpan().SequenceEqual(new byte[] { 0x01 }))
{
//q
return CoreOps.OpDefaultUnknwon(args);
return CoreOps.OpDefaultUnknwon(atom,args);
}
else if (atom.AsSpan().SequenceEqual(new byte[] { 0x02 }))
{
//a
//default_unknown_op (not wrote yet)
return CoreOps.OpDefaultUnknwon(args);
return CoreOps.OpDefaultUnknwon(atom, args);
}

else if (atom.AsSpan().SequenceEqual(new byte[] { 0x03 }))
Expand Down
2 changes: 1 addition & 1 deletion CLVMDotNet/src/CLVM/SExp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class SExp
{
public static SExp True { get; } = new SExp(new CLVMObject { Atom = new byte[] { 0x01 } });
public static SExp False { get; } = new SExp(new CLVMObject());
public static CLVMObject NULL { get; } = null;
public static SExp NULL { get; } = new SExp();
public byte[]? Atom { get; set; }
public Tuple<dynamic, dynamic>? Pair { get; set; }

Expand Down

0 comments on commit 01b0792

Please sign in to comment.