refactor(wpcarro/compiler): Modularize debug fns
Define `debug.ml` and `prettify.ml` to clean-up some code. Change-Id: Iee2e1ed666f2ccb5e56cc50054ca85b8ba513f3b Reviewed-on: https://cl.tvl.fyi/c/depot/+/7078 Tested-by: BuildkiteCI Reviewed-by: wpcarro <wpcarro@gmail.com>
This commit is contained in:
parent
a8876a4cda
commit
1e9c3955bf
7 changed files with 91 additions and 85 deletions
66
users/wpcarro/scratch/compiler/debug.ml
Normal file
66
users/wpcarro/scratch/compiler/debug.ml
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
open Types
|
||||||
|
|
||||||
|
(* Print x prefixed with tag and return x unchanged. *)
|
||||||
|
let print (f : 'a -> string) (tag : string) (x : 'a) : 'a =
|
||||||
|
Printf.printf "%s: %s\n" tag (f x);
|
||||||
|
x
|
||||||
|
|
||||||
|
let rec ast (tree : Types.value) : string =
|
||||||
|
match tree with
|
||||||
|
| ValueLiteral (LiteralBool x) ->
|
||||||
|
Printf.sprintf "ValueLiteral (LiteralBool %s)" (string_of_bool x)
|
||||||
|
| ValueLiteral (LiteralInt x) ->
|
||||||
|
Printf.sprintf "ValueLiteral (LiteralInt %s)" (string_of_int x)
|
||||||
|
| ValueVariable x ->
|
||||||
|
Printf.sprintf "ValueVariable %s" x
|
||||||
|
| ValueFunction (x, body) ->
|
||||||
|
Printf.sprintf "ValueFunction (%s, %s)" x (ast body)
|
||||||
|
| ValueApplication (f, x) ->
|
||||||
|
Printf.sprintf "ValueApplication (%s, %s)" (ast f) (ast x)
|
||||||
|
| ValueVarApplication (f, x) ->
|
||||||
|
Printf.sprintf "ValueVarApplication (%s, %s)" f (ast x)
|
||||||
|
| ValueBinder (k, v, x) ->
|
||||||
|
Printf.sprintf "ValueBinder (%s, %s, %s)" k (ast v) (ast x)
|
||||||
|
|
||||||
|
let rec value (x : value) : string =
|
||||||
|
match x with
|
||||||
|
| ValueLiteral (LiteralInt x) ->
|
||||||
|
Printf.sprintf "Int %d" x
|
||||||
|
| ValueLiteral (LiteralBool x) ->
|
||||||
|
Printf.sprintf "Bool %b" x
|
||||||
|
| ValueVariable x ->
|
||||||
|
Printf.sprintf "Var %s" x
|
||||||
|
| ValueFunction (name, x) ->
|
||||||
|
Printf.sprintf "Fn %s %s" name (value x)
|
||||||
|
| ValueApplication (f, x) ->
|
||||||
|
Printf.sprintf "App %s %s" (value f) (value x)
|
||||||
|
| ValueVarApplication (name, x) ->
|
||||||
|
Printf.sprintf "App %s %s" name (value x)
|
||||||
|
| ValueBinder (name, x, body) ->
|
||||||
|
Printf.sprintf "Bind %s %s %s" name (value x) (value body)
|
||||||
|
|
||||||
|
let rec type' (t : _type) : string =
|
||||||
|
match t with
|
||||||
|
| TypeInt -> "Integer"
|
||||||
|
| TypeBool -> "Boolean"
|
||||||
|
| TypeVariable k -> Printf.sprintf "%s" k
|
||||||
|
| TypeArrow (a, b) -> Printf.sprintf "%s -> %s" (type' a) (type' b)
|
||||||
|
|
||||||
|
let quantified_type (q : quantified_type) : string =
|
||||||
|
let QuantifiedType (vars, t) = q in
|
||||||
|
if List.length vars == 0 then
|
||||||
|
Printf.sprintf "%s" (type' t)
|
||||||
|
else
|
||||||
|
Printf.sprintf "forall %s. %s" (String.concat "," vars) (type' t)
|
||||||
|
|
||||||
|
let substitution (s : substitution) : string =
|
||||||
|
FromString.fold (fun k v acc -> Printf.sprintf "%s\"%s\" |-> %s;" acc k (type' v)) s ""
|
||||||
|
|> Printf.sprintf "{ %s }"
|
||||||
|
|
||||||
|
let env (s : env) : string =
|
||||||
|
FromString.fold (fun k v acc -> Printf.sprintf "%s\"%s\" |-> %s;" acc k (quantified_type v)) s ""
|
||||||
|
|> Printf.sprintf "{ %s }"
|
||||||
|
|
||||||
|
let inference (Inference (s, t)) =
|
||||||
|
Printf.sprintf "type: %s; sub: %s" (type' t) (substitution s)
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
|
|
||||||
open Parser
|
open Parser
|
||||||
open Inference
|
open Inference
|
||||||
|
open Debug
|
||||||
|
open Prettify
|
||||||
|
|
||||||
let to_array (q : 'a Queue.t) : 'a array =
|
let to_array (q : 'a Queue.t) : 'a array =
|
||||||
let result = Array.make (Queue.length q) "" in
|
let result = Array.make (Queue.length q) "" in
|
||||||
|
@ -149,27 +151,6 @@ let parse_language (x : string) : Types.value option =
|
||||||
print_tokens tokens;
|
print_tokens tokens;
|
||||||
parse_expression (new parser tokens)
|
parse_expression (new parser tokens)
|
||||||
|
|
||||||
let rec debug (ast : Types.value) : string =
|
|
||||||
match ast with
|
|
||||||
| ValueLiteral (LiteralBool x) ->
|
|
||||||
Printf.sprintf "ValueLiteral (LiteralBool %s)" (string_of_bool x)
|
|
||||||
| ValueLiteral (LiteralInt x) ->
|
|
||||||
Printf.sprintf "ValueLiteral (LiteralInt %s)" (string_of_int x)
|
|
||||||
| ValueVariable x ->
|
|
||||||
Printf.sprintf "ValueVariable %s" x
|
|
||||||
| ValueFunction (x, body) ->
|
|
||||||
Printf.sprintf "ValueFunction (%s, %s)" x (debug body)
|
|
||||||
| ValueApplication (f, x) ->
|
|
||||||
Printf.sprintf "ValueApplication (%s, %s)" (debug f) (debug x)
|
|
||||||
| ValueVarApplication (f, x) ->
|
|
||||||
Printf.sprintf "ValueVarApplication (%s, %s)" f (debug x)
|
|
||||||
| ValueBinder (k, v, x) ->
|
|
||||||
Printf.sprintf "ValueBinder (%s, %s, %s)" k (debug v) (debug x)
|
|
||||||
|
|
||||||
let debug_ast (ast : Types.value) : Types.value =
|
|
||||||
ast |> debug |> Printf.sprintf "ast: %s" |> print_string |> print_newline;
|
|
||||||
ast
|
|
||||||
|
|
||||||
let main =
|
let main =
|
||||||
while true do
|
while true do
|
||||||
begin
|
begin
|
||||||
|
@ -177,14 +158,14 @@ let main =
|
||||||
let x = read_line () in
|
let x = read_line () in
|
||||||
match parse_language x with
|
match parse_language x with
|
||||||
| Some ast ->
|
| Some ast ->
|
||||||
(match ast |> debug_ast |> do_infer with
|
(match ast |> Debug.print Debug.ast "ast" |> do_infer with
|
||||||
| None ->
|
| None ->
|
||||||
"Type-check failed"
|
"Type-check failed"
|
||||||
|> print_string
|
|> print_string
|
||||||
|> print_newline
|
|> print_newline
|
||||||
| Some x ->
|
| Some x ->
|
||||||
x
|
x
|
||||||
|> Types.pretty
|
|> Prettify.type'
|
||||||
|> print_string
|
|> print_string
|
||||||
|> print_newline)
|
|> print_newline)
|
||||||
| None ->
|
| None ->
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
******************************************************************************)
|
******************************************************************************)
|
||||||
|
|
||||||
open Types
|
open Types
|
||||||
|
open Debug
|
||||||
|
|
||||||
(*******************************************************************************
|
(*******************************************************************************
|
||||||
* Library
|
* Library
|
||||||
|
@ -107,25 +108,25 @@ let rec unify (a : _type) (b : _type) : substitution option =
|
||||||
let* s1 = unify a c in
|
let* s1 = unify a c in
|
||||||
let* s2 = unify (substitute_type s1 b) (substitute_type s1 d) in
|
let* s2 = unify (substitute_type s1 b) (substitute_type s1 d) in
|
||||||
let s3 = compose_substitutions [s1; s2] in
|
let s3 = compose_substitutions [s1; s2] in
|
||||||
s1 |> Types.debug_substitution |> Printf.sprintf "s1: %s\n" |> print_string;
|
s1 |> Debug.substitution |> Printf.sprintf "s1: %s\n" |> print_string;
|
||||||
s2 |> Types.debug_substitution |> Printf.sprintf "s2: %s\n" |> print_string;
|
s2 |> Debug.substitution |> Printf.sprintf "s2: %s\n" |> print_string;
|
||||||
s3 |> Types.debug_substitution |> Printf.sprintf "s3: %s\n" |> print_string;
|
s3 |> Debug.substitution |> Printf.sprintf "s3: %s\n" |> print_string;
|
||||||
Some s3
|
Some s3
|
||||||
| _ -> None
|
| _ -> None
|
||||||
|
|
||||||
let print_env (env : env) =
|
let print_env (env : env) =
|
||||||
Printf.sprintf "env: %s\n" (Types.debug_env env)
|
Printf.sprintf "env: %s\n" (Debug.env env)
|
||||||
|> print_string
|
|> print_string
|
||||||
|
|
||||||
let print_val (x : value) =
|
let print_val (x : value) =
|
||||||
Printf.sprintf "val: %s\n" (Types.debug_value x)
|
Printf.sprintf "val: %s\n" (Debug.value x)
|
||||||
|> print_string
|
|> print_string
|
||||||
|
|
||||||
let print_inference (x : inference option) =
|
let print_inference (x : inference option) =
|
||||||
match x with
|
match x with
|
||||||
| None -> "no inference\n" |> print_string
|
| None -> "no inference\n" |> print_string
|
||||||
| Some x ->
|
| Some x ->
|
||||||
Printf.sprintf "inf: %s\n" (Types.debug_inference x)
|
Printf.sprintf "inf: %s\n" (Debug.inference x)
|
||||||
|> print_string
|
|> print_string
|
||||||
|
|
||||||
let rec infer (env : env) (x : value) : inference option =
|
let rec infer (env : env) (x : value) : inference option =
|
||||||
|
|
9
users/wpcarro/scratch/compiler/prettify.ml
Normal file
9
users/wpcarro/scratch/compiler/prettify.ml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
open Types
|
||||||
|
|
||||||
|
(* Pretty-print the type, t. *)
|
||||||
|
let rec type' (t : _type) : string =
|
||||||
|
match t with
|
||||||
|
| TypeInt -> "Integer"
|
||||||
|
| TypeBool -> "Boolean"
|
||||||
|
| TypeVariable k -> Printf.sprintf "%s" k
|
||||||
|
| TypeArrow (a, b) -> Printf.sprintf "%s -> %s" (type' a) (type' b)
|
|
@ -6,7 +6,7 @@
|
||||||
because one of the goals was to see how similar this OCaml implementation
|
because one of the goals was to see how similar this OCaml implementation
|
||||||
could be to the Python implementation.
|
could be to the Python implementation.
|
||||||
|
|
||||||
Conclusion: It's pretty easily to switch between the two languages.
|
Conclusion: It's pretty easy to switch between the two languages.
|
||||||
|
|
||||||
Usage: Recommended compilation settings I hastily found online:
|
Usage: Recommended compilation settings I hastily found online:
|
||||||
$ ocamlopt -w +A-42-48 -warn-error +A-3-44 ./register_vm.ml && ./a.out
|
$ ocamlopt -w +A-42-48 -warn-error +A-3-44 ./register_vm.ml && ./a.out
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
******************************************************************************)
|
******************************************************************************)
|
||||||
|
|
||||||
open Types
|
open Types
|
||||||
|
open Prettify
|
||||||
open Parser
|
open Parser
|
||||||
open Inference
|
open Inference
|
||||||
|
|
||||||
|
@ -20,10 +21,7 @@ type side = LHS | RHS
|
||||||
let ( let* ) = Option.bind
|
let ( let* ) = Option.bind
|
||||||
|
|
||||||
let printsub (s : substitution) =
|
let printsub (s : substitution) =
|
||||||
FromString.fold (fun k v acc -> Printf.sprintf "%s\"%s\" |-> %s;" acc k (pretty v)) s ""
|
s |> Debug.substitution |> print_string |> print_newline
|
||||||
|> Printf.sprintf "Sub { %s }"
|
|
||||||
|> print_string
|
|
||||||
|> print_newline
|
|
||||||
|
|
||||||
let to_array (q : 'a Queue.t) : 'a array =
|
let to_array (q : 'a Queue.t) : 'a array =
|
||||||
let result = Array.make (Queue.length q) "" in
|
let result = Array.make (Queue.length q) "" in
|
||||||
|
@ -80,7 +78,7 @@ let print_tokens (xs : string array) =
|
||||||
|> print_string |> print_newline
|
|> print_string |> print_newline
|
||||||
|
|
||||||
let print_type (t : _type) =
|
let print_type (t : _type) =
|
||||||
t |> pretty |> Printf.sprintf "type: %s" |> print_string |> print_newline
|
t |> Debug.type' |> Printf.sprintf "type: %s" |> print_string |> print_newline
|
||||||
|
|
||||||
let parse_input (x : string) : _type option =
|
let parse_input (x : string) : _type option =
|
||||||
let tokens = tokenize x in
|
let tokens = tokenize x in
|
||||||
|
@ -109,7 +107,7 @@ let main =
|
||||||
let rhs = read_type RHS in
|
let rhs = read_type RHS in
|
||||||
match unify lhs rhs with
|
match unify lhs rhs with
|
||||||
| None ->
|
| None ->
|
||||||
Printf.printf "Cannot unify \"%s\" with \"%s\"\n" (pretty lhs) (pretty rhs)
|
Printf.printf "Cannot unify \"%s\" with \"%s\"\n" (Debug.type' lhs) (Debug.type' rhs)
|
||||||
| Some x -> printsub x
|
| Some x -> printsub x
|
||||||
end
|
end
|
||||||
done
|
done
|
||||||
|
|
|
@ -9,23 +9,6 @@ type value =
|
||||||
| ValueVarApplication of string * value
|
| ValueVarApplication of string * value
|
||||||
| ValueBinder of string * value * value
|
| ValueBinder of string * value * value
|
||||||
|
|
||||||
let rec debug_value (x : value) : string =
|
|
||||||
match x with
|
|
||||||
| ValueLiteral (LiteralInt x) ->
|
|
||||||
Printf.sprintf "Int %d" x
|
|
||||||
| ValueLiteral (LiteralBool x) ->
|
|
||||||
Printf.sprintf "Bool %b" x
|
|
||||||
| ValueVariable x ->
|
|
||||||
Printf.sprintf "Var %s" x
|
|
||||||
| ValueFunction (name, x) ->
|
|
||||||
Printf.sprintf "Fn %s %s" name (debug_value x)
|
|
||||||
| ValueApplication (f, x) ->
|
|
||||||
Printf.sprintf "App %s %s" (debug_value f) (debug_value x)
|
|
||||||
| ValueVarApplication (name, x) ->
|
|
||||||
Printf.sprintf "App %s %s" name (debug_value x)
|
|
||||||
| ValueBinder (name, x, body) ->
|
|
||||||
Printf.sprintf "Bind %s %s %s" name (debug_value x) (debug_value body)
|
|
||||||
|
|
||||||
module FromString = Map.Make (String)
|
module FromString = Map.Make (String)
|
||||||
|
|
||||||
type _type =
|
type _type =
|
||||||
|
@ -34,43 +17,11 @@ type _type =
|
||||||
| TypeVariable of string
|
| TypeVariable of string
|
||||||
| TypeArrow of _type * _type
|
| TypeArrow of _type * _type
|
||||||
|
|
||||||
let rec debug_type (t : _type) : string =
|
|
||||||
match t with
|
|
||||||
| TypeInt -> "Integer"
|
|
||||||
| TypeBool -> "Boolean"
|
|
||||||
| TypeVariable k -> Printf.sprintf "%s" k
|
|
||||||
| TypeArrow (a, b) -> Printf.sprintf "%s -> %s" (debug_type a) (debug_type b)
|
|
||||||
|
|
||||||
type quantified_type = QuantifiedType of string list * _type
|
type quantified_type = QuantifiedType of string list * _type
|
||||||
|
|
||||||
let debug_quantified_type (q : quantified_type) : string =
|
|
||||||
let QuantifiedType (vars, t) = q in
|
|
||||||
if List.length vars == 0 then
|
|
||||||
Printf.sprintf "%s" (debug_type t)
|
|
||||||
else
|
|
||||||
Printf.sprintf "forall %s. %s" (String.concat "," vars) (debug_type t)
|
|
||||||
|
|
||||||
type set = bool FromString.t
|
type set = bool FromString.t
|
||||||
type substitution = _type FromString.t
|
type substitution = _type FromString.t
|
||||||
|
|
||||||
let debug_substitution (s : substitution) : string =
|
|
||||||
FromString.fold (fun k v acc -> Printf.sprintf "%s\"%s\" |-> %s;" acc k (debug_type v)) s ""
|
|
||||||
|> Printf.sprintf "{ %s }"
|
|
||||||
|
|
||||||
type env = quantified_type FromString.t
|
type env = quantified_type FromString.t
|
||||||
|
|
||||||
let debug_env (s : env) : string =
|
|
||||||
FromString.fold (fun k v acc -> Printf.sprintf "%s\"%s\" |-> %s;" acc k (debug_quantified_type v)) s ""
|
|
||||||
|> Printf.sprintf "{ %s }"
|
|
||||||
|
|
||||||
type inference = Inference of substitution * _type
|
type inference = Inference of substitution * _type
|
||||||
|
|
||||||
let debug_inference (Inference (s, t)) =
|
|
||||||
Printf.sprintf "type: %s; sub: %s" (debug_type t) (debug_substitution s)
|
|
||||||
|
|
||||||
let rec pretty (t : _type) : string =
|
|
||||||
match t with
|
|
||||||
| TypeInt -> "Integer"
|
|
||||||
| TypeBool -> "Boolean"
|
|
||||||
| TypeVariable k -> Printf.sprintf "%s" k
|
|
||||||
| TypeArrow (a, b) -> Printf.sprintf "%s -> %s" (pretty a) (pretty b)
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue