WIP overhaul operand and variadic functions
This commit is contained in:
@@ -257,10 +257,6 @@ class Helpers {
|
|||||||
interp.variables.set("kiss", {
|
interp.variables.set("kiss", {
|
||||||
ReaderExp: {
|
ReaderExp: {
|
||||||
ReaderExpDef: ReaderExpDef
|
ReaderExpDef: ReaderExpDef
|
||||||
},
|
|
||||||
Operand: {
|
|
||||||
toDynamic: Operand.toDynamic,
|
|
||||||
fromDynamic: Operand.fromDynamic
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
interp.variables.set("k", k.forHScript());
|
interp.variables.set("k", k.forHScript());
|
||||||
@@ -407,8 +403,6 @@ class Helpers {
|
|||||||
meta: (m:String, exp:ReaderExp) -> MetaExp(m, exp).withPosOf(posRef),
|
meta: (m:String, exp:ReaderExp) -> MetaExp(m, exp).withPosOf(posRef),
|
||||||
field: (f:String, exp:ReaderExp) -> FieldExp(f, exp).withPosOf(posRef),
|
field: (f:String, exp:ReaderExp) -> FieldExp(f, exp).withPosOf(posRef),
|
||||||
keyValue: (key:ReaderExp, value:ReaderExp) -> KeyValueExp(key, value).withPosOf(posRef),
|
keyValue: (key:ReaderExp, value:ReaderExp) -> KeyValueExp(key, value).withPosOf(posRef),
|
||||||
opToDynamic: (operandExp:ReaderExp) -> CallExp(Symbol("kiss.Operand.toDynamic").withPosOf(posRef), [operandExp]).withPosOf(posRef),
|
|
||||||
opFromDynamic: (operandExp:ReaderExp) -> CallExp(Symbol("kiss.Operand.fromDynamic").withPosOf(posRef), [operandExp]).withPosOf(posRef),
|
|
||||||
begin: (exps:Array<ReaderExp>) -> CallExp(Symbol("begin").withPosOf(posRef), exps).withPosOf(posRef)
|
begin: (exps:Array<ReaderExp>) -> CallExp(Symbol("begin").withPosOf(posRef), exps).withPosOf(posRef)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ class Kiss {
|
|||||||
wrapListExps: true,
|
wrapListExps: true,
|
||||||
loadedFiles: new Map<String, Bool>(),
|
loadedFiles: new Map<String, Bool>(),
|
||||||
// Helpful built-in aliases
|
// Helpful built-in aliases
|
||||||
|
// These ones might conflict with a programmer's variable names, so they only apply in call expressions:
|
||||||
callAliases: [
|
callAliases: [
|
||||||
"print" => Symbol("Prelude.print"),
|
"print" => Symbol("Prelude.print"),
|
||||||
"sort" => Symbol("Prelude.sort"),
|
"sort" => Symbol("Prelude.sort"),
|
||||||
@@ -66,9 +67,24 @@ class Kiss {
|
|||||||
"filter" => Symbol("Lambda.filter"), // TODO use truthy as the default filter function
|
"filter" => Symbol("Lambda.filter"), // TODO use truthy as the default filter function
|
||||||
"flatten" => Symbol("Lambda.flatten"),
|
"flatten" => Symbol("Lambda.flatten"),
|
||||||
"has" => Symbol("Lambda.has"),
|
"has" => Symbol("Lambda.has"),
|
||||||
"count" => Symbol("Lambda.count")
|
"count" => Symbol("Lambda.count"),
|
||||||
|
"min" => Symbol("Prelude.min"),
|
||||||
|
"max" => Symbol("Prelude.max")
|
||||||
|
],
|
||||||
|
// These ones won't conflict with variables and might commonly be used with (apply)
|
||||||
|
identAliases: [
|
||||||
|
"+" => Symbol("Prelude.add"),
|
||||||
|
"-" => Symbol("Prelude.subtract"),
|
||||||
|
"*" => Symbol("Prelude.multiply"),
|
||||||
|
"/" => Symbol("Prelude.divide"),
|
||||||
|
"%" => Symbol("Prelude.mod"),
|
||||||
|
"^" => Symbol("Prelude.pow"),
|
||||||
|
">" => Symbol("Prelude.greaterThan"),
|
||||||
|
">=" => Symbol("Prelude.greaterEqual"),
|
||||||
|
"<" => Symbol("Prelude.lessThan"),
|
||||||
|
"<=" => Symbol("Prelude.lesserEqual"),
|
||||||
|
"=" => Symbol("Prelude.areEqual")
|
||||||
],
|
],
|
||||||
identAliases: new Map(),
|
|
||||||
fields: [],
|
fields: [],
|
||||||
loadingDirectory: "",
|
loadingDirectory: "",
|
||||||
hscript: false
|
hscript: false
|
||||||
|
|||||||
@@ -20,17 +20,13 @@ class KissInterp extends Interp {
|
|||||||
this.nullForUnknownVar = nullForUnknownVar;
|
this.nullForUnknownVar = nullForUnknownVar;
|
||||||
|
|
||||||
variables.set("Prelude", Prelude);
|
variables.set("Prelude", Prelude);
|
||||||
variables.set("kiss", {
|
|
||||||
Operand: {
|
|
||||||
fromDynamic: Operand.fromDynamic,
|
|
||||||
toDynamic: Operand.toDynamic
|
|
||||||
}
|
|
||||||
});
|
|
||||||
variables.set("Lambda", Lambda);
|
variables.set("Lambda", Lambda);
|
||||||
variables.set("Std", Std);
|
variables.set("Std", Std);
|
||||||
variables.set("Keep", ExtraElementHandling.Keep);
|
variables.set("Keep", ExtraElementHandling.Keep);
|
||||||
variables.set("Drop", ExtraElementHandling.Drop);
|
variables.set("Drop", ExtraElementHandling.Drop);
|
||||||
variables.set("Throw", ExtraElementHandling.Throw);
|
variables.set("Throw", ExtraElementHandling.Throw);
|
||||||
|
// Might eventually need to simulate types in the namespace:
|
||||||
|
variables.set("kiss", {});
|
||||||
}
|
}
|
||||||
|
|
||||||
override function resolve(id:String):Dynamic {
|
override function resolve(id:String):Dynamic {
|
||||||
|
|||||||
@@ -65,67 +65,17 @@ class Macros {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macros["%"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k) -> {
|
|
||||||
wholeExp.checkNumArgs(2, 2, '(% [divisor] [dividend])');
|
|
||||||
var b = wholeExp.expBuilder();
|
|
||||||
b.opToDynamic(
|
|
||||||
b.call(
|
|
||||||
b.symbol("Prelude.mod"), [
|
|
||||||
b.opFromDynamic(exps[1]),
|
|
||||||
b.opFromDynamic(exps[0])
|
|
||||||
]));
|
|
||||||
};
|
|
||||||
|
|
||||||
destructiveVersion("%", "%=");
|
destructiveVersion("%", "%=");
|
||||||
|
|
||||||
macros["^"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k) -> {
|
|
||||||
wholeExp.checkNumArgs(2, 2, '(^ [base] [exponent])');
|
|
||||||
var b = wholeExp.expBuilder();
|
|
||||||
b.opToDynamic(
|
|
||||||
b.call(b.symbol("Prelude.pow"), [
|
|
||||||
b.opFromDynamic(exps[1]),
|
|
||||||
b.opFromDynamic(exps[0])
|
|
||||||
]));
|
|
||||||
};
|
|
||||||
destructiveVersion("^", "^=");
|
destructiveVersion("^", "^=");
|
||||||
|
|
||||||
macros["+"] = variadicMacro("Prelude.add");
|
|
||||||
destructiveVersion("+", "+=");
|
destructiveVersion("+", "+=");
|
||||||
|
|
||||||
macros["-"] = variadicMacro("Prelude.subtract");
|
|
||||||
destructiveVersion("-", "-=");
|
destructiveVersion("-", "-=");
|
||||||
|
|
||||||
macros["*"] = variadicMacro("Prelude.multiply");
|
|
||||||
destructiveVersion("*", "*=");
|
destructiveVersion("*", "*=");
|
||||||
|
|
||||||
macros["/"] = variadicMacro("Prelude.divide");
|
|
||||||
destructiveVersion("/", "/=");
|
destructiveVersion("/", "/=");
|
||||||
|
|
||||||
macros["min"] = variadicMacro("Prelude.min");
|
// These shouldn't be ident aliases because they are common variable names
|
||||||
macros["max"] = variadicMacro("Prelude.max");
|
|
||||||
|
|
||||||
macros[">"] = variadicMacro("Prelude.greaterThan");
|
|
||||||
macros[">="] = variadicMacro("Prelude.greaterEqual");
|
|
||||||
macros["<"] = variadicMacro("Prelude.lessThan");
|
|
||||||
macros["<="] = variadicMacro("Prelude.lesserEqual");
|
|
||||||
|
|
||||||
macros["="] = variadicMacro("Prelude.areEqual");
|
|
||||||
|
|
||||||
// the (apply [func] [args]) macro keeps its own list of aliases for the math operators
|
|
||||||
// that can't just be function aliases because they emulate &rest behavior
|
|
||||||
var opAliases = [
|
var opAliases = [
|
||||||
"+" => "Prelude.add",
|
|
||||||
"-" => "Prelude.subtract",
|
|
||||||
"*" => "Prelude.multiply",
|
|
||||||
"/" => "Prelude.divide",
|
|
||||||
">" => "Prelude.greaterThan",
|
|
||||||
">=" => "Prelude.greaterEqual",
|
|
||||||
"<" => "Prelude.lessThan",
|
|
||||||
"<=" => "Prelude.lesserEqual",
|
|
||||||
"=" => "Prelude.areEqual",
|
|
||||||
"max" => "Prelude.max",
|
|
||||||
"min" => "Prelude.min",
|
"min" => "Prelude.min",
|
||||||
"zip" => "Prelude.zip"
|
"max" => "Prelude.max"
|
||||||
];
|
];
|
||||||
|
|
||||||
macros["apply"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k) -> {
|
macros["apply"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k) -> {
|
||||||
@@ -139,22 +89,12 @@ class Macros {
|
|||||||
b.symbol("null");
|
b.symbol("null");
|
||||||
};
|
};
|
||||||
var func = switch (exps[0].def) {
|
var func = switch (exps[0].def) {
|
||||||
case Symbol(sym) if (opAliases.exists(sym)):
|
case Symbol(func) if (opAliases.exists(func)):
|
||||||
b.symbol(opAliases[sym]);
|
b.symbol(opAliases[func]);
|
||||||
default:
|
default:
|
||||||
exps[0];
|
exps[0];
|
||||||
};
|
};
|
||||||
var args = switch (exps[0].def) {
|
var args = exps[1];
|
||||||
case Symbol(sym) if (opAliases.exists(sym)):
|
|
||||||
b.list([
|
|
||||||
b.call(
|
|
||||||
b.field("map", exps[1]), [
|
|
||||||
b.symbol("kiss.Operand.fromDynamic")
|
|
||||||
])
|
|
||||||
]);
|
|
||||||
default:
|
|
||||||
exps[1];
|
|
||||||
};
|
|
||||||
b.call(
|
b.call(
|
||||||
b.symbol("Reflect.callMethod"), [
|
b.symbol("Reflect.callMethod"), [
|
||||||
callOn, func, args
|
callOn, func, args
|
||||||
@@ -833,17 +773,4 @@ class Macros {
|
|||||||
throw CompileError.fromExp(exps[0], 'top-level expression of (cond... ) must be a call list starting with a condition expression');
|
throw CompileError.fromExp(exps[0], 'top-level expression of (cond... ) must be a call list starting with a condition expression');
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static function variadicMacro(func:String):MacroFunction {
|
|
||||||
return (wholeExp:ReaderExp, exps:Array<ReaderExp>, k) -> {
|
|
||||||
var b = wholeExp.expBuilder();
|
|
||||||
b.callSymbol(func, [
|
|
||||||
b.list([
|
|
||||||
for (exp in exps) {
|
|
||||||
b.callSymbol("kiss.Operand.fromDynamic", [exp]);
|
|
||||||
}
|
|
||||||
])
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
package kiss;
|
|
||||||
|
|
||||||
import haxe.ds.Either;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Arithmetic operands
|
|
||||||
**/
|
|
||||||
abstract Operand(Either<String, Float>) from Either<String, Float> to Either<String, Float> {
|
|
||||||
@:from inline static function fromString(s:String):Operand {
|
|
||||||
return Left(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
@:from inline static function fromInt(i:Int):Operand {
|
|
||||||
return Right(0.0 + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
@:from inline static function fromFloat(f:Float):Operand {
|
|
||||||
return Right(0.0 + f);
|
|
||||||
}
|
|
||||||
|
|
||||||
@:from inline static function fromBool(b:Bool):Operand {
|
|
||||||
return if (b == true) Right(Math.POSITIVE_INFINITY) else Right(Math.NEGATIVE_INFINITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Doing this one implicitly just wasn't working in conjunction with Lambda.fold
|
|
||||||
|
|
||||||
/* @:from */
|
|
||||||
public static function fromDynamic(d:Dynamic):Operand {
|
|
||||||
return switch (Type.typeof(d)) {
|
|
||||||
case TInt | TFloat: Right(0.0 + d);
|
|
||||||
// Treating true and false as operands can be useful for equality. In practice, no one should use them
|
|
||||||
// as operands for any other reason
|
|
||||||
case TBool:
|
|
||||||
fromBool(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 converted to Operand';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@:to public inline function toString():Null<String> {
|
|
||||||
return switch (this) {
|
|
||||||
case Left(s): s;
|
|
||||||
default: null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@:to public inline function toFloat():Null<Float> {
|
|
||||||
return switch (this) {
|
|
||||||
case Right(f): f;
|
|
||||||
default: null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@:to public inline function toInt():Null<Int> {
|
|
||||||
return switch (this) {
|
|
||||||
case Right(f): Math.floor(f);
|
|
||||||
default: null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@:to public inline function toBool():Null<Bool> {
|
|
||||||
return switch (this) {
|
|
||||||
case Right(f) if (f == Math.POSITIVE_INFINITY): true;
|
|
||||||
case Right(f) if (f == Math.NEGATIVE_INFINITY): false;
|
|
||||||
default: null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(f): f;
|
|
||||||
case Left(str): str;
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
o;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,6 @@ package kiss;
|
|||||||
|
|
||||||
using Std;
|
using Std;
|
||||||
|
|
||||||
import kiss.Operand;
|
|
||||||
import kiss.ReaderExp;
|
import kiss.ReaderExp;
|
||||||
import haxe.ds.Either;
|
import haxe.ds.Either;
|
||||||
import haxe.Constraints;
|
import haxe.Constraints;
|
||||||
@@ -25,46 +24,39 @@ enum ExtraElementHandling {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Prelude {
|
class Prelude {
|
||||||
static function variadic(op:(Operand, Operand) -> Null<Operand>, comparison = false):(Array<Operand>) -> Dynamic {
|
static function stringOrFloat(d:Dynamic):Either<String,Float> {
|
||||||
return (l:kiss.List<Operand>) -> switch (Lambda.fold(l.slice(1), op, l[0])) {
|
return switch (Type.typeof(d)) {
|
||||||
case null:
|
case TInt | TFloat: Right(0.0 + d);
|
||||||
false;
|
default:
|
||||||
case somethingElse if (comparison):
|
if (Std.isOfType(d, String)) {
|
||||||
true;
|
Left(d);
|
||||||
case somethingElse:
|
} else {
|
||||||
Operand.toDynamic(somethingElse);
|
throw 'cannot use $d in multiplication';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kiss arithmetic will incur overhead because of these switch statements, but the results will not be platform-dependent
|
// Kiss arithmetic will incur overhead because of these switch statements, but the results will not be platform-dependent
|
||||||
static function _add(a:Operand, b:Operand):Operand {
|
static function _add(values:Array<Dynamic>):Dynamic {
|
||||||
return switch ([a, b]) {
|
var sum:Dynamic = values[0];
|
||||||
case [Left(str), Left(str2)]:
|
for (value in values.slice(1)) sum += value;
|
||||||
Left(str2 + str);
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var add:Function = Reflect.makeVarArgs(_add);
|
||||||
|
|
||||||
|
static function _subtract(values:Array<Dynamic>):Dynamic {
|
||||||
|
var difference:Float = values[0];
|
||||||
|
for (value in values.slice(1)) difference -= value;
|
||||||
|
return difference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var subtract:Function = Reflect.makeVarArgs(_subtract);
|
||||||
|
|
||||||
|
static function _multiply2(a:Dynamic, b:Dynamic):Dynamic {
|
||||||
|
return switch ([stringOrFloat(a), stringOrFloat(b)]) {
|
||||||
case [Right(f), Right(f2)]:
|
case [Right(f), Right(f2)]:
|
||||||
Right(f + f2);
|
f * f2;
|
||||||
default:
|
|
||||||
throw 'cannot add mismatched types ${Operand.toDynamic(a)} and ${Operand.toDynamic(b)}';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static var add = variadic(_add);
|
|
||||||
|
|
||||||
static function _subtract(val:Operand, from:Operand):Operand {
|
|
||||||
return switch ([from, val]) {
|
|
||||||
case [Right(from), Right(val)]:
|
|
||||||
Right(from - val);
|
|
||||||
default:
|
|
||||||
throw 'cannot subtract ${Operand.toDynamic(val)} from ${Operand.toDynamic(from)}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static var subtract = variadic(_subtract);
|
|
||||||
|
|
||||||
static function _multiply(a:Operand, b:Operand):Operand {
|
|
||||||
return switch ([a, b]) {
|
|
||||||
case [Right(f), Right(f2)]:
|
|
||||||
Right(f * f2);
|
|
||||||
case [Left(a), Left(b)]:
|
case [Left(a), Left(b)]:
|
||||||
throw 'cannot multiply strings "$a" and "$b"';
|
throw 'cannot multiply strings "$a" and "$b"';
|
||||||
case [Right(i), Left(s)] | [Left(s), Right(i)] if (i % 1 == 0):
|
case [Right(i), Left(s)] | [Left(s), Right(i)] if (i % 1 == 0):
|
||||||
@@ -72,81 +64,75 @@ class Prelude {
|
|||||||
for (_ in 0...Math.floor(i)) {
|
for (_ in 0...Math.floor(i)) {
|
||||||
result += s;
|
result += s;
|
||||||
}
|
}
|
||||||
Left(result);
|
result;
|
||||||
default:
|
default:
|
||||||
throw 'cannot multiply ${Operand.toDynamic(a)} and ${Operand.toDynamic(b)}';
|
throw 'cannot multiply $a and $b';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static var multiply = variadic(_multiply);
|
static function _multiply(values:Array<Dynamic>):Dynamic {
|
||||||
|
var product = values[0];
|
||||||
static function _divide(bottom:Operand, top:Operand):Operand {
|
for (value in values.slice(1)) product = _multiply2(product, value);
|
||||||
return switch ([top, bottom]) {
|
return product;
|
||||||
case [Right(f), Right(f2)]:
|
|
||||||
Right(f / f2);
|
|
||||||
default:
|
|
||||||
throw 'cannot divide $top by $bottom';
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static var divide = variadic(_divide);
|
public static var multiply:Function = Reflect.makeVarArgs(_multiply);
|
||||||
|
|
||||||
public static function mod(bottom:Operand, top:Operand):Operand {
|
static function _divide(values:Array<Dynamic>):Dynamic {
|
||||||
return Right(top.toFloat() % bottom.toFloat());
|
var quotient:Float = values[0];
|
||||||
|
for (value in values.slice(1)) quotient /= value;
|
||||||
|
return quotient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function pow(exponent:Operand, base:Operand):Operand {
|
public static var divide:Function = Reflect.makeVarArgs(_divide);
|
||||||
return Right(Math.pow(base.toFloat(), exponent.toFloat()));
|
|
||||||
|
public static function mod(top:Dynamic, bottom:Dynamic):Dynamic {
|
||||||
|
return top % bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function _min(a:Operand, b:Operand):Operand {
|
public static function pow(base:Dynamic, exponent:Dynamic):Dynamic {
|
||||||
return Right(Math.min(a.toFloat(), b.toFloat()));
|
return Math.pow(base, exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static var min = variadic(_min);
|
static function _min(values:Array<Dynamic>):Dynamic {
|
||||||
|
var min = values[0];
|
||||||
static function _max(a:Operand, b:Operand):Operand {
|
for (value in values.slice(1)) min = Math.min(min, value);
|
||||||
return Right(Math.max(a.toFloat(), b.toFloat()));
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static var max = variadic(_max);
|
public static var min:Function = Reflect.makeVarArgs(_min);
|
||||||
|
|
||||||
static function _greaterThan(b:Operand, a:Operand):Null<Operand> {
|
static function _max(values:Array<Dynamic>):Dynamic {
|
||||||
return if (a == null || b == null) null else if (a.toFloat() > b.toFloat()) b else null;
|
var max = values[0];
|
||||||
|
for (value in values.slice(1)) max = Math.max(max, value);
|
||||||
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static var greaterThan = variadic(_greaterThan, true);
|
public static var max:Function = Reflect.makeVarArgs(_max);
|
||||||
|
|
||||||
static function _greaterEqual(b:Operand, a:Operand):Null<Operand> {
|
static function _comparison(op:String, values:Array<Dynamic>):Bool {
|
||||||
return if (a == null || b == null) null else if (a.toFloat() >= b.toFloat()) b else null;
|
for (idx in 1...values.length) {
|
||||||
|
var a = values[idx-1];
|
||||||
|
var b = values[idx];
|
||||||
|
var check = switch (op) {
|
||||||
|
case ">": a > b;
|
||||||
|
case ">=": a >= b;
|
||||||
|
case "<": a < b;
|
||||||
|
case "<=": a <= b;
|
||||||
|
case "==": a == b;
|
||||||
|
default: throw 'Unreachable case';
|
||||||
|
}
|
||||||
|
if (!check)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static var greaterEqual = variadic(_greaterEqual, true);
|
public static var greaterThan:Function = Reflect.makeVarArgs(_comparison.bind(">"));
|
||||||
|
public static var greaterEqual:Function = Reflect.makeVarArgs(_comparison.bind(">="));
|
||||||
static function _lessThan(b:Operand, a:Operand):Null<Operand> {
|
public static var lessThan:Function = Reflect.makeVarArgs(_comparison.bind("<"));
|
||||||
return if (a == null || b == null) null else if (a.toFloat() < b.toFloat()) b else null;
|
public static var lesserEqual:Function = Reflect.makeVarArgs(_comparison.bind("<="));
|
||||||
}
|
public static var areEqual:Function = Reflect.makeVarArgs(_comparison.bind("=="));
|
||||||
|
|
||||||
public static var lessThan = variadic(_lessThan, true);
|
|
||||||
|
|
||||||
static function _lesserEqual(b:Operand, a:Operand):Null<Operand> {
|
|
||||||
return if (a == null || b == null) null else if (a.toFloat() <= b.toFloat()) b else null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static var lesserEqual = variadic(_lesserEqual, true);
|
|
||||||
|
|
||||||
static function _areEqual(a:Operand, b:Operand):Null<Operand> {
|
|
||||||
return if (a == null || b == null) null else switch ([a, b]) {
|
|
||||||
case [Left(aStr), Left(bStr)] if (aStr == bStr):
|
|
||||||
a;
|
|
||||||
case [Right(aFloat), Right(bFloat)] if (aFloat == bFloat):
|
|
||||||
a;
|
|
||||||
default:
|
|
||||||
null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static var areEqual = variadic(_areEqual, true);
|
|
||||||
|
|
||||||
public static function sort<T>(a:Array<T>, ?comp:(T, T) -> Int):kiss.List<T> {
|
public static function sort<T>(a:Array<T>, ?comp:(T, T) -> Int):kiss.List<T> {
|
||||||
if (comp == null)
|
if (comp == null)
|
||||||
@@ -181,7 +167,6 @@ class Prelude {
|
|||||||
public static function zip(arrays:Array<Array<Dynamic>>, extraHandling = Drop):kiss.List<kiss.List<Dynamic>> {
|
public static function zip(arrays:Array<Array<Dynamic>>, extraHandling = Drop):kiss.List<kiss.List<Dynamic>> {
|
||||||
var lengthsAreEqual = true;
|
var lengthsAreEqual = true;
|
||||||
var lengths = [for (arr in arrays) arr.length];
|
var lengths = [for (arr in arrays) arr.length];
|
||||||
var lengthOperands = [for (length in lengths) Operand.fromDynamic(length)];
|
|
||||||
for (idx in 1...lengths.length) {
|
for (idx in 1...lengths.length) {
|
||||||
if (lengths[idx] != lengths[idx - 1]) {
|
if (lengths[idx] != lengths[idx - 1]) {
|
||||||
lengthsAreEqual = false;
|
lengthsAreEqual = false;
|
||||||
@@ -193,9 +178,9 @@ class Prelude {
|
|||||||
case Throw:
|
case Throw:
|
||||||
throw 'zip was given lists of mis-matched size: $arrays';
|
throw 'zip was given lists of mis-matched size: $arrays';
|
||||||
case Keep:
|
case Keep:
|
||||||
Operand.toDynamic(Prelude.max(lengthOperands));
|
Prelude.max(lengths);
|
||||||
case Drop:
|
case Drop:
|
||||||
Operand.toDynamic(Prelude.min(lengthOperands));
|
Prelude.min(lengths);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lengths[0];
|
lengths[0];
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package year2020;
|
package year2020;
|
||||||
|
|
||||||
import kiss.Prelude;
|
import kiss.Prelude;
|
||||||
import kiss.Operand;
|
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package;
|
|||||||
|
|
||||||
import kiss.Kiss;
|
import kiss.Kiss;
|
||||||
import kiss.Prelude;
|
import kiss.Prelude;
|
||||||
import kiss.Operand;
|
|
||||||
import kiss.Stream;
|
import kiss.Stream;
|
||||||
import vscode.*;
|
import vscode.*;
|
||||||
import js.lib.Promise;
|
import js.lib.Promise;
|
||||||
|
|||||||
@@ -222,9 +222,6 @@
|
|||||||
(defun :Void prepareInterp []
|
(defun :Void prepareInterp []
|
||||||
(interp.variables.set "kiss"
|
(interp.variables.set "kiss"
|
||||||
(object
|
(object
|
||||||
Operand
|
|
||||||
(object
|
|
||||||
fromDynamic Operand.fromDynamic)
|
|
||||||
Prelude
|
Prelude
|
||||||
Prelude))
|
Prelude))
|
||||||
//interp.variables.set("Helpers", Helpers);
|
//interp.variables.set("Helpers", Helpers);
|
||||||
@@ -272,7 +269,6 @@
|
|||||||
|
|
||||||
import kiss.Prelude;
|
import kiss.Prelude;
|
||||||
import kiss.List;
|
import kiss.List;
|
||||||
import kiss.Operand;
|
|
||||||
|
|
||||||
@:build(kiss.Kiss.build())
|
@:build(kiss.Kiss.build())
|
||||||
class ${className} {}
|
class ${className} {}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package nat;
|
|||||||
|
|
||||||
import kiss.Prelude;
|
import kiss.Prelude;
|
||||||
import kiss.List;
|
import kiss.List;
|
||||||
import kiss.Operand;
|
|
||||||
import haxe.Constraints;
|
import haxe.Constraints;
|
||||||
import uuid.Uuid;
|
import uuid.Uuid;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package nat;
|
|||||||
|
|
||||||
import kiss.Prelude;
|
import kiss.Prelude;
|
||||||
import kiss.List;
|
import kiss.List;
|
||||||
import kiss.Operand;
|
|
||||||
import sys.FileSystem;
|
import sys.FileSystem;
|
||||||
import nat.ArchiveController;
|
import nat.ArchiveController;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user