Skip to content

Commit d7ca2f1

Browse files
committed
Remove dangling 'refines' logic in CABI
1 parent 5a34794 commit d7ca2f1

File tree

3 files changed

+24
-69
lines changed

3 files changed

+24
-69
lines changed

design/mvp/CanonicalABI.md

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,10 +1538,7 @@ guaranteed to be a no-op on the first iteration because the record as
15381538
a whole starts out aligned (as asserted at the top of `load`).
15391539

15401540
Variants are loaded using the order of the cases in the type to determine the
1541-
case index, assigning `0` to the first case, `1` to the next case, etc. To
1542-
support the subtyping allowed by `refines`, a lifted variant value semantically
1543-
includes a full ordered list of its `refines` case labels so that the lowering
1544-
code (defined below) can search this list to find a case label it knows about.
1541+
case index, assigning `0` to the first case, `1` to the next case, etc.
15451542
While the code below appears to perform case-label lookup at runtime, a normal
15461543
implementation can build the appropriate index tables at compile-time so that
15471544
variant-passing is always O(1) and not involving string operations.
@@ -1553,24 +1550,9 @@ def load_variant(cx, ptr, cases):
15531550
trap_if(case_index >= len(cases))
15541551
c = cases[case_index]
15551552
ptr = align_to(ptr, max_case_alignment(cases))
1556-
case_label = case_label_with_refinements(c, cases)
15571553
if c.t is None:
1558-
return { case_label: None }
1559-
return { case_label: load(cx, ptr, c.t) }
1560-
1561-
def case_label_with_refinements(c, cases):
1562-
label = c.label
1563-
while c.refines is not None:
1564-
c = cases[find_case(c.refines, cases)]
1565-
label += '|' + c.label
1566-
return label
1567-
1568-
def find_case(label, cases):
1569-
matches = [i for i,c in enumerate(cases) if c.label == label]
1570-
assert(len(matches) <= 1)
1571-
if len(matches) == 1:
1572-
return matches[0]
1573-
return -1
1554+
return { c.label: None }
1555+
return { c.label: load(cx, ptr, c.t) }
15741556
```
15751557

15761558
Flags are converted from a bit-vector to a dictionary whose keys are
@@ -2023,12 +2005,13 @@ def store_record(cx, v, ptr, fields):
20232005
ptr += elem_size(f.t)
20242006
```
20252007

2026-
Variants are stored using the `|`-separated list of `refines` cases built
2027-
by `case_label_with_refinements` (above) to iteratively find a matching case (which
2028-
validation guarantees will succeed). While this code appears to do O(n) string
2029-
matching, a normal implementation can statically fuse `store_variant` with its
2030-
matching `load_variant` to ultimately build a dense array that maps producer's
2031-
case indices to the consumer's case indices.
2008+
Variant values are represented as Python dictionaries containing exactly one
2009+
entry whose key is the label of the lifted case and whose value is the
2010+
(optional) case payload. While this code appears to do an O(n) search of the
2011+
`variant` type for a matching case label, a normal implementation can
2012+
statically fuse `store_variant` with its matching `load_variant` to ultimately
2013+
build a dense array that maps producer's case indices to the consumer's case
2014+
indices.
20322015
```python
20332016
def store_variant(cx, v, ptr, cases):
20342017
case_index, case_value = match_case(v, cases)
@@ -2041,13 +2024,10 @@ def store_variant(cx, v, ptr, cases):
20412024
store(cx, case_value, c.t, ptr)
20422025

20432026
def match_case(v, cases):
2044-
assert(len(v.keys()) == 1)
2045-
key = list(v.keys())[0]
2046-
value = list(v.values())[0]
2047-
for label in key.split('|'):
2048-
case_index = find_case(label, cases)
2049-
if case_index != -1:
2050-
return (case_index, value)
2027+
[label] = v.keys()
2028+
[index] = [i for i,c in enumerate(cases) if c.label == label]
2029+
[value] = v.values()
2030+
return (index, value)
20512031
```
20522032

20532033
Flags are converted from a dictionary to a bit-vector by iterating
@@ -2414,7 +2394,7 @@ def lift_flat_variant(cx, vi, cases):
24142394
v = lift_flat(cx, CoerceValueIter(), c.t)
24152395
for have in flat_types:
24162396
_ = vi.next(have)
2417-
return { case_label_with_refinements(c, cases): v }
2397+
return { c.label: v }
24182398

24192399
def wrap_i64_to_i32(i):
24202400
assert(0 <= i < (1 << 64))

design/mvp/canonical-abi/definitions.py

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ class TupleType(ValType):
153153
class CaseType:
154154
label: str
155155
t: Optional[ValType]
156-
refines: Optional[str] = None
157156

158157
@dataclass
159158
class VariantType(ValType):
@@ -1080,24 +1079,9 @@ def load_variant(cx, ptr, cases):
10801079
trap_if(case_index >= len(cases))
10811080
c = cases[case_index]
10821081
ptr = align_to(ptr, max_case_alignment(cases))
1083-
case_label = case_label_with_refinements(c, cases)
10841082
if c.t is None:
1085-
return { case_label: None }
1086-
return { case_label: load(cx, ptr, c.t) }
1087-
1088-
def case_label_with_refinements(c, cases):
1089-
label = c.label
1090-
while c.refines is not None:
1091-
c = cases[find_case(c.refines, cases)]
1092-
label += '|' + c.label
1093-
return label
1094-
1095-
def find_case(label, cases):
1096-
matches = [i for i,c in enumerate(cases) if c.label == label]
1097-
assert(len(matches) <= 1)
1098-
if len(matches) == 1:
1099-
return matches[0]
1100-
return -1
1083+
return { c.label: None }
1084+
return { c.label: load(cx, ptr, c.t) }
11011085

11021086
def load_flags(cx, ptr, labels):
11031087
i = load_int(cx, ptr, elem_size_flags(labels))
@@ -1413,13 +1397,10 @@ def store_variant(cx, v, ptr, cases):
14131397
store(cx, case_value, c.t, ptr)
14141398

14151399
def match_case(v, cases):
1416-
assert(len(v.keys()) == 1)
1417-
key = list(v.keys())[0]
1418-
value = list(v.values())[0]
1419-
for label in key.split('|'):
1420-
case_index = find_case(label, cases)
1421-
if case_index != -1:
1422-
return (case_index, value)
1400+
[label] = v.keys()
1401+
[index] = [i for i,c in enumerate(cases) if c.label == label]
1402+
[value] = v.values()
1403+
return (index, value)
14231404

14241405
def store_flags(cx, v, ptr, labels):
14251406
i = pack_flags_into_int(v, labels)
@@ -1651,7 +1632,7 @@ def next(self, want):
16511632
v = lift_flat(cx, CoerceValueIter(), c.t)
16521633
for have in flat_types:
16531634
_ = vi.next(have)
1654-
return { case_label_with_refinements(c, cases): v }
1635+
return { c.label: v }
16551636

16561637
def wrap_i64_to_i32(i):
16571638
assert(0 <= i < (1 << 64))

design/mvp/canonical-abi/run_tests.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,11 @@ def test_name():
134134
test(t, [0, 42], {'ok':42})
135135
test(t, [1, 1000], {'error':1000})
136136
t = VariantType([CaseType('w',U8Type()),
137-
CaseType('x',U8Type(),'w'),
138-
CaseType('y',U8Type()),
139-
CaseType('z',U8Type(),'x')])
137+
CaseType('y',U8Type())])
140138
test(t, [0, 42], {'w':42})
141-
test(t, [1, 42], {'x|w':42})
142-
test(t, [2, 42], {'y':42})
143-
test(t, [3, 42], {'z|x|w':42})
139+
test(t, [1, 42], {'y':42})
144140
t2 = VariantType([CaseType('w',U8Type())])
145141
test(t, [0, 42], {'w':42}, lower_t=t2, lower_v={'w':42})
146-
test(t, [1, 42], {'x|w':42}, lower_t=t2, lower_v={'w':42})
147-
test(t, [3, 42], {'z|x|w':42}, lower_t=t2, lower_v={'w':42})
148142

149143
def test_pairs(t, pairs):
150144
for arg,expect in pairs:

0 commit comments

Comments
 (0)