mint icon indicating copy to clipboard operation
mint copied to clipboard

Destructure more complicated data structures

Open Namek opened this issue 5 years ago • 8 comments

Let's examine this ugly function:

enum FieldType {
  Island(Number, ConnectionSizes)
  Connection(Number)
}

/* in a module */
addConnection =
(
  idx1 : Number,
  idx2 : Number,
  genState : GenerationState
) : GenerationState {
  case (Map.get(idx1, genState.fieldsMap)) {
    Maybe::Just isl1 =>
      case (isl1) {
        FieldType::Island idx conns1 =>
          case (Map.get(idx2, genState.fieldsMap)) {
            Maybe::Just isl2 =>
              case (isl2) {
                FieldType::Island idx conns2 =>
                  try {
                    /* TODO update the genState */
                    genState
                  }

                => genState
              }

            => genState
          }

        => genState
      }

    => genState
  }
}

I would like to destructure tuple of 2 Maybes containing enums and directly access internal values of those enums.

case ({Map.get(idx1, genState.fieldsMap), Map.get(idx2, genState.fieldsMap)}) {
  {Maybe::Just(FieldType::Island(_, conns1)), Maybe::Just(FieldType::Island(_, conns2))} =>
    try {
      /* TODO update the genState */
      genState
    }

  => genState
}

Currently even a Tuple of built-in types is not destructurable.

Namek avatar Mar 21 '20 01:03 Namek

However, not just enums are important. Another useful case would be to destructure an array inside Maybe.

dirs = case (maybeDirections) {
  Maybe::Just([dir, ...restDirs]) =>
    try {
      /* TODO process the stuff */
    }
  => []
}

Namek avatar Mar 21 '20 18:03 Namek

I can take it

teggotic avatar May 04 '20 22:05 teggotic

@gdotdesign Could you help me a bit? @gdotdesign I have an issue when try getting a type of Ast::EnumDestructure on the compile stage. https://github.com/teggotic/mint/blob/19a247703cd2814a669fda0a5c5d73d18ee8abfb/src/compilers/case_branch.cr#L78 lookups[match] works on first function call, but params are not found there. This is the code Im trying to compile

enum A {
  B(D)
  C
}
enum D {
  E(String)
  F
}

component Main {
  fun test(str : String) : Html {
    <div>
      <{str}>
    </div>
  }

  fun isLoggedIn (userState : A) : Html {
    case (userState) {
      A::B (D::E str) => test(str)
      A::C => <span/>
    }
  }

  fun render() : Html {
    isLoggedIn(A::B(D::E("Hello world")))
  }
}

DeepinScreenshot_select-area_20200505031206

teggotic avatar May 05 '20 15:05 teggotic

The lookups map is populated in the type checking phase: for the EnumDestructuring it's here https://github.com/mint-lang/mint/blob/master/src/type_checkers/enum_destructuring.cr#L26

What is missing is that since EnumDestructuring can take other things than TypeVariable you need to type check them here: https://github.com/mint-lang/mint/blob/master/src/type_checkers/enum_destructuring.cr#L28 (resolve param) which will type check the nested EnumDestructuring and populate the correct key in lookups

gdotdesign avatar May 05 '20 16:05 gdotdesign

The lookups map is populated in the type checking phase: for the EnumDestructuring it's here https://github.com/mint-lang/mint/blob/master/src/type_checkers/enum_destructuring.cr#L26

What is missing is that since EnumDestructuring can take other things than TypeVariable you need to type check them here: https://github.com/mint-lang/mint/blob/master/src/type_checkers/enum_destructuring.cr#L28 (resolve param) which will type check the nested EnumDestructuring and populate the correct key in lookups

That worked out

teggotic avatar May 05 '20 19:05 teggotic

Trying to pick this back up. Will be taking from https://github.com/mint-lang/mint/pull/283

matthewmcgarvey avatar May 19 '21 18:05 matthewmcgarvey

One problem that I'm not sure of a good way to solve right now is how to make sure that nested destructuring of non-tuples doesn't happen outside of a case statements. The problem I'm thinking of is trying to destructure an Enum inside of a tuple. In the parsing level, the compiler would have to know that it can be a tuple destructuring but only other tuple destructurings can be in it and not other types of destructuring. https://github.com/mint-lang/mint/blob/a700b11d0d3124c7afdd57f757e4f3eaf468f1a0/src/parsers/tuple_destructuring.cr#L9

What do you think?

matthewmcgarvey avatar Jun 16 '21 03:06 matthewmcgarvey

In the parsing level, the compiler would have to know that it can be a tuple destructuring but only other tuple destructurings can be in it and not other types of destructuring.

I think this can be solved by having an argument for the tuple_destructuring function:

def tuple_destructuring(only_tuples_inside = false) : Ast::TupleDestructuring?

and then later on:

if only_tuples_inside
  tuple_destructuring(only_tuples_inside) || variable
else
  tuple_destructuring(only_tuples_inside) || variable || enum_destructuring
end

gdotdesign avatar Jun 16 '21 05:06 gdotdesign