From d7680514dbd6700024d7e2c0d0850c00a9dd64ee Mon Sep 17 00:00:00 2001 From: OopsOverflow Date: Mon, 10 Jan 2022 15:26:53 +0100 Subject: [PATCH] add test cases --- progs/err1.kat | 39 +++++++ progs/err2.kat | 13 +++ progs/err3.kat | 14 +++ progs/err4.kat | 14 +++ progs/errCast.kat | 48 ++++++++ progs/errCycle.kat | 7 ++ progs/errResult.kat | 27 +++++ progs/ex1-V3.kat | 261 ++++++++++++++++++++++++++++++++++++++++++++ progs/gn.kat | 261 ++++++++++++++++++++++++++++++++++++++++++++ progs/grandMere.kat | 46 ++++++++ progs/masking1.kat | 46 ++++++++ test/parse.ml | 18 +-- test/utils.ml | 4 +- 13 files changed, 788 insertions(+), 10 deletions(-) create mode 100644 progs/err1.kat create mode 100644 progs/err2.kat create mode 100644 progs/err3.kat create mode 100644 progs/err4.kat create mode 100644 progs/errCast.kat create mode 100644 progs/errCycle.kat create mode 100644 progs/errResult.kat create mode 100644 progs/ex1-V3.kat create mode 100644 progs/gn.kat create mode 100644 progs/grandMere.kat create mode 100644 progs/masking1.kat diff --git a/progs/err1.kat b/progs/err1.kat new file mode 100644 index 0000000..4a22286 --- /dev/null +++ b/progs/err1.kat @@ -0,0 +1,39 @@ +class Point(xc: Integer, yc: Integer) is { + var x: Integer + var y: Integer + var name: String + var super : Integer /* interdit */ + + def Point(xc: Integer, yc: Integer) is { + this.x := xc; this.y := yc; name = "?"; + } + + + def setName(s: String) : Point is { + this.name := s; + result := this; + return; + this.super := s; /* interdit */ + } + + def print() is { + this.name.println(); + this := new Point(0, 0); /* interdit */ + this.x := this.super.x; /* incorrect */ + result := this; /* interdit car pas de type de retour. */ + } + +} +{ + p, p2: Point + x: Integer + is + p1 := new Point(1, 5); + p2 := new Point(2, 3); + x := new Integer(1); /* interdit */ + this := x; /* interdit */ + result := x; /* interdit */ + p2.setName("glop"); + p1.print(); + p2.print(); +} diff --git a/progs/err2.kat b/progs/err2.kat new file mode 100644 index 0000000..3f8cffd --- /dev/null +++ b/progs/err2.kat @@ -0,0 +1,13 @@ +class A() is { + var va: Integer + def A() is { va := 1; } +} +class B() extends Integer /* Incorrect */ is { + var vb: Integer + def B() : Integer(12) is { vb := 2; } +} +class A2() extends B is { + var w: Integer + def A2() : B() is { w := 3; } + } +{ /* empty */ } diff --git a/progs/err3.kat b/progs/err3.kat new file mode 100644 index 0000000..0536df6 --- /dev/null +++ b/progs/err3.kat @@ -0,0 +1,14 @@ +class A() is { + var va: Integer + def A() is {} +} +class B() extends Int is { /* incorrect: Int inconnue */ + var vb: Integer + def B() : Int(12) is { } +} +class A() extends B is { /* incorrect: double declaration de A */ + var w: Integer + def A() : B() is { } +} +{ +} diff --git a/progs/err4.kat b/progs/err4.kat new file mode 100644 index 0000000..6bf9e5a --- /dev/null +++ b/progs/err4.kat @@ -0,0 +1,14 @@ +class A() is { + var va: Integer + def A() is {} +} +class B() extends Int is { /* incorrect: Int inconnue */ + var vb: Integer + def B() : Int(12) is { } +} +class C() extends B is { /* incorrect: double declaration de A */ + var w: Integer + def C() : B() is { } +} +{ +} diff --git a/progs/errCast.kat b/progs/errCast.kat new file mode 100644 index 0000000..cfc35a9 --- /dev/null +++ b/progs/errCast.kat @@ -0,0 +1,48 @@ +class A() is { + var v: Integer + def f() : Integer := this.v + def A() is { v := 1; } +} +class A2() extends A is { + var v: String + var w: Integer + def g() : String := this.v + def A2() : A() is { v := "coucou"; w := 5; } +} +class A3() extends A2 is { + var v: Integer + def override f() : Integer := this.v + def h() : Integer := (A this).v /* OK */ + def h2(): String := (A2 this).v /* OK */ + /* def k() : Integer := (A this).w /* Incorrect */ + def A3() : A2() is { v := 5; } +} +class A4() extends A3 is { + def A4() : A3() is {} +} +class B() extends A /* une soeur de A2 ! */ +is { + def B() : A() is { } +} +{ + monA : A + monA2 : A2 + monA3 : A3 + monA4 : A4 + monB : B + is + monA := new A(); + monA2 := new A2(); + monA3 := new A3(); + monA4 := new A4(); + monB := new B(); + + /* (A monA3).h().toString.println(); /* KO: h indefinie dans A */ + /* (A4 monA3); /* KO: pas de cast descendant */ + (A3 monA4); /* OK */ + /* (A3 monA); /* KO: pas de cast descendant */ + /* (A2 monA4).k(); /* KO: pas de k() dans A2 */ + /* (Unknown monA4); */ + /* (B monA2); /* KO: A2 et B sons sans relation d'héritage */ + /* (A2 monB); /* idem */ +} diff --git a/progs/errCycle.kat b/progs/errCycle.kat new file mode 100644 index 0000000..f959ccd --- /dev/null +++ b/progs/errCycle.kat @@ -0,0 +1,7 @@ +class A0() is { var va: Integer def A0() is { va := 1; } } +class B() extends A is { var vb: Integer def B(): A() is { vb := 2; } } +/* erreur A et B forment un circuit dans le graphe d'héritage */ +class A() extends B is { var w: Integer def A(): B() is { w := 3; } } +{ + /* bloc vide: autorisé ! */ +} diff --git a/progs/errResult.kat b/progs/errResult.kat new file mode 100644 index 0000000..c9515ff --- /dev/null +++ b/progs/errResult.kat @@ -0,0 +1,27 @@ +class A() is { + var unA : A + var result : Integer /* incorrect: identificateur reserve ! */ + def f(result: Integer) is { } /* incorrect: identificateur reserve ! */ + def g() is { + result : Integer /* incorrect: identificateur reserve ! */ + is + result := 1; + } + def h() is { + result := 1; /* incorrect: h() ne renvoie rien */ + } + def k() : Integer is { + result := 1; /* correct */ + } + def k2() : Integer is { + result := "coucou"; /* incorrect: pas du bon type */ + } + + def A() is { result := unA; } /* result incorrect dans un constructeur */ +} +{ + result : Integer /* incorrect: identificateur reserve ! */ + is + 1; + result.toString().println(); +} diff --git a/progs/ex1-V3.kat b/progs/ex1-V3.kat new file mode 100644 index 0000000..26e0ab6 --- /dev/null +++ b/progs/ex1-V3.kat @@ -0,0 +1,261 @@ +class Point(var x, y: Integer, var name: String) is { + var static next : Integer + def static incr() : Integer is + { Point.next := Point.next + 1; result := Point.next; } + def static howMany() : Integer := Point.next + def static init () is { Point.next := 0; } + + /* attributs supplementaires à initialiser dans le constructeur */ + var hasClone : Integer + var index : Integer + /* la valeur du champ ci-dessous est indefinie si hasClone vaut 0. + * Le probleme est qu'on n'a pas l'equivalent de NULL (du bon type) + */ + var clone : Point + + + /* L'en-tete du constructeur doit etre identique a celui de la classe. + * Les parametres précédés de var correspondent implictement à des attributs + * de meme nom qui seront intialises automatiquement à la valeur du + * parametre, comme si on avait la ligne suivante en tete du constructeur: + * this.x := x; this.y := y; this.name := name; + */ + + def Point(var x, y: Integer, var name: String) is + { this.index := Point.incr(); this.hasClone := 0; } + + def getx() : Integer := this.x /* pas de this implicite */ + + def gety() : Integer := this.y + + def setName(s: String) is { this.name := s; } + + def isCloned() : Integer := this.hasClone <> 0 + + def move(dx: Integer, dy: Integer, verbose: Integer) : Point is { + this.x := this.x + dx; this.y := this.y + dy; + if verbose then { this.print(verbose); } else {} + /* pseudo variable 'result' dans laquelle, par convention, on laisse + * la valeur de retour d'une fonction qui a un type de retour. + * On aurait pu ecrire aussi + * return this; + */ + result := this; + } + + def print(verbose : Integer) is { + if verbose then "Inside Point::print".println(); else { } + /* Exemples avec l'operateur & de concatenation de chaines */ + this.name.print(); + ( "= (" & this.x.toString() & ", " & this.y.toString() & ")" ).println(); + } + + /* par defaut, on ajoute un ' au nom de l'objet. Modifiable avec setName */ + def clone() : Point is + { this.hasClone = 1; + /* On memorise le dernier clone construit à partir de cet objet + * si on voulait on pourrait le chainer a la fin de la liste des clones + */ + this.clone := new Point(this.x, this.y, this.name & "'"); + result := this.clone; + } + + /* imprime le clone de cet objet, s'il existe, ainsi que recursivement + * les clones de ce dernier + */ + def allClones () is { + if this.hasClone <> 0 then { this.clone.print(1); this.clone.allClones(); } + else { } + } + + def egal(p: Point) : Integer is { /* autre version */ + b1, b2: Integer + is + b1 := p.x - this.x; + b2 := p.y - this.y; + result := 0; + if b1 then { } else { result := b2 = 0; } + } +} /* Fin de la classe Point */ + +class Couleur(var coul: Integer) is { + /* 3 couleurs : couleur = 0, 1 ou 2 + * Le corps du constructeur garantit qu'on a bien que trois couleurs. + */ + + def Couleur (var coul: Integer) is { + if this.coul < 0 then this.coul := 0; + else if this.coul > 2 then this.coul := 0; else {} + } + + def name(verbose: Integer) : String is { + aux: String + is + if verbose then "Inside Couleur::couleur".println(); else {} + if this.coul = 0 then result:= "Blanc"; + else { dummy : String + is + dummy := "Noir"; aux := "Gris"; + if this.coul = 1 then aux := dummy; else { } + result := aux; + } + } + + def estGris() : Integer is { + "Inside Couleur::estGris".println(); + result := this.coul = 2; + } +} + +class CouleurFactory() is { + var static theBlanc, theNoir, theGris : Couleur + + def CouleurFactory() is {} + + def static init() is { + CouleurFactory.theBlanc := new Couleur(0); + CouleurFactory.theNoir := new Couleur(1); + CouleurFactory.theGris := new Couleur(2); + } + def static blanc() : Couleur := CouleurFactory.theBlanc + def static noir() : Couleur := CouleurFactory.theNoir + def static gris() : Couleur := CouleurFactory.theGris +} + +/* ci-dessous on ne met pas var devant x et y sinon ca definirait deux + * nouveaux champs qui masqueraient ceux herites de Point + */ +class PointColore(x, y:Integer, var coul: Couleur) extends Point is { + + def couleur() : Couleur := this.coul + + def colore() : Integer := this.coul.estGris() <> 0 + + def PointColore (x, y:Integer, var coul: Couleur) + : Point(x, y, "P-" & Point.howMany().toString() ) is { /* empty */ } + + /* pas PointColore: pas de covariance ! On ne peut pas reutiliser le + * clone de Point car ca nous donnerait une instance de Point. + * On n'a pas le mecanisme predefini de Java qui permet de remonter jusqu'a + * la racine de la hierarchie tout en allouant un objet de la bonne classe. + */ + def override clone() : Point /* pas PointColore. Pas de covariance ! */ + /* ci-dessous x et y sont les champs herites de Point */ + := new PointColore(this.x, this.y, this.coul) + + def estGris() : Integer := this.coul.estGris() + + def override print(verbose : Integer) is { + if verbose then "Inside PointColore::print".println(); else { } + super.print(verbose); /* usage classique de super */ + this.couleur().name(1).println(); + } +} + +class PointNoir(xc, yc:Integer) extends PointColore is { + def override estGris() : Integer := 0 + def override colore() : Integer := 1 + def override couleur() : Couleur := CouleurFactory.noir() + def PointNoir(xc, yc:Integer) + : PointColore(xc, yc, CouleurFactory.noir()) is { /* empty */ } +} + + +class DefaultPoint() extends PointColore is { + def override estGris() : Integer := 0 + def override couleur() : Couleur := CouleurFactory.blanc() + def DefaultPoint() + : PointColore(0, 0, CouleurFactory.blanc()) is { /* empty */ } +} + +class Test () is { + def static test(p: Point, p2: PointColore, p3: PointNoir) is { + c, c2, c3: String + true: Integer + is + true := 1; + p.print(true); + p2.print(true); + "Appel 1: ".println(); + if p2.colore() <> 0 then c := "colore"; else c := "gris"; + "Appel 2: ".println(); + if p3.colore() <> 0 then c2 := "colore"; else c2 := "gris"; + "Appel 3: ".println(); + if p3.colore() <> 0 then c3 := "colore"; else c3 := "gris"; + "Resultats de test: ".println(); + c.print(); " ".print(); + c2.print(); " ".print(); + c3.print(); + "".println(); /* imprime une ligne vide */ + } + + def static test2(p: PointColore) is { p.couleur().name(1).print(); } + + def Test() is {} +} + +{ /* Bloc qui correspond au programme principal */ + p1, p2, p3, clone1, clone2: Point + true, false, fv: Integer + o: PointColore + pn: PointNoir + dp: DefaultPoint + is + "Debut du programme".println(); + Point.init(); + CouleurFactory.init(); + true := 1; + false := 0; + p1 := new Point(1, 5, "p1"); + p2 := new Point(2, 3, "p2"); + p3 := new Point(0, 0, "p3"); + fv := 12; + o := new PointColore(0, 0, CouleurFactory.blanc()); + pn := new PointNoir(+1, -1); + dp := new DefaultPoint(); + p1.print(0); + p2.print(0); + p2.move(p1.getx(), p1.gety(), 0); + p2.print(0); + o.print(0); + o.setName("origine"); + o.print(true); + p2.move(p1.getx()-2*5-3, p1.gety(), 0); + p2.print(true); + + "On va essayer le clonage:".println(); + clone1 := p1.clone(); clone1.print(false); + "p1 isCloned: ".print(); + if p1.isCloned() then "OK".println(); else "KO".println(); + clone2 := clone1.clone(); clone2.move(54, 36, 0).print(false); + + "Impression de tous les clones de p1:".println(); + p1.allClones(); + "Fin de l'impression de tous les clones".println(); + + /* Ne doit pas compiler car clone() renvoie statiquement un Point alors + * que o est declare comme PointColore + * o := o.clone(); + */ + + "Valeur du compteur de nombre de points: ".println(); + Point.howMany().toString().println(); + + p1 := p1.clone().move(+2, -3, 0); + p1.print(true); + o.clone().print(true); + "test(Point, PointColore, PointNoir)".println(); + Test.test(p1, o, pn); + "test(PointNoir, PointNoir, PointNoir)".println(); + Test.test(pn, pn, pn); + p1 := pn; /* affectation entre pointeurs ! */ + Test.test2(o); + Test.test2(pn); + o := pn; /* Idem : on doit avoir de la liaison dynamique ci-dessous */ + + "test(PointNoir, PointNoir, PointNoir)".println(); + Test.test(p1, o, pn); + Test.test2(o); + Test.test2(pn); + "\nDone".println(); +} diff --git a/progs/gn.kat b/progs/gn.kat new file mode 100644 index 0000000..a53d560 --- /dev/null +++ b/progs/gn.kat @@ -0,0 +1,261 @@ +class TriNombre() is { +/* representation d'entiers POSITIFS ou NULS arbitrairement grands par tranches + * de nombres inferieurs a 1000. + * Ex: 33259 est represente par une liste a deux elements 33 et 259 + */ + var trinome:Integer + /* 'last' palie le fait qu'on n'a rien pour representer NULL */ + var last: Integer /* Par defaut, on est isole */ + var suivant: TriNombre /* valeur arbitraire si last = 1 */ + + def TriNombre () is { trinome := 0; } + + def suivant() : TriNombre := this.suivant + + def trinome() : Integer := this.trinome + + def last() : Integer := this.last + + def reset() is { + if this.last = 0 then this.suivant.reset(); else {} + this.last := 1; this.trinome := 0; + } + + def lier(triSuivant:TriNombre) : TriNombre is { + if this.last = 1 then { + this.suivant := triSuivant; this.last := 0; + } else { "Erreur dans TriNombre::lier".println(); } + result := this; + } + + def assurerCapacite(capa:Integer) : TriNombre is { + if capa <= 1 then { + } else { + if this.last = 1 then { + this.lier(new TriNombre()); + } else { } + this.suivant.assurerCapacite(capa - 1); + } + result := this; + } + + def copier(tri:TriNombre) is { + this.trinome := tri.trinome(); + if tri.last() = 0 then { + this.assurerCapacite(2); + this.suivant.copier(tri.suivant()); + } else { this.last = 1; } + } + + def affecter(nombre:Integer) : Integer is { + reste:Integer + is + reste := nombre / 1000; + this.trinome := nombre - (reste * 1000); + if reste > 0 then { + this.assurerCapacite(2); + result := this.suivant.affecter(reste) + 1; + } else { this.last = 1; result := 1; } + } + + def additionner(nombre:Integer) : Integer is { + somme:Integer + is + somme := this.trinome + nombre; + if nombre > 0 then { + if somme >= 1000 then { + div:Integer + is + div := somme / 1000; + this.trinome := somme - (div * 1000); + this.assurerCapacite(2); + result := this.suivant.additionner(div) + 1; + } else { this.trinome := somme; result := 1; } + } else result := 1; + } + + def additionnerTri(tri:TriNombre) : Integer is { + somme: Integer + nb1: Integer + nb2: Integer + is + somme := this.trinome + tri.trinome(); + if somme >= 1000 then { + this.trinome := somme - 1000; + this.assurerCapacite(2); + nb1 := this.suivant.additionner(1); + } else { this.trinome := somme; nb1 := 1; } + if this.last = 1 then { result := nb1; } + else { + this.assurerCapacite(2); + result := this.suivant.additionnerTri(tri.suivant()); + } + } + + def multiplier(nb: Integer) : Integer is { + if nb = 0 then { this.affecter(0); result := 1; + } else { + nb1: Integer + nb2: Integer + res: Integer + is + nb1 := 0; nb2 := 0; + if this.last = 0 then + nb1 := this.suivant.multiplier(nb)+1; else nb1 := 1; + this.trinome := this.trinome * nb; + if this.trinome >= 1000 then { + reste: Integer + is + reste := this.trinome / 1000; + this.trinome := this.trinome - reste * 1000; + this.assurerCapacite(2); + nb2 := this.suivant.additionner(reste) + 1; + } else { } + if nb2 > nb1 then result := nb2; else result := nb1; + } + } + + def imprimer(nb:Integer) is { + if nb >= 1 then { + if nb > 1 then { + if this.last = 0 then this.suivant.imprimer(nb - 1); else { } + " ".print(); + if this.trinome < 100 then 0.toString().print(); else { } + if this.trinome < 10 then 0.toString().print(); else { } + } else { } + this.trinome.toString().print(); + } else { } + } +} + +class GrandNombre() is { + var nombre:TriNombre + var nbTri:Integer + + def GrandNombre () is { + this.nombre := new TriNombre(); this.nbTri := 1; + } + + def nombre() : TriNombre := this.nombre + + def nbTri() : Integer := this.nbTri + + def copier(gn:GrandNombre) : GrandNombre is { + result := this; + this.nombre.reset(); + this.nombre.assurerCapacite(gn.nbTri()); + this.nombre.copier(gn.nombre()); + this.nbTri := gn.nbTri(); + } + + def init(valeur:Integer) is { + this.nombre.reset(); + this.nbTri := this.calculerNbTri(valeur); + if this.nbTri = 0 then this.nbTri := 1; else { } + this.nombre.assurerCapacite(this.nbTri); + this.nombre.affecter(valeur); + } + + def calculerNbTri(valeur:Integer) : Integer is { + if valeur > 0 then result := 1 + this.calculerNbTri(valeur/1000); + else result := 0; + } + + def additionner(nb:Integer) : Integer is { + nbTriAffecte: Integer + is + nbTriAffecte := this.nombre.additionner(nb); + if this.nbTri < nbTriAffecte then this.nbTri := nbTriAffecte; else { } + if this.nbTri = 0 then this.nbTri := 1; else { } + result := this.nbTri; + } + + def additionnerGN(gn:GrandNombre) : Integer is { + nbTriAffecte:Integer + is + nbTriAffecte := this.nombre.additionnerTri(gn.nombre()); + if this.nbTri < nbTriAffecte then this.nbTri := nbTriAffecte; else { } + if this.nbTri = 0 then this.nbTri := 1; else { } + result := this.nbTri; + } + + def multiplier(nb: Integer) : Integer is { + this.nbTri := this.nombre.multiplier(nb); + if this.nbTri = 0 then this.nbTri := 1; else { } + result := this.nbTri; + } + + /* fonction auxiliaire */ + def affecter(nb:Integer) : Integer is { + this.nbTri := this.nombre.affecter(nb); + result := this.nbTri; + } + + def imprimer() is { this.nombre.imprimer(this.nbTri); "".println(); } +} + +class Test() is { + def Test() is {} + def static test1(num: Integer, cible: Integer, res: GrandNombre) is { + if num <= cible then { + /* additionner renvoie un Integer (qu'on ignore) et modifie res */ + res.additionner(num); + Test.test1(num+1, cible, res); + } else { } + } + + def static test2(num: Integer, cible: Integer, gn: GrandNombre) is { + if num <= cible then { + num.toString().print(); "! ".print(); + /* sert juste a aligner les = dans les impressions */ + if num < 10 then " ".print(); else {} + "= ".print(); + gn.multiplier(num); gn.imprimer(); + Test.test2(num+1, cible, gn); + } else { } + } +} +{ + gn, gn2, gn3, gn4, un: GrandNombre + is + gn := new GrandNombre(); + gn2 := new GrandNombre(); + gn3 := new GrandNombre(); + gn4 := new GrandNombre(); + un := new GrandNombre(); + + "Nombre de termes pour representer ".print(); + 33259.toString().print(); " => ".print(); + gn.calculerNbTri(33259).toString().println(); + + gn.init(33259); gn.imprimer(); + /* attention a ne pas depasser la capacite d'un entier dans l'argument + * de init sinon des l'analyse lexicale on n'aura pas la bonne valeur + */ + gn.init(1123456789); gn.imprimer(); + + gn2.init(7230); gn3.init(32400); + gn2.imprimer(); gn3.imprimer(); + + gn2.additionner(32400); gn2.imprimer(); + + gn4.init(7230); gn4.additionnerGN(gn3); gn4.imprimer(); + + gn.copier(gn3); gn.imprimer(); + gn.copier(gn2).imprimer(); + + gn4.init(1); gn.copier(gn4).imprimer(); + gn.init(0); gn.imprimer(); + + + gn.init(999999); gn.additionner(1); gn.imprimer(); + + gn.init(0); + "Somme des entiers de 1 à 100:".println(); + Test.test1(1, 100, gn); + gn.imprimer(); + + un.init(1); + "Table des factorielles de 1 a 30 :".println(); + Test.test2(1, 30, un); +} diff --git a/progs/grandMere.kat b/progs/grandMere.kat new file mode 100644 index 0000000..448cdf6 --- /dev/null +++ b/progs/grandMere.kat @@ -0,0 +1,46 @@ +class A() is { + var va: Integer + def sValeur() : Integer := this.va + def A() is { + "A::(): ".print(); + this.va.toString().print(); + ", ".print(); + this.va := -12; + this.va.toString().println(); + } +} +class B() extends A is { + var vb: Integer + def B() : A() is { "B::(): ".print(); this.vb := this.va + 2; + this.vb.toString().println(); + } +} +class C(v : Integer) extends B is { + var vc: Integer + def C(v : Integer): B() is { + vc := 3 + this.va + this.vb; + "C::(): ".print(); + this.vc.toString().println(); + } +} +class D(v : Integer) extends C is + { var vd: Integer + def valeur() : Integer is { + this.va.toString().println(); + this.vb.toString().println(); + this.vc.toString().println(); + this.vd.toString().println(); + result := this.va + this.vb + this.vc + this.vd; + } + def D(v : Integer): C(12) is { + vd := this.vc + 4; + "D::(): ".print(); + this.vd.toString().println(); + } + } +{ + monD : D + is + monD := new D(5); + monD.valeur().toString().println(); +} diff --git a/progs/masking1.kat b/progs/masking1.kat new file mode 100644 index 0000000..6cf12df --- /dev/null +++ b/progs/masking1.kat @@ -0,0 +1,46 @@ +class A() is { + var v: Integer + def f() : Integer := this.v + def A() is { v := 1; } +} + +class A2() extends A is { + var v: String + def g() : String := this.v + def A2() : A() is { v := "coucou"; } +} + +class A3() extends A2 is { + var v: Integer + def h() : Integer := this.v + def override f() : Integer := this.v + def k() is { + ((A this).v).toString().println(); + ((A2 this).v).println(); + this.v.toString().println(); + } + def A3() : A2() is { v := 5; } +} +class A4() extends A3 is { + def z() : Integer := this.v + def A4() : A3() is { } +} +{ + monA3 : A3 + monA4 : A4 + monA : A + is + monA3 := new A3(); + monA4 := new A4(); + monA := new A(); + monA3.f().toString().println(); + /* le cast est une notion statique, doit donner le meme resultat + * le cast recherche une fonction f() depuis A2 et tombe sur la signature + * de f() dans A. + */ + (A monA3).f().toString().println(); + monA3.g().println(); + monA3.h().toString().println(); + monA3.k(); + monA4.z().toString().println(); +} diff --git a/test/parse.ml b/test/parse.ml index d2acbb5..bb29eac 100644 --- a/test/parse.ml +++ b/test/parse.ml @@ -39,13 +39,8 @@ let%test "wrong-decls" = x = 5; } } - |} && - expects_parse_err{| - { - - } - |} - + |} + let%test "wrong-class-decl" = expects_parse_err {| class Point() {} @@ -70,4 +65,11 @@ let%test "wrong-classbody" = { this.index := Point.incr(); this.hasClone := 0; } } {} - |} + |} && + expects_parse_err {| + class Point(x, y: Integer) is { + def static Point(var x, y: Integer, var name: String) is + { this.index := Point.incr(); this.hasClone := 0; } + } + {} + |} \ No newline at end of file diff --git a/test/utils.ml b/test/utils.ml index 70dc573..28492de 100644 --- a/test/utils.ml +++ b/test/utils.ml @@ -13,11 +13,11 @@ let parse_str str = in Parser.prog Lexer.token lexbuf let expects_err str = - try Contextual.check_all @@ parse_str str; false + try ignore @@ parse_str str; false with Failure _ -> true let expects_parse_err str = - try Contextual.check_all @@ parse_str str; false + try ignore @@ parse_str str; false with Parser.Error -> true let expects_ctx_err str =