diff options
author | Adrian Thurston <thurston@complang.org> | 2014-12-07 12:11:54 -0500 |
---|---|---|
committer | Adrian Thurston <thurston@complang.org> | 2014-12-07 12:11:54 -0500 |
commit | e1b207d6d2642d545f151429d9ffd662d6a82494 (patch) | |
tree | 41b84eb5c64326b74de039fe2142fc97dd88955b /src/synthesis.cc | |
parent | 07e700e57767a14870e50ff1953812727c449c73 (diff) | |
download | colm-e1b207d6d2642d545f151429d9ffd662d6a82494.tar.gz |
support automatic derefs of lists and maps in iterators
Diffstat (limited to 'src/synthesis.cc')
-rw-r--r-- | src/synthesis.cc | 166 |
1 files changed, 96 insertions, 70 deletions
diff --git a/src/synthesis.cc b/src/synthesis.cc index 10c09b4c..d04829bb 100644 --- a/src/synthesis.cc +++ b/src/synthesis.cc @@ -709,7 +709,7 @@ ObjectField *LangVarRef::evaluateRef( Compiler *pd, CodeVect &code, long pushCou ObjectField **LangVarRef::evaluateArgs( Compiler *pd, CodeVect &code, - VarRefLookup &lookup, CallArgVect *args ) + VarRefLookup &lookup, CallArgVect *args, bool derefGenerics ) { /* Parameter list is given only for user defined methods. Otherwise it * will be null. */ @@ -724,101 +724,126 @@ ObjectField **LangVarRef::evaluateArgs( Compiler *pd, CodeVect &code, ObjectField **paramRefs = new ObjectField*[numArgs]; memset( paramRefs, 0, sizeof(ObjectField*) * numArgs ); - /* Evaluate and push the args. */ - if ( args != 0 ) { - /* We use this only if there is a paramter list. */ - ParameterList::Iter p; - long size = 0; - long tempPops = 0; + bool *derefs = new bool[numArgs]; + memset( derefs, 0, sizeof(bool)*numArgs ); + /* Done now if there are no args. */ + if ( args == 0 ) + return paramRefs; + + /* We use this only if there is a paramter list. */ + ParameterList::Iter p; + long size = 0; + long tempPops = 0; + + if ( derefGenerics ) { /* First pass we need to allocate and evaluate temporaries. */ paramList != 0 && ( p = *paramList ); for ( CallArgVect::Iter pe = *args; pe.lte(); pe++ ) { - /* Get the expression and the UT for the arg. */ - LangExpr *expression = (*pe)->expr; - UniqueType *paramUT = lookup.objMethod->paramUTs[pe.pos()]; - - if ( paramUT->typeId == TYPE_REF ) { - /* Make sure we are dealing with a variable reference. */ - if ( ! expression->canTakeRefTest( pd ) ) { - /* Evaluate the expression. */ - UniqueType *exprUT = expression->evaluate( pd, code ); - (*pe)->exprUT = exprUT; - - size += 1; - (*pe)->offTmp = size; - tempPops += 1; - } + CodeVect unused; + UniqueType *ut = (*pe)->expr->evaluate( pd, unused ); + if ( ut->typeId == TYPE_PTR && ut->langEl->generic != 0 && + ( ut->langEl->generic->typeId == GEN_LIST || + ut->langEl->generic->typeId == GEN_MAP ) ) + { + derefs[pe.pos()] = true; } - - /* Advance the parameter list iterator if we have it. */ - paramList != 0 && p.increment(); } + } + /* First pass we need to allocate and evaluate temporaries. */ + paramList != 0 && ( p = *paramList ); + for ( CallArgVect::Iter pe = *args; pe.lte(); pe++ ) { + /* Get the expression and the UT for the arg. */ + LangExpr *expression = (*pe)->expr; + UniqueType *paramUT = lookup.objMethod->paramUTs[pe.pos()]; + + if ( paramUT->typeId == TYPE_REF ) { + /* Make sure we are dealing with a variable reference. */ + if ( derefs[pe.pos()] || ! expression->canTakeRefTest( pd ) ) { + /* Evaluate the expression. */ + UniqueType *exprUT = expression->evaluate( pd, code ); - /* Second pass we need to push object loads for reference parameters. */ - paramList != 0 && ( p = *paramList ); - for ( CallArgVect::Iter pe = *args; pe.lte(); pe++ ) { - /* Get the expression and the UT for the arg. */ - LangExpr *expression = (*pe)->expr; - UniqueType *paramUT = lookup.objMethod->paramUTs[pe.pos()]; + if ( derefs[pe.pos()] ) { + code.append( IN_PTR_DEREF_R ); + exprUT = pd->findUniqueType( TYPE_TREE, exprUT->langEl ); + } - if ( paramUT->typeId == TYPE_REF ) { - if ( expression->canTakeRefTest( pd ) ) { - /* Lookup the field. */ - LangVarRef *varRef = expression->term->varRef; - ObjectField *refOf = varRef->preEvaluateRef( pd, code ); - paramRefs[pe.pos()] = refOf; + (*pe)->exprUT = exprUT; - size += varRef->qual->length() * 2; - (*pe)->offQualRef = size; - } + size += 1; + (*pe)->offTmp = size; + tempPops += 1; } + } + + /* Advance the parameter list iterator if we have it. */ + paramList != 0 && p.increment(); + } - /* Advance the parameter list iterator if we have it. */ - paramList != 0 && p.increment(); + + /* Second pass we need to push object loads for reference parameters. */ + paramList != 0 && ( p = *paramList ); + for ( CallArgVect::Iter pe = *args; pe.lte(); pe++ ) { + /* Get the expression and the UT for the arg. */ + LangExpr *expression = (*pe)->expr; + UniqueType *paramUT = lookup.objMethod->paramUTs[pe.pos()]; + + if ( paramUT->typeId == TYPE_REF ) { + if ( ! derefs[pe.pos()] && expression->canTakeRefTest( pd ) ) { + /* Lookup the field. */ + LangVarRef *varRef = expression->term->varRef; + ObjectField *refOf = varRef->preEvaluateRef( pd, code ); + paramRefs[pe.pos()] = refOf; + + size += varRef->qual->length() * 2; + (*pe)->offQualRef = size; + } } - paramList != 0 && ( p = *paramList ); - for ( CallArgVect::Iter pe = *args; pe.lte(); pe++ ) { - /* Get the expression and the UT for the arg. */ - LangExpr *expression = (*pe)->expr; - UniqueType *paramUT = lookup.objMethod->paramUTs[pe.pos()]; + /* Advance the parameter list iterator if we have it. */ + paramList != 0 && p.increment(); + } - if ( paramUT->typeId == TYPE_REF ) { - if ( expression->canTakeRefTest( pd ) ) { - /* Lookup the field. */ - LangVarRef *varRef = expression->term->varRef; + paramList != 0 && ( p = *paramList ); + for ( CallArgVect::Iter pe = *args; pe.lte(); pe++ ) { + /* Get the expression and the UT for the arg. */ + LangExpr *expression = (*pe)->expr; + UniqueType *paramUT = lookup.objMethod->paramUTs[pe.pos()]; - ObjectField *refOf = varRef->evaluateRef( pd, code, - (size - (*pe)->offQualRef) ); - paramRefs[pe.pos()] = refOf; + if ( paramUT->typeId == TYPE_REF ) { + if ( ! derefs[pe.pos()] && expression->canTakeRefTest( pd ) ) { + /* Lookup the field. */ + LangVarRef *varRef = expression->term->varRef; - size += 2; - } - else { - code.append( IN_REF_FROM_BACK ); - code.appendHalf( size - (*pe)->offTmp ); + ObjectField *refOf = varRef->evaluateRef( pd, code, + (size - (*pe)->offQualRef) ); + paramRefs[pe.pos()] = refOf; - size += 2; - } + size += 2; } else { - UniqueType *exprUT = expression->evaluate( pd, code ); + code.append( IN_REF_FROM_BACK ); + code.appendHalf( size - (*pe)->offTmp ); - if ( !castAssignment( pd, code, paramUT, 0, exprUT ) ) - error(loc) << "arg " << pe.pos()+1 << " is of the wrong type" << endp; - - size += 1; + size += 2; } + } + else { + UniqueType *exprUT = expression->evaluate( pd, code ); + + if ( !castAssignment( pd, code, paramUT, 0, exprUT ) ) + error(loc) << "arg " << pe.pos()+1 << " is of the wrong type" << endp; - /* Advance the parameter list iterator if we have it. */ - paramList != 0 && p.increment(); + size += 1; } - argSize = tempPops; + /* Advance the parameter list iterator if we have it. */ + paramList != 0 && p.increment(); } + argSize = tempPops; + return paramRefs; } @@ -2102,7 +2127,8 @@ void LangStmt::compileForIter( Compiler *pd, CodeVect &code ) const /* Evaluate and push the arguments. */ ObjectField **paramRefs = iterCall->langTerm->varRef->evaluateArgs( - pd, code, lookup, iterCall->langTerm->args ); + pd, code, lookup, iterCall->langTerm->args, + ( iterCall->wasExpr ? true : false ) ); pd->endContiguous( code, resetContiguous ); |