githwxi / ATS-Postiats

ATS2: Unleashing the Potentials of Types and Templates
www.ats-lang.org
Other
354 stars 54 forks source link

undefined reference to `atspre_fileref_get_line_string_main2` #248

Closed morgancmartin closed 5 years ago

morgancmartin commented 5 years ago

When using the fileref_get_line_string function defined in prelude/DATS/filebas.dats, ATS compilation to C succeeds, but GCC throws the error in the title.

I'm not entirely certain why the issue is occurring, but I happened to notice the underlying C function atspre_fileref_get_line_string_main2 was the only non-template, embedded-C style function in the file. Going off that, I moved the C implementation to the matching function declaration in prelude/CATS/filebas.cats, and appended 0 to the parameters there to match the function body and GCC has stopped throwing errors.

My guess is it was simply lost in the mix during some function template refactoring at some point.

Due to my incomplete understanding of ATS internals, I opted to submit this as an issue rather than a PR, but I would be more than happy to submit the PR if it's determined my solution is appropriate.

morgancmartin commented 5 years ago

And in case more context is needed, the issue can be reproduced by attempting to compile the following file:

#include "share/atspre_define.hats"
#include "share/atspre_staload.hats"

implement
main0 (
// argumentless
) = loop() where
{
//
fun loop(): void = let
  val isnot =
    fileref_isnot_eof(stdin_ref)
  // end of [val]
in
//
if isnot then let
  val line =
    fileref_get_line_string(stdin_ref)
  val ((*void*)) = fprintln!(stdout_ref, line)
  val ((*void*)) = strptr_free(line)
in
  loop((*void*))
end else ((*loop exits as the end-of-file is reached*))
//
end (* end of [loop] *)
//
} (* end of [main0] *)

And here is a copy of the original function declaration in filebas.cats:

extern
atstype_ptr
atspre_fileref_get_line_string_main2
(
  atstype_int bsz // int bsz
, atstype_ptr filp // FILE*filp
, atstype_ref nlen // (int)*nlen
) ; // endfun

And finally, a copy of it after removing the implementation from filebas.dats and moving it to the above function declaration in filebas.cats:

extern
atstype_ptr
atspre_fileref_get_line_string_main2
(
  atstype_int bsz0 // int bsz
, atstype_ptr filp0 // FILE*filp
, atstype_ref nlen0 // (int)*nlen
)
{
//
  int bsz = bsz0;
  int ofs1 = 0, ofs2 = 0;
  int *nlen = (int*)nlen0;
  FILE *filp = (FILE*)filp0 ;
  char *buf1, *buf2, *pres ;
//
  buf1 = atspre_malloc_gc(bsz) ;
//
  while (1) {
    buf2 = buf1+ofs1 ;
    pres = fgets(buf2, bsz-ofs1, filp) ;
    if (!pres)
    {
      if (feof(filp))
      {
        *buf2 = '\0' ;
        *nlen = ofs1 ; return buf1 ;
      } else {
        atspre_mfree_gc(buf1) ;
        *nlen = -1 ; return (char*)0 ;
      } // end of [if]
    }
//
    ofs2 = strlen(buf2) ;
//
    if
    (ofs2 > 0) ofs1 += ofs2 ; else return buf1;
//
// HX: ofs1 > 0 holds at this point
// HX: the newline symbol needs to be trimmed:
//
    if(
    buf1[ofs1-1]=='\n'
    ) {
    buf1[ofs1-1] = '\0'; *nlen = ofs1-1 ; return buf1 ;
    } // end of [if]
//
// HX: there is room // so there are no more chars:
//
    if (ofs1+1 < bsz) { ( *nlen = ofs1 ) ; return buf1 ; }
//
// HX: there is no room // another call to [fgets] is needed:
//
    bsz *= 2 ;
    buf2 = buf1 ;
    buf1 = atspre_malloc_gc(bsz) ;
    memcpy(buf1, buf2, ofs1) ; atspre_mfree_gc(buf2) ;
  } // end of [while]
//
  return buf1 ; // HX: this is really deadcode
//
} // end of [atspre_fileref_get_line_string_main2]
githwxi commented 5 years ago

I see. This is case where you need -latslib when compiling.

On Mon, Sep 2, 2019 at 9:34 PM Morgan Martin notifications@github.com wrote:

And in case more context is needed, the issue can be reproduced by attempting to compile the following file:

include "share/atspre_define.hats"

include "share/atspre_staload.hats"

implement main0 ( // argumentless ) = loop() where { // fun loop(): void = let val isnot = fileref_isnot_eof(stdin_ref) // end of [val] in // if isnot then let val line = fileref_get_line_string(stdin_ref) val ((void)) = fprintln!(stdout_ref, line) val ((void)) = strptr_free(line) in loop((void)) end else ((loop exits as the end-of-file is reached)) // end ( end of [loop] ) // } ( end of [main0] )

And here is a copy of the original function declaration in filebas.cats:

extern atstype_ptr atspre_fileref_get_line_string_main2 ( atstype_int bsz // int bsz , atstype_ptr filp // FILEfilp , atstype_ref nlen // (int)nlen ) ; // endfun

And finally, a copy of it after removing the implementation from filebas.dats and moving it to the above function declaration in filebas.cats:

extern atstype_ptr atspre_fileref_get_line_string_main2 ( atstype_int bsz0 // int bsz , atstype_ptr filp0 // FILEfilp , atstype_ref nlen0 // (int)nlen ) { // int bsz = bsz0; int ofs1 = 0, ofs2 = 0; int nlen = (int)nlen0; FILE filp = (FILE)filp0 ; char buf1, buf2, pres ; // buf1 = atspre_malloc_gc(bsz) ; // while (1) { buf2 = buf1+ofs1 ; pres = fgets(buf2, bsz-ofs1, filp) ; if (!pres) { if (feof(filp)) { buf2 = '\0' ; nlen = ofs1 ; return buf1 ; } else { atspre_mfree_gc(buf1) ; nlen = -1 ; return (char)0 ; } // end of [if] } // ofs2 = strlen(buf2) ; // if (ofs2 > 0) ofs1 += ofs2 ; else return buf1; // // HX: ofs1 > 0 holds at this point // HX: the newline symbol needs to be trimmed: // if( buf1[ofs1-1]=='\n' ) { buf1[ofs1-1] = '\0'; nlen = ofs1-1 ; return buf1 ; } // end of [if] // // HX: there is room // so there are no more chars: // if (ofs1+1 < bsz) { ( nlen = ofs1 ) ; return buf1 ; } // // HX: there is no room // another call to [fgets] is needed: // bsz = 2 ; buf2 = buf1 ; buf1 = atspre_malloc_gc(bsz) ; memcpy(buf1, buf2, ofs1) ; atspre_mfree_gc(buf2) ; } // end of [while] // return buf1 ; // HX: this is really deadcode // } // end of [atspre_fileref_get_line_string_main2]

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/githwxi/ATS-Postiats/issues/248?email_source=notifications&email_token=AAEXZVY2QS6FH7DSQFZLE2LQHW5KFA5CNFSM4ITBBVF2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD5WYKRA#issuecomment-527271236, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEXZV7JA7ICWEJFMCLH4YTQHW5KFANCNFSM4ITBBVFQ .

morgancmartin commented 5 years ago

Ah! I just did so and it worked like a charm. Thanks very much.

Do you happen to have a link to any relevant documentation? I believe I've seen it somewhere, but I can't seem to remember where exactly.

morgancmartin commented 5 years ago

Scratch that, I think I found what I was remembering in the intro book. Thanks again for the help.

Closing this issue.

August-Alm commented 4 years ago

Hi! I just discovered that I have the same issue. And compiling with -latslib does not remedy my problem. Here is my code:

include "share/atspre_define.hats"

include "share/atspre_staload.hats"

( Some functions here. )

implement main0 () = loop() where

fun loop(): void = let
    val isnot_eof = fileref_isnot_eof(stdin_ref)
  in
    if isnot_eof then let
        val line = fileref_get_line_string(stdin_ref)
        val echo = rep(line)
      in
        ( fprint_string(stdout_ref, "user> ")
        ; fprintln!(stdout_ref, echo)
        ; strptr_free(echo)
        ; loop()
        )
      end
    else // if eof
      ()
  end // of loop

end

August-Alm commented 4 years ago

Sorry, I got it working. Not sure why, maybe I had the compilator flags in the wrong places.