diff options
| -rw-r--r-- | boot/lower.c | 57 |
1 files changed, 25 insertions, 32 deletions
diff --git a/boot/lower.c b/boot/lower.c index df5fd45..8c588bf 100644 --- a/boot/lower.c +++ b/boot/lower.c @@ -1310,6 +1310,23 @@ lower_expression_construct(struct Lower_Context* ctx, struct Tree_Expression* tr return ir_make_construct(type->id, fields, tree_expr->span); } +struct Expression* +lower_expression_member(struct Lower_Context* ctx, struct Tree_Expression* tree_expr) +{ + struct Tree_Expression_Member* member = &tree_expr->value.member; + struct Expression* subject = lower_expression(ctx, member->subject); + return ir_make_member(subject, member->name, tree_expr->span); +} + +struct Expression* +lower_expression_subscript(struct Lower_Context* ctx, struct Tree_Expression* tree_expr) +{ + struct Tree_Expression_Subscript* subscript = &tree_expr->value.subscript; + struct Expression* subject = lower_expression(ctx, subscript->subject); + struct Expression* index = lower_expression(ctx, subscript->index); + return ir_make_subscript(subject, index, tree_expr->span); +} + // type-as-expression is only valid as the right-side of a top-level binding, // anywhere else it is an error. struct Expression* @@ -1362,21 +1379,8 @@ struct Expression* lower_expression_increment_decrement(struct Lower_Context* ctx, struct Tree_Expression* tree_expr) { struct Tree_Expression_Increment_Decrement* incdec = &tree_expr->value.increment_decrement; - struct Tree_Expression* subject = incdec->subject; - if (!subject || subject->kind != TREE_EXPRESSION_NAME) { - lower_push_error( - ctx->unit, - (struct Lower_Error){ - .kind = LOWER_ERROR_UNIMPLEMENTED, - .span = tree_expr->span, - .detail = string_from_static_c_string( - "increment/decrement on non-trivial " - "lvalue"), - }); - return nil; - } return ir_make_increment_decrement( - lower_expression(ctx, subject), incdec->operation, incdec->prefix, tree_expr->span); + lower_expression(ctx, incdec->subject), incdec->operation, incdec->prefix, tree_expr->span); } // turns a source expression into the lowered form. @@ -1410,11 +1414,13 @@ lower_expression(struct Lower_Context* ctx, struct Tree_Expression* tree_expr) return lower_expression_function(ctx, tree_expr); case TREE_EXPRESSION_INCREMENT_DECREMENT: return lower_expression_increment_decrement(ctx, tree_expr); - case TREE_EXPRESSION_SUBSCRIPT: case TREE_EXPRESSION_MEMBER: + return lower_expression_member(ctx, tree_expr); + case TREE_EXPRESSION_SUBSCRIPT: + return lower_expression_subscript(ctx, tree_expr); case TREE_EXPRESSION_TRY: case TREE_EXPRESSION_MUST: - // TODO: implement these + // TODO: try/must need maybe/result sentinel handling default: lower_push_error( ctx->unit, @@ -1650,22 +1656,9 @@ lower_statement_expression(struct Lower_Context* ctx, struct Tree_Statement* tre } if (op > BINARY_ASSIGN) { // compound assigns always synthesize into a basic assignment - // to a simple binary operation. - if (!lhs_tree || lhs_tree->kind != TREE_EXPRESSION_NAME) { - // TODO: implement non-trivial lhs assignments like function - // calls for example. not too common but sometimes necessary. - lower_push_error( - ctx->unit, - (struct Lower_Error){ - .kind = LOWER_ERROR_UNIMPLEMENTED, - .span = tree_stmt->span, - .detail = string_from_static_c_string( - "compound assignment with " - "non-trivial lvalue"), - }); - return nil; - } - + // to a simple binary operation. note that this evaluates the + // lhs tree twice, so side effects in the lvalue double. + // TODO: handle the double-evaluation once type checker is in. enum Binary_Operation simple_op = binary_operation_strip_assign(op); if (simple_op == BINARY_NONE) { lower_push_error( |
