From 42d50600d1ad3138ea5326b0383f63f375832fda 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) --- kiss/src/kiss/Helpers.hx | 3 +++ kiss/src/kiss/Macros.hx | 22 ++++++++++++++----- kiss/src/test/cases/OnceTestCase.hx | 17 ++++++++++++++ kiss/src/test/cases/OnceTestObject.kiss | 8 +++++++ .../death-trap/source/DeathTrapLogic.kiss | 5 +---- 5 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 kiss/src/test/cases/OnceTestCase.hx create mode 100644 kiss/src/test/cases/OnceTestObject.kiss diff --git a/kiss/src/kiss/Helpers.hx b/kiss/src/kiss/Helpers.hx index 705da415..eeae2b5a 100644 --- a/kiss/src/kiss/Helpers.hx +++ b/kiss/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/kiss/src/kiss/Macros.hx b/kiss/src/kiss/Macros.hx index 0dcfcb75..d1827862 100644 --- a/kiss/src/kiss/Macros.hx +++ b/kiss/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/kiss/src/test/cases/OnceTestCase.hx b/kiss/src/test/cases/OnceTestCase.hx new file mode 100644 index 00000000..26c3b584 --- /dev/null +++ b/kiss/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/kiss/src/test/cases/OnceTestObject.kiss b/kiss/src/test/cases/OnceTestObject.kiss new file mode 100644 index 00000000..f602f480 --- /dev/null +++ b/kiss/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 diff --git a/projects/asciilib2/examples/death-trap/source/DeathTrapLogic.kiss b/projects/asciilib2/examples/death-trap/source/DeathTrapLogic.kiss index bfa6f8c9..f6f90c5f 100644 --- a/projects/asciilib2/examples/death-trap/source/DeathTrapLogic.kiss +++ b/projects/asciilib2/examples/death-trap/source/DeathTrapLogic.kiss @@ -1,11 +1,8 @@ -(defprop &mut firstDraw true) - (defmethod new [] 0) (defmethod :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] - (when firstDraw - (set firstDraw false) + (oncePerInstance (.blitSurface (graphics) (assets.getSurface "laptop") 0 0))) \ No newline at end of file