dtr_core 0.10.0 → 0.11.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ad7236ff8c846c7126d0d8e53f3d7cd5d6635eeefbca857dafdf22e85473cbe6
4
- data.tar.gz: d8741a66894615c02d59be5ba8884f165acdcfdb045c2243c07c57c3116cb699
3
+ metadata.gz: ec65bed75c4955e0c231146f532fd7d1c35ed2e7617966681dce5718076ba0be
4
+ data.tar.gz: a192a2cc58e2b4dbdd6bae900751675236d1532fc869676badc0b79a043a33e7
5
5
  SHA512:
6
- metadata.gz: 83a20837017ec8a60ae948918f6b1947332516248bac6f805bdfc12b7b2a5636d5f01157739c81167113a873218da6cf55b22c297e1903718c9913b29322f2f7
7
- data.tar.gz: 42b2bd3b5ef207d88fe3a955a9358ea54270979115df12e10d2318d6d230c80e8d858979d9d91df91bd2158153dd93f0d2e8efd15e0e27c4f261dee6432d660d
6
+ metadata.gz: 703ec3bd6c1ffd80d0f872bd13351467819daa7dfd42737c33f90402fd66f11026e1d902e4e186449cdd913d4ee2db8489ccdb4b7afcb691f43c7c4cb4c2156e
7
+ data.tar.gz: 5a7fc13e8418ea5917ffa8aa70855922f920750e8b9ee6bde1b0d910daecbb567cf058ce3b819f2cdae4fff8ecd41858a89936c207693456e46b17a7db404386
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DTRCore
4
+ module Graph
5
+ class LCPBT_Forrest
6
+ attr_accessor :trees
7
+
8
+ def initialize
9
+ @trees = []
10
+ end
11
+
12
+ def add_tree(tree)
13
+ @trees << tree
14
+ end
15
+
16
+ def traverse
17
+ @trees.map(&:traverse)
18
+ end
19
+
20
+ def traverse_with_indentation
21
+ @trees.map(&:traverse_with_indentation)
22
+ end
23
+
24
+ # This represents a traversal through a unique path, covering all trees in the forest
25
+ # only once. This is useful for code generation.
26
+ def traverse_to_ids
27
+ id_map = {}
28
+ result = []
29
+
30
+ traverse
31
+ .map { |x| x.map(&:id) }
32
+ .each do |x|
33
+ sub_result = []
34
+ x.each do |y|
35
+ next if id_map[y]
36
+
37
+ sub_result << y
38
+ id_map[y] = true
39
+ end
40
+ result << sub_result
41
+ end
42
+
43
+ result
44
+ end
45
+
46
+ def code_generator_traverse(&block)
47
+ traverse_with_indentation
48
+ .map { |tree| tree.reverse.uniq.reverse.map(&block) }
49
+ end
50
+
51
+ def size
52
+ @trees.size
53
+ end
54
+
55
+ def all_paths_to(instruction_id)
56
+ @trees.map { |x| x.all_paths_to(instruction_id) }.flatten(1).compact
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module DTRCore
6
+ module Graph
7
+ class LeftChildPreferentialBinaryTree
8
+ attr_accessor :value, :left_child, :right_child, :tree_id
9
+
10
+ def initialize(value, indentation: 0)
11
+ @tree_id = SecureRandom.uuid
12
+ @indentation = indentation
13
+ @value = value
14
+ @left_child = nil
15
+ @right_child = nil
16
+ end
17
+
18
+ def set_left_child(node)
19
+ raise 'Left child already exists' if @left_child
20
+
21
+ @left_child = node
22
+ end
23
+
24
+ def set_right_child(node)
25
+ raise 'Right child already exists' if @right_child
26
+
27
+ @right_child = node
28
+ end
29
+
30
+ def traverse
31
+ result = []
32
+ result << @value
33
+ result += @left_child.traverse if @left_child
34
+ result += @right_child.traverse if @right_child
35
+ result
36
+ end
37
+
38
+ def traverse_with_indentation
39
+ result = []
40
+ result << [@value, @indentation]
41
+ result += @left_child.traverse_with_indentation if @left_child
42
+ result += @right_child.traverse_with_indentation if @right_child
43
+ result
44
+ end
45
+
46
+ def all_paths_to(instruction_id, cur_result: [])
47
+ if value.id == instruction_id
48
+ return cur_result.empty? ? [[instruction_id]] : cur_result + [instruction_id]
49
+ end
50
+
51
+ result = nil
52
+
53
+ if @left_child
54
+ left_child_traverse = @left_child.all_paths_to(instruction_id, cur_result: cur_result + [value.id])
55
+ result = left_child_traverse unless left_child_traverse.nil?
56
+ end
57
+
58
+ if @right_child
59
+ right_child_traverse = @right_child.all_paths_to(instruction_id, cur_result: cur_result + [value.id])
60
+ result = result.nil? ? right_child_traverse : [result, right_child_traverse]
61
+ end
62
+
63
+ result
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DTRCore
4
+ module Graph
5
+ class Silviculturist
6
+ attr_accessor :forrest
7
+
8
+ def initialize(instructions)
9
+ @instructions = instructions
10
+ @forrest = LCPBT_Forrest.new
11
+ @seen_instructions = {}
12
+ end
13
+
14
+ def make_forrest
15
+ index = 0
16
+ while index < @instructions.size
17
+ instructions = @instructions[index..]
18
+ scope = 0
19
+ tree = plant_trees(scope, instructions)
20
+ @forrest.add_tree(tree)
21
+
22
+ seen = true
23
+ while seen && index < @instructions.size
24
+ index += 1
25
+ seen = @instructions[index].nil? || @seen_instructions[@instructions[index].id]
26
+ end
27
+ end
28
+ end
29
+
30
+ def plant_trees(scope, instructions, from_id: nil, indentation: 0)
31
+ cur_instruction = instructions[0]
32
+
33
+ return nil if cur_instruction.nil?
34
+
35
+ if cur_instruction.scope != scope
36
+ return plant_trees(scope, instructions[1..], from_id: cur_instruction.id,
37
+ indentation:)
38
+ end
39
+
40
+ return @seen_instructions[cur_instruction.id] if @seen_instructions[cur_instruction.id]
41
+
42
+ down_jump = cur_instruction.instruction == 'jump' && (
43
+ (cur_instruction.inputs.size == 1 && cur_instruction.inputs[0].to_i < scope) ||
44
+ (cur_instruction.inputs.size == 2 && cur_instruction.inputs[1].to_i < scope))
45
+
46
+ rest_of_instructions = instructions[1..]
47
+
48
+ tree = LeftChildPreferentialBinaryTree.new(cur_instruction,
49
+ indentation: if down_jump
50
+ indentation - 1
51
+ else
52
+ indentation
53
+ end)
54
+ @seen_instructions[cur_instruction.id] = tree
55
+
56
+ case cur_instruction.instruction
57
+ when 'jump'
58
+ case cur_instruction.inputs.size
59
+ # unconditional jump
60
+ when 1
61
+ new_scope = cur_instruction.inputs[0].to_i
62
+
63
+ # halt when going back to 0
64
+ return tree if new_scope.zero?
65
+
66
+ tree.set_left_child(plant_trees(new_scope, rest_of_instructions, from_id: cur_instruction.id,
67
+ indentation: down_jump ? indentation - 1 : indentation + 1))
68
+ # conditional jump
69
+ when 2
70
+ # detour
71
+ new_scope = cur_instruction.inputs[1].to_i
72
+
73
+ tree.set_left_child(plant_trees(new_scope, rest_of_instructions,
74
+ from_id: cur_instruction.id, indentation: down_jump ? indentation - 1 : indentation + 1))
75
+ # continue
76
+ tree.set_right_child(plant_trees(scope, rest_of_instructions, from_id: cur_instruction.id,
77
+ indentation:))
78
+ # if-let
79
+ when 3
80
+ raise 'We do not yet support if-let statements'
81
+ end
82
+ # the way a goto works is that you want to drop out of the loop back to the scope you were at
83
+ # when you started the loop
84
+ when 'goto'
85
+ goto_target_id = cur_instruction.inputs[0].to_i
86
+ return_scope = @instructions.find { |x| x.id == goto_target_id }.scope
87
+
88
+ return tree if return_scope.zero?
89
+
90
+ # TODO: fix indentation
91
+ tree.set_left_child(plant_trees(return_scope.to_i, rest_of_instructions, from_id: cur_instruction.id,
92
+ indentation:))
93
+ else
94
+ # left_child
95
+ tree.set_left_child(plant_trees(scope, rest_of_instructions, from_id: cur_instruction.id,
96
+ indentation:))
97
+ end
98
+
99
+ tree
100
+ end
101
+ end
102
+ end
103
+ end
data/lib/dtr_core.rb CHANGED
@@ -12,4 +12,11 @@ module DTRCore
12
12
  autoload :InstructionValidator, 'dtr_core/instruction_validator'
13
13
  autoload :Instruction, 'dtr_core/instruction'
14
14
  autoload :UserDefinedType, 'dtr_core/user_defined_type'
15
+
16
+ # A graph is a collection of nodes and edges representing the structure of a DTR file.
17
+ module Graph
18
+ autoload :LCPBT_Forrest, 'dtr_core/graph/lcpbt_forrest'
19
+ autoload :LeftChildPreferentialBinaryTree, 'dtr_core/graph/left_child_preferential_binary_tree'
20
+ autoload :Silviculturist, 'dtr_core/graph/silviculturist'
21
+ end
15
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dtr_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Durst
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-09 00:00:00.000000000 Z
11
+ date: 2024-07-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Core smart contract intermediate language (Digicus Textual Representation)
14
14
  parser.
@@ -22,6 +22,9 @@ files:
22
22
  - lib/dtr_core/common.rb
23
23
  - lib/dtr_core/contract.rb
24
24
  - lib/dtr_core/function.rb
25
+ - lib/dtr_core/graph/lcpbt_forrest.rb
26
+ - lib/dtr_core/graph/left_child_preferential_binary_tree.rb
27
+ - lib/dtr_core/graph/silviculturist.rb
25
28
  - lib/dtr_core/instruction.rb
26
29
  - lib/dtr_core/instruction_validator.rb
27
30
  - lib/dtr_core/number.rb