Node ReadStateClass::readImport() { NodeFactory imp; imp.start( "import" ); bool pervasive, qualified; readImportQualifiers( *this, pervasive, qualified ); imp.put( "pervasive", pervasive ? "true" : "false" ); imp.put( "qualified", qualified ? "true" : "false" ); readImportMatch( *this, imp ); this->checkToken( tokty_from ); string url = this->readPkgName(); imp.put( "from", url ); if ( this->tryName( "alias" ) ) { imp.put( "alias", this->readIdName() ); } if ( this->tryName( "into" ) ) { readImportInto( *this, imp ); } imp.end(); return imp.build(); }
Node canonise( const int level, Node fn ) { const bool is_var = fn->hasName( VAR ); if ( is_var ) { if ( level == 0 ) { if ( this->name_needed ) this->badHeader(); return this->anon( fn ); } else if ( this->assume_no_name ) { return this->anon( fn ); } else { return fn; } } else if ( fn->hasName( SEQ ) && not this->name_needed ) { return this->anon( fn ); } else if ( fn->hasName( APP ) && fn->size() == 2 ) { NodeFactory b; b.start( APP ); Node n = this->canonise( level + 1, fn->getChild( 0 ) ); b.add( n ); b.start( SEQ ); squash( b, fn->getChild( 1 ) ); b.end(); b.end(); return b.build(); } else { throw this->badHeader(); } }
Node ReadStateClass::readQueryPrec( const int prec ) { Node e = this->readExprPrec( prec ); const std::string name = e->name(); if ( name == BIND || name == IN || name == FROM || name == WHERE || name == WHILE || name == ZIP || name == CROSS || name == OK || name == FINALLY || name == DO ) { return e; } else { NodeFactory where; where.start( WHERE ); where.start( OK ); where.end(); where.add( e ); where.end(); return where.build(); } }
static Node makeSymbol( const std::string & name ) { NodeFactory sym; sym.start( "constant" ); sym.put( "type", "symbol" ); sym.put( "value", name ); sym.end(); return sym.build(); }
Node ReadStateClass::readId( const std::string name ) { SysConst * sysc = lookupSysConst( name ); if ( sysc != NULL ) { NodeFactory constant; constant.start( "constant" ); constant.put( "type", sysc->tag ); constant.put( "value", sysc->value ); constant.end(); return constant.build(); } else { NodeFactory id; id.start( this->pattern_mode ? "var" : "id" ); id.put( "name", name ); id.end(); return id.build(); } }
Node getArgs() const { Node args = this->lhs->getChild( 1 ); if ( args->hasName( SEQ ) ) return args; NodeFactory b; b.start( SEQ ); b.add( args ); b.end(); return b.build(); }
Node ReadStateClass::readMap( TokType closer ) { NodeFactory list; list.start( SYSAPP ); list.put( SYSAPP_NAME, "newMap" ); Node x = this->readStmntsCheck( closer ); list.add( x ); list.end(); return list.build(); }
static Node makeApp( Node lhs, Node rhs ) { if ( lhs->name() == GNX_SYSFN ) { NodeFactory sysapp; sysapp.start( SYSAPP ); std::string name = lhs->attribute( GNX_SYSFN_VALUE ); sysapp.put( SYSAPP_NAME, name ); sysapp.add( rhs ); sysapp.end(); return sysapp.build(); } else { NodeFactory app; app.start( APP ); app.add( lhs ); app.add( rhs ); app.end(); return app.build(); } }
static Node makeIndex( Node lhs, Node rhs ) { NodeFactory index; index.start( SYSAPP ); index.put( SYSAPP_NAME, "index" ); index.add( rhs ); index.add( lhs ); index.end(); return index.build(); }
Node ReadStateClass::readReturn() { NodeFactory ret; ret.start( ASSERT ); ret.put( ASSERT_TAILCALL, "true" ); Node n = this->readExpr(); ret.add( n ); ret.end(); return ret.build(); }
Node anon( Node fn ) { NodeFactory b; b.start( APP ); b.start( VAR ); // But no name - anonymous. b.end(); b.start( SEQ ); squash( b, fn ); b.end(); b.end(); return b.build(); }
Node ReadStateClass::readPackage() { NodeFactory pkg; pkg.start( "package" ); string url = this->readPkgName(); pkg.put( "url", url ); this->checkToken( tokty_semi ); Node body = this->readStmntsCheck( tokty_endpackage ); pkg.add( body ); pkg.end(); return pkg.build(); }
Node ReadStateClass::readIf( TokType sense, TokType closer ) { if ( this->cstyle_mode ) this->checkToken( tokty_oparen ); Node pred = this->readExpr(); this->checkToken( this->cstyle_mode ? tokty_cparen : tokty_then ); Node then_part = this->readStmnts(); if ( this->tryToken( tokty_else ) ) { NodeFactory ifunless; ifunless.start( IF ); predicate( sense, ifunless, pred ); ifunless.add( then_part ); Node x = this->readStmnts(); if ( not this->cstyle_mode ) this->checkToken( closer ); ifunless.add( x ); ifunless.end(); return ifunless.build(); } else if ( this->cstyle_mode || this->tryToken( closer ) ) { NodeFactory ifunless; ifunless.start( IF ); predicate( sense, ifunless, pred ); ifunless.add( then_part ); ifunless.end(); return ifunless.build(); } else { TokType new_sense; if ( this->tryToken( tokty_elseif ) ) { new_sense = tokty_if; } else { this->checkToken( tokty_elseunless ); new_sense = tokty_unless; } NodeFactory ifunless; ifunless.start( IF ); predicate( sense, ifunless, pred ); ifunless.add( then_part ); Node x = this->readIf( new_sense, closer ); ifunless.add( x ); ifunless.end(); return ifunless.build(); } }
Node ReadStateClass::readEnvVar() { this->checkToken( tokty_obrace ); NodeFactory envvar; envvar.start( SYSAPP ); envvar.put( "name", "sysGetEnv" ); envvar.start( "constant" ); envvar.put( "type", "string" ); envvar.put( "value", this->item_factory->read()->nameString() ); envvar.end(); this->checkToken( tokty_cbrace ); envvar.end(); return envvar.build(); }
Node ReadStateClass::readListOrVector( bool vector_vs_list, TokType closer ) { NodeFactory list; list.start( vector_vs_list ? VECTOR : LIST ); Node stmnts = this->readCompoundCore(); if ( not vector_vs_list && this->tryToken( tokty_bar ) ) { list.add( stmnts ); list.end(); Node L = list.build(); NodeFactory append; append.start( LIST_APPEND ); append.add( L ); Node x = this->readCompoundCoreCheck( closer ); append.add( x ); append.end(); return append.build(); } else { this->checkToken( closer ); list.add( stmnts ); list.end(); return list.build(); } }
Node ReadStateClass::readAnon( const std::string name ) { NodeFactory anon; if ( this->pattern_mode ) { anon.start( VAR ); } else { anon.start( CONSTANT ); anon.put( CONSTANT_TYPE, "absent" ); anon.put( CONSTANT_VALUE, "absent" ); anon.put( CONSTANT_WAS_ANON, name ); } anon.put( COMMENT, name ); anon.end(); return anon.build(); }
Node ReadStateClass::readCompoundCore() { if ( this->cstyle_mode ) { NodeFactory stmnts; stmnts.start( SEQ ); while ( this->tryPeekToken( tokty_semi ) || not this->tryPeekCloser() ) { Node n = this->readSingleStmnt(); stmnts.add( n ); } stmnts.end(); return stmnts.build(); } else { return this->readStmnts(); } }
Node ReadStateClass::readVarVal( TokType fnc ) { NodeFactory bind; bind.start( BIND ); Node lhs = this->readExprPrec( prec_assign ); updateAsPattern( lhs, fnc == tokty_val ); bind.add( lhs ); this->checkToken( this->cstyle_mode ? tokty_equal : tokty_bind ); Node x = this->readExpr(); bind.add( x ); bind.end(); return bind.build(); }
Node ReadStateClass::readDHat() { NodeFactory maplet; maplet.start( SYSAPP ); maplet.put( "name", "newMaplet" ); const string name( this->readIdName() ); maplet.start( "constant" ); maplet.put( "type", "symbol" ); maplet.put( "value", name ); maplet.end(); maplet.start( "id" ); maplet.put( "name", name ); maplet.end(); maplet.end(); return maplet.build(); }
Node ReadStateClass::readSingleStmnt( const bool top_level ) { if ( this->cstyle_mode ) { Item it = this->item_factory->read(); //cerr << "SINGLE " << tok_type_name( it->tok_type ) << endl; switch ( it->tok_type ) { case tokty_obrace: return this->readCompoundCoreCheck( tokty_cbrace ); case tokty_function: if ( this->cstyle_mode && this->item_factory->peek()->tok_type == tokty_oparen ) { return this->readLambda(); } else { return this->readDefinition(); } case tokty_if: return this->readIf( tokty_if, tokty_endif ); case tokty_for: return this->readFor(); case tokty_switch: return this->readSwitch(); case tokty_recordclass: return this->readRecordClass(); case tokty_dsemi: case tokty_semi: return makeEmpty(); default: this->item_factory->unread(); // --- Fall-through --- // } } // Fall thru! Node n = this->readOptEmptyExpr(); if ( this->tryToken( tokty_dsemi ) ) { NodeFactory f; f.start( ERASE ); f.add( n ); f.end(); return f.build(); } else if ( this->tryToken( tokty_semi ) ) { return n; } else { if ( this->item_factory->peek()->role.IsCloser() && not top_level ) { return n; } else { throw CompileTimeError( "Missing semi-colon?" ).culprit( "Token", this->item_factory->peek()->nameString() ); } } }
Node ReadStateClass::readSwitchStmnts() { NodeFactory st; st.start( SEQ ); while ( not ( this->tryPeekToken( tokty_cbrace ) || this->tryPeekToken( tokty_case ) || this->tryPeekToken( tokty_default ) ) ) { Node x = this->readSingleStmnt(); st.add( x ); } st.end(); return st.build(); }
static Node makeCharSequence( Item item ) { int n = item->nameString().size(); if ( n == 0 ) { return makeEmpty(); } else { NodeFactory charseq; charseq.start( SEQ ); const std::string & s = item->nameString(); std::string::const_iterator iter = s.begin(); for ( iter = s.begin(); iter != s.end(); ++iter ) { charseq.start( CONSTANT ); charseq.put( CONSTANT_TYPE, "char" ); charseq.put( CONSTANT_VALUE, std::string() + *iter ); // WRONG charseq.end(); } charseq.end(); return charseq.build(); } }
Node ReadStateClass::readLambda() { #ifdef DBG_COMMON2GNX cerr << "LAMBDA" << endl; #endif Node ap = this->readCanonicalLambdaLHS( false ); #ifdef DBG_COMMON2GNX cerr << "Now check =>> is next token" << endl; #endif if ( not this->cstyle_mode ) this->checkToken( tokty_fnarrow ); Node body = this->readCompoundStmnts(); if ( not this->cstyle_mode ) this->checkToken( tokty_endfn ); Uncurry components( ap, body ); components.uncurry(); Node fun = components.getFun(); NodeFactory fn; fn.start( FN ); if ( fun && fun->hasAttribute( "name" ) ) { fn.put( FN_NAME, fun->attribute( "name" ) ); } { Node a = components.getArgs(); fn.add( a ); Node b = components.getBody(); fn.add( b ); } fn.end(); Node lambda = fn.build(); #ifdef DBG_COMMON2GNX cerr << "Built lambda: "; lambda->render( cerr ); cerr << endl; #endif return lambda; }
Node ReadStateClass::readTry( const bool try_vs_transaction ) { NodeFactory ftry; ftry.start( try_vs_transaction ? "try" : "transaction" ); Node app = this->readExpr(); ftry.add( app ); while ( this->tryToken( tokty_catch ) ) { if ( this->tryPeekToken( tokty_oparen ) ) { ftry.start( "catch.return" ); } else { ftry.start( "catch.then" ); ftry.put( "event", this->readIdName() ); } ReadStateClass pattern( *this ); pattern.setPatternMode(); Node catch_patt = pattern.readExpr(); ftry.add( catch_patt ); this->checkToken( tokty_then ); Node e = this->readExpr(); ftry.add( e ); ftry.end(); } if ( this->tryToken( tokty_else ) ) { ftry.start( "catch.else" ); Node else_stmnts = this->readStmnts(); ftry.add( else_stmnts ); ftry.end(); } this->checkToken( try_vs_transaction? tokty_endtry : tokty_endtransaction ); ftry.end(); return ftry.build(); }
Node ReadStateClass::readThrow() { NodeFactory panic; panic.start( "throw" ); panic.put( "event", this->readIdName() ); panic.put( "level", this->tryToken( tokty_bang ) ? "rollback" : this->tryToken( tokty_dbang ) ? "failover" : this->tryToken( tokty_panic ) ? "panic" : "escape" ); if ( this->tryPeekToken( tokty_oparen ) ) { Node e = this->readExpr(); panic.add( e ); } else { panic.start( SEQ ); panic.end(); } panic.end(); return panic.build(); }
void uncurry() { #ifdef DBG_COMMON2GNX cerr << "At start of uncurrying" << endl; cerr << " LHS: "; this->lhs->render( cerr ); cerr << endl; cerr << " RHS: "; this->rhs->render( cerr ); cerr << endl; #endif while ( this->isCurryd() ) { NodeFactory b; b.start( FN ); Node arg = this->lhs->getChild( 1 ); if ( arg->hasName( SEQ ) ) { b.add( arg ); } else { b.start( SEQ ); b.add( arg ); b.end(); } b.add( this->rhs ); b.end(); this->rhs = b.build(); this->lhs = this->lhs->getChild( 0 ); #ifdef DBG_COMMON2GNX cerr << "Uncurried" << endl; cerr << " LHS: "; this->lhs->render( cerr ); cerr << endl; cerr << " RHS: "; this->rhs->render( cerr ); cerr << endl; #endif } }
Node ReadStateClass::readDefinition() { //cerr << "DEFINITION" << endl; Node ap = this->readCanonicalLambdaLHS( true ); if ( not this->cstyle_mode ) this->checkToken( tokty_fnarrow ); Node body0 = this->readCompoundStmnts(); if ( not this->cstyle_mode ) this->checkToken( tokty_enddefine ); if ( this->cstyle_mode ) { this->is_postfix_allowed = false; } Uncurry components( ap, body0 ); components.uncurry(); Node fn = components.getFun(); if ( not fn->hasAttribute( "name" ) ) { throw Ginger::Mishap( "Cannot determine function name" ); } Node args = components.getArgs(); Node body = components.getBody(); const std::string name( fn->attribute( GNX_VID_NAME ) ); NodeFactory def; def.start( BIND ); def.start( VAR ); def.put( GNX_VID_NAME, name ); def.put( GNX_VID_PROTECTED, "true" ); def.end(); def.start( FN ); def.put( FN_NAME, name ); def.add( args ); def.add( body ); def.end(); def.end(); return def.build(); }
Node ReadStateClass::readOptExprPrec( int prec ) { ItemFactory ifact = this->item_factory; Node e = this->prefixProcessing(); if ( not e ) return Node(); //cerr << "starting postfix checking ... " << this->isPostfixAllowed() << endl; while ( this->isPostfixAllowed() ) { int q; //cerr << "peeking" << endl; Item it = ifact->peek(); if ( it->item_is_signed_num() ) { NodeFactory t; t.start( SYSAPP ); t.put( "name", "+" ); t.add( e ); if ( it->tok_type == tokty_int ) { t.start( "constant" ); t.put( "type", "int" ); t.put( "value", it->nameString() ); t.end(); } else { throw CompileTimeError( "Only integers supported so far" ).culprit( "Item", it->nameString() ); } t.end(); e = t.build(); ifact->drop(); } else if ( it->item_is_postfix() ) { q = it->precedence; if ( q >= prec ) break; ifact->drop(); e = this->postfixProcessing( e, it, q ); } else { break; } } return e; }
static Node makeConstant( const char * type, const long value ) { NodeFactory simple; pushConstant( simple, type, value ); return simple.build(); }
Node ReadStateClass::postfixProcessing( Node lhs, Item item, int prec ) { Role role = item->role; TokType fnc = item->tok_type; if ( role.IsBinary() ) { const bool direction = tok_type_as_direction( fnc ); if ( role.IsSys() ) { NodeFactory a; a.start( SYSAPP ); a.put( SYSAPP_NAME, tok_type_as_sysapp( fnc ) ); Node rhs = this->readExprPrec( prec ); a.add( direction ? lhs : rhs ); a.add( !direction ? lhs : rhs ); a.end(); return a.build(); } else if ( role.IsForm() ) { NodeFactory a; a.start( tok_type_as_tag( fnc ) ); Node rhs = this->readExprPrec( prec ); a.add( direction ? lhs : rhs ); a.add( !direction ? lhs : rhs ); a.end(); return a.build(); } else { throw CompileTimeError( "Internal error - postfixProcessing" ); } } else if ( role.IsUnary() ) { if ( role.IsSys() ) { NodeFactory a; a.start( SYSAPP ); a.put( SYSAPP_NAME, tok_type_as_sysapp( fnc ) ); a.add( lhs ); a.end(); return a.build(); } else if ( role.IsForm() ) { NodeFactory a; a.start( tok_type_as_tag( fnc ) ); Node rhs = this->readExprPrec( prec ); a.add( lhs ); a.end(); return a.build(); } else { throw CompileTimeError( "Internal error (postfixProcessing): None of these cases defined yet" ); } } else { switch ( fnc ) { case tokty_bindrev: case tokty_bind: { Node rhs = this->readExprPrec( prec ); updateAsPattern( fnc == tokty_bind ? lhs : rhs, true ); NodeFactory bind; bind.start( BIND ); bind.add( fnc == tokty_bind ? lhs : rhs ); bind.add( fnc != tokty_bind ? lhs : rhs ); bind.end(); return bind.build(); } case tokty_cross: case tokty_zip: { NodeFactory factory; factory.start( fnc == tokty_cross ? CROSS : ZIP ); factory.add( lhs ); Node rhs = this->readQueryPrec( prec ); factory.add( rhs ); factory.end(); return factory.build(); } case tokty_finally: { NodeFactory finally; finally.start( FINALLY ); finally.add( lhs ); Node rhs = this->readExprPrec( prec ); finally.add( rhs ); finally.end(); return finally.build(); } case tokty_until: case tokty_while: { NodeFactory whileuntil; whileuntil.start( WHILE ); whileuntil.add( lhs ); Node rhs = this->readExprPrec( prec ); if ( fnc == tokty_until ) { whileuntil.start( SYSAPP ); whileuntil.put( SYSAPP_NAME, "not" ); } whileuntil.add( rhs ); if ( fnc == tokty_until ) { whileuntil.end(); } if ( this->tryToken( tokty_then ) ) { Node then = this->readExprPrec( prec_then ); whileuntil.add( then ); } else { whileuntil.start( SEQ ); whileuntil.end(); } whileuntil.end(); return whileuntil.build(); } case tokty_where: { NodeFactory where; where.start( WHERE ); where.add( lhs ); Node rhs = this->readExprPrec( prec ); where.add( rhs ); where.end(); return where.build(); } case tokty_do: { NodeFactory node; node.start( DO ); node.add( lhs ); Node do_stmnts = this->readCompoundStmnts(); if ( not this->tryToken( tokty_enddo ) ) { this->checkPeekCloser(); } node.add( do_stmnts ); node.end(); return node.build(); } case tokty_from: { updateAsPattern( lhs, true ); NodeFactory node; node.start( FROM ); Node from_expr = this->readExprPrec( prec ); node.add( lhs ); node.add( from_expr ); const bool has_by_part = this->tryToken( tokty_by ); if ( has_by_part ) { Node by_expr = this->readExprPrec( prec ); node.add( by_expr ); } const bool has_to_part = this->tryToken( tokty_to ); if ( has_to_part && not has_by_part ) { // We should insert a default. // TODO: refactor (extract) adding a constant int. pushConstant( node, "int", "1" ); } if ( has_to_part ) { Node to_expr = this->readExprPrec( prec ); node.add( to_expr ); } node.end(); return node.build(); } case tokty_in: { updateAsPattern( lhs, true ); Node in_expr = this->readExprPrec( prec ); NodeFactory node; node.start( IN ); node.add( lhs ); node.add( in_expr ); node.end(); return node.build(); } case tokty_dsemi: case tokty_semi: { Node rhs = this->readOptExprPrec( prec ); bool hasnt_rhs = not( rhs ); if ( fnc == tokty_semi && hasnt_rhs ) { return lhs; } else { NodeFactory s; s.start( fnc == tokty_semi ? SEQ : ERASE ); s.add( lhs ); if ( not hasnt_rhs ) s.add( rhs ); s.end(); return s.build(); } } case tokty_obracket: { // Indexing operator. Node rhs = this->readStmntsCheck( tokty_cbracket ); return makeIndex( lhs, rhs ); } case tokty_oparen: { Node rhs = this->readOptEmptyExprCheck( tokty_cparen ); return makeApp( lhs, rhs ); } case tokty_at: case tokty_dot: { Node func = this->readExprPrec( prec_tight ); Node rhs = this->readOptExprPrec( prec ); NodeFactory seq; seq.start( SEQ ); seq.add( lhs ); if ( not not rhs ) { seq.add( rhs ); } seq.end(); return makeApp( func, seq.build() ); } case tokty_double: { NodeFactory add; // TODO: Bug?? add.start( "add" ); add.add( lhs ); pushConstant( add, "double", item->nameString() ); add.end(); Node t = add.build(); //cerr << "DEBUG arity " << term_arity( t ) << endl; return t; } case tokty_int: { NodeFactory add; // TODO: Bug?? add.start( "add" ); add.add( lhs ); pushConstant( add, "int", item->nameString() ); add.end(); Node t = add.build(); //cerr << "DEBUG arity " << term_arity( t ) << endl; return t; } /* case tokty_explode: { NodeFactory expl; expl.start( SYSAPP ); expl.put( SYSAPP_NAME, "explode" ); expl.add( lhs ); expl.end(); Node t = expl.build(); return t; } */ default: { throw CompileTimeError( "This keyword not handled" ).culprit( "Keyword", item->nameString() ); } } } throw; // Unreachable. }