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)
STDLIB_OBJS := stdlib.bc.o stdlib.stripped.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)
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))
......
......@@ -15,7 +15,7 @@ endforeach(STDLIB_FILE)
add_custom_target(copy_stdlib ALL DEPENDS ${STDLIB_TARGETS})
# 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
file(GLOB_RECURSE STDOBJECT_SRCS Objects structseq.c capsule.c stringobject.c)
......
......@@ -17,6 +17,8 @@
#ifndef Py_PYCONFIG_H
#define Py_PYCONFIG_H
#define _GNU_SOURCE 1
#define HAVE_STDARG_PROTOTYPES
#define HAVE_LONG_LONG 1
#define PY_LONG_LONG long long
......@@ -41,6 +43,9 @@
#define HAVE_UINTPTR_T 1
#define HAVE_INT32_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_SIZE_T "z"
......
......@@ -29,7 +29,8 @@ __all__ = [
# Imports.
import io as _io
# Pyston change: don't import io
# import io as _io
import os as _os
import errno as _errno
from random import Random as _Random
......@@ -197,8 +198,10 @@ def _get_default_tempdir():
fd = _os.open(filename, flags, 0o600)
try:
try:
with _io.open(fd, 'wb', closefd=False) as fp:
fp.write(b'blat')
# Pyston change: simplify this so that it doesn't need the _io module:
_os.write(fd, b'blat')
# with _io.open(fd, 'wb', closefd=False) as fp:
# fp.write(b'blat')
finally:
_os.close(fd)
finally:
......
......@@ -278,6 +278,7 @@ public:
bool visit_raise(AST_Raise* node) override { return false; }
bool visit_repr(AST_Repr* 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_str(AST_Str* node) override { return false; }
bool visit_subscript(AST_Subscript* node) override { return false; }
......
......@@ -19,8 +19,6 @@
#include <cstdio>
#include <cstdlib>
#include "llvm/Support/ErrorHandling.h" // For llvm_unreachable
#include "analysis/scoping_analysis.h"
#include "core/ast.h"
#include "core/options.h"
......@@ -2173,7 +2171,7 @@ public:
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);
pushAssign(exitname_buf, exit);
enter = makeCall(enter);
enter = remapExpr(makeCall(enter));
if (node->optional_vars) {
pushAssign(node->optional_vars, enter);
......
......@@ -493,7 +493,14 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
}
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 (default_value)
......@@ -528,7 +535,7 @@ Box* hasattr(Box* obj, Box* _str) {
} catch (ExcInfo e) {
if (e.matches(Exception))
return False;
throw;
throw e;
}
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) {
static BoxedClass* thread_lock_cls;
class BoxedThreadLock : public Box {
private:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
public:
BoxedThreadLock() {}
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() {
......@@ -71,6 +90,10 @@ void setupThread() {
thread_lock_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedThreadLock), false);
thread_lock_cls->giveAttr("__name__", boxStrConstant("lock"));
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();
BoxedClass* ThreadError
......
......@@ -19,6 +19,8 @@
#include "Python.h"
#include "llvm/Support/ErrorHandling.h" // For llvm_unreachable
#include "capi/types.h"
#include "core/threading.h"
#include "core/types.h"
......@@ -675,6 +677,11 @@ void setCAPIException(const ExcInfo& e) {
cur_thread_state.curexc_traceback = e.traceback;
}
void throwCAPIException() {
checkAndThrowCAPIException();
llvm_unreachable("No exception was thrown?");
}
void checkAndThrowCAPIException() {
Box* _type = cur_thread_state.curexc_type;
if (!_type)
......@@ -1309,6 +1316,97 @@ extern "C" PyObject* _PyImport_FindExtension(char* name, char* filename) noexcep
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) {
std::string pathname_name = "test/test_extension/" + name + ".pyston.so";
const char* pathname = pathname_name.c_str();
......
......@@ -23,6 +23,7 @@ class BoxedModule;
BoxedModule* importTestExtension(const std::string&);
void checkAndThrowCAPIException();
void throwCAPIException() __attribute__((noreturn));
struct ExcInfo;
void setCAPIException(const ExcInfo& e);
}
......
......@@ -284,6 +284,16 @@ Box* dictDelitem(BoxedDict* self, Box* k) {
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) {
if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor 'pop' requires a 'dict' object but received a '%s'",
......
......@@ -266,7 +266,40 @@ extern "C" int _PyFile_SanitizeMode(char* mode) 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 {
......
......@@ -62,8 +62,15 @@ extern "C" PyAPI_FUNC(PyObject*) _PyInt_Format(PyIntObject* v, int base, int new
Py_FatalError("unimplemented");
}
extern "C" int _PyInt_AsInt(PyObject*) noexcept {
Py_FatalError("unimplemented");
extern "C" int _PyInt_AsInt(PyObject* obj) noexcept {
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];
......
......@@ -39,6 +39,10 @@ extern "C" int PyList_Append(PyObject* op, PyObject* newitem) noexcept {
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) {
LOCK_REGION(self->lock.asRead());
......@@ -428,6 +432,22 @@ Box* listSort1(BoxedList* self) {
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) {
LOCK_REGION(self->lock.asRead());
......
......@@ -66,6 +66,18 @@ extern "C" unsigned PY_LONG_LONG PyLong_AsUnsignedLongLong(PyObject* vv) noexcep
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 {
Py_FatalError("unimplemented");
}
......
......@@ -1494,7 +1494,9 @@ Box* strContains(BoxedString* self, Box* elt) {
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)
raiseExcHelper(TypeError, "descriptor 'startswith' requires a 'str' object but received a '%s'",
getTypeName(self)->c_str());
......@@ -1502,12 +1504,44 @@ Box* strStartswith(BoxedString* self, Box* elt) {
if (elt->cls != str_cls)
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);
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)
raiseExcHelper(TypeError, "descriptor 'endswith' requires a 'str' object but received a '%s'",
getTypeName(self)->c_str());
......@@ -1515,9 +1549,41 @@ Box* strEndswith(BoxedString* self, Box* elt) {
if (elt->cls != str_cls)
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);
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) {
......@@ -1790,8 +1856,10 @@ void setupStr() {
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("endswith", new BoxedFunction(boxRTFunction((void*)strEndswith, BOXED_BOOL, 2)));
str_cls->giveAttr("startswith",
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",
new BoxedFunction(boxRTFunction((void*)strFind, BOXED_INT, 3, 1, false, false), { boxInt(0) }));
......
......@@ -54,9 +54,13 @@ extern "C" void init_collections();
extern "C" void inititertools();
extern "C" void initresource();
extern "C" void initsignal();
extern "C" void initselect();
extern "C" void initfcntl();
namespace pyston {
void setupGC();
bool IN_SHUTDOWN = false;
#define SLICE_START_OFFSET ((char*)&(((BoxedSlice*)0x01)->start) - (char*)0x1)
......@@ -1161,6 +1165,7 @@ void setupRuntime() {
setupBuiltins();
setupTime();
setupThread();
setupGC();
setupCAPI();
......@@ -1185,6 +1190,8 @@ void setupRuntime() {
inititertools();
initresource();
initsignal();
initselect();
initfcntl();
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))
print len(s)
s.clear()
print s
def f2():
print {5}
f2()
......@@ -81,3 +81,8 @@ print "hello world"[False:True:True]
print "{hello}".format(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