Merge branch 'majestic' of github.com:GrammaticalFramework/gf-core into majestic

This commit is contained in:
John J. Camilleri
2021-09-22 15:14:49 +02:00
22 changed files with 183 additions and 159 deletions

View File

@@ -1,14 +0,0 @@
sudo: required
language: c
services:
- docker
before_install:
- docker pull odanoburu/gf-src:3.9
script:
- |
docker run --mount src="$(pwd)",target=/home/gfer,type=bind odanoburu/gf-src:3.9 /bin/bash -c "cd /home/gfer/src/runtime/c &&
autoreconf -i && ./configure && make && make install ; cd /home/gfer ; cabal install -fserver -fc-runtime --extra-lib-dirs='/usr/local/lib'"

11
CHANGELOG.md Normal file
View File

@@ -0,0 +1,11 @@
### New since 3.11 (WIP)
- Added a changelog!
### 3.11
See <https://www.grammaticalframework.org/download/release-3.11.html>
### 3.10
See <https://www.grammaticalframework.org/download/release-3.10.html>

View File

@@ -65,6 +65,6 @@ bintar:
# Make a source tar.gz distribution using git to make sure that everything is included. # Make a source tar.gz distribution using git to make sure that everything is included.
# We put the distribution in dist/ so it is removed on `make clean` # We put the distribution in dist/ so it is removed on `make clean`
sdist: # sdist:
test -d dist || mkdir dist # test -d dist || mkdir dist
git archive --format=tar.gz --output=dist/gf-${VERSION}.tar.gz HEAD # git archive --format=tar.gz --output=dist/gf-${VERSION}.tar.gz HEAD

View File

@@ -1,4 +1,4 @@
![GF Logo](doc/Logos/gf1.svg) ![GF Logo](https://www.grammaticalframework.org/doc/Logos/gf1.svg)
# Grammatical Framework (GF) # Grammatical Framework (GF)
@@ -39,7 +39,7 @@ or:
stack install stack install
``` ```
For more information, including links to precompiled binaries, see the [download page](http://www.grammaticalframework.org/download/index.html). For more information, including links to precompiled binaries, see the [download page](https://www.grammaticalframework.org/download/index.html).
## About this repository ## About this repository

View File

@@ -47,11 +47,14 @@ but the generated _artifacts_ must be manually attached to the release as _asset
In order to do this you will need to be added the [GF maintainers](https://hackage.haskell.org/package/gf/maintainers/) on Hackage. In order to do this you will need to be added the [GF maintainers](https://hackage.haskell.org/package/gf/maintainers/) on Hackage.
1. Run `make sdist` 1. Run `stack sdist --test-tarball` and address any issues.
2. Upload the package, either: 2. Upload the package, either:
1. **Manually**: visit <https://hackage.haskell.org/upload> and upload the file `dist/gf-X.Y.tar.gz` 1. **Manually**: visit <https://hackage.haskell.org/upload> and upload the file generated by the previous command.
2. **via Cabal (≥2.4)**: `cabal upload dist/gf-X.Y.tar.gz` 2. **via Stack**: `stack upload . --candidate`
3. If the documentation-building fails on the Hackage server, do: 3. After testing the candidate, publish it:
1. **Manually**: visit <https://hackage.haskell.org/package/gf-X.Y.Z/candidate/publish>
1. **via Stack**: `stack upload .`
4. If the documentation-building fails on the Hackage server, do:
``` ```
cabal v2-haddock --builddir=dist/docs --haddock-for-hackage --enable-doc cabal v2-haddock --builddir=dist/docs --haddock-for-hackage --enable-doc
cabal upload --documentation dist/docs/*-docs.tar.gz cabal upload --documentation dist/docs/*-docs.tar.gz

View File

@@ -7,7 +7,6 @@ title: "Grammatical Framework: Authors and Acknowledgements"
The current maintainers of GF are The current maintainers of GF are
[Krasimir Angelov](http://www.chalmers.se/cse/EN/organization/divisions/computing-science/people/angelov-krasimir), [Krasimir Angelov](http://www.chalmers.se/cse/EN/organization/divisions/computing-science/people/angelov-krasimir),
[Thomas Hallgren](http://www.cse.chalmers.se/~hallgren/),
[Aarne Ranta](http://www.cse.chalmers.se/~aarne/), [Aarne Ranta](http://www.cse.chalmers.se/~aarne/),
[John J. Camilleri](http://johnjcamilleri.com), and [John J. Camilleri](http://johnjcamilleri.com), and
[Inari Listenmaa](https://inariksit.github.io/). [Inari Listenmaa](https://inariksit.github.io/).
@@ -22,6 +21,7 @@ and
The following people have contributed code to some of the versions: The following people have contributed code to some of the versions:
- [Thomas Hallgren](http://www.cse.chalmers.se/~hallgren/) (University of Gothenburg)
- Grégoire Détrez (University of Gothenburg) - Grégoire Détrez (University of Gothenburg)
- Ramona Enache (University of Gothenburg) - Ramona Enache (University of Gothenburg)
- [Björn Bringert](http://www.cse.chalmers.se/alumni/bringert) (University of Gothenburg) - [Björn Bringert](http://www.cse.chalmers.se/alumni/bringert) (University of Gothenburg)

View File

@@ -53,26 +53,39 @@ You will probably need to update the `PATH` environment variable to include your
For more information, see [Using GF on Windows](https://www.grammaticalframework.org/~inari/gf-windows.html) (latest updated for Windows 10). For more information, see [Using GF on Windows](https://www.grammaticalframework.org/~inari/gf-windows.html) (latest updated for Windows 10).
<!--## Installing the latest Hackage release (macOS, Linux, and WSL2 on Windows) ## Installing from Hackage
_Instructions applicable for macOS, Linux, and WSL2 on Windows._
[GF is on Hackage](http://hackage.haskell.org/package/gf), so under [GF is on Hackage](http://hackage.haskell.org/package/gf), so under
normal circumstances the procedure is fairly simple: normal circumstances the procedure is fairly simple:
1. Install ghcup https://www.haskell.org/ghcup/ ```
2. `ghcup install ghc 8.10.4` cabal update
3. `ghcup set ghc 8.10.4` cabal install gf-3.11
4. `cabal update` ```
5. On Linux: install some C libraries from your Linux distribution (see note below)
6. `cabal install gf-3.11`
You can also download the source code release from [GitHub](https://github.com/GrammaticalFramework/gf-core/releases),
and follow the instructions below under **Installing from the latest developer source code**.
### Notes ### Notes
**GHC version**
The GF source code is known to be compilable with GHC versions 7.10 through to 8.10.
**Obtaining Haskell**
There are various ways of obtaining Haskell, including:
- ghcup
1. Install from https://www.haskell.org/ghcup/
2. `ghcup install ghc 8.10.4`
3. `ghcup set ghc 8.10.4`
- Haskell Platform https://www.haskell.org/platform/
- Stack https://haskellstack.org/
**Installation location** **Installation location**
The above steps installs GF for a single user. The above steps install GF for a single user.
The executables are put in `$HOME/.cabal/bin` (or on macOS in `$HOME/Library/Haskell/bin`), The executables are put in `$HOME/.cabal/bin` (or on macOS in `$HOME/Library/Haskell/bin`),
so you might want to add this directory to your path (in `.bash_profile` or similar): so you might want to add this directory to your path (in `.bash_profile` or similar):
@@ -84,32 +97,34 @@ PATH=$HOME/.cabal/bin:$PATH
GF uses [`haskeline`](http://hackage.haskell.org/package/haskeline), which GF uses [`haskeline`](http://hackage.haskell.org/package/haskeline), which
on Linux depends on some non-Haskell libraries that won't be installed on Linux depends on some non-Haskell libraries that won't be installed
automatically by cabal, and therefore need to be installed manually. automatically by Cabal, and therefore need to be installed manually.
Here is one way to do this: Here is one way to do this:
- On Ubuntu: `sudo apt-get install libghc-haskeline-dev` - On Ubuntu: `sudo apt-get install libghc-haskeline-dev`
- On Fedora: `sudo dnf install ghc-haskeline-devel` - On Fedora: `sudo dnf install ghc-haskeline-devel`
**GHC version** ## Installing from source code
The GF source code has been updated to compile with GHC versions 7.10 through to 8.8. **Obtaining**
-->
## Installing from the latest developer source code
If you haven't already, clone the repository with: To obtain the source code for the **release**,
download it from [GitHub](https://github.com/GrammaticalFramework/gf-core/releases).
Alternatively, to obtain the **latest version** of the source code:
1. If you haven't already, clone the repository with:
``` ```
git clone https://github.com/GrammaticalFramework/gf-core.git git clone https://github.com/GrammaticalFramework/gf-core.git
``` ```
2. If you've already cloned the repository previously, update with:
If you've already cloned the repository previously, update with:
``` ```
git pull git pull
``` ```
Then install with:
**Installing**
You can then install with:
``` ```
cabal install cabal install
``` ```

View File

@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.2/css/all.css" integrity="sha384-/rXc/GQVaYpyDdyxK+ecHPVYJSN9bmVFBvjA/9eOB+pb3F2w2N6fc5qB9Ew5yIns" crossorigin="anonymous"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" crossorigin="anonymous">
<link rel="alternate" href="https://github.com/GrammaticalFramework/gf-core/" title="GF GitHub repository"> <link rel="alternate" href="https://github.com/GrammaticalFramework/gf-core/" title="GF GitHub repository">
</head> </head>
@@ -85,10 +85,27 @@
<div class="col-sm-6 col-md-3 mb-4"> <div class="col-sm-6 col-md-3 mb-4">
<h3>Contribute</h3> <h3>Contribute</h3>
<ul class="mb-2"> <ul class="mb-2">
<li><a href="http://groups.google.com/group/gf-dev">Mailing List</a></li> <li>
<a href="https://web.libera.chat/?channels=#gf">
<i class="fas fa-hashtag"></i>
IRC
</a>
/
<a href="https://discord.gg/EvfUsjzmaz">
<i class="fab fa-discord"></i>
Discord
</a>
</li>
<li>
<a href="https://stackoverflow.com/questions/tagged/gf">
<i class="fab fa-stack-overflow"></i>
Stack Overflow
</a>
</li>
<li><a href="https://groups.google.com/group/gf-dev">Mailing List</a></li>
<li><a href="https://github.com/GrammaticalFramework/gf-core/issues">Issue Tracker</a></li> <li><a href="https://github.com/GrammaticalFramework/gf-core/issues">Issue Tracker</a></li>
<li><a href="doc/gf-people.html">Authors</a></li>
<li><a href="//school.grammaticalframework.org/2020/">Summer School</a></li> <li><a href="//school.grammaticalframework.org/2020/">Summer School</a></li>
<li><a href="doc/gf-people.html">Authors</a></li>
</ul> </ul>
<a href="https://github.com/GrammaticalFramework/" class="btn btn-primary ml-3"> <a href="https://github.com/GrammaticalFramework/" class="btn btn-primary ml-3">
<i class="fab fa-github mr-1"></i> <i class="fab fa-github mr-1"></i>
@@ -154,7 +171,7 @@ least one, it may help you to get a first idea of what GF is.
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<h2>Applications & Availability</h2> <h2>Applications & availability</h2>
<p> <p>
GF can be used for building GF can be used for building
<a href="//cloud.grammaticalframework.org/translator/">translation systems</a>, <a href="//cloud.grammaticalframework.org/translator/">translation systems</a>,
@@ -219,19 +236,28 @@ least one, it may help you to get a first idea of what GF is.
or <a href="https://www.grammaticalframework.org/irc/?C=M;O=D">browse the channel logs</a>. or <a href="https://www.grammaticalframework.org/irc/?C=M;O=D">browse the channel logs</a>.
</p> </p>
<p> <p>
If you have a larger question which the community may benefit from, we recommend you ask it on the <a href="http://groups.google.com/group/gf-dev">mailing list</a>. There is also a <a href="https://discord.gg/EvfUsjzmaz">GF server on Discord</a>.
</p>
<p>
For bug reports and feature requests, please create an issue in the
<a href="https://github.com/GrammaticalFramework/gf-core/issues">GF Core</a> or
<a href="https://github.com/GrammaticalFramework/gf-rgl/issues">RGL</a> repository.
For programming questions, consider asking them on <a href="https://stackoverflow.com/questions/tagged/gf">Stack Overflow with the <code>gf</code> tag</a>.
If you have a more general question to the community, we recommend you ask it on the <a href="http://groups.google.com/group/gf-dev">mailing list</a>.
</p> </p>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<h2>News</h2> <h2>News</h2>
<dt class="col-sm-3 text-center text-nowrap">2021-07-25</dt>
<dd class="col-sm-9">
<strong>GF 3.11 released.</strong>
<a href="download/release-3.11.html">Release notes</a>
</dd>
<dl class="row"> <dl class="row">
<dt class="col-sm-3 text-center text-nowrap">2021-07-25</dt>
<dd class="col-sm-9">
<strong>GF 3.11 released.</strong>
<a href="download/release-3.11.html">Release notes</a>
</dd>
<dt class="col-sm-3 text-center text-nowrap">2021-05-05</dt> <dt class="col-sm-3 text-center text-nowrap">2021-05-05</dt>
<dd class="col-sm-9"> <dd class="col-sm-9">
<a href="https://cloud.grammaticalframework.org/wordnet/">GF WordNet</a> now supports languages for which there are no other WordNets. New additions: Afrikaans, German, Korean, Maltese, Polish, Somali, Swahili. <a href="https://cloud.grammaticalframework.org/wordnet/">GF WordNet</a> now supports languages for which there are no other WordNets. New additions: Afrikaans, German, Korean, Maltese, Polish, Somali, Swahili.
@@ -244,34 +270,6 @@ least one, it may help you to get a first idea of what GF is.
<dd class="col-sm-9"> <dd class="col-sm-9">
<a href="https://www.mitpressjournals.org/doi/pdf/10.1162/COLI_a_00378">Abstract Syntax as Interlingua</a>: Scaling Up the Grammatical Framework from Controlled Languages to Robust Pipelines. A paper in Computational Linguistics (2020) summarizing much of the development in GF in the past ten years. <a href="https://www.mitpressjournals.org/doi/pdf/10.1162/COLI_a_00378">Abstract Syntax as Interlingua</a>: Scaling Up the Grammatical Framework from Controlled Languages to Robust Pipelines. A paper in Computational Linguistics (2020) summarizing much of the development in GF in the past ten years.
</dd> </dd>
<dt class="col-sm-3 text-center text-nowrap">2018-12-03</dt>
<dd class="col-sm-9">
<a href="//school.grammaticalframework.org/2018/">Sixth GF Summer School</a> in Stellenbosch (South Africa), 314 December 2018
</dd>
<dt class="col-sm-3 text-center text-nowrap">2018-12-02</dt>
<dd class="col-sm-9">
<strong>GF 3.10 released.</strong>
<a href="download/release-3.10.html">Release notes</a>
</dd>
<dt class="col-sm-3 text-center text-nowrap">2018-07-25</dt>
<dd class="col-sm-9">
The GF repository has been split in two:
<a href="https://github.com/GrammaticalFramework/gf-core">gf-core</a> and
<a href="https://github.com/GrammaticalFramework/gf-rgl">gf-rgl</a>.
The original <a href="https://github.com/GrammaticalFramework/GF">GF</a> repository is now archived.
</dd>
<dt class="col-sm-3 text-center text-nowrap">2017-08-11</dt>
<dd class="col-sm-9">
<strong>GF 3.9 released.</strong>
<a href="download/release-3.9.html">Release notes</a>
</dd>
<dt class="col-sm-3 text-center text-nowrap">2017-06-29</dt>
<dd class="col-sm-9">
GF is moving to <a href="https://github.com/GrammaticalFramework/GF/">GitHub</a>.</dd>
<dt class="col-sm-3 text-center text-nowrap">2017-03-13</dt>
<dd class="col-sm-9">
<a href="//school.grammaticalframework.org/2017/">GF Summer School</a> in Riga (Latvia), 14-25 August 2017
</dd>
</dl> </dl>
<h2>Projects</h2> <h2>Projects</h2>
@@ -341,7 +339,7 @@ least one, it may help you to get a first idea of what GF is.
Libraries are at the heart of modern software engineering. In natural language Libraries are at the heart of modern software engineering. In natural language
applications, libraries are a way to cope with thousands of details involved in applications, libraries are a way to cope with thousands of details involved in
syntax, lexicon, and inflection. The syntax, lexicon, and inflection. The
<a href="lib/doc/synopsis/index.html">GF resource grammar library</a> has <a href="lib/doc/synopsis/index.html">GF resource grammar library</a> (RGL) has
support for an increasing number of languages, currently including support for an increasing number of languages, currently including
Afrikaans, Afrikaans,
Amharic (partial), Amharic (partial),

View File

@@ -1,3 +1,5 @@
module Main where
import qualified GF import qualified GF
main = GF.main main = GF.main

View File

@@ -12,3 +12,4 @@ So, **Don't Panic!** and keep reading. This is a live document and will develop
1. [Desiderata](DESIDERATA.md) 1. [Desiderata](DESIDERATA.md)
2. [Memory Model](memory_model.md) 2. [Memory Model](memory_model.md)
3. [Abstract Expressions](abstract_expressions.md) 3. [Abstract Expressions](abstract_expressions.md)
3. [Transactions](transactions.md)

View File

View File

@@ -289,6 +289,7 @@ PgfDB::PgfDB(const char* filepath, int flags, int mode) {
fd = -1; fd = -1;
ms = NULL; ms = NULL;
ref_count = 0;
if (filepath == NULL) { if (filepath == NULL) {
this->filepath = NULL; this->filepath = NULL;

View File

@@ -65,6 +65,10 @@ private:
friend class PgfReader; friend class PgfReader;
public: public:
// Here we count to how many revisions the client has access.
// When the count is zero we release the database.
int ref_count;
PGF_INTERNAL_DECL PgfDB(const char* filepath, int flags, int mode); PGF_INTERNAL_DECL PgfDB(const char* filepath, int flags, int mode);
PGF_INTERNAL_DECL ~PgfDB(); PGF_INTERNAL_DECL ~PgfDB();

View File

@@ -638,8 +638,7 @@ PgfBind *PgfExprParser::parse_bind(PgfBind *next)
PgfBind *bind = (PgfBind *) malloc(sizeof(PgfBind)+var->size+1); PgfBind *bind = (PgfBind *) malloc(sizeof(PgfBind)+var->size+1);
bind->bind_type = bind_type; bind->bind_type = bind_type;
bind->next = last; bind->next = last;
bind->var.size = var->size; memcpy(&bind->var, var, sizeof(PgfText)+var->size+1);
memcpy(bind->var.text, var->text, var->size+1);
last = bind; last = bind;
token(); token();
@@ -816,7 +815,7 @@ PgfType PgfExprParser::parse_type()
PgfText *cat = NULL; PgfText *cat = NULL;
size_t n_args = 0; size_t n_args = 0;
PgfType *args = NULL; PgfExpr *args = NULL;
for (;;) { for (;;) {
if (token_tag == PGF_TOKEN_LPAR) { if (token_tag == PGF_TOKEN_LPAR) {
@@ -908,10 +907,14 @@ PgfType PgfExprParser::parse_type()
type = u->dtyp(n_hypos,hypos,cat,n_args,args); type = u->dtyp(n_hypos,hypos,cat,n_args,args);
exit: exit:
PgfType last_type = 0;
while (n_hypos > 0) { while (n_hypos > 0) {
PgfTypeHypo *hypo = &hypos[--n_hypos]; PgfTypeHypo *hypo = &hypos[--n_hypos];
u->free_ref(hypo->type);
free(hypo->cid); free(hypo->cid);
if (hypo->type != last_type) {
u->free_ref(hypo->type);
last_type = hypo->type;
}
} }
free(hypos); free(hypos);

View File

@@ -56,6 +56,7 @@ PgfDB *pgf_read_pgf(const char* fpath,
*revision = pgf.as_object(); *revision = pgf.as_object();
} }
db->ref_count++;
return db; return db;
} PGF_API_END } PGF_API_END
@@ -97,6 +98,7 @@ PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path,
PgfDB::sync(); PgfDB::sync();
} }
db->ref_count++;
return db; return db;
} PGF_API_END } PGF_API_END
@@ -130,6 +132,7 @@ PgfDB *pgf_read_ngf(const char *fpath,
*revision = pgf.as_object(); *revision = pgf.as_object();
} }
db->ref_count++;
return db; return db;
} PGF_API_END } PGF_API_END
@@ -175,6 +178,7 @@ PgfDB *pgf_new_ngf(PgfText *abstract_name,
PgfDB::sync(); PgfDB::sync();
} }
db->ref_count++;
return db; return db;
} PGF_API_END } PGF_API_END
@@ -214,12 +218,6 @@ end:
fclose(out); fclose(out);
} }
PGF_API
void pgf_free(PgfDB *db)
{
delete db;
}
PGF_API_DECL PGF_API_DECL
void pgf_free_revision(PgfDB *db, PgfRevision revision) void pgf_free_revision(PgfDB *db, PgfRevision revision)
{ {
@@ -240,9 +238,14 @@ void pgf_free_revision(PgfDB *db, PgfRevision revision)
PgfPGF::release(pgf); PgfPGF::release(pgf);
PgfDB::free(pgf); PgfDB::free(pgf);
} }
db->ref_count--;
} catch (std::runtime_error& e) { } catch (std::runtime_error& e) {
// silently ignore and hope for the best // silently ignore and hope for the best
} }
if (!db->ref_count)
delete db;
} }
PGF_API PGF_API
@@ -601,6 +604,7 @@ PgfRevision pgf_clone_revision(PgfDB *db, PgfRevision revision,
memcpy(&new_pgf->name, ((name == NULL) ? &pgf->name : name), memcpy(&new_pgf->name, ((name == NULL) ? &pgf->name : name),
sizeof(PgfText)+name_size+1); sizeof(PgfText)+name_size+1);
db->ref_count++;
return new_pgf.as_object(); return new_pgf.as_object();
} PGF_API_END } PGF_API_END
@@ -635,6 +639,7 @@ PgfRevision pgf_checkout_revision(PgfDB *db, PgfText *name,
DB_scope scope(db, WRITER_SCOPE); DB_scope scope(db, WRITER_SCOPE);
ref<PgfPGF> pgf = PgfDB::get_revision(name); ref<PgfPGF> pgf = PgfDB::get_revision(name);
Node<PgfPGF>::add_value_ref(pgf); Node<PgfPGF>::add_value_ref(pgf);
db->ref_count++;
return pgf.as_object(); return pgf.as_object();
} PGF_API_END } PGF_API_END

View File

@@ -259,10 +259,8 @@ void pgf_write_pgf(const char* fpath,
PgfDB *db, PgfRevision revision, PgfDB *db, PgfRevision revision,
PgfExn* err); PgfExn* err);
/* Release the database when it is no longer needed. */ /* Release a revision. If this is the last revision for the given
PGF_API_DECL * database, then the database is released as well. */
void pgf_free(PgfDB *pgf);
PGF_API_DECL PGF_API_DECL
void pgf_free_revision(PgfDB *pgf, PgfRevision revision); void pgf_free_revision(PgfDB *pgf, PgfRevision revision);

View File

@@ -112,11 +112,10 @@ readPGF fpath =
withCString fpath $ \c_fpath -> withCString fpath $ \c_fpath ->
alloca $ \p_revision -> alloca $ \p_revision ->
mask_ $ do mask_ $ do
c_pgf <- withPgfExn "readPGF" (pgf_read_pgf c_fpath p_revision) c_db <- withPgfExn "readPGF" (pgf_read_pgf c_fpath p_revision)
c_revision <- peek p_revision c_revision <- peek p_revision
fptr1 <- newForeignPtr pgf_free_fptr c_pgf fptr <- C.newForeignPtr c_revision (pgf_free_revision c_db c_revision)
fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision)) return (PGF c_db fptr Map.empty)
return (PGF fptr1 fptr2 Map.empty)
-- | Reads a PGF file and stores the unpacked data in an NGF file -- | Reads a PGF file and stores the unpacked data in an NGF file
-- ready to be shared with other process, or used for quick startup. -- ready to be shared with other process, or used for quick startup.
@@ -128,11 +127,10 @@ bootNGF pgf_path ngf_path =
withCString ngf_path $ \c_ngf_path -> withCString ngf_path $ \c_ngf_path ->
alloca $ \p_revision -> alloca $ \p_revision ->
mask_ $ do mask_ $ do
c_pgf <- withPgfExn "bootNGF" (pgf_boot_ngf c_pgf_path c_ngf_path p_revision) c_db <- withPgfExn "bootNGF" (pgf_boot_ngf c_pgf_path c_ngf_path p_revision)
c_revision <- peek p_revision c_revision <- peek p_revision
fptr1 <- newForeignPtr pgf_free_fptr c_pgf fptr <- C.newForeignPtr c_revision (pgf_free_revision c_db c_revision)
fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision)) return (PGF c_db fptr Map.empty)
return (PGF fptr1 fptr2 Map.empty)
-- | Reads the grammar from an already booted NGF file. -- | Reads the grammar from an already booted NGF file.
-- The function fails if the file does not exist. -- The function fails if the file does not exist.
@@ -143,9 +141,8 @@ readNGF fpath =
mask_ $ do mask_ $ do
c_db <- withPgfExn "readNGF" (pgf_read_ngf c_fpath p_revision) c_db <- withPgfExn "readNGF" (pgf_read_ngf c_fpath p_revision)
c_revision <- peek p_revision c_revision <- peek p_revision
fptr1 <- newForeignPtr pgf_free_fptr c_db fptr <- C.newForeignPtr c_revision (pgf_free_revision c_db c_revision)
fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision)) return (PGF c_db fptr Map.empty)
return (PGF fptr1 fptr2 Map.empty)
-- | Creates a new NGF file with a grammar with the given abstract_name. -- | Creates a new NGF file with a grammar with the given abstract_name.
-- Aside from the name, the grammar is otherwise empty but can be later -- Aside from the name, the grammar is otherwise empty but can be later
@@ -159,16 +156,14 @@ newNGF abs_name mb_fpath =
mask_ $ do mask_ $ do
c_db <- withPgfExn "newNGF" (pgf_new_ngf c_abs_name c_fpath p_revision) c_db <- withPgfExn "newNGF" (pgf_new_ngf c_abs_name c_fpath p_revision)
c_revision <- peek p_revision c_revision <- peek p_revision
fptr1 <- newForeignPtr pgf_free_fptr c_db fptr <- C.newForeignPtr c_revision (pgf_free_revision c_db c_revision)
fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision)) return (PGF c_db fptr Map.empty)
return (PGF fptr1 fptr2 Map.empty)
writePGF :: FilePath -> PGF -> IO () writePGF :: FilePath -> PGF -> IO ()
writePGF fpath p = writePGF fpath p =
withCString fpath $ \c_fpath -> withCString fpath $ \c_fpath ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> withForeignPtr (revision p) $ \c_revision ->
withPgfExn "writePGF" (pgf_write_pgf c_fpath c_db c_revision) withPgfExn "writePGF" (pgf_write_pgf c_fpath (a_db p) c_revision)
showPGF :: PGF -> String showPGF :: PGF -> String
showPGF = error "TODO: showPGF" showPGF = error "TODO: showPGF"
@@ -178,9 +173,8 @@ showPGF = error "TODO: showPGF"
abstractName :: PGF -> AbsName abstractName :: PGF -> AbsName
abstractName p = abstractName p =
unsafePerformIO $ unsafePerformIO $
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> withForeignPtr (revision p) $ \c_revision ->
bracket (withPgfExn "abstractName" (pgf_abstract_name c_db c_revision)) free $ \c_text -> bracket (withPgfExn "abstractName" (pgf_abstract_name (a_db p) c_revision)) free $ \c_text ->
peekText c_text peekText c_text
-- | The start category is defined in the grammar with -- | The start category is defined in the grammar with
@@ -192,9 +186,8 @@ startCat :: PGF -> Type
startCat p = startCat p =
unsafePerformIO $ unsafePerformIO $
withForeignPtr unmarshaller $ \u -> withForeignPtr unmarshaller $ \u ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> do withForeignPtr (revision p) $ \c_revision -> do
c_typ <- withPgfExn "startCat" (pgf_start_cat c_db c_revision u) c_typ <- withPgfExn "startCat" (pgf_start_cat (a_db p) c_revision u)
typ <- deRefStablePtr c_typ typ <- deRefStablePtr c_typ
freeStablePtr c_typ freeStablePtr c_typ
return typ return typ
@@ -204,10 +197,9 @@ functionType :: PGF -> Fun -> Maybe Type
functionType p fn = functionType p fn =
unsafePerformIO $ unsafePerformIO $
withForeignPtr unmarshaller $ \u -> withForeignPtr unmarshaller $ \u ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> withForeignPtr (revision p) $ \c_revision ->
withText fn $ \c_fn -> do withText fn $ \c_fn -> do
c_typ <- withPgfExn "functionType" (pgf_function_type c_db c_revision c_fn u) c_typ <- withPgfExn "functionType" (pgf_function_type (a_db p) c_revision c_fn u)
if c_typ == castPtrToStablePtr nullPtr if c_typ == castPtrToStablePtr nullPtr
then return Nothing then return Nothing
else do typ <- deRefStablePtr c_typ else do typ <- deRefStablePtr c_typ
@@ -218,27 +210,24 @@ functionIsConstructor :: PGF -> Fun -> Bool
functionIsConstructor p fun = functionIsConstructor p fun =
unsafePerformIO $ unsafePerformIO $
withText fun $ \c_fun -> withText fun $ \c_fun ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> withForeignPtr (revision p) $ \c_revision ->
do res <- withPgfExn "functionIsConstructor" (pgf_function_is_constructor c_db c_revision c_fun) do res <- withPgfExn "functionIsConstructor" (pgf_function_is_constructor (a_db p) c_revision c_fun)
return (res /= 0) return (res /= 0)
functionProbability :: PGF -> Fun -> Float functionProbability :: PGF -> Fun -> Float
functionProbability p fun = functionProbability p fun =
unsafePerformIO $ unsafePerformIO $
withText fun $ \c_fun -> withText fun $ \c_fun ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> withForeignPtr (revision p) $ \c_revision ->
withPgfExn "functionProbability" (pgf_function_prob c_db c_revision c_fun) withPgfExn "functionProbability" (pgf_function_prob (a_db p) c_revision c_fun)
exprProbability :: PGF -> Expr -> Float exprProbability :: PGF -> Expr -> Float
exprProbability p e = exprProbability p e =
unsafePerformIO $ unsafePerformIO $
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> withForeignPtr (revision p) $ \c_revision ->
bracket (newStablePtr e) freeStablePtr $ \c_e -> bracket (newStablePtr e) freeStablePtr $ \c_e ->
withForeignPtr marshaller $ \m -> withForeignPtr marshaller $ \m ->
withPgfExn "exprProbability" (pgf_expr_prob c_db c_revision c_e m) withPgfExn "exprProbability" (pgf_expr_prob (a_db p) c_revision c_e m)
checkExpr :: PGF -> Expr -> Type -> Either String Expr checkExpr :: PGF -> Expr -> Type -> Either String Expr
checkExpr = error "TODO: checkExpr" checkExpr = error "TODO: checkExpr"
@@ -503,10 +492,9 @@ categories p =
ref <- newIORef [] ref <- newIORef []
(allocaBytes (#size PgfItor) $ \itor -> (allocaBytes (#size PgfItor) $ \itor ->
bracket (wrapItorCallback (getCategories ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getCategories ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> do withForeignPtr (revision p) $ \c_revision -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
withPgfExn "categories" (pgf_iter_categories c_db c_revision itor) withPgfExn "categories" (pgf_iter_categories (a_db p) c_revision itor)
cs <- readIORef ref cs <- readIORef ref
return (reverse cs)) return (reverse cs))
where where
@@ -522,10 +510,9 @@ categoryContext p cat =
withText cat $ \c_cat -> withText cat $ \c_cat ->
alloca $ \p_n_hypos -> alloca $ \p_n_hypos ->
withForeignPtr unmarshaller $ \u -> withForeignPtr unmarshaller $ \u ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> withForeignPtr (revision p) $ \c_revision ->
mask_ $ do mask_ $ do
c_hypos <- withPgfExn "categoryContext" (pgf_category_context c_db c_revision c_cat p_n_hypos u) c_hypos <- withPgfExn "categoryContext" (pgf_category_context (a_db p) c_revision c_cat p_n_hypos u)
if c_hypos == nullPtr if c_hypos == nullPtr
then return Nothing then return Nothing
else do n_hypos <- peek p_n_hypos else do n_hypos <- peek p_n_hypos
@@ -550,9 +537,8 @@ categoryProbability :: PGF -> Cat -> Float
categoryProbability p cat = categoryProbability p cat =
unsafePerformIO $ unsafePerformIO $
withText cat $ \c_cat -> withText cat $ \c_cat ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> withForeignPtr (revision p) $ \c_revision ->
withPgfExn "categoryProbability" (pgf_category_prob c_db c_revision c_cat) withPgfExn "categoryProbability" (pgf_category_prob (a_db p) c_revision c_cat)
-- | List of all functions defined in the abstract syntax -- | List of all functions defined in the abstract syntax
functions :: PGF -> [Fun] functions :: PGF -> [Fun]
@@ -561,10 +547,9 @@ functions p =
ref <- newIORef [] ref <- newIORef []
(allocaBytes (#size PgfItor) $ \itor -> (allocaBytes (#size PgfItor) $ \itor ->
bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> do withForeignPtr (revision p) $ \c_revision -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
withPgfExn "functions" (pgf_iter_functions c_db c_revision itor) withPgfExn "functions" (pgf_iter_functions (a_db p) c_revision itor)
fs <- readIORef ref fs <- readIORef ref
return (reverse fs)) return (reverse fs))
where where
@@ -582,10 +567,9 @@ functionsByCat p cat =
(withText cat $ \c_cat -> (withText cat $ \c_cat ->
allocaBytes (#size PgfItor) $ \itor -> allocaBytes (#size PgfItor) $ \itor ->
bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> do withForeignPtr (revision p) $ \c_revision -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
withPgfExn "functionsByCat" (pgf_iter_functions_by_cat c_db c_revision c_cat itor) withPgfExn "functionsByCat" (pgf_iter_functions_by_cat (a_db p) c_revision c_cat itor)
fs <- readIORef ref fs <- readIORef ref
return (reverse fs)) return (reverse fs))
where where
@@ -599,10 +583,9 @@ globalFlag :: PGF -> String -> Maybe Literal
globalFlag p name = globalFlag p name =
unsafePerformIO $ unsafePerformIO $
withText name $ \c_name -> withText name $ \c_name ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> withForeignPtr (revision p) $ \c_revision ->
withForeignPtr unmarshaller $ \u -> do withForeignPtr unmarshaller $ \u -> do
c_lit <- withPgfExn "globalFlag" (pgf_get_global_flag c_db c_revision c_name u) c_lit <- withPgfExn "globalFlag" (pgf_get_global_flag (a_db p) c_revision c_name u)
if c_lit == castPtrToStablePtr nullPtr if c_lit == castPtrToStablePtr nullPtr
then return Nothing then return Nothing
else do lit <- deRefStablePtr c_lit else do lit <- deRefStablePtr c_lit
@@ -613,10 +596,9 @@ abstractFlag :: PGF -> String -> Maybe Literal
abstractFlag p name = abstractFlag p name =
unsafePerformIO $ unsafePerformIO $
withText name $ \c_name -> withText name $ \c_name ->
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> withForeignPtr (revision p) $ \c_revision ->
withForeignPtr unmarshaller $ \u -> do withForeignPtr unmarshaller $ \u -> do
c_lit <- withPgfExn "abstractFlag" (pgf_get_abstract_flag c_db c_revision c_name u) c_lit <- withPgfExn "abstractFlag" (pgf_get_abstract_flag (a_db p) c_revision c_name u)
if c_lit == castPtrToStablePtr nullPtr if c_lit == castPtrToStablePtr nullPtr
then return Nothing then return Nothing
else do lit <- deRefStablePtr c_lit else do lit <- deRefStablePtr c_lit

View File

@@ -23,11 +23,11 @@ type ConcName = String -- ^ Name of concrete syntax
-- | An abstract data type representing multilingual grammar -- | An abstract data type representing multilingual grammar
-- in Portable Grammar Format. -- in Portable Grammar Format.
data PGF = PGF { a_db :: ForeignPtr PgfDB data PGF = PGF { a_db :: Ptr PgfDB
, revision :: ForeignPtr PgfRevision , revision :: ForeignPtr PgfRevision
, languages:: Map.Map ConcName Concr , languages:: Map.Map ConcName Concr
} }
data Concr = Concr {c_pgf :: ForeignPtr PgfDB, concr :: Ptr PgfConcr} data Concr = Concr {c_pgf :: Ptr PgfDB, concr :: Ptr PgfConcr}
------------------------------------------------------------------ ------------------------------------------------------------------
-- libpgf API -- libpgf API
@@ -62,9 +62,6 @@ foreign import ccall pgf_new_ngf :: Ptr PgfText -> CString -> Ptr (Ptr PgfRevisi
foreign import ccall pgf_write_pgf :: CString -> Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfExn -> IO () foreign import ccall pgf_write_pgf :: CString -> Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfExn -> IO ()
foreign import ccall "&pgf_free"
pgf_free_fptr :: FinalizerPtr PgfDB
foreign import ccall "pgf_free_revision" foreign import ccall "pgf_free_revision"
pgf_free_revision :: Ptr PgfDB -> Ptr PgfRevision -> IO () pgf_free_revision :: Ptr PgfDB -> Ptr PgfRevision -> IO ()

View File

@@ -73,41 +73,39 @@ branchPGF p name t =
branchPGF_ :: Ptr PgfText -> PGF -> Transaction a -> IO PGF branchPGF_ :: Ptr PgfText -> PGF -> Transaction a -> IO PGF
branchPGF_ c_name p (Transaction f) = branchPGF_ c_name p (Transaction f) =
withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> withForeignPtr (revision p) $ \c_revision ->
withPgfExn "branchPGF" $ \c_exn -> withPgfExn "branchPGF" $ \c_exn ->
mask $ \restore -> do mask $ \restore -> do
c_revision <- pgf_clone_revision c_db c_revision c_name c_exn c_revision <- pgf_clone_revision (a_db p) c_revision c_name c_exn
ex_type <- (#peek PgfExn, type) c_exn ex_type <- (#peek PgfExn, type) c_exn
if (ex_type :: (#type PgfExnType)) == (#const PGF_EXN_NONE) if (ex_type :: (#type PgfExnType)) == (#const PGF_EXN_NONE)
then do ((restore (f c_db c_revision c_exn)) then do ((restore (f (a_db p) c_revision c_exn))
`catch` `catch`
(\e -> do (\e -> do
pgf_free_revision c_db c_revision pgf_free_revision (a_db p) c_revision
throwIO (e :: SomeException))) throwIO (e :: SomeException)))
ex_type <- (#peek PgfExn, type) c_exn ex_type <- (#peek PgfExn, type) c_exn
if (ex_type :: (#type PgfExnType)) == (#const PGF_EXN_NONE) if (ex_type :: (#type PgfExnType)) == (#const PGF_EXN_NONE)
then do pgf_commit_revision c_db c_revision c_exn then do pgf_commit_revision (a_db p) c_revision c_exn
ex_type <- (#peek PgfExn, type) c_exn ex_type <- (#peek PgfExn, type) c_exn
if (ex_type :: (#type PgfExnType)) == (#const PGF_EXN_NONE) if (ex_type :: (#type PgfExnType)) == (#const PGF_EXN_NONE)
then do fptr2 <- C.newForeignPtr c_revision (withForeignPtr (a_db p) (\c_db -> pgf_free_revision c_db c_revision)) then do fptr <- C.newForeignPtr c_revision (pgf_free_revision (a_db p) c_revision)
return (PGF (a_db p) fptr2 (languages p)) return (PGF (a_db p) fptr (languages p))
else do pgf_free_revision c_db c_revision else do pgf_free_revision (a_db p) c_revision
return p return p
else do pgf_free_revision c_db c_revision else do pgf_free_revision (a_db p) c_revision
return p return p
else return p else return p
{- | Retrieves the branch with the given name -} {- | Retrieves the branch with the given name -}
checkoutPGF :: PGF -> String -> IO (Maybe PGF) checkoutPGF :: PGF -> String -> IO (Maybe PGF)
checkoutPGF p name = checkoutPGF p name =
withForeignPtr (a_db p) $ \c_db ->
withText name $ \c_name -> do withText name $ \c_name -> do
c_revision <- withPgfExn "checkoutPGF" (pgf_checkout_revision c_db c_name) c_revision <- withPgfExn "checkoutPGF" (pgf_checkout_revision (a_db p) c_name)
if c_revision == nullPtr if c_revision == nullPtr
then return Nothing then return Nothing
else do fptr2 <- C.newForeignPtr c_revision (withForeignPtr (a_db p) (\c_db -> pgf_free_revision c_db c_revision)) else do fptr <- C.newForeignPtr c_revision (pgf_free_revision (a_db p) c_revision)
return (Just (PGF (a_db p) fptr2 (languages p))) return (Just (PGF (a_db p) fptr (languages p)))
createFunction :: Fun -> Type -> Int -> Float -> Transaction () createFunction :: Fun -> Type -> Int -> Float -> Transaction ()
createFunction name ty arity prob = Transaction $ \c_db c_revision c_exn -> createFunction name ty arity prob = Transaction $ \c_db c_revision c_exn ->

View File

@@ -13,7 +13,7 @@
static void static void
PGF_dealloc(PGFObject *self) PGF_dealloc(PGFObject *self)
{ {
pgf_free(self->db); pgf_free_revision(self->db, self->revision);
Py_TYPE(self)->tp_free((PyObject *)self); Py_TYPE(self)->tp_free((PyObject *)self);
} }

View File

@@ -1,2 +1,12 @@
i -retain testsuite/compiler/compute/Variants.gf i -retain testsuite/compiler/compute/Variants.gf
cc hello cc hello
cc <\x -> x++x : Str -> Str> ("a"|"b")
cc <\x -> x : Str -> Str> ("a"|"b")
cc <\x -> "c" : Str -> Str> ("a"|"b")
cc <let x = ("a"|"b") in x++x : Str>
cc <let x = ("a"|"b") in x : Str>
cc <let x = ("a"|"b") in "c" : Str>
cc <\x -> x.p1++x.p1 : Str*Str -> Str> <"a"|"b","c">
cc <\x -> x.p1 : Str*Str -> Str> <"a"|"b","c">
cc <\x -> x.p2++x.p2 : Str*Str -> Str> <"a"|"b","c">
cc <\x -> x.p2 : Str*Str -> Str> <"a"|"b","c">

View File

@@ -1 +1,11 @@
variants {"hello"; "hello" ++ "hello"} variants {"hello"; "hello" ++ "hello"}
variants {"a" ++ "a"; "b" ++ "b"}
variants {"a"; "b"}
"c"
variants {"a"; "b"} ++ variants {"a"; "b"}
variants {"a"; "b"}
"c"
variants {"a"; "b"} ++ variants {"a"; "b"}
variants {"a"; "b"}
"c" ++ "c"
"c"