diff options
Diffstat (limited to 'src/runtime/haskell-bind')
| -rw-r--r-- | src/runtime/haskell-bind/CHANGELOG.md | 22 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/HACKAGE.md | 10 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/LICENSE | 165 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/PGF.hs | 3 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/PGF/Internal.hs | 1 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/PGF2.hsc | 145 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/PGF2/FFI.hsc | 20 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/README | 26 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/README.md | 56 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/SG.hsc | 349 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/SG/FFI.hs | 84 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/pgf2.cabal | 77 | ||||
| -rwxr-xr-x | src/runtime/haskell-bind/stack-haddock-upload.sh | 31 | ||||
| -rw-r--r-- | src/runtime/haskell-bind/stack.yaml | 3 |
14 files changed, 440 insertions, 552 deletions
diff --git a/src/runtime/haskell-bind/CHANGELOG.md b/src/runtime/haskell-bind/CHANGELOG.md new file mode 100644 index 000000000..570c7fd73 --- /dev/null +++ b/src/runtime/haskell-bind/CHANGELOG.md @@ -0,0 +1,22 @@ +## 1.3.0 + +- Add completion support. + +## 1.2.1 + +- Remove deprecated `pgf_print_expr_tuple`. +- Added an API for cloning expressions/types/literals. + +## 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/HACKAGE.md b/src/runtime/haskell-bind/HACKAGE.md new file mode 100644 index 000000000..d931ef8f9 --- /dev/null +++ b/src/runtime/haskell-bind/HACKAGE.md @@ -0,0 +1,10 @@ +# Instructions for uploading to Hackage + +You will need a Hackage account for steps 4 & 5. + +1. Bump the version number in `pgf2.cabal` +2. Add details in `CHANGELOG.md` +3. Run `stack sdist` (or `cabal sdist`) +4. Visit `https://hackage.haskell.org/upload` and upload the file `./.stack-work/dist/x86_64-osx/Cabal-2.2.0.1/pgf2-x.y.z.tar.gz` (or Cabal equivalent) +5. If successful, upload documentation with `./stack-haddock-upload.sh pgf2 x.y.z` (compilation on Hackage's servers will fail because of missing C libraries) +6. Commit and push to this repository (`gf-core`) 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. <https://fsf.org/> + 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/PGF2.hsc b/src/runtime/haskell-bind/PGF2.hsc index 4b41a7471..38fae67ef 100644 --- a/src/runtime/haskell-bind/PGF2.hsc +++ b/src/runtime/haskell-bind/PGF2.hsc @@ -43,30 +43,28 @@ module PGF2 (-- * PGF mkCId, exprHash, exprSize, exprFunctions, exprSubstitute, treeProbability, - -- ** Types Type, Hypo, BindType(..), startCat, readType, showType, showContext, mkType, unType, - -- ** Type checking + -- | Dynamically-built expressions should always be type-checked before using in other functions, + -- as the exceptions thrown by using invalid expressions may not catchable. checkExpr, inferExpr, checkType, - -- ** Computing compute, -- * Concrete syntax ConcName,Concr,languages,concreteName,languageCode, - -- ** Linearization linearize,linearizeAll,tabularLinearize,tabularLinearizeAll,bracketedLinearize,bracketedLinearizeAll, FId, BracketedString(..), showBracketedString, flattenBracketedString, printName, categoryFields, - alignWords, -- ** Parsing ParseOutput(..), parse, parseWithHeuristics, parseToChart, PArg(..), + complete, -- ** Sentence Lookup lookupSentence, -- ** Generation @@ -180,7 +178,7 @@ languageCode c = unsafePerformIO (peekUtf8CString =<< pgf_language_code (concr c -- | Generates an exhaustive possibly infinite list of --- all abstract syntax expressions of the given type. +-- all abstract syntax expressions of the given type. -- The expressions are ordered by their probability. generateAll :: PGF -> Type -> [(Expr,Float)] generateAll p (Type ctype _) = @@ -433,6 +431,7 @@ graphvizParseTree c opts e = c_opts <- newGraphvizOptions tmpPl opts pgf_graphviz_parse_tree (concr c) (expr e) c_opts out exn touchExpr e + touchConcr c s <- gu_string_buf_freeze sb tmpPl peekUtf8CString s @@ -468,21 +467,21 @@ newGraphvizOptions pool opts = do -- Functions using Concr -- Morpho analyses, parsing & linearization --- | This triple is returned by all functions that deal with +-- | This triple is returned by all functions that deal with -- the grammar's lexicon. Its first element is the name of an abstract --- lexical function which can produce a given word or +-- lexical function which can produce a given word or -- a multiword expression (i.e. this is the lemma). --- After that follows a string which describes +-- After that follows a string which describes -- the particular inflection form. -- -- The last element is a logarithm from the --- the probability of the function. The probability is not +-- the probability of the function. The probability is not -- conditionalized on the category of the function. This makes it -- possible to compare the likelihood of two functions even if they --- have different types. +-- have different types. type MorphoAnalysis = (Fun,String,Float) --- | 'lookupMorpho' takes a string which must be a single word or +-- | 'lookupMorpho' takes a string which must be a single word or -- a multiword expression. It then computes the list of all possible -- morphological analyses. lookupMorpho :: Concr -> String -> [MorphoAnalysis] @@ -540,12 +539,12 @@ lookupCohorts lang@(Concr concr master) sent = return ((start,tok,ans,end):cohs) filterBest :: [(Int,String,[MorphoAnalysis],Int)] -> [(Int,String,[MorphoAnalysis],Int)] -filterBest ans = +filterBest ans = reverse (iterate (maxBound :: Int) [(0,0,[],ans)] [] []) where iterate v0 [] [] res = res iterate v0 [] new res = iterate v0 new [] res - iterate v0 ((_,v,conf, []):old) new res = + iterate v0 ((_,v,conf, []):old) new res = case compare v0 v of LT -> res EQ -> iterate v0 old new (merge conf res) @@ -648,7 +647,7 @@ getAnalysis ref self c_lemma c_anal prob exn = do data ParseOutput a = ParseFailed Int String -- ^ The integer is the position in number of unicode characters where the parser failed. -- The string is the token where the parser have failed. - | ParseOk a -- ^ If the parsing and the type checking are successful + | ParseOk a -- ^ If the parsing and the type checking are successful -- we get the abstract syntax trees as either a list or a chart. | ParseIncomplete -- ^ The sentence is not complete. @@ -658,9 +657,9 @@ parse lang ty sent = parseWithHeuristics lang ty sent (-1.0) [] parseWithHeuristics :: Concr -- ^ the language with which we parse -> Type -- ^ the start category -> String -- ^ the input sentence - -> Double -- ^ the heuristic factor. - -- A negative value tells the parser - -- to lookup up the default from + -> Double -- ^ the heuristic factor. + -- A negative value tells the parser + -- to lookup up the default from -- the grammar flags -> [(Cat, String -> Int -> Maybe (Expr,Float,Int))] -- ^ a list of callbacks for literal categories. @@ -714,9 +713,9 @@ parseWithHeuristics lang (Type ctype touchType) sent heuristic callbacks = parseToChart :: Concr -- ^ the language with which we parse -> Type -- ^ the start category -> String -- ^ the input sentence - -> Double -- ^ the heuristic factor. - -- A negative value tells the parser - -- to lookup up the default from + -> Double -- ^ the heuristic factor. + -- A negative value tells the parser + -- to lookup up the default from -- the grammar flags -> [(Cat, String -> Int -> Maybe (Expr,Float,Int))] -- ^ a list of callbacks for literal categories. @@ -726,7 +725,7 @@ parseToChart :: Concr -- ^ the language with which we parse -- If a literal has been recognized then the output should -- be Just (expr,probability,end_offset) -> Int -- ^ the maximal number of roots - -> ParseOutput ([FId],Map.Map FId ([(Int,Int,String)],[(Expr,[PArg],Float)])) + -> ParseOutput ([FId],Map.Map FId ([(Int,Int,String)],[(Expr,[PArg],Float)],Cat)) parseToChart lang (Type ctype touchType) sent heuristic callbacks roots = unsafePerformIO $ withGuPool $ \parsePl -> do @@ -776,19 +775,23 @@ parseToChart lang (Type ctype touchType) sent heuristic callbacks roots = c_total_cats <- (#peek PgfConcr, total_cats) (concr lang) if Map.member fid chart || fid < c_total_cats then return (fid,chart) - else do range <- get_range c_ccat >>= peekSequence peekRange (#size PgfParseRange) + else do c_cnccat <- (#peek PgfCCat, cnccat) c_ccat + c_abscat <- (#peek PgfCCat, cnccat) c_cnccat + c_name <- (#peek PgfCCat, cnccat) c_abscat + cat <- peekUtf8CString c_name + range <- get_range c_ccat >>= peekSequence peekRange (#size PgfParseRange) c_prods <- (#peek PgfCCat, prods) c_ccat if c_prods == nullPtr - then do return (fid,Map.insert fid (range,[]) chart) + then do return (fid,Map.insert fid (range,[],cat) chart) else do c_len <- (#peek PgfCCat, n_synprods) c_ccat - (prods,chart) <- fixIO (\res -> peekProductions (Map.insert fid (range,fst res) chart) + (prods,chart) <- fixIO (\res -> peekProductions (Map.insert fid (range,fst res,cat) chart) (fromIntegral (c_len :: CSizeT)) (c_prods `plusPtr` (#offset GuSeq, data))) return (fid,chart) where peekProductions chart 0 ptr = return ([],chart) peekProductions chart len ptr = do - (ps1, chart) <- deRef (peekProduction chart) ptr + (ps1,chart) <- deRef (peekProduction chart) ptr (ps2,chart) <- peekProductions chart (len-1) (ptr `plusPtr` (#size GuVariant)) return (ps1++ps2,chart) @@ -806,13 +809,15 @@ parseToChart lang (Type ctype touchType) sent heuristic callbacks roots = return ([(Expr expr (touchConcr lang), pargs, p)],chart) } (#const PGF_PRODUCTION_COERCE) -> do { c_coerce <- (#peek PgfProductionCoerce, coerce) dt ; (fid,chart) <- peekCCat get_range chart c_coerce ; - return (maybe [] snd (Map.lookup fid chart),chart) } + return (maybe [] snd3 (Map.lookup fid chart),chart) } (#const PGF_PRODUCTION_EXTERN) -> do { c_ep <- (#peek PgfProductionExtern, ep) dt ; expr <- (#peek PgfExprProb, expr) c_ep ; p <- (#peek PgfExprProb, prob) c_ep ; return ([(Expr expr (touchConcr lang), [], p)],chart) } _ -> error ("Unknown production type "++show tag++" in the grammar") + snd3 (_,x,_) = x + peekPArgs chart 0 ptr = return ([],chart) peekPArgs chart len ptr = do (a, chart) <- peekPArg chart ptr @@ -852,16 +857,7 @@ mkCallbacksMap concr callbacks pool = do Just (e,prob,offset') -> do poke poffset (fromIntegral offset') -- here we copy the expression to out_pool - c_e <- withGuPool $ \tmpPl -> do - exn <- gu_new_exn tmpPl - - (sb,out) <- newOut tmpPl - let printCtxt = nullPtr - pgf_print_expr (expr e) printCtxt 1 out exn - c_str <- gu_string_buf_freeze sb tmpPl - - guin <- gu_string_in c_str tmpPl - pgf_read_expr guin out_pool tmpPl exn + c_e <- pgf_clone_expr (expr e) out_pool ep <- gu_malloc out_pool (#size PgfExprProb) (#poke PgfExprProb, expr) ep c_e @@ -888,7 +884,7 @@ lookupSentence lang (Type ctype _) sent = -- | The oracle is a triple of functions. -- The first two take a category name and a linearization field name --- and they should return True/False when the corresponding +-- and they should return True/False when the corresponding -- prediction or completion is appropriate. The third function -- is the oracle for literals. type Oracle = (Maybe (Cat -> String -> Int -> Bool) @@ -976,6 +972,67 @@ parseWithOracle lang cat sent (predict,complete,literal) = return ep Nothing -> do return nullPtr +-- | Returns possible completions of the current partial input. +complete :: Concr -- ^ the language with which we parse + -> Type -- ^ the start category + -> String -- ^ the input sentence (excluding token being completed) + -> String -- ^ prefix (partial token being completed) + -> ParseOutput [(String, CId, CId, Float)] -- ^ (token, category, function, probability) +complete lang (Type ctype _) sent pfx = + unsafePerformIO $ do + parsePl <- gu_new_pool + exn <- gu_new_exn parsePl + sent <- newUtf8CString sent parsePl + pfx <- newUtf8CString pfx parsePl + enum <- pgf_complete (concr lang) ctype sent pfx exn parsePl + failed <- gu_exn_is_raised exn + if failed + then do + is_parse_error <- gu_exn_caught exn gu_exn_type_PgfParseError + if is_parse_error + then do + c_err <- (#peek GuExn, data.data) exn + c_offset <- (#peek PgfParseError, offset) c_err + token_ptr <- (#peek PgfParseError, token_ptr) c_err + token_len <- (#peek PgfParseError, token_len) c_err + tok <- peekUtf8CStringLen token_ptr token_len + gu_pool_free parsePl + return (ParseFailed (fromIntegral (c_offset :: CInt)) tok) + else do + is_exn <- gu_exn_caught exn gu_exn_type_PgfExn + if is_exn + then do + c_msg <- (#peek GuExn, data.data) exn + msg <- peekUtf8CString c_msg + gu_pool_free parsePl + throwIO (PGFError msg) + else do + gu_pool_free parsePl + throwIO (PGFError "Parsing failed") + else do + fpl <- newForeignPtr gu_pool_finalizer parsePl + ParseOk <$> fromCompletions enum fpl + where + fromCompletions :: Ptr GuEnum -> ForeignPtr GuPool -> IO [(String, CId, CId, Float)] + fromCompletions enum fpl = + withGuPool $ \tmpPl -> do + cmpEntry <- alloca $ \ptr -> + withForeignPtr fpl $ \pl -> + do gu_enum_next enum ptr pl + peek ptr + if cmpEntry == nullPtr + then do + finalizeForeignPtr fpl + touchConcr lang + return [] + else do + tok <- peekUtf8CString =<< (#peek PgfTokenProb, tok) cmpEntry + cat <- peekUtf8CString =<< (#peek PgfTokenProb, cat) cmpEntry + fun <- peekUtf8CString =<< (#peek PgfTokenProb, fun) cmpEntry + prob <- (#peek PgfTokenProb, prob) cmpEntry + toks <- unsafeInterleaveIO (fromCompletions enum fpl) + return ((tok, cat, fun, prob) : toks) + -- | Returns True if there is a linearization defined for that function in that language hasLinearization :: Concr -> Fun -> Bool hasLinearization lang id = unsafePerformIO $ @@ -1049,7 +1106,7 @@ linearizeAll lang e = unsafePerformIO $ -- | Generates a table of linearizations for an expression tabularLinearize :: Concr -> Expr -> [(String, String)] -tabularLinearize lang e = +tabularLinearize lang e = case tabularLinearizeAll lang e of (lins:_) -> lins _ -> [] @@ -1140,7 +1197,7 @@ data BracketedString -- the phrase. The 'FId' is an unique identifier for -- every phrase in the sentence. For context-free grammars -- i.e. without discontinuous constituents this identifier - -- is also unique for every bracket. When there are discontinuous + -- is also unique for every bracket. When there are discontinuous -- phrases then the identifiers are unique for every phrase but -- not for every bracket since the bracket represents a constituent. -- The different constituents could still be distinguished by using @@ -1150,7 +1207,7 @@ data BracketedString -- The second 'CId' is the name of the abstract function that generated -- this phrase. --- | Renders the bracketed string as a string where +-- | Renders the bracketed string as a string where -- the brackets are shown as @(S ...)@ where -- @S@ is the category. showBracketedString :: BracketedString -> String @@ -1168,7 +1225,7 @@ flattenBracketedString (Bracket _ _ _ _ bss) = concatMap flattenBracketedString bracketedLinearize :: Concr -> Expr -> [BracketedString] bracketedLinearize lang e = unsafePerformIO $ - withGuPool $ \pl -> + withGuPool $ \pl -> do exn <- gu_new_exn pl cts <- pgf_lzr_concretize (concr lang) (expr e) exn pl failed <- gu_exn_is_raised exn @@ -1194,7 +1251,7 @@ bracketedLinearize lang e = unsafePerformIO $ bracketedLinearizeAll :: Concr -> Expr -> [[BracketedString]] bracketedLinearizeAll lang e = unsafePerformIO $ - withGuPool $ \pl -> + withGuPool $ \pl -> do exn <- gu_new_exn pl cts <- pgf_lzr_concretize (concr lang) (expr e) exn pl failed <- gu_exn_is_raised exn @@ -1469,7 +1526,7 @@ type LiteralCallback = literalCallbacks :: [(AbsName,[(Cat,LiteralCallback)])] literalCallbacks = [("App",[("PN",nerc),("Symb",chunk)])] --- | Named entity recognition for the App grammar +-- | Named entity recognition for the App grammar -- (based on ../java/org/grammaticalframework/pgf/NercLiteralCallback.java) nerc :: LiteralCallback nerc pgf (lang,concr) sentence lin_idx offset = diff --git a/src/runtime/haskell-bind/PGF2/FFI.hsc b/src/runtime/haskell-bind/PGF2/FFI.hsc index b348f5012..16f9ad46d 100644 --- a/src/runtime/haskell-bind/PGF2/FFI.hsc +++ b/src/runtime/haskell-bind/PGF2/FFI.hsc @@ -103,7 +103,7 @@ foreign import ccall unsafe "gu/file.h gu_file_in" foreign import ccall safe "gu/enum.h gu_enum_next" gu_enum_next :: Ptr a -> Ptr (Ptr b) -> Ptr GuPool -> IO () - + foreign import ccall unsafe "gu/string.h gu_string_buf_freeze" gu_string_buf_freeze :: Ptr GuStringBuf -> Ptr GuPool -> IO CString @@ -241,7 +241,7 @@ newSequence elem_size pokeElem values pool = do type FId = Int data PArg = PArg [FId] {-# UNPACK #-} !FId deriving (Eq,Ord,Show) -peekFId :: Ptr a -> IO FId +peekFId :: Ptr a -> IO FId peekFId c_ccat = do c_fid <- (#peek PgfCCat, fid) c_ccat return (fromIntegral (c_fid :: CInt)) @@ -256,6 +256,7 @@ data PgfApplication data PgfConcr type PgfExpr = Ptr () data PgfExprProb +data PgfTokenProb data PgfExprParser data PgfFullFormEntry data PgfMorphoCallback @@ -422,6 +423,9 @@ foreign import ccall foreign import ccall "pgf/pgf.h pgf_parse_with_oracle" pgf_parse_with_oracle :: Ptr PgfConcr -> CString -> CString -> Ptr PgfOracleCallback -> Ptr GuExn -> Ptr GuPool -> Ptr GuPool -> IO (Ptr GuEnum) +foreign import ccall "pgf/pgf.h pgf_complete" + pgf_complete :: Ptr PgfConcr -> PgfType -> CString -> CString -> Ptr GuExn -> Ptr GuPool -> IO (Ptr GuEnum) + foreign import ccall "pgf/pgf.h pgf_lookup_morpho" pgf_lookup_morpho :: Ptr PgfConcr -> CString -> Ptr PgfMorphoCallback -> Ptr GuExn -> IO () @@ -513,9 +517,6 @@ foreign import ccall "pgf/expr.h pgf_compute" foreign import ccall "pgf/expr.h pgf_print_expr" pgf_print_expr :: PgfExpr -> Ptr PgfPrintContext -> CInt -> Ptr GuOut -> Ptr GuExn -> IO () -foreign import ccall "pgf/expr.h pgf_print_expr_tuple" - pgf_print_expr_tuple :: CSizeT -> Ptr PgfExpr -> Ptr PgfPrintContext -> Ptr GuOut -> Ptr GuExn -> IO () - foreign import ccall "pgf/expr.h pgf_print_type" pgf_print_type :: PgfType -> Ptr PgfPrintContext -> CInt -> Ptr GuOut -> Ptr GuExn -> IO () @@ -531,12 +532,6 @@ foreign import ccall "pgf/pgf.h pgf_print" foreign import ccall "pgf/expr.h pgf_read_expr" pgf_read_expr :: Ptr GuIn -> Ptr GuPool -> Ptr GuPool -> Ptr GuExn -> IO PgfExpr -foreign import ccall "pgf/expr.h pgf_read_expr_tuple" - pgf_read_expr_tuple :: Ptr GuIn -> CSizeT -> Ptr PgfExpr -> Ptr GuPool -> Ptr GuExn -> IO CInt - -foreign import ccall "pgf/expr.h pgf_read_expr_matrix" - pgf_read_expr_matrix :: Ptr GuIn -> CSizeT -> Ptr GuPool -> Ptr GuExn -> IO (Ptr GuSeq) - foreign import ccall "pgf/expr.h pgf_read_type" pgf_read_type :: Ptr GuIn -> Ptr GuPool -> Ptr GuPool -> Ptr GuExn -> IO PgfType @@ -557,3 +552,6 @@ foreign import ccall "pgf/data.h pgf_lzr_index" foreign import ccall "pgf/data.h pgf_production_is_lexical" pgf_production_is_lexical :: Ptr PgfProductionApply -> Ptr GuBuf -> Ptr GuPool -> IO (#type bool) + +foreign import ccall "pgf/expr.h pgf_clone_expr" + pgf_clone_expr :: PgfExpr -> Ptr GuPool -> IO PgfExpr 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 <https://github.com/GrammaticalFramework/gf-core/blob/master/src/runtime/c/INSTALL> + +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/SG.hsc b/src/runtime/haskell-bind/SG.hsc deleted file mode 100644 index 791abc767..000000000 --- a/src/runtime/haskell-bind/SG.hsc +++ /dev/null @@ -1,349 +0,0 @@ -{-# LANGUAGE DeriveDataTypeable, ExistentialQuantification #-} - -#include <pgf/pgf.h> -#include <gu/exn.h> -#include <sg/sg.h> - -module SG( SG, openSG, closeSG - , beginTrans, commit, rollback, inTransaction - , SgId - , insertExpr, getExpr, queryExpr - , updateFtsIndex - , queryLinearization - , readTriple, showTriple - , insertTriple, getTriple - , queryTriple - , query - ) where - -import Foreign hiding (unsafePerformIO) -import Foreign.C -import SG.FFI -import PGF2.FFI -import PGF2.Expr - -import Data.Typeable -import Control.Exception(Exception,SomeException,catch,throwIO) -import System.IO.Unsafe(unsafePerformIO,unsafeInterleaveIO) - ------------------------------------------------------------------------ --- Global database operations and types - -newtype SG = SG {sg :: Ptr SgSG} - -openSG :: FilePath -> IO SG -openSG fpath = - withCString fpath $ \c_fpath -> - withGuPool $ \tmpPl -> do - exn <- gu_new_exn tmpPl - sg <- sg_open c_fpath exn - failed <- gu_exn_is_raised exn - if failed - then do is_errno <- gu_exn_caught exn gu_exn_type_GuErrno - if is_errno - then do perrno <- (#peek GuExn, data.data) exn - errno <- peek perrno - ioError (errnoToIOError "openSG" (Errno errno) Nothing (Just fpath)) - else do is_sgerr <- gu_exn_caught exn gu_exn_type_SgError - if is_sgerr - then do c_msg <- (#peek GuExn, data.data) exn - msg <- peekUtf8CString c_msg - throwIO (SGError msg) - else throwIO (SGError "The database cannot be opened") - else return (SG sg) - -closeSG :: SG -> IO () -closeSG (SG sg) = - withGuPool $ \tmpPl -> do - exn <- gu_new_exn tmpPl - sg <- sg_close sg exn - handle_sg_exn exn - -beginTrans :: SG -> IO () -beginTrans (SG sg) = - withGuPool $ \tmpPl -> do - exn <- gu_new_exn tmpPl - sg <- sg_begin_trans sg exn - handle_sg_exn exn - -commit :: SG -> IO () -commit (SG sg) = - withGuPool $ \tmpPl -> do - exn <- gu_new_exn tmpPl - sg <- sg_commit sg exn - handle_sg_exn exn - -rollback :: SG -> IO () -rollback (SG sg) = - withGuPool $ \tmpPl -> do - exn <- gu_new_exn tmpPl - sg <- sg_rollback sg exn - handle_sg_exn exn - -inTransaction :: SG -> IO a -> IO a -inTransaction sg f = - catch (beginTrans sg >> f >>= \x -> commit sg >> return x) - (\e -> rollback sg >> throwIO (e :: SomeException)) - ------------------------------------------------------------------------ --- Expressions - -insertExpr :: SG -> Expr -> IO SgId -insertExpr (SG sg) (Expr expr touch) = - withGuPool $ \tmpPl -> do - exn <- gu_new_exn tmpPl - id <- sg_insert_expr sg expr 1 exn - touch - handle_sg_exn exn - return id - -getExpr :: SG -> SgId -> IO (Maybe Expr) -getExpr (SG sg) id = do - exprPl <- gu_new_pool - exprFPl <- newForeignPtr gu_pool_finalizer exprPl - withGuPool $ \tmpPl -> do - exn <- gu_new_exn tmpPl - c_expr <- sg_get_expr sg id exprPl exn - handle_sg_exn exn - if c_expr == nullPtr - then do touchForeignPtr exprFPl - return Nothing - else do return $ Just (Expr c_expr (touchForeignPtr exprFPl)) - -queryExpr :: SG -> Expr -> IO [(SgId,Expr)] -queryExpr (SG sg) (Expr query touch) = - withGuPool $ \tmpPl -> do - exn <- gu_new_exn tmpPl - res <- sg_query_expr sg query tmpPl exn - touch - handle_sg_exn exn - fetchResults res exn - where - fetchResults res exn = do - exprPl <- gu_new_pool - (key,c_expr) <- alloca $ \pKey -> do - c_expr <- sg_query_next sg res pKey exprPl exn - key <- peek pKey - return (key,c_expr) - failed <- gu_exn_is_raised exn - if failed - then do gu_pool_free exprPl - sg_query_close sg res exn - handle_sg_exn exn - return [] - else if c_expr == nullPtr - then do gu_pool_free exprPl - sg_query_close sg res exn - return [] - else do exprFPl <- newForeignPtr gu_pool_finalizer exprPl - rest <- fetchResults res exn - return ((key,Expr c_expr (touchForeignPtr exprFPl)) : rest) - -updateFtsIndex :: SG -> PGF -> IO () -updateFtsIndex (SG sg) p = do - withGuPool $ \tmpPl -> do - exn <- gu_new_exn tmpPl - sg_update_fts_index sg (pgf p) exn - handle_sg_exn exn - -queryLinearization :: SG -> String -> IO [Expr] -queryLinearization (SG sg) query = do - exprPl <- gu_new_pool - exprFPl <- newForeignPtr gu_pool_finalizer exprPl - (withGuPool $ \tmpPl -> do - c_query <- newUtf8CString query tmpPl - exn <- gu_new_exn tmpPl - seq <- sg_query_linearization sg c_query tmpPl exn - handle_sg_exn exn - len <- (#peek GuSeq, len) seq - ids <- peekArray (fromIntegral (len :: CInt)) (seq `plusPtr` (#offset GuSeq, data)) - getExprs exprFPl exprPl exn ids) - where - getExprs exprFPl exprPl exn [] = return [] - getExprs exprFPl exprPl exn (id:ids) = do - c_expr <- sg_get_expr sg id exprPl exn - handle_sg_exn exn - if c_expr == nullPtr - then getExprs exprFPl exprPl exn ids - else do let e = Expr c_expr (touchForeignPtr exprFPl) - es <- getExprs exprFPl exprPl exn ids - return (e:es) - ------------------------------------------------------------------------ --- Triples - -readTriple :: String -> Maybe (Expr,Expr,Expr) -readTriple str = - unsafePerformIO $ - do exprPl <- gu_new_pool - withGuPool $ \tmpPl -> - withTriple $ \triple -> - do c_str <- newUtf8CString str tmpPl - guin <- gu_string_in c_str tmpPl - exn <- gu_new_exn tmpPl - ok <- pgf_read_expr_tuple guin 3 triple exprPl exn - status <- gu_exn_is_raised exn - if (ok == 1 && not status) - then do c_expr1 <- peekElemOff triple 0 - c_expr2 <- peekElemOff triple 1 - c_expr3 <- peekElemOff triple 2 - exprFPl <- newForeignPtr gu_pool_finalizer exprPl - let touch = touchForeignPtr exprFPl - return $ Just (Expr c_expr1 touch,Expr c_expr2 touch,Expr c_expr3 touch) - else do gu_pool_free exprPl - return Nothing - -showTriple :: Expr -> Expr -> Expr -> String -showTriple (Expr expr1 touch1) (Expr expr2 touch2) (Expr expr3 touch3) = - unsafePerformIO $ - withGuPool $ \tmpPl -> - withTriple $ \triple -> do - (sb,out) <- newOut tmpPl - let printCtxt = nullPtr - exn <- gu_new_exn tmpPl - pokeElemOff triple 0 expr1 - pokeElemOff triple 1 expr2 - pokeElemOff triple 2 expr3 - pgf_print_expr_tuple 3 triple printCtxt out exn - touch1 >> touch2 >> touch3 - s <- gu_string_buf_freeze sb tmpPl - peekUtf8CString s - -insertTriple :: SG -> Expr -> Expr -> Expr -> IO SgId -insertTriple (SG sg) (Expr expr1 touch1) (Expr expr2 touch2) (Expr expr3 touch3) = - withGuPool $ \tmpPl -> - withTriple $ \triple -> do - exn <- gu_new_exn tmpPl - pokeElemOff triple 0 expr1 - pokeElemOff triple 1 expr2 - pokeElemOff triple 2 expr3 - id <- sg_insert_triple sg triple exn - touch1 >> touch2 >> touch3 - handle_sg_exn exn - return id - -getTriple :: SG -> SgId -> IO (Maybe (Expr,Expr,Expr)) -getTriple (SG sg) id = do - exprPl <- gu_new_pool - exprFPl <- newForeignPtr gu_pool_finalizer exprPl - let touch = touchForeignPtr exprFPl - withGuPool $ \tmpPl -> - withTriple $ \triple -> do - exn <- gu_new_exn tmpPl - res <- sg_get_triple sg id triple exprPl exn - handle_sg_exn exn - if res /= 0 - then do c_expr1 <- peekElemOff triple 0 - c_expr2 <- peekElemOff triple 1 - c_expr3 <- peekElemOff triple 2 - return (Just (Expr c_expr1 touch - ,Expr c_expr2 touch - ,Expr c_expr3 touch - )) - else do touch - return Nothing - -queryTriple :: SG -> Maybe Expr -> Maybe Expr -> Maybe Expr -> IO [(SgId,Expr,Expr,Expr)] -queryTriple (SG sg) mb_expr1 mb_expr2 mb_expr3 = - withGuPool $ \tmpPl -> - withTriple $ \triple -> do - exn <- gu_new_exn tmpPl - pokeElemOff triple 0 (toCExpr mb_expr1) - pokeElemOff triple 1 (toCExpr mb_expr2) - pokeElemOff triple 2 (toCExpr mb_expr3) - res <- sg_query_triple sg triple exn - handle_sg_exn exn - unsafeInterleaveIO (fetchResults res) - where - toCExpr Nothing = nullPtr - toCExpr (Just (Expr expr _)) = expr - - fromCExpr c_expr touch Nothing = Expr c_expr touch - fromCExpr c_expr touch (Just e) = e - - fetchResults res = do - exprPl <- gu_new_pool - alloca $ \pKey -> - withGuPool $ \tmpPl -> - withTriple $ \triple -> do - exn <- gu_new_exn tmpPl - r <- sg_triple_result_fetch res pKey triple exprPl exn - failed <- gu_exn_is_raised exn - if failed - then do gu_pool_free exprPl - sg_triple_result_close res exn - handle_sg_exn exn - return [] - else if r == 0 - then do gu_pool_free exprPl - sg_triple_result_close res exn - return [] - else do exprFPl <- newForeignPtr gu_pool_finalizer exprPl - let touch = touchForeignPtr exprFPl - c_expr1 <- peekElemOff triple 0 - c_expr2 <- peekElemOff triple 1 - c_expr3 <- peekElemOff triple 2 - key <- peek pKey - rest <- unsafeInterleaveIO (fetchResults res) - return ((key,fromCExpr c_expr1 touch mb_expr1 - ,fromCExpr c_expr2 touch mb_expr2 - ,fromCExpr c_expr3 touch mb_expr3) : rest) - - -query :: SG -> String -> IO [[Expr]] -query (SG sg) str = - withGuPool $ \tmpPl -> - do c_str <- newUtf8CString str tmpPl - guin <- gu_string_in c_str tmpPl - exn <- gu_new_exn tmpPl - seq <- pgf_read_expr_matrix guin 3 tmpPl exn - if seq /= nullPtr - then do count <- (#peek GuSeq, len) seq - q <- sg_query sg (count `div` 3) (seq `plusPtr` (#offset GuSeq, data)) exn - handle_sg_exn exn - n_cols <- sg_query_result_columns q - unsafeInterleaveIO (fetchResults q n_cols) - else return [] - where - fetchResults q n_cols = - withGuPool $ \tmpPl -> do - exn <- gu_new_exn tmpPl - pExprs <- gu_malloc tmpPl ((#size PgfExpr) * n_cols) - exprPl <- gu_new_pool - res <- sg_query_result_fetch q pExprs exprPl exn - failed <- gu_exn_is_raised exn - if failed - then do gu_pool_free exprPl - sg_query_result_close q exn - handle_sg_exn exn - return [] - else if res /= 0 - then do exprFPl <- newForeignPtr gu_pool_finalizer exprPl - let touch = touchForeignPtr exprFPl - row <- fmap (map (flip Expr touch)) $ peekArray (fromIntegral n_cols) pExprs - rows <- unsafeInterleaveIO (fetchResults q n_cols) - return (row:rows) - else do gu_pool_free exprPl - sg_query_result_close q exn - return [] - ------------------------------------------------------------------------ --- Exceptions - -newtype SGError = SGError String - deriving (Show, Typeable) - -instance Exception SGError - -handle_sg_exn exn = do - failed <- gu_exn_is_raised exn - if failed - then do is_sgerr <- gu_exn_caught exn gu_exn_type_SgError - if is_sgerr - then do c_msg <- (#peek GuExn, data.data) exn - msg <- peekUtf8CString c_msg - throwIO (SGError msg) - else throwIO (SGError "Unknown database error") - else return () - ------------------------------------------------------------------------ diff --git a/src/runtime/haskell-bind/SG/FFI.hs b/src/runtime/haskell-bind/SG/FFI.hs deleted file mode 100644 index ef1b06de8..000000000 --- a/src/runtime/haskell-bind/SG/FFI.hs +++ /dev/null @@ -1,84 +0,0 @@ -{-# LANGUAGE ForeignFunctionInterface, MagicHash #-} -module SG.FFI where - -import Foreign -import Foreign.C -import PGF2.FFI -import GHC.Ptr -import Data.Int - -data SgSG -data SgQueryExprResult -data SgTripleResult -data SgQueryResult -type SgId = Int64 - -foreign import ccall "sg/sg.h sg_open" - sg_open :: CString -> Ptr GuExn -> IO (Ptr SgSG) - -foreign import ccall "sg/sg.h sg_close" - sg_close :: Ptr SgSG -> Ptr GuExn -> IO () - -foreign import ccall "sg/sg.h sg_begin_trans" - sg_begin_trans :: Ptr SgSG -> Ptr GuExn -> IO () - -foreign import ccall "sg/sg.h sg_commit" - sg_commit :: Ptr SgSG -> Ptr GuExn -> IO () - -foreign import ccall "sg/sg.h sg_rollback" - sg_rollback :: Ptr SgSG -> Ptr GuExn -> IO () - -foreign import ccall "sg/sg.h sg_insert_expr" - sg_insert_expr :: Ptr SgSG -> PgfExpr -> CInt -> Ptr GuExn -> IO SgId - -foreign import ccall "sg/sg.h sg_get_expr" - sg_get_expr :: Ptr SgSG -> SgId -> Ptr GuPool -> Ptr GuExn -> IO PgfExpr - -foreign import ccall "sg/sg.h sg_query_expr" - sg_query_expr :: Ptr SgSG -> PgfExpr -> Ptr GuPool -> Ptr GuExn -> IO (Ptr SgQueryExprResult) - -foreign import ccall "sg/sg.h sg_query_next" - sg_query_next :: Ptr SgSG -> Ptr SgQueryExprResult -> Ptr SgId -> Ptr GuPool -> Ptr GuExn -> IO PgfExpr - -foreign import ccall "sg/sg.h sg_query_close" - sg_query_close :: Ptr SgSG -> Ptr SgQueryExprResult -> Ptr GuExn -> IO () - -foreign import ccall "sg/sg.h sg_update_fts_index" - sg_update_fts_index :: Ptr SgSG -> Ptr PgfPGF -> Ptr GuExn -> IO () - -foreign import ccall "sg/sg.h sg_query_linearization" - sg_query_linearization :: Ptr SgSG -> CString -> Ptr GuPool -> Ptr GuExn -> IO (Ptr GuSeq) - -foreign import ccall "sg/sg.h sg_insert_triple" - sg_insert_triple :: Ptr SgSG -> SgTriple -> Ptr GuExn -> IO SgId - -foreign import ccall "sg/sg.h sg_get_triple" - sg_get_triple :: Ptr SgSG -> SgId -> SgTriple -> Ptr GuPool -> Ptr GuExn -> IO CInt - -foreign import ccall "sg/sg.h sg_query_triple" - sg_query_triple :: Ptr SgSG -> SgTriple -> Ptr GuExn -> IO (Ptr SgTripleResult) - -foreign import ccall "sg/sg.h sg_triple_result_fetch" - sg_triple_result_fetch :: Ptr SgTripleResult -> Ptr SgId -> SgTriple -> Ptr GuPool -> Ptr GuExn -> IO CInt - -foreign import ccall "sg/sg.h sg_triple_result_close" - sg_triple_result_close :: Ptr SgTripleResult -> Ptr GuExn -> IO () - -foreign import ccall "sg/sg.h sg_query" - sg_query :: Ptr SgSG -> CSizeT -> Ptr PgfExpr -> Ptr GuExn -> IO (Ptr SgQueryResult) - -foreign import ccall "sg/sg.h sg_query_result_columns" - sg_query_result_columns :: Ptr SgQueryResult -> IO CSizeT - -foreign import ccall "sg/sg.h sg_query_result_fetch" - sg_query_result_fetch :: Ptr SgQueryResult -> Ptr PgfExpr -> Ptr GuPool -> Ptr GuExn -> IO CInt - -foreign import ccall "sg/sg.h sg_query_result_close" - sg_query_result_close :: Ptr SgQueryResult -> Ptr GuExn -> IO () - -type SgTriple = Ptr PgfExpr - -withTriple :: (SgTriple -> IO a) -> IO a -withTriple = allocaArray 3 - -gu_exn_type_SgError = Ptr "SgError"# :: CString diff --git a/src/runtime/haskell-bind/pgf2.cabal b/src/runtime/haskell-bind/pgf2.cabal index 4022f0b9b..c8d5d8c6c 100644 --- a/src/runtime/haskell-bind/pgf2.cabal +++ b/src/runtime/haskell-bind/pgf2.cabal @@ -1,37 +1,46 @@ -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.3.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 +category: Natural Language Processing +build-type: Simple +extra-source-files: CHANGELOG.md, README.md +cabal-version: >=1.10 library - exposed-modules: PGF2, PGF2.Internal, SG - -- backwards compatibility API: - --, PGF, PGF.Internal - other-modules: PGF2.FFI, PGF2.Expr, PGF2.Type, SG.FFI - 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: sg 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 <dimitri.sabadie@gmail.com> +# 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 |
