grumlin 0.11.0 → 0.12.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/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/README.md +87 -7
- data/Rakefile +12 -0
- data/bin/console +1 -1
- data/grumlin.gemspec +6 -2
- data/lib/async/channel.rb +1 -1
- data/lib/grumlin/anonymous_step.rb +3 -3
- data/lib/grumlin/bytecode.rb +2 -2
- data/lib/grumlin/edge.rb +1 -1
- data/lib/grumlin/path.rb +2 -0
- data/lib/grumlin/sugar.rb +8 -6
- data/lib/grumlin/tools/order.rb +13 -0
- data/lib/grumlin/tools/p.rb +45 -0
- data/lib/grumlin/tools/pop.rb +13 -0
- data/lib/grumlin/tools/scope.rb +13 -0
- data/lib/grumlin/tools/t.rb +13 -0
- data/lib/grumlin/tools/tool.rb +18 -0
- data/lib/grumlin/tools/u.rb +19 -0
- data/lib/grumlin/tools/with_options.rb +28 -0
- data/lib/grumlin/traversal.rb +2 -4
- data/lib/grumlin/typing.rb +1 -0
- data/lib/grumlin/version.rb +1 -1
- metadata +16 -9
- data/lib/grumlin/order.rb +0 -17
- data/lib/grumlin/p.rb +0 -46
- data/lib/grumlin/pop.rb +0 -17
- data/lib/grumlin/t.rb +0 -17
- data/lib/grumlin/u.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b01ddca4a13e70f6ab86875cd635655ebec77e877f374b0df9c8021f61ae7753
|
4
|
+
data.tar.gz: c25ccd742c5c40ba797f92fe39176cf2605d485506e56a1a1e8852bbbc11ab0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '042067879c5ae297f5d3a06f2f0a7302cccb5dc0e362fcdb15820f74e8aec6b1d9f5cd085bcfdbfe3d2f671fe8cae24b8da38c03a89e4a645c42a31d60218005'
|
7
|
+
data.tar.gz: b740805e7ab51fc7d45aeb0a1cc11062778561439a51395de1cdf1bd771a8745768c17e4e0b2db4daf2382ba6008f898e469c3f474d4738775c72a99c47cdd75
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
grumlin (0.
|
4
|
+
grumlin (0.12.0)
|
5
5
|
async-pool (~> 0.3)
|
6
6
|
async-websocket (~> 0.19)
|
7
7
|
oj (~> 3.12)
|
@@ -83,6 +83,7 @@ GEM
|
|
83
83
|
protocol-http1 (~> 0.2)
|
84
84
|
racc (1.5.2)
|
85
85
|
rainbow (3.0.0)
|
86
|
+
rake (13.0.3)
|
86
87
|
regexp_parser (2.1.1)
|
87
88
|
reverse_markdown (2.0.0)
|
88
89
|
nokogiri
|
@@ -161,6 +162,7 @@ DEPENDENCIES
|
|
161
162
|
grumlin!
|
162
163
|
nokogiri
|
163
164
|
overcommit
|
165
|
+
rake
|
164
166
|
rspec
|
165
167
|
rubocop
|
166
168
|
rubocop-performance
|
data/README.md
CHANGED
@@ -1,10 +1,30 @@
|
|
1
1
|
# Grumlin
|
2
2
|
|
3
|
-
[
|
3
|
+
[](https://github.com/zhulik/grumlin/actions/workflows/main.yml)
|
4
|
+
[](https://github.com/RichardLitt/standard-readme)
|
5
|
+
[](https://lbesson.mit-license.org/)
|
4
6
|
|
5
|
-
|
7
|
+
Grumlin is a [Gremlin](https://tinkerpop.apache.org/gremlin.html) graph traversal language DSL and client for Ruby.
|
8
|
+
Suitable for and tested with [gremlin-server](http://tinkerpop.apache.org/) and [AWS Neptune](https://aws.amazon.com/neptune/).
|
6
9
|
|
7
|
-
|
10
|
+
**Important**: Grumlin and it's author are not affiliated with The Apache Software Foundation which develops gremlin
|
11
|
+
and gremlin-server.
|
12
|
+
|
13
|
+
**Important**: Grumlin is based on the [async stack](https://github.com/socketry/async) and utilizes
|
14
|
+
[async-websocket](https://github.com/socketry/async-websocket). Code using grumlin must be executed in an async
|
15
|
+
event loop.
|
16
|
+
|
17
|
+
**Warning:** Grumlin is in development, but ready for simple use cases
|
18
|
+
|
19
|
+
## Table of contents
|
20
|
+
- [Install](#install)
|
21
|
+
- [Usage](#usage)
|
22
|
+
- [Development](#development)
|
23
|
+
- [Contributing](#contributing)
|
24
|
+
- [License](#license)
|
25
|
+
- [Code Of Conduct](#code-of-conduct)
|
26
|
+
|
27
|
+
## Install
|
8
28
|
|
9
29
|
Add this line to your application's Gemfile:
|
10
30
|
|
@@ -22,17 +42,77 @@ Or install it yourself as:
|
|
22
42
|
|
23
43
|
## Usage
|
24
44
|
|
25
|
-
|
45
|
+
### Configuration
|
46
|
+
```ruby
|
47
|
+
Grumlin.configure do |config|
|
48
|
+
config.url = "ws://localhost:8182/gremlin"
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
### Traversing graphs
|
53
|
+
|
54
|
+
**Warning:** Not all steps and tools described in the standard are supported
|
55
|
+
|
56
|
+
#### Sugar
|
57
|
+
|
58
|
+
Grumlin provides an easy to use module called `Grumlin::Sugar`. Once included in your class it injects some useful
|
59
|
+
constants and methods turning your class into an entrypoint for traversals.
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
class MyRepository
|
63
|
+
include Grumlin::Sugar
|
64
|
+
|
65
|
+
def nodes(property1:, property2:)
|
66
|
+
g.V()
|
67
|
+
.has(T.label, "node")
|
68
|
+
.has(:property1, property1)
|
69
|
+
.has(:property2, property2)
|
70
|
+
.order.by(:property3, Order.asc).limit(10)
|
71
|
+
.toList
|
72
|
+
end
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
#### Testing
|
77
|
+
|
78
|
+
Grumlin provides a couple of helpers to simplify testing code written with it.
|
79
|
+
|
80
|
+
##### RSpec
|
81
|
+
|
82
|
+
Make sure you have [async-rspec](https://github.com/socketry/async-rspec) installed.
|
83
|
+
|
84
|
+
`spec_helper.rb` or `rails_helper.rb`:
|
85
|
+
```ruby
|
86
|
+
require 'async/rspec'
|
87
|
+
require require "grumlin/test/rspec"
|
88
|
+
...
|
89
|
+
config.include_context(Async::RSpec::Reactor) # Runs async reactor
|
90
|
+
config.include_context(Grumlin::Test::RSpec::GremlinContext) # Injects sugar and makes sure client is closed after every test
|
91
|
+
config.include_context(Grumlin::Test::RSpec::DBCleanerContext) # Cleans the database before every test
|
92
|
+
...
|
93
|
+
```
|
94
|
+
|
95
|
+
It is highly recommended to use `Grumlin::Sugar` and not trying to use lower level APIs as they are subject to change.
|
26
96
|
|
27
97
|
## Development
|
28
98
|
|
29
|
-
|
99
|
+
Before running tests make sure you have gremlin-server running on your computer. The simplest way to run it is using
|
100
|
+
[docker-compose](https://docs.docker.com/compose/) and provided `docker-compose.yml` and `gremlin_server/Dockerfile`:
|
101
|
+
|
102
|
+
$ docker-compose up -d gremlin_server
|
103
|
+
|
104
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
|
105
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
106
|
|
31
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update
|
107
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update
|
108
|
+
the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version,
|
109
|
+
push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
110
|
|
33
111
|
## Contributing
|
34
112
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
113
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/zhulik/grumlin. This project is intended to
|
114
|
+
be a safe, welcoming space for collaboration, and contributors are expected to adhere to the
|
115
|
+
[code of conduct](https://github.com/zhulik/grumlin/blob/master/CODE_OF_CONDUCT.md).
|
36
116
|
|
37
117
|
## License
|
38
118
|
|
data/Rakefile
ADDED
data/bin/console
CHANGED
data/grumlin.gemspec
CHANGED
@@ -8,8 +8,12 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ["Gleb Sinyavskiy"]
|
9
9
|
spec.email = ["zhulik.gleb@gmail.com"]
|
10
10
|
|
11
|
-
spec.summary = "Gremlin
|
12
|
-
|
11
|
+
spec.summary = "Gremlin graph traversal language DSL and client for Ruby."
|
12
|
+
|
13
|
+
spec.description = <<~DESCRIPTION
|
14
|
+
Gremlin graph traversal language DSL and client for Ruby. Suitable and tested with gremlin-server and AWS Neptune.
|
15
|
+
DESCRIPTION
|
16
|
+
|
13
17
|
spec.homepage = "https://github.com/zhulik/grumlin"
|
14
18
|
spec.license = "MIT"
|
15
19
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
|
data/lib/async/channel.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Async
|
4
4
|
# Channel is a wrapper around Async::Queue that provides
|
5
5
|
# a protocol and handy tools for passing data, exceptions and closing.
|
6
|
-
# It is designed to be used with
|
6
|
+
# It is designed to be used only with one publisher and one subscriber
|
7
7
|
class Channel
|
8
8
|
class ChannelError < StandardError; end
|
9
9
|
|
@@ -5,9 +5,9 @@ module Grumlin
|
|
5
5
|
attr_reader :name, :args, :previous_step
|
6
6
|
|
7
7
|
# TODO: add other steps
|
8
|
-
SUPPORTED_STEPS = %
|
9
|
-
hasId hasLabel hasNot in inV label limit not order out outE path project property
|
10
|
-
to unfold union valueMap values where].freeze
|
8
|
+
SUPPORTED_STEPS = %i[E V addE addV as both by coalesce count dedup drop elementMap emit fold from group groupCount
|
9
|
+
has hasId hasLabel hasNot id in inV label limit not order out outE path project property range
|
10
|
+
repeat select skip tail to unfold union until valueMap values where with].freeze
|
11
11
|
|
12
12
|
def initialize(name, *args, previous_step: nil)
|
13
13
|
@name = name
|
data/lib/grumlin/bytecode.rb
CHANGED
@@ -38,10 +38,10 @@ module Grumlin
|
|
38
38
|
# depending on the `serialization_method` parameter. I should be either `:to_readable_bytecode` for human readable
|
39
39
|
# representation or `:to_bytecode` for query.
|
40
40
|
def serialize_arg(arg, serialization_method: :to_bytecode)
|
41
|
-
return arg.send(serialization_method) if arg.respond_to?(
|
41
|
+
return arg.send(serialization_method) if arg.respond_to?(serialization_method)
|
42
42
|
return arg unless arg.is_a?(AnonymousStep)
|
43
43
|
|
44
|
-
arg.args.flatten.each.with_object([arg.name]) do |a, res|
|
44
|
+
arg.args.flatten.each.with_object([arg.name.to_s]) do |a, res|
|
45
45
|
res << if a.instance_of?(AnonymousStep)
|
46
46
|
a.bytecode.send(serialization_method)
|
47
47
|
else
|
data/lib/grumlin/edge.rb
CHANGED
data/lib/grumlin/path.rb
CHANGED
data/lib/grumlin/sugar.rb
CHANGED
@@ -3,11 +3,13 @@
|
|
3
3
|
module Grumlin
|
4
4
|
module Sugar
|
5
5
|
HELPERS = [
|
6
|
-
Grumlin::
|
7
|
-
Grumlin::
|
8
|
-
Grumlin::
|
9
|
-
Grumlin::
|
10
|
-
Grumlin::
|
6
|
+
Grumlin::Tools::Order,
|
7
|
+
Grumlin::Tools::P,
|
8
|
+
Grumlin::Tools::Pop,
|
9
|
+
Grumlin::Tools::Scope,
|
10
|
+
Grumlin::Tools::T,
|
11
|
+
Grumlin::Tools::U,
|
12
|
+
Grumlin::Tools::WithOptions
|
11
13
|
].freeze
|
12
14
|
|
13
15
|
def self.included(base)
|
@@ -18,7 +20,7 @@ module Grumlin
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def __
|
21
|
-
Grumlin::U
|
23
|
+
Grumlin::Tools::U
|
22
24
|
end
|
23
25
|
|
24
26
|
def g
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
module Tools
|
5
|
+
module P
|
6
|
+
class << self
|
7
|
+
class Predicate < TypedValue
|
8
|
+
def initialize(name, args:, arg_type: nil)
|
9
|
+
super(type: "P")
|
10
|
+
@name = name
|
11
|
+
@args = args
|
12
|
+
@arg_type = arg_type
|
13
|
+
end
|
14
|
+
|
15
|
+
def value
|
16
|
+
@value ||= {
|
17
|
+
predicate: @name,
|
18
|
+
value: TypedValue.new(type: @arg_type, value: @args).to_bytecode
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# TODO: support more predicates
|
24
|
+
%i[eq neq].each do |predicate|
|
25
|
+
define_method predicate do |*args|
|
26
|
+
Predicate.new(predicate, args: args[0])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
%i[within without].each do |predicate|
|
31
|
+
define_method predicate do |*args|
|
32
|
+
args = if args.count == 1 && args[0].is_a?(Array)
|
33
|
+
args[0]
|
34
|
+
elsif args.count == 1 && args[0].is_a?(Set)
|
35
|
+
args[0].to_a
|
36
|
+
else
|
37
|
+
args.to_a
|
38
|
+
end
|
39
|
+
Predicate.new(predicate, args: args, arg_type: "List")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
module Tools
|
5
|
+
module Tool
|
6
|
+
def define_steps(steps, tool_name)
|
7
|
+
steps.each do |step|
|
8
|
+
self.class.define_method step do
|
9
|
+
name = "@#{step}"
|
10
|
+
return instance_variable_get(name) if instance_variable_defined?(name)
|
11
|
+
|
12
|
+
instance_variable_set(name, TypedValue.new(type: tool_name, value: step))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
module Tools
|
5
|
+
module U
|
6
|
+
# TODO: add other start steps
|
7
|
+
SUPPORTED_STEPS = %i[V addV count fold has id inV label out outV project repeat timeLimit unfold valueMap
|
8
|
+
values].freeze
|
9
|
+
|
10
|
+
class << self
|
11
|
+
SUPPORTED_STEPS.each do |step|
|
12
|
+
define_method step do |*args|
|
13
|
+
AnonymousStep.new(step, *args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grumlin
|
4
|
+
module Tools
|
5
|
+
module WithOptions
|
6
|
+
WITH_OPTIONS = {
|
7
|
+
tokens: "~tinkerpop.valueMap.tokens",
|
8
|
+
none: 0,
|
9
|
+
ids: 1,
|
10
|
+
labels: 2,
|
11
|
+
keys: 4,
|
12
|
+
values: 8,
|
13
|
+
all: 15,
|
14
|
+
indexer: "~tinkerpop.index.indexer",
|
15
|
+
list: 0,
|
16
|
+
map: 1
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
class << self
|
20
|
+
WITH_OPTIONS.each do |k, v|
|
21
|
+
define_method k do
|
22
|
+
v
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/grumlin/traversal.rb
CHANGED
@@ -2,16 +2,14 @@
|
|
2
2
|
|
3
3
|
module Grumlin
|
4
4
|
class Traversal
|
5
|
-
attr_reader :connection
|
6
|
-
|
7
5
|
# TODO: add other start steps
|
8
|
-
|
6
|
+
SUPPORTED_STEPS = %i[E V addE addV].freeze
|
9
7
|
|
10
8
|
def initialize(pool = Grumlin.default_pool)
|
11
9
|
@pool = pool
|
12
10
|
end
|
13
11
|
|
14
|
-
|
12
|
+
SUPPORTED_STEPS.each do |step|
|
15
13
|
define_method step do |*args|
|
16
14
|
Step.new(@pool, step, *args)
|
17
15
|
end
|
data/lib/grumlin/typing.rb
CHANGED
@@ -13,6 +13,7 @@ module Grumlin
|
|
13
13
|
"g:Int32" => ->(value) { cast_int(value) },
|
14
14
|
"g:Double" => ->(value) { cast_double(value) },
|
15
15
|
"g:Traverser" => ->(value) { cast(value[:value]) }, # TODO: wtf is bulk?
|
16
|
+
"g:Direction" => ->(value) { value },
|
16
17
|
"g:T" => ->(value) { value.to_sym }
|
17
18
|
}.freeze
|
18
19
|
|
data/lib/grumlin/version.rb
CHANGED
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.12.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: 2021-09-
|
11
|
+
date: 2021-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-pool
|
@@ -66,7 +66,10 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '2.4'
|
69
|
-
description: Gremlin
|
69
|
+
description: 'Gremlin graph traversal language DSL and client for Ruby. Suitable and
|
70
|
+
tested with gremlin-server and AWS Neptune.
|
71
|
+
|
72
|
+
'
|
70
73
|
email:
|
71
74
|
- zhulik.gleb@gmail.com
|
72
75
|
executables: []
|
@@ -85,6 +88,7 @@ files:
|
|
85
88
|
- Gemfile.lock
|
86
89
|
- LICENSE.txt
|
87
90
|
- README.md
|
91
|
+
- Rakefile
|
88
92
|
- bin/console
|
89
93
|
- bin/setup
|
90
94
|
- docker-compose.yml
|
@@ -97,22 +101,25 @@ files:
|
|
97
101
|
- lib/grumlin/bytecode.rb
|
98
102
|
- lib/grumlin/client.rb
|
99
103
|
- lib/grumlin/edge.rb
|
100
|
-
- lib/grumlin/order.rb
|
101
|
-
- lib/grumlin/p.rb
|
102
104
|
- lib/grumlin/path.rb
|
103
|
-
- lib/grumlin/pop.rb
|
104
105
|
- lib/grumlin/request_dispatcher.rb
|
105
106
|
- lib/grumlin/step.rb
|
106
107
|
- lib/grumlin/sugar.rb
|
107
|
-
- lib/grumlin/t.rb
|
108
108
|
- lib/grumlin/test/rspec.rb
|
109
109
|
- lib/grumlin/test/rspec/db_cleaner_context.rb
|
110
110
|
- lib/grumlin/test/rspec/gremlin_context.rb
|
111
|
+
- lib/grumlin/tools/order.rb
|
112
|
+
- lib/grumlin/tools/p.rb
|
113
|
+
- lib/grumlin/tools/pop.rb
|
114
|
+
- lib/grumlin/tools/scope.rb
|
115
|
+
- lib/grumlin/tools/t.rb
|
116
|
+
- lib/grumlin/tools/tool.rb
|
117
|
+
- lib/grumlin/tools/u.rb
|
118
|
+
- lib/grumlin/tools/with_options.rb
|
111
119
|
- lib/grumlin/transport.rb
|
112
120
|
- lib/grumlin/traversal.rb
|
113
121
|
- lib/grumlin/typed_value.rb
|
114
122
|
- lib/grumlin/typing.rb
|
115
|
-
- lib/grumlin/u.rb
|
116
123
|
- lib/grumlin/version.rb
|
117
124
|
- lib/grumlin/vertex.rb
|
118
125
|
homepage: https://github.com/zhulik/grumlin
|
@@ -140,5 +147,5 @@ requirements: []
|
|
140
147
|
rubygems_version: 3.2.22
|
141
148
|
signing_key:
|
142
149
|
specification_version: 4
|
143
|
-
summary: Gremlin
|
150
|
+
summary: Gremlin graph traversal language DSL and client for Ruby.
|
144
151
|
test_files: []
|
data/lib/grumlin/order.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Grumlin
|
4
|
-
module Order
|
5
|
-
# TODO: share the code?
|
6
|
-
class << self
|
7
|
-
%i[asc desc].each do |step|
|
8
|
-
define_method step do
|
9
|
-
name = "@#{step}"
|
10
|
-
return instance_variable_get(name) if instance_variable_defined?(name)
|
11
|
-
|
12
|
-
instance_variable_set(name, TypedValue.new(type: "Order", value: step))
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
data/lib/grumlin/p.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Grumlin
|
4
|
-
module P
|
5
|
-
module P
|
6
|
-
class Predicate < TypedValue
|
7
|
-
def initialize(name, args:, arg_type: nil)
|
8
|
-
super(type: "P")
|
9
|
-
@name = name
|
10
|
-
@args = args
|
11
|
-
@arg_type = arg_type
|
12
|
-
end
|
13
|
-
|
14
|
-
def value
|
15
|
-
@value ||=
|
16
|
-
{
|
17
|
-
predicate: @name,
|
18
|
-
value: TypedValue.new(type: @arg_type, value: @args).to_bytecode
|
19
|
-
}
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# TODO: support more predicates
|
24
|
-
%w[eq neq].each do |predicate|
|
25
|
-
define_method predicate do |*args|
|
26
|
-
Predicate.new(predicate, args: args[0])
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
%w[within without].each do |predicate|
|
31
|
-
define_method predicate do |*args|
|
32
|
-
args = if args.count == 1 && args[0].is_a?(Array)
|
33
|
-
args[0]
|
34
|
-
elsif args.count == 1 && args[0].is_a?(Set)
|
35
|
-
args[0].to_a
|
36
|
-
else
|
37
|
-
args.to_a
|
38
|
-
end
|
39
|
-
Predicate.new(predicate, args: args, arg_type: "List")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
extend P
|
45
|
-
end
|
46
|
-
end
|
data/lib/grumlin/pop.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Grumlin
|
4
|
-
module Pop
|
5
|
-
# TODO: share the code?
|
6
|
-
class << self
|
7
|
-
%i[first last all mixed].each do |step|
|
8
|
-
define_method step do
|
9
|
-
name = "@#{step}"
|
10
|
-
return instance_variable_get(name) if instance_variable_defined?(name)
|
11
|
-
|
12
|
-
instance_variable_set(name, TypedValue.new(type: "Pop", value: step))
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
data/lib/grumlin/t.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Grumlin
|
4
|
-
module T
|
5
|
-
# TODO: share the code?
|
6
|
-
class << self
|
7
|
-
%i[id label].each do |step|
|
8
|
-
define_method step do
|
9
|
-
name = "@#{step}"
|
10
|
-
return instance_variable_get(name) if instance_variable_defined?(name)
|
11
|
-
|
12
|
-
instance_variable_set(name, TypedValue.new(type: "T", value: step))
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
data/lib/grumlin/u.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Grumlin
|
4
|
-
module U
|
5
|
-
# TODO: add other start steps
|
6
|
-
SUPPORTED_START_STEPS = %w[V addV count fold has out repeat unfold values].freeze
|
7
|
-
|
8
|
-
class << self
|
9
|
-
SUPPORTED_START_STEPS.each do |step|
|
10
|
-
define_method step do |*args|
|
11
|
-
AnonymousStep.new(step, *args)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|