-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathop_collections.py
100 lines (84 loc) · 2.8 KB
/
op_collections.py
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
"""Built-in collections operators for stilted."""
from error import Tilted
from evaluate import operator, Engine
from dtypes import (
from_py, typecheck,
Array, Dict, Integer, Name, String, Stringy,
)
from util import rangecheck
@operator
def get(engine: Engine) -> None:
obj, ind = engine.opopn(2)
match obj:
case Array():
typecheck(Integer, ind)
rangecheck(0, ind.value, len(obj.value)-1)
elt = obj[ind.value]
engine.opush(elt)
case Dict():
typecheck(Stringy, ind)
try:
obj = obj[ind.str_value]
except KeyError:
raise Tilted("undefined", f"{ind.value}")
engine.opush(obj)
case String():
typecheck(Integer, ind)
rangecheck(0, ind.value, obj.length - 1)
byte = obj[ind.value]
engine.opush(from_py(byte))
case _:
raise Tilted("typecheck", f"got {type(obj)}")
@operator
def getinterval(engine: Engine) -> None:
obj, ind, count = engine.opopn(3)
typecheck(Integer, ind, count)
match obj:
case Array() | String():
engine.opush(obj.new_sub(ind.value, count.value))
case _:
raise Tilted("typecheck", f"got {type(obj)}")
@operator
def length(engine: Engine) -> None:
o = engine.opop()
match o:
case Array() | String():
engine.opush(from_py(len(o)))
case Dict() | Name():
engine.opush(from_py(len(o.value)))
case _:
raise Tilted("typecheck", f"got {type(o)}")
@operator
def put(engine: Engine) -> None:
obj, ind, elt = engine.opopn(3)
match obj:
case Array():
typecheck(Integer, ind)
rangecheck(0, ind.value, len(obj.value)-1)
engine.prep_for_change(obj)
obj[ind.value] = elt
case Dict():
typecheck(Stringy, ind)
engine.prep_for_change(obj)
obj[ind.str_value] = elt
case String():
typecheck(Integer, ind, elt)
rangecheck(0, elt.value, 255)
rangecheck(0, ind.value, obj.length - 1)
obj[ind.value] = elt.value
case _:
raise Tilted("typecheck", f"got {type(obj)}")
@operator
def putinterval(engine: Engine) -> None:
obj1, ind, obj2 = engine.opopn(3)
typecheck(Integer, ind)
match obj1, obj2:
case (Array(), Array()) | (String(), String()):
if not (0 <= ind.value <= obj1.length):
raise Tilted("rangecheck")
if not (ind.value + obj2.length <= obj1.length):
raise Tilted("rangecheck")
for i in range(obj2.length):
obj1[ind.value + i] = obj2[i]
case _:
raise Tilted("typecheck", f"got {type(obj1)}")