Commit 087f7771 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'selfhost'

parents f8746677 18741a0c
...@@ -31,6 +31,8 @@ TEST_THREADS := 1 ...@@ -31,6 +31,8 @@ TEST_THREADS := 1
ERROR_LIMIT := 10 ERROR_LIMIT := 10
COLOR := 1 COLOR := 1
SELF_HOST := 0
VERBOSE := 0 VERBOSE := 0
ENABLE_INTEL_JIT_EVENTS := 0 ENABLE_INTEL_JIT_EVENTS := 0
...@@ -48,6 +50,14 @@ NINJA := ninja ...@@ -48,6 +50,14 @@ NINJA := ninja
-include Makefile.local -include Makefile.local
ifneq ($(SELF_HOST),1)
PYTHON := python
PYTHON_EXE_DEPS :=
else
PYTHON := $(abspath ./pyston_dbg)
PYTHON_EXE_DEPS := pyston_dbg
endif
TOOLS_DIR := ./tools TOOLS_DIR := ./tools
TEST_DIR := ./test TEST_DIR := ./test
TESTS_DIR := ./test/tests TESTS_DIR := ./test/tests
...@@ -368,11 +378,11 @@ analyze: ...@@ -368,11 +378,11 @@ analyze:
$(MAKE) pyston_dbg USE_DISTCC=0 USE_CCACHE=0 $(MAKE) pyston_dbg USE_DISTCC=0 USE_CCACHE=0
.PHONY: lint cpplint .PHONY: lint cpplint
lint: lint: $(PYTHON_EXE_DEPS)
$(ECHO) linting... $(ECHO) linting...
$(VERB) cd src && python ../tools/lint.py $(VERB) cd src && $(PYTHON) ../tools/lint.py
cpplint: cpplint:
$(VERB) cd src && python $(TOOLS_DIR)/cpplint.py --filter=-whitespace,-build/header_guard,-build/include_order,-readability/todo $(SRCS) $(VERB) $(PYTHON) $(TOOLS_DIR)/cpplint.py --filter=-whitespace,-build/header_guard,-build/include_order,-readability/todo $(SRCS)
.PHONY: check quick_check .PHONY: check quick_check
check: check:
...@@ -786,10 +796,10 @@ RUN_DEPS := ext_pyston ...@@ -786,10 +796,10 @@ RUN_DEPS := ext_pyston
define make_target define make_target
$(eval \ $(eval \
.PHONY: test$1 check$1 .PHONY: test$1 check$1
check$1 test$1: pyston$1 ext_pyston check$1 test$1: $(PYTHON_EXE_DEPS) pyston$1 ext_pyston
python $(TOOLS_DIR)/tester.py -R pyston$1 -j$(TEST_THREADS) -k $(TESTS_DIR) $(ARGS) $(PYTHON) $(TOOLS_DIR)/tester.py -R pyston$1 -j$(TEST_THREADS) -k $(TESTS_DIR) $(ARGS)
python $(TOOLS_DIR)/tester.py -a -x -R pyston$1 -j$(TEST_THREADS) -a -n -k $(TESTS_DIR) $(ARGS) $(PYTHON) $(TOOLS_DIR)/tester.py -a -x -R pyston$1 -j$(TEST_THREADS) -a -n -k $(TESTS_DIR) $(ARGS)
python $(TOOLS_DIR)/tester.py -R pyston$1 -j$(TEST_THREADS) -a -O -k $(TESTS_DIR) $(ARGS) $(PYTHON) $(TOOLS_DIR)/tester.py -R pyston$1 -j$(TEST_THREADS) -a -O -k $(TESTS_DIR) $(ARGS)
.PHONY: run$1 dbg$1 .PHONY: run$1 dbg$1
run$1: pyston$1 $$(RUN_DEPS) run$1: pyston$1 $$(RUN_DEPS)
...@@ -867,10 +877,10 @@ $(call make_search,profile_%) ...@@ -867,10 +877,10 @@ $(call make_search,profile_%)
# pprof-based profiling: # pprof-based profiling:
.PHONY: pprof_% pprof_release_% .PHONY: pprof_% pprof_release_%
pprof_%: %.py pyston_pprof pprof_%: %.py $(PYTHON_EXE_DEPS) pyston_pprof
CPUPROFILE_FREQUENCY=1000 CPUPROFILE=$@.out ./pyston_pprof -p $(ARGS) $< CPUPROFILE_FREQUENCY=1000 CPUPROFILE=$@.out ./pyston_pprof -p $(ARGS) $<
pprof --raw pyston_pprof $@.out > $@_raw.out pprof --raw pyston_pprof $@.out > $@_raw.out
python codegen/profiling/process_pprof.py $@_raw.out pprof.jit > $@_processed.out $(PYTHON) codegen/profiling/process_pprof.py $@_raw.out pprof.jit > $@_processed.out
pprof --text $@_processed.out pprof --text $@_processed.out
# rm -f pprof.out pprof.raw pprof.jit # rm -f pprof.out pprof.raw pprof.jit
$(call make_search,pprof_%) $(call make_search,pprof_%)
...@@ -945,10 +955,21 @@ TEST_EXT_MODULE_NAMES := basic_test descr_test slots_test ...@@ -945,10 +955,21 @@ TEST_EXT_MODULE_NAMES := basic_test descr_test slots_test
.PHONY: ext_pyston .PHONY: ext_pyston
ext_pyston: $(TEST_EXT_MODULE_NAMES:%=$(TEST_DIR)/test_extension/%.pyston.so) ext_pyston: $(TEST_EXT_MODULE_NAMES:%=$(TEST_DIR)/test_extension/%.pyston.so)
ifneq ($(SELF_HOST),1)
$(TEST_DIR)/test_extension/%.pyston.so: $(TEST_DIR)/test_extension/%.o $(TEST_DIR)/test_extension/%.pyston.so: $(TEST_DIR)/test_extension/%.o
gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro $< -o $@ -g gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro $< -o $@ -g
$(TEST_DIR)/test_extension/%.o: $(TEST_DIR)/test_extension/%.c $(wildcard ./include/*.h) $(TEST_DIR)/test_extension/%.o: $(TEST_DIR)/test_extension/%.c $(wildcard ./include/*.h)
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -Wimplicit -I./include -c $< -o $@ gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -Wimplicit -I./include -c $< -o $@
else
# Hax: we want to generate multiple targets from a single rule, and run the rule only if the
# dependencies have been updated, and only run it once for all the targets.
# So just tell make to generate the first extension module, and that the non-first ones just
# depend on the first one.
$(TEST_DIR)/test_extension/$(firstword $(TEST_EXT_MODULE_NAMES)).pyston.so: $(TEST_EXT_MODULE_NAMES:%=$(TEST_DIR)/test_extension/%.c) | pyston_dbg
$(MAKE) ext_pyston_selfhost
NONFIRST_EXT := $(wordlist 2,9999,$(TEST_EXT_MODULE_NAMES))
$(NONFIRST_EXT:%=$(TEST_DIR)/test_extension/%.pyston.so): $(TEST_DIR)/test_extension/$(firstword $(TEST_EXT_MODULE_NAMES)).pyston.so
endif
.PHONY: ext_pyston_selfhost dbg_ext_pyston_selfhost ext_pyston_selfhost_release .PHONY: ext_pyston_selfhost dbg_ext_pyston_selfhost ext_pyston_selfhost_release
ext_pyston_selfhost: pyston_dbg $(TEST_EXT_MODULE_NAMES:%=$(TEST_DIR)/test_extension/*.c) ext_pyston_selfhost: pyston_dbg $(TEST_EXT_MODULE_NAMES:%=$(TEST_DIR)/test_extension/*.c)
......
# TODO: we will have to figure out a better way of generating this file # TODO: we will have to figure out a better way of generating this file
build_time_vars = {} build_time_vars = {
"CC": "gcc -pthread",
"CXX": "g++ -pthread",
"OPT": "-DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes",
"CFLAGS": "-fno-strict-aliasing -g -O3 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes",
"CCSHARED": "-fPIC",
"LDSHARED": "gcc -pthread -shared",
"SO": ".pyston.so",
"AR": "ar",
"ARFLAGS": "rc",
}
# This file is originally from CPython 2.7, with modifications for Pyston
# We should probably create a pyston-specific version instead of modifying the
# CPython one.
"""Provide access to Python's configuration information. The specific """Provide access to Python's configuration information. The specific
configuration variables available depend heavily on the platform and configuration variables available depend heavily on the platform and
configuration. The values may be retrieved using configuration. The values may be retrieved using
...@@ -64,6 +68,9 @@ def get_python_version(): ...@@ -64,6 +68,9 @@ def get_python_version():
def get_python_inc(plat_specific=0, prefix=None): def get_python_inc(plat_specific=0, prefix=None):
# Pyston change: this is the way we layout things internally:
return os.path.join(os.path.dirname(sys.executable), "include")
"""Return the directory containing installed Python header files. """Return the directory containing installed Python header files.
If 'plat_specific' is false (the default), this is the path to the If 'plat_specific' is false (the default), this is the path to the
......
// Copyright (c) 2014 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 <algorithm>
#include <cstring>
#include <sstream>
#include <unordered_map>
#include "core/common.h"
#include "core/types.h"
#include "core/util.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/dict.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
#include "runtime/util.h"
namespace pyston {
extern "C" PyObject* PyErr_SetFromErrnoWithFilenameObject(PyObject* exc, PyObject* filenameObject) {
PyObject* v;
// Pyston change: made const
const char* s;
int i = errno;
#ifdef PLAN9
char errbuf[ERRMAX];
#endif
#ifdef MS_WINDOWS
char* s_buf = NULL;
char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */
#endif
#ifdef EINTR
if (i == EINTR && PyErr_CheckSignals())
return NULL;
#endif
#ifdef PLAN9
rerrstr(errbuf, sizeof errbuf);
s = errbuf;
#else
if (i == 0)
s = "Error"; /* Sometimes errno didn't get set */
else
#ifndef MS_WINDOWS
s = strerror(i);
#else
{
/* Note that the Win32 errors do not lineup with the
errno error. So if the error is in the MSVC error
table, we use it, otherwise we assume it really _is_
a Win32 error code
*/
if (i > 0 && i < _sys_nerr) {
s = _sys_errlist[i];
} else {
int len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, /* no message source */
i, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
/* Default language */
(LPTSTR)&s_buf, 0, /* size not used */
NULL); /* no args */
if (len == 0) {
/* Only ever seen this in out-of-mem
situations */
sprintf(s_small_buf, "Windows Error 0x%X", i);
s = s_small_buf;
s_buf = NULL;
} else {
s = s_buf;
/* remove trailing cr/lf and dots */
while (len > 0 && (s[len - 1] <= ' ' || s[len - 1] == '.'))
s[--len] = '\0';
}
}
}
#endif /* Unix/Windows */
#endif /* PLAN 9*/
if (filenameObject != NULL)
v = Py_BuildValue("(isO)", i, s, filenameObject);
else
v = Py_BuildValue("(is)", i, s);
if (v != NULL) {
PyErr_SetObject(exc, v);
Py_DECREF(v);
}
#ifdef MS_WINDOWS
LocalFree(s_buf);
#endif
return NULL;
}
extern "C" PyObject* PyErr_SetFromErrnoWithFilename(PyObject* exc, const char* filename) {
PyObject* name = filename ? PyString_FromString(filename) : NULL;
PyObject* result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
Py_XDECREF(name);
return result;
}
#ifdef MS_WINDOWS
extern "C" PyObject* PyErr_SetFromErrnoWithUnicodeFilename(PyObject* exc, const Py_UNICODE* filename) {
PyObject* name = filename ? PyUnicode_FromUnicode(filename, wcslen(filename)) : NULL;
PyObject* result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
Py_XDECREF(name);
return result;
}
#endif /* MS_WINDOWS */
extern "C" PyObject* PyErr_SetFromErrno(PyObject* exc) {
return PyErr_SetFromErrnoWithFilenameObject(exc, NULL);
}
}
...@@ -32,7 +32,7 @@ namespace threading { ...@@ -32,7 +32,7 @@ namespace threading {
bool threadWasStarted(); bool threadWasStarted();
struct ThreadState { struct ThreadState {
Box* curexc_type, *curexc_value, *curexc_traceback; Box* exc_type, *exc_value, *exc_traceback;
}; };
extern __thread ThreadState cur_thread_state; extern __thread ThreadState cur_thread_state;
......
...@@ -55,12 +55,12 @@ void collectOtherThreadsStacks(TraceStack* stack) { ...@@ -55,12 +55,12 @@ void collectOtherThreadsStacks(TraceStack* stack) {
collectRoots(tstate.stack_start, tstate.stack_end, stack); collectRoots(tstate.stack_start, tstate.stack_end, stack);
collectRoots(tstate.ucontext, tstate.ucontext + 1, stack); collectRoots(tstate.ucontext, tstate.ucontext + 1, stack);
if (tstate.thread_state->curexc_type) if (tstate.thread_state->exc_type)
v.visit(tstate.thread_state->curexc_type); v.visit(tstate.thread_state->exc_type);
if (tstate.thread_state->curexc_value) if (tstate.thread_state->exc_value)
v.visit(tstate.thread_state->curexc_value); v.visit(tstate.thread_state->exc_value);
if (tstate.thread_state->curexc_traceback) if (tstate.thread_state->exc_traceback)
v.visit(tstate.thread_state->curexc_traceback); v.visit(tstate.thread_state->exc_traceback);
} }
} }
...@@ -86,12 +86,12 @@ static void collectLocalStack(TraceStack* stack) { ...@@ -86,12 +86,12 @@ static void collectLocalStack(TraceStack* stack) {
#endif #endif
GCVisitor v(stack); GCVisitor v(stack);
if (threading::cur_thread_state.curexc_type) if (threading::cur_thread_state.exc_type)
v.visit(threading::cur_thread_state.curexc_type); v.visit(threading::cur_thread_state.exc_type);
if (threading::cur_thread_state.curexc_value) if (threading::cur_thread_state.exc_value)
v.visit(threading::cur_thread_state.curexc_value); v.visit(threading::cur_thread_state.exc_value);
if (threading::cur_thread_state.curexc_traceback) if (threading::cur_thread_state.exc_traceback)
v.visit(threading::cur_thread_state.curexc_traceback); v.visit(threading::cur_thread_state.exc_traceback);
} }
void collectStackRoots(TraceStack* stack) { void collectStackRoots(TraceStack* stack) {
......
...@@ -768,6 +768,104 @@ public: ...@@ -768,6 +768,104 @@ public:
self->filename = filename; self->filename = filename;
return None; return None;
} }
static PyObject* __str__(BoxedEnvironmentError* self) noexcept {
PyObject* rtnval = NULL;
if (self->filename) {
PyObject* fmt;
PyObject* repr;
PyObject* tuple;
fmt = PyString_FromString("[Errno %s] %s: %s");
if (!fmt)
return NULL;
repr = PyObject_Repr(self->filename);
if (!repr) {
Py_DECREF(fmt);
return NULL;
}
tuple = PyTuple_New(3);
if (!tuple) {
Py_DECREF(repr);
Py_DECREF(fmt);
return NULL;
}
if (self->myerrno) {
Py_INCREF(self->myerrno);
PyTuple_SET_ITEM(tuple, 0, self->myerrno);
} else {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(tuple, 0, Py_None);
}
if (self->strerror) {
Py_INCREF(self->strerror);
PyTuple_SET_ITEM(tuple, 1, self->strerror);
} else {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(tuple, 1, Py_None);
}
PyTuple_SET_ITEM(tuple, 2, repr);
rtnval = PyString_Format(fmt, tuple);
Py_DECREF(fmt);
Py_DECREF(tuple);
} else if (self->myerrno && self->strerror) {
PyObject* fmt;
PyObject* tuple;
fmt = PyString_FromString("[Errno %s] %s");
if (!fmt)
return NULL;
tuple = PyTuple_New(2);
if (!tuple) {
Py_DECREF(fmt);
return NULL;
}
if (self->myerrno) {
Py_INCREF(self->myerrno);
PyTuple_SET_ITEM(tuple, 0, self->myerrno);
} else {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(tuple, 0, Py_None);
}
if (self->strerror) {
Py_INCREF(self->strerror);
PyTuple_SET_ITEM(tuple, 1, self->strerror);
} else {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(tuple, 1, Py_None);
}
rtnval = PyString_Format(fmt, tuple);
Py_DECREF(fmt);
Py_DECREF(tuple);
} else
rtnval = exceptionStr(self);
return rtnval;
}
static void gcHandler(GCVisitor* v, Box* _b) {
assert(isSubclass(_b->cls, EnvironmentError));
boxGCHandler(v, _b);
BoxedEnvironmentError* ee = static_cast<BoxedEnvironmentError*>(_b);
if (ee->myerrno)
v->visit(ee->myerrno);
if (ee->strerror)
v->visit(ee->strerror);
if (ee->filename)
v->visit(ee->filename);
}
}; };
void setupBuiltins() { void setupBuiltins() {
...@@ -825,9 +923,18 @@ void setupBuiltins() { ...@@ -825,9 +923,18 @@ void setupBuiltins() {
NotImplementedError = makeBuiltinException(RuntimeError, "NotImplementedError"); NotImplementedError = makeBuiltinException(RuntimeError, "NotImplementedError");
PendingDeprecationWarning = makeBuiltinException(Warning, "PendingDeprecationWarning"); PendingDeprecationWarning = makeBuiltinException(Warning, "PendingDeprecationWarning");
EnvironmentError->gc_visit = BoxedEnvironmentError::gcHandler;
EnvironmentError->giveAttr( EnvironmentError->giveAttr(
"__init__", "__init__",
new BoxedFunction(boxRTFunction((void*)BoxedEnvironmentError::__init__, NONE, 4, 1, false, false), { None })); new BoxedFunction(boxRTFunction((void*)BoxedEnvironmentError::__init__, NONE, 4, 1, false, false), { NULL }));
EnvironmentError->giveAttr(
"errno", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedEnvironmentError, myerrno)));
EnvironmentError->giveAttr("strerror", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT,
offsetof(BoxedEnvironmentError, strerror)));
EnvironmentError->giveAttr("filename", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT,
offsetof(BoxedEnvironmentError, filename)));
EnvironmentError->giveAttr("__str__",
new BoxedFunction(boxRTFunction((void*)BoxedEnvironmentError::__str__, UNKNOWN, 1)));
repr_obj = new BoxedFunction(boxRTFunction((void*)repr, UNKNOWN, 1)); repr_obj = new BoxedFunction(boxRTFunction((void*)repr, UNKNOWN, 1));
builtins_module->giveAttr("repr", repr_obj); builtins_module->giveAttr("repr", repr_obj);
......
...@@ -31,6 +31,13 @@ namespace pyston { ...@@ -31,6 +31,13 @@ namespace pyston {
BoxedModule* sys_module; BoxedModule* sys_module;
BoxedDict* sys_modules_dict; BoxedDict* sys_modules_dict;
Box* sysExcInfo() {
return new BoxedTuple(
{ threading::cur_thread_state.exc_type ? threading::cur_thread_state.exc_type : None,
threading::cur_thread_state.exc_value ? threading::cur_thread_state.exc_value : None,
threading::cur_thread_state.exc_traceback ? threading::cur_thread_state.exc_traceback : None });
}
BoxedDict* getSysModulesDict() { BoxedDict* getSysModulesDict() {
// PyPy's behavior: fetch from sys.modules each time: // PyPy's behavior: fetch from sys.modules each time:
// Box *_sys_modules = sys_module->getattr("modules"); // Box *_sys_modules = sys_module->getattr("modules");
...@@ -134,6 +141,8 @@ void setupSys() { ...@@ -134,6 +141,8 @@ void setupSys() {
sys_module->giveAttr("stdin", new BoxedFile(stdin, "<stdin>", "r")); sys_module->giveAttr("stdin", new BoxedFile(stdin, "<stdin>", "r"));
sys_module->giveAttr("stderr", new BoxedFile(stderr, "<stderr>", "w")); sys_module->giveAttr("stderr", new BoxedFile(stderr, "<stderr>", "w"));
sys_module->giveAttr("exc_info", new BoxedFunction(boxRTFunction((void*)sysExcInfo, BOXED_TUPLE, 0)));
sys_module->giveAttr("warnoptions", new BoxedList()); sys_module->giveAttr("warnoptions", new BoxedList());
sys_module->giveAttr("py3kwarning", False); sys_module->giveAttr("py3kwarning", False);
......
...@@ -630,30 +630,30 @@ extern "C" int PyCallable_Check(PyObject* x) { ...@@ -630,30 +630,30 @@ extern "C" int PyCallable_Check(PyObject* x) {
} }
void checkAndThrowCAPIException() { void checkAndThrowCAPIException() {
Box* value = threading::cur_thread_state.curexc_value; Box* value = threading::cur_thread_state.exc_value;
if (value) { if (value) {
RELEASE_ASSERT(threading::cur_thread_state.curexc_traceback == NULL, "unsupported"); RELEASE_ASSERT(threading::cur_thread_state.exc_traceback == NULL, "unsupported");
// This doesn't seem like the right behavior... // This doesn't seem like the right behavior...
if (value->cls != threading::cur_thread_state.curexc_type) { if (value->cls != threading::cur_thread_state.exc_type) {
if (value->cls == tuple_cls) if (value->cls == tuple_cls)
value = runtimeCall(threading::cur_thread_state.curexc_type, ArgPassSpec(0, 0, true, false), value, value = runtimeCall(threading::cur_thread_state.exc_type, ArgPassSpec(0, 0, true, false), value, NULL,
NULL, NULL, NULL, NULL); NULL, NULL, NULL);
else else
value = runtimeCall(threading::cur_thread_state.curexc_type, ArgPassSpec(1), value, NULL, NULL, NULL, value
NULL); = runtimeCall(threading::cur_thread_state.exc_type, ArgPassSpec(1), value, NULL, NULL, NULL, NULL);
} }
RELEASE_ASSERT(value->cls == threading::cur_thread_state.curexc_type, "unsupported"); RELEASE_ASSERT(value->cls == threading::cur_thread_state.exc_type, "unsupported");
PyErr_Clear(); PyErr_Clear();
throw value; throw value;
} }
} }
extern "C" void PyErr_Restore(PyObject* type, PyObject* value, PyObject* traceback) { extern "C" void PyErr_Restore(PyObject* type, PyObject* value, PyObject* traceback) {
threading::cur_thread_state.curexc_type = type; threading::cur_thread_state.exc_type = type;
threading::cur_thread_state.curexc_value = value; threading::cur_thread_state.exc_value = value;
threading::cur_thread_state.curexc_traceback = traceback; threading::cur_thread_state.exc_traceback = traceback;
} }
extern "C" void PyErr_Clear() { extern "C" void PyErr_Clear() {
...@@ -685,18 +685,13 @@ extern "C" int PyErr_ExceptionMatches(PyObject* exc) { ...@@ -685,18 +685,13 @@ extern "C" int PyErr_ExceptionMatches(PyObject* exc) {
} }
extern "C" PyObject* PyErr_Occurred() { extern "C" PyObject* PyErr_Occurred() {
return threading::cur_thread_state.curexc_type; return threading::cur_thread_state.exc_type;
} }
extern "C" int PyErr_WarnEx(PyObject* category, const char* text, Py_ssize_t stacklevel) { extern "C" int PyErr_WarnEx(PyObject* category, const char* text, Py_ssize_t stacklevel) {
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
extern "C" PyObject* PyErr_SetFromErrno(PyObject* type) {
Py_FatalError("unimplemented");
return NULL;
}
extern "C" PyObject* PyImport_Import(PyObject* module_name) { extern "C" PyObject* PyImport_Import(PyObject* module_name) {
RELEASE_ASSERT(module_name, ""); RELEASE_ASSERT(module_name, "");
RELEASE_ASSERT(module_name->cls == str_cls, ""); RELEASE_ASSERT(module_name->cls == str_cls, "");
...@@ -949,84 +944,6 @@ extern "C" int PyBuffer_IsContiguous(Py_buffer* view, char fort) { ...@@ -949,84 +944,6 @@ extern "C" int PyBuffer_IsContiguous(Py_buffer* view, char fort) {
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
extern "C" PyObject* PyErr_SetFromErrnoWithFilename(PyObject* exc, const char* filename) {
PyObject* name = filename ? PyString_FromString(filename) : NULL;
PyObject* result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
Py_XDECREF(name);
return result;
}
extern "C" PyObject* PyErr_SetFromErrnoWithFilenameObject(PyObject* exc, PyObject* filenameObject) {
PyObject* v;
const char* s;
int i = errno;
#ifdef PLAN9
char errbuf[ERRMAX];
#endif
#ifdef MS_WINDOWS
char* s_buf = NULL;
char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */
#endif
#ifdef EINTR
if (i == EINTR && PyErr_CheckSignals())
return NULL;
#endif
#ifdef PLAN9
rerrstr(errbuf, sizeof errbuf);
s = errbuf;
#else
if (i == 0)
s = "Error"; /* Sometimes errno didn't get set */
else
#ifndef MS_WINDOWS
s = strerror(i);
#else
{
/* Note that the Win32 errors do not lineup with the
errno error. So if the error is in the MSVC error
table, we use it, otherwise we assume it really _is_
a Win32 error code
*/
if (i > 0 && i < _sys_nerr) {
s = _sys_errlist[i];
} else {
int len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, /* no message source */
i, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
/* Default language */
(LPTSTR)&s_buf, 0, /* size not used */
NULL); /* no args */
if (len == 0) {
/* Only ever seen this in out-of-mem
situations */
sprintf(s_small_buf, "Windows Error 0x%X", i);
s = s_small_buf;
s_buf = NULL;
} else {
s = s_buf;
/* remove trailing cr/lf and dots */
while (len > 0 && (s[len - 1] <= ' ' || s[len - 1] == '.'))
s[--len] = '\0';
}
}
}
#endif /* Unix/Windows */
#endif /* PLAN 9*/
if (filenameObject != NULL)
v = Py_BuildValue("(isO)", i, s, filenameObject);
else
v = Py_BuildValue("(is)", i, s);
if (v != NULL) {
PyErr_SetObject(exc, v);
Py_DECREF(v);
}
#ifdef MS_WINDOWS
LocalFree(s_buf);
#endif
return NULL;
}
extern "C" int PyOS_snprintf(char* str, size_t size, const char* format, ...) { extern "C" int PyOS_snprintf(char* str, size_t size, const char* format, ...) {
int rc; int rc;
va_list va; va_list va;
......
...@@ -508,6 +508,13 @@ Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) { ...@@ -508,6 +508,13 @@ Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) {
bool is_order bool is_order
= (op_type == AST_TYPE::Lt || op_type == AST_TYPE::LtE || op_type == AST_TYPE::Gt || op_type == AST_TYPE::GtE); = (op_type == AST_TYPE::Lt || op_type == AST_TYPE::LtE || op_type == AST_TYPE::Gt || op_type == AST_TYPE::GtE);
if (lsz != rsz) {
if (op_type == AST_TYPE::Eq)
return False;
if (op_type == AST_TYPE::NotEq)
return True;
}
int n = std::min(lsz, rsz); int n = std::min(lsz, rsz);
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
Box* is_eq = compareInternal(lhs->elts->elts[i], rhs->elts->elts[i], AST_TYPE::Eq, NULL); Box* is_eq = compareInternal(lhs->elts->elts[i], rhs->elts->elts[i], AST_TYPE::Eq, NULL);
...@@ -552,6 +559,16 @@ Box* listEq(BoxedList* self, Box* rhs) { ...@@ -552,6 +559,16 @@ Box* listEq(BoxedList* self, Box* rhs) {
return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::Eq); return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::Eq);
} }
Box* listNe(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) {
return NotImplemented;
}
LOCK_REGION(self->lock.asRead());
return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::NotEq);
}
void setupList() { void setupList() {
list_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &listIteratorGCHandler, 0, sizeof(BoxedList), false); list_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &listIteratorGCHandler, 0, sizeof(BoxedList), false);
...@@ -569,6 +586,7 @@ void setupList() { ...@@ -569,6 +586,7 @@ void setupList() {
new BoxedFunction(boxRTFunction((void*)listIter, typeFromClass(list_iterator_cls), 1))); new BoxedFunction(boxRTFunction((void*)listIter, typeFromClass(list_iterator_cls), 1)));
list_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)listEq, UNKNOWN, 2))); list_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)listEq, UNKNOWN, 2)));
list_cls->giveAttr("__ne__", new BoxedFunction(boxRTFunction((void*)listNe, UNKNOWN, 2)));
list_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)listRepr, STR, 1))); list_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)listRepr, STR, 1)));
list_cls->giveAttr("__str__", list_cls->getattr("__repr__")); list_cls->giveAttr("__str__", list_cls->getattr("__repr__"));
......
...@@ -134,6 +134,9 @@ static void _printTraceback(const std::vector<const LineInfo*>& tb) { ...@@ -134,6 +134,9 @@ static void _printTraceback(const std::vector<const LineInfo*>& tb) {
for (auto line : tb) { for (auto line : tb) {
fprintf(stderr, " File \"%s\", line %d, in %s:\n", line->file.c_str(), line->line, line->func.c_str()); fprintf(stderr, " File \"%s\", line %d, in %s:\n", line->file.c_str(), line->line, line->func.c_str());
if (line->line < 0)
continue;
FILE* f = fopen(line->file.c_str(), "r"); FILE* f = fopen(line->file.c_str(), "r");
if (f) { if (f) {
assert(line->line < 10000000 && "Refusing to try to seek that many lines forward"); assert(line->line < 10000000 && "Refusing to try to seek that many lines forward");
......
...@@ -686,6 +686,18 @@ public: ...@@ -686,6 +686,18 @@ public:
return None; return None;
} }
static Box* get(Box* _self, Box* _key, Box* def) {
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
RELEASE_ASSERT(_key->cls == str_cls, "");
BoxedString* key = static_cast<BoxedString*>(_key);
Box* r = self->b->getattr(key->s);
if (!r)
return def;
return r;
}
static Box* getitem(Box* _self, Box* _key) { static Box* getitem(Box* _self, Box* _key) {
RELEASE_ASSERT(_self->cls == attrwrapper_cls, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -951,6 +963,8 @@ void setupRuntime() { ...@@ -951,6 +963,8 @@ void setupRuntime() {
attrwrapper_cls->giveAttr("__name__", boxStrConstant("attrwrapper")); attrwrapper_cls->giveAttr("__name__", boxStrConstant("attrwrapper"));
attrwrapper_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::setitem, UNKNOWN, 3))); attrwrapper_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::setitem, UNKNOWN, 3)));
attrwrapper_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::getitem, UNKNOWN, 2))); attrwrapper_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::getitem, UNKNOWN, 2)));
attrwrapper_cls->giveAttr(
"get", new BoxedFunction(boxRTFunction((void*)AttrWrapper::get, UNKNOWN, 3, 1, false, false), { None }));
attrwrapper_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::str, UNKNOWN, 1))); attrwrapper_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::str, UNKNOWN, 1)));
attrwrapper_cls->giveAttr("__contains__", attrwrapper_cls->giveAttr("__contains__",
new BoxedFunction(boxRTFunction((void*)AttrWrapper::contains, UNKNOWN, 2))); new BoxedFunction(boxRTFunction((void*)AttrWrapper::contains, UNKNOWN, 2)));
......
...@@ -55,3 +55,6 @@ class C(object): ...@@ -55,3 +55,6 @@ class C(object):
def __init__(self): def __init__(self):
self.a = 1 self.a = 1
print vars(C()).items() print vars(C()).items()
print globals().get("not a real variable")
print globals().get("not a real variable", 1)
...@@ -88,3 +88,11 @@ class Reverse(object): ...@@ -88,3 +88,11 @@ class Reverse(object):
return self.n <= rhs.n return self.n <= rhs.n
print Reverse(4) > Reverse(3), Reverse(4) > Reverse(4) print Reverse(4) > Reverse(3), Reverse(4) > Reverse(4)
class EqOnly(object):
def __eq__(self, rhs):
print "eq"
return False
print EqOnly() == 1
print EqOnly() != 1
...@@ -76,3 +76,14 @@ print l ...@@ -76,3 +76,14 @@ print l
x = [0, 1, 2] x = [0, 1, 2]
print 2 * x print 2 * x
print x * 2 print x * 2
print range(5) == range(5)
print range(5) == range(4)
class C(object):
def __eq__(self, rhs):
print "C.eq"
return False
# Should not call C().__eq__
print [C()] == [1, 2]
...@@ -16,4 +16,15 @@ print os.path.expanduser("~") == os.environ["HOME"] ...@@ -16,4 +16,15 @@ print os.path.expanduser("~") == os.environ["HOME"]
print os.path.isfile("/dev/null") print os.path.isfile("/dev/null")
print os.path.isfile("/should_not_exist!") print os.path.isfile("/should_not_exist!")
OSError(1, 2, 3) e = OSError(1, 2, 3)
print e
print e.errno
print e.strerror
print e.filename
print OSError(1, 2).filename
# This part needs sys.exc_info() and the three-arg raise statement
# try:
# os.execvp("aoeuaoeu", ['aoeuaoeu'])
# except OSError, e:
# print e
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