Commit 42b34706 authored by Kevin Modzelewski's avatar Kevin Modzelewski

print statement improvements

`print >>None` goes to stdout, and printing to things without write()
functions should throw exceptions.
parent 87d01381
...@@ -2003,7 +2003,7 @@ private: ...@@ -2003,7 +2003,7 @@ private:
ConcreteCompilerVariable* dest = NULL; ConcreteCompilerVariable* dest = NULL;
if (node->dest) { if (node->dest) {
auto d = evalExpr(node->dest, unw_info); auto d = evalExpr(node->dest, unw_info);
dest = d->makeConverted(emitter, d->getConcreteType()); dest = d->makeConverted(emitter, d->getBoxType());
d->decvref(emitter); d->decvref(emitter);
} else { } else {
llvm::Value* sys_stdout_val = emitter.createCall(unw_info, g.funcs.getSysStdout); llvm::Value* sys_stdout_val = emitter.createCall(unw_info, g.funcs.getSysStdout);
...@@ -2012,63 +2012,22 @@ private: ...@@ -2012,63 +2012,22 @@ private:
} }
assert(dest); assert(dest);
static BoxedString* write_str = internStringImmortal("write"); assert(node->values.size() <= 1);
static BoxedString* newline_str = internStringImmortal("\n"); ConcreteCompilerVariable* converted;
static BoxedString* space_str = internStringImmortal(" ");
// TODO: why are we inline-generating all this code instead of just emitting a call to some runtime function? if (node->values.size() == 1) {
// (=printHelper()) CompilerVariable* var = evalExpr(node->values[0], unw_info);
int nvals = node->values.size(); converted = var->makeConverted(emitter, var->getBoxType());
for (int i = 0; i < nvals; i++) {
CompilerVariable* var = evalExpr(node->values[i], unw_info);
ConcreteCompilerVariable* converted = var->makeConverted(emitter, var->getBoxType());
var->decvref(emitter); var->decvref(emitter);
} else {
// begin code for handling of softspace converted = new ConcreteCompilerVariable(UNKNOWN, getNullPtr(g.llvm_value_type_ptr), true);
bool new_softspace = (i < nvals - 1) || (!node->nl);
llvm::Value* dospace = emitter.createCall(unw_info, g.funcs.softspace,
{ dest->getValue(), getConstantInt(new_softspace, g.i1) });
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);
CallattrFlags flags = {.cls_only = false, .null_on_nonexistent = false, .argspec = ArgPassSpec(1) };
auto r = dest->callattr(emitter, getOpInfoForNode(node, unw_info), write_str, flags, { 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(unw_info, g.funcs.strOrUnicode, converted->getValue());
v = emitter.getBuilder()->CreateBitCast(v, g.llvm_value_type_ptr);
auto s = new ConcreteCompilerVariable(STR, v, true);
r = dest->callattr(emitter, getOpInfoForNode(node, unw_info), write_str, flags, { s }, NULL);
s->decvref(emitter);
r->decvref(emitter);
converted->decvref(emitter);
} }
if (node->nl) { emitter.createCall3(unw_info, g.funcs.printHelper, dest->getValue(), converted->getValue(),
CallattrFlags flags = {.cls_only = false, .null_on_nonexistent = false, .argspec = ArgPassSpec(1) }; getConstantInt(node->nl, g.i1));
auto r = dest->callattr(emitter, getOpInfoForNode(node, unw_info), write_str, flags,
{ makeStr(newline_str) }, NULL);
r->decvref(emitter);
if (nvals == 0) {
emitter.createCall(unw_info, g.funcs.softspace, { dest->getValue(), getConstantInt(0, g.i1) });
}
}
dest->decvref(emitter); dest->decvref(emitter);
converted->decvref(emitter);
} }
void doReturn(AST_Return* node, const UnwindInfo& unw_info) { void doReturn(AST_Return* node, const UnwindInfo& unw_info) {
......
...@@ -240,6 +240,7 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -240,6 +240,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(assertFailDerefNameDefined); GET(assertFailDerefNameDefined);
GET(assertFail); GET(assertFail);
GET(printExprHelper); GET(printExprHelper);
GET(printHelper);
GET(printFloat); GET(printFloat);
GET(listAppendInternal); GET(listAppendInternal);
......
...@@ -42,7 +42,7 @@ struct GlobalFuncs { ...@@ -42,7 +42,7 @@ struct GlobalFuncs {
llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseAttributeErrorCapi, llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseAttributeErrorCapi,
*raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *raiseIndexErrorStrCapi, *raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *raiseIndexErrorStrCapi,
*assertNameDefined, *assertFail, *assertFailDerefNameDefined, *printExprHelper; *assertNameDefined, *assertFail, *assertFailDerefNameDefined, *printExprHelper, *printHelper;
llvm::Value* printFloat, *listAppendInternal, *getSysStdout; llvm::Value* printFloat, *listAppendInternal, *getSysStdout;
ExceptionSwitchable<llvm::Value*> runtimeCall0, runtimeCall1, runtimeCall2, runtimeCall3, runtimeCall, runtimeCallN; ExceptionSwitchable<llvm::Value*> runtimeCall0, runtimeCall1, runtimeCall2, runtimeCall3, runtimeCall, runtimeCallN;
ExceptionSwitchable<llvm::Value*> callattr0, callattr1, callattr2, callattr3, callattr, callattrN; ExceptionSwitchable<llvm::Value*> callattr0, callattr1, callattr2, callattr3, callattr, callattrN;
......
...@@ -113,6 +113,7 @@ void force() { ...@@ -113,6 +113,7 @@ void force() {
FORCE(assertFailDerefNameDefined); FORCE(assertFailDerefNameDefined);
FORCE(assertFail); FORCE(assertFail);
FORCE(printExprHelper); FORCE(printExprHelper);
FORCE(printHelper);
FORCE(strOrUnicode); FORCE(strOrUnicode);
FORCE(printFloat); FORCE(printFloat);
......
...@@ -222,6 +222,9 @@ extern "C" void printHelper(Box* dest, Box* var, bool nl) { ...@@ -222,6 +222,9 @@ extern "C" void printHelper(Box* dest, Box* var, bool nl) {
static BoxedString* newline_str = internStringImmortal("\n"); static BoxedString* newline_str = internStringImmortal("\n");
static BoxedString* space_str = internStringImmortal(" "); static BoxedString* space_str = internStringImmortal(" ");
if (dest == None)
dest = getSysStdout();
if (var) { if (var) {
// begin code for handling of softspace // begin code for handling of softspace
bool new_softspace = !nl; bool new_softspace = !nl;
...@@ -229,11 +232,17 @@ extern "C" void printHelper(Box* dest, Box* var, bool nl) { ...@@ -229,11 +232,17 @@ extern "C" void printHelper(Box* dest, Box* var, bool nl) {
callattrInternal<CXX>(dest, write_str, CLASS_OR_INST, 0, ArgPassSpec(1), space_str, 0, 0, 0, 0); callattrInternal<CXX>(dest, write_str, CLASS_OR_INST, 0, ArgPassSpec(1), space_str, 0, 0, 0, 0);
Box* str_or_unicode_var = (var->cls == unicode_cls) ? var : str(var); Box* str_or_unicode_var = (var->cls == unicode_cls) ? var : str(var);
callattrInternal<CXX>(dest, write_str, CLASS_OR_INST, 0, ArgPassSpec(1), str_or_unicode_var, 0, 0, 0, 0); Box* write_rtn
= callattrInternal<CXX>(dest, write_str, CLASS_OR_INST, 0, ArgPassSpec(1), str_or_unicode_var, 0, 0, 0, 0);
if (!write_rtn)
raiseAttributeError(dest, write_str->s());
} }
if (nl) { if (nl) {
callattrInternal<CXX>(dest, write_str, CLASS_OR_INST, 0, ArgPassSpec(1), newline_str, 0, 0, 0, 0); Box* write_rtn
= callattrInternal<CXX>(dest, write_str, CLASS_OR_INST, 0, ArgPassSpec(1), newline_str, 0, 0, 0, 0);
if (!write_rtn)
raiseAttributeError(dest, write_str->s());
if (!var) if (!var)
softspace(dest, false); softspace(dest, false);
} }
......
...@@ -54,3 +54,9 @@ try: ...@@ -54,3 +54,9 @@ try:
assert 0, "expected TypeError was not thrown" assert 0, "expected TypeError was not thrown"
except TypeError: except TypeError:
pass pass
print >>None, "this should still print"
try:
print >>1, "this should error"
except AttributeError as 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