summaryrefslogtreecommitdiff
path: root/src/lookup.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lookup.cc')
-rw-r--r--src/lookup.cc243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/lookup.cc b/src/lookup.cc
new file mode 100644
index 0000000..3809de3
--- /dev/null
+++ b/src/lookup.cc
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2007-2014 Adrian Thurston <thurston@complang.org>
+ */
+
+/* This file is part of Colm.
+ *
+ * Colm is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Colm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Colm; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "bytecode.h"
+#include "parsedata.h"
+
+#include <iostream>
+#include <assert.h>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+
+ObjectDef *UniqueType::objectDef()
+{
+ if ( typeId != TYPE_TREE && typeId != TYPE_REF ) {
+ /* This should have generated a compiler error. */
+ assert(false);
+ }
+
+ return langEl->objectDef;
+}
+
+/* Recurisve find through a single object def's scope. */
+ObjectField *ObjectDef::findFieldInScope( const ObjNameScope *inScope, const String &name ) const
+{
+ ObjFieldMapEl *objDefMapEl = inScope->objFieldMap->find( name );
+ if ( objDefMapEl != 0 )
+ return objDefMapEl->value;
+ if ( inScope->parentScope != 0 )
+ return findFieldInScope( inScope->parentScope, name );
+ return 0;
+}
+
+ObjectField *ObjNameScope::findField( const String &name ) const
+{
+ return owner->findFieldInScope( this, name );
+}
+
+ObjMethod *ObjectDef::findMethod( const String &name ) const
+{
+ ObjMethodMapEl *objMethodMapEl = objMethodMap->find( name );
+ if ( objMethodMapEl != 0 )
+ return objMethodMapEl->value;
+ return 0;
+}
+
+VarRefLookup LangVarRef::lookupQualification( Compiler *pd, ObjNameScope *rootScope ) const
+{
+ int lastPtrInQual = -1;
+ ObjNameScope *searchScope = rootScope;
+ int firstConstPart = -1;
+
+ for ( QualItemVect::Iter qi = *qual; qi.lte(); qi++ ) {
+ /* Lookup the field int the current qualification. */
+ ObjectField *el = searchScope->findField( qi->data );
+ if ( el == 0 )
+ error(qi->loc) << "cannot resolve qualification " << qi->data << endp;
+
+ /* Lookup the type of the field. */
+ el->typeRef->resolveType( pd );
+ UniqueType *qualUT = el->typeRef->uniqueType;
+
+ /* If we are dealing with an iterator then dereference it. */
+ if ( qualUT->typeId == TYPE_ITER )
+ qualUT = el->typeRef->searchUniqueType;
+
+ /* Is it const? */
+ if ( firstConstPart < 0 && el->isConst )
+ firstConstPart = qi.pos();
+
+ /* Check for references. When loop is done we will have the last one
+ * present, if any. */
+ if ( qualUT->typeId == TYPE_PTR )
+ lastPtrInQual = qi.pos();
+
+ if ( qi->form == QualItem::Dot ) {
+ /* Cannot dot a reference. Iterator yes (access of the iterator
+ * not the current) */
+ if ( qualUT->typeId == TYPE_PTR )
+ error(loc) << "dot cannot be used to access a pointer" << endp;
+ }
+ else if ( qi->form == QualItem::Arrow ) {
+ if ( qualUT->typeId == TYPE_ITER )
+ qualUT = el->typeRef->searchUniqueType;
+ else if ( qualUT->typeId == TYPE_PTR )
+ qualUT = pd->findUniqueType( TYPE_TREE, qualUT->langEl );
+ }
+
+ ObjectDef *searchObjDef = qualUT->objectDef();
+ searchScope = searchObjDef->rootScope;
+ }
+
+ return VarRefLookup( lastPtrInQual, firstConstPart, searchScope->owner, searchScope );
+}
+
+bool LangVarRef::isLocalRef() const
+{
+ if ( qual->length() > 0 ) {
+ if ( scope->findField( qual->data[0].data ) != 0 )
+ return true;
+ }
+ else if ( scope->findField( name ) != 0 )
+ return true;
+ else if ( scope->owner->findMethod( name ) != 0 )
+ return true;
+
+ return false;
+}
+
+bool LangVarRef::isContextRef() const
+{
+ if ( context != 0 ) {
+ if ( qual->length() > 0 ) {
+ if ( context->contextObjDef->rootScope->findField( qual->data[0].data ) != 0 )
+ return true;
+ }
+ else if ( context->contextObjDef->rootScope->findField( name ) != 0 )
+ return true;
+ else if ( context->contextObjDef->findMethod( name ) != 0 )
+ return true;
+ }
+
+ return false;
+}
+
+bool LangVarRef::isCustom() const
+{
+ if ( qual->length() > 0 ) {
+ ObjectField *field = scope->findField( qual->data[0].data );
+ if ( field != 0 && field->isCustom )
+ return true;
+ }
+ else {
+ ObjectField *field = scope->findField( name );
+ if ( field != 0 ) {
+ if ( field->isCustom )
+ return true;
+ }
+ else {
+ ObjMethod *method = scope->owner->findMethod( name );
+ if ( method != 0 && method->isCustom )
+ return true;
+ }
+
+ }
+ return false;
+}
+
+VarRefLookup LangVarRef::lookupObj( Compiler *pd ) const
+{
+ ObjNameScope *rootScope;
+ if ( isLocalRef() )
+ rootScope = scope;
+ else if ( isContextRef() )
+ rootScope = context->contextObjDef->rootScope;
+ else
+ rootScope = pd->globalObjectDef->rootScope;
+
+ return lookupQualification( pd, rootScope );
+}
+
+VarRefLookup LangVarRef::lookupField( Compiler *pd ) const
+{
+ /* Lookup the object that the field is in. */
+ VarRefLookup lookup = lookupObj( pd );
+
+ /* Lookup the field. */
+ ObjectField *field = lookup.inScope->findField( name );
+ if ( field == 0 )
+ error(loc) << "cannot find name " << name << " in object" << endp;
+
+ lookup.objField = field;
+ lookup.uniqueType = field->typeRef->uniqueType;
+
+ if ( field->typeRef->searchUniqueType != 0 )
+ lookup.iterSearchUT = field->typeRef->searchUniqueType;
+
+ return lookup;
+}
+
+UniqueType *LangVarRef::lookup( Compiler *pd ) const
+{
+ /* Lookup the loadObj. */
+ VarRefLookup lookup = lookupField( pd );
+
+ ObjectField *el = lookup.objField;
+ UniqueType *elUT = el->typeRef->resolveType( pd );
+
+ /* Deref iterators. */
+ if ( elUT->typeId == TYPE_ITER )
+ elUT = el->typeRef->searchUniqueType;
+
+ return elUT;
+}
+
+
+VarRefLookup LangVarRef::lookupMethod( Compiler *pd ) const
+{
+ /* Lookup the object that the field is in. */
+ VarRefLookup lookup = lookupObj( pd );
+
+ /* Find the method. */
+ assert( lookup.inObject->objMethodMap != 0 );
+ ObjMethod *method = lookup.inObject->findMethod( name );
+ if ( method == 0 ) {
+ /* Not found as a method, try it as an object on which we will call a
+ * default function. */
+ qual->append( QualItem( QualItem::Dot, loc, name ) );
+
+ /* Lookup the object that the field is in. */
+ VarRefLookup lookup = lookupObj( pd );
+
+ /* Find the method. */
+ assert( lookup.inObject->objMethodMap != 0 );
+ method = lookup.inObject->findMethod( "finish" );
+ if ( method == 0 )
+ error(loc) << "cannot find " << name << "(...) in object" << endp;
+ }
+
+ lookup.objMethod = method;
+ lookup.uniqueType = method->returnUT;
+
+ return lookup;
+}