optionals
This commit is contained in:
79
src/sema.zig
79
src/sema.zig
@@ -278,6 +278,13 @@ pub const Analyzer = struct {
|
||||
const elem_name = elem_type.displayName(self.allocator) catch return .void_type;
|
||||
return .{ .slice_type = .{ .element_name = elem_name } };
|
||||
}
|
||||
// Optional type: ?T
|
||||
if (tn.data == .optional_type_expr) {
|
||||
const ote = tn.data.optional_type_expr;
|
||||
const inner_type = self.resolveTypeNode(ote.inner_type);
|
||||
const inner_name = inner_type.displayName(self.allocator) catch return .void_type;
|
||||
return .{ .optional_type = .{ .child_name = inner_name } };
|
||||
}
|
||||
// Pointer type: *T
|
||||
if (tn.data == .pointer_type_expr) {
|
||||
const pte = tn.data.pointer_type_expr;
|
||||
@@ -456,6 +463,16 @@ pub const Analyzer = struct {
|
||||
}
|
||||
return .void_type;
|
||||
},
|
||||
.force_unwrap => |fu| {
|
||||
const opt_ty = self.inferExprType(fu.operand);
|
||||
if (opt_ty.isOptional()) return Type.fromName(opt_ty.optional_type.child_name) orelse .void_type;
|
||||
return .void_type;
|
||||
},
|
||||
.null_coalesce => |nc| {
|
||||
const opt_ty = self.inferExprType(nc.lhs);
|
||||
if (opt_ty.isOptional()) return Type.fromName(opt_ty.optional_type.child_name) orelse .void_type;
|
||||
return self.inferExprType(nc.rhs);
|
||||
},
|
||||
.deref_expr => |de| {
|
||||
const ptr_ty = self.inferExprType(de.operand);
|
||||
if (ptr_ty.isPointer()) return ptr_ty.pointerPointeeType() orelse .void_type;
|
||||
@@ -711,7 +728,20 @@ pub const Analyzer = struct {
|
||||
},
|
||||
.if_expr => |ie| {
|
||||
try self.analyzeNode(ie.condition);
|
||||
try self.analyzeNode(ie.then_branch);
|
||||
if (ie.binding_name) |bname| {
|
||||
// `if val := expr { ... }` — val is the unwrapped optional
|
||||
const cond_ty = self.inferExprType(ie.condition);
|
||||
const inner_ty: ?Type = if (cond_ty.isOptional())
|
||||
Type.fromName(cond_ty.optional_type.child_name)
|
||||
else
|
||||
null;
|
||||
try self.pushScope();
|
||||
try self.addSymbol(bname, .variable, inner_ty, node.span);
|
||||
try self.analyzeNode(ie.then_branch);
|
||||
self.popScope();
|
||||
} else {
|
||||
try self.analyzeNode(ie.then_branch);
|
||||
}
|
||||
if (ie.else_branch) |eb| {
|
||||
try self.analyzeNode(eb);
|
||||
}
|
||||
@@ -729,7 +759,19 @@ pub const Analyzer = struct {
|
||||
},
|
||||
.while_expr => |we| {
|
||||
try self.analyzeNode(we.condition);
|
||||
try self.analyzeNode(we.body);
|
||||
if (we.binding_name) |bname| {
|
||||
const cond_ty = self.inferExprType(we.condition);
|
||||
const inner_ty: ?Type = if (cond_ty.isOptional())
|
||||
Type.fromName(cond_ty.optional_type.child_name)
|
||||
else
|
||||
null;
|
||||
try self.pushScope();
|
||||
try self.addSymbol(bname, .variable, inner_ty, node.span);
|
||||
try self.analyzeNode(we.body);
|
||||
self.popScope();
|
||||
} else {
|
||||
try self.analyzeNode(we.body);
|
||||
}
|
||||
},
|
||||
.for_expr => |fe| {
|
||||
try self.analyzeNode(fe.iterable);
|
||||
@@ -812,6 +854,7 @@ pub const Analyzer = struct {
|
||||
.slice_type_expr,
|
||||
.pointer_type_expr,
|
||||
.many_pointer_type_expr,
|
||||
.optional_type_expr,
|
||||
.null_literal,
|
||||
.array_literal,
|
||||
.parameterized_type_expr,
|
||||
@@ -829,6 +872,13 @@ pub const Analyzer = struct {
|
||||
try self.analyzeNode(elem.value);
|
||||
}
|
||||
},
|
||||
.force_unwrap => |fu| {
|
||||
try self.analyzeNode(fu.operand);
|
||||
},
|
||||
.null_coalesce => |nc| {
|
||||
try self.analyzeNode(nc.lhs);
|
||||
try self.analyzeNode(nc.rhs);
|
||||
},
|
||||
.deref_expr => |de| {
|
||||
try self.analyzeNode(de.operand);
|
||||
},
|
||||
@@ -864,6 +914,8 @@ pub const Analyzer = struct {
|
||||
.index_expr,
|
||||
.slice_expr,
|
||||
.deref_expr,
|
||||
.force_unwrap,
|
||||
.null_coalesce,
|
||||
.null_literal,
|
||||
.type_expr,
|
||||
.insert_expr,
|
||||
@@ -905,7 +957,17 @@ pub const Analyzer = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
// For compound types (pointers, slices, arrays), resolve inner type refs
|
||||
// Compound types: ?T, *T, [*]T, []T, [N]T — delegate to resolveTypeNode
|
||||
switch (tn.data) {
|
||||
.optional_type_expr, .pointer_type_expr, .many_pointer_type_expr,
|
||||
.slice_type_expr, .array_type_expr,
|
||||
=> {
|
||||
const resolved = self.resolveTypeNode(tn);
|
||||
if (resolved != .void_type) return resolved;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
// For compound types, resolve inner type refs
|
||||
self.resolveTypeRef(tn);
|
||||
}
|
||||
return null;
|
||||
@@ -950,6 +1012,9 @@ pub const Analyzer = struct {
|
||||
.array_type_expr => |ate| {
|
||||
self.resolveTypeRef(ate.element_type);
|
||||
},
|
||||
.optional_type_expr => |ote| {
|
||||
self.resolveTypeRef(ote.inner_type);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
@@ -1152,6 +1217,7 @@ pub fn findNodeAtOffset(node: *Node, offset: u32) ?*Node {
|
||||
.slice_type_expr,
|
||||
.pointer_type_expr,
|
||||
.many_pointer_type_expr,
|
||||
.optional_type_expr,
|
||||
.null_literal,
|
||||
.array_literal,
|
||||
.parameterized_type_expr,
|
||||
@@ -1165,6 +1231,13 @@ pub fn findNodeAtOffset(node: *Node, offset: u32) ?*Node {
|
||||
if (findNodeAtOffset(elem.value, offset)) |found| return found;
|
||||
}
|
||||
},
|
||||
.null_coalesce => |nc| {
|
||||
if (findNodeAtOffset(nc.lhs, offset)) |found| return found;
|
||||
if (findNodeAtOffset(nc.rhs, offset)) |found| return found;
|
||||
},
|
||||
.force_unwrap => |fu| {
|
||||
if (findNodeAtOffset(fu.operand, offset)) |found| return found;
|
||||
},
|
||||
.deref_expr => |de| {
|
||||
if (findNodeAtOffset(de.operand, offset)) |found| return found;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user