|
3 | 3 |
|
4 | 4 | #pseudo-python
|
5 | 5 |
|
6 |
| -A Python to JavaScript / Ruby / C++ / Go / C# / PHP translator |
| 6 | +A restricted Python to idiomatic JavaScript / Ruby / Go / C# translator |
7 | 7 |
|
8 | 8 | [Pseudo](https://github.com/alehander42/pseudo) is a framework for high level code generation: it is used by this compiler to translate a subset of Python to all Pseudo-supported languages
|
9 | 9 |
|
10 | 10 | ## Supported subset
|
11 | 11 |
|
12 |
| -Pseudo supports a very clear and somehow limited subset of a language: |
| 12 | +pseudo-python compiles to `pseudo ast`. Pseudo supports a very clear and somehow limited subset of a language: |
13 | 13 |
|
14 | 14 | * basic types and collections and standard library methods for them
|
15 | 15 |
|
@@ -37,35 +37,53 @@ Pseudo supports a very clear and somehow limited subset of a language:
|
37 | 37 | * conditionals (if / else if / else)
|
38 | 38 | * standard math/logical operations
|
39 | 39 |
|
40 |
| -## pseudo-python compiler |
| 40 | +## Installation |
41 | 41 |
|
42 |
| -pseudo-python checks if your program is using a valid pseudo-translatable subset of Python, type checks it according to pseudo type rules and generates a `<filename>.pseudo.yaml` output file containing pseudo-ast code |
43 | 42 |
|
44 |
| -[TODO] |
45 |
| -You can directly run `pseudo-python <filename.py> <lang>` e.g. |
| 43 | +```bash |
| 44 | +pip install pseudo-python |
| 45 | +``` |
| 46 | + |
| 47 | +## Usage |
46 | 48 |
|
47 | 49 | ```bash
|
48 | 50 | pseudo-python <filename.py> ruby
|
49 |
| -pseudo-python <filename.py> cpp |
| 51 | +pseudo-python <filename.py> csharp |
50 | 52 | ```
|
51 |
| -etc for all the supported pseudo languages (javascript, c++, c#, go, ruby and python) |
| 53 | +etc for all the supported pseudo targets (javascript, c#, go, ruby and python) |
| 54 | + |
| 55 | +## examples |
| 56 | + |
| 57 | +Each example contains a detailed README and working translations to Python, JS, Ruby, Go and C#, generated by Pseudo |
| 58 | + |
| 59 | +[fibonacci](examples/fib) |
| 60 | + |
| 61 | +[a football results processing command line tool](examples/football) |
| 62 | + |
| 63 | +[a verbal expressions-like library ported to all the target languages](examples/verbal_expressions) |
| 64 | + |
52 | 65 |
|
53 | 66 | ## Error messages
|
54 | 67 |
|
55 | 68 | A lot of work has been put into making pseudo-python error messages as clear and helpful as possible: they show the offending snippet of code and
|
56 | 69 | often they offer suggestions, list possible fixes or right/wrong ways to write something
|
57 | 70 |
|
58 |
| - |
| 71 | + |
| 72 | + |
| 73 | +Beware, pseudo and especially pseudo-python are still in early stage, so if there is anything weird going on, don't hesitate to submit an issue |
59 | 74 |
|
60 | 75 | ## Type inference
|
61 | 76 |
|
| 77 | +pseudo-python checks if your program is using a valid pseudo-translatable subset of Python, type checks it according to pseudo type rules and then generates a pseudo ast and passes it to pseudo for code generation. |
| 78 | + |
| 79 | + |
62 | 80 | The rules are relatively simple: currently pseudo-python infers everything
|
63 | 81 | from the usage of functions/classes, so has sufficient information when the program is calling/initializing all
|
64 | 82 | of its functions/classes (except for no-arg functions)
|
65 | 83 |
|
66 | 84 | Often you don't really need to do that for **all** of them, you just need to do it in a way that can create call graphs covering all of them (e.g. often you'll have `a` calling `b` calling `x` and you only need to have an `a` invocation in your source)
|
67 | 85 |
|
68 |
| -You can also add type annotations. We are trying to respect existing Python3 type annotation conventions and currently pseudo-python recognizes `int`, `float`, `str`, `bool`, `List[<type>]`, |
| 86 | +You can also use type annotations. We are trying to respect existing Python3 type annotation conventions and currently pseudo-python recognizes `int`, `float`, `str`, `bool`, `List[<type>]`, |
69 | 87 | `Dict[<key-type>, <value-type>]`, `Tuple[<type>..]`, `Set[<type>]` and `Callable[[<type>..], <type>]`
|
70 | 88 |
|
71 | 89 | Beware, you can't just annotate one param, if you provide type annotations for a function/method, pseudo-python expects type hints for all params and a return type
|
@@ -106,3 +124,83 @@ but methods in children should accept the same types as their equivalents in the
|
106 | 124 | The easiest way to play with the type system is to just try several programs: `pseudo-python` errors should be enough to guide you, if not,
|
107 | 125 | you can always open an issue
|
108 | 126 |
|
| 127 | +## How does Pseudo work? |
| 128 | + |
| 129 | + |
| 130 | +The implementation goal is to make the definitions of new supported languages really clear and simple. |
| 131 | + |
| 132 | +If you dive in, you'll find out |
| 133 | +a lot of the code/api transformations are defined using a declarative dsl with rare ocassions |
| 134 | +of edge case handling helpers. |
| 135 | + |
| 136 | +That has a lot of advantages: |
| 137 | + |
| 138 | +* Less bugs: the core transformation code is really generalized, it's reused as a dsl and its results are well tested |
| 139 | + |
| 140 | +* Easy to comprehend: it almost looks like a config file |
| 141 | + |
| 142 | +* Easy to add support for other languages: I was planning to support just python and c# in the initial version but it is so easy to add support for a language similar to the current supported ones, that I |
| 143 | +added support for 4 more. |
| 144 | + |
| 145 | +* Easy to test: there is a simple test dsl too which helps all |
| 146 | +language tests to share input examples [like that](pseudo/tests/test_ruby.py) |
| 147 | + |
| 148 | +However language translation is related to a lot of details and |
| 149 | +a lot of little gotchas, tuning and refining some of them took days. Pseudo uses different abstractions to streamline the process and to reuse logic across languages. |
| 150 | + |
| 151 | +```ruby |
| 152 | +PSEUDO AST: |
| 153 | + NORMAL CODE PSEUDO STANDARD LIBRARY INVOCATIONS |
| 154 | + || || |
| 155 | + || || |
| 156 | + || API TRANSLATOR |
| 157 | + || || |
| 158 | + || || |
| 159 | + || \/ |
| 160 | + || IDIOMATIC TARGET LANGUAGE |
| 161 | + || STANDARD LIBRARY INVOCATIONS |
| 162 | + || || |
| 163 | + \/ \/ |
| 164 | + STANDARD OR LANGUAGE-SPECIFIC MIDDLEWARES |
| 165 | + e.g. |
| 166 | + name camel_case/snake_case middleware |
| 167 | + convert-tuples-to-classes middleware |
| 168 | + convert-exception-based errors handling |
| 169 | + to return-based error handling middleware |
| 170 | + etc |
| 171 | + |
| 172 | + || |
| 173 | + || |
| 174 | + || |
| 175 | + || |
| 176 | + TARGET LANGUAGE CODE GENERATOR |
| 177 | + |
| 178 | + defined with a dsl aware |
| 179 | + that handles formatting |
| 180 | + automatically |
| 181 | + || |
| 182 | + || |
| 183 | + || |
| 184 | + \/ |
| 185 | +
|
| 186 | + OUTPUT |
| 187 | +``` |
| 188 | +
|
| 189 | +
|
| 190 | +## What's the difference between Pseudo and Haxe? |
| 191 | +
|
| 192 | +They might seem comparable at a first glance, but they have completely different goals. |
| 193 | +
|
| 194 | +Pseudo wants to generate readable code, ideally something that looks like a human wrote it/ported it |
| 195 | + |
| 196 | +Pseudo doesn't use a target language runtime, it uses the target language standard library for everything (except for JS, but even there is uses `lodash` which is pretty popular and standard) |
| 197 | +
|
| 198 | +Pseudo's goal is to help with automated translation for cases |
| 199 | +like algorithm generation, parser generation, refactoring, porting codebases etc. The fact that you can write compilers targetting Pseudo and receiver translation to many languages for free is just a happy accident |
| 200 | + |
| 201 | + |
| 202 | +## License |
| 203 | + |
| 204 | +Copyright © 2015 2016 [Alexander Ivanov](https://twitter.com/alehander42) |
| 205 | + |
| 206 | +Distributed under the MIT License. |
0 commit comments