Files
kiss/src/test/cases/BasicTestCase.kiss

518 lines
15 KiB
Plaintext

// (load) brings in the fields and compile-time definitions of another Kiss file
(load "BasicTestCaseExtra.kiss")
// (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))
// (collect) turns iterators to arrays
(defun _testCollect []
(Assert.equals "[0,1,2]" (Std.string (collect (range 3)))))
// 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 true (if 0 true false))
(Assert.equals true (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)
(defun myTryCatch [:Any e]
(try
(throw e)
(catch [:String error] 5)
(catch [:Int error] 6)
(catch [error] 7)))
(defun myTypeCheck []
(the Int 5))
(defun _testConcat []
(Assert.equals (.toString [1 2 3 4]) (.toString (concat [1] [2 3] [4]))))
(defun _testGroups []
(Assert.equals (.toString [[1 2] [3 4]]) (.toString (groups [1 2 3 4] 2)))
(Assert.equals (.toString [[1 2 3] [4]]) (.toString (groups [1 2 3 4] 3 Keep)))
(try (begin (groups [1 2 3 4] 3 Throw) (Assert.fail))
(catch [error] (Assert.pass))))
(defun _testZip []
(Assert.equals (.toString [[1 2] [3 4]]) (.toString (zip [1 3] [2 4] Throw)))
(Assert.equals (.toString [[1 2] [3 null]]) (.toString (zip [1 3] [2] Keep)))
(Assert.equals (.toString [[1 2] [null 4]]) (.toString (zip [1 null] [2 4] Keep)))
(try (begin (zip [1 3] [2] Throw) (Assert.fail))
(catch [error] (Assert.pass)))
(try (begin (zip [1] [2 4] Throw) (Assert.fail))
(catch [error] (Assert.pass)))
(Assert.equals (.toString [[1 2 3] [2 null 3]]) (.toString (zip [1 2] [2] [3 3] Keep))))
(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 !(= 0 (% 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)))
(defun toOption [:Dynamic value]
(if value (Some value) None))
(defun _testCase []
(case (toOption [])
(None (Assert.pass))
((Some value) (Assert.fail)))
(case (toOption "hey")
(None (Assert.fail))
((Some "hey") (Assert.pass))
(otherwise (Assert.fail)))
(Assert.equals 5 (case (toOption 0)
(otherwise 5)))
// Test case with guards and multiple values
(case 5
((or 5 6) (Assert.pass))
(otherwise (Assert.fail)))
(case [2 3]
((or [_ 3] [1 1]) (Assert.pass))
(otherwise (Assert.fail)))
(case 5
((when false (or 5 6)) (Assert.fail))
(otherwise (Assert.pass)))
// In Haxe,
// `switch (Some(true)) { case Some(true | false): "a"; default: "b"; }`
// returns "a", so nested use of `or` in case patterns should also be valid:
(case (Some true)
((Some (or true false))
(Assert.pass))
(otherwise (Assert.fail)))
(case (Some 5)
((Some (or 6 5 4))
(Assert.pass))
(otherwise (Assert.fail))))
(defun _testMaps []
(deflocal :Map<String,String> myMap [=>"hey" "you"
=>"found" "me"])
(Assert.equals "you" (dictGet myMap "hey"))
(Assert.equals "me" (dictGet myMap "found"))
(doFor =>key value myMap
(Assert.isTrue (<= 0 (.indexOf ["hey" "found"] key)))
(Assert.isTrue (<= 0 (.indexOf ["you" "me"] value))))
// Map destructuring:
(let [[=>"hey" v1 =>"found" v2] myMap]
(Assert.equals "you" v1)
(Assert.equals "me" v2)))
(defun _testRange []
// With just one arg, it's the max:
(deflocal &mut :kiss.List<Int> myList (for i (range 5) i))
(Assert.equals 4 (nth myList -1))
// with two args, they are min and max:
(set myList (for i (range 3 5) i))
(Assert.equals 3 (first myList))
(Assert.equals 4 (last myList))
// With three args, they are min, max, and step:
(set myList (for i (range 7 17 2) i))
(Assert.equals 7 (first myList))
(Assert.equals 9 (second myList))
(Assert.equals 15 (last myList)))
(defun _testRest []
(Assert.equals (.toString [2 3 4]) (.toString (rest [1 2 3 4]))))
(defun doSomething [:Int->Int func]
(func 5))
(defun itsAMonster [:Null<Map<String,Map<String,Array<String>>>> monsterArg] "but it still compiles")
(defun _testTypeParsing []
// Do stuff with functions that take complex type parameters, mostly just to check if it compiles
(Assert.equals 5 (doSomething (lambda [i] i)))
(Assert.equals 7 (doSomething (lambda [i] (+ i 2))))
// Pass null to the really crazy one because I'm lazy:
(Assert.equals "but it still compiles" (itsAMonster null)))
(defmacro defconstfunc [name const] `(defun ,name [] ,const))
(defconstfunc func5 5)
(defconstfunc funcHello "hello")
(defun _testDefmacro []
(Assert.equals 5 (func5))
(Assert.equals "hello" (funcHello)))
(defvar &mut welcomeCount 0)
(defmacro macroWithLogic [name]
(deflocal message1 (ReaderExp.StrExp "Welcome "))
(deflocal message2 (ReaderExp.StrExp " (Guest #"))
(deflocal message3 (ReaderExp.StrExp ")"))
`(begin (set welcomeCount (+ welcomeCount 1))
(+ ,message1 ,name ,message2 (Std.string welcomeCount) ,message3)))
(defun _testDefmacroWithLogic []
(Assert.equals "Welcome Stevo (Guest #1)" (macroWithLogic "Stevo"))
(Assert.equals "Welcome Bob (Guest #2)" (macroWithLogic "Bob")))
// Make sure built-in call aliases don't override user-defined variables
(defun _testCallAlias []
(let [map [=>"hey" "you"]]
(Assert.equals "you" (dictGet map "hey"))))
(defun _testAssignArith []
(deflocal &mut num 5)
(+= num 5 6)
(Assert.equals 16 num)
(%= num 5)
(Assert.equals 1 num)
(^= num 3)
(Assert.equals 1 num)
(*= num 25 2)
(Assert.equals 50 num)
(/= num 25 2)
(Assert.equals 1 num)
(-= num 5 6)
(Assert.equals -10 num))
(defun _testPatternLets []
(let [some5 (Some 5)
some6 (Some 6)
none None
:Null<Option<Any>> oops null]
(ifLet [(Some a) some5
(Some b) some6]
(Assert.equals 11 (+ a b))
(Assert.fail))
(ifLet [(Some a) none]
(Assert.fail))
(whenLet [(Some a) oops]
(print "something went wrong!")
(Assert.fail))
(unlessLet [(Some (or 5 6)) some5]
(print "something else went wrong!")
(Assert.fail))
// Don't double evaluate the expression:
(let [&mut v 1]
(unlessLet [2 (begin (+= v 1) v)]
(Assert.fail))
(Assert.equals 2 v))))
(defun _testRawString []
(Assert.equals #| "\\" |# #"\"#)
(Assert.equals #| "\"#" |# ##""#"##))
(defun _testKissStrings []
(Assert.equals #| "\\\t\r\n\"$" |# "\\\t\r\n\"\$")
(let [str "it's"
num 3
l1 ["a" "b" "c"]
l2 [1 2 3]]
// string interpolation:
(Assert.equals "it's 3asy as [a,b,c] [1,2,3]" "$str ${num}asy as $l1 $l2")))
(defun _testArrowLambdas []
(let [withArgs
->[arg1 arg2] (+ arg1 arg2)
withArg
->arg (* 2 arg)
withoutArgs
->{
(+ 5)
6}
&mut num 5
void
->:Void [] (set num 6)]
(Assert.equals 11 (withArgs 5 6))
(Assert.equals 12 (withArg 6))
(Assert.equals 6 (withoutArgs))
(void)
(Assert.equals 6 num)))
(defvar &mut voidRan false)
(defun :Void myVoid [] (set voidRan true))
(defun _testVoid []
(myVoid)
(Assert.isTrue voidRan))
(defun _testLetThrow []
(try
{
(letThrow
(throw "the error we want")
(catch [e] (Assert.fail)))
(Assert.fail)}
(catch [:String e]
(Assert.equals "the error we want" e))))