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