/* * Copyright 2012-2018 Adrian Thurston * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include "compiler.h" void Compiler::initUniqueTypes( ) { uniqueTypeNil = new UniqueType( TYPE_NIL ); uniqueTypeVoid = new UniqueType( TYPE_VOID ); uniqueTypePtr = new UniqueType( TYPE_TREE, ptrLangEl ); uniqueTypeBool = new UniqueType( TYPE_BOOL ); uniqueTypeInt = new UniqueType( TYPE_INT ); uniqueTypeStr = new UniqueType( TYPE_TREE, strLangEl ); uniqueTypeIgnore = new UniqueType( TYPE_TREE, ignoreLangEl ); uniqueTypeAny = new UniqueType( TYPE_TREE, anyLangEl ); uniqueTypeInput = new UniqueType( TYPE_STRUCT, inputSel ); uniqueTypeStream = new UniqueType( TYPE_STRUCT, streamSel ); uniqeTypeMap.insert( uniqueTypeNil ); uniqeTypeMap.insert( uniqueTypeVoid ); uniqeTypeMap.insert( uniqueTypePtr ); uniqeTypeMap.insert( uniqueTypeBool ); uniqeTypeMap.insert( uniqueTypeInt ); uniqeTypeMap.insert( uniqueTypeStr ); uniqeTypeMap.insert( uniqueTypeIgnore ); uniqeTypeMap.insert( uniqueTypeAny ); uniqeTypeMap.insert( uniqueTypeInput ); uniqeTypeMap.insert( uniqueTypeStream ); } ObjectMethod *initFunction( UniqueType *retType, Namespace *nspace, ObjectDef *obj, ObjectMethod::Type type, const String &name, int methIdWV, int methIdWC, int nargs, UniqueType **args, bool isConst, bool useFnInstr, GenericType *useGeneric ) { ObjectMethod *objMethod = new ObjectMethod( retType, name, methIdWV, methIdWC, nargs, args, 0, isConst ); objMethod->type = type; objMethod->useFnInstr = useFnInstr; if ( nspace != 0 ) nspace->rootScope->methodMap.insert( name, objMethod ); else obj->rootScope->methodMap.insert( name, objMethod ); if ( useGeneric ) { objMethod->useGenericId = true; objMethod->generic = useGeneric; } return objMethod; } ObjectMethod *initFunction( UniqueType *retType, ObjectDef *obj, ObjectMethod::Type type, const String &name, int methIdWV, int methIdWC, bool isConst, bool useFnInstr, GenericType *useGeneric ) { return initFunction( retType, 0, obj, type, name, methIdWV, methIdWC, 0, 0, isConst, useFnInstr, useGeneric ); } ObjectMethod *initFunction( UniqueType *retType, ObjectDef *obj, ObjectMethod::Type type, const String &name, int methIdWV, int methIdWC, UniqueType *arg1, bool isConst, bool useFnInstr, GenericType *useGeneric ) { UniqueType *args[] = { arg1 }; return initFunction( retType, 0, obj, type, name, methIdWV, methIdWC, 1, args, isConst, useFnInstr, useGeneric ); } ObjectMethod *initFunction( UniqueType *retType, ObjectDef *obj, ObjectMethod::Type type, const String &name, int methIdWV, int methIdWC, UniqueType *arg1, UniqueType *arg2, bool isConst, bool useFnInstr, GenericType *useGeneric ) { UniqueType *args[] = { arg1, arg2 }; return initFunction( retType, 0, obj, type, name, methIdWV, methIdWC, 2, args, isConst, useFnInstr, useGeneric ); } /* * With namespace supplied. Global functions. */ ObjectMethod *initFunction( UniqueType *retType, Namespace *nspace, ObjectDef *obj, ObjectMethod::Type type, const String &name, int methIdWV, int methIdWC, bool isConst, bool useFnInstr, GenericType *useGeneric ) { return initFunction( retType, nspace, obj, type, name, methIdWV, methIdWC, 0, 0, isConst, useFnInstr, useGeneric ); } ObjectMethod *initFunction( UniqueType *retType, Namespace *nspace, ObjectDef *obj, ObjectMethod::Type type, const String &name, int methIdWV, int methIdWC, UniqueType *arg1, bool isConst, bool useFnInstr, GenericType *useGeneric ) { UniqueType *args[] = { arg1 }; return initFunction( retType, nspace, obj, type, name, methIdWV, methIdWC, 1, args, isConst, useFnInstr, useGeneric ); } ObjectMethod *initFunction( UniqueType *retType, Namespace *nspace, ObjectDef *obj, ObjectMethod::Type type, const String &name, int methIdWV, int methIdWC, UniqueType *arg1, UniqueType *arg2, bool isConst, bool useFnInstr, GenericType *useGeneric ) { UniqueType *args[] = { arg1, arg2 }; return initFunction( retType, nspace, obj, type, name, methIdWV, methIdWC, 2, args, isConst, useFnInstr, useGeneric ); } ObjectField *NameScope::checkRedecl( const String &name ) { return owningObj->checkRedecl( this, name ); } void NameScope::insertField( const String &name, ObjectField *value ) { return owningObj->insertField( this, name, value ); } ObjectField *ObjectDef::checkRedecl( NameScope *inScope, const String &name ) { FieldMapEl *objDefMapEl = inScope->fieldMap.find( name ); if ( objDefMapEl != 0 ) return objDefMapEl->value; return 0; } void ObjectDef::insertField( NameScope *inScope, const String &name, ObjectField *value ) { inScope->fieldMap.insert( name, value ); fieldList.append( value ); value->scope = inScope; } NameScope *ObjectDef::pushScope( NameScope *curScope ) { NameScope *newScope = new NameScope; newScope->owningObj = this; newScope->parentScope = curScope; curScope->children.append( newScope ); return newScope; } void LexJoin::varDecl( Compiler *pd, TokenDef *tokenDef ) { expr->varDecl( pd, tokenDef ); } void LexExpression::varDecl( Compiler *pd, TokenDef *tokenDef ) { switch ( type ) { case OrType: case IntersectType: case SubtractType: case StrongSubtractType: expression->varDecl( pd, tokenDef ); term->varDecl( pd, tokenDef ); break; case TermType: term->varDecl( pd, tokenDef ); break; case BuiltinType: break; } } void LexTerm::varDecl( Compiler *pd, TokenDef *tokenDef ) { switch ( type ) { case ConcatType: case RightStartType: case RightFinishType: case LeftType: term->varDecl( pd, tokenDef ); factorAug->varDecl( pd, tokenDef ); break; case FactorAugType: factorAug->varDecl( pd, tokenDef ); break; } } void LexFactorAug::varDecl( Compiler *pd, TokenDef *tokenDef ) { for ( ReCaptureVect::Iter re = reCaptureVect; re.lte(); re++ ) { if ( tokenDef->objectDef->rootScope->checkRedecl( re->objField->name ) != 0 ) { error(re->objField->loc) << "label name \"" << re->objField->name << "\" already in use" << endp; } /* Insert it into the map. */ tokenDef->objectDef->rootScope->insertField( re->objField->name, re->objField ); /* Store it in the TokenDef. */ tokenDef->reCaptureVect.append( *re ); } } void Compiler::declareReVars() { for ( NamespaceList::Iter n = namespaceList; n.lte(); n++ ) { for ( TokenDefListNs::Iter tok = n->tokenDefList; tok.lte(); tok++ ) { if ( tok->join != 0 ) tok->join->varDecl( this, tok ); } } /* FIXME: declare RE captures in token generation actions. */ #if 0 /* Add captures to the local frame. We Depend on these becoming the * first local variables so we can compute their location. */ /* Make local variables corresponding to the local capture vector. */ for ( ReCaptureVect::Iter c = reCaptureVect; c.lte(); c++ ) { ObjectField *objField = ObjectField::cons( c->objField->loc, c->objField->typeRef, c->objField->name ); /* Insert it into the field map. */ pd->curLocalFrame->insertField( objField->name, objField ); } #endif } LangEl *declareLangEl( Compiler *pd, Namespace *nspace, const String &data, LangEl::Type type ) { /* If the id is already in the dict, it will be placed in last found. If it * is not there then it will be inserted and last found will be set to it. */ TypeMapEl *inDict = nspace->typeMap.find( data ); if ( inDict != 0 ) error() << "language element '" << data << "' already defined as something else" << endp; /* Language element not there. Make the new lang el and insert.. */ LangEl *langEl = new LangEl( nspace, data, type ); TypeMapEl *typeMapEl = new TypeMapEl( TypeMapEl::LangElType, data, langEl ); nspace->typeMap.insert( typeMapEl ); pd->langEls.append( langEl ); return langEl; } StructEl *declareStruct( Compiler *pd, Namespace *inNspace, const String &data, StructDef *structDef ) { if ( inNspace != 0 ) { TypeMapEl *inDict = inNspace->typeMap.find( data ); if ( inDict != 0 ) error() << "struct '" << data << "' already defined as something else" << endp; } StructEl *structEl = new StructEl( data, structDef ); pd->structEls.append( structEl ); structDef->structEl = structEl; if ( inNspace ) { TypeMapEl *typeMapEl = new TypeMapEl( TypeMapEl::StructType, data, structEl ); inNspace->typeMap.insert( typeMapEl ); } return structEl; } /* Does not map the new language element. */ LangEl *addLangEl( Compiler *pd, Namespace *inNspace, const String &data, LangEl::Type type ) { LangEl *langEl = new LangEl( inNspace, data, type ); pd->langEls.append( langEl ); return langEl; } void declareTypeAlias( Compiler *pd, Namespace *nspace, const String &data, TypeRef *typeRef ) { /* If the id is already in the dict, it will be placed in last found. If * it is not there then it will be inserted and last found will be set to it. */ TypeMapEl *inDict = nspace->typeMap.find( data ); if ( inDict != 0 ) error() << "alias '" << data << "' already defined as something else" << endp; /* Language element not there. Make the new lang el and insert. */ TypeMapEl *typeMapEl = new TypeMapEl( TypeMapEl::AliasType, data, typeRef ); nspace->typeMap.insert( typeMapEl ); } LangEl *findType( Compiler *pd, Namespace *nspace, const String &data ) { /* If the id is already in the dict, it will be placed in last found. If * it is not there then it will be inserted and last found will be set to it. */ TypeMapEl *inDict = nspace->typeMap.find( data ); if ( inDict == 0 ) error() << "'" << data << "' not declared as anything" << endp; return inDict->value; } void Compiler::declareBaseLangEls() { /* Order here is important because we make assumptions about the inbuilt * language elements in the runtime. Note tokens are have identifiers set * in an initial pass. */ /* Make a "_notoken" language element. This element is used when a * generation action fails to generate anything, but there is reverse code * that needs to be associated with a language element. This allows us to * always associate reverse code with the first language element produced * after a generation action. */ noTokenLangEl = declareLangEl( this, rootNamespace, "_notoken", LangEl::Term ); noTokenLangEl->isIgnore = true; ptrLangEl = declareLangEl( this, rootNamespace, "ptr", LangEl::Term ); strLangEl = declareLangEl( this, rootNamespace, "str", LangEl::Term ); ignoreLangEl = declareLangEl( this, rootNamespace, "il", LangEl::Term ); /* Make the EOF language element. */ eofLangEl = 0; /* Make the "any" language element */ anyLangEl = declareLangEl( this, rootNamespace, "any", LangEl::NonTerm ); } void Compiler::addProdRedObjectVar( ObjectDef *localFrame, LangEl *nonTerm ) { UniqueType *prodNameUT = findUniqueType( TYPE_TREE, nonTerm ); TypeRef *typeRef = TypeRef::cons( internal, prodNameUT ); ObjectField *el = ObjectField::cons( internal, ObjectField::LhsElType, typeRef, "lhs" ); localFrame->rootScope->insertField( el->name, el ); } void Compiler::addProdRHSVars( ObjectDef *localFrame, ProdElList *prodElList ) { long position = 1; for ( ProdElList::Iter rhsEl = *prodElList; rhsEl.lte(); rhsEl++, position++ ) { if ( rhsEl->type == ProdEl::ReferenceType ) { /* Use an offset of zero. For frame objects we compute the offset on * demand. */ String name( 8, "r%d", position ); ObjectField *el = ObjectField::cons( InputLoc(), ObjectField::RedRhsType, rhsEl->typeRef, name ); rhsEl->rhsElField = el; /* Right hand side elements are constant. */ el->isConst = true; localFrame->rootScope->insertField( el->name, el ); } } } void GenericType::declare( Compiler *pd, Namespace *nspace ) { elUt = elTr->resolveType( pd ); if ( typeId == GEN_MAP ) keyUt = keyTr->resolveType( pd ); if ( typeId == GEN_MAP || typeId == GEN_LIST ) valueUt = valueTr->resolveType( pd ); objDef = ObjectDef::cons( ObjectDef::BuiltinType, "generic", pd->nextObjectId++ ); switch ( typeId ) { case GEN_MAP: pd->initMapFunctions( this ); pd->initMapFields( this ); break; case GEN_LIST: pd->initListFunctions( this ); pd->initListFields( this ); break; case GEN_PARSER: elUt->langEl->parserId = pd->nextParserId++; pd->initParserFunctions( this ); pd->initParserFields( this ); break; } } void Namespace::declare( Compiler *pd ) { for ( GenericList::Iter g = genericList; g.lte(); g++ ) g->declare( pd, this ); for ( TokenDefListNs::Iter tokenDef = tokenDefList; tokenDef.lte(); tokenDef++ ) { if ( tokenDef->isLiteral ) { if ( tokenDef->isZero ) { assert( tokenDef->regionSet->collectIgnore->zeroLel != 0 ); tokenDef->tdLangEl = tokenDef->regionSet->collectIgnore->zeroLel; } else { /* Original. Create a token for the literal. */ LangEl *litEl = declareLangEl( pd, this, tokenDef->name, LangEl::Term ); litEl->lit = tokenDef->literal; litEl->isLiteral = true; litEl->tokenDef = tokenDef; litEl->objectDef = tokenDef->objectDef; tokenDef->tdLangEl = litEl; if ( tokenDef->noPreIgnore ) litEl->noPreIgnore = true; if ( tokenDef->noPostIgnore ) litEl->noPostIgnore = true; } } } for ( StructDefList::Iter s = structDefList; s.lte(); s++ ) declareStruct( pd, this, s->name, s ); for ( TokenDefListNs::Iter tokenDef = tokenDefList; tokenDef.lte(); tokenDef++ ) { /* Literals already taken care of. */ if ( ! tokenDef->isLiteral ) { /* Create the token. */ LangEl *tokEl = declareLangEl( pd, this, tokenDef->name, LangEl::Term ); tokEl->isIgnore = tokenDef->isIgnore; tokEl->transBlock = tokenDef->codeBlock; tokEl->objectDef = tokenDef->objectDef; tokEl->contextIn = tokenDef->contextIn; tokEl->tokenDef = tokenDef; if ( tokenDef->noPreIgnore ) tokEl->noPreIgnore = true; if ( tokenDef->noPostIgnore ) tokEl->noPostIgnore = true; tokenDef->tdLangEl = tokEl; if ( tokenDef->isZero ) { /* Setting zero lel to newly created tokEl. */ tokenDef->regionSet->collectIgnore->zeroLel = tokEl; tokEl->isZero = true; } } } for ( NtDefList::Iter n = ntDefList; n.lte(); n++ ) { /* Get the language element. */ if ( n->isRedef ) { TypeMapEl *inDict = this->typeMap.find( n->name ); if ( inDict == 0 ) { error() << "redef not found '" << n->name << endp; } LangEl *langEl = inDict->value; this->typeMap.remove( n->name ); /* Traverse the list of productions, moving to combined and taking * the original language element's productions when we enounter * [...]. Afterwards move the newly combined productions * to the nonterminal-definition and proceed with the declaration. */ LelProdList combined; while ( n->prodList->length() > 0 ) { Production *prod = n->prodList->detachFirst(); if ( prod->dotDotDot ) { while ( langEl->prodList.length() ) { Production *prod = langEl->prodList.detachFirst(); prod->prodNum = combined.length(); combined.append( prod ); } } else { prod->prodNum = combined.length(); combined.append( prod ); } } /* Move bak to non-term def and proceed with rest of declaration. */ n->prodList->transfer( combined ); } LangEl *langEl = declareLangEl( pd, this, n->name, LangEl::NonTerm ); /* Get the language element. */ langEl->objectDef = n->objectDef; langEl->reduceFirst = n->reduceFirst; langEl->contextIn = n->contextIn; langEl->prodList.transfer( *n->prodList ); for ( LelProdList::Iter d = langEl->prodList; d.lte(); d++ ) { d->prodName = langEl; if ( d->redBlock != 0 ) { pd->addProdRedObjectVar( d->redBlock->localFrame, langEl ); pd->addProdRHSVars( d->redBlock->localFrame, d->prodElList ); } /* References to the reduce item. */ } } for ( TypeAliasList::Iter ta = typeAliasList; ta.lte(); ta++ ) declareTypeAlias( pd, this, ta->name, ta->typeRef ); /* Go into child namespaces. */ for ( NamespaceVect::Iter c = childNamespaces; c.lte(); c++ ) (*c)->declare( pd ); } void Compiler::makeIgnoreCollectors() { for ( RegionSetList::Iter regionSet = regionSetList; regionSet.lte(); regionSet++ ) { if ( regionSet->collectIgnore->zeroLel == 0 ) { String name( 128, "_ign_%p", regionSet->tokenIgnore ); LangEl *zeroLel = new LangEl( rootNamespace, name, LangEl::Term ); langEls.append( zeroLel ); zeroLel->isZero = true; zeroLel->regionSet = regionSet; regionSet->collectIgnore->zeroLel = zeroLel; } } } 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, 0, context, scope, "triter" ); /* The parameters. */ CallArgVect *callExprVect = new CallArgVect; callExprVect->append( new CallArg( iterCall->langExpr ) ); iterCall->langTerm = LangTerm::cons( InputLoc(), callVarRef, callExprVect ); iterCall->langExpr = 0; iterCall->form = IterCall::Call; iterCall->wasExpr = true; } void LangStmt::declareForIter( Compiler *pd ) const { if ( iterCall->form != IterCall::Call ) chooseDefaultIter( pd, iterCall ); objField->typeRef = TypeRef::cons( loc, typeRef, iterCall ); } void LangStmt::declare( Compiler *pd ) const { switch ( type ) { case ExprType: break; case IfType: for ( StmtList::Iter stmt = *stmtList; stmt.lte(); stmt++ ) stmt->declare( pd ); if ( elsePart != 0 ) elsePart->declare( pd ); break; case ElseType: for ( StmtList::Iter stmt = *stmtList; stmt.lte(); stmt++ ) stmt->declare( pd ); break; case RejectType: break; case WhileType: for ( StmtList::Iter stmt = *stmtList; stmt.lte(); stmt++ ) stmt->declare( pd ); break; case AssignType: break; case ForIterType: declareForIter( pd ); for ( StmtList::Iter stmt = *stmtList; stmt.lte(); stmt++ ) stmt->declare( pd ); break; case ReturnType: break; case BreakType: break; case YieldType: break; } } void CodeBlock::declare( Compiler *pd ) const { for ( StmtList::Iter stmt = *stmtList; stmt.lte(); stmt++ ) stmt->declare( pd ); } void Compiler::declareFunction( Function *func ) { CodeBlock *block = func->codeBlock; block->declare( this ); } void Compiler::declareReductionCode( Production *prod ) { CodeBlock *block = prod->redBlock; block->declare( this ); } void Compiler::declareTranslateBlock( LangEl *langEl ) { CodeBlock *block = langEl->transBlock; /* References to the reduce item. */ addMatchLength( block->localFrame, langEl ); addMatchText( block->localFrame, langEl ); addInput( block->localFrame ); addThis( block->localFrame ); block->declare( this ); } void Compiler::declarePreEof( TokenRegion *region ) { CodeBlock *block = region->preEofBlock; addInput( block->localFrame ); addThis( block->localFrame ); block->declare( this ); } void Compiler::declareRootBlock() { CodeBlock *block = rootCodeBlock; block->declare( this ); } void Compiler::declareByteCode() { for ( FunctionList::Iter f = functionList; f.lte(); f++ ) declareFunction( f ); for ( ProdList::Iter prod = prodList; prod.lte(); prod++ ) { if ( prod->redBlock != 0 ) declareReductionCode( prod ); } for ( LelList::Iter lel = langEls; lel.lte(); lel++ ) { if ( lel->transBlock != 0 ) declareTranslateBlock( lel ); } for ( RegionList::Iter r = regionList; r.lte(); r++ ) { if ( r->preEofBlock != 0 ) declarePreEof( r ); } declareRootBlock( ); } void Compiler::makeDefaultIterators() { /* Tree iterator. */ { UniqueType *anyRefUT = findUniqueType( TYPE_REF, anyLangEl ); ObjectMethod *objMethod = initFunction( uniqueTypeAny, rootNamespace, globalObjectDef, ObjectMethod::Call, "triter", IN_HALT, IN_HALT, anyRefUT, true ); IterDef *triter = findIterDef( IterDef::Tree ); objMethod->iterDef = triter; } { UniqueType *anyRefUT = findUniqueType( TYPE_REF, anyLangEl ); ObjectMethod *objMethod = initFunction( uniqueTypeAny, rootNamespace, globalObjectDef, ObjectMethod::Call, "with_ignore", IN_HALT, IN_HALT, anyRefUT, true ); IterDef *triter = findIterDef( IterDef::WithIgnore ); objMethod->iterDef = triter; } /* Child iterator. */ { UniqueType *anyRefUT = findUniqueType( TYPE_REF, anyLangEl ); ObjectMethod *objMethod = initFunction( uniqueTypeAny, rootNamespace, globalObjectDef, ObjectMethod::Call, "child", IN_HALT, IN_HALT, anyRefUT, true ); IterDef *triter = findIterDef( IterDef::Child ); objMethod->iterDef = triter; } /* Reverse iterator. */ { UniqueType *anyRefUT = findUniqueType( TYPE_REF, anyLangEl ); ObjectMethod *objMethod = initFunction( uniqueTypeAny, rootNamespace, globalObjectDef, ObjectMethod::Call, "rev_child", IN_HALT, IN_HALT, anyRefUT, true ); IterDef *triter = findIterDef( IterDef::RevChild ); objMethod->iterDef = triter; } /* Repeat iterator. */ { UniqueType *anyRefUT = findUniqueType( TYPE_REF, anyLangEl ); ObjectMethod *objMethod = initFunction( uniqueTypeAny, rootNamespace, globalObjectDef, ObjectMethod::Call, "repeat", IN_HALT, IN_HALT, anyRefUT, true ); IterDef *triter = findIterDef( IterDef::Repeat ); objMethod->iterDef = triter; } /* Reverse repeat iterator. */ { UniqueType *anyRefUT = findUniqueType( TYPE_REF, anyLangEl ); ObjectMethod *objMethod = initFunction( uniqueTypeAny, rootNamespace, globalObjectDef, ObjectMethod::Call, "rev_repeat", IN_HALT, IN_HALT, anyRefUT, true ); IterDef *triter = findIterDef( IterDef::RevRepeat ); objMethod->iterDef = triter; } /* List iterator. */ { UniqueType *anyRefUT = findUniqueType( TYPE_REF, anyLangEl ); ObjectMethod *objMethod = initFunction( uniqueTypeAny, rootNamespace, globalObjectDef, ObjectMethod::Call, "list_iter", IN_HALT, IN_HALT, anyRefUT, true ); IterDef *triter = findIterDef( IterDef::ListEl ); objMethod->iterDef = triter; } /* Reverse Value List iterator. */ { UniqueType *anyRefUT = findUniqueType( TYPE_REF, anyLangEl ); ObjectMethod *objMethod = initFunction( uniqueTypeAny, rootNamespace, globalObjectDef, ObjectMethod::Call, "rev_list_iter", IN_HALT, IN_HALT, anyRefUT, true ); IterDef *triter = findIterDef( IterDef::RevListVal ); objMethod->iterDef = triter; } /* Map iterator. */ { UniqueType *anyRefUT = findUniqueType( TYPE_REF, anyLangEl ); ObjectMethod *objMethod = initFunction( uniqueTypeAny, rootNamespace, globalObjectDef, ObjectMethod::Call, "map_iter", IN_HALT, IN_HALT, anyRefUT, true ); IterDef *triter = findIterDef( IterDef::MapEl ); objMethod->iterDef = triter; } } void Compiler::addMatchLength( ObjectDef *frame, LangEl *lel ) { /* Make the type ref. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeInt ); /* Create the field and insert it into the map. */ ObjectField *el = ObjectField::cons( InputLoc(), ObjectField::InbuiltFieldType, typeRef, "match_length" ); el->isConst = true; el->inGetR = IN_GET_MATCH_LENGTH_R; el->inGetValR = IN_GET_MATCH_LENGTH_R; frame->rootScope->insertField( el->name, el ); } void Compiler::addMatchText( ObjectDef *frame, LangEl *lel ) { /* Make the type ref. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStr ); /* Create the field and insert it into the map. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "match_text" ); el->isConst = true; el->inGetR = IN_GET_MATCH_TEXT_R; el->inGetValR = IN_GET_MATCH_TEXT_R; frame->rootScope->insertField( el->name, el ); } void Compiler::addInput( ObjectDef *frame ) { /* Make the type ref. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeInput ); /* Create the field and insert it into the map. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltObjectType, typeRef, "input" ); el->inGetR = IN_LOAD_INPUT_R; el->inGetWV = IN_LOAD_INPUT_WV; el->inGetWC = IN_LOAD_INPUT_WC; el->inGetValR = IN_LOAD_INPUT_R; el->inGetValWC = IN_LOAD_INPUT_WC; el->inGetValWV = IN_LOAD_INPUT_WV; frame->rootScope->insertField( el->name, el ); } void Compiler::addThis( ObjectDef *frame ) { /* Make the type ref. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStream ); /* Create the field and insert it into the map. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltObjectType, typeRef, "this" ); el->inGetR = IN_LOAD_CONTEXT_R; el->inGetWV = IN_LOAD_CONTEXT_WV; el->inGetWC = IN_LOAD_CONTEXT_WC; el->inGetValR = IN_LOAD_CONTEXT_R; el->inGetValWC = IN_LOAD_CONTEXT_WC; el->inGetValWV = IN_LOAD_CONTEXT_WV; frame->rootScope->insertField( el->name, el ); } void Compiler::declareIntFields( ) { intObj = ObjectDef::cons( ObjectDef::BuiltinType, "int", nextObjectId++ ); // intLangEl->objectDef = intObj; initFunction( uniqueTypeStr, intObj, ObjectMethod::Call, "to_string", IN_INT_TO_STR, IN_INT_TO_STR, true ); } void Compiler::declareStrFields( ) { strObj = ObjectDef::cons( ObjectDef::BuiltinType, "str", nextObjectId++ ); strLangEl->objectDef = strObj; initFunction( uniqueTypeInt, strObj, ObjectMethod::Call, "atoi", FN_STR_ATOI, FN_STR_ATOI, true, true ); initFunction( uniqueTypeInt, strObj, ObjectMethod::Call, "atoo", FN_STR_ATOO, FN_STR_ATOO, true, true ); initFunction( uniqueTypeInt, strObj, ObjectMethod::Call, "uord8", FN_STR_UORD8, FN_STR_UORD8, true, true ); initFunction( uniqueTypeInt, strObj, ObjectMethod::Call, "sord8", FN_STR_SORD8, FN_STR_SORD8, true, true ); initFunction( uniqueTypeInt, strObj, ObjectMethod::Call, "uord16", FN_STR_UORD16, FN_STR_UORD16, true, true ); initFunction( uniqueTypeInt, strObj, ObjectMethod::Call, "sord16", FN_STR_SORD16, FN_STR_SORD16, true, true ); initFunction( uniqueTypeInt, strObj, ObjectMethod::Call, "uord32", FN_STR_UORD32, FN_STR_UORD32, true, true ); initFunction( uniqueTypeInt, strObj, ObjectMethod::Call, "sord32", FN_STR_SORD32, FN_STR_SORD32, true, true ); initFunction( uniqueTypeStr, strObj, ObjectMethod::Call, "prefix", FN_STR_PREFIX, FN_STR_PREFIX, uniqueTypeInt, true, true ); initFunction( uniqueTypeStr, strObj, ObjectMethod::Call, "suffix", FN_STR_SUFFIX, FN_STR_SUFFIX, uniqueTypeInt, true, true ); initFunction( uniqueTypeStr, rootNamespace, globalObjectDef, ObjectMethod::Call, "sprintf", FN_SPRINTF, FN_SPRINTF, uniqueTypeStr, uniqueTypeInt, true, true ); addLengthField( strObj, IN_STR_LENGTH ); } void Compiler::declareInputField( ObjectDef *objDef, code_t getLength ) { /* Create the "length" field. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStr ); ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "tree" ); el->isConst = true; el->inGetR = IN_GET_COLLECT_STRING; el->inGetValR = IN_GET_COLLECT_STRING; objDef->rootScope->insertField( el->name, el ); } void Compiler::declareStreamField( ObjectDef *objDef, code_t getLength ) { /* Create the "length" field. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStr ); ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "tree" ); el->isConst = true; el->inGetR = IN_GET_COLLECT_STRING; el->inGetValR = IN_GET_COLLECT_STRING; objDef->rootScope->insertField( el->name, el ); } void Compiler::declareInputFields( ) { inputObj = inputSel->structDef->objectDef; initFunction( uniqueTypeStr, inputObj, ObjectMethod::Call, "pull", IN_INPUT_PULL_WV, IN_INPUT_PULL_WC, uniqueTypeInt, false ); initFunction( uniqueTypeStr, inputObj, ObjectMethod::Call, "push", IN_INPUT_PUSH_WV, IN_INPUT_PUSH_WV, uniqueTypeAny, false ); initFunction( uniqueTypeStr, inputObj, ObjectMethod::Call, "push_ignore", IN_INPUT_PUSH_IGNORE_WV, IN_INPUT_PUSH_IGNORE_WV, uniqueTypeAny, false ); initFunction( uniqueTypeStr, inputObj, ObjectMethod::Call, "push_stream", IN_INPUT_PUSH_STREAM_WV, IN_INPUT_PUSH_STREAM_WV, uniqueTypeStream, false ); initFunction( uniqueTypeVoid, inputObj, ObjectMethod::Call, "close", IN_INPUT_CLOSE_WC, IN_INPUT_CLOSE_WC, false ); initFunction( uniqueTypeVoid, inputObj, ObjectMethod::Call, "auto_trim", IN_IINPUT_AUTO_TRIM_WC, IN_IINPUT_AUTO_TRIM_WC, uniqueTypeBool, false ); declareInputField( inputObj, 0 ); } void Compiler::declareStreamFields( ) { streamObj = streamSel->structDef->objectDef; initFunction( uniqueTypeStr, streamObj, ObjectMethod::Call, "pull", IN_INPUT_PULL_WV, IN_INPUT_PULL_WC, uniqueTypeInt, false ); initFunction( uniqueTypeStr, streamObj, ObjectMethod::Call, "push", IN_INPUT_PUSH_WV, IN_INPUT_PUSH_WV, uniqueTypeAny, false ); initFunction( uniqueTypeStr, streamObj, ObjectMethod::Call, "push_ignore", IN_INPUT_PUSH_IGNORE_WV, IN_INPUT_PUSH_IGNORE_WV, uniqueTypeAny, false ); initFunction( uniqueTypeStr, streamObj, ObjectMethod::Call, "push_stream", IN_INPUT_PUSH_STREAM_WV, IN_INPUT_PUSH_STREAM_WV, uniqueTypeStream, false ); initFunction( uniqueTypeVoid, streamObj, ObjectMethod::Call, "close", IN_INPUT_CLOSE_WC, IN_INPUT_CLOSE_WC, false ); initFunction( uniqueTypeVoid, streamObj, ObjectMethod::Call, "auto_trim", IN_INPUT_AUTO_TRIM_WC, IN_INPUT_AUTO_TRIM_WC, uniqueTypeBool, false ); declareStreamField( streamObj, 0 ); } ObjectField *Compiler::makeDataEl() { /* Create the "data" field. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStr ); ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "data" ); el->inGetR = IN_GET_TOKEN_DATA_R; el->inSetWC = IN_SET_TOKEN_DATA_WC; el->inSetWV = IN_SET_TOKEN_DATA_WV; return el; } ObjectField *Compiler::makeFileEl() { /* Create the "file" field. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStr ); ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "file" ); el->isConst = true; el->inGetR = IN_GET_TOKEN_FILE_R; el->inGetValR = IN_GET_TOKEN_FILE_R; return el; } ObjectField *Compiler::makeLineEl() { /* Create the "line" field. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeInt ); ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "line" ); el->isConst = true; el->inGetR = IN_GET_TOKEN_LINE_R; el->inGetValR = IN_GET_TOKEN_LINE_R; return el; } ObjectField *Compiler::makeColEl() { /* Create the "col" field. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeInt ); ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "col" ); el->isConst = true; el->inGetR = IN_GET_TOKEN_COL_R; el->inGetValR = IN_GET_TOKEN_COL_R; return el; } ObjectField *Compiler::makePosEl() { /* Create the "data" field. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeInt ); ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "pos" ); el->isConst = true; el->inGetR = IN_GET_TOKEN_POS_R; el->inGetValR = IN_GET_TOKEN_POS_R; return el; } /* Add a constant length field to the object. * Opcode supplied by the caller. */ void Compiler::addLengthField( ObjectDef *objDef, code_t getLength ) { /* Create the "length" field. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeInt ); ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "length" ); el->isConst = true; el->inGetR = getLength; el->inGetValR = getLength; objDef->rootScope->insertField( el->name, el ); } void Compiler::declareTokenFields( ) { /* Give all user terminals the token object type. */ for ( LelList::Iter lel = langEls; lel.lte(); lel++ ) { if ( lel->type == LangEl::Term ) { if ( lel->objectDef != 0 ) { /* Create the "data" field. */ ObjectField *dataEl = makeDataEl(); lel->objectDef->rootScope->insertField( dataEl->name, dataEl ); /* Create the "file" field. */ ObjectField *fileEl = makeFileEl(); lel->objectDef->rootScope->insertField( fileEl->name, fileEl ); /* Create the "line" field. */ ObjectField *lineEl = makeLineEl(); lel->objectDef->rootScope->insertField( lineEl->name, lineEl ); /* Create the "col" field. */ ObjectField *colEl = makeColEl(); lel->objectDef->rootScope->insertField( colEl->name, colEl ); /* Create the "pos" field. */ ObjectField *posEl = makePosEl(); lel->objectDef->rootScope->insertField( posEl->name, posEl ); } } } } void Compiler::declareGlobalFields() { ObjectMethod *method; method = initFunction( uniqueTypeStream, rootNamespace, globalObjectDef, ObjectMethod::Call, "open", IN_OPEN_FILE, IN_OPEN_FILE, uniqueTypeStr, uniqueTypeStr, true ); method->useCallObj = false; method = initFunction( uniqueTypeStr, rootNamespace, globalObjectDef, ObjectMethod::Call, "tolower", IN_TO_LOWER, IN_TO_LOWER, uniqueTypeStr, true ); method->useCallObj = false; method = initFunction( uniqueTypeStr, rootNamespace, globalObjectDef, ObjectMethod::Call, "toupper", IN_TO_UPPER, IN_TO_UPPER, uniqueTypeStr, true ); method->useCallObj = false; method = initFunction( uniqueTypeInt, rootNamespace, globalObjectDef, ObjectMethod::Call, "atoi", FN_STR_ATOI, FN_STR_ATOI, uniqueTypeStr, true, true ); method->useCallObj = false; method = initFunction( uniqueTypeInt, rootNamespace, globalObjectDef, ObjectMethod::Call, "atoo", FN_STR_ATOO, FN_STR_ATOO, uniqueTypeStr, true, true ); method->useCallObj = false; method = initFunction( uniqueTypeStr, rootNamespace, globalObjectDef, ObjectMethod::Call, "prefix", FN_PREFIX, FN_PREFIX, uniqueTypeStr, uniqueTypeInt, true, true ); method->useCallObj = false; method = initFunction( uniqueTypeStr, rootNamespace, globalObjectDef, ObjectMethod::Call, "suffix", FN_SUFFIX, FN_SUFFIX, uniqueTypeStr, uniqueTypeInt, true, true ); method->useCallObj = false; method = initFunction( uniqueTypeInt, rootNamespace, globalObjectDef, ObjectMethod::Call, "uord8", FN_STR_UORD8, FN_STR_UORD8, uniqueTypeStr, true, true ); method->useCallObj = false; method = initFunction( uniqueTypeInt, rootNamespace, globalObjectDef, ObjectMethod::Call, "sord8", FN_STR_SORD8, FN_STR_SORD8, uniqueTypeStr, true, true ); method->useCallObj = false; method = initFunction( uniqueTypeInt, rootNamespace, globalObjectDef, ObjectMethod::Call, "uord16", FN_STR_UORD16, FN_STR_UORD16, uniqueTypeStr, true, true ); method->useCallObj = false; method = initFunction( uniqueTypeInt, rootNamespace, globalObjectDef, ObjectMethod::Call, "sord16", FN_STR_SORD16, FN_STR_SORD16, uniqueTypeStr, true, true ); method->useCallObj = false; method = initFunction( uniqueTypeInt, rootNamespace, globalObjectDef, ObjectMethod::Call, "uord32", FN_STR_UORD32, FN_STR_UORD32, uniqueTypeStr, true, true ); method->useCallObj = false; method = initFunction( uniqueTypeInt, rootNamespace, globalObjectDef, ObjectMethod::Call, "sord32", FN_STR_SORD32, FN_STR_SORD32, uniqueTypeStr, true, true ); method->useCallObj = false; method = initFunction( uniqueTypeInt, rootNamespace, globalObjectDef, ObjectMethod::Call, "exit", FN_EXIT, FN_EXIT, uniqueTypeInt, true, true ); method = initFunction( uniqueTypeInt, rootNamespace, globalObjectDef, ObjectMethod::Call, "exit_hard", FN_EXIT_HARD, FN_EXIT_HARD, uniqueTypeInt, true, true ); method = initFunction( uniqueTypeInt, rootNamespace, globalObjectDef, ObjectMethod::Call, "system", IN_SYSTEM, IN_SYSTEM, uniqueTypeStr, true ); method = initFunction( uniqueTypeStr, rootNamespace, globalObjectDef, ObjectMethod::Call, "xml", IN_TREE_TO_STR_XML, IN_TREE_TO_STR_XML, uniqueTypeAny, true ); method->useCallObj = false; method = initFunction( uniqueTypeStr, rootNamespace, globalObjectDef, ObjectMethod::Call, "xmlac", IN_TREE_TO_STR_XML_AC, IN_TREE_TO_STR_XML_AC, uniqueTypeAny, true ); method->useCallObj = false; method = initFunction( uniqueTypeStr, rootNamespace, globalObjectDef, ObjectMethod::Call, "postfix", IN_TREE_TO_STR_POSTFIX, IN_TREE_TO_STR_POSTFIX, uniqueTypeAny, true ); method->useCallObj = false; addStdin(); addStdout(); addStderr(); addStds(); addArgv(); addError(); addDefineArgs(); } void Compiler::addStdin() { /* Make the type ref. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStream ); /* Create the field and insert it into the map. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "stdin" ); el->isConst = true; el->inGetR = IN_GET_CONST; el->inGetWC = IN_GET_CONST; el->inGetWV = IN_GET_CONST; el->inGetValR = IN_GET_CONST; el->inGetValWC = IN_GET_CONST; el->inGetValWV = IN_GET_CONST; el->isConstVal = true; el->constValId = CONST_STDIN; rootNamespace->rootScope->insertField( el->name, el ); } void Compiler::addStdout() { /* Make the type ref. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStream ); /* Create the field and insert it into the map. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "stdout" ); el->isConst = true; el->inGetR = IN_GET_CONST; el->inGetWC = IN_GET_CONST; el->inGetWV = IN_GET_CONST; el->inGetValR = IN_GET_CONST; el->inGetValWC = IN_GET_CONST; el->inGetValWV = IN_GET_CONST; el->isConstVal = true; el->constValId = CONST_STDOUT; rootNamespace->rootScope->insertField( el->name, el ); } void Compiler::addStderr() { /* Make the type ref. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStream ); /* Create the field and insert it into the map. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "stderr" ); el->isConst = true; el->inGetR = IN_GET_CONST; el->inGetWC = IN_GET_CONST; el->inGetWV = IN_GET_CONST; el->inGetValR = IN_GET_CONST; el->inGetValWC = IN_GET_CONST; el->inGetValWV = IN_GET_CONST; el->isConstVal = true; el->constValId = CONST_STDERR; rootNamespace->rootScope->insertField( el->name, el ); } void Compiler::addArgv() { /* Create the field and insert it into the map. */ ObjectField *el = ObjectField::cons( internal, ObjectField::StructFieldType, argvTypeRef, "argv" ); el->isConst = true; rootNamespace->rootScope->insertField( el->name, el ); argv = el; TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStr ); el = ObjectField::cons( internal, ObjectField::StructFieldType, typeRef, "arg0" ); el->isConst = true; rootNamespace->rootScope->insertField( el->name, el ); arg0 = el; } void Compiler::addStds() { ObjectField *el = ObjectField::cons( internal, ObjectField::StructFieldType, stdsTypeRef, "stds" ); rootNamespace->rootScope->insertField( el->name, el ); stds = el; } void Compiler::addError() { /* Make the type ref. */ TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStr ); /* Create the field and insert it into the map. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, "error" ); el->isConst = true; el->inGetR = IN_GET_ERROR; el->inGetWC = IN_GET_ERROR; el->inGetWV = IN_GET_ERROR; rootNamespace->rootScope->insertField( el->name, el ); } void Compiler::addDefineArgs() { for ( DefineVector::Iter d = defineArgs; d.lte(); d++ ) { TypeRef *typeRef = TypeRef::cons( internal, uniqueTypeStr ); /* Create the field and insert it into the map. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltFieldType, typeRef, d->name ); el->isConst = true; el->inGetR = IN_GET_CONST; el->inGetWC = IN_GET_CONST; el->inGetWV = IN_GET_CONST; el->inGetValR = IN_GET_CONST; el->inGetValWC = IN_GET_CONST; el->inGetValWV = IN_GET_CONST; el->isConstVal = true; el->constValId = CONST_ARG; el->constValArg = d->value; rootNamespace->rootScope->insertField( el->name, el ); } } void Compiler::initMapFunctions( GenericType *gen ) { /* Value functions. */ initFunction( gen->valueUt, gen->objDef, ObjectMethod::Call, "find", FN_VMAP_FIND, FN_VMAP_FIND, gen->keyUt, true, true, gen ); initFunction( uniqueTypeInt, gen->objDef, ObjectMethod::Call, "insert", FN_VMAP_INSERT_WV, FN_VMAP_INSERT_WC, gen->keyUt, gen->valueUt, false, true, gen ); initFunction( gen->elUt, gen->objDef, ObjectMethod::Call, "remove", FN_VMAP_REMOVE_WV, FN_VMAP_REMOVE_WC, gen->keyUt, false, true, gen ); /* * Element Functions */ initFunction( gen->elUt, gen->objDef, ObjectMethod::Call, "find_el", FN_MAP_FIND, FN_MAP_FIND, gen->keyUt, true, true, gen ); initFunction( uniqueTypeInt, gen->objDef, ObjectMethod::Call, "insert_el", FN_MAP_INSERT_WV, FN_MAP_INSERT_WC, gen->elUt, false, true, gen ); initFunction( gen->elUt, gen->objDef, ObjectMethod::Call, "detach_el", FN_MAP_DETACH_WV, FN_MAP_DETACH_WC, gen->elUt, false, true, gen ); } void Compiler::initMapField( GenericType *gen, const char *name, int offset ) { /* Make the type ref and create the field. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltOffType, gen->elTr, name ); el->inGetR = IN_GET_MAP_MEM_R; el->inGetWC = IN_GET_MAP_MEM_WC; el->inGetWV = IN_GET_MAP_MEM_WV; // el->inSetWC = IN_SET_MAP_MEM_WC; // el->inSetWV = IN_SET_MAP_MEM_WV; el->inGetValR = IN_GET_MAP_MEM_R; el->inGetValWC = IN_GET_MAP_MEM_WC; el->inGetValWV = IN_GET_MAP_MEM_WV; gen->objDef->rootScope->insertField( el->name, el ); el->useGenericId = true; el->generic = gen; /* Zero for head, One for tail. */ el->offset = offset; } void Compiler::initMapFields( GenericType *gen ) { addLengthField( gen->objDef, IN_MAP_LENGTH ); initMapField( gen, "head_el", 0 ); initMapField( gen, "tail_el", 1 ); initMapElKey( gen, "key", 0 ); initMapElField( gen, "prev", 0 ); initMapElField( gen, "next", 1 ); } void Compiler::initMapElKey( GenericType *gen, const char *name, int offset ) { /* Make the type ref and create the field. */ ObjectField *el = ObjectField::cons( internal, ObjectField::GenericDependentType, gen->keyTr, name ); gen->el->mapKeyField = el; /* Offset will be computed when the offset of the owning map element field * is computed. */ gen->elUt->structEl->structDef->objectDef->rootScope->insertField( el->name, el ); } void Compiler::initMapElField( GenericType *gen, const char *name, int offset ) { /* Make the type ref and create the field. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltOffType, gen->elTr, name ); el->inGetR = IN_GET_MAP_EL_MEM_R; el->inGetValR = IN_GET_MAP_EL_MEM_R; // el->inGetWC = IN_GET_LIST2EL_MEM_WC; // el->inGetWV = IN_GET_LIST2EL_MEM_WV; // el->inSetWC = IN_SET_LIST2EL_MEM_WC; // el->inSetWV = IN_SET_LIST2EL_MEM_WV; el->useGenericId = true; el->generic = gen; /* Zero for head, One for tail. */ el->offset = offset; gen->elUt->structEl->structDef->objectDef->rootScope->insertField( el->name, el ); } void Compiler::initListFunctions( GenericType *gen ) { initFunction( uniqueTypeInt, gen->objDef, ObjectMethod::Call, "push_head", FN_VLIST_PUSH_HEAD_WV, FN_VLIST_PUSH_HEAD_WC, gen->valueUt, false, true, gen ); initFunction( uniqueTypeInt, gen->objDef, ObjectMethod::Call, "push_tail", FN_VLIST_PUSH_TAIL_WV, FN_VLIST_PUSH_TAIL_WC, gen->valueUt, false, true, gen ); initFunction( uniqueTypeInt, gen->objDef, ObjectMethod::Call, "push", FN_VLIST_PUSH_HEAD_WV, FN_VLIST_PUSH_HEAD_WC, gen->valueUt, false, true, gen ); initFunction( gen->valueUt, gen->objDef, ObjectMethod::Call, "pop_head", FN_VLIST_POP_HEAD_WV, FN_VLIST_POP_HEAD_WC, false, true, gen ); initFunction( gen->valueUt, gen->objDef, ObjectMethod::Call, "pop_tail", FN_VLIST_POP_TAIL_WV, FN_VLIST_POP_TAIL_WC, false, true, gen ); initFunction( gen->valueUt, gen->objDef, ObjectMethod::Call, "pop", FN_VLIST_POP_HEAD_WV, FN_VLIST_POP_HEAD_WC, false, true, gen ); initFunction( uniqueTypeInt, gen->objDef, ObjectMethod::Call, "push_head_el", FN_LIST_PUSH_HEAD_WV, FN_LIST_PUSH_HEAD_WC, gen->elUt, false, true, gen ); initFunction( uniqueTypeInt, gen->objDef, ObjectMethod::Call, "push_tail_el", FN_LIST_PUSH_TAIL_WV, FN_LIST_PUSH_TAIL_WC, gen->elUt, false, true, gen ); initFunction( uniqueTypeInt, gen->objDef, ObjectMethod::Call, "push_el", FN_LIST_PUSH_HEAD_WV, FN_LIST_PUSH_HEAD_WC, gen->elUt, false, true, gen ); initFunction( gen->elUt, gen->objDef, ObjectMethod::Call, "pop_head_el", FN_LIST_POP_HEAD_WV, FN_LIST_POP_HEAD_WC, false, true, gen ); initFunction( gen->elUt, gen->objDef, ObjectMethod::Call, "pop_tail_el", FN_LIST_POP_TAIL_WV, FN_LIST_POP_TAIL_WC, false, true, gen ); initFunction( gen->elUt, gen->objDef, ObjectMethod::Call, "pop_el", FN_LIST_POP_HEAD_WV, FN_LIST_POP_HEAD_WC, false, true, gen ); } void Compiler::initListElField( GenericType *gen, const char *name, int offset ) { /* Make the type ref and create the field. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltOffType, gen->elTr, name ); el->inGetR = IN_GET_LIST_EL_MEM_R; el->inGetValR = IN_GET_LIST_EL_MEM_R; // el->inGetWC = IN_GET_LIST2EL_MEM_WC; // el->inGetWV = IN_GET_LIST2EL_MEM_WV; // el->inSetWC = IN_SET_LIST2EL_MEM_WC; // el->inSetWV = IN_SET_LIST2EL_MEM_WV; el->useGenericId = true; el->generic = gen; /* Zero for head, One for tail. */ el->offset = offset; gen->elUt->structEl->structDef->objectDef->rootScope->insertField( el->name, el ); } void Compiler::initListFieldEl( GenericType *gen, const char *name, int offset ) { /* Make the type ref and create the field. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltOffType, gen->elTr, name ); el->inGetR = IN_GET_LIST_MEM_R; el->inGetWC = IN_GET_LIST_MEM_WC; el->inGetWV = IN_GET_LIST_MEM_WV; // el->inSetWC = IN_SET_LIST_MEM_WC; // el->inSetWV = IN_SET_LIST_MEM_WV; el->inGetValR = IN_GET_LIST_MEM_R; el->inGetValWC = IN_GET_LIST_MEM_WC; el->inGetValWV = IN_GET_LIST_MEM_WV; gen->objDef->rootScope->insertField( el->name, el ); el->useGenericId = true; el->generic = gen; /* Zero for head, One for tail. */ el->offset = offset; } void Compiler::initListFieldVal( GenericType *gen, const char *name, int offset ) { /* Make the type ref and create the field. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltOffType, gen->valueTr, name ); el->inGetR = IN_GET_VLIST_MEM_R; el->inGetWC = IN_GET_VLIST_MEM_WC; el->inGetWV = IN_GET_VLIST_MEM_WV; // el->inSetWC = IN_SET_VLIST_MEM_WC; // el->inSetWV = IN_SET_VLIST_MEM_WV; el->inGetValR = IN_GET_VLIST_MEM_R; el->inGetValWC = IN_GET_VLIST_MEM_WC; el->inGetValWV = IN_GET_VLIST_MEM_WV; gen->objDef->rootScope->insertField( el->name, el ); el->useGenericId = true; el->generic = gen; /* Zero for head, One for tail. */ el->offset = offset; } void Compiler::initListFields( GenericType *gen ) { /* The value fields. */ initListFieldVal( gen, "head", 0 ); initListFieldVal( gen, "tail", 1 ); initListFieldVal( gen, "top", 0 ); /* The element fields. */ initListFieldEl( gen, "head_el", 0 ); initListFieldEl( gen, "tail_el", 1 ); initListFieldEl( gen, "top_el", 0 ); addLengthField( gen->objDef, IN_LIST_LENGTH ); /* The fields of the list element. */ initListElField( gen, "prev", 0 ); initListElField( gen, "next", 1 ); } void Compiler::initParserFunctions( GenericType *gen ) { initFunction( gen->elUt, gen->objDef, ObjectMethod::ParseFinish, "finish", IN_PARSE_FRAG_W, IN_PARSE_FRAG_W, true ); initFunction( gen->elUt, gen->objDef, ObjectMethod::ParseFinish, "eof", IN_PARSE_FRAG_W, IN_PARSE_FRAG_W, true ); initFunction( uniqueTypeInput, gen->objDef, ObjectMethod::Call, "gets", IN_GET_PARSER_STREAM, IN_GET_PARSER_STREAM, true ); } void Compiler::initParserField( GenericType *gen, const char *name, int offset, TypeRef *typeRef ) { /* Make the type ref and create the field. */ ObjectField *el = ObjectField::cons( internal, ObjectField::InbuiltOffType, typeRef, name ); el->inGetR = IN_GET_PARSER_MEM_R; // el->inGetWC = IN_GET_PARSER_MEM_WC; // el->inGetWV = IN_GET_PARSER_MEM_WV; // el->inSetWC = IN_SET_PARSER_MEM_WC; // el->inSetWV = IN_SET_PARSER_MEM_WV; gen->objDef->rootScope->insertField( el->name, el ); /* Zero for head, One for tail. */ el->offset = offset; } void Compiler::initParserFields( GenericType *gen ) { TypeRef *typeRef; typeRef = TypeRef::cons( internal, gen->elUt ); initParserField( gen, "tree", 0, typeRef ); typeRef = TypeRef::cons( internal, uniqueTypeStr ); initParserField( gen, "error", 1, typeRef ); } void Compiler::makeFuncVisible( Function *func, bool isUserIter ) { func->localFrame = func->codeBlock->localFrame; /* Set up the parameters. */ for ( ParameterList::Iter param = *func->paramList; param.lte(); param++ ) { if ( func->localFrame->rootScope->findField( param->name ) != 0 ) error(param->loc) << "parameter " << param->name << " redeclared" << endp; func->localFrame->rootScope->insertField( param->name, param ); } /* Insert the function into the global function map. */ ObjectMethod *objMethod = new ObjectMethod( func->typeRef, func->name, IN_CALL_WV, IN_CALL_WC, func->paramList->length(), 0, func->paramList, false ); objMethod->funcId = func->funcId; objMethod->useFuncId = true; objMethod->useCallObj = false; objMethod->func = func; if ( isUserIter ) { IterDef *uiter = findIterDef( IterDef::User, func ); objMethod->iterDef = uiter; } NameScope *scope = func->nspace->rootScope; // : globalObjectDef->rootScope; if ( !scope->methodMap.insert( func->name, objMethod ) ) error(func->typeRef->loc) << "function " << func->name << " redeclared" << endp; func->objMethod = objMethod; } void Compiler::makeInHostVisible( Function *func ) { /* Set up the parameters. */ for ( ParameterList::Iter param = *func->paramList; param.lte(); param++ ) { if ( func->localFrame->rootScope->findField( param->name ) != 0 ) error(param->loc) << "parameter " << param->name << " redeclared" << endp; func->localFrame->rootScope->insertField( param->name, param ); } /* Insert the function into the global function map. */ ObjectMethod *objMethod = new ObjectMethod( func->typeRef, func->name, IN_HOST, IN_HOST, func->paramList->length(), 0, func->paramList, false ); objMethod->funcId = func->funcId; objMethod->useFuncId = true; objMethod->useCallObj = false; objMethod->func = func; NameScope *scope = func->nspace->rootScope; if ( !scope->methodMap.insert( func->name, objMethod ) ) { error(func->typeRef->loc) << "in-host function " << func->name << " redeclared" << endp; } func->objMethod = objMethod; } /* * Type Declaration Root. */ void Compiler::declarePass() { declareReVars(); makeDefaultIterators(); for ( FunctionList::Iter f = functionList; f.lte(); f++ ) makeFuncVisible( f, f->isUserIter ); for ( FunctionList::Iter f = inHostList; f.lte(); f++ ) makeInHostVisible( f ); rootNamespace->declare( this ); /* Will fill in zero lels that were not declared. */ makeIgnoreCollectors(); declareByteCode(); declareIntFields(); declareStrFields(); declareInputFields(); declareStreamFields(); declareTokenFields(); declareGlobalFields(); /* Fill any empty scanners with a default token. */ initEmptyScanners(); }