Completely change naming conventions of field forms and definition macros. Close #32

This commit is contained in:
2021-07-24 14:22:10 -06:00
parent 9d6a4b2054
commit f5a5cdfb40
67 changed files with 433 additions and 447 deletions

View File

@@ -34,12 +34,9 @@ class CompileError {
firstPos + '-' + lastPos.substr(justLineAndColumnIdx);
}
var failed = if (warning) "warning!"; else "failed!";
var failed = if (warning) "warning"; else "failed";
return '\nKiss compilation $failed\n'
+ posPrefix
+ ": "
+ message
return '$posPrefix: Kiss compilation $failed: $message'
+ "\nFrom:"
+ [for (exp in exps) exp.def.toString()].toString();
}

View File

@@ -29,22 +29,22 @@ class FieldForms {
map[newName] = form;
}
map["defvar"] = varOrProperty.bind("classVar");
renameAndDeprecate("defvar", "classVar");
map["defprop"] = varOrProperty.bind("classProp");
renameAndDeprecate("defprop", "classProp");
map["defvar"] = varOrProperty.bind("var");
renameAndDeprecate("defvar", "var");
map["defprop"] = varOrProperty.bind("prop");
renameAndDeprecate("defprop", "prop");
map["defun"] = funcOrMethod.bind("classFunction");
renameAndDeprecate("defun", "classFunction");
map["defmethod"] = funcOrMethod.bind("classMethod");
renameAndDeprecate("defmethod", "classMethod");
map["defun"] = funcOrMethod.bind("function");
renameAndDeprecate("defun", "function");
map["defmethod"] = funcOrMethod.bind("method");
renameAndDeprecate("defmethod", "method");
return map;
}
static function fieldAccess(formName:String, fieldName:String, nameExp:ReaderExp, ?access:Array<Access>) {
if (access == null) {
access = if (["defvar", "defprop", "classVar", "classProp"].indexOf(formName) != -1) {
access = if (["defvar", "defprop", "var", "prop"].indexOf(formName) != -1) {
[AFinal];
} else {
[];
@@ -69,7 +69,7 @@ class FieldForms {
access.push(AFinal);
fieldAccess(formName, fieldName, nameExp, access);
default:
if (["defvar", "defun", "classVar", "classFunction"].indexOf(formName) != -1) {
if (["defvar", "defun", "var", "function"].indexOf(formName) != -1) {
access.push(AStatic);
}
access.push(if (fieldName.startsWith("_")) APrivate else APublic);

View File

@@ -340,7 +340,7 @@ class Macros {
}
macros["defmacro"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
wholeExp.checkNumArgs(3, null, '(defmacro [name] [[args...]] [body...])');
wholeExp.checkNumArgs(3, null, '(defMacro [name] [[args...]] [body...])');
var name = switch (exps[0].def) {
case Symbol(name): name;
@@ -439,9 +439,10 @@ class Macros {
null;
};
renameAndDeprecate("defmacro", "defMacro");
macros["undefmacro"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
wholeExp.checkNumArgs(1, 1, '(undefmacro [name])');
wholeExp.checkNumArgs(1, 1, '(undefMacro [name])');
var name = switch (exps[0].def) {
case Symbol(name): name;
@@ -451,9 +452,10 @@ class Macros {
k.macros.remove(name);
null;
};
renameAndDeprecate("undefmacro", "undefMacro");
macros["defreadermacro"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
wholeExp.checkNumArgs(3, null, '(defreadermacro [optional &start] ["[startingString]" or [startingStrings...]] [[streamArgName]] [body...])');
wholeExp.checkNumArgs(3, null, '(defReaderMacro [optional &start] ["[startingString]" or [startingStrings...]] [[streamArgName]] [body...])');
// reader macros declared in the form (defreadermacro &start ...) will only be applied
// at the beginning of lines
@@ -464,9 +466,9 @@ class Macros {
var strings = switch (exps[0].def) {
case MetaExp("start", stringsExp):
table = k.startOfLineReadTable;
stringsThatMatch(stringsExp, "defreadermacro");
stringsThatMatch(stringsExp, "defReaderMacro");
default:
stringsThatMatch(exps[0], "defreadermacro");
stringsThatMatch(exps[0], "defReaderMacro");
};
for (s in strings) {
switch (exps[1].def) {
@@ -487,9 +489,10 @@ class Macros {
return null;
};
renameAndDeprecate("defreadermacro", "defReaderMacro");
macros["undefreadermacro"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
wholeExp.checkNumArgs(1, 1, '(undefreadermacro [optional &start] ["[startingString]" or [startingStrings...]])');
wholeExp.checkNumArgs(1, 1, '(undefReaderMacro [optional &start] ["[startingString]" or [startingStrings...]])');
// reader macros undeclared in the form (undefreadermacro &start ...) will be removed from the table
// for reader macros that must be at the beginning of lines
// at the beginning of lines
@@ -509,6 +512,7 @@ class Macros {
}
return null;
};
renameAndDeprecate("undefreadermacro", "undefReaderMacro");
// Having this floating out here is sketchy, but should work out fine because the variable is always re-set
// through the next function before being used in defalias or undefalias
@@ -535,20 +539,22 @@ class Macros {
}
macros["defalias"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
wholeExp.checkNumArgs(2, 2, "(defalias [[&call or &ident] whenItsThis] [makeItThis])");
var name = getAliasName(k, exps[0], "defalias");
wholeExp.checkNumArgs(2, 2, "(defAlias [[&call or &ident] whenItsThis] [makeItThis])");
var name = getAliasName(k, exps[0], "defAlias");
aliasMap[name] = exps[1].def;
return null;
};
renameAndDeprecate("defalias", "defAlias");
macros["undefalias"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
wholeExp.checkNumArgs(1, 1, "(undefalias [[&call or &ident] alias])");
var name = getAliasName(k, exps[0], "undefalias");
wholeExp.checkNumArgs(1, 1, "(undefAlias [[&call or &ident] alias])");
var name = getAliasName(k, exps[0], "undefAlias");
aliasMap.remove(name);
return null;
};
renameAndDeprecate("undefalias", "undefAlias");
// Macros that null-check and extract patterns from enums (inspired by Rust)
function ifLet(wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) {
@@ -661,11 +667,11 @@ class Macros {
var propertyDefs = [for (bindingPair in bindingPairs) {
var b = bindingPair[0].expBuilder();
b.call(b.symbol("defprop"), [bindingPair[0]]);
b.call(b.symbol("prop"), [bindingPair[0]]);
}];
var propertySetExps = [for (bindingPair in bindingPairs) {
var b = bindingPair[1].expBuilder();
b.call(b.symbol("set"), [b.symbol(Helpers.varName("a defprop property binding", bindingPair[0])), bindingPair[1]]);
b.call(b.symbol("set"), [b.symbol(Helpers.varName("a prop property binding", bindingPair[0])), bindingPair[1]]);
}];
var argList = [];
@@ -676,7 +682,7 @@ class Macros {
case MetaExp("prop", propExp):
argList.push(propExp);
propertyDefs.push(
b.call(b.symbol("defprop"), [propExp]));
b.call(b.symbol("prop"), [propExp]));
// TODO allow &prop &mut or &mut &prop
switch (propExp.def) {
case TypedExp(_, {pos: _, def: Symbol(name)}):
@@ -693,7 +699,7 @@ class Macros {
var b = wholeExp.expBuilder();
return b.begin(propertyDefs.concat([
b.call(b.symbol("defmethod"), [
b.call(b.symbol("method"), [
b.symbol("new"),
b.list(argList)
].concat(propertySetExps).concat(exps.slice(2)))
@@ -715,8 +721,8 @@ class Macros {
return b.call(b.symbol("when"), [flag, b.call(b.symbol("set"), [flag, b.symbol("false")])].concat(exps));
}
macros["once"] = once.bind("defvar");
macros["oncePerInstance"] = once.bind("defprop");
macros["once"] = once.bind("var");
macros["oncePerInstance"] = once.bind("prop");
// Replace "try" with this in a try-catch statement to let all exceptions throw
// their original call stacks. This is more convenient for debugging than trying to

View File

@@ -226,7 +226,7 @@ class SpecialForms {
case KeyValueExp(_, _): k.convert(namesExp);
default: {
bodyExps.insert(0,
CallExp(Symbol("deflocal").withPosOf(args[2]), [namesExp, Symbol(uniqueVarName).withPosOf(args[2])]).withPosOf(args[2]));
CallExp(Symbol("localVar").withPosOf(args[2]), [namesExp, Symbol(uniqueVarName).withPosOf(args[2])]).withPosOf(args[2]));
macro $i{uniqueVarName};
}
};

View File

@@ -1,80 +1,80 @@
// (load) brings in the fields and compile-time definitions of another Kiss file
(load "BasicTestCaseExtra.kiss")
// (defvar) declares static variables
(defvar message "Howdy")
// (var) declares static variables
(var message "Howdy")
// #| ... |# parses and injects raw Haxe code
(defvar mathResult #|5 + 6 * 3|#) // Order of operations will apply
(var mathResult #|5 + 6 * 3|#) // Order of operations will apply
// (defun) declares static functions
(defun myFloor [num]
// (function) declares static functions
(function myFloor [num]
// funcalls can use dot access
(Math.floor num))
// functions are resolved in the macro context
(defvar funResult (myFloor 7.5))
(var funResult (myFloor 7.5))
// (defprop) declares instance variables
(defprop myField 5)
// (prop) declares instance variables
(prop myField 5)
// (defmethod) declares instance methods
(defmethod myMethod [] this.myField)
// (method) declares instance methods
(method myMethod [] this.myField)
// [...] returns a Kiss array (they have special features and convert implicitly)
(defvar myArray [1 2 3])
(var myArray [1 2 3])
// Array access is via nth
(defvar myArrayLast (nth myArray -1))
(var myArrayLast (nth myArray -1))
// (collect) turns iterators to arrays
(defun _testCollect []
(function _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))
(var mySum (+ 1 2 3))
(defvar myDifference (- 5 4 3))
(var myDifference (- 5 4 3))
(defun _testMultiplication []
(function _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))
(var myQuotient (/ 6 3 2 2))
(defvar myRemainder (% 10 6))
(var myRemainder (% 10 6))
(defvar myPower (^ 2 8))
(var myPower (^ 2 8))
(defvar &mut myNum 6)
(defvar myInc ++myNum)
(var &mut myNum 6)
(var myInc ++myNum)
(defvar myMin (min 9 3 7 1))
(defvar myMax (max 9 3 7 1))
(var myMin (min 9 3 7 1))
(var myMax (max 9 3 7 1))
(defun _testLessThan []
(function _testLessThan []
(Assert.isTrue (< 1 2 3 4))
(Assert.isFalse (< 1 1 3 4))
(Assert.isFalse (< 1 12 12)))
(defun _testLesserEqual []
(function _testLesserEqual []
(Assert.isTrue (<= 1 2 3 4))
(Assert.isTrue (<= 1 1 3 4))
(Assert.isFalse (<= 1 12 11)))
(defun _testGreaterThan []
(function _testGreaterThan []
(Assert.isTrue (> 4 3 2 1))
(Assert.isFalse (> 4 4 2 1))
(Assert.isFalse (> 9 3 3)))
(defun _testGreaterEqual []
(function _testGreaterEqual []
(Assert.isTrue (>= 4 3 2 1))
(Assert.isTrue (>= 4 4 2 1))
(Assert.isFalse (>= 9 4 5)))
(defun _testEqual []
(function _testEqual []
(Assert.isTrue (= 1 1 1 1))
(Assert.isFalse (= 1 2 1 1))
(Assert.isTrue (= "hey" "hey" "hey"))
@@ -83,7 +83,7 @@
(Assert.isFalse (= true false true))
(Assert.isTrue (= false false false)))
(defun _testIf []
(function _testIf []
(Assert.equals true (if 1 true false))
(Assert.equals true (if 0 true false))
(Assert.equals true (if -1 true false))
@@ -97,28 +97,28 @@
(Assert.equals 5 (if true 5))
(Assert.equals null (if false 5)))
(defvar :Int myInt 8)
(var :Int myInt 8)
(defun myTryCatch [:Any e]
(function myTryCatch [:Any e]
(try
(throw e)
(catch [:String error] 5)
(catch [:Int error] 6)
(catch [error] 7)))
(defun myTypeCheck []
(function myTypeCheck []
(the Int 5))
(defun _testConcat []
(function _testConcat []
(Assert.equals (.toString [1 2 3 4]) (.toString (concat [1] [2 3] [4]))))
(defun _testGroups []
(function _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 []
(function _testZip []
(Assert.equals (.toString [[1 2] [3 4]]) (.toString (zipThrow [1 3] [2 4])))
(Assert.equals (.toString [[1 2] [3 null]]) (.toString (zipKeep [1 3] [2])))
(Assert.equals (.toString [[1 2] [null 4]]) (.toString (zipKeep [1 null] [2 4])))
@@ -130,11 +130,11 @@
(Assert.equals (.toString [[1 2]]) (.toString (zipDrop [1 2 3 4] [2])))
(Assert.equals (.toString [[1 2] [3 4]]) (.toString (apply zipThrow [[1 3] [2 4]]))))
(defun _testEnumerate []
(function _testEnumerate []
(Assert.equals (.toString [[0 1] [1 2]]) (.toString (enumerate [1 2])))
(Assert.equals (.toString [[1 1] [2 2]]) (.toString (enumerate [1 2] 1))))
(defun _testLet []
(function _testLet []
(let [a 5
b 6
:String c "stuff"]
@@ -146,50 +146,50 @@
(set a "str2")
(Assert.equals "str2" a)))
(defvar myConstructedString (new String "sup"))
(var myConstructedString (new String "sup"))
(defvar myCond1 (cond
(var myCond1 (cond
((= 5 6) "not this")
((= 8 9) "not this either")
((= 1 1) "this one")
(true "not the default")))
(defvar myCond2 (cond
(var myCond2 (cond
((= 5 6) "not this")
((= 8 9) "not this either")
((= 2 1) "not the third one")
(true "the default")))
(defvar myCond3 (cond
(var myCond3 (cond
((= 5 5) "this")
(true "default")))
(defvar myCondFallthrough (cond
(var myCondFallthrough (cond
(false "not this")))
(defvar myOr1 (or null 5))
(var myOr1 (or null 5))
(defvar myAnd1 (and 5 6))
(defvar myAnd2 (and false 5 6))
(defvar myAnd3 (and 5 false 6))
(var myAnd1 (and 5 6))
(var myAnd2 (and false 5 6))
(var myAnd3 (and 5 false 6))
(defun mySetLocal []
(function mySetLocal []
(localVar &mut loc "one thing")
(set loc "another thing")
loc)
(defvar myNot1 (not 5))
(defvar myNot2 !5)
(var myNot1 (not 5))
(var myNot2 !5)
(defvar myFilteredList (begin
(var myFilteredList (begin
(localVar l [-1 -2 5 -3 6])
(l.filter (lambda [v] (< 0 v)))))
(defvar myWhen1 (when true 5 6))
(var myWhen1 (when true 5 6))
(defvar myListOfTen [1 2 3 4 5 6 7 8 9 10])
(var myListOfTen [1 2 3 4 5 6 7 8 9 10])
(defun _testQuickNths []
(function _testQuickNths []
(Assert.equals 1 (first myListOfTen))
(Assert.equals 2 (second myListOfTen))
(Assert.equals 3 (third myListOfTen))
@@ -202,7 +202,7 @@
(Assert.equals 10 (tenth myListOfTen))
(Assert.equals 10 (last myListOfTen)))
(defun _testListDestructuring []
(function _testListDestructuring []
(localVar [a b c d &mut e f g h i j] myListOfTen)
(Assert.equals 1 a)
(Assert.equals 2 b)
@@ -232,9 +232,9 @@
(Assert.equals 10 j)))
(defvar myMetaList [myListOfTen myListOfTen myListOfTen])
(var myMetaList [myListOfTen myListOfTen myListOfTen])
(defun _testDoFor []
(function _testDoFor []
(localVar &mut c 0)
(doFor v myListOfTen
(Assert.equals (+ c 1) v)
@@ -251,7 +251,7 @@
(Assert.equals 9 i)
(Assert.equals 10 j)))
(defun _testFor []
(function _testFor []
(localVar incrementedList (for v myListOfTen (+ 1 v)))
(let [[a b c d e f g h i j] incrementedList]
(Assert.equals 2 a)
@@ -270,34 +270,34 @@
(Assert.equals 5 e)
(Assert.equals 10 i)))
(defun myOptionalFunc [a &opt b c]
(function 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]
(function myRestSum [firstOne &rest :List<Int> others]
(localVar &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))
(var myRest1 (myRestSum 5))
(var myRest2 (myRestSum 1 1 1 1 1))
(var myRest3 (myRestSum 1 2 2))
(defun myCombinedOptRest [firstOne &opt secondOne &rest :List<String> thirdAndMore]
(function myCombinedOptRest [firstOne &opt secondOne &rest :List<String> thirdAndMore]
(localVar &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"))
(var myCombined1 (myCombinedOptRest "a" "b" "c" "d"))
(var myCombined2 (myCombinedOptRest "a"))
(var myCombined3 (myCombinedOptRest "a" "b"))
(defun _testFieldExps []
(function _testFieldExps []
(Assert.equals "hey" (.trim " hey "))
(Assert.equals "e" (.charAt (.trim " hey ") 1)))
(defun _testBreakContinue []
(function _testBreakContinue []
(let [[a b c]
(for val [1 2 3 4 5 6 7 8]
(if (> val 6)
@@ -309,7 +309,7 @@
(Assert.equals 4 b)
(Assert.equals 6 c)))
(defun _testAssert []
(function _testAssert []
(try
(assert false (+ "false " "should " "have " "been " "true"))
(catch [:String message]
@@ -318,13 +318,13 @@
(assert true)
(assert ![]))
(defun _testApply []
(function _testApply []
(Assert.equals 6 (apply + [1 2 3])))
(defun applyWithMethod [obj]
(function applyWithMethod [obj]
(apply .multiply obj [6]))
(defun _testAnonymousObject []
(function _testAnonymousObject []
(let [obj
(object
a "string A"
@@ -332,10 +332,10 @@
(Assert.equals "string A" obj.a)
(Assert.equals 5 obj.b)))
(defun toOption [:Dynamic value]
(function toOption [:Dynamic value]
(if value (Some value) None))
(defun _testCase []
(function _testCase []
(case (toOption [])
(None (Assert.pass))
((Some value) (Assert.fail)))
@@ -375,7 +375,7 @@
(Assert.isTrue (Type.enumEq (Some 5) inner)))
(otherwise (Assert.fail))))
(defun _testMaps []
(function _testMaps []
(localVar :Map<String,String> myMap [=>"hey" "you"
=>"found" "me"])
(Assert.equals "you" (dictGet myMap "hey"))
@@ -389,7 +389,7 @@
(Assert.equals "you" v1)
(Assert.equals "me" v2)))
(defun _testRange []
(function _testRange []
// With just one arg, it's the max:
(localVar &mut :kiss.List<Int> myList (for i (range 5) i))
(Assert.equals 4 (nth myList -1))
@@ -403,32 +403,32 @@
(Assert.equals 9 (second myList))
(Assert.equals 15 (last myList)))
(defun _testRest []
(function _testRest []
(Assert.equals (.toString [2 3 4]) (.toString (rest [1 2 3 4]))))
(defun doSomething [:Int->Int func]
(function doSomething [:Int->Int func]
(func 5))
(defun itsAMonster [:Null<Map<String,Map<String,Array<String>>>> monsterArg] "but it still compiles")
(function itsAMonster [:Null<Map<String,Map<String,Array<String>>>> monsterArg] "but it still compiles")
(defun _testTypeParsing []
(function _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))
(defMacro defconstfunc [name const] `(function ,name [] ,const))
(defconstfunc func5 5)
(defconstfunc funcHello "hello")
(defun _testDefmacro []
(function _testDefmacro []
(Assert.equals 5 (func5))
(Assert.equals "hello" (funcHello)))
(defvar &mut welcomeCount 0)
(defmacro macroWithLogic [name]
(var &mut welcomeCount 0)
(defMacro macroWithLogic [name]
(localVar message1 (ReaderExp.StrExp "Welcome "))
(localVar message2 (ReaderExp.StrExp " (Guest #"))
(localVar message3 (ReaderExp.StrExp ")"))
@@ -436,16 +436,16 @@
`(begin (set welcomeCount (+ welcomeCount 1))
(+ ,message1 ,name ,message2 (Std.string welcomeCount) ,message3)))
(defun _testDefmacroWithLogic []
(function _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 []
(function _testCallAlias []
(let [map [=>"hey" "you"]]
(Assert.equals "you" (dictGet map "hey"))))
(defun _testAssignArith []
(function _testAssignArith []
(localVar &mut num 5)
(+= num 5 6)
(Assert.equals 16 num)
@@ -460,7 +460,7 @@
(-= num 5 6)
(Assert.equals -10 num))
(defun _testPatternLets []
(function _testPatternLets []
(let [some5 (Some 5)
some6 (Some 6)
none None
@@ -484,11 +484,11 @@
(Assert.fail))
(Assert.equals 2 v))))
(defun _testRawString []
(function _testRawString []
(Assert.equals #| "\\" |# #"\"#)
(Assert.equals #| "\"#" |# ##""#"##))
(defun _testKissStrings []
(function _testKissStrings []
(Assert.equals #| "\\\t\r\n\"$" |# "\\\t\r\n\"\$")
(let [str "it's"
num 3
@@ -497,7 +497,7 @@
// string interpolation:
(Assert.equals "it's 3asy as [a,b,c] [1,2,3]" "$str ${num}asy as $l1 $l2")))
(defun _testArrowLambdas []
(function _testArrowLambdas []
(let [withArgs
->[arg1 arg2] (+ arg1 arg2)
withArg
@@ -515,13 +515,13 @@
(void)
(Assert.equals 6 num)))
(defvar &mut voidRan false)
(defun :Void myVoid [] (set voidRan true))
(defun _testVoid []
(var &mut voidRan false)
(function :Void myVoid [] (set voidRan true))
(function _testVoid []
(myVoid)
(Assert.isTrue voidRan))
(defun _testLetThrow []
(function _testLetThrow []
(try
{
(letThrow
@@ -529,4 +529,4 @@
(catch [e] (Assert.fail)))
(Assert.fail)}
(catch [:String e]
(Assert.equals "the error we want" e))))
(Assert.equals "the error we want" e))))

View File

@@ -1 +1 @@
(defun loadedFunction [] "loaded")
(function loadedFunction [] "loaded")

View File

@@ -1,5 +1,5 @@
(defun myFun []
(function myFun []
(localVar something 5)
)
// This comment used to cause a hard-to-track-down error!
// This comment used to cause a hard-to-track-down error!

View File

@@ -1,4 +1,4 @@
(defun myFun []
(function myFun []
(localVar something 5)
// This comment used to cause a hard-to-track-down error!
)
)

View File

@@ -1,21 +1,21 @@
(defvar runningInHaxe (#if interp true false))
(defvar runningInPyOrJs (#if (or py js) true false))
(var runningInHaxe (#if interp true false))
(var runningInPyOrJs (#if (or py js) true false))
(defun number []
(function number []
(let [&mut num 5]
(#when interp
(+= num 5)
(-= num 4))
num))
(defun number2 []
(function number2 []
(let [&mut num 12]
(#unless interp
(+= num 5)
(-= num 8))
num))
(defvar targetLanguage
(var targetLanguage
(#cond
(cpp "C++")
(cs "C#")
@@ -24,10 +24,10 @@
(js "JavaScript")
(python "Python")))
(defun _testCase []
(function _testCase []
(#case var1ForCase
("var1" (Assert.pass))
(otherwise (Assert.fail)))
(#case var2ForCase
("var2" (Assert.pass))
(otherwise (Assert.fail))))
(otherwise (Assert.fail))))

View File

@@ -1,3 +1,3 @@
// TODO make a better position reification scheme here
(defreadermacro "goop" [stream] #|ReaderExp.CallExp({pos: {file: "bleh", line: 1, column: 1, absoluteChar: 1}, def: ReaderExp.Symbol("Assert.isTrue")}, [{pos: {file: "bleh", line: 1, column: 1, absoluteChar: 1}, def: ReaderExp.Symbol("true")}])|#)
(defreadermacro "gloop" [stream] #|ReaderExp.CallExp({pos: {file: "bleh", line: 1, column: 1, absoluteChar: 1}, def: ReaderExp.Symbol("Assert.isFalse")}, [{pos: {file: "bleh", line: 1, column: 1, absoluteChar: 1}, def: ReaderExp.Symbol("false")}])|#)
(defReaderMacro "goop" [stream] #|ReaderExp.CallExp({pos: {file: "bleh", line: 1, column: 1, absoluteChar: 1}, def: ReaderExp.Symbol("Assert.isTrue")}, [{pos: {file: "bleh", line: 1, column: 1, absoluteChar: 1}, def: ReaderExp.Symbol("true")}])|#)
(defReaderMacro "gloop" [stream] #|ReaderExp.CallExp({pos: {file: "bleh", line: 1, column: 1, absoluteChar: 1}, def: ReaderExp.Symbol("Assert.isFalse")}, [{pos: {file: "bleh", line: 1, column: 1, absoluteChar: 1}, def: ReaderExp.Symbol("false")}])|#)

View File

@@ -1,4 +1,4 @@
(defun _testListEating []
(function _testListEating []
// TODO document that list-eating only works on explictly Array-typed variables
(let [:Array<Int> l [1 2 3 4]]
(case l
@@ -29,4 +29,4 @@
(Assert.equals (.toString [1 2 3]) (.toString rest))
(Assert.equals 4 last))
(otherwise
(Assert.fail)))))
(Assert.fail)))))

View File

@@ -1,22 +1,22 @@
(defmacro defMultiple [varName funcName]
(defMacro defMultiple [varName funcName]
`{
(defvar ,varName 5)
(defun ,funcName [] 6)})
(var ,varName 5)
(function ,funcName [] 6)})
(defMultiple myVar myFunc)
(defmacro variadicPlus [&rest l]
(defMacro variadicPlus [&rest l]
`(+ ,@l))
(defmacro listPlus [l]
(defMacro listPlus [l]
`(+ ,@l))
// Both forms of passing expression lists to macros should work:
(defun sum1 [] (variadicPlus 1 2 3))
(defun sum2 [] (listPlus [1 2 3]))
(function sum1 [] (variadicPlus 1 2 3))
(function sum2 [] (listPlus [1 2 3]))
// You should be able to run list comprehensions on expressions
// and put the pieces back together in a modular way
(defmacro altDefun [name args &body body]
(defMacro altDefun [name args &body body]
(let [argPairs
(groups (expList args) 2)
untypedArgs
@@ -30,22 +30,22 @@
(print name)
(letBindings.push `(the ,type ,name)))
(print letBindings)
`(defun ,name ,untypedArgs
`(function ,name ,untypedArgs
(let ,letBindings ,@body))))
(altDefun nameAndNumber [name String number Int]
"$name $number")
// If for whatever reason, you wanted to make a variable called print
(undefalias &call print)
(defvar print 9)
(undefAlias &call print)
(var print 9)
(defalias &ident alias 5)
(undefalias &ident alias)
(defvar alias 9)
(defun aliasValue [] alias)
(defAlias &ident alias 5)
(undefAlias &ident alias)
(var alias 9)
(function aliasValue [] alias)
// If for whatever reason, you wanted to make a function called and
(undefmacro and)
(defun and [a b] (+ a b))
(defun andValue [] (and 5 6))
(undefMacro and)
(function and [a b] (+ a b))
(function andValue [] (and 5 6))

View File

@@ -1,8 +1,8 @@
(defvar &mut staticCount 0)
(defvar &mut instanceCount 0)
(var &mut staticCount 0)
(var &mut instanceCount 0)
(defmethod new []
(method new []
(once
(+= staticCount 1))
(oncePerInstance
(+= instanceCount 1)))
(+= instanceCount 1)))

View File

@@ -1,31 +1,31 @@
(defreadermacro &start "!" [stream]
(defReaderMacro &start "!" [stream]
(let [line (stream.expect "a string line" (lambda [] (stream.takeLine)))]
(ReaderExp.StrExp line)))
(defun myLine []
(function myLine []
!String that takes the rest of the line
)
(defun myBool []
(function myBool []
(begin !false))
(defalias &call pluppers +)
(defalias &ident fluffers 5)
(defalias &ident buffers 4)
(defAlias &call pluppers +)
(defAlias &ident fluffers 5)
(defAlias &ident buffers 4)
(defvar mySum (pluppers fluffers buffers))
(var mySum (pluppers fluffers buffers))
// Read b c directly as strings
(defreadermacro ["b" "c"] [stream] #|ReaderExp.StrExp(stream.expect("b, or c", function () stream.takeChars(1)))|#)
(defReaderMacro ["b" "c"] [stream] #|ReaderExp.StrExp(stream.expect("b, or c", function () stream.takeChars(1)))|#)
(defvar str1 b)
(defvar str2 c)
(var str1 b)
(var str2 c)
// rassert asserts the next expression without parens
(defreadermacro "rassert" [stream] `(assert ,(read stream)))
(defReaderMacro "rassert" [stream] `(assert ,(read stream)))
(defun _testQuasiquoteMacro []
(function _testQuasiquoteMacro []
rassert [5]
rassert b
rassert fluffers
(Assert.pass))
(Assert.pass))

View File

@@ -1,2 +1,2 @@
(defun :Void main []
(print "Hello world!"))
(function :Void main []
(print "Hello world!"))

View File

@@ -1,6 +1,6 @@
(load "UtilMacros.kiss")
(defun :Void main []
(function :Void main []
(year 2018
(Solutions2018.run))
(year 2020
(Solutions2020.run)))
(Solutions2020.run)))

View File

@@ -1,4 +1,4 @@
(defun readLines [file]
(function readLines [file]
(.filter
(.map
// TODO implement escape sequences in kiss string literals
@@ -6,7 +6,7 @@
StringTools.trim)
(lambda [l] (< 0 l.length))))
(defun readParagraphLines [file]
(function readParagraphLines [file]
(.filter
(for paragraph
(.split
@@ -18,7 +18,7 @@
(lambda [lines] (< 0 lines.length))))
// TODO won't need to specify type here if last is not a quickNth
(defun :kiss.List<Int> readInts [file] (let [lines (readLines file)] (lines.map Std.parseInt)))
(function :kiss.List<Int> readInts [file] (let [lines (readLines file)] (lines.map Std.parseInt)))
(defun countChar [char str]
(count (str.split "") (lambda [c] ?(= c char))))
(function countChar [char str]
(count (str.split "") (lambda [c] ?(= c char))))

View File

@@ -1,6 +1,6 @@
(load "../UtilMacros.kiss")
(defun run []
(function run []
(day 1
(let [inputs
(.slice (.split (sys.io.File.getContent "src/year2018/inputs/day1.txt") "\n") 0 -1)
@@ -31,4 +31,4 @@
(dayTodo 22)
(dayTodo 23)
(dayTodo 24)
(dayTodo 25))
(dayTodo 25))

View File

@@ -1,7 +1,7 @@
(defun differences [:kiss.List<Int> ratings]
(function differences [:kiss.List<Int> ratings]
(for pair (pairs ratings) (- 0 (apply - pair))))
(defun distribution [:kiss.List<Int> numbers]
(function distribution [:kiss.List<Int> numbers]
(let [:Map<Int,Int> dist (new Map)]
(doFor num numbers
(dictSet dist num
@@ -10,7 +10,7 @@
1)))
dist))
(defun &dynamic arrangementCount [:kiss.List<Int> ratings startingIndex]
(function &dynamic arrangementCount [:kiss.List<Int> ratings startingIndex]
(if (= startingIndex (- ratings.length 1)) 1
(let [&mut :Int64 sum 0
startingRating (nth ratings startingIndex)

View File

@@ -1,7 +1,7 @@
(defun bagColor [:String bag]
(function bagColor [:String bag]
(bag.substr 0 (Math.floor (- (bag.indexOf "bag") 1))))
(defun parseRule [:String line :ParentMap parentMap :ChildMap childMap]
(function parseRule [:String line :ParentMap parentMap :ChildMap childMap]
(unless (<= 0 (line.indexOf "contain no other bags"))
(let [[containerStr contents] (line.split "contain ")
contentStrs (contents.split ", ")]
@@ -15,17 +15,17 @@
(.push (dictGet childMap (bagColor colorStr)) (bagColor containerStr))))
(dictSet parentMap (bagColor containerStr) innerMap))))
(defun findIndirectContainers [color :ChildMap childMap :Map<String,Bool> outMap]
(function findIndirectContainers [color :ChildMap childMap :Map<String,Bool> outMap]
(when (childMap.exists color)
(doFor parentColor (dictGet childMap color)
(dictSet outMap parentColor true)
(findIndirectContainers parentColor childMap outMap))))
(defun totalChildBags [bag :ParentMap parentMap]
(function totalChildBags [bag :ParentMap parentMap]
(if (parentMap.exists bag)
(begin
(localVar &mut sum 0)
(doFor =>childColor quantity (dictGet parentMap bag)
(set sum (+ sum quantity (* quantity (totalChildBags childColor parentMap)))))
sum)
0))
0))

View File

@@ -1,9 +1,9 @@
(defprop &mut accumulator 0)
(prop &mut accumulator 0)
(defmethod setBreakPoint [] (addBreakPoint instructionPointer))
(method setBreakPoint [] (addBreakPoint instructionPointer))
(defmethod nop [v :Dynamic self] (self.setBreakPoint))
(defmethod acc [v :Dynamic self] (self.setBreakPoint) (set self.accumulator (+ self.accumulator v)))
(defmethod jmp [v :Dynamic self]
(method nop [v :Dynamic self] (self.setBreakPoint))
(method acc [v :Dynamic self] (self.setBreakPoint) (set self.accumulator (+ self.accumulator v)))
(method jmp [v :Dynamic self]
(self.setBreakPoint)
(set self.instructionPointer (+ self.instructionPointer (- v 1))))
(set self.instructionPointer (+ self.instructionPointer (- v 1))))

View File

@@ -1,8 +1,8 @@
(load "BootCodeCommon.kiss")
(defvar :Map<Int,Bool> instructionsTested (new Map<Int,Bool>))
(defprop &mut forked false)
(defprop &mut forkedAt -1)
(var :Map<Int,Bool> instructionsTested (new Map<Int,Bool>))
(prop &mut forked false)
(prop &mut forkedAt -1)
(defreadermacro ["jmp" "nop"] [stream]
(let [inst
@@ -35,4 +35,4 @@
])))))
// Define the default reader LAST because default readers tend to break everything
(load "BootCodeDSL.kiss")
(load "BootCodeDSL.kiss")

View File

@@ -1,14 +1,14 @@
(defun countAnyYes [:Array<String> group]
(function countAnyYes [:Array<String> group]
(countWhereYes group (lambda [c] (< 0 c))))
(defun countAllYes [:Array<String> group]
(function countAllYes [:Array<String> group]
(countWhereYes group (lambda [c] (= c group.length))))
(defun countWhereYes [:Array<String> group predicate]
(function countWhereYes [:Array<String> group predicate]
(let [yesDict (new Map<String,Int>)]
(doFor person group
(doFor question (person.split "")
(dictSet yesDict question
(+ 1
(if (yesDict.exists question) (dictGet yesDict question) 0)))))
(count yesDict predicate)))
(count yesDict predicate)))

View File

@@ -1,27 +1,27 @@
(defprop &mut x 0)
(defprop &mut y 0)
(prop &mut x 0)
(prop &mut y 0)
// 0 is east
// 1 is south
// 2 is west
// 3 is north
(defprop &mut facing 0)
(prop &mut facing 0)
(defun fixFacing [f]
(function fixFacing [f]
(Math.floor (% (if (> 0 f) (+ 4 f) f) 4)))
(defmethod N [num]
(classMethod N [num]
(set y (+ y num)))
(defmethod S [num]
(classMethod S [num]
(set y (- y num)))
(defmethod E [num]
(classMethod E [num]
(set x (+ x num)))
(defmethod W [num]
(classMethod W [num]
(set x (- x num)))
(defmethod R [angle]
(classMethod R [angle]
(set facing (fixFacing (+ facing (/ angle 90)))))
(defmethod L [angle]
(classMethod L [angle]
(set facing (fixFacing (- facing (/ angle 90)))))
(defmethod F [num]
(classMethod F [num]
(case facing
(0 (E num))
(1 (S num))
@@ -35,4 +35,4 @@
null
`(,(ReaderExp.Symbol
(stream.expect "a ship command" (lambda [] (stream.takeChars 1))))
,(ReaderExp.Symbol (stream.expect "a number argument" (lambda [] (stream.takeUntilAndDrop #|"\n"|#)))))))
,(ReaderExp.Symbol (stream.expect "a number argument" (lambda [] (stream.takeUntilAndDrop #|"\n"|#)))))))

View File

@@ -1,6 +1,6 @@
(defun :FerrySquare floor [:Array<FerrySquare> n :SeatsChanged changed] floor)
(function :FerrySquare floor [:Array<FerrySquare> n :SeatsChanged changed] floor)
(defun :FerrySquare emptySeat [:Array<FerrySquare> n :SeatsChanged changed]
(function :FerrySquare emptySeat [:Array<FerrySquare> n :SeatsChanged changed]
// Empty seats with completely empty neighbors, fill up
(cond
((= true (apply = (for neighbor n #|neighbor != fullSeat|#)))
@@ -8,7 +8,7 @@
fullSeat)
(true emptySeat)))
(defun :FerrySquare fullSeat [:Array<FerrySquare> n :SeatsChanged changed]
(function :FerrySquare fullSeat [:Array<FerrySquare> n :SeatsChanged changed]
// Full seats with 4 or more full neighbors become empty
(cond
((<= 4 (count n (lambda [neighbor] #|neighbor == fullSeat|#)))
@@ -16,7 +16,7 @@
emptySeat)
(true fullSeat)))
(defun neighbors [x y :Array<Array<FerrySquare>> grid]
(function neighbors [x y :Array<Array<FerrySquare>> grid]
(localVar &mut n [])
(doFor xx (range (- x 1) (+ x 2))
(doFor yy (range (- y 1) (+ y 2))
@@ -25,9 +25,9 @@
(n.push (nth (nth grid yy) xx))))))
n)
(defprop &mut :Array<Array<FerrySquare>> state [])
(prop &mut :Array<Array<FerrySquare>> state [])
(defmethod simulate []
(method simulate []
(localVar changed (object changed false))
(set state
(for rowIdx (range state.length)
@@ -35,10 +35,10 @@
(for seatIdx (range row.length) ((nth row seatIdx) (neighbors seatIdx rowIdx state) changed)))))
changed.changed)
(defmethod fullSimulate []
(method fullSimulate []
(when (simulate) (fullSimulate)))
(defmethod countFullSeats []
(method countFullSeats []
(apply +
(for :Array<FerrySquare> row state
(apply +
@@ -51,4 +51,4 @@
(undefreadermacro "...")
(defreadermacro &start "" [stream]
`(state.push ,(ReaderExp.ListExp (readExpArray stream #|"\n"|#))))
`(state.push ,(ReaderExp.ListExp (readExpArray stream #|"\n"|#))))

View File

@@ -1,4 +1,4 @@
(defun readPassport [:Stream stream &opt :Map<String,String> pp]
(function readPassport [:Stream stream &opt :Map<String,String> pp]
(set pp (or pp (new Map<String,String>)))
(when (stream.isEmpty) (return pp))
(let [key (stream.expect "passport key" (lambda [] (stream.takeUntilAndDrop ":")))
@@ -8,7 +8,7 @@
(begin (stream.dropWhitespace) pp)
(begin (stream.dropWhitespace) (readPassport stream pp))))
(defun checkPassport [:Map<String,String> pp strict]
(function checkPassport [:Map<String,String> pp strict]
(doFor key ["byr" "iyr" "eyr" "hgt" "hcl" "ecl" "pid"]
(if !(pp.exists key) (return false)))
(when strict
@@ -32,8 +32,8 @@
(unless (and (= 9 pid.length) (Std.parseInt pid)) (return false))))
(return true))
(defun countValidPassports [:Stream stream &opt strict c]
(function countValidPassports [:Stream stream &opt strict c]
(unless c (set c 0))
(if (stream.isEmpty)
c
(countValidPassports stream strict (if (checkPassport (readPassport stream) strict) (+ c 1) c))))
(countValidPassports stream strict (if (checkPassport (readPassport stream) strict) (+ c 1) c))))

View File

@@ -1,17 +1,17 @@
(defun parsePasswordCheck1 [:String ruleStr]
(function parsePasswordCheck1 [:String ruleStr]
(let [[min max letter]
(.split (ruleStr.replace " " "-") "-")]
(lambda [password] (<= (Std.parseInt min) (Util.countChar letter password) (Std.parseInt max)))))
(defun parsePasswordCheck2 [:String ruleStr]
(function parsePasswordCheck2 [:String ruleStr]
(let [[a b letter]
(.split (ruleStr.replace " " "-") "-")
aIdx (- (Std.parseInt a) 1)
bIdx (- (Std.parseInt b) 1)]
(lambda [password] (= 1 (Util.countChar letter (+ (.charAt password aIdx) (.charAt password bIdx)))))))
(defun validateInputLine [:String line ruleParser]
(function validateInputLine [:String line ruleParser]
(let [[rule password]
(line.split ": ")]
((ruleParser rule) password)))
((ruleParser rule) password)))

View File

@@ -1,6 +1,6 @@
// Airplane seating
(defun search [:Array<String> letters min max rowOrColumn]
(function search [:Array<String> letters min max rowOrColumn]
(if (= min max)
min
(let [middle (Math.floor (/ (+ min max) 2))]
@@ -11,7 +11,7 @@
(["R" "column"] (search letters (+ 1 middle) max rowOrColumn))
(otherwise (throw "invalid search call"))))))
(defun seatId [:String boardingPass]
(function seatId [:String boardingPass]
(+
(* 8 (search (.split (boardingPass.substr 0 7) "") 0 127 "row"))
(search (.split (boardingPass.substr 7) "") 0 7 "column")))
(search (.split (boardingPass.substr 7) "") 0 7 "column")))

View File

@@ -1,6 +1,6 @@
(load "../UtilMacros.kiss")
(defun run []
(function run []
(day 1
(let [p (SummingTuples.pairWithSum 2020 [1721 979 366 299 675 1456])]
(assert (and (has p 1721) (has p 299)) "pairWithSum is broken"))
@@ -156,4 +156,4 @@
(dayTodo 22)
(dayTodo 23)
(dayTodo 24)
(dayTodo 25))
(dayTodo 25))

View File

@@ -1,4 +1,4 @@
(defun :kiss.List<Int> pairWithSum [sum :kiss.List<Int> numbers]
(function :kiss.List<Int> pairWithSum [sum :kiss.List<Int> numbers]
// Put the numbers in a map for random access. This gives an O(n) solution
(localVar :Map<Int,Int> numbersMap (new Map))
(doFor number numbers
@@ -8,7 +8,7 @@
(return [number requiredForPair]))))
null)
(defun :kiss.List<Int> trioWithSum [sum :kiss.List<Int> numbers]
(function :kiss.List<Int> trioWithSum [sum :kiss.List<Int> numbers]
(doFor number numbers
(let [requiredForTrio (- sum number)
pairThatSatisfies (pairWithSum requiredForTrio numbers)]
@@ -16,7 +16,7 @@
(return [number (nth pairThatSatisfies 0) (nth pairThatSatisfies 1)]))))
null)
(defun contiguousSumTuple [sum :kiss.List<Int> numbers]
(function contiguousSumTuple [sum :kiss.List<Int> numbers]
(doFor i (range numbers.length)
(localVar &mut testSum (nth numbers i))
(doFor j (range (+ i 1) numbers.length)
@@ -26,4 +26,4 @@
(return (numbers.slice i (+ j 1))))
((> testSum sum)
(break)))))
null)
null)

View File

@@ -1,8 +1,8 @@
(defun path [:kiss.List<String> hillTile x0 y0 dx dy]
(function path [:kiss.List<String> hillTile x0 y0 dx dy]
(if (>= y0 .length hillTile)
[]
(concat [(.charAt (nth hillTile y0) (Math.floor (% x0 .length (nth hillTile y0))))] (path hillTile (+ x0 dx) (+ y0 dy) dx dy))))
(defun pathString [:kiss.List<String> hillTile x0 y0 dx dy] (.join (path hillTile x0 y0 dx dy) ""))
(function pathString [:kiss.List<String> hillTile x0 y0 dx dy] (.join (path hillTile x0 y0 dx dy) ""))
(defun pathTrees [:kiss.List<String> hillTile x0 y0 dx dy] (Util.countChar "#" (pathString hillTile x0 y0 dx dy)))
(function pathTrees [:kiss.List<String> hillTile x0 y0 dx dy] (Util.countChar "#" (pathString hillTile x0 y0 dx dy)))

View File

@@ -1,4 +1,4 @@
(defun firstOffender [preambleLength :kiss.List<Int> input]
(function firstOffender [preambleLength :kiss.List<Int> input]
(doFor idx (range preambleLength input.length)
(unless (SummingTuples.pairWithSum (nth input idx) (input.slice (- idx preambleLength) idx))
(return (nth input idx))))

View File

@@ -1,2 +1,2 @@
(defun :Void main []
(print "Hello world!"))
(function :Void main []
(print "Hello world!"))

View File

@@ -2,11 +2,11 @@
[:Map<String,Surface> _surfaces (new Map)])
// TODO don't allow overriding a key -- use a macro so all load___() calls check their maps first
(defmethod loadSurface [key path]
(method loadSurface [key path]
(dictSet _surfaces key (Surface.fromString (backend.loadText path))))
// TODO runtime-assert that the key exists. Use a macro so all get___() calls check their maps first
(defmethod getSurface [key]
(method getSurface [key]
(dictGet _surfaces key))
// TODO freeSurface() etc.
// TODO freeSurface() etc.

View File

@@ -8,33 +8,33 @@
(fill (or fillColor Black)))
(defmethod fill [:Color color]
(method fill [:Color color]
(red.fill 0 area color.r)
(green.fill 0 area color.g)
(blue.fill 0 area color.b))
(defmethod _index [x y]
(method _index [x y]
(+ x (* y width)))
(defmacro withIndex [idxName xName yName &body body]
`(let [,idxName (_index ,xName ,yName)]
,@body))
(defmethod getPixel [x y]
(method getPixel [x y]
(withIndex idx x y
(object r (red.get idx) g (green.get idx) b (blue.get idx))))
(defmethod setPixel [x y color]
(method setPixel [x y color]
(withIndex idx x y
(red.set idx color.r)
(green.set idx color.g)
(blue.set idx color.b)))
(defun equal [c1 c2]
(function equal [c1 c2]
(and (= c1.r c2.r) (= c1.g c2.g) (= c1.b c2.b)))
(defvar Black (object r 0 g 0 b 0))
(defvar Red (object r 255 g 0 b 0))
(defvar Green (object r 0 g 255 b 0))
(defvar Blue (object r 0 g 0 b 255))
(defvar White (object r 255 g 255 b 255))
(var Black (object r 0 g 0 b 0))
(var Red (object r 255 g 0 b 0))
(var Green (object r 0 g 255 b 0))
(var Blue (object r 0 g 0 b 255))
(var White (object r 255 g 255 b 255))

View File

@@ -16,10 +16,10 @@
(graphicsBackend.initialize title width height letterWidth letterHeight)
(gameLogic.initialize assets))
(defmethod update [:Float deltaSeconds]
(method update [:Float deltaSeconds]
(gameLogic.update this deltaSeconds))
(defmethod draw []
(method draw []
(let [&mut changedGraphics false]
(gameLogic.draw (lambda [] (set changedGraphics true) graphics) assets)
(when changedGraphics (graphicsBackend.draw graphics))))
(when changedGraphics (graphicsBackend.draw graphics))))

View File

@@ -1,2 +1,2 @@
(defmethod new [width height]
(super width height))
(method new [width height]
(super width height))

View File

@@ -3,5 +3,5 @@
:Int height _height
:Array<Array<T>> rows (for _ (range height) (for _ (range width) defaultValue))])
(defmethod getCell [x y] (nth (nth rows y) x))
(defmethod setCell [x y value] (setNth (nth rows y) x value))
(method getCell [x y] (nth (nth rows y) x))
(method setCell [x y value] (setNth (nth rows y) x value))

View File

@@ -3,11 +3,11 @@
:Int height _height
:Array<String> rows (for _ (range height) (* (or letter " ") width))])
(defmethod getChar [x y]
(method getChar [x y]
(.charAt (nth rows y) x))
(defmethod setChar [x y char]
(method setChar [x y char]
(let [row (nth rows y)
left (row.substr 0 x)
right (row.substr (+ x 1))]
(setNth rows y "${left}${char}${right}")))
(setNth rows y "${left}${char}${right}")))

View File

@@ -7,34 +7,34 @@
:Grid<Bool> opacity (new Grid width height true)
:Grid<String> specialInfo (new Grid width height "")])
(defmethod getBackgroundColor [x y]
(method getBackgroundColor [x y]
(backgroundColors.getPixel x y))
(defmethod setBackgroundColor [x y color]
(method setBackgroundColor [x y color]
(backgroundColors.setPixel x y color))
(defmethod getLetter [x y]
(method getLetter [x y]
(object char (letters.getChar x y) color (letterColors.getPixel x y)))
(defmethod setLetter [x y letter]
(method setLetter [x y letter]
(letters.setChar x y letter.char)
(letterColors.setPixel x y letter.color))
(defmethod isCellOpaque [x y]
(method isCellOpaque [x y]
(opacity.getCell x y))
(defmethod setCellOpacity [x y value]
(method setCellOpacity [x y value]
(opacity.setCell x y value))
(defmethod getSpecialInfo [x y]
(method getSpecialInfo [x y]
(specialInfo.getCell x y))
(defmethod setSpecialInfo [x y value]
(method setSpecialInfo [x y value]
(specialInfo.setCell x y value))
// TODO rectangle type
// TODO optional source rectangle argument
(defmethod blitSurface [:Surface surface x y]
(method blitSurface [:Surface surface x y]
(doFor [srcX destX] (the kiss.List<kiss.List<Int>> (zipDrop (range surface.width) (range x (+ x surface.width))))
(when (< -1 destX width)
(doFor [srcY destY] (the kiss.List<kiss.List<Int>> (zipDrop (range 0 surface.height) (range y (+ y surface.height))))
@@ -46,7 +46,7 @@
// Cover transparent cells in the lower surface with opaque ones
(setCellOpacity destX destY true)))))))
(defun fromString [text]
(function fromString [text]
(let [stream (Stream.fromString text)
:Map<String,Color> colors (new Map)
:Map<String,String> infoCodes (new Map)
@@ -95,4 +95,4 @@
(doFor x (range width)
(surface.specialInfo.setCell x y (dictGet infoCodes (stream.expect "a special info code" ->{(stream.takeChars 1)}))))
(stream.dropString "\n"))
surface)))))
surface)))))

View File

@@ -1,3 +1,3 @@
(defnew [])
(defmethod loadText [filePath] (Assets.getText filePath))
(method loadText [filePath] (Assets.getText filePath))

View File

@@ -1,8 +1,8 @@
(defprop &mut :FlxGroup backgroundColors null)
(defprop &mut :FlxGroup letters null)
(defprop &mut :Int letterWidth 0)
(defprop &mut :Int letterHeight 0)
(defprop &mut :FlxBitmapFont font null)
(prop &mut :FlxGroup backgroundColors null)
(prop &mut :FlxGroup letters null)
(prop &mut :Int letterWidth 0)
(prop &mut :Int letterHeight 0)
(prop &mut :FlxBitmapFont font null)
(defnew [_state
_fontAsset
@@ -13,14 +13,14 @@
:FlxRect region _region
:FlxPoint spacing _spacing])
(defmethod :Void initialize [:String title :Int width :Int height :Int _letterWidth :Int _letterHeight]
(method :Void initialize [:String title :Int width :Int height :Int _letterWidth :Int _letterHeight]
(set letterWidth _letterWidth)
(set letterHeight _letterHeight)
(set font (FlxBitmapFont.fromMonospace fontAsset fontLetters (new FlxPoint letterWidth letterHeight) region spacing))
(set backgroundColors (new FlxGroup))
(set letters (new FlxGroup)))
(defmethod :Void draw [:Graphics graphics]
(method :Void draw [:Graphics graphics]
(backgroundColors.kill)
(set backgroundColors (new FlxGroup))
(letters.kill)
@@ -42,4 +42,4 @@
(set text.textColor (FlxColor.fromRGB color.r color.g color.b))
(letters.add text))))))
(state.add backgroundColors)
(state.add letters))
(state.add letters))

View File

@@ -1,3 +1,3 @@
(defnew [])
(defmethod loadText [filePath] (File.getContent filePath))
(method loadText [filePath] (File.getContent filePath))

View File

@@ -1,12 +1,12 @@
(defprop &mut :Int letterWidth 0)
(defprop &mut :Int letterHeight 0)
(defprop &mut :Int drawCalled 0)
(prop &mut :Int letterWidth 0)
(prop &mut :Int letterHeight 0)
(prop &mut :Int drawCalled 0)
(defnew [])
(defmethod :Void initialize [:String title :Int width :Int height :Int _letterWidth :Int _letterHeight]
(method :Void initialize [:String title :Int width :Int height :Int _letterWidth :Int _letterHeight]
(set letterWidth _letterWidth)
(set letterHeight _letterHeight))
(defmethod :Void draw [:Graphics graphics]
(+= drawCalled 1))
(method :Void draw [:Graphics graphics]
(+= drawCalled 1))

View File

@@ -1,4 +1,4 @@
(defun :Void main []
(function :Void main []
(let [[jsonFile workingDir]
(Sys.args)
json
@@ -13,4 +13,4 @@
(versionParts.join ".")]
(print "Bumping version of $jsonFile from $oldVersion -> $newVersion")
(set json.version newVersion)
(File.saveContent (joinPath workingDir jsonFile) (Json.stringify json "\t")))))
(File.saveContent (joinPath workingDir jsonFile) (Json.stringify json "\t")))))

View File

@@ -1,8 +1,8 @@
(defnew [])
(defmethod :Void initialize [:Assets assets]
(method :Void initialize [:Assets assets]
(assets.loadSurface "laptop" AssetPaths.laptop__srf))
(defmethod :Void update [:Game game :Float deltaSeconds] 0)
(defmethod :Void draw [:Void->Graphics graphics :Assets assets]
(method :Void update [:Game game :Float deltaSeconds] 0)
(method :Void draw [:Void->Graphics graphics :Assets assets]
(oncePerInstance
(.blitSurface (graphics) (assets.getSurface "laptop") 0 0)))
(.blitSurface (graphics) (assets.getSurface "laptop") 0 0)))

View File

@@ -1,8 +1,8 @@
(defmethod new [:Float x :Float y]
(method new [:Float x :Float y]
(super x y)
(loadGraphic AssetPaths.coin__png false 8 8))
(defmethod &override :Void kill []
(method &override :Void kill []
(set alive false)
(FlxTween.tween
this
@@ -14,5 +14,5 @@
ease FlxEase.circOut
onComplete finishKill)))
(defmethod finishKill [_]
(set exists false))
(method finishKill [_]
(set exists false))

View File

@@ -1,4 +1,4 @@
(defvar &inline :Float SPEED 140)
(var &inline :Float SPEED 140)
(defnew [:Float x :Float y :EnemyType _type]
[:EnemyType type _type
@@ -29,7 +29,7 @@
(set offset.x 4)
(set offset.y 2))
(defmethod &override :Void update [:Float elapsed]
(method &override :Void update [:Float elapsed]
(when (and
(or !(= velocity.x 0) !(= velocity.y 0))
(= touching FlxObject.NONE))
@@ -54,7 +54,7 @@
(brain.update elapsed)
(super.update elapsed))
(defmethod :Void idle [:Float elapsed]
(method :Void idle [:Float elapsed]
(cond
(seesPlayer
// TODO (the FSM) here should not be necessary!
@@ -74,7 +74,7 @@
(true
(-= idleTimer elapsed))))
(defmethod :Void chase [:Float elapsed]
(method :Void chase [:Float elapsed]
(if !seesPlayer
(set brain.activeState idle)
(FlxVelocity.moveTowardsPoint this playerPosition (Std.int SPEED))))
(FlxVelocity.moveTowardsPoint this playerPosition (Std.int SPEED))))

View File

@@ -1,7 +1,7 @@
(defprop &mut :Float->Void activeState null)
(prop &mut :Float->Void activeState null)
(defmethod new [:Float->Void initialState]
(method new [:Float->Void initialState]
(set activeState initialState))
(defmethod :Void update [:Float elapsed]
(activeState elapsed))
(method :Void update [:Float elapsed]
(activeState elapsed))

View File

@@ -1,3 +1,3 @@
(defmethod new []
(method new []
(super)
(addChild (new FlxGame 320 240 MenuState)))
(addChild (new FlxGame 320 240 MenuState)))

View File

@@ -1,9 +1,9 @@
(defprop &mut :FlxButton playButton null)
(prop &mut :FlxButton playButton null)
(defmethod &override :Void create []
(method &override :Void create []
(set playButton (new FlxButton 0 0 "Play" clickPlay))
(playButton.screenCenter)
(add playButton))
(defun clickPlay []
(FlxG.switchState (new PlayState)))
(function clickPlay []
(FlxG.switchState (new PlayState)))

View File

@@ -1,10 +1,10 @@
(defprop &mut :Player player null)
(defprop &mut :FlxOgmo3Loader map null)
(defprop &mut :FlxTilemap walls null)
(defprop &mut :FlxTypedGroup<Coin> coins null)
(defprop &mut :FlxTypedGroup<Enemy> enemies null)
(prop &mut :Player player null)
(prop &mut :FlxOgmo3Loader map null)
(prop &mut :FlxTilemap walls null)
(prop &mut :FlxTypedGroup<Coin> coins null)
(prop &mut :FlxTypedGroup<Enemy> enemies null)
(defmethod &override :Void create []
(method &override :Void create []
(set map (new FlxOgmo3Loader AssetPaths.turnBasedRPG__ogmo AssetPaths.room_001__json))
(set walls (map.loadTilemap AssetPaths.tiles__png "walls"))
(walls.follow)
@@ -19,7 +19,7 @@
(FlxG.camera.follow player TOPDOWN 1)
(super.create))
(defmethod :Void placeEntities [:EntityData entity]
(method :Void placeEntities [:EntityData entity]
(case entity.name
("player"
(set player (new Player entity.x entity.y))
@@ -31,14 +31,14 @@
("boss"
(enemies.add (new Enemy (+ entity.x 4) entity.y BOSS)))))
(defmethod &override :Void update [:Float elapsed]
(method &override :Void update [:Float elapsed]
(super.update elapsed)
(FlxG.collide player walls)
(FlxG.overlap player coins playerTouchCoin)
(FlxG.collide enemies walls)
(enemies.forEachAlive checkEnemyVision))
(defmethod :Void checkEnemyVision [:Enemy enemy]
(method :Void checkEnemyVision [:Enemy enemy]
(if (walls.ray (enemy.getMidpoint) (player.getMidpoint))
{
(set enemy.seesPlayer true)
@@ -46,6 +46,6 @@
}
(set enemy.seesPlayer false)))
(defmethod playerTouchCoin [:Player player :Coin coin]
(method playerTouchCoin [:Player player :Coin coin]
(when (and player.alive player.exists coin.alive coin.exists)
(coin.kill)))
(coin.kill)))

View File

@@ -1,6 +1,6 @@
(defvar &inline :Float SPEED 200)
(var &inline :Float SPEED 200)
(defmethod new [:Float x :Float y]
(method new [:Float x :Float y]
(super x y)
(loadGraphic AssetPaths.player__png true 16 16)
(setFacingFlip FlxObject.LEFT false false)
@@ -12,7 +12,7 @@
(setSize 8 8)
(offset.set 4 4))
(defmethod :Void updateMovement []
(method :Void updateMovement []
(let [[&mut up &mut down &mut left &mut right]
(map [[UP W] [DOWN S] [LEFT A] [RIGHT D]] FlxG.keys.anyPressed)]
(when (and up down)
@@ -62,6 +62,6 @@
(otherwise
(return))))))
(defmethod &override update [:Float elapsed]
(method &override update [:Float elapsed]
(updateMovement)
(super.update elapsed))
(super.update elapsed))

View File

@@ -22,7 +22,7 @@
/**
* Helper functions
*/
(defun selectedText []
(function selectedText []
(if (and activeTextEditor .selection activeTextEditor)
(let [document
// TODO should be able to use activeTextEditor.document and have the alias still work
@@ -35,12 +35,12 @@
// TODO make an async annotation that throws an error if the promise is not wrapped in awaitLet or awaitBegin or returned by an async function?
// but in some cases it doesn't matter and there are so many edge cases.
(defun insertAt [:vscode.Position pos text]
(function insertAt [:vscode.Position pos text]
(.edit activeTextEditor
(lambda [e]
(e.insert pos text))))
(defun insert [text]
(function insert [text]
// TODO this let is because identifier alias dot access is broken:
(let [editor activeTextEditor]
(insertAt editor.selection.active text)))
@@ -49,18 +49,18 @@
* State
*/
(defvar :Map<String,Command> commands (new Map))
(defvar :Map<String,ShortcutKey> commandShortcuts (new Map))
(var :Map<String,Command> commands (new Map))
(var :Map<String,ShortcutKey> commandShortcuts (new Map))
(defvar &mut :String lastCommand null)
(defvar parser (new Parser))
(defvar interp (new Interp))
(var &mut :String lastCommand null)
(var parser (new Parser))
(var interp (new Interp))
/**
* Functionality
*/
(defun :Dynamic evalString [:String kissStr]
(function :Dynamic evalString [:String kissStr]
(try
(interp.execute
(parser.parseString
@@ -69,16 +69,16 @@
(errorMessage "Error `${e}` from $kissStr")
null)))
(defun :Void evalAndPrint [&opt :String selectedText]
(function :Void evalAndPrint [&opt :String selectedText]
(if selectedText
(infoMessage (Std.string (evalString selectedText))))
(awaitLet [kissStr (inputBox)]
(infoMessage (Std.string (evalString kissStr)))))
(defun :Void runCommand [&opt command] (_runCommand command))
(function :Void runCommand [&opt command] (_runCommand command))
(defun :Void _runCommand [&opt command inputText]
(function :Void _runCommand [&opt command inputText]
(unless inputText (set inputText (selectedText)))
(if command
{(set lastCommand command) ((dictGet commands command) inputText)}
@@ -95,13 +95,13 @@
(set lastCommand chosenCommand.label)
((dictGet commands chosenCommand.label) inputText))))))
(defun :Void runLastCommand [&opt _]
(function :Void runLastCommand [&opt _]
(if lastCommand
(runCommand lastCommand)
(errorMessage "No Kiss command was run previously.")))
(defvar &mut :vscode.WebviewPanel shortcutPanel null)
(defun :Void showShortcutPanel [&opt :Map<String,ShortcutKey> prefixMap]
(var &mut :vscode.WebviewPanel shortcutPanel null)
(function :Void showShortcutPanel [&opt :Map<String,ShortcutKey> prefixMap]
// Preserve the selected text and focused document before opening the webview:
(let [inputText (selectedText)]
// When called without a prefixMap, if a shortcut panel is still open, close it and start over:
@@ -133,7 +133,7 @@
{(warningMessage "$key is not mapped to a shortcut in this context")(return)}))))
(set shortcutPanel.webview.html (shortcutPanelHtml prefixMap))))
(defun shortcutPanelHtml [:Map<String,ShortcutKey> prefixMap]
(function shortcutPanelHtml [:Map<String,ShortcutKey> prefixMap]
(let [shortcutParagraphs
(for =>key shortcutKey prefixMap
"<p><strong>${key}</strong> - $(case shortcutKey
@@ -159,11 +159,11 @@
</body>
</html>"))
(defun :Void runKeyboardShortcut [&opt _]
(function :Void runKeyboardShortcut [&opt _]
(showShortcutPanel))
// Extract [k]eyboard [s]hortcuts from a string:
(defun extractKeyboardShortcuts [str &opt :Stream stream :String shortcuts]
(function extractKeyboardShortcuts [str &opt :Stream stream :String shortcuts]
(unless stream (set stream (Stream.fromString str)))
(unless shortcuts (set shortcuts ""))
(case (stream.takeUntilAndDrop "[")
@@ -177,7 +177,7 @@
(None
shortcuts)))
(defun :Void registerShortcut [keys description &opt :Map<String,ShortcutKey> prefixMap]
(function :Void registerShortcut [keys description &opt :Map<String,ShortcutKey> prefixMap]
(unless prefixMap (set prefixMap commandShortcuts))
(let [firstKey (keys.shift)]
(cond
@@ -199,16 +199,16 @@
(registerShortcut keys description innerPrefixMap))
(dictSet prefixMap firstKey (Final description)))))))
(defun registerCommand [description command]
(function registerCommand [description command]
(dictSet commands description command)
(whenLet [keyboardShortcut (extractKeyboardShortcuts description)]
(registerShortcut (keyboardShortcut.split "") description)))
// Register a VSCode command (built-in, or from an extension)
(defun registerExistingCommand [description command]
(function registerExistingCommand [description command]
(registerCommand description (lambda :Void [&opt _] (executeCommand command))))
(defun :Void registerBuiltins []
(function :Void registerBuiltins []
(set Prelude.print
->[v] {
(infoMessage (Std.string v))
@@ -220,7 +220,7 @@
(registerCommand "[n]ew kiss class" newKissClass))
// TODO standardize this with KissInterp
(defun :Void prepareInterp []
(function :Void prepareInterp []
(interp.variables.set "kiss"
(object
Prelude
@@ -244,7 +244,7 @@
(awaitLet [,v (inputBox)]
,@body)))
(defun :Void newKissClass [&opt _]
(function :Void newKissClass [&opt _]
(awaitLet [className (inputBox)]
(let [currentFile
.fileName .document activeTextEditor
@@ -275,4 +275,4 @@ import kiss.List;
class ${className} {}
")
(File.saveContent kissFile "")
(Vscode.window.showTextDocument (Uri.file kissFile)))))
(Vscode.window.showTextDocument (Uri.file kissFile)))))

View File

@@ -1,2 +1,2 @@
(defun init []
(return))
(function init []
(return))

View File

@@ -1,6 +1,6 @@
(defun :Void init []
(function :Void init []
(registerCommand "print a nice message"
(lambda :Void [&opt selectedText]
(infoMessage "Hello world!")
(when selectedText
(infoMessage (+ "Also, " selectedText))))))
(infoMessage (+ "Also, " selectedText))))))

View File

@@ -1,15 +1,15 @@
(defun userHome [] (or (Sys.getEnv "MSYSHOME") (Sys.getEnv "HOME") (Sys.getEnv "UserProfile")))
(defun userConfigDir []
(function userHome [] (or (Sys.getEnv "MSYSHOME") (Sys.getEnv "HOME") (Sys.getEnv "UserProfile")))
(function userConfigDir []
(joinPath
(userHome)
".kiss"))
(defvar &mut activeConfigDir "")
(defvar &mut lastConfigDir "")
(defvar &mut builtinConfigDir "")
(defvar &mut :KissConfig config null)
(var &mut activeConfigDir "")
(var &mut lastConfigDir "")
(var &mut builtinConfigDir "")
(var &mut :KissConfig config null)
(defun walkDirectory [basePath directory :String->Void processFile :String->Void processSubdirectory]
(function walkDirectory [basePath directory :String->Void processFile :String->Void processSubdirectory]
(doFor fileOrFolder (FileSystem.readDirectory (joinPath basePath directory))
(case fileOrFolder
((when (FileSystem.isDirectory (joinPath basePath directory folder)) folder)
@@ -19,7 +19,7 @@
(file
(processFile (joinPath directory file))))))
(defun :Void tryLoadConfig [&opt :String text]
(function :Void tryLoadConfig [&opt :String text]
// TODO if a config object is active and a shortcut panel is open, dispose the panel before we lose the handle in the current config object
// If a backup exists, delete it
@@ -97,7 +97,7 @@
(Vscode.window.showErrorMessage errorMessage))))))))
(#unless test
(defun _activate [:ExtensionContext context]
(function _activate [:ExtensionContext context]
(context.subscriptions.push
(Vscode.commands.registerCommand
"kiss.reloadConfig"
@@ -134,7 +134,7 @@
(set lastConfigDir (joinPath (userHome) ".kiss-vscode" "lastActiveConfig"))
(tryLoadConfig)))
(defun :Void main []
(function :Void main []
(#when test
(set builtinConfigDir "config")
(set activeConfigDir "_activeConfig")
@@ -142,4 +142,4 @@
(tryLoadConfig)
// Load the config twice more to make sure it moves the last active config out of the way properly:
(tryLoadConfig)
(tryLoadConfig)))
(tryLoadConfig)))

View File

@@ -47,7 +47,7 @@
</dict>
</dict>
<key>match</key>
<string>(?:\()((?i:defmacro|defun|classFunction|classMethod|def[A-Z]\S+))\s+((?:\w|[+\-<>/*&amp;=.?!$%:@\[\]^{}~#|])+)</string>
<string>(?:\()((?i:defmacro|defMacro|defun|function|defmethod|method|def[A-Z]\S+))\s+((?:\w|[+\-<>/*&amp;=.?!$%:@\[\]^{}~#|])+)</string>
<key>name</key>
<string>meta.function.kiss</string>
</dict>
@@ -57,23 +57,6 @@
<key>name</key>
<string>meta.function-parameters.kiss</string>
</dict>
<dict>
<key>captures</key>
<dict>
<key>1</key>
<dict>
<key>name</key>
<string>storage.type.function-type.kiss</string>
</dict>
<key>2</key>
<dict>
<key>name</key>
<string>entity.name.type.kiss</string>
</dict>
</dict>
<key>match</key>
<string>(?:\()((?i:deftype|defstruct))\s+((?:\w|[+\-<>/*&amp;=.?!$%:@\[\]^{}~#|])+)</string>
</dict>
<dict>
<key>captures</key>
<dict>
@@ -89,7 +72,7 @@
</dict>
</dict>
<key>match</key>
<string>(?:\()((?i:defvar|defprop|classVar|classProp))\s+((?:\w|[+\-<>/*&amp;=.?!$%:@\[\]^{}~#|])+)</string>
<string>(?:\()((?i:defvar|defprop|var|prop))\s+((?:\w|[+\-<>/*&amp;=.?!$%:@\[\]^{}~#|])+)</string>
</dict>
<!-- <dict>
<key>captures</key>
@@ -133,7 +116,7 @@
<dict>
<key>match</key>
<!-- TODO cut this down and add some missing ones -->
<string>(?<=\()(?i:\*|\*\*|\*\*\*|\+|\+\+|\+\+\+|\-|/|//|///|/=|<|<=|=|>|>=|and|apply|assert|begin|break|case|catch|concat|cond|continue|count|defMacro|defReaderMacro|defun|classMethod|classFunction|defvar|classVar|classProp|for|doFor|eighth|eval|fifth|first|fourth|localFunction|localVar|symbol|if|load|withFunction|withFunctions|lambda|last|let|loop|map|max|min|ninth|not|nth|setNth|getDict|setDict|or|otherwise|print|rest|return|reversed|second|set|sixth|Some|sort|symbolName|symbolNameValue|tenth|the|third|throw|trace|when|unless|ifLet|whenLet|unlessLet|forCase|doForCase|with[A-Z]\S+)(?=\s+)</string>
<string>(?<=\()(?i:\*|\*\*|\*\*\*|\+|\+\+|\+\+\+|\-|/|//|///|/=|<|<=|=|>|>=|and|apply|assert|begin|break|case|catch|concat|cond|continue|count|defMacro|defReaderMacro|defun|defmethod|method|function|defvar|var|defprop|prop|for|doFor|eighth|eval|fifth|first|fourth|localFunction|localVar|symbol|if|load|withFunction|withFunctions|lambda|last|let|loop|map|max|min|ninth|not|nth|setNth|getDict|setDict|or|otherwise|print|rest|return|reversed|second|set|sixth|Some|sort|symbolName|symbolNameValue|tenth|the|third|throw|trace|when|unless|ifLet|whenLet|unlessLet|forCase|doForCase|with[A-Z]\S+)(?=\s+)</string>
<key>name</key>
<string>keyword.control.kiss</string>
</dict>

View File

@@ -10,14 +10,14 @@
(let [entryFiles (FileSystem.readDirectory entryDir)]
(for file entryFiles =>(file.withoutExtension) (the Entry (Json.parse (File.getContent (joinPath archiveDir "entries" file)))))))])
(defmethod addSystem [:System system]
(method addSystem [:System system]
// Assign entries to the Systems that care about them
(doFor =>id entry entries
(system.checkEntryInOrOut this entry))
(systems.push system)
system)
(defmethod :Entry createEntry [:Entry->Dynamic initializer] // initializer returns Dynamic so ->:Void isn't required
(method :Entry createEntry [:Entry->Dynamic initializer] // initializer returns Dynamic so ->:Void isn't required
(let [e (_newEntry)]
(initializer e)
(dictSet entries e.id e)
@@ -26,20 +26,20 @@
// After modifying an entry, this must be called. If you are writing in a createEntry initializer or a system's processEntry function, this will happen automatically.
// Otherwise, you can guarantee it happens automatically by using the (withWritableEntry) macro in Lib.kiss
(defmethod refreshEntry [:Entry e]
(method refreshEntry [:Entry e]
(_saveEntry e)
(doFor system systems
(system.checkEntryInOrOut this e)))
(defmethod _saveEntry [:Entry e]
(method _saveEntry [:Entry e]
(File.saveContent
(joinPath archiveDir "entries" (e.id.withExtension "json"))
(Json.stringify e)))
(defmethod componentData [:Entry e :String componentType]
(method componentData [:Entry e :String componentType]
(haxe.Json.parse (File.getContent (joinPath archiveDir "components" "$(dictGet e.components componentType).json"))))
(defmethod fullData [:Entry e]
(method fullData [:Entry e]
(object
id e.id
components
@@ -48,11 +48,11 @@
files
e.files))
(defmethod fullString [:Entry e]
(method fullString [:Entry e]
(haxe.Json.stringify (fullData e) null "\t"))
(defun :Entry _newEntry []
(function :Entry _newEntry []
(object
id (Uuid.v4)
components (new Map)
files []))
files []))

View File

@@ -1,6 +1,6 @@
(load "Lib.kiss")
(defmethod :Void _collectAndValidateArg [:CommandArg arg :Dynamic->Void continuation]
(method :Void _collectAndValidateArg [:CommandArg arg :Dynamic->Void continuation]
(case arg.type
(SelectedEntry
(if (= 1 selectedEntries.length)
@@ -91,11 +91,11 @@
min
max))))
(defmethod :Void->Void _composeArgCollector [:Array<Dynamic> collectedArgs :CommandArg arg :Void->Void lastCollector]
(method :Void->Void _composeArgCollector [:Array<Dynamic> collectedArgs :CommandArg arg :Void->Void lastCollector]
(lambda :Void []
(_collectAndValidateArg arg ->:Void [:Dynamic argValue] {(collectedArgs.push argValue) (lastCollector)})))
(defmethod :Void runCommand [:Command command]
(method :Void runCommand [:Command command]
(let [collectedArgs
[]
&mut lastCollector
@@ -125,7 +125,7 @@
(for [name type] argPairs
`(object name ,(symbolName name) type ,type))]
`{
(defmethod ,name [,@methodArgs] ,@body)
(method ,name [,@methodArgs] ,@body)
(dictSet commands ,(symbolName name) (object args [,@commandArgs] handler (the Function ,name)))}))
(defnew [&prop :Archive archive
@@ -184,4 +184,4 @@
(selectEntries (filter archive.entries ->e (tagsMatch archive e tagsBoolExp))))
(defcommand selectByComponents [componentsBoolExp (Text null)]
(selectEntries (filter archive.entries ->e (componentsMatch e componentsBoolExp)))))
(selectEntries (filter archive.entries ->e (componentsMatch e componentsBoolExp)))))

View File

@@ -1,4 +1,4 @@
(defun eval [:String expStr :Array<String> activeConditions]
(function eval [:String expStr :Array<String> activeConditions]
(let [hscriptExp
(.parseString (new Parser)
(Prelude.convertToHScript expStr))
@@ -6,4 +6,4 @@
(new BoolExpInterp)]
(doFor condition activeConditions
(interp.variables.set condition true))
?(interp.execute hscriptExp)))
?(interp.execute hscriptExp)))

View File

@@ -1,6 +1,6 @@
(load "Lib.kiss")
(defun :Void main []
(function :Void main []
(let [[archiveDir] (Sys.args)
controller
(new ArchiveController
@@ -16,7 +16,7 @@
(defnew [])
(defmethod :Void enterText [prompt resolve maxLength]
(method :Void enterText [prompt resolve maxLength]
(Sys.print "$prompt ")
(loop
(let [entered (.toString (.readLine (Sys.stdin)))]
@@ -25,7 +25,7 @@
{(resolve entered)
(break)}))))
(defmethod :Void enterNumber [prompt resolve min max &opt inStepsOf]
(method :Void enterNumber [prompt resolve min max &opt inStepsOf]
(Sys.print "$prompt ")
(loop
(let [entered (Std.parseFloat (.toString (.readLine (Sys.stdin))))]
@@ -37,10 +37,10 @@
{(resolve entered)
(break)}))))
(defmethod :Void chooseEntry [prompt :Archive archive resolve]
(method :Void chooseEntry [prompt :Archive archive resolve]
(_chooseEntry prompt archive resolve ->(chooseEntry "empty name doesn't match any entries. Try again?" archive resolve)))
(defmethod :Void _chooseEntry [prompt :Archive archive resolve onEmptyString]
(method :Void _chooseEntry [prompt :Archive archive resolve onEmptyString]
// TODO allow narrowing down with a tag string
(enterText "entry name for $prompt"
->name {
@@ -59,10 +59,10 @@
(multipleEntries (throw "ambiguous between multiple entries")))))}
Math.POSITIVE_INFINITY))
(defmethod :Void chooseEntries [prompt archive resolve min max]
(method :Void chooseEntries [prompt archive resolve min max]
(_chooseEntries prompt archive resolve min max []))
(defmethod :Void _chooseEntries [prompt archive resolve min max :Array<Entry> collectedEntries]
(method :Void _chooseEntries [prompt archive resolve min max :Array<Entry> collectedEntries]
(let [onEmptyString
->(if (<= min collectedEntries.length)
(resolve collectedEntries)
@@ -84,12 +84,12 @@
(_chooseNextEntry)))
(defmethod handleChanges [:Archive archive :ChangeSet changeSet]
(method handleChanges [:Archive archive :ChangeSet changeSet]
(doFor e changeSet
(print (archive.fullString e))))
(defmethod :Void displayMessage [message]
(method :Void displayMessage [message]
(print message))
(defmethod :Void reportError [error]
(print error))
(method :Void reportError [error]
(print error))

View File

@@ -64,13 +64,13 @@
(= ,value (readComponent ,archive e ,componentType))))
,process))
(defun tagList [archive e]
(function tagList [archive e]
(let [t
(readComponent archive e Tags)]
(collect (t.keys))))
(defun tagsMatch [archive e tagsBoolExp]
(function tagsMatch [archive e tagsBoolExp]
(BoolExpInterp.eval tagsBoolExp (tagList archive e)))
(defun componentsMatch [:nat.Entry e componentsBoolExp]
(BoolExpInterp.eval componentsBoolExp (for =>cType cId e.components cType)))
(function componentsMatch [:nat.Entry e componentsBoolExp]
(BoolExpInterp.eval componentsBoolExp (for =>cType cId e.components cType)))

View File

@@ -1,6 +1,6 @@
(defprop :Map<String,Entry> entries (new Map))
(prop :Map<String,Entry> entries (new Map))
(defmethod :Void process [:Archive archive]
(method :Void process [:Archive archive]
(doFor e (entries.iterator)
(processEntry archive e)
(archive.refreshEntry e)))
@@ -9,7 +9,7 @@
&prop :EntryProcessor processEntry]
[])
(defmethod :Void checkEntryInOrOut [:Archive archive :Entry e]
(method :Void checkEntryInOrOut [:Archive archive :Entry e]
(if (canProcessEntry archive e)
(dictSet entries e.id e)
(entries.remove e.id)))

View File

@@ -4,7 +4,7 @@
(load "../nat/Lib.kiss")
(defun :Void main []
(function :Void main []
(assert (BoolExpInterp.eval "true" []))
(assert !(BoolExpInterp.eval "false" []))
(assert !(BoolExpInterp.eval "flag" []))
@@ -32,4 +32,4 @@
[author Author
name Name]
(assert (= author "Rafael Krux"))
(assert (= name "Adventure")))))
(assert (= name "Adventure")))))

View File

@@ -1,4 +1,4 @@
(loadFrom "nat-archive-tool" "src/nat/Lib.kiss")
(defun :Void main []
(print "Hello world!"))
(function :Void main []
(print "Hello world!"))

View File

@@ -1,4 +1,4 @@
(defun loadAll [:Array<String> paths :Function callback &opt :Array<PDFDocument> pdfs]
(function loadAll [:Array<String> paths :Function callback &opt :Array<PDFDocument> pdfs]
(unless pdfs (set pdfs []))
(localVar nextPdf (paths.shift))
(if (nextPdf.endsWith ".pdf")
@@ -13,7 +13,7 @@
// TODO add sequentialPerPDF argument (which, when used, .shift()s pages from the beginning of PDFs)
// TODO add chunkSize argument (default 1, which specifies how many pages in order to pull from a random PDF. value of -1 means take the whole PDF, and remove it from the list)
// TODO make output page limit optional
(defun :Void main []
(function :Void main []
(let [[sourceDir numPages] (Sys.args)]
(loadAll (for file (Fs.readdirSync sourceDir) (+ sourceDir "/" file))
(lambda [:Array<PDFDocument> inputPdfs]