Commit 4d906a96 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'selfhost'

parents d0af6118 05f3b5b5
...@@ -290,7 +290,7 @@ SRCS := $(MAIN_SRCS) $(STDLIB_SRCS) ...@@ -290,7 +290,7 @@ SRCS := $(MAIN_SRCS) $(STDLIB_SRCS)
STDLIB_OBJS := stdlib.bc.o stdlib.stripped.bc.o STDLIB_OBJS := stdlib.bc.o stdlib.stripped.bc.o
STDLIB_RELEASE_OBJS := stdlib.release.bc.o STDLIB_RELEASE_OBJS := stdlib.release.bc.o
STDMODULE_SRCS := errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c itertoolsmodule.c resource.c signalmodule.c $(EXTRA_STDMODULE_SRCS) STDMODULE_SRCS := errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c itertoolsmodule.c resource.c signalmodule.c selectmodule.c fcntlmodule.c $(EXTRA_STDMODULE_SRCS)
STDOBJECT_SRCS := structseq.c capsule.c stringobject.c $(EXTRA_STDOBJECT_SRCS) STDOBJECT_SRCS := structseq.c capsule.c stringobject.c $(EXTRA_STDOBJECT_SRCS)
STDPYTHON_SRCS := pyctype.c getargs.c formatter_string.c pystrtod.c dtoa.c $(EXTRA_STDPYTHON_SRCS) STDPYTHON_SRCS := pyctype.c getargs.c formatter_string.c pystrtod.c dtoa.c $(EXTRA_STDPYTHON_SRCS)
FROM_CPYTHON_SRCS := $(addprefix from_cpython/Modules/,$(STDMODULE_SRCS)) $(addprefix from_cpython/Objects/,$(STDOBJECT_SRCS)) $(addprefix from_cpython/Python/,$(STDPYTHON_SRCS)) FROM_CPYTHON_SRCS := $(addprefix from_cpython/Modules/,$(STDMODULE_SRCS)) $(addprefix from_cpython/Objects/,$(STDOBJECT_SRCS)) $(addprefix from_cpython/Python/,$(STDPYTHON_SRCS))
......
...@@ -15,7 +15,7 @@ endforeach(STDLIB_FILE) ...@@ -15,7 +15,7 @@ endforeach(STDLIB_FILE)
add_custom_target(copy_stdlib ALL DEPENDS ${STDLIB_TARGETS}) add_custom_target(copy_stdlib ALL DEPENDS ${STDLIB_TARGETS})
# compile specified files in from_cpython/Modules # compile specified files in from_cpython/Modules
file(GLOB_RECURSE STDMODULE_SRCS Modules errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c itertoolsmodule.c resource.c signalmodule.c) file(GLOB_RECURSE STDMODULE_SRCS Modules errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c itertoolsmodule.c resource.c signalmodule.c selectmodule.c fcntlmodule.c)
# compile specified files in from_cpython/Objects # compile specified files in from_cpython/Objects
file(GLOB_RECURSE STDOBJECT_SRCS Objects structseq.c capsule.c stringobject.c) file(GLOB_RECURSE STDOBJECT_SRCS Objects structseq.c capsule.c stringobject.c)
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#ifndef Py_PYCONFIG_H #ifndef Py_PYCONFIG_H
#define Py_PYCONFIG_H #define Py_PYCONFIG_H
#define _GNU_SOURCE 1
#define HAVE_STDARG_PROTOTYPES #define HAVE_STDARG_PROTOTYPES
#define HAVE_LONG_LONG 1 #define HAVE_LONG_LONG 1
#define PY_LONG_LONG long long #define PY_LONG_LONG long long
...@@ -41,6 +43,9 @@ ...@@ -41,6 +43,9 @@
#define HAVE_UINTPTR_T 1 #define HAVE_UINTPTR_T 1
#define HAVE_INT32_T 1 #define HAVE_INT32_T 1
#define HAVE_INT64_T 1 #define HAVE_INT64_T 1
#define HAVE_EPOLL 1
#define HAVE_POLL 1
#define HAVE_SELECT 1
#define PY_FORMAT_LONG_LONG "ll" #define PY_FORMAT_LONG_LONG "ll"
#define PY_FORMAT_SIZE_T "z" #define PY_FORMAT_SIZE_T "z"
......
...@@ -29,7 +29,8 @@ __all__ = [ ...@@ -29,7 +29,8 @@ __all__ = [
# Imports. # Imports.
import io as _io # Pyston change: don't import io
# import io as _io
import os as _os import os as _os
import errno as _errno import errno as _errno
from random import Random as _Random from random import Random as _Random
...@@ -197,8 +198,10 @@ def _get_default_tempdir(): ...@@ -197,8 +198,10 @@ def _get_default_tempdir():
fd = _os.open(filename, flags, 0o600) fd = _os.open(filename, flags, 0o600)
try: try:
try: try:
with _io.open(fd, 'wb', closefd=False) as fp: # Pyston change: simplify this so that it doesn't need the _io module:
fp.write(b'blat') _os.write(fd, b'blat')
# with _io.open(fd, 'wb', closefd=False) as fp:
# fp.write(b'blat')
finally: finally:
_os.close(fd) _os.close(fd)
finally: finally:
......
...@@ -278,6 +278,7 @@ public: ...@@ -278,6 +278,7 @@ public:
bool visit_raise(AST_Raise* node) override { return false; } bool visit_raise(AST_Raise* node) override { return false; }
bool visit_repr(AST_Repr* node) override { return false; } bool visit_repr(AST_Repr* node) override { return false; }
bool visit_return(AST_Return* node) override { return false; } bool visit_return(AST_Return* node) override { return false; }
bool visit_set(AST_Set* node) override { return false; }
bool visit_slice(AST_Slice* node) override { return false; } bool visit_slice(AST_Slice* node) override { return false; }
bool visit_str(AST_Str* node) override { return false; } bool visit_str(AST_Str* node) override { return false; }
bool visit_subscript(AST_Subscript* node) override { return false; } bool visit_subscript(AST_Subscript* node) override { return false; }
......
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include "llvm/Support/ErrorHandling.h" // For llvm_unreachable
#include "analysis/scoping_analysis.h" #include "analysis/scoping_analysis.h"
#include "core/ast.h" #include "core/ast.h"
#include "core/options.h" #include "core/options.h"
...@@ -2173,7 +2171,7 @@ public: ...@@ -2173,7 +2171,7 @@ public:
AST_expr* enter = makeLoadAttribute(makeName(ctxmgrname_buf, AST_TYPE::Load, node->lineno), "__enter__", true); AST_expr* enter = makeLoadAttribute(makeName(ctxmgrname_buf, AST_TYPE::Load, node->lineno), "__enter__", true);
AST_expr* exit = makeLoadAttribute(makeName(ctxmgrname_buf, AST_TYPE::Load, node->lineno), "__exit__", true); AST_expr* exit = makeLoadAttribute(makeName(ctxmgrname_buf, AST_TYPE::Load, node->lineno), "__exit__", true);
pushAssign(exitname_buf, exit); pushAssign(exitname_buf, exit);
enter = makeCall(enter); enter = remapExpr(makeCall(enter));
if (node->optional_vars) { if (node->optional_vars) {
pushAssign(node->optional_vars, enter); pushAssign(node->optional_vars, enter);
......
...@@ -493,7 +493,14 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) { ...@@ -493,7 +493,14 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
} }
BoxedString* str = static_cast<BoxedString*>(_str); BoxedString* str = static_cast<BoxedString*>(_str);
Box* rtn = getattrInternal(obj, str->s, NULL);
Box* rtn = NULL;
try {
rtn = getattrInternal(obj, str->s, NULL);
} catch (ExcInfo e) {
if (!e.matches(AttributeError))
throw e;
}
if (!rtn) { if (!rtn) {
if (default_value) if (default_value)
...@@ -528,7 +535,7 @@ Box* hasattr(Box* obj, Box* _str) { ...@@ -528,7 +535,7 @@ Box* hasattr(Box* obj, Box* _str) {
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (e.matches(Exception)) if (e.matches(Exception))
return False; return False;
throw; throw e;
} }
Box* rtn = attr ? True : False; Box* rtn = attr ? True : False;
......
// Copyright (c) 2014-2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/types.h"
namespace pyston {
Box* gcCollect() {
gc::runCollection();
return None;
}
void setupGC() {
BoxedModule* gc_module = createModule("gc", "__builtin__");
gc_module->giveAttr("__hex__", new BoxedFunction(boxRTFunction((void*)gcCollect, NONE, 0)));
}
}
...@@ -47,10 +47,29 @@ Box* startNewThread(Box* target, Box* args) { ...@@ -47,10 +47,29 @@ Box* startNewThread(Box* target, Box* args) {
static BoxedClass* thread_lock_cls; static BoxedClass* thread_lock_cls;
class BoxedThreadLock : public Box { class BoxedThreadLock : public Box {
private:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
public: public:
BoxedThreadLock() {} BoxedThreadLock() {}
DEFAULT_CLASS(thread_lock_cls); DEFAULT_CLASS(thread_lock_cls);
static Box* acquire(Box* _self) {
RELEASE_ASSERT(_self->cls == thread_lock_cls, "");
BoxedThreadLock* self = static_cast<BoxedThreadLock*>(_self);
pthread_mutex_lock(&self->lock);
return None;
}
static Box* release(Box* _self) {
RELEASE_ASSERT(_self->cls == thread_lock_cls, "");
BoxedThreadLock* self = static_cast<BoxedThreadLock*>(_self);
pthread_mutex_unlock(&self->lock);
return None;
}
}; };
Box* allocateLock() { Box* allocateLock() {
...@@ -71,6 +90,10 @@ void setupThread() { ...@@ -71,6 +90,10 @@ void setupThread() {
thread_lock_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedThreadLock), false); thread_lock_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedThreadLock), false);
thread_lock_cls->giveAttr("__name__", boxStrConstant("lock")); thread_lock_cls->giveAttr("__name__", boxStrConstant("lock"));
thread_lock_cls->giveAttr("__module__", boxStrConstant("thread")); thread_lock_cls->giveAttr("__module__", boxStrConstant("thread"));
thread_lock_cls->giveAttr("acquire", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::acquire, NONE, 1)));
thread_lock_cls->giveAttr("release", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::release, NONE, 1)));
thread_lock_cls->giveAttr("acquire_lock", thread_lock_cls->getattr("acquire"));
thread_lock_cls->giveAttr("release_lock", thread_lock_cls->getattr("release"));
thread_lock_cls->freeze(); thread_lock_cls->freeze();
BoxedClass* ThreadError BoxedClass* ThreadError
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include "Python.h" #include "Python.h"
#include "llvm/Support/ErrorHandling.h" // For llvm_unreachable
#include "capi/types.h" #include "capi/types.h"
#include "core/threading.h" #include "core/threading.h"
#include "core/types.h" #include "core/types.h"
...@@ -675,6 +677,11 @@ void setCAPIException(const ExcInfo& e) { ...@@ -675,6 +677,11 @@ void setCAPIException(const ExcInfo& e) {
cur_thread_state.curexc_traceback = e.traceback; cur_thread_state.curexc_traceback = e.traceback;
} }
void throwCAPIException() {
checkAndThrowCAPIException();
llvm_unreachable("No exception was thrown?");
}
void checkAndThrowCAPIException() { void checkAndThrowCAPIException() {
Box* _type = cur_thread_state.curexc_type; Box* _type = cur_thread_state.curexc_type;
if (!_type) if (!_type)
...@@ -1309,6 +1316,97 @@ extern "C" PyObject* _PyImport_FindExtension(char* name, char* filename) noexcep ...@@ -1309,6 +1316,97 @@ extern "C" PyObject* _PyImport_FindExtension(char* name, char* filename) noexcep
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
static PyObject* listmethodchain(PyMethodChain* chain) noexcept {
PyMethodChain* c;
PyMethodDef* ml;
int i, n;
PyObject* v;
n = 0;
for (c = chain; c != NULL; c = c->link) {
for (ml = c->methods; ml->ml_name != NULL; ml++)
n++;
}
v = PyList_New(n);
if (v == NULL)
return NULL;
i = 0;
for (c = chain; c != NULL; c = c->link) {
for (ml = c->methods; ml->ml_name != NULL; ml++) {
PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
i++;
}
}
if (PyErr_Occurred()) {
Py_DECREF(v);
return NULL;
}
PyList_Sort(v);
return v;
}
extern "C" PyObject* Py_FindMethodInChain(PyMethodChain* chain, PyObject* self, const char* name) noexcept {
if (name[0] == '_' && name[1] == '_') {
if (strcmp(name, "__methods__") == 0) {
if (PyErr_WarnPy3k("__methods__ not supported in 3.x", 1) < 0)
return NULL;
return listmethodchain(chain);
}
if (strcmp(name, "__doc__") == 0) {
const char* doc = self->cls->tp_doc;
if (doc != NULL)
return PyString_FromString(doc);
}
}
while (chain != NULL) {
PyMethodDef* ml = chain->methods;
for (; ml->ml_name != NULL; ml++) {
if (name[0] == ml->ml_name[0] && strcmp(name + 1, ml->ml_name + 1) == 0)
/* XXX */
return PyCFunction_New(ml, self);
}
chain = chain->link;
}
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
}
/* Find a method in a single method list */
extern "C" PyObject* Py_FindMethod(PyMethodDef* methods, PyObject* self, const char* name) noexcept {
PyMethodChain chain;
chain.methods = methods;
chain.link = NULL;
return Py_FindMethodInChain(&chain, self, name);
}
extern "C" PyObject* PyCFunction_NewEx(PyMethodDef* ml, PyObject* self, PyObject* module) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int _PyEval_SliceIndex(PyObject* v, Py_ssize_t* pi) noexcept {
if (v != NULL) {
Py_ssize_t x;
if (PyInt_Check(v)) {
/* XXX(nnorwitz): I think PyInt_AS_LONG is correct,
however, it looks like it should be AsSsize_t.
There should be a comment here explaining why.
*/
x = PyInt_AS_LONG(v);
} else if (PyIndex_Check(v)) {
x = PyNumber_AsSsize_t(v, NULL);
if (x == -1 && PyErr_Occurred())
return 0;
} else {
PyErr_SetString(PyExc_TypeError, "slice indices must be integers or "
"None or have an __index__ method");
return 0;
}
*pi = x;
}
return 1;
}
BoxedModule* importTestExtension(const std::string& name) { BoxedModule* importTestExtension(const std::string& name) {
std::string pathname_name = "test/test_extension/" + name + ".pyston.so"; std::string pathname_name = "test/test_extension/" + name + ".pyston.so";
const char* pathname = pathname_name.c_str(); const char* pathname = pathname_name.c_str();
......
...@@ -23,6 +23,7 @@ class BoxedModule; ...@@ -23,6 +23,7 @@ class BoxedModule;
BoxedModule* importTestExtension(const std::string&); BoxedModule* importTestExtension(const std::string&);
void checkAndThrowCAPIException(); void checkAndThrowCAPIException();
void throwCAPIException() __attribute__((noreturn));
struct ExcInfo; struct ExcInfo;
void setCAPIException(const ExcInfo& e); void setCAPIException(const ExcInfo& e);
} }
......
...@@ -284,6 +284,16 @@ Box* dictDelitem(BoxedDict* self, Box* k) { ...@@ -284,6 +284,16 @@ Box* dictDelitem(BoxedDict* self, Box* k) {
return None; return None;
} }
extern "C" int PyDict_DelItem(PyObject* op, PyObject* key) noexcept {
try {
dictDelitem((BoxedDict*)op, key);
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
return 0;
}
Box* dictPop(BoxedDict* self, Box* k, Box* d) { Box* dictPop(BoxedDict* self, Box* k, Box* d) {
if (!isSubclass(self->cls, dict_cls)) if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor 'pop' requires a 'dict' object but received a '%s'", raiseExcHelper(TypeError, "descriptor 'pop' requires a 'dict' object but received a '%s'",
......
...@@ -266,7 +266,40 @@ extern "C" int _PyFile_SanitizeMode(char* mode) noexcept { ...@@ -266,7 +266,40 @@ extern "C" int _PyFile_SanitizeMode(char* mode) noexcept {
} }
extern "C" int PyObject_AsFileDescriptor(PyObject* o) noexcept { extern "C" int PyObject_AsFileDescriptor(PyObject* o) noexcept {
Py_FatalError("unimplemented"); int fd;
PyObject* meth;
if (PyInt_Check(o)) {
fd = _PyInt_AsInt(o);
} else if (PyLong_Check(o)) {
fd = _PyLong_AsInt(o);
} else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL) {
PyObject* fno = PyEval_CallObject(meth, NULL);
Py_DECREF(meth);
if (fno == NULL)
return -1;
if (PyInt_Check(fno)) {
fd = _PyInt_AsInt(fno);
Py_DECREF(fno);
} else if (PyLong_Check(fno)) {
fd = _PyLong_AsInt(fno);
Py_DECREF(fno);
} else {
PyErr_SetString(PyExc_TypeError, "fileno() returned a non-integer");
Py_DECREF(fno);
return -1;
}
} else {
PyErr_SetString(PyExc_TypeError, "argument must be an int, or have a fileno() method.");
return -1;
}
if (fd < 0) {
PyErr_Format(PyExc_ValueError, "file descriptor cannot be a negative integer (%i)", fd);
return -1;
}
return fd;
} }
extern "C" int PyFile_SoftSpace(PyObject* f, int newflag) noexcept { extern "C" int PyFile_SoftSpace(PyObject* f, int newflag) noexcept {
......
...@@ -62,8 +62,15 @@ extern "C" PyAPI_FUNC(PyObject*) _PyInt_Format(PyIntObject* v, int base, int new ...@@ -62,8 +62,15 @@ extern "C" PyAPI_FUNC(PyObject*) _PyInt_Format(PyIntObject* v, int base, int new
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
extern "C" int _PyInt_AsInt(PyObject*) noexcept { extern "C" int _PyInt_AsInt(PyObject* obj) noexcept {
Py_FatalError("unimplemented"); long result = PyInt_AsLong(obj);
if (result == -1 && PyErr_Occurred())
return -1;
if (result > INT_MAX || result < INT_MIN) {
PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C int");
return -1;
}
return (int)result;
} }
BoxedInt* interned_ints[NUM_INTERNED_INTS]; BoxedInt* interned_ints[NUM_INTERNED_INTS];
......
...@@ -39,6 +39,10 @@ extern "C" int PyList_Append(PyObject* op, PyObject* newitem) noexcept { ...@@ -39,6 +39,10 @@ extern "C" int PyList_Append(PyObject* op, PyObject* newitem) noexcept {
return 0; return 0;
} }
extern "C" int PyList_SetItem(PyObject* op, Py_ssize_t i, PyObject* newitem) noexcept {
Py_FatalError("unimplemented");
}
extern "C" Box* listRepr(BoxedList* self) { extern "C" Box* listRepr(BoxedList* self) {
LOCK_REGION(self->lock.asRead()); LOCK_REGION(self->lock.asRead());
...@@ -428,6 +432,22 @@ Box* listSort1(BoxedList* self) { ...@@ -428,6 +432,22 @@ Box* listSort1(BoxedList* self) {
return None; return None;
} }
extern "C" int PyList_Sort(PyObject* v) noexcept {
if (v == NULL || !PyList_Check(v)) {
PyErr_BadInternalCall();
return -1;
}
try {
listSort1((BoxedList*)v);
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
return 0;
}
Box* listContains(BoxedList* self, Box* elt) { Box* listContains(BoxedList* self, Box* elt) {
LOCK_REGION(self->lock.asRead()); LOCK_REGION(self->lock.asRead());
......
...@@ -66,6 +66,18 @@ extern "C" unsigned PY_LONG_LONG PyLong_AsUnsignedLongLong(PyObject* vv) noexcep ...@@ -66,6 +66,18 @@ extern "C" unsigned PY_LONG_LONG PyLong_AsUnsignedLongLong(PyObject* vv) noexcep
return bytes; return bytes;
} }
extern "C" int _PyLong_AsInt(PyObject* obj) noexcept {
int overflow;
long result = PyLong_AsLongAndOverflow(obj, &overflow);
if (overflow || result > INT_MAX || result < INT_MIN) {
/* XXX: could be cute and give a different
message for overflow == -1 */
PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C int");
return -1;
}
return (int)result;
}
extern "C" unsigned long PyLong_AsUnsignedLongMask(PyObject* op) noexcept { extern "C" unsigned long PyLong_AsUnsignedLongMask(PyObject* op) noexcept {
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
......
...@@ -1494,7 +1494,9 @@ Box* strContains(BoxedString* self, Box* elt) { ...@@ -1494,7 +1494,9 @@ Box* strContains(BoxedString* self, Box* elt) {
return True; return True;
} }
Box* strStartswith(BoxedString* self, Box* elt) { Box* strStartswith(BoxedString* self, Box* elt, Box* start, Box** _args) {
Box* end = _args[0];
if (self->cls != str_cls) if (self->cls != str_cls)
raiseExcHelper(TypeError, "descriptor 'startswith' requires a 'str' object but received a '%s'", raiseExcHelper(TypeError, "descriptor 'startswith' requires a 'str' object but received a '%s'",
getTypeName(self)->c_str()); getTypeName(self)->c_str());
...@@ -1502,12 +1504,44 @@ Box* strStartswith(BoxedString* self, Box* elt) { ...@@ -1502,12 +1504,44 @@ Box* strStartswith(BoxedString* self, Box* elt) {
if (elt->cls != str_cls) if (elt->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object"); raiseExcHelper(TypeError, "expected a character buffer object");
Py_ssize_t istart = 0, iend = PY_SSIZE_T_MAX;
if (start) {
int r = _PyEval_SliceIndex(start, &istart);
if (!r)
throwCAPIException();
}
if (end) {
int r = _PyEval_SliceIndex(end, &iend);
if (!r)
throwCAPIException();
}
BoxedString* sub = static_cast<BoxedString*>(elt); BoxedString* sub = static_cast<BoxedString*>(elt);
return boxBool(startswith(self->s, sub->s)); Py_ssize_t n = self->s.size();
iend = std::min(iend, n);
if (iend < 0)
iend += n;
if (iend < 0)
iend = 0;
if (istart < 0)
istart += n;
if (istart < 0)
istart = 0;
Py_ssize_t compare_len = iend - istart;
if (compare_len < 0)
return False;
if (sub->s.size() > compare_len)
return False;
return boxBool(self->s.compare(istart, sub->s.size(), sub->s) == 0);
} }
Box* strEndswith(BoxedString* self, Box* elt) { Box* strEndswith(BoxedString* self, Box* elt, Box* start, Box** _args) {
Box* end = _args[0];
if (self->cls != str_cls) if (self->cls != str_cls)
raiseExcHelper(TypeError, "descriptor 'endswith' requires a 'str' object but received a '%s'", raiseExcHelper(TypeError, "descriptor 'endswith' requires a 'str' object but received a '%s'",
getTypeName(self)->c_str()); getTypeName(self)->c_str());
...@@ -1515,9 +1549,41 @@ Box* strEndswith(BoxedString* self, Box* elt) { ...@@ -1515,9 +1549,41 @@ Box* strEndswith(BoxedString* self, Box* elt) {
if (elt->cls != str_cls) if (elt->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object"); raiseExcHelper(TypeError, "expected a character buffer object");
Py_ssize_t istart = 0, iend = PY_SSIZE_T_MAX;
if (start) {
int r = _PyEval_SliceIndex(start, &istart);
if (!r)
throwCAPIException();
}
if (end) {
int r = _PyEval_SliceIndex(end, &iend);
if (!r)
throwCAPIException();
}
BoxedString* sub = static_cast<BoxedString*>(elt); BoxedString* sub = static_cast<BoxedString*>(elt);
return boxBool(endswith(self->s, sub->s)); Py_ssize_t n = self->s.size();
iend = std::min(iend, n);
if (iend < 0)
iend += n;
if (iend < 0)
iend = 0;
if (istart < 0)
istart += n;
if (istart < 0)
istart = 0;
Py_ssize_t compare_len = iend - istart;
if (compare_len < 0)
return False;
if (sub->s.size() > compare_len)
return False;
// XXX: this line is the only difference between startswith and endswith:
istart += compare_len - sub->s.size();
return boxBool(self->s.compare(istart, sub->s.size(), sub->s) == 0);
} }
Box* strFind(BoxedString* self, Box* elt, Box* _start) { Box* strFind(BoxedString* self, Box* elt, Box* _start) {
...@@ -1790,8 +1856,10 @@ void setupStr() { ...@@ -1790,8 +1856,10 @@ void setupStr() {
str_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)strContains, BOXED_BOOL, 2))); str_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)strContains, BOXED_BOOL, 2)));
str_cls->giveAttr("startswith", new BoxedFunction(boxRTFunction((void*)strStartswith, BOXED_BOOL, 2))); str_cls->giveAttr("startswith",
str_cls->giveAttr("endswith", new BoxedFunction(boxRTFunction((void*)strEndswith, BOXED_BOOL, 2))); new BoxedFunction(boxRTFunction((void*)strStartswith, BOXED_BOOL, 4, 2, 0, 0), { NULL, NULL }));
str_cls->giveAttr("endswith",
new BoxedFunction(boxRTFunction((void*)strEndswith, BOXED_BOOL, 4, 2, 0, 0), { NULL, NULL }));
str_cls->giveAttr("find", str_cls->giveAttr("find",
new BoxedFunction(boxRTFunction((void*)strFind, BOXED_INT, 3, 1, false, false), { boxInt(0) })); new BoxedFunction(boxRTFunction((void*)strFind, BOXED_INT, 3, 1, false, false), { boxInt(0) }));
......
...@@ -54,9 +54,13 @@ extern "C" void init_collections(); ...@@ -54,9 +54,13 @@ extern "C" void init_collections();
extern "C" void inititertools(); extern "C" void inititertools();
extern "C" void initresource(); extern "C" void initresource();
extern "C" void initsignal(); extern "C" void initsignal();
extern "C" void initselect();
extern "C" void initfcntl();
namespace pyston { namespace pyston {
void setupGC();
bool IN_SHUTDOWN = false; bool IN_SHUTDOWN = false;
#define SLICE_START_OFFSET ((char*)&(((BoxedSlice*)0x01)->start) - (char*)0x1) #define SLICE_START_OFFSET ((char*)&(((BoxedSlice*)0x01)->start) - (char*)0x1)
...@@ -1161,6 +1165,7 @@ void setupRuntime() { ...@@ -1161,6 +1165,7 @@ void setupRuntime() {
setupBuiltins(); setupBuiltins();
setupTime(); setupTime();
setupThread(); setupThread();
setupGC();
setupCAPI(); setupCAPI();
...@@ -1185,6 +1190,8 @@ void setupRuntime() { ...@@ -1185,6 +1190,8 @@ void setupRuntime() {
inititertools(); inititertools();
initresource(); initresource();
initsignal(); initsignal();
initselect();
initfcntl();
setupSysEnd(); setupSysEnd();
......
import fcntl
for k in sorted(dir(fcntl)):
if k[0] == '_' or k != k.upper():
continue
print k, getattr(fcntl, k)
import select
for k in sorted(dir(select)):
if not k.startswith("EPOLL") and not k.startswith("POLL"):
continue
print k, getattr(select, k)
...@@ -59,3 +59,7 @@ s = set(range(5)) ...@@ -59,3 +59,7 @@ s = set(range(5))
print len(s) print len(s)
s.clear() s.clear()
print s print s
def f2():
print {5}
f2()
...@@ -81,3 +81,8 @@ print "hello world"[False:True:True] ...@@ -81,3 +81,8 @@ print "hello world"[False:True:True]
print "{hello}".format(hello="world") print "{hello}".format(hello="world")
print "%.3s" % "hello world" print "%.3s" % "hello world"
for i in xrange(-5, 15):
for j in xrange(-5, 15):
print i, j, "banana".startswith("ana", i, j), "banana".endswith("ana", i, j)
# allow-warning: converting unicode literal to str
import os
import tempfile
fd, dirname = tempfile.mkstemp()
print type(fd), type(dirname)
print os.path.exists(dirname)
os.unlink(dirname)
print os.path.exists(dirname)
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