added lines between callee/caller functions
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 3 Mar 2020 05:27:41 +0000 (23:27 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 3 Mar 2020 05:27:41 +0000 (23:27 -0600)
conf.lua
data/main.wasm
docs/todo
main.lua
src/ui/ui.lua
src/utils.lua
src/wasm/analyze.lua [new file with mode: 0644]
src/wasm/decompile.lua
testing.lua

index a97a94b29dd7e29cedef8105d1a7722211c772c2..8b1368951cab9b60092aba606ac43c48fcb27b25 100644 (file)
--- a/conf.lua
+++ b/conf.lua
@@ -43,7 +43,8 @@ function love.conf(t)
        t.window.title = "TBD"
        t.window.width = 1200
        t.window.height = 900
-       t.window.resizable = false
+       t.window.resizable = true
+       t.window.vsync = true
 end
 
 return {
index 2e254e94444efadbbcdd2a9b0dfa6e11d7a88244..39e07ae3327cac8fdba142156e1d1022713b2d64 100755 (executable)
Binary files a/data/main.wasm and b/data/main.wasm differ
index 52e7488f05bb5d1d8e8287ec0642d4663e3d0d42..a679a74d3f1c63fd06762f07b10284b41d8f087e 100644 (file)
--- a/docs/todo
+++ b/docs/todo
@@ -1,6 +1,9 @@
 [X] Rewrite function text builder into a more abstract system
 [ ] Implement arrows from call sites to other functions
 [ ] Implement internal arrows from "br" to destination
-[ ] Implement right click context menu
+[X] Implement right click context menu
        * Own region dismissed on mouse leave
        * Starts centered on mouse
+[X] Implement auto resizing
+[ ] Focus a function
+       * Big window with better details
index cc85e915b25df7af431aad82b145402980b6fc8f..c7311bed03ae35647d3eabd2bcda5c170e609976 100644 (file)
--- a/main.lua
+++ b/main.lua
@@ -5,6 +5,7 @@ import {
        pprint = "lualib.pprint";
 
        decompile = "src.wasm.decompile:";
+       analyze = "src.wasm.analyze:";
        WasmCodeGenerator = "src.wasm.text:";
 
        Ui = "src.ui.ui:Ui";
@@ -21,10 +22,15 @@ import {
        COLORS = "conf:COLOR_SCHEME";
 }
 
+local funcBlocks = {}
+
 class "FunctionBlock" [DraggableRect] {
        init = function(self, func, x, y)
                DraggableRect.init(self, x, y, 400, 400)
 
+               self.func = func
+               funcBlocks[func.funcidx] = self
+
                WasmCodeGenerator:setup(func, mod, COLORS)
                self.header_text = WasmCodeGenerator:build_header()
 
@@ -130,7 +136,24 @@ class "FunctionBlock" [DraggableRect] {
                end
 
                love.graphics.setColor(1, 1, 1)
-               love.graphics.draw(self.canvas)
+               love.graphics.draw(self.canvas, self.rect.x, self.rect.y)
+
+               if self.func.callees then
+                       love.graphics.setColor(COLORS.primary_light)
+                       for _, callee in ipairs(self.func.callees) do
+                               local sx, sy = self.rect:center()
+                               local tx, ty = funcBlocks[callee].rect:center()
+                               love.graphics.line(sx, sy, tx, ty)
+                       end
+               end
+               if self.func.callers then
+                       love.graphics.setColor(COLORS.secondary_dark)
+                       for _, caller in ipairs(self.func.callers) do
+                               local sx, sy = self.rect:center()
+                               local tx, ty = funcBlocks[caller].rect:center()
+                               love.graphics.line(sx, sy, tx, ty)
+                       end
+               end
        end;
 }
 
@@ -171,12 +194,19 @@ function love.load()
        ui = Ui()
 
        mod = decompile(arg[2])
+       analyze(mod)
 
        ui_region = ScrollingUiRegion(ui)
        with(ui_region) {
                rect = Rectangle(0, 0, 1200, 900);
                background_color = COLORS.background;
                line_color = COLORS.dark_background;
+               layer = 0;
+
+               onresize = function(region, new_width, new_height)
+                       region.rect.w = new_width
+                       region.rect.h = new_height
+               end;
        }
 
        local x = 0
@@ -189,6 +219,16 @@ function love.load()
        end
 
        ui:add_region(ui_region)
+
+       ui:add_region(with(UiRegion()) {
+               rect = Rectangle(0, 0, 1200, 50);
+               background_color = COLORS.dark_background;
+               layer = 10;
+
+               onresize = function(region, new_width, _)
+                       region.rect.w = new_width
+               end;
+       })
 end
 
 function love.update(dt)
index 764b201d924568d12907ba0bbdbf708c30be5b60..73d3c43433963380278599ca2daa1bccf6ba1194 100644 (file)
@@ -87,6 +87,9 @@ class "Ui" {
        end;
 
        onresize = function(self, new_width, new_height)
+               for _, region in ipairs(self.regions) do
+                       region:onresize(new_width, new_height)
+               end
        end;
 
        update = function(self, dt)
@@ -240,6 +243,8 @@ class "UiRegion" {
                end
        end;
 
+       onresize = function(self, new_width, new_height) end;
+
        onkeydown = function(self, key) end;
        onkeyup = function(self, key) end;
 
@@ -257,7 +262,7 @@ class "UiRegion" {
 
                for _, obj in ipairs(self.objects) do
                        love.graphics.push()
-                       love.graphics.translate(obj.rect.x, obj.rect.y)
+                       -- love.graphics.translate(obj.rect.x, obj.rect.y)
                        obj:draw()
                        love.graphics.pop()
                end
@@ -308,17 +313,21 @@ class "ScrollingUiRegion" [UiRegion] {
                UiRegion.onmousewheel(self, dx, dy)
 
                if self.selected_object == nil then
-                       self.zoom = self.zoom * (dy > 0 and 1.05 or (1 / 1.05))
-                       -- if self.zoom >= 1 then self.zoom = 1 end
-                       if self.zoom <= 0.2 then self.zoom = 0.2 end
+                       self:change_zoom(dy > 0 and 1.05 or (1 / 1.05))
                end
        end;
 
+       change_zoom = function(self, multiplier)
+               self.zoom = self.zoom * multiplier
+               -- if self.zoom >= 1 then self.zoom = 1 end
+               if self.zoom <= 0.2 then self.zoom = 0.2 end
+       end;
+
        update = function(self, dt)
                UiRegion.update(self, dt)
 
                if self.active then
-                       local speed = 300 / self.zoom
+                       local speed = 600 / self.zoom
                        if love.keyboard.isDown "left" then
                                self.offset.x = self.offset.x + speed * dt
                        end
@@ -331,6 +340,13 @@ class "ScrollingUiRegion" [UiRegion] {
                        if love.keyboard.isDown "down" then
                                self.offset.y = self.offset.y - speed * dt
                        end
+
+                       if love.keyboard.isDown "q" then
+                               self:change_zoom(1 + 0.5 * dt)
+                       end
+                       if love.keyboard.isDown "a" then
+                               self:change_zoom(1 - 0.5 * dt)
+                       end
                end
        end;
 
index 07f3235b5554544f7d79ce50c32233568a887d0d..812847a141e35ddda9607df381a57926bb437d22 100644 (file)
@@ -94,6 +94,10 @@ class "Rectangle" {
                        and self.y + self.h >= other.y
        end;
 
+       center = function(self)
+               return self.x + self.w / 2, self.y + self.h / 2
+       end;
+
        __lt = function(self, other) return self:intersects(other) end
 }
 
diff --git a/src/wasm/analyze.lua b/src/wasm/analyze.lua
new file mode 100644 (file)
index 0000000..52fe537
--- /dev/null
@@ -0,0 +1,42 @@
+import {}
+
+function add_function_relations(wasm_funcs)
+       function func_rel_helper(callees, instrs)
+               for _, instr in ipairs(instrs) do
+                       if instr[1] == "call" then
+                               callees[instr.x] = true
+                       elseif instr[1] == "block" or instr[1] == "loop" then
+                               func_rel_helper(callees, instr.instrs)
+                       elseif instr[1] == "if" then
+                               func_rel_helper(callees, instr.instrs)
+                               if instr.else_instrs then
+                                       func_rel_helper(callees, instr.else_instrs)
+                               end
+                       end
+               end
+       end
+
+       for _, func in ipairs(wasm_funcs) do
+               if not func.imported then
+                       func.callees = {}
+                       local callees = {}
+
+                       func_rel_helper(callees, func.body)
+
+                       for callee, _ in pairs(callees) do
+                               wasm_funcs[callee].callers = wasm_funcs[callee].callers or {}
+                               table.insert(wasm_funcs[callee].callers, func.funcidx)
+
+                               table.insert(func.callees, callee)
+                       end
+               end
+       end
+end
+
+function analyze(wasm_mod)
+       add_function_relations(wasm_mod.funcs)
+
+       return wasm_mod
+end
+
+return module { analyze }
index 512d6867f7ce6967ccc79a55ed6a1dd566f5fd3c..b67f97312f6b588ef24c8b7962cc22f4a20e00a2 100644 (file)
@@ -642,6 +642,7 @@ function parse_module(r)
                                        name = build_str(v.mod) .. "." .. build_str(v.name);
                                        funcidx = funcidx;
                                        type_ = functypes.contents[v.desc.x + 1];
+                                       imported = true;
                                }
                                funcidx = funcidx + 1
                        end
@@ -675,7 +676,8 @@ function parse_module(r)
                                name = "func" .. funcidx;
                                type_ = functypes.contents[typeidxs.contents[i] + 1];
                                locals = new_locals;
-                               body = codes.contents[i].body
+                               body = codes.contents[i].body;
+                               imported = false;
                        }
                        funcidx = funcidx + 1
                end
@@ -697,7 +699,7 @@ function parse_module(r)
 end
 
 
--- Reader util class used for interfacing
+-- Parser util class used for interfacing
 -- with the parse_helper c library
 class "Parser" {
        init = function(self, filename)
index 68233497b10635c8a5ac7d66b64b6516d6eceb59..935dc9caf3e6ea14eaa515216d8c19c26c05f4d7 100644 (file)
@@ -2,10 +2,12 @@ require "lualib.oop"
 
 import {
        decompile = "src.wasm.decompile:";
+       analyze = "src.wasm.analyze:";
        build_str = "src.utils:build_str";
        pprint = "lualib.pprint";
 }
 
 local mod = decompile(arg[1])
+analyze(mod)
 pprint(mod)