firescript
Version:
Firescript transpiler
155 lines (123 loc) • 2.94 kB
JavaScript
class SourceBuffer {
constructor () {
this.buffer = []
this.locationMap = []
this.line = 1
this.column = 1
this.indention = 0
this.indentionSize = 2
}
write (str, defaultValue) {
if (!str) {
if (defaultValue) {
this.write(defaultValue)
}
return this
}
if (typeof str === 'object') {
str.compile(this)
return this
}
const lastIndex = str.lastIndexOf('\n')
if (lastIndex === -1) {
this.column += str.length
} else {
this.column = str.length - lastIndex
this.line += (str.split('\n').length - 1)
}
this.buffer.push(str)
return this
}
writeItem (item) {
if (item.leadingComments && item.leadingComments.length) {
this.writeComments(item.leadingComments)
this.indent()
}
item.compile(this)
if (item.trailingComments && item.trailingComments.length) {
this.indent()
this.writeComments(item.trailingComments)
}
}
writeComments (comments, joiner) {
if (comments && comments.length > 0) {
comments.forEach((comment, index) => {
if (index) {
joiner === undefined ? this.indent() : this.write(joiner)
}
this.write(comment)
})
}
}
nl (num = 1) {
this.line += num
this.column = 1
this.buffer.push('\n'.repeat(num))
return this
}
getLocation () {
return [ this.line, this.column ]
}
getIndent () {
// console.log('INDENT', this.indention, this.indentionSize, `"${' '.repeat(this.indention * this.indentionSize)}"`)
return '\n' + ' '.repeat(this.indention * this.indentionSize)
}
indent (size, noWrite) {
size = size || 0
this.indention += size
if (!noWrite) {
this.write(this.getIndent())
}
}
item (node) {
node.compile(this)
return this
}
loop (arr, joiner = this.getIndent(), fn) {
if (arr) {
arr.forEach((item, index) => {
if (index > 0) {
this.write(joiner)
}
this.writeItem(item)
})
}
return this
}
registerItem (origLocation, name) {
if (origLocation) {
const map = [
origLocation.line,
origLocation.column,
this.line,
this.column
]
if (typeof name === 'string') {
map.push(name)
}
this.locationMap.push(map)
}
return this
}
toString () {
return this.buffer.join('')
}
print () {
console.log(this.buffer.slice(-5))
}
createLocationMap () {
if (this.locationMap.length === 0) {
return
}
this.write('module.exports.__fsLocationMap = [')
this.write(this.locationMap.map((item) => {
const args = item.slice(0, 4)
if (item[4]) {
args.push(`'${item[4].replace(/'/g, '\\\'')}'`)
}
return `[${args.join(', ')}]`
}).join(', '))
this.write('];')
}
}
module.exports = SourceBuffer