moonsharp-devs / moonsharp

An interpreter for the Lua language, written entirely in C# for the .NET, Mono, Xamarin and Unity3D platforms, including handy remote debugger facilities.
http://www.moonsharp.org
Other
1.41k stars 213 forks source link

Compiler: Evaluate constant expressions #290

Open CallumDev opened 4 years ago

CallumDev commented 4 years ago

This updates Expressions to be able to be reduced to literals at compile time.

e.g. the expression 3 + 5 * 3 will become just LITERAL 18 in bytecode.

CallumDev commented 4 years ago

This PR uses C# 7.0 and won't cleanly apply to master yet

Benjamin-Dobell commented 4 years ago

I like the idea. However, there's a few things that make me a little bit uneasy about this.

  1. Is emitted bytecode supposed to be portable? (Honestly I'm not sure.) If so, does the .NET runtime provide floating point guarantees? Otherwise, there may be subtle differences in floating point calculations performed at runtime (variables) vs. those emitted on another host.

  2. I've only glanced over this, not run it. However, I don't believe it covers expression lists. So it could lead to surprising behaviour with:

    local a, b, c = 2 * 3, 4 + 2, 9

    being less performant than:

    local a = 2 * 3
    local b = 4 + 2
    local c = 9
    1. Profiling. I wonder in practice how common constant arithmetic is within real code-bases. Although it only happens during bytecode emission. If this is sufficiently rare, the slower bytecode generation may negatively affect some use cases. Perhaps it's safer to take a different approach; an optional optimisation pass, rather doing the work during compile/emit.
CallumDev commented 4 years ago
  1. At least the modern .NET runtime tries its best to follow IEEE 754-2008, so the same runtime version should be producing the same values as this code doesn't use vectors. As this doesn't ever re-order operations I would think it to be relatively safe.

  2. Expression lists become series of LITERAL bytecodes followed by MkTuple. I wasn't sure if it is possible to do a tuple literal.

  3. This showed noticeable speedup on at least scimark.lua, will need to somehow profile the difference in codegen time between the two, I assume the early exits should make the impact minimal.

I also noticed Pow was not implemented in Eval and implemented it there, but it seems that for this usecase it seems to produce strange results for combining negative numbers with the power operator. Occasionally it puts the unary operator as a subexpression, while Lua 5.2 behaves as if the unary negation is outside the pow.