A transpiler that converts Logo code into Python
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
chelodina
examples
tests
.editorconfig
.gitignore
.pre-commit-config.yaml
LICENSE
Pipfile
Pipfile.lock
README.md
grammar.bnf
license.png
pypi.svg
setup.py

README.md

Chelodina

PyPI LICENSE Code Style

Chelodina is a transpiler that converts LOGO:

TO triangle :length
  REPEAT 3 [ FORWARD :length RIGHT 120 ]
END

TO flower :length :count
  REPEAT 150 [
    triangle :length
    RIGHT 360 / :count
  ]
END

TO web
  REPEAT 6 [ flower 150 18 ]
END

web

Into Python:

import turtle


def triangle(p_length):
    for _ in range(3):
        turtle.forward(p_length)
        turtle.right(120.0)


def flower(p_length, p_count):
    for _ in range(150):
        triangle(p_length)
        turtle.right(360.0 / p_count)


def web():
    for _ in range(6):
        flower(150.0, 18.0)


web()
turtle.done()

Installation

pip install chelodina

Usage

usage: chelodina [-h] --input INPUT [--run]

arguments:
  -h, --help     show this help message and exit
  --input INPUT  Logo source file
  --run          Run the transpiled code

There's some ready examples to try if you clone the repository:

chelodina --input examples/example1.logo

You can also trigger the program to run in a GUI:

chelodina --input examples/example1.logo --run

Status

  • Implemented:
    • Motion functions: FORWARD, BACK, LEFT, RIGHT, SETPOS, SETX, SETY, SETHEADING, SETH, HOME
    • Screen functions: DONE, CLEARSCREEN
    • Control structures: REPEAT
    • Function calls and definitions with optional parameters
    • Binary operations

This is still on an early stage, I focused on making some examples work. Functions with similar structure are trivial to implement, but I want to focus on improving the tests first.

For grammar reference look at grammar.bnf.

Known quirks

  • Validations for a valid AST (e.g. to make sure a function parameter exists before trying to use it on a statement) are not user friendly yet. I suggest double-checking your programs elsewhere first.
  • Only tested on Python 3.6+ so far.

Development

Use pipenv to install dependencies:

pipenv install --dev

Running tests

Run tests with:

pipenv run tests

Automatically run tests after detecting changes with:

pipenv run tests-watch

Debug

  • The easy way is to write tests to debug your code. Feel free to use assert False where necessary.
  • If you need to run tests along anything that sends to or needs the standard output (a debugger like pdb or pudb), you'll need to run pytest directly: pytest --capture=no.
  • There's a library to pretty-print your AST in the utils package. Usage example:
from chelodina import compiler
from chelodina.utils.debug import parseprint

logo_code = """
to myfunction
  forward 51.0
  left 91
end
"""

parsed_ast = compiler.get_ast(logo_code)
parseprint(parsed)

And you'll see the resulting AST:

Module(body=[
    Import(names=[
        alias(name='turtle', asname=None),
      ]),
    FunctionDef(name='myfunction', args=arguments(args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[
        Expr(value=Call(func=Attribute(value=Name(id='turtle', ctx=Load()), attr='forward', ctx=Load()), args=[
            Num(n=51.0),
          ], keywords=[])),
        Expr(value=Call(func=Attribute(value=Name(id='turtle', ctx=Load()), attr='left', ctx=Load()), args=[
            Num(n=91.0),
          ], keywords=[])),
      ], decorator_list=[], returns=None),
    Expr(value=Call(func=Attribute(value=Name(id='turtle', ctx=Load()), attr='done', ctx=Load()), args=[], keywords=[])),
  ])

Code style

I use black for code formatting, please install the pre-commit hook before doing a PR. This will be enforced with a linter check in the future.

You can run the command manually too:

black .

Not required, but if you install EditorConfig in your editor of choice it will make your life easier.