static void predicate( TokType sense, NodeFactory & ifunless, Node pred ) { if ( sense == tokty_if ) { ifunless.add( pred ); } else { // TODO: This is a bug? ifunless.start( "sysval" ); ifunless.put( "name", "not" ); ifunless.add( pred ); ifunless.end(); } }
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 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 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(); } }
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(); }
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::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(); }
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::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(); }
void squash( NodeFactory acc, Node rhs ) { const std::string name = rhs->name(); if ( name == SEQ ) { int n = rhs->size(); for ( int i = 0; i < n; i++ ) { squash( acc, rhs->getChild( i ) ); } } else { acc.add( rhs ); } }
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::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::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::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::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(); } }
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::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(); }
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(); }
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; }
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::readElement() { NodeFactory element; element.start( SEQ ); for (;;) { element.start( SYSAPP ); element.put( SYSAPP_NAME, "newElement" ); element.start( SYSAPP ); element.put( SYSAPP_NAME, "newAttrMap" ); // Cache the element name for the close tag. Anything other than // a literal name will need the close-anything tag. std::string element_name; Item item = this->item_factory->peek(); if ( item->tok_type == tokty_id ) { element_name = item->nameString(); } Node name = this->readAtomicExpr(); element.add( name ); bool closed = false; for (;;) { if ( this->tryToken( tokty_gt ) ) break; if ( this->tryToken( tokty_slashgt ) ) { closed = true; break; } Node key_or_keyvalue = this->readAtomicExpr( false ); if ( this->tryToken( tokty_equal ) ) { Node a1 = makeAssert1( key_or_keyvalue ); element.add( a1 ); Node value = this->readAtomicExpr(); element.add( value ); } else { element.start( SYSAPP ); element.put( SYSAPP_NAME, "explodeMapsAndMaplets" ); element.add( key_or_keyvalue ); element.end(); } } element.end(); // newAttrMap. if ( not closed ) { // Read the children. bool ended = false; for (;;) { if ( this->tryToken( tokty_ltslash ) ) break; if ( this->tryToken( tokty_endelement ) ) { ended = true; break; } Node child = this->readExpr(); element.add( child ); } if ( not ended ) { const string ename( this->readIdName() ); if ( ename != element_name ) { throw CompileTimeError( "Element close tag does not match open tag" ).culprit( "Open tag", element_name ).culprit( "Close tag", ename ); } this->checkToken( tokty_gt ); } } element.end(); // newElement. // Uniquely, at this point in the language, no semi-colon is // needed if the next item is ANOTHER element. if ( not this->tryToken( tokty_lt ) ) break; } element.end(); Node answer = element.build(); return answer->size() == 1 ? answer->getChild( 0 ) : answer; }
Node ReadStateClass::readSwitch() { NodeFactory sw; sw.start( SWITCH ); bool else_seen = false; Node swelse; if ( this->cstyle_mode ) { this->checkToken( tokty_oparen ); Node swvalue = this->readExprCheck( tokty_cparen ); sw.add( swvalue ); this->checkToken( tokty_obrace ); for (;;) { if ( this->tryToken( tokty_case ) ) { Node e = this->readExpr(); sw.add( e ); this->checkToken( tokty_colon ); Node b = this->readSwitchStmnts(); sw.add( b ); } else if ( this->tryToken( tokty_default ) ) { if ( else_seen ) { throw CompileTimeError( "Switch with two default parts" ); } else_seen = true; this->checkToken( tokty_colon ); swelse = this->readSwitchStmnts(); } else { break; } } this->checkToken( tokty_cbrace ); } else { Node swvalue = this->readExpr(); sw.add( swvalue ); for (;;) { if ( this->tryToken( tokty_case ) ) { Node e = this->readExprCheck( tokty_then ); sw.add( e ); Node b = this->readStmnts(); sw.add( b ); } else if ( this->tryToken( tokty_else ) ) { if ( else_seen ) { throw CompileTimeError( "Switch with two else parts" ); } else_seen = true; swelse = this->readOptExpr(); } else { break; } } this->checkToken( tokty_endswitch ); } if ( else_seen ) { sw.add( swelse ); } sw.end(); return sw.build(); }
Node ReadStateClass::prefixProcessingCore() { ItemFactory ifact = this->item_factory; Item item = ifact->read(); #ifdef DBG_COMMON2GNX cerr << "First item was " << tok_type_name( item->tok_type ) << endl; #endif TokType fnc = item->tok_type; Role role = item->role; //cout << "PREFIX PROCESSING: " << item->nameString() << endl; //cout << " tokty = " << tok_type_name( fnc ) << endl; if ( role.IsLiteral() ) { NodeFactory simple; simple.start( "constant" ); simple.put( "type", tok_type_as_type( fnc ) ); simple.put( "value", item->nameString() ); simple.end(); return simple.build(); } else if ( role.IsUnary() ) { if ( role.IsForm() ) { NodeFactory unary; unary.start( tok_type_as_tag( fnc ) ); Node x = this->readExprPrec( item->precedence ); unary.add( x ); unary.end(); return unary.build(); } else if ( role.IsSys() ) { NodeFactory sf; sf.start( SYSAPP ); sf.put( SYSAPP_NAME, tok_type_as_sysapp( fnc ) ); Node x = this->readExprPrec( item->precedence ); sf.add( x ); sf.end(); return sf.build(); } else { throw CompileTimeError( "Internal error - unreachable code reached" ); } } switch ( fnc ) { case tokty_sub: { Node e = this->readExprPrec( prec_negate ); NodeFactory neg; neg.start( SYSAPP ); neg.put( SYSAPP_NAME, "negate" ); neg.add( e ); neg.end(); return neg.build(); } case tokty_add: { Node e = this->readExprPrec( prec_negate ); NodeFactory pos; pos.start( SYSAPP ); pos.put( SYSAPP_NAME, "positivate" ); pos.add( e ); pos.end(); return pos.build(); } case tokty_id: return this->readId( item->nameString() ); case tokty_anon: return this->readAnon( item->nameString() ); // changed for ${VAR} case study case tokty_envvar: return this->readEnvVar(); case tokty_return: return this->readReturn(); case tokty_throw: return this->readThrow(); case tokty_try: case tokty_transaction: return this->readTry( fnc == tokty_try ); case tokty_charseq: return makeCharSequence( item ); case tokty_val: case tokty_var : return this->readVarVal( fnc ); case tokty_oparen: { if ( this->cstyle_mode ) { return this->readOptEmptyExprCheck( tokty_cparen ); } else { return this->readStmntsCheck( tokty_cparen ); } } case tokty_obracket: return this->readListOrVector( true, tokty_cbracket ); case tokty_obrace: return this->readMap( tokty_cbrace ); case tokty_fat_obracket: return this->readListOrVector( false, tokty_fat_cbracket ); case tokty_fat_ocbracket: { Node list( new Ginger::Mnx( LIST ) ); return list; } case tokty_unless: return this->readIf( tokty_unless, tokty_endunless ); case tokty_if: { if ( this->cstyle_mode ) break; return this->readIf( tokty_if, tokty_endif ); } case tokty_syscall: return this->readSyscall(); case tokty_for: { if ( this->cstyle_mode ) break; return this->readFor(); } case tokty_function: { #ifdef DBG_COMMON2GNX cerr << "FUNCTION" << endl; #endif if ( this->item_factory->peek()->tok_type == tokty_oparen ) { return this->readLambda(); } else { break; } } case tokty_define: //cerr << "DEFINE" << endl; return this->readDefinition(); case tokty_fn: return this->readLambda(); case tokty_lt: return this->readElement(); case tokty_package: return this->readPackage(); case tokty_import: return this->readImport(); case tokty_dhat: return this->readDHat(); case tokty_switch: { if ( this->cstyle_mode ) break; return this->readSwitch(); } case tokty_recordclass: return this->readRecordClass(); default: {} } ifact->unread(); return Node(); }
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. }