diff --git a/src/compiler/GF/Compile/PGFtoHaskell.hs b/src/compiler/GF/Compile/PGFtoHaskell.hs index fc17e4e4e..6356c9f6d 100644 --- a/src/compiler/GF/Compile/PGFtoHaskell.hs +++ b/src/compiler/GF/Compile/PGFtoHaskell.hs @@ -26,50 +26,58 @@ import Data.List --(isPrefixOf, find, intersperse) import qualified Data.Map as Map type Prefix = String -> String +type DerivingClause = String -- | the main function grammar2haskell :: Options -> String -- ^ Module name. -> PGF -> String -grammar2haskell opts name gr = foldr (++++) [] $ - pragmas ++ haskPreamble gadt name ++ [types, gfinstances gId lexical gr'] ++ compos +grammar2haskell opts name gr = foldr (++++) [] $ + pragmas ++ haskPreamble gadt name derivingClause extraImports ++ + [types, gfinstances gId lexical gr'] ++ compos where gr' = hSkeleton gr gadt = haskellOption opts HaskellGADT + dataExt = haskellOption opts HaskellData lexical cat = haskellOption opts HaskellLexical && isLexicalCat opts cat - gId | haskellOption opts HaskellNoPrefix = id - | otherwise = ("G"++) - pragmas | gadt = ["{-# OPTIONS_GHC -fglasgow-exts #-}","{-# LANGUAGE GADTs #-}"] + gId | haskellOption opts HaskellNoPrefix = rmForbiddenChars + | otherwise = ("G"++) . rmForbiddenChars + -- GF grammars allow weird identifier names inside '', e.g. 'VP/Object' + rmForbiddenChars = filter (`notElem` "'!#$%&*+./<=>?@\\^|-~") + pragmas | gadt = ["{-# LANGUAGE GADTs, FlexibleInstances, KindSignatures, RankNTypes, TypeSynonymInstances #-}"] + | dataExt = ["{-# LANGUAGE DeriveDataTypeable #-}"] | otherwise = [] + derivingClause + | dataExt = "deriving (Show,Data)" + | otherwise = "deriving Show" + extraImports | gadt = ["import Control.Monad.Identity", + "import Data.Monoid"] + | dataExt = ["import Data.Data"] + | otherwise = [] types | gadt = datatypesGADT gId lexical gr' - | otherwise = datatypes gId lexical gr' + | otherwise = datatypes gId derivingClause lexical gr' compos | gadt = prCompos gId lexical gr' ++ composClass | otherwise = [] -haskPreamble gadt name = +haskPreamble gadt name derivingClause extraImports = [ "module " ++ name ++ " where", "" - ] ++ - (if gadt then [ - "import Control.Monad.Identity", - "import Data.Monoid" - ] else []) ++ - [ + ] ++ extraImports ++ [ "import PGF hiding (Tree)", "----------------------------------------------------", "-- automatic translation from GF to Haskell", "----------------------------------------------------", - "", + "", "class Gf a where", " gf :: a -> Expr", " fg :: Expr -> a", "", - predefInst gadt "GString" "String" "unStr" "mkStr", + predefInst gadt derivingClause "GString" "String" "unStr" "mkStr", "", - predefInst gadt "GInt" "Int" "unInt" "mkInt", + predefInst gadt derivingClause "GInt" "Int" "unInt" "mkInt", "", - predefInst gadt "GFloat" "Double" "unFloat" "mkFloat", + predefInst gadt derivingClause "GFloat" "Double" "unFloat" "mkFloat", "", "----------------------------------------------------", "-- below this line machine-generated", @@ -77,11 +85,11 @@ haskPreamble gadt name = "" ] -predefInst gadt gtyp typ destr consr = +predefInst gadt derivingClause gtyp typ destr consr = (if gadt - then [] - else ("newtype" +++ gtyp +++ "=" +++ gtyp +++ typ +++ " deriving Show\n\n") - ) + then [] + else ("newtype" +++ gtyp +++ "=" +++ gtyp +++ typ +++ derivingClause ++ "\n\n") + ) ++ "instance Gf" +++ gtyp +++ "where" ++++ " gf (" ++ gtyp +++ "x) =" +++ consr +++ "x" ++++ @@ -94,24 +102,24 @@ type OIdent = String type HSkeleton = [(OIdent, [(OIdent, [OIdent])])] -datatypes :: Prefix -> (OIdent -> Bool) -> (String,HSkeleton) -> String -datatypes gId lexical = (foldr (+++++) "") . (filter (/="")) . (map (hDatatype gId lexical)) . snd +datatypes :: Prefix -> DerivingClause -> (OIdent -> Bool) -> (String,HSkeleton) -> String +datatypes gId derivingClause lexical = (foldr (+++++) "") . (filter (/="")) . (map (hDatatype gId derivingClause lexical)) . snd gfinstances :: Prefix -> (OIdent -> Bool) -> (String,HSkeleton) -> String gfinstances gId lexical (m,g) = (foldr (+++++) "") $ (filter (/="")) $ (map (gfInstance gId lexical m)) g -hDatatype :: Prefix -> (OIdent -> Bool) -> (OIdent, [(OIdent, [OIdent])]) -> String -hDatatype _ _ ("Cn",_) = "" --- -hDatatype gId _ (cat,[]) = "data" +++ gId cat -hDatatype gId _ (cat,rules) | isListCat (cat,rules) = - "newtype" +++ gId cat +++ "=" +++ gId cat +++ "[" ++ gId (elemCat cat) ++ "]" - +++ "deriving Show" -hDatatype gId lexical (cat,rules) = +hDatatype :: Prefix -> DerivingClause -> (OIdent -> Bool) -> (OIdent, [(OIdent, [OIdent])]) -> String +hDatatype _ _ _ ("Cn",_) = "" --- +hDatatype gId _ _ (cat,[]) = "data" +++ gId cat +hDatatype gId derivingClause _ (cat,rules) | isListCat (cat,rules) = + "newtype" +++ gId cat +++ "=" +++ gId cat +++ "[" ++ gId (elemCat cat) ++ "]" + +++ derivingClause +hDatatype gId derivingClause lexical (cat,rules) = "data" +++ gId cat +++ "=" ++ (if length rules == 1 then "" else "\n ") +++ foldr1 (\x y -> x ++ "\n |" +++ y) constructors ++++ - " deriving Show" + " " +++ derivingClause where constructors = [gId f +++ foldr (+++) "" (map (gId) xx) | (f,xx) <- nonLexicalRules (lexical cat) rules] ++ if lexical cat then [lexicalConstructor cat +++ "String"] else [] diff --git a/src/compiler/GF/Infra/Option.hs b/src/compiler/GF/Infra/Option.hs index c4108cbe3..afcd6f705 100644 --- a/src/compiler/GF/Infra/Option.hs +++ b/src/compiler/GF/Infra/Option.hs @@ -131,7 +131,7 @@ data CFGTransform = CFGNoLR deriving (Show,Eq,Ord) data HaskellOption = HaskellNoPrefix | HaskellGADT | HaskellLexical - | HaskellConcrete | HaskellVariants + | HaskellConcrete | HaskellVariants | HaskellData deriving (Show,Eq,Ord) data Warning = WarnMissingLincat @@ -530,7 +530,8 @@ haskellOptionNames = ("gadt", HaskellGADT), ("lexical", HaskellLexical), ("concrete", HaskellConcrete), - ("variants", HaskellVariants)] + ("variants", HaskellVariants), + ("data", HaskellData)] -- | This is for bacward compatibility. Since GHC 6.12 we -- started using the native Unicode support in GHC but it diff --git a/src/runtime/haskell-bind/CHANGELOG.md b/src/runtime/haskell-bind/CHANGELOG.md new file mode 100644 index 000000000..e9da7fac4 --- /dev/null +++ b/src/runtime/haskell-bind/CHANGELOG.md @@ -0,0 +1,13 @@ +## 1.2.0 + +- Stop `pgf-shell` from being built by default. +- parseToChart also returns the category. +- bugfix in bracketedLinearize. + +## 1.1.0 + +- Remove SG library. + +## 1.0.0 + +- Everything up until 2020-07-11. diff --git a/src/runtime/haskell-bind/LICENSE b/src/runtime/haskell-bind/LICENSE new file mode 100644 index 000000000..0a041280b --- /dev/null +++ b/src/runtime/haskell-bind/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/src/runtime/haskell-bind/PGF.hs b/src/runtime/haskell-bind/PGF.hs deleted file mode 100644 index 8aeca7ab8..000000000 --- a/src/runtime/haskell-bind/PGF.hs +++ /dev/null @@ -1,3 +0,0 @@ -module PGF(module PGF2) where - -import PGF2 diff --git a/src/runtime/haskell-bind/PGF/Internal.hs b/src/runtime/haskell-bind/PGF/Internal.hs deleted file mode 100644 index e8193b788..000000000 --- a/src/runtime/haskell-bind/PGF/Internal.hs +++ /dev/null @@ -1 +0,0 @@ -module PGF.Internal where diff --git a/src/runtime/haskell-bind/README b/src/runtime/haskell-bind/README deleted file mode 100644 index 4782c2d37..000000000 --- a/src/runtime/haskell-bind/README +++ /dev/null @@ -1,26 +0,0 @@ -This is a binding to the new GF runtime in C. - -The files are: - -PGF2.hsc -- a user API similar to Python and Java APIs -PGF2/FFI.hs -- an internal module with FFI definitions for - -- the relevant C functions - -HOW TO COMPILE: - -cabal install - -HOW TO USE: - -- Import PGF to the Haskell program that you're writing. - The Cabal infrastructure will make sure to tell the compiler - where to find the relevant modules. Example: - - module Main where - - import PGF2 - import qualified Data.Map as Map - - main = do - pgf <- readPGF "Foo.pgf" - let Just english = Map.lookup "FooEng" (languages pgf) diff --git a/src/runtime/haskell-bind/README.md b/src/runtime/haskell-bind/README.md new file mode 100644 index 000000000..1cb68df65 --- /dev/null +++ b/src/runtime/haskell-bind/README.md @@ -0,0 +1,56 @@ +# PGF2 + +This is a Haskell binding to the PGF runtime written in C. + +The exposed modules are: + +- `PGF2`: a user API similar to Python and Java APIs +- `PGF2.Internal`: an internal module with FFI definitions for the relevant C functions + +## How to compile + +**Important:** You must have the C runtime already installed and available on your system. +See + +Once the runtine is installed, you can install the library to your global Cabal installation: + +``` +cabal install pgf2 --extra-lib-dirs=/usr/local/lib +``` + +or add it to your `stack.yaml` file: + +```yaml +extra-deps: + - pgf2 +extra-lib-dirs: + - /usr/local/lib +``` + +## How to use + +Simply import `PGF2` in your Haskell program. +The Cabal infrastructure will make sure to tell the compiler where to find the relevant modules. + +## Example + +```haskell +module Main where + +import PGF2 +import qualified Data.Map as Map + +main = do + pgf <- readPGF "App12.pgf" + let Just eng = Map.lookup "AppEng" (languages pgf) + + -- Parsing + let res = parse eng (startCat pgf) "this is a small theatre" + let ParseOk ((tree,prob):rest) = res + print tree + + -- Linearisation + let Just expr = readExpr "AdjCN (PositA red_A) (UseN theatre_N)" + let s = linearize eng expr + print s +``` diff --git a/src/runtime/haskell-bind/pgf2.cabal b/src/runtime/haskell-bind/pgf2.cabal index 9197bff9a..a4e113f3b 100644 --- a/src/runtime/haskell-bind/pgf2.cabal +++ b/src/runtime/haskell-bind/pgf2.cabal @@ -1,37 +1,47 @@ -name: pgf2 -version: 0.1.0.0 --- synopsis: --- description: -homepage: http://www.grammaticalframework.org -license: LGPL-3 ---license-file: LICENSE -author: Krasimir Angelov, Inari -maintainer: --- copyright: -category: Language -build-type: Simple -extra-source-files: README -cabal-version: >=1.10 +name: pgf2 +version: 1.2.0 +synopsis: Bindings to the C version of the PGF runtime +description: + 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. + This package provides Haskell bindings to that runtime. +homepage: https://www.grammaticalframework.org +license: LGPL-3 +license-file: LICENSE +author: Krasimir Angelov +maintainer: kr.angelov@gmail.com +category: Language +build-type: Simple +extra-source-files: CHANGELOG.md, README.md +cabal-version: >=1.10 library - exposed-modules: PGF2, PGF2.Internal - -- backwards compatibility API: - --, PGF, PGF.Internal - other-modules: PGF2.FFI, PGF2.Expr, PGF2.Type - build-depends: base >=4.3, - containers, pretty - -- hs-source-dirs: - default-language: Haskell2010 - build-tools: hsc2hs + exposed-modules: + PGF2, + PGF2.Internal + other-modules: + PGF2.FFI, + PGF2.Expr, + PGF2.Type + build-depends: + base >=4.3 && <5, + containers, + pretty + default-language: Haskell2010 + build-tools: hsc2hs + extra-libraries: pgf gu + cc-options: -std=c99 + c-sources: utils.c - extra-libraries: pgf gu - cc-options: -std=c99 - c-sources: utils.c - -executable pgf-shell - main-is: pgf-shell.hs - hs-source-dirs: examples - build-depends: base, pgf2, containers, mtl, lifted-base - default-language: Haskell2010 - if impl(ghc>=7.0) - ghc-options: -rtsopts +-- executable pgf-shell +-- main-is: pgf-shell.hs +-- hs-source-dirs: examples +-- build-depends: +-- base, +-- containers, +-- lifted-base, +-- mtl, +-- pgf2 +-- default-language: Haskell2010 +-- if impl(ghc>=7.0) +-- ghc-options: -rtsopts diff --git a/src/runtime/haskell-bind/stack-haddock-upload.sh b/src/runtime/haskell-bind/stack-haddock-upload.sh new file mode 100755 index 000000000..47333bf38 --- /dev/null +++ b/src/runtime/haskell-bind/stack-haddock-upload.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Author: Dimitri Sabadie +# 2015 + +if [ $# -lt 2 ]; then + echo "Usage: ./stack-haddock-upload.sh NAME VERSION" + exit 1 +fi + +dist=`stack path --dist-dir --stack-yaml ./stack.yaml 2> /dev/null` + +echo -e "\033[1;36mGenerating documentation...\033[0m" +stack haddock 2> /dev/null + +if [ "$?" -eq "0" ]; then + docdir=$dist/doc/html + cd $docdir || exit + doc=$1-$2-docs + echo -e "Compressing documentation from \033[1;34m$docdir\033[0m for \033[1;35m$1\033[0m-\033[1;33m$2\033[1;30m" + cp -r $1 $doc + tar -c -v -z --format=ustar -f $doc.tar.gz $doc + echo -e "\033[1;32mUploading to Hackage...\033[0m" + read -p "Hackage username: " username + read -p "Hackage password: " -s password + echo "" + curl -X PUT -H 'Content-Type: application/x-tar' -H 'Content-Encoding: gzip' --data-binary "@$doc.tar.gz" "https://$username:$password@hackage.haskell.org/package/$1-$2/docs" + exit $? +else + echo -e "\033[1;31mNot in a stack-powered project\033[0m" +fi diff --git a/src/runtime/haskell-bind/stack.yaml b/src/runtime/haskell-bind/stack.yaml new file mode 100644 index 000000000..3b1a3092b --- /dev/null +++ b/src/runtime/haskell-bind/stack.yaml @@ -0,0 +1,3 @@ +# This is mainly here so that I can run `stack sdist` for uploading to Hackage + +resolver: lts-12.26 # ghc 8.4.4