1
0
forked from GitHub/gf-core

Implement all Expr unmarshalling (untested). Put wordsize logic in constants.ts. Some README additions.

This commit is contained in:
John J. Camilleri
2021-10-08 12:39:42 +02:00
parent 15e3ca9acd
commit a27cf6a17b
5 changed files with 178 additions and 28 deletions

View File

@@ -2,7 +2,9 @@
## Requirements ## Requirements
Required system packages (Debian/Ubuntu): ### Debian/Ubuntu
Required system packages (`apt install ...`):
``` ```
autoconf autoconf
automake automake
@@ -11,6 +13,11 @@ make
g++ g++
``` ```
### macOS
- Install XCode from App Store
- Install XCode command line tools: `xcode-select --install`
## Installation ## Installation
Installing the runtime (puts libraries in `/usr/local/lib`): Installing the runtime (puts libraries in `/usr/local/lib`):

View File

@@ -30,3 +30,12 @@ npm run build
``` ```
npm run test npm run test
``` ```
## Known issues
There is a known issue with random crashes with Node 14 and 16 on macOS. See here:
- https://github.com/nodejs/node/issues/32463
- https://github.com/node-ffi-napi/node-ffi-napi/issues/97
- https://github.com/node-ffi-napi/ref-napi/issues/47
It seems to work with Node 12 on macOS, as well as on other platforms.

View File

@@ -0,0 +1,39 @@
// Untested!
import os from 'os'
export const BE: boolean = os.endianness() === 'BE'
export let WORDSIZE_BITS: number
switch (process.arch) {
case 'arm':
case 'ia32':
case 'ppc':
case 's390':
case 'x32':
WORDSIZE_BITS = 32
break
case 'arm64':
case 'mips':
case 'mipsel':
case 'ppc64':
case 's390x':
case 'x64':
WORDSIZE_BITS = 64
break
default:
throw Error(`Unknown architecture: ${process.arch}`)
}
export const WORDSIZE_BYTES = WORDSIZE_BITS / 8
export let LINT_BASE: bigint
switch (WORDSIZE_BITS) {
case 64: LINT_BASE = BigInt('10000000000000000000'); break
case 32: LINT_BASE = BigInt('1000000000'); break
case 16: LINT_BASE = BigInt('10000'); break
case 8: LINT_BASE = BigInt('100'); break
default: throw Error(`Unsupported word size: ${WORDSIZE_BITS}`)
}

View File

@@ -1,7 +1,13 @@
export class Type { export class Type {
hypos!: Hypo[] hypos: Hypo[]
name!: string name: string
exprs!: Expr[] exprs: Expr[]
constructor (hs: Hypo[], n: string, es: Expr[]) {
this.hypos = hs
this.name = n
this.exprs = es
}
} }
export class Hypo { export class Hypo {
@@ -11,6 +17,7 @@ export class Hypo {
} }
export class Expr { export class Expr {
// TODO overload
constructor (n?: number) { constructor (n?: number) {
if (n != null) { if (n != null) {
return new ExprLit(n) return new ExprLit(n)
@@ -24,13 +31,32 @@ export class Expr {
} }
export class ExprAbs extends Expr { export class ExprAbs extends Expr {
bind_type: boolean
name: string
body: Expr
constructor (bt: boolean, n: string, b: Expr) {
super()
this.bind_type = bt
this.name = n
this.body = b
} }
}
export class ExprApp extends Expr { export class ExprApp extends Expr {
fun: Expr
arg: Expr
constructor (f: Expr, a: Expr) {
super()
this.fun = f
this.arg = a
} }
}
export class ExprLit extends Expr { export class ExprLit extends Expr {
lit: Literal lit: Literal
constructor (l: Literal | number | bigint | string) { constructor (l: Literal | number | bigint | string) {
super() super()
if (l instanceof Literal) this.lit = l if (l instanceof Literal) this.lit = l
@@ -41,24 +67,57 @@ export class ExprLit extends Expr {
return this.lit.toString() return this.lit.toString()
} }
} }
export class ExprMeta extends Expr { export class ExprMeta extends Expr {
id: number
constructor (i: number) {
super()
this.id = i
} }
}
export class ExprFun extends Expr { export class ExprFun extends Expr {
name: string
constructor (n: string) {
super()
this.name = n
} }
}
export class ExprVar extends Expr { export class ExprVar extends Expr {
var: number
constructor (v: number) {
super()
this.var = v
} }
}
export class ExprTyped extends Expr { export class ExprTyped extends Expr {
expr: Expr
type: Type
constructor (e: Expr, t: Type) {
super()
this.expr = e
this.type = t
}
} }
export class ExprImplArg extends Expr {
export class ExprImplArg extends Expr {
expr: Expr
constructor (e: Expr) {
super()
this.expr = e
}
} }
export class Literal { export class Literal {
val: number | bigint | string val: number | bigint | string
constructor (v: number | bigint | string) { constructor (v: number | bigint | string) {
this.val = v this.val = v
} }

View File

@@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable @typescript-eslint/naming-convention */
import { import {
Type, Type,
// Hypo, Hypo,
Expr,
ExprAbs, ExprAbs,
ExprApp, ExprApp,
ExprLit, ExprLit,
@@ -12,8 +13,8 @@ import {
ExprImplArg, ExprImplArg,
Literal Literal
} from './expr' } from './expr'
import { BE, WORDSIZE_BITS, WORDSIZE_BYTES, LINT_BASE } from './constants'
import os from 'os'
import ffi from 'ffi-napi' import ffi from 'ffi-napi'
import ref, { Pointer } from 'ref-napi' import ref, { Pointer } from 'ref-napi'
import ref_struct from 'ref-struct-di' import ref_struct from 'ref-struct-di'
@@ -47,7 +48,7 @@ export const PgfTextPtr = ref.refType(PgfText)
export const PgfItorPtr = ref.refType(ref.types.void) export const PgfItorPtr = ref.refType(ref.types.void)
const PgfType = ref.types.void // TODO const PgfType = ref.refType(ref.types.Object) // TODO
// const PgfTypePtr = ref.refType(PgfType) // const PgfTypePtr = ref.refType(PgfType)
const PgfTypeHypo = ref.types.void // TODO const PgfTypeHypo = ref.types.void // TODO
@@ -159,17 +160,24 @@ export function PgfText_FromString (str: string): Pointer<any> {
const eabs = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.bool, PgfTextPtr, PgfExpr], const eabs = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.bool, PgfTextPtr, PgfExpr],
function (self, btype: boolean, name: Pointer<any>, body: Pointer<any>): Pointer<ExprAbs> { function (self, btype: boolean, name: Pointer<any>, body: Pointer<any>): Pointer<ExprAbs> {
return 0 as any const jsname = PgfText_AsString(name)
const obj = new ExprAbs(btype, jsname, body) // TODO check body
const buf = ref.alloc(ref.types.Object) as Pointer<ExprAbs>
ref.writeObject(buf, 0, obj)
return buf
}) })
const eapp = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfExpr], const eapp = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfExpr],
function (self, fun: Pointer<any>, arg: Pointer<any>): Pointer<ExprApp> { function (self, fun: Pointer<Expr>, arg: Pointer<Type>): Pointer<ExprApp> {
return 0 as any const obj = new ExprApp(fun, arg) // TODO check
const buf = ref.alloc(ref.types.Object) as Pointer<ExprApp>
ref.writeObject(buf, 0, obj)
return buf
}) })
const elit = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfLiteral], const elit = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfLiteral],
function (self, lit: Pointer<any>): Pointer<ExprLit> { function (self, lit: Pointer<Literal>): Pointer<ExprLit> {
const litObj = lit.deref() as Literal const litObj = lit.deref()
const obj = new ExprLit(litObj) const obj = new ExprLit(litObj)
const buf = ref.alloc(ref.types.Object) as Pointer<ExprLit> const buf = ref.alloc(ref.types.Object) as Pointer<ExprLit>
ref.writeObject(buf, 0, obj) ref.writeObject(buf, 0, obj)
@@ -177,35 +185,46 @@ const elit = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfLiteral],
}) })
const emeta = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfMetaId], const emeta = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfMetaId],
function (self, meta: Pointer<any>): Pointer<ExprMeta> { function (self, meta: number): Pointer<ExprMeta> {
return 0 as any const obj = new ExprMeta(meta)
const buf = ref.alloc(ref.types.Object) as Pointer<ExprMeta>
ref.writeObject(buf, 0, obj)
return buf
}) })
const efun = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfTextPtr], const efun = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfTextPtr],
function (self, name: Pointer<any>): Pointer<ExprFun> { function (self, name: Pointer<any>): Pointer<ExprFun> {
return 0 as any const jsname = PgfText_AsString(name)
const obj = new ExprFun(jsname)
const buf = ref.alloc(ref.types.Object) as Pointer<ExprFun>
ref.writeObject(buf, 0, obj)
return buf
}) })
const evar = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.int], const evar = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.int],
function (self, index: number): Pointer<ExprVar> { function (self, index: number): Pointer<ExprVar> {
return 0 as any const obj = new ExprVar(index)
const buf = ref.alloc(ref.types.Object) as Pointer<ExprVar>
ref.writeObject(buf, 0, obj)
return buf
}) })
const etyped = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfType], const etyped = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfType],
function (self, expr: Pointer<any>, type: Pointer<any>): Pointer<ExprTyped> { function (self, expr: Pointer<Expr>, type: Pointer<Type>): Pointer<ExprTyped> {
return 0 as any const obj = new ExprTyped(expr, type.deref()) // TODO check
const buf = ref.alloc(ref.types.Object) as Pointer<ExprTyped>
ref.writeObject(buf, 0, obj)
return buf
}) })
const eimplarg = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr], const eimplarg = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr],
function (self, expr: Pointer<any>): Pointer<ExprImplArg> { function (self, expr: Pointer<Expr>): Pointer<ExprImplArg> {
return 0 as any const obj = new ExprImplArg(expr) // TODO check
const buf = ref.alloc(ref.types.Object) as Pointer<ExprImplArg>
ref.writeObject(buf, 0, obj)
return buf
}) })
// 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)], const lint = ffi.Callback(PgfLiteral, [PgfUnmarshaller, ref.types.size_t, ref.refType(ref.types.int)],
function (self, size: number, val: Pointer<number>): Pointer<Literal> { function (self, size: number, val: Pointer<number>): Pointer<Literal> {
let jsval: number | bigint = 0 let jsval: number | bigint = 0
@@ -219,7 +238,17 @@ const lint = ffi.Callback(PgfLiteral, [PgfUnmarshaller, ref.types.size_t, ref.re
let thisval let thisval
switch (WORDSIZE_BITS) { switch (WORDSIZE_BITS) {
case 64: case 64:
thisval = BigInt((os.endianness() === 'LE') ? vals.readUInt64LE(n * WORDSIZE_BYTES) : vals.readUInt64BE(n * WORDSIZE_BYTES)) thisval = BigInt(BE ? vals.readUInt64BE(n * WORDSIZE_BYTES) : vals.readUInt64LE(n * WORDSIZE_BYTES))
break
case 32:
thisval = BigInt(BE ? vals.readUInt32BE(n * WORDSIZE_BYTES) : vals.readUInt32LE(n * WORDSIZE_BYTES))
break
case 16:
thisval = BigInt(BE ? vals.readUInt16BE(n * WORDSIZE_BYTES) : vals.readUInt16LE(n * WORDSIZE_BYTES))
break
case 8:
thisval = BigInt(vals.readUInt8(n * WORDSIZE_BYTES))
break
} }
if (thisval == null) { if (thisval == null) {
throw Error(`Unsupported word size: ${WORDSIZE_BITS}`) throw Error(`Unsupported word size: ${WORDSIZE_BITS}`)
@@ -253,7 +282,14 @@ const lstr = ffi.Callback(PgfLiteral, [PgfUnmarshaller, PgfTextPtr],
const dtyp = ffi.Callback(PgfType, [PgfUnmarshaller, ref.types.int, PgfTypeHypoPtr, PgfTextPtr, ref.types.int, ref.refType(PgfExpr)], const dtyp = ffi.Callback(PgfType, [PgfUnmarshaller, ref.types.int, PgfTypeHypoPtr, PgfTextPtr, ref.types.int, ref.refType(PgfExpr)],
function (self, n_hypos: number, hypos: Pointer<any>, cat: Pointer<any>, n_exprs: number, exprs: Pointer<any>): Pointer<Type> { function (self, n_hypos: number, hypos: Pointer<any>, cat: Pointer<any>, n_exprs: number, exprs: Pointer<any>): Pointer<Type> {
return 0 as any // TODO
const jshypos: Hypo[] = []
const jsname = PgfText_AsString(cat)
const jsexprs: Expr[] = []
const obj = new Type(jshypos, jsname, jsexprs)
const buf = ref.alloc(ref.types.Object) as Pointer<Type>
ref.writeObject(buf, 0, obj)
return buf
}) })
const free_ref = ffi.Callback(ref.types.void, [PgfUnmarshaller, ref.refType(ref.types.Object)], const free_ref = ffi.Callback(ref.types.void, [PgfUnmarshaller, ref.refType(ref.types.Object)],