Skip to content

Commit d4579e3

Browse files
authored
Merge pull request #20 from supermemoryai/12-20-add_cloudflare_workers_wasm_compatibility
wasm instead of cloudflare
2 parents 6ad9efa + cda366b commit d4579e3

File tree

8 files changed

+711
-115
lines changed

8 files changed

+711
-115
lines changed

packages/code-chunk/package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"url": "git+https://github.com/supermemoryai/code-chunk.git"
1616
},
1717
"scripts": {
18-
"build": "bunup",
18+
"build": "bunup src/index.ts src/wasm.ts",
1919
"dev": "bunup --watch",
2020
"release": "bumpp --commit --push --tag",
2121
"test": "bun test",
@@ -46,6 +46,14 @@
4646
"default": "./dist/index.js"
4747
}
4848
},
49+
"./wasm": {
50+
"types": "./src/wasm.ts",
51+
"bun": "./src/wasm.ts",
52+
"import": {
53+
"types": "./dist/wasm.d.ts",
54+
"default": "./dist/wasm.js"
55+
}
56+
},
4957
"./package.json": "./package.json"
5058
},
5159
"module": "./dist/index.js",

packages/code-chunk/src/parser/index.ts

Lines changed: 11 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
import { Effect } from 'effect'
2-
import {
3-
Parser,
4-
type Node as TSNode,
5-
type Tree as TSTree,
6-
} from 'web-tree-sitter'
2+
import { Parser } from 'web-tree-sitter'
73
import type { Language, ParseError, ParseResult } from '../types'
84
import {
95
clearGrammarCache,
106
type GrammarLoadError,
117
getLanguageGrammar,
128
} from './languages'
9+
import { buildParseResult } from './shared'
1310

14-
// Re-export language utilities
1511
export {
1612
clearGrammarCache,
1713
detectLanguage,
1814
GrammarLoadError,
1915
LANGUAGE_EXTENSIONS,
2016
loadGrammar,
2117
} from './languages'
18+
export {
19+
buildParseResult,
20+
getParseErrorMessage,
21+
hasParseErrors,
22+
} from './shared'
2223

23-
/**
24-
* Error thrown when parser initialization fails
25-
*/
2624
export class ParserInitError extends Error {
2725
readonly _tag = 'ParserInitError'
2826
override readonly cause?: unknown
@@ -34,16 +32,8 @@ export class ParserInitError extends Error {
3432
}
3533
}
3634

37-
/**
38-
* Flag to track if tree-sitter has been initialized
39-
*/
4035
let initialized: boolean = false
4136

42-
/**
43-
* Initialize the tree-sitter WASM module
44-
*
45-
* @returns Effect that initializes tree-sitter
46-
*/
4737
export function initParser(): Effect.Effect<void, ParserInitError> {
4838
return Effect.gen(function* () {
4939
if (initialized) {
@@ -60,99 +50,28 @@ export function initParser(): Effect.Effect<void, ParserInitError> {
6050
})
6151
}
6252

63-
/**
64-
* Check if a parse tree has errors
65-
*/
66-
function hasParseErrors(tree: TSTree): boolean {
67-
return tree.rootNode.hasError
68-
}
69-
70-
/**
71-
* Get error message from a tree with errors
72-
*/
73-
function getParseErrorMessage(tree: TSTree): string {
74-
const errorNodes: string[] = []
75-
76-
function findErrors(node: TSNode) {
77-
if (node.isError || node.isMissing) {
78-
const pos = node.startPosition
79-
errorNodes.push(
80-
`${node.isError ? 'ERROR' : 'MISSING'} at line ${pos.row + 1}, column ${pos.column + 1}`,
81-
)
82-
}
83-
for (const child of node.children) {
84-
findErrors(child)
85-
}
86-
}
87-
88-
findErrors(tree.rootNode)
89-
return errorNodes.length > 0
90-
? errorNodes.slice(0, 3).join('; ') +
91-
(errorNodes.length > 3 ? `; ... and ${errorNodes.length - 3} more` : '')
92-
: 'Unknown parse error'
93-
}
94-
95-
/**
96-
* Parse source code into an AST
97-
*
98-
* Uses Effect internally for error handling. Tree-sitter always produces a tree
99-
* even with syntax errors (recoverable parsing).
100-
*
101-
* @param parser - The tree-sitter parser instance
102-
* @param code - The source code to parse
103-
* @param language - The programming language
104-
* @returns Effect resolving to ParseResult
105-
*/
10653
export function parse(
10754
parser: Parser,
10855
code: string,
10956
language: Language,
11057
): Effect.Effect<ParseResult, ParseError | GrammarLoadError> {
11158
return Effect.gen(function* () {
112-
// Load and set the language grammar
11359
const grammar = yield* getLanguageGrammar(language)
11460
parser.setLanguage(grammar)
11561

116-
// Parse the code
11762
const tree = parser.parse(code)
63+
const result = buildParseResult(tree)
11864

119-
if (!tree) {
120-
return yield* Effect.fail({
121-
message: 'Parser returned null - no language set or parsing cancelled',
122-
recoverable: false,
123-
} satisfies ParseError)
65+
if (result.error && !result.error.recoverable) {
66+
return yield* Effect.fail(result.error)
12467
}
12568

126-
// Check for parse errors
127-
if (hasParseErrors(tree)) {
128-
return {
129-
tree,
130-
error: {
131-
message: getParseErrorMessage(tree),
132-
recoverable: true, // Tree-sitter always produces a tree
133-
},
134-
} satisfies ParseResult
135-
}
136-
137-
return {
138-
tree,
139-
error: null,
140-
} satisfies ParseResult
69+
return result
14170
})
14271
}
14372

144-
// ============================================================================
145-
// Public API - Unwraps Effect for consumers
146-
// ============================================================================
147-
148-
/**
149-
* Shared parser instance for the public API
150-
*/
15173
let sharedParser: Parser | null = null
15274

153-
/**
154-
* Get or create the shared parser instance
155-
*/
15675
async function getSharedParser(): Promise<Parser> {
15776
if (sharedParser) {
15877
return sharedParser
@@ -163,14 +82,6 @@ async function getSharedParser(): Promise<Parser> {
16382
return sharedParser
16483
}
16584

166-
/**
167-
* Parse source code into an AST (public async API)
168-
*
169-
* @param code - The source code to parse
170-
* @param language - The programming language
171-
* @returns Promise resolving to ParseResult
172-
* @throws ParseError or GrammarLoadError if parsing fails irrecoverably
173-
*/
17485
export async function parseCode(
17586
code: string,
17687
language: Language,
@@ -179,24 +90,10 @@ export async function parseCode(
17990
return Effect.runPromise(parse(parser, code, language))
18091
}
18192

182-
/**
183-
* Initialize the parser module (public async API)
184-
*
185-
* Call this before using other parser functions to ensure tree-sitter is ready.
186-
* This is called automatically by parseCode, but can be called explicitly for
187-
* early initialization.
188-
*
189-
* @returns Promise that resolves when initialization is complete
190-
* @throws ParserInitError if initialization fails
191-
*/
19293
export async function initializeParser(): Promise<void> {
19394
await getSharedParser()
19495
}
19596

196-
/**
197-
* Reset the shared parser state (useful for testing)
198-
* Also clears the grammar cache to ensure clean reinitialization
199-
*/
20097
export function resetParser(): void {
20198
if (sharedParser) {
20299
sharedParser.delete()
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import type { Node as TSNode, Tree as TSTree } from 'web-tree-sitter'
2+
import type { ParseResult } from '../types'
3+
4+
export function hasParseErrors(tree: TSTree): boolean {
5+
return tree.rootNode.hasError
6+
}
7+
8+
export function getParseErrorMessage(tree: TSTree): string {
9+
const errorNodes: string[] = []
10+
11+
function findErrors(node: TSNode) {
12+
if (node.isError || node.isMissing) {
13+
const pos = node.startPosition
14+
errorNodes.push(
15+
`${node.isError ? 'ERROR' : 'MISSING'} at line ${pos.row + 1}, column ${pos.column + 1}`,
16+
)
17+
}
18+
for (const child of node.children) {
19+
findErrors(child)
20+
}
21+
}
22+
23+
findErrors(tree.rootNode)
24+
return errorNodes.length > 0
25+
? errorNodes.slice(0, 3).join('; ') +
26+
(errorNodes.length > 3 ? `; ... and ${errorNodes.length - 3} more` : '')
27+
: 'Unknown parse error'
28+
}
29+
30+
export function buildParseResult(tree: TSTree | null): ParseResult {
31+
if (!tree) {
32+
return {
33+
tree: undefined as unknown as TSTree,
34+
error: {
35+
message: 'Parser returned null - no language set or parsing cancelled',
36+
recoverable: false,
37+
},
38+
}
39+
}
40+
41+
if (hasParseErrors(tree)) {
42+
return {
43+
tree,
44+
error: {
45+
message: getParseErrorMessage(tree),
46+
recoverable: true,
47+
},
48+
}
49+
}
50+
51+
return { tree, error: null }
52+
}

0 commit comments

Comments
 (0)