Skip to content

Commit

Permalink
feat(json-expression): 🎸 add keys operator
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Aug 28, 2023
1 parent 1819880 commit e713ece
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 1 deletion.
18 changes: 18 additions & 0 deletions src/json-expression/__tests__/jsonExpressionUnitTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1564,6 +1564,24 @@ export const jsonExpressionUnitTests = (
});
});

describe('Object operators', () => {
describe('keys', () => {
test('returns empty array for empty object', () => {
check(['keys', {}], []);
});

test('returns keys of an object', () => {
check(['keys', {foo: 1}], ['foo']);
});

test('throws on invalid operand count', () => {
expect(() => check(['keys', 'a', 'b'] as any, false)).toThrowErrorMatchingInlineSnapshot(
`""keys" operator expects 1 operands."`,
);
});
});
});

describe('Branching operators', () => {
describe('if or ?', () => {
test('branches', () => {
Expand Down
2 changes: 2 additions & 0 deletions src/json-expression/operators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {logicalOperators} from './logical';
import {typeOperators} from './type';
import {stringOperators} from './string';
import {binaryOperators} from './binary';
import {objectOperators} from './object';
import {branchingOperators} from './branching';
import {inputOperators} from './input';
import {bitwiseOperators} from './bitwise';
Expand All @@ -16,6 +17,7 @@ export const operators = [
...typeOperators,
...stringOperators,
...binaryOperators,
...objectOperators,
...branchingOperators,
...inputOperators,
...bitwiseOperators,
Expand Down
20 changes: 20 additions & 0 deletions src/json-expression/operators/object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as util from '../util';
import {Expression, ExpressionResult} from '../codegen-steps';
import type * as types from '../types';

export const objectOperators: types.OperatorDefinition<any>[] = [
[
'keys',
[],
1,
(expr: types.ExprKeys, ctx) => {
const operand = ctx.eval(expr[1], ctx);
return util.keys(operand);
},
(ctx: types.OperatorCodegenCtx<types.ExprKeys>): ExpressionResult => {
ctx.link(util.keys, 'keys');
const js = `keys(${ctx.operands[0]})`;
return new Expression(js);
},
] as types.OperatorDefinition<types.ExprKeys>,
];
5 changes: 4 additions & 1 deletion src/json-expression/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,11 @@ export type ExprF32 = BinaryExpression<'f32'>;
export type ExprF64 = BinaryExpression<'f64'>;

// Object expressions
export type ObjectExpression = ExprIn;
export type ObjectExpression =
| ExprKeys
| ExprIn;

export type ExprKeys = UnaryExpression<'keys'>;
export type ExprIn = [fn: 'in', what: unknown, list: unknown];

// Bitwise expressions
Expand Down
8 changes: 8 additions & 0 deletions src/json-expression/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ export const asBin = (value: unknown): Uint8Array => {
throw new Error('NOT_BINARY');
};

export const asObj = (value: unknown): object => {
if (type(value) === 'object') return value as object;
throw new Error('NOT_OBJECT');
};

export const keys = (value: unknown): string[] =>
Object.keys(asObj(value));

export const u8 = (bin: unknown, pos: unknown) => {
const buf = asBin(bin);
const index = int(pos);
Expand Down

0 comments on commit e713ece

Please sign in to comment.