Repository navigation
Expand file tree
/
Copy patharray.ts
More file actions
284 lines (254 loc) · 11.2 KB
/
Copy patharray.ts
File metadata and controls
284 lines (254 loc) · 11.2 KB
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
import { State, IdentifierStatus, DynamicBasis, StaticBasis } from '../state';
import { TypeVariable, FunctionType, CustomType, TupleType } from '../types';
import { Integer, PredefinedFunction, Value, RecordValue,
ConstructedValue, ArrayValue } from '../values';
import { InternalInterpreterError } from '../errors';
import { EvaluationParameters } from '../evaluator';
import { Module, intType, sizeException, subscriptException } from '../stdlib';
function addArrayLib(state: State): State {
let dres = new DynamicBasis({}, {}, {}, {}, {});
let sres = new StaticBasis({}, {}, {}, {}, {});
let arrayType = new CustomType('array', [new TypeVariable('\'a')]);
let listType = new CustomType('list', [new TypeVariable('\'a')]);
sres.setType('array', arrayType, [], 1, true);
dres.setType('array', []);
dres.setValue('array', new PredefinedFunction('array', (val: Value, params: EvaluationParameters) => {
if (val instanceof RecordValue && val.entries.size === 2) {
let cnt = val.getValue('1');
let value = val.getValue('2');
if (cnt instanceof Integer) {
let c = cnt.value;
if (c < 0) {
return [sizeException.construct(), true, []];
}
let arr = new ArrayValue(params.modifiable.memory[0] + 1, c);
// we need to waste one cell so that no two arrays can be the same
params.modifiable.setNewCell(arr);
for (let i = 0; i < c; ++i) {
params.modifiable.setNewCell(value);
}
return [arr, false, []];
}
}
throw new InternalInterpreterError('std type mismatch');
}), IdentifierStatus.VALUE_VARIABLE);
sres.setValue('array',
new FunctionType(new TupleType([intType, new TypeVariable('\'a')]).simplify(), arrayType),
IdentifierStatus.VALUE_VARIABLE);
dres.setValue('fromList', new PredefinedFunction('fromList', (val: Value, params: EvaluationParameters) => {
let arr = new ArrayValue(params.modifiable.memory[0] + 1, 0);
params.modifiable.setNewCell(arr); // we need to waste one cell so that no two arrays can be the same
if (val instanceof ConstructedValue) {
let list: ConstructedValue = val;
while (list.constructorName !== 'nil') {
if (list.constructorName !== '::') {
throw new InternalInterpreterError('std type mismatch');
}
let arg = list.argument;
if (arg instanceof RecordValue && arg.entries.size === 2) {
let a1 = arg.getValue('1');
let a2 = arg.getValue('2');
if (a1 instanceof Value && a2 instanceof ConstructedValue) {
params.modifiable.setNewCell(a1);
arr.length++;
list = a2;
} else {
throw new InternalInterpreterError('std type mismatch');
}
} else {
throw new InternalInterpreterError('std type mismatch');
}
}
return [arr, false, []];
} else {
throw new InternalInterpreterError('std type mismatch');
}
}), IdentifierStatus.VALUE_VARIABLE);
sres.setValue('fromList', new FunctionType(listType, arrayType), IdentifierStatus.VALUE_VARIABLE);
dres.setValue('sub', new PredefinedFunction('sub', (val: Value, params: EvaluationParameters) => {
if (val instanceof RecordValue && val.entries.size === 2) {
let arr = val.getValue('1');
let index = val.getValue('2');
if (arr instanceof ArrayValue && index instanceof Integer) {
let ind = index.value;
if (ind < 0 || ind >= arr.length) {
return [subscriptException.construct(), true, []];
}
return [(<Value> params.modifiable.getCell(arr.address + ind)), false, []];
} else {
throw new InternalInterpreterError('std type mismatch');
}
} else {
throw new InternalInterpreterError('std type mismatch');
}
}), IdentifierStatus.VALUE_VARIABLE);
sres.setValue('sub',
new FunctionType(new TupleType([arrayType, intType]).simplify(), new TypeVariable('\'a')),
IdentifierStatus.VALUE_VARIABLE);
dres.setValue('update', new PredefinedFunction('update', (val: Value, params: EvaluationParameters) => {
if (val instanceof RecordValue && val.entries.size === 3) {
let arr = val.getValue('1');
let index = val.getValue('2');
let value = val.getValue('3');
if (arr instanceof ArrayValue && index instanceof Integer) {
let ind = index.value;
if (ind < 0 || ind >= arr.length) {
return [subscriptException.construct(), true, []];
}
params.modifiable.setCell(arr.address + ind, value);
return [new RecordValue(), false, []];
} else {
throw new InternalInterpreterError('std type mismatch');
}
} else {
throw new InternalInterpreterError('std type mismatch');
}
}), IdentifierStatus.VALUE_VARIABLE);
sres.setValue('update',
new FunctionType(new TupleType([arrayType, intType, new TypeVariable('\'a')]), new TupleType([])).simplify(),
IdentifierStatus.VALUE_VARIABLE);
dres.setValue('length', new PredefinedFunction('length', (val: Value, params: EvaluationParameters) => {
if (val instanceof ArrayValue) {
let res = new Integer(val.length);
return [res, false, []];
} else {
throw new InternalInterpreterError('std type mismatch');
}
}), IdentifierStatus.VALUE_VARIABLE);
sres.setValue('length', new FunctionType(arrayType, intType), IdentifierStatus.VALUE_VARIABLE);
state.setDynamicStructure('Array', dres);
state.setStaticStructure('Array', sres);
return state;
}
export let ARRAY_LIB: Module = {
'native': addArrayLib,
'code': `signature ARRAY = sig
(* eqtype 'a array = 'a array *)
(* type 'a vector = 'a Vector.vector *)
(* val maxLen : int *)
val array : int * 'a -> 'a array
val fromList : 'a list -> 'a array
val tabulate : int * (int -> 'a) -> 'a array
val length : 'a array -> int
val sub : 'a array * int -> 'a
val update : 'a array * int * 'a -> unit
val vector : 'a array -> 'a vector
val copy : {src : 'a array, dst : 'a array, di : int} -> unit
val copyVec : {src : 'a vector, dst : 'a array, di : int} -> unit
val appi : (int * 'a -> unit) -> 'a array -> unit
val app : ('a -> unit) -> 'a array -> unit
val modifyi : (int * 'a -> 'a) -> 'a array -> unit
val modify : ('a -> 'a) -> 'a array -> unit
val foldli : (int * 'a * 'b -> 'b) -> 'b -> 'a array -> 'b
val foldri : (int * 'a * 'b -> 'b) -> 'b -> 'a array -> 'b
val foldl : ('a * 'b -> 'b) -> 'b -> 'a array -> 'b
val foldr : ('a * 'b -> 'b) -> 'b -> 'a array -> 'b
val findi : (int * 'a -> bool) -> 'a array -> (int * 'a) option
val find : ('a -> bool) -> 'a array -> 'a option
val exists : ('a -> bool) -> 'a array -> bool
val all : ('a -> bool) -> 'a array -> bool
val collate : ('a * 'a -> order) -> 'a array * 'a array -> order
end;
structure Array :> ARRAY = struct
open Array;
fun tabulate (n, f) = fromList (List.tabulate (n, f));
fun vector arr = Vector.tabulate (length arr, fn i => sub (arr, i));
fun copy {src, dst, di} = if di < 0 orelse length dst < di + length src then raise Subscript
else
let
val len = length src
fun loop index = if index = len then ()
else ( update(dst, index + di, sub(src, index)); loop (index + 1))
in
loop 0
end;
fun copyVec {src, dst, di} = if di < 0 orelse length dst < di + Vector.length src then raise Subscript
else
let
val len = Vector.length src
fun loop index = if index = len then ()
else ( update(dst, index + di, Vector.sub(src, index)); loop (index + 1))
in
loop 0
end;
fun appi p arr = let
val len = length arr
fun loop index = if index = len then ()
else (p(index, sub(arr, index)); loop (index +1))
in
loop 0
end;
fun app p = appi (fn (_, v) => p v);
fun modifyi p arr =
let
val len = length arr
fun loop index = if index = len then ()
else ( update(arr, index, p(index, sub(arr, index))); loop (index +1))
in
loop 0
end;
fun modifyi p arr =
let
val len = length arr
fun loop index = if index = len then ()
else ( update(arr, index, p(index, sub(arr, index))); loop (index +1))
in
loop 0
end;
fun modify p = modifyi (fn (_, v) => p v);
fun foldli f init arr =
let
val len = length arr
fun loop (i, b) =
if i = len then b
else loop (i + 1, f (i, sub (arr, i), b))
in
loop (0, init)
end;
fun foldri f init arr =
let
val len = length arr
fun loop (i, b) =
if i = ~1 then b
else loop (i - 1, f (i, sub (arr, i), b))
in
loop (len - 1, init)
end;
fun foldl f init arr = foldli (fn (_, a, x) => f(a, x)) init arr;
fun foldr f init arr = foldri (fn (_, a, x) => f(a, x)) init arr;
fun findi f arr =
let
val len = length arr
fun loop index =
if index = Array.length arr then NONE
else
let
val el = sub(arr, index)
in
if f (index, el) then SOME (index, el) else loop (index+1)
end
in
loop 0
end;
fun find f arr = case findi (fn (_, v) => f v) arr of NONE => NONE
| SOME (_, v) => SOME v;
fun exists p arr = case find p arr of NONE => false
| SOME _ => true;
fun all p = foldl (fn (v, acc) => p v andalso acc) true;
fun collate p (a1, a2) =
let
val length1 = length a1
val length2 = length a2
fun loop index =
if index = length1 andalso index = length2 then EQUAL
else if index = length1 then LESS
else if index = length2 then GREATER
else case p (sub (a1, index), sub (a2, index)) of
EQUAL => loop (index + 1)
| l => l
in
loop 0
end;
end;`,
'requires': ['Option', 'List', 'Vector']
};