Skip to content

Commit 8c7eb12

Browse files
committed
modifier context and materialize flags
1 parent ba7a772 commit 8c7eb12

File tree

12 files changed

+44
-64
lines changed

12 files changed

+44
-64
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
"test"
1919
],
2020
"devDependencies": {
21-
"@biomejs/biome": "^2.2.3",
21+
"@biomejs/biome": "^2.2.4",
2222
"@changesets/changelog-github": "^0.5.1",
23-
"@changesets/cli": "^2.29.6",
23+
"@changesets/cli": "^2.29.7",
2424
"@types/bun": "^1.2.21",
2525
"knip": "^5.63.1",
2626
"sherif": "^1.6.1",

packages/get/src/calls.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ export async function callModifier(
1616
) {
1717
const entry = await registry.importMod(mod)
1818
if (entry) {
19-
return entry.mod(context?.data, args)
19+
const ctx =
20+
context && entry.materialize ? materialize(context) : context?.data
21+
return entry.mod(ctx, args)
2022
}
2123

2224
invariant(context, 'Modifier requires context')

packages/get/src/execute.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export async function execute(
107107
async SliceExpr({ slice, typeInfo }) {
108108
try {
109109
const ctx = scope.context
110-
const deps = ctx && materialize(ctx)
110+
const deps = ctx ? materialize(ctx) : {}
111111
const ret = await hooks.slice(slice.value, deps)
112112
const data =
113113
ret === undefined ? new lib.NullSelection('<slice>') : ret
@@ -158,12 +158,9 @@ export async function execute(
158158
},
159159

160160
async ModifierExpr(node) {
161-
const data = await callModifier(
162-
registry,
163-
node.modifier.value,
164-
node.args.data,
165-
scope.context,
166-
)
161+
const mod = node.modifier.value
162+
const args = materialize(node.args)
163+
const data = await callModifier(registry, mod, args, scope.context)
167164
return { data, typeInfo: node.typeInfo }
168165
},
169166

packages/get/src/registry.ts

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ import { Type } from '@getlang/ast'
33
import type { Hooks, Modifier } from '@getlang/lib'
44
import { RecursiveCallError, ValueTypeError } from '@getlang/lib/errors'
55
import { analyze, desugar, inference, parse } from '@getlang/parser'
6-
import type { Pattern } from 'acorn'
7-
import { parse as acorn } from 'acorn'
8-
import { traverse } from 'estree-toolkit'
96

107
type ModEntry = {
118
mod: Modifier
129
useContext: boolean
10+
materialize: boolean
1311
returnType: TypeInfo
1412
}
1513

@@ -53,31 +51,6 @@ function buildImportKey(module: string, typeInfo?: TypeInfo) {
5351
return key
5452
}
5553

56-
function inferContext(mod: Modifier) {
57-
const src = mod.toString()
58-
const ast = acorn(src, { ecmaVersion: 'latest' })
59-
let useContext = false
60-
traverse(ast, {
61-
$: { scope: true },
62-
Program(path) {
63-
const fn = ast.body[0]
64-
let ctxParam: Pattern | undefined
65-
if (fn?.type === 'FunctionDeclaration') {
66-
ctxParam = fn.params[0]
67-
} else if (fn?.type === 'ExpressionStatement') {
68-
if (fn.expression.type === 'ArrowFunctionExpression') {
69-
ctxParam = fn.expression.params[0]
70-
}
71-
}
72-
const fnScope = path.scope?.children[0]
73-
const bindings = Object.values(fnScope?.bindings || {})
74-
const ctxBinding = bindings.find(b => b?.identifierPath.node === ctxParam)
75-
useContext = Boolean(ctxBinding?.references.length)
76-
},
77-
})
78-
return useContext
79-
}
80-
8154
export class Registry {
8255
private info: Record<string, Promise<Info>> = {}
8356
private entries: Record<string, Promise<Entry>> = {}
@@ -91,10 +64,20 @@ export class Registry {
9164
if (!compiled) {
9265
return null
9366
}
94-
const fn = compiled.modifier
95-
const useContext = inferContext(fn)
96-
const returnType = compiled.typeInfo || { type: Type.Value }
97-
return { mod: fn, useContext, returnType }
67+
68+
const {
69+
modifier: fn,
70+
useContext = false,
71+
materialize = true,
72+
returnType = { type: Type.Value },
73+
} = compiled
74+
75+
return {
76+
mod: fn,
77+
useContext,
78+
materialize,
79+
returnType,
80+
}
9881
})
9982
return this.modifiers[mod]
10083
}

packages/lib/src/core/hooks.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ export type Modifier = (context: any, options: Record<string, unknown>) => any
2828
export type ModifierHook = (modifier: string) => MaybePromise<
2929
| {
3030
modifier: Modifier
31-
typeInfo?: TypeInfo
31+
useContext?: boolean
32+
materialize?: boolean
33+
returnType?: TypeInfo
3234
}
3335
| undefined
3436
>

packages/parser/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"@types/nearley": "^2.11.5",
3131
"acorn": "^8.15.0",
3232
"estree-toolkit": "^1.7.13",
33-
"globals": "^16.3.0",
33+
"globals": "^16.4.0",
3434
"lodash-es": "^4.17.21",
3535
"moo": "^0.5.2",
3636
"nearley": "^2.20.1",

packages/parser/src/passes/desugar.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const visitors = [
2323
dropDrills,
2424
]
2525

26-
export function desugar(ast: Program, macros: string[] = []) {
26+
export function desugar(ast: Program, macros: string[] = []): Program {
2727
const parsers = new RequestParsers()
2828
const program = visitors.reduce((ast, pass) => {
2929
parsers.reset()

packages/parser/src/passes/inference/calls.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { isToken } from '@getlang/ast'
33
import { transform } from '@getlang/walker'
44
import { LineageTracker } from '../lineage.js'
55

6-
export function registerCalls(ast: Program, macros: string[] = []) {
6+
export function registerCalls(ast: Program, macros: string[] = []): Program {
77
const scope = new LineageTracker()
88

99
function registerCall(node: Expr) {

packages/parser/src/passes/inference/typeinfo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ export function resolveTypes(ast: Program, options: ResolveTypeOptions) {
267267
},
268268
}
269269

270-
const program = transform(ast, { scope, ...visitor })
270+
const program: Program = transform(ast, { scope, ...visitor })
271271
const returnType = ex?.typeInfo ?? { type: Type.Never }
272272

273273
return { program, returnType: returnType }

test/helpers.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expect } from 'bun:test'
22
import { executeModule } from '@getlang/get'
3-
import type { Hooks, Inputs, MaybePromise, ModifierHook } from '@getlang/lib'
3+
import type { Hooks, Inputs, MaybePromise } from '@getlang/lib'
44
import { invariant } from '@getlang/lib'
55
import { ImportError } from '@getlang/lib/errors'
66
import { desugar, parse, print } from '@getlang/parser'
@@ -9,7 +9,6 @@ import './expect.js'
99

1010
type ExecuteOptions = Partial<{
1111
fetch: Fetch
12-
modifier: ModifierHook
1312
willThrow: boolean
1413
hooks: Hooks
1514
}>
@@ -29,7 +28,7 @@ export async function execute(
2928
inputs?: Inputs,
3029
options: ExecuteOptions = {},
3130
): Promise<any> {
32-
const { fetch, modifier, willThrow } = options
31+
const { fetch, willThrow } = options
3332
const normalized = typeof program === 'string' ? { Home: program } : program
3433
const modules: Record<string, string> = {}
3534
for (const [name, source] of Object.entries(normalized)) {
@@ -40,7 +39,6 @@ export async function execute(
4039
}
4140

4241
const hooks: Hooks = {
43-
modifier,
4442
import(module) {
4543
const src = modules[module]
4644
invariant(src, new ImportError(`Failed to import module: ${module}`))

0 commit comments

Comments
 (0)