Published
Edited
Dec 12, 2021
Importers
Insert cell
md`# MapScript`
Insert cell
Insert cell
semanticAttribute = {
function stanza(stanzaOf) {
let s = stanzaOf.ast
if (s.statements) {
let r = Object.assign({}, s.header, {statements: s.statements})

if (r.needs) {
r.statements.unshift(
...r.needs.map(need => ({type: "need", need: need}))
)
delete r.needs
}
r.statements = r.statements.filter(stmt => stmt.type !== "empty")
return r
}

return s
}

return {
Epoch: stanzas => ({
type: "epoch",
stanzas: stanzas.asIteration().ast,
}),
Epochs: epochs => ({
type: "root",
epochs: epochs.asIteration().ast
}),
stanzaOf(header, _1, _2, statements) {
let h = header.ast
let s = statements.asIteration()
return {
header: h,
statements: s[0] ? s[0].ast : [],
}
},
attributeStmt_incomplete(name, _2) {
return {
type: "attribute",
name: name.sourceString,
valueString: "",
valueSource: _2.source,
source: this.source,
}
},
attributeStmt_complete(name, _2, _3, _4, value) {
return {
type: "attribute",
name: name.sourceString,
valueString: value.sourceString,
valueSource: value.source,
source: this.source,
}
},
annotationStmtSimple(name, _3) {
return {
type: "annotation",
name: name.sourceString,
source: this.source,
}
},
annotationStmtParameterized(name, _3, param, _5) {
return {
type: "annotation",
name: name.sourceString,
param: param.sourceString,
paramString: param.sourceString,
paramSource: param.source,
source: this.source,
}
},
componentStanzaStmt(_, stmt) {
return stmt.ast
},
annotationStanzaStmt(_, stmt) {
return stmt.ast
},
needStanzaStmt(_, stmt) {
return stmt.ast
},
emptyStmt(_1) {
return {
type: "empty",
}
},
needStanzaHeader_incomplete1(_1, _2) {
return {type: "empty"}
},
needStanzaHeader_incomplete2(_1, _2) {
return {type: "empty"}
},
needStanzaHeader_complete(_1, _2, name, _3, _4) {
return {
type: "need",
need: name.sourceString,
source: this.source,
}
},
annotationStanzaHeader(name, _) {
return {
type: "component",
name: name.ast,
source: this.source,
}
},
componentStanzaHeaderSimple(name, _1) {
return {
type: "component",
source: this.source,
name: name.ast,
}
},
componentStanzaHeaderLegacy(name, _1, _2, needs) {
return {
type: "component",
name: name.ast,
needs: needs.asIteration().ast,
source: this.source,
}
},
stanza(stanzaOf) {
return stanza(stanzaOf)
},
needStanza(stanzaOf) {
return stanza(stanzaOf)
},
ident(_1, _2) { return this.sourceString },
_terminal() { return this.sourceString },
annotationName(_1, _2) { return this.sourceString },
componentName(_1) { return this.sourceString },
}
;
}
Insert cell
ohmGrammar = source => {
try {
return ohm.grammar(source)
} catch (e) {
const lineAndCol = ohm.util.getLineAndColumn(source, e.interval.startIdx)
lineAndCol.lineNum += 1
lineAndCol.colNum -= 1
e.message = e.message + ` (${lineAndCol.lineNum}:${lineAndCol.colNum})`
throw e
}
}
Insert cell
compile = {
const semantics = grammar.createSemantics()
.addAttribute("ast", semanticAttribute)

return (source, lineOffset, initialLineColumOffset) => {
let match = grammar.match(source)
if (match.succeeded()) {

return semantics(match).ast
}

if (match.failed()) {
const lineAndCol = ohm.util.getLineAndColumn(match.input, match.getRightmostFailurePosition())
if (initialLineColumOffset && lineAndCol.lineNum === 1) {
lineAndCol.colNum += 10
}
// I don't understand why we need to add one...
if (lineOffset) {
lineAndCol.lineNum += lineOffset
}
throw new Error(`${match.shortMessage} (${lineAndCol.lineNum}:${lineAndCol.colNum})`)
}
}
}
Insert cell
Insert cell
mapscript `
cup-of-tea:
-> hot-water:
usage = 8 oz
`
Insert cell
mapscript `
x = 1

cup-of-tea:
-> hot-water:
usage = 8 oz

cup-of-tea:
@product:4

@product:
n = required
Location = ["product", n/10]
`
Insert cell
mapscript `
user:
-> cup-of-tea:
usage = 8 oz
@custom
`
Insert cell
mapscript`
user:
-> cup-of-tea
@custom

cup-of-tea:
-> pour
-> cup
x
@custom

cup:
@product:9

pour: brew barista
@custom

brew: tea hot-water
@custom

barista:
@custom:9

tea:
@product:6

hot-water: kettle water
@custom:2

kettle: power
@product:6

power:
@utility

water:
@utility

cup-of-tea: milk

milk:
@product:1

`
Insert cell
mapscript `
user: cup-of-tea
@custom

cup-of-tea: pour cup
@custom
measure = 8 oz

cup:
@product:9 # d

# x
#
#

#
pour: brew barista
@custom

brew: tea hot-water
@s
@custom

barista:
@custom:9
measure = 1 hour # dsd

@a:
x = 1
`
Insert cell
mapscript `
user: cup-of-tea
@custom

cup-of-tea: pour cup
@custom
measure = 8 oz

cup:
@product:9

pour: brew barista
@custom

brew: tea hot-water
@custom

barista:
@custom:9
measure = 1 hour

@a:
x = 1
`
Insert cell
mapscript `
user:
-> cup-of-tea:
usage = 1
@custom
`
Insert cell
mapscript `
@varcost:
varunitcost = default 0
usage = default 1 varunit
varcostrate = (sum(deps.varcost) + varunitcost) / varunit
varcost = dot(usage, varcostrate)

@fixedcost:
fixedcost = 0
fixedunit = 1
fixedcostself = 0
fixedcost = (sum(deps.fixedcost) + fixedcostself) / fixedunit

@activity:
Type = "activity"
@varcost

@custom:
maturityRating = default 5

Location = ["custom", maturityRating/10]
@activity

@utility:
maturityRating = default 5
Location = ["utility", maturityRating/10]
@activity

@product:
maturityRating = default 5
Location = ["product", maturityRating/10]
@activity

@genesis:
maturityRating = default 5
Location = ["genesis", maturityRating/10]
@activity

a:
a = 1

b:
@a

---
user: cup-of-tea
@custom

cup-of-tea: pour cup
@custom
varunit = 8 oz

cup:
@product

pour: brew barista
@custom

barista:
@custom
measure = 1 hour
`
Insert cell
ohm = require("https://unpkg.com/ohm-js@15.5.0/dist/ohm.min.js")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more