code wiki / (root) / nx_synthroom.nx

nx_synthroom.nx source

↩ module page · 153 lines · 7096 B

1// nx_synthroom.nx -- THE ROOM PROTOCOL TOOL (/compare/synthroom rung SR1): the thin main over 2// nx_synthroom_lib. All judgement lives in the lib so the gate can reach it in-process and a mutation 3// bite is not hidden behind a fork boundary. 4// 5// nx_synthroom append <log> <nonce> <verb> <actor> [a1] [a2] -> appends ONE event row, or refuses by name 6// nx_synthroom replay <log> <menu.conf> -> prints the derived intent stream 7// nx_synthroom menu <menu.conf> <amount> [item] -> prints the intent one tip maps to 8// nx_synthroom verbs -> prints the verb vocabulary 9// 10// exit 0 done | 1 refused (the reason is printed and named) | 2 usage 11// license_tier: ORIGINAL No hw writes (Rule 26). 12import "nx_syscalls.nx" 13import "nx_synthroom_lib.nx" 14 15const SRT_EXIT_OK: i64 = 0 16const SRT_EXIT_REFUSED: i64 = 1 17const SRT_EXIT_USAGE: i64 = 2 18const SRT_ARGV_VERB: i64 = 1 19const SRT_MIN_ARGC: i64 = 2 20const SRT_APPEND_MIN: i64 = 6 21const SRT_REPLAY_ARGC: i64 = 4 22const SRT_MENU_MIN: i64 = 4 23const SRT_A_LOG: i64 = 2 24const SRT_A_NONCE: i64 = 3 25const SRT_A_VERB: i64 = 4 26const SRT_A_ACTOR: i64 = 5 27const SRT_A_A1: i64 = 6 28const SRT_A_A2: i64 = 7 29const SRT_A_MENU: i64 = 3 30const SRT_M_CONF: i64 = 2 31const SRT_M_AMT: i64 = 3 32const SRT_M_ITEM: i64 = 4 33// The menu table and the replay buffer are sized from the inputs: rows <= lines + 1 of the conf, and the 34// intent stream is at most the log plus one bounded row per event -- derived, never guessed. 35const SRT_ROW_MAX: i64 = 128 36const SRT_WORD: i64 = 8 37 38func srt_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 39func srt_n(v: i64) -> i64 { 40 let b: *u8 = sys_mmap(SR_SCRATCH) 41 let p: i64 = sr_catnum(b, 0, v) 42 sys_write(1, b, p) 43 return 0 44} 45 46func srt_usage() -> i64 { 47 srt_w("usage: nx_synthroom append <log> <nonce> <verb> <actor> [a1] [a2]\n" as *u8) 48 srt_w(" nx_synthroom replay <log> <menu.conf>\n" as *u8) 49 srt_w(" nx_synthroom menu <menu.conf> <amount> [item]\n" as *u8) 50 srt_w(" nx_synthroom verbs\n" as *u8) 51 srt_w(" verbs: tip say enter leave gesture command toy. A tip carries a1=amount a2=item-or-dash.\n" as *u8) 52 srt_w(" The nonce is the caller's identity for the event: a duplicate is REFUSED, never double-applied.\n" as *u8) 53 srt_w(" exit 0 done | 1 refused by name | 2 usage\n" as *u8) 54 return 0 55} 56 57func srt_refuse(d: i64) -> i64 { 58 srt_w(" " as *u8); srt_w(sr_decision_name(d)) 59 srt_w("\n " as *u8); srt_w(sr_decision_why(d)); srt_w("\n" as *u8) 60 return 0 61} 62 63// lines + 1 of a counted buffer: the derived row capacity for a menu conf. 64func srt_lines(buf: *u8, n: i64) -> i64 { 65 var l: i64 = 1 66 var i: i64 = 0 67 while i < n { if buf[i] == (SR_CH_NL as u8) { l = l + 1 } i = i + 1 } 68 return l 69} 70 71func main(argc: i64, argv: *i64) -> i64 { 72 if argc < SRT_MIN_ARGC { srt_usage(); sys_exit(SRT_EXIT_USAGE) } 73 let verb: *u8 = argv[SRT_ARGV_VERB] as *u8 74 75 if sr_streq(verb, "verbs" as *u8) == 1 { 76 var v: i64 = 0 77 while v < SR_V_N { srt_w(" " as *u8); srt_w(sr_verb_name(v)); srt_w("\n" as *u8); v = v + 1 } 78 sys_exit(SRT_EXIT_OK) 79 } 80 81 if sr_streq(verb, "append" as *u8) == 1 { 82 if argc < SRT_APPEND_MIN { srt_usage(); sys_exit(SRT_EXIT_USAGE) } 83 var a1: *u8 = SR_EMPTY 84 var a2: *u8 = SR_EMPTY 85 if argc > SRT_A_A1 { a1 = argv[SRT_A_A1] as *u8 } 86 if argc > SRT_A_A2 { a2 = argv[SRT_A_A2] as *u8 } 87 let line: *u8 = sys_mmap(SR_LINE) 88 let scratch: *u8 = sys_mmap(SR_SCRATCH) 89 let lp: *i64 = sys_mmap(SRT_WORD * 2) as *i64 90 let now: i64 = sys_now_realtime_sec() 91 let d: i64 = sr_event_append(argv[SRT_A_LOG] as *u8, argv[SRT_A_NONCE] as *u8, now, argv[SRT_A_VERB] as *u8, 92 argv[SRT_A_ACTOR] as *u8, a1, a2, line, SR_LINE, scratch, lp) 93 srt_w("=== NX-SYNTHROOM append log=" as *u8); srt_w(argv[SRT_A_LOG] as *u8) 94 srt_w(" nonce=" as *u8); srt_w(argv[SRT_A_NONCE] as *u8) 95 srt_w(" ts=" as *u8); srt_n(now); srt_w(" ===\n" as *u8) 96 srt_refuse(d) 97 if d == SR_OK { srt_w(" row=" as *u8); srt_w(line) } 98 if d != SR_OK { sys_exit(SRT_EXIT_REFUSED) } 99 sys_exit(SRT_EXIT_OK) 100 } 101 102 if sr_streq(verb, "menu" as *u8) == 1 { 103 if argc < SRT_MENU_MIN { srt_usage(); sys_exit(SRT_EXIT_USAGE) } 104 let amount: i64 = sr_atoi_strict(argv[SRT_M_AMT] as *u8) 105 if amount < 0 { srt_w("REFUSED-BAD-AMOUNT: the amount must be a non-negative integer\n" as *u8); sys_exit(SRT_EXIT_USAGE) } 106 var item: *u8 = SR_EMPTY 107 if argc > SRT_M_ITEM { item = argv[SRT_M_ITEM] as *u8 } 108 let lp: *i64 = sys_mmap(SRT_WORD * 2) as *i64 109 let why: *i64 = sys_mmap(SRT_WORD) as *i64 110 let fb: *i64 = sys_mmap(SRT_WORD) as *i64 111 let tab: *i64 = sys_mmap(SRT_ROW_MAX * SR_M_STRIDE * SR_I64_BYTES) as *i64 112 let rows: i64 = sr_menu_load(argv[SRT_M_CONF] as *u8, tab, SRT_ROW_MAX, fb, why, lp) 113 if rows < 0 { srt_refuse(why[0]); sys_exit(SRT_EXIT_REFUSED) } 114 let intent: *u8 = sr_menu_intent(tab, rows, fb[0] as *u8, amount, item) 115 srt_w(" rows=" as *u8); srt_n(rows) 116 srt_w(" amount=" as *u8); srt_n(amount) 117 srt_w(" item=" as *u8); srt_w(item) 118 srt_w(" intent=" as *u8); srt_w(intent); srt_w("\n" as *u8) 119 sys_exit(SRT_EXIT_OK) 120 } 121 122 if sr_streq(verb, "replay" as *u8) == 1 { 123 if argc < SRT_REPLAY_ARGC { srt_usage(); sys_exit(SRT_EXIT_USAGE) } 124 let lp: *i64 = sys_mmap(SRT_WORD * 2) as *i64 125 let why: *i64 = sys_mmap(SRT_WORD) as *i64 126 let fb: *i64 = sys_mmap(SRT_WORD) as *i64 127 let tab: *i64 = sys_mmap(SRT_ROW_MAX * SR_M_STRIDE * SR_I64_BYTES) as *i64 128 let rows: i64 = sr_menu_load(argv[SRT_A_MENU] as *u8, tab, SRT_ROW_MAX, fb, why, lp) 129 if rows < 0 { srt_refuse(why[0]); sys_exit(SRT_EXIT_REFUSED) } 130 let lg: *u8 = sys_read_file(argv[SRT_A_LOG] as *u8, lp) 131 if (lg as i64) == 0 { srt_refuse(SR_D_NOLOG); sys_exit(SRT_EXIT_REFUSED) } 132 let n: i64 = lp[0] 133 // one bounded intent row per event: the log length plus one SR_LINE per newline is a safe cap 134 let ocap: i64 = n + (srt_lines(lg, n) * SR_LINE) + 1 135 let out: *u8 = sys_mmap(ocap) 136 let cnt: *i64 = sys_mmap(SRT_WORD) as *i64 137 let bad: *i64 = sys_mmap(SRT_WORD) as *i64 138 let d: i64 = sr_replay(lg, n, tab, rows, fb[0] as *u8, out, ocap, cnt, bad) 139 if d != SR_OK { 140 srt_refuse(d) 141 if bad[0] >= 0 { srt_w(" row-index=" as *u8); srt_n(bad[0]); srt_w("\n" as *u8) } 142 sys_exit(SRT_EXIT_REFUSED) 143 } 144 srt_w(out) 145 srt_w(" intents=" as *u8); srt_n(cnt[0]); srt_w(" menu_rows=" as *u8); srt_n(rows); srt_w("\n" as *u8) 146 sys_exit(SRT_EXIT_OK) 147 } 148 149 srt_w("REFUSED-BAD-VERB: the verbs are append replay menu verbs\n" as *u8) 150 srt_usage() 151 sys_exit(SRT_EXIT_USAGE) 152 return 0 153}