githwxi / ATS-Postiats

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

Error with order of functions #231

Open antoyo opened 5 years ago

antoyo commented 5 years ago

Hi. Here's the code with the error:

(* lib.dats *)
#include "share/atspre_staload.hats"
#include "share/atspre_staload_libats_ML.hats"

#define ATS_DYNLOADFLAG 0

staload UN = "prelude/SATS/unsafe.sats"
staload "./lib.sats"

implement alpha() =
    one_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

implement alpha_num() =
    or(alpha(), num())

implement {a} or(parser1, parser2) =
   '{ parser = lam(stream) =>
        case+ parser1.parser(stream) of
        | Ok(@(stream, value)) => Ok((stream, value))
        | Err(_) => parser2.parser(stream)
    }

implement num() =
    one_of("0123456789")

implement one_of(chars) =
   '{ parser = lam(stream) =>
        case+ stream of
        | list0_nil() => Err(Eof)
        | list0_cons(first, rest) =>
            if first <> 0 && string_find_index(chars, $UN.cast{charNZ}(first)) <> i2ssz(~1) then
                Ok((rest, first))
            else
                Err(Unexpected(
                   '{ actual = char2string(first)
                    , expected = "one of " + chars
                    }
                ))
    }

and:

(* lib.sats *)
#include "share/atspre_staload_libats_ML.hats"

datatype Result(value:t@ype, error: t@ype) =
    | Ok of value
    | Err of error

typedef UnexpectedError =
   '{ actual = string
    , expected = string
    }

datatype Error =
    | Eof
    | Unexpected of UnexpectedError

typedef Stream = list0(char)

typedef Parser(a: t@ype) =
  '{ parser = (Stream) -<cloref1> Result((Stream, a), Error)
   }

fun alpha(): Parser(char)

fun alpha_num(): Parser(char)

fun num(): Parser(char)

fun one_of(chars: string): Parser(char)

fun {a: t@ype} or(parser1: Parser(a), parser2: Parser(a)): Parser(a)

I've tried to reproduce the issue with a small example, but I was unable to do so, so I've simplified my example to a minimum. Here's the error that is produced:

In file included from lib_dats.c:15:
lib_dats.c: Dans la fonction « _057_Tests_057_ATS_057_order_bug_057_lib_056_sats__alpha_num »:
lib_dats.c:1799:21: error: « PMVtmpltcstmat » non déclaré (première utilisation dans cette fonction)
 ATSINSmove(tmpret1, PMVtmpltcstmat[0](or<S2Ecst(char_t0ype)>)(tmp2, tmp3)) ;
                     ^~~~~~~~~~~~~~
/usr/lib/ats2-postiats-0.3.11/ccomp/runtime/pats_ccomp_instrset.h:276:37: note: dans la définition de la macro « ATSINSmove »
 #define ATSINSmove(tmp, val) (tmp = val)
                                     ^~~
lib_dats.c:1799:21: note: chaque identificateur non déclaré est rapporté une seule fois pour chaque fonction dans laquelle il apparaît
 ATSINSmove(tmpret1, PMVtmpltcstmat[0](or<S2Ecst(char_t0ype)>)(tmp2, tmp3)) ;
                     ^~~~~~~~~~~~~~
/usr/lib/ats2-postiats-0.3.11/ccomp/runtime/pats_ccomp_instrset.h:276:37: note: dans la définition de la macro « ATSINSmove »
 #define ATSINSmove(tmp, val) (tmp = val)
                                     ^~~
lib_dats.c:1799:39: error: « or » non déclaré (première utilisation dans cette fonction)
 ATSINSmove(tmpret1, PMVtmpltcstmat[0](or<S2Ecst(char_t0ype)>)(tmp2, tmp3)) ;
                                       ^~
/usr/lib/ats2-postiats-0.3.11/ccomp/runtime/pats_ccomp_instrset.h:276:37: note: dans la définition de la macro « ATSINSmove »
 #define ATSINSmove(tmp, val) (tmp = val)
                                     ^~~
lib_dats.c:1799:42: warning: déclaration implicite de la fonction « S2Ecst » [-Wimplicit-function-declaration]
 ATSINSmove(tmpret1, PMVtmpltcstmat[0](or<S2Ecst(char_t0ype)>)(tmp2, tmp3)) ;
                                          ^~~~~~
/usr/lib/ats2-postiats-0.3.11/ccomp/runtime/pats_ccomp_instrset.h:276:37: note: dans la définition de la macro « ATSINSmove »
 #define ATSINSmove(tmp, val) (tmp = val)
                                     ^~~
lib_dats.c:1799:49: error: « char_t0ype » non déclaré (première utilisation dans cette fonction); vouliez-vous utiliser « wchar_t » ?
 ATSINSmove(tmpret1, PMVtmpltcstmat[0](or<S2Ecst(char_t0ype)>)(tmp2, tmp3)) ;
                                                 ^~~~~~~~~~
/usr/lib/ats2-postiats-0.3.11/ccomp/runtime/pats_ccomp_instrset.h:276:37: note: dans la définition de la macro « ATSINSmove »
 #define ATSINSmove(tmp, val) (tmp = val)
                                     ^~~
lib_dats.c:1799:61: error: expected expression before « ) » token
 ATSINSmove(tmpret1, PMVtmpltcstmat[0](or<S2Ecst(char_t0ype)>)(tmp2, tmp3)) ;
                                                             ^
/usr/lib/ats2-postiats-0.3.11/ccomp/runtime/pats_ccomp_instrset.h:276:37: note: dans la définition de la macro « ATSINSmove »
 #define ATSINSmove(tmp, val) (tmp = val)
                                     ^~~

If I put the implement or before the call to or, the code compiles fine:

implement {a} or(parser1, parser2) =
   '{ parser = lam(stream) =>
        case+ parser1.parser(stream) of
        | Ok(@(stream, value)) => Ok((stream, value))
        | Err(_) => parser2.parser(stream)
    }

implement alpha_num() =
    or(alpha(), num())

I believe this is a bug as this seems to work in other scenarios. Thanks to fix the issue.

githwxi commented 5 years ago

This is not a bug.

It is actually a very important feature. A template function can always be re-implemented. And lexical scoping is used to determine which implementation of the template is supposed to be used.

antoyo commented 5 years ago

Ok, having an error reporting in ATS instead of in C (gcc) would be great to explain what is going on. It seemed strange to me that function without generic parameters have a different behavior.