Skip to content

Commit 1ac162e

Browse files
committed
add lazy array getters, string pool and hashmap tests
1 parent 70db8cd commit 1ac162e

File tree

20 files changed

+1349
-41
lines changed

20 files changed

+1349
-41
lines changed

.babelrc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212
}
1313
}
1414
}],
15-
["trace", {strip: true}]
15+
["trace", {strip: true}],
16+
["transform-async-to-module-method", {
17+
"module": "bluebird",
18+
"method": "coroutine"
19+
}]
1620
],
1721
"passPerPreset": true
1822
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"babel-core": "^6.5.1",
1818
"babel-plugin-contracts": "^1.1.1",
1919
"babel-plugin-trace": "^1.0.0",
20+
"babel-plugin-transform-async-to-module-method": "^6.5.2",
2021
"babel-plugin-typecheck": "^3.6.1",
2122
"babel-polyfill": "^6.5.0",
2223
"babel-preset-es2015": "^6.5.0",

src/builtins/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {make as makeFloat64} from "./float64";
1515
//import {make as makeNumber} from "./number";
1616

1717
import {make as makeBoolean} from "./boolean";
18+
import {make as makeString} from "./string";
1819

1920

2021
export function registerBuiltins (realm: Realm): TypeRegistry {
@@ -31,6 +32,7 @@ export function registerBuiltins (realm: Realm): TypeRegistry {
3132
registry.add(makeFloat64(realm, 8));
3233
//registry.add(makeNumber(realm, 9));
3334
registry.add(makeBoolean(realm, 10));
35+
registry.add(makeString(realm, 11));
3436

3537
return registry;
3638
}

src/builtins/string/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* @flow */
2+
3+
import type Backing from "backing";
4+
import type {Realm} from "../..";
5+
6+
import {$StringPool} from "../../symbols";
7+
8+
export function make (realm: Realm, typeId: uint32): Type<string> {
9+
const pool = realm[$StringPool];
10+
return pool.makeStringType('String', typeId);
11+
}

src/builtins/string/test.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
describeRealm('Builtin: String', function (options) {
2+
let realm;
3+
let backing;
4+
let T;
5+
let address;
6+
7+
before(() => {
8+
realm = options.realm;
9+
backing = realm.backing;
10+
T = realm.T;
11+
address = backing.alloc(T.String.byteLength);
12+
});
13+
14+
after(() => {
15+
backing.free(address);
16+
});
17+
18+
describe('Cast', function () {
19+
it('should return an empty value for empty input', function () {
20+
T.String().should.equal('');
21+
});
22+
23+
});
24+
25+
it('should not create a new instance', function () {
26+
(() => new T.String('wat')).should.throw(TypeError);
27+
});
28+
29+
describe('.emptyValue()', function () {
30+
it('should return an empty value', function () {
31+
T.String.emptyValue().should.equal('');
32+
});
33+
});
34+
35+
describe('.randomValue()', function () {
36+
it('should return a random value', function () {
37+
const value = T.String.randomValue();
38+
(typeof value).should.equal('string');
39+
});
40+
41+
it('should accept a random value', function () {
42+
T.String.accepts(T.String.randomValue()).should.equal(true);
43+
});
44+
});
45+
46+
describe('.initialize(), .store(), .load() and .clear()', function () {
47+
let input;
48+
before(() => {
49+
input = T.String.randomValue();
50+
});
51+
52+
it('should initialize an address', function () {
53+
T.String.initialize(backing, address);
54+
});
55+
56+
it('should load an empty value from a just-initialized address', function () {
57+
T.String.load(backing, address).should.equal(T.String.emptyValue());
58+
});
59+
60+
it('should store a value at an address', function () {
61+
T.String.store(backing, address, input);
62+
});
63+
64+
it('should load a value from an address', function () {
65+
T.String.load(backing, address).should.equal(input);
66+
});
67+
68+
it('should clear a value from an address', function () {
69+
T.String.clear(backing, address);
70+
});
71+
72+
it('should load an empty value from a cleaned up address', function () {
73+
(T.String.load(backing, address) === T.String.emptyValue()).should.equal(true);
74+
});
75+
});
76+
77+
describe('.hashValue()', function () {
78+
it('should hash a value', function () {
79+
T.String.hashValue(123).should.be.above(-1);
80+
});
81+
82+
it('should hash a random value', function () {
83+
T.String.hashValue(T.String.randomValue()).should.be.above(-1);
84+
});
85+
86+
it('should hash an empty value', function () {
87+
T.String.hashValue(T.String.emptyValue()).should.be.above(-1);
88+
});
89+
90+
});
91+
});

src/index.js

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
/* @flow */
22
import {make as makeTypeClass} from "./type-class";
33
import {make as makePrimitiveType} from "./type-class/primitive-type";
4+
import {make as makeStringType} from "./type-class/string-type";
45
import {make as makeReferenceType} from "./type-class/reference-type";
56
import {make as makeStructType} from "./type-class/struct-type";
67
import {make as makeArrayType} from "./type-class/array-type";
78
import {make as makeHashMapType} from "./type-class/hash-map-type";
89

10+
import {make as makeStringPool} from "./string-pool";
11+
912

1013
import {registerBuiltins} from "./builtins";
14+
import {$StringPool} from "./symbols";
15+
1116

1217
import type Backing from "backing";
1318
import type TypeRegistry from "type-registry";
1419

20+
const HEADER_ADDRESS = 336; // First usable block in the backing store.
21+
const VERSION_ADDRESS = HEADER_ADDRESS;
22+
const STRING_POOL_POINTER_ADDRESS = VERSION_ADDRESS + 8;
23+
const HEADER_CHECKSUM_ADDRESS = STRING_POOL_POINTER_ADDRESS + 16;
24+
const HEADER_SIZE = (HEADER_CHECKSUM_ADDRESS + 8) - HEADER_ADDRESS;
25+
const FIRST_ADDRESS = HEADER_ADDRESS + HEADER_SIZE;
1526

1627
export class Realm {
1728

@@ -44,9 +55,9 @@ export class Realm {
4455
this.ReferenceType = makeReferenceType(this);
4556
this.StructType = makeStructType(this);
4657
this.ArrayType = makeArrayType(this);
58+
this.StringType = makeStringType(this);
4759
this.HashMapType = makeHashMapType(this);
4860
this.isInitialized = false;
49-
registerBuiltins(this);
5061
}
5162

5263
/**
@@ -56,11 +67,43 @@ export class Realm {
5667
if (this.isInitialized) {
5768
throw new Error(`Realm cannot be initialized twice.`);
5869
}
70+
trace: `Initializing the realm.`
5971
if (!this.backing.isInitialized) {
6072
await this.backing.init();
6173
}
74+
verifyHeader(this);
75+
this[$StringPool] = makeStringPool(this, STRING_POOL_POINTER_ADDRESS);
76+
registerBuiltins(this);
6277
this.isInitialized = true;
6378
Object.freeze(this);
6479
return this;
6580
}
66-
}
81+
82+
/**
83+
* Ensure that the given value is aligned to the given number of bytes.
84+
*/
85+
alignTo (value: number, numberOfBytes: number): number {
86+
const rem = value % numberOfBytes;
87+
return rem === 0 ? value : value + (numberOfBytes - rem);
88+
}
89+
}
90+
91+
92+
function verifyHeader (realm: Realm) {
93+
const backing: Backing = realm.backing;
94+
if (
95+
backing.getUint32(HEADER_ADDRESS) !== HEADER_ADDRESS ||
96+
backing.getUint32(HEADER_CHECKSUM_ADDRESS) !== HEADER_CHECKSUM_ADDRESS
97+
) {
98+
const address = backing.calloc(HEADER_SIZE);
99+
100+
/* istanbul ignore if */
101+
if (address !== HEADER_ADDRESS) {
102+
throw new TypeError(`Allocator returned an invalid backing header address, got ${address} expected ${HEADER_ADDRESS}.`);
103+
}
104+
backing.setUint32(HEADER_ADDRESS, HEADER_ADDRESS);
105+
backing.setUint32(HEADER_CHECKSUM_ADDRESS, HEADER_CHECKSUM_ADDRESS);
106+
backing.setFloat64(STRING_POOL_POINTER_ADDRESS, 0);
107+
}
108+
}
109+

0 commit comments

Comments
 (0)