Newer
Older
const Reps = require('./reps.js')
const JSUnit = require('./lib/jsunit.js')
let isStateKey = JSUnit.isStateKey
id: name
},
modules: {}
}
return program
}
function loadModuleFromSource(program, path, id) {
// source -> heap
if (fs.existsSync(path)) {
var src = require(path)
var mod = new src()
// wants unique module id's
if (program.description.counter == null) {
program.description.counter++
// make unique name, or recall from program save
if (id) {
mod.description.id = id
} else {
mod.description.id = mod.description.name + '-' + program.description.counter
}
// add to program object
program.modules[mod.description.id] = mod
/* ---------------------------------- */
// WARN! Corner Case should Go Away or Improve at next spiral
if (mod.description.isLink) {
for (mdlName in program.modules) {
if (program.modules[mdlName].description.isLink) {
console.log("PRGMEM ONLY BIG ENOUGH FOR ONE LINK")
}
}
}
// end corner case code
/* ---------------------------------- */
// input need references for later hookup
for (key in mod.inputs) {
mod.inputs[key].parentId = mod.description.id
mod.inputs[key].key = key
}
// state updating, begs for update
for (key in mod.state) {
if (key == 'onChange' | key == 'emitChange' | key == 'emitters') {
//console.log('rolling past change fn')
} else {
mod.state['_' + key] = mod.state[key]
mod.state[key] = {}
writeStateObject(mod, key)
}
}
if (program.description.id == null) {
if (program.description.name == null) {
if (program.description == null) {
program.description = {}
}
program.description.name = 'unnamed program'
}
program.description.id = program.description.name + '-' + 0
}
console.log('ADDING', mod.description.id, 'to', program.description.id)
/* ---------------------------------- */
// WARN! Corner Case should Go Away or Improve at next spiral
// hardware corner case is hardware corner case
// here's what we'll do
// if it's hardware, and we're not loading from some saved program (no id)
//
if (mod.description.isHardware && !mod.description.isLink /* && id == null */ ) {
for (mdlName in program.modules) {
if (program.modules[mdlName].description.isLink) {
lnk = mdlName
}
}
if (lnk) {
console.log('CORNER CASE: LOADING HW MODULE, LINKING TO LINK')
program.modules[lnk].attach(mod.route)
} else {
console.log('CORNER CASE: LOADING HW MODULE, ALSO LOADING LINK')
var link = loadModuleFromSource(program, './modules/hardware/atkseriallink.js')
// hook it up auto-like
link.attach(mod.route)
}
}
// also return it so that we can write programs without the UI
return mod
} else {
console.log('ERR no module found at ', path)
}
}
function writeStateObject(mod, key) {
Object.defineProperty(mod.state, key, {
set: function(x) {
// update internal value
this['_' + key] = x
// console.log('SET', key, this['_' + key])
// let's call emitChange from the server-side ...
// so that we don't get into any heavy VIR
// when we change it within the module
// this.emitChange(key)
// push to external view
if (socket) {
}
})
Object.defineProperty(mod.state, key, {
get: function() {
//console.log('GET', key, this['_' + key])
return this['_' + key]
}
})
}
function removeModuleFromProgram(program, id) {
for (key in program.modules) {
for (otKey in mdl.outputs) {
function assignSocket(sckt) {
socket = sckt
function pushState(mod, key) {
var data = {
id: mod.description.id,
key: key,
val: mod.state[key]
}
socket.send('put state change', data)
function saveProgram(prgmem, path) {
// ok, and we're interested in just copying the relevant things ...
var svprgmem = {
description: {
name: prgmem.description.name,
counter: prgmem.description.counter
},
modules: {}
}
var mdls = prgmem.modules
for (key in mdls) {
var og = Reps.makeFromModule(mdl)
svprgmem.modules[mdl.description.id] = og
}
fs.writeFileSync(path, JSON.stringify(svprgmem, null, 2), 'utf8')
console.log('PROGRAM SAVED AT', path)
function openProgram(path) {
var program = {}
// get the .json file as an object
var prgRep = JSON.parse(fs.readFileSync(path, 'utf8'))
console.log('OPENING THIS PRGRAM REP', prgRep)
// copy-pasta the program descro,
program.description = {
name: prgRep.description.name,
counter: 0,
id: prgRep.description.name + 1, // in another world, we count
path: path
}
// gonna get those modules from source
program.modules = {}
for (key in prgRep.modules) {
loadModuleFromSource(program, mdlRep.description.path, mdlRep.description.id)
for (modName in prgRep.modules) {
// this is the representation that we're opening up from
// this is the actual object, having functions and whatnot
if (mdl == null) {
console.log('-------------------------------- NULL MDL at openProgram')
console.log('prgRep modules', prgRep.modules)
console.log('program modules', program.modules)
}
for (outName in mdlRep.outputs) {
var outRep = mdlRep.outputs[outName]
// each has some caller ids
for (nestedInputRep in outRep.calls) {
// conn from tl program -> this hookup
var nIRParent = outRep.calls[nestedInputRep].parentId
var nIRKey = outRep.calls[nestedInputRep].key
var nI = program.modules[nIRParent].inputs[nIRKey]
console.log("ATTACHING", nIRKey, 'to', outName)
mdl.outputs[outName].attach(nI)
}
}
/* the first wrap, only here to prevent link not-reconnecting on program restart, should go away */
if (!mdlRep.description.isLink) {
for (key in mdlRep.state) {
if (isStateKey(key)) {
// I think this is OK?
// would prefer to do this before we write getters and setters
// for now we walk-around to secret key ...
if (mdl.state[key].type == 'button' || mdl.state[key].type == 'multiline') {
// defaul vals
} else if (key == 'route'){
// absolutely does not belong here
// TODO: states: sometimes we load, we want to run the change emitter ... sometimes we don't
// what choice ?
mdl.state['_' + key] = mdlRep.state[key]
mdl.state.emitChange('route')
} else {
mdl.state['_' + key] = mdlRep.state[key]
}
}
// and let's run init if it's there
if(mdl.init != null){
mdl.init()
}
//console.log('mdlRep', mdlRep)
//console.log('mdl', mdl)
// restore position / UI state
if (mdlRep.description.position != null) {
mdl.description.position = {}
mdl.description.position.left = mdlRep.description.position.left
mdl.description.position.top = mdlRep.description.position.top
}
// once modules exist, link inputs / outputs / copy state ?
return program
}
module.exports = {