@theqrl/hypc 0.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.
Files changed (63) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +361 -0
  3. package/abi.js +80 -0
  4. package/bindings/compile.js +157 -0
  5. package/bindings/core.js +116 -0
  6. package/bindings/helpers.js +35 -0
  7. package/bindings/index.js +16 -0
  8. package/build/clean.js +6 -0
  9. package/build/pack-publish-block.js +10 -0
  10. package/build/postbuild.js +3 -0
  11. package/common/helpers.js +24 -0
  12. package/common/types.js +2 -0
  13. package/contractA_hyp_A.bin +1 -0
  14. package/contractB_hyp_B.bin +1 -0
  15. package/downloadCurrentVersion.js +93 -0
  16. package/formatters.js +17 -0
  17. package/hypc.js +259 -0
  18. package/hypjson.js +1733 -0
  19. package/importA_hyp_C.bin +1 -0
  20. package/importB_hyp_D.bin +1 -0
  21. package/index.js +7 -0
  22. package/libX_hyp_X.bin +1 -0
  23. package/libY_hyp_Y.bin +1 -0
  24. package/libZ_hyp_Z.bin +1 -0
  25. package/linker.js +156 -0
  26. package/package.json +74 -0
  27. package/smtchecker.js +39 -0
  28. package/smtsolver.js +89 -0
  29. package/test/abi.js +77 -0
  30. package/test/cli.js +245 -0
  31. package/test/compiler.js +791 -0
  32. package/test/index.js +36 -0
  33. package/test/linker.js +132 -0
  34. package/test/resources/fixtureAsmJson.hyp +8 -0
  35. package/test/resources/fixtureAsmJson.json +528 -0
  36. package/test/resources/fixtureAsmJson.output +101 -0
  37. package/test/resources/fixtureIncorrectSource.hyp +1 -0
  38. package/test/resources/fixtureSmoke.hyp +5 -0
  39. package/test/resources/importA.hyp +7 -0
  40. package/test/resources/importB.hyp +5 -0
  41. package/test/resources/importCallback/base/contractA.hyp +8 -0
  42. package/test/resources/importCallback/base/contractB.hyp +6 -0
  43. package/test/resources/importCallback/contractC.hyp +4 -0
  44. package/test/resources/importCallback/includeA/libX.hyp +4 -0
  45. package/test/resources/importCallback/includeA/libY.hyp +6 -0
  46. package/test/resources/importCallback/includeA/utils.hyp +4 -0
  47. package/test/resources/importCallback/includeB/libZ.hyp +4 -0
  48. package/test/resources/smtChecker/loop.hyp +8 -0
  49. package/test/resources/smtChecker/smoke.hyp +5 -0
  50. package/test/resources/smtChecker/smoke_with_engine.hyp +6 -0
  51. package/test/resources/smtChecker/smoke_with_multi_engine.hyp +8 -0
  52. package/test/smtcallback.js +221 -0
  53. package/test/smtchecker.js +83 -0
  54. package/test/translate.js +83 -0
  55. package/test_resources_fixtureSmoke_hyp_C.abi +1 -0
  56. package/test_resources_fixtureSmoke_hyp_C.bin +1 -0
  57. package/test_resources_importA_hyp_C.bin +1 -0
  58. package/test_resources_importB_hyp_D.bin +1 -0
  59. package/translate.js +186 -0
  60. package/tsconfig.json +25 -0
  61. package/utils_hyp_Utils.bin +1 -0
  62. package/verifyVersion.js +43 -0
  63. package/wrapper.js +143 -0
package/LICENSE ADDED
File without changes
package/README.md ADDED
@@ -0,0 +1,361 @@
1
+ # hypc-js
2
+
3
+ JavaScript bindings for the [Hyperion compiler](https://github.com/theQRL/hyperion).
4
+
5
+ Uses the Emscripten compiled Hyperion found in the [hypc-bin repository](https://github.com/theQRL/hypc-bin).
6
+
7
+ ## Node.js Usage
8
+
9
+ To use the latest stable version of the Hyperion compiler via Node.js you can install it via npm:
10
+
11
+ ```bash
12
+ npm install @theqrl/hypc
13
+ ```
14
+
15
+ ### Usage on the Command-Line
16
+
17
+ If this package is installed globally (`npm install -g @theqrl/hypc`), a command-line tool called `hypcjs` will be available.
18
+
19
+ To see all the supported features, execute:
20
+
21
+ ```bash
22
+ hypcjs --help
23
+ ```
24
+
25
+ To compile a contract that imports other contracts via relative paths:
26
+ ```bash
27
+ hypcjs --bin --include-path node_modules/ --base-path . MainContract.hyp
28
+ ```
29
+ Use the ``--base-path`` and ``--include-path`` options to describe the layout of your project.
30
+ ``--base-path`` represents the root of your own source tree while ``--include-path`` allows you to
31
+ specify extra locations containing external code (e.g. libraries installed with a package manager).
32
+
33
+ Note: ensure that all the files you specify on the command line are located inside the base path or
34
+ one of the include paths.
35
+ The compiler refers to files from outside of these directories using absolute paths.
36
+ Having absolute paths in contract metadata will result in your bytecode being reproducible only
37
+ when it's placed in these exact absolute locations.
38
+
39
+ Note: this commandline interface is not compatible with `hypc` provided by the Hyperion compiler package and thus cannot be
40
+ used in combination with an Zond client via the `zond.compile.hyperion()` RPC method. Please refer to the
41
+ [Hyperion compiler documentation](https://theqrl.org/) for instructions to install `hypc`.
42
+ Furthermore, the commandline interface to hypc-js provides fewer features than the binary release.
43
+
44
+ ### Usage in Projects
45
+
46
+ There are two ways to use `hypc`:
47
+
48
+ 1. Through a high-level API giving a uniform interface to all compiler versions
49
+ 2. Through a low-level API giving access to all the compiler interfaces, which depend on the version of the compiler
50
+
51
+ #### High-level API
52
+
53
+ The high-level API consists of a single method, `compile`, which expects the [Compiler Standard Input and Output JSON](https://theqrl.org/).
54
+
55
+ It also accepts an optional set of callback functions, which include the ``import`` and the ``smtSolver`` callbacks.
56
+ Starting 0.6.0 it only accepts an object in place of the callback to supply the callbacks.
57
+
58
+ The ``import`` callback function is used to resolve unmet dependencies.
59
+ This callback receives a path and must synchronously return either an error or the content of the dependency
60
+ as a string. It cannot be used together with callback-based, asynchronous,
61
+ filesystem access. A workaround is to collect the names of dependencies, return
62
+ an error, and keep re-running the compiler until all of them are resolved.
63
+
64
+ #### Example usage without the import callback
65
+
66
+ Example:
67
+
68
+ ```javascript
69
+ var hypc = require('@theqrl/hypc');
70
+
71
+ var input = {
72
+ language: 'Hyperion',
73
+ sources: {
74
+ 'test.hyp': {
75
+ content: 'contract C { function f() public { } }'
76
+ }
77
+ },
78
+ settings: {
79
+ outputSelection: {
80
+ '*': {
81
+ '*': ['*']
82
+ }
83
+ }
84
+ }
85
+ };
86
+
87
+ var output = JSON.parse(hypc.compile(JSON.stringify(input)));
88
+
89
+ // `output` here contains the JSON output as specified in the documentation
90
+ for (var contractName in output.contracts['test.hyp']) {
91
+ console.log(
92
+ contractName +
93
+ ': ' +
94
+ output.contracts['test.hyp'][contractName].evm.bytecode.object
95
+ );
96
+ }
97
+ ```
98
+
99
+ #### Example usage with import callback
100
+
101
+ ```javascript
102
+ var hypc = require('@theqrl/hypc');
103
+
104
+ var input = {
105
+ language: 'Hyperion',
106
+ sources: {
107
+ 'test.hyp': {
108
+ content: 'import "lib.hyp"; contract C { function f() public { L.f(); } }'
109
+ }
110
+ },
111
+ settings: {
112
+ outputSelection: {
113
+ '*': {
114
+ '*': ['*']
115
+ }
116
+ }
117
+ }
118
+ };
119
+
120
+ function findImports(path) {
121
+ if (path === 'lib.hyp')
122
+ return {
123
+ contents:
124
+ 'library L { function f() internal returns (uint) { return 7; } }'
125
+ };
126
+ else return { error: 'File not found' };
127
+ }
128
+
129
+ // New syntax (supported from 0.5.12, mandatory from 0.6.0)
130
+ var output = JSON.parse(
131
+ hypc.compile(JSON.stringify(input), { import: findImports })
132
+ );
133
+
134
+ // `output` here contains the JSON output as specified in the documentation
135
+ for (var contractName in output.contracts['test.hyp']) {
136
+ console.log(
137
+ contractName +
138
+ ': ' +
139
+ output.contracts['test.hyp'][contractName].evm.bytecode.object
140
+ );
141
+ }
142
+ ```
143
+
144
+ Since version 0.5.1, the ``smtSolver`` callback function is used to solve SMT queries generated by
145
+ Hyperion's SMTChecker. If you have an SMT solver installed locally, it can
146
+ be used to solve the given queries, where the callback must synchronously
147
+ return either an error or the result from the solver. A default
148
+ ``smtSolver`` callback is included in this package via the module
149
+ ``smtchecker.js`` which exports the ``smtCallback`` function that takes 1) a
150
+ function that takes queries and returns the solving result, and 2) a solver
151
+ configuration object. The module ``smtsolver.js`` has a few predefined solver
152
+ configurations, and relies on Z3, Eldarica or cvc5 being installed locally. It
153
+ exports the list of locally found solvers and a function that invokes a given
154
+ solver.
155
+
156
+ The API of the SMT callback is **experimental** and can change at any time.
157
+ The last change was in version 0.8.11.
158
+
159
+ #### Example usage with smtSolver callback
160
+
161
+ ```javascript
162
+ var hypc = require('@theqrl/hypc');
163
+ const smtchecker = require('@theqrl/hypc/smtchecker');
164
+ const smtsolver = require('@theqrl/hypc/smtsolver');
165
+ // Note that this example only works via node and not in the browser.
166
+
167
+ var input = {
168
+ language: 'Hyperion',
169
+ sources: {
170
+ 'test.hyp': {
171
+ content: 'contract C { function f(uint x) public { assert(x > 0); } }'
172
+ }
173
+ },
174
+ settings: {
175
+ modelChecker: {
176
+ engine: "chc",
177
+ solvers: [ "smtlib2" ]
178
+ }
179
+ }
180
+ };
181
+
182
+ var output = JSON.parse(
183
+ hypc.compile(
184
+ JSON.stringify(input),
185
+ { smtSolver: smtchecker.smtCallback(smtsolver.smtSolver, smtsolver.availableSolvers[0]) }
186
+ )
187
+ );
188
+
189
+ ```
190
+ The assertion is clearly false, and an ``assertion failure`` warning
191
+ should be returned, together with a counterexample.
192
+
193
+ #### Low-level API
194
+
195
+ The low-level API is as follows:
196
+
197
+ - `hypc.lowlevel.compileSingle`: the original entry point, supports only a single file
198
+ - `hypc.lowlevel.compileMulti`: this supports multiple files, introduced in 0.1.6
199
+ - `hypc.lowlevel.compileCallback`: this supports callbacks, introduced in 0.2.1
200
+ - `hypc.lowlevel.compileStandard`: this works just like `compile` above, but is only present in compilers after (and including) 0.4.11
201
+
202
+ For examples how to use them, please refer to the README of the above mentioned hypc-js releases.
203
+
204
+ **Note**: These low-level functions remain available for compatibility reasons.
205
+ However, they were superseded by the `compile()` function and are no longer required.
206
+ Starting from version `0.5.0+commit.1d4f565a`, the functions `compileSingle`, `compileMulti`, and `compileCallback` are always `null` when using newer hypc binary versions.
207
+ It is recommended to use the latest release of hypc-js, but it should also handle all the older hypc binaries down to `0.1.x`.
208
+
209
+ ### Using with Electron
210
+
211
+ **Note:**
212
+ If you are using Electron, `nodeIntegration` is on for `BrowserWindow` by default. If it is on, Electron will provide a `require` method which will not behave as expected and this may cause calls, such as `require('@theqrl/hypc')`, to fail.
213
+
214
+ To turn off `nodeIntegration`, use the following:
215
+
216
+ ```javascript
217
+ new BrowserWindow({
218
+ webPreferences: {
219
+ nodeIntegration: false
220
+ }
221
+ });
222
+ ```
223
+
224
+ ### Using a Legacy Version
225
+
226
+ In order to compile contracts using a specific version of Hyperion, the `hypc.loadRemoteVersion(version, callback)` method is available. This returns a new `hypc` object that uses a version of the compiler specified.
227
+
228
+ You can also load the "binary" manually and use `setupMethods` to create the familiar wrapper functions described above:
229
+ `var hypc = hypc.setupMethods(require("/my/local/hypjson.js"))`.
230
+
231
+ ### Using the Latest Development Snapshot
232
+
233
+ By default, the npm version is only created for releases. This prevents people from deploying contracts with non-release versions because they are less stable and harder to verify. If you would like to use the latest development snapshot (at your own risk!), you may use the following example code.
234
+
235
+ ```javascript
236
+ var hypc = require('@theqrl/hypc');
237
+
238
+ // getting the development snapshot
239
+ hypc.loadRemoteVersion('latest', function(err, hypcSnapshot) {
240
+ if (err) {
241
+ // An error was encountered, display and quit
242
+ } else {
243
+ // NOTE: Use `hypcSnapshot` here with the same interface `hypc` has
244
+ // For example:
245
+ const output = hypcSnapshot.compile(/* ... */)
246
+ }
247
+ });
248
+ ```
249
+
250
+ The version **must** be in the long format.
251
+ Thus, if you would like to use version `v0.8.17` you need to include the commit hash of the release.
252
+ You can extract the long version string for each version from the [publicly available release list](https://binaries.theqrl.org/bin/list.json).
253
+
254
+ ```javascript
255
+ hypc.loadRemoteVersion('v0.8.17+commit.8df45f5f', function(err, hypcSnapshot) { /* ... */ });
256
+ ```
257
+
258
+ ### Linking Bytecode
259
+
260
+ When using libraries, the resulting bytecode will contain placeholders for the real addresses of the referenced libraries. These have to be updated, via a process called linking, before deploying the contract.
261
+
262
+ The `linker` module (`require('@theqrl/hypc/linker')`) offers helpers to accomplish this.
263
+
264
+ The `linkBytecode` method provides a simple helper for linking:
265
+
266
+ ```javascript
267
+ var linker = require('@theqrl/hypc/linker');
268
+
269
+ bytecode = linker.linkBytecode(bytecode, { MyLibrary: '0x123456...' });
270
+ ```
271
+
272
+ As of Hyperion 0.4.11 the compiler supports [standard JSON input and output](https://theqrl.org) which outputs a _link references_ map. This gives a map of library names to offsets in the bytecode to replace the addresses at. It also doesn't have the limitation on library file and contract name lengths.
273
+
274
+ There is a method available in the `linker` module called `findLinkReferences` which can find such link references in bytecode produced by an older compiler:
275
+
276
+ ```javascript
277
+ var linker = require('@theqrl/hypc/linker');
278
+
279
+ var linkReferences = linker.findLinkReferences(bytecode);
280
+ ```
281
+
282
+ ### Updating the ABI
283
+
284
+ The ABI generated by Hyperion versions can differ slightly, due to new features introduced. There is a tool included which aims to translate the ABI generated by an older Hyperion version to conform to the latest standard.
285
+
286
+ It can be used as:
287
+
288
+ ```javascript
289
+ var abi = require('@theqrl/hypc/abi');
290
+
291
+ var inputABI = [
292
+ {
293
+ constant: false,
294
+ inputs: [],
295
+ name: 'hello',
296
+ outputs: [{ name: '', type: 'string' }],
297
+ payable: false,
298
+ type: 'function'
299
+ }
300
+ ];
301
+ var outputABI = abi.update('0.3.6', inputABI);
302
+ // Output contains: [{"constant":false,"inputs":[],"name":"hello","outputs":[{"name":"","type":"string"}],"payable":true,"type":"function"},{"type":"fallback","payable":true}]
303
+ ```
304
+
305
+ ### Formatting old JSON assembly output
306
+
307
+ There is a helper available to format old JSON assembly output into a text familiar to earlier users of Remix IDE.
308
+
309
+ ```
310
+ var translate = require('@theqrl/hypc/translate')
311
+
312
+ // assemblyJSON refers to the JSON of the given assembly and sourceCode is the source of which the assembly was generated from
313
+ var output = translate.prettyPrintLegacyAssemblyJSON(assemblyJSON, sourceCode)
314
+ ```
315
+
316
+ ## Browser Usage
317
+
318
+ Compilation is generally a long-running and resource intensive task that cannot reasonably be performed in the main thread of the browser.
319
+ Some browsers even disallow synchronous compilation on the main thread if the module is larger than 4KB.
320
+ Thus, the only supported way to use `hypc` in a web browser is through a [web worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers).
321
+
322
+ ### Loading hypc with web workers
323
+
324
+ Web Workers allow you to run javascript in the background in the browser, letting the browser's main thread free to do whatever it needs to do.
325
+ Please, see the minimal example of how to use `hypc` with web workers below or check out this [repository](https://theqrl.org) for a full demo.
326
+
327
+ * index.html
328
+ ```html
329
+ <!DOCTYPE html>
330
+ <html>
331
+
332
+ <head>
333
+ <meta charset="utf-8" />
334
+ </head>
335
+
336
+ <body>
337
+ <script>
338
+ var worker = new Worker('./dist/bundle.js');
339
+ worker.addEventListener('message', function (e) {
340
+ console.log(e.data.version)
341
+ }, false);
342
+
343
+ worker.postMessage({})
344
+ </script>
345
+ </body>
346
+
347
+ </html>
348
+ ```
349
+
350
+ * worker.js:
351
+ ```javascript
352
+ importScripts('https://binaries.theqrl.org/bin/hypjson-v0.0.2+commit.3e18e55.js')
353
+ import wrapper from '@theqrl/hypc/wrapper';
354
+
355
+ self.addEventListener('message', () => {
356
+ const compiler = wrapper(self.Module)
357
+ self.postMessage({
358
+ version: compiler.version()
359
+ })
360
+ }, false)
361
+ ```
package/abi.js ADDED
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ const semver = __importStar(require("semver"));
26
+ function update(compilerVersion, abi) {
27
+ let hasConstructor = false;
28
+ let hasFallback = false;
29
+ for (let i = 0; i < abi.length; i++) {
30
+ const item = abi[i];
31
+ if (item.type === 'constructor') {
32
+ hasConstructor = true;
33
+ // <0.4.5 assumed every constructor to be payable
34
+ if (semver.lt(compilerVersion, '0.4.5')) {
35
+ item.payable = true;
36
+ }
37
+ }
38
+ else if (item.type === 'fallback') {
39
+ hasFallback = true;
40
+ }
41
+ if (item.type !== 'event') {
42
+ // add 'payable' to everything, except constant functions
43
+ if (!item.constant && semver.lt(compilerVersion, '0.4.0')) {
44
+ item.payable = true;
45
+ }
46
+ // add stateMutability field
47
+ if (semver.lt(compilerVersion, '0.4.16')) {
48
+ if (item.payable) {
49
+ item.stateMutability = 'payable';
50
+ }
51
+ else if (item.constant) {
52
+ item.stateMutability = 'view';
53
+ }
54
+ else {
55
+ item.stateMutability = 'nonpayable';
56
+ }
57
+ }
58
+ }
59
+ }
60
+ // 0.1.2 from Aug 2015 had it. The code has it since May 2015 (e7931ade)
61
+ if (!hasConstructor && semver.lt(compilerVersion, '0.1.2')) {
62
+ abi.push({
63
+ type: 'constructor',
64
+ payable: true,
65
+ stateMutability: 'payable',
66
+ inputs: []
67
+ });
68
+ }
69
+ if (!hasFallback && semver.lt(compilerVersion, '0.4.0')) {
70
+ abi.push({
71
+ type: 'fallback',
72
+ payable: true,
73
+ stateMutability: 'payable'
74
+ });
75
+ }
76
+ return abi;
77
+ }
78
+ module.exports = {
79
+ update
80
+ };
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setupCompile = void 0;
7
+ const assert_1 = __importDefault(require("assert"));
8
+ const helpers_1 = require("../common/helpers");
9
+ const helpers_2 = require("./helpers");
10
+ function setupCompile(hypJson, core) {
11
+ return {
12
+ compileJson: bindCompileJson(hypJson),
13
+ compileJsonCallback: bindCompileJsonCallback(hypJson, core),
14
+ compileJsonMulti: bindCompileJsonMulti(hypJson),
15
+ compileStandard: bindCompileStandard(hypJson, core)
16
+ };
17
+ }
18
+ exports.setupCompile = setupCompile;
19
+ /**********************
20
+ * COMPILE
21
+ **********************/
22
+ /**
23
+ * Returns a binding to the hyperion compileJSON method.
24
+ * input (text), optimize (bool) -> output (jsontext)
25
+ *
26
+ * @param hypJson The Emscripten compiled Hyperion object.
27
+ */
28
+ function bindCompileJson(hypJson) {
29
+ return (0, helpers_2.bindHypcMethod)(hypJson, 'compileJSON', 'string', ['string', 'number'], null);
30
+ }
31
+ /**
32
+ * Returns a binding to the hyperion compileJSONMulti method.
33
+ * input (jsontext), optimize (bool) -> output (jsontext)
34
+ *
35
+ * @param hypJson The Emscripten compiled Hyperion object.
36
+ */
37
+ function bindCompileJsonMulti(hypJson) {
38
+ return (0, helpers_2.bindHypcMethod)(hypJson, 'compileJSONMulti', 'string', ['string', 'number'], null);
39
+ }
40
+ /**
41
+ * Returns a binding to the hyperion compileJSONCallback method.
42
+ * input (jsontext), optimize (bool), callback (ptr) -> output (jsontext)
43
+ *
44
+ * @param hypJson The Emscripten compiled Hyperion object.
45
+ * @param coreBindings The core bound Hyperion methods.
46
+ */
47
+ function bindCompileJsonCallback(hypJson, coreBindings) {
48
+ const compileInternal = (0, helpers_2.bindHypcMethod)(hypJson, 'compileJSONCallback', 'string', ['string', 'number', 'number'], null);
49
+ if ((0, helpers_1.isNil)(compileInternal))
50
+ return null;
51
+ return function (input, optimize, readCallback) {
52
+ return runWithCallbacks(hypJson, coreBindings, readCallback, compileInternal, [input, optimize]);
53
+ };
54
+ }
55
+ /**
56
+ * Returns a binding to the hyperion hyperion_compile method with a fallback to
57
+ * compileStandard.
58
+ * input (jsontext), callback (optional >= v6 only - ptr) -> output (jsontext)
59
+ *
60
+ * @param hypJson The Emscripten compiled Hyperion object.
61
+ * @param coreBindings The core bound Hyperion methods.
62
+ */
63
+ function bindCompileStandard(hypJson, coreBindings) {
64
+ let boundFunctionStandard = null;
65
+ let boundFunctionHyperion = null;
66
+ // input (jsontext), callback (ptr) -> output (jsontext)
67
+ const compileInternal = (0, helpers_2.bindHypcMethod)(hypJson, 'compileStandard', 'string', ['string', 'number'], null);
68
+ // input (jsontext), callback (ptr), callback_context (ptr) -> output (jsontext)
69
+ boundFunctionHyperion = (0, helpers_2.bindHypcMethod)(hypJson, 'hyperion_compile', 'string', ['string', 'number', 'number'], null);
70
+ if (!(0, helpers_1.isNil)(compileInternal)) {
71
+ boundFunctionStandard = function (input, readCallback) {
72
+ return runWithCallbacks(hypJson, coreBindings, readCallback, compileInternal, [input]);
73
+ };
74
+ }
75
+ if (!(0, helpers_1.isNil)(boundFunctionHyperion)) {
76
+ boundFunctionStandard = function (input, callbacks) {
77
+ return runWithCallbacks(hypJson, coreBindings, callbacks, boundFunctionHyperion, [input]);
78
+ };
79
+ }
80
+ return boundFunctionStandard;
81
+ }
82
+ /**********************
83
+ * CALL BACKS
84
+ **********************/
85
+ function wrapCallbackWithKind(coreBindings, callback) {
86
+ (0, assert_1.default)(typeof callback === 'function', 'Invalid callback specified.');
87
+ return function (context, kind, data, contents, error) {
88
+ // Must be a null pointer.
89
+ (0, assert_1.default)(context === 0, 'Callback context must be null.');
90
+ const result = callback(coreBindings.copyFromCString(kind), coreBindings.copyFromCString(data));
91
+ if (typeof result.contents === 'string') {
92
+ coreBindings.copyToCString(result.contents, contents);
93
+ }
94
+ if (typeof result.error === 'string') {
95
+ coreBindings.copyToCString(result.error, error);
96
+ }
97
+ };
98
+ }
99
+ // calls compile() with args || cb
100
+ function runWithCallbacks(hypJson, coreBindings, callbacks, compile, args) {
101
+ if (callbacks) {
102
+ (0, assert_1.default)(typeof callbacks === 'object', 'Invalid callback object specified.');
103
+ }
104
+ else {
105
+ callbacks = {};
106
+ }
107
+ let readCallback = callbacks.import;
108
+ if (readCallback === undefined) {
109
+ readCallback = function (data) {
110
+ return {
111
+ error: 'File import callback not supported'
112
+ };
113
+ };
114
+ }
115
+ let singleCallback;
116
+ // After 0.6.x multiple kind of callbacks are supported.
117
+ let smtSolverCallback = callbacks.smtSolver;
118
+ if (smtSolverCallback === undefined) {
119
+ smtSolverCallback = function (data) {
120
+ return {
121
+ error: 'SMT solver callback not supported'
122
+ };
123
+ };
124
+ }
125
+ singleCallback = function (kind, data) {
126
+ if (kind === 'source') {
127
+ return readCallback(data);
128
+ }
129
+ else if (kind === 'smt-query') {
130
+ return smtSolverCallback(data);
131
+ }
132
+ else {
133
+ (0, assert_1.default)(false, 'Invalid callback kind specified.');
134
+ }
135
+ };
136
+ singleCallback = wrapCallbackWithKind(coreBindings, singleCallback);
137
+ const cb = coreBindings.addFunction(singleCallback, 'viiiii');
138
+ let output;
139
+ try {
140
+ args.push(cb);
141
+ // Callback context.
142
+ args.push(null);
143
+ output = compile(...args);
144
+ }
145
+ finally {
146
+ coreBindings.removeFunction(cb);
147
+ }
148
+ if (coreBindings.reset) {
149
+ // Explicitly free memory.
150
+ //
151
+ // NOTE: cwrap() of "compile" will copy the returned pointer into a
152
+ // Javascript string and it is not possible to call free() on it.
153
+ // reset() however will clear up all allocations.
154
+ coreBindings.reset();
155
+ }
156
+ return output;
157
+ }