This repository has been archived by the owner on Feb 12, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
array.js
102 lines (95 loc) · 2.58 KB
/
array.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
* Copyright (c) 2015-2016, Salesforce.com, Inc.
* All rights reserved.
* Licensed under the MIT license.
* For full license text, see LICENSE.md file in the repo root or
* https://opensource.org/licenses/MIT
*/
'use strict';
let array = {};
module.exports = array;
let makeType = require('./factory.js');
let Type = require('./type.js');
let Value = require('./value.js');
let errors = require('../errors.js');
let NumberValue = require('./number.js');
let RangeValue = require('./range.js');
class ArrayValue extends Value {
constructor(type) {
super(type);
let length = this.type.indextype.high - this.type.indextype.low + 1;
this.items = Array.from({
length: length
},
() => this.type.valuetype.makeDefaultValue());
}
index(i) {
if (i instanceof NumberValue.Value || i instanceof RangeValue.Value) {
i = i.value;
}
if (typeof i !== 'number') {
throw new errors.Internal(`Trying to index array with ${i}`);
}
if (i < this.type.indextype.low || i > this.type.indextype.high) {
throw new errors.Bounds(`Cannot access index ${i} of ${this}`);
}
let v = this.items[i - this.type.indextype.low];
if (v == undefined) {
throw new errors.Internal(`Bounds check failed to catch issue: ${i}`);
}
return v;
}
forEach(cb) {
this.items.forEach((v, i) => cb(v, this.type.indextype.low + i));
}
map(cb) {
return this.items.map((v, i) => cb(v, this.type.indextype.low + i));
}
toString() {
let inner = this.items.map((v, i) => {
return `${this.type.indextype.low + i}: ${v.toString()}`;
}).join(', ');
return `[${inner}]`;
}
toJSON() {
return this.items.map((v, i) => [this.type.indextype.low + i, v.toJSON()]);
}
assignJSON(spec) {
spec.forEach(x => {
this.index(x[0]).assignJSON(x[1]);
});
}
assign(other) {
this.forEach((v, i) => this.index(i).assign(other.index(i)));
}
equals(other) {
let allEqual = true;
this.forEach((v, i) => {
if (!v.equals(other.index(i))) {
allEqual = false;
}
});
return allEqual;
}
size() {
return this.items.length;
}
capacity() {
return this.items.length;
}
}
class ArrayType extends Type {
constructor(decl, env, name) {
super(decl, env, name);
this.valuetype = makeType.make(this.decl.args[0], this.env);
this.indextype = makeType.make(this.decl.indexBy, this.env);
}
makeDefaultValue() {
return new ArrayValue(this);
}
toString() {
return `Array<${this.valuetype}>[${this.indextype}]`;
}
}
array.Type = ArrayType;
array.Value = ArrayValue;