Commit 56f6fbea authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'merge'

parents da9f8db9 0d932768
......@@ -135,6 +135,7 @@ link_directories(${CMAKE_BINARY_DIR}/libunwind/lib)
link_directories(${LLVM_LIBRARY_DIRS})
add_subdirectory(lib_python)
add_subdirectory(lib_pyston)
add_subdirectory(src)
add_subdirectory(test/test_extension)
add_subdirectory(test/unittests)
......
......@@ -749,10 +749,10 @@ $(call link,_release,$(OPT_OBJS),$(LDFLAGS_RELEASE),$(LLVM_RELEASE_DEPS))
else
.PHONY: pyston_dbg pyston_release
pyston_dbg:
$(NINJA) -C $(HOME)/pyston-build-dbg pyston $(NINJAFLAGS)
$(NINJA) -C $(HOME)/pyston-build-dbg pyston copy_stdlib copy_libpyston $(NINJAFLAGS)
ln -sf $(HOME)/pyston-build-dbg/pyston pyston_dbg
pyston_release:
$(NINJA) -C $(HOME)/pyston-build-release pyston $(NINJAFLAGS)
$(NINJA) -C $(HOME)/pyston-build-release pyston copy_stdlib copy_libpyston $(NINJAFLAGS)
ln -sf $(HOME)/pyston-build-release/pyston pyston_release
endif
......
# Copy any changed lib_pyston sources:
file(GLOB_RECURSE LIBPYSTON_SRCS . "*.py")
SET(LIBPYSTON_TARGETS "")
foreach(STDLIB_FILE ${LIBPYSTON_SRCS})
file(RELATIVE_PATH FN_REL ${CMAKE_SOURCE_DIR} ${STDLIB_FILE})
set(TARGET ${CMAKE_BINARY_DIR}/${FN_REL})
add_custom_command(OUTPUT ${TARGET} COMMAND
${CMAKE_COMMAND} -E copy_if_different ${STDLIB_FILE} ${TARGET}
DEPENDS ${STDLIB_FILE}
COMMENT "Copying ${FN_REL}"
)
set(LIBPYSTON_TARGETS ${LIBPYSTON_TARGETS} ${TARGET})
endforeach(STDLIB_FILE)
add_custom_target(copy_libpyston ALL DEPENDS ${LIBPYSTON_TARGETS})
# TODO: we will have to figure out a better way of generating this file
build_time_vars = {}
# Copy any changed stdlib files to the destination:
file(GLOB_RECURSE STDLIB_SRCS 2.7/ "*.py")
SET(STDLIB_TARGETS "")
foreach(STDLIB_FILE ${STDLIB_SRCS})
file(RELATIVE_PATH FN_REL ${CMAKE_SOURCE_DIR} ${STDLIB_FILE})
set(TARGET ${CMAKE_BINARY_DIR}/${FN_REL})
add_custom_command(OUTPUT ${TARGET} COMMAND
${CMAKE_COMMAND} -E copy_if_different ${STDLIB_FILE} ${TARGET}
DEPENDS ${STDLIB_FILE}
COMMENT "Copying ${FN_REL}"
)
set(STDLIB_TARGETS ${STDLIB_TARGETS} ${TARGET})
endforeach(STDLIB_FILE)
add_custom_target(copy_stdlib ALL DEPENDS ${STDLIB_TARGETS})
# compile specified files in lib_python/2.7_Modules
file(GLOB_RECURSE STDMODULE_SRCS 2.7_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)
......
......@@ -123,6 +123,12 @@ int main(int argc, char** argv) {
llvm::sys::path::append(stdlib_dir, "2.7");
appendToSysPath(stdlib_dir.c_str());
// go from ./lib_python/2.7 to ./lib_pyston
llvm::sys::path::remove_filename(stdlib_dir);
llvm::sys::path::remove_filename(stdlib_dir);
llvm::sys::path::append(stdlib_dir, "lib_pyston");
appendToSysPath(stdlib_dir.c_str());
// end of argument parsing
_t.split("to run");
......
......@@ -84,18 +84,23 @@ void prependToSysPath(const std::string& path) {
static BoxedClass* sys_flags_cls;
class BoxedSysFlags : public Box {
public:
Box* division_warning, *bytes_warning;
Box* division_warning, *bytes_warning, *no_user_site;
BoxedSysFlags() : Box(sys_flags_cls) {
auto zero = boxInt(0);
division_warning = zero;
bytes_warning = zero;
no_user_site = zero;
}
static void gcHandler(GCVisitor* v, Box* b) {
assert(b->cls == sys_flags_cls);
static void gcHandler(GCVisitor* v, Box* _b) {
assert(_b->cls == sys_flags_cls);
boxGCHandler(v, _b);
boxGCHandler(v, b);
BoxedSysFlags* self = static_cast<BoxedSysFlags*>(_b);
v->visit(self->division_warning);
v->visit(self->bytes_warning);
v->visit(self->no_user_site);
}
static Box* __new__(Box* cls, Box* args, Box* kwargs) {
......@@ -164,6 +169,7 @@ void setupSys() {
new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedSysFlags, name)))
ADD(division_warning);
ADD(bytes_warning);
ADD(no_user_site);
#undef ADD
sys_flags_cls->freeze();
......
......@@ -305,43 +305,82 @@ extern "C" Box* dictNew(Box* _cls, BoxedTuple* args, BoxedDict* kwargs) {
return new BoxedDict();
}
extern "C" Box* dictInit(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) {
int args_sz = args->elts.size();
int kwargs_sz = kwargs->d.size();
void dictMerge(BoxedDict* self, Box* other) {
if (other->cls == dict_cls) {
for (const auto& p : static_cast<BoxedDict*>(other)->d)
self->d[p.first] = p.second;
return;
}
// CPython accepts a single positional and keyword arguments, in any combination
if (args_sz > 1)
raiseExcHelper(TypeError, "dict expected at most 1 arguments, got %d", args_sz);
static const std::string keys_str("keys");
Box* keys = callattr(other, &keys_str, CallattrFlags({.cls_only = false, .null_on_nonexistent = true }),
ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
assert(keys);
// handle positional argument first as iterable
if (args_sz == 1) {
int idx = 0;
for (Box* k : keys->pyElements()) {
self->d[k] = getitem(other, k);
}
}
void dictMergeFromSeq2(BoxedDict* self, Box* other) {
int idx = 0;
// raises if not iterable
for (const auto& element : args->elts[0]->pyElements()) {
// raises if not iterable
for (const auto& element : other->pyElements()) {
// should this check subclasses? anyway to check if something is iterable...
if (element->cls == list_cls) {
BoxedList* list = static_cast<BoxedList*>(element);
if (list->size != 2)
raiseExcHelper(ValueError, "dictionary update sequence element #%d has length %d; 2 is required",
idx, list->size);
// should this check subclasses? anyway to check if something is iterable...
if (element->cls == list_cls) {
BoxedList* list = static_cast<BoxedList*>(element);
if (list->size != 2)
raiseExcHelper(ValueError, "dictionary update sequence element #%d has length %d; 2 is required", idx,
list->size);
self->d[list->elts->elts[0]] = list->elts->elts[1];
} else if (element->cls == tuple_cls) {
BoxedTuple* tuple = static_cast<BoxedTuple*>(element);
if (tuple->elts.size() != 2)
raiseExcHelper(ValueError, "dictionary update sequence element #%d has length %d; 2 is required",
idx, tuple->elts.size());
self->d[list->elts->elts[0]] = list->elts->elts[1];
} else if (element->cls == tuple_cls) {
BoxedTuple* tuple = static_cast<BoxedTuple*>(element);
if (tuple->elts.size() != 2)
raiseExcHelper(ValueError, "dictionary update sequence element #%d has length %d; 2 is required", idx,
tuple->elts.size());
self->d[tuple->elts[0]] = tuple->elts[1];
} else
raiseExcHelper(TypeError, "cannot convert dictionary update sequence element #%d to a sequence", idx);
self->d[tuple->elts[0]] = tuple->elts[1];
} else
raiseExcHelper(TypeError, "cannot convert dictionary update sequence element #%d to a sequence", idx);
idx++;
}
}
Box* dictUpdate(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) {
assert(args->cls == tuple_cls);
assert(kwargs);
assert(kwargs->cls == dict_cls);
idx++;
RELEASE_ASSERT(args->elts.size() <= 1, ""); // should throw a TypeError
if (args->elts.size()) {
Box* arg = args->elts[0];
if (getattrInternal(arg, "keys", NULL)) {
dictMerge(self, arg);
} else {
dictMergeFromSeq2(self, arg);
}
}
if (kwargs->d.size())
dictMerge(self, kwargs);
return None;
}
extern "C" Box* dictInit(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) {
int args_sz = args->elts.size();
int kwargs_sz = kwargs->d.size();
// CPython accepts a single positional and keyword arguments, in any combination
if (args_sz > 1)
raiseExcHelper(TypeError, "dict expected at most 1 arguments, got %d", args_sz);
dictUpdate(self, args, kwargs);
// handle keyword arguments by merging (possibly over positional entries per CPy)
assert(kwargs->cls == dict_cls);
......@@ -396,6 +435,8 @@ void setupDict() {
dict_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)dictIterKeys, typeFromClass(dict_iterator_cls), 1)));
dict_cls->giveAttr("update", new BoxedFunction(boxRTFunction((void*)dictUpdate, NONE, 1, 0, true, true)));
dict_cls->giveAttr("clear", new BoxedFunction(boxRTFunction((void*)dictClear, NONE, 1)));
dict_cls->giveAttr("copy", new BoxedFunction(boxRTFunction((void*)dictCopy, DICT, 1)));
......
......@@ -1841,6 +1841,10 @@ extern "C" void dump(void* p) {
printf("Int value: %ld\n", static_cast<BoxedInt*>(b)->n);
}
if (isSubclass(b->cls, list_cls)) {
printf("%ld elements\n", static_cast<BoxedList*>(b)->size);
}
return;
}
......
......@@ -285,6 +285,8 @@ extern "C" void typeGCHandler(GCVisitor* v, Box* b) {
if (cls->base)
v->visit(cls->base);
if (cls->tp_dict)
v->visit(cls->tp_dict);
}
extern "C" void instancemethodGCHandler(GCVisitor* v, Box* b) {
......
......@@ -163,3 +163,34 @@ try:
assert 0
except KeyError, e:
print 'ok'
d = {}
d.update({1:2, 3:4})
print sorted(d.items())
print sorted(dict(d).items())
class CustomMapping(object):
def __init__(self):
self.n = 0
def keys(self):
print "keys()"
return [1, 3, 7]
def __getitem__(self, key):
print key
self.n += 1
return self.n
print sorted(dict(CustomMapping()).items())
cm = CustomMapping()
def custom_keys():
print "custom_keys()"
return [2, 4, 2]
cm.keys = custom_keys
print sorted(dict(cm).items())
d = {}
d.update({'c':3}, a=1, b=2)
print sorted(d.items())
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