Commit 5c1e2802 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #513 from kmod/dashm

-m support
parents 8b47368a 17ce4263
......@@ -11,10 +11,10 @@ typedef PyObject *(*getter)(PyObject *, void *);
typedef int (*setter)(PyObject *, PyObject *, void *);
typedef struct PyGetSetDef {
char *name;
const char *name;
getter get;
setter set;
char *doc;
const char *doc;
void *closure;
} PyGetSetDef;
......
......@@ -354,7 +354,55 @@ extern "C" void PyErr_Display(PyObject* exception, PyObject* value, PyObject* tb
}
static void handle_system_exit(void) noexcept {
Py_FatalError("unimplemented");
PyObject* exception, *value, *tb;
int exitcode = 0;
if (Py_InspectFlag)
/* Don't exit if -i flag was given. This flag is set to 0
* when entering interactive mode for inspecting. */
return;
PyErr_Fetch(&exception, &value, &tb);
if (Py_FlushLine())
PyErr_Clear();
fflush(stdout);
if (value == NULL || value == Py_None)
goto done;
if (PyExceptionInstance_Check(value)) {
/* The error code should be in the `code' attribute. */
PyObject* code = PyObject_GetAttrString(value, "code");
if (code) {
Py_DECREF(value);
value = code;
if (value == Py_None)
goto done;
}
/* If we failed to dig out the 'code' attribute,
just let the else clause below print the error. */
}
if (PyInt_Check(value))
exitcode = (int)PyInt_AsLong(value);
else {
PyObject* sys_stderr = PySys_GetObject("stderr");
if (sys_stderr != NULL && sys_stderr != Py_None) {
PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW);
} else {
PyObject_Print(value, stderr, Py_PRINT_RAW);
fflush(stderr);
}
PySys_WriteStderr("\n");
exitcode = 1;
}
done:
/* Restore and clear the exception info, in order to properly decref
* the exception, value, and traceback. If we just exit instead,
* these leak, which confuses PYTHONDUMPREFS output, and may prevent
* some finalizers from running.
*/
PyErr_Restore(exception, value, tb);
PyErr_Clear();
Py_Exit(exitcode);
/* NOTREACHED */
}
extern "C" void PyErr_PrintEx(int set_sys_last_vars) noexcept {
......
......@@ -82,6 +82,7 @@ bool BOOLS_AS_I64 = ENABLE_FRAME_INTROSPECTION;
extern "C" {
int Py_FrozenFlag = 1;
int Py_IgnoreEnvironmentFlag = 0;
int Py_InspectFlag = 0;
int Py_NoSiteFlag = 0;
int Py_OptimizeFlag = 0;
int Py_VerboseFlag = 0;
......
......@@ -31,6 +31,7 @@
#include "osdefs.h"
#include "capi/types.h"
#include "codegen/entry.h"
#include "codegen/irgen/hooks.h"
#include "codegen/parser.h"
......@@ -54,42 +55,7 @@ namespace pyston {
extern void setEncodingAndErrors();
// returns true iff we got a request to exit, i.e. SystemExit, placing the
// return code in `*retcode`. does not touch `*retcode* if it returns false.
static bool handle_toplevel_exn(const ExcInfo& e, int* retcode) {
if (e.matches(SystemExit)) {
Box* value = e.value;
if (value && PyExceptionInstance_Check(value)) {
Box* code = getattr(value, "code");
if (code)
value = code;
}
if (!value || value == None)
*retcode = 0;
else if (isSubclass(value->cls, int_cls))
*retcode = static_cast<BoxedInt*>(value)->n;
else {
*retcode = 1;
PyObject* sys_stderr = PySys_GetObject("stderr");
if (sys_stderr != NULL && sys_stderr != Py_None) {
PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW);
} else {
PyObject_Print(value, stderr, Py_PRINT_RAW);
fflush(stderr);
}
PySys_WriteStderr("\n");
}
return true;
}
e.printExcAndTraceback();
return false;
}
static bool force_repl = false;
static bool unbuffered = false;
static const char* argv0;
......@@ -186,7 +152,7 @@ int handleArg(char code) {
else if (code == 'I')
FORCE_INTERPRETER = true;
else if (code == 'i')
force_repl = true;
Py_InspectFlag = true;
else if (code == 'n') {
ENABLE_INTERPRETER = false;
} else if (code == 'p') {
......@@ -222,6 +188,41 @@ int handleArg(char code) {
return 0;
}
static int RunModule(const char* module, int set_argv0) {
PyObject* runpy, *runmodule, *runargs, *result;
runpy = PyImport_ImportModule("runpy");
if (runpy == NULL) {
fprintf(stderr, "Could not import runpy module\n");
return -1;
}
runmodule = PyObject_GetAttrString(runpy, "_run_module_as_main");
if (runmodule == NULL) {
fprintf(stderr, "Could not access runpy._run_module_as_main\n");
Py_DECREF(runpy);
return -1;
}
runargs = Py_BuildValue("(si)", module, set_argv0);
if (runargs == NULL) {
fprintf(stderr, "Could not create arguments for runpy._run_module_as_main\n");
Py_DECREF(runpy);
Py_DECREF(runmodule);
return -1;
}
result = PyObject_Call(runmodule, runargs, NULL);
if (result == NULL) {
PyErr_Print();
}
Py_DECREF(runpy);
Py_DECREF(runmodule);
Py_DECREF(runargs);
if (result == NULL) {
return -1;
}
Py_DECREF(result);
return 0;
}
static int main(int argc, char** argv) {
argv0 = argv[0];
......@@ -233,12 +234,13 @@ static int main(int argc, char** argv) {
timespec before_ts, after_ts;
Timer main_time;
int rtncode;
int rtncode = 0;
{
STAT_TIMER2(t0, "us_timer_main_toplevel", main_time.getStartTime());
int code;
const char* command = NULL;
const char* module = NULL;
char* env_args = getenv("PYSTON_RUN_ARGS");
......@@ -253,12 +255,17 @@ static int main(int argc, char** argv) {
// Suppress getopt errors so we can throw them ourselves
opterr = 0;
while ((code = getopt(argc, argv, "+:OqdIibpjtrsSvnxEc:FuPTG")) != -1) {
while ((code = getopt(argc, argv, "+:OqdIibpjtrsSvnxEc:FuPTGm:")) != -1) {
if (code == 'c') {
assert(optarg);
command = optarg;
// no more option parsing; the rest of our arguments go into sys.argv.
break;
} else if (code == 'm') {
assert(optarg);
module = optarg;
// no more option parsing; the rest of our arguments go into sys.argv.
break;
} else if (code == ':') {
fprintf(stderr, "Argument expected for the -%c option\n", optopt);
return 2;
......@@ -299,7 +306,10 @@ static int main(int argc, char** argv) {
// are parsed.
if (command)
addToSysArgv("-c");
else if (optind != argc) {
else if (module) {
// CPython does this...
addToSysArgv("-c");
} else if (optind != argc) {
addToSysArgv(argv[optind]);
if (strcmp("-", argv[optind]) != 0)
fn = argv[optind];
......@@ -351,49 +361,53 @@ static int main(int argc, char** argv) {
main_module = createModule("__main__", "<string>");
AST_Module* m = parse_string(command);
compileAndRunModule(m, main_module);
rtncode = 0;
} catch (ExcInfo e) {
int retcode = 1;
(void)handle_toplevel_exn(e, &retcode);
Stats::dump(false);
return retcode;
}
}
if (fn != NULL) {
llvm::SmallString<128> path;
if (!llvm::sys::path::is_absolute(fn)) {
char cwd_buf[1026];
char* cwd = getcwd(cwd_buf, sizeof(cwd_buf));
assert(cwd);
path = cwd;
setCAPIException(e);
PyErr_Print();
rtncode = 1;
}
} else if (module != NULL) {
// TODO: CPython uses the same main module for all code paths
main_module = createModule("__main__", "<string>");
rtncode = (RunModule(module, 1) != 0);
} else {
rtncode = 0;
if (fn != NULL) {
llvm::SmallString<128> path;
if (!llvm::sys::path::is_absolute(fn)) {
char cwd_buf[1026];
char* cwd = getcwd(cwd_buf, sizeof(cwd_buf));
assert(cwd);
path = cwd;
}
llvm::sys::path::append(path, fn);
llvm::sys::path::remove_filename(path);
char* real_path
= realpath(path.str().str().c_str(), NULL); // inefficient way of null-terminating the string
prependToSysPath(real_path);
free(real_path);
llvm::sys::path::append(path, fn);
llvm::sys::path::remove_filename(path);
char* real_path
= realpath(path.str().str().c_str(), NULL); // inefficient way of null-terminating the string
prependToSysPath(real_path);
free(real_path);
main_module = createModule("__main__", fn);
try {
AST_Module* ast = caching_parse_file(fn);
compileAndRunModule(ast, main_module);
} catch (ExcInfo e) {
int retcode = 1;
(void)handle_toplevel_exn(e, &retcode);
if (!force_repl) {
Stats::dump(false);
return retcode;
main_module = createModule("__main__", fn);
try {
AST_Module* ast = caching_parse_file(fn);
compileAndRunModule(ast, main_module);
} catch (ExcInfo e) {
setCAPIException(e);
PyErr_Print();
rtncode = 1;
}
}
}
if (force_repl || !(command || fn)) {
if (Py_InspectFlag || !(command || fn || module)) {
printf("Pyston v%d.%d (rev " STRINGIFY(GITREV) ")", PYSTON_VERSION_MAJOR, PYSTON_VERSION_MINOR);
printf(", targeting Python %d.%d.%d\n", PYTHON_VERSION_MAJOR, PYTHON_VERSION_MINOR, PYTHON_VERSION_MICRO);
Py_InspectFlag = 0;
if (!main_module) {
main_module = createModule("__main__", "<stdin>");
} else {
......@@ -432,11 +446,8 @@ static int main(int argc, char** argv) {
compileAndRunModule(m, main_module);
} catch (ExcInfo e) {
int retcode = 0xdeadbeef; // should never be seen
if (handle_toplevel_exn(e, &retcode)) {
Stats::dump(false);
return retcode;
}
setCAPIException(e);
PyErr_Print();
}
}
}
......@@ -450,7 +461,7 @@ static int main(int argc, char** argv) {
_t.split("joinRuntime");
rtncode = joinRuntime();
joinRuntime();
_t.split("finishing up");
uint64_t main_time_ended_at;
......
......@@ -685,6 +685,13 @@ void checkAndThrowCAPIException() {
}
}
extern "C" void Py_Exit(int sts) noexcept {
// Py_Finalize();
Stats::dump(false);
exit(sts);
}
extern "C" void PyErr_Restore(PyObject* type, PyObject* value, PyObject* traceback) noexcept {
cur_thread_state.curexc_type = type;
cur_thread_state.curexc_value = value;
......
......@@ -1572,6 +1572,10 @@ static PyObject* file_isatty(BoxedFile* f) noexcept {
return PyBool_FromLong(res);
}
static PyObject* get_closed(BoxedFile* f, void* closure) noexcept {
return PyBool_FromLong((long)(f->f_fp == 0));
}
PyDoc_STRVAR(seek_doc, "seek(offset[, whence]) -> None. Move to new file position.\n"
"\n"
"Argument offset is a byte count. Optional argument whence defaults to\n"
......@@ -1592,13 +1596,17 @@ PyDoc_STRVAR(readlines_doc, "readlines([size]) -> list of strings, each a line f
PyDoc_STRVAR(isatty_doc, "isatty() -> true or false. True if the file is connected to a tty device.");
PyMethodDef file_methods[] = {
static PyMethodDef file_methods[] = {
{ "seek", (PyCFunction)file_seek, METH_VARARGS, seek_doc },
{ "readlines", (PyCFunction)file_readlines, METH_VARARGS, readlines_doc },
{ "writelines", (PyCFunction)file_writelines, METH_O, NULL },
{ "isatty", (PyCFunction)file_isatty, METH_NOARGS, isatty_doc },
};
static PyGetSetDef file_getsetlist[] = {
{ "closed", (getter)get_closed, NULL, "True if the file is closed", NULL },
};
void fileDestructor(Box* b) {
assert(isSubclass(b->cls, file_cls));
BoxedFile* self = static_cast<BoxedFile*>(b);
......@@ -1657,6 +1665,11 @@ void setupFile() {
file_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, file_cls));
}
for (auto& getset : file_getsetlist) {
file_cls->giveAttr(getset.name, new (capi_getset_cls) BoxedGetsetDescriptor(
getset.get, (void (*)(Box*, Box*, void*))getset.set, getset.closure));
}
file_cls->freeze();
}
......
......@@ -235,9 +235,6 @@ extern "C" void raise0() {
#ifndef NDEBUG
ExcInfo::ExcInfo(Box* type, Box* value, Box* traceback) : type(type), value(value), traceback(traceback) {
if (this->type && this->type != None)
RELEASE_ASSERT(isSubclass(this->type->cls, type_cls), "throwing old-style objects not supported yet (%s)",
getTypeName(this->type));
}
#endif
......@@ -253,39 +250,50 @@ bool ExcInfo::matches(BoxedClass* cls) const {
}
// takes the three arguments of a `raise' and produces the ExcInfo to throw
ExcInfo excInfoForRaise(Box* exc_cls, Box* exc_val, Box* exc_tb) {
assert(exc_cls && exc_val && exc_tb); // use None for default behavior, not nullptr
ExcInfo excInfoForRaise(Box* type, Box* value, Box* tb) {
assert(type && value && tb); // use None for default behavior, not nullptr
// TODO switch this to PyErr_Normalize
if (exc_tb == None)
exc_tb = getTraceback();
if (isSubclass(exc_cls->cls, type_cls)) {
BoxedClass* c = static_cast<BoxedClass*>(exc_cls);
if (isSubclass(c, BaseException)) {
Box* exc_obj;
if (isSubclass(exc_val->cls, BaseException)) {
exc_obj = exc_val;
c = exc_obj->cls;
} else if (exc_val != None) {
exc_obj = runtimeCall(c, ArgPassSpec(1), exc_val, NULL, NULL, NULL, NULL);
} else {
exc_obj = runtimeCall(c, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
}
if (tb == None)
tb = getTraceback();
return ExcInfo(c, exc_obj, exc_tb);
}
/* Next, repeatedly, replace a tuple exception with its first item */
while (PyTuple_Check(type) && PyTuple_Size(type) > 0) {
PyObject* tmp = type;
type = PyTuple_GET_ITEM(type, 0);
Py_INCREF(type);
Py_DECREF(tmp);
}
if (isSubclass(exc_cls->cls, BaseException)) {
if (exc_val != None)
if (PyExceptionClass_Check(type)) {
PyErr_NormalizeException(&type, &value, &tb);
if (!PyExceptionInstance_Check(value)) {
raiseExcHelper(TypeError, "calling %s() should have returned an instance of "
"BaseException, not '%s'",
((PyTypeObject*)type)->tp_name, Py_TYPE(value)->tp_name);
}
} else if (PyExceptionInstance_Check(type)) {
/* Raising an instance. The value should be a dummy. */
if (value != Py_None) {
raiseExcHelper(TypeError, "instance exception may not have a separate value");
return ExcInfo(exc_cls->cls, exc_cls, exc_tb);
} else {
/* Normalize to raise <class>, <instance> */
Py_DECREF(value);
value = type;
type = PyExceptionInstance_Class(type);
Py_INCREF(type);
}
} else {
/* Not something you can raise. You get an exception
anyway, just not what you specified :-) */
raiseExcHelper(TypeError, "exceptions must be old-style classes or "
"derived from BaseException, not %s",
type->cls->tp_name);
}
raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not %s",
getTypeName(exc_cls));
assert(PyExceptionClass_Check(type));
return ExcInfo(type, value, tb);
}
extern "C" void raise3(Box* arg0, Box* arg1, Box* arg2) {
......
......@@ -1530,28 +1530,43 @@ public:
return boxInt(attrs->hcls->getStrAttrOffsets().size());
}
static Box* update(Box* _self, Box* _container) {
static Box* update(Box* _self, BoxedTuple* args, BoxedDict* kwargs) {
STAT_TIMER(t0, "us_timer_AttrWrapper_update");
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
if (_container->cls == attrwrapper_cls) {
AttrWrapper* container = static_cast<AttrWrapper*>(_container);
HCAttrs* attrs = container->b->getHCAttrsPtr();
assert(args->cls == tuple_cls);
assert(kwargs);
assert(kwargs->cls == dict_cls);
RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
self->b->setattr(p.first(), attrs->attr_list->attrs[p.second], NULL);
}
} else if (_container->cls == dict_cls) {
BoxedDict* container = static_cast<BoxedDict*>(_container);
RELEASE_ASSERT(args->size() <= 1, ""); // should throw a TypeError
auto handle = [&](Box* _container) {
if (_container->cls == attrwrapper_cls) {
AttrWrapper* container = static_cast<AttrWrapper*>(_container);
HCAttrs* attrs = container->b->getHCAttrsPtr();
for (const auto& p : container->d) {
AttrWrapper::setitem(self, p.first, p.second);
RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON,
"");
for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
self->b->setattr(p.first(), attrs->attr_list->attrs[p.second], NULL);
}
} else if (_container->cls == dict_cls) {
BoxedDict* container = static_cast<BoxedDict*>(_container);
for (const auto& p : container->d) {
AttrWrapper::setitem(self, p.first, p.second);
}
} else {
RELEASE_ASSERT(0, "not implemented: %s", _container->cls->tp_name);
}
} else {
RELEASE_ASSERT(0, "not implemented: %s", _container->cls->tp_name);
};
for (auto e : *args) {
handle(e);
}
handle(kwargs);
return None;
}
......@@ -2481,7 +2496,8 @@ void setupRuntime() {
attrwrapper_cls->giveAttr("copy", new BoxedFunction(boxRTFunction((void*)AttrWrapper::copy, UNKNOWN, 1)));
attrwrapper_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::len, BOXED_INT, 1)));
attrwrapper_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::iter, UNKNOWN, 1)));
attrwrapper_cls->giveAttr("update", new BoxedFunction(boxRTFunction((void*)AttrWrapper::update, NONE, 2)));
attrwrapper_cls->giveAttr("update",
new BoxedFunction(boxRTFunction((void*)AttrWrapper::update, NONE, 1, 0, true, true)));
attrwrapper_cls->freeze();
attrwrapperiter_cls->giveAttr("__hasnext__",
......
import os
import sys
import subprocess
me = sys.executable
with open('/dev/null')as ignore:
def run(args):
print subprocess.call([me] + args, stderr=ignore)
# just prints out the usage
run(["-m", "pydoc"])
run(["-m", "doesnt_exist"])
os.environ["PYTHONPATH"] = os.path.dirname(__file__)
run(["-m", "import_target"])
......@@ -95,7 +95,7 @@ l.sort()
print l
c = C1()
c.__dict__.update(dict(a=1, b=5))
c.__dict__.update(dict(a=1, b=5), d=4)
print sorted(c.__dict__.items())
class TestClass3: # old-style
......
......@@ -91,3 +91,5 @@ try:
print "succeeded"
except Exception as e:
print e
print sys.stdout.closed
# expected: fail
import sys
print sys.stdout.closed
......@@ -20,3 +20,8 @@ __all__ = ['x', u'z']
def letMeCallThatForYou(f, *args):
return f(*args)
if __name__ == "__main__":
import sys
print "running import_target as main"
print "argv:", sys.argv
......@@ -275,3 +275,27 @@ class OldSeqTest:
return n ** 2
m = OldSeqTest()
print list(m)
import sys
class E:
def __init__(self, *args):
print "__init__", args
def __repr__(self):
return "<E object>"
try:
raise E
except:
print sys.exc_info()[0].__name__, sys.exc_info()[1]
try:
raise E, 1
except:
print sys.exc_info()[0].__name__, sys.exc_info()[1]
try:
raise E()
except:
print sys.exc_info()[0].__name__, sys.exc_info()[1]
try:
raise E(), 1
except:
print sys.exc_info()[0].__name__, sys.exc_info()[1]
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