Introduction
Python has tools for examining python source code. Let's look at some examples in python 2.7.
import ast
ast.dump(ast.parse("123"))
The result should be:
'Module(body=[Expr(value=Num(n=123))])'
A slightly more complicated expression:
ast.dump(ast.parse("2 + 3"))
Results in:
'Module(body=[Expr(value=BinOp(left=Num(n=2), op=Add(), right=Num(n=3)))])'
Assignment statements and variables
code = """
a = 2
b = 3
print a * b + b
"""
ast.dump(ast.parse(code))
"Module(body=[
Assign(targets=[Name(id='a', ctx=Store())], value=Num(n=2)),
Assign(targets=[Name(id='b', ctx=Store())], value=Num(n=3)),
Print(dest=None, values=[BinOp(left=BinOp(left=Name(id='a',
ctx=Load()), op=Mult(), right=Name(id='b', ctx=Load())), op=Add(),
right=Name(id='b', ctx=Load()))], nl=True)])"
We can define OCaml data types to represent a subset of python programs.
type id = string
type binop = Add | Sub | Mult | Div
type exp =
| Num of int
| BinOp of exp * binop * exp
| Name of id
type stm =
| Assign of id * exp
| Print of exp list
| Expr of exp
type prog =
| Module of stm list
let p1 = Module [Expr (Num 123)];;
let p2 = Module [Expr (BinOp (Num 3, Add, Num 2))];;
let p3 = Module [Assign ("a", Num 3); Print [BinOp (Name "a", Mult, Num 2)]];;
Exercises
-
Write a pretty printer for depython programs
pretty : prog -> unitthat prints out a human readable version of the given program. -
Write an interpreter for depython, following the instructions for the SLP interpreter. You will need a function
interp : prog -> unitthat interprets the top level program, and auxiliary functions to interpret thestmandexpdatatypes in an appropriate environment. You should have mutualy recursive functionsinterpStm stm * table -> tableandinterpExp exp * table -> int * table. A table is a list of (id, int) pairs, and the first id that matches should hold the current value of the id. You should haveupdateandlookupfunctions that add new bindings and lookup current values.update : table * id * int -> tabletakes a table, and adds a binding of id to the given int.lookup : table * id -> intlooks up the id in the given table and returns the current value.