Commit fe8fa138 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Faithfully follow the Python 'print' protocol, at the cost of performance.

Need this to track "softspace" correctly...
parent e6ebbb72
// This file is originally from CPython 2.7, with modifications for Pyston
#ifndef Py_STRUCTMEMBER_H
#define Py_STRUCTMEMBER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Interface to map C struct members to Python object attributes */
#include <stddef.h> /* For offsetof */
/* The offsetof() macro calculates the offset of a structure member
in its structure. Unfortunately this cannot be written down
portably, hence it is provided by a Standard C header file.
For pre-Standard C compilers, here is a version that usually works
(but watch out!): */
#ifndef offsetof
#define offsetof(type, member) ( (int) & ((type*)0) -> member )
#endif
/* An array of memberlist structures defines the name, type and offset
of selected members of a C structure. These can be read by
PyMember_Get() and set by PyMember_Set() (except if their READONLY flag
is set). The array must be terminated with an entry whose name
pointer is NULL. */
struct memberlist {
/* Obsolete version, for binary backwards compatibility */
char *name;
int type;
int offset;
int flags;
};
typedef struct PyMemberDef {
/* Current version, use this */
char *name;
int type;
Py_ssize_t offset;
int flags;
char *doc;
} PyMemberDef;
/* Types */
#define T_SHORT 0
#define T_INT 1
#define T_LONG 2
#define T_FLOAT 3
#define T_DOUBLE 4
#define T_STRING 5
#define T_OBJECT 6
/* XXX the ordering here is weird for binary compatibility */
#define T_CHAR 7 /* 1-character string */
#define T_BYTE 8 /* 8-bit signed int */
/* unsigned variants: */
#define T_UBYTE 9
#define T_USHORT 10
#define T_UINT 11
#define T_ULONG 12
/* Added by Jack: strings contained in the structure */
#define T_STRING_INPLACE 13
/* Added by Lillo: bools contained in the structure (assumed char) */
#define T_BOOL 14
#define T_OBJECT_EX 16 /* Like T_OBJECT, but raises AttributeError
when the value is NULL, instead of
converting to None. */
#ifdef HAVE_LONG_LONG
#define T_LONGLONG 17
#define T_ULONGLONG 18
#endif /* HAVE_LONG_LONG */
#define T_PYSSIZET 19 /* Py_ssize_t */
/* Flags */
#define READONLY 1
#define RO READONLY /* Shorthand */
#define READ_RESTRICTED 2
#define PY_WRITE_RESTRICTED 4
#define RESTRICTED (READ_RESTRICTED | PY_WRITE_RESTRICTED)
/* Obsolete API, for binary backwards compatibility */
PyAPI_FUNC(PyObject *) PyMember_Get(const char *, struct memberlist *, const char *);
PyAPI_FUNC(int) PyMember_Set(char *, struct memberlist *, const char *, PyObject *);
/* Current API, use this */
PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, struct PyMemberDef *);
PyAPI_FUNC(int) PyMember_SetOne(char *, struct PyMemberDef *, PyObject *);
#ifdef __cplusplus
}
#endif
#endif /* !Py_STRUCTMEMBER_H */
......@@ -363,8 +363,8 @@ check:
$(MAKE) run_unittests
@# jit_prof forces the use of GCC as the compiler, which can expose other errors, so just build it and see what happens:
# $(MAKE) check_prof
$(MAKE) pyston_prof
@# and run some basic tests to make sure it works:
$(call checksha,./pyston_prof -cq $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d)
$(call checksha,./pyston_prof -cqn $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d)
$(call checksha,./pyston_prof -cqO $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d)
......
......@@ -178,11 +178,6 @@ public:
virtual bool isFitBy(BoxedClass* c) { return true; }
// XXX should get rid of this implementation and have it just do print o.__repr__()
virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
emitter.createCall(info.exc_info, g.funcs.print, var->getValue());
}
virtual CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
const std::string* attr, bool cls_only);
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
......@@ -728,14 +723,6 @@ public:
// pass
}
virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
assert(var->getValue()->getType() == g.i64);
llvm::Constant* int_fmt = getStringConstantPtr("%ld");
;
emitter.getBuilder()->CreateCall2(g.funcs.printf, int_fmt, var->getValue());
}
virtual CompilerType* getattrType(const std::string* attr, bool cls_only) {
/*
static std::vector<AbstractFunctionType::Sig*> sigs;
......@@ -944,12 +931,6 @@ public:
// pass
}
virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
assert(var->getValue()->getType() == g.double_);
emitter.getBuilder()->CreateCall(g.funcs.printFloat, var->getValue());
}
virtual CompilerType* getattrType(const std::string* attr, bool cls_only) {
static std::vector<AbstractFunctionType::Sig*> sigs;
if (sigs.size() == 0) {
......@@ -984,12 +965,22 @@ public:
virtual CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
const std::string* attr, bool cls_only) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_INT);
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_FLOAT);
CompilerVariable* rtn = converted->getattr(emitter, info, attr, cls_only);
converted->decvref(emitter);
return rtn;
}
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
const std::string* attr, bool clsonly, ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_FLOAT);
CompilerVariable* rtn = converted->callattr(emitter, info, attr, clsonly, argspec, args, keyword_names);
converted->decvref(emitter);
return rtn;
}
virtual void setattr(IREmitter& emitter, const OpInfo& info, VAR* var, const std::string* attr,
CompilerVariable* v) {
llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
......@@ -1270,12 +1261,6 @@ public:
return UNKNOWN->delattr(emitter, info, var, attr);
}
virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, UNKNOWN);
converted->print(emitter, info);
converted->decvref(emitter);
}
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
ArgPassSpec argspec, const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) {
......@@ -1539,7 +1524,7 @@ public:
} _GENERATOR;
ConcreteCompilerType* GENERATOR = &_GENERATOR;
class StrConstantType : public ValuedCompilerType<std::string*> {
class StrConstantType : public ValuedCompilerType<const std::string*> {
public:
std::string debugName() { return "str_constant"; }
......@@ -1555,14 +1540,7 @@ public:
// pass
}
virtual void print(IREmitter& emitter, const OpInfo& info, ValuedCompilerVariable<std::string*>* value) {
llvm::Constant* ptr = getStringConstantPtr(*(value->getValue()) + '\0');
llvm::Constant* fmt = getStringConstantPtr("%s\0");
emitter.getBuilder()->CreateCall2(g.funcs.printf, fmt, ptr);
}
virtual ConcreteCompilerVariable* makeConverted(IREmitter& emitter, ValuedCompilerVariable<std::string*>* var,
ConcreteCompilerType* other_type) {
virtual ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var, ConcreteCompilerType* other_type) {
assert(other_type == STR || other_type == UNKNOWN);
llvm::Value* boxed = emitter.getBuilder()->CreateCall(g.funcs.boxStringPtr,
embedConstantPtr(var->getValue(), g.llvm_str_type_ptr));
......@@ -1618,10 +1596,10 @@ public:
return rtn;
}
};
ValuedCompilerType<std::string*>* STR_CONSTANT = new StrConstantType();
static ValuedCompilerType<const std::string*>* STR_CONSTANT = new StrConstantType();
CompilerVariable* makeStr(std::string* s) {
return new ValuedCompilerVariable<std::string*>(STR_CONSTANT, s, true);
CompilerVariable* makeStr(const std::string* s) {
return new ValuedCompilerVariable<const std::string*>(STR_CONSTANT, s, true);
}
class VoidType : public ConcreteCompilerType {
......@@ -1647,14 +1625,6 @@ public:
virtual void grab(IREmitter& emitter, VAR* var) {
// pass
}
virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
assert(var->getValue()->getType() == g.i1);
llvm::Value* true_str = getStringConstantPtr("True");
llvm::Value* false_str = getStringConstantPtr("False");
llvm::Value* selected = emitter.getBuilder()->CreateSelect(var->getValue(), true_str, false_str);
emitter.getBuilder()->CreateCall(g.funcs.printf, selected);
}
virtual ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
var->incvref();
......@@ -1689,6 +1659,16 @@ public:
return rtn;
}
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
const std::string* attr, bool clsonly, ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, BOXED_BOOL);
CompilerVariable* rtn = converted->callattr(emitter, info, attr, clsonly, argspec, args, keyword_names);
converted->decvref(emitter);
return rtn;
}
CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* rhs,
AST_TYPE::AST_TYPE op_type, BinExpType exp_type) override {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, UNKNOWN);
......@@ -1753,10 +1733,6 @@ public:
return rtn;
}
virtual void print(IREmitter& emitter, const OpInfo& info, VAR* var) {
return makeConverted(emitter, var, getConcreteType())->print(emitter, info);
}
virtual bool canConvertTo(ConcreteCompilerType* other_type) {
return (other_type == UNKNOWN || other_type == BOXED_TUPLE);
}
......@@ -1881,7 +1857,6 @@ public:
}
return rtn;
}
virtual void print(IREmitter& emitter, const OpInfo& info, VAR* var) {}
virtual ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var, ConcreteCompilerType* other_type) {
llvm::Value* v = llvm::UndefValue::get(other_type->llvmType());
return new ConcreteCompilerVariable(other_type, v, true);
......
......@@ -119,10 +119,6 @@ public:
printf("call not defined for %s\n", debugName().c_str());
abort();
}
virtual void print(IREmitter& emitter, const OpInfo& info, VAR* var) {
printf("print not defined for %s\n", debugName().c_str());
abort();
}
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) {
printf("len not defined for %s\n", debugName().c_str());
abort();
......@@ -245,7 +241,6 @@ public:
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, struct ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) = 0;
virtual void print(IREmitter& emitter, const OpInfo& info) = 0;
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) = 0;
virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, CompilerVariable*) = 0;
virtual CompilerVariable* binexp(IREmitter& emitter, const OpInfo& info, CompilerVariable* rhs,
......@@ -318,7 +313,6 @@ public:
const std::vector<const std::string*>* keyword_names) override {
return type->call(emitter, info, this, argspec, args, keyword_names);
}
void print(IREmitter& emitter, const OpInfo& info) override { type->print(emitter, info, this); }
ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) override {
return type->len(emitter, info, this);
}
......@@ -348,7 +342,7 @@ ConcreteCompilerVariable* makeInt(int64_t);
ConcreteCompilerVariable* makeFloat(double);
ConcreteCompilerVariable* makeBool(bool);
ConcreteCompilerVariable* makeLong(IREmitter& emitter, std::string&);
CompilerVariable* makeStr(std::string*);
CompilerVariable* makeStr(const std::string*);
CompilerVariable* makeFunction(IREmitter& emitter, CLFunction*, CompilerVariable* closure, bool isGenerator,
const std::vector<ConcreteCompilerVariable*>& defaults);
ConcreteCompilerVariable* undefVariable();
......
......@@ -250,6 +250,12 @@ private:
OpInfo getEmptyOpInfo(ExcInfo exc_info) { return OpInfo(irstate->getEffortLevel(), NULL, exc_info); }
// Helper function:
void raiseSyntaxError(const char* msg, AST* node_at) {
::pyston::raiseSyntaxError(msg, node_at->lineno, node_at->col_offset,
irstate->getSourceInfo()->parent_module->fn, irstate->getLLVMFunction()->getName());
}
void createExprTypeGuard(llvm::Value* check_val, AST_expr* node, CompilerVariable* node_value) {
assert(check_val->getType() == g.i1);
......@@ -1577,8 +1583,7 @@ private:
// there will be things that end up not getting cleaned up.
// Then again, there are a huge number of things that don't get cleaned up even
// if an exception doesn't get thrown...
raiseSyntaxError("the __future__ module is not supported yet", node->lineno, node->col_offset,
irstate->getSourceInfo()->parent_module->fn, irstate->getLLVMFunction()->getName());
raiseSyntaxError("the __future__ module is not supported yet", node);
}
assert(node->level == 0);
......@@ -1618,20 +1623,73 @@ private:
if (state == PARTIAL)
return;
RELEASE_ASSERT(node->dest == NULL, "");
for (int i = 0; i < node->values.size(); i++) {
if (i > 0) {
emitter.getBuilder()->CreateCall(g.funcs.printf, getStringConstantPtr(" "));
}
ConcreteCompilerVariable* dest = NULL;
if (node->dest) {
auto d = evalExpr(node->dest, exc_info);
dest = d->makeConverted(emitter, d->getConcreteType());
d->decvref(emitter);
} else {
dest = new ConcreteCompilerVariable(typeFromClass(file_cls),
embedConstantPtr(getSysStdout(), g.llvm_value_type_ptr), true);
}
assert(dest);
static const std::string write_str("write");
static const std::string newline_str("\n");
static const std::string space_str(" ");
int nvals = node->values.size();
for (int i = 0; i < nvals; i++) {
CompilerVariable* var = evalExpr(node->values[i], exc_info);
var->print(emitter, getEmptyOpInfo(exc_info));
ConcreteCompilerVariable* converted = var->makeConverted(emitter, var->getBoxType());
var->decvref(emitter);
// begin code for handling of softspace
bool new_softspace = (i < nvals - 1) || (!node->nl);
llvm::Value* dospace
= emitter.createCall(exc_info, g.funcs.softspace,
{ dest->getValue(), getConstantInt(new_softspace, g.i1) }).getInstruction();
assert(dospace->getType() == g.i1);
llvm::BasicBlock* ss_block = llvm::BasicBlock::Create(g.context, "softspace", irstate->getLLVMFunction());
llvm::BasicBlock* join_block = llvm::BasicBlock::Create(g.context, "print", irstate->getLLVMFunction());
emitter.getBuilder()->CreateCondBr(dospace, ss_block, join_block);
curblock = ss_block;
emitter.getBuilder()->SetInsertPoint(ss_block);
auto r = dest->callattr(emitter, getOpInfoForNode(node, exc_info), &write_str, false, ArgPassSpec(1),
{ makeStr(&space_str) }, NULL);
r->decvref(emitter);
emitter.getBuilder()->CreateBr(join_block);
curblock = join_block;
emitter.getBuilder()->SetInsertPoint(join_block);
// end code for handling of softspace
llvm::Value* v = emitter.createCall(exc_info, g.funcs.str, { converted->getValue() }).getInstruction();
v = emitter.getBuilder()->CreateBitCast(v, g.llvm_value_type_ptr);
auto s = new ConcreteCompilerVariable(STR, v, true);
r = dest->callattr(emitter, getOpInfoForNode(node, exc_info), &write_str, false, ArgPassSpec(1), { s },
NULL);
s->decvref(emitter);
r->decvref(emitter);
converted->decvref(emitter);
}
if (node->nl)
emitter.createCall(exc_info, g.funcs.printf, getStringConstantPtr("\n"));
else
emitter.createCall(exc_info, g.funcs.printf, getStringConstantPtr(" "));
if (node->nl) {
auto r = dest->callattr(emitter, getOpInfoForNode(node, exc_info), &write_str, false, ArgPassSpec(1),
{ makeStr(&newline_str) }, NULL);
r->decvref(emitter);
if (nvals == 0) {
emitter.createCall(exc_info, g.funcs.softspace, { dest->getValue(), getConstantInt(0, g.i1) });
}
}
dest->decvref(emitter);
}
void doReturn(AST_Return* node, ExcInfo exc_info) {
......
......@@ -151,6 +151,8 @@ void initGlobalFuncs(GlobalState& g) {
g.funcs.allowGLReadPreemption = addFunc((void*)threading::allowGLReadPreemption, g.void_);
GET(softspace);
GET(boxCLFunction);
GET(unboxCLFunction);
GET(createUserClass);
......@@ -191,6 +193,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(importFrom);
GET(importStar);
GET(repr);
GET(str);
GET(isinstance);
GET(yield);
......
......@@ -28,6 +28,8 @@ namespace pyston {
struct GlobalFuncs {
llvm::Value* allowGLReadPreemption;
llvm::Value* softspace;
llvm::Value* printf, *my_assert, *malloc, *free;
llvm::Value* boxInt, *unboxInt, *boxFloat, *unboxFloat, *boxStringPtr, *boxCLFunction, *unboxCLFunction,
......@@ -35,7 +37,7 @@ struct GlobalFuncs {
*createUserClass, *createClosure, *createGenerator, *createLong, *createSet;
llvm::Value* getattr, *setattr, *delattr, *delitem, *delGlobal, *print, *nonzero, *binop, *compare, *augbinop,
*unboxedLen, *getitem, *getclsattr, *getGlobal, *setitem, *unaryop, *import, *importFrom, *importStar, *repr,
*isinstance, *yield;
*str, *isinstance, *yield;
llvm::Value* checkUnpackingLength, *raiseAttributeError, *raiseAttributeErrorStr, *raiseNotIterableError,
*assertNameDefined, *assertFail;
......
......@@ -53,6 +53,12 @@ BoxedList* getSysPath() {
return static_cast<BoxedList*>(_sys_path);
}
Box* getSysStdout() {
Box* sys_stdout = sys_module->getattr("stdout");
RELEASE_ASSERT(sys_stdout, "lost sys.stdout??");
return sys_stdout;
}
void addToSysArgv(const char* str) {
Box* sys_argv = sys_module->getattr("argv");
assert(sys_argv);
......
......@@ -173,6 +173,9 @@ void setupFile() {
file_cls->giveAttr("__enter__", new BoxedFunction(boxRTFunction((void*)fileEnter, typeFromClass(file_cls), 1)));
file_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)fileExit, UNKNOWN, 4)));
file_cls->giveAttr("softspace",
new BoxedMemberDescriptor(BoxedMemberDescriptor::BYTE, offsetof(BoxedFile, softspace)));
file_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)fileNew, UNKNOWN, 3, 1, false, false),
{ boxStrConstant("r") }));
......
......@@ -42,6 +42,7 @@ namespace _force {
#define FORCE(name) forceLink((void*)name)
void force() {
FORCE(softspace);
FORCE(my_assert);
FORCE(boxInt);
......@@ -84,6 +85,7 @@ void force() {
FORCE(importFrom);
FORCE(importStar);
FORCE(repr);
FORCE(str);
FORCE(isinstance);
FORCE(yield);
......
......@@ -295,6 +295,27 @@ bool PyLt::operator()(Box* lhs, Box* rhs) const {
return rtn;
}
extern "C" bool softspace(Box* b, bool newval) {
assert(b);
if (isSubclass(b->cls, file_cls)) {
bool& ss = static_cast<BoxedFile*>(b)->softspace;
bool r = ss;
ss = newval;
return r;
}
bool r;
Box* gotten = b->getattr("softspace");
if (!gotten) {
r = 0;
} else {
r = nonzero(gotten);
}
b->setattr("softspace", boxInt(newval), NULL);
return r;
}
extern "C" void my_assert(bool b) {
assert(b);
}
......@@ -666,6 +687,14 @@ static Box* _handleClsAttr(Box* obj, Box* attr) {
RELEASE_ASSERT(rtn, "");
return rtn;
}
case BoxedMemberDescriptor::BYTE: {
int8_t rtn = reinterpret_cast<int8_t*>(obj)[member_desc->offset];
return boxInt(rtn);
}
case BoxedMemberDescriptor::BOOL: {
bool rtn = reinterpret_cast<bool*>(obj)[member_desc->offset];
return boxBool(rtn);
}
default:
RELEASE_ASSERT(0, "%d", member_desc->type);
}
......@@ -1093,14 +1122,12 @@ extern "C" BoxedString* str(Box* obj) {
slowpath_str.log();
if (obj->cls != str_cls) {
Box* str = getclsattr_internal(obj, "__str__", NULL);
assert(str); // TODO clean the rest of this up now that this assert is true
obj = runtimeCallInternal0(str, NULL, ArgPassSpec(0));
static const std::string str_str("__str__");
obj = callattrInternal(obj, &str_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
}
if (obj->cls != str_cls) {
fprintf(stderr, "__str__ did not return a string!\n");
abort();
raiseExcHelper(TypeError, "__str__ did not return a string!");
}
return static_cast<BoxedString*>(obj);
}
......@@ -1109,9 +1136,8 @@ extern "C" Box* repr(Box* obj) {
static StatCounter slowpath_repr("slowpath_repr");
slowpath_repr.log();
Box* repr = getclsattr_internal(obj, "__repr__", NULL);
assert(repr);
obj = runtimeCall0(repr, ArgPassSpec(0));
static const std::string repr_str("__repr__");
obj = callattrInternal(obj, &repr_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (obj->cls != str_cls) {
raiseExcHelper(TypeError, "__repr__ did not return a string!");
......
......@@ -40,6 +40,7 @@ void raiseExcHelper(BoxedClass*, const char* fmt, ...) __attribute__((__noreturn
extern "C" const std::string* getNameOfClass(BoxedClass* cls);
// TODO sort this
extern "C" bool softspace(Box* b, bool newval);
extern "C" void my_assert(bool b);
extern "C" Box* getattr(Box* obj, const char* attr);
extern "C" void setattr(Box* obj, const char* attr, Box* attr_val);
......
......@@ -17,6 +17,9 @@
#include <ucontext.h>
#include "Python.h"
#include "structmember.h"
#include "core/threading.h"
#include "core/types.h"
#include "gc/gc_alloc.h"
......@@ -68,6 +71,7 @@ void setupSysEnd();
BoxedDict* getSysModulesDict();
BoxedList* getSysPath();
Box* getSysStdout();
extern "C" {
extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *float_cls, *str_cls, *function_cls, *none_cls,
......@@ -260,7 +264,8 @@ class BoxedFile : public Box {
public:
FILE* f;
bool closed;
BoxedFile(FILE* f) __attribute__((visibility("default"))) : Box(file_cls), f(f), closed(false) {}
bool softspace;
BoxedFile(FILE* f) __attribute__((visibility("default"))) : Box(file_cls), f(f), closed(false), softspace(false) {}
};
struct PyHasher {
......@@ -317,7 +322,9 @@ public:
class BoxedMemberDescriptor : public Box {
public:
enum MemberType {
OBJECT,
BOOL = T_BOOL,
BYTE = T_BYTE,
OBJECT = T_OBJECT,
} type;
int offset;
......
# run_args: -n
# callattr: c.foo(i) should theoretically create an instancemethod object and then call that,
# but calling an attribute is such a common case that I special case it as a callattr(),
# but calling an attribute is such a common case that we special case it as a callattr(),
# which avoids the allocation/immediate deallocation of the instancemethod object.
# statcheck: noninit_count('num_instancemethods') <= 10
# statcheck: stats['slowpath_callattr'] <= 20
......
def f(o, msg):
print msg
return o
class C(object):
def write(self, s):
print "class write", repr(s)
c = C()
c2 = C()
def write2(s):
print "instance write", repr(s)
c.write = write2
l = [c, c2]
print >>f(l[0], "evaluating dest"), f(1, "evaluating argument"),
print >>l[0], f(2, "evaluating second argument"),
print "softspace:", c.softspace
print hasattr(c2, "softspace")
print >>l[1], f(3, 3),
print hasattr(c2, "softspace")
print >>l[0], f(4, 4)
print "softspace:", c.softspace
import sys
ss_1 = sys.stdout.softspace
print 1,
ss_2 = sys.stdout.softspace
print
ss_3 = sys.stdout.softspace
print ss_1, ss_2, ss_3
print >>c, c.softspace, c.softspace
print
def clear_softspace():
print c.softspace
print >>c
print c.softspace
return 2
# there is no softspace before the print value of clear_softspace(), even though it looks like there should be
print >>c, c.softspace, clear_softspace(), c.softspace
class D(object):
def __str__(self):
return 1
try:
print >>c, D()
assert 0, "expected TypeError was not thrown"
except TypeError:
pass
# expected: fail
# - I don't feel like implementing this right now
class C(object):
def write(self, s):
print "class write", repr(s)
c = C()
# CPython softspace special-case:
# if you print a string that ends with a newline, don't emit a space on the next print.
# This only applies if you're printing a string object, not to anything else even if they
# will get printed as a string with a newline at the end.
class R(object):
def __str__(self):
print "str"
return "\n"
print >>c, R(),
print c.softspace
print >>c, "\n",
print c.softspace
# expected: fail
import sys
sys.stdout.write("hello world\n")
......
......@@ -29,6 +29,9 @@ def verify_license(_, dir, files):
PYSTON_SRC_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "../src"))
PYSTON_SRC_SUBDIRS = [bn for bn in os.listdir(PYSTON_SRC_DIR) if os.path.isdir(os.path.join(PYSTON_SRC_DIR, bn))]
CAPI_HEADER_DIR = os.path.join(PYSTON_SRC_DIR, "../include")
CAPI_HEADERS = [bn for bn in os.listdir(CAPI_HEADER_DIR) if bn.endswith(".h")]
def verify_include_order(_, dir, files):
for bn in files:
fn = os.path.join(dir, bn)
......@@ -81,8 +84,17 @@ def verify_include_order(_, dir, files):
for incl in section:
if incl.startswith('#include "llvm/'):
continue
if '"opagent.h"' in incl or '"Python.h"' in incl or '"object.h"' in incl:
if '"opagent.h"' in incl:
continue
matches_capi_header = False
for h in CAPI_HEADERS:
if '"%s"' % h in incl:
matches_capi_header = True
break
if matches_capi_header:
continue
return False
return True
......
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