diff options
author | Adrian Thurston <thurston@complang.org> | 2013-06-03 00:29:29 +0000 |
---|---|---|
committer | Adrian Thurston <thurston@complang.org> | 2013-06-03 00:30:20 +0000 |
commit | 8dbc115720d6cca9c880af41ac14c7c0707d2d2d (patch) | |
tree | c5494bc475433bda34f4e3645ae31e8a121b57cf | |
parent | cad4e8ef93185ee16e95337277e470db123b541c (diff) | |
download | colm-8dbc115720d6cca9c880af41ac14c7c0707d2d2d.tar.gz |
first pass at taking refs of temps for non-referencable expressions
Only one allowed per call.
-rw-r--r-- | colm/bytecode.c | 2 | ||||
-rw-r--r-- | colm/colm.lm | 6 | ||||
-rw-r--r-- | colm/loadcolm.cc | 28 | ||||
-rw-r--r-- | colm/parser.cc | 17 | ||||
-rw-r--r-- | colm/parser.h | 2 | ||||
-rw-r--r-- | colm/parsetree.h | 68 | ||||
-rw-r--r-- | colm/resolve.cc | 15 | ||||
-rw-r--r-- | colm/synthesis.cc | 126 |
8 files changed, 186 insertions, 78 deletions
diff --git a/colm/bytecode.c b/colm/bytecode.c index a58f395f..0f4a0202 100644 --- a/colm/bytecode.c +++ b/colm/bytecode.c @@ -2738,7 +2738,7 @@ again: short int field; read_half( field ); - debug( prg, REALM_BYTECODE, "IN_REF_FROM_LOCAL\n" ); + debug( prg, REALM_BYTECODE, "IN_REF_FROM_LOCAL %hd\n", field ); /* First push the null next pointer, then the kid pointer. */ Tree **ptr = vm_plocal(field); diff --git a/colm/colm.lm b/colm/colm.lm index 54d2853f..4cf12923 100644 --- a/colm/colm.lm +++ b/colm/colm.lm @@ -392,8 +392,9 @@ def optional_else | [] def iter_call - [VarRef: var_ref POPEN CodeExprList: code_expr* PCLOSE] -| [Id: id] + [E1 VarRef: var_ref POPEN CodeExprList: code_expr* PCLOSE] +| [E2 Id: id] +| [E3 Expr: code_expr] def block_or_single [COPEN LangStmtList: lang_stmt_list CCLOSE] @@ -561,6 +562,7 @@ def pattern def E1 [] def E2 [] +def E3 [] def cons_el [E1 RegionQual: region_qual Lit: lit] diff --git a/colm/loadcolm.cc b/colm/loadcolm.cc index 84177fe8..45565a25 100644 --- a/colm/loadcolm.cc +++ b/colm/loadcolm.cc @@ -220,9 +220,9 @@ struct LoadColm TypeRef *typeRef = walkTypeRef( Statement.TypeRef() ); StmtList *stmtList = walkBlockOrSingle( Statement.BlockOrSingle() ); - LangTerm *langTerm = walkIterCall( Statement.IterCall() ); + LangIterCall *iterCall = walkIterCall( Statement.IterCall() ); - stmt = forScope( Statement.ForDecl().loc(), forDecl, typeRef, langTerm, stmtList ); + stmt = forScope( Statement.ForDecl().loc(), forDecl, typeRef, iterCall, stmtList ); popScope(); } @@ -1628,21 +1628,29 @@ struct LoadColm return ObjectField::cons( varDef.Id().loc(), typeRef, id ); } - LangTerm *walkIterCall( iter_call IterCall ) + LangIterCall *walkIterCall( iter_call IterCall ) { - LangTerm *langTerm = 0; - if ( IterCall.Id() != 0 ) { + LangIterCall *iterCall = 0; + if ( IterCall.VarRef() != 0 ) { + LangVarRef *varRef = walkVarRef( IterCall.VarRef() ); + CallArgVect *exprVect = walkCodeExprList( IterCall.CodeExprList() ); + LangTerm *langTerm = LangTerm::cons( varRef->loc, varRef, exprVect ); + iterCall = LangIterCall::cons( LangIterCall::IterCall, langTerm ); + + } + else if ( IterCall.Id() != 0 ) { String tree = IterCall.Id().text().c_str(); - langTerm = LangTerm::cons( IterCall.Id().loc(), + LangTerm *langTerm = LangTerm::cons( IterCall.Id().loc(), LangTerm::VarRefType, LangVarRef::cons( IterCall.Id().loc(), tree ) ); + LangExpr *langExpr = LangExpr::cons( langTerm ); + iterCall = LangIterCall::cons( LangIterCall::VarRef, langExpr ); } else { - LangVarRef *varRef = walkVarRef( IterCall.VarRef() ); - CallArgVect *exprVect = walkCodeExprList( IterCall.CodeExprList() ); - langTerm = LangTerm::cons( varRef->loc, varRef, exprVect ); + LangExpr *langExpr = walkCodeExpr( IterCall.Expr() ); + iterCall = LangIterCall::cons( LangIterCall::Expr, langExpr ); } - return langTerm; + return iterCall; } diff --git a/colm/parser.cc b/colm/parser.cc index 13789a72..4e465e7a 100644 --- a/colm/parser.cc +++ b/colm/parser.cc @@ -647,20 +647,27 @@ ConsItemList *BaseParser::consListConcat( ConsItemList *list1, } LangStmt *BaseParser::forScope( const InputLoc &loc, const String &data, - TypeRef *typeRef, LangTerm *langTerm, StmtList *stmtList ) + TypeRef *typeRef, LangIterCall *iterCall, StmtList *stmtList ) { /* Check for redeclaration. */ if ( pd->curLocalFrame->checkRedecl( data ) != 0 ) error( loc ) << "variable " << data << " redeclared" << endp; - /* Note that we pass in a null type reference. This type is dependent - * on the result of the iter_call lookup since it must contain a reference - * to the iterator that is called. This lookup is done at compile time. */ + /* Note that we pass in a null type reference. This type is dependent on + * the result of the iter_call lookup since it must contain a reference to + * the iterator that is called. This lookup is done at compile time. */ ObjectField *iterField = ObjectField::cons( loc, (TypeRef*)0, data ); pd->curLocalFrame->insertField( data, iterField ); + /* This temporary is for the tree being walked, used only if it cannot be + * referenced. In this case the iterator is constant. */ + String iterTemp = "__iter_tmp_" + data + "__"; + ObjectField *tmpTreeField = ObjectField::cons( loc, (TypeRef*)0, iterTemp ); + pd->curLocalFrame->insertField( iterTemp, tmpTreeField ); + iterCall->tmpTreeField = tmpTreeField; + LangStmt *stmt = LangStmt::cons( loc, LangStmt::ForIterType, - iterField, typeRef, langTerm, stmtList ); + iterField, tmpTreeField, typeRef, iterCall, stmtList ); return stmt; } diff --git a/colm/parser.h b/colm/parser.h index 74dbbd5d..10b995bf 100644 --- a/colm/parser.h +++ b/colm/parser.h @@ -96,7 +96,7 @@ struct BaseParser PatternItemList *patListConcat( PatternItemList *list1, PatternItemList *list2 ); ConsItemList *consListConcat( ConsItemList *list1, ConsItemList *list2 ); LangStmt *forScope( const InputLoc &loc, const String &data, - TypeRef *typeRef, LangTerm *langTerm, StmtList *stmtList ); + TypeRef *typeRef, LangIterCall *iterCall, StmtList *stmtList ); void preEof( const InputLoc &loc, StmtList *stmtList, ObjectDef *localFrame ); ProdEl *prodElName( const InputLoc &loc, const String &data, diff --git a/colm/parsetree.h b/colm/parsetree.h index bf430eb4..5260b1d4 100644 --- a/colm/parsetree.h +++ b/colm/parsetree.h @@ -2298,9 +2298,10 @@ struct ObjectDef struct CallArg { CallArg( LangExpr *expr ) - : expr(expr) {} + : expr(expr), varRefExpr(0) {} LangExpr *expr; + LangExpr *varRefExpr; }; typedef Vector<LangExpr*> ExprVect; @@ -2414,6 +2415,7 @@ struct LangVarRef int lastPtrInQual, bool forWriting ) const; void loadObj( Compiler *pd, CodeVect &code, int lastPtrInQual, bool forWriting ) const; void canTakeRef( Compiler *pd, VarRefLookup &lookup ) const; + bool canTakeRefTest( Compiler *pd, VarRefLookup &lookup ) const; void setFieldIter( Compiler *pd, CodeVect &code, ObjectDef *inObject, UniqueType *objUT, UniqueType *exprType, bool revert ) const; @@ -2424,7 +2426,7 @@ struct LangVarRef void assignValue( Compiler *pd, CodeVect &code, UniqueType *exprUT ) const; ObjectField **evaluateArgs( Compiler *pd, CodeVect &code, - VarRefLookup &lookup, CallArgVect *args ) const; + VarRefLookup &lookup, CallArgVect *args, ObjectField *tmpTreeField ) const; void callOperation( Compiler *pd, CodeVect &code, VarRefLookup &lookup ) const; UniqueType *evaluateCall( Compiler *pd, CodeVect &code, CallArgVect *args ); UniqueType *evaluate( Compiler *pd, CodeVect &code, bool forWriting = false ) const; @@ -2690,6 +2692,7 @@ struct LangExpr void resolve( Compiler *pd ) const; UniqueType *evaluate( Compiler *pd, CodeVect &code ) const; + bool canTakeRefTest( Compiler *pd ) const; InputLoc loc; Type type; @@ -2702,6 +2705,45 @@ struct LangExpr struct LangStmt; typedef DList<LangStmt> StmtList; +struct LangIterCall +{ + enum Type { + VarRef, + IterCall, + Expr + }; + + LangIterCall() + : + langTerm(0), + langExpr(0), + tmpTreeField(0) + {} + + static LangIterCall *cons( Type type, LangTerm *langTerm ) + { + LangIterCall *iterCall = new LangIterCall; + iterCall->type = type; + iterCall->langTerm = langTerm; + return iterCall; + } + + static LangIterCall *cons( Type type, LangExpr *langExpr ) + { + LangIterCall *iterCall = new LangIterCall; + iterCall->type = type; + iterCall->langExpr = langExpr; + return iterCall; + } + + void resolve( Compiler *pd ) const; + + Type type; + LangTerm *langTerm; + LangExpr *langExpr; + ObjectField *tmpTreeField; +}; + struct LangStmt { enum Type { @@ -2735,6 +2777,7 @@ struct LangStmt fieldInitVect(0), stmtList(0), elsePart(0), + iterCall(0), /* Normally you don't need to initialize double list pointers, however, * we make use of the next pointer for returning a pair of statements @@ -2841,7 +2884,7 @@ struct LangStmt return s; } - static LangStmt *cons( const InputLoc &loc, Type type, ObjectField *objField, + static LangStmt *cons( const InputLoc &loc, Type type, ObjectField *objField, TypeRef *typeRef, LangTerm *langTerm, StmtList *stmtList ) { LangStmt *s = new LangStmt; @@ -2854,6 +2897,21 @@ struct LangStmt return s; } + static LangStmt *cons( const InputLoc &loc, Type type, ObjectField *objField, + ObjectField *tmpTreeField, TypeRef *typeRef, LangIterCall *iterCall, StmtList *stmtList ) + { + LangStmt *s = new LangStmt; + s->loc = loc; + s->type = type; + s->objField = objField; + s->tmpTreeField = tmpTreeField; + s->typeRef = typeRef; + s->iterCall = iterCall; + s->stmtList = stmtList; + return s; + } + + static LangStmt *cons( Type type ) { LangStmt *s = new LangStmt; @@ -2864,7 +2922,7 @@ struct LangStmt void resolve( Compiler *pd ) const; void resolveParserItems( Compiler *pd ) const; - LangTerm *chooseDefaultIter( Compiler *pd, LangTerm *fromVarRef ) const; + void chooseDefaultIter( Compiler *pd, LangIterCall *iterCall ) const; void compileWhile( Compiler *pd, CodeVect &code ) const; void compileForIterBody( Compiler *pd, CodeVect &code, UniqueType *iterUT ) const; void compileForIter( Compiler *pd, CodeVect &code ) const; @@ -2875,6 +2933,7 @@ struct LangStmt LangVarRef *varRef; LangTerm *langTerm; ObjectField *objField; + ObjectField *tmpTreeField; TypeRef *typeRef; LangExpr *expr; Constructor *constructor; @@ -2885,6 +2944,7 @@ struct LangStmt /* Either another if, or an else. */ LangStmt *elsePart; String name; + LangIterCall *iterCall; /* Normally you don't need to initialize double list pointers, however, we * make use of the next pointer for returning a pair of statements using diff --git a/colm/resolve.cc b/colm/resolve.cc index 4bc4dce3..f5aa4540 100644 --- a/colm/resolve.cc +++ b/colm/resolve.cc @@ -418,6 +418,19 @@ void LangStmt::resolveParserItems( Compiler *pd ) const } } +void LangIterCall::resolve( Compiler *pd ) const +{ + switch ( type ) { + case IterCall: + langTerm->resolve( pd ); + break; + case VarRef: + case Expr: + langExpr->resolve( pd ); + break; + } +} + void LangStmt::resolve( Compiler *pd ) const { switch ( type ) { @@ -472,7 +485,7 @@ void LangStmt::resolve( Compiler *pd ) const typeRef->lookupType( pd ); /* Evaluate and push the arguments. */ - langTerm->resolve( pd ); + iterCall->resolve( pd ); /* Compile the contents. */ for ( StmtList::Iter stmt = *stmtList; stmt.lte(); stmt++ ) diff --git a/colm/synthesis.cc b/colm/synthesis.cc index 21a06cc2..0daf0872 100644 --- a/colm/synthesis.cc +++ b/colm/synthesis.cc @@ -881,7 +881,7 @@ UniqueType *LangVarRef::evaluate( Compiler *pd, CodeVect &code, bool forWriting return ut; } -void LangVarRef::canTakeRef( Compiler *pd, VarRefLookup &lookup ) const +bool LangVarRef::canTakeRefTest( Compiler *pd, VarRefLookup &lookup ) const { bool canTake = false; @@ -892,6 +892,13 @@ void LangVarRef::canTakeRef( Compiler *pd, VarRefLookup &lookup ) const else if ( isLocalRef(pd) && lookup.lastPtrInQual < 0 && lookup.uniqueType->typeId != TYPE_PTR ) canTake = true; + return canTake; +} + +void LangVarRef::canTakeRef( Compiler *pd, VarRefLookup &lookup ) const +{ + bool canTake = canTakeRefTest( pd, lookup ); + if ( !canTake ) { error(loc) << "can only take references of locals or " "attributes accessed via a local" << endp; @@ -901,6 +908,19 @@ void LangVarRef::canTakeRef( Compiler *pd, VarRefLookup &lookup ) const error(loc) << "reference currently active, cannot take another" << endp; } +bool LangExpr::canTakeRefTest( Compiler *pd ) const +{ + bool canTake = false; + + if ( type == LangExpr::TermType && term->type == LangTerm::VarRefType ) { + VarRefLookup lookup = term->varRef->lookupField( pd ); + if ( term->varRef->canTakeRefTest( pd, lookup ) ) + canTake = true; + } + return canTake; +} + + /* Return the field referenced. */ ObjectField *LangVarRef::preEvaluateRef( Compiler *pd, CodeVect &code ) const { @@ -952,8 +972,9 @@ ObjectField *LangVarRef::evaluateRef( Compiler *pd, CodeVect &code, long pushCou return lookup.objField; } + ObjectField **LangVarRef::evaluateArgs( Compiler *pd, CodeVect &code, - VarRefLookup &lookup, CallArgVect *args ) const + VarRefLookup &lookup, CallArgVect *args, ObjectField *tmpTreeField ) const { /* Parameter list is given only for user defined methods. Otherwise it * will be null. */ @@ -983,14 +1004,37 @@ ObjectField **LangVarRef::evaluateArgs( Compiler *pd, CodeVect &code, if ( paramUT->typeId == TYPE_REF ) { /* Make sure we are dealing with a variable reference. */ - if ( expression->type != LangExpr::TermType ) - error(loc) << "not a term: argument must be a local variable" << endp; - if ( expression->term->type != LangTerm::VarRefType ) - error(loc) << "not a variable: argument must be a local variable" << endp; + if ( ! expression->canTakeRefTest( pd ) ) { + if ( tmpTreeField == 0 ) { + /* Can't make this local. */ + error(loc) << "argument must be a local variable" << endp; + } + else { + /* Evaluate the expression. */ + UniqueType *exprUT = expression->evaluate( pd, code ); + + /* Can copy the value to a tmp local and render the + * iterator constant. Give the tmp a type. */ + tmpTreeField->typeRef = TypeRef::cons( loc, exprUT ); + + /* Make an expression that refereces the tmp local. */ + LangVarRef *varRef = LangVarRef::cons( loc, tmpTreeField->name ); + LangTerm *langTerm = LangTerm::cons( loc, LangTerm::VarRefType, varRef ); + (*pe)->varRefExpr = LangExpr::cons( langTerm ); + + /* Stash to the local. */ + varRef->assignValue( pd, code, exprUT ); + + /* Replace the argument with the local referene. */ + expression = (*pe)->varRefExpr; + + /* Only have one to use. */ + tmpTreeField = 0; + } + } /* Lookup the field. */ LangVarRef *varRef = expression->term->varRef; - ObjectField *refOf = varRef->preEvaluateRef( pd, code ); paramRefs[pe.pos()] = refOf; @@ -1008,12 +1052,8 @@ ObjectField **LangVarRef::evaluateArgs( Compiler *pd, CodeVect &code, UniqueType *paramUT = lookup.objMethod->paramUTs[pe.pos()]; if ( paramUT->typeId == TYPE_REF ) { - - /* Make sure we are dealing with a variable reference. */ - if ( expression->type != LangExpr::TermType ) - error(loc) << "not a term: argument must be a local variable" << endp; - if ( expression->term->type != LangTerm::VarRefType ) - error(loc) << "not a variable: argument must be a local variable" << endp; + if ( ! expression->canTakeRefTest( pd ) ) + expression = (*pe)->varRefExpr; /* Lookup the field. */ LangVarRef *varRef = expression->term->varRef; @@ -1112,6 +1152,9 @@ void LangVarRef::popRefQuals( Compiler *pd, CodeVect &code, UniqueType *paramUT = lookup.objMethod->paramUTs[pe.pos()]; if ( paramUT->typeId == TYPE_REF ) { + if ( ! expression->canTakeRefTest( pd ) ) + expression = (*pe)->varRefExpr; + /* Lookup the field. */ LangVarRef *varRef = expression->term->varRef; popCount += varRef->qual->length() * 2; @@ -1165,7 +1208,7 @@ UniqueType *LangVarRef::evaluateCall( Compiler *pd, CodeVect &code, CallArgVect } /* Evaluate and push the arguments. */ - ObjectField **paramRefs = evaluateArgs( pd, code, lookup, args ); + ObjectField **paramRefs = evaluateArgs( pd, code, lookup, args, 0 ); /* Write the call opcode. */ callOperation( pd, code, lookup ); @@ -2094,55 +2137,31 @@ void LangStmt::compileForIterBody( Compiler *pd, /* Clean up any prepush args. */ } -LangTerm *LangStmt::chooseDefaultIter( Compiler *pd, LangTerm *fromVarRef ) const +void LangStmt::chooseDefaultIter( Compiler *pd, LangIterCall *iterCall ) const { - /* Lookup the lang term and decide what iterator to use based - * on its type. */ - VarRefLookup lookup = fromVarRef->varRef->lookupField( pd ); - - if ( lookup.inObject->type != ObjectDef::FrameType ) - error(loc) << "root of iteration must be a local" << endp; - - LangVarRef *callVarRef = 0; - if ( lookup.uniqueType->typeId == TYPE_TREE || - lookup.uniqueType->typeId == TYPE_REF || - lookup.uniqueType->typeId == TYPE_ITER || - lookup.uniqueType->typeId == TYPE_PTR ) - { - /* The iterator name. */ - callVarRef = LangVarRef::cons( loc, "triter" ); - } - else { - error(loc) << "there is no default iterator for a " - "root of that type" << endp; - } + /* The iterator name. */ + LangVarRef *callVarRef = LangVarRef::cons( loc, "triter" ); /* The parameters. */ CallArgVect *callExprVect = new CallArgVect; - LangExpr *callExpr = LangExpr::cons( LangTerm::cons( - InputLoc(), LangTerm::VarRefType, fromVarRef->varRef ) ); - callExprVect->append( new CallArg( callExpr ) ); - - LangTerm *callLangTerm = LangTerm::cons( InputLoc(), callVarRef, callExprVect ); - - return callLangTerm; + callExprVect->append( new CallArg( iterCall->langExpr ) ); + iterCall->langTerm = LangTerm::cons( InputLoc(), callVarRef, callExprVect ); + iterCall->langExpr = 0; + iterCall->type = LangIterCall::IterCall; } void LangStmt::compileForIter( Compiler *pd, CodeVect &code ) const { pd->curLocalFrame->iterPushScope(); - LangTerm *iterCallTerm = langTerm; - if ( iterCallTerm->type != LangTerm::MethodCallType ) - iterCallTerm = chooseDefaultIter( pd, langTerm ); + if ( iterCall->type != LangIterCall::IterCall ) + chooseDefaultIter( pd, iterCall ); /* The type we are searching for. */ UniqueType *searchUT = typeRef->uniqueType; - /* - * Declare the iterator variable. - */ - VarRefLookup lookup = iterCallTerm->varRef->lookupMethod( pd ); + /* Lookup the iterator call. Make sure it is an iterator. */ + VarRefLookup lookup = iterCall->langTerm->varRef->lookupMethod( pd ); if ( lookup.objMethod->iterDef == 0 ) { error(loc) << "attempt to iterate using something " "that is not an iterator" << endp; @@ -2156,7 +2175,6 @@ void LangStmt::compileForIter( Compiler *pd, CodeVect &code ) const resetContiguous = pd->beginContiguous( code, stretch ); } - /* Now that we have done the iterator call lookup we can make the type * reference for the object field. */ UniqueType *iterUniqueType = pd->findUniqueType( TYPE_ITER, lookup.objMethod->iterDef ); @@ -2172,8 +2190,8 @@ void LangStmt::compileForIter( Compiler *pd, CodeVect &code ) const UniqueType *iterUT = objField->typeRef->uniqueType; /* Evaluate and push the arguments. */ - ObjectField **paramRefs = iterCallTerm->varRef->evaluateArgs( - pd, code, lookup, iterCallTerm->args ); + ObjectField **paramRefs = iterCall->langTerm->varRef->evaluateArgs( + pd, code, lookup, iterCall->langTerm->args, iterCall->tmpTreeField ); if ( pd->revertOn ) code.append( iterUT->iterDef->inCreateWV ); @@ -2195,9 +2213,9 @@ void LangStmt::compileForIter( Compiler *pd, CodeVect &code ) const compileForIterBody( pd, code, iterUT ); - iterCallTerm->varRef->popRefQuals( pd, code, lookup, iterCallTerm->args ); + iterCall->langTerm->varRef->popRefQuals( pd, code, lookup, iterCall->langTerm->args ); - iterCallTerm->varRef->resetActiveRefs( pd, lookup, paramRefs ); + iterCall->langTerm->varRef->resetActiveRefs( pd, lookup, paramRefs ); delete[] paramRefs; pd->curLocalFrame->iterPopScope(); |