Parse an allocation
()
| 1319 | Parse an allocation |
| 1320 | */ |
| 1321 | private Node alloc() { |
| 1322 | Type t = type(); |
| 1323 | if( t==null ) throw error("Expected a type"); |
| 1324 | // Parse ary[ length_expr ] |
| 1325 | if( match("[") ) { |
| 1326 | if( !t.makeZero().isa(t) ) |
| 1327 | throw error("Cannot allocate a non-nullable, since arrays always zero/null fill"); |
| 1328 | Node len = parseAsgn(); |
| 1329 | if( !(len._type instanceof TypeInteger) ) |
| 1330 | throw error("Cannot allocate an array with length "+len._type); |
| 1331 | require("]"); |
| 1332 | TypeMemPtr tmp = typeAry(t,false); |
| 1333 | return newArray(tmp._obj,len); |
| 1334 | } |
| 1335 | |
| 1336 | if( !(t instanceof TypeMemPtr tmp) ) |
| 1337 | throw error("Cannot allocate a "+t.str()); |
| 1338 | |
| 1339 | // Parse new struct { default_initialization } |
| 1340 | StructNode s = INITS.get(tmp._obj._name); |
| 1341 | if( s==null ) throw error("Unknown struct type '" + tmp._obj._name + "'"); |
| 1342 | |
| 1343 | Field[] fs = s._ts._fields; |
| 1344 | // if the object is fully initialized, we can skip a block here. |
| 1345 | // Check for constructor block: |
| 1346 | boolean hasConstructor = match("{"); |
| 1347 | Ary<Node> init=s._inputs; int idx=0; |
| 1348 | if( hasConstructor ) { |
| 1349 | idx = _scope.nIns(); |
| 1350 | // Push a scope, and pre-assign all struct fields. |
| 1351 | _scope.push(new Kind.Block()); |
| 1352 | Lexer loc = loc(); |
| 1353 | for( int i=0; i<fs.length; i++ ) |
| 1354 | // An initial TOP means the field needs to be initialized. We |
| 1355 | // store a BOT initially; any partial init will fall to BOT |
| 1356 | // (merge BOT and the partial) and be obviously only a partial |
| 1357 | // init. To be initialized the field needs a full clobber. |
| 1358 | _scope.define(fs[i]._fname, fs[i]._t, fs[i]._final, s.in(i)._type==Type.TOP ? con(Type.BOTTOM) : s.in(i), loc); |
| 1359 | // Parse the constructor body |
| 1360 | require(parseBlock(new Kind.Alloc(tmp)),"}"); |
| 1361 | init = _scope._inputs; |
| 1362 | } |
| 1363 | // Check that all fields are initialized |
| 1364 | for( int i=idx; i<init.size(); i++ ) |
| 1365 | if( init.at(i)._type == Type.TOP || init.at(i)._type == Type.BOTTOM ) |
| 1366 | throw error("'"+tmp._obj._name+"' is not fully initialized, field '" + fs[i-idx]._fname + "' needs to be set in a constructor"); |
| 1367 | Node ptr = newStruct(tmp._obj, off(tmp._obj, " len"), idx, init ); |
| 1368 | if( hasConstructor ) |
| 1369 | _scope.pop(); |
| 1370 | return ptr; |
| 1371 | } |
| 1372 | |
| 1373 | |
| 1374 | /** |
no test coverage detected