nomen-lang 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/NOMEN_AGENTS.md CHANGED
@@ -18,6 +18,7 @@ Flags worth knowing:
18
18
 
19
19
  - `--in <path>` override the entry file/folder
20
20
  - `--arch c` emit C instead of AArch64 assembly
21
+ - `--arch js` emit a JavaScript module and run it with Node
21
22
  - `--platform macos|ios|linux|android|windows|web` target platform
22
23
  - `--watch` rebuild on change
23
24
  - `-f <regex>` filter which test files run
@@ -45,7 +46,7 @@ const int x = 5 // avoid
45
46
  const lines = split_lines(text) // good — inferred List<Line>
46
47
  const List<Line> lines = split_lines(text) // avoid
47
48
  const msg = "hi" // good
48
- var items = [1, 2, 3] // good — int[]
49
+ const items = [1, 2, 3] // good — int[]
49
50
  ```
50
51
 
51
52
  Annotate when you need a wider type (`int64` rather than `int`), when there is
@@ -179,7 +180,7 @@ import System::Test
179
180
  func add = (int a, int b, out int) => a + b
180
181
 
181
182
  func add_once = () {
182
- const int r = add(1, 1)
183
+ const r = add(1, 1)
183
184
  }
184
185
 
185
186
  pub func test_add = (ref Tester t) {
@@ -197,10 +198,10 @@ pub func bench_add = (ref Tester t) {
197
198
 
198
199
  ```nomen
199
200
  const x = 5 // immutable
200
- var int y = 10 // mutable, explicit type
201
- const int[] nums = [1, 2, 3]
202
- const int[10] buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] // fixed-length
203
- var int? maybe = null // nullable
201
+ var y = 10 // mutable
202
+ const nums = [1, 2, 3]
203
+ const int[10] buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] // fixed-length — annotation is load-bearing
204
+ var int? maybe = null // nullable — annotation required (null infers nothing)
204
205
  ref Box q = p // mv-struct alias — must be spelled (no plain copies)
205
206
  ```
206
207
 
@@ -41,6 +41,14 @@
41
41
  * the desugar synthesizes the override dispatching ids to the app's
42
42
  * `.on_<event>` handlers.
43
43
  *
44
+ * - LIFETIME — on macOS the process OUTLIVES the last window: after the
45
+ * frame loop ends, run keeps pumping until Dock Quit or the app menu's
46
+ * Quit (⌘Q) ends the process, and a Dock click reopens the window and
47
+ * resumes frames. Apps that want exit-on-last-close call `win.quit()`
48
+ * from their `close_requested` override; self-terminating programs
49
+ * (tests, probes) call `win.quit()` where they used to call
50
+ * `win.close()`.
51
+ *
44
52
  * Handlers are METHODS on the app (the `ref self` receiver), so app state —
45
53
  * every control field — is reachable without lambda captures (capturing a
46
54
  * control MOVES it; a capture-free method reference moves nothing). The
@@ -1708,12 +1708,78 @@ pub mv struct Container: Control {
1708
1708
  // close() and close_pending() extern both flags.
1709
1709
  int nomen_close_pending = 0;
1710
1710
  int nomen_close_forced = 0;
1711
+ // App-lifetime quit: set by Window.quit() — the keep-alive pump
1712
+ // (Window.keep_alive) returns when it is set. On macOS the process
1713
+ // stays alive after the last window closes (the platform
1714
+ // convention); quitting is explicit.
1715
+ int nomen_app_quit = 0;
1716
+ // Set by the Dock-click reopen handler; Window.run resumes the
1717
+ // frame loop when it is set.
1718
+ int nomen_app_reopen = 0;
1719
+ // The app menu's Quit item (⌘Q): sets the same flag Window.quit()
1720
+ // sets, so main unwinds normally instead of hard-exiting.
1721
+ void nomen_quit_clicked_imp(id self, SEL cmd, id sender) {
1722
+ (void)self; (void)cmd; (void)sender;
1723
+ nomen_app_quit = 1;
1724
+ }
1725
+ // Dock click while every window is closed: re-show the window and
1726
+ // tell the Nomen loop to resume its frame loop.
1727
+ BOOL nomen_app_should_reopen_imp(id self, SEL cmd, id notification, BOOL flag) {
1728
+ (void)self; (void)cmd; (void)notification; (void)flag;
1729
+ nomen_app_reopen = 1;
1730
+ return NO; // handled — the Nomen loop re-shows the window
1731
+ }
1711
1732
  BOOL nomen_window_should_close_imp(id self, SEL cmd, id notification) {
1712
1733
  (void)self; (void)cmd; (void)notification;
1713
1734
  if (nomen_close_forced) return YES;
1714
1735
  nomen_close_pending = 1;
1715
1736
  return NO;
1716
1737
  }
1738
+ // The one NSApp/window delegate class (resize, close interception,
1739
+ // menu Quit, Dock reopen). Created lazily, registered once.
1740
+ void nomen_window_did_resize(id self, SEL cmd, id notification);
1741
+ Class nomen_delegate_class(void) {
1742
+ Class Dc = objc_getClass("NomenResizeDelegate");
1743
+ if (!Dc) {
1744
+ Dc = objc_allocateClassPair(objc_getClass("NSObject"), "NomenResizeDelegate", 0);
1745
+ if (Dc) {
1746
+ class_addMethod(Dc, sel_registerName("windowDidResize:"), (IMP)nomen_window_did_resize, "v@:@");
1747
+ // Close interception: refuse the native close, set the
1748
+ // pending flag, let Window.run consult the app.
1749
+ class_addMethod(Dc, sel_registerName("windowShouldClose:"), (IMP)nomen_window_should_close_imp, "c@:@");
1750
+ class_addMethod(Dc, sel_registerName("quitClicked:"), (IMP)nomen_quit_clicked_imp, "v@:@");
1751
+ class_addMethod(Dc, sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:"), (IMP)nomen_app_should_reopen_imp, "c@:@c");
1752
+ objc_registerClassPair(Dc);
1753
+ }
1754
+ }
1755
+ return Dc;
1756
+ }
1757
+ // The standard app menu: an app submenu with Quit (⌘Q). Quit sets
1758
+ // the app-quit flag on the delegate so main unwinds normally
1759
+ // (terminate: would hard-exit past Nomen's cleanup).
1760
+ void nomen_install_app_menu(id delegate) {
1761
+ static BOOL installed = 0;
1762
+ if (installed) return;
1763
+ installed = 1;
1764
+ id nsapp = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
1765
+ ((void(*)(id, SEL, id))objc_msgSend)(nsapp, sel_registerName("setDelegate:"), delegate);
1766
+ id nsstr = (id)objc_getClass("NSString");
1767
+ SEL utf8 = sel_registerName("stringWithUTF8String:");
1768
+ id menubar = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSMenu"), sel_registerName("alloc"));
1769
+ menubar = ((id(*)(id, SEL))objc_msgSend)(menubar, sel_registerName("init"));
1770
+ id app_item = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSMenuItem"), sel_registerName("alloc"));
1771
+ app_item = ((id(*)(id, SEL, id, SEL, id))objc_msgSend)(app_item, sel_registerName("initWithTitle:action:keyEquivalent:"), ((id(*)(id, SEL, const char*))objc_msgSend)(nsstr, utf8, "Nomen"), (SEL)0, ((id(*)(id, SEL, const char*))objc_msgSend)(nsstr, utf8, ""));
1772
+ id submenu = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSMenu"), sel_registerName("alloc"));
1773
+ submenu = ((id(*)(id, SEL, id))objc_msgSend)(submenu, sel_registerName("initWithTitle:"), ((id(*)(id, SEL, const char*))objc_msgSend)(nsstr, utf8, "Nomen"));
1774
+ id quit_item = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSMenuItem"), sel_registerName("alloc"));
1775
+ quit_item = ((id(*)(id, SEL, id, SEL, id))objc_msgSend)(quit_item, sel_registerName("initWithTitle:action:keyEquivalent:"), ((id(*)(id, SEL, const char*))objc_msgSend)(nsstr, utf8, "Quit"), sel_registerName("quitClicked:"), ((id(*)(id, SEL, const char*))objc_msgSend)(nsstr, utf8, "q"));
1776
+ ((void(*)(id, SEL, unsigned long))objc_msgSend)(quit_item, sel_registerName("setKeyEquivalentModifierMask:"), 1UL << 20);
1777
+ ((void(*)(id, SEL, id))objc_msgSend)(quit_item, sel_registerName("setTarget:"), delegate);
1778
+ ((void(*)(id, SEL, id))objc_msgSend)(submenu, sel_registerName("addItem:"), quit_item);
1779
+ ((void(*)(id, SEL, id))objc_msgSend)(app_item, sel_registerName("setSubmenu:"), submenu);
1780
+ ((void(*)(id, SEL, id))objc_msgSend)(menubar, sel_registerName("addItem:"), app_item);
1781
+ ((void(*)(id, SEL, id))objc_msgSend)(nsapp, sel_registerName("setMainMenu:"), menubar);
1782
+ }
1717
1783
  void nomen_window_did_resize(id self, SEL cmd, id notification) {
1718
1784
  (void)self; (void)cmd; (void)notification;
1719
1785
  if (g_resize_grid && g_resize_win) {
@@ -1750,12 +1816,78 @@ pub mv struct Container: Control {
1750
1816
  // close() and close_pending() extern both flags.
1751
1817
  int nomen_close_pending = 0;
1752
1818
  int nomen_close_forced = 0;
1819
+ // App-lifetime quit: set by Window.quit() — the keep-alive pump
1820
+ // (Window.keep_alive) returns when it is set. On macOS the process
1821
+ // stays alive after the last window closes (the platform
1822
+ // convention); quitting is explicit.
1823
+ int nomen_app_quit = 0;
1824
+ // Set by the Dock-click reopen handler; Window.run resumes the
1825
+ // frame loop when it is set.
1826
+ int nomen_app_reopen = 0;
1827
+ // The app menu's Quit item (⌘Q): sets the same flag Window.quit()
1828
+ // sets, so main unwinds normally instead of hard-exiting.
1829
+ void nomen_quit_clicked_imp(id self, SEL cmd, id sender) {
1830
+ (void)self; (void)cmd; (void)sender;
1831
+ nomen_app_quit = 1;
1832
+ }
1833
+ // Dock click while every window is closed: re-show the window and
1834
+ // tell the Nomen loop to resume its frame loop.
1835
+ BOOL nomen_app_should_reopen_imp(id self, SEL cmd, id notification, BOOL flag) {
1836
+ (void)self; (void)cmd; (void)notification; (void)flag;
1837
+ nomen_app_reopen = 1;
1838
+ return NO; // handled — the Nomen loop re-shows the window
1839
+ }
1753
1840
  BOOL nomen_window_should_close_imp(id self, SEL cmd, id notification) {
1754
1841
  (void)self; (void)cmd; (void)notification;
1755
1842
  if (nomen_close_forced) return YES;
1756
1843
  nomen_close_pending = 1;
1757
1844
  return NO;
1758
1845
  }
1846
+ // The one NSApp/window delegate class (resize, close interception,
1847
+ // menu Quit, Dock reopen). Created lazily, registered once.
1848
+ void nomen_window_did_resize(id self, SEL cmd, id notification);
1849
+ Class nomen_delegate_class(void) {
1850
+ Class Dc = objc_getClass("NomenResizeDelegate");
1851
+ if (!Dc) {
1852
+ Dc = objc_allocateClassPair(objc_getClass("NSObject"), "NomenResizeDelegate", 0);
1853
+ if (Dc) {
1854
+ class_addMethod(Dc, sel_registerName("windowDidResize:"), (IMP)nomen_window_did_resize, "v@:@");
1855
+ // Close interception: refuse the native close, set the
1856
+ // pending flag, let Window.run consult the app.
1857
+ class_addMethod(Dc, sel_registerName("windowShouldClose:"), (IMP)nomen_window_should_close_imp, "c@:@");
1858
+ class_addMethod(Dc, sel_registerName("quitClicked:"), (IMP)nomen_quit_clicked_imp, "v@:@");
1859
+ class_addMethod(Dc, sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:"), (IMP)nomen_app_should_reopen_imp, "c@:@c");
1860
+ objc_registerClassPair(Dc);
1861
+ }
1862
+ }
1863
+ return Dc;
1864
+ }
1865
+ // The standard app menu: an app submenu with Quit (⌘Q). Quit sets
1866
+ // the app-quit flag on the delegate so main unwinds normally
1867
+ // (terminate: would hard-exit past Nomen's cleanup).
1868
+ void nomen_install_app_menu(id delegate) {
1869
+ static BOOL installed = 0;
1870
+ if (installed) return;
1871
+ installed = 1;
1872
+ id nsapp = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
1873
+ ((void(*)(id, SEL, id))objc_msgSend)(nsapp, sel_registerName("setDelegate:"), delegate);
1874
+ id nsstr = (id)objc_getClass("NSString");
1875
+ SEL utf8 = sel_registerName("stringWithUTF8String:");
1876
+ id menubar = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSMenu"), sel_registerName("alloc"));
1877
+ menubar = ((id(*)(id, SEL))objc_msgSend)(menubar, sel_registerName("init"));
1878
+ id app_item = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSMenuItem"), sel_registerName("alloc"));
1879
+ app_item = ((id(*)(id, SEL, id, SEL, id))objc_msgSend)(app_item, sel_registerName("initWithTitle:action:keyEquivalent:"), ((id(*)(id, SEL, const char*))objc_msgSend)(nsstr, utf8, "Nomen"), (SEL)0, ((id(*)(id, SEL, const char*))objc_msgSend)(nsstr, utf8, ""));
1880
+ id submenu = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSMenu"), sel_registerName("alloc"));
1881
+ submenu = ((id(*)(id, SEL, id))objc_msgSend)(submenu, sel_registerName("initWithTitle:"), ((id(*)(id, SEL, const char*))objc_msgSend)(nsstr, utf8, "Nomen"));
1882
+ id quit_item = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSMenuItem"), sel_registerName("alloc"));
1883
+ quit_item = ((id(*)(id, SEL, id, SEL, id))objc_msgSend)(quit_item, sel_registerName("initWithTitle:action:keyEquivalent:"), ((id(*)(id, SEL, const char*))objc_msgSend)(nsstr, utf8, "Quit"), sel_registerName("quitClicked:"), ((id(*)(id, SEL, const char*))objc_msgSend)(nsstr, utf8, "q"));
1884
+ ((void(*)(id, SEL, unsigned long))objc_msgSend)(quit_item, sel_registerName("setKeyEquivalentModifierMask:"), 1UL << 20);
1885
+ ((void(*)(id, SEL, id))objc_msgSend)(quit_item, sel_registerName("setTarget:"), delegate);
1886
+ ((void(*)(id, SEL, id))objc_msgSend)(submenu, sel_registerName("addItem:"), quit_item);
1887
+ ((void(*)(id, SEL, id))objc_msgSend)(app_item, sel_registerName("setSubmenu:"), submenu);
1888
+ ((void(*)(id, SEL, id))objc_msgSend)(menubar, sel_registerName("addItem:"), app_item);
1889
+ ((void(*)(id, SEL, id))objc_msgSend)(nsapp, sel_registerName("setMainMenu:"), menubar);
1890
+ }
1759
1891
  void nomen_window_did_resize(id self, SEL cmd, id notification) {
1760
1892
  (void)self; (void)cmd; (void)notification;
1761
1893
  if (g_resize_grid && g_resize_win) {
@@ -1767,42 +1899,28 @@ pub mv struct Container: Control {
1767
1899
  #arch: c
1768
1900
  #platform: macos
1769
1901
  nomen_set_resize_target(self, win);
1770
- Class Dc = objc_getClass("NomenResizeDelegate");
1771
- if (!Dc) {
1772
- Dc = objc_allocateClassPair(objc_getClass("NSObject"), "NomenResizeDelegate", 0);
1773
- if (Dc) {
1774
- class_addMethod(Dc, sel_registerName("windowDidResize:"), (IMP)nomen_window_did_resize, "v@:@");
1775
- // Close interception: refuse the native close, set the
1776
- // pending flag, let Window.run consult the app.
1777
- class_addMethod(Dc, sel_registerName("windowShouldClose:"), (IMP)nomen_window_should_close_imp, "c@:@");
1778
- objc_registerClassPair(Dc);
1779
- }
1780
- }
1902
+ Class Dc = nomen_delegate_class();
1781
1903
  if (Dc) {
1782
1904
  id delegate = ((id(*)(id, SEL))objc_msgSend)((id)Dc, sel_registerName("alloc"));
1783
1905
  delegate = ((id(*)(id, SEL))objc_msgSend)(delegate, sel_registerName("init"));
1784
1906
  ((void(*)(id, SEL, id))objc_msgSend)((id)win->handle, sel_registerName("setDelegate:"), delegate);
1907
+ // Also the NSApp delegate (Dock reopen), and the app menu with
1908
+ // its Quit ⌘Q item — installed once per process.
1909
+ nomen_install_app_menu(delegate);
1785
1910
  }
1786
1911
  ```
1787
1912
  ```
1788
1913
  #arch: aarch64_use_c
1789
1914
  #platform: macos
1790
1915
  nomen_set_resize_target(self, win);
1791
- Class Dc = objc_getClass("NomenResizeDelegate");
1792
- if (!Dc) {
1793
- Dc = objc_allocateClassPair(objc_getClass("NSObject"), "NomenResizeDelegate", 0);
1794
- if (Dc) {
1795
- class_addMethod(Dc, sel_registerName("windowDidResize:"), (IMP)nomen_window_did_resize, "v@:@");
1796
- // Close interception: refuse the native close, set the
1797
- // pending flag, let Window.run consult the app.
1798
- class_addMethod(Dc, sel_registerName("windowShouldClose:"), (IMP)nomen_window_should_close_imp, "c@:@");
1799
- objc_registerClassPair(Dc);
1800
- }
1801
- }
1916
+ Class Dc = nomen_delegate_class();
1802
1917
  if (Dc) {
1803
1918
  id delegate = ((id(*)(id, SEL))objc_msgSend)((id)Dc, sel_registerName("alloc"));
1804
1919
  delegate = ((id(*)(id, SEL))objc_msgSend)(delegate, sel_registerName("init"));
1805
1920
  ((void(*)(id, SEL, id))objc_msgSend)((id)win->handle, sel_registerName("setDelegate:"), delegate);
1921
+ // Also the NSApp delegate (Dock reopen), and the app menu with
1922
+ // its Quit ⌘Q item — installed once per process.
1923
+ nomen_install_app_menu(delegate);
1806
1924
  }
1807
1925
  ```
1808
1926
  }
@@ -1816,41 +1934,27 @@ pub mv struct Container: Control {
1816
1934
  ```
1817
1935
  #arch: c
1818
1936
  #platform: macos
1819
- Class Dc = objc_getClass("NomenResizeDelegate");
1820
- if (!Dc) {
1821
- Dc = objc_allocateClassPair(objc_getClass("NSObject"), "NomenResizeDelegate", 0);
1822
- if (Dc) {
1823
- class_addMethod(Dc, sel_registerName("windowDidResize:"), (IMP)nomen_window_did_resize, "v@:@");
1824
- // Close interception: refuse the native close, set the
1825
- // pending flag, let Window.run consult the app.
1826
- class_addMethod(Dc, sel_registerName("windowShouldClose:"), (IMP)nomen_window_should_close_imp, "c@:@");
1827
- objc_registerClassPair(Dc);
1828
- }
1829
- }
1937
+ Class Dc = nomen_delegate_class();
1830
1938
  if (Dc) {
1831
1939
  id delegate = ((id(*)(id, SEL))objc_msgSend)((id)Dc, sel_registerName("alloc"));
1832
1940
  delegate = ((id(*)(id, SEL))objc_msgSend)(delegate, sel_registerName("init"));
1833
1941
  ((void(*)(id, SEL, id))objc_msgSend)((id)win->handle, sel_registerName("setDelegate:"), delegate);
1942
+ // Also the NSApp delegate (Dock reopen), and the app menu with
1943
+ // its Quit ⌘Q item — installed once per process.
1944
+ nomen_install_app_menu(delegate);
1834
1945
  }
1835
1946
  ```
1836
1947
  ```
1837
1948
  #arch: aarch64_use_c
1838
1949
  #platform: macos
1839
- Class Dc = objc_getClass("NomenResizeDelegate");
1840
- if (!Dc) {
1841
- Dc = objc_allocateClassPair(objc_getClass("NSObject"), "NomenResizeDelegate", 0);
1842
- if (Dc) {
1843
- class_addMethod(Dc, sel_registerName("windowDidResize:"), (IMP)nomen_window_did_resize, "v@:@");
1844
- // Close interception: refuse the native close, set the
1845
- // pending flag, let Window.run consult the app.
1846
- class_addMethod(Dc, sel_registerName("windowShouldClose:"), (IMP)nomen_window_should_close_imp, "c@:@");
1847
- objc_registerClassPair(Dc);
1848
- }
1849
- }
1950
+ Class Dc = nomen_delegate_class();
1850
1951
  if (Dc) {
1851
1952
  id delegate = ((id(*)(id, SEL))objc_msgSend)((id)Dc, sel_registerName("alloc"));
1852
1953
  delegate = ((id(*)(id, SEL))objc_msgSend)(delegate, sel_registerName("init"));
1853
1954
  ((void(*)(id, SEL, id))objc_msgSend)((id)win->handle, sel_registerName("setDelegate:"), delegate);
1955
+ // Also the NSApp delegate (Dock reopen), and the app menu with
1956
+ // its Quit ⌘Q item — installed once per process.
1957
+ nomen_install_app_menu(delegate);
1854
1958
  }
1855
1959
  ```
1856
1960
  }