dtr_core 0.9.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/dtr_core/contract.rb +5 -5
- data/lib/dtr_core/function.rb +2 -1
- data/lib/dtr_core/graph/lcpbt_forrest.rb +60 -0
- data/lib/dtr_core/graph/left_child_preferential_binary_tree.rb +67 -0
- data/lib/dtr_core/graph/silviculturist.rb +103 -0
- data/lib/dtr_core/instruction.rb +10 -6
- data/lib/dtr_core.rb +7 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec65bed75c4955e0c231146f532fd7d1c35ed2e7617966681dce5718076ba0be
|
4
|
+
data.tar.gz: a192a2cc58e2b4dbdd6bae900751675236d1532fc869676badc0b79a043a33e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 703ec3bd6c1ffd80d0f872bd13351467819daa7dfd42737c33f90402fd66f11026e1d902e4e186449cdd913d4ee2db8489ccdb4b7afcb691f43c7c4cb4c2156e
|
7
|
+
data.tar.gz: 5a7fc13e8418ea5917ffa8aa70855922f920750e8b9ee6bde1b0d910daecbb567cf058ce3b819f2cdae4fff8ecd41858a89936c207693456e46b17a7db404386
|
data/lib/dtr_core/contract.rb
CHANGED
@@ -55,31 +55,31 @@ module DTRCore
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def state_to_s
|
58
|
-
return '' if @state.nil?
|
58
|
+
return '' if @state.nil? || @state.empty?
|
59
59
|
|
60
60
|
"[State]:\n#{@state&.map(&:to_s)&.join("\n")}\n:[State]\n"
|
61
61
|
end
|
62
62
|
|
63
63
|
def interface_to_s
|
64
|
-
return '' if @
|
64
|
+
return '' if @interface.nil? || @interface.empty?
|
65
65
|
|
66
66
|
"[Interface]:\n#{@interface&.map(&:to_s)&.join("\n")}\n:[Interface]\n"
|
67
67
|
end
|
68
68
|
|
69
69
|
def user_defined_types_to_s
|
70
|
-
return '' if @user_defined_types.nil?
|
70
|
+
return '' if @user_defined_types.nil? || @user_defined_types.empty?
|
71
71
|
|
72
72
|
"[User Defined Types]:\n#{@user_defined_types&.map(&:to_s)&.join("\n")}\n:[User Defined Types]\n"
|
73
73
|
end
|
74
74
|
|
75
75
|
def helpers_to_s
|
76
|
-
return '' if @helpers.nil?
|
76
|
+
return '' if @helpers.nil? || @helpers.empty?
|
77
77
|
|
78
78
|
"[Helpers]:\n#{@helpers&.map(&:to_s)&.join("\n")}\n:[Helpers]\n"
|
79
79
|
end
|
80
80
|
|
81
81
|
def non_translatables_to_s
|
82
|
-
return '' if @non_translatables.nil?
|
82
|
+
return '' if @non_translatables.nil? || @non_translatables.empty?
|
83
83
|
|
84
84
|
"[NonTranslatable]:\n#{@non_translatables}\n:[NonTranslatable]"
|
85
85
|
end
|
data/lib/dtr_core/function.rb
CHANGED
@@ -98,7 +98,8 @@ module DTRCore
|
|
98
98
|
instruction[/instruction:\s*(?<all>[^\s,]+)/, 1],
|
99
99
|
parse_function_instruction_input(instruction),
|
100
100
|
instruction[/\s*assign:\s*\[?(?<all>[^\s\,\]]+)\]?/, 1],
|
101
|
-
instruction[/\s*scope:\s*(?<all>[^\s\,]+)/, 1].to_i || 0
|
101
|
+
instruction[/\s*scope:\s*(?<all>[^\s\,]+)/, 1].to_i || 0,
|
102
|
+
instruction[/\sid:\s*(?<all>[^\s,]+)/, 1].to_i || 0
|
102
103
|
)
|
103
104
|
|
104
105
|
raise "Invalid instruction: #{instruction}" unless instruction.valid?
|
@@ -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/instruction.rb
CHANGED
@@ -3,26 +3,29 @@
|
|
3
3
|
module DTRCore
|
4
4
|
# Instruction class
|
5
5
|
class Instruction
|
6
|
-
attr_reader :instruction, :inputs, :assign, :scope
|
6
|
+
attr_reader :instruction, :inputs, :assign, :scope, :id
|
7
7
|
|
8
|
-
def initialize(instruction, inputs, assign, scope)
|
8
|
+
def initialize(instruction, inputs, assign, scope, id)
|
9
9
|
@instruction = instruction
|
10
10
|
@inputs = inputs
|
11
11
|
@assign = assign
|
12
12
|
@scope = scope
|
13
|
+
@id = id
|
13
14
|
end
|
14
15
|
|
15
16
|
def ==(other)
|
16
17
|
instruction == other.instruction &&
|
17
18
|
inputs == other.inputs &&
|
18
19
|
assign == other.assign &&
|
19
|
-
scope == other.scope
|
20
|
+
scope == other.scope &&
|
21
|
+
id == other.id
|
20
22
|
end
|
21
23
|
|
22
24
|
def to_s
|
23
|
-
|
25
|
+
assignment = @assign.nil? ? '' : "assign: #{@assign}, "
|
26
|
+
"{ id: #{id}, instruction: #{instruction}, " \
|
24
27
|
"input: (#{inputs&.join(', ')}), " \
|
25
|
-
"
|
28
|
+
"#{assignment}scope: #{scope} }"
|
26
29
|
end
|
27
30
|
|
28
31
|
def to_json(*_args)
|
@@ -30,7 +33,8 @@ module DTRCore
|
|
30
33
|
instruction:,
|
31
34
|
inputs:,
|
32
35
|
assign:,
|
33
|
-
scope
|
36
|
+
scope:,
|
37
|
+
id:
|
34
38
|
}.to_json
|
35
39
|
end
|
36
40
|
|
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.
|
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-
|
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
|