52 Commits

Author SHA1 Message Date
Andreas Källberg
8814fde817 Only run the script once per release 2021-07-25 09:30:36 +08:00
Andreas Källberg
375b3cf285 Update release script to build for two ubuntu versions 2021-07-25 08:23:25 +08:00
Andreas Källberg
3c4f42db15 Build ubuntu packages on ubuntu-latest
Fixes #74
2021-07-25 08:23:25 +08:00
John J. Camilleri
0474a37af6 Make Makefile compatible with stack and old/new cabal (with v1- prefix when necessary) 2021-07-25 08:23:25 +08:00
Andreas Källberg
e3498d5ead Update to newest haskell github action
Also fix so the stack builds use the correct ghc versions
2021-07-25 08:23:25 +08:00
Andreas Källberg
4c5927c98c Update scripts to use cabal v1-... so they work on newer cabal
Fixes build failures like https://github.com/GrammaticalFramework/gf-core/runs/2949099280?check_suite_focus=true
2021-07-25 08:23:25 +08:00
John J. Camilleri
bb51224e8e IRC link pre-fills channel. Link to logs gives newest first. 2021-07-23 16:07:34 +02:00
John J. Camilleri
9533edc3ca Merge pull request #128 from GrammaticalFramework/windows-binary
Fixes to building Windows binary
2021-07-23 15:55:37 +02:00
John J. Camilleri
4df8999ed5 Change Python 3.8 to 3.9 2021-07-23 08:05:35 +02:00
John J. Camilleri
7fdbf3f400 Update path in main workflow for binaries 2021-07-22 23:11:01 +02:00
John J. Camilleri
0d6c67f6b1 Try without rewriting envvar 2021-07-22 23:02:22 +02:00
John J. Camilleri
2610219f6a Update path 2021-07-22 22:56:39 +02:00
John J. Camilleri
7674f078d6 Try another path 2021-07-22 22:49:44 +02:00
John J. Camilleri
c67fe05c08 Narrow search, print env var 2021-07-22 22:44:53 +02:00
John J. Camilleri
7b9bb780a2 Find Java stuff 2021-07-22 22:34:26 +02:00
John J. Camilleri
4f256447e2 Add separate Windows binary CI action for easier testing 2021-07-22 22:27:15 +02:00
Inari Listenmaa
dfa5b9276d #gf IRC channel has moved to Libera 2021-07-22 01:08:00 +02:00
Inari Listenmaa
667bfd30bd Merge pull request #87 from anka-213/make-it-fast
Remove the `Either Int` from value2term
2021-07-20 04:35:37 +02:00
Inari Listenmaa
66ae31e99e Merge pull request #126 from inariksit/developers-documentation
Update developers' documentation
2021-07-15 05:16:55 +02:00
Inari Listenmaa
a677f0373c General restructuring, various minor changes 2021-07-15 10:40:26 +08:00
Inari Listenmaa
13f845d127 Update C runtime instructions 2021-07-15 10:39:54 +08:00
Inari Listenmaa
aa530233fb Remove instructions to create binaries
Those are in github actions
2021-07-15 10:27:57 +08:00
Inari Listenmaa
45bc5595c0 Update C runtime install instructions 2021-07-15 09:54:15 +08:00
Inari Listenmaa
6d12754e4f Split the Cabal instructions to another page
and link from main instructions
2021-07-15 08:21:29 +08:00
1Regina
a09d9bd006 install and upgrade stack 2021-07-14 17:20:20 +08:00
Meowyam
fffe3161d4 updated docs to reflect binaries generated via github actions
fix merge conflicts

resolve merge conflict
2021-07-14 17:20:20 +08:00
Meowyam
743f5e55d4 add missing install.sh file for c runtime 2021-07-14 17:20:20 +08:00
Inari Listenmaa
9e209bbaba Changes in Git instructions 2021-07-14 17:20:07 +08:00
Inari Listenmaa
a1594e6a69 updated doc with instructions for C runtime for ubuntu and fedora 2021-07-14 16:44:44 +08:00
Inari Listenmaa
06e0a986d1 Changes in Git instructions 2021-07-14 16:12:11 +08:00
Meowyam
6f2a4bcd2c update doc for linux installation 2021-07-14 15:32:02 +08:00
Inari Listenmaa
f345f615f4 Update information about test suite
Co-Authored-By: 1Regina <46968488+1Regina@users.noreply.github.com>
2021-07-14 15:16:23 +08:00
Inari Listenmaa
80d16fcf94 Update instructions about C runtime 2021-07-14 15:03:59 +08:00
Andreas Källberg
7faf8c9dad Clean up redundant case expressions 2021-07-12 16:38:29 +08:00
Andreas Källberg
c2ffa6763b Github actions: Fix build for stack 2021-07-12 15:53:49 +08:00
Andreas Källberg
b3881570c7 Remove last traces of the Either in value2term 2021-07-12 15:53:49 +08:00
Andreas Källberg
bd270b05ff Remove the Either Int from value2term
This prevents HUGE space leak and makes compiling a PGF a LOT faster

For example, an application grammar moved from taking over 50GB
of ram and taking 5 minutes (most of which is spent on garbage colelction)
to taking 1.2 seconds and using 42mb of memory

The price we pay is that the "variable #n is out of scope" error is now
lazy and will happen when we try to evaluate the term instead of
happening when the function returns and allowing the caller to chose how
to handle the error.
I don't think this should matter in practice, since it's very rare;
at least Inari has never encountered it.
2021-07-12 15:50:43 +08:00
John J. Camilleri
a1fd3ea142 Fix bug introduced in cdbe73eb47
Apparently I don't understand how pattern-matching works in Haskell
2021-07-08 13:56:58 +02:00
John J. Camilleri
cdbe73eb47 Remove two missing-methods warnings 2021-07-08 12:10:41 +02:00
John J. Camilleri
6077d5dd5b Merge pull request #124 from GrammaticalFramework/cabal-cleanup
More cabal file cleanup
2021-07-08 08:56:31 +02:00
John J. Camilleri
0954b4cbab More cabal file cleanup. Remove some more tabs from Haskell source. 2021-07-07 13:04:09 +02:00
John J. Camilleri
f2e52d6f2c Replace tabs for whitespace in source code 2021-07-07 09:40:41 +02:00
John J. Camilleri
a2b23d5897 Make whitespace uniform in Cabal files, add a few more dependency bounds 2021-07-07 09:11:46 +02:00
John J. Camilleri
0886eb520d Update 3.11 release notes 2021-07-06 15:45:21 +02:00
John J. Camilleri
ef42216415 Add import from command line invocation to command history
Closes #64
2021-07-06 15:35:03 +02:00
John J. Camilleri
0c3ca3d79a Add note in PGF2 documentation about risk for integer overflow.
Closes #109
2021-07-06 14:43:21 +02:00
John J. Camilleri
e2e5033075 Merge pull request #122 from 2jacobtan/master
specify version bounds in *.cabal files
2021-07-06 14:31:29 +02:00
John J. Camilleri
84b4b6fab9 Some more cabal file cleanup. Add stack files for pgf, pgf2. 2021-07-06 14:11:30 +02:00
Inari Listenmaa
5e052ff499 Merge pull request #119 from GrammaticalFramework/concrete-new
Clean up Compute.ConcreteNew and TypeCheck.RConcrete
2021-07-06 14:05:00 +02:00
2jacobtan
e1a40640cd specify version bounds in pgf.cabal and pgf2.cabal 2021-07-06 05:42:34 +08:00
2jacobtan
be231584f6 set stack.yaml to lts-18.0 2021-07-06 05:20:09 +08:00
2jacobtan
12c564f97c specify version bounds in gf.cabal 2021-07-06 05:08:00 +08:00
60 changed files with 1602 additions and 1418 deletions

View File

@@ -14,7 +14,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
cabal: ["3.2"] cabal: ["latest"]
ghc: ghc:
- "8.6.5" - "8.6.5"
- "8.8.3" - "8.8.3"
@@ -33,7 +33,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master' if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'
- uses: actions/setup-haskell@v1.1.4 - uses: haskell/actions/setup@v1
id: setup-haskell-cabal id: setup-haskell-cabal
name: Setup Haskell name: Setup Haskell
with: with:
@@ -65,7 +65,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
stack: ["2.3.3"] stack: ["latest"]
ghc: ["7.10.3","8.0.2", "8.2.2", "8.4.4", "8.6.5", "8.8.4"] ghc: ["7.10.3","8.0.2", "8.2.2", "8.4.4", "8.6.5", "8.8.4"]
# ghc: ["8.8.3"] # ghc: ["8.8.3"]
@@ -73,11 +73,12 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master' if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'
- uses: actions/setup-haskell@v1.1.4 - uses: haskell/actions/setup@v1
name: Setup Haskell Stack name: Setup Haskell Stack
with: with:
# ghc-version: ${{ matrix.ghc }} ghc-version: ${{ matrix.ghc }}
stack-version: ${{ matrix.stack }} stack-version: 'latest'
enable-stack: true
- uses: actions/cache@v1 - uses: actions/cache@v1
name: Cache ~/.stack name: Cache ~/.stack

View File

@@ -2,7 +2,8 @@ name: Build Binary Packages
on: on:
workflow_dispatch: workflow_dispatch:
release: release:
types: ["created"]
jobs: jobs:
@@ -10,11 +11,13 @@ jobs:
ubuntu: ubuntu:
name: Build Ubuntu package name: Build Ubuntu package
runs-on: ubuntu-18.04 strategy:
# strategy: matrix:
# matrix: os:
# ghc: ["8.6.5"] - ubuntu-18.04
# cabal: ["2.4"] - ubuntu-20.04
runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -53,7 +56,7 @@ jobs:
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: gf-${{ github.sha }}-ubuntu name: gf-${{ github.sha }}-${{ matrix.os }}
path: dist/gf_*.deb path: dist/gf_*.deb
if-no-files-found: error if-no-files-found: error
@@ -136,16 +139,18 @@ jobs:
cp /mingw64/bin/libpgf-0.dll /c/tmp-dist/c cp /mingw64/bin/libpgf-0.dll /c/tmp-dist/c
cp /mingw64/bin/libgu-0.dll /c/tmp-dist/c cp /mingw64/bin/libgu-0.dll /c/tmp-dist/c
# JAVA_HOME_8_X64 = C:\hostedtoolcache\windows\Java_Adopt_jdk\8.0.292-10\x64
- name: Build Java bindings - name: Build Java bindings
shell: msys2 {0} shell: msys2 {0}
run: | run: |
export PATH="${PATH}:/c/Program Files/Java/jdk8u275-b01/bin" export JDKPATH=/c/hostedtoolcache/windows/Java_Adopt_jdk/8.0.292-10/x64
export PATH="${PATH}:${JDKPATH}/bin"
cd src/runtime/java cd src/runtime/java
make \ make \
JNI_INCLUDES="-I \"/c/Program Files/Java/jdk8u275-b01/include\" -I \"/c/Program Files/Java/jdk8u275-b01/include/win32\" -I \"/mingw64/include\" -D__int64=int64_t" \ JNI_INCLUDES="-I \"${JDKPATH}/include\" -I \"${JDKPATH}/include/win32\" -I \"/mingw64/include\" -D__int64=int64_t" \
WINDOWS_LDFLAGS="-L\"/mingw64/lib\" -no-undefined" WINDOWS_LDFLAGS="-L\"/mingw64/lib\" -no-undefined"
make install make install
cp .libs//msys-jpgf-0.dll /c/tmp-dist/java/jpgf.dll cp .libs/msys-jpgf-0.dll /c/tmp-dist/java/jpgf.dll
cp jpgf.jar /c/tmp-dist/java cp jpgf.jar /c/tmp-dist/java
- name: Build Python bindings - name: Build Python bindings
@@ -157,7 +162,7 @@ jobs:
cd src/runtime/python cd src/runtime/python
python setup.py build python setup.py build
python setup.py install python setup.py install
cp /usr/lib/python3.8/site-packages/pgf* /c/tmp-dist/python cp /usr/lib/python3.9/site-packages/pgf* /c/tmp-dist/python
- name: Setup Haskell - name: Setup Haskell
uses: actions/setup-haskell@v1 uses: actions/setup-haskell@v1

View File

@@ -1,31 +1,48 @@
.PHONY: all build install doc clean gf html deb pkg bintar sdist .PHONY: all build install doc clean html deb pkg bintar sdist
# This gets the numeric part of the version from the cabal file # This gets the numeric part of the version from the cabal file
VERSION=$(shell sed -ne "s/^version: *\([0-9.]*\).*/\1/p" gf.cabal) VERSION=$(shell sed -ne "s/^version: *\([0-9.]*\).*/\1/p" gf.cabal)
# Check if stack is installed
STACK=$(shell if hash stack 2>/dev/null; then echo "1"; else echo "0"; fi)
# Check if cabal >= 2.4 is installed (with v1- and v2- commands)
CABAL_NEW=$(shell if cabal v1-repl --help >/dev/null 2>&1 ; then echo "1"; else echo "0"; fi)
ifeq ($(STACK),1)
CMD=stack
else
CMD=cabal
ifeq ($(CABAL_NEW),1)
CMD_PFX=v1-
endif
endif
all: build all: build
dist/setup-config: gf.cabal Setup.hs WebSetup.hs dist/setup-config: gf.cabal Setup.hs WebSetup.hs
cabal configure ifneq ($(STACK),1)
cabal ${CMD_PFX}configure
endif
build: dist/setup-config build: dist/setup-config
cabal build ${CMD} ${CMD_PFX}build
install: install:
cabal copy ifeq ($(STACK),1)
cabal register stack install
else
cabal ${CMD_PFX}copy
cabal ${CMD_PFX}register
endif
doc: doc:
cabal haddock ${CMD} ${CMD_PFX}haddock
clean: clean:
cabal clean ${CMD} ${CMD_PFX}clean
bash bin/clean_html bash bin/clean_html
gf:
cabal build rgl-none
strip dist/build/gf/gf
html:: html::
bash bin/update_html bash bin/update_html
@@ -35,7 +52,7 @@ html::
deb: deb:
dpkg-buildpackage -b -uc dpkg-buildpackage -b -uc
# Make an OS X Installer package # Make a macOS installer package
pkg: pkg:
FMT=pkg bash bin/build-binary-dist.sh FMT=pkg bash bin/build-binary-dist.sh

10
debian/rules vendored
View File

@@ -16,9 +16,9 @@ override_dh_shlibdeps:
override_dh_auto_configure: override_dh_auto_configure:
cd src/runtime/c && bash setup.sh configure --prefix=/usr cd src/runtime/c && bash setup.sh configure --prefix=/usr
cd src/runtime/c && bash setup.sh build cd src/runtime/c && bash setup.sh build
cabal update cabal v1-update
cabal install --only-dependencies cabal v1-install --only-dependencies
cabal configure --prefix=/usr -fserver -fc-runtime --extra-lib-dirs=$(CURDIR)/src/runtime/c/.libs --extra-include-dirs=$(CURDIR)/src/runtime/c cabal v1-configure --prefix=/usr -fserver -fc-runtime --extra-lib-dirs=$(CURDIR)/src/runtime/c/.libs --extra-include-dirs=$(CURDIR)/src/runtime/c
SET_LDL=LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(CURDIR)/src/runtime/c/.libs SET_LDL=LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(CURDIR)/src/runtime/c/.libs
@@ -26,10 +26,10 @@ override_dh_auto_build:
cd src/runtime/python && EXTRA_INCLUDE_DIRS=$(CURDIR)/src/runtime/c EXTRA_LIB_DIRS=$(CURDIR)/src/runtime/c/.libs python setup.py build cd src/runtime/python && EXTRA_INCLUDE_DIRS=$(CURDIR)/src/runtime/c EXTRA_LIB_DIRS=$(CURDIR)/src/runtime/c/.libs python setup.py build
cd src/runtime/java && make CFLAGS="-I$(CURDIR)/src/runtime/c -L$(CURDIR)/src/runtime/c/.libs" INSTALL_PATH=/usr cd src/runtime/java && make CFLAGS="-I$(CURDIR)/src/runtime/c -L$(CURDIR)/src/runtime/c/.libs" INSTALL_PATH=/usr
echo $(SET_LDL) echo $(SET_LDL)
-$(SET_LDL) cabal build -$(SET_LDL) cabal v1-build
override_dh_auto_install: override_dh_auto_install:
$(SET_LDL) cabal copy --destdir=$(CURDIR)/debian/gf $(SET_LDL) cabal v1-copy --destdir=$(CURDIR)/debian/gf
cd src/runtime/c && bash setup.sh copy prefix=$(CURDIR)/debian/gf/usr cd src/runtime/c && bash setup.sh copy prefix=$(CURDIR)/debian/gf/usr
cd src/runtime/python && python setup.py install --prefix=$(CURDIR)/debian/gf/usr cd src/runtime/python && python setup.py install --prefix=$(CURDIR)/debian/gf/usr
cd src/runtime/java && make INSTALL_PATH=$(CURDIR)/debian/gf/usr install cd src/runtime/java && make INSTALL_PATH=$(CURDIR)/debian/gf/usr install

View File

@@ -0,0 +1,201 @@
GF Developer's Guide: Old installation instructions with Cabal
This page contains the old installation instructions from the [Developer's Guide ../doc/gf-developers.html].
We recommend Stack as a primary installation method, because it's easier for a Haskell beginner, and we want to keep the main instructions short.
But if you are an experienced Haskeller and want to keep using Cabal, here are the old instructions using ``cabal install``.
Note that some of these instructions may be outdated. Other parts may still be useful.
== Compilation from source with Cabal ==
The build system of GF is based on //Cabal//, which is part of the
Haskell Platform, so no extra steps are needed to install it. In the simplest
case, all you need to do to compile and install GF, after downloading the
source code as described above, is
```
$ cabal install
```
This will automatically download any additional Haskell libraries needed to
build GF. If this is the first time you use Cabal, you might need to run
``cabal update`` first, to update the list of available libraries.
If you want more control, the process can also be split up into the usual
//configure//, //build// and //install// steps.
=== Configure ===
During the configuration phase Cabal will check that you have all
necessary tools and libraries needed for GF. The configuration is
started by the command:
```
$ cabal configure
```
If you don't see any error message from the above command then you
have everything that is needed for GF. You can also add the option
``-v`` to see more details about the configuration.
You can use ``cabal configure --help`` to get a list of configuration options.
=== Build ===
The build phase does two things. First it builds the GF compiler from
the Haskell source code and after that it builds the GF Resource Grammar
Library using the already build compiler. The simplest command is:
```
$ cabal build
```
Again you can add the option ``-v`` if you want to see more details.
==== Parallel builds ====
If you have Cabal>=1.20 you can enable parallel compilation by using
```
$ cabal build -j
```
or by putting a line
```
jobs: $ncpus
```
in your ``.cabal/config`` file. Cabal
will pass this option to GHC when building the GF compiler, if you
have GHC>=7.8.
Cabal also passes ``-j`` to GF to enable parallel compilation of the
Resource Grammar Library. This is done unconditionally to avoid
causing problems for developers with Cabal<1.20. You can disable this
by editing the last few lines in ``WebSetup.hs``.
=== Install ===
After you have compiled GF you need to install the executable and libraries
to make the system usable.
```
$ cabal copy
$ cabal register
```
This command installs the GF compiler for a single user, in the standard
place used by Cabal.
On Linux and Mac this could be ``$HOME/.cabal/bin``.
On Mac it could also be ``$HOME/Library/Haskell/bin``.
On Windows this is ``C:\Program Files\Haskell\bin``.
The compiled GF Resource Grammar Library will be installed
under the same prefix, e.g. in
``$HOME/.cabal/share/gf-3.3.3/lib`` on Linux and
in ``C:\Program Files\Haskell\gf-3.3.3\lib`` on Windows.
If you want to install in some other place then use the ``--prefix``
option during the configuration phase.
=== Clean ===
Sometimes you want to clean up the compilation and start again from clean
sources. Use the clean command for this purpose:
```
$ cabal clean
```
%=== SDist ===
%
%You can use the command:
%
%% This does *NOT* include everything that is needed // TH 2012-08-06
%```
%$ cabal sdist
%```
%
%to prepare archive with all source codes needed to compile GF.
=== Known problems with Cabal ===
Some versions of Cabal (at least version 1.16) seem to have a bug that can
cause the following error:
```
Configuring gf-3.x...
setup: Distribution/Simple/PackageIndex.hs:124:8-13: Assertion failed
```
The exact cause of this problem is unclear, but it seems to happen
during the configure phase if the same version of GF is already installed,
so a workaround is to remove the existing installation with
```
ghc-pkg unregister gf
```
You can check with ``ghc-pkg list gf`` that it is gone.
== Compilation with make ==
If you feel more comfortable with Makefiles then there is a thin Makefile
wrapper arround Cabal for you. If you just type:
```
$ make
```
the configuration phase will be run automatically if needed and after that
the sources will be compiled.
%% cabal build rgl-none does not work with recent versions of Cabal
%If you don't want to compile the resource library
%every time then you can use:
%```
%$ make gf
%```
For installation use:
```
$ make install
```
For cleaning:
```
$ make clean
```
%and to build source distribution archive run:
%```
%$ make sdist
%```
== Partial builds of RGL ==
**NOTE**: The following doesn't work with recent versions of ``cabal``. //(This comment was left in 2015, so make your own conclusions.)//
%% // TH 2015-06-22
%Sometimes you just want to work on the GF compiler and don't want to
%recompile the resource library after each change. In this case use
%this extended command:
%```
%$ cabal build rgl-none
%```
The resource grammar library can be compiled in two modes: with present
tense only and with all tenses. By default it is compiled with all
tenses. If you want to use the library with only present tense you can
compile it in this special mode with the command:
```
$ cabal build present
```
You could also control which languages you want to be recompiled by
adding the option ``langs=list``. For example the following command
will compile only the English and the Swedish language:
```
$ cabal build langs=Eng,Swe
```

View File

@@ -1,6 +1,6 @@
GF Developers Guide GF Developers Guide
2018-07-26 2021-07-15
%!options(html): --toc %!options(html): --toc
@@ -15,388 +15,287 @@ you are a GF user who just wants to download and install GF
== Setting up your system for building GF == == Setting up your system for building GF ==
To build GF from source you need to install some tools on your To build GF from source you need to install some tools on your
system: the //Haskell Platform//, //Git// and the //Haskeline library//. system: the Haskell build tool //Stack//, the version control software //Git// and the //Haskeline// library.
**On Linux** the best option is to install the tools via the standard %**On Linux** the best option is to install the tools via the standard
software distribution channels, i.e. by using the //Software Center// %software distribution channels, i.e. by using the //Software Center//
in Ubuntu or the corresponding tool in other popular Linux distributions. %in Ubuntu or the corresponding tool in other popular Linux distributions.
Or, from a Terminal window, the following command should be enough:
- On Ubuntu: ``sudo apt-get install haskell-platform git libghc6-haskeline-dev`` %**On Mac OS and Windows**, the tools can be downloaded from their respective
- On Fedora: ``sudo dnf install haskell-platform git ghc-haskeline-devel`` %web sites, as described below.
=== Stack ===
The primary installation method is via //Stack//.
(You can also use Cabal, but we recommend Stack to those who are new to Haskell.)
To install Stack:
- **On Linux and Mac OS**, do either
``$ curl -sSL https://get.haskellstack.org/ | sh``
or
``$ wget -qO- https://get.haskellstack.org/ | sh``
**On Mac OS and Windows**, the tools can be downloaded from their respective - **On other operating systems**, see the [installation guide https://docs.haskellstack.org/en/stable/install_and_upgrade].
web sites, as described below.
=== The Haskell Platform ===
GF is written in Haskell, so first of all you need %If you already have Stack installed, upgrade it to the latest version by running: ``stack upgrade``
the //Haskell Platform//, e.g. version 8.0.2 or 7.10.3. Downloads
and installation instructions are available from here:
http://hackage.haskell.org/platform/
Once you have installed the Haskell Platform, open a terminal
(Command Prompt on Windows) and try to execute the following command:
```
$ ghc --version
```
This command should show you which version of GHC you have. If the installation
of the Haskell Platform was successful you should see a message like:
```
The Glorious Glasgow Haskell Compilation System, version 8.0.2
```
Other required tools included in the Haskell Platform are
[Cabal http://www.haskell.org/cabal/],
[Alex http://www.haskell.org/alex/]
and
[Happy http://www.haskell.org/happy/].
=== Git === === Git ===
To get the GF source code, you also need //Git//. To get the GF source code, you also need //Git//, a distributed version control system.
//Git// is a distributed version control system, see
https://git-scm.com/downloads for more information.
=== The haskeline library === - **On Linux**, the best option is to install the tools via the standard
software distribution channels:
- On Ubuntu: ``sudo apt-get install git-all``
- On Fedora: ``sudo dnf install git-all``
- **On other operating systems**, see
https://git-scm.com/book/en/v2/Getting-Started-Installing-Git for installation.
=== Haskeline ===
GF uses //haskeline// to enable command line editing in the GF shell. GF uses //haskeline// to enable command line editing in the GF shell.
This should work automatically on Mac OS and Windows, but on Linux one
extra step is needed to make sure the C libraries (terminfo)
required by //haskeline// are installed. Here is one way to do this:
- On Ubuntu: ``sudo apt-get install libghc-haskeline-dev`` - **On Mac OS and Windows**, this should work automatically.
- On Fedora: ``sudo dnf install ghc-haskeline-devel``
- **On Linux**, an extra step is needed to make sure the C libraries (terminfo)
required by //haskeline// are installed:
- On Ubuntu: ``sudo apt-get install libghc-haskeline-dev``
- On Fedora: ``sudo dnf install ghc-haskeline-devel``
== Getting the source == == Getting the source ==[getting-source]
Once you have all tools in place you can get the GF source code. If you Once you have all tools in place you can get the GF source code from
just want to compile and use GF then it is enough to have read-only [GitHub https://github.com/GrammaticalFramework/]:
access. It is also possible to make changes in the source code but if you
want these changes to be applied back to the main source repository you will
have to send the changes to us. If you plan to work continuously on
GF then you should consider getting read-write access.
=== Read-only access === - https://github.com/GrammaticalFramework/gf-core for the GF compiler
- https://github.com/GrammaticalFramework/gf-rgl for the Resource Grammar Library
==== Getting a fresh copy for read-only access ====
Anyone can get the latest development version of GF by running: === Read-only access: clone the main repository ===
If you only want to compile and use GF, you can just clone the repositories as follows:
``` ```
$ git clone https://github.com/GrammaticalFramework/gf-core.git $ git clone https://github.com/GrammaticalFramework/gf-core.git
$ git clone https://github.com/GrammaticalFramework/gf-rgl.git $ git clone https://github.com/GrammaticalFramework/gf-rgl.git
``` ```
This will create directories ``gf-core`` and ``gf-rgl`` in the current directory. To get new updates, run the following anywhere in your local copy of the repository:
==== Updating your copy ====
To get all new patches from each repo:
```
$ git pull
```
This can be done anywhere in your local repository.
==== Recording local changes ====[record]
Since every copy is a repository, you can have local version control
of your changes.
If you have added files, you first need to tell your local repository to
keep them under revision control:
``` ```
$ git add file1 file2 ... $ git pull
``` ```
To record changes, use: === Contribute your changes: fork the main repository ===
If you want the possibility to contribute your changes,
you should create your own fork, do your changes there,
and then send a pull request to the main repository.
+ **Creating and cloning a fork —**
See GitHub documentation for instructions how to [create your own fork https://docs.github.com/en/get-started/quickstart/fork-a-repo]
of the repository. Once you've done it, clone the fork to your local computer.
``` ```
$ git commit file1 file2 ... $ git clone https://github.com/<YOUR_USERNAME>/gf-core.git
``` ```
This creates a patch against the previous version and stores it in your + **Updating your copy —**
local repository. You can record any number of changes before Once you have cloned your fork, you need to set up the main repository as a remote:
pushing them to the main repo. In fact, you don't have to push them at
all if you want to keep the changes only in your local repo.
Instead of enumerating all modified files on the command line,
you can use the flag ``-a`` to automatically record //all// modified
files. You still need to use ``git add`` to add new files.
=== Read-write access ===
If you are a member of the GF project on GitHub, you can push your
changes directly to the GF git repository on GitHub.
``` ```
$ git push $ git remote add upstream https://github.com/GrammaticalFramework/gf-core.git
``` ```
It is also possible for anyone else to contribute by Then you can get the latest updates by running the following:
- creating a fork of the GF repository on GitHub, ```
- working with local clone of the fork (obtained with ``git clone``), $ git pull upstream master
- pushing changes to the fork, ```
- and finally sending a pull request.
+ **Recording local changes —**
See Git tutorial on how to [record and push your changes https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository] to your fork.
+ **Pull request —**
When you want to contribute your changes to the main gf-core repository,
[create a pull request https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request]
from your fork.
== Compilation from source with Cabal == If you want to contribute to the RGL as well, do the same process for the RGL repository.
The build system of GF is based on //Cabal//, which is part of the
Haskell Platform, so no extra steps are needed to install it. In the simplest == Compilation from source ==
case, all you need to do to compile and install GF, after downloading the
source code as described above, is By now you should have installed Stack and Haskeline, and cloned the Git repository on your own computer, in a directory called ``gf-core``.
=== Primary recommendation: use Stack ===
Open a terminal, go to the top directory (``gf-core``), and type the following command.
```
$ stack install
```
It will install GF and all necessary tools and libraries to do that.
=== Alternative: use Cabal ===
You can also install GF using Cabal, if you prefer Cabal to Stack. In that case, you may need to install some prerequisites yourself.
The actual installation process is similar to Stack: open a terminal, go to the top directory (``gf-core``), and type the following command.
``` ```
$ cabal install $ cabal install
``` ```
This will automatically download any additional Haskell libraries needed to //The old (potentially outdated) instructions for Cabal are moved to a [separate page ../doc/gf-developers-old-cabal.html]. If you run into trouble with ``cabal install``, you may want to take a look.//
build GF. If this is the first time you use Cabal, you might need to run
``cabal update`` first, to update the list of available libraries.
If you want more control, the process can also be split up into the usual == Compiling GF with C runtime system support ==
//configure//, //build// and //install// steps.
=== Configure === The C runtime system is a separate implementation of the PGF runtime services.
During the configuration phase Cabal will check that you have all
necessary tools and libraries needed for GF. The configuration is
started by the command:
```
$ cabal configure
```
If you don't see any error message from the above command then you
have everything that is needed for GF. You can also add the option
``-v`` to see more details about the configuration.
You can use ``cabal configure --help`` to get a list of configuration options.
=== Build ===
The build phase does two things. First it builds the GF compiler from
the Haskell source code and after that it builds the GF Resource Grammar
Library using the already build compiler. The simplest command is:
```
$ cabal build
```
Again you can add the option ``-v`` if you want to see more details.
==== Parallel builds ====
If you have Cabal>=1.20 you can enable parallel compilation by using
```
$ cabal build -j
```
or by putting a line
```
jobs: $ncpus
```
in your ``.cabal/config`` file. Cabal
will pass this option to GHC when building the GF compiler, if you
have GHC>=7.8.
Cabal also passes ``-j`` to GF to enable parallel compilation of the
Resource Grammar Library. This is done unconditionally to avoid
causing problems for developers with Cabal<1.20. You can disable this
by editing the last few lines in ``WebSetup.hs``.
==== Partial builds ====
**NOTE**: The following doesn't work with recent versions of ``cabal``.
%% // TH 2015-06-22
Sometimes you just want to work on the GF compiler and don't want to
recompile the resource library after each change. In this case use
this extended command:
```
$ cabal build rgl-none
```
The resource library could also be compiled in two modes: with present
tense only and with all tenses. By default it is compiled with all
tenses. If you want to use the library with only present tense you can
compile it in this special mode with the command:
```
$ cabal build present
```
You could also control which languages you want to be recompiled by
adding the option ``langs=list``. For example the following command
will compile only the English and the Swedish language:
```
$ cabal build langs=Eng,Swe
```
=== Install ===
After you have compiled GF you need to install the executable and libraries
to make the system usable.
```
$ cabal copy
$ cabal register
```
This command installs the GF compiler for a single user, in the standard
place used by Cabal.
On Linux and Mac this could be ``$HOME/.cabal/bin``.
On Mac it could also be ``$HOME/Library/Haskell/bin``.
On Windows this is ``C:\Program Files\Haskell\bin``.
The compiled GF Resource Grammar Library will be installed
under the same prefix, e.g. in
``$HOME/.cabal/share/gf-3.3.3/lib`` on Linux and
in ``C:\Program Files\Haskell\gf-3.3.3\lib`` on Windows.
If you want to install in some other place then use the ``--prefix``
option during the configuration phase.
=== Clean ===
Sometimes you want to clean up the compilation and start again from clean
sources. Use the clean command for this purpose:
```
$ cabal clean
```
%=== SDist ===
%
%You can use the command:
%
%% This does *NOT* include everything that is needed // TH 2012-08-06
%```
%$ cabal sdist
%```
%
%to prepare archive with all source codes needed to compile GF.
=== Known problems with Cabal ===
Some versions of Cabal (at least version 1.16) seem to have a bug that can
cause the following error:
```
Configuring gf-3.x...
setup: Distribution/Simple/PackageIndex.hs:124:8-13: Assertion failed
```
The exact cause of this problem is unclear, but it seems to happen
during the configure phase if the same version of GF is already installed,
so a workaround is to remove the existing installation with
```
ghc-pkg unregister gf
```
You can check with ``ghc-pkg list gf`` that it is gone.
== Compilation with make ==
If you feel more comfortable with Makefiles then there is a thin Makefile
wrapper arround Cabal for you. If you just type:
```
$ make
```
the configuration phase will be run automatically if needed and after that
the sources will be compiled.
%% cabal build rgl-none does not work with recent versions of Cabal
%If you don't want to compile the resource library
%every time then you can use:
%```
%$ make gf
%```
For installation use:
```
$ make install
```
For cleaning:
```
$ make clean
```
%and to build source distribution archive run:
%```
%$ make sdist
%```
== Compiling GF with C run-time system support ==
The C run-time system is a separate implementation of the PGF run-time services.
It makes it possible to work with very large, ambiguous grammars, using It makes it possible to work with very large, ambiguous grammars, using
probabilistic models to obtain probable parses. The C run-time system might probabilistic models to obtain probable parses. The C runtime system might
also be easier to use than the Haskell run-time system on certain platforms, also be easier to use than the Haskell runtime system on certain platforms,
e.g. Android and iOS. e.g. Android and iOS.
To install the C run-time system, go to the ``src/runtime/c`` directory To install the C runtime system, go to the ``src/runtime/c`` directory.
%and follow the instructions in the ``INSTALL`` file.
and use the ``install.sh`` script:
```
bash setup.sh configure
bash setup.sh build
bash setup.sh install
```
This will install
the C header files and libraries need to write C programs that use PGF grammars.
Some example C programs are included in the ``utils`` subdirectory, e.g.
``pgf-translate.c``.
When the C run-time system is installed, you can install GF with C run-time - **On Linux and Mac OS —**
support by doing You should have autoconf, automake, libtool and make.
If you are missing some of them, follow the
instructions in the [INSTALL https://github.com/GrammaticalFramework/gf-core/blob/master/src/runtime/c/INSTALL] file.
Once you have the required libraries, the easiest way to install the C runtime is to use the ``install.sh`` script. Just type
``$ bash install.sh``
This will install the C header files and libraries need to write C programs
that use PGF grammars.
% If this doesn't work for you, follow the manual instructions in the [INSTALL https://github.com/GrammaticalFramework/gf-core/blob/master/src/runtime/c/INSTALL] file under your operating system.
- **On other operating systems —** Follow the instructions in the
[INSTALL https://github.com/GrammaticalFramework/gf-core/blob/master/src/runtime/c/INSTALL] file under your operating system.
Depending on what you want to do with the C runtime, you can follow one or more of the following steps.
=== Use the C runtime from another programming language ===[bindings]
% **If you just want to use the C runtime from Python, Java, or Haskell, you don't need to change your GF installation.**
- **What —**
This is the most common use case for the C runtime: compile
your GF grammars into PGF with the standard GF executable,
and manipulate the PGFs from another programming language,
using the bindings to the C runtime.
- **How —**
The Python, Java and Haskell bindings are found in the
``src/runtime/{python,java,haskell-bind}`` directories,
respecively. Compile them by following the instructions
in the ``INSTALL`` or ``README`` files in those directories.
The Python library can also be installed from PyPI using ``pip install pgf``.
//If you are on Mac and get an error about ``clang`` version, you can try some of [these solutions https://stackoverflow.com/questions/63972113/big-sur-clang-invalid-version-error-due-to-macosx-deployment-target]—but be careful before removing any existing installations.//
=== Use GF shell with C runtime support ===
- **What —**
If you want to use the GF shell with C runtime functionalities, then you need to (re)compile GF with special flags.
The GF shell can be started with ``gf -cshell`` or ``gf -crun`` to use
the C run-time system instead of the Haskell run-time system.
Only limited functionality is available when running the shell in these
modes (use the ``help`` command in the shell for details).
(Re)compiling your GF with these flags will also give you
Haskell bindings to the C runtime, as a library called ``PGF2``,
but if you want Python or Java bindings, you need to do [the previous step #bindings].
% ``PGF2``: a module to import in Haskell programs, providing a binding to the C run-time system.
- **How —**
If you use cabal, run the following command:
``` ```
cabal install -fserver -fc-runtime cabal install -fc-runtime
``` ```
from the top directory. This give you three new things:
- ``PGF2``: a module to import in Haskell programs, providing a binding to from the top directory (``gf-core``).
the C run-time system.
- The GF shell can be started with ``gf -cshell`` or ``gf -crun`` to use If you use stack, uncomment the following lines in the ``stack.yaml`` file:
the C run-time system instead of the Haskell run-time system.
Only limited functionality is available when running the shell in these
modes (use the ``help`` command in the shell for details).
- ``gf -server`` mode is extended with new requests to call the C run-time ```
system, e.g. ``c-parse``, ``c-linearize`` and ``c-translate``. flags:
gf:
c-runtime: true
extra-lib-dirs:
- /usr/local/lib
```
and then run ``stack install`` from the top directory (``gf-core``).
=== Python and Java bindings === //If you get an "``error while loading shared libraries``" when trying to run GF with C runtime, remember to declare your ``LD_LIBRARY_PATH``.//
//Add ``export LD_LIBRARY_PATH="/usr/local/lib"`` to either your ``.bashrc`` or ``.profile``. You should now be able to start GF with C runtime.//
=== Use GF server mode with C runtime ===
- **What —**
With this feature, ``gf -server`` mode is extended with new requests to call the C run-time
system, e.g. ``c-parse``, ``c-linearize`` and ``c-translate``.
- **How —**
If you use cabal, run the following command:
```
cabal install -fc-runtime -fserver
```
from the top directory.
If you use stack, add the following lines in the ``stack.yaml`` file:
```
flags:
gf:
c-runtime: true
server: true
extra-lib-dirs:
- /usr/local/lib
```
and then run ``stack install``, also from the top directory.
The C run-time system can also be used from Python and Java. Python and Java
bindings are found in the ``src/runtime/python`` and ``src/runtime/java``
directories, respecively. Compile them by following the instructions in
the ``INSTALL`` files in those directories.
The Python library can also be installed from PyPI using `pip install pgf`.
== Compilation of RGL == == Compilation of RGL ==
As of 2018-07-26, the RGL is distributed separately from the GF compiler and runtimes. As of 2018-07-26, the RGL is distributed separately from the GF compiler and runtimes.
To get the source, follow the previous instructions on [how to clone a repository with Git #getting-source].
After cloning the RGL, you should have a directory named ``gf-rgl`` on your computer.
=== Simple === === Simple ===
To install the RGL, you can use the following commands from within the ``gf-rgl`` repository: To install the RGL, you can use the following commands from within the ``gf-rgl`` repository:
``` ```
@@ -418,103 +317,68 @@ If you do not have Haskell installed, you can use the simple build script ``Setu
== Creating binary distribution packages == == Creating binary distribution packages ==
=== Creating .deb packages for Ubuntu === The binaries are generated with Github Actions. More details can be viewed here:
This was tested on Ubuntu 14.04 for the release of GF 3.6, and the https://github.com/GrammaticalFramework/gf-core/actions/workflows/build-binary-packages.yml
resulting ``.deb`` packages appears to work on Ubuntu 12.04, 13.10 and 14.04.
For the release of GF 3.7, we generated ``.deb`` packages on Ubuntu 15.04 and
tested them on Ubuntu 12.04 and 14.04.
Under Ubuntu, Haskell executables are statically linked against other Haskell
libraries, so the .deb packages are fairly self-contained.
==== Preparations ==== == Running the test suite ==
The GF test suite is run with one of the following commands from the top directory:
``` ```
sudo apt-get install dpkg-dev debhelper $ cabal test
``` ```
==== Creating the package ==== or
Make sure the ``debian/changelog`` starts with an entry that describes the
version you are building. Then run
``` ```
make deb $ stack test
``` ```
If get error messages about missing dependencies
(e.g. ``autoconf``, ``automake``, ``libtool-bin``, ``python-dev``,
``java-sdk``, ``txt2tags``)
use ``apt-get intall`` to install them, then try again.
=== Creating OS X Installer packages ===
Run
```
make pkg
```
=== Creating binary tar distributions ===
Run
```
make bintar
```
=== Creating .rpm packages for Fedora ===
This is possible, but the procedure has not been automated.
It involves using the cabal-rpm tool,
```
sudo dnf install cabal-rpm
```
and following the Fedora guide
[How to create an RPM package http://fedoraproject.org/wiki/How_to_create_an_RPM_package].
Under Fedora, Haskell executables are dynamically linked against other Haskell
libraries, so ``.rpm`` packages for all Haskell libraries that GF depends on
are required. Most of them are already available in the Fedora distribution,
but a few of them might have to be built and distributed along with
the GF ``.rpm`` package.
When building ``.rpm`` packages for GF 3.4, we also had to build ``.rpm``s for
``fst`` and ``httpd-shed``.
== Running the testsuite ==
**NOTE:** The test suite has not been maintained recently, so expect many
tests to fail.
%% // TH 2012-08-06
GF has testsuite. It is run with the following command:
```
$ cabal test
```
The testsuite architecture for GF is very simple but still very flexible. The testsuite architecture for GF is very simple but still very flexible.
GF by itself is an interpreter and could execute commands in batch mode. GF by itself is an interpreter and could execute commands in batch mode.
This is everything that we need to organize a testsuite. The root of the This is everything that we need to organize a testsuite. The root of the
testsuite is the testsuite/ directory. It contains subdirectories which testsuite is the ``testsuite/`` directory. It contains subdirectories
themself contain GF batch files (with extension .gfs). The above command which themselves contain GF batch files (with extension ``.gfs``).
searches the subdirectories of the testsuite/ directory for files with extension The above command searches the subdirectories of the ``testsuite/`` directory
.gfs and when it finds one it is executed with the GF interpreter. for files with extension ``.gfs`` and when it finds one, it is executed with
The output of the script is stored in file with extension .out and is compared the GF interpreter. The output of the script is stored in file with extension ``.out``
with the content of the corresponding file with extension .gold, if there is one. and is compared with the content of the corresponding file with extension ``.gold``, if there is one.
If the contents are identical the command reports that the test was passed successfully.
Otherwise the test had failed.
Every time when you make some changes to GF that have to be tested, instead of Every time when you make some changes to GF that have to be tested,
writing the commands by hand in the GF shell, add them to one .gfs file in the testsuite instead of writing the commands by hand in the GF shell, add them to one ``.gfs``
and run the test. In this way you can use the same test later and we will be sure file in the testsuite subdirectory where its ``.gf`` file resides and run the test.
that we will not incidentaly break your code later. In this way you can use the same test later and we will be sure that we will not
accidentally break your code later.
**Test Outcome - Passed:** If the contents of the files with the ``.out`` extension
are identical to their correspondingly-named files with the extension ``.gold``,
the command will report that the tests passed successfully, e.g.
If you don't want to run the whole testsuite you can write the path to the subdirectory
in which you are interested. For example:
``` ```
$ cabal test testsuite/compiler Running 1 test suites...
Test suite gf-tests: RUNNING...
Test suite gf-tests: PASS
1 of 1 test suites (1 of 1 test cases) passed.
``` ```
will run only the testsuite for the compiler.
**Test Outcome - Failed:** If there is a contents mismatch between the files
with the ``.out`` extension and their corresponding files with the extension ``.gold``,
the test diagnostics will show a fail and the areas that failed. e.g.
```
testsuite/compiler/compute/Records.gfs: OK
testsuite/compiler/compute/Variants.gfs: FAIL
testsuite/compiler/params/params.gfs: OK
Test suite gf-tests: FAIL
0 of 1 test suites (0 of 1 test cases) passed.
```
The fail results overview is available in gf-tests.html which shows 4 columns:
+ __Results__ - only areas that fail will appear. (Note: There are 3 failures in the gf-tests.html which are labelled as (expected). These failures should be ignored.)
+ __Input__ - which is the test written in the .gfs file
+ __Gold__ - the expected output from running the test set out in the .gfs file. This column refers to the contents from the .gold extension files.
+ __Output__ - This column refers to the contents from the .out extension files which are generated as test output.
After fixing the areas which fail, rerun the test command. Repeat the entire process of fix-and-test until the test suite passes before submitting a pull request to include your changes.

View File

@@ -1,6 +1,6 @@
--- ---
title: GF 3.11 Release Notes title: GF 3.11 Release Notes
date: ... December 2020 date: ... July 2021
... ...
## Installation ## Installation
@@ -12,24 +12,27 @@ See the [download page](index-3.11.html).
From this release, the binary GF core packages do not contain the RGL. From this release, the binary GF core packages do not contain the RGL.
The RGL's release cycle is now completely separate from GF's. See [RGL releases](https://github.com/GrammaticalFramework/gf-rgl/releases). The RGL's release cycle is now completely separate from GF's. See [RGL releases](https://github.com/GrammaticalFramework/gf-rgl/releases).
Over 400 changes have been pushed to GF core Over 500 changes have been pushed to GF core
since the release of GF 3.10 in December 2018. since the release of GF 3.10 in December 2018.
## General ## General
- Make the test suite work again. - Make the test suite work again.
- Compatibility with new versions of GHC, including multiple Stack files for the different versions. - Compatibility with new versions of GHC, including multiple Stack files for the different versions.
- Updates to build scripts and CI. - Support for newer version of Ubuntu 20.04 in the precompiled binaries.
- Bug fixes. - Updates to build scripts and CI workflows.
- Bug fixes and code cleanup.
## GF compiler and run-time library ## GF compiler and run-time library
- Huge improvements in time & space requirements for grammar compilation (pending [#87](https://github.com/GrammaticalFramework/gf-core/pull/87)).
- Add CoNLL output to `visualize_tree` shell command. - Add CoNLL output to `visualize_tree` shell command.
- Add canonical GF as output format in the compiler. - Add canonical GF as output format in the compiler.
- Add PGF JSON as output format in the compiler. - Add PGF JSON as output format in the compiler.
- Deprecate JavaScript runtime in favour of updated [TypeScript runtime](https://github.com/GrammaticalFramework/gf-typescript). - Deprecate JavaScript runtime in favour of updated [TypeScript runtime](https://github.com/GrammaticalFramework/gf-typescript).
- Improvements in time & space requirements when compiling certain grammars.
- Improvements to Haskell export. - Improvements to Haskell export.
- Improvements to the GF shell.
- Improvements to canonical GF compilation.
- Improvements to the C runtime. - Improvements to the C runtime.
- Improvements to `gf -server` mode. - Improvements to `gf -server` mode.
- Clearer compiler error messages. - Clearer compiler error messages.

176
gf.cabal
View File

@@ -1,17 +1,16 @@
name: gf name: gf
version: 3.10.4-git version: 3.11.0-git
cabal-version: >= 1.22 cabal-version: 1.22
build-type: Custom build-type: Custom
license: OtherLicense license: OtherLicense
license-file: LICENSE license-file: LICENSE
category: Natural Language Processing, Compiler category: Natural Language Processing, Compiler
synopsis: Grammatical Framework synopsis: Grammatical Framework
description: GF, Grammatical Framework, is a programming language for multilingual grammar applications description: GF, Grammatical Framework, is a programming language for multilingual grammar applications
homepage: http://www.grammaticalframework.org/ homepage: https://www.grammaticalframework.org/
bug-reports: https://github.com/GrammaticalFramework/gf-core/issues bug-reports: https://github.com/GrammaticalFramework/gf-core/issues
maintainer: Thomas Hallgren tested-with: GHC==7.10.3, GHC==8.0.2, GHC==8.10.4
tested-with: GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.3
data-dir: src data-dir: src
extra-source-files: WebSetup.hs extra-source-files: WebSetup.hs
@@ -42,23 +41,23 @@ data-files:
custom-setup custom-setup
setup-depends: setup-depends:
base, base >= 4.9.1 && < 4.15,
Cabal >=1.22.0.0, Cabal >= 1.22.0.0,
directory, directory >= 1.3.0 && < 1.4,
filepath, filepath >= 1.4.1 && < 1.5,
process >=1.0.1.1 process >= 1.0.1.1 && < 1.7
source-repository head source-repository head
type: git type: git
location: https://github.com/GrammaticalFramework/gf-core.git location: https://github.com/GrammaticalFramework/gf-core.git
flag interrupt flag interrupt
Description: Enable Ctrl+Break in the shell Description: Enable Ctrl+Break in the shell
Default: True Default: True
flag server flag server
Description: Include --server mode Description: Include --server mode
Default: True Default: True
flag network-uri flag network-uri
description: Get Network.URI from the network-uri package description: Get Network.URI from the network-uri package
@@ -70,24 +69,29 @@ flag network-uri
flag c-runtime flag c-runtime
Description: Include functionality from the C run-time library (which must be installed already) Description: Include functionality from the C run-time library (which must be installed already)
Default: False Default: False
library library
default-language: Haskell2010 default-language: Haskell2010
build-depends: base >= 4.6 && <5, build-depends:
array, -- GHC 8.0.2 to GHC 8.10.4
containers, array >= 0.5.1 && < 0.6,
bytestring, base >= 4.9.1 && < 4.15,
utf8-string, bytestring >= 0.10.8 && < 0.11,
random, containers >= 0.5.7 && < 0.7,
pretty, exceptions >= 0.8.3 && < 0.11,
mtl, ghc-prim >= 0.5.0 && < 0.7,
exceptions, mtl >= 2.2.1 && < 2.3,
fail, pretty >= 1.1.3 && < 1.2,
-- For compatability with ghc < 8 random >= 1.1 && < 1.3,
-- We need transformers-compat >= 0.6.3, but that is only in newer snapshots where it is redundant. utf8-string >= 1.0.1.1 && < 1.1,
transformers-compat, -- We need transformers-compat >= 0.6.3, but that is only in newer snapshots where it is redundant.
ghc-prim transformers-compat >= 0.5.1.4 && < 0.7
if impl(ghc<8.0)
build-depends:
fail >= 4.9.0 && < 4.10
hs-source-dirs: src/runtime/haskell hs-source-dirs: src/runtime/haskell
other-modules: other-modules:
@@ -136,18 +140,28 @@ library
if flag(c-runtime) if flag(c-runtime)
exposed-modules: PGF2 exposed-modules: PGF2
other-modules: PGF2.FFI PGF2.Expr PGF2.Type other-modules:
GF.Interactive2 GF.Command.Commands2 PGF2.FFI
hs-source-dirs: src/runtime/haskell-bind PGF2.Expr
build-tools: hsc2hs PGF2.Type
GF.Interactive2
GF.Command.Commands2
hs-source-dirs: src/runtime/haskell-bind
build-tools: hsc2hs
extra-libraries: pgf gu extra-libraries: pgf gu
c-sources: src/runtime/haskell-bind/utils.c c-sources: src/runtime/haskell-bind/utils.c
cc-options: -std=c99 cc-options: -std=c99
---- GF compiler as a library: ---- GF compiler as a library:
build-depends: filepath, directory>=1.2, time, build-depends:
process, haskeline, parallel>=3, json directory >= 1.3.0 && < 1.4,
filepath >= 1.4.1 && < 1.5,
haskeline >= 0.7.3 && < 0.9,
json >= 0.9.1 && < 0.11,
parallel >= 3.2.1.1 && < 3.3,
process >= 1.4.3 && < 1.7,
time >= 1.6.0 && < 1.10
hs-source-dirs: src/compiler hs-source-dirs: src/compiler
exposed-modules: exposed-modules:
@@ -158,12 +172,19 @@ library
GF.Grammar.Canonical GF.Grammar.Canonical
other-modules: other-modules:
GF.Main GF.Compiler GF.Interactive GF.Main
GF.Compiler
GF.Interactive
GF.Compile GF.CompileInParallel GF.CompileOne GF.Compile.GetGrammar GF.Compile
GF.CompileInParallel
GF.CompileOne
GF.Compile.GetGrammar
GF.Grammar GF.Grammar
GF.Data.Operations GF.Infra.Option GF.Infra.UseIO GF.Data.Operations
GF.Infra.Option
GF.Infra.UseIO
GF.Command.Abstract GF.Command.Abstract
GF.Command.CommandInfo GF.Command.CommandInfo
@@ -273,12 +294,17 @@ library
cpp-options: -DC_RUNTIME cpp-options: -DC_RUNTIME
if flag(server) if flag(server)
build-depends: httpd-shed>=0.4.0.3, network>=2.3 && <2.7, build-depends:
cgi>=3001.2.2.0 cgi >= 3001.3.0.2 && < 3001.6,
httpd-shed >= 0.4.0 && < 0.5,
network>=2.3 && <2.7
if flag(network-uri) if flag(network-uri)
build-depends: network-uri>=2.6, network>=2.6 build-depends:
network-uri >= 2.6.1.0 && < 2.7,
network>=2.6 && <2.7
else else
build-depends: network<2.6 build-depends:
network >= 2.5 && <2.6
cpp-options: -DSERVER_MODE cpp-options: -DSERVER_MODE
other-modules: other-modules:
@@ -295,7 +321,10 @@ library
Fold Fold
ExampleDemo ExampleDemo
ExampleService ExampleService
hs-source-dirs: src/server src/server/transfer src/example-based hs-source-dirs:
src/server
src/server/transfer
src/example-based
if flag(interrupt) if flag(interrupt)
cpp-options: -DUSE_INTERRUPT cpp-options: -DUSE_INTERRUPT
@@ -304,17 +333,24 @@ library
other-modules: GF.System.NoSignal other-modules: GF.System.NoSignal
if impl(ghc>=7.8) if impl(ghc>=7.8)
build-tools: happy>=1.19, alex>=3.1 build-tools:
happy>=1.19,
alex>=3.1
-- ghc-options: +RTS -A20M -RTS -- ghc-options: +RTS -A20M -RTS
else else
build-tools: happy, alex>=3 build-tools:
happy,
alex>=3
ghc-options: -fno-warn-tabs ghc-options: -fno-warn-tabs
if os(windows) if os(windows)
build-depends: Win32 build-depends:
Win32 >= 2.3.1.1 && < 2.7
else else
build-depends: unix, terminfo>=0.4 build-depends:
terminfo >=0.4.0 && < 0.5,
unix >= 2.7.2 && < 2.8
if impl(ghc>=8.2) if impl(ghc>=8.2)
ghc-options: -fhide-source-paths ghc-options: -fhide-source-paths
@@ -322,8 +358,10 @@ library
executable gf executable gf
hs-source-dirs: src/programs hs-source-dirs: src/programs
main-is: gf-main.hs main-is: gf-main.hs
default-language: Haskell2010 default-language: Haskell2010
build-depends: gf, base build-depends:
gf,
base
ghc-options: -threaded ghc-options: -threaded
--ghc-options: -fwarn-unused-imports --ghc-options: -fwarn-unused-imports
@@ -337,20 +375,30 @@ executable gf
if impl(ghc>=8.2) if impl(ghc>=8.2)
ghc-options: -fhide-source-paths ghc-options: -fhide-source-paths
executable pgf-shell -- executable pgf-shell
--if !flag(c-runtime) -- --if !flag(c-runtime)
buildable: False -- buildable: False
main-is: pgf-shell.hs -- main-is: pgf-shell.hs
hs-source-dirs: src/runtime/haskell-bind/examples -- hs-source-dirs: src/runtime/haskell-bind/examples
build-depends: gf, base, containers, mtl, lifted-base -- build-depends:
default-language: Haskell2010 -- gf,
if impl(ghc>=7.0) -- base,
ghc-options: -rtsopts -- containers,
-- mtl,
-- lifted-base
-- default-language: Haskell2010
-- if impl(ghc>=7.0)
-- ghc-options: -rtsopts
test-suite gf-tests test-suite gf-tests
type: exitcode-stdio-1.0 type: exitcode-stdio-1.0
main-is: run.hs main-is: run.hs
hs-source-dirs: testsuite hs-source-dirs: testsuite
build-depends: base>=4.3 && <5, Cabal>=1.8, directory, filepath, process build-depends:
base >= 4.9.1 && < 4.15,
Cabal >= 1.8,
directory >= 1.3.0 && < 1.4,
filepath >= 1.4.1 && < 1.5,
process >= 1.4.3 && < 1.7
build-tool-depends: gf:gf build-tool-depends: gf:gf
default-language: Haskell2010 default-language: Haskell2010

View File

@@ -214,9 +214,9 @@ least one, it may help you to get a first idea of what GF is.
</p> </p>
<p> <p>
We run the IRC channel <strong><code>#gf</code></strong> on the Freenode network, where you are welcome to look for help with small questions or just start a general discussion. We run the IRC channel <strong><code>#gf</code></strong> on the Libera network, where you are welcome to look for help with small questions or just start a general discussion.
You can <a href="https://webchat.freenode.net/?channels=gf">open a web chat</a> You can <a href="https://web.libera.chat/?channels=#gf">open a web chat</a>
or <a href="/irc/">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>. 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>.

View File

@@ -18,7 +18,7 @@ import Data.List
-------------------------- --------------------------
cf2pgf :: FilePath -> ParamCFG -> PGF cf2pgf :: FilePath -> ParamCFG -> PGF
cf2pgf fpath cf = cf2pgf fpath cf =
let pgf = PGF Map.empty aname (cf2abstr cf) (Map.singleton cname (cf2concr cf)) let pgf = PGF Map.empty aname (cf2abstr cf) (Map.singleton cname (cf2concr cf))
in updateProductionIndices pgf in updateProductionIndices pgf
where where
@@ -33,7 +33,7 @@ cf2abstr cfg = Abstr aflags afuns acats
acats = Map.fromList [(cat, ([], [(0,mkRuleName rule) | rule <- rules], 0)) acats = Map.fromList [(cat, ([], [(0,mkRuleName rule) | rule <- rules], 0))
| (cat,rules) <- (Map.toList . Map.fromListWith (++)) | (cat,rules) <- (Map.toList . Map.fromListWith (++))
[(cat2id cat, catRules cfg cat) | [(cat2id cat, catRules cfg cat) |
cat <- allCats' cfg]] cat <- allCats' cfg]]
afuns = Map.fromList [(mkRuleName rule, (cftype [cat2id c | NonTerminal c <- ruleRhs rule] (cat2id (ruleLhs rule)), 0, Nothing, 0)) afuns = Map.fromList [(mkRuleName rule, (cftype [cat2id c | NonTerminal c <- ruleRhs rule] (cat2id (ruleLhs rule)), 0, Nothing, 0))
| rule <- allRules cfg] | rule <- allRules cfg]
@@ -52,7 +52,7 @@ cf2concr cfg = Concr Map.empty Map.empty
cats = allCats' cfg cats = allCats' cfg
rules = allRules cfg rules = allRules cfg
sequences0 = Set.fromList (listArray (0,0) [SymCat 0 0] : sequences0 = Set.fromList (listArray (0,0) [SymCat 0 0] :
map mkSequence rules) map mkSequence rules)
sequences = listArray (0,Set.size sequences0-1) (Set.toList sequences0) sequences = listArray (0,Set.size sequences0-1) (Set.toList sequences0)
@@ -102,7 +102,7 @@ cf2concr cfg = Concr Map.empty Map.empty
mkLinDefRef (cat,_) = mkLinDefRef (cat,_) =
(cat2fid cat 0,[0]) (cat2fid cat 0,[0])
addProd prods (fid,prod) = addProd prods (fid,prod) =
case IntMap.lookup fid prods of case IntMap.lookup fid prods of
Just set -> IntMap.insert fid (Set.insert prod set) prods Just set -> IntMap.insert fid (Set.insert prod set) prods
@@ -130,5 +130,5 @@ cf2concr cfg = Concr Map.empty Map.empty
mkRuleName rule = mkRuleName rule =
case ruleName rule of case ruleName rule of
CFObj n _ -> n CFObj n _ -> n
_ -> wildCId _ -> wildCId

View File

@@ -175,7 +175,7 @@ checkInfo opts cwd sgr (m,mo) c info = checkInModule cwd mo NoLoc empty $ do
checkTyp gr typ checkTyp gr typ
case md of case md of
Just eqs -> mapM_ (\(L loc eq) -> mkCheck loc "the definition of function" $ Just eqs -> mapM_ (\(L loc eq) -> mkCheck loc "the definition of function" $
checkDef gr (m,c) typ eq) eqs checkDef gr (m,c) typ eq) eqs
Nothing -> return () Nothing -> return ()
return (AbsFun (Just (L loc typ)) ma md moper) return (AbsFun (Just (L loc typ)) ma md moper)
@@ -316,7 +316,7 @@ linTypeOfType cnc m typ = do
mkLinArg (i,(n,mc@(m,cat))) = do mkLinArg (i,(n,mc@(m,cat))) = do
val <- lookLin mc val <- lookLin mc
let vars = mkRecType varLabel $ replicate n typeStr let vars = mkRecType varLabel $ replicate n typeStr
symb = argIdent n cat i symb = argIdent n cat i
rec <- if n==0 then return val else rec <- if n==0 then return val else
errIn (render ("extending" $$ errIn (render ("extending" $$
nest 2 vars $$ nest 2 vars $$

View File

@@ -30,11 +30,12 @@ import Debug.Trace(trace)
normalForm :: GlobalEnv -> L Ident -> Term -> Term normalForm :: GlobalEnv -> L Ident -> Term -> Term
normalForm (GE gr rv opts _) loc = err (bugloc loc) id . nfx (GE gr rv opts loc) normalForm (GE gr rv opts _) loc = err (bugloc loc) id . nfx (GE gr rv opts loc)
nfx :: GlobalEnv -> Term -> Err Term
nfx env@(GE _ _ _ loc) t = do nfx env@(GE _ _ _ loc) t = do
v <- eval env [] t v <- eval env [] t
case value2term loc [] v of return (value2term loc [] v)
Left i -> fail ("variable #"++show i++" is out of scope") -- Old value2term error message:
Right t -> return t -- Left i -> fail ("variable #"++show i++" is out of scope")
eval :: GlobalEnv -> Env -> Term -> Err Value eval :: GlobalEnv -> Env -> Term -> Err Value
eval (GE gr rvs opts loc) env t = ($ (map snd env)) # value cenv t eval (GE gr rvs opts loc) env t = ($ (map snd env)) # value cenv t
@@ -288,9 +289,9 @@ glue env (v1,v2) = glu v1 v2
(v1,v2) -> if flag optPlusAsBind (opts env) (v1,v2) -> if flag optPlusAsBind (opts env)
then VC v1 (VC (VApp BIND []) v2) then VC v1 (VC (VApp BIND []) v2)
else let loc = gloc env else let loc = gloc env
vt v = case value2term loc (local env) v of vt v = value2term loc (local env) v
Left i -> Error ('#':show i) -- Old value2term error message:
Right t -> t -- Left i -> Error ('#':show i)
originalMsg = render $ ppL loc (hang "unsupported token gluing" 4 originalMsg = render $ ppL loc (hang "unsupported token gluing" 4
(Glue (vt v1) (vt v2))) (Glue (vt v1) (vt v2)))
term = render $ pp $ Glue (vt v1) (vt v2) term = render $ pp $ Glue (vt v1) (vt v2)
@@ -355,9 +356,9 @@ select env vv =
(v1,v2) -> ok2 VS v1 v2 (v1,v2) -> ok2 VS v1 v2
match loc cs v = match loc cs v =
case value2term loc [] v of err bad return (matchPattern cs (value2term loc [] v))
Left i -> bad ("variable #"++show i++" is out of scope") -- Old value2term error message:
Right t -> err bad return (matchPattern cs t) -- Left i -> bad ("variable #"++show i++" is out of scope")
where where
bad = fail . ("In pattern matching: "++) bad = fail . ("In pattern matching: "++)
@@ -383,9 +384,8 @@ valueTable env i cs =
wild = case i of TWild _ -> True; _ -> False wild = case i of TWild _ -> True; _ -> False
convertv cs' vty = convertv cs' vty =
case value2term (gloc env) [] vty of convert' cs' =<< paramValues'' env (value2term (gloc env) [] vty)
Left i -> fail ("variable #"++show i++" is out of scope") -- Old value2term error message: Left i -> fail ("variable #"++show i++" is out of scope")
Right pty -> convert' cs' =<< paramValues'' env pty
convert cs' ty = convert' cs' =<< paramValues' env ty convert cs' ty = convert' cs' =<< paramValues' env ty
@@ -492,58 +492,60 @@ vtrace loc arg res = trace (render (hang (pv arg) 4 ("->"<+>pv res))) res
pf (_,VString n) = pp n pf (_,VString n) = pp n
pf (_,v) = ppV v pf (_,v) = ppV v
pa (_,v) = ppV v pa (_,v) = ppV v
ppV v = case value2term' True loc [] v of ppV v = ppTerm Unqualified 10 (value2term' True loc [] v)
Left i -> "variable #" <> pp i <+> "is out of scope" -- Old value2term error message:
Right t -> ppTerm Unqualified 10 t -- Left i -> "variable #" <> pp i <+> "is out of scope"
-- | Convert a value back to a term -- | Convert a value back to a term
value2term :: GLocation -> [Ident] -> Value -> Either Int Term value2term :: GLocation -> [Ident] -> Value -> Term
value2term = value2term' False value2term = value2term' False
value2term' :: Bool -> p -> [Ident] -> Value -> Term
value2term' stop loc xs v0 = value2term' stop loc xs v0 =
case v0 of case v0 of
VApp pre vs -> liftM (foldl App (Q (cPredef,predefName pre))) (mapM v2t vs) VApp pre vs -> applyMany (Q (cPredef,predefName pre)) vs
VCApp f vs -> liftM (foldl App (QC f)) (mapM v2t vs) VCApp f vs -> applyMany (QC f) vs
VGen j vs -> liftM2 (foldl App) (var j) (mapM v2t vs) VGen j vs -> applyMany (var j) vs
VMeta j env vs -> liftM (foldl App (Meta j)) (mapM v2t vs) VMeta j env vs -> applyMany (Meta j) vs
VProd bt v x f -> liftM2 (Prod bt x) (v2t v) (v2t' x f) VProd bt v x f -> Prod bt x (v2t v) (v2t' x f)
VAbs bt x f -> liftM (Abs bt x) (v2t' x f) VAbs bt x f -> Abs bt x (v2t' x f)
VInt n -> return (EInt n) VInt n -> EInt n
VFloat f -> return (EFloat f) VFloat f -> EFloat f
VString s -> return (if null s then Empty else K s) VString s -> if null s then Empty else K s
VSort s -> return (Sort s) VSort s -> Sort s
VImplArg v -> liftM ImplArg (v2t v) VImplArg v -> ImplArg (v2t v)
VTblType p res -> liftM2 Table (v2t p) (v2t res) VTblType p res -> Table (v2t p) (v2t res)
VRecType rs -> liftM RecType (mapM (\(l,v) -> fmap ((,) l) (v2t v)) rs) VRecType rs -> RecType [(l, v2t v) | (l,v) <- rs]
VRec as -> liftM R (mapM (\(l,v) -> v2t v >>= \t -> return (l,(Nothing,t))) as) VRec as -> R [(l, (Nothing, v2t v)) | (l,v) <- as]
VV t _ vs -> liftM (V t) (mapM v2t vs) VV t _ vs -> V t (map v2t vs)
VT wild v cs -> v2t v >>= \t -> liftM (T ((if wild then TWild else TTyped) t)) (mapM nfcase cs) VT wild v cs -> T ((if wild then TWild else TTyped) (v2t v)) (map nfcase cs)
VFV vs -> liftM FV (mapM v2t vs) VFV vs -> FV (map v2t vs)
VC v1 v2 -> liftM2 C (v2t v1) (v2t v2) VC v1 v2 -> C (v2t v1) (v2t v2)
VS v1 v2 -> liftM2 S (v2t v1) (v2t v2) VS v1 v2 -> S (v2t v1) (v2t v2)
VP v l -> v2t v >>= \t -> return (P t l) VP v l -> P (v2t v) l
VPatt p -> return (EPatt p) VPatt p -> EPatt p
VPattType v -> v2t v >>= return . EPattType VPattType v -> EPattType $ v2t v
VAlts v vvs -> liftM2 Alts (v2t v) (mapM (\(x,y) -> liftM2 (,) (v2t x) (v2t y)) vvs) VAlts v vvs -> Alts (v2t v) [(v2t x, v2t y) | (x,y) <- vvs]
VStrs vs -> liftM Strs (mapM v2t vs) VStrs vs -> Strs (map v2t vs)
-- VGlue v1 v2 -> Glue (v2t v1) (v2t v2) -- VGlue v1 v2 -> Glue (v2t v1) (v2t v2)
-- VExtR v1 v2 -> ExtR (v2t v1) (v2t v2) -- VExtR v1 v2 -> ExtR (v2t v1) (v2t v2)
VError err -> return (Error err) VError err -> Error err
where where
applyMany f vs = foldl App f (map v2t vs)
v2t = v2txs xs v2t = v2txs xs
v2txs = value2term' stop loc v2txs = value2term' stop loc
v2t' x f = v2txs (x:xs) (bind f (gen xs)) v2t' x f = v2txs (x:xs) (bind f (gen xs))
var j var j
| j<length xs = Right (Vr (reverse xs !! j)) | j<length xs = Vr (reverse xs !! j)
| otherwise = Left j | otherwise = error ("variable #"++show j++" is out of scope")
pushs xs e = foldr push e xs pushs xs e = foldr push e xs
push x (env,xs) = ((x,gen xs):env,x:xs) push x (env,xs) = ((x,gen xs):env,x:xs)
gen xs = VGen (length xs) [] gen xs = VGen (length xs) []
nfcase (p,f) = liftM ((,) p) (v2txs xs' (bind f env')) nfcase (p,f) = (,) p (v2txs xs' (bind f env'))
where (env',xs') = pushs (pattVars p) ([],xs) where (env',xs') = pushs (pattVars p) ([],xs)
bind (Bind f) x = if stop bind (Bind f) x = if stop

View File

@@ -27,6 +27,10 @@ instance Predef Int where
instance Predef Bool where instance Predef Bool where
toValue = boolV toValue = boolV
fromValue v = case v of
VCApp (mn,i) [] | mn == cPredef && i == cPTrue -> return True
VCApp (mn,i) [] | mn == cPredef && i == cPFalse -> return False
_ -> verror "Bool" v
instance Predef String where instance Predef String where
toValue = string toValue = string

View File

@@ -5,7 +5,7 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/05/30 18:39:44 $ -- > CVS $Date: 2005/05/30 18:39:44 $
-- > CVS $Author: aarne $ -- > CVS $Author: aarne $
-- > CVS $Revision: 1.19 $ -- > CVS $Revision: 1.19 $
-- --
@@ -23,9 +23,9 @@
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module GF.Compile.Rename ( module GF.Compile.Rename (
renameSourceTerm, renameSourceTerm,
renameModule renameModule
) where ) where
import GF.Infra.Ident import GF.Infra.Ident
import GF.Infra.CheckM import GF.Infra.CheckM
@@ -68,7 +68,7 @@ renameIdentTerm env = accumulateError (renameIdentTerm' env)
-- Fails immediately on error, makes it possible to try other possibilities -- Fails immediately on error, makes it possible to try other possibilities
renameIdentTerm' :: Status -> Term -> Check Term renameIdentTerm' :: Status -> Term -> Check Term
renameIdentTerm' env@(act,imps) t0 = renameIdentTerm' env@(act,imps) t0 =
case t0 of case t0 of
Vr c -> ident predefAbs c Vr c -> ident predefAbs c
Cn c -> ident (\_ s -> checkError s) c Cn c -> ident (\_ s -> checkError s) c
@@ -85,8 +85,8 @@ renameIdentTerm' env@(act,imps) t0 =
_ -> return t0 _ -> return t0
where where
opens = [st | (OSimple _,st) <- imps] opens = [st | (OSimple _,st) <- imps]
qualifs = [(m, st) | (OQualif m _, st) <- imps] ++ qualifs = [(m, st) | (OQualif m _, st) <- imps] ++
[(m, st) | (OQualif _ m, st) <- imps] ++ [(m, st) | (OQualif _ m, st) <- imps] ++
[(m, st) | (OSimple m, st) <- imps] -- qualif is always possible [(m, st) | (OSimple m, st) <- imps] -- qualif is always possible
-- this facility is mainly for BWC with GF1: you need not import PredefAbs -- this facility is mainly for BWC with GF1: you need not import PredefAbs
@@ -94,7 +94,7 @@ renameIdentTerm' env@(act,imps) t0 =
| isPredefCat c = return (Q (cPredefAbs,c)) | isPredefCat c = return (Q (cPredefAbs,c))
| otherwise = checkError s | otherwise = checkError s
ident alt c = ident alt c =
case Map.lookup c act of case Map.lookup c act of
Just f -> return (f c) Just f -> return (f c)
_ -> case mapMaybe (Map.lookup c) opens of _ -> case mapMaybe (Map.lookup c) opens of
@@ -157,7 +157,7 @@ modInfo2status (o,mo) = (o,tree2status o (jments mo))
self2status :: ModuleName -> ModuleInfo -> StatusMap self2status :: ModuleName -> ModuleInfo -> StatusMap
self2status c m = Map.mapWithKey (info2status (Just c)) (jments m) self2status c m = Map.mapWithKey (info2status (Just c)) (jments m)
renameInfo :: FilePath -> Status -> Module -> Ident -> Info -> Check Info renameInfo :: FilePath -> Status -> Module -> Ident -> Info -> Check Info
renameInfo cwd status (m,mi) i info = renameInfo cwd status (m,mi) i info =
case info of case info of
@@ -208,7 +208,7 @@ renameTerm env vars = ren vars where
Abs b x t -> liftM (Abs b x) (ren (x:vs) t) Abs b x t -> liftM (Abs b x) (ren (x:vs) t)
Prod bt x a b -> liftM2 (Prod bt x) (ren vs a) (ren (x:vs) b) Prod bt x a b -> liftM2 (Prod bt x) (ren vs a) (ren (x:vs) b)
Typed a b -> liftM2 Typed (ren vs a) (ren vs b) Typed a b -> liftM2 Typed (ren vs a) (ren vs b)
Vr x Vr x
| elem x vs -> return trm | elem x vs -> return trm
| otherwise -> renid trm | otherwise -> renid trm
Cn _ -> renid trm Cn _ -> renid trm
@@ -219,7 +219,7 @@ renameTerm env vars = ren vars where
i' <- case i of i' <- case i of
TTyped ty -> liftM TTyped $ ren vs ty -- the only annotation in source TTyped ty -> liftM TTyped $ ren vs ty -- the only annotation in source
_ -> return i _ -> return i
liftM (T i') $ mapM (renCase vs) cs liftM (T i') $ mapM (renCase vs) cs
Let (x,(m,a)) b -> do Let (x,(m,a)) b -> do
m' <- case m of m' <- case m of
@@ -229,7 +229,7 @@ renameTerm env vars = ren vars where
b' <- ren (x:vs) b b' <- ren (x:vs) b
return $ Let (x,(m',a')) b' return $ Let (x,(m',a')) b'
P t@(Vr r) l -- Here we have $r.l$ and this is ambiguous it could be either P t@(Vr r) l -- Here we have $r.l$ and this is ambiguous it could be either
-- record projection from variable or constant $r$ or qualified expression with module $r$ -- record projection from variable or constant $r$ or qualified expression with module $r$
| elem r vs -> return trm -- try var proj first .. | elem r vs -> return trm -- try var proj first ..
| otherwise -> checks [ renid' (Q (MN r,label2ident l)) -- .. and qualified expression second. | otherwise -> checks [ renid' (Q (MN r,label2ident l)) -- .. and qualified expression second.
@@ -331,7 +331,7 @@ renamePattern env patt =
renameContext :: Status -> Context -> Check Context renameContext :: Status -> Context -> Check Context
renameContext b = renc [] where renameContext b = renc [] where
renc vs cont = case cont of renc vs cont = case cont of
(bt,x,t) : xts (bt,x,t) : xts
| isWildIdent x -> do | isWildIdent x -> do
t' <- ren vs t t' <- ren vs t
xts' <- renc vs xts xts' <- renc vs xts

View File

@@ -5,7 +5,7 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/09/15 16:22:02 $ -- > CVS $Date: 2005/09/15 16:22:02 $
-- > CVS $Author: aarne $ -- > CVS $Author: aarne $
-- > CVS $Revision: 1.16 $ -- > CVS $Revision: 1.16 $
-- --
@@ -13,11 +13,11 @@
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module GF.Compile.TypeCheck.Abstract (-- * top-level type checking functions; TC should not be called directly. module GF.Compile.TypeCheck.Abstract (-- * top-level type checking functions; TC should not be called directly.
checkContext, checkContext,
checkTyp, checkTyp,
checkDef, checkDef,
checkConstrs, checkConstrs,
) where ) where
import GF.Data.Operations import GF.Data.Operations
@@ -33,8 +33,8 @@ import GF.Text.Pretty
--import Control.Monad (foldM, liftM, liftM2) --import Control.Monad (foldM, liftM, liftM2)
-- | invariant way of creating TCEnv from context -- | invariant way of creating TCEnv from context
initTCEnv gamma = initTCEnv gamma =
(length gamma,[(x,VGen i x) | ((x,_),i) <- zip gamma [0..]], gamma) (length gamma,[(x,VGen i x) | ((x,_),i) <- zip gamma [0..]], gamma)
-- interface to TC type checker -- interface to TC type checker

View File

@@ -69,7 +69,6 @@ computeLType gr g0 t = comp (reverse [(b,x, Vr x) | (b,x,_) <- g0] ++ g0) t
lockRecType c t' ---- locking to be removed AR 20/6/2009 lockRecType c t' ---- locking to be removed AR 20/6/2009
_ | ty == typeTok -> return typeStr _ | ty == typeTok -> return typeStr
_ | isPredefConstant ty -> return ty
_ -> composOp (comp g) ty _ -> composOp (comp g) ty

View File

@@ -396,7 +396,7 @@ tcRecTypeFields ge scope ((l,ty):rs) mb_ty = do
return ((l,ty):rs,mb_ty) return ((l,ty):rs,mb_ty)
-- | Invariant: if the third argument is (Just rho), -- | Invariant: if the third argument is (Just rho),
-- then rho is in weak-prenex form -- then rho is in weak-prenex form
instSigma :: GlobalEnv -> Scope -> Term -> Sigma -> Maybe Rho -> TcM (Term, Rho) instSigma :: GlobalEnv -> Scope -> Term -> Sigma -> Maybe Rho -> TcM (Term, Rho)
instSigma ge scope t ty1 Nothing = return (t,ty1) -- INST1 instSigma ge scope t ty1 Nothing = return (t,ty1) -- INST1
instSigma ge scope t ty1 (Just ty2) = do -- INST2 instSigma ge scope t ty1 (Just ty2) = do -- INST2
@@ -568,9 +568,9 @@ unifyVar ge scope i env vs ty2 = do -- Check whether i is bound
Bound ty1 -> do v <- liftErr (eval ge env ty1) Bound ty1 -> do v <- liftErr (eval ge env ty1)
unify ge scope (vapply (geLoc ge) v vs) ty2 unify ge scope (vapply (geLoc ge) v vs) ty2
Unbound scope' _ -> case value2term (geLoc ge) (scopeVars scope') ty2 of Unbound scope' _ -> case value2term (geLoc ge) (scopeVars scope') ty2 of
Left i -> let (v,_) = reverse scope !! i -- Left i -> let (v,_) = reverse scope !! i
in tcError ("Variable" <+> pp v <+> "has escaped") -- in tcError ("Variable" <+> pp v <+> "has escaped")
Right ty2' -> do ms2 <- getMetaVars (geLoc ge) [(scope,ty2)] ty2' -> do ms2 <- getMetaVars (geLoc ge) [(scope,ty2)]
if i `elem` ms2 if i `elem` ms2
then tcError ("Occurs check for" <+> ppMeta i <+> "in:" $$ then tcError ("Occurs check for" <+> ppMeta i <+> "in:" $$
nest 2 (ppTerm Unqualified 0 ty2')) nest 2 (ppTerm Unqualified 0 ty2'))
@@ -631,8 +631,8 @@ allBinders = [ identS [x] | x <- ['a'..'z'] ] ++
type Scope = [(Ident,Value)] type Scope = [(Ident,Value)]
type Sigma = Value type Sigma = Value
type Rho = Value -- No top-level ForAll type Rho = Value -- No top-level ForAll
type Tau = Value -- No ForAlls anywhere type Tau = Value -- No ForAlls anywhere
data MetaValue data MetaValue
= Unbound Scope Sigma = Unbound Scope Sigma
@@ -724,8 +724,8 @@ getMetaVars loc sc_tys = do
go (Vr tv) acc = acc go (Vr tv) acc = acc
go (App x y) acc = go x (go y acc) go (App x y) acc = go x (go y acc)
go (Meta i) acc go (Meta i) acc
| i `elem` acc = acc | i `elem` acc = acc
| otherwise = i : acc | otherwise = i : acc
go (Q _) acc = acc go (Q _) acc = acc
go (QC _) acc = acc go (QC _) acc = acc
go (Sort _) acc = acc go (Sort _) acc = acc
@@ -742,9 +742,9 @@ getFreeVars loc sc_tys = do
return (foldr (go []) [] tys) return (foldr (go []) [] tys)
where where
go bound (Vr tv) acc go bound (Vr tv) acc
| tv `elem` bound = acc | tv `elem` bound = acc
| tv `elem` acc = acc | tv `elem` acc = acc
| otherwise = tv : acc | otherwise = tv : acc
go bound (App x y) acc = go bound x (go bound y acc) go bound (App x y) acc = go bound x (go bound y acc)
go bound (Meta _) acc = acc go bound (Meta _) acc = acc
go bound (Q _) acc = acc go bound (Q _) acc = acc
@@ -765,9 +765,9 @@ zonkTerm (Meta i) = do
zonkTerm t = composOp zonkTerm t zonkTerm t = composOp zonkTerm t
tc_value2term loc xs v = tc_value2term loc xs v =
case value2term loc xs v of return $ value2term loc xs v
Left i -> tcError ("Variable #" <+> pp i <+> "has escaped") -- Old value2term error message:
Right t -> return t -- Left i -> tcError ("Variable #" <+> pp i <+> "has escaped")

View File

@@ -5,21 +5,22 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/10/02 20:50:19 $ -- > CVS $Date: 2005/10/02 20:50:19 $
-- > CVS $Author: aarne $ -- > CVS $Author: aarne $
-- > CVS $Revision: 1.11 $ -- > CVS $Revision: 1.11 $
-- --
-- Thierry Coquand's type checking algorithm that creates a trace -- Thierry Coquand's type checking algorithm that creates a trace
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module GF.Compile.TypeCheck.TC (AExp(..), module GF.Compile.TypeCheck.TC (
Theory, AExp(..),
checkExp, Theory,
inferExp, checkExp,
checkBranch, inferExp,
eqVal, checkBranch,
whnf eqVal,
) where whnf
) where
import GF.Data.Operations import GF.Data.Operations
import GF.Grammar import GF.Grammar
@@ -31,17 +32,17 @@ import Data.Maybe
import GF.Text.Pretty import GF.Text.Pretty
data AExp = data AExp =
AVr Ident Val AVr Ident Val
| ACn QIdent Val | ACn QIdent Val
| AType | AType
| AInt Int | AInt Int
| AFloat Double | AFloat Double
| AStr String | AStr String
| AMeta MetaId Val | AMeta MetaId Val
| ALet (Ident,(Val,AExp)) AExp | ALet (Ident,(Val,AExp)) AExp
| AApp AExp AExp Val | AApp AExp AExp Val
| AAbs Ident Val AExp | AAbs Ident Val AExp
| AProd Ident AExp AExp | AProd Ident AExp AExp
-- -- | AEqs [([Exp],AExp)] --- not used -- -- | AEqs [([Exp],AExp)] --- not used
| ARecType [ALabelling] | ARecType [ALabelling]
| AR [AAssign] | AR [AAssign]
@@ -50,7 +51,7 @@ data AExp =
| AData Val | AData Val
deriving (Eq,Show) deriving (Eq,Show)
type ALabelling = (Label, AExp) type ALabelling = (Label, AExp)
type AAssign = (Label, (Val, AExp)) type AAssign = (Label, (Val, AExp))
type Theory = QIdent -> Err Val type Theory = QIdent -> Err Val
@@ -71,7 +72,7 @@ whnf :: Val -> Err Val
whnf v = ---- errIn ("whnf" +++ prt v) $ ---- debug whnf v = ---- errIn ("whnf" +++ prt v) $ ---- debug
case v of case v of
VApp u w -> do VApp u w -> do
u' <- whnf u u' <- whnf u
w' <- whnf w w' <- whnf w
app u' w' app u' w'
VClos env e -> eval env e VClos env e -> eval env e
@@ -81,9 +82,9 @@ app :: Val -> Val -> Err Val
app u v = case u of app u v = case u of
VClos env (Abs _ x e) -> eval ((x,v):env) e VClos env (Abs _ x e) -> eval ((x,v):env) e
_ -> return $ VApp u v _ -> return $ VApp u v
eval :: Env -> Term -> Err Val eval :: Env -> Term -> Err Val
eval env e = ---- errIn ("eval" +++ prt e +++ "in" +++ prEnv env) $ eval env e = ---- errIn ("eval" +++ prt e +++ "in" +++ prEnv env) $
case e of case e of
Vr x -> lookupVar env x Vr x -> lookupVar env x
Q c -> return $ VCn c Q c -> return $ VCn c
@@ -95,23 +96,23 @@ eval env e = ---- errIn ("eval" +++ prt e +++ "in" +++ prEnv env) $
_ -> return $ VClos env e _ -> return $ VClos env e
eqVal :: Int -> Val -> Val -> Err [(Val,Val)] eqVal :: Int -> Val -> Val -> Err [(Val,Val)]
eqVal k u1 u2 = ---- errIn (prt u1 +++ "<>" +++ prBracket (show k) +++ prt u2) $ eqVal k u1 u2 = ---- errIn (prt u1 +++ "<>" +++ prBracket (show k) +++ prt u2) $
do do
w1 <- whnf u1 w1 <- whnf u1
w2 <- whnf u2 w2 <- whnf u2
let v = VGen k let v = VGen k
case (w1,w2) of case (w1,w2) of
(VApp f1 a1, VApp f2 a2) -> liftM2 (++) (eqVal k f1 f2) (eqVal k a1 a2) (VApp f1 a1, VApp f2 a2) -> liftM2 (++) (eqVal k f1 f2) (eqVal k a1 a2)
(VClos env1 (Abs _ x1 e1), VClos env2 (Abs _ x2 e2)) -> (VClos env1 (Abs _ x1 e1), VClos env2 (Abs _ x2 e2)) ->
eqVal (k+1) (VClos ((x1,v x1):env1) e1) (VClos ((x2,v x1):env2) e2) eqVal (k+1) (VClos ((x1,v x1):env1) e1) (VClos ((x2,v x1):env2) e2)
(VClos env1 (Prod _ x1 a1 e1), VClos env2 (Prod _ x2 a2 e2)) -> (VClos env1 (Prod _ x1 a1 e1), VClos env2 (Prod _ x2 a2 e2)) ->
liftM2 (++) liftM2 (++)
(eqVal k (VClos env1 a1) (VClos env2 a2)) (eqVal k (VClos env1 a1) (VClos env2 a2))
(eqVal (k+1) (VClos ((x1,v x1):env1) e1) (VClos ((x2,v x1):env2) e2)) (eqVal (k+1) (VClos ((x1,v x1):env1) e1) (VClos ((x2,v x1):env2) e2))
(VGen i _, VGen j _) -> return [(w1,w2) | i /= j] (VGen i _, VGen j _) -> return [(w1,w2) | i /= j]
(VCn (_, i), VCn (_,j)) -> return [(w1,w2) | i /= j] (VCn (_, i), VCn (_,j)) -> return [(w1,w2) | i /= j]
--- thus ignore qualifications; valid because inheritance cannot --- thus ignore qualifications; valid because inheritance cannot
--- be qualified. Simplifies annotation. AR 17/3/2005 --- be qualified. Simplifies annotation. AR 17/3/2005
_ -> return [(w1,w2) | w1 /= w2] _ -> return [(w1,w2) | w1 /= w2]
-- invariant: constraints are in whnf -- invariant: constraints are in whnf
@@ -127,10 +128,10 @@ checkExp th tenv@(k,rho,gamma) e ty = do
Abs _ x t -> case typ of Abs _ x t -> case typ of
VClos env (Prod _ y a b) -> do VClos env (Prod _ y a b) -> do
a' <- whnf $ VClos env a --- a' <- whnf $ VClos env a ---
(t',cs) <- checkExp th (t',cs) <- checkExp th
(k+1,(x,v x):rho, (x,a'):gamma) t (VClos ((y,v x):env) b) (k+1,(x,v x):rho, (x,a'):gamma) t (VClos ((y,v x):env) b)
return (AAbs x a' t', cs) return (AAbs x a' t', cs)
_ -> Bad (render ("function type expected for" <+> ppTerm Unqualified 0 e <+> "instead of" <+> ppValue Unqualified 0 typ)) _ -> Bad (render ("function type expected for" <+> ppTerm Unqualified 0 e <+> "instead of" <+> ppValue Unqualified 0 typ))
Let (x, (mb_typ, e1)) e2 -> do Let (x, (mb_typ, e1)) e2 -> do
@@ -150,7 +151,7 @@ checkExp th tenv@(k,rho,gamma) e ty = do
(b',csb) <- checkType th (k+1, (x,v x):rho, (x,VClos rho a):gamma) b (b',csb) <- checkType th (k+1, (x,v x):rho, (x,VClos rho a):gamma) b
return (AProd x a' b', csa ++ csb) return (AProd x a' b', csa ++ csb)
R xs -> R xs ->
case typ of case typ of
VRecType ys -> do case [l | (l,_) <- ys, isNothing (lookup l xs)] of VRecType ys -> do case [l | (l,_) <- ys, isNothing (lookup l xs)] of
[] -> return () [] -> return ()
@@ -174,7 +175,7 @@ checkInferExp th tenv@(k,_,_) e typ = do
(e',w,cs1) <- inferExp th tenv e (e',w,cs1) <- inferExp th tenv e
cs2 <- eqVal k w typ cs2 <- eqVal k w typ
return (e',cs1 ++ cs2) return (e',cs1 ++ cs2)
inferExp :: Theory -> TCEnv -> Term -> Err (AExp, Val, [(Val,Val)]) inferExp :: Theory -> TCEnv -> Term -> Err (AExp, Val, [(Val,Val)])
inferExp th tenv@(k,rho,gamma) e = case e of inferExp th tenv@(k,rho,gamma) e = case e of
Vr x -> mkAnnot (AVr x) $ noConstr $ lookupVar gamma x Vr x -> mkAnnot (AVr x) $ noConstr $ lookupVar gamma x
@@ -200,13 +201,13 @@ inferExp th tenv@(k,rho,gamma) e = case e of
(e2,val2,cs2) <- inferExp th (k,rho,(x,val1):gamma) e2 (e2,val2,cs2) <- inferExp th (k,rho,(x,val1):gamma) e2
return (ALet (x,(val1,e1)) e2, val2, cs1++cs2) return (ALet (x,(val1,e1)) e2, val2, cs1++cs2)
App f t -> do App f t -> do
(f',w,csf) <- inferExp th tenv f (f',w,csf) <- inferExp th tenv f
typ <- whnf w typ <- whnf w
case typ of case typ of
VClos env (Prod _ x a b) -> do VClos env (Prod _ x a b) -> do
(a',csa) <- checkExp th tenv t (VClos env a) (a',csa) <- checkExp th tenv t (VClos env a)
b' <- whnf $ VClos ((x,VClos rho t):env) b b' <- whnf $ VClos ((x,VClos rho t):env) b
return $ (AApp f' a' b', b', csf ++ csa) return $ (AApp f' a' b', b', csf ++ csa)
_ -> Bad (render ("Prod expected for function" <+> ppTerm Unqualified 0 f <+> "instead of" <+> ppValue Unqualified 0 typ)) _ -> Bad (render ("Prod expected for function" <+> ppTerm Unqualified 0 f <+> "instead of" <+> ppValue Unqualified 0 typ))
_ -> Bad (render ("cannot infer type of expression" <+> ppTerm Unqualified 0 e)) _ -> Bad (render ("cannot infer type of expression" <+> ppTerm Unqualified 0 e))
@@ -232,9 +233,9 @@ checkAssign th tenv@(k,rho,gamma) typs (lbl,(Nothing,exp)) = do
return ((lbl,(val,aexp)),cs) return ((lbl,(val,aexp)),cs)
checkBranch :: Theory -> TCEnv -> Equation -> Val -> Err (([Term],AExp),[(Val,Val)]) checkBranch :: Theory -> TCEnv -> Equation -> Val -> Err (([Term],AExp),[(Val,Val)])
checkBranch th tenv b@(ps,t) ty = errIn ("branch" +++ show b) $ checkBranch th tenv b@(ps,t) ty = errIn ("branch" +++ show b) $
chB tenv' ps' ty chB tenv' ps' ty
where where
(ps',_,rho2,k') = ps2ts k ps (ps',_,rho2,k') = ps2ts k ps
tenv' = (k, rho2++rho, gamma) ---- k' ? tenv' = (k, rho2++rho, gamma) ---- k' ?
@@ -245,11 +246,11 @@ checkBranch th tenv b@(ps,t) ty = errIn ("branch" +++ show b) $
typ <- whnf ty typ <- whnf ty
case typ of case typ of
VClos env (Prod _ y a b) -> do VClos env (Prod _ y a b) -> do
a' <- whnf $ VClos env a a' <- whnf $ VClos env a
(p', sigma, binds, cs1) <- checkP tenv p y a' (p', sigma, binds, cs1) <- checkP tenv p y a'
let tenv' = (length binds, sigma ++ rho, binds ++ gamma) let tenv' = (length binds, sigma ++ rho, binds ++ gamma)
((ps',exp),cs2) <- chB tenv' ps2 (VClos ((y,p'):env) b) ((ps',exp),cs2) <- chB tenv' ps2 (VClos ((y,p'):env) b)
return ((p:ps',exp), cs1 ++ cs2) -- don't change the patt return ((p:ps',exp), cs1 ++ cs2) -- don't change the patt
_ -> Bad (render ("Product expected for definiens" <+> ppTerm Unqualified 0 t <+> "instead of" <+> ppValue Unqualified 0 typ)) _ -> Bad (render ("Product expected for definiens" <+> ppTerm Unqualified 0 t <+> "instead of" <+> ppValue Unqualified 0 typ))
[] -> do [] -> do
(e,cs) <- checkExp th tenv t ty (e,cs) <- checkExp th tenv t ty
@@ -259,15 +260,15 @@ checkBranch th tenv b@(ps,t) ty = errIn ("branch" +++ show b) $
let sigma = [(x, VGen i x) | ((x,_),i) <- zip delta [k..]] let sigma = [(x, VGen i x) | ((x,_),i) <- zip delta [k..]]
return (VClos sigma t, sigma, delta, cs) return (VClos sigma t, sigma, delta, cs)
ps2ts k = foldr p2t ([],0,[],k) ps2ts k = foldr p2t ([],0,[],k)
p2t p (ps,i,g,k) = case p of p2t p (ps,i,g,k) = case p of
PW -> (Meta i : ps, i+1,g,k) PW -> (Meta i : ps, i+1,g,k)
PV x -> (Vr x : ps, i, upd x k g,k+1) PV x -> (Vr x : ps, i, upd x k g,k+1)
PAs x p -> p2t p (ps,i,g,k) PAs x p -> p2t p (ps,i,g,k)
PString s -> (K s : ps, i, g, k) PString s -> (K s : ps, i, g, k)
PInt n -> (EInt n : ps, i, g, k) PInt n -> (EInt n : ps, i, g, k)
PFloat n -> (EFloat n : ps, i, g, k) PFloat n -> (EFloat n : ps, i, g, k)
PP c xs -> (mkApp (Q c) xss : ps, j, g',k') PP c xs -> (mkApp (Q c) xss : ps, j, g',k')
where (xss,j,g',k') = foldr p2t ([],i,g,k) xs where (xss,j,g',k') = foldr p2t ([],i,g,k) xs
PImplArg p -> p2t p (ps,i,g,k) PImplArg p -> p2t p (ps,i,g,k)
PTilde t -> (t : ps, i, g, k) PTilde t -> (t : ps, i, g, k)
@@ -307,8 +308,8 @@ checkPatt th tenv exp val = do
case typ of case typ of
VClos env (Prod _ x a b) -> do VClos env (Prod _ x a b) -> do
(a',_,csa) <- checkExpP tenv t (VClos env a) (a',_,csa) <- checkExpP tenv t (VClos env a)
b' <- whnf $ VClos ((x,VClos rho t):env) b b' <- whnf $ VClos ((x,VClos rho t):env) b
return $ (AApp f' a' b', b', csf ++ csa) return $ (AApp f' a' b', b', csf ++ csa)
_ -> Bad (render ("Prod expected for function" <+> ppTerm Unqualified 0 f <+> "instead of" <+> ppValue Unqualified 0 typ)) _ -> Bad (render ("Prod expected for function" <+> ppTerm Unqualified 0 f <+> "instead of" <+> ppValue Unqualified 0 typ))
_ -> Bad (render ("cannot typecheck pattern" <+> ppTerm Unqualified 0 exp)) _ -> Bad (render ("cannot typecheck pattern" <+> ppTerm Unqualified 0 exp))
@@ -321,4 +322,3 @@ mkAnnot :: (Val -> AExp) -> Err (Val,[(Val,Val)]) -> Err (AExp,Val,[(Val,Val)])
mkAnnot a ti = do mkAnnot a ti = do
(v,cs) <- ti (v,cs) <- ti
return (a v, v, cs) return (a v, v, cs)

View File

@@ -5,7 +5,7 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/05/30 18:39:44 $ -- > CVS $Date: 2005/05/30 18:39:44 $
-- > CVS $Author: aarne $ -- > CVS $Author: aarne $
-- > CVS $Revision: 1.8 $ -- > CVS $Revision: 1.8 $
-- --
@@ -34,14 +34,14 @@ buildAnyTree :: Fail.MonadFail m => ModuleName -> [(Ident,Info)] -> m (Map.Map I
buildAnyTree m = go Map.empty buildAnyTree m = go Map.empty
where where
go map [] = return map go map [] = return map
go map ((c,j):is) = do go map ((c,j):is) =
case Map.lookup c map of case Map.lookup c map of
Just i -> case unifyAnyInfo m i j of Just i -> case unifyAnyInfo m i j of
Ok k -> go (Map.insert c k map) is Ok k -> go (Map.insert c k map) is
Bad _ -> fail $ render ("conflicting information in module"<+>m $$ Bad _ -> fail $ render ("conflicting information in module"<+>m $$
nest 4 (ppJudgement Qualified (c,i)) $$ nest 4 (ppJudgement Qualified (c,i)) $$
"and" $+$ "and" $+$
nest 4 (ppJudgement Qualified (c,j))) nest 4 (ppJudgement Qualified (c,j)))
Nothing -> go (Map.insert c j map) is Nothing -> go (Map.insert c j map) is
extendModule :: FilePath -> SourceGrammar -> SourceModule -> Check SourceModule extendModule :: FilePath -> SourceGrammar -> SourceModule -> Check SourceModule
@@ -51,14 +51,14 @@ extendModule cwd gr (name,m)
---- Should be replaced by real control. AR 4/2/2005 ---- Should be replaced by real control. AR 4/2/2005
| mstatus m == MSIncomplete && isModCnc m = return (name,m) | mstatus m == MSIncomplete && isModCnc m = return (name,m)
| otherwise = checkInModule cwd m NoLoc empty $ do | otherwise = checkInModule cwd m NoLoc empty $ do
m' <- foldM extOne m (mextend m) m' <- foldM extOne m (mextend m)
return (name,m') return (name,m')
where where
extOne mo (n,cond) = do extOne mo (n,cond) = do
m0 <- lookupModule gr n m0 <- lookupModule gr n
-- test that the module types match, and find out if the old is complete -- test that the module types match, and find out if the old is complete
unless (sameMType (mtype m) (mtype mo)) unless (sameMType (mtype m) (mtype mo))
(checkError ("illegal extension type to module" <+> name)) (checkError ("illegal extension type to module" <+> name))
let isCompl = isCompleteModule m0 let isCompl = isCompleteModule m0
@@ -67,7 +67,7 @@ extendModule cwd gr (name,m)
js1 <- extendMod gr isCompl ((n,m0), isInherited cond) name (jments mo) js1 <- extendMod gr isCompl ((n,m0), isInherited cond) name (jments mo)
-- if incomplete, throw away extension information -- if incomplete, throw away extension information
return $ return $
if isCompl if isCompl
then mo {jments = js1} then mo {jments = js1}
else mo {mextend= filter ((/=n) . fst) (mextend mo) else mo {mextend= filter ((/=n) . fst) (mextend mo)
@@ -75,7 +75,7 @@ extendModule cwd gr (name,m)
,jments = js1 ,jments = js1
} }
-- | rebuilding instance + interface, and "with" modules, prior to renaming. -- | rebuilding instance + interface, and "with" modules, prior to renaming.
-- AR 24/10/2003 -- AR 24/10/2003
rebuildModule :: FilePath -> SourceGrammar -> SourceModule -> Check SourceModule rebuildModule :: FilePath -> SourceGrammar -> SourceModule -> Check SourceModule
rebuildModule cwd gr mo@(i,mi@(ModInfo mt stat fs_ me mw ops_ med_ msrc_ env_ js_)) = rebuildModule cwd gr mo@(i,mi@(ModInfo mt stat fs_ me mw ops_ med_ msrc_ env_ js_)) =
@@ -88,8 +88,8 @@ rebuildModule cwd gr mo@(i,mi@(ModInfo mt stat fs_ me mw ops_ med_ msrc_ env_ js
-- add the information given in interface into an instance module -- add the information given in interface into an instance module
Nothing -> do Nothing -> do
unless (null is || mstatus mi == MSIncomplete) unless (null is || mstatus mi == MSIncomplete)
(checkError ("module" <+> i <+> (checkError ("module" <+> i <+>
"has open interfaces and must therefore be declared incomplete")) "has open interfaces and must therefore be declared incomplete"))
case mt of case mt of
MTInstance (i0,mincl) -> do MTInstance (i0,mincl) -> do
@@ -113,7 +113,7 @@ rebuildModule cwd gr mo@(i,mi@(ModInfo mt stat fs_ me mw ops_ med_ msrc_ env_ js
let stat' = if all (flip elem infs) is let stat' = if all (flip elem infs) is
then MSComplete then MSComplete
else MSIncomplete else MSIncomplete
unless (stat' == MSComplete || stat == MSIncomplete) unless (stat' == MSComplete || stat == MSIncomplete)
(checkError ("module" <+> i <+> "remains incomplete")) (checkError ("module" <+> i <+> "remains incomplete"))
ModInfo mt0 _ fs me' _ ops0 _ fpath _ js <- lookupModule gr ext ModInfo mt0 _ fs me' _ ops0 _ fpath _ js <- lookupModule gr ext
let ops1 = nub $ let ops1 = nub $
@@ -141,24 +141,24 @@ rebuildModule cwd gr mo@(i,mi@(ModInfo mt stat fs_ me mw ops_ med_ msrc_ env_ js
extendMod :: Grammar -> extendMod :: Grammar ->
Bool -> (Module,Ident -> Bool) -> ModuleName -> Bool -> (Module,Ident -> Bool) -> ModuleName ->
Map.Map Ident Info -> Check (Map.Map Ident Info) Map.Map Ident Info -> Check (Map.Map Ident Info)
extendMod gr isCompl ((name,mi),cond) base new = foldM try new $ Map.toList (jments mi) extendMod gr isCompl ((name,mi),cond) base new = foldM try new $ Map.toList (jments mi)
where where
try new (c,i0) try new (c,i0)
| not (cond c) = return new | not (cond c) = return new
| otherwise = case Map.lookup c new of | otherwise = case Map.lookup c new of
Just j -> case unifyAnyInfo name i j of Just j -> case unifyAnyInfo name i j of
Ok k -> return $ Map.insert c k new Ok k -> return $ Map.insert c k new
Bad _ -> do (base,j) <- case j of Bad _ -> do (base,j) <- case j of
AnyInd _ m -> lookupOrigInfo gr (m,c) AnyInd _ m -> lookupOrigInfo gr (m,c)
_ -> return (base,j) _ -> return (base,j)
(name,i) <- case i of (name,i) <- case i of
AnyInd _ m -> lookupOrigInfo gr (m,c) AnyInd _ m -> lookupOrigInfo gr (m,c)
_ -> return (name,i) _ -> return (name,i)
checkError ("cannot unify the information" $$ checkError ("cannot unify the information" $$
nest 4 (ppJudgement Qualified (c,i)) $$ nest 4 (ppJudgement Qualified (c,i)) $$
"in module" <+> name <+> "with" $$ "in module" <+> name <+> "with" $$
nest 4 (ppJudgement Qualified (c,j)) $$ nest 4 (ppJudgement Qualified (c,j)) $$
"in module" <+> base) "in module" <+> base)
Nothing-> if isCompl Nothing-> if isCompl
then return $ Map.insert c (indirInfo name i) new then return $ Map.insert c (indirInfo name i) new
else return $ Map.insert c i new else return $ Map.insert c i new
@@ -166,11 +166,11 @@ extendMod gr isCompl ((name,mi),cond) base new = foldM try new $ Map.toList (jme
i = globalizeLoc (msrc mi) i0 i = globalizeLoc (msrc mi) i0
indirInfo :: ModuleName -> Info -> Info indirInfo :: ModuleName -> Info -> Info
indirInfo n info = AnyInd b n' where indirInfo n info = AnyInd b n' where
(b,n') = case info of (b,n') = case info of
ResValue _ -> (True,n) ResValue _ -> (True,n)
ResParam _ _ -> (True,n) ResParam _ _ -> (True,n)
AbsFun _ _ Nothing _ -> (True,n) AbsFun _ _ Nothing _ -> (True,n)
AnyInd b k -> (b,k) AnyInd b k -> (b,k)
_ -> (False,n) ---- canonical in Abs _ -> (False,n) ---- canonical in Abs
@@ -194,24 +194,24 @@ globalizeLoc fpath i =
unifyAnyInfo :: ModuleName -> Info -> Info -> Err Info unifyAnyInfo :: ModuleName -> Info -> Info -> Err Info
unifyAnyInfo m i j = case (i,j) of unifyAnyInfo m i j = case (i,j) of
(AbsCat mc1, AbsCat mc2) -> (AbsCat mc1, AbsCat mc2) ->
liftM AbsCat (unifyMaybeL mc1 mc2) liftM AbsCat (unifyMaybeL mc1 mc2)
(AbsFun mt1 ma1 md1 moper1, AbsFun mt2 ma2 md2 moper2) -> (AbsFun mt1 ma1 md1 moper1, AbsFun mt2 ma2 md2 moper2) ->
liftM4 AbsFun (unifyMaybeL mt1 mt2) (unifAbsArrity ma1 ma2) (unifAbsDefs md1 md2) (unifyMaybe moper1 moper2) -- adding defs liftM4 AbsFun (unifyMaybeL mt1 mt2) (unifAbsArrity ma1 ma2) (unifAbsDefs md1 md2) (unifyMaybe moper1 moper2) -- adding defs
(ResParam mt1 mv1, ResParam mt2 mv2) -> (ResParam mt1 mv1, ResParam mt2 mv2) ->
liftM2 ResParam (unifyMaybeL mt1 mt2) (unifyMaybe mv1 mv2) liftM2 ResParam (unifyMaybeL mt1 mt2) (unifyMaybe mv1 mv2)
(ResValue (L l1 t1), ResValue (L l2 t2)) (ResValue (L l1 t1), ResValue (L l2 t2))
| t1==t2 -> return (ResValue (L l1 t1)) | t1==t2 -> return (ResValue (L l1 t1))
| otherwise -> fail "" | otherwise -> fail ""
(_, ResOverload ms t) | elem m ms -> (_, ResOverload ms t) | elem m ms ->
return $ ResOverload ms t return $ ResOverload ms t
(ResOper mt1 m1, ResOper mt2 m2) -> (ResOper mt1 m1, ResOper mt2 m2) ->
liftM2 ResOper (unifyMaybeL mt1 mt2) (unifyMaybeL m1 m2) liftM2 ResOper (unifyMaybeL mt1 mt2) (unifyMaybeL m1 m2)
(CncCat mc1 md1 mr1 mp1 mpmcfg1, CncCat mc2 md2 mr2 mp2 mpmcfg2) -> (CncCat mc1 md1 mr1 mp1 mpmcfg1, CncCat mc2 md2 mr2 mp2 mpmcfg2) ->
liftM5 CncCat (unifyMaybeL mc1 mc2) (unifyMaybeL md1 md2) (unifyMaybeL mr1 mr2) (unifyMaybeL mp1 mp2) (unifyMaybe mpmcfg1 mpmcfg2) liftM5 CncCat (unifyMaybeL mc1 mc2) (unifyMaybeL md1 md2) (unifyMaybeL mr1 mr2) (unifyMaybeL mp1 mp2) (unifyMaybe mpmcfg1 mpmcfg2)
(CncFun m mt1 md1 mpmcfg1, CncFun _ mt2 md2 mpmcfg2) -> (CncFun m mt1 md1 mpmcfg1, CncFun _ mt2 md2 mpmcfg2) ->
liftM3 (CncFun m) (unifyMaybeL mt1 mt2) (unifyMaybeL md1 md2) (unifyMaybe mpmcfg1 mpmcfg2) liftM3 (CncFun m) (unifyMaybeL mt1 mt2) (unifyMaybeL md1 md2) (unifyMaybe mpmcfg1 mpmcfg2)
(AnyInd b1 m1, AnyInd b2 m2) -> do (AnyInd b1 m1, AnyInd b2 m2) -> do

View File

@@ -16,18 +16,18 @@
{-# LANGUAGE CPP #-} {-# LANGUAGE CPP #-}
module GF.Data.BacktrackM ( module GF.Data.BacktrackM (
-- * the backtracking state monad -- * the backtracking state monad
BacktrackM, BacktrackM,
-- * monad specific utilities -- * monad specific utilities
member, member,
cut, cut,
-- * running the monad -- * running the monad
foldBM, runBM, foldBM, runBM,
foldSolutions, solutions, foldSolutions, solutions,
foldFinalStates, finalStates, foldFinalStates, finalStates,
-- * reexport the 'MonadState' class -- * reexport the 'MonadState' class
module Control.Monad.State.Class, module Control.Monad.State.Class,
) where ) where
import Data.List import Data.List
import Control.Applicative import Control.Applicative
@@ -70,7 +70,7 @@ instance Applicative (BacktrackM s) where
instance Monad (BacktrackM s) where instance Monad (BacktrackM s) where
return a = BM (\c s b -> c a s b) return a = BM (\c s b -> c a s b)
BM m >>= k = BM (\c s b -> m (\a s b -> unBM (k a) c s b) s b) BM m >>= k = BM (\c s b -> m (\a s b -> unBM (k a) c s b) s b)
where unBM (BM m) = m where unBM (BM m) = m
#if !(MIN_VERSION_base(4,13,0)) #if !(MIN_VERSION_base(4,13,0))
fail = Fail.fail fail = Fail.fail

View File

@@ -5,7 +5,7 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/11/10 16:43:44 $ -- > CVS $Date: 2005/11/10 16:43:44 $
-- > CVS $Author: bringert $ -- > CVS $Author: bringert $
-- > CVS $Revision: 1.2 $ -- > CVS $Revision: 1.2 $
-- --
@@ -34,7 +34,7 @@ import Data.Set (Set)
import qualified Data.Set as Set import qualified Data.Set as Set
data Graph n a b = Graph [n] ![Node n a] ![Edge n b] data Graph n a b = Graph [n] ![Node n a] ![Edge n b]
deriving (Eq,Show) deriving (Eq,Show)
type Node n a = (n,a) type Node n a = (n,a)
type Edge n b = (n,n,b) type Edge n b = (n,n,b)
@@ -63,7 +63,7 @@ emap f (Graph c ns es) = Graph c ns [(x,y,f l) | (x,y,l) <- es]
-- | Add a node to the graph. -- | Add a node to the graph.
newNode :: a -- ^ Node label newNode :: a -- ^ Node label
-> Graph n a b -> Graph n a b
-> (Graph n a b,n) -- ^ Node graph and name of new node -> (Graph n a b,n) -- ^ Node graph and name of new node
newNode l (Graph (c:cs) ns es) = (Graph cs ((c,l):ns) es, c) newNode l (Graph (c:cs) ns es) = (Graph cs ((c,l):ns) es, c)
@@ -83,7 +83,7 @@ newEdges es g = foldl' (flip newEdge) g es
-- lazy version: -- lazy version:
-- newEdges es' (Graph c ns es) = Graph c ns (es'++es) -- newEdges es' (Graph c ns es) = Graph c ns (es'++es)
insertEdgeWith :: Eq n => insertEdgeWith :: Eq n =>
(b -> b -> b) -> Edge n b -> Graph n a b -> Graph n a b (b -> b -> b) -> Edge n b -> Graph n a b -> Graph n a b
insertEdgeWith f e@(x,y,l) (Graph c ns es) = Graph c ns (h es) insertEdgeWith f e@(x,y,l) (Graph c ns es) = Graph c ns (h es)
where h [] = [e] where h [] = [e]
@@ -97,7 +97,7 @@ removeNode n = removeNodes (Set.singleton n)
-- | Remove a set of nodes and all edges to and from those nodes. -- | Remove a set of nodes and all edges to and from those nodes.
removeNodes :: Ord n => Set n -> Graph n a b -> Graph n a b removeNodes :: Ord n => Set n -> Graph n a b -> Graph n a b
removeNodes xs (Graph c ns es) = Graph c ns' es' removeNodes xs (Graph c ns es) = Graph c ns' es'
where where
keepNode n = not (Set.member n xs) keepNode n = not (Set.member n xs)
ns' = [ x | x@(n,_) <- ns, keepNode n ] ns' = [ x | x@(n,_) <- ns, keepNode n ]
es' = [ e | e@(f,t,_) <- es, keepNode f && keepNode t ] es' = [ e | e@(f,t,_) <- es, keepNode f && keepNode t ]
@@ -105,7 +105,7 @@ removeNodes xs (Graph c ns es) = Graph c ns' es'
-- | Get a map of node names to info about each node. -- | Get a map of node names to info about each node.
nodeInfo :: Ord n => Graph n a b -> NodeInfo n a b nodeInfo :: Ord n => Graph n a b -> NodeInfo n a b
nodeInfo g = Map.fromList [ (n, (x, fn inc n, fn out n)) | (n,x) <- nodes g ] nodeInfo g = Map.fromList [ (n, (x, fn inc n, fn out n)) | (n,x) <- nodes g ]
where where
inc = groupEdgesBy edgeTo g inc = groupEdgesBy edgeTo g
out = groupEdgesBy edgeFrom g out = groupEdgesBy edgeFrom g
fn m n = fromMaybe [] (Map.lookup n m) fn m n = fromMaybe [] (Map.lookup n m)
@@ -148,16 +148,16 @@ reverseGraph :: Graph n a b -> Graph n a b
reverseGraph (Graph c ns es) = Graph c ns [ (t,f,l) | (f,t,l) <- es ] reverseGraph (Graph c ns es) = Graph c ns [ (t,f,l) | (f,t,l) <- es ]
-- | Add the nodes from the second graph to the first graph. -- | Add the nodes from the second graph to the first graph.
-- The nodes in the second graph will be renamed using the name -- The nodes in the second graph will be renamed using the name
-- supply in the first graph. -- supply in the first graph.
-- This function is more efficient when the second graph -- This function is more efficient when the second graph
-- is smaller than the first. -- is smaller than the first.
mergeGraphs :: Ord m => Graph n a b -> Graph m a b mergeGraphs :: Ord m => Graph n a b -> Graph m a b
-> (Graph n a b, m -> n) -- ^ The new graph and a function translating -> (Graph n a b, m -> n) -- ^ The new graph and a function translating
-- the old names of nodes in the second graph -- the old names of nodes in the second graph
-- to names in the new graph. -- to names in the new graph.
mergeGraphs (Graph c ns1 es1) g2 = (Graph c' (ns2++ns1) (es2++es1), newName) mergeGraphs (Graph c ns1 es1) g2 = (Graph c' (ns2++ns1) (es2++es1), newName)
where where
(xs,c') = splitAt (length (nodes g2)) c (xs,c') = splitAt (length (nodes g2)) c
newNames = Map.fromList (zip (map fst (nodes g2)) xs) newNames = Map.fromList (zip (map fst (nodes g2)) xs)
newName n = fromJust $ Map.lookup n newNames newName n = fromJust $ Map.lookup n newNames
@@ -170,7 +170,7 @@ renameNodes :: (n -> m) -- ^ renaming function
-> Graph n a b -> Graph m a b -> Graph n a b -> Graph m a b
renameNodes newName c (Graph _ ns es) = Graph c ns' es' renameNodes newName c (Graph _ ns es) = Graph c ns' es'
where ns' = map' (\ (n,x) -> (newName n,x)) ns where ns' = map' (\ (n,x) -> (newName n,x)) ns
es' = map' (\ (f,t,l) -> (newName f, newName t, l)) es es' = map' (\ (f,t,l) -> (newName f, newName t, l)) es
-- | A strict 'map' -- | A strict 'map'
map' :: (a -> b) -> [a] -> [b] map' :: (a -> b) -> [a] -> [b]

View File

@@ -5,7 +5,7 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/09/15 18:10:44 $ -- > CVS $Date: 2005/09/15 18:10:44 $
-- > CVS $Author: bringert $ -- > CVS $Author: bringert $
-- > CVS $Revision: 1.2 $ -- > CVS $Revision: 1.2 $
-- --
@@ -13,14 +13,14 @@
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module GF.Data.Graphviz ( module GF.Data.Graphviz (
Graph(..), GraphType(..), Graph(..), GraphType(..),
Node(..), Edge(..), Node(..), Edge(..),
Attr, Attr,
addSubGraphs, addSubGraphs,
setName, setName,
setAttr, setAttr,
prGraphviz prGraphviz
) where ) where
import Data.Char import Data.Char
@@ -70,14 +70,14 @@ prGraphviz g@(Graph t i _ _ _ _) =
graphtype t ++ " " ++ maybe "" esc i ++ " {\n" ++ prGraph g ++ "}\n" graphtype t ++ " " ++ maybe "" esc i ++ " {\n" ++ prGraph g ++ "}\n"
prSubGraph :: Graph -> String prSubGraph :: Graph -> String
prSubGraph g@(Graph _ i _ _ _ _) = prSubGraph g@(Graph _ i _ _ _ _) =
"subgraph" ++ " " ++ maybe "" esc i ++ " {\n" ++ prGraph g ++ "}" "subgraph" ++ " " ++ maybe "" esc i ++ " {\n" ++ prGraph g ++ "}"
prGraph :: Graph -> String prGraph :: Graph -> String
prGraph (Graph t id at ns es ss) = prGraph (Graph t id at ns es ss) =
unlines $ map (++";") (map prAttr at unlines $ map (++";") (map prAttr at
++ map prNode ns ++ map prNode ns
++ map (prEdge t) es ++ map (prEdge t) es
++ map prSubGraph ss) ++ map prSubGraph ss)
graphtype :: GraphType -> String graphtype :: GraphType -> String
@@ -96,7 +96,7 @@ edgeop Undirected = "--"
prAttrList :: [Attr] -> String prAttrList :: [Attr] -> String
prAttrList [] = "" prAttrList [] = ""
prAttrList at = "[" ++ join "," (map prAttr at) ++ "]" prAttrList at = "[" ++ join "," (map prAttr at) ++ "]"
prAttr :: Attr -> String prAttr :: Attr -> String
prAttr (n,v) = esc n ++ " = " ++ esc v prAttr (n,v) = esc n ++ " = " ++ esc v

View File

@@ -5,7 +5,7 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/11/11 16:12:41 $ -- > CVS $Date: 2005/11/11 16:12:41 $
-- > CVS $Author: bringert $ -- > CVS $Author: bringert $
-- > CVS $Revision: 1.22 $ -- > CVS $Revision: 1.22 $
-- --
@@ -15,34 +15,34 @@
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module GF.Data.Operations ( module GF.Data.Operations (
-- ** The Error monad -- ** The Error monad
Err(..), err, maybeErr, testErr, fromErr, errIn, Err(..), err, maybeErr, testErr, fromErr, errIn,
lookupErr, lookupErr,
-- ** Error monad class -- ** Error monad class
ErrorMonad(..), checks, --doUntil, allChecks, checkAgain, ErrorMonad(..), checks, --doUntil, allChecks, checkAgain,
liftErr, liftErr,
-- ** Checking
checkUnique, unifyMaybeBy, unifyMaybe,
-- ** Monadic operations on lists and pairs -- ** Checking
mapPairsM, pairM, checkUnique, unifyMaybeBy, unifyMaybe,
-- ** Printing
indent, (+++), (++-), (++++), (+++-), (+++++),
prUpper, prReplicate, prTList, prQuotedString, prParenth, prCurly,
prBracket, prArgList, prSemicList, prCurlyList, restoreEscapes,
numberedParagraphs, prConjList, prIfEmpty, wrapLines,
-- ** Topological sorting -- ** Monadic operations on lists and pairs
topoTest, topoTest2, mapPairsM, pairM,
-- ** Misc -- ** Printing
readIntArg, indent, (+++), (++-), (++++), (+++-), (+++++),
iterFix, chunks, prUpper, prReplicate, prTList, prQuotedString, prParenth, prCurly,
prBracket, prArgList, prSemicList, prCurlyList, restoreEscapes,
) where numberedParagraphs, prConjList, prIfEmpty, wrapLines,
-- ** Topological sorting
topoTest, topoTest2,
-- ** Misc
readIntArg,
iterFix, chunks,
) where
import Data.Char (isSpace, toUpper, isSpace, isDigit) import Data.Char (isSpace, toUpper, isSpace, isDigit)
import Data.List (nub, partition, (\\)) import Data.List (nub, partition, (\\))
@@ -107,7 +107,7 @@ indent i s = replicate i ' ' ++ s
(+++), (++-), (++++), (+++-), (+++++) :: String -> String -> String (+++), (++-), (++++), (+++-), (+++++) :: String -> String -> String
a +++ b = a ++ " " ++ b a +++ b = a ++ " " ++ b
a ++- "" = a a ++- "" = a
a ++- b = a +++ b a ++- b = a +++ b
a ++++ b = a ++ "\n" ++ b a ++++ b = a ++ "\n" ++ b
@@ -145,20 +145,20 @@ prCurly s = "{" ++ s ++ "}"
prBracket s = "[" ++ s ++ "]" prBracket s = "[" ++ s ++ "]"
prArgList, prSemicList, prCurlyList :: [String] -> String prArgList, prSemicList, prCurlyList :: [String] -> String
prArgList = prParenth . prTList "," prArgList = prParenth . prTList ","
prSemicList = prTList " ; " prSemicList = prTList " ; "
prCurlyList = prCurly . prSemicList prCurlyList = prCurly . prSemicList
restoreEscapes :: String -> String restoreEscapes :: String -> String
restoreEscapes s = restoreEscapes s =
case s of case s of
[] -> [] [] -> []
'"' : t -> '\\' : '"' : restoreEscapes t '"' : t -> '\\' : '"' : restoreEscapes t
'\\': t -> '\\' : '\\' : restoreEscapes t '\\': t -> '\\' : '\\' : restoreEscapes t
c : t -> c : restoreEscapes t c : t -> c : restoreEscapes t
numberedParagraphs :: [[String]] -> [String] numberedParagraphs :: [[String]] -> [String]
numberedParagraphs t = case t of numberedParagraphs t = case t of
[] -> [] [] -> []
p:[] -> p p:[] -> p
_ -> concat [(show n ++ ".") : s | (n,s) <- zip [1..] t] _ -> concat [(show n ++ ".") : s | (n,s) <- zip [1..] t]
@@ -204,12 +204,12 @@ topoTest2 g0 = maybe (Right cycles) Left (tsort g)
([],[]) -> Just [] ([],[]) -> Just []
([],_) -> Nothing ([],_) -> Nothing
(ns,rest) -> (leaves:) `fmap` tsort [(n,es \\ leaves) | (n,es)<-rest] (ns,rest) -> (leaves:) `fmap` tsort [(n,es \\ leaves) | (n,es)<-rest]
where leaves = map fst ns where leaves = map fst ns
-- | Fix point iterator (for computing e.g. transitive closures or reachability) -- | Fix point iterator (for computing e.g. transitive closures or reachability)
iterFix :: Eq a => ([a] -> [a]) -> [a] -> [a] iterFix :: Eq a => ([a] -> [a]) -> [a] -> [a]
iterFix more start = iter start start iterFix more start = iter start start
where where
iter old new = if (null new') iter old new = if (null new')
then old then old
@@ -241,7 +241,7 @@ liftErr e = err raise return e
{- {-
instance ErrorMonad (STM s) where instance ErrorMonad (STM s) where
raise msg = STM (\s -> raise msg) raise msg = STM (\s -> raise msg)
handle (STM f) g = STM (\s -> (f s) handle (STM f) g = STM (\s -> (f s)
`handle` (\e -> let STM g' = (g e) in `handle` (\e -> let STM g' = (g e) in
g' s)) g' s))

View File

@@ -5,7 +5,7 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/10/26 17:13:13 $ -- > CVS $Date: 2005/10/26 17:13:13 $
-- > CVS $Author: bringert $ -- > CVS $Author: bringert $
-- > CVS $Revision: 1.1 $ -- > CVS $Revision: 1.1 $
-- --
@@ -83,7 +83,7 @@ transitiveClosure r = fix (Map.map growSet) r
where growSet ys = foldl Set.union ys (map (allRelated r) $ Set.toList ys) where growSet ys = foldl Set.union ys (map (allRelated r) $ Set.toList ys)
reflexiveClosure_ :: Ord a => [a] -- ^ The set over which the relation is defined. reflexiveClosure_ :: Ord a => [a] -- ^ The set over which the relation is defined.
-> Rel a -> Rel a -> Rel a -> Rel a
reflexiveClosure_ u r = relates [(x,x) | x <- u] r reflexiveClosure_ u r = relates [(x,x) | x <- u] r
-- | Uses 'domain' -- | Uses 'domain'
@@ -104,7 +104,7 @@ reflexiveElements :: Ord a => Rel a -> Set a
reflexiveElements r = Set.fromList [ x | (x,ys) <- Map.toList r, x `Set.member` ys ] reflexiveElements r = Set.fromList [ x | (x,ys) <- Map.toList r, x `Set.member` ys ]
-- | Keep the related pairs for which the predicate is true. -- | Keep the related pairs for which the predicate is true.
filterRel :: Ord a => (a -> a -> Bool) -> Rel a -> Rel a filterRel :: Ord a => (a -> a -> Bool) -> Rel a -> Rel a
filterRel p = fst . purgeEmpty . Map.mapWithKey (Set.filter . p) filterRel p = fst . purgeEmpty . Map.mapWithKey (Set.filter . p)
-- | Remove keys that map to no elements. -- | Remove keys that map to no elements.
@@ -112,16 +112,16 @@ purgeEmpty :: Ord a => Rel a -> (Rel a, Set a)
purgeEmpty r = let (r',r'') = Map.partition (not . Set.null) r purgeEmpty r = let (r',r'') = Map.partition (not . Set.null) r
in (r', Map.keysSet r'') in (r', Map.keysSet r'')
-- | Get the equivalence classes from an equivalence relation. -- | Get the equivalence classes from an equivalence relation.
equivalenceClasses :: Ord a => Rel a -> [Set a] equivalenceClasses :: Ord a => Rel a -> [Set a]
equivalenceClasses r = equivalenceClasses_ (Map.keys r) r equivalenceClasses r = equivalenceClasses_ (Map.keys r) r
where equivalenceClasses_ [] _ = [] where equivalenceClasses_ [] _ = []
equivalenceClasses_ (x:xs) r = ys:equivalenceClasses_ zs r equivalenceClasses_ (x:xs) r = ys:equivalenceClasses_ zs r
where ys = allRelated r x where ys = allRelated r x
zs = [x' | x' <- xs, not (x' `Set.member` ys)] zs = [x' | x' <- xs, not (x' `Set.member` ys)]
isTransitive :: Ord a => Rel a -> Bool isTransitive :: Ord a => Rel a -> Bool
isTransitive r = and [z `Set.member` ys | (x,ys) <- Map.toList r, isTransitive r = and [z `Set.member` ys | (x,ys) <- Map.toList r,
y <- Set.toList ys, z <- Set.toList (allRelated r y)] y <- Set.toList ys, z <- Set.toList (allRelated r y)]
isReflexive :: Ord a => Rel a -> Bool isReflexive :: Ord a => Rel a -> Bool
@@ -181,7 +181,7 @@ remove x r = let (mss,r') = Map.updateLookupWithKey (\_ _ -> Nothing) x r
Nothing -> (r', Set.empty, Set.empty) Nothing -> (r', Set.empty, Set.empty)
-- remove element from all incoming and outgoing sets -- remove element from all incoming and outgoing sets
-- of other elements -- of other elements
Just (is,os) -> Just (is,os) ->
let r'' = foldr (\i -> Map.adjust (\ (is',os') -> (is', Set.delete x os')) i) r' $ Set.toList is let r'' = foldr (\i -> Map.adjust (\ (is',os') -> (is', Set.delete x os')) i) r' $ Set.toList is
r''' = foldr (\o -> Map.adjust (\ (is',os') -> (Set.delete x is', os')) o) r'' $ Set.toList os r''' = foldr (\o -> Map.adjust (\ (is',os') -> (Set.delete x is', os')) o) r'' $ Set.toList os
in (r''', is, os) in (r''', is, os)
@@ -190,4 +190,4 @@ incoming :: Ord a => a -> Rel' a -> Set a
incoming x r = maybe Set.empty fst $ Map.lookup x r incoming x r = maybe Set.empty fst $ Map.lookup x r
--outgoing :: Ord a => a -> Rel' a -> Set a --outgoing :: Ord a => a -> Rel' a -> Set a
--outgoing x r = maybe Set.empty snd $ Map.lookup x r --outgoing x r = maybe Set.empty snd $ Map.lookup x r

View File

@@ -4,7 +4,7 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/10/26 18:47:16 $ -- > CVS $Date: 2005/10/26 18:47:16 $
-- > CVS $Author: bringert $ -- > CVS $Author: bringert $
-- > CVS $Revision: 1.6 $ -- > CVS $Revision: 1.6 $
-- --
@@ -33,7 +33,7 @@ longerThan n = not . notLongerThan n
lookupList :: Eq a => a -> [(a, b)] -> [b] lookupList :: Eq a => a -> [(a, b)] -> [b]
lookupList a [] = [] lookupList a [] = []
lookupList a (p:ps) | a == fst p = snd p : lookupList a ps lookupList a (p:ps) | a == fst p = snd p : lookupList a ps
| otherwise = lookupList a ps | otherwise = lookupList a ps
split :: [a] -> ([a], [a]) split :: [a] -> ([a], [a])
split (x : y : as) = (x:xs, y:ys) split (x : y : as) = (x:xs, y:ys)
@@ -48,8 +48,8 @@ splitBy p (a : as) = if p a then (a:xs, ys) else (xs, a:ys)
foldMerge :: (a -> a -> a) -> a -> [a] -> a foldMerge :: (a -> a -> a) -> a -> [a] -> a
foldMerge merge zero = fm foldMerge merge zero = fm
where fm [] = zero where fm [] = zero
fm [a] = a fm [a] = a
fm abs = let (as, bs) = split abs in fm as `merge` fm bs fm abs = let (as, bs) = split abs in fm as `merge` fm bs
select :: [a] -> [(a, [a])] select :: [a] -> [(a, [a])]
select [] = [] select [] = []
@@ -68,7 +68,7 @@ safeInit :: [a] -> [a]
safeInit [] = [] safeInit [] = []
safeInit xs = init xs safeInit xs = init xs
-- | Sorts and then groups elements given an ordering of the -- | Sorts and then groups elements given an ordering of the
-- elements. -- elements.
sortGroupBy :: (a -> a -> Ordering) -> [a] -> [[a]] sortGroupBy :: (a -> a -> Ordering) -> [a] -> [[a]]
sortGroupBy f = groupBy (compareEq f) . sortBy f sortGroupBy f = groupBy (compareEq f) . sortBy f

View File

@@ -45,12 +45,12 @@ data LincatDef = LincatDef CatId LinType deriving Show
data LinDef = LinDef FunId [VarId] LinValue deriving Show data LinDef = LinDef FunId [VarId] LinValue deriving Show
-- | Linearization type, RHS of @lincat@ -- | Linearization type, RHS of @lincat@
data LinType = FloatType data LinType = FloatType
| IntType | IntType
| ParamType ParamType | ParamType ParamType
| RecordType [RecordRowType] | RecordType [RecordRowType]
| StrType | StrType
| TableType LinType LinType | TableType LinType LinType
| TupleType [LinType] | TupleType [LinType]
deriving (Eq,Ord,Show) deriving (Eq,Ord,Show)
@@ -60,7 +60,7 @@ newtype ParamType = ParamTypeId ParamId deriving (Eq,Ord,Show)
data LinValue = ConcatValue LinValue LinValue data LinValue = ConcatValue LinValue LinValue
| LiteralValue LinLiteral | LiteralValue LinLiteral
| ErrorValue String | ErrorValue String
| ParamConstant ParamValue | ParamConstant ParamValue
| PredefValue PredefId | PredefValue PredefId
| RecordValue [RecordRowValue] | RecordValue [RecordRowValue]
| TableValue LinType [TableRowValue] | TableValue LinType [TableRowValue]
@@ -74,9 +74,9 @@ data LinValue = ConcatValue LinValue LinValue
| CommentedValue String LinValue | CommentedValue String LinValue
deriving (Eq,Ord,Show) deriving (Eq,Ord,Show)
data LinLiteral = FloatConstant Float data LinLiteral = FloatConstant Float
| IntConstant Int | IntConstant Int
| StrConstant String | StrConstant String
deriving (Eq,Ord,Show) deriving (Eq,Ord,Show)
data LinPattern = ParamPattern ParamPattern data LinPattern = ParamPattern ParamPattern
@@ -107,7 +107,7 @@ newtype PredefId = PredefId Id deriving (Eq,Ord,Show)
newtype LabelId = LabelId Id deriving (Eq,Ord,Show) newtype LabelId = LabelId Id deriving (Eq,Ord,Show)
data VarValueId = VarValueId QualId deriving (Eq,Ord,Show) data VarValueId = VarValueId QualId deriving (Eq,Ord,Show)
-- | Name of param type or param value -- | Name of param type or param value
newtype ParamId = ParamId QualId deriving (Eq,Ord,Show) newtype ParamId = ParamId QualId deriving (Eq,Ord,Show)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@@ -250,7 +250,7 @@ instance PPA LinLiteral where
FloatConstant f -> pp f FloatConstant f -> pp f
IntConstant n -> pp n IntConstant n -> pp n
StrConstant s -> doubleQuotes s -- hmm StrConstant s -> doubleQuotes s -- hmm
instance RhsSeparator LinValue where rhsSep _ = pp "=" instance RhsSeparator LinValue where rhsSep _ = pp "="
instance Pretty LinPattern where instance Pretty LinPattern where
@@ -265,7 +265,7 @@ instance PPA LinPattern where
ParamPattern pv -> ppA pv ParamPattern pv -> ppA pv
RecordPattern r -> block r RecordPattern r -> block r
TuplePattern ps -> "<"<>punctuate "," ps<>">" TuplePattern ps -> "<"<>punctuate "," ps<>">"
WildPattern -> pp "_" WildPattern -> pp "_"
instance RhsSeparator LinPattern where rhsSep _ = pp "=" instance RhsSeparator LinPattern where rhsSep _ = pp "="

View File

@@ -267,7 +267,7 @@ type AlexInput2 = (AlexInput,AlexInput)
data ParseResult a data ParseResult a
= POk AlexInput2 a = POk AlexInput2 a
| PFailed Posn -- The position of the error | PFailed Posn -- The position of the error
String -- The error message String -- The error message
newtype P a = P { unP :: AlexInput2 -> ParseResult a } newtype P a = P { unP :: AlexInput2 -> ParseResult a }

View File

@@ -6,7 +6,7 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/10/27 13:21:53 $ -- > CVS $Date: 2005/10/27 13:21:53 $
-- > CVS $Author: aarne $ -- > CVS $Author: aarne $
-- > CVS $Revision: 1.15 $ -- > CVS $Revision: 1.15 $
-- --
@@ -20,17 +20,17 @@ module GF.Grammar.Lookup (
lookupOrigInfo, lookupOrigInfo,
allOrigInfos, allOrigInfos,
lookupResDef, lookupResDefLoc, lookupResDef, lookupResDefLoc,
lookupResType, lookupResType,
lookupOverload, lookupOverload,
lookupOverloadTypes, lookupOverloadTypes,
lookupParamValues, lookupParamValues,
allParamValues, allParamValues,
lookupAbsDef, lookupAbsDef,
lookupLincat, lookupLincat,
lookupFunType, lookupFunType,
lookupCatContext, lookupCatContext,
allOpers, allOpersTo allOpers, allOpersTo
) where ) where
import GF.Data.Operations import GF.Data.Operations
import GF.Infra.Ident import GF.Infra.Ident
@@ -69,7 +69,7 @@ lookupResDef gr x = fmap unLoc (lookupResDefLoc gr x)
lookupResDefLoc gr (m,c) lookupResDefLoc gr (m,c)
| isPredefCat c = fmap noLoc (lock c defLinType) | isPredefCat c = fmap noLoc (lock c defLinType)
| otherwise = look m c | otherwise = look m c
where where
look m c = do look m c = do
info <- lookupQIdentInfo gr (m,c) info <- lookupQIdentInfo gr (m,c)
case info of case info of
@@ -77,7 +77,7 @@ lookupResDefLoc gr (m,c)
ResOper _ Nothing -> return (noLoc (Q (m,c))) ResOper _ Nothing -> return (noLoc (Q (m,c)))
CncCat (Just (L l ty)) _ _ _ _ -> fmap (L l) (lock c ty) CncCat (Just (L l ty)) _ _ _ _ -> fmap (L l) (lock c ty)
CncCat _ _ _ _ _ -> fmap noLoc (lock c defLinType) CncCat _ _ _ _ _ -> fmap noLoc (lock c defLinType)
CncFun (Just (cat,_,_)) (Just (L l tr)) _ _ -> fmap (L l) (unlock cat tr) CncFun (Just (cat,_,_)) (Just (L l tr)) _ _ -> fmap (L l) (unlock cat tr)
CncFun _ (Just ltr) _ _ -> return ltr CncFun _ (Just ltr) _ _ -> return ltr
@@ -95,7 +95,7 @@ lookupResType gr (m,c) = do
-- used in reused concrete -- used in reused concrete
CncCat _ _ _ _ _ -> return typeType CncCat _ _ _ _ _ -> return typeType
CncFun (Just (cat,cont,val)) _ _ _ -> do CncFun (Just (cat,cont,val)) _ _ _ -> do
val' <- lock cat val val' <- lock cat val
return $ mkProd cont val' [] return $ mkProd cont val' []
AnyInd _ n -> lookupResType gr (n,c) AnyInd _ n -> lookupResType gr (n,c)
ResParam _ _ -> return typePType ResParam _ _ -> return typePType
@@ -111,7 +111,7 @@ lookupOverloadTypes gr id@(m,c) = do
-- used in reused concrete -- used in reused concrete
CncCat _ _ _ _ _ -> ret typeType CncCat _ _ _ _ _ -> ret typeType
CncFun (Just (cat,cont,val)) _ _ _ -> do CncFun (Just (cat,cont,val)) _ _ _ -> do
val' <- lock cat val val' <- lock cat val
ret $ mkProd cont val' [] ret $ mkProd cont val' []
ResParam _ _ -> ret typePType ResParam _ _ -> ret typePType
ResValue (L _ t) -> ret t ResValue (L _ t) -> ret t
@@ -130,8 +130,8 @@ lookupOverload gr (m,c) = do
case info of case info of
ResOverload os tysts -> do ResOverload os tysts -> do
tss <- mapM (\x -> lookupOverload gr (x,c)) os tss <- mapM (\x -> lookupOverload gr (x,c)) os
return $ [let (args,val) = typeFormCnc ty in (map (\(b,x,t) -> t) args,(val,tr)) | return $ [let (args,val) = typeFormCnc ty in (map (\(b,x,t) -> t) args,(val,tr)) |
(L _ ty,L _ tr) <- tysts] ++ (L _ ty,L _ tr) <- tysts] ++
concat tss concat tss
AnyInd _ n -> lookupOverload gr (n,c) AnyInd _ n -> lookupOverload gr (n,c)
@@ -216,7 +216,7 @@ lookupCatContext gr m c = do
-- notice that it only gives the modules that are reachable and the opers that are included -- notice that it only gives the modules that are reachable and the opers that are included
allOpers :: Grammar -> [(QIdent,Type,Location)] allOpers :: Grammar -> [(QIdent,Type,Location)]
allOpers gr = allOpers gr =
[((m,op),typ,loc) | [((m,op),typ,loc) |
(m,mi) <- maybe [] (allExtends gr) (greatestResource gr), (m,mi) <- maybe [] (allExtends gr) (greatestResource gr),
(op,info) <- Map.toList (jments mi), (op,info) <- Map.toList (jments mi),

View File

@@ -5,18 +5,19 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/10/12 12:38:29 $ -- > CVS $Date: 2005/10/12 12:38:29 $
-- > CVS $Author: aarne $ -- > CVS $Author: aarne $
-- > CVS $Revision: 1.7 $ -- > CVS $Revision: 1.7 $
-- --
-- pattern matching for both concrete and abstract syntax. AR -- 16\/6\/2003 -- pattern matching for both concrete and abstract syntax. AR -- 16\/6\/2003
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module GF.Grammar.PatternMatch (matchPattern, module GF.Grammar.PatternMatch (
testOvershadow, matchPattern,
findMatch, testOvershadow,
measurePatt findMatch,
) where measurePatt
) where
import GF.Data.Operations import GF.Data.Operations
import GF.Grammar.Grammar import GF.Grammar.Grammar
@@ -30,7 +31,7 @@ import GF.Text.Pretty
--import Debug.Trace --import Debug.Trace
matchPattern :: ErrorMonad m => [(Patt,rhs)] -> Term -> m (rhs, Substitution) matchPattern :: ErrorMonad m => [(Patt,rhs)] -> Term -> m (rhs, Substitution)
matchPattern pts term = matchPattern pts term =
if not (isInConstantForm term) if not (isInConstantForm term)
then raise (render ("variables occur in" <+> pp term)) then raise (render ("variables occur in" <+> pp term))
else do else do
@@ -61,15 +62,15 @@ testOvershadow pts vs = do
findMatch :: ErrorMonad m => [([Patt],rhs)] -> [Term] -> m (rhs, Substitution) findMatch :: ErrorMonad m => [([Patt],rhs)] -> [Term] -> m (rhs, Substitution)
findMatch cases terms = case cases of findMatch cases terms = case cases of
[] -> raise (render ("no applicable case for" <+> hsep (punctuate ',' terms))) [] -> raise (render ("no applicable case for" <+> hsep (punctuate ',' terms)))
(patts,_):_ | length patts /= length terms -> (patts,_):_ | length patts /= length terms ->
raise (render ("wrong number of args for patterns :" <+> hsep patts <+> raise (render ("wrong number of args for patterns :" <+> hsep patts <+>
"cannot take" <+> hsep terms)) "cannot take" <+> hsep terms))
(patts,val):cc -> case mapM tryMatch (zip patts terms) of (patts,val):cc -> case mapM tryMatch (zip patts terms) of
Ok substs -> return (val, concat substs) Ok substs -> return (val, concat substs)
_ -> findMatch cc terms _ -> findMatch cc terms
tryMatch :: (Patt, Term) -> Err [(Ident, Term)] tryMatch :: (Patt, Term) -> Err [(Ident, Term)]
tryMatch (p,t) = do tryMatch (p,t) = do
t' <- termForm t t' <- termForm t
trym p t' trym p t'
where where
@@ -83,26 +84,26 @@ tryMatch (p,t) = do
(PString s, ([],K i,[])) | s==i -> return [] (PString s, ([],K i,[])) | s==i -> return []
(PInt s, ([],EInt i,[])) | s==i -> return [] (PInt s, ([],EInt i,[])) | s==i -> return []
(PFloat s,([],EFloat i,[])) | s==i -> return [] --- rounding? (PFloat s,([],EFloat i,[])) | s==i -> return [] --- rounding?
(PC p pp, ([], Con f, tt)) | (PC p pp, ([], Con f, tt)) |
p `eqStrIdent` f && length pp == length tt -> p `eqStrIdent` f && length pp == length tt ->
do matches <- mapM tryMatch (zip pp tt) do matches <- mapM tryMatch (zip pp tt)
return (concat matches) return (concat matches)
(PP (q,p) pp, ([], QC (r,f), tt)) | (PP (q,p) pp, ([], QC (r,f), tt)) |
-- q `eqStrIdent` r && --- not for inherited AR 10/10/2005 -- q `eqStrIdent` r && --- not for inherited AR 10/10/2005
p `eqStrIdent` f && length pp == length tt -> p `eqStrIdent` f && length pp == length tt ->
do matches <- mapM tryMatch (zip pp tt) do matches <- mapM tryMatch (zip pp tt)
return (concat matches) return (concat matches)
---- hack for AppPredef bug ---- hack for AppPredef bug
(PP (q,p) pp, ([], Q (r,f), tt)) | (PP (q,p) pp, ([], Q (r,f), tt)) |
-- q `eqStrIdent` r && --- -- q `eqStrIdent` r && ---
p `eqStrIdent` f && length pp == length tt -> p `eqStrIdent` f && length pp == length tt ->
do matches <- mapM tryMatch (zip pp tt) do matches <- mapM tryMatch (zip pp tt)
return (concat matches) return (concat matches)
(PR r, ([],R r',[])) | (PR r, ([],R r',[])) |
all (`elem` map fst r') (map fst r) -> all (`elem` map fst r') (map fst r) ->
do matches <- mapM tryMatch do matches <- mapM tryMatch
[(p,snd a) | (l,p) <- r, let Just a = lookup l r'] [(p,snd a) | (l,p) <- r, let Just a = lookup l r']
return (concat matches) return (concat matches)
(PT _ p',_) -> trym p' t' (PT _ p',_) -> trym p' t'
@@ -125,7 +126,7 @@ tryMatch (p,t) = do
(PMSeq mp1 mp2, ([],K s, [])) -> matchPMSeq mp1 mp2 s (PMSeq mp1 mp2, ([],K s, [])) -> matchPMSeq mp1 mp2 s
(PRep p1, ([],K s, [])) -> checks [ (PRep p1, ([],K s, [])) -> checks [
trym (foldr (const (PSeq p1)) (PString "") trym (foldr (const (PSeq p1)) (PString "")
[1..n]) t' | n <- [0 .. length s] [1..n]) t' | n <- [0 .. length s]
] >> ] >>
return [] return []

View File

@@ -1,365 +1,364 @@
---------------------------------------------------------------------- ----------------------------------------------------------------------
-- | -- |
-- Module : GF.Grammar.Printer -- Module : GF.Grammar.Printer
-- Maintainer : Krasimir Angelov -- Maintainer : Krasimir Angelov
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
module GF.Grammar.Printer module GF.Grammar.Printer
( -- ** Pretty printing ( -- ** Pretty printing
TermPrintQual(..) TermPrintQual(..)
, ppModule , ppModule
, ppJudgement , ppJudgement
, ppParams , ppParams
, ppTerm , ppTerm
, ppPatt , ppPatt
, ppValue , ppValue
, ppConstrs , ppConstrs
, ppQIdent , ppQIdent
, ppMeta , ppMeta
, getAbs , getAbs
) where ) where
import Prelude hiding ((<>)) -- GHC 8.4.1 clash with Text.PrettyPrint import Prelude hiding ((<>)) -- GHC 8.4.1 clash with Text.PrettyPrint
import GF.Infra.Ident import GF.Infra.Ident
import GF.Infra.Option import GF.Infra.Option
import GF.Grammar.Values import GF.Grammar.Values
import GF.Grammar.Grammar import GF.Grammar.Grammar
import PGF.Internal (ppMeta, ppLit, ppFId, ppFunId, ppSeqId, ppSeq) import PGF.Internal (ppMeta, ppLit, ppFId, ppFunId, ppSeqId, ppSeq)
import GF.Text.Pretty import GF.Text.Pretty
import Data.Maybe (isNothing) import Data.Maybe (isNothing)
import Data.List (intersperse) import Data.List (intersperse)
import qualified Data.Map as Map import qualified Data.Map as Map
--import qualified Data.IntMap as IntMap --import qualified Data.IntMap as IntMap
--import qualified Data.Set as Set --import qualified Data.Set as Set
import qualified Data.Array.IArray as Array import qualified Data.Array.IArray as Array
data TermPrintQual data TermPrintQual
= Terse | Unqualified | Qualified | Internal = Terse | Unqualified | Qualified | Internal
deriving Eq deriving Eq
instance Pretty Grammar where instance Pretty Grammar where
pp = vcat . map (ppModule Qualified) . modules pp = vcat . map (ppModule Qualified) . modules
ppModule :: TermPrintQual -> SourceModule -> Doc ppModule :: TermPrintQual -> SourceModule -> Doc
ppModule q (mn, ModInfo mtype mstat opts exts with opens _ _ mseqs jments) = ppModule q (mn, ModInfo mtype mstat opts exts with opens _ _ mseqs jments) =
hdr $$ hdr $$
nest 2 (ppOptions opts $$ nest 2 (ppOptions opts $$
vcat (map (ppJudgement q) (Map.toList jments)) $$ vcat (map (ppJudgement q) (Map.toList jments)) $$
maybe empty (ppSequences q) mseqs) $$ maybe empty (ppSequences q) mseqs) $$
ftr ftr
where where
hdr = complModDoc <+> modTypeDoc <+> '=' <+> hdr = complModDoc <+> modTypeDoc <+> '=' <+>
hsep (intersperse (pp "**") $ hsep (intersperse (pp "**") $
filter (not . isEmpty) $ [ commaPunct ppExtends exts filter (not . isEmpty) $ [ commaPunct ppExtends exts
, maybe empty ppWith with , maybe empty ppWith with
, if null opens , if null opens
then pp '{' then pp '{'
else "open" <+> commaPunct ppOpenSpec opens <+> "in" <+> '{' else "open" <+> commaPunct ppOpenSpec opens <+> "in" <+> '{'
]) ])
ftr = '}' ftr = '}'
complModDoc = complModDoc =
case mstat of case mstat of
MSComplete -> empty MSComplete -> empty
MSIncomplete -> pp "incomplete" MSIncomplete -> pp "incomplete"
modTypeDoc = modTypeDoc =
case mtype of case mtype of
MTAbstract -> "abstract" <+> mn MTAbstract -> "abstract" <+> mn
MTResource -> "resource" <+> mn MTResource -> "resource" <+> mn
MTConcrete abs -> "concrete" <+> mn <+> "of" <+> abs MTConcrete abs -> "concrete" <+> mn <+> "of" <+> abs
MTInterface -> "interface" <+> mn MTInterface -> "interface" <+> mn
MTInstance ie -> "instance" <+> mn <+> "of" <+> ppExtends ie MTInstance ie -> "instance" <+> mn <+> "of" <+> ppExtends ie
ppExtends (id,MIAll ) = pp id ppExtends (id,MIAll ) = pp id
ppExtends (id,MIOnly incs) = id <+> brackets (commaPunct pp incs) ppExtends (id,MIOnly incs) = id <+> brackets (commaPunct pp incs)
ppExtends (id,MIExcept incs) = id <+> '-' <+> brackets (commaPunct pp incs) ppExtends (id,MIExcept incs) = id <+> '-' <+> brackets (commaPunct pp incs)
ppWith (id,ext,opens) = ppExtends (id,ext) <+> "with" <+> commaPunct ppInstSpec opens ppWith (id,ext,opens) = ppExtends (id,ext) <+> "with" <+> commaPunct ppInstSpec opens
ppOptions opts = ppOptions opts =
"flags" $$ "flags" $$
nest 2 (vcat [option <+> '=' <+> ppLit value <+> ';' | (option,value) <- optionsGFO opts]) nest 2 (vcat [option <+> '=' <+> ppLit value <+> ';' | (option,value) <- optionsGFO opts])
ppJudgement q (id, AbsCat pcont ) = ppJudgement q (id, AbsCat pcont ) =
"cat" <+> id <+> "cat" <+> id <+>
(case pcont of (case pcont of
Just (L _ cont) -> hsep (map (ppDecl q) cont) Just (L _ cont) -> hsep (map (ppDecl q) cont)
Nothing -> empty) <+> ';' Nothing -> empty) <+> ';'
ppJudgement q (id, AbsFun ptype _ pexp poper) = ppJudgement q (id, AbsFun ptype _ pexp poper) =
let kind | isNothing pexp = "data" let kind | isNothing pexp = "data"
| poper == Just False = "oper" | poper == Just False = "oper"
| otherwise = "fun" | otherwise = "fun"
in in
(case ptype of (case ptype of
Just (L _ typ) -> kind <+> id <+> ':' <+> ppTerm q 0 typ <+> ';' Just (L _ typ) -> kind <+> id <+> ':' <+> ppTerm q 0 typ <+> ';'
Nothing -> empty) $$ Nothing -> empty) $$
(case pexp of (case pexp of
Just [] -> empty Just [] -> empty
Just eqs -> "def" <+> vcat [id <+> hsep (map (ppPatt q 2) ps) <+> '=' <+> ppTerm q 0 e <+> ';' | L _ (ps,e) <- eqs] Just eqs -> "def" <+> vcat [id <+> hsep (map (ppPatt q 2) ps) <+> '=' <+> ppTerm q 0 e <+> ';' | L _ (ps,e) <- eqs]
Nothing -> empty) Nothing -> empty)
ppJudgement q (id, ResParam pparams _) = ppJudgement q (id, ResParam pparams _) =
"param" <+> id <+> "param" <+> id <+>
(case pparams of (case pparams of
Just (L _ ps) -> '=' <+> ppParams q ps Just (L _ ps) -> '=' <+> ppParams q ps
_ -> empty) <+> ';' _ -> empty) <+> ';'
ppJudgement q (id, ResValue pvalue) = ppJudgement q (id, ResValue pvalue) =
"-- param constructor" <+> id <+> ':' <+> "-- param constructor" <+> id <+> ':' <+>
(case pvalue of (case pvalue of
(L _ ty) -> ppTerm q 0 ty) <+> ';' (L _ ty) -> ppTerm q 0 ty) <+> ';'
ppJudgement q (id, ResOper ptype pexp) = ppJudgement q (id, ResOper ptype pexp) =
"oper" <+> id <+> "oper" <+> id <+>
(case ptype of {Just (L _ t) -> ':' <+> ppTerm q 0 t; Nothing -> empty} $$ (case ptype of {Just (L _ t) -> ':' <+> ppTerm q 0 t; Nothing -> empty} $$
case pexp of {Just (L _ e) -> '=' <+> ppTerm q 0 e; Nothing -> empty}) <+> ';' case pexp of {Just (L _ e) -> '=' <+> ppTerm q 0 e; Nothing -> empty}) <+> ';'
ppJudgement q (id, ResOverload ids defs) = ppJudgement q (id, ResOverload ids defs) =
"oper" <+> id <+> '=' <+> "oper" <+> id <+> '=' <+>
("overload" <+> '{' $$ ("overload" <+> '{' $$
nest 2 (vcat [id <+> (':' <+> ppTerm q 0 ty $$ '=' <+> ppTerm q 0 e <+> ';') | (L _ ty,L _ e) <- defs]) $$ nest 2 (vcat [id <+> (':' <+> ppTerm q 0 ty $$ '=' <+> ppTerm q 0 e <+> ';') | (L _ ty,L _ e) <- defs]) $$
'}') <+> ';' '}') <+> ';'
ppJudgement q (id, CncCat pcat pdef pref pprn mpmcfg) = ppJudgement q (id, CncCat pcat pdef pref pprn mpmcfg) =
(case pcat of (case pcat of
Just (L _ typ) -> "lincat" <+> id <+> '=' <+> ppTerm q 0 typ <+> ';' Just (L _ typ) -> "lincat" <+> id <+> '=' <+> ppTerm q 0 typ <+> ';'
Nothing -> empty) $$ Nothing -> empty) $$
(case pdef of (case pdef of
Just (L _ exp) -> "lindef" <+> id <+> '=' <+> ppTerm q 0 exp <+> ';' Just (L _ exp) -> "lindef" <+> id <+> '=' <+> ppTerm q 0 exp <+> ';'
Nothing -> empty) $$ Nothing -> empty) $$
(case pref of (case pref of
Just (L _ exp) -> "linref" <+> id <+> '=' <+> ppTerm q 0 exp <+> ';' Just (L _ exp) -> "linref" <+> id <+> '=' <+> ppTerm q 0 exp <+> ';'
Nothing -> empty) $$ Nothing -> empty) $$
(case pprn of (case pprn of
Just (L _ prn) -> "printname" <+> id <+> '=' <+> ppTerm q 0 prn <+> ';' Just (L _ prn) -> "printname" <+> id <+> '=' <+> ppTerm q 0 prn <+> ';'
Nothing -> empty) $$ Nothing -> empty) $$
(case (mpmcfg,q) of (case (mpmcfg,q) of
(Just (PMCFG prods funs),Internal) (Just (PMCFG prods funs),Internal)
-> "pmcfg" <+> id <+> '=' <+> '{' $$ -> "pmcfg" <+> id <+> '=' <+> '{' $$
nest 2 (vcat (map ppProduction prods) $$ nest 2 (vcat (map ppProduction prods) $$
' ' $$ ' ' $$
vcat (map (\(funid,arr) -> ppFunId funid <+> ":=" <+> vcat (map (\(funid,arr) -> ppFunId funid <+> ":=" <+>
parens (hcat (punctuate ',' (map ppSeqId (Array.elems arr))))) parens (hcat (punctuate ',' (map ppSeqId (Array.elems arr)))))
(Array.assocs funs))) $$ (Array.assocs funs))) $$
'}' '}'
_ -> empty) _ -> empty)
ppJudgement q (id, CncFun ptype pdef pprn mpmcfg) = ppJudgement q (id, CncFun ptype pdef pprn mpmcfg) =
(case pdef of (case pdef of
Just (L _ e) -> let (xs,e') = getAbs e Just (L _ e) -> let (xs,e') = getAbs e
in "lin" <+> id <+> hsep (map ppBind xs) <+> '=' <+> ppTerm q 0 e' <+> ';' in "lin" <+> id <+> hsep (map ppBind xs) <+> '=' <+> ppTerm q 0 e' <+> ';'
Nothing -> empty) $$ Nothing -> empty) $$
(case pprn of (case pprn of
Just (L _ prn) -> "printname" <+> id <+> '=' <+> ppTerm q 0 prn <+> ';' Just (L _ prn) -> "printname" <+> id <+> '=' <+> ppTerm q 0 prn <+> ';'
Nothing -> empty) $$ Nothing -> empty) $$
(case (mpmcfg,q) of (case (mpmcfg,q) of
(Just (PMCFG prods funs),Internal) (Just (PMCFG prods funs),Internal)
-> "pmcfg" <+> id <+> '=' <+> '{' $$ -> "pmcfg" <+> id <+> '=' <+> '{' $$
nest 2 (vcat (map ppProduction prods) $$ nest 2 (vcat (map ppProduction prods) $$
' ' $$ ' ' $$
vcat (map (\(funid,arr) -> ppFunId funid <+> ":=" <+> vcat (map (\(funid,arr) -> ppFunId funid <+> ":=" <+>
parens (hcat (punctuate ',' (map ppSeqId (Array.elems arr))))) parens (hcat (punctuate ',' (map ppSeqId (Array.elems arr)))))
(Array.assocs funs))) $$ (Array.assocs funs))) $$
'}' '}'
_ -> empty) _ -> empty)
ppJudgement q (id, AnyInd cann mid) = ppJudgement q (id, AnyInd cann mid) =
case q of case q of
Internal -> "ind" <+> id <+> '=' <+> (if cann then pp "canonical" else empty) <+> mid <+> ';' Internal -> "ind" <+> id <+> '=' <+> (if cann then pp "canonical" else empty) <+> mid <+> ';'
_ -> empty _ -> empty
instance Pretty Term where pp = ppTerm Unqualified 0 instance Pretty Term where pp = ppTerm Unqualified 0
ppTerm q d (Abs b v e) = let (xs,e') = getAbs (Abs b v e) ppTerm q d (Abs b v e) = let (xs,e') = getAbs (Abs b v e)
in prec d 0 ('\\' <> commaPunct ppBind xs <+> "->" <+> ppTerm q 0 e') in prec d 0 ('\\' <> commaPunct ppBind xs <+> "->" <+> ppTerm q 0 e')
ppTerm q d (T TRaw xs) = case getCTable (T TRaw xs) of ppTerm q d (T TRaw xs) = case getCTable (T TRaw xs) of
([],_) -> "table" <+> '{' $$ ([],_) -> "table" <+> '{' $$
nest 2 (vcat (punctuate ';' (map (ppCase q) xs))) $$ nest 2 (vcat (punctuate ';' (map (ppCase q) xs))) $$
'}' '}'
(vs,e) -> prec d 0 ("\\\\" <> commaPunct pp vs <+> "=>" <+> ppTerm q 0 e) (vs,e) -> prec d 0 ("\\\\" <> commaPunct pp vs <+> "=>" <+> ppTerm q 0 e)
ppTerm q d (T (TTyped t) xs) = "table" <+> ppTerm q 0 t <+> '{' $$ ppTerm q d (T (TTyped t) xs) = "table" <+> ppTerm q 0 t <+> '{' $$
nest 2 (vcat (punctuate ';' (map (ppCase q) xs))) $$ nest 2 (vcat (punctuate ';' (map (ppCase q) xs))) $$
'}' '}'
ppTerm q d (T (TComp t) xs) = "table" <+> ppTerm q 0 t <+> '{' $$ ppTerm q d (T (TComp t) xs) = "table" <+> ppTerm q 0 t <+> '{' $$
nest 2 (vcat (punctuate ';' (map (ppCase q) xs))) $$ nest 2 (vcat (punctuate ';' (map (ppCase q) xs))) $$
'}' '}'
ppTerm q d (T (TWild t) xs) = "table" <+> ppTerm q 0 t <+> '{' $$ ppTerm q d (T (TWild t) xs) = "table" <+> ppTerm q 0 t <+> '{' $$
nest 2 (vcat (punctuate ';' (map (ppCase q) xs))) $$ nest 2 (vcat (punctuate ';' (map (ppCase q) xs))) $$
'}' '}'
ppTerm q d (Prod bt x a b)= if x == identW && bt == Explicit ppTerm q d (Prod bt x a b)= if x == identW && bt == Explicit
then prec d 0 (ppTerm q 4 a <+> "->" <+> ppTerm q 0 b) then prec d 0 (ppTerm q 4 a <+> "->" <+> ppTerm q 0 b)
else prec d 0 (parens (ppBind (bt,x) <+> ':' <+> ppTerm q 0 a) <+> "->" <+> ppTerm q 0 b) else prec d 0 (parens (ppBind (bt,x) <+> ':' <+> ppTerm q 0 a) <+> "->" <+> ppTerm q 0 b)
ppTerm q d (Table kt vt)=prec d 0 (ppTerm q 3 kt <+> "=>" <+> ppTerm q 0 vt) ppTerm q d (Table kt vt)=prec d 0 (ppTerm q 3 kt <+> "=>" <+> ppTerm q 0 vt)
ppTerm q d (Let l e) = let (ls,e') = getLet e ppTerm q d (Let l e) = let (ls,e') = getLet e
in prec d 0 ("let" <+> vcat (map (ppLocDef q) (l:ls)) $$ "in" <+> ppTerm q 0 e') in prec d 0 ("let" <+> vcat (map (ppLocDef q) (l:ls)) $$ "in" <+> ppTerm q 0 e')
ppTerm q d (Example e s)=prec d 0 ("in" <+> ppTerm q 5 e <+> str s) ppTerm q d (Example e s)=prec d 0 ("in" <+> ppTerm q 5 e <+> str s)
ppTerm q d (C e1 e2) =prec d 1 (hang (ppTerm q 2 e1) 2 ("++" <+> ppTerm q 1 e2)) ppTerm q d (C e1 e2) =prec d 1 (hang (ppTerm q 2 e1) 2 ("++" <+> ppTerm q 1 e2))
ppTerm q d (Glue e1 e2) =prec d 2 (ppTerm q 3 e1 <+> '+' <+> ppTerm q 2 e2) ppTerm q d (Glue e1 e2) =prec d 2 (ppTerm q 3 e1 <+> '+' <+> ppTerm q 2 e2)
ppTerm q d (S x y) = case x of ppTerm q d (S x y) = case x of
T annot xs -> let e = case annot of T annot xs -> let e = case annot of
TRaw -> y TRaw -> y
TTyped t -> Typed y t TTyped t -> Typed y t
TComp t -> Typed y t TComp t -> Typed y t
TWild t -> Typed y t TWild t -> Typed y t
in "case" <+> ppTerm q 0 e <+>"of" <+> '{' $$ in "case" <+> ppTerm q 0 e <+>"of" <+> '{' $$
nest 2 (vcat (punctuate ';' (map (ppCase q) xs))) $$ nest 2 (vcat (punctuate ';' (map (ppCase q) xs))) $$
'}' '}'
_ -> prec d 3 (hang (ppTerm q 3 x) 2 ("!" <+> ppTerm q 4 y)) _ -> prec d 3 (hang (ppTerm q 3 x) 2 ("!" <+> ppTerm q 4 y))
ppTerm q d (ExtR x y) = prec d 3 (ppTerm q 3 x <+> "**" <+> ppTerm q 4 y) ppTerm q d (ExtR x y) = prec d 3 (ppTerm q 3 x <+> "**" <+> ppTerm q 4 y)
ppTerm q d (App x y) = prec d 4 (ppTerm q 4 x <+> ppTerm q 5 y) ppTerm q d (App x y) = prec d 4 (ppTerm q 4 x <+> ppTerm q 5 y)
ppTerm q d (V e es) = hang "table" 2 (sep [ppTerm q 6 e,brackets (fsep (punctuate ';' (map (ppTerm q 0) es)))]) ppTerm q d (V e es) = hang "table" 2 (sep [ppTerm q 6 e,brackets (fsep (punctuate ';' (map (ppTerm q 0) es)))])
ppTerm q d (FV es) = prec d 4 ("variants" <+> braces (fsep (punctuate ';' (map (ppTerm q 0) es)))) ppTerm q d (FV es) = prec d 4 ("variants" <+> braces (fsep (punctuate ';' (map (ppTerm q 0) es))))
ppTerm q d (AdHocOverload es) = "overload" <+> braces (fsep (punctuate ';' (map (ppTerm q 0) es))) ppTerm q d (AdHocOverload es) = "overload" <+> braces (fsep (punctuate ';' (map (ppTerm q 0) es)))
ppTerm q d (Alts e xs) = prec d 4 ("pre" <+> braces (ppTerm q 0 e <> ';' <+> fsep (punctuate ';' (map (ppAltern q) xs)))) ppTerm q d (Alts e xs) = prec d 4 ("pre" <+> braces (ppTerm q 0 e <> ';' <+> fsep (punctuate ';' (map (ppAltern q) xs))))
ppTerm q d (Strs es) = "strs" <+> braces (fsep (punctuate ';' (map (ppTerm q 0) es))) ppTerm q d (Strs es) = "strs" <+> braces (fsep (punctuate ';' (map (ppTerm q 0) es)))
ppTerm q d (EPatt p) = prec d 4 ('#' <+> ppPatt q 2 p) ppTerm q d (EPatt p) = prec d 4 ('#' <+> ppPatt q 2 p)
ppTerm q d (EPattType t)=prec d 4 ("pattern" <+> ppTerm q 0 t) ppTerm q d (EPattType t)=prec d 4 ("pattern" <+> ppTerm q 0 t)
ppTerm q d (P t l) = prec d 5 (ppTerm q 5 t <> '.' <> l) ppTerm q d (P t l) = prec d 5 (ppTerm q 5 t <> '.' <> l)
ppTerm q d (Cn id) = pp id ppTerm q d (Cn id) = pp id
ppTerm q d (Vr id) = pp id ppTerm q d (Vr id) = pp id
ppTerm q d (Q id) = ppQIdent q id ppTerm q d (Q id) = ppQIdent q id
ppTerm q d (QC id) = ppQIdent q id ppTerm q d (QC id) = ppQIdent q id
ppTerm q d (Sort id) = pp id ppTerm q d (Sort id) = pp id
ppTerm q d (K s) = str s ppTerm q d (K s) = str s
ppTerm q d (EInt n) = pp n ppTerm q d (EInt n) = pp n
ppTerm q d (EFloat f) = pp f ppTerm q d (EFloat f) = pp f
ppTerm q d (Meta i) = ppMeta i ppTerm q d (Meta i) = ppMeta i
ppTerm q d (Empty) = pp "[]" ppTerm q d (Empty) = pp "[]"
ppTerm q d (R []) = pp "<>" -- to distinguish from {} empty RecType ppTerm q d (R []) = pp "<>" -- to distinguish from {} empty RecType
ppTerm q d (R xs) = braces (fsep (punctuate ';' [l <+> ppTerm q d (R xs) = braces (fsep (punctuate ';' [l <+>
fsep [case mb_t of {Just t -> ':' <+> ppTerm q 0 t; Nothing -> empty}, fsep [case mb_t of {Just t -> ':' <+> ppTerm q 0 t; Nothing -> empty},
'=' <+> ppTerm q 0 e] | (l,(mb_t,e)) <- xs])) '=' <+> ppTerm q 0 e] | (l,(mb_t,e)) <- xs]))
ppTerm q d (RecType xs) ppTerm q d (RecType xs)
| q == Terse = case [cat | (l,_) <- xs, let (p,cat) = splitAt 5 (showIdent (label2ident l)), p == "lock_"] of | q == Terse = case [cat | (l,_) <- xs, let (p,cat) = splitAt 5 (showIdent (label2ident l)), p == "lock_"] of
[cat] -> pp cat [cat] -> pp cat
_ -> doc _ -> doc
| otherwise = doc | otherwise = doc
where where
doc = braces (fsep (punctuate ';' [l <+> ':' <+> ppTerm q 0 t | (l,t) <- xs])) doc = braces (fsep (punctuate ';' [l <+> ':' <+> ppTerm q 0 t | (l,t) <- xs]))
ppTerm q d (Typed e t) = '<' <> ppTerm q 0 e <+> ':' <+> ppTerm q 0 t <> '>' ppTerm q d (Typed e t) = '<' <> ppTerm q 0 e <+> ':' <+> ppTerm q 0 t <> '>'
ppTerm q d (ImplArg e) = braces (ppTerm q 0 e) ppTerm q d (ImplArg e) = braces (ppTerm q 0 e)
ppTerm q d (ELincat cat t) = prec d 4 ("lincat" <+> cat <+> ppTerm q 5 t) ppTerm q d (ELincat cat t) = prec d 4 ("lincat" <+> cat <+> ppTerm q 5 t)
ppTerm q d (ELin cat t) = prec d 4 ("lin" <+> cat <+> ppTerm q 5 t) ppTerm q d (ELin cat t) = prec d 4 ("lin" <+> cat <+> ppTerm q 5 t)
ppTerm q d (Error s) = prec d 4 ("Predef.error" <+> str s) ppTerm q d (Error s) = prec d 4 ("Predef.error" <+> str s)
ppEquation q (ps,e) = hcat (map (ppPatt q 2) ps) <+> "->" <+> ppTerm q 0 e ppEquation q (ps,e) = hcat (map (ppPatt q 2) ps) <+> "->" <+> ppTerm q 0 e
ppCase q (p,e) = ppPatt q 0 p <+> "=>" <+> ppTerm q 0 e ppCase q (p,e) = ppPatt q 0 p <+> "=>" <+> ppTerm q 0 e
instance Pretty Patt where pp = ppPatt Unqualified 0 instance Pretty Patt where pp = ppPatt Unqualified 0
ppPatt q d (PAlt p1 p2) = prec d 0 (ppPatt q 0 p1 <+> '|' <+> ppPatt q 1 p2) ppPatt q d (PAlt p1 p2) = prec d 0 (ppPatt q 0 p1 <+> '|' <+> ppPatt q 1 p2)
ppPatt q d (PSeq p1 p2) = prec d 0 (ppPatt q 0 p1 <+> '+' <+> ppPatt q 1 p2) ppPatt q d (PSeq p1 p2) = prec d 0 (ppPatt q 0 p1 <+> '+' <+> ppPatt q 1 p2)
ppPatt q d (PMSeq (_,p1) (_,p2)) = prec d 0 (ppPatt q 0 p1 <+> '+' <+> ppPatt q 1 p2) ppPatt q d (PMSeq (_,p1) (_,p2)) = prec d 0 (ppPatt q 0 p1 <+> '+' <+> ppPatt q 1 p2)
ppPatt q d (PC f ps) = if null ps ppPatt q d (PC f ps) = if null ps
then pp f then pp f
else prec d 1 (f <+> hsep (map (ppPatt q 3) ps)) else prec d 1 (f <+> hsep (map (ppPatt q 3) ps))
ppPatt q d (PP f ps) = if null ps ppPatt q d (PP f ps) = if null ps
then ppQIdent q f then ppQIdent q f
else prec d 1 (ppQIdent q f <+> hsep (map (ppPatt q 3) ps)) else prec d 1 (ppQIdent q f <+> hsep (map (ppPatt q 3) ps))
ppPatt q d (PRep p) = prec d 1 (ppPatt q 3 p <> '*') ppPatt q d (PRep p) = prec d 1 (ppPatt q 3 p <> '*')
ppPatt q d (PAs f p) = prec d 2 (f <> '@' <> ppPatt q 3 p) ppPatt q d (PAs f p) = prec d 2 (f <> '@' <> ppPatt q 3 p)
ppPatt q d (PNeg p) = prec d 2 ('-' <> ppPatt q 3 p) ppPatt q d (PNeg p) = prec d 2 ('-' <> ppPatt q 3 p)
ppPatt q d (PChar) = pp '?' ppPatt q d (PChar) = pp '?'
ppPatt q d (PChars s) = brackets (str s) ppPatt q d (PChars s) = brackets (str s)
ppPatt q d (PMacro id) = '#' <> id ppPatt q d (PMacro id) = '#' <> id
ppPatt q d (PM id) = '#' <> ppQIdent q id ppPatt q d (PM id) = '#' <> ppQIdent q id
ppPatt q d PW = pp '_' ppPatt q d PW = pp '_'
ppPatt q d (PV id) = pp id ppPatt q d (PV id) = pp id
ppPatt q d (PInt n) = pp n ppPatt q d (PInt n) = pp n
ppPatt q d (PFloat f) = pp f ppPatt q d (PFloat f) = pp f
ppPatt q d (PString s) = str s ppPatt q d (PString s) = str s
ppPatt q d (PR xs) = braces (hsep (punctuate ';' [l <+> '=' <+> ppPatt q 0 e | (l,e) <- xs])) ppPatt q d (PR xs) = braces (hsep (punctuate ';' [l <+> '=' <+> ppPatt q 0 e | (l,e) <- xs]))
ppPatt q d (PImplArg p) = braces (ppPatt q 0 p) ppPatt q d (PImplArg p) = braces (ppPatt q 0 p)
ppPatt q d (PTilde t) = prec d 2 ('~' <> ppTerm q 6 t) ppPatt q d (PTilde t) = prec d 2 ('~' <> ppTerm q 6 t)
ppValue :: TermPrintQual -> Int -> Val -> Doc ppValue :: TermPrintQual -> Int -> Val -> Doc
ppValue q d (VGen i x) = x <> "{-" <> i <> "-}" ---- latter part for debugging ppValue q d (VGen i x) = x <> "{-" <> i <> "-}" ---- latter part for debugging
ppValue q d (VApp u v) = prec d 4 (ppValue q 4 u <+> ppValue q 5 v) ppValue q d (VApp u v) = prec d 4 (ppValue q 4 u <+> ppValue q 5 v)
ppValue q d (VCn (_,c)) = pp c ppValue q d (VCn (_,c)) = pp c
ppValue q d (VClos env e) = case e of ppValue q d (VClos env e) = case e of
Meta _ -> ppTerm q d e <> ppEnv env Meta _ -> ppTerm q d e <> ppEnv env
_ -> ppTerm q d e ---- ++ prEnv env ---- for debugging _ -> ppTerm q d e ---- ++ prEnv env ---- for debugging
ppValue q d (VRecType xs) = braces (hsep (punctuate ',' [l <> '=' <> ppValue q 0 v | (l,v) <- xs])) ppValue q d (VRecType xs) = braces (hsep (punctuate ',' [l <> '=' <> ppValue q 0 v | (l,v) <- xs]))
ppValue q d VType = pp "Type" ppValue q d VType = pp "Type"
ppConstrs :: Constraints -> [Doc] ppConstrs :: Constraints -> [Doc]
ppConstrs = map (\(v,w) -> braces (ppValue Unqualified 0 v <+> "<>" <+> ppValue Unqualified 0 w)) ppConstrs = map (\(v,w) -> braces (ppValue Unqualified 0 v <+> "<>" <+> ppValue Unqualified 0 w))
ppEnv :: Env -> Doc ppEnv :: Env -> Doc
ppEnv e = hcat (map (\(x,t) -> braces (x <> ":=" <> ppValue Unqualified 0 t)) e) ppEnv e = hcat (map (\(x,t) -> braces (x <> ":=" <> ppValue Unqualified 0 t)) e)
str s = doubleQuotes s str s = doubleQuotes s
ppDecl q (_,id,typ) ppDecl q (_,id,typ)
| id == identW = ppTerm q 3 typ | id == identW = ppTerm q 3 typ
| otherwise = parens (id <+> ':' <+> ppTerm q 0 typ) | otherwise = parens (id <+> ':' <+> ppTerm q 0 typ)
ppDDecl q (_,id,typ) ppDDecl q (_,id,typ)
| id == identW = ppTerm q 6 typ | id == identW = ppTerm q 6 typ
| otherwise = parens (id <+> ':' <+> ppTerm q 0 typ) | otherwise = parens (id <+> ':' <+> ppTerm q 0 typ)
ppQIdent :: TermPrintQual -> QIdent -> Doc ppQIdent :: TermPrintQual -> QIdent -> Doc
ppQIdent q (m,id) = ppQIdent q (m,id) =
case q of case q of
Terse -> pp id Terse -> pp id
Unqualified -> pp id Unqualified -> pp id
Qualified -> m <> '.' <> id Qualified -> m <> '.' <> id
Internal -> m <> '.' <> id Internal -> m <> '.' <> id
instance Pretty Label where pp = pp . label2ident instance Pretty Label where pp = pp . label2ident
ppOpenSpec (OSimple id) = pp id ppOpenSpec (OSimple id) = pp id
ppOpenSpec (OQualif id n) = parens (id <+> '=' <+> n) ppOpenSpec (OQualif id n) = parens (id <+> '=' <+> n)
ppInstSpec (id,n) = parens (id <+> '=' <+> n) ppInstSpec (id,n) = parens (id <+> '=' <+> n)
ppLocDef q (id, (mbt, e)) = ppLocDef q (id, (mbt, e)) =
id <+> id <+>
(case mbt of {Just t -> ':' <+> ppTerm q 0 t; Nothing -> empty} <+> '=' <+> ppTerm q 0 e) <+> ';' (case mbt of {Just t -> ':' <+> ppTerm q 0 t; Nothing -> empty} <+> '=' <+> ppTerm q 0 e) <+> ';'
ppBind (Explicit,v) = pp v ppBind (Explicit,v) = pp v
ppBind (Implicit,v) = braces v ppBind (Implicit,v) = braces v
ppAltern q (x,y) = ppTerm q 0 x <+> '/' <+> ppTerm q 0 y ppAltern q (x,y) = ppTerm q 0 x <+> '/' <+> ppTerm q 0 y
ppParams q ps = fsep (intersperse (pp '|') (map (ppParam q) ps)) ppParams q ps = fsep (intersperse (pp '|') (map (ppParam q) ps))
ppParam q (id,cxt) = id <+> hsep (map (ppDDecl q) cxt) ppParam q (id,cxt) = id <+> hsep (map (ppDDecl q) cxt)
ppProduction (Production fid funid args) = ppProduction (Production fid funid args) =
ppFId fid <+> "->" <+> ppFunId funid <> ppFId fid <+> "->" <+> ppFunId funid <>
brackets (hcat (punctuate "," (map (hsep . intersperse (pp '|') . map ppFId) args))) brackets (hcat (punctuate "," (map (hsep . intersperse (pp '|') . map ppFId) args)))
ppSequences q seqsArr ppSequences q seqsArr
| null seqs || q /= Internal = empty | null seqs || q /= Internal = empty
| otherwise = "sequences" <+> '{' $$ | otherwise = "sequences" <+> '{' $$
nest 2 (vcat (map ppSeq seqs)) $$ nest 2 (vcat (map ppSeq seqs)) $$
'}' '}'
where where
seqs = Array.assocs seqsArr seqs = Array.assocs seqsArr
commaPunct f ds = (hcat (punctuate "," (map f ds))) commaPunct f ds = (hcat (punctuate "," (map f ds)))
prec d1 d2 doc prec d1 d2 doc
| d1 > d2 = parens doc | d1 > d2 = parens doc
| otherwise = doc | otherwise = doc
getAbs :: Term -> ([(BindType,Ident)], Term) getAbs :: Term -> ([(BindType,Ident)], Term)
getAbs (Abs bt v e) = let (xs,e') = getAbs e getAbs (Abs bt v e) = let (xs,e') = getAbs e
in ((bt,v):xs,e') in ((bt,v):xs,e')
getAbs e = ([],e) getAbs e = ([],e)
getCTable :: Term -> ([Ident], Term) getCTable :: Term -> ([Ident], Term)
getCTable (T TRaw [(PV v,e)]) = let (vs,e') = getCTable e getCTable (T TRaw [(PV v,e)]) = let (vs,e') = getCTable e
in (v:vs,e') in (v:vs,e')
getCTable (T TRaw [(PW, e)]) = let (vs,e') = getCTable e getCTable (T TRaw [(PW, e)]) = let (vs,e') = getCTable e
in (identW:vs,e') in (identW:vs,e')
getCTable e = ([],e) getCTable e = ([],e)
getLet :: Term -> ([LocalDef], Term) getLet :: Term -> ([LocalDef], Term)
getLet (Let l e) = let (ls,e') = getLet e getLet (Let l e) = let (ls,e') = getLet e
in (l:ls,e') in (l:ls,e')
getLet e = ([],e) getLet e = ([],e)

View File

@@ -5,22 +5,23 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/04/21 16:22:32 $ -- > CVS $Date: 2005/04/21 16:22:32 $
-- > CVS $Author: bringert $ -- > CVS $Author: bringert $
-- > CVS $Revision: 1.7 $ -- > CVS $Revision: 1.7 $
-- --
-- (Description of the module) -- (Description of the module)
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module GF.Grammar.Values (-- ** Values used in TC type checking module GF.Grammar.Values (
Val(..), Env, -- ** Values used in TC type checking
-- ** Annotated tree used in editing Val(..), Env,
-- ** Annotated tree used in editing
Binds, Constraints, MetaSubst, Binds, Constraints, MetaSubst,
-- ** For TC -- ** For TC
valAbsInt, valAbsFloat, valAbsString, vType, valAbsInt, valAbsFloat, valAbsString, vType,
isPredefCat, isPredefCat,
eType, eType,
) where ) where
import GF.Infra.Ident import GF.Infra.Ident
import GF.Grammar.Grammar import GF.Grammar.Grammar

View File

@@ -5,7 +5,7 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/04/21 16:22:33 $ -- > CVS $Date: 2005/04/21 16:22:33 $
-- > CVS $Author: bringert $ -- > CVS $Author: bringert $
-- > CVS $Revision: 1.5 $ -- > CVS $Revision: 1.5 $
-- --
@@ -14,10 +14,10 @@
module GF.Infra.CheckM module GF.Infra.CheckM
(Check, CheckResult, Message, runCheck, runCheck', (Check, CheckResult, Message, runCheck, runCheck',
checkError, checkCond, checkWarn, checkWarnings, checkAccumError, checkError, checkCond, checkWarn, checkWarnings, checkAccumError,
checkIn, checkInModule, checkMap, checkMapRecover, checkIn, checkInModule, checkMap, checkMapRecover,
parallelCheck, accumulateError, commitCheck, parallelCheck, accumulateError, commitCheck,
) where ) where
import Prelude hiding ((<>)) -- GHC 8.4.1 clash with Text.PrettyPrint import Prelude hiding ((<>)) -- GHC 8.4.1 clash with Text.PrettyPrint
import GF.Data.Operations import GF.Data.Operations
@@ -141,10 +141,10 @@ checkMapRecover f = fmap Map.fromList . parallelCheck . map f' . Map.toList
where f' (k,v) = fmap ((,)k) (f k v) where f' (k,v) = fmap ((,)k) (f k v)
{- {-
checkMapRecover f mp = do checkMapRecover f mp = do
let xs = map (\ (k,v) -> (k,runCheck (f k v))) (Map.toList mp) let xs = map (\ (k,v) -> (k,runCheck (f k v))) (Map.toList mp)
case [s | (_,Bad s) <- xs] of case [s | (_,Bad s) <- xs] of
ss@(_:_) -> checkError (text (unlines ss)) ss@(_:_) -> checkError (text (unlines ss))
_ -> do _ -> do
let (kx,ss) = unzip [((k,x),s) | (k, Ok (x,s)) <- xs] let (kx,ss) = unzip [((k,x),s) | (k, Ok (x,s)) <- xs]
if not (all null ss) then checkWarn (text (unlines ss)) else return () if not (all null ss) then checkWarn (text (unlines ss)) else return ()

View File

@@ -38,7 +38,6 @@ import GF.Server(server)
#endif #endif
import GF.Command.Messages(welcome) import GF.Command.Messages(welcome)
import GF.Infra.UseIO (Output)
-- Provides an orphan instance of MonadFail for StateT in ghc versions < 8 -- Provides an orphan instance of MonadFail for StateT in ghc versions < 8
import Control.Monad.Trans.Instances () import Control.Monad.Trans.Instances ()
@@ -56,6 +55,7 @@ mainGFI opts files = do
shell opts files = flip evalStateT (emptyGFEnv opts) $ shell opts files = flip evalStateT (emptyGFEnv opts) $
do mapStateT runSIO $ importInEnv opts files do mapStateT runSIO $ importInEnv opts files
modify $ \ gfenv0 -> gfenv0 {history = [unwords ("i":files)]}
loop loop
#ifdef SERVER_MODE #ifdef SERVER_MODE
@@ -433,7 +433,7 @@ wc_type = cmd_name
x2 = takeWhile (\c -> isIdent c || isSpace c || c == '-' || c == '=' || c == '"') x1 x2 = takeWhile (\c -> isIdent c || isSpace c || c == '-' || c == '=' || c == '"') x1
cmd = case [x | (x,cs) <- RP.readP_to_S pCommand x2, all isSpace cs] of cmd = case [x | (x,cs) <- RP.readP_to_S pCommand x2, all isSpace cs] of
[x] -> Just x [x] -> Just x
_ -> Nothing _ -> Nothing
isIdent c = c == '_' || c == '\'' || isAlphaNum c isIdent c = c == '_' || c == '\'' || isAlphaNum c

View File

@@ -58,6 +58,7 @@ mainGFI opts files = do
shell opts files = flip evalStateT (emptyGFEnv opts) $ shell opts files = flip evalStateT (emptyGFEnv opts) $
do mapStateT runSIO $ importInEnv opts files do mapStateT runSIO $ importInEnv opts files
modify $ \ gfenv0 -> gfenv0 {history = [unwords ("i":files)]}
loop loop
{- {-
@@ -101,7 +102,7 @@ timeIt act =
-- | Optionally show how much CPU time was used to run an IO action -- | Optionally show how much CPU time was used to run an IO action
optionallyShowCPUTime :: (Monad m,MonadSIO m) => Options -> m a -> m a optionallyShowCPUTime :: (Monad m,MonadSIO m) => Options -> m a -> m a
optionallyShowCPUTime opts act optionallyShowCPUTime opts act
| not (verbAtLeast opts Normal) = act | not (verbAtLeast opts Normal) = act
| otherwise = do (dt,r) <- timeIt act | otherwise = do (dt,r) <- timeIt act
liftSIO $ putStrLnFlush $ show (dt `div` 1000000000) ++ " msec" liftSIO $ putStrLnFlush $ show (dt `div` 1000000000) ++ " msec"
@@ -358,7 +359,7 @@ wordCompletion gfenv (left,right) = do
CmplIdent _ pref CmplIdent _ pref
-> case mb_pgf of -> case mb_pgf of
Just pgf -> ret (length pref) Just pgf -> ret (length pref)
[Haskeline.simpleCompletion name [Haskeline.simpleCompletion name
| name <- C.functions pgf, | name <- C.functions pgf,
isPrefixOf pref name] isPrefixOf pref name]
_ -> ret (length pref) [] _ -> ret (length pref) []
@@ -369,7 +370,7 @@ wordCompletion gfenv (left,right) = do
cmdEnv = commandenv gfenv cmdEnv = commandenv gfenv
{- {-
optLang opts = valStrOpts "lang" (head $ Map.keys (concretes cmdEnv)) opts optLang opts = valStrOpts "lang" (head $ Map.keys (concretes cmdEnv)) opts
optType opts = optType opts =
let str = valStrOpts "cat" (H.showCId $ H.lookStartCat pgf) opts let str = valStrOpts "cat" (H.showCId $ H.lookStartCat pgf) opts
in case H.readType str of in case H.readType str of
Just ty -> ty Just ty -> ty
@@ -416,7 +417,7 @@ wc_type = cmd_name
option x y (c :cs) option x y (c :cs)
| isIdent c = option x y cs | isIdent c = option x y cs
| otherwise = cmd x cs | otherwise = cmd x cs
optValue x y ('"':cs) = str x y cs optValue x y ('"':cs) = str x y cs
optValue x y cs = cmd x cs optValue x y cs = cmd x cs
@@ -434,9 +435,9 @@ wc_type = cmd_name
where where
x1 = take (length x - length y - d) x x1 = take (length x - length y - d) x
x2 = takeWhile (\c -> isIdent c || isSpace c || c == '-' || c == '=' || c == '"') x1 x2 = takeWhile (\c -> isIdent c || isSpace c || c == '-' || c == '=' || c == '"') x1
cmd = case [x | (x,cs) <- RP.readP_to_S pCommand x2, all isSpace cs] of cmd = case [x | (x,cs) <- RP.readP_to_S pCommand x2, all isSpace cs] of
[x] -> Just x [x] -> Just x
_ -> Nothing _ -> Nothing
isIdent c = c == '_' || c == '\'' || isAlphaNum c isIdent c = c == '_' || c == '\'' || isAlphaNum c

View File

@@ -16,18 +16,19 @@ import Data.Version
import System.Directory import System.Directory
import System.Environment (getArgs) import System.Environment (getArgs)
import System.Exit import System.Exit
import GF.System.Console (setConsoleEncoding) -- import GF.System.Console (setConsoleEncoding)
-- | Run the GF main program, taking arguments from the command line. -- | Run the GF main program, taking arguments from the command line.
-- (It calls 'setConsoleEncoding' and 'getOptions', then 'mainOpts'.) -- (It calls 'setConsoleEncoding' and 'getOptions', then 'mainOpts'.)
-- Run @gf --help@ for usage info. -- Run @gf --help@ for usage info.
main :: IO () main :: IO ()
main = do main = do
--setConsoleEncoding -- setConsoleEncoding
uncurry mainOpts =<< getOptions uncurry mainOpts =<< getOptions
-- | Get and parse GF command line arguments. Fix relative paths. -- | Get and parse GF command line arguments. Fix relative paths.
-- Calls 'getArgs' and 'parseOptions'. -- Calls 'getArgs' and 'parseOptions'.
getOptions :: IO (Options, [FilePath])
getOptions = do getOptions = do
args <- getArgs args <- getArgs
case parseOptions args of case parseOptions args of
@@ -43,7 +44,7 @@ getOptions = do
-- the options it invokes 'mainGFC', 'mainGFI', 'mainRunGFI', 'mainServerGFI', -- the options it invokes 'mainGFC', 'mainGFI', 'mainRunGFI', 'mainServerGFI',
-- or it just prints version/usage info. -- or it just prints version/usage info.
mainOpts :: Options -> [FilePath] -> IO () mainOpts :: Options -> [FilePath] -> IO ()
mainOpts opts files = mainOpts opts files =
case flag optMode opts of case flag optMode opts of
ModeVersion -> putStrLn $ "Grammatical Framework (GF) version " ++ showVersion version ++ "\n" ++ buildInfo ModeVersion -> putStrLn $ "Grammatical Framework (GF) version " ++ showVersion version ++ "\n" ++ buildInfo
ModeHelp -> putStrLn helpMessage ModeHelp -> putStrLn helpMessage

View File

@@ -5,37 +5,37 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/11/10 16:43:44 $ -- > CVS $Date: 2005/11/10 16:43:44 $
-- > CVS $Author: bringert $ -- > CVS $Author: bringert $
-- > CVS $Revision: 1.16 $ -- > CVS $Revision: 1.16 $
-- --
-- A simple finite state network module. -- A simple finite state network module.
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module GF.Speech.FiniteState (FA(..), State, NFA, DFA, module GF.Speech.FiniteState (FA(..), State, NFA, DFA,
startState, finalStates, startState, finalStates,
states, transitions, states, transitions,
isInternal, isInternal,
newFA, newFA_, newFA, newFA_,
addFinalState, addFinalState,
newState, newStates, newState, newStates,
newTransition, newTransitions, newTransition, newTransitions,
insertTransitionWith, insertTransitionsWith, insertTransitionWith, insertTransitionsWith,
mapStates, mapTransitions, mapStates, mapTransitions,
modifyTransitions, modifyTransitions,
nonLoopTransitionsTo, nonLoopTransitionsFrom, nonLoopTransitionsTo, nonLoopTransitionsFrom,
loops, loops,
removeState, removeState,
oneFinalState, oneFinalState,
insertNFA, insertNFA,
onGraph, onGraph,
moveLabelsToNodes, removeTrivialEmptyNodes, moveLabelsToNodes, removeTrivialEmptyNodes,
minimize, minimize,
dfa2nfa, dfa2nfa,
unusedNames, renameStates, unusedNames, renameStates,
prFAGraphviz, faToGraphviz) where prFAGraphviz, faToGraphviz) where
import Data.List import Data.List
import Data.Maybe import Data.Maybe
--import Data.Map (Map) --import Data.Map (Map)
import qualified Data.Map as Map import qualified Data.Map as Map
import Data.Set (Set) import Data.Set (Set)
@@ -98,13 +98,13 @@ newTransition f t l = onGraph (newEdge (f,t,l))
newTransitions :: [(n, n, b)] -> FA n a b -> FA n a b newTransitions :: [(n, n, b)] -> FA n a b -> FA n a b
newTransitions es = onGraph (newEdges es) newTransitions es = onGraph (newEdges es)
insertTransitionWith :: Eq n => insertTransitionWith :: Eq n =>
(b -> b -> b) -> (n, n, b) -> FA n a b -> FA n a b (b -> b -> b) -> (n, n, b) -> FA n a b -> FA n a b
insertTransitionWith f t = onGraph (insertEdgeWith f t) insertTransitionWith f t = onGraph (insertEdgeWith f t)
insertTransitionsWith :: Eq n => insertTransitionsWith :: Eq n =>
(b -> b -> b) -> [(n, n, b)] -> FA n a b -> FA n a b (b -> b -> b) -> [(n, n, b)] -> FA n a b -> FA n a b
insertTransitionsWith f ts fa = insertTransitionsWith f ts fa =
foldl' (flip (insertTransitionWith f)) fa ts foldl' (flip (insertTransitionWith f)) fa ts
mapStates :: (a -> c) -> FA n a b -> FA n c b mapStates :: (a -> c) -> FA n a b -> FA n c b
@@ -128,11 +128,11 @@ unusedNames (FA (Graph names _ _) _ _) = names
-- | Gets all incoming transitions to a given state, excluding -- | Gets all incoming transitions to a given state, excluding
-- transtions from the state itself. -- transtions from the state itself.
nonLoopTransitionsTo :: Eq n => n -> FA n a b -> [(n,b)] nonLoopTransitionsTo :: Eq n => n -> FA n a b -> [(n,b)]
nonLoopTransitionsTo s fa = nonLoopTransitionsTo s fa =
[(f,l) | (f,t,l) <- transitions fa, t == s && f /= s] [(f,l) | (f,t,l) <- transitions fa, t == s && f /= s]
nonLoopTransitionsFrom :: Eq n => n -> FA n a b -> [(n,b)] nonLoopTransitionsFrom :: Eq n => n -> FA n a b -> [(n,b)]
nonLoopTransitionsFrom s fa = nonLoopTransitionsFrom s fa =
[(t,l) | (f,t,l) <- transitions fa, f == s && t /= s] [(t,l) | (f,t,l) <- transitions fa, f == s && t /= s]
loops :: Eq n => n -> FA n a b -> [b] loops :: Eq n => n -> FA n a b -> [b]
@@ -145,7 +145,7 @@ renameStates :: Ord x => [y] -- ^ Infinite supply of new names
renameStates supply (FA g s fs) = FA (renameNodes newName rest g) s' fs' renameStates supply (FA g s fs) = FA (renameNodes newName rest g) s' fs'
where (ns,rest) = splitAt (length (nodes g)) supply where (ns,rest) = splitAt (length (nodes g)) supply
newNodes = Map.fromList (zip (map fst (nodes g)) ns) newNodes = Map.fromList (zip (map fst (nodes g)) ns)
newName n = Map.findWithDefault (error "FiniteState.newName") n newNodes newName n = Map.findWithDefault (error "FiniteState.newName") n newNodes
s' = newName s s' = newName s
fs' = map newName fs fs' = map newName fs
@@ -154,9 +154,9 @@ insertNFA :: NFA a -- ^ NFA to insert into
-> (State, State) -- ^ States to insert between -> (State, State) -- ^ States to insert between
-> NFA a -- ^ NFA to insert. -> NFA a -- ^ NFA to insert.
-> NFA a -> NFA a
insertNFA (FA g1 s1 fs1) (f,t) (FA g2 s2 fs2) insertNFA (FA g1 s1 fs1) (f,t) (FA g2 s2 fs2)
= FA (newEdges es g') s1 fs1 = FA (newEdges es g') s1 fs1
where where
es = (f,ren s2,Nothing):[(ren f2,t,Nothing) | f2 <- fs2] es = (f,ren s2,Nothing):[(ren f2,t,Nothing) | f2 <- fs2]
(g',ren) = mergeGraphs g1 g2 (g',ren) = mergeGraphs g1 g2
@@ -182,9 +182,9 @@ oneFinalState nl el fa =
moveLabelsToNodes :: (Ord n,Eq a) => FA n () (Maybe a) -> FA n (Maybe a) () moveLabelsToNodes :: (Ord n,Eq a) => FA n () (Maybe a) -> FA n (Maybe a) ()
moveLabelsToNodes = onGraph f moveLabelsToNodes = onGraph f
where f g@(Graph c _ _) = Graph c' ns (concat ess) where f g@(Graph c _ _) = Graph c' ns (concat ess)
where is = [ ((n,l),inc) | (n, (l,inc,_)) <- Map.toList (nodeInfo g)] where is = [ ((n,l),inc) | (n, (l,inc,_)) <- Map.toList (nodeInfo g)]
(c',is') = mapAccumL fixIncoming c is (c',is') = mapAccumL fixIncoming c is
(ns,ess) = unzip (concat is') (ns,ess) = unzip (concat is')
-- | Remove empty nodes which are not start or final, and have -- | Remove empty nodes which are not start or final, and have
@@ -196,12 +196,12 @@ removeTrivialEmptyNodes = pruneUnusable . skipSimpleEmptyNodes
-- This is not done if the pointed-to node is a final node. -- This is not done if the pointed-to node is a final node.
skipSimpleEmptyNodes :: (Eq a, Ord n) => FA n (Maybe a) () -> FA n (Maybe a) () skipSimpleEmptyNodes :: (Eq a, Ord n) => FA n (Maybe a) () -> FA n (Maybe a) ()
skipSimpleEmptyNodes fa = onGraph og fa skipSimpleEmptyNodes fa = onGraph og fa
where where
og g@(Graph c ns es) = if es' == es then g else og (Graph c ns es') og g@(Graph c ns es) = if es' == es then g else og (Graph c ns es')
where where
es' = concatMap changeEdge es es' = concatMap changeEdge es
info = nodeInfo g info = nodeInfo g
changeEdge e@(f,t,()) changeEdge e@(f,t,())
| isNothing (getNodeLabel info t) | isNothing (getNodeLabel info t)
-- && (i * o <= i + o) -- && (i * o <= i + o)
&& not (isFinal fa t) && not (isFinal fa t)
@@ -223,28 +223,28 @@ pruneUnusable fa = onGraph f fa
where where
f g = if Set.null rns then g else f (removeNodes rns g) f g = if Set.null rns then g else f (removeNodes rns g)
where info = nodeInfo g where info = nodeInfo g
rns = Set.fromList [ n | (n,_) <- nodes g, rns = Set.fromList [ n | (n,_) <- nodes g,
isInternal fa n, isInternal fa n,
inDegree info n == 0 inDegree info n == 0
|| outDegree info n == 0] || outDegree info n == 0]
fixIncoming :: (Ord n, Eq a) => [n] fixIncoming :: (Ord n, Eq a) => [n]
-> (Node n (),[Edge n (Maybe a)]) -- ^ A node and its incoming edges -> (Node n (),[Edge n (Maybe a)]) -- ^ A node and its incoming edges
-> ([n],[(Node n (Maybe a),[Edge n ()])]) -- ^ Replacement nodes with their -> ([n],[(Node n (Maybe a),[Edge n ()])]) -- ^ Replacement nodes with their
-- incoming edges. -- incoming edges.
fixIncoming cs c@((n,()),es) = (cs'', ((n,Nothing),es'):newContexts) fixIncoming cs c@((n,()),es) = (cs'', ((n,Nothing),es'):newContexts)
where ls = nub $ map edgeLabel es where ls = nub $ map edgeLabel es
(cs',cs'') = splitAt (length ls) cs (cs',cs'') = splitAt (length ls) cs
newNodes = zip cs' ls newNodes = zip cs' ls
es' = [ (x,n,()) | x <- map fst newNodes ] es' = [ (x,n,()) | x <- map fst newNodes ]
-- separate cyclic and non-cyclic edges -- separate cyclic and non-cyclic edges
(cyc,ncyc) = partition (\ (f,_,_) -> f == n) es (cyc,ncyc) = partition (\ (f,_,_) -> f == n) es
-- keep all incoming non-cyclic edges with the right label -- keep all incoming non-cyclic edges with the right label
to (x,l) = [ (f,x,()) | (f,_,l') <- ncyc, l == l'] to (x,l) = [ (f,x,()) | (f,_,l') <- ncyc, l == l']
-- for each cyclic edge with the right label, -- for each cyclic edge with the right label,
-- add an edge from each of the new nodes (including this one) -- add an edge from each of the new nodes (including this one)
++ [ (y,x,()) | (f,_,l') <- cyc, l == l', (y,_) <- newNodes] ++ [ (y,x,()) | (f,_,l') <- cyc, l == l', (y,_) <- newNodes]
newContexts = [ (v, to v) | v <- newNodes ] newContexts = [ (v, to v) | v <- newNodes ]
--alphabet :: Eq b => Graph n a (Maybe b) -> [b] --alphabet :: Eq b => Graph n a (Maybe b) -> [b]
--alphabet = nub . catMaybes . map edgeLabel . edges --alphabet = nub . catMaybes . map edgeLabel . edges
@@ -254,19 +254,19 @@ determinize (FA g s f) = let (ns,es) = h (Set.singleton start) Set.empty Set.emp
(ns',es') = (Set.toList ns, Set.toList es) (ns',es') = (Set.toList ns, Set.toList es)
final = filter isDFAFinal ns' final = filter isDFAFinal ns'
fa = FA (Graph undefined [(n,()) | n <- ns'] es') start final fa = FA (Graph undefined [(n,()) | n <- ns'] es') start final
in renameStates [0..] fa in renameStates [0..] fa
where info = nodeInfo g where info = nodeInfo g
-- reach = nodesReachable out -- reach = nodesReachable out
start = closure info $ Set.singleton s start = closure info $ Set.singleton s
isDFAFinal n = not (Set.null (Set.fromList f `Set.intersection` n)) isDFAFinal n = not (Set.null (Set.fromList f `Set.intersection` n))
h currentStates oldStates es h currentStates oldStates es
| Set.null currentStates = (oldStates,es) | Set.null currentStates = (oldStates,es)
| otherwise = ((h $! uniqueNewStates) $! allOldStates) $! es' | otherwise = ((h $! uniqueNewStates) $! allOldStates) $! es'
where where
allOldStates = oldStates `Set.union` currentStates allOldStates = oldStates `Set.union` currentStates
(newStates,es') = new (Set.toList currentStates) Set.empty es (newStates,es') = new (Set.toList currentStates) Set.empty es
uniqueNewStates = newStates Set.\\ allOldStates uniqueNewStates = newStates Set.\\ allOldStates
-- Get the sets of states reachable from the given states -- Get the sets of states reachable from the given states
-- by consuming one symbol, and the associated edges. -- by consuming one symbol, and the associated edges.
new [] rs es = (rs,es) new [] rs es = (rs,es)
new (n:ns) rs es = new ns rs' es' new (n:ns) rs es = new ns rs' es'
@@ -281,7 +281,7 @@ closure info x = closure_ x x
where closure_ acc check | Set.null check = acc where closure_ acc check | Set.null check = acc
| otherwise = closure_ acc' check' | otherwise = closure_ acc' check'
where where
reach = Set.fromList [y | x <- Set.toList check, reach = Set.fromList [y | x <- Set.toList check,
(_,y,Nothing) <- getOutgoing info x] (_,y,Nothing) <- getOutgoing info x]
acc' = acc `Set.union` reach acc' = acc `Set.union` reach
check' = reach Set.\\ acc check' = reach Set.\\ acc
@@ -296,8 +296,8 @@ reachable1 info ns = Map.fromListWith (++) [(c, [y]) | n <- Set.toList ns, (_,y,
reverseNFA :: NFA a -> NFA a reverseNFA :: NFA a -> NFA a
reverseNFA (FA g s fs) = FA g''' s' [s] reverseNFA (FA g s fs) = FA g''' s' [s]
where g' = reverseGraph g where g' = reverseGraph g
(g'',s') = newNode () g' (g'',s') = newNode () g'
g''' = newEdges [(s',f,Nothing) | f <- fs] g'' g''' = newEdges [(s',f,Nothing) | f <- fs] g''
dfa2nfa :: DFA a -> NFA a dfa2nfa :: DFA a -> NFA a
dfa2nfa = mapTransitions Just dfa2nfa = mapTransitions Just
@@ -313,13 +313,13 @@ prFAGraphviz = Dot.prGraphviz . faToGraphviz
--prFAGraphviz_ = Dot.prGraphviz . faToGraphviz . mapStates show . mapTransitions show --prFAGraphviz_ = Dot.prGraphviz . faToGraphviz . mapStates show . mapTransitions show
faToGraphviz :: (Eq n,Show n) => FA n String String -> Dot.Graph faToGraphviz :: (Eq n,Show n) => FA n String String -> Dot.Graph
faToGraphviz (FA (Graph _ ns es) s f) faToGraphviz (FA (Graph _ ns es) s f)
= Dot.Graph Dot.Directed Nothing [] (map mkNode ns) (map mkEdge es) [] = Dot.Graph Dot.Directed Nothing [] (map mkNode ns) (map mkEdge es) []
where mkNode (n,l) = Dot.Node (show n) attrs where mkNode (n,l) = Dot.Node (show n) attrs
where attrs = [("label",l)] where attrs = [("label",l)]
++ if n == s then [("shape","box")] else [] ++ if n == s then [("shape","box")] else []
++ if n `elem` f then [("style","bold")] else [] ++ if n `elem` f then [("style","bold")] else []
mkEdge (x,y,l) = Dot.Edge (show x) (show y) [("label",l)] mkEdge (x,y,l) = Dot.Edge (show x) (show y) [("label",l)]
-- --
-- * Utilities -- * Utilities

View File

@@ -26,14 +26,14 @@ width = 75
gslPrinter :: Options -> PGF -> CId -> String gslPrinter :: Options -> PGF -> CId -> String
gslPrinter opts pgf cnc = renderStyle st $ prGSL $ makeNonLeftRecursiveSRG opts pgf cnc gslPrinter opts pgf cnc = renderStyle st $ prGSL $ makeNonLeftRecursiveSRG opts pgf cnc
where st = style { lineLength = width } where st = style { lineLength = width }
prGSL :: SRG -> Doc prGSL :: SRG -> Doc
prGSL srg = header $++$ mainCat $++$ foldr ($++$) empty (map prRule (srgRules srg)) prGSL srg = header $++$ mainCat $++$ foldr ($++$) empty (map prRule (srgRules srg))
where where
header = ";GSL2.0" $$ header = ";GSL2.0" $$
comment ("Nuance speech recognition grammar for " ++ srgName srg) $$ comment ("Nuance speech recognition grammar for " ++ srgName srg) $$
comment ("Generated by GF") comment ("Generated by GF")
mainCat = ".MAIN" <+> prCat (srgStartCat srg) mainCat = ".MAIN" <+> prCat (srgStartCat srg)
prRule (SRGRule cat rhs) = prCat cat <+> union (map prAlt rhs) prRule (SRGRule cat rhs) = prCat cat <+> union (map prAlt rhs)
-- FIXME: use the probability -- FIXME: use the probability

View File

@@ -31,7 +31,7 @@ width :: Int
width = 75 width = 75
jsgfPrinter :: Options jsgfPrinter :: Options
-> PGF -> PGF
-> CId -> String -> CId -> String
jsgfPrinter opts pgf cnc = renderStyle st $ prJSGF sisr $ makeNonLeftRecursiveSRG opts pgf cnc jsgfPrinter opts pgf cnc = renderStyle st $ prJSGF sisr $ makeNonLeftRecursiveSRG opts pgf cnc
where st = style { lineLength = width } where st = style { lineLength = width }
@@ -44,7 +44,7 @@ prJSGF sisr srg
header = "#JSGF" <+> "V1.0" <+> "UTF-8" <+> lang <> ';' $$ header = "#JSGF" <+> "V1.0" <+> "UTF-8" <+> lang <> ';' $$
comment ("JSGF speech recognition grammar for " ++ srgName srg) $$ comment ("JSGF speech recognition grammar for " ++ srgName srg) $$
comment "Generated by GF" $$ comment "Generated by GF" $$
("grammar " ++ srgName srg ++ ";") ("grammar " ++ srgName srg ++ ";")
lang = maybe empty pp (srgLanguage srg) lang = maybe empty pp (srgLanguage srg)
mainCat = rule True "MAIN" [prCat (srgStartCat srg)] mainCat = rule True "MAIN" [prCat (srgStartCat srg)]
prRule (SRGRule cat rhs) = rule (isExternalCat srg cat) cat (map prAlt rhs) prRule (SRGRule cat rhs) = rule (isExternalCat srg cat) cat (map prAlt rhs)
@@ -62,7 +62,7 @@ prItem :: Maybe SISRFormat -> CFTerm -> SRGItem -> Doc
prItem sisr t = f 0 prItem sisr t = f 0
where where
f _ (REUnion []) = pp "<VOID>" f _ (REUnion []) = pp "<VOID>"
f p (REUnion xs) f p (REUnion xs)
| not (null es) = brackets (f 0 (REUnion nes)) | not (null es) = brackets (f 0 (REUnion nes))
| otherwise = (if p >= 1 then parens else id) (alts (map (f 1) xs)) | otherwise = (if p >= 1 then parens else id) (alts (map (f 1) xs))
where (es,nes) = partition isEpsilon xs where (es,nes) = partition isEpsilon xs
@@ -110,4 +110,3 @@ prepunctuate p (x:xs) = x : map (p <>) xs
($++$) :: Doc -> Doc -> Doc ($++$) :: Doc -> Doc -> Doc
x $++$ y = x $$ emptyLine $$ y x $++$ y = x $$ emptyLine $$ y

View File

@@ -28,7 +28,7 @@ toBNF f pgf cnc = prCFG $ f $ pgfToCFG pgf cnc
type Profile = [Int] type Profile = [Int]
pgfToCFG :: PGF pgfToCFG :: PGF
-> CId -- ^ Concrete syntax name -> CId -- ^ Concrete syntax name
-> CFG -> CFG
pgfToCFG pgf lang = mkCFG (showCId (lookStartCat pgf)) extCats (startRules ++ concatMap ruleToCFRule rules) pgfToCFG pgf lang = mkCFG (showCId (lookStartCat pgf)) extCats (startRules ++ concatMap ruleToCFRule rules)
@@ -40,8 +40,8 @@ pgfToCFG pgf lang = mkCFG (showCId (lookStartCat pgf)) extCats (startRules ++ co
, prod <- Set.toList set] , prod <- Set.toList set]
fcatCats :: Map FId Cat fcatCats :: Map FId Cat
fcatCats = Map.fromList [(fc, showCId c ++ "_" ++ show i) fcatCats = Map.fromList [(fc, showCId c ++ "_" ++ show i)
| (c,CncCat s e lbls) <- Map.toList (cnccats cnc), | (c,CncCat s e lbls) <- Map.toList (cnccats cnc),
(fc,i) <- zip (range (s,e)) [1..]] (fc,i) <- zip (range (s,e)) [1..]]
fcatCat :: FId -> Cat fcatCat :: FId -> Cat
@@ -58,7 +58,7 @@ pgfToCFG pgf lang = mkCFG (showCId (lookStartCat pgf)) extCats (startRules ++ co
topdownRules cat = f cat [] topdownRules cat = f cat []
where where
f cat rules = maybe rules (Set.foldr g rules) (IntMap.lookup cat (productions cnc)) f cat rules = maybe rules (Set.foldr g rules) (IntMap.lookup cat (productions cnc))
g (PApply funid args) rules = (cncfuns cnc ! funid,args) : rules g (PApply funid args) rules = (cncfuns cnc ! funid,args) : rules
g (PCoerce cat) rules = f cat rules g (PCoerce cat) rules = f cat rules
@@ -67,13 +67,13 @@ pgfToCFG pgf lang = mkCFG (showCId (lookStartCat pgf)) extCats (startRules ++ co
extCats = Set.fromList $ map ruleLhs startRules extCats = Set.fromList $ map ruleLhs startRules
startRules :: [CFRule] startRules :: [CFRule]
startRules = [Rule (showCId c) [NonTerminal (fcatToCat fc r)] (CFRes 0) startRules = [Rule (showCId c) [NonTerminal (fcatToCat fc r)] (CFRes 0)
| (c,CncCat s e lbls) <- Map.toList (cnccats cnc), | (c,CncCat s e lbls) <- Map.toList (cnccats cnc),
fc <- range (s,e), not (isPredefFId fc), fc <- range (s,e), not (isPredefFId fc),
r <- [0..catLinArity fc-1]] r <- [0..catLinArity fc-1]]
ruleToCFRule :: (FId,Production) -> [CFRule] ruleToCFRule :: (FId,Production) -> [CFRule]
ruleToCFRule (c,PApply funid args) = ruleToCFRule (c,PApply funid args) =
[Rule (fcatToCat c l) (mkRhs row) (profilesToTerm [fixProfile row n | n <- [0..length args-1]]) [Rule (fcatToCat c l) (mkRhs row) (profilesToTerm [fixProfile row n | n <- [0..length args-1]])
| (l,seqid) <- Array.assocs rhs | (l,seqid) <- Array.assocs rhs
, let row = sequences cnc ! seqid , let row = sequences cnc ! seqid
@@ -106,7 +106,7 @@ pgfToCFG pgf lang = mkCFG (showCId (lookStartCat pgf)) extCats (startRules ++ co
fixProfile row i = [k | (k,j) <- nts, j == i] fixProfile row i = [k | (k,j) <- nts, j == i]
where where
nts = zip [0..] [j | nt <- Array.elems row, j <- getPos nt] nts = zip [0..] [j | nt <- Array.elems row, j <- getPos nt]
getPos (SymCat j _) = [j] getPos (SymCat j _) = [j]
getPos (SymLit j _) = [j] getPos (SymLit j _) = [j]
getPos _ = [] getPos _ = []

View File

@@ -2,8 +2,8 @@
-- | -- |
-- Module : SRG -- Module : SRG
-- --
-- Representation of, conversion to, and utilities for -- Representation of, conversion to, and utilities for
-- printing of a general Speech Recognition Grammar. -- printing of a general Speech Recognition Grammar.
-- --
-- FIXME: remove \/ warn \/ fail if there are int \/ string literal -- FIXME: remove \/ warn \/ fail if there are int \/ string literal
-- categories in the grammar -- categories in the grammar
@@ -40,20 +40,20 @@ import qualified Data.Set as Set
--import Debug.Trace --import Debug.Trace
data SRG = SRG { srgName :: String -- ^ grammar name data SRG = SRG { srgName :: String -- ^ grammar name
, srgStartCat :: Cat -- ^ start category name , srgStartCat :: Cat -- ^ start category name
, srgExternalCats :: Set Cat , srgExternalCats :: Set Cat
, srgLanguage :: Maybe String -- ^ The language for which the grammar , srgLanguage :: Maybe String -- ^ The language for which the grammar
-- is intended, e.g. en-UK -- is intended, e.g. en-UK
, srgRules :: [SRGRule] , srgRules :: [SRGRule]
} }
deriving (Eq,Show) deriving (Eq,Show)
data SRGRule = SRGRule Cat [SRGAlt] data SRGRule = SRGRule Cat [SRGAlt]
deriving (Eq,Show) deriving (Eq,Show)
-- | maybe a probability, a rule name and an EBNF right-hand side -- | maybe a probability, a rule name and an EBNF right-hand side
data SRGAlt = SRGAlt (Maybe Double) CFTerm SRGItem data SRGAlt = SRGAlt (Maybe Double) CFTerm SRGItem
deriving (Eq,Show) deriving (Eq,Show)
type SRGItem = RE SRGSymbol type SRGItem = RE SRGSymbol
@@ -65,7 +65,7 @@ type SRGNT = (Cat, Int)
ebnfPrinter :: Options -> PGF -> CId -> String ebnfPrinter :: Options -> PGF -> CId -> String
ebnfPrinter opts pgf cnc = prSRG opts $ makeSRG opts pgf cnc ebnfPrinter opts pgf cnc = prSRG opts $ makeSRG opts pgf cnc
-- | Create a compact filtered non-left-recursive SRG. -- | Create a compact filtered non-left-recursive SRG.
makeNonLeftRecursiveSRG :: Options -> PGF -> CId -> SRG makeNonLeftRecursiveSRG :: Options -> PGF -> CId -> SRG
makeNonLeftRecursiveSRG opts = makeSRG opts' makeNonLeftRecursiveSRG opts = makeSRG opts'
where where
@@ -76,11 +76,11 @@ makeSRG opts = mkSRG cfgToSRG preprocess
where where
cfgToSRG cfg = [cfRulesToSRGRule rs | (_,rs) <- allRulesGrouped cfg] cfgToSRG cfg = [cfRulesToSRGRule rs | (_,rs) <- allRulesGrouped cfg]
preprocess = maybeTransform opts CFGMergeIdentical mergeIdentical preprocess = maybeTransform opts CFGMergeIdentical mergeIdentical
. maybeTransform opts CFGNoLR removeLeftRecursion . maybeTransform opts CFGNoLR removeLeftRecursion
. maybeTransform opts CFGRegular makeRegular . maybeTransform opts CFGRegular makeRegular
. maybeTransform opts CFGTopDownFilter topDownFilter . maybeTransform opts CFGTopDownFilter topDownFilter
. maybeTransform opts CFGBottomUpFilter bottomUpFilter . maybeTransform opts CFGBottomUpFilter bottomUpFilter
. maybeTransform opts CFGRemoveCycles removeCycles . maybeTransform opts CFGRemoveCycles removeCycles
. maybeTransform opts CFGStartCatOnly purgeExternalCats . maybeTransform opts CFGStartCatOnly purgeExternalCats
setDefaultCFGTransform :: Options -> CFGTransform -> Bool -> Options setDefaultCFGTransform :: Options -> CFGTransform -> Bool -> Options
@@ -95,7 +95,7 @@ stats g = "Categories: " ++ show (countCats g)
++ ", External categories: " ++ show (Set.size (cfgExternalCats g)) ++ ", External categories: " ++ show (Set.size (cfgExternalCats g))
++ ", Rules: " ++ show (countRules g) ++ ", Rules: " ++ show (countRules g)
-} -}
makeNonRecursiveSRG :: Options makeNonRecursiveSRG :: Options
-> PGF -> PGF
-> CId -- ^ Concrete syntax name. -> CId -- ^ Concrete syntax name.
-> SRG -> SRG
@@ -111,26 +111,26 @@ makeNonRecursiveSRG opts = mkSRG cfgToSRG id
mkSRG :: (CFG -> [SRGRule]) -> (CFG -> CFG) -> PGF -> CId -> SRG mkSRG :: (CFG -> [SRGRule]) -> (CFG -> CFG) -> PGF -> CId -> SRG
mkSRG mkRules preprocess pgf cnc = mkSRG mkRules preprocess pgf cnc =
SRG { srgName = showCId cnc, SRG { srgName = showCId cnc,
srgStartCat = cfgStartCat cfg, srgStartCat = cfgStartCat cfg,
srgExternalCats = cfgExternalCats cfg, srgExternalCats = cfgExternalCats cfg,
srgLanguage = languageCode pgf cnc, srgLanguage = languageCode pgf cnc,
srgRules = mkRules cfg } srgRules = mkRules cfg }
where cfg = renameCats (showCId cnc) $ preprocess $ pgfToCFG pgf cnc where cfg = renameCats (showCId cnc) $ preprocess $ pgfToCFG pgf cnc
-- | Renames all external cats C to C_cat, and all internal cats C_X (where X is any string), -- | Renames all external cats C to C_cat, and all internal cats C_X (where X is any string),
-- to C_N where N is an integer. -- to C_N where N is an integer.
renameCats :: String -> CFG -> CFG renameCats :: String -> CFG -> CFG
renameCats prefix cfg = mapCFGCats renameCat cfg renameCats prefix cfg = mapCFGCats renameCat cfg
where renameCat c | isExternal c = c ++ "_cat" where renameCat c | isExternal c = c ++ "_cat"
| otherwise = Map.findWithDefault (badCat c) c names | otherwise = Map.findWithDefault (badCat c) c names
isExternal c = c `Set.member` cfgExternalCats cfg isExternal c = c `Set.member` cfgExternalCats cfg
catsByPrefix = buildMultiMap [(takeWhile (/='_') cat, cat) | cat <- allCats' cfg, not (isExternal cat)] catsByPrefix = buildMultiMap [(takeWhile (/='_') cat, cat) | cat <- allCats' cfg, not (isExternal cat)]
names = Map.fromList [(c,pref++"_"++show i) | (pref,cs) <- catsByPrefix, (c,i) <- zip cs [1..]] names = Map.fromList [(c,pref++"_"++show i) | (pref,cs) <- catsByPrefix, (c,i) <- zip cs [1..]]
badCat c = error ("GF.Speech.SRG.renameCats: " ++ c ++ "\n" ++ prCFG cfg) badCat c = error ("GF.Speech.SRG.renameCats: " ++ c ++ "\n" ++ prCFG cfg)
cfRulesToSRGRule :: [CFRule] -> SRGRule cfRulesToSRGRule :: [CFRule] -> SRGRule
cfRulesToSRGRule rs@(r:_) = SRGRule (ruleLhs r) rhs cfRulesToSRGRule rs@(r:_) = SRGRule (ruleLhs r) rhs
where where
alts = [((n,Nothing),mkSRGSymbols 0 ss) | Rule c ss n <- rs] alts = [((n,Nothing),mkSRGSymbols 0 ss) | Rule c ss n <- rs]
rhs = [SRGAlt p n (srgItem sss) | ((n,p),sss) <- buildMultiMap alts ] rhs = [SRGAlt p n (srgItem sss) | ((n,p),sss) <- buildMultiMap alts ]
@@ -153,7 +153,7 @@ srgItem = unionRE . map mergeItems . sortGroupBy (compareBy filterCats)
-- non-optimizing version: -- non-optimizing version:
--srgItem = unionRE . map seqRE --srgItem = unionRE . map seqRE
-- | Merges a list of right-hand sides which all have the same -- | Merges a list of right-hand sides which all have the same
-- sequence of non-terminals. -- sequence of non-terminals.
mergeItems :: [[SRGSymbol]] -> SRGItem mergeItems :: [[SRGSymbol]] -> SRGItem
mergeItems = minimizeRE . ungroupTokens . minimizeRE . unionRE . map seqRE . map groupTokens mergeItems = minimizeRE . ungroupTokens . minimizeRE . unionRE . map seqRE . map groupTokens
@@ -174,16 +174,16 @@ ungroupTokens = joinRE . mapRE (symbol (RESymbol . NonTerminal) (REConcat . map
prSRG :: Options -> SRG -> String prSRG :: Options -> SRG -> String
prSRG opts srg = prProductions $ map prRule $ ext ++ int prSRG opts srg = prProductions $ map prRule $ ext ++ int
where where
sisr = flag optSISR opts sisr = flag optSISR opts
(ext,int) = partition (isExternalCat srg . srgLHSCat) (srgRules srg) (ext,int) = partition (isExternalCat srg . srgLHSCat) (srgRules srg)
prRule (SRGRule c alts) = (c,unwords (intersperse "|" (concatMap prAlt alts))) prRule (SRGRule c alts) = (c,unwords (intersperse "|" (concatMap prAlt alts)))
prAlt (SRGAlt _ t rhs) = prAlt (SRGAlt _ t rhs) =
-- FIXME: hack: we high-jack the --sisr flag to add -- FIXME: hack: we high-jack the --sisr flag to add
-- a simple lambda calculus format for semantic interpretation -- a simple lambda calculus format for semantic interpretation
-- Maybe the --sisr flag should be renamed. -- Maybe the --sisr flag should be renamed.
case sisr of case sisr of
Just _ -> Just _ ->
-- copy tags to each part of a top-level union, -- copy tags to each part of a top-level union,
-- to get simpler output -- to get simpler output
case rhs of case rhs of

View File

@@ -5,7 +5,7 @@
-- Stability : (stable) -- Stability : (stable)
-- Portability : (portable) -- Portability : (portable)
-- --
-- > CVS $Date: 2005/11/01 20:09:04 $ -- > CVS $Date: 2005/11/01 20:09:04 $
-- > CVS $Author: bringert $ -- > CVS $Author: bringert $
-- > CVS $Revision: 1.16 $ -- > CVS $Revision: 1.16 $
-- --
@@ -38,7 +38,7 @@ width :: Int
width = 75 width = 75
srgsAbnfPrinter :: Options srgsAbnfPrinter :: Options
-> PGF -> CId -> String -> PGF -> CId -> String
srgsAbnfPrinter opts pgf cnc = showDoc $ prABNF sisr $ makeNonLeftRecursiveSRG opts pgf cnc srgsAbnfPrinter opts pgf cnc = showDoc $ prABNF sisr $ makeNonLeftRecursiveSRG opts pgf cnc
where sisr = flag optSISR opts where sisr = flag optSISR opts
@@ -72,7 +72,7 @@ prItem :: Maybe SISRFormat -> CFTerm -> SRGItem -> Doc
prItem sisr t = f 0 prItem sisr t = f 0
where where
f _ (REUnion []) = pp "$VOID" f _ (REUnion []) = pp "$VOID"
f p (REUnion xs) f p (REUnion xs)
| not (null es) = brackets (f 0 (REUnion nes)) | not (null es) = brackets (f 0 (REUnion nes))
| otherwise = (if p >= 1 then parens else id) (alts (map (f 1) xs)) | otherwise = (if p >= 1 then parens else id) (alts (map (f 1) xs))
where (es,nes) = partition isEpsilon xs where (es,nes) = partition isEpsilon xs
@@ -84,13 +84,13 @@ prItem sisr t = f 0
prSymbol :: Maybe SISRFormat -> CFTerm -> SRGSymbol -> Doc prSymbol :: Maybe SISRFormat -> CFTerm -> SRGSymbol -> Doc
prSymbol sisr cn (NonTerminal n@(c,_)) = prCat c <+> tag sisr (catSISR cn n) prSymbol sisr cn (NonTerminal n@(c,_)) = prCat c <+> tag sisr (catSISR cn n)
prSymbol _ cn (Terminal t) prSymbol _ cn (Terminal t)
| all isPunct t = empty -- removes punctuation | all isPunct t = empty -- removes punctuation
| otherwise = pp t -- FIXME: quote if there is whitespace or odd chars | otherwise = pp t -- FIXME: quote if there is whitespace or odd chars
tag :: Maybe SISRFormat -> (SISRFormat -> SISRTag) -> Doc tag :: Maybe SISRFormat -> (SISRFormat -> SISRTag) -> Doc
tag Nothing _ = empty tag Nothing _ = empty
tag (Just fmt) t = tag (Just fmt) t =
case t fmt of case t fmt of
[] -> empty [] -> empty
-- grr, silly SRGS ABNF does not have an escaping mechanism -- grr, silly SRGS ABNF does not have an escaping mechanism
@@ -125,4 +125,3 @@ prepunctuate p (x:xs) = x : map (p <>) xs
($++$) :: Doc -> Doc -> Doc ($++$) :: Doc -> Doc -> Doc
x $++$ y = x $$ emptyLine $$ y x $++$ y = x $$ emptyLine $$ y

View File

@@ -34,13 +34,13 @@ prSrgsXml :: Maybe SISRFormat -> SRG -> String
prSrgsXml sisr srg = showXMLDoc (optimizeSRGS xmlGr) prSrgsXml sisr srg = showXMLDoc (optimizeSRGS xmlGr)
where where
xmlGr = grammar sisr (srgStartCat srg) (srgLanguage srg) $ xmlGr = grammar sisr (srgStartCat srg) (srgLanguage srg) $
[meta "description" [meta "description"
("SRGS XML speech recognition grammar for " ++ srgName srg ++ "."), ("SRGS XML speech recognition grammar for " ++ srgName srg ++ "."),
meta "generator" "Grammatical Framework"] meta "generator" "Grammatical Framework"]
++ map ruleToXML (srgRules srg) ++ map ruleToXML (srgRules srg)
ruleToXML (SRGRule cat alts) = Tag "rule" ([("id",cat)]++pub) (prRhs alts) ruleToXML (SRGRule cat alts) = Tag "rule" ([("id",cat)]++pub) (prRhs alts)
where pub = if isExternalCat srg cat then [("scope","public")] else [] where pub = if isExternalCat srg cat then [("scope","public")] else []
prRhs rhss = [oneOf (map (mkProd sisr) rhss)] prRhs rhss = [oneOf (map (mkProd sisr) rhss)]
mkProd :: Maybe SISRFormat -> SRGAlt -> XML mkProd :: Maybe SISRFormat -> SRGAlt -> XML
mkProd sisr (SRGAlt mp n rhs) = Tag "item" [] (ti ++ [x] ++ tf) mkProd sisr (SRGAlt mp n rhs) = Tag "item" [] (ti ++ [x] ++ tf)
@@ -50,9 +50,9 @@ mkProd sisr (SRGAlt mp n rhs) = Tag "item" [] (ti ++ [x] ++ tf)
mkItem :: Maybe SISRFormat -> CFTerm -> SRGItem -> XML mkItem :: Maybe SISRFormat -> CFTerm -> SRGItem -> XML
mkItem sisr cn = f mkItem sisr cn = f
where where
f (REUnion []) = ETag "ruleref" [("special","VOID")] f (REUnion []) = ETag "ruleref" [("special","VOID")]
f (REUnion xs) f (REUnion xs)
| not (null es) = Tag "item" [("repeat","0-1")] [f (REUnion nes)] | not (null es) = Tag "item" [("repeat","0-1")] [f (REUnion nes)]
| otherwise = oneOf (map f xs) | otherwise = oneOf (map f xs)
where (es,nes) = partition isEpsilon xs where (es,nes) = partition isEpsilon xs
@@ -62,7 +62,7 @@ mkItem sisr cn = f
f (RESymbol s) = symItem sisr cn s f (RESymbol s) = symItem sisr cn s
symItem :: Maybe SISRFormat -> CFTerm -> Symbol SRGNT Token -> XML symItem :: Maybe SISRFormat -> CFTerm -> Symbol SRGNT Token -> XML
symItem sisr cn (NonTerminal n@(c,_)) = symItem sisr cn (NonTerminal n@(c,_)) =
Tag "item" [] $ [ETag "ruleref" [("uri","#" ++ c)]] ++ tag sisr (catSISR cn n) Tag "item" [] $ [ETag "ruleref" [("uri","#" ++ c)]] ++ tag sisr (catSISR cn n)
symItem _ _ (Terminal t) = Tag "item" [] [Data (showToken t)] symItem _ _ (Terminal t) = Tag "item" [] [Data (showToken t)]
@@ -81,12 +81,12 @@ oneOf = Tag "one-of" []
grammar :: Maybe SISRFormat grammar :: Maybe SISRFormat
-> String -- ^ root -> String -- ^ root
-> Maybe String -- ^language -> Maybe String -- ^language
-> [XML] -> XML -> [XML] -> XML
grammar sisr root ml = grammar sisr root ml =
Tag "grammar" $ [("xmlns","http://www.w3.org/2001/06/grammar"), Tag "grammar" $ [("xmlns","http://www.w3.org/2001/06/grammar"),
("version","1.0"), ("version","1.0"),
("mode","voice"), ("mode","voice"),
("root",root)] ("root",root)]
++ (if isJust sisr then [("tag-format","semantics/1.0")] else []) ++ (if isJust sisr then [("tag-format","semantics/1.0")] else [])
++ maybe [] (\l -> [("xml:lang", l)]) ml ++ maybe [] (\l -> [("xml:lang", l)]) ml
@@ -94,7 +94,7 @@ meta :: String -> String -> XML
meta n c = ETag "meta" [("name",n),("content",c)] meta n c = ETag "meta" [("name",n),("content",c)]
optimizeSRGS :: XML -> XML optimizeSRGS :: XML -> XML
optimizeSRGS = bottomUpXML f optimizeSRGS = bottomUpXML f
where f (Tag "item" [] [x@(Tag "item" _ _)]) = x where f (Tag "item" [] [x@(Tag "item" _ _)]) = x
f (Tag "item" [] [x@(Tag "one-of" _ _)]) = x f (Tag "item" [] [x@(Tag "one-of" _ _)]) = x
f (Tag "item" as [Tag "item" [] xs]) = Tag "item" as xs f (Tag "item" as [Tag "item" [] xs]) = Tag "item" as xs

View File

@@ -17,7 +17,7 @@ import qualified Data.Map as Map
-- to add a new one: define the Unicode range and the corresponding ASCII strings, -- to add a new one: define the Unicode range and the corresponding ASCII strings,
-- which may be one or more characters long -- which may be one or more characters long
-- conventions to be followed: -- conventions to be followed:
-- each character is either [letter] or [letter+nonletters] -- each character is either [letter] or [letter+nonletters]
-- when using a sparse range of unicodes, mark missing codes as "-" in transliterations -- when using a sparse range of unicodes, mark missing codes as "-" in transliterations
-- characters can be invisible: ignored in translation to unicode -- characters can be invisible: ignored in translation to unicode
@@ -33,7 +33,7 @@ transliterateWithFile name src isFrom =
(if isFrom then appTransFromUnicode else appTransToUnicode) (getTransliterationFile name src) (if isFrom then appTransFromUnicode else appTransToUnicode) (getTransliterationFile name src)
transliteration :: String -> Maybe Transliteration transliteration :: String -> Maybe Transliteration
transliteration s = Map.lookup s allTransliterations transliteration s = Map.lookup s allTransliterations
allTransliterations = Map.fromList [ allTransliterations = Map.fromList [
("amharic",transAmharic), ("amharic",transAmharic),
@@ -67,25 +67,25 @@ data Transliteration = Trans {
} }
appTransToUnicode :: Transliteration -> String -> String appTransToUnicode :: Transliteration -> String -> String
appTransToUnicode trans = appTransToUnicode trans =
concat . concat .
map (\c -> maybe c (return . toEnum) $ map (\c -> maybe c (return . toEnum) $
Map.lookup c (trans_to_unicode trans) Map.lookup c (trans_to_unicode trans)
) . ) .
filter (flip notElem (invisible_chars trans)) . filter (flip notElem (invisible_chars trans)) .
unchar unchar
appTransFromUnicode :: Transliteration -> String -> String appTransFromUnicode :: Transliteration -> String -> String
appTransFromUnicode trans = appTransFromUnicode trans =
concat . concat .
map (\c -> maybe [toEnum c] id $ map (\c -> maybe [toEnum c] id $
Map.lookup c (trans_from_unicode trans) Map.lookup c (trans_from_unicode trans)
) . ) .
map fromEnum map fromEnum
mkTransliteration :: String -> [String] -> [Int] -> Transliteration mkTransliteration :: String -> [String] -> [Int] -> Transliteration
mkTransliteration name ts us = mkTransliteration name ts us =
Trans (Map.fromList (tzip ts us)) (Map.fromList (uzip us ts)) [] name Trans (Map.fromList (tzip ts us)) (Map.fromList (uzip us ts)) [] name
where where
tzip ts us = [(t,u) | (t,u) <- zip ts us, t /= "-"] tzip ts us = [(t,u) | (t,u) <- zip ts us, t /= "-"]
@@ -102,7 +102,7 @@ getTransliterationFile name = uncurry (mkTransliteration name) . codes
unchar :: String -> [String] unchar :: String -> [String]
unchar s = case s of unchar s = case s of
c:d:cs c:d:cs
| isAlpha d -> [c] : unchar (d:cs) | isAlpha d -> [c] : unchar (d:cs)
| isSpace d -> [c]:[d]: unchar cs | isSpace d -> [c]:[d]: unchar cs
| otherwise -> let (ds,cs2) = break (\x -> isAlpha x || isSpace x) cs in | otherwise -> let (ds,cs2) = break (\x -> isAlpha x || isSpace x) cs in
@@ -122,8 +122,8 @@ transThai = mkTransliteration "Thai" allTrans allCodes where
allCodes = [0x0e00 .. 0x0e7f] allCodes = [0x0e00 .. 0x0e7f]
transDevanagari :: Transliteration transDevanagari :: Transliteration
transDevanagari = transDevanagari =
(mkTransliteration "Devanagari" (mkTransliteration "Devanagari"
allTransUrduHindi allCodes){invisible_chars = ["a"]} where allTransUrduHindi allCodes){invisible_chars = ["a"]} where
allCodes = [0x0900 .. 0x095f] ++ [0x0966 .. 0x096f] allCodes = [0x0900 .. 0x095f] ++ [0x0966 .. 0x096f]
@@ -136,13 +136,13 @@ allTransUrduHindi = words $
"- - - - - - - - q x g. z R R' f - " ++ "- - - - - - - - q x g. z R R' f - " ++
"N0 N1 N2 N3 N4 N5 N6 N7 N8 N9 " "N0 N1 N2 N3 N4 N5 N6 N7 N8 N9 "
transUrdu :: Transliteration transUrdu :: Transliteration
transUrdu = transUrdu =
(mkTransliteration "Urdu" allTrans allCodes) where (mkTransliteration "Urdu" allTrans allCodes) where
allCodes = [0x0622 .. 0x062f] ++ [0x0630 .. 0x063a] ++ [0x0641,0x0642] ++ [0x06A9] ++ [0x0644 .. 0x0648] ++ allCodes = [0x0622 .. 0x062f] ++ [0x0630 .. 0x063a] ++ [0x0641,0x0642] ++ [0x06A9] ++ [0x0644 .. 0x0648] ++
[0x0654,0x0658,0x0679,0x067e,0x0686,0x0688,0x0691,0x0698,0x06af,0x06c1,0x06c3,0x06cc,0x06ba,0x06be,0x06d2] ++ [0x0654,0x0658,0x0679,0x067e,0x0686,0x0688,0x0691,0x0698,0x06af,0x06c1,0x06c3,0x06cc,0x06ba,0x06be,0x06d2] ++
[0x06f0 .. 0x06f9] ++ [0x061f,0x06D4] [0x06f0 .. 0x06f9] ++ [0x061f,0x06D4]
allTrans = words $ allTrans = words $
"A - w^ - y^ a b - t C j H K d " ++ -- 0622 - 062f "A - w^ - y^ a b - t C j H K d " ++ -- 0622 - 062f
"Z r z s X S Z- t- z- e G " ++ -- 0630 - 063a "Z r z s X S Z- t- z- e G " ++ -- 0630 - 063a
@@ -151,22 +151,22 @@ transUrdu =
"N0 N1 N2 N3 N4 N5 N6 N7 N8 N9 " ++ "? ." "N0 N1 N2 N3 N4 N5 N6 N7 N8 N9 " ++ "? ."
transSindhi :: Transliteration transSindhi :: Transliteration
transSindhi = transSindhi =
(mkTransliteration "Sindhi" allTrans allCodes) where (mkTransliteration "Sindhi" allTrans allCodes) where
allCodes = [0x062e] ++ [0x0627 .. 0x062f] ++ [0x0630 .. 0x063a] ++ [0x0641 .. 0x0648] ++ allCodes = [0x062e] ++ [0x0627 .. 0x062f] ++ [0x0630 .. 0x063a] ++ [0x0641 .. 0x0648] ++
[0x067a,0x067b,0x067d,0x067e,0x067f] ++ [0x0680 .. 0x068f] ++ [0x067a,0x067b,0x067d,0x067e,0x067f] ++ [0x0680 .. 0x068f] ++
[0x0699,0x0918,0x06a6,0x061d,0x06a9,0x06af,0x06b3,0x06bb,0x06be,0x06f6,0x064a,0x06b1, 0x06aa, 0x06fd, 0x06fe] ++ [0x0699,0x0918,0x06a6,0x061d,0x06a9,0x06af,0x06b3,0x06bb,0x06be,0x06f6,0x064a,0x06b1, 0x06aa, 0x06fd, 0x06fe] ++
[0x06f0 .. 0x06f9] ++ [0x061f,0x06D4] [0x06f0 .. 0x06f9] ++ [0x061f,0x06D4]
allTrans = words $ allTrans = words $
"K a b - t C j H - d " ++ -- 0626 - 062f "K a b - t C j H - d " ++ -- 0626 - 062f
"Z r z s X S Z- t- z- e G " ++ -- 0630 - 063a "Z r z s X S Z- t- z- e G " ++ -- 0630 - 063a
"f q - L m n - W " ++ -- 0641 - 0648 "f q - L m n - W " ++ -- 0641 - 0648
"T! B T p T' " ++ -- 067a,067b,067d,067e,067f "T! B T p T' " ++ -- 067a,067b,067d,067e,067f
"B' - - Y' J' - c c' - - d! - d' D - D' " ++ -- 0680 - 068f "B' - - Y' J' - c c' - - d! - d' D - D' " ++ -- 0680 - 068f
"R - F' - k' g G' t' h' e' y c! k A M " ++ -- 0699, 0918, 06a6, 061d, 06a9,06af,06b3,06bb,06be,06f6,06cc,06b1 "R - F' - k' g G' t' h' e' y c! k A M " ++ -- 0699, 0918, 06a6, 061d, 06a9,06af,06b3,06bb,06be,06f6,06cc,06b1
"N0 N1 N2 N3 N4 N5 N6 N7 N8 N9 " ++ "? ." "N0 N1 N2 N3 N4 N5 N6 N7 N8 N9 " ++ "? ."
transArabic :: Transliteration transArabic :: Transliteration
transArabic = mkTransliteration "Arabic" allTrans allCodes where transArabic = mkTransliteration "Arabic" allTrans allCodes where
@@ -175,8 +175,8 @@ transArabic = mkTransliteration "Arabic" allTrans allCodes where
"W r z s C S D T Z c G " ++ -- 0630 - 063a "W r z s C S D T Z c G " ++ -- 0630 - 063a
" f q k l m n h w y. y a. u. i. a u " ++ -- 0641 - 064f " f q k l m n h w y. y a. u. i. a u " ++ -- 0641 - 064f
"i v2 o a: V+ V- i: a+ " ++ -- 0650 - 0657 "i v2 o a: V+ V- i: a+ " ++ -- 0650 - 0657
"A* q?" -- 0671 (used by AED) "A* q?" -- 0671 (used by AED)
allCodes = [0x0621..0x062f] ++ [0x0630..0x063a] ++ allCodes = [0x0621..0x062f] ++ [0x0630..0x063a] ++
[0x0641..0x064f] ++ [0x0650..0x0657] ++ [0x0671,0x061f] [0x0641..0x064f] ++ [0x0650..0x0657] ++ [0x0671,0x061f]
@@ -193,16 +193,16 @@ transPersian = (mkTransliteration "Persian/Farsi" allTrans allCodes)
" V A: A? w? A- y? A b t. t t- j H K d " ++ -- 0621 - 062f " V A: A? w? A- y? A b t. t t- j H K d " ++ -- 0621 - 062f
"W r z s C S D T Z c G " ++ -- 0630 - 063a "W r z s C S D T Z c G " ++ -- 0630 - 063a
" f q - l m n h v - y. a. u. i. a u " ++ -- 0640 - 064f " f q - l m n h v - y. a. u. i. a u " ++ -- 0640 - 064f
"i v2 o a: V+ V- i: a+ " ++ -- 0650 - 0657 "i v2 o a: V+ V- i: a+ " ++ -- 0650 - 0657
"p c^ J k g y q? Z0" "p c^ J k g y q? Z0"
allCodes = [0x0621..0x062f] ++ [0x0630..0x063a] ++ allCodes = [0x0621..0x062f] ++ [0x0630..0x063a] ++
[0x0641..0x064f] ++ [0x0650..0x0657] ++ [0x0641..0x064f] ++ [0x0650..0x0657] ++
[0x067e,0x0686,0x0698,0x06a9,0x06af,0x06cc,0x061f,0x200c] [0x067e,0x0686,0x0698,0x06a9,0x06af,0x06cc,0x061f,0x200c]
transNepali :: Transliteration transNepali :: Transliteration
transNepali = mkTransliteration "Nepali" allTrans allCodes where transNepali = mkTransliteration "Nepali" allTrans allCodes where
allTrans = words $ allTrans = words $
"z+ z= " ++ "z+ z= " ++
"- V M h: - H A i: I: f F Z - - - e: " ++ "- V M h: - H A i: I: f F Z - - - e: " ++
"E: - - O W k K g G n: C c j J Y q " ++ "E: - - O W k K g G n: C c j J Y q " ++
"Q x X N t T d D n - p P b B m y " ++ "Q x X N t T d D n - p P b B m y " ++
@@ -241,7 +241,7 @@ transGreek = mkTransliteration "modern Greek" allTrans allCodes where
"i= A B G D E Z H V I K L M N X O " ++ "i= A B G D E Z H V I K L M N X O " ++
"P R - S T Y F C Q W I- Y- a' e' h' i' " ++ "P R - S T Y F C Q W I- Y- a' e' h' i' " ++
"y= a b g d e z h v i k l m n x o " ++ "y= a b g d e z h v i k l m n x o " ++
"p r s* s t y f c q w i- y- o' y' w' - " "p r s* s t y f c q w i- y- o' y' w' - "
allCodes = [0x0380 .. 0x03cf] allCodes = [0x0380 .. 0x03cf]
transAncientGreek :: Transliteration transAncientGreek :: Transliteration
@@ -261,32 +261,32 @@ transAncientGreek = mkTransliteration "ancient Greek" allTrans allCodes where
"y) y( y)` y(` y)' y(' y)~ y(~ - Y( - Y(` - Y(' - Y(~ " ++ "y) y( y)` y(` y)' y(' y)~ y(~ - Y( - Y(` - Y(' - Y(~ " ++
"w) w( w)` w(` w)' w(' w)~ w(~ W) W( W)` W(` W)' W(' W)~ W(~ " ++ "w) w( w)` w(` w)' w(' w)~ w(~ W) W( W)` W(` W)' W(' W)~ W(~ " ++
"a` a' e` e' h` h' i` i' o` o' y` y' w` w' - - " ++ "a` a' e` e' h` h' i` i' o` o' y` y' w` w' - - " ++
"a|) a|( a|)` a|(` a|)' a|(' a|)~ a|(~ - - - - - - - - " ++ -- 1f80- "a|) a|( a|)` a|(` a|)' a|(' a|)~ a|(~ - - - - - - - - " ++ -- 1f80-
"h|) h|( h|)` h|(` h|)' h|(' h|)~ h|(~ - - - - - - - - " ++ -- 1f90- "h|) h|( h|)` h|(` h|)' h|(' h|)~ h|(~ - - - - - - - - " ++ -- 1f90-
"w|) w|( w|)` w|(` w|)' w|(' w|)~ w|(~ - - - - - - - - " ++ -- 1fa0- "w|) w|( w|)` w|(` w|)' w|(' w|)~ w|(~ - - - - - - - - " ++ -- 1fa0-
"a. a_ a|` a| a|' - a~ a|~ - - - - - - - - " ++ -- 1fb0- "a. a_ a|` a| a|' - a~ a|~ - - - - - - - - " ++ -- 1fb0-
"- - h|` h| h|' - h~ h|~ - - - - - - - - " ++ -- 1fc0- "- - h|` h| h|' - h~ h|~ - - - - - - - - " ++ -- 1fc0-
"i. i_ i=` i=' - - i~ i=~ - - - - - - - - " ++ -- 1fd0- "i. i_ i=` i=' - - i~ i=~ - - - - - - - - " ++ -- 1fd0-
"y. y_ y=` y=' r) r( y~ y=~ - - - - - - - - " ++ -- 1fe0- "y. y_ y=` y=' r) r( y~ y=~ - - - - - - - - " ++ -- 1fe0-
"- - w|` w| w|' - w~ w|~ - - - - - - - - " ++ -- 1ff0- "- - w|` w| w|' - w~ w|~ - - - - - - - - " ++ -- 1ff0-
-- HL, Private Use Area Code Points (New Athena Unicode, Cardo, ALPHABETUM, Antioch) -- HL, Private Use Area Code Points (New Athena Unicode, Cardo, ALPHABETUM, Antioch)
-- see: http://apagreekkeys.org/technicalDetails.html -- see: http://apagreekkeys.org/technicalDetails.html
-- GreekKeys Support by Donald Mastronarde -- GreekKeys Support by Donald Mastronarde
"- - - - - - - - - e. o. R) Y) Y)` Y)' Y)~ " ++ -- e1a0-e1af "- - - - - - - - - e. o. R) Y) Y)` Y)' Y)~ " ++ -- e1a0-e1af
"e~ e)~ e(~ e_ e_' e_` e_) e_( e_)` e_(` e_)' e_(' E)~ E(~ E_ E. " ++ -- e1b0-e1bf "e~ e)~ e(~ e_ e_' e_` e_) e_( e_)` e_(` e_)' e_(' E)~ E(~ E_ E. " ++ -- e1b0-e1bf
"o~ o)~ o(~ o_ o_' o_` o_) o_( o_)` o_(` o_)' o_(' O)~ O(~ O_ O. " ++ -- e1c0-e1cf "o~ o)~ o(~ o_ o_' o_` o_) o_( o_)` o_(` o_)' o_(' O)~ O(~ O_ O. " ++ -- e1c0-e1cf
"a_` - a_~ a_)` a_(` a_)~ a_(~ - a.` a.) a.)` a.(' a.(` - - - " ++ -- eaf0-eaff "a_` - a_~ a_)` a_(` a_)~ a_(~ - a.` a.) a.)` a.(' a.(` - - - " ++ -- eaf0-eaff
"a_' - - - a_) a_( - a_)' - a_(' a.' a.( a.)' - - - " ++ -- eb00-eb0f "a_' - - - a_) a_( - a_)' - a_(' a.' a.( a.)' - - - " ++ -- eb00-eb0f
"e_)~ e_(~ - - - - - e_~ - - - - - - - - " ++ -- eb20-eb2f "e_)~ e_(~ - - - - - e_~ - - - - - - - - " ++ -- eb20-eb2f
"- - - - - - i_~ - i_` i_' - - i_) i_)' i_( i_(' " ++ -- eb30-eb3f "- - - - - - i_~ - i_` i_' - - i_) i_)' i_( i_(' " ++ -- eb30-eb3f
"i.' i.) i.)' i.( i.` i.)` - i.(' i.(` - - - - - - - " ++ -- eb40-eb4f "i.' i.) i.)' i.( i.` i.)` - i.(' i.(` - - - - - - - " ++ -- eb40-eb4f
"- - - - i_)` i_(` - i_)~ i_(~ - o_~ o_)~ o_(~ - - - " ++ -- eb50-eb5f "- - - - i_)` i_(` - i_)~ i_(~ - o_~ o_)~ o_(~ - - - " ++ -- eb50-eb5f
"y_` " ++ -- eb6f "y_` " ++ -- eb6f
"y_~ y_)` - - - y_(` - y_)~ y_(~ - y_' - - y_) y_( y_)' " ++ -- eb70-eb7f "y_~ y_)` - - - y_(` - y_)~ y_(~ - y_' - - y_) y_( y_)' " ++ -- eb70-eb7f
"y_(' y.' y.( y.` y.) y.)' - - y.)` y.(' y.(` - - - - - " -- eb80-eb8f "y_(' y.' y.( y.` y.) y.)' - - y.)` y.(' y.(` - - - - - " -- eb80-eb8f
allCodes = -- [0x00B0 .. 0x00Bf] allCodes = -- [0x00B0 .. 0x00Bf]
[0x0380 .. 0x03cf] ++ [0x1f00 .. 0x1fff] [0x0380 .. 0x03cf] ++ [0x1f00 .. 0x1fff]
++ [0xe1a0 .. 0xe1af] ++ [0xe1a0 .. 0xe1af]
++ [0xe1b0 .. 0xe1bf] ++ [0xe1b0 .. 0xe1bf]
++ [0xe1c0 .. 0xe1cf] ++ [0xe1c0 .. 0xe1cf]
++ [0xeaf0 .. 0xeaff] ++ [0xeaf0 .. 0xeaff]
@@ -297,36 +297,34 @@ transAncientGreek = mkTransliteration "ancient Greek" allTrans allCodes where
++ [0xeb50 .. 0xeb5f] ++ [0xeb6f] ++ [0xeb50 .. 0xeb5f] ++ [0xeb6f]
++ [0xeb70 .. 0xeb7f] ++ [0xeb70 .. 0xeb7f]
++ [0xeb80 .. 0xeb8f] ++ [0xeb80 .. 0xeb8f]
transAmharic :: Transliteration transAmharic :: Transliteration
transAmharic = mkTransliteration "Amharic" allTrans allCodes where transAmharic = mkTransliteration "Amharic" allTrans allCodes where
allTrans = words $
allTrans = words $ " h. h- h' h( h) h h? h* l. l- l' l( l) l l? l* "++
" H. H- H' H( H) H H? H* m. m- m' m( m) m m? m* "++
" h. h- h' h( h) h h? h* l. l- l' l( l) l l? l* "++ " s. s- s' s( s) s s? s* r. r- r' r( r) r r? r* "++
" H. H- H' H( H) H H? H* m. m- m' m( m) m m? m* "++ " - - - - - - - - x. x- x' x( x) x x? x* "++
" s. s- s' s( s) s s? s* r. r- r' r( r) r r? r* "++ " q. q- q' q( q) q q? q* - - - - - - - - "++
" - - - - - - - - x. x- x' x( x) x x? x* "++ " - - - - - - - - - - - - - - - - "++
" q. q- q' q( q) q q? q* - - - - - - - - "++ " b. b- b' b( b) b b? b* v. v- v' v( v) v v? v* "++
" - - - - - - - - - - - - - - - - "++ " t. t- t' t( t) t t? t* c. c- c' c( c) c c? c* "++
" b. b- b' b( b) b b? b* v. v- v' v( v) v v? v* "++ " X. X- X' X( X) X X? - - - - X* - - - - "++
" t. t- t' t( t) t t? t* c. c- c' c( c) c c? c* "++ " n. n- n' n( n) n n? n* N. N- N' N( N) N N? N* "++
" X. X- X' X( X) X X? - - - - X* - - - - "++ " a u i A E e o e* k. k- k' k( k) k k? - "++
" n. n- n' n( n) n n? n* N. N- N' N( N) N N? N* "++ " - - - k* - - - - - - - - - - - - "++
" a u i A E e o e* k. k- k' k( k) k k? - "++ " - - - - - - - - w. w- w' w( w) w w? w* "++
" - - - k* - - - - - - - - - - - - "++ " - - - - - - - - z. z- z' z( z) z z? z* "++
" - - - - - - - - w. w- w' w( w) w w? w* "++ " Z. Z- Z' Z( Z) Z Z? Z* y. y- y' y( y) y y? y* "++
" - - - - - - - - z. z- z' z( z) z z? z* "++ " d. d- d' d( d) d d? d* - - - - - - - - "++
" Z. Z- Z' Z( Z) Z Z? Z* y. y- y' y( y) y y? y* "++ " j. j- j' j( j) j j? j* g. g- g' g( g) g g? - "++
" d. d- d' d( d) d d? d* - - - - - - - - "++ " - - - g* - - - - - - - - - - - - "++
" j. j- j' j( j) j j? j* g. g- g' g( g) g g? - "++ " T. T- T' T( T) T T? T* C. C- C' C( C) C C? C* "++
" - - - g* - - - - - - - - - - - - "++ " P. P- P' P( P) P P? P* S. S- S' S( S) S S? S* "++
" T. T- T' T( T) T T? T* C. C- C' C( C) C C? C* "++ " - - - - - - - - f. f- f' f( f) f f? f*"++
" P. P- P' P( P) P P? P* S. S- S' S( S) S S? S* "++ " p. p- p' p( p) p p? p*"
" - - - - - - - - f. f- f' f( f) f f? f*"++ allCodes = [0x1200..0x1357]
" p. p- p' p( p) p p? p*"
allCodes = [0x1200..0x1357]
-- by Prasad 31/5/2013 -- by Prasad 31/5/2013
transSanskrit :: Transliteration transSanskrit :: Transliteration
transSanskrit = (mkTransliteration "Sanskrit" allTrans allCodes) {invisible_chars = ["a"]} where transSanskrit = (mkTransliteration "Sanskrit" allTrans allCodes) {invisible_chars = ["a"]} where

View File

@@ -23,10 +23,10 @@ data Fun = Fun { fname:: FunId, ftype:: Type }
data Concrete = Concrete { langcode:: Id, data Concrete = Concrete { langcode:: Id,
opens:: [ModId], opens:: [ModId],
params:: [Param], params:: [Param],
lincats:: [Lincat], lincats:: [Lincat],
opers:: [Oper], opers:: [Oper],
lins:: [Lin] } lins:: [Lin] }
deriving Show deriving Show
data Param = Param {pname:: Id, prhs:: String} deriving Show data Param = Param {pname:: Id, prhs:: String} deriving Show

View File

@@ -14,6 +14,9 @@ For Linux users
You will need the packages: autoconf, automake, libtool, make You will need the packages: autoconf, automake, libtool, make
- On Ubuntu: $ apt-get install autotools-dev
- On Fedora: $ dnf install autoconf automake libtool
The compilation steps are: The compilation steps are:
$ autoreconf -i $ autoreconf -i
@@ -28,7 +31,7 @@ For Mac OSX users
The following is what I did to make it work on MacOSX 10.8: The following is what I did to make it work on MacOSX 10.8:
- Install XCode and XCode command line tools - Install XCode and XCode command line tools
- Install Homebrew: http://mxcl.github.com/homebrew/ - Install Homebrew: https://brew.sh
$ brew install automake autoconf libtool $ brew install automake autoconf libtool
$ glibtoolize $ glibtoolize
@@ -49,7 +52,7 @@ For Windows users
After the installation, don't forget to fix the fstab file. See here: After the installation, don't forget to fix the fstab file. See here:
http://www.mingw.org/wiki/Getting_Started http://www.mingw.org/wiki/Getting_Started
- From the MSYS shell (c:/MinGW/msys/1.0/msys.bat) go to the directory - From the MSYS shell (c:/MinGW/msys/1.0/msys.bat) go to the directory
which contains the INSTALL file and do: which contains the INSTALL file and do:
$ autoreconf -i $ autoreconf -i

3
src/runtime/c/install.sh Executable file
View File

@@ -0,0 +1,3 @@
bash setup.sh configure
bash setup.sh build
bash setup.sh install

View File

@@ -19,7 +19,7 @@ wildCId = "_" :: CId
type Cat = CId -- ^ Name of syntactic category type Cat = CId -- ^ Name of syntactic category
type Fun = CId -- ^ Name of function type Fun = CId -- ^ Name of function
data BindType = data BindType =
Explicit Explicit
| Implicit | Implicit
deriving Show deriving Show
@@ -38,7 +38,7 @@ instance Show Expr where
show = showExpr [] show = showExpr []
instance Eq Expr where instance Eq Expr where
(Expr e1 e1_touch) == (Expr e2 e2_touch) = (Expr e1 e1_touch) == (Expr e2 e2_touch) =
unsafePerformIO $ do unsafePerformIO $ do
res <- pgf_expr_eq e1 e2 res <- pgf_expr_eq e1 e2
e1_touch >> e2_touch e1_touch >> e2_touch
@@ -113,9 +113,9 @@ unApp (Expr expr touch) =
appl <- pgf_expr_unapply expr pl appl <- pgf_expr_unapply expr pl
if appl == nullPtr if appl == nullPtr
then return Nothing then return Nothing
else do else do
fun <- peekCString =<< (#peek PgfApplication, fun) appl fun <- peekCString =<< (#peek PgfApplication, fun) appl
arity <- (#peek PgfApplication, n_args) appl :: IO CInt arity <- (#peek PgfApplication, n_args) appl :: IO CInt
c_args <- peekArray (fromIntegral arity) (appl `plusPtr` (#offset PgfApplication, args)) c_args <- peekArray (fromIntegral arity) (appl `plusPtr` (#offset PgfApplication, args))
return $ Just (fun, [Expr c_arg touch | c_arg <- c_args]) return $ Just (fun, [Expr c_arg touch | c_arg <- c_args])
@@ -140,7 +140,9 @@ unStr (Expr expr touch) =
touch touch
return (Just s) return (Just s)
-- | Constructs an expression from an integer literal -- | Constructs an expression from an integer literal.
-- Note that the C runtime does not support long integers, and you may run into overflow issues with large values.
-- See [here](https://github.com/GrammaticalFramework/gf-core/issues/109) for more details.
mkInt :: Int -> Expr mkInt :: Int -> Expr
mkInt val = mkInt val =
unsafePerformIO $ do unsafePerformIO $ do
@@ -267,7 +269,7 @@ foreign import ccall "wrapper"
-- in the expression in order reverse to the order -- in the expression in order reverse to the order
-- of binding. -- of binding.
showExpr :: [CId] -> Expr -> String showExpr :: [CId] -> Expr -> String
showExpr scope e = showExpr scope e =
unsafePerformIO $ unsafePerformIO $
withGuPool $ \tmpPl -> withGuPool $ \tmpPl ->
do (sb,out) <- newOut tmpPl do (sb,out) <- newOut tmpPl

View File

@@ -1,18 +1,21 @@
name: pgf2 name: pgf2
version: 1.3.0 version: 1.3.0
cabal-version: 1.22
build-type: Simple
license: LGPL-3
license-file: LICENSE
category: Natural Language Processing
synopsis: Bindings to the C version of the PGF runtime synopsis: Bindings to the C version of the PGF runtime
description: description:
GF, Grammatical Framework, is a programming language for multilingual grammar applications. GF, Grammatical Framework, is a programming language for multilingual grammar applications.
GF grammars are compiled into Portable Grammar Format (PGF) which can be used with the PGF runtime, written in C. GF grammars are compiled into Portable Grammar Format (PGF) which can be used with the PGF runtime, written in C.
This package provides Haskell bindings to that runtime. This package provides Haskell bindings to that runtime.
homepage: https://www.grammaticalframework.org homepage: https://www.grammaticalframework.org/
license: LGPL-3 bug-reports: https://github.com/GrammaticalFramework/gf-core/issues
license-file: LICENSE
author: Krasimir Angelov author: Krasimir Angelov
category: Natural Language Processing
build-type: Simple
extra-source-files: CHANGELOG.md, README.md extra-source-files: CHANGELOG.md, README.md
cabal-version: >=1.10 tested-with: GHC==7.10.3, GHC==8.0.2, GHC==8.10.4
library library
exposed-modules: exposed-modules:
@@ -23,9 +26,9 @@ library
PGF2.Expr, PGF2.Expr,
PGF2.Type PGF2.Type
build-depends: build-depends:
base >=4.3 && <5, base >= 4.9.1 && < 4.15,
containers, containers >= 0.5.7 && < 0.7,
pretty pretty >= 1.1.3 && < 1.2
default-language: Haskell2010 default-language: Haskell2010
build-tools: hsc2hs build-tools: hsc2hs
extra-libraries: pgf gu extra-libraries: pgf gu

View File

@@ -0,0 +1,3 @@
resolver: lts-6.35 # ghc 7.10.3
allow-newer: true

View File

@@ -0,0 +1 @@
resolver: lts-9.21 # ghc 8.0.2

View File

@@ -0,0 +1 @@
resolver: lts-18.0 # ghc 8.10.4

View File

@@ -28,7 +28,7 @@ instance Binary PGF where
let v = (major,minor) let v = (major,minor)
if major==pgfMajorVersion && minor<=pgfMinorVersion if major==pgfMajorVersion && minor<=pgfMinorVersion
then getPGF' then getPGF'
else if v==Old.version else if v==Old.version
then Old.getPGF' then Old.getPGF'
else fail $ "Unsupported PGF version "++show (major,minor) else fail $ "Unsupported PGF version "++show (major,minor)
@@ -185,6 +185,7 @@ instance Binary Instr where
put (PUSH_ACCUM (LFlt d)) = putWord8 78 >> put d put (PUSH_ACCUM (LFlt d)) = putWord8 78 >> put d
put (POP_ACCUM ) = putWord8 80 put (POP_ACCUM ) = putWord8 80
put (ADD ) = putWord8 84 put (ADD ) = putWord8 84
get = fail "Missing implementation for get in the instance declaration for Binary Instr"
instance Binary Type where instance Binary Type where
put (DTyp hypos cat exps) = put (hypos,cat,exps) put (DTyp hypos cat exps) = put (hypos,cat,exps)

View File

@@ -1,29 +1,32 @@
name: pgf name: pgf
version: 3.10.1-git version: 3.11.0-git
cabal-version: >= 1.20 cabal-version: 1.22
build-type: Simple build-type: Simple
license: OtherLicense license: OtherLicense
category: Natural Language Processing category: Natural Language Processing
synopsis: Grammatical Framework synopsis: Grammatical Framework
description: A library for interpreting the Portable Grammar Format (PGF) description: A library for interpreting the Portable Grammar Format (PGF)
homepage: http://www.grammaticalframework.org/ homepage: https://www.grammaticalframework.org/
bug-reports: https://github.com/GrammaticalFramework/gf-core/issues bug-reports: https://github.com/GrammaticalFramework/gf-core/issues
tested-with: GHC==7.6.3, GHC==7.8.3, GHC==7.10.3, GHC==8.0.2, GHC==8.4.4 tested-with: GHC==7.10.3, GHC==8.0.2, GHC==8.10.4
library library
default-language: Haskell2010 default-language: Haskell2010
build-depends: build-depends:
array, array >= 0.5.1 && < 0.6,
base >= 4.6 && <5, base >= 4.9.1 && < 4.15,
bytestring, bytestring >= 0.10.8 && < 0.11,
containers, containers >= 0.5.7 && < 0.7,
-- exceptions, ghc-prim >= 0.5.0 && < 0.7,
ghc-prim, mtl >= 2.2.1 && < 2.3,
mtl, pretty >= 1.1.3 && < 1.2,
pretty, random >= 1.1 && < 1.3,
random, utf8-string >= 1.0.1.1 && < 1.1
utf8-string
if impl(ghc<8.0)
build-depends:
fail >= 4.9.0 && < 4.10
other-modules: other-modules:
-- not really part of GF but I have changed the original binary library -- not really part of GF but I have changed the original binary library

View File

@@ -0,0 +1,3 @@
resolver: lts-6.35 # ghc 7.10.3
allow-newer: true

View File

@@ -0,0 +1 @@
resolver: lts-9.21 # ghc 8.0.2

View File

@@ -0,0 +1 @@
resolver: lts-18.0 # ghc 8.10.4

View File

@@ -6,9 +6,9 @@ import Data.Char (chr,digitToInt,isHexDigit)
-- | Decode hexadecimal escapes -- | Decode hexadecimal escapes
urlDecodeUnicode :: String -> String urlDecodeUnicode :: String -> String
urlDecodeUnicode [] = "" urlDecodeUnicode [] = ""
urlDecodeUnicode ('%':'u':x1:x2:x3:x4:s) urlDecodeUnicode ('%':'u':x1:x2:x3:x4:s)
| all isHexDigit [x1,x2,x3,x4] = | all isHexDigit [x1,x2,x3,x4] =
chr ( digitToInt x1 `shiftL` 12 chr ( digitToInt x1 `shiftL` 12
.|. digitToInt x2 `shiftL` 8 .|. digitToInt x2 `shiftL` 8
.|. digitToInt x3 `shiftL` 4 .|. digitToInt x3 `shiftL` 4
.|. digitToInt x4) : urlDecodeUnicode s .|. digitToInt x4) : urlDecodeUnicode s
@@ -45,8 +45,8 @@ fromhex2 d1 d2 = 16*digitToInt d1+digitToInt d2
-- Repeatedly extract (and transform) values until a predicate hold. Return the list of values. -- Repeatedly extract (and transform) values until a predicate hold. Return the list of values.
unfoldr :: (a -> (b, a)) -> (a -> Bool) -> a -> [b] unfoldr :: (a -> (b, a)) -> (a -> Bool) -> a -> [b]
unfoldr f p x | p x = [] unfoldr f p x | p x = []
| otherwise = y:unfoldr f p x' | otherwise = y:unfoldr f p x'
where (y, x') = f x where (y, x') = f x
chopList :: ([a] -> (b, [a])) -> [a] -> [b] chopList :: ([a] -> (b, [a])) -> [a] -> [b]
chopList f l = unfoldr f null l chopList f l = unfoldr f null l
@@ -54,8 +54,8 @@ chopList f l = unfoldr f null l
breakAt :: (Eq a) => a -> [a] -> ([a], [a]) breakAt :: (Eq a) => a -> [a] -> ([a], [a])
breakAt _ [] = ([], []) breakAt _ [] = ([], [])
breakAt x (x':xs) = breakAt x (x':xs) =
if x == x' then if x == x' then
([], xs) ([], xs)
else else
let (ys, zs) = breakAt x xs let (ys, zs) = breakAt x xs
in (x':ys, zs) in (x':ys, zs)

View File

@@ -13,14 +13,14 @@ fold t =
case unApp t of case unApp t of
Just (i,[x]) -> Just (i,[x]) ->
case M.lookup i foldable of case M.lookup i foldable of
Just j -> appFold j x Just j -> appFold j x
_ -> mkApp i [fold x] _ -> mkApp i [fold x]
Just (i,xs) -> mkApp i $ map fold xs Just (i,xs) -> mkApp i $ map fold xs
_ -> t _ -> t
appFold :: CId -> Tree -> Tree appFold :: CId -> Tree -> Tree
appFold j t = appFold j t =
case unApp t of case unApp t of
Just (i,[t,ts]) | isPre i "Cons" -> mkApp j [fold t, appFold j ts] Just (i,[t,ts]) | isPre i "Cons" -> mkApp j [fold t, appFold j ts]
Just (i,[t,s]) | isPre i "Base" -> mkApp j [fold t, fold s] Just (i,[t,s]) | isPre i "Base" -> mkApp j [fold t, fold s]
where isPre i s = take 4 (show i) == s where isPre i s = take 4 (show i) == s

14
stack-ghc8.10.4.yaml Normal file
View File

@@ -0,0 +1,14 @@
resolver: lts-18.0 # ghc 8.10.4
extra-deps:
- network-2.6.3.6
- httpd-shed-0.4.0.3
- cgi-3001.5.0.0@sha256:3d1193a328d5f627a021a0ef3927c1ae41dd341e32dba612fed52d0e3a6df056,2990
- json-0.10@sha256:d9fc6b07ce92b8894825a17d2cf14799856767eb30c8bf55962baa579207d799,3210
- multipart-0.2.0@sha256:b8770e3ff6089be4dd089a8250894b31287cca671f3d258190a505f9351fa8a9,1084
# flags:
# gf:
# c-runtime: true
# extra-lib-dirs:
# - /usr/local/lib

View File

@@ -1,13 +1,15 @@
# This default stack file is a copy of stack-ghc8.6.5.yaml # This default stack file is a copy of stack-ghc8.10.4.yaml
# But committing a symlink can be problematic on Windows, so it's a real copy. # But committing a symlink can be problematic on Windows, so it's a real copy.
# See: https://github.com/GrammaticalFramework/gf-core/pull/106 # See: https://github.com/GrammaticalFramework/gf-core/pull/106
resolver: lts-14.27 # ghc 8.6.5 resolver: lts-18.0 # ghc 8.10.4
extra-deps: extra-deps:
- network-2.6.3.6 - network-2.6.3.6
- httpd-shed-0.4.0.3 - httpd-shed-0.4.0.3
- cgi-3001.5.0.0 - cgi-3001.5.0.0@sha256:3d1193a328d5f627a021a0ef3927c1ae41dd341e32dba612fed52d0e3a6df056,2990
- json-0.10@sha256:d9fc6b07ce92b8894825a17d2cf14799856767eb30c8bf55962baa579207d799,3210
- multipart-0.2.0@sha256:b8770e3ff6089be4dd089a8250894b31287cca671f3d258190a505f9351fa8a9,1084
# flags: # flags:
# gf: # gf: