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 {
[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
pprint = "lualib.pprint";
decompile = "src.wasm.decompile:";
+ analyze = "src.wasm.analyze:";
WasmCodeGenerator = "src.wasm.text:";
Ui = "src.ui.ui:Ui";
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()
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;
}
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
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)
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)
end
end;
+ onresize = function(self, new_width, new_height) end;
+
onkeydown = function(self, key) end;
onkeyup = function(self, key) end;
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
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
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;
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
}
--- /dev/null
+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 }
name = build_str(v.mod) .. "." .. build_str(v.name);
funcidx = funcidx;
type_ = functypes.contents[v.desc.x + 1];
+ imported = true;
}
funcidx = funcidx + 1
end
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
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)
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)