Play

Changes On Branch modules
Login

Changes In Branch modules Excluding Merge-Ins

This is equivalent to a diff from 87090dea70 to 6eb1210a51

2021-03-30
08:57
Merge basic module and package support. check-in: 97ad30bba8 user: robin.hansen tags: trunk
2021-03-28
11:18
PackageLoader now successfully generates Qualified AST for a multi-module project. Skips validation,... Closed-Leaf check-in: 6eb1210a51 user: robin.hansen tags: modules
09:45
PackageLoader now provides Qualifier with information about available external modules. check-in: c20bd81f06 user: robin.hansen tags: modules
2021-02-13
07:46
Update copyright year in LICENSE. check-in: e0f1c277bd user: robin.hansen tags: trunk
2021-02-12
09:19
Merge new test script names from trunk. check-in: 4a3f3a82db user: robin.hansen tags: modules
06:31
Change name scheme of scripts. check-in: 87090dea70 user: robin.hansen tags: trunk
2021-02-01
05:29
Update dependencies check-in: 98700dab4b user: robin.hansen tags: trunk

Modified elm.json from [72ea3d105b] to [0b26ef7325].

4
5
6
7
8
9
10

11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29

30
31
32
        "src"
    ],
    "elm-version": "0.19.1",
    "dependencies": {
        "direct": {
            "elm/core": "1.0.5",
            "elm/html": "1.0.0",

            "elm/parser": "1.1.0",
            "elm-community/dict-extra": "2.4.0",
            "elm-community/list-extra": "8.2.3",
            "elm-community/result-extra": "2.4.0"
        },
        "indirect": {
            "elm/json": "1.1.3",
            "elm/virtual-dom": "1.0.2"
        }
    },
    "test-dependencies": {
        "direct": {
            "elm-explorations/test": "1.2.2",
            "elm-community/string-extra": "4.0.1"

        },
        "indirect": {
            "elm/random": "1.0.0",
            "elm/time": "1.0.0",
            "elm/regex": "1.0.0"

        }
    }
}







>






<





<
|
>



<
|
>



4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22

23
24
25
26
27

28
29
30
31
32
        "src"
    ],
    "elm-version": "0.19.1",
    "dependencies": {
        "direct": {
            "elm/core": "1.0.5",
            "elm/html": "1.0.0",
            "elm/json": "1.1.3",
            "elm/parser": "1.1.0",
            "elm-community/dict-extra": "2.4.0",
            "elm-community/list-extra": "8.2.3",
            "elm-community/result-extra": "2.4.0"
        },
        "indirect": {

            "elm/virtual-dom": "1.0.2"
        }
    },
    "test-dependencies": {
        "direct": {

            "elm-community/string-extra": "4.0.1",
            "elm-explorations/test": "1.2.2"
        },
        "indirect": {
            "elm/random": "1.0.0",

            "elm/regex": "1.0.0",
            "elm/time": "1.0.0"
        }
    }
}

Modified package-lock.json from [844e07d068] to [8a88db7fc1].

1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
....
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
....
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
....
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
....
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574

3575
3576
3577
3578
3579
3580
3581
....
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
....
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
....
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
....
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036











5037
5038
5039
5040
5041
5042
5043
....
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
    "binary-extensions": {
      "version": "2.2.0",
      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
      "dev": true
    },
    "binwrap": {
      "version": "0.2.2",
      "resolved": "https://registry.npmjs.org/binwrap/-/binwrap-0.2.2.tgz",
      "integrity": "sha512-Y+Wvypk3JhH5GPZAvlwJAWOVH/OsOhQMSj37vySuWHwQivoALplPxfBA8b973rFJI7OS+O+1YmmYXIiEXVMAcw==",
      "dev": true,
      "requires": {
        "mustache": "^3.0.1",
        "request": "^2.88.0",
        "request-promise": "^4.2.4",
        "tar": "^4.4.10",
        "unzip-stream": "^0.3.0"
      }
    },
    "bluebird": {
      "version": "3.7.2",
      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
      "dev": true
    },
    "brace-expansion": {
      "version": "1.1.11",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
      "dev": true,
      "requires": {
        "balanced-match": "^1.0.0",
................................................................................
          "integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==",
          "dev": true,
          "optional": true
        }
      }
    },
    "chownr": {
      "version": "1.1.4",
      "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
      "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
      "dev": true
    },
    "ci-info": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
      "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
      "dev": true
................................................................................
      "integrity": "sha512-dyBoPvFiNLvxOStQJdyq28gZEjS/enZXdZ5yyCtNtDEMbFJJVQq4pYNRKvhrKKdlxNot6d96iQe1uczoqO5yvA==",
      "dev": true,
      "requires": {
        "request": "^2.88.0"
      }
    },
    "elm-format": {
      "version": "0.8.4",
      "resolved": "https://registry.npmjs.org/elm-format/-/elm-format-0.8.4.tgz",
      "integrity": "sha512-0KurHC4MBUljdA2Sr+yzcoyAVqCku0LuNpvq5B3UIAlCPZ9PnOW2tUhVnQOCvp9RXngwbnsf18dE48tQ+s8r7g==",
      "dev": true,
      "requires": {
        "binwrap": "^0.2.2"
      }
    },
    "elm-test": {
      "version": "0.19.1-revision6",
      "resolved": "https://registry.npmjs.org/elm-test/-/elm-test-0.19.1-revision6.tgz",
      "integrity": "sha512-4VbIyCRlCUm/py0E0AjMT3/mwd6DR4Y5Z5gEox6z5JII6ZdKIJmcQzjgWRI5qo5ERJiw9M/Nxhk7SGXFUbZsxQ==",
      "dev": true,
................................................................................
      "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
      "dev": true,
      "requires": {
        "map-cache": "^0.2.2"
      }
    },
    "fs-minipass": {
      "version": "1.2.7",
      "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
      "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
      "dev": true,
      "requires": {
        "minipass": "^2.6.0"
      }
    },
    "fs.realpath": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
      "dev": true
................................................................................
    "minimist": {
      "version": "1.2.5",
      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
      "dev": true
    },
    "minipass": {
      "version": "2.9.0",
      "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
      "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
      "dev": true,
      "requires": {
        "safe-buffer": "^5.1.2",
        "yallist": "^3.0.0"
      }
    },
    "minizlib": {
      "version": "1.3.3",
      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
      "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
      "dev": true,
      "requires": {
        "minipass": "^2.9.0"

      }
    },
    "mixin-deep": {
      "version": "1.3.2",
      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
      "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
      "dev": true,
................................................................................
          "requires": {
            "is-plain-object": "^2.0.4"
          }
        }
      }
    },
    "mkdirp": {
      "version": "0.5.5",
      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
      "dev": true,
      "requires": {
        "minimist": "^1.2.5"
      }
    },
    "ms": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
      "dev": true
    },
    "mustache": {
      "version": "3.2.1",
      "resolved": "https://registry.npmjs.org/mustache/-/mustache-3.2.1.tgz",
      "integrity": "sha512-RERvMFdLpaFfSRIEe632yDm5nsd0SDKn8hGmcUwswnyiE5mtdZLDybtHAz6hjJhawokF0hXvGLtx9mrQfm6FkA==",
      "dev": true
    },
    "nanomatch": {
      "version": "1.2.13",
      "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
      "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
      "dev": true,
      "requires": {
        "arr-diff": "^4.0.0",
................................................................................
        "qs": "~6.5.2",
        "safe-buffer": "^5.1.2",
        "tough-cookie": "~2.5.0",
        "tunnel-agent": "^0.6.0",
        "uuid": "^3.3.2"
      }
    },
    "request-promise": {
      "version": "4.2.6",
      "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz",
      "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==",
      "dev": true,
      "requires": {
        "bluebird": "^3.5.0",
        "request-promise-core": "1.1.4",
        "stealthy-require": "^1.1.1",
        "tough-cookie": "^2.3.3"
      }
    },
    "request-promise-core": {
      "version": "1.1.4",
      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
      "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
      "dev": true,
      "requires": {
        "lodash": "^4.17.19"
................................................................................
    "symbol-tree": {
      "version": "3.2.4",
      "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
      "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
      "dev": true
    },
    "tar": {
      "version": "4.4.13",
      "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
      "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
      "dev": true,
      "requires": {
        "chownr": "^1.1.1",
        "fs-minipass": "^1.2.5",
        "minipass": "^2.8.6",
        "minizlib": "^1.2.1",
        "mkdirp": "^0.5.0",
        "safe-buffer": "^5.1.2",
        "yallist": "^3.0.3"
      }
    },
    "terminal-link": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
      "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==",
      "dev": true,
................................................................................
          "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
          "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
          "dev": true
        }
      }
    },
    "unzip-stream": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/unzip-stream/-/unzip-stream-0.3.0.tgz",
      "integrity": "sha512-NG1h/MdGIX3HzyqMjyj1laBCmlPYhcO4xEy7gEqqzGiSLw7XqDQCnY4nYSn5XSaH8mQ6TFkaujrO8d/PIZN85A==",
      "dev": true,
      "requires": {
        "binary": "^0.3.0",
        "mkdirp": "^0.5.1"











      }
    },
    "uri-js": {
      "version": "4.2.2",
      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
      "dev": true,
................................................................................
    "y18n": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
      "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
      "dev": true
    },
    "yallist": {
      "version": "3.1.1",
      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
      "dev": true
    },
    "yargs": {
      "version": "15.4.1",
      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
      "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
      "dev": true,







|
|
|


<

<
|
|


<
<
<
<
<
<







 







|
|
|







 







|
|
|


|







 







|
|
|


|







 







|
|
|


<
|



|
|
|


|
>







 







|
|
|
|
<
<
<







<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<







 







|
|
|


|
|
|
|
|
<
|







 







|
|
|




>
>
>
>
>
>
>
>
>
>
>







 







|
|
|







1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167

1168

1169
1170
1171
1172






1173
1174
1175
1176
1177
1178
1179
....
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
....
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
....
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
....
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555

3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
....
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594



3595
3596
3597
3598
3599
3600
3601






3602
3603
3604
3605
3606
3607
3608
....
4078
4079
4080
4081
4082
4083
4084












4085
4086
4087
4088
4089
4090
4091
....
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787

4788
4789
4790
4791
4792
4793
4794
4795
....
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
....
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
    "binary-extensions": {
      "version": "2.2.0",
      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
      "dev": true
    },
    "binwrap": {
      "version": "0.2.3",
      "resolved": "https://registry.npmjs.org/binwrap/-/binwrap-0.2.3.tgz",
      "integrity": "sha512-N4Pm7iyDEv0BrAMs+dny8WQa+e0nNTdzn2ODkf/MM6XBtKSCxCSUA1ZOQGoc1n7mUqdgOS5pwjsW91rmXVxy2Q==",
      "dev": true,
      "requires": {

        "request": "^2.88.0",

        "tar": "^6.1.0",
        "unzip-stream": "^0.3.1"
      }
    },






    "brace-expansion": {
      "version": "1.1.11",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
      "dev": true,
      "requires": {
        "balanced-match": "^1.0.0",
................................................................................
          "integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==",
          "dev": true,
          "optional": true
        }
      }
    },
    "chownr": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
      "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
      "dev": true
    },
    "ci-info": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
      "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
      "dev": true
................................................................................
      "integrity": "sha512-dyBoPvFiNLvxOStQJdyq28gZEjS/enZXdZ5yyCtNtDEMbFJJVQq4pYNRKvhrKKdlxNot6d96iQe1uczoqO5yvA==",
      "dev": true,
      "requires": {
        "request": "^2.88.0"
      }
    },
    "elm-format": {
      "version": "0.8.5",
      "resolved": "https://registry.npmjs.org/elm-format/-/elm-format-0.8.5.tgz",
      "integrity": "sha512-/Mjwz5RhJ8cdcMsHT98AEKprSIHyRde+URIPvnHez9WH7Xp+rFCOJx0FNMPIYrbHE9Ei7HDSVwhjDP0i+mlvpQ==",
      "dev": true,
      "requires": {
        "binwrap": "^0.2.3"
      }
    },
    "elm-test": {
      "version": "0.19.1-revision6",
      "resolved": "https://registry.npmjs.org/elm-test/-/elm-test-0.19.1-revision6.tgz",
      "integrity": "sha512-4VbIyCRlCUm/py0E0AjMT3/mwd6DR4Y5Z5gEox6z5JII6ZdKIJmcQzjgWRI5qo5ERJiw9M/Nxhk7SGXFUbZsxQ==",
      "dev": true,
................................................................................
      "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
      "dev": true,
      "requires": {
        "map-cache": "^0.2.2"
      }
    },
    "fs-minipass": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
      "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
      "dev": true,
      "requires": {
        "minipass": "^3.0.0"
      }
    },
    "fs.realpath": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
      "dev": true
................................................................................
    "minimist": {
      "version": "1.2.5",
      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
      "dev": true
    },
    "minipass": {
      "version": "3.1.3",
      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
      "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==",
      "dev": true,
      "requires": {

        "yallist": "^4.0.0"
      }
    },
    "minizlib": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
      "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
      "dev": true,
      "requires": {
        "minipass": "^3.0.0",
        "yallist": "^4.0.0"
      }
    },
    "mixin-deep": {
      "version": "1.3.2",
      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
      "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
      "dev": true,
................................................................................
          "requires": {
            "is-plain-object": "^2.0.4"
          }
        }
      }
    },
    "mkdirp": {
      "version": "1.0.4",
      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
      "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
      "dev": true



    },
    "ms": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
      "dev": true
    },






    "nanomatch": {
      "version": "1.2.13",
      "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
      "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
      "dev": true,
      "requires": {
        "arr-diff": "^4.0.0",
................................................................................
        "qs": "~6.5.2",
        "safe-buffer": "^5.1.2",
        "tough-cookie": "~2.5.0",
        "tunnel-agent": "^0.6.0",
        "uuid": "^3.3.2"
      }
    },












    "request-promise-core": {
      "version": "1.1.4",
      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
      "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
      "dev": true,
      "requires": {
        "lodash": "^4.17.19"
................................................................................
    "symbol-tree": {
      "version": "3.2.4",
      "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
      "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
      "dev": true
    },
    "tar": {
      "version": "6.1.0",
      "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
      "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
      "dev": true,
      "requires": {
        "chownr": "^2.0.0",
        "fs-minipass": "^2.0.0",
        "minipass": "^3.0.0",
        "minizlib": "^2.1.1",
        "mkdirp": "^1.0.3",

        "yallist": "^4.0.0"
      }
    },
    "terminal-link": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
      "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==",
      "dev": true,
................................................................................
          "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
          "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
          "dev": true
        }
      }
    },
    "unzip-stream": {
      "version": "0.3.1",
      "resolved": "https://registry.npmjs.org/unzip-stream/-/unzip-stream-0.3.1.tgz",
      "integrity": "sha512-RzaGXLNt+CW+T41h1zl6pGz3EaeVhYlK+rdAap+7DxW5kqsqePO8kRtWPaCiVqdhZc86EctSPVYNix30YOMzmw==",
      "dev": true,
      "requires": {
        "binary": "^0.3.0",
        "mkdirp": "^0.5.1"
      },
      "dependencies": {
        "mkdirp": {
          "version": "0.5.5",
          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
          "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
          "dev": true,
          "requires": {
            "minimist": "^1.2.5"
          }
        }
      }
    },
    "uri-js": {
      "version": "4.2.2",
      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
      "dev": true,
................................................................................
    "y18n": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
      "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
      "dev": true
    },
    "yallist": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
      "dev": true
    },
    "yargs": {
      "version": "15.4.1",
      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
      "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
      "dev": true,

Modified package.json from [9974fb2cf5] to [ad181fde73].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "name": "play",
  "version": "0.0.1",
  "description": "",
  "dependencies": {},
  "devDependencies": {
    "elm": "^0.19.1-5",
    "elm-format": "^0.8.4",
    "elm-test": "^0.19.1-revision6",
    "jest": "^26.6.3",
    "strip-indent": "^3.0.0",
    "wabt": "^1.0.20"
  },
  "scripts": {
    "test": "npm run test:elm && npm run test:wasm",







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "name": "play",
  "version": "0.0.1",
  "description": "",
  "dependencies": {},
  "devDependencies": {
    "elm": "^0.19.1-5",
    "elm-format": "^0.8.5",
    "elm-test": "^0.19.1-revision6",
    "jest": "^26.6.3",
    "strip-indent": "^3.0.0",
    "wabt": "^1.0.20"
  },
  "scripts": {
    "test": "npm run test:elm && npm run test:wasm",

Modified src/Main.elm from [e1269bbd45] to [fe49ef1d5b].

54
55
56
57
58
59
60


61






62
63
64
65
66
67
68
compile : String -> Result String Wasm.Module
compile sourceCode =
    case Parser.run sourceCode of
        Err parserErrors ->
            formatErrors (ParserProblem.toString sourceCode) parserErrors

        Ok ast ->


            case Qualifier.run ast of






                Err qualifierErrors ->
                    formatErrors (QualifierProblem.toString sourceCode) qualifierErrors

                Ok qualifiedAst ->
                    case TypeChecker.run qualifiedAst of
                        Err typeErrors ->
                            formatErrors (TypeCheckerProblem.toString sourceCode) typeErrors







>
>
|
>
>
>
>
>
>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
compile : String -> Result String Wasm.Module
compile sourceCode =
    case Parser.run sourceCode of
        Err parserErrors ->
            formatErrors (ParserProblem.toString sourceCode) parserErrors

        Ok ast ->
            let
                qualifierResult =
                    Qualifier.run
                        { packageName = ""
                        , modulePath = ""
                        , ast = ast
                        }
            in
            case qualifierResult of
                Err qualifierErrors ->
                    formatErrors (QualifierProblem.toString sourceCode) qualifierErrors

                Ok qualifiedAst ->
                    case TypeChecker.run qualifiedAst of
                        Err typeErrors ->
                            formatErrors (TypeCheckerProblem.toString sourceCode) typeErrors

Added src/Play/Data/ModuleName.elm version [1e115d5ae1].























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
module Play.Data.ModuleName exposing
    ( ModuleName
    , fromString
    , toPartStrings
    , toString
    )

import Play.Data.PackageName as PackageName


type ModuleName
    = ModuleName String


fromString : String -> Result () ModuleName
fromString str =
    let
        parts =
            String.split "/" str
    in
    if List.any PackageName.invalidPart parts then
        Err ()

    else
        Ok <| ModuleName <| String.join "/" parts



-- TODO: missing tests


toPartStrings : ModuleName -> List String
toPartStrings (ModuleName str) =
    String.split "/" str



-- TODO: missing test


toString : ModuleName -> String
toString (ModuleName str) =
    str

Added src/Play/Data/PackageMetadata.elm version [cab47e39e5].

































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
module Play.Data.PackageMetadata exposing
    ( PackageMetadata
    , decoder
    )

import Dict exposing (Dict)
import Json.Decode as Json
import Play.Data.ModuleName as ModuleName exposing (ModuleName)
import Play.Data.PackageName as PackageName exposing (PackageName)
import Play.Data.PackagePath as PackagePath exposing (PackagePath)
import Play.Data.SemanticVersion as SemanticVersion exposing (SemanticVersion)


type alias PackageMetadata =
    { name : PackageName
    , version : SemanticVersion
    , compatibleLanguageVersion : SemanticVersion
    , exposedModules : List ModuleName
    , dependencies : Dict String SemanticVersion
    , packagePaths : List PackagePath
    }


decoder : Json.Decoder PackageMetadata
decoder =
    Json.map6 PackageMetadata
        (Json.field "name" packageNameDecoder)
        (Json.field "version" semverDecoder)
        (Json.field "language-version" semverDecoder)
        (Json.field "exposed-modules" (Json.list moduleNameDecoder))
        (Json.field "dependencies" (Json.dict semverDecoder |> Json.andThen validateDependencyKeys))
        (Json.field "package-paths" (Json.list packagePathDecoder))


packageNameDecoder : Json.Decoder PackageName
packageNameDecoder =
    Json.string
        |> Json.andThen (resultDecodeAdapt << PackageName.fromString)


semverDecoder : Json.Decoder SemanticVersion
semverDecoder =
    Json.string
        |> Json.andThen (resultDecodeAdapt << SemanticVersion.fromString)


moduleNameDecoder : Json.Decoder ModuleName
moduleNameDecoder =
    Json.string
        |> Json.andThen (resultDecodeAdapt << ModuleName.fromString)


packagePathDecoder : Json.Decoder PackagePath
packagePathDecoder =
    Json.string
        |> Json.map PackagePath.fromString


validateDependencyKeys : Dict String SemanticVersion -> Json.Decoder (Dict String SemanticVersion)
validateDependencyKeys deps =
    let
        isValid =
            Dict.keys deps
                |> List.all (\k -> Result.toMaybe (PackageName.fromString k) /= Nothing)
    in
    if isValid then
        Json.succeed deps

    else
        Json.fail "Invalid dependency package name"


resultDecodeAdapt : Result err ok -> Json.Decoder ok
resultDecodeAdapt result =
    case result of
        Ok value ->
            Json.succeed value

        Err err ->
            Json.fail "Something went wrong"

Added src/Play/Data/PackageName.elm version [83dc1a13a9].





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
module Play.Data.PackageName exposing
    ( PackageName
    , fromString
    , invalidPart
    , toString
    )


type PackageName
    = PackageName String String


fromString : String -> Result () PackageName
fromString str =
    case String.split "/" str of
        [ part1, part2 ] ->
            if invalidPart part1 || invalidPart part2 then
                Err ()

            else
                Ok <| PackageName part1 part2

        _ ->
            Err ()


invalidPart : String -> Bool
invalidPart str =
    case String.uncons str of
        Nothing ->
            True

        Just ( first, rest ) ->
            not
                (Char.isLower first
                    && String.all (\c -> Char.isLower c || Char.isDigit c || c == '_') rest
                )


toString : PackageName -> String
toString (PackageName group name) =
    group ++ "/" ++ name

Added src/Play/Data/PackagePath.elm version [b58e74fd1c].





























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
module Play.Data.PackagePath exposing
    ( PackagePath(..)
    , fromString
    , prefix
    )


type PackagePath
    = Directory String
    | AllDirectoriesInDirectory String


fromString : String -> PackagePath
fromString str =
    let
        ctor =
            if String.endsWith "*" str then
                AllDirectoriesInDirectory

            else
                Directory

        charsToDrop =
            if String.endsWith "/*" str then
                2

            else if String.endsWith "*" str then
                1

            else if String.endsWith "/" str then
                1

            else
                0
    in
    ctor <| String.dropRight charsToDrop str


prefix : String -> PackagePath -> PackagePath
prefix pathToPrefix packagePath =
    case packagePath of
        Directory dir ->
            Directory <| pathToPrefix ++ "/" ++ dir

        AllDirectoriesInDirectory dir ->
            AllDirectoriesInDirectory <| pathToPrefix ++ "/" ++ dir

Added src/Play/Data/SemanticVersion.elm version [b8b4cd3223].



















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
module Play.Data.SemanticVersion exposing
    ( Compatibility(..)
    , ParseError(..)
    , SemanticVersion
    , compatible
    , fromString
    )


type SemanticVersion
    = SemanticVersion Int Int Int


type ParseError
    = InvalidFormat String
    | ExpectedInteger String
    | NegativeVersions String
    | LessThanMinimumVersion String


fromString : String -> Result ParseError SemanticVersion
fromString str =
    case String.split "." str of
        [ major, minor, patch ] ->
            fromInts str major minor patch

        _ ->
            Err <| InvalidFormat str


fromInts : String -> String -> String -> String -> Result ParseError SemanticVersion
fromInts originalStr majorStr minorStr patchStr =
    let
        intVersions =
            [ majorStr, minorStr, patchStr ]
                |> List.filterMap String.toInt
    in
    case intVersions of
        [ major, minor, patch ] ->
            if major < 0 || minor < 0 || patch < 0 then
                Err <| NegativeVersions originalStr

            else if major == 0 && minor == 0 && patch < 1 then
                Err <| LessThanMinimumVersion originalStr

            else
                Ok <| SemanticVersion major minor patch

        _ ->
            Err <| ExpectedInteger originalStr


type Compatibility
    = Incompatible
    | LessThan
    | GreaterThanOrEqual


compatible : SemanticVersion -> SemanticVersion -> Compatibility
compatible (SemanticVersion lhsMajor lhsMinor lhsPatch) (SemanticVersion rhsMajor rhsMinor rhsPatch) =
    if lhsMajor /= rhsMajor then
        Incompatible

    else
        case compare lhsMinor rhsMinor of
            GT ->
                if lhsMajor == 0 then
                    Incompatible

                else
                    LessThan

            LT ->
                if lhsMajor == 0 then
                    Incompatible

                else
                    GreaterThanOrEqual

            EQ ->
                case compare lhsPatch rhsPatch of
                    GT ->
                        LessThan

                    EQ ->
                        GreaterThanOrEqual

                    LT ->
                        GreaterThanOrEqual

Added src/Play/PackageLoader.elm version [fe3c68a4e4].



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
module Play.PackageLoader exposing
    ( Model(..)
    , Msg(..)
    , Problem(..)
    , SideEffect(..)
    , init
    , update
    )

import Dict exposing (Dict)
import Json.Decode as Json
import List.Extra as List
import Play.Data.ModuleName as ModuleName exposing (ModuleName)
import Play.Data.PackageMetadata as PackageMetadata exposing (PackageMetadata)
import Play.Data.PackageName as PackageName exposing (PackageName)
import Play.Data.PackagePath as PackagePath exposing (PackagePath)
import Play.Data.SemanticVersion as SemanticVersion exposing (SemanticVersion)
import Play.Parser as Parser
import Play.Qualifier as Qualifier
import Result.Extra as Result
import Set exposing (Set)


type Problem
    = InvalidPackageMetadata String String
    | UnknownMessageForState String
    | NoExposedModulesInRootProject
    | ModuleNotFound String
    | InternalError String


type Model
    = Initializing SideEffect
    | LoadingMetadata State (List PackagePath) SideEffect
    | ResolvingModulePaths State (List PackageInfo) SideEffect
    | Compiling State (List ( PackageInfo, ModuleName )) SideEffect
    | Done Qualifier.ExposedAST
    | Failed Problem


type alias State =
    { rootPackage : PackageInfo
    , dependencies : Dict String SemanticVersion
    , dependentPackages : Dict String PackageInfo
    , filePathToModule : Dict String ( PackageName, ModuleName )
    , moduleNameToPackageName : Dict String String
    , absoluteModuleNameToDetails : Dict String ( PackageInfo, ModuleName )
    , inProgressAst : Maybe Qualifier.AST
    , parsedModules : Set String
    }


type alias PackageInfo =
    { path : String
    , metadata : PackageMetadata
    , modules : List ModuleName
    }


emptyState : PackageInfo -> State
emptyState rootPackage =
    { rootPackage = rootPackage
    , dependencies = rootPackage.metadata.dependencies
    , dependentPackages = Dict.empty
    , filePathToModule = Dict.empty
    , moduleNameToPackageName = Dict.empty
    , absoluteModuleNameToDetails = Dict.empty
    , inProgressAst = Nothing
    , parsedModules = Set.empty
    }


type Msg
    = FileContents String String String
    | ResolvedDirectories String (List PackagePath)
    | ResolvedPackageModules String (List String)


type SideEffect
    = ReadFile String String
    | ResolveDirectories String
    | ResolvePackageModules String String


init : String -> Model
init projectDirPath =
    Initializing
        (ReadFile projectDirPath "play.json")


update : Msg -> Model -> Model
update msg model =
    case model of
        Initializing _ ->
            case msg of
                FileContents path _ content ->
                    case Json.decodeString PackageMetadata.decoder content of
                        Ok metadata ->
                            let
                                state =
                                    emptyState
                                        { path = path
                                        , metadata = metadata
                                        , modules = []
                                        }

                                pathsToLoad =
                                    List.map (PackagePath.prefix path) metadata.packagePaths
                            in
                            case pathsToLoad of
                                [] ->
                                    ResolvingModulePaths state [] <|
                                        ResolvePackageModules (PackageName.toString metadata.name) path

                                (PackagePath.Directory nextPathDir) :: _ ->
                                    LoadingMetadata state pathsToLoad <|
                                        ReadFile nextPathDir "play.json"

                                (PackagePath.AllDirectoriesInDirectory nextPathDir) :: _ ->
                                    LoadingMetadata state pathsToLoad <|
                                        ResolveDirectories nextPathDir

                        Err err ->
                            Failed <| InvalidPackageMetadata path <| Json.errorToString err

                _ ->
                    Failed (InvalidPackageMetadata "todo: path" "Wrong message on initialization")

        LoadingMetadata state remainingPaths _ ->
            loadingMetadataUpdate msg state remainingPaths

        ResolvingModulePaths state remainingPackages _ ->
            resolvingModulePathsUpdate msg state remainingPackages

        Compiling state remainingModules _ ->
            compilingUpdate msg state remainingModules

        Done _ ->
            model

        Failed _ ->
            model


loadingMetadataUpdate : Msg -> State -> List PackagePath -> Model
loadingMetadataUpdate msg state remainingPaths =
    let
        nextStep pathsToLoad nextState pathPrefix =
            case pathsToLoad of
                [] ->
                    ResolvingModulePaths nextState
                        (Dict.values nextState.dependentPackages)
                        (ResolvePackageModules
                            (PackageName.toString nextState.rootPackage.metadata.name)
                            nextState.rootPackage.path
                        )

                (PackagePath.Directory nextPathDir) :: _ ->
                    LoadingMetadata nextState pathsToLoad <|
                        ReadFile nextPathDir "play.json"

                (PackagePath.AllDirectoriesInDirectory nextPathDir) :: _ ->
                    LoadingMetadata nextState pathsToLoad <|
                        ResolveDirectories (pathPrefix ++ nextPathDir)
    in
    case msg of
        FileContents path _ content ->
            case Json.decodeString PackageMetadata.decoder content of
                Ok metadata ->
                    case Dict.get (PackageName.toString metadata.name) state.dependencies of
                        Nothing ->
                            -- This package is not required, so ignore it
                            let
                                pathsToLoad =
                                    List.remove (PackagePath.Directory path) remainingPaths
                            in
                            nextStep pathsToLoad state ""

                        Just _ ->
                            let
                                updatedState =
                                    -- TODO: Register dependencies of sub-packages
                                    { state
                                        | dependentPackages =
                                            Dict.update
                                                (PackageName.toString metadata.name)
                                                (insertHighestPackage
                                                    { path = path
                                                    , metadata = metadata
                                                    , modules = []
                                                    }
                                                )
                                                state.dependentPackages
                                    }

                                absolutePackagePaths =
                                    List.map (PackagePath.prefix path) metadata.packagePaths

                                pathsToLoad =
                                    remainingPaths
                                        |> List.remove (PackagePath.Directory path)
                                        |> (++) absolutePackagePaths
                            in
                            nextStep pathsToLoad updatedState ""

                Err err ->
                    Debug.todo (Json.errorToString err)

        ResolvedDirectories parentDir paths ->
            let
                pathsToLoad =
                    remainingPaths
                        |> List.remove (PackagePath.AllDirectoriesInDirectory parentDir)
                        |> (++) paths
            in
            nextStep pathsToLoad state (parentDir ++ "/")

        _ ->
            Failed <| UnknownMessageForState "LoadingMetadata"


insertHighestPackage : PackageInfo -> Maybe PackageInfo -> Maybe PackageInfo
insertHighestPackage packageInfo maybeExistingPackage =
    case maybeExistingPackage of
        Nothing ->
            Just packageInfo

        Just existingPackage ->
            if
                SemanticVersion.compatible
                    existingPackage.metadata.version
                    packageInfo.metadata.version
                    == SemanticVersion.GreaterThanOrEqual
            then
                Just packageInfo

            else
                Just existingPackage


resolvingModulePathsUpdate : Msg -> State -> List PackageInfo -> Model
resolvingModulePathsUpdate msg state remainingPackages =
    case msg of
        ResolvedPackageModules packageName modules ->
            let
                rootPackage =
                    state.rootPackage

                moduleNameResults =
                    List.map (String.replace ".play" "") modules
                        |> List.map ModuleName.fromString
                        |> Result.combine

                updatedRemainingPackages =
                    List.filter (\p -> PackageName.toString p.metadata.name /= packageName) remainingPackages

                nextStep newState =
                    case updatedRemainingPackages of
                        nextPackage :: _ ->
                            ResolvingModulePaths newState
                                updatedRemainingPackages
                                (ResolvePackageModules (PackageName.toString nextPackage.metadata.name) nextPackage.path)

                        [] ->
                            initCompileStep newState
            in
            case moduleNameResults of
                Err _ ->
                    Failed <| InternalError <| "Invalid module names for package " ++ packageName

                Ok moduleNames ->
                    if packageName == PackageName.toString state.rootPackage.metadata.name then
                        nextStep { state | rootPackage = { rootPackage | modules = moduleNames } }

                    else
                        case Dict.get packageName state.dependentPackages of
                            Nothing ->
                                Failed <| InternalError <| "Package " ++ packageName ++ " doesn't exist"

                            Just package ->
                                nextStep
                                    { state
                                        | dependentPackages =
                                            Dict.insert packageName { package | modules = moduleNames } state.dependentPackages
                                    }

        _ ->
            Failed <| UnknownMessageForState "ResolvingModulePaths"


initCompileStep : State -> Model
initCompileStep state =
    case state.rootPackage.metadata.exposedModules of
        [] ->
            Failed NoExposedModulesInRootProject

        firstExposedModule :: remModules ->
            if List.member firstExposedModule state.rootPackage.modules then
                let
                    ( path, fileName ) =
                        readModuleFromDisk state.rootPackage.path firstExposedModule

                    allPackages =
                        state.rootPackage :: Dict.values state.dependentPackages

                    pathsToModuleNames =
                        List.foldl pathsOfModules Dict.empty allPackages

                    moduleNameToPackageName =
                        List.foldl absolutePathsOfModules Dict.empty allPackages

                    absoluteNameToDetails =
                        allPackages
                            |> List.concatMap (\pInfo -> List.map (\m -> ( pInfo, m )) pInfo.modules)
                            |> List.map (\( pInfo, mName ) -> ( absoluteModuleName pInfo.metadata.name mName, ( pInfo, mName ) ))
                            |> Dict.fromList
                in
                Compiling
                    { state
                        | filePathToModule = pathsToModuleNames
                        , moduleNameToPackageName = moduleNameToPackageName
                        , absoluteModuleNameToDetails = absoluteNameToDetails
                    }
                    (List.map (\m -> ( state.rootPackage, m )) remModules)
                    (ReadFile path fileName)

            else
                Failed (ModuleNotFound (ModuleName.toString firstExposedModule))


readModuleFromDisk : String -> ModuleName -> ( String, String )
readModuleFromDisk packagePath moduleName =
    let
        ( path, fileName ) =
            case List.reverse (ModuleName.toPartStrings moduleName) of
                name :: reversePath ->
                    ( reversePath
                        |> List.reverse
                        |> String.join "/"
                    , name ++ ".play"
                    )

                _ ->
                    ( "", "" )
    in
    ( [ packagePath, "src", path ]
        |> List.filter (not << String.isEmpty)
        |> String.join "/"
    , fileName
    )


pathsOfModules : PackageInfo -> Dict String ( PackageName, ModuleName ) -> Dict String ( PackageName, ModuleName )
pathsOfModules package acc =
    let
        modulePaths =
            List.map (\moduleName -> ( pathToModule moduleName, ( package.metadata.name, moduleName ) )) package.modules
                |> Dict.fromList

        pathToModule moduleName =
            let
                ( path, fileName ) =
                    readModuleFromDisk package.path moduleName
            in
            path ++ "/" ++ fileName
    in
    Dict.union acc modulePaths


absolutePathsOfModules : PackageInfo -> Dict String String -> Dict String String
absolutePathsOfModules package acc =
    let
        absolutePathsForModule =
            List.map
                (\moduleName ->
                    ( "/" ++ ModuleName.toString moduleName
                    , PackageName.toString package.metadata.name
                    )
                )
                package.modules
                |> Dict.fromList
    in
    Dict.union acc absolutePathsForModule


compilingUpdate : Msg -> State -> List ( PackageInfo, ModuleName ) -> Model
compilingUpdate msg state remainingModules =
    case msg of
        FileContents path fileName content ->
            let
                fullPath =
                    path ++ "/" ++ fileName

                possibleModuleInfo =
                    Dict.get fullPath state.filePathToModule
            in
            case ( possibleModuleInfo, Parser.run content ) of
                ( _, Err parserError ) ->
                    Failed <| InternalError <| "Parser error: " ++ Debug.toString parserError

                ( Just ( packageName, moduleName ), Ok parserAst ) ->
                    let
                        qualifierResult =
                            Qualifier.run
                                { packageName = PackageName.toString packageName
                                , modulePath = ModuleName.toString moduleName
                                , ast = parserAst
                                , externalModules = state.moduleNameToPackageName
                                }
                    in
                    case qualifierResult of
                        Err qualifierError ->
                            Failed <| InternalError <| "Qualifier error: " ++ Debug.toString qualifierError

                        Ok qualifiedAST ->
                            let
                                fullModuleName =
                                    absoluteModuleName packageName moduleName

                                mergedQualifiedAst =
                                    state.inProgressAst
                                        |> Maybe.map
                                            (\ipa ->
                                                { additionalModulesRequired =
                                                    Set.union
                                                        ipa.additionalModulesRequired
                                                        qualifiedAST.additionalModulesRequired
                                                , checkForExistingTypes =
                                                    Set.union
                                                        ipa.checkForExistingTypes
                                                        qualifiedAST.checkForExistingTypes
                                                , checkForExistingWords =
                                                    Set.union
                                                        ipa.checkForExistingWords
                                                        qualifiedAST.checkForExistingWords
                                                , types = Dict.union ipa.types qualifiedAST.types
                                                , words = Dict.union ipa.words qualifiedAST.words
                                                }
                                            )
                                        |> Maybe.withDefault qualifiedAST

                                updatedParsedModules =
                                    Set.insert fullModuleName state.parsedModules

                                modulesQueuedForOrAlreadyParsed =
                                    remainingModules
                                        |> List.map (\( pInfo, mName ) -> absoluteModuleName pInfo.metadata.name mName)
                                        |> Set.fromList
                                        |> Set.union updatedParsedModules

                                missingModulesInParseQueue =
                                    Set.diff mergedQualifiedAst.additionalModulesRequired modulesQueuedForOrAlreadyParsed
                                        |> Set.toList
                                        |> List.filterMap (\absName -> Dict.get absName state.absoluteModuleNameToDetails)

                                updatedRemainingModules =
                                    missingModulesInParseQueue ++ remainingModules
                            in
                            nextCompileStep updatedParsedModules mergedQualifiedAst updatedRemainingModules state

                ( Nothing, _ ) ->
                    Failed <| InternalError <| "Don't know why we read file: " ++ fullPath

        _ ->
            Failed <| InternalError <| "Unknown message for compile stage: " ++ Debug.toString msg


absoluteModuleName : PackageName -> ModuleName -> String
absoluteModuleName packageName moduleName =
    "/" ++ PackageName.toString packageName ++ "/" ++ ModuleName.toString moduleName


nextCompileStep : Set String -> Qualifier.AST -> List ( PackageInfo, ModuleName ) -> State -> Model
nextCompileStep parsedModules inProgressAst remainingModules state =
    case remainingModules of
        [] ->
            Done
                { types = inProgressAst.types
                , words = inProgressAst.words
                }

        ( packageInfo, moduleName ) :: otherModules ->
            let
                ( path, fileName ) =
                    readModuleFromDisk packageInfo.path moduleName
            in
            Compiling
                { state
                    | parsedModules = parsedModules
                    , inProgressAst = Just inProgressAst
                }
                otherModules
                (ReadFile path fileName)

Modified src/Play/Parser.elm from [0674f5af9e] to [8b0faf8562].

57
58
59
60
61
62
63


64
65
66
67
68
69
70
..
94
95
96
97
98
99
100

101

102
103
104
105
106
107
108
...
174
175
176
177
178
179
180













































































181
182
183
184
185
186
187
...
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
    | LiteralType Type
    | RecursiveMatch TypeMatch


type AstNode
    = Integer SourceLocationRange Int
    | Word SourceLocationRange String


    | Quotation SourceLocationRange (List AstNode)
    | ConstructType String
    | GetMember String String
    | SetMember String String


run : String -> Result (List Problem) AST
................................................................................
        , '{'
        , '}'
        , '['
        , ']'
        , '('
        , ')'
        , '.'

        , '#'

        ]


whitespaceChars : Set Char
whitespaceChars =
    Set.fromList
        [ ' '
................................................................................
                |. Parser.symbol (Token ":" NotMetadata)
                |> Parser.andThen (\_ -> Parser.problem FoundMetadata)
            , Parser.succeed identity
            ]
        |. noiseParser
        |> Parser.backtrackable















































































definitionMetadataParser : Parser String
definitionMetadataParser =
    Parser.variable
        { start = \c -> not (Char.isDigit c || Char.isUpper c || Set.member c invalidSymbolChars)
        , inner = validSymbolChar
        , reserved = Set.fromList [ "def", "defmulti", "defstruct", "defunion" ]
................................................................................
nodeParser : Parser AstNode
nodeParser =
    Parser.oneOf
        [ Parser.succeed (\startLoc value endLoc -> Integer (SourceLocationRange startLoc endLoc) value)
            |= sourceLocationParser
            |= intParser
            |= sourceLocationParser
        , Parser.succeed (\startLoc value endLoc -> Word (SourceLocationRange startLoc endLoc) value)
            |= sourceLocationParser
            |= symbolImplParser
            |= sourceLocationParser
        ]


typeDefinitionName : TypeDefinition -> String
typeDefinitionName typeDef =
    case typeDef of







>
>







 







>

>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|

|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
..
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
...
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
    | LiteralType Type
    | RecursiveMatch TypeMatch


type AstNode
    = Integer SourceLocationRange Int
    | Word SourceLocationRange String
    | PackageWord SourceLocationRange (List String) String
    | ExternalWord SourceLocationRange (List String) String
    | Quotation SourceLocationRange (List AstNode)
    | ConstructType String
    | GetMember String String
    | SetMember String String


run : String -> Result (List Problem) AST
................................................................................
        , '{'
        , '}'
        , '['
        , ']'
        , '('
        , ')'
        , '.'
        , ','
        , '#'
        , '/'
        ]


whitespaceChars : Set Char
whitespaceChars =
    Set.fromList
        [ ' '
................................................................................
                |. Parser.symbol (Token ":" NotMetadata)
                |> Parser.andThen (\_ -> Parser.problem FoundMetadata)
            , Parser.succeed identity
            ]
        |. noiseParser
        |> Parser.backtrackable


symbolImplParser2 : Parser (SourceLocationRange -> AstNode)
symbolImplParser2 =
    let
        externalBuilder firstSymbol (( partialPath, reference ) as modulePathResult) =
            let
                path =
                    firstSymbol :: partialPath
            in
            if checkForUpperCaseLetterInPath path then
                Parser.problem <| InvalidModulePath <| "/" ++ String.join "/" path

            else if modulePathResult == ( [], "" ) then
                Parser.problem <| InvalidModulePath <| "/" ++ firstSymbol

            else
                Parser.succeed <|
                    \loc ->
                        ExternalWord loc path reference

        internalBuilder firstSymbol (( partialPath, reference ) as modulePathResult) =
            let
                path =
                    firstSymbol :: partialPath
            in
            if checkForUpperCaseLetterInPath path && partialPath /= [] then
                Parser.problem <| InvalidModulePath <| String.join "/" path

            else
                Parser.succeed <|
                    \loc ->
                        if modulePathResult == ( [], "" ) then
                            Word loc firstSymbol

                        else
                            PackageWord loc path reference

        checkForUpperCaseLetterInPath path =
            List.any (String.any Char.isUpper) path
    in
    Parser.oneOf
        [ Parser.succeed externalBuilder
            |. Parser.symbol (Token "/" NotMetadata)
            |= symbolImplParser
            |= Parser.loop [] modulePathParser
        , Parser.succeed internalBuilder
            |= symbolImplParser
            |= Parser.oneOf
                [ Parser.loop [] modulePathParser
                , Parser.succeed ( [], "" )
                ]
        ]
        |> Parser.andThen identity


modulePathParser : List String -> Parser (Parser.Step (List String) ( List String, String ))
modulePathParser symbols =
    Parser.oneOf
        [ Parser.succeed (\name -> Parser.Loop (name :: symbols))
            |. Parser.symbol (Token "/" NotMetadata)
            |= symbolImplParser
        , Parser.succeed (Parser.Done (modulePathFinalizer symbols))
        ]


modulePathFinalizer : List String -> ( List String, String )
modulePathFinalizer symbols =
    case symbols of
        [] ->
            ( [], "" )

        [ only ] ->
            ( [], only )

        first :: rest ->
            ( List.reverse rest, first )


definitionMetadataParser : Parser String
definitionMetadataParser =
    Parser.variable
        { start = \c -> not (Char.isDigit c || Char.isUpper c || Set.member c invalidSymbolChars)
        , inner = validSymbolChar
        , reserved = Set.fromList [ "def", "defmulti", "defstruct", "defunion" ]
................................................................................
nodeParser : Parser AstNode
nodeParser =
    Parser.oneOf
        [ Parser.succeed (\startLoc value endLoc -> Integer (SourceLocationRange startLoc endLoc) value)
            |= sourceLocationParser
            |= intParser
            |= sourceLocationParser
        , Parser.succeed (\startLoc builder endLoc -> builder (SourceLocationRange startLoc endLoc))
            |= sourceLocationParser
            |= symbolImplParser2
            |= sourceLocationParser
        ]


typeDefinitionName : TypeDefinition -> String
typeDefinitionName typeDef =
    case typeDef of

Modified src/Play/Parser/Problem.elm from [1260a0c31a] to [7563961c4b].

19
20
21
22
23
24
25

26
27
28
29
30
31
32
..
91
92
93
94
95
96
97



    | ExpectedEnd
    | ExpectedTypeSeperator
    | ExpectedLeftBracket
    | ExpectedRightBracket
    | WordAlreadyDefined String (Maybe SourceLocationRange) (Maybe SourceLocationRange)
    | TypeAlreadyDefined String SourceLocationRange SourceLocationRange
    | UnknownMetadata String



toString : String -> Problem -> String
toString source problem =
    case problem of
        NotInt ->
            "this is not an integer"
................................................................................
                ++ ": You're trying to define a new type called '"
                ++ typeName
                ++ "', but this type has already been defined here:\n\n"
                ++ SourceLocation.extractFromString source previousDefinitionRange

        UnknownMetadata meta ->
            meta ++ " is not a known metadata label."










>







 







>
>
>
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
92
93
94
95
96
97
98
99
100
101
    | ExpectedEnd
    | ExpectedTypeSeperator
    | ExpectedLeftBracket
    | ExpectedRightBracket
    | WordAlreadyDefined String (Maybe SourceLocationRange) (Maybe SourceLocationRange)
    | TypeAlreadyDefined String SourceLocationRange SourceLocationRange
    | UnknownMetadata String
    | InvalidModulePath String


toString : String -> Problem -> String
toString source problem =
    case problem of
        NotInt ->
            "this is not an integer"
................................................................................
                ++ ": You're trying to define a new type called '"
                ++ typeName
                ++ "', but this type has already been defined here:\n\n"
                ++ SourceLocation.extractFromString source previousDefinitionRange

        UnknownMetadata meta ->
            meta ++ " is not a known metadata label."

        InvalidModulePath path ->
            "'" ++ path ++ "' is not a valid module path. Note: Upper case characters are not allowed."

Modified src/Play/Qualifier.elm from [51e4fe35b3] to [d1f74ef9ef].

11
12
13
14
15
16
17









18
19
20
21
22
23
24
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74








75
76
77
78
79
80
81
82
83










84
85
86
87
88
89



90
91
92
93
94
95
96
...
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

156

157
























158
159



160








161
162





























163
164

165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187



188
189
190
191



192
193

194
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211

212
213
214
215
216

217
218
219
220
221
222
223
224
225
226
227

228
229
230
231
232


233
234
235




236
237
238



239
240
241
242
243
244

245
246
247
248




249
250
251

252
253
254
255
256




257
258
259

260
261
262
263
264
265

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292

293
294
295
296
297

298
299
300
301
302

303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319




320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
...
349
350
351
352
353
354
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408




409

410
411
412


413
414






415
416
417

418
419
420




421
422
423
424
425
426
427
428
429
430
431
432
433
434




435

436
437

438
439





440








441
442
443


444
445

446






447




448
449
450
451

452


453
454
455
456
457

458



459
460
461
462
463
464
465
466
467
468
469

470
471
472
473
474

475

476

477

478
479
480
481
482
483
484
485
486
487

488
489
490
491
492
493


494
495
496
497
498
499
500
501
502
503






























import Result.Extra as Result
import Set exposing (Set)


type alias AST =
    { types : Dict String TypeDefinition
    , words : Dict String WordDefinition









    }


type TypeDefinition
    = CustomTypeDef String SourceLocationRange (List String) (List ( String, Type ))
    | UnionTypeDef String SourceLocationRange (List String) (List Type)

................................................................................

builtinDict : Dict String Builtin
builtinDict =
    Dict.fromList
        [ ( "+", Builtin.Plus )
        , ( "-", Builtin.Minus )
        , ( "*", Builtin.Multiply )
        , ( "/", Builtin.Divide )
        , ( "=", Builtin.Equal )
        , ( "swap", Builtin.StackSwap )
        , ( "dup", Builtin.StackDuplicate )
        , ( "drop", Builtin.StackDrop )
        , ( "rotate", Builtin.StackRightRotate )
        , ( "-rotate", Builtin.StackLeftRotate )
        , ( "!", Builtin.Apply )
        ]










run : Parser.AST -> Result (List Problem) AST
run ast =
    let
        ( typeErrors, qualifiedTypes ) =
            Dict.foldl (\_ val acc -> qualifyType ast val acc) ( [], Dict.empty ) ast.types
                |> Tuple.mapSecond (\qt -> Dict.map (\_ v -> resolveUnionInTypeDefs qt v) qt)

        ( wordErrors, qualifiedWords ) =
            Dict.foldl (\_ val acc -> qualifyDefinition ast qualifiedTypes val acc) ( [], Dict.empty ) ast.words










    in
    case ( typeErrors, wordErrors ) of
        ( [], [] ) ->
            Ok
                { types = qualifiedTypes
                , words = qualifiedWords



                }

        _ ->
            Err <| typeErrors ++ wordErrors


resolveUnionInTypeDefs : Dict String TypeDefinition -> TypeDefinition -> TypeDefinition
................................................................................
                    type_

        _ ->
            type_


qualifyType :
    Parser.AST
    -> Parser.TypeDefinition
    -> ( List Problem, Dict String TypeDefinition )
    -> ( List Problem, Dict String TypeDefinition )
qualifyType ast typeDef ( errors, acc ) =
    ( errors
    , case typeDef of
        Parser.CustomTypeDef range name generics members ->

            Dict.insert name (CustomTypeDef name range generics members) acc


























        Parser.UnionTypeDef range name generics memberTypes ->
            Dict.insert name (UnionTypeDef name range generics memberTypes) acc



    )







































qualifyDefinition :
    Parser.AST

    -> Dict String TypeDefinition
    -> Parser.WordDefinition
    -> ( List Problem, Dict String WordDefinition )
    -> ( List Problem, Dict String WordDefinition )
qualifyDefinition ast qualifiedTypes unqualifiedWord ( errors, acc ) =
    let
        ( whens, impl ) =
            case unqualifiedWord.implementation of
                Parser.SoloImpl defImpl ->
                    ( [], defImpl )

                Parser.MultiImpl whenImpl defImpl ->
                    ( whenImpl, defImpl )

        ( newWordsAfterWhens, qualifiedWhensResult ) =
            List.foldr (qualifyWhen ast qualifiedTypes unqualifiedWord.name) ( acc, [] ) whens
                |> Tuple.mapSecond Result.combine

        ( newWordsAfterImpl, qualifiedImplementationResult ) =
            initQualifyNode unqualifiedWord.name ast newWordsAfterWhens impl

        qualifiedMetadataResult =
            qualifyMetadata qualifiedTypes unqualifiedWord.metadata



    in
    case ( qualifiedWhensResult, qualifiedImplementationResult, qualifiedMetadataResult ) of
        ( Ok qualifiedWhens, Ok qualifiedImplementation, Ok qualifiedMetadata ) ->
            ( errors



            , Dict.insert unqualifiedWord.name
                { name = unqualifiedWord.name

                , metadata = qualifiedMetadata
                , implementation =
                    if List.isEmpty qualifiedWhens then
                        SoloImpl qualifiedImplementation

                    else
                        MultiImpl qualifiedWhens qualifiedImplementation
                }
                newWordsAfterImpl
            )

        ( Err whenError, _, _ ) ->
            ( whenError :: errors

            , newWordsAfterImpl
            )

        ( _, Err implError, _ ) ->
            ( implError :: errors

            , newWordsAfterImpl
            )

        ( _, _, Err metaError ) ->
            ( metaError :: errors

            , newWordsAfterImpl
            )


qualifyMetadata : Dict String TypeDefinition -> Metadata -> Result Problem Metadata
qualifyMetadata qualifiedTypes meta =
    let
        wordRange =
            Maybe.withDefault SourceLocation.emptyRange meta.sourceLocationRange

        typeRefErrors =

            TypeSignature.toMaybe meta.type_
                |> Maybe.map (\ts -> ts.input ++ ts.output)
                |> Maybe.withDefault []
                |> List.filterMap (validateTypeReferences qualifiedTypes wordRange)
    in


    case List.head typeRefErrors of
        Just err ->
            Err err





        Nothing ->
            Ok



                { meta
                    | type_ =
                        TypeSignature.map (resolveUnions qualifiedTypes) meta.type_
                }



validateTypeReferences : Dict String TypeDefinition -> SourceLocationRange -> Type -> Maybe Problem
validateTypeReferences typeDefs wordRange type_ =
    case type_ of
        Type.Custom typeName ->




            case Dict.get typeName typeDefs of
                Just _ ->
                    Nothing


                Nothing ->
                    Just <| UnknownTypeRef wordRange typeName

        Type.CustomGeneric typeName types ->




            case Dict.get typeName typeDefs of
                Just _ ->
                    Nothing


                Nothing ->
                    Just <| UnknownTypeRef wordRange typeName

        _ ->
            Nothing



resolveUnions : Dict String TypeDefinition -> WordType -> WordType
resolveUnions typeDefs wt =
    { input = List.map (resolveUnion typeDefs) wt.input
    , output = List.map (resolveUnion typeDefs) wt.output
    }


qualifyWhen :
    Parser.AST
    -> Dict String TypeDefinition
    -> String
    -> ( Parser.TypeMatch, List Parser.AstNode )
    -> ( Dict String WordDefinition, List (Result Problem ( TypeMatch, List Node )) )
    -> ( Dict String WordDefinition, List (Result Problem ( TypeMatch, List Node )) )
qualifyWhen ast qualifiedTypes wordName ( typeMatch, impl ) ( qualifiedWords, result ) =
    let
        ( newWords, qualifiedImplementationResult ) =
            initQualifyNode wordName ast qualifiedWords impl

        qualifiedMatchResult =
            qualifyMatch qualifiedTypes typeMatch
    in
    case ( qualifiedImplementationResult, qualifiedMatchResult ) of
        ( Err err, _ ) ->
            ( newWords

            , Err err :: result
            )

        ( _, Err err ) ->
            ( newWords

            , Err err :: result
            )

        ( Ok qualifiedImplementation, Ok qualifiedMatch ) ->
            ( newWords

            , Ok ( qualifiedMatch, qualifiedImplementation ) :: result
            )


qualifyMatch : Dict String TypeDefinition -> Parser.TypeMatch -> Result Problem TypeMatch
qualifyMatch qualifiedTypes typeMatch =
    case typeMatch of
        Parser.TypeMatch range Type.Int [] ->
            Ok <| TypeMatch range Type.Int []

        Parser.TypeMatch range Type.Int [ ( "value", Parser.LiteralInt val ) ] ->
            Ok <| TypeMatch range Type.Int [ ( "value", LiteralInt val ) ]

        Parser.TypeMatch range ((Type.Generic _) as type_) [] ->
            Ok <| TypeMatch range type_ []

        Parser.TypeMatch range ((Type.Custom name) as type_) patterns ->




            case Dict.get name qualifiedTypes of
                Just (CustomTypeDef _ _ gens members) ->
                    let
                        memberNames =
                            members
                                |> List.map Tuple.first
                                |> Set.fromList

                        qualifiedPatternsResult =
                            patterns
                                |> List.map (qualifyMatchValue qualifiedTypes range name memberNames)
                                |> Result.combine

                        actualType =
                            case gens of
                                [] ->
                                    type_

                                _ ->
                                    Type.CustomGeneric name (List.map Type.Generic gens)
                    in
                    case qualifiedPatternsResult of
                        Ok qualifiedPatterns ->
                            Ok <| TypeMatch range actualType qualifiedPatterns

                        Err err ->
                            Err err
................................................................................
                    if List.isEmpty patterns then
                        Ok <| TypeMatch range (Type.Union types) []

                    else
                        Err <| UnionTypeMatchWithPatterns range

                Nothing ->
                    Err <| UnknownTypeRef range name

        Parser.TypeMatch range _ _ ->
            Err <| InvalidTypeMatch range


qualifyMatchValue :

    Dict String TypeDefinition
    -> SourceLocationRange
    -> String
    -> Set String
    -> ( String, Parser.TypeMatchValue )
    -> Result Problem ( String, TypeMatchValue )
qualifyMatchValue qualifiedTypes range typeName memberNames ( fieldName, matchValue ) =
    if Set.member fieldName memberNames then
        case matchValue of
            Parser.LiteralInt val ->
                Ok <| ( fieldName, LiteralInt val )

            Parser.LiteralType type_ ->
                Ok <| ( fieldName, LiteralType type_ )

            Parser.RecursiveMatch typeMatch ->
                case qualifyMatch qualifiedTypes typeMatch of
                    Err err ->
                        Err err

                    Ok match ->
                        Ok <| ( fieldName, RecursiveMatch match )

    else
        Err <| NoSuchMemberOnType range typeName fieldName


initQualifyNode :
    String
    -> Parser.AST
    -> Dict String WordDefinition
    -> List Parser.AstNode
    -> ( Dict String WordDefinition, Result Problem (List Node) )
initQualifyNode currentDefName ast qualifiedWords impl =
    List.foldr (qualifyNode ast currentDefName) ( 1, qualifiedWords, [] ) impl
        |> (\( _, newQualifiedWords, errors ) -> ( newQualifiedWords, Result.combine errors ))


qualifyNode :
    Parser.AST
    -> String
    -> Parser.AstNode
    -> ( Int, Dict String WordDefinition, List (Result Problem Node) )
    -> ( Int, Dict String WordDefinition, List (Result Problem Node) )
qualifyNode ast currentDefName node ( availableQuoteId, qualifiedWords, qualifiedNodes ) =
    case node of




        Parser.Integer loc value ->

            ( availableQuoteId
            , qualifiedWords
            , Ok (Integer loc value) :: qualifiedNodes


            )







        Parser.Word loc value ->
            if Dict.member value ast.words then
                ( availableQuoteId

                , qualifiedWords
                , Ok (Word loc value) :: qualifiedNodes
                )





            else
                case Dict.get value builtinDict of
                    Just builtin ->
                        ( availableQuoteId
                        , qualifiedWords
                        , Ok (Builtin loc builtin) :: qualifiedNodes
                        )

                    Nothing ->
                        ( availableQuoteId
                        , qualifiedWords
                        , Err (UnknownWordRef loc value) :: qualifiedNodes
                        )






        Parser.ConstructType typeName ->
            ( availableQuoteId

            , qualifiedWords
            , Ok (ConstructType typeName) :: qualifiedNodes





            )









        Parser.SetMember typeName memberName ->
            ( availableQuoteId


            , qualifiedWords
            , Ok (SetMember typeName memberName) :: qualifiedNodes

            )











        Parser.GetMember typeName memberName ->
            ( availableQuoteId
            , qualifiedWords
            , Ok (GetMember typeName memberName) :: qualifiedNodes

            )



        Parser.Quotation sourceLocation quotImpl ->
            let
                quoteName =
                    currentDefName ++ "__" ++ "quote" ++ String.fromInt availableQuoteId





                ( newWordsAfterQuot, qualifiedQuotImplResult ) =
                    initQualifyNode quoteName ast qualifiedWords quotImpl
            in
            case qualifiedQuotImplResult of
                Ok [ Word _ wordRef ] ->
                    case Dict.get wordRef newWordsAfterQuot of
                        Nothing ->
                            Debug.todo "Cannot happen"

                        Just oldWord ->
                            ( availableQuoteId

                            , Dict.insert wordRef
                                { oldWord | metadata = Metadata.isQuoted oldWord.metadata }
                                newWordsAfterQuot
                            , Ok (WordRef sourceLocation wordRef) :: qualifiedNodes
                            )



                Ok qualifiedQuotImpl ->

                    ( availableQuoteId + 1

                    , Dict.insert quoteName
                        { name = quoteName
                        , metadata =
                            Metadata.default
                                |> Metadata.isQuoted
                        , implementation = SoloImpl qualifiedQuotImpl
                        }
                        newWordsAfterQuot
                    , Ok (WordRef sourceLocation quoteName) :: qualifiedNodes
                    )


                Err err ->
                    ( availableQuoteId
                    , qualifiedWords
                    , Err err :: qualifiedNodes
                    )




typeDefinitionName : TypeDefinition -> String
typeDefinitionName typeDef =
    case typeDef of
        CustomTypeDef name _ _ _ ->
            name

        UnionTypeDef name _ _ _ ->
            name





































>
>
>
>
>
>
>
>
>







 







|










>
>
>
>
>
>
>
>
|
|


|


|
|
>
>
>
>
>
>
>
>
>
>






>
>
>







 







|



|
<
|

>
|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
>
>
>
|
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
>


|
|
|









|
|
|

|
|


|
>
>
>




>
>
>
|
<
>













>





>





>




|
|



<
<
>
|
|
|
|
<
>
>
|
|
|
>
>
>
>
|
<
<
>
>
>


|

|

>
|
|


>
>
>
>
|

<
>


|


>
>
>
>
|

<
>


|


<
>










|



|
|
|

|
|


|




>





>





>




|
|










|
>
>
>
>
|









|





|


|







 







|






>
|





|









|












|


|
|
|
|


|
|
<
<
|
|
<
<
>
>
>
>
|
>
|
|
|
>
>
|

>
>
>
>
>
>

<
<
>
|
<
<
>
>
>
>




<
<
|
|
<

<
<
|
|
>
>
>
>

>
|
<
>
|
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>

<
<
>
>
|
<
>
|
>
>
>
>
>
>
|
>
>
>
>
|
<
<
<
>
|
>
>




|
>

>
>
>
|
|








|
>
|
|
|
|
<
>
|
>

>
|
>
|
|
|
|
|
|
|
|
|
<
>
|
<
<
<
<
|
>
>










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
171
172
173
174
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328


329
330
331
332
333

334
335
336
337
338
339
340
341
342
343


344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
371
372
373
374
375

376
377
378
379
380
381

382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527


528
529


530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549


550
551


552
553
554
555
556
557
558
559


560
561

562


563
564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589


590
591
592

593
594
595
596
597
598
599
600
601
602
603
604
605
606



607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652

653
654




655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
import Result.Extra as Result
import Set exposing (Set)


type alias AST =
    { types : Dict String TypeDefinition
    , words : Dict String WordDefinition
    , additionalModulesRequired : Set String
    , checkForExistingTypes : Set String
    , checkForExistingWords : Set String
    }


type alias ExposedAST =
    { types : Dict String TypeDefinition
    , words : Dict String WordDefinition
    }


type TypeDefinition
    = CustomTypeDef String SourceLocationRange (List String) (List ( String, Type ))
    | UnionTypeDef String SourceLocationRange (List String) (List Type)

................................................................................

builtinDict : Dict String Builtin
builtinDict =
    Dict.fromList
        [ ( "+", Builtin.Plus )
        , ( "-", Builtin.Minus )
        , ( "*", Builtin.Multiply )
        , ( "div", Builtin.Divide )
        , ( "=", Builtin.Equal )
        , ( "swap", Builtin.StackSwap )
        , ( "dup", Builtin.StackDuplicate )
        , ( "drop", Builtin.StackDrop )
        , ( "rotate", Builtin.StackRightRotate )
        , ( "-rotate", Builtin.StackLeftRotate )
        , ( "!", Builtin.Apply )
        ]


type alias RunConfig =
    { packageName : String
    , modulePath : String
    , ast : Parser.AST
    , externalModules : Dict String String
    }


run : RunConfig -> Result (List Problem) AST
run config =
    let
        ( typeErrors, qualifiedTypes ) =
            Dict.foldl (\_ val acc -> qualifyType config val acc) ( [], Dict.empty ) config.ast.types
                |> Tuple.mapSecond (\qt -> Dict.map (\_ v -> resolveUnionInTypeDefs qt v) qt)

        ( wordErrors, externalWords, qualifiedWords ) =
            Dict.foldl (\_ val acc -> qualifyDefinition config qualifiedTypes val acc) ( [], Set.empty, Dict.empty ) config.ast.words

        requiredModules =
            Set.toList externalWords
                |> List.map Tuple.first
                |> Set.fromList

        wordsToCheck =
            Set.toList externalWords
                |> List.map (\( path, name ) -> path ++ "/" ++ name)
                |> Set.fromList
    in
    case ( typeErrors, wordErrors ) of
        ( [], [] ) ->
            Ok
                { types = qualifiedTypes
                , words = qualifiedWords
                , additionalModulesRequired = requiredModules
                , checkForExistingTypes = Set.empty
                , checkForExistingWords = wordsToCheck
                }

        _ ->
            Err <| typeErrors ++ wordErrors


resolveUnionInTypeDefs : Dict String TypeDefinition -> TypeDefinition -> TypeDefinition
................................................................................
                    type_

        _ ->
            type_


qualifyType :
    RunConfig
    -> Parser.TypeDefinition
    -> ( List Problem, Dict String TypeDefinition )
    -> ( List Problem, Dict String TypeDefinition )
qualifyType config typeDef ( errors, acc ) =

    case typeDef of
        Parser.CustomTypeDef range name generics members ->
            let
                qualifiedName =
                    qualifyName config name

                qualifiedMemberResult =
                    List.map (Tuple.mapSecond (qualifyMemberType config range)) members
                        |> List.map raiseTupleError
                        |> Result.combine

                raiseTupleError ( label, result ) =
                    case result of
                        Ok value ->
                            Ok ( label, value )

                        Err err ->
                            Err err
            in
            case qualifiedMemberResult of
                Err err ->
                    ( err :: errors
                    , acc
                    )

                Ok qualifiedMembers ->
                    ( errors
                    , Dict.insert qualifiedName (CustomTypeDef qualifiedName range generics members) acc
                    )

        Parser.UnionTypeDef range name generics memberTypes ->

            let
                qualifiedName =
                    qualifyName config name

                qualifiedMemberTypesResult =
                    List.map (qualifyMemberType config range) memberTypes
                        |> Result.combine
            in
            case qualifiedMemberTypesResult of
                Err err ->
                    ( err :: errors
                    , acc
                    )

                Ok qualifiedMemberTypes ->
                    ( errors
                    , Dict.insert qualifiedName (UnionTypeDef qualifiedName range generics qualifiedMemberTypes) acc
                    )


qualifyMemberType : RunConfig -> SourceLocationRange -> Type -> Result Problem Type
qualifyMemberType config range type_ =
    case type_ of
        Type.Custom name ->
            case Dict.get name config.ast.types of
                Just _ ->
                    Ok <| Type.Custom (qualifyName config name)

                Nothing ->
                    Err <| UnknownTypeRef range name

        Type.CustomGeneric name binds ->
            case Dict.get name config.ast.types of
                Just _ ->
                    Ok <| Type.CustomGeneric (qualifyName config name) binds

                Nothing ->
                    Err <| UnknownTypeRef range name

        _ ->
            Ok type_


qualifyDefinition :

    RunConfig
    -> Dict String TypeDefinition
    -> Parser.WordDefinition
    -> ( List Problem, Set ( String, String ), Dict String WordDefinition )
    -> ( List Problem, Set ( String, String ), Dict String WordDefinition )
qualifyDefinition config qualifiedTypes unqualifiedWord ( errors, externalWords, acc ) =
    let
        ( whens, impl ) =
            case unqualifiedWord.implementation of
                Parser.SoloImpl defImpl ->
                    ( [], defImpl )

                Parser.MultiImpl whenImpl defImpl ->
                    ( whenImpl, defImpl )

        ( newWordsAfterWhens, externalWordsAfterWhens, qualifiedWhensResult ) =
            List.foldr (qualifyWhen config qualifiedTypes unqualifiedWord.name) ( acc, Set.empty, [] ) whens
                |> (\( a, b, nodes ) -> ( a, b, Result.combine nodes ))

        ( newWordsAfterImpl, externalWordsAfterImpl, qualifiedImplementationResult ) =
            initQualifyNode unqualifiedWord.name config newWordsAfterWhens impl

        qualifiedMetadataResult =
            qualifyMetadata config qualifiedTypes unqualifiedWord.metadata

        qualifiedName =
            qualifyName config unqualifiedWord.name
    in
    case ( qualifiedWhensResult, qualifiedImplementationResult, qualifiedMetadataResult ) of
        ( Ok qualifiedWhens, Ok qualifiedImplementation, Ok qualifiedMetadata ) ->
            ( errors
            , externalWords
                |> Set.union externalWordsAfterWhens
                |> Set.union externalWordsAfterImpl
            , Dict.insert qualifiedName

                { name = qualifiedName
                , metadata = qualifiedMetadata
                , implementation =
                    if List.isEmpty qualifiedWhens then
                        SoloImpl qualifiedImplementation

                    else
                        MultiImpl qualifiedWhens qualifiedImplementation
                }
                newWordsAfterImpl
            )

        ( Err whenError, _, _ ) ->
            ( whenError :: errors
            , externalWords
            , newWordsAfterImpl
            )

        ( _, Err implError, _ ) ->
            ( implError :: errors
            , externalWords
            , newWordsAfterImpl
            )

        ( _, _, Err metaError ) ->
            ( metaError :: errors
            , externalWords
            , newWordsAfterImpl
            )


qualifyMetadata : RunConfig -> Dict String TypeDefinition -> Metadata -> Result Problem Metadata
qualifyMetadata config qualifiedTypes meta =
    let
        wordRange =
            Maybe.withDefault SourceLocation.emptyRange meta.sourceLocationRange


    in
    TypeSignature.toMaybe meta.type_
        |> Maybe.map (\ts -> ts.input ++ ts.output)
        |> Maybe.withDefault []
        |> List.map (validateTypeReferences config qualifiedTypes wordRange)

        |> Result.combine
        |> Result.map
            (\qualifiedFlatTypeSignature ->
                let
                    ts =
                        TypeSignature.map
                            (\wt ->
                                { input = List.take (List.length wt.input) qualifiedFlatTypeSignature
                                , output = List.drop (List.length wt.input) qualifiedFlatTypeSignature
                                }


                            )
                            meta.type_
                in
                { meta
                    | type_ =
                        TypeSignature.map (resolveUnions qualifiedTypes) ts
                }
            )


validateTypeReferences : RunConfig -> Dict String TypeDefinition -> SourceLocationRange -> Type -> Result Problem Type
validateTypeReferences config typeDefs wordRange type_ =
    case type_ of
        Type.Custom typeName ->
            let
                qualifiedName =
                    qualifyName config typeName
            in
            case Dict.get qualifiedName typeDefs of
                Just _ ->

                    Ok <| Type.Custom qualifiedName

                Nothing ->
                    Err <| UnknownTypeRef wordRange qualifiedName

        Type.CustomGeneric typeName types ->
            let
                qualifiedName =
                    qualifyName config typeName
            in
            case Dict.get qualifiedName typeDefs of
                Just _ ->

                    Ok <| Type.CustomGeneric qualifiedName types

                Nothing ->
                    Err <| UnknownTypeRef wordRange qualifiedName

        _ ->

            Ok type_


resolveUnions : Dict String TypeDefinition -> WordType -> WordType
resolveUnions typeDefs wt =
    { input = List.map (resolveUnion typeDefs) wt.input
    , output = List.map (resolveUnion typeDefs) wt.output
    }


qualifyWhen :
    RunConfig
    -> Dict String TypeDefinition
    -> String
    -> ( Parser.TypeMatch, List Parser.AstNode )
    -> ( Dict String WordDefinition, Set ( String, String ), List (Result Problem ( TypeMatch, List Node )) )
    -> ( Dict String WordDefinition, Set ( String, String ), List (Result Problem ( TypeMatch, List Node )) )
qualifyWhen config qualifiedTypes wordName ( typeMatch, impl ) ( qualifiedWords, externalWords, result ) =
    let
        ( newWords, externalWordsAfterImpl, qualifiedImplementationResult ) =
            initQualifyNode wordName config qualifiedWords impl

        qualifiedMatchResult =
            qualifyMatch config qualifiedTypes typeMatch
    in
    case ( qualifiedImplementationResult, qualifiedMatchResult ) of
        ( Err err, _ ) ->
            ( newWords
            , externalWords
            , Err err :: result
            )

        ( _, Err err ) ->
            ( newWords
            , externalWords
            , Err err :: result
            )

        ( Ok qualifiedImplementation, Ok qualifiedMatch ) ->
            ( newWords
            , Set.union externalWords externalWordsAfterImpl
            , Ok ( qualifiedMatch, qualifiedImplementation ) :: result
            )


qualifyMatch : RunConfig -> Dict String TypeDefinition -> Parser.TypeMatch -> Result Problem TypeMatch
qualifyMatch config qualifiedTypes typeMatch =
    case typeMatch of
        Parser.TypeMatch range Type.Int [] ->
            Ok <| TypeMatch range Type.Int []

        Parser.TypeMatch range Type.Int [ ( "value", Parser.LiteralInt val ) ] ->
            Ok <| TypeMatch range Type.Int [ ( "value", LiteralInt val ) ]

        Parser.TypeMatch range ((Type.Generic _) as type_) [] ->
            Ok <| TypeMatch range type_ []

        Parser.TypeMatch range (Type.Custom name) patterns ->
            let
                qualifiedName =
                    qualifyName config name
            in
            case Dict.get qualifiedName qualifiedTypes of
                Just (CustomTypeDef _ _ gens members) ->
                    let
                        memberNames =
                            members
                                |> List.map Tuple.first
                                |> Set.fromList

                        qualifiedPatternsResult =
                            patterns
                                |> List.map (qualifyMatchValue config qualifiedTypes range qualifiedName memberNames)
                                |> Result.combine

                        actualType =
                            case gens of
                                [] ->
                                    Type.Custom qualifiedName

                                _ ->
                                    Type.CustomGeneric qualifiedName (List.map Type.Generic gens)
                    in
                    case qualifiedPatternsResult of
                        Ok qualifiedPatterns ->
                            Ok <| TypeMatch range actualType qualifiedPatterns

                        Err err ->
                            Err err
................................................................................
                    if List.isEmpty patterns then
                        Ok <| TypeMatch range (Type.Union types) []

                    else
                        Err <| UnionTypeMatchWithPatterns range

                Nothing ->
                    Err <| UnknownTypeRef range qualifiedName

        Parser.TypeMatch range _ _ ->
            Err <| InvalidTypeMatch range


qualifyMatchValue :
    RunConfig
    -> Dict String TypeDefinition
    -> SourceLocationRange
    -> String
    -> Set String
    -> ( String, Parser.TypeMatchValue )
    -> Result Problem ( String, TypeMatchValue )
qualifyMatchValue config qualifiedTypes range typeName memberNames ( fieldName, matchValue ) =
    if Set.member fieldName memberNames then
        case matchValue of
            Parser.LiteralInt val ->
                Ok <| ( fieldName, LiteralInt val )

            Parser.LiteralType type_ ->
                Ok <| ( fieldName, LiteralType type_ )

            Parser.RecursiveMatch typeMatch ->
                case qualifyMatch config qualifiedTypes typeMatch of
                    Err err ->
                        Err err

                    Ok match ->
                        Ok <| ( fieldName, RecursiveMatch match )

    else
        Err <| NoSuchMemberOnType range typeName fieldName


initQualifyNode :
    String
    -> RunConfig
    -> Dict String WordDefinition
    -> List Parser.AstNode
    -> ( Dict String WordDefinition, Set ( String, String ), Result Problem (List Node) )
initQualifyNode currentDefName config qualifiedWords impl =
    List.foldr (qualifyNode config currentDefName) (initQualifyNodeAccumulator qualifiedWords) impl
        |> (\acc -> ( acc.qualifiedWords, acc.externalWords, Result.combine acc.qualifiedNodes ))


type alias QualifyNodeAccumulator =
    { availableQuoteId : Int


    , qualifiedWords : Dict String WordDefinition
    , qualifiedNodes : List (Result Problem Node)


    , externalWords : Set ( String, String )
    }


initQualifyNodeAccumulator : Dict String WordDefinition -> QualifyNodeAccumulator
initQualifyNodeAccumulator qualifiedWords =
    { availableQuoteId = 1
    , qualifiedWords = qualifiedWords
    , qualifiedNodes = []
    , externalWords = Set.empty
    }


qualifyNode : RunConfig -> String -> Parser.AstNode -> QualifyNodeAccumulator -> QualifyNodeAccumulator
qualifyNode config currentDefName node acc =
    case node of
        Parser.Integer loc value ->
            { acc | qualifiedNodes = Ok (Integer loc value) :: acc.qualifiedNodes }

        Parser.Word loc value ->


            let
                qualifiedName =


                    qualifyName config value
            in
            if Dict.member value config.ast.words then
                { acc | qualifiedNodes = Ok (Word loc qualifiedName) :: acc.qualifiedNodes }

            else
                case Dict.get value builtinDict of
                    Just builtin ->


                        { acc | qualifiedNodes = Ok (Builtin loc builtin) :: acc.qualifiedNodes }


                    Nothing ->


                        { acc | qualifiedNodes = Err (UnknownWordRef loc value) :: acc.qualifiedNodes }

        Parser.PackageWord loc path value ->
            let
                normalizedPath =
                    String.join "/" path

                qualifiedPath =
                    qualifyPackageModule config normalizedPath


                qualifiedName =
                    String.join "/" [ qualifiedPath, value ]
            in
            { acc
                | qualifiedNodes = Ok (Word loc qualifiedName) :: acc.qualifiedNodes
                , externalWords = Set.insert ( qualifiedPath, value ) acc.externalWords
            }

        Parser.ExternalWord loc path value ->
            let
                normalizedPath =
                    "/" ++ String.join "/" path
            in
            case Dict.get normalizedPath config.externalModules of
                Nothing ->
                    { acc | qualifiedNodes = Err (UnknownWordRef loc (normalizedPath ++ "/" ++ value)) :: acc.qualifiedNodes }



                Just package ->
                    let
                        qualifiedPath =

                            "/" ++ package ++ normalizedPath

                        fullReference =
                            qualifiedPath ++ "/" ++ value
                    in
                    { acc
                        | qualifiedNodes = Ok (Word loc fullReference) :: acc.qualifiedNodes
                        , externalWords = Set.insert ( qualifiedPath, value ) acc.externalWords
                    }

        Parser.ConstructType typeName ->
            { acc | qualifiedNodes = Ok (ConstructType (qualifyName config typeName)) :: acc.qualifiedNodes }

        Parser.SetMember typeName memberName ->



            { acc | qualifiedNodes = Ok (SetMember (qualifyName config typeName) memberName) :: acc.qualifiedNodes }

        Parser.GetMember typeName memberName ->
            { acc | qualifiedNodes = Ok (GetMember (qualifyName config typeName) memberName) :: acc.qualifiedNodes }

        Parser.Quotation sourceLocation quotImpl ->
            let
                quoteName =
                    if String.startsWith "quote:" currentDefName then
                        currentDefName ++ "/" ++ String.fromInt acc.availableQuoteId

                    else
                        "quote:" ++ qualifyName config currentDefName ++ "/" ++ String.fromInt acc.availableQuoteId

                ( newWordsAfterQuot, externalWords, qualifiedQuotImplResult ) =
                    initQualifyNode quoteName config acc.qualifiedWords quotImpl
            in
            case qualifiedQuotImplResult of
                Ok [ Word _ wordRef ] ->
                    case Dict.get wordRef newWordsAfterQuot of
                        Nothing ->
                            Debug.todo "Cannot happen"

                        Just oldWord ->
                            { acc
                                | qualifiedWords =
                                    Dict.insert wordRef
                                        { oldWord | metadata = Metadata.isQuoted oldWord.metadata }
                                        newWordsAfterQuot
                                , qualifiedNodes = Ok (WordRef sourceLocation wordRef) :: acc.qualifiedNodes

                                , externalWords = Set.union externalWords acc.externalWords
                            }

                Ok qualifiedQuotImpl ->
                    { acc
                        | availableQuoteId = acc.availableQuoteId + 1
                        , qualifiedWords =
                            Dict.insert quoteName
                                { name = quoteName
                                , metadata =
                                    Metadata.default
                                        |> Metadata.isQuoted
                                , implementation = SoloImpl qualifiedQuotImpl
                                }
                                newWordsAfterQuot
                        , qualifiedNodes = Ok (WordRef sourceLocation quoteName) :: acc.qualifiedNodes

                        , externalWords = Set.union externalWords acc.externalWords
                    }





                Err err ->
                    { acc | qualifiedNodes = Err err :: acc.qualifiedNodes }


typeDefinitionName : TypeDefinition -> String
typeDefinitionName typeDef =
    case typeDef of
        CustomTypeDef name _ _ _ ->
            name

        UnionTypeDef name _ _ _ ->
            name


qualifyName : RunConfig -> String -> String
qualifyName config name =
    if config.packageName == "" then
        name

    else
        String.concat
            [ "/"
            , config.packageName
            , "/"
            , config.modulePath
            , "/"
            , name
            ]


qualifyPackageModule : RunConfig -> String -> String
qualifyPackageModule config path =
    if config.packageName == "" then
        path

    else
        String.concat
            [ "/"
            , config.packageName
            , "/"
            , path
            ]

Modified src/Play/TypeChecker.elm from [fec5dbde4e] to [2a58b70563].

70
71
72
73
74
75
76
77







78
79
80
81
82
83
84
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147


type StackEffect
    = Push Type
    | Pop Type


initContext : Qualifier.AST -> Context







initContext ast =
    let
        concreteTypes =
            Dict.map
                (\_ t ->
                    case t of
                        Qualifier.CustomTypeDef name range generics members ->
................................................................................
    , boundGenerics = Dict.empty
    , boundStackRanges = Dict.empty
    , callStack = Set.empty
    , errors = List.concatMap genericErrors (Dict.values concreteTypes)
    }


run : Qualifier.AST -> Result (List Problem) AST
run ast =
    typeCheckHelper (initContext ast) ast


typeCheckHelper : Context -> Qualifier.AST -> Result (List Problem) AST
typeCheckHelper context ast =
    let
        updatedContext =
            Dict.foldl (\_ v acc -> typeCheckDefinition v acc) context ast.words
    in
    if List.isEmpty updatedContext.errors then
        Ok <|







|
>
>
>
>
>
>
>







 







|




|







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154


type StackEffect
    = Push Type
    | Pop Type


type alias LoadedQualifierAST a =
    { a
        | types : Dict String Qualifier.TypeDefinition
        , words : Dict String Qualifier.WordDefinition
    }


initContext : LoadedQualifierAST a -> Context
initContext ast =
    let
        concreteTypes =
            Dict.map
                (\_ t ->
                    case t of
                        Qualifier.CustomTypeDef name range generics members ->
................................................................................
    , boundGenerics = Dict.empty
    , boundStackRanges = Dict.empty
    , callStack = Set.empty
    , errors = List.concatMap genericErrors (Dict.values concreteTypes)
    }


run : LoadedQualifierAST a -> Result (List Problem) AST
run ast =
    typeCheckHelper (initContext ast) ast


typeCheckHelper : Context -> LoadedQualifierAST a -> Result (List Problem) AST
typeCheckHelper context ast =
    let
        updatedContext =
            Dict.foldl (\_ v acc -> typeCheckDefinition v acc) context ast.words
    in
    if List.isEmpty updatedContext.errors then
        Ok <|

Added tests/Test/Data/ModuleName.elm version [96d969b684].

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
module Test.Data.ModuleName exposing (suite)

import Expect
import Fuzz
import Play.Data.ModuleName as ModuleName
import Play.Data.PackageName as PackageName
import Test exposing (Test, describe, fuzz, test)


suite : Test
suite =
    describe "ModuleName"
        [ fuzz Fuzz.string "Valid 2-part module names are also valid package names" <|
            \name ->
                let
                    combinedModuleName =
                        String.join "/" [ name, name ]
                in
                expectSameResult
                    (PackageName.fromString combinedModuleName)
                    (ModuleName.fromString combinedModuleName)
        , test "Module names can have only one part" <|
            \_ ->
                Expect.ok <| ModuleName.fromString "dict"
        , test "Module names can have many parts" <|
            \_ ->
                Expect.ok <| ModuleName.fromString "stdlib/dict/ordered"
        , test "The empty string is not a valid module name" <|
            \_ ->
                Expect.err <| ModuleName.fromString ""
        , test "Module names cannot start with a slash" <|
            \_ ->
                Expect.err <| ModuleName.fromString "/dict"
        , test "Module names cannot end with a slash" <|
            \_ ->
                Expect.err <| ModuleName.fromString "dict/"
        , test "toString returns input of properly formated module name" <|
            \_ ->
                "some/module"
                    |> ModuleName.fromString
                    |> Result.map ModuleName.toString
                    |> Result.withDefault ""
                    |> Expect.equal "some/module"
        , test "toPartStrings return each part of a module name in a list" <|
            \_ ->
                "some/kind/of/module"
                    |> ModuleName.fromString
                    |> Result.map ModuleName.toPartStrings
                    |> Result.withDefault []
                    |> Expect.equalLists [ "some", "kind", "of", "module" ]
        ]


expectSameResult : Result aErr aOk -> Result bErr bOk -> Expect.Expectation
expectSameResult left right =
    case ( left, right ) of
        ( Ok _, Ok _ ) ->
            Expect.pass

        ( Err _, Err _ ) ->
            Expect.pass

        _ ->
            Expect.fail <| "Different results: " ++ Debug.toString ( left, right )

Added tests/Test/Data/PackageName.elm version [bcb092c8ca].













































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
module Test.Data.PackageName exposing (suite)

import Expect
import Play.Data.PackageName as PackageName
import Test exposing (Test, describe, test)
import Test.PlayExpect as PlayExpect


suite : Test
suite =
    describe "PackageName"
        [ test "valid package names" <|
            \_ ->
                PlayExpect.allOk PackageName.fromString
                    [ "some/package"
                    , "play/std_lib"
                    , "number1/package123"
                    , "play_std/lib"
                    ]
        , test "Must contain exactly two parts, seperated by a single slash" <|
            \_ ->
                PlayExpect.allErr PackageName.fromString
                    [ "/"
                    , "one/"
                    , "/one"
                    , "one"
                    , "one/two/three"
                    ]
        , test "Both parts of a name must start with lower cased ascii character" <|
            \_ ->
                PlayExpect.allErr PackageName.fromString
                    [ "1pack/name"
                    , "_priv/pack"
                    , "#whaaat/events"
                    , "Some/package"
                    , "pack/1name"
                    , "priv/_pack"
                    , "whaaat/#events"
                    , "some/Package"
                    ]
        , test "Both parts of a name cannot contain upper case letters" <|
            \_ ->
                PlayExpect.allErr PackageName.fromString
                    [ "myPack/name"
                    , "mypackage/someName"
                    , "mypackage/some_Name"
                    ]
        , test "Both parts of a name cannot contain non ascii or digit letters" <|
            \_ ->
                PlayExpect.allErr PackageName.fromString
                    [ "my#pack/name"
                    , "mypackage/bills$"
                    ]
        ]

Added tests/Test/Data/PackagePath.elm version [156de36d36].





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module Test.Data.PackagePath exposing (suite)

import Expect
import Play.Data.PackagePath as PackagePath
import Test exposing (Test, describe, test)


suite : Test
suite =
    describe "PackagePath"
        [ test "Any path not ending in * is a directory" <|
            \_ ->
                Expect.equal
                    (PackagePath.Directory "/some/path")
                    (PackagePath.fromString "/some/path")
        , test "Any path ending in * is a recursive directory path" <|
            \_ ->
                Expect.equal
                    (PackagePath.AllDirectoriesInDirectory "/some/path")
                    (PackagePath.fromString "/some/path/*")
        , test "Final slash is removed" <|
            \_ ->
                Expect.equal
                    (PackagePath.Directory "/some/path")
                    (PackagePath.fromString "/some/path/")
        ]

Added tests/Test/Data/SemanticVersion.elm version [831feac96b].



















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
module Test.Data.SemanticVersion exposing (suite)

import Expect
import Play.Data.SemanticVersion as SemanticVersion
import Test exposing (Test, describe, test)
import Test.PlayExpect as PlayExpect


suite : Test
suite =
    describe "SemanticVersion"
        [ test "Valid versions" <|
            \_ ->
                PlayExpect.allOk SemanticVersion.fromString
                    [ "1.2.3"
                    , "10.100.1000"
                    , "0.0.1"
                    , "0.1.0"
                    ]
        , test "Cannot contain more than three parts" <|
            \_ ->
                SemanticVersion.fromString "1.2.3.4"
                    |> Expect.equal (Err <| SemanticVersion.InvalidFormat "1.2.3.4")
        , test "Cannot contain less than three parts" <|
            \_ ->
                PlayExpect.allEqual SemanticVersion.fromString
                    [ ( "1", Err <| SemanticVersion.InvalidFormat "1" )
                    , ( "1.2", Err <| SemanticVersion.InvalidFormat "1.2" )
                    ]
        , test "Cannot be empty string" <|
            \_ ->
                SemanticVersion.fromString ""
                    |> Expect.equal (Err <| SemanticVersion.InvalidFormat "")
        , test "Must be numbers" <|
            \_ ->
                PlayExpect.allEqual SemanticVersion.fromString
                    [ ( "A", Err <| SemanticVersion.InvalidFormat "A" )
                    , ( "*", Err <| SemanticVersion.InvalidFormat "*" )
                    , ( "~", Err <| SemanticVersion.InvalidFormat "~" )
                    , ( "1.0.x", Err <| SemanticVersion.ExpectedInteger "1.0.x" )
                    , ( "1.0.~", Err <| SemanticVersion.ExpectedInteger "1.0.~" )
                    , ( "~1.0.0", Err <| SemanticVersion.ExpectedInteger "~1.0.0" )
                    , ( "1.0.0-alpha1", Err <| SemanticVersion.ExpectedInteger "1.0.0-alpha1" )
                    , ( "alpha.1", Err <| SemanticVersion.InvalidFormat "alpha.1" )
                    ]
        , test "Minimum version is 0.0.1" <|
            \_ ->
                SemanticVersion.fromString "0.0.0"
                    |> Expect.equal (Err <| SemanticVersion.LessThanMinimumVersion "0.0.0")
        , test "Cannot contain negative versions" <|
            \_ ->
                PlayExpect.allEqual SemanticVersion.fromString
                    [ ( "-1.0.0", Err <| SemanticVersion.NegativeVersions "-1.0.0" )
                    , ( "1.-2.0", Err <| SemanticVersion.NegativeVersions "1.-2.0" )
                    , ( "1.2.-3", Err <| SemanticVersion.NegativeVersions "1.2.-3" )
                    ]
        , describe "Compatibility" <|
            let
                helper ( lhs, rhs ) =
                    Result.map2 SemanticVersion.compatible (SemanticVersion.fromString lhs) (SemanticVersion.fromString rhs)
            in
            [ test "Same version, or greater version, returns GreaterThanOrEqual" <|
                \_ ->
                    PlayExpect.allEqual helper
                        [ ( ( "1.0.0", "1.0.0" ), Ok SemanticVersion.GreaterThanOrEqual )
                        , ( ( "0.2.1", "0.2.1" ), Ok SemanticVersion.GreaterThanOrEqual )
                        , ( ( "2.0.8", "2.0.8" ), Ok SemanticVersion.GreaterThanOrEqual )
                        , ( ( "1.0.0", "1.2.0" ), Ok SemanticVersion.GreaterThanOrEqual )
                        , ( ( "2.1.0", "2.1.1" ), Ok SemanticVersion.GreaterThanOrEqual )
                        , ( ( "1.2.3", "1.3.0" ), Ok SemanticVersion.GreaterThanOrEqual )
                        ]
            , test "Lesser version returns LessThan" <|
                \_ ->
                    PlayExpect.allEqual helper
                        [ ( ( "0.2.1", "0.2.0" ), Ok SemanticVersion.LessThan )
                        , ( ( "1.1.0", "1.0.5" ), Ok SemanticVersion.LessThan )
                        , ( ( "2.1.3", "2.1.1" ), Ok SemanticVersion.LessThan )
                        , ( ( "1.2.3", "1.2.2" ), Ok SemanticVersion.LessThan )
                        ]
            , test "Incompatible versions" <|
                \_ ->
                    PlayExpect.allEqual helper
                        [ ( ( "0.2.1", "0.3.0" ), Ok SemanticVersion.Incompatible )
                        , ( ( "1.0.0", "2.0.0" ), Ok SemanticVersion.Incompatible )
                        , ( ( "1.2.0", "2.2.0" ), Ok SemanticVersion.Incompatible )
                        , ( ( "0.0.1", "1.0.1" ), Ok SemanticVersion.Incompatible )
                        ]
            ]
        ]

Added tests/Test/PackageLoader.elm version [a50f684204].







































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
module Test.PackageLoader exposing (suite)

import Dict exposing (Dict)
import Dict.Extra as Dict
import Expect exposing (Expectation)
import List.Extra as List
import Play.Data.Builtin as Builtin
import Play.Data.Metadata as Metadata
import Play.Data.PackagePath as PackagePath
import Play.Data.SourceLocation exposing (emptyRange)
import Play.PackageLoader as PackageLoader
import Play.Qualifier as Qualifier
import Test exposing (Test, describe, test)
import Test.Qualifier.Util as Util


suite : Test
suite =
    describe "PackageLoader"
        [ test "Passes the load package metadata step" <|
            \_ ->
                PackageLoader.init "/project"
                    |> Expect.equal (PackageLoader.Initializing <| PackageLoader.ReadFile "/project" "play.json")
        , test "Retrieves necessary files" <|
            \_ ->
                PackageLoader.init "/project"
                    |> expectSideEffects testFiles
                        [ PackageLoader.ReadFile "/project" "play.json"
                        , PackageLoader.ResolveDirectories "/project/lib"
                        , PackageLoader.ReadFile "/project/lib/template_strings" "play.json"
                        , PackageLoader.ReadFile "/project/lib/template_strings/lib/version" "play.json"
                        , PackageLoader.ReadFile "/project/lib/unused" "play.json"
                        , PackageLoader.ReadFile "/project/lib/version" "play.json"
                        , PackageLoader.ResolvePackageModules "robheghan/fnv" "/project"
                        , PackageLoader.ResolvePackageModules "jarvis/template_strings" "/project/lib/template_strings"
                        , PackageLoader.ResolvePackageModules "play/version" "/project/lib/template_strings/lib/version"
                        , PackageLoader.ReadFile "/project/src" "mod1.play"
                        , PackageLoader.ReadFile "/project/lib/template_strings/lib/version/src/version" "data.play"
                        ]
        , test "Compiles to qualified AST" <|
            \_ ->
                let
                    loaderResult =
                        PackageLoader.init "/project"
                            |> resolveSideEffects testFiles []
                            |> Result.map Tuple.second
                in
                case loaderResult of
                    Err msg ->
                        Expect.fail msg

                    Ok ast ->
                        Expect.equal
                            { types =
                                Dict.fromListBy Qualifier.typeDefinitionName []
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "/robheghan/fnv/mod1/next-version"
                                      , metadata = Metadata.default
                                      , implementation =
                                            Qualifier.SoloImpl
                                                [ Qualifier.Word emptyRange "/play/version/version/data/number"
                                                , Qualifier.Integer emptyRange 1
                                                , Qualifier.Builtin emptyRange Builtin.Plus
                                                ]
                                      }
                                    , { name = "/play/version/version/data/number"
                                      , metadata = Metadata.default
                                      , implementation =
                                            Qualifier.SoloImpl
                                                [ Qualifier.Integer emptyRange 2
                                                ]
                                      }
                                    ]
                            }
                            (Util.stripLocations ast)
        ]


expectSideEffects : Dict String String -> List PackageLoader.SideEffect -> PackageLoader.Model -> Expectation
expectSideEffects fileSystem expectedSFs model =
    case resolveSideEffects fileSystem [] model of
        Err msg ->
            Expect.fail msg

        Ok ( seenSfs, _ ) ->
            let
                sfDiff =
                    List.filter (\sf -> not <| List.member sf expectedSFs) seenSfs
            in
            Expect.equalLists [] sfDiff


resolveSideEffects :
    Dict String String
    -> List PackageLoader.SideEffect
    -> PackageLoader.Model
    -> Result String ( List PackageLoader.SideEffect, Qualifier.ExposedAST )
resolveSideEffects fileSystem seenSfs model =
    case getSideEffect model of
        Nothing ->
            case model of
                PackageLoader.Done ast ->
                    Ok ( seenSfs, ast )

                _ ->
                    Err <| "Expected model be Done, was: " ++ Debug.toString model

        Just sideEffect ->
            case sideEffect of
                PackageLoader.ReadFile path filename ->
                    case Dict.get (path ++ "/" ++ filename) fileSystem of
                        Just fileContent ->
                            resolveSideEffects
                                fileSystem
                                (sideEffect :: seenSfs)
                                (PackageLoader.update
                                    (PackageLoader.FileContents path filename fileContent)
                                    model
                                )

                        Nothing ->
                            Err <| "No such file: " ++ path

                PackageLoader.ResolveDirectories dir ->
                    let
                        childPaths =
                            Dict.keys fileSystem
                                |> List.filter (childPackage dir)
                                |> List.map (String.replace "/play.json" "")
                                |> List.map PackagePath.Directory
                    in
                    resolveSideEffects
                        fileSystem
                        (sideEffect :: seenSfs)
                        (PackageLoader.update
                            (PackageLoader.ResolvedDirectories dir childPaths)
                            model
                        )

                PackageLoader.ResolvePackageModules packageName packagePath ->
                    let
                        srcPath =
                            packagePath ++ "/src/"

                        childPaths =
                            Dict.keys fileSystem
                                |> List.filter
                                    (\path ->
                                        String.startsWith srcPath path
                                    )
                                |> List.map (String.replace srcPath "")
                    in
                    resolveSideEffects
                        fileSystem
                        (sideEffect :: seenSfs)
                        (PackageLoader.update
                            (PackageLoader.ResolvedPackageModules packageName childPaths)
                            model
                        )


childPackage : String -> String -> Bool
childPackage targetDir path =
    if not <| String.startsWith targetDir path then
        False

    else
        let
            pathParts =
                path
                    |> String.replace (targetDir ++ "/") ""
                    |> String.split "/"
        in
        case pathParts of
            [ _, "play.json" ] ->
                True

            _ ->
                False


getSideEffect : PackageLoader.Model -> Maybe PackageLoader.SideEffect
getSideEffect model =
    case model of
        PackageLoader.Done _ ->
            Nothing

        PackageLoader.Failed _ ->
            Nothing

        PackageLoader.Initializing sf ->
            Just sf

        PackageLoader.LoadingMetadata _ _ sf ->
            Just sf

        PackageLoader.ResolvingModulePaths _ _ sf ->
            Just sf

        PackageLoader.Compiling _ _ sf ->
            Just sf


testFiles : Dict String String
testFiles =
    Dict.fromList
        [ ( "/project/play.json"
          , """
            {
                "name": "robheghan/fnv",
                "version": "1.0.0",
                "language-version": "0.2.0",
                "exposed-modules": [
                    "mod1"
                ],
                "dependencies": {
                    "jarvis/template_strings": "1.2.0",
                    "play/version": "1.0.0"
                },
                "package-paths": [
                    "lib/*"
                ]
            }
            """
          )
        , ( "/project/src/mod1.play"
          , """
            def: next-version
            : /version/data/number 1 +
            """
          )
        , ( "/project/lib/template_strings/play.json"
          , """
            {
                "name": "jarvis/template_strings",
                "version": "1.2.0",
                "language-version": "0.2.0",
                "exposed-modules": [
                    "template_strings/mod"
                ],
                "dependencies": {
                    "play/version": "1.1.0"
                },
                "package-paths": [
                    "lib/version"
                ]
            }
          """
          )
        , ( "/project/lib/template_strings/src/template_strings/mod.play"
          , """
            def: dec
            : 1 =
            """
          )
        , ( "/project/lib/unused/play.json"
          , """
            {
                "name": "some/useless",
                "version": "1.7.0",
                "language-version": "0.2.0",
                "exposed-modules": [
                    "useless/mod"
                ],
                "dependencies": {
                },
                "package-paths": [
                ]
            }
          """
          )
        , ( "/project/lib/unused/src/useless/mod.play"
          , """
            def: square
            : dup *
            """
          )
        , ( "/project/lib/version/play.json"
          , """
            {
                "name": "play/version",
                "version": "1.0.0",
                "language-version": "0.2.0",
                "exposed-modules": [
                    "version/data"
                ],
                "dependencies": {
                },
                "package-paths": [
                ]
            }
          """
          )
        , ( "/project/lib/version/src/version/data.play"
          , """
            def: number
            : 1
            """
          )
        , ( "/project/lib/template_strings/lib/version/play.json"
          , """
            {
                "name": "play/version",
                "version": "1.2.0",
                "language-version": "0.2.0",
                "exposed-modules": [
                    "version/data"
                ],
                "dependencies": {
                },
                "package-paths": [
                ]
            }
          """
          )
        , ( "/project/lib/template_strings/lib/version/src/version/data.play"
          , """
            def: number
            : 2
            """
          )
        ]

Modified tests/Test/Parser.elm from [a3937d228f] to [183827d1df].

706
707
708
709
710
711
712


























































713
714
715
716
717
718
719
                                                  , [ AST.Word emptyRange "True" ]
                                                  )
                                                ]
                                                [ AST.Word emptyRange "False" ]
                                      }
                                    ]
                            }


























































                    in
                    case compile source of
                        Err _ ->
                            Expect.fail "Did not expect parsing to fail"

                        Ok ast ->
                            Expect.equal expectedAst ast







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
                                                  , [ AST.Word emptyRange "True" ]
                                                  )
                                                ]
                                                [ AST.Word emptyRange "False" ]
                                      }
                                    ]
                            }
                    in
                    case compile source of
                        Err _ ->
                            Expect.fail "Did not expect parsing to fail"

                        Ok ast ->
                            Expect.equal expectedAst ast
            ]
        , describe "modules" <|
            [ test "internal reference" <|
                \_ ->
                    let
                        source =
                            """
                            def: test
                            : some/module/sample
                            """

                        expectedAst =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "test"
                                      , metadata = Metadata.default
                                      , implementation =
                                            SoloImpl
                                                [ AST.PackageWord emptyRange [ "some", "module" ] "sample" ]
                                      }
                                    ]
                            }
                    in
                    case compile source of
                        Err _ ->
                            Expect.fail "Did not expect parsing to fail"

                        Ok ast ->
                            Expect.equal expectedAst ast
            , test "external reference" <|
                \_ ->
                    let
                        source =
                            """
                            def: test
                            : /some/module/sample
                            """

                        expectedAst =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "test"
                                      , metadata = Metadata.default
                                      , implementation =
                                            SoloImpl
                                                [ AST.ExternalWord emptyRange [ "some", "module" ] "sample" ]
                                      }
                                    ]
                            }
                    in
                    case compile source of
                        Err _ ->
                            Expect.fail "Did not expect parsing to fail"

                        Ok ast ->
                            Expect.equal expectedAst ast

Modified tests/Test/Parser/Error.elm from [b45ca2f7fa] to [297a7bb4eb].

113
114
115
116
117
118
119














































120
121
122
123
124
125
126
        , test "Only compiler can create functions which names begins with an upper case letter" <|
            \_ ->
                checkForError ((==) NotSymbol) <|
                    """
                    def: Person
                    : 1
                    """














































        ]


checkForError : (Problem -> Bool) -> String -> Expectation
checkForError fn source =
    case compile source of
        Err errors ->







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
        , test "Only compiler can create functions which names begins with an upper case letter" <|
            \_ ->
                checkForError ((==) NotSymbol) <|
                    """
                    def: Person
                    : 1
                    """
        , describe "Module path elements" <|
            let
                invalidModulePathError err =
                    case err of
                        InvalidModulePath _ ->
                            True

                        _ ->
                            False
            in
            [ test "Starting with upper case" <|
                \_ ->
                    checkForError invalidModulePathError <|
                        """
                        def: sample
                        : some/Other/module
                        """
            , test "Contains upper case" <|
                \_ ->
                    checkForError invalidModulePathError <|
                        """
                        def: sample
                        : some/otHer/module
                        """
            , test "Starting with upper case (external)" <|
                \_ ->
                    checkForError invalidModulePathError <|
                        """
                        def: sample
                        : /some/Other/module
                        """
            , test "Contains upper case (external)" <|
                \_ ->
                    checkForError invalidModulePathError <|
                        """
                        def: sample
                        : /some/otHer/module
                        """
            , test "External reference must contain two parts" <|
                \_ ->
                    checkForError invalidModulePathError <|
                        """
                        def: sample
                        : /some
                        """
            ]
        ]


checkForError : (Problem -> Bool) -> String -> Expectation
checkForError fn source =
    case compile source of
        Err errors ->

Modified tests/Test/Parser/Util.elm from [34556264c0] to [d64d255e03].

70
71
72
73
74
75
76






77
78
79
80
81
82
83
    case node of
        AST.Integer _ val ->
            AST.Integer emptyRange val

        AST.Word _ val ->
            AST.Word emptyRange val







        AST.Quotation _ val ->
            AST.Quotation emptyRange (List.map stripNodeLocation val)

        _ ->
            node









>
>
>
>
>
>







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
    case node of
        AST.Integer _ val ->
            AST.Integer emptyRange val

        AST.Word _ val ->
            AST.Word emptyRange val

        AST.PackageWord _ path val ->
            AST.PackageWord emptyRange path val

        AST.ExternalWord _ path val ->
            AST.ExternalWord emptyRange path val

        AST.Quotation _ val ->
            AST.Quotation emptyRange (List.map stripNodeLocation val)

        _ ->
            node


Added tests/Test/PlayExpect.elm version [1b415049a2].





































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
module Test.PlayExpect exposing
    ( allEqual
    , allErr
    , allOk
    )

import Expect


allOk : (a -> Result err ok) -> List a -> Expect.Expectation
allOk fn values =
    let
        expectationList =
            List.map (\val -> \f -> f val |> expectOk val) values

        expectOk original result =
            case result of
                Ok _ ->
                    Expect.pass

                Err _ ->
                    Expect.fail <| "Expected Ok for input " ++ Debug.toString original ++ ", was: " ++ Debug.toString result
    in
    Expect.all expectationList fn


allErr : (a -> Result err ok) -> List a -> Expect.Expectation
allErr fn values =
    let
        expectationList =
            List.map (\val -> \f -> f val |> expectErr val) values

        expectErr original result =
            case result of
                Ok _ ->
                    Expect.fail <| "Expected Err for input " ++ Debug.toString original ++ ", was: " ++ Debug.toString result

                Err _ ->
                    Expect.pass
    in
    Expect.all expectationList fn


allEqual : (a -> b) -> List ( a, b ) -> Expect.Expectation
allEqual fn values =
    let
        expectationList =
            List.map (\( input, expected ) -> \f -> Expect.equal expected (f input)) values
    in
    Expect.all expectationList fn

Modified tests/Test/Qualifier.elm from [f2374a327b] to [34e6530c10].

5
6
7
8
9
10
11

12
13
14
15
16
17
18
..
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
...
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
...
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
...
675
676
677
678
679
680
681









682















































































































































































































683
















































684
685





686

















































687













688



















































































































import Expect
import Play.Data.Builtin as Builtin
import Play.Data.Metadata as Metadata
import Play.Data.SourceLocation exposing (emptyRange)
import Play.Data.Type as Type
import Play.Parser as AST
import Play.Qualifier exposing (..)

import Test exposing (Test, describe, test)
import Test.Parser.Util as ParserUtil
import Test.Qualifier.Util as QualifierUtil


suite : Test
suite =
................................................................................
                                            , Integer emptyRange 2
                                            , Builtin emptyRange Builtin.Equal
                                            ]
                                  }
                                ]
                        }
                in
                case run unqualifiedAst of
                    Err _ ->
                        Expect.fail "Did not expect qualification to fail"

                    Ok qualifiedAst ->
                        Expect.equal expectedAst qualifiedAst
        , test "Generic function types" <|
            \_ ->
                let
                    unqualifiedAst =
                        { types = Dict.empty
                        , words =
                            Dict.fromListBy .name
................................................................................
                                            , Builtin emptyRange Builtin.StackDuplicate
                                            , Builtin emptyRange Builtin.StackRightRotate
                                            ]
                                  }
                                ]
                        }
                in
                case run unqualifiedAst of
                    Err _ ->
                        Expect.fail "Did not expect qualification to fail"

                    Ok qualifiedAst ->
                        Expect.equal expectedAst qualifiedAst
        , test "Union types and multifunctions" <|
            \_ ->
                let
                    unqualifiedAst =
                        { types =
                            Dict.fromListBy AST.typeDefinitionName
                                [ AST.UnionTypeDef emptyRange
................................................................................
                                            ]
                                            []
                                  }
                                ]
                        }
                            |> QualifierUtil.addFunctionsForStructs
                in
                case run unqualifiedAst of
                    Err _ ->
                        Expect.fail "Did not expect qualification to fail"

                    Ok qualifiedAst ->
                        Expect.equal expectedAst qualifiedAst
        , describe "Quotations"
            [ test "Basic case" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types = Dict.empty
                            , words =
................................................................................
                                    , { name = "main"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.asEntryPoint
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , WordRef emptyRange "main__quote2"
                                                , Word emptyRange "apply-to-num"
                                                , WordRef emptyRange "main__quote1"
                                                , Word emptyRange "apply-to-num"
                                                ]
                                      }
                                    , { name = "main__quote2"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.isQuoted
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , Builtin emptyRange Builtin.Plus
                                                ]
                                      }
                                    , { name = "main__quote1"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.isQuoted
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , Builtin emptyRange Builtin.Minus
                                                ]
                                      }
                                    ]
                            }
                    in
                    case run unqualifiedAst of
                        Err _ ->
                            Expect.fail "Did not expect qualification to fail"

                        Ok qualifiedAst ->
                            Expect.equal expectedAst qualifiedAst
            , test "Do not create new function if quoting exactly one word" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
................................................................................
                                                [ Integer emptyRange 1
                                                , Builtin emptyRange Builtin.Plus
                                                ]
                                      }
                                    ]
                            }
                    in
                    case run unqualifiedAst of
                        Err _ ->
                            Expect.fail "Did not expect qualification to fail"

                        Ok qualifiedAst ->
                            Expect.equal expectedAst qualifiedAst
            , test "Quotes within quotes is fine" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
................................................................................
                                    [ { name = "main"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.asEntryPoint
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , WordRef emptyRange "main__quote1"
                                                , Builtin emptyRange Builtin.Apply
                                                ]
                                      }
                                    , { name = "main__quote1"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.isQuoted
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , WordRef emptyRange "main__quote1__quote1"
                                                , Builtin emptyRange Builtin.Apply
                                                , Builtin emptyRange Builtin.Plus
                                                ]
                                      }
                                    , { name = "main__quote1__quote1"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.isQuoted
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , Builtin emptyRange Builtin.Plus
                                                ]
                                      }
                                    ]
                            }
                    in
                    case run unqualifiedAst of
                        Err _ ->
                            Expect.fail "Did not expect qualification to fail"

                        Ok qualifiedAst ->
                            Expect.equal expectedAst qualifiedAst
            ]
        , describe "Pattern matching"
            [ test "Basic example" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types =
................................................................................
                                                ]
                                                [ Word emptyRange "False" ]
                                      }
                                    ]
                            }
                                |> QualifierUtil.addFunctionsForStructs
                    in
                    case run unqualifiedAst of
                        Err _ ->
                            Expect.fail "Did not expect qualification to fail"

                        Ok qualifiedAst ->
                            Expect.equal expectedAst qualifiedAst
            , test "Generic cases are allowed" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types =
                                Dict.fromListBy AST.typeDefinitionName
                                    [ AST.UnionTypeDef emptyRange
................................................................................
                                                , Builtin emptyRange Builtin.StackDrop
                                                ]
                                      }
                                    ]
                            }
                                |> QualifierUtil.addFunctionsForStructs
                    in
                    case run unqualifiedAst of
                        Err _ ->
                            Expect.fail "Did not expect qualification to fail"

                        Ok qualifiedAst ->
                            Expect.equal expectedAst qualifiedAst
            ]
        , test "Resolves unions" <|
            \_ ->
                let
                    boolUnion =
                        Type.Union
                            [ Type.Custom "True"
................................................................................
                                            ]
                                            [ Word emptyRange "False" ]
                                  }
                                ]
                        }
                            |> QualifierUtil.addFunctionsForStructs
                in









                case run unqualifiedAst of















































































































































































































                    Err _ ->
















































                        Expect.fail "Did not expect qualification to fail"






                    Ok qualifiedAst ->

















































                        Expect.equal expectedAst qualifiedAst













        ]


























































































































>







 







|
<
<
<
<
<







 







|
<
<
<
<
<







 







|
<
<
<
<
<







 







|

|



|









|












|
<
<
<
<
<







 







|
<
<
<
<
<







 







|



|






|




|












|
<
<
<
<
<







 







|
<
<
<
<
<







 







|
<
<
<
<
<







 







>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
..
91
92
93
94
95
96
97
98





99
100
101
102
103
104
105
...
138
139
140
141
142
143
144
145





146
147
148
149
150
151
152
...
196
197
198
199
200
201
202
203





204
205
206
207
208
209
210
...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300





301
302
303
304
305
306
307
...
353
354
355
356
357
358
359
360





361
362
363
364
365
366
367
...
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430





431
432
433
434
435
436
437
...
491
492
493
494
495
496
497
498





499
500
501
502
503
504
505
...
553
554
555
556
557
558
559
560





561
562
563
564
565
566
567
...
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
import Expect
import Play.Data.Builtin as Builtin
import Play.Data.Metadata as Metadata
import Play.Data.SourceLocation exposing (emptyRange)
import Play.Data.Type as Type
import Play.Parser as AST
import Play.Qualifier exposing (..)
import Set
import Test exposing (Test, describe, test)
import Test.Parser.Util as ParserUtil
import Test.Qualifier.Util as QualifierUtil


suite : Test
suite =
................................................................................
                                            , Integer emptyRange 2
                                            , Builtin emptyRange Builtin.Equal
                                            ]
                                  }
                                ]
                        }
                in
                QualifierUtil.expectOutput unqualifiedAst expectedAst





        , test "Generic function types" <|
            \_ ->
                let
                    unqualifiedAst =
                        { types = Dict.empty
                        , words =
                            Dict.fromListBy .name
................................................................................
                                            , Builtin emptyRange Builtin.StackDuplicate
                                            , Builtin emptyRange Builtin.StackRightRotate
                                            ]
                                  }
                                ]
                        }
                in
                QualifierUtil.expectOutput unqualifiedAst expectedAst





        , test "Union types and multifunctions" <|
            \_ ->
                let
                    unqualifiedAst =
                        { types =
                            Dict.fromListBy AST.typeDefinitionName
                                [ AST.UnionTypeDef emptyRange
................................................................................
                                            ]
                                            []
                                  }
                                ]
                        }
                            |> QualifierUtil.addFunctionsForStructs
                in
                QualifierUtil.expectOutput unqualifiedAst expectedAst





        , describe "Quotations"
            [ test "Basic case" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types = Dict.empty
                            , words =
................................................................................
                                    , { name = "main"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.asEntryPoint
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , WordRef emptyRange "quote:main/2"
                                                , Word emptyRange "apply-to-num"
                                                , WordRef emptyRange "quote:main/1"
                                                , Word emptyRange "apply-to-num"
                                                ]
                                      }
                                    , { name = "quote:main/2"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.isQuoted
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , Builtin emptyRange Builtin.Plus
                                                ]
                                      }
                                    , { name = "quote:main/1"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.isQuoted
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , Builtin emptyRange Builtin.Minus
                                                ]
                                      }
                                    ]
                            }
                    in
                    QualifierUtil.expectOutput unqualifiedAst expectedAst





            , test "Do not create new function if quoting exactly one word" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
................................................................................
                                                [ Integer emptyRange 1
                                                , Builtin emptyRange Builtin.Plus
                                                ]
                                      }
                                    ]
                            }
                    in
                    QualifierUtil.expectOutput unqualifiedAst expectedAst





            , test "Quotes within quotes is fine" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
................................................................................
                                    [ { name = "main"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.asEntryPoint
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , WordRef emptyRange "quote:main/1"
                                                , Builtin emptyRange Builtin.Apply
                                                ]
                                      }
                                    , { name = "quote:main/1"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.isQuoted
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , WordRef emptyRange "quote:main/1/1"
                                                , Builtin emptyRange Builtin.Apply
                                                , Builtin emptyRange Builtin.Plus
                                                ]
                                      }
                                    , { name = "quote:main/1/1"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.isQuoted
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , Builtin emptyRange Builtin.Plus
                                                ]
                                      }
                                    ]
                            }
                    in
                    QualifierUtil.expectOutput unqualifiedAst expectedAst





            ]
        , describe "Pattern matching"
            [ test "Basic example" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types =
................................................................................
                                                ]
                                                [ Word emptyRange "False" ]
                                      }
                                    ]
                            }
                                |> QualifierUtil.addFunctionsForStructs
                    in
                    QualifierUtil.expectOutput unqualifiedAst expectedAst





            , test "Generic cases are allowed" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types =
                                Dict.fromListBy AST.typeDefinitionName
                                    [ AST.UnionTypeDef emptyRange
................................................................................
                                                , Builtin emptyRange Builtin.StackDrop
                                                ]
                                      }
                                    ]
                            }
                                |> QualifierUtil.addFunctionsForStructs
                    in
                    QualifierUtil.expectOutput unqualifiedAst expectedAst





            ]
        , test "Resolves unions" <|
            \_ ->
                let
                    boolUnion =
                        Type.Union
                            [ Type.Custom "True"
................................................................................
                                            ]
                                            [ Word emptyRange "False" ]
                                  }
                                ]
                        }
                            |> QualifierUtil.addFunctionsForStructs
                in
                QualifierUtil.expectOutput unqualifiedAst expectedAst
        , test "Name mangling" <|
            \_ ->
                let
                    qualifiedUsMoneyUnion =
                        [ Type.Custom "/play/test/some/module/Dollar"
                        , Type.Custom "/play/test/some/module/Cent"
                        ]

                    unqualifiedAst =
                        { types =
                            Dict.fromListBy AST.typeDefinitionName
                                [ AST.UnionTypeDef emptyRange
                                    "USMoney"
                                    []
                                    [ Type.Custom "Dollar"
                                    , Type.Custom "Cent"
                                    ]
                                , AST.CustomTypeDef emptyRange
                                    "Dollar"
                                    []
                                    [ ( "dollar-value", Type.Int ) ]
                                , AST.CustomTypeDef emptyRange
                                    "Cent"
                                    []
                                    [ ( "cent-value", Type.Int ) ]
                                ]
                        , words =
                            Dict.fromListBy .name
                                [ { name = "into-cents"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withType
                                                [ Type.Custom "USMoney" ]
                                                [ Type.Custom "USMoney" ]
                                  , implementation =
                                        AST.MultiImpl
                                            [ ( AST.TypeMatch emptyRange (Type.Custom "Dollar") []
                                              , [ AST.Word emptyRange "dollar-value>"
                                                , AST.Integer emptyRange 100
                                                , AST.Word emptyRange "*"
                                                ]
                                              )
                                            , ( AST.TypeMatch emptyRange (Type.Custom "Cent") []
                                              , [ AST.Word emptyRange "cent-value>"
                                                ]
                                              )
                                            ]
                                            []
                                  }
                                , { name = "add-money"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withType
                                                [ Type.Custom "USMoney", Type.Custom "USMoney" ]
                                                [ Type.Custom "USMoney" ]
                                  , implementation =
                                        AST.SoloImpl
                                            [ AST.Word emptyRange "into-cents"
                                            , AST.Word emptyRange "swap"
                                            , AST.Word emptyRange "into-cents"
                                            , AST.Word emptyRange "+"
                                            ]
                                  }
                                , { name = "quote-excuse"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withType [ Type.Custom "Dollar" ] [ Type.Custom "Dollar" ]
                                  , implementation =
                                        AST.SoloImpl
                                            [ AST.Word emptyRange "dollar-value>"
                                            , AST.Quotation emptyRange
                                                [ AST.Integer emptyRange 2
                                                , AST.Word emptyRange "*"
                                                ]
                                            , AST.Word emptyRange "!"
                                            , AST.Word emptyRange ">Dollar"
                                            ]
                                  }
                                ]
                        }
                            |> ParserUtil.addFunctionsForStructs

                    expectedAst =
                        { types =
                            Dict.fromListBy typeDefinitionName
                                [ UnionTypeDef
                                    "/play/test/some/module/USMoney"
                                    emptyRange
                                    []
                                    qualifiedUsMoneyUnion
                                , CustomTypeDef "/play/test/some/module/Dollar"
                                    emptyRange
                                    []
                                    [ ( "dollar-value", Type.Int ) ]
                                , CustomTypeDef "/play/test/some/module/Cent"
                                    emptyRange
                                    []
                                    [ ( "cent-value", Type.Int ) ]
                                ]
                        , words =
                            Dict.fromListBy .name
                                [ { name = "/play/test/some/module/into-cents"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withType
                                                [ Type.Union qualifiedUsMoneyUnion ]
                                                [ Type.Union qualifiedUsMoneyUnion ]
                                  , implementation =
                                        MultiImpl
                                            [ ( TypeMatch emptyRange (Type.Custom "/play/test/some/module/Dollar") []
                                              , [ Word emptyRange "/play/test/some/module/dollar-value>"
                                                , Integer emptyRange 100
                                                , Builtin emptyRange Builtin.Multiply
                                                ]
                                              )
                                            , ( TypeMatch emptyRange (Type.Custom "/play/test/some/module/Cent") []
                                              , [ Word emptyRange "/play/test/some/module/cent-value>"
                                                ]
                                              )
                                            ]
                                            []
                                  }
                                , { name = "/play/test/some/module/add-money"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withType
                                                [ Type.Union qualifiedUsMoneyUnion, Type.Union qualifiedUsMoneyUnion ]
                                                [ Type.Union qualifiedUsMoneyUnion ]
                                  , implementation =
                                        SoloImpl
                                            [ Word emptyRange "/play/test/some/module/into-cents"
                                            , Builtin emptyRange Builtin.StackSwap
                                            , Word emptyRange "/play/test/some/module/into-cents"
                                            , Builtin emptyRange Builtin.Plus
                                            ]
                                  }
                                , { name = "/play/test/some/module/quote-excuse"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withType
                                                [ Type.Custom "/play/test/some/module/Dollar" ]
                                                [ Type.Custom "/play/test/some/module/Dollar" ]
                                  , implementation =
                                        SoloImpl
                                            [ Word emptyRange "/play/test/some/module/dollar-value>"
                                            , WordRef emptyRange "quote:/play/test/some/module/quote-excuse/1"
                                            , Builtin emptyRange Builtin.Apply
                                            , Word emptyRange "/play/test/some/module/>Dollar"
                                            ]
                                  }
                                , { name = "quote:/play/test/some/module/quote-excuse/1"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.isQuoted
                                  , implementation =
                                        SoloImpl
                                            [ Integer emptyRange 2
                                            , Builtin emptyRange Builtin.Multiply
                                            ]
                                  }
                                , { name = "/play/test/some/module/>Dollar"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withVerifiedType [ Type.Int ] [ Type.Custom "/play/test/some/module/Dollar" ]
                                  , implementation =
                                        SoloImpl [ ConstructType "/play/test/some/module/Dollar" ]
                                  }
                                , { name = "/play/test/some/module/>Cent"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withVerifiedType [ Type.Int ] [ Type.Custom "/play/test/some/module/Cent" ]
                                  , implementation =
                                        SoloImpl [ ConstructType "/play/test/some/module/Cent" ]
                                  }
                                , { name = "/play/test/some/module/>dollar-value"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withVerifiedType
                                                [ Type.Custom "/play/test/some/module/Dollar", Type.Int ]
                                                [ Type.Custom "/play/test/some/module/Dollar" ]
                                  , implementation =
                                        SoloImpl
                                            [ SetMember "/play/test/some/module/Dollar" "dollar-value" ]
                                  }
                                , { name = "/play/test/some/module/>cent-value"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withVerifiedType
                                                [ Type.Custom "/play/test/some/module/Cent", Type.Int ]
                                                [ Type.Custom "/play/test/some/module/Cent" ]
                                  , implementation =
                                        SoloImpl
                                            [ SetMember "/play/test/some/module/Cent" "cent-value" ]
                                  }
                                , { name = "/play/test/some/module/dollar-value>"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withVerifiedType [ Type.Custom "/play/test/some/module/Dollar" ] [ Type.Int ]
                                  , implementation =
                                        SoloImpl
                                            [ GetMember "/play/test/some/module/Dollar" "dollar-value" ]
                                  }
                                , { name = "/play/test/some/module/cent-value>"
                                  , metadata =
                                        Metadata.default
                                            |> Metadata.withVerifiedType [ Type.Custom "/play/test/some/module/Cent" ] [ Type.Int ]
                                  , implementation =
                                        SoloImpl
                                            [ GetMember "/play/test/some/module/Cent" "cent-value" ]
                                  }
                                ]
                        }
                in
                QualifierUtil.expectModuleOutput unqualifiedAst expectedAst
        , describe "Module loading"
            [ test "Detects package reference in simple word" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "call-external"
                                      , metadata = Metadata.default
                                      , implementation =
                                            AST.SoloImpl
                                                [ AST.Integer emptyRange 1
                                                , AST.PackageWord emptyRange [ "package", "module" ] "sample"
                                                ]
                                      }
                                    ]
                            }

                        expectedAst =
                            { additionalModulesRequired =
                                Set.fromList
                                    [ "/play/test/package/module" ]
                            , checkForExistingTypes = Set.empty
                            , checkForExistingWords =
                                Set.fromList
                                    [ "/play/test/package/module/sample" ]
                            , types = Dict.empty
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "/play/test/package/tests/call-external"
                                      , metadata = Metadata.default
                                      , implementation =
                                            SoloImpl
                                                [ Integer emptyRange 1
                                                , Word emptyRange "/play/test/package/module/sample"
                                                ]
                                      }
                                    ]
                            }

                        result =
                            run
                                { packageName = "play/test"
                                , modulePath = "package/tests"
                                , ast = unqualifiedAst
                                , externalModules = Dict.empty
                                }
                    in
                    case result of
                        Err err ->
                            Expect.fail <| "Did not expect qualification to fail with error: " ++ Debug.toString err

                        Ok actualAst ->
                            Expect.equal expectedAst actualAst
            , test "Detects external reference in simple word" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "call-external"
                                      , metadata = Metadata.default
                                      , implementation =
                                            AST.SoloImpl
                                                [ AST.ExternalWord emptyRange [ "package", "module" ] "sample" ]
                                      }
                                    ]
                            }

                        expectedAst =
                            { additionalModulesRequired =
                                Set.fromList
                                    [ "/external/test/package/module" ]
                            , checkForExistingTypes = Set.empty
                            , checkForExistingWords =
                                Set.fromList
                                    [ "/external/test/package/module/sample"
                                    ]
                            , types = Dict.empty
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "/play/test/package/tests/call-external"
                                      , metadata = Metadata.default
                                      , implementation =
                                            SoloImpl
                                                [ Word emptyRange "/external/test/package/module/sample" ]
                                      }
                                    ]
                            }

                        result =
                            run
                                { packageName = "play/test"
                                , modulePath = "package/tests"
                                , ast = unqualifiedAst
                                , externalModules =
                                    Dict.fromList
                                        [ ( "/package/module", "external/test" )
                                        ]
                                }
                    in
                    case result of
                        Err err ->
                            Expect.fail <| "Did not expect qualification to fail with error: " ++ Debug.toString err

                        Ok actualAst ->
                            Expect.equal expectedAst actualAst
            , test "Detects package reference in multiword" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "call-external"
                                      , metadata = Metadata.default
                                      , implementation =
                                            AST.MultiImpl
                                                [ ( AST.TypeMatch emptyRange Type.Int [ ( "value", AST.LiteralInt 1 ) ]
                                                  , [ AST.PackageWord emptyRange [ "package", "module" ] "when-one"
                                                    ]
                                                  )
                                                ]
                                                [ AST.PackageWord emptyRange [ "package", "module" ] "when-other-one" ]
                                      }
                                    ]
                            }

                        expectedAst =
                            { additionalModulesRequired =
                                Set.fromList
                                    [ "/play/test/package/module" ]
                            , checkForExistingTypes = Set.empty
                            , checkForExistingWords =
                                Set.fromList
                                    [ "/play/test/package/module/when-one"
                                    , "/play/test/package/module/when-other-one"
                                    ]
                            , types = Dict.empty
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "/play/test/package/tests/call-external"
                                      , metadata = Metadata.default
                                      , implementation =
                                            MultiImpl
                                                [ ( TypeMatch emptyRange Type.Int [ ( "value", LiteralInt 1 ) ]
                                                  , [ Word emptyRange "/play/test/package/module/when-one"
                                                    ]
                                                  )
                                                ]
                                                [ Word emptyRange "/play/test/package/module/when-other-one" ]
                                      }
                                    ]
                            }

                        result =
                            run
                                { packageName = "play/test"
                                , modulePath = "package/tests"
                                , ast = unqualifiedAst
                                , externalModules = Dict.empty
                                }
                    in
                    case result of
                        Err err ->
                            Expect.fail <| "Did not expect qualification to fail with error: " ++ Debug.toString err

                        Ok actualAst ->
                            Expect.equal expectedAst actualAst
            , test "Detects external reference in multiword" <|
                \_ ->
                    let
                        unqualifiedAst =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "call-external"
                                      , metadata = Metadata.default
                                      , implementation =
                                            AST.MultiImpl
                                                [ ( AST.TypeMatch emptyRange Type.Int [ ( "value", AST.LiteralInt 1 ) ]
                                                  , [ AST.ExternalWord emptyRange [ "package", "module" ] "when-one"
                                                    ]
                                                  )
                                                ]
                                                [ AST.ExternalWord emptyRange [ "package", "module" ] "when-other-one" ]
                                      }
                                    ]
                            }

                        expectedAst =
                            { additionalModulesRequired =
                                Set.fromList
                                    [ "/external/test/package/module" ]
                            , checkForExistingTypes = Set.empty
                            , checkForExistingWords =
                                Set.fromList
                                    [ "/external/test/package/module/when-one"
                                    , "/external/test/package/module/when-other-one"
                                    ]
                            , types = Dict.empty
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "/play/test/package/tests/call-external"
                                      , metadata = Metadata.default
                                      , implementation =
                                            MultiImpl
                                                [ ( TypeMatch emptyRange Type.Int [ ( "value", LiteralInt 1 ) ]
                                                  , [ Word emptyRange "/external/test/package/module/when-one"
                                                    ]
                                                  )
                                                ]
                                                [ Word emptyRange "/external/test/package/module/when-other-one" ]
                                      }
                                    ]
                            }

                        result =
                            run
                                { packageName = "play/test"
                                , modulePath = "package/tests"
                                , ast = unqualifiedAst
                                , externalModules =
                                    Dict.fromList
                                        [ ( "/package/module", "external/test" )
                                        ]
                                }
                    in
                    case result of
                        Err err ->
                            Expect.fail <| "Did not expect qualification to fail with error: " ++ Debug.toString err

                        Ok actualAst ->
                            Expect.equal expectedAst actualAst
            ]
        ]

Modified tests/Test/Qualifier/Error.elm from [a210e4b5e1] to [42c36a26bb].

43
44
45
46
47
48
49

















50
51
52
53
54
55
56
57


58
59
60
61
62
63
64
65
66
..
84
85
86
87
88
89
90














91
92
93
94
95





96





97
98












99
100
101
102
103
104




















105
106









107
108
109
110
111
112
113
114
115
116
                                                , AST.Word emptyRange "dec"
                                                , AST.Integer emptyRange 2
                                                , AST.Word emptyRange "="
                                                ]
                                      }
                                    ]
                            }


















                        noSuchReferenceError name problem =
                            case problem of
                                UnknownWordRef _ problemName ->
                                    name == problemName

                                _ ->
                                    False


                    in
                    checkForError (noSuchReferenceError "dec") ast
            , test "Type" <|
                \_ ->
                    let
                        ast =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
................................................................................
                                                , AST.Word emptyRange "inc"
                                                , AST.Integer emptyRange 2
                                                , AST.Word emptyRange "="
                                                ]
                                      }
                                    ]
                            }















                        noSuchReferenceError name problem =
                            case problem of
                                UnknownTypeRef _ problemName ->
                                    name == problemName











                                _ ->
                                    False












                    in
                    checkForError (noSuchReferenceError "Ints") ast
            ]
        ]






















checkForError : (Problem -> Bool) -> AST.AST -> Expectation
checkForError fn source =









    case run source of
        Err errors ->
            if List.any fn errors then
                Expect.pass

            else
                Expect.fail <| "Failed for unexpected reason: " ++ Debug.toString errors

        Ok _ ->
            Expect.fail "Did not expect parsing to succeed"







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
|
<
<
>
>

|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
>
>
>
>
>
|
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>

|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
|









43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67




68


69
70
71
72
73
74
75
76
77
78
79
..
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118




119
120
121
122
123
124
125
126
127
128
129
130

131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
                                                , AST.Word emptyRange "dec"
                                                , AST.Integer emptyRange 2
                                                , AST.Word emptyRange "="
                                                ]
                                      }
                                    ]
                            }
                    in
                    checkForError (noSuchWordReferenceError "dec") ast
            , test "External" <|
                \_ ->
                    let
                        ast =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "main"
                                      , metadata =
                                            Metadata.default
                                                |> Metadata.asEntryPoint
                                      , implementation =
                                            AST.SoloImpl
                                                [ AST.Integer emptyRange 1
                                                , AST.Word emptyRange "/external/module/inc"
                                                ]




                                      }


                                    ]
                            }
                    in
                    checkForError (noSuchWordReferenceError "/external/module/inc") ast
            , test "Type" <|
                \_ ->
                    let
                        ast =
                            { types = Dict.empty
                            , words =
                                Dict.fromListBy .name
................................................................................
                                                , AST.Word emptyRange "inc"
                                                , AST.Integer emptyRange 2
                                                , AST.Word emptyRange "="
                                                ]
                                      }
                                    ]
                            }
                    in
                    checkForError (noSuchTypeReferenceError "Ints") ast
            , test "Wrong reference within union definition" <|
                \_ ->
                    let
                        ast =
                            { types =
                                Dict.fromListBy AST.typeDefinitionName
                                    [ AST.UnionTypeDef
                                        emptyRange
                                        "USMoney"
                                        []
                                        [ Type.Custom "Dollar"
                                        , Type.Custom "Cent"
                                        ]




                                    , AST.CustomTypeDef
                                        emptyRange
                                        "Dollar"
                                        []
                                        [ ( "dollar-value", Type.Int ) ]
                                    ]
                            , words = Dict.empty
                            }
                    in
                    checkForError (noSuchTypeReferenceError "Cent") ast
            , test "Wrong reference within custom type definition" <|
                \_ ->

                    let
                        ast =
                            { types =
                                Dict.fromListBy AST.typeDefinitionName
                                    [ AST.CustomTypeDef
                                        emptyRange
                                        "BoxWrapper"
                                        []
                                        [ ( "box", Type.Custom "Box" ) ]
                                    ]
                            , words = Dict.empty
                            }
                    in
                    checkForError (noSuchTypeReferenceError "Box") ast
            ]
        ]


noSuchWordReferenceError : String -> Problem -> Bool
noSuchWordReferenceError name problem =
    case problem of
        UnknownWordRef _ problemName ->
            name == problemName

        _ ->
            False


noSuchTypeReferenceError : String -> Problem -> Bool
noSuchTypeReferenceError name problem =
    case problem of
        UnknownTypeRef _ problemName ->
            name == problemName

        _ ->
            False


checkForError : (Problem -> Bool) -> AST.AST -> Expectation
checkForError fn source =
    let
        result =
            run
                { packageName = ""
                , modulePath = ""
                , ast = source
                , externalModules = Dict.empty
                }
    in
    case result of
        Err errors ->
            if List.any fn errors then
                Expect.pass

            else
                Expect.fail <| "Failed for unexpected reason: " ++ Debug.toString errors

        Ok _ ->
            Expect.fail "Did not expect parsing to succeed"

Modified tests/Test/Qualifier/Util.elm from [2822ce177a] to [f85a91ec9e].

1




2

3
4

5

6

7








8
9



















































10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
74
75
76
77
78
79
80















































































module Test.Qualifier.Util exposing (addFunctionsForStructs)






import Dict
import Dict.Extra as Dict

import Play.Data.Metadata as Metadata

import Play.Data.Type as Type exposing (Type)

import Play.Qualifier as AST exposing (AST)





























































addFunctionsForStructs : AST -> AST
addFunctionsForStructs ast =
    let
        helper _ t wipAst =
            case t of
                AST.CustomTypeDef name _ generics members ->
                    addFunctionsForStructsHelper name generics members wipAst

                _ ->
                    wipAst
    in
    Dict.foldl helper ast ast.types


addFunctionsForStructsHelper : String -> List String -> List ( String, Type ) -> AST -> AST
addFunctionsForStructsHelper name generics members ast =
    let
        selfType =
            if List.isEmpty generics then
                Type.Custom name

            else
................................................................................

        allFuncs =
            (ctor :: setters)
                ++ getters
                |> Dict.fromListBy .name
    in
    { ast | words = Dict.union ast.words allFuncs }















































































|
>
>
>
>
|
>
|

>

>

>
|
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|













|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
module Test.Qualifier.Util exposing
    ( addFunctionsForStructs
    , expectModuleOutput
    , expectOutput
    , stripLocations
    )

import Dict exposing (Dict)
import Dict.Extra as Dict
import Expect exposing (Expectation)
import Play.Data.Metadata as Metadata
import Play.Data.SourceLocation exposing (emptyRange)
import Play.Data.Type as Type exposing (Type)
import Play.Parser as Parser
import Play.Qualifier as AST
    exposing
        ( ExposedAST
        , Node(..)
        , TypeDefinition
        , TypeMatch(..)
        , TypeMatchValue(..)
        , WordDefinition
        , WordImplementation(..)
        )


type alias FullyLoadedAST =
    { types : Dict String TypeDefinition
    , words : Dict String WordDefinition
    }


expectOutput : Parser.AST -> FullyLoadedAST -> Expectation
expectOutput parserAst expectedAst =
    let
        result =
            AST.run
                { packageName = ""
                , modulePath = ""
                , ast = parserAst
                , externalModules = Dict.empty
                }
    in
    case result of
        Err errors ->
            Expect.fail <| "Did not expect qualification to fail. Errors: " ++ Debug.toString errors

        Ok actualAst ->
            Expect.equal expectedAst
                { types = actualAst.types
                , words = actualAst.words
                }


expectModuleOutput : Parser.AST -> FullyLoadedAST -> Expectation
expectModuleOutput parserAst expectedAst =
    let
        result =
            AST.run
                { packageName = "play/test"
                , modulePath = "some/module"
                , ast = parserAst
                , externalModules = Dict.empty
                }
    in
    case result of
        Err errors ->
            Expect.fail <| "Did not expect qualification to fail. Errors: " ++ Debug.toString errors

        Ok actualAst ->
            Expect.equal expectedAst
                { types = actualAst.types
                , words = actualAst.words
                }


addFunctionsForStructs : FullyLoadedAST -> FullyLoadedAST
addFunctionsForStructs ast =
    let
        helper _ t wipAst =
            case t of
                AST.CustomTypeDef name _ generics members ->
                    addFunctionsForStructsHelper name generics members wipAst

                _ ->
                    wipAst
    in
    Dict.foldl helper ast ast.types


addFunctionsForStructsHelper : String -> List String -> List ( String, Type ) -> FullyLoadedAST -> FullyLoadedAST
addFunctionsForStructsHelper name generics members ast =
    let
        selfType =
            if List.isEmpty generics then
                Type.Custom name

            else
................................................................................

        allFuncs =
            (ctor :: setters)
                ++ getters
                |> Dict.fromListBy .name
    in
    { ast | words = Dict.union ast.words allFuncs }


stripLocations : ExposedAST -> ExposedAST
stripLocations ast =
    { types = Dict.map (\_ t -> stripTypeLocation t) ast.types
    , words = Dict.map (\_ d -> stripWordLocation d) ast.words
    }


stripTypeLocation : TypeDefinition -> TypeDefinition
stripTypeLocation typeDef =
    case typeDef of
        AST.CustomTypeDef name _ generics members ->
            AST.CustomTypeDef name emptyRange generics members

        AST.UnionTypeDef name _ generics members ->
            AST.UnionTypeDef name emptyRange generics members


stripWordLocation : WordDefinition -> WordDefinition
stripWordLocation word =
    { word
        | implementation = stripImplementationLocation word.implementation
        , metadata = Metadata.clearSourceLocationRange word.metadata
    }


stripImplementationLocation : WordImplementation -> WordImplementation
stripImplementationLocation impl =
    case impl of
        SoloImpl nodes ->
            SoloImpl (List.map stripNodeLocation nodes)

        MultiImpl conds default ->
            MultiImpl
                (List.map stripMultiWordBranchLocation conds)
                (List.map stripNodeLocation default)


stripNodeLocation : Node -> Node
stripNodeLocation node =
    case node of
        AST.Integer _ val ->
            AST.Integer emptyRange val

        AST.Word _ val ->
            AST.Word emptyRange val

        AST.WordRef _ val ->
            AST.WordRef emptyRange val

        AST.Builtin _ val ->
            AST.Builtin emptyRange val

        _ ->
            node


stripMultiWordBranchLocation : ( TypeMatch, List Node ) -> ( TypeMatch, List Node )
stripMultiWordBranchLocation ( typeMatch, nodes ) =
    ( stripTypeMatchLocation typeMatch
    , List.map stripNodeLocation nodes
    )


stripTypeMatchLocation : TypeMatch -> TypeMatch
stripTypeMatchLocation (TypeMatch _ type_ otherConds) =
    TypeMatch emptyRange type_ <|
        List.map (Tuple.mapSecond stripRecursiveTypeMatchLocation) otherConds


stripRecursiveTypeMatchLocation : TypeMatchValue -> TypeMatchValue
stripRecursiveTypeMatchLocation typeMatchValue =
    case typeMatchValue of
        RecursiveMatch typeMatch ->
            RecursiveMatch (stripTypeMatchLocation typeMatch)

        _ ->
            typeMatchValue

Modified tests/Test/TypeChecker/Error.elm from [6a887ebaba] to [59a5248785].

616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
                                    False
                    in
                    checkForError inexhaustiveError input
            ]
        ]


checkForError : (Problem.Problem -> Bool) -> AST -> Expectation
checkForError fn source =
    case TypeChecker.run source of
        Err errors ->
            if List.any fn errors then
                Expect.pass

            else
                Expect.fail <| "Failed for unexpected reason: " ++ Debug.toString errors

        Ok _ ->
            Expect.fail "Did not expect type checking to succeed"







|











616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
                                    False
                    in
                    checkForError inexhaustiveError input
            ]
        ]


checkForError : (Problem.Problem -> Bool) -> TypeChecker.LoadedQualifierAST a -> Expectation
checkForError fn source =
    case TypeChecker.run source of
        Err errors ->
            if List.any fn errors then
                Expect.pass

            else
                Expect.fail <| "Failed for unexpected reason: " ++ Debug.toString errors

        Ok _ ->
            Expect.fail "Did not expect type checking to succeed"

Modified wasm_tests/math.test.js from [427aff9e64] to [3440282ac4].

36
37
38
39
40
41
42
43
44
45
46
47
48
49
    expect(result.stackElement()).toBe(15);
});

test('Division', async () => {
    const wat = await compiler.toWat(`
        def: main
        entry: true
        : 10 5 /
    `);

    const result = await compiler.run(wat, 'main');

    expect(result.stackElement()).toBe(2);
});







|






36
37
38
39
40
41
42
43
44
45
46
47
48
49
    expect(result.stackElement()).toBe(15);
});

test('Division', async () => {
    const wat = await compiler.toWat(`
        def: main
        entry: true
        : 10 5 div
    `);

    const result = await compiler.run(wat, 'main');

    expect(result.stackElement()).toBe(2);
});