Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion crates/runtime/include/scuzz_rt.h
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,10 @@ SzString *sz_fs_basename(SzString *path);

/* Pure Json. Enum Null|Bool|Int|Float|Str|Arr|Obj.
* parse / stringify return Result (Err=0 / Ok=1). Query kits return empty
* lists on a miss or a wrong tag. `*_or` / `get_*` use the default.
* lists on a miss or a wrong tag. is* and as* stay tag-strict.
* intOr / floatOr / getInt / getFloat coerce JSON numbers. Int to Float
* is a C double cast. Float to Int is an exact i64, else the default.
* Other *_or / get_* use the default.
* Write kits copy Obj / Arr cells. A miss keeps the default or retains `j`. */
SzAdt *sz_json_parse(SzString *s);
SzAdt *sz_json_stringify(SzAdt *j);
Expand All @@ -875,6 +878,7 @@ SzList *sz_json_pairs(SzAdt *j); /* List[(String, Json)]; empty if
int64_t sz_json_is_null(SzAdt *j);
int64_t sz_json_is_bool(SzAdt *j);
int64_t sz_json_is_int(SzAdt *j);
int64_t sz_json_is_float(SzAdt *j);
int64_t sz_json_is_str(SzAdt *j);
int64_t sz_json_is_arr(SzAdt *j);
int64_t sz_json_is_obj(SzAdt *j);
Expand Down
2 changes: 2 additions & 0 deletions crates/runtime/include/scuzz_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ SzString *sz_signal_dump(void);
/* Publish the for-binder name. Property and Timeline kits read that name. */
void sz_signal_name(const void *sig, const char *name);

/* Named observation. A missing name panics. */
int64_t sz_property_signal_int(SzString *name);
SzString *sz_property_signal_str(SzString *name);
int64_t sz_property_signal_list_len(SzString *name);
Expand Down Expand Up @@ -729,6 +730,7 @@ SzString *sz_lang_signal_str_get(SzSignalStr *s);
void *sz_lang_signal_str_set(SzSignalStr *s, SzString *v);
SzSignalList *sz_lang_signal_list(SzList *initial, SzString *name,
int64_t elem_str);
/* Retain the current list. Last-use drops it. */
SzList *sz_lang_signal_list_get(SzSignalList *s);
void *sz_lang_signal_list_set(SzSignalList *s, SzList *v);

Expand Down
43 changes: 26 additions & 17 deletions crates/runtime/src/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,7 @@ SzList *sz_json_pairs(SzAdt *j) {
int64_t sz_json_is_null(SzAdt *j) { return json_tag(j) == JSON_NULL ? 1 : 0; }
int64_t sz_json_is_bool(SzAdt *j) { return json_tag(j) == JSON_BOOL ? 1 : 0; }
int64_t sz_json_is_int(SzAdt *j) { return json_tag(j) == JSON_INT ? 1 : 0; }
int64_t sz_json_is_float(SzAdt *j) { return json_tag(j) == JSON_FLOAT ? 1 : 0; }
int64_t sz_json_is_str(SzAdt *j) { return json_tag(j) == JSON_STR ? 1 : 0; }
int64_t sz_json_is_arr(SzAdt *j) { return json_tag(j) == JSON_ARR ? 1 : 0; }
int64_t sz_json_is_obj(SzAdt *j) { return json_tag(j) == JSON_OBJ ? 1 : 0; }
Expand Down Expand Up @@ -831,16 +832,27 @@ int64_t sz_json_bool_or(SzAdt *j, int64_t d) {
return n;
}

static int json_float_exact_i64(double x, int64_t *out) {
int64_t n;
if (!isfinite(x))
return 0;
if (x < (double)INT64_MIN || x >= 0x1p63)
return 0;
n = (int64_t)x;
if ((double)n != x)
return 0;
*out = n;
return 1;
}

int64_t sz_json_int_or(SzAdt *j, int64_t d) {
SzList *xs = sz_json_as_int(j);
int tag = json_tag(j);
int64_t n;
if (!xs) {
sz_release(xs);
return d;
}
n = sz_unbox_i64(sz_list_head(xs));
sz_release(xs);
return n;
if (tag == JSON_INT)
return sz_unbox_i64(sz_adt_payload(j));
if (tag == JSON_FLOAT && json_float_exact_i64(unbox_f64(sz_adt_payload(j)), &n))
return n;
return d;
}

SzString *sz_json_str_or(SzAdt *j, SzString *d) {
Expand Down Expand Up @@ -938,15 +950,12 @@ SzAdt *sz_json_merge(SzAdt *a, SzAdt *b) {
}

double sz_json_float_or(SzAdt *j, double d) {
SzList *xs = sz_json_as_float(j);
double x;
if (!xs) {
sz_release(xs);
return d;
}
x = unbox_f64(sz_list_head(xs));
sz_release(xs);
return x;
int tag = json_tag(j);
if (tag == JSON_FLOAT)
return unbox_f64(sz_adt_payload(j));
if (tag == JSON_INT)
return (double)sz_unbox_i64(sz_adt_payload(j));
return d;
}

double sz_json_get_float(SzAdt *j, SzString *key, double d) {
Expand Down
2 changes: 1 addition & 1 deletion crates/runtime/src/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -2528,7 +2528,7 @@ static SzIo *ensure_run_fin_err(SzIo *fin, SzError *err) {
}

static SzIo *ignore_then_io(void *ignored, void *env) {
(void)ignored;
sz_release(ignored);
return (SzIo *)env;
}

Expand Down
70 changes: 47 additions & 23 deletions crates/runtime/src/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,23 @@ static SigReg *sig_find(SigKind kind, const char *name) {
return NULL;
}

static void sig_missing(const char *name) {
char buf[192];
snprintf(buf, sizeof buf, "missing signal %s",
name && name[0] ? name : "(empty)");
sz_panic(buf);
}

/* First non-null head decides String vs count-only. Empty keeps `unknown`. */
static int sig_list_heads_str(const SzList *p, int unknown) {
for (; p; p = p->tail) {
if (!p->head)
continue;
return sz_rc_kind(p->head) == SZ_RC_STRING;
}
return unknown ? 1 : 0;
}

/* Mark a list signal's element kind: 1 = String (dump prints elements),
* 0 = other (dump prints the count only). */
static void sig_set_elem_str(const void *sig, int64_t elem_str) {
Expand Down Expand Up @@ -144,7 +161,7 @@ SzString *sz_signal_dump(void) {
break;
case SIG_LIST: {
SzList *p = sz_signal_list_get((const SzSignalList *)r->sig);
if (!r->elem_str) {
if (!sig_list_heads_str(p, r->elem_str)) {
snprintf(line, sizeof line, "list[%d] %s= <%lld>\n", r->id, tag,
(long long)sz_list_len(p));
sz_dump_append(&buf, &len, &cap, line);
Expand Down Expand Up @@ -175,7 +192,9 @@ int64_t sz_property_signal_int(SzString *name) {
if (sz_timeline_replaying())
return sz_timeline_replay_signal_int(n);
r = sig_find(SIG_INT, n);
return r ? sz_signal_int_get((const SzSignalInt *)r->sig) : 0;
if (!r)
sig_missing(n);
return sz_signal_int_get((const SzSignalInt *)r->sig);
}

SzString *sz_property_signal_str(SzString *name) {
Expand All @@ -184,10 +203,9 @@ SzString *sz_property_signal_str(SzString *name) {
if (sz_timeline_replaying())
return sz_timeline_replay_signal_str(n);
r = sig_find(SIG_STR, n);
if (r)
return sz_string_from_cstr(
sz_signal_str_get((const SzSignalStr *)r->sig));
return sz_string_from_cstr("");
if (!r)
sig_missing(n);
return sz_string_from_cstr(sz_signal_str_get((const SzSignalStr *)r->sig));
}

int64_t sz_property_signal_list_len(SzString *name) {
Expand All @@ -196,10 +214,9 @@ int64_t sz_property_signal_list_len(SzString *name) {
if (sz_timeline_replaying())
return sz_timeline_replay_signal_list_len(n);
r = sig_find(SIG_LIST, n);
if (r)
return (int64_t)sz_list_len(
sz_signal_list_get((const SzSignalList *)r->sig));
return 0;
if (!r)
sig_missing(n);
return (int64_t)sz_list_len(sz_signal_list_get((const SzSignalList *)r->sig));
}

SzString *sz_property_signal_list_at(SzString *name, int64_t index) {
Expand All @@ -212,17 +229,19 @@ SzString *sz_property_signal_list_at(SzString *name, int64_t index) {
if (sz_timeline_replaying())
return sz_timeline_replay_signal_list_at(n, index);
r = sig_find(SIG_LIST, n);
if (r && r->elem_str) {
p = sz_signal_list_get((const SzSignalList *)r->sig);
i = 0;
while (p) {
if (i == index) {
SzString *h = (SzString *)p->head;
return sz_string_from_cstr(h ? sz_string_cstr(h) : "");
}
p = p->tail;
i++;
if (!r)
sig_missing(n);
p = sz_signal_list_get((const SzSignalList *)r->sig);
if (!sig_list_heads_str(p, r->elem_str))
return sz_string_from_cstr("");
i = 0;
while (p) {
if (i == index) {
SzString *h = (SzString *)p->head;
return sz_string_from_cstr(h ? sz_string_cstr(h) : "");
}
p = p->tail;
i++;
}
return sz_string_from_cstr("");
}
Expand Down Expand Up @@ -323,9 +342,9 @@ int sz_signal_list_elem_str(const SzSignalList *s) {
SigReg *r;
for (r = g_sig_head; r; r = r->next) {
if (r->sig == (const void *)s)
return r->elem_str;
return sig_list_heads_str(s ? s->value : NULL, r->elem_str);
}
return 1;
return 0;
}

SzSignalList *sz_lang_signal_list(SzList *initial, SzString *name,
Expand All @@ -337,7 +356,12 @@ SzSignalList *sz_lang_signal_list(SzList *initial, SzString *name,
return s;
}

SzList *sz_lang_signal_list_get(SzSignalList *s) { return sz_signal_list_get(s); }
/* Retain so last-use can drop. The C getter stays a borrow. */
SzList *sz_lang_signal_list_get(SzSignalList *s) {
SzList *xs = sz_signal_list_get(s);
sz_retain(xs);
return xs;
}

void *sz_lang_signal_list_set(SzSignalList *s, SzList *v) {
sz_signal_list_set(s, v);
Expand Down
Loading
Loading