ADT generator: polymorphic types (list, option…)

This commit is contained in:
Suzanne Dupéron 2020-02-10 11:45:44 +01:00
parent 2588de2395
commit 5151a0fd92
3 changed files with 65 additions and 20 deletions

View File

@ -1,6 +1,6 @@
type root = type root =
| A of a | A of rootA
| B of int | B of rootB
| C of string | C of string
and a = { and a = {
@ -15,3 +15,20 @@ and ta1 =
and ta2 = and ta2 =
| Z of ta2 | Z of ta2
| W of unit | W of unit
and rootA =
a list
and rootB =
int list
let fold_list v state continue =
let aux = fun (lst', state) elt ->
let (elt', state) = continue elt state in
(elt' :: lst' , state) in
List.fold_left aux ([], state) v
let fold_option v state continue =
match v with
Some x -> continue x state
| None -> None

View File

@ -1,34 +1,49 @@
moduleName = "A" moduleName = "A"
variant="_ _variant"
record="_ _record"
def poly(x): return x
adts = [ adts = [
# typename, variant?, fields_or_ctors # typename, kind, fields_or_ctors
("root", True, [ ("root", variant, [
# ctor, builtin, type # ctor, builtin?, type
("A", False, "a"), ("A", False, "rootA"),
("B", True, "int"), ("B", False, "rootB"),
("C", True, "string"), ("C", True, "string"),
]), ]),
("a", False, [ ("a", record, [
# field, builtin?, type
("a1", False, "ta1"), ("a1", False, "ta1"),
("a2", False, "ta2"), ("a2", False, "ta2"),
]), ]),
("ta1", True, [ ("ta1", variant, [
("X", False, "root"), ("X", False, "root"),
("Y", False, "ta2"), ("Y", False, "ta2"),
]), ]),
("ta2", True, [ ("ta2", variant, [
("Z", False, "ta2"), ("Z", False, "ta2"),
("W", True, "unit"), ("W", True, "unit"),
]), ]),
# polymorphic type
("rootA", poly("list"),
[
# Position (0..n-1), builtin?, type argument
(0, False, "a")
]),
("rootB", poly("list"),
[
# Position (0..n-1), builtin?, type argument
(0, True, "int")
]),
] ]
from collections import namedtuple from collections import namedtuple
adt = namedtuple('adt', ['name', 'newName', 'isVariant', 'ctorsOrFields']) adt = namedtuple('adt', ['name', 'newName', 'kind', 'ctorsOrFields'])
ctorOrField = namedtuple('ctorOrField', ['name', 'newName', 'isBuiltin', 'type_', 'newType']) ctorOrField = namedtuple('ctorOrField', ['name', 'newName', 'isBuiltin', 'type_', 'newType'])
adts = [ adts = [
adt( adt(
name = name, name = name,
newName = f"{name}'", newName = f"{name}'",
isVariant = isVariant, kind = kind,
ctorsOrFields = [ ctorsOrFields = [
ctorOrField( ctorOrField(
name = cf, name = cf,
@ -40,23 +55,32 @@ adts = [
for (cf, isBuiltin, type_) in ctors for (cf, isBuiltin, type_) in ctors
], ],
) )
for (name, isVariant, ctors) in adts for (name, kind, ctors) in adts
] ]
print("(* This is an auto-generated file. Do not edit. *)")
print("")
print("open %s" % moduleName) print("open %s" % moduleName)
print("") print("")
for (index, t) in enumerate(adts): for (index, t) in enumerate(adts):
typeOrAnd = "type" if index == 0 else "and" typeOrAnd = "type" if index == 0 else "and"
print(f"{typeOrAnd} {t.newName} =") print(f"{typeOrAnd} {t.newName} =")
if t.isVariant: if t.kind == variant:
for c in t.ctorsOrFields: for c in t.ctorsOrFields:
print(f" | {c.newName} of {c.newType}") print(f" | {c.newName} of {c.newType}")
else: elif t.kind == record:
print(" {") print(" {")
for f in t.ctorsOrFields: for f in t.ctorsOrFields:
print(f" {f.newName} : {f.newType} ;") print(f" {f.newName} : {f.newType} ;")
print(" }") print(" }")
else:
print(" ", end='')
for a in t.ctorsOrFields:
print(f"{a.newType}", end=' ')
print(t.kind, end='')
print("")
print("") print("")
print(f"type 'state continue_fold =") print(f"type 'state continue_fold =")
@ -107,10 +131,10 @@ print("let no_op : 'a fold_config = {")
for t in adts: for t in adts:
print(f" {t.name} = (fun v state continue ->") print(f" {t.name} = (fun v state continue ->")
print(" match v with") print(" match v with")
if t.isVariant: if t.kind == variant:
for c in t.ctorsOrFields: for c in t.ctorsOrFields:
print(f" | {c.name} v -> let (v, state) = continue.{t.name}_{c.name} v state in ({c.newName} v, state)") print(f" | {c.name} v -> let (v, state) = continue.{t.name}_{c.name} v state in ({c.newName} v, state)")
else: elif t.kind == record:
print(" {", end=' ') print(" {", end=' ')
for f in t.ctorsOrFields: for f in t.ctorsOrFields:
print(f"{f.name};", end=' ') print(f"{f.name};", end=' ')
@ -121,6 +145,10 @@ for t in adts:
for f in t.ctorsOrFields: for f in t.ctorsOrFields:
print(f"{f.newName};", end=' ') print(f"{f.newName};", end=' ')
print("}, state)") print("}, state)")
else:
print(f" v -> fold_{t.kind} v state (", end=' ')
print(", ".join([f"continue.{t.name}_{f.name}" for f in t.ctorsOrFields]), end='')
print(" )")
print(" );") print(" );")
print(f" {t.name}_pre_state = (fun v state -> ignore v; state) ;") print(f" {t.name}_pre_state = (fun v state -> ignore v; state) ;")
print(f" {t.name}_post_state = (fun v new_v state -> ignore (v, new_v); state) ;") print(f" {t.name}_post_state = (fun v new_v state -> ignore (v, new_v); state) ;")

View File

@ -4,7 +4,7 @@ open Fold
(* TODO: how should we plug these into our test framework? *) (* TODO: how should we plug these into our test framework? *)
let () = let () =
let some_root : root = A { a1 = X (A { a1 = X (B 1) ; a2 = W () ; }) ; a2 = Z (W ()) ; } in let some_root : root = A [{ a1 = X (A [{ a1 = X (B [1;2;3]) ; a2 = W () ; }]) ; a2 = Z (W ()) ; }] in
let op = { let op = {
no_op with no_op with
a = fun the_a state continue_fold -> a = fun the_a state continue_fold ->
@ -23,7 +23,7 @@ let () =
() ()
let () = let () =
let some_root : root = A { a1 = X (A { a1 = X (B 1) ; a2 = W () ; }) ; a2 = Z (W ()) ; } in let some_root : root = A [{ a1 = X (A [{ a1 = X (B [1;2;3]) ; a2 = W () ; }]) ; a2 = Z (W ()) ; }] in
let op = { no_op with a_pre_state = fun _the_a state -> state + 1 } in let op = { no_op with a_pre_state = fun _the_a state -> state + 1 } in
let state = 0 in let state = 0 in
let (_, state) = fold_root op some_root state in let (_, state) = fold_root op some_root state in
@ -33,7 +33,7 @@ let () =
() ()
let () = let () =
let some_root : root = A { a1 = X (A { a1 = X (B 1) ; a2 = W () ; }) ; a2 = Z (W ()) ; } in let some_root : root = A [{ a1 = X (A [{ a1 = X (B [1;2;3]) ; a2 = W () ; }]) ; a2 = Z (W ()) ; }] in
let op = { no_op with a_post_state = fun _the_a _new_a state -> state + 1 } in let op = { no_op with a_post_state = fun _the_a _new_a state -> state + 1 } in
let state = 0 in let state = 0 in
let (_, state) = fold_root op some_root state in let (_, state) = fold_root op some_root state in