From 30d8a365bce979bb77302ed8151e6fbaa4bc77ca Mon Sep 17 00:00:00 2001 From: Torben Ewert Date: Fri, 26 Jun 2026 10:56:33 +0200 Subject: [PATCH] feat: add char value and operations --- lib/pinc_bytecode/value.ml | 19 ++++++++++--------- lib/pinc_compiler/compiler.ml | 2 +- lib/pinc_vm/vm.ml | 26 ++++++++++++++++---------- test/vm/char.pi | 3 +++ test/vm/run.t | 9 +++++++++ 5 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 test/vm/char.pi diff --git a/lib/pinc_bytecode/value.ml b/lib/pinc_bytecode/value.ml index 19bf78f..61b382c 100644 --- a/lib/pinc_bytecode/value.ml +++ b/lib/pinc_bytecode/value.ml @@ -3,18 +3,10 @@ type t = | Int of int | Float of float | Bool of bool + | Char of Uchar.t | String of string | Array of t array | Record of t StringMap.t -(* -let pp fmt = function - | Null -> Format.fprintf fmt "\n%!" - | Int i -> Format.fprintf fmt "%i\n%!" i - | Float f -> Format.fprintf fmt "%f\n%!" f - | Bool b -> Format.fprintf fmt "%b\n%!" b - | String s -> Format.fprintf fmt "%S\n%!" s - | Array _ -> Format.fprintf fmt "\n%!" -;; *) let rec to_string = function | Null -> "" @@ -22,6 +14,10 @@ let rec to_string = function | Float f when Float.is_integer f -> string_of_int (int_of_float f) | Float f -> string_of_float f | Bool b -> string_of_bool b + | Char c -> + let buf = Buffer.create 32 in + c |> Buffer.add_utf_8_uchar buf; + Buffer.contents buf | String s -> s | Array a -> let buf = Buffer.create 200 in @@ -49,6 +45,7 @@ let is_true = function | Bool b -> b | Int _ -> true | Float _ -> true + | Char _ -> true | String s -> s <> "" | Array [||] -> false | Array _ -> true @@ -62,6 +59,7 @@ let rec equal a b = | Float a, Int b -> a = float_of_int b | Int a, Float b -> float_of_int a = b | Bool a, Bool b -> a = b + | Char a, Char b -> Uchar.equal a b | String a, String b -> a = b | Null, Null -> true | Array a, Array b -> Array.equal equal a b @@ -76,6 +74,9 @@ let compare a b = | Float a, Int b -> Float.compare a (float_of_int b) | Int a, Float b -> Float.compare (float_of_int a) b | Bool a, Bool b -> Bool.compare a b + | Char a, Char b -> Uchar.compare a b + | Char a, Int b -> Int.compare (Uchar.to_int a) b + | Int a, Char b -> Int.compare a (Uchar.to_int b) | String a, String b -> String.compare a b | Null, Null -> 0 | Array a, Array b -> Int.compare (Array.length a) (Array.length b) diff --git a/lib/pinc_compiler/compiler.ml b/lib/pinc_compiler/compiler.ml index 645a076..c8d1b02 100644 --- a/lib/pinc_compiler/compiler.ml +++ b/lib/pinc_compiler/compiler.ml @@ -105,7 +105,7 @@ let rec compile_expr t (expr : Pinc_Types.Ast.expression) = match expr.expression_desc with | Void -> t | String s -> compile_string_template t s - | Char _ -> raise_notrace TODO + | Char c -> emit_constant t (Pinc_Bytecode.Value.Char c) | Int i -> emit_constant t (Pinc_Bytecode.Value.Int i) | Float f -> emit_constant t (Pinc_Bytecode.Value.Float f) | Bool true -> emit t Pinc_Bytecode.Instruction.I_True diff --git a/lib/pinc_vm/vm.ml b/lib/pinc_vm/vm.ml index 86d6bbe..10ada72 100644 --- a/lib/pinc_vm/vm.ml +++ b/lib/pinc_vm/vm.ml @@ -57,8 +57,10 @@ and execute_binary_add l r = | Value.Float x, Value.Int y -> Value.Float (x +. float_of_int y) | Value.Int x, Value.Float y -> Value.Float (float_of_int x +. y) | Value.Float x, Value.Float y -> Value.Float (x +. y) - | (Value.Int _ | Value.Float _), _ | _, (Value.Int _ | Value.Float _) | _ -> - raise_notrace (Invalid_argument "Trying to add non numeric values.") + | Char a, Char b -> Value.Char Uchar.(of_int (to_int a + to_int b)) + | Char a, Int b -> Value.Char Uchar.(of_int (to_int a + b)) + | Int a, Char b -> Value.Char Uchar.(of_int (a + to_int b)) + | _ -> raise_notrace (Invalid_argument "Trying to add non numeric values.") and execute_binary_sub l r = match (l, r) with @@ -66,8 +68,10 @@ and execute_binary_sub l r = | Value.Float x, Value.Int y -> Value.Float (x -. float_of_int y) | Value.Int x, Value.Float y -> Value.Float (float_of_int x -. y) | Value.Float x, Value.Float y -> Value.Float (x -. y) - | (Value.Int _ | Value.Float _), _ | _, (Value.Int _ | Value.Float _) | _ -> - raise_notrace (Invalid_argument "Trying to subtract non numeric values.") + | Char a, Char b -> Value.Char Uchar.(of_int (to_int a - to_int b)) + | Char a, Int b -> Value.Char Uchar.(of_int (to_int a - b)) + | Int a, Char b -> Value.Char Uchar.(of_int (a - to_int b)) + | _ -> raise_notrace (Invalid_argument "Trying to subtract non numeric values.") and execute_binary_times l r = match (l, r) with @@ -75,8 +79,10 @@ and execute_binary_times l r = | Value.Float x, Value.Int y -> Value.Float (x *. float_of_int y) | Value.Int x, Value.Float y -> Value.Float (float_of_int x *. y) | Value.Float x, Value.Float y -> Value.Float (x *. y) - | (Value.Int _ | Value.Float _), _ | _, (Value.Int _ | Value.Float _) | _ -> - raise_notrace (Invalid_argument "Trying to multiply non numeric values.") + | Char a, Char b -> Value.Char Uchar.(of_int (to_int a * to_int b)) + | Char a, Int b -> Value.Char Uchar.(of_int (to_int a * b)) + | Int a, Char b -> Value.Char Uchar.(of_int (a * to_int b)) + | _ -> raise_notrace (Invalid_argument "Trying to multiply non numeric values.") and execute_binary_div l r = match (l, r) with @@ -125,7 +131,7 @@ and execute_binary_concat l r = | Value.String a, Value.String b -> Buffer.add_string buf a; Buffer.add_string buf b - (* | Value.String a, Value.Char b -> + | Value.String a, Value.Char b -> Buffer.add_string buf a; Buffer.add_utf_8_uchar buf b | Value.Char a, Value.String b -> @@ -133,7 +139,7 @@ and execute_binary_concat l r = Buffer.add_string buf b | Value.Char a, Value.Char b -> Buffer.add_utf_8_uchar buf a; - Buffer.add_utf_8_uchar buf b *) + Buffer.add_utf_8_uchar buf b | _ -> raise_notrace (Invalid_argument "Trying to concat non string literals.") in Value.String (Buffer.contents buf) @@ -151,7 +157,7 @@ and execute_binary_bracket_access l r = match (l, r) with | Value.Array a, Value.Int b -> ( try Array.get a b with Invalid_argument _ -> Value.Null) - (* | Value.String a, Value.Int b -> ( + | Value.String a, Value.Int b -> ( try let chr = a @@ -160,7 +166,7 @@ and execute_binary_bracket_access l r = |> Fun.flip List.nth b in Value.Char chr - with Failure _ | Invalid_argument _ -> Value.Null) *) + with Failure _ | Invalid_argument _ -> Value.Null) | Record a, String b -> a |> StringMap.find_opt b |> Option.value ~default:Value.Null | Null, _ -> Value.Null | Array _, _ -> diff --git a/test/vm/char.pi b/test/vm/char.pi new file mode 100644 index 0000000..a2dbe9f --- /dev/null +++ b/test/vm/char.pi @@ -0,0 +1,3 @@ +component Char { + 'c' + 1 +} diff --git a/test/vm/run.t b/test/vm/run.t index 671b9d4..5775574 100644 --- a/test/vm/run.t +++ b/test/vm/run.t @@ -251,6 +251,15 @@ Unbound identifier `one` [1] + $ NO_COLOR="1" print_vm . Char + d + + $ NO_COLOR="1" print_instructions . Char + 0000 I_Constant 0x00000001 (00000001) + 0005 I_Constant 0x00000002 (00000002) + 0010 I_Add + 0011 I_Pop + $ NO_COLOR="1" print_vm . String Hello! -- 2.51.2