2023-11-06 20:21:30 +03:00
|
|
|
|
// Module: RSLang model API
|
|
|
|
|
|
2023-11-06 22:21:36 +03:00
|
|
|
|
import { applyPattern } from '../utils/utils';
|
2023-11-06 20:21:30 +03:00
|
|
|
|
import { CstType } from './rsform';
|
|
|
|
|
import { IArgumentValue } from './rslang'
|
|
|
|
|
|
2023-11-06 22:21:36 +03:00
|
|
|
|
const LOCALS_REGEXP = /[_a-zα-ω][a-zα-ω]*\d*/g;
|
|
|
|
|
|
2023-11-06 20:21:30 +03:00
|
|
|
|
export function extractGlobals(expression: string): Set<string> {
|
|
|
|
|
return new Set(expression.match(/[XCSADFPT]\d+/g) ?? []);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function inferTemplatedType(templateType: CstType, args: IArgumentValue[]): CstType {
|
|
|
|
|
if (args.length === 0 || args.some(arg => !arg.value)) {
|
|
|
|
|
return templateType;
|
|
|
|
|
} else if (templateType === CstType.PREDICATE) {
|
|
|
|
|
return CstType.AXIOM;
|
|
|
|
|
} else {
|
|
|
|
|
return CstType.TERM;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function splitTemplateDefinition(target: string) {
|
|
|
|
|
let start = 0;
|
|
|
|
|
for (; start < target.length && target[start] !== '['; ++start) ;
|
|
|
|
|
if (start < target.length) {
|
|
|
|
|
for (let counter = 0, end = start + 1; end < target.length; ++end) {
|
|
|
|
|
if (target[end] === '[') {
|
|
|
|
|
++counter;
|
|
|
|
|
} else if (target[end] === ']') {
|
|
|
|
|
if (counter !== 0) {
|
|
|
|
|
--counter;
|
|
|
|
|
} else {
|
2023-11-06 22:21:36 +03:00
|
|
|
|
return {
|
|
|
|
|
head: target.substring(start + 1, end).trim(),
|
|
|
|
|
body: target.substring(end + 1).trim()
|
|
|
|
|
}
|
2023-11-06 20:21:30 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
head: '',
|
|
|
|
|
body: target
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-06 22:21:36 +03:00
|
|
|
|
export function substituteTemplateArgs(expression: string, args: IArgumentValue[]): string {
|
|
|
|
|
if (args.every(arg => !arg.value)) {
|
|
|
|
|
return expression;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const mapping: { [key: string]: string } = {};
|
|
|
|
|
args.filter(arg => !!arg.value).forEach(arg => { mapping[arg.alias] = arg.value!; })
|
|
|
|
|
|
|
|
|
|
let { head, body } = splitTemplateDefinition(expression);
|
|
|
|
|
body = applyPattern(body, mapping, LOCALS_REGEXP);
|
|
|
|
|
const argTexts = head.split(',').map(text => text.trim());
|
|
|
|
|
head = argTexts
|
|
|
|
|
.filter(
|
|
|
|
|
arg => [...arg.matchAll(LOCALS_REGEXP)]
|
|
|
|
|
.every(local => local.every(match => !(match in mapping)))
|
|
|
|
|
).join(', ');
|
|
|
|
|
|
|
|
|
|
console.log(body);
|
|
|
|
|
console.log(head);
|
|
|
|
|
console.log(args);
|
|
|
|
|
console.log(mapping);
|
2023-11-06 20:21:30 +03:00
|
|
|
|
|
2023-11-06 22:21:36 +03:00
|
|
|
|
if (!head) {
|
|
|
|
|
return body;
|
|
|
|
|
} else {
|
|
|
|
|
return `[${head}] ${body}`
|
|
|
|
|
}
|
|
|
|
|
}
|