118 Commits

Author SHA1 Message Date
Krasimir Angelov
1957eb1fc5 more comments 2022-09-12 12:20:30 +02:00
Krasimir Angelov
bd3ccb4a0d now linearization is working 2022-09-12 12:11:56 +02:00
Krasimir Angelov
c71ed9f513 better error handling and an API for linearizations 2022-09-12 12:06:40 +02:00
Krasimir Angelov
f9ca462a06 turn abstractName into a property to better follow the Python API 2022-09-12 11:03:15 +02:00
Krasimir Angelov
7492cd52d1 extract the list of languages 2022-09-12 10:55:26 +02:00
Krasimir Angelov
6f6f742d01 Merge branch 'wasm' of github.com:GrammaticalFramework/gf-core into wasm 2022-09-01 13:28:49 +02:00
Krasimir Angelov
d477250c48 more high-level API & better memory management 2022-09-01 13:26:38 +02:00
John J. Camilleri
3a17a68da6 Update README.md 2022-08-31 16:42:41 +02:00
John J. Camilleri
6ea53e44a4 Update README.md 2022-08-31 16:41:59 +02:00
Krasimir Angelov
4ecd216796 DataView doesn't work use Uint8Array instead 2022-08-31 16:21:08 +02:00
Krasimir Angelov
0b01f56fd7 fix pgf_jit_predicate for emscripten 2022-08-31 16:19:48 +02:00
John J. Camilleri
0bac8f0dae Load and read PGF in test-web: doesn't fail but abstract name is empty 2022-08-01 14:47:28 +02:00
John J. Camilleri
8df9767493 Revert changes to top-level .gitignore 2022-08-01 14:16:30 +02:00
John J. Camilleri
3d272ac053 Move everything to javascript dir. Add jspgf API, test files for both Node and web. 2022-08-01 14:11:45 +02:00
John J. Camilleri
63828de0c2 Git-ignore WASM files 2022-08-01 11:56:39 +02:00
John J. Camilleri
72bec84f58 Add Dockerfile and script for building WASM files 2022-08-01 11:56:11 +02:00
John J. Camilleri
539b946c96 Clear out javascript and typescript folders 2022-08-01 09:59:44 +02:00
Krasimir Angelov
a42cec2107 support for BIND tokens in the Python bindings 2022-07-16 20:29:36 +02:00
Krasimir Angelov
4d446fcd3f Merge branch 'master' of github.com:GrammaticalFramework/gf-core 2022-07-04 10:42:59 +02:00
Krasimir Angelov
ae460e76b6 allow compilation with emscripten 2022-07-04 10:42:34 +02:00
John J. Camilleri
65308861bc Merge branch 'master' of github.com:GrammaticalFramework/gf-core 2022-06-18 21:09:23 +02:00
Krasimir Angelov
b7672b67a3 adjust the -view command depending on the OS 2022-05-31 10:15:50 +02:00
Krasimir Angelov
e33de168fd use a relative link to WordNet 2022-05-31 07:44:25 +02:00
Inari Listenmaa
fc5b3e9037 Merge pull request #141 from anka-213/hardcode-utf8
Always use UTF8 encoding in the gf executable
2022-05-18 09:46:03 +02:00
Andreas Källberg
9b9905c0b2 Always use UTF8 encoding in the gf executable
This fixes many of the "Invalid character" messages
you can get on different platforms.

This has helped both with a nix-installation that didn't have global
locale set and with a windows installation.
2022-05-18 14:42:01 +08:00
Inari Listenmaa
ec70e4a83e Merge pull request #136 from mengwong/ghc9
compiles with GHC 9.0.2
2022-05-06 03:26:00 +02:00
Inari Listenmaa
e6ade90679 update nightly to latest lts 2022-05-06 08:45:12 +08:00
Inari Listenmaa
6414bc8923 Merge pull request #140 from anka-213/no-profile-bind
Don't add automatic cost centres to Data.Binary.Get
2022-05-04 10:46:37 +02:00
Andreas Källberg
b0b2a06f3b Improve comment 2022-05-03 13:10:29 +08:00
Andreas Källberg
221597bd79 When profiling, don't add cost centres in Data.Binary.Get
This change speeds up profiling by an order of magnitude.
Without it, the >>= function for Get dominates runtime completely during profiling.
2022-05-03 13:08:35 +08:00
Inari Listenmaa
862aeb5d9b Update base <4.15 to <4.16 for tests + pgf*.cabal 2022-03-05 13:42:11 +08:00
Inari Listenmaa
25dd1354c7 Merge pull request #135 from mengwong/base-4-15
prepare for GHC 9, base 4.15, by using Buffer constructor interface
2022-03-05 06:28:17 +01:00
Inari Listenmaa
b762e24a82 Add ghc-9.0.2 to CI 2022-03-05 13:25:26 +08:00
Meng Weng Wong
20453193fe add compilation support for ghc 9.0.2 2022-03-05 13:15:40 +08:00
Meng Weng Wong
b53a102c98 if this PR is accepted we don't need these instructions 2022-03-05 12:59:25 +08:00
Meng Weng Wong
bc14a56f83 "now try this" instructions for people flailing with Apple Silicon M1 2022-03-05 12:59:25 +08:00
Meng Weng Wong
3a1213ab37 prepare for GHC 9, base 4.15, by using Buffer constructor interface 2022-03-05 12:59:25 +08:00
Inari Listenmaa
1b41e94f83 Merge pull request #138 from anka-213/patch-1
Fix stack ci
2022-03-05 05:49:43 +01:00
Andreas Källberg
308f4773dc Upgrade to ghc-8.10.7
This version has better support for m1 macbooks
2022-03-05 12:25:46 +08:00
Andreas Källberg
05fc093b5e Add restore key to cache 2022-03-05 12:25:46 +08:00
Andreas Källberg
4caf6d684e Another attempt at fixing linker errors 2022-03-05 12:25:46 +08:00
Andreas Källberg
bfd8f9c16d Upgrade haskell setup action 2022-03-05 12:24:38 +08:00
Andreas Källberg
aefac84670 Clear stack cache and make cache-key more fine-grained
Attempt at fixing #137
2022-03-05 12:24:10 +08:00
John J. Camilleri
9f2a3de7a3 Add simpler VSCode extension to editor modes page 2021-11-08 12:30:21 +01:00
krangelov
e4b2f281d9 Merge branch 'master' of github.com:GrammaticalFramework/gf-core 2021-09-22 14:11:27 +02:00
krangelov
063c517f3c more tests for variants 2021-09-22 14:11:11 +02:00
John J. Camilleri
bedb46527d Move Thomas from current to previous on maintainers page 2021-08-17 10:18:34 +02:00
John J. Camilleri
0258a87257 Add IRC, Discord, SO links to "contribute" section at top of homepage 2021-08-17 09:57:50 +02:00
John J. Camilleri
ef0e831c9e Update installation instructions from Hackage, source code 2021-08-17 09:38:20 +02:00
Inari Listenmaa
8ec13b1030 Uncomment installation instructions from Hackage 2021-08-16 09:07:59 +08:00
John J. Camilleri
058526ec5d Remove Travis CI workflow, we use GitHub actions now
Closes #123
2021-08-12 15:27:10 +02:00
John J. Camilleri
974e8b0835 Typos in homepage 2021-08-12 15:20:29 +02:00
John J. Camilleri
bbe4682c3d Update homepage
- Add Discord link
- Point to GitHub issues, Stack Overflow in "Getting help"
- Remove old news
2021-08-12 15:19:17 +02:00
John J. Camilleri
e477ce4b1f HTML fix on homepage 2021-08-12 10:05:45 +02:00
John J. Camilleri
7a63ba34b4 Add changelog
This will hopefully help us keep track of changes for the next release
2021-08-12 09:56:34 +02:00
John J. Camilleri
723bec1ba0 Changes made in order to get Hackage upload working 2021-08-09 13:41:25 +02:00
krangelov
265f08d6ee added link to vis-network.min.js 2021-07-26 16:57:05 +02:00
krangelov
e47042424e Merge branch 'master' of https://github.com/GrammaticalFramework/gf-core 2021-07-26 16:52:11 +02:00
krangelov
ecf309a28e fix links to WordNet 2021-07-26 16:51:58 +02:00
Inari Listenmaa
d0a881f903 add VS code on the list of editor modes 2021-07-26 14:11:48 +08:00
Inari Listenmaa
810640822d Update documentation for release 3.11 2021-07-25 15:37:12 +08:00
Inari Listenmaa
ed79955931 Merge pull request #129 from anka-213/automate-release
Automatically upload release assets after building for release
2021-07-25 08:20:41 +02:00
Andreas Källberg
1867bfc8a1 Rename packages based on git tag 2021-07-25 11:08:21 +08:00
Andreas Källberg
6ef4f27d32 Upload release assets automatically as well 2021-07-25 10:43:36 +08:00
Inari Listenmaa
3ab07ec58f Update debian changelog for GF 3.11 2021-07-25 10:30:49 +08:00
Inari Listenmaa
b8324fe3e6 Merge pull request #116 from anka-213/fix-binary-package-build
Update scripts to use `cabal v1-...` so they work on newer cabal
2021-07-25 04:15:07 +02:00
Andreas Källberg
8814fde817 Only run the script once per release 2021-07-25 09:30:36 +08:00
Andreas Källberg
375b3cf285 Update release script to build for two ubuntu versions 2021-07-25 08:23:25 +08:00
Andreas Källberg
3c4f42db15 Build ubuntu packages on ubuntu-latest
Fixes #74
2021-07-25 08:23:25 +08:00
John J. Camilleri
0474a37af6 Make Makefile compatible with stack and old/new cabal (with v1- prefix when necessary) 2021-07-25 08:23:25 +08:00
Andreas Källberg
e3498d5ead Update to newest haskell github action
Also fix so the stack builds use the correct ghc versions
2021-07-25 08:23:25 +08:00
Andreas Källberg
4c5927c98c Update scripts to use cabal v1-... so they work on newer cabal
Fixes build failures like https://github.com/GrammaticalFramework/gf-core/runs/2949099280?check_suite_focus=true
2021-07-25 08:23:25 +08:00
John J. Camilleri
bb51224e8e IRC link pre-fills channel. Link to logs gives newest first. 2021-07-23 16:07:34 +02:00
John J. Camilleri
9533edc3ca Merge pull request #128 from GrammaticalFramework/windows-binary
Fixes to building Windows binary
2021-07-23 15:55:37 +02:00
John J. Camilleri
4df8999ed5 Change Python 3.8 to 3.9 2021-07-23 08:05:35 +02:00
John J. Camilleri
7fdbf3f400 Update path in main workflow for binaries 2021-07-22 23:11:01 +02:00
John J. Camilleri
0d6c67f6b1 Try without rewriting envvar 2021-07-22 23:02:22 +02:00
John J. Camilleri
2610219f6a Update path 2021-07-22 22:56:39 +02:00
John J. Camilleri
7674f078d6 Try another path 2021-07-22 22:49:44 +02:00
John J. Camilleri
c67fe05c08 Narrow search, print env var 2021-07-22 22:44:53 +02:00
John J. Camilleri
7b9bb780a2 Find Java stuff 2021-07-22 22:34:26 +02:00
John J. Camilleri
4f256447e2 Add separate Windows binary CI action for easier testing 2021-07-22 22:27:15 +02:00
Inari Listenmaa
dfa5b9276d #gf IRC channel has moved to Libera 2021-07-22 01:08:00 +02:00
Inari Listenmaa
667bfd30bd Merge pull request #87 from anka-213/make-it-fast
Remove the `Either Int` from value2term
2021-07-20 04:35:37 +02:00
Inari Listenmaa
66ae31e99e Merge pull request #126 from inariksit/developers-documentation
Update developers' documentation
2021-07-15 05:16:55 +02:00
Inari Listenmaa
a677f0373c General restructuring, various minor changes 2021-07-15 10:40:26 +08:00
Inari Listenmaa
13f845d127 Update C runtime instructions 2021-07-15 10:39:54 +08:00
Inari Listenmaa
aa530233fb Remove instructions to create binaries
Those are in github actions
2021-07-15 10:27:57 +08:00
Inari Listenmaa
45bc5595c0 Update C runtime install instructions 2021-07-15 09:54:15 +08:00
Inari Listenmaa
6d12754e4f Split the Cabal instructions to another page
and link from main instructions
2021-07-15 08:21:29 +08:00
1Regina
a09d9bd006 install and upgrade stack 2021-07-14 17:20:20 +08:00
Meowyam
fffe3161d4 updated docs to reflect binaries generated via github actions
fix merge conflicts

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

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

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

View File

@@ -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: |

View File

@@ -2,7 +2,8 @@ name: Build Binary Packages
on: on:
workflow_dispatch: workflow_dispatch:
release: release:
types: ["created"]
jobs: jobs:
@@ -10,11 +11,13 @@ jobs:
ubuntu: ubuntu:
name: Build Ubuntu package name: Build Ubuntu package
runs-on: ubuntu-18.04 strategy:
# strategy: matrix:
# matrix: os:
# ghc: ["8.6.5"] - ubuntu-18.04
# cabal: ["2.4"] - ubuntu-20.04
runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -53,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

View File

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

11
CHANGELOG.md Normal file
View File

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

View File

@@ -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

View File

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

View File

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

6
debian/changelog vendored
View File

@@ -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
View File

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

View File

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

View File

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

View File

@@ -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

View File

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

View File

@@ -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).

View File

@@ -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>

View File

@@ -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.

187
gf.cabal
View File

@@ -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
@@ -273,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:
@@ -295,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
@@ -304,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
@@ -322,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
@@ -332,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

View File

@@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.2/css/all.css" integrity="sha384-/rXc/GQVaYpyDdyxK+ecHPVYJSN9bmVFBvjA/9eOB+pb3F2w2N6fc5qB9Ew5yIns" crossorigin="anonymous"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" crossorigin="anonymous">
<link rel="alternate" href="https://github.com/GrammaticalFramework/gf-core/" title="GF GitHub repository"> <link rel="alternate" href="https://github.com/GrammaticalFramework/gf-core/" title="GF GitHub repository">
</head> </head>
@@ -85,10 +85,27 @@
<div class="col-sm-6 col-md-3 mb-4"> <div class="col-sm-6 col-md-3 mb-4">
<h3>Contribute</h3> <h3>Contribute</h3>
<ul class="mb-2"> <ul class="mb-2">
<li><a href="http://groups.google.com/group/gf-dev">Mailing List</a></li> <li>
<a href="https://web.libera.chat/?channels=#gf">
<i class="fas fa-hashtag"></i>
IRC
</a>
/
<a href="https://discord.gg/EvfUsjzmaz">
<i class="fab fa-discord"></i>
Discord
</a>
</li>
<li>
<a href="https://stackoverflow.com/questions/tagged/gf">
<i class="fab fa-stack-overflow"></i>
Stack Overflow
</a>
</li>
<li><a href="https://groups.google.com/group/gf-dev">Mailing List</a></li>
<li><a href="https://github.com/GrammaticalFramework/gf-core/issues">Issue Tracker</a></li> <li><a href="https://github.com/GrammaticalFramework/gf-core/issues">Issue Tracker</a></li>
<li><a href="doc/gf-people.html">Authors</a></li>
<li><a href="//school.grammaticalframework.org/2020/">Summer School</a></li> <li><a href="//school.grammaticalframework.org/2020/">Summer School</a></li>
<li><a href="doc/gf-people.html">Authors</a></li>
</ul> </ul>
<a href="https://github.com/GrammaticalFramework/" class="btn btn-primary ml-3"> <a href="https://github.com/GrammaticalFramework/" class="btn btn-primary ml-3">
<i class="fab fa-github mr-1"></i> <i class="fab fa-github mr-1"></i>
@@ -154,7 +171,7 @@ least one, it may help you to get a first idea of what GF is.
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<h2>Applications & Availability</h2> <h2>Applications & availability</h2>
<p> <p>
GF can be used for building GF can be used for building
<a href="//cloud.grammaticalframework.org/translator/">translation systems</a>, <a href="//cloud.grammaticalframework.org/translator/">translation systems</a>,
@@ -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 &ndash; 8 August 2021. <a href="//school.grammaticalframework.org/2020/">Seventh GF Summer School</a>, in Singapore and online, 26 July &ndash; 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), 314 December 2018
</dd>
<dt class="col-sm-3 text-center text-nowrap">2018-12-02</dt>
<dd class="col-sm-9">
<strong>GF 3.10 released.</strong>
<a href="download/release-3.10.html">Release notes</a>
</dd>
<dt class="col-sm-3 text-center text-nowrap">2018-07-25</dt>
<dd class="col-sm-9">
The GF repository has been split in two:
<a href="https://github.com/GrammaticalFramework/gf-core">gf-core</a> and
<a href="https://github.com/GrammaticalFramework/gf-rgl">gf-rgl</a>.
The original <a href="https://github.com/GrammaticalFramework/GF">GF</a> repository is now archived.
</dd>
<dt class="col-sm-3 text-center text-nowrap">2017-08-11</dt>
<dd class="col-sm-9">
<strong>GF 3.9 released.</strong>
<a href="download/release-3.9.html">Release notes</a>
</dd>
<dt class="col-sm-3 text-center text-nowrap">2017-06-29</dt>
<dd class="col-sm-9">
GF is moving to <a href="https://github.com/GrammaticalFramework/GF/">GitHub</a>.</dd>
<dt class="col-sm-3 text-center text-nowrap">2017-03-13</dt>
<dd class="col-sm-9">
<a href="//school.grammaticalframework.org/2017/">GF Summer School</a> in Riga (Latvia), 14-25 August 2017
</dd>
</dl> </dl>
<h2>Projects</h2> <h2>Projects</h2>
@@ -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),

View File

@@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,18 +16,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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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)
{ {

View File

@@ -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
View File

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

View File

@@ -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

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
----------------------------------------------------------------------------- -----------------------------------------------------------------------------

View File

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

View File

@@ -1,29 +1,32 @@
name: pgf name: pgf
version: 3.10.1-git version: 3.11.0-git
cabal-version: >= 1.20 cabal-version: 1.22
build-type: Simple build-type: Simple
license: OtherLicense license: OtherLicense
category: Natural Language Processing category: Natural Language Processing
synopsis: Grammatical Framework synopsis: Grammatical Framework
description: A library for interpreting the Portable Grammar Format (PGF) description: A library for interpreting the Portable Grammar Format (PGF)
homepage: http://www.grammaticalframework.org/ homepage: https://www.grammaticalframework.org/
bug-reports: https://github.com/GrammaticalFramework/gf-core/issues bug-reports: https://github.com/GrammaticalFramework/gf-core/issues
tested-with: GHC==7.6.3, GHC==7.8.3, GHC==7.10.3, GHC==8.0.2, GHC==8.4.4 tested-with: GHC==7.10.3, GHC==8.0.2, GHC==8.10.4
library library
default-language: Haskell2010 default-language: Haskell2010
build-depends: build-depends:
array, array >= 0.5.1 && < 0.6,
base >= 4.6 && <5, base >= 4.9.1 && < 4.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

View File

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

View File

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

View File

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

1
src/runtime/javascript/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.libs/

View File

@@ -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>.

View 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\
"

View 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

View 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/"

View File

@@ -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 ;
}

View File

@@ -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)) ;
}

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,543 @@
/**
* This module is the high-level JavaScript wrapper around the WASM-compiled version.
*/
async function mkAPI() {
const sizeof_GuMapItor = 4;
const offsetof_GuMapItor_fn = 0;
var asm = null;
var wasmTable = null;
var freeTableIndexes = [];
function setErrNo(value) {
HEAP32[asm.__errno_location() >> 2] = value;
return value;
}
function abortOnCannotGrowMemory(requestedSize) {
abort('Cannot enlarge memory arrays to size ' + requestedSize + ' bytes (OOM). Either (1) compile with -s INITIAL_MEMORY=X with X higher than the current value ' + HEAP8.length + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ');
}
function _emscripten_resize_heap(requestedSize) {
var oldSize = HEAPU8.length;
requestedSize = requestedSize >>> 0;
abortOnCannotGrowMemory(requestedSize);
}
var tempRet0 = 0;
var urlData = {};
var fdData = {};
var fdMax = 0;
var asmLibraryArg = {
"__syscall_fcntl64":
function (fd, cmd, varargs) {
setErrNo(134);
return -1;
},
"__syscall_ioctl":
function (fd, op, varargs) {
setErrNo(134);
return -1;
},
"__syscall_open":
function (pathPtr, flags, varargs) {
const path = UTF8ToString(pathPtr);
const data = urlData[path];
if (data == null) {
setErrNo(129);
return -1;
}
fdMax++;
fdData[fdMax] = {data: data, pos: 0};
delete urlData[path];
return fdMax;
},
"_munmap_js":
function (addr, len, prot, flags, fd, offset) {
setErrNo(134);
return -1;
},
"abort":
function () {
console.log('native code called abort()');
},
"emscripten_memcpy_big":
function (dest, src, num) {
HEAPU8.copyWithin(dest, src, src + num);
},
"emscripten_resize_heap":
function _emscripten_resize_heap(requestedSize) {
var oldSize = HEAPU8.length;
requestedSize = requestedSize >>> 0;
abortOnCannotGrowMemory(requestedSize);
},
"fd_close":
function (fd) {
delete fdData[fd];
return 0;
},
"fd_read":
function (fd, iov, iovcnt, pnum) {
const info = fdData[fd];
if (info == null) {
setErrNo(121);
return -1;
}
let num = 0;
for (let i = 0; i < iovcnt; i++) {
const ptr = HEAP32[(((iov)+(i*8))>>2)];
const len = HEAP32[(((iov)+(i*8 + 4))>>2)];
let cnt = 0;
while (cnt < len && info.pos < info.data.length) {
HEAP8[ptr+cnt] = info.data[info.pos];
info.pos++
cnt++;
}
num += cnt;
if (cnt < len) break; // nothing more to read
}
HEAP32[((pnum)>>2)] = num;
return 0;
},
"fd_seek":
function (fd, offset_low, offset_high, whence, newOffset) {
setErrNo(134);
return -1;
},
"fd_write":
function _fd_write(fd, iov, iovcnt, pnum) {
setErrNo(134);
return -1;
},
"setTempRet0":
function (value) {
tempRet0 = value;
},
"__assert_fail":
function (condition, filename, line, func) {
abort('Assertion failed: ' + UTF8ToString(condition) + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);
}
};
// Wraps a JS function as a wasm function with a given signature.
function convertJsFunctionToWasm(func, sig) {
// If the type reflection proposal is available, use the new
// "WebAssembly.Function" constructor.
// Otherwise, construct a minimal wasm module importing the JS function and
// re-exporting it.
if (typeof WebAssembly.Function == "function") {
var typeNames = {
'i': 'i32',
'j': 'i64',
'f': 'f32',
'd': 'f64'
};
var type = {
parameters: [],
results: sig[0] == 'v' ? [] : [typeNames[sig[0]]]
};
for (var i = 1; i < sig.length; ++i) {
type.parameters.push(typeNames[sig[i]]);
}
return new WebAssembly.Function(type, func);
}
// The module is static, with the exception of the type section, which is
// generated based on the signature passed in.
var typeSection = [
0x01, // id: section,
0x00, // length: 0 (placeholder)
0x01, // count: 1
0x60, // form: func
];
var sigRet = sig.slice(0, 1);
var sigParam = sig.slice(1);
var typeCodes = {
'i': 0x7f, // i32
'j': 0x7e, // i64
'f': 0x7d, // f32
'd': 0x7c, // f64
};
// Parameters, length + signatures
typeSection.push(sigParam.length);
for (var i = 0; i < sigParam.length; ++i) {
typeSection.push(typeCodes[sigParam[i]]);
}
// Return values, length + signatures
// With no multi-return in MVP, either 0 (void) or 1 (anything else)
if (sigRet == 'v') {
typeSection.push(0x00);
} else {
typeSection = typeSection.concat([0x01, typeCodes[sigRet]]);
}
// Write the overall length of the type section back into the section header
// (excepting the 2 bytes for the section id and length)
typeSection[1] = typeSection.length - 2;
// Rest of the module is static
var bytes = new Uint8Array([
0x00, 0x61, 0x73, 0x6d, // magic ("\0asm")
0x01, 0x00, 0x00, 0x00, // version: 1
].concat(typeSection, [
0x02, 0x07, // import section
// (import "e" "f" (func 0 (type 0)))
0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00,
0x07, 0x05, // export section
// (export "f" (func 0 (type 0)))
0x01, 0x01, 0x66, 0x00, 0x00,
]));
// We can compile this wasm module synchronously because it is very small.
// This accepts an import (at "e.f"), that it reroutes to an export (at "f")
var module = new WebAssembly.Module(bytes);
var instance = new WebAssembly.Instance(module, {
'e': {'f': func}
});
var wrappedFunc = instance.exports['f'];
return wrappedFunc;
}
function addFunction(func, sig) {
func = convertJsFunctionToWasm(func, sig);
let index;
// Reuse a free index if there is one, otherwise grow.
if (freeTableIndexes.length) {
index = freeTableIndexes.pop();
} else {
// Grow the table
try {
wasmTable.grow(1);
} catch (err) {
if (!(err instanceof RangeError)) {
throw err;
}
throw 'Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.';
}
index = wasmTable.length - 1;
}
wasmTable.set(index, func);
return index;
}
function removeFunction(index) {
freeTableIndexes.push(index);
}
const response = await fetch("pgf.wasm", { credentials: 'same-origin' });
const info = {
'env': asmLibraryArg,
'wasi_snapshot_preview1': asmLibraryArg,
};
// Suppress closure warning here since the upstream definition for
// instantiateStreaming only allows Promise<Repsponse> rather than
// an actual Response.
// TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed.
/** @suppress {checkTypes} */
const result = await WebAssembly.instantiateStreaming(response, info);
asm = result["instance"].exports;
wasmTable = asm['__indirect_function_table'];
const buf = asm['memory'].buffer;
const HEAP8 = new Int8Array(buf);
const HEAP16 = new Int16Array(buf);
const HEAP32 = new Int32Array(buf);
const HEAPU8 = new Uint8Array(buf);
const HEAPU16 = new Uint16Array(buf);
const HEAPU32 = new Uint32Array(buf);
const HEAPF32 = new Float32Array(buf);
const HEAPF64 = new Float64Array(buf);
// Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte.
function lengthBytesUTF8(str) {
var len = 0;
for (var i = 0; i < str.length; ++i) {
// Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8.
// See http://unicode.org/faq/utf_bom.html#utf16-3
var u = str.charCodeAt(i); // possibly a lead surrogate
if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
if (u <= 0x7F) ++len;
else if (u <= 0x7FF) len += 2;
else if (u <= 0xFFFF) len += 3;
else len += 4;
}
return len;
}
function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes.
return 0;
var startIdx = outIdx;
var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator.
for (var i = 0; i < str.length; ++i) {
// Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8.
// See http://unicode.org/faq/utf_bom.html#utf16-3
// For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629
var u = str.charCodeAt(i); // possibly a lead surrogate
if (u >= 0xD800 && u <= 0xDFFF) {
var u1 = str.charCodeAt(++i);
u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF);
}
if (u <= 0x7F) {
if (outIdx >= endIdx) break;
heap[outIdx++] = u;
} else if (u <= 0x7FF) {
if (outIdx + 1 >= endIdx) break;
heap[outIdx++] = 0xC0 | (u >> 6);
heap[outIdx++] = 0x80 | (u & 63);
} else if (u <= 0xFFFF) {
if (outIdx + 2 >= endIdx) break;
heap[outIdx++] = 0xE0 | (u >> 12);
heap[outIdx++] = 0x80 | ((u >> 6) & 63);
heap[outIdx++] = 0x80 | (u & 63);
} else {
if (outIdx + 3 >= endIdx) break;
if (u > 0x10FFFF) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).');
heap[outIdx++] = 0xF0 | (u >> 18);
heap[outIdx++] = 0x80 | ((u >> 12) & 63);
heap[outIdx++] = 0x80 | ((u >> 6) & 63);
heap[outIdx++] = 0x80 | (u & 63);
}
}
// Null-terminate the pointer to the buffer.
heap[outIdx] = 0;
return outIdx - startIdx;
}
function allocateUTF8(pool,str) {
var size = lengthBytesUTF8(str) + 1;
var ptr = asm.gu_malloc(pool,size);
if (ptr) stringToUTF8Array(str, HEAP8, ptr, size);
return ptr;
}
const UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined;
/**
* @param {number} idx
* @param {number=} maxBytesToRead
* @return {string}
*/
function UTF8ArrayToString(heap, idx, maxBytesToRead) {
var endIdx = idx + maxBytesToRead;
var endPtr = idx;
// TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
// Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
// (As a tiny code save trick, compare endPtr against endIdx using a negation, so that undefined means Infinity)
while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr;
if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) {
return UTF8Decoder.decode(heap.subarray(idx, endPtr));
} else {
var str = '';
// If building with TextDecoder, we have already computed the string length above, so test loop end condition against that
while (idx < endPtr) {
// For UTF8 byte structure, see:
// http://en.wikipedia.org/wiki/UTF-8#Description
// https://www.ietf.org/rfc/rfc2279.txt
// https://tools.ietf.org/html/rfc3629
var u0 = heap[idx++];
if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
var u1 = heap[idx++] & 63;
if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
var u2 = heap[idx++] & 63;
if ((u0 & 0xF0) == 0xE0) {
u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
} else {
if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heap[idx++] & 63);
}
if (u0 < 0x10000) {
str += String.fromCharCode(u0);
} else {
var ch = u0 - 0x10000;
str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
}
}
}
return str;
}
function UTF8ToString(ptr, maxBytesToRead) {
return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
}
const GuErrnoStrPtr = asm.malloc(8);
stringToUTF8Array("GuErrno", HEAP8, GuErrnoStrPtr, 8);
const PgfExnStrPtr = asm.malloc(8);
stringToUTF8Array("PgfExn", HEAP8, PgfExnStrPtr, 8);
function pgfError(err) {
if (asm.gu_exn_caught_(err, GuErrnoStrPtr)) {
errDataPtr = asm.gu_exn_caught_data(err);
return new Error("errno="+HEAP32[errDataPtr >> 2]);
} else if (asm.gu_exn_caught_(err, PgfExnStrPtr)) {
msgPtr = asm.gu_exn_caught_data(err);
return new Error(UTF8ToString(msgPtr));
}
return new Error();
}
const registry = new FinalizationRegistry((pool) => {
asm.gu_pool_free(pool);
});
function PGF(pgfPtr,name,pool) {
this.pgfPtr = pgfPtr;
this.abstractName = name;
this.pool = pool;
this.languages = {};
registry.register(this,pool);
}
function Concr(pgf,concrPtr,name) {
this.pgf = pgf;
this.name = name;
this.concrPtr = concrPtr;
}
Concr.prototype.linearize = function(expr) {
const tmp_pool = asm.gu_new_pool();
const err = asm.gu_new_exn(tmp_pool);
const sb = asm.gu_new_string_buf(tmp_pool);
const out = asm.gu_string_buf_out(sb);
asm.pgf_linearize(this.concrPtr, expr.exprPtr, out, err);
if (asm.gu_exn_is_raised(err)) {
const e = pgfError(err);
asm.gu_pool_free(tmp_pool);
throw e;
}
const strPtr = asm.gu_string_buf_data(sb);
const len = asm.gu_string_buf_length(sb);
const str = UTF8ToString(strPtr,len);
asm.gu_pool_free(tmp_pool);
return str
}
async function readPGF(pgfURL) {
const response = await fetch(pgfURL);
urlData[pgfURL] = new Int8Array(await response.arrayBuffer());
const pool = asm.gu_new_pool();
const tmp_pool = asm.gu_new_pool();
const err = asm.gu_new_exn(tmp_pool);
const strPtr = allocateUTF8(tmp_pool,pgfURL);
const pgfPtr = asm.pgf_read(strPtr,pool,err);
if (asm.gu_exn_is_raised(err)) {
const e = pgfError(err);
asm.gu_pool_free(tmp_pool);
throw e;
}
const namePtr = asm.pgf_abstract_name(pgfPtr);
const abstractName = UTF8ToString(namePtr);
const pgf = new PGF(pgfPtr,abstractName,pool);
const itor = asm.gu_malloc(tmp_pool,sizeof_GuMapItor);
const fn =
addFunction(
(itor,namePtr,concrPtrPtr,err) => {
const name = UTF8ToString(namePtr);
const concrPtr = HEAP32[concrPtrPtr >> 2];
pgf.languages[name] = new Concr(pgf,concrPtr,name);
},
"viiii"
);
HEAP32[(itor+offsetof_GuMapItor_fn) >> 2] = fn;
asm.pgf_iter_languages(pgfPtr,itor,err);
removeFunction(fn);
asm.gu_pool_free(tmp_pool);
return pgf;
}
function Expr(exprPtr,pool) {
this.exprPtr = exprPtr;
this.pool = pool;
registry.register(this,pool);
}
Expr.prototype.toString = function() {
const tmp_pool = asm.gu_new_pool();
const sb = asm.gu_new_string_buf(tmp_pool);
const out = asm.gu_string_buf_out(sb);
const err = asm.gu_new_exn(tmp_pool);
asm.pgf_print_expr(this.exprPtr, 0, 0, out, err);
if (asm.gu_exn_is_raised(err)) {
const e = pgfError(err);
asm.gu_pool_free(tmp_pool);
throw e;
}
const strPtr = asm.gu_string_buf_data(sb);
const len = asm.gu_string_buf_length(sb);
const str = UTF8ToString(strPtr,len);
asm.gu_pool_free(tmp_pool);
return str;
};
Expr.prototype.arity = function(expr) {
return asm.pgf_expr_arity(this.expr);
}
function readExpr(exprStr) {
const tmp_pool = asm.gu_new_pool();
const strPtr = allocateUTF8(tmp_pool,exprStr);
const in_ = asm.gu_data_in(strPtr, exprStr.length, tmp_pool);
const err = asm.gu_new_exn(tmp_pool);
const pool = asm.gu_new_pool();
const expr = asm.pgf_read_expr(in_, pool, tmp_pool, err);
asm.gu_pool_free(tmp_pool);
if (asm.gu_exn_is_raised(err)) {
throw pgfError(err);
}
if (expr == 0) {
throw new Error('Expression cannot be parsed');
}
return new Expr(expr,pool);
}
return { readPGF, readExpr };
}
// This allows us to use both from Node and in browser
if (typeof module != 'undefined') {
module.exports = mkAPI;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 B

View File

@@ -1,252 +0,0 @@
body {
font-family:arial,helvetica,sans-serif;
font-size:12px;
background-color: white;
}
#wrapper {
width:740px;
height:520px;
margin:auto 50px;
border:1px solid gray;
padding:10px;
}
#absFrame {
width:250px;
height:250px;
padding:10px;
border:1px solid gray;
float:left;
white-space: nowrap;
}
#conFrame {
width:436px;
height:250px;
margin-left:10px;
padding:10px;
border:1px solid gray;
float:left;
white-space: normal;
overflow:auto;
}
#actFrame {
width:250px;
height:170px;
margin-top:10px;
padding:10px;
border:1px solid gray;
float:left;
overflow:auto;
}
#refFrame {
width:436px;
height:170px;
margin-left:10px;
margin-top:10px;
padding:10px;
border:1px solid gray;
float:left;
overflow:auto;
}
#messageFrame {
width:506px;
height:15px;
margin-top:10px;
margin-right:10px;
padding:10px;
border:1px solid gray;
float:left;
overflow:hidden;
}
#clipboardFrame {
width:180px;
height:15px;
margin-top:10px;
padding:10px;
border:1px solid gray;
float:left;
overflow:auto;
}
#tree {
left: -10px;
top: -10px;
margin: 0px;
padding: 10px;
overflow: auto;
}
ul {
position: relative;
list-style: none;
margin-left: 20px;
padding: 0px;
}
li {
position: relative;
}
img.tree-menu {
margin-right: 5px;
}
a.tree:link, a.tree:visited, a.tree:active {
color: black;
background-color: white;
text-decoration: none;
margin-right:10px;
}
a.tree:hover {
color: blue;
background-color: white;
text-decoration: underline;
margin-right:10px;
}
a.treeSelected:link, a.treeSelected:visited, a.treeSelected:active {
color: white;
background-color: #3366CC;
text-decoration: none;
margin-right:10px;
}
a.treeSelected:hover {
color: white;
background-color: #3366CC;
text-decoration: underline;
margin-right:10px;
}
a.treeGray:link, a.treeGray:visited, a.treeGray:active {
color: silver;
background-color: white;
text-decoration: none;
margin-right:10px;
}
a.treeGray:hover {
color: silver;
background-color: white;
text-decoration: none;
margin-right:10px;
}
table.action, table.refinement, table.wrapper, table.tree, table.language {
margin: 0px;
padding: 0px;
border-style: none;
border-collapse: collapse;
border-spacing: 0px;
}
tr.selected {
color: white;
background-color: #3366CC;
}
tr.unavailable, tr.closed {
color: silver;
background-color: white;
}
tr.unavailable:hover {
color: silver;
background-color: #3366CC;
}
tr.action, tr.refinement, tr.wrapper, tr.tree {
color: black;
background-color: white;
}
tr.action:hover, tr.refinement:hover, tr.wrapper:hover, tr.tree:hover {
color: white;
background-color: #3366CC;
}
td.action {
width: 220px;
margin: 0px;
padding: 0px;
}
td.refinement, td.wrapper, td.tree {
width: 515px;
margin: 0px;
padding: 0px;
}
td.hotKey {
width: 30px;
margin: 0px;
padding: 0px;
text-align: right;
}
td.language {
color: black;
background-color: white;
margin: 1px;
padding: 1px;
}
td.language:hover {
color: blue;
background-color: white;
text-decoration: underline;
margin: 1px;
padding: 1px;
}
td.selected {
color: white;
background-color: #3366CC;
margin: 1px;
padding: 1px;
}
td.selected:hover {
color: white;
background-color: #3366CC;
text-decoration: underline;
margin: 1px;
padding: 1px;
}
p {
margin-bottom: 40px;
}
span.normal {
color: black;
background-color: white;
text-decoration: none;
padding-left: 2px;
padding-right: 2px;
}
span.edit {
color: black;
background-color: white;
text-decoration: none;
border:2px inset;
padding-left: 2px;
padding-right: 2px;
}
span.selected {
color: white;
background-color: #3366CC;
text-decoration: none;
padding-left: 2px;
padding-right: 2px;
}

View File

@@ -0,0 +1,33 @@
const Module = require('./.libs/pgf.js');
const JSPGF = require('./jspgf.js')(Module);
const fs = require('fs');
const path = require('path');
Module.onRuntimeInitialized = () => {
// Read PGF path from args
if (process.argv.length > 2) {
const pgfPathHost = process.argv[2];
// Copy file into filesystem
const pgfPathFS = '/tmp/' + path.basename(pgfPathHost);
const rawPgf = fs.readFileSync(pgfPathHost);
Module.FS.writeFile(pgfPathFS, rawPgf);
// Read PGF
const pgf = JSPGF.readPGF(pgfPathFS);
// Print its name
console.log(JSPGF.abstractName(pgf));
}
// Parse expression
const expr = JSPGF.readExpr("Pred (Another (x f))");
// Show it
console.log(JSPGF.showExpr(expr));
// Print its arity
console.log('arity', JSPGF.arity(expr));
}

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<script type="text/javascript" src="./jspgf.js"></script>
<script type="text/javascript" src="./test-web.js"></script>
</body>
</html>

View File

@@ -0,0 +1,21 @@
mkAPI().then((pgf) => {
// Parse expression
const expr = pgf.readExpr("Pred (This Fish) Fresh");
// Show it
console.log(expr.toString());
// Print its arity
console.log('arity', expr.arity());
pgf.readPGF("Foods.pgf").then((gr) => {
// Print the grammar name
console.log(gr.abstractName);
// Access a language and print the concrete name
console.log(gr.languages["FoodsEng"].name);
// Linearize an expression
console.log(gr.languages["FoodsEng"].linearize(expr));
});
});

View File

@@ -1,54 +0,0 @@
body {
color: black;
background-color: white;
}
dl {
}
dt {
margin: 0;
padding: 0;
}
dl dd {
margin: 0;
padding: 0;
}
dl.fromLang dt {
display: none;
}
dl.toLang {
border-width: 1px 0 0 0;
border-style: solid;
border-color: #c0c0c0;
}
dl.toLang dt {
color: #c0c0c0;
display: block;
float: left;
width: 5em;
}
dl.toLang dd {
border-width: 0 0 1px 0;
border-style: solid;
border-color: #c0c0c0;
}
ul {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
margin: 0;
padding: 0;
}

View File

@@ -1,48 +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="translator.css" />
<script type="text/javascript" src="gflib.js"></script>
<script type="text/javascript" src="grammar.js"></script>
<script type="text/javascript" src="translator.js"></script>
<script type="text/javascript">
/* CHANGE ME */
var grammar = Foods;
function updateTranslation () {
var input = document.getElementById('inputText').value;
var fromLang = document.getElementById('fromLang').value;
var toLang = document.getElementById('toLang').value;
var output = document.getElementById('output');
var translation = grammar.translate(input, fromLang, toLang);
removeChildren(output);
output.appendChild(formatTranslation(translation));
}
function populateLangs () {
var f = document.getElementById('fromLang');
var t = document.getElementById('toLang');
for (var c in grammar.concretes) {
addOption(f, c, c);
addOption(t, c, c);
}
}
</script>
<title>Web-based GF Translator</title>
</head>
<body onload="populateLangs(grammar, 'fromLang', 'toLang')">
<form id="translate">
<p>
<input type="text" name="inputText" id="inputText" value="this cheese is warm" size="50" />
</p>
<p>
From: <select name="fromLang" id="fromLang" onchange=""><option value="">Any language</option></select>
To: <select name="toLang" id="toLang"><option value="">All languages</option></select>
<input type="button" value="Translate" onclick="updateTranslation()" />
</p>
</form>
<div id="output"></div>
</body>
</html>

View File

@@ -1,51 +0,0 @@
function formatTranslation (outputs) {
var dl1 = document.createElement("dl");
dl1.className = "fromLang";
for (var fromLang in outputs) {
var ul = document.createElement("ul");
addDefinition(dl1, document.createTextNode(fromLang), ul);
for (var i in outputs[fromLang]) {
var dl2 = document.createElement("dl");
dl2.className = "toLang";
for (var toLang in outputs[fromLang][i]) {
addDefinition(dl2, document.createTextNode(toLang), document.createTextNode(outputs[fromLang][i][toLang]));
}
addItem(ul, dl2);
}
}
return dl1;
}
/* DOM utilities for specific tags */
function addDefinition (dl, t, d) {
var dt = document.createElement("dt");
dt.appendChild(t);
dl.appendChild(dt);
var dd = document.createElement("dd");
dd.appendChild(d);
dl.appendChild(dd);
}
function addItem (ul, i) {
var li = document.createElement("li");
li.appendChild(i);
ul.appendChild(li);
}
function addOption (select, value, content) {
var option = document.createElement("option");
option.value = value;
option.appendChild(document.createTextNode(content));
select.appendChild(option);
}
/* General DOM utilities */
/* Removes all the children of a node */
function removeChildren(node) {
while (node.hasChildNodes()) {
node.removeChild(node.firstChild);
}
}

Some files were not shown because too many files have changed in this diff Show More