expr icon indicating copy to clipboard operation
expr copied to clipboard

Feature request: allow multiple expressions in a single program

Open vmihailenco opened this issue 1 year ago • 4 comments

TLDR The following program should be a valid expr:

let x = 42
let y = 42
x * y

It should work like Ruby, where everything is an expression and the last expression is used as the result. Given that it works fairly well for Ruby, I guess expr-lang can be modeled just like it.

Currently what we do in Uptrace transformations, is just split the multi-line expressions into individual programs and then run them one by one. It works so far, but variables don't survive between programs and the performance is probably sub-optimal since each program requires a separate VM.

I believe OpenTelemetry does the same with multi-line OTTL so they would probably benefit as well.

A more realistic example what multi-line expressions can achieve:

let val = split(attr("foo"), "-")
setAttr("xxx", val[0])
setAttr("yyy", val[1])
deleteAttr("foo")

vmihailenco avatar Aug 10 '24 07:08 vmihailenco

Well, actually this is possible right now as well if ; added at the let ends:

let x = 42;
let y = 42;
x * y

We can improve lexer and allow \n to be treated as ;.

antonmedv avatar Aug 10 '24 07:08 antonmedv

Well, actually this is possible right now as well if ; added at the let ends:

Yes, I know, but the real program looks more like this:

let val = split(attr("foo"), "-")
setAttr("xxx", val[0])
setAttr("yyy", val[1])
deleteAttr("foo")

I guess I can rewrite it like this, but it is not as readable and debuggable:

let val = split(attr("foo"), "-"); setAttr("xxx", val[0]) && setAttr("yyy", val[1]) && deleteAttr("foo")

vmihailenco avatar Aug 10 '24 07:08 vmihailenco

I see. So, this request to add statements to Expr. I think this is nice to add via option: expr.AllowStatments().

antonmedv avatar Aug 10 '24 08:08 antonmedv

So, this request to add statements to Expr.

Maybe, but I explicitly say that "everything is an expression" so :) If we take switch in account, would it be a statement or an expression? I believe it should be an expression or it probably would not fit into the existing purpose of the language.

And if switch is an expression, why a function call or an assignment should not be?

vmihailenco avatar Aug 10 '24 08:08 vmihailenco

Statements support(or using ; to simply discard expression output) would be very helpful indeed. I'm currently having the following usecase:

assert(status_code == 0);
assert(status_message == "");
// normal expr stuff
1 + 1

Currently it's possible to work around this by

  1. Making assert return an any.
- func assert(condition bool)
+ func assert(condition bool) any // always returns nil
  1. change the assert statement to assignments:
let _s1 = assert(status_code == 0);
let _s2 = assert(status_message == "");
// normal expr stuff
1 + 1

xiaoas avatar Dec 18 '24 03:12 xiaoas

I’m working on adding multi-expressions available.

antonmedv avatar Feb 09 '25 10:02 antonmedv

Done! Not this is possible to do in Expr! Expr support multiple expression separated by ;

let x = foo();
asd(x);
check();
x + 1

antonmedv avatar Mar 10 '25 16:03 antonmedv