ssm-lang / Scoria

This is an embedding of the Sparse Synchronous Model, in Haskell!
BSD 3-Clause "New" or "Revised" License
4 stars 0 forks source link

SSM time types for frontend #51

Closed hmontero1205 closed 2 years ago

hmontero1205 commented 2 years ago

Opening for visibility in case anyone has anything else to add!

John and I discussed having dedicated time types for the frontend for specifying time durations in statements like after.. something like (5 :: Ms) which then generates 5 * SSM_MILLISECONDS.

Rewbert commented 2 years ago

Maybe we can make the units functions?

ms :: Word64 -> SSMTime where SSMTime is some appropriate representation of time.

after (ms 500) r 10 after (s 2) y x

Looks a little less chunky, and there's no need to annotate it with any type

j-hui commented 2 years ago

@Rewbert that would probably be more idiomatic, but is there any way to make it postfix?

Rewbert commented 2 years ago

Unfortunately not. We can only write prefix & infix functions.

hmontero1205 commented 2 years ago

Would it make sense to add SSMTime as a valid variable type? I imagine there could be use cases for dynamically computing sleep/assignment time.

Rewbert commented 2 years ago

Hm then maybe it makes sense just keeping it as Exp Word64, since that already supports that.

Rewbert commented 2 years ago

I think maybe the easiest thing to do (least amount of work) is to keep it as a Exp Word64 and have that be some unit of time (e.g ms), and then provide helper functions ms :: Exp Word64 -> Exp Word64 to convert a 5 to 5000.

If we want to generate more specific code like your initial suggestion we probably want to add a dedicated time type. However, we would then replicate some functionality that SSMExp already implements.

j-hui commented 2 years ago

Unfortunately not. We can only write prefix & infix functions.

I played around briefly with the PostfixOperators language extension, but that only works with symbols.

But you're right, doing prefix is much easier. If we can decide on a neat infix operator we could do something like:

(#) = flip ($)
x = 4 # ms

Purely cosmetic, but yeah definitely neater than my suggestion. Are there existing symbolic suggestions for a flipped $ operator?

I would be hesitant to define ms as (* 1000) (lifted to SSMExp) since that is predicated on the base resolution being fixed at microseconds. Doing someting like after 1 v e should not be well-defined since that base resolution of the time is platform-dependent.

Ultimately, I do think there should be a dedicated time type in the language, to force the user to specify the time units if anything. Under the hood this will be type aliased to u64 but that shouldn't be visible to the user. But that will certainly involve additional cases to the way we evaluate SSMExp, and some helpers for lifting arithmetic operators to work on time values.

j-hui commented 2 years ago

Ah, the "canonical" flipped $ operator is &: https://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Function.html

hmontero1205 commented 2 years ago

John and I chatted a bit more and we think a reasonable compromise would be to do something like changing the signature of after to after :: SSMTime -> Ref a -> Exp a -> SSM (), where SSMTimes are constructed like Sec <Word64-val> or MilliSec <Word64-val>. SSMTime's wouldn't be introduced to the frontend typesystem to avoid redundancy. This method would also avoid base resolution being done too high in the compiler stack -- we simply pass a SSMTime to a platform's codegen and let it do the conversion.