Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/debug/WARDuino.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export namespace WARDuino {
import Frame = WASM.Frame;
import Table = WASM.Table;
import Memory = WASM.Memory;
import Type = WASM.Type;

export interface CallbackMapping {
callbackid: string;
Expand Down Expand Up @@ -77,9 +78,9 @@ export namespace WARDuino {
pc_error?: number;
exception_msg?: string;
breakpoints?: number[];
stack?: Value<bigint | number>[];
stack?: Value<Type>[];
callstack?: Frame[];
globals?: Value<bigint | number>[];
globals?: Value<Type>[];
table?: Table;
memory?: Memory;
br_table?: BRTable;
Expand Down
2 changes: 1 addition & 1 deletion src/framework/Testee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function timeout<T>(label: string, time: number, promise: Promise<T>): Pr
* @param field dot string describing the field of the value (or path)
*/
export function getValue(object: any, field: string): any {
if (object?.type == WASM.Type.nothing) {
if (object?.type === WASM.Special.nothing) {
return undefined;
}

Expand Down
9 changes: 6 additions & 3 deletions src/framework/scenario/Invoker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {Target} from '../Testee';
import Value = WASM.Value;
import Type = WASM.Type;
import nothing = WASM.nothing;
import Special = WASM.Special;
import Float = WASM.Float;

export class Invoker implements Step {
readonly title: string;
Expand All @@ -28,9 +30,10 @@ export function invoke(func: string, args: Value<any>[]): Instruction {
return {kind: Kind.Request, value: Message.invoke(func, args)};
}

export function returns<T extends bigint | number>(n: Value<T>): Expectation[] {
if (n.type == Type.nothing) {
export function returns<T extends Type>(n: Value<T>): Expectation[] {
if (n.type == Special.nothing) {
return [{'value': {kind: 'primitive', value: undefined} as Expected<undefined>}]
}
return [{'value': {kind: 'primitive', value: n.value} as Expected<T>}]
type R = T extends Float ? number : bigint;
return [{'value': {kind: 'primitive', value: n.value} as Expected<R>}]
}
18 changes: 10 additions & 8 deletions src/messaging/Message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

export namespace Message {
import Inspect = WARDuino.Inspect;
import Integer = WASM.Integer;

Check failure

Code scanning / ESLint

Disallow unused variables Error

'Integer' is defined but never used. Allowed unused vars must match /^_/u.
import Float = WASM.Float;
export const run: Request<Ack> = {
type: Interrupt.run,
parser: (line: string) => {
Expand Down Expand Up @@ -162,7 +164,7 @@
}
}

export function invoke(func: string, args: Value<bigint | number>[]): Request<WASM.Value<bigint | number> | Exception> {
export function invoke(func: string, args: Value<Type>[]): Request<WASM.Value<Type> | Exception> {
function fidx(map: SourceMap.Mapping, func: string): number {
const fidx: number | void = map.functions.find((closure: SourceMap.Closure) => closure.name === func)?.index;
if (fidx === undefined) {
Expand All @@ -171,15 +173,15 @@
return fidx!;
}

function convert(args: Value<bigint | number>[]) {
function convert(args: Value<Type>[]) {
let payload: string = '';
args.forEach((arg: Value<bigint | number>) => {
if (arg.type === Type.i32 || arg.type === Type.i64) {
payload += WASM.leb128(arg.value);
} else {
const buff = Buffer.alloc(arg.type === Type.f32 ? 4 : 8);
write(buff, Number(arg.value), 0, true, arg.type === Type.f32 ? 23 : 52, buff.length); // todo fix precision loss
args.forEach((arg: Value<Type>) => {
if (arg.type === Float.f32 || arg.type === Float.f64) {
const buff = Buffer.alloc(arg.type === Float.f32 ? 4 : 8);
write(buff, Number(arg.value), 0, true, arg.type === Float.f32 ? 23 : 52, buff.length); // todo fix precision loss
payload += buff.toString('hex');
} else {
payload += WASM.leb128(arg.value);
}
});
return payload;
Expand Down
42 changes: 27 additions & 15 deletions src/messaging/Parsers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import {JSONParse} from 'json-with-bigint';
import State = WARDuino.State;
import nothing = WASM.nothing;

import Type = WASM.Type;
export function identityParser(text: string) {
return stripEnd(text);
}
Expand All @@ -15,7 +15,7 @@
return JSONParse(text);
}

export function invokeParser(text: string): WASM.Value<bigint | number> | Exception {
export function invokeParser(text: string): WASM.Value<Type> | Exception {
if (exception(text)) {
return {text: text};
}
Expand Down Expand Up @@ -60,38 +60,50 @@
}

export function signed(value: bigint, bits = 32) {
let x = BigInt(value);
let x = value;

Check failure

Code scanning / ESLint

Require `const` declarations for variables that are never reassigned after declared Error

'x' is never reassigned. Use 'const' instead.
const sign = 1n << BigInt(bits - 1);
const mod = 1n << BigInt(bits);
return x >= sign ? x - mod : x;

}

function stacking(objects: {value: bigint, type: any}[]): WASM.Value<bigint | number>[] {
const stacked: WASM.Value<bigint | number>[] = [];
function extractType(object: {value: bigint | number, type: any}): Type {

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.
if (isNaN(<number>object.value)) return WASM.Special.nan;
if (<number>object.value === Infinity) return WASM.Special.infinity;
return WASM.typing.get(object.type.toLowerCase()) ?? WASM.Special.unknown;
}

function stacking(objects: {value: bigint | number, type: any}[]): WASM.Value<Type>[] {

Check failure

Code scanning / ESLint

Disallow the `any` type Error

Unexpected any. Specify a different type.
const stacked: WASM.Value<Type>[] = [];
for (const object of objects) {
const type: WASM.Type = WASM.typing.get(object.type.toLowerCase()) ?? WASM.Type.unknown;
const type: WASM.Type = extractType(object);
let buff;
switch (type) {
case WASM.Type.u32:
case WASM.Type.u64:
case WASM.Special.nan:
stacked.push({value: NaN, type: type});
break;
case WASM.Special.infinity:
stacked.push({value: Infinity, type: type});
break;
case WASM.Integer.u32:
case WASM.Integer.u64:
stacked.push({value: object.value, type: type});
break;
case WASM.Type.i32:
stacked.push({value: signed(object.value, 32), type: type});
case WASM.Integer.i32:
stacked.push({value: signed(BigInt(object.value), 32), type: type});
break;
case WASM.Type.i64:
stacked.push({value: signed(object.value, 64), type: type});
case WASM.Integer.i64:
stacked.push({value: signed(BigInt(object.value), 64), type: type});
break;
case WASM.Type.f32:
case WASM.Float.f32:
buff = Buffer.from(Number(object.value.toString(16)).toString(16), 'hex');
stacked.push({value: ieee754.read(buff, 0, false, 23, buff.length), type: type});
break;
case WASM.Type.f64:
case WASM.Float.f64:
buff = Buffer.from(BigInt(object.value.toString(16)).toString(16), 'hex');
stacked.push({value: ieee754.read(buff, 0, false, 52, buff.length), type: type});
break;
case WASM.Type.unknown:
case WASM.Special.unknown:
break;
}
}
Expand Down
89 changes: 57 additions & 32 deletions src/sourcemap/Wasm.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,82 @@
export namespace WASM {
export enum Type {
f32,
f64,
u32,
i32,
u64,
i64,
nothing,
unknown
export enum Float {
f32 = 'f32',
f64 = 'f64'
}

export enum Integer {
u32 = 'u32',
i32 = 'i32',
u64 = 'u64',
i64 = 'i64'
}

export enum Special {
nothing = 'nothing',
nan = 'nan',
infinity = 'infinity',
unknown = 'unknown'
}

export type Type = Float | Integer | Special;

export const typing = new Map<string, Type>([
['f32', Type.f32],
['f64', Type.f64],
['u32', Type.u32],
['i32', Type.i32],
['u64', Type.u64],
['i64', Type.i64]
['f32', Float.f32],
['f64', Float.f64],
['u32', Integer.u32],
['i32', Integer.i32],
['u64', Integer.u64],
['i64', Integer.i64]
]);

export interface Value<T extends bigint | number> {
type: Type;
value: T;
export interface Value<T extends Type> {
type: T;
value: T extends Integer ? bigint : number;
}

export function equals<T extends Type>(a: Value<T>, b: Value<T>): boolean {
switch (a.type) {
case Special.nan:
return b.type === Special.nan;
case Special.infinity:
return b.type === Special.infinity;
case Special.nothing:
return b.type === Special.nothing;
case Special.unknown:
return b.type === Special.unknown;
default:
return a.type === b.type && a.value === b.value;
}
}

export interface Nothing extends Value<number> {}
export interface Nothing extends Value<Special> {}

Check failure

Code scanning / ESLint

Disallow accidentally using the "empty object" type Error

An interface declaring no members is equivalent to its supertype.

export const nothing: Nothing = {
type: Type.nothing, value: 0
type: Special.nothing, value: 0
}

export function u32(n: bigint): WASM.Value<bigint> {
return {value: n, type: Type.u32};
export function u32(n: bigint): WASM.Value<Integer> {
return {value: n, type: Integer.u32};
}

export function i32(n: bigint): WASM.Value<bigint> {
return {value: n, type: Type.i32};
export function i32(n: bigint): WASM.Value<Integer> {
return {value: n, type: Integer.i32};
}

export function f32(n: number): WASM.Value<number> {
return {value: n, type: Type.f32};
export function f32(n: number): WASM.Value<Float> {
return {value: n, type: Float.f32};
}

export function f64(n: number): WASM.Value<number> {
return {value: n, type: Type.f64};
export function f64(n: number): WASM.Value<Float> {
return {value: n, type: Float.f64};
}

export function u64(n: bigint): WASM.Value<bigint> {
return {value: n, type: Type.u64};
export function u64(n: bigint): WASM.Value<Integer> {
return {value: n, type: Integer.u64};
}

export function i64(n: bigint): WASM.Value<bigint> {
return {value: n, type: Type.i64};
export function i64(n: bigint): WASM.Value<Integer> {
return {value: n, type: Integer.i64};
}

export interface Frame {
Expand Down
Loading