kissCache

This commit is contained in:
2022-08-07 22:16:53 +00:00
parent c3953040df
commit 773b122b74
2 changed files with 43 additions and 4 deletions

View File

@@ -58,7 +58,9 @@ typedef KissState = {
macroVars:Map<String, Dynamic>,
collectedBlocks:Map<String, Array<ReaderExp>>,
inStaticFunction:Bool,
typeHints:Array<Var>
typeHints:Array<Var>,
conversionStack:Array<ReaderExp>,
stateChanged:Bool
};
#end
@@ -168,6 +170,8 @@ class Kiss {
collectedBlocks: new Map(),
inStaticFunction: false,
typeHints: [],
conversionStack: [],
stateChanged: false
};
k.doc = (form:String, minArgs:Null<Int>, maxArgs:Null<Int>, expectedForm = "", doc = "") -> {
@@ -413,8 +417,27 @@ class Kiss {
}
static var macroUsed = false;
static var expCache:haxe.DynamicAccess<String> = null;
static var cacheFile = ".kissCache.json";
static var cacheThreshold = 0.2;
public static function readerExpToHaxeExpr(exp:ReaderExp, k:KissState):Expr {
#if kissCache
if (expCache == null) {
expCache = if (sys.FileSystem.exists(cacheFile)) {
haxe.Json.parse(File.getContent(cacheFile));
} else {
{};
}
}
var str = Reader.toString(exp.def);
if (expCache.exists(str)) {
return Context.parse(expCache[str], Helpers.macroPos(exp));
}
#end
if (k.conversionStack.length == 0) k.stateChanged = false;
k.conversionStack.push(exp);
var macros = k.macros;
var fieldForms = k.fieldForms;
var specialForms = k.specialForms;
@@ -437,6 +460,7 @@ class Kiss {
var none = EBlock([]).withMacroPosOf(exp);
var startTime = haxe.Timer.stamp();
var expr = switch (exp.def) {
case None:
none;
@@ -455,6 +479,7 @@ class Kiss {
var field = fieldForms[ff](exp, args.copy(), k);
k.fieldList.push(field);
k.fieldDict[field.name] = field;
k.stateChanged = true;
none; // Field forms are no-ops
case CallExp({pos: _, def: Symbol(mac)}, args) if (macros.exists(mac)):
checkNumArgs(mac);
@@ -516,8 +541,13 @@ class Kiss {
default:
throw KissError.fromExp(exp, 'conversion not implemented');
};
#if test
// Sys.println(expr.toString()); // For very fine-grained codegen inspection--slows compilation a lot.
var conversionTime = haxe.Timer.stamp() - startTime;
k.conversionStack.pop();
#if kissCache
if (conversionTime > cacheThreshold && !k.stateChanged) {
expCache[str] = expr.toString();
File.saveContent(cacheFile, haxe.Json.stringify(expCache));
}
#end
return expr;

View File

@@ -410,6 +410,7 @@ class Macros {
k.doc("defmacro", 3, null, '(defMacro <name> [<args...>] <body...>)');
macros["defmacro"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
k.stateChanged = true;
var name = switch (exps[0].def) {
case Symbol(name): name;
default: throw KissError.fromExp(exps[0], "macro name should be a symbol");
@@ -528,6 +529,7 @@ class Macros {
k.doc("undefmacro", 1, 1, '(undefMacro <name>)');
macros["undefmacro"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
k.stateChanged = true;
var name = switch (exps[0].def) {
case Symbol(name): name;
default: throw KissError.fromExp(exps[0], "macro name should be a symbol");
@@ -540,6 +542,7 @@ class Macros {
k.doc("defreadermacro", 3, null, '(defReaderMacro <optional &start> <"<startingString>" or [<startingStrings...>]> [<streamArgName>] <body...>)');
macros["defreadermacro"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
k.stateChanged = true;
// reader macros declared in the form (defreadermacro &start ...) will only be applied
// at the beginning of lines
@@ -610,6 +613,7 @@ class Macros {
k.doc("undefreadermacro", 1, 1, '(undefReaderMacro <optional &start> ["<startingString>" or <startingStrings...>])');
macros["undefreadermacro"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
k.stateChanged = true;
// 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
@@ -663,6 +667,7 @@ class Macros {
k.doc("defalias", 2, 2, "(defAlias <<&call or &ident> whenItsThis> <makeItThis>)");
macros["defalias"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
k.stateChanged = true;
var name = getAliasName(k, exps[0], "defAlias");
aliasMap[name] = exps[1].def;
@@ -672,6 +677,7 @@ class Macros {
k.doc("undefalias", 1, 1, "(undefAlias <<&call or &ident> alias>)");
macros["undefalias"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
k.stateChanged = true;
var name = getAliasName(k, exps[0], "undefAlias");
aliasMap.remove(name);
@@ -896,6 +902,7 @@ class Macros {
k.doc("defMacroVar", 2, 2, "(defMacroVar <name> <value>)");
macros["defMacroVar"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
k.stateChanged = true;
var name = exps[0].symbolNameValue();
k.macroVars[name] = Helpers.runAtCompileTimeDynamic(exps[1], k);
@@ -905,6 +912,7 @@ class Macros {
k.doc("setMacroVar",2, 2, "(setMacroVar <name> <value>)");
macros["setMacroVar"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
k.stateChanged = true;
var name = exps[0].symbolName().withPosOf(exps[0]);
var b = wholeExp.expBuilder();
@@ -913,6 +921,7 @@ class Macros {
k.doc("defMacroFunction", 3, null, "(defMacroFunction <name> [<args>] <body...>)");
macros["defMacroFunction"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
k.stateChanged = true;
var b = wholeExp.expBuilder();
var name = exps[0].symbolNameValue();
var lambdaExp = b.callSymbol("lambda", [exps[1]].concat(exps.slice(2)));