| 133 | private <N extends Node> N ctrl(N n) { return _scope.ctrl(n); } |
| 134 | |
| 135 | public void parse() { |
| 136 | |
| 137 | _scope.define(ScopeNode.CTRL, Type.CONTROL , false, null, _lexer); |
| 138 | _scope.define(ScopeNode.MEM0, TypeMem.BOT , false, null, _lexer); |
| 139 | _scope.define(ScopeNode.ARG0, TypeInteger.BOT, false, null, _lexer); |
| 140 | |
| 141 | ctrl(XCTRL); |
| 142 | _scope.mem(new MemMergeNode(false)); |
| 143 | |
| 144 | // Parse the sys import |
| 145 | _lexer = new Lexer(sys.SYS); |
| 146 | while( !_lexer.isEOF() ) { |
| 147 | parseStatement(); |
| 148 | _lexer.skipWhiteSpace(); |
| 149 | } |
| 150 | |
| 151 | // Reset lexer for program text |
| 152 | _lexer = new Lexer(_code._src); |
| 153 | _xScopes.push(_scope); |
| 154 | |
| 155 | // Parse whole program, as-if function header "{ int arg -> body }" |
| 156 | parseFunctionBody( _code._main,loc(),"arg"); |
| 157 | |
| 158 | // Kill an empty default main. Keep only if it was explicitly defined |
| 159 | // (programmer asked for a "main") or it has stuff (i.e. beginner |
| 160 | // default main). |
| 161 | FunNode main = _code.link(_code._main); |
| 162 | StopNode stop = _code._stop; |
| 163 | // Gather an explicit main |
| 164 | FunNode xmain = null; |
| 165 | for( Node n : stop._inputs ) |
| 166 | if( n instanceof ReturnNode ret && "main".equals(ret.fun()._name) ) |
| 167 | if( xmain != null ) throw Utils.TODO(); |
| 168 | else xmain = ret.fun(); |
| 169 | |
| 170 | if( main.ret().expr()._type==Type.TOP && main.uctrl()==null ) { |
| 171 | // Kill an empty default main; so it does not attempt to put a |
| 172 | // "main" in any final ELF file |
| 173 | main.setDef(1,XCTRL); // Delete default start input |
| 174 | stop.delDef(stop._inputs.find(main.ret())); |
| 175 | if( xmain != null ) |
| 176 | _code.setMain(xmain); |
| 177 | |
| 178 | } else { |
| 179 | // We have a non-empty default main. |
| 180 | if( xmain != null ) |
| 181 | // Found an explicit "main" AND we have a default "main" |
| 182 | throw error("Cannot define both an explicit main and a default main"); |
| 183 | main._name = "main"; |
| 184 | } |
| 185 | |
| 186 | if( !_lexer.isEOF() ) throw _errorSyntax("unexpected"); |
| 187 | |
| 188 | // Clean up and reset |
| 189 | _xScopes.pop(); |
| 190 | _scope.kill(); |
| 191 | for( StructNode init : INITS.values() ) |
| 192 | init.unkeep().kill(); |