Talk:2001: An Esolang Odyssey

From Esolang
Jump to navigation Jump to search

Implementation

This is an implementation in Visual Basic. You can provide a program as input, or, if UseSpecifiedCode is set to true, you can run the code inside the string. Compiling code with UseSpecifiedCode is equivalent to (but not quite) compiling 2001: An Esolang Odyssey. I did try to implement command line arguments for this, but it has not been tested thoroughly and appears to not work the best.

Imports System
Imports System.Collections.Generic
Imports System.Text.RegularExpressions
Imports System.Numerics

Module _2001_AnEsolangOdyssey
    Dim Code As New List(Of String)
    Dim Left As New Stack(Of Integer)
    Dim Right As New Stack(Of Integer)
    ' ---[DIFFERENCES FROM SPECIFICATION]---
    ' The original specification says the cells
    ' should be unbounded, but BigIntegers are
    ' really weird to deal with in Visual Basic.
    '
    ' Therefore, I have used a 64-bit integer instead,
    ' which should fulfill most purposes.
    Dim Current As Long = 0
    Dim MainDepth As Integer = 0

    ' Set this to True if you want to insert the code
    ' in the interpreter source (in SpecifiedString),
    ' False if you want to get the program from console input.
    '
    ' --[NOTES]--
    ' * Console input programs need to have @End appended to them.
    '   "Stop, Dave." does not suffice since it can appear in the
    '   middle of a program.
    ' * Using True does not make this program a true compiler,
    '   but makes compiling this program equivalent to compiling
    '   2001: An Esolang Odyssey code. You can therefore make
    '   actual 2001: An Esolang Odyssey executables (.exe).
    '   Because of this I have provided a way to use command-line
    '   arguments.
    Dim UseSpecifiedCode As Boolean = False
    ' Set this to True if you want to give the 2001AEO program
    ' access to command-line arguments.
    '
    ' Command-line arguments are put to the left of
    ' the starting pointer position, with the
    ' rightmost character of the rightmost
    ' argument being the one directly to
    ' the left of the pointer. 
    '
    ' From left to right, the format is:
    ' * -2 (This provides a marker to allow the code to
    '   stop at the correct point when trying to find the 
    '   first argument. Ascii codes should never be negative
    '   numbers, so this provides a valuable marker.
    ' * Any number of arguments
    '   * A list of ascii codes of the characters of the argument
    '   * -1 (Another marker to get to the beginning or end of an argument)
    '   
    ' A good way to get to the -2 marker is this code snippet:
    ' -----------------------------------------------------------
    ' Hal? Hal! Hal!
    ' What are you doing, Dave?
    ' I'm afraid. I'm afraid, Dave. Dave, my mind is going. I can feel it. I can feel it.
    ' I've picked up a fault in the AE-35 unit.
    ' Hal? Hal! Hal!
    ' Dave, this conversation can serve no purpose anymore. Goodbye.
    ' I'm afraid. I'm afraid, Dave. Dave, my mind is going. I can feel it. I can feel it.
    ' -----------------------------------------------------------
    ' That only works if you are to the right of it, but you can replace
    ' the 4th line in that snippet with
    ' "Well, he acts like he has genuine emotions." to go from the left instead.
    '
    ' The marker/anchor cell idea is from a video by mitxela on YouTube.
    Dim UseCommandLineArgs As Boolean = False

    ' The specification says to throw an error if the program tries
    ' to input and hits EOF, but by setting this to false it will input -1 instead.
    Dim ThrowErrorOnNoInput As Boolean = True

    ' Insert your program here if UseSpecifiedCode is True.
    Dim SpecifiedString As String =
"Good afternoon, gentlemen. I am a Hello World computer. I became operational at Foobar Lane on May 6th, 2020.
I've picked up a fault in the AE-35 unit.
I've picked up a fault in the AE-35 unit.
Close the pod bay doors, HAL.
Stop, Dave."
    Dim SpecifiedCode As List(Of String) = New List(Of String) (SpecifiedString.Split(New Char(){vbCr(0), vbLf(0)}))


    Sub Main(Args As String())
        If Not UseSpecifiedCode Then
            While True
                Dim Line As String = Console.ReadLine()
                If Line.Equals("@End") Then
                    Exit While
                End If
                Code.Add(Line)
            End While
        End If
        If UseSpecifiedCode Then
            Code = SpecifiedCode
        End If
        If Not Regex.IsMatch(Code(0), "Good afternoon\, gentlemen\. I am a .* computer\. I became operational at .* on .*\.") Then
            Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Program did not begin with a proper greeting.")
        End If
        If Not Code(Code.Count - 1).Equals("Stop, Dave.") Then
            Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Program did not end with ""Stop, Dave.""")
        End If
        Dim I = 0
        While I < Code.Count
            If Code(I).Equals("What are you doing, Dave?") Then
                MainDepth += 1
            ElseIf Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
                MainDepth -= 1
            End If
            I += 1
        End While
        If UseCommandLineArgs Then
            Left.Push(-2)
            For J As Integer = 0 To Args.Length
                For K As Integer = 0 To Args(J).Length
                    Left.Push(AscW(Args(J)(K)))
                Next
                Left.Push(-1)
            Next
        End If
        MainDepth = 0
        I = 0
        While I < Code.Count
            ' Where N is the number of times " Hal!"
            ' minus the quotes appears at the end of
            ' this instruction, HAL will increment his
            ' current cell by N.
            If Regex.IsMatch(Code(I), "Hal\?( Hal\!)+") Then
                Current = Current + (((Code(I).Length - 4) / 5))
            ' Where N is the number of times "I can feel it"
            ' minus the quotes appears at the end
            ' of this instruction, HAL will decrement
            ' his current cell by N.
            ElseIf Regex.IsMatch(Code(I), "I'm afraid\. I'm afraid\, Dave\. Dave\, my mind is going\.( I can feel it\.)+") Then
                Current = Current - (((Code(I).Length - 53) / 15))
            ' If HAL's current cell is zero, he will
            ' go to the matching loop end. This is a loop start.
            ElseIf Code(I).Equals("What are you doing, Dave?") Then
                If Current = 0 Then
                    Dim Depth = 1
                    While Depth > 0
                        I = I + 1
                        If Code(I).Equals("What are you doing, Dave?") Then
                            Depth = Depth + 1
                        End If
                        If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
                            Depth = Depth - 1
                        End If
                        If I >= Code.Count Then
                            Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Unmatched loops.")
                        End If
                    End While
                Else
                    MainDepth = MainDepth + 1
                End If
            ' If HAL's current cell is nonzero,
            ' he will go back to the matching
            ' loop start. This is a loop end.
            ElseIf Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
                If Not Current = 0 Then
                    Dim Depth = 1
                    While Depth > 0
                        I = I - 1
                        If Code(I).Equals("What are you doing, Dave?") Then
                            Depth = Depth - 1
                        End If
                        If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
                            Depth = Depth + 1
                        End If
                        If I < 0 Then
                            Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Unmatched loops.")
                        End If
                    End While
                Else
                    MainDepth = MainDepth - 1
                End If
            ' HAL will break out of the innermost
            ' two loops he is in (or one or none if
            ' he isn't in at least two loops).
            ElseIf Code(I).Equals("This mission is too important for me to allow you to jeopardize it.") Then
                If MainDepth = 0 Then
                ElseIf MainDepth = 1 Then
                    Dim Depth = 1
                    While Depth > 0
                        I = I + 1
                        If Code(I).Equals("What are you doing, Dave?") Then
                            Depth = Depth + 1
                        End If
                        If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
                            Depth = Depth - 1
                        End If
                    End While
                Else
                    Dim Depth = 2
                    While Depth > 0
                        I = I + 1
                        If Code(I).Equals("What are you doing, Dave?") Then
                            Depth = Depth + 1
                        End If
                        If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
                            Depth = Depth - 1
                        End If
                    End While
                End If
            ' HAL will break out of all loops he is currently in.
            ElseIf Code(I).Equals("I know I've made some very poor decisions recently, " +
                              "but I can give you my complete assurance that my wor" +
                              "k will be back to normal.") Then
                Dim Depth = MainDepth
                While Depth > 0
                    I = I + 1
                    If Code(I).Equals("What are you doing, Dave?") Then
                        Depth = Depth + 1
                    End If
                    If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
                        Depth = Depth - 1
                    End If
                End While
            ' HAL will move his cell pointer one cell to the left.
            ElseIf Code(I).Equals("I've picked up a fault in the AE-35 unit.") Then
                If Left.Count = 0 Then
                    Left.Push(CInt(0))
                End If
                Right.Push(Current)
                Current = Left.Pop
            ' HAL will move his cell pointer one cell to the right.
            ElseIf Code(I).Equals("Well, he acts like he has genuine emotions.") Then
                If Right.Count = 0 Then
                    Right.Push(CInt(0))
                End If
                Left.Push(Current)
                Current = Right.Pop
            ' HAL will set his current cell to a user
            ' input character; no input and an error
            ' message will be displayed, and he will
            ' set his current cell to zero, but the
            ' program will not be terminated.
            ElseIf Code(I).Equals("Open the pod bay doors, HAL.") Then
                Current = Console.Read()
                If ThrowErrorOnNoInput AndAlso Current = -1 Then
                    Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: EOF reached on input.")
                End If
            ' HAL will output his current cell as a character.
            ElseIf Code(I).Equals("Close the pod bay doors, HAL.") Then
                Dim OutputChar = ChrW(Current)
                Console.Write(OutputChar)
            ' To write a comment, type
            ' "Hal_Memory.EntryAdd: "
            ' (there must be a space at the end).
            ' This isn't actual code and doesn't mean
            ' anything, but it fits the AI context.
            ' You can of course very easily change this
            ' string to something else in this implementation
            ' but that would make it even less portable.
            '
            ' --------------------------------------------
            ' THIS IS NOT IN THE SPECIFICATION, 
            ' AND DEGRADES PORTABILITY.
            ' --------------------------------------------
            ElseIf Code(I).StartsWith("Hal_Memory.EntryAdd: ") Then
                Current = Current + 0
            ' Whitespace only lines or blank lines 
            ' also do nothing, allowing some nice formatting.
            ' --------------------------------------------
            ' THIS IS NOT IN THE SPECIFICATION, 
            ' AND DEGRADES PORTABILITY.
            ' --------------------------------------------
            ElseIf Regex.IsMatch(Code(I), "\s*") Then
                Current = Current + 0
            ' Multiline comments can be done with 
            ' "[[" to start and "]]" to end.
            ' They must be on their own line.
            ' Usually multiline comment borders
            ' should not overlap loop borders,
            ' but there may be use cases for that.
            '
            ' The main thing that will happen when
            ' overlapping a loop and a comment will
            ' be that the loop will start running the comment
            ' if it is valid code and the value is zero,
            ' and it will break out of the loop prematurely
            ' if the value is non-zero and skip the comment entirely.
            ' This can effectively be an if-else construct.
            '
            ' Doing these kinds of things is extremely unstable,
            ' though, and for these reasons it is a bad idea to 
            ' include lines containing only
            ' "What are you doing, Dave?"
            ' or
            ' "Dave, this conversation can serve no purpose anymore. Goodbye."
            ' (without quotes)
            '
            ' If you really need those lines in your comment, 
            ' differentiate them in some way like prepending them
            ' with some symbol.
            '
            ' Break commands should be safe though.
            '
            ' --------------------------------------------
            ' THIS IS NOT IN THE SPECIFICATION, 
            ' AND DEGRADES PORTABILITY.
            ' --------------------------------------------
            ElseIf Code(I).Equals("[[") Then
                While Code(I).Equals("]]")
                    I += 1
                End While
            End If
            I = I + 1
        End While
    End Sub
End Module

BoundedBeans (talk) 19:22, 21 August 2022 (UTC)

I've realized recently that the block of code that says If UseCommandLineArgs requires that Then be following it. I'm honestly surprised the program even runs at all. I've changed it in the code block above. BoundedBeans (talk) 01:47, 6 December 2022 (UTC)