106 lines
3.0 KiB
TypeScript
106 lines
3.0 KiB
TypeScript
import { TextDocuments } from 'vscode-languageserver/node'
|
|
import { TextDocument } from 'vscode-languageserver-textdocument'
|
|
import { createConnection, ProposedFeatures } from 'vscode-languageserver/node'
|
|
import { buildDiagnostics } from './diagnostics'
|
|
import { buildSemanticTokens, TOKEN_MODIFIERS, TOKEN_TYPES } from './semanticTokens'
|
|
import { parser } from '../../../src/parser/shrimp'
|
|
import { Compiler } from '../../../src/compiler/compiler'
|
|
|
|
const connection = createConnection(ProposedFeatures.all)
|
|
const documents = new TextDocuments(TextDocument)
|
|
documents.listen(connection)
|
|
|
|
connection.onInitialize(() => {
|
|
connection.console.log('🦐 Server initialized with capabilities')
|
|
return {
|
|
capabilities: {
|
|
textDocumentSync: 1,
|
|
semanticTokensProvider: {
|
|
legend: {
|
|
tokenTypes: TOKEN_TYPES,
|
|
tokenModifiers: TOKEN_MODIFIERS,
|
|
},
|
|
full: true,
|
|
},
|
|
},
|
|
}
|
|
})
|
|
|
|
connection.languages.semanticTokens.on((params) => {
|
|
const document = documents.get(params.textDocument.uri)
|
|
if (!document) {
|
|
return { data: [] }
|
|
}
|
|
|
|
const data = buildSemanticTokens(document)
|
|
return { data }
|
|
})
|
|
|
|
documents.onDidChangeContent((change) => {
|
|
const textDocument = change.document
|
|
|
|
const diagnostics = buildDiagnostics(textDocument)
|
|
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics })
|
|
})
|
|
|
|
connection.onRequest('shrimp/parseTree', (params: { uri: string }) => {
|
|
connection.console.log(`🦐 Parse tree requested for: ${params.uri}`)
|
|
const document = documents.get(params.uri)
|
|
if (!document) return 'Document not found'
|
|
|
|
const text = document.getText()
|
|
const tree = parser.parse(text)
|
|
const treeString = tree.toString()
|
|
|
|
// Format with indentation, without parentheses
|
|
let formatted = ''
|
|
let indent = 0
|
|
for (let i = 0; i < treeString.length; i++) {
|
|
const char = treeString[i]
|
|
if (char === '(') {
|
|
formatted += '\n'
|
|
indent++
|
|
formatted += ' '.repeat(indent)
|
|
} else if (char === ')') {
|
|
indent--
|
|
} else if (char === ',') {
|
|
formatted += '\n'
|
|
formatted += ' '.repeat(indent)
|
|
} else {
|
|
formatted += char
|
|
}
|
|
}
|
|
|
|
return formatted
|
|
})
|
|
|
|
connection.onRequest('shrimp/bytecode', (params: { uri: string }) => {
|
|
connection.console.log(`🦐 Bytecode requested for: ${params.uri}`)
|
|
const document = documents.get(params.uri)
|
|
if (!document) return 'Document not found'
|
|
|
|
try {
|
|
const text = document.getText()
|
|
const compiler = new Compiler(text)
|
|
|
|
// Format bytecode as readable string
|
|
let output = 'Bytecode:\n\n'
|
|
const bytecode = compiler.bytecode
|
|
|
|
output += bytecode.instructions
|
|
.map((op, i) => `${i.toString().padStart(4)}: ${JSON.stringify(op)}`)
|
|
.join('\n')
|
|
|
|
// Strip ANSI color codes
|
|
output = output.replace(/\x1b\[[0-9;]*m/g, '')
|
|
|
|
return output
|
|
} catch (error) {
|
|
const errorMsg = error instanceof Error ? error.message : String(error)
|
|
// Strip ANSI color codes from error message too
|
|
return `Compilation failed: ${errorMsg.replace(/\x1b\[[0-9;]*m/g, '')}`
|
|
}
|
|
})
|
|
|
|
connection.listen()
|