diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index b3f7d01..9b3fdd5 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -29,7 +29,7 @@ jobs:
build:
strategy:
matrix:
- os: [windows-latest, ubuntu-latest, macos-latest]
+ os: [ubuntu-24.04, windows-2022, macos-13]
node: [16]
runs-on: ${{ matrix.os }}
steps:
@@ -37,6 +37,10 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin'
+ java-version: 21
- run: npm install
- run: npm install --force -g grunt-cli
- run: npm test
diff --git a/eo2js-runtime/package-lock.json b/eo2js-runtime/package-lock.json
index 9a56232..d745371 100644
--- a/eo2js-runtime/package-lock.json
+++ b/eo2js-runtime/package-lock.json
@@ -8,6 +8,9 @@
"name": "eo2js-runtime",
"version": "0.0.0",
"license": "MIT",
+ "dependencies": {
+ "colors": "1.4.0"
+ },
"devDependencies": {
"eslint": "9.6.0",
"eslint-config-google": "0.14.0",
@@ -501,10 +504,10 @@
"dev": true
},
"node_modules/colors": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
- "integrity": "sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==",
- "dev": true,
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+ "license": "MIT",
"engines": {
"node": ">=0.1.90"
}
@@ -1613,6 +1616,16 @@
"node": ">=10"
}
},
+ "node_modules/grunt-legacy-log/node_modules/colors": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
"node_modules/grunt-legacy-util": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.1.tgz",
diff --git a/eo2js-runtime/src/objects/org/eolang/cage$encaged$encage.js b/eo2js-runtime/src/objects/org/eolang/cage$encaged$encage.js
deleted file mode 100644
index eee0150..0000000
--- a/eo2js-runtime/src/objects/org/eolang/cage$encaged$encage.js
+++ /dev/null
@@ -1,26 +0,0 @@
-const object = require('../../../runtime/object')
-const {LAMBDA, RHO} = require('../../../runtime/attribute/specials');
-const at_void = require('../../../runtime/attribute/at-void');
-const cages = require('../../../runtime/cages');
-const dataized = require('../../../runtime/dataized');
-const {NUMBER} = require('../../../runtime/types');
-const data = require('../../../runtime/data')
-
-/**
- * Cage.encaged.encage.
- * @return {Object} - Cage.encaged.encage object
- */
-const cage$encaged$encage = function() {
- const obj = object('cage$encaged$encage')
- obj.attrs['object'] = at_void('object')
- obj.assets[LAMBDA] = function(self) {
- cages.encage(
- dataized(self.take(RHO).take('locator'), NUMBER),
- self.take('object')
- );
- return data.toObject(true)
- }
- return obj
-}
-
-module.exports = cage$encaged$encage
diff --git "a/eo2js-runtime/src/objects/org/eolang/cage$encaged$\317\206.js" "b/eo2js-runtime/src/objects/org/eolang/cage$encaged$\317\206.js"
deleted file mode 100644
index f1d9667..0000000
--- "a/eo2js-runtime/src/objects/org/eolang/cage$encaged$\317\206.js"
+++ /dev/null
@@ -1,21 +0,0 @@
-const object = require('../../../runtime/object')
-const {LAMBDA, RHO} = require('../../../runtime/attribute/specials');
-const dataized = require('../../../runtime/dataized');
-const {NUMBER} = require('../../../runtime/types');
-const {traced} = require('../../../runtime/traced');
-const cages = require('../../../runtime/cages');
-
-/**
- * Cage.encaged.φ.
- * @return {Object} - Cage.encaged.φ object
- */
-const cage$encaged$φ = function() {
- const obj = object('cage$encaged$φ')
- obj.assets[LAMBDA] = function(self) {
- const locator = dataized(self.take(RHO).take('locator'), NUMBER)
- return traced(cages.get(locator), locator)
- }
- return obj
-}
-
-module.exports = cage$encaged$φ
diff --git "a/eo2js-runtime/src/objects/org/eolang/cage$\317\206.js" "b/eo2js-runtime/src/objects/org/eolang/cage$\317\206.js"
deleted file mode 100644
index ea02f9f..0000000
--- "a/eo2js-runtime/src/objects/org/eolang/cage$\317\206.js"
+++ /dev/null
@@ -1,23 +0,0 @@
-const object = require('../../../runtime/object')
-const {LAMBDA, RHO} = require('../../../runtime/attribute/specials');
-const data = require('../../../runtime/data');
-const cages = require('../../../runtime/cages');
-
-/**
- * Cage.φ.
- * @return {Object} - Cage.φ object
- */
-const cage$φ = function() {
- const obj = object('cage$φ')
- obj.assets[LAMBDA] = function(self) {
- const rho = self.take(RHO)
- return rho.take('encaged').with({
- locator: data.toObject(
- cages.init(rho.take('object'))
- )
- })
- }
- return obj
-}
-
-module.exports = cage$φ
diff --git a/eo2js-runtime/src/objects/org/eolang/malloc$of$allocated$resize.js b/eo2js-runtime/src/objects/org/eolang/malloc$of$allocated$resized.js
similarity index 79%
rename from eo2js-runtime/src/objects/org/eolang/malloc$of$allocated$resize.js
rename to eo2js-runtime/src/objects/org/eolang/malloc$of$allocated$resized.js
index c3ef063..ac841c1 100644
--- a/eo2js-runtime/src/objects/org/eolang/malloc$of$allocated$resize.js
+++ b/eo2js-runtime/src/objects/org/eolang/malloc$of$allocated$resized.js
@@ -7,10 +7,10 @@ const dataized = require('../../../runtime/dataized');
const data = require('../../../runtime/data')
/**
- * Malloc.of.allocated.resize.
- * @return {Object} - Malloc.of.allocated.resize object
+ * Malloc.of.allocated.resized.
+ * @return {Object} - Malloc.of.allocated.resized object
*/
-const malloc$of$allocated$resize = function() {
+const malloc$of$allocated$resized = function() {
const obj = object('malloc$of$allocated$resize')
obj.attrs['size'] = at_void('size')
obj.assets[LAMBDA] = function(self) {
@@ -23,4 +23,4 @@ const malloc$of$allocated$resize = function() {
return obj
}
-module.exports = malloc$of$allocated$resize
+module.exports = malloc$of$allocated$resized
diff --git "a/eo2js-runtime/src/objects/org/eolang/malloc$of$\317\206.js" "b/eo2js-runtime/src/objects/org/eolang/malloc$of$\317\206.js"
index 0d30555..398bee2 100644
--- "a/eo2js-runtime/src/objects/org/eolang/malloc$of$\317\206.js"
+++ "b/eo2js-runtime/src/objects/org/eolang/malloc$of$\317\206.js"
@@ -18,14 +18,15 @@ const malloc$of$φ = function() {
)
let res;
try {
- dataized(
- rho.take('scope').with({
- 0: rho.take('allocated').with({
- id: data.toObject(identifier)
+ res = data.toObject(
+ dataized(
+ rho.take('scope').with({
+ 0: rho.take('allocated').with({
+ id: data.toObject(identifier)
+ })
})
- })
+ )
)
- res = data.toObject(heaps.read(identifier, 0, heaps.size(identifier)))
} finally {
heaps.free(identifier)
}
diff --git a/eo2js-runtime/src/objects/org/eolang/string$length.js b/eo2js-runtime/src/objects/org/eolang/string$length.js
deleted file mode 100644
index fa373e7..0000000
--- a/eo2js-runtime/src/objects/org/eolang/string$length.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const object = require('../../../runtime/object')
-const {LAMBDA, RHO} = require('../../../runtime/attribute/specials');
-const {STRING} = require('../../../runtime/types');
-const dataized = require('../../../runtime/dataized');
-const data = require('../../../runtime/data')
-
-/**
- * String.length.
- * @return {Object} - String.length object
- */
-const string$length = function() {
- const obj = object('string$length')
- obj.assets[LAMBDA] = function(self) {
- return data.toObject(
- dataized(self.take(RHO), STRING).length
- )
- }
- return obj
-}
-
-module.exports = string$length
diff --git a/eo2js-runtime/src/objects/org/eolang/string$slice.js b/eo2js-runtime/src/objects/org/eolang/string$slice.js
deleted file mode 100644
index b8ed9fd..0000000
--- a/eo2js-runtime/src/objects/org/eolang/string$slice.js
+++ /dev/null
@@ -1,44 +0,0 @@
-const object = require('../../../runtime/object')
-const {LAMBDA, RHO} = require('../../../runtime/attribute/specials');
-const at_void = require('../../../runtime/attribute/at-void');
-const dataized = require('../../../runtime/dataized');
-const {NUMBER, STRING} = require('../../../runtime/types');
-const data = require('../../../runtime/data')
-const ErFailure = require('../../../runtime/error/ErFailure');
-
-/**
- * String.slice.
- * @return {Object} - String.slice object
- */
-const string$slice = function() {
- const obj = object('string$slice')
- obj.attrs['start'] = at_void('start')
- obj.attrs['len'] = at_void('len')
- obj.assets[LAMBDA] = function(self) {
- const str = dataized(self.take(RHO), STRING)
- const start = dataized(self.take('start'), NUMBER)
- const length = dataized(self.take('len'), NUMBER)
- const end = length + start;
- if (start < 0) {
- throw new ErFailure(
- `Start index must be greater than 0 but was ${start}`,
- );
- }
- if (start > end) {
- throw new ErFailure(
- `End index must be greater or equal to start but was ${end} < ${start}`,
- );
- }
- if (end > str.length) {
- throw new ErFailure(
- `Start index + length must not exceed string length but was ${end} > ${str.length}`,
- );
- }
- return data.toObject(
- str.slice(Number(start), Number(end))
- )
- }
- return obj
-}
-
-module.exports = string$slice
diff --git a/eo2js-runtime/src/runtime/cages.js b/eo2js-runtime/src/runtime/cages.js
deleted file mode 100644
index 2473f26..0000000
--- a/eo2js-runtime/src/runtime/cages.js
+++ /dev/null
@@ -1,72 +0,0 @@
-const ErFailure = require('./error/ErFailure');
-
-/**
- * Encaged objects.
- * @type {{}}
- */
-const OBJECTS = {}
-
-/**
- * Locators generator.
- * @type {number}
- */
-let locator = 0
-
-/**
- * Cages for objects
- * @type {{
- * init: function(Object): number,
- * encage: function(Number, Object),
- * get: function(Number): Object
- * }}
- */
-const cages = {
- /**
- * Encage object for the first time.
- * New locator will be generated.
- * @param {Number} object
- * @return {number}
- */
- init: function(object) {
- const loc = ++locator
- if (!OBJECTS.hasOwnProperty(loc)) {
- OBJECTS[loc] = object
- }
- return loc
- },
- /**
- * Encage object to the storage by locator.
- * @param {Number} loc - Locator
- * @param {Object} object - Object
- */
- encage: function(loc, object) {
- if (!OBJECTS.hasOwnProperty(loc)) {
- throw new ErFailure(
- `Encaged object with locator ${loc} was not initialized, can't reencage, can't encage`
- )
- }
- const current = OBJECTS[loc].forma()
- const forma = object.forma()
- if (current !== forma) {
- throw new ErFailure(
- `Can't encage an object formed by ${forma} because object formed by ${current} was encaged before`
- )
- }
- OBJECTS[loc] = object
- },
- /**
- * Retrieve object from storage by locator
- * @param {Number} loc - Locator
- * @return {Object}
- */
- get: function(loc) {
- if (!OBJECTS.hasOwnProperty(loc)) {
- throw new ErFailure(
- `Object with locator ${loc} is absent in cage, can't get`
- )
- }
- return OBJECTS[loc]
- }
-}
-
-module.exports = cages
diff --git a/eo2js-runtime/test/objects/org/eolang/cage.test.js b/eo2js-runtime/test/objects/org/eolang/cage.test.js
deleted file mode 100644
index 99b8030..0000000
--- a/eo2js-runtime/test/objects/org/eolang/cage.test.js
+++ /dev/null
@@ -1,123 +0,0 @@
-const phi = require('../../../../temp/runtime/phi');
-const data = require('../../../../temp/runtime/data');
-const dataized = require('../../../../temp/runtime/dataized');
-const attr = require('../../../../temp/runtime/attribute/attr');
-const object = require('../../../../temp/runtime/object');
-const assert = require('assert');
-const {NUMBER} = require('../../../../src/runtime/types');
-const {LAMBDA} = require('../../../../src/runtime/attribute/specials');
-const {RECURSION_THRESHOLD} = require('../../../../src/runtime/traced');
-
-/**
- * Encaged object.
- * @param {Object} object - Object to encage
- * @return {Object} - Cage
- */
-const encaged = function(object) {
- return phi.take('org.eolang.cage').with({
- 0: object
- }).take('new')
-}
-
-/**
- * Encage given object to given cage.
- * @param {Object} cage - Cage
- * @param {Object} obj - Object to encage
- */
-const encageTo = function(cage, obj) {
- dataized(cage.take('encage').with({
- 0: obj
- }))
-}
-
-/**
- * Dummy object.
- * @param {Number} num
- * @return {Object} - Dummy object
- */
-const dummy = function(num) {
- const obj = object('dummy')
- obj.attrs['x'] = attr.simple(data.toObject(num))
- return obj
-}
-
-/**
- * Recursive dummy.
- * @param {Object} cage - Cage
- * @param {Number} depth - Depth
- * @return {Object} - Recursive dummy
- */
-const recursiveDummy = function(cage, depth) {
- let counter = 0
- const obj = object('dummy')
- obj.assets[LAMBDA] = function(_) {
- if (++counter >= depth) {
- return data.toObject(1)
- } else {
- return cage
- }
- }
- return obj
-}
-
-describe('cage', function() {
- it('should encage via application', function() {
- const cage = encaged(data.toObject(1))
- assert.equal(dataized(cage, NUMBER), 1)
- })
- it('should encage and reencage', function() {
- const cage = encaged(data.toObject(1))
- encageTo(cage, data.toObject(2))
- assert.equal(dataized(cage, NUMBER), 2)
- })
- it('should overwrite caged object', function() {
- const cage = encaged(dummy(1))
- assert.equal(dataized(cage.take('x'), NUMBER), 1)
- encageTo(cage, dummy(2))
- assert.equal(dataized(cage.take('x'), NUMBER), 2)
- })
- it('should encage object on copying', function() {
- const first = encaged(data.toObject(1))
- const second = first.copy()
- encageTo(second, data.toObject(2))
- assert.equal(dataized(first, NUMBER), 2)
- })
- it('should write and rewrite primitive', function() {
- const cage = encaged(data.toObject(1))
- assert.equal(dataized(cage, NUMBER), 1)
- encageTo(cage, data.toObject(5))
- assert.equal(dataized(cage, NUMBER), 5)
- })
- it('should no write primitive formed differently', function() {
- const cage = encaged(data.toObject(1))
- assert.throws(() => encageTo(cage, data.toObject('Hello, world!')))
- })
- it('should not write bounded method', function() {
- const five = data.toObject(5)
- const ten = five.take('plus').with({
- 0: data.toObject(5)
- })
- const cage = encaged(five)
- assert.throws(() => encageTo(cage, ten))
- })
- it('should throw error on recursion', function() {
- const cage = encaged(phi.take('org.eolang.cage').take('encaged'))
- encageTo(cage, cage)
- assert.throws(() => dataized(cage))
- })
- it('should not throw an error on small depth', function() {
- const cage = encaged(recursiveDummy(object(), 1))
- encageTo(cage, recursiveDummy(cage, RECURSION_THRESHOLD / 2))
- assert.doesNotThrow(() => dataized(cage))
- })
- it('should not throw on max depth', function() {
- const cage = encaged(recursiveDummy(object(), 1))
- encageTo(cage, recursiveDummy(cage, RECURSION_THRESHOLD))
- assert.doesNotThrow(() => dataized(cage))
- })
- it('should throw an error on big depth', function() {
- const cage = encaged(recursiveDummy(object(), 1))
- encageTo(cage, recursiveDummy(cage, RECURSION_THRESHOLD + 1))
- assert.throws(() => dataized(cage))
- })
-})
diff --git a/eo2js-runtime/test/runtime/cages.test.js b/eo2js-runtime/test/runtime/cages.test.js
deleted file mode 100644
index 9cecacb..0000000
--- a/eo2js-runtime/test/runtime/cages.test.js
+++ /dev/null
@@ -1,31 +0,0 @@
-const cages = require('../../temp/runtime/cages');
-const object = require('../../temp/runtime/object');
-const assert = require('assert');
-
-describe('cages', function() {
- it('should initialize object for the first time', function() {
- assert.doesNotThrow(() => cages.init(object()))
- })
- it('should encage object with locator', function() {
- const first = object()
- const second = object()
- const locator = cages.init(first)
- cages.encage(locator, second)
- assert.equal(cages.get(locator).toString(), second.toString())
- })
- it('should fail to encage object if it was not initialized', function() {
- assert.throws(() => cages.encage(0, object()))
- })
- it('should fail to encage object of different forma', function() {
- const locator = cages.init(object('first'))
- assert.throws(() => cages.encage(locator, object('second')))
- })
- it('should fail to get object if it was not initialized', function() {
- assert.throws(() => cages.get(0))
- })
- it('should get object by right locator', function() {
- const first = cages.init(object('first'))
- cages.init(object('second'))
- assert.ok(cages.get(first).toString().includes('first'))
- })
-})
diff --git a/eo2js/package-lock.json b/eo2js/package-lock.json
index 01bab80..94f29af 100644
--- a/eo2js/package-lock.json
+++ b/eo2js/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.0.0",
"license": "MIT",
"dependencies": {
+ "colors": "1.4.0",
"commander": "^12.0.0",
"fast-xml-parser": "^4.3.5",
"saxon-js": "^2.6.0"
@@ -545,6 +546,15 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
+ "node_modules/colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
diff --git a/eo2js/package.json b/eo2js/package.json
index 9f1e3e3..824342d 100644
--- a/eo2js/package.json
+++ b/eo2js/package.json
@@ -20,7 +20,8 @@
"dependencies": {
"commander": "^12.0.0",
"fast-xml-parser": "^4.3.5",
- "saxon-js": "^2.6.0"
+ "saxon-js": "^2.6.0",
+ "colors": "1.4.0"
},
"devDependencies": {
"grunt": "^1.6.1",
diff --git a/eo2js/src/commands/transpile.js b/eo2js/src/commands/transpile.js
index 83b790b..bb66261 100644
--- a/eo2js/src/commands/transpile.js
+++ b/eo2js/src/commands/transpile.js
@@ -46,12 +46,15 @@ const makeDirIfNotExist = function(dir) {
* @return {boolean} - If given XMIR has tests meta or not
*/
const hasMeta = function(xmir, name) {
- const metas = xmir.program.metas.meta
+ const metas = xmir.program.metas
let res = false
- if (Array.isArray(metas)) {
- res = metas.findIndex((meta) => meta.head === name) !== -1
- } else if (typeof metas === 'object' && metas.hasOwnProperty('head')) {
- res = metas.head === name
+ if (metas != null) {
+ const metas = xmir.program.metas.meta
+ if (Array.isArray(metas)) {
+ res = metas.findIndex((meta) => meta.head === name) !== -1
+ } else if (typeof metas === 'object' && metas.hasOwnProperty('head')) {
+ res = metas.head === name
+ }
}
return res
}
diff --git a/eo2js/src/compile-stylesheets.js b/eo2js/src/compile-stylesheets.js
index 692eb0a..5a6142d 100644
--- a/eo2js/src/compile-stylesheets.js
+++ b/eo2js/src/compile-stylesheets.js
@@ -4,7 +4,7 @@ const {execSync} = require('child_process');
const xsls = path.resolve('src/resources/xsl')
const jsons = path.resolve('src/resources/json')
-const all = ['attrs', 'data', 'objects', 'package', 'to-js', 'tests']
+const all = ['_funcs', 'attrs', 'data', 'objects', 'package', 'to-js', 'tests']
const ext = '.sef.json'
/**
diff --git a/eo2js/src/resources/xsl/_funcs.xsl b/eo2js/src/resources/xsl/_funcs.xsl
new file mode 100644
index 0000000..026ac67
--- /dev/null
+++ b/eo2js/src/resources/xsl/_funcs.xsl
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
diff --git a/eo2js/src/resources/xsl/data.xsl b/eo2js/src/resources/xsl/data.xsl
index 763ace7..c201d73 100644
--- a/eo2js/src/resources/xsl/data.xsl
+++ b/eo2js/src/resources/xsl/data.xsl
@@ -22,28 +22,27 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-->
-
+
+
-
+
-
-
+
+
-
-
- [
-
-
- ,
-
- '0x
-
- '
-
- ]
-
-
+ [
+
+
+
+ ,
+
+ '0x
+
+ '
+
+
+ ]
diff --git a/eo2js/src/resources/xsl/to-js.xsl b/eo2js/src/resources/xsl/to-js.xsl
index b34a5b5..e8c2d38 100644
--- a/eo2js/src/resources/xsl/to-js.xsl
+++ b/eo2js/src/resources/xsl/to-js.xsl
@@ -395,6 +395,7 @@ SOFTWARE.
+ .copy()
rho
@@ -577,14 +578,18 @@ SOFTWARE.
- =
+ = applied(
- .with({
+ , {
+ 0: object().with({
+
'
':
+
+ })
})
diff --git a/eo2js/test/commands/transpile.test.js b/eo2js/test/commands/transpile.test.js
index 5dc1ce2..f3acfdd 100644
--- a/eo2js/test/commands/transpile.test.js
+++ b/eo2js/test/commands/transpile.test.js
@@ -12,14 +12,14 @@ const compileStylesheets = require('../../src/compile-stylesheets');
* Don't forget to clear the array before push!
* @type {string[]}
*/
-const only = ['prepares-data']
+const only = []
const home = path.resolve('temp/test-transpile')
describe('transpile', function() {
before('compile stylesheets', function() {
compileStylesheets()
fs.rmSync(home, {recursive: true, force: true})
- fs.mkdirSync(home)
+ fs.mkdirSync(home, {recursive: true})
})
describe('command', function() {
const target = path.resolve(home, 'target')
@@ -27,53 +27,39 @@ describe('transpile', function() {
fs.rmSync(target, {recursive: true, force: true})
fs.mkdirSync(target)
})
- it('should fail if eo-foreign is not found', function() {
- assert.throws(() => runSync(['transpile', '-t', target], false))
- })
- it('should fail if eo-foreign file is not .json', function() {
- const foreign = 'eo-foreign.csv'
- fs.writeFileSync(path.resolve(target, foreign), 'some data')
- assert.throws(() => runSync(['transpile', '-t', target, '-f', foreign], false))
- })
- /**
- * Prepare files for transpilation.
- * Creates eo-foreign.json file and copies XMIR file from test resources.
- * @param {String} name - Name of the object to transpile, defaults to 'simple'
- */
- const prepare = function(name = 'simple') {
- const verified = path.resolve(target, `6-verify/com/eo2js/${name}.xmir`)
- const foreign = [{
- id: `com.eo2js.${name}`,
- verified: verified
- }]
- fs.writeFileSync(path.resolve(target, 'eo-foreign.json'), JSON.stringify(foreign))
- fs.mkdirSync(path.resolve(target, '6-verify/com/eo2js'), {recursive: true})
- fs.copyFileSync(path.resolve(`test/resources/transpile/${name}.xmir`), verified)
- }
+ /* eslint-disable valid-jsdoc */
/**
* Run transpile command with verbose output.
- * @param {String} name - Name of the object to transpile, defaults to 'simple'
- * @return {String} - Command stdout from transpilation
- */
- const transpile = function(name = 'simple') {
- prepare(name)
- return runSync([
- 'transpile',
- '--verbose',
- '-t', target,
- ])
- }
- /**
- * Run transpile command again with verbose output, without preparing files.
- * @return {String} - Command stdout from retranspilation
+ * @param {{[name]: String, [prepare]: Boolean}} opts - Options
+ * @return {String} - Output
*/
- const retranspile = function() {
+ const transpile = function(opts= {}) {
+ opts.name = opts.name || 'simple'
+ opts.prepare = opts.prepare !== undefined ? opts.prepare : true
+ if (opts.prepare) {
+ const verified = path.resolve(target, `6-verify/com/eo2js/${opts.name}.xmir`)
+ const foreign = [{
+ id: `com.eo2js.${opts.name}`,
+ verified: verified
+ }]
+ fs.writeFileSync(path.resolve(target, 'eo-foreign.json'), JSON.stringify(foreign))
+ fs.mkdirSync(path.resolve(target, '6-verify/com/eo2js'), {recursive: true})
+ fs.copyFileSync(path.resolve(`test/resources/transpile/${opts.name}.xmir`), verified)
+ }
return runSync([
'transpile',
'--verbose',
'-t', target,
])
}
+ it('should fail if eo-foreign is not found', function() {
+ assert.throws(() => runSync(['transpile', '-t', target], false))
+ })
+ it('should fail if eo-foreign file is not .json', function() {
+ const foreign = 'eo-foreign.csv'
+ fs.writeFileSync(path.resolve(target, foreign), 'some data')
+ assert.throws(() => runSync(['transpile', '-t', target, '-f', foreign], false))
+ })
it('should create transpiled XMIRs', function() {
const traspiled = '8-transpile/com/eo2js/simple.xmir'
assertFilesExist(transpile(), target, [traspiled])
@@ -84,14 +70,14 @@ describe('transpile', function() {
});
['simple-test', 'alone-test'].forEach((name) => {
it(`should generate test JS file for ${name}`, function() {
- assertFilesExist(transpile(name), target, [`project/com/eo2js/${name}.test.js`])
+ assertFilesExist(transpile({name}), target, [`project/com/eo2js/${name}.test.js`])
})
})
it('should skip transpilation if source was not modified', function() {
transpile()
const transpiled = path.resolve(target, '8-transpile/com/eo2js/simple.xmir')
const first = fs.statSync(transpiled).mtime
- retranspile()
+ transpile({prepare: false})
const second = fs.statSync(transpiled).mtime
assert.equal(first.getTime(), second.getTime())
})
@@ -102,7 +88,7 @@ describe('transpile', function() {
const first = fs.statSync(transpiled).mtime
await new Promise((resolve) => setTimeout(resolve, 1000))
fs.writeFileSync(source, fs.readFileSync(source))
- retranspile()
+ transpile({prepare: false})
const second = fs.statSync(transpiled).mtime
assert.notEqual(first.getTime(), second.getTime())
})
@@ -119,17 +105,18 @@ describe('transpile', function() {
fs.rmSync(folder, {recursive: true})
}
const json = JSON.parse(fs.readFileSync(path.resolve(packs, test)).toString())
- const res = pack({home: folder, sources: 'src', target: 'target', json})
- if (res.skip) {
- this.skip()
- } else {
- assert.equal(
- res.failures.length,
- 0,
- `Result XMIR:\n ${res.xmir}\nJSON: ${JSON.stringify(res.json, null, 2)}\nFailed tests: ${res.failures.join(';\n')}`
- )
- done()
- }
+ pack({home: folder, sources: 'src', target: 'target', json}).then((res) => {
+ if (res.skip) {
+ this.skip()
+ } else {
+ assert.equal(
+ res.failures.length,
+ 0,
+ `Result XMIR:\n ${res.xmir}\nJSON: ${JSON.stringify(res.json, null, 2)}\nFailed tests: ${res.failures.join(';\n')}`
+ )
+ done()
+ }
+ })
})
})
})
diff --git a/eo2js/test/helpers.js b/eo2js/test/helpers.js
index e78da5c..95e1d5d 100644
--- a/eo2js/test/helpers.js
+++ b/eo2js/test/helpers.js
@@ -68,9 +68,9 @@ const parser = new XMLParser({ignoreAttributes: false})
/**
* Transformations test pack.
* @param {{home: String, sources: String, target: String, json: Object}} params - Pack params
- * @return {{skip: boolean, failures: array., xmir: String, json: Object}} - Output
+ * @return {Promise<{skip: boolean, failures: array., xmir: String, json: Object}>}
*/
-const pack = function(params) {
+const pack = async function(params) {
const res = {
skip: false,
failures: [],
@@ -78,60 +78,64 @@ const pack = function(params) {
json: ''
}
if (params.json['skip'] || !params.json['xsls'] || params.json['xsls'].length === 0) {
- res.skip = true
+ return new Promise((resolve) => {
+ res.skip = true
+ resolve(res)
+ })
} else {
const sources = path.resolve(params.home, params.sources)
const target = path.resolve(params.home, params.target)
fs.mkdirSync(sources, {recursive: true})
fs.mkdirSync(target, {recursive: true})
fs.writeFileSync(path.resolve(sources, `test.eo`), `${params.json['eo'].join('\n')}\n`)
- mvnw(['register', 'parse', 'optimize', 'shake'], params)
- const shaken = JSON.parse(
- fs.readFileSync(path.resolve(target, 'eo-foreign.json')).toString()
- )[0]['shaken']
- let xml = fs.readFileSync(shaken).toString()
- const transformations = path.resolve(__dirname, '../src/resources/json')
- params.json['xsls']
- .map((name) => path.resolve(transformations, `${name}.sef.json`))
- .forEach((transformation) => {
- xml = saxon.transform({
- stylesheetFileName: transformation,
- sourceText: xml,
- destination: 'serialized'
- }).principalResult
- })
- res.xmir = xml
- const saved = path.resolve(target, '3-transpiled')
- fs.mkdirSync(saved, {recursive: true})
- fs.writeFileSync(path.resolve(saved, 'test.xmir'), res.xmir)
- xml = parser.parse(xml, {})
- res.json = xml
- params.json['tests'].forEach((test) => {
- if (typeof test === 'object') {
- const node = test.node
- const method = test.method
- const args = test.args
- const applied = jp.apply(node, xml)
- if (applied.length === 0) {
- res.failures.push(node)
+ return mvnw(['register', 'parse', 'optimize', 'shake'], params).then((r) => {
+ const shaken = JSON.parse(
+ fs.readFileSync(path.resolve(target, 'eo-foreign.json')).toString()
+ )[0]['shaken']
+ let xml = fs.readFileSync(shaken).toString()
+ const transformations = path.resolve(__dirname, '../src/resources/json')
+ params.json['xsls']
+ .map((name) => path.resolve(transformations, `${name}.sef.json`))
+ .forEach((transformation) => {
+ xml = saxon.transform({
+ stylesheetFileName: transformation,
+ sourceText: xml,
+ destination: 'serialized'
+ }).principalResult
+ })
+ res.xmir = xml
+ const saved = path.resolve(target, '3-transpiled')
+ fs.mkdirSync(saved, {recursive: true})
+ fs.writeFileSync(path.resolve(saved, 'test.xmir'), res.xmir)
+ xml = parser.parse(xml, {})
+ res.json = xml
+ params.json['tests'].forEach((test) => {
+ if (typeof test === 'object') {
+ const node = test.node
+ const method = test.method
+ const args = test.args
+ const applied = jp.apply(node, xml)
+ if (applied.length === 0) {
+ res.failures.push(node)
+ } else {
+ args.forEach((arg) => {
+ if (Array.isArray(arg)) {
+ arg = arg.join('\n')
+ }
+ if (!applied[0][method](arg)) {
+ res.failures.push(`NODE: ${node}, METHOD: ${method}, ARG: ${arg}`)
+ }
+ })
+ }
} else {
- args.forEach((arg) => {
- if (Array.isArray(arg)) {
- arg = arg.join('\n')
- }
- if (!applied[0][method](arg)) {
- res.failures.push(`NODE: ${node}, METHOD: ${method}, ARG: ${arg}`)
- }
- })
- }
- } else {
- if (jp.apply(test, xml).length === 0) {
- res.failures.push(test)
+ if (jp.apply(test, xml).length === 0) {
+ res.failures.push(test)
+ }
}
- }
+ })
+ return res
})
}
- return res
}
/**
diff --git a/eo2js/test/it/runtime-tests.test.js b/eo2js/test/it/runtime-tests.test.js
index c2b57ee..58f4d8d 100644
--- a/eo2js/test/it/runtime-tests.test.js
+++ b/eo2js/test/it/runtime-tests.test.js
@@ -1,9 +1,9 @@
-const path = require('path');
-const fs = require('fs');
-const mvnw = require('../mvnw/mvnw.js');
+const path = require('path')
+const fs = require('fs')
+const mvnw = require('../mvnw/mvnw.js')
const {execSync} = require('child_process')
-const {runSync} = require('../helpers');
-const assert = require('assert');
+const {runSync} = require('../helpers')
+const assert = require('assert')
/**
* Excluded tests.
@@ -38,7 +38,7 @@ const exclude = [
* @return {Array.} - Files from the directory
*/
const allFilesFrom = function(dir) {
- const files = fs.readdirSync(dir, {withFileTypes: true});
+ const files = fs.readdirSync(dir, {withFileTypes: true})
const res = []
for (const file of files) {
if (file.isDirectory()) {
@@ -63,19 +63,15 @@ const COMPILE = true
* eo-maven-plugin, transpiles and executes using eo2js.
*/
describe('runtime tests', function() {
+ this.timeout(0)
const home = path.resolve('temp/runtime-tests')
const target = path.resolve(home, 'target')
const project = path.resolve(target, 'project')
const runtime = path.resolve('../eo2js-runtime')
- before('prepare environment', function() {
+ before('prepare environment', async function() {
if (COMPILE) {
fs.rmSync(home, {recursive: true, force: true})
fs.mkdirSync(project, {recursive: true})
- }
- })
- it('should execute all eo-runtime tests', function(done) {
- this.timeout(0)
- if (COMPILE) {
execSync([
'git init',
'git remote add origin https://github.com/objectionary/home.git',
@@ -89,11 +85,13 @@ describe('runtime tests', function() {
.join('\n')
}`)
console.debug(`\nExcluded:\n${exclude.map((pth) => `- ${pth}`).join('\n')}`)
- mvnw(
- ['register', 'assemble', 'verify'],
- {home, sources: 'tests', target: 'target'}
- )
+ const opts = {home, sources: 'tests', target: 'target'}
+ await mvnw('register', opts)
+ await mvnw('assemble', opts)
+ await mvnw('verify', opts)
}
+ })
+ it('should execute all eo-runtime tests', function(done) {
if (!COMPILE) {
runSync(['link -t', target, '-p project --tests --alone -d', runtime])
}
diff --git a/eo2js/test/it/simple.test.js b/eo2js/test/it/simple.test.js
index 39a2fe3..dadc6bb 100644
--- a/eo2js/test/it/simple.test.js
+++ b/eo2js/test/it/simple.test.js
@@ -5,13 +5,25 @@ const {runSync} = require('../helpers');
const compileStylesheets = require('../../src/compile-stylesheets');
const assert = require('assert');
+/**
+ * Prepare sources.
+ * @param {String} home - Home directory
+ * @return {Promise|String>} - Maven promise
+ */
+const prepare = function(home) {
+ return mvnw(
+ ['register', 'assemble', 'verify'],
+ {home, sources: 'src/eo', target: 'target'}
+ )
+}
+
describe('integration test', function() {
const home = path.resolve('temp/it-test')
const target = path.resolve(home, 'target')
const project = path.resolve(target, 'project')
const runtime = path.resolve('../eo2js-runtime')
this.timeout(1000000)
- before('recompile stylesheets', function() {
+ before('recompile stylesheets', async function() {
compileStylesheets()
fs.rmSync(home, {recursive: true, force: true})
fs.mkdirSync(project, {recursive: true})
@@ -20,10 +32,7 @@ describe('integration test', function() {
path.resolve(home, 'src/eo'),
{recursive: true}
)
- mvnw(
- ['register', 'assemble', 'verify'],
- {home, sources: 'src/eo', target: 'target'}
- )
+ await prepare(home)
})
it('should execute simple unit test', function(done) {
const log = runSync(['test', '-t', target, '-p project -d', runtime])
diff --git a/eo2js/test/mvnw/eo-version.txt b/eo2js/test/mvnw/eo-version.txt
index d0a1915..a8ab6c9 100644
--- a/eo2js/test/mvnw/eo-version.txt
+++ b/eo2js/test/mvnw/eo-version.txt
@@ -1 +1 @@
-0.40.1
+0.44.0
diff --git a/eo2js/test/mvnw/mvnw.js b/eo2js/test/mvnw/mvnw.js
index 2bf38a0..c2c237e 100644
--- a/eo2js/test/mvnw/mvnw.js
+++ b/eo2js/test/mvnw/mvnw.js
@@ -1,12 +1,33 @@
-const path = require('path');
-const {execSync} = require('child_process');
-const fs = require('fs');
+const path = require('path')
+const {spawn} = require('child_process')
+const fs = require('fs')
+const colors = require('colors')
+const readline = require('readline')
/**
* Version.
* @type {null|String}
*/
let ver = null
+/**
+ * Is execution running.
+ * @type {boolean}
+ */
+let running = false
+/**
+ * Start datetime.
+ * @type {Number}
+ */
+let beginning
+/**
+ * Target directory.
+ * @type {String}
+ */
+let target
+/**
+ * Current phase
+ */
+let phase = null
/**
* Get EO version.
@@ -25,7 +46,7 @@ const version = function() {
*/
function shell() {
if (process.platform === 'win32') {
- return 'C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe';
+ return 'C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe'
}
}
@@ -42,33 +63,118 @@ const flags = function(opts) {
]
}
+/* eslint-disable valid-jsdoc */
/**
* Execute given goals of eo-maven-plugin.
- * @param {Array.} goals - Goals to execute in right order
- * @param {{sources: String, target: String, home: String}} opts - Options
+ * @param {Array.|String} goals - Goals to execute in right order
+ * @param {{sources: String, target: String, home: String, [skip]: Boolean}} opts - Options
+ * @return {Promise|String>}
*/
-const mvnw = function(goals, opts) {
- const bin = path.resolve(__dirname, 'mvnw') + (process.platform === 'win32' ? '.cmd' : '');
- const params = [
- ...flags(opts),
- '--batch-mode',
- '--color=never',
- '--update-snapshots',
- '--fail-fast',
- '--strict-checksums',
- ]
- execSync(
- [
- bin,
+const mvnw = function(goals, opts = {}) {
+ return new Promise((resolve, reject) => {
+ if (opts.skip) {
+ resolve(goals)
+ }
+ phase = Array.isArray(goals) ? null : goals
+ goals = Array.isArray(goals) ? goals : [goals]
+ const bin = path.resolve(__dirname, 'mvnw') + (process.platform === 'win32' ? '.cmd' : '')
+ target = path.resolve(opts.home, opts.target)
+ const params = [
+ ...flags(opts),
+ '--batch-mode',
+ '--color=never',
+ '--update-snapshots',
+ '--fail-fast',
+ '--strict-checksums',
+ ]
+ const args = [
...goals.map((goal) => `org.eolang:eo-maven-plugin:${goal}`),
...process.platform === 'win32' ? params.map((p) => `"${p}"`) : params,
- ].join(' '),
- {
- cwd: __dirname,
- // stdio: 'inherit',
- shell: shell(),
+ ]
+ const command = [bin, ...args].join(' ');
+ console.debug(`Running: ${command}`)
+ const result = spawn(
+ bin,
+ args,
+ {
+ cwd: __dirname,
+ stdio: 'inherit',
+ shell: shell(),
+ }
+ )
+ start()
+ result.on('close', (code) => {
+ if (code !== 0) {
+ console.error(`The command "${command}" exited with #${code} code`)
+ process.exit(1)
+ }
+ stop()
+ resolve(goals)
+ })
+ })
+}
+
+/**
+ * Starts mvnw execution status detection.
+ */
+function start() {
+ running = true
+ beginning = Date.now()
+ const check = function() {
+ if (running) {
+ print()
+ setTimeout(check, 1000)
}
- )
+ }
+ check()
+}
+
+
+/**
+ * Stops mvnw execution status detection.
+ */
+function stop() {
+ running = false
+ readline.clearLine(process.stdout, 0)
+}
+
+/**
+ * Prints mvnw execution status.
+ */
+function print() {
+ const duration = Date.now() - beginning;
+ /**
+ * Recursively calculates number of files under a directory.
+ * @param {String} dir - Directory where to count.
+ * @param {Integer} curr - Current counter.
+ * @return {Integer} Total number files.
+ */
+ function count(dir, curr) {
+ if (fs.existsSync(dir)) {
+ for (const f of fs.readdirSync(dir)) {
+ const next = path.join(dir, f);
+ if (fs.statSync(next).isDirectory()) {
+ curr = count(next, curr);
+ } else {
+ curr++;
+ }
+ }
+ }
+ return curr;
+ }
+ let elapsed;
+ if (duration < 1000) {
+ elapsed = `${duration}ms`;
+ } else if (duration < 60 * 1000) {
+ elapsed = `${Math.ceil(duration / 1000)}s`;
+ } else {
+ elapsed = `${Math.ceil(duration / 3600000)}min`;
+ }
+ process.stdout.write(
+ colors.yellow(`${phase ? `[${phase}]: `: ''} ${elapsed}; ${count(target, 0)} files generated so far...`)
+ );
+ readline.clearLine(process.stdout, 1);
+ readline.cursorTo(process.stdout, 0);
}
module.exports = mvnw
diff --git a/eo2js/test/resources/transpile/packs/data-as-bytes.json b/eo2js/test/resources/transpile/packs/data-as-bytes.json
index 76a4c43..af43027 100644
--- a/eo2js/test/resources/transpile/packs/data-as-bytes.json
+++ b/eo2js/test/resources/transpile/packs/data-as-bytes.json
@@ -23,9 +23,11 @@
"args": [
[
" let ret = phi.take('org').take('eolang').take('number')",
- " let ret_1 = phi.take('org').take('eolang').take('bytes')",
- " ret_1 = ret_1.with({",
- " 'Δ': ['0x40', '0x45', '0x00', '0x00', '0x00', '0x00', '0x00', '0x00']",
+ " let ret_1 = phi.take('org').take('eolang').take('bytes').copy()",
+ " ret_1 = applied(ret_1, {",
+ " 0: object().with({",
+ " 'Δ': ['0x40', '0x45', '0x00', '0x00', '0x00', '0x00', '0x00', '0x00']",
+ " })",
" })",
" ret = applied(ret, {",
" 0: ret_1",
@@ -41,9 +43,11 @@
[
" let ret = phi.take('org').take('eolang').take('float')",
" let ret_1 = phi.take('org').take('eolang').take('number')",
- " let ret_1_1 = phi.take('org').take('eolang').take('bytes')",
- " ret_1_1 = ret_1_1.with({",
- " 'Δ': ['0x40', '0x0C', '0x00', '0x00', '0x00', '0x00', '0x00', '0x00']",
+ " let ret_1_1 = phi.take('org').take('eolang').take('bytes').copy()",
+ " ret_1_1 = applied(ret_1_1, {",
+ " 0: object().with({",
+ " 'Δ': ['0x40', '0x0C', '0x00', '0x00', '0x00', '0x00', '0x00', '0x00']",
+ " })",
" })",
" ret_1 = applied(ret_1, {",
" 0: ret_1_1",
@@ -60,9 +64,41 @@
"method": "includes",
"args": [
[
- " let ret = phi.take('org').take('eolang').take('bytes')",
- " ret = ret.with({",
- " 'Δ': ['0x01', '0xAF']",
+ " let ret = phi.take('org').take('eolang').take('bytes').copy()",
+ " ret = applied(ret, {",
+ " 0: object().with({",
+ " 'Δ': ['0x01', '0xAF']",
+ " })",
+ " })",
+ " return ret"
+ ]
+ ]
+ },
+ {
+ "node": ".program.objects.object{.\"@_name\" == 'one-byte'}.javascript",
+ "method": "includes",
+ "args": [
+ [
+ " let ret = phi.take('org').take('eolang').take('bytes').copy()",
+ " ret = applied(ret, {",
+ " 0: object().with({",
+ " 'Δ': ['0x01']",
+ " })",
+ " })",
+ " return ret"
+ ]
+ ]
+ },
+ {
+ "node": ".program.objects.object{.\"@_name\" == 'empty'}.javascript",
+ "method": "includes",
+ "args": [
+ [
+ " let ret = phi.take('org').take('eolang').take('bytes').copy()",
+ " ret = applied(ret, {",
+ " 0: object().with({",
+ " 'Δ': []",
+ " })",
" })",
" return ret"
]
@@ -81,6 +117,12 @@
" float 3.5 > @",
"# This is the default 64+ symbols comment in front of named abstract object.",
"[] > b",
- " 01-AF > @"
+ " 01-AF > @",
+ "# This is the default 64+ symbols comment in front of named abstract object.",
+ "[] > one-byte",
+ " 01- > @",
+ "# This is the default 64+ symbols comment in front of named abstract object.",
+ "[] > empty",
+ " -- > @"
]
}
diff --git a/package.json b/package.json
index c0485bc..64e96bc 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
"postinstall": "npm run install-eo2js && npm run install-eo2js-runtime",
"test-eo2js": "cd eo2js && grunt",
"test-eo2js-runtime": "cd eo2js-runtime && grunt",
- "test": "npm run test-eo2js && npm run test-eo2js-runtime"
+ "test": "npm run test-eo2js-runtime && npm run test-eo2js"
},
"author": "maxonfjvipon",
"license": "MIT"