furnace-xray 1.1.0.pre1 → 1.1.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/lib/furnace-xray/app/assets/javascripts/application.js.coffee +9 -9
  3. data/lib/furnace-xray/app/assets/javascripts/lib/graph.js.coffee +6 -5
  4. data/lib/furnace-xray/app/assets/javascripts/lib/input.js.coffee +43 -104
  5. data/lib/furnace-xray/app/assets/javascripts/lib/input_state.js.coffee +6 -4
  6. data/lib/furnace-xray/app/assets/javascripts/lib/node.js.coffee +39 -0
  7. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/argument.js.coffee +9 -2
  8. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/basic_block.js.coffee +82 -0
  9. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/constant.js.coffee +9 -0
  10. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/function.js.coffee +20 -5
  11. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/instruction.js.coffee +43 -23
  12. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/module.js.coffee +8 -0
  13. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/phi.js.coffee +10 -0
  14. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/type.js.coffee +6 -9
  15. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/type_bottom.js.coffee +3 -0
  16. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/type_variable.js.coffee +1 -0
  17. data/lib/furnace-xray/app/views/nodes/{instruction_typed.jst.mustache → instruction.jst.mustache} +0 -0
  18. data/lib/furnace-xray/app/views/nodes/{operand_argument.jst.mustache → operands/argument.jst.mustache} +0 -0
  19. data/lib/furnace-xray/app/views/nodes/{operand_basic_block.jst.mustache → operands/basic_block.jst.mustache} +0 -0
  20. data/lib/furnace-xray/app/views/nodes/{operand_constant.jst.mustache → operands/constant.jst.mustache} +0 -0
  21. data/lib/furnace-xray/app/views/nodes/{operand_instruction.jst.mustache → operands/instruction.jst.mustache} +0 -0
  22. data/lib/furnace-xray/app/views/nodes/{type_constant.jst.mustache → type.jst.mustache} +0 -0
  23. data/lib/furnace-xray/version.rb +1 -1
  24. data/sample.json +8909 -1
  25. metadata +15 -13
  26. data/lib/furnace-xray/app/assets/javascripts/lib/map.js.coffee +0 -48
  27. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/block.js.coffee +0 -76
  28. data/lib/furnace-xray/app/assets/javascripts/lib/nodes/operand.js.coffee +0 -21
  29. data/lib/furnace-xray/app/views/nodes/operand_constant_function.jst.mustache +0 -1
  30. data/lib/furnace-xray/app/views/nodes/type_parametric.jst.mustache +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad3fbcd1c6346fa30c03fa890bd356da8440d602
4
- data.tar.gz: ab2c38eee0ee6edaff32064341037e61874bb34f
3
+ metadata.gz: c33b7ac042d318fbb36bc37effca9374300eff92
4
+ data.tar.gz: 126063f60ad1f161a7d3f8b093dbdf78a6637e94
5
5
  SHA512:
6
- metadata.gz: 2b18eba9f93d570ddc9f9c40a4fead4b045c46088354666248b1eb87aa1ef835e3b919a030b5f59248a7b183703284f69b0c13b27a563181eb06b0c0bacb081d
7
- data.tar.gz: b9cfcca32473c06a899459259a602028b322ed9db8c30ce43aea2a8d8697c3e63fa3b832d7d64679828dd0f5ba71ed2f329037c7df7d4fb656791853a732d4ed
6
+ metadata.gz: 14b818259d317c73fe046ef38ed131dbc24cd32430c4afdb2413f4100f90f76c7a12c0e7d418066caba2018ad396791fc0ea548b995f2bfae4502af630c1bf7c
7
+ data.tar.gz: aa33c93878d6d0a011c4640526c949114d89768bc0d9a631e2a145429047722924ebcade79660fb13028628e90d133c39e8ab23c464e123a361c4113d69bd5b7
@@ -64,16 +64,16 @@ class Application
64
64
  @transform.removeClass('active').html('')
65
65
  @diff.html('')
66
66
 
67
- input = @data[@currentFunction]
67
+ input = Input.functions[@currentFunction].input
68
68
 
69
- Drawer.reset() if @input?.source.name != input.source.name
69
+ Drawer.reset() if @input?.function.name != input.function.name
70
70
  Drawer.clear()
71
71
 
72
72
  @input = input
73
73
  @input.rewind(@currentStep)
74
74
  @drawer = new Drawer(new Graph(@input))
75
75
 
76
- @title.html @input.function.title()
76
+ @title.html @input.map[@input.function.id]?.title()
77
77
  @diff.html "~ " + @input.previousState.cursor if @input.previousState?.cursor?
78
78
 
79
79
  @renewZoomer()
@@ -87,7 +87,7 @@ class Application
87
87
 
88
88
  dehasherize: ->
89
89
  hash = window.location.hash.from(1)
90
- hash = "0:#{@data[0].events.length-1}" if hash.length == 0
90
+ hash = "0:#{Input.functions[0].input.events.length-1}" if hash.length == 0
91
91
  [@currentFunction, @currentStep] = hash.split(":").map (x) -> x.toNumber()
92
92
 
93
93
  jumpTo: (func, step) ->
@@ -95,8 +95,8 @@ class Application
95
95
  @selector.find('option').each (x) ->
96
96
  func = $(@).attr('value').toNumber() if $(@).text() == func
97
97
 
98
- @currentFunction = func; step = @data[func].events.length-1 if step == undefined
99
- @currentStep = [step, @data[func].events.length-1].min()
98
+ @currentFunction = func; step = Input.functions[func].input.events.length-1 if step == undefined
99
+ @currentStep = [step, Input.functions[func].input.events.length-1].min()
100
100
  @currentStep = [0, @currentStep].max()
101
101
  window.location.hash = "#{@currentFunction}:#{@currentStep || 0}"
102
102
 
@@ -162,9 +162,9 @@ class Application
162
162
  buildSelector: ->
163
163
  groups = ['Present', 'Removed'].map (x) -> $("<optgroup label='#{x}'></optgroup>")
164
164
 
165
- @data.each (f, i) =>
166
- group = if f.source.present then groups[0] else groups[1]
167
- group.append "<option value='#{i}'>#{f.source.name}</option>"
165
+ Input.functions.each (f, i) ->
166
+ group = if f.present then groups[0] else groups[1]
167
+ group.append "<option value='#{i}'>#{f.name}</option>"
168
168
 
169
169
  groups.each (x) => @selector.append x
170
170
 
@@ -8,18 +8,19 @@ class @Graph
8
8
  @edges = []
9
9
  blockNodes = Object.extended()
10
10
 
11
- @input.blocks.each (i, b) =>
12
- blockNodes[b.name] =
11
+ @input.activeBlocks()?.each (b) =>
12
+ blockNodes[b.id] =
13
13
  edges: b.references()
14
14
  label: b.name
15
- data: b.title(@input.previousState?.blocks[b.name])
15
+ data: b.title(unless @input.previousState? then false else (@input.previousState.basicBlocks[b.id] || []))
16
16
 
17
17
  blockNodes.each (i, n) =>
18
18
  edges = []
19
19
 
20
20
  n.edges.each (x) =>
21
- edges.add {source: n, target: blockNodes[x], data: blockNodes[x].label}
22
- @edges.add edges.last()
21
+ if blockNodes[x]?
22
+ edges.add {source: n, target: blockNodes[x], data: blockNodes[x].label}
23
+ @edges.add edges.last()
23
24
 
24
25
  n.edges = edges
25
26
 
@@ -2,61 +2,63 @@
2
2
  # Internal representation of input JSON
3
3
  #
4
4
  class @Input
5
- @normalize: (data) ->
6
- data.map (x) -> new Input(x)
7
-
8
- constructor: (@source) ->
9
- @source.events.each (x) -> x.event = x.event.camelize(false)
10
-
11
- # Scan for effective events
12
- @events = []
13
- reducer = []
5
+ @normalize: (@events) =>
6
+ @functions = []
7
+ events = Object.extended()
14
8
  transforms = Object.extended()
15
9
 
16
- @source.events.each (x, i) =>
17
- switch x.event
18
- when 'addInstruction'
19
- reducer.add x.name
20
- @events.add i
21
- when 'removeInstruction'
22
- reducer.exclude x.name
23
- @events.add i
24
- when 'updateInstruction', 'renameInstruction'
25
- @events.add i if reducer.any(x.name)
26
- when 'type', 'transformStart'
27
- else
28
- @events.add i
29
-
30
- if x.event == 'transformStart'
31
- id = @events.length-1
32
- transforms[id] = {id: id, label: x.name}
33
-
34
- @transforms = transforms.values()
10
+ @events.each (event, i) =>
11
+ if event['kind'] == 'transform'
12
+ f = event['function_id']
13
+
14
+ transforms[f] ||= []
15
+ transforms[f].push
16
+ id: events[f].length - 1
17
+ label: event['name']
18
+ else
19
+ node = Node.refresh(event)
20
+
21
+ if node.attachedFunctions?
22
+ Object.each node.attachedFunctions(), (id, f) =>
23
+ events[id] ||= []
24
+ events[id].push i
25
+
26
+ Node.kinds['function'].each (f) =>
27
+ @functions.push
28
+ name: f.name
29
+ present: f.present
30
+ input: new Input(f, events[f.id], transforms[f.id])
31
+
32
+ @constantize: (kind) ->
33
+ result = window[kind.camelize()+'Node']
34
+ result
35
+
36
+ constructor: (@function, @events, @transforms) ->
35
37
  @transforms = @transforms.filter (x, i) =>
36
38
  x.length = (@transforms[i+1]?.id || @events.length) - x.id
37
- x.id < @events.length-1
39
+ x.id < @events.length-1 && x.length > 0
38
40
 
39
41
  @reset()
40
42
 
41
- reset: ->
42
- @types = Object.extended()
43
- @blocks = Object.extended()
44
- @instructions = Object.extended()
45
- @blocksMap = new Map 'blocks'
46
- @instructionsMap = new Map 'instructions'
43
+ activeBlocks: ->
44
+ data = @kinds['basic_block']?.findAll (b) =>
45
+ b.attachedFunctions()[@function.id]?
47
46
 
48
- @function = new FunctionNode(@source.name, @source.present)
49
- @cursor = 0
47
+ data || []
50
48
 
51
- # run first step at initialization
52
- i = -1; @run(i) while (i+=1) <= (@events[1] || @source.events.length-1)
49
+ reset: ->
50
+ @map = Object.extended()
51
+ @kinds = Object.extended()
52
+ @cursor = 0
53
+
54
+ # run upcoming steps at initialization
55
+ i = -1; @run(i) while (i+=1) < @events[0]
53
56
 
54
57
  rewind: (to) ->
55
58
  return if to == @cursor
56
59
 
57
60
  if to < @cursor
58
61
  delete @previousState
59
- @reset()
60
62
  else
61
63
  @previousState = new InputState(@)
62
64
 
@@ -72,67 +74,4 @@ class @Input
72
74
  @cursor = stop
73
75
 
74
76
  run: (step) ->
75
- event = @source.events[step]
76
-
77
- if event.event == 'type'
78
- @types[event.id] = new TypeNode(event.kind, event.name, event.parameters)
79
- else
80
- @[event.event]?(event)
81
- console.log "UNKNOWN EVENT: #{event.event}" unless @[event.event]?
82
-
83
- type: (id) ->
84
- return undefined unless id?
85
-
86
- if type = @types[id]
87
- return type
88
- else
89
- @reset()
90
- throw "Type #{id} not found in #{@types.keys().join(',')}"
91
-
92
- setReturnType: (event) ->
93
- @function.setReturnType @type(event.return_type)
94
-
95
- setArguments: (event) ->
96
- @function.setArguments(event.arguments.map (x) =>
97
- new ArgumentNode(x.name, @type(x.type)))
98
-
99
- addBasicBlock: (event) ->
100
- @blocksMap.add event.name, (id) =>
101
- @blocks[id] = new BlockNode(event.name)
102
-
103
- removeBasicBlock: (event) ->
104
- @blocksMap.remove event.name, (id) =>
105
- delete @blocks[id]
106
-
107
- renameBasicBlock: (event) ->
108
- @blocksMap.rename event.name, event.new_name, (id) =>
109
- @blocks[id].setName(event.new_name)
110
-
111
- updateInstruction: (event) ->
112
- id = @instructionsMap.add event.name, (id) =>
113
- @instructions[id] = new InstructionNode
114
-
115
- if Object.isArray(event.operands)
116
- operands = event.operands.map (x) =>
117
- new OperandNode x.kind, @type(x.type), x.name, x.value
118
- else
119
- operands = []
120
- Object.each event.operands, (key, x) =>
121
- operands.push [key, new OperandNode(x.kind, @type(x.type), x.name, x.value)]
122
-
123
- @instructions[id].update event.opcode, event.name, event.parameters, operands, @type(event.type)
124
-
125
- addInstruction: (event) ->
126
- @instructionsMap.locateOrAdd event.name, (i) =>
127
- @blocksMap.locate event.basic_block, (b) =>
128
- @instructions[i].link @blocks[b], event.index
129
-
130
- removeInstruction: (event) ->
131
- @instructionsMap.locate event.name, (i) =>
132
- @instructions[i].unlink()
133
-
134
- renameInstruction: (event) ->
135
- @instructionsMap.rename event.name, event.new_name, (i) =>
136
- @instructions[i].name = event.new_name
137
-
138
- transformStart: (event) ->
77
+ node = Node.refresh(Input.events[step], @map, @kinds)
@@ -1,8 +1,10 @@
1
1
  class @InputState
2
2
  constructor: (input) ->
3
- @blocks = Object.extended()
3
+ @basicBlocks = Object.extended()
4
4
  @cursor = input.cursor
5
5
 
6
- input.blocksMap.each (bname, id) =>
7
- @blocks[bname] = input.blocks[id].instructions.map (x) ->
8
- {title: x.title(), name: x.name}
6
+ input.kinds['basic_block']?.each (b) =>
7
+ @basicBlocks[b.id] = b.instructions.map (i) =>
8
+ id: i.id
9
+ name: i.name
10
+ title: i.title()
@@ -0,0 +1,39 @@
1
+ class @Node
2
+ @refresh: (data, map=false, kinds=false) ->
3
+ Node.map ||= Object.extended()
4
+ Node.kinds ||= Object.extended()
5
+
6
+ map ||= Node.map
7
+ kinds ||= Node.kinds
8
+
9
+ if map[data.id]
10
+ map[data.id].update(data, map)
11
+ else
12
+ klass = window[data.kind.camelize()+'Node']
13
+
14
+ return false if !klass?
15
+
16
+ kinds[data.kind] ||= []
17
+ kinds[data.kind].push map[data.id] = new klass(data, map)
18
+
19
+ map[data.id]
20
+
21
+ @reset: ->
22
+ Node.map = Object.extended()
23
+ Node.kinds = {}
24
+
25
+ constructor: (data, map) ->
26
+ @id = data.id
27
+ @update(data, map)
28
+
29
+ update: (data, map) ->
30
+
31
+ locate: (id, map) ->
32
+ map[id] || throw("Element #{id} not found in map")
33
+
34
+ reassign: (before, after, callback) ->
35
+ if !before? || before.length == 0
36
+ callback([], after)
37
+ else
38
+ intersection = before.intersect(after)
39
+ callback before.subtract(intersection), after.subtract(intersection)
@@ -1,7 +1,14 @@
1
- class @ArgumentNode
2
- constructor: (@name, @type) ->
1
+ class @ArgumentNode extends Node
2
+ update: (data, map) ->
3
+ @name = data['name']
4
+ @type = @locate(data['type'], map)
3
5
 
4
6
  title: ->
5
7
  JST['nodes/argument']
8
+ type: @type.title()
9
+ name: @name
10
+
11
+ operandTitle: ->
12
+ JST['nodes/operands/argument']
6
13
  type: @type.title()
7
14
  name: @name
@@ -0,0 +1,82 @@
1
+ class @BasicBlockNode extends Node
2
+ constructor: (data, map) ->
3
+ super
4
+ @functions = Object.extended()
5
+
6
+ update: (data, map) ->
7
+ @name = data['name']
8
+
9
+ @reassign @instructionIds, data['instruction_ids'], (removed, added) =>
10
+ removed.each (id) => @locate(id, map).unlinkBlock(@)
11
+ added.each (id) => @locate(id, map).linkBlock(@)
12
+
13
+ @instructionIds = data['instruction_ids']
14
+ @instructions = @instructionIds.map (id) => @locate(id, map)
15
+
16
+ linkFunction: (f) ->
17
+ @functions[f.id] = f
18
+
19
+ unlinkFunction: (f) ->
20
+ delete @functions[f.id]
21
+
22
+ attachedFunctions: -> @functions
23
+
24
+ title: (previousInstructions) ->
25
+ JST['nodes/block']
26
+ name: @name
27
+ instructions: @titleizeInstructions(previousInstructions)
28
+
29
+ operandTitle: ->
30
+ JST['nodes/operands/basic_block']
31
+ name: @name
32
+
33
+ titleizeInstructions: (previousInstructions) ->
34
+ unless previousInstructions
35
+ result = ""
36
+ result += JST['nodes/diff/unchanged_line'] line: x.title() for x in @instructions
37
+ result
38
+ else
39
+ result = ""
40
+ removed = Object.extended()
41
+ added = Object.extended()
42
+ changed = Object.extended()
43
+ unchanged = Object.extended()
44
+
45
+ for cs, i in @instructions
46
+ previous = previousInstructions.find (ps) -> ps.id == cs.id
47
+ currentTitle = cs.title()
48
+
49
+ if previous && previous.title == currentTitle
50
+ unchanged[i] = previous.title
51
+ previous.newPosition = i
52
+ else if previous
53
+ changed[i] = [previous.title, currentTitle]
54
+ previous.newPosition = i
55
+ else
56
+ added[i] = currentTitle
57
+
58
+ for ps, i in previousInstructions
59
+ if !ps.newPosition?
60
+ position = 0
61
+
62
+ while --i >= 0
63
+ if previousInstructions[i].newPosition?
64
+ position = previousInstructions[i].newPosition+1
65
+ break
66
+
67
+ removed[position] ||= []
68
+ removed[position].push ps.title
69
+
70
+ [@instructions.length, previousInstructions.length].max().times (i) ->
71
+ if removed[i]
72
+ result += JST['nodes/diff/removed_line'](line: l) for l in removed[i]
73
+
74
+ result += JST['nodes/diff/added_line'](line: added[i]) if added[i]
75
+ result += JST['nodes/diff/changed_line'](before: changed[i][0], after:changed[i][1]) if changed[i]
76
+ result += JST['nodes/diff/unchanged_line'](line: unchanged[i]) if unchanged[i]
77
+
78
+ result
79
+
80
+ references: ->
81
+ ids = @instructions.last()?.operands.findAll((x) -> x instanceof BasicBlockNode).map((x) -> x.id)
82
+ (ids || []).exclude((x) => x == @id)
@@ -0,0 +1,9 @@
1
+ class @ConstantNode extends Node
2
+ update: (data, map) ->
3
+ @value = data['value']
4
+ @type = @locate(data['type'], map)
5
+
6
+ operandTitle: ->
7
+ JST['nodes/operands/constant']
8
+ type: @type.title()
9
+ value: @value
@@ -1,10 +1,25 @@
1
- class @FunctionNode
2
- constructor: (@name, @present) ->
3
- @arguments = []
1
+ class @FunctionNode extends Node
2
+ update: (data, map) ->
3
+ @name = data['name']
4
+ @type = @locate(data['return_type'], map)
5
+ @present = false
4
6
 
5
- setArguments: (@arguments) ->
7
+ @arguments = data['argument_ids'].map (id) => @locate(id, map)
6
8
 
7
- setReturnType: (@type) ->
9
+ @reassign @blockIds, data['basic_block_ids'], (removed, added) =>
10
+ removed.each (id) => @locate(id, map).unlinkFunction(@)
11
+ added.each (id) => @locate(id, map).linkFunction(@)
12
+
13
+ @blockIds = data['basic_block_ids']
14
+ @blocks = @blockIds.map (id) => @locate(id, map)
15
+
16
+ linkModule: -> @present = true
17
+ unlinkModule: -> @present = false
18
+
19
+ attachedFunctions: ->
20
+ result = {}
21
+ result[@id] = @
22
+ result
8
23
 
9
24
  title: ->
10
25
  template = if @present then 'nodes/function' else 'nodes/function_removed'
@@ -1,33 +1,53 @@
1
- class @InstructionNode
2
- constructor: ->
3
- @blocks = []
1
+ class @InstructionNode extends Node
2
+ constructor: (data, map) ->
3
+ super
4
+ @blocks = Object.extended()
4
5
 
5
- update: (@opcode, @name, @parameters, @operands, @type) ->
6
+ linkBlock: (block) ->
7
+ @blocks[block.id] = block
8
+ @operands?.each (x) => x.linkBlock(block) if x['linkBlock']?
6
9
 
7
- link: (block, index) ->
8
- block.addInstruction(@, index)
9
- @blocks.add block
10
+ unlinkBlock: (block) ->
11
+ delete @blocks[block.id]
12
+ @operands?.each (x) => x.unlinkBlock(block) if x['unlinkBlock']?
10
13
 
11
- unlink: ->
12
- @blocks.each (x) => x.removeInstruction(@)
13
- @blocks = []
14
+ attachedFunctions: ->
15
+ result = {}
16
+ @blocks.values().each (x) -> Object.merge result, x.attachedFunctions()
17
+ result
14
18
 
15
- title: ->
16
- operands = @operands.map (x) ->
17
- if x instanceof OperandNode
18
- x.title()
19
- else
20
- "%#{x[0]} => #{x[1].title()}"
19
+ update: (data, map) ->
20
+ @type = @locate(data['type'], map)
21
+ @name = data['name']
22
+ @opcode = data['opcode']
23
+ @parameters = data['parameters']
21
24
 
22
- if @type.kind == 'void'
23
- JST['nodes/instruction_void']
24
- opcode: @opcode
25
- parameters: @parameters
26
- operands: operands.join(', ')
25
+ if data['operand_ids']
26
+ @updateOperands(data['operand_ids'], map)
27
27
  else
28
- JST['nodes/instruction_typed']
28
+ @operands = null
29
+
30
+ updateOperands: (data, map) ->
31
+ @operands = data.map (x) => @locate(x, map)
32
+
33
+ title: ->
34
+ if @type && !@type.void()
35
+ JST['nodes/instruction']
29
36
  type: @type.title()
30
37
  name: @name
31
38
  opcode: @opcode
32
39
  parameters: @parameters
33
- operands: operands.join(', ')
40
+ operands: @titleizeOperands()
41
+ else
42
+ JST['nodes/instruction_void']
43
+ opcode: @opcode
44
+ parameters: @parameters
45
+ operands: @titleizeOperands()
46
+
47
+ titleizeOperands: ->
48
+ return "<DETACHED>" unless @operands
49
+ @operands.map((x) -> x.operandTitle()).join(', ')
50
+
51
+ operandTitle: ->
52
+ JST['nodes/operands/instruction']
53
+ name: @name
@@ -0,0 +1,8 @@
1
+ class @ModuleNode extends Node
2
+ update: (data, map) ->
3
+ @reassign @functionIds, data['function_ids'], (removed, added) =>
4
+ removed.each (id) => @locate(id, map).unlinkModule(@)
5
+ added.each (id) => @locate(id, map).linkModule(@)
6
+
7
+ @functionIds = data['function_ids']
8
+ @functions = @functionIds.map (id) => @locate(id, map)
@@ -0,0 +1,10 @@
1
+ class @PhiNode extends InstructionNode
2
+
3
+ updateOperands: (data, map) ->
4
+ @operands = data.map (pair) =>
5
+ pair.map (x) =>
6
+ @locate(x, map)
7
+
8
+ titleizeOperands: (data) ->
9
+ return "<DETACHED>" unless @operands
10
+ @operands.map (pair) => "#{pair[0].operandTitle()} => #{pair[1].operandTitle()}"
@@ -1,12 +1,9 @@
1
- class @TypeNode
1
+ class @TypeNode extends Node
2
2
 
3
- constructor: (@kind, @name, @parameters) ->
3
+ update: (data, map) ->
4
+ @name = data['name']
5
+
6
+ void: () -> false
4
7
 
5
8
  title: ->
6
- switch @kind
7
- when 'void' then JST['nodes/type_constant'](type: 'void')
8
- when 'monotype' then JST['nodes/type_constant'](type: @name)
9
- when 'parametric'
10
- JST['nodes/type_parametric']
11
- type: @name
12
- parameters: @parameters.map((x) -> x.title()).join(', ')
9
+ JST['nodes/type'](type: @name)
@@ -0,0 +1,3 @@
1
+ class @TypeBottomNode extends TypeNode
2
+
3
+ void: () -> true
@@ -0,0 +1 @@
1
+ class @TypeVariableNode extends @TypeNode
@@ -1,5 +1,5 @@
1
1
  module Furnace
2
2
  module Xray
3
- VERSION = '1.1.0.pre1'
3
+ VERSION = '1.1.0.pre2'
4
4
  end
5
5
  end