Newer
Older

Jake Read
committed
/* --------------------------- ---------------------------- */
/* ------------------------ HUNKITUP ------------------------- */
/* --------------------------- ---------------------------- */
function Hunkify(hunk) {
// scripting languages should name hunks by their script location and filename
// compiled languages will assign a string
// because this is always added by .addHunk(path) (path == name)
// we set this during load, only once, this avoids some confusion
hunk.type = null
// we keep a copy of our position-in-the-array ... of our parent ... our pip
hunk.ind = null
let str = `LG from ${hunk.name} at ${hunk.ind}: `
if (i < arguments.length - 1) str += ', '
console.log(str)

Jake Read
committed
// input, output, and state: ay balls, here we go
hunk.inputs = new Array()
hunk.outputs = new Array()

Jake Read
committed
hunk.input = (type, name) => {
let ip = new Input(type, name, hunk)
hunk.inputs.push(ip)
return ip
}
hunk.output = (type, name) => {
let op = new Output(type, name, hunk)
hunk.outputs.push(op)
return op
}
hunk.state = (type, name, dfault) => {
let st = new State(type, name, dfault)
hunk.states.push(st)
return st
}
// top-secret backdoor

Jake Read
committed
/* --------------------------- ---------------------------- */
/* ------------------------- OUTPUT -------------------------- */
/* --------------------------- ---------------------------- */
function Output(type, name, parent, linktype) {
this.phy = findPhy(this.type) // checks, throws error if type doesn't exist
this.parent = parent

Jake Read
committed
this.ref = null
// 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
}
}

Jake Read
committed
/* --------------------------- ---------------------------- */
/* ------------ OUTPUT PUT AND TRANSPORT (TYPED) ------------- */
/* --------------------------- ---------------------------- */
// yonder put call, transport call
// 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)
// typing ... odd ?
this.put = (data) => {

Jake Read
committed
if (!this.io()) {
this.ref = data
this.data = this.phy.copy[this.type](data)
this.setIo()
return true
} else {
console.error(`WARNING: put called on occupied output: output ${this.name} in ${this.parent.name}`)
return false

Jake Read
committed
}

Jake Read
committed
/* --------------------------- ---------------------------- */
/* ---------------- OUTPUT MANAGE CONNECTIONS ---------------- */
/* --------------------------- ---------------------------- */
// we can only do this if a fn exists for us to copy from-us-to-them
if (this.phy.copy[input.type]) {
// the wire is the stateful part,
let wire = {
op: this,
ip: input,
io: false
}
input.connections.push(wire)
this.connections.push(wire)

Jake Read
committed
} else {
console.error(`ERROR: missing type conversion from: ${this.type} to ${input.type}`)

Jake Read
committed
}
let ind = this.connections.findIndex((cand) => {
input.disconnect(this)
console.log('ERROR: wire removal, was looking for', input, 'in', this.connections)
this.findOwnIndex = () => {
// find self in parent's inputs
let index = this.parent.outputs.findIndex((cand) => {
return (cand.name === this.name && cand.type === this.type)
})
console.log(`output could not find itself in parent: ${index}`, this, 'unstrung', this.parent.outputs, 'strung', JSON.parse(JSON.stringify(this.parent.outputs)))
throw new Error(`output could not find itself in parent: ${index}`)
}
return index
}
// here we're disconnecting the input, meaning the input is removing this from its list of connections
}
// this is actually a genuine way to delete an array in js, http://shrugguy.com
this.connections.length = 0
}
/* --------------------------- ---------------------------- */
/* ----------- OUTPUT TRICKS FOR LINK CONNECTIONS ------------ */
/* --------------------------- ---------------------------- */
// has stash ?
this.needsAck = false;
}
} // FIN output
/* --------------------------- ---------------------------- */
/* -------------------------- INPUT -------------------------- */
/* --------------------------- ---------------------------- */
function Input(type, name, parent, linktype) {
// naming, etc
this.name = name
this.type = type
this.parent = parent
// 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
}
// get calls are now a bit messier,
// we have multiple wires,
this.lastGet = 0 // place we read from last (have multiple wires case)
this.get = () => {
// we want to (roughly) round robin these, so we pick up from where we last pulled,
var i = this.lastGet
// find the next occupied conn: do iterations max. of total length of connections,

Jake Read
committed
for (var u = 0; u < this.connections.length; u++) {
// increment, wrap

Jake Read
committed
i++
if (i >= this.connections.length) i = 0
// do work,
if (this.connections[i].io) {
let wire = this.connections[i]
// and set that wire to read / empty
wire.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
// here we call the function from typeset.js that is custom between the-output -> and the-input
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
return wire.op.phy.copy[this.type](wire.op.data)
}
}
// if we pass this for w/o hitting return,
console.error(`WARNING: get called on occupied input: ${this.name} in ${this.parent.name}`)
return null
}
this.findOwnIndex = () => {
// find self in parent's inputs
let index = this.parent.inputs.findIndex((cand) => {
return (cand.name === this.name && cand.type === this.type)
})
if (index === -1) throw new Error('input could not find itself in parent')
return index
}
this.disconnect = (output) => {
let index = this.connections.findIndex((cand) => {
return (cand.op = output)
})
if (index === -1) throw new Error('during output disconnect, input cannot find output...')
this.connections.splice(index, 1)
// find the reference in our array,
}
this.disconnectAll = () => {
for (let cn of this.connections) {
cn.op.remove(this)
}
}
// inputs / outputs for 'link' (a hunk) ports have more state,
if (linktype) {
// assume clear upstream on startup, maybe dangerous?
this.icus = true
}
// working the onChange / change function (onChange feels more better?)
// if we do .on('change', (val) => {
//})
// we can potentially add ... .on('startup') or something, to set hard defaults ?
// and then: write out copy fn's per item ...
this.phy = findPhy(this.type) // types must have *some* code -> by finding one here, we check that it exists
// TODO pls add check for missing startup value ?
this.value = startup
// this is still something of a hack
// during load, the manager gets in here and dishes a function 2 us
this.hookup = (newval) => {
console.error('ERROR: when state-change request made, no hookup function yet - probable manager error while loading hunk')
}
// from within a hunk, we typically call this
// to update the value and ship it out to any views
this.set = (value) => {
// for good measure, we copy-in state as well. who knows.
this.value = this.phy.copy[this.type](value)
this.hookup(this.value, this.msgid)
this.msgid = null
// the manager calls this fn, when a request is made.
//
this.tryChange = (value, msgid) => {
// coupla steps here, we track and then call internal fn,
this.msgid = msgid
// not sure, but we could clean these here by doing this.phy.copy[this.type](value)
this.onChange(value)
} else {
this.set(value)
}