From 723bec1ba0579ace280f6d67ad71a1596fc4f166 Mon Sep 17 00:00:00 2001 From: "John J. Camilleri" Date: Mon, 9 Aug 2021 13:41:25 +0200 Subject: [PATCH 01/17] Changes made in order to get Hackage upload working --- Makefile | 6 +++--- RELEASE.md | 11 +++++++---- gf.cabal | 9 ++++++--- src/programs/gf-main.hs | 2 ++ 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index cdb35e49a..fc2a38808 100644 --- a/Makefile +++ b/Makefile @@ -65,6 +65,6 @@ bintar: # 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` -sdist: - test -d dist || mkdir dist - git archive --format=tar.gz --output=dist/gf-${VERSION}.tar.gz HEAD +# sdist: +# test -d dist || mkdir dist +# git archive --format=tar.gz --output=dist/gf-${VERSION}.tar.gz HEAD diff --git a/RELEASE.md b/RELEASE.md index 04bd4b933..1deaa3a90 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -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. -1. Run `make sdist` +1. Run `stack sdist --test-tarball` and address any issues. 2. Upload the package, either: - 1. **Manually**: visit and upload the file `dist/gf-X.Y.tar.gz` - 2. **via Cabal (≥2.4)**: `cabal upload dist/gf-X.Y.tar.gz` -3. If the documentation-building fails on the Hackage server, do: + 1. **Manually**: visit and upload the file generated by the previous command. + 2. **via Stack**: `stack upload . --candidate` +3. After testing the candidate, publish it: + 1. **Manually**: visit + 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 upload --documentation dist/docs/*-docs.tar.gz diff --git a/gf.cabal b/gf.cabal index 711acaeb2..e356614ec 100644 --- a/gf.cabal +++ b/gf.cabal @@ -8,12 +8,15 @@ license-file: LICENSE category: Natural Language Processing, Compiler synopsis: Grammatical Framework description: GF, Grammatical Framework, is a programming language for multilingual grammar applications +maintainer: John J. Camilleri homepage: https://www.grammaticalframework.org/ bug-reports: https://github.com/GrammaticalFramework/gf-core/issues tested-with: GHC==7.10.3, GHC==8.0.2, GHC==8.10.4 data-dir: src -extra-source-files: WebSetup.hs +extra-source-files: + WebSetup.hs + doc/Logos/gf0.png data-files: www/*.html www/*.css @@ -106,7 +109,7 @@ library --ghc-options: -fwarn-unused-imports --if impl(ghc>=7.8) -- ghc-options: +RTS -A20M -RTS - ghc-prof-options: -fprof-auto + -- ghc-prof-options: -fprof-auto exposed-modules: PGF @@ -370,7 +373,7 @@ executable gf if impl(ghc<7.8) ghc-options: -with-rtsopts=-K64M - ghc-prof-options: -auto-all + -- ghc-prof-options: -auto-all if impl(ghc>=8.2) ghc-options: -fhide-source-paths diff --git a/src/programs/gf-main.hs b/src/programs/gf-main.hs index 1dae54bc7..cf387d2fa 100644 --- a/src/programs/gf-main.hs +++ b/src/programs/gf-main.hs @@ -1,3 +1,5 @@ +module Main where + import qualified GF main = GF.main From 7a63ba34b471a1b4edd4655422f4ae235dbcf12b Mon Sep 17 00:00:00 2001 From: "John J. Camilleri" Date: Thu, 12 Aug 2021 09:56:34 +0200 Subject: [PATCH 02/17] Add changelog This will hopefully help us keep track of changes for the next release --- CHANGELOG.md | 11 +++++++++++ README.md | 4 ++-- gf.cabal | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..ac209f1af --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +### New since 3.11 (WIP) + +- Added a changelog! + +### 3.11 + +See + +### 3.10 + +See diff --git a/README.md b/README.md index e393be0e6..79e6ab68f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![GF Logo](doc/Logos/gf1.svg) +![GF Logo](https://www.grammaticalframework.org/doc/Logos/gf1.svg) # Grammatical Framework (GF) @@ -39,7 +39,7 @@ or: 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 diff --git a/gf.cabal b/gf.cabal index e356614ec..b4dcf81a0 100644 --- a/gf.cabal +++ b/gf.cabal @@ -15,6 +15,8 @@ tested-with: GHC==7.10.3, GHC==8.0.2, GHC==8.10.4 data-dir: src extra-source-files: + README.md + CHANGELOG.md WebSetup.hs doc/Logos/gf0.png data-files: From e477ce4b1fbc5544c1fe0d8dedd83df3f5ec1290 Mon Sep 17 00:00:00 2001 From: "John J. Camilleri" Date: Thu, 12 Aug 2021 10:05:45 +0200 Subject: [PATCH 03/17] HTML fix on homepage --- index.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index 8816cc265..6bf896c28 100644 --- a/index.html +++ b/index.html @@ -226,12 +226,12 @@ least one, it may help you to get a first idea of what GF is.

News

-
2021-07-25
-
- GF 3.11 released. - Release notes -
+
2021-07-25
+
+ GF 3.11 released. + Release notes +
2021-05-05
GF WordNet now supports languages for which there are no other WordNets. New additions: Afrikaans, German, Korean, Maltese, Polish, Somali, Swahili. From bbe4682c3da36d69441e00758c9979a5f0ac44cb Mon Sep 17 00:00:00 2001 From: "John J. Camilleri" Date: Thu, 12 Aug 2021 15:19:17 +0200 Subject: [PATCH 04/17] Update homepage - Add Discord link - Point to GitHub issues, Stack Overflow in "Getting help" - Remove old news --- index.html | 41 +++++++++++------------------------------ 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/index.html b/index.html index 6bf896c28..91848da60 100644 --- a/index.html +++ b/index.html @@ -219,7 +219,16 @@ least one, it may help you to get a first idea of what GF is. or browse the channel logs.

- If you have a larger question which the community may benefit from, we recommend you ask it on the mailing list. + The is also a GF server on Discord. +

+ +

+ For bug reports and feature requests, please create an issue on the + GF Core or + RGL repositories. + + For programming questions, consider asking them on Stack Overflow with the gf tag. + If you have a more general question to the community, we recommend you ask it on the mailing list.

@@ -244,34 +253,6 @@ least one, it may help you to get a first idea of what GF is.
Abstract Syntax as Interlingua: 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.
-
2018-12-03
-
- Sixth GF Summer School in Stellenbosch (South Africa), 3–14 December 2018 -
-
2018-12-02
-
- GF 3.10 released. - Release notes -
-
2018-07-25
-
- The GF repository has been split in two: - gf-core and - gf-rgl. - The original GF repository is now archived. -
-
2017-08-11
-
- GF 3.9 released. - Release notes -
-
2017-06-29
-
- GF is moving to GitHub.
-
2017-03-13
-
- GF Summer School in Riga (Latvia), 14-25 August 2017 -

Projects

@@ -341,7 +322,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 applications, libraries are a way to cope with thousands of details involved in syntax, lexicon, and inflection. The - GF resource grammar library has + GF resource grammar library (RGL) has support for an increasing number of languages, currently including Afrikaans, Amharic (partial), From 974e8b08353ee9baab59e0e4d8f81413f0789afc Mon Sep 17 00:00:00 2001 From: "John J. Camilleri" Date: Thu, 12 Aug 2021 15:20:29 +0200 Subject: [PATCH 05/17] Typos in homepage --- index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 91848da60..f87fa5273 100644 --- a/index.html +++ b/index.html @@ -219,13 +219,13 @@ least one, it may help you to get a first idea of what GF is. or browse the channel logs.

- The is also a GF server on Discord. + There is also a GF server on Discord.

- For bug reports and feature requests, please create an issue on the + For bug reports and feature requests, please create an issue in the GF Core or - RGL repositories. + RGL repository. For programming questions, consider asking them on Stack Overflow with the gf tag. If you have a more general question to the community, we recommend you ask it on the mailing list. From 058526ec5d33759f5f19dedc4767276009888a97 Mon Sep 17 00:00:00 2001 From: "John J. Camilleri" Date: Thu, 12 Aug 2021 15:27:10 +0200 Subject: [PATCH 06/17] Remove Travis CI workflow, we use GitHub actions now Closes #123 --- .travis.yml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0ca0794b0..000000000 --- a/.travis.yml +++ /dev/null @@ -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'" From 8ec13b1030f21f5938e4129d2b2a800645721cc0 Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Mon, 16 Aug 2021 09:07:59 +0800 Subject: [PATCH 07/17] Uncomment installation instructions from Hackage --- download/index-3.11.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/download/index-3.11.md b/download/index-3.11.md index 4f2798a0a..25b4cf7fb 100644 --- a/download/index-3.11.md +++ b/download/index-3.11.md @@ -53,10 +53,11 @@ 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). - +The GF source code has been updated to compile with GHC versions 7.10 through to 8.10. + ## Installing from the latest developer source code If you haven't already, clone the repository with: From ef0e831c9e532e091d463905294958daea57d103 Mon Sep 17 00:00:00 2001 From: "John J. Camilleri" Date: Tue, 17 Aug 2021 09:38:20 +0200 Subject: [PATCH 08/17] Update installation instructions from Hackage, source code --- download/index-3.11.md | 58 ++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/download/index-3.11.md b/download/index-3.11.md index 25b4cf7fb..8fa1d5c02 100644 --- a/download/index-3.11.md +++ b/download/index-3.11.md @@ -53,27 +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). -## 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 -normal circumstances the procedure is fairly simple. -If you already have a version of GHC between 7.10 and 8.10, go directly to point 4. +normal circumstances the procedure is fairly simple: -1. Install ghcup https://www.haskell.org/ghcup/ -2. `ghcup install ghc 8.10.4` -3. `ghcup set ghc 8.10.4` -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**. +``` +cabal update +cabal install gf-3.11 +``` ### 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** -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`), so you might want to add this directory to your path (in `.bash_profile` or similar): @@ -85,32 +97,34 @@ PATH=$HOME/.cabal/bin:$PATH GF uses [`haskeline`](http://hackage.haskell.org/package/haskeline), which 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: - On Ubuntu: `sudo apt-get install libghc-haskeline-dev` - 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.10. +**Obtaining** -## Installing from the latest developer source code +To obtain the source code for the **release**, +download it from [GitHub](https://github.com/GrammaticalFramework/gf-core/releases). -If you haven't already, clone the repository with: +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 ``` - -If you've already cloned the repository previously, update with: - +2. If you've already cloned the repository previously, update with: ``` git pull ``` -Then install with: +**Installing** + +You can then install with: ``` cabal install ``` From 0258a8725717d029b3c6900ef1ace39b9835e9ad Mon Sep 17 00:00:00 2001 From: "John J. Camilleri" Date: Tue, 17 Aug 2021 09:57:50 +0200 Subject: [PATCH 09/17] Add IRC, Discord, SO links to "contribute" section at top of homepage --- index.html | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index f87fa5273..f657cc5b5 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,7 @@ - + @@ -85,10 +85,27 @@

Contribute

@@ -154,7 +171,7 @@ least one, it may help you to get a first idea of what GF is.
-

Applications & Availability

+

Applications & availability

GF can be used for building translation systems, From bedb46527daa99125f103b87e9fdf8e3cbe9d98b Mon Sep 17 00:00:00 2001 From: "John J. Camilleri" Date: Tue, 17 Aug 2021 10:18:34 +0200 Subject: [PATCH 10/17] Move Thomas from current to previous on maintainers page --- doc/gf-people.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gf-people.md b/doc/gf-people.md index 7d0ef90c2..d7b755b9d 100644 --- a/doc/gf-people.md +++ b/doc/gf-people.md @@ -7,7 +7,6 @@ title: "Grammatical Framework: Authors and Acknowledgements" The current maintainers of GF are [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/), [John J. Camilleri](http://johnjcamilleri.com), and [Inari Listenmaa](https://inariksit.github.io/). @@ -22,6 +21,7 @@ and 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) - Ramona Enache (University of Gothenburg) - [Björn Bringert](http://www.cse.chalmers.se/alumni/bringert) (University of Gothenburg) From 1d1d1aad81938a6d481882c8f2a28885e50270e8 Mon Sep 17 00:00:00 2001 From: krangelov Date: Wed, 22 Sep 2021 11:02:45 +0200 Subject: [PATCH 11/17] small optimization --- src/runtime/c/pgf/expr.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/runtime/c/pgf/expr.cxx b/src/runtime/c/pgf/expr.cxx index d67ab1cd2..0853ec90a 100644 --- a/src/runtime/c/pgf/expr.cxx +++ b/src/runtime/c/pgf/expr.cxx @@ -638,8 +638,7 @@ PgfBind *PgfExprParser::parse_bind(PgfBind *next) PgfBind *bind = (PgfBind *) malloc(sizeof(PgfBind)+var->size+1); bind->bind_type = bind_type; bind->next = last; - bind->var.size = var->size; - memcpy(bind->var.text, var->text, var->size+1); + memcpy(&bind->var, var, sizeof(PgfText)+var->size+1); last = bind; token(); From be43b0ba35190e69f0faf2703c000cf3f3722705 Mon Sep 17 00:00:00 2001 From: krangelov Date: Wed, 22 Sep 2021 11:03:16 +0200 Subject: [PATCH 12/17] fix variable type --- src/runtime/c/pgf/expr.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/c/pgf/expr.cxx b/src/runtime/c/pgf/expr.cxx index 0853ec90a..3b7cf56bb 100644 --- a/src/runtime/c/pgf/expr.cxx +++ b/src/runtime/c/pgf/expr.cxx @@ -815,7 +815,7 @@ PgfType PgfExprParser::parse_type() PgfText *cat = NULL; size_t n_args = 0; - PgfType *args = NULL; + PgfExpr *args = NULL; for (;;) { if (token_tag == PGF_TOKEN_LPAR) { From 58b8c2771e96465fdcfaab4c4002d500afc55f59 Mon Sep 17 00:00:00 2001 From: krangelov Date: Wed, 22 Sep 2021 11:16:29 +0200 Subject: [PATCH 13/17] fix double release for stable pointers --- src/runtime/c/pgf/expr.cxx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/runtime/c/pgf/expr.cxx b/src/runtime/c/pgf/expr.cxx index 3b7cf56bb..fbcbd2810 100644 --- a/src/runtime/c/pgf/expr.cxx +++ b/src/runtime/c/pgf/expr.cxx @@ -812,6 +812,9 @@ PgfType PgfExprParser::parse_type() size_t n_hypos = 0; PgfTypeHypo *hypos = NULL; + size_t n_types = 0; + PgfType *types = NULL; + PgfText *cat = NULL; size_t n_args = 0; @@ -851,6 +854,9 @@ PgfType PgfExprParser::parse_type() if (type == 0) goto exit; + types = (PgfType*) realloc(types, sizeof(PgfType)*(n_types+1)); + types[n_types++] = type; + if (token_tag != PGF_TOKEN_RPAR) goto exit; @@ -891,6 +897,9 @@ PgfType PgfExprParser::parse_type() bt->type = u->dtyp(0,NULL,cat,n_args,args); n_hypos++; + types = (PgfType*) realloc(types, sizeof(PgfType)*(n_types+1)); + types[n_types++] = bt->type; + while (n_args > 0) { u->free_ref(args[--n_args]); } @@ -909,11 +918,16 @@ PgfType PgfExprParser::parse_type() exit: while (n_hypos > 0) { PgfTypeHypo *hypo = &hypos[--n_hypos]; - u->free_ref(hypo->type); free(hypo->cid); } free(hypos); + while (n_types > 0) { + PgfType type = types[--n_types]; + u->free_ref(type); + } + free(types); + free(cat); while (n_args > 0) { From e11e775a96f2c7e86c12dd81653f7ae6512df936 Mon Sep 17 00:00:00 2001 From: krangelov Date: Wed, 22 Sep 2021 13:21:07 +0200 Subject: [PATCH 14/17] merge pgf_free and pgf_free_revision since otherwise we cannot control the finalizers in Haskell --- src/runtime/c/pgf/db.cxx | 1 + src/runtime/c/pgf/db.h | 4 ++ src/runtime/c/pgf/pgf.cxx | 17 +++--- src/runtime/c/pgf/pgf.h | 6 +-- src/runtime/haskell/PGF2.hsc | 66 +++++++++-------------- src/runtime/haskell/PGF2/FFI.hsc | 7 +-- src/runtime/haskell/PGF2/Transactions.hsc | 24 ++++----- src/runtime/python/pypgf.c | 2 +- 8 files changed, 56 insertions(+), 71 deletions(-) diff --git a/src/runtime/c/pgf/db.cxx b/src/runtime/c/pgf/db.cxx index b0bad20f7..ff20835a5 100644 --- a/src/runtime/c/pgf/db.cxx +++ b/src/runtime/c/pgf/db.cxx @@ -289,6 +289,7 @@ PgfDB::PgfDB(const char* filepath, int flags, int mode) { fd = -1; ms = NULL; + ref_count = 0; if (filepath == NULL) { this->filepath = NULL; diff --git a/src/runtime/c/pgf/db.h b/src/runtime/c/pgf/db.h index bfde56ebb..b7bc01482 100644 --- a/src/runtime/c/pgf/db.h +++ b/src/runtime/c/pgf/db.h @@ -65,6 +65,10 @@ private: friend class PgfReader; 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(); diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index 14a65b566..a6b228810 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -56,6 +56,7 @@ PgfDB *pgf_read_pgf(const char* fpath, *revision = pgf.as_object(); } + db->ref_count++; return db; } PGF_API_END @@ -97,6 +98,7 @@ PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path, PgfDB::sync(); } + db->ref_count++; return db; } PGF_API_END @@ -130,6 +132,7 @@ PgfDB *pgf_read_ngf(const char *fpath, *revision = pgf.as_object(); } + db->ref_count++; return db; } PGF_API_END @@ -175,6 +178,7 @@ PgfDB *pgf_new_ngf(PgfText *abstract_name, PgfDB::sync(); } + db->ref_count++; return db; } PGF_API_END @@ -214,12 +218,6 @@ end: fclose(out); } -PGF_API -void pgf_free(PgfDB *db) -{ - delete db; -} - PGF_API_DECL void pgf_free_revision(PgfDB *db, PgfRevision revision) { @@ -240,9 +238,14 @@ void pgf_free_revision(PgfDB *db, PgfRevision revision) PgfPGF::release(pgf); PgfDB::free(pgf); } + + db->ref_count--; } catch (std::runtime_error& e) { // silently ignore and hope for the best } + + if (!db->ref_count) + delete db; } PGF_API @@ -601,6 +604,7 @@ PgfRevision pgf_clone_revision(PgfDB *db, PgfRevision revision, memcpy(&new_pgf->name, ((name == NULL) ? &pgf->name : name), sizeof(PgfText)+name_size+1); + db->ref_count++; return new_pgf.as_object(); } PGF_API_END @@ -635,6 +639,7 @@ PgfRevision pgf_checkout_revision(PgfDB *db, PgfText *name, DB_scope scope(db, WRITER_SCOPE); ref pgf = PgfDB::get_revision(name); Node::add_value_ref(pgf); + db->ref_count++; return pgf.as_object(); } PGF_API_END diff --git a/src/runtime/c/pgf/pgf.h b/src/runtime/c/pgf/pgf.h index f9a8dd8b2..b8f866cd6 100644 --- a/src/runtime/c/pgf/pgf.h +++ b/src/runtime/c/pgf/pgf.h @@ -259,10 +259,8 @@ void pgf_write_pgf(const char* fpath, PgfDB *db, PgfRevision revision, PgfExn* err); -/* Release the database when it is no longer needed. */ -PGF_API_DECL -void pgf_free(PgfDB *pgf); - +/* Release a revision. If this is the last revision for the given + * database, then the database is released as well. */ PGF_API_DECL void pgf_free_revision(PgfDB *pgf, PgfRevision revision); diff --git a/src/runtime/haskell/PGF2.hsc b/src/runtime/haskell/PGF2.hsc index 57083d4b8..2af222f92 100644 --- a/src/runtime/haskell/PGF2.hsc +++ b/src/runtime/haskell/PGF2.hsc @@ -112,11 +112,10 @@ readPGF fpath = withCString fpath $ \c_fpath -> alloca $ \p_revision -> 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 - fptr1 <- newForeignPtr pgf_free_fptr c_pgf - fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision)) - return (PGF fptr1 fptr2 Map.empty) + fptr <- C.newForeignPtr c_revision (pgf_free_revision c_db c_revision) + return (PGF c_db fptr Map.empty) -- | 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. @@ -128,11 +127,10 @@ bootNGF pgf_path ngf_path = withCString ngf_path $ \c_ngf_path -> alloca $ \p_revision -> 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 - fptr1 <- newForeignPtr pgf_free_fptr c_pgf - fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision)) - return (PGF fptr1 fptr2 Map.empty) + fptr <- C.newForeignPtr c_revision (pgf_free_revision c_db c_revision) + return (PGF c_db fptr Map.empty) -- | Reads the grammar from an already booted NGF file. -- The function fails if the file does not exist. @@ -143,9 +141,8 @@ readNGF fpath = mask_ $ do c_db <- withPgfExn "readNGF" (pgf_read_ngf c_fpath p_revision) c_revision <- peek p_revision - fptr1 <- newForeignPtr pgf_free_fptr c_db - fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision)) - return (PGF fptr1 fptr2 Map.empty) + fptr <- C.newForeignPtr c_revision (pgf_free_revision c_db c_revision) + return (PGF c_db fptr Map.empty) -- | 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 @@ -159,16 +156,14 @@ newNGF abs_name mb_fpath = mask_ $ do c_db <- withPgfExn "newNGF" (pgf_new_ngf c_abs_name c_fpath p_revision) c_revision <- peek p_revision - fptr1 <- newForeignPtr pgf_free_fptr c_db - fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision)) - return (PGF fptr1 fptr2 Map.empty) + fptr <- C.newForeignPtr c_revision (pgf_free_revision c_db c_revision) + return (PGF c_db fptr Map.empty) writePGF :: FilePath -> PGF -> IO () writePGF fpath p = withCString fpath $ \c_fpath -> - withForeignPtr (a_db p) $ \c_db -> 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 = error "TODO: showPGF" @@ -178,9 +173,8 @@ showPGF = error "TODO: showPGF" abstractName :: PGF -> AbsName abstractName p = unsafePerformIO $ - withForeignPtr (a_db p) $ \c_db -> 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 -- | The start category is defined in the grammar with @@ -192,9 +186,8 @@ startCat :: PGF -> Type startCat p = unsafePerformIO $ withForeignPtr unmarshaller $ \u -> - withForeignPtr (a_db p) $ \c_db -> 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 freeStablePtr c_typ return typ @@ -204,10 +197,9 @@ functionType :: PGF -> Fun -> Maybe Type functionType p fn = unsafePerformIO $ withForeignPtr unmarshaller $ \u -> - withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> 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 then return Nothing else do typ <- deRefStablePtr c_typ @@ -218,27 +210,24 @@ functionIsConstructor :: PGF -> Fun -> Bool functionIsConstructor p fun = unsafePerformIO $ withText fun $ \c_fun -> - withForeignPtr (a_db p) $ \c_db -> 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) functionProbability :: PGF -> Fun -> Float functionProbability p fun = unsafePerformIO $ withText fun $ \c_fun -> - withForeignPtr (a_db p) $ \c_db -> 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 p e = unsafePerformIO $ - withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> bracket (newStablePtr e) freeStablePtr $ \c_e -> 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 = error "TODO: checkExpr" @@ -503,10 +492,9 @@ categories p = ref <- newIORef [] (allocaBytes (#size PgfItor) $ \itor -> bracket (wrapItorCallback (getCategories ref)) freeHaskellFunPtr $ \fptr -> - withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> do (#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 return (reverse cs)) where @@ -522,10 +510,9 @@ categoryContext p cat = withText cat $ \c_cat -> alloca $ \p_n_hypos -> withForeignPtr unmarshaller $ \u -> - withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> 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 then return Nothing else do n_hypos <- peek p_n_hypos @@ -550,9 +537,8 @@ categoryProbability :: PGF -> Cat -> Float categoryProbability p cat = unsafePerformIO $ withText cat $ \c_cat -> - withForeignPtr (a_db p) $ \c_db -> 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 functions :: PGF -> [Fun] @@ -561,10 +547,9 @@ functions p = ref <- newIORef [] (allocaBytes (#size PgfItor) $ \itor -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> - withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> do (#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 return (reverse fs)) where @@ -582,10 +567,9 @@ functionsByCat p cat = (withText cat $ \c_cat -> allocaBytes (#size PgfItor) $ \itor -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> - withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> do (#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 return (reverse fs)) where @@ -599,10 +583,9 @@ globalFlag :: PGF -> String -> Maybe Literal globalFlag p name = unsafePerformIO $ withText name $ \c_name -> - withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> 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 then return Nothing else do lit <- deRefStablePtr c_lit @@ -613,10 +596,9 @@ abstractFlag :: PGF -> String -> Maybe Literal abstractFlag p name = unsafePerformIO $ withText name $ \c_name -> - withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> 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 then return Nothing else do lit <- deRefStablePtr c_lit diff --git a/src/runtime/haskell/PGF2/FFI.hsc b/src/runtime/haskell/PGF2/FFI.hsc index 3e229597b..76caeec29 100644 --- a/src/runtime/haskell/PGF2/FFI.hsc +++ b/src/runtime/haskell/PGF2/FFI.hsc @@ -23,11 +23,11 @@ type ConcName = String -- ^ Name of concrete syntax -- | An abstract data type representing multilingual grammar -- in Portable Grammar Format. -data PGF = PGF { a_db :: ForeignPtr PgfDB +data PGF = PGF { a_db :: Ptr PgfDB , revision :: ForeignPtr PgfRevision , 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 @@ -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_free" - pgf_free_fptr :: FinalizerPtr PgfDB - foreign import ccall "pgf_free_revision" pgf_free_revision :: Ptr PgfDB -> Ptr PgfRevision -> IO () diff --git a/src/runtime/haskell/PGF2/Transactions.hsc b/src/runtime/haskell/PGF2/Transactions.hsc index 2231e360f..a3f4df371 100644 --- a/src/runtime/haskell/PGF2/Transactions.hsc +++ b/src/runtime/haskell/PGF2/Transactions.hsc @@ -73,41 +73,39 @@ branchPGF p name t = branchPGF_ :: Ptr PgfText -> PGF -> Transaction a -> IO PGF branchPGF_ c_name p (Transaction f) = - withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> withPgfExn "branchPGF" $ \c_exn -> 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 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` (\e -> do - pgf_free_revision c_db c_revision + pgf_free_revision (a_db p) c_revision throwIO (e :: SomeException))) ex_type <- (#peek PgfExn, type) c_exn 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 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)) - return (PGF (a_db p) fptr2 (languages p)) - else do 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) fptr (languages p)) + else do pgf_free_revision (a_db p) c_revision return p - else do pgf_free_revision c_db c_revision + else do pgf_free_revision (a_db p) c_revision return p else return p {- | Retrieves the branch with the given name -} checkoutPGF :: PGF -> String -> IO (Maybe PGF) checkoutPGF p name = - withForeignPtr (a_db p) $ \c_db -> 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 then return Nothing - else do fptr2 <- C.newForeignPtr c_revision (withForeignPtr (a_db p) (\c_db -> pgf_free_revision c_db c_revision)) - return (Just (PGF (a_db p) fptr2 (languages p))) + else do fptr <- C.newForeignPtr c_revision (pgf_free_revision (a_db p) c_revision) + return (Just (PGF (a_db p) fptr (languages p))) createFunction :: Fun -> Type -> Int -> Float -> Transaction () createFunction name ty arity prob = Transaction $ \c_db c_revision c_exn -> diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c index 6f2d7d7cd..dbf15ee7e 100644 --- a/src/runtime/python/pypgf.c +++ b/src/runtime/python/pypgf.c @@ -13,7 +13,7 @@ static void PGF_dealloc(PGFObject *self) { - pgf_free(self->db); + pgf_free_revision(self->db, self->revision); Py_TYPE(self)->tp_free((PyObject *)self); } From dd65f9f365d222cb1e548aafe23ccfae3b7cc295 Mon Sep 17 00:00:00 2001 From: krangelov Date: Wed, 22 Sep 2021 13:44:03 +0200 Subject: [PATCH 15/17] a better way to handle double releases --- src/runtime/c/pgf/expr.cxx | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/runtime/c/pgf/expr.cxx b/src/runtime/c/pgf/expr.cxx index fbcbd2810..3bffc4713 100644 --- a/src/runtime/c/pgf/expr.cxx +++ b/src/runtime/c/pgf/expr.cxx @@ -812,9 +812,6 @@ PgfType PgfExprParser::parse_type() size_t n_hypos = 0; PgfTypeHypo *hypos = NULL; - size_t n_types = 0; - PgfType *types = NULL; - PgfText *cat = NULL; size_t n_args = 0; @@ -854,9 +851,6 @@ PgfType PgfExprParser::parse_type() if (type == 0) goto exit; - types = (PgfType*) realloc(types, sizeof(PgfType)*(n_types+1)); - types[n_types++] = type; - if (token_tag != PGF_TOKEN_RPAR) goto exit; @@ -897,9 +891,6 @@ PgfType PgfExprParser::parse_type() bt->type = u->dtyp(0,NULL,cat,n_args,args); n_hypos++; - types = (PgfType*) realloc(types, sizeof(PgfType)*(n_types+1)); - types[n_types++] = bt->type; - while (n_args > 0) { u->free_ref(args[--n_args]); } @@ -916,18 +907,17 @@ PgfType PgfExprParser::parse_type() type = u->dtyp(n_hypos,hypos,cat,n_args,args); exit: + PgfType last_type = 0; while (n_hypos > 0) { PgfTypeHypo *hypo = &hypos[--n_hypos]; free(hypo->cid); + if (hypo->type != last_type) { + u->free_ref(hypo->type); + last_type = hypo->type; + } } free(hypos); - while (n_types > 0) { - PgfType type = types[--n_types]; - u->free_ref(type); - } - free(types); - free(cat); while (n_args > 0) { From 063c517f3c99aa34ebf5ce25a97d85bb05d7abe4 Mon Sep 17 00:00:00 2001 From: krangelov Date: Wed, 22 Sep 2021 14:11:11 +0200 Subject: [PATCH 16/17] more tests for variants --- testsuite/compiler/compute/Variants.gfs | 10 ++++++++++ testsuite/compiler/compute/Variants.gfs.gold | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/testsuite/compiler/compute/Variants.gfs b/testsuite/compiler/compute/Variants.gfs index 1f512694c..f65427e88 100644 --- a/testsuite/compiler/compute/Variants.gfs +++ b/testsuite/compiler/compute/Variants.gfs @@ -1,2 +1,12 @@ i -retain testsuite/compiler/compute/Variants.gf 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 +cc +cc +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"> diff --git a/testsuite/compiler/compute/Variants.gfs.gold b/testsuite/compiler/compute/Variants.gfs.gold index cd74b1c23..50af5e513 100644 --- a/testsuite/compiler/compute/Variants.gfs.gold +++ b/testsuite/compiler/compute/Variants.gfs.gold @@ -1 +1,11 @@ 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" From bcbf9efa5f71348591da383f7ab679c237adbeca Mon Sep 17 00:00:00 2001 From: krangelov Date: Wed, 22 Sep 2021 14:44:56 +0200 Subject: [PATCH 17/17] started a page about transactions --- src/runtime/c/doc/README.md | 1 + src/runtime/c/doc/transactions.md | 0 2 files changed, 1 insertion(+) create mode 100644 src/runtime/c/doc/transactions.md diff --git a/src/runtime/c/doc/README.md b/src/runtime/c/doc/README.md index 7c11b755c..7940f51f5 100644 --- a/src/runtime/c/doc/README.md +++ b/src/runtime/c/doc/README.md @@ -12,3 +12,4 @@ So, **Don't Panic!** and keep reading. This is a live document and will develop 1. [Desiderata](DESIDERATA.md) 2. [Memory Model](memory_model.md) 3. [Abstract Expressions](abstract_expressions.md) +3. [Transactions](transactions.md) diff --git a/src/runtime/c/doc/transactions.md b/src/runtime/c/doc/transactions.md new file mode 100644 index 000000000..e69de29bb