Skip to content

Commit

Permalink
Switch Optional to an orElse extension method. (#194)
Browse files Browse the repository at this point in the history
  • Loading branch information
PapyChacal authored Feb 5, 2025
1 parent d18f613 commit 897049e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 63 deletions.
70 changes: 29 additions & 41 deletions core/src/main/scala-3/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,32 +74,22 @@ object Parser {
a
}

def optionlessSeq[A](option: Option[Seq[A]]): Seq[A] = option match {
case None => Seq[A]()
case Some(x) => x
}

/** Higher-order optional parser.
*
* Takes a parser p, and parses it optionally, defaulting the parsed value to
* the passed default.
*
* @todo:
* Figure out dark implicit magic to figure out magically that the default
* is "T()".
*
* @tparam T
* The optionally parsed type.
* @param p
* The parser to use optionally
* @param default
* The default value to use if the parser fails.
* @return
* A parser optionally parsing p, defaulting to default.
*/
inline def Optional[$: P, T](p: => P[T], default: T): P[T] = P(
p.?.map(_.getOrElse(default))
)
extension [T](inline p: P[T])

/** Make the parser optional, parsing defaults if otherwise failing.
*
* @todo:
* Figure out dark implicit magic to figure out magically that the
* default default is "T()".
*
* @param default
* The default value to use if the parser fails.
* @return
* An optional parser, defaulting to default.
*/
inline def orElse[$: P](default: T): P[T] = P(
p.?.map(_.getOrElse(default))
)

/*≡==--==≡≡≡==--=≡≡*\
|| SCOPE ||
Expand Down Expand Up @@ -374,7 +364,7 @@ object Parser {
def FloatLiteral[$: P] = P(
CharIn("\\-\\+").? ~~ (Digit.repX(1) ~~ "." ~~ Digit.repX(1)).!
~~ (CharIn("eE")
~~ (CharIn("\\-\\+").? ~~ Digit.repX(1)).!).?.map(_.getOrElse("0"))
~~ (CharIn("\\-\\+").? ~~ Digit.repX(1)).!).orElse("0")
).map(parseFloatNum(_)) // substituted [0-9]* with [0-9]+

def notExcluded[$: P] = P(
Expand Down Expand Up @@ -713,9 +703,7 @@ class Parser(val context: MLContext, val args: Args = Args())
P(OperationPat.rep(at_least_this_many).map(_.to(ListType)))

def OperationPat[$: P]: P[Operation] = P(
OpResultList.?./.map(
optionlessSeq
).flatMap(Op(_)) ~/ TrailingLocation.?
OpResultList.orElse(Seq()).flatMap(Op(_)) ~/ TrailingLocation.?
)

def Op[$: P](resNames: Seq[String]) = P(
Expand All @@ -732,11 +720,11 @@ class Parser(val context: MLContext, val args: Args = Args())
})

def GenericOperation[$: P](resNames: Seq[String]) = P(
StringLiteral ~/ "(" ~ ValueUseList.?.map(optionlessSeq) ~ ")"
~/ SuccessorList.?.map(optionlessSeq)
~/ Optional(DictionaryProperties, DictType.empty)
~/ RegionList.?.map(optionlessSeq)
~/ Optional(DictionaryAttribute, DictType.empty) ~/ ":" ~/ FunctionType
StringLiteral ~/ "(" ~ ValueUseList.orElse(Seq()) ~ ")"
~/ SuccessorList.orElse(Seq())
~/ DictionaryProperties.orElse(DictType.empty)
~/ RegionList.orElse(Seq())
~/ (DictionaryAttribute).orElse(DictType.empty) ~/ ":" ~/ FunctionType
).map(
(
(
Expand Down Expand Up @@ -802,7 +790,7 @@ class Parser(val context: MLContext, val args: Args = Args())
P(BlockLabel ~ Operations(0)).map(createBlock)

def BlockLabel[$: P] = P(
BlockId ~ BlockArgList.?.map(optionlessSeq) ~ ":"
BlockId ~ BlockArgList.orElse(Seq()) ~ ":"
)

/*≡==--==≡≡≡≡≡==--=≡≡*\
Expand Down Expand Up @@ -874,10 +862,10 @@ class Parser(val context: MLContext, val args: Args = Args())
def ValueIdAndType[$: P] = P(ValueId ~ ":" ~ Type)

def ValueIdAndTypeList[$: P] =
P(ValueIdAndType.rep(sep = ","))
P(ValueIdAndType.rep(sep = ",")).orElse(Seq())

def BlockArgList[$: P] =
P("(" ~ ValueIdAndTypeList.? ~ ")").map(optionlessSeq)
P("(" ~ ValueIdAndTypeList ~ ")")

// [x] dictionary-properties ::= `<` dictionary-attribute `>`
// [x] dictionary-attribute ::= `{` (attribute-entry (`,` attribute-entry)*)? `}`
Expand Down Expand Up @@ -910,7 +898,7 @@ class Parser(val context: MLContext, val args: Args = Args())
* present.
*/
inline def OptionalProperties[$: P]() =
Optional(DictionaryProperties, DictType.empty)
(DictionaryProperties).orElse(DictType.empty)

/** Parses an optional attributes dictionary from the input.
*
Expand All @@ -919,7 +907,7 @@ class Parser(val context: MLContext, val args: Args = Args())
* present.
*/
inline def OptionalAttributes[$: P] =
Optional(DictionaryAttribute, DictType.empty)
(DictionaryAttribute).orElse(DictType.empty)

/** Parses an optional attributes dictionary from the input, preceded by the
* `attributes` keyword.
Expand All @@ -928,7 +916,7 @@ class Parser(val context: MLContext, val args: Args = Args())
* An optional dictionary of attributes - empty if no keyword is present.
*/
inline def OptionalKeywordAttributes[$: P] =
Optional("attributes" ~ DictionaryAttribute, DictType.empty)
("attributes" ~ DictionaryAttribute).orElse(DictType.empty)

/*≡==--==≡≡≡≡==--=≡≡*\
|| PARSE FUNCTION ||
Expand Down
11 changes: 5 additions & 6 deletions core/src/main/scala-3/builtin/AttrParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,13 @@ class AttrParser(val ctx: MLContext) {
// dense-array-attribute ::= `array` `<` (integer-type | float-type) (`:` tensor-literal)? `>`

def DenseArrayAttributeP[$: P]: P[DenseArrayAttr] = P(
"array<" ~ (((IntegerTypeP) ~ (":" ~ IntDataP.rep(sep = ",")).?.map(
_.getOrElse(Seq())
"array<" ~ (((IntegerTypeP) ~ (":" ~ IntDataP.rep(sep = ",")).orElse(
Seq()
)).map((typ: IntegerType, x: Seq[IntData]) =>
DenseArrayAttr(typ, x.map(IntegerAttr(_, typ)))
) | ((FloatTypeP) ~ (":" ~ FloatDataP.rep(sep = ",")).?.map(
_.getOrElse(Seq())
)).map((typ: FloatType, x: Seq[FloatData]) =>
DenseArrayAttr(typ, x.map(FloatAttr(_, typ)))
) | ((FloatTypeP) ~ (":" ~ FloatDataP.rep(sep = ",")).orElse(Seq())).map(
(typ: FloatType, x: Seq[FloatData]) =>
DenseArrayAttr(typ, x.map(FloatAttr(_, typ)))
)) ~ ">"
)

Expand Down
24 changes: 9 additions & 15 deletions dialects/src/main/scala-3/lingodb/RelAlgOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import scair.Parser
import scair.Parser.BareId
import scair.Parser.E
import scair.Parser.ValueId
import scair.Parser.optionlessSeq
import scair.Parser.orElse
import scair.Parser.whitespace
import scair.dialects.LingoDB.SubOperatorOps.*
import scair.dialects.LingoDB.TupleStream.*
Expand Down Expand Up @@ -136,13 +136,13 @@ case class SortSpecificationAttr(

private def DialectRegion[$: P](parser: Parser) = P(
E({ parser.enterLocalRegion })
~ (parser.BlockArgList.?.map(optionlessSeq).map(
(x: Seq[(String, Attribute)]) => {
~ (parser.BlockArgList
.orElse(Seq())
.map((x: Seq[(String, Attribute)]) => {
val b = new Block(ListType.empty, ListType.from(x.map(_._2)))
parser.currentScope.defineValues(x.map(_._1) zip b.arguments)
b
}
)
})
~ "{"
~ parser.Operations(1) ~ "}").map((b: Block, y: ListType[Operation]) => {
b.operations ++= y
Expand Down Expand Up @@ -244,8 +244,8 @@ object SelectionOp extends OperationObject {
override def parse[$: P](
parser: Parser
): P[Operation] = P(
ValueId ~ DialectRegion(parser)
~ "attributes" ~ parser.OptionalAttributes
ValueId ~ DialectRegion(parser) ~
parser.OptionalKeywordAttributes
)
.map(
(
Expand Down Expand Up @@ -325,10 +325,7 @@ object MapOp extends OperationObject {
~ "computes" ~ ":"
~ "[" ~ ColumnDefAttr.parse(parser).rep.map(ArrayAttribute(_)) ~ "]"
~ DialectRegion(parser)
~ Parser.Optional(
"attributes" ~ parser.DictionaryAttribute,
DictType.empty
)
~ parser.OptionalKeywordAttributes
).map(
(
x: String,
Expand Down Expand Up @@ -430,10 +427,7 @@ object AggregationOp extends OperationObject {
.rep(sep = ",")
.map(ArrayAttribute(_)) ~ "]"
~ DialectRegion(parser)
~ Parser.Optional(
"attributes" ~ parser.DictionaryAttribute,
DictType.empty
)
~ parser.OptionalKeywordAttributes
).map(
(
x: String,
Expand Down
3 changes: 2 additions & 1 deletion dialects/src/main/scala-3/lingodb/TupleStream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import fastparse.*
import scair.AttrParser
import scair.Parser
import scair.Parser.ValueId
import scair.Parser.orElse
import scair.Parser.whitespace
import scair.dialects.builtin.*
import scair.ir.*
Expand Down Expand Up @@ -142,7 +143,7 @@ object ReturnOp extends OperationObject {
): P[Operation] = P(
parser.OptionalAttributes ~ (ValueId.rep(sep = ",")
~ ":" ~
parser.Type.rep(sep = ",")).?.map(makeResults)
parser.Type.rep(sep = ",")).orElse((Seq(), Seq()))
).map((x: DictType[String, Attribute], y: (Seq[String], Seq[Attribute])) =>
parser.generateOperation(
opName = name,
Expand Down

0 comments on commit 897049e

Please sign in to comment.