diff options
author | Adrian Thurston <thurston@complang.org> | 2009-02-06 02:08:57 +0000 |
---|---|---|
committer | Adrian Thurston <thurston@complang.org> | 2009-02-06 02:08:57 +0000 |
commit | 687a4b9503616a7ed872b7eab08e69d7709cc7fa (patch) | |
tree | 69954b332b1aca22bb51c6fa32570922da476b27 | |
parent | 34f8eabcf0a11adefc1ab924f29d96ff99cf7d2d (diff) | |
download | colm-687a4b9503616a7ed872b7eab08e69d7709cc7fa.tar.gz |
Started on producing refefences from qualified items. Working on calling
functions with reference parameters. On return they need to be popped, this is
not done yet.
-rw-r--r-- | colm/bytecode.cpp | 13 | ||||
-rw-r--r-- | colm/bytecode.h | 1 | ||||
-rw-r--r-- | colm/compile.cpp | 136 | ||||
-rw-r--r-- | colm/parsetree.h | 5 | ||||
-rw-r--r-- | colm/tree.cpp | 2 |
5 files changed, 144 insertions, 13 deletions
diff --git a/colm/bytecode.cpp b/colm/bytecode.cpp index 965e1251..985fc16e 100644 --- a/colm/bytecode.cpp +++ b/colm/bytecode.cpp @@ -2029,6 +2029,19 @@ again: push( (SW)ref->kid ); break; } + case IN_REF_FROM_QUAL_REF: { + short int field; + read_half( field ); + + #ifdef COLM_LOG_BYTECODE + cerr << "IN_REF_FROM_QUAL_REF " << field << endl; + #endif + + Ref *ref = (Ref*)plocal(field); + push( (SW)ref ); + push( (SW)ref->kid ); + break; + } case IN_TRITER_REF_FROM_CUR: { short int field; read_half( field ); diff --git a/colm/bytecode.h b/colm/bytecode.h index 6fce4b19..743b5221 100644 --- a/colm/bytecode.h +++ b/colm/bytecode.h @@ -141,6 +141,7 @@ typedef unsigned char uchar; #define IN_REF_FROM_LOCAL 0x62 #define IN_REF_FROM_REF 0x97 +#define IN_REF_FROM_QUAL_REF 0xa5 #define IN_TRITER_REF_FROM_CUR 0x63 #define IN_UITER_REF_FROM_CUR 0x64 diff --git a/colm/compile.cpp b/colm/compile.cpp index 74449095..d9ef83f0 100644 --- a/colm/compile.cpp +++ b/colm/compile.cpp @@ -353,6 +353,51 @@ ObjectDef *objDefFromUT( ParseData *pd, UniqueType *ut ) return objDef; } +/* The qualification must start at a local frame. There cannot be any pointer. */ +long LangVarRef::loadQualificationRefs( ParseData *pd, CodeVect &code ) const +{ + long count = 0; + ObjectDef *rootObj = pd->curLocalFrame; + + /* Start the search from the root object. */ + ObjectDef *searchObjDef = rootObj; + + for ( QualItemVect::Iter qi = *qual; qi.lte(); qi++ ) { + /* Lookup the field in the current qualification. */ + ObjFieldMapEl *objDefMapEl = searchObjDef->objFieldMap->find( qi->data ); + if ( objDefMapEl == 0 ) + error(qi->loc) << "cannot resolve qualification " << qi->data << endp; + ObjField *el = objDefMapEl->value; + + if ( qi.pos() > 0 ) { + code.append( IN_REF_FROM_QUAL_REF ); + code.appendHalf( 0 ); + } + else if ( el->typeRef->iterDef != 0 ) { + code.append( el->typeRef->iterDef->inRefFromCur ); + code.appendHalf( el->offset ); + } + else if ( el->typeRef->isRef ) { + code.append( IN_REF_FROM_REF ); + code.appendHalf( el->offset ); + } + else { + code.append( IN_REF_FROM_LOCAL ); + code.appendHalf( el->offset ); + } + + UniqueType *elUT = el->typeRef->lookupType( pd ); + if ( elUT->typeId == TYPE_ITER ) + elUT = el->typeRef->searchTypeRef->lookupType( pd ); + + assert( qi->type == QualItem::Dot ); + + searchObjDef = objDefFromUT( pd, elUT ); + count += 1; + } + return count; +} + void LangVarRef::loadQualification( ParseData *pd, CodeVect &code, ObjectDef *rootObj, int lastPtrInQual, bool forWriting, bool revert ) const { @@ -661,29 +706,63 @@ UniqueType *LangVarRef::evaluate( ParseData *pd, CodeVect &code, bool forWriting return ut; } +void LangVarRef::canTakeRef( ParseData *pd, VarRefLookup &lookup ) const +{ + bool canTake = false; + + /* If the var is not a local, it must be an attribute accessed + * via a local and attributes. */ + if ( lookup.inObject->type == ObjectDef::FrameType ) + canTake = true; + else if ( isLocalRef(pd) && lookup.lastPtrInQual < 0 && lookup.uniqueType->typeId != TYPE_PTR ) + canTake = true; + + if ( !canTake ) { + error(loc) << "can only take references of locals or " + "attributes accessed via a local" << endp; + } + + if ( lookup.objField->refActive ) + error(loc) << "reference currently active, cannot take another" << endp; +} + /* Return the field referenced. */ -ObjField *LangVarRef::evaluateRef( ParseData *pd, CodeVect &code ) const +ObjField *LangVarRef::preEvaluateRef( ParseData *pd, CodeVect &code ) const { /* Lookup the loadObj. */ VarRefLookup lookup = lookupField( pd ); - if ( lookup.inObject->type != ObjectDef::FrameType ) - error(loc) << "can only take references of local variables" << endl; - - if ( lookup.objField->refActive ) - error(loc) << "reference current active, cannot take another" << endl; + canTakeRef( pd, lookup ); + + loadQualificationRefs( pd, code ); + + return lookup.objField; +} + +/* Return the field referenced. */ +ObjField *LangVarRef::evaluateRef( ParseData *pd, CodeVect &code, long pushCount ) const +{ + /* Lookup the loadObj. */ + VarRefLookup lookup = lookupField( pd ); + + canTakeRef( pd, lookup ); /* Ensure that the field is referenced. */ lookup.inObject->referenceField( pd, lookup.objField ); /* Note that we could have modified children. */ - lookup.objField->refActive = true; + if ( qual->length() == 0 ) + lookup.objField->refActive = true; /* Whenever we take a reference we have to assume writing and that the * tree is dirty. */ lookup.objField->dirtyTree = true; - if ( lookup.objField->typeRef->iterDef != 0 ) { + if ( qual->length() > 0 ) { + code.append( IN_REF_FROM_QUAL_REF ); + code.appendHalf( pushCount ); + } + else if ( lookup.objField->typeRef->iterDef != 0 ) { code.append( lookup.objField->typeRef->iterDef->inRefFromCur ); code.appendHalf( lookup.objField->offset ); } @@ -717,16 +796,45 @@ ObjField **LangVarRef::evaluateArgs( ParseData *pd, CodeVect &code, /* Evaluate and push the args. */ if ( args != 0 ) { - /* If we have the parameter list, initialize an iterator. */ + /* We use this only if there is a paramter list. */ ParameterList::Iter p; + long pushCount = 0; + + /* First pass we need to push object loads for reference parameters. */ paramList != 0 && ( p = *paramList ); + for ( ExprVect::Iter pe = *args; pe.lte(); pe++ ) { + /* Get the expression and the UT for the arg. */ + LangExpr *expression = *pe; + 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; + + /* Lookup the field. */ + LangVarRef *varRef = expression->term->varRef; + + ObjField *refOf = varRef->preEvaluateRef( pd, code ); + paramRefs[pe.pos()] = refOf; + + pushCount += varRef->qual->length() * 2; + } + + /* Advance the parameter list iterator if we have it. */ + paramList != 0 && p.increment(); + } + + paramList != 0 && ( p = *paramList ); for ( ExprVect::Iter pe = *args; pe.lte(); pe++ ) { /* Get the expression and the UT for the arg. */ LangExpr *expression = *pe; 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; @@ -736,14 +844,20 @@ ObjField **LangVarRef::evaluateArgs( ParseData *pd, CodeVect &code, /* Lookup the field. */ LangVarRef *varRef = expression->term->varRef; - ObjField *refOf = varRef->evaluateRef( pd, code ); + pushCount -= varRef->qual->length() * 2; + + ObjField *refOf = varRef->evaluateRef( pd, code, pushCount ); paramRefs[pe.pos()] = refOf; + + pushCount += 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; + + pushCount += 1; } /* Advance the parameter list iterator if we have it. */ @@ -1667,7 +1781,7 @@ void LangStmt::compile( ParseData *pd, CodeVect &code ) const } case YieldType: { /* take a reference and yield it. Immediately reset the referece. */ - ObjField *objField = varRef->evaluateRef( pd, code ); + ObjField *objField = varRef->evaluateRef( pd, code, 0 ); objField->refActive = false; code.append( IN_YIELD ); break; diff --git a/colm/parsetree.h b/colm/parsetree.h index 08773cce..c34ed104 100644 --- a/colm/parsetree.h +++ b/colm/parsetree.h @@ -1343,6 +1343,7 @@ struct LangVarRef void loadGlobalObj( ParseData *pd, CodeVect &code, int lastPtrInQual, bool forWriting ) const; void loadObj( ParseData *pd, CodeVect &code, int lastPtrInQual, bool forWriting ) const; + void canTakeRef( ParseData *pd, VarRefLookup &lookup ) const; void setFieldIter( ParseData *pd, CodeVect &code, ObjectDef *inObject, UniqueType *objUT, UniqueType *exprType, bool revert ) const; @@ -1357,8 +1358,10 @@ struct LangVarRef void callOperation( ParseData *pd, CodeVect &code, VarRefLookup &lookup ) const; UniqueType *evaluateCall( ParseData *pd, CodeVect &code, ExprVect *args ) const; UniqueType *evaluate( ParseData *pd, CodeVect &code, bool forWriting = false ) const; - ObjField *evaluateRef( ParseData *pd, CodeVect &code ) const; + ObjField *evaluateRef( ParseData *pd, CodeVect &code, long pushCount ) const; + ObjField *preEvaluateRef( ParseData *pd, CodeVect &code ) const; void resetActiveRefs( ParseData *pd, VarRefLookup &lookup, ObjField **paramRefs ) const; + long loadQualificationRefs( ParseData *pd, CodeVect &code ) const; InputLoc loc; QualItemVect *qual; diff --git a/colm/tree.cpp b/colm/tree.cpp index 45ac50a6..476585ce 100644 --- a/colm/tree.cpp +++ b/colm/tree.cpp @@ -525,7 +525,7 @@ rec_call: if ( vm_ptop() != root ) { objectLength = lelInfo[((Kid*)vm_top())->tree->id].objectLength; if ( kidNum < objectLength ) - cout << " attr=" << kidNum; + cout << " an=\"" << kidNum << '"'; } objectLength = lelInfo[kid->tree->id].objectLength; |