Commit d450c321 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Implement ord() and string iteration

parent 3691c258
...@@ -931,9 +931,9 @@ public: ...@@ -931,9 +931,9 @@ public:
if (cls->is_constant && !cls->hasattrs && cls->hasGenericGetattr()) { if (cls->is_constant && !cls->hasattrs && cls->hasGenericGetattr()) {
Box* rtattr = cls->peekattr(*attr); Box* rtattr = cls->peekattr(*attr);
if (rtattr == NULL) { if (rtattr == NULL) {
llvm::CallSite call llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
= emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr, getStringConstantPtr(*getNameOfClass(cls) + "\0"),
getStringConstantPtr(debugName() + '\0'), getStringConstantPtr(*attr + '\0')); getStringConstantPtr(*attr + '\0'));
call.setDoesNotReturn(); call.setDoesNotReturn();
return undefVariable(); return undefVariable();
} }
......
...@@ -161,6 +161,18 @@ extern "C" Box* chr(Box* arg) { ...@@ -161,6 +161,18 @@ extern "C" Box* chr(Box* arg) {
return boxString(std::string(1, (char)n)); return boxString(std::string(1, (char)n));
} }
extern "C" Box* ord(Box* arg) {
if (arg->cls != str_cls) {
raiseExcHelper(TypeError, "ord() expected string of length 1, but %s found", getTypeName(arg)->c_str());
}
const std::string& s = static_cast<BoxedString*>(arg)->s;
if (s.size() != 1)
raiseExcHelper(TypeError, "ord() expected string of length 1, but string of length %d found", s.size());
return boxInt(s[0]);
}
Box* range1(Box* end) { Box* range1(Box* end) {
RELEASE_ASSERT(end->cls == int_cls, "%s", getTypeName(end)->c_str()); RELEASE_ASSERT(end->cls == int_cls, "%s", getTypeName(end)->c_str());
...@@ -396,6 +408,8 @@ void setupBuiltins() { ...@@ -396,6 +408,8 @@ void setupBuiltins() {
chr_obj = new BoxedFunction(boxRTFunction((void*)chr, NULL, 1, false)); chr_obj = new BoxedFunction(boxRTFunction((void*)chr, NULL, 1, false));
builtins_module->giveAttr("chr", chr_obj); builtins_module->giveAttr("chr", chr_obj);
ord_obj = new BoxedFunction(boxRTFunction((void*)ord, NULL, 1, false));
builtins_module->giveAttr("ord", ord_obj);
trap_obj = new BoxedFunction(boxRTFunction((void*)trap, NULL, 0, false)); trap_obj = new BoxedFunction(boxRTFunction((void*)trap, NULL, 0, false));
builtins_module->giveAttr("trap", trap_obj); builtins_module->giveAttr("trap", trap_obj);
......
...@@ -452,7 +452,61 @@ extern "C" Box* strGetitem(BoxedString* self, Box* slice) { ...@@ -452,7 +452,61 @@ extern "C" Box* strGetitem(BoxedString* self, Box* slice) {
} }
} }
// TODO it looks like strings don't have their own iterators, but instead
// rely on the sequence iteration protocol.
// Should probably implement that, and maybe once that's implemented get
// rid of the striterator class?
BoxedClass* str_iterator_cls = NULL;
extern "C" void strIteratorGCHandler(GCVisitor* v, void* p);
extern "C" const ObjectFlavor str_iterator_flavor(&strIteratorGCHandler, NULL);
class BoxedStringIterator : public Box {
public:
BoxedString* s;
std::string::const_iterator it, end;
BoxedStringIterator(BoxedString* s) : Box(&str_iterator_flavor, str_iterator_cls), s(s), it(s->s.begin()), end(s->s.end()) {}
static bool hasnextUnboxed(BoxedStringIterator* self) {
assert(self->cls == str_iterator_cls);
return self->it != self->end;
}
static Box* hasnext(BoxedStringIterator* self) {
assert(self->cls == str_iterator_cls);
return boxBool(self->it != self->end);
}
static Box* next(BoxedStringIterator* self) {
assert(self->cls == str_iterator_cls);
assert(hasnextUnboxed(self));
char c = *self->it;
++self->it;
return new BoxedString(std::string(1, c));
}
};
extern "C" void strIteratorGCHandler(GCVisitor* v, void* p) {
boxGCHandler(v, p);
BoxedStringIterator* it = (BoxedStringIterator*)p;
v->visit(it->s);
}
Box* strIter(BoxedString* self) {
assert(self->cls == str_cls);
return new BoxedStringIterator(self);
}
void setupStr() { void setupStr() {
str_iterator_cls = new BoxedClass(false, false);
str_iterator_cls->giveAttr("__name__", boxStrConstant("striterator"));
str_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, NULL, 1, false)));
str_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::next, STR, 1, false)));
str_iterator_cls->freeze();
str_cls->giveAttr("__name__", boxStrConstant("str")); str_cls->giveAttr("__name__", boxStrConstant("str"));
str_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)strLen, NULL, 1, false))); str_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)strLen, NULL, 1, false)));
...@@ -471,6 +525,8 @@ void setupStr() { ...@@ -471,6 +525,8 @@ void setupStr() {
str_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)strEq, NULL, 2, false))); str_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)strEq, NULL, 2, false)));
str_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)strGetitem, NULL, 2, false))); str_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)strGetitem, NULL, 2, false)));
str_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)strIter, typeFromClass(str_iterator_cls), 1, false)));
str_cls->giveAttr("join", new BoxedFunction(boxRTFunction((void*)strJoin, NULL, 2, false))); str_cls->giveAttr("join", new BoxedFunction(boxRTFunction((void*)strJoin, NULL, 2, false)));
CLFunction* strSplit = boxRTFunction((void*)strSplit1, LIST, 1, false); CLFunction* strSplit = boxRTFunction((void*)strSplit1, LIST, 1, false);
......
...@@ -272,6 +272,8 @@ extern "C" BoxedString* functionRepr(BoxedFunction* v) { ...@@ -272,6 +272,8 @@ extern "C" BoxedString* functionRepr(BoxedFunction* v) {
return boxStrConstant("<built-in function open>"); return boxStrConstant("<built-in function open>");
if (v == chr_obj) if (v == chr_obj)
return boxStrConstant("<built-in function chr>"); return boxStrConstant("<built-in function chr>");
if (v == ord_obj)
return boxStrConstant("<built-in function ord>");
return new BoxedString("function"); return new BoxedString("function");
} }
...@@ -286,6 +288,7 @@ Box* min_obj = NULL; ...@@ -286,6 +288,7 @@ Box* min_obj = NULL;
Box* max_obj = NULL; Box* max_obj = NULL;
Box* open_obj = NULL; Box* open_obj = NULL;
Box* chr_obj = NULL; Box* chr_obj = NULL;
Box* ord_obj = NULL;
Box* trap_obj = NULL; Box* trap_obj = NULL;
Box* range_obj = NULL; Box* range_obj = NULL;
} }
......
...@@ -71,7 +71,7 @@ extern "C" { extern const ObjectFlavor user_flavor; } ...@@ -71,7 +71,7 @@ extern "C" { extern const ObjectFlavor user_flavor; }
extern "C" { extern Box* None, *NotImplemented, *True, *False; } extern "C" { extern Box* None, *NotImplemented, *True, *False; }
extern "C" { extern "C" {
extern Box* repr_obj, *len_obj, *hash_obj, *range_obj, *abs_obj, *min_obj, *max_obj, *open_obj, *chr_obj, *trap_obj; extern Box* repr_obj, *len_obj, *hash_obj, *range_obj, *abs_obj, *min_obj, *max_obj, *open_obj, *chr_obj, *ord_obj, *trap_obj;
} // these are only needed for functionRepr, which is hacky } // these are only needed for functionRepr, which is hacky
extern "C" { extern BoxedModule* sys_module, *math_module, *time_module, *builtins_module; } extern "C" { extern BoxedModule* sys_module, *math_module, *time_module, *builtins_module; }
......
...@@ -24,3 +24,7 @@ print repr(" \t\n\v\ftest \t\n\v\f".strip()) ...@@ -24,3 +24,7 @@ print repr(" \t\n\v\ftest \t\n\v\f".strip())
for pattern in ["hello", "o w", "nope"]: for pattern in ["hello", "o w", "nope"]:
print pattern in "hello world" print pattern in "hello world"
print ord("\a")
for c in "hello world":
print repr(c), ord(c)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment