Skip to content

Commit 2c79a4a

Browse files
committed
Add natural_number.add to prelude
1 parent 10d144c commit 2c79a4a

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

src/end-to-end.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,11 @@ testCases(endToEnd, code => code)('end-to-end tests', [
191191
assert.deepEqual(typeof output.value.value, 'string')
192192
},
193193
],
194+
[`:natural_number.add(1)(1)`, either.makeRight('2')],
195+
[
196+
`:natural_number.add(one)(juan)`,
197+
output => {
198+
assert(either.isLeft(output))
199+
},
200+
],
194201
])

src/language/compiling/semantics/prelude.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
makeFunctionType,
2525
makeObjectType,
2626
makeTypeParameter,
27+
makeUnionType,
2728
type FunctionType,
2829
} from '../../semantics/type-system/type-formats.js'
2930

@@ -279,6 +280,67 @@ export const prelude: ObjectNode = makeObjectNode({
279280
},
280281
),
281282

283+
natural_number: makeObjectNode({
284+
add: preludeFunction(
285+
['natural_number', 'add'],
286+
{
287+
parameter: types.naturalNumber,
288+
return: makeFunctionType('', {
289+
parameter: types.naturalNumber,
290+
return: types.naturalNumber,
291+
}),
292+
},
293+
number1 =>
294+
either.makeRight(
295+
makeFunctionNode(
296+
{
297+
parameter: types.naturalNumber,
298+
return: types.naturalNumber,
299+
},
300+
() =>
301+
either.makeRight(
302+
makeUnelaboratedObjectNode({
303+
0: '@apply',
304+
function: {
305+
0: '@lookup',
306+
query: { 0: 'natural_number', 1: 'add' },
307+
},
308+
argument: number1,
309+
}),
310+
),
311+
option.none,
312+
number2 => {
313+
if (
314+
typeof number1 !== 'string' ||
315+
!types.naturalNumber.isAssignableFrom(
316+
makeUnionType('', [number1]),
317+
) ||
318+
typeof number2 !== 'string' ||
319+
!types.naturalNumber.isAssignableFrom(
320+
makeUnionType('', [number2]),
321+
)
322+
) {
323+
return either.makeLeft({
324+
kind: 'panic',
325+
message: 'numbers must be atoms',
326+
})
327+
} else {
328+
return either.makeRight(
329+
// FIXME: It's wasteful to always convert here.
330+
//
331+
// Consider `add(add(1)(1))(1)`—the `2` returned from the inner `add` is
332+
// stringified only to be converted back to a bigint. This is acceptable for the
333+
// prototype, but a real implementation could use a fancier `SemanticGraph` which
334+
// can model atoms as different native data types.
335+
String(BigInt(number1) + BigInt(number2)),
336+
)
337+
}
338+
},
339+
),
340+
),
341+
),
342+
}),
343+
282344
object: makeObjectNode({
283345
lookup: preludeFunction(
284346
['object', 'lookup'],

0 commit comments

Comments
 (0)