Symbolic Python

From Esolang
Jump to navigation Jump to search

Symbolic Python is a restricted source version of Python 2, designed by PPCG user FlipTack, in which only non-alphanumeric characters are allowed in the source code.

Specifications

Of course, I/O is impossible without the print and input functions. Consequently, the execution of SP programs differs slightly from standard Python:

  • A single Python literal is taken as input and stored in the variable named _
  • A function with the name __ is created. Given a string, this executes the string as Python code in the context of the program's global variables.
  • After execution, the value left in _ is automatically printed.

These modifications are necessary to make full programs possible.

Programming in Symbolic Python

Constants

The bulk of programming in this language is finding ways to generate specific values using only symbols. Examples of simple values and how to create them can be found below:

Constant Code
0 (False) []>[]
1 (True) []==[]
2 -~([]==[])
8 ([]==[])<<-~-~([]==[]) or -~-~-~-~-~-~-~([]==[])
'T' `[]==[]`[[]>[]]
'e' `[]>[]`[~([]>[])]
'%c' '%'+`'£'`[-~-~([]==[])]

Value generation depends highly on Python's automatic conversion of booleans to integers - []==[] evaluates to True, but acts as 1 in almost every operation. Using backticks as a shortcut call to the repr function is also very important, as this allows (through splicing syntax) the generation of individual characters.

Perhaps the most important value on this list is the last. In Python, %c is a string which, passed an integer argument using printf-style string formatting, yields the character with that code. Being able to obtain this value means that we can create any string, and thus simulate any Python program using SP's __ function, the equivalent of exec.

Variables

In Python, variables can only contain alphabetical characters, digits, and underscores. However, because the first two character sets are not allowed in SP, variables names are made entirely out of underscores - for example, the initial input (_) and the exec function (__).

Example Programs

Adding two numbers:

_=_[{}=={}]+_[[]>[]]

This expects input as a tuple or list containing two numbers. _[{}=={}] gets the first item (index 0), _[[]>[]] gets the second (index 1) and + adds them together. The result is put into the single underscore variable, which is implicitly printed.

Numbers 1-10:

_=+([]==[]),
__('_+=-~_[~([]>[])],;'*-~-~-~-~-~-~-~-~([]==[]))

The first line sets the output to a tuple containing the number 1. The second line is a pseudo-loop: a string with the instructions "get the last item in the tuple, increment it, and append it" is multiplied 9 times, and then passed to the exec function. The output is left in the single underscore variable - a tuple of the numbers (1, 2, 3, 4, 5, 6, 7, 8, 9, 10).

"Hello, World!"

____=`_`[_==_]
_=_==_
__=-~_<<-~_
___='%'+`'�'`[~_]
_=___%(__*-~__)+`_`[-_]+`_>_`[-~_]*-~_+____+', '+___%~-(__*-~-~-~__)+____+`_`[_]+`_>_`[-~_]+`'�'`[~_]+'!'

This is currently the shortest known Hello World program, submitted by PPCG user JoKing.

Quine

_="_='_='+`_`+';__(_)'";__(_)

This program outputs its own source code, once again submitted by JoKing.

Random hex digit

_=`__`[((([]==[])<<-~-~([]==[]))*-~([]==[]))-~([]==[])-~([]==[])]

Created by Cortex

Computational Class

Symbolic Python is Turing-Complete as it is possible to simulate any Python program. Any string can be created using the string formatting techniques described above, for example Python programs, which are then passed to the __ function to execute. With that being said, SP is extremely hard to use for complex algorithms, and is only designed to test Python's limits.

Example Implementation

The following is a primitive example interpreter of SP:

#!/usr/bin/python2
"""
sypy.py: Example interpreter for Symbolic Python.
Call with command line arguments: <script-file> [input]
"""

import sys
import ast

script = open(sys.argv[1]).read()

if len(sys.argv) > 2:
  _ = ast.literal_eval(sys.argv[2])
else:
  _ = None

for char in script:
  if char.isalnum():
    print("Invalid script: the %r character is banned." % char)
    quit()

def __(cmd):
  for i,j in globals().items(): locals()[i] = j
  exec cmd
  del cmd
  for i,j in locals().items(): globals()[i] = j

exec script

print _