motoko 1.0.1 → 2.0.2

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,121 @@
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 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: '</',
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,
82
+ contains: [
83
+ hljs.QUOTE_STRING_MODE,
84
+ hljs.C_LINE_COMMENT_MODE,
85
+ hljs.COMMENT('/\\*', '\\*/', {
86
+ contains: ['self'],
87
+ }),
88
+ ],
89
+ },
90
+ ],
91
+ };
92
+ });
93
+ hljs.registerLanguage('candid', function (hljs) {
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
+ });
121
+ };
@@ -0,0 +1,163 @@
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
+ ];
48
+
49
+ exports.configure = (monaco) => {
50
+ monaco.languages.register({ id: 'motoko' });
51
+ monaco.languages.setLanguageConfiguration('motoko', {
52
+ comments: {
53
+ lineComment: '//',
54
+ blockComment: ['/*', '*/'],
55
+ },
56
+ brackets: [
57
+ ['{', '}'],
58
+ ['[', ']'],
59
+ ['(', ')'],
60
+ ],
61
+ autoClosingPairs: [
62
+ { open: '{', close: '}' },
63
+ { open: '[', close: ']' },
64
+ { open: '(', close: ')' },
65
+ { open: '"', close: '"' },
66
+ { open: '<', close: '>' },
67
+ ],
68
+ });
69
+ monaco.languages.setMonarchTokensProvider('motoko', {
70
+ defaultToken: '',
71
+ tokenPostfix: '.mo',
72
+ // prettier-ignore
73
+ keywords: MOTOKO_KEYWORDS,
74
+ accessmodifiers: ['public', 'private', 'shared'],
75
+ // prettier-ignore
76
+ typeKeywords: [
77
+ 'Any', 'None', 'Null', 'Bool', 'Int', 'Int8', 'Int16', 'Int32', 'Int64', 'Nat',
78
+ 'Nat8', 'Nat16', 'Nat32', 'Nat64', 'Float',
79
+ 'Char', 'Text', 'Blob', 'Error', 'Principal',
80
+ ],
81
+ // prettier-ignore
82
+ operators: [
83
+ '=', '<', '>', ':', '<:', '?', '+', '-', '*', '/', '%', '**', '&', '|', '^', '<<', '>>',
84
+ '#', '==', '!=', '>=', '<=', ':=', '+=', '-=', '*=', '/=', '%=', '**=', '&=', '|=',
85
+ '^=', '<<=', '>>=', '#=', '->',
86
+ ],
87
+ symbols: /[=(){}[\].,:;@#_&\-<>`?!+*\\/]/,
88
+ // C# style strings
89
+ escapes:
90
+ /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
91
+ tokenizer: {
92
+ root: [
93
+ // identifiers and keywords
94
+ [
95
+ /[a-zA-Z_$][\w$]*/,
96
+ {
97
+ cases: {
98
+ '@typeKeywords': 'keyword.type',
99
+ '@keywords': 'keyword',
100
+ '@default': 'identifier',
101
+ },
102
+ },
103
+ ],
104
+ // whitespace
105
+ { include: '@whitespace' },
106
+
107
+ // delimiters and operators
108
+ [/[{}()[\]]/, '@brackets'],
109
+ [/[<>](?!@symbols)/, '@brackets'],
110
+ [
111
+ /@symbols/,
112
+ { cases: { '@operators': 'operator', '@default': '' } },
113
+ ],
114
+ // numbers
115
+ [/\d*\.\d+([eE][-+]?\d+)?/, 'number.float'],
116
+ [/0[xX][0-9a-fA-F_]+/, 'number.hex'],
117
+ [/[0-9_]+/, 'number'],
118
+
119
+ // delimiter: after number because of .\d floats
120
+ [/[;,.]/, 'delimiter'],
121
+
122
+ // strings
123
+ [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
124
+ [
125
+ /"/,
126
+ {
127
+ token: 'string.quote',
128
+ bracket: '@open',
129
+ next: '@string',
130
+ },
131
+ ],
132
+
133
+ // characters
134
+ [/'[^\\']'/, 'string'],
135
+ [/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
136
+ [/'/, 'string.invalid'],
137
+ ],
138
+
139
+ comment: [
140
+ [/[^/*]+/, 'comment'],
141
+ [/\/\*/, 'comment', '@push'], // nested comment
142
+ ['\\*/', 'comment', '@pop'],
143
+ [/[/*]/, 'comment'],
144
+ ],
145
+
146
+ string: [
147
+ [/[^\\"]+/, 'string'],
148
+ [/@escapes/, 'string.escape'],
149
+ [/\\./, 'string.escape.invalid'],
150
+ [
151
+ /"/,
152
+ { token: 'string.quote', bracket: '@close', next: '@pop' },
153
+ ],
154
+ ],
155
+
156
+ whitespace: [
157
+ [/[ \t\r\n]+/, 'white'],
158
+ [/\/\*/, 'comment', '@comment'],
159
+ [/\/\/.*$/, 'comment'],
160
+ ],
161
+ },
162
+ });
163
+ };
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
+ };