dtr_core 0.1.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 +7 -0
- data/lib/dtr_core/common.rb +18 -0
- data/lib/dtr_core/contract.rb +20 -0
- data/lib/dtr_core/function.rb +22 -0
- data/lib/dtr_core/number.rb +23 -0
- data/lib/dtr_core/parser.rb +117 -0
- data/lib/dtr_core/state.rb +20 -0
- data/lib/dtr_core/type_validator.rb +43 -0
- data/lib/dtr_core.rb +13 -0
- metadata +52 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6c7633c61c5ed0d1268fb63d2b9245037292c352e850c819e5017fab420c8044
|
4
|
+
data.tar.gz: 7a0dcefa916e3daecefa505c8556e75fe5047e39836a31fe893affa043745f02
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a2de4799a22ec515c6a23ee27e09735f6cd7043832dc3ab79b108ea68c802ddc0ae721ca78c72384712796302a2df55aee0b529c12439430b1ceaf948ee6ad79
|
7
|
+
data.tar.gz: 0b379f38905d1d28ea6d4dc8044622b7598383d1ee3bf627fa70f9c6d25d019506b8ab269bc99561c71bd6548afa969e3ec18621af19372bf4f441c2677b2fcd
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRCore
|
4
|
+
# Common methods used by the DTRCore module.
|
5
|
+
module Common
|
6
|
+
def strip_and_remove_quotes(str)
|
7
|
+
str.strip.gsub(/['"]/, '')
|
8
|
+
end
|
9
|
+
|
10
|
+
def split_strip_select(some_list)
|
11
|
+
some_list&.split("\n")&.map { |x| x&.strip }&.select { |x| x.length.positive? }
|
12
|
+
end
|
13
|
+
|
14
|
+
def first_match_for_content(patterm)
|
15
|
+
content.match(patterm)&.captures&.first
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRCore
|
4
|
+
# Represents a contract in a DTR file.
|
5
|
+
class Contract
|
6
|
+
attr_reader :functions, :name, :state
|
7
|
+
|
8
|
+
def initialize(name, state, functions)
|
9
|
+
@name = name
|
10
|
+
@state = state
|
11
|
+
@functions = functions
|
12
|
+
end
|
13
|
+
|
14
|
+
def ==(other)
|
15
|
+
name == other.name &&
|
16
|
+
state == other.state &&
|
17
|
+
functions == other.functions
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRCore
|
4
|
+
# Represents a state in a DTR file.
|
5
|
+
class Function
|
6
|
+
attr_reader :name, :inputs, :output, :instructions
|
7
|
+
|
8
|
+
def initialize(name, inputs, output, instructions)
|
9
|
+
@name = name
|
10
|
+
@inputs = inputs
|
11
|
+
@output = output
|
12
|
+
@instructions = instructions
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(other)
|
16
|
+
name == other.name &&
|
17
|
+
inputs == other.inputs &&
|
18
|
+
output == other.output &&
|
19
|
+
instructions == other.instructions
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRCore
|
4
|
+
module Number
|
5
|
+
MIN_U32 = 0
|
6
|
+
MAX_U32 = (2**32) - 1
|
7
|
+
|
8
|
+
MIN_U64 = 0
|
9
|
+
MAX_U64 = (2**64) - 1
|
10
|
+
|
11
|
+
MIN_U256 = 0
|
12
|
+
MAX_U256 = (2**256) - 1
|
13
|
+
|
14
|
+
MIN_I32 = -2**31
|
15
|
+
MAX_I32 = (2**31) - 1
|
16
|
+
|
17
|
+
MIN_I64 = -2**63
|
18
|
+
MAX_I64 = (2**63) - 1
|
19
|
+
|
20
|
+
MIN_I256 = -2**255
|
21
|
+
MAX_I256 = (2**255) - 1
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dtr_core/common'
|
4
|
+
|
5
|
+
module DTRCore
|
6
|
+
# Parses a DTR file and returns a Contract object.
|
7
|
+
class Parser
|
8
|
+
include ::DTRCore::Common
|
9
|
+
|
10
|
+
def initialize(file_path)
|
11
|
+
raise "Unable to find file: #{file_path}." unless File.exist?(file_path)
|
12
|
+
|
13
|
+
@content = File.read(file_path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.parse(file_path)
|
17
|
+
new(file_path).parse
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse
|
21
|
+
DTRCore::Contract.new(parse_contract_name_section, parse_state_section, parse_function_section)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :content
|
27
|
+
attr_accessor :sections
|
28
|
+
|
29
|
+
def parse_contract_name_section
|
30
|
+
contract_name_section = first_match_for_content(/\[Contract\]:\s*(.+)/)
|
31
|
+
|
32
|
+
raise 'Missing contract name.' if contract_name_section.nil?
|
33
|
+
|
34
|
+
contract_name_section
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_state_section
|
38
|
+
state_section = first_match_for_content(/\[State\]:\s*((?:\s*\*\s*\[.+?\]\n(?:\s* \* .+\n?)*)*)/)
|
39
|
+
|
40
|
+
return nil if state_section.nil?
|
41
|
+
|
42
|
+
state_definitions = state_section
|
43
|
+
.split(/\n\s*\*\s*\[/).map { |x| "[#{x.strip}" }
|
44
|
+
.map { |definition| state_definition_to_state_object(definition) }
|
45
|
+
|
46
|
+
raise 'Empty state section.' if state_definitions.empty?
|
47
|
+
|
48
|
+
state_definitions
|
49
|
+
end
|
50
|
+
|
51
|
+
def clean_state_definition_name(definition)
|
52
|
+
definition.gsub(/[\*\n\[]/, '').strip
|
53
|
+
end
|
54
|
+
|
55
|
+
def state_definition_to_state_object(definition)
|
56
|
+
name = clean_state_definition_name definition[/^\[([^\]]+)\]/, 1]
|
57
|
+
|
58
|
+
type = definition[/Type:\s*(\w+)/, 1]
|
59
|
+
|
60
|
+
initial_value = DTRCore::TypeValidator.new(type, definition[/Initial Value:\s*(.+)/, 1])
|
61
|
+
.validate_then_coerce_initial_value!
|
62
|
+
|
63
|
+
DTRCore::State.new(name, type, initial_value)
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse_function_section
|
67
|
+
function_section = first_match_for_content(/\[Functions\]:(?<all>.*):\[Functions\]/m)
|
68
|
+
|
69
|
+
return nil if function_section.nil?
|
70
|
+
|
71
|
+
function_definitions = parse_parse_function_section(function_section)
|
72
|
+
|
73
|
+
raise 'Empty function section.' if function_definitions.empty?
|
74
|
+
|
75
|
+
function_definitions
|
76
|
+
end
|
77
|
+
|
78
|
+
def parse_parse_function_section(function_section)
|
79
|
+
function_section.split('-()')
|
80
|
+
.map { |x| function_definition_to_function_object(x.strip.to_s) }
|
81
|
+
.reject { |x| x.name.nil? }
|
82
|
+
end
|
83
|
+
|
84
|
+
def function_definition_to_function_object(definition)
|
85
|
+
name = definition[/\s*\[(?<all>[^\]]+)]/, 1]
|
86
|
+
inputs = format_function_inputs(definition[/Inputs\s*:\s*{\s*(?<inputs>[^}]+)\s*}/, 1])
|
87
|
+
# TODO: check output type
|
88
|
+
output = definition[/Output:\s*(.+)/, 1]
|
89
|
+
instructions = format_function_instruction(definition[/Instructions:\s*\$(?<inputs>[^\$]+)\$/, 1])
|
90
|
+
|
91
|
+
DTRCore::Function.new(name, inputs, output, instructions)
|
92
|
+
end
|
93
|
+
|
94
|
+
def format_function_inputs(inputs)
|
95
|
+
return [] if inputs.nil?
|
96
|
+
|
97
|
+
split_strip_select(inputs).map { |x| { name: x.split(':')[0].strip, type_name: x.split(':')[1].strip } }
|
98
|
+
end
|
99
|
+
|
100
|
+
def format_function_instruction(instructions)
|
101
|
+
split_strip_select(instructions)&.map { |instruction| parse_function_instruction(instruction) }
|
102
|
+
end
|
103
|
+
|
104
|
+
def parse_function_instruction(instruction)
|
105
|
+
{
|
106
|
+
instruction: instruction[/instruction:\s*(?<all>[^\s,]+)/, 1],
|
107
|
+
inputs: parse_function_instruction_input(instruction),
|
108
|
+
assign: instruction[/\s*assign:\s*(?<all>[^\s\,]+)/, 1]
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
def parse_function_instruction_input(definition)
|
113
|
+
definition[/\s*input:\s*\((?<all>[^\)]+)\)/, 1]
|
114
|
+
&.split(',')&.map(&:strip)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRCore
|
4
|
+
# Represents a state in a DTR file.
|
5
|
+
class State
|
6
|
+
attr_reader :name, :type, :initial_value
|
7
|
+
|
8
|
+
def initialize(name, type, initial_value)
|
9
|
+
@name = name
|
10
|
+
@type = type
|
11
|
+
@initial_value = initial_value
|
12
|
+
end
|
13
|
+
|
14
|
+
def ==(other)
|
15
|
+
name == other.name &&
|
16
|
+
type == other.type &&
|
17
|
+
initial_value == other.initial_value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dtr_core/common'
|
4
|
+
|
5
|
+
module DTRCore
|
6
|
+
# Type validator for DTR types.
|
7
|
+
class TypeValidator
|
8
|
+
include ::DTRCore::Common
|
9
|
+
|
10
|
+
def initialize(type_name, initial_value)
|
11
|
+
@type_name = type_name
|
12
|
+
@initial_value = initial_value
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate_then_coerce_initial_value!
|
16
|
+
raise 'Missing Type Name.' if @type_name.nil?
|
17
|
+
raise 'Missing Initial Value.' if @initial_value.nil?
|
18
|
+
|
19
|
+
case @type_name
|
20
|
+
when 'I32', 'I64', 'I256', 'U32', 'U64', 'U256'
|
21
|
+
validate_numeric!
|
22
|
+
|
23
|
+
# TODO: check type
|
24
|
+
when 'Symbol'
|
25
|
+
strip_and_remove_quotes(@initial_value)
|
26
|
+
else
|
27
|
+
raise 'Missing Invalid Type Name.'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def validate_numeric!
|
34
|
+
raise 'Invalid initial value for type. Wrong type.' unless @initial_value =~ (/^[\-\.\d]\d*(\.?\d*)*/)
|
35
|
+
|
36
|
+
raise "Invalid initial value for type #{@type_name}. Out of range." unless @initial_value.to_i.between?(
|
37
|
+
DTRCore::Number.const_get(:"MIN_#{@type_name}"), DTRCore::Number.const_get(:"MAX_#{@type_name}")
|
38
|
+
)
|
39
|
+
|
40
|
+
@initial_value.to_i
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/dtr_core.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Core logic for consuming Digicus Textual Representation (DTR) files.
|
4
|
+
module DTRCore
|
5
|
+
autoload :Contract, 'dtr_core/contract'
|
6
|
+
autoload :Function, 'dtr_core/function'
|
7
|
+
autoload :Number, 'dtr_core/number'
|
8
|
+
autoload :Parser, 'dtr_core/parser'
|
9
|
+
autoload :State, 'dtr_core/state'
|
10
|
+
autoload :TypeValidator, 'dtr_core/type_validator'
|
11
|
+
|
12
|
+
VERSION = '0.1.0'
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dtr_core
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rob Durst
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-04-22 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A longer description of my_gem
|
14
|
+
email:
|
15
|
+
- me@robdurst.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/dtr_core.rb
|
21
|
+
- lib/dtr_core/common.rb
|
22
|
+
- lib/dtr_core/contract.rb
|
23
|
+
- lib/dtr_core/function.rb
|
24
|
+
- lib/dtr_core/number.rb
|
25
|
+
- lib/dtr_core/parser.rb
|
26
|
+
- lib/dtr_core/state.rb
|
27
|
+
- lib/dtr_core/type_validator.rb
|
28
|
+
homepage:
|
29
|
+
licenses:
|
30
|
+
- MIT
|
31
|
+
metadata:
|
32
|
+
rubygems_mfa_required: 'true'
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 3.2.0
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubygems_version: 3.4.10
|
49
|
+
signing_key:
|
50
|
+
specification_version: 4
|
51
|
+
summary: A short summary of my_gem
|
52
|
+
test_files: []
|