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,119 @@
1
+ require 'json'
2
+
3
+
4
+ module Sbuilder
5
+ module Ethereum
6
+
7
+
8
+ class Load
9
+
10
+ PROGNAME = nil # progname for logger default class name
11
+ include MyLogger # mix logger
12
+
13
+
14
+ def initialize( options = {} )
15
+
16
+ @options = options
17
+ @logger = getLogger( nil, options )
18
+ @logger.info "#{__method__}: initalized"
19
+
20
+
21
+ end
22
+
23
+
24
+ # ------------------------------------------------------------------
25
+ # @!group Access solc AST for solidity source
26
+
27
+ # @param [String] solcAstPath path JSON file containing solc
28
+ # combined-AST
29
+ #
30
+ # @yield [SexpAst, compileUnit] ast process, string identifying
31
+ # ast (source+counter)
32
+ #
33
+ def processAllAsts( solcAstPath )
34
+ @logger.info "#{__method__}: solcAstPath=#{solcAstPath}"
35
+ solcHash = solc_input( solcAstPath )
36
+
37
+ solcHash['sourceList'].each do |solSource|
38
+ hashes = solcHash['sources'][solSource]['AST']
39
+ @logger.debug "#{__method__}: hash.keys=#{hashes.keys}" if @logger.debug?
40
+ hashes["children"].each_with_index do |ast,indx|
41
+ astName = "#{solSource}-#{indx}"
42
+ sourceUnit = SourceUnit.define( astName, SexpAst.build_sexp(ast) )
43
+ yield sourceUnit, astName
44
+ end
45
+ end
46
+ end
47
+
48
+
49
+ # Read solidyty source in +solcAstPath+, and
50
+ #
51
+ # @param [String] solcAstPath path JSON file containing solc
52
+ # combined-AST
53
+ #
54
+ # @param [Integer] index to contract to compile
55
+ #
56
+ # @return [SexpAst] sexp ast for solc json AST in {solc_hash},
57
+ # nil
58
+ def load_solc_ast_as_sexp( solcAstPath, index=0 )
59
+
60
+ @logger.info "#{__method__}: solcAstPath=#{solcAstPath}"
61
+ # read result of solc compiler
62
+ solcHash = solc_input( solcAstPath )
63
+ @logger.debug "#{__method__}: solcHash=#{solcHash.to_yaml}" if @logger.debug?
64
+
65
+ # extract AST from the result of solc compiler
66
+ solcSexpAst = solc_ast( solcHash, index )
67
+
68
+ solcSexpAst
69
+
70
+ end
71
+
72
+
73
+ #
74
+ # @param [String] solcAstPath path to solidity source file
75
+ #
76
+ # @return [hash] cached '@solcHash' parsed from JSON file in
77
+ # {solcAstPath} containing the AST from solc compilation
78
+ def solc_input( solcAstPath )
79
+ return @solcHash unless @solcHash.nil?
80
+ str = readSolc( solcAstPath )
81
+ @solcHash = JSON.parse( str )
82
+ end
83
+
84
+ # Read AST JSON string created by solc compiler for compiling
85
+ # solidity source in file {solcAstPath}.
86
+ #
87
+ # @param [String] solcAstPath path to solidity source
88
+ #
89
+ # @return [String] solc AST JSON in a string
90
+ def readSolc( solcAstPath )
91
+ File.read( solcAstPath )
92
+ end
93
+
94
+ # Create Sexp AST tree for +index+-th compile unit in solc AST
95
+ # in +solc_hash+
96
+ #
97
+ # @param [Hash] solcHash JSON hash created by solc compiler
98
+ #
99
+ # @option solcHash [sources.<file>.AST]
100
+ #
101
+ # @return [SexpAst] sexp ast for solc json AST in +solc_hash+,
102
+ # nil if +index+ exceeds number of sources in the +solcHash+.
103
+ def solc_ast( solcHash, index=0 )
104
+ return nil if solcHash['sourceList'].length <= index
105
+ solSource = solcHash['sourceList'][index]
106
+ @logger.info "#{__method__}: index:#{index}, solSource=#{solSource}"
107
+ # extract AST part from solcHash for {solSource}
108
+ hash = solcHash['sources'][solSource]['AST']
109
+ # converst hash to sexp AST tree
110
+ SexpAst.build_sexp( hash )
111
+ end
112
+
113
+ # @!endgroup
114
+
115
+
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,152 @@
1
+ require 'mustache'
2
+
3
+
4
+ # ------------------------------------------------------------------
5
+ # Hack mustache to allow change default otag '{{' ctag '}}'
6
+
7
+ class Mustache
8
+
9
+
10
+ # Open mustache to define class accessors 'otag' and 'ctag'
11
+ def self.otag=( o )
12
+ @@otag = o
13
+ end
14
+ def self.ctag=( c )
15
+ @@ctag = c
16
+ end
17
+ def self.otag
18
+ @@otag ||= '{{'
19
+ end
20
+ def self.ctag
21
+ @@ctag ||= '}}'
22
+ end
23
+
24
+
25
+ class Template
26
+
27
+ # Open template to set otag/ctag on parser.
28
+ #
29
+ # Returns an array of tokens for a given template.
30
+ #
31
+ # @return [Array] Array of tokens.
32
+ #
33
+ def tokens(src = @source)
34
+ p = Parser.new
35
+ p.otag = Mustache.otag
36
+ p.ctag = Mustache.ctag
37
+ p.compile(src)
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ module Sbuilder
44
+ module Ethereum
45
+
46
+ class Renderer < Mustache
47
+
48
+ # @attr [Logger] loger
49
+ attr_reader :logger
50
+ PROGNAME = nil # progname for logger default class name
51
+ include MyLogger # mix logger
52
+
53
+
54
+ # @attr [String:Array] partials must be set before +to_str+
55
+ attr_accessor :partials
56
+
57
+ # @attr [Hash] preferences modify mustache rendering (debug?)
58
+ attr_reader :preferences
59
+
60
+ def initialize( options={} )
61
+ # exception raise if accessing unknown property
62
+ self.raise_on_context_miss = true
63
+
64
+ @options = options
65
+ @logger = getLogger( nil, options )
66
+ @logger.info "#{__method__}: starting options=#{options}"
67
+
68
+ end
69
+
70
+ def setPreferences( preferences )
71
+ @preferences = preferences
72
+ @logger.info "#{__method__}: preferences=#{preferences}"
73
+ end
74
+
75
+ # Use 'to_str' instead of 'render' to use non-default otag/ctag's
76
+ def to_str( template, data=nil )
77
+ Mustache.otag = '{|'
78
+ Mustache.ctag = '|}'
79
+
80
+ begin
81
+ ret = render( template, data )
82
+ ensure
83
+ # restore default otag/ctag
84
+ Mustache.otag = '{{'
85
+ Mustache.ctag = '}}'
86
+ end
87
+ ret
88
+ end
89
+
90
+ # Render conxtext.current[key].
91
+
92
+ # @param [String, '.'] key to render, '.' means current context,
93
+ # string lookup key in current context
94
+ def EVAL( key )
95
+
96
+ logger.info "#{__method__}: key='#{key}', context.current=#{context.current}" if logger.debug?
97
+
98
+ # find generate sexp( :sym, data ) to render
99
+ if key == '.'
100
+ sexp = context.current
101
+ else
102
+ # to evaluate
103
+ hash = context.current.is_a?( Array ) ? context.current[1] : context.current
104
+ sexp = hash[key] || hash[key.to_sym]
105
+ raise SbuilderEtherumMustacheException, "No such key #{key}:#{key.class} found in #{hash}" if sexp.nil?
106
+ end
107
+
108
+ sexp_type = sexp[0]
109
+ data = sexp[1]
110
+ logger.debug "#{__method__}: key=#{key}, sexp_type=#{sexp_type}" if logger.debug?
111
+
112
+
113
+ # find correct template
114
+ template = partials[sexp_type]
115
+ raise SbuilderEtherumMustacheException, <<-EOS if template.nil?
116
+ Unknown partial for sexp_type '#{sexp_type}'
117
+
118
+ Known partials: #{partials.keys.join(',')}"
119
+ Conxt = #{context.current}
120
+ EOS
121
+
122
+ logger.debug "#{__method__}: template=#{template}, data=#{data}" if logger.debug?
123
+ return render( template, data )
124
+
125
+ end
126
+
127
+
128
+ # # partials are constant strings, partial to use is defined in
129
+ # # SexpAst#sexp_type in context stack
130
+ # def partial( partial )
131
+
132
+
133
+ # logger.debug "#{__method__}: partial=#{partial}, sex_type=#{context.current.respond_to?(:sexp_type)}, context.current=#{context.current}, context.current.class=#{context.current.class}" if logger.debug?
134
+
135
+ # raise "TOOD remove"
136
+
137
+ # partial = context.current.sexp_type if context.current.respond_to?( :sexp_type )
138
+ # partial_str = partials[partial]
139
+ # logger.debug "#{__method__}: using partial =#{partial}"
140
+
141
+
142
+ # raise SbuilderEtherumMustacheException.new "Unknown partial '#{partial}'" if partial_str.nil?
143
+
144
+ # return partial_str
145
+ # end
146
+
147
+
148
+
149
+ end
150
+
151
+ end
152
+ end
@@ -0,0 +1,141 @@
1
+
2
+ require 'json'
3
+
4
+ module Sbuilder
5
+ module Ethereum
6
+
7
+ class Render
8
+
9
+
10
+ # SNIPPET_ROOT = <<-EOS
11
+ # {|>__partial_root__|}
12
+ # EOS
13
+
14
+
15
+ # @attr [Logger] logger
16
+ attr_reader :logger
17
+ PROGNAME = nil # progname for logger default class name
18
+ include MyLogger # mix logger
19
+
20
+ # @attr [Hash] options
21
+ attr_reader :options
22
+
23
+ # @attr [Hash] partials mapping used to find starting point for Snippets
24
+ attr_reader :partials
25
+
26
+ # # @attr [Renderer] renderer mustache template generator
27
+ # attr_reader :renderer
28
+
29
+ # @attr [Hash] preferences passesed as PREFERENCES property to rendering
30
+ attr_reader :preferences
31
+
32
+ # ------------------------------------------------------------------
33
+ # @!group Construct && configure
34
+
35
+ def initialize( options={} )
36
+ @options = options
37
+ @logger = getLogger( PROGNAME, options )
38
+ setPreferences( Constants::DEFAULT_PREFERENCES )
39
+ end
40
+
41
+ ##
42
+ # Configure partials used to render snippets
43
+ def setPartials( partials )
44
+ # used later to find starting point for a snippet
45
+ @partials = partials
46
+ end
47
+
48
+ ##
49
+ # Configure 'PREFERENCES' property passed to rendering
50
+ def setPreferences( preferences )
51
+ @preferences = Constants::DEFAULT_PREFERENCES.merge( preferences || {} )
52
+ end
53
+
54
+ def getRenderer
55
+ return @renderer unless @renderer.nil?
56
+ # create mustache renderer && configure it
57
+ @renderer = Renderer.new( options )
58
+
59
+ # Pass a hash mapping TLA generate element sexp_type to mustache
60
+ # templates used to generate TLA code for TLA generate element
61
+ # sexp to the object responsible the generation.
62
+ @renderer.partials = partials
63
+ @renderer.setPreferences( preferences )
64
+ @renderer
65
+
66
+ end
67
+
68
+ # @!endgroup
69
+
70
+ # ------------------------------------------------------------------
71
+ # @!group Iterater, render yield result
72
+
73
+ ##
74
+ # Uses +renderer+ to render +snippet+ to +body+ string in TLA language
75
+ #
76
+ # @param [Snippet] snippet ie. TLA generate (data) element
77
+ #
78
+ # @yield [metatype,appName,body]
79
+ # @yieldparam [String] metatype of the snippet
80
+ # @yieldparam [String] appName in application domain
81
+ # @yieldparam [String] body snippet content
82
+ #
83
+
84
+ def renderSnippet( snippet, &blk )
85
+
86
+ # logger.info "#{__method__}: snippet=#{snippet[0]}-#{snippet[0]}"
87
+ logger.debug "#{__method__}: snippet=#{snippet}" if logger.debug?
88
+
89
+ # use +snippet.sext_type+ to look up template in +partials+
90
+ partial = snippet.sexp_type
91
+ template = getRenderer.partials[partial]
92
+ logger.debug "#{__method__}, partial=#{partial}, template #{template}" if logger.debug?
93
+
94
+ raise SbuilderEtherumMustacheException.new, "Unknown partial '#{partial}', known partials: #{getRenderer.partials.keys.join(',')}" if template.nil?
95
+
96
+ # Typicall snippet renders a body, however it is also possible to
97
+ # create a mapping from appName to specName in some matatype
98
+ # without defining body. (Which may be laoded later for that
99
+ # specName)
100
+ #
101
+ snippet_str = getRenderer.to_str( template, snippet ) if snippet.snippet && snippet.snippet.any?
102
+ logger.debug "#{__method__}, metatype=#{snippet.metatype}, appName=#{snippet.appName}) snippet_str='#{snippet_str}'" if logger.debug?
103
+
104
+ # yield result to block
105
+ logger.debug "#{__method__}, yield metatype=#{snippet.metatype}, appName=#{snippet.appName}) body=#{snippet_str ? snippet_str[1..20] : 'no body'}" if logger.debug?
106
+ yield snippet.metatype, snippet.appName, snippet_str if block_given?
107
+
108
+ end
109
+
110
+
111
+ # iterate, render, and yield result.
112
+ #
113
+ #
114
+ # @return [Integer] number of snippets rendered
115
+
116
+ def render( snippets, &blk )
117
+
118
+ logger.info "#{__method__}, start snippets=#{snippets}"
119
+ raise "Should have used #setPartials before #render" if partials.nil?
120
+
121
+
122
+ # init counter
123
+ rendered = 0
124
+ snippets.sexp_body.each do |snippet|
125
+
126
+ renderSnippet( snippet, &blk )
127
+
128
+ rendered += 1
129
+ end
130
+ rendered
131
+
132
+ end
133
+
134
+ # @!endgroup
135
+
136
+ # Render +snippet+ to string
137
+
138
+ end
139
+
140
+ end
141
+ end
@@ -0,0 +1,21 @@
1
+ module Sbuilder
2
+ module Ethereum
3
+
4
+ # Helper method to build s-expressions
5
+
6
+ # def s(type, *children)
7
+ # Ast.new(type, children)
8
+ # end
9
+
10
+ def self.s(*args)
11
+ Sbuilder::Ethereum::SexpAst.new(*args)
12
+ end
13
+
14
+
15
+ end
16
+ end
17
+
18
+ # Override sexp_processos s
19
+ def s( *args )
20
+ Sbuilder::Ethereum::s( *args )
21
+ end
@@ -0,0 +1,1378 @@
1
+ # coding: utf-8
2
+
3
+ require 'sexp_processor'
4
+
5
+ module Sbuilder
6
+ module Ethereum
7
+
8
+
9
+ # ------------------------------------------------------------------
10
+ # @!group Common root for Sbuilder
11
+
12
+ # Common root
13
+
14
+ class SexpSbuilder < Sexp
15
+
16
+ # Create a new Sexp containing +args+.
17
+ def initialize(*args)
18
+ super(*args)
19
+ end
20
+
21
+ # @return [Ast:Array] sexpAst nodes with +type+
22
+ # def return_nodes_with_type( type )
23
+ # sexpAstArray = s() # []
24
+ # deep_each { |n|
25
+ # sexpAstArray << n if n.sexp_type == type
26
+ # }
27
+ # sexpAstArray
28
+ # end
29
+ def return_nodes_with_type( type )
30
+ return_nodes_with_match { |n|
31
+ n.sexp_type == type
32
+ }
33
+ end
34
+
35
+
36
+ def return_nodes_with_match( &blk )
37
+ sexpAstArray = s() # []
38
+ deep_each { |n|
39
+ sexpAstArray << n if blk[n]
40
+ }
41
+ sexpAstArray
42
+ end
43
+
44
+
45
+ # alias-method to return nodes with type
46
+ def t( type )
47
+ return_nodes_with_type( type ).first[1..-1]
48
+ end
49
+
50
+ # Restore behaviour missing methods
51
+ def method_missing meth, delete = false
52
+ raise "Unknwon method '#{meth}' called on #{self}"
53
+ end
54
+
55
+ end
56
+ # @!endgroup
57
+
58
+
59
+ # ------------------------------------------------------------------
60
+ # @!group Node in AST
61
+
62
+
63
+ class SexpAst < SexpSbuilder
64
+
65
+ # @əttr [String] src source definition e.g. 0:106:1
66
+ attr_accessor :src
67
+
68
+ # @əttr [String] id as given by solc compiler
69
+ attr_accessor :id
70
+
71
+ # @attr [SexpAst] parent pointer to parent SexpAst
72
+ attr_accessor :parent
73
+
74
+
75
+ # Create a new Sexp containing +args+.
76
+ def initialize(*args)
77
+ super(*args)
78
+ end
79
+
80
+ def setParent( parent )
81
+ @parent = parent
82
+ end
83
+
84
+
85
+ # ------------------------------------------------------------------
86
+ # Build ast
87
+
88
+ # Create ast sexp tree from {json}.
89
+ #
90
+ # @param [Json] json to load as sexp
91
+ #
92
+ # @param [Interger] id generate unique identifier for each AST node
93
+ #
94
+ def self.build_sexp( json )
95
+
96
+ raise SexpException.new "Nil input" if json.nil?
97
+ raise SexpException.new "Missing name property in '#{json}'" if json['name'].nil?
98
+
99
+ # create sexp Node based on json['name']
100
+ result = new_node( json )
101
+
102
+ # add common content for all node types
103
+ result.src = json['src']
104
+ result.id = json['id']
105
+
106
+ # add children & create back pointer
107
+ json['children'] && json['children'].each do |x|
108
+ chld = self.build_sexp(x )
109
+ chld.setParent( result )
110
+ result << chld
111
+ end
112
+
113
+ result
114
+
115
+ end
116
+
117
+ def self.new_node( json )
118
+
119
+ # map solc node type to SexpClass. This guarantees that we know
120
+ # each node type. Sexp classes know also attributes, which solc
121
+ # json defines.
122
+ node2class = {
123
+ :Identifier => Sbuilder::Ethereum::Identifier,
124
+ :PragmaDirective => Sbuilder::Ethereum::PragmaDirective,
125
+ :BinaryOperation => Sbuilder::Ethereum::BinaryOperation,
126
+ :Literal => Sbuilder::Ethereum::Literal,
127
+ :SourceUnit => Sbuilder::Ethereum::SourceUnit,
128
+ :ContractDefinition => Sbuilder::Ethereum::ContractDefinition,
129
+ :FunctionDefinition => Sbuilder::Ethereum::FunctionDefinition,
130
+ :ParameterList => Sbuilder::Ethereum::ParameterList,
131
+ :VariableDeclaration => Sbuilder::Ethereum::VariableDeclaration,
132
+ :ElementaryTypeName => Sbuilder::Ethereum::ElementaryTypeName,
133
+ :Mapping => Sbuilder::Ethereum::Mapping,
134
+ :IndexAccess => Sbuilder::Ethereum::IndexAccess,
135
+ :VariableDefinitionStatement =>Sbuilder::Ethereum::VariableDefinitionStatement,
136
+ :Block => Sbuilder::Ethereum::Block,
137
+ :Return => Sbuilder::Ethereum::Return,
138
+ :ExpressionStatement => Sbuilder::Ethereum::ExpressionStatement,
139
+ :Assignment => Sbuilder::Ethereum::Assignment,
140
+ :MemberAccess => Sbuilder::Ethereum::MemberAccess,
141
+ :FunctionCall => Sbuilder::Ethereum::FunctionCall,
142
+ :NewExpression => Sbuilder::Ethereum::NewExpression,
143
+ :UserDefinedTypeName => Sbuilder::Ethereum::UserDefinedTypeName,
144
+ :Throw => Sbuilder::Ethereum::Throw,
145
+ :Domain => Sbuilder::Ethereum::Domain,
146
+ :IfStatement => Sbuilder::Ethereum::IfStatement,
147
+ :UnaryOperation => Sbuilder::Ethereum::UnaryOperation,
148
+ }
149
+
150
+ nodeType = json['name'].is_a?( String ) ? json['name'].to_sym : json['name']
151
+ klass = node2class[nodeType]
152
+ raise SexpException.new "Unknown node type '#{json['name']}' in #{json.to_yaml}" if klass.nil?
153
+
154
+ result = klass.json( json )
155
+
156
+
157
+ end
158
+
159
+
160
+
161
+ end
162
+
163
+ class Identifier < SexpAst
164
+
165
+ # reference to declaration
166
+ include Sbuilder::Ethereum::DeclRef
167
+
168
+ # pointer to domain of the declaration
169
+ include Sbuilder::Ethereum::DomainRef
170
+
171
+
172
+ # Create a new Sexp containing +json+.
173
+ def self.json(json=nil)
174
+ ary = [
175
+ json['name'].to_sym,
176
+ json['attributes']['type'],
177
+ json['attributes']['value'],
178
+ ] unless json.nil?
179
+
180
+ Identifier.new(*ary)
181
+ end
182
+
183
+ def self.s( type, value )
184
+ Identifier.new( :Identifier, type, value )
185
+ end
186
+
187
+ def type
188
+ self[1]
189
+ end
190
+
191
+ # value for identifier as an expression
192
+ def value
193
+ self[2]
194
+ end
195
+
196
+ # semantic routine
197
+
198
+ # name of identifier
199
+ def name
200
+ value
201
+ end
202
+ def resolvedReference
203
+ raise 'Identifier reference #{self} not resolved' if declationRef.nil?
204
+ declationRef
205
+ end
206
+
207
+ end
208
+
209
+ class PragmaDirective < SexpAst
210
+ def self.json(json)
211
+ ary = [
212
+ json['name'].to_sym,
213
+ ]
214
+ PragmaDirective.new(*ary)
215
+ end
216
+ end
217
+
218
+ class SourceUnit < SexpAst
219
+ def self.json(json)
220
+ ary = [
221
+ json['name'].to_sym,
222
+ ]
223
+ SourceUnit.new(*ary)
224
+ end
225
+
226
+ def self.define( sourceUnit, ast )
227
+ SourceUnit.new( :SourceUnit, sourceUnit, ast )
228
+ end
229
+
230
+ end
231
+
232
+ class ContractDefinition < SexpAst
233
+
234
+ # number of contracts is a domain
235
+ include Sbuilder::Ethereum::DomainRef
236
+
237
+ include Scope
238
+
239
+ # type hierarcy
240
+ include TypeSymbol
241
+
242
+ # TypeSymbol uses 'typeName' to create unique names in type
243
+ # hierarchy
244
+ def typeName
245
+ name
246
+ end
247
+
248
+ def self.json(json)
249
+ ary = [
250
+ json['name'].to_sym,
251
+ json['attributes']['name'],
252
+ ]
253
+ ContractDefinition.new(*ary)
254
+ end
255
+ def name
256
+ self[1]
257
+ end
258
+
259
+ ##
260
+ # Name of set to hold contract identifiers
261
+ def contractIdSet
262
+ "#{name}_ids"
263
+ end
264
+
265
+ ##
266
+ # @return [VariableDeclaration:Array] symbols with 'sexp_type' ==
267
+ # :VariableDeclaration defined in contract scope
268
+ def contractVariables
269
+ return s() if symbols.nil?
270
+ symbols.values.select { |s| s.sexp_type == :VariableDeclaration }
271
+ end
272
+
273
+ end
274
+
275
+
276
+ class ParameterList < SexpAst
277
+
278
+ # back pointer to scope where declared
279
+ include Scoped
280
+
281
+ # it acts also as a scope
282
+ include Scope
283
+
284
+ def self.json(json)
285
+ ary = [
286
+ json['name'].to_sym,
287
+ ]
288
+ ParameterList.new(*ary)
289
+ end
290
+
291
+ # parameters SexpAst nodes starting form pos 1
292
+ def parameters
293
+ # return self[1..-1] if self.length > 1
294
+ return self[1..-1]
295
+ end
296
+
297
+ ##
298
+ # Name as function for function
299
+ def name
300
+ parent.name
301
+ end
302
+
303
+ end
304
+
305
+ class ExpressionStatement < SexpAst
306
+ def self.json(json)
307
+ ary = [
308
+ json['name'].to_sym,
309
+ ]
310
+ ExpressionStatement.new(*ary)
311
+ end
312
+ end
313
+
314
+ class MemberAccess < SexpAst
315
+
316
+ # reference to declaration
317
+ include DeclRef
318
+
319
+ # pointer to domain of the declaration
320
+ include DomainRef
321
+
322
+
323
+ def self.json(json)
324
+ ary = [
325
+ json['name'].to_sym,
326
+ json['attributes']['member_name'],
327
+ # json['attributes']['type'],
328
+ ]
329
+ MemberAccess.new(*ary)
330
+ end
331
+
332
+ # @return [String] member_name e.g. 'sender' in 'msg.sender'
333
+ def member_name
334
+ self[1]
335
+ end
336
+
337
+
338
+ ## Children
339
+ # @return [Identifier|MemberAccesss] msg in 'msg.sender', sender
340
+ # in 'msg.sender.send'
341
+
342
+ def memberStruct
343
+ self[2]
344
+ end
345
+
346
+
347
+ # "calling a function on the function" e.g. f.gas(2).value(20)()
348
+ # calls the modified function f and thereby sending 20 Wei and
349
+ # limiting the gas to 2 we catch this later in code generation
350
+ # phase, and have no need for declationRef
351
+ #
352
+ # @return [Boolean] true if 'mmbStct.decLRef.sexp_type == :FucnDef'
353
+ def isFunctionOnFunction
354
+ memberStruct && memberStruct.declationRef && memberStruct.declationRef.sexp_type == :FunctionDefinition
355
+ end
356
+
357
+ ##
358
+ # @return [Sexp] recipientSexp in s(:MemberAccess, "send",
359
+ # s(:MemberAccess, "sender", s(:Identifier, "msg", "msg"))) it
360
+ # returns s(:MemberAccess, "sender", s(:Identifier, "msg", "msg"))
361
+ # def recipientSexp
362
+ # memberStruct
363
+ # end
364
+
365
+
366
+ end
367
+
368
+ class Assignment < SexpAst
369
+ def self.json(json)
370
+ ary = [
371
+ json['name'].to_sym,
372
+ json['attributes']['operator'],
373
+ json['attributes']['type'],
374
+ ]
375
+ Assignment.new(*ary)
376
+ end
377
+
378
+ def operator
379
+ self[1]
380
+ end
381
+
382
+ def type
383
+ self[2]
384
+ end
385
+
386
+ # variable being assined to, 1.st child
387
+ def lval
388
+ self[3]
389
+ end
390
+
391
+ # expression being assined, 2nd child
392
+ def rval
393
+ self[4]
394
+ end
395
+
396
+ # Canonize
397
+ def setOperator( operator='=' )
398
+ self[1] = operator
399
+ end
400
+
401
+ def setRval( rval )
402
+ self[4] = rval
403
+ end
404
+
405
+ end
406
+
407
+
408
+ class Block < SexpAst
409
+ def self.json(json)
410
+ ary = [
411
+ json['name'].to_sym,
412
+ ]
413
+ Block.new(*ary)
414
+ end
415
+
416
+ # ------------------------------------------------------------------
417
+ # semantic methods
418
+ def statements
419
+ self[1..-1]
420
+ end
421
+
422
+ end
423
+
424
+ class Return < SexpAst
425
+
426
+ # back pointer for the function scope where return variables are set
427
+ include Scoped
428
+
429
+ def self.json(json=nil)
430
+ ary = [
431
+ json['name'].to_sym,
432
+ ] unless json.nil?
433
+ Return.new(*ary)
434
+ end
435
+
436
+ # list of expressions returned start from pos 1
437
+ def expressions
438
+ self[1..-1]
439
+ end
440
+
441
+ # semantic methods
442
+
443
+ # alias a name with more semantics
444
+ alias_method :function, :scopeDefining
445
+
446
+ # '(uint retVal, ...)' in 'function get() constant returns (uint retVal, ...)'
447
+ def functionReturnList
448
+ raise "function scope for #{self} not resolved" if function.nil?
449
+ function.returnList
450
+ end
451
+
452
+ def functionReturnParameter( i )
453
+ raise "function scope for #{self} not resolved" if function.nil?
454
+ function.returnParameter( i )
455
+ end
456
+
457
+ end
458
+
459
+
460
+ class IndexAccess < SexpAst
461
+
462
+ include DomainRef
463
+
464
+ def self.json(json)
465
+ ary = [
466
+ json['name'].to_sym,
467
+ ]
468
+ IndexAccess.new(*ary)
469
+ end
470
+
471
+ # childs
472
+ def identifier
473
+ self[1]
474
+ end
475
+
476
+ def indexer
477
+ self[2]
478
+ end
479
+ end
480
+
481
+ class Mapping < SexpAst
482
+
483
+
484
+ def self.json(json)
485
+ ary = [
486
+ json['name'].to_sym,
487
+ ]
488
+ Mapping.new(*ary)
489
+ end
490
+
491
+ # childs
492
+ def mapFrom
493
+ self[1]
494
+ end
495
+ def mapTo
496
+ self[2]
497
+ end
498
+
499
+ # @return [Array] mappings [from, to]
500
+ def maps
501
+ self[1..-1]
502
+ end
503
+
504
+
505
+ end
506
+
507
+
508
+ class VariableDeclaration < SexpAst
509
+
510
+ # back pointer to scope where declared
511
+ include Scoped
512
+
513
+ # pointer to domain of the declaration
514
+ include DomainRef
515
+
516
+ def self.json(json=nil)
517
+ ary = [
518
+ json['name'].to_sym,
519
+ json['attributes']['name'],
520
+ json['attributes']['type'],
521
+
522
+ ] unless json.nil?
523
+ VariableDeclaration.new(*ary)
524
+ end
525
+
526
+ def self.s( name, typeSexp=ElementaryTypeName.s )
527
+ VariableDeclaration.new( :VariableDeclaration, name, "domain", typeSexp )
528
+ end
529
+
530
+ def name
531
+ self[1]
532
+ end
533
+ # function return parameters do not have a name,
534
+ # canonize process may update name
535
+ def setName( name )
536
+ self[1] = name
537
+ end
538
+
539
+
540
+ def type
541
+ self[2]
542
+ end
543
+
544
+ # childs
545
+ def typeSexp
546
+ self[3]
547
+ end
548
+
549
+ def isMapping
550
+ typeSexp.sexp_type == :Mapping
551
+ end
552
+
553
+ # @return true iff +typeSexp? == :ElementaryTypeName
554
+ # def isElementary
555
+ # typeSexp && typeSexp.sexp_type == :ElementaryTypeName
556
+ # end
557
+
558
+
559
+ end
560
+
561
+
562
+ # @see Assignment because 'VariableDefinitionStatement' is intepreted
563
+ # an assignment
564
+ class VariableDefinitionStatement < SexpAst
565
+
566
+ # back pointer to scope where declared
567
+ include Scoped
568
+
569
+ def self.json(json)
570
+ ary = [
571
+ json['name'].to_sym,
572
+ ]
573
+ VariableDefinitionStatement.new(*ary)
574
+ end
575
+
576
+ # variable being assined to, 1.st child
577
+ def lval
578
+ self[1]
579
+ end
580
+
581
+ # expression being assined, 2nd child
582
+ def rval
583
+ self[2]
584
+ end
585
+
586
+
587
+
588
+ end
589
+
590
+
591
+ # @see UserDefinedTypeName implementing also typeName
592
+ class ElementaryTypeName < SexpAst
593
+
594
+ # back pointer to scope where declared
595
+ include Scoped
596
+
597
+ # pointer to symbol type (i.e User defined/elementary type)
598
+ include SymbolRef
599
+
600
+ # pointer to domain of the declaration
601
+ include DomainRef
602
+
603
+ def self.json(json)
604
+ ary = [
605
+ json['name'].to_sym,
606
+ json['attributes']['name'],
607
+ ]
608
+ ElementaryTypeName.new(*ary)
609
+ end
610
+
611
+ def self.s()
612
+ ElementaryTypeName.new( :ElementaryTypeName )
613
+ end
614
+
615
+ def typeName
616
+ self[1]
617
+ end
618
+
619
+
620
+ end
621
+
622
+ class IfStatement < SexpAst
623
+ def self.json(json)
624
+ ary = [
625
+ json['name'].to_sym,
626
+ ]
627
+ IfStatement.new(*ary)
628
+ end
629
+
630
+ def condition
631
+ self[1]
632
+ end
633
+
634
+ # childs
635
+ def then_branch
636
+ self[2]
637
+ end
638
+
639
+ def else_branch
640
+ self[3]
641
+ end
642
+
643
+ end
644
+
645
+ class Throw < SexpAst
646
+ def self.json(json)
647
+ ary = [
648
+ json['name'].to_sym,
649
+ ]
650
+ Throw.new(*ary)
651
+ end
652
+
653
+ end
654
+
655
+ class UserDefinedTypeName < SexpAst
656
+
657
+ # back pointer to scope where declared
658
+ include Scoped
659
+
660
+ # pointer to symbol type (i.e User defined/elementary type)
661
+ include SymbolRef
662
+
663
+ def self.json(json)
664
+ ary = [
665
+ json['name'].to_sym,
666
+ json['attributes']['name'],
667
+ ]
668
+ UserDefinedTypeName.new(*ary)
669
+ end
670
+
671
+ def name
672
+ self[1]
673
+ end
674
+
675
+ # common method for UserDefinedTypeName, ElementaryTypeName
676
+ def typeName
677
+ name
678
+ end
679
+
680
+
681
+ end
682
+
683
+ class NewExpression < SexpAst
684
+
685
+ # reference to constructor declaration
686
+ include DeclRef
687
+
688
+ def self.json(json)
689
+ ary = [
690
+ json['name'].to_sym,
691
+ json['attributes']['type'],
692
+ ]
693
+ NewExpression.new(*ary)
694
+ end
695
+
696
+ def type
697
+ self[1]
698
+ end
699
+
700
+ ##
701
+ # Semantic
702
+ def contractConstructed
703
+ self[2]
704
+ end
705
+
706
+ # def name
707
+ # functionCalled.name
708
+ # end
709
+
710
+
711
+ end
712
+
713
+ ##
714
+ # Wrap function call to indicate that we should read result of
715
+ # function, which was called previously. This sexp is created when
716
+ # spllitting statement with function call e.g. in assignment or in
717
+ # condiational
718
+ class FunctionCallReadReturn < SexpAst
719
+
720
+ # function may assign to variable with domain of the declaration,
721
+ # this is handled in 'FunctionCallReadReturn'
722
+ include DomainRef
723
+
724
+ def initialize( functionCall )
725
+ ary = [
726
+ :FunctionCallReadReturn,
727
+ functionCall,
728
+ ]
729
+ super(*ary)
730
+ end
731
+ def self.define( functionCall )
732
+ FunctionCallReadReturn.new( functionCall )
733
+ end
734
+
735
+ def functionCalled
736
+ self[1]
737
+ end
738
+
739
+ end
740
+
741
+ class FunctionCall < SexpAst
742
+
743
+
744
+ def self.json(json=nil)
745
+ ary = [
746
+ json['name'].to_sym,
747
+ json['attributes']['type'],
748
+ ] unless json.nil?
749
+ FunctionCall.new(*ary)
750
+ end
751
+
752
+ def type
753
+ self[1]
754
+ end
755
+
756
+ ##
757
+ # childs
758
+ def functionExpression
759
+ self[2]
760
+ end
761
+
762
+ def actualParameters
763
+ self[3..-1]
764
+ end
765
+
766
+ end
767
+
768
+ class FunctionDefinition < SexpAst
769
+ # Function definition is also a scope
770
+ include Scope
771
+
772
+ # @əttr [ContractDefinition] contractDefinition
773
+ attr_accessor :contractDefinition
774
+
775
+ # pointer to domain of the declaration
776
+ include DomainRef
777
+
778
+ def self.json(json=nil)
779
+ ary = [
780
+ json['name'].to_sym,
781
+ json['attributes']['name'],
782
+ json['attributes']['public'],
783
+ json['attributes']['constant'],
784
+ ] unless json.nil?
785
+ FunctionDefinition.new(*ary)
786
+ end
787
+
788
+ def name
789
+ self[1]
790
+ end
791
+
792
+ def isPublic
793
+ self[2]
794
+ end
795
+ def isConstant
796
+ self[3]
797
+ end
798
+ # child nodes in AST
799
+ # @return [ParameterList] parameterList
800
+ def parameterList
801
+ self[4]
802
+ end
803
+ # child nodes in AST
804
+ # @return [ParameterList] returnList
805
+ def returnList
806
+ self[5]
807
+ end
808
+ def block
809
+ self[6]
810
+ end
811
+
812
+ # ------------------------------------------------------------------
813
+ # semantic
814
+ def statements
815
+ block.statements
816
+ end
817
+
818
+ def returnParameter( i )
819
+ returnList[i+1]
820
+ end
821
+
822
+ ##
823
+ # Method added dyncamially
824
+ # def interfaceName
825
+ # return "Demo()" or "Demo(set)
826
+ # end
827
+
828
+ end
829
+
830
+ class UnaryOperation < SexpAst
831
+ # pointer to domain of the declaration
832
+ include DomainRef
833
+
834
+ # Create a new Sexp containing +args+.
835
+ def self.json(json)
836
+ ary = [
837
+ json['name'].to_sym,
838
+ json['attributes']['operator'],
839
+ ]
840
+
841
+ UnaryOperation.new(*ary)
842
+ end
843
+
844
+ def operator
845
+ self[1]
846
+ end
847
+
848
+ # childs
849
+ def expr
850
+ self[2]
851
+ end
852
+
853
+ end
854
+
855
+
856
+ class BinaryOperation < SexpAst
857
+
858
+ # pointer to domain of the declaration
859
+ include DomainRef
860
+
861
+
862
+ # Create a new Sexp containing +args+.
863
+ def self.json(json)
864
+ ary = [
865
+ json['name'].to_sym,
866
+ json['attributes']['operator'],
867
+ ]
868
+
869
+ BinaryOperation.new(*ary)
870
+ end
871
+
872
+ def operator
873
+ self[1]
874
+ end
875
+
876
+ # childs
877
+ def lhs
878
+ self[2]
879
+ end
880
+ def rhs
881
+ self[3]
882
+ end
883
+
884
+
885
+ # value of operator expression
886
+ def value
887
+ "op_#{operator}"
888
+ end
889
+
890
+ end
891
+
892
+ class Literal < SexpAst
893
+
894
+ # literals participate to data flows
895
+ include DomainRef
896
+
897
+ # Create a new Sexp containing +args+.
898
+ def self.json(json)
899
+ ary = [
900
+ json['name'].to_sym,
901
+ json['attributes']['type'],
902
+ json['attributes']['value'],
903
+ ]
904
+
905
+ Literal.new(*ary)
906
+ end
907
+
908
+ def type
909
+ self[1]
910
+ end
911
+
912
+ # value of the expression
913
+ def value
914
+ self[2]
915
+ end
916
+
917
+ ##
918
+ # canonize maps literal constant values in solc to TLA
919
+ def setValue( value )
920
+ self[2] = value
921
+ end
922
+
923
+ end
924
+ # @!endgroup
925
+
926
+ # ------------------------------------------------------------------
927
+ # @!group Symbols
928
+
929
+ class BuiltInSymbol < SexpSbuilder
930
+
931
+ # integer, boolean, etc
932
+ include TypeSymbol;
933
+
934
+
935
+ # TypeSymbol uses 'typeName' to create unique names in type
936
+ # hierarchy
937
+ def typeName
938
+ name
939
+ end
940
+
941
+
942
+ # it may define names e.g. address knowns of 'send'
943
+ include Scope;
944
+
945
+ def initialize(name)
946
+ ary = [
947
+ :BuiltInSymbol,
948
+ name
949
+ ]
950
+ super(*ary)
951
+ end
952
+
953
+ def name
954
+ self[1]
955
+ end
956
+
957
+ # @return unique identifier like no other
958
+ def id
959
+ "#{self.class}-#{name}"
960
+ end
961
+
962
+
963
+ end
964
+
965
+ # @!endgroup
966
+ # ------------------------------------------------------------------
967
+
968
+ # ------------------------------------------------------------------
969
+ # @!group Sexp cretad outside AST
970
+
971
+ # Symbol table main entry (like Sexp), not found in AST
972
+ class GlobalScope < SexpSbuilder
973
+ include Scope
974
+
975
+ def initialize
976
+ ary = [
977
+ :GlobalScope,
978
+ ]
979
+
980
+ super(*ary)
981
+ end
982
+
983
+ def name
984
+ self[0].to_s
985
+ end
986
+
987
+ ##
988
+ # Use global scope like contract
989
+ def contractVariables
990
+ s()
991
+ end
992
+
993
+ end
994
+
995
+ # @see http://solidity.readthedocs.io/en/develop/units-and-global-variables.html
996
+ class Msg < SexpSbuilder
997
+
998
+ # e.g. to hold 'sender', 'value', 'gas', ...
999
+ include Scope
1000
+
1001
+ def initialize( id )
1002
+ ary = [
1003
+ :Msg,
1004
+ id,
1005
+ ]
1006
+ super(*ary)
1007
+ end
1008
+
1009
+ ##
1010
+ # @return unique identifier like no other
1011
+ def id
1012
+ self[1]
1013
+ end
1014
+
1015
+
1016
+
1017
+ end
1018
+
1019
+ # @see http://solidity.readthedocs.io/en/develop/units-and-global-variables.html
1020
+ class Now < SexpSbuilder
1021
+
1022
+ def initialize( id )
1023
+ ary = [
1024
+ :Now,
1025
+ id,
1026
+ ]
1027
+ super(*ary)
1028
+ end
1029
+
1030
+ # @return unique identifier like no other
1031
+ def id
1032
+ self[1]
1033
+ end
1034
+ end
1035
+
1036
+
1037
+ # not <SexpSbuilder because we construct Domain nodes
1038
+ class Domain < SexpAst
1039
+
1040
+ # Using Domain to define types for common message properties
1041
+ include Scoped
1042
+
1043
+ # pointer to symbol type (i.e User defined/elementary type)
1044
+ include SymbolRef
1045
+
1046
+ def initialize(name, solidityType=nil)
1047
+ ary = [
1048
+ :Domain,
1049
+ name,
1050
+ solidityType,
1051
+ ]
1052
+
1053
+ super(*ary)
1054
+ end
1055
+
1056
+ def self.json(json)
1057
+ ary = [
1058
+ # json['name'].to_sym,
1059
+ json['attributes']['name'],
1060
+ json['attributes']['solidityType'],
1061
+ ]
1062
+ Domain.new(*ary)
1063
+ end
1064
+
1065
+ def self.s( name, solidityType=nil )
1066
+ Domain.new( name, solidityType )
1067
+ end
1068
+
1069
+ def domainName
1070
+ self[1]
1071
+ end
1072
+
1073
+ def solidityType
1074
+ self[2]
1075
+ end
1076
+
1077
+
1078
+ ##
1079
+ # values idenfied for domain e.g. contract names in 'eth_code_hash'.
1080
+ # Possibly literals in ethereum contracts.
1081
+ #
1082
+ def domainValues
1083
+ self[3..-1]
1084
+ end
1085
+
1086
+ def name
1087
+ domainName
1088
+ end
1089
+
1090
+ end
1091
+
1092
+ class Domains < SexpSbuilder
1093
+
1094
+ # @param [Domain:array] domainArr array of Domain sexps
1095
+ def initialize( domainArr )
1096
+ ary = [
1097
+ :Domains,
1098
+ *domainArr
1099
+ ]
1100
+
1101
+ super(*ary)
1102
+ end
1103
+
1104
+ def domains
1105
+ self[1..-1]
1106
+ end
1107
+
1108
+ end
1109
+
1110
+
1111
+
1112
+ # Snippets created
1113
+ class Snippets < SexpSbuilder
1114
+
1115
+ # @param [Domain:array] domainArr array of Domain sexps
1116
+ def initialize( snippets )
1117
+ ary = [
1118
+ :Snippets,
1119
+ *snippets
1120
+ ]
1121
+
1122
+ super(*ary)
1123
+ end
1124
+
1125
+ end
1126
+
1127
+ class Interfaces < SexpSbuilder
1128
+
1129
+ # @param [Interface:Array] interfaces array of Interface instances
1130
+ def initialize( interfaces )
1131
+ ary = [
1132
+ :Interfaces,
1133
+ *interfaces
1134
+ ]
1135
+ super(*ary)
1136
+ end
1137
+
1138
+ def interfaces
1139
+ self[1..-1]
1140
+ end
1141
+
1142
+ end
1143
+
1144
+
1145
+ class Definitions < SexpSbuilder
1146
+
1147
+ # @param [Definition:Array] interfaces array of Definition instances
1148
+ def initialize( definitions )
1149
+ ary = [
1150
+ :Definitions,
1151
+ *definitions
1152
+ ]
1153
+ super(*ary)
1154
+ end
1155
+
1156
+ def definitions
1157
+ self[1..-1]
1158
+ end
1159
+
1160
+ end
1161
+
1162
+
1163
+ class Definition < SexpSbuilder
1164
+
1165
+ #
1166
+ # @param [:Symbol] definitionType :normal or :function
1167
+ def initialize( definitionName, properties, definitionType )
1168
+ raise "Unknown type #{definitionType}" unless [:normal, :function ].include? definitionType
1169
+ ary = [
1170
+ :Definition,
1171
+ definitionName,
1172
+ properties,
1173
+ definitionType
1174
+ ]
1175
+ super(*ary)
1176
+ end
1177
+
1178
+ def self.define( definitionName, propertiesSexp, definitionType = :normal )
1179
+ Definition.new(
1180
+ definitionName,
1181
+ propertiesSexp.map do |prop|
1182
+ # prop = s(name domain_name)
1183
+ p = {
1184
+ :type => prop[0],
1185
+ :name => prop[1],
1186
+ }
1187
+ p[:domain_name] = prop[2] if prop[0] == :parameter
1188
+ p[:reference] = prop[2] if prop[0] == :reference
1189
+ p
1190
+ end,
1191
+ definitionType
1192
+ )
1193
+ end
1194
+
1195
+ def name
1196
+ self[1]
1197
+ end
1198
+
1199
+ # @return [Hash:Array] prop
1200
+ # @option prop [:Symbol] :type values :parameter or :reference
1201
+ # @option prop [:Symbol] :name
1202
+ # @option prop [:Symbol] :domain_name if :type == :parameter
1203
+ # @option prop [:Symbol] :reference if :type == :reference
1204
+ def properties
1205
+ self[2]
1206
+ end
1207
+
1208
+ # @return [:Symbol] definitionType one of [:normal, :function]
1209
+ def definitionType
1210
+ self[3]
1211
+ end
1212
+
1213
+
1214
+ end
1215
+
1216
+
1217
+
1218
+ class Interface < SexpSbuilder
1219
+
1220
+ def initialize( interfaceDefinition, input=nil, output=nil )
1221
+ ary = [
1222
+ :Interface,
1223
+ interfaceDefinition,
1224
+ input,
1225
+ output,
1226
+ ]
1227
+ super(*ary)
1228
+ end
1229
+
1230
+ def self.define( contractName, functionName, inputSexp, outputSexp )
1231
+ Interface.new(
1232
+ {
1233
+ :interface => contractName,
1234
+ :method => functionName,
1235
+ :input => inputSexp.map do |param|
1236
+ # param s(:type name domain_name)
1237
+ {
1238
+ :name => param[1],
1239
+ :domain_name => param[2]
1240
+ }
1241
+ end,
1242
+ :output => outputSexp.map do |param|
1243
+ # param s(:type name domain_name)
1244
+ {
1245
+ :name => param[1],
1246
+ :domain_name => param[2]
1247
+ }
1248
+ end
1249
+ })
1250
+ end
1251
+
1252
+ # #
1253
+ # # @param [ParameterList] input request parameters
1254
+ # #
1255
+ # # @param [ParameterList] output response parameters
1256
+
1257
+ # def self.create( contractName, functionName, input, output )
1258
+ # Interface.new(
1259
+ # {
1260
+ # :interface => functionName,
1261
+ # :input => input.parameters.map do |param|
1262
+ # # param [VariableDeclation]
1263
+ # raise "Domain reference not resolved on #{param}" unless param.domainReference
1264
+ # {
1265
+ # :name => param.name,
1266
+ # # :type => param.type,
1267
+ # :domain_name => param.domainReference.name,
1268
+ # }
1269
+ # end,
1270
+ # :output => output.parameters.map do |param|
1271
+ # # param [VariableDeclation]
1272
+ # raise "Domain reference not resolved on #{param}" unless param.domainReference
1273
+ # {
1274
+ # :name => param.name,
1275
+ # # :type => param.type,
1276
+ # :domain_name => param.domainReference.name,
1277
+ # }
1278
+ # end,
1279
+
1280
+ # # :output => functionName.parameters.map { |param| a },
1281
+ # },
1282
+ # input, output,
1283
+
1284
+ # )
1285
+ # end
1286
+
1287
+
1288
+
1289
+ def interfaceDefinition
1290
+ self[1]
1291
+ end
1292
+ def inputParameters
1293
+ raise "Not used"
1294
+ self[2]
1295
+ end
1296
+ def outputParameters
1297
+ raise "Not used"
1298
+ self[3]
1299
+ end
1300
+
1301
+ # return +path+ parameter for ApiLoaderFacade#newInterce
1302
+ def path
1303
+ interfaceDefinition[:interface]
1304
+ end
1305
+
1306
+ # return +op+ parameter for ApiLoaderFacade#newInterce
1307
+ def op
1308
+ interfaceDefinition[:method]
1309
+ end
1310
+
1311
+ def input
1312
+ raise "Not used"
1313
+ interfaceDefinition[:input]
1314
+ end
1315
+
1316
+ end
1317
+
1318
+ class Snippet < SexpSbuilder
1319
+
1320
+ def initialize( metatype, name, sexp, specName=nil, comment=false )
1321
+ ary = [
1322
+ :Snippet,
1323
+ metatype,
1324
+ name,
1325
+ sexp,
1326
+ specName,
1327
+ comment,
1328
+ ]
1329
+ super(*ary)
1330
+ end
1331
+
1332
+ # ------
1333
+ # sematics
1334
+
1335
+ def metatype
1336
+ self[1]
1337
+ end
1338
+ def name
1339
+ self[2]
1340
+ end
1341
+ # Genarate body
1342
+ def sexp
1343
+ self[3]
1344
+ end
1345
+ # optional specName - if want override generation
1346
+ def specName
1347
+ self[4]
1348
+ end
1349
+ def comment
1350
+ self[5]
1351
+ end
1352
+
1353
+ # this stuff gets rendered as snippetBody
1354
+ def snippet
1355
+ # self[2..-1]
1356
+ s(sexp)
1357
+ end
1358
+
1359
+
1360
+ # metatype+appName combination is unique identifier in specification
1361
+ # code domain.
1362
+
1363
+ # appName is unique identifier in application domain
1364
+ def appName
1365
+ name
1366
+ end
1367
+
1368
+ # Unique name as identified by 'metatype':'appName'
1369
+ def snippetId
1370
+ "#{metatype}:#{appName}"
1371
+ end
1372
+
1373
+ end
1374
+
1375
+ # @!endgroup
1376
+
1377
+ end
1378
+ end