Christiano Braga
Universidade Federal Fluminense
http://www.ic.uff.br/~cbraga
July 2019
http://github.com/ChristianoBraga/PiFramework
A compiler for the ImΠ language is defined by means of functions mapping constructions from the ImΠ language to Π IR.
<S> ::= <cmd>
<cmd> ::= 'nop' | <let> | <assign> | <loop> | <call>
<call> ::= <identifier> '(' <actual> ')'
<actual> ::= <expression> (',' <expression>)* | ε
<loop> ::= 'while' <expression> 'do' <cmd>+
<assign> ::= <identifier> ':=' <expression>
<let> ::= 'let' <dec> 'in' <cmd>+
<dec> ::= <const> | <var> | <fn>
<const> ::= 'const' <identifier> '=' <expression>
<var> ::= 'var' <identifier> '=' <expression>
<fn> ::= 'fn' <identifier> '(' <formal> ')' '=' <cmd>
<formal> ::= <identifier> (',' <identifier>)* | ε
<expression> ::= <bool_expression> | <arith_expression>
<bool_expression> ::= <negation> | <equality> | <conjunction> | <disjunction>
| <lowereq> | <greatereq> | <lowerthan> | <greaterthan>
<equality> ::= <arith_expression> "==" <expression>
<conjunction> ::= <bool_expression> "and" <bool_expression>
<disjunction> ::= <bool_expression> "or" <bool_expression>
<lowereq> ::= <arith_expression> "<=" <arith_expression>
<greatereq> ::= <arith_expression> ">=" <arith_expression>
<lowerthan> ::= <arith_expression> "<" <arith_expression>
<greaterthan> ::= <arith_expression> ">" <arith_expression>
<parentesisexp> ::= '(' <bool_expression> ')'
<negation> ::= 'not' <bool_expression>
<arith_expression> ::= <addition> | <subtraction> | <mult_expression> | <division>
<addition> ::= <mult_expression> "+" <arith_expression>
<subtraction> ::= <mult_expression> "-" <arith_expression>
<mult_expression> ::= <multiplication> | <division> | <atom> | <parentesisexp>
<multiplication> ::= <atom> "*" <mult_expression>
<division> ::= <atom> "/" <mult_expression>
<atom> ::= <number> | <truth> | <identifier>
<number> ::= /\d+/
<identifier> ::= /(?!\d)\w+/
<truth> ::= 'True' | 'False'
# The classic iterative factorial example
let var z = 1
in
let var y = 10
in
while not (y == 0)
do
z := z * y
y := y - 1
# In this example we encapsulate the iterative calculation
# of the factorial within a function call.
let var z = 1
in
let fn f(x) =
let var y = x
in
while not (y == 0)
do
z := z * y
y := y - 1
in f(10)
A Π denotation for the ImΠ language is a function
⟦⋅⟧ : Gimp → GΠ,
intentionally defined, that associates (a class of) words derivable by ImΠ's grammar with (a class of words) words derivable by Π IR grammar.
Let ast ∈ L(Gimp),
-
⟦ identifier(ast) ⟧ = Id(str(ast)), where function str returns a string given an
<identifier>
. -
⟦ number(ast) ⟧ = Num(int(ast)), where function int returns an integer given a
<number>
. -
⟦ addition(ast) ⟧ = Sum( ⟦ left(ast) ⟧, ⟦ right(ast) ⟧), where functions left and right return the left branch and right branches of ast, respectively.
-
⟦ subtraction(ast) ⟧ = Sub(⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ multiplication(ast) ⟧ = Mul(⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ division(ast) ⟧ = Div(⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ truth(ast) ⟧ = Boo(bool(ast)), where function bool returns a Boolean value given a
<truth>
token. -
⟦ negation(ast) ⟧ = Not( ⟦ ast ⟧ )
-
⟦ equality(ast) ⟧ = Eq(⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ lowerthan(ast) ⟧ = Lt(⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ greaterthan(ast) ⟧ = Gt(⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ lowereq(ast) ⟧ = Le⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ greatereq(ast) ⟧ = Ge(⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ conjunction(ast) ⟧ = And(⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ disconjunction(ast) ⟧ = Or(⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ nop(ast) ⟧ = Nop
Let _mkAbs : <formal>
× <cmd>
→ <Abs>
be
mkAbs([], c) = Abs([], ⟦ c ⟧) mkAbs(h :: ls, b) = Abs(⟦ h ⟧ :: mkFor(ls), ⟦ c ⟧)
and mkFor : <identifier>*
→ <Id>*
_mkFor([]) = []
mkFor(h :: ls) = ⟦ h ⟧ :: mkFor(ls)
-
⟦ var(ast) ⟧ = Bind(⟦ left(ast) ⟧, Ref(⟦ right(ast) ⟧))
-
⟦ const(ast) ⟧ = Bind(⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ fn(ast) ⟧ = Bind(⟦ fst(ast) ⟧, mkAbs(snd(ast), trd(ast))
-
⟦ rfn(ast) ⟧ = Rbnd(⟦ fst(ast) ⟧, mkAbs(snd(ast), trd(ast))
Let mkCSeq : <cmd>+
→ <CSeq>
be defined by the following equations,
mkCSeq([h]) = h,
mkCSeq(h::ls) = CSeq(⟦ h ⟧ , mkCSeq(ls)),
and mkAct : <actual>
→ <Exp>*
be as follows
mkAct([]) = [],
mkAct(h::ls) = ⟦ h ⟧ :: mkAct(ls)).
-
⟦ assign(ast) ⟧ = Assign(⟦ left(ast) ⟧, ⟦ right(ast) ⟧)
-
⟦ let(ast) ⟧ = Blk(⟦ left(ast) ⟧, ⟦ right(ast) ⟧), if _right(ast) ∈
<cmd>
-
⟦ let(ast) ⟧ = Blk(⟦ left(ast) ⟧, mkCSeq(right(ast))), if right(ast) ∈
<cmd>+
-
⟦ loop(ast) ⟧ = Loop(⟦ left(ast) ⟧, ⟦ right(ast) ⟧), if right(ast) ∈
<cmd>
-
⟦ loop(ast) ⟧ = Loop(⟦ left(ast) ⟧, mkCSeq(right(ast))), if right(ast) ∈
<cmd>+
-
⟦ call(ast) ⟧ = Call(⟦ left(ast) ⟧, mkAct(right(ast)))
- For the iteractive factorial:
Π IR AST: Blk(Bind(Id(z), Ref(Num(1))),
Blk(Bind(Id(y), Ref(Num(10))),
Loop(Not(Eq(Id(y), Num(0))),
CSeq(Assign(Id(z), Mul(Id(z), Id(y))),
Assign(Id(y), Sub(Id(y), Num(1)))))))
- For the functional factorial:
Π IR AST: Blk(Bind(Id(z), Ref(Num(1))),
Blk(Bind(Id(f),
Abs(Id(x),
Blk(Bind(Id(y), Ref(Id(x))),
Loop(Not(Eq(Id(y), Num(0))),
CSeq(Assign(Id(z), Mul(Id(z), Id(y))),
Assign(Id(y), Sub(Id(y), Num(1)))))))),
Call(Id(f), [Num(10)])))