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

Non deterministic behaviour when reading variables with lifetimes #46

Open
Joshix-1 opened this issue Dec 28, 2024 · 10 comments
Open

Non deterministic behaviour when reading variables with lifetimes #46

Joshix-1 opened this issue Dec 28, 2024 · 10 comments

Comments

@Joshix-1
Copy link
Contributor

I have the following script. It's supposed to count from -1 to 2220 while waiting 1 second between every print.

var const i = -1!

when (i + 1 < 2222) {
   const const time<1s> = waiting!

   var const j = one!
   when(j) {
      if (time == waiting) {
         j = j + one!
      }
      if (time ;= waiting) {
         print(i)!
         i = i + one!
      }
   }
}

Sometimes it prints:

Warning: Public global variable `pivo` access failed.
-1
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
dreamberd.base.NonFormattedError: Variable is undefined.

During handling of the above exception, another exception occurred:

dreamberd.base.InterpretationError: __unnamed_file__, line 8

        if (time == waiting) {

Variable is undefined.

Sometimes only -1:

Warning: Public global variable `pivo` access failed.
-1
dreamberd.base.NonFormattedError: Variable is undefined.

During handling of the above exception, another exception occurred:

dreamberd.base.InterpretationError: __unnamed_file__, line 8

        if (time == waiting) {

Variable is undefined.

There's probably some kind of race-condition when trying to remove the variables from the thread. I guess a lock somewhere could fix it.

@Joshix-1
Copy link
Contributor Author

The following patch makes the issue less likely to occur:

diff --git a/dreamberd/builtin.py b/dreamberd/builtin.py
index f1bc374..6fa1cc8 100644
--- a/dreamberd/builtin.py
+++ b/dreamberd/builtin.py
@@ -376,8 +376,8 @@ class Variable:
     def value(self) -> DreamberdValue:
         if self.lifetimes:
             return self.lifetimes[0].value
-        raise NonFormattedError("Variable is undefined.")
-    
+        return DreamberdString(self.name)
+
 def all_function_keywords() -> list[str]:
 
     # this code boutta be crazy

@Joshix-1
Copy link
Contributor Author

Joshix-1 commented Dec 28, 2024

But with that patch i get after 78 (or at some after some other number) the error RecursionError: maximum recursion depth exceeded

@vivaansinghvi07
Copy link
Owner

Thank you for your contributions! I think if that patch seems to work I would just increase the maximum recursion limit in the main __init__.py file, as during creation I made the bad design decision of checking if when statements are activated within variable assignment, which ends up recursing into assign -> run when statement -> assign -> run when statement -> ...

@vivaansinghvi07
Copy link
Owner

vivaansinghvi07 commented Dec 29, 2024

Actually, nevermind -- I forgot I had already done that; I think the constant updating of j would just have to be changed to be less often or something (like adding calls to sleep, if implemented within the language I can't remember) as each update adds a few more stack frames.

@Joshix-1
Copy link
Contributor Author

After thinking about the patch i think it's bad. It probably should also check if the name is numeric and then return a numeric value.

the whole reason for the j updates is, that there is no gold way to sleep. I tried to just listen with when on the end of lifetime, but that didn't work. (As described in the Readme)

i've locally increased the stack limit even further and that resulted in really high ram usage (over 40GB). So that's not really practical

it would probably best to not do recursive calls

@vivaansinghvi07
Copy link
Owner

Yeah, changing the inner workings like that definitely would take a while though -- I think for the time being we could add a sleep function into the language

@vivaansinghvi07
Copy link
Owner

I just pushed a commit that adds a sleep function so it should make your use case a lot easier to implement

@Joshix-1
Copy link
Contributor Author

A sleep function is kind of boring. The original spec didn't mention it

@Joshix-1
Copy link
Contributor Author

Joshix-1 commented Dec 29, 2024

I think the following would be a better patch, but it is also really hacky

diff --git a/dreamberd/builtin.py b/dreamberd/builtin.py
index 8848e3b..1c878c2 100644
--- a/dreamberd/builtin.py
+++ b/dreamberd/builtin.py
@@ -6,7 +6,7 @@ import math
 from abc import ABCMeta, abstractmethod
 from dataclasses import dataclass, field
 from typing import Callable, Optional, Union
-from dreamberd.base import NonFormattedError
+from dreamberd.base import NonFormattedError, Token, TokenType
 
 from dreamberd.processor.syntax_tree import CodeStatement
 
@@ -377,8 +377,10 @@ class Variable:
     def value(self) -> DreamberdValue:
         if self.lifetimes:
             return self.lifetimes[0].value
-        raise NonFormattedError("Variable is undefined.")
-    
+        # local import to avoid problems with recursive imports
+        from dreamberd.interpreter import determine_non_name_value
+        return determine_non_name_value(Token(TokenType.STRING, self.name, -1, -1))
+
 def all_function_keywords() -> list[str]:
 
     # this code boutta be crazy

@not-nullptr
Copy link

This is intended behaviour - do not question the Perfect Language. All behaviour is intended behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants