Parse an allocation
()
| 1377 | Parse an allocation |
| 1378 | */ |
| 1379 | private Node alloc() { |
| 1380 | Type t = type(); |
| 1381 | if( t==null ) throw error("Expected a type"); |
| 1382 | // Parse ary[ length_expr ] |
| 1383 | if( match("[") ) { |
| 1384 | if( !t.makeZero().isa(t) ) |
| 1385 | throw error("Cannot allocate a non-nullable, since arrays always zero/null fill"); |
| 1386 | Node len = parseAsgn(); |
| 1387 | if( !(len._type instanceof TypeInteger) ) |
| 1388 | throw error("Cannot allocate an array with length "+len._type); |
| 1389 | require("]"); |
| 1390 | TypeMemPtr tmp = typeAry(t,false); |
| 1391 | return newArray(tmp._obj,len); |
| 1392 | } |
| 1393 | |
| 1394 | if( !(t instanceof TypeMemPtr tmp) ) |
| 1395 | throw error("Cannot allocate a "+t.str()); |
| 1396 | |
| 1397 | // Parse new struct { default_initialization } |
| 1398 | StructNode s = INITS.get(tmp._obj._name); |
| 1399 | if( s==null ) throw error("Unknown struct type '" + tmp._obj._name + "'"); |
| 1400 | |
| 1401 | Field[] fs = s._ts._fields; |
| 1402 | // if the object is fully initialized, we can skip a block here. |
| 1403 | // Check for constructor block: |
| 1404 | boolean hasConstructor = match("{"); |
| 1405 | Ary<Node> init=s._inputs; int idx=0; |
| 1406 | if( hasConstructor ) { |
| 1407 | idx = _scope.nIns(); |
| 1408 | // Push a scope, and pre-assign all struct fields. |
| 1409 | _scope.push(new Kind.Block()); |
| 1410 | Lexer loc = loc(); |
| 1411 | for( int i=0; i<fs.length; i++ ) |
| 1412 | // An initial TOP means the field needs to be initialized. We |
| 1413 | // store a BOT initially; any partial init will fall to BOT |
| 1414 | // (merge BOT and the partial) and be obviously only a partial |
| 1415 | // init. To be initialized the field needs a full clobber. |
| 1416 | _scope.define(fs[i]._fname, fs[i]._t, fs[i]._final, s.in(i)._type==Type.TOP ? con(Type.BOTTOM) : s.in(i), loc); |
| 1417 | // Parse the constructor body |
| 1418 | require(parseBlock(new Kind.Alloc(tmp)),"}"); |
| 1419 | init = _scope._inputs; |
| 1420 | } |
| 1421 | // Check that all fields are initialized |
| 1422 | for( int i=idx; i<init.size(); i++ ) |
| 1423 | if( init.at(i)._type == Type.TOP || init.at(i)._type == Type.BOTTOM ) |
| 1424 | throw error("'"+tmp._obj._name+"' is not fully initialized, field '" + fs[i-idx]._fname + "' needs to be set in a constructor"); |
| 1425 | Node ptr = newStruct(tmp._obj, off(tmp._obj, " len"), idx, init ); |
| 1426 | if( hasConstructor ) |
| 1427 | _scope.pop(); |
| 1428 | return ptr; |
| 1429 | } |
| 1430 | |
| 1431 | |
| 1432 | /** |
no test coverage detected