Skip to content

Commit

Permalink
Add F.with_meta to attach metadata to an arbitrary node
Browse files Browse the repository at this point in the history
  • Loading branch information
Txus committed Oct 10, 2022
1 parent b9209ab commit 1398acb
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 33 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
fql (0.2.0)
fql (0.2.1)
activerecord (~> 6.0)
i18n (~> 1.8)
sorbet-rails (~> 0.7.3)
Expand Down
52 changes: 37 additions & 15 deletions lib/fql/query/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,62 @@ class Query
module DSL
extend T::Sig

module Node
extend T::Sig

sig { params(base: Module).void }
def self.included(base)
base.include T::Struct::ActsAsComparable
base.const :metadata, T::Hash[Symbol, T.untyped], default: {}
end
end

class And < T::Struct
include T::Struct::ActsAsComparable
include Node

const :lhs, T.untyped # BoolExpr, but Sorbet can't do recursive type aliases
const :rhs, T.untyped # BoolExpr, but Sorbet can't do recursive type aliases
end

class Or < T::Struct
include T::Struct::ActsAsComparable
include Node

const :lhs, T.untyped # BoolExpr, but Sorbet can't do recursive type aliases
const :rhs, T.untyped # BoolExpr, but Sorbet can't do recursive type aliases
end

class Not < T::Struct
include T::Struct::ActsAsComparable
include Node

const :expr, T.untyped # BoolExpr, but Sorbet can't do recursive type aliases
end

# Resolve a relation.
# The special relation named `:self` resolves to the root entity.
class Rel < T::Struct
include T::Struct::ActsAsComparable
include Node

const :name, T::Array[Symbol]
end

# Resolve an attribute of a relation.
class Attr < T::Struct
include T::Struct::ActsAsComparable
include Node

const :target, Rel
const :name, Symbol
end

# Resolve a variable at runtime that will be passed to the interpreter.
class Var < T::Struct
include T::Struct::ActsAsComparable
include Node

const :name, Symbol
end

# Resolve a variable at runtime that will be passed to the interpreter.
class Call < T::Struct
include T::Struct::ActsAsComparable
include Node

const :name, Symbol
const :arguments, T::Array[T.untyped]
Expand All @@ -66,56 +76,56 @@ class Call < T::Struct

# Determine equality between two values.
class Eq < T::Struct
include T::Struct::ActsAsComparable
include Node

const :lhs, ValueExpr
const :rhs, T.any(ValueExpr, NilClass)
end

class Gt < T::Struct
include T::Struct::ActsAsComparable
include Node

const :lhs, ValueExpr
const :rhs, ValueExpr
end

class Lt < T::Struct
include T::Struct::ActsAsComparable
include Node

const :lhs, ValueExpr
const :rhs, ValueExpr
end

class Gte < T::Struct
include T::Struct::ActsAsComparable
include Node

const :lhs, ValueExpr
const :rhs, ValueExpr
end

class Lte < T::Struct
include T::Struct::ActsAsComparable
include Node

const :lhs, ValueExpr
const :rhs, ValueExpr
end

class OneOf < T::Struct
include T::Struct::ActsAsComparable
include Node

const :member, ValueExpr
const :set, T::Array[Primitive]
end

class Contains < T::Struct
include T::Struct::ActsAsComparable
include Node

const :lhs, ValueExpr
const :rhs, String
end

class MatchesRegex < T::Struct
include T::Struct::ActsAsComparable
include Node

const :lhs, ValueExpr
const :rhs, String
Expand All @@ -124,6 +134,18 @@ class MatchesRegex < T::Struct
module Methods
extend T::Sig

sig do
type_parameters(:T)
.params(
metadata: T::Hash[Symbol, T.untyped],
node: T.all(T.type_parameter(:T), Node)
)
.returns(T.type_parameter(:T))
end
def with_meta(metadata, node)
node.tap { |n| n.metadata.merge!(metadata) }
end

sig { params(lhs: BoolExpr, rhs: BoolExpr).returns(And) }
def and(lhs, rhs)
And.new(lhs: lhs, rhs: rhs)
Expand Down
2 changes: 1 addition & 1 deletion lib/fql/version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: false
module FQL
VERSION = "0.2.0".freeze
VERSION = "0.2.1".freeze
end
42 changes: 26 additions & 16 deletions rbi/fql.rbi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# typed: strong
module FQL
VERSION = "0.2.0".freeze
VERSION = "0.2.1".freeze

class Library
extend T::Sig
Expand Down Expand Up @@ -267,111 +267,121 @@ module FQL
ValueExpr = T.type_alias { T.any(Attr, Rel, Var, Call, Primitive, T::Array[Primitive]) }
Expr = T.type_alias { T.any(BoolExpr, ValueExpr) }

module Node
extend T::Sig

sig { params(base: Module).void }
def self.included(base); end
end

class And < T::Struct
prop :lhs, T.untyped, immutable: true
prop :rhs, T.untyped, immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Or < T::Struct
prop :lhs, T.untyped, immutable: true
prop :rhs, T.untyped, immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Not < T::Struct
prop :expr, T.untyped, immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Rel < T::Struct
prop :name, T::Array[Symbol], immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Attr < T::Struct
prop :target, Rel, immutable: true
prop :name, Symbol, immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Var < T::Struct
prop :name, Symbol, immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Call < T::Struct
prop :name, Symbol, immutable: true
prop :arguments, T::Array[T.untyped], immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Eq < T::Struct
prop :lhs, ValueExpr, immutable: true
prop :rhs, T.any(ValueExpr, NilClass), immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Gt < T::Struct
prop :lhs, ValueExpr, immutable: true
prop :rhs, ValueExpr, immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Lt < T::Struct
prop :lhs, ValueExpr, immutable: true
prop :rhs, ValueExpr, immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Gte < T::Struct
prop :lhs, ValueExpr, immutable: true
prop :rhs, ValueExpr, immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Lte < T::Struct
prop :lhs, ValueExpr, immutable: true
prop :rhs, ValueExpr, immutable: true

include T::Struct::ActsAsComparable
include Node
end

class OneOf < T::Struct
prop :member, ValueExpr, immutable: true
prop :set, T::Array[Primitive], immutable: true

include T::Struct::ActsAsComparable
include Node
end

class Contains < T::Struct
prop :lhs, ValueExpr, immutable: true
prop :rhs, String, immutable: true

include T::Struct::ActsAsComparable
include Node
end

class MatchesRegex < T::Struct
prop :lhs, ValueExpr, immutable: true
prop :rhs, String, immutable: true

include T::Struct::ActsAsComparable
include Node
end

module Methods
extend T::Sig

sig { type_parameters(:T).params(metadata: T::Hash[Symbol, T.untyped], node: T.all(T.type_parameter(:T), Node)).returns(T.type_parameter(:T)) }
def with_meta(metadata, node); end

sig { params(lhs: BoolExpr, rhs: BoolExpr).returns(And) }
def and(lhs, rhs); end

Expand Down
13 changes: 13 additions & 0 deletions spec/fql/query_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,17 @@
expect(result).to eq(F.not(expression))
end
end

describe "metadata" do
let(:expression) do
F.eq(
F.with_meta({ name: "the user id" }, F.var(:foo)),
3
)
end

it "can be attached to an arbitrary node" do
expect(expression.lhs.metadata).to eq(name: "the user id")
end
end
end

0 comments on commit 1398acb

Please sign in to comment.