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

After and await seem to not work correctly #30

Open
JanEricNitschke opened this issue Oct 10, 2024 · 10 comments
Open

After and await seem to not work correctly #30

JanEricNitschke opened this issue Oct 10, 2024 · 10 comments

Comments

@JanEricNitschke
Copy link
Contributor

I wanted to run this example from the readme:

const var score = 5!
after ("click") { score = score + 1! }
print(await next score)!

and first got an error that "click" is an invalid event. I had a look at the code and it looks like the correct one is "mouseclick".
But even with that i get an error

$ dreamberd tictactoe.db
IndexError: list index out of range
@JanEricNitschke
Copy link
Contributor Author

Here is the full python traceback:

 dreamberd -s tictactoe.db
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\users\jan-eric\.local\bin\dreamberd.exe\__main__.py", line 7, in <module>
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\__init__.py", line 126, in main
    run_file(args.file)
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\__init__.py", line 98, in run_file
    interpret_code_statements_main_wrapper(statements, namespaces, [], [{}])
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 1509, in interpret_code_statements_main_wrapper
    interpret_code_statements(statements, namespaces, async_statements, when_statement_watchers)
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 1474, in interpret_code_statements
    elif retval := interpret_statement(statement, namespaces, async_statements, when_statement_watchers):
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 1329, in interpret_statement
    val = evaluate_expression(statement.expression, namespaces, async_statements, when_statement_watchers)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 722, in evaluate_expression
    retval = evaluate_expression_for_real(expr, namespaces, async_statements, when_statement_watchers, ignore_string_escape_sequences)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 797, in evaluate_expression_for_real
    return evaluate_normal_function(expr, func.value, namespaces, args, when_statement_watchers)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 87, in evaluate_normal_function
    return interpret_code_statements(func.code, namespaces + [new_namespace], [], when_statement_watchers + [{}]) or DreamberdUndefined()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 1474, in interpret_code_statements
    elif retval := interpret_statement(statement, namespaces, async_statements, when_statement_watchers):
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 1329, in interpret_statement
    val = evaluate_expression(statement.expression, namespaces, async_statements, when_statement_watchers)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 722, in evaluate_expression
    retval = evaluate_expression_for_real(expr, namespaces, async_statements, when_statement_watchers, ignore_string_escape_sequences)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 797, in evaluate_expression_for_real
    return evaluate_normal_function(expr, func.value, namespaces, args, when_statement_watchers)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 87, in evaluate_normal_function
    return interpret_code_statements(func.code, namespaces + [new_namespace], [], when_statement_watchers + [{}]) or DreamberdUndefined()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 1474, in interpret_code_statements
    elif retval := interpret_statement(statement, namespaces, async_statements, when_statement_watchers):
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 1303, in interpret_statement
    namespaces[-1] |= (prev_namespace := prev_namespace | wait_for_async_nexts(all_async_nexts, namespaces))
                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Jan-Eric\pipx\venvs\dreamberd\Lib\site-packages\dreamberd\interpreter.py", line 1102, in wait_for_async_nexts
    new_namespace[mod_name] = Name(mod_name, v.prev_values[i])
                                             ~~~~~~~~~~~~~^^^
IndexError: list index out of range

@vivaansinghvi07
Copy link
Owner

I appreciate you finding all these issues! I’ll have them fixed soon

@JanEricNitschke
Copy link
Contributor Author

Awesome, thanks! If you have any pointers i could also try to take one of these issues. I tried to start with the "await next" but didnt manage to properly understand all of the code yet.

@JanEricNitschke
Copy link
Contributor Author

JanEricNitschke commented Oct 12, 2024

And just for reference, this is the program i am trying to run:

const var board = [0, 1, 2, 3, 4, 5, 6, 7, 8]!

var const player = "X"!

funci game_won(game_board) => {
   if (game_board[-1]===player & game_board[0]===player & game_board[1]===player) {
      return true!
   }
   if (game_board[2]===player & game_board[3]===player & game_board[4]===player) {
      return true!
   }
   if (game_board[5]===player & game_board[6]===player & game_board[7]===player) {
      return true!
   }
   if (game_board[-1]===player & game_board[2]===player & game_board[5]===player) {
      return true!
   }
   if (game_board[0]===player & game_board[3]===player & game_board[6]===player) {
      return true!
   }
   if (game_board[1]===player & game_board[4]===player & game_board[7]===player) {
      return true!
   }
   if (game_board[-1]===player & game_board[3]===player & game_board[7]===player) {
      return true!
   }
   if (game_board[1]===player & game_board[3]===player & game_board[5]===player) {
      return true!
   }
   return false!
}

funci board_full(game_board) => {
   return game_board[-1];==0 & game_board[0];==1 & game_board[1];==2 & game_board[2];==3 & game_board[3];==4 & game_board[4];==5 & game_board[5];==6 & game_board[6];==7 & game_board[7];==8!
}

funci player_turn() => {
   print ("Player €{player} enter your move (0-8)!")!
   show_board()!
   await  next board!
}

funci swap_player() => {
   if (player === "X") {
      player[0] = "O"!
   }
   if (player === "O") {
      player[0] = "X"!
   }
}

funci show_board() => {
   print  ('€{board[-1]} | €{board[0]} | €{board[1]}')!
   print  ("---------")!
   print  ('€{board[2]} | €{board[3]} | €{board[4]}')!
   print  ("---------")!
   print  ('€{board[5]} | €{board[6]} | €{board[7]}')!
}

funci play() => {
   player_turn()!
   swap_player()!
   play()!
}

after "keyclick" {
   const const index = Number(event.key) - 1!
   board[index] = player!
}

when (game_won(board) === true) {
   print("Player €{player} wins the game!")!
   show_board()!
   exit()!
}

when (board_full(board) === true) {
   print("Game Drawn!")!
   show_board()!
   exit()!
}

play()!


@JanEricNitschke
Copy link
Contributor Author

Made PRs to fix all of the others, but this one is still a bit too deep into complicated logic for me.

@JanEricNitschke
Copy link
Contributor Author

JanEricNitschke commented Oct 16, 2024

I think i am making some progress:

In the simple "mouseclick" example, the code Here seems to be going wrong.

We have

name = 'score_2035826893696__next'
nexts = {'score'}

And so the check seems to fail.


But also this seems relevant. I think it needs to be an == (same here probably), otherwise it always proceeds instantly without waiting.

Adjusting that makes the example above run without an error but it prints 5 instead of 6.


I now also changed this block to just always set the "next" value to v.value and that seems to work in the simple example.

@JanEricNitschke
Copy link
Contributor Author

JanEricNitschke commented Oct 16, 2024

Got it to generally work now. Now i am stuck on my larger program again.

Whenever i perform a keyclick to make a move, the when check is performed BEFORE the board has been updated. Additionally, it seems to just go right back to waiting instead of continuing in my gameplay loop.

Minimal example to reproduce:

var var score = [1]!
after ("mouseclick") { score[-1] = score[-1] + 1! }
when (score[-1] > 0) {
   print(score)!
}

This initially prints [1] from the initial check of the when, but also does so after the first click. Where as this version:

var var score = 1!
after ("mouseclick") { score = score + 1! }
when (score > 0) {
   print(score)!
}

print 1 and after the first click prints 2.


This seems to be due to this part here. This triggers the watcher before the actual assignment happens and the addition to the visited_whens prevents a trigger later when it actually has been updated.

@vivaansinghvi07
Copy link
Owner

Sorry for the late reply (was on a break), but thank you for all the work you've done so far! I've merged all your other PRs, and it looks like your modifications to the code in the second to last reply are all spot on. Regarding your last reply, I agree on your description of where the bug is happening:

when_watchers = get_code_from_when_statement_watchers(id(value_to_modify), when_statement_watchers)
for when_watcher in when_watchers:  # i just wanna be done with this :(
    if any([when_watcher == x for x in visited_whens]): 
        continue
    condition, inside_statements = when_watcher
    condition_val = evaluate_expression(condition, namespaces, async_statements, when_statement_watchers)
    execute_conditional(condition_val, inside_statements, namespaces, when_statement_watchers)
    visited_whens.append(when_watcher)

if not remaining_indexes:  # perform actual assignment here
    value_to_modify.assign_index(index, new_value)
else:
    assign_variable_helper(value_to_modify.access_index(index), remaining_indexes)

I think this could be alleviated by moving things so that it is:

if not remaining_indexes:  # perform actual assignment here
    value_to_modify.assign_index(index, new_value)
else:
    assign_variable_helper(value_to_modify.access_index(index), remaining_indexes)

when_watchers = get_code_from_when_statement_watchers(id(value_to_modify), when_statement_watchers)
for when_watcher in when_watchers:  # i just wanna be done with this :(
    if any([when_watcher == x for x in visited_whens]): 
        continue
    condition, inside_statements = when_watcher
    condition_val = evaluate_expression(condition, namespaces, async_statements, when_statement_watchers)
    execute_conditional(condition_val, inside_statements, namespaces, when_statement_watchers)
    visited_whens.append(when_watcher)

Feel free to make all this into a PR (or let me know if there's another issue) if you want!

@JanEricNitschke
Copy link
Contributor Author

Thanks a ton! And dont feel any pressure from me, i realize that this is a "for fun" hobby project, but i am very grateful that it is there for use in my own :).

I am currently working on a branch when i added pre-commit and did formatting and so on. So i will move these changes afterwards into something you can easily merge here.

I found another thing that was stopping my program from working but i think that was just my mistake. Changing an entry in a list wasnt actually adding to its previous values and so the await next never finished. I have now added a helper variable for that but encoutnered another issue. Will let you know when i understand what is happening.

@JanEricNitschke
Copy link
Contributor Author

Got a fully working version now: https://github.com/JanEricNitschke/TicTacToe/actions/runs/11386283921/job/31678124278#step:5:21

Will swap this to your PyPI hosted one once it has everything in that i need.

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

2 participants