summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@complang.org>2013-06-03 00:29:29 +0000
committerAdrian Thurston <thurston@complang.org>2013-06-03 00:30:20 +0000
commit8dbc115720d6cca9c880af41ac14c7c0707d2d2d (patch)
treec5494bc475433bda34f4e3645ae31e8a121b57cf
parentcad4e8ef93185ee16e95337277e470db123b541c (diff)
downloadcolm-8dbc115720d6cca9c880af41ac14c7c0707d2d2d.tar.gz
first pass at taking refs of temps for non-referencable expressions
Only one allowed per call.
-rw-r--r--colm/bytecode.c2
-rw-r--r--colm/colm.lm6
-rw-r--r--colm/loadcolm.cc28
-rw-r--r--colm/parser.cc17
-rw-r--r--colm/parser.h2
-rw-r--r--colm/parsetree.h68
-rw-r--r--colm/resolve.cc15
-rw-r--r--colm/synthesis.cc126
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();