Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
c.ml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165(**********************************************************************) (* *) (* This file is part of the FSML library *) (* github.com/jserot/fsml *) (* *) (* Copyright (c) 2020-present, Jocelyn SEROT. All rights reserved. *) (* *) (* This source code is licensed under the license found in the *) (* LICENSE file in the root directory of this source tree. *) (* *) (**********************************************************************) (* C backend *) open Printf type config = { mutable state_var: string; mutable incl_file: string } let cfg = { state_var = "state"; incl_file = "fsml.h" } exception Error of string * string (* where, message *) let string_of_type t = match Types.real_type t with | Types.TyBool -> "int" | Types.TyInt (sg, _, _) when sg = Types.Const Unsigned-> "unsigned int" | Types.TyInt _ -> "int" | _ -> failwith ("C backend: illegal type: " ^ Types.to_string t) let string_of_typed_item ?(ptr=false) (id,ty) = match ty with | _ -> string_of_type ty ^ " " ^ (if ptr then "*" else "") ^ id (* let string_of_value v = match v with * | Expr.Int i -> string_of_int i * | Expr.Bool b -> string_of_bool b *) let string_of_comp m id = if List.mem_assoc id m.Seqmodel.m_vars then id else "ctx->" ^ id let rec string_of_expr m e = let paren level s = if level > 0 then "(" ^ s ^ ")" else s in let rec string_of level e = match e.Expr.e_desc with Expr.EInt c -> string_of_int c | Expr.EBool c -> if c then "1" else "0" | Expr.EVar n -> string_of_comp m n | Expr.EBinop (op,e1,e2) -> paren level (string_of (level+1) e1 ^ string_of_op op ^ string_of (level+1) e2) in string_of 0 e and string_of_op = function "=" -> "==" | op -> op let string_of_guard m exp = string_of_expr m exp let string_of_action m a = match a with | Action.Assign (id, expr) -> string_of_comp m id ^ "=" ^ string_of_expr m expr let dump_action oc m tab a = fprintf oc "%s%s;\n" tab (string_of_action m a) let dump_transition oc m tab is_first src (_,guards,acts,dst) = match guards with | [] -> List.iter (dump_action oc m tab) acts; if dst <> src then fprintf oc "%s%s = %s;\n" tab cfg.state_var dst | _ -> fprintf oc "%s%sif ( %s ) {\n" tab (if is_first then "" else "else ") (Misc.string_of_list ~f:(string_of_guard m) ~sep:" && " guards); List.iter (dump_action oc m (tab ^ " ")) acts; if dst <> src then fprintf oc "%s %s = %s;\n" tab cfg.state_var dst; fprintf oc "%s }\n" tab let dump_transitions oc m src after tss = if after then fprintf oc " else {\n"; let tab = if after then " " else " " in begin match tss with [] -> () (* no wait in this case *) | _ -> Misc.iter_fst (fun is_first t -> dump_transition oc m tab is_first src t) tss; end; if after then fprintf oc " }\n" let dump_output_valuation oc m state = let open Seqmodel in assert (List.mem_assoc state m.m_states); List.iter (fun (o,e) -> fprintf oc " %s = %s;\n" (string_of_comp m o) (string_of_expr m e)) (List.assoc state m.m_states) let dump_state_case oc m (src, tss) = fprintf oc " case %s:\n" src; dump_output_valuation oc m src; dump_transitions oc m src false tss; fprintf oc " break;\n" let dump_impl prefix fname m = let open Seqmodel in let modname = "fsm_" ^ m.m_name in let oc = open_out fname in fprintf oc "#include \"%s.h\"\n" prefix; fprintf oc "#include <stdio.h>\n\n"; let ctx_comps = List.map fst (m.m_inps @ m.m_outps @ m.m_vars) in fprintf oc "void dump_ctx(ctx_t ctx)\n"; fprintf oc "{\n"; fprintf oc " printf(\"%s\\n\", %s);\n" (Misc.string_of_list ~f:(fun id -> id ^ "=%d") ~sep:" " ctx_comps) (Misc.string_of_list ~f:(fun id -> "ctx." ^ id) ~sep:", " ctx_comps); fprintf oc "}\n\n"; fprintf oc "void %s(ctx_t *ctx)\n" modname; fprintf oc "{\n"; List.iter (fun (id,ty) -> fprintf oc " static %s;\n" (string_of_typed_item (id,ty))) m.m_vars; if List.length m.m_states > 1 then fprintf oc " static enum { %s } %s;\n" (Misc.string_of_list ~f:fst ~sep:", " m.m_states) cfg.state_var; fprintf oc " static int _init = 1;\n"; fprintf oc " if ( _init ) {\n"; List.iter (dump_action oc m " ") (snd m.m_init); fprintf oc " %s=%s;\n" cfg.state_var (fst m.m_init); fprintf oc " _init=0;\n"; fprintf oc " }\n"; begin match m.m_body with [] -> () (* should not happen *) | [c] -> dump_state_case oc m c | _ -> fprintf oc " switch ( %s ) {\n" cfg.state_var; List.iter (dump_state_case oc m) m.m_body; fprintf oc " }\n" end; List.iter (fun (id,_) -> fprintf oc " ctx->%s = %s;\n" id id) m.m_vars; fprintf oc "};\n"; printf "Wrote file %s\n" fname; close_out oc let dump_intf prefix fname m = let open Seqmodel in let oc = open_out fname in let modname = "fsm_" ^ m.m_name in fprintf oc "#ifndef _%s_h\n" prefix; fprintf oc "#define _%s_h\n\n" prefix; fprintf oc "#include \"%s\"\n\n" cfg.incl_file; fprintf oc "typedef struct {\n"; List.iter (fun (id,ty) -> fprintf oc " IN %s;\n" (string_of_typed_item (id,ty))) m.m_inps; List.iter (fun (id,ty) -> fprintf oc " OUT %s;\n" (string_of_typed_item (id,ty))) m.m_outps; List.iter (fun (id,ty) -> fprintf oc " %s;\n" (string_of_typed_item (id,ty))) m.m_vars; fprintf oc "} ctx_t;\n\n"; fprintf oc "void dump_ctx(ctx_t ctx);\n"; fprintf oc "void %s(ctx_t *ctx);\n\n" modname; fprintf oc "#endif\n"; printf "Wrote file %s\n" fname; close_out oc let write ?(dir="") ~prefix f = let m = Seqmodel.make f in let () = Misc.check_dir dir in let p = dir ^ Filename.dir_sep ^ prefix in dump_intf prefix (p ^ ".h") m; dump_impl prefix (p ^ ".c") m