Module: Fusion::AST::Expression

Defined in:
lib/fusion/ast.rb,
lib/fusion/ast.rb

Overview

Expression and Pattern nodes each form a closed family, declared up front (empty) so a member of either may reference the other. Each module is mixed into all of its members at the bottom of its body, so the module doubles as a marker: a field typed ‘Expression` accepts any expression node, `Pattern` any pattern node.

Constant Summary collapse

Lit =

atom literal (incl NULL)

TypedData.define(value: Atom)
ErrLit =

!expr or bare ! (payload nil = !null)

TypedData.define(payload: ->(v) { Expression === v || v.nil? })
ArrLit =
TypedData.define(items: ->(v) { v.is_a?(Array) && v.all? { |e| ArrayItem === e || ArraySpread === e } })
ObjLit =

[KeyValuePair|ObjectSpread], distinct fixed keys

TypedData.define(pairs: ->(v) {                                                    # [KeyValuePair|ObjectSpread], distinct fixed keys
  v.is_a?(Array) &&
    v.all? { |m| KeyValuePair === m || ObjectSpread === m } &&
    v.filter_map { |m| m.key if KeyValuePair === m }.then { |keys| keys.uniq.size == keys.size }
})
FuncLit =

the empty function

TypedData.define(clauses: ->(v) { v.is_a?(Array) && v.all? { |c| Clause === c } })
Ident =

read a builtin/bound name

TypedData.define(name: Identifier)
FileRef =
TypedData.define(variety: ->(v) { %i[self name path].include?(v) }, path: ->(v) { String === v || v.nil? })
Pipe =

left | right

TypedData.define(left: Expression, right: Expression)
Member =

obj.key

TypedData.define(obj: Expression, key: Identifier)
Index =

obj

TypedData.define(obj: Expression, idx: Expression)