Skip to content

Commit

Permalink
Add "all" device attribute
Browse files Browse the repository at this point in the history
"all" is a boolean; if set, device selection is skipped and the program
operates on all devices that match the selector
(unset is the same as false)
  • Loading branch information
gcampax committed Nov 1, 2019
1 parent f9953a4 commit 3aa9bd6
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 5 deletions.
7 changes: 5 additions & 2 deletions lib/ast/program.js
Expand Up @@ -20,7 +20,6 @@ const {
recursiveYieldArraySlots,
FieldSlot
} = require('./slots');
const { stringEscape } = require('../escaping');

/**
* Base class of all expressions that select a device.
Expand Down Expand Up @@ -53,8 +52,10 @@ class DeviceSelector extends Selector {
* all devices if no attributes are specified
* @param {null} principal - reserved/deprecated, must be `null`
* @param {Ast.InputParam[]} attributes - other attributes used to select a device, if ID is unspecified
* @param {boolean} [all=false] - operate on all devices that match the attributes, instead of
* having the user choose
*/
constructor(kind, id, principal, attributes = []) {
constructor(kind, id, principal, attributes = [], all = false) {
super();

assert(typeof kind === 'string');
Expand All @@ -67,6 +68,8 @@ class DeviceSelector extends Selector {
this.principal = principal;

this.attributes = attributes;

this.all = all;
}

clone() {
Expand Down
11 changes: 10 additions & 1 deletion lib/grammar.pegjs
Expand Up @@ -287,14 +287,23 @@ example = 'stream' _ params:(lambda_param_decl_list)? _ ':=' _ stream:stream _
device_selector = type:class_name _ attrlist:input_param_list {
let id = null;
let all = undefined;
for (let { name, value } of attrlist) {
if (name === 'id') {
if (!value.isString)
return error(`id attribute must be a constant string`);
if (id)
return error(`duplicate device id`);
id = value.toJS();
} else if (name === 'all') {
if (!value.isBoolean)
return error(`all attribute must be a constant boolean`);
if (all !== undefined)
return error(`duplicate device attribute all`);
all = value.toJS();
}
}
return new Ast.Selector.Device(type, id, null, attrlist.filter((attr) => attr.name !== 'id'));
return new Ast.Selector.Device(type, id, null, attrlist.filter((attr) => attr.name !== 'id'), !!all);
}
device_attribute_list = first:device_attribute _ rest:(',' _ device_attribute _)* {
return [first].concat(take(rest, 2));
Expand Down
7 changes: 6 additions & 1 deletion lib/prettyprint.js
Expand Up @@ -107,12 +107,17 @@ function prettyprintSelector(ast) {

if (ast.id)
return `@${ast.kind}(id=${stringEscape(ast.id)}, ${attributes})`;
else if (ast.all)
return `@${ast.kind}(all=true, ${attributes})`;
else
return `@${ast.kind}(${attributes})`;
} else {
if (ast.id)
return `@${ast.kind}(id=${stringEscape(ast.id)})`;
return `@${ast.kind}`;
else if (ast.all)
return `@${ast.kind}(all=true)`;
else
return `@${ast.kind}`;
}
}

Expand Down
10 changes: 9 additions & 1 deletion lib/typecheck.js
Expand Up @@ -612,6 +612,8 @@ function resolveJoin(ast, lhs, rhs) {
);
}

const VALID_DEVICE_ATTRIBUTES = ['name'];

function typeCheckInputArgs(ast, schema, scope, classes) {
if (!ast.isVarRef && !ast.isJoin) {
assert(ast.selector);
Expand All @@ -623,11 +625,17 @@ function typeCheckInputArgs(ast, schema, scope, classes) {
throw new TypeError(`Duplicate device attribute ${attr.name}`);
dupes.add(attr.name);

if (VALID_DEVICE_ATTRIBUTES.indexOf(attr.name) < 0)
throw new TypeError(`Invalid device attribute ${attr.name}`);

const valueType = typeForValue(attr.value, scope);
if (!Type.isAssignable(valueType, Type.String, {}, false))
if (!Type.isAssignable(valueType, Type.String, {}, false) || attr.value.isUndefined)
throw new TypeError(`Invalid type for device attribute ${attr.name}, have ${valueType}, need String`);
}

if (ast.selector.id && ast.selector.all)
throw new TypeError(`all=true device attribute is incompatible with setting a device ID`);

if (ast.selector.kind in classes) {
const classdef = classes[ast.selector.kind];

Expand Down

0 comments on commit 3aa9bd6

Please sign in to comment.