Commit 79c06084 authored by Jun Furuse's avatar Jun Furuse

Very rough implementation of --scaml-revert, which is to revert SCaml...

Very rough implementation of --scaml-revert, which is to revert SCaml expression from a Michelson value and its SCaml type
parent de93f54c
......@@ -12,9 +12,9 @@ If you are not familiar with OCaml, please learn it first.
The compiler `scamlc` has almost the same interface as `ocamlc`.
`scamlc xxx.ml` compiles `xxx.ml` to `xxx.tz`.
### Converrsion mode: `scamlc --scaml-convert`
### Conversion mode: `scamlc --scaml-convert`
There is a SCaml specific compiler switch `--scaml-convert`.
SCaml specific compiler switch `--scaml-convert`.
With this option, `scamlc` command takes a `.ml` and print Michelson representations of
ML constants and types to stdout. The conversion targets must be defined as toplevel
declarations. For example:
......@@ -50,3 +50,35 @@ v: Right (Right { Pair "jon" (Pair 18 10000000000) ; Pair "dow" (Pair 50 1000000
Note that the values must be constants. Constructors and types can refer to types
defined in other modules, as far as they are already compiled to `.cmi` files.
### Revert mode: `scamlc --scaml-revert file`
SCaml specific compiler switch `--scaml-revert file`, where `file` is a file name
which contains Michelson constant expression.
With this option, `scamlc` command takes a `.ml` of one type definition, then translate
the Michelson constant expression in `file` as an SCaml value of the type in `.ml`,
then print out the SCaml expression to stdout. For example, suppose we have `hoo.ml`
of the example of `--scaml-convert`. Create `hoo_type.ml` with a type alias definition
of `Hoo.t`:
```ocaml
(* hoo_u.ml *)
type u = Hoo.u (* Refers the type defined in hoo.ml in the example of --scaml-convert *)
```
Prepare a file with the Michelson constant obtained in the example of the conversion:
```
/* value.tz */
Right (Right { Pair "jon" (Pair 18 10000000000) ; Pair "dow" (Pair 50 1000000) })
```
```shell
$ scamlc --scaml-revert value.tz hoo_u.ml
Boo
[{ name = "jon"; age = (Nat 18); salary = (Tz 10000.000000) };
{ name = "dow"; age = (Nat 50); salary = (Tz 1.000000) }]
```
Note that the values must be constants. Constructors and types can refer to types
defined in other modules, as far as they are already compiled to `.cmi` files.
......@@ -83,9 +83,19 @@ let convert _sourcefile _outputprefix _modulename (str, _coercion) =
Format.printf "%s: @[<2>%[email protected]]@." (Ident.name id) M.Constant.pp c
end) ts
let revert m _sourcefile _outputprefix _modulename (str, _coercion) =
match File.to_string m with
| Error (`Exn e) -> raise e
| Ok m ->
match Revert.do_revert str m with
| Error e -> failwith e
| Ok parsetree ->
Format.eprintf "%[email protected]" Pprintast.expression parsetree
let compile sourcefile outputprefix modulename (typedtree, coercion) =
let f =
if !Flags.flags.scaml_convert then convert
else implementation
let f = match !Flags.flags.scaml_mode with
| None | Some Compile -> implementation
| Some Convert -> convert
| Some (Revert s) -> revert s
in
f sourcefile outputprefix modulename (typedtree, coercion)
......@@ -16,18 +16,28 @@ open Spotlib.Spot
open Ocaml_conv.Default
type t =
type mode =
| Compile
| Convert
| Revert of string
and t =
{ iml_optimization : bool
; iml_pattern_match : bool
; scaml_debug : bool
; scaml_convert : bool
; scaml_mode : mode option
; scaml_noscamlib : bool
; dump_iml0 : bool
; dump_iml : bool
} [@@deriving conv{ocaml}]
let pp = Camlon.Ocaml.format_with ocaml_of_t
let set_mode t m =
match t.scaml_mode with
| None -> { t with scaml_mode = Some m }
| Some _ -> failwith "You cannot change SCaml running mode twice"
let eval flags (k, v) =
let must_be_a_bool () = Error "attribute type error: must be a bool" in
match String.concat "." & Longident.flatten k, v with
......@@ -37,8 +47,12 @@ let eval flags (k, v) =
| "iml_pattern_match", _ -> must_be_a_bool ()
| "scaml_debug", `Bool b -> Ok { flags with scaml_debug= b }
| "scaml_debug", _ -> must_be_a_bool ()
| "scaml_convert", `Bool b -> Ok { flags with scaml_convert= b }
| "scaml_convert", _ -> must_be_a_bool ()
(*
| "scaml_convert", `Unit -> set_mode flags Convert
| "scaml_convert", _ -> must_be_a_unit ()
| "scaml_revert", `String s -> set_mode flags (Revert s)
| "scaml_revert", _ -> must_be_a_unit ()
*)
| "scaml_noscamlib", `Bool b -> Ok { flags with scaml_noscamlib= b }
| "scaml_noscamlib", _ -> must_be_a_bool ()
| "dump_iml0", `Bool b -> Ok { flags with dump_iml0= b }
......@@ -51,7 +65,7 @@ let flags = ref
{ iml_optimization = true
; iml_pattern_match = true
; scaml_debug = begin try ignore (Sys.getenv "SCAML_DEBUG"); true with _ -> false end
; scaml_convert = false
; scaml_mode = None
; scaml_noscamlib = false
; dump_iml0 = false
; dump_iml = false
......
......@@ -14,15 +14,20 @@
open Spotlib.Spot
type t =
{ iml_optimization : bool
type mode =
| Compile
| Convert
| Revert of string
and t =
{ iml_optimization : bool
; iml_pattern_match : bool
; scaml_debug : bool
; scaml_convert : bool (** type and value conversion mode *)
; scaml_noscamlib : bool (** do not add -I `opam config var prefix`/scaml *)
; dump_iml0 : bool
; dump_iml : bool
}
; scaml_debug : bool
; scaml_mode : mode option
; scaml_noscamlib : bool (** do not add -I `opam config var prefix`/scaml *)
; dump_iml0 : bool
; dump_iml : bool
} [@@deriving conv{ocaml}]
val flags : t ref
......@@ -30,3 +35,4 @@ val pp : Format.t -> t -> unit
val eval : t -> Longident.t * [`Bool of bool | `Constant of Parsetree.constant ] -> (t, string) Result.t
val update : (t -> t) -> unit
val if_debug : (unit -> unit) -> unit
val set_mode : t -> mode -> t
......@@ -206,8 +206,10 @@ let main () =
(* SCaml *)
; "--scaml-debug", Arg.Unit (fun () -> Flags.(flags := { !flags with scaml_debug = true })),
"Print SCaml debug messages"
; "--scaml-convert", Arg.Unit (fun () -> Flags.(flags := { !flags with scaml_convert = true })),
; "--scaml-convert", Arg.Unit (fun () -> Flags.(flags := set_mode !flags Convert)),
"Convert types and values, instead of compling a smart contract"
; "--scaml-revert", Arg.String (fun s -> Flags.(flags := set_mode !flags (Revert s))),
"Revert values, instead of compling a smart contract"
; "--scaml-noscamlib", Arg.Unit (fun () -> Flags.(flags := { !flags with scaml_noscamlib = true })),
"Do not add default directory for SCamlib to the list of include directories"
; "--scaml-version", Arg.Unit (fun () ->
......
This diff is collapsed.
val do_revert : Typedtree.structure -> string -> (Parsetree.expression, string) result
(* hoo.ml *)
open SCaml
type t =
{ name : string
; age : nat
; salary : tz
}
and u =
| Foo of int * tz * string
| Bar
| Boo of t list
| Far
let v = Boo [ { name= "jon"; age= Nat 18; salary= Tz 10000.0 }
; { name= "dow"; age= Nat 50; salary= Tz 1.0 }
]
Right (Right { Pair "jon" (Pair 18 10000000000) ; Pair "dow" (Pair 50 1000000) })
open SCaml
open App_vote
let initial_storage = {
config = { title = "Do you like curry?" (* 投票のタイトルを設定 *)
; beginning_time = Timestamp "2020-01-01T00:00:00Z" (* 投票の開始時刻を設定 *)
; finish_time = Timestamp "2020-12-31T23:59:59Z" (* 投票の終了時刻を設定 *)
}
; candidates = Map [ ("Yes", Int 0); ("No", Int 0) ] (* 票数は0で初期化 *)
; voters = Set [] (* 初期状態で投票済みのアドレスはない *)
}
......@@ -197,7 +197,7 @@ let rec type_expr tyenv ty =
fn tyenv t >>= fun t -> Ok (tyOption t)
| Tconstr (p, [], _) when p = Predef.path_unit -> Ok (tyUnit)
| Tconstr (p, [], _) when p = Predef.path_string -> Ok (tyString)
| Tconstr (p, [], _) when p = Predef.path_bytes -> Ok (tyBytes)
(* | Tconstr (p, [], _) when p = Predef.path_bytes -> Ok (tyBytes) *)
| Tconstr (p, tys, _) ->
let rec f res = function
| [] -> Ok (List.rev res)
......
......@@ -22,3 +22,4 @@ val implementation
val convert
: Typedtree.structure
-> [> `Type of Ident.t * Michelson.Type.t | `Value of Ident.t option * IML.t ] list
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment