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 uniqueVarName = "_" + Uuid.v4().toShort();
var uniqueVarSymbol = Symbol(uniqueVarName).withPosOf(wholeExp); var uniqueVarSymbol = Symbol(uniqueVarName).withPosOf(wholeExp);
uniqueVarExps.push(uniqueVarSymbol); 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), [ CallExp(Symbol("let").withPosOf(wholeExp), [
ListExp(bindingList).withPosOf(wholeExp), ListExp(bindingList).withPosOf(wholeExp),
CallExp(Symbol("kiss.Operand.toDynamic").withPosOf(wholeExp), [
CallExp(Symbol("Lambda.fold").withPosOf(wholeExp), [ CallExp(Symbol("Lambda.fold").withPosOf(wholeExp), [
ListExp(uniqueVarExps.slice(1)).withPosOf(wholeExp), ListExp(uniqueVarExps.slice(1)).withPosOf(wholeExp),
Symbol(func).withPosOf(wholeExp), Symbol(func).withPosOf(wholeExp),
uniqueVarExps[0] uniqueVarExps[0]
]).withPosOf(wholeExp) ]).withPosOf(wholeExp)
]).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)); 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)) { return switch (Type.typeof(d)) {
case TInt: Right(Left(d)); case TInt: Right(Left(d));
case TFloat: Right(Right(d)); case TFloat: Right(Right(d));
default: default:
if (Std.isOfType(d, String)) { if (Std.isOfType(d, String)) {
Left(d); 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 { } else {
throw '$d cannot be Operand'; 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> { // This wasn't working as an implicit conversion in conjunction with Lambda.fold()
return switch (this) {
/* @: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(Left(i)): i;
case Right(Right(f)): f; case Right(Right(f)): f;
case Left(str): str; 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(); 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()); return Math.pow(base.toFloat(), exponent.toFloat());
} }
@@ -97,7 +97,7 @@ class Prelude {
} }
public static function areEqual(a:Operand, b:Operand):Operand { 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) { 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) -> { return (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> {
var callFoldMacroExpr = k.convert(CallExp(Symbol(func).withPosOf(wholeExp), args).withPosOf(wholeExp)); var callFoldMacroExpr = k.convert(CallExp(Symbol(func).withPosOf(wholeExp), args).withPosOf(wholeExp));
wholeExp.checkNumArgs(1, null); 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);
}; };
} }
} }