motoko 1.0.1 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
package/README.md ADDED
@@ -0,0 +1,191 @@
1
+ # Motoko
2
+
3
+ > ### Compile [Motoko](https://smartcontracts.org/) smart contracts in Node.js and the browser.
4
+
5
+ ---
6
+
7
+ ## Installation:
8
+
9
+ ```sh
10
+ npm i --save motoko
11
+ ```
12
+
13
+ ## Examples:
14
+
15
+ ### Basic usage
16
+
17
+ ```js
18
+ import mo from 'motoko';
19
+ // -- OR --
20
+ const mo = require('motoko');
21
+
22
+ // Create a Motoko script in a virtual file system
23
+ mo.write('Main.mo', `
24
+ actor {
25
+ public query func hello() : async Text {
26
+ "Hello, JavaScript!"
27
+ };
28
+ }
29
+ `);
30
+
31
+ // Generate the corresponding Candid interface
32
+ console.log(mo.candid('Main.mo'));
33
+ ```
34
+
35
+ ### Evaluate a program
36
+
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
+ ```
57
+
58
+ ### Load dependencies from GitHub
59
+
60
+ ```js
61
+ mo.clearPackages();
62
+ await mo.loadPackages({
63
+ base: 'dfinity/motoko-base/master/src', // import "mo:base/...";
64
+ });
65
+ ```
66
+
67
+ ### Generate parse trees
68
+
69
+ ```js
70
+ // Generate a Motoko AST
71
+ console.log(mo.parseMotoko('actor Main { public query func test() : async Nat { 123 } }'));
72
+
73
+ // Generate a Candid AST
74
+ console.log(mo.parseCandid('service : { test : () -> (nat) }'));
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
+ ```
@@ -0,0 +1,122 @@
1
+ // Highlight.js configuration
2
+
3
+ exports.configure = (hljs) => {
4
+ var string = {
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
+ };
15
+ var number = {
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
+ };
27
+ hljs.registerLanguage('motoko', function (hljs) {
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' +
39
+ ' assert ignore from_candid to_candid with',
40
+ literal: 'true false null',
41
+ built_in:
42
+ 'Any None Null Bool Int Int8 Int16 Int32 Int64' +
43
+ ' Nat Nat8 Nat16 Nat32 Nat64 Word8 Word16 Word32 Word64' +
44
+ ' Float Char Text Blob Error Principal' +
45
+ ' async',
46
+ },
47
+ illegal: '</',
48
+ contains: [
49
+ hljs.C_LINE_COMMENT_MODE,
50
+ hljs.COMMENT('/\\*', '\\*/', {
51
+ contains: ['self'],
52
+ }),
53
+ hljs.inherit(hljs.QUOTE_STRING_MODE, {
54
+ begin: /b?"/,
55
+ illegal: null,
56
+ }),
57
+ string,
58
+ number,
59
+ {
60
+ className: 'symbol',
61
+ begin: '#' + hljs.UNDERSCORE_IDENT_RE,
62
+ },
63
+ {
64
+ className: 'function',
65
+ beginKeywords: 'func',
66
+ end: '(\\(|<|=|{)',
67
+ excludeEnd: true,
68
+ contains: [hljs.UNDERSCORE_TITLE_MODE],
69
+ },
70
+ {
71
+ className: 'class',
72
+ begin: '\\b(actor( class)?|module|object)\\b',
73
+ keywords: 'actor class module object',
74
+ end: '(\\(|<|{)',
75
+ contains: [hljs.UNDERSCORE_TITLE_MODE],
76
+ illegal: '[\\w\\d]',
77
+ },
78
+ {
79
+ className: 'built_in',
80
+ beginKeywords: 'import type',
81
+ end: '(;|$|=)',
82
+ excludeEnd: true,
83
+ contains: [
84
+ hljs.QUOTE_STRING_MODE,
85
+ hljs.C_LINE_COMMENT_MODE,
86
+ hljs.COMMENT('/\\*', '\\*/', {
87
+ contains: ['self'],
88
+ }),
89
+ ],
90
+ },
91
+ ],
92
+ };
93
+ });
94
+ hljs.registerLanguage('candid', function (hljs) {
95
+ return {
96
+ name: 'Candid',
97
+ aliases: ['did'],
98
+ keywords: {
99
+ $pattern: '[a-zA-Z_]\\w*',
100
+ keyword: 'import service type',
101
+ built_in:
102
+ 'opt vec record variant func blob principal' +
103
+ ' nat nat8 nat16 nat32 nat64 int int8 int16 int32 int64' +
104
+ ' float32 float64 bool text null reserved empty' +
105
+ ' oneway query',
106
+ },
107
+ illegal: '</',
108
+ contains: [
109
+ hljs.C_LINE_COMMENT_MODE,
110
+ hljs.COMMENT('/\\*', '\\*/', {
111
+ contains: ['self'],
112
+ }),
113
+ hljs.inherit(hljs.QUOTE_STRING_MODE, {
114
+ begin: /b?"/,
115
+ illegal: null,
116
+ }),
117
+ string,
118
+ number,
119
+ ],
120
+ };
121
+ });
122
+ };
@@ -0,0 +1,164 @@
1
+ // Monaco editor configuration
2
+
3
+ const MOTOKO_KEYWORDS = [
4
+ 'actor',
5
+ 'and',
6
+ 'async',
7
+ 'assert',
8
+ 'await',
9
+ 'break',
10
+ 'case',
11
+ 'catch',
12
+ 'class',
13
+ 'continue',
14
+ 'debug',
15
+ 'else',
16
+ 'false',
17
+ 'for',
18
+ 'func',
19
+ 'if',
20
+ 'in',
21
+ 'import',
22
+ 'module',
23
+ 'not',
24
+ 'null',
25
+ 'object',
26
+ 'or',
27
+ 'label',
28
+ 'let',
29
+ 'loop',
30
+ 'private',
31
+ 'public',
32
+ 'return',
33
+ 'shared',
34
+ 'try',
35
+ 'throw',
36
+ 'debug_show',
37
+ 'query',
38
+ 'switch',
39
+ 'true',
40
+ 'type',
41
+ 'var',
42
+ 'while',
43
+ 'stable',
44
+ 'flexible',
45
+ 'system',
46
+ 'ignore',
47
+ 'with',
48
+ ];
49
+
50
+ exports.configure = (monaco) => {
51
+ monaco.languages.register({ id: 'motoko' });
52
+ monaco.languages.setLanguageConfiguration('motoko', {
53
+ comments: {
54
+ lineComment: '//',
55
+ blockComment: ['/*', '*/'],
56
+ },
57
+ brackets: [
58
+ ['{', '}'],
59
+ ['[', ']'],
60
+ ['(', ')'],
61
+ ],
62
+ autoClosingPairs: [
63
+ { open: '{', close: '}' },
64
+ { open: '[', close: ']' },
65
+ { open: '(', close: ')' },
66
+ { open: '"', close: '"' },
67
+ { open: '<', close: '>' },
68
+ ],
69
+ });
70
+ monaco.languages.setMonarchTokensProvider('motoko', {
71
+ defaultToken: '',
72
+ tokenPostfix: '.mo',
73
+ // prettier-ignore
74
+ keywords: MOTOKO_KEYWORDS,
75
+ accessmodifiers: ['public', 'private', 'shared'],
76
+ // prettier-ignore
77
+ typeKeywords: [
78
+ 'Any', 'None', 'Null', 'Bool', 'Int', 'Int8', 'Int16', 'Int32', 'Int64', 'Nat',
79
+ 'Nat8', 'Nat16', 'Nat32', 'Nat64', 'Float',
80
+ 'Char', 'Text', 'Blob', 'Error', 'Principal',
81
+ ],
82
+ // prettier-ignore
83
+ operators: [
84
+ '=', '<', '>', ':', '<:', '?', '+', '-', '*', '/', '%', '**', '&', '|', '^', '<<', '>>',
85
+ '#', '==', '!=', '>=', '<=', ':=', '+=', '-=', '*=', '/=', '%=', '**=', '&=', '|=',
86
+ '^=', '<<=', '>>=', '#=', '->',
87
+ ],
88
+ symbols: /[=(){}[\].,:;@#_&\-<>`?!+*\\/]/,
89
+ // C# style strings
90
+ escapes:
91
+ /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
92
+ tokenizer: {
93
+ root: [
94
+ // identifiers and keywords
95
+ [
96
+ /[a-zA-Z_$][\w$]*/,
97
+ {
98
+ cases: {
99
+ '@typeKeywords': 'keyword.type',
100
+ '@keywords': 'keyword',
101
+ '@default': 'identifier',
102
+ },
103
+ },
104
+ ],
105
+ // whitespace
106
+ { include: '@whitespace' },
107
+
108
+ // delimiters and operators
109
+ [/[{}()[\]]/, '@brackets'],
110
+ [/[<>](?!@symbols)/, '@brackets'],
111
+ [
112
+ /@symbols/,
113
+ { cases: { '@operators': 'operator', '@default': '' } },
114
+ ],
115
+ // numbers
116
+ [/\d*\.\d+([eE][-+]?\d+)?/, 'number.float'],
117
+ [/0[xX][0-9a-fA-F_]+/, 'number.hex'],
118
+ [/[0-9_]+/, 'number'],
119
+
120
+ // delimiter: after number because of .\d floats
121
+ [/[;,.]/, 'delimiter'],
122
+
123
+ // strings
124
+ [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
125
+ [
126
+ /"/,
127
+ {
128
+ token: 'string.quote',
129
+ bracket: '@open',
130
+ next: '@string',
131
+ },
132
+ ],
133
+
134
+ // characters
135
+ [/'[^\\']'/, 'string'],
136
+ [/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
137
+ [/'/, 'string.invalid'],
138
+ ],
139
+
140
+ comment: [
141
+ [/[^/*]+/, 'comment'],
142
+ [/\/\*/, 'comment', '@push'], // nested comment
143
+ ['\\*/', 'comment', '@pop'],
144
+ [/[/*]/, 'comment'],
145
+ ],
146
+
147
+ string: [
148
+ [/[^\\"]+/, 'string'],
149
+ [/@escapes/, 'string.escape'],
150
+ [/\\./, 'string.escape.invalid'],
151
+ [
152
+ /"/,
153
+ { token: 'string.quote', bracket: '@close', next: '@pop' },
154
+ ],
155
+ ],
156
+
157
+ whitespace: [
158
+ [/[ \t\r\n]+/, 'white'],
159
+ [/\/\*/, 'comment', '@comment'],
160
+ [/\/\/.*$/, 'comment'],
161
+ ],
162
+ },
163
+ });
164
+ };
package/index.js ADDED
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ module.exports = require('./lib')(
4
+ require('./versions/latest/moc.min').Motoko,
5
+ 'latest',
6
+ );
package/interpreter.js ADDED
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ module.exports = require('./lib')(
4
+ require('./versions/latest/moc.min').Motoko,
5
+ 'latest/interpreter',
6
+ );
@@ -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
+ };