Hacker News new | ask | show | jobs
by ljm 931 days ago
Given that it's built as a whole language, I'm curious about the choice to make no obvious distinction between 'preflight' and 'inflight' functions.

It's not obvious at a glance that you can only call inflight functions in an inflight scope, because the syntax for calling them is identical to calling a preflight function on the same object.

Do you just compile it and see where it fails?

1 comments

(engineer on the Winglang team here)

Your observation is partially correct. The language does make a distinction when you're defining new functions: you must use the "inflight" keyword annotation to define an inflight function, and most un-annotated functions are assumed to be "preflight". (The top-level scope of every Wing program has a preflight phase).

But at _call sites_ no distinction is made. We don't have have a different calling convention between calling preflight/inflight functions because the compiler uses type checking to enforce that inflight functions can only be called in inflight scopes, and preflight functions can only be called in preflight scopes. Scopes are lexical, meaning you can automatically assume when you see `inflight () => { ... }` or `inflight foo() { ... }` that all code inside that block is executed inflight, i.e. at runtime.

The neat thing here is if you're writing code to access a method on a class (typing `obj.`), your IDE's auto-completion will only show you the methods available to you based on the scope you're in. There's a short 10 second clip showing this here: https://twitter.com/rybickic/status/1720168675641102803

We've prioritized LSP support while designing the compiler to help out with this.

> In existing languages, where there is no way to distinguish between multiple execution phases, it is impossible to naturally represent this idea that an object has methods that can only be executed from within a specific execution phase.

I'm sure I'm getting the wrong end of the stick but isn't this possible to ensure using typing? Very simple dependent typing/phantom types/bog standard normal types?

The current type system is designed around the experience of writing code like the example below where objects can have two kinds of methods:

  let bucket = new cloud.Bucket();
  let api = new cloud.Api();
  
  // api.get is a preflight method - it generates cloud infrastructure
  api.post("/hello", inflight (req) => {
    // bucket.put is an inflight method - it performs data plane operations, at "runtime"
    bucket.put("data.txt", req.body ?? "empty");
  });
Importantly, if you try calling bucket.put() outside of one of these "inflight" scopes or try calling api.get() inside one of these "inflight" scopes, you'll get compilation errors - not runtime errors.

Could this style of API be achieved in an existing language? I think it's an open ended question - I'm not sure. But I reckon it gets into complex framework territory (or may require injecting modifications into existing compilers, which presents other challenges). But I'd love to see more exploration into this direction.

Okay, I partly take back what I said in my sibling post. Your "(req) => {..}" lambda has to be constrained only to contain inflight methods.

Yes, it can be done by either building the contents of the lambda in some truly horrid way (you'd effectively be building an AST at runtime). The alternative is to get hold of the AST/parse tree at runtime (which I believe.NET can do if you ask it nicely, but that is very specifically .NET) which you can then analyse.

The first way is utterly vile though workable and language agnostic, the second way is definitely tied to one platform. If there's third way I can't think of it ATM.

What I was getting at is that it seems to depend on the compiler to know the difference between preflight and inflight because the calling convention is identical.

I personally don't think it's intuitive that function calls using the same syntax either emit terraform code or JS. It's like mixing compile time macros and code into one.

With respect, and also with the understanding that I do not comprehend your domain very well so I may be talking out of my but with static typing I think it is possible, perhaps if a bit less pretty.

I can try and put something together in C# but not right now I'm afraid (it would be a good exercise for me as I've only read up on these, not actually use them personally, although I plan to start very soon for my own personal work). There was some examples going round here https://old.reddit.com/r/programming/comments/zm7f9/phantom_... which may help.

Again, I may be misunderstanding your domain completely, so bear it in mind please.