sbuilder-ethereum 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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