diff --git a/bootstrap.js b/bootstrap.js index 9912334593771d0a04965975829108afa2d5d514..b2adef479890720f21518cc2bb8aecd02132c659 100644 --- a/bootstrap.js +++ b/bootstrap.js @@ -39,7 +39,7 @@ function bootloop() { console.error('loop halting, mgr bailing') return } - setTimeout(bootloop) + setTimeout(bootloop, 50) } window.onload = () => { diff --git a/hunks/debug/timing.js b/hunks/debug/timing.js index 365523561638ff905ab0727d3578c037bdcce9ac..a5f19d0042fdae17ca1632387c3aa9ec5631b55d 100644 --- a/hunks/debug/timing.js +++ b/hunks/debug/timing.js @@ -20,7 +20,7 @@ function Timing(){ let out = new Output('boolean', 'thru', this) this.outputs.push(out) - let count = new State('number', 'average', 100) + let count = new State('number', 'average', 20) this.states.push(count) let val = false @@ -37,7 +37,7 @@ function Timing(){ t1 = performance.now() // work avsum += t1 - t0 - t0 = t1 + t0 = t1 avcnt ++ if(avcnt > count.value){ console.log("tm: ", avsum / count.value) diff --git a/hunks/hunks.js b/hunks/hunks.js index 40d6ca95f076ed629f34c65d0b4ef26ab7b55a6c..f409fd02ba7bcea29ae10f300401c99972572655 100644 --- a/hunks/hunks.js +++ b/hunks/hunks.js @@ -2,7 +2,9 @@ /* ------------------------ HUNKITUP ------------------------- */ /* --------------------------- ---------------------------- */ -import { TSET } from '../typeset.js' +import { + TSET +} from '../typeset.js' function Hunkify(hunk) { // scripting languages should name hunks by their script location and filename @@ -18,7 +20,7 @@ function Hunkify(hunk) { let str = `LG from ${hunk.name} at ${hunk.ind}: ` for (let i = 0; i < arguments.length; i++) { str += arguments[i] - if(i < arguments.length - 1) str += ', ' + if (i < arguments.length - 1) str += ', ' } console.log(str) } @@ -37,41 +39,64 @@ function Hunkify(hunk) { /* --------------------------- ---------------------------- */ function Input(type, name, parent, linktype) { + // naming, etc this.name = name this.type = type - // need this ... this.parent = parent - this.ref = null - this.data = null - this.io = false - // rules, baby (nevermind: no rules) - if (!isOKType(type)) { - //throw new Error(`unknown type specified at input, wyd? type: ${this.type}, name: ${this.name}`) + // we keep access to the outputs we're hooked up to here + this.connections = new Array() + this.io = () => { + // if any of our connections have data that we haven't read once yet, + for (var i = 0; i < this.connections.length; i++) { + // have to update calls to .io -> .io() + if (this.connections[i].io) return true + } + return false } - - // output.transport() uses this to deliver data, - this.put = (data, ref) => { - // used when MGR does transport - if (data === undefined || data === null) { - console.log("THROWING PUT OF UNDEF OR NULL") - console.log('to', this) - throw new Error('UNDEF OR NULL PUT TO LINK') - } else { - this.data = data - // minutia hack for view function (??? @ jake wyd ???) - if (ref) this.ref = ref - this.io = true + // get calls are now a bit messier, + // we have multiple wires, + this.lastGet = -1 // place we read from last (have multiple wires case) + this.copyOut = {} + this.get = () => { + // we want to (roughly) round robin these + var i = this.lastGet + // find the next occupied conn + for(var u = 0; u < this.connections.length; u ++){ + // increment, wrap + i ++ + if(i >= this.connections.length) i = 0 + // do work, + console.log('work for', i, this.connections[i]) + if (this.connections[i].io) { + // and set that wire to read / empty + this.connections[i].io = false + // and we'd like to remember from whence we last took data + this.lastGet = i + // get this data out ... we have to copy it out again, otherwise + // downstream operators may write to objects that have handles elsewhere + return this.copyOut(i) + } } + // if we pass this for w/o hitting return, + console.error("Warn! Hunk pulling on empty input!") + return null } - // hunk pulls data via .get() - this.get = () => { - if (this.io) { - this.io = false - return this.data - } else { - throw new Error('Warn! Hunk pulling on empty input!') - return null + // typing ... odd ? + if (type === "number" || type === "boolean" || type === "string") { // these are genuine base types and are not passed by reference, + this.copyOut = (indice) => { + console.log('cout reg') + return this.connections[indice].op.data + } + } else if (type === 'reference') { + this.copyOut = (indice) => { + console.log('cout ref') + return this.connections[indice].op.ref + } + } else { // this would cover "Object" and "Any" and whatever else, do your typechecking there + this.copyOut = (indice) => { + console.log('cout else') + return deepCopy(this.connections[indice].op.data) } } @@ -84,8 +109,6 @@ function Input(type, name, parent, linktype) { return index } - // we keep a list as well, - this.connections = new Array() this.disconnect = (output) => { let index = this.connections.findIndex((cand) => { return (cand.parent.ind === output.parent.ind && cand.name === output.name && cand.type === output.type) @@ -94,6 +117,7 @@ function Input(type, name, parent, linktype) { this.connections.splice(index, 1) // find the reference in our array, } + this.disconnectAll = () => { for (let op of this.connections) { op.remove(this) @@ -105,6 +129,7 @@ function Input(type, name, parent, linktype) { // assume clear upstream on startup, maybe dangerous? this.icus = true } + } /* --------------------------- ---------------------------- */ @@ -112,14 +137,30 @@ function Input(type, name, parent, linktype) { /* --------------------------- ---------------------------- */ function Output(type, name, parent, linktype) { + // naming, etc this.name = name this.type = type this.parent = parent + // store, this.ref = null this.data = null - this.posted = false - this.io = false + // hookup this.connections = new Array() + // check in realtime, manager does less + this.io = () => { + for (var i = 0; i < this.connections.length; i++) { + // connection arrays contain 'wires' ... these are stateful + if (this.connections[i].io) return true + } + return false + } + + // when we put, we use this to set states + this.setIo = () => { + for (var i = 0; i < this.connections.length; i++) { + this.connections[i].io = true + } + } /* --------------------------- ---------------------------- */ /* ------------ OUTPUT PUT AND TRANSPORT (TYPED) ------------- */ @@ -129,77 +170,49 @@ function Output(type, name, parent, linktype) { // copy-in (chances are that after .put call the referenced object changes, before it is copied out) // and copy-out (same on the other side, we are potentially passing to many downstream, need a different copy for each) this.put = {} - this.transport = {} // typing ... odd ? - if (type === "Number" || type === "Boolean" || type === "String") { // these are genuine base types and are not passed by reference, + if (type === "number" || type === "boolean" || type === "string") { // these are genuine base types and are not passed by reference, this.put = (data) => { - if (!(this.io)) { + if (!(this.io())) { this.ref = data this.data = data // so this is effectively a pass - this.io = true - this.posted = false + this.setIo() return true } else { console.error(`ERROOOOOOR: put called on occupied output: output ${this.name} in ${this.parent.name}`) return false } } - this.transport = () => { - for (let input of this.connections) { - input.put(this.data) - } - this.posted = true - } } else if (type === 'reference') { - // that's *right* this.put = (data) => { - if(!this.io) { + if (!this.io()) { this.ref = data this.data = data - this.io = true - this.posted = false + this.setIo() return true } else { console.error(`ERROOOOOOR: put called on occupied output: output ${this.name} in ${this.parent.name}`) return false } } - this.transport = () => { - for(let input of this.connections){ - input.put(this.data, this.data) - } - this.posted = true - } } else { // this would cover "Object" and "Any" and whatever else, do your typechecking there // no rules bb // names still gotta match tho // scratch that, truly no rules //if(!(type === "Object" || type === "Any")) throw new Error(`unknown type specified at hunk, wyd? type: ${this.type}, name: ${this.name}`) this.put = (data) => { - if (!this.io) { + if (!this.io()) { // HACK for view this.ref = data // make case for byteArray: themr buffers this.data = deepCopy(data) - this.io = true - this.posted = false + this.setIo() return true } else { console.error(`WARN: put called on occupied output: output ${this.name} in ${this.parent.name}`) return false } } - this.transport = () => { - for (let input of this.connections) { - input.put(deepCopy(this.data), this.ref) - } - this.posted = true - } - } - - this.clear = () => { - this.data = null - this.io = false } /* --------------------------- ---------------------------- */ @@ -209,8 +222,16 @@ function Output(type, name, parent, linktype) { this.attach = (input) => { // no rules on types ATM, historic placeholder if (this.type === input.type || input.type === 'any' || true) { - input.connections.push(this) - this.connections.push(input) + // the wire is the stateful part, + let wire = { + op: this, + opi: this.connections.length, + ip: input, + ipi: input.connections.length, + io: false + } + input.connections.push(wire) + this.connections.push(wire) return true } else { throw new Error('attempt to attach mismatched types') @@ -292,7 +313,7 @@ function State(type, name, startup) { this.change = (value, msgid) => { // coupla steps here, we track and then call internal fn, this.msgid = msgid - if(this.onChange){ + if (this.onChange) { this.onChange(value) } else { this.set(value) @@ -307,12 +328,13 @@ function deepCopy(obj) { return JSON.parse(JSON.stringify(obj)) } +// depricated: used this to check (on input / output startup) function isOKType(type) { // etc, lowecase to match with typeof ~ queeeries ~ let ind = TSET.findIndex((cand) => { return cand.name === type }) - if(type === 'any'){ + if (type === 'any') { console.log('WARN!, type of "any" is a bit risky, and cannot traverse a link') return true } else if (ind === -1) { diff --git a/hunks/manager.js b/hunks/manager.js index 84b744e14991ba0335e58437ea17a030d435042d..99af7dc631c4527d4822d0185eb0f2c2179c47b8 100644 --- a/hunks/manager.js +++ b/hunks/manager.js @@ -478,7 +478,7 @@ function Manager() { this.loop = () => { // getting messages - if (msgsin.io) { + if (msgsin.io()) { let msg = msgsin.get() if (msgverbose) console.log('MGR RX MSG:', msg) if (!Array.isArray(msg)) throw new Error(`manager throwing object message, having header ${msg.header}`) @@ -667,7 +667,7 @@ function Manager() { // MSGS output check, if (outmsgbuffer.length > 0) { let debug = true - if (!msgsout.io) { + if (!msgsout.io()) { if (debug) { let msg = outmsgbuffer.shift() if (msgverbose) this.log(`buffer release msg type: ${msg.header}`) @@ -679,8 +679,8 @@ function Manager() { } } // end msgs output check - // TRANSPORT - + // TRANSPORT (modmod: internal to outputs, inputs) + /* hunks.forEach((hunk) => { // begin transport, walk each output and push along hunk.outputs.forEach((output) => { @@ -726,6 +726,7 @@ function Manager() { } }) // end for each output }) // end forEach((hunk)) for transport + */ // allow time, start at i = 1 so that we don't call out own loop, ourorbourousing ourselves to death for (let i = 1; i < hunks.length; i++) { @@ -742,7 +743,7 @@ function Manager() { let writeMessage = (bytes) => { if (this.isConnectedTo) { - if (!msgsout.io && outmsgbuffer.length < 1) { + if (!msgsout.io() && outmsgbuffer.length < 1) { // str8 shooters if (msgverbose) this.log('msg out', bytes) msgsout.put(bytes) diff --git a/hunks/view.js b/hunks/view.js index 2e29087186a854c951ff6f7bd264fc192e277db7..73bd3b6eecba47a249181681eaed2461650e4fe7 100644 --- a/hunks/view.js +++ b/hunks/view.js @@ -890,7 +890,7 @@ function View() { let outmsgbuffer = new Array() let writeMessage = (bytes) => { - if (!msgsout.io && outmsgbuffer.length < 1) { + if (!msgsout.io() && outmsgbuffer.length < 1) { // str8 shooters if (msgverbose) this.log('msg out', bytes) msgsout.put(bytes) @@ -932,7 +932,7 @@ function View() { this.loop = () => { // THE Q: is it trees or is it inputs / outputs ? ports ... - if (msgsin.io) { + if (msgsin.io()) { let msg = msgsin.get() if (msgverbose) console.log('VIEW RX MSG:', msg) if (!Array.isArray(msg)) throw new Error(`view throwing object message, having header ${msg.header}`) @@ -1101,7 +1101,7 @@ function View() { // MSGS output check, if (outmsgbuffer.length > 0) { let debug = true - if (!msgsout.io) { + if (!msgsout.io()) { if (debug) { let msg = outmsgbuffer.shift() if (msgverbose) this.log(`buffer release msg type: ${msg.header}`) diff --git a/save/contexts/cuttlefish/simple-loop.json b/save/contexts/cuttlefish/simple-loop.json index 8e139ed930500cbc37cb99cc5bacd2e86f280edd..b74f4546cefae88cd335275f4b6ceb7f4529b129 100644 --- a/save/contexts/cuttlefish/simple-loop.json +++ b/save/contexts/cuttlefish/simple-loop.json @@ -73,7 +73,7 @@ { "name": "average", "type": "number", - "value": 100 + "value": 20 } ] }, @@ -124,4 +124,4 @@ "states": [] } ] -} \ No newline at end of file +}