From 690d3441f896532c4b9cc6ae26ca85672b3fdf5d Mon Sep 17 00:00:00 2001 From: Matt Kantor Date: Tue, 22 Apr 2025 16:11:17 -0400 Subject: [PATCH] Add `boolean.and` & `boolean.or` to prelude Also `&&` & `||` aliases. --- src/language/semantics/prelude.ts | 2 + src/language/semantics/stdlib/boolean.ts | 79 +++++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/language/semantics/prelude.ts b/src/language/semantics/prelude.ts index 5e8266f..29f7326 100644 --- a/src/language/semantics/prelude.ts +++ b/src/language/semantics/prelude.ts @@ -22,4 +22,6 @@ export const prelude = makeObjectNode({ '<': integer.less_than, '>': integer.greater_than, '%': natural_number.modulo, + '&&': boolean.and, + '||': boolean.or, }) diff --git a/src/language/semantics/stdlib/boolean.ts b/src/language/semantics/stdlib/boolean.ts index fb32dbe..b1f9402 100644 --- a/src/language/semantics/stdlib/boolean.ts +++ b/src/language/semantics/stdlib/boolean.ts @@ -1,7 +1,12 @@ import either from '@matt.kantor/either' +import option from '@matt.kantor/option' +import { makeFunctionNode } from '../function-node.js' import { type SemanticGraph } from '../semantic-graph.js' import { types } from '../type-system.js' -import { preludeFunction } from './stdlib-utilities.js' +import { + preludeFunction, + serializeOnceAppliedFunction, +} from './stdlib-utilities.js' type BooleanNode = 'true' | 'false' const nodeIsBoolean = (node: SemanticGraph): node is BooleanNode => @@ -33,4 +38,76 @@ export const boolean = { } }, ), + and: preludeFunction( + ['boolean', 'and'], + { + parameter: types.boolean, + return: types.boolean, + }, + argument2 => { + if (!nodeIsBoolean(argument2)) { + return either.makeLeft({ + kind: 'panic', + message: 'argument was not a boolean', + }) + } else { + return either.makeRight( + makeFunctionNode( + { + parameter: types.boolean, + return: types.integer, + }, + serializeOnceAppliedFunction(['boolean', 'and'], argument2), + option.none, + argument1 => { + if (!nodeIsBoolean(argument1)) { + return either.makeLeft({ + kind: 'panic', + message: 'argument was not a boolean', + }) + } else { + return either.makeRight(String(argument1 && argument2)) + } + }, + ), + ) + } + }, + ), + or: preludeFunction( + ['boolean', 'or'], + { + parameter: types.boolean, + return: types.boolean, + }, + argument2 => { + if (!nodeIsBoolean(argument2)) { + return either.makeLeft({ + kind: 'panic', + message: 'argument was not a boolean', + }) + } else { + return either.makeRight( + makeFunctionNode( + { + parameter: types.boolean, + return: types.integer, + }, + serializeOnceAppliedFunction(['boolean', 'or'], argument2), + option.none, + argument1 => { + if (!nodeIsBoolean(argument1)) { + return either.makeLeft({ + kind: 'panic', + message: 'argument was not a boolean', + }) + } else { + return either.makeRight(String(argument1 || argument2)) + } + }, + ), + ) + } + }, + ), }