grumlin 0.15.3 → 0.16.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 +4 -4
- data/.rubocop.yml +10 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +2 -2
- data/README.md +4 -0
- data/Rakefile +21 -3
- data/lib/definitions.yml +114 -0
- data/lib/grumlin/action.rb +124 -0
- data/lib/grumlin/client.rb +2 -2
- data/lib/grumlin/expressions/operator.rb +1 -1
- data/lib/grumlin/expressions/order.rb +1 -1
- data/lib/grumlin/expressions/p.rb +12 -17
- data/lib/grumlin/expressions/pop.rb +1 -1
- data/lib/grumlin/expressions/scope.rb +1 -1
- data/lib/grumlin/expressions/t.rb +1 -1
- data/lib/grumlin/expressions/text_p.rb +15 -0
- data/lib/grumlin/expressions/with_options.rb +17 -14
- data/lib/grumlin/repository.rb +2 -2
- data/lib/grumlin/shortcut.rb +27 -0
- data/lib/grumlin/shortcuts/properties.rb +6 -2
- data/lib/grumlin/shortcuts.rb +15 -13
- data/lib/grumlin/shortcuts_applyer.rb +48 -0
- data/lib/grumlin/step_data.rb +18 -0
- data/lib/grumlin/steps.rb +77 -0
- data/lib/grumlin/steps_serializers/bytecode.rb +65 -0
- data/lib/grumlin/steps_serializers/human_readable_bytecode.rb +36 -0
- data/lib/grumlin/steps_serializers/serializer.rb +16 -0
- data/lib/grumlin/steps_serializers/string.rb +42 -0
- data/lib/grumlin/sugar.rb +4 -4
- data/lib/grumlin/traversal_start.rb +51 -0
- data/lib/grumlin/typed_value.rb +0 -15
- data/lib/grumlin/version.rb +1 -1
- data/lib/grumlin.rb +6 -4
- metadata +14 -8
- data/lib/grumlin/anonymous_step.rb +0 -49
- data/lib/grumlin/bytecode.rb +0 -70
- data/lib/grumlin/expressions/u.rb +0 -19
- data/lib/grumlin/shortcut_proxy.rb +0 -53
- data/lib/grumlin/step.rb +0 -43
- data/lib/grumlin/traversal.rb +0 -37
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
class ShortcutsApplyer
|
5
|
+
class << self
|
6
|
+
def call(steps)
|
7
|
+
new.call(steps)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(steps)
|
12
|
+
return steps unless steps.uses_shortcuts?
|
13
|
+
|
14
|
+
shortcuts = steps.shortcuts
|
15
|
+
|
16
|
+
configuration_steps = process_steps(steps.configuration_steps, shortcuts)
|
17
|
+
regular_steps = process_steps(steps.steps, shortcuts)
|
18
|
+
|
19
|
+
Steps.new(shortcuts).tap do |processed_steps|
|
20
|
+
(configuration_steps + regular_steps).each do |step|
|
21
|
+
processed_steps.add(step.name, step.arguments)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def process_steps(steps, shortcuts) # rubocop:disable Metrics/AbcSize
|
29
|
+
steps.each_with_object([]) do |step, result|
|
30
|
+
arguments = step.arguments.map do |arg|
|
31
|
+
arg.is_a?(Steps) ? ShortcutsApplyer.call(arg) : arg
|
32
|
+
end
|
33
|
+
|
34
|
+
if shortcuts.include?(step.name)
|
35
|
+
t = TraversalStart.new(shortcuts)
|
36
|
+
action = shortcuts[step.name].apply(t, *arguments)
|
37
|
+
next if action.nil? || action == t # Shortcut did not add any steps
|
38
|
+
|
39
|
+
new_steps = ShortcutsApplyer.call(Steps.from(action))
|
40
|
+
result.concat(new_steps.configuration_steps)
|
41
|
+
result.concat(new_steps.steps)
|
42
|
+
else
|
43
|
+
result << StepData.new(step.name, arguments)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
class StepData
|
5
|
+
attr_reader :name, :arguments
|
6
|
+
|
7
|
+
def initialize(name, arguments)
|
8
|
+
@name = name
|
9
|
+
@arguments = arguments
|
10
|
+
end
|
11
|
+
|
12
|
+
def ==(other)
|
13
|
+
self.class == other.class &&
|
14
|
+
@name == other.name &&
|
15
|
+
@arguments == other.arguments
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
class Steps
|
5
|
+
CONFIGURATION_STEPS = Action::CONFIGURATION_STEPS
|
6
|
+
ALL_STEPS = Action::ALL_STEPS
|
7
|
+
|
8
|
+
def self.from(action)
|
9
|
+
raise ArgumentError, "expected: #{Action}, given: #{action.class}" unless action.is_a?(Action)
|
10
|
+
|
11
|
+
shortcuts = action.shortcuts
|
12
|
+
actions = []
|
13
|
+
|
14
|
+
until action.nil?
|
15
|
+
actions.unshift(action)
|
16
|
+
action = action.previous_step
|
17
|
+
end
|
18
|
+
|
19
|
+
new(shortcuts).tap do |chain|
|
20
|
+
actions.each do |act|
|
21
|
+
chain.add(act.name, act.arguments)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :configuration_steps, :steps, :shortcuts
|
27
|
+
|
28
|
+
def initialize(shortcuts, configuration_steps: [], steps: [])
|
29
|
+
@shortcuts = shortcuts
|
30
|
+
@configuration_steps = configuration_steps
|
31
|
+
@steps = steps
|
32
|
+
end
|
33
|
+
|
34
|
+
def add(name, arguments)
|
35
|
+
return add_configuration_step(name, arguments) if CONFIGURATION_STEPS.include?(name)
|
36
|
+
|
37
|
+
StepData.new(name, cast_arguments(arguments)).tap do |step|
|
38
|
+
@steps << step
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def uses_shortcuts?
|
43
|
+
shortcuts?(@configuration_steps) || shortcuts?(@steps)
|
44
|
+
end
|
45
|
+
|
46
|
+
def ==(other)
|
47
|
+
self.class == other.class &&
|
48
|
+
@shortcuts == other.shortcuts &&
|
49
|
+
@configuration_steps == other.configuration_steps &&
|
50
|
+
@steps == other.steps
|
51
|
+
end
|
52
|
+
|
53
|
+
# TODO: add #bytecode, to_s, inspect
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def shortcuts?(steps_ary)
|
58
|
+
steps_ary.any? do |step|
|
59
|
+
@shortcuts.include?(step.name) || step.arguments.any? do |arg|
|
60
|
+
arg.is_a?(Steps) ? arg.uses_shortcuts? : false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_configuration_step(name, arguments)
|
66
|
+
raise ArgumentError, "cannot use configuration steps after start step was used" unless @steps.empty?
|
67
|
+
|
68
|
+
StepData.new(name, cast_arguments(arguments)).tap do |step|
|
69
|
+
@configuration_steps << step
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def cast_arguments(arguments)
|
74
|
+
arguments.map { |arg| arg.is_a?(Action) ? Steps.from(arg) : arg }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
module StepsSerializers
|
5
|
+
class Bytecode < Serializer
|
6
|
+
# constructor params: no_return: true|false, default false
|
7
|
+
# TODO: add pretty
|
8
|
+
|
9
|
+
NONE_STEP = StepData.new("none", [])
|
10
|
+
|
11
|
+
def serialize
|
12
|
+
steps = ShortcutsApplyer.call(@steps)
|
13
|
+
no_return = @params[:no_return] || false
|
14
|
+
|
15
|
+
{
|
16
|
+
step: (steps.steps + (no_return ? [NONE_STEP] : [])).map { |s| serialize_step(s) }
|
17
|
+
}.tap do |v|
|
18
|
+
v.merge!(source: steps.configuration_steps.map { |s| serialize_step(s) }) if steps.configuration_steps.any?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def serialize_step(step)
|
25
|
+
[step.name, *step.arguments.map { |arg| serialize_arg(arg) }]
|
26
|
+
end
|
27
|
+
|
28
|
+
def serialize_arg(arg)
|
29
|
+
return serialize_typed_value(arg) if arg.is_a?(TypedValue)
|
30
|
+
return serialize_predicate(arg) if arg.is_a?(Expressions::P::Predicate)
|
31
|
+
return arg.value if arg.is_a?(Expressions::WithOptions)
|
32
|
+
|
33
|
+
return arg unless arg.is_a?(Steps)
|
34
|
+
|
35
|
+
{ :@type => "g:Bytecode", :@value => Bytecode.new(arg, **@params.merge(no_return: false)).serialize }
|
36
|
+
end
|
37
|
+
|
38
|
+
def serialize_typed_value(value)
|
39
|
+
return value.value if value.type.nil?
|
40
|
+
|
41
|
+
{
|
42
|
+
"@type": "g:#{value.type}",
|
43
|
+
"@value": value.value
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def serialize_predicate(value)
|
48
|
+
{
|
49
|
+
"@type": "g:#{value.namespace}",
|
50
|
+
"@value": {
|
51
|
+
predicate: value.name,
|
52
|
+
value: if value.type.nil?
|
53
|
+
value.value
|
54
|
+
else
|
55
|
+
{
|
56
|
+
"@type": "g:#{value.type}",
|
57
|
+
"@value": value.value
|
58
|
+
}
|
59
|
+
end
|
60
|
+
}
|
61
|
+
}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
module StepsSerializers
|
5
|
+
class HumanReadableBytecode < Serializer
|
6
|
+
def serialize
|
7
|
+
steps = ShortcutsApplyer.call(@steps)
|
8
|
+
[serialize_steps(steps.configuration_steps), serialize_steps(steps.steps)]
|
9
|
+
end
|
10
|
+
|
11
|
+
def serialize_steps(steps)
|
12
|
+
steps.map { |s| serialize_step(s) }
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def serialize_step(step)
|
18
|
+
[step.name, *step.arguments.map { |arg| serialize_arg(arg) }]
|
19
|
+
end
|
20
|
+
|
21
|
+
def serialize_arg(arg)
|
22
|
+
return arg.to_s if arg.is_a?(TypedValue)
|
23
|
+
return serialize_predicate(arg) if arg.is_a?(Expressions::P::Predicate)
|
24
|
+
return arg.value if arg.is_a?(Expressions::WithOptions)
|
25
|
+
|
26
|
+
return arg unless arg.is_a?(Steps)
|
27
|
+
|
28
|
+
HumanReadableBytecode.new(arg, **@params.merge(no_return: false)).serialize[1]
|
29
|
+
end
|
30
|
+
|
31
|
+
def serialize_predicate(arg)
|
32
|
+
"#{arg.name}(#{arg.value})"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
module StepsSerializers
|
5
|
+
class String < Serializer
|
6
|
+
# constructor params: apply_shortcuts: true|false, default: false
|
7
|
+
# constructor params: anonymous: true|false, default: false
|
8
|
+
# TODO: add pretty
|
9
|
+
|
10
|
+
def serialize
|
11
|
+
steps = @params[:apply_shortcuts] ? ShortcutsApplyer.call(@steps) : @steps
|
12
|
+
|
13
|
+
configuration_steps = serialize_steps(steps.configuration_steps)
|
14
|
+
regular_steps = serialize_steps(steps.steps)
|
15
|
+
|
16
|
+
"#{prefix}.#{(configuration_steps + regular_steps).join(".")}"
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def prefix
|
22
|
+
@prefix ||= @params[:anonymous] ? "__" : "g"
|
23
|
+
end
|
24
|
+
|
25
|
+
def serialize_arg(arg)
|
26
|
+
return "\"#{arg}\"" if arg.is_a?(::String) || arg.is_a?(Symbol)
|
27
|
+
return "#{arg.type}.#{arg.value}" if arg.is_a?(Grumlin::TypedValue)
|
28
|
+
return arg.to_s if arg.is_a?(Grumlin::Expressions::WithOptions)
|
29
|
+
|
30
|
+
return arg unless arg.is_a?(Steps)
|
31
|
+
|
32
|
+
StepsSerializers::String.new(arg, anonymous: true, **@params).serialize
|
33
|
+
end
|
34
|
+
|
35
|
+
def serialize_steps(steps)
|
36
|
+
steps.map do |step|
|
37
|
+
"#{step.name}(#{step.arguments.map { |a| serialize_arg(a) }.join(", ")})"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/grumlin/sugar.rb
CHANGED
@@ -6,12 +6,12 @@ module Grumlin
|
|
6
6
|
base.include(Grumlin::Expressions)
|
7
7
|
end
|
8
8
|
|
9
|
-
def __
|
10
|
-
Grumlin::
|
9
|
+
def __(shortcuts = {})
|
10
|
+
Grumlin::TraversalStart.new(shortcuts) # TODO: allow only regular and start steps
|
11
11
|
end
|
12
12
|
|
13
|
-
def g
|
14
|
-
Grumlin::
|
13
|
+
def g(shortcuts = {})
|
14
|
+
Grumlin::TraversalStart.new(shortcuts)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
class TraversalStart
|
5
|
+
START_STEPS = Grumlin.definitions.dig(:steps, :start).map(&:to_sym).freeze
|
6
|
+
REGULAR_STEPS = Grumlin.definitions.dig(:steps, :regular).map(&:to_sym).freeze
|
7
|
+
CONFIGURATION_STEPS = Grumlin.definitions.dig(:steps, :configuration).map(&:to_sym).freeze
|
8
|
+
|
9
|
+
ALL_STEPS = START_STEPS + CONFIGURATION_STEPS + REGULAR_STEPS
|
10
|
+
|
11
|
+
ALL_STEPS.each do |step|
|
12
|
+
define_method step do |*args, **params|
|
13
|
+
step(step, *args, **params)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :shortcuts
|
18
|
+
|
19
|
+
def initialize(shortcuts)
|
20
|
+
@shortcuts = shortcuts
|
21
|
+
end
|
22
|
+
|
23
|
+
def step(name, *args, **params)
|
24
|
+
Action.new(name, args: args, params: params, shortcuts: @shortcuts)
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_missing(name, *args, **params)
|
28
|
+
return step(name, *args, **params) if @shortcuts.key?(name)
|
29
|
+
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def __
|
34
|
+
TraversalStart.new(@shortcuts) # TODO: allow only regular and start steps
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s(*)
|
38
|
+
self.class.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
def inspect
|
42
|
+
self.class.inspect
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def respond_to_missing?(name, _include_private = false)
|
48
|
+
@shortcuts.key?(name)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/grumlin/typed_value.rb
CHANGED
@@ -9,17 +9,6 @@ module Grumlin
|
|
9
9
|
@value = value
|
10
10
|
end
|
11
11
|
|
12
|
-
def to_bytecode
|
13
|
-
@to_bytecode ||= if type.nil?
|
14
|
-
value
|
15
|
-
else
|
16
|
-
{
|
17
|
-
"@type": "g:#{type}",
|
18
|
-
"@value": value
|
19
|
-
}
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
12
|
def inspect
|
24
13
|
"<#{type}.#{value}>"
|
25
14
|
end
|
@@ -27,9 +16,5 @@ module Grumlin
|
|
27
16
|
def to_s
|
28
17
|
inspect
|
29
18
|
end
|
30
|
-
|
31
|
-
def to_readable_bytecode
|
32
|
-
inspect
|
33
|
-
end
|
34
19
|
end
|
35
20
|
end
|
data/lib/grumlin/version.rb
CHANGED
data/lib/grumlin.rb
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
require "securerandom"
|
4
4
|
require "oj"
|
5
|
+
require "yaml"
|
5
6
|
|
7
|
+
# TODO: use Oj directly
|
6
8
|
Oj.mimic_JSON
|
7
9
|
Oj.add_to_json
|
8
10
|
|
@@ -108,10 +110,6 @@ module Grumlin
|
|
108
110
|
end
|
109
111
|
end
|
110
112
|
|
111
|
-
def self.supported_steps
|
112
|
-
@supported_steps ||= (Grumlin::AnonymousStep::SUPPORTED_STEPS + Grumlin::Expressions::U::SUPPORTED_STEPS).sort.uniq
|
113
|
-
end
|
114
|
-
|
115
113
|
@pool_mutex = Mutex.new
|
116
114
|
|
117
115
|
class << self
|
@@ -145,6 +143,10 @@ module Grumlin
|
|
145
143
|
Thread.current.thread_variable_set(:grumlin_default_pool, nil)
|
146
144
|
end
|
147
145
|
end
|
146
|
+
|
147
|
+
def definitions
|
148
|
+
@definitions ||= YAML.safe_load(File.read(File.join(__dir__, "definitions.yml")), symbolize_names: true)
|
149
|
+
end
|
148
150
|
end
|
149
151
|
end
|
150
152
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grumlin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gleb Sinyavskiy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-pool
|
@@ -96,9 +96,9 @@ files:
|
|
96
96
|
- gremlin_server/tinkergraph-empty.properties
|
97
97
|
- grumlin.gemspec
|
98
98
|
- lib/async/channel.rb
|
99
|
+
- lib/definitions.yml
|
99
100
|
- lib/grumlin.rb
|
100
|
-
- lib/grumlin/
|
101
|
-
- lib/grumlin/bytecode.rb
|
101
|
+
- lib/grumlin/action.rb
|
102
102
|
- lib/grumlin/client.rb
|
103
103
|
- lib/grumlin/edge.rb
|
104
104
|
- lib/grumlin/expressions/expression.rb
|
@@ -108,22 +108,28 @@ files:
|
|
108
108
|
- lib/grumlin/expressions/pop.rb
|
109
109
|
- lib/grumlin/expressions/scope.rb
|
110
110
|
- lib/grumlin/expressions/t.rb
|
111
|
-
- lib/grumlin/expressions/
|
111
|
+
- lib/grumlin/expressions/text_p.rb
|
112
112
|
- lib/grumlin/expressions/with_options.rb
|
113
113
|
- lib/grumlin/path.rb
|
114
114
|
- lib/grumlin/property.rb
|
115
115
|
- lib/grumlin/repository.rb
|
116
116
|
- lib/grumlin/request_dispatcher.rb
|
117
|
-
- lib/grumlin/
|
117
|
+
- lib/grumlin/shortcut.rb
|
118
118
|
- lib/grumlin/shortcuts.rb
|
119
119
|
- lib/grumlin/shortcuts/properties.rb
|
120
|
-
- lib/grumlin/
|
120
|
+
- lib/grumlin/shortcuts_applyer.rb
|
121
|
+
- lib/grumlin/step_data.rb
|
122
|
+
- lib/grumlin/steps.rb
|
123
|
+
- lib/grumlin/steps_serializers/bytecode.rb
|
124
|
+
- lib/grumlin/steps_serializers/human_readable_bytecode.rb
|
125
|
+
- lib/grumlin/steps_serializers/serializer.rb
|
126
|
+
- lib/grumlin/steps_serializers/string.rb
|
121
127
|
- lib/grumlin/sugar.rb
|
122
128
|
- lib/grumlin/test/rspec.rb
|
123
129
|
- lib/grumlin/test/rspec/db_cleaner_context.rb
|
124
130
|
- lib/grumlin/test/rspec/gremlin_context.rb
|
125
131
|
- lib/grumlin/transport.rb
|
126
|
-
- lib/grumlin/
|
132
|
+
- lib/grumlin/traversal_start.rb
|
127
133
|
- lib/grumlin/traverser.rb
|
128
134
|
- lib/grumlin/typed_value.rb
|
129
135
|
- lib/grumlin/typing.rb
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Grumlin
|
4
|
-
class AnonymousStep
|
5
|
-
attr_reader :name, :previous_step, :configuration_steps
|
6
|
-
|
7
|
-
# TODO: add other steps
|
8
|
-
SUPPORTED_STEPS = %i[E V addE addV aggregate and as both bothE by choose coalesce count dedup drop elementMap emit
|
9
|
-
fold from group groupCount has hasId hasLabel hasNot id identity in inE inV is label limit
|
10
|
-
map not or order out outE path project properties property range repeat sack select sideEffect
|
11
|
-
skip sum tail to unfold union until valueMap values where with].freeze
|
12
|
-
|
13
|
-
def initialize(name, *args, configuration_steps: [], previous_step: nil, **params)
|
14
|
-
@name = name
|
15
|
-
@previous_step = previous_step
|
16
|
-
@args = args
|
17
|
-
@params = params
|
18
|
-
@configuration_steps = configuration_steps
|
19
|
-
end
|
20
|
-
|
21
|
-
SUPPORTED_STEPS.each do |step|
|
22
|
-
define_method(step) do |*args, **params|
|
23
|
-
step(step, *args, **params)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def step(name, *args, **params)
|
28
|
-
self.class.new(name, *args, previous_step: self, configuration_steps: configuration_steps, **params)
|
29
|
-
end
|
30
|
-
|
31
|
-
def inspect
|
32
|
-
bytecode.inspect
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_s
|
36
|
-
inspect
|
37
|
-
end
|
38
|
-
|
39
|
-
def bytecode(no_return: false)
|
40
|
-
@bytecode ||= Bytecode.new(self, no_return: no_return)
|
41
|
-
end
|
42
|
-
|
43
|
-
def args
|
44
|
-
[*@args].tap do |args|
|
45
|
-
args << @params if @params.any?
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
data/lib/grumlin/bytecode.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Grumlin
|
4
|
-
# Incapsulates logic of converting step chains and step arguments to queries that can be sent to the server
|
5
|
-
# and to human readable strings.
|
6
|
-
class Bytecode < TypedValue
|
7
|
-
class NoneStep
|
8
|
-
def to_bytecode
|
9
|
-
["none"]
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
NONE_STEP = NoneStep.new
|
14
|
-
|
15
|
-
def initialize(step, no_return: false)
|
16
|
-
super(type: "Bytecode")
|
17
|
-
@step = step
|
18
|
-
@no_return = no_return
|
19
|
-
end
|
20
|
-
|
21
|
-
def inspect
|
22
|
-
configuration_steps = @step.configuration_steps.map do |s|
|
23
|
-
serialize_arg(s, serialization_method: :to_readable_bytecode)
|
24
|
-
end
|
25
|
-
"#{configuration_steps.any? ? configuration_steps : nil}#{to_readable_bytecode}"
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_s
|
29
|
-
inspect
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_readable_bytecode
|
33
|
-
@to_readable_bytecode ||= steps.map { |s| serialize_arg(s, serialization_method: :to_readable_bytecode) }
|
34
|
-
end
|
35
|
-
|
36
|
-
def value
|
37
|
-
@value ||= { step: (steps + (@no_return ? [NONE_STEP] : [])).map { |s| serialize_arg(s) } }.tap do |v|
|
38
|
-
v.merge!(source: @step.configuration_steps.map { |s| serialize_arg(s) }) if @step.configuration_steps.any?
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
# Serializes step or a step argument to either an executable query or a human readable string representation
|
45
|
-
# depending on the `serialization_method` parameter. It should be either `:to_readable_bytecode` for human readable
|
46
|
-
# representation or `:to_bytecode` for query.
|
47
|
-
def serialize_arg(arg, serialization_method: :to_bytecode)
|
48
|
-
return arg.public_send(serialization_method) if arg.respond_to?(serialization_method)
|
49
|
-
return arg unless arg.is_a?(AnonymousStep)
|
50
|
-
|
51
|
-
arg.args.each.with_object([arg.name.to_s]) do |a, res|
|
52
|
-
res << if a.respond_to?(:bytecode)
|
53
|
-
a.bytecode.public_send(serialization_method)
|
54
|
-
else
|
55
|
-
serialize_arg(a, serialization_method: serialization_method)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def steps
|
61
|
-
@steps ||= [].tap do |result|
|
62
|
-
step = @step
|
63
|
-
until step.nil?
|
64
|
-
result.unshift(step)
|
65
|
-
step = step.previous_step
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Grumlin
|
4
|
-
module Expressions
|
5
|
-
module U
|
6
|
-
# TODO: add other start steps
|
7
|
-
SUPPORTED_STEPS = %i[V addV coalesce constant count drop fold has hasLabel hasNot id identity in inE inV is label
|
8
|
-
out outE outV project repeat select timeLimit unfold valueMap values].freeze
|
9
|
-
|
10
|
-
class << self
|
11
|
-
SUPPORTED_STEPS.each do |step|
|
12
|
-
define_method step do |*args, **params|
|
13
|
-
AnonymousStep.new(step, *args, **params)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|