More ergonomic variadic operations, hopefully

This commit is contained in:
2020-12-02 13:52:31 -07:00
parent 3598db1834
commit 4d2d18d797
4 changed files with 38 additions and 17 deletions

View File

@@ -249,16 +249,21 @@ class Macros {
var uniqueVarName = "_" + Uuid.v4().toShort();
var uniqueVarSymbol = Symbol(uniqueVarName).withPosOf(wholeExp);
uniqueVarExps.push(uniqueVarSymbol);
bindingList = bindingList.concat([TypedExp("kiss.Operand", uniqueVarSymbol).withPosOf(wholeExp), exp]);
bindingList = bindingList.concat([
TypedExp("kiss.Operand", uniqueVarSymbol).withPosOf(wholeExp),
CallExp(Symbol("kiss.Operand.fromDynamic").withPosOf(wholeExp), [exp]).withPosOf(wholeExp)
]);
};
CallExp(Symbol("let").withPosOf(wholeExp), [
ListExp(bindingList).withPosOf(wholeExp),
CallExp(Symbol("Lambda.fold").withPosOf(wholeExp), [
ListExp(uniqueVarExps.slice(1)).withPosOf(wholeExp),
Symbol(func).withPosOf(wholeExp),
uniqueVarExps[0]
]).withPosOf(wholeExp)
CallExp(Symbol("kiss.Operand.toDynamic").withPosOf(wholeExp), [
CallExp(Symbol("Lambda.fold").withPosOf(wholeExp), [
ListExp(uniqueVarExps.slice(1)).withPosOf(wholeExp),
Symbol(func).withPosOf(wholeExp),
uniqueVarExps[0]
]).withPosOf(wholeExp)
]).withPosOf(wholeExp),
]).withPosOf(wholeExp);
};
}

View File

@@ -18,13 +18,21 @@ abstract Operand(Either<String, Either<Int, Float>>) from Either<String, Either<
return Right(Right(f));
}
@:from inline static function fromDynamic(d:Dynamic):Operand {
// Doing this one implicitly just wasn't working in conjunction with Lambda.fold
/* @:from */
public inline static function fromDynamic(d:Dynamic):Operand {
return switch (Type.typeof(d)) {
case TInt: Right(Left(d));
case TFloat: Right(Right(d));
default:
if (Std.isOfType(d, String)) {
Left(d);
}
// Taking a gamble here that no one will ever try to pass a different kind of Either as an operand,
// because at runtime this is as specific as the check can get.
else if (Std.isOfType(d, Either)) {
d;
} else {
throw '$d cannot be Operand';
};
@@ -54,11 +62,19 @@ abstract Operand(Either<String, Either<Int, Float>>) from Either<String, Either<
};
}
@:to public inline function toDynamic():Null<Dynamic> {
return switch (this) {
case Right(Left(i)): i;
case Right(Right(f)): f;
case Left(str): str;
}
// This wasn't working as an implicit conversion in conjunction with Lambda.fold()
/* @:to */
public static function toDynamic(o:Dynamic):Null<Dynamic> {
return if (Std.isOfType(o, Either)) {
var o:Operand = cast o;
switch (o) {
case Right(Left(i)): i;
case Right(Right(f)): f;
case Left(str): str;
};
} else {
o;
};
}
}

View File

@@ -72,11 +72,11 @@ class Prelude {
};
}
public static function mod(bottom:Operand, top:Operand):Operand {
public static function mod(bottom:Operand, top:Operand):Float {
return top.toFloat() % bottom.toFloat();
}
public static function pow(exponent:Operand, base:Operand):Operand {
public static function pow(exponent:Operand, base:Operand):Float {
return Math.pow(base.toFloat(), exponent.toFloat());
}
@@ -97,7 +97,7 @@ class Prelude {
}
public static function areEqual(a:Operand, b:Operand):Operand {
return if (a.toDynamic() == b.toDynamic()) a else Right(Right(Math.NaN));
return if (Operand.toDynamic(a) == Operand.toDynamic(b)) a else Right(Right(Math.NaN));
}
public static function groups<T>(a:Array<T>, size, keepRemainder = false) {

View File

@@ -287,7 +287,7 @@ class SpecialForms {
return (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> {
var callFoldMacroExpr = k.convert(CallExp(Symbol(func).withPosOf(wholeExp), args).withPosOf(wholeExp));
wholeExp.checkNumArgs(1, null);
EBinop(OpEq, k.convert(args[0]), macro ${callFoldMacroExpr}.toDynamic()).withMacroPosOf(wholeExp);
EBinop(OpEq, k.convert(args[0]), macro kiss.Operand.toDynamic($callFoldMacroExpr)).withMacroPosOf(wholeExp);
};
}
}