blob: 1372e94ea36774e98e1d80850d8159e40521ed35 [file] [log] [blame] [edit]
open Util
open Sexpr
open Source
open Xl
open Il
open Ast
(* Literal *)
let bool b = Atom (Bool.to_string b)
let text t = Atom ("\"" ^ String.escaped t ^ "\"")
let id x = text x.it
let mixop op = text (Mixop.to_string op)
let num = function
| `Nat n -> Node ("nat", [Atom (Z.to_string n)])
| `Int i -> Node ("int", [Atom ((if i >= Z.zero then "+" else "-") ^ Z.to_string (Z.abs i))])
| `Rat q -> Node ("rat", [Atom (Z.to_string (Q.num q) ^ "/" ^ Z.to_string (Q.den q))])
| `Real r -> Node ("real", [Atom (Printf.sprintf "%.17g" r)])
(* Operators *)
let unop = function
| `NotOp -> Atom "not"
| `PlusOp -> Atom "plus"
| `MinusOp -> Atom "minus"
| `PlusMinusOp -> Atom "plusminus"
| `MinusPlusOp -> Atom "minusplus"
let binop = function
| `AndOp -> Atom "and"
| `OrOp -> Atom "or"
| `ImplOp -> Atom "impl"
| `EquivOp -> Atom "equiv"
| `AddOp -> Atom "add"
| `SubOp -> Atom "sub"
| `MulOp -> Atom "mul"
| `DivOp -> Atom "div"
| `ModOp -> Atom "mod"
| `PowOp -> Atom "pow"
let cmpop = function
| `EqOp -> Atom "eq"
| `NeOp -> Atom "ne"
| `LtOp -> Atom "lt"
| `GtOp -> Atom "gt"
| `LeOp -> Atom "le"
| `GeOp -> Atom "ge"
(* Iterations *)
let rec iter = function
| Opt -> Atom "opt"
| List -> Atom "list"
| List1 -> Atom "list1"
| ListN (e, xo) -> Node ("listn", [exp e] @ List.map id (Option.to_list xo))
(* Types *)
and booltyp t = Atom (Bool.string_of_typ t)
and numtyp t = Atom (Num.string_of_typ t)
and optyp = function
| #Bool.typ as t -> booltyp t
| #Num.typ as t -> numtyp t
and typ t =
match t.it with
| VarT (x, as1) -> Node ("var", [id x] @ List.map arg as1)
| BoolT -> Atom "bool"
| NumT t -> numtyp t
| TextT -> Atom "text"
| TupT ets -> Node ("tup", List.map typbind ets)
| IterT (t1, it) -> Node ("iter", [typ t1; iter it])
and deftyp dt =
match dt.it with
| AliasT t -> Node ("alias", [typ t])
| StructT tfs -> Node ("struct", List.map typfield tfs)
| VariantT tcs -> Node ("variant", List.map typcase tcs)
and typbind (x, t) =
Node ("bind", [id x; typ t])
and typfield (at, (t, qs, prs), _hints) =
Node ("field", mixop (Mixop.Atom at) :: typ t :: List.map param qs @ List.map prem prs)
and typcase (op, (t, qs, prs), _hints) =
Node ("case", mixop op :: typ t :: List.map param qs @ List.map prem prs)
(* Expressions *)
and exp e =
match e.it with
| VarE x -> Node ("var", [id x])
| BoolE b -> Node ("bool", [bool b])
| NumE n -> Node ("num", [num n])
| TextE t -> Node ("text", [text t])
| UnE (op, t, e2) -> Node ("un", [unop op; optyp t; exp e2])
| BinE (op, t, e1, e2) -> Node ("bin", [binop op; optyp t; exp e1; exp e2])
| CmpE (op, t, e1, e2) -> Node ("cmp", [cmpop op; optyp t; exp e1; exp e2])
| IdxE (e1, e2) -> Node ("idx", [exp e1; exp e2])
| SliceE (e1, e2, e3) -> Node ("slice", [exp e1; exp e2; exp e3])
| UpdE (e1, p, e2) -> Node ("upd", [exp e1; path p; exp e2])
| ExtE (e1, p, e2) -> Node ("ext", [exp e1; path p; exp e2])
| StrE efs -> Node ("struct", List.map expfield efs)
| DotE (e1, at) -> Node ("dot", [exp e1; mixop (Mixop.Atom at)])
| CompE (e1, e2) -> Node ("comp", [exp e1; exp e2])
| MemE (e1, e2) -> Node ("mem", [exp e1; exp e2])
| LenE e1 -> Node ("len", [exp e1])
| TupE es -> Node ("tup", List.map exp es)
| CallE (x, as1) -> Node ("call", id x :: List.map arg as1)
| IterE (e1, it) -> Node ("iter", [exp e1] @ iterexp it)
| ProjE (e1, i) -> Node ("proj", [exp e1; Atom (string_of_int i)])
| CaseE (op, e1) -> Node ("case", [mixop op; exp e1])
| UncaseE (e1, op) -> Node ("uncase", [exp e1; mixop op])
| OptE eo -> Node ("opt", List.map exp (Option.to_list eo))
| TheE e1 -> Node ("unopt", [exp e1])
| ListE es -> Node ("list", List.map exp es)
| LiftE e1 -> Node ("lift", [exp e1])
| CatE (e1, e2) -> Node ("cat", [exp e1; exp e2])
| CvtE (e1, nt1, nt2) -> Node ("cvt", [numtyp nt1; numtyp nt2; exp e1])
| SubE (e1, t1, t2) -> Node ("sub", [typ t1; typ t2; exp e1])
and expfield (at, e) =
Node ("field", [mixop (Mixop.Atom at); exp e])
and path p =
match p.it with
| RootP -> Atom "root"
| IdxP (p1, e) -> Node ("idx", [path p1; exp e])
| SliceP (p1, e1, e2) -> Node ("slice", [path p1; exp e1; exp e2])
| DotP (p1, at) -> Node ("dot", [path p1; mixop (Mixop.Atom at)])
and iterexp (it, xes) =
iter it :: List.map (fun (x, e) -> Node ("dom", [id x; exp e])) xes
(* Grammars *)
and sym g =
match g.it with
| VarG (x, as1) -> Node ("var", id x :: List.map arg as1)
| NumG n -> Node ("num", [Atom (Printf.sprintf "0x%02X" n)])
| TextG t -> Node ("text", [text t])
| EpsG -> Atom "eps"
| SeqG gs -> Node ("seq", List.map sym gs)
| AltG gs -> Node ("alt", List.map sym gs)
| RangeG (g1, g2) -> Node ("range", [sym g1; sym g2])
| IterG (g1, it) -> Node ("iter", [sym g1] @ iterexp it)
| AttrG (e, g1) -> Node ("attr", [exp e; sym g1])
(* Premises *)
and prem pr =
match pr.it with
| RulePr (x, as1, op, e) -> Node ("rule", id x :: List.map arg as1 @ [mixop op; exp e])
| IfPr e -> Node ("if", [exp e])
| LetPr (e1, e2, _xs) -> Node ("let", [exp e1; exp e2])
| ElsePr -> Atom "else"
| IterPr (pr1, it) -> Node ("iter", [prem pr1] @ iterexp it)
(* Definitions *)
and arg a =
match a.it with
| ExpA e -> Node ("exp", [exp e])
| TypA t -> Node ("typ", [typ t])
| DefA x -> Node ("def", [id x])
| GramA g -> Node ("gram", [sym g])
and param p =
match p.it with
| ExpP (x, t) -> Node ("exp", [id x; typ t])
| TypP x -> Node ("typ", [id x])
| DefP (x, ps, t) -> Node ("def", [id x] @ List.map param ps @ [typ t])
| GramP (x, ps, t) -> Node ("gram", [id x] @ List.map param ps @ [typ t])
let inst inst =
match inst.it with
| InstD (ps, as_, dt) ->
Node ("inst", List.map param ps @ List.map arg as_ @ [deftyp dt])
let rule rule =
match rule.it with
| RuleD (x, ps, op, e, prs) ->
Node ("rule", [id x] @ List.map param ps @ [mixop op; exp e] @ List.map prem prs)
let clause clause =
match clause.it with
| DefD (ps, as_, e, prs) ->
Node ("clause", List.map param ps @ List.map arg as_ @ [exp e] @ List.map prem prs)
let prod prod =
match prod.it with
| ProdD (ps, g, e, prs) ->
Node ("prod", List.map param ps @ [sym g; exp e] @ List.map prem prs)
let rec def d =
match d.it with
| TypD (x, ps, insts) ->
Node ("typ", [id x] @ List.map param ps @ List.map inst insts)
| RelD (x, ps, op, t, rules) ->
Node ("rel", [id x] @ List.map param ps @ [mixop op; typ t] @ List.map rule rules)
| DecD (x, ps, t, clauses) ->
Node ("def", [id x] @ List.map param ps @ [typ t] @ List.map clause clauses)
| GramD (x, ps, t, prods) ->
Node ("gram", [id x] @ List.map param ps @ [typ t] @ List.map prod prods)
| RecD ds ->
Node ("rec", List.map def ds)
| HintD _ ->
Atom ""
(* Scripts *)
let script ds =
List.filter ((<>) (Atom "")) (List.map def ds)
(* Printing *)
open Config
let output_typ oc cfg t = Sexpr.output oc cfg.width (typ t)
let output_exp oc cfg e = Sexpr.output oc cfg.width (exp e)
let output_def oc cfg d = Sexpr.output oc cfg.width (def d)
let output_script oc cfg s = List.iter (Sexpr.output oc cfg.width) (script s)
let string_of_typ cfg t = Sexpr.to_string cfg.width (typ t)
let string_of_exp cfg e = Sexpr.to_string cfg.width (exp e)
let string_of_def cfg d = Sexpr.to_string cfg.width (def d)
let string_of_script cfg s =
String.concat "\n" (List.map (Sexpr.to_string cfg.width) (script s))