├── .gitignore ├── README.md ├── another.gr ├── favicon.ico ├── hello.gr ├── index.html ├── package.json └── tools └── grain /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | **/*.gr.wasm 3 | stdlib/*.md 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Grain Web Example 2 | 3 | This repo contains an example of Grain wasm files running in a browser. 4 | 5 | ## Setup 6 | 7 | First, you'll need to install the Grain compiler by following the [Getting Grain](https://grain-lang.org/docs/getting_grain) guide for your operating system. 8 | 9 | Additionally, you'll need to install the project dependencies using: 10 | 11 | ```sh 12 | npm install 13 | ``` 14 | 15 | The easiest way to compile your Grain files to WebAssembly is to use the built-in npm script: 16 | 17 | ```sh 18 | npm run compile 19 | ``` 20 | 21 | This will compile `hello.gr`, `another.gr`, and the necessary stdlib dependencies. 22 | 23 | Then, run a webserver in this directory. You can use our other npm script: 24 | 25 | ```sh 26 | npm start 27 | ``` 28 | 29 | (This script will also compile your project before starting the webserver). 30 | 31 | If you visit `localhost:1337` and open your dev console, you should see the hello world messages appear. 32 | 33 | ## `index.html` Breakdown 34 | 35 | We first load the Grain browser runtime with this script tag: 36 | 37 | ```html 38 | 39 | ``` 40 | 41 | `Grain.buildGrainRunner` takes a locator function as its argument. In this case, we just use the `defaultURLLocator`. As arguments, we pass the locations to look for wasm files—the current URL as the root, and the `node_modules/@grain/stdlib` subdirectory. The default locator will try to find wasm files by first looking in the root of this project, followed by the stdlib directory. 42 | 43 | Once the `GrainRunner` is set up, we call `GrainRunner.runURL` with `hello.wasm`. The locator will then fetch `hello.wasm`, see that it depends on `another.wasm` and `pervasives.wasm`, and load those as well. 44 | -------------------------------------------------------------------------------- /another.gr: -------------------------------------------------------------------------------- 1 | export let anotherHello = "Hello from another file!" 2 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grain-lang/grain-web-example/70e5e3c1f3361dc4f5138eaef9f70c8da15e6179/favicon.ico -------------------------------------------------------------------------------- /hello.gr: -------------------------------------------------------------------------------- 1 | import { anotherHello } from "./another" 2 | 3 | print("Hello, world!") 4 | print(anotherHello) 5 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grain-web-example", 3 | "version": "0.0.0", 4 | "description": "This repo contains an example of Grain wasm files running in a browser.", 5 | "dependencies": { 6 | "@grain/js-runner": "^0.4.0", 7 | "@grain/stdlib": "^0.4.0" 8 | }, 9 | "devDependencies": { 10 | "st": "^3.0.0", 11 | "which": "^2.0.2" 12 | }, 13 | "scripts": { 14 | "prestart": "npm run compile", 15 | "start": "st -l -i index.html", 16 | "compile": "tools/grain compile --stdlib=node_modules/@grain/stdlib hello.gr" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tools/grain: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const cp = require('child_process'); 4 | const which = require('which'); 5 | 6 | const grainBinaries = [ 7 | 'grain', 8 | 'grain.cmd', // TODO: check this on windows 9 | 'grain-mac-x64', 10 | 'grain-linux-x64', 11 | 'grain-win-x64.exe' 12 | ]; 13 | 14 | function findGrain() { 15 | for (const bin of grainBinaries) { 16 | try { 17 | const grain = which.sync(bin); 18 | // If it didn't throw, we found a grain binary 19 | return grain; 20 | } catch (err) { 21 | // Not found 22 | } 23 | } 24 | console.error('Unable to locate any Grain binary. Did you install it?'); 25 | process.exit(1); 26 | } 27 | 28 | const grain = findGrain(); 29 | const args = process.argv.slice(2); 30 | 31 | const result = cp.spawnSync(grain, args, { stdio: 'inherit' }); 32 | process.exit(result.status); 33 | --------------------------------------------------------------------------------