[m-users.] Higher-order predicate issue
Sean Charles (emacstheviking)
objitsu at gmail.com
Sun Oct 3 08:11:20 AEDT 2021
Hi Peter,
Thank you very much indeed. It has taken me the best part of my day here but I have finally managed to understand things to the point where I now have what I would call ’standard higher order behaviours’ that Haskell provides for example. And more remarkably, I think, after many hours of writing small test programs to grok it, that I may be in serious danger of understanding what’s going on, at least in part!
The final working code feels clean now, I am sure you guys would shudder but here it is as a summary:
:- type renderer == (pred(render_inst, rop_error, tcon, tcon)).
:- mode renderer == (pred(in, out, in, out) is det).
my top level processing function is now declared as:
:- pred translate_top_level_term(renderer, lsnode, tcon, tcon, io, io).
:- mode translate_top_level_term(renderer, in, in, out, di, uo) is det.
and the intermediate level evaluation is:
:- pred eval(renderer, location, instruction, lsnode, renderout, tcon, tcon).
:- mode eval(renderer, in, in, in, out, in, out) is semidet.
It all works well but there is ONE fly left in the ointment… I currently have some inline code to decide on what target backend is going to do the rendering, currently there is only one but this code is to prove that I can have many:
LCTarget = string.to_lower(Target),
( if LCTarget = "php" then
Renderer = target_c.render
else
Renderer = target_c.render
),
% Renderer = get_target_renderer(Target),
The commented out line I cannot get to work, basically I moved that code into a small helper function for code clarity:
:- func get_target_renderer(string::in) = (renderer::out).
get_target_renderer(T) = R :-
LCTarget = string.to_lower(T),
( if LCTarget = "php" then
R = target_c.render
else
R = target_c.render
).
It compiles but when I try to use it seven types of hell break loose and I don’t understand the message, pasted at the end, and I would very much appreciate it if you had the time to explain what I have done this time to upset the compiler that tolerates me so wonderfully most of the time.
Again, thanks for that reply, it got me thinking, learning and tinkering to the point of success, mostly!
Sean.
————
translate.m:143: In clause for `translate(in, in, in, di, uo)':
translate.m:143: mode error in conjunction. The next 13 error messages
translate.m:143: indicate possible causes of this error.
translate.m:143:
translate.m:126: In clause for `translate(in, in, in, di, uo)':
translate.m:126: in argument 1 (i.e. the predicate term) of higher-order
translate.m:126: predicate call:
translate.m:126: mode error: variable `Renderer' has instantiatedness
translate.m:126: `ground',
translate.m:126: expecting higher-order pred inst of arity 4.
translate.m:143:
translate.m:128: In clause for `translate(in, in, in, di, uo)':
translate.m:128: in argument 1 of call to function `string.string'/1:
translate.m:128: mode error: variable `Result' has instantiatedness `free',
translate.m:128: expected instantiatedness was `ground'.
translate.m:143:
translate.m:128: In clause for `translate(in, in, in, di, uo)':
translate.m:128: in argument 2 of call to predicate `io.format'/4:
translate.m:128: mode error: variable `V_45' has instantiatedness `free',
translate.m:128: expected instantiatedness was `ground'.
translate.m:143:
translate.m:130: In clause for `translate(in, in, in, di, uo)':
translate.m:130: in argument 5 of call to predicate
translate.m:130: `translate.translate_top_level_term'/6:
translate.m:130: unique-mode error: the called procedure would clobber its
translate.m:130: argument, but variable `STATE_VARIABLE_IO_46' is still live.
translate.m:143:
translate.m:139: In clause for `translate(in, in, in, di, uo)':
translate.m:139: in argument 1 of call to function `list.reverse'/1:
translate.m:139: mode error: variable `V_52' has instantiatedness `free',
translate.m:139: expected instantiatedness was `ground'.
translate.m:143:
translate.m:139: In clause for `translate(in, in, in, di, uo)':
translate.m:139: in argument 1 of functor `reverse/1':
translate.m:139: mode error in unification of `STATE_VARIABLE_T_50' and
translate.m:139: `translate.tcon(V_107, V_52, V_108, V_109)'.
translate.m:139: Variable `STATE_VARIABLE_T_50' has instantiatedness `free',
translate.m:139: term `translate.tcon(V_107, V_52, V_108, V_109)' has
translate.m:139: instantiatedness
translate.m:139: named inst translate.tcon(free, free, free, free).
translate.m:143:
translate.m:140: In clause for `translate(in, in, in, di, uo)':
translate.m:140: in argument 1 of call to function `list.reverse'/1:
translate.m:140: mode error: variable `V_53' has instantiatedness `free',
translate.m:140: expected instantiatedness was `ground'.
translate.m:143:
translate.m:140: In clause for `translate(in, in, in, di, uo)':
translate.m:140: in argument 1 of functor `reverse/1':
translate.m:140: mode error in unification of `STATE_VARIABLE_T_50' and
translate.m:140: `translate.tcon(V_110, V_111, V_112, V_53)'.
translate.m:140: Variable `STATE_VARIABLE_T_50' has instantiatedness `free',
translate.m:140: term `translate.tcon(V_110, V_111, V_112, V_53)' has
translate.m:140: instantiatedness
translate.m:140: named inst translate.tcon(free, free, free, free).
translate.m:143:
translate.m:141: In clause for `translate(in, in, in, di, uo)':
translate.m:141: in argument 1 of call to function `list.reverse'/1:
translate.m:141: mode error: variable `V_54' has instantiatedness `free',
translate.m:141: expected instantiatedness was `ground'.
translate.m:143:
translate.m:141: In clause for `translate(in, in, in, di, uo)':
translate.m:141: in argument 1 of functor `reverse/1':
translate.m:141: mode error in unification of `STATE_VARIABLE_T_50' and
translate.m:141: `translate.tcon(V_113, V_114, V_54, V_115)'.
translate.m:141: Variable `STATE_VARIABLE_T_50' has instantiatedness `free',
translate.m:141: term `translate.tcon(V_113, V_114, V_54, V_115)' has
translate.m:141: instantiatedness
translate.m:141: named inst translate.tcon(free, free, free, free).
translate.m:143:
translate.m:143: In clause for `translate(in, in, in, di, uo)':
translate.m:143: in argument 1 of call to predicate
translate.m:143: `io.unsafe_set_io_state'/1:
translate.m:143: unique-mode error: the called procedure would clobber its
translate.m:143: argument, but variable `STATE_VARIABLE_Dbg_106' is still
translate.m:143: live.
translate.m:143:
translate.m:128: In clause for `translate(in, in, in, di, uo)':
translate.m:128: in argument 2 of call to predicate `io.format'/4:
translate.m:128: in list element #0:
translate.m:128: mode error in unification of `V_47' and `string.s(V_48)'.
translate.m:128: Variable `V_47' has instantiatedness `free',
translate.m:128: term `string.s(V_48)' has instantiatedness
translate.m:128: `named inst string.s(free)'.
translate.m:143:
translate.m:128: In clause for `translate(in, in, in, di, uo)':
translate.m:128: in argument 2 of call to predicate `io.format'/4:
translate.m:128: mode error in unification of `V_45' and `list.[V_47 |
translate.m:128: V_49]'.
translate.m:128: Variable `V_45' has instantiatedness `free',
translate.m:128: term `list.[V_47 | V_49]' has instantiatedness
translate.m:128: `named inst list.'[|]'(free, unique([]))’.
and here is the full section of code, with line numbers…...
101 translate(Options, Target, AstTerms, !IO) :-
102 % TODO: Env = map.init(string, univ),
103 % TODO: replace !IO with a stream I open into a file!
104 some [!T]
105 (
106 % LCTarget = string.to_lower(Target),
107 % ( if LCTarget = "php" then
108 % Renderer = target_c.render
109 % else
110 % Renderer = target_c.render
111 % ),
112 Renderer = get_target_renderer(Target),
113
114 trace[io(!Dbg), runtime(env("FELT_TRN"))]
115 (ttrace(0, "selected target:%s\n%s\n",
116 [s(string(Renderer)), s(string(AstTerms))],
117 !Dbg)),
118
119 !:T = tcon(
120 Options, % command line
121 [], % output
122 [], % warnings
123 [] % errors
124 ),
125
126 Renderer(include([pstring(pos(0,0,0),"testing")]),
127 Result,!T),
128 io.format("TESTED OUTPUT: %s",[s(string(Result))], !IO),
129
130 translate_top_level_term(
131 Renderer,
132 AstTerms,
133 !T,
134 !IO
135 ),
136
137 % CodeList MAY be invalid of errors are present.
138 % ^^^
139 Code = reverse(output(!.T)),
140 Errors = reverse(errors(!.T)), %sort by pos(!,_,_)
141 Warnings = reverse(warnings(!.T)),
142
143 trace[io(!Dbg), runtime(env("FELT_TRN"))]
144 (
145 ttrace(0, "%s:WARNINGS%s", [s(colour(yellow)),
146 s(colour(reset))], !Dbg),
147 list.foldl(io.print_line, Warnings, !Dbg),
148
149 ttrace(0, "%s:ERRORS%s", [s(colour(red)),
150 s(colour(reset))], !Dbg),
151 list.foldl(io.print_line, Errors, !Dbg),
152
153 ttrace(0, "%s:TRANSLATIONS%s", [s(colour(green)),
154 s(colour(reset))], !Dbg),
155 list.foldl(io.print_line, Code, !Dbg),
156
157 io.format("\n**************\n", [], !Dbg),
158 list.foldl(render_op(0, Options), Code, !Dbg),
159 io.format("\n**************\n", [], !Dbg)
160 )
161 ).
> On 2 Oct 2021, at 02:57, Peter Wang <novalazy at gmail.com> wrote:
>
> On Fri, 01 Oct 2021 21:27:40 +0100 "Sean Charles (emacstheviking)" <objitsu at gmail.com <mailto:objitsu at gmail.com>> wrote:
>> Hi,
>>
>> I am trying to pass around a predicate to execute at a later point in my translation process:
>>
>> :- type renderer == (pred(instruction, lstring, rop_error, tcon, tcon)).
>> :- inst renderer == (pred(in, in, out, in, out) is det).
>>
>> then to set the renderer:
>>
>> Renderer = target_c.render
>>
>> then I have a work in progress evaluation predicate:
>>
>> :- pred eval(renderer::in, location::in, instruction::in, lsnode::in,
>> renderout::out, tcon::in, tcon::out) is semidet.
>
> The mode 'in' is defined as 'ground >> ground',
> so the pred-mode declaration declares that the first argument has
> initial inst 'ground' and final inst 'ground'.
>
>>
>> eval(Render, Pos, defvar, Args, Result, !T) :-
>> trace[io(!Dbg), runtime(env("FELT_TRN"))]
>> (sdump($pred, $line, Args, !Dbg)),
>>
>> ( if Args = [tk(Pos, VarName)] then
>> %
>> % this it not working well
>> % ...what can be done to make it better ?
>> %
>> 348 Render(defvar, lstring(Pos, VarName), CodeM, !T),
>
> Renderer has inst 'ground' here, meaning it has no higher-order inst
> information, so it cannot be called. (It is possible to call a
> higher-order *function* term without higher-order inst information,
> but that is a special case.)
>
> You need to change the mode of the first argument from 'in' to
> 'in(renderer)', which expands to 'renderer >> renderer',
> where 'renderer' refers to the inst you have defined earlier.
> There is no implied connection between the type name 'renderer'
> and the inst name 'renderer'.
>
> Peter
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20211002/b8c5d94d/attachment-0001.html>
More information about the users
mailing list