authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-07 05:29:11-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-07 05:29:11-07:00
log9aea99a999997e223307d8559e0ff9fa613839a3
tree241d9f8fc2b8225a4941bbf8b748170eb49411e7
parentea69d6ecda8412cf47b85853c8645d453c826427

implement array slicing syntax

closes #52

7 files changed, 199 insertions(+), 18 deletions(-)

doc/langref.md+3-1
...@@ -148,7 +148,7 @@ CastExpression : CastExpression token(as) Type | PrefixOpExpression...@@ -148,7 +148,7 @@ CastExpression : CastExpression token(as) Type | PrefixOpExpression
148148
149PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression149PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
150150
151SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression)151SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
152152
153FieldAccessExpression : token(Dot) token(Symbol)153FieldAccessExpression : token(Dot) token(Symbol)
154154
...@@ -156,6 +156,8 @@ FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)...@@ -156,6 +156,8 @@ FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
156156
157ArrayAccessExpression : token(LBracket) Expression token(RBracket)157ArrayAccessExpression : token(LBracket) Expression token(RBracket)
158158
159SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))
160
159PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const)))161PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const)))
160162
161PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | CompilerFnType163PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | CompilerFnType
src/analyze.cpp+54-1
...@@ -23,6 +23,8 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -23,6 +23,8 @@ static AstNode *first_executing_node(AstNode *node) {
23 return first_executing_node(node->data.bin_op_expr.op1);23 return first_executing_node(node->data.bin_op_expr.op1);
24 case NodeTypeArrayAccessExpr:24 case NodeTypeArrayAccessExpr:
25 return first_executing_node(node->data.array_access_expr.array_ref_expr);25 return first_executing_node(node->data.array_access_expr.array_ref_expr);
26 case NodeTypeSliceExpr:
27 return first_executing_node(node->data.slice_expr.array_ref_expr);
26 case NodeTypeFieldAccessExpr:28 case NodeTypeFieldAccessExpr:
27 return first_executing_node(node->data.field_access_expr.struct_expr);29 return first_executing_node(node->data.field_access_expr.struct_expr);
28 case NodeTypeCastExpr:30 case NodeTypeCastExpr:
...@@ -875,6 +877,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -875,6 +877,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
875 case NodeTypeBinOpExpr:877 case NodeTypeBinOpExpr:
876 case NodeTypeFnCallExpr:878 case NodeTypeFnCallExpr:
877 case NodeTypeArrayAccessExpr:879 case NodeTypeArrayAccessExpr:
880 case NodeTypeSliceExpr:
878 case NodeTypeNumberLiteral:881 case NodeTypeNumberLiteral:
879 case NodeTypeStringLiteral:882 case NodeTypeStringLiteral:
880 case NodeTypeCharLiteral:883 case NodeTypeCharLiteral:
...@@ -950,6 +953,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {...@@ -950,6 +953,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
950 case NodeTypeBinOpExpr:953 case NodeTypeBinOpExpr:
951 case NodeTypeFnCallExpr:954 case NodeTypeFnCallExpr:
952 case NodeTypeArrayAccessExpr:955 case NodeTypeArrayAccessExpr:
956 case NodeTypeSliceExpr:
953 case NodeTypeNumberLiteral:957 case NodeTypeNumberLiteral:
954 case NodeTypeStringLiteral:958 case NodeTypeStringLiteral:
955 case NodeTypeCharLiteral:959 case NodeTypeCharLiteral:
...@@ -1349,6 +1353,50 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -1349,6 +1353,50 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
1349 return return_type;1353 return return_type;
1350}1354}
13511355
1356static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1357 AstNode *node)
1358{
1359 TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr,
1360 node->data.slice_expr.array_ref_expr);
1361
1362 TypeTableEntry *return_type;
1363
1364 if (array_type->id == TypeTableEntryIdInvalid) {
1365 return_type = g->builtin_types.entry_invalid;
1366 } else if (array_type->id == TypeTableEntryIdArray) {
1367 return_type = get_unknown_size_array_type(g, import, array_type->data.array.child_type,
1368 node->data.slice_expr.is_const);
1369 } else if (array_type->id == TypeTableEntryIdPointer) {
1370 return_type = get_unknown_size_array_type(g, import, array_type->data.pointer.child_type,
1371 node->data.slice_expr.is_const);
1372 } else if (array_type->id == TypeTableEntryIdStruct &&
1373 array_type->data.structure.is_unknown_size_array)
1374 {
1375 return_type = get_unknown_size_array_type(g, import,
1376 array_type->data.structure.fields[0].type_entry,
1377 node->data.slice_expr.is_const);
1378 } else {
1379 add_node_error(g, node,
1380 buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name)));
1381 return_type = g->builtin_types.entry_invalid;
1382 }
1383
1384 if (return_type->id != TypeTableEntryIdInvalid) {
1385 assert(node->codegen_node);
1386 node->codegen_node->data.struct_val_expr_node.type_entry = return_type;
1387 node->codegen_node->data.struct_val_expr_node.source_node = node;
1388 context->struct_val_expr_alloca_list.append(&node->codegen_node->data.struct_val_expr_node);
1389 }
1390
1391 analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.slice_expr.start);
1392
1393 if (node->data.slice_expr.end) {
1394 analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.slice_expr.end);
1395 }
1396
1397 return return_type;
1398}
1399
1352static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,1400static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1353 AstNode *node)1401 AstNode *node)
1354{1402{
...@@ -1363,7 +1411,8 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i...@@ -1363,7 +1411,8 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i
1363 return_type = array_type->data.pointer.child_type;1411 return_type = array_type->data.pointer.child_type;
1364 } else {1412 } else {
1365 if (array_type->id != TypeTableEntryIdInvalid) {1413 if (array_type->id != TypeTableEntryIdInvalid) {
1366 add_node_error(g, node, buf_sprintf("array access of non-array"));1414 add_node_error(g, node,
1415 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));
1367 }1416 }
1368 return_type = g->builtin_types.entry_invalid;1417 return_type = g->builtin_types.entry_invalid;
1369 }1418 }
...@@ -2197,6 +2246,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -2197,6 +2246,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
2197 // for reading array access; assignment handled elsewhere2246 // for reading array access; assignment handled elsewhere
2198 return_type = analyze_array_access_expr(g, import, context, node);2247 return_type = analyze_array_access_expr(g, import, context, node);
2199 break;2248 break;
2249 case NodeTypeSliceExpr:
2250 return_type = analyze_slice_expr(g, import, context, node);
2251 break;
2200 case NodeTypeFieldAccessExpr:2252 case NodeTypeFieldAccessExpr:
2201 return_type = analyze_field_access_expr(g, import, context, node);2253 return_type = analyze_field_access_expr(g, import, context, node);
2202 break;2254 break;
...@@ -2541,6 +2593,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,...@@ -2541,6 +2593,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
2541 case NodeTypeBinOpExpr:2593 case NodeTypeBinOpExpr:
2542 case NodeTypeFnCallExpr:2594 case NodeTypeFnCallExpr:
2543 case NodeTypeArrayAccessExpr:2595 case NodeTypeArrayAccessExpr:
2596 case NodeTypeSliceExpr:
2544 case NodeTypeNumberLiteral:2597 case NodeTypeNumberLiteral:
2545 case NodeTypeStringLiteral:2598 case NodeTypeStringLiteral:
2546 case NodeTypeCharLiteral:2599 case NodeTypeCharLiteral:
src/analyze.hpp+2
...@@ -355,9 +355,11 @@ struct CodeGenNode {...@@ -355,9 +355,11 @@ struct CodeGenNode {
355 StructDeclNode struct_decl_node; // for NodeTypeStructDecl355 StructDeclNode struct_decl_node; // for NodeTypeStructDecl
356 FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr356 FieldAccessNode field_access_node; // for NodeTypeFieldAccessExpr
357 CastNode cast_node; // for NodeTypeCastExpr357 CastNode cast_node; // for NodeTypeCastExpr
358 // note: I've been using this field on some non-number literal nodes too.
358 NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral359 NumberLiteralNode num_lit_node; // for NodeTypeNumberLiteral
359 VarDeclNode var_decl_node; // for NodeTypeVariableDeclaration360 VarDeclNode var_decl_node; // for NodeTypeVariableDeclaration
360 StructValFieldNode struct_val_field_node; // for NodeTypeStructValueField361 StructValFieldNode struct_val_field_node; // for NodeTypeStructValueField
362 // note: I've been using this field on some non-struct val expressions too.
361 StructValExprNode struct_val_expr_node; // for NodeTypeStructValueExpr363 StructValExprNode struct_val_expr_node; // for NodeTypeStructValueExpr
362 IfVarNode if_var_node; // for NodeTypeStructValueExpr364 IfVarNode if_var_node; // for NodeTypeStructValueExpr
363 ParamDeclNode param_decl_node; // for NodeTypeParamDecl365 ParamDeclNode param_decl_node; // for NodeTypeParamDecl
src/codegen.cpp+60-8
...@@ -215,26 +215,34 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -215,26 +215,34 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
215 }215 }
216}216}
217217
218static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) {218static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) {
219 assert(node->type == NodeTypeArrayAccessExpr);219 TypeTableEntry *type_entry = get_expr_type(node);
220
221 AstNode *array_expr_node = node->data.array_access_expr.array_ref_expr;
222 TypeTableEntry *type_entry = get_expr_type(array_expr_node);
223220
224 LLVMValueRef array_ptr;221 LLVMValueRef array_ptr;
225 if (array_expr_node->type == NodeTypeFieldAccessExpr) {222 if (node->type == NodeTypeFieldAccessExpr) {
226 array_ptr = gen_field_access_expr(g, array_expr_node, true);223 array_ptr = gen_field_access_expr(g, node, true);
227 if (type_entry->id == TypeTableEntryIdPointer) {224 if (type_entry->id == TypeTableEntryIdPointer) {
228 // we have a double pointer so we must dereference it once225 // we have a double pointer so we must dereference it once
229 add_debug_source_node(g, node);226 add_debug_source_node(g, node);
230 array_ptr = LLVMBuildLoad(g->builder, array_ptr, "");227 array_ptr = LLVMBuildLoad(g->builder, array_ptr, "");
231 }228 }
232 } else {229 } else {
233 array_ptr = gen_expr(g, array_expr_node);230 array_ptr = gen_expr(g, node);
234 }231 }
235232
236 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);233 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
237234
235 return array_ptr;
236}
237
238static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) {
239 assert(node->type == NodeTypeArrayAccessExpr);
240
241 AstNode *array_expr_node = node->data.array_access_expr.array_ref_expr;
242 TypeTableEntry *type_entry = get_expr_type(array_expr_node);
243
244 LLVMValueRef array_ptr = gen_array_base_ptr(g, array_expr_node);
245
238 LLVMValueRef subscript_value = gen_expr(g, node->data.array_access_expr.subscript);246 LLVMValueRef subscript_value = gen_expr(g, node->data.array_access_expr.subscript);
239 assert(subscript_value);247 assert(subscript_value);
240248
...@@ -299,6 +307,48 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou...@@ -299,6 +307,48 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
299 return LLVMBuildStructGEP(g->builder, struct_ptr, codegen_field_access->field_index, "");307 return LLVMBuildStructGEP(g->builder, struct_ptr, codegen_field_access->field_index, "");
300}308}
301309
310static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
311 assert(node->type == NodeTypeSliceExpr);
312
313 AstNode *array_ref_node = node->data.slice_expr.array_ref_expr;
314 TypeTableEntry *array_type = get_expr_type(array_ref_node);
315
316 LLVMValueRef tmp_struct_ptr = node->codegen_node->data.struct_val_expr_node.ptr;
317
318 if (array_type->id == TypeTableEntryIdArray) {
319 LLVMValueRef array_ptr = gen_array_base_ptr(g, array_ref_node);
320 LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start);
321 LLVMValueRef end_val;
322 if (node->data.slice_expr.end) {
323 end_val = gen_expr(g, node->data.slice_expr.end);
324 } else {
325 end_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, array_type->data.array.len, false);
326 }
327
328 add_debug_source_node(g, node);
329 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
330 LLVMValueRef indices[] = {
331 LLVMConstNull(g->builtin_types.entry_usize->type_ref),
332 start_val,
333 };
334 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
335 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
336
337 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
338 LLVMValueRef len_value = LLVMBuildSub(g->builder, end_val, start_val, "");
339 LLVMBuildStore(g->builder, len_value, len_field_ptr);
340
341 return tmp_struct_ptr;
342 } else if (array_type->id == TypeTableEntryIdPointer) {
343 zig_panic("TODO gen_slice_expr pointer");
344 } else if (array_type->id == TypeTableEntryIdStruct) {
345 assert(array_type->data.structure.is_unknown_size_array);
346 zig_panic("TODO gen_slice_expr unknown size array");
347 } else {
348 zig_unreachable();
349 }
350}
351
302static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {352static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
303 assert(node->type == NodeTypeArrayAccessExpr);353 assert(node->type == NodeTypeArrayAccessExpr);
304354
...@@ -1443,6 +1493,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {...@@ -1443,6 +1493,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1443 return gen_fn_call_expr(g, node);1493 return gen_fn_call_expr(g, node);
1444 case NodeTypeArrayAccessExpr:1494 case NodeTypeArrayAccessExpr:
1445 return gen_array_access_expr(g, node, false);1495 return gen_array_access_expr(g, node, false);
1496 case NodeTypeSliceExpr:
1497 return gen_slice_expr(g, node);
1446 case NodeTypeFieldAccessExpr:1498 case NodeTypeFieldAccessExpr:
1447 return gen_field_access_expr(g, node, false);1499 return gen_field_access_expr(g, node, false);
1448 case NodeTypeUnreachable:1500 case NodeTypeUnreachable:
src/parser.cpp+42-8
...@@ -90,6 +90,8 @@ const char *node_type_str(NodeType node_type) {...@@ -90,6 +90,8 @@ const char *node_type_str(NodeType node_type) {
90 return "FnCallExpr";90 return "FnCallExpr";
91 case NodeTypeArrayAccessExpr:91 case NodeTypeArrayAccessExpr:
92 return "ArrayAccessExpr";92 return "ArrayAccessExpr";
93 case NodeTypeSliceExpr:
94 return "SliceExpr";
93 case NodeTypeExternBlock:95 case NodeTypeExternBlock:
94 return "ExternBlock";96 return "ExternBlock";
95 case NodeTypeDirective:97 case NodeTypeDirective:
...@@ -298,6 +300,14 @@ void ast_print(AstNode *node, int indent) {...@@ -298,6 +300,14 @@ void ast_print(AstNode *node, int indent) {
298 ast_print(node->data.array_access_expr.array_ref_expr, indent + 2);300 ast_print(node->data.array_access_expr.array_ref_expr, indent + 2);
299 ast_print(node->data.array_access_expr.subscript, indent + 2);301 ast_print(node->data.array_access_expr.subscript, indent + 2);
300 break;302 break;
303 case NodeTypeSliceExpr:
304 fprintf(stderr, "%s\n", node_type_str(node->type));
305 ast_print(node->data.slice_expr.array_ref_expr, indent + 2);
306 ast_print(node->data.slice_expr.start, indent + 2);
307 if (node->data.slice_expr.end) {
308 ast_print(node->data.slice_expr.end, indent + 2);
309 }
310 break;
301 case NodeTypeDirective:311 case NodeTypeDirective:
302 fprintf(stderr, "%s\n", node_type_str(node->type));312 fprintf(stderr, "%s\n", node_type_str(node->type));
303 break;313 break;
...@@ -1381,9 +1391,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -1381,9 +1391,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
1381}1391}
13821392
1383/*1393/*
1384SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression)1394SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
1385FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)1395FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
1386ArrayAccessExpression : token(LBracket) Expression token(RBracket)1396ArrayAccessExpression : token(LBracket) Expression token(RBracket)
1397SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))
1387FieldAccessExpression : token(Dot) token(Symbol)1398FieldAccessExpression : token(Dot) token(Symbol)
1388*/1399*/
1389static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {1400static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {
...@@ -1405,15 +1416,38 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo...@@ -1405,15 +1416,38 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo
1405 } else if (token->id == TokenIdLBracket) {1416 } else if (token->id == TokenIdLBracket) {
1406 *token_index += 1;1417 *token_index += 1;
14071418
1408 AstNode *node = ast_create_node(pc, NodeTypeArrayAccessExpr, token);1419 AstNode *expr_node = ast_parse_expression(pc, token_index, true);
1409 node->data.array_access_expr.array_ref_expr = primary_expr;
1410 node->data.array_access_expr.subscript = ast_parse_expression(pc, token_index, true);
14111420
1412 Token *r_bracket = &pc->tokens->at(*token_index);1421 Token *ellipsis_or_r_bracket = &pc->tokens->at(*token_index);
1413 *token_index += 1;
1414 ast_expect_token(pc, r_bracket, TokenIdRBracket);
14151422
1416 primary_expr = node;1423 if (ellipsis_or_r_bracket->id == TokenIdEllipsis) {
1424 *token_index += 1;
1425
1426 AstNode *node = ast_create_node(pc, NodeTypeSliceExpr, token);
1427 node->data.slice_expr.array_ref_expr = primary_expr;
1428 node->data.slice_expr.start = expr_node;
1429 node->data.slice_expr.end = ast_parse_expression(pc, token_index, false);
1430
1431 ast_eat_token(pc, token_index, TokenIdRBracket);
1432
1433 Token *const_tok = &pc->tokens->at(*token_index);
1434 if (const_tok->id == TokenIdKeywordConst) {
1435 *token_index += 1;
1436 node->data.slice_expr.is_const = true;
1437 }
1438
1439 primary_expr = node;
1440 } else if (ellipsis_or_r_bracket->id == TokenIdRBracket) {
1441 *token_index += 1;
1442
1443 AstNode *node = ast_create_node(pc, NodeTypeArrayAccessExpr, token);
1444 node->data.array_access_expr.array_ref_expr = primary_expr;
1445 node->data.array_access_expr.subscript = expr_node;
1446
1447 primary_expr = node;
1448 } else {
1449 ast_invalid_token_error(pc, token);
1450 }
1417 } else if (token->id == TokenIdDot) {1451 } else if (token->id == TokenIdDot) {
1418 *token_index += 1;1452 *token_index += 1;
14191453
src/parser.hpp+9
...@@ -41,6 +41,7 @@ enum NodeType {...@@ -41,6 +41,7 @@ enum NodeType {
41 NodeTypePrefixOpExpr,41 NodeTypePrefixOpExpr,
42 NodeTypeFnCallExpr,42 NodeTypeFnCallExpr,
43 NodeTypeArrayAccessExpr,43 NodeTypeArrayAccessExpr,
44 NodeTypeSliceExpr,
44 NodeTypeFieldAccessExpr,45 NodeTypeFieldAccessExpr,
45 NodeTypeUse,46 NodeTypeUse,
46 NodeTypeVoid,47 NodeTypeVoid,
...@@ -181,6 +182,13 @@ struct AstNodeArrayAccessExpr {...@@ -181,6 +182,13 @@ struct AstNodeArrayAccessExpr {
181 AstNode *subscript;182 AstNode *subscript;
182};183};
183184
185struct AstNodeSliceExpr {
186 AstNode *array_ref_expr;
187 AstNode *start;
188 AstNode *end;
189 bool is_const;
190};
191
184struct AstNodeFieldAccessExpr {192struct AstNodeFieldAccessExpr {
185 AstNode *struct_expr;193 AstNode *struct_expr;
186 Buf field_name;194 Buf field_name;
...@@ -378,6 +386,7 @@ struct AstNode {...@@ -378,6 +386,7 @@ struct AstNode {
378 AstNodePrefixOpExpr prefix_op_expr;386 AstNodePrefixOpExpr prefix_op_expr;
379 AstNodeFnCallExpr fn_call_expr;387 AstNodeFnCallExpr fn_call_expr;
380 AstNodeArrayAccessExpr array_access_expr;388 AstNodeArrayAccessExpr array_access_expr;
389 AstNodeSliceExpr slice_expr;
381 AstNodeUse use;390 AstNodeUse use;
382 AstNodeIfBoolExpr if_bool_expr;391 AstNodeIfBoolExpr if_bool_expr;
383 AstNodeIfVarExpr if_var_expr;392 AstNodeIfVarExpr if_var_expr;
test/run_tests.cpp+29
...@@ -907,6 +907,35 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -907,6 +907,35 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
907 "min i16: -32768\n"907 "min i16: -32768\n"
908 "min i32: -2147483648\n"908 "min i32: -2147483648\n"
909 "min i64: -9223372036854775808\n");909 "min i64: -9223372036854775808\n");
910
911
912 add_simple_case("slicing", R"SOURCE(
913use "std.zig";
914pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
915 var array : [20]i32;
916
917 array[5] = 1234;
918
919 var slice = array[5...10];
920
921 if (slice.len != 5) {
922 print_str("BAD\n");
923 }
924
925 if (slice.ptr[0] != 1234) {
926 print_str("BAD\n");
927 }
928
929 var slice_rest = array[10...];
930 if (slice_rest.len != 10) {
931 print_str("BAD\n");
932 }
933
934 print_str("OK\n");
935 return 0;
936}
937 )SOURCE", "OK\n");
938
910}939}
911940
912////////////////////////////////////////////////////////////////////////////////////941////////////////////////////////////////////////////////////////////////////////////