mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-24 03:52:50 -06:00
Add FFI bindings for all API functions. Implement getCategories and getFunctions
This commit is contained in:
2
.github/workflows/build-majestic.yml
vendored
2
.github/workflows/build-majestic.yml
vendored
@@ -58,7 +58,7 @@ jobs:
|
|||||||
pytest
|
pytest
|
||||||
|
|
||||||
- name: Run JavaScript testsuite
|
- name: Run JavaScript testsuite
|
||||||
working-directory: ./src/runtime/python
|
working-directory: ./src/runtime/javascript
|
||||||
env:
|
env:
|
||||||
LD_LIBRARY_PATH: /usr/local/lib
|
LD_LIBRARY_PATH: /usr/local/lib
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -1,31 +1,62 @@
|
|||||||
import errno from './errno'
|
import errno from './errno'
|
||||||
import ffi from 'ffi'
|
import ffi from 'ffi'
|
||||||
import { deref } from 'ref'
|
|
||||||
import ref from 'ref'
|
import ref from 'ref'
|
||||||
import Struct from 'ref-struct'
|
import Struct from 'ref-struct'
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// FFI "Types"
|
// FFI "Types"
|
||||||
|
|
||||||
|
const voidPtr = ref.refType(ref.types.void)
|
||||||
|
const prob_t = ref.types.float
|
||||||
|
const size_t = ref.types.size_t
|
||||||
|
|
||||||
const PgfDB = ref.types.int
|
const PgfDB = ref.types.int
|
||||||
const PgfDBPtr = ref.refType(PgfDB)
|
const PgfDBPtr = ref.refType(PgfDB)
|
||||||
|
|
||||||
const PgfRevision = ref.types.int
|
const PgfRevision = ref.types.int
|
||||||
const PgfRevisionPtr = ref.refType(PgfRevision)
|
const PgfRevisionPtr = ref.refType(PgfRevision)
|
||||||
|
|
||||||
const PgfExn = Struct({
|
const PgfExn = Struct({
|
||||||
type: ref.types.int,
|
type: ref.types.int,
|
||||||
code: ref.types.int,
|
code: ref.types.int,
|
||||||
msg: ref.types.CString
|
msg: ref.types.CString
|
||||||
})
|
})
|
||||||
const PgfExnPtr = ref.refType(PgfExn)
|
const PgfExnPtr = ref.refType(PgfExn)
|
||||||
|
|
||||||
const PgfText = Struct({
|
const PgfText = Struct({
|
||||||
size: ref.types.size_t,
|
size: ref.types.size_t,
|
||||||
text: ref.types.char // char[]
|
text: ref.types.char // char[]
|
||||||
})
|
})
|
||||||
const PgfTextPtr = ref.refType(PgfText)
|
const PgfTextPtr = ref.refType(PgfText)
|
||||||
|
|
||||||
|
const PgfItor = Struct({
|
||||||
|
fn: voidPtr
|
||||||
|
})
|
||||||
|
const PgfItorPtr = ref.refType(PgfItor)
|
||||||
|
|
||||||
|
const PgfType = ref.types.void // TODO
|
||||||
|
const PgfTypePtr = ref.refType(PgfType)
|
||||||
|
|
||||||
|
const PgfTypeHypo = ref.types.void // TODO
|
||||||
|
const PgfTypeHypoPtr = ref.refType(PgfTypeHypo)
|
||||||
|
|
||||||
|
const PgfExpr = ref.types.void // TODO
|
||||||
|
const PgfLiteral = ref.types.void // TODO
|
||||||
|
|
||||||
|
const PgfPrintContext = ref.types.void // TODO
|
||||||
|
const PgfPrintContextPtr = ref.refType(PgfPrintContext)
|
||||||
|
|
||||||
|
const PgfUnmarshaller = ref.types.void // TODO
|
||||||
|
const PgfUnmarshallerPtr = ref.refType(PgfUnmarshaller)
|
||||||
|
|
||||||
|
const PgfMarshaller = ref.types.void // TODO
|
||||||
|
const PgfMarshallerPtr = ref.refType(PgfMarshaller)
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// TypeScript Types
|
// TypeScript Types
|
||||||
|
|
||||||
|
// Type definitions for `ref` package don't include extensions to Buffer
|
||||||
interface Pointer extends Buffer {
|
interface Pointer extends Buffer {
|
||||||
deref(): any
|
deref(): any
|
||||||
}
|
}
|
||||||
@@ -41,8 +72,43 @@ class PGFError extends Error {
|
|||||||
|
|
||||||
const runtime = ffi.Library('libpgf', {
|
const runtime = ffi.Library('libpgf', {
|
||||||
'pgf_read_pgf': [ PgfDBPtr, [ ref.types.CString, PgfRevisionPtr, PgfExnPtr ] ],
|
'pgf_read_pgf': [ PgfDBPtr, [ ref.types.CString, PgfRevisionPtr, PgfExnPtr ] ],
|
||||||
'pgf_write_pgf': [ ref.types.void, [ ref.types.CString, PgfDBPtr, PgfRevisionPtr, PgfExnPtr ] ],
|
'pgf_boot_ngf': [ PgfDBPtr, [ ref.types.CString, ref.types.CString, PgfRevisionPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_read_ngf': [ PgfDBPtr, [ ref.types.CString, PgfRevisionPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_new_ngf': [ PgfDBPtr, [ PgfTextPtr, ref.types.CString, PgfRevisionPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_write_pgf': [ ref.types.void, [ ref.types.CString, PgfDBPtr, PgfRevision, PgfExnPtr ] ],
|
||||||
|
|
||||||
|
'pgf_free_revision': [ ref.types.void, [ PgfDBPtr, PgfRevision ] ],
|
||||||
|
|
||||||
'pgf_abstract_name': [ PgfTextPtr, [ PgfDBPtr, PgfRevision, PgfExnPtr ] ],
|
'pgf_abstract_name': [ PgfTextPtr, [ PgfDBPtr, PgfRevision, PgfExnPtr ] ],
|
||||||
|
'pgf_iter_categories': [ ref.types.void, [ PgfDBPtr, PgfRevision, PgfItorPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_start_cat': [ PgfType, [ PgfDBPtr, PgfRevision, PgfUnmarshallerPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_category_context': [ PgfTypeHypoPtr, [ PgfDBPtr, PgfRevision, PgfTextPtr, ref.refType(ref.types.size_t), PgfUnmarshallerPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_category_prob': [ prob_t, [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_iter_functions': [ ref.types.void, [ PgfDBPtr, PgfRevision, PgfItorPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_iter_functions_by_cat': [ ref.types.void, [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfItorPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_function_type': [ PgfType, [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfUnmarshallerPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_function_is_constructor': [ ref.types.int, [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_function_prob': [ prob_t, [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_print_expr': [ PgfTextPtr, [ PgfExpr, PgfPrintContextPtr, ref.types.int, PgfMarshallerPtr ] ],
|
||||||
|
'pgf_read_expr': [ PgfExpr, [ PgfTextPtr, PgfUnmarshallerPtr ] ],
|
||||||
|
'pgf_read_expr_ex': [ PgfExpr , [ PgfTextPtr, ref.refType(ref.types.CString), PgfUnmarshallerPtr ] ],
|
||||||
|
'pgf_expr_prob': [ prob_t , [ PgfDBPtr, PgfRevision, PgfExpr, PgfMarshallerPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_print_type': [ PgfTextPtr, [ PgfType, PgfPrintContextPtr, ref.types.int, PgfMarshallerPtr ] ],
|
||||||
|
'pgf_print_context': [ PgfTextPtr, [ size_t, PgfTypeHypoPtr, PgfPrintContextPtr, ref.types.int, PgfMarshallerPtr ] ],
|
||||||
|
'pgf_read_type': [ PgfType , [ PgfTextPtr, PgfUnmarshallerPtr ] ],
|
||||||
|
|
||||||
|
'pgf_clone_revision': [ PgfRevision , [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_commit_revision': [ ref.types.void, [ PgfDBPtr, PgfRevision, PgfExnPtr ] ],
|
||||||
|
'pgf_checkout_revision': [ PgfRevision , [ PgfDBPtr, PgfTextPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_create_function': [ ref.types.void, [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfType, size_t, prob_t, PgfMarshallerPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_drop_function': [ ref.types.void, [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_create_category': [ ref.types.void, [ PgfDBPtr, PgfRevision, PgfTextPtr, size_t, PgfTypeHypoPtr, prob_t, PgfMarshallerPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_drop_category': [ ref.types.void, [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfExnPtr ] ],
|
||||||
|
|
||||||
|
'pgf_get_global_flag': [ PgfLiteral , [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfUnmarshallerPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_set_global_flag': [ ref.types.void, [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfLiteral, PgfMarshallerPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_get_abstract_flag': [ PgfLiteral , [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfUnmarshallerPtr, PgfExnPtr ] ],
|
||||||
|
'pgf_set_abstract_flag': [ ref.types.void, [ PgfDBPtr, PgfRevision, PgfTextPtr, PgfLiteral, PgfMarshallerPtr, PgfExnPtr ] ],
|
||||||
})
|
})
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -90,6 +156,11 @@ class PGF {
|
|||||||
this.revision = 0
|
this.revision = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NB the library user is responsible for calling this
|
||||||
|
destructor () {
|
||||||
|
runtime.pgf_free_revision(this.db, this.revision)
|
||||||
|
}
|
||||||
|
|
||||||
getAbstractName () {
|
getAbstractName () {
|
||||||
const err = ref.alloc(PgfExn) as Pointer
|
const err = ref.alloc(PgfExn) as Pointer
|
||||||
const txt = runtime.pgf_abstract_name(this.db, this.revision, err)
|
const txt = runtime.pgf_abstract_name(this.db, this.revision, err)
|
||||||
@@ -97,6 +168,32 @@ class PGF {
|
|||||||
return PgfText_AsString(txt)
|
return PgfText_AsString(txt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCategories () {
|
||||||
|
const cats = new Array()
|
||||||
|
const callback = ffi.Callback(ref.types.void, [ PgfItorPtr, PgfTextPtr, voidPtr, PgfExnPtr],
|
||||||
|
function (self: Pointer, key: Pointer, value: Pointer, err: Pointer) {
|
||||||
|
const k = PgfText_AsString(key)
|
||||||
|
cats.push(k)
|
||||||
|
})
|
||||||
|
const err = ref.alloc(PgfExn) as Pointer
|
||||||
|
runtime.pgf_iter_categories(this.db, this.revision, ref.ref(callback), err)
|
||||||
|
handleError(err)
|
||||||
|
return cats
|
||||||
|
}
|
||||||
|
|
||||||
|
getFunctions () {
|
||||||
|
const funs = new Array()
|
||||||
|
const callback = ffi.Callback(ref.types.void, [ PgfItorPtr, PgfTextPtr, voidPtr, PgfExnPtr],
|
||||||
|
function (self: Pointer, key: Pointer, value: Pointer, err: Pointer) {
|
||||||
|
const k = PgfText_AsString(key)
|
||||||
|
funs.push(k)
|
||||||
|
})
|
||||||
|
const err = ref.alloc(PgfExn) as Pointer
|
||||||
|
runtime.pgf_iter_functions(this.db, this.revision, ref.ref(callback), err)
|
||||||
|
handleError(err)
|
||||||
|
return funs
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -120,3 +217,9 @@ function readPGF (path: string): PGF {
|
|||||||
export default {
|
export default {
|
||||||
readPGF
|
readPGF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Quick testing
|
||||||
|
|
||||||
|
// const gr: PGF = readPGF('../haskell/tests/basic.pgf')
|
||||||
|
// console.log(gr.getCategories())
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
preset: 'ts-jest',
|
preset: 'ts-jest',
|
||||||
testEnvironment: 'node'
|
testEnvironment: 'node',
|
||||||
};
|
testPathIgnorePatterns: [
|
||||||
|
'<rootDir>/dist/',
|
||||||
|
'<rootDir>/node_modules/'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import PGF from '../index'
|
import PGF from '../index'
|
||||||
|
|
||||||
|
// readPGF
|
||||||
|
|
||||||
test('readPGF successful', () => {
|
test('readPGF successful', () => {
|
||||||
let gr = PGF.readPGF('../haskell/tests/basic.pgf')
|
let gr = PGF.readPGF('../haskell/tests/basic.pgf')
|
||||||
})
|
})
|
||||||
@@ -10,7 +12,19 @@ test('readPGF missing file', () => {
|
|||||||
}).toThrow()
|
}).toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// abstract syntax
|
||||||
|
|
||||||
test('abstract name', () => {
|
test('abstract name', () => {
|
||||||
let gr = PGF.readPGF('../haskell/tests/basic.pgf')
|
let gr = PGF.readPGF('../haskell/tests/basic.pgf')
|
||||||
expect(gr.getAbstractName()).toBe('basic')
|
expect(gr.getAbstractName()).toBe('basic')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('categories', () => {
|
||||||
|
let gr = PGF.readPGF('../haskell/tests/basic.pgf')
|
||||||
|
expect(gr.getCategories()).toEqual(['Float','Int','N','P','S','String'])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('functions', () => {
|
||||||
|
let gr = PGF.readPGF('../haskell/tests/basic.pgf')
|
||||||
|
expect(gr.getFunctions()).toEqual(['c','ind','s','z'])
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user