From 2acefb133dd5224e5d3e5fc36d9a2531e39d8ee2 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Tue, 27 Apr 2021 20:05:57 -0600 Subject: [PATCH] (once) and (oncePerInstance) --- src/kiss/Helpers.hx | 3 +++ src/kiss/Macros.hx | 22 ++++++++++++++++------ src/test/cases/OnceTestCase.hx | 17 +++++++++++++++++ src/test/cases/OnceTestObject.kiss | 8 ++++++++ 4 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 src/test/cases/OnceTestCase.hx create mode 100644 src/test/cases/OnceTestObject.kiss diff --git a/src/kiss/Helpers.hx b/src/kiss/Helpers.hx index 705da41..eeae2b5 100644 --- a/src/kiss/Helpers.hx +++ b/src/kiss/Helpers.hx @@ -9,7 +9,9 @@ import kiss.Reader; import kiss.CompileError; import kiss.Kiss; import kiss.SpecialForms; +import uuid.Uuid; +using uuid.Uuid; using tink.MacroApi; using kiss.Reader; using kiss.Helpers; @@ -364,6 +366,7 @@ class Helpers { list: (exps:Array) -> ListExp(exps).withPosOf(posRef), str: (s:String) -> StrExp(s).withPosOf(posRef), symbol: (name:String) -> Symbol(name).withPosOf(posRef), + gensym: () -> Symbol('_${Uuid.v4().toShort()}').withPosOf(posRef), raw: (code:String) -> RawHaxe(code).withPosOf(posRef), typed: (path:String, exp:ReaderExp) -> TypedExp(path, exp).withPosOf(posRef), meta: (m:String, exp:ReaderExp) -> MetaExp(m, exp).withPosOf(posRef), diff --git a/src/kiss/Macros.hx b/src/kiss/Macros.hx index 0dcfcb7..d182786 100644 --- a/src/kiss/Macros.hx +++ b/src/kiss/Macros.hx @@ -2,12 +2,10 @@ package kiss; import haxe.macro.Expr; import haxe.macro.Context; -import uuid.Uuid; import kiss.Reader; import kiss.Kiss; import kiss.CompileError; -using uuid.Uuid; using kiss.Kiss; using kiss.Reader; using kiss.Helpers; @@ -178,8 +176,8 @@ class Macros { macros["or"] = (wholeExp:ReaderExp, args:Array, k) -> { wholeExp.checkNumArgs(2, null, "(or [v1] [v2] [values...])"); var b = wholeExp.expBuilder(); - var uniqueVarName = "_" + Uuid.v4().toShort(); - var uniqueVarSymbol = b.symbol(uniqueVarName); + + var uniqueVarSymbol = b.gensym(); b.begin([ b.call(b.symbol("deflocal"), [ @@ -204,8 +202,8 @@ class Macros { macros["and"] = (wholeExp:ReaderExp, args:Array, k) -> { wholeExp.checkNumArgs(2, null, "(and [v1] [v2] [values...])"); var b = wholeExp.expBuilder(); - var uniqueVarName = "_" + Uuid.v4().toShort(); - var uniqueVarSymbol = b.symbol(uniqueVarName); + + var uniqueVarSymbol = b.gensym(); var condCases = [ for (arg in args) { @@ -552,8 +550,20 @@ class Macros { wholeExp.checkNumArgs(1, 1, "(collect [iterator or iterable])"); var b = wholeExp.expBuilder(); b.call(b.symbol("for"), [b.symbol("elem"), exps[0], b.symbol("elem")]); + }; + + function once(macroName:String, wholeExp:ReaderExp, exps:Array, k:KissState) { + wholeExp.checkNumArgs(1, null, '($macroName [body...])'); + var b = wholeExp.expBuilder(); + var flag = b.gensym(); + // define the field: + k.convert(b.call(b.symbol(macroName), [b.meta("mut", flag), b.symbol("true")])); + 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"); + return macros; } diff --git a/src/test/cases/OnceTestCase.hx b/src/test/cases/OnceTestCase.hx new file mode 100644 index 0000000..26c3b58 --- /dev/null +++ b/src/test/cases/OnceTestCase.hx @@ -0,0 +1,17 @@ +package test.cases; + +import utest.Test; +import utest.Assert; +import kiss.Prelude; + +class OnceTestCase extends Test { + function testOnce() { + new OnceTestObject(); + new OnceTestObject(); + Assert.equals(1, OnceTestObject.staticCount); + Assert.equals(2, OnceTestObject.instanceCount); + } +} + +@:build(kiss.Kiss.build("OnceTestObject.kiss")) +class OnceTestObject {} diff --git a/src/test/cases/OnceTestObject.kiss b/src/test/cases/OnceTestObject.kiss new file mode 100644 index 0000000..f602f48 --- /dev/null +++ b/src/test/cases/OnceTestObject.kiss @@ -0,0 +1,8 @@ +(defvar &mut staticCount 0) +(defvar &mut instanceCount 0) + +(defmethod new [] + (once + (+= staticCount 1)) + (oncePerInstance + (+= instanceCount 1))) \ No newline at end of file