Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Compiler] Variable "has no value" when compiled (interpreted works) #5451

Open
SkySpiral7 opened this issue Dec 23, 2023 · 4 comments
Open
Assignees
Labels
status.wontfix Change requested by ticket will not be done (should be elaborated in comments). type.bug Ticket describes an abnormal behavior, not conforming to the specs or expectation. type.compiler Red compiler related issues.

Comments

@SkySpiral7
Copy link

Describe the bug
Confusing compilation behavior is wrong and inconsistent with interpreted. For some reason the variable "has no value".

To reproduce
Unfortunately the minimum reproducible example is a little large:

Red []

print ""
print ""

deltaIterator: context [
   someConstant: 64
   deltaStream: 64

   parseNext: does [
      prin "top deltaStream = "
      print deltaStream
      switch deltaStream reduce [
         someConstant [
            prin "switch deltaStream = "
            print deltaStream
         ]
      ]
   ]
]

applyDelta: does [
   deltaItr: make deltaIterator []
   print "before parseNext"
   deltaItr/parseNext
   print "after parseNext"
]
applyDelta

When compiling this code with redc -c or redc -r then running it, it will fail with "Script Error: deltaStream has no value" inside the switch even though it can print fine just before that.

Additionally redc -c will work with any of these (illogical) changes:

  • If deltaStream is moved outside of deltaIterator.
  • If deltaStream is moved inside of deltaIterator/parseNext.
  • If deltaIterator/parseNext switch statment doesn't reduce.
  • If the lines for applyDelta are put directly in the red script (instead of in a function).

Expected behavior
Running the interpreter (or compiling with -e) correctly prints "switch deltaStream = 64".

Platform version

-----------RED & PLATFORM VERSION----------- 
RED: [ branch: "master" tag: #v0.6.4 ahead: 5075 date: 22-Dec-2023/9:07:34 commit: #6cb7d502bcbfae8b00630adee6561909eee2b478 ]
PLATFORM: [ name: "Ubuntu 22.04.3 LTS" OS: 'Linux arch: 'x86_64 version: 6.2.0 build: {#40~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 16 10:53:04 UTC 2} ]
--------------------------------------------
@hiiamboris hiiamboris added type.bug Ticket describes an abnormal behavior, not conforming to the specs or expectation. type.compiler Red compiler related issues. labels Dec 24, 2023
@dockimbel dockimbel self-assigned this Dec 25, 2023
@dockimbel
Copy link
Member

dockimbel commented Dec 30, 2023

After a short analysis, I am not still not sure if it is a compiler limitation (most probably) or just a bug.

The core issue is that switch (like most other control flow functions when compiled) requires a static block as second argument. If you provide a dynamic one (like here generating it with reduce), you are on your own, as the compiler cannot statically analyze what switch will get as second argument anymore. In such case, it may work without issue, or not, depending on what you provide.

I will do a more in-depth investigation in the next days to get to the bottom of it, though, in the meantime, you can use at least two workarounds:

  1. Set explicitly deltaStream value when cloning the object:
deltaItr: make deltaIterator [deltaStream: 100]
  1. Force the binding of the reduce argument block to the local object:
switch deltaStream bind reduce [...] self

Anyway, I am working on deprecating the high-level compiler partially (or completely), so that all provided Red code will be directed to the interpreter, getting rid of those problematic static/dynamic combos edge cases for the compiler. Such cases can be solved but the increase in complexity in the compiler internals is just not worth the effort. They are better (cleaner, faster, shorter) ways.

@SkySpiral7
Copy link
Author

It doesn't make sense to me that switch takes a static block, I expected it to bind to the self by default (which would match interpreted). Your work around #2 does work however #1 doesn't: deltaItr: make deltaIterator [deltaStream: 64] has the same "no value" error. The reason the value 100 didn't fail is because the switch statement doesn't match and therefore the deltaStream value is not accessed.

I'm guessing by "high-level compiler" you mean compiling ahead of time instead of JIT. Being able to do redc -e -r is pretty fundamental to distribution but AOT vs JIT doesn't make much difference. I wouldn't mind redc -c being removed and -e being the new default. AOT would be better but maybe it contradicts Red design at a fundamental level such that it would never be possible (or maybe just impractical).

@dockimbel dockimbel added the status.wontfix Change requested by ticket will not be done (should be elaborated in comments). label Jan 17, 2024
@dockimbel
Copy link
Member

dockimbel commented Jan 17, 2024

After a deeper analysis, I confirm that it is a compiler limitation: the deltaStream word in the reduce argument block is stored (along with that block) in redbin format with a binding to an empty context, as the compiler in the above case compiles the objects entirely into code, so that the compiled context and the one stored in redbin format are not linked together. The result is that the inner deltaStream is pulling its value from an empty context in redbin format where all the fields are unset.

It doesn't make sense to me that switch takes a static block

I should have used "literal" instead of "static" there to avoid misunderstanding.

The reason the value 100 didn't fail is because the switch statement doesn't match and therefore the deltaStream value is not accessed.

You're right, I've missed that, sorry.

I'm guessing by "high-level compiler" you mean compiling ahead of time instead of JIT

I meant the Red to Red/System compiler which is currently an AOT one. In the future, we will have a JIT one, which is a much better fit for Red semantics.

Being able to do redc -e -r is pretty fundamental to distribution

We're keeping that of course.

AOT would be better but maybe it contradicts Red design at a fundamental level such that it would never be possible (or maybe just impractical).

That's exactly right.

@dockimbel
Copy link
Member

I will leave that ticket open with the "wontfix" status until we drop the Red compiler. Once that done, we'll close all the "type.compiler" tickets all together.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status.wontfix Change requested by ticket will not be done (should be elaborated in comments). type.bug Ticket describes an abnormal behavior, not conforming to the specs or expectation. type.compiler Red compiler related issues.
Projects
None yet
Development

No branches or pull requests

3 participants