septima-lang 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/ast-node.d.ts +103 -0
- package/dist/src/ast-node.js +156 -0
- package/dist/src/extract-message.d.ts +1 -0
- package/dist/src/extract-message.js +10 -0
- package/dist/src/fail-me.d.ts +1 -0
- package/dist/src/fail-me.js +11 -0
- package/dist/src/find-array-method.d.ts +15 -0
- package/dist/src/find-array-method.js +104 -0
- package/dist/src/find-string-method.d.ts +2 -0
- package/dist/src/find-string-method.js +88 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +18 -0
- package/dist/src/location.d.ts +11 -0
- package/dist/src/location.js +3 -0
- package/dist/src/parser.d.ts +45 -0
- package/dist/src/parser.js +490 -0
- package/dist/src/result.d.ts +24 -0
- package/dist/src/result.js +29 -0
- package/dist/src/runtime.d.ts +28 -0
- package/dist/src/runtime.js +351 -0
- package/dist/src/scanner.d.ts +23 -0
- package/dist/src/scanner.js +88 -0
- package/dist/src/septima.d.ts +32 -0
- package/dist/src/septima.js +91 -0
- package/dist/src/should-never-happen.d.ts +1 -0
- package/dist/src/should-never-happen.js +9 -0
- package/dist/src/source-code.d.ts +19 -0
- package/dist/src/source-code.js +90 -0
- package/dist/src/stack.d.ts +11 -0
- package/dist/src/stack.js +19 -0
- package/dist/src/switch-on.d.ts +1 -0
- package/dist/src/switch-on.js +9 -0
- package/dist/src/symbol-table.d.ts +6 -0
- package/dist/src/symbol-table.js +3 -0
- package/dist/src/value.d.ts +128 -0
- package/dist/src/value.js +634 -0
- package/dist/tests/parser.spec.d.ts +1 -0
- package/dist/tests/parser.spec.js +35 -0
- package/dist/tests/septima-compute-module.spec.d.ts +1 -0
- package/dist/tests/septima-compute-module.spec.js +36 -0
- package/dist/tests/septima.spec.d.ts +1 -0
- package/dist/tests/septima.spec.js +857 -0
- package/dist/tests/value.spec.d.ts +1 -0
- package/dist/tests/value.spec.js +355 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +3 -3
- package/src/a.js +66 -0
- package/src/ast-node.ts +269 -0
- package/src/extract-message.ts +5 -0
- package/src/fail-me.ts +7 -0
- package/src/find-array-method.ts +115 -0
- package/src/find-string-method.ts +84 -0
- package/src/index.ts +1 -0
- package/src/location.ts +13 -0
- package/src/parser.ts +563 -0
- package/src/result.ts +45 -0
- package/src/runtime.ts +370 -0
- package/src/scanner.ts +106 -0
- package/src/septima.ts +121 -0
- package/src/should-never-happen.ts +4 -0
- package/src/source-code.ts +101 -0
- package/src/stack.ts +18 -0
- package/src/switch-on.ts +4 -0
- package/src/symbol-table.ts +7 -0
- package/src/value.ts +742 -0
- package/tests/parser.spec.ts +36 -0
- package/tests/septima-compute-module.spec.ts +41 -0
- package/tests/septima.spec.ts +933 -0
- package/tests/value.spec.ts +387 -0
- package/main.js +0 -1
package/src/ast-node.ts
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { Span } from './location'
|
|
2
|
+
import { Token } from './scanner'
|
|
3
|
+
import { shouldNeverHappen } from './should-never-happen'
|
|
4
|
+
import { switchOn } from './switch-on'
|
|
5
|
+
|
|
6
|
+
export type Let = { start: Token; ident: Ident; value: AstNode }
|
|
7
|
+
|
|
8
|
+
export type Import = {
|
|
9
|
+
start: Token
|
|
10
|
+
ident: Ident
|
|
11
|
+
pathToImportFrom: Token
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type Literal = {
|
|
15
|
+
tag: 'literal'
|
|
16
|
+
type: 'str' | 'bool' | 'num' | 'sink' | 'sink!' | 'sink!!'
|
|
17
|
+
t: Token
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type ObjectLiteralPart =
|
|
21
|
+
| { tag: 'hardName'; k: Ident; v: AstNode }
|
|
22
|
+
| { tag: 'computedName'; k: AstNode; v: AstNode }
|
|
23
|
+
| { tag: 'spread'; o: AstNode }
|
|
24
|
+
|
|
25
|
+
export type ArrayLiteralPart = { tag: 'element'; v: AstNode } | { tag: 'spread'; v: AstNode }
|
|
26
|
+
|
|
27
|
+
export type Ident = {
|
|
28
|
+
tag: 'ident'
|
|
29
|
+
t: Token
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type Lambda = {
|
|
33
|
+
tag: 'lambda'
|
|
34
|
+
start: Token
|
|
35
|
+
formalArgs: Ident[]
|
|
36
|
+
body: AstNode
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type Unit = {
|
|
40
|
+
tag: 'unit'
|
|
41
|
+
imports: Import[]
|
|
42
|
+
expression: AstNode
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type AstNode =
|
|
46
|
+
| Ident
|
|
47
|
+
| Literal
|
|
48
|
+
| Unit
|
|
49
|
+
| {
|
|
50
|
+
start: Token
|
|
51
|
+
tag: 'arrayLiteral'
|
|
52
|
+
parts: ArrayLiteralPart[]
|
|
53
|
+
end: Token
|
|
54
|
+
}
|
|
55
|
+
| {
|
|
56
|
+
start: Token
|
|
57
|
+
tag: 'objectLiteral'
|
|
58
|
+
parts: ObjectLiteralPart[]
|
|
59
|
+
end: Token
|
|
60
|
+
}
|
|
61
|
+
| {
|
|
62
|
+
tag: 'binaryOperator'
|
|
63
|
+
operator: '+' | '-' | '*' | '/' | '**' | '%' | '&&' | '||' | '>' | '<' | '>=' | '<=' | '==' | '!=' | '??'
|
|
64
|
+
lhs: AstNode
|
|
65
|
+
rhs: AstNode
|
|
66
|
+
}
|
|
67
|
+
| {
|
|
68
|
+
tag: 'unaryOperator'
|
|
69
|
+
operatorToken: Token
|
|
70
|
+
operator: '+' | '-' | '!'
|
|
71
|
+
operand: AstNode
|
|
72
|
+
}
|
|
73
|
+
| {
|
|
74
|
+
tag: 'topLevelExpression'
|
|
75
|
+
definitions: Let[]
|
|
76
|
+
computation?: AstNode
|
|
77
|
+
}
|
|
78
|
+
| Lambda
|
|
79
|
+
| {
|
|
80
|
+
tag: 'ternary'
|
|
81
|
+
condition: AstNode
|
|
82
|
+
positive: AstNode
|
|
83
|
+
negative: AstNode
|
|
84
|
+
}
|
|
85
|
+
| {
|
|
86
|
+
tag: 'functionCall'
|
|
87
|
+
actualArgs: AstNode[]
|
|
88
|
+
callee: AstNode
|
|
89
|
+
end: Token
|
|
90
|
+
}
|
|
91
|
+
| {
|
|
92
|
+
tag: 'if'
|
|
93
|
+
condition: AstNode
|
|
94
|
+
positive: AstNode
|
|
95
|
+
negative: AstNode
|
|
96
|
+
}
|
|
97
|
+
| {
|
|
98
|
+
tag: 'dot'
|
|
99
|
+
receiver: AstNode
|
|
100
|
+
ident: Ident
|
|
101
|
+
}
|
|
102
|
+
| {
|
|
103
|
+
tag: 'indexAccess'
|
|
104
|
+
receiver: AstNode
|
|
105
|
+
index: AstNode
|
|
106
|
+
}
|
|
107
|
+
| {
|
|
108
|
+
// A sepcial AST node meant to be generated internally (needed for exporting definition from one unit to another).
|
|
109
|
+
// Not intended to be parsed from source code. Hence, it is effectively empty, and its location cannot be
|
|
110
|
+
// determined.
|
|
111
|
+
tag: 'export*'
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function show(ast: AstNode | AstNode[]): string {
|
|
115
|
+
if (Array.isArray(ast)) {
|
|
116
|
+
return ast.map(curr => show(curr)).join(', ')
|
|
117
|
+
}
|
|
118
|
+
if (ast.tag === 'arrayLiteral') {
|
|
119
|
+
const parts = ast.parts.map(p => {
|
|
120
|
+
if (p.tag === 'element') {
|
|
121
|
+
return show(p.v)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (p.tag === 'spread') {
|
|
125
|
+
return `...${show(p.v)}`
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
shouldNeverHappen(p)
|
|
129
|
+
})
|
|
130
|
+
return `[${parts.join(', ')}]`
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (ast.tag === 'binaryOperator') {
|
|
134
|
+
return `(${show(ast.lhs)} ${ast.operator} ${show(ast.rhs)})`
|
|
135
|
+
}
|
|
136
|
+
if (ast.tag === 'dot') {
|
|
137
|
+
return `${show(ast.receiver)}.${show(ast.ident)}`
|
|
138
|
+
}
|
|
139
|
+
if (ast.tag === 'export*') {
|
|
140
|
+
return `(export*)`
|
|
141
|
+
}
|
|
142
|
+
if (ast.tag === 'ternary') {
|
|
143
|
+
return `${show(ast.condition)} ? ${show(ast.positive)} : ${show(ast.negative)}`
|
|
144
|
+
}
|
|
145
|
+
if (ast.tag === 'functionCall') {
|
|
146
|
+
return `${show(ast.callee)}(${show(ast.actualArgs)})`
|
|
147
|
+
}
|
|
148
|
+
if (ast.tag === 'ident') {
|
|
149
|
+
return ast.t.text
|
|
150
|
+
}
|
|
151
|
+
if (ast.tag === 'if') {
|
|
152
|
+
return `if (${show(ast.condition)}) ${show(ast.positive)} else ${show(ast.negative)}`
|
|
153
|
+
}
|
|
154
|
+
if (ast.tag === 'indexAccess') {
|
|
155
|
+
return `${show(ast.receiver)}[${show(ast.index)}]`
|
|
156
|
+
}
|
|
157
|
+
if (ast.tag === 'lambda') {
|
|
158
|
+
return `fun (${show(ast.formalArgs)}) ${show(ast.body)}`
|
|
159
|
+
}
|
|
160
|
+
if (ast.tag === 'literal') {
|
|
161
|
+
return switchOn(ast.type, {
|
|
162
|
+
bool: () => ast.t.text,
|
|
163
|
+
num: () => ast.t.text,
|
|
164
|
+
sink: () => 'sink',
|
|
165
|
+
'sink!': () => 'sink!',
|
|
166
|
+
'sink!!': () => 'sink!!',
|
|
167
|
+
str: () => `'${ast.t.text}'`,
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
if (ast.tag === 'objectLiteral') {
|
|
171
|
+
const pairs = ast.parts.map(p => {
|
|
172
|
+
if (p.tag === 'computedName') {
|
|
173
|
+
return `[${show(p.k)}]: ${show(p.v)}`
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (p.tag === 'hardName') {
|
|
177
|
+
return `${show(p.k)}: ${show(p.v)}`
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (p.tag === 'spread') {
|
|
181
|
+
return `...${show(p.o)}`
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
shouldNeverHappen(p)
|
|
185
|
+
})
|
|
186
|
+
return `{${pairs.join(', ')}}`
|
|
187
|
+
}
|
|
188
|
+
if (ast.tag === 'topLevelExpression') {
|
|
189
|
+
const defs = ast.definitions.map(d => `let ${show(d.ident)} = ${show(d.value)}`).join('; ')
|
|
190
|
+
const sep = defs && ast.computation ? ' ' : ''
|
|
191
|
+
return `${defs ? defs + ';' : ''}${sep}${ast.computation ? show(ast.computation) : ''}`
|
|
192
|
+
}
|
|
193
|
+
if (ast.tag === 'unaryOperator') {
|
|
194
|
+
return `${ast.operator}${show(ast.operand)}`
|
|
195
|
+
}
|
|
196
|
+
if (ast.tag === 'unit') {
|
|
197
|
+
const imports = ast.imports
|
|
198
|
+
.map(imp => `import * as ${show(imp.ident)} from '${imp.pathToImportFrom.text}';`)
|
|
199
|
+
.join('\n')
|
|
200
|
+
return `${imports ? imports + '\n' : ''}${show(ast.expression)}`
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
shouldNeverHappen(ast)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function span(ast: AstNode): Span {
|
|
207
|
+
const ofRange = (a: Span, b: Span) => ({ from: a.from, to: b.to })
|
|
208
|
+
const ofToken = (t: Token) => ({ from: t.location, to: { offset: t.location.offset + t.text.length - 1 } })
|
|
209
|
+
|
|
210
|
+
if (ast.tag === 'arrayLiteral') {
|
|
211
|
+
return ofRange(ofToken(ast.start), ofToken(ast.end))
|
|
212
|
+
}
|
|
213
|
+
if (ast.tag === 'binaryOperator') {
|
|
214
|
+
return ofRange(span(ast.lhs), span(ast.rhs))
|
|
215
|
+
}
|
|
216
|
+
if (ast.tag === 'dot') {
|
|
217
|
+
return ofRange(span(ast.receiver), span(ast.ident))
|
|
218
|
+
}
|
|
219
|
+
if (ast.tag === 'functionCall') {
|
|
220
|
+
return ofRange(span(ast.callee), ofToken(ast.end))
|
|
221
|
+
}
|
|
222
|
+
if (ast.tag === 'ident') {
|
|
223
|
+
return ofToken(ast.t)
|
|
224
|
+
}
|
|
225
|
+
if (ast.tag === 'export*') {
|
|
226
|
+
return { from: { offset: 0 }, to: { offset: 0 } }
|
|
227
|
+
}
|
|
228
|
+
if (ast.tag === 'if') {
|
|
229
|
+
return ofRange(span(ast.condition), span(ast.negative))
|
|
230
|
+
}
|
|
231
|
+
if (ast.tag === 'indexAccess') {
|
|
232
|
+
return ofRange(span(ast.receiver), span(ast.index))
|
|
233
|
+
}
|
|
234
|
+
if (ast.tag === 'lambda') {
|
|
235
|
+
return ofRange(ofToken(ast.start), span(ast.body))
|
|
236
|
+
}
|
|
237
|
+
if (ast.tag === 'ternary') {
|
|
238
|
+
return ofRange(span(ast.condition), span(ast.negative))
|
|
239
|
+
}
|
|
240
|
+
if (ast.tag === 'literal') {
|
|
241
|
+
return ofToken(ast.t)
|
|
242
|
+
}
|
|
243
|
+
if (ast.tag === 'objectLiteral') {
|
|
244
|
+
return ofRange(ofToken(ast.start), ofToken(ast.end))
|
|
245
|
+
}
|
|
246
|
+
if (ast.tag === 'topLevelExpression') {
|
|
247
|
+
if (ast.computation) {
|
|
248
|
+
const d0 = ast.definitions.find(Boolean)
|
|
249
|
+
const comp = span(ast.computation)
|
|
250
|
+
return ofRange(d0 ? ofToken(d0.start) : comp, comp)
|
|
251
|
+
} else if (ast.definitions.length) {
|
|
252
|
+
const first = ast.definitions[0]
|
|
253
|
+
const last = ast.definitions[ast.definitions.length - 1]
|
|
254
|
+
return ofRange(ofToken(first.start), span(last.value))
|
|
255
|
+
} else {
|
|
256
|
+
return { from: { offset: 0 }, to: { offset: 0 } }
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (ast.tag === 'unaryOperator') {
|
|
260
|
+
return ofRange(ofToken(ast.operatorToken), span(ast.operand))
|
|
261
|
+
}
|
|
262
|
+
if (ast.tag === 'unit') {
|
|
263
|
+
const i0 = ast.imports.find(Boolean)
|
|
264
|
+
const exp = span(ast.expression)
|
|
265
|
+
return ofRange(i0 ? ofToken(i0.start) : exp, exp)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
shouldNeverHappen(ast)
|
|
269
|
+
}
|
package/src/fail-me.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Value } from './value'
|
|
2
|
+
|
|
3
|
+
export type CallEvaluator = (callable: Value, args: Value[]) => Value
|
|
4
|
+
/**
|
|
5
|
+
* return an implementation for array methods. The following Array methods were not implemented
|
|
6
|
+
* as it is hard to find an intuitive immutable API due to their mutable nature:
|
|
7
|
+
* - copyWithin
|
|
8
|
+
* - fill
|
|
9
|
+
* - forEach
|
|
10
|
+
* - keys
|
|
11
|
+
* - pop
|
|
12
|
+
* - push
|
|
13
|
+
* - shift
|
|
14
|
+
* - unshift
|
|
15
|
+
*/
|
|
16
|
+
export function findArrayMethod(arr: unknown[], index: string, callEvaluator: CallEvaluator) {
|
|
17
|
+
const adjustedCallback =
|
|
18
|
+
(callback: Value) =>
|
|
19
|
+
(...args: unknown[]) =>
|
|
20
|
+
callEvaluator(
|
|
21
|
+
callback,
|
|
22
|
+
args.map(x => Value.from(x)),
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
const adjustedPredicate =
|
|
26
|
+
(predicate: Value) =>
|
|
27
|
+
(...args: unknown[]) =>
|
|
28
|
+
callEvaluator(
|
|
29
|
+
predicate,
|
|
30
|
+
args.map(x => Value.from(x)),
|
|
31
|
+
).assertBool()
|
|
32
|
+
|
|
33
|
+
if (index === 'at') {
|
|
34
|
+
return Value.foreign(n => arr.at(n.assertNum()))
|
|
35
|
+
}
|
|
36
|
+
if (index === 'concat') {
|
|
37
|
+
return Value.foreign(arg => arr.concat(arg.assertArr()))
|
|
38
|
+
}
|
|
39
|
+
if (index === 'entries') {
|
|
40
|
+
return Value.foreign(() => [...arr.entries()])
|
|
41
|
+
}
|
|
42
|
+
if (index === 'every') {
|
|
43
|
+
return Value.foreign(predicate => arr.every(adjustedPredicate(predicate)))
|
|
44
|
+
}
|
|
45
|
+
if (index === 'filter') {
|
|
46
|
+
return Value.foreign(predicate => arr.filter(adjustedPredicate(predicate)))
|
|
47
|
+
}
|
|
48
|
+
if (index === 'find') {
|
|
49
|
+
return Value.foreign(predicate => arr.find(adjustedPredicate(predicate)))
|
|
50
|
+
}
|
|
51
|
+
if (index === 'findIndex') {
|
|
52
|
+
return Value.foreign(predicate => arr.findIndex(adjustedPredicate(predicate)))
|
|
53
|
+
}
|
|
54
|
+
if (index === 'flatMap') {
|
|
55
|
+
return Value.foreign(callback => flatten(arr.map(adjustedCallback(callback))))
|
|
56
|
+
}
|
|
57
|
+
if (index === 'flat') {
|
|
58
|
+
return Value.foreign(() => flatten(arr))
|
|
59
|
+
}
|
|
60
|
+
if (index === 'includes') {
|
|
61
|
+
return Value.foreign((arg: Value) => arr.some(curr => Value.from(curr).equalsTo(arg).isTrue()))
|
|
62
|
+
}
|
|
63
|
+
if (index === 'indexOf') {
|
|
64
|
+
return Value.foreign(arg => arr.findIndex(curr => Value.from(curr).equalsTo(arg).isTrue()))
|
|
65
|
+
}
|
|
66
|
+
if (index === 'join') {
|
|
67
|
+
return Value.foreign(arg => arr.join(arg.assertStr()))
|
|
68
|
+
}
|
|
69
|
+
if (index === 'lastIndexOf') {
|
|
70
|
+
return Value.foreign(arg => {
|
|
71
|
+
for (let i = arr.length - 1; i >= 0; --i) {
|
|
72
|
+
if (Value.from(arr[i]).equalsTo(arg).isTrue()) {
|
|
73
|
+
return i
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return -1
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
if (index === 'length') {
|
|
80
|
+
return Value.num(arr.length)
|
|
81
|
+
}
|
|
82
|
+
if (index === 'map') {
|
|
83
|
+
return Value.foreign(callback => arr.map(adjustedCallback(callback)))
|
|
84
|
+
}
|
|
85
|
+
if (index === 'reverse') {
|
|
86
|
+
return Value.foreign(() => [...arr].reverse())
|
|
87
|
+
}
|
|
88
|
+
if (index === 'reduce') {
|
|
89
|
+
return Value.foreign((callback, initialValue) => arr.reduce(adjustedCallback(callback), initialValue))
|
|
90
|
+
}
|
|
91
|
+
if (index === 'reduceRight') {
|
|
92
|
+
return Value.foreign((callback, initialValue) => arr.reduceRight(adjustedCallback(callback), initialValue))
|
|
93
|
+
}
|
|
94
|
+
if (index === 'slice') {
|
|
95
|
+
return Value.foreign((start, end) => arr.slice(start?.assertNum(), end?.assertNum()))
|
|
96
|
+
}
|
|
97
|
+
if (index === 'some') {
|
|
98
|
+
return Value.foreign(predicate => arr.some(adjustedPredicate(predicate)))
|
|
99
|
+
}
|
|
100
|
+
throw new Error(`Unrecognized array method: ${index}`)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function flatten(input: unknown[]) {
|
|
104
|
+
const ret = []
|
|
105
|
+
for (const curr of input) {
|
|
106
|
+
const v = Value.from(curr)
|
|
107
|
+
const unwrapped = v.unwrap()
|
|
108
|
+
if (Array.isArray(unwrapped)) {
|
|
109
|
+
ret.push(...unwrapped)
|
|
110
|
+
} else {
|
|
111
|
+
ret.push(v)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return ret
|
|
115
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Value } from './value'
|
|
2
|
+
|
|
3
|
+
export function findStringMethod(s: string, indexValue: string | Value) {
|
|
4
|
+
const index = Value.toStringOrNumber(indexValue)
|
|
5
|
+
if (typeof index === 'number') {
|
|
6
|
+
throw new Error(`Index is of type number - not supported`)
|
|
7
|
+
}
|
|
8
|
+
if (index === 'at') {
|
|
9
|
+
return Value.foreign(n => s.at(n.assertNum()))
|
|
10
|
+
}
|
|
11
|
+
if (index === 'charAt') {
|
|
12
|
+
return Value.foreign(n => s.charAt(n.assertNum()))
|
|
13
|
+
}
|
|
14
|
+
if (index === 'concat') {
|
|
15
|
+
return Value.foreign(arg => s.concat(arg.assertStr()))
|
|
16
|
+
}
|
|
17
|
+
if (index === 'endsWith') {
|
|
18
|
+
return Value.foreign(arg => s.endsWith(arg.assertStr()))
|
|
19
|
+
}
|
|
20
|
+
if (index === 'includes') {
|
|
21
|
+
return Value.foreign(arg => s.includes(arg.assertStr()))
|
|
22
|
+
}
|
|
23
|
+
if (index === 'indexOf') {
|
|
24
|
+
return Value.foreign(searchString => s.indexOf(searchString.assertStr()))
|
|
25
|
+
}
|
|
26
|
+
if (index === 'lastIndexOf') {
|
|
27
|
+
return Value.foreign(searchString => s.lastIndexOf(searchString.assertStr()))
|
|
28
|
+
}
|
|
29
|
+
if (index === 'length') {
|
|
30
|
+
return Value.num(s.length)
|
|
31
|
+
}
|
|
32
|
+
if (index === 'match') {
|
|
33
|
+
return Value.foreign(r => s.match(r.assertStr()))
|
|
34
|
+
}
|
|
35
|
+
if (index === 'matchAll') {
|
|
36
|
+
return Value.foreign(r => [...s.matchAll(new RegExp(r.assertStr(), 'g'))])
|
|
37
|
+
}
|
|
38
|
+
if (index === 'padEnd') {
|
|
39
|
+
return Value.foreign((maxLength, fillString) => s.padEnd(maxLength.assertNum(), fillString?.assertStr()))
|
|
40
|
+
}
|
|
41
|
+
if (index === 'padStart') {
|
|
42
|
+
return Value.foreign((maxLength, fillString) => s.padStart(maxLength.assertNum(), fillString?.assertStr()))
|
|
43
|
+
}
|
|
44
|
+
if (index === 'repeat') {
|
|
45
|
+
return Value.foreign(count => s.repeat(count.assertNum()))
|
|
46
|
+
}
|
|
47
|
+
if (index === 'replace') {
|
|
48
|
+
return Value.foreign((searchValue, replacer) => s.replace(searchValue.assertStr(), replacer.assertStr()))
|
|
49
|
+
}
|
|
50
|
+
if (index === 'replaceAll') {
|
|
51
|
+
return Value.foreign((searchValue, replacer) => s.replaceAll(searchValue.assertStr(), replacer.assertStr()))
|
|
52
|
+
}
|
|
53
|
+
if (index === 'search') {
|
|
54
|
+
return Value.foreign(searcher => s.search(searcher.assertStr()))
|
|
55
|
+
}
|
|
56
|
+
if (index === 'slice') {
|
|
57
|
+
return Value.foreign((start, end) => s.slice(start?.assertNum(), end?.assertNum()))
|
|
58
|
+
}
|
|
59
|
+
if (index === 'split') {
|
|
60
|
+
return Value.foreign(splitter => s.split(splitter.assertStr()))
|
|
61
|
+
}
|
|
62
|
+
if (index === 'startsWith') {
|
|
63
|
+
return Value.foreign(arg => s.startsWith(arg.assertStr()))
|
|
64
|
+
}
|
|
65
|
+
if (index === 'substring') {
|
|
66
|
+
return Value.foreign((start, end) => s.substring(start.assertNum(), end?.assertNum()))
|
|
67
|
+
}
|
|
68
|
+
if (index === 'toLowerCase') {
|
|
69
|
+
return Value.foreign(() => s.toLowerCase())
|
|
70
|
+
}
|
|
71
|
+
if (index === 'toUpperCase') {
|
|
72
|
+
return Value.foreign(() => s.toUpperCase())
|
|
73
|
+
}
|
|
74
|
+
if (index === 'trim') {
|
|
75
|
+
return Value.foreign(() => s.trim())
|
|
76
|
+
}
|
|
77
|
+
if (index === 'trimEnd') {
|
|
78
|
+
return Value.foreign(() => s.trimEnd())
|
|
79
|
+
}
|
|
80
|
+
if (index === 'trimStart') {
|
|
81
|
+
return Value.foreign(() => s.trimStart())
|
|
82
|
+
}
|
|
83
|
+
throw new Error(`Unrecognized string method: ${index}`)
|
|
84
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './septima'
|