Commit ec1b3848 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Implement execfile() (1-arg version)

Also required adding some string functions so that
we could use os.path.
parent 59e195aa
......@@ -452,7 +452,8 @@ static_assert(sizeof(pyston::BoxedClass) == sizeof(struct _typeobject), "");
// TODO these shouldn't be here
void setupRuntime();
void teardownRuntime();
BoxedModule* createModule(const std::string& name, const std::string& fn);
BoxedModule* compileAndRunModule(const std::string& name, const std::string& fn, bool add_to_sys_modules);
BoxedModule* createModule(const std::string& name, const std::string& fn, bool add_to_sys_modules = true);
std::string getPythonFuncAt(void* ip, void* sp);
......
......@@ -83,11 +83,17 @@ Timer::~Timer() {
}
bool startswith(const std::string& s, const std::string& pattern) {
if (s.size() == 0)
return pattern.size() == 0;
if (pattern.size() > s.size())
return false;
return s.compare(0, pattern.size(), pattern) == 0;
}
bool endswith(const std::string& s, const std::string& pattern) {
if (pattern.size() > s.size())
return false;
return s.compare(s.size() - pattern.size(), pattern.size(), pattern) == 0;
}
void removeDirectoryIfExists(const std::string& path) {
llvm::error_code code;
......
......@@ -48,6 +48,7 @@ public:
};
bool startswith(const std::string& s, const std::string& pattern);
bool endswith(const std::string& s, const std::string& pattern);
void removeDirectoryIfExists(const std::string& path);
......
......@@ -127,8 +127,6 @@ int main(int argc, char** argv) {
_t.split("to run");
BoxedModule* main_module = NULL;
if (fn != NULL) {
main_module = createModule("__main__", fn);
llvm::SmallString<128> path;
if (!llvm::sys::path::is_absolute(fn)) {
......@@ -147,20 +145,8 @@ int main(int argc, char** argv) {
num_iterations = 1000;
for (int i = 0; i < num_iterations; i++) {
AST_Module* m;
if (caching)
m = caching_parse(fn);
else
m = parse(fn);
if (VERBOSITY() >= 1) {
printf("Parsed code; ast:\n");
print_ast(m);
printf("==============\n");
}
try {
compileAndRunModule(m, main_module);
main_module = compileAndRunModule("__main__", fn, true);
} catch (Box* b) {
std::string msg = formatException(b);
printLastTraceback();
......@@ -173,7 +159,7 @@ int main(int argc, char** argv) {
if (repl && BENCH) {
if (!main_module) {
main_module = createModule("__main__", "<bench>");
main_module = createModule("__main__", "<bench>", true);
} else {
main_module->fn = "<bench>";
}
......@@ -211,7 +197,7 @@ int main(int argc, char** argv) {
printf(", targeting Python %d.%d.%d\n", PYTHON_VERSION_MAJOR, PYTHON_VERSION_MINOR, PYTHON_VERSION_MICRO);
if (!main_module) {
main_module = createModule("__main__", "<stdin>");
main_module = createModule("__main__", "<stdin>", true);
} else {
main_module->fn = "<stdin>";
}
......
......@@ -16,6 +16,8 @@
#include <cstddef>
#include <err.h>
#include "llvm/Support/FileSystem.h"
#include "codegen/compvars.h"
#include "core/ast.h"
#include "core/types.h"
......@@ -524,6 +526,29 @@ Box* divmod(Box* lhs, Box* rhs) {
return binopInternal(lhs, rhs, AST_TYPE::DivMod, false, NULL);
}
Box* execfile(Box* _fn) {
// The "globals" and "locals" arguments aren't implemented for now
if (!isSubclass(_fn->cls, str_cls)) {
raiseExcHelper(TypeError, "must be string, not %s", getTypeName(_fn)->c_str());
}
BoxedString* fn = static_cast<BoxedString*>(_fn);
bool exists;
llvm::error_code code = llvm::sys::fs::exists(fn->s, exists);
#if LLVMREV < 210072
ASSERT(code == 0, "%s: %s", code.message().c_str(), fn->s.c_str());
#else
assert(!code);
#endif
if (!exists)
raiseExcHelper(IOError, "No such file or directory: '%s'", fn->s.c_str());
compileAndRunModule("aoeu", fn->s, false);
return None;
}
void setupBuiltins() {
builtins_module = createModule("__builtin__", "__builtin__");
......@@ -649,6 +674,8 @@ void setupBuiltins() {
builtins_module->giveAttr("divmod", new BoxedFunction(boxRTFunction((void*)divmod, UNKNOWN, 2)));
builtins_module->giveAttr("execfile", new BoxedFunction(boxRTFunction((void*)execfile, UNKNOWN, 1)));
builtins_module->giveAttr("map", new BoxedFunction(boxRTFunction((void*)map2, LIST, 2)));
builtins_module->giveAttr("filter", new BoxedFunction(boxRTFunction((void*)filter2, LIST, 2)));
builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2)));
......
......@@ -3487,6 +3487,14 @@ extern "C" Box* getGlobal(BoxedModule* m, std::string* name) {
raiseExcHelper(NameError, "global name '%s' is not defined", name->c_str());
}
BoxedModule* compileAndRunModule(const std::string& name, const std::string& fn, bool add_to_sys_modules) {
BoxedModule* module = createModule(name, fn, add_to_sys_modules);
AST_Module* ast = caching_parse(fn.c_str());
compileAndRunModule(ast, module);
return module;
}
// TODO I feel like importing should go somewhere else; it's more closely tied to codegen
// than to the object model.
extern "C" Box* import(const std::string* name) {
......@@ -3533,9 +3541,7 @@ extern "C" Box* import(const std::string* name) {
printf("Importing %s from %s\n", name->c_str(), fn.c_str());
// TODO duplication with jit.cpp:
BoxedModule* module = createModule(*name, fn);
AST_Module* ast = caching_parse(fn.c_str());
compileAndRunModule(ast, module);
BoxedModule* module = compileAndRunModule(*name, fn, true);
return module;
}
......
......@@ -23,6 +23,7 @@
#include "codegen/compvars.h"
#include "core/common.h"
#include "core/types.h"
#include "core/util.h"
#include "gc/collector.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......@@ -694,6 +695,64 @@ Box* strContains(BoxedString* self, Box* elt) {
return True;
}
Box* strStartswith(BoxedString* self, Box* elt) {
if (self->cls != str_cls)
raiseExcHelper(TypeError, "descriptor 'startswith' requires a 'str' object but received a '%s'",
getTypeName(elt)->c_str());
if (elt->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object");
BoxedString* sub = static_cast<BoxedString*>(elt);
return boxBool(startswith(self->s, sub->s));
}
Box* strEndswith(BoxedString* self, Box* elt) {
if (self->cls != str_cls)
raiseExcHelper(TypeError, "descriptor 'endswith' requires a 'str' object but received a '%s'",
getTypeName(elt)->c_str());
if (elt->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object");
BoxedString* sub = static_cast<BoxedString*>(elt);
return boxBool(endswith(self->s, sub->s));
}
Box* strFind(BoxedString* self, Box* elt) {
if (self->cls != str_cls)
raiseExcHelper(TypeError, "descriptor 'find' requires a 'str' object but received a '%s'",
getTypeName(elt)->c_str());
if (elt->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object");
BoxedString* sub = static_cast<BoxedString*>(elt);
size_t r = self->s.find(sub->s);
if (r == std::string::npos)
return boxInt(-1);
return boxInt(r);
}
Box* strRfind(BoxedString* self, Box* elt) {
if (self->cls != str_cls)
raiseExcHelper(TypeError, "descriptor 'rfind' requires a 'str' object but received a '%s'",
getTypeName(elt)->c_str());
if (elt->cls != str_cls)
raiseExcHelper(TypeError, "expected a character buffer object");
BoxedString* sub = static_cast<BoxedString*>(elt);
size_t r = self->s.rfind(sub->s);
if (r == std::string::npos)
return boxInt(-1);
return boxInt(r);
}
extern "C" Box* strGetitem(BoxedString* self, Box* slice) {
assert(self->cls == str_cls);
......@@ -851,9 +910,7 @@ void setupStr() {
str_cls->giveAttr("upper", new BoxedFunction(boxRTFunction((void*)strUpper, STR, 1)));
str_cls->giveAttr("strip", new BoxedFunction(boxRTFunction((void*)strStrip, STR, 2, 1, false, false), { None }));
str_cls->giveAttr("lstrip", new BoxedFunction(boxRTFunction((void*)strLStrip, STR, 2, 1, false, false), { None }));
str_cls->giveAttr("rstrip", new BoxedFunction(boxRTFunction((void*)strRStrip, STR, 2, 1, false, false), { None }));
str_cls->giveAttr("capitalize", new BoxedFunction(boxRTFunction((void*)strCapitalize, STR, 1)));
......@@ -861,6 +918,12 @@ 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("find", new BoxedFunction(boxRTFunction((void*)strFind, BOXED_INT, 2)));
str_cls->giveAttr("rfind", new BoxedFunction(boxRTFunction((void*)strRfind, BOXED_INT, 2)));
str_cls->giveAttr("__add__", new BoxedFunction(boxRTFunction((void*)strAdd, UNKNOWN, 2)));
str_cls->giveAttr("__mod__", new BoxedFunction(boxRTFunction((void*)strMod, STR, 2)));
str_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)strMul, UNKNOWN, 2)));
......
......@@ -805,14 +805,16 @@ void setupRuntime() {
TRACK_ALLOCATIONS = true;
}
BoxedModule* createModule(const std::string& name, const std::string& fn) {
BoxedModule* createModule(const std::string& name, const std::string& fn, bool add_to_sys_modules) {
assert(fn.size() && "probably wanted to set the fn to <stdin>?");
BoxedModule* module = new BoxedModule(name, fn);
if (add_to_sys_modules) {
BoxedDict* d = getSysModulesDict();
Box* b_name = boxStringPtr(&name);
assert(d->d.count(b_name) == 0);
d->d[b_name] = module;
}
module->giveAttr("__doc__", None);
return module;
......
# expected: fail
# execfile() not implemented yet
execfile("execfile_target.py")
try:
execfile("doesnt_exist.py")
except IOError, e:
print e
import os
fn = os.path.join(os.path.dirname(__file__), 'execfile_target.py')
execfile(fn)
print "done with first execfile"
execfile("execfile_target.py")
execfile(fn)
......@@ -56,3 +56,7 @@ print sorted([str(i) for i in xrange(25)])
for i in xrange(-3, 5):
print i, "bananananananananana".split("an", i)
for i in ["", "a", "ab", "aa"]:
for j in ["", "b", "a", "ab", "aa"]:
print i, j, i.startswith(j), j.startswith(i), i.endswith(j), j.endswith(i), i.find(j), j.find(i), i.rfind(j), j.rfind(i)
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