ludic/packages/ludic.nativeecho/echo.ludic

66 lines
2 KiB
Text

# echo.ludic - the state, its verbs and its facts. The slices crossing to C are made once and
# reused (L7), and what C recorded is drained into the queue after each call returns.
export const ECHO_CAP: int = 64
export property EchoFact {
index: int = 0 # which element went over
value: float = 0.0
}
export state EchoState {
ec_xs: []float = floats(ECHO_CAP)
ec_n: int = 0
ec_kinds: []int = words(ECHO_CAP)
ec_values: []float = floats(ECHO_CAP)
ec_facts: Queue<EchoFact> = ec_facts__new()
}
function ec_ready() -> void {
}
# what went over, oldest first
export function echo_facts(echo_st: EchoState) -> Queue<EchoFact> {
return echo_st.ec_facts
}
# put a value in the next slot; false when the slice is full
export function echo_put(echo_st: mut EchoState, x: float) -> bool {
ec_ready()
if echo_st.ec_n >= ECHO_CAP { return false }
echo_st.ec_xs[echo_st.ec_n] = x
echo_st.ec_n += 1
return true
}
export function echo_clear(echo_st: mut EchoState) -> void { echo_st.ec_n = 0 }
# the sum of what was put, worked out in C
export function echo_sum(echo_st: mut EchoState) -> float {
ec_ready()
return ne_sum(echo_st.ec_xs, echo_st.ec_n)
}
# C walks the values and records each one over `over`; the records come back as facts
export function echo_scan(echo_st: mut EchoState, over: float) -> int {
ec_ready()
let hits = ne_scan(echo_st.ec_xs, echo_st.ec_n, over)
ec_drain(echo_st)
return hits
}
function ec_drain(echo_st: mut EchoState) -> void {
let n = ne_drain(echo_st.ec_kinds, echo_st.ec_values, ECHO_CAP)
for i in 0 .. n {
let f = new EchoFact
f.index = echo_st.ec_kinds[i]
f.value = echo_st.ec_values[i]
q_push(echo_facts(echo_st), f)
}
}
# how many records C had to drop because nobody drained them
export function echo_lost() -> int { return ne_lost_count() }
# a 64-bit value there and back
export function echo_twice(x: long) -> long { return ne_twice(x) }
function ec_facts__new() -> Queue<EchoFact> { return queue_new("nativeecho.facts") }