summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@complang.org>2009-02-06 02:08:57 +0000
committerAdrian Thurston <thurston@complang.org>2009-02-06 02:08:57 +0000
commit687a4b9503616a7ed872b7eab08e69d7709cc7fa (patch)
tree69954b332b1aca22bb51c6fa32570922da476b27
parent34f8eabcf0a11adefc1ab924f29d96ff99cf7d2d (diff)
downloadcolm-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.cpp13
-rw-r--r--colm/bytecode.h1
-rw-r--r--colm/compile.cpp136
-rw-r--r--colm/parsetree.h5
-rw-r--r--colm/tree.cpp2
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;