sbuilder-ethereum 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/VERSION +1 -0
  3. data/lib/mixer/decl_ref.rb +19 -0
  4. data/lib/mixer/domain_ref.rb +18 -0
  5. data/lib/mixer/scope.rb +92 -0
  6. data/lib/mixer/scoped.rb +17 -0
  7. data/lib/mixer/symbol_ref.rb +16 -0
  8. data/lib/mixer/type_symbol.rb +75 -0
  9. data/lib/plugin/plugin.rb +332 -0
  10. data/lib/resources/correctness/accouns_type.tla +1 -0
  11. data/lib/resources/correctness/accounts_unique.tla +2 -0
  12. data/lib/resources/correctness/accounts_valid.tla +2 -0
  13. data/lib/resources/correctness/storage_root_unique.tla +2 -0
  14. data/lib/resources/correctness/total_value.tla +1 -0
  15. data/lib/resources/eth/accounts_state.tla +2 -0
  16. data/lib/resources/eth/accounts_temp.tla +2 -0
  17. data/lib/resources/eth/address_free.tla +2 -0
  18. data/lib/resources/eth/mined_state.tla +1 -0
  19. data/lib/resources/eth/storageRoot.tla +1 -0
  20. data/lib/resources/eth/storageRoot_temp.tla +1 -0
  21. data/lib/resources/mine/mine_entry.tla +4 -0
  22. data/lib/resources/mine/mine_service.tla +22 -0
  23. data/lib/resources/operators/elementExists.tla +4 -0
  24. data/lib/resources/operators/gasPrice.tla +2 -0
  25. data/lib/resources/operators/gasValue.tla +2 -0
  26. data/lib/resources/operators/getElement.tla +5 -0
  27. data/lib/resources/operators/intrinsicGas.tla +4 -0
  28. data/lib/resources/operators/transactionGas.tla +4 -0
  29. data/lib/resources/operators/upFrontCost.tla +6 -0
  30. data/lib/resources/personal_newAccount/personal_newAccount_done.tla +14 -0
  31. data/lib/resources/personal_newAccount/personal_newAccount_entry.tla +10 -0
  32. data/lib/resources/personal_newAccount/personal_newAccount_service.tla +29 -0
  33. data/lib/resources/removed/sendTransaction_entry.tla +5 -0
  34. data/lib/resources/removed/sendTransaction_service.tla +36 -0
  35. data/lib/resources/removed/tst.tla +1 -0
  36. data/lib/resources/transaction/ethereum_service_done.tla +24 -0
  37. data/lib/resources/transaction/ethereum_service_pop.tla +24 -0
  38. data/lib/resources/transaction/ethereum_service_push.tla +14 -0
  39. data/lib/resources/transaction/ethereum_service_start.tla +13 -0
  40. data/lib/resources/transaction/status_fail.tla +1 -0
  41. data/lib/resources/transaction/status_ok.tla +1 -0
  42. data/lib/sbuilder-ethereum.rb +52 -0
  43. data/lib/sbuilder/compile.rb +163 -0
  44. data/lib/sbuilder/constants.rb +93 -0
  45. data/lib/sbuilder/exception.rb +22 -0
  46. data/lib/sbuilder/generate/sexp_processor_tla.rb +2674 -0
  47. data/lib/sbuilder/generate/tla_element_generator.rb +1206 -0
  48. data/lib/sbuilder/generate/tla_element_text.rb +703 -0
  49. data/lib/sbuilder/load.rb +119 -0
  50. data/lib/sbuilder/mustache/renderer.rb +152 -0
  51. data/lib/sbuilder/render.rb +141 -0
  52. data/lib/sbuilder/s.rb +21 -0
  53. data/lib/sbuilder/sexp_ast.rb +1378 -0
  54. data/lib/sbuilder/sexp_processor_api.rb +184 -0
  55. data/lib/sbuilder/sexp_processor_canonize.rb +326 -0
  56. data/lib/sbuilder/sexp_processor_dataflow.rb +461 -0
  57. data/lib/sbuilder/sexp_processor_ethereum.rb +127 -0
  58. data/lib/sbuilder/sexp_processor_need_to_canonize.rb +572 -0
  59. data/lib/sbuilder/sexp_processor_snippet.rb +154 -0
  60. data/lib/sbuilder/sexp_processor_symboltable1.rb +296 -0
  61. data/lib/sbuilder/sexp_processor_symboltable2.rb +175 -0
  62. data/lib/sbuilder/sexp_utils.rb +417 -0
  63. data/lib/utils/logger.rb +82 -0
  64. data/lib/utils/string_inject.rb +11 -0
  65. data/sbuilder-ethereum.gemspec +39 -0
  66. metadata +190 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fa3a1818b9e4c6c2f3eb5fcc251320fce12bf664
4
+ data.tar.gz: 4b5e415b5aacf139ae0b495d78df88c0db29f51f
5
+ SHA512:
6
+ metadata.gz: e80192d1a6c95840eed592ead93333e74e4dc8a70d6b505a3257224faf312a0e27ceb7db51d5a0820578099a38bdd1d38ddb742a56f6db3e7dc29a77cea22f9c
7
+ data.tar.gz: 8a9a1faba9367c4048c324448d67e133506c3bc3d9198b05a0683c08838df9afd679c8796154fea1553b25ec357712177289eb4570367cc91893d0c2fd4f1c7b
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.6
@@ -0,0 +1,19 @@
1
+
2
+ module Sbuilder; module Ethereum
3
+
4
+ module DeclRef
5
+
6
+ # @attr [Ast] enclosingScope pointer to scope (sets in SexpProcessorSymbolTable1)
7
+ attr_accessor :enclosingScope
8
+
9
+ # @attr [Ast] declationRef pointer to declartion (set in SexpProcessorSymbolTable2)
10
+ attr_accessor :declationRef
11
+
12
+ # @return [Boolean] true because mixes as declaration reference
13
+ def isDeclarationRef
14
+ true
15
+ end
16
+
17
+ end
18
+
19
+ end; end
@@ -0,0 +1,18 @@
1
+ module Sbuilder
2
+ module Ethereum
3
+
4
+ module DomainRef
5
+
6
+ # @attr [Domain] domainReference
7
+ attr_accessor :domainReference
8
+
9
+ # @return [Boolean] true because mixes as declaration reference
10
+ def isDomainRef
11
+ true
12
+ end
13
+
14
+ end
15
+
16
+
17
+ end
18
+ end
@@ -0,0 +1,92 @@
1
+
2
+ module Sbuilder
3
+ module Ethereum
4
+
5
+ module Scope
6
+ # @attr [Hash] map name to symbol
7
+ attr_reader :symbols
8
+
9
+ # @attr [Sccope] enclosing_scope
10
+ attr_accessor :enclosing_scope
11
+
12
+ #
13
+ # @param [SexpAst] symbol to add to scope
14
+ #
15
+ def define( name, symbol )
16
+ @symbols ||={}
17
+ symbols[name] = symbol
18
+
19
+ end
20
+
21
+ def allSymbols()
22
+ parentSymbols = {}
23
+ if getEnclosingScope
24
+ parentSymbols = getEnclosingScope.allSymbols
25
+ end
26
+ parentSymbols.merge( symbols || {} )
27
+ end
28
+
29
+ ##
30
+ # Return symbol definitions
31
+ def symbolDefinitions
32
+ symbols.values
33
+ end
34
+
35
+ def scopeHiearachy
36
+ hierarchy = [ sexp_type ]
37
+ if getEnclosingScope
38
+ hierarchy += getEnclosingScope.scopeHiearachy
39
+ end
40
+ hierarchy
41
+ end
42
+
43
+ ##
44
+ # Return top most scope
45
+ def globalScope
46
+ return self if getEnclosingScope.nil?
47
+ getEnclosingScope.globalScope
48
+ end
49
+
50
+ def getSymbol( name )
51
+ symbols[name] if symbols && symbols[name]
52
+ end
53
+
54
+ # @param [String] name to resolve
55
+ #
56
+ # @return [Symbol] symbol resolved for the {name}, nil if not found
57
+ def resolve( name )
58
+ ret = getSymbol( name )
59
+ return ret unless ret.nil?
60
+ return getEnclosingScope.resolve( name ) if getEnclosingScope
61
+ nil
62
+ end
63
+
64
+ def resolveOrReportError( name )
65
+ resolved = resolve( name )
66
+ return resolved if resolved
67
+
68
+ raise SbuilderEtherumScopeException, <<-EOS
69
+ Could not resolve '#{name}' on #{self}
70
+
71
+ Scope hierarchy: #{scopeHiearachy.join(',')}
72
+ Known symbols : #{allSymbols.keys().join(',')}
73
+ EOS
74
+
75
+ end
76
+
77
+
78
+ # @return [Scope|nil] scope for enclosing scope, nil for root scope
79
+ def getEnclosingScope
80
+ enclosing_scope
81
+ end
82
+
83
+ # @return [Boolean] true because mixes module scope
84
+ def isScope
85
+ true
86
+ end
87
+
88
+
89
+ end
90
+
91
+ end
92
+ end
@@ -0,0 +1,17 @@
1
+ module Sbuilder
2
+ module Ethereum
3
+
4
+ module Scoped
5
+
6
+ # @attr [Ast] enclosingScope pointer to scope (sets in SexpProcessorSymbolTable1)
7
+ attr_accessor :scopeDefining
8
+
9
+ # @return [Boolean] true because can be scoped
10
+ def isScoped
11
+ true
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Sbuilder
2
+ module Ethereum
3
+ module SymbolRef
4
+ # add a reference to type definition
5
+
6
+ # @attr [TypeSymbol] symbolTypeReference pointer to symbol (sets in SexpProcessorSymbolTable2)
7
+ attr_accessor :symbolTypeReference
8
+
9
+ # @return [Boolean] true because mixes module symbol reference
10
+ def isSymbolRef
11
+ true
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,75 @@
1
+ module Sbuilder
2
+ module Ethereum
3
+
4
+ # Depends on 'scope'
5
+
6
+ module TypeSymbol
7
+ # add a reference to type definition
8
+
9
+ # @attr [TypeSymbol] isA pointer to parent type
10
+ attr_accessor :isA
11
+
12
+ # @attr [TypeSymbol:Array] derivedTypes direct 'derivedTypes'
13
+ # @return [TypeSymbol:Array]
14
+ def derivedTypes
15
+ @derivedTypes || []
16
+ end
17
+
18
+ # @return [Hash] knownTypes all known 'derivedTypes' in
19
+ # derication hierarch
20
+ # @option knownTypes [String] <key >typeName
21
+ # @option knownTypes [Array] <value> array of known types
22
+
23
+ def allDerivedTypes( knownTypes )
24
+ childTypes = []
25
+ knownTypes[typeName] = [self]
26
+ derivedTypes.each do |derivedType|
27
+ # find out knownTypes in 'derivedTypes'
28
+ knownTypes = derivedType.allDerivedTypes( knownTypes )
29
+ # propagete derived types to parent type
30
+ childTypes += knownTypes[derivedType.typeName] unless knownTypes[derivedType.typeName].nil?
31
+ end
32
+
33
+ knownTypes[typeName] += childTypes.uniq
34
+ knownTypes
35
+ end
36
+
37
+ # @return [TypeSymbol|nil] typeSymbol scope for enclosing type,
38
+ # nil for root type. Wrapper to isA
39
+ def getEnclosingType
40
+ isA
41
+ end
42
+
43
+ #
44
+ # @return [TypeSymbol] top element in type hierarchy
45
+ def rootSymbol
46
+ return self if isA.nil?
47
+ isA.rootSymbol
48
+ end
49
+
50
+ # Build type hierarchy bottom up ie. child.inherits( parent )'
51
+ #
52
+ # @param [TypeSymbol] parentExp inherited
53
+ def inherits( parentExp )
54
+ raise "parentExp #{parentExp} is not 'TypeSymbol'" unless parentExp.respond_to?(:isTypeSymbol) && parentExp.isTypeSymbol
55
+ self.isA = parentExp
56
+ # add back pointer in parent to poin to me
57
+ parentExp.addDerivedTypes( self )
58
+ self
59
+ end
60
+
61
+ # Add 'childEntry' to '@derivedTypes', private method
62
+ def addDerivedTypes( childEntry )
63
+ @derivedTypes = [] if @derivedTypes.nil?
64
+ @derivedTypes << childEntry
65
+ end
66
+
67
+
68
+ # @return [Boolean] true because mixes module symbol
69
+ def isTypeSymbol
70
+ true
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,332 @@
1
+ require 'sbuilder'
2
+
3
+ module Sbuilder
4
+ module Ethereum
5
+
6
+ class Plugin < Sbuilder::LoaderPluginRoot
7
+
8
+ extend Forwardable # for easy delegation
9
+
10
+ # mix api loader plugin services
11
+ include ApiLoaderPluginMixer
12
+
13
+ # mix snippet loader plugin services
14
+ include SnippetLoaderPluginMixer
15
+
16
+ # @attr [SexpProcessorTla] tla which has created +interfaces+,
17
+ # +snippets+, +partials+, and +metatypes+
18
+ attr_reader :tla
19
+
20
+ # @attr [GlobalScope] globalScope the one
21
+ attr_reader :globalScope
22
+
23
+ def_delegators :tla,
24
+ # @attr [Interfaces] interfaces created by tla-processor
25
+ :interfaces,
26
+ # @attr [Definitions] definitions created by tla-processor
27
+ :definitions,
28
+ # @attr [Snippets] snippets i.e. TLA generate
29
+ # elements created by tla-processor
30
+ :snippets,
31
+ # @attr [Hash] partials mapping TLA generate element to mustache partial
32
+ :partials,
33
+ # @attr [Hash] metatypes used by TLA generate,
34
+ # key=metatype, value=desciption
35
+ :metatypes,
36
+ # @attr [String:Array] domainNames to create in TLA model
37
+ :domainNames
38
+
39
+ # @attr [Domains] dataFlowDomains
40
+ attr_reader :dataFlowDomains
41
+
42
+ # @attr [Hash] preferences passesed as PREFERENCES property to rendering
43
+ attr_reader :preferences
44
+
45
+ ##
46
+ # Collect domains in 'dataFlowDomains'.
47
+ #
48
+ # @param [Domains] resolvedDomains
49
+ def addDataflowDomains( resolvedDomains )
50
+ if dataFlowDomains.nil?
51
+ # init array
52
+ @dataFlowDomains = resolvedDomains
53
+ else
54
+ # concat arrays
55
+ resolvedDomains.domains.each do |resolvedDomain|
56
+ @dataFlowDomains << resolvedDomain
57
+ end
58
+ end
59
+ @logger.info "#{__method__}: domains=#{dataFlowDomains}"
60
+ end
61
+
62
+
63
+ # @attr [Hash] options set in constructor
64
+ attr_reader :options
65
+
66
+ # ------------------------------------------------------------------
67
+ # @!group Construct && configure
68
+
69
+ def initialize( options = {} )
70
+ super( options )
71
+ @options = options
72
+ logger.info "#{__method__}: plugin created"
73
+ end
74
+
75
+ # Class level configuration
76
+ #
77
+ # @param [Hash] configuration given in 'extend.loaders'
78
+ # @option configuration [String] solc_command path to solc executable
79
+ #
80
+ def self.configure( configuration )
81
+ validateProperties( configuration, Constants::VALIDATION[:class_configure][:required], Constants::VALIDATION[:class_configure][:allowed] )
82
+ @@solc_command = configuration['solc_command'] if configuration.is_a?(Hash ) && configuration.key?( 'solc_command' )
83
+ end
84
+
85
+ # Instance level configuration
86
+ #
87
+ # @param [Hash] configuration for object instance
88
+ def configure( configuration )
89
+ logger.info "#{__method__}: configuration=#{configuration}"
90
+ validateProperties( configuration, Constants::VALIDATION[:configure][:required], Constants::VALIDATION[:configure][:allowed] )
91
+ @preferences = configuration['preferences']
92
+ end
93
+
94
+ ##
95
+ # @return [String] solc_command path to compile executable- if configerd
96
+ def self.solc_command
97
+ @@solc_command if defined?( @@solc_command )
98
+ end
99
+
100
+
101
+
102
+ # @!endgroup
103
+
104
+ # ------------------------------------------------------------------
105
+ # @!group compile & parse solidity
106
+
107
+ ##
108
+ # compile, load, create symbol table, resolve symbols, identify domains,
109
+ # create TLA snippets && infterfaces
110
+ #
111
+
112
+ def processSource( soliditySource )
113
+
114
+ # Compile +soliditySource+ to +astPath+ json file
115
+ compiler = Compile.new( options )
116
+ compiler.output_directory = compileWorkDirectory
117
+ compiler.solc_command = self.class.solc_command
118
+ compiler.compile( soliditySource )
119
+ astPath = compiler.compiledAst
120
+
121
+ # load +astPath+ into SexpAst tree +ast+
122
+ loader = Load.new( options )
123
+
124
+ # Create the unique global scope
125
+ @globalScope = SexpUtils.createGlobalScope
126
+ @logger.debug "#{__method__}: globalScope=#{globalScope}" if @logger.debug?
127
+ # create tla processor, which maps ast to snippets,
128
+ # interfaces, etc. make tla aware of +baseMetatypes+ in
129
+ # 'sbuilder' framework.
130
+
131
+ @tla = SexpProcessorTla.new( facade.baseMetatypes, options )
132
+ # tla.setBaseMetatypes( facade.baseMetatypes )
133
+
134
+ # process global scope - it defines global functions, which should be processed
135
+ processAst( "GlobalScope", globalScope, nil )
136
+
137
+ # process all compile units
138
+
139
+ asts = []
140
+ loader.processAllAsts( astPath ) do |ast, astName |
141
+ processAst( astName, ast, globalScope )
142
+ asts << ast
143
+ end
144
+
145
+ # after all solidity ast's have been preprossesed
146
+ tla.process( globalScope )
147
+ asts.each do |ast|
148
+ # Create +snippets+, +interfaces+, +partials+, +domains+
149
+ tla.process( ast )
150
+ end
151
+
152
+ end
153
+
154
+
155
+ ##
156
+ # Process 'ast' trhough steps: 1) fix.point( canonize ), 2)
157
+ # Create symbol table hierarchy, 3) Resolve refernces using the
158
+ # symbol table, 4) identify data flows, 4) map processed ast to
159
+ # tla-language elements
160
+ #
161
+ # @param [String] compileUnit name of solidity AST
162
+ private def processAst( compileUnit, ast, globalScope )
163
+
164
+ @logger.debug "#{__method__}: ast=#{ast}" if @logger.debug?
165
+
166
+ # preprocess
167
+ needAnalyzer = Sbuilder::Ethereum::SexpProcessorNeedToCanonize.new( options )
168
+ needProcessor = Sbuilder::Ethereum::SexpProcessorCanonize.new( options )
169
+ needProcessor.setCompileUnit( compileUnit )
170
+
171
+ # iterate canonization until fixpoint
172
+ begin
173
+ needAnalyzer.initIt
174
+ needAnalyzer.process( ast )
175
+ needProcessor.setNeeds( needAnalyzer )
176
+ needProcessor.process( ast );
177
+ end while ( needProcessor.somethingCanonized )
178
+
179
+
180
+ # Scope hierarchy for symbol table in +ast+
181
+ symbolTable1 = SexpProcessorSymbolTable1.new( options )
182
+ symbolTable1.globalScope = globalScope
183
+ symbolTable1.process( ast )
184
+
185
+ # Resolve references in +ast+
186
+ symbolTable2 = SexpProcessorSymbolTable2.new( options )
187
+ symbolTable2.process( ast )
188
+
189
+ # Identity dataflow in in +ast+ and produde +domains+
190
+ dataFlow = SexpProcessorDataflow.new( options )
191
+ dataFlow.process( ast )
192
+
193
+ # adds to context accross compile units
194
+ addDataflowDomains( dataFlow.domains )
195
+
196
+ # # Create +snippets+, +interfaces+, +partials+, +domains+
197
+ # tla.process( ast )
198
+
199
+ # @logger.debug "#{__method__}: #{compileUnit} defines-snippets=#{snippets.length}" if @logger.debug?
200
+ # @logger.debug "#{__method__}: interfaces=#{interfaces}" if @logger.debug?
201
+ # @logger.debug "#{__method__}: definitions=#{definitions}" if @logger.debug?
202
+
203
+ end
204
+
205
+ # @!endgroup
206
+
207
+
208
+ # ------------------------------------------------------------------
209
+ # @!group APi loader
210
+
211
+ ##
212
+ # Load API interfaces to sbuilder for solidity source
213
+ #
214
+ # @param [String] soliditySource given in sbuilder.yaml
215
+ #
216
+ def load( soliditySource )
217
+ logger.info "#{__method__} soliditySource=#{soliditySource}"
218
+ # snippets parsed
219
+
220
+ processSource( soliditySource )
221
+
222
+ loadDomains
223
+
224
+ loadApis
225
+
226
+ end
227
+
228
+ ##
229
+ # Load domainNames to sbuilder using via +facade+
230
+ private def loadDomains
231
+ logger.info "#{__method__}: starting"
232
+
233
+ # Load domains idendified during dataflow analysis
234
+ dataFlowDomains.domains.each do |domain|
235
+ logger.info "#{__method__}: dataflow domainName=#{domain.domainName}, values=#{domain.domainValues.join(',')}"
236
+ facade.defineDomain( domain.domainName, domain.domainValues )
237
+ end
238
+
239
+ # Load domains identified during TLA processing
240
+ domainNames.each do |domain|
241
+ logger.info "#{__method__}: TLA app-domainName=#{domain.domainName}, values=#{domain.domainValues.join(',')}"
242
+ facade.defineDomain( domain.domainName, domain.domainValues )
243
+ end
244
+ logger.debug "#{__method__} done" if logger.debug?
245
+ end
246
+
247
+
248
+ ##
249
+ # Ensture that 'getCacheDir'/solidity exists && return this
250
+ # directory as a path. Called in API loader phase --> use facade
251
+ # to access sbuilder context.
252
+ #
253
+ # @return [String] path to compiler wordking directory private
254
+
255
+ def compileWorkDirectory()
256
+
257
+ subDir = "solidity"
258
+
259
+ directoryPath = "#{facade.getCacheDir}/#{subDir}"
260
+
261
+ Dir.mkdir( directoryPath ) unless File.exist?( directoryPath )
262
+ directoryPath
263
+
264
+ end
265
+
266
+ ##
267
+ # Load api configuration to sbuilder using via +facade+.
268
+ private def loadApis
269
+
270
+ # Create loader to process :Interfaces sexps
271
+ apiLoader = SexpProcessorApi.new( options )
272
+ apiLoader.apiFacade = facade
273
+ # InfrastructureService -> support returning 'response'
274
+ facade.configureInfrastructureService( true )
275
+ apiLoader.process( interfaces )
276
+
277
+ apiLoader.process( definitions )
278
+
279
+ end
280
+
281
+ # @return [Boolean] true #load has called #process, which sets +snippets+
282
+ def loadDone
283
+ !tla.nil? && !snippets.nil?
284
+ end
285
+
286
+
287
+ # @!endgroup
288
+
289
+ # ------------------------------------------------------------------
290
+ # @!group Snippet loader
291
+
292
+ ##
293
+ # Register snippets for a solidity contract.
294
+
295
+ # Implemtnation assumes that +process+ method has been called
296
+ # earlier, and uses +snippets+ getter to retrive TLA generate
297
+ # element to load into sbuilder.
298
+ #
299
+ # Overrides abstract method in parent class.
300
+ #
301
+ # @param [Hash:Array] snippetDefitions given in sbuilder.yaml
302
+ #
303
+ # @return [Boolean] true after success
304
+ #
305
+ def doRegisterSnippets( snippetDefitions )
306
+ logger.info "#{__method__}: snippetDefitions=#{snippetDefitions}"
307
+ raise SbuilderEtherumPluginException, "Should call #load before calling ##{__method__}" unless loadDone
308
+ logger.debug "#{__method__}: snippets-dump=#{snippets}" if logger.debug?
309
+ logger.info "#{__method__}: snippets=#{snippets.return_nodes_with_type(:Snippet).map {|s| s.metatype.to_s + '/' + s.appName.to_s}.join(',')}"
310
+
311
+ # Create renderer i.e. an object to convert TLA generate
312
+ # element to TLA language snippets by using mustache partial
313
+ renderer = Render.new( options )
314
+ renderer.setPreferences( preferences )
315
+ renderer.setPartials( partials )
316
+
317
+ # Create && configure snippet loader to process ':Snippets' sexps
318
+ snippetLoader = SexpProcessorSnippet.new( options )
319
+ snippetLoader.setSnippetFacade( snippetFacade )
320
+ snippetLoader.setRenderer( renderer )
321
+ snippetLoader.setMetatypes( metatypes )
322
+ snippetLoader.process( snippets )
323
+
324
+ true
325
+ end
326
+
327
+ # @!endgroup
328
+
329
+
330
+ end # class Plugin < Sbuilder::SnippetLoaderPlugin
331
+ end
332
+ end