Parse an allocation
()
| 1148 | Parse an allocation |
| 1149 | */ |
| 1150 | private Node alloc() { |
| 1151 | Type t = type(); |
| 1152 | if( t==null ) throw error("Expected a type"); |
| 1153 | // Parse ary[ length_expr ] |
| 1154 | if( match("[") ) { |
| 1155 | if( !t.makeZero().isa(t) ) |
| 1156 | throw error("Cannot allocate a non-nullable, since arrays always zero/null fill"); |
| 1157 | Node len = parseAsgn(); |
| 1158 | if( !(len._type instanceof TypeInteger) ) |
| 1159 | throw error("Cannot allocate an array with length "+len._type); |
| 1160 | require("]"); |
| 1161 | TypeMemPtr tmp = typeAry(t); |
| 1162 | return newArray(tmp._obj,len); |
| 1163 | } |
| 1164 | |
| 1165 | if( !(t instanceof TypeMemPtr tmp) ) |
| 1166 | throw error("Cannot allocate a "+t.str()); |
| 1167 | |
| 1168 | // Parse new struct { default_initialization } |
| 1169 | StructNode s = INITS.get(tmp._obj._name); |
| 1170 | if( s==null ) throw error("Unknown struct type '" + tmp._obj._name + "'"); |
| 1171 | |
| 1172 | Field[] fs = s._ts._fields; |
| 1173 | // if the object is fully initialized, we can skip a block here. |
| 1174 | // Check for constructor block: |
| 1175 | boolean hasConstructor = match("{"); |
| 1176 | Ary<Node> init=s._inputs; int idx=0; |
| 1177 | if( hasConstructor ) { |
| 1178 | idx = _scope.nIns(); |
| 1179 | // Push a scope, and pre-assign all struct fields. |
| 1180 | _scope.push(ScopeNode.Kind.Block); |
| 1181 | Lexer loc = loc(); |
| 1182 | for( int i=0; i<fs.length; i++ ) |
| 1183 | _scope.define(fs[i]._fname, fs[i]._type, fs[i]._final, s.in(i)._type==Type.TOP ? con(Type.BOTTOM) : s.in(i), loc); |
| 1184 | // Parse the constructor body |
| 1185 | require(parseBlock(ScopeNode.Kind.Constructor),"}"); |
| 1186 | init = _scope._inputs; |
| 1187 | } |
| 1188 | // Check that all fields are initialized |
| 1189 | for( int i=idx; i<init.size(); i++ ) |
| 1190 | if( init.at(i)._type == Type.TOP || init.at(i)._type == Type.BOTTOM ) |
| 1191 | throw error("'"+tmp._obj._name+"' is not fully initialized, field '" + fs[i-idx]._fname + "' needs to be set in a constructor"); |
| 1192 | Node ptr = newStruct(tmp._obj, con(tmp._obj.offset(fs.length)), idx, init ); |
| 1193 | if( hasConstructor ) |
| 1194 | _scope.pop(); |
| 1195 | return ptr; |
| 1196 | } |
| 1197 | |
| 1198 | |
| 1199 | /** |
no test coverage detected