5. Если после своего выполнения условие вернуло значение False, то запускается механизм обратного прохода. Уничтожается последний элемент TSubStackNode, и программа возвращается к предыдущему условию и пытается найти новое решение для него.
6. Если все условия были выполнены, то формируются выходные параметры и функция возвращает истину. В противном случае, программа возвращается к пункту 1 и пытается найти еще одно предложение, соответствующее входным данным.
7. Если были исчерпаны все предложения и ни для одно не было найдено решения, то необходимо возвратить False.
Обращение к базе данных происходит с помощью SQL-запросов.
При первом обращении к базе данных создается объект SQL-запроса и сам запрос.
Формат SQL-запроса
SELECT <поле1>,…,<полеN>
FROM <имя базы данных>
WHERE
<поле1>=<значение1> and
<поле2>=<значение2> and
…
<полеN>=<значениеN>
В запросе используются только условия-равенства, так как в Прологе при сопоставлении значении на входе в предикат используется только сравнение.
В список условий помещаются только те поля, значения которых на входе определены.
При первом обращении к базе берется первая запись из запроса.
При последующих вызовах базы данных (в случае обратного пути в бэктрекинге) объект SQL-запроса не создается, а используется ранее созданный, и применяется функция Next для доступа к следующей записи.
Таким образом, доступ к базе данных осуществляется как обычным предикатам, которые состоят только из предложений-фактов.
На основе построенного при компиляции дерева арифметического выражения достаточно несложно, используя рекурсию, вычислить выражение.
На вход функции поступает объект с деревом арифметического выражения и объект со списком переменных, созданных ранее программой.
Программа смотрит, если в корне дерева находится арифметическая операция, то рекурсивно вызывается функция вычисления выражений для левой и правой частей выражения, которые в свою очередь являются деревьями арифметического выражения.
Дерево может состоять из одного элемента, если это константа или переменная. На этом шаге рекурсия заканчивается и возвращается значение константы или переменной (если до этого в списке переменных ее не значилось, то создается новая переменная).
Для преставления переменных всех типов (целые, дробные, строки, логические, списки, структуры) служит класс TPrologVariable. Для определения типа переменной служит поле iType. В поле Data хранится указатель на данные, соответствующие типу. Для простых типов (целые, дробные, строки, логические) – это указатель на соответствующий тип. Конструктор создает переменную без типа. Деструктор автоматически освобождает память для переменной любого типа. Для этого класса опеределены следующие методы:
1. procedure CreateVariable(DomainType:string; vName:string) - создание переменной типа DomainType с именем vName;
2. procedure DestroyVariable - уничтожение переменной (эта процедура не является деструктором, так как не уничтожает сам объект, а только освобождает память)
3. function CreateCopy:TPrologVariable - создание точной копии переменной;
4. procedure AssignVariable (v:TPrologVariable) - присваивание значения переменной.
Для представления списков введен класс TPrologVariableList, в котором хранится имя типа списка, имя типа элемента списка, тип представления списка (в виде перечисления элементов или «голова-хвост»), а также динамический массив, содержащий объекты TPrologVariable, являющиеся элементами списка.
В структурах (TPrologVariableStruct) аналогично хранится имя типа структуры, массив с типами элементов структуры и динамический массив с элементами структуры.
Следует отметить, что в классе TPrologVariable, могут храниться как переменные, так и константы. У константы поле Name - пустая строка.
Класс TPrologVariables позволяет организовать к пакету переменных:
1. procedure AddVariable(v:TPrologVariable) - добавление переменной в список переменных;
2. function AddNewVariable:TPrologVariable - создание и добавление новой переменной в список;
3. procedure DeleteVariable(n:integer) procedure DeleteVariable(vName:string) procedure DeleteLastVariable - удаление переменной по ее индексу или по имени, либо последнюю переменную в списке;
4. function VariableByName(vName:string):TPrologVariable - доступ к конкретной переменной по ее имени;
5. property Variables[ind:integer]:TPrologVariable - свойство, оргназиующее доступ к переменным как к массиву переменных.
Все стандартные функции и предикаты имеют одинаковые параметры.
Объявление функции выглядит следующим образом:
TStdFunction=function (Args:TPrologVariables):TPrologVariable;
Args – пакет с входными параметрами.
Функция возвращает значение в виде переменной TPrologVariable.
Объявление функции, выполняющая работу предиката:
TStdPredicate=function (VarPacket:TPrologVariables; BackTracking:Boolean):Boolean;
VarPacket – пакет с параметрами к предикату
BackTracking – логическая переменная, которая установлена в True, если предикат был вызван на обратном пути алгоритма бэктрекинга.
Функция возвращает логическое значение, которое должен возвратить предикат после своего выполнения.
Для хранения откомпилированной Пролог-программы используются три класса TPrologTerm, TPredicateClause и TProgramPredicate.
TPrologTerm служит для хранения одного условия внутри предложения. В нем хранится тип условия (выражение, предикат, база данных), позиция условия в тексте Пролог-программы, а также указатель (Data) на объект представляющий данное условие (TSubTermPredicate, TSubTermExtData, TSubTermExpression).
TSubTermPredicate служит для хранения условий-предикатов. В данном классе есть следующие поля:
1. Name :String - имя предиката;
2. StandardPredicate :Boolean - True - если предикат стандартный;
3. Params :TVariablesArray - параметры для вызова предиката;
4. NoInverse :Boolean - признак наличия или отсутствия инверсии перед вызовом предиката.
TSubTermExtData аналогичен классу TSubTermPredicate за исключением того, что в нем нет поля StandardPredicate.
TSubTermExtData предназначен для представления арифметических выражений. Он представляет собой рекурсивный объект с полями LeftHand и RightHand для представления выражений левой и правой частей выражения. Данный класс содержит следующие поля:
1. Operation :TExpressionOperation - тип операции;
2. FuncName :String - имя функции, если Operation=eoFunction;
3. Operand :TPrologVariable - переменная или константа, если Operation=eoVariable;
4. LeftHand :TSubTermExpression - левая часть выражения;
5. RightHand :TSubTermExpression - правая часть выражения
6. FuncParams :array of TSubTermExpression - параметры функции, если Operation=eoFunction.
TPredicateClause хранит в себе одно предложение. Параметры предложения хранятся в массиве Params, а условия - в Terms.
TProgramPredicate хранит полную информацию о предикате. Объект этого класса используется как на этапе компиляции, так и на этапе интерпретации. Он хранит имя предиката (Name), типы параметров, текст предиката, все лексемы предиката, а также массив с предложениями предиката.
Класс TPrologProgram хранит всю информацию о Пролог-программе:
· Описания типов (Domains);
· Описания баз данных (ExtData);
· Предикаты (TProgramPredicate);
· Массив со стеком (Stack);
· Массив с контрольными точками (BreakPoints);
· Имя запускаемого предиката (StartPredicate);
· Флаг работы программы (OnTheRun).
Модуль CompileUnit. В данном модуле определяется класс пролог-программы - TPrologProgram, а также два класса, использующихся при запуске интерпретатора: TStackNode и TSubStackNode. Модуль CompileUnit является ядром интерпретатора.
Модуль ProgramClasses. В данном модуле описываются основные классы, использующиеся в объектах TPrologProgram, TStackNode и TSubStackNode как контейнерные:
– TLexemRecord - представляет одну лексему, выделенную из текста программы;
– TPrologVariable - представляет переменную во время выполнения пролог-программы.
– TPrologVariableList - контейнерный класс, использующийся в TPrologVariable, для представления списков;
– TPrologVariableStruct - контейнерный класс, использующийся в классе TPrologVariable, для представления структур;
– TPrologVariables - класс, представляющий собой список переменных TPrologVariable с возможностью доступа к переменной по имени;
– TSubTermPredicate - класс использующийся в TPrologTerm для представления обычного предикатного условия в предложении;
– TSubTermExtData - класс использующийся в TPrologTerm для представления предикатного условия вызова базы данных в предложении;
– TSubTermExpression - класс использующийся в TPrologTerm для представления арифметических выражений в предложении;
– TPrologTerm - класс использует TSubTermPredicate, TSubTermExtData, TSubTermExpression как контейнерные для представления одного условия в предложении;
– TPredicateClause - использует массив объекстов TPrologTerm и TPrologVariable для представления одного предложения в программе;
– TProgramDomain - класс использующийся в TPrologProgram как контейнерный для описания типов;
– TProgramExtData - класс использующийся в TPrologProgram как контейнерный для описания баз данных;
– TProgramPredicate - класс использующийся в TPrologProgram как контейнерный для описания предикатов;
– TPrologFile - класс использующийся в TPrologProgram как контейнерный для описания файлов открытых во время выполнения программы;
Модуль PrologRunTime описывает класс ошибок TRunTimeError, а также все функции и встроенные предикаты Пролога.
MainFormUnit - модуль описания главной формы TMainForm;
ProgFormUnit - модуль описания окна инспектора TProgForm;
DomConstrFormUnit - модуль описания конструктора типов TExtDataForm;
ExtDataFormUnit - модуль описания конструктора баз данных TExtDataForm;