From fee5f32f5818a2fd075aa6035de2fa980d2b8a58 Mon Sep 17 00:00:00 2001 From: Adrian Thurston Date: Tue, 21 Jan 2014 21:28:27 -0500 Subject: the contiguous instruction also pushes a null value An initial push prevents a push-pop-push from clearing the contiguous block. This can happen easily when evaluating args (quals, expresssions, etc). --- src/bytecode.c | 2 ++ src/iter.c | 1 + src/parsedata.h | 1 + src/synthesis.cc | 24 +++++++++++++++++++++--- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/bytecode.c b/src/bytecode.c index 1065d923..d69cf902 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -3343,6 +3343,7 @@ again: read_half( size ); debug( prg, REALM_BYTECODE, "IN_CONTIGUOUS %hd\n", size ); vm_contiguous( size ); + vm_push( 0 ); break; } case IN_INIT_LOCALS: { @@ -3644,6 +3645,7 @@ again: instr = (Code*) vm_pop(); Tree *retVal = vm_pop(); vm_popn( fi->argSize ); + vm_pop(); treeDownref( prg, sp, retVal ); } diff --git a/src/iter.c b/src/iter.c index 3d38fa3a..9e60a2df 100644 --- a/src/iter.c +++ b/src/iter.c @@ -165,6 +165,7 @@ void userIterDestroy2( Program *prg, Tree ***psp, UserIter *uiter ) vm_popn( uiter->yieldSize ); vm_popn( sizeof(UserIter) / sizeof(Word) ); vm_popn( argSize ); + vm_pop(); uiter->type = 0; diff --git a/src/parsedata.h b/src/parsedata.h index 85b70b8c..f9f7df2e 100644 --- a/src/parsedata.h +++ b/src/parsedata.h @@ -979,6 +979,7 @@ struct Compiler bool beginContiguous( CodeVect &code, int stretch ); void endContiguous( CodeVect &code, bool resetContiguous ); + void clearContiguous( CodeVect &code, bool resetContiguous ); void declareReVars(); }; diff --git a/src/synthesis.cc b/src/synthesis.cc index 4286320b..ac77b4b0 100644 --- a/src/synthesis.cc +++ b/src/synthesis.cc @@ -899,7 +899,9 @@ bool Compiler::beginContiguous( CodeVect &code, int stretch ) if ( inContiguous ) contiguousStretch += stretch; else { - contiguousStretch = stretch; + /* We add one for the push that always comes with the contiguous + * statement. */ + contiguousStretch = stretch + 1; code.append( IN_CONTIGUOUS ); contiguousOffset = code.length(); @@ -920,6 +922,14 @@ void Compiler::endContiguous( CodeVect &code, bool resetContiguous ) } } +void Compiler::clearContiguous( CodeVect &code, bool resetContiguous ) +{ + if ( resetContiguous ) { + code.append( IN_TOP_SWAP ); + code.append( IN_POP ); + } +} + UniqueType *LangVarRef::evaluateCall( Compiler *pd, CodeVect &code, CallArgVect *args ) { /* Evaluate the object. */ @@ -944,6 +954,7 @@ UniqueType *LangVarRef::evaluateCall( Compiler *pd, CodeVect &code, CallArgVect delete[] paramRefs; pd->endContiguous( code, resetContiguous ); + pd->clearContiguous( code, resetContiguous ); /* Return the type to the expression. */ return lookup.uniqueType; @@ -1354,6 +1365,7 @@ void LangTerm::evaluateSendStream( Compiler *pd, CodeVect &code ) const * leave the varref on the stack. */ pd->endContiguous( code, resetContiguous ); + pd->clearContiguous( code, resetContiguous ); } void LangTerm::evaluateSendParser( Compiler *pd, CodeVect &code ) const @@ -1873,6 +1885,7 @@ UniqueType *LangTerm::evaluateMakeToken( Compiler *pd, CodeVect &code ) const code.append( args->length() ); pd->endContiguous( code, resetContiguous ); + pd->clearContiguous( code, resetContiguous ); return pd->uniqueTypeAny; } @@ -1903,6 +1916,7 @@ UniqueType *LangTerm::evaluateMakeTree( Compiler *pd, CodeVect &code ) const code.append( args->length() ); pd->endContiguous( code, resetContiguous ); + pd->clearContiguous( code, resetContiguous ); return pd->uniqueTypeAny; } @@ -2002,6 +2016,8 @@ void LangStmt::compileForIter( Compiler *pd, CodeVect &code ) const ObjectField **paramRefs = iterCall->langTerm->varRef->evaluateArgs( pd, code, lookup, iterCall->langTerm->args ); + pd->endContiguous( code, resetContiguous ); + if ( pd->revertOn ) code.append( iterUT->iterDef->inCreateWV ); else @@ -2018,14 +2034,16 @@ void LangStmt::compileForIter( Compiler *pd, CodeVect &code ) const code.appendHalf( searchUT->langEl->id ); } - pd->endContiguous( code, resetContiguous ); - compileForIterBody( pd, code, iterUT ); + iterCall->langTerm->varRef->popRefQuals( pd, code, lookup, iterCall->langTerm->args ); iterCall->langTerm->varRef->resetActiveRefs( pd, lookup, paramRefs ); delete[] paramRefs; + + if ( resetContiguous ) + code.append( IN_POP ); } void LangStmt::compileWhile( Compiler *pd, CodeVect &code ) const -- cgit v1.2.1