(once) and (oncePerInstance)

This commit is contained in:
2021-04-27 20:05:57 -06:00
parent fa72a9776d
commit 42d50600d1
5 changed files with 45 additions and 10 deletions

View File

@@ -9,7 +9,9 @@ import kiss.Reader;
import kiss.CompileError; import kiss.CompileError;
import kiss.Kiss; import kiss.Kiss;
import kiss.SpecialForms; import kiss.SpecialForms;
import uuid.Uuid;
using uuid.Uuid;
using tink.MacroApi; using tink.MacroApi;
using kiss.Reader; using kiss.Reader;
using kiss.Helpers; using kiss.Helpers;
@@ -364,6 +366,7 @@ class Helpers {
list: (exps:Array<ReaderExp>) -> ListExp(exps).withPosOf(posRef), list: (exps:Array<ReaderExp>) -> ListExp(exps).withPosOf(posRef),
str: (s:String) -> StrExp(s).withPosOf(posRef), str: (s:String) -> StrExp(s).withPosOf(posRef),
symbol: (name:String) -> Symbol(name).withPosOf(posRef), symbol: (name:String) -> Symbol(name).withPosOf(posRef),
gensym: () -> Symbol('_${Uuid.v4().toShort()}').withPosOf(posRef),
raw: (code:String) -> RawHaxe(code).withPosOf(posRef), raw: (code:String) -> RawHaxe(code).withPosOf(posRef),
typed: (path:String, exp:ReaderExp) -> TypedExp(path, exp).withPosOf(posRef), typed: (path:String, exp:ReaderExp) -> TypedExp(path, exp).withPosOf(posRef),
meta: (m:String, exp:ReaderExp) -> MetaExp(m, exp).withPosOf(posRef), meta: (m:String, exp:ReaderExp) -> MetaExp(m, exp).withPosOf(posRef),

View File

@@ -2,12 +2,10 @@ package kiss;
import haxe.macro.Expr; import haxe.macro.Expr;
import haxe.macro.Context; import haxe.macro.Context;
import uuid.Uuid;
import kiss.Reader; import kiss.Reader;
import kiss.Kiss; import kiss.Kiss;
import kiss.CompileError; import kiss.CompileError;
using uuid.Uuid;
using kiss.Kiss; using kiss.Kiss;
using kiss.Reader; using kiss.Reader;
using kiss.Helpers; using kiss.Helpers;
@@ -178,8 +176,8 @@ class Macros {
macros["or"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k) -> { macros["or"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k) -> {
wholeExp.checkNumArgs(2, null, "(or [v1] [v2] [values...])"); wholeExp.checkNumArgs(2, null, "(or [v1] [v2] [values...])");
var b = wholeExp.expBuilder(); var b = wholeExp.expBuilder();
var uniqueVarName = "_" + Uuid.v4().toShort();
var uniqueVarSymbol = b.symbol(uniqueVarName); var uniqueVarSymbol = b.gensym();
b.begin([ b.begin([
b.call(b.symbol("deflocal"), [ b.call(b.symbol("deflocal"), [
@@ -204,8 +202,8 @@ class Macros {
macros["and"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k) -> { macros["and"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k) -> {
wholeExp.checkNumArgs(2, null, "(and [v1] [v2] [values...])"); wholeExp.checkNumArgs(2, null, "(and [v1] [v2] [values...])");
var b = wholeExp.expBuilder(); var b = wholeExp.expBuilder();
var uniqueVarName = "_" + Uuid.v4().toShort();
var uniqueVarSymbol = b.symbol(uniqueVarName); var uniqueVarSymbol = b.gensym();
var condCases = [ var condCases = [
for (arg in args) { for (arg in args) {
@@ -552,8 +550,20 @@ class Macros {
wholeExp.checkNumArgs(1, 1, "(collect [iterator or iterable])"); wholeExp.checkNumArgs(1, 1, "(collect [iterator or iterable])");
var b = wholeExp.expBuilder(); var b = wholeExp.expBuilder();
b.call(b.symbol("for"), [b.symbol("elem"), exps[0], b.symbol("elem")]); b.call(b.symbol("for"), [b.symbol("elem"), exps[0], b.symbol("elem")]);
};
function once(macroName:String, wholeExp:ReaderExp, exps:Array<ReaderExp>, 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; return macros;
} }

View File

@@ -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 {}

View File

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

View File

@@ -1,11 +1,8 @@
(defprop &mut firstDraw true)
(defmethod new [] 0) (defmethod new [] 0)
(defmethod :Void initialize [:Assets assets] (defmethod :Void initialize [:Assets assets]
(assets.loadSurface "laptop" AssetPaths.laptop__srf)) (assets.loadSurface "laptop" AssetPaths.laptop__srf))
(defmethod :Void update [:Game game :Float deltaSeconds] 0) (defmethod :Void update [:Game game :Float deltaSeconds] 0)
(defmethod :Void draw [:Void->Graphics graphics :Assets assets] (defmethod :Void draw [:Void->Graphics graphics :Assets assets]
(when firstDraw (oncePerInstance
(set firstDraw false)
(.blitSurface (graphics) (assets.getSurface "laptop") 0 0))) (.blitSurface (graphics) (assets.getSurface "laptop") 0 0)))