output.pl 3.63 KB
% == No, Emacs this is -*-Prolog-*- code, not what you thought... =============

% == Code generation for PaCCS ================================================

cg_emit(fzn(preds(PS), vars(VS), constrs(CS), G), ST) :-
    cg_emit(PS, VS, CS, G, ST, TEXT, []),
    format("~s\n", [TEXT]).

cg_emit(PS, VS, CS, G, ST) -->
    cg_prefix,
    cg_preds(PS, ST),
    "\n",
    cg_vars(decl, VS, ST),
    cg_vars(init, VS, ST),
    "\n",
    cg_constrs(CS, ST),
    "\n",
    cg_goal(G, VS, ST),
    cg_suffix.

% == DCGs for code generation =================================================


% -- predicates ---------------------------------------------------------------

cg_preds(_PS, _ST) --> [].


% -- variables ----------------------------------------------------------------

cg_vars(OP,  [V|Vs], ST) --> cg_var(OP, V, ST), cg_vars(OP, Vs, ST).
cg_vars(_OP, [], _) --> [].

cg_var(OP, var(N,int,I,A), ST) --> 
    { ! },
    cg_var(OP, var(N,int(1,999),I,A), ST). % FIXME


cg_var(decl, var(N,int(LB,UB),_I,_A), _ST) -->
    { format_to_codes(S, "  fd_int ~w = fd_new(~d, ~d);\n", [N, LB, UB]) },
    S.

cg_var(init, var(_,int(_,_),_,_), _ST) --> [].

cg_var(decl, val(N,int,lit(INIT,_),_), _) -->
    { format_to_codes(S, "  int ~w = ~w;\n", [N, INIT]) },
    S.

cg_var(init, val(_,int,_,_), _ST) --> [].

% -- array of variables - - - - - - - - - - - - - - - - - - - - - - - - - - - -

cg_var(decl, var(N,array(_T,LB,UB),[],_), _ST) --> !,
    { SZ is UB-LB+1,
      format_to_codes(S, "  fd_int ~w[~d];\n", [N, SZ]) },
    S.

cg_var(init, var(N,array(T,ALB,AUB),[],_), _ST) --> !,
    { SZ is AUB-ALB+1, bound(lb, T, LB), bound(ub, T, UB) },
    { format_to_codes(S1, "  for (i=0; i<~d; ++i)\n", [SZ]) }, S1,
    { format_to_codes(S2, "    ~w[i] = fd_new(~d, ~d);\n", [N, LB, UB]) }, S2.

% -- array of constants - - - - - - - - - - - - - - - - - - - - - - - - - - - -

cg_var(decl, val(N,array(_T,LB,UB),lit(INIT,array(_)),_), _ST) --> 
    { nonvar(INIT), INIT=[_|_] }, !,
    { SZ is UB-LB+1,
      format_to_codes(S, "  int ~w[~d] = {", [N, SZ]) },
    S,
    cg_constant_list(INIT, " "),
    " };\n".

cg_var(init, val(_N,array(_T,_LB,_UB),lit(INIT,array(_)),_), _ST) -->
    { nonvar(INIT), INIT=[_|_] }, !,
    [].


% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

cg_constant_list([], _) --> [].
cg_constant_list([C|Cs], PFX) --> 
    PFX, cg_constant(C),
    cg_constant_list(Cs, ", ").

cg_constant(lit(N,int)) --> { format_to_codes(S, "~w", [N]) }, S.


% -- constraints --------------------------------------------------------------

cg_constrs([], _) --> {!}, [].
cg_constrs(CS, ST) --> cg_coverage(CS, CR, ST), cg_constrs(CR, ST).

% ++ cg_coverage(CI, CO, ST) [DCG]  - - - - - - - - - - - - - - - - - - - - - -
%
% emit an instruction which partly covers CI, leaving CO untreated
% FIXME: still need to search for an optimal solution...

cg_coverage([constraint(CE, _A)|CS], CS, ST) --> cv_basic(CE, ST).


% -- goal ---------------------------------------------------------------------

cg_goal(solve(satisfy,_), VS, ST) --> % FIXME: add minimize and maximize
    "\n",
    "  if (fd_solve()) {\n",
    cg_var_print(VS, ST, "    "),
    "  }\n",
    "  fd_end();\n".

cg_var_print([], _, _) --> [].
cg_var_print([var(N,_,_,A)|Vs], ST, PFX) -->
    { member(output, A), ! },
    { format_to_codes(S, "~sfd_println(~w);\n", [PFX, N]) }, S,
    cg_var_print(Vs, ST, PFX).
cg_var_print([_|Vs], ST, PFX) --> cg_var_print(Vs, ST, PFX).


% -- prefix and suffix --------------------------------------------------------

cg_prefix -->
    "#include \"paccs.h\"\n\n",
    "int main(int argc, char *argv[])\n",
    "{\n",
    "  int i, j;\n".

cg_suffix -->
    "}\n".