(with_import "./collections.kp" (let ( match (vau de (x & cases) (let ( x (eval x de) evaluate_case (rec-lambda recurse (name_dict x c) (cond ; an explicit nil name_dict case allows us to simply fold over recurse in the array case later (nil? name_dict) nil (symbol? c) (put name_dict c x) (and (int? x) (int? c) (= x c)) name_dict (and (string? x) (string? c) (= x c)) name_dict (and (bool? x) (bool? c) (= x c)) name_dict (and (combiner? x) (combiner? c) (= x c)) name_dict ; check for invocation of quote directly ; not necessarily ideal if they define their own quote or something (and (symbol? x) (array? c) (= 2 (len c)) (= quote (idx c 0)) (= x (idx c 1))) name_dict ; ditto with above, but with unquote to allow matching against the *value* of variables (and (array? c) (= 2 (len c)) (= 'unquote (idx c 0)) (= x (eval (idx c 1) de))) name_dict ; ditto with above, but with array. Also note this means you have to use '[' and ']' as calling ; array explicitly will give you the symbol array instead... (and (array? x) (array? c) (= (+ 1 (len x)) (len c)) (= array (idx c 0))) (foldl recurse name_dict x (slice c 1 -1)) true nil )) iter (rec-lambda recurse (x i cases) (if (>= i (len cases)) (error "none of match arms matched!") (let ( mapping (evaluate_case empty_dict x (idx cases i))) (if (!= nil mapping) (eval (idx cases (+ i 1)) (add-dict-to-env de mapping)) (recurse x (+ i 2) cases))))) ) (iter x 0 cases))) ) (provide match) ))