Skip to content
This repository was archived by the owner on Oct 24, 2024. It is now read-only.

Positions for TOML nodes? #19

@olafurpg

Description

@olafurpg

Thank you for creating this project! I'm using toml-scala in new configuration library that I'm working on (adaptation of https://github.com/scalameta/metaconfig) and I'm curious if it would be possible to somehow expose position information in the toml.Value._ case classes.

My goal is to be able to report positioned type error messages when decoding TOML into Scala case classes, for example

# config.toml
booleanField = "stringValue"

The reported error would look like this

config.toml:0 error: Type mismatch;
  found    : String
  expected : Boolean
booleanField = "stringValue"
               ^

One way to achieve this with an immutable ADT with minimal boilerplate is to add a private var into the superclass

abstract class Value {
  private var myIndex: Option[Int] = None
  def position: Option[Int] = myIndex
  def withPosition(newIndex: Int): Value = {
    val copy = copyThis()
    copy.myIndex = Some(newIndex)
    copy
  }
  private[this] def copyThis(): Value = this match {
    case Value.Str(value) => Value.Str(value)
    // ...
  }
}

As long as copyThis().myIndex = is the only place where you mutate the var then the class remains effectively immutable. The position field can be added in a backwards compatible way, it doesn't affect Value equality semantics.

The Rules parser can then construct nodes with the Index fastparse parser and construct nodes with something like this (I didn't check if it compiles)

  val basicStr: Parser[Value.Str] =
    P(Index ~ (DoubleQuote.toString ~/ (strChars | escape).rep.! ~ DoubleQuote.toString))
      .map((index, str) => Value.Str(Unescape.unescapeJavaString(str)).withPosition(index))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions