Skip to content

Commit 559db65

Browse files
committed
Optimization
1 parent 0711ede commit 559db65

4 files changed

Lines changed: 249 additions & 15 deletions

File tree

example/wasm/wasm.ts

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/*--------------------------------------------------------------------------
2+
3+
ParseBox
4+
5+
The MIT License (MIT)
6+
7+
Copyright (c) 2024-2026 Haydn Paterson
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
---------------------------------------------------------------------------*/
28+
29+
export function test(math: Math) {
30+
const a = math.$add(1, 2)
31+
const b = math.$sub(1, 2)
32+
const c = math.$mul(1, 2)
33+
const d = math.$div(1, 2)
34+
35+
const expr = math.$add( // (1 - 2) + (3 + ((4 * 5) / 6))
36+
math.$sub(1, 2),
37+
math.$add(3,
38+
math.$div(
39+
math.$mul(4, 5),
40+
6
41+
)
42+
)
43+
)
44+
}
45+
46+
type Math = Wat<`(module
47+
(func $add (param $x f32) (param $y f32) (result f32)
48+
local.get $x
49+
local.get $y
50+
f32.add
51+
)
52+
(func $sub (param $x f32) (param $y f32) (result f32)
53+
local.get $x
54+
local.get $y
55+
f32.sub
56+
)
57+
(func $mul (param $x f32) (param $y f32) (result f32)
58+
local.get $x
59+
local.get $y
60+
f32.mul
61+
)
62+
(func $div (param $x f32) (param $y f32) (result f32)
63+
local.get $x
64+
local.get $y
65+
f32.div
66+
)
67+
)`>
68+
69+
import { Static } from '@sinclair/parsebox'
70+
71+
// ---------------------------------------------------
72+
// Wat: Parse
73+
// ---------------------------------------------------
74+
export type Wat<Code extends string,
75+
Parsed extends unknown = Static.Parse<Module, Code>[0],
76+
Ast extends TModule = Parsed extends TModule ? Parsed : TModule<[]>,
77+
Exports extends Record<PropertyKey, unknown> = GetExports<Ast>
78+
> = Exports
79+
80+
// ---------------------------------------------------
81+
// Query: Exports
82+
// ---------------------------------------------------
83+
type GetExportsParams<Params extends TParam[], Result extends unknown[] = []> = (
84+
Params extends [infer _ extends TParam, ...infer Right extends TParam[]]
85+
? GetExportsParams<Right, [...Result, number]> // i32, i64, f32, f64
86+
: Result
87+
)
88+
type GetExportsFunc<Func extends TFunc,
89+
Params extends unknown[] = GetExportsParams<Func['params']>,
90+
Return extends unknown = number, // single return type
91+
Result extends Record<PropertyKey, unknown> = {
92+
[K in Func['name']]: (...args: [...Params]) => Return
93+
}
94+
> = Result
95+
type GetExportsQuery<Funcs extends TFunc[], Result extends Record<PropertyKey, unknown> = {}> = (
96+
Funcs extends [infer Left extends TFunc, ...infer Right extends TFunc[]]
97+
? GetExportsQuery<Right, Result & GetExportsFunc<Left>>
98+
: {[K in keyof Result]: Result[K]}
99+
)
100+
type GetExports<Module extends TModule> = GetExportsQuery<Module['funcs']>
101+
102+
// ---------------------------------------------------
103+
// NativeType
104+
// ---------------------------------------------------
105+
type NativeType = Static.Union<[
106+
Static.Const<'i32'>,
107+
Static.Const<'i64'>,
108+
Static.Const<'f32'>,
109+
Static.Const<'i64'>
110+
]>
111+
// ---------------------------------------------------
112+
// Param
113+
// ---------------------------------------------------
114+
interface TParam<Name extends string = string, Type extends string = string> {
115+
kind: 'Param'
116+
name: Name
117+
type: Type
118+
}
119+
interface ParamMapping extends Static.IMapping {
120+
output: this['input'] extends ['(', 'param', infer Name extends string, infer Type extends string, ')']
121+
? TParam<Name, Type>
122+
: never
123+
}
124+
type Param = Static.Tuple<[
125+
Static.Const<'('>,
126+
Static.Const<'param'>,
127+
Static.Ident,
128+
NativeType,
129+
Static.Const<')'>
130+
], ParamMapping>
131+
type Params = Static.Array<Param>
132+
// ---------------------------------------------------
133+
// Result
134+
// ---------------------------------------------------
135+
interface TResult<Type extends string = string> {
136+
kind: 'Result'
137+
type: Type
138+
}
139+
interface ResultMapping extends Static.IMapping {
140+
output: this['input'] extends ['(', 'result', infer Type extends string, ')']
141+
? TResult<Type>
142+
: never
143+
}
144+
type Result = Static.Tuple<[
145+
Static.Const<'('>,
146+
Static.Const<'result'>,
147+
NativeType,
148+
Static.Const<')'>,
149+
], ResultMapping>
150+
// ---------------------------------------------------
151+
// Instruction
152+
// ---------------------------------------------------
153+
type Oprand = Static.Union<[
154+
Static.Ident,
155+
Static.Number
156+
]>
157+
interface TInstruction<
158+
Namespace extends string = string,
159+
Operator extends string = string,
160+
Operand extends string[] = string[]
161+
> {
162+
kind: 'Instruction'
163+
namespace: Namespace
164+
operator: Operator
165+
operand: Operand
166+
}
167+
interface InstructionMapping extends Static.IMapping {
168+
output: this['input'] extends [infer Namespace extends string, '.', infer Operator extends string, infer Operand extends string[]]
169+
? TInstruction<Namespace, Operator, Operand>
170+
: never
171+
}
172+
type Instruction = Static.Tuple<[
173+
Static.Union<[NativeType, Static.Const<'local'>]>,
174+
Static.Const<'.'>,
175+
Static.Ident,
176+
Static.Optional<Oprand>
177+
], InstructionMapping>
178+
type Instructions = Static.Array<Instruction>
179+
// ---------------------------------------------------
180+
// Func
181+
// ---------------------------------------------------
182+
interface TFunc<
183+
Name extends string = string,
184+
Params extends TParam[] = TParam[],
185+
Result extends TResult = TResult,
186+
Instructions extends TInstruction[] = TInstruction[]> {
187+
kind: 'Func'
188+
name: Name
189+
params: Params
190+
result: Result
191+
instructions: Instructions
192+
}
193+
interface FuncMapping extends Static.IMapping {
194+
output: this['input'] extends ['(', 'func', infer Name extends string, infer Params extends TParam[], infer Result extends TResult, infer Instructions extends TInstruction[], ')']
195+
? TFunc<Name, Params, Result, Instructions>
196+
: never
197+
}
198+
type Func = Static.Tuple<[
199+
Static.Const<'('>,
200+
Static.Const<'func'>,
201+
Static.Ident,
202+
Params,
203+
Result,
204+
Instructions,
205+
Static.Const<')'>
206+
], FuncMapping>
207+
type Funcs = Static.Array<Func>
208+
// ---------------------------------------------------
209+
// Module
210+
// ---------------------------------------------------
211+
interface TModule<Funcs extends TFunc[] = TFunc[]> {
212+
kind: 'Module'
213+
funcs: Funcs
214+
}
215+
interface ModuleMapping extends Static.IMapping {
216+
output: this['input'] extends ['(', 'module', infer Funcs extends TFunc[], ')']
217+
? TModule<Funcs>
218+
: never
219+
}
220+
type Module = Static.Tuple<[
221+
Static.Const<'('>,
222+
Static.Const<'module'>,
223+
Funcs,
224+
Static.Const<')'>
225+
], ModuleMapping>

src/runtime/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export { Module } from './module.ts'
3737
export { type INumber, IsNumber, Number } from './number.ts'
3838
export { type IOptional, IsOptional, Optional } from './optional.ts'
3939
export { Parse } from './parse.ts'
40-
export { type IParser, type IProperties, type IMapping, As, Identity } from './parser.ts'
40+
export { type IParser, type IProperties, type IMapping, Identity } from './parser.ts'
4141
export { type IRef, Ref, IsRef, } from './ref.ts'
4242
export { type IRest, Rest, IsRest, } from './rest.ts'
4343
export { type IString, IsString, String } from './string.ts'

src/runtime/parser.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ export type IMapping<Input extends unknown = any, Output extends unknown = unkno
3838
/** Maps input to output. This is the default Mapping */
3939
export const Identity = (value: unknown) => value
4040

41-
/** Maps the output as the given parameter T */
42-
export function As<T>(mapping: T): ((value: unknown) => T) {
43-
return (_: unknown) => mapping
44-
}
4541
// ------------------------------------------------------------------
4642
// Parser
4743
// ------------------------------------------------------------------

src/token/internal/take.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ THE SOFTWARE.
2828

2929
// deno-fmt-ignore-file
3030

31-
import { IsEqual, IsString } from './guard.ts'
31+
import { IsMatch } from './match.ts'
32+
import { IsEqual } from './guard.ts'
3233

3334
// ------------------------------------------------------------------
3435
// TakeString
@@ -58,13 +59,25 @@ export type TTake<Variants extends string[], Input extends string> = (
5859
)
5960
/** Takes one of the given variants or fail */
6061
export function Take<Variants extends string[], Input extends string>(variants: [...Variants], input: Input): TTake<Variants, Input> {
61-
const [left, ...right] = variants
62-
return (
63-
IsString(left)
64-
? (() => {
65-
const result = TakeVariant(left, input)
66-
return IsEqual(result.length, 2) ? result : Take(right, input)
67-
})()
68-
: []
69-
) as never
62+
// ----------------------------------------------------------------
63+
// Symmetric
64+
// ----------------------------------------------------------------
65+
// const [left, ...right] = variants
66+
// return (
67+
// IsString(left)
68+
// ? (() => {
69+
// const result = TakeVariant(left, input)
70+
// return IsEqual(result.length, 2) ? result : Take(right, input)
71+
// })()
72+
// : []
73+
// ) as never
74+
// ----------------------------------------------------------------
75+
// Inline
76+
// ----------------------------------------------------------------
77+
for (let i = 0; i < variants.length; i++) {
78+
const result = TakeVariant(variants[i], input)
79+
if (IsMatch(result)) return result as never
80+
}
81+
return [] as never
82+
7083
}

0 commit comments

Comments
 (0)