sbuilder-eth 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,30 @@
1
+ module Sbuilder
2
+ module Eth
3
+
4
+ ##
5
+ # Mixer module to AST nodes, which need to be resolved for a
6
+ # {#reference} to a {#Sbuilder::Eth::Scoped} symbol
7
+ module Reference
8
+
9
+ # @!attribute enclosingScope [Scope] a pointer to scope which
10
+ # knows how to resolve {#reference}
11
+ attr_accessor :enclosingScope
12
+
13
+ # @!attribute reference [Scoped] a (resolved) pointer to
14
+ # {#Scoped} symbol declaration
15
+ attr_writer :reference
16
+
17
+ def reference
18
+ raise "Reference not resolved for #{self}" if @reference.nil?
19
+ @reference
20
+ end
21
+
22
+
23
+ # @return [Boolean] true because mixes as reference
24
+ def isReference
25
+ true
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,100 @@
1
+ module Sbuilder
2
+ module Eth
3
+ ##
4
+ # Mixer module to be included to AST nodes, which scope symbols
5
+ module Scope
6
+
7
+ # @!attribute [Hash<Symbol:AstSexp>] symbols
8
+ def symbols
9
+ @symbols || {}
10
+ end
11
+
12
+ # @attribute [Sccope] enclosingScope
13
+ attr_accessor :enclosingScope
14
+
15
+ # @param name [String,Symbol] identifier to assign to 'astSexp'
16
+ # @param astSexp [AstSexp] AST node to associate with name
17
+ def define(name, astSexp)
18
+ @symbols ||= {}
19
+ @symbols[name] = astSexp
20
+
21
+ # Add back reference
22
+ astSexp.scopeDefining = self
23
+ end
24
+
25
+ # def resolve( name )
26
+ # ret
27
+ # end
28
+
29
+ def scopeHiearachy
30
+ # assume to be included sto AstSexp implementing 'sexp_type'
31
+ hierarchy = [ sexp_type ]
32
+ if enclosingScope
33
+ hierarchy += enclosingScope.scopeHiearachy
34
+ end
35
+ hierarchy
36
+ end
37
+
38
+ ##
39
+ # @return [Scope] topmost scope
40
+ def globalScope
41
+ return self if enclosingScope.nil?
42
+ enclosingScope.globalScope
43
+ end
44
+
45
+ def allSymbols()
46
+ parentSymbols = {}
47
+ if enclosingScope
48
+ parentSymbols = enclosingScope.allSymbols
49
+ end
50
+ parentSymbols.merge( symbols )
51
+ end
52
+
53
+ def getSymbol( name )
54
+ symbols[name] if symbols && symbols[name]
55
+ end
56
+
57
+ # @param [String] name to resolve
58
+ #
59
+ # @param errorReport [Boolean] true for raising error if not
60
+ # found
61
+ #
62
+ # @return [Symbol] symbol resolved for the 'name', nil if not
63
+ # found
64
+ def resolve( name, errorReport=true )
65
+ ret = getSymbol( name )
66
+ return ret unless ret.nil?
67
+ ret = enclosingScope.resolve( name, false ) if enclosingScope
68
+ return ret unless ret.nil?
69
+
70
+ raise ScopeException, <<-EOS if errorReport
71
+ Could not resolve '#{name}' on #{self}
72
+
73
+ Scope hierarchy: #{scopeHiearachy.join(',')}
74
+ Known symbols : #{allSymbols.keys().join(',')}
75
+ EOS
76
+ # it is nil
77
+ ret
78
+ end
79
+
80
+ # def resolveOrReportError( name )
81
+ # resolved = resolve( name )
82
+ # return resolved if resolved
83
+
84
+ # raise SbuilderEtherumScopeException, <<-EOS
85
+ # Could not resolve '#{name}' on #{self}
86
+
87
+ # Scope hierarchy: #{scopeHiearachy.join(',')}
88
+ # Known symbols : #{allSymbols.keys().join(',')}
89
+ # EOS
90
+
91
+ # end
92
+
93
+
94
+ # @return [Boolean] true because mixes module scope
95
+ def isScope
96
+ true
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,18 @@
1
+ module Sbuilder
2
+ module Eth
3
+ ##
4
+ # Mixer module to be included to AST nodes acting as symbols which
5
+ # can be refenced to.
6
+ module Scoped
7
+
8
+ # @!attribute [AstSexp:Scope] back pointer to scope defininign this symbol
9
+ attr_accessor :scopeDefining
10
+
11
+ # @return [Boolean] true because can be scoped
12
+ def isScoped
13
+ true
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,267 @@
1
+ module Sbuilder
2
+ module Eth
3
+ module Plugin
4
+
5
+ # Controller for Loading Ethreum application to sbuilder.
6
+ #
7
+ # Plugin calls {#initApplication} method, which creates an array
8
+ # of AlObject and passes these objects controller parent using
9
+ # method {Sbuilder::Al::Plugin::Controller#addAlObjects}.
10
+ #
11
+ #
12
+
13
+
14
+ class Controller < Sbuilder::Al::Plugin::Controller
15
+
16
+
17
+ # ------------------------------------------------------------------
18
+ # @!group Attributes
19
+
20
+
21
+ # @!attribute [Hash] options command line configurations
22
+ attr_accessor :options
23
+
24
+ # @!attribute [Sbuilder::Eth::SolidityCompiler] compiler
25
+ attr_accessor :compiler
26
+
27
+ # @!attribute [Sbuilder::Eth::SolidityLoader] loader
28
+ attr_accessor :loader
29
+
30
+ # @!attribute [Sbuilder::Eth::SolidityT] eth_translator
31
+ attr_accessor :eth_translator
32
+
33
+ # @!attribute [SexpProcessorScope] scope
34
+ attr_accessor :scope
35
+
36
+ # @!attribute [SexpProcessorResolve] resolve
37
+ attr_accessor :resolve
38
+
39
+ # @!attribute ethRuntimeReturned allows 'ethRuntime' to execute only once
40
+ @@ethRuntimeReturned = false
41
+
42
+ # @!attribute contractClasses [Array<String>] names of classes
43
+ # parsed
44
+ @@contractClasses = []
45
+
46
+
47
+ # @!endgroup
48
+
49
+ # ------------------------------------------------------------------
50
+ # @!group Constructor & initialization
51
+
52
+ def initialize( options = {} )
53
+ super( options )
54
+ self.options = options
55
+ @logger = getLogger( "EthController", options )
56
+ @logger.info( "#{__method__}: init eth.controller")
57
+ # initApi
58
+ end
59
+
60
+ # Create tools in toolchain
61
+ #
62
+ # # @param configuration [Hash] configugration yaml from sbuilder.yaml
63
+ def initInputProcessingPipe( configuration )
64
+ @logger.info( "#{__method__}: configuration=#{configuration}")
65
+
66
+ self.loader = Sbuilder::Eth::SolidityLoader.new( options )
67
+
68
+ self.compiler = Sbuilder::Eth::SolidityCompiler.new( options )
69
+ compiler.solc_command =configuration['compiler']['solc_command'] if configuration && configuration['compiler'] && configuration['compiler']['solc_command']
70
+ compiler.solc_flags =configuration['compiler']['solc_flags'] if configuration && configuration['compiler'] && configuration['compiler']['solc_flags']
71
+ compiler.output_directory =configuration['compiler']['output_directory'] if configuration && configuration['compiler'] && configuration['compiler']['output_directory']
72
+
73
+ self.scope = Sbuilder::Eth::SexpProcessorScope.new( options )
74
+
75
+ self.resolve = Sbuilder::Eth::SexpProcessorResolve.new( options )
76
+
77
+ self.eth_translator = Sbuilder::Eth::SolidityTranslator.new( options )
78
+
79
+ end
80
+
81
+ # @!endgroup
82
+
83
+ # ------------------------------------------------------------------
84
+ # @!group Class services
85
+
86
+
87
+ # Load inputs as AlObjects to an application array (managed in
88
+ # super class)
89
+ #
90
+ # Method in Sbuilder::Al::Plugin::Controller overridden.
91
+ #
92
+ # @param configuration [Hash] hash with properites
93
+ #
94
+ # @option configuration [String|Array<String>] 'input' path to
95
+ # input files to load.
96
+ #
97
+ def initApplication( configuration )
98
+ @logger.info( "#{__method__}: configuration=#{configuration}")
99
+
100
+
101
+ warn "No 'input' property in #{configuration} - nothing loaded" if configuration['input'].nil?
102
+
103
+ # Create clean state for processing
104
+ initInputProcessingPipe( configuration )
105
+
106
+ # add metatype definitions (used by alObjects below) to
107
+ # parent controller state
108
+ metaDefs = processMetatypes
109
+ addMetatypes( metaDefs )
110
+
111
+ # add AL (application language) objects to parent controller
112
+ alObjects = processInputs( configuration['input'] )
113
+ addAlObjects( alObjects )
114
+
115
+ end # initApplication
116
+
117
+ # Add runtime AL-objects for translation.
118
+ #
119
+ # This method called when all sbuilder plugins have had their
120
+ # {#initApplication} called, and next phase in sbuilder
121
+ # loading starts. In out case we'll add runtime AL objects
122
+ # (only once)
123
+ #
124
+
125
+ def initApplicationFinalize
126
+
127
+ # run only once (also for many instances!)
128
+ return if @@ethRuntimeReturned
129
+
130
+ alObject = []
131
+ # Create alObjects - if any alObjects created
132
+ alObjects = eth_translator.solidityRuntime( @@contractClasses ) unless eth_translator.nil?
133
+ addAlObjects( alObjects )
134
+
135
+ @@ethRuntimeReturned = true
136
+
137
+ end
138
+
139
+
140
+ # @!endgroup
141
+
142
+ # ------------------------------------------------------------------
143
+ # @!group Class implementation
144
+
145
+ # Implementation 1) compiles solidity source file pointed by
146
+ # configuration['input'], 2) loads AST files created in
147
+ # compilation step 3) translates AST structures to AlObjects,
148
+ # 4) passes AlObjects to application using method
149
+ # {Sbuilder::Al::Plugin::Controller#addAlObjects}.
150
+ #
151
+ # @param inputs [String, Array<String>] file names to load
152
+ def processInputs( inputs )
153
+ inputs = inputs || []
154
+ inputs = [inputs] unless inputs.is_a?(Array)
155
+ @logger.info "#{__method__}: inputs=#{inputs.join(',')}"
156
+
157
+ alObjects =
158
+ # # runtime objects
159
+ # eth_translator.solidityTranslate( nil ) +
160
+
161
+ # objects compiled for input files
162
+ inputs.map do |inputFile|
163
+
164
+ # compiles & returns name of AST fie
165
+ compiler.compile(inputFile)
166
+
167
+ end.reduce( []) do |memo, astFile|
168
+
169
+ # 1 AST file = N ASTs
170
+ @logger.info "#{__method__}: astFile=#{astFile}"
171
+ loader.load( astFile ) do |solSource, index, ast|
172
+ # loaded one 'ast' from 'astFile'
173
+ memo << {
174
+ :ast => ast,
175
+ :solSource => solSource
176
+ }
177
+ end
178
+ memo
179
+ end.
180
+ map do |astDef|
181
+ ast = astDef[:ast]
182
+
183
+ # ensure getters for public membar variables
184
+ SexpProcessorGetter.new(options).process( ast )
185
+
186
+ astDef
187
+ end.
188
+ map do |astDef|
189
+ ast = astDef[:ast]
190
+
191
+ # find scope of declations && resolve identifiers
192
+ scope.process( ast )
193
+ resolve.process( ast )
194
+
195
+ astDef
196
+
197
+ end.
198
+ map do |astDef|
199
+ ast = astDef[:ast]
200
+
201
+ # sepate function call from expressions
202
+ SexpProcessorCallSeparator.new(options).process( ast )
203
+
204
+ astDef
205
+ end.
206
+ reduce( [] ) do |memo, astDef|
207
+ ast = astDef[:ast]
208
+ # translate one AST at a time + memoize alObjects
209
+ outputMsg( astDef[:solSource] )
210
+ memo += eth_translator.solidityTranslate( ast, astDef[:solSource] ) do |contractClass|
211
+ outputMsg( " - #{astDef[:solSource]} : processing class #{contractClass}" )
212
+ # Collect class names into an array
213
+ addContractClass(contractClass)
214
+ end
215
+ memo
216
+ end
217
+
218
+ @logger.info( "#{__method__}: alObjects.length=#{alObjects.length}")
219
+ @logger.debug( "#{__method__}: alObjects=#{alObjects}") if @logger.debug?
220
+ # @logger.info( "#{__method__}: alObjects=#{alObjects.map { |alO| alO[:type] }.join(',')}")
221
+
222
+ # pass alObjects to application array
223
+ alObjects
224
+
225
+ end
226
+
227
+ # @return [Hash] metaDefs (metatype definition used in
228
+ # application)
229
+ def processMetatypes
230
+ eth_translator.metaDefs
231
+ end
232
+
233
+ # @!endgroup
234
+
235
+ # ------------------------------------------------------------------
236
+ # @!group Helpers
237
+
238
+
239
+ # @param soliditySource [String] name solidity file processed
240
+ def outputMsg(soliditySource)
241
+ msg =" - Solidity translation: #{soliditySource}"
242
+ @logger.info( msg )
243
+ puts msg
244
+ end
245
+
246
+
247
+ # @!endgroup
248
+
249
+ # ------------------------------------------------------------------
250
+ # @!group Helpers
251
+
252
+ def addContractClass(className)
253
+ @@contractClasses << className
254
+ end
255
+
256
+
257
+ # @!endgroup
258
+
259
+
260
+
261
+ end # class Controller < Sbuilder::Al::Plugin::Controller
262
+
263
+ end
264
+
265
+
266
+ end
267
+ end
@@ -0,0 +1,3 @@
1
+ require_relative "controller"
2
+ require_relative "plugin"
3
+
@@ -0,0 +1,33 @@
1
+ require "sbuilder"
2
+
3
+ module Sbuilder
4
+
5
+ module Eth
6
+
7
+ module Plugin
8
+
9
+
10
+ # Extent Sbuilder::Al::Plugin::Plugin class. The only
11
+ # modification being to replace default plugin.controller
12
+ # Sbuilder::Al::Plugin::Controller with
13
+ # Sbuilder::Eth::Controller.
14
+ class Plugin < Sbuilder::Al::Plugin::Plugin
15
+
16
+ def initialize( options={} )
17
+ @logger = getLogger( "EthPlugin", options )
18
+ @logger.info( "#{__method__} sbuilder-eth plugin initialized" )
19
+ super( options )
20
+ # replace controller
21
+ self.controller = Sbuilder::Eth::Plugin::Controller.new( options )
22
+ end
23
+
24
+ # @return [String] version from VERSION
25
+ def self.version
26
+ File.read( File.join( File.dirname( __FILE__), "../..", "VERSION"))
27
+ end
28
+
29
+ end
30
+ end
31
+
32
+ end
33
+ end