summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/interpreter.rb
blob: 88ab5854ea65e05e7e494161ee20eabed7a280b8 (plain)
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/local/bin/ruby -w

# $Id$

# the interpreter
#
# this builds our virtual pinball machine, into which we'll place our host-specific
# information and out of which we'll receive our host-specific configuration

require 'puppet'
require 'puppet/parser/parser'
require 'puppet/parser/scope'


module Puppet
    module Parser
        #---------------------------------------------------------------
        class Interpreter
            attr_accessor :ast, :topscope
            # just shorten the constant path a bit, using what amounts to an alias
            AST = Puppet::Parser::AST

            #------------------------------------------------------------
            def clear
                TransObject.clear
            end
            #------------------------------------------------------------

            #------------------------------------------------------------
            #def callfunc(function,*args)
            #    #Puppet.debug("Calling %s on %s" % [function,@client])
            #    @client.callfunc(function,*args)
            #    #Puppet.debug("Finished %s" % function)
            #end
            #------------------------------------------------------------

            #------------------------------------------------------------
            # create our interpreter
            def initialize(hash)
                unless hash.include?(:ast)
                    raise ArgumentError.new("Must pass tree and client to Interpreter")
                end
                @ast = hash[:ast]
                #@client = hash[:client]

                @scope = Puppet::Parser::Scope.new() # no parent scope
                @topscope = @scope
                @scope.interp = self

                if hash.include?(:facts)
                    facts = hash[:facts]
                    unless facts.is_a?(Hash)
                        raise ArgumentError.new("Facts must be a hash")
                    end

                    facts.each { |fact,value|
                        @scope.setvar(fact,value)
                    }
                end
            end
            #------------------------------------------------------------

            #------------------------------------------------------------
            # evaluate our whole tree
            def run
                # evaluate returns a value, but at the top level we only
                # care about its side effects
                # i think
                unless @ast.is_a?(AST) or @ast.is_a?(AST::ASTArray)
                    Puppet.err "Received top-level non-ast '%s' of type %s" %
                        [@ast,@ast.class]
                    raise TypeError.new("Received non-ast '%s' of type %s" %
                        [@ast,@ast.class])
                end

                begin
                    @ast.evaluate(@scope)
                rescue Puppet::DevError, Puppet::Error, Puppet::ParseError => except
                    #Puppet.err "File %s, line %s: %s" %
                    #    [except.file, except.line, except.message]
                    if Puppet[:debug]
                        puts except.stack
                    end
                    #exit(1)
                    raise
                rescue => except
                    error = Puppet::DevError.new("%s: %s" %
                        [except.class, except.message])
                    error.stack = caller
                    if Puppet[:debug]
                        puts error.stack
                    end
                    raise error
                end

                # okay, at this point we have a tree of scopes, and we want to
                # unzip along that tree, building our structure of objects
                # to pass to the client
                # this will be heirarchical, and will (at this point) contain
                # only TransObjects and TransSettings
                @topscope.name = "top"
                @topscope.type = "puppet"
                begin
                    topbucket = @topscope.to_trans
                rescue => detail
                    Puppet.warning detail
                    raise
                end

                # add our settings to the front of the array
                # at least, for now
                #@topscope.typesets.each { |setting|
                #    topbucket.unshift setting
                #}

                # guarantee that settings are at the very top
                #topbucket.push settingbucket
                #topbucket.push @scope.to_trans

                #retlist = TransObject.list
                #Puppet.debug "retobject length is %s" % retlist.length
                #TransObject.clear
                return topbucket
            end
            #------------------------------------------------------------

            #------------------------------------------------------------
            def scope
                return @scope
            end
            #------------------------------------------------------------
        end
        #---------------------------------------------------------------
    end
end