diff --git a/hxformat.json b/hxformat.json new file mode 100644 index 00000000..b8e0be6e --- /dev/null +++ b/hxformat.json @@ -0,0 +1,5 @@ +{ + "indentation": { + "character": " " + } +} \ No newline at end of file diff --git a/src/kiss/FieldForms.hx b/src/kiss/FieldForms.hx index ce228dd8..0a3788be 100644 --- a/src/kiss/FieldForms.hx +++ b/src/kiss/FieldForms.hx @@ -11,89 +11,89 @@ using StringTools; typedef FieldFormFunction = (position:String, args:Array, convert:ExprConversion) -> Field; class FieldForms { - public static function builtins() { - var map:Map = []; + public static function builtins() { + var map:Map = []; - map["defvar"] = varOrProperty.bind("defvar"); - map["defprop"] = varOrProperty.bind("defprop"); + map["defvar"] = varOrProperty.bind("defvar"); + map["defprop"] = varOrProperty.bind("defprop"); - map["defun"] = funcOrMethod.bind("defun"); - map["defmethod"] = funcOrMethod.bind("defmethod"); + map["defun"] = funcOrMethod.bind("defun"); + map["defmethod"] = funcOrMethod.bind("defmethod"); - return map; - } + return map; + } - static function fieldAccess(formName:String, fieldName:String) { - var access = []; - if (formName == "defvar" || formName == "defun") { - access.push(AStatic); - } - access.push(if (fieldName.startsWith("_")) APrivate else APublic); - return access; - } + static function fieldAccess(formName:String, fieldName:String) { + var access = []; + if (formName == "defvar" || formName == "defun") { + access.push(AStatic); + } + access.push(if (fieldName.startsWith("_")) APrivate else APublic); + return access; + } - static function fieldName(formName:String, position:String, nameExp:ReaderExp) { - return switch (nameExp) { - case Symbol(name): - name; - default: - throw 'The first argument to $formName at $position should be a variable name'; - }; - } + static function fieldName(formName:String, position:String, nameExp:ReaderExp) { + return switch (nameExp) { + case Symbol(name): + name; + default: + throw 'The first argument to $formName at $position should be a variable name'; + }; + } - static function varOrProperty(formName:String, position:String, args:Array, convert:ExprConversion):Field { - if (args.length != 2) { - throw '$formName with $args at $position is not a valid field definition'; - } + static function varOrProperty(formName:String, position:String, args:Array, convert:ExprConversion):Field { + if (args.length != 2) { + throw '$formName with $args at $position is not a valid field definition'; + } - var name = fieldName(formName, position, args[0]); - var access = fieldAccess(formName, name); + var name = fieldName(formName, position, args[0]); + var access = fieldAccess(formName, name); - return { - name: name, - access: access, - kind: FVar(null, // TODO allow type anotations - convert(args[1])), - pos: Context.currentPos() - }; - } + return { + name: name, + access: access, + kind: FVar(null, // TODO allow type anotations + convert(args[1])), + pos: Context.currentPos() + }; + } - static function funcOrMethod(formName:String, position:String, args:Array, convert:ExprConversion):Field { - if (args.length <= 2) { - throw '$formName with $args is not a valid function/method definition'; - } + static function funcOrMethod(formName:String, position:String, args:Array, convert:ExprConversion):Field { + if (args.length <= 2) { + throw '$formName with $args is not a valid function/method definition'; + } - var name = fieldName(formName, position, args[0]); - var access = fieldAccess(formName, name); + var name = fieldName(formName, position, args[0]); + var access = fieldAccess(formName, name); - return { - name: name, - access: access, - kind: FFun({ - args: switch (args[1]) { - case ListExp(funcArgs): - [ - for (funcArg in funcArgs) - { - name: switch (funcArg) { - case Symbol(name): - name; - default: - throw '$funcArg should be a symbol for a function argument'; - }, - type: null - } - ]; - default: - throw '$args[1] should be an argument list'; - }, - ret: null, - expr: { - pos: Context.currentPos(), - expr: EReturn(convert(CallExp(Symbol("begin"), args.slice(2)))) - } - }), - pos: Context.currentPos() - }; - } + return { + name: name, + access: access, + kind: FFun({ + args: switch (args[1]) { + case ListExp(funcArgs): + [ + for (funcArg in funcArgs) + { + name: switch (funcArg) { + case Symbol(name): + name; + default: + throw '$funcArg should be a symbol for a function argument'; + }, + type: null + } + ]; + default: + throw '$args[1] should be an argument list'; + }, + ret: null, + expr: { + pos: Context.currentPos(), + expr: EReturn(convert(CallExp(Symbol("begin"), args.slice(2)))) + } + }), + pos: Context.currentPos() + }; + } } diff --git a/src/kiss/Kiss.hx b/src/kiss/Kiss.hx index d5df5e33..05652a04 100644 --- a/src/kiss/Kiss.hx +++ b/src/kiss/Kiss.hx @@ -9,91 +9,91 @@ import kiss.SpecialForms; import kiss.Macros; class Kiss { - /** - Build a Haxe class from a corresponding .kiss file - **/ - macro static public function build(kissFile:String):Array { - var classFields = Context.getBuildFields(); + /** + Build a Haxe class from a corresponding .kiss file + **/ + macro static public function build(kissFile:String):Array { + var classFields = Context.getBuildFields(); - var stream = new Stream(kissFile); + var stream = new Stream(kissFile); - var readTable = Reader.builtins(); - var fieldForms = FieldForms.builtins(); - var specialForms = SpecialForms.builtins(); - var macros = Macros.builtins(); + var readTable = Reader.builtins(); + var fieldForms = FieldForms.builtins(); + var specialForms = SpecialForms.builtins(); + var macros = Macros.builtins(); - while (true) { - stream.dropWhitespace(); - if (stream.isEmpty()) - break; - var position = stream.position(); - var nextExp = Reader.read(stream, readTable); - #if test - trace(nextExp); - #end - // The last expression might be a comment, in which case None will be returned - switch (nextExp) { - case Some(nextExp): - classFields.push(readerExpToField(nextExp, position, fieldForms, macros, specialForms)); - case None: - stream.dropWhitespace(); // If there was a comment, drop whitespace that comes after - } - } + while (true) { + stream.dropWhitespace(); + if (stream.isEmpty()) + break; + var position = stream.position(); + var nextExp = Reader.read(stream, readTable); + #if test + trace(nextExp); + #end + // The last expression might be a comment, in which case None will be returned + switch (nextExp) { + case Some(nextExp): + classFields.push(readerExpToField(nextExp, position, fieldForms, macros, specialForms)); + case None: + stream.dropWhitespace(); // If there was a comment, drop whitespace that comes after + } + } - return classFields; - } + return classFields; + } - static function readerExpToField(exp:ReaderExp, position:String, fieldForms:Map, macros:Map, - specialForms:Map):Field { - return switch (exp) { - case CallExp(Symbol(formName), args) if (fieldForms.exists(formName)): - fieldForms[formName](position, args, readerExpToHaxeExpr.bind(_, macros, specialForms)); - default: - throw '$exp at $position is not a valid field form'; - }; - } + static function readerExpToField(exp:ReaderExp, position:String, fieldForms:Map, macros:Map, + specialForms:Map):Field { + return switch (exp) { + case CallExp(Symbol(formName), args) if (fieldForms.exists(formName)): + fieldForms[formName](position, args, readerExpToHaxeExpr.bind(_, macros, specialForms)); + default: + throw '$exp at $position is not a valid field form'; + }; + } - static function readerExpToHaxeExpr(exp:ReaderExp, macros:Map, specialForms:Map):Expr { - // Bind the table arguments of this function for easy recursive calling/passing - var convert = readerExpToHaxeExpr.bind(_, macros, specialForms); - var expr = switch (exp) { - case Symbol(name): - Context.parse(name, Context.currentPos()); - case StrExp(s): - { - pos: Context.currentPos(), - expr: EConst(CString(s)) - }; - case CallExp(Symbol(mac), args) if (macros.exists(mac)): - convert(macros[mac](args)); - case CallExp(Symbol(specialForm), args) if (specialForms.exists(specialForm)): - specialForms[specialForm](args, convert); - case CallExp(func, body): - { - pos: Context.currentPos(), - expr: ECall(readerExpToHaxeExpr(func, macros, specialForms), [for (bodyExp in body) readerExpToHaxeExpr(bodyExp, macros, specialForms)]) - }; - case ListExp(elements): - { - pos: Context.currentPos(), - expr: ENew({ - pack: ["kiss"], - name: "List" - }, [ - { - pos: Context.currentPos(), - expr: EArrayDecl([for (elementExp in elements) convert(elementExp)]) - } - ]) - } - case RawHaxe(code): - Context.parse(code, Context.currentPos()); - default: - throw 'cannot convert $exp yet'; - }; - #if test - trace(expr.expr); - #end - return expr; - } + static function readerExpToHaxeExpr(exp:ReaderExp, macros:Map, specialForms:Map):Expr { + // Bind the table arguments of this function for easy recursive calling/passing + var convert = readerExpToHaxeExpr.bind(_, macros, specialForms); + var expr = switch (exp) { + case Symbol(name): + Context.parse(name, Context.currentPos()); + case StrExp(s): + { + pos: Context.currentPos(), + expr: EConst(CString(s)) + }; + case CallExp(Symbol(mac), args) if (macros.exists(mac)): + convert(macros[mac](args)); + case CallExp(Symbol(specialForm), args) if (specialForms.exists(specialForm)): + specialForms[specialForm](args, convert); + case CallExp(func, body): + { + pos: Context.currentPos(), + expr: ECall(readerExpToHaxeExpr(func, macros, specialForms), [for (bodyExp in body) readerExpToHaxeExpr(bodyExp, macros, specialForms)]) + }; + case ListExp(elements): + { + pos: Context.currentPos(), + expr: ENew({ + pack: ["kiss"], + name: "List" + }, [ + { + pos: Context.currentPos(), + expr: EArrayDecl([for (elementExp in elements) convert(elementExp)]) + } + ]) + } + case RawHaxe(code): + Context.parse(code, Context.currentPos()); + default: + throw 'cannot convert $exp yet'; + }; + #if test + trace(expr.expr); + #end + return expr; + } } diff --git a/src/kiss/List.hx b/src/kiss/List.hx index fbd50d6f..efecb73f 100644 --- a/src/kiss/List.hx +++ b/src/kiss/List.hx @@ -1,52 +1,52 @@ package kiss; @:forward(length, concat, contains, copy, filter, indexOf, // insert is re-implemented with negative index support - iterator, join, keyValueIterator, - lastIndexOf, map, pop, push, remove, resize, reverse, shift, // slice is re-implemented with negative index support - sort, - // splice is re-implemented with negative index support, - toString, unshift) + iterator, join, keyValueIterator, + lastIndexOf, map, pop, push, remove, resize, reverse, shift, // slice is re-implemented with negative index support + sort, + // splice is re-implemented with negative index support, + toString, unshift) abstract List(Array) from Array to Array { - public inline function new(a:Array) { - this = a; - } + public inline function new(a:Array) { + this = a; + } - @:from - static public function fromArray(a:Array) { - return new List(a); - } + @:from + static public function fromArray(a:Array) { + return new List(a); + } - @:to - public function toArray() { - return this; - } + @:to + public function toArray() { + return this; + } - inline function realIndex(idx:Int) { - return if (idx < 0) this.length + idx else idx; - } + inline function realIndex(idx:Int) { + return if (idx < 0) this.length + idx else idx; + } - @:arrayAccess - public inline function get(idx:Int):Null { - return this[realIndex(idx)]; - } + @:arrayAccess + public inline function get(idx:Int):Null { + return this[realIndex(idx)]; + } - @:arrayAccess - public inline function arrayWrite(idx:Int, v:T):T { - this[realIndex(idx)] = v; - return v; - } + @:arrayAccess + public inline function arrayWrite(idx:Int, v:T):T { + this[realIndex(idx)] = v; + return v; + } - public function insert(idx:Int, v:T) { - this.insert(realIndex(idx), v); - } + public function insert(idx:Int, v:T) { + this.insert(realIndex(idx), v); + } - public function slice(start:Int, ?end:Int) { - if (end == null) - end = this.length; - return this.slice(realIndex(start), realIndex(end)); - } + public function slice(start:Int, ?end:Int) { + if (end == null) + end = this.length; + return this.slice(realIndex(start), realIndex(end)); + } - public function splice(start:Int, len:Int) { - return this.splice(realIndex(start), len); - } + public function splice(start:Int, len:Int) { + return this.splice(realIndex(start), len); + } } diff --git a/src/kiss/Macros.hx b/src/kiss/Macros.hx index 1571ac9b..8343ddda 100644 --- a/src/kiss/Macros.hx +++ b/src/kiss/Macros.hx @@ -6,37 +6,37 @@ import kiss.Reader; typedef MacroFunction = (Array) -> ReaderExp; class Macros { - public static function builtins() { - var macros:Map = []; + public static function builtins() { + var macros:Map = []; - macros["+"] = foldMacro("Prelude.add"); + macros["+"] = foldMacro("Prelude.add"); - macros["-"] = foldMacro("Prelude.subtract"); + macros["-"] = foldMacro("Prelude.subtract"); - macros["*"] = foldMacro("Prelude.multiply"); + macros["*"] = foldMacro("Prelude.multiply"); - macros["/"] = foldMacro("Prelude.divide"); + macros["/"] = foldMacro("Prelude.divide"); - macros["%"] = (exps:Array) -> { - if (exps.length != 2) { - throw 'Got ${exps.length} arguments for % instead of 2.'; - } - CallExp(Symbol("Prelude.mod"), [exps[1], exps[0]]); - }; + macros["%"] = (exps:Array) -> { + if (exps.length != 2) { + throw 'Got ${exps.length} arguments for % instead of 2.'; + } + CallExp(Symbol("Prelude.mod"), [exps[1], exps[0]]); + }; - macros["^"] = (exps:Array) -> { - if (exps.length != 2) { - throw 'Got ${exps.length} arguments for ^ instead of 2.'; - } - CallExp(Symbol("Prelude.pow"), [exps[1], exps[0]]); - }; + macros["^"] = (exps:Array) -> { + if (exps.length != 2) { + throw 'Got ${exps.length} arguments for ^ instead of 2.'; + } + CallExp(Symbol("Prelude.pow"), [exps[1], exps[0]]); + }; - return macros; - } + return macros; + } - static function foldMacro(func:String):MacroFunction { - return (exps) -> { - CallExp(Symbol("Lambda.fold"), [ListExp(exps.slice(1)), Symbol(func), exps[0]]); - }; - } + static function foldMacro(func:String):MacroFunction { + return (exps) -> { + CallExp(Symbol("Lambda.fold"), [ListExp(exps.slice(1)), Symbol(func), exps[0]]); + }; + } } diff --git a/src/kiss/Prelude.hx b/src/kiss/Prelude.hx index d44032cf..d9e34ec7 100644 --- a/src/kiss/Prelude.hx +++ b/src/kiss/Prelude.hx @@ -1,27 +1,27 @@ package kiss; class Prelude { - public static function add(a, b) { - return a + b; - } + public static function add(a, b) { + return a + b; + } - public static function subtract(val, from) { - return from - val; - } + public static function subtract(val, from) { + return from - val; + } - public static function multiply(a, b) { - return a * b; - } + public static function multiply(a, b) { + return a * b; + } - public static function divide(bottom:Float, top:Float) { - return top / bottom; - } + public static function divide(bottom:Float, top:Float) { + return top / bottom; + } - public static function mod(bottom, top) { - return top % bottom; - } + public static function mod(bottom, top) { + return top % bottom; + } - public static function pow(exponent, base) { - return Math.pow(base, exponent); - } + public static function pow(exponent, base) { + return Math.pow(base, exponent); + } } diff --git a/src/kiss/Reader.hx b/src/kiss/Reader.hx index d1f643ec..b1caf6db 100644 --- a/src/kiss/Reader.hx +++ b/src/kiss/Reader.hx @@ -4,76 +4,76 @@ import haxe.ds.Option; import kiss.Stream; enum ReaderExp { - CallExp(func:ReaderExp, args:Array); // (f a1 a2...) - ListExp(exps:Array); // [v1 v2 v3] - StrExp(s:String); // "literal" - Symbol(name:String); // s - RawHaxe(code:String); + CallExp(func:ReaderExp, args:Array); // (f a1 a2...) + ListExp(exps:Array); // [v1 v2 v3] + StrExp(s:String); // "literal" + Symbol(name:String); // s + RawHaxe(code:String); } typedef ReadFunction = (Stream) -> Null; class Reader { - // The built-in readtable - public static function builtins() { - var readTable:Map = []; + // The built-in readtable + public static function builtins() { + var readTable:Map = []; - readTable["("] = (stream) -> CallExp(assertRead(stream, readTable), readExpArray(stream, ")", readTable)); - readTable["["] = (stream) -> ListExp(readExpArray(stream, "]", readTable)); - readTable["\""] = (stream) -> StrExp(stream.expect("closing \"", () -> stream.takeUntilAndDrop("\""))); - readTable["/*"] = (stream) -> { - stream.dropUntil("*/"); - stream.dropString("*/"); - null; - }; - readTable["//"] = (stream) -> { - stream.dropUntil("\n"); - null; - }; - readTable["#|"] = (stream) -> RawHaxe(stream.expect("closing |", () -> stream.takeUntilAndDrop("|#"))); + readTable["("] = (stream) -> CallExp(assertRead(stream, readTable), readExpArray(stream, ")", readTable)); + readTable["["] = (stream) -> ListExp(readExpArray(stream, "]", readTable)); + readTable["\""] = (stream) -> StrExp(stream.expect("closing \"", () -> stream.takeUntilAndDrop("\""))); + readTable["/*"] = (stream) -> { + stream.dropUntil("*/"); + stream.dropString("*/"); + null; + }; + readTable["//"] = (stream) -> { + stream.dropUntil("\n"); + null; + }; + readTable["#|"] = (stream) -> RawHaxe(stream.expect("closing |", () -> stream.takeUntilAndDrop("|#"))); - return readTable; - } + return readTable; + } - public static function assertRead(stream:Stream, readTable:Map):ReaderExp { - var position = stream.position(); - return switch (read(stream, readTable)) { - case Some(exp): - exp; - case None: - throw 'There were no expressions left in the stream at $position'; - }; - } + public static function assertRead(stream:Stream, readTable:Map):ReaderExp { + var position = stream.position(); + return switch (read(stream, readTable)) { + case Some(exp): + exp; + case None: + throw 'There were no expressions left in the stream at $position'; + }; + } - public static function read(stream:Stream, readTable:Map):Option { - stream.dropWhitespace(); + public static function read(stream:Stream, readTable:Map):Option { + stream.dropWhitespace(); - if (stream.isEmpty()) - return None; + if (stream.isEmpty()) + return None; - var readTableKeys = [for (key in readTable.keys()) key]; - readTableKeys.sort((a, b) -> b.length - a.length); + var readTableKeys = [for (key in readTable.keys()) key]; + readTableKeys.sort((a, b) -> b.length - a.length); - for (key in readTableKeys) { - switch (stream.peekChars(key.length)) { - case Some(k) if (k == key): - stream.dropString(key); - var expOrNull = readTable[key](stream); - return if (expOrNull != null) Some(expOrNull) else read(stream, readTable); - default: - } - } + for (key in readTableKeys) { + switch (stream.peekChars(key.length)) { + case Some(k) if (k == key): + stream.dropString(key); + var expOrNull = readTable[key](stream); + return if (expOrNull != null) Some(expOrNull) else read(stream, readTable); + default: + } + } - return Some(Symbol(stream.expect("a symbol name", () -> stream.takeUntilOneOf([")", "]", "/*", "\n", " "])))); - } + return Some(Symbol(stream.expect("a symbol name", () -> stream.takeUntilOneOf([")", "]", "/*", "\n", " "])))); + } - public static function readExpArray(stream:Stream, end:String, readTable:Map):Array { - var array = []; - while (stream.expect('$end to terminate list', () -> stream.peekChars(end.length)) != end) { - stream.dropWhitespace(); - array.push(assertRead(stream, readTable)); - } - stream.dropString(end); - return array; - } + public static function readExpArray(stream:Stream, end:String, readTable:Map):Array { + var array = []; + while (stream.expect('$end to terminate list', () -> stream.peekChars(end.length)) != end) { + stream.dropWhitespace(); + array.push(assertRead(stream, readTable)); + } + stream.dropString(end); + return array; + } } diff --git a/src/kiss/SpecialForms.hx b/src/kiss/SpecialForms.hx index 516f72ed..3e8870ac 100644 --- a/src/kiss/SpecialForms.hx +++ b/src/kiss/SpecialForms.hx @@ -9,19 +9,19 @@ import kiss.Types; typedef SpecialFormFunction = (args:Array, convert:ExprConversion) -> Expr; class SpecialForms { - public static function builtins() { - var map:Map = []; + public static function builtins() { + var map:Map = []; - map["begin"] = (args:Array, convert:ExprConversion) -> { - pos: Context.currentPos(), - expr: EBlock([for (bodyExp in args) convert(bodyExp)]) - }; + map["begin"] = (args:Array, convert:ExprConversion) -> { + pos: Context.currentPos(), + expr: EBlock([for (bodyExp in args) convert(bodyExp)]) + }; - map["nth"] = (args:Array, convert:ExprConversion) -> { - pos: Context.currentPos(), - expr: EArray(convert(args[0]), convert(args[1])) - }; + map["nth"] = (args:Array, convert:ExprConversion) -> { + pos: Context.currentPos(), + expr: EArray(convert(args[0]), convert(args[1])) + }; - return map; - } + return map; + } } diff --git a/src/kiss/Stream.hx b/src/kiss/Stream.hx index c46009ee..cc67e619 100644 --- a/src/kiss/Stream.hx +++ b/src/kiss/Stream.hx @@ -7,102 +7,102 @@ using StringTools; using Lambda; class Stream { - var content:String; - var file:String; - var line:Int; - var column:Int; + var content:String; + var file:String; + var line:Int; + var column:Int; - public function new(file:String) { - // Banish ye Windows line-endings - content = File.getContent(file).replace('\r', ''); - // Life is easier with a trailing newline - if (content.charAt(content.length - 1) != "\n") - content += "\n"; + public function new(file:String) { + // Banish ye Windows line-endings + content = File.getContent(file).replace('\r', ''); + // Life is easier with a trailing newline + if (content.charAt(content.length - 1) != "\n") + content += "\n"; - this.file = file; - line = 1; - column = 1; - } + this.file = file; + line = 1; + column = 1; + } - public function peekChars(chars:Int):Option { - if (content.length < chars) - return None; - return Some(content.substr(0, chars)); - } + public function peekChars(chars:Int):Option { + if (content.length < chars) + return None; + return Some(content.substr(0, chars)); + } - public function isEmpty() { - return content.length == 0; - } + public function isEmpty() { + return content.length == 0; + } - public function position() { - return '$file:$line:$column'; - } + public function position() { + return '$file:$line:$column'; + } - /** Every drop call should end up calling dropChars() or the position tracker will be wrong. **/ - private function dropChars(count:Int) { - for (idx in 0...count) { - switch (content.charAt(idx)) { - case "\n": - line += 1; - column = 1; - default: - column += 1; - } - } - content = content.substr(count); - } + /** Every drop call should end up calling dropChars() or the position tracker will be wrong. **/ + private function dropChars(count:Int) { + for (idx in 0...count) { + switch (content.charAt(idx)) { + case "\n": + line += 1; + column = 1; + default: + column += 1; + } + } + content = content.substr(count); + } - public function takeChars(count:Int):Option { - if (count > content.length) - return None; - var toReturn = content.substr(0, count); - dropChars(count); - return Some(toReturn); - } + public function takeChars(count:Int):Option { + if (count > content.length) + return None; + var toReturn = content.substr(0, count); + dropChars(count); + return Some(toReturn); + } - public function dropString(s:String) { - var toDrop = content.substr(0, s.length); - if (toDrop != s) { - throw 'Expected $s at ${position()}'; - } - dropChars(s.length); - } + public function dropString(s:String) { + var toDrop = content.substr(0, s.length); + if (toDrop != s) { + throw 'Expected $s at ${position()}'; + } + dropChars(s.length); + } - public function dropUntil(s:String) { - dropChars(content.indexOf(s)); - } + public function dropUntil(s:String) { + dropChars(content.indexOf(s)); + } - public function dropWhitespace() { - var trimmed = content.ltrim(); - dropChars(content.length - trimmed.length); - } + public function dropWhitespace() { + var trimmed = content.ltrim(); + dropChars(content.length - trimmed.length); + } - public function takeUntilOneOf(terminators:Array):Option { - var indices = [for (term in terminators) content.indexOf(term)].filter((idx) -> idx >= 0); - if (indices.length == 0) - return None; - var firstIndex = Math.floor(indices.fold(Math.min, indices[0])); - return takeChars(firstIndex); - } + public function takeUntilOneOf(terminators:Array):Option { + var indices = [for (term in terminators) content.indexOf(term)].filter((idx) -> idx >= 0); + if (indices.length == 0) + return None; + var firstIndex = Math.floor(indices.fold(Math.min, indices[0])); + return takeChars(firstIndex); + } - public function takeUntilAndDrop(s:String):Option { - var idx = content.indexOf(s); + public function takeUntilAndDrop(s:String):Option { + var idx = content.indexOf(s); - if (idx < 0) - return None; + if (idx < 0) + return None; - var toReturn = content.substr(0, idx); - dropChars(toReturn.length + s.length); - return Some(toReturn); - } + var toReturn = content.substr(0, idx); + dropChars(toReturn.length + s.length); + return Some(toReturn); + } - public function expect(whatToExpect:String, f:Void->Option):String { - var position = position(); - switch (f()) { - case Some(s): - return s; - case None: - throw 'Expected $whatToExpect at $position'; - } - } + public function expect(whatToExpect:String, f:Void->Option):String { + var position = position(); + switch (f()) { + case Some(s): + return s; + case None: + throw 'Expected $whatToExpect at $position'; + } + } } diff --git a/src/test/TestMain.hx b/src/test/TestMain.hx index 77abd17f..14d23546 100644 --- a/src/test/TestMain.hx +++ b/src/test/TestMain.hx @@ -4,10 +4,10 @@ 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(); - } + public static function main() { + var runner = new Runner(); + runner.addCases(test.cases); + Report.create(runner); + runner.run(); + } } diff --git a/src/test/cases/BasicTestCase.hx b/src/test/cases/BasicTestCase.hx index c5974bf6..50bd81b7 100644 --- a/src/test/cases/BasicTestCase.hx +++ b/src/test/cases/BasicTestCase.hx @@ -6,72 +6,72 @@ import kiss.Prelude; @:build(kiss.Kiss.build("src/test/cases/BasicTestCase.kiss")) class BasicTestCase extends Test { - function testStaticVar() { - Assert.equals("Howdy", BasicTestCase.message); - } + function testStaticVar() { + Assert.equals("Howdy", BasicTestCase.message); + } - function testHaxeInsertion() { - Assert.equals(23, BasicTestCase.mathResult); - } + function testHaxeInsertion() { + Assert.equals(23, BasicTestCase.mathResult); + } - function testStaticFunction() { - Assert.equals(6, BasicTestCase.myFloor(6.5)); - } + function testStaticFunction() { + Assert.equals(6, BasicTestCase.myFloor(6.5)); + } - function testFuncall() { - Assert.equals(7, BasicTestCase.funResult); - } + function testFuncall() { + Assert.equals(7, BasicTestCase.funResult); + } - function testField() { - Assert.equals(5, new BasicTestCase().myField); - } + function testField() { + Assert.equals(5, new BasicTestCase().myField); + } - function testMethod() { - Assert.equals(5, new BasicTestCase().myMethod()); - } + 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]); + 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]); - } + // 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 testArrayAccess() { + Assert.equals(3, BasicTestCase.myArrayLast); + } - function testVariadicAdd() { - Assert.equals(6, BasicTestCase.mySum); - } + function testVariadicAdd() { + Assert.equals(6, BasicTestCase.mySum); + } - function testVariadicSubtract() { - Assert.equals(-2, BasicTestCase.myDifference); - } + function testVariadicSubtract() { + Assert.equals(-2, BasicTestCase.myDifference); + } - function testVariadicMultiply() { - Assert.equals(60, BasicTestCase.myProduct); - } + function testVariadicMultiply() { + Assert.equals(60, BasicTestCase.myProduct); + } - function testVariadicDivide() { - Assert.equals(0.5, BasicTestCase.myQuotient); - } + function testVariadicDivide() { + Assert.equals(0.5, BasicTestCase.myQuotient); + } - function testMod() { - Assert.equals(4, BasicTestCase.myRemainder); - } + function testMod() { + Assert.equals(4, BasicTestCase.myRemainder); + } - function testPow() { - Assert.equals(256, BasicTestCase.myPower); - } + function testPow() { + Assert.equals(256, BasicTestCase.myPower); + } - function testUnop() { - Assert.equals(7, BasicTestCase.myInc); - } + function testUnop() { + Assert.equals(7, BasicTestCase.myInc); + } }