Skip to content

adds ast builder#62109

Closed
ppisljar wants to merge 3 commits intoelastic:masterfrom
ppisljar:astbuilder
Closed

adds ast builder#62109
ppisljar wants to merge 3 commits intoelastic:masterfrom
ppisljar:astbuilder

Conversation

@ppisljar
Copy link
Copy Markdown
Contributor

@ppisljar ppisljar commented Apr 1, 2020

Summary

resolves #56748

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@ppisljar ppisljar added Feature:ExpressionLanguage Interpreter expression language (aka canvas pipeline) v8.0.0 Team:AppArch release_note:skip Skip the PR/issue when compiling release notes v7.8.0 labels Apr 1, 2020
@ppisljar ppisljar requested a review from a team as a code owner April 1, 2020 06:52
@elasticmachine
Copy link
Copy Markdown
Contributor

Pinging @elastic/kibana-app-arch (Team:AppArch)

@ppisljar ppisljar requested a review from lukeelmers April 1, 2020 06:53
@kibanamachine
Copy link
Copy Markdown
Contributor

💔 Build Failed

Failed CI Steps


Test Failures

Kibana Pipeline / kibana-intake-agent / Jest Tests.src/plugins/expressions/common/ast.ast builder best way to use it

Link to Jenkins

Standard Out

Failed Tests Reporter:
  - Test has not failed recently on tracked branches


Stack Trace

Error: expect(received).toMatchSnapshot()

New snapshot was not written. The update flag must be explicitly passed to write a new snapshot.

This is likely because this test is run in a continuous integration (CI) environment in which snapshots are not written by default.

Received value 
Object {
  "chain": Array [
    Object {
      "arguments": Object {
        "arg1": Array [
          true,
        ],
      },
      "function": "test",
      "type": "function",
    },
  ],
  "type": "expression",
}

    at Object.test (/var/lib/jenkins/workspace/elastic+kibana+pipeline-pull-request/kibana/src/plugins/expressions/common/ast/ast_builder.test.ts:107:17)
    at Object.asyncJestTest (/var/lib/jenkins/workspace/elastic+kibana+pipeline-pull-request/kibana/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:102:37)
    at resolve (/var/lib/jenkins/workspace/elastic+kibana+pipeline-pull-request/kibana/node_modules/jest-jasmine2/build/queueRunner.js:43:12)
    at new Promise (<anonymous>)
    at mapper (/var/lib/jenkins/workspace/elastic+kibana+pipeline-pull-request/kibana/node_modules/jest-jasmine2/build/queueRunner.js:26:19)
    at promise.then (/var/lib/jenkins/workspace/elastic+kibana+pipeline-pull-request/kibana/node_modules/jest-jasmine2/build/queueRunner.js:73:41)

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

Copy link
Copy Markdown
Contributor

@lukeelmers lukeelmers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still pondering this, but added a few initial thoughts.

Comment on lines +31 to +34
const createFunction = (
name: string,
args: Record<string, ExpressionAstArgument[] | ExpressionAstArgument> = {}
): ExpressionAstFunction => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's an example of how we could go about making something like createFunction type safe: #62334

However, one question to solve with this is how to deal with the builders if you can do fn.addArg() for each individual argument... how can you enforce that all provided args are present on the function when they aren't added all at once?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how can you enforce that all provided args are present on the function when they aren't added all at once?

I guess I should've rephrased this to "you can't enforce that all provided args are present on the function". So if we let folks update functions with an individual argument instead of passing all of them at once, the tradeoff we are making is that we aren't 100% sure all args have been provided.

The only way around this I can think of would be to force users to provide a full list of the required arguments when instantiating the function builder, and then allow them to manipulate the args one-by-one later. That way you'd know that no required args are missing.

Which brings another question to mind - is there a use case for removing an arg from a function?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the ability to add arguments later and remove them just makes the api way easier to consume (and refacture current string concatenation logic). however i think everything should still be possible with the above mentioned limitations (you need to provide default values for all required arguments and you cannot remove arguments).

what we are discussing here is are we willing to trade typesafety for better usability ? (we could still provide runtime checks if we opt for not being type safe here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to provide default values for all required arguments and you cannot remove arguments

Agreed, IMHO this is an acceptable tradeoff for type safety vs useability. If you are forced to provide defaults for all required args up front, then you have the safety of knowing that you aren't missing anything. And then any subsequent call to update one of those args will enforce the correct type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also try to do runtime checks, the only tricky part there is that it would probably require looking up the referenced functions from the registry to get their metadata, vs the current implementation which is much simpler in that it is static.

Comment on lines +104 to +105
// if you know everything about expression upfront use createExpression
const ast = createExpression([createFunction('test', { arg1: true })]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if having separate createX and createXBuilder functions makes this more confusing.

Thinking out loud -- What if we only provided the builders, and at the end when you call ExpressionBuilder.toAst() it goes through all of the functions & calls .toAst() on each of them?

That way you could hang on to references to functions even after they've been added to the expression, and make updates.

For example (I'm using a class-based approach for the builders here, but you get the idea):

import { expressionAstBuilder } from '../expressions/public';
const { Expression, ExpressionFunction } = expressionAstBuilder;

// create instance of expression builder with one function as the "initial state"
const myExpression = new Expression([
  new ExpressionFunction('esaggs', { index: 'abc123' }
]);

// add another function
const fn = new ExpressionFunction('foo', { bar: true });
myExpression.addFunction(fn);

// update the function you've just added
const subExpression = new Expression([...]);
// works cause you saved a reference to it
fn.addArgument('bar', subExpression);

// toAst will go through and call toAst on each of the provided functions
const ast = myExpression.toAst();

// I suppose you could also offer a way to get the string as a convenience.
// It would call toAst() and then convert it to the expression string.
const string = myExpression.toString();

@lukeelmers lukeelmers mentioned this pull request Apr 24, 2020
6 tasks
@ppisljar ppisljar closed this May 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature:ExpressionLanguage Interpreter expression language (aka canvas pipeline) release_note:skip Skip the PR/issue when compiling release notes v7.8.0 v8.0.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expression AST builder

4 participants