Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Toy Language Interpreter

A Toy Language Interpreter

Ionuț G. Stan

December 18, 2014
Tweet

More Decks by Ionuț G. Stan

Other Decks in Programming

Transcript

  1. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Plan ‣ Interpreters

    and Compilers ‣ Why Learn Compilers ‣ Why Scala for Today ‣ Coding Part
  2. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Learn Compilers

    ‣ This is my motivation ‣ I like looking under the hood ‣ A compiler's hood is like a starship's hood ‣ Compilers are really well documented ‣ You get to understand tricky language concepts ‣ You get to understand modular architecture ‣ Useful for (E)DSLs development ‣ It's fun!
  3. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Learn Compilers

    ‣ This is my motivation ‣ I like looking under the hood ‣ A compiler's hood is like a starship's hood ‣ Compilers are really well documented ‣ You get to understand tricky language concepts ‣ You get to understand modular architecture ‣ Useful for (E)DSLs development ‣ It's fun!
  4. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Learn Compilers

    ‣ This is my motivation ‣ I like looking under the hood ‣ A compiler's hood is like a starship's hood ‣ Compilers are really well documented ‣ You get to understand tricky language concepts ‣ You get to understand modular architecture ‣ Useful for (E)DSLs development ‣ It's fun!
  5. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Learn Compilers

    ‣ This is my motivation ‣ I like looking under the hood ‣ A compiler's hood is like a starship's hood ‣ Compilers are really well documented ‣ You get to understand tricky language concepts ‣ You get to understand modular architecture ‣ Useful for (E)DSLs development ‣ It's fun!
  6. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Learn Compilers

    ‣ This is my motivation ‣ I like looking under the hood ‣ A compiler's hood is like a starship's hood ‣ Compilers are really well documented ‣ You get to understand tricky language concepts ‣ You get to understand modular architecture ‣ Useful for (E)DSLs development ‣ It's fun!
  7. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Learn Compilers

    ‣ This is my motivation ‣ I like looking under the hood ‣ A compiler's hood is like a starship's hood ‣ Compilers are really well documented ‣ You get to understand tricky language concepts ‣ You get to understand modular architecture ‣ Useful for (E)DSLs development ‣ It's fun!
  8. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Learn Compilers

    ‣ This is my motivation ‣ I like looking under the hood ‣ A compiler's hood is like a starship's hood ‣ Compilers are really well documented ‣ You get to understand tricky language concepts ‣ You get to understand modular architecture ‣ Useful for (E)DSLs development ‣ It's fun!
  9. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Learn Compilers

    ‣ This is my motivation ‣ I like looking under the hood ‣ A compiler's hood is like a starship's hood ‣ Compilers are really well documented ‣ You get to understand tricky language concepts ‣ You get to understand modular architecture ‣ Useful for (E)DSLs development ‣ It's fun!
  10. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Scala ‣

    I could have used Java 8 ‣ But... there's one missing feature in Java 8 ‣ The closest alternative is the Visitor pattern ‣ But that's a cumbersome pattern ‣ Last, but not least, I write Scala daily :-)
  11. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Scala ‣

    I could have used Java 8 ‣ One missing feature, though ‣ The closest alternative is the Visitor pattern ‣ But that's a cumbersome pattern ‣ Last, but not least, I write Scala daily :-)
  12. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Scala ‣

    I could have used Java 8 ‣ One missing feature, though: pattern matching ‣ The closest alternative is the Visitor pattern ‣ But that's a cumbersome pattern ‣ Last, but not least, I write Scala daily :-)
  13. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Representing an AST

    in Scala trait Node! case class Num(value: Int) extends Node! case class Add(left: Node, right: Node) extends Node! ! val ast = Add(Num(1), Num(2))! ! val sum = ast match {! case Add(Num(a), Num(b)) => a + b! }
  14. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Representing an AST

    in Scala trait Node! case class Num(value: Int) extends Node! case class Add(left: Node, right: Node) extends Node! ! val ast = Add(Num(1), Num(2))! ! val sum = ast match {! case Add(Num(a), Num(b)) => a + b! }
  15. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Representing an AST

    in Scala trait Node! case class Num(value: Int) extends Node! case class Add(left: Node, right: Node) extends Node! ! val ast = Add(Num(1), Num(2))! ! val sum = ast match {! case Add(Num(a), Num(b)) => a + b! }
  16. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Representing an AST

    in Scala trait Node! case class Num(value: Int) extends Node! case class Add(left: Node, right: Node) extends Node! ! val ast = Add(Num(1), Num(2))! ! val sum = ast match {! case Add(Num(a), Num(b)) => a + b! }
  17. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Traversing an AST

    in Scala trait Node! case class Num(value: Int) extends Node! case class Add(left: Node, right: Node) extends Node! ! val ast = Add(Num(1), Num(2))! ! val sum = ast match {! case Add(Num(a), Num(b)) => a + b! }
  18. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Scala ‣

    I could have used Java 8 ‣ One missing feature, though: pattern matching ‣ The closest alternative is the Visitor pattern ‣ But that's a cumbersome pattern ‣ Last, but not least, I write Scala daily :-)
  19. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Representing an AST

    in Java public interface Node {}! ! public class Num implements Node {! public final int value;! public Num(int value) { this.value = value; }! }! ! public class Add implements Node {! public final Node left, right;! public Add(Node left, Node right) {! this.left = left;! this.right = right;! }! }
  20. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Representing an AST

    in Java public interface Node {}! ! public class Num implements Node {! public final int value;! public Num(int value) { this.value = value; }! }! ! public class Add implements Node {! public final Node left, right;! public Add(Node left, Node right) {! this.left = left;! this.right = right;! }! }
  21. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Representing an AST

    in Java public interface Node {}! ! public class Num implements Node {! public final int value;! public Num(int value) { this.value = value; }! }! ! public class Add implements Node {! public final Node left, right;! public Add(Node left, Node right) {! this.left = left;! this.right = right;! }! }
  22. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Traversing an AST

    in Java public interface Node {! public <R> R match(Matcher<R> matcher);! }! ! public interface Matcher<R> {! public R matchNum(Num n);! public R matchAdd(Add a);! }
  23. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Traversing an AST

    in Java public class Num implements Node {! // fields and constructor omitted! ! @Override! public <R> R match(Matcher<R> matcher) {! return matcher.matchNum(this);! }! }
  24. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Traversing an AST

    in Java public class Add implements Node {! // fields and constructor omitted! ! @Override! public <R> R match(Matcher<R> matcher) {! return matcher.matchAdd(this);! }! }
  25. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Traversing an AST

    in Java int ast = new Add(new Num(1), new Num(2));! ! int sum = ast.match(new Matcher<Integer> {! @Override! public R matchNum(Num n) {! return n.value;! }! ! @Override! public R matchAdd(Add a) {! int left = a.left.match(this);! int right = a.right.match(this);! return left + right;! }! });
  26. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Traversing an AST

    in Java int ast = new Add(new Num(1), new Num(2));! ! int sum = ast.match(new Matcher<Integer> {! @Override! public R matchNum(Num n) {! return n.value;! }! ! @Override! public R matchAdd(Add a) {! int left = a.left.match(this);! int right = a.right.match(this);! return left + right;! }! });
  27. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Traversing an AST

    in Java int ast = new Add(new Num(1), new Num(2));! ! int sum = ast.match(new Matcher<Integer> {! @Override! public Integer matchNum(Num n) {! return n.value;! }! ! @Override! public R matchAdd(Add a) {! int left = a.left.match(this);! int right = a.right.match(this);! return left + right;! }! });
  28. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Traversing an AST

    in Java int ast = new Add(new Num(1), new Num(2));! ! int sum = ast.match(new Matcher<Integer> {! @Override! public Integer matchNum(Num n) {! return n.value;! }! ! @Override! public Integer matchAdd(Add a) {! int left = a.left.match(this);! int right = a.right.match(this);! return left + right;! }! });
  29. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Traversing an AST

    in Java public interface Node {! public <R> R match(Matcher<R> matcher);! }! ! public interface Matcher<R> {! public R matchNum(Num n);! public R matchAdd(Add a);! }
  30. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro The Visitor Pattern

    public interface Node {! public <R> R visit(NodeVisitor<R> visitor);! }! ! public interface NodeVisitor<R> {! public R visitNum(Num n);! public R visitAdd(Add a);! }
  31. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Nashorn $ nashorn:

    cd nashorn/src/jdk/nashorn/internal/ir/! $ ir: ls *Node.java! AccessNode.java FunctionNode.java ReturnNode.java! BaseNode.java IdentNode.java RuntimeNode.java! BinaryNode.java IfNode.java SplitNode.java! BreakNode.java IndexNode.java SwitchNode.java! BreakableNode.java LabelNode.java TernaryNode.java! CallNode.java LexicalContextNode.java ThrowNode.java! CaseNode.java LiteralNode.java TryNode.java! CatchNode.java LoopNode.java UnaryNode.java! ContinueNode.java Node.java VarNode.java! EmptyNode.java ObjectNode.java WhileNode.java! ForNode.java PropertyNode.java WithNode.java
  32. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Nashorn $ ir:

    cd ..! $ internal: find . -name *Visitor*! ./ir/debug/PrintVisitor.java! ./ir/visitor/NodeOperatorVisitor.java! ./ir/visitor/NodeVisitor.java! $ internal: grep -hR 'extends NodeVisitor' .! final class FoldConstants extends NodeVisitor<LexicalContext> {! final class Splitter extends NodeVisitor<LexicalContext> {! public final class JSONWriter extends NodeVisitor<LexicalContext> {! public final class PrintVisitor extends NodeVisitor<LexicalContext> {! public class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T> {
  33. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Example Interpreter in

    Java https://github.com/igstan/tree-interpreter-visitor
  34. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Scala ‣

    I could have used Java 8 ‣ One missing feature, though: pattern matching ‣ The closest alternative is the Visitor pattern ‣ Cumbersome pattern, for me ‣ Last, but not least, I write Scala daily :-)
  35. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Scala ‣

    I could have used Java 8 ‣ One missing feature, though: pattern matching ‣ The closest alternative is the Visitor pattern ‣ Cumbersome pattern, for me ‣ Last, but not least, I write Scala daily :-)
  36. Ionuț G. Stan · ionut.g.stan@gmail.com · igstan.ro Why Scala ‣

    I could have used Java 8 ‣ One missing feature, though: pattern matching ‣ The closest alternative is the Visitor pattern ‣ Cumbersome pattern, for me ‣ Last, but not least, I write Scala daily :-)