mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-22 03:09:33 -06:00
Compare commits
134 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1957eb1fc5 | ||
|
|
bd3ccb4a0d | ||
|
|
c71ed9f513 | ||
|
|
f9ca462a06 | ||
|
|
7492cd52d1 | ||
|
|
6f6f742d01 | ||
|
|
d477250c48 | ||
|
|
3a17a68da6 | ||
|
|
6ea53e44a4 | ||
|
|
4ecd216796 | ||
|
|
0b01f56fd7 | ||
|
|
0bac8f0dae | ||
|
|
8df9767493 | ||
|
|
3d272ac053 | ||
|
|
63828de0c2 | ||
|
|
72bec84f58 | ||
|
|
539b946c96 | ||
|
|
a42cec2107 | ||
|
|
4d446fcd3f | ||
|
|
ae460e76b6 | ||
|
|
65308861bc | ||
|
|
b7672b67a3 | ||
|
|
e33de168fd | ||
|
|
fc5b3e9037 | ||
|
|
9b9905c0b2 | ||
|
|
ec70e4a83e | ||
|
|
e6ade90679 | ||
|
|
6414bc8923 | ||
|
|
b0b2a06f3b | ||
|
|
221597bd79 | ||
|
|
862aeb5d9b | ||
|
|
25dd1354c7 | ||
|
|
b762e24a82 | ||
|
|
20453193fe | ||
|
|
b53a102c98 | ||
|
|
bc14a56f83 | ||
|
|
3a1213ab37 | ||
|
|
1b41e94f83 | ||
|
|
308f4773dc | ||
|
|
05fc093b5e | ||
|
|
4caf6d684e | ||
|
|
bfd8f9c16d | ||
|
|
aefac84670 | ||
|
|
9f2a3de7a3 | ||
|
|
e4b2f281d9 | ||
|
|
063c517f3c | ||
|
|
bedb46527d | ||
|
|
0258a87257 | ||
|
|
ef0e831c9e | ||
|
|
8ec13b1030 | ||
|
|
058526ec5d | ||
|
|
974e8b0835 | ||
|
|
bbe4682c3d | ||
|
|
e477ce4b1f | ||
|
|
7a63ba34b4 | ||
|
|
723bec1ba0 | ||
|
|
265f08d6ee | ||
|
|
e47042424e | ||
|
|
ecf309a28e | ||
|
|
d0a881f903 | ||
|
|
810640822d | ||
|
|
ed79955931 | ||
|
|
1867bfc8a1 | ||
|
|
6ef4f27d32 | ||
|
|
3ab07ec58f | ||
|
|
b8324fe3e6 | ||
|
|
8814fde817 | ||
|
|
375b3cf285 | ||
|
|
3c4f42db15 | ||
|
|
0474a37af6 | ||
|
|
e3498d5ead | ||
|
|
4c5927c98c | ||
|
|
bb51224e8e | ||
|
|
9533edc3ca | ||
|
|
4df8999ed5 | ||
|
|
7fdbf3f400 | ||
|
|
0d6c67f6b1 | ||
|
|
2610219f6a | ||
|
|
7674f078d6 | ||
|
|
c67fe05c08 | ||
|
|
7b9bb780a2 | ||
|
|
4f256447e2 | ||
|
|
dfa5b9276d | ||
|
|
667bfd30bd | ||
|
|
66ae31e99e | ||
|
|
a677f0373c | ||
|
|
13f845d127 | ||
|
|
aa530233fb | ||
|
|
45bc5595c0 | ||
|
|
6d12754e4f | ||
|
|
a09d9bd006 | ||
|
|
fffe3161d4 | ||
|
|
743f5e55d4 | ||
|
|
9e209bbaba | ||
|
|
a1594e6a69 | ||
|
|
06e0a986d1 | ||
|
|
6f2a4bcd2c | ||
|
|
f345f615f4 | ||
|
|
80d16fcf94 | ||
|
|
7faf8c9dad | ||
|
|
c2ffa6763b | ||
|
|
b3881570c7 | ||
|
|
bd270b05ff | ||
|
|
a1fd3ea142 | ||
|
|
cdbe73eb47 | ||
|
|
6077d5dd5b | ||
|
|
0954b4cbab | ||
|
|
f2e52d6f2c | ||
|
|
a2b23d5897 | ||
|
|
0886eb520d | ||
|
|
ef42216415 | ||
|
|
0c3ca3d79a | ||
|
|
e2e5033075 | ||
|
|
84b4b6fab9 | ||
|
|
5e052ff499 | ||
|
|
d2fb755fab | ||
|
|
1b66bf2773 | ||
|
|
1e3de38ac4 | ||
|
|
4e8859aa75 | ||
|
|
dff215504a | ||
|
|
173ab96839 | ||
|
|
dff1193f7b | ||
|
|
e1a40640cd | ||
|
|
be231584f6 | ||
|
|
12c564f97c | ||
|
|
09d772046e | ||
|
|
d53e1713c7 | ||
|
|
3df04295d9 | ||
|
|
b090e9b0ff | ||
|
|
5d7c687cb7 | ||
|
|
376b1234a2 | ||
|
|
71d99b9ecb | ||
|
|
d5c6aec3ec | ||
|
|
bfcab16de6 |
26
.github/workflows/build-all-versions.yml
vendored
26
.github/workflows/build-all-versions.yml
vendored
@@ -14,11 +14,11 @@ 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"
|
||||||
- "8.10.1"
|
- "8.10.7"
|
||||||
exclude:
|
exclude:
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
ghc: 8.8.3
|
ghc: 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.2.9
|
||||||
id: setup-haskell-cabal
|
id: setup-haskell-cabal
|
||||||
name: Setup Haskell
|
name: Setup Haskell
|
||||||
with:
|
with:
|
||||||
@@ -65,25 +65,33 @@ 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", "8.10.7", "9.0.2"]
|
||||||
# ghc: ["8.8.3"]
|
# ghc: ["8.8.3"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- 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.2.9
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
|
# Fix linker errrors on ghc-7.10.3 for ubuntu (see https://github.com/commercialhaskell/stack/blob/255cd830627870cdef34b5e54d670ef07882523e/doc/faq.md#i-get-strange-ld-errors-about-recompiling-with--fpic)
|
||||||
|
- run: sed -i.bak 's/"C compiler link flags", "/&-no-pie /' /home/runner/.ghcup/ghc/7.10.3/lib/ghc-7.10.3/settings
|
||||||
|
if: matrix.ghc == '7.10.3'
|
||||||
|
|
||||||
- uses: actions/cache@v1
|
- uses: actions/cache@v1
|
||||||
name: Cache ~/.stack
|
name: Cache ~/.stack
|
||||||
with:
|
with:
|
||||||
path: ~/.stack
|
path: ~/.stack
|
||||||
key: ${{ runner.os }}-${{ matrix.ghc }}-stack
|
key: ${{ runner.os }}-${{ matrix.ghc }}-stack--${{ hashFiles(format('stack-ghc{0}', matrix.ghc)) }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-${{ matrix.ghc }}-stack
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
75
.github/workflows/build-binary-packages.yml
vendored
75
.github/workflows/build-binary-packages.yml
vendored
@@ -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,19 +56,33 @@ 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.event.release.tag_name }}-${{ matrix.os }}.deb
|
||||||
path: dist/gf_*.deb
|
path: dist/gf_*.deb
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Rename package for specific ubuntu version
|
||||||
|
run: |
|
||||||
|
mv dist/gf_*.deb dist/gf-${{ github.event.release.tag_name }}-${{ matrix.os }}.deb
|
||||||
|
|
||||||
|
- uses: actions/upload-release-asset@v1.0.2
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ github.event.release.upload_url }}
|
||||||
|
asset_path: dist/gf-${{ github.event.release.tag_name }}-${{ matrix.os }}.deb
|
||||||
|
asset_name: gf-${{ github.event.release.tag_name }}-${{ matrix.os }}.deb
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
name: Build macOS package
|
name: Build macOS package
|
||||||
runs-on: macos-10.15
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
ghc: ["8.6.5"]
|
ghc: ["8.6.5"]
|
||||||
cabal: ["2.4"]
|
cabal: ["2.4"]
|
||||||
|
os: ["macos-10.15"]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -92,19 +109,33 @@ jobs:
|
|||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: gf-${{ github.sha }}-macos
|
name: gf-${{ github.event.release.tag_name }}-macos
|
||||||
path: dist/gf-*.pkg
|
path: dist/gf-*.pkg
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Rename package
|
||||||
|
run: |
|
||||||
|
mv dist/gf-*.pkg dist/gf-${{ github.event.release.tag_name }}-macos.pkg
|
||||||
|
|
||||||
|
- uses: actions/upload-release-asset@v1.0.2
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ github.event.release.upload_url }}
|
||||||
|
asset_path: dist/gf-${{ github.event.release.tag_name }}-macos.pkg
|
||||||
|
asset_name: gf-${{ github.event.release.tag_name }}-macos.pkg
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
name: Build Windows package
|
name: Build Windows package
|
||||||
runs-on: windows-2019
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
ghc: ["8.6.5"]
|
ghc: ["8.6.5"]
|
||||||
cabal: ["2.4"]
|
cabal: ["2.4"]
|
||||||
|
os: ["windows-2019"]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -136,16 +167,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 +190,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
|
||||||
@@ -180,6 +213,18 @@ jobs:
|
|||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: gf-${{ github.sha }}-windows
|
name: gf-${{ github.event.release.tag_name }}-windows
|
||||||
path: C:\tmp-dist\*
|
path: C:\tmp-dist\*
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Create archive
|
||||||
|
run: |
|
||||||
|
Compress-Archive C:\tmp-dist C:\gf-${{ github.event.release.tag_name }}-windows.zip
|
||||||
|
- uses: actions/upload-release-asset@v1.0.2
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ github.event.release.upload_url }}
|
||||||
|
asset_path: C:\gf-${{ github.event.release.tag_name }}-windows.zip
|
||||||
|
asset_name: gf-${{ github.event.release.tag_name }}-windows.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
|||||||
14
.travis.yml
14
.travis.yml
@@ -1,14 +0,0 @@
|
|||||||
sudo: required
|
|
||||||
|
|
||||||
language: c
|
|
||||||
|
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- docker pull odanoburu/gf-src:3.9
|
|
||||||
|
|
||||||
script:
|
|
||||||
- |
|
|
||||||
docker run --mount src="$(pwd)",target=/home/gfer,type=bind odanoburu/gf-src:3.9 /bin/bash -c "cd /home/gfer/src/runtime/c &&
|
|
||||||
autoreconf -i && ./configure && make && make install ; cd /home/gfer ; cabal install -fserver -fc-runtime --extra-lib-dirs='/usr/local/lib'"
|
|
||||||
11
CHANGELOG.md
Normal file
11
CHANGELOG.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
### New since 3.11 (WIP)
|
||||||
|
|
||||||
|
- Added a changelog!
|
||||||
|
|
||||||
|
### 3.11
|
||||||
|
|
||||||
|
See <https://www.grammaticalframework.org/download/release-3.11.html>
|
||||||
|
|
||||||
|
### 3.10
|
||||||
|
|
||||||
|
See <https://www.grammaticalframework.org/download/release-3.10.html>
|
||||||
47
Makefile
47
Makefile
@@ -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
|
||||||
|
|
||||||
@@ -48,6 +65,6 @@ bintar:
|
|||||||
|
|
||||||
# Make a source tar.gz distribution using git to make sure that everything is included.
|
# Make a source tar.gz distribution using git to make sure that everything is included.
|
||||||
# We put the distribution in dist/ so it is removed on `make clean`
|
# We put the distribution in dist/ so it is removed on `make clean`
|
||||||
sdist:
|
# sdist:
|
||||||
test -d dist || mkdir dist
|
# test -d dist || mkdir dist
|
||||||
git archive --format=tar.gz --output=dist/gf-${VERSION}.tar.gz HEAD
|
# git archive --format=tar.gz --output=dist/gf-${VERSION}.tar.gz HEAD
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||

|

|
||||||
|
|
||||||
# Grammatical Framework (GF)
|
# Grammatical Framework (GF)
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ or:
|
|||||||
stack install
|
stack install
|
||||||
```
|
```
|
||||||
|
|
||||||
For more information, including links to precompiled binaries, see the [download page](http://www.grammaticalframework.org/download/index.html).
|
For more information, including links to precompiled binaries, see the [download page](https://www.grammaticalframework.org/download/index.html).
|
||||||
|
|
||||||
## About this repository
|
## About this repository
|
||||||
|
|
||||||
|
|||||||
11
RELEASE.md
11
RELEASE.md
@@ -47,11 +47,14 @@ but the generated _artifacts_ must be manually attached to the release as _asset
|
|||||||
|
|
||||||
In order to do this you will need to be added the [GF maintainers](https://hackage.haskell.org/package/gf/maintainers/) on Hackage.
|
In order to do this you will need to be added the [GF maintainers](https://hackage.haskell.org/package/gf/maintainers/) on Hackage.
|
||||||
|
|
||||||
1. Run `make sdist`
|
1. Run `stack sdist --test-tarball` and address any issues.
|
||||||
2. Upload the package, either:
|
2. Upload the package, either:
|
||||||
1. **Manually**: visit <https://hackage.haskell.org/upload> and upload the file `dist/gf-X.Y.tar.gz`
|
1. **Manually**: visit <https://hackage.haskell.org/upload> and upload the file generated by the previous command.
|
||||||
2. **via Cabal (≥2.4)**: `cabal upload dist/gf-X.Y.tar.gz`
|
2. **via Stack**: `stack upload . --candidate`
|
||||||
3. If the documentation-building fails on the Hackage server, do:
|
3. After testing the candidate, publish it:
|
||||||
|
1. **Manually**: visit <https://hackage.haskell.org/package/gf-X.Y.Z/candidate/publish>
|
||||||
|
1. **via Stack**: `stack upload .`
|
||||||
|
4. If the documentation-building fails on the Hackage server, do:
|
||||||
```
|
```
|
||||||
cabal v2-haddock --builddir=dist/docs --haddock-for-hackage --enable-doc
|
cabal v2-haddock --builddir=dist/docs --haddock-for-hackage --enable-doc
|
||||||
cabal upload --documentation dist/docs/*-docs.tar.gz
|
cabal upload --documentation dist/docs/*-docs.tar.gz
|
||||||
|
|||||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -1,3 +1,9 @@
|
|||||||
|
gf (3.11) bionic focal; urgency=low
|
||||||
|
|
||||||
|
* GF 3.11
|
||||||
|
|
||||||
|
-- Inari Listenmaa <inari@digitalgrammars.com> Sun, 25 Jul 2021 10:27:40 +0800
|
||||||
|
|
||||||
gf (3.10.4-1) xenial bionic cosmic; urgency=low
|
gf (3.10.4-1) xenial bionic cosmic; urgency=low
|
||||||
|
|
||||||
* GF 3.10.4
|
* GF 3.10.4
|
||||||
|
|||||||
10
debian/rules
vendored
10
debian/rules
vendored
@@ -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
|
||||||
|
|||||||
201
doc/gf-developers-old-cabal.t2t
Normal file
201
doc/gf-developers-old-cabal.t2t
Normal 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
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -15,6 +15,13 @@ instructions inside.
|
|||||||
==Atom==
|
==Atom==
|
||||||
[language-gf https://atom.io/packages/language-gf], by John J. Camilleri
|
[language-gf https://atom.io/packages/language-gf], by John J. Camilleri
|
||||||
|
|
||||||
|
==Visual Studio Code==
|
||||||
|
|
||||||
|
- [Grammatical Framework Language Server https://marketplace.visualstudio.com/items?itemName=anka-213.gf-vscode] by Andreas Källberg.
|
||||||
|
This provides syntax highlighting and a client for the Grammatical Framework language server. Follow the installation instructions in the link.
|
||||||
|
- [Grammatical Framework https://marketplace.visualstudio.com/items?itemName=GrammaticalFramework.gf-vscode] is a simpler extension
|
||||||
|
without any external dependencies which provides only syntax highlighting.
|
||||||
|
|
||||||
==Eclipse==
|
==Eclipse==
|
||||||
|
|
||||||
[GF Eclipse Plugin https://github.com/GrammaticalFramework/gf-eclipse-plugin/], by John J. Camilleri
|
[GF Eclipse Plugin https://github.com/GrammaticalFramework/gf-eclipse-plugin/], by John J. Camilleri
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ title: "Grammatical Framework: Authors and Acknowledgements"
|
|||||||
The current maintainers of GF are
|
The current maintainers of GF are
|
||||||
|
|
||||||
[Krasimir Angelov](http://www.chalmers.se/cse/EN/organization/divisions/computing-science/people/angelov-krasimir),
|
[Krasimir Angelov](http://www.chalmers.se/cse/EN/organization/divisions/computing-science/people/angelov-krasimir),
|
||||||
[Thomas Hallgren](http://www.cse.chalmers.se/~hallgren/),
|
|
||||||
[Aarne Ranta](http://www.cse.chalmers.se/~aarne/),
|
[Aarne Ranta](http://www.cse.chalmers.se/~aarne/),
|
||||||
[John J. Camilleri](http://johnjcamilleri.com), and
|
[John J. Camilleri](http://johnjcamilleri.com), and
|
||||||
[Inari Listenmaa](https://inariksit.github.io/).
|
[Inari Listenmaa](https://inariksit.github.io/).
|
||||||
@@ -22,6 +21,7 @@ and
|
|||||||
|
|
||||||
The following people have contributed code to some of the versions:
|
The following people have contributed code to some of the versions:
|
||||||
|
|
||||||
|
- [Thomas Hallgren](http://www.cse.chalmers.se/~hallgren/) (University of Gothenburg)
|
||||||
- Grégoire Détrez (University of Gothenburg)
|
- Grégoire Détrez (University of Gothenburg)
|
||||||
- Ramona Enache (University of Gothenburg)
|
- Ramona Enache (University of Gothenburg)
|
||||||
- [Björn Bringert](http://www.cse.chalmers.se/alumni/bringert) (University of Gothenburg)
|
- [Björn Bringert](http://www.cse.chalmers.se/alumni/bringert) (University of Gothenburg)
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
---
|
---
|
||||||
title: Grammatical Framework Download and Installation
|
title: Grammatical Framework Download and Installation
|
||||||
...
|
date: 25 July 2021
|
||||||
|
---
|
||||||
|
|
||||||
**GF 3.11** was released on ... December 2020.
|
**GF 3.11** was released on 25 July 2021.
|
||||||
|
|
||||||
What's new? See the [release notes](release-3.11.html).
|
What's new? See the [release notes](release-3.11.html).
|
||||||
|
|
||||||
@@ -24,22 +25,25 @@ Binary packages are available for Debian/Ubuntu, macOS, and Windows and include:
|
|||||||
|
|
||||||
Unlike in previous versions, the binaries **do not** include the RGL.
|
Unlike in previous versions, the binaries **do not** include the RGL.
|
||||||
|
|
||||||
[Binary packages on GitHub](https://github.com/GrammaticalFramework/gf-core/releases/tag/RELEASE-3.11)
|
[Binary packages on GitHub](https://github.com/GrammaticalFramework/gf-core/releases/tag/3.11)
|
||||||
|
|
||||||
#### Debian/Ubuntu
|
#### Debian/Ubuntu
|
||||||
|
|
||||||
|
There are two versions: `gf-3.11-ubuntu-18.04.deb` for Ubuntu 18.04 (Cosmic), and `gf-3.11-ubuntu-20.04.deb` for Ubuntu 20.04 (Focal).
|
||||||
|
|
||||||
To install the package use:
|
To install the package use:
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo dpkg -i gf_3.11.deb
|
sudo apt-get install ./gf-3.11-ubuntu-*.deb
|
||||||
```
|
```
|
||||||
|
|
||||||
The Ubuntu `.deb` packages should work on Ubuntu 16.04, 18.04 and similar Linux distributions.
|
<!-- The Ubuntu `.deb` packages should work on Ubuntu 16.04, 18.04 and similar Linux distributions. -->
|
||||||
|
|
||||||
#### macOS
|
#### macOS
|
||||||
|
|
||||||
To install the package, just double-click it and follow the installer instructions.
|
To install the package, just double-click it and follow the installer instructions.
|
||||||
|
|
||||||
The packages should work on at least 10.13 (High Sierra) and 10.14 (Mojave).
|
The packages should work on at least Catalina and Big Sur.
|
||||||
|
|
||||||
#### Windows
|
#### Windows
|
||||||
|
|
||||||
@@ -49,26 +53,39 @@ You will probably need to update the `PATH` environment variable to include your
|
|||||||
|
|
||||||
For more information, see [Using GF on Windows](https://www.grammaticalframework.org/~inari/gf-windows.html) (latest updated for Windows 10).
|
For more information, see [Using GF on Windows](https://www.grammaticalframework.org/~inari/gf-windows.html) (latest updated for Windows 10).
|
||||||
|
|
||||||
## Installing the latest Hackage release (macOS, Linux, and WSL2 on Windows)
|
## Installing from Hackage
|
||||||
|
|
||||||
|
_Instructions applicable for macOS, Linux, and WSL2 on Windows._
|
||||||
|
|
||||||
[GF is on Hackage](http://hackage.haskell.org/package/gf), so under
|
[GF is on Hackage](http://hackage.haskell.org/package/gf), so under
|
||||||
normal circumstances the procedure is fairly simple:
|
normal circumstances the procedure is fairly simple:
|
||||||
|
|
||||||
1. Install ghcup https://www.haskell.org/ghcup/
|
```
|
||||||
2. `ghcup install ghc 8.10.4`
|
cabal update
|
||||||
3. `ghcup set ghc 8.10.4`
|
cabal install gf-3.11
|
||||||
4. `cabal update`
|
```
|
||||||
5. On Linux: install some C libraries from your Linux distribution (see note below)
|
|
||||||
6. `cabal install gf-3.11`
|
|
||||||
|
|
||||||
You can also download the source code release from [GitHub](https://github.com/GrammaticalFramework/gf-core/releases),
|
|
||||||
and follow the instructions below under **Installing from the latest developer source code**.
|
|
||||||
|
|
||||||
### Notes
|
### Notes
|
||||||
|
|
||||||
|
**GHC version**
|
||||||
|
|
||||||
|
The GF source code is known to be compilable with GHC versions 7.10 through to 8.10.
|
||||||
|
|
||||||
|
**Obtaining Haskell**
|
||||||
|
|
||||||
|
There are various ways of obtaining Haskell, including:
|
||||||
|
|
||||||
|
- ghcup
|
||||||
|
1. Install from https://www.haskell.org/ghcup/
|
||||||
|
2. `ghcup install ghc 8.10.4`
|
||||||
|
3. `ghcup set ghc 8.10.4`
|
||||||
|
- Haskell Platform https://www.haskell.org/platform/
|
||||||
|
- Stack https://haskellstack.org/
|
||||||
|
|
||||||
|
|
||||||
**Installation location**
|
**Installation location**
|
||||||
|
|
||||||
The above steps installs GF for a single user.
|
The above steps install GF for a single user.
|
||||||
The executables are put in `$HOME/.cabal/bin` (or on macOS in `$HOME/Library/Haskell/bin`),
|
The executables are put in `$HOME/.cabal/bin` (or on macOS in `$HOME/Library/Haskell/bin`),
|
||||||
so you might want to add this directory to your path (in `.bash_profile` or similar):
|
so you might want to add this directory to your path (in `.bash_profile` or similar):
|
||||||
|
|
||||||
@@ -80,32 +97,34 @@ PATH=$HOME/.cabal/bin:$PATH
|
|||||||
|
|
||||||
GF uses [`haskeline`](http://hackage.haskell.org/package/haskeline), which
|
GF uses [`haskeline`](http://hackage.haskell.org/package/haskeline), which
|
||||||
on Linux depends on some non-Haskell libraries that won't be installed
|
on Linux depends on some non-Haskell libraries that won't be installed
|
||||||
automatically by cabal, and therefore need to be installed manually.
|
automatically by Cabal, and therefore need to be installed manually.
|
||||||
Here is one way to do this:
|
Here is one way to do this:
|
||||||
|
|
||||||
- On Ubuntu: `sudo apt-get install libghc-haskeline-dev`
|
- On Ubuntu: `sudo apt-get install libghc-haskeline-dev`
|
||||||
- On Fedora: `sudo dnf install ghc-haskeline-devel`
|
- On Fedora: `sudo dnf install ghc-haskeline-devel`
|
||||||
|
|
||||||
**GHC version**
|
## Installing from source code
|
||||||
|
|
||||||
The GF source code has been updated to compile with GHC versions 7.10 through to 8.8.
|
**Obtaining**
|
||||||
|
|
||||||
## Installing from the latest developer source code
|
To obtain the source code for the **release**,
|
||||||
|
download it from [GitHub](https://github.com/GrammaticalFramework/gf-core/releases).
|
||||||
|
|
||||||
If you haven't already, clone the repository with:
|
Alternatively, to obtain the **latest version** of the source code:
|
||||||
|
|
||||||
|
1. If you haven't already, clone the repository with:
|
||||||
```
|
```
|
||||||
git clone https://github.com/GrammaticalFramework/gf-core.git
|
git clone https://github.com/GrammaticalFramework/gf-core.git
|
||||||
```
|
```
|
||||||
|
2. If you've already cloned the repository previously, update with:
|
||||||
If you've already cloned the repository previously, update with:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
git pull
|
git pull
|
||||||
```
|
```
|
||||||
|
|
||||||
Then install with:
|
|
||||||
|
|
||||||
|
**Installing**
|
||||||
|
|
||||||
|
You can then install with:
|
||||||
```
|
```
|
||||||
cabal install
|
cabal install
|
||||||
```
|
```
|
||||||
@@ -116,7 +135,7 @@ or, if you're a Stack user:
|
|||||||
stack install
|
stack install
|
||||||
```
|
```
|
||||||
|
|
||||||
The above notes for installing from source apply also in these cases.
|
<!--The above notes for installing from source apply also in these cases.-->
|
||||||
For more info on working with the GF source code, see the
|
For more info on working with the GF source code, see the
|
||||||
[GF Developers Guide](../doc/gf-developers.html).
|
[GF Developers Guide](../doc/gf-developers.html).
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="refresh" content="0; URL=/download/index-3.10.html" />
|
<meta http-equiv="refresh" content="0; URL=/download/index-3.11.html" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
You are being redirected to <a href="index-3.10.html">the current version</a> of this page.
|
You are being redirected to <a href="index-3.11.html">the current version</a> of this page.
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
title: GF 3.11 Release Notes
|
title: GF 3.11 Release Notes
|
||||||
date: ... December 2020
|
date: 25 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.
|
||||||
|
|||||||
190
gf.cabal
190
gf.cabal
@@ -1,20 +1,24 @@
|
|||||||
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/
|
maintainer: John J. Camilleri <john@digitalgrammars.com>
|
||||||
|
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, GHC==9.0.2
|
||||||
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:
|
||||||
|
README.md
|
||||||
|
CHANGELOG.md
|
||||||
|
WebSetup.hs
|
||||||
|
doc/Logos/gf0.png
|
||||||
data-files:
|
data-files:
|
||||||
www/*.html
|
www/*.html
|
||||||
www/*.css
|
www/*.css
|
||||||
@@ -42,23 +46,23 @@ data-files:
|
|||||||
|
|
||||||
custom-setup
|
custom-setup
|
||||||
setup-depends:
|
setup-depends:
|
||||||
base,
|
base >= 4.9.1 && < 4.16,
|
||||||
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 +74,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.16,
|
||||||
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.1,
|
||||||
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:
|
||||||
@@ -102,7 +111,7 @@ library
|
|||||||
--ghc-options: -fwarn-unused-imports
|
--ghc-options: -fwarn-unused-imports
|
||||||
--if impl(ghc>=7.8)
|
--if impl(ghc>=7.8)
|
||||||
-- ghc-options: +RTS -A20M -RTS
|
-- ghc-options: +RTS -A20M -RTS
|
||||||
ghc-prof-options: -fprof-auto
|
-- ghc-prof-options: -fprof-auto
|
||||||
|
|
||||||
exposed-modules:
|
exposed-modules:
|
||||||
PGF
|
PGF
|
||||||
@@ -136,18 +145,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 +177,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
|
||||||
@@ -178,7 +204,7 @@ library
|
|||||||
GF.Command.TreeOperations
|
GF.Command.TreeOperations
|
||||||
GF.Compile.CFGtoPGF
|
GF.Compile.CFGtoPGF
|
||||||
GF.Compile.CheckGrammar
|
GF.Compile.CheckGrammar
|
||||||
GF.Compile.Compute.ConcreteNew
|
GF.Compile.Compute.Concrete
|
||||||
GF.Compile.Compute.Predef
|
GF.Compile.Compute.Predef
|
||||||
GF.Compile.Compute.Value
|
GF.Compile.Compute.Value
|
||||||
GF.Compile.ExampleBased
|
GF.Compile.ExampleBased
|
||||||
@@ -207,7 +233,6 @@ library
|
|||||||
GF.Compile.TypeCheck.Concrete
|
GF.Compile.TypeCheck.Concrete
|
||||||
GF.Compile.TypeCheck.ConcreteNew
|
GF.Compile.TypeCheck.ConcreteNew
|
||||||
GF.Compile.TypeCheck.Primitives
|
GF.Compile.TypeCheck.Primitives
|
||||||
GF.Compile.TypeCheck.RConcrete
|
|
||||||
GF.Compile.TypeCheck.TC
|
GF.Compile.TypeCheck.TC
|
||||||
GF.Compile.Update
|
GF.Compile.Update
|
||||||
GF.Data.BacktrackM
|
GF.Data.BacktrackM
|
||||||
@@ -274,12 +299,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 && <3.2
|
||||||
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 && <3.2
|
||||||
else
|
else
|
||||||
build-depends: network<2.6
|
build-depends:
|
||||||
|
network >= 2.5 && <3.2
|
||||||
|
|
||||||
cpp-options: -DSERVER_MODE
|
cpp-options: -DSERVER_MODE
|
||||||
other-modules:
|
other-modules:
|
||||||
@@ -296,7 +326,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
|
||||||
@@ -305,17 +338,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
|
||||||
@@ -323,8 +363,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
|
||||||
|
|
||||||
@@ -333,25 +375,35 @@ executable gf
|
|||||||
if impl(ghc<7.8)
|
if impl(ghc<7.8)
|
||||||
ghc-options: -with-rtsopts=-K64M
|
ghc-options: -with-rtsopts=-K64M
|
||||||
|
|
||||||
ghc-prof-options: -auto-all
|
-- ghc-prof-options: -auto-all
|
||||||
|
|
||||||
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.16,
|
||||||
|
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
|
||||||
|
|||||||
80
index.html
80
index.html
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.2/css/all.css" integrity="sha384-/rXc/GQVaYpyDdyxK+ecHPVYJSN9bmVFBvjA/9eOB+pb3F2w2N6fc5qB9Ew5yIns" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" crossorigin="anonymous">
|
||||||
|
|
||||||
<link rel="alternate" href="https://github.com/GrammaticalFramework/gf-core/" title="GF GitHub repository">
|
<link rel="alternate" href="https://github.com/GrammaticalFramework/gf-core/" title="GF GitHub repository">
|
||||||
</head>
|
</head>
|
||||||
@@ -85,10 +85,27 @@
|
|||||||
<div class="col-sm-6 col-md-3 mb-4">
|
<div class="col-sm-6 col-md-3 mb-4">
|
||||||
<h3>Contribute</h3>
|
<h3>Contribute</h3>
|
||||||
<ul class="mb-2">
|
<ul class="mb-2">
|
||||||
<li><a href="http://groups.google.com/group/gf-dev">Mailing List</a></li>
|
<li>
|
||||||
|
<a href="https://web.libera.chat/?channels=#gf">
|
||||||
|
<i class="fas fa-hashtag"></i>
|
||||||
|
IRC
|
||||||
|
</a>
|
||||||
|
/
|
||||||
|
<a href="https://discord.gg/EvfUsjzmaz">
|
||||||
|
<i class="fab fa-discord"></i>
|
||||||
|
Discord
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://stackoverflow.com/questions/tagged/gf">
|
||||||
|
<i class="fab fa-stack-overflow"></i>
|
||||||
|
Stack Overflow
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="https://groups.google.com/group/gf-dev">Mailing List</a></li>
|
||||||
<li><a href="https://github.com/GrammaticalFramework/gf-core/issues">Issue Tracker</a></li>
|
<li><a href="https://github.com/GrammaticalFramework/gf-core/issues">Issue Tracker</a></li>
|
||||||
<li><a href="doc/gf-people.html">Authors</a></li>
|
|
||||||
<li><a href="//school.grammaticalframework.org/2020/">Summer School</a></li>
|
<li><a href="//school.grammaticalframework.org/2020/">Summer School</a></li>
|
||||||
|
<li><a href="doc/gf-people.html">Authors</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<a href="https://github.com/GrammaticalFramework/" class="btn btn-primary ml-3">
|
<a href="https://github.com/GrammaticalFramework/" class="btn btn-primary ml-3">
|
||||||
<i class="fab fa-github mr-1"></i>
|
<i class="fab fa-github mr-1"></i>
|
||||||
@@ -154,7 +171,7 @@ least one, it may help you to get a first idea of what GF is.
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h2>Applications & Availability</h2>
|
<h2>Applications & availability</h2>
|
||||||
<p>
|
<p>
|
||||||
GF can be used for building
|
GF can be used for building
|
||||||
<a href="//cloud.grammaticalframework.org/translator/">translation systems</a>,
|
<a href="//cloud.grammaticalframework.org/translator/">translation systems</a>,
|
||||||
@@ -214,60 +231,45 @@ 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>.
|
There is also a <a href="https://discord.gg/EvfUsjzmaz">GF server on Discord</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For bug reports and feature requests, please create an issue in the
|
||||||
|
<a href="https://github.com/GrammaticalFramework/gf-core/issues">GF Core</a> or
|
||||||
|
<a href="https://github.com/GrammaticalFramework/gf-rgl/issues">RGL</a> repository.
|
||||||
|
|
||||||
|
For programming questions, consider asking them on <a href="https://stackoverflow.com/questions/tagged/gf">Stack Overflow with the <code>gf</code> tag</a>.
|
||||||
|
If you have a more general question to the community, we recommend you ask it on the <a href="http://groups.google.com/group/gf-dev">mailing list</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h2>News</h2>
|
<h2>News</h2>
|
||||||
|
|
||||||
<dl class="row">
|
<dl class="row">
|
||||||
|
<dt class="col-sm-3 text-center text-nowrap">2021-07-25</dt>
|
||||||
|
<dd class="col-sm-9">
|
||||||
|
<strong>GF 3.11 released.</strong>
|
||||||
|
<a href="download/release-3.11.html">Release notes</a>
|
||||||
|
</dd>
|
||||||
<dt class="col-sm-3 text-center text-nowrap">2021-05-05</dt>
|
<dt class="col-sm-3 text-center text-nowrap">2021-05-05</dt>
|
||||||
<dd class="col-sm-9">
|
<dd class="col-sm-9">
|
||||||
<a href="https://cloud.grammaticalframework.org/wordnet/">GF WordNet</a> now supports languages for which there are no other WordNets. New additions: Afrikaans, German, Korean, Maltese, Polish, Somali, Swahili.
|
<a href="https://cloud.grammaticalframework.org/wordnet/">GF WordNet</a> now supports languages for which there are no other WordNets. New additions: Afrikaans, German, Korean, Maltese, Polish, Somali, Swahili.
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="col-sm-3 text-center text-nowrap">2021-03-01</dt>
|
<dt class="col-sm-3 text-center text-nowrap">2021-03-01</dt>
|
||||||
<dd class="col-sm-9">
|
<dd class="col-sm-9">
|
||||||
<a href="//school.grammaticalframework.org/2020/">Seventh GF Summer School</a>, in Singapore and online, 26 July – 8 August 2021.
|
<a href="//school.grammaticalframework.org/2020/">Seventh GF Summer School</a>, in Singapore and online, 26 July – 6 August 2021.
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="col-sm-3 text-center text-nowrap">2020-09-29</dt>
|
<dt class="col-sm-3 text-center text-nowrap">2020-09-29</dt>
|
||||||
<dd class="col-sm-9">
|
<dd class="col-sm-9">
|
||||||
<a href="https://www.mitpressjournals.org/doi/pdf/10.1162/COLI_a_00378">Abstract Syntax as Interlingua</a>: Scaling Up the Grammatical Framework from Controlled Languages to Robust Pipelines. A paper in Computational Linguistics (2020) summarizing much of the development in GF in the past ten years.
|
<a href="https://www.mitpressjournals.org/doi/pdf/10.1162/COLI_a_00378">Abstract Syntax as Interlingua</a>: Scaling Up the Grammatical Framework from Controlled Languages to Robust Pipelines. A paper in Computational Linguistics (2020) summarizing much of the development in GF in the past ten years.
|
||||||
</dd>
|
</dd>
|
||||||
<dt class="col-sm-3 text-center text-nowrap">2018-12-03</dt>
|
|
||||||
<dd class="col-sm-9">
|
|
||||||
<a href="//school.grammaticalframework.org/2018/">Sixth GF Summer School</a> in Stellenbosch (South Africa), 3–14 December 2018
|
|
||||||
</dd>
|
|
||||||
<dt class="col-sm-3 text-center text-nowrap">2018-12-02</dt>
|
|
||||||
<dd class="col-sm-9">
|
|
||||||
<strong>GF 3.10 released.</strong>
|
|
||||||
<a href="download/release-3.10.html">Release notes</a>
|
|
||||||
</dd>
|
|
||||||
<dt class="col-sm-3 text-center text-nowrap">2018-07-25</dt>
|
|
||||||
<dd class="col-sm-9">
|
|
||||||
The GF repository has been split in two:
|
|
||||||
<a href="https://github.com/GrammaticalFramework/gf-core">gf-core</a> and
|
|
||||||
<a href="https://github.com/GrammaticalFramework/gf-rgl">gf-rgl</a>.
|
|
||||||
The original <a href="https://github.com/GrammaticalFramework/GF">GF</a> repository is now archived.
|
|
||||||
</dd>
|
|
||||||
<dt class="col-sm-3 text-center text-nowrap">2017-08-11</dt>
|
|
||||||
<dd class="col-sm-9">
|
|
||||||
<strong>GF 3.9 released.</strong>
|
|
||||||
<a href="download/release-3.9.html">Release notes</a>
|
|
||||||
</dd>
|
|
||||||
<dt class="col-sm-3 text-center text-nowrap">2017-06-29</dt>
|
|
||||||
<dd class="col-sm-9">
|
|
||||||
GF is moving to <a href="https://github.com/GrammaticalFramework/GF/">GitHub</a>.</dd>
|
|
||||||
<dt class="col-sm-3 text-center text-nowrap">2017-03-13</dt>
|
|
||||||
<dd class="col-sm-9">
|
|
||||||
<a href="//school.grammaticalframework.org/2017/">GF Summer School</a> in Riga (Latvia), 14-25 August 2017
|
|
||||||
</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h2>Projects</h2>
|
<h2>Projects</h2>
|
||||||
@@ -337,7 +339,7 @@ least one, it may help you to get a first idea of what GF is.
|
|||||||
Libraries are at the heart of modern software engineering. In natural language
|
Libraries are at the heart of modern software engineering. In natural language
|
||||||
applications, libraries are a way to cope with thousands of details involved in
|
applications, libraries are a way to cope with thousands of details involved in
|
||||||
syntax, lexicon, and inflection. The
|
syntax, lexicon, and inflection. The
|
||||||
<a href="lib/doc/synopsis/index.html">GF resource grammar library</a> has
|
<a href="lib/doc/synopsis/index.html">GF resource grammar library</a> (RGL) has
|
||||||
support for an increasing number of languages, currently including
|
support for an increasing number of languages, currently including
|
||||||
Afrikaans,
|
Afrikaans,
|
||||||
Amharic (partial),
|
Amharic (partial),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ module GF.Command.Commands (
|
|||||||
options,flags,
|
options,flags,
|
||||||
) where
|
) where
|
||||||
import Prelude hiding (putStrLn,(<>)) -- GHC 8.4.1 clash with Text.PrettyPrint
|
import Prelude hiding (putStrLn,(<>)) -- GHC 8.4.1 clash with Text.PrettyPrint
|
||||||
|
import System.Info(os)
|
||||||
|
|
||||||
import PGF
|
import PGF
|
||||||
|
|
||||||
@@ -882,11 +883,15 @@ pgfCommands = Map.fromList [
|
|||||||
Right ty -> ty
|
Right ty -> ty
|
||||||
Nothing -> error ("Can't parse '"++str++"' as a type")
|
Nothing -> error ("Can't parse '"++str++"' as a type")
|
||||||
optViewFormat opts = valStrOpts "format" "png" opts
|
optViewFormat opts = valStrOpts "format" "png" opts
|
||||||
optViewGraph opts = valStrOpts "view" "open" opts
|
optViewGraph opts = valStrOpts "view" open_cmd opts
|
||||||
optNum opts = valIntOpts "number" 1 opts
|
optNum opts = valIntOpts "number" 1 opts
|
||||||
optNumInf opts = valIntOpts "number" 1000000000 opts ---- 10^9
|
optNumInf opts = valIntOpts "number" 1000000000 opts ---- 10^9
|
||||||
takeOptNum opts = take (optNumInf opts)
|
takeOptNum opts = take (optNumInf opts)
|
||||||
|
|
||||||
|
open_cmd | os == "linux" = "xdg-open"
|
||||||
|
| os == "mingw32" = "start"
|
||||||
|
| otherwise = "open"
|
||||||
|
|
||||||
returnFromExprs es = return $ case es of
|
returnFromExprs es = return $ case es of
|
||||||
[] -> pipeMessage "no trees found"
|
[] -> pipeMessage "no trees found"
|
||||||
_ -> fromExprs es
|
_ -> fromExprs es
|
||||||
@@ -1022,4 +1027,4 @@ stanzas = map unlines . chop . lines where
|
|||||||
|
|
||||||
#if !(MIN_VERSION_base(4,9,0))
|
#if !(MIN_VERSION_base(4,9,0))
|
||||||
errorWithoutStackTrace = error
|
errorWithoutStackTrace = error
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import GF.Command.Abstract --(isOpt,valStrOpts,prOpt)
|
|||||||
import GF.Text.Pretty
|
import GF.Text.Pretty
|
||||||
import GF.Text.Transliterations
|
import GF.Text.Transliterations
|
||||||
import GF.Text.Lexing(stringOp,opInEnv)
|
import GF.Text.Lexing(stringOp,opInEnv)
|
||||||
|
import Data.Char (isSpace)
|
||||||
|
|
||||||
import qualified PGF as H(showCId,showExpr,toATree,toTrie,Trie(..))
|
import qualified PGF as H(showCId,showExpr,toATree,toTrie,Trie(..))
|
||||||
|
|
||||||
@@ -170,7 +171,8 @@ commonCommands = fmap (mapCommandExec liftSIO) $ Map.fromList [
|
|||||||
restrictedSystem $ syst ++ " <" ++ tmpi ++ " >" ++ tmpo
|
restrictedSystem $ syst ++ " <" ++ tmpi ++ " >" ++ tmpo
|
||||||
fmap fromString $ restricted $ readFile tmpo,
|
fmap fromString $ restricted $ readFile tmpo,
|
||||||
-}
|
-}
|
||||||
fmap fromString . restricted . readShellProcess syst $ toString arg,
|
fmap (fromStrings . lines) . restricted . readShellProcess syst . unlines . map (dropWhile (=='\n')) $ toStrings $ arg,
|
||||||
|
|
||||||
flags = [
|
flags = [
|
||||||
("command","the system command applied to the argument")
|
("command","the system command applied to the argument")
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ import GF.Grammar.Parser (runP, pExp)
|
|||||||
import GF.Grammar.ShowTerm
|
import GF.Grammar.ShowTerm
|
||||||
import GF.Grammar.Lookup (allOpers,allOpersTo)
|
import GF.Grammar.Lookup (allOpers,allOpersTo)
|
||||||
import GF.Compile.Rename(renameSourceTerm)
|
import GF.Compile.Rename(renameSourceTerm)
|
||||||
import qualified GF.Compile.Compute.ConcreteNew as CN(normalForm,resourceValues)
|
import GF.Compile.Compute.Concrete(normalForm,resourceValues)
|
||||||
import GF.Compile.TypeCheck.RConcrete as TC(inferLType,ppType)
|
import GF.Compile.TypeCheck.Concrete as TC(inferLType,ppType)
|
||||||
import GF.Infra.Dependencies(depGraph)
|
import GF.Infra.Dependencies(depGraph)
|
||||||
import GF.Infra.CheckM(runCheck)
|
import GF.Infra.CheckM(runCheck)
|
||||||
|
|
||||||
@@ -259,7 +259,7 @@ checkComputeTerm os sgr t =
|
|||||||
((t,_),_) <- runCheck $ do t <- renameSourceTerm sgr mo t
|
((t,_),_) <- runCheck $ do t <- renameSourceTerm sgr mo t
|
||||||
inferLType sgr [] t
|
inferLType sgr [] t
|
||||||
let opts = modifyFlags (\fs->fs{optTrace=isOpt "trace" os})
|
let opts = modifyFlags (\fs->fs{optTrace=isOpt "trace" os})
|
||||||
t1 = CN.normalForm (CN.resourceValues opts sgr) (L NoLoc identW) t
|
t1 = normalForm (resourceValues opts sgr) (L NoLoc identW) t
|
||||||
t2 = evalStr t1
|
t2 = evalStr t1
|
||||||
checkPredefError t2
|
checkPredefError t2
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
-- Stability : (stable)
|
-- Stability : (stable)
|
||||||
-- Portability : (portable)
|
-- Portability : (portable)
|
||||||
--
|
--
|
||||||
-- > CVS $Date: 2005/11/11 23:24:33 $
|
-- > CVS $Date: 2005/11/11 23:24:33 $
|
||||||
-- > CVS $Author: aarne $
|
-- > CVS $Author: aarne $
|
||||||
-- > CVS $Revision: 1.31 $
|
-- > CVS $Revision: 1.31 $
|
||||||
--
|
--
|
||||||
@@ -27,9 +27,9 @@ import GF.Infra.Ident
|
|||||||
import GF.Infra.Option
|
import GF.Infra.Option
|
||||||
|
|
||||||
import GF.Compile.TypeCheck.Abstract
|
import GF.Compile.TypeCheck.Abstract
|
||||||
import GF.Compile.TypeCheck.RConcrete
|
import GF.Compile.TypeCheck.Concrete(computeLType,checkLType,inferLType,ppType)
|
||||||
import qualified GF.Compile.TypeCheck.ConcreteNew as CN
|
import qualified GF.Compile.TypeCheck.ConcreteNew as CN(checkLType,inferLType)
|
||||||
import qualified GF.Compile.Compute.ConcreteNew as CN
|
import qualified GF.Compile.Compute.Concrete as CN(normalForm,resourceValues)
|
||||||
|
|
||||||
import GF.Grammar
|
import GF.Grammar
|
||||||
import GF.Grammar.Lexer
|
import GF.Grammar.Lexer
|
||||||
@@ -74,9 +74,9 @@ checkRestrictedInheritance cwd sgr (name,mo) = checkInModule cwd mo NoLoc empty
|
|||||||
let (incl,excl) = partition (isInherited mi) (Map.keys (jments m))
|
let (incl,excl) = partition (isInherited mi) (Map.keys (jments m))
|
||||||
let incld c = Set.member c (Set.fromList incl)
|
let incld c = Set.member c (Set.fromList incl)
|
||||||
let illegal c = Set.member c (Set.fromList excl)
|
let illegal c = Set.member c (Set.fromList excl)
|
||||||
let illegals = [(f,is) |
|
let illegals = [(f,is) |
|
||||||
(f,cs) <- allDeps, incld f, let is = filter illegal cs, not (null is)]
|
(f,cs) <- allDeps, incld f, let is = filter illegal cs, not (null is)]
|
||||||
case illegals of
|
case illegals of
|
||||||
[] -> return ()
|
[] -> return ()
|
||||||
cs -> checkWarn ("In inherited module" <+> i <> ", dependence of excluded constants:" $$
|
cs -> checkWarn ("In inherited module" <+> i <> ", dependence of excluded constants:" $$
|
||||||
nest 2 (vcat [f <+> "on" <+> fsep is | (f,is) <- cs]))
|
nest 2 (vcat [f <+> "on" <+> fsep is | (f,is) <- cs]))
|
||||||
@@ -92,12 +92,12 @@ checkCompleteGrammar opts cwd gr (am,abs) (cm,cnc) = checkInModule cwd cnc NoLoc
|
|||||||
|
|
||||||
-- check that all abstract constants are in concrete; build default lin and lincats
|
-- check that all abstract constants are in concrete; build default lin and lincats
|
||||||
jsc <- foldM checkAbs jsc (Map.toList jsa)
|
jsc <- foldM checkAbs jsc (Map.toList jsa)
|
||||||
|
|
||||||
return (cm,cnc{jments=jsc})
|
return (cm,cnc{jments=jsc})
|
||||||
where
|
where
|
||||||
checkAbs js i@(c,info) =
|
checkAbs js i@(c,info) =
|
||||||
case info of
|
case info of
|
||||||
AbsFun (Just (L loc ty)) _ _ _
|
AbsFun (Just (L loc ty)) _ _ _
|
||||||
-> do let mb_def = do
|
-> do let mb_def = do
|
||||||
let (cxt,(_,i),_) = typeForm ty
|
let (cxt,(_,i),_) = typeForm ty
|
||||||
info <- lookupIdent i js
|
info <- lookupIdent i js
|
||||||
@@ -136,11 +136,11 @@ checkCompleteGrammar opts cwd gr (am,abs) (cm,cnc) = checkInModule cwd cnc NoLoc
|
|||||||
checkWarn ("no linearization type for" <+> c <> ", inserting default {s : Str}")
|
checkWarn ("no linearization type for" <+> c <> ", inserting default {s : Str}")
|
||||||
return $ Map.insert c (CncCat (Just (L NoLoc defLinType)) Nothing Nothing Nothing Nothing) js
|
return $ Map.insert c (CncCat (Just (L NoLoc defLinType)) Nothing Nothing Nothing Nothing) js
|
||||||
_ -> return js
|
_ -> return js
|
||||||
|
|
||||||
checkCnc js (c,info) =
|
checkCnc js (c,info) =
|
||||||
case info of
|
case info of
|
||||||
CncFun _ d mn mf -> case lookupOrigInfo gr (am,c) of
|
CncFun _ d mn mf -> case lookupOrigInfo gr (am,c) of
|
||||||
Ok (_,AbsFun (Just (L _ ty)) _ _ _) ->
|
Ok (_,AbsFun (Just (L _ ty)) _ _ _) ->
|
||||||
do (cont,val) <- linTypeOfType gr cm ty
|
do (cont,val) <- linTypeOfType gr cm ty
|
||||||
let linty = (snd (valCat ty),cont,val)
|
let linty = (snd (valCat ty),cont,val)
|
||||||
return $ Map.insert c (CncFun (Just linty) d mn mf) js
|
return $ Map.insert c (CncFun (Just linty) d mn mf) js
|
||||||
@@ -159,14 +159,14 @@ checkCompleteGrammar opts cwd gr (am,abs) (cm,cnc) = checkInModule cwd cnc NoLoc
|
|||||||
_ -> return $ Map.insert c info js
|
_ -> return $ Map.insert c info js
|
||||||
|
|
||||||
|
|
||||||
-- | General Principle: only Just-values are checked.
|
-- | General Principle: only Just-values are checked.
|
||||||
-- A May-value has always been checked in its origin module.
|
-- A May-value has always been checked in its origin module.
|
||||||
checkInfo :: Options -> FilePath -> SourceGrammar -> SourceModule -> Ident -> Info -> Check Info
|
checkInfo :: Options -> FilePath -> SourceGrammar -> SourceModule -> Ident -> Info -> Check Info
|
||||||
checkInfo opts cwd sgr (m,mo) c info = checkInModule cwd mo NoLoc empty $ do
|
checkInfo opts cwd sgr (m,mo) c info = checkInModule cwd mo NoLoc empty $ do
|
||||||
checkReservedId c
|
checkReservedId c
|
||||||
case info of
|
case info of
|
||||||
AbsCat (Just (L loc cont)) ->
|
AbsCat (Just (L loc cont)) ->
|
||||||
mkCheck loc "the category" $
|
mkCheck loc "the category" $
|
||||||
checkContext gr cont
|
checkContext gr cont
|
||||||
|
|
||||||
AbsFun (Just (L loc typ0)) ma md moper -> do
|
AbsFun (Just (L loc typ0)) ma md moper -> do
|
||||||
@@ -175,13 +175,13 @@ 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)
|
||||||
|
|
||||||
CncCat mty mdef mref mpr mpmcfg -> do
|
CncCat mty mdef mref mpr mpmcfg -> do
|
||||||
mty <- case mty of
|
mty <- case mty of
|
||||||
Just (L loc typ) -> chIn loc "linearization type of" $
|
Just (L loc typ) -> chIn loc "linearization type of" $
|
||||||
(if False --flag optNewComp opts
|
(if False --flag optNewComp opts
|
||||||
then do (typ,_) <- CN.checkLType (CN.resourceValues opts gr) typ typeType
|
then do (typ,_) <- CN.checkLType (CN.resourceValues opts gr) typ typeType
|
||||||
typ <- computeLType gr [] typ
|
typ <- computeLType gr [] typ
|
||||||
@@ -191,19 +191,19 @@ checkInfo opts cwd sgr (m,mo) c info = checkInModule cwd mo NoLoc empty $ do
|
|||||||
return (Just (L loc typ)))
|
return (Just (L loc typ)))
|
||||||
Nothing -> return Nothing
|
Nothing -> return Nothing
|
||||||
mdef <- case (mty,mdef) of
|
mdef <- case (mty,mdef) of
|
||||||
(Just (L _ typ),Just (L loc def)) ->
|
(Just (L _ typ),Just (L loc def)) ->
|
||||||
chIn loc "default linearization of" $ do
|
chIn loc "default linearization of" $ do
|
||||||
(def,_) <- checkLType gr [] def (mkFunType [typeStr] typ)
|
(def,_) <- checkLType gr [] def (mkFunType [typeStr] typ)
|
||||||
return (Just (L loc def))
|
return (Just (L loc def))
|
||||||
_ -> return Nothing
|
_ -> return Nothing
|
||||||
mref <- case (mty,mref) of
|
mref <- case (mty,mref) of
|
||||||
(Just (L _ typ),Just (L loc ref)) ->
|
(Just (L _ typ),Just (L loc ref)) ->
|
||||||
chIn loc "reference linearization of" $ do
|
chIn loc "reference linearization of" $ do
|
||||||
(ref,_) <- checkLType gr [] ref (mkFunType [typ] typeStr)
|
(ref,_) <- checkLType gr [] ref (mkFunType [typ] typeStr)
|
||||||
return (Just (L loc ref))
|
return (Just (L loc ref))
|
||||||
_ -> return Nothing
|
_ -> return Nothing
|
||||||
mpr <- case mpr of
|
mpr <- case mpr of
|
||||||
(Just (L loc t)) ->
|
(Just (L loc t)) ->
|
||||||
chIn loc "print name of" $ do
|
chIn loc "print name of" $ do
|
||||||
(t,_) <- checkLType gr [] t typeStr
|
(t,_) <- checkLType gr [] t typeStr
|
||||||
return (Just (L loc t))
|
return (Just (L loc t))
|
||||||
@@ -212,13 +212,13 @@ checkInfo opts cwd sgr (m,mo) c info = checkInModule cwd mo NoLoc empty $ do
|
|||||||
|
|
||||||
CncFun mty mt mpr mpmcfg -> do
|
CncFun mty mt mpr mpmcfg -> do
|
||||||
mt <- case (mty,mt) of
|
mt <- case (mty,mt) of
|
||||||
(Just (cat,cont,val),Just (L loc trm)) ->
|
(Just (cat,cont,val),Just (L loc trm)) ->
|
||||||
chIn loc "linearization of" $ do
|
chIn loc "linearization of" $ do
|
||||||
(trm,_) <- checkLType gr [] trm (mkFunType (map (\(_,_,ty) -> ty) cont) val) -- erases arg vars
|
(trm,_) <- checkLType gr [] trm (mkFunType (map (\(_,_,ty) -> ty) cont) val) -- erases arg vars
|
||||||
return (Just (L loc trm))
|
return (Just (L loc trm))
|
||||||
_ -> return mt
|
_ -> return mt
|
||||||
mpr <- case mpr of
|
mpr <- case mpr of
|
||||||
(Just (L loc t)) ->
|
(Just (L loc t)) ->
|
||||||
chIn loc "print name of" $ do
|
chIn loc "print name of" $ do
|
||||||
(t,_) <- checkLType gr [] t typeStr
|
(t,_) <- checkLType gr [] t typeStr
|
||||||
return (Just (L loc t))
|
return (Just (L loc t))
|
||||||
@@ -251,16 +251,16 @@ checkInfo opts cwd sgr (m,mo) c info = checkInModule cwd mo NoLoc empty $ do
|
|||||||
ResOverload os tysts -> chIn NoLoc "overloading" $ do
|
ResOverload os tysts -> chIn NoLoc "overloading" $ do
|
||||||
tysts' <- mapM (uncurry $ flip (\(L loc1 t) (L loc2 ty) -> checkLType gr [] t ty >>= \(t,ty) -> return (L loc1 t, L loc2 ty))) tysts -- return explicit ones
|
tysts' <- mapM (uncurry $ flip (\(L loc1 t) (L loc2 ty) -> checkLType gr [] t ty >>= \(t,ty) -> return (L loc1 t, L loc2 ty))) tysts -- return explicit ones
|
||||||
tysts0 <- lookupOverload gr (m,c) -- check against inherited ones too
|
tysts0 <- lookupOverload gr (m,c) -- check against inherited ones too
|
||||||
tysts1 <- mapM (uncurry $ flip (checkLType gr []))
|
tysts1 <- mapM (uncurry $ flip (checkLType gr []))
|
||||||
[(mkFunType args val,tr) | (args,(val,tr)) <- tysts0]
|
[(mkFunType args val,tr) | (args,(val,tr)) <- tysts0]
|
||||||
--- this can only be a partial guarantee, since matching
|
--- this can only be a partial guarantee, since matching
|
||||||
--- with value type is only possible if expected type is given
|
--- with value type is only possible if expected type is given
|
||||||
checkUniq $
|
checkUniq $
|
||||||
sort [let (xs,t) = typeFormCnc x in t : map (\(b,x,t) -> t) xs | (_,x) <- tysts1]
|
sort [let (xs,t) = typeFormCnc x in t : map (\(b,x,t) -> t) xs | (_,x) <- tysts1]
|
||||||
return (ResOverload os [(y,x) | (x,y) <- tysts'])
|
return (ResOverload os [(y,x) | (x,y) <- tysts'])
|
||||||
|
|
||||||
ResParam (Just (L loc pcs)) _ -> do
|
ResParam (Just (L loc pcs)) _ -> do
|
||||||
ts <- chIn loc "parameter type" $
|
ts <- chIn loc "parameter type" $
|
||||||
liftM concat $ mapM mkPar pcs
|
liftM concat $ mapM mkPar pcs
|
||||||
return (ResParam (Just (L loc pcs)) (Just ts))
|
return (ResParam (Just (L loc pcs)) (Just ts))
|
||||||
|
|
||||||
@@ -274,9 +274,9 @@ checkInfo opts cwd sgr (m,mo) c info = checkInModule cwd mo NoLoc empty $ do
|
|||||||
return $ map (mkApp (QC (m,f))) vs
|
return $ map (mkApp (QC (m,f))) vs
|
||||||
|
|
||||||
checkUniq xss = case xss of
|
checkUniq xss = case xss of
|
||||||
x:y:xs
|
x:y:xs
|
||||||
| x == y -> checkError $ "ambiguous for type" <+>
|
| x == y -> checkError $ "ambiguous for type" <+>
|
||||||
ppType (mkFunType (tail x) (head x))
|
ppType (mkFunType (tail x) (head x))
|
||||||
| otherwise -> checkUniq $ y:xs
|
| otherwise -> checkUniq $ y:xs
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ checkInfo opts cwd sgr (m,mo) c info = checkInModule cwd mo NoLoc empty $ do
|
|||||||
t' <- compAbsTyp ((x,Vr x):g) t
|
t' <- compAbsTyp ((x,Vr x):g) t
|
||||||
return $ Prod b x a' t'
|
return $ Prod b x a' t'
|
||||||
Abs _ _ _ -> return t
|
Abs _ _ _ -> return t
|
||||||
_ -> composOp (compAbsTyp g) t
|
_ -> composOp (compAbsTyp g) t
|
||||||
|
|
||||||
|
|
||||||
-- | for grammars obtained otherwise than by parsing ---- update!!
|
-- | for grammars obtained otherwise than by parsing ---- update!!
|
||||||
@@ -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 $$
|
||||||
|
|||||||
@@ -1,3 +1,590 @@
|
|||||||
module GF.Compile.Compute.Concrete{-(module M)-} where
|
-- | Functions for computing the values of terms in the concrete syntax, in
|
||||||
--import GF.Compile.Compute.ConcreteLazy as M -- New
|
-- | preparation for PMCFG generation.
|
||||||
--import GF.Compile.Compute.ConcreteStrict as M -- Old, inefficient
|
module GF.Compile.Compute.Concrete
|
||||||
|
(GlobalEnv, GLocation, resourceValues, geLoc, geGrammar,
|
||||||
|
normalForm,
|
||||||
|
Value(..), Bind(..), Env, value2term, eval, vapply
|
||||||
|
) where
|
||||||
|
import Prelude hiding ((<>)) -- GHC 8.4.1 clash with Text.PrettyPrint
|
||||||
|
|
||||||
|
import GF.Grammar hiding (Env, VGen, VApp, VRecType)
|
||||||
|
import GF.Grammar.Lookup(lookupResDefLoc,allParamValues)
|
||||||
|
import GF.Grammar.Predef(cPredef,cErrorType,cTok,cStr,cTrace,cPBool)
|
||||||
|
import GF.Grammar.PatternMatch(matchPattern,measurePatt)
|
||||||
|
import GF.Grammar.Lockfield(isLockLabel,lockRecType) --unlockRecord,lockLabel
|
||||||
|
import GF.Compile.Compute.Value hiding (Error)
|
||||||
|
import GF.Compile.Compute.Predef(predef,predefName,delta)
|
||||||
|
import GF.Data.Str(Str,glueStr,str2strings,str,sstr,plusStr,strTok)
|
||||||
|
import GF.Data.Operations(Err,err,errIn,maybeErr,mapPairsM)
|
||||||
|
import GF.Data.Utilities(mapFst,mapSnd)
|
||||||
|
import GF.Infra.Option
|
||||||
|
import Control.Monad(ap,liftM,liftM2) -- ,unless,mplus
|
||||||
|
import Data.List (findIndex,intersect,nub,elemIndex,(\\)) --,isInfixOf
|
||||||
|
--import Data.Char (isUpper,toUpper,toLower)
|
||||||
|
import GF.Text.Pretty
|
||||||
|
import qualified Data.Map as Map
|
||||||
|
import Debug.Trace(trace)
|
||||||
|
|
||||||
|
-- * Main entry points
|
||||||
|
|
||||||
|
normalForm :: GlobalEnv -> L Ident -> Term -> Term
|
||||||
|
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
|
||||||
|
v <- eval env [] t
|
||||||
|
return (value2term loc [] v)
|
||||||
|
-- Old value2term error message:
|
||||||
|
-- Left i -> fail ("variable #"++show i++" is out of scope")
|
||||||
|
|
||||||
|
eval :: GlobalEnv -> Env -> Term -> Err Value
|
||||||
|
eval (GE gr rvs opts loc) env t = ($ (map snd env)) # value cenv t
|
||||||
|
where
|
||||||
|
cenv = CE gr rvs opts loc (map fst env)
|
||||||
|
|
||||||
|
--apply env = apply' env
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- * Environments
|
||||||
|
|
||||||
|
type ResourceValues = Map.Map ModuleName (Map.Map Ident (Err Value))
|
||||||
|
|
||||||
|
data GlobalEnv = GE Grammar ResourceValues Options GLocation
|
||||||
|
data CompleteEnv = CE {srcgr::Grammar,rvs::ResourceValues,
|
||||||
|
opts::Options,
|
||||||
|
gloc::GLocation,local::LocalScope}
|
||||||
|
type GLocation = L Ident
|
||||||
|
type LocalScope = [Ident]
|
||||||
|
type Stack = [Value]
|
||||||
|
type OpenValue = Stack->Value
|
||||||
|
|
||||||
|
geLoc (GE _ _ _ loc) = loc
|
||||||
|
geGrammar (GE gr _ _ _) = gr
|
||||||
|
|
||||||
|
ext b env = env{local=b:local env}
|
||||||
|
extend bs env = env{local=bs++local env}
|
||||||
|
global env = GE (srcgr env) (rvs env) (opts env) (gloc env)
|
||||||
|
|
||||||
|
var :: CompleteEnv -> Ident -> Err OpenValue
|
||||||
|
var env x = maybe unbound pick' (elemIndex x (local env))
|
||||||
|
where
|
||||||
|
unbound = fail ("Unknown variable: "++showIdent x)
|
||||||
|
pick' i = return $ \ vs -> maybe (err i vs) ok (pick i vs)
|
||||||
|
err i vs = bug $ "Stack problem: "++showIdent x++": "
|
||||||
|
++unwords (map showIdent (local env))
|
||||||
|
++" => "++show (i,length vs)
|
||||||
|
ok v = --trace ("var "++show x++" = "++show v) $
|
||||||
|
v
|
||||||
|
|
||||||
|
pick :: Int -> Stack -> Maybe Value
|
||||||
|
pick 0 (v:_) = Just v
|
||||||
|
pick i (_:vs) = pick (i-1) vs
|
||||||
|
pick i vs = Nothing -- bug $ "pick "++show (i,vs)
|
||||||
|
|
||||||
|
resource env (m,c) =
|
||||||
|
-- err bug id $
|
||||||
|
if isPredefCat c
|
||||||
|
then value0 env =<< lockRecType c defLinType -- hmm
|
||||||
|
else maybe e id $ Map.lookup c =<< Map.lookup m (rvs env)
|
||||||
|
where e = fail $ "Not found: "++render m++"."++showIdent c
|
||||||
|
|
||||||
|
-- | Convert operators once, not every time they are looked up
|
||||||
|
resourceValues :: Options -> SourceGrammar -> GlobalEnv
|
||||||
|
resourceValues opts gr = env
|
||||||
|
where
|
||||||
|
env = GE gr rvs opts (L NoLoc identW)
|
||||||
|
rvs = Map.mapWithKey moduleResources (moduleMap gr)
|
||||||
|
moduleResources m = Map.mapWithKey (moduleResource m) . jments
|
||||||
|
moduleResource m c _info = do L l t <- lookupResDefLoc gr (m,c)
|
||||||
|
let loc = L l c
|
||||||
|
qloc = L l (Q (m,c))
|
||||||
|
eval (GE gr rvs opts loc) [] (traceRes qloc t)
|
||||||
|
|
||||||
|
traceRes = if flag optTrace opts
|
||||||
|
then traceResource
|
||||||
|
else const id
|
||||||
|
|
||||||
|
-- * Tracing
|
||||||
|
|
||||||
|
-- | Insert a call to the trace function under the top-level lambdas
|
||||||
|
traceResource (L l q) t =
|
||||||
|
case termFormCnc t of
|
||||||
|
(abs,body) -> mkAbs abs (mkApp traceQ [args,body])
|
||||||
|
where
|
||||||
|
args = R $ tuple2record (K lstr:[Vr x|(bt,x)<-abs,bt==Explicit])
|
||||||
|
lstr = render (l<>":"<>ppTerm Qualified 0 q)
|
||||||
|
traceQ = Q (cPredef,cTrace)
|
||||||
|
|
||||||
|
-- * Computing values
|
||||||
|
|
||||||
|
-- | Computing the value of a top-level term
|
||||||
|
value0 :: CompleteEnv -> Term -> Err Value
|
||||||
|
value0 env = eval (global env) []
|
||||||
|
|
||||||
|
-- | Computing the value of a term
|
||||||
|
value :: CompleteEnv -> Term -> Err OpenValue
|
||||||
|
value env t0 =
|
||||||
|
-- Each terms is traversed only once by this function, using only statically
|
||||||
|
-- available information. Notably, the values of lambda bound variables
|
||||||
|
-- will be unknown during the term traversal phase.
|
||||||
|
-- The result is an OpenValue, which is a function that may be applied many
|
||||||
|
-- times to different dynamic values, but without the term traversal overhead
|
||||||
|
-- and without recomputing other statically known information.
|
||||||
|
-- For this to work, there should be no recursive calls under lambdas here.
|
||||||
|
-- Whenever we need to construct the OpenValue function with an explicit
|
||||||
|
-- lambda, we have to lift the recursive calls outside the lambda.
|
||||||
|
-- (See e.g. the rules for Let, Prod and Abs)
|
||||||
|
{-
|
||||||
|
trace (render $ text "value"<+>sep [ppL (gloc env)<>text ":",
|
||||||
|
brackets (fsep (map ppIdent (local env))),
|
||||||
|
ppTerm Unqualified 10 t0]) $
|
||||||
|
--}
|
||||||
|
errIn (render t0) $
|
||||||
|
case t0 of
|
||||||
|
Vr x -> var env x
|
||||||
|
Q x@(m,f)
|
||||||
|
| m == cPredef -> if f==cErrorType -- to be removed
|
||||||
|
then let p = identS "P"
|
||||||
|
in const # value0 env (mkProd [(Implicit,p,typeType)] (Vr p) [])
|
||||||
|
else if f==cPBool
|
||||||
|
then const # resource env x
|
||||||
|
else const . flip VApp [] # predef f
|
||||||
|
| otherwise -> const # resource env x --valueResDef (fst env) x
|
||||||
|
QC x -> return $ const (VCApp x [])
|
||||||
|
App e1 e2 -> apply' env e1 . (:[]) =<< value env e2
|
||||||
|
Let (x,(oty,t)) body -> do vb <- value (ext x env) body
|
||||||
|
vt <- value env t
|
||||||
|
return $ \ vs -> vb (vt vs:vs)
|
||||||
|
Meta i -> return $ \ vs -> VMeta i (zip (local env) vs) []
|
||||||
|
Prod bt x t1 t2 ->
|
||||||
|
do vt1 <- value env t1
|
||||||
|
vt2 <- value (ext x env) t2
|
||||||
|
return $ \ vs -> VProd bt (vt1 vs) x $ Bind $ \ vx -> vt2 (vx:vs)
|
||||||
|
Abs bt x t -> do vt <- value (ext x env) t
|
||||||
|
return $ VAbs bt x . Bind . \ vs vx -> vt (vx:vs)
|
||||||
|
EInt n -> return $ const (VInt n)
|
||||||
|
EFloat f -> return $ const (VFloat f)
|
||||||
|
K s -> return $ const (VString s)
|
||||||
|
Empty -> return $ const (VString "")
|
||||||
|
Sort s | s == cTok -> return $ const (VSort cStr) -- to be removed
|
||||||
|
| otherwise -> return $ const (VSort s)
|
||||||
|
ImplArg t -> (VImplArg.) # value env t
|
||||||
|
Table p res -> liftM2 VTblType # value env p <# value env res
|
||||||
|
RecType rs -> do lovs <- mapPairsM (value env) rs
|
||||||
|
return $ \vs->VRecType $ mapSnd ($vs) lovs
|
||||||
|
t@(ExtR t1 t2) -> ((extR t.)# both id) # both (value env) (t1,t2)
|
||||||
|
FV ts -> ((vfv .) # sequence) # mapM (value env) ts
|
||||||
|
R as -> do lovs <- mapPairsM (value env.snd) as
|
||||||
|
return $ \ vs->VRec $ mapSnd ($vs) lovs
|
||||||
|
T i cs -> valueTable env i cs
|
||||||
|
V ty ts -> do pvs <- paramValues env ty
|
||||||
|
((VV ty pvs .) . sequence) # mapM (value env) ts
|
||||||
|
C t1 t2 -> ((ok2p vconcat.) # both id) # both (value env) (t1,t2)
|
||||||
|
S t1 t2 -> ((select env.) # both id) # both (value env) (t1,t2)
|
||||||
|
P t l -> --maybe (bug $ "project "++show l++" from "++show v) id $
|
||||||
|
do ov <- value env t
|
||||||
|
return $ \ vs -> let v = ov vs
|
||||||
|
in maybe (VP v l) id (proj l v)
|
||||||
|
Alts t tts -> (\v vts -> VAlts # v <# mapM (both id) vts) # value env t <# mapM (both (value env)) tts
|
||||||
|
Strs ts -> ((VStrs.) # sequence) # mapM (value env) ts
|
||||||
|
Glue t1 t2 -> ((ok2p (glue env).) # both id) # both (value env) (t1,t2)
|
||||||
|
ELin c r -> (unlockVRec (gloc env) c.) # value env r
|
||||||
|
EPatt p -> return $ const (VPatt p) -- hmm
|
||||||
|
EPattType ty -> do vt <- value env ty
|
||||||
|
return (VPattType . vt)
|
||||||
|
Typed t ty -> value env t
|
||||||
|
t -> fail.render $ "value"<+>ppTerm Unqualified 10 t $$ show t
|
||||||
|
|
||||||
|
vconcat vv@(v1,v2) =
|
||||||
|
case vv of
|
||||||
|
(VString "",_) -> v2
|
||||||
|
(_,VString "") -> v1
|
||||||
|
(VApp NonExist _,_) -> v1
|
||||||
|
(_,VApp NonExist _) -> v2
|
||||||
|
_ -> VC v1 v2
|
||||||
|
|
||||||
|
proj l v | isLockLabel l = return (VRec [])
|
||||||
|
---- a workaround 18/2/2005: take this away and find the reason
|
||||||
|
---- why earlier compilation destroys the lock field
|
||||||
|
proj l v =
|
||||||
|
case v of
|
||||||
|
VFV vs -> liftM vfv (mapM (proj l) vs)
|
||||||
|
VRec rs -> lookup l rs
|
||||||
|
-- VExtR v1 v2 -> proj l v2 `mplus` proj l v1 -- hmm
|
||||||
|
VS (VV pty pvs rs) v2 -> flip VS v2 . VV pty pvs # mapM (proj l) rs
|
||||||
|
_ -> return (ok1 VP v l)
|
||||||
|
|
||||||
|
ok1 f v1@(VError {}) _ = v1
|
||||||
|
ok1 f v1 v2 = f v1 v2
|
||||||
|
|
||||||
|
ok2 f v1@(VError {}) _ = v1
|
||||||
|
ok2 f _ v2@(VError {}) = v2
|
||||||
|
ok2 f v1 v2 = f v1 v2
|
||||||
|
|
||||||
|
ok2p f (v1@VError {},_) = v1
|
||||||
|
ok2p f (_,v2@VError {}) = v2
|
||||||
|
ok2p f vv = f vv
|
||||||
|
|
||||||
|
unlockVRec loc c0 v0 = v0
|
||||||
|
{-
|
||||||
|
unlockVRec loc c0 v0 = unlockVRec' c0 v0
|
||||||
|
where
|
||||||
|
unlockVRec' ::Ident -> Value -> Value
|
||||||
|
unlockVRec' c v =
|
||||||
|
case v of
|
||||||
|
-- VClosure env t -> err bug (VClosure env) (unlockRecord c t)
|
||||||
|
VAbs bt x (Bind f) -> VAbs bt x (Bind $ \ v -> unlockVRec' c (f v))
|
||||||
|
VRec rs -> plusVRec rs lock
|
||||||
|
-- _ -> VExtR v (VRec lock) -- hmm
|
||||||
|
_ -> {-trace (render $ ppL loc $ "unlock non-record "++show v0)-} v -- hmm
|
||||||
|
-- _ -> bugloc loc $ "unlock non-record "++show v0
|
||||||
|
where
|
||||||
|
lock = [(lockLabel c,VRec [])]
|
||||||
|
-}
|
||||||
|
|
||||||
|
-- suspicious, but backwards compatible
|
||||||
|
plusVRec rs1 rs2 = VRec ([(l,v)|(l,v)<-rs1,l `notElem` ls2] ++ rs2)
|
||||||
|
where ls2 = map fst rs2
|
||||||
|
|
||||||
|
extR t vv =
|
||||||
|
case vv of
|
||||||
|
(VFV vs,v2) -> vfv [extR t (v1,v2)|v1<-vs]
|
||||||
|
(v1,VFV vs) -> vfv [extR t (v1,v2)|v2<-vs]
|
||||||
|
(VRecType rs1, VRecType rs2) ->
|
||||||
|
case intersect (map fst rs1) (map fst rs2) of
|
||||||
|
[] -> VRecType (rs1 ++ rs2)
|
||||||
|
ls -> error $ "clash"<+>show ls
|
||||||
|
(VRec rs1, VRec rs2) -> plusVRec rs1 rs2
|
||||||
|
(v1 , VRec [(l,_)]) | isLockLabel l -> v1 -- hmm
|
||||||
|
(VS (VV t pvs vs) s,v2) -> VS (VV t pvs [extR t (v1,v2)|v1<-vs]) s
|
||||||
|
-- (v1,v2) -> ok2 VExtR v1 v2 -- hmm
|
||||||
|
(v1,v2) -> error $ "not records" $$ show v1 $$ show v2
|
||||||
|
where
|
||||||
|
error explain = ppbug $ "The term" <+> t
|
||||||
|
<+> "is not reducible" $$ explain
|
||||||
|
|
||||||
|
glue env (v1,v2) = glu v1 v2
|
||||||
|
where
|
||||||
|
glu v1 v2 =
|
||||||
|
case (v1,v2) of
|
||||||
|
(VFV vs,v2) -> vfv [glu v1 v2|v1<-vs]
|
||||||
|
(v1,VFV vs) -> vfv [glu v1 v2|v2<-vs]
|
||||||
|
(VString s1,VString s2) -> VString (s1++s2)
|
||||||
|
(v1,VAlts d vs) -> VAlts (glx d) [(glx v,c) | (v,c) <- vs]
|
||||||
|
where glx v2 = glu v1 v2
|
||||||
|
(v1@(VAlts {}),v2) ->
|
||||||
|
--err (const (ok2 VGlue v1 v2)) id $
|
||||||
|
err bug id $
|
||||||
|
do y' <- strsFromValue v2
|
||||||
|
x' <- strsFromValue v1
|
||||||
|
return $ vfv [foldr1 VC (map VString (str2strings (glueStr v u))) | v <- x', u <- y']
|
||||||
|
(VC va vb,v2) -> VC va (glu vb v2)
|
||||||
|
(v1,VC va vb) -> VC (glu v1 va) vb
|
||||||
|
(VS (VV ty pvs vs) vb,v2) -> VS (VV ty pvs [glu v v2|v<-vs]) vb
|
||||||
|
(v1,VS (VV ty pvs vs) vb) -> VS (VV ty pvs [glu v1 v|v<-vs]) vb
|
||||||
|
(v1@(VApp NonExist _),_) -> v1
|
||||||
|
(_,v2@(VApp NonExist _)) -> v2
|
||||||
|
-- (v1,v2) -> ok2 VGlue v1 v2
|
||||||
|
(v1,v2) -> if flag optPlusAsBind (opts env)
|
||||||
|
then VC v1 (VC (VApp BIND []) v2)
|
||||||
|
else let loc = gloc env
|
||||||
|
vt v = value2term loc (local env) v
|
||||||
|
-- Old value2term error message:
|
||||||
|
-- Left i -> Error ('#':show i)
|
||||||
|
originalMsg = render $ ppL loc (hang "unsupported token gluing" 4
|
||||||
|
(Glue (vt v1) (vt v2)))
|
||||||
|
term = render $ pp $ Glue (vt v1) (vt v2)
|
||||||
|
in error $ unlines
|
||||||
|
[originalMsg
|
||||||
|
,""
|
||||||
|
,"There was a problem in the expression `"++term++"`, either:"
|
||||||
|
,"1) You are trying to use + on runtime arguments, possibly via an oper."
|
||||||
|
,"2) One of the arguments in `"++term++"` is a bound variable from pattern matching a string, but the cases are non-exhaustive."
|
||||||
|
,"For more help see https://github.com/GrammaticalFramework/gf-core/tree/master/doc/errors/gluing.md"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
-- | to get a string from a value that represents a sequence of terminals
|
||||||
|
strsFromValue :: Value -> Err [Str]
|
||||||
|
strsFromValue t = case t of
|
||||||
|
VString s -> return [str s]
|
||||||
|
VC s t -> do
|
||||||
|
s' <- strsFromValue s
|
||||||
|
t' <- strsFromValue t
|
||||||
|
return [plusStr x y | x <- s', y <- t']
|
||||||
|
{-
|
||||||
|
VGlue s t -> do
|
||||||
|
s' <- strsFromValue s
|
||||||
|
t' <- strsFromValue t
|
||||||
|
return [glueStr x y | x <- s', y <- t']
|
||||||
|
-}
|
||||||
|
VAlts d vs -> do
|
||||||
|
d0 <- strsFromValue d
|
||||||
|
v0 <- mapM (strsFromValue . fst) vs
|
||||||
|
c0 <- mapM (strsFromValue . snd) vs
|
||||||
|
--let vs' = zip v0 c0
|
||||||
|
return [strTok (str2strings def) vars |
|
||||||
|
def <- d0,
|
||||||
|
vars <- [[(str2strings v, map sstr c) | (v,c) <- zip vv c0] |
|
||||||
|
vv <- sequence v0]
|
||||||
|
]
|
||||||
|
VFV ts -> concat # mapM strsFromValue ts
|
||||||
|
VStrs ts -> concat # mapM strsFromValue ts
|
||||||
|
|
||||||
|
_ -> fail ("cannot get Str from value " ++ show t)
|
||||||
|
|
||||||
|
vfv vs = case nub vs of
|
||||||
|
[v] -> v
|
||||||
|
vs -> VFV vs
|
||||||
|
|
||||||
|
select env vv =
|
||||||
|
case vv of
|
||||||
|
(v1,VFV vs) -> vfv [select env (v1,v2)|v2<-vs]
|
||||||
|
(VFV vs,v2) -> vfv [select env (v1,v2)|v1<-vs]
|
||||||
|
(v1@(VV pty vs rs),v2) ->
|
||||||
|
err (const (VS v1 v2)) id $
|
||||||
|
do --ats <- allParamValues (srcgr env) pty
|
||||||
|
--let vs = map (value0 env) ats
|
||||||
|
i <- maybeErr "no match" $ findIndex (==v2) vs
|
||||||
|
return (ix (gloc env) "select" rs i)
|
||||||
|
(VT _ _ [(PW,Bind b)],_) -> {-trace "eliminate wild card table" $-} b []
|
||||||
|
(v1@(VT _ _ cs),v2) ->
|
||||||
|
err (\_->ok2 VS v1 v2) (err bug id . valueMatch env) $
|
||||||
|
match (gloc env) cs v2
|
||||||
|
(VS (VV pty pvs rs) v12,v2) -> VS (VV pty pvs [select env (v11,v2)|v11<-rs]) v12
|
||||||
|
(v1,v2) -> ok2 VS v1 v2
|
||||||
|
|
||||||
|
match loc cs v =
|
||||||
|
err bad return (matchPattern cs (value2term loc [] v))
|
||||||
|
-- Old value2term error message:
|
||||||
|
-- Left i -> bad ("variable #"++show i++" is out of scope")
|
||||||
|
where
|
||||||
|
bad = fail . ("In pattern matching: "++)
|
||||||
|
|
||||||
|
valueMatch :: CompleteEnv -> (Bind Env,Substitution) -> Err Value
|
||||||
|
valueMatch env (Bind f,env') = f # mapPairsM (value0 env) env'
|
||||||
|
|
||||||
|
valueTable :: CompleteEnv -> TInfo -> [Case] -> Err OpenValue
|
||||||
|
valueTable env i cs =
|
||||||
|
case i of
|
||||||
|
TComp ty -> do pvs <- paramValues env ty
|
||||||
|
((VV ty pvs .) # sequence) # mapM (value env.snd) cs
|
||||||
|
_ -> do ty <- getTableType i
|
||||||
|
cs' <- mapM valueCase cs
|
||||||
|
err (dynamic cs' ty) return (convert cs' ty)
|
||||||
|
where
|
||||||
|
dynamic cs' ty _ = cases cs' # value env ty
|
||||||
|
|
||||||
|
cases cs' vty vs = err keep ($vs) (convertv cs' (vty vs))
|
||||||
|
where
|
||||||
|
keep msg = --trace (msg++"\n"++render (ppTerm Unqualified 0 (T i cs))) $
|
||||||
|
VT wild (vty vs) (mapSnd ($vs) cs')
|
||||||
|
|
||||||
|
wild = case i of TWild _ -> True; _ -> False
|
||||||
|
|
||||||
|
convertv cs' vty =
|
||||||
|
convert' cs' =<< paramValues'' env (value2term (gloc env) [] vty)
|
||||||
|
-- Old value2term error message: Left i -> fail ("variable #"++show i++" is out of scope")
|
||||||
|
|
||||||
|
convert cs' ty = convert' cs' =<< paramValues' env ty
|
||||||
|
|
||||||
|
convert' cs' ((pty,vs),pvs) =
|
||||||
|
do sts <- mapM (matchPattern cs') vs
|
||||||
|
return $ \ vs -> VV pty pvs $ map (err bug id . valueMatch env)
|
||||||
|
(mapFst ($vs) sts)
|
||||||
|
|
||||||
|
valueCase (p,t) = do p' <- measurePatt # inlinePattMacro p
|
||||||
|
pvs <- linPattVars p'
|
||||||
|
vt <- value (extend pvs env) t
|
||||||
|
return (p',\vs-> Bind $ \bs-> vt (push' p' bs pvs vs))
|
||||||
|
|
||||||
|
inlinePattMacro p =
|
||||||
|
case p of
|
||||||
|
PM qc -> do r <- resource env qc
|
||||||
|
case r of
|
||||||
|
VPatt p' -> inlinePattMacro p'
|
||||||
|
_ -> ppbug $ hang "Expected pattern macro:" 4
|
||||||
|
(show r)
|
||||||
|
_ -> composPattOp inlinePattMacro p
|
||||||
|
|
||||||
|
|
||||||
|
paramValues env ty = snd # paramValues' env ty
|
||||||
|
|
||||||
|
paramValues' env ty = paramValues'' env =<< nfx (global env) ty
|
||||||
|
|
||||||
|
paramValues'' env pty = do ats <- allParamValues (srcgr env) pty
|
||||||
|
pvs <- mapM (eval (global env) []) ats
|
||||||
|
return ((pty,ats),pvs)
|
||||||
|
|
||||||
|
push' p bs xs = if length bs/=length xs
|
||||||
|
then bug $ "push "++show (p,bs,xs)
|
||||||
|
else push bs xs
|
||||||
|
|
||||||
|
push :: Env -> LocalScope -> Stack -> Stack
|
||||||
|
push bs [] vs = vs
|
||||||
|
push bs (x:xs) vs = maybe err id (lookup x bs):push bs xs vs
|
||||||
|
where err = bug $ "Unbound pattern variable "++showIdent x
|
||||||
|
|
||||||
|
apply' :: CompleteEnv -> Term -> [OpenValue] -> Err OpenValue
|
||||||
|
apply' env t [] = value env t
|
||||||
|
apply' env t vs =
|
||||||
|
case t of
|
||||||
|
QC x -> return $ \ svs -> VCApp x (map ($svs) vs)
|
||||||
|
{-
|
||||||
|
Q x@(m,f) | m==cPredef -> return $
|
||||||
|
let constr = --trace ("predef "++show x) .
|
||||||
|
VApp x
|
||||||
|
in \ svs -> maybe constr id (Map.lookup f predefs)
|
||||||
|
$ map ($svs) vs
|
||||||
|
| otherwise -> do r <- resource env x
|
||||||
|
return $ \ svs -> vapply (gloc env) r (map ($svs) vs)
|
||||||
|
-}
|
||||||
|
App t1 t2 -> apply' env t1 . (:vs) =<< value env t2
|
||||||
|
_ -> do fv <- value env t
|
||||||
|
return $ \ svs -> vapply (gloc env) (fv svs) (map ($svs) vs)
|
||||||
|
|
||||||
|
vapply :: GLocation -> Value -> [Value] -> Value
|
||||||
|
vapply loc v [] = v
|
||||||
|
vapply loc v vs =
|
||||||
|
case v of
|
||||||
|
VError {} -> v
|
||||||
|
-- VClosure env (Abs b x t) -> beta gr env b x t vs
|
||||||
|
VAbs bt _ (Bind f) -> vbeta loc bt f vs
|
||||||
|
VApp pre vs1 -> delta' pre (vs1++vs)
|
||||||
|
where
|
||||||
|
delta' Trace (v1:v2:vs) = let vr = vapply loc v2 vs
|
||||||
|
in vtrace loc v1 vr
|
||||||
|
delta' pre vs = err msg vfv $ mapM (delta pre) (varyList vs)
|
||||||
|
--msg = const (VApp pre (vs1++vs))
|
||||||
|
msg = bug . (("Applying Predef."++showIdent (predefName pre)++": ")++)
|
||||||
|
VS (VV t pvs fs) s -> VS (VV t pvs [vapply loc f vs|f<-fs]) s
|
||||||
|
VFV fs -> vfv [vapply loc f vs|f<-fs]
|
||||||
|
VCApp f vs0 -> VCApp f (vs0++vs)
|
||||||
|
VMeta i env vs0 -> VMeta i env (vs0++vs)
|
||||||
|
VGen i vs0 -> VGen i (vs0++vs)
|
||||||
|
v -> bug $ "vapply "++show v++" "++show vs
|
||||||
|
|
||||||
|
vbeta loc bt f (v:vs) =
|
||||||
|
case (bt,v) of
|
||||||
|
(Implicit,VImplArg v) -> ap v
|
||||||
|
(Explicit, v) -> ap v
|
||||||
|
where
|
||||||
|
ap (VFV avs) = vfv [vapply loc (f v) vs|v<-avs]
|
||||||
|
ap v = vapply loc (f v) vs
|
||||||
|
|
||||||
|
vary (VFV vs) = vs
|
||||||
|
vary v = [v]
|
||||||
|
varyList = mapM vary
|
||||||
|
|
||||||
|
{-
|
||||||
|
beta env b x t (v:vs) =
|
||||||
|
case (b,v) of
|
||||||
|
(Implicit,VImplArg v) -> apply' (ext (x,v) env) t vs
|
||||||
|
(Explicit, v) -> apply' (ext (x,v) env) t vs
|
||||||
|
-}
|
||||||
|
|
||||||
|
vtrace loc arg res = trace (render (hang (pv arg) 4 ("->"<+>pv res))) res
|
||||||
|
where
|
||||||
|
pv v = case v of
|
||||||
|
VRec (f:as) -> hang (pf f) 4 (fsep (map pa as))
|
||||||
|
_ -> ppV v
|
||||||
|
pf (_,VString n) = pp n
|
||||||
|
pf (_,v) = ppV v
|
||||||
|
pa (_,v) = ppV v
|
||||||
|
ppV v = ppTerm Unqualified 10 (value2term' True loc [] v)
|
||||||
|
-- Old value2term error message:
|
||||||
|
-- Left i -> "variable #" <> pp i <+> "is out of scope"
|
||||||
|
|
||||||
|
-- | Convert a value back to a term
|
||||||
|
value2term :: GLocation -> [Ident] -> Value -> Term
|
||||||
|
value2term = value2term' False
|
||||||
|
|
||||||
|
value2term' :: Bool -> p -> [Ident] -> Value -> Term
|
||||||
|
value2term' stop loc xs v0 =
|
||||||
|
case v0 of
|
||||||
|
VApp pre vs -> applyMany (Q (cPredef,predefName pre)) vs
|
||||||
|
VCApp f vs -> applyMany (QC f) vs
|
||||||
|
VGen j vs -> applyMany (var j) vs
|
||||||
|
VMeta j env vs -> applyMany (Meta j) vs
|
||||||
|
VProd bt v x f -> Prod bt x (v2t v) (v2t' x f)
|
||||||
|
VAbs bt x f -> Abs bt x (v2t' x f)
|
||||||
|
VInt n -> EInt n
|
||||||
|
VFloat f -> EFloat f
|
||||||
|
VString s -> if null s then Empty else K s
|
||||||
|
VSort s -> Sort s
|
||||||
|
VImplArg v -> ImplArg (v2t v)
|
||||||
|
VTblType p res -> Table (v2t p) (v2t res)
|
||||||
|
VRecType rs -> RecType [(l, v2t v) | (l,v) <- rs]
|
||||||
|
VRec as -> R [(l, (Nothing, v2t v)) | (l,v) <- as]
|
||||||
|
VV t _ vs -> V t (map v2t vs)
|
||||||
|
VT wild v cs -> T ((if wild then TWild else TTyped) (v2t v)) (map nfcase cs)
|
||||||
|
VFV vs -> FV (map v2t vs)
|
||||||
|
VC v1 v2 -> C (v2t v1) (v2t v2)
|
||||||
|
VS v1 v2 -> S (v2t v1) (v2t v2)
|
||||||
|
VP v l -> P (v2t v) l
|
||||||
|
VPatt p -> EPatt p
|
||||||
|
VPattType v -> EPattType $ v2t v
|
||||||
|
VAlts v vvs -> Alts (v2t v) [(v2t x, v2t y) | (x,y) <- vvs]
|
||||||
|
VStrs vs -> Strs (map v2t vs)
|
||||||
|
-- VGlue v1 v2 -> Glue (v2t v1) (v2t v2)
|
||||||
|
-- VExtR v1 v2 -> ExtR (v2t v1) (v2t v2)
|
||||||
|
VError err -> Error err
|
||||||
|
where
|
||||||
|
applyMany f vs = foldl App f (map v2t vs)
|
||||||
|
v2t = v2txs xs
|
||||||
|
v2txs = value2term' stop loc
|
||||||
|
v2t' x f = v2txs (x:xs) (bind f (gen xs))
|
||||||
|
|
||||||
|
var j
|
||||||
|
| j<length xs = Vr (reverse xs !! j)
|
||||||
|
| otherwise = error ("variable #"++show j++" is out of scope")
|
||||||
|
|
||||||
|
|
||||||
|
pushs xs e = foldr push e xs
|
||||||
|
push x (env,xs) = ((x,gen xs):env,x:xs)
|
||||||
|
gen xs = VGen (length xs) []
|
||||||
|
|
||||||
|
nfcase (p,f) = (,) p (v2txs xs' (bind f env'))
|
||||||
|
where (env',xs') = pushs (pattVars p) ([],xs)
|
||||||
|
|
||||||
|
bind (Bind f) x = if stop
|
||||||
|
then VSort (identS "...") -- hmm
|
||||||
|
else f x
|
||||||
|
|
||||||
|
|
||||||
|
linPattVars p =
|
||||||
|
if null dups
|
||||||
|
then return pvs
|
||||||
|
else fail.render $ hang "Pattern is not linear. All variable names on the left-hand side must be distinct." 4 (ppPatt Unqualified 0 p)
|
||||||
|
where
|
||||||
|
allpvs = allPattVars p
|
||||||
|
pvs = nub allpvs
|
||||||
|
dups = allpvs \\ pvs
|
||||||
|
|
||||||
|
pattVars = nub . allPattVars
|
||||||
|
allPattVars p =
|
||||||
|
case p of
|
||||||
|
PV i -> [i]
|
||||||
|
PAs i p -> i:allPattVars p
|
||||||
|
_ -> collectPattOp allPattVars p
|
||||||
|
|
||||||
|
---
|
||||||
|
ix loc fn xs i =
|
||||||
|
if i<n
|
||||||
|
then xs !! i
|
||||||
|
else bugloc loc $ "(!!): index too large in "++fn++", "++show i++"<"++show n
|
||||||
|
where n = length xs
|
||||||
|
|
||||||
|
infixl 1 #,<# --,@@
|
||||||
|
|
||||||
|
f # x = fmap f x
|
||||||
|
mf <# mx = ap mf mx
|
||||||
|
--m1 @@ m2 = (m1 =<<) . m2
|
||||||
|
|
||||||
|
both f (x,y) = (,) # f x <# f y
|
||||||
|
|
||||||
|
bugloc loc s = ppbug $ ppL loc s
|
||||||
|
|
||||||
|
bug msg = ppbug msg
|
||||||
|
ppbug doc = error $ render $ hang "Internal error in Compute.Concrete:" 4 doc
|
||||||
|
|||||||
@@ -1,588 +0,0 @@
|
|||||||
-- | Functions for computing the values of terms in the concrete syntax, in
|
|
||||||
-- | preparation for PMCFG generation.
|
|
||||||
module GF.Compile.Compute.ConcreteNew
|
|
||||||
(GlobalEnv, GLocation, resourceValues, geLoc, geGrammar,
|
|
||||||
normalForm,
|
|
||||||
Value(..), Bind(..), Env, value2term, eval, vapply
|
|
||||||
) where
|
|
||||||
import Prelude hiding ((<>)) -- GHC 8.4.1 clash with Text.PrettyPrint
|
|
||||||
|
|
||||||
import GF.Grammar hiding (Env, VGen, VApp, VRecType)
|
|
||||||
import GF.Grammar.Lookup(lookupResDefLoc,allParamValues)
|
|
||||||
import GF.Grammar.Predef(cPredef,cErrorType,cTok,cStr,cTrace,cPBool)
|
|
||||||
import GF.Grammar.PatternMatch(matchPattern,measurePatt)
|
|
||||||
import GF.Grammar.Lockfield(isLockLabel,lockRecType) --unlockRecord,lockLabel
|
|
||||||
import GF.Compile.Compute.Value hiding (Error)
|
|
||||||
import GF.Compile.Compute.Predef(predef,predefName,delta)
|
|
||||||
import GF.Data.Str(Str,glueStr,str2strings,str,sstr,plusStr,strTok)
|
|
||||||
import GF.Data.Operations(Err,err,errIn,maybeErr,mapPairsM)
|
|
||||||
import GF.Data.Utilities(mapFst,mapSnd)
|
|
||||||
import GF.Infra.Option
|
|
||||||
import Control.Monad(ap,liftM,liftM2) -- ,unless,mplus
|
|
||||||
import Data.List (findIndex,intersect,nub,elemIndex,(\\)) --,isInfixOf
|
|
||||||
--import Data.Char (isUpper,toUpper,toLower)
|
|
||||||
import GF.Text.Pretty
|
|
||||||
import qualified Data.Map as Map
|
|
||||||
import Debug.Trace(trace)
|
|
||||||
|
|
||||||
-- * Main entry points
|
|
||||||
|
|
||||||
normalForm :: GlobalEnv -> L Ident -> Term -> Term
|
|
||||||
normalForm (GE gr rv opts _) loc = err (bugloc loc) id . nfx (GE gr rv opts loc)
|
|
||||||
|
|
||||||
nfx env@(GE _ _ _ loc) t = do
|
|
||||||
v <- eval env [] t
|
|
||||||
case value2term loc [] v of
|
|
||||||
Left i -> fail ("variable #"++show i++" is out of scope")
|
|
||||||
Right t -> return t
|
|
||||||
|
|
||||||
eval :: GlobalEnv -> Env -> Term -> Err Value
|
|
||||||
eval (GE gr rvs opts loc) env t = ($ (map snd env)) # value cenv t
|
|
||||||
where
|
|
||||||
cenv = CE gr rvs opts loc (map fst env)
|
|
||||||
|
|
||||||
--apply env = apply' env
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- * Environments
|
|
||||||
|
|
||||||
type ResourceValues = Map.Map ModuleName (Map.Map Ident (Err Value))
|
|
||||||
|
|
||||||
data GlobalEnv = GE Grammar ResourceValues Options GLocation
|
|
||||||
data CompleteEnv = CE {srcgr::Grammar,rvs::ResourceValues,
|
|
||||||
opts::Options,
|
|
||||||
gloc::GLocation,local::LocalScope}
|
|
||||||
type GLocation = L Ident
|
|
||||||
type LocalScope = [Ident]
|
|
||||||
type Stack = [Value]
|
|
||||||
type OpenValue = Stack->Value
|
|
||||||
|
|
||||||
geLoc (GE _ _ _ loc) = loc
|
|
||||||
geGrammar (GE gr _ _ _) = gr
|
|
||||||
|
|
||||||
ext b env = env{local=b:local env}
|
|
||||||
extend bs env = env{local=bs++local env}
|
|
||||||
global env = GE (srcgr env) (rvs env) (opts env) (gloc env)
|
|
||||||
|
|
||||||
var :: CompleteEnv -> Ident -> Err OpenValue
|
|
||||||
var env x = maybe unbound pick' (elemIndex x (local env))
|
|
||||||
where
|
|
||||||
unbound = fail ("Unknown variable: "++showIdent x)
|
|
||||||
pick' i = return $ \ vs -> maybe (err i vs) ok (pick i vs)
|
|
||||||
err i vs = bug $ "Stack problem: "++showIdent x++": "
|
|
||||||
++unwords (map showIdent (local env))
|
|
||||||
++" => "++show (i,length vs)
|
|
||||||
ok v = --trace ("var "++show x++" = "++show v) $
|
|
||||||
v
|
|
||||||
|
|
||||||
pick :: Int -> Stack -> Maybe Value
|
|
||||||
pick 0 (v:_) = Just v
|
|
||||||
pick i (_:vs) = pick (i-1) vs
|
|
||||||
pick i vs = Nothing -- bug $ "pick "++show (i,vs)
|
|
||||||
|
|
||||||
resource env (m,c) =
|
|
||||||
-- err bug id $
|
|
||||||
if isPredefCat c
|
|
||||||
then value0 env =<< lockRecType c defLinType -- hmm
|
|
||||||
else maybe e id $ Map.lookup c =<< Map.lookup m (rvs env)
|
|
||||||
where e = fail $ "Not found: "++render m++"."++showIdent c
|
|
||||||
|
|
||||||
-- | Convert operators once, not every time they are looked up
|
|
||||||
resourceValues :: Options -> SourceGrammar -> GlobalEnv
|
|
||||||
resourceValues opts gr = env
|
|
||||||
where
|
|
||||||
env = GE gr rvs opts (L NoLoc identW)
|
|
||||||
rvs = Map.mapWithKey moduleResources (moduleMap gr)
|
|
||||||
moduleResources m = Map.mapWithKey (moduleResource m) . jments
|
|
||||||
moduleResource m c _info = do L l t <- lookupResDefLoc gr (m,c)
|
|
||||||
let loc = L l c
|
|
||||||
qloc = L l (Q (m,c))
|
|
||||||
eval (GE gr rvs opts loc) [] (traceRes qloc t)
|
|
||||||
|
|
||||||
traceRes = if flag optTrace opts
|
|
||||||
then traceResource
|
|
||||||
else const id
|
|
||||||
|
|
||||||
-- * Tracing
|
|
||||||
|
|
||||||
-- | Insert a call to the trace function under the top-level lambdas
|
|
||||||
traceResource (L l q) t =
|
|
||||||
case termFormCnc t of
|
|
||||||
(abs,body) -> mkAbs abs (mkApp traceQ [args,body])
|
|
||||||
where
|
|
||||||
args = R $ tuple2record (K lstr:[Vr x|(bt,x)<-abs,bt==Explicit])
|
|
||||||
lstr = render (l<>":"<>ppTerm Qualified 0 q)
|
|
||||||
traceQ = Q (cPredef,cTrace)
|
|
||||||
|
|
||||||
-- * Computing values
|
|
||||||
|
|
||||||
-- | Computing the value of a top-level term
|
|
||||||
value0 :: CompleteEnv -> Term -> Err Value
|
|
||||||
value0 env = eval (global env) []
|
|
||||||
|
|
||||||
-- | Computing the value of a term
|
|
||||||
value :: CompleteEnv -> Term -> Err OpenValue
|
|
||||||
value env t0 =
|
|
||||||
-- Each terms is traversed only once by this function, using only statically
|
|
||||||
-- available information. Notably, the values of lambda bound variables
|
|
||||||
-- will be unknown during the term traversal phase.
|
|
||||||
-- The result is an OpenValue, which is a function that may be applied many
|
|
||||||
-- times to different dynamic values, but without the term traversal overhead
|
|
||||||
-- and without recomputing other statically known information.
|
|
||||||
-- For this to work, there should be no recursive calls under lambdas here.
|
|
||||||
-- Whenever we need to construct the OpenValue function with an explicit
|
|
||||||
-- lambda, we have to lift the recursive calls outside the lambda.
|
|
||||||
-- (See e.g. the rules for Let, Prod and Abs)
|
|
||||||
{-
|
|
||||||
trace (render $ text "value"<+>sep [ppL (gloc env)<>text ":",
|
|
||||||
brackets (fsep (map ppIdent (local env))),
|
|
||||||
ppTerm Unqualified 10 t0]) $
|
|
||||||
--}
|
|
||||||
errIn (render t0) $
|
|
||||||
case t0 of
|
|
||||||
Vr x -> var env x
|
|
||||||
Q x@(m,f)
|
|
||||||
| m == cPredef -> if f==cErrorType -- to be removed
|
|
||||||
then let p = identS "P"
|
|
||||||
in const # value0 env (mkProd [(Implicit,p,typeType)] (Vr p) [])
|
|
||||||
else if f==cPBool
|
|
||||||
then const # resource env x
|
|
||||||
else const . flip VApp [] # predef f
|
|
||||||
| otherwise -> const # resource env x --valueResDef (fst env) x
|
|
||||||
QC x -> return $ const (VCApp x [])
|
|
||||||
App e1 e2 -> apply' env e1 . (:[]) =<< value env e2
|
|
||||||
Let (x,(oty,t)) body -> do vb <- value (ext x env) body
|
|
||||||
vt <- value env t
|
|
||||||
return $ \ vs -> vb (vt vs:vs)
|
|
||||||
Meta i -> return $ \ vs -> VMeta i (zip (local env) vs) []
|
|
||||||
Prod bt x t1 t2 ->
|
|
||||||
do vt1 <- value env t1
|
|
||||||
vt2 <- value (ext x env) t2
|
|
||||||
return $ \ vs -> VProd bt (vt1 vs) x $ Bind $ \ vx -> vt2 (vx:vs)
|
|
||||||
Abs bt x t -> do vt <- value (ext x env) t
|
|
||||||
return $ VAbs bt x . Bind . \ vs vx -> vt (vx:vs)
|
|
||||||
EInt n -> return $ const (VInt n)
|
|
||||||
EFloat f -> return $ const (VFloat f)
|
|
||||||
K s -> return $ const (VString s)
|
|
||||||
Empty -> return $ const (VString "")
|
|
||||||
Sort s | s == cTok -> return $ const (VSort cStr) -- to be removed
|
|
||||||
| otherwise -> return $ const (VSort s)
|
|
||||||
ImplArg t -> (VImplArg.) # value env t
|
|
||||||
Table p res -> liftM2 VTblType # value env p <# value env res
|
|
||||||
RecType rs -> do lovs <- mapPairsM (value env) rs
|
|
||||||
return $ \vs->VRecType $ mapSnd ($vs) lovs
|
|
||||||
t@(ExtR t1 t2) -> ((extR t.)# both id) # both (value env) (t1,t2)
|
|
||||||
FV ts -> ((vfv .) # sequence) # mapM (value env) ts
|
|
||||||
R as -> do lovs <- mapPairsM (value env.snd) as
|
|
||||||
return $ \ vs->VRec $ mapSnd ($vs) lovs
|
|
||||||
T i cs -> valueTable env i cs
|
|
||||||
V ty ts -> do pvs <- paramValues env ty
|
|
||||||
((VV ty pvs .) . sequence) # mapM (value env) ts
|
|
||||||
C t1 t2 -> ((ok2p vconcat.) # both id) # both (value env) (t1,t2)
|
|
||||||
S t1 t2 -> ((select env.) # both id) # both (value env) (t1,t2)
|
|
||||||
P t l -> --maybe (bug $ "project "++show l++" from "++show v) id $
|
|
||||||
do ov <- value env t
|
|
||||||
return $ \ vs -> let v = ov vs
|
|
||||||
in maybe (VP v l) id (proj l v)
|
|
||||||
Alts t tts -> (\v vts -> VAlts # v <# mapM (both id) vts) # value env t <# mapM (both (value env)) tts
|
|
||||||
Strs ts -> ((VStrs.) # sequence) # mapM (value env) ts
|
|
||||||
Glue t1 t2 -> ((ok2p (glue env).) # both id) # both (value env) (t1,t2)
|
|
||||||
ELin c r -> (unlockVRec (gloc env) c.) # value env r
|
|
||||||
EPatt p -> return $ const (VPatt p) -- hmm
|
|
||||||
EPattType ty -> do vt <- value env ty
|
|
||||||
return (VPattType . vt)
|
|
||||||
Typed t ty -> value env t
|
|
||||||
t -> fail.render $ "value"<+>ppTerm Unqualified 10 t $$ show t
|
|
||||||
|
|
||||||
vconcat vv@(v1,v2) =
|
|
||||||
case vv of
|
|
||||||
(VString "",_) -> v2
|
|
||||||
(_,VString "") -> v1
|
|
||||||
(VApp NonExist _,_) -> v1
|
|
||||||
(_,VApp NonExist _) -> v2
|
|
||||||
_ -> VC v1 v2
|
|
||||||
|
|
||||||
proj l v | isLockLabel l = return (VRec [])
|
|
||||||
---- a workaround 18/2/2005: take this away and find the reason
|
|
||||||
---- why earlier compilation destroys the lock field
|
|
||||||
proj l v =
|
|
||||||
case v of
|
|
||||||
VFV vs -> liftM vfv (mapM (proj l) vs)
|
|
||||||
VRec rs -> lookup l rs
|
|
||||||
-- VExtR v1 v2 -> proj l v2 `mplus` proj l v1 -- hmm
|
|
||||||
VS (VV pty pvs rs) v2 -> flip VS v2 . VV pty pvs # mapM (proj l) rs
|
|
||||||
_ -> return (ok1 VP v l)
|
|
||||||
|
|
||||||
ok1 f v1@(VError {}) _ = v1
|
|
||||||
ok1 f v1 v2 = f v1 v2
|
|
||||||
|
|
||||||
ok2 f v1@(VError {}) _ = v1
|
|
||||||
ok2 f _ v2@(VError {}) = v2
|
|
||||||
ok2 f v1 v2 = f v1 v2
|
|
||||||
|
|
||||||
ok2p f (v1@VError {},_) = v1
|
|
||||||
ok2p f (_,v2@VError {}) = v2
|
|
||||||
ok2p f vv = f vv
|
|
||||||
|
|
||||||
unlockVRec loc c0 v0 = v0
|
|
||||||
{-
|
|
||||||
unlockVRec loc c0 v0 = unlockVRec' c0 v0
|
|
||||||
where
|
|
||||||
unlockVRec' ::Ident -> Value -> Value
|
|
||||||
unlockVRec' c v =
|
|
||||||
case v of
|
|
||||||
-- VClosure env t -> err bug (VClosure env) (unlockRecord c t)
|
|
||||||
VAbs bt x (Bind f) -> VAbs bt x (Bind $ \ v -> unlockVRec' c (f v))
|
|
||||||
VRec rs -> plusVRec rs lock
|
|
||||||
-- _ -> VExtR v (VRec lock) -- hmm
|
|
||||||
_ -> {-trace (render $ ppL loc $ "unlock non-record "++show v0)-} v -- hmm
|
|
||||||
-- _ -> bugloc loc $ "unlock non-record "++show v0
|
|
||||||
where
|
|
||||||
lock = [(lockLabel c,VRec [])]
|
|
||||||
-}
|
|
||||||
|
|
||||||
-- suspicious, but backwards compatible
|
|
||||||
plusVRec rs1 rs2 = VRec ([(l,v)|(l,v)<-rs1,l `notElem` ls2] ++ rs2)
|
|
||||||
where ls2 = map fst rs2
|
|
||||||
|
|
||||||
extR t vv =
|
|
||||||
case vv of
|
|
||||||
(VFV vs,v2) -> vfv [extR t (v1,v2)|v1<-vs]
|
|
||||||
(v1,VFV vs) -> vfv [extR t (v1,v2)|v2<-vs]
|
|
||||||
(VRecType rs1, VRecType rs2) ->
|
|
||||||
case intersect (map fst rs1) (map fst rs2) of
|
|
||||||
[] -> VRecType (rs1 ++ rs2)
|
|
||||||
ls -> error $ "clash"<+>show ls
|
|
||||||
(VRec rs1, VRec rs2) -> plusVRec rs1 rs2
|
|
||||||
(v1 , VRec [(l,_)]) | isLockLabel l -> v1 -- hmm
|
|
||||||
(VS (VV t pvs vs) s,v2) -> VS (VV t pvs [extR t (v1,v2)|v1<-vs]) s
|
|
||||||
-- (v1,v2) -> ok2 VExtR v1 v2 -- hmm
|
|
||||||
(v1,v2) -> error $ "not records" $$ show v1 $$ show v2
|
|
||||||
where
|
|
||||||
error explain = ppbug $ "The term" <+> t
|
|
||||||
<+> "is not reducible" $$ explain
|
|
||||||
|
|
||||||
glue env (v1,v2) = glu v1 v2
|
|
||||||
where
|
|
||||||
glu v1 v2 =
|
|
||||||
case (v1,v2) of
|
|
||||||
(VFV vs,v2) -> vfv [glu v1 v2|v1<-vs]
|
|
||||||
(v1,VFV vs) -> vfv [glu v1 v2|v2<-vs]
|
|
||||||
(VString s1,VString s2) -> VString (s1++s2)
|
|
||||||
(v1,VAlts d vs) -> VAlts (glx d) [(glx v,c) | (v,c) <- vs]
|
|
||||||
where glx v2 = glu v1 v2
|
|
||||||
(v1@(VAlts {}),v2) ->
|
|
||||||
--err (const (ok2 VGlue v1 v2)) id $
|
|
||||||
err bug id $
|
|
||||||
do y' <- strsFromValue v2
|
|
||||||
x' <- strsFromValue v1
|
|
||||||
return $ vfv [foldr1 VC (map VString (str2strings (glueStr v u))) | v <- x', u <- y']
|
|
||||||
(VC va vb,v2) -> VC va (glu vb v2)
|
|
||||||
(v1,VC va vb) -> VC (glu v1 va) vb
|
|
||||||
(VS (VV ty pvs vs) vb,v2) -> VS (VV ty pvs [glu v v2|v<-vs]) vb
|
|
||||||
(v1,VS (VV ty pvs vs) vb) -> VS (VV ty pvs [glu v1 v|v<-vs]) vb
|
|
||||||
(v1@(VApp NonExist _),_) -> v1
|
|
||||||
(_,v2@(VApp NonExist _)) -> v2
|
|
||||||
-- (v1,v2) -> ok2 VGlue v1 v2
|
|
||||||
(v1,v2) -> if flag optPlusAsBind (opts env)
|
|
||||||
then VC v1 (VC (VApp BIND []) v2)
|
|
||||||
else let loc = gloc env
|
|
||||||
vt v = case value2term loc (local env) v of
|
|
||||||
Left i -> Error ('#':show i)
|
|
||||||
Right t -> t
|
|
||||||
originalMsg = render $ ppL loc (hang "unsupported token gluing" 4
|
|
||||||
(Glue (vt v1) (vt v2)))
|
|
||||||
term = render $ pp $ Glue (vt v1) (vt v2)
|
|
||||||
in error $ unlines
|
|
||||||
[originalMsg
|
|
||||||
,""
|
|
||||||
,"There was a problem in the expression `"++term++"`, either:"
|
|
||||||
,"1) You are trying to use + on runtime arguments, possibly via an oper."
|
|
||||||
,"2) One of the arguments in `"++term++"` is a bound variable from pattern matching a string, but the cases are non-exhaustive."
|
|
||||||
,"For more help see https://github.com/GrammaticalFramework/gf-core/tree/master/doc/errors/gluing.md"
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
-- | to get a string from a value that represents a sequence of terminals
|
|
||||||
strsFromValue :: Value -> Err [Str]
|
|
||||||
strsFromValue t = case t of
|
|
||||||
VString s -> return [str s]
|
|
||||||
VC s t -> do
|
|
||||||
s' <- strsFromValue s
|
|
||||||
t' <- strsFromValue t
|
|
||||||
return [plusStr x y | x <- s', y <- t']
|
|
||||||
{-
|
|
||||||
VGlue s t -> do
|
|
||||||
s' <- strsFromValue s
|
|
||||||
t' <- strsFromValue t
|
|
||||||
return [glueStr x y | x <- s', y <- t']
|
|
||||||
-}
|
|
||||||
VAlts d vs -> do
|
|
||||||
d0 <- strsFromValue d
|
|
||||||
v0 <- mapM (strsFromValue . fst) vs
|
|
||||||
c0 <- mapM (strsFromValue . snd) vs
|
|
||||||
--let vs' = zip v0 c0
|
|
||||||
return [strTok (str2strings def) vars |
|
|
||||||
def <- d0,
|
|
||||||
vars <- [[(str2strings v, map sstr c) | (v,c) <- zip vv c0] |
|
|
||||||
vv <- sequence v0]
|
|
||||||
]
|
|
||||||
VFV ts -> concat # mapM strsFromValue ts
|
|
||||||
VStrs ts -> concat # mapM strsFromValue ts
|
|
||||||
|
|
||||||
_ -> fail ("cannot get Str from value " ++ show t)
|
|
||||||
|
|
||||||
vfv vs = case nub vs of
|
|
||||||
[v] -> v
|
|
||||||
vs -> VFV vs
|
|
||||||
|
|
||||||
select env vv =
|
|
||||||
case vv of
|
|
||||||
(v1,VFV vs) -> vfv [select env (v1,v2)|v2<-vs]
|
|
||||||
(VFV vs,v2) -> vfv [select env (v1,v2)|v1<-vs]
|
|
||||||
(v1@(VV pty vs rs),v2) ->
|
|
||||||
err (const (VS v1 v2)) id $
|
|
||||||
do --ats <- allParamValues (srcgr env) pty
|
|
||||||
--let vs = map (value0 env) ats
|
|
||||||
i <- maybeErr "no match" $ findIndex (==v2) vs
|
|
||||||
return (ix (gloc env) "select" rs i)
|
|
||||||
(VT _ _ [(PW,Bind b)],_) -> {-trace "eliminate wild card table" $-} b []
|
|
||||||
(v1@(VT _ _ cs),v2) ->
|
|
||||||
err (\_->ok2 VS v1 v2) (err bug id . valueMatch env) $
|
|
||||||
match (gloc env) cs v2
|
|
||||||
(VS (VV pty pvs rs) v12,v2) -> VS (VV pty pvs [select env (v11,v2)|v11<-rs]) v12
|
|
||||||
(v1,v2) -> ok2 VS v1 v2
|
|
||||||
|
|
||||||
match loc cs v =
|
|
||||||
case value2term loc [] v of
|
|
||||||
Left i -> bad ("variable #"++show i++" is out of scope")
|
|
||||||
Right t -> err bad return (matchPattern cs t)
|
|
||||||
where
|
|
||||||
bad = fail . ("In pattern matching: "++)
|
|
||||||
|
|
||||||
valueMatch :: CompleteEnv -> (Bind Env,Substitution) -> Err Value
|
|
||||||
valueMatch env (Bind f,env') = f # mapPairsM (value0 env) env'
|
|
||||||
|
|
||||||
valueTable :: CompleteEnv -> TInfo -> [Case] -> Err OpenValue
|
|
||||||
valueTable env i cs =
|
|
||||||
case i of
|
|
||||||
TComp ty -> do pvs <- paramValues env ty
|
|
||||||
((VV ty pvs .) # sequence) # mapM (value env.snd) cs
|
|
||||||
_ -> do ty <- getTableType i
|
|
||||||
cs' <- mapM valueCase cs
|
|
||||||
err (dynamic cs' ty) return (convert cs' ty)
|
|
||||||
where
|
|
||||||
dynamic cs' ty _ = cases cs' # value env ty
|
|
||||||
|
|
||||||
cases cs' vty vs = err keep ($vs) (convertv cs' (vty vs))
|
|
||||||
where
|
|
||||||
keep msg = --trace (msg++"\n"++render (ppTerm Unqualified 0 (T i cs))) $
|
|
||||||
VT wild (vty vs) (mapSnd ($vs) cs')
|
|
||||||
|
|
||||||
wild = case i of TWild _ -> True; _ -> False
|
|
||||||
|
|
||||||
convertv cs' vty =
|
|
||||||
case value2term (gloc env) [] vty of
|
|
||||||
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' ((pty,vs),pvs) =
|
|
||||||
do sts <- mapM (matchPattern cs') vs
|
|
||||||
return $ \ vs -> VV pty pvs $ map (err bug id . valueMatch env)
|
|
||||||
(mapFst ($vs) sts)
|
|
||||||
|
|
||||||
valueCase (p,t) = do p' <- measurePatt # inlinePattMacro p
|
|
||||||
pvs <- linPattVars p'
|
|
||||||
vt <- value (extend pvs env) t
|
|
||||||
return (p',\vs-> Bind $ \bs-> vt (push' p' bs pvs vs))
|
|
||||||
|
|
||||||
inlinePattMacro p =
|
|
||||||
case p of
|
|
||||||
PM qc -> do r <- resource env qc
|
|
||||||
case r of
|
|
||||||
VPatt p' -> inlinePattMacro p'
|
|
||||||
_ -> ppbug $ hang "Expected pattern macro:" 4
|
|
||||||
(show r)
|
|
||||||
_ -> composPattOp inlinePattMacro p
|
|
||||||
|
|
||||||
|
|
||||||
paramValues env ty = snd # paramValues' env ty
|
|
||||||
|
|
||||||
paramValues' env ty = paramValues'' env =<< nfx (global env) ty
|
|
||||||
|
|
||||||
paramValues'' env pty = do ats <- allParamValues (srcgr env) pty
|
|
||||||
pvs <- mapM (eval (global env) []) ats
|
|
||||||
return ((pty,ats),pvs)
|
|
||||||
|
|
||||||
push' p bs xs = if length bs/=length xs
|
|
||||||
then bug $ "push "++show (p,bs,xs)
|
|
||||||
else push bs xs
|
|
||||||
|
|
||||||
push :: Env -> LocalScope -> Stack -> Stack
|
|
||||||
push bs [] vs = vs
|
|
||||||
push bs (x:xs) vs = maybe err id (lookup x bs):push bs xs vs
|
|
||||||
where err = bug $ "Unbound pattern variable "++showIdent x
|
|
||||||
|
|
||||||
apply' :: CompleteEnv -> Term -> [OpenValue] -> Err OpenValue
|
|
||||||
apply' env t [] = value env t
|
|
||||||
apply' env t vs =
|
|
||||||
case t of
|
|
||||||
QC x -> return $ \ svs -> VCApp x (map ($svs) vs)
|
|
||||||
{-
|
|
||||||
Q x@(m,f) | m==cPredef -> return $
|
|
||||||
let constr = --trace ("predef "++show x) .
|
|
||||||
VApp x
|
|
||||||
in \ svs -> maybe constr id (Map.lookup f predefs)
|
|
||||||
$ map ($svs) vs
|
|
||||||
| otherwise -> do r <- resource env x
|
|
||||||
return $ \ svs -> vapply (gloc env) r (map ($svs) vs)
|
|
||||||
-}
|
|
||||||
App t1 t2 -> apply' env t1 . (:vs) =<< value env t2
|
|
||||||
_ -> do fv <- value env t
|
|
||||||
return $ \ svs -> vapply (gloc env) (fv svs) (map ($svs) vs)
|
|
||||||
|
|
||||||
vapply :: GLocation -> Value -> [Value] -> Value
|
|
||||||
vapply loc v [] = v
|
|
||||||
vapply loc v vs =
|
|
||||||
case v of
|
|
||||||
VError {} -> v
|
|
||||||
-- VClosure env (Abs b x t) -> beta gr env b x t vs
|
|
||||||
VAbs bt _ (Bind f) -> vbeta loc bt f vs
|
|
||||||
VApp pre vs1 -> delta' pre (vs1++vs)
|
|
||||||
where
|
|
||||||
delta' Trace (v1:v2:vs) = let vr = vapply loc v2 vs
|
|
||||||
in vtrace loc v1 vr
|
|
||||||
delta' pre vs = err msg vfv $ mapM (delta pre) (varyList vs)
|
|
||||||
--msg = const (VApp pre (vs1++vs))
|
|
||||||
msg = bug . (("Applying Predef."++showIdent (predefName pre)++": ")++)
|
|
||||||
VS (VV t pvs fs) s -> VS (VV t pvs [vapply loc f vs|f<-fs]) s
|
|
||||||
VFV fs -> vfv [vapply loc f vs|f<-fs]
|
|
||||||
VCApp f vs0 -> VCApp f (vs0++vs)
|
|
||||||
VMeta i env vs0 -> VMeta i env (vs0++vs)
|
|
||||||
VGen i vs0 -> VGen i (vs0++vs)
|
|
||||||
v -> bug $ "vapply "++show v++" "++show vs
|
|
||||||
|
|
||||||
vbeta loc bt f (v:vs) =
|
|
||||||
case (bt,v) of
|
|
||||||
(Implicit,VImplArg v) -> ap v
|
|
||||||
(Explicit, v) -> ap v
|
|
||||||
where
|
|
||||||
ap (VFV avs) = vfv [vapply loc (f v) vs|v<-avs]
|
|
||||||
ap v = vapply loc (f v) vs
|
|
||||||
|
|
||||||
vary (VFV vs) = vs
|
|
||||||
vary v = [v]
|
|
||||||
varyList = mapM vary
|
|
||||||
|
|
||||||
{-
|
|
||||||
beta env b x t (v:vs) =
|
|
||||||
case (b,v) of
|
|
||||||
(Implicit,VImplArg v) -> apply' (ext (x,v) env) t vs
|
|
||||||
(Explicit, v) -> apply' (ext (x,v) env) t vs
|
|
||||||
-}
|
|
||||||
|
|
||||||
vtrace loc arg res = trace (render (hang (pv arg) 4 ("->"<+>pv res))) res
|
|
||||||
where
|
|
||||||
pv v = case v of
|
|
||||||
VRec (f:as) -> hang (pf f) 4 (fsep (map pa as))
|
|
||||||
_ -> ppV v
|
|
||||||
pf (_,VString n) = pp n
|
|
||||||
pf (_,v) = ppV v
|
|
||||||
pa (_,v) = ppV v
|
|
||||||
ppV v = case value2term' True loc [] v of
|
|
||||||
Left i -> "variable #" <> pp i <+> "is out of scope"
|
|
||||||
Right t -> ppTerm Unqualified 10 t
|
|
||||||
|
|
||||||
-- | Convert a value back to a term
|
|
||||||
value2term :: GLocation -> [Ident] -> Value -> Either Int Term
|
|
||||||
value2term = value2term' False
|
|
||||||
value2term' stop loc xs v0 =
|
|
||||||
case v0 of
|
|
||||||
VApp pre vs -> liftM (foldl App (Q (cPredef,predefName pre))) (mapM v2t vs)
|
|
||||||
VCApp f vs -> liftM (foldl App (QC f)) (mapM v2t vs)
|
|
||||||
VGen j vs -> liftM2 (foldl App) (var j) (mapM v2t vs)
|
|
||||||
VMeta j env vs -> liftM (foldl App (Meta j)) (mapM v2t vs)
|
|
||||||
VProd bt v x f -> liftM2 (Prod bt x) (v2t v) (v2t' x f)
|
|
||||||
VAbs bt x f -> liftM (Abs bt x) (v2t' x f)
|
|
||||||
VInt n -> return (EInt n)
|
|
||||||
VFloat f -> return (EFloat f)
|
|
||||||
VString s -> return (if null s then Empty else K s)
|
|
||||||
VSort s -> return (Sort s)
|
|
||||||
VImplArg v -> liftM ImplArg (v2t v)
|
|
||||||
VTblType p res -> liftM2 Table (v2t p) (v2t res)
|
|
||||||
VRecType rs -> liftM RecType (mapM (\(l,v) -> fmap ((,) l) (v2t v)) rs)
|
|
||||||
VRec as -> liftM R (mapM (\(l,v) -> v2t v >>= \t -> return (l,(Nothing,t))) as)
|
|
||||||
VV t _ vs -> liftM (V t) (mapM v2t vs)
|
|
||||||
VT wild v cs -> v2t v >>= \t -> liftM (T ((if wild then TWild else TTyped) t)) (mapM nfcase cs)
|
|
||||||
VFV vs -> liftM FV (mapM v2t vs)
|
|
||||||
VC v1 v2 -> liftM2 C (v2t v1) (v2t v2)
|
|
||||||
VS v1 v2 -> liftM2 S (v2t v1) (v2t v2)
|
|
||||||
VP v l -> v2t v >>= \t -> return (P t l)
|
|
||||||
VPatt p -> return (EPatt p)
|
|
||||||
VPattType v -> v2t v >>= return . EPattType
|
|
||||||
VAlts v vvs -> liftM2 Alts (v2t v) (mapM (\(x,y) -> liftM2 (,) (v2t x) (v2t y)) vvs)
|
|
||||||
VStrs vs -> liftM Strs (mapM v2t vs)
|
|
||||||
-- VGlue v1 v2 -> Glue (v2t v1) (v2t v2)
|
|
||||||
-- VExtR v1 v2 -> ExtR (v2t v1) (v2t v2)
|
|
||||||
VError err -> return (Error err)
|
|
||||||
|
|
||||||
where
|
|
||||||
v2t = v2txs xs
|
|
||||||
v2txs = value2term' stop loc
|
|
||||||
v2t' x f = v2txs (x:xs) (bind f (gen xs))
|
|
||||||
|
|
||||||
var j
|
|
||||||
| j<length xs = Right (Vr (reverse xs !! j))
|
|
||||||
| otherwise = Left j
|
|
||||||
|
|
||||||
|
|
||||||
pushs xs e = foldr push e xs
|
|
||||||
push x (env,xs) = ((x,gen xs):env,x:xs)
|
|
||||||
gen xs = VGen (length xs) []
|
|
||||||
|
|
||||||
nfcase (p,f) = liftM ((,) p) (v2txs xs' (bind f env'))
|
|
||||||
where (env',xs') = pushs (pattVars p) ([],xs)
|
|
||||||
|
|
||||||
bind (Bind f) x = if stop
|
|
||||||
then VSort (identS "...") -- hmm
|
|
||||||
else f x
|
|
||||||
|
|
||||||
|
|
||||||
linPattVars p =
|
|
||||||
if null dups
|
|
||||||
then return pvs
|
|
||||||
else fail.render $ hang "Pattern is not linear. All variable names on the left-hand side must be distinct." 4 (ppPatt Unqualified 0 p)
|
|
||||||
where
|
|
||||||
allpvs = allPattVars p
|
|
||||||
pvs = nub allpvs
|
|
||||||
dups = allpvs \\ pvs
|
|
||||||
|
|
||||||
pattVars = nub . allPattVars
|
|
||||||
allPattVars p =
|
|
||||||
case p of
|
|
||||||
PV i -> [i]
|
|
||||||
PAs i p -> i:allPattVars p
|
|
||||||
_ -> collectPattOp allPattVars p
|
|
||||||
|
|
||||||
---
|
|
||||||
ix loc fn xs i =
|
|
||||||
if i<n
|
|
||||||
then xs !! i
|
|
||||||
else bugloc loc $ "(!!): index too large in "++fn++", "++show i++"<"++show n
|
|
||||||
where n = length xs
|
|
||||||
|
|
||||||
infixl 1 #,<# --,@@
|
|
||||||
|
|
||||||
f # x = fmap f x
|
|
||||||
mf <# mx = ap mf mx
|
|
||||||
--m1 @@ m2 = (m1 =<<) . m2
|
|
||||||
|
|
||||||
both f (x,y) = (,) # f x <# f y
|
|
||||||
|
|
||||||
bugloc loc s = ppbug $ ppL loc s
|
|
||||||
|
|
||||||
bug msg = ppbug msg
|
|
||||||
ppbug doc = error $ render $ hang "Internal error in Compute.ConcreteNew:" 4 doc
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ data Value
|
|||||||
| VGen Int [Value] -- for lambda bound variables, possibly applied
|
| VGen Int [Value] -- for lambda bound variables, possibly applied
|
||||||
| VMeta MetaId Env [Value]
|
| VMeta MetaId Env [Value]
|
||||||
-- -- | VClosure Env Term -- used in Typecheck.ConcreteNew
|
-- -- | VClosure Env Term -- used in Typecheck.ConcreteNew
|
||||||
| VAbs BindType Ident Binding -- used in Compute.ConcreteNew
|
| VAbs BindType Ident Binding -- used in Compute.Concrete
|
||||||
| VProd BindType Value Ident Binding -- used in Compute.ConcreteNew
|
| VProd BindType Value Ident Binding -- used in Compute.Concrete
|
||||||
| VInt Int
|
| VInt Int
|
||||||
| VFloat Double
|
| VFloat Double
|
||||||
| VString String
|
| VString String
|
||||||
@@ -47,10 +47,10 @@ type Env = [(Ident,Value)]
|
|||||||
|
|
||||||
-- | Predefined functions
|
-- | Predefined functions
|
||||||
data Predefined = Drop | Take | Tk | Dp | EqStr | Occur | Occurs | ToUpper
|
data Predefined = Drop | Take | Tk | Dp | EqStr | Occur | Occurs | ToUpper
|
||||||
| ToLower | IsUpper | Length | Plus | EqInt | LessInt
|
| ToLower | IsUpper | Length | Plus | EqInt | LessInt
|
||||||
{- | Show | Read | ToStr | MapStr | EqVal -}
|
{- | Show | Read | ToStr | MapStr | EqVal -}
|
||||||
| Error | Trace
|
| Error | Trace
|
||||||
-- Canonical values below:
|
-- Canonical values below:
|
||||||
| PBool | PFalse | PTrue | Int | Float | Ints | NonExist
|
| PBool | PFalse | PTrue | Int | Float | Ints | NonExist
|
||||||
| BIND | SOFT_BIND | SOFT_SPACE | CAPIT | ALL_CAPIT
|
| BIND | SOFT_BIND | SOFT_SPACE | CAPIT | ALL_CAPIT
|
||||||
deriving (Show,Eq,Ord,Ix,Bounded,Enum)
|
deriving (Show,Eq,Ord,Ix,Bounded,Enum)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import GF.Data.BacktrackM
|
|||||||
import GF.Data.Operations
|
import GF.Data.Operations
|
||||||
import GF.Infra.UseIO (ePutStr,ePutStrLn) -- IOE,
|
import GF.Infra.UseIO (ePutStr,ePutStrLn) -- IOE,
|
||||||
import GF.Data.Utilities (updateNthM) --updateNth
|
import GF.Data.Utilities (updateNthM) --updateNth
|
||||||
import GF.Compile.Compute.ConcreteNew(normalForm,resourceValues)
|
import GF.Compile.Compute.Concrete(normalForm,resourceValues)
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import qualified Data.List as List
|
import qualified Data.List as List
|
||||||
@@ -82,7 +82,7 @@ addPMCFG opts gr cenv opath am cm seqs id (GF.Grammar.CncFun mty@(Just (cat,cont
|
|||||||
(goB b1 CNil [])
|
(goB b1 CNil [])
|
||||||
(pres,pargs)
|
(pres,pargs)
|
||||||
pmcfg = getPMCFG pmcfgEnv1
|
pmcfg = getPMCFG pmcfgEnv1
|
||||||
|
|
||||||
stats = let PMCFG prods funs = pmcfg
|
stats = let PMCFG prods funs = pmcfg
|
||||||
(s,e) = bounds funs
|
(s,e) = bounds funs
|
||||||
!prods_cnt = length prods
|
!prods_cnt = length prods
|
||||||
@@ -103,7 +103,7 @@ addPMCFG opts gr cenv opath am cm seqs id (GF.Grammar.CncFun mty@(Just (cat,cont
|
|||||||
newArgs = map getFIds newArgs'
|
newArgs = map getFIds newArgs'
|
||||||
in addFunction env0 newCat fun newArgs
|
in addFunction env0 newCat fun newArgs
|
||||||
|
|
||||||
addPMCFG opts gr cenv opath am cm seqs id (GF.Grammar.CncCat mty@(Just (L _ lincat))
|
addPMCFG opts gr cenv opath am cm seqs id (GF.Grammar.CncCat mty@(Just (L _ lincat))
|
||||||
mdef@(Just (L loc1 def))
|
mdef@(Just (L loc1 def))
|
||||||
mref@(Just (L loc2 ref))
|
mref@(Just (L loc2 ref))
|
||||||
mprn
|
mprn
|
||||||
@@ -162,7 +162,7 @@ pgfCncCat :: SourceGrammar -> Type -> Int -> CncCat
|
|||||||
pgfCncCat gr lincat index =
|
pgfCncCat gr lincat index =
|
||||||
let ((_,size),schema) = computeCatRange gr lincat
|
let ((_,size),schema) = computeCatRange gr lincat
|
||||||
in PGF.CncCat index (index+size-1)
|
in PGF.CncCat index (index+size-1)
|
||||||
(mkArray (map (renderStyle style{mode=OneLineMode} . ppPath)
|
(mkArray (map (renderStyle style{mode=OneLineMode} . ppPath)
|
||||||
(getStrPaths schema)))
|
(getStrPaths schema)))
|
||||||
where
|
where
|
||||||
getStrPaths :: Schema Identity s c -> [Path]
|
getStrPaths :: Schema Identity s c -> [Path]
|
||||||
@@ -243,7 +243,7 @@ choices nr path = do (args,_) <- get
|
|||||||
| (value,index) <- values])
|
| (value,index) <- values])
|
||||||
descend schema path rpath = bug $ "descend "++show (schema,path,rpath)
|
descend schema path rpath = bug $ "descend "++show (schema,path,rpath)
|
||||||
|
|
||||||
updateEnv path value gr c (args,seq) =
|
updateEnv path value gr c (args,seq) =
|
||||||
case updateNthM (restrictProtoFCat path value) nr args of
|
case updateNthM (restrictProtoFCat path value) nr args of
|
||||||
Just args -> c value (args,seq)
|
Just args -> c value (args,seq)
|
||||||
Nothing -> bug "conflict in updateEnv"
|
Nothing -> bug "conflict in updateEnv"
|
||||||
@@ -606,7 +606,7 @@ restrictProtoFCat path v (PFCat cat f schema) = do
|
|||||||
Just index -> return (CPar (m,[(v,index)]))
|
Just index -> return (CPar (m,[(v,index)]))
|
||||||
Nothing -> mzero
|
Nothing -> mzero
|
||||||
addConstraint CNil v (CStr _) = bug "restrictProtoFCat: string path"
|
addConstraint CNil v (CStr _) = bug "restrictProtoFCat: string path"
|
||||||
|
|
||||||
update k0 f [] = return []
|
update k0 f [] = return []
|
||||||
update k0 f (x@(k,Identity v):xs)
|
update k0 f (x@(k,Identity v):xs)
|
||||||
| k0 == k = do v <- f v
|
| k0 == k = do v <- f v
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import GF.Compile.Compute.Value(Predefined(..))
|
|||||||
import GF.Infra.Ident(ModuleName(..),Ident,ident2raw,rawIdentS,showIdent,isWildIdent)
|
import GF.Infra.Ident(ModuleName(..),Ident,ident2raw,rawIdentS,showIdent,isWildIdent)
|
||||||
import GF.Infra.Option(Options,optionsPGF)
|
import GF.Infra.Option(Options,optionsPGF)
|
||||||
import PGF.Internal(Literal(..))
|
import PGF.Internal(Literal(..))
|
||||||
import GF.Compile.Compute.ConcreteNew(GlobalEnv,normalForm,resourceValues)
|
import GF.Compile.Compute.Concrete(GlobalEnv,normalForm,resourceValues)
|
||||||
import GF.Grammar.Canonical as C
|
import GF.Grammar.Canonical as C
|
||||||
import System.FilePath ((</>), (<.>))
|
import System.FilePath ((</>), (<.>))
|
||||||
import qualified Debug.Trace as T
|
import qualified Debug.Trace as T
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
-- Stability : (stable)
|
-- Stability : (stable)
|
||||||
-- Portability : (portable)
|
-- Portability : (portable)
|
||||||
--
|
--
|
||||||
-- > CVS $Date: 2005/09/16 13:56:13 $
|
-- > CVS $Date: 2005/09/16 13:56:13 $
|
||||||
-- > CVS $Author: aarne $
|
-- > CVS $Author: aarne $
|
||||||
-- > CVS $Revision: 1.18 $
|
-- > CVS $Revision: 1.18 $
|
||||||
--
|
--
|
||||||
@@ -21,7 +21,7 @@ import GF.Grammar.Printer
|
|||||||
import GF.Grammar.Macros
|
import GF.Grammar.Macros
|
||||||
import GF.Grammar.Lookup
|
import GF.Grammar.Lookup
|
||||||
import GF.Grammar.Predef
|
import GF.Grammar.Predef
|
||||||
import GF.Compile.Compute.ConcreteNew(GlobalEnv,normalForm,resourceValues)
|
import GF.Compile.Compute.Concrete(GlobalEnv,normalForm,resourceValues)
|
||||||
import GF.Data.Operations
|
import GF.Data.Operations
|
||||||
import GF.Infra.Option
|
import GF.Infra.Option
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ evalInfo opts resenv sgr m c info = do
|
|||||||
let ppr' = fmap (evalPrintname resenv c) ppr
|
let ppr' = fmap (evalPrintname resenv c) ppr
|
||||||
return $ CncFun mt pde' ppr' mpmcfg -- only cat in type actually needed
|
return $ CncFun mt pde' ppr' mpmcfg -- only cat in type actually needed
|
||||||
{-
|
{-
|
||||||
ResOper pty pde
|
ResOper pty pde
|
||||||
| not new && OptExpand `Set.member` optim -> do
|
| not new && OptExpand `Set.member` optim -> do
|
||||||
pde' <- case pde of
|
pde' <- case pde of
|
||||||
Just (L loc de) -> do de <- computeConcrete gr de
|
Just (L loc de) -> do de <- computeConcrete gr de
|
||||||
@@ -171,13 +171,13 @@ mkLinDefault gr typ = liftM (Abs Explicit varStr) $ mkDefField typ
|
|||||||
_ -> Bad (render ("linearization type field cannot be" <+> typ))
|
_ -> Bad (render ("linearization type field cannot be" <+> typ))
|
||||||
|
|
||||||
mkLinReference :: SourceGrammar -> Type -> Err Term
|
mkLinReference :: SourceGrammar -> Type -> Err Term
|
||||||
mkLinReference gr typ =
|
mkLinReference gr typ =
|
||||||
liftM (Abs Explicit varStr) $
|
liftM (Abs Explicit varStr) $
|
||||||
case mkDefField typ (Vr varStr) of
|
case mkDefField typ (Vr varStr) of
|
||||||
Bad "no string" -> return Empty
|
Bad "no string" -> return Empty
|
||||||
x -> x
|
x -> x
|
||||||
where
|
where
|
||||||
mkDefField ty trm =
|
mkDefField ty trm =
|
||||||
case ty of
|
case ty of
|
||||||
Table pty ty -> do ps <- allParamValues gr pty
|
Table pty ty -> do ps <- allParamValues gr pty
|
||||||
case ps of
|
case ps of
|
||||||
@@ -203,7 +203,7 @@ factor param c i t =
|
|||||||
T (TComp ty) cs -> factors ty [(p, factor param c (i+1) v) | (p, v) <- cs]
|
T (TComp ty) cs -> factors ty [(p, factor param c (i+1) v) | (p, v) <- cs]
|
||||||
_ -> composSafeOp (factor param c i) t
|
_ -> composSafeOp (factor param c i) t
|
||||||
where
|
where
|
||||||
factors ty pvs0
|
factors ty pvs0
|
||||||
| not param = V ty (map snd pvs0)
|
| not param = V ty (map snd pvs0)
|
||||||
factors ty [] = V ty []
|
factors ty [] = V ty []
|
||||||
factors ty pvs0@[(p,v)] = V ty [v]
|
factors ty pvs0@[(p,v)] = V ty [v]
|
||||||
@@ -224,7 +224,7 @@ factor param c i t =
|
|||||||
replace :: Term -> Term -> Term -> Term
|
replace :: Term -> Term -> Term -> Term
|
||||||
replace old new trm =
|
replace old new trm =
|
||||||
case trm of
|
case trm of
|
||||||
-- these are the important cases, since they can correspond to patterns
|
-- these are the important cases, since they can correspond to patterns
|
||||||
QC _ | trm == old -> new
|
QC _ | trm == old -> new
|
||||||
App _ _ | trm == old -> new
|
App _ _ | trm == old -> new
|
||||||
R _ | trm == old -> new
|
R _ | trm == old -> new
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
-- Stability : (stable)
|
-- Stability : (stable)
|
||||||
-- Portability : (portable)
|
-- Portability : (portable)
|
||||||
--
|
--
|
||||||
-- > CVS $Date: 2005/06/17 12:39:07 $
|
-- > CVS $Date: 2005/06/17 12:39:07 $
|
||||||
-- > CVS $Author: bringert $
|
-- > CVS $Author: bringert $
|
||||||
-- > CVS $Revision: 1.8 $
|
-- > CVS $Revision: 1.8 $
|
||||||
--
|
--
|
||||||
@@ -22,7 +22,7 @@ import PGF.Internal
|
|||||||
import GF.Data.Operations
|
import GF.Data.Operations
|
||||||
import GF.Infra.Option
|
import GF.Infra.Option
|
||||||
|
|
||||||
import Data.List --(isPrefixOf, find, intersperse)
|
import Data.List(isPrefixOf,find,intercalate,intersperse,groupBy,sortBy)
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
type Prefix = String -> String
|
type Prefix = String -> String
|
||||||
@@ -34,11 +34,12 @@ grammar2haskell :: Options
|
|||||||
-> PGF
|
-> PGF
|
||||||
-> String
|
-> String
|
||||||
grammar2haskell opts name gr = foldr (++++) [] $
|
grammar2haskell opts name gr = foldr (++++) [] $
|
||||||
pragmas ++ haskPreamble gadt name derivingClause extraImports ++
|
pragmas ++ haskPreamble gadt name derivingClause (extraImports ++ pgfImports) ++
|
||||||
[types, gfinstances gId lexical gr'] ++ compos
|
[types, gfinstances gId lexical gr'] ++ compos
|
||||||
where gr' = hSkeleton gr
|
where gr' = hSkeleton gr
|
||||||
gadt = haskellOption opts HaskellGADT
|
gadt = haskellOption opts HaskellGADT
|
||||||
dataExt = haskellOption opts HaskellData
|
dataExt = haskellOption opts HaskellData
|
||||||
|
pgf2 = haskellOption opts HaskellPGF2
|
||||||
lexical cat = haskellOption opts HaskellLexical && isLexicalCat opts cat
|
lexical cat = haskellOption opts HaskellLexical && isLexicalCat opts cat
|
||||||
gId | haskellOption opts HaskellNoPrefix = rmForbiddenChars
|
gId | haskellOption opts HaskellNoPrefix = rmForbiddenChars
|
||||||
| otherwise = ("G"++) . rmForbiddenChars
|
| otherwise = ("G"++) . rmForbiddenChars
|
||||||
@@ -50,21 +51,23 @@ grammar2haskell opts name gr = foldr (++++) [] $
|
|||||||
derivingClause
|
derivingClause
|
||||||
| dataExt = "deriving (Show,Data)"
|
| dataExt = "deriving (Show,Data)"
|
||||||
| otherwise = "deriving Show"
|
| otherwise = "deriving Show"
|
||||||
extraImports | gadt = ["import Control.Monad.Identity",
|
extraImports | gadt = ["import Control.Monad.Identity", "import Data.Monoid"]
|
||||||
"import Data.Monoid"]
|
|
||||||
| dataExt = ["import Data.Data"]
|
| dataExt = ["import Data.Data"]
|
||||||
| otherwise = []
|
| otherwise = []
|
||||||
|
pgfImports | pgf2 = ["import PGF2 hiding (Tree)", "", "showCId :: CId -> String", "showCId = id"]
|
||||||
|
| otherwise = ["import PGF hiding (Tree)"]
|
||||||
types | gadt = datatypesGADT gId lexical gr'
|
types | gadt = datatypesGADT gId lexical gr'
|
||||||
| otherwise = datatypes gId derivingClause lexical gr'
|
| otherwise = datatypes gId derivingClause lexical gr'
|
||||||
compos | gadt = prCompos gId lexical gr' ++ composClass
|
compos | gadt = prCompos gId lexical gr' ++ composClass
|
||||||
| otherwise = []
|
| otherwise = []
|
||||||
|
|
||||||
haskPreamble gadt name derivingClause extraImports =
|
haskPreamble :: Bool -> String -> String -> [String] -> [String]
|
||||||
|
haskPreamble gadt name derivingClause imports =
|
||||||
[
|
[
|
||||||
"module " ++ name ++ " where",
|
"module " ++ name ++ " where",
|
||||||
""
|
""
|
||||||
] ++ extraImports ++ [
|
] ++ imports ++ [
|
||||||
"import PGF hiding (Tree)",
|
"",
|
||||||
"----------------------------------------------------",
|
"----------------------------------------------------",
|
||||||
"-- automatic translation from GF to Haskell",
|
"-- automatic translation from GF to Haskell",
|
||||||
"----------------------------------------------------",
|
"----------------------------------------------------",
|
||||||
@@ -85,10 +88,11 @@ haskPreamble gadt name derivingClause extraImports =
|
|||||||
""
|
""
|
||||||
]
|
]
|
||||||
|
|
||||||
|
predefInst :: Bool -> String -> String -> String -> String -> String -> String
|
||||||
predefInst gadt derivingClause gtyp typ destr consr =
|
predefInst gadt derivingClause gtyp typ destr consr =
|
||||||
(if gadt
|
(if gadt
|
||||||
then []
|
then []
|
||||||
else ("newtype" +++ gtyp +++ "=" +++ gtyp +++ typ +++ derivingClause ++ "\n\n")
|
else "newtype" +++ gtyp +++ "=" +++ gtyp +++ typ +++ derivingClause ++ "\n\n"
|
||||||
)
|
)
|
||||||
++
|
++
|
||||||
"instance Gf" +++ gtyp +++ "where" ++++
|
"instance Gf" +++ gtyp +++ "where" ++++
|
||||||
@@ -103,10 +107,10 @@ type OIdent = String
|
|||||||
type HSkeleton = [(OIdent, [(OIdent, [OIdent])])]
|
type HSkeleton = [(OIdent, [(OIdent, [OIdent])])]
|
||||||
|
|
||||||
datatypes :: Prefix -> DerivingClause -> (OIdent -> Bool) -> (String,HSkeleton) -> String
|
datatypes :: Prefix -> DerivingClause -> (OIdent -> Bool) -> (String,HSkeleton) -> String
|
||||||
datatypes gId derivingClause lexical = (foldr (+++++) "") . (filter (/="")) . (map (hDatatype gId derivingClause lexical)) . snd
|
datatypes gId derivingClause lexical = foldr (+++++) "" . filter (/="") . map (hDatatype gId derivingClause lexical) . snd
|
||||||
|
|
||||||
gfinstances :: Prefix -> (OIdent -> Bool) -> (String,HSkeleton) -> String
|
gfinstances :: Prefix -> (OIdent -> Bool) -> (String,HSkeleton) -> String
|
||||||
gfinstances gId lexical (m,g) = (foldr (+++++) "") $ (filter (/="")) $ (map (gfInstance gId lexical m)) g
|
gfinstances gId lexical (m,g) = foldr (+++++) "" $ filter (/="") $ map (gfInstance gId lexical m) g
|
||||||
|
|
||||||
|
|
||||||
hDatatype :: Prefix -> DerivingClause -> (OIdent -> Bool) -> (OIdent, [(OIdent, [OIdent])]) -> String
|
hDatatype :: Prefix -> DerivingClause -> (OIdent -> Bool) -> (OIdent, [(OIdent, [OIdent])]) -> String
|
||||||
@@ -131,16 +135,17 @@ nonLexicalRules True rules = [r | r@(f,t) <- rules, not (null t)]
|
|||||||
lexicalConstructor :: OIdent -> String
|
lexicalConstructor :: OIdent -> String
|
||||||
lexicalConstructor cat = "Lex" ++ cat
|
lexicalConstructor cat = "Lex" ++ cat
|
||||||
|
|
||||||
|
predefTypeSkel :: HSkeleton
|
||||||
predefTypeSkel = [(c,[]) | c <- ["String", "Int", "Float"]]
|
predefTypeSkel = [(c,[]) | c <- ["String", "Int", "Float"]]
|
||||||
|
|
||||||
-- GADT version of data types
|
-- GADT version of data types
|
||||||
datatypesGADT :: Prefix -> (OIdent -> Bool) -> (String,HSkeleton) -> String
|
datatypesGADT :: Prefix -> (OIdent -> Bool) -> (String,HSkeleton) -> String
|
||||||
datatypesGADT gId lexical (_,skel) = unlines $
|
datatypesGADT gId lexical (_,skel) = unlines $
|
||||||
concatMap (hCatTypeGADT gId) (skel ++ predefTypeSkel) ++
|
concatMap (hCatTypeGADT gId) (skel ++ predefTypeSkel) ++
|
||||||
[
|
[
|
||||||
"",
|
"",
|
||||||
"data Tree :: * -> * where"
|
"data Tree :: * -> * where"
|
||||||
] ++
|
] ++
|
||||||
concatMap (map (" "++) . hDatatypeGADT gId lexical) skel ++
|
concatMap (map (" "++) . hDatatypeGADT gId lexical) skel ++
|
||||||
[
|
[
|
||||||
" GString :: String -> Tree GString_",
|
" GString :: String -> Tree GString_",
|
||||||
@@ -164,23 +169,23 @@ hCatTypeGADT gId (cat,rules)
|
|||||||
"data"+++gId cat++"_"]
|
"data"+++gId cat++"_"]
|
||||||
|
|
||||||
hDatatypeGADT :: Prefix -> (OIdent -> Bool) -> (OIdent, [(OIdent, [OIdent])]) -> [String]
|
hDatatypeGADT :: Prefix -> (OIdent -> Bool) -> (OIdent, [(OIdent, [OIdent])]) -> [String]
|
||||||
hDatatypeGADT gId lexical (cat, rules)
|
hDatatypeGADT gId lexical (cat, rules)
|
||||||
| isListCat (cat,rules) = [gId cat+++"::"+++"["++gId (elemCat cat)++"]" +++ "->" +++ t]
|
| isListCat (cat,rules) = [gId cat+++"::"+++"["++gId (elemCat cat)++"]" +++ "->" +++ t]
|
||||||
| otherwise =
|
| otherwise =
|
||||||
[ gId f +++ "::" +++ concatMap (\a -> gId a +++ "-> ") args ++ t
|
[ gId f +++ "::" +++ concatMap (\a -> gId a +++ "-> ") args ++ t
|
||||||
| (f,args) <- nonLexicalRules (lexical cat) rules ]
|
| (f,args) <- nonLexicalRules (lexical cat) rules ]
|
||||||
++ if lexical cat then [lexicalConstructor cat +++ ":: String ->"+++ t] else []
|
++ if lexical cat then [lexicalConstructor cat +++ ":: String ->"+++ t] else []
|
||||||
where t = "Tree" +++ gId cat ++ "_"
|
where t = "Tree" +++ gId cat ++ "_"
|
||||||
|
|
||||||
hEqGADT :: Prefix -> (OIdent -> Bool) -> (OIdent, [(OIdent, [OIdent])]) -> [String]
|
hEqGADT :: Prefix -> (OIdent -> Bool) -> (OIdent, [(OIdent, [OIdent])]) -> [String]
|
||||||
hEqGADT gId lexical (cat, rules)
|
hEqGADT gId lexical (cat, rules)
|
||||||
| isListCat (cat,rules) = let r = listr cat in ["(" ++ patt "x" r ++ "," ++ patt "y" r ++ ") -> " ++ listeqs]
|
| isListCat (cat,rules) = let r = listr cat in ["(" ++ patt "x" r ++ "," ++ patt "y" r ++ ") -> " ++ listeqs]
|
||||||
| otherwise = ["(" ++ patt "x" r ++ "," ++ patt "y" r ++ ") -> " ++ eqs r | r <- nonLexicalRules (lexical cat) rules]
|
| otherwise = ["(" ++ patt "x" r ++ "," ++ patt "y" r ++ ") -> " ++ eqs r | r <- nonLexicalRules (lexical cat) rules]
|
||||||
++ if lexical cat then ["(" ++ lexicalConstructor cat +++ "x" ++ "," ++ lexicalConstructor cat +++ "y" ++ ") -> x == y"] else []
|
++ if lexical cat then ["(" ++ lexicalConstructor cat +++ "x" ++ "," ++ lexicalConstructor cat +++ "y" ++ ") -> x == y"] else []
|
||||||
|
|
||||||
where
|
where
|
||||||
patt s (f,xs) = unwords (gId f : mkSVars s (length xs))
|
patt s (f,xs) = unwords (gId f : mkSVars s (length xs))
|
||||||
eqs (_,xs) = unwords ("and" : "[" : intersperse "," [x ++ " == " ++ y |
|
eqs (_,xs) = unwords ("and" : "[" : intersperse "," [x ++ " == " ++ y |
|
||||||
(x,y) <- zip (mkSVars "x" (length xs)) (mkSVars "y" (length xs)) ] ++ ["]"])
|
(x,y) <- zip (mkSVars "x" (length xs)) (mkSVars "y" (length xs)) ] ++ ["]"])
|
||||||
listr c = (c,["foo"]) -- foo just for length = 1
|
listr c = (c,["foo"]) -- foo just for length = 1
|
||||||
listeqs = "and [x == y | (x,y) <- zip x1 y1]"
|
listeqs = "and [x == y | (x,y) <- zip x1 y1]"
|
||||||
@@ -189,25 +194,26 @@ prCompos :: Prefix -> (OIdent -> Bool) -> (String,HSkeleton) -> [String]
|
|||||||
prCompos gId lexical (_,catrules) =
|
prCompos gId lexical (_,catrules) =
|
||||||
["instance Compos Tree where",
|
["instance Compos Tree where",
|
||||||
" compos r a f t = case t of"]
|
" compos r a f t = case t of"]
|
||||||
++
|
++
|
||||||
[" " ++ prComposCons (gId f) xs | (c,rs) <- catrules, not (isListCat (c,rs)),
|
[" " ++ prComposCons (gId f) xs | (c,rs) <- catrules, not (isListCat (c,rs)),
|
||||||
(f,xs) <- rs, not (null xs)]
|
(f,xs) <- rs, not (null xs)]
|
||||||
++
|
++
|
||||||
[" " ++ prComposCons (gId c) ["x1"] | (c,rs) <- catrules, isListCat (c,rs)]
|
[" " ++ prComposCons (gId c) ["x1"] | (c,rs) <- catrules, isListCat (c,rs)]
|
||||||
++
|
++
|
||||||
[" _ -> r t"]
|
[" _ -> r t"]
|
||||||
where
|
where
|
||||||
prComposCons f xs = let vs = mkVars (length xs) in
|
prComposCons f xs = let vs = mkVars (length xs) in
|
||||||
f +++ unwords vs +++ "->" +++ rhs f (zip vs xs)
|
f +++ unwords vs +++ "->" +++ rhs f (zip vs xs)
|
||||||
rhs f vcs = "r" +++ f +++ unwords (map (prRec f) vcs)
|
rhs f vcs = "r" +++ f +++ unwords (map (prRec f) vcs)
|
||||||
prRec f (v,c)
|
prRec f (v,c)
|
||||||
| isList f = "`a` foldr (a . a (r (:)) . f) (r [])" +++ v
|
| isList f = "`a` foldr (a . a (r (:)) . f) (r [])" +++ v
|
||||||
| otherwise = "`a`" +++ "f" +++ v
|
| otherwise = "`a`" +++ "f" +++ v
|
||||||
isList f = (gId "List") `isPrefixOf` f
|
isList f = gId "List" `isPrefixOf` f
|
||||||
|
|
||||||
gfInstance :: Prefix -> (OIdent -> Bool) -> String -> (OIdent, [(OIdent, [OIdent])]) -> String
|
gfInstance :: Prefix -> (OIdent -> Bool) -> String -> (OIdent, [(OIdent, [OIdent])]) -> String
|
||||||
gfInstance gId lexical m crs = hInstance gId lexical m crs ++++ fInstance gId lexical m crs
|
gfInstance gId lexical m crs = hInstance gId lexical m crs ++++ fInstance gId lexical m crs
|
||||||
|
|
||||||
|
hInstance :: (String -> String) -> (String -> Bool) -> String -> (String, [(OIdent, [OIdent])]) -> String
|
||||||
----hInstance m ("Cn",_) = "" --- seems to belong to an old applic. AR 18/5/2004
|
----hInstance m ("Cn",_) = "" --- seems to belong to an old applic. AR 18/5/2004
|
||||||
hInstance gId _ m (cat,[]) = unlines [
|
hInstance gId _ m (cat,[]) = unlines [
|
||||||
"instance Show" +++ gId cat,
|
"instance Show" +++ gId cat,
|
||||||
@@ -216,15 +222,15 @@ hInstance gId _ m (cat,[]) = unlines [
|
|||||||
" gf _ = undefined",
|
" gf _ = undefined",
|
||||||
" fg _ = undefined"
|
" fg _ = undefined"
|
||||||
]
|
]
|
||||||
hInstance gId lexical m (cat,rules)
|
hInstance gId lexical m (cat,rules)
|
||||||
| isListCat (cat,rules) =
|
| isListCat (cat,rules) =
|
||||||
"instance Gf" +++ gId cat +++ "where" ++++
|
"instance Gf" +++ gId cat +++ "where" ++++
|
||||||
" gf (" ++ gId cat +++ "[" ++ concat (intersperse "," baseVars) ++ "])"
|
" gf (" ++ gId cat +++ "[" ++ intercalate "," baseVars ++ "])"
|
||||||
+++ "=" +++ mkRHS ("Base"++ec) baseVars ++++
|
+++ "=" +++ mkRHS ("Base"++ec) baseVars ++++
|
||||||
" gf (" ++ gId cat +++ "(x:xs)) = "
|
" gf (" ++ gId cat +++ "(x:xs)) = "
|
||||||
++ mkRHS ("Cons"++ec) ["x",prParenth (gId cat+++"xs")]
|
++ mkRHS ("Cons"++ec) ["x",prParenth (gId cat+++"xs")]
|
||||||
-- no show for GADTs
|
-- no show for GADTs
|
||||||
-- ++++ " gf (" ++ gId cat +++ "xs) = error (\"Bad " ++ cat ++ " value: \" ++ show xs)"
|
-- ++++ " gf (" ++ gId cat +++ "xs) = error (\"Bad " ++ cat ++ " value: \" ++ show xs)"
|
||||||
| otherwise =
|
| otherwise =
|
||||||
"instance Gf" +++ gId cat +++ "where\n" ++
|
"instance Gf" +++ gId cat +++ "where\n" ++
|
||||||
unlines ([mkInst f xx | (f,xx) <- nonLexicalRules (lexical cat) rules]
|
unlines ([mkInst f xx | (f,xx) <- nonLexicalRules (lexical cat) rules]
|
||||||
@@ -233,19 +239,22 @@ hInstance gId lexical m (cat,rules)
|
|||||||
ec = elemCat cat
|
ec = elemCat cat
|
||||||
baseVars = mkVars (baseSize (cat,rules))
|
baseVars = mkVars (baseSize (cat,rules))
|
||||||
mkInst f xx = let xx' = mkVars (length xx) in " gf " ++
|
mkInst f xx = let xx' = mkVars (length xx) in " gf " ++
|
||||||
(if length xx == 0 then gId f else prParenth (gId f +++ foldr1 (+++) xx')) +++
|
(if null xx then gId f else prParenth (gId f +++ foldr1 (+++) xx')) +++
|
||||||
"=" +++ mkRHS f xx'
|
"=" +++ mkRHS f xx'
|
||||||
mkRHS f vars = "mkApp (mkCId \"" ++ f ++ "\")" +++
|
mkRHS f vars = "mkApp (mkCId \"" ++ f ++ "\")" +++
|
||||||
"[" ++ prTList ", " ["gf" +++ x | x <- vars] ++ "]"
|
"[" ++ prTList ", " ["gf" +++ x | x <- vars] ++ "]"
|
||||||
|
|
||||||
|
mkVars :: Int -> [String]
|
||||||
mkVars = mkSVars "x"
|
mkVars = mkSVars "x"
|
||||||
|
|
||||||
|
mkSVars :: String -> Int -> [String]
|
||||||
mkSVars s n = [s ++ show i | i <- [1..n]]
|
mkSVars s n = [s ++ show i | i <- [1..n]]
|
||||||
|
|
||||||
----fInstance m ("Cn",_) = "" ---
|
----fInstance m ("Cn",_) = "" ---
|
||||||
fInstance _ _ m (cat,[]) = ""
|
fInstance _ _ m (cat,[]) = ""
|
||||||
fInstance gId lexical m (cat,rules) =
|
fInstance gId lexical m (cat,rules) =
|
||||||
" fg t =" ++++
|
" fg t =" ++++
|
||||||
(if isList
|
(if isList
|
||||||
then " " ++ gId cat ++ " (fgs t) where\n fgs t = case unApp t of"
|
then " " ++ gId cat ++ " (fgs t) where\n fgs t = case unApp t of"
|
||||||
else " case unApp t of") ++++
|
else " case unApp t of") ++++
|
||||||
unlines [mkInst f xx | (f,xx) <- nonLexicalRules (lexical cat) rules] ++++
|
unlines [mkInst f xx | (f,xx) <- nonLexicalRules (lexical cat) rules] ++++
|
||||||
@@ -257,27 +266,28 @@ fInstance gId lexical m (cat,rules) =
|
|||||||
" Just (i," ++
|
" Just (i," ++
|
||||||
"[" ++ prTList "," xx' ++ "])" +++
|
"[" ++ prTList "," xx' ++ "])" +++
|
||||||
"| i == mkCId \"" ++ f ++ "\" ->" +++ mkRHS f xx'
|
"| i == mkCId \"" ++ f ++ "\" ->" +++ mkRHS f xx'
|
||||||
where xx' = ["x" ++ show i | (_,i) <- zip xx [1..]]
|
where
|
||||||
mkRHS f vars
|
xx' = ["x" ++ show i | (_,i) <- zip xx [1..]]
|
||||||
| isList =
|
mkRHS f vars
|
||||||
if "Base" `isPrefixOf` f
|
| isList =
|
||||||
then "[" ++ prTList ", " [ "fg" +++ x | x <- vars ] ++ "]"
|
if "Base" `isPrefixOf` f
|
||||||
else "fg" +++ (vars !! 0) +++ ":" +++ "fgs" +++ (vars !! 1)
|
then "[" ++ prTList ", " [ "fg" +++ x | x <- vars ] ++ "]"
|
||||||
| otherwise =
|
else "fg" +++ (vars !! 0) +++ ":" +++ "fgs" +++ (vars !! 1)
|
||||||
gId f +++
|
| otherwise =
|
||||||
prTList " " [prParenth ("fg" +++ x) | x <- vars]
|
gId f +++
|
||||||
|
prTList " " [prParenth ("fg" +++ x) | x <- vars]
|
||||||
|
|
||||||
--type HSkeleton = [(OIdent, [(OIdent, [OIdent])])]
|
--type HSkeleton = [(OIdent, [(OIdent, [OIdent])])]
|
||||||
hSkeleton :: PGF -> (String,HSkeleton)
|
hSkeleton :: PGF -> (String,HSkeleton)
|
||||||
hSkeleton gr =
|
hSkeleton gr =
|
||||||
(showCId (absname gr),
|
(showCId (absname gr),
|
||||||
let fs =
|
let fs =
|
||||||
[(showCId c, [(showCId f, map showCId cs) | (f, (cs,_)) <- fs]) |
|
[(showCId c, [(showCId f, map showCId cs) | (f, (cs,_)) <- fs]) |
|
||||||
fs@((_, (_,c)):_) <- fns]
|
fs@((_, (_,c)):_) <- fns]
|
||||||
in fs ++ [(sc, []) | c <- cts, let sc = showCId c, notElem sc (["Int", "Float", "String"] ++ map fst fs)]
|
in fs ++ [(sc, []) | c <- cts, let sc = showCId c, sc `notElem` (["Int", "Float", "String"] ++ map fst fs)]
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
cts = Map.keys (cats (abstract gr))
|
cts = Map.keys (cats (abstract gr))
|
||||||
fns = groupBy valtypg (sortBy valtyps (map jty (Map.assocs (funs (abstract gr)))))
|
fns = groupBy valtypg (sortBy valtyps (map jty (Map.assocs (funs (abstract gr)))))
|
||||||
valtyps (_, (_,x)) (_, (_,y)) = compare x y
|
valtyps (_, (_,x)) (_, (_,y)) = compare x y
|
||||||
valtypg (_, (_,x)) (_, (_,y)) = x == y
|
valtypg (_, (_,x)) (_, (_,y)) = x == y
|
||||||
@@ -291,9 +301,10 @@ updateSkeleton cat skel rule =
|
|||||||
-}
|
-}
|
||||||
isListCat :: (OIdent, [(OIdent, [OIdent])]) -> Bool
|
isListCat :: (OIdent, [(OIdent, [OIdent])]) -> Bool
|
||||||
isListCat (cat,rules) = "List" `isPrefixOf` cat && length rules == 2
|
isListCat (cat,rules) = "List" `isPrefixOf` cat && length rules == 2
|
||||||
&& ("Base"++c) `elem` fs && ("Cons"++c) `elem` fs
|
&& ("Base"++c) `elem` fs && ("Cons"++c) `elem` fs
|
||||||
where c = elemCat cat
|
where
|
||||||
fs = map fst rules
|
c = elemCat cat
|
||||||
|
fs = map fst rules
|
||||||
|
|
||||||
-- | Gets the element category of a list category.
|
-- | Gets the element category of a list category.
|
||||||
elemCat :: OIdent -> OIdent
|
elemCat :: OIdent -> OIdent
|
||||||
@@ -310,7 +321,7 @@ baseSize (_,rules) = length bs
|
|||||||
where Just (_,bs) = find (("Base" `isPrefixOf`) . fst) rules
|
where Just (_,bs) = find (("Base" `isPrefixOf`) . fst) rules
|
||||||
|
|
||||||
composClass :: [String]
|
composClass :: [String]
|
||||||
composClass =
|
composClass =
|
||||||
[
|
[
|
||||||
"",
|
"",
|
||||||
"class Compos t where",
|
"class Compos t where",
|
||||||
@@ -337,4 +348,3 @@ composClass =
|
|||||||
"",
|
"",
|
||||||
"newtype C b a = C { unC :: b }"
|
"newtype C b a = C { unC :: b }"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -39,6 +39,7 @@ import GF.Data.Operations
|
|||||||
|
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Data.List (nub,(\\))
|
import Data.List (nub,(\\))
|
||||||
|
import qualified Data.List as L
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Data.Maybe(mapMaybe)
|
import Data.Maybe(mapMaybe)
|
||||||
import GF.Text.Pretty
|
import GF.Text.Pretty
|
||||||
@@ -67,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
|
||||||
@@ -84,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
|
||||||
@@ -93,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
|
||||||
@@ -105,7 +106,26 @@ renameIdentTerm' env@(act,imps) t0 =
|
|||||||
ts@(t:_) -> do checkWarn ("atomic term" <+> ppTerm Qualified 0 t0 $$
|
ts@(t:_) -> do checkWarn ("atomic term" <+> ppTerm Qualified 0 t0 $$
|
||||||
"conflict" <+> hsep (punctuate ',' (map (ppTerm Qualified 0) ts)) $$
|
"conflict" <+> hsep (punctuate ',' (map (ppTerm Qualified 0) ts)) $$
|
||||||
"given" <+> fsep (punctuate ',' (map fst qualifs)))
|
"given" <+> fsep (punctuate ',' (map fst qualifs)))
|
||||||
return t
|
return (bestTerm ts) -- Heuristic for resource grammar. Returns t for all others.
|
||||||
|
where
|
||||||
|
-- Hotfix for https://github.com/GrammaticalFramework/gf-core/issues/56
|
||||||
|
-- Real bug is probably somewhere deeper in recognising excluded functions. /IL 2020-06-06
|
||||||
|
notFromCommonModule :: Term -> Bool
|
||||||
|
notFromCommonModule term =
|
||||||
|
let t = render $ ppTerm Qualified 0 term :: String
|
||||||
|
in not $ any (\moduleName -> moduleName `L.isPrefixOf` t)
|
||||||
|
["CommonX", "ConstructX", "ExtendFunctor"
|
||||||
|
,"MarkHTMLX", "ParamX", "TenseX", "TextX"]
|
||||||
|
|
||||||
|
-- If one of the terms comes from the common modules,
|
||||||
|
-- we choose the other one, because that's defined in the grammar.
|
||||||
|
bestTerm :: [Term] -> Term
|
||||||
|
bestTerm [] = error "constant not found" -- not reached: bestTerm is only called for case ts@(t:_)
|
||||||
|
bestTerm ts@(t:_) =
|
||||||
|
let notCommon = [t | t <- ts, notFromCommonModule t]
|
||||||
|
in case notCommon of
|
||||||
|
[] -> t -- All terms are from common modules, return first of original list
|
||||||
|
(u:_) -> u -- ≥1 terms are not from common modules, return first of those
|
||||||
|
|
||||||
info2status :: Maybe ModuleName -> Ident -> Info -> StatusInfo
|
info2status :: Maybe ModuleName -> Ident -> Info -> StatusInfo
|
||||||
info2status mq c i = case i of
|
info2status mq c i = case i of
|
||||||
@@ -137,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
|
||||||
@@ -188,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
|
||||||
@@ -199,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
|
||||||
@@ -209,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.
|
||||||
@@ -311,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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{-# LANGUAGE PatternGuards #-}
|
{-# LANGUAGE PatternGuards #-}
|
||||||
module GF.Compile.TypeCheck.Concrete( {-checkLType, inferLType, computeLType, ppType-} ) where
|
module GF.Compile.TypeCheck.Concrete( checkLType, inferLType, computeLType, ppType ) where
|
||||||
{-
|
import Prelude hiding ((<>)) -- GHC 8.4.1 clash with Text.PrettyPrint
|
||||||
|
|
||||||
import GF.Infra.CheckM
|
import GF.Infra.CheckM
|
||||||
import GF.Data.Operations
|
import GF.Data.Operations
|
||||||
|
|
||||||
@@ -22,10 +23,16 @@ computeLType gr g0 t = comp (reverse [(b,x, Vr x) | (b,x,_) <- g0] ++ g0) t
|
|||||||
_ | Just _ <- isTypeInts ty -> return ty ---- shouldn't be needed
|
_ | Just _ <- isTypeInts ty -> return ty ---- shouldn't be needed
|
||||||
| isPredefConstant ty -> return ty ---- shouldn't be needed
|
| isPredefConstant ty -> return ty ---- shouldn't be needed
|
||||||
|
|
||||||
Q (m,ident) -> checkIn (text "module" <+> ppIdent m) $ do
|
Q (m,ident) -> checkIn ("module" <+> m) $ do
|
||||||
ty' <- lookupResDef gr (m,ident)
|
ty' <- lookupResDef gr (m,ident)
|
||||||
if ty' == ty then return ty else comp g ty' --- is this necessary to test?
|
if ty' == ty then return ty else comp g ty' --- is this necessary to test?
|
||||||
|
|
||||||
|
AdHocOverload ts -> do
|
||||||
|
over <- getOverload gr g (Just typeType) t
|
||||||
|
case over of
|
||||||
|
Just (tr,_) -> return tr
|
||||||
|
_ -> checkError ("unresolved overloading of constants" <+> ppTerm Qualified 0 t)
|
||||||
|
|
||||||
Vr ident -> checkLookup ident g -- never needed to compute!
|
Vr ident -> checkLookup ident g -- never needed to compute!
|
||||||
|
|
||||||
App f a -> do
|
App f a -> do
|
||||||
@@ -62,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
|
||||||
|
|
||||||
@@ -73,26 +79,26 @@ inferLType gr g trm = case trm of
|
|||||||
|
|
||||||
Q (m,ident) | isPredef m -> termWith trm $ case typPredefined ident of
|
Q (m,ident) | isPredef m -> termWith trm $ case typPredefined ident of
|
||||||
Just ty -> return ty
|
Just ty -> return ty
|
||||||
Nothing -> checkError (text "unknown in Predef:" <+> ppIdent ident)
|
Nothing -> checkError ("unknown in Predef:" <+> ident)
|
||||||
|
|
||||||
Q ident -> checks [
|
Q ident -> checks [
|
||||||
termWith trm $ lookupResType gr ident >>= computeLType gr g
|
termWith trm $ lookupResType gr ident >>= computeLType gr g
|
||||||
,
|
,
|
||||||
lookupResDef gr ident >>= inferLType gr g
|
lookupResDef gr ident >>= inferLType gr g
|
||||||
,
|
,
|
||||||
checkError (text "cannot infer type of constant" <+> ppTerm Unqualified 0 trm)
|
checkError ("cannot infer type of constant" <+> ppTerm Unqualified 0 trm)
|
||||||
]
|
]
|
||||||
|
|
||||||
QC (m,ident) | isPredef m -> termWith trm $ case typPredefined ident of
|
QC (m,ident) | isPredef m -> termWith trm $ case typPredefined ident of
|
||||||
Just ty -> return ty
|
Just ty -> return ty
|
||||||
Nothing -> checkError (text "unknown in Predef:" <+> ppIdent ident)
|
Nothing -> checkError ("unknown in Predef:" <+> ident)
|
||||||
|
|
||||||
QC ident -> checks [
|
QC ident -> checks [
|
||||||
termWith trm $ lookupResType gr ident >>= computeLType gr g
|
termWith trm $ lookupResType gr ident >>= computeLType gr g
|
||||||
,
|
,
|
||||||
lookupResDef gr ident >>= inferLType gr g
|
lookupResDef gr ident >>= inferLType gr g
|
||||||
,
|
,
|
||||||
checkError (text "cannot infer type of canonical constant" <+> ppTerm Unqualified 0 trm)
|
checkError ("cannot infer type of canonical constant" <+> ppTerm Unqualified 0 trm)
|
||||||
]
|
]
|
||||||
|
|
||||||
Vr ident -> termWith trm $ checkLookup ident g
|
Vr ident -> termWith trm $ checkLookup ident g
|
||||||
@@ -100,7 +106,12 @@ inferLType gr g trm = case trm of
|
|||||||
Typed e t -> do
|
Typed e t -> do
|
||||||
t' <- computeLType gr g t
|
t' <- computeLType gr g t
|
||||||
checkLType gr g e t'
|
checkLType gr g e t'
|
||||||
return (e,t')
|
|
||||||
|
AdHocOverload ts -> do
|
||||||
|
over <- getOverload gr g Nothing trm
|
||||||
|
case over of
|
||||||
|
Just trty -> return trty
|
||||||
|
_ -> checkError ("unresolved overloading of constants" <+> ppTerm Qualified 0 trm)
|
||||||
|
|
||||||
App f a -> do
|
App f a -> do
|
||||||
over <- getOverload gr g Nothing trm
|
over <- getOverload gr g Nothing trm
|
||||||
@@ -110,13 +121,17 @@ inferLType gr g trm = case trm of
|
|||||||
(f',fty) <- inferLType gr g f
|
(f',fty) <- inferLType gr g f
|
||||||
fty' <- computeLType gr g fty
|
fty' <- computeLType gr g fty
|
||||||
case fty' of
|
case fty' of
|
||||||
Prod bt z arg val -> do
|
Prod bt z arg val -> do
|
||||||
a' <- justCheck g a arg
|
a' <- justCheck g a arg
|
||||||
ty <- if isWildIdent z
|
ty <- if isWildIdent z
|
||||||
then return val
|
then return val
|
||||||
else substituteLType [(bt,z,a')] val
|
else substituteLType [(bt,z,a')] val
|
||||||
return (App f' a',ty)
|
return (App f' a',ty)
|
||||||
_ -> checkError (text "A function type is expected for" <+> ppTerm Unqualified 0 f <+> text "instead of type" <+> ppType fty)
|
_ ->
|
||||||
|
let term = ppTerm Unqualified 0 f
|
||||||
|
funName = pp . head . words .render $ term
|
||||||
|
in checkError ("A function type is expected for" <+> term <+> "instead of type" <+> ppType fty $$
|
||||||
|
"\n ** Maybe you gave too many arguments to" <+> funName <+> "\n")
|
||||||
|
|
||||||
S f x -> do
|
S f x -> do
|
||||||
(f', fty) <- inferLType gr g f
|
(f', fty) <- inferLType gr g f
|
||||||
@@ -124,7 +139,7 @@ inferLType gr g trm = case trm of
|
|||||||
Table arg val -> do
|
Table arg val -> do
|
||||||
x'<- justCheck g x arg
|
x'<- justCheck g x arg
|
||||||
return (S f' x', val)
|
return (S f' x', val)
|
||||||
_ -> checkError (text "table lintype expected for the table in" $$ nest 2 (ppTerm Unqualified 0 trm))
|
_ -> checkError ("table lintype expected for the table in" $$ nest 2 (ppTerm Unqualified 0 trm))
|
||||||
|
|
||||||
P t i -> do
|
P t i -> do
|
||||||
(t',ty) <- inferLType gr g t --- ??
|
(t',ty) <- inferLType gr g t --- ??
|
||||||
@@ -132,16 +147,16 @@ inferLType gr g trm = case trm of
|
|||||||
let tr2 = P t' i
|
let tr2 = P t' i
|
||||||
termWith tr2 $ case ty' of
|
termWith tr2 $ case ty' of
|
||||||
RecType ts -> case lookup i ts of
|
RecType ts -> case lookup i ts of
|
||||||
Nothing -> checkError (text "unknown label" <+> ppLabel i <+> text "in" $$ nest 2 (ppTerm Unqualified 0 ty'))
|
Nothing -> checkError ("unknown label" <+> i <+> "in" $$ nest 2 (ppTerm Unqualified 0 ty'))
|
||||||
Just x -> return x
|
Just x -> return x
|
||||||
_ -> checkError (text "record type expected for:" <+> ppTerm Unqualified 0 t $$
|
_ -> checkError ("record type expected for:" <+> ppTerm Unqualified 0 t $$
|
||||||
text " instead of the inferred:" <+> ppTerm Unqualified 0 ty')
|
" instead of the inferred:" <+> ppTerm Unqualified 0 ty')
|
||||||
|
|
||||||
R r -> do
|
R r -> do
|
||||||
let (ls,fs) = unzip r
|
let (ls,fs) = unzip r
|
||||||
fsts <- mapM inferM fs
|
fsts <- mapM inferM fs
|
||||||
let ts = [ty | (Just ty,_) <- fsts]
|
let ts = [ty | (Just ty,_) <- fsts]
|
||||||
checkCond (text "cannot infer type of record" $$ nest 2 (ppTerm Unqualified 0 trm)) (length ts == length fsts)
|
checkCond ("cannot infer type of record" $$ nest 2 (ppTerm Unqualified 0 trm)) (length ts == length fsts)
|
||||||
return $ (R (zip ls fsts), RecType (zip ls ts))
|
return $ (R (zip ls fsts), RecType (zip ls ts))
|
||||||
|
|
||||||
T (TTyped arg) pts -> do
|
T (TTyped arg) pts -> do
|
||||||
@@ -152,10 +167,10 @@ inferLType gr g trm = case trm of
|
|||||||
checkLType gr g trm (Table arg val)
|
checkLType gr g trm (Table arg val)
|
||||||
T ti pts -> do -- tries to guess: good in oper type inference
|
T ti pts -> do -- tries to guess: good in oper type inference
|
||||||
let pts' = [pt | pt@(p,_) <- pts, isConstPatt p]
|
let pts' = [pt | pt@(p,_) <- pts, isConstPatt p]
|
||||||
case pts' of
|
case pts' of
|
||||||
[] -> checkError (text "cannot infer table type of" <+> ppTerm Unqualified 0 trm)
|
[] -> checkError ("cannot infer table type of" <+> ppTerm Unqualified 0 trm)
|
||||||
---- PInt k : _ -> return $ Ints $ max [i | PInt i <- pts']
|
---- PInt k : _ -> return $ Ints $ max [i | PInt i <- pts']
|
||||||
_ -> do
|
_ -> do
|
||||||
(arg,val) <- checks $ map (inferCase Nothing) pts'
|
(arg,val) <- checks $ map (inferCase Nothing) pts'
|
||||||
checkLType gr g trm (Table arg val)
|
checkLType gr g trm (Table arg val)
|
||||||
V arg pts -> do
|
V arg pts -> do
|
||||||
@@ -166,9 +181,9 @@ inferLType gr g trm = case trm of
|
|||||||
K s -> do
|
K s -> do
|
||||||
if elem ' ' s
|
if elem ' ' s
|
||||||
then do
|
then do
|
||||||
let ss = foldr C Empty (map K (words s))
|
let ss = foldr C Empty (map K (words s))
|
||||||
----- removed irritating warning AR 24/5/2008
|
----- removed irritating warning AR 24/5/2008
|
||||||
----- checkWarn ("token \"" ++ s ++
|
----- checkWarn ("token \"" ++ s ++
|
||||||
----- "\" converted to token list" ++ prt ss)
|
----- "\" converted to token list" ++ prt ss)
|
||||||
return (ss, typeStr)
|
return (ss, typeStr)
|
||||||
else return (trm, typeStr)
|
else return (trm, typeStr)
|
||||||
@@ -179,50 +194,56 @@ inferLType gr g trm = case trm of
|
|||||||
|
|
||||||
Empty -> return (trm, typeStr)
|
Empty -> return (trm, typeStr)
|
||||||
|
|
||||||
C s1 s2 ->
|
C s1 s2 ->
|
||||||
check2 (flip (justCheck g) typeStr) C s1 s2 typeStr
|
check2 (flip (justCheck g) typeStr) C s1 s2 typeStr
|
||||||
|
|
||||||
Glue s1 s2 ->
|
Glue s1 s2 ->
|
||||||
check2 (flip (justCheck g) typeStr) Glue s1 s2 typeStr ---- typeTok
|
check2 (flip (justCheck g) typeStr) Glue s1 s2 typeStr ---- typeTok
|
||||||
|
|
||||||
---- hack from Rename.identRenameTerm, to live with files with naming conflicts 18/6/2007
|
---- hack from Rename.identRenameTerm, to live with files with naming conflicts 18/6/2007
|
||||||
Strs (Cn c : ts) | c == cConflict -> do
|
Strs (Cn c : ts) | c == cConflict -> do
|
||||||
checkWarn (text "unresolved constant, could be any of" <+> hcat (map (ppTerm Unqualified 0) ts))
|
checkWarn ("unresolved constant, could be any of" <+> hcat (map (ppTerm Unqualified 0) ts))
|
||||||
inferLType gr g (head ts)
|
inferLType gr g (head ts)
|
||||||
|
|
||||||
Strs ts -> do
|
Strs ts -> do
|
||||||
ts' <- mapM (\t -> justCheck g t typeStr) ts
|
ts' <- mapM (\t -> justCheck g t typeStr) ts
|
||||||
return (Strs ts', typeStrs)
|
return (Strs ts', typeStrs)
|
||||||
|
|
||||||
Alts t aa -> do
|
Alts t aa -> do
|
||||||
t' <- justCheck g t typeStr
|
t' <- justCheck g t typeStr
|
||||||
aa' <- flip mapM aa (\ (c,v) -> do
|
aa' <- flip mapM aa (\ (c,v) -> do
|
||||||
c' <- justCheck g c typeStr
|
c' <- justCheck g c typeStr
|
||||||
v' <- checks $ map (justCheck g v) [typeStrs, EPattType typeStr]
|
v' <- checks $ map (justCheck g v) [typeStrs, EPattType typeStr]
|
||||||
return (c',v'))
|
return (c',v'))
|
||||||
return (Alts t' aa', typeStr)
|
return (Alts t' aa', typeStr)
|
||||||
|
|
||||||
RecType r -> do
|
RecType r -> do
|
||||||
let (ls,ts) = unzip r
|
let (ls,ts) = unzip r
|
||||||
ts' <- mapM (flip (justCheck g) typeType) ts
|
ts' <- mapM (flip (justCheck g) typeType) ts
|
||||||
return (RecType (zip ls ts'), typeType)
|
return (RecType (zip ls ts'), typeType)
|
||||||
|
|
||||||
ExtR r s -> do
|
ExtR r s -> do
|
||||||
(r',rT) <- inferLType gr g r
|
|
||||||
|
--- over <- getOverload gr g Nothing r
|
||||||
|
--- let r1 = maybe r fst over
|
||||||
|
let r1 = r ---
|
||||||
|
|
||||||
|
(r',rT) <- inferLType gr g r1
|
||||||
rT' <- computeLType gr g rT
|
rT' <- computeLType gr g rT
|
||||||
|
|
||||||
(s',sT) <- inferLType gr g s
|
(s',sT) <- inferLType gr g s
|
||||||
sT' <- computeLType gr g sT
|
sT' <- computeLType gr g sT
|
||||||
|
|
||||||
let trm' = ExtR r' s'
|
let trm' = ExtR r' s'
|
||||||
---- trm' <- plusRecord r' s'
|
|
||||||
case (rT', sT') of
|
case (rT', sT') of
|
||||||
(RecType rs, RecType ss) -> do
|
(RecType rs, RecType ss) -> do
|
||||||
rt <- plusRecType rT' sT'
|
let rt = RecType ([field | field@(l,_) <- rs, notElem l (map fst ss)] ++ ss) -- select types of later fields
|
||||||
checkLType gr g trm' rt ---- return (trm', rt)
|
checkLType gr g trm' rt ---- return (trm', rt)
|
||||||
_ | rT' == typeType && sT' == typeType -> return (trm', typeType)
|
_ | rT' == typeType && sT' == typeType -> do
|
||||||
_ -> checkError (text "records or record types expected in" <+> ppTerm Unqualified 0 trm)
|
return (trm', typeType)
|
||||||
|
_ -> checkError ("records or record types expected in" <+> ppTerm Unqualified 0 trm)
|
||||||
|
|
||||||
Sort _ ->
|
Sort _ ->
|
||||||
termWith trm $ return typeType
|
termWith trm $ return typeType
|
||||||
|
|
||||||
Prod bt x a b -> do
|
Prod bt x a b -> do
|
||||||
@@ -231,7 +252,7 @@ inferLType gr g trm = case trm of
|
|||||||
return (Prod bt x a' b', typeType)
|
return (Prod bt x a' b', typeType)
|
||||||
|
|
||||||
Table p t -> do
|
Table p t -> do
|
||||||
p' <- justCheck g p typeType --- check p partype!
|
p' <- justCheck g p typeType --- check p partype!
|
||||||
t' <- justCheck g t typeType
|
t' <- justCheck g t typeType
|
||||||
return $ (Table p' t', typeType)
|
return $ (Table p' t', typeType)
|
||||||
|
|
||||||
@@ -250,9 +271,9 @@ inferLType gr g trm = case trm of
|
|||||||
ELin c trm -> do
|
ELin c trm -> do
|
||||||
(trm',ty) <- inferLType gr g trm
|
(trm',ty) <- inferLType gr g trm
|
||||||
ty' <- lockRecType c ty ---- lookup c; remove lock AR 20/6/2009
|
ty' <- lockRecType c ty ---- lookup c; remove lock AR 20/6/2009
|
||||||
return $ (ELin c trm', ty')
|
return $ (ELin c trm', ty')
|
||||||
|
|
||||||
_ -> checkError (text "cannot infer lintype of" <+> ppTerm Unqualified 0 trm)
|
_ -> checkError ("cannot infer lintype of" <+> ppTerm Unqualified 0 trm)
|
||||||
|
|
||||||
where
|
where
|
||||||
isPredef m = elem m [cPredef,cPredefAbs]
|
isPredef m = elem m [cPredef,cPredefAbs]
|
||||||
@@ -299,7 +320,6 @@ inferLType gr g trm = case trm of
|
|||||||
PChars _ -> return $ typeStr
|
PChars _ -> return $ typeStr
|
||||||
_ -> inferLType gr g (patt2term p) >>= return . snd
|
_ -> inferLType gr g (patt2term p) >>= return . snd
|
||||||
|
|
||||||
|
|
||||||
-- type inference: Nothing, type checking: Just t
|
-- type inference: Nothing, type checking: Just t
|
||||||
-- the latter permits matching with value type
|
-- the latter permits matching with value type
|
||||||
getOverload :: SourceGrammar -> Context -> Maybe Type -> Term -> Check (Maybe (Term,Type))
|
getOverload :: SourceGrammar -> Context -> Maybe Type -> Term -> Check (Maybe (Term,Type))
|
||||||
@@ -310,15 +330,28 @@ getOverload gr g mt ot = case appForm ot of
|
|||||||
v <- matchOverload f typs ttys
|
v <- matchOverload f typs ttys
|
||||||
return $ Just v
|
return $ Just v
|
||||||
_ -> return Nothing
|
_ -> return Nothing
|
||||||
|
(AdHocOverload cs@(f:_), ts) -> do --- the function name f is only used in error messages
|
||||||
|
let typs = concatMap collectOverloads cs
|
||||||
|
ttys <- mapM (inferLType gr g) ts
|
||||||
|
v <- matchOverload f typs ttys
|
||||||
|
return $ Just v
|
||||||
_ -> return Nothing
|
_ -> return Nothing
|
||||||
|
|
||||||
where
|
where
|
||||||
|
collectOverloads tr@(Q c) = case lookupOverload gr c of
|
||||||
|
Ok typs -> typs
|
||||||
|
_ -> case lookupResType gr c of
|
||||||
|
Ok ty -> let (args,val) = typeFormCnc ty in [(map (\(b,x,t) -> t) args,(val,tr))]
|
||||||
|
_ -> []
|
||||||
|
collectOverloads _ = [] --- constructors QC
|
||||||
|
|
||||||
matchOverload f typs ttys = do
|
matchOverload f typs ttys = do
|
||||||
let (tts,tys) = unzip ttys
|
let (tts,tys) = unzip ttys
|
||||||
let vfs = lookupOverloadInstance tys typs
|
let vfs = lookupOverloadInstance tys typs
|
||||||
let matches = [vf | vf@((_,v,_),_) <- vfs, matchVal mt v]
|
let matches = [vf | vf@((_,v,_),_) <- vfs, matchVal mt v]
|
||||||
let showTypes ty = hsep (map ppType ty)
|
let showTypes ty = hsep (map ppType ty)
|
||||||
|
|
||||||
|
|
||||||
let (stys,styps) = (showTypes tys, [showTypes ty | (ty,_) <- typs])
|
let (stys,styps) = (showTypes tys, [showTypes ty | (ty,_) <- typs])
|
||||||
|
|
||||||
-- to avoid strange error msg e.g. in case of unmatch record extension, show whole types if needed AR 28/1/2013
|
-- to avoid strange error msg e.g. in case of unmatch record extension, show whole types if needed AR 28/1/2013
|
||||||
@@ -329,50 +362,57 @@ getOverload gr g mt ot = case appForm ot of
|
|||||||
case ([vf | (vf,True) <- matches],[vf | (vf,False) <- matches]) of
|
case ([vf | (vf,True) <- matches],[vf | (vf,False) <- matches]) of
|
||||||
([(_,val,fun)],_) -> return (mkApp fun tts, val)
|
([(_,val,fun)],_) -> return (mkApp fun tts, val)
|
||||||
([],[(pre,val,fun)]) -> do
|
([],[(pre,val,fun)]) -> do
|
||||||
checkWarn $ text "ignoring lock fields in resolving" <+> ppTerm Unqualified 0 ot $$
|
checkWarn $ "ignoring lock fields in resolving" <+> ppTerm Unqualified 0 ot $$
|
||||||
text "for" $$
|
"for" $$
|
||||||
nest 2 (showTypes tys) $$
|
nest 2 (showTypes tys) $$
|
||||||
text "using" $$
|
"using" $$
|
||||||
nest 2 (showTypes pre)
|
nest 2 (showTypes pre)
|
||||||
return (mkApp fun tts, val)
|
return (mkApp fun tts, val)
|
||||||
([],[]) -> do
|
([],[]) -> do
|
||||||
checkError $ text "no overload instance of" <+> ppTerm Unqualified 0 f $$
|
checkError $ "no overload instance of" <+> ppTerm Qualified 0 f $$
|
||||||
text "for" $$
|
maybe empty (\x -> "with value type" <+> ppType x) mt $$
|
||||||
|
"for argument list" $$
|
||||||
nest 2 stysError $$
|
nest 2 stysError $$
|
||||||
text "among" $$
|
"among alternatives" $$
|
||||||
nest 2 (vcat stypsError) $$
|
nest 2 (vcat stypsError)
|
||||||
maybe empty (\x -> text "with value type" <+> ppType x) mt
|
|
||||||
|
|
||||||
(vfs1,vfs2) -> case (noProds vfs1,noProds vfs2) of
|
(vfs1,vfs2) -> case (noProds vfs1,noProds vfs2) of
|
||||||
([(val,fun)],_) -> do
|
([(val,fun)],_) -> do
|
||||||
return (mkApp fun tts, val)
|
return (mkApp fun tts, val)
|
||||||
([],[(val,fun)]) -> do
|
([],[(val,fun)]) -> do
|
||||||
checkWarn (text "ignoring lock fields in resolving" <+> ppTerm Unqualified 0 ot)
|
checkWarn ("ignoring lock fields in resolving" <+> ppTerm Unqualified 0 ot)
|
||||||
return (mkApp fun tts, val)
|
return (mkApp fun tts, val)
|
||||||
|
|
||||||
----- unsafely exclude irritating warning AR 24/5/2008
|
----- unsafely exclude irritating warning AR 24/5/2008
|
||||||
----- checkWarn $ "overloading of" +++ prt f +++
|
----- checkWarn $ "overloading of" +++ prt f +++
|
||||||
----- "resolved by excluding partial applications:" ++++
|
----- "resolved by excluding partial applications:" ++++
|
||||||
----- unlines [prtType env ty | (ty,_) <- vfs', not (noProd ty)]
|
----- unlines [prtType env ty | (ty,_) <- vfs', not (noProd ty)]
|
||||||
|
|
||||||
|
--- now forgiving ambiguity with a warning AR 1/2/2014
|
||||||
_ -> checkError $ text "ambiguous overloading of" <+> ppTerm Unqualified 0 f <+>
|
-- This gives ad hoc overloading the same behaviour as the choice of the first match in renaming did before.
|
||||||
text "for" <+> hsep (map ppType tys) $$
|
-- But it also gives a chance to ambiguous overloadings that were banned before.
|
||||||
text "with alternatives" $$
|
(nps1,nps2) -> do
|
||||||
nest 2 (vcat [ppType ty | (_,ty,_) <- if null vfs1 then vfs2 else vfs2])
|
checkWarn $ "ambiguous overloading of" <+> ppTerm Unqualified 0 f <+>
|
||||||
|
---- "with argument types" <+> hsep (map (ppTerm Qualified 0) tys) $$
|
||||||
|
"resolved by selecting the first of the alternatives" $$
|
||||||
|
nest 2 (vcat [ppTerm Qualified 0 fun | (_,ty,fun) <- vfs1 ++ if null vfs1 then vfs2 else []])
|
||||||
|
case [(mkApp fun tts,val) | (val,fun) <- nps1 ++ nps2] of
|
||||||
|
[] -> checkError $ "no alternatives left when resolving" <+> ppTerm Unqualified 0 f
|
||||||
|
h:_ -> return h
|
||||||
|
|
||||||
matchVal mt v = elem mt [Nothing,Just v,Just (unlocked v)]
|
matchVal mt v = elem mt [Nothing,Just v,Just (unlocked v)]
|
||||||
|
|
||||||
unlocked v = case v of
|
unlocked v = case v of
|
||||||
RecType fs -> RecType $ filter (not . isLockLabel . fst) fs
|
RecType fs -> RecType $ filter (not . isLockLabel . fst) (sortRec fs)
|
||||||
_ -> v
|
_ -> v
|
||||||
---- TODO: accept subtypes
|
---- TODO: accept subtypes
|
||||||
---- TODO: use a trie
|
---- TODO: use a trie
|
||||||
lookupOverloadInstance tys typs =
|
lookupOverloadInstance tys typs =
|
||||||
[((pre,mkFunType rest val, t),isExact) |
|
[((pre,mkFunType rest val, t),isExact) |
|
||||||
let lt = length tys,
|
let lt = length tys,
|
||||||
(ty,(val,t)) <- typs, length ty >= lt,
|
(ty,(val,t)) <- typs, length ty >= lt,
|
||||||
let (pre,rest) = splitAt lt ty,
|
let (pre,rest) = splitAt lt ty,
|
||||||
let isExact = pre == tys,
|
let isExact = pre == tys,
|
||||||
isExact || map unlocked pre == map unlocked tys
|
isExact || map unlocked pre == map unlocked tys
|
||||||
]
|
]
|
||||||
@@ -385,20 +425,21 @@ getOverload gr g mt ot = case appForm ot of
|
|||||||
|
|
||||||
checkLType :: SourceGrammar -> Context -> Term -> Type -> Check (Term, Type)
|
checkLType :: SourceGrammar -> Context -> Term -> Type -> Check (Term, Type)
|
||||||
checkLType gr g trm typ0 = do
|
checkLType gr g trm typ0 = do
|
||||||
|
|
||||||
typ <- computeLType gr g typ0
|
typ <- computeLType gr g typ0
|
||||||
|
|
||||||
case trm of
|
case trm of
|
||||||
|
|
||||||
Abs bt x c -> do
|
Abs bt x c -> do
|
||||||
case typ of
|
case typ of
|
||||||
Prod bt' z a b -> do
|
Prod bt' z a b -> do
|
||||||
(c',b') <- if isWildIdent z
|
(c',b') <- if isWildIdent z
|
||||||
then checkLType gr ((bt,x,a):g) c b
|
then checkLType gr ((bt,x,a):g) c b
|
||||||
else do b' <- checkIn (text "abs") $ substituteLType [(bt',z,Vr x)] b
|
else do b' <- checkIn (pp "abs") $ substituteLType [(bt',z,Vr x)] b
|
||||||
checkLType gr ((bt,x,a):g) c b'
|
checkLType gr ((bt,x,a):g) c b'
|
||||||
return $ (Abs bt x c', Prod bt' x a b')
|
return $ (Abs bt x c', Prod bt' z a b')
|
||||||
_ -> checkError $ text "function type expected instead of" <+> ppType typ
|
_ -> checkError $ "function type expected instead of" <+> ppType typ $$
|
||||||
|
"\n ** Double-check that the type signature of the operation" $$
|
||||||
|
"matches the number of arguments given to it.\n"
|
||||||
|
|
||||||
App f a -> do
|
App f a -> do
|
||||||
over <- getOverload gr g (Just typ) trm
|
over <- getOverload gr g (Just typ) trm
|
||||||
@@ -408,6 +449,12 @@ checkLType gr g trm typ0 = do
|
|||||||
(trm',ty') <- inferLType gr g trm
|
(trm',ty') <- inferLType gr g trm
|
||||||
termWith trm' $ checkEqLType gr g typ ty' trm'
|
termWith trm' $ checkEqLType gr g typ ty' trm'
|
||||||
|
|
||||||
|
AdHocOverload ts -> do
|
||||||
|
over <- getOverload gr g Nothing trm
|
||||||
|
case over of
|
||||||
|
Just trty -> return trty
|
||||||
|
_ -> checkError ("unresolved overloading of constants" <+> ppTerm Qualified 0 trm)
|
||||||
|
|
||||||
Q _ -> do
|
Q _ -> do
|
||||||
over <- getOverload gr g (Just typ) trm
|
over <- getOverload gr g (Just typ) trm
|
||||||
case over of
|
case over of
|
||||||
@@ -417,21 +464,21 @@ checkLType gr g trm typ0 = do
|
|||||||
termWith trm' $ checkEqLType gr g typ ty' trm'
|
termWith trm' $ checkEqLType gr g typ ty' trm'
|
||||||
|
|
||||||
T _ [] ->
|
T _ [] ->
|
||||||
checkError (text "found empty table in type" <+> ppTerm Unqualified 0 typ)
|
checkError ("found empty table in type" <+> ppTerm Unqualified 0 typ)
|
||||||
T _ cs -> case typ of
|
T _ cs -> case typ of
|
||||||
Table arg val -> do
|
Table arg val -> do
|
||||||
case allParamValues gr arg of
|
case allParamValues gr arg of
|
||||||
Ok vs -> do
|
Ok vs -> do
|
||||||
let ps0 = map fst cs
|
let ps0 = map fst cs
|
||||||
ps <- testOvershadow ps0 vs
|
ps <- testOvershadow ps0 vs
|
||||||
if null ps
|
if null ps
|
||||||
then return ()
|
then return ()
|
||||||
else checkWarn (text "patterns never reached:" $$
|
else checkWarn ("patterns never reached:" $$
|
||||||
nest 2 (vcat (map (ppPatt Unqualified 0) ps)))
|
nest 2 (vcat (map (ppPatt Unqualified 0) ps)))
|
||||||
_ -> return () -- happens with variable types
|
_ -> return () -- happens with variable types
|
||||||
cs' <- mapM (checkCase arg val) cs
|
cs' <- mapM (checkCase arg val) cs
|
||||||
return (T (TTyped arg) cs', typ)
|
return (T (TTyped arg) cs', typ)
|
||||||
_ -> checkError $ text "table type expected for table instead of" $$ nest 2 (ppType typ)
|
_ -> checkError $ "table type expected for table instead of" $$ nest 2 (ppType typ)
|
||||||
V arg0 vs ->
|
V arg0 vs ->
|
||||||
case typ of
|
case typ of
|
||||||
Table arg1 val ->
|
Table arg1 val ->
|
||||||
@@ -439,51 +486,54 @@ checkLType gr g trm typ0 = do
|
|||||||
vs1 <- allParamValues gr arg1
|
vs1 <- allParamValues gr arg1
|
||||||
if length vs1 == length vs
|
if length vs1 == length vs
|
||||||
then return ()
|
then return ()
|
||||||
else checkError $ text "wrong number of values in table" <+> ppTerm Unqualified 0 trm
|
else checkError $ "wrong number of values in table" <+> ppTerm Unqualified 0 trm
|
||||||
vs' <- map fst `fmap` sequence [checkLType gr g v val|v<-vs]
|
vs' <- map fst `fmap` sequence [checkLType gr g v val|v<-vs]
|
||||||
return (V arg' vs',typ)
|
return (V arg' vs',typ)
|
||||||
|
|
||||||
R r -> case typ of --- why needed? because inference may be too difficult
|
R r -> case typ of --- why needed? because inference may be too difficult
|
||||||
RecType rr -> do
|
RecType rr -> do
|
||||||
let (ls,_) = unzip rr -- labels of expected type
|
--let (ls,_) = unzip rr -- labels of expected type
|
||||||
fsts <- mapM (checkM r) rr -- check that they are found in the record
|
fsts <- mapM (checkM r) rr -- check that they are found in the record
|
||||||
return $ (R fsts, typ) -- normalize record
|
return $ (R fsts, typ) -- normalize record
|
||||||
|
|
||||||
_ -> checkError (text "record type expected in type checking instead of" $$ nest 2 (ppTerm Unqualified 0 typ))
|
_ -> checkError ("record type expected in type checking instead of" $$ nest 2 (ppTerm Unqualified 0 typ))
|
||||||
|
|
||||||
ExtR r s -> case typ of
|
ExtR r s -> case typ of
|
||||||
_ | typ == typeType -> do
|
_ | typ == typeType -> do
|
||||||
trm' <- computeLType gr g trm
|
trm' <- computeLType gr g trm
|
||||||
case trm' of
|
case trm' of
|
||||||
RecType _ -> termWith trm $ return typeType
|
RecType _ -> termWith trm' $ return typeType
|
||||||
ExtR (Vr _) (RecType _) -> termWith trm $ return typeType
|
ExtR (Vr _) (RecType _) -> termWith trm' $ return typeType
|
||||||
-- ext t = t ** ...
|
-- ext t = t ** ...
|
||||||
_ -> checkError (text "invalid record type extension" <+> nest 2 (ppTerm Unqualified 0 trm))
|
_ -> checkError ("invalid record type extension" <+> nest 2 (ppTerm Unqualified 0 trm))
|
||||||
|
|
||||||
RecType rr -> do
|
RecType rr -> do
|
||||||
(r',ty,s') <- checks [
|
|
||||||
do (r',ty) <- inferLType gr g r
|
|
||||||
return (r',ty,s)
|
|
||||||
,
|
|
||||||
do (s',ty) <- inferLType gr g s
|
|
||||||
return (s',ty,r)
|
|
||||||
]
|
|
||||||
|
|
||||||
case ty of
|
ll2 <- case s of
|
||||||
RecType rr1 -> do
|
R ss -> return $ map fst ss
|
||||||
let (rr0,rr2) = recParts rr rr1
|
_ -> do
|
||||||
r2 <- justCheck g r' rr0
|
(s',typ2) <- inferLType gr g s
|
||||||
s2 <- justCheck g s' rr2
|
case typ2 of
|
||||||
return $ (ExtR r2 s2, typ)
|
RecType ss -> return $ map fst ss
|
||||||
_ -> checkError (text "record type expected in extension of" <+> ppTerm Unqualified 0 r $$
|
_ -> checkError ("cannot get labels from" $$ nest 2 (ppTerm Unqualified 0 typ2))
|
||||||
text "but found" <+> ppTerm Unqualified 0 ty)
|
let ll1 = [l | (l,_) <- rr, notElem l ll2]
|
||||||
|
|
||||||
|
--- over <- getOverload gr g Nothing r --- this would solve #66 but fail ParadigmsAra. AR 6/7/2020
|
||||||
|
--- let r1 = maybe r fst over
|
||||||
|
let r1 = r ---
|
||||||
|
|
||||||
|
(r',_) <- checkLType gr g r1 (RecType [field | field@(l,_) <- rr, elem l ll1])
|
||||||
|
(s',_) <- checkLType gr g s (RecType [field | field@(l,_) <- rr, elem l ll2])
|
||||||
|
|
||||||
|
let rec = R ([(l,(Nothing,P r' l)) | l <- ll1] ++ [(l,(Nothing,P s' l)) | l <- ll2])
|
||||||
|
return (rec, typ)
|
||||||
|
|
||||||
ExtR ty ex -> do
|
ExtR ty ex -> do
|
||||||
r' <- justCheck g r ty
|
r' <- justCheck g r ty
|
||||||
s' <- justCheck g s ex
|
s' <- justCheck g s ex
|
||||||
return $ (ExtR r' s', typ) --- is this all? it assumes the same division in trm and typ
|
return $ (ExtR r' s', typ) --- is this all? it assumes the same division in trm and typ
|
||||||
|
|
||||||
_ -> checkError (text "record extension not meaningful for" <+> ppTerm Unqualified 0 typ)
|
_ -> checkError ("record extension not meaningful for" <+> ppTerm Unqualified 0 typ)
|
||||||
|
|
||||||
FV vs -> do
|
FV vs -> do
|
||||||
ttys <- mapM (flip (checkLType gr g) typ) vs
|
ttys <- mapM (flip (checkLType gr g) typ) vs
|
||||||
@@ -498,7 +548,7 @@ checkLType gr g trm typ0 = do
|
|||||||
(arg',val) <- checkLType gr g arg p
|
(arg',val) <- checkLType gr g arg p
|
||||||
checkEqLType gr g typ t trm
|
checkEqLType gr g typ t trm
|
||||||
return (S tab' arg', t)
|
return (S tab' arg', t)
|
||||||
_ -> checkError (text "table type expected for applied table instead of" <+> ppType ty')
|
_ -> checkError ("table type expected for applied table instead of" <+> ppType ty')
|
||||||
, do
|
, do
|
||||||
(arg',ty) <- inferLType gr g arg
|
(arg',ty) <- inferLType gr g arg
|
||||||
ty' <- computeLType gr g ty
|
ty' <- computeLType gr g ty
|
||||||
@@ -507,7 +557,8 @@ checkLType gr g trm typ0 = do
|
|||||||
]
|
]
|
||||||
Let (x,(mty,def)) body -> case mty of
|
Let (x,(mty,def)) body -> case mty of
|
||||||
Just ty -> do
|
Just ty -> do
|
||||||
(def',ty') <- checkLType gr g def ty
|
(ty0,_) <- checkLType gr g ty typeType
|
||||||
|
(def',ty') <- checkLType gr g def ty0
|
||||||
body' <- justCheck ((Explicit,x,ty'):g) body typ
|
body' <- justCheck ((Explicit,x,ty'):g) body typ
|
||||||
return (Let (x,(Just ty',def')) body', typ)
|
return (Let (x,(Just ty',def')) body', typ)
|
||||||
_ -> do
|
_ -> do
|
||||||
@@ -523,10 +574,10 @@ checkLType gr g trm typ0 = do
|
|||||||
termWith trm' $ checkEqLType gr g typ ty' trm'
|
termWith trm' $ checkEqLType gr g typ ty' trm'
|
||||||
where
|
where
|
||||||
justCheck g ty te = checkLType gr g ty te >>= return . fst
|
justCheck g ty te = checkLType gr g ty te >>= return . fst
|
||||||
|
{-
|
||||||
recParts rr t = (RecType rr1,RecType rr2) where
|
recParts rr t = (RecType rr1,RecType rr2) where
|
||||||
(rr1,rr2) = partition (flip elem (map fst t) . fst) rr
|
(rr1,rr2) = partition (flip elem (map fst t) . fst) rr
|
||||||
|
-}
|
||||||
checkM rms (l,ty) = case lookup l rms of
|
checkM rms (l,ty) = case lookup l rms of
|
||||||
Just (Just ty0,t) -> do
|
Just (Just ty0,t) -> do
|
||||||
checkEqLType gr g ty ty0 t
|
checkEqLType gr g ty ty0 t
|
||||||
@@ -535,12 +586,12 @@ checkLType gr g trm typ0 = do
|
|||||||
Just (_,t) -> do
|
Just (_,t) -> do
|
||||||
(t',ty') <- checkLType gr g t ty
|
(t',ty') <- checkLType gr g t ty
|
||||||
return (l,(Just ty',t'))
|
return (l,(Just ty',t'))
|
||||||
_ -> checkError $
|
_ -> checkError $
|
||||||
if isLockLabel l
|
if isLockLabel l
|
||||||
then let cat = drop 5 (showIdent (label2ident l))
|
then let cat = drop 5 (showIdent (label2ident l))
|
||||||
in ppTerm Unqualified 0 (R rms) <+> text "is not in the lincat of" <+> text cat <>
|
in ppTerm Unqualified 0 (R rms) <+> "is not in the lincat of" <+> cat <>
|
||||||
text "; try wrapping it with lin" <+> text cat
|
"; try wrapping it with lin" <+> cat
|
||||||
else text "cannot find value for label" <+> ppLabel l <+> text "in" <+> ppTerm Unqualified 0 (R rms)
|
else "cannot find value for label" <+> l <+> "in" <+> ppTerm Unqualified 0 (R rms)
|
||||||
|
|
||||||
checkCase arg val (p,t) = do
|
checkCase arg val (p,t) = do
|
||||||
cont <- pattContext gr g arg p
|
cont <- pattContext gr g arg p
|
||||||
@@ -553,7 +604,7 @@ pattContext env g typ p = case p of
|
|||||||
PP (q,c) ps | q /= cPredef -> do ---- why this /=? AR 6/1/2006
|
PP (q,c) ps | q /= cPredef -> do ---- why this /=? AR 6/1/2006
|
||||||
t <- lookupResType env (q,c)
|
t <- lookupResType env (q,c)
|
||||||
let (cont,v) = typeFormCnc t
|
let (cont,v) = typeFormCnc t
|
||||||
checkCond (text "wrong number of arguments for constructor in" <+> ppPatt Unqualified 0 p)
|
checkCond ("wrong number of arguments for constructor in" <+> ppPatt Unqualified 0 p)
|
||||||
(length cont == length ps)
|
(length cont == length ps)
|
||||||
checkEqLType env g typ v (patt2term p)
|
checkEqLType env g typ v (patt2term p)
|
||||||
mapM (\((_,_,ty),p) -> pattContext env g ty p) (zip cont ps) >>= return . concat
|
mapM (\((_,_,ty),p) -> pattContext env g ty p) (zip cont ps) >>= return . concat
|
||||||
@@ -564,7 +615,7 @@ pattContext env g typ p = case p of
|
|||||||
let pts = [(ty,tr) | (l,tr) <- r, Just ty <- [lookup l t]]
|
let pts = [(ty,tr) | (l,tr) <- r, Just ty <- [lookup l t]]
|
||||||
----- checkWarn $ prt p ++++ show pts ----- debug
|
----- checkWarn $ prt p ++++ show pts ----- debug
|
||||||
mapM (uncurry (pattContext env g)) pts >>= return . concat
|
mapM (uncurry (pattContext env g)) pts >>= return . concat
|
||||||
_ -> checkError (text "record type expected for pattern instead of" <+> ppTerm Unqualified 0 typ')
|
_ -> checkError ("record type expected for pattern instead of" <+> ppTerm Unqualified 0 typ')
|
||||||
PT t p' -> do
|
PT t p' -> do
|
||||||
checkEqLType env g typ t (patt2term p')
|
checkEqLType env g typ t (patt2term p')
|
||||||
pattContext env g typ p'
|
pattContext env g typ p'
|
||||||
@@ -577,10 +628,10 @@ pattContext env g typ p = case p of
|
|||||||
g1 <- pattContext env g typ p'
|
g1 <- pattContext env g typ p'
|
||||||
g2 <- pattContext env g typ q
|
g2 <- pattContext env g typ q
|
||||||
let pts = nub ([x | pt@(_,x,_) <- g1, notElem pt g2] ++ [x | pt@(_,x,_) <- g2, notElem pt g1])
|
let pts = nub ([x | pt@(_,x,_) <- g1, notElem pt g2] ++ [x | pt@(_,x,_) <- g2, notElem pt g1])
|
||||||
checkCond
|
checkCond
|
||||||
(text "incompatible bindings of" <+>
|
("incompatible bindings of" <+>
|
||||||
fsep (map ppIdent pts) <+>
|
fsep pts <+>
|
||||||
text "in pattern alterantives" <+> ppPatt Unqualified 0 p) (null pts)
|
"in pattern alterantives" <+> ppPatt Unqualified 0 p) (null pts)
|
||||||
return g1 -- must be g1 == g2
|
return g1 -- must be g1 == g2
|
||||||
PSeq p q -> do
|
PSeq p q -> do
|
||||||
g1 <- pattContext env g typ p
|
g1 <- pattContext env g typ p
|
||||||
@@ -590,11 +641,11 @@ pattContext env g typ p = case p of
|
|||||||
PNeg p' -> noBind typ p'
|
PNeg p' -> noBind typ p'
|
||||||
|
|
||||||
_ -> return [] ---- check types!
|
_ -> return [] ---- check types!
|
||||||
where
|
where
|
||||||
noBind typ p' = do
|
noBind typ p' = do
|
||||||
co <- pattContext env g typ p'
|
co <- pattContext env g typ p'
|
||||||
if not (null co)
|
if not (null co)
|
||||||
then checkWarn (text "no variable bound inside pattern" <+> ppPatt Unqualified 0 p)
|
then checkWarn ("no variable bound inside pattern" <+> ppPatt Unqualified 0 p)
|
||||||
>> return []
|
>> return []
|
||||||
else return []
|
else return []
|
||||||
|
|
||||||
@@ -603,9 +654,31 @@ checkEqLType gr g t u trm = do
|
|||||||
(b,t',u',s) <- checkIfEqLType gr g t u trm
|
(b,t',u',s) <- checkIfEqLType gr g t u trm
|
||||||
case b of
|
case b of
|
||||||
True -> return t'
|
True -> return t'
|
||||||
False -> checkError $ text s <+> text "type of" <+> ppTerm Unqualified 0 trm $$
|
False ->
|
||||||
text "expected:" <+> ppType t $$
|
let inferredType = ppTerm Qualified 0 u
|
||||||
text "inferred:" <+> ppType u
|
expectedType = ppTerm Qualified 0 t
|
||||||
|
term = ppTerm Unqualified 0 trm
|
||||||
|
funName = pp . head . words .render $ term
|
||||||
|
helpfulMsg =
|
||||||
|
case (arrows inferredType, arrows expectedType) of
|
||||||
|
(0,0) -> pp "" -- None of the types is a function
|
||||||
|
_ -> "\n **" <+>
|
||||||
|
if expectedType `isLessApplied` inferredType
|
||||||
|
then "Maybe you gave too few arguments to" <+> funName
|
||||||
|
else pp "Double-check that type signature and number of arguments match."
|
||||||
|
in checkError $ s <+> "type of" <+> term $$
|
||||||
|
"expected:" <+> expectedType $$ -- ppqType t u $$
|
||||||
|
"inferred:" <+> inferredType $$ -- ppqType u t
|
||||||
|
helpfulMsg
|
||||||
|
where
|
||||||
|
-- count the number of arrows in the prettyprinted term
|
||||||
|
arrows :: Doc -> Int
|
||||||
|
arrows = length . filter (=="->") . words . render
|
||||||
|
|
||||||
|
-- If prettyprinted type t has fewer arrows then prettyprinted type u,
|
||||||
|
-- then t is "less applied", and we can print out more helpful error msg.
|
||||||
|
isLessApplied :: Doc -> Doc -> Bool
|
||||||
|
isLessApplied t u = arrows t < arrows u
|
||||||
|
|
||||||
checkIfEqLType :: SourceGrammar -> Context -> Type -> Type -> Term -> Check (Bool,Type,Type,String)
|
checkIfEqLType :: SourceGrammar -> Context -> Type -> Type -> Term -> Check (Bool,Type,Type,String)
|
||||||
checkIfEqLType gr g t u trm = do
|
checkIfEqLType gr g t u trm = do
|
||||||
@@ -617,60 +690,62 @@ checkIfEqLType gr g t u trm = do
|
|||||||
--- better: use a flag to forgive? (AR 31/1/2006)
|
--- better: use a flag to forgive? (AR 31/1/2006)
|
||||||
_ -> case missingLock [] t' u' of
|
_ -> case missingLock [] t' u' of
|
||||||
Ok lo -> do
|
Ok lo -> do
|
||||||
checkWarn $ text "missing lock field" <+> fsep (map ppLabel lo)
|
checkWarn $ "missing lock field" <+> fsep lo
|
||||||
return (True,t',u',[])
|
return (True,t',u',[])
|
||||||
Bad s -> return (False,t',u',s)
|
Bad s -> return (False,t',u',s)
|
||||||
|
|
||||||
where
|
where
|
||||||
|
|
||||||
-- t is a subtype of u
|
-- check that u is a subtype of t
|
||||||
--- quick hack version of TC.eqVal
|
--- quick hack version of TC.eqVal
|
||||||
alpha g t u = case (t,u) of
|
alpha g t u = case (t,u) of
|
||||||
|
|
||||||
-- error (the empty type!) is subtype of any other type
|
-- error (the empty type!) is subtype of any other type
|
||||||
(_,u) | u == typeError -> True
|
(_,u) | u == typeError -> True
|
||||||
|
|
||||||
-- contravariance
|
-- contravariance
|
||||||
(Prod _ x a b, Prod _ y c d) -> alpha g c a && alpha ((x,y):g) b d
|
(Prod _ x a b, Prod _ y c d) -> alpha g c a && alpha ((x,y):g) b d
|
||||||
|
|
||||||
-- record subtyping
|
-- record subtyping
|
||||||
(RecType rs, RecType ts) -> all (\ (l,a) ->
|
(RecType rs, RecType ts) -> all (\ (l,a) ->
|
||||||
any (\ (k,b) -> alpha g a b && l == k) ts) rs
|
any (\ (k,b) -> l == k && alpha g a b) ts) rs
|
||||||
(ExtR r s, ExtR r' s') -> alpha g r r' && alpha g s s'
|
(ExtR r s, ExtR r' s') -> alpha g r r' && alpha g s s'
|
||||||
(ExtR r s, t) -> alpha g r t || alpha g s t
|
(ExtR r s, t) -> alpha g r t || alpha g s t
|
||||||
|
|
||||||
-- the following say that Ints n is a subset of Int and of Ints m >= n
|
-- the following say that Ints n is a subset of Int and of Ints m >= n
|
||||||
(t,u) | Just m <- isTypeInts t, Just n <- isTypeInts t -> m >= n
|
-- But why does it also allow Int as a subtype of Ints m? /TH 2014-04-04
|
||||||
|
(t,u) | Just m <- isTypeInts t, Just n <- isTypeInts u -> m >= n
|
||||||
| Just _ <- isTypeInts t, u == typeInt -> True ---- check size!
|
| Just _ <- isTypeInts t, u == typeInt -> True ---- check size!
|
||||||
| t == typeInt, Just _ <- isTypeInts u -> True ---- why this ???? AR 11/12/2005
|
| t == typeInt, Just _ <- isTypeInts u -> True ---- why this ???? AR 11/12/2005
|
||||||
|
|
||||||
---- this should be made in Rename
|
---- this should be made in Rename
|
||||||
(Q (m,a), Q (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
(Q (m,a), Q (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
||||||
|| elem n (allExtendsPlus gr m)
|
|| elem n (allExtendsPlus gr m)
|
||||||
|| m == n --- for Predef
|
|| m == n --- for Predef
|
||||||
(QC (m,a), QC (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
(QC (m,a), QC (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
||||||
|| elem n (allExtendsPlus gr m)
|
|| elem n (allExtendsPlus gr m)
|
||||||
(QC (m,a), Q (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
(QC (m,a), Q (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
||||||
|| elem n (allExtendsPlus gr m)
|
|| elem n (allExtendsPlus gr m)
|
||||||
(Q (m,a), QC (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
(Q (m,a), QC (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
||||||
|| elem n (allExtendsPlus gr m)
|
|| elem n (allExtendsPlus gr m)
|
||||||
|
|
||||||
(Table a b, Table c d) -> alpha g a c && alpha g b d
|
-- contravariance
|
||||||
|
(Table a b, Table c d) -> alpha g c a && alpha g b d
|
||||||
(Vr x, Vr y) -> x == y || elem (x,y) g || elem (y,x) g
|
(Vr x, Vr y) -> x == y || elem (x,y) g || elem (y,x) g
|
||||||
_ -> t == u
|
_ -> t == u
|
||||||
--- the following should be one-way coercions only. AR 4/1/2001
|
--- the following should be one-way coercions only. AR 4/1/2001
|
||||||
|| elem t sTypes && elem u sTypes
|
|| elem t sTypes && elem u sTypes
|
||||||
|| (t == typeType && u == typePType)
|
|| (t == typeType && u == typePType)
|
||||||
|| (u == typeType && t == typePType)
|
|| (u == typeType && t == typePType)
|
||||||
|
|
||||||
missingLock g t u = case (t,u) of
|
missingLock g t u = case (t,u) of
|
||||||
(RecType rs, RecType ts) ->
|
(RecType rs, RecType ts) ->
|
||||||
let
|
let
|
||||||
ls = [l | (l,a) <- rs,
|
ls = [l | (l,a) <- rs,
|
||||||
not (any (\ (k,b) -> alpha g a b && l == k) ts)]
|
not (any (\ (k,b) -> alpha g a b && l == k) ts)]
|
||||||
(locks,others) = partition isLockLabel ls
|
(locks,others) = partition isLockLabel ls
|
||||||
in case others of
|
in case others of
|
||||||
_:_ -> Bad $ render (text "missing record fields:" <+> fsep (punctuate comma (map ppLabel others)))
|
_:_ -> Bad $ render ("missing record fields:" <+> fsep (punctuate ',' (others)))
|
||||||
_ -> return locks
|
_ -> return locks
|
||||||
-- contravariance
|
-- contravariance
|
||||||
(Prod _ x a b, Prod _ y c d) -> do
|
(Prod _ x a b, Prod _ y c d) -> do
|
||||||
@@ -696,7 +771,7 @@ termWith t ct = do
|
|||||||
return (t,ty)
|
return (t,ty)
|
||||||
|
|
||||||
-- | compositional check\/infer of binary operations
|
-- | compositional check\/infer of binary operations
|
||||||
check2 :: (Term -> Check Term) -> (Term -> Term -> Term) ->
|
check2 :: (Term -> Check Term) -> (Term -> Term -> Term) ->
|
||||||
Term -> Term -> Type -> Check (Term,Type)
|
Term -> Term -> Type -> Check (Term,Type)
|
||||||
check2 chk con a b t = do
|
check2 chk con a b t = do
|
||||||
a' <- chk a
|
a' <- chk a
|
||||||
@@ -708,14 +783,18 @@ ppType :: Type -> Doc
|
|||||||
ppType ty =
|
ppType ty =
|
||||||
case ty of
|
case ty of
|
||||||
RecType fs -> case filter isLockLabel $ map fst fs of
|
RecType fs -> case filter isLockLabel $ map fst fs of
|
||||||
[lock] -> text (drop 5 (showIdent (label2ident lock)))
|
[lock] -> pp (drop 5 (showIdent (label2ident lock)))
|
||||||
_ -> ppTerm Unqualified 0 ty
|
_ -> ppTerm Unqualified 0 ty
|
||||||
Prod _ x a b -> ppType a <+> text "->" <+> ppType b
|
Prod _ x a b -> ppType a <+> "->" <+> ppType b
|
||||||
_ -> ppTerm Unqualified 0 ty
|
_ -> ppTerm Unqualified 0 ty
|
||||||
|
{-
|
||||||
|
ppqType :: Type -> Type -> Doc
|
||||||
|
ppqType t u = case (ppType t, ppType u) of
|
||||||
|
(pt,pu) | render pt == render pu -> ppTerm Qualified 0 t
|
||||||
|
(pt,_) -> pt
|
||||||
|
-}
|
||||||
checkLookup :: Ident -> Context -> Check Type
|
checkLookup :: Ident -> Context -> Check Type
|
||||||
checkLookup x g =
|
checkLookup x g =
|
||||||
case [ty | (b,y,ty) <- g, x == y] of
|
case [ty | (b,y,ty) <- g, x == y] of
|
||||||
[] -> checkError (text "unknown variable" <+> ppIdent x)
|
[] -> checkError ("unknown variable" <+> x)
|
||||||
(ty:_) -> return ty
|
(ty:_) -> return ty
|
||||||
-}
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import GF.Grammar hiding (Env, VGen, VApp, VRecType)
|
|||||||
import GF.Grammar.Lookup
|
import GF.Grammar.Lookup
|
||||||
import GF.Grammar.Predef
|
import GF.Grammar.Predef
|
||||||
import GF.Grammar.Lockfield
|
import GF.Grammar.Lockfield
|
||||||
import GF.Compile.Compute.ConcreteNew
|
import GF.Compile.Compute.Concrete
|
||||||
import GF.Compile.Compute.Predef(predef,predefName)
|
import GF.Compile.Compute.Predef(predef,predefName)
|
||||||
import GF.Infra.CheckM
|
import GF.Infra.CheckM
|
||||||
import GF.Data.Operations
|
import GF.Data.Operations
|
||||||
@@ -133,7 +133,7 @@ tcRho ge scope t@(RecType rs) (Just ty) = do
|
|||||||
[] -> unifyVar ge scope i env vs vtypePType
|
[] -> unifyVar ge scope i env vs vtypePType
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
ty -> do ty <- zonkTerm =<< tc_value2term (geLoc ge) (scopeVars scope) ty
|
ty -> do ty <- zonkTerm =<< tc_value2term (geLoc ge) (scopeVars scope) ty
|
||||||
tcError ("The record type" <+> ppTerm Unqualified 0 t $$
|
tcError ("The record type" <+> ppTerm Unqualified 0 t $$
|
||||||
"cannot be of type" <+> ppTerm Unqualified 0 ty)
|
"cannot be of type" <+> ppTerm Unqualified 0 ty)
|
||||||
(rs,mb_ty) <- tcRecTypeFields ge scope rs (Just ty')
|
(rs,mb_ty) <- tcRecTypeFields ge scope rs (Just ty')
|
||||||
return (f (RecType rs),ty)
|
return (f (RecType rs),ty)
|
||||||
@@ -187,7 +187,7 @@ tcRho ge scope (R rs) (Just ty) = do
|
|||||||
case ty' of
|
case ty' of
|
||||||
(VRecType ltys) -> do lttys <- checkRecFields ge scope rs ltys
|
(VRecType ltys) -> do lttys <- checkRecFields ge scope rs ltys
|
||||||
rs <- mapM (\(l,t,ty) -> tc_value2term (geLoc ge) (scopeVars scope) ty >>= \ty -> return (l, (Just ty, t))) lttys
|
rs <- mapM (\(l,t,ty) -> tc_value2term (geLoc ge) (scopeVars scope) ty >>= \ty -> return (l, (Just ty, t))) lttys
|
||||||
return ((f . R) rs,
|
return ((f . R) rs,
|
||||||
VRecType [(l, ty) | (l,t,ty) <- lttys]
|
VRecType [(l, ty) | (l,t,ty) <- lttys]
|
||||||
)
|
)
|
||||||
ty -> do lttys <- inferRecFields ge scope rs
|
ty -> do lttys <- inferRecFields ge scope rs
|
||||||
@@ -277,11 +277,11 @@ tcApp ge scope (App fun arg) = -- APP2
|
|||||||
varg <- liftErr (eval ge (scopeEnv scope) arg)
|
varg <- liftErr (eval ge (scopeEnv scope) arg)
|
||||||
return (App fun arg, res_ty varg)
|
return (App fun arg, res_ty varg)
|
||||||
tcApp ge scope (Q id) = -- VAR (global)
|
tcApp ge scope (Q id) = -- VAR (global)
|
||||||
mkTcA (lookupOverloadTypes (geGrammar ge) id) `bindTcA` \(t,ty) ->
|
mkTcA (lookupOverloadTypes (geGrammar ge) id) `bindTcA` \(t,ty) ->
|
||||||
do ty <- liftErr (eval ge [] ty)
|
do ty <- liftErr (eval ge [] ty)
|
||||||
return (t,ty)
|
return (t,ty)
|
||||||
tcApp ge scope (QC id) = -- VAR (global)
|
tcApp ge scope (QC id) = -- VAR (global)
|
||||||
mkTcA (lookupOverloadTypes (geGrammar ge) id) `bindTcA` \(t,ty) ->
|
mkTcA (lookupOverloadTypes (geGrammar ge) id) `bindTcA` \(t,ty) ->
|
||||||
do ty <- liftErr (eval ge [] ty)
|
do ty <- liftErr (eval ge [] ty)
|
||||||
return (t,ty)
|
return (t,ty)
|
||||||
tcApp ge scope t =
|
tcApp ge scope t =
|
||||||
@@ -350,7 +350,7 @@ tcPatt ge scope (PM q) ty0 = do
|
|||||||
Bad err -> tcError (pp err)
|
Bad err -> tcError (pp err)
|
||||||
tcPatt ge scope p ty = unimplemented ("tcPatt "++show p)
|
tcPatt ge scope p ty = unimplemented ("tcPatt "++show p)
|
||||||
|
|
||||||
inferRecFields ge scope rs =
|
inferRecFields ge scope rs =
|
||||||
mapM (\(l,r) -> tcRecField ge scope l r Nothing) rs
|
mapM (\(l,r) -> tcRecField ge scope l r Nothing) rs
|
||||||
|
|
||||||
checkRecFields ge scope [] ltys
|
checkRecFields ge scope [] ltys
|
||||||
@@ -368,7 +368,7 @@ checkRecFields ge scope ((l,t):lts) ltys =
|
|||||||
where
|
where
|
||||||
takeIt l1 [] = (Nothing, [])
|
takeIt l1 [] = (Nothing, [])
|
||||||
takeIt l1 (lty@(l2,ty):ltys)
|
takeIt l1 (lty@(l2,ty):ltys)
|
||||||
| l1 == l2 = (Just ty,ltys)
|
| l1 == l2 = (Just ty,ltys)
|
||||||
| otherwise = let (mb_ty,ltys') = takeIt l1 ltys
|
| otherwise = let (mb_ty,ltys') = takeIt l1 ltys
|
||||||
in (mb_ty,lty:ltys')
|
in (mb_ty,lty:ltys')
|
||||||
|
|
||||||
@@ -390,13 +390,13 @@ tcRecTypeFields ge scope ((l,ty):rs) mb_ty = do
|
|||||||
| s == cPType -> return mb_ty
|
| s == cPType -> return mb_ty
|
||||||
VMeta _ _ _ -> return mb_ty
|
VMeta _ _ _ -> return mb_ty
|
||||||
_ -> do sort <- zonkTerm =<< tc_value2term (geLoc ge) (scopeVars scope) sort
|
_ -> do sort <- zonkTerm =<< tc_value2term (geLoc ge) (scopeVars scope) sort
|
||||||
tcError ("The record type field" <+> l <+> ':' <+> ppTerm Unqualified 0 ty $$
|
tcError ("The record type field" <+> l <+> ':' <+> ppTerm Unqualified 0 ty $$
|
||||||
"cannot be of type" <+> ppTerm Unqualified 0 sort)
|
"cannot be of type" <+> ppTerm Unqualified 0 sort)
|
||||||
(rs,mb_ty) <- tcRecTypeFields ge scope rs mb_ty
|
(rs,mb_ty) <- tcRecTypeFields ge scope rs mb_ty
|
||||||
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
|
||||||
@@ -444,11 +444,11 @@ subsCheckRho ge scope t (VApp p1 _) (VApp p2 _) -- Rule
|
|||||||
| predefName p1 == cInts && predefName p2 == cInt = return t
|
| predefName p1 == cInts && predefName p2 == cInt = return t
|
||||||
subsCheckRho ge scope t (VApp p1 [VInt i]) (VApp p2 [VInt j]) -- Rule INT2
|
subsCheckRho ge scope t (VApp p1 [VInt i]) (VApp p2 [VInt j]) -- Rule INT2
|
||||||
| predefName p1 == cInts && predefName p2 == cInts =
|
| predefName p1 == cInts && predefName p2 == cInts =
|
||||||
if i <= j
|
if i <= j
|
||||||
then return t
|
then return t
|
||||||
else tcError ("Ints" <+> i <+> "is not a subtype of" <+> "Ints" <+> j)
|
else tcError ("Ints" <+> i <+> "is not a subtype of" <+> "Ints" <+> j)
|
||||||
subsCheckRho ge scope t ty1@(VRecType rs1) ty2@(VRecType rs2) = do -- Rule REC
|
subsCheckRho ge scope t ty1@(VRecType rs1) ty2@(VRecType rs2) = do -- Rule REC
|
||||||
let mkAccess scope t =
|
let mkAccess scope t =
|
||||||
case t of
|
case t of
|
||||||
ExtR t1 t2 -> do (scope,mkProj1,mkWrap1) <- mkAccess scope t1
|
ExtR t1 t2 -> do (scope,mkProj1,mkWrap1) <- mkAccess scope t1
|
||||||
(scope,mkProj2,mkWrap2) <- mkAccess scope t2
|
(scope,mkProj2,mkWrap2) <- mkAccess scope t2
|
||||||
@@ -557,7 +557,7 @@ unify ge scope v (VMeta i env vs) = unifyVar ge scope i env vs v
|
|||||||
unify ge scope v1 v2 = do
|
unify ge scope v1 v2 = do
|
||||||
t1 <- zonkTerm =<< tc_value2term (geLoc ge) (scopeVars scope) v1
|
t1 <- zonkTerm =<< tc_value2term (geLoc ge) (scopeVars scope) v1
|
||||||
t2 <- zonkTerm =<< tc_value2term (geLoc ge) (scopeVars scope) v2
|
t2 <- zonkTerm =<< tc_value2term (geLoc ge) (scopeVars scope) v2
|
||||||
tcError ("Cannot unify terms:" <+> (ppTerm Unqualified 0 t1 $$
|
tcError ("Cannot unify terms:" <+> (ppTerm Unqualified 0 t1 $$
|
||||||
ppTerm Unqualified 0 t2))
|
ppTerm Unqualified 0 t2))
|
||||||
|
|
||||||
-- | Invariant: tv1 is a flexible type variable
|
-- | Invariant: tv1 is a flexible type variable
|
||||||
@@ -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'))
|
||||||
@@ -609,7 +609,7 @@ quantify ge scope t tvs ty0 = do
|
|||||||
ty <- tc_value2term (geLoc ge) (scopeVars scope) ty0
|
ty <- tc_value2term (geLoc ge) (scopeVars scope) ty0
|
||||||
let used_bndrs = nub (bndrs ty) -- Avoid quantified type variables in use
|
let used_bndrs = nub (bndrs ty) -- Avoid quantified type variables in use
|
||||||
new_bndrs = take (length tvs) (allBinders \\ used_bndrs)
|
new_bndrs = take (length tvs) (allBinders \\ used_bndrs)
|
||||||
mapM_ bind (tvs `zip` new_bndrs) -- 'bind' is just a cunning way
|
mapM_ bind (tvs `zip` new_bndrs) -- 'bind' is just a cunning way
|
||||||
ty <- zonkTerm ty -- of doing the substitution
|
ty <- zonkTerm ty -- of doing the substitution
|
||||||
vty <- liftErr (eval ge [] (foldr (\v ty -> Prod Implicit v typeType ty) ty new_bndrs))
|
vty <- liftErr (eval ge [] (foldr (\v ty -> Prod Implicit v typeType ty) ty new_bndrs))
|
||||||
return (foldr (Abs Implicit) t new_bndrs,vty)
|
return (foldr (Abs Implicit) t new_bndrs,vty)
|
||||||
@@ -619,7 +619,7 @@ quantify ge scope t tvs ty0 = do
|
|||||||
bndrs (Prod _ x t1 t2) = [x] ++ bndrs t1 ++ bndrs t2
|
bndrs (Prod _ x t1 t2) = [x] ++ bndrs t1 ++ bndrs t2
|
||||||
bndrs _ = []
|
bndrs _ = []
|
||||||
|
|
||||||
allBinders :: [Ident] -- a,b,..z, a1, b1,... z1, a2, b2,...
|
allBinders :: [Ident] -- a,b,..z, a1, b1,... z1, a2, b2,...
|
||||||
allBinders = [ identS [x] | x <- ['a'..'z'] ] ++
|
allBinders = [ identS [x] | x <- ['a'..'z'] ] ++
|
||||||
[ identS (x : show i) | i <- [1 :: Integer ..], x <- ['a'..'z']]
|
[ identS (x : show i) | i <- [1 :: Integer ..], x <- ['a'..'z']]
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -688,12 +688,12 @@ runTcM f = case unTcM f IntMap.empty [] of
|
|||||||
TcFail (msg:msgs) -> do checkWarnings msgs; checkError msg
|
TcFail (msg:msgs) -> do checkWarnings msgs; checkError msg
|
||||||
|
|
||||||
newMeta :: Scope -> Sigma -> TcM MetaId
|
newMeta :: Scope -> Sigma -> TcM MetaId
|
||||||
newMeta scope ty = TcM (\ms msgs ->
|
newMeta scope ty = TcM (\ms msgs ->
|
||||||
let i = IntMap.size ms
|
let i = IntMap.size ms
|
||||||
in TcOk i (IntMap.insert i (Unbound scope ty) ms) msgs)
|
in TcOk i (IntMap.insert i (Unbound scope ty) ms) msgs)
|
||||||
|
|
||||||
getMeta :: MetaId -> TcM MetaValue
|
getMeta :: MetaId -> TcM MetaValue
|
||||||
getMeta i = TcM (\ms msgs ->
|
getMeta i = TcM (\ms msgs ->
|
||||||
case IntMap.lookup i ms of
|
case IntMap.lookup i ms of
|
||||||
Just mv -> TcOk mv ms msgs
|
Just mv -> TcOk mv ms msgs
|
||||||
Nothing -> TcFail (("Unknown metavariable" <+> ppMeta i) : msgs))
|
Nothing -> TcFail (("Unknown metavariable" <+> ppMeta i) : msgs))
|
||||||
@@ -702,7 +702,7 @@ setMeta :: MetaId -> MetaValue -> TcM ()
|
|||||||
setMeta i mv = TcM (\ms msgs -> TcOk () (IntMap.insert i mv ms) msgs)
|
setMeta i mv = TcM (\ms msgs -> TcOk () (IntMap.insert i mv ms) msgs)
|
||||||
|
|
||||||
newVar :: Scope -> Ident
|
newVar :: Scope -> Ident
|
||||||
newVar scope = head [x | i <- [1..],
|
newVar scope = head [x | i <- [1..],
|
||||||
let x = identS ('v':show i),
|
let x = identS ('v':show i),
|
||||||
isFree scope x]
|
isFree scope x]
|
||||||
where
|
where
|
||||||
@@ -721,11 +721,11 @@ getMetaVars loc sc_tys = do
|
|||||||
return (foldr go [] tys)
|
return (foldr go [] tys)
|
||||||
where
|
where
|
||||||
-- Get the MetaIds from a term; no duplicates in result
|
-- Get the MetaIds from a term; no duplicates in result
|
||||||
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
|
||||||
@@ -741,10 +741,10 @@ getFreeVars loc sc_tys = do
|
|||||||
tys <- mapM (\(scope,ty) -> zonkTerm =<< tc_value2term loc (scopeVars scope) ty) sc_tys
|
tys <- mapM (\(scope,ty) -> zonkTerm =<< tc_value2term loc (scopeVars scope) ty) sc_tys
|
||||||
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,13 +765,13 @@ 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")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data TcA x a
|
data TcA x a
|
||||||
= TcSingle (MetaStore -> [Message] -> TcResult a)
|
= TcSingle (MetaStore -> [Message] -> TcResult a)
|
||||||
| TcMany [x] (MetaStore -> [Message] -> [(a,MetaStore,[Message])])
|
| TcMany [x] (MetaStore -> [Message] -> [(a,MetaStore,[Message])])
|
||||||
|
|
||||||
|
|||||||
@@ -1,801 +0,0 @@
|
|||||||
{-# LANGUAGE PatternGuards #-}
|
|
||||||
module GF.Compile.TypeCheck.RConcrete( checkLType, inferLType, computeLType, ppType ) where
|
|
||||||
import Prelude hiding ((<>)) -- GHC 8.4.1 clash with Text.PrettyPrint
|
|
||||||
|
|
||||||
import GF.Infra.CheckM
|
|
||||||
import GF.Data.Operations
|
|
||||||
|
|
||||||
import GF.Grammar
|
|
||||||
import GF.Grammar.Lookup
|
|
||||||
import GF.Grammar.Predef
|
|
||||||
import GF.Grammar.PatternMatch
|
|
||||||
import GF.Grammar.Lockfield (isLockLabel, lockRecType, unlockRecord)
|
|
||||||
import GF.Compile.TypeCheck.Primitives
|
|
||||||
|
|
||||||
import Data.List
|
|
||||||
import Control.Monad
|
|
||||||
import GF.Text.Pretty
|
|
||||||
|
|
||||||
computeLType :: SourceGrammar -> Context -> Type -> Check Type
|
|
||||||
computeLType gr g0 t = comp (reverse [(b,x, Vr x) | (b,x,_) <- g0] ++ g0) t
|
|
||||||
where
|
|
||||||
comp g ty = case ty of
|
|
||||||
_ | Just _ <- isTypeInts ty -> return ty ---- shouldn't be needed
|
|
||||||
| isPredefConstant ty -> return ty ---- shouldn't be needed
|
|
||||||
|
|
||||||
Q (m,ident) -> checkIn ("module" <+> m) $ do
|
|
||||||
ty' <- lookupResDef gr (m,ident)
|
|
||||||
if ty' == ty then return ty else comp g ty' --- is this necessary to test?
|
|
||||||
|
|
||||||
AdHocOverload ts -> do
|
|
||||||
over <- getOverload gr g (Just typeType) t
|
|
||||||
case over of
|
|
||||||
Just (tr,_) -> return tr
|
|
||||||
_ -> checkError ("unresolved overloading of constants" <+> ppTerm Qualified 0 t)
|
|
||||||
|
|
||||||
Vr ident -> checkLookup ident g -- never needed to compute!
|
|
||||||
|
|
||||||
App f a -> do
|
|
||||||
f' <- comp g f
|
|
||||||
a' <- comp g a
|
|
||||||
case f' of
|
|
||||||
Abs b x t -> comp ((b,x,a'):g) t
|
|
||||||
_ -> return $ App f' a'
|
|
||||||
|
|
||||||
Prod bt x a b -> do
|
|
||||||
a' <- comp g a
|
|
||||||
b' <- comp ((bt,x,Vr x) : g) b
|
|
||||||
return $ Prod bt x a' b'
|
|
||||||
|
|
||||||
Abs bt x b -> do
|
|
||||||
b' <- comp ((bt,x,Vr x):g) b
|
|
||||||
return $ Abs bt x b'
|
|
||||||
|
|
||||||
Let (x,(_,a)) b -> comp ((Explicit,x,a):g) b
|
|
||||||
|
|
||||||
ExtR r s -> do
|
|
||||||
r' <- comp g r
|
|
||||||
s' <- comp g s
|
|
||||||
case (r',s') of
|
|
||||||
(RecType rs, RecType ss) -> plusRecType r' s' >>= comp g
|
|
||||||
_ -> return $ ExtR r' s'
|
|
||||||
|
|
||||||
RecType fs -> do
|
|
||||||
let fs' = sortRec fs
|
|
||||||
liftM RecType $ mapPairsM (comp g) fs'
|
|
||||||
|
|
||||||
ELincat c t -> do
|
|
||||||
t' <- comp g t
|
|
||||||
lockRecType c t' ---- locking to be removed AR 20/6/2009
|
|
||||||
|
|
||||||
_ | ty == typeTok -> return typeStr
|
|
||||||
_ | isPredefConstant ty -> return ty
|
|
||||||
|
|
||||||
_ -> composOp (comp g) ty
|
|
||||||
|
|
||||||
-- the underlying algorithms
|
|
||||||
|
|
||||||
inferLType :: SourceGrammar -> Context -> Term -> Check (Term, Type)
|
|
||||||
inferLType gr g trm = case trm of
|
|
||||||
|
|
||||||
Q (m,ident) | isPredef m -> termWith trm $ case typPredefined ident of
|
|
||||||
Just ty -> return ty
|
|
||||||
Nothing -> checkError ("unknown in Predef:" <+> ident)
|
|
||||||
|
|
||||||
Q ident -> checks [
|
|
||||||
termWith trm $ lookupResType gr ident >>= computeLType gr g
|
|
||||||
,
|
|
||||||
lookupResDef gr ident >>= inferLType gr g
|
|
||||||
,
|
|
||||||
checkError ("cannot infer type of constant" <+> ppTerm Unqualified 0 trm)
|
|
||||||
]
|
|
||||||
|
|
||||||
QC (m,ident) | isPredef m -> termWith trm $ case typPredefined ident of
|
|
||||||
Just ty -> return ty
|
|
||||||
Nothing -> checkError ("unknown in Predef:" <+> ident)
|
|
||||||
|
|
||||||
QC ident -> checks [
|
|
||||||
termWith trm $ lookupResType gr ident >>= computeLType gr g
|
|
||||||
,
|
|
||||||
lookupResDef gr ident >>= inferLType gr g
|
|
||||||
,
|
|
||||||
checkError ("cannot infer type of canonical constant" <+> ppTerm Unqualified 0 trm)
|
|
||||||
]
|
|
||||||
|
|
||||||
Vr ident -> termWith trm $ checkLookup ident g
|
|
||||||
|
|
||||||
Typed e t -> do
|
|
||||||
t' <- computeLType gr g t
|
|
||||||
checkLType gr g e t'
|
|
||||||
|
|
||||||
AdHocOverload ts -> do
|
|
||||||
over <- getOverload gr g Nothing trm
|
|
||||||
case over of
|
|
||||||
Just trty -> return trty
|
|
||||||
_ -> checkError ("unresolved overloading of constants" <+> ppTerm Qualified 0 trm)
|
|
||||||
|
|
||||||
App f a -> do
|
|
||||||
over <- getOverload gr g Nothing trm
|
|
||||||
case over of
|
|
||||||
Just trty -> return trty
|
|
||||||
_ -> do
|
|
||||||
(f',fty) <- inferLType gr g f
|
|
||||||
fty' <- computeLType gr g fty
|
|
||||||
case fty' of
|
|
||||||
Prod bt z arg val -> do
|
|
||||||
a' <- justCheck g a arg
|
|
||||||
ty <- if isWildIdent z
|
|
||||||
then return val
|
|
||||||
else substituteLType [(bt,z,a')] val
|
|
||||||
return (App f' a',ty)
|
|
||||||
_ ->
|
|
||||||
let term = ppTerm Unqualified 0 f
|
|
||||||
funName = pp . head . words .render $ term
|
|
||||||
in checkError ("A function type is expected for" <+> term <+> "instead of type" <+> ppType fty $$
|
|
||||||
"\n ** Maybe you gave too many arguments to" <+> funName <+> "\n")
|
|
||||||
|
|
||||||
S f x -> do
|
|
||||||
(f', fty) <- inferLType gr g f
|
|
||||||
case fty of
|
|
||||||
Table arg val -> do
|
|
||||||
x'<- justCheck g x arg
|
|
||||||
return (S f' x', val)
|
|
||||||
_ -> checkError ("table lintype expected for the table in" $$ nest 2 (ppTerm Unqualified 0 trm))
|
|
||||||
|
|
||||||
P t i -> do
|
|
||||||
(t',ty) <- inferLType gr g t --- ??
|
|
||||||
ty' <- computeLType gr g ty
|
|
||||||
let tr2 = P t' i
|
|
||||||
termWith tr2 $ case ty' of
|
|
||||||
RecType ts -> case lookup i ts of
|
|
||||||
Nothing -> checkError ("unknown label" <+> i <+> "in" $$ nest 2 (ppTerm Unqualified 0 ty'))
|
|
||||||
Just x -> return x
|
|
||||||
_ -> checkError ("record type expected for:" <+> ppTerm Unqualified 0 t $$
|
|
||||||
" instead of the inferred:" <+> ppTerm Unqualified 0 ty')
|
|
||||||
|
|
||||||
R r -> do
|
|
||||||
let (ls,fs) = unzip r
|
|
||||||
fsts <- mapM inferM fs
|
|
||||||
let ts = [ty | (Just ty,_) <- fsts]
|
|
||||||
checkCond ("cannot infer type of record" $$ nest 2 (ppTerm Unqualified 0 trm)) (length ts == length fsts)
|
|
||||||
return $ (R (zip ls fsts), RecType (zip ls ts))
|
|
||||||
|
|
||||||
T (TTyped arg) pts -> do
|
|
||||||
(_,val) <- checks $ map (inferCase (Just arg)) pts
|
|
||||||
checkLType gr g trm (Table arg val)
|
|
||||||
T (TComp arg) pts -> do
|
|
||||||
(_,val) <- checks $ map (inferCase (Just arg)) pts
|
|
||||||
checkLType gr g trm (Table arg val)
|
|
||||||
T ti pts -> do -- tries to guess: good in oper type inference
|
|
||||||
let pts' = [pt | pt@(p,_) <- pts, isConstPatt p]
|
|
||||||
case pts' of
|
|
||||||
[] -> checkError ("cannot infer table type of" <+> ppTerm Unqualified 0 trm)
|
|
||||||
---- PInt k : _ -> return $ Ints $ max [i | PInt i <- pts']
|
|
||||||
_ -> do
|
|
||||||
(arg,val) <- checks $ map (inferCase Nothing) pts'
|
|
||||||
checkLType gr g trm (Table arg val)
|
|
||||||
V arg pts -> do
|
|
||||||
(_,val) <- checks $ map (inferLType gr g) pts
|
|
||||||
-- return (trm, Table arg val) -- old, caused issue 68
|
|
||||||
checkLType gr g trm (Table arg val)
|
|
||||||
|
|
||||||
K s -> do
|
|
||||||
if elem ' ' s
|
|
||||||
then do
|
|
||||||
let ss = foldr C Empty (map K (words s))
|
|
||||||
----- removed irritating warning AR 24/5/2008
|
|
||||||
----- checkWarn ("token \"" ++ s ++
|
|
||||||
----- "\" converted to token list" ++ prt ss)
|
|
||||||
return (ss, typeStr)
|
|
||||||
else return (trm, typeStr)
|
|
||||||
|
|
||||||
EInt i -> return (trm, typeInt)
|
|
||||||
|
|
||||||
EFloat i -> return (trm, typeFloat)
|
|
||||||
|
|
||||||
Empty -> return (trm, typeStr)
|
|
||||||
|
|
||||||
C s1 s2 ->
|
|
||||||
check2 (flip (justCheck g) typeStr) C s1 s2 typeStr
|
|
||||||
|
|
||||||
Glue s1 s2 ->
|
|
||||||
check2 (flip (justCheck g) typeStr) Glue s1 s2 typeStr ---- typeTok
|
|
||||||
|
|
||||||
---- hack from Rename.identRenameTerm, to live with files with naming conflicts 18/6/2007
|
|
||||||
Strs (Cn c : ts) | c == cConflict -> do
|
|
||||||
checkWarn ("unresolved constant, could be any of" <+> hcat (map (ppTerm Unqualified 0) ts))
|
|
||||||
inferLType gr g (head ts)
|
|
||||||
|
|
||||||
Strs ts -> do
|
|
||||||
ts' <- mapM (\t -> justCheck g t typeStr) ts
|
|
||||||
return (Strs ts', typeStrs)
|
|
||||||
|
|
||||||
Alts t aa -> do
|
|
||||||
t' <- justCheck g t typeStr
|
|
||||||
aa' <- flip mapM aa (\ (c,v) -> do
|
|
||||||
c' <- justCheck g c typeStr
|
|
||||||
v' <- checks $ map (justCheck g v) [typeStrs, EPattType typeStr]
|
|
||||||
return (c',v'))
|
|
||||||
return (Alts t' aa', typeStr)
|
|
||||||
|
|
||||||
RecType r -> do
|
|
||||||
let (ls,ts) = unzip r
|
|
||||||
ts' <- mapM (flip (justCheck g) typeType) ts
|
|
||||||
return (RecType (zip ls ts'), typeType)
|
|
||||||
|
|
||||||
ExtR r s -> do
|
|
||||||
|
|
||||||
--- over <- getOverload gr g Nothing r
|
|
||||||
--- let r1 = maybe r fst over
|
|
||||||
let r1 = r ---
|
|
||||||
|
|
||||||
(r',rT) <- inferLType gr g r1
|
|
||||||
rT' <- computeLType gr g rT
|
|
||||||
|
|
||||||
(s',sT) <- inferLType gr g s
|
|
||||||
sT' <- computeLType gr g sT
|
|
||||||
|
|
||||||
let trm' = ExtR r' s'
|
|
||||||
case (rT', sT') of
|
|
||||||
(RecType rs, RecType ss) -> do
|
|
||||||
let rt = RecType ([field | field@(l,_) <- rs, notElem l (map fst ss)] ++ ss) -- select types of later fields
|
|
||||||
checkLType gr g trm' rt ---- return (trm', rt)
|
|
||||||
_ | rT' == typeType && sT' == typeType -> do
|
|
||||||
return (trm', typeType)
|
|
||||||
_ -> checkError ("records or record types expected in" <+> ppTerm Unqualified 0 trm)
|
|
||||||
|
|
||||||
Sort _ ->
|
|
||||||
termWith trm $ return typeType
|
|
||||||
|
|
||||||
Prod bt x a b -> do
|
|
||||||
a' <- justCheck g a typeType
|
|
||||||
b' <- justCheck ((bt,x,a'):g) b typeType
|
|
||||||
return (Prod bt x a' b', typeType)
|
|
||||||
|
|
||||||
Table p t -> do
|
|
||||||
p' <- justCheck g p typeType --- check p partype!
|
|
||||||
t' <- justCheck g t typeType
|
|
||||||
return $ (Table p' t', typeType)
|
|
||||||
|
|
||||||
FV vs -> do
|
|
||||||
(_,ty) <- checks $ map (inferLType gr g) vs
|
|
||||||
--- checkIfComplexVariantType trm ty
|
|
||||||
checkLType gr g trm ty
|
|
||||||
|
|
||||||
EPattType ty -> do
|
|
||||||
ty' <- justCheck g ty typeType
|
|
||||||
return (EPattType ty',typeType)
|
|
||||||
EPatt p -> do
|
|
||||||
ty <- inferPatt p
|
|
||||||
return (trm, EPattType ty)
|
|
||||||
|
|
||||||
ELin c trm -> do
|
|
||||||
(trm',ty) <- inferLType gr g trm
|
|
||||||
ty' <- lockRecType c ty ---- lookup c; remove lock AR 20/6/2009
|
|
||||||
return $ (ELin c trm', ty')
|
|
||||||
|
|
||||||
_ -> checkError ("cannot infer lintype of" <+> ppTerm Unqualified 0 trm)
|
|
||||||
|
|
||||||
where
|
|
||||||
isPredef m = elem m [cPredef,cPredefAbs]
|
|
||||||
|
|
||||||
justCheck g ty te = checkLType gr g ty te >>= return . fst
|
|
||||||
|
|
||||||
-- for record fields, which may be typed
|
|
||||||
inferM (mty, t) = do
|
|
||||||
(t', ty') <- case mty of
|
|
||||||
Just ty -> checkLType gr g t ty
|
|
||||||
_ -> inferLType gr g t
|
|
||||||
return (Just ty',t')
|
|
||||||
|
|
||||||
inferCase mty (patt,term) = do
|
|
||||||
arg <- maybe (inferPatt patt) return mty
|
|
||||||
cont <- pattContext gr g arg patt
|
|
||||||
(_,val) <- inferLType gr (reverse cont ++ g) term
|
|
||||||
return (arg,val)
|
|
||||||
isConstPatt p = case p of
|
|
||||||
PC _ ps -> True --- all isConstPatt ps
|
|
||||||
PP _ ps -> True --- all isConstPatt ps
|
|
||||||
PR ps -> all (isConstPatt . snd) ps
|
|
||||||
PT _ p -> isConstPatt p
|
|
||||||
PString _ -> True
|
|
||||||
PInt _ -> True
|
|
||||||
PFloat _ -> True
|
|
||||||
PChar -> True
|
|
||||||
PChars _ -> True
|
|
||||||
PSeq p q -> isConstPatt p && isConstPatt q
|
|
||||||
PAlt p q -> isConstPatt p && isConstPatt q
|
|
||||||
PRep p -> isConstPatt p
|
|
||||||
PNeg p -> isConstPatt p
|
|
||||||
PAs _ p -> isConstPatt p
|
|
||||||
_ -> False
|
|
||||||
|
|
||||||
inferPatt p = case p of
|
|
||||||
PP (q,c) ps | q /= cPredef -> liftM valTypeCnc (lookupResType gr (q,c))
|
|
||||||
PAs _ p -> inferPatt p
|
|
||||||
PNeg p -> inferPatt p
|
|
||||||
PAlt p q -> checks [inferPatt p, inferPatt q]
|
|
||||||
PSeq _ _ -> return $ typeStr
|
|
||||||
PRep _ -> return $ typeStr
|
|
||||||
PChar -> return $ typeStr
|
|
||||||
PChars _ -> return $ typeStr
|
|
||||||
_ -> inferLType gr g (patt2term p) >>= return . snd
|
|
||||||
|
|
||||||
-- type inference: Nothing, type checking: Just t
|
|
||||||
-- the latter permits matching with value type
|
|
||||||
getOverload :: SourceGrammar -> Context -> Maybe Type -> Term -> Check (Maybe (Term,Type))
|
|
||||||
getOverload gr g mt ot = case appForm ot of
|
|
||||||
(f@(Q c), ts) -> case lookupOverload gr c of
|
|
||||||
Ok typs -> do
|
|
||||||
ttys <- mapM (inferLType gr g) ts
|
|
||||||
v <- matchOverload f typs ttys
|
|
||||||
return $ Just v
|
|
||||||
_ -> return Nothing
|
|
||||||
(AdHocOverload cs@(f:_), ts) -> do --- the function name f is only used in error messages
|
|
||||||
let typs = concatMap collectOverloads cs
|
|
||||||
ttys <- mapM (inferLType gr g) ts
|
|
||||||
v <- matchOverload f typs ttys
|
|
||||||
return $ Just v
|
|
||||||
_ -> return Nothing
|
|
||||||
|
|
||||||
where
|
|
||||||
collectOverloads tr@(Q c) = case lookupOverload gr c of
|
|
||||||
Ok typs -> typs
|
|
||||||
_ -> case lookupResType gr c of
|
|
||||||
Ok ty -> let (args,val) = typeFormCnc ty in [(map (\(b,x,t) -> t) args,(val,tr))]
|
|
||||||
_ -> []
|
|
||||||
collectOverloads _ = [] --- constructors QC
|
|
||||||
|
|
||||||
matchOverload f typs ttys = do
|
|
||||||
let (tts,tys) = unzip ttys
|
|
||||||
let vfs = lookupOverloadInstance tys typs
|
|
||||||
let matches = [vf | vf@((_,v,_),_) <- vfs, matchVal mt v]
|
|
||||||
let showTypes ty = hsep (map ppType ty)
|
|
||||||
|
|
||||||
|
|
||||||
let (stys,styps) = (showTypes tys, [showTypes ty | (ty,_) <- typs])
|
|
||||||
|
|
||||||
-- to avoid strange error msg e.g. in case of unmatch record extension, show whole types if needed AR 28/1/2013
|
|
||||||
let (stysError,stypsError) = if elem (render stys) (map render styps)
|
|
||||||
then (hsep (map (ppTerm Unqualified 0) tys), [hsep (map (ppTerm Unqualified 0) ty) | (ty,_) <- typs])
|
|
||||||
else (stys,styps)
|
|
||||||
|
|
||||||
case ([vf | (vf,True) <- matches],[vf | (vf,False) <- matches]) of
|
|
||||||
([(_,val,fun)],_) -> return (mkApp fun tts, val)
|
|
||||||
([],[(pre,val,fun)]) -> do
|
|
||||||
checkWarn $ "ignoring lock fields in resolving" <+> ppTerm Unqualified 0 ot $$
|
|
||||||
"for" $$
|
|
||||||
nest 2 (showTypes tys) $$
|
|
||||||
"using" $$
|
|
||||||
nest 2 (showTypes pre)
|
|
||||||
return (mkApp fun tts, val)
|
|
||||||
([],[]) -> do
|
|
||||||
checkError $ "no overload instance of" <+> ppTerm Qualified 0 f $$
|
|
||||||
maybe empty (\x -> "with value type" <+> ppType x) mt $$
|
|
||||||
"for argument list" $$
|
|
||||||
nest 2 stysError $$
|
|
||||||
"among alternatives" $$
|
|
||||||
nest 2 (vcat stypsError)
|
|
||||||
|
|
||||||
|
|
||||||
(vfs1,vfs2) -> case (noProds vfs1,noProds vfs2) of
|
|
||||||
([(val,fun)],_) -> do
|
|
||||||
return (mkApp fun tts, val)
|
|
||||||
([],[(val,fun)]) -> do
|
|
||||||
checkWarn ("ignoring lock fields in resolving" <+> ppTerm Unqualified 0 ot)
|
|
||||||
return (mkApp fun tts, val)
|
|
||||||
|
|
||||||
----- unsafely exclude irritating warning AR 24/5/2008
|
|
||||||
----- checkWarn $ "overloading of" +++ prt f +++
|
|
||||||
----- "resolved by excluding partial applications:" ++++
|
|
||||||
----- unlines [prtType env ty | (ty,_) <- vfs', not (noProd ty)]
|
|
||||||
|
|
||||||
--- now forgiving ambiguity with a warning AR 1/2/2014
|
|
||||||
-- This gives ad hoc overloading the same behaviour as the choice of the first match in renaming did before.
|
|
||||||
-- But it also gives a chance to ambiguous overloadings that were banned before.
|
|
||||||
(nps1,nps2) -> do
|
|
||||||
checkWarn $ "ambiguous overloading of" <+> ppTerm Unqualified 0 f <+>
|
|
||||||
---- "with argument types" <+> hsep (map (ppTerm Qualified 0) tys) $$
|
|
||||||
"resolved by selecting the first of the alternatives" $$
|
|
||||||
nest 2 (vcat [ppTerm Qualified 0 fun | (_,ty,fun) <- vfs1 ++ if null vfs1 then vfs2 else []])
|
|
||||||
case [(mkApp fun tts,val) | (val,fun) <- nps1 ++ nps2] of
|
|
||||||
[] -> checkError $ "no alternatives left when resolving" <+> ppTerm Unqualified 0 f
|
|
||||||
h:_ -> return h
|
|
||||||
|
|
||||||
matchVal mt v = elem mt [Nothing,Just v,Just (unlocked v)]
|
|
||||||
|
|
||||||
unlocked v = case v of
|
|
||||||
RecType fs -> RecType $ filter (not . isLockLabel . fst) (sortRec fs)
|
|
||||||
_ -> v
|
|
||||||
---- TODO: accept subtypes
|
|
||||||
---- TODO: use a trie
|
|
||||||
lookupOverloadInstance tys typs =
|
|
||||||
[((pre,mkFunType rest val, t),isExact) |
|
|
||||||
let lt = length tys,
|
|
||||||
(ty,(val,t)) <- typs, length ty >= lt,
|
|
||||||
let (pre,rest) = splitAt lt ty,
|
|
||||||
let isExact = pre == tys,
|
|
||||||
isExact || map unlocked pre == map unlocked tys
|
|
||||||
]
|
|
||||||
|
|
||||||
noProds vfs = [(v,f) | (_,v,f) <- vfs, noProd v]
|
|
||||||
|
|
||||||
noProd ty = case ty of
|
|
||||||
Prod _ _ _ _ -> False
|
|
||||||
_ -> True
|
|
||||||
|
|
||||||
checkLType :: SourceGrammar -> Context -> Term -> Type -> Check (Term, Type)
|
|
||||||
checkLType gr g trm typ0 = do
|
|
||||||
typ <- computeLType gr g typ0
|
|
||||||
|
|
||||||
case trm of
|
|
||||||
|
|
||||||
Abs bt x c -> do
|
|
||||||
case typ of
|
|
||||||
Prod bt' z a b -> do
|
|
||||||
(c',b') <- if isWildIdent z
|
|
||||||
then checkLType gr ((bt,x,a):g) c b
|
|
||||||
else do b' <- checkIn (pp "abs") $ substituteLType [(bt',z,Vr x)] b
|
|
||||||
checkLType gr ((bt,x,a):g) c b'
|
|
||||||
return $ (Abs bt x c', Prod bt' z a b')
|
|
||||||
_ -> checkError $ "function type expected instead of" <+> ppType typ $$
|
|
||||||
"\n ** Double-check that the type signature of the operation" $$
|
|
||||||
"matches the number of arguments given to it.\n"
|
|
||||||
|
|
||||||
App f a -> do
|
|
||||||
over <- getOverload gr g (Just typ) trm
|
|
||||||
case over of
|
|
||||||
Just trty -> return trty
|
|
||||||
_ -> do
|
|
||||||
(trm',ty') <- inferLType gr g trm
|
|
||||||
termWith trm' $ checkEqLType gr g typ ty' trm'
|
|
||||||
|
|
||||||
AdHocOverload ts -> do
|
|
||||||
over <- getOverload gr g Nothing trm
|
|
||||||
case over of
|
|
||||||
Just trty -> return trty
|
|
||||||
_ -> checkError ("unresolved overloading of constants" <+> ppTerm Qualified 0 trm)
|
|
||||||
|
|
||||||
Q _ -> do
|
|
||||||
over <- getOverload gr g (Just typ) trm
|
|
||||||
case over of
|
|
||||||
Just trty -> return trty
|
|
||||||
_ -> do
|
|
||||||
(trm',ty') <- inferLType gr g trm
|
|
||||||
termWith trm' $ checkEqLType gr g typ ty' trm'
|
|
||||||
|
|
||||||
T _ [] ->
|
|
||||||
checkError ("found empty table in type" <+> ppTerm Unqualified 0 typ)
|
|
||||||
T _ cs -> case typ of
|
|
||||||
Table arg val -> do
|
|
||||||
case allParamValues gr arg of
|
|
||||||
Ok vs -> do
|
|
||||||
let ps0 = map fst cs
|
|
||||||
ps <- testOvershadow ps0 vs
|
|
||||||
if null ps
|
|
||||||
then return ()
|
|
||||||
else checkWarn ("patterns never reached:" $$
|
|
||||||
nest 2 (vcat (map (ppPatt Unqualified 0) ps)))
|
|
||||||
_ -> return () -- happens with variable types
|
|
||||||
cs' <- mapM (checkCase arg val) cs
|
|
||||||
return (T (TTyped arg) cs', typ)
|
|
||||||
_ -> checkError $ "table type expected for table instead of" $$ nest 2 (ppType typ)
|
|
||||||
V arg0 vs ->
|
|
||||||
case typ of
|
|
||||||
Table arg1 val ->
|
|
||||||
do arg' <- checkEqLType gr g arg0 arg1 trm
|
|
||||||
vs1 <- allParamValues gr arg1
|
|
||||||
if length vs1 == length vs
|
|
||||||
then return ()
|
|
||||||
else checkError $ "wrong number of values in table" <+> ppTerm Unqualified 0 trm
|
|
||||||
vs' <- map fst `fmap` sequence [checkLType gr g v val|v<-vs]
|
|
||||||
return (V arg' vs',typ)
|
|
||||||
|
|
||||||
R r -> case typ of --- why needed? because inference may be too difficult
|
|
||||||
RecType rr -> do
|
|
||||||
--let (ls,_) = unzip rr -- labels of expected type
|
|
||||||
fsts <- mapM (checkM r) rr -- check that they are found in the record
|
|
||||||
return $ (R fsts, typ) -- normalize record
|
|
||||||
|
|
||||||
_ -> checkError ("record type expected in type checking instead of" $$ nest 2 (ppTerm Unqualified 0 typ))
|
|
||||||
|
|
||||||
ExtR r s -> case typ of
|
|
||||||
_ | typ == typeType -> do
|
|
||||||
trm' <- computeLType gr g trm
|
|
||||||
case trm' of
|
|
||||||
RecType _ -> termWith trm' $ return typeType
|
|
||||||
ExtR (Vr _) (RecType _) -> termWith trm' $ return typeType
|
|
||||||
-- ext t = t ** ...
|
|
||||||
_ -> checkError ("invalid record type extension" <+> nest 2 (ppTerm Unqualified 0 trm))
|
|
||||||
|
|
||||||
RecType rr -> do
|
|
||||||
|
|
||||||
ll2 <- case s of
|
|
||||||
R ss -> return $ map fst ss
|
|
||||||
_ -> do
|
|
||||||
(s',typ2) <- inferLType gr g s
|
|
||||||
case typ2 of
|
|
||||||
RecType ss -> return $ map fst ss
|
|
||||||
_ -> checkError ("cannot get labels from" $$ nest 2 (ppTerm Unqualified 0 typ2))
|
|
||||||
let ll1 = [l | (l,_) <- rr, notElem l ll2]
|
|
||||||
|
|
||||||
--- over <- getOverload gr g Nothing r --- this would solve #66 but fail ParadigmsAra. AR 6/7/2020
|
|
||||||
--- let r1 = maybe r fst over
|
|
||||||
let r1 = r ---
|
|
||||||
|
|
||||||
(r',_) <- checkLType gr g r1 (RecType [field | field@(l,_) <- rr, elem l ll1])
|
|
||||||
(s',_) <- checkLType gr g s (RecType [field | field@(l,_) <- rr, elem l ll2])
|
|
||||||
|
|
||||||
let rec = R ([(l,(Nothing,P r' l)) | l <- ll1] ++ [(l,(Nothing,P s' l)) | l <- ll2])
|
|
||||||
return (rec, typ)
|
|
||||||
|
|
||||||
ExtR ty ex -> do
|
|
||||||
r' <- justCheck g r ty
|
|
||||||
s' <- justCheck g s ex
|
|
||||||
return $ (ExtR r' s', typ) --- is this all? it assumes the same division in trm and typ
|
|
||||||
|
|
||||||
_ -> checkError ("record extension not meaningful for" <+> ppTerm Unqualified 0 typ)
|
|
||||||
|
|
||||||
FV vs -> do
|
|
||||||
ttys <- mapM (flip (checkLType gr g) typ) vs
|
|
||||||
--- checkIfComplexVariantType trm typ
|
|
||||||
return (FV (map fst ttys), typ) --- typ' ?
|
|
||||||
|
|
||||||
S tab arg -> checks [ do
|
|
||||||
(tab',ty) <- inferLType gr g tab
|
|
||||||
ty' <- computeLType gr g ty
|
|
||||||
case ty' of
|
|
||||||
Table p t -> do
|
|
||||||
(arg',val) <- checkLType gr g arg p
|
|
||||||
checkEqLType gr g typ t trm
|
|
||||||
return (S tab' arg', t)
|
|
||||||
_ -> checkError ("table type expected for applied table instead of" <+> ppType ty')
|
|
||||||
, do
|
|
||||||
(arg',ty) <- inferLType gr g arg
|
|
||||||
ty' <- computeLType gr g ty
|
|
||||||
(tab',_) <- checkLType gr g tab (Table ty' typ)
|
|
||||||
return (S tab' arg', typ)
|
|
||||||
]
|
|
||||||
Let (x,(mty,def)) body -> case mty of
|
|
||||||
Just ty -> do
|
|
||||||
(ty0,_) <- checkLType gr g ty typeType
|
|
||||||
(def',ty') <- checkLType gr g def ty0
|
|
||||||
body' <- justCheck ((Explicit,x,ty'):g) body typ
|
|
||||||
return (Let (x,(Just ty',def')) body', typ)
|
|
||||||
_ -> do
|
|
||||||
(def',ty) <- inferLType gr g def -- tries to infer type of local constant
|
|
||||||
checkLType gr g (Let (x,(Just ty,def')) body) typ
|
|
||||||
|
|
||||||
ELin c tr -> do
|
|
||||||
tr1 <- unlockRecord c tr
|
|
||||||
checkLType gr g tr1 typ
|
|
||||||
|
|
||||||
_ -> do
|
|
||||||
(trm',ty') <- inferLType gr g trm
|
|
||||||
termWith trm' $ checkEqLType gr g typ ty' trm'
|
|
||||||
where
|
|
||||||
justCheck g ty te = checkLType gr g ty te >>= return . fst
|
|
||||||
{-
|
|
||||||
recParts rr t = (RecType rr1,RecType rr2) where
|
|
||||||
(rr1,rr2) = partition (flip elem (map fst t) . fst) rr
|
|
||||||
-}
|
|
||||||
checkM rms (l,ty) = case lookup l rms of
|
|
||||||
Just (Just ty0,t) -> do
|
|
||||||
checkEqLType gr g ty ty0 t
|
|
||||||
(t',ty') <- checkLType gr g t ty
|
|
||||||
return (l,(Just ty',t'))
|
|
||||||
Just (_,t) -> do
|
|
||||||
(t',ty') <- checkLType gr g t ty
|
|
||||||
return (l,(Just ty',t'))
|
|
||||||
_ -> checkError $
|
|
||||||
if isLockLabel l
|
|
||||||
then let cat = drop 5 (showIdent (label2ident l))
|
|
||||||
in ppTerm Unqualified 0 (R rms) <+> "is not in the lincat of" <+> cat <>
|
|
||||||
"; try wrapping it with lin" <+> cat
|
|
||||||
else "cannot find value for label" <+> l <+> "in" <+> ppTerm Unqualified 0 (R rms)
|
|
||||||
|
|
||||||
checkCase arg val (p,t) = do
|
|
||||||
cont <- pattContext gr g arg p
|
|
||||||
t' <- justCheck (reverse cont ++ g) t val
|
|
||||||
return (p,t')
|
|
||||||
|
|
||||||
pattContext :: SourceGrammar -> Context -> Type -> Patt -> Check Context
|
|
||||||
pattContext env g typ p = case p of
|
|
||||||
PV x -> return [(Explicit,x,typ)]
|
|
||||||
PP (q,c) ps | q /= cPredef -> do ---- why this /=? AR 6/1/2006
|
|
||||||
t <- lookupResType env (q,c)
|
|
||||||
let (cont,v) = typeFormCnc t
|
|
||||||
checkCond ("wrong number of arguments for constructor in" <+> ppPatt Unqualified 0 p)
|
|
||||||
(length cont == length ps)
|
|
||||||
checkEqLType env g typ v (patt2term p)
|
|
||||||
mapM (\((_,_,ty),p) -> pattContext env g ty p) (zip cont ps) >>= return . concat
|
|
||||||
PR r -> do
|
|
||||||
typ' <- computeLType env g typ
|
|
||||||
case typ' of
|
|
||||||
RecType t -> do
|
|
||||||
let pts = [(ty,tr) | (l,tr) <- r, Just ty <- [lookup l t]]
|
|
||||||
----- checkWarn $ prt p ++++ show pts ----- debug
|
|
||||||
mapM (uncurry (pattContext env g)) pts >>= return . concat
|
|
||||||
_ -> checkError ("record type expected for pattern instead of" <+> ppTerm Unqualified 0 typ')
|
|
||||||
PT t p' -> do
|
|
||||||
checkEqLType env g typ t (patt2term p')
|
|
||||||
pattContext env g typ p'
|
|
||||||
|
|
||||||
PAs x p -> do
|
|
||||||
g' <- pattContext env g typ p
|
|
||||||
return ((Explicit,x,typ):g')
|
|
||||||
|
|
||||||
PAlt p' q -> do
|
|
||||||
g1 <- pattContext env g typ p'
|
|
||||||
g2 <- pattContext env g typ q
|
|
||||||
let pts = nub ([x | pt@(_,x,_) <- g1, notElem pt g2] ++ [x | pt@(_,x,_) <- g2, notElem pt g1])
|
|
||||||
checkCond
|
|
||||||
("incompatible bindings of" <+>
|
|
||||||
fsep pts <+>
|
|
||||||
"in pattern alterantives" <+> ppPatt Unqualified 0 p) (null pts)
|
|
||||||
return g1 -- must be g1 == g2
|
|
||||||
PSeq p q -> do
|
|
||||||
g1 <- pattContext env g typ p
|
|
||||||
g2 <- pattContext env g typ q
|
|
||||||
return $ g1 ++ g2
|
|
||||||
PRep p' -> noBind typeStr p'
|
|
||||||
PNeg p' -> noBind typ p'
|
|
||||||
|
|
||||||
_ -> return [] ---- check types!
|
|
||||||
where
|
|
||||||
noBind typ p' = do
|
|
||||||
co <- pattContext env g typ p'
|
|
||||||
if not (null co)
|
|
||||||
then checkWarn ("no variable bound inside pattern" <+> ppPatt Unqualified 0 p)
|
|
||||||
>> return []
|
|
||||||
else return []
|
|
||||||
|
|
||||||
checkEqLType :: SourceGrammar -> Context -> Type -> Type -> Term -> Check Type
|
|
||||||
checkEqLType gr g t u trm = do
|
|
||||||
(b,t',u',s) <- checkIfEqLType gr g t u trm
|
|
||||||
case b of
|
|
||||||
True -> return t'
|
|
||||||
False ->
|
|
||||||
let inferredType = ppTerm Qualified 0 u
|
|
||||||
expectedType = ppTerm Qualified 0 t
|
|
||||||
term = ppTerm Unqualified 0 trm
|
|
||||||
funName = pp . head . words .render $ term
|
|
||||||
helpfulMsg =
|
|
||||||
case (arrows inferredType, arrows expectedType) of
|
|
||||||
(0,0) -> pp "" -- None of the types is a function
|
|
||||||
_ -> "\n **" <+>
|
|
||||||
if expectedType `isLessApplied` inferredType
|
|
||||||
then "Maybe you gave too few arguments to" <+> funName
|
|
||||||
else pp "Double-check that type signature and number of arguments match."
|
|
||||||
in checkError $ s <+> "type of" <+> term $$
|
|
||||||
"expected:" <+> expectedType $$ -- ppqType t u $$
|
|
||||||
"inferred:" <+> inferredType $$ -- ppqType u t
|
|
||||||
helpfulMsg
|
|
||||||
where
|
|
||||||
-- count the number of arrows in the prettyprinted term
|
|
||||||
arrows :: Doc -> Int
|
|
||||||
arrows = length . filter (=="->") . words . render
|
|
||||||
|
|
||||||
-- If prettyprinted type t has fewer arrows then prettyprinted type u,
|
|
||||||
-- then t is "less applied", and we can print out more helpful error msg.
|
|
||||||
isLessApplied :: Doc -> Doc -> Bool
|
|
||||||
isLessApplied t u = arrows t < arrows u
|
|
||||||
|
|
||||||
checkIfEqLType :: SourceGrammar -> Context -> Type -> Type -> Term -> Check (Bool,Type,Type,String)
|
|
||||||
checkIfEqLType gr g t u trm = do
|
|
||||||
t' <- computeLType gr g t
|
|
||||||
u' <- computeLType gr g u
|
|
||||||
case t' == u' || alpha [] t' u' of
|
|
||||||
True -> return (True,t',u',[])
|
|
||||||
-- forgive missing lock fields by only generating a warning.
|
|
||||||
--- better: use a flag to forgive? (AR 31/1/2006)
|
|
||||||
_ -> case missingLock [] t' u' of
|
|
||||||
Ok lo -> do
|
|
||||||
checkWarn $ "missing lock field" <+> fsep lo
|
|
||||||
return (True,t',u',[])
|
|
||||||
Bad s -> return (False,t',u',s)
|
|
||||||
|
|
||||||
where
|
|
||||||
|
|
||||||
-- check that u is a subtype of t
|
|
||||||
--- quick hack version of TC.eqVal
|
|
||||||
alpha g t u = case (t,u) of
|
|
||||||
|
|
||||||
-- error (the empty type!) is subtype of any other type
|
|
||||||
(_,u) | u == typeError -> True
|
|
||||||
|
|
||||||
-- contravariance
|
|
||||||
(Prod _ x a b, Prod _ y c d) -> alpha g c a && alpha ((x,y):g) b d
|
|
||||||
|
|
||||||
-- record subtyping
|
|
||||||
(RecType rs, RecType ts) -> all (\ (l,a) ->
|
|
||||||
any (\ (k,b) -> l == k && alpha g a b) ts) rs
|
|
||||||
(ExtR r s, ExtR r' s') -> alpha g r r' && alpha g s s'
|
|
||||||
(ExtR r s, t) -> alpha g r t || alpha g s t
|
|
||||||
|
|
||||||
-- the following say that Ints n is a subset of Int and of Ints m >= n
|
|
||||||
-- But why does it also allow Int as a subtype of Ints m? /TH 2014-04-04
|
|
||||||
(t,u) | Just m <- isTypeInts t, Just n <- isTypeInts u -> m >= n
|
|
||||||
| Just _ <- isTypeInts t, u == typeInt -> True ---- check size!
|
|
||||||
| t == typeInt, Just _ <- isTypeInts u -> True ---- why this ???? AR 11/12/2005
|
|
||||||
|
|
||||||
---- this should be made in Rename
|
|
||||||
(Q (m,a), Q (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
|
||||||
|| elem n (allExtendsPlus gr m)
|
|
||||||
|| m == n --- for Predef
|
|
||||||
(QC (m,a), QC (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
|
||||||
|| elem n (allExtendsPlus gr m)
|
|
||||||
(QC (m,a), Q (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
|
||||||
|| elem n (allExtendsPlus gr m)
|
|
||||||
(Q (m,a), QC (n,b)) | a == b -> elem m (allExtendsPlus gr n)
|
|
||||||
|| elem n (allExtendsPlus gr m)
|
|
||||||
|
|
||||||
-- contravariance
|
|
||||||
(Table a b, Table c d) -> alpha g c a && alpha g b d
|
|
||||||
(Vr x, Vr y) -> x == y || elem (x,y) g || elem (y,x) g
|
|
||||||
_ -> t == u
|
|
||||||
--- the following should be one-way coercions only. AR 4/1/2001
|
|
||||||
|| elem t sTypes && elem u sTypes
|
|
||||||
|| (t == typeType && u == typePType)
|
|
||||||
|| (u == typeType && t == typePType)
|
|
||||||
|
|
||||||
missingLock g t u = case (t,u) of
|
|
||||||
(RecType rs, RecType ts) ->
|
|
||||||
let
|
|
||||||
ls = [l | (l,a) <- rs,
|
|
||||||
not (any (\ (k,b) -> alpha g a b && l == k) ts)]
|
|
||||||
(locks,others) = partition isLockLabel ls
|
|
||||||
in case others of
|
|
||||||
_:_ -> Bad $ render ("missing record fields:" <+> fsep (punctuate ',' (others)))
|
|
||||||
_ -> return locks
|
|
||||||
-- contravariance
|
|
||||||
(Prod _ x a b, Prod _ y c d) -> do
|
|
||||||
ls1 <- missingLock g c a
|
|
||||||
ls2 <- missingLock g b d
|
|
||||||
return $ ls1 ++ ls2
|
|
||||||
|
|
||||||
_ -> Bad ""
|
|
||||||
|
|
||||||
sTypes = [typeStr, typeTok, typeString]
|
|
||||||
|
|
||||||
-- auxiliaries
|
|
||||||
|
|
||||||
-- | light-weight substitution for dep. types
|
|
||||||
substituteLType :: Context -> Type -> Check Type
|
|
||||||
substituteLType g t = case t of
|
|
||||||
Vr x -> return $ maybe t id $ lookup x [(x,t) | (_,x,t) <- g]
|
|
||||||
_ -> composOp (substituteLType g) t
|
|
||||||
|
|
||||||
termWith :: Term -> Check Type -> Check (Term, Type)
|
|
||||||
termWith t ct = do
|
|
||||||
ty <- ct
|
|
||||||
return (t,ty)
|
|
||||||
|
|
||||||
-- | compositional check\/infer of binary operations
|
|
||||||
check2 :: (Term -> Check Term) -> (Term -> Term -> Term) ->
|
|
||||||
Term -> Term -> Type -> Check (Term,Type)
|
|
||||||
check2 chk con a b t = do
|
|
||||||
a' <- chk a
|
|
||||||
b' <- chk b
|
|
||||||
return (con a' b', t)
|
|
||||||
|
|
||||||
-- printing a type with a lock field lock_C as C
|
|
||||||
ppType :: Type -> Doc
|
|
||||||
ppType ty =
|
|
||||||
case ty of
|
|
||||||
RecType fs -> case filter isLockLabel $ map fst fs of
|
|
||||||
[lock] -> pp (drop 5 (showIdent (label2ident lock)))
|
|
||||||
_ -> ppTerm Unqualified 0 ty
|
|
||||||
Prod _ x a b -> ppType a <+> "->" <+> ppType b
|
|
||||||
_ -> ppTerm Unqualified 0 ty
|
|
||||||
{-
|
|
||||||
ppqType :: Type -> Type -> Doc
|
|
||||||
ppqType t u = case (ppType t, ppType u) of
|
|
||||||
(pt,pu) | render pt == render pu -> ppTerm Qualified 0 t
|
|
||||||
(pt,_) -> pt
|
|
||||||
-}
|
|
||||||
checkLookup :: Ident -> Context -> Check Type
|
|
||||||
checkLookup x g =
|
|
||||||
case [ty | (b,y,ty) <- g, x == y] of
|
|
||||||
[] -> checkError ("unknown variable" <+> x)
|
|
||||||
(ty:_) -> return ty
|
|
||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 "="
|
||||||
|
|
||||||
|
|||||||
@@ -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 }
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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 []
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 ()
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ module GF.Infra.Option
|
|||||||
(
|
(
|
||||||
-- ** Command line options
|
-- ** Command line options
|
||||||
-- *** Option types
|
-- *** Option types
|
||||||
Options,
|
Options,
|
||||||
Flags(..),
|
Flags(..),
|
||||||
Mode(..), Phase(..), Verbosity(..),
|
Mode(..), Phase(..), Verbosity(..),
|
||||||
OutputFormat(..),
|
OutputFormat(..),
|
||||||
SISRFormat(..), Optimization(..), CFGTransform(..), HaskellOption(..),
|
SISRFormat(..), Optimization(..), CFGTransform(..), HaskellOption(..),
|
||||||
Dump(..), Pass(..), Recomp(..),
|
Dump(..), Pass(..), Recomp(..),
|
||||||
outputFormatsExpl,
|
outputFormatsExpl,
|
||||||
-- *** Option parsing
|
-- *** Option parsing
|
||||||
parseOptions, parseModuleOptions, fixRelativeLibPaths,
|
parseOptions, parseModuleOptions, fixRelativeLibPaths,
|
||||||
-- *** Option pretty-printing
|
-- *** Option pretty-printing
|
||||||
@@ -47,7 +47,7 @@ import PGF.Internal(Literal(..))
|
|||||||
import qualified Control.Monad.Fail as Fail
|
import qualified Control.Monad.Fail as Fail
|
||||||
|
|
||||||
usageHeader :: String
|
usageHeader :: String
|
||||||
usageHeader = unlines
|
usageHeader = unlines
|
||||||
["Usage: gf [OPTIONS] [FILE [...]]",
|
["Usage: gf [OPTIONS] [FILE [...]]",
|
||||||
"",
|
"",
|
||||||
"How each FILE is handled depends on the file name suffix:",
|
"How each FILE is handled depends on the file name suffix:",
|
||||||
@@ -90,10 +90,10 @@ data Phase = Preproc | Convert | Compile | Link
|
|||||||
data OutputFormat = FmtPGFPretty
|
data OutputFormat = FmtPGFPretty
|
||||||
| FmtCanonicalGF
|
| FmtCanonicalGF
|
||||||
| FmtCanonicalJson
|
| FmtCanonicalJson
|
||||||
| FmtJavaScript
|
| FmtJavaScript
|
||||||
| FmtJSON
|
| FmtJSON
|
||||||
| FmtPython
|
| FmtPython
|
||||||
| FmtHaskell
|
| FmtHaskell
|
||||||
| FmtJava
|
| FmtJava
|
||||||
| FmtProlog
|
| FmtProlog
|
||||||
| FmtBNF
|
| FmtBNF
|
||||||
@@ -102,37 +102,42 @@ data OutputFormat = FmtPGFPretty
|
|||||||
| FmtNoLR
|
| FmtNoLR
|
||||||
| FmtSRGS_XML
|
| FmtSRGS_XML
|
||||||
| FmtSRGS_XML_NonRec
|
| FmtSRGS_XML_NonRec
|
||||||
| FmtSRGS_ABNF
|
| FmtSRGS_ABNF
|
||||||
| FmtSRGS_ABNF_NonRec
|
| FmtSRGS_ABNF_NonRec
|
||||||
| FmtJSGF
|
| FmtJSGF
|
||||||
| FmtGSL
|
| FmtGSL
|
||||||
| FmtVoiceXML
|
| FmtVoiceXML
|
||||||
| FmtSLF
|
| FmtSLF
|
||||||
| FmtRegExp
|
| FmtRegExp
|
||||||
| FmtFA
|
| FmtFA
|
||||||
deriving (Eq,Ord)
|
deriving (Eq,Ord)
|
||||||
|
|
||||||
data SISRFormat =
|
data SISRFormat =
|
||||||
-- | SISR Working draft 1 April 2003
|
-- | SISR Working draft 1 April 2003
|
||||||
-- <http://www.w3.org/TR/2003/WD-semantic-interpretation-20030401/>
|
-- <http://www.w3.org/TR/2003/WD-semantic-interpretation-20030401/>
|
||||||
SISR_WD20030401
|
SISR_WD20030401
|
||||||
| SISR_1_0
|
| SISR_1_0
|
||||||
deriving (Show,Eq,Ord)
|
deriving (Show,Eq,Ord)
|
||||||
|
|
||||||
data Optimization = OptStem | OptCSE | OptExpand | OptParametrize
|
data Optimization = OptStem | OptCSE | OptExpand | OptParametrize
|
||||||
deriving (Show,Eq,Ord)
|
deriving (Show,Eq,Ord)
|
||||||
|
|
||||||
data CFGTransform = CFGNoLR
|
data CFGTransform = CFGNoLR
|
||||||
| CFGRegular
|
| CFGRegular
|
||||||
| CFGTopDownFilter
|
| CFGTopDownFilter
|
||||||
| CFGBottomUpFilter
|
| CFGBottomUpFilter
|
||||||
| CFGStartCatOnly
|
| CFGStartCatOnly
|
||||||
| CFGMergeIdentical
|
| CFGMergeIdentical
|
||||||
| CFGRemoveCycles
|
| CFGRemoveCycles
|
||||||
deriving (Show,Eq,Ord)
|
deriving (Show,Eq,Ord)
|
||||||
|
|
||||||
data HaskellOption = HaskellNoPrefix | HaskellGADT | HaskellLexical
|
data HaskellOption = HaskellNoPrefix
|
||||||
| HaskellConcrete | HaskellVariants | HaskellData
|
| HaskellGADT
|
||||||
|
| HaskellLexical
|
||||||
|
| HaskellConcrete
|
||||||
|
| HaskellVariants
|
||||||
|
| HaskellData
|
||||||
|
| HaskellPGF2
|
||||||
deriving (Show,Eq,Ord)
|
deriving (Show,Eq,Ord)
|
||||||
|
|
||||||
data Warning = WarnMissingLincat
|
data Warning = WarnMissingLincat
|
||||||
@@ -196,7 +201,7 @@ instance Show Options where
|
|||||||
parseOptions :: ErrorMonad err =>
|
parseOptions :: ErrorMonad err =>
|
||||||
[String] -- ^ list of string arguments
|
[String] -- ^ list of string arguments
|
||||||
-> err (Options, [FilePath])
|
-> err (Options, [FilePath])
|
||||||
parseOptions args
|
parseOptions args
|
||||||
| not (null errs) = errors errs
|
| not (null errs) = errors errs
|
||||||
| otherwise = do opts <- concatOptions `fmap` liftErr (sequence optss)
|
| otherwise = do opts <- concatOptions `fmap` liftErr (sequence optss)
|
||||||
return (opts, files)
|
return (opts, files)
|
||||||
@@ -208,7 +213,7 @@ parseModuleOptions :: ErrorMonad err =>
|
|||||||
-> err Options
|
-> err Options
|
||||||
parseModuleOptions args = do
|
parseModuleOptions args = do
|
||||||
(opts,nonopts) <- parseOptions args
|
(opts,nonopts) <- parseOptions args
|
||||||
if null nonopts
|
if null nonopts
|
||||||
then return opts
|
then return opts
|
||||||
else errors $ map ("Non-option among module options: " ++) nonopts
|
else errors $ map ("Non-option among module options: " ++) nonopts
|
||||||
|
|
||||||
@@ -281,7 +286,7 @@ defaultFlags = Flags {
|
|||||||
optOptimizations = Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize],
|
optOptimizations = Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize],
|
||||||
optOptimizePGF = False,
|
optOptimizePGF = False,
|
||||||
optSplitPGF = False,
|
optSplitPGF = False,
|
||||||
optCFGTransforms = Set.fromList [CFGRemoveCycles, CFGBottomUpFilter,
|
optCFGTransforms = Set.fromList [CFGRemoveCycles, CFGBottomUpFilter,
|
||||||
CFGTopDownFilter, CFGMergeIdentical],
|
CFGTopDownFilter, CFGMergeIdentical],
|
||||||
optLibraryPath = [],
|
optLibraryPath = [],
|
||||||
optStartCat = Nothing,
|
optStartCat = Nothing,
|
||||||
@@ -301,7 +306,7 @@ defaultFlags = Flags {
|
|||||||
-- | Option descriptions
|
-- | Option descriptions
|
||||||
{-# NOINLINE optDescr #-}
|
{-# NOINLINE optDescr #-}
|
||||||
optDescr :: [OptDescr (Err Options)]
|
optDescr :: [OptDescr (Err Options)]
|
||||||
optDescr =
|
optDescr =
|
||||||
[
|
[
|
||||||
Option ['?','h'] ["help"] (NoArg (mode ModeHelp)) "Show help message.",
|
Option ['?','h'] ["help"] (NoArg (mode ModeHelp)) "Show help message.",
|
||||||
Option ['V'] ["version"] (NoArg (mode ModeVersion)) "Display GF version number.",
|
Option ['V'] ["version"] (NoArg (mode ModeVersion)) "Display GF version number.",
|
||||||
@@ -327,44 +332,44 @@ optDescr =
|
|||||||
-- Option ['t'] ["trace"] (NoArg (trace True)) "Trace computations",
|
-- Option ['t'] ["trace"] (NoArg (trace True)) "Trace computations",
|
||||||
-- Option [] ["no-trace"] (NoArg (trace False)) "Don't trace computations",
|
-- Option [] ["no-trace"] (NoArg (trace False)) "Don't trace computations",
|
||||||
Option [] ["gfo-dir"] (ReqArg gfoDir "DIR") "Directory to put .gfo files in (default = '.').",
|
Option [] ["gfo-dir"] (ReqArg gfoDir "DIR") "Directory to put .gfo files in (default = '.').",
|
||||||
Option ['f'] ["output-format"] (ReqArg outFmt "FMT")
|
Option ['f'] ["output-format"] (ReqArg outFmt "FMT")
|
||||||
(unlines ["Output format. FMT can be one of:",
|
(unlines ["Output format. FMT can be one of:",
|
||||||
"Canonical GF grammar: canonical_gf, canonical_json, (and haskell with option --haskell=concrete)",
|
"Canonical GF grammar: canonical_gf, canonical_json, (and haskell with option --haskell=concrete)",
|
||||||
"Multiple concrete: pgf (default), json, js, pgf_pretty, prolog, python, ...", -- gar,
|
"Multiple concrete: pgf (default), json, js, pgf_pretty, prolog, python, ...", -- gar,
|
||||||
"Single concrete only: bnf, ebnf, fa, gsl, jsgf, regexp, slf, srgs_xml, srgs_abnf, vxml, ....", -- cf, lbnf,
|
"Single concrete only: bnf, ebnf, fa, gsl, jsgf, regexp, slf, srgs_xml, srgs_abnf, vxml, ....", -- cf, lbnf,
|
||||||
"Abstract only: haskell, ..."]), -- prolog_abs,
|
"Abstract only: haskell, ..."]), -- prolog_abs,
|
||||||
Option [] ["sisr"] (ReqArg sisrFmt "FMT")
|
Option [] ["sisr"] (ReqArg sisrFmt "FMT")
|
||||||
(unlines ["Include SISR tags in generated speech recognition grammars.",
|
(unlines ["Include SISR tags in generated speech recognition grammars.",
|
||||||
"FMT can be one of: old, 1.0"]),
|
"FMT can be one of: old, 1.0"]),
|
||||||
Option [] ["haskell"] (ReqArg hsOption "OPTION")
|
Option [] ["haskell"] (ReqArg hsOption "OPTION")
|
||||||
("Turn on an optional feature when generating Haskell data types. OPTION = "
|
("Turn on an optional feature when generating Haskell data types. OPTION = "
|
||||||
++ concat (intersperse " | " (map fst haskellOptionNames))),
|
++ concat (intersperse " | " (map fst haskellOptionNames))),
|
||||||
Option [] ["lexical"] (ReqArg lexicalCat "CAT[,CAT[...]]")
|
Option [] ["lexical"] (ReqArg lexicalCat "CAT[,CAT[...]]")
|
||||||
"Treat CAT as a lexical category.",
|
"Treat CAT as a lexical category.",
|
||||||
Option [] ["literal"] (ReqArg literalCat "CAT[,CAT[...]]")
|
Option [] ["literal"] (ReqArg literalCat "CAT[,CAT[...]]")
|
||||||
"Treat CAT as a literal category.",
|
"Treat CAT as a literal category.",
|
||||||
Option ['D'] ["output-dir"] (ReqArg outDir "DIR")
|
Option ['D'] ["output-dir"] (ReqArg outDir "DIR")
|
||||||
"Save output files (other than .gfo files) in DIR.",
|
"Save output files (other than .gfo files) in DIR.",
|
||||||
Option [] ["gf-lib-path"] (ReqArg gfLibPath "DIR")
|
Option [] ["gf-lib-path"] (ReqArg gfLibPath "DIR")
|
||||||
"Overrides the value of GF_LIB_PATH.",
|
"Overrides the value of GF_LIB_PATH.",
|
||||||
Option [] ["src","force-recomp"] (NoArg (recomp AlwaysRecomp))
|
Option [] ["src","force-recomp"] (NoArg (recomp AlwaysRecomp))
|
||||||
"Always recompile from source.",
|
"Always recompile from source.",
|
||||||
Option [] ["recomp-if-newer"] (NoArg (recomp RecompIfNewer))
|
Option [] ["recomp-if-newer"] (NoArg (recomp RecompIfNewer))
|
||||||
"(default) Recompile from source if the source is newer than the .gfo file.",
|
"(default) Recompile from source if the source is newer than the .gfo file.",
|
||||||
Option [] ["gfo","no-recomp"] (NoArg (recomp NeverRecomp))
|
Option [] ["gfo","no-recomp"] (NoArg (recomp NeverRecomp))
|
||||||
"Never recompile from source, if there is already .gfo file.",
|
"Never recompile from source, if there is already .gfo file.",
|
||||||
Option [] ["retain"] (NoArg (set $ \o -> o { optRetainResource = True })) "Retain opers.",
|
Option [] ["retain"] (NoArg (set $ \o -> o { optRetainResource = True })) "Retain opers.",
|
||||||
Option [] ["probs"] (ReqArg probsFile "file.probs") "Read probabilities from file.",
|
Option [] ["probs"] (ReqArg probsFile "file.probs") "Read probabilities from file.",
|
||||||
Option ['n'] ["name"] (ReqArg name "NAME")
|
Option ['n'] ["name"] (ReqArg name "NAME")
|
||||||
(unlines ["Use NAME as the name of the output. This is used in the output file names, ",
|
(unlines ["Use NAME as the name of the output. This is used in the output file names, ",
|
||||||
"with suffixes depending on the formats, and, when relevant, ",
|
"with suffixes depending on the formats, and, when relevant, ",
|
||||||
"internally in the output."]),
|
"internally in the output."]),
|
||||||
Option ['i'] [] (ReqArg addLibDir "DIR") "Add DIR to the library search path.",
|
Option ['i'] [] (ReqArg addLibDir "DIR") "Add DIR to the library search path.",
|
||||||
Option [] ["path"] (ReqArg setLibPath "DIR:DIR:...") "Set the library search path.",
|
Option [] ["path"] (ReqArg setLibPath "DIR:DIR:...") "Set the library search path.",
|
||||||
Option [] ["preproc"] (ReqArg preproc "CMD")
|
Option [] ["preproc"] (ReqArg preproc "CMD")
|
||||||
(unlines ["Use CMD to preprocess input files.",
|
(unlines ["Use CMD to preprocess input files.",
|
||||||
"Multiple preprocessors can be used by giving this option multiple times."]),
|
"Multiple preprocessors can be used by giving this option multiple times."]),
|
||||||
Option [] ["coding"] (ReqArg coding "ENCODING")
|
Option [] ["coding"] (ReqArg coding "ENCODING")
|
||||||
("Character encoding of the source grammar, ENCODING = utf8, latin1, cp1251, ..."),
|
("Character encoding of the source grammar, ENCODING = utf8, latin1, cp1251, ..."),
|
||||||
Option [] ["startcat"] (ReqArg startcat "CAT") "Grammar start category.",
|
Option [] ["startcat"] (ReqArg startcat "CAT") "Grammar start category.",
|
||||||
Option [] ["language"] (ReqArg language "LANG") "Set the speech language flag to LANG in the generated grammar.",
|
Option [] ["language"] (ReqArg language "LANG") "Set the speech language flag to LANG in the generated grammar.",
|
||||||
@@ -372,7 +377,7 @@ optDescr =
|
|||||||
Option [] ["unlexer"] (ReqArg unlexer "UNLEXER") "Use unlexer UNLEXER.",
|
Option [] ["unlexer"] (ReqArg unlexer "UNLEXER") "Use unlexer UNLEXER.",
|
||||||
Option [] ["pmcfg"] (NoArg (pmcfg True)) "Generate PMCFG (default).",
|
Option [] ["pmcfg"] (NoArg (pmcfg True)) "Generate PMCFG (default).",
|
||||||
Option [] ["no-pmcfg"] (NoArg (pmcfg False)) "Don't generate PMCFG (useful for libraries).",
|
Option [] ["no-pmcfg"] (NoArg (pmcfg False)) "Don't generate PMCFG (useful for libraries).",
|
||||||
Option [] ["optimize"] (ReqArg optimize "OPT")
|
Option [] ["optimize"] (ReqArg optimize "OPT")
|
||||||
"Select an optimization package. OPT = all | values | parametrize | none",
|
"Select an optimization package. OPT = all | values | parametrize | none",
|
||||||
Option [] ["optimize-pgf"] (NoArg (optimize_pgf True))
|
Option [] ["optimize-pgf"] (NoArg (optimize_pgf True))
|
||||||
"Enable or disable global grammar optimization. This could significantly reduce the size of the final PGF file",
|
"Enable or disable global grammar optimization. This could significantly reduce the size of the final PGF file",
|
||||||
@@ -447,7 +452,7 @@ optDescr =
|
|||||||
optimize x = case lookup x optimizationPackages of
|
optimize x = case lookup x optimizationPackages of
|
||||||
Just p -> set $ \o -> o { optOptimizations = p }
|
Just p -> set $ \o -> o { optOptimizations = p }
|
||||||
Nothing -> fail $ "Unknown optimization package: " ++ x
|
Nothing -> fail $ "Unknown optimization package: " ++ x
|
||||||
|
|
||||||
optimize_pgf x = set $ \o -> o { optOptimizePGF = x }
|
optimize_pgf x = set $ \o -> o { optOptimizePGF = x }
|
||||||
splitPGF x = set $ \o -> o { optSplitPGF = x }
|
splitPGF x = set $ \o -> o { optSplitPGF = x }
|
||||||
|
|
||||||
@@ -471,7 +476,7 @@ outputFormats :: [(String,OutputFormat)]
|
|||||||
outputFormats = map fst outputFormatsExpl
|
outputFormats = map fst outputFormatsExpl
|
||||||
|
|
||||||
outputFormatsExpl :: [((String,OutputFormat),String)]
|
outputFormatsExpl :: [((String,OutputFormat),String)]
|
||||||
outputFormatsExpl =
|
outputFormatsExpl =
|
||||||
[(("pgf_pretty", FmtPGFPretty),"human-readable pgf"),
|
[(("pgf_pretty", FmtPGFPretty),"human-readable pgf"),
|
||||||
(("canonical_gf", FmtCanonicalGF),"Canonical GF source files"),
|
(("canonical_gf", FmtCanonicalGF),"Canonical GF source files"),
|
||||||
(("canonical_json", FmtCanonicalJson),"Canonical JSON source files"),
|
(("canonical_json", FmtCanonicalJson),"Canonical JSON source files"),
|
||||||
@@ -504,11 +509,11 @@ instance Read OutputFormat where
|
|||||||
readsPrec = lookupReadsPrec outputFormats
|
readsPrec = lookupReadsPrec outputFormats
|
||||||
|
|
||||||
optimizationPackages :: [(String, Set Optimization)]
|
optimizationPackages :: [(String, Set Optimization)]
|
||||||
optimizationPackages =
|
optimizationPackages =
|
||||||
[("all", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize]),
|
[("all", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize]),
|
||||||
("values", Set.fromList [OptStem,OptCSE,OptExpand]),
|
("values", Set.fromList [OptStem,OptCSE,OptExpand]),
|
||||||
("noexpand", Set.fromList [OptStem,OptCSE]),
|
("noexpand", Set.fromList [OptStem,OptCSE]),
|
||||||
|
|
||||||
-- deprecated
|
-- deprecated
|
||||||
("all_subs", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize]),
|
("all_subs", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize]),
|
||||||
("parametrize", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize]),
|
("parametrize", Set.fromList [OptStem,OptCSE,OptExpand,OptParametrize]),
|
||||||
@@ -516,7 +521,7 @@ optimizationPackages =
|
|||||||
]
|
]
|
||||||
|
|
||||||
cfgTransformNames :: [(String, CFGTransform)]
|
cfgTransformNames :: [(String, CFGTransform)]
|
||||||
cfgTransformNames =
|
cfgTransformNames =
|
||||||
[("nolr", CFGNoLR),
|
[("nolr", CFGNoLR),
|
||||||
("regular", CFGRegular),
|
("regular", CFGRegular),
|
||||||
("topdown", CFGTopDownFilter),
|
("topdown", CFGTopDownFilter),
|
||||||
@@ -532,7 +537,8 @@ haskellOptionNames =
|
|||||||
("lexical", HaskellLexical),
|
("lexical", HaskellLexical),
|
||||||
("concrete", HaskellConcrete),
|
("concrete", HaskellConcrete),
|
||||||
("variants", HaskellVariants),
|
("variants", HaskellVariants),
|
||||||
("data", HaskellData)]
|
("data", HaskellData),
|
||||||
|
("pgf2", HaskellPGF2)]
|
||||||
|
|
||||||
-- | This is for bacward compatibility. Since GHC 6.12 we
|
-- | This is for bacward compatibility. Since GHC 6.12 we
|
||||||
-- started using the native Unicode support in GHC but it
|
-- started using the native Unicode support in GHC but it
|
||||||
@@ -558,7 +564,7 @@ onOff f def = OptArg g "[on,off]"
|
|||||||
_ -> fail $ "Expected [on,off], got: " ++ show x
|
_ -> fail $ "Expected [on,off], got: " ++ show x
|
||||||
|
|
||||||
readOutputFormat :: Fail.MonadFail m => String -> m OutputFormat
|
readOutputFormat :: Fail.MonadFail m => String -> m OutputFormat
|
||||||
readOutputFormat s =
|
readOutputFormat s =
|
||||||
maybe (fail $ "Unknown output format: " ++ show s) return $ lookup s outputFormats
|
maybe (fail $ "Unknown output format: " ++ show s) return $ lookup s outputFormats
|
||||||
|
|
||||||
-- FIXME: this is a copy of the function in GF.Devel.UseIO.
|
-- FIXME: this is a copy of the function in GF.Devel.UseIO.
|
||||||
@@ -570,7 +576,7 @@ splitInModuleSearchPath s = case break isPathSep s of
|
|||||||
isPathSep :: Char -> Bool
|
isPathSep :: Char -> Bool
|
||||||
isPathSep c = c == ':' || c == ';'
|
isPathSep c = c == ':' || c == ';'
|
||||||
|
|
||||||
--
|
--
|
||||||
-- * Convenience functions for checking options
|
-- * Convenience functions for checking options
|
||||||
--
|
--
|
||||||
|
|
||||||
@@ -592,7 +598,7 @@ isLiteralCat opts c = Set.member c (flag optLiteralCats opts)
|
|||||||
isLexicalCat :: Options -> String -> Bool
|
isLexicalCat :: Options -> String -> Bool
|
||||||
isLexicalCat opts c = Set.member c (flag optLexicalCats opts)
|
isLexicalCat opts c = Set.member c (flag optLexicalCats opts)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- * Convenience functions for setting options
|
-- * Convenience functions for setting options
|
||||||
--
|
--
|
||||||
|
|
||||||
@@ -623,8 +629,8 @@ readMaybe s = case reads s of
|
|||||||
|
|
||||||
toEnumBounded :: (Bounded a, Enum a, Ord a) => Int -> Maybe a
|
toEnumBounded :: (Bounded a, Enum a, Ord a) => Int -> Maybe a
|
||||||
toEnumBounded i = let mi = minBound
|
toEnumBounded i = let mi = minBound
|
||||||
ma = maxBound `asTypeOf` mi
|
ma = maxBound `asTypeOf` mi
|
||||||
in if i >= fromEnum mi && i <= fromEnum ma
|
in if i >= fromEnum mi && i <= fromEnum ma
|
||||||
then Just (toEnum i `asTypeOf` mi)
|
then Just (toEnum i `asTypeOf` mi)
|
||||||
else Nothing
|
else Nothing
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -16,18 +16,21 @@ 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 GHC.IO.Encoding
|
||||||
|
-- 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
|
setLocaleEncoding utf8
|
||||||
|
-- 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 +46,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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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 _ = []
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ decodeUnicode :: TextEncoding -> ByteString -> String
|
|||||||
decodeUnicode enc bs = unsafePerformIO $ decodeUnicodeIO enc bs
|
decodeUnicode enc bs = unsafePerformIO $ decodeUnicodeIO enc bs
|
||||||
|
|
||||||
decodeUnicodeIO enc (PS fptr l len) = do
|
decodeUnicodeIO enc (PS fptr l len) = do
|
||||||
let bbuf = Buffer{bufRaw=fptr, bufState=ReadBuffer, bufSize=len, bufL=l, bufR=l+len}
|
let bbuf = (emptyBuffer fptr len ReadBuffer) { bufL=l, bufR=l+len }
|
||||||
cbuf <- newCharBuffer 128 WriteBuffer
|
cbuf <- newCharBuffer 128 WriteBuffer
|
||||||
case enc of
|
case enc of
|
||||||
TextEncoding {mkTextDecoder=mk} -> do decoder <- mk
|
TextEncoding {mkTextDecoder=mk} -> do decoder <- mk
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
import qualified GF
|
import qualified GF
|
||||||
|
|
||||||
main = GF.main
|
main = GF.main
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -18,12 +18,24 @@ gu_exn_is_raised(GuExn* err) {
|
|||||||
return err && (err->state == GU_EXN_RAISED);
|
return err && (err->state == GU_EXN_RAISED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GU_API_DECL void
|
||||||
|
gu_exn_clear(GuExn* err) {
|
||||||
|
err->caught = NULL;
|
||||||
|
err->state = GU_EXN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
GU_API bool
|
GU_API bool
|
||||||
gu_exn_caught_(GuExn* err, const char* type)
|
gu_exn_caught_(GuExn* err, const char* type)
|
||||||
{
|
{
|
||||||
return (err->caught && strcmp(err->caught, type) == 0);
|
return (err->caught && strcmp(err->caught, type) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GU_API_DECL void*
|
||||||
|
gu_exn_caught_data(GuExn* err)
|
||||||
|
{
|
||||||
|
return err->data.data;
|
||||||
|
}
|
||||||
|
|
||||||
GU_API void
|
GU_API void
|
||||||
gu_exn_block(GuExn* err)
|
gu_exn_block(GuExn* err)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -71,11 +71,13 @@ gu_new_exn(GuPool* pool);
|
|||||||
GU_API_DECL bool
|
GU_API_DECL bool
|
||||||
gu_exn_is_raised(GuExn* err);
|
gu_exn_is_raised(GuExn* err);
|
||||||
|
|
||||||
static inline void
|
// static inline void
|
||||||
gu_exn_clear(GuExn* err) {
|
// gu_exn_clear(GuExn* err) {
|
||||||
err->caught = NULL;
|
// err->caught = NULL;
|
||||||
err->state = GU_EXN_OK;
|
// err->state = GU_EXN_OK;
|
||||||
}
|
// }
|
||||||
|
GU_API_DECL void
|
||||||
|
gu_exn_clear(GuExn* err);
|
||||||
|
|
||||||
#define gu_exn_caught(err, type) \
|
#define gu_exn_caught(err, type) \
|
||||||
(err->caught && strcmp(err->caught, #type) == 0)
|
(err->caught && strcmp(err->caught, #type) == 0)
|
||||||
@@ -83,11 +85,13 @@ gu_exn_clear(GuExn* err) {
|
|||||||
GU_API_DECL bool
|
GU_API_DECL bool
|
||||||
gu_exn_caught_(GuExn* err, const char* type);
|
gu_exn_caught_(GuExn* err, const char* type);
|
||||||
|
|
||||||
static inline const void*
|
// static inline const void*
|
||||||
gu_exn_caught_data(GuExn* err)
|
// gu_exn_caught_data(GuExn* err)
|
||||||
{
|
// {
|
||||||
return err->data.data;
|
// return err->data.data;
|
||||||
}
|
// }
|
||||||
|
GU_API_DECL void*
|
||||||
|
gu_exn_caught_data(GuExn* err);
|
||||||
|
|
||||||
/// Temporarily block a raised exception.
|
/// Temporarily block a raised exception.
|
||||||
GU_API_DECL void
|
GU_API_DECL void
|
||||||
|
|||||||
3
src/runtime/c/install.sh
Executable file
3
src/runtime/c/install.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
bash setup.sh configure
|
||||||
|
bash setup.sh build
|
||||||
|
bash setup.sh install
|
||||||
@@ -8,6 +8,42 @@
|
|||||||
|
|
||||||
//#define PGF_JIT_DEBUG
|
//#define PGF_JIT_DEBUG
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
|
||||||
|
PGF_INTERNAL PgfJitState*
|
||||||
|
pgf_new_jit(PgfReader* rdr)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PGF_INTERNAL PgfEvalGates*
|
||||||
|
pgf_jit_gates(PgfReader* rdr)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PGF_INTERNAL void
|
||||||
|
pgf_jit_predicate(PgfReader* rdr, PgfAbstr* abstr,
|
||||||
|
PgfAbsCat* abscat)
|
||||||
|
{
|
||||||
|
size_t n_funs = pgf_read_len(rdr);
|
||||||
|
gu_return_on_exn(rdr->err, );
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n_funs; i++) {
|
||||||
|
gu_in_f64be(rdr->in, rdr->err); // ignore
|
||||||
|
gu_return_on_exn(rdr->err, );
|
||||||
|
|
||||||
|
PgfCId name = pgf_read_cid(rdr, rdr->tmp_pool);
|
||||||
|
gu_return_on_exn(rdr->err, );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PGF_INTERNAL void
|
||||||
|
pgf_jit_done(PgfReader* rdr, PgfAbstr* abstr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
struct PgfJitState {
|
struct PgfJitState {
|
||||||
jit_state jit;
|
jit_state jit;
|
||||||
@@ -1329,3 +1365,5 @@ pgf_jit_done(PgfReader* rdr, PgfAbstr* abstr)
|
|||||||
|
|
||||||
jit_flush_code(rdr->jit_state->buf, jit_get_ip().ptr);
|
jit_flush_code(rdr->jit_state->buf, jit_get_ip().ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ typedef struct {
|
|||||||
PgfParseState *before;
|
PgfParseState *before;
|
||||||
PgfParseState *after;
|
PgfParseState *after;
|
||||||
PgfToken prefix;
|
PgfToken prefix;
|
||||||
|
bool prefix_bind;
|
||||||
PgfTokenProb* tp;
|
PgfTokenProb* tp;
|
||||||
PgfExprEnum en; // enumeration for the generated trees/tokens
|
PgfExprEnum en; // enumeration for the generated trees/tokens
|
||||||
#ifdef PGF_COUNTS_DEBUG
|
#ifdef PGF_COUNTS_DEBUG
|
||||||
@@ -1009,6 +1010,7 @@ pgf_new_parse_state(PgfParsing* ps, size_t start_offset,
|
|||||||
(start_offset == end_offset);
|
(start_offset == end_offset);
|
||||||
state->start_offset = start_offset;
|
state->start_offset = start_offset;
|
||||||
state->end_offset = end_offset;
|
state->end_offset = end_offset;
|
||||||
|
|
||||||
state->viterbi_prob = viterbi_prob;
|
state->viterbi_prob = viterbi_prob;
|
||||||
state->lexicon_idx =
|
state->lexicon_idx =
|
||||||
gu_new_buf(PgfLexiconIdxEntry, ps->pool);
|
gu_new_buf(PgfLexiconIdxEntry, ps->pool);
|
||||||
@@ -1381,20 +1383,30 @@ pgf_parsing_symbol(PgfParsing* ps, PgfItem* item, PgfSymbol sym)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PGF_SYMBOL_BIND: {
|
case PGF_SYMBOL_BIND: {
|
||||||
if (ps->before->start_offset == ps->before->end_offset &&
|
if (!ps->prefix_bind && ps->prefix != NULL && *(ps->sentence + ps->before->end_offset) == 0) {
|
||||||
ps->before->needs_bind) {
|
PgfProductionApply* papp = gu_variant_data(item->prod);
|
||||||
PgfParseState* state =
|
|
||||||
pgf_new_parse_state(ps, ps->before->end_offset, BIND_HARD,
|
ps->tp = gu_new(PgfTokenProb, ps->out_pool);
|
||||||
item->inside_prob+item->conts->outside_prob);
|
ps->tp->tok = NULL;
|
||||||
if (state != NULL) {
|
ps->tp->cat = item->conts->ccat->cnccat->abscat->name;
|
||||||
pgf_item_advance(item, ps->pool);
|
ps->tp->fun = papp->fun->absfun->name;
|
||||||
gu_buf_heap_push(state->agenda, pgf_item_prob_order, &item);
|
ps->tp->prob = item->inside_prob + item->conts->outside_prob;
|
||||||
} else {
|
} else {
|
||||||
pgf_item_free(ps, item);
|
if (ps->before->start_offset == ps->before->end_offset &&
|
||||||
}
|
ps->before->needs_bind) {
|
||||||
} else {
|
PgfParseState* state =
|
||||||
pgf_item_free(ps, item);
|
pgf_new_parse_state(ps, ps->before->end_offset, BIND_HARD,
|
||||||
}
|
item->inside_prob+item->conts->outside_prob);
|
||||||
|
if (state != NULL) {
|
||||||
|
pgf_item_advance(item, ps->pool);
|
||||||
|
gu_buf_heap_push(state->agenda, pgf_item_prob_order, &item);
|
||||||
|
} else {
|
||||||
|
pgf_item_free(ps, item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pgf_item_free(ps, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PGF_SYMBOL_SOFT_BIND:
|
case PGF_SYMBOL_SOFT_BIND:
|
||||||
@@ -2337,7 +2349,8 @@ pgf_parser_completions_next(GuEnum* self, void* to, GuPool* pool)
|
|||||||
|
|
||||||
PGF_API GuEnum*
|
PGF_API GuEnum*
|
||||||
pgf_complete(PgfConcr* concr, PgfType* type, GuString sentence,
|
pgf_complete(PgfConcr* concr, PgfType* type, GuString sentence,
|
||||||
GuString prefix, GuExn *err, GuPool* pool)
|
GuString prefix, bool prefix_bind,
|
||||||
|
GuExn *err, GuPool* pool)
|
||||||
{
|
{
|
||||||
if (concr->sequences == NULL ||
|
if (concr->sequences == NULL ||
|
||||||
concr->cnccats == NULL) {
|
concr->cnccats == NULL) {
|
||||||
@@ -2377,6 +2390,7 @@ pgf_complete(PgfConcr* concr, PgfType* type, GuString sentence,
|
|||||||
// Now begin enumerating the completions
|
// Now begin enumerating the completions
|
||||||
ps->en.next = pgf_parser_completions_next;
|
ps->en.next = pgf_parser_completions_next;
|
||||||
ps->prefix = prefix;
|
ps->prefix = prefix;
|
||||||
|
ps->prefix_bind = prefix_bind;
|
||||||
ps->tp = NULL;
|
ps->tp = NULL;
|
||||||
return &ps->en;
|
return &ps->en;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,7 +251,8 @@ typedef struct {
|
|||||||
|
|
||||||
PGF_API_DECL GuEnum*
|
PGF_API_DECL GuEnum*
|
||||||
pgf_complete(PgfConcr* concr, PgfType* type, GuString string,
|
pgf_complete(PgfConcr* concr, PgfType* type, GuString string,
|
||||||
GuString prefix, GuExn* err, GuPool* pool);
|
GuString prefix, bool prefix_bind,
|
||||||
|
GuExn* err, GuPool* pool);
|
||||||
|
|
||||||
typedef struct PgfLiteralCallback PgfLiteralCallback;
|
typedef struct PgfLiteralCallback PgfLiteralCallback;
|
||||||
|
|
||||||
|
|||||||
@@ -1326,7 +1326,7 @@ pgf_read_concretes(PgfReader* rdr, PgfAbstr* abstr, bool with_content)
|
|||||||
PGF_INTERNAL PgfPGF*
|
PGF_INTERNAL PgfPGF*
|
||||||
pgf_read_pgf(PgfReader* rdr) {
|
pgf_read_pgf(PgfReader* rdr) {
|
||||||
PgfPGF* pgf = gu_new(PgfPGF, rdr->opool);
|
PgfPGF* pgf = gu_new(PgfPGF, rdr->opool);
|
||||||
|
|
||||||
pgf->major_version = gu_in_u16be(rdr->in, rdr->err);
|
pgf->major_version = gu_in_u16be(rdr->in, rdr->err);
|
||||||
gu_return_on_exn(rdr->err, NULL);
|
gu_return_on_exn(rdr->err, NULL);
|
||||||
|
|
||||||
@@ -1335,7 +1335,7 @@ pgf_read_pgf(PgfReader* rdr) {
|
|||||||
|
|
||||||
pgf->gflags = pgf_read_flags(rdr);
|
pgf->gflags = pgf_read_flags(rdr);
|
||||||
gu_return_on_exn(rdr->err, NULL);
|
gu_return_on_exn(rdr->err, NULL);
|
||||||
|
|
||||||
pgf_read_abstract(rdr, &pgf->abstract);
|
pgf_read_abstract(rdr, &pgf->abstract);
|
||||||
gu_return_on_exn(rdr->err, NULL);
|
gu_return_on_exn(rdr->err, NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -1026,7 +1026,10 @@ complete lang (Type ctype _) sent pfx =
|
|||||||
touchConcr lang
|
touchConcr lang
|
||||||
return []
|
return []
|
||||||
else do
|
else do
|
||||||
tok <- peekUtf8CString =<< (#peek PgfTokenProb, tok) cmpEntry
|
p_tok <- (#peek PgfTokenProb, tok) cmpEntry
|
||||||
|
tok <- if p_tok == nullPtr
|
||||||
|
then return "&+"
|
||||||
|
else peekUtf8CString p_tok
|
||||||
cat <- peekUtf8CString =<< (#peek PgfTokenProb, cat) cmpEntry
|
cat <- peekUtf8CString =<< (#peek PgfTokenProb, cat) cmpEntry
|
||||||
fun <- peekUtf8CString =<< (#peek PgfTokenProb, fun) cmpEntry
|
fun <- peekUtf8CString =<< (#peek PgfTokenProb, fun) cmpEntry
|
||||||
prob <- (#peek PgfTokenProb, prob) cmpEntry
|
prob <- (#peek PgfTokenProb, prob) cmpEntry
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.16,
|
||||||
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
|
||||||
|
|||||||
3
src/runtime/haskell-bind/stack-ghc7.10.3.yaml
Normal file
3
src/runtime/haskell-bind/stack-ghc7.10.3.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
resolver: lts-6.35 # ghc 7.10.3
|
||||||
|
|
||||||
|
allow-newer: true
|
||||||
1
src/runtime/haskell-bind/stack-ghc8.0.2.yaml
Normal file
1
src/runtime/haskell-bind/stack-ghc8.0.2.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
resolver: lts-9.21 # ghc 8.0.2
|
||||||
1
src/runtime/haskell-bind/stack-ghc8.10.4.yaml
Normal file
1
src/runtime/haskell-bind/stack-ghc8.10.4.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
resolver: lts-18.0 # ghc 8.10.4
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
{-# LANGUAGE CPP, MagicHash #-}
|
{-# LANGUAGE CPP, MagicHash #-}
|
||||||
|
-- This module makes profiling a lot slower, so don't add automatic cost centres
|
||||||
|
{-# OPTIONS_GHC -fno-prof-auto #-}
|
||||||
-- for unboxed shifts
|
-- for unboxed shifts
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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.16,
|
||||||
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
|
||||||
|
|||||||
3
src/runtime/haskell/stack-ghc7.10.3.yaml
Normal file
3
src/runtime/haskell/stack-ghc7.10.3.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
resolver: lts-6.35 # ghc 7.10.3
|
||||||
|
|
||||||
|
allow-newer: true
|
||||||
1
src/runtime/haskell/stack-ghc8.0.2.yaml
Normal file
1
src/runtime/haskell/stack-ghc8.0.2.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
resolver: lts-9.21 # ghc 8.0.2
|
||||||
1
src/runtime/haskell/stack-ghc8.10.4.yaml
Normal file
1
src/runtime/haskell/stack-ghc8.10.4.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
resolver: lts-18.0 # ghc 8.10.4
|
||||||
1
src/runtime/javascript/.gitignore
vendored
Normal file
1
src/runtime/javascript/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.libs/
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# Deprecation notice
|
|
||||||
|
|
||||||
As of June 2019, this JavaScript version of the GF runtime is considered deprecated,
|
|
||||||
in favour of the TypeScript version in <https://github.com/GrammaticalFramework/gf-typescript>.
|
|
||||||
48
src/runtime/javascript/Dockerfile
Normal file
48
src/runtime/javascript/Dockerfile
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
FROM emscripten/emsdk:latest
|
||||||
|
|
||||||
|
RUN apt update
|
||||||
|
RUN apt install -y autoconf automake libtool make
|
||||||
|
|
||||||
|
WORKDIR /tmp/c
|
||||||
|
COPY gu/*.c gu/*.h /tmp/c/gu/
|
||||||
|
COPY pgf/*.c pgf/*.h /tmp/c/pgf/
|
||||||
|
COPY pgf/lightning/i386/*.h /tmp/c/pgf/lightning/i386/
|
||||||
|
COPY pgf/lightning/*.h /tmp/c/pgf/lightning/
|
||||||
|
COPY \
|
||||||
|
Makefile.am \
|
||||||
|
configure.ac \
|
||||||
|
lib*.pc.in \
|
||||||
|
/tmp/c/
|
||||||
|
RUN autoreconf -i
|
||||||
|
RUN emconfigure ./configure
|
||||||
|
RUN emmake make
|
||||||
|
RUN emcc .libs/libgu.a .libs/libpgf.a -o pgf.js \
|
||||||
|
-sALLOW_MEMORY_GROWTH \
|
||||||
|
-sEXPORTED_FUNCTIONS="\
|
||||||
|
_pgf_read,\
|
||||||
|
_pgf_abstract_name,\
|
||||||
|
_pgf_read_expr,\
|
||||||
|
_pgf_print_expr,\
|
||||||
|
_pgf_expr_arity,\
|
||||||
|
_gu_new_pool,\
|
||||||
|
_gu_new_exn,\
|
||||||
|
_gu_data_in,\
|
||||||
|
_gu_exn_is_raised,\
|
||||||
|
_gu_exn_caught_,\
|
||||||
|
_gu_exn_caught_data,\
|
||||||
|
_gu_exn_clear,\
|
||||||
|
_gu_new_string_buf,\
|
||||||
|
_gu_string_buf_out,\
|
||||||
|
_gu_string_buf_data,\
|
||||||
|
_malloc,\
|
||||||
|
_free\
|
||||||
|
"\
|
||||||
|
-sEXPORTED_RUNTIME_METHODS="\
|
||||||
|
ccall,\
|
||||||
|
FS,\
|
||||||
|
getValue,\
|
||||||
|
AsciiToString,\
|
||||||
|
stringToUTF8,\
|
||||||
|
UTF8ToString,\
|
||||||
|
allocateUTF8\
|
||||||
|
"
|
||||||
11
src/runtime/javascript/README.md
Normal file
11
src/runtime/javascript/README.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# JavaScript runtime using Web Assembly
|
||||||
|
|
||||||
|
This folder contains very early work experimenting with a pure JavaScript runtime,
|
||||||
|
compiled to Web Assembly (WASM) using [Emscripten](https://emscripten.org/).
|
||||||
|
|
||||||
|
1. Compile the WASM files (inside Docker) using `build-wasm.sh`, placing them in `.libs/`
|
||||||
|
2. Test in Node.js by running `node test-node.js [path to PGF]`
|
||||||
|
3. Test in a web browser
|
||||||
|
1. Start a server with `npx serve -l 41296`
|
||||||
|
2. Browse to `http://localhost:41296/test-web.html`
|
||||||
|
3. Check JavaScript console
|
||||||
10
src/runtime/javascript/build-wasm.sh
Executable file
10
src/runtime/javascript/build-wasm.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#! /usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Build inside Docker image
|
||||||
|
IMAGE="gf/build-c-runtime-wasm"
|
||||||
|
docker build ../c --file Dockerfile --tag $IMAGE
|
||||||
|
|
||||||
|
# Copy bulit files from container to host
|
||||||
|
mkdir -p .libs
|
||||||
|
docker run --rm --volume "$PWD":/tmp/host $IMAGE bash -c "cp pgf.js pgf.wasm /tmp/host/.libs/"
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
abstract Editor = {
|
|
||||||
|
|
||||||
cat Adjective ;
|
|
||||||
Noun ;
|
|
||||||
Verb ;
|
|
||||||
Determiner ;
|
|
||||||
Sentence ;
|
|
||||||
|
|
||||||
fun Available : Adjective ;
|
|
||||||
Next : Adjective ;
|
|
||||||
Previous : Adjective ;
|
|
||||||
|
|
||||||
fun Bulgarian : Noun ;
|
|
||||||
Danish : Noun ;
|
|
||||||
English : Noun ;
|
|
||||||
Finnish : Noun ;
|
|
||||||
French : Noun ;
|
|
||||||
German : Noun ;
|
|
||||||
Italian : Noun ;
|
|
||||||
Norwegian : Noun ;
|
|
||||||
Russian : Noun ;
|
|
||||||
Spanish : Noun ;
|
|
||||||
Swedish : Noun ;
|
|
||||||
|
|
||||||
fun Float_N : Noun ;
|
|
||||||
Integer_N : Noun ;
|
|
||||||
String_N : Noun ;
|
|
||||||
|
|
||||||
Language : Noun ;
|
|
||||||
Node : Noun ;
|
|
||||||
Page : Noun ;
|
|
||||||
Refinement : Noun ;
|
|
||||||
Tree : Noun ;
|
|
||||||
Wrapper : Noun ;
|
|
||||||
|
|
||||||
fun Copy : Verb ;
|
|
||||||
Cut : Verb ;
|
|
||||||
Delete : Verb ;
|
|
||||||
Enter : Verb ;
|
|
||||||
Parse : Verb ;
|
|
||||||
Paste : Verb ;
|
|
||||||
Redo : Verb ;
|
|
||||||
Refine : Verb ;
|
|
||||||
Replace : Verb ;
|
|
||||||
Select : Verb ;
|
|
||||||
Show : Verb ;
|
|
||||||
Undo : Verb ;
|
|
||||||
Wrap : Verb ;
|
|
||||||
|
|
||||||
fun DefPlDet : Determiner ;
|
|
||||||
DefSgDet : Determiner ;
|
|
||||||
IndefPlDet : Determiner ;
|
|
||||||
IndefSgDet : Determiner ;
|
|
||||||
|
|
||||||
fun Command : Verb -> Determiner -> Noun -> Sentence ;
|
|
||||||
CommandAdj : Verb -> Determiner -> Adjective -> Noun -> Sentence ;
|
|
||||||
ErrorMessage : Adjective -> Noun -> Sentence ;
|
|
||||||
Label : Noun -> Sentence ;
|
|
||||||
RandomlyCommand : Verb -> Determiner -> Noun -> Sentence ;
|
|
||||||
SingleWordCommand : Verb -> Sentence ;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
--# -path=alltenses
|
|
||||||
concrete EditorEng of Editor = open GrammarEng, ParadigmsEng in {
|
|
||||||
|
|
||||||
lincat Adjective = A ;
|
|
||||||
Noun = N ;
|
|
||||||
Verb = V ;
|
|
||||||
Determiner = Det ;
|
|
||||||
Sentence = Utt ;
|
|
||||||
|
|
||||||
lin Available = mkA "available" ;
|
|
||||||
Next = mkA "next" ;
|
|
||||||
Previous = mkA "previous" ;
|
|
||||||
|
|
||||||
lin Bulgarian = mkN "Bulgarian" ;
|
|
||||||
Danish = mkN "Danish" ;
|
|
||||||
English = mkN "English" ;
|
|
||||||
Finnish = mkN "Finnish" ;
|
|
||||||
French = mkN "French" ;
|
|
||||||
German = mkN "German" ;
|
|
||||||
Italian = mkN "Italian" ;
|
|
||||||
Norwegian = mkN "Norwegian" ;
|
|
||||||
Russian = mkN "Russian" ;
|
|
||||||
Spanish = mkN "Spanish" ;
|
|
||||||
Swedish = mkN "Swedish" ;
|
|
||||||
|
|
||||||
lin Float_N = mkN "float" ;
|
|
||||||
Integer_N = mkN "integer" ;
|
|
||||||
String_N = mkN "string" ;
|
|
||||||
|
|
||||||
Language = mkN "language" ;
|
|
||||||
Node = mkN "node" ;
|
|
||||||
Page = mkN "page" ;
|
|
||||||
Refinement = mkN "refinement" ;
|
|
||||||
Tree = mkN "tree" ;
|
|
||||||
Wrapper = mkN "wrapper" ;
|
|
||||||
|
|
||||||
lin Copy = mkV "copy" ;
|
|
||||||
Cut = mkV "cut" ;
|
|
||||||
Delete = mkV "delete" ;
|
|
||||||
Enter = mkV "enter" ;
|
|
||||||
Parse = mkV "parse" ;
|
|
||||||
Paste = mkV "paste" ;
|
|
||||||
Redo = mkV "redo" ;
|
|
||||||
Refine = mkV "refine" ;
|
|
||||||
Replace = mkV "replace" ;
|
|
||||||
Select = mkV "select" ;
|
|
||||||
Show = mkV "show" ;
|
|
||||||
Undo = mkV "undo" ;
|
|
||||||
Wrap = mkV "wrap" ;
|
|
||||||
|
|
||||||
lin DefPlDet = DetQuant DefArt NumPl ;
|
|
||||||
DefSgDet = DetQuant DefArt NumSg ;
|
|
||||||
IndefPlDet = DetQuant IndefArt NumPl ;
|
|
||||||
IndefSgDet = DetQuant IndefArt NumSg ;
|
|
||||||
|
|
||||||
lin Command v d n = UttImpSg PPos (ImpVP (ComplSlash (SlashV2a (mkV2 v)) (DetCN d (UseN n)))) ;
|
|
||||||
CommandAdj v d a n = UttImpSg PPos (ImpVP (ComplSlash (SlashV2a (mkV2 v)) (DetCN d (AdjCN (PositA a) (UseN n))))) ;
|
|
||||||
ErrorMessage a n = UttNP (DetCN (DetQuant no_Quant NumPl) (AdjCN (PositA a) (UseN n))) ;
|
|
||||||
Label n = UttNP (MassNP (UseN n)) ;
|
|
||||||
RandomlyCommand v d n = UttImpSg PPos (ImpVP (AdvVP (ComplSlash (SlashV2a (mkV2 v)) (DetCN d (UseN n))) (PrepNP (mkPrep "at") (MassNP (UseN (mkN "random")))))) ;
|
|
||||||
SingleWordCommand v = UttImpSg PPos (ImpVP (UseV v)) ;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
|
||||||
<script type="text/javascript" src="gflib.js"></script>
|
|
||||||
<script type="text/javascript" src="editorGrammar.js"></script>
|
|
||||||
<script type="text/javascript" src="grammar.js"></script>
|
|
||||||
<script type="text/javascript" src="gfjseditor.js"></script>
|
|
||||||
<title>Web-based Syntax Editor</title>
|
|
||||||
</head>
|
|
||||||
<body onload="mkEditor('editor', Foods)" onkeydown="return hotKeys(event)">
|
|
||||||
<div id="editor">
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 161 B |
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
|||||||
/* Output */
|
|
||||||
|
|
||||||
function sayText(text) {
|
|
||||||
document.voice_output_text = text;
|
|
||||||
activateForm("voice_output");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XHTML+Voice Utilities */
|
|
||||||
|
|
||||||
function activateForm(formid) {
|
|
||||||
var form = document.getElementById(formid);
|
|
||||||
var e = document.createEvent("UIEvents");
|
|
||||||
e.initEvent("DOMActivate","true","true");
|
|
||||||
form.dispatchEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* DOM utilities */
|
|
||||||
|
|
||||||
/* Gets the head element of the document. */
|
|
||||||
function getHeadElement() {
|
|
||||||
var hs = document.getElementsByTagName("head");
|
|
||||||
if (hs.length == 0) {
|
|
||||||
var head = document.createElement("head");
|
|
||||||
document.documentElement.insertBefore(head, document.documentElement.firstChild);
|
|
||||||
return head;
|
|
||||||
} else {
|
|
||||||
return hs[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Gets the body element of the document. */
|
|
||||||
function getBodyElement() {
|
|
||||||
var bs = document.getElementsByTagName("body");
|
|
||||||
if (bs.length == 0) {
|
|
||||||
var body = document.createElement("body");
|
|
||||||
document.documentElement.appendChild(body);
|
|
||||||
return body;
|
|
||||||
} else {
|
|
||||||
return bs[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Removes all the children of a node */
|
|
||||||
function removeChildren(node) {
|
|
||||||
while (node.hasChildNodes()) {
|
|
||||||
node.removeChild(node.firstChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setText(node, text) {
|
|
||||||
removeChildren(node);
|
|
||||||
node.appendChild(document.createTextNode(text));
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user