Buffer position to line,column

Sorted. Ended up with this , for the record, probably not most efficient but the first error that gets found aborts the translation anyway.

pos_linecol(Src, Pos, (Line, Col)) :-
    poslin(Src, Pos, 1, 0, Line, Col).
           
poslin(_, 0, Lin, Cin, Lin, Cin) :- !.
poslin([], _, Lin, Cin, Lin, Cin) :- !.
poslin([Chr|Cs], Pos, Lin, Cin, L, C) :-
    chrpos(Chr, (Lin, Cin), (Lout, Cout)),
    Pos1 is Pos-1,
    poslin(Cs, Pos1, Lout, Cout, L, C).

chrpos(10,(L,_),(L1,0)) :- L1 is L+1, !.
chrpos(_, (L,C),(L,C1)) :- C1 is C+1.

Is this for your language? If so can you not get your lexer to return (Lexeme, Line, Col) triples, ig that would be easier if you want to report errors with line numbers and column numbers.

What about the other unprintables (Ch =< 32) such as tab, carriage return, etc.?

Also, what about the built in prdicate stream_position_line_position/2 have you considered that? Actually, that might not be ISO compliant, what about stream_position_data/3?

@bwat – old history now!! I COULD have made the triple but for memory efficiency (I know, premature optimisation!) on possibly large compilation units, I elected to just have the buffer position and then turn it into an absolute line and column when needed.

Actually, it’s all working with print_message/2 in the last 15 minutes:

ast:  ?- runfile('fixtures/one.lisp',X).
ERROR: fixtures/one.lisp:16:6: map has an odd number of elements.
X = fail(ast_error(syntax(map, uneven_elements, 342))).

You can see the rendered message and the X variable shows the original buffer position.
This leads me to another question, another post!

Thanks.
Sean.