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

Merge branch 'selfhost'

parents f8746677 18741a0c
......@@ -31,6 +31,8 @@ TEST_THREADS := 1
ERROR_LIMIT := 10
COLOR := 1
SELF_HOST := 0
VERBOSE := 0
ENABLE_INTEL_JIT_EVENTS := 0
......@@ -48,6 +50,14 @@ NINJA := ninja
-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
TEST_DIR := ./test
TESTS_DIR := ./test/tests
......@@ -368,11 +378,11 @@ analyze:
$(MAKE) pyston_dbg USE_DISTCC=0 USE_CCACHE=0
.PHONY: lint cpplint
lint:
lint: $(PYTHON_EXE_DEPS)
$(ECHO) linting...
$(VERB) cd src && python ../tools/lint.py
$(VERB) cd src && $(PYTHON) ../tools/lint.py
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
check:
......@@ -786,10 +796,10 @@ RUN_DEPS := ext_pyston
define make_target
$(eval \
.PHONY: test$1 check$1
check$1 test$1: pyston$1 ext_pyston
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 -R pyston$1 -j$(TEST_THREADS) -a -O -k $(TESTS_DIR) $(ARGS)
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 -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)
.PHONY: run$1 dbg$1
run$1: pyston$1 $$(RUN_DEPS)
......@@ -867,10 +877,10 @@ $(call make_search,profile_%)
# pprof-based profiling:
.PHONY: pprof_% pprof_release_%
pprof_%: %.py pyston_pprof
pprof_%: %.py $(PYTHON_EXE_DEPS) pyston_pprof
CPUPROFILE_FREQUENCY=1000 CPUPROFILE=$@.out ./pyston_pprof -p $(ARGS) $<
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
# rm -f pprof.out pprof.raw pprof.jit
$(call make_search,pprof_%)
......@@ -945,10 +955,21 @@ TEST_EXT_MODULE_NAMES := basic_test descr_test slots_test
.PHONY: ext_pyston
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
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)
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
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
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
configuration variables available depend heavily on the platform and
configuration. The values may be retrieved using
......@@ -64,6 +68,9 @@ def get_python_version():
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.
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 {
bool threadWasStarted();
struct ThreadState {
Box* curexc_type, *curexc_value, *curexc_traceback;
Box* exc_type, *exc_value, *exc_traceback;
};
extern __thread ThreadState cur_thread_state;
......
......@@ -55,12 +55,12 @@ void collectOtherThreadsStacks(TraceStack* stack) {
collectRoots(tstate.stack_start, tstate.stack_end, stack);
collectRoots(tstate.ucontext, tstate.ucontext + 1, stack);
if (tstate.thread_state->curexc_type)
v.visit(tstate.thread_state->curexc_type);
if (tstate.thread_state->curexc_value)
v.visit(tstate.thread_state->curexc_value);
if (tstate.thread_state->curexc_traceback)
v.visit(tstate.thread_state->curexc_traceback);
if (tstate.thread_state->exc_type)
v.visit(tstate.thread_state->exc_type);
if (tstate.thread_state->exc_value)
v.visit(tstate.thread_state->exc_value);
if (tstate.thread_state->exc_traceback)
v.visit(tstate.thread_state->exc_traceback);
}
}
......@@ -86,12 +86,12 @@ static void collectLocalStack(TraceStack* stack) {
#endif
GCVisitor v(stack);
if (threading::cur_thread_state.curexc_type)
v.visit(threading::cur_thread_state.curexc_type);
if (threading::cur_thread_state.curexc_value)
v.visit(threading::cur_thread_state.curexc_value);
if (threading::cur_thread_state.curexc_traceback)
v.visit(threading::cur_thread_state.curexc_traceback);
if (threading::cur_thread_state.exc_type)
v.visit(threading::cur_thread_state.exc_type);
if (threading::cur_thread_state.exc_value)
v.visit(threading::cur_thread_state.exc_value);
if (threading::cur_thread_state.exc_traceback)
v.visit(threading::cur_thread_state.exc_traceback);
}
void collectStackRoots(TraceStack* stack) {
......
......@@ -768,6 +768,104 @@ public:
self->filename = filename;
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() {
......@@ -825,9 +923,18 @@ void setupBuiltins() {
NotImplementedError = makeBuiltinException(RuntimeError, "NotImplementedError");
PendingDeprecationWarning = makeBuiltinException(Warning, "PendingDeprecationWarning");
EnvironmentError->gc_visit = BoxedEnvironmentError::gcHandler;
EnvironmentError->giveAttr(
"__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));
builtins_module->giveAttr("repr", repr_obj);
......
......@@ -31,6 +31,13 @@ namespace pyston {
BoxedModule* sys_module;
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() {
// PyPy's behavior: fetch from sys.modules each time:
// Box *_sys_modules = sys_module->getattr("modules");
......@@ -134,6 +141,8 @@ void setupSys() {
sys_module->giveAttr("stdin", new BoxedFile(stdin, "<stdin>", "r"));
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("py3kwarning", False);
......
......@@ -630,30 +630,30 @@ extern "C" int PyCallable_Check(PyObject* x) {
}
void checkAndThrowCAPIException() {
Box* value = threading::cur_thread_state.curexc_value;
Box* value = threading::cur_thread_state.exc_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...
if (value->cls != threading::cur_thread_state.curexc_type) {
if (value->cls != threading::cur_thread_state.exc_type) {
if (value->cls == tuple_cls)
value = runtimeCall(threading::cur_thread_state.curexc_type, ArgPassSpec(0, 0, true, false), value,
NULL, NULL, NULL, NULL);
value = runtimeCall(threading::cur_thread_state.exc_type, ArgPassSpec(0, 0, true, false), value, NULL,
NULL, NULL, NULL);
else
value = runtimeCall(threading::cur_thread_state.curexc_type, ArgPassSpec(1), value, NULL, NULL, NULL,
NULL);
value
= 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();
throw value;
}
}
extern "C" void PyErr_Restore(PyObject* type, PyObject* value, PyObject* traceback) {
threading::cur_thread_state.curexc_type = type;
threading::cur_thread_state.curexc_value = value;
threading::cur_thread_state.curexc_traceback = traceback;
threading::cur_thread_state.exc_type = type;
threading::cur_thread_state.exc_value = value;
threading::cur_thread_state.exc_traceback = traceback;
}
extern "C" void PyErr_Clear() {
......@@ -685,18 +685,13 @@ extern "C" int PyErr_ExceptionMatches(PyObject* exc) {
}
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) {
Py_FatalError("unimplemented");
}
extern "C" PyObject* PyErr_SetFromErrno(PyObject* type) {
Py_FatalError("unimplemented");
return NULL;
}
extern "C" PyObject* PyImport_Import(PyObject* module_name) {
RELEASE_ASSERT(module_name, "");
RELEASE_ASSERT(module_name->cls == str_cls, "");
......@@ -949,84 +944,6 @@ extern "C" int PyBuffer_IsContiguous(Py_buffer* view, char fort) {
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, ...) {
int rc;
va_list va;
......
......@@ -508,6 +508,13 @@ Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) {
bool is_order
= (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);
for (int i = 0; i < n; i++) {
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) {
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() {
list_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &listIteratorGCHandler, 0, sizeof(BoxedList), false);
......@@ -569,6 +586,7 @@ void setupList() {
new BoxedFunction(boxRTFunction((void*)listIter, typeFromClass(list_iterator_cls), 1)));
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("__str__", list_cls->getattr("__repr__"));
......
......@@ -134,6 +134,9 @@ static void _printTraceback(const std::vector<const LineInfo*>& tb) {
for (auto line : tb) {
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");
if (f) {
assert(line->line < 10000000 && "Refusing to try to seek that many lines forward");
......
......@@ -686,6 +686,18 @@ public:
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) {
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
......@@ -951,6 +963,8 @@ void setupRuntime() {
attrwrapper_cls->giveAttr("__name__", boxStrConstant("attrwrapper"));
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(
"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("__contains__",
new BoxedFunction(boxRTFunction((void*)AttrWrapper::contains, UNKNOWN, 2)));
......
......@@ -55,3 +55,6 @@ class C(object):
def __init__(self):
self.a = 1
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):
return self.n <= rhs.n
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
x = [0, 1, 2]
print 2 * x
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"]
print os.path.isfile("/dev/null")
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