Merge lp:~mgiuca/mars/atom into lp:mars

Proposed by Matt Giuca
Status: Merged
Merged at revision: 1262
Proposed branch: lp:~mgiuca/mars/atom
Merge into: lp:mars
Diff against target: 894 lines (+233/-144)
10 files modified
doc/dev/isa.rst (+16/-19)
src/ast_cfg.m (+70/-45)
src/cfg.m (+1/-1)
src/interactive.m (+6/-1)
src/interpret.m (+30/-19)
src/ir.m (+19/-15)
src/pretty.m (+14/-20)
src/typedict.m (+34/-11)
src/usedef.m (+14/-13)
test/cases/compiler/ctorsym-unify.mar (+29/-0)
To merge this branch: bzr merge lp:~mgiuca/mars/atom
Reviewer Review Type Date Requested Status
Matt Giuca Approve
Review via email: mp+79226@code.launchpad.net

Description of the change

Added 'atoms' to instruction set, removed ld_intlit and ld_ctorsym, and changed code generator to generate atoms rather than instructions where possible.

Note that there may be a bug in typedict. See atom_type (it has an XXX). Whereas before, we would have loaded the ctorsym into a variable (which would have been given the correct local type), we are now pulling the type directly out of the global typedef, and ignoring its varset. Therefore, the varset of ctorsyms may be in the wrong namespace for local variables. Check this before merging.

To post a comment you must log in.
lp:~mgiuca/mars/atom updated
1266. By Matt Giuca

Added test case ctorsym-unify for LP: #877111.

1267. By Matt Giuca

Test case ctorsym-unify: Added description, and a new test function that passes Nil as the only argument to a function.

1268. By Matt Giuca

typedict: XXX comment refers to bug LP: #877111.

1269. By Matt Giuca

typedict: Changed atom_type to thread a varset, so that it can augment the varset with ctorsym type variables.
Update code that uses it -- calls augment_globalref with the augmented varset.
Note: Currently atom_type doesn't actually update the varset.

1270. By Matt Giuca

test case ctorsym-unify: cons now calls show on the two arguments, so that it requires the 'a' type dict.
This doesn't really change the test case, but it makes the output more clearly correct (since foo will pass the correct type dictionary).

1271. By Matt Giuca

test case ctorsym: Added a new case, nil_id.
It currently passes, but when I tried to fix LP: #877111 it broke, so best to have it in here.
(reverse in the prelude broke; this is a simplified version of the same problem).

1272. By Matt Giuca

typedict: augment_instr_globalrefs now uses the augmented varset from calling atom_type on a new_closure instruction (previously only did it for a call_global).
This doesn't have any effect now, but fixing atom_type to augment the varset properly would break on new_closure (see the nil_id case in the test file ctorsym-unify).

1273. By Matt Giuca

typedict: atom_type now merges the ctorsym's varset into the local one and updates the type.
Now it performs type unification on a consistent namespace.
Fixes LP: #877111.

1274. By Matt Giuca

interpret: Fix long lines.

Revision history for this message
Matt Giuca (mgiuca) wrote :

Approved.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'doc/dev/isa.rst'
--- doc/dev/isa.rst 2011-05-11 08:14:46 +0000
+++ doc/dev/isa.rst 2011-10-21 03:33:25 +0000
@@ -111,25 +111,22 @@
111The basic instructions form the body of a basic block. Each block may have111The basic instructions form the body of a basic block. Each block may have
112zero or more basic instructions.112zero or more basic instructions.
113113
114Many instructions accept an *atom*, which refers to one of the following:
115
116* A variable name,
117* An arbitrary-precision integer, or
118* A constant symbol (parameterless constructor). This MUST be the name of a
119 constant symbol, not a constructor function.
120
114:samp:`nop`121:samp:`nop`
115 Does nothing.122 Does nothing.
116123
117:samp:`mov {dest} {source}`124:samp:`mov {dest} {source}`
118 Copies the value of variable `source` to `dest`.125 Copies the value of atom `source` to variable `dest`.
119
120:samp:`ld_intlit {dest} {value}`
121 Assigns the integer `value` to `dest`. `value` is an arbitrary-precision
122 integer.
123126
124:samp:`ld_arraylit {dest} {sources}`127:samp:`ld_arraylit {dest} {sources}`
125 Creates a new array, with the values of the variables listed in `sources`128 Creates a new array, with the values of the variables listed in `sources`
126 as its elements, and assigns it to `dest`. `sources` is a list of129 as its elements, and assigns it to `dest`. `sources` is a list of atoms.
127 variable names.
128
129:samp:`ld_ctorsym {dest} {ctor}`
130 Loads the constant symbol constructor `ctor` to `dest`. This sets the
131 variable to that constant value. `ctor` MUST be the name of a constant
132 symbol, not a constructor function.
133130
134:samp:`ld_cgc {dest} {cgc}`131:samp:`ld_cgc {dest} {cgc}`
135 Loads the value of a computable global constant `cgc` to `dest`. This may132 Loads the value of a computable global constant `cgc` to `dest`. This may
@@ -160,7 +157,7 @@
160 Destructively modifies a field of an object, by index of a given157 Destructively modifies a field of an object, by index of a given
161 constructor. Fields are indexed by parameters of the constructor used to158 constructor. Fields are indexed by parameters of the constructor used to
162 create the object (0 is the first parameter, etc).159 create the object (0 is the first parameter, etc).
163 Copies the value of variable `value` to field number `index` of variable160 Copies the value of atom `value` to field number `index` of variable
164 `source`, mutating the object referenced by `source`.161 `source`, mutating the object referenced by `source`.
165 `source` MUST be a variable of an algebraic data type. It MUST be162 `source` MUST be a variable of an algebraic data type. It MUST be
166 statically known to have been constructed with constructor `ctor`. This163 statically known to have been constructed with constructor `ctor`. This
@@ -175,7 +172,7 @@
175 object (0 is the first parameter, etc).172 object (0 is the first parameter, etc).
176 Creates a new object with constructor `ctor`. Initialises all fields of173 Creates a new object with constructor `ctor`. Initialises all fields of
177 the new object with the values of the fields in `source`, except for field174 the new object with the values of the fields in `source`, except for field
178 number `index`, which is initialised to the value of variable `value`.175 number `index`, which is initialised to the value of atom `value`.
179 Assigns the new object to `dest`.176 Assigns the new object to `dest`.
180 `source` MUST be a variable of an algebraic data type. It MUST be177 `source` MUST be a variable of an algebraic data type. It MUST be
181 statically known to have been constructed with constructor `ctor`. This178 statically known to have been constructed with constructor `ctor`. This
@@ -189,7 +186,7 @@
189 result to `dest`. Constructs a new function object with the parameters and186 result to `dest`. Constructs a new function object with the parameters and
190 result of the closure template.187 result of the closure template.
191 `func` MUST be the name of a closure template.188 `func` MUST be the name of a closure template.
192 `args` is a list of variables containing the arguments. It MUST contain189 `args` is a list of atoms containing the arguments. It MUST contain
193 the exact number of closure variables expected by `func`, and any190 the exact number of closure variables expected by `func`, and any
194 supplied arguments must be of correct types.191 supplied arguments must be of correct types.
195192
@@ -203,7 +200,7 @@
203 Calls a function from local variable `func`, supplying arguments `args`200 Calls a function from local variable `func`, supplying arguments `args`
204 and assigning the result to `dest`.201 and assigning the result to `dest`.
205 `func` MUST be a variable containing a function value. `args` is a list of202 `func` MUST be a variable containing a function value. `args` is a list of
206 variables containing the arguments. It MUST contain the exact number of203 atoms containing the arguments. It MUST contain the exact number of
207 arguments expected by `func`, of correct types.204 arguments expected by `func`, of correct types.
208 The execution may cause side-effects or fail to return.205 The execution may cause side-effects or fail to return.
209206
@@ -211,7 +208,7 @@
211 Calls constructor function `ctor`, supplying arguments `args` and208 Calls constructor function `ctor`, supplying arguments `args` and
212 assigning the result to `dest`.209 assigning the result to `dest`.
213 `ctor` MUST not be the name of a constant symbol.210 `ctor` MUST not be the name of a constant symbol.
214 `args` is a list of variables containing the arguments. It MUST contain211 `args` is a list of atoms containing the arguments. It MUST contain
215 the exact number of arguments expected by `ctor`, of correct types.212 the exact number of arguments expected by `ctor`, of correct types.
216213
217:samp:`call_global {dest} {func} {args}`214:samp:`call_global {dest} {func} {args}`
@@ -219,7 +216,7 @@
219 result to `dest`.216 result to `dest`.
220 `func` MUST not be the name of a computable global constant or217 `func` MUST not be the name of a computable global constant or
221 constructor.218 constructor.
222 `args` is a list of variables containing the arguments. It MUST contain219 `args` is a list of atoms containing the arguments. It MUST contain
223 the exact number of arguments expected by `func`, of correct types.220 the exact number of arguments expected by `func`, of correct types.
224 The execution may cause side-effects or fail to return.221 The execution may cause side-effects or fail to return.
225222
@@ -252,7 +249,7 @@
252 for the rather complicated algorithm that performs this translation.249 for the rather complicated algorithm that performs this translation.
253250
254:samp:`cond_branch {if} {then} {else}`251:samp:`cond_branch {if} {then} {else}`
255 Conditional branch based on the value of the `if` variable, which MUST be252 Conditional branch based on the value of the `if` atom, which MUST be
256 an :type:`Int`. If `if` is not equal to 0, branches to the `then` block.253 an :type:`Int`. If `if` is not equal to 0, branches to the `then` block.
257 Otherwise, branches to the `else` block.254 Otherwise, branches to the `else` block.
258255
259256
=== modified file 'src/ast_cfg.m'
--- src/ast_cfg.m 2011-10-10 12:38:16 +0000
+++ src/ast_cfg.m 2011-10-21 03:33:25 +0000
@@ -51,19 +51,21 @@
51:- pred func_to_cfg(progtable::in, function::in, function::out,51:- pred func_to_cfg(progtable::in, function::in, function::out,
52 list(function)::out) is det.52 list(function)::out) is det.
5353
54% expr_to_instrs(+PT, +Expr, -VarName, -Instrs, -Types, -SynthFuncs,54% expr_to_instrs(+PT, +Expr, -Atom, -Instrs, -Types, -SynthFuncs,
55% !ASTState).55% !ASTState).
56% Converts a single expression into a sequence of low-level instructions56% Takes a single expression. If it is atomic (a variable name, int literal or
57% which compute the expression and assign it to a variable (possibly a57% constructor symbol), returns it as an Atom. Otherwise, compiles the
58% new temporary variable name). Returns the assigned variable name in VarName.58% expression into a sequence of low-level instructions which compute the
59% expression and assign it to a new temporary variable name). Returns the
60% assigned variable name in Atom.
59% (May clobber the temporary variable namespace, as there is no block or61% (May clobber the temporary variable namespace, as there is no block or
60% subscript information given). Useful for stand-alone statements.62% subscript information given). Useful for stand-alone statements.
61% Also produces map of types of all variables bound by the instructions.63% Also produces map of types of all variables bound by the instructions.
62:- pred expr_to_instrs(progtable::in, varset::in, expr::in, varname::out,64:- pred expr_to_instrs(progtable::in, varset::in, expr::in, atom::out,
63 list(instr)::out, map(varname, typeval)::out, list(function)::out,65 list(instr)::out, map(varname, typeval)::out, list(function)::out,
64 ast_state::in, ast_state::out) is det.66 ast_state::in, ast_state::out) is det.
6567
66% expr_to_instrs_post_ssa(+PT, +Varset, +BlockID, +Expr, -VarName, -Instrs,68% expr_to_instrs_post_ssa(+PT, +Varset, +BlockID, +Expr, -Atom, -Instrs,
67% -Types, -SynthFuncs, !BlockTempCount).69% -Types, -SynthFuncs, !BlockTempCount).
68% Special version of expr_to_instrs, with some important restrictions:70% Special version of expr_to_instrs, with some important restrictions:
69% - Variables in the expr must already be in SSA form, will not be converted.71% - Variables in the expr must already be in SSA form, will not be converted.
@@ -71,7 +73,7 @@
71% subscripts on the temporaries. BlockTempCount is the ID of the next73% subscripts on the temporaries. BlockTempCount is the ID of the next
72% available temporary in this block; it will be updated.74% available temporary in this block; it will be updated.
73:- pred expr_to_instrs_post_ssa(progtable::in, varset::in, int::in, expr::in,75:- pred expr_to_instrs_post_ssa(progtable::in, varset::in, int::in, expr::in,
74 varname::out, list(instr)::out, map(varname, typeval)::out,76 atom::out, list(instr)::out, map(varname, typeval)::out,
75 list(function)::out, int::in, int::out) is det.77 list(function)::out, int::in, int::out) is det.
7678
77% basic_stmt_to_instrs(+PT, +BasicStmt, -Instrs, -Types, -SynthFuncs,79% basic_stmt_to_instrs(+PT, +BasicStmt, -Instrs, -Types, -SynthFuncs,
@@ -831,17 +833,17 @@
831 pretty.string_pattern(P)).833 pretty.string_pattern(P)).
832pattern_type(pattern(_, yes(T))) = T.834pattern_type(pattern(_, yes(T))) = T.
833835
834% exprs_to_instrs(+PT, +BlockID, +Ctx, +Exprs, -VarNames, -Instrs, -Types,836% exprs_to_instrs(+PT, +BlockID, +Ctx, +Exprs, -Atoms, -Instrs, -Types,
835% !SubscriptMap).837% !SubscriptMap).
836:- pred exprs_to_instrs(progtable::in, varset::in, int::in, context::in,838:- pred exprs_to_instrs(progtable::in, varset::in, int::in, context::in,
837 list(expr)::in, list(varname)::out, list(instr)::out, type_map::out,839 list(expr)::in, list(atom)::out, list(instr)::out, type_map::out,
838 subscript_map::in, subscript_map::out,840 subscript_map::in, subscript_map::out,
839 list(function)::in, list(function)::out) is det.841 list(function)::in, list(function)::out) is det.
840exprs_to_instrs(PT, Varset, BlockID, Ctx, Es, VarNames, Instrs, Types,842exprs_to_instrs(PT, Varset, BlockID, Ctx, Es, Atoms, Instrs, Types,
841 !SubscriptMap, !SynthFuncs) :-843 !SubscriptMap, !SynthFuncs) :-
842 exprs_to_instrs_(PT, Varset, BlockID, Ctx, Es, Types, [], VarNamesRev, [],844 exprs_to_instrs_(PT, Varset, BlockID, Ctx, Es, Types, [], AtomsRev, [],
843 LLInstrsRev, !SubscriptMap, !SynthFuncs),845 LLInstrsRev, !SubscriptMap, !SynthFuncs),
844 list.reverse(VarNamesRev, VarNames),846 list.reverse(AtomsRev, Atoms),
845 list.reverse(LLInstrsRev, LLInstrs),847 list.reverse(LLInstrsRev, LLInstrs),
846 % "Condense" the list-of-lists into a flat list of instructions848 % "Condense" the list-of-lists into a flat list of instructions
847 list.condense(LLInstrs, Instrs).849 list.condense(LLInstrs, Instrs).
@@ -851,37 +853,37 @@
851% Instrs is a list of lists (to be flattened). The outer list is reversed, the853% Instrs is a list of lists (to be flattened). The outer list is reversed, the
852% inner list is not -- this is to allow prepending.854% inner list is not -- this is to allow prepending.
853:- pred exprs_to_instrs_(progtable::in, varset::in, int::in, context::in,855:- pred exprs_to_instrs_(progtable::in, varset::in, int::in, context::in,
854 list(expr)::in, type_map::out, list(varname)::in, list(varname)::out,856 list(expr)::in, type_map::out, list(atom)::in, list(atom)::out,
855 list(list(instr))::in, list(list(instr))::out,857 list(list(instr))::in, list(list(instr))::out,
856 subscript_map::in, subscript_map::out,858 subscript_map::in, subscript_map::out,
857 list(function)::in, list(function)::out) is det.859 list(function)::in, list(function)::out) is det.
858exprs_to_instrs_(_PT, _Varset, _BlockID, _Ctx, [], map.init, !VarNames,860exprs_to_instrs_(_PT, _Varset, _BlockID, _Ctx, [], map.init, !Atoms,
859 !Instrs, !SubscriptMap, !SynthFuncs).861 !Instrs, !SubscriptMap, !SynthFuncs).
860exprs_to_instrs_(PT, Varset, BlockID,Ctx,[E|Es],Types,!VarNames, !Instrs,862exprs_to_instrs_(PT, Varset, BlockID,Ctx,[E|Es],Types,!Atoms, !Instrs,
861 !SubscriptMap, !SynthFuncs) :-863 !SubscriptMap, !SynthFuncs) :-
862 % Create a new variable name and generate instructions for each expr864 % Create a new variable name and generate instructions for each expr
863 expr_to_instrs(PT, Varset, BlockID, Ctx, E, V, Is, Types0, !SubscriptMap,865 expr_to_instrs(PT, Varset, BlockID, Ctx, E, A, Is, Types0, !SubscriptMap,
864 !SynthFuncs),866 !SynthFuncs),
865 !:VarNames = [V | !.VarNames],867 !:Atoms = [A | !.Atoms],
866 !:Instrs = [Is | !.Instrs], % Do not flatten Is; keep as list of lists868 !:Instrs = [Is | !.Instrs], % Do not flatten Is; keep as list of lists
867 exprs_to_instrs_(PT, Varset, BlockID, Ctx, Es, Types1, !VarNames, !Instrs,869 exprs_to_instrs_(PT, Varset, BlockID, Ctx, Es, Types1, !Atoms, !Instrs,
868 !SubscriptMap, !SynthFuncs),870 !SubscriptMap, !SynthFuncs),
869 Types = type_map_union(Types0, Types1).871 Types = type_map_union(Types0, Types1).
870872
871% expr_to_instrs(+BlockID, +Ctx, +Expr, -VarName, -Instrs, !SubscriptMap).873% expr_to_instrs_var(+BlockID, +Ctx, +Expr, -VarName, -Instrs, !SubscriptMap).
872% Converts a single expression into a sequence of low-level instructions874% Same as expr_to_instrs, but always produces a variable. (Atomic non-variable
873% which compute the expression and assign it to a variable (possibly a875% expressions such as integer literals are converted into separate
874% new temporary variable name). Returns the assigned variable name in VarName.876% instructions.)
875:- pred expr_to_instrs(progtable::in, varset::in, int::in, context::in,877:- pred expr_to_instrs_var(progtable::in, varset::in, int::in, context::in,
876 expr::in, varname::out, list(instr)::out, type_map::out,878 expr::in, varname::out, list(instr)::out, type_map::out,
877 subscript_map::in, subscript_map::out,879 subscript_map::in, subscript_map::out,
878 list(function)::in, list(function)::out) is det.880 list(function)::in, list(function)::out) is det.
879expr_to_instrs(PT, Varset, BlockID, Ctx, E, V, Is, Types, !SubscriptMap,881expr_to_instrs_var(PT, Varset, BlockID, Ctx, E, V, Is, Types, !SubscriptMap,
880 !SynthFuncs) :-882 !SynthFuncs) :-
881 ( E = expr(varref(Var), _) ->883 ( E = expr(varref(Var), _) ->
882 % Special case -- expr_to_instrs_as will generate a mov.884 % Special case -- expr_to_instrs_as will generate a mov.
883 % We can avoid this by not generating a temp var, and just returning885 % We can avoid this by not generating a temp var, and just returning
884 % the variable name (with no instructions at all).886 % the variable name as an atom (with no instructions at all).
885 V = Var,887 V = Var,
886 Is = [],888 Is = [],
887 Types = map.init889 Types = map.init
@@ -891,6 +893,34 @@
891 !SubscriptMap, !SynthFuncs)893 !SubscriptMap, !SynthFuncs)
892 ).894 ).
893895
896% expr_to_instrs(+BlockID, +Ctx, +Expr, -Atom, -Instrs, !SubscriptMap).
897% Converts a single expression into a sequence of low-level instructions
898% which compute the expression and assign it to a variable (possibly a
899% new temporary variable name). Returns the assigned variable name in VarName.
900:- pred expr_to_instrs(progtable::in, varset::in, int::in, context::in,
901 expr::in, atom::out, list(instr)::out, type_map::out,
902 subscript_map::in, subscript_map::out,
903 list(function)::in, list(function)::out) is det.
904expr_to_instrs(PT, Varset, BlockID, Ctx, E, A, Is, Types, !SubscriptMap,
905 !SynthFuncs) :-
906 ( E = expr(intlit(Val), _) ->
907 % Special case -- expr_to_instrs_var will generate a mov.
908 % We can avoid this by just returning the int as an atom.
909 A = intatom(Val),
910 Is = [],
911 Types = map.init
912 ; E = expr(ctorref(Name), _), ir.ctor_is_cgc(PT, Name) ->
913 % Special case -- expr_to_instrs_var will generate a mov.
914 % We can avoid this by just returning the ctorsym as an atom.
915 A = ctorsym(Name),
916 Is = [],
917 Types = map.init
918 ;
919 expr_to_instrs_var(PT, Varset, BlockID, Ctx, E, V, Is, Types,
920 !SubscriptMap, !SynthFuncs),
921 A = varname(V)
922 ).
923
894% XXX The *public* version of expr_to_instrs expects non-SSA variable names;924% XXX The *public* version of expr_to_instrs expects non-SSA variable names;
895% it will convert them to SSA form.925% it will convert them to SSA form.
896% Conversely, the *private* version of expr_to_instrs expects926% Conversely, the *private* version of expr_to_instrs expects
@@ -923,7 +953,7 @@
923expr_to_instrs_as(_PT, _Varset, _BlockID, Ctx, E@expr(intlit(Val),_), V, Is,953expr_to_instrs_as(_PT, _Varset, _BlockID, Ctx, E@expr(intlit(Val),_), V, Is,
924 Types, !SubscriptMap, !SynthFuncs) :-954 Types, !SubscriptMap, !SynthFuncs) :-
925 Types = expr_typemap(V, E),955 Types = expr_typemap(V, E),
926 Is = [instr(ld_intlit(V, Val), Ctx)].956 Is = [instr(mov(V, intatom(Val)), Ctx)].
927expr_to_instrs_as(PT, Varset, BlockID, Ctx, E@expr(arraylit(Elems0),_), V, Is,957expr_to_instrs_as(PT, Varset, BlockID, Ctx, E@expr(arraylit(Elems0),_), V, Is,
928 Types, !SubscriptMap, !SynthFuncs) :-958 Types, !SubscriptMap, !SynthFuncs) :-
929 Types0 = expr_typemap(V, E),959 Types0 = expr_typemap(V, E),
@@ -934,7 +964,7 @@
934expr_to_instrs_as(_PT, _Varset, _BlockID, Ctx, E@expr(varref(Var),_), V, Is,964expr_to_instrs_as(_PT, _Varset, _BlockID, Ctx, E@expr(varref(Var),_), V, Is,
935 Types, !SubscriptMap, !SynthFuncs) :-965 Types, !SubscriptMap, !SynthFuncs) :-
936 Types = expr_typemap(V, E),966 Types = expr_typemap(V, E),
937 Is = [instr(mov(V, Var), Ctx)].967 Is = [instr(mov(V, varname(Var)), Ctx)].
938expr_to_instrs_as(PT, _Varset, _BlockID, Ctx, E@expr(globalref(Name),_), V,968expr_to_instrs_as(PT, _Varset, _BlockID, Ctx, E@expr(globalref(Name),_), V,
939 Is, Types, !SubscriptMap, !SynthFuncs) :-969 Is, Types, !SubscriptMap, !SynthFuncs) :-
940 Types = expr_typemap(V, E),970 Types = expr_typemap(V, E),
@@ -952,8 +982,8 @@
952 Types = expr_typemap(V, E),982 Types = expr_typemap(V, E),
953 % The instruction will depend upon the type of constructor983 % The instruction will depend upon the type of constructor
954 ( ir.ctor_is_cgc(PT, Name) ->984 ( ir.ctor_is_cgc(PT, Name) ->
955 % Algebraic constant. ld_ctorsym instruction.985 % Algebraic constant. mov instruction, loading the ctorsym.
956 Is = [instr(ld_ctorsym(V, Name), Ctx)]986 Is = [instr(mov(V, ctorsym(Name)), Ctx)]
957 ;987 ;
958 % Constructor function. Generate synthetic closure template; no cvars.988 % Constructor function. Generate synthetic closure template; no cvars.
959 parcall_ctor_closure_template(PT, Name, 0, CTName, !SynthFuncs),989 parcall_ctor_closure_template(PT, Name, 0, CTName, !SynthFuncs),
@@ -1005,7 +1035,7 @@
1005 Is1 = [instr(call_ctor(V, CtorName, Args), Ctx)],1035 Is1 = [instr(call_ctor(V, CtorName, Args), Ctx)],
1006 Is = Is0 ++ Is11036 Is = Is0 ++ Is1
1007 ;1037 ;
1008 expr_to_instrs(PT, Varset, BlockID, Ctx, Func0, Func, Is0, Types1,1038 expr_to_instrs_var(PT, Varset, BlockID, Ctx, Func0, Func, Is0, Types1,
1009 !SubscriptMap, !SynthFuncs),1039 !SubscriptMap, !SynthFuncs),
1010 exprs_to_instrs(PT, Varset, BlockID, Ctx, Args0, Args, Is1, Types2,1040 exprs_to_instrs(PT, Varset, BlockID, Ctx, Args0, Args, Is1, Types2,
1011 !SubscriptMap, !SynthFuncs),1041 !SubscriptMap, !SynthFuncs),
@@ -1174,8 +1204,8 @@
1174 % Calculate the condition expression at the end of BBCurrent1204 % Calculate the condition expression at the end of BBCurrent
1175 apply_def_map_to_expr(DefMap, Ctx, Ctrl0, Ctrl),1205 apply_def_map_to_expr(DefMap, Ctx, Ctrl0, Ctrl),
1176 BlockID = ref_id(BBCurrent, !.CFG),1206 BlockID = ref_id(BBCurrent, !.CFG),
1177 expr_to_instrs(PT, Varset, BlockID, Ctx, Ctrl, CtrlVar, CtrlInstrs,1207 expr_to_instrs_var(PT, Varset, BlockID, Ctx, Ctrl, CtrlVar, CtrlInstrs,
1178 Types0, SubscriptMap0, SubscriptMap, !SynthFuncs),1208 Types0, SubscriptMap0, SubscriptMap, !SynthFuncs),
1179 cfg.append_instrs(BBCurrent, CtrlInstrs, !CFG),1209 cfg.append_instrs(BBCurrent, CtrlInstrs, !CFG),
1180 % Convert all patterns to use SSA variables, and generate CFG code for the1210 % Convert all patterns to use SSA variables, and generate CFG code for the
1181 % bodies of all case statements. The resulting Cases contains goto1211 % bodies of all case statements. The resulting Cases contains goto
@@ -1884,7 +1914,7 @@
1884 RetType = ObjType,1914 RetType = ObjType,
1885 InstrBuilder = (func(Dst, Ctor, Idx) =1915 InstrBuilder = (func(Dst, Ctor, Idx) =
1886 i_fieldreplace(Dst, svname("object"), Ctor, Idx,1916 i_fieldreplace(Dst, svname("object"), Ctor, Idx,
1887 svname("value"))).1917 varname(svname("value")))).
18881918
1889% fieldfunc_set(Typedef, FieldName, FieldType) builds a field set function.1919% fieldfunc_set(Typedef, FieldName, FieldType) builds a field set function.
1890:- func fieldfunc_set(typedef, string, typeval) = function.1920:- func fieldfunc_set(typedef, string, typeval) = function.
@@ -1897,7 +1927,7 @@
1897 RetType = ObjType,1927 RetType = ObjType,
1898 InstrBuilder = (func(_Dst, Ctor, Idx) =1928 InstrBuilder = (func(_Dst, Ctor, Idx) =
1899 i_fieldset(svname("object"), Ctor, Idx,1929 i_fieldset(svname("object"), Ctor, Idx,
1900 svname("value"))).1930 varname(svname("value")))).
19011931
1902% fieldfunc_(Typedef, FieldName, FuncName, Params, RetType, InstrBuilder,1932% fieldfunc_(Typedef, FieldName, FuncName, Params, RetType, InstrBuilder,
1903% Obj, RetVar)1933% Obj, RetVar)
@@ -1958,7 +1988,7 @@
1958 list.map(func(B-_) = B, Preds), !CFG),1988 list.map(func(B-_) = B, Preds), !CFG),
1959 ( RetVar = yes(RetN) ->1989 ( RetVar = yes(RetN) ->
1960 % If RetVar, return the given variable name1990 % If RetVar, return the given variable name
1961 cfg.append_instr(Exit, instr(mov(retvname, RetN),1991 cfg.append_instr(Exit, instr(mov(retvname, varname(RetN)),
1962 Typedef^typedef_context), !CFG),1992 Typedef^typedef_context), !CFG),
1963 % The "Dst variables" should never have been assigned; don't put1993 % The "Dst variables" should never have been assigned; don't put
1964 % them in the localtable1994 % them in the localtable
@@ -2008,24 +2038,19 @@
2008 cfg.append_predecessor(Bl, Pred, !CFG),2038 cfg.append_predecessor(Bl, Pred, !CFG),
2009 Msg = string.format("%s instance has no field \"%s\"",2039 Msg = string.format("%s instance has no field \"%s\"",
2010 [s(Typedef^typedef_name), s(FieldName)]),2040 [s(Typedef^typedef_name), s(FieldName)]),
2011 list.map_foldl2((pred(Chr::in, V::out, ID::in, ID+1::out, C0::in, C::out)2041 CharAtoms = list.map(func(Chr) = intatom(integer(char.to_int(Chr))),
2012 is det :-2042 string.to_char_list(Msg)),
2013 V = qvname(qvname(tempvname, cfg.ref_id(Bl, C0)), ID),
2014 I = instr(ld_intlit(V, integer(char.to_int(Chr))), Ctx),
2015 cfg.append_instr(Bl, I, C0, C)
2016 ), string.to_char_list(Msg), CharVars, 0, _, !CFG),
2017 % Call the 'error' built-in with this message as a Mars string2043 % Call the 'error' built-in with this message as a Mars string
2018 MsgVar = qvname(tempvname, cfg.ref_id(Bl, !.CFG)),2044 MsgVar = qvname(tempvname, cfg.ref_id(Bl, !.CFG)),
2019 MsgInstr = instr(ld_arraylit(MsgVar, CharVars), Ctx),2045 MsgInstr = instr(ld_arraylit(MsgVar, CharAtoms), Ctx),
2020 cfg.append_instr(Bl, MsgInstr, !CFG),2046 cfg.append_instr(Bl, MsgInstr, !CFG),
2021 % Assign the result to a new variable2047 % Assign the result to a new variable
2022 Dst = qvname(retvname, cfg.ref_id(Bl, !.CFG)),2048 Dst = qvname(retvname, cfg.ref_id(Bl, !.CFG)),
2023 Instr = instr(call_global(Dst, "error", [MsgVar]), Ctx),2049 Instr = instr(call_global(Dst, "error", [varname(MsgVar)]), Ctx),
2024 cfg.append_instr(Bl, Instr, !CFG),2050 cfg.append_instr(Bl, Instr, !CFG),
2025 Term = branch(Exit, Ctx),2051 Term = branch(Exit, Ctx),
2026 cfg.set_terminator(Bl, Term, !CFG),2052 cfg.set_terminator(Bl, Term, !CFG),
2027 TypeMap = map(func(V) = V-types.const("Int"), CharVars) ++2053 TypeMap = [MsgVar-types.app(types.const("Array"), [types.const("Int")])].
2028 [MsgVar-types.app(types.const("Array"), [types.const("Int")])].
20292054
2030% -------------------------------------------------------------------------- %2055% -------------------------------------------------------------------------- %
2031% Closure template generation2056% Closure template generation
20322057
=== modified file 'src/cfg.m'
--- src/cfg.m 2011-10-08 06:55:14 +0000
+++ src/cfg.m 2011-10-21 03:33:25 +0000
@@ -51,7 +51,7 @@
51:- type bbref(S).51:- type bbref(S).
5252
53% A phi is a phi statement in Static Single Assignment notation.53% A phi is a phi statement in Static Single Assignment notation.
54% It maps a variable name V onto a mapping from bbrefs to varnames.54% It maps a variable name V onto a mapping from bbrefs to atoms.
55% The bbref is a predecessor block P, and the varname is V0.55% The bbref is a predecessor block P, and the varname is V0.
56% That is to say, "if you just came from block P, set V to the value of V0".56% That is to say, "if you just came from block P, set V to the value of V0".
57:- type phi(S)57:- type phi(S)
5858
=== modified file 'src/interactive.m'
--- src/interactive.m 2011-10-21 03:11:44 +0000
+++ src/interactive.m 2011-10-21 03:33:25 +0000
@@ -385,8 +385,13 @@
385 yes(types.app(types.const("Array"),385 yes(types.app(types.const("Array"),
386 [types.const("Int")]))),386 [types.const("Int")]))),
387 ast_cfg.expr_to_instrs(!.State^st_progtable, !.State^st_localvarset,387 ast_cfg.expr_to_instrs(!.State^st_progtable, !.State^st_localvarset,
388 ShowExpr, VarName, Instrs0, Types_Raw, SynthFuncs,388 ShowExpr, Atom, Instrs0, Types_Raw, SynthFuncs,
389 !.State^st_aststate, NewASTState0),389 !.State^st_aststate, NewASTState0),
390 ( Atom = ir.varname(VarName_) ->
391 VarName = VarName_
392 ;
393 error("expr_to_instrs returned non-variable")
394 ),
390 % Return the name of the temporary395 % Return the name of the temporary
391 Result = yes(VarName)396 Result = yes(VarName)
392 ;397 ;
393398
=== modified file 'src/interpret.m'
--- src/interpret.m 2011-10-21 03:11:44 +0000
+++ src/interpret.m 2011-10-21 03:33:25 +0000
@@ -162,6 +162,21 @@
162 ir.varname_string(VarName))162 ir.varname_string(VarName))
163 ).163 ).
164164
165% atom_value(+Atom, -Value, !Env, !IO)
166% Converts an atom into a runtime value.
167% If the atom is a variable, searches the environment for that variable, and
168% aborts if it is not found. Similarly, ctor symbols abort if not found.
169% Unfortunately, requires a mutable environment and IO, due to the very
170% backwards way in which we construct constructor symbol terms.
171:- pred atom_value(atom::in, value::out, env::in, env::out, io::di, io::uo)
172 is det.
173atom_value(varname(VarName), Value, !Env, !IO) :-
174 local_search_det(!.Env, VarName, Value).
175atom_value(intatom(I), Value, !Env, !IO) :-
176 Value = val_int(I).
177atom_value(ctorsym(Name), Value, !Env, !IO) :-
178 read_ctor(Name, Value, !Env, !IO).
179
165% global_search(Env, VarName, Value)180% global_search(Env, VarName, Value)
166% Searches an environment for a global variable of the given name, and returns181% Searches an environment for a global variable of the given name, and returns
167% its value.182% its value.
@@ -455,13 +470,14 @@
455 Result = Result0470 Result = Result0
456 ).471 ).
457472
458% read_var_into_vector(!Env, VectorRef, VarName, !IO).473% read_atom_into_vector(!Env, VectorRef, Atom, !IO).
459% Reads a local variable, and appends its value onto the end of the vector.474% Reads a local variable or atom, and appends its value onto the end of the
475% vector.
460% Uses IO as the vector's store.476% Uses IO as the vector's store.
461:- pred read_var_into_vector(vectorref(value, io)::in, varname::in,477:- pred read_atom_into_vector(vectorref(value, io)::in, atom::in,
462 env::in, env::out, io::di, io::uo) is det.478 env::in, env::out, io::di, io::uo) is det.
463read_var_into_vector(VectorRef, VarName, !Env, !IO) :-479read_atom_into_vector(VectorRef, Atom, !Env, !IO) :-
464 local_search_det(!.Env, VarName, Value),480 atom_value(Atom, Value, !Env, !IO),
465 vectorref.add(VectorRef, Value, !IO).481 vectorref.add(VectorRef, Value, !IO).
466482
467% Insert a set of new functions into the runtime environment.483% Insert a set of new functions into the runtime environment.
@@ -490,11 +506,11 @@
490 io::di, io::uo) is det.506 io::di, io::uo) is det.
491exec_instr_(nop, _Ctx, !Env, !IO).507exec_instr_(nop, _Ctx, !Env, !IO).
492exec_instr_(mov(Dst, Src), _Ctx, !Env, !IO) :-508exec_instr_(mov(Dst, Src), _Ctx, !Env, !IO) :-
493 local_search_det(!.Env, Src, Result),509 atom_value(Src, Result, !Env, !IO),
494 env_assign_local(Dst, Result, !Env).510 env_assign_local(Dst, Result, !Env).
495exec_instr_(i_fieldset(ValName, ICtor, Idx, SrcName), _Ctx, !Env, !IO) :-511exec_instr_(i_fieldset(ValName, ICtor, Idx, SrcName), _Ctx, !Env, !IO) :-
496 local_search_det(!.Env, ValName, Val),512 local_search_det(!.Env, ValName, Val),
497 local_search_det(!.Env, SrcName, Src),513 atom_value(SrcName, Src, !Env, !IO),
498 ( Val = val_term(Term) -> % Must match supplied Ctor name514 ( Val = val_term(Term) -> % Must match supplied Ctor name
499 store.get_mutvar(Term, marsterm(Ctor, Fields0), !IO),515 store.get_mutvar(Term, marsterm(Ctor, Fields0), !IO),
500 field_check_ctor(ICtor, Ctor), % May abort516 field_check_ctor(ICtor, Ctor), % May abort
@@ -516,7 +532,7 @@
516exec_instr_(i_fieldreplace(Dst, ValName, ICtor, Idx, SrcName), _Ctx,532exec_instr_(i_fieldreplace(Dst, ValName, ICtor, Idx, SrcName), _Ctx,
517 !Env, !IO) :-533 !Env, !IO) :-
518 local_search_det(!.Env, ValName, Val),534 local_search_det(!.Env, ValName, Val),
519 local_search_det(!.Env, SrcName, Src),535 atom_value(SrcName, Src, !Env, !IO),
520 ( Val = val_term(Term0) -> % Must match supplied Ctor name536 ( Val = val_term(Term0) -> % Must match supplied Ctor name
521 store.get_mutvar(Term0, marsterm(Ctor, Fields0), !IO),537 store.get_mutvar(Term0, marsterm(Ctor, Fields0), !IO),
522 field_check_ctor(ICtor, Ctor), % May abort538 field_check_ctor(ICtor, Ctor), % May abort
@@ -536,18 +552,13 @@
536 store.new_mutvar(marsterm(Ctor, Fields), Term, !IO),552 store.new_mutvar(marsterm(Ctor, Fields), Term, !IO),
537 Result = val_term(Term),553 Result = val_term(Term),
538 env_assign_local(Dst, Result, !Env).554 env_assign_local(Dst, Result, !Env).
539exec_instr_(ld_intlit(Dst, I), _Ctx, !Env, !IO) :-
540 env_assign_local(Dst, val_int(I), !Env).
541exec_instr_(ld_arraylit(Dst, Elems), _Ctx, !Env, !IO) :-555exec_instr_(ld_arraylit(Dst, Elems), _Ctx, !Env, !IO) :-
542 % Create a new, empty vector of values556 % Create a new, empty vector of values
543 Capacity = good_vector_capacity(list.length(Elems)),557 Capacity = good_vector_capacity(list.length(Elems)),
544 vectorref.init(Capacity, VectorRef, !IO),558 vectorref.init(Capacity, VectorRef, !IO),
545 % Evaluate each expression, populating the vector559 % Evaluate each expression, populating the vector
546 list.foldl2(read_var_into_vector(VectorRef), Elems, !Env, !IO),560 list.foldl2(read_atom_into_vector(VectorRef), Elems, !Env, !IO),
547 env_assign_local(Dst, val_array(VectorRef), !Env).561 env_assign_local(Dst, val_array(VectorRef), !Env).
548exec_instr_(ld_ctorsym(Dst, Name), _Ctx, !Env, !IO) :-
549 read_ctor(Name, Result, !Env, !IO),
550 env_assign_local(Dst, Result, !Env).
551exec_instr_(ld_cgc(Dst, Name), _Ctx, !Env, !IO) :-562exec_instr_(ld_cgc(Dst, Name), _Ctx, !Env, !IO) :-
552 read_cgc(Name, Result, !Env, !IO),563 read_cgc(Name, Result, !Env, !IO),
553 env_assign_local(Dst, Result, !Env).564 env_assign_local(Dst, Result, !Env).
@@ -569,28 +580,28 @@
569exec_instr_(new_closure(Dst, Func, Args), _Ctx, !Env, !IO) :-580exec_instr_(new_closure(Dst, Func, Args), _Ctx, !Env, !IO) :-
570 % Evaluate Func and Arg (eagerly)581 % Evaluate Func and Arg (eagerly)
571 global_search_det(!.Env, Func, FuncVal),582 global_search_det(!.Env, Func, FuncVal),
572 list.map(local_search_det(!.Env), Args, ArgVals),583 list.map_foldl2(atom_value, Args, ArgVals, !Env, !IO),
573 % Curry Args in Func, but do not evaluate584 % Curry Args in Func, but do not evaluate
574 partial_apply_vals(FuncVal, ArgVals, Result),585 partial_apply_vals(FuncVal, ArgVals, Result),
575 env_assign_local(Dst, Result, !Env).586 env_assign_local(Dst, Result, !Env).
576exec_instr_(call(Dst, Func, Args), _Ctx, !Env, !IO) :-587exec_instr_(call(Dst, Func, Args), _Ctx, !Env, !IO) :-
577 % Evaluate Func and Arg (eagerly)588 % Evaluate Func and Arg (eagerly)
578 local_search_det(!.Env, Func, FuncVal),589 local_search_det(!.Env, Func, FuncVal),
579 list.map(local_search_det(!.Env), Args, ArgVals),590 list.map_foldl2(atom_value, Args, ArgVals, !Env, !IO),
580 % Apply Arg to Func591 % Apply Arg to Func
581 apply_vals(FuncVal, ArgVals, Result, !Env, !IO),592 apply_vals(FuncVal, ArgVals, Result, !Env, !IO),
582 env_assign_local(Dst, Result, !Env).593 env_assign_local(Dst, Result, !Env).
583exec_instr_(call_ctor(Dst, Ctor, Args), _Ctx, !Env, !IO) :-594exec_instr_(call_ctor(Dst, Ctor, Args), _Ctx, !Env, !IO) :-
584 % Evaluate Ctor and Arg (eagerly)595 % Evaluate Ctor and Arg (eagerly)
585 read_ctor(Ctor, CtorVal, !Env, !IO),596 read_ctor(Ctor, CtorVal, !Env, !IO),
586 list.map(local_search_det(!.Env), Args, ArgVals),597 list.map_foldl2(atom_value, Args, ArgVals, !Env, !IO),
587 % Apply Arg to Ctor598 % Apply Arg to Ctor
588 apply_vals(CtorVal, ArgVals, Result, !Env, !IO),599 apply_vals(CtorVal, ArgVals, Result, !Env, !IO),
589 env_assign_local(Dst, Result, !Env).600 env_assign_local(Dst, Result, !Env).
590exec_instr_(call_global(Dst, Func, Args), _Ctx, !Env, !IO) :-601exec_instr_(call_global(Dst, Func, Args), _Ctx, !Env, !IO) :-
591 % Evaluate Func and Arg (eagerly)602 % Evaluate Func and Arg (eagerly)
592 global_search_det(!.Env, Func, FuncVal),603 global_search_det(!.Env, Func, FuncVal),
593 list.map(local_search_det(!.Env), Args, ArgVals),604 list.map_foldl2(atom_value, Args, ArgVals, !Env, !IO),
594 % Apply Arg to Func605 % Apply Arg to Func
595 apply_vals(FuncVal, ArgVals, Result, !Env, !IO),606 apply_vals(FuncVal, ArgVals, Result, !Env, !IO),
596 env_assign_local(Dst, Result, !Env).607 env_assign_local(Dst, Result, !Env).
@@ -763,7 +774,7 @@
763 exec_cases(CFG, BBRef, !Env, ControlVal, Cases, Default, !IO)774 exec_cases(CFG, BBRef, !Env, ControlVal, Cases, Default, !IO)
764 ;775 ;
765 Term = cond_branch(Cond, Then, Else, _),776 Term = cond_branch(Cond, Then, Else, _),
766 local_search_det(!.Env, Cond, CondVal),777 atom_value(Cond, CondVal, !Env, !IO),
767 ( CondVal = val_int(integer(0)) ->778 ( CondVal = val_int(integer(0)) ->
768 % False779 % False
769 exec_block(CFG, BBRef, Else, !Env, !IO)780 exec_block(CFG, BBRef, Else, !Env, !IO)
770781
=== modified file 'src/ir.m'
--- src/ir.m 2011-10-10 12:38:16 +0000
+++ src/ir.m 2011-10-21 03:33:25 +0000
@@ -185,6 +185,15 @@
185 % repeating until the condition is zero.185 % repeating until the condition is zero.
186 ; while(expr,stmt_block).186 ; while(expr,stmt_block).
187187
188% atom: An atomic value which may be given as input to various instructions.
189:- type atom
190 % A variable name
191 ---> varname(varname)
192 % An integer literal (note: arbitrary precision)
193 ; intatom(integer)
194 % A constructor symbol (parameterless constructor names only)
195 ; ctorsym(string).
196
188% instr: A low-level statement with no control flow, sub-statements or197% instr: A low-level statement with no control flow, sub-statements or
189% sub-expressions. Used by only the CFG program representation.198% sub-expressions. Used by only the CFG program representation.
190:- type instr199:- type instr
@@ -195,21 +204,16 @@
195:- type instr_204:- type instr_
196 % NOP instruction (equivalent of pass statement)205 % NOP instruction (equivalent of pass statement)
197 ---> nop206 ---> nop
198 % Copy instruction. Copies a value from one variable to another.207 % Copy instruction. Copies a value from an atom to a variable.
199 ; mov(varname, varname)208 ; mov(varname, atom)
200 % Field update (destructive). (S, C, I, V) <=> S.I := V209 % Field update (destructive). (S, C, I, V) <=> S.I := V
201 % (See ld_field)210 % (See ld_field)
202 ; i_fieldset(varname, string, int, varname)211 ; i_fieldset(varname, string, int, atom)
203 % Field replace (non-destructive).212 % Field replace (non-destructive).
204 % (R, S, C, I, V) <=> R := % S.I <- V (See ld_field)213 % (R, S, C, I, V) <=> R := % S.I <- V (See ld_field)
205 ; i_fieldreplace(varname, varname, string, int, varname)214 ; i_fieldreplace(varname, varname, string, int, atom)
206 % Load an integer literal. (Note arbitrary precision).
207 ; ld_intlit(varname, integer)
208 % Construct an array from a list of variables.215 % Construct an array from a list of variables.
209 ; ld_arraylit(varname, list(varname))216 ; ld_arraylit(varname, list(atom))
210 % Load a symbolic constant constructor into a variable.
211 % String is the name of the ctor (must not take arguments).
212 ; ld_ctorsym(varname, string)
213 % Load the value of a computable global constant into a variable.217 % Load the value of a computable global constant into a variable.
214 % String is the name of the CGC. Its body may be executed.218 % String is the name of the CGC. Its body may be executed.
215 ; ld_cgc(varname, string)219 ; ld_cgc(varname, string)
@@ -219,15 +223,15 @@
219 ; ld_field(varname, varname, string, int)223 ; ld_field(varname, varname, string, int)
220 % Create closure from closure template. (Result, Function, Args).224 % Create closure from closure template. (Result, Function, Args).
221 % Function must be a global closure template (not a ctor or CGC).225 % Function must be a global closure template (not a ctor or CGC).
222 ; new_closure(varname, string, list(varname))226 ; new_closure(varname, string, list(atom))
223 % Local function call. (Result, Function, Args).227 % Local function call. (Result, Function, Args).
224 ; call(varname, varname, list(varname))228 ; call(varname, varname, list(atom))
225 % Constructor function call. (Result, Ctor, Args).229 % Constructor function call. (Result, Ctor, Args).
226 % Ctor is the name of a constructor.230 % Ctor is the name of a constructor.
227 ; call_ctor(varname, string, list(varname))231 ; call_ctor(varname, string, list(atom))
228 % Global function call. (Result, Function, Args).232 % Global function call. (Result, Function, Args).
229 % Function must be a global function (not a ctor or CGC).233 % Function must be a global function (not a ctor or CGC).
230 ; call_global(varname, string, list(varname)).234 ; call_global(varname, string, list(atom)).
231235
232% terminator_instr: An instruction which may only appear at the end of a basic236% terminator_instr: An instruction which may only appear at the end of a basic
233% block in the CFG representation. These roughly are the equivalents of the237% block in the CFG representation. These roughly are the equivalents of the
@@ -250,7 +254,7 @@
250 % Conditional branch instruction. Expr must be of type Int.254 % Conditional branch instruction. Expr must be of type Int.
251 % Evaluates Expr, then branches to the first basic block if it is255 % Evaluates Expr, then branches to the first basic block if it is
252 % nonzero, or the second basic block if it is zero.256 % nonzero, or the second basic block if it is zero.
253 ; cond_branch(varname, bbref(S), bbref(S), context.context)257 ; cond_branch(atom, bbref(S), bbref(S), context.context)
254 % Unconditionally branches to the given basic block.258 % Unconditionally branches to the given basic block.
255 ; branch(bbref(S), context.context)259 ; branch(bbref(S), context.context)
256 % "Null terminator". It is a semantic error if a block with a null260 % "Null terminator". It is a semantic error if a block with a null
257261
=== modified file 'src/pretty.m'
--- src/pretty.m 2011-10-09 08:12:06 +0000
+++ src/pretty.m 2011-10-21 03:33:25 +0000
@@ -358,6 +358,11 @@
358 io.write_string(":\n", !IO),358 io.write_string(":\n", !IO),
359 foldl(print_stmt(Indent+1), Stmts, !IO).359 foldl(print_stmt(Indent+1), Stmts, !IO).
360360
361:- func atom_string(atom) = string.
362atom_string(varname(VarName)) = ir.varname_string(VarName).
363atom_string(intatom(I)) = integer.to_string(I).
364atom_string(ctorsym(Name)) = Name.
365
361:- pred print_instr(int::in, instr::in, io::di, io::uo) is det.366:- pred print_instr(int::in, instr::in, io::di, io::uo) is det.
362print_instr(Indent, Instr, !IO) :-367print_instr(Indent, Instr, !IO) :-
363 print_instr_(Indent, Instr ^ instr_instr, !IO),368 print_instr_(Indent, Instr ^ instr_instr, !IO),
@@ -371,35 +376,25 @@
371 indent(Indent, !IO),376 indent(Indent, !IO),
372 io.write_string(ir.varname_string(Dst), !IO),377 io.write_string(ir.varname_string(Dst), !IO),
373 io.write_string(" = ", !IO),378 io.write_string(" = ", !IO),
374 io.write_string(ir.varname_string(Src), !IO).379 io.write_string(atom_string(Src), !IO).
375print_instr_(Indent, i_fieldset(Target, Ctor, Idx, Expr), !IO) :-380print_instr_(Indent, i_fieldset(Target, Ctor, Idx, Expr), !IO) :-
376 indent(Indent, !IO),381 indent(Indent, !IO),
377 io.write_string(fieldref_str(Target, Ctor, Idx), !IO),382 io.write_string(fieldref_str(Target, Ctor, Idx), !IO),
378 io.write_string(" =! ", !IO),383 io.write_string(" =! ", !IO),
379 io.write_string(ir.varname_string(Expr), !IO).384 io.write_string(atom_string(Expr), !IO).
380print_instr_(Indent, i_fieldreplace(Dst, Target, Ctor, Idx, Expr), !IO) :-385print_instr_(Indent, i_fieldreplace(Dst, Target, Ctor, Idx, Expr), !IO) :-
381 indent(Indent, !IO),386 indent(Indent, !IO),
382 io.write_string(ir.varname_string(Dst), !IO),387 io.write_string(ir.varname_string(Dst), !IO),
383 io.write_string(" = ", !IO),388 io.write_string(" = ", !IO),
384 io.write_string(fieldref_str(Target, Ctor, Idx), !IO),389 io.write_string(fieldref_str(Target, Ctor, Idx), !IO),
385 io.write_string(" := ", !IO),390 io.write_string(" := ", !IO),
386 io.write_string(ir.varname_string(Expr), !IO).391 io.write_string(atom_string(Expr), !IO).
387print_instr_(Indent, ld_intlit(Dst, I), !IO) :-
388 indent(Indent, !IO),
389 io.write_string(ir.varname_string(Dst), !IO),
390 io.write_string(" = ", !IO),
391 io.write_string(integer.to_string(I), !IO).
392print_instr_(Indent, ld_arraylit(Dst, Elems), !IO) :-392print_instr_(Indent, ld_arraylit(Dst, Elems), !IO) :-
393 indent(Indent, !IO),393 indent(Indent, !IO),
394 io.write_string(ir.varname_string(Dst), !IO),394 io.write_string(ir.varname_string(Dst), !IO),
395 io.write_string(" = ", !IO),395 io.write_string(" = ", !IO),
396 io.write_string("[" ++ string.join_list(", ",396 io.write_string("[" ++ string.join_list(", ",
397 list.map(ir.varname_string, Elems)) ++ "]", !IO).397 list.map(atom_string, Elems)) ++ "]", !IO).
398print_instr_(Indent, ld_ctorsym(Dst, Name), !IO) :-
399 indent(Indent, !IO),
400 io.write_string(ir.varname_string(Dst), !IO),
401 io.write_string(" = ", !IO),
402 io.write_string(Name, !IO).
403print_instr_(Indent, ld_cgc(Dst, Name), !IO) :-398print_instr_(Indent, ld_cgc(Dst, Name), !IO) :-
404 indent(Indent, !IO),399 indent(Indent, !IO),
405 io.write_string(ir.varname_string(Dst), !IO),400 io.write_string(ir.varname_string(Dst), !IO),
@@ -413,26 +408,25 @@
413 indent(Indent, !IO),408 indent(Indent, !IO),
414 io.write_string(ir.varname_string(Dst), !IO),409 io.write_string(ir.varname_string(Dst), !IO),
415 io.write_string(" = @", !IO),410 io.write_string(" = @", !IO),
416 ArgsStr = string.join_list(", ", list.map(ir.varname_string, Args)),411 ArgsStr = string.join_list(", ", list.map(atom_string, Args)),
417 io.write_string(Func ++ "{" ++ ArgsStr ++ "}", !IO).412 io.write_string(Func ++ "{" ++ ArgsStr ++ "}", !IO).
418print_instr_(Indent, call(Dst, Func, Args), !IO) :-413print_instr_(Indent, call(Dst, Func, Args), !IO) :-
419 indent(Indent, !IO),414 indent(Indent, !IO),
420 io.write_string(ir.varname_string(Dst), !IO),415 io.write_string(ir.varname_string(Dst), !IO),
421 io.write_string(" = ", !IO),416 io.write_string(" = ", !IO),
422 ArgsStr = string.join_list(", ",417 ArgsStr = string.join_list(", ", list.map(atom_string, Args)),
423 list.map(ir.varname_string, Args)),
424 io.write_string(ir.varname_string(Func) ++ "(" ++ ArgsStr ++ ")", !IO).418 io.write_string(ir.varname_string(Func) ++ "(" ++ ArgsStr ++ ")", !IO).
425print_instr_(Indent, call_ctor(Dst, Ctor, Args), !IO) :-419print_instr_(Indent, call_ctor(Dst, Ctor, Args), !IO) :-
426 indent(Indent, !IO),420 indent(Indent, !IO),
427 io.write_string(ir.varname_string(Dst), !IO),421 io.write_string(ir.varname_string(Dst), !IO),
428 io.write_string(" = ", !IO),422 io.write_string(" = ", !IO),
429 ArgsStr = string.join_list(", ", list.map(ir.varname_string, Args)),423 ArgsStr = string.join_list(", ", list.map(atom_string, Args)),
430 io.write_string(Ctor ++ "(" ++ ArgsStr ++ ")", !IO).424 io.write_string(Ctor ++ "(" ++ ArgsStr ++ ")", !IO).
431print_instr_(Indent, call_global(Dst, Func, Args), !IO) :-425print_instr_(Indent, call_global(Dst, Func, Args), !IO) :-
432 indent(Indent, !IO),426 indent(Indent, !IO),
433 io.write_string(ir.varname_string(Dst), !IO),427 io.write_string(ir.varname_string(Dst), !IO),
434 io.write_string(" = @", !IO),428 io.write_string(" = @", !IO),
435 ArgsStr = string.join_list(", ", list.map(ir.varname_string, Args)),429 ArgsStr = string.join_list(", ", list.map(atom_string, Args)),
436 io.write_string(Func ++ "(" ++ ArgsStr ++ ")", !IO).430 io.write_string(Func ++ "(" ++ ArgsStr ++ ")", !IO).
437431
438:- func fieldref_str(varname, string, int) = string.432:- func fieldref_str(varname, string, int) = string.
@@ -461,7 +455,7 @@
461 !IO) :-455 !IO) :-
462 indent(Indent, !IO),456 indent(Indent, !IO),
463 io.write_string("if ", !IO),457 io.write_string("if ", !IO),
464 io.write_string(ir.varname_string(Cond), !IO),458 io.write_string(atom_string(Cond), !IO),
465 io.write_string(" goto ", !IO),459 io.write_string(" goto ", !IO),
466 io.write_string(cfg.ref_name(ThenPart, CFG), !IO),460 io.write_string(cfg.ref_name(ThenPart, CFG), !IO),
467 io.write_string(" else goto ", !IO),461 io.write_string(" else goto ", !IO),
468462
=== modified file 'src/typedict.m'
--- src/typedict.m 2011-10-11 11:38:29 +0000
+++ src/typedict.m 2011-10-21 03:33:25 +0000
@@ -1224,7 +1224,9 @@
1224 ; Instr0 = new_closure(Dst, Name, Args) ->1224 ; Instr0 = new_closure(Dst, Name, Args) ->
1225 ( tables.lookup_local(!.LT, Dst, DstType) ->1225 ( tables.lookup_local(!.LT, Dst, DstType) ->
1226 FuncType = DstType,1226 FuncType = DstType,
1227 ( map(tables.lookup_local(!.LT), Args, ArgTypes_) ->1227 ( map_foldl(atom_type(PT, !.LT), Args, ArgTypes_, Varset, VSA) ->
1228 % See below
1229 VarsetAug = VSA,
1228 ArgTypes = ArgTypes_,1230 ArgTypes = ArgTypes_,
1229 ( DstType = types.app(types.functype, _) ->1231 ( DstType = types.app(types.functype, _) ->
1230 true1232 true
@@ -1239,15 +1241,19 @@
1239 error("augment_instr_globalrefs: Not in LT: " ++1241 error("augment_instr_globalrefs: Not in LT: " ++
1240 ir.varname_string(Dst))1242 ir.varname_string(Dst))
1241 ),1243 ),
1242 augment_globalref(PT, PTAug, Varset, Rigids, TDVars, Name, FuncType,1244 augment_globalref(PT, PTAug, VarsetAug, Rigids, TDVars, Name,
1243 ArgTypes, TDExprs, !RequiredVars),1245 FuncType, ArgTypes, TDExprs, !RequiredVars),
1244 % new_closure has the type dicts prepended to its argument list1246 % new_closure has the type dicts prepended to its argument list
1245 generate_expr_code(PTAug, Varset, Rigids, BlockID, TDExprs,1247 generate_expr_code(PTAug, Varset, Rigids, BlockID, TDExprs,
1246 TDArgs, PreInstrs, !LT, !BlockTempCount),1248 TDArgs, PreInstrs, !LT, !BlockTempCount),
1247 Instr = new_closure(Dst, Name, TDArgs ++ Args)1249 Instr = new_closure(Dst, Name, TDArgs ++ Args)
1248 ; Instr0 = call_global(Dst, Name, Args) ->1250 ; Instr0 = call_global(Dst, Name, Args) ->
1249 ( tables.lookup_local(!.LT, Dst, DstType) ->1251 ( tables.lookup_local(!.LT, Dst, DstType) ->
1250 ( map(tables.lookup_local(!.LT), Args, ArgTypes) ->1252 ( map_foldl(atom_type(PT, !.LT), Args, ArgTypes, Varset, VSA) ->
1253 % atom_type may add new varset items due to ctorsyms.
1254 % augment_globalref must use this augmented varset.
1255 % (See LP: #877111)
1256 VarsetAug = VSA,
1251 FuncType = types.app(types.functype, ArgTypes ++ [DstType])1257 FuncType = types.app(types.functype, ArgTypes ++ [DstType])
1252 ;1258 ;
1253 error("augment_instr_globalrefs: Arg not in LT")1259 error("augment_instr_globalrefs: Arg not in LT")
@@ -1256,8 +1262,8 @@
1256 error("augment_instr_globalrefs: Not in LT: " ++1262 error("augment_instr_globalrefs: Not in LT: " ++
1257 ir.varname_string(Dst))1263 ir.varname_string(Dst))
1258 ),1264 ),
1259 augment_globalref(PT, PTAug, Varset, Rigids, TDVars, Name, FuncType,1265 augment_globalref(PT, PTAug, VarsetAug, Rigids, TDVars, Name,
1260 [], TDExprs, !RequiredVars),1266 FuncType, [], TDExprs, !RequiredVars),
1261 ( method_builtin(Name), TDExprs = [TDExpr] ->1267 ( method_builtin(Name), TDExprs = [TDExpr] ->
1262 % call to show or eq -- replace with field access1268 % call to show or eq -- replace with field access
1263 MethodExpr0 = expr(fieldref(TDExpr, Name), no),1269 MethodExpr0 = expr(fieldref(TDExpr, Name), no),
@@ -1266,7 +1272,11 @@
1266 generate_expr_code(PTAug, Varset, Rigids, BlockID, [MethodExpr],1272 generate_expr_code(PTAug, Varset, Rigids, BlockID, [MethodExpr],
1267 MethodVars, PreInstrs, !LT, !BlockTempCount),1273 MethodVars, PreInstrs, !LT, !BlockTempCount),
1268 ( MethodVars = [MethodVar] ->1274 ( MethodVars = [MethodVar] ->
1269 Instr = call(Dst, MethodVar, Args)1275 ( MethodVar = varname(MethodVarName) ->
1276 Instr = call(Dst, MethodVarName, Args)
1277 ;
1278 error("augment_instr_globalrefs: call to non-var atom")
1279 )
1270 ;1280 ;
1271 error("augment_instr_globalrefs: generate_expr_code failed")1281 error("augment_instr_globalrefs: generate_expr_code failed")
1272 )1282 )
@@ -1282,18 +1292,31 @@
1282 ),1292 ),
1283 Instrs = PreInstrs ++ [InitInstr^instr_instr := Instr].1293 Instrs = PreInstrs ++ [InitInstr^instr_instr := Instr].
12841294
1295% Get the type of an atom. Fail if it cannot be found.
1296:- pred atom_type(progtable::in, localtable::in, atom::in, typeval::out,
1297 varset::in, varset::out) is semidet.
1298atom_type(_PT, LT, varname(VarName), Ty, !Varset) :-
1299 tables.lookup_local(LT, VarName, Ty).
1300atom_type(_PT, _LT, intatom(_), types.const("Int"), !Varset).
1301atom_type(PT, _LT, ctorsym(Name), Ty, !Varset) :-
1302 tables.lookup_ctor(PT, Name, Typedef, _),
1303 ir.ctor_type(Typedef, Name, CtorVarset, Ty0),
1304 % Add the varset of this ctor into the local varset namespace, and update
1305 % the type so is is in the local namespace.
1306 types.varset_mergeone(CtorVarset, !Varset, Ty0, Ty).
1307
1285% generate_expr_code(+PT, +Varset, +Rigids, +BlockID, +Exprs, -VarNames,1308% generate_expr_code(+PT, +Varset, +Rigids, +BlockID, +Exprs, -VarNames,
1286% -Instrs, !LT, !BlockTempCount).1309% -Instrs, !LT, !BlockTempCount).
1287% Generate code for a sequence of expressions (using ast_cfg). Concatenate all1310% Generate code for a sequence of expressions (using ast_cfg). Concatenate all
1288% the generated instructions together, update the localtable and temp count,1311% the generated instructions together, update the localtable and temp count,
1289% and produce a list of var names corresponding to the input expressions.1312% and produce a list of atoms corresponding to the input expressions.
1290:- pred generate_expr_code(progtable::in, varset::in, list(var)::in, int::in,1313:- pred generate_expr_code(progtable::in, varset::in, list(var)::in, int::in,
1291 list(expr)::in, list(varname)::out, list(instr)::out,1314 list(expr)::in, list(atom)::out, list(instr)::out,
1292 localtable::in, localtable::out, int::in, int::out) is det.1315 localtable::in, localtable::out, int::in, int::out) is det.
1293generate_expr_code(PT, Varset, _Rigids, BlockID, Exprs, VarNames, Instrs, !LT,1316generate_expr_code(PT, Varset, _Rigids, BlockID, Exprs, Atoms, Instrs, !LT,
1294 !BlockTempCount) :-1317 !BlockTempCount) :-
1295 list_map4_foldl(ast_cfg.expr_to_instrs_post_ssa(PT, Varset, BlockID),1318 list_map4_foldl(ast_cfg.expr_to_instrs_post_ssa(PT, Varset, BlockID),
1296 Exprs, VarNames, InstrLists, TypeMaps, SynthFuncses,1319 Exprs, Atoms, InstrLists, TypeMaps, SynthFuncses,
1297 !BlockTempCount),1320 !BlockTempCount),
1298 Instrs = list.condense(InstrLists),1321 Instrs = list.condense(InstrLists),
1299 ( list.condense(SynthFuncses) : list(function) = [] ->1322 ( list.condense(SynthFuncses) : list(function) = [] ->
13001323
=== modified file 'src/usedef.m'
--- src/usedef.m 2011-10-09 08:12:06 +0000
+++ src/usedef.m 2011-10-21 03:33:25 +0000
@@ -151,26 +151,27 @@
151 Uses = uses_cond_uses(UsesSet),151 Uses = uses_cond_uses(UsesSet),
152 Defs = uses_cond_uses(DefsSet).152 Defs = uses_cond_uses(DefsSet).
153153
154:- func atoms_vars(list(atom)) = list(varname).
155atoms_vars(Atoms) = Vars :-
156 list.filter_map(pred(varname(VarName)::in, VarName::out) is semidet,
157 Atoms, Vars).
158
154instr_use_def(Instr, Uses, Defs) :-159instr_use_def(Instr, Uses, Defs) :-
155 instr_use_def_(Instr ^ instr_instr, Uses, Defs).160 instr_use_def_(Instr ^ instr_instr, Uses, Defs).
156:- pred instr_use_def_(instr_::in, set(varname)::out, set(varname)::out)161:- pred instr_use_def_(instr_::in, set(varname)::out, set(varname)::out)
157 is det.162 is det.
158instr_use_def_(nop, set.init, set.init).163instr_use_def_(nop, set.init, set.init).
159instr_use_def_(mov(Dst, Src), Uses, Defs) :-164instr_use_def_(mov(Dst, Src), Uses, Defs) :-
160 set.singleton_set(Uses, Src),165 Uses = set(atoms_vars([Src])),
161 set.singleton_set(Defs, Dst).166 set.singleton_set(Defs, Dst).
162instr_use_def_(i_fieldset(Obj, _CtorIdxMap, _Msg, Var), Uses, set.init) :-167instr_use_def_(i_fieldset(Obj, _CtorIdxMap, _Msg, Var), Uses, set.init) :-
163 % Note: No defs, as the variable is being mutated, not assigned to.168 % Note: No defs, as the variable is being mutated, not assigned to.
164 Uses = set([Obj, Var]).169 Uses = set([Obj | atoms_vars([Var])]).
165instr_use_def_(i_fieldreplace(Dst, Obj, _CtorIdxMap, _Msg, Var), Uses, Defs):-170instr_use_def_(i_fieldreplace(Dst, Obj, _CtorIdxMap, _Msg, Var), Uses, Defs):-
166 Uses = set([Obj, Var]),171 Uses = set([Obj | atoms_vars([Var])]),
167 set.singleton_set(Defs, Dst).
168instr_use_def_(ld_intlit(Dst, _I), set.init, Defs) :-
169 set.singleton_set(Defs, Dst).172 set.singleton_set(Defs, Dst).
170instr_use_def_(ld_arraylit(Dst, Elems), Uses, Defs) :-173instr_use_def_(ld_arraylit(Dst, Elems), Uses, Defs) :-
171 Uses = set(Elems),174 Uses = set(atoms_vars(Elems)),
172 set.singleton_set(Defs, Dst).
173instr_use_def_(ld_ctorsym(Dst, _Name), set.init, Defs) :-
174 set.singleton_set(Defs, Dst).175 set.singleton_set(Defs, Dst).
175instr_use_def_(ld_cgc(Dst, _Name), set.init, Defs) :-176instr_use_def_(ld_cgc(Dst, _Name), set.init, Defs) :-
176 set.singleton_set(Defs, Dst).177 set.singleton_set(Defs, Dst).
@@ -178,16 +179,16 @@
178 set.singleton_set(Uses, Obj),179 set.singleton_set(Uses, Obj),
179 set.singleton_set(Defs, Dst).180 set.singleton_set(Defs, Dst).
180instr_use_def_(new_closure(Dst, _Func, Args), Uses, Defs) :-181instr_use_def_(new_closure(Dst, _Func, Args), Uses, Defs) :-
181 Uses = set(Args),182 Uses = set(atoms_vars(Args)),
182 set.singleton_set(Defs, Dst).183 set.singleton_set(Defs, Dst).
183instr_use_def_(call(Dst, Func, Args), Uses, Defs) :-184instr_use_def_(call(Dst, Func, Args), Uses, Defs) :-
184 Uses = set([Func|Args]),185 Uses = set([Func | atoms_vars(Args)]),
185 set.singleton_set(Defs, Dst).186 set.singleton_set(Defs, Dst).
186instr_use_def_(call_ctor(Dst, _Ctor, Args), Uses, Defs) :-187instr_use_def_(call_ctor(Dst, _Ctor, Args), Uses, Defs) :-
187 Uses = set(Args),188 Uses = set(atoms_vars(Args)),
188 set.singleton_set(Defs, Dst).189 set.singleton_set(Defs, Dst).
189instr_use_def_(call_global(Dst, _Func, Args), Uses, Defs) :-190instr_use_def_(call_global(Dst, _Func, Args), Uses, Defs) :-
190 Uses = set(Args),191 Uses = set(atoms_vars(Args)),
191 set.singleton_set(Defs, Dst).192 set.singleton_set(Defs, Dst).
192193
193instrs_use_def(Instrs, Uses, Defs) :-194instrs_use_def(Instrs, Uses, Defs) :-
@@ -199,7 +200,7 @@
199 set.singleton_set(Uses0, Control),200 set.singleton_set(Uses0, Control),
200 Uses = uses_cond_uses(Uses0).201 Uses = uses_cond_uses(Uses0).
201terminator_instr_use_def(cond_branch(Cond, _Then, _Else,_), Uses, map.init) :-202terminator_instr_use_def(cond_branch(Cond, _Then, _Else,_), Uses, map.init) :-
202 set.singleton_set(Uses0, Cond),203 Uses0 = set(atoms_vars([Cond])),
203 Uses = uses_cond_uses(Uses0).204 Uses = uses_cond_uses(Uses0).
204terminator_instr_use_def(branch(_Target,_), map.init, map.init).205terminator_instr_use_def(branch(_Target,_), map.init, map.init).
205terminator_instr_use_def(null_terminator(_), map.init, map.init).206terminator_instr_use_def(null_terminator(_), map.init, map.init).
206207
=== added file 'test/cases/compiler/ctorsym-unify.mar'
--- test/cases/compiler/ctorsym-unify.mar 1970-01-01 00:00:00 +0000
+++ test/cases/compiler/ctorsym-unify.mar 2011-10-21 03:33:25 +0000
@@ -0,0 +1,29 @@
1type List(a):
2 Cons(head :: a, tail :: List(a))
3 Nil
4
5def cons(y :: a, xs :: List(a)) :: List(a):
6 show(y)
7 show(xs)
8 return Cons(y, xs)
9
10def show_list(x :: List(a)) :: Array(Int):
11 return show(x)
12
13def id(x :: a) :: a = x
14
15# Test that we can take the Nil constructor :: List(a) and pass it to a
16# function of local type (b, List(b)) -> List(b) without unification problems.
17# LP: #877111
18def foo(one :: a, two :: b) :: List(b):
19 return cons(two, Nil)
20
21# Test that we can curry Nil into id (this broke when we tried to fix the
22# above bug)
23def nil_id() :: () -> List(t):
24 return id(Nil, ...)
25
26# Test that we can pass the typedict for Nil :: List(a) to another function
27# when passed directly as a constructor symbol atom.
28def bar(one :: a, two :: b) :: Array(Int):
29 return show(Nil)

Subscribers

People subscribed via source and target branches

to all changes: