How do I execute, as part of a ML{*…*} command, a string that contains ML source?

StackOverflow https://stackoverflow.com//questions/23006991

  •  21-12-2019
  •  | 
  •  

Question

From the Isabelle user list Makarius Wenzel says this:

It is also possible to pass around ML sources as strings or tokens in Isabelle/ML, and invoke the compiler on it. That is a normal benefit of incremental compilation.

I have an ML statement as a string, like this:

ML{* val source_string = "val x = 3 + 4"; *}

I want to use "val x = 3 + 4" as a ML statement in a ML{*...*} command. I can do it by calling Poly/ML externally like this:

ML{* 
fun polyp cmd = Isabelle_System.bash 
  ("perl -e 'print q(" ^ cmd ^ ");' | $ML_HOME/poly");
*}

ML{* polyp source_string; *}

That takes about 200ms. I figure it would be about 0ms if I could do it internally.

Update 140411

Makarius Wenzel may have another way to do things, but what I have below with ML_Context.eval_text is almost what I want. It's in line with what I've been experimenting with. The problem is that used_only_by_src1 is global. I can't put it in the let.

I suppose if I was using src1 in two different ML{*...*} commands, there's some short period of time in which used_only_by_src1 could be changed by the one before it was used by the other. But, I guess this is all part of learning about stateless programming.

ML{*
val src1 = "x + y" (*I would actually have a global list of sources.*)

val used_only_by_src1 = Unsynchronized.ref "";

fun two_int_arg_fun s1 s2 = let
    val s = "val x = " ^ s1 ^ "val y = " ^ s2 
             ^ "used_only_by_src1 := (Int.toString(" ^ src1 ^ "))";
    val _ = ML_Context.eval_text true Position.none s;
  in !used_only_by_src1 end;
*}

ML{*
  two_int_arg_fun;  
  two_int_arg_fun "44;" "778;"
  (*3ms*)
*}

Note 140412: Actually, I don't need to execute ML strings. I can program in ML like normal, since any ML{*...*} can access global ML functions, where I can write what I need.

The main solution I got from this is how to pass arguments to a string of Perl code, which I got here from trying to do it for ML, so thanks to davidg. Plus, ML_Context.exec and ML_Context.eval_text might come in useful somewhere, and learning enough to be able to use them is totally useful.

There is the problem of needing a local or global Unsynchronized.ref that's guaranteed to not be changed by some other code (or a non-mutable type), but surely there's a solution to that.

I didn't pursue ML_Context.exec because isar_syn.ML wasn't making any sense to me, but I've gotten as far as below, so now I'm asking, "What functions do I need that involve Context.generic -> Context.generic or Toplevel.transition -> Toplevel.transition, and what do those do for me as far as being able to get the return value of 3+4 in a ML{*...*}?"

I'm using grep with Isabelle_System.bash, and I've gotten as far as what's below, in looking for the right signatures in Isabelle/Pure. I throw in for free a grep I use to look for useful or needed functions in the Poly/ML Basis.

ML{*
Isabelle_System.bash ("grep -nr 'get_generic' $ISABELLE_HOME/src/Pure");
Isabelle_System.bash ("grep -nr 'hash' $ML_HOME/../src/Basis/*");

Config.get_generic;

(*From use at line 265 of isar_syn.ML.*)
ML_Context.exec;
ML_Context.exec (fn () => ML_Context.eval_text true Position.none "3 + 4");
  (*OUT: val it = fn: Context.generic -> Context.generic*)  

(fn (txt, pos) =>
      Toplevel.generic_theory
        (ML_Context.exec (fn () => ML_Context.eval_text true pos txt) #>
          Local_Theory.propagate_ml_env)) ("3 + 4", Position.none);
  (*OUT: val it = fn: Toplevel.transition -> Toplevel.transition*)
*}
Was it helpful?

Solution

The structure ML_Context might be a good starting point to look. For instance, your expression can be executed as so:

ML {*
  ML_Context.eval_text true Position.none "val x = 3 + 4"
*}

This will internally evaluate the expression 3 + 4, and throw away the results.

Functions like ML_Context.exec will allow you to capture the results of expressions and put them into your local context; you might want to look at implementation of the ML Isar command in src/Pure/Isar/isar_syn.ML to see how such functions are used in practice.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top