Skip to content

Commit

Permalink
* added K-form pretty printing module; works reasonably good
Browse files Browse the repository at this point in the history
* some small improvements and cleanups at various places
  • Loading branch information
vpisarev committed Mar 18, 2021
1 parent 65ec25a commit dfc26d0
Show file tree
Hide file tree
Showing 22 changed files with 623 additions and 102 deletions.
9 changes: 9 additions & 0 deletions compiler/Ast.fx
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,15 @@ fun get_numeric_typ_size(t: typ_t, allow_tuples: bool): int =
| _ => -1
}

fun string(fm: for_make_t)
{
| ForMakeNone => "ForMakeNone"
| ForMakeArray => "ForMakeArray"
| ForMakeList => "ForMakeList"
| ForMakeTuple => "ForMakeTuple"
| _ => "ForMake???"
}

fun string(c: cmpop_t) {
| CmpEQ => "=="
| CmpNE => "!="
Expand Down
7 changes: 4 additions & 3 deletions compiler/AstTypeChecker.fx
Original file line number Diff line number Diff line change
Expand Up @@ -2668,8 +2668,9 @@ fun instantiate_variant(ty_args: typ_t list, dvar: defvariant_t ref, env: env_t,
| (TypTuple(telems), _) when nrealargs == nargs => telems
| _ =>
throw compile_err( loc,
f"cannot instantiate case '{id2str(ctor_name)}' of variant '{id2str(dvar_name)}' defined at '{dvar_loc}':"
+ f"wrong number of actual parameters {nrealargs} (vs {nargs} expected)" )
f"cannot instantiate case '{id2str(ctor_name)}' of variant " +
f"'{id2str(dvar_name)}' defined at '{dvar_loc}': " +
f"wrong number of actual parameters {nrealargs} (vs {nargs} expected)" )
}
val (inst_cname, _) = register_typ_constructor(ctor_name, CtorVariant(n),
inst_dvar->dvar_templ_args, argtyps,
Expand Down Expand Up @@ -2800,7 +2801,7 @@ fun check_pat(pat: pat_t, typ: typ_t, env: env_t, idset: idset_t, typ_vars: idse
(n, p)
| _ =>
throw compile_err( loc,
f"element '{pp_id2str(n)}' is not found in the record '{pp_id2str(rn_opt.getsome(noid))}'")
f"element '{pp_id2str(n)}' is not found in the record '{pp_id2str(rn_opt.value_or(noid))}'")
} } :]
(PatRecord(if ctor != noid {Some(ctor)} else {None}, new_relems, loc), false)
| PatCons(p1, p2, loc) =>
Expand Down
15 changes: 9 additions & 6 deletions compiler/Compiler.fx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
// (calls all other parts of the compiler in the proper order)

import Filename, Sys, Map
import Ast, AstTypeChecker, AstPP, KForm, KNormalize, Lexer, Parser, Options
import Ast, AstPP, Lexer, Parser, Options
import AstTypeChecker
import KForm, KPP, KNormalize

exception CumulativeParseError

type id_t = Ast.id_t
val pr_verbose = Ast.pr_verbose

fun get_preamble(mfname: string): Lexer.token_t list {
val bare_name = Filename.remove_extension(Filename.basename(mfname))
Expand Down Expand Up @@ -326,19 +329,19 @@ fun process_all(fname0: string): bool {
}
}
val modules_used = ", ".join(Ast.all_modules_sorted.map(Ast.pp_id2str))
Ast.pr_verbose(f"Parsing complete. Modules used: {modules_used}")
pr_verbose(f"Parsing complete. Modules used: {modules_used}")
val ok = typecheck_all(Ast.all_modules_sorted)
Ast.pr_verbose("Type checking complete")
pr_verbose("Type checking complete")
if ok && Options.opt.print_ast {
for m <- Ast.all_modules_sorted {
val minfo = Ast.get_module(m)
AstPP.pprint_mod(minfo)
}
}
val (kmods, ok) = if ok { k_normalize_all(Ast.all_modules_sorted) } else { ([], false) }
/*pr_verbose("K-normalization complete")
if ok && options.print_k0 { K_pp.pprint_kmods(kmods) }
pr_verbose("K-form optimization started")
pr_verbose("K-normalization complete")
if ok && Options.opt.print_k0 { KPP.pp_kmods(kmods) }
/*pr_verbose("K-form optimization started")
val (kmods, ok) = if ok { k_optimize_all(kmods) } else { ([], false) }
if ok { pr_verbose("K-form optimization complete") }
if ok && options.print_k { K_pp.pprint_kmods(kmods) }
Expand Down
42 changes: 22 additions & 20 deletions compiler/KForm.fx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

/*
K-normal form (or K-form in short) definition.
This is a greatly extended variant of K-normal form in min-caml:
This is a greatly extended variation of K-normal form in min-caml:
https://github.com/esumii/min-caml.

Similarly to ficus AST, which is defined in ast.ml,
Similarly to ficus AST, which is defined in Ast.fx,
K-form is an hierarchical (tree-like) representation of
the compiled code. However, it's much simpler and more
suitable for intermediate optimizations and then for
Expand All @@ -17,21 +17,23 @@
In particular:

* all the symbols in K-form are resolved and unique, e.g:
fun foo(i: int) { val i = i+1; val i = i*2; for(i<-0:i) println(i) }
type i = int
fun foo(i: i) { val i = i+1; val i = i*2; for i<-0:i {println(i)} }
is transformed to something like
fun foo@999(i@1000: int): int {
fun foo@999(i@1000: int): void {
val i@1001: int = i@1000+1; val i@1002: int = i@1001*2
for ((i@1003:int) <- 0:i@1002) println@56<int->void>(i@1003)
for (i@1003:int) <- 0:i@1002 {println@56<int->void>(i@1003)}
}
* all the symbols have known type. If it cannot be figured out,
type checker or the k-form generator (see k_norm.ml) report compile error.
type checker or the k-form generator (see KNormalize.fx) report compile error.
* at once, all the types (typ_t) are converted to k-types (ktyp_t), i.e.
all indirections are eliminated, instances of generic types
(TypApp(<args...>, <some_generic_type_id>)) are replaced with concrete instances
(KTypName(<instance_type_id>)) or even actual types where applicable.
(KTypName(<instance_type_id>)) or even actual types where applicable
(like the type alias 'i' above was replaced with it's actual meaning, i.e. 'int').
* all complex expressions are broken down into sequences of basic operations
with intermediate results stored in temporary values.
* pattern matching is converted into a sequences of nested if-expressions
* pattern matching is converted into sequences of nested if-expressions
* import directives are removed; we've already resolved all the symbols
* generic types and functions are removed. Their instances, generated
by type checker, are retained though.
Expand Down Expand Up @@ -438,17 +440,17 @@ fun get_atom_ktyp(a: atom_t, loc: loc_t): ktyp_t =
| AtomLit(l) => get_lit_ktyp(l)
}

fun intrin2str(iop: intrin_t): string
fun string(iop: intrin_t): string
{
| IntrinPopExn => "INTRIN_POP_EXN"
| IntrinVariantTag => "INTRIN_VARIANT_TAG"
| IntrinVariantCase => "INTRIN_VARIANT_CASE"
| IntrinListHead => "INTRIN_LIST_HD"
| IntrinListTail => "INTRIN_LIST_TL"
| IntrinStrConcat => "INTRIN_STR_CONCAT"
| IntrinGetSize => "INTRIN_GET_SIZE"
| IntrinCheckIdx => "INTRIN_CHECK_IDX"
| IntrinCheckIdxRange => "INTRIN_CHECK_IDX_RANGE"
| IntrinPopExn => "__pop_exn__"
| IntrinVariantTag => "__variant_tag__"
| IntrinVariantCase => "__variant_case__"
| IntrinListHead => "__hd__"
| IntrinListTail => "__tl__"
| IntrinStrConcat => "__intrin_str_concat__"
| IntrinGetSize => "__intrin_size__"
| IntrinCheckIdx => "__check_idx__"
| IntrinCheckIdxRange => "__check_range__"
}

fun get_code_loc(code: kcode_t, default_loc: loc_t) =
Expand Down Expand Up @@ -1132,7 +1134,7 @@ fun ktyp2str(t: ktyp_t): string
fun klit2str(lit: klit_t, cmode: bool, loc: loc_t): string
{
match lit {
| KLitInt(v) => f"{v}i"
| KLitInt(v) => f"{v}"
| KLitSInt(64, v) =>
if cmode { f"{v}iLL" } else { f"{v}ii{64}" }
| KLitUInt(64, v) =>
Expand Down Expand Up @@ -1170,7 +1172,7 @@ fun kexp2str(e: kexp_t): string
| KExpAtom(a, _) => "KExpAtom(" + atom2str(a) + ")"
| KExpBinary(bop, a, b, _) => f"KExpBinary({bop}, {atom2str(a)}, {atom2str(b)})"
| KExpUnary(uop, a, _) => f"KExpUnary({uop}, {atom2str(a)})"
| KExpIntrin(i, _, _) => f"KExpIntrin({intrin2str(i)}, ...)"
| KExpIntrin(i, _, _) => f"KExpIntrin({i}), ...)"
| KExpSeq(_, _) => "KExpSeq(...)"
| KExpIf(_, _, _, _) => "KExpIf(...)"
| KExpCall(f, args, _) => f"KExpCall({idk2str(f, l)}, ...)"
Expand Down
15 changes: 8 additions & 7 deletions compiler/KNormalize.fx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

/*
Converts the Abstract Syntax Tree (ast.ml) into K-form (K_form.ml).
Converts the Abstract Syntax Tree (Ast.fx) into K-form (KForm.fx).

For now only the global compilation mode is supported, i.e.
the code from all the modules, used in the program,
Expand Down Expand Up @@ -544,7 +544,7 @@ fun exp2id(e: exp_t, code: kcode_t, tref: bool, sc: scope_t list, msg: string):

fun exp2dom(e: exp_t, code: kcode_t, sc: scope_t list): (dom_t, kcode_t) =
match e {
| ExpRange(_, _, _, _) =>
| ExpRange _ =>
val (ek, code) = exp2kexp(e, code, false, sc)
match ek {
| KExpMkTuple(a :: b :: c :: [], _) => (DomainRange(a, b, c), code)
Expand Down Expand Up @@ -642,7 +642,7 @@ fun match_record_pat(pat: pat_t, ptyp: ktyp_t): ((id_t, ktyp_t, bool, bool), (id
else { (found_idx, found_t) }
}
if found_idx < 0 {
throw compile_err(loc, f"element '{pp_id2str(ni)}' is not found in the record '{pp_id2str(rn_opt.getsome(noid))}'")
throw compile_err(loc, f"element '{pp_id2str(ni)}' is not found in the record '{pp_id2str(rn_opt.value_or(noid))}'")
}
(ni, pi, found_t, found_idx) :: typed_rec_pl
}
Expand Down Expand Up @@ -1381,8 +1381,9 @@ fun normalize_all_modules(modules: id_t list): kmodule_t list
val kcode_typedefs = transform_all_types_and_cons(minfo.dm_defs, [], modsc)
(m, minfo, kcode_typedefs) :: modules_plus
}
fold kmods = [] for (m, minfo, kcode_typedefs)@i <- modules_plus.rev() {
val km = normalize_mod(m, minfo, kcode_typedefs, i + 1 == n)
km :: kmods
}
[:
for (m, minfo, kcode_typedefs)@i <- modules_plus.rev() {
normalize_mod(m, minfo, kcode_typedefs, i + 1 == n)
}
:]
}
Loading

0 comments on commit dfc26d0

Please sign in to comment.