[m-users.] A naming and access problem
Sean Charles (emacstheviking)
objitsu at gmail.com
Tue May 18 22:32:22 AEST 2021
Hi Zoltan,
Thank you. I have been attempting to port my SWI Prolog code but I can see in this instance using arg/4 was not the way.
As it happens I have already now written a predicate that does what you suggested `func` does however I will rewrite that to use func as it better suits the call site context.
Originally the functors for the brackets were op/cp/ol/cl/om/cm and ironically I only recently changed them as I thought it would make the AST code more readable! How wrong can one get? I will also put them back too!
Many thanks again,
Sean
> On 18 May 2021, at 13:28, Zoltan Somogyi <zoltan.somogyi at runbox.com> wrote:
>
>
> 2021-05-18 18:00 GMT+10:00 "Sean Charles (emacstheviking)" <objitsu at gmail.com>:
>> Hi, I have a token definition like this:
>>
>> :- type location
>> ---> pos(index::int, line::int, col::int).
>>
>> % for ast detection later.
>> :- type token
>> ---> tk(location, string)
>> ; '('(location) ; ')'(location)
>> ; '['(location) ; ']'(location)
>> ; '{'(location) ; '}'(location)
>> ; c1(location, string) ; cn(location, string)
>> ; s1(location, string) ; s2(location, string)
>> .
>>
>> Given the above, I have now realised that I can’t easily (?) access the location part of any particulr instance of the token type because it doesn’t have a name and thus no field reader will be generated. As I understand it, I would have to give a unique name.
>>
>> I tried:
>>
>> arg(Tok1, canonicalize, 0, Out),
>>
>> and was rewarded with this message from the compiler,
>>
>> repl.m:199: In clause for predicate `run_lex'/3:
>> repl.m:199: in argument 1 of call to predicate `lexer.on_string'/4:
>> repl.m:199: in argument 2 of functor `string.between/3’:
>> repl.m:199: in unification of argument
>> repl.m:199: and term `index(Out)’:
>> repl.m:199: type error in argument of functor `index'/1.
>> repl.m:199: Argument 1 (Out) has type `(some [ArgT] ArgT)’,
>> repl.m:199: expected type was `lexer.location’.
>>
>> Which is fair enough but how do I do it? That message is currently above my pay grade.
>> Have I overlooked something blindingly obvious?
>
> Using 'arg' here is the wrong thing to do for several reasons.
>
> First, it would be fragile in the face of future development that would add
> some field other than the location in front of what is now the first arg in some
> of the token type's function symbols.
>
> Second, the first argument of the different function symbols can be different.
> In this case, they are not, but 'arg' cannot rely on that: it has to work even on types
> whose function symbols have different types in the same argument positions.
> This is why its type signature says "I am returning a value, but the type of that
> value is not known at compile time". (That is what "some [ArgT] ArgT" means.)
>
> Third, that is an existential type, and as I said earlier, that is not something
> people new to Mercury should start with.
>
> Your problem has a much simpler solution. You can simply write
>
> :- func get_token_location(token) = location.
>
> get_token_location(tk(Locn, _)) = Locn.
> get_token_location(c1(Locn, )) = Locn.
> etc.
>
> By the way, I advise you against using character constants as function symbols.
> Mercury supports this because its syntax was originally the same as the syntax
> of Prolog (the Mercury parser started out as an existing parser for Prolog), but
> just because you can do something, does not mean you should. Using e.g.
> lparen and rparen instead of '(' and ')' as function symbol names would
> essentially eliminate the chance of code not being parsed right without
> quoting, and would make error messages much easier to read. As you can see,
> all the function symbols in the token type in Mercury's own lexer contain nothing
> but lower case letters and underscores.
>
> Zoltan.
More information about the users
mailing list