1
0
forked from GitHub/gf-core

Add tests for reading & equality of various expressions

This commit is contained in:
John J. Camilleri
2021-10-08 15:06:34 +02:00
parent 71536e8e37
commit 0e011955be
4 changed files with 193 additions and 37 deletions

View File

@@ -71,9 +71,10 @@ export class ExprLit extends Expr {
export class ExprMeta extends Expr {
id: number
constructor (i: number) {
constructor (i?: number) {
super()
this.id = i
if (i != null) this.id = i
else this.id = 0
}
}

View File

@@ -159,9 +159,9 @@ export function PgfText_FromString (str: string): Pointer<any> {
// Un/marshalling
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<Expr>): Pointer<ExprAbs> {
const jsname = PgfText_AsString(name)
const obj = new ExprAbs(btype, jsname, body) // TODO check body
const obj = new ExprAbs(btype, jsname, body.deref())
const buf = ref.alloc(ref.types.Object) as Pointer<ExprAbs>
ref.writeObject(buf, 0, obj)
return buf
@@ -169,7 +169,7 @@ const eabs = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.bool, PgfTextPtr,
const eapp = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfExpr],
function (self, fun: Pointer<Expr>, arg: Pointer<Type>): Pointer<ExprApp> {
const obj = new ExprApp(fun, arg) // TODO check
const obj = new ExprApp(fun.deref(), arg.deref())
const buf = ref.alloc(ref.types.Object) as Pointer<ExprApp>
ref.writeObject(buf, 0, obj)
return buf
@@ -211,7 +211,7 @@ const evar = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.int],
const etyped = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfType],
function (self, expr: Pointer<Expr>, type: Pointer<Type>): Pointer<ExprTyped> {
const obj = new ExprTyped(expr, type.deref()) // TODO check
const obj = new ExprTyped(expr.deref(), type.deref())
const buf = ref.alloc(ref.types.Object) as Pointer<ExprTyped>
ref.writeObject(buf, 0, obj)
return buf
@@ -219,7 +219,7 @@ const etyped = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfType],
const eimplarg = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr],
function (self, expr: Pointer<Expr>): Pointer<ExprImplArg> {
const obj = new ExprImplArg(expr) // TODO check
const obj = new ExprImplArg(expr.deref())
const buf = ref.alloc(ref.types.Object) as Pointer<ExprImplArg>
ref.writeObject(buf, 0, obj)
return buf

View File

@@ -1,7 +1,20 @@
/* eslint-disable @typescript-eslint/naming-convention */
import errno from './errno'
import { Expr, ExprLit } from './expr'
import {
Type,
Hypo,
Expr,
ExprAbs,
ExprApp,
ExprLit,
ExprMeta,
ExprFun,
ExprVar,
ExprTyped,
ExprImplArg,
Literal
} from './expr'
import {
voidPtr,
PgfRevisionPtr,
@@ -67,7 +80,7 @@ function handleError (err: StructObject<PgfExnType>): void {
// ----------------------------------------------------------------------------
// PGF grammar object
export class PGFGrammar {
class PGFGrammar {
readonly db: Pointer<any>
readonly revision: Pointer<any>
@@ -198,6 +211,15 @@ function newNGF (abstract_name: string, path?: string): PGFGrammar {
return new PGFGrammar(db, rev)
}
function readType (str: string): Type {
const txt = PgfText_FromString(str)
const type = runtime.pgf_read_type(txt, unmarshaller.ref())
if (ref.isNull(type)) {
throw new PGFError('unable to parse type')
}
return ref.readObject(type) as Type
}
function readExpr (str: string): Expr {
const txt = PgfText_FromString(str)
const expr = runtime.pgf_read_expr(txt, unmarshaller.ref())
@@ -210,15 +232,51 @@ function readExpr (str: string): Expr {
// ----------------------------------------------------------------------------
// Exposed library API
export default {
export {
PGFGrammar,
PGFError,
readPGF,
bootNGF,
readNGF,
newNGF,
readType,
readExpr,
Type,
Hypo,
Expr,
ExprLit
ExprAbs,
ExprApp,
ExprLit,
ExprMeta,
ExprFun,
ExprVar,
ExprTyped,
ExprImplArg,
Literal
}
export default {
PGFGrammar,
PGFError,
readPGF,
bootNGF,
readNGF,
newNGF,
readType,
readExpr,
Type,
Hypo,
Expr,
ExprAbs,
ExprApp,
ExprLit,
ExprMeta,
ExprFun,
ExprVar,
ExprTyped,
ExprImplArg,
Literal
}

View File

@@ -1,4 +1,19 @@
import PGF, { PGFGrammar } from '../index'
import PGF, {
PGFError,
PGFGrammar,
// Type,
// Hypo,
// Expr,
// ExprAbs,
ExprApp,
ExprLit,
ExprMeta,
ExprFun,
// ExprVar,
// ExprTyped,
ExprImplArg
// Literal
} from '../index'
import fs from 'fs'
// ----------------------------------------------------------------------------
@@ -17,7 +32,7 @@ describe('readPGF', () => {
test('GF', () => {
expect(() => {
PGF.readPGF('../haskell/tests/basic.gf')
}).toThrow(PGF.PGFError)
}).toThrow(PGFError)
})
test('NGF', () => {
@@ -29,7 +44,7 @@ describe('readPGF', () => {
PGF.bootNGF('../haskell/tests/basic.pgf', './basic.ngf')
expect(() => {
PGF.readPGF('./basic.ngf')
}).toThrow(PGF.PGFError)
}).toThrow(PGFError)
})
})
@@ -57,13 +72,13 @@ describe('bootNGF', () => {
test('GF', () => {
expect(() => {
PGF.bootNGF('../haskell/tests/basic.gf', './abc.ngf')
}).toThrow(PGF.PGFError)
}).toThrow(PGFError)
})
test('NGF', () => {
expect(() => {
PGF.bootNGF('./basic.ngf', './abc.ngf')
}).toThrow(PGF.PGFError)
}).toThrow(PGFError)
})
test('existing', () => {
@@ -98,13 +113,13 @@ describe('readNGF', () => {
test('GF', () => {
expect(() => {
PGF.readNGF('../haskell/tests/basic.gf')
}).toThrow(PGF.PGFError)
}).toThrow(PGFError)
})
test('PGF', () => {
expect(() => {
PGF.readNGF('../haskell/tests/basic.pgf')
}).toThrow(PGF.PGFError)
}).toThrow(PGFError)
})
})
@@ -209,88 +224,170 @@ describe('abstract syntax', () => {
// ----------------------------------------------------------------------------
describe('types', () => {
test('invalid', () => {
expect(() => {
PGF.readType('->')
}).toThrow(PGFError)
})
})
// ----------------------------------------------------------------------------
describe('expressions', () => {
test('invalid', () => {
expect(() => {
PGF.readExpr('->')
}).toThrow(PGF.PGFError)
}).toThrow(PGFError)
})
describe('literals', () => {
test('small integer', () => {
const e1 = PGF.readExpr('123')
const e2 = new PGF.ExprLit(123)
const e3 = new PGF.ExprLit(456)
const e2 = new ExprLit(123)
const e3 = new 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)
const e2 = new ExprLit(-123)
const e3 = new 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'))
const e2 = new ExprLit(BigInt('774763251095801167872'))
expect(e1).toEqual(e2)
})
test('negative big integer', () => {
const e1 = PGF.readExpr('-774763251095801167872')
const e2 = new PGF.ExprLit(BigInt('-774763251095801167872'))
const e2 = new 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'))
const e2 = new ExprLit(BigInt('7747632510958011678729003251095801167999'))
const e3 = new 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'))
const e2 = new ExprLit(BigInt('-7747632510958011678729003251095801167999'))
const e3 = new 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)
const e2 = new ExprLit(3.142)
const e3 = new 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)
const e2 = new ExprLit(-3.142)
const e3 = new 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')
const e2 = new ExprLit('abc')
const e3 = new 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')
const e2 = new ExprLit('açġħ')
const e3 = new ExprLit('acgh')
expect(e1).toEqual(e2)
expect(e1).not.toEqual(e3)
})
})
describe('functions', () => {
test('simple', () => {
const e1 = PGF.readExpr('f')
expect(e1).toBeInstanceOf(ExprFun)
expect((e1 as ExprFun).name).toEqual('f')
const e2 = new ExprFun('f')
const e3 = new ExprFun('g')
expect(e1).toEqual(e2)
expect(e1).not.toEqual(e3)
})
test('application 1', () => {
const e1 = PGF.readExpr('f x y')
expect(e1).toBeInstanceOf(ExprApp)
expect((e1 as ExprApp).arg).toEqual(new ExprFun('y'))
const e2 = new ExprApp(
new ExprApp(
new ExprFun('f'),
new ExprFun('x')
), new ExprFun('y')
)
expect(e1).toEqual(e2)
})
test('application 2', () => {
const e1 = PGF.readExpr('f (g x)')
const e2 = new ExprApp(
new ExprFun('f'),
new ExprApp(
new ExprFun('g'),
new ExprFun('x')
)
)
expect(e1).toEqual(e2)
})
test('application 3', () => {
const e1 = PGF.readExpr('f {g x}')
const e2 = new ExprApp(
new ExprFun('f'),
new ExprImplArg(
new ExprApp(
new ExprFun('g'),
new ExprFun('x')
)
)
)
expect(e1).toEqual(e2)
})
})
describe('variables', () => {
test('meta 1', () => {
const e1 = PGF.readExpr('?')
expect(e1).toBeInstanceOf(ExprMeta)
const e2 = new ExprMeta()
const e3 = new ExprMeta(0)
const e4 = new ExprMeta(1)
expect(e1).toEqual(e2)
expect(e1).toEqual(e3)
expect(e1).not.toEqual(e4)
})
test('meta 2', () => {
const e1 = PGF.readExpr('?42')
const e2 = new ExprMeta(42)
expect(e1).toEqual(e2)
})
})
})