- swipl
- library
- error.pl -- Error generating support
- apply.pl -- Apply predicates on a list
- lists.pl -- List Manipulation
- debug.pl -- Print debug messages and test assertions
- broadcast.pl -- Event service
- socket.pl -- Network socket (TCP and UDP) library
- predicate_options.pl -- Access and analyse predicate options
- shlib.pl -- Utility library for loading foreign objects (DLLs, shared objects)
- option.pl -- Option list processing
- uid.pl -- User and group management on Unix systems
- unix.pl -- Unix specific operations
- syslog.pl -- Unix syslog interface
- thread_pool.pl -- Resource bounded thread management
- gensym.pl -- Generate unique symbols
- settings.pl -- Setting management
- arithmetic.pl -- Extensible arithmetic
- main.pl -- Provide entry point for scripts
- readutil.pl -- Read utilities
- ssl.pl -- Secure Socket Layer (SSL) library
- crypto.pl -- Cryptography and authentication library
- filesex.pl -- Extended operations on files
- doc_http.pl -- Documentation server
- pldoc.pl -- Process source documentation
- operators.pl -- Manage operators
- pairs.pl -- Operations on key-value lists
- prolog_source.pl -- Examine Prolog source-files
- sgml.pl -- SGML, XML and HTML parser
- quasi_quotations.pl -- Define Quasi Quotation syntax
- uri.pl -- Process URIs
- url.pl -- Analysing and constructing URL
- www_browser.pl -- Open a URL in the users browser
- prolog_colour.pl -- Prolog syntax colouring support.
- record.pl -- Access compound arguments by name
- prolog_xref.pl -- Prolog cross-referencer data collection
- occurs.pl -- Finding and counting sub-terms
- ordsets.pl -- Ordered set manipulation
- assoc.pl -- Binary associations
- ugraphs.pl -- Graph manipulation library
- memfile.pl
- xpath.pl -- Select nodes in an XML DOM
- iostream.pl -- Utilities to deal with streams
- atom.pl -- Operations on atoms
- porter_stem.pl
- solution_sequences.pl -- Modify solution sequences
- prolog_pack.pl -- A package manager for Prolog
- prolog_config.pl -- Provide configuration information
- process.pl -- Create processes and redirect I/O
- git.pl -- Run GIT commands
- ctypes.pl -- Character code classification
- time.pl -- Time and alarm library
- utf8.pl -- UTF-8 encoding/decoding on lists of character codes.
- base64.pl -- Base64 encoding and decoding
- sha.pl -- SHA secure hashes
- crypt.pl
- persistency.pl -- Provide persistent dynamic predicates
- pure_input.pl -- Pure Input from files and streams
- nb_set.pl -- Non-backtrackable sets
- xsdp_types.pl -- XML-Schema primitive types
- uuid.pl -- Universally Unique Identifier (UUID) Library
- pcre.pl -- Perl compatible regular expression matching for SWI-Prolog
- aggregate.pl -- Aggregation operators on backtrackable predicates
- rdf_write.pl -- Write RDF/XML from a list of triples
- rdf.pl -- RDF/XML parser
- sgml_write.pl -- XML/SGML writer module
- archive.pl -- Access several archive formats
- csv.pl -- Process CSV (Comma-Separated Values) data
- dialect.pl -- Support multiple Prolog dialects
- apply_macros.pl -- Goal expansion rules to avoid meta-calling
- prolog_code.pl -- Utilities for reasoning about code
- prolog_stack.pl -- Examine the Prolog stack
- pengines.pl -- Pengines: Web Logic Programming Made Easy
- yall.pl -- Lambda expressions
- random.pl -- Random numbers
- zlib.pl -- Zlib wrapper for SWI-Prolog
- bdb.pl -- Berkeley DB interface
- hash_stream.pl -- Maintain a hash on a stream
- md5.pl -- MD5 hashes
- sandbox.pl -- Sandboxed Prolog code
- prolog_format.pl -- Analyse format specifications
- pprint.pl -- Pretty Print Prolog terms
- lazy_lists.pl -- Lazy list handling
- helpidx.pl
- pengines_io.pl -- Provide Prolog I/O for HTML clients
- edinburgh.pl -- Some traditional Edinburgh predicates
- prolog_clause.pl -- Get detailed source-information about a clause
- prolog_breakpoints.pl -- Manage Prolog break-points
- dicts.pl -- Dict utilities
- dif.pl -- The dif/2 constraint
- thread.pl -- High level thread primitives
- system.pl -- System utilities
- modules.pl -- Module utility predicates
- rbtrees.pl -- Red black trees
- listing.pl -- List programs and pretty print clauses
- optparse.pl -- command line parsing
- strings.pl -- String utilities
- double_metaphone.pl -- Phonetic string matching
- intercept.pl -- Intercept and signal interface
- table.pl
- backcomp.pl -- Backward compatibility
- quintus.pl -- Quintus compatibility
- prolog_debug.pl -- User level debugging tools
- make.pl -- Reload modified source files
- redis.pl -- Redis client
- help.pl -- Text based manual
- c14n2.pl -- C14n2 canonical XML documents
- xmldsig.pl -- XML Digital signature
- xmlenc.pl -- XML encryption library
- files.pl
- redis_streams.pl -- Using Redis streams
- prolog_stream.pl -- A stream with Prolog callbacks
- tty.pl -- Terminal operations
- snowball.pl -- The Snowball multi-lingual stemmer library
- sort.pl
- varnumbers.pl -- Utilities for numbered terms
- portray_text.pl -- Portray text
- heaps.pl -- heaps/priority queues
- terms.pl -- Term manipulation
- when.pl -- Conditional coroutining
- zip.pl -- Access resource ZIP archives
- charsio.pl -- I/O on Lists of Character Codes
- wfs.pl -- Well Founded Semantics interface
- protobufs.pl -- Google's Protocol Buffers ("protobufs")
- edit.pl -- Editor interface
- streampool.pl -- Input multiplexing
- fastrw.pl -- Fast reading and writing of terms
- tables.pl -- XSB interface to tables
- ansi_term.pl -- Print decorated text to ANSI consoles
- test_cover.pl -- Clause coverage analysis
- shell.pl -- Elementary shell commands
- explain.pl -- Describe Prolog Terms
- term_to_json.pl
- language_server.pl
- cgi.pl -- Read CGI parameters
- readline.pl -- GNU readline interface
- statistics.pl -- Get information about resource usage
- streams.pl -- Manage Prolog streams
- plunit.pl -- Unit Testing
- paxos.pl -- A Replicated Data Store
- udp_broadcast.pl -- A UDP broadcast proxy
- doc_latex.pl -- PlDoc LaTeX backend
- threadutil.pl -- Interactive thread utilities
- editline.pl -- BSD libedit based command line editing
- base32.pl -- Base32 encoding and decoding
- codesio.pl -- I/O on Lists of Character Codes
- coinduction.pl -- Co-Logic Programming
- date.pl -- Process dates and times
- unicode.pl -- Unicode string handling
- yaml.pl -- Process YAML data
- check.pl -- Consistency checking
- prolog_codewalk.pl -- Prolog code walker
- prolog_autoload.pl -- Autoload all dependencies
- isub.pl -- isub: a string similarity measure
- prolog_wrap.pl -- Wrapping predicates
- prolog_trace.pl -- Print access to predicates
- qsave.pl -- Save current program as a state or executable
- prolog_metainference.pl -- Infer meta-predicate properties
- prolog_history.pl -- Per-directory persistent commandline history
- writef.pl -- Old-style formatted write
- mqi.pl
- rewrite_term.pl
- odbc.pl
- prolog_jiti.pl -- Just In Time Indexing (JITI) utilities
- rlimit.pl
- rdf_triple.pl -- Create triples from intermediate representation
- rdf_parser.pl
- hashtable.pl -- Hash tables
- stomp.pl -- STOMP client.
- increval.pl -- Incremental dynamic predicate modification
- pwp.pl -- Prolog Well-formed Pages
- doc_files.pl -- Create stand-alone documentation files
- oset.pl -- Ordered set manipulation
- library
- language_server(+Options:list) is semidet
- Starts a Prolog language server using Options. The server is normally started automatically by a library built for a particular programming language such as the
swiplserver
Python library, but starting manually can be useful when debugging Prolog code in some scenarios. See the documentation on "Standalone Mode" for more information.Once started, the server listens for TCP/IP or Unix Domain Socket connections and authenticates them using the password provided before processing any messages. The messages processed by the server are described below.
For debugging, the server outputs traces using the debug/3 predicate so that the server operation can be observed by using the debug/1 predicate. Run the following commands to see them:
debug(language_server(protocol))
: Traces protocol messages to show the flow of commands and connections. It is designed to avoid filling the screen with large queries and results to make it easier to read.debug(language_server(query))
: Traces messages that involve each query and its results. Therefore it can be quite verbose depending on the query.
Options
Options is a list containing any combination of the following options. When used in the Prolog top level (i.e. in Standalone Mode), these are specified as normal Prolog options like this:
language_server([unix_domain_socket(Socket), password('a password')])
When using "Embedded Mode" they are passed using the same name but as normal command line arguments like this:
swipl --quiet -g language_server -t halt -- --write_connection_values=true --password="a password" --create_unix_domain_socket=true
Note the use of quotes around values that could confuse command line processing like spaces (e.g. "a password") and that
unix_domain_socket(Variable)
is written as--create_unix_domain_socket=true
on the command line. See below for more information.- port(?Port)
- The TCP/IP port to bind to on localhost. This option is ignored if the unix_domain_socket/1 option is set. Port is either a legal TCP/IP port number (integer) or a variable term like Port. If it is a variable, it causes the system to select a free port and unify the variable with the selected port as in tcp_bind/2. If the option
write_connection_values(true)
is set, the selected port is output to STDOUT followed by\n
on startup to allow the client language library to retrieve it in "Embedded Mode". - unix_domain_socket(?Unix_Domain_Socket_Path_And_File)
- If set, Unix Domain Sockets will be used as the way to communicate with the server. Unix_Domain_Socket_Path_And_File specifies the fully qualified path and filename to use for the socket.
To have one generated instead (recommended), pass Unix_Domain_Socket_Path_And_File as a variable when calling from the Prolog top level and the variable will be unified with a created filename. If launching in "Embedded Mode", instead pass
--create_unix_domain_socket=true
since there isn't a way to specify variables from the command line. When generating the file, a temporary directory will be created using tmp_file/2 and a socket file will be created within that directory following the below requirements. If the directory and file are unable to be created for some reason, language_server/1 fails.Regardless of whether the file is specified or generated, if the option
write_connection_values(true)
is set, the fully qualified path to the generated file is output to STDOUT followed by\n
on startup to allow the client language library to retrieve it.Specifying a file to use should follow the same guidelines as the generated file:
- If the file exists when the server is launched, it will be deleted.
- The Prolog process will attempt to create and, if Prolog exits cleanly, delete this file (and directory if it was created) when the server closes. This means the directory from a specified file must have the appropriate permissions to allow the Prolog process to do so.
- For security reasons, the filename should not be predictable and the directory it is contained in should have permissions set so that files created are only accessible to the current user.
- The path must be below 92 bytes long (including null terminator) to be portable according to the Linux documentation.
- password(?Password)
- The password required for a connection. If not specified (recommended), the server will generate one as a Prolog string type since Prolog atoms are globally visible (be sure not to convert to an atom for this reason). If Password is a variable it will be unified with the created password. Regardless of whether the password is specified or generated, if the option
write_connection_values(true)
is set, the password is output to STDOUT followed by\n
on startup to allow the client language library to retrieve it. This is the recommended way to integrate the server with a language as it avoids including the password as source code. This option is only included so that a known password can be supplied for when the server is running in Standalone Mode. - query_timeout(+Seconds)
- Sets the default time in seconds that a query is allowed to run before it is cancelled. This can be overridden on a query by query basis. If not set, the default is no timeout (
-1
). - pending_connections(+Count)
- Sets the number of pending connections allowed for the server as in tcp_listen/2. If not provided, the default is
5
. - run_server_on_thread(+Run_Server_On_Thread)
- Determines whether language_server/1 runs in the background on its own thread or blocks until the server shuts down. Must be missing or set to
true
when running in "Embedded Mode" so that the SWI Prolog process can exit properly. If not set, the default istrue
. - server_thread(?Server_Thread)
- Specifies or retrieves the name of the thread the server will run on if
run_server_on_thread(true)
. Passing in an atom for Server_Thread will only set the server thread name ifrun_server_on_thread(true)
. If Server_Thread is a variable, it is unified with a generated name. - write_connection_values(+Write_Connection_Values)
- Determines whether the server writes the port (or generated Unix Domain Socket) and password to STDOUT as it initializes. Used by language libraries to retrieve this information for connecting. If not set, the default is
false
. - write_output_to_file(+File)
- Redirects STDOUT and STDERR to the file path specified. Useful for debugging the server when it is being used in "Embedded Mode". If using multiple servers in one SWI Prolog instance, only set this on the first one. Each time it is set the output will be redirected.
Language Server Messages
The messages the server responds to are described below. A few things are true for all of them:
- Every connection is in its own separate thread. Opening more than one connection means the code is running concurrently.
- Closing the socket without sending
close
and waiting for a response will halt the process if running in "Embedded Mode". This is so that stopping a debugger doesn't leave the process orphaned. - All messages are request/response messages. After sending, there will be exactly one response from the server.
- Timeout in all of the commands is in seconds. Sending a variable (e.g. _) will use the default timeout passed to the initial language_server/1 predicate and
-1
means no timeout. - All queries are run in the default module context of
user
. module/1 has no effect.
Language Server Message Format
Every language server message is a single valid Prolog term. Those that run queries have an argument which represents the query as a single term. To run several goals at once use
(goal1, goal2, ...)
as the goal term.The format of sent and received messages is identical (
\n
stands for the ASCII newline character which is a single byte):<stringByteLength>.\n<stringBytes>.\n.
For example, to send
hello
as a message you would send this:7.\nhello.\n
<stringByteLength>
is the number of bytes of the string to follow (including the.\n
), in human readable numbers, such as15
for a 15 byte string. It must be followed by.\n
.<stringBytes>
is the actual message string being sent, such asrun(atom(a), -1).\n
. It must always end with.\n
. The character encoding used to decode and encode the string is UTF-8.
To send a message to the server, send a message using the message format above to the localhost port or Unix Domain Socket that the server is listening on. For example, to run the synchronous goal
atom(a)
, send the following message:18.\nrun(atom(a), -1).\n<end of stream>
You will receive the response below on the receive stream of the same connection you sent on. Note that the answer is in JSON format. If a message takes longer than 2 seconds, there will be "heartbeat" characters (".") at the beginning of the response message, approximately 1 every 2 seconds. So, if the query takes 6 seconds for some reason, there will be three "." characters first:
...12\ntrue([[]]).\n
Language Server Messages Reference
The full list of language server messages are described below:
- run(Goal, Timeout)
- Runs Goal on the connection's designated query thread. Stops accepting new commands until the query is finished and it has responded with the results. If a previous query is still in progress, waits until the previous query finishes (discarding that query's results) before beginning the new query.
Timeout is in seconds and indicates a timeout for generating all results for the query. Sending a variable (e.g. _) will use the default timeout passed to the initial language_server/1 predicate and
-1
means no timeout.While it is waiting for the query to complete, sends a "." character not in message format, just as a single character, once every two seconds to proactively ensure that the client is alive. Those should be read and discarded by the client.
If a communication failure happens (during a heartbeat or otherwise), the connection is terminated, the query is aborted and (if running in "Embedded Mode") the SWI Prolog process shuts down.
When completed, sends a response message using the normal message format indicating the result.
Response:
true([Answer1, Answer2, ... ])
The goal succeeded at least once. The response always includes all answers as if run with findall()
(see run_async/3 below to get individual results back iteratively). Each Answer is a list of the assignments of free variables in the answer. If there are no free variables, Answer is an empty list.false
The goal failed. exception(time_limit_exceeded)
The query timed out. exception(Exception)
An arbitrary exception was not caught while running the goal. exception(connection_failed)
The query thread unexpectedly exited. The server will no longer be listening after this exception. - run_async(Goal, Timeout, Find_All)
- Starts a Prolog query specified by Goal on the connection's designated query thread. Answers to the query, including exceptions, are retrieved afterwards by sending the
async_result
message (described below). The query can be cancelled by sending thecancel_async
message. If a previous query is still in progress, waits until that query finishes (discarding that query's results) before responding.Timeout is in seconds and indicates a timeout for generating all results for the query. Sending a variable (e.g. _) will use the default timeout passed to the initial language_server/1 predicate and
-1
means no timeout.If the socket closes before a response is sent, the connection is terminated, the query is aborted and (if running in "Embedded Mode") the SWI Prolog process shuts down.
If it needs to wait for the previous query to complete, it will send heartbeat messages (see "Language Server Message Format") while it waits. After it responds, however, it does not send more heartbeats. This is so that it can begin accepting new commands immediately after responding so the client.
Find_All == true
means generate one response to anasync_result
message with all of the answers to the query (as in therun
message above).Find_All == false
generates a single response to anasync_result
message per answer.Response:
true([[]])
The goal was successfully parsed. exception(Exception)
An error occurred parsing the goal. exception(connection_failed)
The goal thread unexpectedly shut down. The server will no longer be listening after this exception. - cancel_async
- Attempt to cancel a query started by the
run_async
message in a way that allows further queries to be run on this Prolog thread afterwards.If there is a goal running, injects a
throw(cancel_goal)
into the executing goal to attempt to stop the goal's execution. Begins accepting new commands immediately after responding. Does not inject abort/0 because this would kill the connection's designated thread and the system is designed to maintain thread local data for the client. This does mean it is a "best effort" cancel since the exception can be caught.cancel_async
is guaranteed to either respond with an exception (if there is no query or pending results from the last query), or safely attempt to stop the last executed query even if it has already finished.To guarantee that a query is cancelled, send
close
and close the socket.It is not necessary to determine the outcome of
cancel_async
after sending it and receiving a response. Further queries can be immediately run. They will start after the current query stops.However, if you do need to determine the outcome or determine when the query stops, send
async_result
. UsingTimeout = 0
is recommended since the query might have caught the exception or still be running. Sendingasync_result
will find out the "natural" result of the goal's execution. The "natural" result depends on the particulars of what the code actually did. The response could be:exception(cancel_goal)
The query was running and did not catch the exception. I.e. the goal was successfully cancelled. exception(time_limit_exceeded)
The query timed out before getting cancelled. exception(Exception)
They query hits another exception before it has a chance to be cancelled. A valid answer The query finished before being cancelled. Note that you will need to continue sending
async_result
until you receive anexception(Exception)
message if you want to be sure the query is finished (see documentation forasync_result
).Response:
true([[]])
There is a query running or there are pending results for the last query. exception(no_query)
There is no query or pending results from a query to cancel. exception(connection_failed)
The connection has been unexpectedly shut down. The server will no longer be listening after this exception. - async_result(Timeout)
- Get results from a query that was started via a
run_async
message. Used to get results for all cases: if the query terminates normally, is cancelled by sending acancel_async
message, or times out.Each response to an
async_result
message responds with one result and, when there are no more results, responds withexception(no_more_results)
or whatever exception stopped the query. Receiving anyexception
response exceptexception(result_not_available)
means there are no more results. Ifrun_async
was run withFind_All == false
, multipleasync_result
messages may be required before receiving the final exception.Waits Timeout seconds for a result.
Timeout == -1
or sending a variable for Timeout indicates no timeout. If the timeout is exceeded and no results are ready, sendsexception(result_not_available)
.Some examples:
If the query succeeds with N answers... async_result
messages 1 to N will receive each answer, in order, andasync_result
message N+1 will receiveexception(no_more_results)
If the query fails (i.e. has no answers)... async_result
message 1 will receivefalse
andasync_result
message 2 will receiveexception(no_more_results)
If the query times out after one answer... async_result
message 1 will receive the first answer andasync_result
message 2 will receiveexception(time_limit_exceeded)
If the query is cancelled after it had a chance to get 3 answers... async_result
messages 1 to 3 will receive each answer, in order, andasync_result
message 4 will receiveexception(cancel_goal)
If the query throws an exception before returning any results... async_result
message 1 will receiveexception(Exception)
Note that, after sending
cancel_async
, callingasync_result
will return the "natural" result of the goal's execution. The "natural" result depends on the particulars of what the code actually did since this is multi-threaded and there are race conditions. This is described more below in the response section and above incancel_async
.Response:
true([Answer1, Answer2, ... ])
The next answer from the query is a successful answer. Whether there are more than one Answer in the response depends on the findall
setting. Each Answer is a list of the assignments of free variables in the answer. If there are no free variables, Answer is an empty list.false
The query failed with no answers. exception(no_query)
There is no query in progress. exception(result_not_available)
There is a running query and no results were available in Timeout seconds. exception(no_more_results)
There are no more answers and no other exception occurred. exception(cancel_goal)
The next answer is an exception caused by cancel_async
. Indicates no more answers.exception(time_limit_exceeded)
The query timed out generating the next answer (possibly in a race condition before getting cancelled). Indicates no more answers. exception(Exception)
The next answer is an arbitrary exception. This can happen after cancel_async
if thecancel_async
exception is caught or the code hits another exception first. Indicates no more answers.exception(connection_failed)
The goal thread unexpectedly exited. The server will no longer be listening after this exception. - close
- Closes a connection cleanly, indicating that the subsequent socket close is not a connection failure. Thus it doesn't shutdown the server in "Embedded Mode". The response must be processed by the client before closing the socket or it will be interpreted as a connection failure.
Any asynchronous query that is still running will be halted by using abort/0 in the connection's query thread.
Response:
true([[]])
- quit
- Stops the server and ends the SWI Prolog process. This allows client language libraries to ask for an orderly shutdown of the Prolog process.
Response:
true([[]])