Parse an allocation
()
| 1212 | Parse an allocation |
| 1213 | */ |
| 1214 | private Node alloc() { |
| 1215 | Type t = type(); |
| 1216 | if( t==null ) throw error("Expected a type"); |
| 1217 | // Parse ary[ length_expr ] |
| 1218 | if( match("[") ) { |
| 1219 | if( !t.makeZero().isa(t) ) |
| 1220 | throw error("Cannot allocate a non-nullable, since arrays always zero/null fill"); |
| 1221 | Node len = parseAsgn(); |
| 1222 | if( !(len._type instanceof TypeInteger) ) |
| 1223 | throw error("Cannot allocate an array with length "+len._type); |
| 1224 | require("]"); |
| 1225 | TypeMemPtr tmp = typeAry(t); |
| 1226 | return newArray(tmp._obj,len); |
| 1227 | } |
| 1228 | |
| 1229 | if( !(t instanceof TypeMemPtr tmp) ) |
| 1230 | throw error("Cannot allocate a "+t.str()); |
| 1231 | |
| 1232 | // Parse new struct { default_initialization } |
| 1233 | StructNode s = INITS.get(tmp._obj._name); |
| 1234 | if( s==null ) throw error("Unknown struct type '" + tmp._obj._name + "'"); |
| 1235 | |
| 1236 | Field[] fs = s._ts._fields; |
| 1237 | // if the object is fully initialized, we can skip a block here. |
| 1238 | // Check for constructor block: |
| 1239 | boolean hasConstructor = match("{"); |
| 1240 | Ary<Node> init=s._inputs; int idx=0; |
| 1241 | if( hasConstructor ) { |
| 1242 | idx = _scope.nIns(); |
| 1243 | // Push a scope, and pre-assign all struct fields. |
| 1244 | _scope.push(ScopeNode.Kind.Block); |
| 1245 | Lexer loc = loc(); |
| 1246 | for( int i=0; i<fs.length; i++ ) |
| 1247 | _scope.define(fs[i]._fname, fs[i]._type, fs[i]._final, s.in(i)._type==Type.TOP ? con(Type.BOTTOM) : s.in(i), loc); |
| 1248 | // Parse the constructor body |
| 1249 | require(parseBlock(ScopeNode.Kind.Constructor),"}"); |
| 1250 | init = _scope._inputs; |
| 1251 | } |
| 1252 | // Check that all fields are initialized |
| 1253 | for( int i=idx; i<init.size(); i++ ) |
| 1254 | if( init.at(i)._type == Type.TOP || init.at(i)._type == Type.BOTTOM ) |
| 1255 | throw error("'"+tmp._obj._name+"' is not fully initialized, field '" + fs[i-idx]._fname + "' needs to be set in a constructor"); |
| 1256 | Node ptr = newStruct(tmp._obj, con(tmp._obj.offset(fs.length)), idx, init ); |
| 1257 | if( hasConstructor ) |
| 1258 | _scope.pop(); |
| 1259 | return ptr; |
| 1260 | } |
| 1261 | |
| 1262 | |
| 1263 | /** |
no test coverage detected