From bc14a7da3476291d4c9ccdae91f5c25bec0ce3e7 Mon Sep 17 00:00:00 2001 From: eneoli Date: Thu, 8 Aug 2024 16:08:34 +0200 Subject: [PATCH 1/2] special rendering for A -> False --- frontend/src/util/print-prop.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/frontend/src/util/print-prop.ts b/frontend/src/util/print-prop.ts index 46b8d7b..6dee2ea 100644 --- a/frontend/src/util/print-prop.ts +++ b/frontend/src/util/print-prop.ts @@ -55,6 +55,11 @@ export function printProp(prop: Prop): string { const shouldWrapFst = (propPrecedence > fstPrecedence) || (propPrecedence === fstPrecedence && isRightAssociative(prop)); const shouldWrapSnd = (propPrecedence > sndPrecedence) || (propPrecedence === sndPrecedence && isLeftAssociative(prop)); + // Special rendering for A -> False + if (prop.kind === 'Impl' && snd.kind === 'False') { + const shoudlWrap = propPrecedence > fstPrecedence; + return `¬${wrap(fst, shoudlWrap)}`; + } return wrap(fst, shouldWrapFst) + ` ${connective} ` + wrap(snd, shouldWrapSnd); } @@ -65,7 +70,13 @@ function getPrecedence(prop: Prop): number { case 'False': return 999; case 'And': return 4; case 'Or': return 3; - case 'Impl': return 2; + case 'Impl': { + if (prop.value[1].kind === 'False') { + return 999; + } + + return 2; + } case 'ForAll': return 1; case 'Exists': return 1; } From e44645548907a5c8106caf5bd707abc15bd7e831 Mon Sep 17 00:00:00 2001 From: eneoli Date: Sat, 10 Aug 2024 12:13:37 +0200 Subject: [PATCH 2/2] added prompt that instantiates passed proposition parameters --- ...f-editor-parameter-identifier-selector.tsx | 207 +++++++++++++++ .../and-elim-fst-rule-handler.ts | 14 +- .../and-elim-snd-rule-handler.ts | 14 +- .../exists-elim-rule-handler.ts | 29 +-- .../false-elim-rule-handler.ts | 15 +- .../impl-elim-rule-handler.ts | 13 +- .../or-elim-rule-handler.ts | 25 +- .../or-intro-fst-rule-handler.ts | 14 +- .../or-intro-snd-rule-handler.ts | 13 +- .../proof-rule-handler/proof-rule-handler.ts | 102 +++++++- src/kernel/prop.rs | 241 ++++++++++++++++++ src/lib.rs | 10 + 12 files changed, 609 insertions(+), 88 deletions(-) create mode 100644 frontend/src/domain/visual-proof-editor/components/visual-proof-editor-parameter-identifier-selector.tsx diff --git a/frontend/src/domain/visual-proof-editor/components/visual-proof-editor-parameter-identifier-selector.tsx b/frontend/src/domain/visual-proof-editor/components/visual-proof-editor-parameter-identifier-selector.tsx new file mode 100644 index 0000000..cabf40e --- /dev/null +++ b/frontend/src/domain/visual-proof-editor/components/visual-proof-editor-parameter-identifier-selector.tsx @@ -0,0 +1,207 @@ +import { get_free_parameters, Identifier, instantiate_free_parameter_by_index, Prop } from 'alice'; +import { Select, Space } from 'antd'; +import React, { Fragment, ReactElement, useCallback, useEffect, useRef, useState } from 'react'; + +interface VisualProofEditorParameterIdentifierSelectorProps { + prop: Prop; + options: { [name: string]: Identifier[] }, + onAllSelect: (prop: Prop) => void; + getPopupContainer?: () => HTMLElement; +} + +interface RenderPropResult { + node: ReactElement; + newIndex: number; +} + +type RenderProp = (prop: Prop, index: number, boundIdentifiers: string[]) => RenderPropResult; + +export function VisualProofEditorParameterIdentifierSelector(props: VisualProofEditorParameterIdentifierSelectorProps) { + const { + prop, + options, + onAllSelect, + getPopupContainer, + } = props; + + const containerRef = useRef(null); + const [paramMapping, setParamMapping] = useState<{ [idx: number]: number } | null>(null); + + useEffect(() => { + const selectableParamSize = get_free_parameters(prop) + .filter((param) => param.kind === 'Uninstantiated') + .length; + + setParamMapping(Object.assign({}, Array(selectableParamSize).fill(0))); + }, [prop]); + + useEffect(() => { + + if (!paramMapping) { + return; + } + + const params = get_free_parameters(prop); + let instantiatedProp = { ...prop }; + for (const [paramIndex, identifierIndex] of Object.entries(paramMapping)) { + const param = params[parseInt(paramIndex)]; + const paramName = param.kind === 'Instantiated' ? param.value.name : param.value; + + instantiatedProp = instantiate_free_parameter_by_index( + instantiatedProp, + parseInt(paramIndex), + options[paramName][identifierIndex], + ); + } + + onAllSelect(instantiatedProp); + }, [paramMapping]); + + const renderProp: RenderProp = (prop: Prop, index: number, boundIdentifiers: string[]) => { + + const handlePrimitive = useCallback((symbol: string, index: number) => { + return { + node: ({symbol}), + newIndex: index, + }; + }, []); + + const handleBinaryConnective = useCallback((symbol: string, prop: Prop & { kind: 'And' | 'Or' | 'Impl' }, index: number, boundIdentifiers: string[]) => { + const fst = renderProp(prop, index, [...boundIdentifiers]); + const snd = renderProp(prop, fst.newIndex, boundIdentifiers); + + const node = ( + <> + {fst.node} + + {symbol} + + {snd.node} + + ); + + return { + node, + newIndex: snd.newIndex, + }; + }, []); + + const handleQuantifier = useCallback((symbol: string, prop: Prop & { kind: 'ForAll' | 'Exists' }, index: number, boundIdentifiers: string[]) => { + const body = renderProp( + prop.value.body, + index, + [...boundIdentifiers, prop.value.object_ident], + ); + + const node = ( + <> + {symbol} + {prop.value.object_ident} + : + {prop.value.object_type_ident} + . + {body.node} + + ); + + return { + node, + newIndex: body.newIndex, + }; + }, []); + + const handleAtom = useCallback((prop: Prop & { kind: 'Atom' }, index: number, boundIdentifiers: string[]) => { + const params = prop.value[1]; + + const paramNodes = []; + for (const param of params) { + const paramIndex = index; + const paramName = param.kind === 'Instantiated' ? param.value.name : param.value; + + if (param.kind === 'Instantiated' || boundIdentifiers.includes(paramName)) { + paramNodes.push({paramName}); + + index++; + continue; + } + + const identOptions = options[paramName]; + + if (!identOptions || identOptions.length === 0) { + throw new Error(`No options for name ${paramName}.`); + } + + const selectionOptions = identOptions + .map((option, i) => ({ + label: `${option.name} - ${option.unique_id}`, + value: i, + })); + + const handleSelect = (idx: number) => { + setParamMapping({ + ...paramMapping, + [paramIndex]: idx, + }); + }; + + const node = ( + +