summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@complang.org>2015-02-12 14:07:07 -0500
committerAdrian Thurston <thurston@complang.org>2015-02-12 14:07:07 -0500
commit5c20c54c78a16050f65cbf3073536469fc9c78ed (patch)
treebb9bd32c96758d53d2ab0fbe85a5dd08b0806100
parent5feead50112d87338230a438d2a92c242fac7e59 (diff)
downloadcolm-5c20c54c78a16050f65cbf3073536469fc9c78ed.tar.gz
added a list iterator so we don't need to use while loops
-rw-r--r--src/bytecode.c58
-rw-r--r--src/bytecode.h17
-rw-r--r--src/declare.cc12
-rw-r--r--src/iter.c69
-rw-r--r--src/parsetree.h5
-rw-r--r--src/synthesis.cc53
-rw-r--r--src/tree.h17
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 )
diff --git a/src/iter.c b/src/iter.c
index b6864908..1fc0ffdc 100644
--- a/src/iter.c
+++ b/src/iter.c
@@ -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;
diff --git a/src/tree.h b/src/tree.h
index d3c1e875..ba2dd806 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -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)
}