reorganize kiss into its own directory

This commit is contained in:
2020-12-05 18:35:09 -07:00
commit b440f0f07c
30 changed files with 2430 additions and 0 deletions

13
src/test/TestMain.hx Normal file
View File

@@ -0,0 +1,13 @@
package test;
import utest.Runner;
import utest.ui.Report;
class TestMain {
public static function main() {
var runner = new Runner();
runner.addCases(test.cases);
Report.create(runner);
runner.run();
}
}

View File

@@ -0,0 +1,249 @@
package test.cases;
import utest.Test;
import utest.Assert;
import kiss.Prelude;
import kiss.List;
using StringTools;
@:build(kiss.Kiss.build("kiss/src/test/cases/BasicTestCase.kiss"))
class BasicTestCase extends Test {
function testStaticVar() {
Assert.equals("Howdy", BasicTestCase.message);
}
function testHaxeInsertion() {
Assert.equals(23, BasicTestCase.mathResult);
}
function testStaticFunction() {
Assert.equals(6, BasicTestCase.myFloor(6.5));
}
function testFuncall() {
Assert.equals(7, BasicTestCase.funResult);
}
function testField() {
Assert.equals(5, new BasicTestCase().myField);
}
function testMethod() {
Assert.equals(5, new BasicTestCase().myMethod());
}
function testArray() {
var arr = BasicTestCase.myArray;
Assert.equals(3, arr.length);
Assert.equals(1, arr[0]);
Assert.equals(2, arr[1]);
Assert.equals(3, arr[2]);
// Kiss arrays can be negatively indexed like Python
Assert.equals(3, arr[-1]);
Assert.equals(2, arr[-2]);
Assert.equals(1, arr[-3]);
}
function testArrayAccess() {
Assert.equals(3, BasicTestCase.myArrayLast);
}
function testVariadicAdd() {
Assert.equals(6, BasicTestCase.mySum);
}
function testVariadicSubtract() {
Assert.equals(-2, BasicTestCase.myDifference);
}
function testVariadicMultiply() {
_testMultiplication();
}
function testVariadicDivide() {
Assert.equals(0.5, BasicTestCase.myQuotient);
}
function testMod() {
Assert.equals(4, BasicTestCase.myRemainder);
}
function testPow() {
Assert.equals(256, BasicTestCase.myPower);
}
function testUnop() {
Assert.equals(7, BasicTestCase.myInc);
Assert.equals(7, BasicTestCase.myNum);
}
function testMin() {
Assert.equals(1, BasicTestCase.myMin);
}
function testMax() {
Assert.equals(9, BasicTestCase.myMax);
}
function testLessThan() {
_testLessThan();
}
function testLesserEqual() {
_testLesserEqual();
}
function testGreaterThan() {
_testGreaterThan();
}
function testGreaterEqual() {
_testGreaterEqual();
}
function testEqual() {
_testEqual();
}
function testIf() {
_testIf();
}
function testMacros() {
Assert.equals(7, BasicTestCase.incrementTwice(5));
var seasonsGreetings = "ho ";
Assert.equals("ho ho ho ", BasicTestCase.doTwiceString(() -> {
seasonsGreetings += "ho ";
}));
}
// TODO to really test typed variable definitions, check for compilation failure on a bad example
function testTypedDefvar() {
Assert.equals(8, BasicTestCase.myInt);
}
function testTryCatch() {
Assert.equals(5, BasicTestCase.myTryCatch("string error"));
Assert.equals(6, BasicTestCase.myTryCatch(404));
Assert.equals(7, BasicTestCase.myTryCatch(["list error"]));
}
function testTypeCheck() {
Assert.equals(5, BasicTestCase.myTypeCheck());
}
function testGroups() {
Assert.equals([[1, 2], [3, 4]].toString(), BasicTestCase.myGroups1().toString());
Assert.equals([[1, 2, 3], [4]].toString(), BasicTestCase.myGroups2().toString());
}
function testLet() {
_testLet();
}
function testConstructors() {
Assert.equals("sup", BasicTestCase.myConstructedString);
}
function testCond() {
Assert.equals("this one", BasicTestCase.myCond1);
Assert.equals("the default", BasicTestCase.myCond2);
Assert.equals("this", BasicTestCase.myCond3);
Assert.equals(null, BasicTestCase.myCondFallthrough);
}
function testSetAndDeflocal() {
Assert.equals("another thing", BasicTestCase.mySetLocal());
}
function testOr() {
Assert.equals(5, BasicTestCase.myOr1);
}
function testAnd() {
Assert.equals(6, BasicTestCase.myAnd1);
Assert.equals(null, BasicTestCase.myAnd2);
Assert.equals(null, BasicTestCase.myAnd3);
}
function testNot() {
Assert.equals(false, BasicTestCase.myNot1);
Assert.equals(false, BasicTestCase.myNot2);
}
function testLambda() {
Assert.equals([5, 6].toString(), BasicTestCase.myFilteredList.toString());
}
function testWhen() {
Assert.equals(6, BasicTestCase.myWhen1);
}
function testQuickNths() {
_testQuickNths();
}
function testListDestructuring() {
_testListDestructuring();
}
function testDoFor() {
_testDoFor();
}
function testOptionalArguments() {
myOptionalFunc(5);
}
function testRestArguments() {
Assert.equals(5, myRest1);
Assert.equals(5, myRest2);
Assert.equals(5, myRest3);
}
function testCombinedOptRest() {
Assert.equals("abcd", myCombined1);
Assert.equals("aboop", myCombined2);
Assert.equals("ab", myCombined3);
}
function testFieldExps() {
_testFieldExps();
}
function testBreakContinue() {
_testBreakContinue();
}
function testAssert() {
_testAssert();
}
function testApply() {
_testApply();
}
function testApplyWithMethod() {
Assert.equals(30, applyWithMethod(new BasicObject(5)));
Assert.equals(18, applyWithMethod(new BasicObject(3)));
}
function testAnonymousObject() {
_testAnonymousObject();
}
}
class BasicObject {
var val:Int;
public function new(val:Int) {
this.val = val;
}
public function multiply(otherVal:Int) {
return val * otherVal;
}
}

View File

@@ -0,0 +1,319 @@
// (defvar) declares static variables
(defvar message "Howdy")
// #| ... |# parses and injects raw Haxe code
(defvar mathResult #|5 + 6 * 3|#) // Order of operations will apply
// (defun) declares static functions
(defun myFloor [num]
// funcalls can use dot access
(Math.floor num))
// functions are resolved in the macro context
(defvar funResult (myFloor 7.5))
// (defprop) declares instance variables
(defprop myField 5)
// (defmethod) declares instance methods
(defmethod myMethod [] this.myField)
// [...] returns a Kiss array (they have special features and convert implicitly)
(defvar myArray [1 2 3])
// Array access is via nth
(defvar myArrayLast (nth myArray -1))
// Variadic math uses haxe's Lambda.fold under the hood
(defvar mySum (+ 1 2 3))
(defvar myDifference (- 5 4 3))
(defun _testMultiplication []
(Assert.equals 60 (* 2 5 6))
(Assert.equals 5522401584 (* 84 289 89 71 36))
(Assert.equals "heyheyhey" (* "hey" 3)))
// All math operations return floats, none truncate by default
(defvar myQuotient (/ 6 3 2 2))
(defvar myRemainder (% 10 6))
(defvar myPower (^ 2 8))
(defvar &mut myNum 6)
(defvar myInc ++myNum)
(defvar myMin (min 9 3 7 1))
(defvar myMax (max 9 3 7 1))
(defun _testLessThan []
(Assert.isTrue (< 1 2 3 4))
(Assert.isFalse (< 1 1 3 4))
(Assert.isFalse (< 1 12 12)))
(defun _testLesserEqual []
(Assert.isTrue (<= 1 2 3 4))
(Assert.isTrue (<= 1 1 3 4))
(Assert.isFalse (<= 1 12 11)))
(defun _testGreaterThan []
(Assert.isTrue (> 4 3 2 1))
(Assert.isFalse (> 4 4 2 1))
(Assert.isFalse (> 9 3 3)))
(defun _testGreaterEqual []
(Assert.isTrue (>= 4 3 2 1))
(Assert.isTrue (>= 4 4 2 1))
(Assert.isFalse (>= 9 4 5)))
(defun _testEqual []
(Assert.isTrue (= 1 1 1 1))
(Assert.isFalse (= 1 2 1 1))
(Assert.isTrue (= "hey" "hey" "hey"))
(Assert.isFalse (= "hey" "you" "hey"))
(Assert.isTrue (= true true true))
(Assert.isFalse (= true false true))
(Assert.isTrue (= false false false)))
(defun _testIf []
(Assert.equals true (if 1 true false))
(Assert.equals false (if 0 true false))
(Assert.equals false (if -1 true false))
(Assert.equals false (if null true false))
(Assert.equals true (if true true false))
(Assert.equals false (if false true false))
(Assert.equals true (if "string" true false))
(Assert.equals false (if "" true false))
(Assert.equals false (if [] true false))
(Assert.equals true (if [1] true false))
(Assert.equals 5 (if true 5))
(Assert.equals null (if false 5)))
(defvar :Int myInt 8)
(defmacrofun doTwiceInt [intOp]
,intOp
,intOp)
// I think this causes doTwiceInt's runtime function to be typed as requiring Quote<Int> and returning Int
(defun :Int incrementTwice [:Int val]
(doTwiceInt ++val))
(defmacrofun doTwiceString [stringOp]
,stringOp
,stringOp)
(defun myTryCatch [:Any e]
(try
(throw e)
(catch [:String error] 5)
(catch [:Int error] 6)
(catch [error] 7)))
(defun myTypeCheck []
(the Int 5))
(defun myGroups1 []
(Prelude.groups [1 2 3 4] 2))
(defun myGroups2 []
(Prelude.groups [1 2 3 4] 3 true))
(defun _testLet []
(let [a 5
b 6
:String c "stuff"]
(Assert.equals 5 a)
(Assert.equals 6 b)
(Assert.equals "stuff" c))
(let [&mut a "str1"]
(Assert.equals "str1" a)
(set a "str2")
(Assert.equals "str2" a)))
(defvar myConstructedString (new String "sup"))
(defvar myCond1 (cond
((= 5 6) "not this")
((= 8 9) "not this either")
((= 1 1) "this one")
(true "not the default")))
(defvar myCond2 (cond
((= 5 6) "not this")
((= 8 9) "not this either")
((= 2 1) "not the third one")
(true "the default")))
(defvar myCond3 (cond
((= 5 5) "this")
(true "default")))
(defvar myCondFallthrough (cond
(false "not this")))
(defvar myOr1 (or null 5))
(defvar myAnd1 (and 5 6))
(defvar myAnd2 (and false 5 6))
(defvar myAnd3 (and 5 false 6))
(defun mySetLocal []
(deflocal &mut loc "one thing")
(set loc "another thing")
loc)
(defvar myNot1 (not 5))
(defvar myNot2 !5)
(defvar myFilteredList (begin
(deflocal l [-1 -2 5 -3 6])
(l.filter (lambda [v] (< 0 v)))))
(defvar myWhen1 (when true 5 6))
(defvar myListOfTen [1 2 3 4 5 6 7 8 9 10])
(defun _testQuickNths []
(Assert.equals 1 (first myListOfTen))
(Assert.equals 2 (second myListOfTen))
(Assert.equals 3 (third myListOfTen))
(Assert.equals 4 (fourth myListOfTen))
(Assert.equals 5 (fifth myListOfTen))
(Assert.equals 6 (sixth myListOfTen))
(Assert.equals 7 (seventh myListOfTen))
(Assert.equals 8 (eighth myListOfTen))
(Assert.equals 9 (ninth myListOfTen))
(Assert.equals 10 (tenth myListOfTen))
(Assert.equals 10 (last myListOfTen)))
(defun _testListDestructuring []
(deflocal [a b c d &mut e f g h i j] myListOfTen)
(Assert.equals 1 a)
(Assert.equals 2 b)
(Assert.equals 3 c)
(Assert.equals 4 d)
(Assert.equals 5 e)
(set e 6)
(Assert.equals 6 e)
(Assert.equals 6 f)
(Assert.equals 7 g)
(Assert.equals 8 h)
(Assert.equals 9 i)
(Assert.equals 10 j)
(let [[a b c &mut d e f g h i j] myListOfTen]
(Assert.equals 1 a)
(Assert.equals 2 b)
(Assert.equals 3 c)
(Assert.equals 4 d)
(set d 6)
(Assert.equals 6 d)
(Assert.equals 5 e)
(Assert.equals 6 f)
(Assert.equals 7 g)
(Assert.equals 8 h)
(Assert.equals 9 i)
(Assert.equals 10 j)))
(defvar myMetaList [myListOfTen myListOfTen myListOfTen])
(defun _testDoFor []
(deflocal &mut c 0)
(doFor v myListOfTen
(Assert.equals (+ c 1) v)
(set c v))
(doFor [a b c d e f g h i j] myMetaList
(Assert.equals 1 a)
(Assert.equals 2 b)
(Assert.equals 3 c)
(Assert.equals 4 d)
(Assert.equals 5 e)
(Assert.equals 6 f)
(Assert.equals 7 g)
(Assert.equals 8 h)
(Assert.equals 9 i)
(Assert.equals 10 j)))
(defun _testFor []
(deflocal incrementedList (for v myListOfTen (+ 1 v)))
(let [[a b c d e f g h i j] incrementedList]
(Assert.equals 2 a)
(Assert.equals 3 b)
(Assert.equals 4 c)
(Assert.equals 5 d)
(Assert.equals 6 e)
(Assert.equals 7 f)
(Assert.equals 8 g)
(Assert.equals 9 h)
(Assert.equals 10 i)
(Assert.equals 11 j))
(deflocal smallerMetaList (for [a b c d e f g h i j] myMetaList [a e i]))
(doFor [a e i] smallerMetaList
(Assert.equals 1 a)
(Assert.equals 5 e)
(Assert.equals 10 i)))
(defun myOptionalFunc [a &opt b c]
(Assert.equals 5 a)
(Assert.equals null b)
(Assert.equals 6 (or c 6))) // (or [optionalVar] [defaultValue]) is the convention for default values
(defun myRestSum [firstOne &rest :List<Int> others]
(deflocal &mut sum firstOne)
(doFor nextOne others (set sum (+ sum nextOne)))
sum)
(defvar myRest1 (myRestSum 5))
(defvar myRest2 (myRestSum 1 1 1 1 1))
(defvar myRest3 (myRestSum 1 2 2))
(defun myCombinedOptRest [firstOne &opt secondOne &rest :List<String> thirdAndMore]
(deflocal &mut concatString (+ firstOne (or secondOne "boop")))
(doFor str thirdAndMore (set concatString (+ concatString str)))
concatString)
(defvar myCombined1 (myCombinedOptRest "a" "b" "c" "d"))
(defvar myCombined2 (myCombinedOptRest "a"))
(defvar myCombined3 (myCombinedOptRest "a" "b"))
(defun _testFieldExps []
(Assert.equals "hey" (.trim " hey "))
(Assert.equals "e" (.charAt (.trim " hey ") 1)))
(defun _testBreakContinue []
(let [[a b c]
(for val [1 2 3 4 5 6 7 8]
(if (> val 6)
(break)
(if (% val 2)
(continue)
val)))]
(Assert.equals 2 a)
(Assert.equals 4 b)
(Assert.equals 6 c)))
(defun _testAssert []
(try
(assert false (+ "false " "should " "have " "been " "true"))
(catch [:String message]
(Assert.equals "Assertion false failed: false should have been true" message)))
(assert true)
(assert ![]))
(defun _testApply []
(Assert.equals 6 (apply + [1 2 3])))
(defun applyWithMethod [obj]
(apply .multiply obj [6]))
(defun _testAnonymousObject []
(let [obj
(object
a "string A"
b 5)]
(Assert.equals "string A" obj.a)
(Assert.equals 5 obj.b)))

View File

@@ -0,0 +1,4 @@
(defun myFun []
(deflocal something 5)
// TODO This comment causes a hard-to-track-down error!
)

View File

@@ -0,0 +1,22 @@
package test.cases;
import utest.Test;
import utest.Assert;
import kiss.Prelude;
@:build(kiss.Kiss.build("kiss/src/test/cases/ReaderMacroTestCase.kiss"))
class ReaderMacroTestCase extends Test {
function testReadBang() {
Assert.equals("String that takes the rest of the line", ReaderMacroTestCase.myLine());
}
function testDefAlias() {
Assert.equals(9, ReaderMacroTestCase.mySum);
}
function testMultipleInitiators() {
Assert.equals("a", ReaderMacroTestCase.str1);
Assert.equals("b", ReaderMacroTestCase.str2);
Assert.equals("c", ReaderMacroTestCase.str3);
}
}

View File

@@ -0,0 +1,18 @@
(defreadermacro "!" [stream] #|ReaderExp.StrExp(stream.expect("a string line", function () stream.takeLine()))|#)
(defun myLine []
!String that takes the rest of the line
)
(defalias pluppers +)
(defalias fluffers 5)
(defalias buffers 4)
(defvar mySum (pluppers fluffers buffers))
// Read a b c directly as strings
(defreadermacro ["a" "b" "c"] [stream] #|ReaderExp.StrExp(stream.expect("a, b, or c", function () stream.takeChars(1)))|#)
(defvar str1 a)
(defvar str2 b)
(defvar str3 c)