Add warning if term expressions are not equal

This commit is contained in:
Ivan 2024-08-28 12:33:47 +03:00
parent 49ff1c8f6c
commit 0a5fb5eecf
6 changed files with 72 additions and 8 deletions

View File

@ -37,7 +37,12 @@ function TabSynthesis({
substitutions={substitutions}
setSubstitutions={setSubstitutions}
/>
<TextArea disabled value={validationText} style={{ borderColor: isCorrect ? undefined : colors.fgRed }} />
<TextArea
disabled
value={validationText}
rows={4}
style={{ borderColor: isCorrect ? undefined : colors.fgRed }}
/>
</DataLoader>
);
}

View File

@ -213,6 +213,7 @@ export enum SubstitutionErrorType {
typificationCycle,
baseSubstitutionNotSet,
unequalTypification,
unequalExpressions,
unequalArgsCount,
unequalArgs
}

View File

@ -2,13 +2,15 @@
* Module: API for OperationSystem.
*/
import { limits } from '@/utils/constants';
import { describeSubstitutionError, information } from '@/utils/labels';
import { TextMatcher } from '@/utils/utils';
import { Graph } from './Graph';
import { ILibraryItem, LibraryItemID } from './library';
import { ICstSubstitute, IOperation, IOperationSchema, SubstitutionErrorType } from './oss';
import { ConstituentaID, CstType, IConstituenta, IRSForm } from './rsform';
import { ConstituentaID, CstClass, CstType, IConstituenta, IRSForm } from './rsform';
import { inferClass } from './rsformAPI';
import { AliasMapping, ParsingStatus } from './rslang';
import { applyAliasMapping, applyTypificationMapping, extractGlobals, isSetTypification } from './rslangAPI';
@ -51,6 +53,7 @@ export function sortItemsForOSS(oss: IOperationSchema, items: ILibraryItem[]): I
type CrossMapping = Map<LibraryItemID, AliasMapping>;
// TODO: test validator
/**
* Validator for Substitution table.
*/
@ -59,6 +62,10 @@ export class SubstitutionValidator {
private schemas: IRSForm[];
private substitutions: ICstSubstitute[];
private constituents = new Set<ConstituentaID>();
private originals = new Set<ConstituentaID>();
private mapping: CrossMapping = new Map();
private cstByID = new Map<ConstituentaID, IConstituenta>();
private schemaByID = new Map<LibraryItemID, IRSForm>();
private schemaByCst = new Map<ConstituentaID, IRSForm>();
@ -66,13 +73,32 @@ export class SubstitutionValidator {
constructor(schemas: IRSForm[], substitutions: ICstSubstitute[]) {
this.schemas = schemas;
this.substitutions = substitutions;
if (this.substitutions.length === 0) {
return;
}
schemas.forEach(schema => {
this.schemaByID.set(schema.id, schema);
this.mapping.set(schema.id, {});
schema.items.forEach(item => {
this.cstByID.set(item.id, item);
this.schemaByCst.set(item.id, schema);
});
});
let index = limits.max_semantic_index;
substitutions.forEach(item => {
this.constituents.add(item.original);
this.constituents.add(item.substitution);
this.originals.add(item.original);
const original = this.cstByID.get(item.original);
const substitution = this.cstByID.get(item.substitution);
if (!original || !substitution) {
return;
}
index++;
const newAlias = `${substitution.alias[0]}${index}`;
this.mapping.get(original.schema)![original.alias] = newAlias;
this.mapping.get(substitution.schema)![substitution.alias] = newAlias;
});
}
public validate(): boolean {
@ -85,7 +111,7 @@ export class SubstitutionValidator {
if (!this.checkCycles()) {
return false;
}
if (!this.checkTypifications()) {
if (!this.checkSubstitutions()) {
return false;
}
@ -204,7 +230,7 @@ export class SubstitutionValidator {
return true;
}
private checkTypifications(): boolean {
private checkSubstitutions(): boolean {
const baseMappings = this.prepareBaseMappings();
const typeMappings = this.calculateSubstituteMappings(baseMappings);
if (typeMappings === null) {
@ -216,6 +242,13 @@ export class SubstitutionValidator {
continue;
}
const substitution = this.cstByID.get(item.substitution)!;
if (original.cst_type === substitution.cst_type && inferClass(original.cst_type) === CstClass.DERIVED) {
if (!this.checkEqual(original, substitution)) {
this.reportError(SubstitutionErrorType.unequalExpressions, [substitution.alias, original.alias]);
// Note: do not interrupt the validation process. Only warn about the problem.
}
}
const originalType = applyTypificationMapping(
applyAliasMapping(original.parse.typification, baseMappings.get(original.schema)!),
typeMappings
@ -310,13 +343,35 @@ export class SubstitutionValidator {
return result;
}
private checkEqual(left: IConstituenta, right: IConstituenta): boolean {
const schema1 = this.schemaByID.get(left.schema)!;
const inputs1 = schema1.graph.at(left.id)!.inputs;
if (inputs1.some(id => !this.constituents.has(id))) {
return false;
}
const schema2 = this.schemaByID.get(right.schema)!;
const inputs2 = schema2.graph.at(right.id)!.inputs;
if (inputs2.some(id => !this.constituents.has(id))) {
return false;
}
const expression1 = applyAliasMapping(left.definition_formal, this.mapping.get(schema1.id)!);
const expression2 = applyAliasMapping(right.definition_formal, this.mapping.get(schema2.id)!);
return expression1.replace(' ', '') === expression2.replace(' ', '');
}
private setValid(): boolean {
this.msg = information.substitutionsCorrect;
if (this.msg.length > 0) {
this.msg += '\n';
}
this.msg += information.substitutionsCorrect;
return true;
}
private reportError(errorType: SubstitutionErrorType, params: string[]): boolean {
this.msg = describeSubstitutionError({
if (this.msg.length > 0) {
this.msg += '\n';
}
this.msg += describeSubstitutionError({
errorType: errorType,
params: params
});

View File

@ -93,7 +93,7 @@ export function inferTemplate(expression: string): boolean {
* - `CstClass.DERIVED` if the CstType is TERM, FUNCTION, or PREDICATE.
* - `CstClass.STATEMENT` if the CstType is AXIOM or THEOREM.
*/
export function inferClass(type: CstType, isTemplate: boolean): CstClass {
export function inferClass(type: CstType, isTemplate: boolean = false): CstClass {
if (isTemplate) {
return CstClass.TEMPLATE;
}

View File

@ -42,7 +42,8 @@ export const PARAMETER = {
* Numeric limitations.
*/
export const limits = {
location_len: 500
location_len: 500,
max_semantic_index: 900
};
/**

View File

@ -824,6 +824,8 @@ export function describeSubstitutionError(error: ISubstitutionErrorDescription):
return `Ошибка ${error.params[0]} -> ${error.params[1]}: количество аргументов не совпадает`;
case SubstitutionErrorType.unequalArgs:
return `Ошибка ${error.params[0]} -> ${error.params[1]}: типизация аргументов не совпадает`;
case SubstitutionErrorType.unequalExpressions:
return `Предупреждение ${error.params[0]} -> ${error.params[1]}: определения понятий не совпадают`;
}
return 'UNKNOWN ERROR';
}