authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-18 23:52:42-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-18 23:52:42-05:00
log19037014e5a25eaac9564d22cc04cf12fb6ef98e
treeec7ec61515ddf48ab94585d054bb69c329febce3
parent31565efe9d6cde2e4909f986d50f8c46166d3311

IR: more maybe type support


4 files changed, 150 insertions(+), 86 deletions(-)

src/ast_render.cpp+55-35
......@@ -342,13 +342,23 @@ static void print_symbol(AstRender *ar, Buf *symbol) {
342342 fprintf(ar->f, "@\"%s\"", buf_ptr(&escaped));
343343}
344344
345static void render_node(AstRender *ar, AstNode *node) {
345static void render_node_extra(AstRender *ar, AstNode *node, bool grouped);
346
347static void render_node_grouped(AstRender *ar, AstNode *node) {
348 return render_node_extra(ar, node, true);
349}
350
351static void render_node_ungrouped(AstRender *ar, AstNode *node) {
352 return render_node_extra(ar, node, false);
353}
354
355static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
346356 switch (node->type) {
347357 case NodeTypeRoot:
348358 for (size_t i = 0; i < node->data.root.top_level_decls.length; i += 1) {
349359 AstNode *child = node->data.root.top_level_decls.at(i);
350360 print_indent(ar);
351 render_node(ar, child);
361 render_node_grouped(ar, child);
352362
353363 if (child->type == NodeTypeUse ||
354364 child->type == NodeTypeVariableDeclaration ||
......@@ -381,7 +391,7 @@ static void render_node(AstRender *ar, AstNode *node) {
381391 print_symbol(ar, param_decl->data.param_decl.name);
382392 fprintf(ar->f, ": ");
383393 }
384 render_node(ar, param_decl->data.param_decl.type);
394 render_node_grouped(ar, param_decl->data.param_decl.type);
385395
386396 if (arg_i + 1 < arg_count || is_var_args) {
387397 fprintf(ar->f, ", ");
......@@ -394,14 +404,14 @@ static void render_node(AstRender *ar, AstNode *node) {
394404
395405 AstNode *return_type_node = node->data.fn_proto.return_type;
396406 fprintf(ar->f, " -> ");
397 render_node(ar, return_type_node);
407 render_node_grouped(ar, return_type_node);
398408 break;
399409 }
400410 case NodeTypeFnDef:
401411 {
402 render_node(ar, node->data.fn_def.fn_proto);
412 render_node_grouped(ar, node->data.fn_def.fn_proto);
403413 fprintf(ar->f, " ");
404 render_node(ar, node->data.fn_def.body);
414 render_node_grouped(ar, node->data.fn_def.body);
405415 break;
406416 }
407417 case NodeTypeBlock:
......@@ -414,7 +424,7 @@ static void render_node(AstRender *ar, AstNode *node) {
414424 for (size_t i = 0; i < node->data.block.statements.length; i += 1) {
415425 AstNode *statement = node->data.block.statements.at(i);
416426 print_indent(ar);
417 render_node(ar, statement);
427 render_node_grouped(ar, statement);
418428 if (i != node->data.block.statements.length - 1)
419429 fprintf(ar->f, ";");
420430 fprintf(ar->f, "\n");
......@@ -427,14 +437,14 @@ static void render_node(AstRender *ar, AstNode *node) {
427437 {
428438 const char *return_str = return_string(node->data.return_expr.kind);
429439 fprintf(ar->f, "%s ", return_str);
430 render_node(ar, node->data.return_expr.expr);
440 render_node_grouped(ar, node->data.return_expr.expr);
431441 break;
432442 }
433443 case NodeTypeDefer:
434444 {
435445 const char *defer_str = defer_string(node->data.defer.kind);
436446 fprintf(ar->f, "%s ", defer_str);
437 render_node(ar, node->data.return_expr.expr);
447 render_node_grouped(ar, node->data.return_expr.expr);
438448 break;
439449 }
440450 case NodeTypeVariableDeclaration:
......@@ -447,11 +457,11 @@ static void render_node(AstRender *ar, AstNode *node) {
447457
448458 if (node->data.variable_declaration.type) {
449459 fprintf(ar->f, ": ");
450 render_node(ar, node->data.variable_declaration.type);
460 render_node_grouped(ar, node->data.variable_declaration.type);
451461 }
452462 if (node->data.variable_declaration.expr) {
453463 fprintf(ar->f, " = ");
454 render_node(ar, node->data.variable_declaration.expr);
464 render_node_grouped(ar, node->data.variable_declaration.expr);
455465 }
456466 break;
457467 }
......@@ -460,15 +470,15 @@ static void render_node(AstRender *ar, AstNode *node) {
460470 const char *pub_str = visib_mod_string(node->data.type_decl.top_level_decl.visib_mod);
461471 const char *var_name = buf_ptr(node->data.type_decl.symbol);
462472 fprintf(ar->f, "%stype %s = ", pub_str, var_name);
463 render_node(ar, node->data.type_decl.child_type);
473 render_node_grouped(ar, node->data.type_decl.child_type);
464474 break;
465475 }
466476 case NodeTypeBinOpExpr:
467 fprintf(ar->f, "(");
468 render_node(ar, node->data.bin_op_expr.op1);
477 if (!grouped) fprintf(ar->f, "(");
478 render_node_ungrouped(ar, node->data.bin_op_expr.op1);
469479 fprintf(ar->f, " %s ", bin_op_str(node->data.bin_op_expr.bin_op));
470 render_node(ar, node->data.bin_op_expr.op2);
471 fprintf(ar->f, ")");
480 render_node_ungrouped(ar, node->data.bin_op_expr.op2);
481 if (!grouped) fprintf(ar->f, ")");
472482 break;
473483 case NodeTypeNumberLiteral:
474484 switch (node->data.number_literal.bignum->kind) {
......@@ -511,7 +521,7 @@ static void render_node(AstRender *ar, AstNode *node) {
511521 PrefixOp op = node->data.prefix_op_expr.prefix_op;
512522 fprintf(ar->f, "%s", prefix_op_str(op));
513523
514 render_node(ar, node->data.prefix_op_expr.primary_expr);
524 render_node_ungrouped(ar, node->data.prefix_op_expr.primary_expr);
515525 break;
516526 }
517527 case NodeTypeFnCallExpr:
......@@ -520,7 +530,7 @@ static void render_node(AstRender *ar, AstNode *node) {
520530 } else {
521531 fprintf(ar->f, "(");
522532 }
523 render_node(ar, node->data.fn_call_expr.fn_ref_expr);
533 render_node_ungrouped(ar, node->data.fn_call_expr.fn_ref_expr);
524534 if (!node->data.fn_call_expr.is_builtin) {
525535 fprintf(ar->f, ")");
526536 }
......@@ -530,21 +540,21 @@ static void render_node(AstRender *ar, AstNode *node) {
530540 if (i != 0) {
531541 fprintf(ar->f, ", ");
532542 }
533 render_node(ar, param);
543 render_node_grouped(ar, param);
534544 }
535545 fprintf(ar->f, ")");
536546 break;
537547 case NodeTypeArrayAccessExpr:
538 render_node(ar, node->data.array_access_expr.array_ref_expr);
548 render_node_ungrouped(ar, node->data.array_access_expr.array_ref_expr);
539549 fprintf(ar->f, "[");
540 render_node(ar, node->data.array_access_expr.subscript);
550 render_node_grouped(ar, node->data.array_access_expr.subscript);
541551 fprintf(ar->f, "]");
542552 break;
543553 case NodeTypeFieldAccessExpr:
544554 {
545555 AstNode *lhs = node->data.field_access_expr.struct_expr;
546556 Buf *rhs = node->data.field_access_expr.field_name;
547 render_node(ar, lhs);
557 render_node_ungrouped(ar, lhs);
548558 fprintf(ar->f, ".");
549559 print_symbol(ar, rhs);
550560 break;
......@@ -565,7 +575,7 @@ static void render_node(AstRender *ar, AstNode *node) {
565575 print_indent(ar);
566576 print_symbol(ar, field_node->data.struct_field.name);
567577 fprintf(ar->f, ": ");
568 render_node(ar, field_node->data.struct_field.type);
578 render_node_grouped(ar, field_node->data.struct_field.type);
569579 fprintf(ar->f, ",\n");
570580 }
571581
......@@ -574,9 +584,8 @@ static void render_node(AstRender *ar, AstNode *node) {
574584 break;
575585 }
576586 case NodeTypeContainerInitExpr:
577 fprintf(ar->f, "(");
578 render_node(ar, node->data.container_init_expr.type);
579 fprintf(ar->f, "){");
587 render_node_ungrouped(ar, node->data.container_init_expr.type);
588 fprintf(ar->f, "{");
580589 assert(node->data.container_init_expr.entries.length == 0);
581590 fprintf(ar->f, "}");
582591 break;
......@@ -584,13 +593,13 @@ static void render_node(AstRender *ar, AstNode *node) {
584593 {
585594 fprintf(ar->f, "[");
586595 if (node->data.array_type.size) {
587 render_node(ar, node->data.array_type.size);
596 render_node_grouped(ar, node->data.array_type.size);
588597 }
589598 fprintf(ar->f, "]");
590599 if (node->data.array_type.is_const) {
591600 fprintf(ar->f, "const ");
592601 }
593 render_node(ar, node->data.array_type.child_type);
602 render_node_ungrouped(ar, node->data.array_type.child_type);
594603 break;
595604 }
596605 case NodeTypeErrorType:
......@@ -622,7 +631,7 @@ static void render_node(AstRender *ar, AstNode *node) {
622631 buf_ptr(asm_output->constraint));
623632 if (asm_output->return_type) {
624633 fprintf(ar->f, "-> ");
625 render_node(ar, asm_output->return_type);
634 render_node_grouped(ar, asm_output->return_type);
626635 } else {
627636 fprintf(ar->f, "%s", buf_ptr(asm_output->variable_name));
628637 }
......@@ -642,7 +651,7 @@ static void render_node(AstRender *ar, AstNode *node) {
642651 fprintf(ar->f, "[%s] \"%s\" (",
643652 buf_ptr(asm_input->asm_symbolic_name),
644653 buf_ptr(asm_input->constraint));
645 render_node(ar, asm_input->expr);
654 render_node_grouped(ar, asm_input->expr);
646655 fprintf(ar->f, ")");
647656 }
648657 fprintf(ar->f, "\n");
......@@ -660,13 +669,13 @@ static void render_node(AstRender *ar, AstNode *node) {
660669 {
661670 const char *inline_str = node->data.while_expr.is_inline ? "inline " : "";
662671 fprintf(ar->f, "%swhile (", inline_str);
663 render_node(ar, node->data.while_expr.condition);
672 render_node_grouped(ar, node->data.while_expr.condition);
664673 if (node->data.while_expr.continue_expr) {
665674 fprintf(ar->f, "; ");
666 render_node(ar, node->data.while_expr.continue_expr);
675 render_node_grouped(ar, node->data.while_expr.continue_expr);
667676 }
668677 fprintf(ar->f, ") ");
669 render_node(ar, node->data.while_expr.body);
678 render_node_grouped(ar, node->data.while_expr.body);
670679 break;
671680 }
672681 case NodeTypeThisLiteral:
......@@ -680,6 +689,18 @@ static void render_node(AstRender *ar, AstNode *node) {
680689 fprintf(ar->f, "%s", bool_str);
681690 break;
682691 }
692 case NodeTypeIfBoolExpr:
693 {
694 fprintf(ar->f, "if (");
695 render_node_grouped(ar, node->data.if_bool_expr.condition);
696 fprintf(ar->f, ") ");
697 render_node_grouped(ar, node->data.if_bool_expr.then_block);
698 if (node->data.if_bool_expr.else_node) {
699 fprintf(ar->f, "else ");
700 render_node_grouped(ar, node->data.if_bool_expr.else_node);
701 }
702 break;
703 }
683704 case NodeTypeFnDecl:
684705 case NodeTypeParamDecl:
685706 case NodeTypeErrorValueDecl:
......@@ -690,7 +711,6 @@ static void render_node(AstRender *ar, AstNode *node) {
690711 case NodeTypeUse:
691712 case NodeTypeNullLiteral:
692713 case NodeTypeZeroesLiteral:
693 case NodeTypeIfBoolExpr:
694714 case NodeTypeIfVarExpr:
695715 case NodeTypeForExpr:
696716 case NodeTypeSwitchExpr:
......@@ -711,5 +731,5 @@ void ast_render(FILE *f, AstNode *node, int indent_size) {
711731 ar.indent_size = indent_size;
712732 ar.indent = 0;
713733
714 render_node(&ar, node);
734 render_node_grouped(&ar, node);
715735}
src/codegen.cpp+11-1
......@@ -3242,9 +3242,19 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
32423242 buf_appendf(out_buf, "%s%s *", const_str, buf_ptr(&child_buf));
32433243 break;
32443244 }
3245 case TypeTableEntryIdMaybe:
3246 {
3247 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
3248 if (child_type->id == TypeTableEntryIdPointer ||
3249 child_type->id == TypeTableEntryIdFn)
3250 {
3251 return get_c_type(g, child_type, out_buf);
3252 } else {
3253 zig_unreachable();
3254 }
3255 }
32453256 case TypeTableEntryIdArray:
32463257 case TypeTableEntryIdStruct:
3247 case TypeTableEntryIdMaybe:
32483258 case TypeTableEntryIdErrorUnion:
32493259 case TypeTableEntryIdPureError:
32503260 case TypeTableEntryIdEnum:
src/ir.cpp+71-44
......@@ -3113,8 +3113,11 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
31133113 var->type = result_type;
31143114 assert(var->type);
31153115
3116 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
3117 *mem_slot = casted_init_value->static_value;
3116 if (var->mem_slot_index != SIZE_MAX) {
3117 assert(var->mem_slot_index < ira->exec_context.mem_slot_count);
3118 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
3119 *mem_slot = casted_init_value->static_value;
3120 }
31183121
31193122 ir_build_var_decl_from(&ira->new_irb, &decl_var_instruction->base, var, var_type, casted_init_value);
31203123
......@@ -3341,6 +3344,70 @@ static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp
33413344 return child_type;
33423345}
33433346
3347static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
3348 IrInstruction *value = un_op_instruction->value->other;
3349 TypeTableEntry *type_entry = ir_resolve_type(ira, value);
3350 TypeTableEntry *canon_type = get_underlying_type(type_entry);
3351 switch (canon_type->id) {
3352 case TypeTableEntryIdInvalid:
3353 return ira->codegen->builtin_types.entry_invalid;
3354 case TypeTableEntryIdVar:
3355 case TypeTableEntryIdTypeDecl:
3356 zig_unreachable();
3357 case TypeTableEntryIdMetaType:
3358 case TypeTableEntryIdVoid:
3359 case TypeTableEntryIdBool:
3360 case TypeTableEntryIdInt:
3361 case TypeTableEntryIdFloat:
3362 case TypeTableEntryIdPointer:
3363 case TypeTableEntryIdArray:
3364 case TypeTableEntryIdStruct:
3365 case TypeTableEntryIdNumLitFloat:
3366 case TypeTableEntryIdNumLitInt:
3367 case TypeTableEntryIdUndefLit:
3368 case TypeTableEntryIdNullLit:
3369 case TypeTableEntryIdMaybe:
3370 case TypeTableEntryIdErrorUnion:
3371 case TypeTableEntryIdPureError:
3372 case TypeTableEntryIdEnum:
3373 case TypeTableEntryIdUnion:
3374 case TypeTableEntryIdFn:
3375 case TypeTableEntryIdNamespace:
3376 case TypeTableEntryIdBlock:
3377 case TypeTableEntryIdGenericFn:
3378 {
3379 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base,
3380 value->static_value.depends_on_compile_var);
3381 out_val->data.x_type = get_maybe_type(ira->codegen, type_entry);
3382 return ira->codegen->builtin_types.entry_type;
3383 }
3384 case TypeTableEntryIdUnreachable:
3385 add_node_error(ira->codegen, un_op_instruction->base.source_node,
3386 buf_sprintf("type '%s' not nullable", buf_ptr(&type_entry->name)));
3387 // TODO if it's a type decl, put an error note here pointing to the decl
3388 return ira->codegen->builtin_types.entry_invalid;
3389 }
3390 zig_unreachable();
3391}
3392
3393static TypeTableEntry *ir_analyze_unwrap_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
3394 IrInstruction *value = un_op_instruction->value->other;
3395 TypeTableEntry *type_entry = value->type_entry;
3396 if (type_entry->id == TypeTableEntryIdInvalid) {
3397 return type_entry;
3398 } else if (type_entry->id == TypeTableEntryIdMaybe) {
3399 if (value->static_value.special != ConstValSpecialRuntime) {
3400 zig_panic("TODO compile time eval unwrap maybe");
3401 }
3402 ir_build_un_op_from(&ira->new_irb, &un_op_instruction->base, IrUnOpUnwrapMaybe, value);
3403 return type_entry->data.maybe.child_type;
3404 } else {
3405 add_node_error(ira->codegen, un_op_instruction->base.source_node,
3406 buf_sprintf("expected maybe type, found '%s'", buf_ptr(&type_entry->name)));
3407 return ira->codegen->builtin_types.entry_invalid;
3408 }
3409}
3410
33443411static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
33453412 IrUnOp op_id = un_op_instruction->op_id;
33463413 switch (op_id) {
......@@ -3417,34 +3484,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
34173484 case IrUnOpDereference:
34183485 return ir_analyze_dereference(ira, un_op_instruction);
34193486 case IrUnOpMaybe:
3420 zig_panic("TODO analyze PrefixOpMaybe");
3421 //{
3422 // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
3423
3424 // if (type_entry->id == TypeTableEntryIdInvalid) {
3425 // return type_entry;
3426 // } else if (type_entry->id == TypeTableEntryIdMetaType) {
3427 // TypeTableEntry *meta_type = resolve_type(g, *expr_node);
3428 // if (meta_type->id == TypeTableEntryIdInvalid) {
3429 // return g->builtin_types.entry_invalid;
3430 // } else if (meta_type->id == TypeTableEntryIdUnreachable) {
3431 // add_node_error(g, node, buf_create_from_str("unable to wrap unreachable in maybe type"));
3432 // return g->builtin_types.entry_invalid;
3433 // } else {
3434 // return resolve_expr_const_val_as_type(g, node, get_maybe_type(g, meta_type), false);
3435 // }
3436 // } else if (type_entry->id == TypeTableEntryIdUnreachable) {
3437 // add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in maybe type"));
3438 // return g->builtin_types.entry_invalid;
3439 // } else {
3440 // ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
3441 // TypeTableEntry *maybe_type = get_maybe_type(g, type_entry);
3442 // if (!target_const_val->ok) {
3443 // return maybe_type;
3444 // }
3445 // return resolve_expr_const_val_as_non_null(g, node, maybe_type, target_const_val);
3446 // }
3447 //}
3487 return ir_analyze_maybe(ira, un_op_instruction);
34483488 case IrUnOpError:
34493489 return ir_analyze_unary_prefix_op_err(ira, un_op_instruction);
34503490 case IrUnOpUnwrapError:
......@@ -3463,20 +3503,7 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
34633503 // }
34643504 //}
34653505 case IrUnOpUnwrapMaybe:
3466 zig_panic("TODO analyze PrefixOpUnwrapMaybe");
3467 //{
3468 // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
3469
3470 // if (type_entry->id == TypeTableEntryIdInvalid) {
3471 // return type_entry;
3472 // } else if (type_entry->id == TypeTableEntryIdMaybe) {
3473 // return type_entry->data.maybe.child_type;
3474 // } else {
3475 // add_node_error(g, *expr_node,
3476 // buf_sprintf("expected maybe type, got '%s'", buf_ptr(&type_entry->name)));
3477 // return g->builtin_types.entry_invalid;
3478 // }
3479 //}
3506 return ir_analyze_unwrap_maybe(ira, un_op_instruction);
34803507 case IrUnOpErrorReturn:
34813508 zig_panic("TODO analyze IrUnOpErrorReturn");
34823509 case IrUnOpMaybeReturn:
std/builtin.zig+13-6
......@@ -1,24 +1,31 @@
11// These functions are provided when not linking against libc because LLVM
22// sometimes generates code that calls them.
33
4// TODO dest should be nullable and return value should be nullable
5export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {
4export fn memset(dest: ?&u8, c: u8, n: usize) -> ?&u8 {
65 @setDebugSafety(this, false);
76
7 if (n == 0)
8 return dest;
9
10 const d = ??dest;
811 var index: usize = 0;
912 while (index != n; index += 1)
10 dest[index] = c;
13 d[index] = c;
1114
1215 return dest;
1316}
1417
15// TODO dest, source, and return value should be nullable
16export fn memcpy(noalias dest: &u8, noalias src: &const u8, n: usize) -> &u8 {
18export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) -> ?&u8 {
1719 @setDebugSafety(this, false);
1820
21 if (n == 0)
22 return dest;
23
24 const d = ??dest;
25 const s = ??src;
1926 var index: usize = 0;
2027 while (index != n; index += 1)
21 dest[index] = src[index];
28 d[index] = s[index];
2229
2330 return dest;
2431}