Website

Check-in [73f643169e]
Login
Overview
Comment:Repl now actually works! Code is executed and potential errors reported.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 73f643169ec9149071835d64499bc277e8d46f4ef15aae7ccd7fd41c1d361a1f
User & Date: robin.hansen on 2020-11-04 06:30:39
Other Links: manifest | tags
Context
2020-11-05
18:21
Added the first five lessons. check-in: f8c89b049f user: robin.hansen tags: trunk
2020-11-04
06:30
Repl now actually works! Code is executed and potential errors reported. check-in: 73f643169e user: robin.hansen tags: trunk
2020-11-03
06:09
Add feature to switch between different lessons in playground check-in: 114740dc32 user: robin.hansen tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Modified playground/package-lock.json from [cc2c4bf748] to [6d94a9b0de].

334
335
336
337
338
339
340
341
342
343
344
345
346
347
348





















































349
350
351
352
353
354
355
...
955
956
957
958
959
960
961










962
963
964
965
966
967
968
....
7077
7078
7079
7080
7081
7082
7083






7084
7085
7086
7087
7088
7089
7090
        "@babel/helper-function-name": "^7.10.4",
        "@babel/template": "^7.10.4",
        "@babel/traverse": "^7.10.4",
        "@babel/types": "^7.10.4"
      }
    },
    "@babel/helpers": {
      "version": "7.12.1",
      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.1.tgz",
      "integrity": "sha512-9JoDSBGoWtmbay98efmT2+mySkwjzeFeAL9BuWNoVQpkPFQF8SIIFUfY5os9u8wVzglzoiPRSW7cuJmBDUt43g==",
      "dev": true,
      "requires": {
        "@babel/template": "^7.10.4",
        "@babel/traverse": "^7.12.1",
        "@babel/types": "^7.12.1"





















































      }
    },
    "@babel/highlight": {
      "version": "7.10.4",
      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
      "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
      "dev": true,
................................................................................
      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz",
      "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==",
      "dev": true,
      "requires": {
        "@babel/helper-create-regexp-features-plugin": "^7.12.1",
        "@babel/helper-plugin-utils": "^7.10.4"
      }










    },
    "@babel/preset-env": {
      "version": "7.12.1",
      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.1.tgz",
      "integrity": "sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg==",
      "dev": true,
      "requires": {
................................................................................
      "dev": true,
      "requires": {
        "domexception": "^1.0.1",
        "webidl-conversions": "^4.0.2",
        "xml-name-validator": "^3.0.0"
      }
    },






    "wcwidth": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
      "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
      "dev": true,
      "requires": {
        "defaults": "^1.0.3"







|
|
|



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







 







>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>







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
....
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
....
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
        "@babel/helper-function-name": "^7.10.4",
        "@babel/template": "^7.10.4",
        "@babel/traverse": "^7.10.4",
        "@babel/types": "^7.10.4"
      }
    },
    "@babel/helpers": {
      "version": "7.12.5",
      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz",
      "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==",
      "dev": true,
      "requires": {
        "@babel/template": "^7.10.4",
        "@babel/traverse": "^7.12.5",
        "@babel/types": "^7.12.5"
      },
      "dependencies": {
        "@babel/generator": {
          "version": "7.12.5",
          "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.5.tgz",
          "integrity": "sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A==",
          "dev": true,
          "requires": {
            "@babel/types": "^7.12.5",
            "jsesc": "^2.5.1",
            "source-map": "^0.5.0"
          }
        },
        "@babel/parser": {
          "version": "7.12.5",
          "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.5.tgz",
          "integrity": "sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ==",
          "dev": true
        },
        "@babel/traverse": {
          "version": "7.12.5",
          "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.5.tgz",
          "integrity": "sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA==",
          "dev": true,
          "requires": {
            "@babel/code-frame": "^7.10.4",
            "@babel/generator": "^7.12.5",
            "@babel/helper-function-name": "^7.10.4",
            "@babel/helper-split-export-declaration": "^7.11.0",
            "@babel/parser": "^7.12.5",
            "@babel/types": "^7.12.5",
            "debug": "^4.1.0",
            "globals": "^11.1.0",
            "lodash": "^4.17.19"
          }
        },
        "@babel/types": {
          "version": "7.12.5",
          "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.5.tgz",
          "integrity": "sha512-gyTcvz7JFa4V45C0Zklv//GmFOAal5fL23OWpBLqc4nZ4Yrz67s4kCNwSK1Gu0MXGTU8mRY3zJYtacLdKXlzig==",
          "dev": true,
          "requires": {
            "@babel/helper-validator-identifier": "^7.10.4",
            "lodash": "^4.17.19",
            "to-fast-properties": "^2.0.0"
          }
        },
        "source-map": {
          "version": "0.5.7",
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
          "dev": true
        }
      }
    },
    "@babel/highlight": {
      "version": "7.10.4",
      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
      "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
      "dev": true,
................................................................................
      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz",
      "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==",
      "dev": true,
      "requires": {
        "@babel/helper-create-regexp-features-plugin": "^7.12.1",
        "@babel/helper-plugin-utils": "^7.10.4"
      }
    },
    "@babel/polyfill": {
      "version": "7.12.1",
      "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz",
      "integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==",
      "dev": true,
      "requires": {
        "core-js": "^2.6.5",
        "regenerator-runtime": "^0.13.4"
      }
    },
    "@babel/preset-env": {
      "version": "7.12.1",
      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.1.tgz",
      "integrity": "sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg==",
      "dev": true,
      "requires": {
................................................................................
      "dev": true,
      "requires": {
        "domexception": "^1.0.1",
        "webidl-conversions": "^4.0.2",
        "xml-name-validator": "^3.0.0"
      }
    },
    "wabt": {
      "version": "1.0.19",
      "resolved": "https://registry.npmjs.org/wabt/-/wabt-1.0.19.tgz",
      "integrity": "sha512-z/7XRZB8tPRW0XdE8HYbA95w2kjus5AwOHnJ5NT9PqzaNZ7z/zHnUdpNdB78TFMgWt+D/u01lg1jG6nWiFmyEw==",
      "dev": true
    },
    "wcwidth": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
      "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
      "dev": true,
      "requires": {
        "defaults": "^1.0.3"

Modified playground/package.json from [7c8a9cbfd9] to [8c57dc3c7c].

6
7
8
9
10
11
12

13
14
15
16
17

18
19
  "scripts": {
    "start": "parcel src/playground.html",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Robin Heggelund Hansen",
  "license": "MIT",
  "devDependencies": {

    "elm": "^0.19.1-3",
    "elm-format": "^0.8.4",
    "elm-hot": "^1.1.5",
    "node-elm-compiler": "^5.0.5",
    "parcel": "^1.12.4"

  }
}







>




|
>


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  "scripts": {
    "start": "parcel src/playground.html",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Robin Heggelund Hansen",
  "license": "MIT",
  "devDependencies": {
    "@babel/polyfill": "^7.12.1",
    "elm": "^0.19.1-3",
    "elm-format": "^0.8.4",
    "elm-hot": "^1.1.5",
    "node-elm-compiler": "^5.0.5",
    "parcel": "^1.12.4",
    "wabt": "^1.0.19"
  }
}

Modified playground/src/Playground.elm from [027f165ed8] to [000c661098].

1
2
3
4
5
6
7
8
..
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
..
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
...
107
108
109
110
111
112
113










114
115
116
117
118
119
120
121
122
123
124
125
module Playground exposing (main)

import Browser
import Dict exposing (Dict)
import Html exposing (Html)
import Html.Attributes as Attributes
import Html.Events as Events
import Lesson01
................................................................................

-- MODEL


type alias Model =
    { activeLesson : LessonContract
    , source : String

    }


init : flags -> ( Model, Cmd Msg )
init _ =
    ( { activeLesson = Lesson01.contract
      , source = Lesson01.contract.content

      }
    , Cmd.none
    )



-- Update


type Msg
    = EditSource String
    | SwitchLesson String




update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        EditSource newSource ->
            ( { model | source = newSource }
................................................................................
                      }
                    , Cmd.none
                    )

                Nothing ->
                    ( model, Cmd.none )













-- VIEW


view : Model -> Html Msg
view model =
    Html.div
        [ Attributes.style "height" "100vh"
        ]
        [ Html.h1
            []
            [ Html.text "Playground" ]



        , Html.div [ Attributes.style "height" "50%" ]
            [ Html.textarea
                [ Attributes.style "width" "50vw"
                , Attributes.style "height" "100%"
                , Events.onInput EditSource
                , Attributes.value model.source
                ]
                []






            , lessonSwitcher model




            ]
        ]


lessonSwitcher : Model -> Html Msg
lessonSwitcher model =
    Html.select
................................................................................

lessonSwitcherOption : LessonContract -> Html Msg
lessonSwitcherOption contract =
    Html.option [ Attributes.value contract.key ]
        [ Html.text contract.label ]













-- MAIN


main : Program () Model Msg
main =
    Browser.element
        { init = init
        , update = update
        , view = view
        , subscriptions = always Sub.none
        }
|







 







>







>












>
>







 







>
>
>
>
>
>
>
>
>
>













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







 







>
>
>
>
>
>
>
>
>
>










|

1
2
3
4
5
6
7
8
..
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
..
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
...
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
port module Playground exposing (main)

import Browser
import Dict exposing (Dict)
import Html exposing (Html)
import Html.Attributes as Attributes
import Html.Events as Events
import Lesson01
................................................................................

-- MODEL


type alias Model =
    { activeLesson : LessonContract
    , source : String
    , result : String
    }


init : flags -> ( Model, Cmd Msg )
init _ =
    ( { activeLesson = Lesson01.contract
      , source = Lesson01.contract.content
      , result = ""
      }
    , Cmd.none
    )



-- Update


type Msg
    = EditSource String
    | SwitchLesson String
    | Compile String
    | CompilationResult String


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        EditSource newSource ->
            ( { model | source = newSource }
................................................................................
                      }
                    , Cmd.none
                    )

                Nothing ->
                    ( model, Cmd.none )

        Compile source ->
            ( model
            , compileSource source
            )

        CompilationResult result ->
            ( { model | result = result }
            , Cmd.none
            )



-- VIEW


view : Model -> Html Msg
view model =
    Html.div
        [ Attributes.style "height" "100vh"
        ]
        [ Html.h1
            []
            [ Html.text "Playground" ]
        , Html.div
            [ Attributes.style "height" "100%" ]
            [ Html.div
                [ Attributes.style "height" "50%" ]
                [ Html.textarea
                    [ Attributes.style "width" "50vw"
                    , Attributes.style "height" "100%"
                    , Events.onInput EditSource
                    , Attributes.value model.source
                    ]
                    []
                , Html.span
                    []
                    [ Html.text model.result ]
                ]
            , Html.div
                []
                [ lessonSwitcher model
                , Html.button
                    [ Events.onClick <| Compile model.source ]
                    [ Html.text "Run" ]
                ]
            ]
        ]


lessonSwitcher : Model -> Html Msg
lessonSwitcher model =
    Html.select
................................................................................

lessonSwitcherOption : LessonContract -> Html Msg
lessonSwitcherOption contract =
    Html.option [ Attributes.value contract.key ]
        [ Html.text contract.label ]



-- PORTS


port compileSource : String -> Cmd msg


port compilationResult : (String -> msg) -> Sub msg



-- MAIN


main : Program () Model Msg
main =
    Browser.element
        { init = init
        , update = update
        , view = view
        , subscriptions = always <| compilationResult CompilationResult
        }

Modified playground/src/playground.js from [0ab9c525d8] to [1cab96131b].

1



2
3
4
5























































import { Elm } from './Playground.elm';




const app = Elm.Playground.init({
  node: document.getElementById('elm-app')
});
























































>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
import { Elm } from './Playground.elm';
import Compiler from '../../../play/wasm_tests/compiler';
import '@babel/polyfill';
import wabtInit from 'wabt';

const app = Elm.Playground.init({
  node: document.getElementById('elm-app')
});

app.ports.compileSource.subscribe(source => {
    compileToWat(source)
        .then(val => {
            return execute(val);
        })
        .then(val => {
            return app.ports.compilationResult.send(val);
        })
        .catch(err => {
            return app.ports.compilationResult.send(err);
        });
});

function compileToWat(source) {
    return new Promise((resolve, reject) => {
        const compiler = Compiler.Elm.Main.init({});

        compiler.ports.compileFinished.subscribe(([ok, output]) => {
            if (ok) {
                resolve(output);
            } else {
                reject(output);
            }
        });

        compiler.ports.compileString.send(source);
    });
}

async function execute(wat) {
    const wabt = await wabtInit();
    const wasmModule = wabt.parseWat('tmp', wat).toBinary({}).buffer;

    const memory = new WebAssembly.Memory({
        initial: 10
    });

    const imports = {
        host: {
            memory: memory
        }
    };

    const program = await WebAssembly.instantiate(wasmModule, imports);
    const main = program.instance.exports.main;
    if (typeof main === 'undefined') {
        return "Could not find a word named 'main'";
    }

    main();

    const memView = new Uint32Array(memory.buffer);
    return memView[3].toString(); // First three i32 elements are stack and heap information
}