Skip to content

Commit

Permalink
Merge pull request #1261 from NASA-AMMOS/eDSL_variable_reference
Browse files Browse the repository at this point in the history
Support JPL CoreFSW Variable References
  • Loading branch information
goetzrrGit authored Jan 17, 2024
2 parents fb1f43f + cdfeecb commit f6dd79f
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 18 deletions.
20 changes: 20 additions & 0 deletions sequencing-server/src/lib/codegen/CommandEDSLPreface.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ describe('Sequence', () => {
local.setKind('locals')
const parameter = Variable.new(ENUM('duration', 'POSSIBLE_DURATION'));
parameter.setKind('parameters')
const reference = Variable.new(FLOAT('LO1FLOAT' ));
reference.setKind('parameters')
reference.setAsVariableReference()
const sequence = Sequence.new({
seqId: 'test',
metadata: {},
Expand Down Expand Up @@ -378,6 +381,17 @@ describe('Sequence', () => {
}).METADATA({
author: 'ZZZZ',
}),
CommandStem.new({
stem: 'TEST',
arguments: {
temperature: reference,
duration: 10,
},

absoluteTime: doyToInstant('2022-001T00:00:00.000' as DOY_STRING),
}).METADATA({
author: 'bbbb',
}),
],
});

Expand All @@ -401,6 +415,12 @@ describe('Sequence', () => {
.METADATA({
author: 'ZZZZ',
}),
A\`2022-001T00:00:00.000\`.TEST(
REF(parameters.LO1FLOAT) --> "VERIFY: 'parameters.LO1FLOAT' is a Variable References"
,10)
.METADATA({
author: 'bbbb',
}),
]),
});`);
});
Expand Down
59 changes: 51 additions & 8 deletions sequencing-server/src/lib/codegen/CommandEDSLPreface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,10 @@ declare global {
optionals?: { allowable_ranges?: VariableRange[]; allowable_values?: unknown[]; sc_name?: string },
): ENUM<N, E>;

function REF<T extends VARIABLE_INT | VARIABLE_UINT | VARIABLE_FLOAT | VARIABLE_STRING | VARIABLE_ENUM>(
type: T,
): T;

// @ts-ignore : 'GroundEpoch' and 'Step' found in JSON Spec
function REQUEST(name: string, epoch: GroundEpoch, ...steps: [Step, ...Step[]]): RequestEpoch;

Expand Down Expand Up @@ -966,6 +970,7 @@ export class Variable implements VariableDeclaration {

[k: string]: unknown;
private kind: 'locals' | 'parameters' | 'unknown' = 'locals';
public reference: boolean = false;
private readonly _enum_name?: string | undefined;
// @ts-ignore : 'VariableRange: Request' found in JSON Spec
private readonly _allowable_ranges?: VariableRange[] | undefined;
Expand Down Expand Up @@ -1041,8 +1046,13 @@ export class Variable implements VariableDeclaration {
return variable;
}

public setAsVariableReference() {
this.reference = true;
}

public toReferenceString(): string {
return `${this.kind}.${this.name}`;
const _var = `${this.kind}.${this.name}`;
return this.reference ? `\nREF(${_var}) --> "VERIFY: '${_var}' is a Variable References"\n` : _var;
}

public toEDSLString(): string {
Expand Down Expand Up @@ -1214,6 +1224,24 @@ export function ENUM<const N extends string, const E extends string>(
return { name, enum_name, type: VariableType.ENUM as unknown as VARIABLE_ENUM, allowable_ranges, allowable_values, sc_name };
}

export function REF<T extends VARIABLE_INT | VARIABLE_UINT | VARIABLE_FLOAT | VARIABLE_STRING | VARIABLE_ENUM>(
value: T,
): T {
if (
Variable.isVariable(value) &&
(value.type === 'FLOAT' ||
value.type === 'INT' ||
value.type === 'STRING' ||
value.type === 'UINT' ||
value.type === 'ENUM')
) {
const var_ref = new Variable({ name: value.name as unknown as string, type: value.type as T });
var_ref.setAsVariableReference();
return var_ref as unknown as T;
}
throw new Error('Invalid variable, make sure you use a defined local or parameter variable');
}

/**
* ---------------------------------
* STEPS eDSL
Expand Down Expand Up @@ -3593,6 +3621,24 @@ function convertInterfacesToArgs(interfaces: Args, localNames?: String[], parame
return { hex_error: 'Remote property injection detected...' };
} else {
if (validate(argName)) {
// This is JPL mission specific for Variable References
if (arg.type === 'string') {
let variable = Variable.new({ name: arg.value, type: VariableType.INT });
if (localNames && localNames.length > 0) {
if (localNames.includes(arg.value)) {
variable.setKind('locals');
variable.setAsVariableReference();
return { [argName]: variable };
}
}
if (parameterNames && parameterNames.length > 0) {
if (parameterNames.includes(arg.value)) {
variable.setKind('parameters');
variable.setAsVariableReference();
return { [argName]: variable };
}
}
}
return { [argName]: arg.value };
}
return { error: 'Remote property injection detected...' };
Expand Down Expand Up @@ -3648,17 +3694,14 @@ function convertValueToObject(value: any, key: string): any {
case 'boolean':
return { type: 'boolean', value: value, name: key };
default:
if (
value instanceof Object &&
'name' in value &&
'type' in value &&
if (Variable.isVariable(value) &&
(value.type === 'FLOAT' ||
value.type === 'INT' ||
value.type === 'STRING' ||
value.type === 'UINT' ||
value.type === 'ENUM')
) {
return { type: 'symbol', value: value.name, name: key };
value.type === 'ENUM')) {
// jpl specific support for Variable Reference
return { type: value.reference ? 'string' : 'symbol', value: value.name, name: key };
} else if (
value instanceof Object &&
value.hex &&
Expand Down
2 changes: 1 addition & 1 deletion sequencing-server/src/lib/codegen/CommandTypeCodegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const Hardwares = {\n${dictionary.hwCommands
.map(hwCommands => `\t\t${hwCommands.stem}: ${hwCommands.stem},\n`)
.join('')}};
Object.assign(globalThis, { A:A, R:R, E:E, C:Object.assign(Commands, STEPS, REQUESTS), Sequence, FLOAT, UINT,INT, STRING, ENUM, REQUEST}, Hardwares, Immediates);
Object.assign(globalThis, { A:A, R:R, E:E, C:Object.assign(Commands, STEPS, REQUESTS), Sequence, FLOAT, UINT,INT, STRING, ENUM, REQUEST, REF}, Hardwares, Immediates);
`;

return {
Expand Down
61 changes: 52 additions & 9 deletions sequencing-server/test/__snapshots__/command-types.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,10 @@ declare global {
optionals?: { allowable_ranges?: VariableRange[]; allowable_values?: unknown[]; sc_name?: string },
): ENUM<N, E>;

function REF<T extends VARIABLE_INT | VARIABLE_UINT | VARIABLE_FLOAT | VARIABLE_STRING | VARIABLE_ENUM>(
type: T,
): T;

// @ts-ignore : 'GroundEpoch' and 'Step' found in JSON Spec
function REQUEST(name: string, epoch: GroundEpoch, ...steps: [Step, ...Step[]]): RequestEpoch;

Expand Down Expand Up @@ -969,6 +973,7 @@ export class Variable implements VariableDeclaration {

[k: string]: unknown;
private kind: 'locals' | 'parameters' | 'unknown' = 'locals';
public reference: boolean = false;
private readonly _enum_name?: string | undefined;
// @ts-ignore : 'VariableRange: Request' found in JSON Spec
private readonly _allowable_ranges?: VariableRange[] | undefined;
Expand Down Expand Up @@ -1044,8 +1049,13 @@ export class Variable implements VariableDeclaration {
return variable;
}

public setAsVariableReference() {
this.reference = true;
}

public toReferenceString(): string {
return \`\${this.kind}.\${this.name}\`;
const _var = \`\${this.kind}.\${this.name}\`;
return this.reference ? \`\\nREF(\${_var}) --> "VERIFY: '\${_var}' is a Variable References"\\n\` : _var;
}

public toEDSLString(): string {
Expand Down Expand Up @@ -1217,6 +1227,24 @@ export function ENUM<const N extends string, const E extends string>(
return { name, enum_name, type: VariableType.ENUM as unknown as VARIABLE_ENUM, allowable_ranges, allowable_values, sc_name };
}

export function REF<T extends VARIABLE_INT | VARIABLE_UINT | VARIABLE_FLOAT | VARIABLE_STRING | VARIABLE_ENUM>(
value: T,
): T {
if (
Variable.isVariable(value) &&
(value.type === 'FLOAT' ||
value.type === 'INT' ||
value.type === 'STRING' ||
value.type === 'UINT' ||
value.type === 'ENUM')
) {
const var_ref = new Variable({ name: value.name as unknown as string, type: value.type as T });
var_ref.setAsVariableReference();
return var_ref as unknown as T;
}
throw new Error('Invalid variable, make sure you use a defined local or parameter variable');
}

/**
* ---------------------------------
* STEPS eDSL
Expand Down Expand Up @@ -3596,6 +3624,24 @@ function convertInterfacesToArgs(interfaces: Args, localNames?: String[], parame
return { hex_error: 'Remote property injection detected...' };
} else {
if (validate(argName)) {
// This is JPL mission specific for Variable References
if (arg.type === 'string') {
let variable = Variable.new({ name: arg.value, type: VariableType.INT });
if (localNames && localNames.length > 0) {
if (localNames.includes(arg.value)) {
variable.setKind('locals');
variable.setAsVariableReference();
return { [argName]: variable };
}
}
if (parameterNames && parameterNames.length > 0) {
if (parameterNames.includes(arg.value)) {
variable.setKind('parameters');
variable.setAsVariableReference();
return { [argName]: variable };
}
}
}
return { [argName]: arg.value };
}
return { error: 'Remote property injection detected...' };
Expand Down Expand Up @@ -3651,17 +3697,14 @@ function convertValueToObject(value: any, key: string): any {
case 'boolean':
return { type: 'boolean', value: value, name: key };
default:
if (
value instanceof Object &&
'name' in value &&
'type' in value &&
if (Variable.isVariable(value) &&
(value.type === 'FLOAT' ||
value.type === 'INT' ||
value.type === 'STRING' ||
value.type === 'UINT' ||
value.type === 'ENUM')
) {
return { type: 'symbol', value: value.name, name: key };
value.type === 'ENUM')) {
// jpl specific support for Variable Reference
return { type: value.reference ? 'string' : 'symbol', value: value.name, name: key };
} else if (
value instanceof Object &&
value.hex &&
Expand Down Expand Up @@ -4661,6 +4704,6 @@ export const Hardwares = {
HDW_BLENDER_DUMP: HDW_BLENDER_DUMP,
};

Object.assign(globalThis, { A:A, R:R, E:E, C:Object.assign(Commands, STEPS, REQUESTS), Sequence, FLOAT, UINT,INT, STRING, ENUM, REQUEST}, Hardwares, Immediates);
Object.assign(globalThis, { A:A, R:R, E:E, C:Object.assign(Commands, STEPS, REQUESTS), Sequence, FLOAT, UINT,INT, STRING, ENUM, REQUEST, REF}, Hardwares, Immediates);
"
`;
85 changes: 85 additions & 0 deletions sequencing-server/test/seqjson-to-edsl.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,91 @@ describe('getEdslForSeqJson', () => {
]),
});`);
});

it('should create variable reference in edsl', async () => {
const res = await graphqlClient.request<{
getEdslForSeqJson: string;
}>(
gql`
query GetEdslForSeqJson($seqJson: SequenceSeqJson!) {
getEdslForSeqJson(seqJson: $seqJson)
}
`,
{
seqJson: {
id: '',
locals: [
{
name: 'LOOFLOAT',
type: 'FLOAT',
},
],
metadata: {},
parameters: [
{
name: 'LOOINT',
type: 'INT',
},
],
steps: [
{
args: [
{
name: 'temperature',
type: 'string',
value: 'LOOINT',
},
],
stem: 'PREHEAT_OVEN',
time: {
type: 'COMMAND_COMPLETE',
},
type: 'command',
},
{
args: [
{
name: 'tb_sugar',
type: 'string',
value: 'LOOFLOAT',
},
{
name: 'gluten_free',
type: 'string',
value: 'FALSE',
},
],
stem: 'PREPARE_LOAF',
time: {
type: 'COMMAND_COMPLETE',
},
type: 'command',
},
],
},
},
);

expect(res.getEdslForSeqJson).toEqual(`export default () =>
Sequence.new({
seqId: '',
metadata: {},
locals: [
FLOAT('LOOFLOAT')
],
parameters: [
INT('LOOINT')
],
steps: ({ locals, parameters }) => ([
C.PREHEAT_OVEN(
REF(parameters.LOOINT) --> "VERIFY: 'parameters.LOOINT' is a Variable References"
),
C.PREPARE_LOAF(
REF(locals.LOOFLOAT) --> "VERIFY: 'locals.LOOFLOAT' is a Variable References"
,'FALSE'),
]),
});`);
});
});

describe('getEdslForSeqJsonBulk', () => {
Expand Down

0 comments on commit f6dd79f

Please sign in to comment.