Compare commits
2 commits
3c938749d0
...
44d2876f57
Author | SHA1 | Date | |
---|---|---|---|
44d2876f57 | |||
a5bd38ef01 |
7 changed files with 174 additions and 12 deletions
|
@ -1,17 +1,126 @@
|
||||||
%! Author = tdpeuter
|
%! Author = tdpeuter
|
||||||
%! Date = 27/03/2025
|
%! Date = 27/03/2025
|
||||||
|
|
||||||
% Preamble
|
\documentclass[11pt,a4paper]{article}
|
||||||
\documentclass[11pt]{article}
|
|
||||||
|
|
||||||
% Packages
|
|
||||||
\usepackage{amsmath}
|
\usepackage{amsmath}
|
||||||
|
\usepackage[dutch]{babel} % Nederlands taal
|
||||||
|
\usepackage{enumitem} % Aanpasbare lijsten
|
||||||
|
\usepackage[margin=1in]{geometry} % Sane marges
|
||||||
|
\usepackage{multicol} % Meerdere kolommen
|
||||||
|
|
||||||
|
\title{Ghent Prolog}
|
||||||
|
\author{Tibo De Peuter}
|
||||||
|
\date{\today}
|
||||||
|
|
||||||
% Document
|
% Document
|
||||||
\begin{document}
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
|
||||||
% Lexer op basis van https://craftinginterpreters.com/scanning.html
|
% Lexer op basis van https://craftinginterpreters.com/scanning.html
|
||||||
|
|
||||||
|
\appendix
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
\section{Geïmplementeerde predicaten}\label{sec:predicaten}
|
||||||
|
|
||||||
|
\begin{multicols}{2}
|
||||||
|
\begin{itemize}[label={}]
|
||||||
|
\item \textbf{Analysing and Constructing Terms}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{functor/3}
|
||||||
|
\item \texttt{arg/3}
|
||||||
|
\item \texttt{=..}
|
||||||
|
\item \texttt{numbervars/1}
|
||||||
|
\item \texttt{numbervars/3}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Arithmetic}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{between/3}
|
||||||
|
\item \texttt{succ/2}
|
||||||
|
\item \texttt{plus/3}
|
||||||
|
\item \texttt{=\textbackslash=/2}
|
||||||
|
\item \texttt{=:=/2}
|
||||||
|
\item \texttt{is/2}
|
||||||
|
\item \texttt{-/1}
|
||||||
|
\item \texttt{+/1}
|
||||||
|
\item \texttt{+/2}
|
||||||
|
\item \texttt{*/2}
|
||||||
|
\item \texttt{//2}
|
||||||
|
\item \texttt{inf/0}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Comparison and Unification of Terms}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{=/2}
|
||||||
|
\item \texttt{\textbackslash=/2}
|
||||||
|
\item \texttt{==/2}
|
||||||
|
\item \texttt{\textbackslash==/2}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Control Predicates}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{fail/0}
|
||||||
|
\item \texttt{false/0}
|
||||||
|
\item \texttt{true/0}
|
||||||
|
\item \texttt{!/0}
|
||||||
|
\item \texttt{,/2}
|
||||||
|
\item \texttt{;/2}
|
||||||
|
\item \texttt{|/2}
|
||||||
|
\item \texttt{\textbackslash+/1}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Database}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{retract/1}
|
||||||
|
\item \texttt{retractall/1}
|
||||||
|
\item \texttt{asserta/1}
|
||||||
|
\item \texttt{assertz/1}
|
||||||
|
\item \texttt{assert/1}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Declaring predicate properties}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{dynamic/1}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Delimited continuations}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{reset/3}
|
||||||
|
\item \texttt{shift/1}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Examining the program}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{clause/2}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Forall}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{forall/2}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Loading Prolog source files}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{consult/1}
|
||||||
|
\item \texttt{initialization/1}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Meta-Call Predicates}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{call/1}
|
||||||
|
\item \texttt{once/1}
|
||||||
|
\item \texttt{ignore/1}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Primitive character I/O}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{nl/0}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Term reading and writing}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{write/1}
|
||||||
|
\item \texttt{writeln/1}
|
||||||
|
\item \texttt{read/1}
|
||||||
|
\end{itemize}
|
||||||
|
\item \textbf{Verify Type of a Term}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \texttt{var/1}
|
||||||
|
\item \texttt{nonvar/1}
|
||||||
|
\item \texttt{atom/1}
|
||||||
|
\item \texttt{compound/1}
|
||||||
|
\end{itemize}
|
||||||
|
\end{itemize}
|
||||||
|
\end{multicols}
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
|
@ -107,6 +107,10 @@ open class Preprocessor {
|
||||||
Successor(args[0] as Expression, args[1] as Expression)
|
Successor(args[0] as Expression, args[1] as Expression)
|
||||||
} else term
|
} else term
|
||||||
|
|
||||||
|
Functor.of("plus/3") -> if (args.all { it is Expression }) {
|
||||||
|
Plus(args[0] as Expression, args[1] as Expression, args[2] as Expression)
|
||||||
|
} else term
|
||||||
|
|
||||||
// Control
|
// Control
|
||||||
Functor.of("fail/0") -> Fail
|
Functor.of("fail/0") -> Fail
|
||||||
Functor.of("false/0") -> False
|
Functor.of("false/0") -> False
|
||||||
|
@ -158,12 +162,16 @@ open class Preprocessor {
|
||||||
Functor.of("member/2") -> Member(args[0], args[1])
|
Functor.of("member/2") -> Member(args[0], args[1])
|
||||||
Functor.of("append/3") -> Append(args[0], args[1], args[2])
|
Functor.of("append/3") -> Append(args[0], args[1], args[2])
|
||||||
|
|
||||||
|
// Loading
|
||||||
|
Functor.of("consult/1") -> Consult(args[0])
|
||||||
|
Functor.of("initialization/1") -> Initialization(args[0] as Goal)
|
||||||
|
|
||||||
// Meta
|
// Meta
|
||||||
Functor.of("call/1") -> Call(args[0])
|
Functor.of("call/1") -> Call(args[0])
|
||||||
|
Functor.of("once/1") -> Once(args[0] as Goal)
|
||||||
Functor.of("ignore/1") -> Ignore(args[0] as Goal)
|
Functor.of("ignore/1") -> Ignore(args[0] as Goal)
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
Functor.of("initialization/1") -> Initialization(args[0] as Goal)
|
|
||||||
Functor.of("forall/2") -> ForAll(args[0] as LogicOperand, args[1] as Goal)
|
Functor.of("forall/2") -> ForAll(args[0] as LogicOperand, args[1] as Goal)
|
||||||
|
|
||||||
// Unification
|
// Unification
|
||||||
|
|
|
@ -122,6 +122,11 @@ open class Add(private val expr1: Expression, private val expr2: Expression) :
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Plus(private val expr1: Expression, private val expr2: Expression, private val expr3: Expression) :
|
||||||
|
CompoundTerm("plus", expr1, expr2, expr3) {
|
||||||
|
override fun satisfy(subs: Substitutions): Answers = plus(expr1, expr2, expr3, subs)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Result = Expr1 - Expr2
|
* Result = Expr1 - Expr2
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,7 +3,6 @@ package prolog.builtins
|
||||||
import prolog.Answers
|
import prolog.Answers
|
||||||
import prolog.Substitutions
|
import prolog.Substitutions
|
||||||
import prolog.ast.arithmetic.Integer
|
import prolog.ast.arithmetic.Integer
|
||||||
import prolog.ast.terms.Atom
|
|
||||||
import prolog.ast.terms.Goal
|
import prolog.ast.terms.Goal
|
||||||
import prolog.ast.terms.Structure
|
import prolog.ast.terms.Structure
|
||||||
import prolog.ast.terms.Term
|
import prolog.ast.terms.Term
|
||||||
|
|
39
src/prolog/builtins/loadingSourceOperators.kt
Normal file
39
src/prolog/builtins/loadingSourceOperators.kt
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package prolog.builtins
|
||||||
|
|
||||||
|
import interpreter.FileLoader
|
||||||
|
import prolog.Answers
|
||||||
|
import prolog.Substitutions
|
||||||
|
import prolog.ast.logic.LogicOperand
|
||||||
|
import prolog.ast.logic.LogicOperator
|
||||||
|
import prolog.ast.terms.Atom
|
||||||
|
import prolog.ast.terms.Operator
|
||||||
|
import prolog.ast.terms.Term
|
||||||
|
import prolog.logic.applySubstitution
|
||||||
|
|
||||||
|
class Consult(val file: Term) : Operator("consult", rightOperand = file) {
|
||||||
|
private val fileLoader = FileLoader()
|
||||||
|
|
||||||
|
override fun satisfy(subs: Substitutions): Answers {
|
||||||
|
val fileAtom = applySubstitution(file, subs)
|
||||||
|
require(fileAtom is Atom) { "File name must be an atom" }
|
||||||
|
|
||||||
|
var filePath = fileAtom.name
|
||||||
|
if (!filePath.endsWith(".pl")) {
|
||||||
|
filePath += ".pl"
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
fileLoader.load(filePath)
|
||||||
|
return sequenceOf(Result.success(emptyMap()))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return sequenceOf(Result.failure(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = "consult($file)"
|
||||||
|
}
|
||||||
|
|
||||||
|
class Initialization(val goal: LogicOperand) : LogicOperator(":-", rightOperand = goal) {
|
||||||
|
override fun satisfy(subs: Substitutions): Answers = goal.satisfy(subs).take(1)
|
||||||
|
override fun toString(): String = goal.toString()
|
||||||
|
}
|
|
@ -2,7 +2,6 @@ package prolog.builtins
|
||||||
|
|
||||||
import prolog.Answers
|
import prolog.Answers
|
||||||
import prolog.Substitutions
|
import prolog.Substitutions
|
||||||
import prolog.ast.terms.Atom
|
|
||||||
import prolog.ast.terms.Goal
|
import prolog.ast.terms.Goal
|
||||||
import prolog.ast.terms.Operator
|
import prolog.ast.terms.Operator
|
||||||
import prolog.ast.terms.Term
|
import prolog.ast.terms.Term
|
||||||
|
@ -16,10 +15,18 @@ class Call(private val goal: Term) : Operator("call", rightOperand = goal) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a possibly nondeterministic [Goal] semideterministic, i.e. succeed at most once.
|
||||||
|
*/
|
||||||
|
class Once(private val goal: Term) : Operator("once", rightOperand = goal) {
|
||||||
|
private val conjunction = Conjunction(Call(goal), Cut())
|
||||||
|
override fun satisfy(subs: Substitutions): Answers = conjunction.satisfy(subs).take(1)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls [Goal] once, but succeeds, regardless of whether Goal succeeded or not.
|
* Calls [Goal] once, but succeeds, regardless of whether Goal succeeded or not.
|
||||||
*/
|
*/
|
||||||
class Ignore(goal: Goal) : Operator("ignore", rightOperand = goal) {
|
class Ignore(goal: Term) : Operator("ignore", rightOperand = goal) {
|
||||||
private val disjunction = Disjunction(
|
private val disjunction = Disjunction(
|
||||||
Conjunction(Call(goal), Cut()),
|
Conjunction(Call(goal), Cut()),
|
||||||
True
|
True
|
||||||
|
|
|
@ -6,11 +6,6 @@ import prolog.ast.logic.LogicOperand
|
||||||
import prolog.ast.logic.LogicOperator
|
import prolog.ast.logic.LogicOperator
|
||||||
import prolog.ast.terms.Goal
|
import prolog.ast.terms.Goal
|
||||||
|
|
||||||
class Initialization(val goal: LogicOperand) : LogicOperator(":-", rightOperand = goal) {
|
|
||||||
override fun satisfy(subs: Substitutions): Answers = goal.satisfy(subs).take(1)
|
|
||||||
override fun toString(): String = goal.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
class Query(val query: LogicOperand) : LogicOperator("?-", rightOperand = query) {
|
class Query(val query: LogicOperand) : LogicOperator("?-", rightOperand = query) {
|
||||||
override fun satisfy(subs: Substitutions): Answers = query.satisfy(subs)
|
override fun satisfy(subs: Substitutions): Answers = query.satisfy(subs)
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue