blob: 5707e466e09f80057acd8bce4d4d04faaaf2b79b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
(** Neovere Live - Interactive Urbit runtime with Eio *)
open Eio.Std
open Nock_lib
let version = "0.1.0"
let project_root =
match Sys.getenv_opt "NEOVERE_ROOT" with
| Some root -> root
| None ->
let exe_dir = Filename.dirname Sys.executable_name in
let rec find_root dir =
let pills_dir = Filename.concat dir "pills" in
if Sys.file_exists pills_dir && Sys.is_directory pills_dir then dir
else
let parent = Filename.dirname dir in
if String.equal parent dir then
failwith "unable to locate project root containing pills/"
else find_root parent
in
find_root exe_dir
(** Boot the ship *)
let boot_ship pier_name =
traceln "Booting ship: %s" pier_name;
let pier_path = Filename.concat project_root pier_name in
if Sys.file_exists pier_path then begin
traceln "Error: Pier %s already exists" pier_path;
exit 1
end;
Unix.mkdir pier_path 0o755;
let state = State.create ~pier_path () in
(* Boot ivory *)
let ivory_path = Filename.concat project_root "pills/ivory.pill" in
begin match Boot.boot_ivory state ivory_path with
| Error _ -> traceln "Ivory boot failed"; exit 1
| Ok () -> traceln "✓ Ivory kernel loaded"
end;
(* Boot solid *)
let solid_path = Filename.concat project_root "pills/solid.pill" in
begin match Boot.boot_solid_lifecycle state solid_path with
| Error _ -> traceln "Solid boot failed"; exit 1
| Ok () ->
traceln "✓ Solid boot complete (events: %Ld)" (State.event_number state)
end;
state
(** Main event loop using Eio's structured concurrency *)
let run_event_loop env state =
let stdin = Eio.Stdenv.stdin env in
let stdout = Eio.Stdenv.stdout env in
let clock = Eio.Stdenv.clock env in
traceln "\n~zod:dojo> ";
Eio.Flow.copy_string "~zod:dojo> " stdout;
(* Create Dill wire for terminal 1 *)
let dill_wire = Noun.cell
(Noun.atom (Z.of_int (Char.code 'd')))
(Noun.cell
(Noun.atom_of_string "term")
(Noun.cell (Noun.atom (Z.of_int 1)) (Noun.atom Z.zero)))
in
(* Process effects helper *)
let process_effects result =
match result with
| Noun.Cell (effects, _new_core) ->
Nock_lib.Dill.render_effects ~stdout effects
| _ ->
traceln "Warning: poke returned unexpected structure"
in
(* Run concurrent fibers *)
Switch.run @@ fun _sw ->
Fiber.all [
(* Terminal input fiber *)
(fun () ->
traceln "[Input fiber started]";
Nock_lib.Dill.input_loop ~stdin ~state ~wire:dill_wire process_effects
);
(* Timer fiber (placeholder) *)
(fun () ->
traceln "[Timer fiber started]";
while true do
Eio.Time.sleep clock 10.0;
traceln "[Timer tick]"
done
);
(* Status fiber (placeholder) *)
(fun () ->
traceln "[Status fiber started]";
Eio.Time.sleep clock 5.0;
let eve = State.event_number state in
traceln "[Status] Events: %Ld" eve;
);
]
(** Main entry point *)
let main env =
let pier_name =
if Array.length Sys.argv > 1 then Sys.argv.(1)
else "zod-live"
in
traceln "╔═══════════════════════════════════════════════════════╗";
traceln "║ Neovere Live v%s ║" version;
traceln "╚═══════════════════════════════════════════════════════╝";
traceln "";
(* Boot ship *)
let state = boot_ship pier_name in
traceln "";
traceln "Ship booted successfully!";
traceln "Starting event loop with Eio structured concurrency...";
traceln "";
(* Run event loop *)
run_event_loop env state;
(* Cleanup *)
State.close_eventlog state;
traceln "Shutdown complete"
let () =
Eio_main.run @@ fun env ->
try
main env
with
| Sys_error msg ->
traceln "System error: %s" msg;
exit 1
| e ->
traceln "Fatal error: %s" (Printexc.to_string e);
Printexc.print_backtrace stderr;
exit 1
|