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,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