Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect behavior of the sprintf macro #16

Open
OlivierNicole opened this issue Sep 30, 2022 · 2 comments
Open

Incorrect behavior of the sprintf macro #16

OlivierNicole opened this issue Sep 30, 2022 · 2 comments

Comments

@OlivierNicole
Copy link
Collaborator

There seems to be an incorrect shadowing when splicing a fast exponentiation macro. Using the following power.ml file:

type (_, _) fmt =
    Int : (int -> 'a, 'a) fmt
  | Lit : string -> ('a, 'a) fmt
  | Cat : ('a, 'b) fmt * ('b, 'c) fmt -> ('a, 'c) fmt

static (%) x y = Cat (x, y)

macro rec printk :
    type a b. (string expr -> b expr) -> (a, b) fmt -> a expr =
  fun k -> function
  | Int -> << fun s -> $(k <<string_of_int s>>) >>
  | Lit s -> k (Expr.of_string s)
  | Cat (l, r) ->
      printk (fun x ->
        printk (fun y -> k << $x ^ $y >>) r) l

macro sprintf fmt = printk (fun x -> x) fmt

static p = Lit "(" % Int % Lit "," % Int % Lit ")"

We get the following results in the toplevel at revision 05372c7:

# #use "power.ml";;
type (_, _) fmt =
    Int : (int -> 'a, 'a) fmt
  | Lit : string -> ('a, 'a) fmt
  | Cat : ('a, 'b) fmt * ('b, 'c) fmt -> ('a, 'c) fmt
static val ( % ) : ('a, 'b) fmt -> ('b, 'c) fmt -> ('a, 'c) fmt = <fun>
macro printk : (string expr -> 'b expr) -> ('a, 'b) fmt -> 'a expr = <fun>
macro sprintf : ('a, string) fmt -> 'a expr = <fun>
static val p : (int -> int -> '_a, '_a) fmt =
  Cat (Cat (Cat (Cat (Lit "(", Int), Lit ","), Int), Lit ")")
# sprintf p;;;
- : (int -> int -> string) expr =
<< (function s/1287
     (function s/1287
       (apply (field 15 (global Pervasives!))
         (apply (field 15 (global Pervasives!))
           (apply (field 15 (global Pervasives!))
             (apply (field 15 (global Pervasives!)) "("
               (apply (field 19 (global Pervasives!)) s/1287))
             ",")
           (apply (field 19 (global Pervasives!)) s/1287))
         ")"))) >>
# $(sprintf p) 1 3;;
- : string = "(3,3)"

The result string should be "(1,3)".

This example used to work at the time of this blog post so maybe a bug was introduced when switch from Parsetree to Lambda for the quotes?

@yallop
Copy link
Member

yallop commented Oct 14, 2022

Similarly (?),

$ cat splices.ml
macro one = << 1 >>
macro two = << 2 >>
macro three = << 3 >>

let () =
  begin
    Printf.printf "%d\n" $(one);
    Printf.printf "%d\n" $(two);
    Printf.printf "%d\n" $(three);
  end
$ ocaml splices.ml
1
1
1

@OlivierNicole
Copy link
Collaborator Author

I see why this is happening. Visibly I made an error when switch the quoting/splicing mechanisms from Parsetre to Lambda quotes.

| Texp_escape exp ->
begin
(* If toplevel splice *)
if Env.cur_stage e.exp_env = 0 then
match !splice_array with
| Some arr_ref ->
Array.get !arr_ref !splice_index

splice_index is never updated.
In addition, the contribution of 42a0061 which introduced a sane (i.e. not using mutable state) management of toplevel splices has somehow disappeared.

@yallop yallop changed the title Incorrect behavior of the power macro Incorrect behavior of the sprintf macro Mar 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants