wasm_decompile = "src.wasm.decompile:";
wasm_analyze = "src.wasm.analyze:";
+ wasm_text = "src.wasm.text";
+
+ ui = "src.ui:";
+ ui_text = "src.ui.text:";
COLORS = "conf:COLOR_SCHEME";
}
-class "FunctionBlock" [DraggableRect] {
- init = function(self, func, x, y)
- DraggableRect.init(self, x, y, 400, 400)
+-- A node reacts to no events, just helps with the rendering / event processing ordering
+ui.register_component "node" {}
- self.func = func
- funcBlocks[func.funcidx] = self
+ui.register_component "root" {
+ resize = function(self, w, h)
+ self.rect.w = w
+ self.rect.h = h
+ end;
+}
- WasmCodeGenerator:setup(func, mod, COLORS)
- self.header_text = WasmCodeGenerator:build_header()
+ui.register_component "rect" {
+ mousepressed_trans = function(self, button, x, y)
+ return button, x - self.rect.x, y - self.rect.y
+ end;
- if func.body then
- self.body_text = WasmCodeGenerator:build_body()
- else
- self.body_text = {
- { text = "imported function", color = COLORS.code }
- }
- end
+ mousereleased_trans = function(self, button, x, y)
+ return button, x - self.rect.x, y - self.rect.y
+ end;
- self.scroll = 0
- self.body_visible = true
- self.old_height = 400
+ mousemoved_trans = function(self, x, y, dx, dy)
+ return x - self.rect.x, y - self.rect.y, dx, dy
+ end;
- self.canvas = love.graphics.newCanvas(800, 800)
- self.redraw = true
+ mousepressed = function(self, button, x, y)
+ if self.rect:contains_trans(x, y) then
+ ui.focus(self)
+ return true
+ end
end;
- toggle_body_visible = function(self)
- self.body_visible = not self.body_visible
- self.rect.h = self.body_visible and self.old_height or 22
- self.redraw = true
+ predraw = function(self)
+ love.graphics.push()
+ love.graphics.translate(self.rect.x, self.rect.y)
+ love.graphics.setColor(self.color)
+ love.graphics.rectangle("fill", 0, 0, self.rect.w, self.rect.h)
end;
- onhover = function(self, x, y)
- self.redraw = not self.selected or self.redraw
- self.selected = true
+ postdraw = function(self)
+ love.graphics.pop()
end;
+}
+
+local drag_rect = { extends = "rect" }
+function drag_rect.init(self) self.mouse_down = false end
+
+function drag_rect.mousepressed(self, button, x, y)
+ if not self.rect:contains_trans(x, y) then return false end
+
+ ui.focus(self)
+ if button == 1 then self.mouse_down = true end
+ return true
+end;
+
+function drag_rect.mousereleased(self, button, x, y)
+ if button == 1 then self.mouse_down = false end
+end
+
+function drag_rect.unfocus(self)
+ self.mouse_down = false
+end
+
+function drag_rect.mousemoved(self, x, y, dx, dy)
+ if ui.focused == self and self.mouse_down then
+ self.rect.x = self.rect.x + dx
+ self.rect.y = self.rect.y + dy
+ end
+end
+
+
+local function_block = { extends = "drag_rect" }
+function function_block.init(self, wasm_function, wasm_mod)
+ self.func = wasm_function
+ self.mod = wasm_mod
+
+ local header_text, body_text = wasm_text.generate_text_format(self.func, self.mod, COLORS)
+ self.header_text = header_text
+ self.body_text = body_text
+
+ self.scroll = 0
+ self.body_visible = true
+ self.old_height = 400
+ self.resize_down = false
+
+ self.canvas = love.graphics.newCanvas(800, 800)
+ self.redraw = true
+end
- onunhover = function(self)
- self.selected = false
+function function_block.toggle_body_visible(self)
+ self.body_visible = not self.body_visible
+ self.rect.h = self.body_visible and self.old_height or 22
+ self.redraw = true
+end
+
+function function_block.mousepressed(self, button, x, y)
+ local result = false
+ if drag_rect.mousepressed(self, button, x, y) then
self.redraw = true
- end;
+ result = true
+ end
+ if self.rect:contains_trans(x, y) and button == 2 then
+ self.resize_down = true
+ result = true
+ end
+
+ return result
+end
- onclick = function(self, button, x, y, ox, oy)
- DraggableRect.onclick(self, button, x, y, ox, oy)
-
- if button == 2 then
- local cmr
- cmr = ContextMenu(self.ui, ox, oy, {
- { text = "Toggle open", action = function()
- cmr.should_delete = true
- self:toggle_body_visible()
- end
- };
- { text = "Resize", action = function() cmr.should_delete = true end };
- { text = "Hide", action = function() end; };
- })
- self.ui:add_region(cmr)
+function function_block.mousereleased(self, button, x, y)
+ drag_rect.mousereleased(self, button, x, y)
+ if button == 2 then self.resize_down = false end
+end
+
+function function_block.focus(self)
+ self.layer = 0
+end
+
+function function_block.unfocus(self)
+ self.resize_down = false
+ self.redraw = true
+ self.layer = self.layer + 1
+end
+
+function function_block.mousemoved(self, x, y, dx, dy)
+ drag_rect.mousemoved(self, x, y, dx, dy)
+
+ if self.resize_down then
+ self.rect.w = math.min(800, math.max(100, x))
+ if self.body_visible then
+ self.rect.h = math.min(800, math.max(22, y))
+ self.old_height = self.rect.h
end
self.redraw = true
- end;
+ end
+end
+
+function function_block.wheelmoved(self, dx, dy)
+ if ui.focused ~= self then return false end
+
+ self.scroll = self.scroll - dy * 10
+ if self.scroll < 0 then self.scroll = 0 end
+ self.redraw = true
+
+ return true
+end
+
+function function_block.update(self, dt)
+ if ui.focused ~= self then return end
- onwheel = function(self, _, dy)
- self.scroll = self.scroll - dy * 10;
- if self.scroll < 0 then self.scroll = 0 end
+ if love.keyboard.isDown "down" then
+ self.scroll = self.scroll + 300 * dt
self.redraw = true
- end;
+ end
+ if love.keyboard.isDown "up" then
+ self.scroll = self.scroll - 300 * dt
+ self.redraw = true
+ end
+end
- ondrag = function(self, button, x, y, dx, dy)
- DraggableRect.ondrag(self, button, x, y, dx, dy)
+function function_block.predraw(self)
+ if self.redraw then
+ love.graphics.setCanvas(self.canvas)
+ local oldscissor = { love.graphics.getScissor() }
+ love.graphics.push()
+ love.graphics.origin()
+ love.graphics.setScissor(0, 0, self.canvas:getWidth(), self.canvas:getHeight())
+ love.graphics.setBackgroundColor(0, 0, 0, 0)
+ love.graphics.clear()
+ love.graphics.setScissor(0, 0, self.rect.w, self.rect.h)
- if y >= 24 and button == 3 then
- self.rect.w = math.min(800, math.max(100, self.rect.w + dx))
- if self.body_visible then
- self.rect.h = math.min(800, math.max(22, self.rect.h + dy))
- self.old_height = self.rect.h
- end
- self.redraw = true
- end
- end;
+ love.graphics.setColor(0, 0, 0)
+ love.graphics.rectangle("fill", 0, 0, self.rect.w, self.rect.h)
+ love.graphics.setColor(ui.focused == self and COLORS.background or COLORS.dark_background)
+ love.graphics.rectangle("fill", 2, 2, self.rect.w - 4, self.rect.h - 4)
+ love.graphics.setColor(COLORS.dark_background)
+ love.graphics.rectangle("fill", 2, 2, self.rect.w - 4, 18)
- draw = function(self)
- if self.redraw then
- love.graphics.setCanvas(self.canvas)
- local oldscissor = { love.graphics.getScissor() }
- love.graphics.push()
- love.graphics.origin()
- love.graphics.setScissor(0, 0, self.canvas:getWidth(), self.canvas:getHeight())
- love.graphics.setBackgroundColor(0, 0, 0, 0)
- love.graphics.clear()
- love.graphics.setScissor(0, 0, self.rect.w, self.rect.h)
-
- love.graphics.setColor(0, 0, 0)
- love.graphics.rectangle("fill", 0, 0, self.rect.w, self.rect.h)
- love.graphics.setColor(self.selected and COLORS.background or COLORS.dark_background)
- love.graphics.rectangle("fill", 2, 2, self.rect.w - 4, self.rect.h - 4)
- love.graphics.setColor(COLORS.dark_background)
- love.graphics.rectangle("fill", 2, 2, self.rect.w - 4, 18)
-
- local x, y = Text.render_text(2, 2, self.header_text)
-
- if self.body_visible and self.body_text then
- love.graphics.intersectScissor(2, y - 1, self.rect.w - 4, self.rect.h - 22)
- Text.render_text(2, y + 4 - self.scroll, self.body_text)
- end
-
- love.graphics.pop()
- love.graphics.setScissor(unpack(oldscissor))
- love.graphics.setCanvas()
- self.redraw = false
- end
+ local x, y = ui_text.render_text(2, 2, self.header_text)
- love.graphics.setColor(1, 1, 1)
- love.graphics.draw(self.canvas, self.rect.x, self.rect.y)
-
- if self.selected then
- 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()
- draw_arrow(sx, sy, tx, ty)
- end
- end
- if self.func.callers then
- love.graphics.setColor(COLORS.secondary)
- for _, caller in ipairs(self.func.callers) do
- local sx, sy = self.rect:center()
- local tx, ty = funcBlocks[caller].rect:center()
- draw_arrow(tx, ty, sx, sy)
- end
- end
+ if self.body_visible and self.body_text then
+ love.graphics.intersectScissor(2, y - 4, self.rect.w - 4, self.rect.h - 22)
+ ui_text.render_text(2, y - self.scroll, self.body_text)
end
- end;
-}
-class "ContextMenu" [Region] {
- init = function(self, ui, cx, cy, options)
- Region.init(self, ui)
-
- self.rect.w = 200
- self.rect.h = 25 * #options
- self.rect.x = cx - self.rect.w / 2
- self.rect.y = cy - self.rect.h / 2
-
- self.background = COLORS.secondary_dark
-
- for i, opt in ipairs(options) do
- self:add_object(with(UiButton()) {
- text = opt.text;
- background = COLORS.secondary_dark;
- hover_background = COLORS.secondary;
- click_background = COLORS.secondary_light;
- foreground = COLORS.secondary_text;
- rect = Rectangle(0, (i - 1) * 25, 200, 25);
- click = opt.action
- })
- end
+ love.graphics.pop()
+ love.graphics.setScissor(unpack(oldscissor))
+ love.graphics.setCanvas()
+ self.redraw = false
+ end
- self.layer = 100
- end;
+ love.graphics.setColor(1, 1, 1)
+ love.graphics.draw(self.canvas, self.rect.x, self.rect.y)
+end
- onmouseleave = function(self)
- self.should_delete = true
- end;
-}
+function function_block.postdraw(self) end
-function make_top_bar(app)
- local top_bar = Region()
- with(top_bar) {
- -- Maybe don't hard code this?
- rect = Rectangle(0, 0, 1200, 50);
+local scrolling = {}
+function scrolling.init(self)
+ self.offset = { x = 0; y = 0 }
+ self.line_color = { 0, 0, 0 }
+ self.zoom = 1
+ self.mouse_down = false
+end
- background_color = COLORS.dark_background;
- layer = 10;
+function scrolling.mouse_trans(self, x, y)
+ return
+ ((x - self.rect.x) - self.rect.w / 2) / self.zoom + self.rect.w / 2 - self.offset.x,
+ ((y - self.rect.y) - self.rect.h / 2) / self.zoom + self.rect.h / 2 - self.offset.y
+end
- onresize = function(region, new_width, _)
- -- Fill the width of the screen
- region.rect.w = new_width
- end
- }
+function scrolling.mousepressed_trans(self, button, x, y)
+ local mx, my = scrolling.mouse_trans(self, x, y)
+ return button, mx, my
+end
+
+function scrolling.mousereleased_trans(self, button, x, y)
+ local mx, my = scrolling.mouse_trans(self, x, y)
+ return button, mx, my
+end
- local test = with(Button()) {
- text = "Test Button";
- background = COLORS.primary_dark;
- hovered_background = COLORS.primary;
- click_background = COLORS.primary_light;
- foreground = COLORS.primary_text;
+function scrolling.mousemoved_trans(self, x, y, dx, dy)
+ local mx, my = scrolling.mouse_trans(self, x, y)
+ return mx, my, dx / self.zoom, dy / self.zoom
+end
- rect = Rectangle(10, 10, 80, 30);
- }
+function scrolling.mousepressed(self, button, x, y)
+ ui.focus(self)
+ self.mouse_down = true
+ return true
+end
+
+function scrolling.mousereleased(self, button, x, y)
+ self.mouse_down = false
+end
- top_bar:add_component(test)
- return top_bar
+function scrolling.unfocus(self)
+ self.mouse_down = false
end
+function scrolling.mousemoved(self, x, y, dx, dy)
+ if self.mouse_down then
+ self.offset.x = self.offset.x + dx
+ self.offset.y = self.offset.y + dy
+ end
+
+ return true
+end
+
+function scrolling.change_zoom(self, multiplier)
+ self.zoom = self.zoom * multiplier
+ if self.zoom <= 0.2 then self.zoom = 0.2 end
+end
+
+function scrolling.wheelmoved(self, dx, dy)
+ if ui.focused == self then
+ scrolling.change_zoom(self, dy > 0 and 1.05 or (1 / 1.05))
+ end
+end
+
+function scrolling.resize(self, w, h)
+ self.rect.w = w
+ self.rect.h = h - self.rect.y
+end
+
+function scrolling.update(self, dt)
+ if ui.focused ~= self then return end
+
+ local speed = 600 / self.zoom
+ if love.keyboard.isDown "left" then
+ self.offset.x = self.offset.x + speed * dt
+ end
+ if love.keyboard.isDown "right" then
+ self.offset.x = self.offset.x - speed * dt
+ end
+ if love.keyboard.isDown "up" then
+ self.offset.y = self.offset.y + speed * dt
+ end
+ if love.keyboard.isDown "down" then
+ self.offset.y = self.offset.y - speed * dt
+ end
+
+ if love.keyboard.isDown "q" then
+ scrolling.change_zoom(self, 1 + 0.5 * dt)
+ end
+ if love.keyboard.isDown "a" then
+ scrolling.change_zoom(self, 1 - 0.5 * dt)
+ end
+end
+
+function scrolling.predraw(self)
+ love.graphics.push()
+ love.graphics.translate(self.rect.x, self.rect.y)
+ love.graphics.setScissor(self.rect.x, self.rect.y, self.rect.w, self.rect.h)
+
+ if self.background_color ~= nil then
+ love.graphics.setColor(self.background_color)
+ love.graphics.rectangle("fill", 0, 0, self.rect.w, self.rect.h)
+ end
+ love.graphics.translate(self.rect.w / 2, self.rect.h / 2)
+ love.graphics.scale(self.zoom, self.zoom)
+ love.graphics.translate(-self.rect.w / 2, -self.rect.h / 2)
+
+ local xoff = self.offset.x
+ local yoff = self.offset.y
+ local spacing = 64
+
+ while xoff >= spacing do xoff = xoff - spacing end
+ while yoff >= spacing do yoff = yoff - spacing end
+ while xoff <= -spacing do xoff = xoff + spacing end
+ while yoff <= -spacing do yoff = yoff + spacing end
+
+ love.graphics.setColor(self.line_color)
+ for x = -60, 100 do
+ love.graphics.line(x * spacing + xoff, -self.rect.h * 2, x * spacing + xoff, self.rect.h * 4)
+ end
+ for y = -60, 100 do
+ love.graphics.line(-self.rect.w * 2, y * spacing + yoff, self.rect.w * 4, y * spacing + yoff)
+ end
+
+ love.graphics.translate(self.offset.x, self.offset.y)
+end
+
+function scrolling.postdraw(self)
+ love.graphics.pop()
+ love.graphics.setScissor()
+end
+
+ui.register_component "drag_rect" (drag_rect)
+ui.register_component "function_block" (function_block)
+ui.register_component "scrolling" (scrolling)
+
-- Responsible for containing and managing all
-- global-ish objects for the application
class "Application" {
init = function(self)
- self.ui = Ui()
- self.wasm = nil
- end;
+ ui_text.register_font("fonts/FiraCode-Regular", 16)
+ ui_text.set_font("fonts/FiraCode-Regular", 16)
- create = function(self)
- self.scrolling_region = ScrollingRegion(self.ui)
- with(self.scrolling_region) {
+ self.ui = with(ui.make_element "root") {
+ rect = Rectangle(0, 0, 0, 0);
+ }
+
+ -- ui.insert_child(self.ui, with(ui.make_element "rect") {
+ -- rect = Rectangle(0, 0, 1200, 50);
+ -- color = COLORS.dark_background;
+ -- })
+
+ self.scroller = with(ui.make_element "scrolling") {
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;
+ line_color = COLORS.primary_dark;
+ layer = 10;
}
- self.ui:add_region(self.scrolling_region)
- self.ui:add_region(make_top_bar(self))
+ ui.insert_child(self.ui, self.scroller)
+
+ self.wasm = nil
end;
bootstrap = function(self)
- local ui = self.ui
-
-- Sets all Love callbacks
function love.filedropped(file) self:open_file(file:getFilename()) end
- function love.mousepressed(x, y, button) ui:onmousedown(button, x, y) end
- function love.mousereleased(x, y, button) ui:onmouseup(button, x, y) end
- function love.mousemoved(x, y, dx, dy) ui:onmousemove(x, y, dx, dy) end
- function love.wheelmoved(dx, dy) ui:onmousewheel(dx, dy) end
- function love.keypressed(key) ui:onkeydown(key) end
- function love.keyreleased(key) ui:onkeyup(key) end
- function love.resize(w, h) ui:onresize(w, h) end
function love.update(dt) self:update(dt) end
function love.draw() self:draw() end
+
+ function love.mousepressed(x, y, button) ui.mousepressed(self.ui, button, x, y) end
+ function love.mousereleased(x, y, button) ui.mousereleased(self.ui, button, x, y) end
+ function love.mousemoved(x, y, dx, dy) ui.mousemoved(self.ui, x, y, dx, dy) end
+ function love.wheelmoved(dx, dy) ui.wheelmoved(self.ui, dx, dy) end
+ function love.keypressed(key) ui.keypressed(self.ui, key) end
+ function love.keyreleased(key) ui.keyreleased(self.ui, key) end
+ function love.resize(w, h) ui.resize(self.ui, w, h) end
end;
open_file = function(self, path)
wasm_mod = wasm_analyze(wasm_mod)
self.wasm = wasm_mod
- -- TODO DO SOMETHING HERE
+ -- Delete all old children
+ for _, chld in ipairs(self.scroller.children) do
+ chld.remove = true
+ end
+ ui.fire_propagating_event(self.scroller, "dummy")
+
+ local i = 0
+ for _, func in ipairs(wasm_mod.funcs) do
+ ui.insert_child(self.scroller, with(ui.make_element("function_block", func, wasm_mod)) {
+ rect = Rectangle(i * 400, 0, 400, 400);
+ layer = i + 1
+ })
+
+ i = i + 1
+ end
end;
update = function(self, dt)
love.event.quit()
end
- self.ui:update(dt)
+ ui.update(self.ui, dt)
end;
draw = function(self)
love.graphics.setBackgroundColor(0, 0, 0)
love.graphics.clear()
- self.ui:draw()
+ ui.draw(self.ui)
love.graphics.setScissor()
end;
}
function love.load()
- app:create()
app:bootstrap()
if arg[2] then
app:open_file(arg[2])
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
- -- local y = 0
- -- for _, func in pairs(mod.funcs) do
- -- local block = FunctionBlock(func, math.random() * 20000, math.random() * 20000)
- -- block.order = #mod.funcs * 20 + 1 - y
- -- ui_region:add_object(block)
- -- y = y + 20
- -- 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
+++ /dev/null
-import {
- Rectangle = "src.utils:Rectangle";
- uuid = "src.utils:uuidv4";
-}
-
-class "Component" {
- init = function(self)
- self.uuid = uuid()
-
- self.rect = Rectangle(0, 0, 0, 0)
- self.selected = false
- self.order = math.random(1, 1024)
- self.ui = {}
- end;
-
- onclick = function(self, button, x, y, ox, oy) end;
- ondrag = function(self, button, x, y, dx, dy) end;
- onhover = function(self, x, y) end;
- onunhover = function(self) end;
- onwheel = function(self, dx, dy) end;
- onmousedown = function(self, button, x, y, ox, oy)
- self.selected = true
- end;
-
- onselect = function(self)
- self.selected = true
- end;
- onunselect = function(self)
- self.selected = false
- end;
-
- onkey = function(self, button) end;
-
- update = function(self, dt) end;
- draw = function(self) end;
-}
-
-class "Button" [Component] {
- init = function(self)
- Component.init(self)
-
- self.text = "Placeholder"
- self.hovered = false
- self.background = { 0, 0, 0 }
- self.hover_background = { 0.2, 0.2, 0.2 }
- self.click_background = { 0.4, 0.4, 0.4 }
- self.foreground = { 1, 1, 1 }
- end;
-
- onclick = function(self, button, x, y, ox, oy)
- if button == 1 and self.click then
- self.click(self, x, y)
- end
- self.selected = false
- end;
-
- onhover = function(self, x, y)
- self.hovered = true
- end;
-
- onunhover = function(self)
- self.hovered = false
- end;
-
- draw = function(self)
- if self.selected then
- love.graphics.setColor(self.click_background)
- elseif self.hovered then
- love.graphics.setColor(self.hover_background)
- else
- love.graphics.setColor(self.background)
- end
- love.graphics.rectangle("fill", self.rect.x, self.rect.y, self.rect.w, self.rect.h)
-
- love.graphics.setColor(self.foreground)
- love.graphics.printf(self.text, self.rect.x + 2, self.rect.y + 2, self.rect.w, "center")
- end;
-}
-
-class "DraggableRect" [Component] {
- init = function(self, x, y, w, h)
- Component.init(self)
-
- self.rect = Rectangle(x, y, w, h)
- end;
-
- ondrag = function(self, button, x, y, dx, dy)
- if button == 1 then
- self.rect.x = self.rect.x + dx
- self.rect.y = self.rect.y + dy
- end
- end;
-}
-
-return module {
- Component = Component;
- Button = Button;
- DraggableRect = DraggableRect;
-}
+++ /dev/null
-import {
- revipairs = "src.utils:revipairs";
- Rectangle = "src.utils:Rectangle";
- scissor_points = "src.utils:scissor_points";
-}
-
-class "Region" {
- init = function(self, ui)
- self.active = false
- self.ui = ui
-
- self.selected_comp = nil
- self.comps = {}
-
- self.rect = Rectangle(0, 0, 0, 0)
- self.background_color = { 0, 0, 0 }
- self.layer = 0
-
- -- Internals
- self.is_mouse_down = false
- self.fire_onclick = false
- self.should_delete = false
- self.hovered_comp = nil
- end;
-
- add_component = function(self, obj)
- obj.ui = self.ui
- table.insert(self.comps, obj)
- end;
-
- -- Used for sorting in the Ui
- __lt = function(self, other)
- return self.layer < other.layer
- end;
-
- _obj_rect = function(self, obj)
- return obj.rect
- end;
-
- set_selected_comp = function(self, new_selected)
- if self.selected_comp ~= new_selected then
- if self.selected_comp ~= nil then
- self.selected_comp:onunselect()
- end
-
- self.selected_comp = new_selected
-
- if self.selected_comp ~= nil then
- self.selected_comp.order = 0
-
- for _, obj in ipairs(self.comps) do
- if obj ~= self.selected_comp then
- obj.order = obj.order + 1
- end
- end
-
- table.sort(self.comps, function(a, b)
- return a.order > b.order
- end)
-
- self.selected_comp:onselect()
- end
- end
- end;
-
- onmousedown = function(self, button, x, y, ox, oy)
- self.is_mouse_down = button
- self.fire_onclick = true
- local new_selected = nil
-
- for _, obj in revipairs(self.comps) do
- if self:_obj_rect(obj):contains(x, y) then
- new_selected = obj
- break
- end
- end
-
- self:set_selected_comp(new_selected)
-
- if self.selected_comp then
- self.selected_comp:onmousedown(button, x, y, ox, oy)
- end
- end;
-
- onmouseup = function(self, button, x, y, ox, oy)
- self.is_mouse_down = false
-
- if self.selected_comp ~= nil and self.fire_onclick then
- local obj_rect = self:_obj_rect(self.selected_comp)
- self.selected_comp:onclick(button, x - obj_rect.x, y - obj_rect.y, ox, oy)
- end
- end;
-
- onmousemove = function(self, x, y, dx, dy)
- local old_hovered = self.hovered_comp
-
- self.hovered_comp = nil
- for _, obj in revipairs(self.comps) do
- if self:_obj_rect(obj):contains(x, y) then
- obj:onhover(x, y)
- self.hovered_comp = obj
- break
- end
- end
-
- if old_hovered and self.hovered_comp ~= old_hovered then
- old_hovered:onunhover()
- end
-
- self:set_selected_comp(self.hovered_comp)
-
- if self.is_mouse_down and self.selected_comp ~= nil then
- local obj_rect = self:_obj_rect(self.selected_comp)
- self.selected_comp:ondrag(self.is_mouse_down, x - obj_rect.x, y - obj_rect.y, dx, dy)
- self.fire_onclick = self.fire_onclick and (math.abs(dx) + math.abs(dy)) < 2
- end
- end;
-
- onmouseenter = function(self)
- self.active = true
- end;
-
- onmouseleave = function(self)
- self.active = false;
- self.is_mouse_down = false
- self.fire_onclick = false
-
- self:set_selected_comp(nil)
- end;
-
- onmousewheel = function(self, dx, dy)
- if self.selected_comp ~= nil then
- self.selected_comp:onwheel(dx, dy)
- end
- end;
-
- onresize = function(self, new_width, new_height) end;
-
- onkeydown = function(self, key) end;
- onkeyup = function(self, key) end;
-
- update = function(self, dt)
- for _, obj in ipairs(self.comps) do
- obj:update(dt)
- end
- end;
-
- draw = function(self)
- if self.background_color ~= nil then
- love.graphics.setColor(self.background_color)
- love.graphics.rectangle("fill", 0, 0, self.rect.w, self.rect.h)
- end
-
- for _, comp in ipairs(self.comps) do
- love.graphics.push()
- -- love.graphics.translate(obj.rect.x, obj.rect.y)
- comp:draw()
- love.graphics.pop()
- end
- end;
-}
-
-class "ScrollingRegion" [Region] {
- init = function(self, ui)
- Region.init(self, ui)
-
- self.offset = { x = 0; y = 0; }
- self.line_color = { 0, 0, 0 }
-
- self.zoom = 1
- end;
-
- _obj_rect = function(self, obj)
- return obj.rect
- end;
-
- _transform_mouse = function(self, x, y)
- return
- (x - self.rect.w / 2) / self.zoom + self.rect.w / 2 - self.offset.x,
- (y - self.rect.h / 2) / self.zoom + self.rect.h / 2 - self.offset.y
- end;
-
- onmousedown = function(self, button, x, y, ox, oy)
- local mx, my = self:_transform_mouse(x, y)
- Region.onmousedown(self, button, mx, my, ox, oy)
- end;
-
- onmouseup = function(self, button, x, y, ox, oy)
- local mx, my = self:_transform_mouse(x, y)
- Region.onmouseup(self, button, mx, my, ox, oy)
- end;
-
- onmousemove = function(self, x, y, dx, dy)
- local mx, my = self:_transform_mouse(x, y)
- Region.onmousemove(self, mx, my, dx / self.zoom, dy / self.zoom)
-
- if self.is_mouse_down and self.selected_comp == nil then
- self.offset.x = self.offset.x + dx / self.zoom
- self.offset.y = self.offset.y + dy / self.zoom
- end
- end;
-
- onmousewheel = function(self, dx, dy)
- Region.onmousewheel(self, dx, dy)
-
- if self.selected_comp == nil then
- 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)
- Region.update(self, dt)
-
- if self.active then
- local speed = 600 / self.zoom
- if love.keyboard.isDown "left" then
- self.offset.x = self.offset.x + speed * dt
- end
- if love.keyboard.isDown "right" then
- self.offset.x = self.offset.x - speed * dt
- end
- if love.keyboard.isDown "up" then
- self.offset.y = self.offset.y + 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;
-
- draw = function(self)
- love.graphics.push()
-
- if self.background_color ~= nil then
- love.graphics.setColor(self.background_color)
- love.graphics.rectangle("fill", 0, 0, self.rect.w, self.rect.h)
- end
- local tmpbgcolor = self.background_color
- self.background_color = nil
-
- love.graphics.translate(self.rect.w / 2, self.rect.h / 2)
- love.graphics.scale(self.zoom, self.zoom)
- love.graphics.translate(-self.rect.w / 2, -self.rect.h / 2)
-
-
- local xoff = self.offset.x
- local yoff = self.offset.y
- local spacing = 64
-
- while xoff >= spacing do xoff = xoff - spacing end
- while yoff >= spacing do yoff = yoff - spacing end
- while xoff <= -spacing do xoff = xoff + spacing end
- while yoff <= -spacing do yoff = yoff + spacing end
-
- love.graphics.setColor(self.line_color)
- for x = -60, 100 do
- love.graphics.line(x * spacing + xoff, -self.rect.h * 2, x * spacing + xoff, self.rect.h * 4)
- end
- for y = -60, 100 do
- love.graphics.line(-self.rect.w * 2, y * spacing + yoff, self.rect.w * 4, y * spacing + yoff)
- end
-
- love.graphics.translate(self.offset.x, self.offset.y)
- Region.draw(self)
- love.graphics.pop()
-
- self.background_color = tmpbgcolor
- end;
-}
-
-return module {
- Region = Region;
- ScrollingRegion = ScrollingRegion;
-}
+++ /dev/null
-import { }
-
-FONTS = {}
-
-Text = {}
-function Text.render_text(x, y, text)
- local curr_font = love.graphics.getFont()
-
- local origx = x
- local fheight = curr_font:getHeight()
- local indent_level = 0
- local indentation = ""
- local fresh_newline = true
-
- for _, txt in ipairs(text) do
- if txt.text then
- local printed = txt.text
- if fresh_newline then
- if txt.post_indent then
- printed = txt.text .. indentation
- else
- printed = indentation .. txt.text
- end
- fresh_newline = false
- end
-
- if txt.background then
- love.graphics.setColor(txt.background)
- love.graphics.rectangle("fill", x, y, curr_font:getWidth(txt.text), fheight + 2);
- end
-
- if txt.color then
- love.graphics.setColor(txt.color)
- end
- love.graphics.print(printed, x, y)
-
- x = x + curr_font:getWidth(printed)
- end
-
- if txt.newline then
- y = y + fheight + 2;
- x = origx
- fresh_newline = true
- end
-
- if txt.change_indent then
- indent_level = indent_level + txt.change_indent
- indentation = ""
- for i=1,indent_level do
- indentation = indentation .. " "
- end
- end
- end
-
- return x, y
-end
-
-function Text.register_font(name, size)
- local fonts = FONTS[name] or {}
- fonts[size] = love.graphics.newFont(("res/%s.ttf"):format(name), size)
- FONTS[name] = fonts
-end
-
-function Text.set_font(name, size)
- if FONTS[name][size] then
- love.graphics.setFont(FONTS[name][size])
- end
-end
-
-return module { Text }
+++ /dev/null
-import {
- revipairs = "src.utils:revipairs";
- scissor_points = "src.utils:scissor_points";
-}
-
-class "Ui" {
- init = function(self)
- self.regions = {}
- self.active_region = nil
- end;
-
- add_region = function(self, region)
- table.insert(self.regions, region)
- table.sort(self.regions)
- end;
-
- onmousedown = function(self, button, x, y)
- local region = nil
- for _, r in revipairs(self.regions) do
- if r.rect:contains(x, y) then
- region = r
- break
- end
- end
-
- if region ~= nil then
- region:onmousedown(button, x - region.rect.x, y - region.rect.y, x, y)
- end
- end;
-
- onmouseup = function(self, button, x, y)
- local region = nil
- for _, r in revipairs(self.regions) do
- if r.rect:contains(x, y) then
- region = r
- break
- end
- end
-
- if region ~= nil then
- region:onmouseup(button, x - region.rect.x, y - region.rect.y, x, y)
- end
- end;
-
- onmousemove = function(self, x, y, dx, dy)
- local region = nil
- for _, r in revipairs(self.regions) do
- if r.rect:contains(x, y) then
- region = r
- break
- end
- end
-
- if region ~= self.active_region then
- if self.active_region then
- self.active_region:onmouseleave()
- end
-
- if region ~= nil then
- region:onmouseenter()
- end
- end
-
- if region ~= nil then
- region:onmousemove(x - region.rect.x, y - region.rect.y, dx, dy)
- end
-
- self.active_region = region
- end;
-
- onmousewheel = function(self, dx, dy)
- if not self.active_region then return end
- self.active_region:onmousewheel(dx, dy)
- end;
-
- onkeydown = function(self, key)
- if not self.active_region then return end
- self.active_region:onkeydown(key)
- end;
-
- onkeyup = function(self, key)
- if not self.active_region then return end
- self.active_region:onkeyup(key)
- 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)
- for i, region in ipairs(self.regions) do
- region:update(dt)
-
- if region.should_delete then
- table.remove(self.regions, i)
- end
- end
- end;
-
- draw = function(self)
- for _, region in ipairs(self.regions) do
- love.graphics.push()
- love.graphics.setScissor(scissor_points(region.rect.x, region.rect.y, region.rect.w, region.rect.h))
- love.graphics.translate(region.rect.x, region.rect.y)
- region:draw()
- love.graphics.setScissor()
- love.graphics.pop()
- end
- end;
-}
-
-return module { Ui }
import {
+ Rectangle = "src.utils:Rectangle";
+ revipairs = "src.utils:revipairs";
}
-ui_class = {}
-function ui_class:make()
+components = {}
+function component_lookup(type_, name)
+ if type(components[type_][name]) == "function" then
+ return components[type_][name]
+ end
+
+ if components[type_].extends then
+ local l = component_lookup(components[type_].extends, name)
+ if l then return l end
+ return false
+ end
+
+ return false
+end
+
+ui = {}
+function ui.register_component(name)
+ if components[name] ~= nil then
+ error("Component with name " .. name .. " already registered")
+ end
+
+ return function(component)
+ components[name] = component
+ end
+end
+
+function ui.make_element(type_, ...)
+ local o = {
+ type = type_; -- Type used to look up component functions
+ layer = layer or 0; -- Used for sorting children
+ remove = false; -- Whether to remove this element
+ rect = Rectangle(0, 0, 0, 0); -- Rectangle bounds of the object
+ children = {}; -- List of children, sorted by layer
+
+ -- Any other data can be appended to this object
+ }
+
+ local init_func = component_lookup(type_, "init")
+ if init_func then init_func(o, ...) end
+
+ return o
+end
+
+ui.focused = nil
+function ui.focus(elem)
+ if ui.focused == elem then return end
+
+ if ui.focused then
+ local unfocus_func = component_lookup(ui.focused.type, "unfocus")
+ if unfocus_func then unfocus_func(ui.focused) end
+ end
+
+ ui.focused = elem
+
+ if ui.focused then
+ local focus_func = component_lookup(ui.focused.type, "focus")
+ if focus_func then focus_func(ui.focused) end
+ end
+end
+
+function ui.insert_child(parent, child)
+ table.insert(parent.children, child)
+ ui.sort_children(parent)
+end
+
+function ui.sort_children(elem)
+ table.sort(elem.children, function(a, b)
+ return a.layer < b.layer
+ end)
+end
+
+function ui.fire_stoppable_event(elem, eventname, ...)
+ local args
+
+ local args_trans_func = component_lookup(elem.type, eventname .. "_trans")
+ if args_trans_func then
+ args = { args_trans_func(elem, ...) }
+ else
+ args = { ... }
+ end
+ if #elem.children > 0 then
+ for _, chld in ipairs(elem.children) do
+ if ui.fire_stoppable_event(chld, eventname, unpack(args)) then
+ if chld.remove then
+ table.remove(elem.children, i)
+ end
+
+ ui.sort_children(elem)
+
+ return true
+ end
+ end
+ end
+
+ local event_func = component_lookup(elem.type, eventname)
+ if event_func then return event_func(elem, unpack(args)) end
+ return false
+end
+
+function ui.fire_propagating_event(elem, eventname, ...)
+ local args
+ local args_trans_func = component_lookup(elem.type, eventname .. "_trans")
+ if args_trans_func then
+ args = { args_trans_func(elem, ...) }
+ else
+ args = { ... }
+ end
+ if #elem.children > 0 then
+ for i, chld in ipairs(elem.children) do
+ ui.fire_propagating_event(chld, eventname, unpack(args))
+
+ if chld.remove then
+ table.remove(elem.children, i)
+ end
+ end
+
+ -- TODO: Maybe make this a flag?
+ -- ui.resort = true?
+ ui.sort_children(elem)
+ end
+
+ local event_func = component_lookup(elem.type, eventname)
+ if event_func then event_func(elem, unpack(args)) end
end
-ui = singleton(ui_class)
+local events = {
+ "mousepressed",
+ "mousereleased",
+ "mousemoved",
+ "wheelmoved",
+ "keypressed",
+ "keyreleased",
+}
+for _, ev in ipairs(events) do
+ ui[ev] = function(elem, ...) ui.fire_stoppable_event(elem, ev, ...) end
+end
+
+function ui.update(elem, dt)
+ ui.fire_propagating_event(elem, "update", dt)
+end
+
+function ui.resize(elem, w, h)
+ ui.fire_propagating_event(elem, "resize", w, h)
+end
+
+function ui.draw(elem)
+ local predraw_func = component_lookup(elem.type, "predraw")
+ if predraw_func then predraw_func(elem) end
+
+ for _, chld in revipairs(elem.children) do
+ ui.draw(chld)
+ end
+
+ local postdraw_func = component_lookup(elem.type, "postdraw")
+ if postdraw_func then postdraw_func(elem) end
+end
return module {
ui
--- /dev/null
+import { }
+
+FONTS = {}
+
+Text = {}
+function Text.render_text(x, y, text)
+ local curr_font = love.graphics.getFont()
+
+ local origx = x
+ local fheight = curr_font:getHeight()
+ local indent_level = 0
+ local indentation = ""
+ local fresh_newline = true
+
+ for _, txt in ipairs(text) do
+ if txt.text then
+ local printed = txt.text
+ if fresh_newline then
+ if txt.post_indent then
+ printed = txt.text .. indentation
+ else
+ printed = indentation .. txt.text
+ end
+ fresh_newline = false
+ end
+
+ if txt.background then
+ love.graphics.setColor(txt.background)
+ love.graphics.rectangle("fill", x, y, curr_font:getWidth(txt.text), fheight + 2);
+ end
+
+ if txt.color then
+ love.graphics.setColor(txt.color)
+ end
+ love.graphics.print(printed, x, y)
+
+ x = x + curr_font:getWidth(printed)
+ end
+
+ if txt.newline then
+ y = y + fheight + 2;
+ x = origx
+ fresh_newline = true
+ end
+
+ if txt.change_indent then
+ indent_level = indent_level + txt.change_indent
+ indentation = ""
+ for i=1,indent_level do
+ indentation = indentation .. " "
+ end
+ end
+ end
+
+ return x, y
+end
+
+function Text.register_font(name, size)
+ local fonts = FONTS[name] or {}
+ fonts[size] = love.graphics.newFont(("res/%s.ttf"):format(name), size)
+ FONTS[name] = fonts
+end
+
+function Text.set_font(name, size)
+ if FONTS[name][size] then
+ love.graphics.setFont(FONTS[name][size])
+ end
+end
+
+return module { Text }
end
function revipairs(t)
- local max = 1
- while t[max] ~= nil do
- max = max + 1
- end
+ local max = #t + 1
local function ripairs_it(t, i)
i = i - 1
local v = t[i]
and y >= self.y and y <= self.y + self.h
end;
+ contains_trans = function(self, x, y)
+ return x >= 0 and y >= 0 and x <= self.w and y <= self.h
+ end;
+
intersects = function(self, other)
return self.x <= other.x + other.w
and self.x + self.w >= other.x
pprint = "lualib.pprint";
}
+-- The current line number during processing
+-- This is a global to the functions and is shared
+-- This processed can not be parallelized for this variable
+-- (but I wouldn't paralleize it right now anyway)
+local line = 1
+
function build_type(text, type_, color)
for _, t in ipairs(type_.param_types) do
table.insert(text, { text = t .. " ", color = color })
end
end
-WasmCodeGenerator = singleton {
- init = function(self) end;
+function build_header(func, mod, colors)
+ local text = {}
- setup = function(self, func, mod, colors)
- self.func = func
- self.mod = mod
- self.colors = colors;
- self.line = 1
- end;
+ if mod.start ~= nil and mod.start.contents.func == func.funcidx then
+ table.insert(text, { text = "*START* ", color = colors.primary_text })
+ end
+ table.insert(text, { text = "func[" .. func.funcidx .. "] ", color = colors.code })
+ table.insert(text, { text = func.name, color = colors.keyword })
+ table.insert(text, { text = ": ", color = colors.code })
- build_header = function(self)
- local text = {}
+ build_type(text, func.type_, colors.code)
+ table.insert(text, { newline = true })
- if self.mod.start ~= nil and self.mod.start.contents.func == self.func.funcidx then
- table.insert(text, { text = "*START* ", color = self.colors.primary_text })
- end
- table.insert(text, { text = "func[" .. self.func.funcidx .. "] ", color = self.colors.code })
- table.insert(text, { text = self.func.name, color = self.colors.keyword })
- table.insert(text, { text = ": ", color = self.colors.code })
-
- build_type(text, self.func.type_, self.colors.code)
- table.insert(text, { newline = true })
-
- return text
- end;
-
- add_line_number = function(self, textlist, newline)
- if newline == nil then newline = true end
-
- table.insert(textlist, { newline = newline })
- table.insert(textlist, {
- text = ("%4d"):format(line),
- color = self.colors.code,
- background = self.colors.dark_background,
- post_indent = true
- })
- table.insert(textlist, { text = " ", post_indent = true })
-
- line = line + 1
- end;
-
- instr_to_text = function(self, textlist, instr)
- if instr[1] == "block" then
- table.insert(textlist, { change_indent = 1 })
- for _, ins in ipairs(instr.instrs) do
- self:instr_to_text(textlist, ins)
- end
- table.insert(textlist, { change_indent = -1 })
- self:add_line_number(textlist)
- table.insert(textlist, { text = "label ", color = self.colors.jumppoint })
- table.insert(textlist, { text = instr.label, color = self.colors.value })
+ return text
+end
- elseif instr[1] == "loop" then
- self:add_line_number(textlist)
- table.insert(textlist, { text = "loop ", color = self.colors.jumppoint })
- table.insert(textlist, { text = instr.label, color = self.colors.value, change_indent = 1 })
+function add_line_number(textlist, colors, newline)
+ if newline == nil then newline = true end
- for _, ins in ipairs(instr.instrs) do
- self:instr_to_text(textlist, ins)
- end
- table.insert(textlist, { change_indent = -1 })
+ table.insert(textlist, { newline = newline })
+ table.insert(textlist, {
+ text = ("%4d"):format(line),
+ color = colors.code,
+ background = colors.dark_background,
+ post_indent = true
+ })
+ table.insert(textlist, { text = " ", post_indent = true })
- elseif instr[1] == "if" then
- self:add_line_number(textlist)
- table.insert(textlist, { text = "if", color = self.colors.jumppoint, change_indent = 1 })
- for _, ins in ipairs(instr.instrs) do
- self:instr_to_text(textlist, ins)
+ line = line + 1
+end
+
+function instr_to_text(textlist, instr, func, mod, colors)
+ if instr[1] == "block" then
+ table.insert(textlist, { change_indent = 1 })
+ for _, ins in ipairs(instr.instrs) do
+ instr_to_text(textlist, ins, func, mod, colors)
+ end
+ table.insert(textlist, { change_indent = -1 })
+ add_line_number(textlist, colors)
+ table.insert(textlist, { text = "label ", color = colors.jumppoint })
+ table.insert(textlist, { text = instr.label, color = colors.value })
+
+ elseif instr[1] == "loop" then
+ add_line_number(textlist, colors)
+ table.insert(textlist, { text = "loop ", color = colors.jumppoint })
+ table.insert(textlist, { text = instr.label, color = colors.value, change_indent = 1 })
+
+ for _, ins in ipairs(instr.instrs) do
+ instr_to_text(textlist, ins, func, mod, colors)
+ end
+ table.insert(textlist, { change_indent = -1 })
+
+ elseif instr[1] == "if" then
+ add_line_number(textlist, colors)
+ table.insert(textlist, { text = "if", color = colors.jumppoint, change_indent = 1 })
+ for _, ins in ipairs(instr.instrs) do
+ instr_to_text(textlist, ins, func, mod, colors)
+ end
+ table.insert(textlist, { change_indent = -1 })
+
+ if #instr.else_instrs > 0 then
+ add_line_number(textlist, colors)
+ table.insert(textlist, { text = "else", color = colors.jumppoint, change_indent = 1 })
+ for _, ins in ipairs(instr.else_instrs) do
+ instr_to_text(textlist, ins, func, mod, colors)
end
table.insert(textlist, { change_indent = -1 })
+ end
- if #instr.else_instrs > 0 then
- self:add_line_number(textlist)
- table.insert(textlist, { text = "else", color = self.colors.jumppoint, change_indent = 1 })
- for _, ins in ipairs(instr.else_instrs) do
- self:instr_to_text(textlist, ins)
+ elseif instr[1] == "call" then
+ add_line_number(textlist, colors)
+ table.insert(textlist, { text = instr[1] .. " ", color = colors.keyword })
+ table.insert(textlist, { text = mod.funcs[instr.x].name, color = colors.value })
+
+ elseif instr[1] == "call_indirect" then
+ add_line_number(textlist, colors)
+ table.insert(textlist, { text = ("%s [%d] "):format(instr[1], instr.table), color = colors.keyword })
+ build_type(textlist, mod.types.contents[instr.x + 1], colors.code)
+
+ elseif instr[1]:match("local") then
+ add_line_number(textlist, colors)
+ table.insert(textlist, { text = instr[1] .. " ", color = colors.keyword })
+ table.insert(textlist, { text = func.locals[instr.x + 1].name, color = colors.value })
+
+ else
+ add_line_number(textlist, colors)
+ table.insert(textlist, { text = instr[1] .. " ", color = colors.keyword })
+ if instr.x then
+ if type(instr.x) == "table" then
+ if instr.x[1] == "memarg" then
+ table.insert(textlist, {
+ text = ("align=0x%02x offset=0x%04x"):format(instr.x.align, instr.x.offset);
+ color = colors.value
+ })
end
- table.insert(textlist, { change_indent = -1 })
- end
- elseif instr[1] == "call" then
- self:add_line_number(textlist)
- table.insert(textlist, { text = instr[1] .. " ", color = self.colors.keyword })
- table.insert(textlist, { text = self.mod.funcs[instr.x].name, color = self.colors.value })
-
- elseif instr[1] == "call_indirect" then
- self:add_line_number(textlist)
- table.insert(textlist, { text = ("%s [%d] "):format(instr[1], instr.table), color = self.colors.keyword })
- build_type(textlist, self.mod.types.contents[instr.x + 1], self.colors.code)
-
- elseif instr[1]:match("local") then
- self:add_line_number(textlist)
- table.insert(textlist, { text = instr[1] .. " ", color = self.colors.keyword })
- table.insert(textlist, { text = self.func.locals[instr.x + 1].name, color = self.colors.value })
-
- else
- self:add_line_number(textlist)
- table.insert(textlist, { text = instr[1] .. " ", color = self.colors.keyword })
- if instr.x then
- if type(instr.x) == "table" then
- if instr.x[1] == "memarg" then
- table.insert(textlist, {
- text = ("align=0x%02x offset=0x%04x"):format(instr.x.align, instr.x.offset);
- color = self.colors.value
- })
+ if instr.x[1] == "labelidx" then
+ if instr.x.block then
+ table.insert(textlist, { text = instr.x.block.label .. " ", color = colors.value })
end
-
- if instr.x[1] == "labelidx" then
- if instr.x.block then
- table.insert(textlist, { text = instr.x.block.label .. " ", color = self.colors.value })
- end
- table.insert(textlist, { text = ("[0x%02x]"):format(instr.x.labelidx), color = self.colors.code })
- end
- else
- table.insert(textlist, { text = tostring(instr.x), color = self.colors.value })
+ table.insert(textlist, { text = ("[0x%02x]"):format(instr.x.labelidx), color = colors.code })
end
+ else
+ table.insert(textlist, { text = tostring(instr.x), color = colors.value })
end
end
+ end
- return line
- end;
+ return line
+end
- build_body = function(self)
- local text = {}
- line = 1
+function build_body(func, mod, colors)
+ if func.imported then
+ return { text = "Imported function", colors = colors.code, newline = true }
+ end
- table.insert(text, { text = " Locals:", color = self.colors.keyword, newline = true, change_indent = 2 })
- for _, loc in ipairs(self.func.locals) do
- table.insert(text, { text = loc.type_ .. " " .. loc.name, color = self.colors.code , newline = true })
- end
+ local text = {}
+ table.insert(text, { text = " Locals:", color = colors.keyword, newline = true, change_indent = 2 })
+ for _, loc in ipairs(func.locals) do
+ table.insert(text, { text = loc.type_ .. " " .. loc.name, color = colors.code , newline = true })
+ end
- if #self.func.locals == 0 then
- table.insert(text, { text = "no locals", color = self.colors.code, newline = true })
- end
+ if #func.locals == 0 then
+ table.insert(text, { text = "no locals", color = colors.code, newline = true })
+ end
- table.insert(text, { newline = true, change_indent = -2 })
- table.insert(text, { text = " Body:", color = self.colors.keyword })
+ table.insert(text, { newline = true, change_indent = -2 })
+ table.insert(text, { text = " Body:", color = colors.keyword })
- for _, instr in ipairs(self.func.body) do
- self:instr_to_text(text, instr)
- end
+ for _, instr in ipairs(func.body) do
+ instr_to_text(text, instr, func, mod, colors)
+ end
- return text
- end;
-}
+ return text
+end
+
+function generate_text_format(func, mod, colors, line_start)
+ line = line_start or 1
+ local heading = build_header(func, mod, colors)
+ local body = build_body(func, mod, colors)
+ return heading, body
+end
return module {
- WasmCodeGenerator;
+ generate_text_format = generate_text_format;
+ build_header = build_header;
+ build_body = build_body;
}
-