motoko 0.1.5 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +153 -9
- package/contrib/hljs.js +109 -110
- package/contrib/monaco.js +2 -2
- package/index.js +6 -0
- package/interpreter.js +6 -0
- package/lib/__tests__/index.test.js +40 -0
- package/lib/__tests__/interpreter.test.js +15 -0
- package/lib/file.js +66 -0
- package/lib/index.js +112 -78
- package/lib/package.js +2 -4
- package/package.json +8 -5
- package/versions/latest/didc.min.js +1 -0
- package/versions/latest/moc.min.js +1 -0
- package/versions/latest/moc_interpreter.min.js +1 -0
- package/lib/generated/moc.js +0 -1
- package/lib/index.spec.js +0 -31
package/README.md
CHANGED
@@ -7,10 +7,12 @@
|
|
7
7
|
## Installation:
|
8
8
|
|
9
9
|
```sh
|
10
|
-
npm
|
10
|
+
npm i --save motoko
|
11
11
|
```
|
12
12
|
|
13
|
-
##
|
13
|
+
## Examples:
|
14
|
+
|
15
|
+
### Basic usage
|
14
16
|
|
15
17
|
```js
|
16
18
|
import mo from 'motoko';
|
@@ -18,11 +20,11 @@ import mo from 'motoko';
|
|
18
20
|
const mo = require('motoko');
|
19
21
|
|
20
22
|
// Create a Motoko script in a virtual file system
|
21
|
-
mo.
|
23
|
+
mo.write('Main.mo', `
|
22
24
|
actor {
|
23
|
-
public func hello() : async Text {
|
25
|
+
public query func hello() : async Text {
|
24
26
|
"Hello, JavaScript!"
|
25
|
-
}
|
27
|
+
};
|
26
28
|
}
|
27
29
|
`);
|
28
30
|
|
@@ -30,18 +32,160 @@ actor {
|
|
30
32
|
console.log(mo.candid('Main.mo'));
|
31
33
|
```
|
32
34
|
|
33
|
-
|
35
|
+
### Evaluate a program
|
34
36
|
|
35
37
|
```js
|
38
|
+
mo.write('Main.mo', `
|
39
|
+
actor Main {
|
40
|
+
public query func hello() : async Text {
|
41
|
+
"Hello, world!"
|
42
|
+
};
|
43
|
+
};
|
44
|
+
|
45
|
+
await Main.hello();
|
46
|
+
`)
|
47
|
+
mo.run('Main.mo');
|
48
|
+
```
|
49
|
+
|
50
|
+
### Evaluate a program (shorthand)
|
51
|
+
|
52
|
+
```js
|
53
|
+
mo.file('Main.mo')
|
54
|
+
.write('actor Main { public query func getNumber() : async Nat { 5 } }')
|
55
|
+
.run();
|
56
|
+
```
|
36
57
|
|
37
|
-
|
58
|
+
### Load dependencies from GitHub
|
59
|
+
|
60
|
+
```js
|
61
|
+
mo.clearPackages();
|
38
62
|
await mo.loadPackages({
|
39
|
-
base: 'dfinity/motoko-base/master/src',
|
63
|
+
base: 'dfinity/motoko-base/master/src', // import "mo:base/...";
|
40
64
|
});
|
65
|
+
```
|
66
|
+
|
67
|
+
### Generate parse trees
|
41
68
|
|
69
|
+
```js
|
42
70
|
// Generate a Motoko AST
|
43
|
-
console.log(mo.
|
71
|
+
console.log(mo.parseMotoko('actor Main { public query func test() : async Nat { 123 } }'));
|
44
72
|
|
45
73
|
// Generate a Candid AST
|
46
74
|
console.log(mo.parseCandid('service : { test : () -> (nat) }'));
|
47
75
|
```
|
76
|
+
|
77
|
+
### Optimize for browsers
|
78
|
+
|
79
|
+
```js
|
80
|
+
// Load just the `write()`, `loadPackages()`, `clearPackages()`, and `run()`, operations for a smaller file size:
|
81
|
+
import mo from 'motoko/interpreter';
|
82
|
+
```
|
83
|
+
|
84
|
+
## API:
|
85
|
+
|
86
|
+
### Top-level API
|
87
|
+
|
88
|
+
```js
|
89
|
+
// Read the contents of a virtual file
|
90
|
+
mo.read(path)
|
91
|
+
|
92
|
+
// Write a string to a virtual file
|
93
|
+
mo.write(path, string)
|
94
|
+
|
95
|
+
// Rename a virtual file
|
96
|
+
mo.rename(path, newPath)
|
97
|
+
|
98
|
+
// Delete a virtual file
|
99
|
+
mo.delete(path)
|
100
|
+
|
101
|
+
// List the files in a virtual directory
|
102
|
+
mo.list(path)
|
103
|
+
|
104
|
+
// Try to load packages from GitHub and/or jsDelivr
|
105
|
+
await mo.loadPackages({ packageName: repositoryPath, ... })
|
106
|
+
|
107
|
+
// Use a virtual directory as a package
|
108
|
+
mo.addPackage(packageName, directory)
|
109
|
+
|
110
|
+
// Clear loaded packages
|
111
|
+
mo.clearPackages()
|
112
|
+
|
113
|
+
// Configure the compiler to resolve `import "canister:{alias}";` -> `import "canister:{id}";`
|
114
|
+
mo.setAliases({ alias: id, ... })
|
115
|
+
|
116
|
+
// Set the public metadata (an array of strings) used by the compiler
|
117
|
+
mo.setMetadata(strings)
|
118
|
+
|
119
|
+
// Generate errors and warnings for a Motoko program
|
120
|
+
mo.check(path)
|
121
|
+
|
122
|
+
// Run a Motoko program with optional virtual library paths
|
123
|
+
mo.run(path)
|
124
|
+
mo.run(path, [libraryPath, ...])
|
125
|
+
|
126
|
+
// Generate the Candid interface for a Motoko program
|
127
|
+
mo.candid(path)
|
128
|
+
|
129
|
+
// Compile a Motoko program to WebAssembly
|
130
|
+
mo.wasm(path, 'ic') // IC interface format (default)
|
131
|
+
mo.wasm(path, 'wasi') // WASI interface format
|
132
|
+
|
133
|
+
// Return the parse tree for a Motoko string
|
134
|
+
mo.parseMotoko(motokoString)
|
135
|
+
|
136
|
+
// Return the parse tree for a Candid string
|
137
|
+
mo.parseCandid(candidString)
|
138
|
+
|
139
|
+
// Get the version name
|
140
|
+
mo.version
|
141
|
+
|
142
|
+
// Access the underlying Motoko compiler
|
143
|
+
mo.compiler
|
144
|
+
```
|
145
|
+
|
146
|
+
### File API
|
147
|
+
|
148
|
+
```js
|
149
|
+
// Create an object representing a virtual file
|
150
|
+
const file = mo.file('Main.mo')
|
151
|
+
|
152
|
+
// Get the file path
|
153
|
+
file.path
|
154
|
+
|
155
|
+
// Get another file object with the same path
|
156
|
+
file.clone()
|
157
|
+
|
158
|
+
// Read the file as a string
|
159
|
+
file.read()
|
160
|
+
|
161
|
+
// Write a string to the file
|
162
|
+
file.write(string)
|
163
|
+
|
164
|
+
// Rename the file
|
165
|
+
file.rename(newPath)
|
166
|
+
|
167
|
+
// Delete the file
|
168
|
+
file.delete()
|
169
|
+
|
170
|
+
// List children (if a directory)
|
171
|
+
file.list()
|
172
|
+
|
173
|
+
// Generate errors and warnings for a Motoko program
|
174
|
+
file.check()
|
175
|
+
|
176
|
+
// Run the file as a Motoko program
|
177
|
+
file.run()
|
178
|
+
|
179
|
+
// Generate the Candid interface for a Motoko program
|
180
|
+
file.candid()
|
181
|
+
|
182
|
+
// Compile the file to WebAssembly (see `mo.wasm()`)
|
183
|
+
file.wasm('ic')
|
184
|
+
file.wasm('wasi') // note: cannot contain actors
|
185
|
+
|
186
|
+
// Parse the file as a Motoko program
|
187
|
+
file.parseMotoko()
|
188
|
+
|
189
|
+
// Parse the file as a Candid interface
|
190
|
+
file.parseCandid()
|
191
|
+
```
|
package/contrib/hljs.js
CHANGED
@@ -1,122 +1,121 @@
|
|
1
1
|
// Highlight.js configuration
|
2
2
|
|
3
|
-
|
3
|
+
exports.configure = (hljs) => {
|
4
4
|
var string = {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
className: 'string',
|
6
|
+
variants: [
|
7
|
+
{
|
8
|
+
begin: /r(#*)"(.|\n)*?"\1(?!#)/,
|
9
|
+
},
|
10
|
+
{
|
11
|
+
begin: /b?'\\?(x\w{2}|u\w{4}|U\w{8}|.)'/,
|
12
|
+
},
|
13
|
+
],
|
14
14
|
};
|
15
15
|
var number = {
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
16
|
+
className: 'number',
|
17
|
+
variants: [
|
18
|
+
{
|
19
|
+
begin: '[+-]?\\b0[xX]([A-Fa-f0-9_]+)',
|
20
|
+
},
|
21
|
+
{
|
22
|
+
begin: '[+-]?\\b(\\d[\\d_]*(\\.[0-9_]+)?([eE][+-]?[0-9_]+)?)',
|
23
|
+
},
|
24
|
+
],
|
25
|
+
relevance: 0,
|
26
26
|
};
|
27
27
|
hljs.registerLanguage('motoko', function (hljs) {
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
contains: [
|
48
|
-
hljs.C_LINE_COMMENT_MODE,
|
49
|
-
hljs.COMMENT('/\\*', '\\*/', {
|
50
|
-
contains: ['self'],
|
51
|
-
}),
|
52
|
-
hljs.inherit(hljs.QUOTE_STRING_MODE, {
|
53
|
-
begin: /b?"/,
|
54
|
-
illegal: null,
|
55
|
-
}),
|
56
|
-
string,
|
57
|
-
number,
|
58
|
-
{
|
59
|
-
className: 'symbol',
|
60
|
-
begin: '#' + hljs.UNDERSCORE_IDENT_RE,
|
61
|
-
},
|
62
|
-
{
|
63
|
-
className: 'function',
|
64
|
-
beginKeywords: 'func',
|
65
|
-
end: '(\\(|<|=|{)',
|
66
|
-
excludeEnd: true,
|
67
|
-
contains: [hljs.UNDERSCORE_TITLE_MODE],
|
68
|
-
},
|
69
|
-
{
|
70
|
-
className: 'class',
|
71
|
-
begin: '\\b(actor( class)?|module|object)\\b',
|
72
|
-
keywords: 'actor class module object',
|
73
|
-
end: '(\\(|<|{)',
|
74
|
-
contains: [hljs.UNDERSCORE_TITLE_MODE],
|
75
|
-
illegal: '[\\w\\d]',
|
76
|
-
},
|
77
|
-
{
|
78
|
-
className: 'built_in',
|
79
|
-
beginKeywords: 'import type',
|
80
|
-
end: '(;|$|=)',
|
81
|
-
excludeEnd: true,
|
28
|
+
return {
|
29
|
+
name: 'Motoko',
|
30
|
+
aliases: ['mo'],
|
31
|
+
keywords: {
|
32
|
+
$pattern: '[a-zA-Z_]\\w*',
|
33
|
+
keyword:
|
34
|
+
'actor and await break case catch class' +
|
35
|
+
' continue debug do else for func if in import' +
|
36
|
+
' module not object or label let loop private' +
|
37
|
+
' public return shared try throw query switch' +
|
38
|
+
' type var while stable flexible system debug_show assert ignore from_candid to_candid',
|
39
|
+
literal: 'true false null',
|
40
|
+
built_in:
|
41
|
+
'Any None Null Bool Int Int8 Int16 Int32 Int64' +
|
42
|
+
' Nat Nat8 Nat16 Nat32 Nat64 Word8 Word16 Word32 Word64' +
|
43
|
+
' Float Char Text Blob Error Principal' +
|
44
|
+
' async',
|
45
|
+
},
|
46
|
+
illegal: '</',
|
82
47
|
contains: [
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
48
|
+
hljs.C_LINE_COMMENT_MODE,
|
49
|
+
hljs.COMMENT('/\\*', '\\*/', {
|
50
|
+
contains: ['self'],
|
51
|
+
}),
|
52
|
+
hljs.inherit(hljs.QUOTE_STRING_MODE, {
|
53
|
+
begin: /b?"/,
|
54
|
+
illegal: null,
|
55
|
+
}),
|
56
|
+
string,
|
57
|
+
number,
|
58
|
+
{
|
59
|
+
className: 'symbol',
|
60
|
+
begin: '#' + hljs.UNDERSCORE_IDENT_RE,
|
61
|
+
},
|
62
|
+
{
|
63
|
+
className: 'function',
|
64
|
+
beginKeywords: 'func',
|
65
|
+
end: '(\\(|<|=|{)',
|
66
|
+
excludeEnd: true,
|
67
|
+
contains: [hljs.UNDERSCORE_TITLE_MODE],
|
68
|
+
},
|
69
|
+
{
|
70
|
+
className: 'class',
|
71
|
+
begin: '\\b(actor( class)?|module|object)\\b',
|
72
|
+
keywords: 'actor class module object',
|
73
|
+
end: '(\\(|<|{)',
|
74
|
+
contains: [hljs.UNDERSCORE_TITLE_MODE],
|
75
|
+
illegal: '[\\w\\d]',
|
76
|
+
},
|
77
|
+
{
|
78
|
+
className: 'built_in',
|
79
|
+
beginKeywords: 'import type',
|
80
|
+
end: '(;|$|=)',
|
81
|
+
excludeEnd: true,
|
82
|
+
contains: [
|
83
|
+
hljs.QUOTE_STRING_MODE,
|
84
|
+
hljs.C_LINE_COMMENT_MODE,
|
85
|
+
hljs.COMMENT('/\\*', '\\*/', {
|
86
|
+
contains: ['self'],
|
87
|
+
}),
|
88
|
+
],
|
89
|
+
},
|
88
90
|
],
|
89
|
-
|
90
|
-
],
|
91
|
-
};
|
91
|
+
};
|
92
92
|
});
|
93
93
|
hljs.registerLanguage('candid', function (hljs) {
|
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
|
-
|
94
|
+
return {
|
95
|
+
name: 'Candid',
|
96
|
+
aliases: ['did'],
|
97
|
+
keywords: {
|
98
|
+
$pattern: '[a-zA-Z_]\\w*',
|
99
|
+
keyword: 'import service type',
|
100
|
+
built_in:
|
101
|
+
'opt vec record variant func blob principal' +
|
102
|
+
' nat nat8 nat16 nat32 nat64 int int8 int16 int32 int64' +
|
103
|
+
' float32 float64 bool text null reserved empty' +
|
104
|
+
' oneway query',
|
105
|
+
},
|
106
|
+
illegal: '</',
|
107
|
+
contains: [
|
108
|
+
hljs.C_LINE_COMMENT_MODE,
|
109
|
+
hljs.COMMENT('/\\*', '\\*/', {
|
110
|
+
contains: ['self'],
|
111
|
+
}),
|
112
|
+
hljs.inherit(hljs.QUOTE_STRING_MODE, {
|
113
|
+
begin: /b?"/,
|
114
|
+
illegal: null,
|
115
|
+
}),
|
116
|
+
string,
|
117
|
+
number,
|
118
|
+
],
|
119
|
+
};
|
120
120
|
});
|
121
|
-
|
122
|
-
|
121
|
+
};
|
package/contrib/monaco.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
// Monaco editor configuration
|
2
2
|
|
3
|
-
|
3
|
+
const MOTOKO_KEYWORDS = [
|
4
4
|
'actor',
|
5
5
|
'and',
|
6
6
|
'async',
|
@@ -46,7 +46,7 @@ export const MOTOKO_KEYWORDS = [
|
|
46
46
|
'ignore',
|
47
47
|
];
|
48
48
|
|
49
|
-
|
49
|
+
exports.configure = (monaco) => {
|
50
50
|
monaco.languages.register({ id: 'motoko' });
|
51
51
|
monaco.languages.setLanguageConfiguration('motoko', {
|
52
52
|
comments: {
|
package/index.js
ADDED
package/interpreter.js
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const mo = require('../..');
|
4
|
+
|
5
|
+
const actor = `
|
6
|
+
actor Main {
|
7
|
+
public func test() : async Nat {
|
8
|
+
123
|
9
|
+
}
|
10
|
+
}
|
11
|
+
`;
|
12
|
+
|
13
|
+
describe('virtual file system I/O', () => {
|
14
|
+
test('write -> read', () => {
|
15
|
+
const path = 'test__write_read__.txt';
|
16
|
+
const text = 'A\nB';
|
17
|
+
mo.write(path, text);
|
18
|
+
expect(mo.read(path)).toStrictEqual(text);
|
19
|
+
});
|
20
|
+
});
|
21
|
+
|
22
|
+
describe('check', () => {
|
23
|
+
test('works for a basic example', () => {
|
24
|
+
const path = 'test__check__.mo';
|
25
|
+
mo.write(path, actor);
|
26
|
+
expect(mo.check(path)).toStrictEqual([]);
|
27
|
+
});
|
28
|
+
});
|
29
|
+
|
30
|
+
describe('run', () => {
|
31
|
+
test('works for a basic example', () => {
|
32
|
+
const path = 'test__run__.mo';
|
33
|
+
mo.write(path, 'let x = 1 + 1; x');
|
34
|
+
expect(mo.run(path)).toStrictEqual({
|
35
|
+
result: 0,
|
36
|
+
stdout: '2 : Nat\n',
|
37
|
+
stderr: '',
|
38
|
+
});
|
39
|
+
});
|
40
|
+
});
|
@@ -0,0 +1,15 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const mo = require('../../interpreter');
|
4
|
+
|
5
|
+
describe('run', () => {
|
6
|
+
test('works for a basic example', () => {
|
7
|
+
const path = 'test__run__.mo';
|
8
|
+
mo.write(path, 'let x = 1 + 1; x');
|
9
|
+
expect(mo.run(path)).toStrictEqual({
|
10
|
+
result: 0,
|
11
|
+
stdout: '2 : Nat\n',
|
12
|
+
stderr: '',
|
13
|
+
});
|
14
|
+
});
|
15
|
+
});
|
package/lib/file.js
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
function getValidPath(path) {
|
4
|
+
if (typeof path !== 'string') {
|
5
|
+
throw new Error('File path must be a string');
|
6
|
+
}
|
7
|
+
if (path.startsWith('/')) {
|
8
|
+
path = path.slice(1);
|
9
|
+
}
|
10
|
+
if (path.endsWith('/')) {
|
11
|
+
path = path.slice(0, -1);
|
12
|
+
}
|
13
|
+
return path;
|
14
|
+
}
|
15
|
+
|
16
|
+
exports.file = (mo, path) => {
|
17
|
+
path = getValidPath(path);
|
18
|
+
const result = {
|
19
|
+
get path() {
|
20
|
+
return path;
|
21
|
+
},
|
22
|
+
// file(subPath) {
|
23
|
+
// subPath = getValidPath(subPath);
|
24
|
+
// return exports.file(`${path}/${subPath}`);
|
25
|
+
// },
|
26
|
+
clone() {
|
27
|
+
return exports.file(path);
|
28
|
+
},
|
29
|
+
read() {
|
30
|
+
return mo.read(path);
|
31
|
+
},
|
32
|
+
write(content) {
|
33
|
+
return mo.write(path, content);
|
34
|
+
},
|
35
|
+
rename(newPath) {
|
36
|
+
let result = mo.rename(path, newPath);
|
37
|
+
path = newPath;
|
38
|
+
return result;
|
39
|
+
},
|
40
|
+
delete() {
|
41
|
+
return mo.delete(path);
|
42
|
+
},
|
43
|
+
list() {
|
44
|
+
return mo.list(path);
|
45
|
+
},
|
46
|
+
check() {
|
47
|
+
return mo.check(path, ...args);
|
48
|
+
},
|
49
|
+
run() {
|
50
|
+
return mo.run(path);
|
51
|
+
},
|
52
|
+
candid() {
|
53
|
+
return mo.candid(path);
|
54
|
+
},
|
55
|
+
wasm(mode) {
|
56
|
+
return mo.wasm(path, mode);
|
57
|
+
},
|
58
|
+
parseMotoko() {
|
59
|
+
return mo.parseMotoko(result.read());
|
60
|
+
},
|
61
|
+
parseCandid() {
|
62
|
+
return mo.parseCandid(result.read());
|
63
|
+
},
|
64
|
+
};
|
65
|
+
return result;
|
66
|
+
};
|