diff --git a/sequencing-server/src/lib/codegen/CommandEDSLPreface.spec.ts b/sequencing-server/src/lib/codegen/CommandEDSLPreface.spec.ts index 4ef75fdac5..a230aced5a 100644 --- a/sequencing-server/src/lib/codegen/CommandEDSLPreface.spec.ts +++ b/sequencing-server/src/lib/codegen/CommandEDSLPreface.spec.ts @@ -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: {}, @@ -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', + }), ], }); @@ -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', + }), ]), });`); }); diff --git a/sequencing-server/src/lib/codegen/CommandEDSLPreface.ts b/sequencing-server/src/lib/codegen/CommandEDSLPreface.ts index 1999902a2b..40b670bbd0 100644 --- a/sequencing-server/src/lib/codegen/CommandEDSLPreface.ts +++ b/sequencing-server/src/lib/codegen/CommandEDSLPreface.ts @@ -465,6 +465,10 @@ declare global { optionals?: { allowable_ranges?: VariableRange[]; allowable_values?: unknown[]; sc_name?: string }, ): ENUM; + function REF( + type: T, + ): T; + // @ts-ignore : 'GroundEpoch' and 'Step' found in JSON Spec function REQUEST(name: string, epoch: GroundEpoch, ...steps: [Step, ...Step[]]): RequestEpoch; @@ -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; @@ -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 { @@ -1214,6 +1224,24 @@ export function ENUM( return { name, enum_name, type: VariableType.ENUM as unknown as VARIABLE_ENUM, allowable_ranges, allowable_values, sc_name }; } +export function REF( + 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 @@ -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...' }; @@ -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 && diff --git a/sequencing-server/src/lib/codegen/CommandTypeCodegen.ts b/sequencing-server/src/lib/codegen/CommandTypeCodegen.ts index 907febd592..5bf826d6a0 100644 --- a/sequencing-server/src/lib/codegen/CommandTypeCodegen.ts +++ b/sequencing-server/src/lib/codegen/CommandTypeCodegen.ts @@ -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 { diff --git a/sequencing-server/test/__snapshots__/command-types.spec.ts.snap b/sequencing-server/test/__snapshots__/command-types.spec.ts.snap index cea9e21917..ab5448338b 100644 --- a/sequencing-server/test/__snapshots__/command-types.spec.ts.snap +++ b/sequencing-server/test/__snapshots__/command-types.spec.ts.snap @@ -468,6 +468,10 @@ declare global { optionals?: { allowable_ranges?: VariableRange[]; allowable_values?: unknown[]; sc_name?: string }, ): ENUM; + function REF( + type: T, + ): T; + // @ts-ignore : 'GroundEpoch' and 'Step' found in JSON Spec function REQUEST(name: string, epoch: GroundEpoch, ...steps: [Step, ...Step[]]): RequestEpoch; @@ -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; @@ -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 { @@ -1217,6 +1227,24 @@ export function ENUM( return { name, enum_name, type: VariableType.ENUM as unknown as VARIABLE_ENUM, allowable_ranges, allowable_values, sc_name }; } +export function REF( + 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 @@ -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...' }; @@ -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 && @@ -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); " `; diff --git a/sequencing-server/test/seqjson-to-edsl.spec.ts b/sequencing-server/test/seqjson-to-edsl.spec.ts index 8e4a12c626..f96bc924b7 100644 --- a/sequencing-server/test/seqjson-to-edsl.spec.ts +++ b/sequencing-server/test/seqjson-to-edsl.spec.ts @@ -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', () => {