You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Due to the way the execution environment works and the need for most of the OS language functions to be asynchronous (since they query an external Studio API), writing code for orchestration scripts can be syntactically messy, requiring the user to add async/await flags and this.keywords for any OS functions. For instance, this is what a simple trigger to send a message during a SIG meeting currently looks like:
One way to clean this up is to create a custom plugin with Babel that takes code that is more human-readable and workable, and transforms it in a middleware layer before it's saved to the database. The user only ever interacts with the nice to read/work with code, while the backend system gets the representation that's easy for it to execute.
Here's a tester implementation that gets most of the way there (see TODOs in the code for what needs to still be done):
importbabelfrom'@babel/core';import*astfrom"@babel/types";// define a babel configurationconstbabelTransformConfig={plugins: [functionorchestrationScriptTransformer(){return{visitor: {FunctionDeclaration(path){path.node.async=true;},VariableDeclaration(path){// TODO: may also need to add a check for variables that are stored as objects in the PL},Identifier(path){// don't work on the highest-level identifier// TODO: is there a more elegant way to do this? (maybe check parent?)if(path.node.name==="detector"){return;}// TODO: need to check if the expressions are anything in our library// add this keyword to member expressionif(t.isCallExpression(path.parentPath.node)){path.replaceWith(t.memberExpression(t.thisExpression(),path.node));}// skip children so we don't repeatpath.skip();},CallExpression(path){// TODO: need to check if the expressions are anything in our library// make any calls to OS functions asyncif(!t.isAwaitExpression(path.parentPath.node)){path.replaceWith(t.awaitExpression(path.node));}}},};},],// keep any white space so code stays prettyretainLines: true};consttransformOSCode=function(code,config){letoutput=babel.transformSync(code,config);returnoutput.code;}
Going back to the example above, here's what the input code can now become, and the output generated though the transformation above:
// input code (what a mentor would write)functionfeedbackOpportunity(){returnduring(venue("SIG"));}// output code (what the engine will use to execute)asyncfunctionfeedbackOpportunity(){returnawaitthis.during(awaitthis.venue("SIG"));}
// input code (what a mentor would write)functionfeedbackOpportunity(){returnduring(venue("SIG"));}
With this input code, it's actually possible (and pretty easy) to remove the return as well and just have the expression code there. In the transform, a ReturnStatement with the node starting from FunctionDeclaration would need to be added
See the orchestration-scripts-ast-transformer repo for the development code. It'll be easier to play around there and get the system working as intended before adding it into the engine.
Due to the way the execution environment works and the need for most of the OS language functions to be asynchronous (since they query an external Studio API), writing code for orchestration scripts can be syntactically messy, requiring the user to add
async/await
flags andthis.
keywords for any OS functions. For instance, this is what a simple trigger to send a message during a SIG meeting currently looks like:One way to clean this up is to create a custom plugin with Babel that takes code that is more human-readable and workable, and transforms it in a middleware layer before it's saved to the database. The user only ever interacts with the nice to read/work with code, while the backend system gets the representation that's easy for it to execute.
Here's a tester implementation that gets most of the way there (see TODOs in the code for what needs to still be done):
Going back to the example above, here's what the input code can now become, and the output generated though the transformation above:
Some helpful links:
Writing Transformations
Writing a babel transform
Custom plugins in babel
Dealing with replaced nodes
More on stopping code for added nodes
AST Explorers + Info
Babel-specific
General
ASTs in JS
Babel Documentation
Babel Plugin Handbook
@babel/parser
@babel/generator
@babel/traverse
@babel/types
More on babel types
Babel options
The text was updated successfully, but these errors were encountered: