Skip to content

Commit 06d2e0a

Browse files
committed
Add Null type support across AST, IR, and type checker.
Signed-off-by: Cong Wang <cwang@multikernel.io>
1 parent 6372c0c commit 06d2e0a

File tree

3 files changed

+15
-8
lines changed

3 files changed

+15
-8
lines changed

src/ast.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ and bpf_type =
9090
| Ringbuf of bpf_type * int (* value_type, size - ring buffer object *)
9191
(* None type - represents missing/absent values *)
9292
| NoneType
93+
(* Null type - represents null pointers, compatible with any pointer type *)
94+
| Null
9395

9496
(** Map configuration *)
9597
type map_config = {
@@ -644,6 +646,7 @@ let rec string_of_bpf_type = function
644646
| RingbufRef value_type -> Printf.sprintf "ringbuf_ref<%s>" (string_of_bpf_type value_type)
645647
| Ringbuf (value_type, size) -> Printf.sprintf "ringbuf<%s>(%d)" (string_of_bpf_type value_type) size
646648
| NoneType -> "none"
649+
| Null -> "null"
647650

648651
let rec string_of_literal = function
649652
| IntLit (i, original_opt) ->

src/ir.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,8 @@ let rec ast_type_to_ir_type = function
732732
| ProgramHandle -> IRI32 (* Program handles are represented as file descriptors (i32) in IR to support error codes *)
733733
| Ringbuf (value_type, size) -> IRRingbuf (ast_type_to_ir_type value_type, size) (* Ring buffer object *)
734734
| RingbufRef _ -> IRU32 (* Ring buffer references are represented as pointers/handles (u32) in IR *)
735-
| NoneType -> IRU32 (* None type represented as u32 sentinel value in IR *)
735+
| NoneType -> IRU32 (* None type represented as u32 sentinel value in IR *)
736+
| Null -> IRPointer (IRU32, {min_size = Some 0; max_size = Some 0; alignment = 1; nullable = true}) (* Null is represented as a nullable pointer in IR *)
736737

737738
(* Helper function that preserves type aliases when converting AST types to IR types *)
738739
let rec ast_type_to_ir_type_with_context symbol_table ast_type =

src/type_checker.ml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -312,16 +312,18 @@ let rec unify_types t1 t2 =
312312
| Some unified -> Some (Array (unified, s1))
313313
| None -> None)
314314

315-
(* Pointer types - any pointer can be null *)
315+
(* Null type unification - null can unify with any pointer or function type *)
316+
| Null, Pointer t -> Some (Pointer t) (* null unifies with any pointer *)
317+
| Pointer t, Null -> Some (Pointer t) (* any pointer unifies with null *)
318+
| Null, Function (params, ret) -> Some (Function (params, ret)) (* null unifies with functions *)
319+
| Function (params, ret), Null -> Some (Function (params, ret)) (* functions unify with null *)
320+
321+
(* Pointer types *)
316322
| Pointer t1, Pointer t2 ->
317323
(match unify_types t1 t2 with
318324
| Some unified -> Some (Pointer unified)
319325
| None -> None)
320326

321-
(* Special case: null pointer (Pointer U32) can unify with any function type *)
322-
| Pointer U32, Function (params, ret) -> Some (Function (params, ret))
323-
| Function (params, ret), Pointer U32 -> Some (Function (params, ret))
324-
325327
(* Result types *)
326328
| Result (ok1, err1), Result (ok2, err2) ->
327329
(match unify_types ok1 ok2, unify_types err1 err2 with
@@ -430,7 +432,7 @@ let type_check_literal lit pos =
430432
Str (max 1 len) (* At least size 1 to handle empty strings *)
431433
| CharLit _ -> Char
432434
| BoolLit _ -> Bool
433-
| NullLit -> Pointer U32 (* null literal as nullable pointer, can be unified with any pointer type *)
435+
| NullLit -> Null (* null literal - can unify with any pointer or function type *)
434436
| NoneLit -> NoneType (* none literal represents missing/absent values *)
435437
| ArrayLit init_style ->
436438
(* Handle enhanced array literal type checking *)
@@ -1080,7 +1082,8 @@ and type_check_binary_op ctx left op right pos =
10801082
(match resolved_left_type, resolved_right_type with
10811083
| Str _, Str _ -> Bool (* Allow string comparison regardless of size *)
10821084
(* Null comparisons - any type can be compared with null *)
1083-
| _, Pointer _ | Pointer _, _ -> Bool
1085+
| Null, _ | _, Null -> Bool (* Direct null comparisons *)
1086+
| _, Pointer _ | Pointer _, _ -> Bool (* Pointer comparisons (legacy) *)
10841087
(* None comparisons - allow with map access expressions or variables that could contain map results *)
10851088
| NoneType, _ | _, NoneType ->
10861089
(* Check if at least one operand is a map access or could reasonably be a map result *)

0 commit comments

Comments
 (0)