Skip to content

Commit

Permalink
feat(#61): malloc + cage atoms and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
maxonfjvipon committed May 29, 2024
1 parent b6e4f9b commit e72c23b
Show file tree
Hide file tree
Showing 23 changed files with 670 additions and 81 deletions.
21 changes: 12 additions & 9 deletions eo2js-runtime/src/objects/org/eolang/cage$encaged$encage.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
const object = require('../../../runtime/object')
const {LAMBDA} = require('../../../runtime/attribute/specials');
const ErFailure = require('../../../runtime/error/ErFailure');
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 {INT, data} = require('../../../runtime/data');

/**
* Cage.encaged.encage.
* @return {Object} - Cage.encaged.encage object
* @todo #3:30min Implement cage$encaged$encage atom. We need to implement the atom and make sure it
* works. For the details of implementation check the Java analogue on
* https://github.com/objectionary/eo/tree/master/eo-runtime/src/main/java/EOorg/EOeolang
*/
const cage$encaged$encage = function() {
const obj = object('cage$encaged$encage')
obj.assets[LAMBDA] = function(_) {
throw new ErFailure(
`Atom cage$encaged$encage is not implemented yet`
)
obj.attrs['object'] = at_void('object')
obj.assets[LAMBDA] = function(self) {
cages.encage(
Number(dataized(self.take(RHO).take('locator'), INT)),
self.take('object')
);
return data.toObject(true)
}
return obj
}
Expand Down
17 changes: 9 additions & 8 deletions eo2js-runtime/src/objects/org/eolang/cage$encaged$φ.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
const object = require('../../../runtime/object')
const {LAMBDA} = require('../../../runtime/attribute/specials');
const ErFailure = require('../../../runtime/error/ErFailure');
const {LAMBDA, RHO} = require('../../../runtime/attribute/specials');
const dataized = require('../../../runtime/dataized');
const {INT} = require('../../../runtime/data');
const {traced} = require('../../../runtime/traced');
const cages = require('../../../runtime/cages');

/**
* Cage.encaged.φ.
* @return {Object} - Cage.encaged.φ object
* @todo #3:30min Implement cage$encaged$φ atom. We need to implement the atom and make sure it
* works. For the details of implementation check the Java analogue on
* https://github.com/objectionary/eo/tree/master/eo-runtime/src/main/java/EOorg/EOeolang
*/
const cage$encaged$φ = function() {
const obj = object('cage$encaged$φ')
obj.assets[LAMBDA] = function(_) {
throw new ErFailure(
`Atom cage$encaged$φ is not implemented yet`
obj.assets[LAMBDA] = function(self) {
const locator = Number(
dataized(self.take(RHO).take('locator'), INT)
)
return traced(cages.get(locator), locator)
}
return obj
}
Expand Down
19 changes: 10 additions & 9 deletions eo2js-runtime/src/objects/org/eolang/cage$φ.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
const object = require('../../../runtime/object')
const {LAMBDA} = require('../../../runtime/attribute/specials');
const ErFailure = require('../../../runtime/error/ErFailure');
const {LAMBDA, RHO} = require('../../../runtime/attribute/specials');
const {data} = require('../../../runtime/data');
const cages = require('../../../runtime/cages');

/**
* Cage.φ.
* @return {Object} - Cage.φ object
* @todo #3:30min Implement cage$φ atom. We need to implement the atom and make sure it
* works. For the details of implementation check the Java analogue on
* https://github.com/objectionary/eo/tree/master/eo-runtime/src/main/java/EOorg/EOeolang
*/
const cage$φ = function() {
const obj = object('cage$φ')
obj.assets[LAMBDA] = function(_) {
throw new ErFailure(
`Atom cage$φ is not implemented yet`
)
obj.assets[LAMBDA] = function(self) {
const rho = self.take(RHO)
return rho.take('encaged').with({
locator: data.toObject(
BigInt(cages.init(rho.take('object')))
)
})
}
return obj
}
Expand Down
22 changes: 14 additions & 8 deletions eo2js-runtime/src/objects/org/eolang/malloc$of$allocated$read.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
const object = require('../../../runtime/object')
const {LAMBDA} = require('../../../runtime/attribute/specials');
const ErFailure = require('../../../runtime/error/ErFailure');
const {LAMBDA, RHO} = require('../../../runtime/attribute/specials');
const at_void = require('../../../runtime/attribute/at-void');
const dataized = require('../../../runtime/dataized');
const {INT, data} = require('../../../runtime/data');
const heaps = require('../../../runtime/heaps');

/**
* Malloc.of.allocated.read.
* @return {Object} - Malloc.of.allocated.read object
* @todo #3:30min Implement malloc$of$allocated$read atom. We need to implement the atom and make
* sure it works. For the details of implementation check the Java analogue on
* https://github.com/objectionary/eo/tree/master/eo-runtime/src/main/java/EOorg/EOeolang
*/
const malloc$of$allocated$read = function() {
const obj = object('malloc$of$allocated$read')
obj.assets[LAMBDA] = function(_) {
throw new ErFailure(
`Atom malloc$of$allocated$read is not implemented yet`
obj.attrs['offset'] = at_void('offset')
obj.attrs['length'] = at_void('length')
obj.assets[LAMBDA] = function(self) {
return data.toObject(
heaps.read(
Number(dataized(self.take(RHO).take('id'), INT)),
Number(dataized(self.take('offset'), INT)),
Number(dataized(self.take('length'), INT))
)
)
}
return obj
Expand Down
21 changes: 13 additions & 8 deletions eo2js-runtime/src/objects/org/eolang/malloc$of$allocated$write.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
const object = require('../../../runtime/object')
const {LAMBDA} = require('../../../runtime/attribute/specials');
const ErFailure = require('../../../runtime/error/ErFailure');
const {LAMBDA, RHO} = require('../../../runtime/attribute/specials');
const at_void = require('../../../runtime/attribute/at-void');
const {data, INT} = require('../../../runtime/data');
const heaps = require('../../../runtime/heaps');
const dataized = require('../../../runtime/dataized');

/**
* Malloc.of.allocated.write.
* @return {Object} - Malloc.of.allocated.write object
* @todo #3:30min Implement malloc$of$allocated$write atom. We need to implement the atom and make
* sure it works. For the details of implementation check the Java analogue on
* https://github.com/objectionary/eo/tree/master/eo-runtime/src/main/java/EOorg/EOeolang
*/
const malloc$of$allocated$write = function() {
const obj = object('malloc$of$allocated$write')
obj.assets[LAMBDA] = function(_) {
throw new ErFailure(
`Atom malloc$of$allocated$write is not implemented yet`
obj.attrs['offset'] = at_void('offset')
obj.attrs['data'] = at_void('data')
obj.assets[LAMBDA] = function(self) {
heaps.write(
Number(dataized(self.take(RHO).take('id'), INT)),
Number(dataized(self.take('offset'), INT)),
dataized(self.take('data'))
)
return data.toObject(true)
}
return obj
}
Expand Down
31 changes: 22 additions & 9 deletions eo2js-runtime/src/objects/org/eolang/malloc$of$φ.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
const object = require('../../../runtime/object')
const {LAMBDA} = require('../../../runtime/attribute/specials');
const ErFailure = require('../../../runtime/error/ErFailure');
const {LAMBDA, RHO} = require('../../../runtime/attribute/specials');
const dataized = require('../../../runtime/dataized');
const {INT, data} = require('../../../runtime/data');
const heaps = require('../../../runtime/heaps');

/**
* Malloc.of.φ.
* @return {Object} - Malloc.of.φ object
* @todo #3:30min Implement malloc$of$φ atom. We need to implement the atom and make sure it
* works. For the details of implementation check the Java analogue on
* https://github.com/objectionary/eo/tree/master/eo-runtime/src/main/java/EOorg/EOeolang
*/
const malloc$of$φ = function() {
const obj = object('malloc$of$φ')
obj.assets[LAMBDA] = function(_) {
throw new ErFailure(
`Atom malloc$of$φ is not implemented yet`
)
obj.assets[LAMBDA] = function(self) {
const rho = self.take(RHO);
const size = Number(dataized(rho.take('size'), INT))
const identifier = heaps.malloc(size)
let res;
try {
dataized(
rho.take('scope').with({
0: rho.take('allocated').with({
id: data.toObject(BigInt(identifier))
})
})
)
res = data.toObject(heaps.read(identifier, 0, size))
} finally {
heaps.free(identifier)
}
return res
}
return obj
}
Expand Down
4 changes: 2 additions & 2 deletions eo2js-runtime/src/runtime/attribute/at-void.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ const at_void = function(name, object = null) {
return {
put: function(object) {
if (obj != null) {
throw new ErFailure(`Void attribute ${name} is already set, can't reset`)
throw new ErFailure(`Void attribute '${name}' is already set, can't reset`)
}
obj = object
return true
},
get: function() {
if (obj == null) {
throw new ErFailure(`Void attribute ${name} is not set, can't take`)
throw new ErFailure(`Void attribute '${name}' is not set, can't take`)
}
return obj
},
Expand Down
72 changes: 72 additions & 0 deletions eo2js-runtime/src/runtime/cages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
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
12 changes: 10 additions & 2 deletions eo2js-runtime/src/runtime/error/ErError.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const ErAbstract = require('./ErAbstract');
const dataized = require('../dataized');
const {STRING} = require('../data');
const {DELTA} = require('../attribute/specials');
const bytesOf = require('../bytes-of');

/**
* This Error is thrown by the {@see error} object only.
Expand All @@ -22,7 +23,14 @@ class ErError extends ErAbstract {
* @return {string}
*/
static safeMessage(enclosure) {
return dataized(enclosure, STRING)
let result
try {
const raw = dataized(enclosure)
result = `${enclosure.toString()}(${DELTA} = ${bytesOf(raw).verbose()})`
} catch (first) {
result = enclosure.toString();
}
return result
}
}

Expand Down
Loading

0 comments on commit e72c23b

Please sign in to comment.