Xavier Nayrac

Rubyiste accro au TDD, serial blogger, apprenti data scientist, heureux utilisateur de Vim, accordéoniste.
Si vous vous sentez particulièrement généreux, suivez moi sur Twitter.

Un langage sur Parrot - partie 13

| Comments

Niveau : intermédiaire

Après avoir utilisé un AST pour représenter le code source de Naam, je parcours cet AST pour sortir le code assembleur PIR pour la machine virtuelle Parrot.

Voici la méthode principale (et temporaire):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def self.run(filename)
  .
  .
  .
  syntaxer = Syntaxer.new
  ast = syntaxer.run(units.dup)

  organizer = Organizer.new(ast)
  ast = organizer.reorganize

  emitter = Emitter.new(ast)
  pir_code = emitter.pir_code
  puts pir_code
end

La classe Syntaxer se charge de transformer la suite d’unités lexicales en un arbre syntaxique abstrait (AST). La classe Organizer va en quelque sorte réorganiser l’arbre, par exemple en regroupant les instructions qui ne sont pas dans une fonction à l’intérieur d’une fonction principale PIR. Quant à la classe Emitter, elle est chargée de transformer l’AST en code PIR.

Voici un extrait de cette classe Emitter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
module Naam
  class Emitter

    def initialize(ast)
      @ast = ast.dup
      @code = ""
      @label = "LABEL0000"
      @labels = []
    end

    # Public: Get PIR code.
    #
    # Returns PIR code as a String.
    def pir_code
      compile(@ast)
      @code
    end

    private

    def compile(node)
      case node
      when MainAST then compile_main(node)
      when FunctionHeaderAST then compile_header(node)
      when IfClauseAST then compile_if_clause(node)
      when ElseClauseAST then compile_else_clause(node)
      when FunctionFooterAST then compile_footer(node)
      end
      node.children.each {|child| compile(child) }
    end

    ...

    def compile_header(node)
      name = node.children.first.value
      arg = node.children.last.value
      @code += ".sub #{name}\n"
      @code += "    .param int #{arg}\n"
      @code += "    .local int result\n"
    end

    ...

    # Get the next label.
    #
    # value - The String value attached to the label.
    #
    # Examples
    #
    #   next_label
    #   # => {name: "LABEL0001", value: "123"}.
    #
    # Returns a Hash.
    def next_label(value)
      label = {name: @label.next!.dup, value: value}
      @labels << label
      label
    end

  end
end

La prochaine fois, le compilateur sera fonctionnel.

À demain.

Articles connexes

Commentaires