[m-rev.] for review: initial erlang code generator

Peter Wang wangp at students.csse.unimelb.edu.au
Mon May 14 18:03:40 AEST 2007


On 2007-05-14, Peter Ross <pro at missioncriticalit.com> wrote:
> On Mon, May 14, 2007 at 02:02:13PM +1000, Peter Wang wrote:
> > 
> > library/array.m:
> > library/bitmap.m:
> > library/io.m:
> > 	Add Erlang foreign_type declarations for array(T),
> > 	bitmap and io.system_error.
> > 
> Say why you've added these.

Done.

> > +:- type elds_term
> > +    --->    elds_char(char)
> > +    ;       elds_int(int)
> > +    ;       elds_float(float)
> > +    ;       elds_string(string)
> > +    ;       elds_atom_raw(string)
> > +    ;       elds_atom(sym_name)
> 
> what is the difference between these two, a comment of some sort is
> needed.

Done.

> > +    % expr_or_void(MaybeExpr)
> > +    %
> > +    % Return `E' if MaybeExpr unifies with `yes(E)', or any constant expression
> > +    % if MaybeExpr unifies with `no'.  MaybeExpr should only be `no' if value
> > +    % that an expression evaluates to doesn't matter.
> > +    %
> > +:- func expr_or_void(maybe(elds_expr)) = elds_expr.
> > +
> I find the above hard to parse.  Can you reword it?  I'm not sure how.

Done.

> > +:- pred output_var(prog_varset::in, prog_var::in, io::di, io::uo) is det.
> > +
> > +output_var(VarSet, Var, !IO) :-
> > +    varset.lookup_name(VarSet, Var, VarName),
> > +    term.var_to_int(Var, VarNumber),
> > +    % XXX this assumes all Mercury variable names are a subset of Erlang
> > +    % variable names
> 
> But you think it is because of Erlangs roots in prolog, correct?

Yes.

> > +    % erl_gen_call(PredId, ProcId, ArgNames, ArgTypes,
> > +    %   CodeModel, Context, SuccessExpr, Statement, !Info):
> > +    %
> > +    % Generate ELDS code for an HLDS procedure call.
> > +    %
> > +:- pred erl_gen_call(pred_id::in, proc_id::in, prog_vars::in,
> > +    list(mer_type)::in, code_model::in, prog_context::in, maybe(elds_expr)::in,
> > +    elds_expr::out, erl_gen_info::in, erl_gen_info::out) is det.
> > +
> What is a SuccessExpr?
> 

I've added a comment above erl_gen_goal.

> > +:- pred erl_gen_negation(hlds_goal::in, code_model::in, instmap::in,
> > +    prog_context::in, maybe(elds_expr)::in, elds_expr::out,
> > +    erl_gen_info::in, erl_gen_info::out) is det.
> > +
> > +erl_gen_negation(Cond, CodeModel, InstMap, _Context, MaybeSuccessExpr,
> > +        Statement, !Info) :-
> > +    Cond = hlds_goal(_, CondGoalInfo),
> > +    goal_info_get_code_model(CondGoalInfo, CondCodeModel),
> > +    (
> > +        % model_det negation:
> > +        %       <not(Goal)>
> > +        %   ===>
> > +
> > +        CodeModel = model_det,
> > +        % XXX haven't found a test case for this yet
> > +        sorry(this_file, "erl_gen_negation: model_det")
> 
> :- pred q is det.
> q :- not p.
> 
> :- pred p is failure.
> p :- fail.

Thanks.  I think that's implemented now.

> > +    % erl_bind_unbound_vars(ModuleInfo, VarsToBind, Goal, InstMap,
> > +    %   !Statement)
> > +    %
> > +    % For any variables in VarsToBind which are not bound in Goal, add
> > +    % assignment expressions to !Statement.  This is necessary to ensure that
> > +    % all branches of ELDS code bind the same variables, to avoid warnings from
> > +    % the Erlang compiler when one branch doesn't bind all the variables
> > +    % because it has determinism `erroneous'.
> > +    %
> > +:- pred erl_bind_unbound_vars(module_info::in, set(prog_var)::in,
> > +    hlds_goal::in, instmap::in, elds_expr::in, elds_expr::out) is det.
> > +
> Mention that it doesn't matter to what the variables are bound to.

Done.

Interdiff follows.


diff -u compiler/elds.m compiler/elds.m
--- compiler/elds.m	14 May 2007 04:00:50 -0000
+++ compiler/elds.m	14 May 2007 07:57:06 -0000
@@ -79,6 +79,13 @@
     ;       elds_string(string)
     ;       elds_atom_raw(string)
     ;       elds_atom(sym_name)
+            % `elds_atom_raw' is useful to introduce arbitrary atoms into the
+            % generated code.
+            %
+            % `elds_atom' is intended to be used with functors; how a functor
+            % is ultimately written out is not the concern of the ELDS code
+            % generator.
+
     ;       elds_tuple(list(elds_expr))
     ;       elds_var(prog_var)
     ;       elds_anon_var.
@@ -156,9 +163,9 @@
 
     % expr_or_void(MaybeExpr)
     %
-    % Return `E' if MaybeExpr unifies with `yes(E)', or any constant expression
-    % if MaybeExpr unifies with `no'.  MaybeExpr should only be `no' if value
-    % that an expression evaluates to doesn't matter.
+    % Return `E' if MaybeExpr is `yes(E)', otherwise return any constant
+    % expression.  This function should only be used if the return value
+    % doesn't matter if MaybeExpr can be `no'.
     %
 :- func expr_or_void(maybe(elds_expr)) = elds_expr.
 
diff -u compiler/erl_code_gen.m compiler/erl_code_gen.m
--- compiler/erl_code_gen.m	14 May 2007 04:00:50 -0000
+++ compiler/erl_code_gen.m	14 May 2007 07:57:07 -0000
@@ -253,6 +253,10 @@
 
     % Generate ELDS code for the specified goal in the specified code model.
     %
+    % If MaybeSuccessExpr is `yes(SuccessExpr)' then SuccessExpr is the
+    % expression that the code generated for Goal must evaluate to, if the Goal
+    % succeeds.
+    %
 erl_gen_goal(CodeModel, InstMap, Goal, MaybeSuccessExpr, Code, !Info) :-
     Goal = hlds_goal(GoalExpr, GoalInfo),
     goal_info_get_context(GoalInfo, Context),
@@ -588,10 +593,16 @@
         % model_det negation:
         %       <not(Goal)>
         %   ===>
+        %       <Goal>  % must fail
 
         CodeModel = model_det,
-        % XXX haven't found a test case for this yet
-        sorry(this_file, "erl_gen_negation: model_det")
+
+        % The code generator expects semidet goals to always have a success
+        % expression, although in this case we know it won't arise at run time.
+        DummySuccessExpr = elds_term(elds_empty_tuple),
+        erl_gen_goal(model_semi, InstMap, Cond, yes(DummySuccessExpr),
+            CondStatement, !Info),
+        Statement = maybe_join_exprs(CondStatement, MaybeSuccessExpr)
     ;
         % model_semi negation, model_det goal:
         %       <succeeded = not(Goal)>
diff -u compiler/erl_code_util.m compiler/erl_code_util.m
--- compiler/erl_code_util.m	14 May 2007 04:00:50 -0000
+++ compiler/erl_code_util.m	14 May 2007 07:57:07 -0000
@@ -100,7 +100,9 @@
     % assignment expressions to !Statement.  This is necessary to ensure that
     % all branches of ELDS code bind the same variables, to avoid warnings from
     % the Erlang compiler when one branch doesn't bind all the variables
-    % because it has determinism `erroneous'.
+    % because it has determinism `erroneous'.  The values given to the
+    % variables do not matter since this is only done to appease the
+    % Erlang compiler.
     %
 :- pred erl_bind_unbound_vars(module_info::in, set(prog_var)::in,
     hlds_goal::in, instmap::in, elds_expr::in, elds_expr::out) is det.
only in patch2:
unchanged:
--- compiler/notes/compiler_design.html	11 Jan 2007 03:36:01 -0000	1.126
+++ compiler/notes/compiler_design.html	14 May 2007 07:57:07 -0000
@@ -121,6 +121,13 @@
                <ul type=disc>
                <li> 4c. code generation (annotated HLDS -> bytecode)
                </ul>
+          <li> d. Erlang back-end
+               <br> Package: erl_backend.m
+               <ul type=disc>
+               <li> 4d. code generation (annotated HLDS -> ELDS)
+               <li> 6d. output code
+     	       (ELDS -> Erlang)
+               </ul>
           <li> There's also a package backend_libs.m which contains
 	       modules which are shared between several different back-ends.
           </ul>
@@ -1543,7 +1550,7 @@
 <hr>
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
-<h3> d. BYTECODE BACK-END </h3>
+<h3> c. BYTECODE BACK-END </h3>
 
 <p>
 This is the bytecode_backend.m package.
@@ -1570,6 +1577,41 @@
 <hr>
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
+<h3> d. ERLANG BACK-END </h3>
+
+<p>
+This is the erl_backend.m package.
+
+<p>
+
+The Mercury compiler can translate Mercury programs into Erlang.
+The intent of this is to take advantage of the features of the
+Erlang implementation (concurrency, fault tolerance, etc.)
+However, the backend is still incomplete.
+This back-end uses the Erlang Data Structure (elds.m) as its
+intermediate representation.
+
+<h4> 4d. ELDS code generation </h4>
+<ul>
+<li> erl_code_gen.m converts HLDS code to ELDS.
+	  The following sub-modules are used to handle different constructs:
+		<ul>
+		<li> erl_unify_gen.m
+		<li> erl_call_gen.m
+		</ul>
+	  The module erl_code_util.m provides utility routines for
+	  ELDS code generation.
+</ul>
+
+<h4> 6d. ELDS output </h4>
+
+<ul>
+<li>elds_to_erlang.m converts ELDS to Erlang code.
+</ul>
+
+<hr>
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
 <h3> SMART RECOMPILATION </h3>
 
 <p>


--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list