aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/lower.c57
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(