summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-05-16 08:24:59 -0700
committerRose Hogenson <rosehogenson@posteo.net>2025-05-17 09:50:31 -0700
commit06624f3183f4d773cf1023cabe2e370ebba5dee1 (patch)
tree93742397b82037c81077507920096d5ac80d4e63
parentc2bb80335b590c9118bad0da1d4407942b3765de (diff)
downloadsml-06624f3183f4d773cf1023cabe2e370ebba5dee1.tar.zst
Use code generation for printing the AST
-rw-r--r--CPS.sml2
-rw-r--r--CodeGen.sml2
-rw-r--r--Compiler.sml10
-rw-r--r--Parser.sml13
-rw-r--r--ShowSyntax.sml190
-rw-r--r--Syntax.sml134
-rw-r--r--generate-show-syntax.sml66
-rw-r--r--main.sml1
-rw-r--r--program.cm1
9 files changed, 277 insertions, 142 deletions
diff --git a/CPS.sml b/CPS.sml
index 13dbbe8..e48cfcf 100644
--- a/CPS.sml
+++ b/CPS.sml
@@ -127,7 +127,7 @@ struct
, toCPS expr (fn v => go v sortedArms contFunc)
)
end
- | _ => raise Fail ("malformed expression " ^ Syntax.lexpToString e)
+ | _ => raise Fail ("malformed expression " ^ ShowSyntax.lexpToString e)
fun hoist (expr : Syntax.cexp) : Syntax.cexp =
let
diff --git a/CodeGen.sml b/CodeGen.sml
index 0bd86be..04b2774 100644
--- a/CodeGen.sml
+++ b/CodeGen.sml
@@ -175,7 +175,7 @@ struct
Syntax.OWrite (translate ptr, translateVal off, translateVal len) :: go k
| Syntax.CPrimop (Syntax.PWriteErr, [Syntax.VVar ptr, off, len], _, [k]) =>
Syntax.OWriteErr (translate ptr, translateVal off, translateVal len) :: go k
- | _ => raise Fail ("malformed CPS:\n" ^ Syntax.cexpToString expr)
+ | _ => raise Fail ("malformed CPS:\n" ^ ShowSyntax.cexpToString expr)
in go expr
end
end
diff --git a/Compiler.sml b/Compiler.sml
index 4c5e238..0ca0ee5 100644
--- a/Compiler.sml
+++ b/Compiler.sml
@@ -2,17 +2,17 @@ structure Compiler =
struct
fun compile (prog : Syntax.expr) : Word8Vector.vector =
let
- val _ = print ("ast:\n" ^ Syntax.exprToString prog ^ "\n")
+ val _ = print ("ast:\n" ^ ShowSyntax.exprToString prog ^ "\n")
val elab = Elab.elaborate prog
- val _ = print ("lambda lang:\n" ^ Syntax.lexpToString elab ^ "\n")
+ val _ = print ("lambda lang:\n" ^ ShowSyntax.lexpToString elab ^ "\n")
val cps =
CPS.toCPS elab
(fn _ => Syntax.CPrimop (Syntax.PExit, [Syntax.VInt 0], [], []))
- val _ = print ("cps1:\n" ^ Syntax.cexpToString cps ^ "\n")
+ val _ = print ("cps1:\n" ^ ShowSyntax.cexpToString cps ^ "\n")
val cps' = CPS.convertClosures cps
- val _ = print ("cps:\n" ^ Syntax.cexpToString cps' ^ "\n")
+ val _ = print ("cps:\n" ^ ShowSyntax.cexpToString cps' ^ "\n")
val asm = CodeGen.toASM cps'
- val _ = print ("bytecode:\n" ^ String.concatWith "\n" (map Syntax.opcodeToString asm) ^ "\n")
+ val _ = print ("bytecode:\n" ^ String.concatWith "\n" (map ShowSyntax.opcodeToString asm) ^ "\n")
in
Linker.link asm
end
diff --git a/Parser.sml b/Parser.sml
index f632380..50d302d 100644
--- a/Parser.sml
+++ b/Parser.sml
@@ -426,6 +426,9 @@ struct
[i] => Syntax.PVar i
| _ => Syntax.PCon (ident, Syntax.PTuple [])))
<|> atpat) st
+ and typedPat : Syntax.pat parser = fn st =>
+ (bind appPat (fn pat =>
+ pat <$ (reserved ":" >> parseType) <|> const pat)) st
and pat : Syntax.pat parser = fn st =>
foldl
(fn (i, patLower) =>
@@ -445,7 +448,7 @@ struct
bind patLower (fn pat1 =>
patLeft pat1 <|> patRight pat1 <|> const pat1)
end)
- appPat
+ typedPat
(List.tabulate (10, fn i => 9 - i)) st
val rec atom : Syntax.expr parser =
@@ -546,7 +549,7 @@ struct
else {infixTable = Vector.update (infixTable, level, (ops @ leftOps, rightOps))}
end) >>
const NONE)))
- <|> (reserved "datatype" >>
+ <|> ((reserved "datatype" <|> reserved "and") >>
(between (symbol "(") (symbol ")") (sepBy1 tyvar (symbol ","))
<|> (fn x => [x]) <$> tyvar
<|> const []) >>
@@ -561,6 +564,11 @@ struct
<|> const (con, NONE)))
(reserved "|")) (fn cons =>
const (SOME (Syntax.DDatatype (name, cons))))))
+ <|> (reserved "type" >>
+ bind identifier (fn name =>
+ reserved "=" >>
+ bind parseType (fn ty =>
+ const (SOME (Syntax.DType (name, ty))))))
<|> (reserved "val" >>
bind (true <$ reserved "rec" <|> const false) (fn isRec =>
bind pat (fn p =>
@@ -628,6 +636,7 @@ struct
| fixDecConstructors constructors (Syntax.DFun (f, arms)) =
Syntax.DFun (f, map (fn (args, body) => (map (fixPatConstructors constructors) args, fixConstructors constructors body)) arms)
| fixDecConstructors _ (decl as Syntax.DDatatype _) = decl
+ | fixDecConstructors _ (decl as Syntax.DType _) = decl
| fixDecConstructors constructors (Syntax.DStruct (name, decs)) =
let
val constructors = ref constructors
diff --git a/ShowSyntax.sml b/ShowSyntax.sml
new file mode 100644
index 0000000..645ef84
--- /dev/null
+++ b/ShowSyntax.sml
@@ -0,0 +1,190 @@
+(*
+ This file was generated by generate-show-syntax.sml. Do not edit manually.
+ To regenerate, use
+
+ sml generate-show-syntax.sml -o ShowSyntax.sml Syntax.sml
+*)
+
+structure ShowSyntax = struct
+fun intToStringI (_ : string) (i : int) : string = Int.toString i
+
+fun varToStringI (_ : string) (v : Syntax.var) : string = "Var " ^ Int.toString v
+
+fun stringToStringI (_ : string) (s : string) : string = "\"" ^ String.toString s ^ "\""
+
+fun optionToString (_ : string -> 'a -> string) (_ : string) NONE : string = "NONE"
+ | optionToString show indent (SOME x) = "SOME (" ^ show indent x ^ ")"
+
+fun listToString (_ : string -> 'a -> string) (_ : string) ([] : 'a list) : string = "[]"
+ | listToString show indent [x] = "[" ^ show indent x ^ "]"
+ | listToString show indent xs =
+ let val indent' = indent ^ " " in
+ "[\n" ^ indent' ^ String.concatWith (",\n" ^ indent') (map (show indent') xs) ^ "\n" ^ indent ^ "]"
+ end
+
+fun etypeToStringI (indent : string) (Syntax.Tyvar x : Syntax.etype) : string =
+ "Tyvar " ^ stringToStringI indent x
+ | etypeToStringI (indent : string) (Syntax.Tycon x : Syntax.etype) : string =
+ "Tycon " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ listToString (etypeToStringI) indent' x0 ^ ",\n" ^ indent' ^ stringToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | etypeToStringI (indent : string) (Syntax.TyTuple x : Syntax.etype) : string =
+ "TyTuple " ^ listToString (etypeToStringI) indent x
+ | etypeToStringI (indent : string) (Syntax.Tyfun x : Syntax.etype) : string =
+ "Tyfun " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ etypeToStringI indent' x0 ^ ",\n" ^ indent' ^ etypeToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+and etypeToString (x : Syntax.etype) : string = etypeToStringI "" x
+
+and patToStringI (indent : string) (Syntax.PWild : Syntax.pat) : string =
+ "PWild"
+ | patToStringI (indent : string) (Syntax.PVar x : Syntax.pat) : string =
+ "PVar " ^ stringToStringI indent x
+ | patToStringI (indent : string) (Syntax.PInt x : Syntax.pat) : string =
+ "PInt " ^ intToStringI indent x
+ | patToStringI (indent : string) (Syntax.PTuple x : Syntax.pat) : string =
+ "PTuple " ^ listToString (patToStringI) indent x
+ | patToStringI (indent : string) (Syntax.PCon x : Syntax.pat) : string =
+ "PCon " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ listToString (stringToStringI) indent' x0 ^ ",\n" ^ indent' ^ patToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+and patToString (x : Syntax.pat) : string = patToStringI "" x
+
+and exprToStringI (indent : string) (Syntax.EIdent x : Syntax.expr) : string =
+ "EIdent " ^ listToString (stringToStringI) indent x
+ | exprToStringI (indent : string) (Syntax.EBuiltin x : Syntax.expr) : string =
+ "EBuiltin " ^ stringToStringI indent x
+ | exprToStringI (indent : string) (Syntax.EInt x : Syntax.expr) : string =
+ "EInt " ^ intToStringI indent x
+ | exprToStringI (indent : string) (Syntax.EStr x : Syntax.expr) : string =
+ "EStr " ^ stringToStringI indent x
+ | exprToStringI (indent : string) (Syntax.ETuple x : Syntax.expr) : string =
+ "ETuple " ^ listToString (exprToStringI) indent x
+ | exprToStringI (indent : string) (Syntax.EList x : Syntax.expr) : string =
+ "EList " ^ listToString (exprToStringI) indent x
+ | exprToStringI (indent : string) (Syntax.EApp x : Syntax.expr) : string =
+ "EApp " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ exprToStringI indent' x0 ^ ",\n" ^ indent' ^ exprToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | exprToStringI (indent : string) (Syntax.ETyped x : Syntax.expr) : string =
+ "ETyped " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ exprToStringI indent' x0 ^ ",\n" ^ indent' ^ etypeToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | exprToStringI (indent : string) (Syntax.EAndAlso x : Syntax.expr) : string =
+ "EAndAlso " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ exprToStringI indent' x0 ^ ",\n" ^ indent' ^ exprToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | exprToStringI (indent : string) (Syntax.EOrElse x : Syntax.expr) : string =
+ "EOrElse " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ exprToStringI indent' x0 ^ ",\n" ^ indent' ^ exprToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | exprToStringI (indent : string) (Syntax.ELet x : Syntax.expr) : string =
+ "ELet " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ listToString (decToStringI) indent' x0 ^ ",\n" ^ indent' ^ exprToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | exprToStringI (indent : string) (Syntax.ELambda x : Syntax.expr) : string =
+ "ELambda " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ patToStringI indent' x0 ^ ",\n" ^ indent' ^ exprToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | exprToStringI (indent : string) (Syntax.ECase x : Syntax.expr) : string =
+ "ECase " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ exprToStringI indent' x0 ^ ",\n" ^ indent' ^ listToString ((fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ patToStringI indent' x0 ^ ",\n" ^ indent' ^ exprToStringI indent' x1 ^ "\n" ^ indent ^ ")" end)) indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+and exprToString (x : Syntax.expr) : string = exprToStringI "" x
+
+and decToStringI (indent : string) (Syntax.DVal x : Syntax.dec) : string =
+ "DVal " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ patToStringI indent' x0 ^ ",\n" ^ indent' ^ exprToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | decToStringI (indent : string) (Syntax.DValRec x : Syntax.dec) : string =
+ "DValRec " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ patToStringI indent' x0 ^ ",\n" ^ indent' ^ exprToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | decToStringI (indent : string) (Syntax.DFun x : Syntax.dec) : string =
+ "DFun " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ stringToStringI indent' x0 ^ ",\n" ^ indent' ^ listToString ((fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ listToString (patToStringI) indent' x0 ^ ",\n" ^ indent' ^ exprToStringI indent' x1 ^ "\n" ^ indent ^ ")" end)) indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | decToStringI (indent : string) (Syntax.DDatatype x : Syntax.dec) : string =
+ "DDatatype " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ stringToStringI indent' x0 ^ ",\n" ^ indent' ^ listToString ((fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ stringToStringI indent' x0 ^ ",\n" ^ indent' ^ optionToString (etypeToStringI) indent' x1 ^ "\n" ^ indent ^ ")" end)) indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | decToStringI (indent : string) (Syntax.DType x : Syntax.dec) : string =
+ "DType " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ stringToStringI indent' x0 ^ ",\n" ^ indent' ^ etypeToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | decToStringI (indent : string) (Syntax.DStruct x : Syntax.dec) : string =
+ "DStruct " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ stringToStringI indent' x0 ^ ",\n" ^ indent' ^ listToString (decToStringI) indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+and decToString (x : Syntax.dec) : string = decToStringI "" x
+
+and primopToStringI (indent : string) (Syntax.PExit : Syntax.primop) : string =
+ "PExit"
+ | primopToStringI (indent : string) (Syntax.PAdd : Syntax.primop) : string =
+ "PAdd"
+ | primopToStringI (indent : string) (Syntax.PSub : Syntax.primop) : string =
+ "PSub"
+ | primopToStringI (indent : string) (Syntax.PMul : Syntax.primop) : string =
+ "PMul"
+ | primopToStringI (indent : string) (Syntax.PDiv : Syntax.primop) : string =
+ "PDiv"
+ | primopToStringI (indent : string) (Syntax.PLess : Syntax.primop) : string =
+ "PLess"
+ | primopToStringI (indent : string) (Syntax.PEq : Syntax.primop) : string =
+ "PEq"
+ | primopToStringI (indent : string) (Syntax.PIf : Syntax.primop) : string =
+ "PIf"
+ | primopToStringI (indent : string) (Syntax.PRead : Syntax.primop) : string =
+ "PRead"
+ | primopToStringI (indent : string) (Syntax.PWrite : Syntax.primop) : string =
+ "PWrite"
+ | primopToStringI (indent : string) (Syntax.PWriteErr : Syntax.primop) : string =
+ "PWriteErr"
+and primopToString (x : Syntax.primop) : string = primopToStringI "" x
+
+and lexpToStringI (indent : string) (Syntax.LVar x : Syntax.lexp) : string =
+ "LVar " ^ varToStringI indent x
+ | lexpToStringI (indent : string) (Syntax.LFn x : Syntax.lexp) : string =
+ "LFn " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ lexpToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | lexpToStringI (indent : string) (Syntax.LFix x : Syntax.lexp) : string =
+ "LFix " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ listToString ((fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ varToStringI indent' x1 ^ ",\n" ^ indent' ^ lexpToStringI indent' x2 ^ "\n" ^ indent ^ ")" end)) indent' x0 ^ ",\n" ^ indent' ^ lexpToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | lexpToStringI (indent : string) (Syntax.LApp x : Syntax.lexp) : string =
+ "LApp " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ lexpToStringI indent' x0 ^ ",\n" ^ indent' ^ lexpToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | lexpToStringI (indent : string) (Syntax.LInt x : Syntax.lexp) : string =
+ "LInt " ^ intToStringI indent x
+ | lexpToStringI (indent : string) (Syntax.LString x : Syntax.lexp) : string =
+ "LString " ^ stringToStringI indent x
+ | lexpToStringI (indent : string) (Syntax.LRecord x : Syntax.lexp) : string =
+ "LRecord " ^ listToString (lexpToStringI) indent x
+ | lexpToStringI (indent : string) (Syntax.LSelect x : Syntax.lexp) : string =
+ "LSelect " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ intToStringI indent' x0 ^ ",\n" ^ indent' ^ lexpToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | lexpToStringI (indent : string) (Syntax.LPrim x : Syntax.lexp) : string =
+ "LPrim " ^ primopToStringI indent x
+ | lexpToStringI (indent : string) (Syntax.LSwitch x : Syntax.lexp) : string =
+ "LSwitch " ^ (fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ lexpToStringI indent' x0 ^ ",\n" ^ indent' ^ listToString ((fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ intToStringI indent' x0 ^ ",\n" ^ indent' ^ lexpToStringI indent' x1 ^ "\n" ^ indent ^ ")" end)) indent' x1 ^ ",\n" ^ indent' ^ optionToString (lexpToStringI) indent' x2 ^ "\n" ^ indent ^ ")" end) indent x
+and lexpToString (x : Syntax.lexp) : string = lexpToStringI "" x
+
+and valueToStringI (indent : string) (Syntax.VVar x : Syntax.value) : string =
+ "VVar " ^ varToStringI indent x
+ | valueToStringI (indent : string) (Syntax.VLabel x : Syntax.value) : string =
+ "VLabel " ^ varToStringI indent x
+ | valueToStringI (indent : string) (Syntax.VInt x : Syntax.value) : string =
+ "VInt " ^ intToStringI indent x
+and valueToString (x : Syntax.value) : string = valueToStringI "" x
+
+and cexpToStringI (indent : string) (Syntax.CRecord x : Syntax.cexp) : string =
+ "CRecord " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ listToString ((fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ listToString ((fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ valueToStringI indent' x0 ^ ",\n" ^ indent' ^ listToString (intToStringI) indent' x1 ^ "\n" ^ indent ^ ")" end)) indent' x0 ^ ",\n" ^ indent' ^ varToStringI indent' x1 ^ "\n" ^ indent ^ ")" end)) indent' x0 ^ ",\n" ^ indent' ^ cexpToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | cexpToStringI (indent : string) (Syntax.CSelect x : Syntax.cexp) : string =
+ "CSelect " ^ (fn indent => fn (x0, x1, x2, x3) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ intToStringI indent' x0 ^ ",\n" ^ indent' ^ valueToStringI indent' x1 ^ ",\n" ^ indent' ^ varToStringI indent' x2 ^ ",\n" ^ indent' ^ cexpToStringI indent' x3 ^ "\n" ^ indent ^ ")" end) indent x
+ | cexpToStringI (indent : string) (Syntax.CApp x : Syntax.cexp) : string =
+ "CApp " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ valueToStringI indent' x0 ^ ",\n" ^ indent' ^ listToString (valueToStringI) indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | cexpToStringI (indent : string) (Syntax.CFix x : Syntax.cexp) : string =
+ "CFix " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ listToString ((fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ listToString (varToStringI) indent' x1 ^ ",\n" ^ indent' ^ cexpToStringI indent' x2 ^ "\n" ^ indent ^ ")" end)) indent' x0 ^ ",\n" ^ indent' ^ cexpToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | cexpToStringI (indent : string) (Syntax.CPrimop x : Syntax.cexp) : string =
+ "CPrimop " ^ (fn indent => fn (x0, x1, x2, x3) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ primopToStringI indent' x0 ^ ",\n" ^ indent' ^ listToString (valueToStringI) indent' x1 ^ ",\n" ^ indent' ^ listToString (varToStringI) indent' x2 ^ ",\n" ^ indent' ^ listToString (cexpToStringI) indent' x3 ^ "\n" ^ indent ^ ")" end) indent x
+and cexpToString (x : Syntax.cexp) : string = cexpToStringI "" x
+
+and opcodeToStringI (indent : string) (Syntax.OAlloc x : Syntax.opcode) : string =
+ "OAlloc " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ valueToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OCall : Syntax.opcode) : string =
+ "OCall"
+ | opcodeToStringI (indent : string) (Syntax.OPoke x : Syntax.opcode) : string =
+ "OPoke " ^ (fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ intToStringI indent' x0 ^ ",\n" ^ indent' ^ varToStringI indent' x1 ^ ",\n" ^ indent' ^ valueToStringI indent' x2 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OPeek x : Syntax.opcode) : string =
+ "OPeek " ^ (fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ intToStringI indent' x1 ^ ",\n" ^ indent' ^ valueToStringI indent' x2 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OShuf x : Syntax.opcode) : string =
+ "OShuf " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ valueToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OExit x : Syntax.opcode) : string =
+ "OExit " ^ valueToStringI indent x
+ | opcodeToStringI (indent : string) (Syntax.OAdd x : Syntax.opcode) : string =
+ "OAdd " ^ (fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ valueToStringI indent' x1 ^ ",\n" ^ indent' ^ valueToStringI indent' x2 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OSub x : Syntax.opcode) : string =
+ "OSub " ^ (fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ valueToStringI indent' x1 ^ ",\n" ^ indent' ^ valueToStringI indent' x2 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OMul x : Syntax.opcode) : string =
+ "OMul " ^ (fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ valueToStringI indent' x1 ^ ",\n" ^ indent' ^ valueToStringI indent' x2 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.ODiv x : Syntax.opcode) : string =
+ "ODiv " ^ (fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ valueToStringI indent' x1 ^ ",\n" ^ indent' ^ valueToStringI indent' x2 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OLess x : Syntax.opcode) : string =
+ "OLess " ^ (fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ valueToStringI indent' x1 ^ ",\n" ^ indent' ^ valueToStringI indent' x2 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OEq x : Syntax.opcode) : string =
+ "OEq " ^ (fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ valueToStringI indent' x1 ^ ",\n" ^ indent' ^ valueToStringI indent' x2 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OIf x : Syntax.opcode) : string =
+ "OIf " ^ (fn indent => fn (x0, x1) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ valueToStringI indent' x0 ^ ",\n" ^ indent' ^ varToStringI indent' x1 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OLabel x : Syntax.opcode) : string =
+ "OLabel " ^ varToStringI indent x
+ | opcodeToStringI (indent : string) (Syntax.ORead x : Syntax.opcode) : string =
+ "ORead " ^ (fn indent => fn (x0, x1, x2, x3) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ varToStringI indent' x1 ^ ",\n" ^ indent' ^ valueToStringI indent' x2 ^ ",\n" ^ indent' ^ valueToStringI indent' x3 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OWrite x : Syntax.opcode) : string =
+ "OWrite " ^ (fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ valueToStringI indent' x1 ^ ",\n" ^ indent' ^ valueToStringI indent' x2 ^ "\n" ^ indent ^ ")" end) indent x
+ | opcodeToStringI (indent : string) (Syntax.OWriteErr x : Syntax.opcode) : string =
+ "OWriteErr " ^ (fn indent => fn (x0, x1, x2) => let val indent' = indent ^ " " in "(\n" ^ indent' ^ varToStringI indent' x0 ^ ",\n" ^ indent' ^ valueToStringI indent' x1 ^ ",\n" ^ indent' ^ valueToStringI indent' x2 ^ "\n" ^ indent ^ ")" end) indent x
+and opcodeToString (x : Syntax.opcode) : string = opcodeToStringI "" x
+end
diff --git a/Syntax.sml b/Syntax.sml
index 2f7a96e..bb394b4 100644
--- a/Syntax.sml
+++ b/Syntax.sml
@@ -34,6 +34,7 @@ struct
| DValRec of pat * expr
| DFun of string * (pat list * expr) list
| DDatatype of string * (string * etype option) list
+ | DType of string * etype
| DStruct of string * dec list
(* Lambda language *)
@@ -95,137 +96,4 @@ struct
| ORead of var * var * value * value
| OWrite of var * value * value
| OWriteErr of var * value * value
-
- fun listToString (show : 'a -> string) (l : 'a list) =
- "[" ^ String.concatWith ", " (map show l) ^ "]"
-
- fun multilineListToString (show : string -> 'a -> string) (indent : string) (l : 'a list) =
- case l of
- [] => "[]"
- | [x] => "[ " ^ show (indent ^ " ") x ^ " ]"
- | (x :: xs) =>
- let val indent' = indent ^ " "
- in "[ " ^ show indent' x ^ concat (map (fn x => "\n" ^ indent ^ ", " ^ show indent' x) xs) ^ "\n" ^ indent ^ "]"
- end
-
- fun quote (s : string) : string = "\"" ^ String.toString s ^ "\""
-
- fun optionToString (show : 'a -> string) (x : 'a option) =
- case x of
- NONE => "NONE"
- | SOME x => "SOME " ^ show x
-
- fun etypeToString (x : etype) : string =
- case x of
- Tyvar s => "Tyvar " ^ quote s
- | Tycon (args, con) => "Tycon (" ^ listToString etypeToString args ^ ", " ^ quote con ^ ")"
- | TyTuple args => "TyTuple " ^ listToString etypeToString args
- | Tyfun (a, b) => "Tyfun (" ^ etypeToString a ^ ", " ^ etypeToString b ^ ")"
-
- fun patToString (p : pat) : string =
- case p of
- PWild => "PWild"
- | PVar v => "PVar " ^ quote v
- | PInt i => "PInt " ^ Int.toString i
- | PTuple pats => "PTuple " ^ listToString patToString pats
- | PCon (con, v) => "PCon " ^ "(" ^ listToString quote con ^ ", " ^ patToString v ^ ")"
-
- fun exprToStringI (indent : string) (x : expr) : string =
- let val self = exprToStringI indent
- in case x of
- EIdent i => "EIdent " ^ listToString quote i
- | EBuiltin b => "EBuiltin " ^ quote b
- | EInt i => "EInt " ^ Int.toString i
- | EStr s => "EStr " ^ quote s
- | ETuple xs => "ETuple " ^ listToString self xs
- | EList l => "EList " ^ listToString self l
- | EApp (f, x) => "EApp (" ^ self f ^ ", " ^ self x ^ ")"
- | ETyped (e, t) => "ETyped (" ^ self e ^ ", " ^ etypeToString t ^ ")"
- | EAndAlso (a, b) => "EAndAlso (" ^ self a ^ ", " ^ self b ^ ")"
- | EOrElse (a, b) => "EOrElse (" ^ self a ^ ", " ^ self b ^ ")"
- | ELet (decs, e) => "ELet (" ^ multilineListToString decToStringI indent decs ^ ", " ^ self e ^ ")"
- | ELambda (pat, e) => "ELambda (" ^ patToString pat ^ ", " ^ exprToStringI indent e ^ ")"
- | ECase (e, branches) => "ECase (" ^ self e ^ ", " ^ multilineListToString (fn indent => fn (pat, body) => "(" ^ patToString pat ^ ", " ^ exprToStringI indent body ^ ")") indent branches ^ ")"
- end
-
- and decToStringI (indent : string) (x : dec) : string =
- case x of
- DVal (p, e) => "DVal (" ^ patToString p ^ ", " ^ exprToStringI indent e ^ ")"
- | DValRec (p, e) => "DValRec (" ^ patToString p ^ ", " ^ exprToStringI indent e ^ ")"
- | DFun (name, cases) => "DFun (" ^ quote name ^ ", " ^ multilineListToString (fn indent => fn (ps, b) => "(" ^ listToString patToString ps ^ ", " ^ exprToStringI indent b ^ ")") indent cases ^ ")"
- | DDatatype (name, arms) => "DDatatype (" ^ quote name ^ ", " ^ listToString (fn (con, v) => "(" ^ quote con ^ ", " ^ optionToString etypeToString v ^ ")") arms ^ ")"
- | DStruct (name, decls) => "DStruct (" ^ quote name ^ ",\n" ^ indent ^ "\t" ^ multilineListToString decToStringI (indent ^ "\t") decls ^ ")"
-
- val exprToString : expr -> string = exprToStringI ""
-
- val decToString : dec -> string = decToStringI ""
-
- fun primopToString (x : primop) : string =
- case x of
- PExit => "PExit"
- | PAdd => "PAdd"
- | PSub => "PSub"
- | PMul => "PMul"
- | PDiv => "PDiv"
- | PLess => "PLess"
- | PEq => "PEq"
- | PIf => "PIf"
- | PRead => "PRead"
- | PWrite => "PWrite"
- | PWriteErr => "PWriteErr"
-
- fun lexpToStringI (indent : string) (x : lexp) : string =
- case x of
- LVar v => "LVar " ^ Int.toString v
- | LFn (arg, expr) => "LFun (" ^ Int.toString arg ^ ",\n" ^ indent ^ "\t" ^ lexpToStringI (indent ^ "\t") expr ^ ")"
- | LFix (decls, body) => "LFix (" ^ multilineListToString (fn indent => fn (arg, var, expr) => "(" ^ Int.toString arg ^ ", " ^ Int.toString var ^ ", " ^ lexpToStringI indent expr ^ ")") indent decls ^ ",\n" ^ indent ^ lexpToStringI indent body ^ ")"
- | LApp (a, b) => "LApp (" ^ lexpToStringI indent a ^ ",\n" ^ indent ^ "\t" ^ lexpToStringI (indent ^ "\t") b ^ ")"
- | LInt i => "LInt " ^ Int.toString i
- | LString s => "LString " ^ quote s
- | LRecord l => "LRecord " ^ listToString (lexpToStringI indent) l
- | LSelect (i, r) => "LSelect (" ^ Int.toString i ^ ", " ^ lexpToStringI indent r ^ ")"
- | LPrim p => "LPrim " ^ primopToString p
- | LSwitch (e, arms, otherwise) => "LSwitch (" ^ lexpToStringI indent e ^ ",\n" ^ indent ^ "\t" ^ multilineListToString (fn indent => fn (x, e) => "(" ^ Int.toString x ^ ", " ^ lexpToStringI indent e ^ ")") (indent ^ "\t") arms ^ ",\n" ^ indent ^ "\t" ^ optionToString (lexpToStringI (indent ^ "\t")) otherwise ^ ")"
-
- fun lexpToString (x : lexp) : string = lexpToStringI "" x
-
- fun valueToString (x : value) : string =
- case x of
- VVar v => "VVar " ^ Int.toString v
- | VLabel l => "VLabel " ^ Int.toString l
- | VInt i => "VInt " ^ Int.toString i
-
- fun cexpToStringI (indent : string) (x : cexp) : string =
- let
- val self = cexpToStringI indent
- val newIndent = indent ^ "\t"
- in case x of
- CRecord (records, c) => "CRecord (" ^ listToString (fn (a, b) => listToString (fn (x, y) => "(" ^ valueToString x ^ ", " ^ listToString Int.toString y ^ ")") a ^ ", " ^ Int.toString b ^ ")") records ^ ",\n" ^ indent ^ self c ^ ")"
- | CSelect (a, b, c, d) => "CSelect (" ^ Int.toString a ^ ", " ^ valueToString b ^ ", " ^ Int.toString c ^ ",\n" ^ indent ^ self d ^ ")"
- | CApp (a, b) => "CApp (" ^ valueToString a ^ ", " ^ listToString valueToString b ^ ")"
- | CFix (a, b) => "CFix (" ^ multilineListToString (fn indent' => fn (x, y, z) => "(" ^ Int.toString x ^ ", " ^ listToString Int.toString y ^ ",\n" ^ indent' ^ "\t" ^ cexpToStringI (indent' ^ "\t") z) newIndent a ^ ",\n" ^ newIndent ^ cexpToStringI newIndent b ^ ")"
- | CPrimop (a, b, c, d) => "CPrimop (" ^ primopToString a ^ ", " ^ listToString valueToString b ^ ", " ^ listToString Int.toString c ^ ",\n" ^ indent ^ multilineListToString cexpToStringI indent d ^ ")"
- end
-
- val cexpToString : cexp -> string = cexpToStringI ""
-
- fun opcodeToString (oper : opcode) : string =
- case oper of
- OAlloc (r, s) => "Var " ^ Int.toString r ^ " = OAlloc (" ^ valueToString s ^ ")"
- | OCall => "OCall"
- | OPoke (i, p, v) => "Var " ^ Int.toString p ^ "[" ^ Int.toString i ^ "] = " ^ valueToString v
- | OPeek (r, i, p) => "Var " ^ Int.toString r ^ " = " ^ valueToString p ^ "[" ^ Int.toString i ^ "]"
- | OShuf (d, s) => "Var " ^ Int.toString d ^ " = " ^ valueToString s
- | OExit v => "OExit (" ^ valueToString v ^ ")"
- | OAdd (r, v1, v2) => "Var " ^ Int.toString r ^ " = OAdd (" ^ valueToString v1 ^ ", " ^ valueToString v2 ^ ")"
- | OSub (r, v1, v2) => "Var " ^ Int.toString r ^ " = OSub (" ^ valueToString v1 ^ ", " ^ valueToString v2 ^ ")"
- | OMul (r, v1, v2) => "Var " ^ Int.toString r ^ " = OMul (" ^ valueToString v1 ^ ", " ^ valueToString v2 ^ ")"
- | ODiv (r, v1, v2) => "Var " ^ Int.toString r ^ " = ODiv (" ^ valueToString v1 ^ ", " ^ valueToString v2 ^ ")"
- | OLess (r, v1, v2) => "Var " ^ Int.toString r ^ " = OLess (" ^ valueToString v1 ^ ", " ^ valueToString v2 ^ ")"
- | OEq (r, v1, v2) => "Var " ^ Int.toString r ^ " = OEq (" ^ valueToString v1 ^ ", " ^ valueToString v2 ^ ")"
- | OIf (condition, target) => "OIf (" ^ valueToString condition ^ ") goto " ^ Int.toString target
- | OLabel l => "OLabel " ^ Int.toString l
- | ORead (r, ptr, off, len) => "Var " ^ Int.toString r ^ " = ORead (Var " ^ Int.toString ptr ^ ", " ^ valueToString off ^ ", " ^ valueToString len ^ ")"
- | OWrite (ptr, off, len) => "OWrite (Var " ^ Int.toString ptr ^ ", " ^ valueToString off ^ ", " ^ valueToString len ^ ")"
- | OWriteErr (ptr, off, len) => "OWriteErr (Var " ^ Int.toString ptr ^ ", " ^ valueToString off ^ ", " ^ valueToString len ^ ")"
end
diff --git a/generate-show-syntax.sml b/generate-show-syntax.sml
new file mode 100644
index 0000000..7e7e38a
--- /dev/null
+++ b/generate-show-syntax.sml
@@ -0,0 +1,66 @@
+use "Result.sml";
+use "Map.sml";
+use "Syntax.sml";
+use "Parser.sml";
+use "Opts.sml";
+
+val header =
+ "fun intToStringI (_ : string) (i : int) : string = Int.toString i\n"
+ ^ "\n"
+ ^ "fun varToStringI (_ : string) (v : Syntax.var) : string = \"Var \" ^ Int.toString v\n"
+ ^ "\n"
+ ^ "fun stringToStringI (_ : string) (s : string) : string = \"\\\"\" ^ String.toString s ^ \"\\\"\"\n"
+ ^ "\n"
+ ^ "fun optionToString (_ : string -> 'a -> string) (_ : string) NONE : string = \"NONE\"\n"
+ ^ " | optionToString show indent (SOME x) = \"SOME (\" ^ show indent x ^ \")\"\n"
+ ^ "\n"
+ ^ "fun listToString (_ : string -> 'a -> string) (_ : string) ([] : 'a list) : string = \"[]\"\n"
+ ^ " | listToString show indent [x] = \"[\" ^ show indent x ^ \"]\"\n"
+ ^ " | listToString show indent xs =\n"
+ ^ " let val indent' = indent ^ \" \" in\n"
+ ^ " \"[\\n\" ^ indent' ^ String.concatWith (\",\\n\" ^ indent') (map (show indent') xs) ^ \"\\n\" ^ indent ^ \"]\"\n"
+ ^ " end\n"
+
+fun showTy (Syntax.Tyvar var) : string = var ^ "ToStringI"
+ | showTy (Syntax.Tycon ([ty], con)) = con ^ "ToString (" ^ showTy ty ^ ")"
+ | showTy (Syntax.TyTuple tys) =
+ let val vars = List.tabulate (length tys, fn i => "x" ^ Int.toString i)
+ in
+ "(fn indent => fn (" ^ String.concatWith ", " vars ^ ") => let val indent' = indent ^ \" \" in \"(\\n\" ^ indent' ^ " ^ String.concatWith " ^ \",\\n\" ^ indent' ^ " (map (fn (var, ty) => showTy ty ^ " indent' " ^ var) (ListPair.zip (vars, tys))) ^ " ^ \"\\n\" ^ indent ^ \")\" end)"
+ end
+ | showTy _ = "(fn _ => fn _ => \"UNHANDLED\")"
+
+val opts = { o = ref "/dev/stdout" }
+val flags =
+ [ ("o", Opts.StringOpt (fn arg => #o opts := arg)) ]
+val filename =
+ case Opts.getOpt flags (CommandLine.arguments ()) of
+ [arg] => arg
+ | _ => raise Fail "usage: showsyntax <filename>"
+val ast =
+ case Parser.parse filename of
+ Result.Left e => raise Fail e
+ | Result.Right x => x
+val (structName, decls) =
+ case ast of
+ Syntax.ELet (Syntax.DStruct str :: _, _) => str
+ | _ => raise Fail "ast has unexpected format (I can't print it sorry)"
+val out = TextIO.openOut (!(#o opts))
+val _ = TextIO.output (out, "(*\n This file was generated by generate-show-syntax.sml. Do not edit manually.\n To regenerate, use\n\n sml generate-show-syntax.sml -o " ^ !(#o opts) ^ " " ^ filename ^ "\n*)\n\n")
+val _ = TextIO.output (out, "structure Show" ^ structName ^ " = struct\n")
+val _ = TextIO.output (out, header)
+val _ = map
+ (fn (i, Syntax.DDatatype (typeName, cases)) => (
+ TextIO.output (out,
+ "\n" ^ (if i = 0 then "fun" else "and") ^ " "
+ ^ String.concatWith "\n | " (map
+ (fn (caseName, NONE) => typeName ^ "ToStringI (indent : string) (" ^ structName ^ "." ^ caseName ^ " : " ^ structName ^ "." ^ typeName ^ ") : string =\n \"" ^ caseName ^ "\""
+ | (caseName, SOME ty) => typeName ^ "ToStringI (indent : string) (" ^ structName ^ "." ^ caseName ^ " x : " ^ structName ^ "." ^ typeName ^ ") : string =\n \"" ^ caseName ^ " \" ^ " ^ showTy ty ^ " indent x")
+ cases)
+ ^ "\n");
+ TextIO.output (out, "and " ^ typeName ^ "ToString (x : " ^ structName ^ "." ^ typeName ^ ") : string = " ^ typeName ^ "ToStringI \"\" x\n")
+ )
+ | _ => ())
+ (ListPair.zip (List.tabulate (length decls, fn i => i), decls))
+val _ = TextIO.output(out, "end\n")
+val _ = OS.Process.exit OS.Process.success
diff --git a/main.sml b/main.sml
index b391219..13e6774 100644
--- a/main.sml
+++ b/main.sml
@@ -4,6 +4,7 @@ use "Buffer.sml";
use "GenSym.sml";
use "Map.sml";
use "Syntax.sml";
+use "ShowSyntax.sml";
use "CodeGen.sml";
use "CPS.sml";
use "Elab.sml";
diff --git a/program.cm b/program.cm
index ff015c7..c99286a 100644
--- a/program.cm
+++ b/program.cm
@@ -11,6 +11,7 @@ Map.sml
Opts.sml
Parser.sml
Result.sml
+ShowSyntax.sml
Syntax.sml
$/basis.cm