diff --git a/build.hxml b/build.hxml index ddae091..7af058f 100644 --- a/build.hxml +++ b/build.hxml @@ -9,4 +9,6 @@ -D lua-vanilla -D lua-ver 5.1 +--macro include("bin") + --lua build/haxe.lua diff --git a/src/bin/HelloWorldGUI.hx b/src/bin/HelloWorldGUI.hx new file mode 100644 index 0000000..a7d6df9 --- /dev/null +++ b/src/bin/HelloWorldGUI.hx @@ -0,0 +1,74 @@ +package bin; + +import kernel.log.Log; +import lib.ui.elements.TextElement; +import lib.Pos; +import lib.ui.elements.UIElement; +import lib.ui.elements.LayerdRootElement; +import kernel.ui.WindowContext; +import kernel.ps.ProcessHandle; +import kernel.ps.Process; + +@:build(macros.Binstore.includeBin("HelloWorld-GUI", ["hello-gui"])) +class HelloWorldGUI implements Process { + private var handle:ProcessHandle; + private var ctx:WindowContext; + private var requestRender:Void->Void; + private var root:LayerdRootElement; + + public function new() {} + + public function run(handle:ProcessHandle) { + this.handle = handle; + + var stateless = handle.createStatelessWindowContext(); + this.ctx = stateless.ctx; + this.requestRender = stateless.requestRender; + + stateless.setRenderFunc(this.render); + + this.root = new LayerdRootElement(); + + this.ctx.delegateEvents(this.root); + + this.requestRender(); + } + + private function render() { + var children:Array<{element:UIElement, offset:Pos}> = [ + { + element: new TextElement("Hello World", { + uiEvents: { + onClick: () -> { + Log.debug("Hello World"); + } + } + }), + offset: new Pos({x: 0, y: 0}) + }, + { + element: new TextElement("Holla Mundo", { + uiEvents: { + onClick: () -> { + Log.debug("Holla Mundo"); + } + } + }), + offset: new Pos({x: 0, y: 1}) + }, + { + element: new TextElement("Ayyy", { + uiEvents: { + onClick: () -> { + Log.debug("Ayy"); + } + } + }), + offset: new Pos({x: 4, y: 1}) + } + ]; + + this.root.setChildren(children); + this.root.render(ctx.getSize()).renderToContext(ctx); + } +} diff --git a/src/bin/Terminal.hx b/src/bin/Terminal.hx index 0c3ccd2..43346af 100644 --- a/src/bin/Terminal.hx +++ b/src/bin/Terminal.hx @@ -141,7 +141,7 @@ class Terminal implements Process { var commandArgs:Array = args.slice(1); - var ps = getProgByName(commandName); + var ps = BinStore.instantiate(commandName); if (ps == null) { this.backlog.push("Unknown command: " + commandName); this.requestRender(); @@ -204,15 +204,6 @@ class Terminal implements Process { this.requestRender(); } - private function getProgByName(name:String):Process { - var bin = BinStore.getBinByAlias(name); - if (bin == null) { - return null; - } - - return Type.createInstance(bin.c, []); - } - private function moveCursorToInput() { var size = this.ctx.getSize(); this.ctx.setCursorPos(this.input.length + 2, size.y - 1); diff --git a/src/kernel/DCEHack.hx b/src/kernel/DCEHack.hx deleted file mode 100644 index edfacf6..0000000 --- a/src/kernel/DCEHack.hx +++ /dev/null @@ -1,9 +0,0 @@ -package kernel; - -@:keep -class DCEHack { - // Dont actually call this - public static function load():Array { - macros.DCEHack.dceGenerateCreate(); - } -} diff --git a/src/kernel/Init.hx b/src/kernel/Init.hx index 93d16b5..91675f6 100644 --- a/src/kernel/Init.hx +++ b/src/kernel/Init.hx @@ -8,7 +8,6 @@ import kernel.net.Routing; import lib.Debug; import kernel.ui.WindowManager; import kernel.net.Net; -import kernel.DCEHack; // Important for DCE hack class Init { @:allow(kernel.KernelEvents) diff --git a/src/kernel/binstore/Bin.hx b/src/kernel/binstore/Bin.hx index 4aef4d9..201807d 100644 --- a/src/kernel/binstore/Bin.hx +++ b/src/kernel/binstore/Bin.hx @@ -6,7 +6,7 @@ import kernel.ps.Process; Represents a callable program. **/ typedef Bin = { - c:Class, + c:Void->Process, name:String, aliases:Array, } diff --git a/src/kernel/binstore/BinStore.hx b/src/kernel/binstore/BinStore.hx index 4715f37..ad43c6f 100644 --- a/src/kernel/binstore/BinStore.hx +++ b/src/kernel/binstore/BinStore.hx @@ -1,64 +1,31 @@ package kernel.binstore; -import bin.turtle.Excavate; -import bin.turtle.Patrol; -import bin.pathfinder.PFClient; -import bin.ID; -import bin.exporter.Res; -import bin.exporter.ResManager; -import bin.KSettings; -import bin.Perf; -import bin.srsc.CLI; -import bin.srsc.SiteRessourceController; -import bin.HelloWorldService; -import bin.Service; -import bin.LSPS; -import bin.Turtle; -import bin.Terminal; -import bin.Redstone; -import bin.Net; -import bin.KernelLog; -import bin.HelloWorld; -import bin.GPS; -import bin.Disk; -import haxe.ds.ReadOnlyArray; +import kernel.ps.Process; +import macros.Binstore; class BinStore { - private static final store:ReadOnlyArray = [ - {c: Disk, name: "Disk", aliases: ["disk"]}, - {c: GPS, name: "GPS", aliases: ["gps"]}, - {c: HelloWorld, name: "HelloWorld", aliases: ["hello"]}, - {c: KernelLog, name: "KernelLog", aliases: ["log"]}, - {c: Net, name: "Net", aliases: ["net"]}, - {c: Redstone, name: "Redstone", aliases: ["redstone", "rs"]}, - {c: Terminal, name: "Terminal", aliases: ["terminal", "term"]}, - {c: Turtle, name: "Turtle", aliases: ["turtle", "t"]}, - {c: LSPS, name: "PM", aliases: ["lsps"]}, - {c: Service, name: "Service", aliases: ["service", "srv"]}, - {c: HelloWorldService, name: "HelloWorldService", aliases: ["hello-service"]}, - {c: SiteRessourceController, name: "SiteRessourceController", aliases: ["srsc"]}, - {c: CLI, name: "SRSC CLI", aliases: ["srsc-cli"]}, - {c: Perf, name: "Perf", aliases: ["perf"]}, - {c: KSettings, name: "KSettings", aliases: ["ksettings", "ks"]}, - {c: ResManager, name: "ResManager", aliases: ["resmanager", "resmgr"]}, - {c: Res, name: "Res", aliases: ["res"]}, - {c: ID, name: "ID", aliases: ["id"]}, - {c: PFClient, name: "PFClient", aliases: ["pfclient"]}, - {c: Patrol, name: "Patrol", aliases: ["patrol"]}, - {c: Excavate, name: "Excavate", aliases: ["excavate"]} - ]; + private static final bins:Array = populateStore(); - public static function getBinByName(name:String):Null { - for (bin in store) { - if (bin.name == name) { - return bin; + private static function populateStore() + return { + var bins:Array = []; + Binstore.generateBinStore(); + return bins; + } + + public static function instantiate(alias:String):Null { + for (bin in bins) { + for (a in bin.aliases) { + if (a == alias) { + return bin.c(); + } } } return null; } - public static function getBinByAlias(alias:String):Null { - for (bin in store) { + private static function getBinByAlias(alias:String):Null { + for (bin in bins) { for (a in bin.aliases) { if (a == alias) { return bin; @@ -68,7 +35,7 @@ class BinStore { return null; } - public static function getNameByAlias(alias:String):String { + public static function getNameByAlias(alias:String):Null { var bin = getBinByAlias(alias); if (bin == null) { return null; diff --git a/src/kernel/ps/Process.hx b/src/kernel/ps/Process.hx index 1465e00..f61d095 100644 --- a/src/kernel/ps/Process.hx +++ b/src/kernel/ps/Process.hx @@ -3,7 +3,6 @@ package kernel.ps; /** Defines an independent process that can be run by the kernel. **/ -@:autoBuild(macros.DCEHack.DCEHack.dceInclude()) interface Process { public function run(handle:ProcessHandle):Void; } diff --git a/src/kernel/service/Service.hx b/src/kernel/service/Service.hx index 7788450..3e88158 100644 --- a/src/kernel/service/Service.hx +++ b/src/kernel/service/Service.hx @@ -21,13 +21,13 @@ class Service { } public function start() { - var bin = BinStore.getBinByAlias(this.binName); + var ps = BinStore.instantiate(this.binName); - if (bin == null) { + if (ps == null) { throw new Error('Bin ${this.binName} not found'); } - this.ps = Type.createInstance(bin.c, this.args); + this.ps = ps; this.pid = ProcessManager.run(this.ps, {}); } diff --git a/src/kernel/service/ServiceManager.hx b/src/kernel/service/ServiceManager.hx index c16d227..d867f98 100644 --- a/src/kernel/service/ServiceManager.hx +++ b/src/kernel/service/ServiceManager.hx @@ -65,7 +65,7 @@ class ServiceManager { } public static function register(name:String, binName:String, args:Array):Outcome { - if (BinStore.getBinByAlias(binName) == null) { + if (BinStore.getNameByAlias(binName) == null) { return Failure("bin not found"); } diff --git a/src/lib/HomeContext.hx b/src/lib/HomeContext.hx index c48d5a1..fec460f 100644 --- a/src/lib/HomeContext.hx +++ b/src/lib/HomeContext.hx @@ -31,7 +31,7 @@ class HomeContext { private var selectedOutput:String = "main"; private var selectedOutputIndex:Int = -1; - private final listedApps:Array = ["terminal", "log", "pfclient"]; + private final listedApps:Array = ["terminal", "log", "tprint", "hello-gui"]; public function new() {} @@ -101,14 +101,13 @@ class HomeContext { } private function spawnPs(binName:String) { - var bin = BinStore.getBinByAlias(binName); + var ps = BinStore.instantiate(binName); - if (bin == null) { + if (ps == null) { Log.error('Could not find bin: ${binName}'); return; } - var ps = Type.createInstance(bin.c, []); var pid = ProcessManager.run(ps, {}); var lastContextID = -1; diff --git a/src/macros/Binstore.hx b/src/macros/Binstore.hx new file mode 100644 index 0000000..af5a537 --- /dev/null +++ b/src/macros/Binstore.hx @@ -0,0 +1,68 @@ +package macros; + +import haxe.macro.TypeTools; +import haxe.macro.Context; +import haxe.macro.Expr; + +using Lambda; + +class Binstore { + static var bins:Array<{c:TypePath, name:String, alias:Array}> = []; + + macro static function includeBin(name:String, alias:Array):Array { + var fields = Context.getBuildFields(); + var localClass = Context.getLocalClass().get(); + + // FIXME: Right now we are trusting the dev that the class implements Process. It will fail later + // anyway but better tell ihm now. + + var constructor = fields.find((field) -> field.name == "new"); + + if (!constructor.access.contains(APublic)) { + Context.error("Constructor needs to be public", constructor.pos); + } + + switch constructor.kind { + case FFun(f): + if (f.args.length != 0) { + Context.error("Process constructor are not allowed to have args", constructor.pos); + } + default: + Context.error("Somethings wrong with your constructor", constructor.pos); + } + + switch TypeTools.toComplexType(Context.getLocalType()) { + case TPath(p): + bins.push({ + c: p, + name: name, + alias: alias + }); + default: + Context.error("IDFK what went wrong", localClass.pos); + } + + return fields; + } + + public macro static function generateBinStore() { + var exprs:Array = []; + + for (bin in bins) { + var c = bin.c; + exprs.push(macro { + bins.push({ + c: () -> { + return new $c(); + }, + name: $v{bin.name}, + aliases: $v{bin.alias} + }); + }); + } + + return macro { + $a{exprs} + }; + } +} diff --git a/src/macros/DCEHack.hx b/src/macros/DCEHack.hx deleted file mode 100644 index b911d45..0000000 --- a/src/macros/DCEHack.hx +++ /dev/null @@ -1,44 +0,0 @@ -package macros; - -import haxe.macro.Context; -import haxe.macro.Expr; - -using Lambda; - -class DCEHack { - public static final classes:Array = []; - - macro static public function dceInclude():Array { - #if !display - var localClass = Context.getLocalClass(); - - if (localClass == null) { - return Context.getBuildFields(); - } - - // Ignore abstract classes - if (localClass.get().isAbstract) { - return Context.getBuildFields(); - } - - classes.push(Context.getLocalType()); - #end - return Context.getBuildFields(); - } - - macro static public function dceGenerateCreate() { - var exprs = []; - - for (c in classes) { - switch (c) { - case TInst(_.get() => t, _): - var path:TypePath = {pack: t.pack, name: t.name}; - exprs.push(macro new $path()); - default: - Context.error("Unknown type: " + c, Context.currentPos()); - } - } - - return macro return $a{exprs}; - } -}