diff options
author | Adrian Thurston <thurston@complang.org> | 2015-02-12 14:07:07 -0500 |
---|---|---|
committer | Adrian Thurston <thurston@complang.org> | 2015-02-12 14:07:07 -0500 |
commit | 5c20c54c78a16050f65cbf3073536469fc9c78ed (patch) | |
tree | bb9bd32c96758d53d2ab0fbe85a5dd08b0806100 | |
parent | 5feead50112d87338230a438d2a92c242fac7e59 (diff) | |
download | colm-5c20c54c78a16050f65cbf3073536469fc9c78ed.tar.gz |
added a list iterator so we don't need to use while loops
-rw-r--r-- | src/bytecode.c | 58 | ||||
-rw-r--r-- | src/bytecode.h | 17 | ||||
-rw-r--r-- | src/declare.cc | 12 | ||||
-rw-r--r-- | src/iter.c | 69 | ||||
-rw-r--r-- | src/parsetree.h | 5 | ||||
-rw-r--r-- | src/synthesis.cc | 53 | ||||
-rw-r--r-- | src/tree.h | 17 |
7 files changed, 225 insertions, 6 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index 07abc126..cc573df3 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -2032,6 +2032,64 @@ again: treeDownref( prg, sp, old ); break; } + case IN_LIST_ITER_FROM_REF: { + short field; + Half argSize; + Half genericId; + read_half( field ); + read_half( argSize ); + read_half( genericId ); + + debug( prg, REALM_BYTECODE, "IN_LIST_ITER_FROM_REF " + "%hd %hd %hd\n", field, argSize, genericId ); + + Ref rootRef; + rootRef.kid = (Kid*)vm_pop(); + rootRef.next = (Ref*)vm_pop(); + void *mem = vm_plocal(field); + + Tree **stackRoot = vm_ptop(); + long rootSize = vm_ssize(); + + colm_init_list_iter( (ListIter*)mem, stackRoot, argSize, + rootSize, &rootRef, genericId ); + break; + } + case IN_LIST_ITER_DESTROY: { + short field; + read_half( field ); + + ListIter *iter = (ListIter*) vm_plocal(field); + + debug( prg, REALM_BYTECODE, "IN_LIST_ITER_DESTROY %d\n", iter->yieldSize ); + + colm_list_iter_destroy( prg, &sp, iter ); + break; + } + case IN_LIST_ITER_ADVANCE: { + short field; + read_half( field ); + + debug( prg, REALM_BYTECODE, "IN_LIST_ITER_ADVANCE\n" ); + + TreeIter *iter = (TreeIter*) vm_plocal(field); + Tree *res = colm_list_iter_advance( prg, &sp, iter ); + //treeUpref( res ); + vm_push( res ); + break; + } + case IN_LIST_ITER_GET_CUR_R: { + short field; + read_half( field ); + + debug( prg, REALM_BYTECODE, "IN_LIST_ITER_GET_CUR_R\n" ); + + TreeIter *iter = (TreeIter*) vm_plocal(field); + Tree *tree = colm_list_iter_deref_cur( prg, iter ); + //treeUpref( tree ); + vm_push( tree ); + break; + } case IN_MATCH: { Half patternId; read_half( patternId ); diff --git a/src/bytecode.h b/src/bytecode.h index 1ee071f9..9f843537 100644 --- a/src/bytecode.h +++ b/src/bytecode.h @@ -57,7 +57,6 @@ typedef unsigned long colm_value_t; #define IN_TST_EQL_VAL 0x59 #define IN_TST_EQL_TREE 0x0c -//#define IN_TST_EQL 0x0c #define IN_TST_NOT_EQL_TREE 0x0d #define IN_TST_NOT_EQL_VAL 0x5f #define IN_TST_LESS_VAL 0x0e @@ -75,9 +74,19 @@ typedef unsigned long colm_value_t; #define IN_TST_NZ_TREE 0xd1 -//0xd3 -//0xd4 -//0xd5 +// 0xe6 +// 0xe7 +// 0xe8 +// 0xe9 +// 0xea +// 0xeb +// 0xec +// 0xd4 + +#define IN_LIST_ITER_FROM_REF 0xd3 +#define IN_LIST_ITER_DESTROY 0xd5 +#define IN_LIST_ITER_ADVANCE 0xde +#define IN_LIST_ITER_GET_CUR_R 0xdf #define IN_NOT_VAL 0x14 #define IN_NOT_TREE 0xd2 diff --git a/src/declare.cc b/src/declare.cc index 8c551c89..57cc0fa4 100644 --- a/src/declare.cc +++ b/src/declare.cc @@ -495,6 +495,8 @@ void Compiler::makeIgnoreCollectors() void LangStmt::chooseDefaultIter( Compiler *pd, IterCall *iterCall ) const { + /* This is two-part, It gets rewritten before evaluation in synthesis. */ + /* The iterator name. */ LangVarRef *callVarRef = LangVarRef::cons( loc, context, scope, "triter" ); @@ -682,6 +684,16 @@ void Compiler::makeDefaultIterators() IterDef *triter = findIterDef( IterDef::RevRepeat ); objMethod->iterDef = triter; } + + /* List iterator. */ + { + UniqueType *anyRefUT = findUniqueType( TYPE_REF, anyLangEl ); + ObjectMethod *objMethod = initFunction( uniqueTypeAny, globalObjectDef, + "list_iter", IN_HALT, IN_HALT, anyRefUT, true ); + + IterDef *triter = findIterDef( IterDef::List ); + objMethod->iterDef = triter; + } } void Compiler::addMatchLength( ObjectDef *frame, LangEl *lel ) @@ -28,6 +28,75 @@ #define true 1 #define false 0 +void colm_init_list_iter( ListIter *listIter, Tree **stackRoot, + long argSize, long rootSize, const Ref *rootRef, int genericId ) +{ + listIter->type = IT_Tree; + listIter->rootRef = *rootRef; + listIter->stackRoot = stackRoot; + listIter->yieldSize = 0; + listIter->rootSize = rootSize; + listIter->ref.kid = 0; + listIter->ref.next = 0; + listIter->argSize = argSize; + listIter->genericId = genericId; +} + +void colm_list_iter_destroy( Program *prg, Tree ***psp, ListIter *iter ) +{ + if ( (int)iter->type != 0 ) { + int i; + Tree **sp = *psp; + long curStackSize = vm_ssize() - iter->rootSize; + assert( iter->yieldSize == curStackSize ); + vm_popn( iter->yieldSize ); + for ( i = 0; i < iter->argSize; i++ ) + treeDownref( prg, sp, vm_pop() ); + iter->type = 0; + *psp = sp; + } +} + +Tree *colm_list_iter_advance( Program *prg, Tree ***psp, ListIter *iter ) +{ + Tree **sp = *psp; + assert( iter->yieldSize == (vm_ssize() - iter->rootSize) ); + + if ( iter->ref.kid == 0 ) { + /* Kid is zero, start from the root. */ + List *list = *((List**)iter->rootRef.kid); + iter->ref.kid = list->head; + iter->ref.next = 0; + + //= iter->rootRef; + //iter + //iterFind( prg, psp, iter, true ); + } + else { + /* Have a previous item, continue searching from there. */ + //iterFind( prg, psp, iter, false ); + + ListEl *listEl = iter->ref.kid; + listEl = listEl->list_next; + iter->ref.kid = listEl; + iter->ref.next = 0; + } + + sp = *psp; + iter->yieldSize = vm_ssize() - iter->rootSize; + + return (iter->ref.kid ? prg->trueVal : prg->falseVal ); +} + +Tree *colm_list_iter_deref_cur( Program *prg, ListIter *iter ) +{ + GenericInfo *gi = &prg->rtd->genericInfo[iter->genericId]; + ListEl *el = (ListEl*)iter->ref.kid; + struct colm_struct *s = el != 0 ? + colm_struct_container( el, gi->elOffset ) : 0; + return (Tree*)s; +} + void initTreeIter( TreeIter *treeIter, Tree **stackRoot, long argSize, long rootSize, const Ref *rootRef, int searchId ) diff --git a/src/parsetree.h b/src/parsetree.h index 6f3f78c1..90a1cb42 100644 --- a/src/parsetree.h +++ b/src/parsetree.h @@ -1731,7 +1731,7 @@ struct Function; struct IterDef { - enum Type { Tree, Child, RevChild, Repeat, RevRepeat, User }; + enum Type { Tree, Child, RevChild, Repeat, RevRepeat, User, List }; IterDef( Type type, Function *func ); IterDef( Type type ); @@ -1741,6 +1741,7 @@ struct IterDef Function *func; bool useFuncId; bool useSearchUT; + bool useGenericId; Code inCreateWV; Code inCreateWC; @@ -2645,6 +2646,8 @@ struct LangVarRef void assignValue( Compiler *pd, CodeVect &code, UniqueType *exprUT ) const; + void chooseTriterCall( Compiler *pd, CallArgVect *args ); + /* The deref generics value is for iterator calls with lists and maps as args. */ ObjectField **evaluateArgs( Compiler *pd, CodeVect &code, VarRefLookup &lookup, CallArgVect *args ); diff --git a/src/synthesis.cc b/src/synthesis.cc index 3cd7462c..b4856f27 100644 --- a/src/synthesis.cc +++ b/src/synthesis.cc @@ -34,7 +34,8 @@ IterDef::IterDef( Type type ) : type(type), func(0), useFuncId(false), - useSearchUT(false) + useSearchUT(false), + useGenericId(false) { switch ( type ) { case Tree: @@ -99,6 +100,19 @@ IterDef::IterDef( Type type ) : inRefFromCur = IN_TRITER_REF_FROM_CUR; useSearchUT = true; break; + + case List: + inCreateWV = IN_LIST_ITER_FROM_REF; + inCreateWC = IN_LIST_ITER_FROM_REF; + inDestroy = IN_LIST_ITER_DESTROY; + inAdvance = IN_LIST_ITER_ADVANCE; + + inGetCurR = IN_LIST_ITER_GET_CUR_R; + inGetCurWC = //IN_LIST_ITER_GET_CUR_WC; + inSetCurWC = //IN_HALT; + inRefFromCur = //IN_LIST_ITER_REF_FROM_CUR; + useGenericId = true; + break; case User: assert(false); @@ -221,10 +235,15 @@ long sizeOfField( UniqueType *fieldUT ) case IterDef::RevRepeat: size = sizeof(TreeIter) / sizeof(Word); break; + case IterDef::RevChild: size = sizeof(RevTreeIter) / sizeof(Word); break; + case IterDef::List: + size = sizeof(ListIter) / sizeof(Word); + break; + case IterDef::User: /* User iterators are just a pointer to the UserIter struct. The * struct needs to go right beneath the call to the user iterator @@ -724,6 +743,21 @@ ObjectField *LangVarRef::evaluateRef( Compiler *pd, CodeVect &code, long pushCou return lookup.objField; } +void LangVarRef::chooseTriterCall( Compiler *pd, CallArgVect *args ) +{ + /* Evaluate the triter args and choose the triter call based on it. */ + if ( args->length() == 1 ) { + /* Evaluate the expression. */ + CodeVect unused; + CallArgVect::Iter pe = *args; + UniqueType *exprUT = (*pe)->expr->evaluate( pd, unused ); + + if ( exprUT->typeId == TYPE_GENERIC && exprUT->generic->typeId == GEN_LIST ) { + cerr << "iterating list" << endl; + name = "list_iter"; + } + } +} ObjectField **LangVarRef::evaluateArgs( Compiler *pd, CodeVect &code, VarRefLookup &lookup, CallArgVect *args ) @@ -2138,6 +2172,9 @@ void LangStmt::compileForIter( Compiler *pd, CodeVect &code ) const /* The type we are searching for. */ UniqueType *searchUT = typeRef->uniqueType; + if ( iterCall->wasExpr ) + iterCall->langTerm->varRef->chooseTriterCall( pd, iterCall->langTerm->args ); + /* Lookup the iterator call. Make sure it is an iterator. */ VarRefLookup lookup = iterCall->langTerm->varRef->lookupMethod( pd ); if ( lookup.objMethod->iterDef == 0 ) { @@ -2182,6 +2219,14 @@ void LangStmt::compileForIter( Compiler *pd, CodeVect &code ) const if ( iterUT->iterDef->useSearchUT ) code.appendHalf( searchUT->langEl->id ); + if ( iterUT->iterDef->useGenericId ) { + CodeVect unused; + UniqueType *ut = + iterCall->langTerm->args->data[0]->expr->evaluate( pd, unused ); + + code.appendHalf( ut->generic->id ); + } + compileForIterBody( pd, code, iterUT ); iterCall->langTerm->varRef->popRefQuals( pd, code, lookup, @@ -2439,6 +2484,12 @@ void Compiler::findLocals( ObjectDef *localFrame, CodeBlock *block ) case IterDef::RevRepeat: type = LT_Iter; break; + + case IterDef::List: + /* ? */ + type = LT_Iter; + break; + case IterDef::RevChild: type = LT_RevIter; break; @@ -166,6 +166,18 @@ typedef struct _TreeIter long rootSize; } TreeIter; +typedef struct _ListIter +{ + enum IterType type; + Ref rootRef; + Ref ref; + Tree **stackRoot; + long argSize; + long yieldSize; + long rootSize; + long genericId; +} ListIter; + /* This must overlay tree iter because some of the same bytecodes are used. */ typedef struct _RevTreeIter { @@ -329,6 +341,11 @@ void userIterDestroy2( struct colm_program *prg, Tree ***psp, UserIter *uiter ); Tree *castTree( struct colm_program *prg, int langElId, Tree *tree ); StreamImpl *streamToImpl( Stream *ptr ); +void colm_init_list_iter( ListIter *listIter, Tree **stackRoot, + long argSize, long rootSize, const Ref *rootRef, int genericId ); +void colm_list_iter_destroy( struct colm_program *prg, Tree ***psp, ListIter *iter ); +Tree *colm_list_iter_advance( struct colm_program *prg, Tree ***psp, ListIter *iter ); +Tree *colm_list_iter_deref_cur( struct colm_program *prg, ListIter *iter ); #if defined(__cplusplus) } |