From c12cd3e4207c184dc80cad6013bf4492165fce4c Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Sat, 4 Jan 2020 12:57:44 +0100 Subject: [PATCH 1/3] Handle `Int` nodes. --- package-lock.json | 12 +- package.json | 2 +- src/implementation/bitcode/node/index.ts | 2 + src/implementation/bitcode/node/int.ts | 19 +++ src/implementation/c/node/index.ts | 2 + src/implementation/c/node/int.ts | 10 ++ src/implementation/js/node/index.ts | 2 + src/implementation/js/node/int.ts | 196 +++++++++++++++++++++++ 8 files changed, 237 insertions(+), 8 deletions(-) create mode 100644 src/implementation/bitcode/node/int.ts create mode 100644 src/implementation/c/node/int.ts create mode 100644 src/implementation/js/node/int.ts diff --git a/package-lock.json b/package-lock.json index a581084..f88fe21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -404,9 +404,8 @@ } }, "llparse-builder": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/llparse-builder/-/llparse-builder-1.3.2.tgz", - "integrity": "sha512-0l2slf0O7TpzR+uWsENSCbMv+kdAgLC9eBuaLZYpXKYGg5bD4o4xX9MRKw8a51Prce+HvkpEWpR+8d/VYGpQpg==", + "version": "git+https://github.com/arthurschreiber/llparse-builder.git#591065e9eb043a068547f35c951b533e91a58b99", + "from": "git+https://github.com/arthurschreiber/llparse-builder.git#arthur/binary-parsing", "requires": { "@types/debug": "0.0.30", "binary-search": "^1.3.3", @@ -414,12 +413,11 @@ } }, "llparse-frontend": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/llparse-frontend/-/llparse-frontend-1.2.1.tgz", - "integrity": "sha512-7n7NHAU2ZVNP/7S3llhvScY5FoDzMbPo5Le1lYr3JMAH91EPOxEbCxristRtMVcGKgij8qb2Ar7SBeu4mnb++g==", + "version": "git+https://github.com/arthurschreiber/llparse-frontend.git#14aa483f7ffd6048db768d77e07c7e8231844f5f", + "from": "git+https://github.com/arthurschreiber/llparse-frontend.git#arthur/binary-parsing", "requires": { "debug": "^3.2.6", - "llparse-builder": "^1.3.2" + "llparse-builder": "git+https://github.com/arthurschreiber/llparse-builder.git#arthur/binary-parsing" } }, "llparse-test-fixture": { diff --git a/package.json b/package.json index d17c866..6c11745 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,6 @@ "dependencies": { "bitcode": "^1.2.0", "debug": "^3.2.6", - "llparse-frontend": "^1.2.1" + "llparse-frontend": "git+https://github.com/arthurschreiber/llparse-frontend.git#arthur/binary-parsing" } } diff --git a/src/implementation/bitcode/node/index.ts b/src/implementation/bitcode/node/index.ts index 3ee9305..aa2ec03 100644 --- a/src/implementation/bitcode/node/index.ts +++ b/src/implementation/bitcode/node/index.ts @@ -4,6 +4,7 @@ import { Consume } from './consume'; import { Empty } from './empty'; import { Error as ErrorNode } from './error'; import { Invoke } from './invoke'; +import { Int } from './int'; import { Pause } from './pause'; import { Sequence } from './sequence'; import { Single } from './single'; @@ -17,6 +18,7 @@ export default { Consume, Empty, Error: class Error extends ErrorNode {}, + Int, Invoke, Pause, Sequence, diff --git a/src/implementation/bitcode/node/int.ts b/src/implementation/bitcode/node/int.ts new file mode 100644 index 0000000..b450913 --- /dev/null +++ b/src/implementation/bitcode/node/int.ts @@ -0,0 +1,19 @@ +import * as assert from 'assert'; +import * as frontend from 'llparse-frontend'; + +import { Code } from '../code'; +import { IRBasicBlock, IRValue } from '../compilation'; +import { CONTAINER_KEY } from '../constants'; +import { INodePosition, Node } from './base'; + +export class Int extends Node { + protected doBuild(bb: IRBasicBlock, pos: INodePosition): void { + const otherwise = this.ref.otherwise!; + + if (!otherwise.noAdvance) { + bb = this.prologue(bb, pos); + } + + this.tailTo(bb, otherwise, pos); + } +} diff --git a/src/implementation/c/node/index.ts b/src/implementation/c/node/index.ts index ba751d9..f50ea9f 100644 --- a/src/implementation/c/node/index.ts +++ b/src/implementation/c/node/index.ts @@ -3,6 +3,7 @@ import * as frontend from 'llparse-frontend'; import { Consume } from './consume'; import { Empty } from './empty'; import { Error as ErrorNode } from './error'; +import { Int } from './int'; import { Invoke } from './invoke'; import { Pause } from './pause'; import { Sequence } from './sequence'; @@ -17,6 +18,7 @@ export default { Consume, Empty, Error: class Error extends ErrorNode {}, + Int, Invoke, Pause, Sequence, diff --git a/src/implementation/c/node/int.ts b/src/implementation/c/node/int.ts new file mode 100644 index 0000000..1c3c7e6 --- /dev/null +++ b/src/implementation/c/node/int.ts @@ -0,0 +1,10 @@ +import * as frontend from 'llparse-frontend'; + +import { Compilation } from '../compilation'; +import { Node } from './base'; + +export class Int extends Node { + public doBuild(out: string[]): void { + + } +} diff --git a/src/implementation/js/node/index.ts b/src/implementation/js/node/index.ts index ba751d9..f50ea9f 100644 --- a/src/implementation/js/node/index.ts +++ b/src/implementation/js/node/index.ts @@ -3,6 +3,7 @@ import * as frontend from 'llparse-frontend'; import { Consume } from './consume'; import { Empty } from './empty'; import { Error as ErrorNode } from './error'; +import { Int } from './int'; import { Invoke } from './invoke'; import { Pause } from './pause'; import { Sequence } from './sequence'; @@ -17,6 +18,7 @@ export default { Consume, Empty, Error: class Error extends ErrorNode {}, + Int, Invoke, Pause, Sequence, diff --git a/src/implementation/js/node/int.ts b/src/implementation/js/node/int.ts new file mode 100644 index 0000000..755dc14 --- /dev/null +++ b/src/implementation/js/node/int.ts @@ -0,0 +1,196 @@ +import * as frontend from 'llparse-frontend'; + +import { Compilation } from '../compilation'; +import { Node } from './base'; + +export class Int extends Node { + public doBuild(out: string[]): void { + this.prologue(out); + + switch (this.ref.bytes) { + case 1: { + if (this.ref.signed) { + this.readInt8(out); + } else { + this.readUInt8(out); + } + break; + } + + case 2: { + if (this.ref.littleEndian) { + this.readUInt16LE(out); + } else { + this.readUInt16BE(out); + } + break; + } + + case 3: { + if (this.ref.littleEndian) { + this.readUInt24LE(out); + } else { + this.readUInt24BE(out); + } + break; + } + + case 4: { + if (this.ref.littleEndian) { + this.readUInt32LE(out); + } else { + this.readUInt32BE(out); + } + break; + } + } + + this.tailTo(out, this.ref.otherwise!); + } + + private readInt8(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + out.push(`${index} = (${ctx.bufArg()}[${ctx.offArg()}] & 2 ** 7) * 0x1fffffe;`) + } + + private readUInt8(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`) + } + + private readUInt16LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`) + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + } + } + + private readUInt24LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`) + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + } + } + + private readUInt32LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`) + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 3: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 24;`); + break; + } + } + } + + private readUInt16BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`) + break; + } + } + } + + private readUInt24BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`) + break; + } + } + } + + private readUInt32BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 24;`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 3: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`) + break; + } + } + } +} From 4407172fc5a266ee16da48c9edceecb091820242 Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Tue, 7 Jan 2020 20:50:43 +0100 Subject: [PATCH 2/3] Remove unused import. --- src/implementation/js/node/int.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/implementation/js/node/int.ts b/src/implementation/js/node/int.ts index 755dc14..b2d8ba6 100644 --- a/src/implementation/js/node/int.ts +++ b/src/implementation/js/node/int.ts @@ -1,6 +1,5 @@ import * as frontend from 'llparse-frontend'; -import { Compilation } from '../compilation'; import { Node } from './base'; export class Int extends Node { From f41d63ad9b47c27e3004a65ca144872c92882c2b Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Tue, 7 Jan 2020 20:54:41 +0100 Subject: [PATCH 3/3] Implement missing methods. --- src/implementation/js/node/int.ts | 188 +++++++++++++++++++++++++++--- 1 file changed, 174 insertions(+), 14 deletions(-) diff --git a/src/implementation/js/node/int.ts b/src/implementation/js/node/int.ts index b2d8ba6..11f8ee8 100644 --- a/src/implementation/js/node/int.ts +++ b/src/implementation/js/node/int.ts @@ -18,27 +18,51 @@ export class Int extends Node { case 2: { if (this.ref.littleEndian) { - this.readUInt16LE(out); + if (this.ref.signed) { + this.readInt16LE(out); + } else { + this.readUInt16LE(out); + } } else { - this.readUInt16BE(out); + if (this.ref.signed) { + this.readInt16BE(out); + } else { + this.readUInt16BE(out); + } } break; } case 3: { if (this.ref.littleEndian) { - this.readUInt24LE(out); + if (this.ref.signed) { + this.readInt24LE(out); + } else { + this.readUInt24LE(out); + } } else { - this.readUInt24BE(out); + if (this.ref.signed) { + this.readInt24BE(out); + } else { + this.readUInt24BE(out); + } } break; } case 4: { if (this.ref.littleEndian) { - this.readUInt32LE(out); + if (this.ref.signed) { + this.readInt32LE(out); + } else { + this.readUInt32LE(out); + } } else { - this.readUInt32BE(out); + if (this.ref.signed) { + this.readInt32BE(out); + } else { + this.readUInt32BE(out); + } } break; } @@ -51,14 +75,32 @@ export class Int extends Node { const ctx = this.compilation; const index = ctx.stateField(this.ref.field); - out.push(`${index} = (${ctx.bufArg()}[${ctx.offArg()}] & 2 ** 7) * 0x1fffffe;`) + out.push(`${index} = (${ctx.bufArg()}[${ctx.offArg()}] & 2 ** 7) * 0x1fffffe;`); } private readUInt8(out: string[]) { const ctx = this.compilation; const index = ctx.stateField(this.ref.field); - out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`) + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); + } + + private readInt16LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + out.push(`${index} |= (${index} & 2 ** 15) * 0x1fffe;`); + break; + } + } } private readUInt16LE(out: string[]) { @@ -67,7 +109,7 @@ export class Int extends Node { switch (this.ref.byteOffset) { case 0: { - out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`) + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); break; } @@ -78,13 +120,36 @@ export class Int extends Node { } } + private readInt24LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + out.push(`${index} |= (${index} & 2 ** 23) * 0x1fe`); + break; + } + } + } + private readUInt24LE(out: string[]) { const ctx = this.compilation; const index = ctx.stateField(this.ref.field); switch (this.ref.byteOffset) { case 0: { - out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`) + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); break; } @@ -100,13 +165,40 @@ export class Int extends Node { } } + private readInt32LE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 3: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] << 24;`); // Overflow + break; + } + } + } + private readUInt32LE(out: string[]) { const ctx = this.compilation; const index = ctx.stateField(this.ref.field); switch (this.ref.byteOffset) { case 0: { - out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`) + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}];`); break; } @@ -127,6 +219,24 @@ export class Int extends Node { } } + private readInt16BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); + out.push(`${index} |= (${index} & 2 ** 15) * 0x1fffe;`); + break; + } + } + } + private readUInt16BE(out: string[]) { const ctx = this.compilation; const index = ctx.stateField(this.ref.field); @@ -138,7 +248,30 @@ export class Int extends Node { } case 1: { - out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`) + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + } + } + + private readInt24BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); + out.push(`${index} |= (${index} & 2 ** 23) * 0x1fe;`); break; } } @@ -160,7 +293,34 @@ export class Int extends Node { } case 2: { - out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`) + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); + break; + } + } + } + + private readInt32BE(out: string[]) { + const ctx = this.compilation; + const index = ctx.stateField(this.ref.field); + + switch (this.ref.byteOffset) { + case 0: { + out.push(`${index} = ${ctx.bufArg()}[${ctx.offArg()}] << 24;`); // Overflow + break; + } + + case 1: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 16;`); + break; + } + + case 2: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}] * 2 ** 8;`); + break; + } + + case 3: { + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); break; } } @@ -187,7 +347,7 @@ export class Int extends Node { } case 3: { - out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`) + out.push(`${index} += ${ctx.bufArg()}[${ctx.offArg()}];`); break; } }