Quantcast

Cache computed values of custom functions when evaluating the script.

Johnny C. Lam [07-19-13 - 05:33]
Cache computed values of custom functions when evaluating the script.

* Split out parsing AddFunction statements into its own function.

* Functions declared using AddFunction compile into a new node type. The
  new node type "customfunction" has a single child node that points to
  the master node for the function.

* Give the script an age depending on how many times it has been
  evaluated. Cache the computed values of custom function so that
  subsequent calls to the same function within the same script pull from
  the cached values instead of re-computing from scratch.

This fixes ticket 271 in the right way.

git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@977 d5049fe3-3747-40f7-a4b5-f36d6801af5f
Filename
OvaleBestAction.lua
OvaleCompile.lua
diff --git a/OvaleBestAction.lua b/OvaleBestAction.lua
index 15d2df5..9e3599f 100644
--- a/OvaleBestAction.lua
+++ b/OvaleBestAction.lua
@@ -43,6 +43,9 @@ local API_IsUsableAction = IsUsableAction
 local API_IsUsableSpell = IsUsableSpell

 local OVALE_DEFAULT_PRIORITY = 3
+
+-- Age of the current computation.
+local self_serial = 0
 --</private-static-properties>

 --<private-static-methods>
@@ -196,6 +199,18 @@ local function ComputeCompare(element)
 	return nil
 end

+local function ComputeCustomFunction(element)
+	Ovale:Logf("custom function %s", element.name)
+	local self = OvaleBestAction
+	if not element.serial or element.serial < self_serial then
+		element.startA, element.endA, element.priorityA, element.elementA = self:Compute(element.a)
+		element.serial = self_serial
+	else
+		Ovale:Logf("Using cached values for %s", element.name)
+	end
+	return element.startA, element.endA, element.priorityA, element.elementA
+end
+
 local function ComputeFromUntil(element)
 	Ovale:Log("fromuntil")
 	local self = OvaleBestAction
@@ -676,6 +691,7 @@ local OVALE_COMPUTE_VISITOR =
 	["before"] = ComputeBefore,
 	["between"] = ComputeBetween,
 	["compare"] = ComputeCompare,
+	["customfunction"] = ComputeCustomFunction,
 	["fromuntil"] = ComputeFromUntil,
 	["function"] = ComputeFunction,
 	["group"] = ComputeGroup,
@@ -695,6 +711,7 @@ local OVALE_COMPUTE_VISITOR =
 function OvaleBestAction:StartNewAction()
 	OvaleState:Reset()
 	OvaleState:ApplyActiveSpells()
+	self_serial = self_serial + 1
 end

 function OvaleBestAction:GetActionInfo(element)
diff --git a/OvaleCompile.lua b/OvaleCompile.lua
index 8608858..5bbaa17 100644
--- a/OvaleCompile.lua
+++ b/OvaleCompile.lua
@@ -617,11 +617,11 @@ local function ParseCommands(text)
 		end
 	end

-	local masterNode
-	if (text) then
-		masterNode = strmatch(text, "node(%d+)")
+	local nodeId
+	if text then
+		nodeId = strmatch(text, "node(%d+)")
 	end
-	if (not masterNode) then
+	if not nodeId then
 		Ovale:Print("no master node")
 		return nil
 	end
@@ -633,7 +633,16 @@ local function ParseCommands(text)
 		Ovale:FormatPrint("syntax error: %s", text)
 		return nil
 	end
-	return masterNode
+	return nodeId
+end
+
+local function ParseAddFunction(name, text)
+	local nodeId = ParseCommands(text)
+	local node = self_pool:Get()
+	node.type = "customfunction"
+	node.name = name
+	node.a = self_node[tonumber(nodeId)]
+	return AddNode(node)
 end

 local function ParseAddIcon(params, text, secure)
@@ -756,10 +765,10 @@ local function CompileScript(text)
 	text = CompileDeclarations(text)
 	text = CompileInputs(text)

-	for p,t in strgmatch(text, "AddFunction%s+(%w+)%s*(%b{})") do
-		local node = ParseCommands(t)
+	for name, t in strgmatch(text, "AddFunction%s+(%w+)%s*(%b{})") do
+		local node = ParseAddFunction(name, t)
 		if node then
-			self_customFunctions[p] = "node"..node
+			self_customFunctions[name] = node
 		end
 	end

@@ -886,6 +895,8 @@ function OvaleCompile:DebugNode(node)
 			text = text .. k.."=" .. p .. " "
 		end
 		text = text .. ")"
+	elseif (node.type == "customfunction") then
+		text = self:DebugNode(node.a)
 	elseif (node.type == "if") then
 		text = "if "..self:DebugNode(node.a).." "..self:DebugNode(node.b)
 	elseif (node.type == "unless") then