├── rockstarpy ├── __init__.py ├── __main__.py ├── command_line.py └── transpile.py ├── tests ├── testfunccall.numbers.py ├── testfunccall.numbers.rock ├── testfunccall.variables.py ├── testfunccall.variables.rock ├── testglobal.py ├── testglobal.rock ├── fizz.py ├── fizz.rock ├── test_pronouns.py ├── test_variables.py ├── run_tests.py ├── test_calculation.py ├── test_conditionals.py ├── test_blocks.py └── test_assignment.py ├── .travis.yml ├── LICENSE ├── setup.py ├── .gitignore ├── .github └── workflows │ └── codeql-analysis.yml └── README.md /rockstarpy/__init__.py: -------------------------------------------------------------------------------- 1 | from .transpile import Transpiler 2 | -------------------------------------------------------------------------------- /tests/testfunccall.numbers.py: -------------------------------------------------------------------------------- 1 | def Multiply(Love, Life): 2 | return Love * Life 3 | print(Multiply(3, 444)) 4 | -------------------------------------------------------------------------------- /tests/testfunccall.numbers.rock: -------------------------------------------------------------------------------- 1 | Multiply takes Love and Life 2 | Give back Love of Life 3 | 4 | Say Multiply taking 3, 444 5 | -------------------------------------------------------------------------------- /rockstarpy/__main__.py: -------------------------------------------------------------------------------- 1 | from rockstarpy.command_line import command_line 2 | 3 | if __name__ == "__main__": 4 | command_line() -------------------------------------------------------------------------------- /tests/testfunccall.variables.py: -------------------------------------------------------------------------------- 1 | def Multiply(Love, Life): 2 | return Love * Life 3 | my_heart = 1 4 | the_devil = 666 5 | Multiply(my_heart, the_devil) 6 | -------------------------------------------------------------------------------- /tests/testfunccall.variables.rock: -------------------------------------------------------------------------------- 1 | Multiply takes Love and Life 2 | Give back Love of Life 3 | 4 | Put 1 into my heart 5 | Put 666 into the devil 6 | Multiply taking my heart, the devil 7 | -------------------------------------------------------------------------------- /tests/testglobal.py: -------------------------------------------------------------------------------- 1 | Desire = 100 2 | print(Desire) 3 | def Midnight(your_heart, your_soul): 4 | global Desire 5 | Desire = 5 6 | print(Desire) 7 | return your_heart 8 | print(Desire) 9 | Midnight(5, 2) 10 | print(Desire) 11 | -------------------------------------------------------------------------------- /tests/testglobal.rock: -------------------------------------------------------------------------------- 1 | Desire's a lovestruck ladykiller. 2 | Shout Desire 3 | 4 | Midnight takes your heart and your soul; 5 | Desire is water 6 | Shout Desire 7 | Give back your heart, 8 | 9 | Shout Desire 10 | Midnight taking 5, 2. 11 | Shout Desire -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | dist: bionic 3 | 4 | python: 5 | - "3.6" 6 | - "3.7" 7 | - "3.8" 8 | - "3.9-dev" 9 | - "3.10-dev" 10 | - "nightly" 11 | 12 | jobs: 13 | allow_failures: 14 | - python: "nightly" 15 | 16 | install: 17 | - python setup.py install 18 | 19 | script: 20 | - python tests/run_tests.py 21 | 22 | -------------------------------------------------------------------------------- /tests/fizz.py: -------------------------------------------------------------------------------- 1 | def Midnight(your_heart, your_soul): 2 | while your_heart >= your_soul: # this is a comment 3 | your_heart = your_heart - your_soul 4 | return your_heart 5 | Desire = 100 6 | my_world = False 7 | Fire = 3 # i love comments 8 | Hate = 5 9 | while not my_world == Desire: 10 | my_world += 1 11 | if Midnight(my_world, Fire) == False and Midnight(my_world, Hate) == False: 12 | print("FizzBuzz!") 13 | continue 14 | if Midnight(my_world, Fire) == False: 15 | print("Fizz!") 16 | continue 17 | if Midnight(my_world, Hate) == False: 18 | print("Buzz!") 19 | continue 20 | print(my_world) 21 | -------------------------------------------------------------------------------- /tests/fizz.rock: -------------------------------------------------------------------------------- 1 | Midnight takes your heart and your soul 2 | While your heart is as high as your soul (this is a comment) 3 | Put your heart without your soul into your heart 4 | 5 | Give back your heart 6 | 7 | 8 | Desire's a lovestruck ladykiller 9 | My world is empty 10 | Fire's ice (i love comments) 11 | Hate is water 12 | Until my world is Desire, 13 | Build my world up 14 | If Midnight taking my world, Fire is nothing and Midnight taking my world, Hate is nothing 15 | Shout "FizzBuzz!" 16 | Take it to the top 17 | 18 | If Midnight taking my world, Fire is nothing 19 | Shout "Fizz!" 20 | Take it to the top 21 | 22 | If Midnight taking my world, Hate is nothing 23 | Say "Buzz!" 24 | Take it to the top 25 | 26 | Whisper my world 27 | -------------------------------------------------------------------------------- /tests/test_pronouns.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import unittest 4 | 5 | sys.path = [os.path.dirname(os.path.dirname(os.path.realpath(__file__)))] + sys.path 6 | from rockstarpy.transpile import Transpiler 7 | 8 | 9 | class TestPronouns(unittest.TestCase): 10 | def test_it_if(self): 11 | rock = ["Green is 0\n", "Build it up\n"] 12 | 13 | py = ["Green = 0\n", "Green += 1\n"] 14 | 15 | self.__run_block_test(rock, py) 16 | 17 | @unittest.skip("Pronouns are not working in calculations") 18 | def test_it_until(self): 19 | rock = ["The day is 0\n", "Until the day is 7\n", "Build it up\n"] 20 | 21 | py = ["the_day = 0\n", "while not the_day == 7:\n", " the_day += 1\n"] 22 | 23 | self.__run_block_test(rock, py) 24 | 25 | def __run_block_test(self, rock, py): 26 | transpiler = Transpiler() 27 | transpiled = [transpiler.transpile_line(line) for line in rock] 28 | self.assertEqual(len(py), len(transpiled)) 29 | for py_line, transpiled_line in zip(py, transpiled): 30 | self.assertEqual(py_line, transpiled_line) 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Yan Orestes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/test_variables.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import unittest 4 | 5 | sys.path = [os.path.dirname(os.path.dirname(os.path.realpath(__file__)))] + sys.path 6 | from rockstarpy.transpile import Transpiler 7 | 8 | 9 | class TestVariables(unittest.TestCase): 10 | def test_simple_variables(self): 11 | transpiler = Transpiler() 12 | py_line = transpiler.transpile_line("X is 2\n") 13 | self.assertEqual(py_line, "X = 2\n") 14 | 15 | py_line = transpiler.transpile_line("Tommy is a rockstar\n") 16 | self.assertEqual(py_line, "Tommy = 18\n") 17 | 18 | def test_common_variables(self): 19 | transpiler = Transpiler() 20 | py_line = transpiler.transpile_line("My variable is 5\n") 21 | self.assertEqual(py_line, "my_variable = 5\n") 22 | 23 | py_line = transpiler.transpile_line("Shout the total\n") 24 | self.assertEqual(py_line, "print(the_total)\n") 25 | 26 | def test_proper_variables(self): 27 | transpiler = Transpiler() 28 | py_line = transpiler.transpile_line("Master Of The Universe is nothing\n") 29 | self.assertEqual(py_line, "Master_Of_The_Universe = False\n") 30 | 31 | 32 | if __name__ == "__main__": 33 | unittest.main() 34 | -------------------------------------------------------------------------------- /tests/run_tests.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import sys 3 | import difflib 4 | import unittest 5 | 6 | test_path = Path(__file__).resolve().parent 7 | sys.path.insert(0, str(test_path.parent)) 8 | from rockstarpy.transpile import Transpiler 9 | 10 | 11 | def check_files_identical(expected, actual): 12 | diff = difflib.unified_diff(expected, actual, fromfile="expected", tofile="actual",) 13 | line = None 14 | for line in diff: 15 | print(line, end="") 16 | if line is not None: 17 | print() 18 | assert False, "There are differences" 19 | 20 | def main(): 21 | identical_test_files = [ 22 | (file, file.with_suffix(".py")) 23 | for file in test_path.iterdir() 24 | if file.suffix == ".rock" 25 | ] 26 | for rock_path, py_path in identical_test_files: 27 | print("testing", rock_path.name) 28 | 29 | assert py_path.is_file(), f"{py_path} does not exist" 30 | 31 | transpiler = Transpiler() 32 | converted_code = "" 33 | with rock_path.open() as rockstar_file: 34 | for line in rockstar_file: 35 | converted_code += transpiler.transpile_line(line) 36 | 37 | with py_path.open() as expected_file: 38 | expected_code = expected_file.read() 39 | 40 | check_files_identical(expected_code, converted_code) 41 | 42 | suite = unittest.defaultTestLoader.discover(test_path, pattern="test_*.py") 43 | runner = unittest.TextTestRunner() 44 | runner.run(suite) 45 | 46 | 47 | if __name__ == "__main__": 48 | main() 49 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | with open("README.md") as file: 4 | long_description = file.read() 5 | 6 | setup( 7 | name="rockstar-py", 8 | version="2.1.0", 9 | author="yyyyyyyan", 10 | author_email="contact@yyyyyyyan.tech", 11 | packages=["rockstarpy"], 12 | description="Python transpiler for the esoteric language Rockstar", 13 | long_description=long_description, 14 | long_description_content_type="text/markdown", 15 | url="https://github.com/yyyyyyyan/rockstar-py", 16 | download_url="https://github.com/yyyyyyyan/rockstar-py/archive/2.1.0.zip", 17 | license="MIT", 18 | keywords="esoteric rockstar transpiler", 19 | classifiers=[ 20 | "Development Status :: 5 - Production/Stable", 21 | "Environment :: Console", 22 | "Intended Audience :: Developers", 23 | "License :: OSI Approved :: MIT License", 24 | "Natural Language :: English", 25 | "Operating System :: OS Independent", 26 | "Programming Language :: Python :: 3", 27 | "Programming Language :: Python :: 3 :: Only", 28 | "Programming Language :: Python :: 3.6", 29 | "Programming Language :: Python :: 3.7", 30 | "Programming Language :: Python :: 3.8", 31 | "Programming Language :: Python :: 3.9", 32 | "Topic :: Software Development :: Compilers", 33 | "Topic :: Software Development :: Interpreters", 34 | ], 35 | python_requires=">= 3.6", 36 | entry_points={ 37 | "console_scripts": ["rockstar-py=rockstarpy.command_line:command_line"] 38 | }, 39 | ) 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User 2 | TODO 3 | 4 | # PyCharm 5 | .idea/ 6 | 7 | # Byte-compiled / optimized / DLL files 8 | __pycache__/ 9 | *.py[cod] 10 | *$py.class 11 | 12 | # C extensions 13 | *.so 14 | 15 | # Distribution / packaging 16 | .Python 17 | build/ 18 | develop-eggs/ 19 | dist/ 20 | downloads/ 21 | eggs/ 22 | .eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | wheels/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | MANIFEST 33 | 34 | # PyInstaller 35 | # Usually these files are written by a python script from a template 36 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 37 | *.manifest 38 | *.spec 39 | 40 | # Installer logs 41 | pip-log.txt 42 | pip-delete-this-directory.txt 43 | 44 | # Unit test / coverage reports 45 | htmlcov/ 46 | .tox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | .hypothesis/ 54 | .pytest_cache/ 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Django stuff: 61 | *.log 62 | local_settings.py 63 | db.sqlite3 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # pyenv 82 | .python-version 83 | 84 | # celery beat schedule file 85 | celerybeat-schedule 86 | 87 | # SageMath parsed files 88 | *.sage.py 89 | 90 | # Environments 91 | .env 92 | .venv 93 | env/ 94 | venv/ 95 | ENV/ 96 | env.bak/ 97 | venv.bak/ 98 | 99 | # Spyder project settings 100 | .spyderproject 101 | .spyproject 102 | 103 | # Rope project settings 104 | .ropeproject 105 | 106 | # mkdocs documentation 107 | /site 108 | 109 | # mypy 110 | .mypy_cache/ 111 | -------------------------------------------------------------------------------- /rockstarpy/command_line.py: -------------------------------------------------------------------------------- 1 | from rockstarpy.transpile import Transpiler 2 | from io import BytesIO 3 | import sys 4 | import argparse 5 | 6 | parser = argparse.ArgumentParser( 7 | description="Python transpiler for the esoteric language Rockstar" 8 | ) 9 | 10 | input_group = parser.add_mutually_exclusive_group(required=True) 11 | input_group.add_argument("-i", "--input", action="store", help="Input file (.rock)") 12 | input_group.add_argument( 13 | "--stdin", 14 | action="store_const", 15 | const=sys.stdin.buffer, 16 | help="Stream in stdin. Send EOF (Ctrl+D in *nix, Ctrl+Z in Windows) to stop", 17 | ) 18 | 19 | output_group = parser.add_mutually_exclusive_group() 20 | output_group.add_argument( 21 | "-o", "--output", action="store", help="Output file (.py)", default="output.py" 22 | ) 23 | output_group.add_argument( 24 | "--stdout", action="store_const", const=sys.stdout.buffer, help="Stream to stdout" 25 | ) 26 | output_group.add_argument( 27 | "--exec", action="store_true", help="Execute (without saving) the transpiled code " 28 | ) 29 | 30 | parser.add_argument( 31 | "-v", "--version", action="version", help="Version", version="2.1.0" 32 | ) 33 | 34 | args = parser.parse_args() 35 | 36 | def command_line(): 37 | sys.tracebacklimit = 0 38 | lyrics = args.stdin or open(args.input, "rb") 39 | output = BytesIO() if args.exec else args.stdout or open(args.output, "wb") 40 | 41 | transpiler = Transpiler() 42 | line_number = 1 43 | for line in lyrics: 44 | line = line.decode("utf8") 45 | try: 46 | output.write(transpiler.transpile_line(line).encode("utf8")) 47 | except SyntaxError as err: 48 | raise SyntaxError(err.msg + f":\n{line_number}.\t{line}") 49 | line_number += 1 50 | 51 | if args.exec: 52 | exec(output.getvalue()) 53 | if args.stdin is None: 54 | lyrics.close() 55 | if args.stdout is None: 56 | output.close() 57 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [master] 9 | schedule: 10 | - cron: '0 14 * * 4' 11 | 12 | jobs: 13 | analyze: 14 | name: Analyze 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | # Override automatic language detection by changing the below list 21 | # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] 22 | language: ['python'] 23 | # Learn more... 24 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection 25 | 26 | steps: 27 | - name: Checkout repository 28 | uses: actions/checkout@v2 29 | with: 30 | # We must fetch at least the immediate parents so that if this is 31 | # a pull request then we can checkout the head. 32 | fetch-depth: 2 33 | 34 | # If this run was triggered by a pull request event, then checkout 35 | # the head of the pull request instead of the merge commit. 36 | - run: git checkout HEAD^2 37 | if: ${{ github.event_name == 'pull_request' }} 38 | 39 | # Initializes the CodeQL tools for scanning. 40 | - name: Initialize CodeQL 41 | uses: github/codeql-action/init@v1 42 | with: 43 | languages: ${{ matrix.language }} 44 | 45 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 46 | # If this step fails, then you should remove it and run the build manually (see below) 47 | - name: Autobuild 48 | uses: github/codeql-action/autobuild@v1 49 | 50 | # ℹ️ Command-line programs to run using the OS shell. 51 | # 📚 https://git.io/JvXDl 52 | 53 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 54 | # and modify them (or add more) to build your code if your project 55 | # uses a compiled language 56 | 57 | #- run: | 58 | # make bootstrap 59 | # make release 60 | 61 | - name: Perform CodeQL Analysis 62 | uses: github/codeql-action/analyze@v1 63 | -------------------------------------------------------------------------------- /tests/test_calculation.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import unittest 4 | 5 | sys.path = [os.path.dirname(os.path.dirname(os.path.realpath(__file__)))] + sys.path 6 | from rockstarpy.transpile import Transpiler 7 | 8 | 9 | class TestCalculation(unittest.TestCase): 10 | def test_add_numbers(self): 11 | transpiler = Transpiler() 12 | py_line = transpiler.transpile_line("Put 1 plus 3 into my pocket\n") 13 | self.assertEqual(py_line, "my_pocket = 1 + 3\n") 14 | 15 | def test_add_poetic(self): 16 | transpiler = Transpiler() 17 | py_line = transpiler.transpile_line("Put this with that into my pocket\n") 18 | self.assertEqual(py_line, "my_pocket = this + that\n") 19 | 20 | def test_subtract_numbers(self): 21 | transpiler = Transpiler() 22 | py_line = transpiler.transpile_line("Put 1 minus 3 into my pocket\n") 23 | self.assertEqual(py_line, "my_pocket = 1 - 3\n") 24 | 25 | def test_subtract_poetic(self): 26 | transpiler = Transpiler() 27 | py_line = transpiler.transpile_line("Put this without that into my pocket\n") 28 | self.assertEqual(py_line, "my_pocket = this - that\n") 29 | 30 | def test_multiply_numbers(self): 31 | transpiler = Transpiler() 32 | py_line = transpiler.transpile_line("Put 1 times 3 into my pocket\n") 33 | self.assertEqual(py_line, "my_pocket = 1 * 3\n") 34 | 35 | def test_multiply_poetic(self): 36 | transpiler = Transpiler() 37 | py_line = transpiler.transpile_line("Put this of that into my pocket\n") 38 | self.assertEqual(py_line, "my_pocket = this * that\n") 39 | 40 | def test_divide_numbers(self): 41 | transpiler = Transpiler() 42 | py_line = transpiler.transpile_line("Put 1 over 3 into my pocket\n") 43 | self.assertEqual(py_line, "my_pocket = 1 / 3\n") 44 | 45 | def test_divide_poetic(self): 46 | transpiler = Transpiler() 47 | py_line = transpiler.transpile_line("Put this over that into my pocket\n") 48 | self.assertEqual(py_line, "my_pocket = this / that\n") 49 | 50 | def test_decrement(self): 51 | transpiler = Transpiler() 52 | py_line = transpiler.transpile_line("Knock the hate down\n") 53 | self.assertEqual(py_line, "the_hate -= 1\n") 54 | 55 | def test_increment(self): 56 | transpiler = Transpiler() 57 | py_line = transpiler.transpile_line("Build my money up\n") 58 | self.assertEqual(py_line, "my_money += 1\n") 59 | 60 | @unittest.skip("Compound assignment not implemented, yet") 61 | def test_compund_addition_assignment(self): 62 | transpiler = Transpiler() 63 | py_line = transpiler.transpile_line("Let X be with 10\n") 64 | self.assertEqual(py_line, "X += 10\n") 65 | 66 | 67 | if __name__ == "__main__": 68 | unittest.main() 69 | -------------------------------------------------------------------------------- /tests/test_conditionals.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import unittest 4 | 5 | sys.path = [os.path.dirname(os.path.dirname(os.path.realpath(__file__)))] + sys.path 6 | from rockstarpy.transpile import Transpiler 7 | 8 | 9 | class TestConditionals(unittest.TestCase): 10 | def test_equals(self): 11 | transpiler = Transpiler() 12 | py_line = transpiler.transpile_line("If Tommy is nobody\n") 13 | self.assertEqual(py_line, "if Tommy == False:\n") 14 | 15 | def test_greater(self): 16 | transpiler = Transpiler() 17 | py_line = transpiler.transpile_line("If Tommy is stronger than Superman\n") 18 | self.assertEqual(py_line, "if Tommy > Superman:\n") 19 | 20 | def test_greater_equals(self): 21 | transpiler = Transpiler() 22 | py_line = transpiler.transpile_line("If Love is as high as mountain\n") 23 | self.assertEqual(py_line, "if Love >= mountain:\n") 24 | 25 | def test_less(self): 26 | transpiler = Transpiler() 27 | py_line = transpiler.transpile_line("If Tommy is weaker than a worm\n") 28 | self.assertEqual(py_line, "if Tommy < a_worm:\n") 29 | 30 | def test_less_equals(self): 31 | transpiler = Transpiler() 32 | py_line = transpiler.transpile_line("If my mind is as low as my soul\n") 33 | self.assertEqual(py_line, "if my_mind <= my_soul:\n") 34 | 35 | def test_while_equals(self): 36 | transpiler = Transpiler() 37 | py_line = transpiler.transpile_line("While Tommy is nobody\n") 38 | self.assertEqual(py_line, "while Tommy == False:\n") 39 | 40 | def test_until_greater(self): 41 | transpiler = Transpiler() 42 | py_line = transpiler.transpile_line("Until Tommy is stronger than Superman\n") 43 | self.assertEqual(py_line, "while not Tommy > Superman:\n") 44 | 45 | def test_not(self): 46 | transpiler = Transpiler() 47 | py_line = transpiler.transpile_line("If not number is 28\n") 48 | self.assertEqual(py_line, "if not number == 28:\n") 49 | 50 | def test_or(self): 51 | transpiler = Transpiler() 52 | py_line = transpiler.transpile_line("If Tommy is nobody or Billy is nobody\n") 53 | self.assertEqual(py_line, "if Tommy == False or Billy == False:\n") 54 | 55 | def test_and(self): 56 | transpiler = Transpiler() 57 | py_line = transpiler.transpile_line("If Tommy is nobody and Billy is nobody\n") 58 | self.assertEqual(py_line, "if Tommy == False and Billy == False:\n") 59 | 60 | @unittest.skip("apostrophe handling is not working fully") 61 | def test_aint(self): 62 | transpiler = Transpiler() 63 | py_line = transpiler.transpile_line("If Tommy ain't nobody\n") 64 | self.assertEqual(py_line, "if Tommy != False:\n") 65 | 66 | @unittest.skip("nor operator not implemented, yet") 67 | def test_nor(self): 68 | transpiler = Transpiler() 69 | py_line = transpiler.transpile_line("If Tommy is nobody nor Billy is nobody\n") 70 | self.assertEqual(py_line, "if not Tommy == False or Billy == False:\n") 71 | 72 | 73 | if __name__ == "__main__": 74 | 75 | unittest.main() 76 | -------------------------------------------------------------------------------- /tests/test_blocks.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import unittest 4 | 5 | sys.path = [os.path.dirname(os.path.dirname(os.path.realpath(__file__)))] + sys.path 6 | from rockstarpy.transpile import Transpiler 7 | 8 | 9 | class TestBlocks(unittest.TestCase): 10 | def test_if_block(self): 11 | rock = ["If Tommy is nobody\n", 'Shout "Tommy?"\n', "\n", 'Shout "Tommy!"\n'] 12 | 13 | py = ["if Tommy == False:\n", ' print("Tommy?")\n', "", 'print("Tommy!")\n'] 14 | 15 | self.__run_block_test(rock, py) 16 | 17 | def test_if_else_block(self): 18 | rock = [ 19 | "If Tommy is nobody\n", 20 | 'Shout "Tommy?"\n', 21 | "Else\n", 22 | 'Shout "Tommy!"\n', 23 | "\n", 24 | 'Shout "Tommy!"\n', 25 | ] 26 | 27 | py = [ 28 | "if Tommy == False:\n", 29 | ' print("Tommy?")\n', 30 | "else:\n", 31 | ' print("Tommy!")\n', 32 | "", 33 | 'print("Tommy!")\n', 34 | ] 35 | 36 | self.__run_block_test(rock, py) 37 | 38 | def test_while_block(self): 39 | rock = [ 40 | "While Tommy is not 0\n", 41 | "Knock Tommy down\n", 42 | "\n", 43 | 'Shout "Tommy!"\n', 44 | ] 45 | 46 | py = ["while Tommy != 0:\n", " Tommy -= 1\n", "", 'print("Tommy!")\n'] 47 | 48 | self.__run_block_test(rock, py) 49 | 50 | def test_until_block(self): 51 | rock = ["Until Tommy is 0\n", "Knock Tommy down\n", "\n", 'Shout "Tommy!"\n'] 52 | 53 | py = ["while not Tommy == 0:\n", " Tommy -= 1\n", "", 'print("Tommy!")\n'] 54 | 55 | self.__run_block_test(rock, py) 56 | 57 | def test_function_numeric(self): 58 | rock = [ 59 | "Multiply takes Love and Life\n", 60 | "Give back Love of Life\n", 61 | "\n", 62 | "Say Multiply taking 3, 444\n", 63 | ] 64 | 65 | py = [ 66 | "def Multiply(Love, Life):\n", 67 | " return Love * Life\n", 68 | "", 69 | "print(Multiply(3, 444))\n", 70 | ] 71 | 72 | self.__run_block_test(rock, py) 73 | 74 | def test_function_variables(self): 75 | rock = [ 76 | "Multiply takes Love and Life\n", 77 | "Give back Love of Life\n", 78 | "\n", 79 | "Put 1 into my heart\n", 80 | "Put 666 into the devil\n", 81 | "Multiply taking my heart, the devil\n", 82 | ] 83 | 84 | py = [ 85 | "def Multiply(Love, Life):\n", 86 | " return Love * Life\n", 87 | "", 88 | "my_heart = 1\n", 89 | "the_devil = 666\n", 90 | "Multiply(my_heart, the_devil)\n", 91 | ] 92 | 93 | self.__run_block_test(rock, py) 94 | 95 | def __run_block_test(self, rock, py): 96 | transpiler = Transpiler() 97 | transpiled = [transpiler.transpile_line(line) for line in rock] 98 | self.assertEqual(len(py), len(transpiled)) 99 | for py_line, transpiled_line in zip(py, transpiled): 100 | self.assertEqual(py_line, transpiled_line) 101 | 102 | 103 | if __name__ == "__main__": 104 | unittest.main() 105 | -------------------------------------------------------------------------------- /tests/test_assignment.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import unittest 4 | 5 | sys.path = [os.path.dirname(os.path.dirname(os.path.realpath(__file__)))] + sys.path 6 | from rockstarpy.transpile import Transpiler 7 | 8 | 9 | class TestAssignment(unittest.TestCase): 10 | def test_is_bool(self): 11 | transpiler = Transpiler() 12 | py_line = transpiler.transpile_line("Life is ok\n") 13 | self.assertEqual(py_line, "Life = True\n") 14 | 15 | def test_is_poetic(self): 16 | transpiler = Transpiler() 17 | py_line = transpiler.transpile_line("My life is a mess\n") 18 | self.assertEqual(py_line, "my_life = 14\n") 19 | 20 | py_line = transpiler.transpile_line("Life is a one day after another\n") 21 | self.assertEqual(py_line, "Life = 13357\n") 22 | 23 | def test_is_numeric(self): 24 | transpiler = Transpiler() 25 | py_line = transpiler.transpile_line("Seven is 11\n") 26 | self.assertEqual(py_line, "Seven = 11\n") 27 | 28 | def test_is_numeric_with_dot(self): 29 | transpiler = Transpiler() 30 | py_line = transpiler.transpile_line("X is 1.23\n") 31 | self.assertEqual(py_line, "X = 1.23\n") 32 | 33 | def test_is_poetic_with_dot(self): 34 | transpiler = Transpiler() 35 | py_line = transpiler.transpile_line( 36 | "My dreams were ice. A life unfulfilled; wakin' everybody up, taking booze and pills\n" 37 | ) 38 | self.assertEqual(py_line, "my_dreams = 3.1415926535\n") 39 | 40 | def test_is_poetic_with_hyphen(self): 41 | transpiler = Transpiler() 42 | py_line = transpiler.transpile_line("Greed is all-consuming\n") 43 | self.assertEqual(py_line, "Greed = 3\n") 44 | 45 | py_line = transpiler.transpile_line("God is power-hungry\n") 46 | self.assertEqual(py_line, "God = 2\n") 47 | 48 | def test_is_poetic_and_numeric(self): 49 | transpiler = Transpiler() 50 | py_line = transpiler.transpile_line("Car is 4 W D\n") 51 | self.assertEqual(py_line, "Car = 411\n") 52 | 53 | @unittest.skip("keywords are replaced too early in assignments") 54 | def test_is_poetic_keyword(self): 55 | transpiler = Transpiler() 56 | py_line = transpiler.transpile_line("Tommy was without\n") 57 | self.assertEqual(py_line, "Tommy = 7\n") 58 | 59 | def test_is_string(self): 60 | transpiler = Transpiler() 61 | py_line = transpiler.transpile_line('Message is "Hello"\n') 62 | self.assertEqual(py_line, 'Message = "Hello"\n') 63 | 64 | def test_let_be_bool(self): 65 | transpiler = Transpiler() 66 | py_line = transpiler.transpile_line("Let my beer be empty\n") 67 | self.assertEqual(py_line, "my_beer = False\n") 68 | 69 | def test_let_be_poetic(self): 70 | transpiler = Transpiler() 71 | py_line = transpiler.transpile_line("Let Stuart be a yellow Minion\n") 72 | self.assertEqual(py_line, "Stuart = 166\n") 73 | 74 | def test_let_be_numeric(self): 75 | transpiler = Transpiler() 76 | py_line = transpiler.transpile_line("Let One be 0\n") 77 | self.assertEqual(py_line, "One = 0\n") 78 | 79 | def test_let_be_string(self): 80 | transpiler = Transpiler() 81 | py_line = transpiler.transpile_line('Let the letter be "R"\n') 82 | self.assertEqual(py_line, 'the_letter = "R"\n') 83 | 84 | def test_put_into_bool(self): 85 | transpiler = Transpiler() 86 | py_line = transpiler.transpile_line("Put nothing into my hand\n") 87 | self.assertEqual(py_line, "my_hand = False\n") 88 | 89 | def test_put_into_poetic_assigns_variable(self): 90 | transpiler = Transpiler() 91 | py_line = transpiler.transpile_line("Put a flower into the vase\n") 92 | self.assertEqual(py_line, "the_vase = a_flower\n") 93 | 94 | def test_put_into_numeric(self): 95 | transpiler = Transpiler() 96 | py_line = transpiler.transpile_line("Put 3.14 into PI\n") 97 | self.assertEqual(py_line, "Pi = 3.14\n") 98 | 99 | def test_put_into_string(self): 100 | transpiler = Transpiler() 101 | py_line = transpiler.transpile_line('Put "letter" into the envelope\n') 102 | self.assertEqual(py_line, 'the_envelope = "letter"\n') 103 | 104 | 105 | if __name__ == "__main__": 106 | unittest.main() 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rockstar-py 2 | 3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |