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()