Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Declare Your Language: Transformation by Strategic Term Rewriting

423 views

Published on

Lecture 4 of compiler construction course on program transformation by means of strategic term rewriting in Stratego

Published in: Software
  • Be the first to comment

  • Be the first to like this

Declare Your Language: Transformation by Strategic Term Rewriting

  1. 1. Eelco Visser IN4303 Compiler Construction TU Delft September 2017 Declare Your Language Chapter 4: Transformation by Strategic Term Rewriting
  2. 2. 2 Source Code Editor Parse Abstract Syntax Tree Transform Abstract Syntax Tree Define transformations on abstract syntax trees (terms) using rewrite rules
  3. 3. Reading Material 3 The following papers add background, conceptual exposition, and examples to the material from the slides. Some notation and technical details have been changed; check the documentation.
  4. 4. 4 Term rewrite rules define transformations on (abstract syntax) trees. Traditional rewrite systems apply rules exhaustively. This paper introduces programmable rewriting strategies to control the application of rules, the core of the design of the Stratego transformation language. Note that the notation for contextual rules is no longer supported by Stratego. However, the technique to implement contextual rules still applies. https://doi.org/10.1145/291251.289425 ICFP 1998
  5. 5. 5 Stratego/XT combines SDF2 and Stratego into toolset for program transformation. This paper gives a high-level overview of the concepts. The StrategoXT.jar is still part of the Spoofax distribution. https://doi.org/10.1007/978-3-540-25935-0_13 Lecture Notes in Computer Science 2003
  6. 6. 6 Spoofax combines SDF2 and Stratego into a language workbench, i.e. an IDE for creating language definition from which IDEs for the defined languages can be generated. A distinctive feature of Spoofax is live language development, which supports developing a language definition and programs in the defined language in the same IDE instance. Spoofax was developed for Eclipse, which is still the main development platform. However, Spoofax Core is now independent of any IDE. https://doi.org/10.1145/1932682.1869497 OOPSLA 2010
  7. 7. 7 Note that the since the publication of this paper, we have introduced more declarative approaches to name and type analysis, which will be the topic of the next lectures. https://doi.org/10.1145/1932682.1869497 OOPSLA 2010
  8. 8. 8 Documentation for Stratego at the metaborg.org website. http://www.metaborg.org/en/latest/source/langdev/meta/lang/stratego/index.html
  9. 9. Transformation Architecture 9 This presentation uses the Stratego Shell for explaining the behavior of Stratego programs. The Stratego Shell is currently not supported by Spoofax
  10. 10. 10
  11. 11. 11
  12. 12. 12
  13. 13. 13
  14. 14. 14
  15. 15. 15
  16. 16. 16
  17. 17. 17
  18. 18. 18
  19. 19. Terms 19
  20. 20. Parsing: From Text to Terms 20 Let( [ FunDec( "fact" , [FArg("n", Tp(Tid("int")))] , Tp(Tid("int")) , If( Lt(Var("n"), Int("1")) , Int("1") , Seq( [ Times( Var("n") , Call( Var("fact") , [Minus(Var("n"), Int("1"))] ) ) ] ) ) ) ] , [Call(Var("fact"), [Int("10")])] ) let function fact(n : int) : int = if n < 1 then 1 else (n * fact(n - 1)) in fact(10) end
  21. 21. Syntax of Terms 21 module Terms sorts Cons Term lexical syntax Cons = [a-zA-Z][a-zA-Z0-9]* context-free syntax Term.App = <<Cons>(<{Term ","}*>)> Zero() Succ(Zero()) Cons(A(), Cons(B(), Nil()))
  22. 22. Syntax of Terms 22 module Terms sorts Cons Term lexical syntax Cons = [a-zA-Z][a-zA-Z0-9]* context-free syntax Term.App = <<Cons>(<{Term ","}*>)> Term.List = <[<{Term ","}*>]> Term.Tuple = <(<{Term ","}*>)> Zero() Succ(Zero()) [A(), B()]
  23. 23. module ATerms sorts Cons Term lexical syntax Cons = [a-zA-Z][a-zA-Z0-9]* Cons = String Int = [0-9]+ String = """ StringChar* """ StringChar = ~["n] StringChar = "" ["] context-free syntax Term.Str = <<String>> Term.Int = <<Int>> Term.App = <<Cons>(<{Term ","}*>)> Term.List = <[<{Term ","}*>]> Term.Tuple = <(<{Term ","}*>)> Syntax of Terms 23 0 1 [A(), B()] Var(“x”) Let( [ Decl(“x”, IntT()), Decl(“y”, BoolT()) ] , Eq(Var(“x”), Int(0)) )
  24. 24. Syntax of A(nnotated) Terms 24 module ATerms sorts Cons Term lexical syntax Cons = [a-zA-Z][a-zA-Z0-9]* // more lexical syntax omitted context-free syntax Term.Anno = <<PreTerm>{<{Term “,"}*>}> Term = <<PreTerm>> PreTerm.Str = <<String>> PreTerm.Int = <<Int>> PreTerm.App = <<Cons>(<{Term ","}*>)> PreTerm.List = <[<{Term ","}*>]> PreTerm.Tuple = <(<{Term ","}*>)> Var(“x”){Type(IntT())}
  25. 25. Signatures 25
  26. 26. Signatures 26 signature constructors Uminus : Exp -> Exp Power : Exp * Exp -> Exp Times : Exp * Exp -> Exp Divide : Exp * Exp -> Exp Plus : Exp * Exp -> Exp Minus : Exp * Exp -> Exp CPlus : Exp * Exp -> Exp CMinus : Exp * Exp -> Exp Eq : Exp * Exp -> Exp Neq : Exp * Exp -> Exp Gt : Exp * Exp -> Exp Lt : Exp * Exp -> Exp Geq : Exp * Exp -> Exp Leq : Exp * Exp -> Exp True : Exp False : Exp And : Exp * Exp -> Exp Or : Exp * Exp -> Exp context-free syntax Exp.Uminus = [- [Exp]] Exp.Power = [[Exp] ** [Exp]] Exp.Times = [[Exp] * [Exp]] Exp.Divide = [[Exp] / [Exp]] Exp.Plus = [[Exp] + [Exp]] Exp.Minus = [[Exp] - [Exp]] Exp.CPlus = [[Exp] +i [Exp]] Exp.CMinus = [[Exp] -i [Exp]] Exp.Eq = [[Exp] = [Exp]] Exp.Neq = [[Exp] <> [Exp]] Exp.Gt = [[Exp] > [Exp]] Exp.Lt = [[Exp] < [Exp]] Exp.Geq = [[Exp] >= [Exp]] Exp.Leq = [[Exp] <= [Exp]] Exp.True = <true> Exp.False = <false> Exp.And = [[Exp] & [Exp]] Exp.Or = [[Exp] | [Exp]] Signature declares argument and return types of term constructors Signature is automatically generated from SDF3 productions Stratego compiler only checks arity of constructor applications
  27. 27. Rewrite Rules 27
  28. 28. Desugaring 28 if x then printint(x) desugar: IfThen(e1, e2) -> IfThenElse(e1, e2, NoVal()) if x then printint(x) else () IfThen( Var("x") , Call( "printint" , [Var("x")] ) ) IfThenElse( Var("x") , Call( "printint" , [Var("x")] ) , NoVal() ) pattern matching pattern instantiation e1 e2
  29. 29. More Desugaring 29 desugar: Uminus(e) -> Bop(MINUS(), Int("0"), e) desugar: Plus(e1, e2) -> Bop(PLUS(), e1, e2) desugar: Minus(e1, e2) -> Bop(MINUS(), e1, e2) desugar: Times(e1, e2) -> Bop(MUL(), e1, e2) desugar: Divide(e1, e2) -> Bop(DIV(), e1, e2) desugar: Eq(e1, e2) -> Rop(EQ(), e1, e2) desugar: Neq(e1, e2) -> Rop(NE(), e1, e2) desugar: Leq(e1, e2) -> Rop(LE(), e1, e2) desugar: Lt(e1, e2) -> Rop(LT(), e1, e2) desugar: Geq(e1, e2) -> Rop(LE(), e2, e1) desugar: Gt(e1, e2) -> Rop(LT(), e2, e1) desugar: And(e1, e2) -> IfThenElse(e1, e2, Int("0")) desugar: Or(e1, e2) -> IfThenElse(e1, Int("1"), e2) signature constructors PLUS: BinOp MINUS: BinOp MUL: BinOp DIV: BinOp EQ: RelOp NE: RelOp LE: RelOp LT: RelOp Bop: BinOp * Expr * Expr -> Expr Rop: RelOp * Expr * Expr -> Expr
  30. 30. Constant Folding 30 x := 21 + 21 + x eval: Bop(PLUS(), Int(i1), Int(i2)) -> Int(i3) where <addS> (i1, i2) => i3 x := 42 + x Assign( Var("x") , Plus( Plus( Int("21") , Int("21") ) , Var("x") ) ) Assign( Var("x") , Plus( Int("42") , Var("x") ) )
  31. 31. More Constant Folding 31 eval: Bop(PLUS(), Int(i1), Int(i2)) -> Int(<addS> (i1, i2)) eval: Bop(MINUS(), Int(i1), Int(i2)) -> Int(<subtS> (i1, i2)) eval: Bop(MUL(), Int(i1), Int(i2)) -> Int(<mulS> (i1, i2)) eval: Bop(DIV(), Int(i1), Int(i2)) -> Int(<divS> (i1, i2)) eval: Rop(EQ(), Int(i), Int(i)) -> Int("1") eval: Rop(EQ(), Int(i1), Int(i2)) -> Int("0") where not( <eq> (i1, i2) ) eval: Rop(NE(), Int(i), Int(i)) -> Int("0") eval: Rop(NE(), Int(i1), Int(i2)) -> Int("1") where not( <eq> (i1, i2) ) eval: Rop(LT(), Int(i1), Int(i2)) -> Int("1") where <ltS> (i1, i2) eval: Rop(LT(), Int(i1), Int(i2)) -> Int("0") where not( <ltS> (i1, i2) ) eval: Rop(LE(), Int(i1), Int(i2)) -> Int("1") where <leqS> (i1, i2) eval: Rop(LE(), Int(i1), Int(i2)) -> Int("0") where not( <leqS> (i1, i2))
  32. 32. Term Rewriting (Bottom-up) 32
  33. 33. 33
  34. 34. 34
  35. 35. 35
  36. 36. 36
  37. 37. 37
  38. 38. 38
  39. 39. 39
  40. 40. 40
  41. 41. 41
  42. 42. 42
  43. 43. 43
  44. 44. 44
  45. 45. 45
  46. 46. 46
  47. 47. 47
  48. 48. 48
  49. 49. 49
  50. 50. 50
  51. 51. 51
  52. 52. 52
  53. 53. 53
  54. 54. 54
  55. 55. 55
  56. 56. 56
  57. 57. 57
  58. 58. 58
  59. 59. 59
  60. 60. 60
  61. 61. 61
  62. 62. Parameterized Rewrite Rules: Map 62 [ 1 , 2 , 3 ] [ 2 , 3 , 4 ] map(inc) inc 1 2 3 2 3 4inc inc map(s): [] -> [] map(s): [x|xs] -> [<s> x | <map(s)> xs]
  63. 63. Parameterized Rewrite Rules: Zip 63 [ 1 , 2 , 3 ] [ (1,4) , (2,5) , (3,6) ] [ 4 , 5 , 6 ] zip [ 1 , 2 , 3 ] [ 5 , 7 , 9 ] [ 4 , 5 , 6 ] zip(add) map(add) zip(s): ([],[]) -> [] zip(s): ([x|xs],[y|ys]) -> [<s> (x,y) | <zip(s)> (xs,ys)] zip = zip(id)
  64. 64. Parameterized Rewrite Rules: Fold 64 [1,2,3] foldr(!0,add) 6 [] 0 [3] 3 [2,3] 56 [1,2,3] foldr(s1,s2): [] -> <s1> foldr(s1,s2): [x|xs] -> <s2> (x,<foldr(s1,s2)> xs)
  65. 65. Parameterized Rewrite Rules: Inverse 65 [1,2,3] inverse(|[]) [3,2,1] [2,3] [1][] [1,2,3] [3] [2,1] [3,2,1] [] inverse(|is): [] -> is inverse(|is): [x|xs] -> <inverse(|[x|is])> xs
  66. 66. 66
  67. 67. 67
  68. 68. 68
  69. 69. 69
  70. 70. Traversal Strategies 70
  71. 71. 71
  72. 72. 72
  73. 73. 73
  74. 74. 74
  75. 75. 75
  76. 76. 76
  77. 77. 77
  78. 78. 78
  79. 79. 79
  80. 80. 80
  81. 81. 81
  82. 82. 82
  83. 83. 83
  84. 84. 84
  85. 85. Traversal Combinators 85
  86. 86. 86
  87. 87. 87
  88. 88. 88
  89. 89. 89
  90. 90. 90
  91. 91. 91
  92. 92. 92
  93. 93. Traversal: Topdown 93 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) topdown(s) = s ; all(topdown(s)) topdown(switch) Const Mul Const 3 4 5 Const Add1
  94. 94. Traversal: Topdown 94 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) topdown(s) = s ; all(topdown(s)) topdown(switch) Mul Const 3 Const 4 5 Const Add1 2
  95. 95. Traversal: Topdown 95 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) topdown(s) = s ; all(topdown(s)) topdown(switch) Mul Const 3 Const 5 4 Const Add1 2 3
  96. 96. Traversal: Topdown/Try 96 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) topdown(s) = s ; all(topdown(s)) topdown(try(switch)) Const Mul Const 3 4 5 Const Add1
  97. 97. Traversal: Topdown/Try 97 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) topdown(s) = s ; all(topdown(s)) topdown(try(switch)) Mul Const 3 Const 4 5 Const Add1 2
  98. 98. Traversal: Topdown/Try 98 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) topdown(s) = s ; all(topdown(s)) topdown(try(switch)) Mul Const 3 Const 5 4 Const Add1 2 3 4 5 6 7 8
  99. 99. Traversal: Alltd 99 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) alltd(s) = s <+ all(alltd(s)) alltd(switch) Const Mul Const 3 4 5 Const Add1
  100. 100. Traversal: Alltd 100 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) alltd(s) = s <+ all(alltd(s)) alltd(switch) Mul Const 3 Const 4 5 Const Add1
  101. 101. Traversal: Alltd 101 switch: Mul(e1, e2) -> Mul(e2, e1) alltd(s) = s <+ all(alltd(s)) alltd(switch) Const Mul Const 3 4 5 Const Add1 2 3 4
  102. 102. Traversal: Alltd 102 switch: Mul(e1, e2) -> Mul(e2, e1) alltd(s) = s <+ all(alltd(s)) alltd(switch) Const Mul Const 3 5 4 Const Add1 2 3 4
  103. 103. Traversal: Bottomup 103 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) bottomup(s) = all(bottomup(s)) ; s bottomup(switch) Const Mul Const 3 4 5 Const Add1 2 3
  104. 104. Traversal: Bottomup 104 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) bottomup(s) = all(bottomup(s)) ; s bottomup(try(switch)) Const Mul Const 3 4 5 Const Add1 2 3 4 5 6 7 8
  105. 105. Traversal: Bottomup 105 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) bottomup(s) = all(bottomup(s)) ; s bottomup(try(switch)) Const Mul Const 3 4 5 Const Add1 2 3 4
  106. 106. Traversal: Bottomup 106 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) bottomup(s) = all(bottomup(s)) ; s bottomup(try(switch)) Const Mul Const 3 5 4 Const Add1 2 3 4
  107. 107. Traversal: Bottomup 107 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) bottomup(s) = all(bottomup(s)) ; s bottomup(try(switch)) Const Mul Const 3 5 4 Const Add1
  108. 108. Traversal: Bottomup 108 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) bottomup(s) = all(bottomup(s)) ; s bottomup(try(switch)) Mul Const 3 Const 5 4 Const Add1
  109. 109. 109
  110. 110. 110
  111. 111. Traversal: Innermost 111 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) innermost(s) = bottomup(try(s ; innermost(s))) innermost(switch) Const Mul Const 3 4 5 Const Add1 2 3 4 5 6 7 8
  112. 112. Traversal: Innermost 112 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) innermost(s) = bottomup(try(s ; innermost(s))) innermost(switch) Const Mul Const 3 4 5 Const Add1 2 3 4
  113. 113. Traversal: Innermost 113 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) innermost(s) = bottomup(try(s ; innermost(s))) innermost(switch) Const Mul Const 3 5 4 Const Add1 2 3 4 9 10 11 12
  114. 114. Traversal: Innermost 114 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) innermost(s) = bottomup(try(s ; innermost(s))) innermost(switch) Const Mul Const 3 5 4 Const Add1 2 3 4
  115. 115. Traversal: Innermost 115 switch: Add(e1, e2) -> Add(e2, e1) switch: Mul(e1, e2) -> Mul(e2, e1) innermost(s) = bottomup(try(s ; innermost(s))) innermost(switch) Const Mul Const 3 4 5 Const Add1 2 3 4
  116. 116. 116
  117. 117. 117
  118. 118. 118
  119. 119. 119
  120. 120. 120
  121. 121. 121
  122. 122. Type-Unifying Transformations 122
  123. 123. 123
  124. 124. 124
  125. 125. 125
  126. 126. 126
  127. 127. 127
  128. 128. 128
  129. 129. 129
  130. 130. 130
  131. 131. 131
  132. 132. 132
  133. 133. 133
  134. 134. 134
  135. 135. 135
  136. 136. 136
  137. 137. 137
  138. 138. 138
  139. 139. 139
  140. 140. 140
  141. 141. 141
  142. 142. 142
  143. 143. 143
  144. 144. 144
  145. 145. 145
  146. 146. 146
  147. 147. 147
  148. 148. 148
  149. 149. 149
  150. 150. 150
  151. 151. 151
  152. 152. 152
  153. 153. 153
  154. 154. 154
  155. 155. Spoofax Builders 155
  156. 156. Spoofax Builders 156 rules build : (node, _, ast, path, project-path) -> result with <some-transformation> ast => result Builder gets AST as parameter
  157. 157. Tiger: AST Builder 157 rules // Debugging debug-show-aterm: (node, _, _, path, project-path) -> (filename, result) with filename := <guarantee-extension(|"aterm")> path ; result := node trans/tiger.str module Syntax menus menu: "Syntax" (openeditor) action: "Format" = editor-format (source) action: "Show parsed AST" = debug-show-aterm (source) editor/syntax.esv Builder gets AST as parameter
  158. 158. Application: Formatting 158
  159. 159. Tiger: Formatting Builder 159 module Syntax menus menu: "Syntax" (openeditor) action: "Format" = editor-format (source) action: "Show parsed AST" = debug-show-aterm (source) rules editor-format: (node, _, ast, path, project-path) -> (filename, result) with ext := <get-extension> path ; filename := <guarantee-extension(|$[pp.[ext]])> path ; result := <pp-debug> node editor/syntax.esv trans/pp.str rules pp-Tiger-string = parenthesize-Tiger ; prettyprint-Tiger-start-symbols ; !V([], <id>) ; box2text-string(|120) pp-debug : ast -> result with result := <pp-Tiger-string> ast <+ … ; result := “" trans/pp.str
  160. 160. Tiger: Parenthesize 160 module pp/Tiger-parenthesize imports libstratego-lib signatures/- strategies parenthesize-Tiger = innermost(TigerParenthesize) rules TigerParenthesize : Or(t_0, t_1) -> Or(t_0, Parenthetical(t_1)) where <(?For(_, _, _, _) + ?While(_, _) + ?IfThen(_, _) + ?If(_, _, _) + ?Assign(_, _) + ?Array(_, _, _) + ?Or(_, _) + fail)> t_1 TigerParenthesize : And(t_0, t_1) -> And(Parenthetical(t_0), t_1) where <(?For(_, _, _, _) + ?While(_, _) + ?IfThen(_, _) + ?If(_, _, _) + ?Assign(_, _) + ?Array(_, _, _) + ?Or(_, _) + fail)> t_0 pp/Tiger-parenthesize.str context-free priorities Exp.And > Exp.Or > Exp.Array > Exp.Assign > …
  161. 161. Tiger: Pretty-Print Rules 161 rules prettyprint-Tiger-Exp : If(t1__, t2__, t3__) -> [ H( [SOpt(HS(), "0")] , [ S("if ") , t1__' , S(" then") ] ) , t2__' , H( [SOpt(HS(), "0")] , [S("else")] ) , t3__' ] with t1__' := <pp-one-Z(prettyprint-Tiger-Exp) <+ pp-one-Z(prettyprint-completion-aux)> t1__ with t2__' := <pp-indent(|"2")> [ <pp-one-Z(prettyprint-Tiger-Exp) <+ pp-one-Z(prettyprint-completion-aux)> t2__ ] with t3__' := <pp-indent(|"2")> [ <pp-one-Z(prettyprint-Tiger-Exp) <+ pp-one-Z(prettyprint-completion-aux)> t3__ ] context-free syntax Exp.If = < if <Exp> then <Exp> else <Exp> > syntax/Control-Flow.sdf3 pp/Control-Flow-pp.str
  162. 162. Application: Desugaring 162
  163. 163. Tiger: Desugaring 163 function printboard() = ( for i := 0 to N-1 do ( for j := 0 to N-1 do print(if col[i]=j then " O" else " ."); print("n") ); print("n") ) function printboard() = ( let var i : int := 0 in while i < N - 1 do ( ( let var j : int := 0 in while j < N - 1 do ( print(if col[i] = j then " O" else " ."); j := j + 1 ) end; print("n") ); i := i + 1 ) end; print("n") ) Expressing for in terms of while++
  164. 164. Tiger: Desugaring Builder 164 rules // Desugaring editor-desugar : (node, _, _, path, project-path) -> (filename, result) with filename := <guarantee-extension(|"des.tig")> path ; result := <desugar-all; pp-Tiger-string>node editor-desugar-ast : (node, _, _, path, project-path) -> (filename, result) with filename := <guarantee-extension(|"aterm")> path ; result := <desugar-all>node trans/tiger.str module Transformation menus menu: "Transform" (openeditor) (realtime) action: "Desugar" = editor-desugar (source) action: "Desugar AST" = editor-desugar-ast (source) editor/Transformation.esv
  165. 165. Tiger: Desugaring Transformation 165 module desugar imports signatures/Tiger-sig imports … strategies desugar-all = topdown(try(desugar)) rules desugar : For( Var(i) , e1 , e2 , e_body ) -> Let( [VarDec(i, Tid("int"), e1)] , [ While( Lt(Var(i), e2) , Seq( [ e_body , Assign(Var(i), Plus(Var(i), Int("1"))) ] ) ) ] )
  166. 166. Application: Outline View 166
  167. 167. Tiger: Outline View 167
  168. 168. Tiger: Outline View Builder 168 module Syntax views outline view: editor-outline (source) expand to level: 3 editor/syntax.esv trans/outline.str module outline imports signatures/Tiger-sig signatures/Types-sig signatures/Records-sig signatures/Variables-sig signatures/Functions-sig signatures/Bindings-sig libspoofax/editor/outline pp rules editor-outline: (_, _, ast, path, project-path) -> outline where outline := <simple-label-outline(to-outline-label)> ast
  169. 169. Tiger: Outline View Rules 169 rules to-outline-label : Let(_, _) -> $[let] to-outline-label : TypeDec(name, _) -> $[type [name]] to-outline-label : FunDec(name, _, t, _) -> $[fun [name] : [<pp-tiger-type> t]] to-outline-label : ProcDec(name, _, _) -> $[fun [name]] to-outline-label : VarDecNoType(name, _) -> $[var [name]] to-outline-label : VarDec(name, _, _) -> $[var [name]] trans/outline.str rules to-outline-label : Call(f, _) -> $[[f]()] to-outline-label : If(_, _, _) -> $[if] to-outline-label : For(Var(name), _, _, _) -> $[for [name]] // etc.
  170. 170. Outline View: Generic Strategy 170 module libspoofax/editor/outline imports … signature constructors Node : Label * Children -> Node rules simple-label-outline(s1) = collect-om(to-outline-node(s1, fail), conc) custom-label-outline(s1, s2) = collect-om(origin-track-forced(s2) <+ to-outline-node(s1, s2), conc) to-outline-node(s1, s2): term -> Node(label, children) where random := <next-random>; label := <origin-track-forced(s1; term-to-outline-label)> term; children := <get-arguments; custom-label-outline(s1, s2)> term term-to-outline-label = is-string <+ ?term{a}; origin-text; ?label; !label{a} <+ write-to-string // fallback Language-independent strategy for collecting outline nodes Term structure for outline nodes
  171. 171. Application: Completion 171
  172. 172. Tiger: Completion Rules 172 rules suggest-completions(|completions): Exp-Plhdr() -> <add-completions( | ( "If" , If( <try(inline-completions(|Exp-Plhdr()))> Exp-Plhdr() , <try(inline-completions(|Exp-Plhdr()))> Exp-Plhdr() , <try(inline-completions(|Exp-Plhdr()))> Exp-Plhdr() ) ) ) ; fail> completions context-free syntax Exp.If = < if <Exp> then <Exp> else <Exp> > syntax/Control-Flow.sdf3 completion/Control-Flow-cp.str
  173. 173. 173 Except where otherwise noted, this work is licensed under

×