diff --git a/src/runtime/javascript/expr.ts b/src/runtime/javascript/expr.ts index fcf3bc0f0..5b6d7b90b 100644 --- a/src/runtime/javascript/expr.ts +++ b/src/runtime/javascript/expr.ts @@ -11,7 +11,16 @@ export class Hypo { } export class Expr { - dummy!: string + constructor (n?: number) { + if (n != null) { + return new ExprLit(n) + } + } + + toString (): string { + // TODO call showExpr + return this.toString() + } } export class ExprAbs extends Expr { @@ -21,7 +30,16 @@ export class ExprApp extends Expr { } export class ExprLit extends Expr { + lit: Literal + constructor (l: Literal | number | bigint | string) { + super() + if (l instanceof Literal) this.lit = l + else this.lit = new Literal(l) + } + toString (): string { + return this.lit.toString() + } } export class ExprMeta extends Expr { @@ -38,3 +56,14 @@ export class ExprTyped extends Expr { export class ExprImplArg extends Expr { } + +export class Literal { + val: number | bigint | string + constructor (v: number | bigint | string) { + this.val = v + } + + toString (): string { + return this.val.toString() + } +} diff --git a/src/runtime/javascript/ffi.ts b/src/runtime/javascript/ffi.ts index 015390c8a..89df95197 100644 --- a/src/runtime/javascript/ffi.ts +++ b/src/runtime/javascript/ffi.ts @@ -1,12 +1,65 @@ /* eslint-disable @typescript-eslint/naming-convention */ +import { + Type, + // Hypo, + ExprAbs, + ExprApp, + ExprLit, + ExprMeta, + ExprFun, + ExprVar, + ExprTyped, + ExprImplArg, + Literal +} from './expr' +import os from 'os' import ffi from 'ffi-napi' import ref, { Pointer } from 'ref-napi' import ref_struct from 'ref-struct-di' const Struct = ref_struct(ref) -export const PgfExpr = ref.refType(ref.types.void) -export const PgfLiteral = ref.refType(ref.types.void) +// ---------------------------------------------------------------------------- +// FFI "Types" + +export const voidPtr = ref.refType(ref.types.void) +const prob_t = ref.types.float +const size_t = ref.types.size_t + +const PgfDB = ref.types.void +const PgfDBPtr = ref.refType(PgfDB) + +const PgfRevision = ref.refType(ref.types.void) +export const PgfRevisionPtr = ref.refType(PgfRevision) + +export const PgfExn = Struct({ + type: ref.types.int, + code: ref.types.int, + msg: ref.types.CString +}) +export const PgfExnPtr = ref.refType(PgfExn) + +const PgfText = Struct({ + size: ref.types.size_t, + text: ref.types.char // char[] +}) +export const PgfTextPtr = ref.refType(PgfText) + +export const PgfItorPtr = ref.refType(ref.types.void) + +const PgfType = ref.types.void // TODO +// const PgfTypePtr = ref.refType(PgfType) + +const PgfTypeHypo = ref.types.void // TODO +const PgfTypeHypoPtr = ref.refType(PgfTypeHypo) + +export const PgfExpr = ref.refType(ref.types.Object) +export const PgfLiteral = ref.refType(ref.types.Object) + +const PgfMetaId = ref.types.int + +const PgfPrintContext = ref.types.void // TODO +const PgfPrintContextPtr = ref.refType(PgfPrintContext) const PgfUnmarshallerVtbl = Struct({ eabs: ref.refType(ref.types.void), @@ -23,46 +76,227 @@ const PgfUnmarshallerVtbl = Struct({ dtyp: ref.refType(ref.types.void), free_ref: ref.refType(ref.types.void) }) -export const PgfUnmarshaller = Struct({ +const PgfUnmarshaller = Struct({ vtbl: ref.refType(PgfUnmarshallerVtbl) }) +const PgfUnmarshallerPtr = ref.refType(PgfUnmarshaller) + +const PgfMarshallerVtbl = Struct({ + match_lit: ref.refType(ref.types.void), + match_expr: ref.refType(ref.types.void), + match_type: ref.refType(ref.types.void) +}) +const PgfMarshaller = Struct({ + vtbl: ref.refType(PgfMarshallerVtbl) +}) +const PgfMarshallerPtr = ref.refType(PgfMarshaller) + +// ---------------------------------------------------------------------------- +// FFI + +export const runtime = ffi.Library('libpgf', { + pgf_read_pgf: [PgfDBPtr, [ref.types.CString, 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_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]] +}) + +// ---------------------------------------------------------------------------- +// Conversion helpers + +export function PgfText_AsString (txtPtr: Pointer): string { + const txtSize = txtPtr.deref().size + const charPtr = ref.reinterpret(txtPtr, txtSize, ref.types.size_t.size) + return charPtr.toString('utf8') +} + +export function PgfText_FromString (str: string): Pointer { + const strbuf = Buffer.from(str, 'utf8') + const size = strbuf.length // size in bytes, not chars + const sizebuf = ref.alloc(ref.types.size_t, size) + const txtbuf = Buffer.alloc(ref.types.size_t.size + size + 1) + sizebuf.copy(txtbuf, 0, 0) + strbuf.copy(txtbuf, ref.types.size_t.size, 0) + return txtbuf as Pointer +} + +// ---------------------------------------------------------------------------- +// Un/marshalling + +const eabs = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.bool, PgfTextPtr, PgfExpr], + function (self, btype: boolean, name: Pointer, body: Pointer): Pointer { + return 0 as any + }) + +const eapp = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfExpr], + function (self, fun: Pointer, arg: Pointer): Pointer { + return 0 as any + }) const elit = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfLiteral], - function (self, lit: Pointer): any { // eslint-disable-line @typescript-eslint/no-unused-vars - console.log('myelit') - console.log(' lit', lit) - return lit.deref() + function (self, lit: Pointer): Pointer { + const litObj = lit.deref() as Literal + const obj = new ExprLit(litObj) + const buf = ref.alloc(ref.types.Object) as Pointer + ref.writeObject(buf, 0, obj) + return buf }) -const lint = ffi.Callback(PgfLiteral, [PgfUnmarshaller, ref.types.size_t, ref.refType(ref.types.uint)], - function (self, size: number, val: Pointer): any { // eslint-disable-line @typescript-eslint/no-unused-vars - console.log('mylint') - console.log(' size', size) - console.log(' val', val.deref()) - // const x: number = val.deref() - return val +const emeta = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfMetaId], + function (self, meta: Pointer): Pointer { + return 0 as any }) -const free_ref = ffi.Callback(ref.types.void, [PgfUnmarshaller, ref.refType(ref.types.void)], - function (self, x: any): void { // eslint-disable-line @typescript-eslint/no-unused-vars - console.log('free_ref') +const efun = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfTextPtr], + function (self, name: Pointer): Pointer { + return 0 as any }) -const vtbl = new PgfUnmarshallerVtbl({ - eabs: ref.alloc('void').ref(), - eapp: ref.alloc('void').ref(), +const evar = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.int], + function (self, index: number): Pointer { + return 0 as any + }) + +const etyped = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfType], + function (self, expr: Pointer, type: Pointer): Pointer { + return 0 as any + }) + +const eimplarg = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr], + function (self, expr: Pointer): Pointer { + return 0 as any + }) + +// TODO get from platform/runtime +const WORDSIZE_BITS = 64 +const WORDSIZE_BYTES = WORDSIZE_BITS / 8 +const LINT_BASE = BigInt('10000000000000000000') + +const lint = ffi.Callback(PgfLiteral, [PgfUnmarshaller, ref.types.size_t, ref.refType(ref.types.int)], + function (self, size: number, val: Pointer): Pointer { + let jsval: number | bigint = 0 + if (size === 1) { + jsval = val.deref() + } else if (size > 1) { + jsval = BigInt(val.deref()) + const pos = jsval >= 0 + const vals = ref.reinterpret(val, size * WORDSIZE_BYTES) + for (let n = 1; n < size; n++) { + let thisval + switch (WORDSIZE_BITS) { + case 64: + thisval = BigInt((os.endianness() === 'LE') ? vals.readUInt64LE(n * WORDSIZE_BYTES) : vals.readUInt64BE(n * WORDSIZE_BYTES)) + } + if (thisval == null) { + throw Error(`Unsupported word size: ${WORDSIZE_BITS}`) + } + jsval = (jsval * LINT_BASE) + (pos ? thisval : -thisval) + } + } + + const obj = new Literal(jsval) + const buf = ref.alloc(ref.types.Object) as Pointer + ref.writeObject(buf, 0, obj) + return buf + }) + +const lflt = ffi.Callback(PgfLiteral, [PgfUnmarshaller, ref.types.double], + function (self, val: number): Pointer { + const obj = new Literal(val) + const buf = ref.alloc(ref.types.Object) as Pointer + ref.writeObject(buf, 0, obj) + return buf + }) + +const lstr = ffi.Callback(PgfLiteral, [PgfUnmarshaller, PgfTextPtr], + function (self, val: Pointer): Pointer { + const jsval = PgfText_AsString(val) + const obj = new Literal(jsval) + const buf = ref.alloc(ref.types.Object) as Pointer + ref.writeObject(buf, 0, obj) + return buf + }) + +const dtyp = ffi.Callback(PgfType, [PgfUnmarshaller, ref.types.int, PgfTypeHypoPtr, PgfTextPtr, ref.types.int, ref.refType(PgfExpr)], + function (self, n_hypos: number, hypos: Pointer, cat: Pointer, n_exprs: number, exprs: Pointer): Pointer { + return 0 as any + }) + +const free_ref = ffi.Callback(ref.types.void, [PgfUnmarshaller, ref.refType(ref.types.Object)], + function (self, x: Pointer): void { + }) + +const un_vtbl = new PgfUnmarshallerVtbl({ + eabs: eabs as any, + eapp: eapp as any, elit: elit as any, - emeta: ref.alloc('void').ref(), - efun: ref.alloc('void').ref(), - evar: ref.alloc('void').ref(), - etyped: ref.alloc('void').ref(), - eimplarg: ref.alloc('void').ref(), + emeta: emeta as any, + efun: efun as any, + evar: evar as any, + etyped: etyped as any, + eimplarg: eimplarg as any, lint: lint as any, - lflt: ref.alloc('void').ref(), - lstr: ref.alloc('void').ref(), - dtyp: ref.alloc('void').ref(), + lflt: lflt as any, + lstr: lstr as any, + dtyp: dtyp as any, free_ref: free_ref as any }) -export const unmarshaller = new PgfUnmarshaller({ vtbl: vtbl.ref() }) -export const marshaller = {} +export const unmarshaller = new PgfUnmarshaller({ vtbl: un_vtbl.ref() }) + +const match_lit = ffi.Callback(ref.types.Object, [PgfMarshaller, PgfUnmarshaller, PgfLiteral], + function (self, u: any, lit: any): Pointer { + return 0 as any + }) + +const match_expr = ffi.Callback(ref.types.Object, [PgfMarshaller, PgfUnmarshaller, PgfExpr], + function (self, u: any, expr: any): Pointer { + return 0 as any + }) + +const match_type = ffi.Callback(ref.types.Object, [PgfMarshaller, PgfUnmarshaller, PgfType], + function (self, u: any, type: any): Pointer { + return 0 as any + }) + +const vtbl = new PgfMarshallerVtbl({ + match_lit: match_lit as any, + match_expr: match_expr as any, + match_type: match_type as any +}) + +export const marshaller = new PgfMarshaller({ vtbl: vtbl.ref() }) diff --git a/src/runtime/javascript/index.ts b/src/runtime/javascript/index.ts index 8b2079436..d22294563 100644 --- a/src/runtime/javascript/index.ts +++ b/src/runtime/javascript/index.ts @@ -1,59 +1,25 @@ /* eslint-disable @typescript-eslint/naming-convention */ import errno from './errno' -import { Expr } from './expr' -import { unmarshaller, PgfUnmarshaller, PgfExpr, PgfLiteral } from './ffi' +import { Expr, ExprLit } from './expr' +import { + voidPtr, + PgfRevisionPtr, + PgfItorPtr, + PgfTextPtr, + PgfExn, + PgfExnPtr, + + PgfText_AsString, + PgfText_FromString, + + runtime, + unmarshaller +} from './ffi' import ffi from 'ffi-napi' import ref, { Pointer } from 'ref-napi' -import ref_struct, { StructObject } from 'ref-struct-di' -const Struct = ref_struct(ref) - -// ---------------------------------------------------------------------------- -// 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.void -const PgfDBPtr = ref.refType(PgfDB) - -const PgfRevision = ref.refType(ref.types.void) -const PgfRevisionPtr = ref.refType(PgfRevision) - -const PgfExn = Struct({ - type: ref.types.int, - code: ref.types.int, - msg: ref.types.CString -}) -const PgfExnPtr = ref.refType(PgfExn) - -const PgfText = Struct({ - size: ref.types.size_t, - text: ref.types.char // char[] -}) -const PgfTextPtr = ref.refType(PgfText) - -const PgfItorPtr = ref.refType(ref.types.void) - -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) +import { StructObject } from 'ref-struct-di' // ---------------------------------------------------------------------------- // TypeScript Types @@ -72,50 +38,6 @@ class PGFError extends Error { } } -// ---------------------------------------------------------------------------- -// FFI - -const runtime = ffi.Library('libpgf', { - pgf_read_pgf: [PgfDBPtr, [ref.types.CString, 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_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]] -}) - // ---------------------------------------------------------------------------- // Helpers @@ -142,22 +64,6 @@ function handleError (err: StructObject): void { } } -function PgfText_AsString (txtPtr: Pointer): string { - const txtSize = txtPtr.deref().size - const charPtr = ref.reinterpret(txtPtr, txtSize, ref.types.size_t.size) - return charPtr.toString('utf8') -} - -function PgfText_FromString (str: string): Pointer { - const strbuf = Buffer.from(str, 'utf8') - const size = strbuf.length // size in bytes, not chars - const sizebuf = ref.alloc(ref.types.size_t, size) - const txtbuf = Buffer.alloc(ref.types.size_t.size + size + 1) - sizebuf.copy(txtbuf, 0, 0) - strbuf.copy(txtbuf, ref.types.size_t.size, 0) - return txtbuf as Pointer -} - // ---------------------------------------------------------------------------- // PGF grammar object @@ -185,7 +91,7 @@ export class PGFGrammar { getCategories (): string[] { const cats: string[] = [] const callback = ffi.Callback(ref.types.void, [PgfItorPtr, PgfTextPtr, voidPtr, PgfExnPtr], - function (self: Pointer, key: Pointer, value: Pointer, err: Pointer) { // eslint-disable-line @typescript-eslint/no-unused-vars + function (self: Pointer, key: Pointer, value: Pointer, err: Pointer) { const k = PgfText_AsString(key) cats.push(k) }) @@ -198,7 +104,7 @@ export class PGFGrammar { getFunctions (): string[] { const funs: string[] = [] const callback = ffi.Callback(ref.types.void, [PgfItorPtr, PgfTextPtr, voidPtr, PgfExnPtr], - function (self: Pointer, key: Pointer, value: Pointer, err: Pointer) { // eslint-disable-line @typescript-eslint/no-unused-vars + function (self: Pointer, key: Pointer, value: Pointer, err: Pointer) { const k = PgfText_AsString(key) funs.push(k) }) @@ -244,7 +150,7 @@ export class PGFGrammar { const catname = PgfText_FromString(cat) const funs: string[] = [] const callback = ffi.Callback(ref.types.void, [PgfItorPtr, PgfTextPtr, voidPtr, PgfExnPtr], - function (self: Pointer, key: Pointer, value: Pointer, err: Pointer) { // eslint-disable-line @typescript-eslint/no-unused-vars + function (self: Pointer, key: Pointer, value: Pointer, err: Pointer) { const k = PgfText_AsString(key) funs.push(k) }) @@ -295,9 +201,7 @@ function newNGF (abstract_name: string, path?: string): PGFGrammar { function readExpr (str: string): Expr { const txt = PgfText_FromString(str) const expr = runtime.pgf_read_expr(txt, unmarshaller.ref()) - console.log('expr', expr) - - return new Expr() + return ref.readObject(expr) as Expr } // ---------------------------------------------------------------------------- @@ -310,5 +214,8 @@ export default { readNGF, newNGF, - readExpr + readExpr, + + Expr, + ExprLit } diff --git a/src/runtime/javascript/tests/basic.test.ts b/src/runtime/javascript/tests/basic.test.ts index ae2839ce2..f2303521e 100644 --- a/src/runtime/javascript/tests/basic.test.ts +++ b/src/runtime/javascript/tests/basic.test.ts @@ -206,3 +206,83 @@ describe('abstract syntax', () => { }) }) }) + +// ---------------------------------------------------------------------------- + +describe('expressions', () => { + test('small integer', () => { + const e1 = PGF.readExpr('123') + const e2 = new PGF.ExprLit(123) + const e3 = new PGF.ExprLit(456) + expect(e1).toEqual(e2) + expect(e1).not.toEqual(e3) + }) + + test('negative integer', () => { + const e1 = PGF.readExpr('-123') + const e2 = new PGF.ExprLit(-123) + const e3 = new PGF.ExprLit(-456) + expect(e1).toEqual(e2) + expect(e1).not.toEqual(e3) + }) + + test('big integer', () => { + const e1 = PGF.readExpr('774763251095801167872') + const e2 = new PGF.ExprLit(BigInt('774763251095801167872')) + expect(e1).toEqual(e2) + }) + + test('negative big integer', () => { + const e1 = PGF.readExpr('-774763251095801167872') + const e2 = new PGF.ExprLit(BigInt('-774763251095801167872')) + expect(e1).toEqual(e2) + }) + + test('really big integer', () => { + const e1 = PGF.readExpr('7747632510958011678729003251095801167999') + const e2 = new PGF.ExprLit(BigInt('7747632510958011678729003251095801167999')) + const e3 = new PGF.ExprLit(BigInt('7747632510958011678729003251095801167990')) + expect(e1).toEqual(e2) + expect(e1).not.toEqual(e3) + }) + + test('negative really big integer', () => { + const e1 = PGF.readExpr('-7747632510958011678729003251095801167999') + const e2 = new PGF.ExprLit(BigInt('-7747632510958011678729003251095801167999')) + const e3 = new PGF.ExprLit(BigInt('-7747632510958011678729003251095801167990')) + expect(e1).toEqual(e2) + expect(e1).not.toEqual(e3) + }) + + test('float', () => { + const e1 = PGF.readExpr('3.142') + const e2 = new PGF.ExprLit(3.142) + const e3 = new PGF.ExprLit(2.014) + expect(e1).toEqual(e2) + expect(e1).not.toEqual(e3) + }) + + test('negative float', () => { + const e1 = PGF.readExpr('-3.142') + const e2 = new PGF.ExprLit(-3.142) + const e3 = new PGF.ExprLit(-2.014) + expect(e1).toEqual(e2) + expect(e1).not.toEqual(e3) + }) + + test('string', () => { + const e1 = PGF.readExpr('"abc"') + const e2 = new PGF.ExprLit('abc') + const e3 = new PGF.ExprLit('def') + expect(e1).toEqual(e2) + expect(e1).not.toEqual(e3) + }) + + test('string unicode', () => { + const e1 = PGF.readExpr('"açġħ"') + const e2 = new PGF.ExprLit('açġħ') + const e3 = new PGF.ExprLit('acgh') + expect(e1).toEqual(e2) + expect(e1).not.toEqual(e3) + }) +}) diff --git a/src/runtime/javascript/tsconfig.json b/src/runtime/javascript/tsconfig.json index 663573160..ef83dd09b 100644 --- a/src/runtime/javascript/tsconfig.json +++ b/src/runtime/javascript/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "ES2015", "module": "commonjs", "rootDir": "./", "moduleResolution": "node", diff --git a/src/runtime/typescript/MOVED.md b/src/runtime/typescript/MOVED.md deleted file mode 100644 index 3648aa226..000000000 --- a/src/runtime/typescript/MOVED.md +++ /dev/null @@ -1,7 +0,0 @@ -# Project moved - -The GF TypeScript runtime has been moved to the repository: - - -If you are looking for an updated version of the JavaScript runtime, -you should also look there.