zmbc / shakespearelang

An interpreter for the Shakespeare Programming Language, implemented in Python
http://shakespearelang.com
MIT License
90 stars 18 forks source link

Input Exception #8

Closed Praxidice closed 11 months ago

Praxidice commented 5 years ago

I'm getting the 'No numeric input was given.' exception on line 376 as soon as a second number is requested. In the basic test below it reads the first number correctly, but immediately raises the exception on the second request.

I'll try to debug it and see if I can find what is causing it.

Test.
Macduff, test.
Horatio, test.
Act I: Test.
Scene I: Test.
[Enter Macduff and Horatio]
Macduff: Listen to your heart! Open your heart!
Horatio: Listen to your heart! Open your heart!
[Exeunt]
Praxidice commented 5 years ago

Ok, I think I see the issue. '\n' is being added after input(), but it is never removed during the digit extraction loop. In the next request '\n' is still there in the input buffer, so "if not self._input_buffer" is false and input doesn't get called again, leading to no digits being extracted and the exception. Removing the '\n' and adding a length check to the digit extraction loop seems to fix it... not sure if this affects char reading though.

def _run_input(self, input_op, character):
        if not self._input_buffer:
            try:
                self._input_buffer = input()
            except EOFError:
                if input_op.input_char:
                    self._character_opposite(character).value = -1
                    return
                else:
                    raise Exception('End of file encountered.')

        if input_op.input_number:
            number_input = ''
            while self._input_buffer and self._input_buffer[0].isdigit():
                number_input += self._input_buffer[0]
                self._input_buffer = self._input_buffer[1:]

            if len(number_input) == 0:
                raise Exception('No numeric input was given.')

            self._character_opposite(character).value = int(number_input)
        elif input_op.input_char:
            input_char = ord(self._input_buffer[0])
            self._input_buffer = self._input_buffer[1:]
            self._character_opposite(character).value = input_char
zmbc commented 3 years ago

@Praxidice Thank you for reporting the issue! I'm finally doing a maintenance pass on shakespearelang and I think I've found a good fix for this.

Unfortunately, the numeric input functionality of SPL was not well-defined and the behavior I made up has been somewhat buggy and surprising.

I've revised numeric input in my latest change so that requesting a number will consume all consecutive digits at the start of the input, and an optional line break. If the line break is not present, nothing more is consumed so that the rest of the line can be read as characters.

I'll close this issue when the fix is released.

zmbc commented 2 years ago

A bit late here (it's been out since January) but 1.0.0rc1 fixes this issue -- feel free to test it out!