From bf05e738e2eadad014deaf2b40ce51a4c0b56fad Mon Sep 17 00:00:00 2001 From: Emin Arslan Date: Sun, 17 May 2026 21:32:48 +0300 Subject: [PATCH] compiler and vm: added modulo, rem and abs --- lib/compiler/scope_analysis.ml | 5 ++++- lib/vm/native.ml | 35 +++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/compiler/scope_analysis.ml b/lib/compiler/scope_analysis.ml index 1d71bc5..d7147ec 100644 --- a/lib/compiler/scope_analysis.ml +++ b/lib/compiler/scope_analysis.ml @@ -61,7 +61,10 @@ let default_global_table = ("+", (1, Native 1)); ("-", (2, Native 2)); ("*", (3, Native 3)); - ("/", (4, Native 4)) + ("/", (4, Native 4)); + ("ABS", (5, Native 5)); + ("MOD", (6, Native 6)); + ("REM", (7, Native 7)) ] (* extract all defined global symbols, given the top-level expressions diff --git a/lib/vm/native.ml b/lib/vm/native.ml index e107c6b..e22f5a2 100644 --- a/lib/vm/native.ml +++ b/lib/vm/native.ml @@ -34,6 +34,20 @@ let numeric_mul = numeric_generic ( * ) ( *. ) let numeric_div x y = NDouble ((float_of_numeric x) /. (float_of_numeric y)) +module type Num = sig + type t + val add : t -> t -> t + val zero : t + val rem : t -> t -> t +end + +let aux_mod (type a) (module M : Num with type t = a) (x:a) (y:a) = + let z = M.rem x y in + if z < M.zero then M.add z y else z +let numeric_mod = numeric_generic (aux_mod (module Int)) (aux_mod (module Float)) +let numeric_rem = numeric_generic (Int.rem) (Float.rem) + + let builtin_print (v : Types.value ref list) = List.iter (fun r -> print_endline (print_value !r)) v; Types.Nil @@ -57,13 +71,32 @@ let builtin_div vs = | f :: rest -> of_numeric (List.fold_left numeric_div (to_numeric !f) (List.map (fun r -> to_numeric !r) rest)) | [] -> failwith "invalid number of arguments for division: 0" +let make_single_func s f = function + | first :: [] -> f first + | v -> failwith ("invalid number of arguments for " ^s ^ ": " ^ (string_of_int (List.length v))) + +let make_two_func s f = function + | first :: second :: [] -> f first second + | v -> failwith ("invalid number of arguments for " ^ s ^ ": " ^ (string_of_int (List.length v))) + + +let builtin_abs = make_single_func "ABS" (fun f -> of_numeric (match to_numeric !f with + | NInt x -> NInt (Int.abs x) + | NDouble x -> NDouble (Float.abs x))) +let builtin_mod = + make_two_func "MOD" (fun x y -> of_numeric (numeric_mod (to_numeric !x) (to_numeric !y))) +let builtin_rem = + make_two_func "REM" (fun x y -> of_numeric (numeric_rem (to_numeric !x) (to_numeric !y))) let table = [| builtin_print; builtin_add; builtin_sub; builtin_mul; - builtin_div + builtin_div; + builtin_abs; + builtin_mod; + builtin_rem |]