joshsharp/python-braid
{ "createdAt": "2015-07-11T11:58:09Z", "defaultBranch": "master", "description": "Learning to build a language with RPython.", "fullName": "joshsharp/python-braid", "homepage": "", "language": "Python", "name": "python-braid", "pushedAt": "2017-06-10T06:23:07Z", "stargazersCount": 21, "topics": [], "updatedAt": "2025-03-24T02:04:32Z", "url": "https://github.com/joshsharp/python-braid"}Learning to build a language interpreter with RPython and RPly
I don’t really know what I’m doing but I’m interested in writing a toy language and interpreter. I’ve chosen RPython and RPly because I know Python quite well and the RPython EBNF parsing libs were confusing. RPly’s interface is a bit higher level.
This project is no longer being actively maintained.
Installing
Section titled “Installing”pip install -r requirements.txt
Running
Section titled “Running”python braid.py for REPL, python braid.py [filename].bd for interpreting a file
:a gives you the AST of the last statement, :e to list environment variables, :q or Ctrl-C to quit. The REPL now supports multi-line input too — it’ll just keep appending code and trying to interpret it until it’s valid (eg. you closed the block or whatever), or you break it ;)
Status
Section titled “Status”Basic arithmetic, floats, integers, booleans, and strings, variable assignment, if expressions, and a print() function.
>>> 5 == 5= true>>> 5 != 5= false>>> let a = 5= 5>>> print(a)5>>> print(a + 25)30>>> "hi" + 'hi'= hihi>>> "hi" * 5 - 1= hihihihih
# if expressions>>> if false: print("no") else: print("yes") endyes>>> let a = (if true: 1 else: 5 end)= 1
let a = 50if a == 50 and true: print("doing stuff")else: print("not this though")end
>>> 5 >= 6= false
# assignment via if>>> let a = if true: 5 end= 5>>> :aProgram(BinaryOp(Variable('a'), If(Boolean(True))Then(Integer(5))Else(None)))
# arrays>>> [5, 6, ["hi", 7.0]]= [5, 6, [hi, 7.0]]
# functionsfunc a(b): b + 1end
>>> b(1)= 2
# immutability means loops become recursionfunc p_message(msg, n): if n > 0: print(msg) p_message(msg, n - 1) endend
>>> p_message("hellooo",2)hellooohellooo
# functions can be passed aroundfunc a(): 1end
>>> let b = a>>> b()= 1Compiling
Section titled “Compiling”You will need pypy so you can use RPython’s compiler. Then, like so:
python path/to/rpython/bin/rpython target.py
This will provide a target-c binary which you can use as a compiled substitute for main.py.
A language which can do things I find interesting, and the tools necessary to execute it.
- Define the language (ongoing)
- Lexer
- Parser
- Bytecode compiler
- Interpreter/VM
- Compiles to RPython (mostly but sometimes broken)
- JIT
- Immutability (initial support anyway)
- First-class functions (sort of)
- Structs and traits
- FP concepts like map/reduce
- Pattern matching
- Concurrency via message passing
- Standard library
Status updates
Section titled “Status updates”I’ve abandoned this as I’m no longer interested in building a language on RPython. You can follow me on twitter at @joshsharp if you’re interested in the other stuff I’m working on.