Skip to content

Commit 37d7e0a

Browse files
Chore: Use a binary table to search using O(log n) for attr.
1 parent 87992e9 commit 37d7e0a

1 file changed

Lines changed: 57 additions & 50 deletions

File tree

  • compiler/src/modules/vm/handlers
Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,75 @@
1-
// vm/handlers/attr.rs
2-
31
use super::*;
42
use crate::modules::vm::types::BuiltinMethodId;
53

4+
type AttrRow = (&'static str, &'static str, BuiltinMethodId);
5+
6+
// Table of built-in methods organized by (type, attribute_name). It must be kept in lexicographical order to allow binary search.
7+
static ATTR_TABLE: &[AttrRow] = &[
8+
("dict", "get", BuiltinMethodId::DictGet),
9+
("dict", "items", BuiltinMethodId::DictItems),
10+
("dict", "keys", BuiltinMethodId::DictKeys),
11+
("dict", "pop", BuiltinMethodId::DictPop),
12+
("dict", "setdefault", BuiltinMethodId::DictSetDefault),
13+
("dict", "update", BuiltinMethodId::DictUpdate),
14+
("dict", "values", BuiltinMethodId::DictValues),
15+
("list", "append", BuiltinMethodId::ListAppend),
16+
("list", "clear", BuiltinMethodId::ListClear),
17+
("list", "copy", BuiltinMethodId::ListCopy),
18+
("list", "count", BuiltinMethodId::ListCount),
19+
("list", "extend", BuiltinMethodId::ListExtend),
20+
("list", "index", BuiltinMethodId::ListIndex),
21+
("list", "insert", BuiltinMethodId::ListInsert),
22+
("list", "pop", BuiltinMethodId::ListPop),
23+
("list", "remove", BuiltinMethodId::ListRemove),
24+
("list", "reverse", BuiltinMethodId::ListReverse),
25+
("list", "sort", BuiltinMethodId::ListSort),
26+
("str", "capitalize", BuiltinMethodId::StrCapitalize),
27+
("str", "center", BuiltinMethodId::StrCenter),
28+
("str", "count", BuiltinMethodId::StrCount),
29+
("str", "endswith", BuiltinMethodId::StrEndswith),
30+
("str", "find", BuiltinMethodId::StrFind),
31+
("str", "isalnum", BuiltinMethodId::StrIsAlnum),
32+
("str", "isalpha", BuiltinMethodId::StrIsAlpha),
33+
("str", "isdigit", BuiltinMethodId::StrIsDigit),
34+
("str", "join", BuiltinMethodId::StrJoin),
35+
("str", "lower", BuiltinMethodId::StrLower),
36+
("str", "lstrip", BuiltinMethodId::StrLstrip),
37+
("str", "replace", BuiltinMethodId::StrReplace),
38+
("str", "rstrip", BuiltinMethodId::StrRstrip),
39+
("str", "split", BuiltinMethodId::StrSplit),
40+
("str", "startswith", BuiltinMethodId::StrStartswith),
41+
("str", "strip", BuiltinMethodId::StrStrip),
42+
("str", "title", BuiltinMethodId::StrTitle),
43+
("str", "upper", BuiltinMethodId::StrUpper),
44+
("str", "zfill", BuiltinMethodId::StrZfill),
45+
];
46+
47+
#[inline]
48+
fn lookup_attr(ty: &str, attr: &str) -> Option<BuiltinMethodId> {
49+
ATTR_TABLE.binary_search_by(|&(t, a, _)| { t.cmp(ty).then_with(|| a.cmp(attr))})
50+
.ok()
51+
.map(|i| ATTR_TABLE[i].2)
52+
}
53+
654
impl<'a> VM<'a> {
7-
/// Resolves `obj.name` for builtin types. Pops `obj`, pushes a bound
8-
/// method or returns Err if the attribute is unknown for the type.
955
pub(crate) fn handle_load_attr(&mut self, name_idx: u16, chunk: &SSAChunk) -> Result<(), VmErr> {
10-
let name = chunk.names.get(name_idx as usize)
11-
.ok_or(VmErr::Runtime("LoadAttr: bad name index"))?;
56+
let name = chunk.names.get(name_idx as usize).ok_or(VmErr::Runtime("LoadAttr: bad name index"))?;
57+
1258
let obj = self.pop()?;
59+
let ty = self.type_name(obj);
1360

14-
let method_id = match (self.type_name(obj), name.as_str()) {
15-
("list", "append") => BuiltinMethodId::ListAppend,
16-
("dict", "keys") => BuiltinMethodId::DictKeys,
17-
("dict", "values") => BuiltinMethodId::DictValues,
18-
("dict", "items") => BuiltinMethodId::DictItems,
19-
("str", "upper") => BuiltinMethodId::StrUpper,
20-
("str", "lower") => BuiltinMethodId::StrLower,
21-
("str", "strip") => BuiltinMethodId::StrStrip,
22-
("str", "split") => BuiltinMethodId::StrSplit,
23-
("str", "join") => BuiltinMethodId::StrJoin,
24-
("str", "replace") => BuiltinMethodId::StrReplace,
25-
("str", "startswith") => BuiltinMethodId::StrStartswith,
26-
("str", "endswith") => BuiltinMethodId::StrEndswith,
27-
("str", "find") => BuiltinMethodId::StrFind,
28-
("str", "count") => BuiltinMethodId::StrCount,
29-
("list", "sort") => BuiltinMethodId::ListSort,
30-
("list", "reverse") => BuiltinMethodId::ListReverse,
31-
("list", "pop") => BuiltinMethodId::ListPop,
32-
("list", "insert") => BuiltinMethodId::ListInsert,
33-
("list", "remove") => BuiltinMethodId::ListRemove,
34-
("list", "index") => BuiltinMethodId::ListIndex,
35-
("list", "count") => BuiltinMethodId::ListCount,
36-
("dict", "get") => BuiltinMethodId::DictGet,
37-
("dict", "update") => BuiltinMethodId::DictUpdate,
38-
("dict", "pop") => BuiltinMethodId::DictPop,
39-
("dict", "setdefault") => BuiltinMethodId::DictSetDefault,
40-
("str", "lstrip") => BuiltinMethodId::StrLstrip,
41-
("str", "rstrip") => BuiltinMethodId::StrRstrip,
42-
("str", "isdigit") => BuiltinMethodId::StrIsDigit,
43-
("str", "isalpha") => BuiltinMethodId::StrIsAlpha,
44-
("str", "isalnum") => BuiltinMethodId::StrIsAlnum,
45-
("str", "capitalize") => BuiltinMethodId::StrCapitalize,
46-
("str", "title") => BuiltinMethodId::StrTitle,
47-
("str", "center") => BuiltinMethodId::StrCenter,
48-
("str", "zfill") => BuiltinMethodId::StrZfill,
49-
("list", "extend") => BuiltinMethodId::ListExtend,
50-
("list", "clear") => BuiltinMethodId::ListClear,
51-
("list", "copy") => BuiltinMethodId::ListCopy,
52-
(ty, attr) => {
53-
return Err(attr_not_found(ty, attr));
54-
}
55-
};
61+
// Binary search using O(log n)
62+
let method_id = lookup_attr(ty, name.as_str()).ok_or_else(|| attr_not_found(ty, name.as_str()))?;
5663

5764
let bound = self.heap.alloc(HeapObj::BoundMethod(obj, method_id))?;
5865
self.push(bound);
66+
5967
Ok(())
6068
}
6169
}
6270

6371
#[cold]
6472
fn attr_not_found(ty: &str, attr: &str) -> VmErr {
65-
// Static message keeps VmErr::Type's &'static str contract.
66-
let _ = (ty, attr); // params kept for future expansion
73+
let _ = (ty, attr);
6774
VmErr::Type("'object' has no attribute")
6875
}

0 commit comments

Comments
 (0)