From 528659826fff01b09e2b5e5b81f1d17003130e73 Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Tue, 5 Nov 2024 18:17:00 +0100 Subject: [PATCH 01/14] new constructions, small fixes, TODOs --- lam4-backend/gf-grammar/Lam4.gf | 73 +++++++++++++++++++++++-- lam4-backend/gf-grammar/Lam4.pgf | Bin 6108 -> 6723 bytes lam4-backend/gf-grammar/Lam4Eng.gf | 41 +++++++++++--- lam4-backend/src/Lam4/Render/Lam4Gf.hs | 30 ++++++++++ lam4-backend/src/Lam4/Render/Render.hs | 20 +++++-- 5 files changed, 149 insertions(+), 15 deletions(-) diff --git a/lam4-backend/gf-grammar/Lam4.gf b/lam4-backend/gf-grammar/Lam4.gf index d6ffd78d..132e8007 100644 --- a/lam4-backend/gf-grammar/Lam4.gf +++ b/lam4-backend/gf-grammar/Lam4.gf @@ -14,6 +14,10 @@ abstract Lam4 = { Name ; [Name]{0} ; + -- (condition, value) + -- in order to flatten nested if-then-elses into if-elif-elif-…-else + IfThen ; + [IfThen]{1} ; fun -- Placeholder, or skip some constructs? EmptyS : S ; @@ -22,6 +26,7 @@ abstract Lam4 = { EvalWhetherS, ExprS : Expr -> S ; AssignS : Name -> Expr -> S ; + AtomicConcept : Name -> S ; -- Metadata MkMetadata : String -> Metadata ; @@ -38,17 +43,71 @@ abstract Lam4 = { Lit, QuoteVar, Var : Name -> Expr ; - -- | Cons Expr Expr -- list cons - -- | List [Expr] -- construct a list - -- | ListExpr ListOp [Expr] + + -- the following correspond to List and ListExpr in Lam4 AST, + -- named differently because of a bug in GF, + -- see https://github.com/GrammaticalFramework/gf-core/issues/163 + ConjExpr : [Expr] -> Expr ; -- construct a list + -- ApplyListOp : ListOp -> [Expr] -> Expr ; + Unary : UnaryOp -> Expr -> Expr ; BinExpr : BinOp -> Expr -> Expr -> Expr ; + + -- TODO: get rid of all nested IfThenElses IfThenElse : Expr -> Expr -> Expr -> Expr ; + -- make them into Elif instead + Elif: [IfThen] -> Expr -> Expr ; + {- + + IF i's `the business's number of past and current clients` is larger than + * 10.0: => the business's client bonus factor is 1.5 + * 4.0 => the business's client bonus factor is 1.35 + * 1.0 => the business's client bonus factor is 1.2 + * ELSE => the business's client bonus factor is 1.0 + + -} + FunApp : Expr -> [Expr] -> Expr ; -- Record : (Row Expr) -> Expr ; -- record construction Project : Expr -> Name -> Expr ; -- record projection Fun : (funname : Name) -> Metadata -> (args : [Name]) -> Expr -> Expr ; -- Function - -- Let : Decl Expr + Sig : [Name] -> [Expr] -> Expr ; -- TODO: what is this? only `Sig [] []` present in royalflush data + + {- TODO: this is used in context like + + LET { foo + , bar + , baz + } + IN { expression that uses definitions + , another expression + , yet another + … } + + as AST it looks like + Let (foo + Let (bar + Let baz ))) + + transform into: + + [all variables] + + [all Exprs] + + and linearize as + -- Definitions --- + foo = … + bar = … + baz = … + + -- Expressions -- + if they are just like + `the business eligibility text` = `the business eligibility text`, + then don't print them. + -} + Let : S -> Expr -> Expr ; + Record : Name -> Expr -> Expr ; -- StatementBlock : (NonEmpty Statement) NormIsInfringed : Name -> Expr ; -- NormIsInfringed NameOfNorm. @@ -59,6 +118,12 @@ abstract Lam4 = { PredApp : Expr -> [Expr] -> Expr ; Fold : Expr -> Expr -> Expr -> Expr ; + -- When generating natural language for some file that defines a bunch of stuff like cons, map, filter, + -- apply this function instead to keep it in the AST + -- but skip linearization. + KnownFunction : Name -> Expr ; + + -- Unary and binary operators Not, Floor, diff --git a/lam4-backend/gf-grammar/Lam4.pgf b/lam4-backend/gf-grammar/Lam4.pgf index 129515e968760e684e0f86e3da0f192b9c3bebf6..058c64712c722b8eb557dc99ccba0974970172d7 100644 GIT binary patch literal 6723 zcmb^#O_$unv8r1dX})%L*Ml)&i~$>iKd~_wY=X14*UpChFkTyy5JJR^W>es#gza zdpj(9D|vAH;cj>>>XoS@@aWrvRbviVg*xLm@#EWZ8^P6nn@v2K*BCiN%5j5?5%hw%u+~o zc&w5YlyI{|PFIf|&YHJe4KuZNwe!aOQ^ImJDqk2= z{bF_2^4+y49;dVHvUb;OmYQ;HGaK=NE^Q$l_x#4Gt=;8KtT38ghs*!c*HV4$E*&Sn za@1-{isWF}&%I>g#Mu$rO4!_4YNuu^0GU19{SIY~wYz(1awa@>>U{e~QeE5m(rRl- ze>_ZPn9*4q4`&u;O`PVVbjvaJ;g0R^GLo7d-^CC@21nBZV!XoJH!8IoMhq0 zfsQeIFx75_y=2ta7mL#KgpejTqb=>Y94{?*5rL-WP&clkZ{EUls#mzHLZnjd7146f zbKX!q`q-BE;c^~b<##N4E|24Flb&$aV&FVx8I(ej1#g4}m|1YOpsre~zEliPemD%O zPJ}_|7+7#)WI#u`qP{iqG-=Uh7I{iyaGOjRf{IuM;YeiQJd7B$bnzQf^`25KLE(JNmX0Hp^TozuQryHDoC>a@SI>9kL99s-rzL4^f(BtB0nbHNgNL2xV zP#x2en3K~VJ~xI~a5N~H*5SqoGpB>kSQg-$cO>a9m6`e}h=K>DN%sP@uIrC^fM zFY(*o{h7LXU{{J`X%5#Uo+OaxL3%a7(;x^LqXa|Ej&5b5)Ic!mk`T>cz`aTmkD|om z4*jHzGS*Fhq}rkqFG(jl9iAq-SEkbpr9+8Is4Y|9tFNqp#yUa2Q}jDSzxV0)L0kHC z!|B|U%!3!zf~C6^-4A2Zt<55c^`xwg!fZT>H3vR^M9XMCS$r=sZ?+iQT582)s!w@$ z==)i_1WR|D>WNg!0o5DT>1o4~m8@WH>$xf^m42Y=>98*)l|9m>3TPZECh{Q~5Y?)M z^m@7oWq%N|7Ty~NLvpSx5z-G?h%ywKqbxA#Jzd>B}|p{BwH<|T^9j~+jw z?W3}RU8PJ5sf?g?(G21wLlPZH%}xr5*RhC_BFX_R?p;lGzKCMI3ZYg(juU5zlnGI5 zYKbQ`uRBgD_tR_l2l?)oZA5#m=A_>ynAaJMk{ue2HuT%y|3$TbRqfwghrUaa8%Km= zu{@UJIFfhbh-SYO3o(wxomjy>1{h+52`=F>uHXhQo{lS<5Kni0C`Hm)4tm?HTW$xb zY|v&Wy@m(gk?me;yJ8>Gp;+uwL5253llj zF0$96$CZ9KI84dV#x8cNC^qw6uKKZC!LXC}nRg@6?M{-g!o;C{f{96p`%9Wi?oZu41e7obpYTD+ZN9t#*33%I3WwOcul zf^!}Pw-zTeEqrr|ayG94@WniDL7*}K-^d@Lj#m;EJdr;wq0Sueq)NZ>94FrRifUh0 z?cqHArf5oCR8L~v06x9f;M?>(gD;hmay&Jiejrp+beh^~i03&&$A)?UL3-xEL%IOL zgQaW{yXKLiTV#6pYzaP4&G+!R3HPBp$+>1UI#c1@D9KQfJ*=$(Cak7PXRsz zSOvHV@Dbo4ILPTCXKsfO7T_h$_|8z8rvAO@KnoTry+k;x!5V?*H0Tld7N>av&htmY z+x&6hT_b)GN&I~Qb430T!|UAK(lY$0PcpZ)%$;JSkBgB$DMtDk^R?jT-26gNgYc<< zeKh4?^2dSCD1s68EB-j}YXS4b@&&O|2KpSuSvai5bp*VuM}9?(>>@l5HH24Lr|Stg z!axm<@`sEJFF;+uYl2Mb!!iDl&0!6i2tP*nFa7vSWho5K-KCEbHll7`!XF(H@8co7fJ=tmzRIVM#TQS8=@^Vb`icDEjHAJ&TS*Jsomq(QO Ic|yAX0|vZ%QUCw| delta 2088 zcmZWp&2Lmy6hG(Q_cgC?I_*qp3zSYNg_iPB3itu2rSt=eowh&=lDJ^(+|q&Rd&8SI zC?;lfXEY`@Z(~_h-I$oDku-6~M&m+V_z{=J7+v@exYu*vSBLs0bMNnW?m54E?#H>` zoc?X({VsKskJ}~xXC=2jGN6CE6nyJ%JsjA2bT0SkT!%g(%9XNx8}uc+=suXQ0w9ci zw;{iW{wn@$Mlo#ao>cKGtUH$R-(~p(KWei7#AftJ-|yp>672Bd1b@VDC0JJmIhz$y zU*WT5&;QuiWkv#Q)|2+FACzA)3HU^F6P(xQ6I|B^(@~sprS5pb-!!_D(LtjxNq5c| zO6+eKXA=C__^Oc}i!}5LWqazisvC1<+NqRc!l&zYj5WgJ)oM)5nU%#=VNX?RA~wlo z#W*wPxN9@D8GFU0ofnCszTk?|c=d9klahw=a?wj<$i=xMmJ_LPmDh_&ifV9-@l0Fq znD_CfHWrmu1&2~y$1=S3UEk8hJa|2n3^lRx@*&* z|6%4<3BUf5E0l#z8XW(8dy@wiLAy)SBImZ_A!m-u2VhA-Mqq@NJp+HCs^ z+iqG^btSRVM^|jVik82g?V;^YTpa+=Q$bi zeXhUXYK_FA8b*{wk9*_u#>0MZ$EijtE_UoOCLFsa&ypFqjnUl3dWh$WYa;duaO4wU z-ONaxtIn&752|8PELU*gf0l#VWchx%B(Sk7x^D>dnBczfx?%4V7Y*~_6+={~D~{u0 zUr=;7EXxh|1nusi?T(5LF$QW36n0VIF?P|zuBK9K;Qsa*+Y`5iyXZ{2#bvMT*p$nx zz@xG}5$UbLPPI_B>ox2!3wH~`E0&605iPB7SFRYXRN*cyH&|+>3Ad#Kd$JAfJ9w7V zrjyYV#1b;vOpZ5`5v|~q>JlvQblF^@xY-b+|q;xQN%Y3Kwv2rvk6 z3g9%rGXQ4*&H_vUOaoj5coAS0a2M?5RC!3hqde#kjwxV4JE%mDhfpIp5<;Ee2`X(W z?@`%tI4L^?o{GbtZ6L+Z$fgiF&V`Qiq2t1~{FQC_tK0I|q@M+gvboNnjo3?s8A3Nb zGO#ZYRT%V!viU$(Mc54*LLY;M1**=>A z_?Nzhh45Si(+WJ#z@*R@7_?9~#sg--c^+`9Rf8@mjc^EHNN(U^*$g90AS@wdG75}` oK?Yn1K?)|qXagogkZMz*2jB?6(*TzNZa_Ojlb+)0?q4wb9}!Ri6#xJL diff --git a/lam4-backend/gf-grammar/Lam4Eng.gf b/lam4-backend/gf-grammar/Lam4Eng.gf index be55e24e..2e016d64 100644 --- a/lam4-backend/gf-grammar/Lam4Eng.gf +++ b/lam4-backend/gf-grammar/Lam4Eng.gf @@ -53,6 +53,7 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { EvalS expr = {s = "evaluate" ++ expr.s} ; EvalWhetherS expr = {s = "evaluate whether" ++ expr.s} ; AssignS name expr = {s = quote name.s ++ "is assigned the value" ++ quote expr.s} ; + AtomicConcept name = {s = name.s ++ "is an atomic concept."} ; -- Metadata MkMetadata str = str ** {isEmpty = NonEmpty} ; @@ -85,11 +86,16 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { oper bullet = "*" ; -- just ad hoc characters to `tr "°∞" "\t\n"` in shell - tab = "°" ; + tab = "°°" ; + space = "°" ; linebreak = "∞" ; + indent1, indent2 : Str -> Str ; + indent1 str = linebreak ++ space ++ str ; + indent2 str = linebreak ++ tab ++ str ; + quote : Str -> Str ; - quote str = "‘" ++ BIND ++ str ++ BIND ++ "’" ; + quote str = "[" ++ BIND ++ str ++ BIND ++ "]" ; artIndef = pre { @@ -99,6 +105,11 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { _ => "A" } ; + conjXss = overload { + conjXss : ListX0 -> SS = \xs -> ss (conjX "" xs) ; + conjXss : Str -> ListX0 -> SS = \c,xs -> ss (conjX c xs) + } ; + conjX : Str -> ListX0 -> Str = \conj,xs -> case xs.size of { Many => conjunctX (ss conj) xs ; _ => xs.s2 @@ -127,9 +138,9 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { BinExpr op e1 e2 = cc3 e1 op e2 ; IfThenElse if then else = { - s = "if" ++ if.s ++ linebreak ++ tab - ++ "then" ++ then.s ++ linebreak ++ tab - ++ "else" ++ else.s + s = "if" ++ if.s + ++ indent2 "then" ++ then.s + ++ indent2 "else" ++ else.s } ; -- : Expr -> [Expr] -> Expr ; @@ -142,9 +153,18 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { -- : Name -> Metadata -> [Name] -> Expr -> Expr ; -- Function Fun funname md args body = { s = "Function" ++ funname.s ++ ":" ++ linebreak - ++ linArgs "given" args "," - ++ "return" ++ body.s + ++ linArgs "given" args ", return" + ++ indent1 body.s } ; + + -- : S -> Expr -> Expr ; + Let decl expr = { + s = decl.s ++ linebreak ++ expr.s + } ; + + -- : Name -> Expr -> Expr ; + Record name field = {s = glue name.s "'s" ++ field.s} ; + Sig parents relations = cc2 (conjXss parents) (conjXss relations) ; -- Let : Decl Expr -- StatementBlock : (NonEmpty Statement) @@ -171,6 +191,12 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { ++ "starting from" ++ nil.s } ; + -- When generating natural language for some file that defines a bunch of stuff like cons, map, filter, + -- apply this function instead to keep it in the AST + -- but skip linearization. + -- : Name -> Expr + KnownFunction _ = {s = ""} ; + -- Unary and binary operators Not = ss "not" ; Floor = ss "floor of" ; @@ -194,6 +220,7 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { BaseExpr, BaseName = baseListX0 ; ConsExpr, ConsName = consListX0 ; + ConjExpr = conjXss ; } {- diff --git a/lam4-backend/src/Lam4/Render/Lam4Gf.hs b/lam4-backend/src/Lam4/Render/Lam4Gf.hs index d5b5e94b..b39a7e52 100644 --- a/lam4-backend/src/Lam4/Render/Lam4Gf.hs +++ b/lam4-backend/src/Lam4/Render/Lam4Gf.hs @@ -84,16 +84,21 @@ data Tree :: * -> * where GOr :: Tree GBinOp_ GPlus :: Tree GBinOp_ GBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ + GConjExpr :: GListExpr -> Tree GExpr_ GFold :: GExpr -> GExpr -> GExpr -> Tree GExpr_ GFun :: GName -> GMetadata -> GListName -> GExpr -> Tree GExpr_ GFunApp :: GExpr -> GListExpr -> Tree GExpr_ GIfThenElse :: GExpr -> GExpr -> GExpr -> Tree GExpr_ + GKnownFunction :: GName -> Tree GExpr_ + GLet :: GS -> GExpr -> Tree GExpr_ GLit :: GName -> Tree GExpr_ GNormIsInfringed :: GName -> Tree GExpr_ GPredApp :: GExpr -> GListExpr -> Tree GExpr_ GPredicate :: GName -> GMetadata -> GListName -> GExpr -> Tree GExpr_ GProject :: GExpr -> GName -> Tree GExpr_ GQuoteVar :: GName -> Tree GExpr_ + GRecord :: GName -> GExpr -> Tree GExpr_ + GSig :: GListName -> GListExpr -> Tree GExpr_ GUnary :: GUnaryOp -> GExpr -> Tree GExpr_ GVar :: GName -> Tree GExpr_ GListExpr :: [GExpr] -> Tree GListExpr_ @@ -105,6 +110,7 @@ data Tree :: * -> * where GMkRowDecl :: GMetadata -> GName -> Tree GRowTypeDecl_ GMkRowTypeDecl :: GMetadata -> GName -> GName -> Tree GRowTypeDecl_ GAssignS :: GName -> GExpr -> Tree GS_ + GAtomicConcept :: GName -> Tree GS_ GEmptyS :: Tree GS_ GEvalS :: GExpr -> Tree GS_ GEvalWhetherS :: GExpr -> Tree GS_ @@ -136,16 +142,21 @@ instance Eq (Tree a) where (GOr,GOr) -> and [ ] (GPlus,GPlus) -> and [ ] (GBinExpr x1 x2 x3,GBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] + (GConjExpr x1,GConjExpr y1) -> and [ x1 == y1 ] (GFold x1 x2 x3,GFold y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GFun x1 x2 x3 x4,GFun y1 y2 y3 y4) -> and [ x1 == y1 , x2 == y2 , x3 == y3 , x4 == y4 ] (GFunApp x1 x2,GFunApp y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GIfThenElse x1 x2 x3,GIfThenElse y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] + (GKnownFunction x1,GKnownFunction y1) -> and [ x1 == y1 ] + (GLet x1 x2,GLet y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GLit x1,GLit y1) -> and [ x1 == y1 ] (GNormIsInfringed x1,GNormIsInfringed y1) -> and [ x1 == y1 ] (GPredApp x1 x2,GPredApp y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GPredicate x1 x2 x3 x4,GPredicate y1 y2 y3 y4) -> and [ x1 == y1 , x2 == y2 , x3 == y3 , x4 == y4 ] (GProject x1 x2,GProject y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GQuoteVar x1,GQuoteVar y1) -> and [ x1 == y1 ] + (GRecord x1 x2,GRecord y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GSig x1 x2,GSig y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GUnary x1 x2,GUnary y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GVar x1,GVar y1) -> and [ x1 == y1 ] (GListExpr x1,GListExpr y1) -> and [x == y | (x,y) <- zip x1 y1] @@ -157,6 +168,7 @@ instance Eq (Tree a) where (GMkRowDecl x1 x2,GMkRowDecl y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GMkRowTypeDecl x1 x2 x3,GMkRowTypeDecl y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GAssignS x1 x2,GAssignS y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GAtomicConcept x1,GAtomicConcept y1) -> and [ x1 == y1 ] (GEmptyS,GEmptyS) -> and [ ] (GEvalS x1,GEvalS y1) -> and [ x1 == y1 ] (GEvalWhetherS x1,GEvalWhetherS y1) -> and [ x1 == y1 ] @@ -209,32 +221,42 @@ instance Gf GBinOp where instance Gf GExpr where gf (GBinExpr x1 x2 x3) = mkApp (mkCId "BinExpr") [gf x1, gf x2, gf x3] + gf (GConjExpr x1) = mkApp (mkCId "ConjExpr") [gf x1] gf (GFold x1 x2 x3) = mkApp (mkCId "Fold") [gf x1, gf x2, gf x3] gf (GFun x1 x2 x3 x4) = mkApp (mkCId "Fun") [gf x1, gf x2, gf x3, gf x4] gf (GFunApp x1 x2) = mkApp (mkCId "FunApp") [gf x1, gf x2] gf (GIfThenElse x1 x2 x3) = mkApp (mkCId "IfThenElse") [gf x1, gf x2, gf x3] + gf (GKnownFunction x1) = mkApp (mkCId "KnownFunction") [gf x1] + gf (GLet x1 x2) = mkApp (mkCId "Let") [gf x1, gf x2] gf (GLit x1) = mkApp (mkCId "Lit") [gf x1] gf (GNormIsInfringed x1) = mkApp (mkCId "NormIsInfringed") [gf x1] gf (GPredApp x1 x2) = mkApp (mkCId "PredApp") [gf x1, gf x2] gf (GPredicate x1 x2 x3 x4) = mkApp (mkCId "Predicate") [gf x1, gf x2, gf x3, gf x4] gf (GProject x1 x2) = mkApp (mkCId "Project") [gf x1, gf x2] gf (GQuoteVar x1) = mkApp (mkCId "QuoteVar") [gf x1] + gf (GRecord x1 x2) = mkApp (mkCId "Record") [gf x1, gf x2] + gf (GSig x1 x2) = mkApp (mkCId "Sig") [gf x1, gf x2] gf (GUnary x1 x2) = mkApp (mkCId "Unary") [gf x1, gf x2] gf (GVar x1) = mkApp (mkCId "Var") [gf x1] fg t = case unApp t of Just (i,[x1,x2,x3]) | i == mkCId "BinExpr" -> GBinExpr (fg x1) (fg x2) (fg x3) + Just (i,[x1]) | i == mkCId "ConjExpr" -> GConjExpr (fg x1) Just (i,[x1,x2,x3]) | i == mkCId "Fold" -> GFold (fg x1) (fg x2) (fg x3) Just (i,[x1,x2,x3,x4]) | i == mkCId "Fun" -> GFun (fg x1) (fg x2) (fg x3) (fg x4) Just (i,[x1,x2]) | i == mkCId "FunApp" -> GFunApp (fg x1) (fg x2) Just (i,[x1,x2,x3]) | i == mkCId "IfThenElse" -> GIfThenElse (fg x1) (fg x2) (fg x3) + Just (i,[x1]) | i == mkCId "KnownFunction" -> GKnownFunction (fg x1) + Just (i,[x1,x2]) | i == mkCId "Let" -> GLet (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "Lit" -> GLit (fg x1) Just (i,[x1]) | i == mkCId "NormIsInfringed" -> GNormIsInfringed (fg x1) Just (i,[x1,x2]) | i == mkCId "PredApp" -> GPredApp (fg x1) (fg x2) Just (i,[x1,x2,x3,x4]) | i == mkCId "Predicate" -> GPredicate (fg x1) (fg x2) (fg x3) (fg x4) Just (i,[x1,x2]) | i == mkCId "Project" -> GProject (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "QuoteVar" -> GQuoteVar (fg x1) + Just (i,[x1,x2]) | i == mkCId "Record" -> GRecord (fg x1) (fg x2) + Just (i,[x1,x2]) | i == mkCId "Sig" -> GSig (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "Unary" -> GUnary (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "Var" -> GVar (fg x1) @@ -313,6 +335,7 @@ instance Gf GRowTypeDecl where instance Gf GS where gf (GAssignS x1 x2) = mkApp (mkCId "AssignS") [gf x1, gf x2] + gf (GAtomicConcept x1) = mkApp (mkCId "AtomicConcept") [gf x1] gf GEmptyS = mkApp (mkCId "EmptyS") [] gf (GEvalS x1) = mkApp (mkCId "EvalS") [gf x1] gf (GEvalWhetherS x1) = mkApp (mkCId "EvalWhetherS") [gf x1] @@ -322,6 +345,7 @@ instance Gf GS where fg t = case unApp t of Just (i,[x1,x2]) | i == mkCId "AssignS" -> GAssignS (fg x1) (fg x2) + Just (i,[x1]) | i == mkCId "AtomicConcept" -> GAtomicConcept (fg x1) Just (i,[]) | i == mkCId "EmptyS" -> GEmptyS Just (i,[x1]) | i == mkCId "EvalS" -> GEvalS (fg x1) Just (i,[x1]) | i == mkCId "EvalWhetherS" -> GEvalWhetherS (fg x1) @@ -363,16 +387,21 @@ instance Gf GUnaryOp where instance Compos Tree where compos r a f t = case t of GBinExpr x1 x2 x3 -> r GBinExpr `a` f x1 `a` f x2 `a` f x3 + GConjExpr x1 -> r GConjExpr `a` f x1 GFold x1 x2 x3 -> r GFold `a` f x1 `a` f x2 `a` f x3 GFun x1 x2 x3 x4 -> r GFun `a` f x1 `a` f x2 `a` f x3 `a` f x4 GFunApp x1 x2 -> r GFunApp `a` f x1 `a` f x2 GIfThenElse x1 x2 x3 -> r GIfThenElse `a` f x1 `a` f x2 `a` f x3 + GKnownFunction x1 -> r GKnownFunction `a` f x1 + GLet x1 x2 -> r GLet `a` f x1 `a` f x2 GLit x1 -> r GLit `a` f x1 GNormIsInfringed x1 -> r GNormIsInfringed `a` f x1 GPredApp x1 x2 -> r GPredApp `a` f x1 `a` f x2 GPredicate x1 x2 x3 x4 -> r GPredicate `a` f x1 `a` f x2 `a` f x3 `a` f x4 GProject x1 x2 -> r GProject `a` f x1 `a` f x2 GQuoteVar x1 -> r GQuoteVar `a` f x1 + GRecord x1 x2 -> r GRecord `a` f x1 `a` f x2 + GSig x1 x2 -> r GSig `a` f x1 `a` f x2 GUnary x1 x2 -> r GUnary `a` f x1 `a` f x2 GVar x1 -> r GVar `a` f x1 GMkMetadata x1 -> r GMkMetadata `a` f x1 @@ -380,6 +409,7 @@ instance Compos Tree where GMkRowDecl x1 x2 -> r GMkRowDecl `a` f x1 `a` f x2 GMkRowTypeDecl x1 x2 x3 -> r GMkRowTypeDecl `a` f x1 `a` f x2 `a` f x3 GAssignS x1 x2 -> r GAssignS `a` f x1 `a` f x2 + GAtomicConcept x1 -> r GAtomicConcept `a` f x1 GEvalS x1 -> r GEvalS `a` f x1 GEvalWhetherS x1 -> r GEvalWhetherS `a` f x1 GExprS x1 -> r GExprS `a` f x1 diff --git a/lam4-backend/src/Lam4/Render/Render.hs b/lam4-backend/src/Lam4/Render/Render.hs index 81a1f8d9..47698a6d 100644 --- a/lam4-backend/src/Lam4/Render/Render.hs +++ b/lam4-backend/src/Lam4/Render/Render.hs @@ -49,7 +49,7 @@ makeNLGEnv config = do gr <- PGF.readPGF grammarFile -- Set up PGF Language and GF Linearizer - let lang = initializeGFLang config.concreteSyntaxName gr + let lang = initializeGFLang config.concreteSyntaxName gr linearizer = makeGFLinearizer gr lang pure $ NLGEnv linearizer @@ -90,7 +90,11 @@ renderCstDeclToNL env = gfLin env . gf . parseDecl parseDecl :: Decl -> GS parseDecl = \case DataDecl name typedecl -> GTypeDeclS $ parseTypeDecl name typedecl - Rec name expr -> GExprS $ parseExpr name expr + Rec name expr -> + if commonFunction name.name + then GExprS $ GKnownFunction $ parseName name + else GExprS $ parseExpr name expr + NonRec name (Sig [] []) -> GAtomicConcept (parseName name) NonRec name expr -> GAssignS (parseName name) $ parseExpr noName expr Eval expr -> quoteVars $ if isBool expr then GEvalWhetherS $ parseExpr noName expr @@ -102,6 +106,9 @@ noName = N.MkName mempty Nothing N.NotEntrypoint parseName :: N.Name -> GName parseName = GMkName . GString . T.unpack . N.name +commonFunction :: T.Text -> Bool +commonFunction x = T.unpack x `elem` ["id", "map", "filter", "cons", "nil", "minus", "plus", "div", "mult", "add", "modulo", "pow", "round", "certain", "uncertain", "known", "unknown"] + quoteVars :: Tree a -> Tree a quoteVars (GVar x) = GQuoteVar x quoteVars x = composOp quoteVars x @@ -171,11 +178,16 @@ parseExpr name = PredApp predicate args -> GPredApp (f predicate) (GListExpr $ fmap f args) Foldr combine nil over -> GFold (f combine) (f nil) (f over) Foldl combine nil over -> GFold (f combine) (f nil) (f over) --- Sig parents relations -> Sig parents (traverse f) (tions + Sig parents relations -> GSig (GListName $ fmap parseName parents) (GListExpr $ fmap f relations) + Let decl expr -> GLet (parseDecl decl) (f expr) + Cons e1 e2 -> GConjExpr (GListExpr [f e1, f e2]) + List es -> GConjExpr (GListExpr $ fmap f es) + Record rows -> GConjExpr (GListExpr $ fmap parseRecordRow rows) --) StatementBlock statements -> undefined -- TODO x -> error [i|parseExpr: not yet implemented #{x}|] - +parseRecordRow :: (N.Name, Expr) -> GExpr +parseRecordRow (name, expr) = GRecord (parseName name) (parseExpr name expr) parseTypeDecl :: N.Name -> DataDecl -> GTypeDecl parseTypeDecl name typedecl = From 8834d3d173fff2c4520860256e3f9d86d370a620 Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Wed, 6 Nov 2024 11:38:06 +0100 Subject: [PATCH 02/14] separate "is calculated as" and "is true if" --- lam4-backend/gf-grammar/Lam4.gf | 1 + lam4-backend/gf-grammar/Lam4.pgf | Bin 6723 -> 7216 bytes lam4-backend/gf-grammar/Lam4Eng.gf | 7 +++-- lam4-backend/src/Lam4/Render/Lam4Gf.hs | 37 +++++++++++++++++++++++++ lam4-backend/src/Lam4/Render/Render.hs | 30 +++++++++++++++++--- 5 files changed, 69 insertions(+), 6 deletions(-) diff --git a/lam4-backend/gf-grammar/Lam4.gf b/lam4-backend/gf-grammar/Lam4.gf index 132e8007..9611f7c9 100644 --- a/lam4-backend/gf-grammar/Lam4.gf +++ b/lam4-backend/gf-grammar/Lam4.gf @@ -26,6 +26,7 @@ abstract Lam4 = { EvalWhetherS, ExprS : Expr -> S ; AssignS : Name -> Expr -> S ; + LetIsTrue : Name -> Expr -> S ; AtomicConcept : Name -> S ; -- Metadata diff --git a/lam4-backend/gf-grammar/Lam4.pgf b/lam4-backend/gf-grammar/Lam4.pgf index 058c64712c722b8eb557dc99ccba0974970172d7..c8e76f47700571dbc060c4a08e29e281ff5e4756 100644 GIT binary patch literal 7216 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 Apa1{> delta 2218 zcmZWq-EY%Y6hG(Mj_t(xXybeoLR+9fDU^=_(JWiXohdu3Ke+Am!rfE-`*v_@%+h}vFbAP|%^KtLF=iYpM z;>V*O=kWM?{O|>QPuj-<}Q`#PZSG7U2yS~U}tLn6B3~(7_Z%7kSz3;Sr!r^yKl*h~Kqe6d9 zKdE&CCA<&y7oGm8E>+LijoEjbt&nRoPUAtZLY{N#weYJnx7G-8gz$8;8PaI+-j(}S zW47M5LRI`?!+Fvmv#M)5!cUsF+)ijB&D(B>lM7C3wb(8;?zQa3iY1b&OD(I`lS${? zu2x);h%B53R#imOF0DDPb*&;+)vaEbNg62ID)tSJ_+k@H@2_-W!i;s5d>V+!E}OU8F4r*A{IAMeH`Ao{zA(oq z#xK77+Z-ZX$m}3FmEm|fQy}@w*F4W;V|&8-;coBy%uK9Low006wt}NxB0Jvc=WW;a zQyKwYsH|Eng}&a$*rPZ4lidEY^CT=79{Qi=aOAB0*sfW)t-CDKb;oJpe!uZ?g10>G@a1-24tp=NL+NAeoQp#}O^@T=KyLKRQQqDd<$aCF z=3N|AN_JzdjfH6GVaakUwTfFoGg5lUSB0itdPvLQdycsPd(U&(8*yJPR=0(m1v$}6 zPWFKXFqfvF_+r_k)9?}!pZ>P|&QML{)! zs*0+Hx{i7jV=;^w7>{Ezfqh9#r!Zqe9I^nT0Am1?0LKAN1H1t+1#ki2B0y&zUV2993?lTw5P}Q``3d2_Loyi94+_D<0gMow2%t*v2wkGU;3yv?IK~GVPK55K zklbHmkRbKz94~NjnL&p;l>?_Mfz#E^RM$3BUEfUg7Pm9t1{XIO34~h=(lqC{`5?n> z1}d?4_#nd_1}QSROXdt=03?KA9)ZaWws(TmJN(oN!WM`i?BqcemB9!H5!l5Csxxc_ zoxyHKRn=e*AE@k5f*8V^2>;O2F%YJ^FfPLx22paIVGyI?tmHETW+k5+2^BiIU;%l) zn7sh|c(M0$G0w#@LNY1CT;Qp}xd7;JJ_w;fF#vi>fo%W>08Rod0#u-nAw#L3A$3NY zx&|W&#lNL!kFhNWcN2P7w`Mw0vEjbrv-bsk)x=#TGuA%L+7rHpA1*3Oph Str ; quote str = "[" ++ BIND ++ str ++ BIND ++ "]" ; + quoteSS : SS -> SS ; + quoteSS ss = {s = quote ss.s} ; artIndef = pre { "eu" | "Eu" | "uni" | "Uni" => "A" ; @@ -135,7 +138,7 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { Var name = name ; Lit name = name ; Unary op expr = cc2 op expr ; - BinExpr op e1 e2 = cc3 e1 op e2 ; + BinExpr op e1 e2 = cc3 (quoteSS e1) op (quoteSS e2) ; IfThenElse if then else = { s = "if" ++ if.s diff --git a/lam4-backend/src/Lam4/Render/Lam4Gf.hs b/lam4-backend/src/Lam4/Render/Lam4Gf.hs index b39a7e52..1c02bee2 100644 --- a/lam4-backend/src/Lam4/Render/Lam4Gf.hs +++ b/lam4-backend/src/Lam4/Render/Lam4Gf.hs @@ -46,6 +46,8 @@ type GExpr = Tree GExpr_ data GExpr_ type GListExpr = Tree GListExpr_ data GListExpr_ +type GListIfThen = Tree GListIfThen_ +data GListIfThen_ type GListName = Tree GListName_ data GListName_ type GListRowTypeDecl = Tree GListRowTypeDecl_ @@ -62,6 +64,8 @@ type GTypeDecl = Tree GTypeDecl_ data GTypeDecl_ type GUnaryOp = Tree GUnaryOp_ data GUnaryOp_ +type GIfThen = Tree GIfThen_ +data GIfThen_ type GString = Tree GString_ data GString_ type GInt = Tree GInt_ @@ -85,6 +89,7 @@ data Tree :: * -> * where GPlus :: Tree GBinOp_ GBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ GConjExpr :: GListExpr -> Tree GExpr_ + GElif :: GListIfThen -> GExpr -> Tree GExpr_ GFold :: GExpr -> GExpr -> GExpr -> Tree GExpr_ GFun :: GName -> GMetadata -> GListName -> GExpr -> Tree GExpr_ GFunApp :: GExpr -> GListExpr -> Tree GExpr_ @@ -102,6 +107,7 @@ data Tree :: * -> * where GUnary :: GUnaryOp -> GExpr -> Tree GExpr_ GVar :: GName -> Tree GExpr_ GListExpr :: [GExpr] -> Tree GListExpr_ + GListIfThen :: [GIfThen] -> Tree GListIfThen_ GListName :: [GName] -> Tree GListName_ GListRowTypeDecl :: [GRowTypeDecl] -> Tree GListRowTypeDecl_ GMkMetadata :: GString -> Tree GMetadata_ @@ -115,6 +121,7 @@ data Tree :: * -> * where GEvalS :: GExpr -> Tree GS_ GEvalWhetherS :: GExpr -> Tree GS_ GExprS :: GExpr -> Tree GS_ + GLetIsTrue :: GName -> GExpr -> Tree GS_ GTypeDeclS :: GTypeDecl -> Tree GS_ GMkTypeDecl :: GMetadata -> GName -> GListRowTypeDecl -> Tree GTypeDecl_ GCeiling :: Tree GUnaryOp_ @@ -143,6 +150,7 @@ instance Eq (Tree a) where (GPlus,GPlus) -> and [ ] (GBinExpr x1 x2 x3,GBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GConjExpr x1,GConjExpr y1) -> and [ x1 == y1 ] + (GElif x1 x2,GElif y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GFold x1 x2 x3,GFold y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GFun x1 x2 x3 x4,GFun y1 y2 y3 y4) -> and [ x1 == y1 , x2 == y2 , x3 == y3 , x4 == y4 ] (GFunApp x1 x2,GFunApp y1 y2) -> and [ x1 == y1 , x2 == y2 ] @@ -160,6 +168,7 @@ instance Eq (Tree a) where (GUnary x1 x2,GUnary y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GVar x1,GVar y1) -> and [ x1 == y1 ] (GListExpr x1,GListExpr y1) -> and [x == y | (x,y) <- zip x1 y1] + (GListIfThen x1,GListIfThen y1) -> and [x == y | (x,y) <- zip x1 y1] (GListName x1,GListName y1) -> and [x == y | (x,y) <- zip x1 y1] (GListRowTypeDecl x1,GListRowTypeDecl y1) -> and [x == y | (x,y) <- zip x1 y1] (GMkMetadata x1,GMkMetadata y1) -> and [ x1 == y1 ] @@ -173,6 +182,7 @@ instance Eq (Tree a) where (GEvalS x1,GEvalS y1) -> and [ x1 == y1 ] (GEvalWhetherS x1,GEvalWhetherS y1) -> and [ x1 == y1 ] (GExprS x1,GExprS y1) -> and [ x1 == y1 ] + (GLetIsTrue x1 x2,GLetIsTrue y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GTypeDeclS x1,GTypeDeclS y1) -> and [ x1 == y1 ] (GMkTypeDecl x1 x2 x3,GMkTypeDecl y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GCeiling,GCeiling) -> and [ ] @@ -222,6 +232,7 @@ instance Gf GBinOp where instance Gf GExpr where gf (GBinExpr x1 x2 x3) = mkApp (mkCId "BinExpr") [gf x1, gf x2, gf x3] gf (GConjExpr x1) = mkApp (mkCId "ConjExpr") [gf x1] + gf (GElif x1 x2) = mkApp (mkCId "Elif") [gf x1, gf x2] gf (GFold x1 x2 x3) = mkApp (mkCId "Fold") [gf x1, gf x2, gf x3] gf (GFun x1 x2 x3 x4) = mkApp (mkCId "Fun") [gf x1, gf x2, gf x3, gf x4] gf (GFunApp x1 x2) = mkApp (mkCId "FunApp") [gf x1, gf x2] @@ -243,6 +254,7 @@ instance Gf GExpr where case unApp t of Just (i,[x1,x2,x3]) | i == mkCId "BinExpr" -> GBinExpr (fg x1) (fg x2) (fg x3) Just (i,[x1]) | i == mkCId "ConjExpr" -> GConjExpr (fg x1) + Just (i,[x1,x2]) | i == mkCId "Elif" -> GElif (fg x1) (fg x2) Just (i,[x1,x2,x3]) | i == mkCId "Fold" -> GFold (fg x1) (fg x2) (fg x3) Just (i,[x1,x2,x3,x4]) | i == mkCId "Fun" -> GFun (fg x1) (fg x2) (fg x3) (fg x4) Just (i,[x1,x2]) | i == mkCId "FunApp" -> GFunApp (fg x1) (fg x2) @@ -275,6 +287,18 @@ instance Gf GListExpr where _ -> error ("no ListExpr " ++ show t) +instance Gf GListIfThen where + gf (GListIfThen [x1]) = mkApp (mkCId "BaseIfThen") [gf x1] + gf (GListIfThen (x:xs)) = mkApp (mkCId "ConsIfThen") [gf x, gf (GListIfThen xs)] + fg t = + GListIfThen (fgs t) where + fgs t = case unApp t of + Just (i,[x1]) | i == mkCId "BaseIfThen" -> [fg x1] + Just (i,[x1,x2]) | i == mkCId "ConsIfThen" -> fg x1 : fgs x2 + + + _ -> error ("no ListIfThen " ++ show t) + instance Gf GListName where gf (GListName []) = mkApp (mkCId "BaseName") [] gf (GListName (x:xs)) = mkApp (mkCId "ConsName") [gf x, gf (GListName xs)] @@ -340,6 +364,7 @@ instance Gf GS where gf (GEvalS x1) = mkApp (mkCId "EvalS") [gf x1] gf (GEvalWhetherS x1) = mkApp (mkCId "EvalWhetherS") [gf x1] gf (GExprS x1) = mkApp (mkCId "ExprS") [gf x1] + gf (GLetIsTrue x1 x2) = mkApp (mkCId "LetIsTrue") [gf x1, gf x2] gf (GTypeDeclS x1) = mkApp (mkCId "TypeDeclS") [gf x1] fg t = @@ -350,6 +375,7 @@ instance Gf GS where Just (i,[x1]) | i == mkCId "EvalS" -> GEvalS (fg x1) Just (i,[x1]) | i == mkCId "EvalWhetherS" -> GEvalWhetherS (fg x1) Just (i,[x1]) | i == mkCId "ExprS" -> GExprS (fg x1) + Just (i,[x1,x2]) | i == mkCId "LetIsTrue" -> GLetIsTrue (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "TypeDeclS" -> GTypeDeclS (fg x1) @@ -384,10 +410,19 @@ instance Gf GUnaryOp where _ -> error ("no UnaryOp " ++ show t) + +instance Gf GIfThen where + gf _ = undefined + fg _ = undefined + + + + instance Compos Tree where compos r a f t = case t of GBinExpr x1 x2 x3 -> r GBinExpr `a` f x1 `a` f x2 `a` f x3 GConjExpr x1 -> r GConjExpr `a` f x1 + GElif x1 x2 -> r GElif `a` f x1 `a` f x2 GFold x1 x2 x3 -> r GFold `a` f x1 `a` f x2 `a` f x3 GFun x1 x2 x3 x4 -> r GFun `a` f x1 `a` f x2 `a` f x3 `a` f x4 GFunApp x1 x2 -> r GFunApp `a` f x1 `a` f x2 @@ -413,9 +448,11 @@ instance Compos Tree where GEvalS x1 -> r GEvalS `a` f x1 GEvalWhetherS x1 -> r GEvalWhetherS `a` f x1 GExprS x1 -> r GExprS `a` f x1 + GLetIsTrue x1 x2 -> r GLetIsTrue `a` f x1 `a` f x2 GTypeDeclS x1 -> r GTypeDeclS `a` f x1 GMkTypeDecl x1 x2 x3 -> r GMkTypeDecl `a` f x1 `a` f x2 `a` f x3 GListExpr x1 -> r GListExpr `a` foldr (a . a (r (:)) . f) (r []) x1 + GListIfThen x1 -> r GListIfThen `a` foldr (a . a (r (:)) . f) (r []) x1 GListName x1 -> r GListName `a` foldr (a . a (r (:)) . f) (r []) x1 GListRowTypeDecl x1 -> r GListRowTypeDecl `a` foldr (a . a (r (:)) . f) (r []) x1 _ -> r t diff --git a/lam4-backend/src/Lam4/Render/Render.hs b/lam4-backend/src/Lam4/Render/Render.hs index 47698a6d..8de43bc7 100644 --- a/lam4-backend/src/Lam4/Render/Render.hs +++ b/lam4-backend/src/Lam4/Render/Render.hs @@ -32,8 +32,9 @@ data NLGConfig = MkNLGConfig { -- Loosely copied from dsl/…/natural4 -- | Env that's needed for NLG operations -newtype NLGEnv = NLGEnv +data NLGEnv = NLGEnv { gfLin :: GFLinearizer + , gfTree :: GFLinearizer } gfPath :: String -> String @@ -51,7 +52,8 @@ makeNLGEnv config = do -- Set up PGF Language and GF Linearizer let lang = initializeGFLang config.concreteSyntaxName gr linearizer = makeGFLinearizer gr lang - pure $ NLGEnv linearizer + printTree = T.pack . PGF.showExpr [] + pure $ NLGEnv linearizer printTree makeGFLinearizer :: PGF.PGF -> PGF.Language -> GFLinearizer makeGFLinearizer gr lang = postprocessText . T.pack . PGF.linearize gr lang @@ -82,11 +84,15 @@ postprocessText = newlines . tabs . rmBIND -- | Entrypoint renderCstProgramToNL :: NLGEnv -> CSTProgram -> T.Text -renderCstProgramToNL env = T.unlines . fmap (renderCstDeclToNL env) +renderCstProgramToNL env decls = T.unlines $ + fmap (renderCstDeclToNL env) decls <> fmap (renderCstDeclToGFtrees env) decls renderCstDeclToNL :: NLGEnv -> Decl -> T.Text renderCstDeclToNL env = gfLin env . gf . parseDecl +renderCstDeclToGFtrees :: NLGEnv -> Decl -> T.Text +renderCstDeclToGFtrees env = gfTree env . gf . parseDecl + parseDecl :: Decl -> GS parseDecl = \case DataDecl name typedecl -> GTypeDeclS $ parseTypeDecl name typedecl @@ -95,6 +101,10 @@ parseDecl = \case then GExprS $ GKnownFunction $ parseName name else GExprS $ parseExpr name expr NonRec name (Sig [] []) -> GAtomicConcept (parseName name) + NonRec name expr@(BinExpr binop _ _) -> + if comparisonOp binop + then GLetIsTrue (parseName name) $ parseExpr noName expr + else GAssignS (parseName name) $ parseExpr noName expr NonRec name expr -> GAssignS (parseName name) $ parseExpr noName expr Eval expr -> quoteVars $ if isBool expr then GEvalWhetherS $ parseExpr noName expr @@ -106,9 +116,18 @@ noName = N.MkName mempty Nothing N.NotEntrypoint parseName :: N.Name -> GName parseName = GMkName . GString . T.unpack . N.name +parseNameForRecord :: N.Name -> GName +parseNameForRecord = GMkName . GString . T.unpack . rmThe . N.name + where + rmThe :: T.Text -> T.Text + rmThe input = input & [regex|^\s?the+\s+|] . match %~ const "" + commonFunction :: T.Text -> Bool commonFunction x = T.unpack x `elem` ["id", "map", "filter", "cons", "nil", "minus", "plus", "div", "mult", "add", "modulo", "pow", "round", "certain", "uncertain", "known", "unknown"] +comparisonOp :: BinOp -> Bool +comparisonOp op = op `elem` [Eq, Lt, Gt, Le, Ge, Ne] + quoteVars :: Tree a -> Tree a quoteVars (GVar x) = GQuoteVar x quoteVars x = composOp quoteVars x @@ -169,9 +188,12 @@ parseExpr name = Unary op expr -> GUnary (parseUnaOp op) (f expr) BinExpr op l r -> GBinExpr (parseBinOp op) (f l) (f r) IfThenElse cond thn els -> GIfThenElse (f cond) (f thn) (f els) + + FunApp (Var (N.MkName "div" _ _)) [l,r] -> parseExpr name (BinExpr Divide l r) + FunApp (Var (N.MkName "mult" _ _)) [l,r] -> parseExpr name (BinExpr Mult l r) FunApp fun args -> GFunApp (f fun) (GListExpr $ fmap f args) -- Record rows -> GRecord - Project record label -> GProject (f record) (parseName label) + Project record label -> GProject (f record) (parseNameForRecord label) Fun md args body -> GFun (parseName name) (parseFunMetadata md) (GListName $ fmap parseName args) (f body) -- Let decl body -> Let decl (f body) Predicate md args body -> GPredicate (parseName name) (parseFunMetadata md) (GListName $ fmap parseName args) (f body) From 96d4af0f9b94a71c15106557ae9ae8b2a246e214 Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Wed, 6 Nov 2024 17:54:27 +0100 Subject: [PATCH 03/14] aggregation, small tweaks --- lam4-backend/gf-grammar/Lam4.gf | 13 ++++ lam4-backend/gf-grammar/Lam4.pgf | Bin 7216 -> 8451 bytes lam4-backend/gf-grammar/Lam4Eng.gf | 93 ++++++++++++++++++++----- lam4-backend/src/Lam4/Render/Lam4Gf.hs | 71 +++++++++++++------ lam4-backend/src/Lam4/Render/Render.hs | 59 ++++++++++++++-- 5 files changed, 193 insertions(+), 43 deletions(-) diff --git a/lam4-backend/gf-grammar/Lam4.gf b/lam4-backend/gf-grammar/Lam4.gf index 9611f7c9..5c05fcaf 100644 --- a/lam4-backend/gf-grammar/Lam4.gf +++ b/lam4-backend/gf-grammar/Lam4.gf @@ -52,8 +52,12 @@ abstract Lam4 = { -- ApplyListOp : ListOp -> [Expr] -> Expr ; Unary : UnaryOp -> Expr -> Expr ; + VerboseBinExpr, -- newline + quotes around args + QuotedBinExpr, -- no newline, quotes around args BinExpr : BinOp -> Expr -> Expr -> Expr ; + Unknown, Uncertain : Expr -> Expr ; + -- TODO: get rid of all nested IfThenElses IfThenElse : Expr -> Expr -> Expr -> Expr ; -- make them into Elif instead @@ -68,6 +72,14 @@ abstract Lam4 = { -} +{- [The investor's total allocation in Energy] + is calculated by (AssignS) + adding up (InstanceSumIf) + [the investor's funds allocated to the investment as per sector share] + where + [the investment is in Energy] +-} + InstanceSumIf : (entities : Expr) -> (condition : Expr)-> Expr ; FunApp : Expr -> [Expr] -> Expr ; -- Record : (Row Expr) -> Expr ; -- record construction Project : Expr -> Name -> Expr ; -- record projection @@ -117,6 +129,7 @@ abstract Lam4 = { Predicate : (predname : Name) -> Metadata -> (args : [Name]) -> Expr -> Expr ; -- Differs from a function when doing symbolic evaluation. Exact way in which they should differ is WIP. PredApp : Expr -> [Expr] -> Expr ; + PredAppMany : BinOp -> (business_is_good : [Expr]) -> (uncertain_unknown : [Expr]) -> Expr ; Fold : Expr -> Expr -> Expr -> Expr ; -- When generating natural language for some file that defines a bunch of stuff like cons, map, filter, diff --git a/lam4-backend/gf-grammar/Lam4.pgf b/lam4-backend/gf-grammar/Lam4.pgf index c8e76f47700571dbc060c4a08e29e281ff5e4756..b41afd56304d77a8afeeeacc98b2f3b53c06d187 100644 GIT binary patch delta 2748 zcmZ`*No*Ts6n_8z&v;3kwd2HTvvx~qX+vAOu%u}gCrukCX_K^+rlb?kIGM(tac0IX zfl59g0Y{{fdf)(;iX&=O!3}{bA#pBjlMQPZ^P zxT=}g7b>Oc0)>Qbx`u1$4oKP8%QiqVZV>xcm1;&l@wyuqq%Q@BDVn9|v9y83jGC=EU#W76XaaIgxWzDiQNX!_H>nGJ# z!HjKJHO!TYxnWwjO>aO-hrzsG;&TxmNeo7~l;~{^?|rdixw__M$WbL=#V+Z2%ho8* zLh||&U6I}Ai9->7oT&MpO7=Gzt_n0ZIfwTCMpO;_`1x$8XwTW;)tCsYz!nH~^ zU)Jqa%h7pOQNVYSpH{oVTF0?EyaXYg7`M!u^$aOnGzy_qnzV{qNU+I@8R8gXEP6;b zOcxf{bu(LZ^pLe}E~=5orVG5-Xr1R15h}A8-K}9G!Y#9wU7B{L&4O*1YkHJQJZO4o zQ$GYDFUfU`yy{{~Re$Kw%(|)PBlii>L#%0N)8sexi5dlc4VBn}u@+)^$yDvFkgByZ zfm7aBt$o!xMx2prGJ262xz4EJuw*p#Pl@8eYtSfc&?8e#4G0Ns zfubVJxN~Lwjm4TxYyM=Sfv+6_%b97 zNj#^WMZ2PtXV{G45<+KO+IL3I8D_O@KAHt??Eo|!t_ z)g<^)4R$_3??P`}m=%_D0VRm}dLma(%*Jw-#>Xi=D&=sVXy+K6)#>@O-rt>jTgK^} zO(!R$`68yxQM_1re<@HXn%+Ab%9b$CY|-tTQ@l(v1_H#j-sy`337 z(o#*5nv(5X*d{~X*O^M!S%3+EEWkX#MSx2HmjSK-8T6LBmaD_~8;{=+ z0?jZ=p%w8s$BX=Ug$o&6zO#*Fg63qC* y2FUrK5oVdNYJfQ(G`7ny0B{W848RgV(L1uMJ57^LKfb4V!_g6i|6+2xe*70ZcL@Ff delta 1715 zcmai!&r=&^7{{OIeRuOafenNrD-f%%QKEm_N|W!aeuFKGIn#={DxqF3F8bWt{)5W1+i+_Iz_ zyYuCFZNpHsP1!B#T`}ZhQzgHpm4altg?NO%Ef?HO?&&&ZJgf4_f^N7eX>jM*>sH@lz|ZY`dCjQE zc*5#lM6zgNkC;=mN*TKYxt*MBN=3<(Fy_haSbM~nKexj-WpC(M6L*H~d3Uq%f9V9z zR(DRQc%h+Gyx1(>Xcpt1oL;P`I<^bBifUp9S(5QJ=1m?CkCJ5r&j>3j|I#jYG1+^e z@s{v-6Sp<-E6(e}p!=?{pFK-vyxsO653;$QN@4Xl9S{S_8bo-XfS;>^HHaV+XtR=S@_6>LcWrDH!U$P}m;6_aAk5UUMSxiXA)auK zK$s8n)K(F=${wYLGMQSfB0@AOz(UO#fW;aFAxG_10a&U*uuX(MfO7zs0oDLE*q^B+ LMJ%&)`j>wIma!3o diff --git a/lam4-backend/gf-grammar/Lam4Eng.gf b/lam4-backend/gf-grammar/Lam4Eng.gf index 1b13d117..ae63ef95 100644 --- a/lam4-backend/gf-grammar/Lam4Eng.gf +++ b/lam4-backend/gf-grammar/Lam4Eng.gf @@ -6,9 +6,11 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { Metadata = LinMetadata ; ListExpr = ListX0 ; ListName = ListX0 ; + BinOp = {s : Verbosity => Str} ; param IsEmpty = Empty | NonEmpty ; MyListSize = Zero | One | Many ; + Verbosity = Concise | Verbose ; oper ListX0 : Type = ListX ** {size : MyListSize} ; @@ -50,10 +52,19 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { EmptyS = {s = ""} ; TypeDeclS td = td ; ExprS expr = expr ; - EvalS expr = {s = "evaluate" ++ expr.s} ; - EvalWhetherS expr = {s = "evaluate whether" ++ expr.s} ; - AssignS name expr = {s = quote name.s ++ "is calculated as" ++ indent2 expr.s} ; - LetIsTrue name expr = {s = quote name.s ++ "is true if" ++ indent2 expr.s} ; + EvalS expr = {s = "evaluate" ++ expr.s ++ linebreak} ; + EvalWhetherS expr = {s = "evaluate whether" ++ expr.s ++ linebreak} ; + AssignS name expr = { + s = quote name.s + ++ "is calculated by" + ++ indent1 expr.s + ++ linebreak } ; + LetIsTrue name expr = { + s = quote name.s + ++ "is true if" + ++ indent1 expr.s + ++ linebreak + } ; AtomicConcept name = {s = name.s ++ "is an atomic concept."} ; -- Metadata @@ -128,6 +139,12 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { _ => pr ++ conjX "and" xs ++ pst } } ; + mkBinExpr : Str -> Str -> {s : Verbosity => Str} ; + mkBinExpr short long = { + s = table { + Concise => short ; + Verbose => long } + } ; lin @@ -138,7 +155,32 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { Var name = name ; Lit name = name ; Unary op expr = cc2 op expr ; - BinExpr op e1 e2 = cc3 (quoteSS e1) op (quoteSS e2) ; + BinExpr op e1 e2 = { + s = e1.s + ++ op.s ! Concise + ++ e2.s + } ; + + QuotedBinExpr op e1 e2 = { + s = quote e1.s + ++ op.s ! Concise + ++ quote e2.s + } ; + + VerboseBinExpr op e1 e2 = { + s = (quote e1.s) + ++ indent1 (op.s ! Verbose) + ++ indent1 (quote e2.s) + } ; + + Unknown expr = { + s = quote expr.s ++ "is unknown" + } ; + + Uncertain expr = { + s = quote expr.s ++ "is uncertain" + } ; + IfThenElse if then else = { s = "if" ++ if.s @@ -146,6 +188,14 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { ++ indent2 "else" ++ else.s } ; + -- : Expr -> Expr -> Expr ; + InstanceSumIf entities condition = { + s = "adding up those of" + ++ indent2 (quote entities.s) + ++ indent1 "where" + ++ indent2 (quote condition.s) + } ; + -- : Expr -> [Expr] -> Expr ; FunApp f xs = {s = f.s ++ linArgs "of" xs} ; -- Record : (Row Expr) -> Expr ; -- record construction @@ -187,6 +237,13 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { -- : Expr -> [Expr] -> Expr ; PredApp = FunApp ; + + PredAppMany op args preds = { + s = quote (conjX "and" args) ++ "is" ++ conjX (op.s ! Verbose) preds + } ; + + + Fold combine nil over = { s = linebreak ++ "Combine" ++ quote over.s ++ "into one value," ++ linebreak @@ -207,19 +264,19 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { IntegerToFraction = ss "" ; -- not important in NLG UnaryMinus = ss "-" ; - Or = ss "or" ; - And = ss "and" ; - Plus = ss "+" ; - Minus = ss "-" ; - Modulo = ss "%" ; - Mult = ss "*" ; - Divide = ss "/" ; - Lt = ss "<" ; - Le = ss "≤" ; - Gt = ss ">" ; - Ge = ss "≥" ; - Eq = ss "equals to" ; - Ne = ss "≠" ; + Or = mkBinExpr "||" "or" ; + And = mkBinExpr "&&" "and" ; + Plus = mkBinExpr "+" "added to" ; + Minus = mkBinExpr "-" "subtracted from" ; + Modulo = mkBinExpr "%" "modulo" ; + Mult = mkBinExpr "*" "multiplied by" ; + Divide = mkBinExpr "/" "divided by" ; + Lt = mkBinExpr "<" "is less than" ; + Le = mkBinExpr "≤" "is less than or equal" ; + Gt = mkBinExpr ">" "is greater than" ; + Ge = mkBinExpr "≥" "is greater than or equal to" ; + Eq = mkBinExpr "=" "equals to" ; + Ne = mkBinExpr "≠" "is not equal to" ; BaseExpr, BaseName = baseListX0 ; ConsExpr, ConsName = consListX0 ; diff --git a/lam4-backend/src/Lam4/Render/Lam4Gf.hs b/lam4-backend/src/Lam4/Render/Lam4Gf.hs index 1c02bee2..d970faae 100644 --- a/lam4-backend/src/Lam4/Render/Lam4Gf.hs +++ b/lam4-backend/src/Lam4/Render/Lam4Gf.hs @@ -37,6 +37,7 @@ instance Gf GFloat where ---------------------------------------------------- -- below this line machine-generated instance (Gf (Tree a)) => Show (Tree a) where + show :: Gf (Tree a) => Tree a -> String show = showExpr [] . gf ---------------------------------------------------- @@ -94,18 +95,24 @@ data Tree :: * -> * where GFun :: GName -> GMetadata -> GListName -> GExpr -> Tree GExpr_ GFunApp :: GExpr -> GListExpr -> Tree GExpr_ GIfThenElse :: GExpr -> GExpr -> GExpr -> Tree GExpr_ + GInstanceSumIf :: GExpr -> GExpr -> Tree GExpr_ GKnownFunction :: GName -> Tree GExpr_ GLet :: GS -> GExpr -> Tree GExpr_ GLit :: GName -> Tree GExpr_ GNormIsInfringed :: GName -> Tree GExpr_ GPredApp :: GExpr -> GListExpr -> Tree GExpr_ + GPredAppMany :: GBinOp -> GListExpr -> GListExpr -> Tree GExpr_ GPredicate :: GName -> GMetadata -> GListName -> GExpr -> Tree GExpr_ GProject :: GExpr -> GName -> Tree GExpr_ GQuoteVar :: GName -> Tree GExpr_ + GQuotedBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ GRecord :: GName -> GExpr -> Tree GExpr_ GSig :: GListName -> GListExpr -> Tree GExpr_ GUnary :: GUnaryOp -> GExpr -> Tree GExpr_ + GUncertain :: GExpr -> Tree GExpr_ + GUnknown :: GExpr -> Tree GExpr_ GVar :: GName -> Tree GExpr_ + GVerboseBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ GListExpr :: [GExpr] -> Tree GListExpr_ GListIfThen :: [GIfThen] -> Tree GListIfThen_ GListName :: [GName] -> Tree GListName_ @@ -155,18 +162,24 @@ instance Eq (Tree a) where (GFun x1 x2 x3 x4,GFun y1 y2 y3 y4) -> and [ x1 == y1 , x2 == y2 , x3 == y3 , x4 == y4 ] (GFunApp x1 x2,GFunApp y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GIfThenElse x1 x2 x3,GIfThenElse y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] + (GInstanceSumIf x1 x2,GInstanceSumIf y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GKnownFunction x1,GKnownFunction y1) -> and [ x1 == y1 ] (GLet x1 x2,GLet y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GLit x1,GLit y1) -> and [ x1 == y1 ] (GNormIsInfringed x1,GNormIsInfringed y1) -> and [ x1 == y1 ] (GPredApp x1 x2,GPredApp y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GPredAppMany x1 x2 x3,GPredAppMany y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GPredicate x1 x2 x3 x4,GPredicate y1 y2 y3 y4) -> and [ x1 == y1 , x2 == y2 , x3 == y3 , x4 == y4 ] (GProject x1 x2,GProject y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GQuoteVar x1,GQuoteVar y1) -> and [ x1 == y1 ] + (GQuotedBinExpr x1 x2 x3,GQuotedBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GRecord x1 x2,GRecord y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GSig x1 x2,GSig y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GUnary x1 x2,GUnary y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GUncertain x1,GUncertain y1) -> and [ x1 == y1 ] + (GUnknown x1,GUnknown y1) -> and [ x1 == y1 ] (GVar x1,GVar y1) -> and [ x1 == y1 ] + (GVerboseBinExpr x1 x2 x3,GVerboseBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GListExpr x1,GListExpr y1) -> and [x == y | (x,y) <- zip x1 y1] (GListIfThen x1,GListIfThen y1) -> and [x == y | (x,y) <- zip x1 y1] (GListName x1,GListName y1) -> and [x == y | (x,y) <- zip x1 y1] @@ -212,19 +225,19 @@ instance Gf GBinOp where fg t = case unApp t of - Just (i,[]) | i == mkCId "And" -> GAnd - Just (i,[]) | i == mkCId "Divide" -> GDivide - Just (i,[]) | i == mkCId "Eq" -> GEq - Just (i,[]) | i == mkCId "Ge" -> GGe - Just (i,[]) | i == mkCId "Gt" -> GGt - Just (i,[]) | i == mkCId "Le" -> GLe - Just (i,[]) | i == mkCId "Lt" -> GLt - Just (i,[]) | i == mkCId "Minus" -> GMinus - Just (i,[]) | i == mkCId "Modulo" -> GModulo - Just (i,[]) | i == mkCId "Mult" -> GMult - Just (i,[]) | i == mkCId "Ne" -> GNe - Just (i,[]) | i == mkCId "Or" -> GOr - Just (i,[]) | i == mkCId "Plus" -> GPlus + Just (i,[]) | i == mkCId "And" -> GAnd + Just (i,[]) | i == mkCId "Divide" -> GDivide + Just (i,[]) | i == mkCId "Eq" -> GEq + Just (i,[]) | i == mkCId "Ge" -> GGe + Just (i,[]) | i == mkCId "Gt" -> GGt + Just (i,[]) | i == mkCId "Le" -> GLe + Just (i,[]) | i == mkCId "Lt" -> GLt + Just (i,[]) | i == mkCId "Minus" -> GMinus + Just (i,[]) | i == mkCId "Modulo" -> GModulo + Just (i,[]) | i == mkCId "Mult" -> GMult + Just (i,[]) | i == mkCId "Ne" -> GNe + Just (i,[]) | i == mkCId "Or" -> GOr + Just (i,[]) | i == mkCId "Plus" -> GPlus _ -> error ("no BinOp " ++ show t) @@ -237,18 +250,24 @@ instance Gf GExpr where gf (GFun x1 x2 x3 x4) = mkApp (mkCId "Fun") [gf x1, gf x2, gf x3, gf x4] gf (GFunApp x1 x2) = mkApp (mkCId "FunApp") [gf x1, gf x2] gf (GIfThenElse x1 x2 x3) = mkApp (mkCId "IfThenElse") [gf x1, gf x2, gf x3] + gf (GInstanceSumIf x1 x2) = mkApp (mkCId "InstanceSumIf") [gf x1, gf x2] gf (GKnownFunction x1) = mkApp (mkCId "KnownFunction") [gf x1] gf (GLet x1 x2) = mkApp (mkCId "Let") [gf x1, gf x2] gf (GLit x1) = mkApp (mkCId "Lit") [gf x1] gf (GNormIsInfringed x1) = mkApp (mkCId "NormIsInfringed") [gf x1] gf (GPredApp x1 x2) = mkApp (mkCId "PredApp") [gf x1, gf x2] + gf (GPredAppMany x1 x2 x3) = mkApp (mkCId "PredAppMany") [gf x1, gf x2, gf x3] gf (GPredicate x1 x2 x3 x4) = mkApp (mkCId "Predicate") [gf x1, gf x2, gf x3, gf x4] gf (GProject x1 x2) = mkApp (mkCId "Project") [gf x1, gf x2] gf (GQuoteVar x1) = mkApp (mkCId "QuoteVar") [gf x1] + gf (GQuotedBinExpr x1 x2 x3) = mkApp (mkCId "QuotedBinExpr") [gf x1, gf x2, gf x3] gf (GRecord x1 x2) = mkApp (mkCId "Record") [gf x1, gf x2] gf (GSig x1 x2) = mkApp (mkCId "Sig") [gf x1, gf x2] gf (GUnary x1 x2) = mkApp (mkCId "Unary") [gf x1, gf x2] + gf (GUncertain x1) = mkApp (mkCId "Uncertain") [gf x1] + gf (GUnknown x1) = mkApp (mkCId "Unknown") [gf x1] gf (GVar x1) = mkApp (mkCId "Var") [gf x1] + gf (GVerboseBinExpr x1 x2 x3) = mkApp (mkCId "VerboseBinExpr") [gf x1, gf x2, gf x3] fg t = case unApp t of @@ -259,18 +278,24 @@ instance Gf GExpr where Just (i,[x1,x2,x3,x4]) | i == mkCId "Fun" -> GFun (fg x1) (fg x2) (fg x3) (fg x4) Just (i,[x1,x2]) | i == mkCId "FunApp" -> GFunApp (fg x1) (fg x2) Just (i,[x1,x2,x3]) | i == mkCId "IfThenElse" -> GIfThenElse (fg x1) (fg x2) (fg x3) + Just (i,[x1,x2]) | i == mkCId "InstanceSumIf" -> GInstanceSumIf (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "KnownFunction" -> GKnownFunction (fg x1) Just (i,[x1,x2]) | i == mkCId "Let" -> GLet (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "Lit" -> GLit (fg x1) Just (i,[x1]) | i == mkCId "NormIsInfringed" -> GNormIsInfringed (fg x1) Just (i,[x1,x2]) | i == mkCId "PredApp" -> GPredApp (fg x1) (fg x2) + Just (i,[x1,x2,x3]) | i == mkCId "PredAppMany" -> GPredAppMany (fg x1) (fg x2) (fg x3) Just (i,[x1,x2,x3,x4]) | i == mkCId "Predicate" -> GPredicate (fg x1) (fg x2) (fg x3) (fg x4) Just (i,[x1,x2]) | i == mkCId "Project" -> GProject (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "QuoteVar" -> GQuoteVar (fg x1) + Just (i,[x1,x2,x3]) | i == mkCId "QuotedBinExpr" -> GQuotedBinExpr (fg x1) (fg x2) (fg x3) Just (i,[x1,x2]) | i == mkCId "Record" -> GRecord (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "Sig" -> GSig (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "Unary" -> GUnary (fg x1) (fg x2) + Just (i,[x1]) | i == mkCId "Uncertain" -> GUncertain (fg x1) + Just (i,[x1]) | i == mkCId "Unknown" -> GUnknown (fg x1) Just (i,[x1]) | i == mkCId "Var" -> GVar (fg x1) + Just (i,[x1,x2,x3]) | i == mkCId "VerboseBinExpr" -> GVerboseBinExpr (fg x1) (fg x2) (fg x3) _ -> error ("no Expr " ++ show t) @@ -330,7 +355,7 @@ instance Gf GMetadata where fg t = case unApp t of Just (i,[x1]) | i == mkCId "MkMetadata" -> GMkMetadata (fg x1) - Just (i,[]) | i == mkCId "NoMetadata" -> GNoMetadata + Just (i,[]) | i == mkCId "NoMetadata" -> GNoMetadata _ -> error ("no Metadata " ++ show t) @@ -371,7 +396,7 @@ instance Gf GS where case unApp t of Just (i,[x1,x2]) | i == mkCId "AssignS" -> GAssignS (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "AtomicConcept" -> GAtomicConcept (fg x1) - Just (i,[]) | i == mkCId "EmptyS" -> GEmptyS + Just (i,[]) | i == mkCId "EmptyS" -> GEmptyS Just (i,[x1]) | i == mkCId "EvalS" -> GEvalS (fg x1) Just (i,[x1]) | i == mkCId "EvalWhetherS" -> GEvalWhetherS (fg x1) Just (i,[x1]) | i == mkCId "ExprS" -> GExprS (fg x1) @@ -400,11 +425,11 @@ instance Gf GUnaryOp where fg t = case unApp t of - Just (i,[]) | i == mkCId "Ceiling" -> GCeiling - Just (i,[]) | i == mkCId "Floor" -> GFloor - Just (i,[]) | i == mkCId "IntegerToFraction" -> GIntegerToFraction - Just (i,[]) | i == mkCId "Not" -> GNot - Just (i,[]) | i == mkCId "UnaryMinus" -> GUnaryMinus + Just (i,[]) | i == mkCId "Ceiling" -> GCeiling + Just (i,[]) | i == mkCId "Floor" -> GFloor + Just (i,[]) | i == mkCId "IntegerToFraction" -> GIntegerToFraction + Just (i,[]) | i == mkCId "Not" -> GNot + Just (i,[]) | i == mkCId "UnaryMinus" -> GUnaryMinus _ -> error ("no UnaryOp " ++ show t) @@ -427,18 +452,24 @@ instance Compos Tree where GFun x1 x2 x3 x4 -> r GFun `a` f x1 `a` f x2 `a` f x3 `a` f x4 GFunApp x1 x2 -> r GFunApp `a` f x1 `a` f x2 GIfThenElse x1 x2 x3 -> r GIfThenElse `a` f x1 `a` f x2 `a` f x3 + GInstanceSumIf x1 x2 -> r GInstanceSumIf `a` f x1 `a` f x2 GKnownFunction x1 -> r GKnownFunction `a` f x1 GLet x1 x2 -> r GLet `a` f x1 `a` f x2 GLit x1 -> r GLit `a` f x1 GNormIsInfringed x1 -> r GNormIsInfringed `a` f x1 GPredApp x1 x2 -> r GPredApp `a` f x1 `a` f x2 + GPredAppMany x1 x2 x3 -> r GPredAppMany `a` f x1 `a` f x2 `a` f x3 GPredicate x1 x2 x3 x4 -> r GPredicate `a` f x1 `a` f x2 `a` f x3 `a` f x4 GProject x1 x2 -> r GProject `a` f x1 `a` f x2 GQuoteVar x1 -> r GQuoteVar `a` f x1 + GQuotedBinExpr x1 x2 x3 -> r GQuotedBinExpr `a` f x1 `a` f x2 `a` f x3 GRecord x1 x2 -> r GRecord `a` f x1 `a` f x2 GSig x1 x2 -> r GSig `a` f x1 `a` f x2 GUnary x1 x2 -> r GUnary `a` f x1 `a` f x2 + GUncertain x1 -> r GUncertain `a` f x1 + GUnknown x1 -> r GUnknown `a` f x1 GVar x1 -> r GVar `a` f x1 + GVerboseBinExpr x1 x2 x3 -> r GVerboseBinExpr `a` f x1 `a` f x2 `a` f x3 GMkMetadata x1 -> r GMkMetadata `a` f x1 GMkName x1 -> r GMkName `a` f x1 GMkRowDecl x1 x2 -> r GMkRowDecl `a` f x1 `a` f x2 diff --git a/lam4-backend/src/Lam4/Render/Render.hs b/lam4-backend/src/Lam4/Render/Render.hs index 8de43bc7..ec76b7cd 100644 --- a/lam4-backend/src/Lam4/Render/Render.hs +++ b/lam4-backend/src/Lam4/Render/Render.hs @@ -88,10 +88,10 @@ renderCstProgramToNL env decls = T.unlines $ fmap (renderCstDeclToNL env) decls <> fmap (renderCstDeclToGFtrees env) decls renderCstDeclToNL :: NLGEnv -> Decl -> T.Text -renderCstDeclToNL env = gfLin env . gf . parseDecl +renderCstDeclToNL env = gfLin env . gf . aggregatePredApp . parseDecl renderCstDeclToGFtrees :: NLGEnv -> Decl -> T.Text -renderCstDeclToGFtrees env = gfTree env . gf . parseDecl +renderCstDeclToGFtrees env = gfTree env . gf . aggregatePredApp . parseDecl parseDecl :: Decl -> GS parseDecl = \case @@ -123,15 +123,45 @@ parseNameForRecord = GMkName . GString . T.unpack . rmThe . N.name rmThe input = input & [regex|^\s?the+\s+|] . match %~ const "" commonFunction :: T.Text -> Bool -commonFunction x = T.unpack x `elem` ["id", "map", "filter", "cons", "nil", "minus", "plus", "div", "mult", "add", "modulo", "pow", "round", "certain", "uncertain", "known", "unknown"] +commonFunction x = T.unpack x `elem` ["id", "map", "filter", "cons", "nil", "minus", "plus", "div", "mult", "add", "modulo", "pow", "round", "certain", "uncertain", "known", "unknown", "default", "instanceSumIf", "instanceSum"] comparisonOp :: BinOp -> Bool comparisonOp op = op `elem` [Eq, Lt, Gt, Le, Ge, Ne] +---- Tree transformations ----- + quoteVars :: Tree a -> Tree a quoteVars (GVar x) = GQuoteVar x quoteVars x = composOp quoteVars x +-- Ground rule: binexpr is verbose if arguments are complex +-- exception: if it's in if-then-else +unVerboseBinExpr :: Tree a -> Tree a +unVerboseBinExpr (GVerboseBinExpr op l r) = + GQuotedBinExpr op + (quoteVarsBinExpr l) -- inner bin exprs become now quoted, even if they were unquoted previously + (quoteVarsBinExpr r) +unVerboseBinExpr x = composOp unVerboseBinExpr x + +-- like above, but also forces concise BinExpr to be quoted +quoteVarsBinExpr :: Tree a -> Tree a +quoteVarsBinExpr (GVerboseBinExpr op l r) = GQuotedBinExpr op l r +quoteVarsBinExpr (GBinExpr op l r) = GQuotedBinExpr op l r +quoteVarsBinExpr x = composOp quoteVarsBinExpr x + +aggregatePredApp :: Tree a -> Tree a +aggregatePredApp tree@(GQuotedBinExpr op (GFunApp f arg) (GFunApp g arg')) = + if True -- sameTree arg arg' + then GPredAppMany op arg (GListExpr [f,g]) + else tree + +aggregatePredApp x = composOp aggregatePredApp x + +-------------------------------- + +sameTree :: forall a. Gf (Tree a) => Tree a -> Tree a -> Bool +sameTree a b = show a == show b + isBool :: Expr -> Bool isBool = \case BinExpr Eq _ _ -> True @@ -186,11 +216,19 @@ parseExpr name = Var var -> GVar (parseName var) Lit lit -> GLit (parseLit lit) Unary op expr -> GUnary (parseUnaOp op) (f expr) - BinExpr op l r -> GBinExpr (parseBinOp op) (f l) (f r) - IfThenElse cond thn els -> GIfThenElse (f cond) (f thn) (f els) + -- e.g. "x / y" + BinExpr op l@Var{} r@Var{} -> GBinExpr (parseBinOp op) (f l) (f r) + -- e.g. "x's z / y" + BinExpr op l@Project{} r@Var{} -> GBinExpr (parseBinOp op) (f l) (f r) + + -- other BinExprs are "verbose" = newlines and stuff + BinExpr op l r -> GVerboseBinExpr (parseBinOp op) (f l) (f r) + IfThenElse cond thn els -> unVerboseBinExpr $ GIfThenElse (f cond) (f thn) (f els) + FunApp (Var (N.MkName "instanceSumIf" _ _)) args -> parseInstanceSum args FunApp (Var (N.MkName "div" _ _)) [l,r] -> parseExpr name (BinExpr Divide l r) FunApp (Var (N.MkName "mult" _ _)) [l,r] -> parseExpr name (BinExpr Mult l r) + FunApp (Var (N.MkName "add" _ _)) [l,r] -> parseExpr name (BinExpr Plus l r) FunApp fun args -> GFunApp (f fun) (GListExpr $ fmap f args) -- Record rows -> GRecord Project record label -> GProject (f record) (parseNameForRecord label) @@ -208,6 +246,17 @@ parseExpr name = --) StatementBlock statements -> undefined -- TODO x -> error [i|parseExpr: not yet implemented #{x}|] +parseInstanceSum :: [Expr] -> GExpr +parseInstanceSum [_set, inst, cond] = GInstanceSumIf instExpr condExpr + where + instExpr = parseExpr noName $ varFromFun inst + condExpr = parseExpr noName $ varFromFun cond + varFromFun :: Expr -> Expr + varFromFun = \case + Fun _md _args (Project _rec label) -> Var label + e -> e +parseInstanceSum _ = GKnownFunction $ GMkName $ GString "SOMETHING WENT WRONG D:" + parseRecordRow :: (N.Name, Expr) -> GExpr parseRecordRow (name, expr) = GRecord (parseName name) (parseExpr name expr) From d01c7a85aa53bf450ff47c46c1283046aaac8b5e Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Mon, 11 Nov 2024 12:44:45 +0100 Subject: [PATCH 04/14] WIP: format in HTML --- lam4-backend/gf-grammar/Lam4.gf | 2 +- lam4-backend/gf-grammar/Lam4.pgf | Bin 8451 -> 9375 bytes lam4-backend/gf-grammar/Lam4Eng.gf | 149 ++++++++++++++++++++----- lam4-backend/src/Lam4/Render/Lam4Gf.hs | 51 +++++---- lam4-backend/src/Lam4/Render/Render.hs | 52 ++++++--- 5 files changed, 190 insertions(+), 64 deletions(-) diff --git a/lam4-backend/gf-grammar/Lam4.gf b/lam4-backend/gf-grammar/Lam4.gf index 5c05fcaf..a4188ed5 100644 --- a/lam4-backend/gf-grammar/Lam4.gf +++ b/lam4-backend/gf-grammar/Lam4.gf @@ -56,7 +56,7 @@ abstract Lam4 = { QuotedBinExpr, -- no newline, quotes around args BinExpr : BinOp -> Expr -> Expr -> Expr ; - Unknown, Uncertain : Expr -> Expr ; + Known, Certain, Unknown, Uncertain : Expr -> Expr ; -- TODO: get rid of all nested IfThenElses IfThenElse : Expr -> Expr -> Expr -> Expr ; diff --git a/lam4-backend/gf-grammar/Lam4.pgf b/lam4-backend/gf-grammar/Lam4.pgf index b41afd56304d77a8afeeeacc98b2f3b53c06d187..3d07e329a59788450f6319b0339ce96efdf0cb4b 100644 GIT binary patch literal 9375 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 Y=2s7*rRBy>hcG(V>i=fu=LuQ-Kc&wDdH?_b literal 8451 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 UdD&!XiCT1;)wlWOWojJ%ADyNuH~;_u diff --git a/lam4-backend/gf-grammar/Lam4Eng.gf b/lam4-backend/gf-grammar/Lam4Eng.gf index ae63ef95..88167779 100644 --- a/lam4-backend/gf-grammar/Lam4Eng.gf +++ b/lam4-backend/gf-grammar/Lam4Eng.gf @@ -12,7 +12,33 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { MyListSize = Zero | One | Many ; Verbosity = Concise | Verbose ; + Hilight = Strong | Emph | Underline ; + oper + + -- Keywords + + hilight : Hilight -> Str -> Str ; + hilight emph str = + openTag emph ++ str ++ closeTag emph ; + + openTag : Hilight -> Str = \t -> case t of { + Strong => "" ; + Emph => "" ; + Underling => "" + } ; + + closeTag : Hilight -> Str = \t -> case t of { + Strong => "" ; + Emph => "" ; + Underling => "" + } ; + + ifKw : Str = hilight Strong "if" ; + thenKw : Str = hilight Strong "then" ; + elseKw : Str = hilight Strong "else" ; + + -- List operations ListX0 : Type = ListX ** {size : MyListSize} ; baseListX0 : ListX0 = { @@ -20,9 +46,31 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { size = Zero } ; - consListX0 : SS -> ListX0 -> ListX0 = \x,xs -> case xs.size of { + -- twoStr : (x,y : Str) -> ListX = \x,y -> + -- {s1 = x ; s2 = y} ; + -- consStr : Str -> ListX -> Str -> ListX = \comma,xs,x -> + -- {s1 = xs.s1 ++ comma ++ xs.s2 ; s2 = x } ; + + + + conslListX0 : SS -> ListX0 -> ListX0 = \x,xs -> case xs.size of { Many => xs ** { - s1 = x.s ++ bindComma ++ xs.s1 + s1 = xs.s1 ++ bindComma ++ xs.s2 ; + s2 = x.s + } ; + One => xs ** { + s2 = x.s ; + size = Many + } ; + Zero => xs ** { + s1 = x.s ; + size = One + } + } ; + + consrListX0 : SS -> ListX0 -> ListX0 = \x,xs -> case xs.size of { + Many => xs ** { + s1 = x.s ++ bindComma ++ xs.s1 ; } ; One => xs ** { s1 = x.s ; @@ -55,17 +103,14 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { EvalS expr = {s = "evaluate" ++ expr.s ++ linebreak} ; EvalWhetherS expr = {s = "evaluate whether" ++ expr.s ++ linebreak} ; AssignS name expr = { - s = quote name.s - ++ "is calculated by" - ++ indent1 expr.s - ++ linebreak } ; + s = dl (quote name.s ++ hilight Strong "is calculated by") + expr.s + } ; LetIsTrue name expr = { - s = quote name.s - ++ "is true if" - ++ indent1 expr.s - ++ linebreak + s = dl (quote name.s ++ ifKw) + expr.s } ; - AtomicConcept name = {s = name.s ++ "is an atomic concept."} ; + AtomicConcept name = {s = paragraph (name.s ++ "is an atomic concept.")} ; -- Metadata MkMetadata str = str ** {isEmpty = NonEmpty} ; @@ -100,18 +145,20 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { -- just ad hoc characters to `tr "°∞" "\t\n"` in shell tab = "°°" ; space = "°" ; - linebreak = "∞" ; + linebreak = "
" ; indent1, indent2 : Str -> Str ; indent1 str = linebreak ++ space ++ str ; indent2 str = linebreak ++ tab ++ str ; quote : Str -> Str ; - quote str = "[" ++ BIND ++ str ++ BIND ++ "]" ; + quote str = "" ++ BIND ++ str ++ BIND ++ "" ; quoteSS : SS -> SS ; quoteSS ss = {s = quote ss.s} ; + paragraph : Str -> Str = \s -> "

" ++ s ++ "

" ; + artIndef = pre { "eu" | "Eu" | "uni" | "Uni" => "A" ; "un" | "Un" => "An" ; @@ -132,20 +179,54 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { linArgs : Str -> ListX0 -> Str = \s,xs -> case xs.size of { Zero => "" ; - _ => s ++ conjX "and" xs } ; + _ => paragraph (s ++ conjX "and" xs) } ; linArgs : Str -> ListX0 -> Str -> Str = \pr,xs,pst -> case xs.size of { Zero => "" ; - _ => pr ++ conjX "and" xs ++ pst } + _ => paragraph (pr ++ conjX "and" xs ++ pst) } } ; + -- Bin expr mkBinExpr : Str -> Str -> {s : Verbosity => Str} ; mkBinExpr short long = { s = table { Concise => short ; - Verbose => long } + Verbose => hilight Emph long } } ; + -- ul = overload { + ul : (i,t,e : Str) -> Str ; + ul i t e = + paragraph ( + i + ++ "
    " + ++ "
  • " ++ t ++ "
  • " + ++ "
  • " ++ e ++ "
  • " + ++ "
" + ) ; + -- } + + dl = overload { + dl : (t,d : Str) -> Str = \t,d -> + "
" + ++ "
" ++ t ++ "
" + ++ "
" ++ d ++ "
" + ++ "
" + ; + dl : Hilight -> (t, d : Str) -> Str = \emph,t,d -> + "
" + ++ "
" ++ hilight emph t ++ "
" + ++ "
" ++ d ++ "
" + ++ "
" + } ; + + + ite : (i,t,e : Str) -> Str ; + ite i t e = + dl ifKw i ++ + (dl thenKw t ++ + dl elseKw e) ; + lin -- Expressions @@ -168,9 +249,8 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { } ; VerboseBinExpr op e1 e2 = { - s = (quote e1.s) - ++ indent1 (op.s ! Verbose) - ++ indent1 (quote e2.s) + s = dl "" e1.s + ++ dl (op.s ! Verbose) e2.s } ; Unknown expr = { @@ -181,19 +261,22 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { s = quote expr.s ++ "is uncertain" } ; + Known expr = { + s = quote expr.s ++ "is known" + } ; + + Certain expr = { + s = quote expr.s ++ "is certain" + } ; IfThenElse if then else = { - s = "if" ++ if.s - ++ indent2 "then" ++ then.s - ++ indent2 "else" ++ else.s + s = ite if.s then.s else.s } ; -- : Expr -> Expr -> Expr ; InstanceSumIf entities condition = { - s = "adding up those of" - ++ indent2 (quote entities.s) - ++ indent1 "where" - ++ indent2 (quote condition.s) + s = dl "adding up those of" (quote entities.s) + ++ dl "where" (quote condition.s) } ; -- : Expr -> [Expr] -> Expr ; @@ -201,7 +284,11 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { -- Record : (Row Expr) -> Expr ; -- record construction -- : Expr -> Name -> Expr ; -- record projection - Project rec field = {s = glue rec.s "'s" ++ field.s} ; + Project rec field = { + s = + -- glue rec.s "'s" ++ + field.s + } ; -- : Name -> Metadata -> [Name] -> Expr -> Expr ; -- Function Fun funname md args body = { @@ -236,7 +323,11 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { } ; -- : Expr -> [Expr] -> Expr ; - PredApp = FunApp ; + PredApp f xs = { + s = case xs.size of { + One => conjX "and" xs ++ "is" ++ f.s ; -- business plan is known + _ => f.s ++ "holds for" ++ conjX "and" xs } + } ; PredAppMany op args preds = { s = quote (conjX "and" args) ++ "is" ++ conjX (op.s ! Verbose) preds @@ -279,7 +370,7 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { Ne = mkBinExpr "≠" "is not equal to" ; BaseExpr, BaseName = baseListX0 ; - ConsExpr, ConsName = consListX0 ; + ConsExpr, ConsName = consrListX0 ; ConjExpr = conjXss ; } diff --git a/lam4-backend/src/Lam4/Render/Lam4Gf.hs b/lam4-backend/src/Lam4/Render/Lam4Gf.hs index d970faae..d4a6932e 100644 --- a/lam4-backend/src/Lam4/Render/Lam4Gf.hs +++ b/lam4-backend/src/Lam4/Render/Lam4Gf.hs @@ -37,7 +37,6 @@ instance Gf GFloat where ---------------------------------------------------- -- below this line machine-generated instance (Gf (Tree a)) => Show (Tree a) where - show :: Gf (Tree a) => Tree a -> String show = showExpr [] . gf ---------------------------------------------------- @@ -89,6 +88,7 @@ data Tree :: * -> * where GOr :: Tree GBinOp_ GPlus :: Tree GBinOp_ GBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ + GCertain :: GExpr -> Tree GExpr_ GConjExpr :: GListExpr -> Tree GExpr_ GElif :: GListIfThen -> GExpr -> Tree GExpr_ GFold :: GExpr -> GExpr -> GExpr -> Tree GExpr_ @@ -96,6 +96,7 @@ data Tree :: * -> * where GFunApp :: GExpr -> GListExpr -> Tree GExpr_ GIfThenElse :: GExpr -> GExpr -> GExpr -> Tree GExpr_ GInstanceSumIf :: GExpr -> GExpr -> Tree GExpr_ + GKnown :: GExpr -> Tree GExpr_ GKnownFunction :: GName -> Tree GExpr_ GLet :: GS -> GExpr -> Tree GExpr_ GLit :: GName -> Tree GExpr_ @@ -156,6 +157,7 @@ instance Eq (Tree a) where (GOr,GOr) -> and [ ] (GPlus,GPlus) -> and [ ] (GBinExpr x1 x2 x3,GBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] + (GCertain x1,GCertain y1) -> and [ x1 == y1 ] (GConjExpr x1,GConjExpr y1) -> and [ x1 == y1 ] (GElif x1 x2,GElif y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GFold x1 x2 x3,GFold y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] @@ -163,6 +165,7 @@ instance Eq (Tree a) where (GFunApp x1 x2,GFunApp y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GIfThenElse x1 x2 x3,GIfThenElse y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GInstanceSumIf x1 x2,GInstanceSumIf y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GKnown x1,GKnown y1) -> and [ x1 == y1 ] (GKnownFunction x1,GKnownFunction y1) -> and [ x1 == y1 ] (GLet x1 x2,GLet y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GLit x1,GLit y1) -> and [ x1 == y1 ] @@ -225,25 +228,26 @@ instance Gf GBinOp where fg t = case unApp t of - Just (i,[]) | i == mkCId "And" -> GAnd - Just (i,[]) | i == mkCId "Divide" -> GDivide - Just (i,[]) | i == mkCId "Eq" -> GEq - Just (i,[]) | i == mkCId "Ge" -> GGe - Just (i,[]) | i == mkCId "Gt" -> GGt - Just (i,[]) | i == mkCId "Le" -> GLe - Just (i,[]) | i == mkCId "Lt" -> GLt - Just (i,[]) | i == mkCId "Minus" -> GMinus - Just (i,[]) | i == mkCId "Modulo" -> GModulo - Just (i,[]) | i == mkCId "Mult" -> GMult - Just (i,[]) | i == mkCId "Ne" -> GNe - Just (i,[]) | i == mkCId "Or" -> GOr - Just (i,[]) | i == mkCId "Plus" -> GPlus + Just (i,[]) | i == mkCId "And" -> GAnd + Just (i,[]) | i == mkCId "Divide" -> GDivide + Just (i,[]) | i == mkCId "Eq" -> GEq + Just (i,[]) | i == mkCId "Ge" -> GGe + Just (i,[]) | i == mkCId "Gt" -> GGt + Just (i,[]) | i == mkCId "Le" -> GLe + Just (i,[]) | i == mkCId "Lt" -> GLt + Just (i,[]) | i == mkCId "Minus" -> GMinus + Just (i,[]) | i == mkCId "Modulo" -> GModulo + Just (i,[]) | i == mkCId "Mult" -> GMult + Just (i,[]) | i == mkCId "Ne" -> GNe + Just (i,[]) | i == mkCId "Or" -> GOr + Just (i,[]) | i == mkCId "Plus" -> GPlus _ -> error ("no BinOp " ++ show t) instance Gf GExpr where gf (GBinExpr x1 x2 x3) = mkApp (mkCId "BinExpr") [gf x1, gf x2, gf x3] + gf (GCertain x1) = mkApp (mkCId "Certain") [gf x1] gf (GConjExpr x1) = mkApp (mkCId "ConjExpr") [gf x1] gf (GElif x1 x2) = mkApp (mkCId "Elif") [gf x1, gf x2] gf (GFold x1 x2 x3) = mkApp (mkCId "Fold") [gf x1, gf x2, gf x3] @@ -251,6 +255,7 @@ instance Gf GExpr where gf (GFunApp x1 x2) = mkApp (mkCId "FunApp") [gf x1, gf x2] gf (GIfThenElse x1 x2 x3) = mkApp (mkCId "IfThenElse") [gf x1, gf x2, gf x3] gf (GInstanceSumIf x1 x2) = mkApp (mkCId "InstanceSumIf") [gf x1, gf x2] + gf (GKnown x1) = mkApp (mkCId "Known") [gf x1] gf (GKnownFunction x1) = mkApp (mkCId "KnownFunction") [gf x1] gf (GLet x1 x2) = mkApp (mkCId "Let") [gf x1, gf x2] gf (GLit x1) = mkApp (mkCId "Lit") [gf x1] @@ -272,6 +277,7 @@ instance Gf GExpr where fg t = case unApp t of Just (i,[x1,x2,x3]) | i == mkCId "BinExpr" -> GBinExpr (fg x1) (fg x2) (fg x3) + Just (i,[x1]) | i == mkCId "Certain" -> GCertain (fg x1) Just (i,[x1]) | i == mkCId "ConjExpr" -> GConjExpr (fg x1) Just (i,[x1,x2]) | i == mkCId "Elif" -> GElif (fg x1) (fg x2) Just (i,[x1,x2,x3]) | i == mkCId "Fold" -> GFold (fg x1) (fg x2) (fg x3) @@ -279,6 +285,7 @@ instance Gf GExpr where Just (i,[x1,x2]) | i == mkCId "FunApp" -> GFunApp (fg x1) (fg x2) Just (i,[x1,x2,x3]) | i == mkCId "IfThenElse" -> GIfThenElse (fg x1) (fg x2) (fg x3) Just (i,[x1,x2]) | i == mkCId "InstanceSumIf" -> GInstanceSumIf (fg x1) (fg x2) + Just (i,[x1]) | i == mkCId "Known" -> GKnown (fg x1) Just (i,[x1]) | i == mkCId "KnownFunction" -> GKnownFunction (fg x1) Just (i,[x1,x2]) | i == mkCId "Let" -> GLet (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "Lit" -> GLit (fg x1) @@ -355,7 +362,7 @@ instance Gf GMetadata where fg t = case unApp t of Just (i,[x1]) | i == mkCId "MkMetadata" -> GMkMetadata (fg x1) - Just (i,[]) | i == mkCId "NoMetadata" -> GNoMetadata + Just (i,[]) | i == mkCId "NoMetadata" -> GNoMetadata _ -> error ("no Metadata " ++ show t) @@ -396,7 +403,7 @@ instance Gf GS where case unApp t of Just (i,[x1,x2]) | i == mkCId "AssignS" -> GAssignS (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "AtomicConcept" -> GAtomicConcept (fg x1) - Just (i,[]) | i == mkCId "EmptyS" -> GEmptyS + Just (i,[]) | i == mkCId "EmptyS" -> GEmptyS Just (i,[x1]) | i == mkCId "EvalS" -> GEvalS (fg x1) Just (i,[x1]) | i == mkCId "EvalWhetherS" -> GEvalWhetherS (fg x1) Just (i,[x1]) | i == mkCId "ExprS" -> GExprS (fg x1) @@ -425,11 +432,11 @@ instance Gf GUnaryOp where fg t = case unApp t of - Just (i,[]) | i == mkCId "Ceiling" -> GCeiling - Just (i,[]) | i == mkCId "Floor" -> GFloor - Just (i,[]) | i == mkCId "IntegerToFraction" -> GIntegerToFraction - Just (i,[]) | i == mkCId "Not" -> GNot - Just (i,[]) | i == mkCId "UnaryMinus" -> GUnaryMinus + Just (i,[]) | i == mkCId "Ceiling" -> GCeiling + Just (i,[]) | i == mkCId "Floor" -> GFloor + Just (i,[]) | i == mkCId "IntegerToFraction" -> GIntegerToFraction + Just (i,[]) | i == mkCId "Not" -> GNot + Just (i,[]) | i == mkCId "UnaryMinus" -> GUnaryMinus _ -> error ("no UnaryOp " ++ show t) @@ -446,6 +453,7 @@ instance Gf GIfThen where instance Compos Tree where compos r a f t = case t of GBinExpr x1 x2 x3 -> r GBinExpr `a` f x1 `a` f x2 `a` f x3 + GCertain x1 -> r GCertain `a` f x1 GConjExpr x1 -> r GConjExpr `a` f x1 GElif x1 x2 -> r GElif `a` f x1 `a` f x2 GFold x1 x2 x3 -> r GFold `a` f x1 `a` f x2 `a` f x3 @@ -453,6 +461,7 @@ instance Compos Tree where GFunApp x1 x2 -> r GFunApp `a` f x1 `a` f x2 GIfThenElse x1 x2 x3 -> r GIfThenElse `a` f x1 `a` f x2 `a` f x3 GInstanceSumIf x1 x2 -> r GInstanceSumIf `a` f x1 `a` f x2 + GKnown x1 -> r GKnown `a` f x1 GKnownFunction x1 -> r GKnownFunction `a` f x1 GLet x1 x2 -> r GLet `a` f x1 `a` f x2 GLit x1 -> r GLit `a` f x1 diff --git a/lam4-backend/src/Lam4/Render/Render.hs b/lam4-backend/src/Lam4/Render/Render.hs index ec76b7cd..300d0889 100644 --- a/lam4-backend/src/Lam4/Render/Render.hs +++ b/lam4-backend/src/Lam4/Render/Render.hs @@ -102,7 +102,7 @@ parseDecl = \case else GExprS $ parseExpr name expr NonRec name (Sig [] []) -> GAtomicConcept (parseName name) NonRec name expr@(BinExpr binop _ _) -> - if comparisonOp binop + if booleanOp binop then GLetIsTrue (parseName name) $ parseExpr noName expr else GAssignS (parseName name) $ parseExpr noName expr NonRec name expr -> GAssignS (parseName name) $ parseExpr noName expr @@ -125,8 +125,13 @@ parseNameForRecord = GMkName . GString . T.unpack . rmThe . N.name commonFunction :: T.Text -> Bool commonFunction x = T.unpack x `elem` ["id", "map", "filter", "cons", "nil", "minus", "plus", "div", "mult", "add", "modulo", "pow", "round", "certain", "uncertain", "known", "unknown", "default", "instanceSumIf", "instanceSum"] -comparisonOp :: BinOp -> Bool -comparisonOp op = op `elem` [Eq, Lt, Gt, Le, Ge, Ne] +booleanOp :: BinOp -> Bool +booleanOp op = op `elem` [Eq, Lt, Gt, Le, Ge, Ne, And, Or] + +isPredicate :: Expr -> Bool +isPredicate = \case + Var (N.MkName name _ _) -> name `elem` ["certain", "known", "uncertain", "unknown"] + _ -> False ---- Tree transformations ----- @@ -137,12 +142,16 @@ quoteVars x = composOp quoteVars x -- Ground rule: binexpr is verbose if arguments are complex -- exception: if it's in if-then-else unVerboseBinExpr :: Tree a -> Tree a -unVerboseBinExpr (GVerboseBinExpr op l r) = - GQuotedBinExpr op - (quoteVarsBinExpr l) -- inner bin exprs become now quoted, even if they were unquoted previously - (quoteVarsBinExpr r) +unVerboseBinExpr (GVerboseBinExpr op l r) = GBinExpr op l r +-- GQuotedBinExpr op +-- (quoteVarsBinExpr l) -- inner bin exprs become now quoted, even if they were unquoted previously +-- (quoteVarsBinExpr r) unVerboseBinExpr x = composOp unVerboseBinExpr x +unVerboseNested :: Tree a -> Tree a +unVerboseNested (GVerboseBinExpr op l r) = GVerboseBinExpr op (unVerboseBinExpr l) (unVerboseBinExpr r) +unVerboseNested x = composOp unVerboseNested x + -- like above, but also forces concise BinExpr to be quoted quoteVarsBinExpr :: Tree a -> Tree a quoteVarsBinExpr (GVerboseBinExpr op l r) = GQuotedBinExpr op l r @@ -150,11 +159,22 @@ quoteVarsBinExpr (GBinExpr op l r) = GQuotedBinExpr op l r quoteVarsBinExpr x = composOp quoteVarsBinExpr x aggregatePredApp :: Tree a -> Tree a -aggregatePredApp tree@(GQuotedBinExpr op (GFunApp f arg) (GFunApp g arg')) = - if True -- sameTree arg arg' +aggregatePredApp tree@(GBinExpr op (GPredApp f arg) (GPredApp g arg')) = + if sameTree arg arg' then GPredAppMany op arg (GListExpr [f,g]) else tree - +aggregatePredApp tree@(GVerboseBinExpr op (GPredApp f arg) (GPredApp g arg')) = + if sameTree arg arg' + then GPredAppMany op arg (GListExpr [f,g]) + else tree +aggregatePredApp tree@(GBinExpr op (GFunApp f arg) (GFunApp g arg')) = + if sameTree arg arg' + then GPredAppMany op arg (GListExpr [f,g]) + else tree +aggregatePredApp tree@(GVerboseBinExpr op (GFunApp f arg) (GFunApp g arg')) = + if sameTree arg arg' + then GPredAppMany op arg (GListExpr [f,g]) + else tree aggregatePredApp x = composOp aggregatePredApp x -------------------------------- @@ -219,17 +239,23 @@ parseExpr name = -- e.g. "x / y" BinExpr op l@Var{} r@Var{} -> GBinExpr (parseBinOp op) (f l) (f r) - -- e.g. "x's z / y" + -- e.g. "a's x / y" BinExpr op l@Project{} r@Var{} -> GBinExpr (parseBinOp op) (f l) (f r) + -- e.g. "a's x / b's y" + BinExpr op l@Project{} r@Project{} -> GBinExpr (parseBinOp op) (f l) (f r) + -- other BinExprs are "verbose" = newlines and stuff BinExpr op l r -> GVerboseBinExpr (parseBinOp op) (f l) (f r) - IfThenElse cond thn els -> unVerboseBinExpr $ GIfThenElse (f cond) (f thn) (f els) + IfThenElse cond thn els -> unVerboseNested $ GIfThenElse (f cond) (f thn) (f els) FunApp (Var (N.MkName "instanceSumIf" _ _)) args -> parseInstanceSum args FunApp (Var (N.MkName "div" _ _)) [l,r] -> parseExpr name (BinExpr Divide l r) FunApp (Var (N.MkName "mult" _ _)) [l,r] -> parseExpr name (BinExpr Mult l r) FunApp (Var (N.MkName "add" _ _)) [l,r] -> parseExpr name (BinExpr Plus l r) - FunApp fun args -> GFunApp (f fun) (GListExpr $ fmap f args) + FunApp fun args -> if isPredicate fun + then parseExpr name (PredApp fun args) + else GFunApp (f fun) (GListExpr $ fmap f args) +-- FunApp fun args -> GFunApp (f fun) (GListExpr $ fmap f args) -- Record rows -> GRecord Project record label -> GProject (f record) (parseNameForRecord label) Fun md args body -> GFun (parseName name) (parseFunMetadata md) (GListName $ fmap parseName args) (f body) From 99949576aeafc8fdcaa6aae675e009f71d86077f Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Mon, 11 Nov 2024 16:28:13 +0100 Subject: [PATCH 05/14] flatten AND/OR, add CSS --- lam4-backend/gf-grammar/Lam4.gf | 14 +- lam4-backend/gf-grammar/Lam4.pgf | Bin 9375 -> 10753 bytes lam4-backend/gf-grammar/Lam4Eng.gf | 146 ++++++++++++------ lam4-backend/src/Lam4/Render/Lam4Gf.hs | 60 ++++++++ lam4-backend/src/Lam4/Render/Render.hs | 197 ++++++++++++++++++++----- 5 files changed, 332 insertions(+), 85 deletions(-) diff --git a/lam4-backend/gf-grammar/Lam4.gf b/lam4-backend/gf-grammar/Lam4.gf index a4188ed5..448f640b 100644 --- a/lam4-backend/gf-grammar/Lam4.gf +++ b/lam4-backend/gf-grammar/Lam4.gf @@ -14,6 +14,11 @@ abstract Lam4 = { Name ; [Name]{0} ; + -- Special values for aggregation + ListOp ; + LExpr ; + [LExpr]{2} ; + -- (condition, value) -- in order to flatten nested if-then-elses into if-elif-elif-…-else IfThen ; @@ -49,7 +54,11 @@ abstract Lam4 = { -- named differently because of a bug in GF, -- see https://github.com/GrammaticalFramework/gf-core/issues/163 ConjExpr : [Expr] -> Expr ; -- construct a list - -- ApplyListOp : ListOp -> [Expr] -> Expr ; + + coerceListExpr : Expr -> LExpr ; + ApplyListOp : ListOp -> [LExpr] -> Expr ; + + ListAnd, ListOr : ListOp ; Unary : UnaryOp -> Expr -> Expr ; VerboseBinExpr, -- newline + quotes around args @@ -79,7 +88,8 @@ abstract Lam4 = { where [the investment is in Energy] -} - InstanceSumIf : (entities : Expr) -> (condition : Expr)-> Expr ; + InstanceSumIf : (entities, condition : Expr)-> Expr ; + InstanceSum : (entities : Expr) -> Expr ; FunApp : Expr -> [Expr] -> Expr ; -- Record : (Row Expr) -> Expr ; -- record construction Project : Expr -> Name -> Expr ; -- record projection diff --git a/lam4-backend/gf-grammar/Lam4.pgf b/lam4-backend/gf-grammar/Lam4.pgf index 3d07e329a59788450f6319b0339ce96efdf0cb4b..848b6dfb48b906b8cc2210972e86934b805ebe46 100644 GIT binary patch literal 10753 zcmb^%*>W7m4d|Xd$>s7~9lqpCz9iB2C7LoNQ8F!3ltoEC6J@nKB*$9LtafHCGjZbN zF+Y&1>``KMM==hn6DYrC$mG?X@v>vM%PXF}Jc@*;mqo z;GSd98k$I?lm%)i$^t#8q_xR9uLgIo?f2dDZl?!L?%F0m!dsz<<^f36rI~dacRY;- zGI%REI@g6uOIDi(dM)_i&(u= zpuDvDS-ZETw~o@56`JJc_jlcB*By-KDzW4N%@=w>Fer39=R(lyDql9EFb;gc_~eD5 z??7dH==&TU(ilF3qMCnFppR*){Ev+uDg+159N)XXf@`sJv#!2;QvlR_E zDqF6b9yaBT+Z=&1jKqKJ=Q$sOzzi&2FzUp>@L089oWyS#qgxvCW^xonS zl5nS4j2TiggqrbYeJG~RoefDPm5M3VR-7Fh?&^wNM;418&cs<NDP8+4I~``IJs!FM;#X)bN;) zXK*{98Cn{E48;TwgD2s^5VE1bP~#nLP~O7^*4xft>8>#pvqKEdyTQOY&yUv}N|fT# zbvXGmm&k-5DYZ%vb5}%jhUfN!VN4^8F!#^oE}IbeCZa>V7PBu2iI{cCHGeUmd-=Hh0E`krR6GZMr3pn6tFlUoK@^V`^Dx*rh-mO1Vv!+f{~Oy(*{ z@l;5X43{OIAdu}P>omaT5`>IV!be;@KBf?ctdIpka7&5giL%X%ggX+SmC}n?Ju_LT z#M9F8PPwOuUa{#kdg(+|gVK{&8`owlK#3<0$5SaQ=YqXkl!($~4r$&58AVe#T&C{) zD3CIsrZUwNhVBU?QsT^YM@p(M$m(`{UyS8>P+FdbrdLbq$|H+7+k;?_M%N^sZjbs{ z>PE}Nw#Yw(ba`nN-qmEyV>o%9Gt45#Jdx4sEV+Bj$}w1q;f%0yr$y>hk$c?r{11`8 zAKCmUiwqaR;2!P9BD?QZyuj>nqIs(y&d64m!e|iqJG3ReZCP7dH0Xh|K1PK@&gG9) zk~d_W5|=AD<1EQLPu3~*c1Yd%-bR-s_inf+-SR(k`xQ3JC8WzVjERAb; zYh1(fmS@3##{BFfzgRri8B~ejL$g+E9*zSeQ zPW#v8)Ph1DPoy@^Nr|#Tp@UyB(pKtio0Cu#kW_rA>z2E1I-}ZQ7<4>!MmcxAXqUQ-z+w7;qig9dNeOa%t*c#W6bZf5tn2a=`BonP{NG4iaG#mGr>8*%})tGY& zTPc|IZ?4>F{|N=BVo6o^XNn2GxEDT|9f0YU|>~D^}T!F8BF&xe2ZZ;TAo$ zi5IS^vb%Whys0Z=J%Q#EsAgB0@$C$DCWF0|!IsiWG`?oR3l{vUsZHZdQkBM6vh`?O zjw{hP$u(%4R^O)jI_fK}*CN!lX)IZ_E_@&@QRABx^L%q!J)4#Y<|NKEaApeUnm9L&3p2Pdi-+d$$UHu^V- zg~L!I^lc5+30%?O1c7I{PUgTl{wcwE{wc#nBmNGnT~nnrxWw=}lD^9V<_W&aaECwq z=toL+wGvM&`IK!tME`DUpbR|*%0$`IKpE(Nrx^2s)VzLb-W}F83$#0DA!I2wf}Tfb z>1Qb52r2uFf68!Izyx8R^G_LmE}%s$UoiVG`SUB*@MWw)BK(?*g$}}#P(nDR>@N#g z)FXIaji4&vIOX;9?*;y;))1b8I>L+GeQiR(OAOTEW&W9%M7RPCg!fi}=^m`?L&i9egVbsu42!GVvp{1kkmfhPP!E1H6zYM|LF!LtBw0lW*)1^5LVBCp5N zVS&>)bA&EsSU1m!AZp<;ddcW`p-WKwps8L<+51ENqVpdfl==`Ue$=6zgdxA@{FfWm zhxt{CBPD^!vyD?0B78xFFIsOhl?rjB4=vTIsE5a{a2`WPIT@nB%|Y^{LMx(m#P21O z4U*5lg-kWMTa&m<&k&~GDrRR1vfm}<=7@k>^Yio**Y?%AsSnYT^8UgCVH9iBe-&)C H2s!$H-)>7_ delta 2849 zcmZWrOKjZM6}|WIH$%=}k|kNT^|NGs>?pQl$F^k2`q~p~B-ta`Nz9q)dAk9ShFVaGU&&tCQz9(PK zx6??j8eY-ebehJK#xVVt+?#B7kX8C5(RpxA`3AMNN?5Z!dPD4@gUOd7UvDN~iSXZ& z>k*z-&qUZ%Peu4$^-6@lQb!~FZ*?-lXSMZ0JEpp2>CS%1w3@CT`XjABOh?(W_Gn7( zO@!%DTkVN_q*7PIjvU=j{l3*V*S1sG)-3<9;Y57Va6H|#LY`Q(t%q>~ak*x0hrQy8 zU8{yfSZPMXWQOM(jj&5CZg1`y)^g1?d{v9>dAex1o^Dl)aH?%EE{d36(~x&wI4c4awD^%dqIXQ zK{m{OXjCHii91c(Gw$ipTBUtO^{Ew@;`TNJ%MgP<%x7h5DtTx}p z`22-fG%9CTsGDujzTBmQALj-L-aGiPkis+yID!Hh9c5sG{-$FuJ;~5H_Dr#7hW2*; z>EP94KSes$^G-_?#2KSLD@b~^YE%W{*@84P#Wn2?LAR=HRcNbJ&DTxe`oaEFU9$10 zsn^_?AF1t!n69AgI0jo#M-aVT-Qq)47AX-}(0`m5ZUwR9W5k-_x`zXpy%O^n??}O3Sb7wKCpH@%H|%;q4ku8H*B+QAU(jYPRj* z3w}YsAzlh_$(Jj>T&CIK{*gQ9$W4zdo{g0QJbknd;2Ek9_sw2Adh=Nps|MMa;x`}V z!!nH{{Qe`7RgVllBl(q)^glT~s%v)1@M!(?sqAgC?vT}s;zq6Ml2c>!=cgxI^IE$c z@#=#&jPY z89CM(PP6wkTT+6efU=AU1yvPODa>Rrm&HO3JM(y~fIS_|3faL$NkBzJMM6c!q=H%k zwIpgPrZr5bFq_6~2J>0$$YEC=y9?Oc328VEa1LM!U>aZsU;$tS;3h!pEO5+MVfpfGwlfC&bl4`7nPD})IFuJT5NYrK)* zdN_QRbA%gQ%wvoBS|pHTWEmO0$Hn)!i2yJ2MuhM4MuJy(ULEZJY5*ko0S6M(ycPfn z^uyF19Hv$|Os&d&Wx(KKn~!SoGI%XsNFa>yFiMiZI0p%sU`-2>DndVK1SSb&L4~ut z(NYLokVd$L@L%?8We|#Om=)m#0x9O=HeoxPfmOk087K)p&*T!&7fk5{&+-|7XL-u! zxwyc^QqWsNxSh|7uogH_VLbpEYy_TExDx=aAi*HOMSwYg`v4Yn5H@SElOTH~b`exC zk)wYYyWdKzny$yolpqn}o+s`Fm1}}85_Z1P^)1%)y1|wru*h7SBn{DvrK{IT#hwz*<;@!^xN_7j(nbRcF)+?+j^r=VC2~U0A^qTXaE2J diff --git a/lam4-backend/gf-grammar/Lam4Eng.gf b/lam4-backend/gf-grammar/Lam4Eng.gf index 88167779..65cb8c0f 100644 --- a/lam4-backend/gf-grammar/Lam4Eng.gf +++ b/lam4-backend/gf-grammar/Lam4Eng.gf @@ -7,9 +7,13 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { ListExpr = ListX0 ; ListName = ListX0 ; BinOp = {s : Verbosity => Str} ; + ListLExpr = LinLExpr ; + ListOp = LinListOp ; + param IsEmpty = Empty | NonEmpty ; MyListSize = Zero | One | Many ; + PListOp = PListAnd | PListOr ; Verbosity = Concise | Verbose ; Hilight = Strong | Emph | Underline ; @@ -37,50 +41,10 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { ifKw : Str = hilight Strong "if" ; thenKw : Str = hilight Strong "then" ; elseKw : Str = hilight Strong "else" ; - - -- List operations - ListX0 : Type = ListX ** {size : MyListSize} ; - - baseListX0 : ListX0 = { - s1, s2 = "" ; - size = Zero - } ; - - -- twoStr : (x,y : Str) -> ListX = \x,y -> - -- {s1 = x ; s2 = y} ; - -- consStr : Str -> ListX -> Str -> ListX = \comma,xs,x -> - -- {s1 = xs.s1 ++ comma ++ xs.s2 ; s2 = x } ; - - - - conslListX0 : SS -> ListX0 -> ListX0 = \x,xs -> case xs.size of { - Many => xs ** { - s1 = xs.s1 ++ bindComma ++ xs.s2 ; - s2 = x.s - } ; - One => xs ** { - s2 = x.s ; - size = Many - } ; - Zero => xs ** { - s1 = x.s ; - size = One - } - } ; - - consrListX0 : SS -> ListX0 -> ListX0 = \x,xs -> case xs.size of { - Many => xs ** { - s1 = x.s ++ bindComma ++ xs.s1 ; - } ; - One => xs ** { - s1 = x.s ; - size = Many - } ; - Zero => xs ** { - s2 = x.s ; - size = One - } - } ; + andKw : Str = hilight Emph "and" ; + orKw : Str = hilight Emph "or" ; + allKw : Str = hilight Strong (hilight Emph "all of") ; + anyKw : Str = hilight Strong (hilight Emph "any of") ; LinMetadata : Type = {s : Str ; isEmpty : IsEmpty} ; linRowMd : LinMetadata -> Str = \md -> @@ -190,8 +154,8 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { mkBinExpr : Str -> Str -> {s : Verbosity => Str} ; mkBinExpr short long = { s = table { - Concise => short ; - Verbose => hilight Emph long } + Concise => hilight Strong short ; + Verbose => long } } ; -- ul = overload { @@ -275,8 +239,13 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { -- : Expr -> Expr -> Expr ; InstanceSumIf entities condition = { - s = dl "adding up those of" (quote entities.s) - ++ dl "where" (quote condition.s) + s = dl "adding up those of" entities.s + ++ dl "where" condition.s + } ; + + -- : Expr -> Expr ; + InstanceSum entities = { + s = dl "adding up" entities.s } ; -- : Expr -> [Expr] -> Expr ; @@ -369,9 +338,90 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { Eq = mkBinExpr "=" "equals to" ; Ne = mkBinExpr "≠" "is not equal to" ; + +------------------------- + -- List operations + oper + ListX0 : Type = ListX ** {size : MyListSize} ; + + baseListX0 : ListX0 = { + s1, s2 = "" ; + size = Zero + } ; + + conslListX0 : SS -> ListX0 -> ListX0 = \x,xs -> case xs.size of { + Many => xs ** { + s1 = xs.s1 ++ bindComma ++ xs.s2 ; + s2 = x.s + } ; + One => xs ** { + s2 = x.s ; + size = Many + } ; + Zero => xs ** { + s1 = x.s ; + size = One + } + } ; + + consrListX0 : SS -> ListX0 -> ListX0 = \x,xs -> case xs.size of { + Many => xs ** { + s1 = x.s ++ bindComma ++ xs.s1 ; + } ; + One => xs ** { + s1 = x.s ; + size = Many + } ; + Zero => xs ** { + s2 = x.s ; + size = One + } + } ; + + -- Special for flattening nested And/Or + LinLExpr : Type = {s : PListOp => Str} ; + LinListOp : Type = {s : Str ; op : PListOp} ; + + conjTable : PListOp => Str = table { + PListAnd => andKw ; + PListOr => orKw } ; + + headerTable : PListOp => Str = table { + PListAnd => allKw ; + PListOr => anyKw } ; + + baseLExpr : SS -> SS -> LinLExpr = \s1,s2 -> { + s = \\conj => + dl (conjTable ! conj) s1.s + ++ + dl (conjTable ! conj) s2.s + + } ; + + consLExpr : SS -> LinLExpr -> LinLExpr = \s,ss -> ss ** { + s = \\conj => + dl (conjTable ! conj) s.s + ++ + ss.s ! conj + + } ; + + conjLExpr : LinListOp -> LinLExpr -> SS = \co,ss -> { + s = ss.s ! co.op + } ; + +lin BaseExpr, BaseName = baseListX0 ; ConsExpr, ConsName = consrListX0 ; ConjExpr = conjXss ; + + BaseLExpr = baseLExpr ; + ConsLExpr = consLExpr ; + ApplyListOp = conjLExpr ; + + ListAnd = {s = "" ; op = PListAnd} ; + ListOr = {s = "" ; op = PListOr} ; + coerceListExpr = id SS ; } {- diff --git a/lam4-backend/src/Lam4/Render/Lam4Gf.hs b/lam4-backend/src/Lam4/Render/Lam4Gf.hs index d4a6932e..3811afee 100644 --- a/lam4-backend/src/Lam4/Render/Lam4Gf.hs +++ b/lam4-backend/src/Lam4/Render/Lam4Gf.hs @@ -44,12 +44,18 @@ type GBinOp = Tree GBinOp_ data GBinOp_ type GExpr = Tree GExpr_ data GExpr_ +type GLExpr = Tree GLExpr_ +data GLExpr_ type GListExpr = Tree GListExpr_ data GListExpr_ type GListIfThen = Tree GListIfThen_ data GListIfThen_ +type GListLExpr = Tree GListLExpr_ +data GListLExpr_ type GListName = Tree GListName_ data GListName_ +type GListOp = Tree GListOp_ +data GListOp_ type GListRowTypeDecl = Tree GListRowTypeDecl_ data GListRowTypeDecl_ type GMetadata = Tree GMetadata_ @@ -87,6 +93,7 @@ data Tree :: * -> * where GNe :: Tree GBinOp_ GOr :: Tree GBinOp_ GPlus :: Tree GBinOp_ + GApplyListOp :: GListOp -> GListLExpr -> Tree GExpr_ GBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ GCertain :: GExpr -> Tree GExpr_ GConjExpr :: GListExpr -> Tree GExpr_ @@ -95,6 +102,7 @@ data Tree :: * -> * where GFun :: GName -> GMetadata -> GListName -> GExpr -> Tree GExpr_ GFunApp :: GExpr -> GListExpr -> Tree GExpr_ GIfThenElse :: GExpr -> GExpr -> GExpr -> Tree GExpr_ + GInstanceSum :: GExpr -> Tree GExpr_ GInstanceSumIf :: GExpr -> GExpr -> Tree GExpr_ GKnown :: GExpr -> Tree GExpr_ GKnownFunction :: GName -> Tree GExpr_ @@ -114,9 +122,13 @@ data Tree :: * -> * where GUnknown :: GExpr -> Tree GExpr_ GVar :: GName -> Tree GExpr_ GVerboseBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ + GcoerceListExpr :: GExpr -> Tree GLExpr_ GListExpr :: [GExpr] -> Tree GListExpr_ GListIfThen :: [GIfThen] -> Tree GListIfThen_ + GListLExpr :: [GLExpr] -> Tree GListLExpr_ GListName :: [GName] -> Tree GListName_ + GListAnd :: Tree GListOp_ + GListOr :: Tree GListOp_ GListRowTypeDecl :: [GRowTypeDecl] -> Tree GListRowTypeDecl_ GMkMetadata :: GString -> Tree GMetadata_ GNoMetadata :: Tree GMetadata_ @@ -156,6 +168,7 @@ instance Eq (Tree a) where (GNe,GNe) -> and [ ] (GOr,GOr) -> and [ ] (GPlus,GPlus) -> and [ ] + (GApplyListOp x1 x2,GApplyListOp y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GBinExpr x1 x2 x3,GBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GCertain x1,GCertain y1) -> and [ x1 == y1 ] (GConjExpr x1,GConjExpr y1) -> and [ x1 == y1 ] @@ -164,6 +177,7 @@ instance Eq (Tree a) where (GFun x1 x2 x3 x4,GFun y1 y2 y3 y4) -> and [ x1 == y1 , x2 == y2 , x3 == y3 , x4 == y4 ] (GFunApp x1 x2,GFunApp y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GIfThenElse x1 x2 x3,GIfThenElse y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] + (GInstanceSum x1,GInstanceSum y1) -> and [ x1 == y1 ] (GInstanceSumIf x1 x2,GInstanceSumIf y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GKnown x1,GKnown y1) -> and [ x1 == y1 ] (GKnownFunction x1,GKnownFunction y1) -> and [ x1 == y1 ] @@ -183,9 +197,13 @@ instance Eq (Tree a) where (GUnknown x1,GUnknown y1) -> and [ x1 == y1 ] (GVar x1,GVar y1) -> and [ x1 == y1 ] (GVerboseBinExpr x1 x2 x3,GVerboseBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] + (GcoerceListExpr x1,GcoerceListExpr y1) -> and [ x1 == y1 ] (GListExpr x1,GListExpr y1) -> and [x == y | (x,y) <- zip x1 y1] (GListIfThen x1,GListIfThen y1) -> and [x == y | (x,y) <- zip x1 y1] + (GListLExpr x1,GListLExpr y1) -> and [x == y | (x,y) <- zip x1 y1] (GListName x1,GListName y1) -> and [x == y | (x,y) <- zip x1 y1] + (GListAnd,GListAnd) -> and [ ] + (GListOr,GListOr) -> and [ ] (GListRowTypeDecl x1,GListRowTypeDecl y1) -> and [x == y | (x,y) <- zip x1 y1] (GMkMetadata x1,GMkMetadata y1) -> and [ x1 == y1 ] (GNoMetadata,GNoMetadata) -> and [ ] @@ -246,6 +264,7 @@ instance Gf GBinOp where _ -> error ("no BinOp " ++ show t) instance Gf GExpr where + gf (GApplyListOp x1 x2) = mkApp (mkCId "ApplyListOp") [gf x1, gf x2] gf (GBinExpr x1 x2 x3) = mkApp (mkCId "BinExpr") [gf x1, gf x2, gf x3] gf (GCertain x1) = mkApp (mkCId "Certain") [gf x1] gf (GConjExpr x1) = mkApp (mkCId "ConjExpr") [gf x1] @@ -254,6 +273,7 @@ instance Gf GExpr where gf (GFun x1 x2 x3 x4) = mkApp (mkCId "Fun") [gf x1, gf x2, gf x3, gf x4] gf (GFunApp x1 x2) = mkApp (mkCId "FunApp") [gf x1, gf x2] gf (GIfThenElse x1 x2 x3) = mkApp (mkCId "IfThenElse") [gf x1, gf x2, gf x3] + gf (GInstanceSum x1) = mkApp (mkCId "InstanceSum") [gf x1] gf (GInstanceSumIf x1 x2) = mkApp (mkCId "InstanceSumIf") [gf x1, gf x2] gf (GKnown x1) = mkApp (mkCId "Known") [gf x1] gf (GKnownFunction x1) = mkApp (mkCId "KnownFunction") [gf x1] @@ -276,6 +296,7 @@ instance Gf GExpr where fg t = case unApp t of + Just (i,[x1,x2]) | i == mkCId "ApplyListOp" -> GApplyListOp (fg x1) (fg x2) Just (i,[x1,x2,x3]) | i == mkCId "BinExpr" -> GBinExpr (fg x1) (fg x2) (fg x3) Just (i,[x1]) | i == mkCId "Certain" -> GCertain (fg x1) Just (i,[x1]) | i == mkCId "ConjExpr" -> GConjExpr (fg x1) @@ -284,6 +305,7 @@ instance Gf GExpr where Just (i,[x1,x2,x3,x4]) | i == mkCId "Fun" -> GFun (fg x1) (fg x2) (fg x3) (fg x4) Just (i,[x1,x2]) | i == mkCId "FunApp" -> GFunApp (fg x1) (fg x2) Just (i,[x1,x2,x3]) | i == mkCId "IfThenElse" -> GIfThenElse (fg x1) (fg x2) (fg x3) + Just (i,[x1]) | i == mkCId "InstanceSum" -> GInstanceSum (fg x1) Just (i,[x1,x2]) | i == mkCId "InstanceSumIf" -> GInstanceSumIf (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "Known" -> GKnown (fg x1) Just (i,[x1]) | i == mkCId "KnownFunction" -> GKnownFunction (fg x1) @@ -307,6 +329,16 @@ instance Gf GExpr where _ -> error ("no Expr " ++ show t) +instance Gf GLExpr where + gf (GcoerceListExpr x1) = mkApp (mkCId "coerceListExpr") [gf x1] + + fg t = + case unApp t of + Just (i,[x1]) | i == mkCId "coerceListExpr" -> GcoerceListExpr (fg x1) + + + _ -> error ("no LExpr " ++ show t) + instance Gf GListExpr where gf (GListExpr []) = mkApp (mkCId "BaseExpr") [] gf (GListExpr (x:xs)) = mkApp (mkCId "ConsExpr") [gf x, gf (GListExpr xs)] @@ -331,6 +363,18 @@ instance Gf GListIfThen where _ -> error ("no ListIfThen " ++ show t) +instance Gf GListLExpr where + gf (GListLExpr [x1,x2]) = mkApp (mkCId "BaseLExpr") [gf x1, gf x2] + gf (GListLExpr (x:xs)) = mkApp (mkCId "ConsLExpr") [gf x, gf (GListLExpr xs)] + fg t = + GListLExpr (fgs t) where + fgs t = case unApp t of + Just (i,[x1,x2]) | i == mkCId "BaseLExpr" -> [fg x1, fg x2] + Just (i,[x1,x2]) | i == mkCId "ConsLExpr" -> fg x1 : fgs x2 + + + _ -> error ("no ListLExpr " ++ show t) + instance Gf GListName where gf (GListName []) = mkApp (mkCId "BaseName") [] gf (GListName (x:xs)) = mkApp (mkCId "ConsName") [gf x, gf (GListName xs)] @@ -343,6 +387,18 @@ instance Gf GListName where _ -> error ("no ListName " ++ show t) +instance Gf GListOp where + gf GListAnd = mkApp (mkCId "ListAnd") [] + gf GListOr = mkApp (mkCId "ListOr") [] + + fg t = + case unApp t of + Just (i,[]) | i == mkCId "ListAnd" -> GListAnd + Just (i,[]) | i == mkCId "ListOr" -> GListOr + + + _ -> error ("no ListOp " ++ show t) + instance Gf GListRowTypeDecl where gf (GListRowTypeDecl []) = mkApp (mkCId "BaseRowTypeDecl") [] gf (GListRowTypeDecl (x:xs)) = mkApp (mkCId "ConsRowTypeDecl") [gf x, gf (GListRowTypeDecl xs)] @@ -452,6 +508,7 @@ instance Gf GIfThen where instance Compos Tree where compos r a f t = case t of + GApplyListOp x1 x2 -> r GApplyListOp `a` f x1 `a` f x2 GBinExpr x1 x2 x3 -> r GBinExpr `a` f x1 `a` f x2 `a` f x3 GCertain x1 -> r GCertain `a` f x1 GConjExpr x1 -> r GConjExpr `a` f x1 @@ -460,6 +517,7 @@ instance Compos Tree where GFun x1 x2 x3 x4 -> r GFun `a` f x1 `a` f x2 `a` f x3 `a` f x4 GFunApp x1 x2 -> r GFunApp `a` f x1 `a` f x2 GIfThenElse x1 x2 x3 -> r GIfThenElse `a` f x1 `a` f x2 `a` f x3 + GInstanceSum x1 -> r GInstanceSum `a` f x1 GInstanceSumIf x1 x2 -> r GInstanceSumIf `a` f x1 `a` f x2 GKnown x1 -> r GKnown `a` f x1 GKnownFunction x1 -> r GKnownFunction `a` f x1 @@ -479,6 +537,7 @@ instance Compos Tree where GUnknown x1 -> r GUnknown `a` f x1 GVar x1 -> r GVar `a` f x1 GVerboseBinExpr x1 x2 x3 -> r GVerboseBinExpr `a` f x1 `a` f x2 `a` f x3 + GcoerceListExpr x1 -> r GcoerceListExpr `a` f x1 GMkMetadata x1 -> r GMkMetadata `a` f x1 GMkName x1 -> r GMkName `a` f x1 GMkRowDecl x1 x2 -> r GMkRowDecl `a` f x1 `a` f x2 @@ -493,6 +552,7 @@ instance Compos Tree where GMkTypeDecl x1 x2 x3 -> r GMkTypeDecl `a` f x1 `a` f x2 `a` f x3 GListExpr x1 -> r GListExpr `a` foldr (a . a (r (:)) . f) (r []) x1 GListIfThen x1 -> r GListIfThen `a` foldr (a . a (r (:)) . f) (r []) x1 + GListLExpr x1 -> r GListLExpr `a` foldr (a . a (r (:)) . f) (r []) x1 GListName x1 -> r GListName `a` foldr (a . a (r (:)) . f) (r []) x1 GListRowTypeDecl x1 -> r GListRowTypeDecl `a` foldr (a . a (r (:)) . f) (r []) x1 _ -> r t diff --git a/lam4-backend/src/Lam4/Render/Render.hs b/lam4-backend/src/Lam4/Render/Render.hs index 300d0889..2dc7d0fe 100644 --- a/lam4-backend/src/Lam4/Render/Render.hs +++ b/lam4-backend/src/Lam4/Render/Render.hs @@ -8,6 +8,7 @@ import qualified Base.Text as T import Control.Lens ((%~), (&)) import Control.Lens.Regex.Text (match, regex) import Data.String.Interpolate (i) +import Text.RawString.QQ import Lam4.Expr.CommonSyntax import Lam4.Expr.ConcreteSyntax import qualified Lam4.Expr.Name as N (Name (..), ReferentStatus (..)) @@ -82,16 +83,111 @@ postprocessText = newlines . tabs . rmBIND newlines :: T.Text -> T.Text newlines = T.map (\c -> if c == '∞' then '\n' else c) +style = [r| + + +|] + -- | Entrypoint renderCstProgramToNL :: NLGEnv -> CSTProgram -> T.Text -renderCstProgramToNL env decls = T.unlines $ - fmap (renderCstDeclToNL env) decls <> fmap (renderCstDeclToGFtrees env) decls +renderCstProgramToNL env decls = T.unlines ( + ["", "", style, "", ""] <> + fmap (renderCstDeclToNL env) decls <> + ["", ""] + + <> fmap (renderCstDeclToGFtrees env) decls) renderCstDeclToNL :: NLGEnv -> Decl -> T.Text -renderCstDeclToNL env = gfLin env . gf . aggregatePredApp . parseDecl +renderCstDeclToNL env = gfLin env . gf . genericTreeTrans . parseDecl renderCstDeclToGFtrees :: NLGEnv -> Decl -> T.Text -renderCstDeclToGFtrees env = gfTree env . gf . aggregatePredApp . parseDecl +renderCstDeclToGFtrees env = gfTree env . gf . genericTreeTrans . parseDecl parseDecl :: Decl -> GS parseDecl = \case @@ -133,31 +229,31 @@ isPredicate = \case Var (N.MkName name _ _) -> name `elem` ["certain", "known", "uncertain", "unknown"] _ -> False +varFromFun :: Expr -> Expr +varFromFun = \case + Fun _md _args (Project _rec label) -> Var label + e -> e ---- Tree transformations ----- +genericTreeTrans :: Tree a -> Tree a +genericTreeTrans = flattenNestedAndOr . aggregatePredApp . binExprVerbosity + quoteVars :: Tree a -> Tree a quoteVars (GVar x) = GQuoteVar x quoteVars x = composOp quoteVars x --- Ground rule: binexpr is verbose if arguments are complex --- exception: if it's in if-then-else +-- Control verbosity of BinExpr in specific contexts +binExprVerbosity :: Tree a -> Tree a +binExprVerbosity (GAssignS e (GBinExpr op lc rc)) = GAssignS e (GVerboseBinExpr op (unVerboseBinExpr lc) (unVerboseBinExpr rc)) +binExprVerbosity (GLetIsTrue e (GBinExpr op lc rc)) = GLetIsTrue e (GVerboseBinExpr op (unVerboseBinExpr lc) (unVerboseBinExpr rc)) +binExprVerbosity (GVerboseBinExpr op lc rc) = GVerboseBinExpr op (unVerboseBinExpr lc) (unVerboseBinExpr rc) +binExprVerbosity x = composOp binExprVerbosity x + +-- helper function for binExprVerbosity unVerboseBinExpr :: Tree a -> Tree a -unVerboseBinExpr (GVerboseBinExpr op l r) = GBinExpr op l r --- GQuotedBinExpr op --- (quoteVarsBinExpr l) -- inner bin exprs become now quoted, even if they were unquoted previously --- (quoteVarsBinExpr r) +unVerboseBinExpr (GVerboseBinExpr op lc rc) = GBinExpr op lc rc unVerboseBinExpr x = composOp unVerboseBinExpr x -unVerboseNested :: Tree a -> Tree a -unVerboseNested (GVerboseBinExpr op l r) = GVerboseBinExpr op (unVerboseBinExpr l) (unVerboseBinExpr r) -unVerboseNested x = composOp unVerboseNested x - --- like above, but also forces concise BinExpr to be quoted -quoteVarsBinExpr :: Tree a -> Tree a -quoteVarsBinExpr (GVerboseBinExpr op l r) = GQuotedBinExpr op l r -quoteVarsBinExpr (GBinExpr op l r) = GQuotedBinExpr op l r -quoteVarsBinExpr x = composOp quoteVarsBinExpr x - aggregatePredApp :: Tree a -> Tree a aggregatePredApp tree@(GBinExpr op (GPredApp f arg) (GPredApp g arg')) = if sameTree arg arg' @@ -177,6 +273,34 @@ aggregatePredApp tree@(GVerboseBinExpr op (GFunApp f arg) (GFunApp g arg')) = else tree aggregatePredApp x = composOp aggregatePredApp x +flattenNestedAndOr :: Tree a -> Tree a +flattenNestedAndOr e@GBinExpr{} = composOp flattenNestedAndOr (flattenIfLongEnough e) +flattenNestedAndOr e@GVerboseBinExpr{} = composOp flattenNestedAndOr (flattenIfLongEnough e) +flattenNestedAndOr x = composOp flattenNestedAndOr x + +flattenIfLongEnough :: GExpr -> GExpr +flattenIfLongEnough e = + case orExprs of + (_:_:_) -> GApplyListOp GListOr (GListLExpr orExprs) + _ -> case andExprs of + (_:_:_) -> GApplyListOp GListAnd (GListLExpr andExprs) + _ -> e + where + orExprs = GcoerceListExpr <$> collectOr e + andExprs = GcoerceListExpr <$> collectAnd e + + collectOr :: GExpr -> [GExpr] + collectOr = \case + GBinExpr GOr left right -> collectOr left <> collectOr right + GVerboseBinExpr GOr left right -> collectOr left <> collectOr right + expr -> [expr] + + collectAnd :: GExpr -> [GExpr] + collectAnd = \case + GBinExpr GAnd left right -> collectAnd left <> collectAnd right + GVerboseBinExpr GAnd left right -> collectAnd left <> collectAnd right + expr -> [expr] + -------------------------------- sameTree :: forall a. Gf (Tree a) => Tree a -> Tree a -> Bool @@ -237,21 +361,25 @@ parseExpr name = Lit lit -> GLit (parseLit lit) Unary op expr -> GUnary (parseUnaOp op) (f expr) -- e.g. "x / y" - BinExpr op l@Var{} r@Var{} -> GBinExpr (parseBinOp op) (f l) (f r) + BinExpr op lc@Var{} rc@Var{} -> GBinExpr (parseBinOp op) (f lc) (f rc) + + -- e.g. "x / b's y" + BinExpr op lc@Var{} rc@Project{} -> GBinExpr (parseBinOp op) (f lc) (f rc) -- e.g. "a's x / y" - BinExpr op l@Project{} r@Var{} -> GBinExpr (parseBinOp op) (f l) (f r) + BinExpr op lc@Project{} rc@Var{} -> GBinExpr (parseBinOp op) (f lc) (f rc) -- e.g. "a's x / b's y" - BinExpr op l@Project{} r@Project{} -> GBinExpr (parseBinOp op) (f l) (f r) + BinExpr op lc@Project{} rc@Project{} -> GBinExpr (parseBinOp op) (f lc) (f rc) -- other BinExprs are "verbose" = newlines and stuff - BinExpr op l r -> GVerboseBinExpr (parseBinOp op) (f l) (f r) - IfThenElse cond thn els -> unVerboseNested $ GIfThenElse (f cond) (f thn) (f els) + BinExpr op lc rc -> GVerboseBinExpr (parseBinOp op) (f lc) (f rc) + IfThenElse cond thn els -> GIfThenElse (f cond) (f thn) (f els) FunApp (Var (N.MkName "instanceSumIf" _ _)) args -> parseInstanceSum args - FunApp (Var (N.MkName "div" _ _)) [l,r] -> parseExpr name (BinExpr Divide l r) - FunApp (Var (N.MkName "mult" _ _)) [l,r] -> parseExpr name (BinExpr Mult l r) - FunApp (Var (N.MkName "add" _ _)) [l,r] -> parseExpr name (BinExpr Plus l r) + FunApp (Var (N.MkName "instanceSum" _ _)) args -> parseInstanceSum args + FunApp (Var (N.MkName "div" _ _)) [lc,rc] -> parseExpr name (BinExpr Divide lc rc) + FunApp (Var (N.MkName "mult" _ _)) [lc,rc] -> parseExpr name (BinExpr Mult lc rc) + FunApp (Var (N.MkName "add" _ _)) [lc,rc] -> parseExpr name (BinExpr Plus lc rc) FunApp fun args -> if isPredicate fun then parseExpr name (PredApp fun args) else GFunApp (f fun) (GListExpr $ fmap f args) @@ -274,13 +402,12 @@ parseExpr name = parseInstanceSum :: [Expr] -> GExpr parseInstanceSum [_set, inst, cond] = GInstanceSumIf instExpr condExpr - where - instExpr = parseExpr noName $ varFromFun inst - condExpr = parseExpr noName $ varFromFun cond - varFromFun :: Expr -> Expr - varFromFun = \case - Fun _md _args (Project _rec label) -> Var label - e -> e + where + instExpr = parseExpr noName $ varFromFun inst + condExpr = parseExpr noName $ varFromFun cond +parseInstanceSum [_set, inst] = GInstanceSum instExpr + where + instExpr = parseExpr noName $ varFromFun inst parseInstanceSum _ = GKnownFunction $ GMkName $ GString "SOMETHING WENT WRONG D:" parseRecordRow :: (N.Name, Expr) -> GExpr From 29aadfc2101620f733b954b5c694dfe1da9d2c0b Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Mon, 11 Nov 2024 16:49:17 +0100 Subject: [PATCH 06/14] add special functions for Round and Default --- lam4-backend/gf-grammar/Lam4.gf | 2 ++ lam4-backend/gf-grammar/Lam4.pgf | Bin 10753 -> 11060 bytes lam4-backend/gf-grammar/Lam4Eng.gf | 19 ++++++++++++++++--- lam4-backend/src/Lam4/Render/Lam4Gf.hs | 10 ++++++++++ lam4-backend/src/Lam4/Render/Render.hs | 11 +++++++++++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lam4-backend/gf-grammar/Lam4.gf b/lam4-backend/gf-grammar/Lam4.gf index 448f640b..59d52c20 100644 --- a/lam4-backend/gf-grammar/Lam4.gf +++ b/lam4-backend/gf-grammar/Lam4.gf @@ -66,6 +66,8 @@ abstract Lam4 = { BinExpr : BinOp -> Expr -> Expr -> Expr ; Known, Certain, Unknown, Uncertain : Expr -> Expr ; + Round : (expr, prec : Expr) -> Expr ; + Default : (val, default : Expr) -> Expr ; -- TODO: get rid of all nested IfThenElses IfThenElse : Expr -> Expr -> Expr -> Expr ; diff --git a/lam4-backend/gf-grammar/Lam4.pgf b/lam4-backend/gf-grammar/Lam4.pgf index 848b6dfb48b906b8cc2210972e86934b805ebe46..3063f331808e670b3f15c1991ca5c440ed8c7533 100644 GIT binary patch delta 2995 zcmaJ@OKcm*8UFv-2VbHnQY(pilCmVrc9b}M#PLI+tp{Z@CiS8u$F-egO|GQ1s9k!w zw4B)z_5@xf=F|*wUierx^1Y|QAszN4X4;&#xni~2yGh&v_~Ee`yYs!(R2`_r{_|Di#>m9 zW&FE|E!69^qoUrh*Xq74w5S{WW&^&YS+=ShJ`XRM#)A_ZyteQ+i20hn8;}*VR`rRn z(&S-UPTR?hu=M^~w6MFiuNnDTL-S3sg3+*5qoS3YhrTV|Wh(?(q??BMIH)l0Fc!XI z>tp^HvJ;KGcZAq)BUtG zm^`O+#}J6V%WEZiLx{4wc28kW5N*~*^xEJAtqt^w8tW(8J227yEd4|5iwnYhGbb@O ziG@1fq#Gk+^hYBj?e|6&k&cfI(|?YR_e%5kt@Akn|L_|SAV&W@npUJe{gGw>K>_Ck z+0yK$Wwf`)6e0Bk?5XJn)4(jd(6u^I6#8~%3>Esb%s3l=o0*6x{tmj4?Wh0BNPN@3 zGc#;?JbRjxe0G{o2iZwxdoO#2jX%$(>7TMGhW?t(un{Lu<&>0{YSVnYbyU}uwMq>! z>>10bbRZ@?Yp_qD>g1_?rPs4NU9?tbm%6~z>ACCOQhz_Fk(c#HdQ~Im3v&Lj zZXcBqNd6)D+N)BYy?152*~8~s`x@&otBgg7*IP!ER%)hcVM*j#ha+6&aEXm~49q)Z z+0!~4_raJCM#*)JTv#L5ZSwWiE)B$~ZuP^{@e{g-vs9fLZCyF3bgbN>Mqb+BN{4di z{ln=Hmw0y12(lyg7W+;!1wx^-_Ix{yk+!1V?_oW(Np-*Q9ae{t4^TEtT zfXe_Y0M`Ll0k#0P0p0{q0qz4Z$=d^bf!;km+j^NWZDv2T1ZP6HCPE6*5Mgw|g;53< zT^M6(k`hC>cyW-(kKgW0LC-l^|lr#_}4JVS#IHuvIHGznt}kKDo@6BuSO-(u5C zEcy|F7^C0jlMLS>FvzxkkGr+_@DB1&Ptc1cAbg*GG+UN8Adav}znmRzRUnD5gYYH$ zYo!owd9YuE*9i16_uB-LZ2FequoT=89G+6bFy+=Z&9htrxWaSJ^Whafth=jkBMc0P paM$(kg?lbY!0Rl~IP>gTX9D59; zq_}J=q?S(GMHj8QLfuqUMyk3hyQ=D{n@X&Tx+oHx{sXPrd*@}F#?rapIrrRikMEuN zIZxLftbE*o=O1+@9A7{FA=7>D^Y1nn(PZ^UJZbVLBxYiDn2e!=pAm11IYE8W)UH0^ zhRsR!1^3+IXSQ<|d+qxzK5M^W@nidt#lP9dE$-r{0!B}s3zB?Cnk`FNMU*A=up?k) zJ>;vLtZ#b3F4TgEZwS4u*LJ@x;bl`mGe2%;pn-V%u}Yj zF}K1V23KNzWmAyi`I2C!xD!%I$w*ltUEVfhp1N4V+QqKjnw8UVhh~(U7nB-{7JE|_ zxwxGuC8YJDC~XK30bRrlXk202FxWM z{hI4e^$M$QT(z0SrNs@C?WEFu@Ud9guQH$^jy08$VQ-us6;c(du>ohgiKENOI^=|LN>jUv#?n(IRCn-_Dkn zCpi1~pkVg?b6h1KU>pJBlJdM;~Hy&vkavBuOVp`Pl~&=jIq z{k5l4oAZSC>2oi8hP1$9xWle}i|Tr~o%21w=DaB7g!KqL=7jjKNTa37N!3za?6_Zkq49Dx= zLu_mC{Eo>|N!*aq*yov4iv*zakO9vo2j`a;7e z8hLouA*vt0Z${_I`AOX`jcz@6>9zMu$n$7GE-u!SQiSR9zvNw7cF+14LsZ- z;HKVPI`mWbJpw_Rv&Zt^XXZXDQ87wz2p_1=htkW7;6Ye|7K9=25;#i04=pgp25&3E zO=v?{MfjKgReT6*2KsGqkw7c0c!@w89WHa4=Yx0D`@_NXae$L-(^JfhGqa%gyo(SB n*x-tu-U3&3@WM4ttJ4DS>fjC9VL!lWfb#%3fP2-K!%6%Pheime diff --git a/lam4-backend/gf-grammar/Lam4Eng.gf b/lam4-backend/gf-grammar/Lam4Eng.gf index 65cb8c0f..d01c2b5f 100644 --- a/lam4-backend/gf-grammar/Lam4Eng.gf +++ b/lam4-backend/gf-grammar/Lam4Eng.gf @@ -143,11 +143,11 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { linArgs : Str -> ListX0 -> Str = \s,xs -> case xs.size of { Zero => "" ; - _ => paragraph (s ++ conjX "and" xs) } ; + _ => s ++ conjX "and" xs } ; linArgs : Str -> ListX0 -> Str -> Str = \pr,xs,pst -> case xs.size of { Zero => "" ; - _ => paragraph (pr ++ conjX "and" xs ++ pst) } + _ => pr ++ conjX "and" xs ++ pst } } ; -- Bin expr @@ -233,6 +233,17 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { s = quote expr.s ++ "is certain" } ; + Round expr precision = expr ; + -- { -- for being extra verbose + -- s = dl "rounding" expr.s + -- ++ dl "to precision of" (precision.s ++ "decimals") + -- } ; + + Default expr default = { + s = dl ("if" ++ expr.s ++ "is uncertain, then") default.s + ++ dl "else" expr.s + } ; + IfThenElse if then else = { s = ite if.s then.s else.s } ; @@ -249,7 +260,9 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { } ; -- : Expr -> [Expr] -> Expr ; - FunApp f xs = {s = f.s ++ linArgs "of" xs} ; + FunApp f xs = { + s = dl f.s (linArgs "" xs) + } ; -- Record : (Row Expr) -> Expr ; -- record construction -- : Expr -> Name -> Expr ; -- record projection diff --git a/lam4-backend/src/Lam4/Render/Lam4Gf.hs b/lam4-backend/src/Lam4/Render/Lam4Gf.hs index 3811afee..0f9b33cc 100644 --- a/lam4-backend/src/Lam4/Render/Lam4Gf.hs +++ b/lam4-backend/src/Lam4/Render/Lam4Gf.hs @@ -97,6 +97,7 @@ data Tree :: * -> * where GBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ GCertain :: GExpr -> Tree GExpr_ GConjExpr :: GListExpr -> Tree GExpr_ + GDefault :: GExpr -> GExpr -> Tree GExpr_ GElif :: GListIfThen -> GExpr -> Tree GExpr_ GFold :: GExpr -> GExpr -> GExpr -> Tree GExpr_ GFun :: GName -> GMetadata -> GListName -> GExpr -> Tree GExpr_ @@ -116,6 +117,7 @@ data Tree :: * -> * where GQuoteVar :: GName -> Tree GExpr_ GQuotedBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ GRecord :: GName -> GExpr -> Tree GExpr_ + GRound :: GExpr -> GExpr -> Tree GExpr_ GSig :: GListName -> GListExpr -> Tree GExpr_ GUnary :: GUnaryOp -> GExpr -> Tree GExpr_ GUncertain :: GExpr -> Tree GExpr_ @@ -172,6 +174,7 @@ instance Eq (Tree a) where (GBinExpr x1 x2 x3,GBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GCertain x1,GCertain y1) -> and [ x1 == y1 ] (GConjExpr x1,GConjExpr y1) -> and [ x1 == y1 ] + (GDefault x1 x2,GDefault y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GElif x1 x2,GElif y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GFold x1 x2 x3,GFold y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GFun x1 x2 x3 x4,GFun y1 y2 y3 y4) -> and [ x1 == y1 , x2 == y2 , x3 == y3 , x4 == y4 ] @@ -191,6 +194,7 @@ instance Eq (Tree a) where (GQuoteVar x1,GQuoteVar y1) -> and [ x1 == y1 ] (GQuotedBinExpr x1 x2 x3,GQuotedBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GRecord x1 x2,GRecord y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GRound x1 x2,GRound y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GSig x1 x2,GSig y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GUnary x1 x2,GUnary y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GUncertain x1,GUncertain y1) -> and [ x1 == y1 ] @@ -268,6 +272,7 @@ instance Gf GExpr where gf (GBinExpr x1 x2 x3) = mkApp (mkCId "BinExpr") [gf x1, gf x2, gf x3] gf (GCertain x1) = mkApp (mkCId "Certain") [gf x1] gf (GConjExpr x1) = mkApp (mkCId "ConjExpr") [gf x1] + gf (GDefault x1 x2) = mkApp (mkCId "Default") [gf x1, gf x2] gf (GElif x1 x2) = mkApp (mkCId "Elif") [gf x1, gf x2] gf (GFold x1 x2 x3) = mkApp (mkCId "Fold") [gf x1, gf x2, gf x3] gf (GFun x1 x2 x3 x4) = mkApp (mkCId "Fun") [gf x1, gf x2, gf x3, gf x4] @@ -287,6 +292,7 @@ instance Gf GExpr where gf (GQuoteVar x1) = mkApp (mkCId "QuoteVar") [gf x1] gf (GQuotedBinExpr x1 x2 x3) = mkApp (mkCId "QuotedBinExpr") [gf x1, gf x2, gf x3] gf (GRecord x1 x2) = mkApp (mkCId "Record") [gf x1, gf x2] + gf (GRound x1 x2) = mkApp (mkCId "Round") [gf x1, gf x2] gf (GSig x1 x2) = mkApp (mkCId "Sig") [gf x1, gf x2] gf (GUnary x1 x2) = mkApp (mkCId "Unary") [gf x1, gf x2] gf (GUncertain x1) = mkApp (mkCId "Uncertain") [gf x1] @@ -300,6 +306,7 @@ instance Gf GExpr where Just (i,[x1,x2,x3]) | i == mkCId "BinExpr" -> GBinExpr (fg x1) (fg x2) (fg x3) Just (i,[x1]) | i == mkCId "Certain" -> GCertain (fg x1) Just (i,[x1]) | i == mkCId "ConjExpr" -> GConjExpr (fg x1) + Just (i,[x1,x2]) | i == mkCId "Default" -> GDefault (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "Elif" -> GElif (fg x1) (fg x2) Just (i,[x1,x2,x3]) | i == mkCId "Fold" -> GFold (fg x1) (fg x2) (fg x3) Just (i,[x1,x2,x3,x4]) | i == mkCId "Fun" -> GFun (fg x1) (fg x2) (fg x3) (fg x4) @@ -319,6 +326,7 @@ instance Gf GExpr where Just (i,[x1]) | i == mkCId "QuoteVar" -> GQuoteVar (fg x1) Just (i,[x1,x2,x3]) | i == mkCId "QuotedBinExpr" -> GQuotedBinExpr (fg x1) (fg x2) (fg x3) Just (i,[x1,x2]) | i == mkCId "Record" -> GRecord (fg x1) (fg x2) + Just (i,[x1,x2]) | i == mkCId "Round" -> GRound (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "Sig" -> GSig (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "Unary" -> GUnary (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "Uncertain" -> GUncertain (fg x1) @@ -512,6 +520,7 @@ instance Compos Tree where GBinExpr x1 x2 x3 -> r GBinExpr `a` f x1 `a` f x2 `a` f x3 GCertain x1 -> r GCertain `a` f x1 GConjExpr x1 -> r GConjExpr `a` f x1 + GDefault x1 x2 -> r GDefault `a` f x1 `a` f x2 GElif x1 x2 -> r GElif `a` f x1 `a` f x2 GFold x1 x2 x3 -> r GFold `a` f x1 `a` f x2 `a` f x3 GFun x1 x2 x3 x4 -> r GFun `a` f x1 `a` f x2 `a` f x3 `a` f x4 @@ -531,6 +540,7 @@ instance Compos Tree where GQuoteVar x1 -> r GQuoteVar `a` f x1 GQuotedBinExpr x1 x2 x3 -> r GQuotedBinExpr `a` f x1 `a` f x2 `a` f x3 GRecord x1 x2 -> r GRecord `a` f x1 `a` f x2 + GRound x1 x2 -> r GRound `a` f x1 `a` f x2 GSig x1 x2 -> r GSig `a` f x1 `a` f x2 GUnary x1 x2 -> r GUnary `a` f x1 `a` f x2 GUncertain x1 -> r GUncertain `a` f x1 diff --git a/lam4-backend/src/Lam4/Render/Render.hs b/lam4-backend/src/Lam4/Render/Render.hs index 2dc7d0fe..6913c799 100644 --- a/lam4-backend/src/Lam4/Render/Render.hs +++ b/lam4-backend/src/Lam4/Render/Render.hs @@ -83,6 +83,7 @@ postprocessText = newlines . tabs . rmBIND newlines :: T.Text -> T.Text newlines = T.map (\c -> if c == '∞' then '\n' else c) +style :: T.Text style = [r| |] @@ -237,7 +255,7 @@ varFromFun = \case ---- Tree transformations ----- genericTreeTrans :: Tree a -> Tree a -genericTreeTrans = flattenNestedAndOr . aggregatePredApp . binExprVerbosity +genericTreeTrans = flattenITE . flattenNestedAndOr . aggregatePredApp . binExprVerbosity quoteVars :: Tree a -> Tree a quoteVars (GVar x) = GQuoteVar x @@ -274,6 +292,21 @@ aggregatePredApp tree@(GVerboseBinExpr op (GFunApp f arg) (GFunApp g arg')) = else tree aggregatePredApp x = composOp aggregatePredApp x +flattenITE :: Tree a -> Tree a +flattenITE expr@GIfThenElse{} = + case collectITE expr of + ites@(_:_:_) -> GElif $ GListIfThen (rmElseFromFirst ites) + _ -> expr + where + rmElseFromFirst (GMiddleIfThen i t : rest) = GFirstIfThen i t : rest + rmElseFromFirst x = x +flattenITE x = composOp flattenITE x + +collectITE :: GExpr -> [GIfThen] +collectITE (GIfThenElse i t e@GIfThenElse{}) = GMiddleIfThen i t : collectITE e +collectITE (GIfThenElse i t e) = [GMiddleIfThen i t, GNilIfThen e] +collectITE e = [GNilIfThen e] + flattenNestedAndOr :: Tree a -> Tree a flattenNestedAndOr e@GBinExpr{} = composOp flattenNestedAndOr (flattenIfLongEnough e) flattenNestedAndOr e@GVerboseBinExpr{} = composOp flattenNestedAndOr (flattenIfLongEnough e) From 21f7e805a3bfa65a866d08246e604497a0ceb6f4 Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Mon, 11 Nov 2024 17:49:07 +0100 Subject: [PATCH 08/14] nicer output for unary functions --- lam4-backend/gf-grammar/Lam4.gf | 2 +- lam4-backend/gf-grammar/Lam4.pgf | Bin 11633 -> 11822 bytes lam4-backend/gf-grammar/Lam4Eng.gf | 8 ++++++-- lam4-backend/lam4-backend.cabal | 3 ++- lam4-backend/src/Lam4/Render/Lam4Gf.hs | 5 +++++ lam4-backend/src/Lam4/Render/Render.hs | 5 +++-- 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/lam4-backend/gf-grammar/Lam4.gf b/lam4-backend/gf-grammar/Lam4.gf index 6ed0ff12..ddcd26f2 100644 --- a/lam4-backend/gf-grammar/Lam4.gf +++ b/lam4-backend/gf-grammar/Lam4.gf @@ -65,7 +65,7 @@ abstract Lam4 = { QuotedBinExpr, -- no newline, quotes around args BinExpr : BinOp -> Expr -> Expr -> Expr ; - Known, Certain, Unknown, Uncertain : Expr -> Expr ; + UnaryMinusExpr, Known, Certain, Unknown, Uncertain : Expr -> Expr ; Round : (expr, prec : Expr) -> Expr ; Default : (val, default : Expr) -> Expr ; diff --git a/lam4-backend/gf-grammar/Lam4.pgf b/lam4-backend/gf-grammar/Lam4.pgf index 656e15d461d74aab9f169a8d7168b6a05313eace..0ec7cc7a5efea1a83bb1914b91f8d12f1f16116b 100644 GIT binary patch delta 1811 zcmah}&2Jk;6yG;%ufJoUa@vrzHLVjnO@K5IO4~HWjqTK_ow&A>(2%Cx+LLPdgH)H59JE8>z%co3zj_ddvD*oc^|(w zPu3r9e0C5@_YN%zoc;T{aTOd$zK636hSBk8$G|_YDth*vmPX>iA#)97T=Oq^W^O*_ z2VC_(o_w%#RLHdzayXb|PPe@xgFk!684L^O7+eAY-=n18!opdg@RRgbz8gOup^DK!?%z3QzI1ae;Uv!Kjwo#o#BhwKl zl`^iWTK!%tMjm-X%CxrgTfCQOLEH!{+*b#>x`-&=bI6{p&#qgHZw$iOrMY_q(du>WEX&*tD zI_>j3b@;+}C z;!glRHs_8_Av9Gat;FcF$w=Bzn^KJusfJqyyhOfAB+#)0d6YOATJkx3gExqOw2WRj zPBunocCSXQx23G!sqVCJ2G?ZR^f|nPNg*R`OLdH1UADOgAY_{@W2XWf%D#dAefwI?PaRnfhlQiAv@Q>!7lT}rNipOFu3|pLq{HDEKve!k2xp0($ zBMcly3mDC=palb+s`fA%MtivoseTs2I8nxiuc!NYOM@?9bau_+EeHX+=Jl%9#xUly z1~#qKffMY}rSFr)X8=?%(9CMMDAnsScJi6<+Rq7kWrO@awq6i}#oKNPZ}bY+dWGvk zQLVRS6}^1LQ>3$vPOhURjLy6nSdwJN^9k~4G7)_pEo?J3n7kg(1 z7Ray3k$iV_;Cv50(1YjLFhSHEBRJPTK#(J1YIbHM*nKHsXx~)8^WAxX3v3c#o_v!U wggE&rWx|yC$#@k`0QUg^_Z;^j@RarRnMXXAMi$_%bhZY?Ja8YGo{1*<59i{yDgXcg delta 1694 zcmai!U2_vv7{~LReMyr|NI^hB3IQ6@5~LKZ6)R$!m$D@Pa0y?aGtPbj^~M>Uar^+@FkCY*j@~$XML9qG2}8rJ zr_4Uz{U<9%`%C#kS0y9SG)=n2NmTyEjZ+!pFH>3Jvs6CfN2&atpQiF3{+=hT`{ApI zx_^xrR4zo4Wu4dvDNrw>J3bAFWjYF(6UMK{iE06m@WL3Bn_hzW# zhNd?kb`FuBIf3T;K{!X{AA2$#^9z0+OOhXBNgDJ#cKm!lAM-z@_pM<46V1S6UARbB z>+z?(6SOyBw$o9zi?U%>I@A}QlT~L1-_By)lw_6K&Kcew2*}|LsjHYYfXyrNhHn%! zrAZCOK0{mgTv(g~wae3QQE{W*!fIYIFm(x{YM7GRz_o6h`r-kf=vU#csoGt?!?dp3`o}W!5onLhwfPuhyUiuU&mrrd*lm-WmL_yUL=19_}Y4Q>Hq;M_lVFH)QZmNn-oFwSXRPUpNbK|Sp z-THP1=Ws)T8(|L@ILqhcExC!&#iEN00H1Gn%4IO?DVg`WGm>OSW^;9!J`V^qA3<}tcdMe`<_ zS_*&&r-KN>nL+pJa6sS5gc87-}5ua$dLRp3n++Q8gADVY};5d0O ZZo!0=JzEFnKIIFp30tnV^y^e-^M{= 3001.5.0.1, multipart ^>= 0.2.1, lens-regex-pcre, - string-interpolate + string-interpolate, + raw-strings-qq diff --git a/lam4-backend/src/Lam4/Render/Lam4Gf.hs b/lam4-backend/src/Lam4/Render/Lam4Gf.hs index e111e017..c7e476ae 100644 --- a/lam4-backend/src/Lam4/Render/Lam4Gf.hs +++ b/lam4-backend/src/Lam4/Render/Lam4Gf.hs @@ -120,6 +120,7 @@ data Tree :: * -> * where GRound :: GExpr -> GExpr -> Tree GExpr_ GSig :: GListName -> GListExpr -> Tree GExpr_ GUnary :: GUnaryOp -> GExpr -> Tree GExpr_ + GUnaryMinusExpr :: GExpr -> Tree GExpr_ GUncertain :: GExpr -> Tree GExpr_ GUnknown :: GExpr -> Tree GExpr_ GVar :: GName -> Tree GExpr_ @@ -200,6 +201,7 @@ instance Eq (Tree a) where (GRound x1 x2,GRound y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GSig x1 x2,GSig y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GUnary x1 x2,GUnary y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GUnaryMinusExpr x1,GUnaryMinusExpr y1) -> and [ x1 == y1 ] (GUncertain x1,GUncertain y1) -> and [ x1 == y1 ] (GUnknown x1,GUnknown y1) -> and [ x1 == y1 ] (GVar x1,GVar y1) -> and [ x1 == y1 ] @@ -301,6 +303,7 @@ instance Gf GExpr where gf (GRound x1 x2) = mkApp (mkCId "Round") [gf x1, gf x2] gf (GSig x1 x2) = mkApp (mkCId "Sig") [gf x1, gf x2] gf (GUnary x1 x2) = mkApp (mkCId "Unary") [gf x1, gf x2] + gf (GUnaryMinusExpr x1) = mkApp (mkCId "UnaryMinusExpr") [gf x1] gf (GUncertain x1) = mkApp (mkCId "Uncertain") [gf x1] gf (GUnknown x1) = mkApp (mkCId "Unknown") [gf x1] gf (GVar x1) = mkApp (mkCId "Var") [gf x1] @@ -335,6 +338,7 @@ instance Gf GExpr where Just (i,[x1,x2]) | i == mkCId "Round" -> GRound (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "Sig" -> GSig (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "Unary" -> GUnary (fg x1) (fg x2) + Just (i,[x1]) | i == mkCId "UnaryMinusExpr" -> GUnaryMinusExpr (fg x1) Just (i,[x1]) | i == mkCId "Uncertain" -> GUncertain (fg x1) Just (i,[x1]) | i == mkCId "Unknown" -> GUnknown (fg x1) Just (i,[x1]) | i == mkCId "Var" -> GVar (fg x1) @@ -555,6 +559,7 @@ instance Compos Tree where GRound x1 x2 -> r GRound `a` f x1 `a` f x2 GSig x1 x2 -> r GSig `a` f x1 `a` f x2 GUnary x1 x2 -> r GUnary `a` f x1 `a` f x2 + GUnaryMinusExpr x1 -> r GUnaryMinusExpr `a` f x1 GUncertain x1 -> r GUncertain `a` f x1 GUnknown x1 -> r GUnknown `a` f x1 GVar x1 -> r GVar `a` f x1 diff --git a/lam4-backend/src/Lam4/Render/Render.hs b/lam4-backend/src/Lam4/Render/Render.hs index b50cdc75..6e79bd41 100644 --- a/lam4-backend/src/Lam4/Render/Render.hs +++ b/lam4-backend/src/Lam4/Render/Render.hs @@ -199,8 +199,8 @@ renderCstProgramToNL env decls = T.unlines ( ["", "", style, "", ""] <> fmap (renderCstDeclToNL env) decls <> ["", ""] - - <> fmap (renderCstDeclToGFtrees env) decls) +-- <> fmap (renderCstDeclToGFtrees env) decls + ) renderCstDeclToNL :: NLGEnv -> Decl -> T.Text renderCstDeclToNL env = gfLin env . gf . genericTreeTrans . parseDecl @@ -393,6 +393,7 @@ parseExpr name = let f = parseExpr name in \case Var var -> GVar (parseName var) Lit lit -> GLit (parseLit lit) + Unary UnaryMinus expr -> GUnaryMinusExpr (f expr) ; Unary op expr -> GUnary (parseUnaOp op) (f expr) -- e.g. "x / y" BinExpr op lc@Var{} rc@Var{} -> GBinExpr (parseBinOp op) (f lc) (f rc) From 0ad5ccc2553edb704782b34d249559037fbb81cd Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Wed, 13 Nov 2024 15:15:51 +0100 Subject: [PATCH 09/14] WIP: add

in linearized paragraphs --- lam4-backend/gf-grammar/Lam4.gf | 12 ++-- lam4-backend/gf-grammar/Lam4.pgf | Bin 11822 -> 11815 bytes lam4-backend/gf-grammar/Lam4Eng.gf | 95 ++++++++++++------------- lam4-backend/src/Lam4/Render/Lam4Gf.hs | 80 ++++++++++----------- lam4-backend/src/Lam4/Render/Render.hs | 72 ++++++++----------- 5 files changed, 121 insertions(+), 138 deletions(-) diff --git a/lam4-backend/gf-grammar/Lam4.gf b/lam4-backend/gf-grammar/Lam4.gf index ddcd26f2..232440b5 100644 --- a/lam4-backend/gf-grammar/Lam4.gf +++ b/lam4-backend/gf-grammar/Lam4.gf @@ -26,13 +26,13 @@ abstract Lam4 = { fun -- Placeholder, or skip some constructs? EmptyS : S ; - TypeDeclS : TypeDecl -> S ; + TypeDeclS : (id : String) -> TypeDecl -> S ; EvalS, EvalWhetherS, - ExprS : Expr -> S ; - AssignS : Name -> Expr -> S ; - LetIsTrue : Name -> Expr -> S ; - AtomicConcept : Name -> S ; + ExprS : (id : String) -> Expr -> S ; + AssignS : (id : String) -> Name -> Expr -> S ; + LetIsTrue : (id : String) -> Name -> Expr -> S ; + AtomicConcept : (id : String) -> Name -> S ; -- Metadata MkMetadata : String -> Metadata ; @@ -62,7 +62,6 @@ abstract Lam4 = { Unary : UnaryOp -> Expr -> Expr ; VerboseBinExpr, -- newline + quotes around args - QuotedBinExpr, -- no newline, quotes around args BinExpr : BinOp -> Expr -> Expr -> Expr ; UnaryMinusExpr, Known, Certain, Unknown, Uncertain : Expr -> Expr ; @@ -97,6 +96,7 @@ abstract Lam4 = { InstanceSum : (entities : Expr) -> Expr ; FunApp : Expr -> [Expr] -> Expr ; -- Record : (Row Expr) -> Expr ; -- record construction + OnlyFieldProject, Project : Expr -> Name -> Expr ; -- record projection Fun : (funname : Name) -> Metadata -> (args : [Name]) -> Expr -> Expr ; -- Function Sig : [Name] -> [Expr] -> Expr ; -- TODO: what is this? only `Sig [] []` present in royalflush data diff --git a/lam4-backend/gf-grammar/Lam4.pgf b/lam4-backend/gf-grammar/Lam4.pgf index 0ec7cc7a5efea1a83bb1914b91f8d12f1f16116b..44214023f61b15a200d55000b15b51565dee2b3c 100644 GIT binary patch delta 2193 zcma)7S#J|p6h7zPnQ?3Qu|N|Rj5+my5+Hms{f)=-&*m~$Nqq}_j;0$1XOh_pYwg+S?)H=w~OB_ zepalfK(s6<(aW$k0 z`dUm=^(>R!L+gJ!^Tq^#7!cU^O^aTjfCzvThbaH^+#j3Mblu(7LZ&1tg>@|=%H{BgKnOLI zgo{+tvL||EUMEx1BV?XAQjFBTGROwnyGNQ|5#mKzJtC|Xp)_2M$h?y*T9w%&e;-p? z8iwu0{{LCcp0!rO{-;z;4a z6ifBYvZvjni@Sm!W38?gvTCmDlvYR;iO;u#Bf2-j(R)P`eLEP|ZN%caxn;G0K6W6` z!EGwg#rv?;K!}qs0{aB{IS>@?d7ztXj$ofi4i0d8CD_UB{a_EbkE{4uu$|-Is>9jp5>Ua#cwf*|Khskp(Hix1SumNRlc!e%_hX^o{ujT}fkWn&3$qW%i-4Q6 zw}n%nLdKz)=e);1F9`2f?FUu+A-7(5fMNnXMkt)L+s)ffJvy zopGl2K6J*~7hl?kwqqylo9%=DK_5HQ=}SMR)91do_hu75I(0L1&hLEO-#zE-y_?UM zzFzt$hvf0y-H6}3&?zF*B(JkBw3f&$tSH8cqQ`}+!wi&4(kDcucb9Hke;_5THj7rr z>4Ih`N%j?vvY+jrB9`vgg(>^Zwcx0Pj;Gbotz2nu{RIh^*(1+@odN*0j9t@5#@V-? zNmk#qG>rff#Q{pwMjp5UAa5}#9-&ftSQ+Mi>sCL}QdBb5a|#f#riRDZlF#qPU6kT3 z3wL>|JALQdC0926!#ChHA+_a=gl?qO>r_hVS{AT$w<%89ShJJ;(k9ygEL0jBDKM9} zkA2ou&%SIe2N2lrZO4SC^rN?h*sPR}<;DTnNLyFwar+Yzuyapg+`@Y?8F&yXE>d-| z!OjCkE476S>avm6RFQ&*D+N~-zI+Z89Iwo}o?cT_-ae%XH3Kp|bKVJm zkiY4wQ6UjiVro~I;4sT}O$qg+d$iWvf%j(R!Q<>vx0B*9mr=iu=QGV8-DW148}k@8W(- zpie9a3~;#^=;U%e(9Px3GJX+g=lG{UcdN%)+32jA(AQ^kh;%|tlHF0}2?iT_9TSF@ zO)sC&)MX`S@Ls2b0n!~{x!@j*v1h?0(&hiS=e6P`7f;Eb(QeN313sxNXYjIhQb{EW z83Tvp$@E$}sgV7%QYe#7A7-$G8;MGD&Qs{6J#la#@`!%W0XrCUQCKtb&dz*h!`oGIo|s8RX!6t;rb5 zdNnan7a z0tYS8v|7lMeM_~`)u>`5k_jV$9yz)iOJo)F)I?YLn93t++Jc)MW&g(bTK;2uIon1s zvBfCjwJjE2*=k&sqgt|%(a6Z66y>ji?72W<3ORhfCYH`r>K&+!X&YsNE2in$NIs&b zbpD}Hl2}7ynt`KaRwsupN^=?B+1?rJoUSCrh;7z6Uj@21oK|}!98IX}c#^I6wXtV? zW9=?m`2&0|q2tkQA6y;7?61E4y=W;PLTs-s>+&42)wyYuFT)NN>K{TM)B7I`?EnY( z01g8j1(*gn1#kx7JirA2e(_TP*8wsB{A0PB^$heD4-tNU5sn~O;RG#Xgh>h9;Ds7) zhD=z?Vc3Lr4yVK_2~G-SfrwBt%v6_01!K%4o)h>qa=thL5624vzafOmGm4x=Gg)#b z%MI}l)53qc31r9%Aajpl0vQUM^{s8zcXPA8TY}3C>q6WXt3(xV5^f>9C1MD72(&`W zBHR^Ph9Utw-{Nf)T84MHZsu94P0HJWy=j$ zY1wvrY~VNB35asW0LDe3$AoxYh diff --git a/lam4-backend/gf-grammar/Lam4Eng.gf b/lam4-backend/gf-grammar/Lam4Eng.gf index fcb0a7e7..fe7c67ce 100644 --- a/lam4-backend/gf-grammar/Lam4Eng.gf +++ b/lam4-backend/gf-grammar/Lam4Eng.gf @@ -62,58 +62,54 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { lin -- Placeholder, or skip some constructs? EmptyS = {s = ""} ; - TypeDeclS td = td ; - ExprS expr = expr ; - EvalS expr = {s = "evaluate" ++ expr.s ++ linebreak} ; - EvalWhetherS expr = {s = "evaluate whether" ++ expr.s ++ linebreak} ; - AssignS name expr = { - s = dl (quote name.s ++ hilight Strong "is calculated by") - expr.s + TypeDeclS id td = {s = paragraph id.s td.s} ; + ExprS id expr = {s = paragraph id.s expr.s} ; + EvalS id expr = {s = paragraph id.s ("evaluate" ++ expr.s)} ; + EvalWhetherS id expr = {s = paragraph id.s ("evaluate whether" ++ expr.s)} ; + AssignS id name expr = { + s = paragraph id.s ( + dl (quote name.s ++ hilight Strong "is calculated by") + expr.s + ) } ; - LetIsTrue name expr = { - s = dl (quote name.s ++ ifKw) - expr.s + LetIsTrue id name expr = { + s = paragraph id.s ( + dl (quote name.s ++ ifKw) + expr.s + ) } ; - AtomicConcept name = {s = paragraph (name.s ++ "is an atomic concept.")} ; + AtomicConcept id name = {s = paragraph id.s (name.s ++ "is an atomic concept.")} ; -- Metadata MkMetadata str = str ** {isEmpty = NonEmpty} ; NoMetadata = {s = [] ; isEmpty = Empty} ; -- Type declarations - MkRowTypeDecl md field typ = {s = bullet ++ "its" ++ field.s ++ linType typ ++ linRowMd md} ; - MkRowDecl md field = {s = bullet ++ "its" ++ field.s ++ linRowMd md} ; + MkRowTypeDecl md field typ = {s = "its" ++ field.s ++ linType typ ++ linRowMd md} ; + MkRowDecl md field = {s = "its" ++ field.s ++ linRowMd md} ; -- These funs are automatically generated from cat [RowTypeDecl]{0} ; -- : [RowTypeDecl] BaseRowTypeDecl = {s = [] ; isEmpty = Empty} ; -- : RowTypeDecl -> [RowTypeDecl] -> [RowTypeDecl] - ConsRowTypeDecl t ts = - let sep : Str = case ts.isEmpty of { - Empty => [] ; - NonEmpty => linebreak } ; - in {s = tab ++ t.s ++ sep ++ ts.s ; isEmpty = NonEmpty} ; + ConsRowTypeDecl t ts = { + s = li t.s ++ ts.s ; + isEmpty = NonEmpty + } ; MkTypeDecl md name rtds = { - s = artIndef ++ name.s ++ linTypeDeclMd md ++ "." ++ - case rtds.isEmpty of { - Empty => [] ; - NonEmpty => "Each" ++ name.s ++ - "has associated with it information like" ++ - linebreak ++ rtds.s - } ; + s = artIndef ++ name.s ++ linTypeDeclMd md ++ + case rtds.isEmpty of { + Empty => [] ; + NonEmpty => "Each" ++ name.s ++ + "has associated with it information like" ++ + ul rtds.s + } } ; oper - bullet = "*" ; - -- just ad hoc characters to `tr "°∞" "\t\n"` in shell - tab = "°°" ; - space = "°" ; - linebreak = "
" ; - - indent1, indent2 : Str -> Str ; - indent1 str = linebreak ++ space ++ str ; - indent2 str = linebreak ++ tab ++ str ; + linebreak = "∞" ; + hr = linebreak ++ "


" ++ linebreak ; quote : Str -> Str ; quote str = "" ++ BIND ++ str ++ BIND ++ "" ; @@ -121,7 +117,10 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { quoteSS : SS -> SS ; quoteSS ss = {s = quote ss.s} ; - paragraph : Str -> Str = \s -> "

" ++ s ++ "

" ; + paragraph = overload { + paragraph : Str -> Str = \s -> "

" ++ s ++ "

" ; + paragraph : (id : Str) -> Str -> Str = \i,s -> "

" ++ s ++ "

" + } ; artIndef = pre { "eu" | "Eu" | "uni" | "Uni" => "A" ; @@ -203,12 +202,6 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { ++ e2.s } ; - QuotedBinExpr op e1 e2 = { - s = quote e1.s - ++ op.s ! Concise - ++ quote e2.s - } ; - VerboseBinExpr op e1 e2 = { s = dl "" e1.s ++ dl (op.s ! Verbose) e2.s @@ -280,21 +273,27 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { -- : Expr -> Name -> Expr ; -- record projection Project rec field = { - s = - -- glue rec.s "'s" ++ + s = glue rec.s "'s" ++ field.s } ; + -- don't print out the record, only the field. + -- Whether to choose this or Project should depend on annotations in the Lam4 program. + OnlyFieldProject _rec field = { + s = field.s + } ; + -- : Name -> Metadata -> [Name] -> Expr -> Expr ; -- Function Fun funname md args body = { - s = "Function" ++ funname.s ++ ":" ++ linebreak - ++ linArgs "given" args ", return" - ++ indent1 body.s + s = + -- "Function" ++ funname.s ++ ":" ++ linebreak ++ + -- ++ linArgs "given" args ", return" ++ + body.s } ; -- : S -> Expr -> Expr ; Let decl expr = { - s = decl.s ++ linebreak ++ expr.s + s = decl.s ++ hr ++ expr.s } ; -- : Name -> Expr -> Expr ; @@ -328,8 +327,6 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { s = quote (conjX "and" args) ++ "is" ++ conjX (op.s ! Verbose) preds } ; - - Fold combine nil over = { s = linebreak ++ "Combine" ++ quote over.s ++ "into one value," ++ linebreak diff --git a/lam4-backend/src/Lam4/Render/Lam4Gf.hs b/lam4-backend/src/Lam4/Render/Lam4Gf.hs index c7e476ae..e4533e69 100644 --- a/lam4-backend/src/Lam4/Render/Lam4Gf.hs +++ b/lam4-backend/src/Lam4/Render/Lam4Gf.hs @@ -110,12 +110,12 @@ data Tree :: * -> * where GLet :: GS -> GExpr -> Tree GExpr_ GLit :: GName -> Tree GExpr_ GNormIsInfringed :: GName -> Tree GExpr_ + GOnlyFieldProject :: GExpr -> GName -> Tree GExpr_ GPredApp :: GExpr -> GListExpr -> Tree GExpr_ GPredAppMany :: GBinOp -> GListExpr -> GListExpr -> Tree GExpr_ GPredicate :: GName -> GMetadata -> GListName -> GExpr -> Tree GExpr_ GProject :: GExpr -> GName -> Tree GExpr_ GQuoteVar :: GName -> Tree GExpr_ - GQuotedBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ GRecord :: GName -> GExpr -> Tree GExpr_ GRound :: GExpr -> GExpr -> Tree GExpr_ GSig :: GListName -> GListExpr -> Tree GExpr_ @@ -141,14 +141,14 @@ data Tree :: * -> * where GMkName :: GString -> Tree GName_ GMkRowDecl :: GMetadata -> GName -> Tree GRowTypeDecl_ GMkRowTypeDecl :: GMetadata -> GName -> GName -> Tree GRowTypeDecl_ - GAssignS :: GName -> GExpr -> Tree GS_ - GAtomicConcept :: GName -> Tree GS_ + GAssignS :: GString -> GName -> GExpr -> Tree GS_ + GAtomicConcept :: GString -> GName -> Tree GS_ GEmptyS :: Tree GS_ - GEvalS :: GExpr -> Tree GS_ - GEvalWhetherS :: GExpr -> Tree GS_ - GExprS :: GExpr -> Tree GS_ - GLetIsTrue :: GName -> GExpr -> Tree GS_ - GTypeDeclS :: GTypeDecl -> Tree GS_ + GEvalS :: GString -> GExpr -> Tree GS_ + GEvalWhetherS :: GString -> GExpr -> Tree GS_ + GExprS :: GString -> GExpr -> Tree GS_ + GLetIsTrue :: GString -> GName -> GExpr -> Tree GS_ + GTypeDeclS :: GString -> GTypeDecl -> Tree GS_ GMkTypeDecl :: GMetadata -> GName -> GListRowTypeDecl -> Tree GTypeDecl_ GCeiling :: Tree GUnaryOp_ GFloor :: Tree GUnaryOp_ @@ -191,12 +191,12 @@ instance Eq (Tree a) where (GLet x1 x2,GLet y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GLit x1,GLit y1) -> and [ x1 == y1 ] (GNormIsInfringed x1,GNormIsInfringed y1) -> and [ x1 == y1 ] + (GOnlyFieldProject x1 x2,GOnlyFieldProject y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GPredApp x1 x2,GPredApp y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GPredAppMany x1 x2 x3,GPredAppMany y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GPredicate x1 x2 x3 x4,GPredicate y1 y2 y3 y4) -> and [ x1 == y1 , x2 == y2 , x3 == y3 , x4 == y4 ] (GProject x1 x2,GProject y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GQuoteVar x1,GQuoteVar y1) -> and [ x1 == y1 ] - (GQuotedBinExpr x1 x2 x3,GQuotedBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GRecord x1 x2,GRecord y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GRound x1 x2,GRound y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GSig x1 x2,GSig y1 y2) -> and [ x1 == y1 , x2 == y2 ] @@ -222,14 +222,14 @@ instance Eq (Tree a) where (GMkName x1,GMkName y1) -> and [ x1 == y1 ] (GMkRowDecl x1 x2,GMkRowDecl y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GMkRowTypeDecl x1 x2 x3,GMkRowTypeDecl y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] - (GAssignS x1 x2,GAssignS y1 y2) -> and [ x1 == y1 , x2 == y2 ] - (GAtomicConcept x1,GAtomicConcept y1) -> and [ x1 == y1 ] + (GAssignS x1 x2 x3,GAssignS y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] + (GAtomicConcept x1 x2,GAtomicConcept y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GEmptyS,GEmptyS) -> and [ ] - (GEvalS x1,GEvalS y1) -> and [ x1 == y1 ] - (GEvalWhetherS x1,GEvalWhetherS y1) -> and [ x1 == y1 ] - (GExprS x1,GExprS y1) -> and [ x1 == y1 ] - (GLetIsTrue x1 x2,GLetIsTrue y1 y2) -> and [ x1 == y1 , x2 == y2 ] - (GTypeDeclS x1,GTypeDeclS y1) -> and [ x1 == y1 ] + (GEvalS x1 x2,GEvalS y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GEvalWhetherS x1 x2,GEvalWhetherS y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GExprS x1 x2,GExprS y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GLetIsTrue x1 x2 x3,GLetIsTrue y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] + (GTypeDeclS x1 x2,GTypeDeclS y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GMkTypeDecl x1 x2 x3,GMkTypeDecl y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GCeiling,GCeiling) -> and [ ] (GFloor,GFloor) -> and [ ] @@ -293,12 +293,12 @@ instance Gf GExpr where gf (GLet x1 x2) = mkApp (mkCId "Let") [gf x1, gf x2] gf (GLit x1) = mkApp (mkCId "Lit") [gf x1] gf (GNormIsInfringed x1) = mkApp (mkCId "NormIsInfringed") [gf x1] + gf (GOnlyFieldProject x1 x2) = mkApp (mkCId "OnlyFieldProject") [gf x1, gf x2] gf (GPredApp x1 x2) = mkApp (mkCId "PredApp") [gf x1, gf x2] gf (GPredAppMany x1 x2 x3) = mkApp (mkCId "PredAppMany") [gf x1, gf x2, gf x3] gf (GPredicate x1 x2 x3 x4) = mkApp (mkCId "Predicate") [gf x1, gf x2, gf x3, gf x4] gf (GProject x1 x2) = mkApp (mkCId "Project") [gf x1, gf x2] gf (GQuoteVar x1) = mkApp (mkCId "QuoteVar") [gf x1] - gf (GQuotedBinExpr x1 x2 x3) = mkApp (mkCId "QuotedBinExpr") [gf x1, gf x2, gf x3] gf (GRecord x1 x2) = mkApp (mkCId "Record") [gf x1, gf x2] gf (GRound x1 x2) = mkApp (mkCId "Round") [gf x1, gf x2] gf (GSig x1 x2) = mkApp (mkCId "Sig") [gf x1, gf x2] @@ -328,12 +328,12 @@ instance Gf GExpr where Just (i,[x1,x2]) | i == mkCId "Let" -> GLet (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "Lit" -> GLit (fg x1) Just (i,[x1]) | i == mkCId "NormIsInfringed" -> GNormIsInfringed (fg x1) + Just (i,[x1,x2]) | i == mkCId "OnlyFieldProject" -> GOnlyFieldProject (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "PredApp" -> GPredApp (fg x1) (fg x2) Just (i,[x1,x2,x3]) | i == mkCId "PredAppMany" -> GPredAppMany (fg x1) (fg x2) (fg x3) Just (i,[x1,x2,x3,x4]) | i == mkCId "Predicate" -> GPredicate (fg x1) (fg x2) (fg x3) (fg x4) Just (i,[x1,x2]) | i == mkCId "Project" -> GProject (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "QuoteVar" -> GQuoteVar (fg x1) - Just (i,[x1,x2,x3]) | i == mkCId "QuotedBinExpr" -> GQuotedBinExpr (fg x1) (fg x2) (fg x3) Just (i,[x1,x2]) | i == mkCId "Record" -> GRecord (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "Round" -> GRound (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "Sig" -> GSig (fg x1) (fg x2) @@ -478,25 +478,25 @@ instance Gf GRowTypeDecl where _ -> error ("no RowTypeDecl " ++ show t) instance Gf GS where - gf (GAssignS x1 x2) = mkApp (mkCId "AssignS") [gf x1, gf x2] - gf (GAtomicConcept x1) = mkApp (mkCId "AtomicConcept") [gf x1] + gf (GAssignS x1 x2 x3) = mkApp (mkCId "AssignS") [gf x1, gf x2, gf x3] + gf (GAtomicConcept x1 x2) = mkApp (mkCId "AtomicConcept") [gf x1, gf x2] gf GEmptyS = mkApp (mkCId "EmptyS") [] - gf (GEvalS x1) = mkApp (mkCId "EvalS") [gf x1] - gf (GEvalWhetherS x1) = mkApp (mkCId "EvalWhetherS") [gf x1] - gf (GExprS x1) = mkApp (mkCId "ExprS") [gf x1] - gf (GLetIsTrue x1 x2) = mkApp (mkCId "LetIsTrue") [gf x1, gf x2] - gf (GTypeDeclS x1) = mkApp (mkCId "TypeDeclS") [gf x1] + gf (GEvalS x1 x2) = mkApp (mkCId "EvalS") [gf x1, gf x2] + gf (GEvalWhetherS x1 x2) = mkApp (mkCId "EvalWhetherS") [gf x1, gf x2] + gf (GExprS x1 x2) = mkApp (mkCId "ExprS") [gf x1, gf x2] + gf (GLetIsTrue x1 x2 x3) = mkApp (mkCId "LetIsTrue") [gf x1, gf x2, gf x3] + gf (GTypeDeclS x1 x2) = mkApp (mkCId "TypeDeclS") [gf x1, gf x2] fg t = case unApp t of - Just (i,[x1,x2]) | i == mkCId "AssignS" -> GAssignS (fg x1) (fg x2) - Just (i,[x1]) | i == mkCId "AtomicConcept" -> GAtomicConcept (fg x1) + Just (i,[x1,x2,x3]) | i == mkCId "AssignS" -> GAssignS (fg x1) (fg x2) (fg x3) + Just (i,[x1,x2]) | i == mkCId "AtomicConcept" -> GAtomicConcept (fg x1) (fg x2) Just (i,[]) | i == mkCId "EmptyS" -> GEmptyS - Just (i,[x1]) | i == mkCId "EvalS" -> GEvalS (fg x1) - Just (i,[x1]) | i == mkCId "EvalWhetherS" -> GEvalWhetherS (fg x1) - Just (i,[x1]) | i == mkCId "ExprS" -> GExprS (fg x1) - Just (i,[x1,x2]) | i == mkCId "LetIsTrue" -> GLetIsTrue (fg x1) (fg x2) - Just (i,[x1]) | i == mkCId "TypeDeclS" -> GTypeDeclS (fg x1) + Just (i,[x1,x2]) | i == mkCId "EvalS" -> GEvalS (fg x1) (fg x2) + Just (i,[x1,x2]) | i == mkCId "EvalWhetherS" -> GEvalWhetherS (fg x1) (fg x2) + Just (i,[x1,x2]) | i == mkCId "ExprS" -> GExprS (fg x1) (fg x2) + Just (i,[x1,x2,x3]) | i == mkCId "LetIsTrue" -> GLetIsTrue (fg x1) (fg x2) (fg x3) + Just (i,[x1,x2]) | i == mkCId "TypeDeclS" -> GTypeDeclS (fg x1) (fg x2) _ -> error ("no S " ++ show t) @@ -549,12 +549,12 @@ instance Compos Tree where GLet x1 x2 -> r GLet `a` f x1 `a` f x2 GLit x1 -> r GLit `a` f x1 GNormIsInfringed x1 -> r GNormIsInfringed `a` f x1 + GOnlyFieldProject x1 x2 -> r GOnlyFieldProject `a` f x1 `a` f x2 GPredApp x1 x2 -> r GPredApp `a` f x1 `a` f x2 GPredAppMany x1 x2 x3 -> r GPredAppMany `a` f x1 `a` f x2 `a` f x3 GPredicate x1 x2 x3 x4 -> r GPredicate `a` f x1 `a` f x2 `a` f x3 `a` f x4 GProject x1 x2 -> r GProject `a` f x1 `a` f x2 GQuoteVar x1 -> r GQuoteVar `a` f x1 - GQuotedBinExpr x1 x2 x3 -> r GQuotedBinExpr `a` f x1 `a` f x2 `a` f x3 GRecord x1 x2 -> r GRecord `a` f x1 `a` f x2 GRound x1 x2 -> r GRound `a` f x1 `a` f x2 GSig x1 x2 -> r GSig `a` f x1 `a` f x2 @@ -572,13 +572,13 @@ instance Compos Tree where GMkName x1 -> r GMkName `a` f x1 GMkRowDecl x1 x2 -> r GMkRowDecl `a` f x1 `a` f x2 GMkRowTypeDecl x1 x2 x3 -> r GMkRowTypeDecl `a` f x1 `a` f x2 `a` f x3 - GAssignS x1 x2 -> r GAssignS `a` f x1 `a` f x2 - GAtomicConcept x1 -> r GAtomicConcept `a` f x1 - GEvalS x1 -> r GEvalS `a` f x1 - GEvalWhetherS x1 -> r GEvalWhetherS `a` f x1 - GExprS x1 -> r GExprS `a` f x1 - GLetIsTrue x1 x2 -> r GLetIsTrue `a` f x1 `a` f x2 - GTypeDeclS x1 -> r GTypeDeclS `a` f x1 + GAssignS x1 x2 x3 -> r GAssignS `a` f x1 `a` f x2 `a` f x3 + GAtomicConcept x1 x2 -> r GAtomicConcept `a` f x1 `a` f x2 + GEvalS x1 x2 -> r GEvalS `a` f x1 `a` f x2 + GEvalWhetherS x1 x2 -> r GEvalWhetherS `a` f x1 `a` f x2 + GExprS x1 x2 -> r GExprS `a` f x1 `a` f x2 + GLetIsTrue x1 x2 x3 -> r GLetIsTrue `a` f x1 `a` f x2 `a` f x3 + GTypeDeclS x1 x2 -> r GTypeDeclS `a` f x1 `a` f x2 GMkTypeDecl x1 x2 x3 -> r GMkTypeDecl `a` f x1 `a` f x2 `a` f x3 GListExpr x1 -> r GListExpr `a` foldr (a . a (r (:)) . f) (r []) x1 GListIfThen x1 -> r GListIfThen `a` foldr (a . a (r (:)) . f) (r []) x1 diff --git a/lam4-backend/src/Lam4/Render/Render.hs b/lam4-backend/src/Lam4/Render/Render.hs index 6e79bd41..90f32c76 100644 --- a/lam4-backend/src/Lam4/Render/Render.hs +++ b/lam4-backend/src/Lam4/Render/Render.hs @@ -71,21 +71,17 @@ initializeGFLang str gr = postprocessText :: T.Text -> T.Text -postprocessText = newlines . tabs . rmBIND +postprocessText = rmBIND . newlines -- . any other postprocessing functions here where -- TODO: the following could be cleaned up / made clearer rmBIND :: T.Text -> T.Text rmBIND input = input & [regex|\s+&\+\s+|] . match %~ const "" - tabs :: T.Text -> T.Text - tabs = T.map (\c -> if c == '°' then ' ' else c) - newlines :: T.Text -> T.Text newlines = T.map (\c -> if c == '∞' then '\n' else c) style :: T.Text -style = [r| - +style = [r| -|] + |] -- | Entrypoint renderCstProgramToNL :: NLGEnv -> CSTProgram -> T.Text @@ -208,22 +186,30 @@ renderCstDeclToNL env = gfLin env . gf . genericTreeTrans . parseDecl renderCstDeclToGFtrees :: NLGEnv -> Decl -> T.Text renderCstDeclToGFtrees env = gfTree env . gf . genericTreeTrans . parseDecl + +-- TODO: do we flatten nested Let-definitions? +-- for royalflush case, that'd be the best thing to do +-- how about generally? parseDecl :: Decl -> GS parseDecl = \case - DataDecl name typedecl -> GTypeDeclS $ parseTypeDecl name typedecl + DataDecl name typedecl -> GTypeDeclS dummyId $ parseTypeDecl name typedecl Rec name expr -> if commonFunction name.name - then GExprS $ GKnownFunction $ parseName name - else GExprS $ parseExpr name expr - NonRec name (Sig [] []) -> GAtomicConcept (parseName name) + then GExprS dummyId $ GKnownFunction $ parseName name + else GExprS dummyId $ parseExpr name expr + NonRec name (Sig [] []) -> GAtomicConcept dummyId (parseName name) NonRec name expr@(BinExpr binop _ _) -> if booleanOp binop - then GLetIsTrue (parseName name) $ parseExpr noName expr - else GAssignS (parseName name) $ parseExpr noName expr - NonRec name expr -> GAssignS (parseName name) $ parseExpr noName expr + then GLetIsTrue dummyId (parseName name) $ parseExpr noName expr + else GAssignS dummyId (parseName name) $ parseExpr noName expr + NonRec name expr -> GAssignS dummyId (parseName name) $ parseExpr noName expr Eval expr -> quoteVars $ if isBool expr - then GEvalWhetherS $ parseExpr noName expr - else GEvalS $ parseExpr noName expr + then GEvalWhetherS dummyId $ parseExpr noName expr + else GEvalS dummyId $ parseExpr noName expr + +-- to wrap all declarations in

+dummyId :: GString +dummyId = GString "paragraph_999999" noName :: N.Name noName = N.MkName mempty Nothing N.NotEntrypoint @@ -263,8 +249,8 @@ quoteVars x = composOp quoteVars x -- Control verbosity of BinExpr in specific contexts binExprVerbosity :: Tree a -> Tree a -binExprVerbosity (GAssignS e (GBinExpr op lc rc)) = GAssignS e (GVerboseBinExpr op (unVerboseBinExpr lc) (unVerboseBinExpr rc)) -binExprVerbosity (GLetIsTrue e (GBinExpr op lc rc)) = GLetIsTrue e (GVerboseBinExpr op (unVerboseBinExpr lc) (unVerboseBinExpr rc)) +binExprVerbosity (GAssignS id_ e (GBinExpr op lc rc)) = GAssignS id_ e (GVerboseBinExpr op (unVerboseBinExpr lc) (unVerboseBinExpr rc)) +binExprVerbosity (GLetIsTrue id_ e (GBinExpr op lc rc)) = GLetIsTrue id_ e (GVerboseBinExpr op (unVerboseBinExpr lc) (unVerboseBinExpr rc)) binExprVerbosity (GVerboseBinExpr op lc rc) = GVerboseBinExpr op (unVerboseBinExpr lc) (unVerboseBinExpr rc) binExprVerbosity x = composOp binExprVerbosity x @@ -422,7 +408,7 @@ parseExpr name = else GFunApp (f fun) (GListExpr $ fmap f args) -- FunApp fun args -> GFunApp (f fun) (GListExpr $ fmap f args) -- Record rows -> GRecord - Project record label -> GProject (f record) (parseNameForRecord label) + Project record label -> GOnlyFieldProject (f record) (parseNameForRecord label) -- TODO: annotation to decide whether to print out the record name or only label? Fun md args body -> GFun (parseName name) (parseFunMetadata md) (GListName $ fmap parseName args) (f body) -- Let decl body -> Let decl (f body) Predicate md args body -> GPredicate (parseName name) (parseFunMetadata md) (GListName $ fmap parseName args) (f body) From a0f1d9c3c5c6ba7591b2615bd75d9397b182ce3d Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Wed, 20 Nov 2024 13:54:31 +0100 Subject: [PATCH 10/14] WIP: remove overly specific functions --- lam4-backend/gf-grammar/Lam4.gf | 31 ++++++------------------ lam4-backend/gf-grammar/Lam4.pgf | Bin 11815 -> 11402 bytes lam4-backend/gf-grammar/Lam4Eng.gf | 18 +------------- lam4-backend/src/Lam4/Render/Lam4Gf.hs | 20 ---------------- lam4-backend/src/Lam4/Render/Render.hs | 32 +++++++++++++------------ 5 files changed, 25 insertions(+), 76 deletions(-) diff --git a/lam4-backend/gf-grammar/Lam4.gf b/lam4-backend/gf-grammar/Lam4.gf index 232440b5..20b53dbb 100644 --- a/lam4-backend/gf-grammar/Lam4.gf +++ b/lam4-backend/gf-grammar/Lam4.gf @@ -64,7 +64,7 @@ abstract Lam4 = { VerboseBinExpr, -- newline + quotes around args BinExpr : BinOp -> Expr -> Expr -> Expr ; - UnaryMinusExpr, Known, Certain, Unknown, Uncertain : Expr -> Expr ; + UnaryMinusExpr : Expr -> Expr ; Round : (expr, prec : Expr) -> Expr ; Default : (val, default : Expr) -> Expr ; @@ -143,8 +143,11 @@ abstract Lam4 = { Predicate : (predname : Name) -> Metadata -> (args : [Name]) -> Expr -> Expr ; -- Differs from a function when doing symbolic evaluation. Exact way in which they should differ is WIP. - PredApp : Expr -> [Expr] -> Expr ; - PredAppMany : BinOp -> (business_is_good : [Expr]) -> (uncertain_unknown : [Expr]) -> Expr ; + + PredApp : (pred : Expr) -> (args : [Expr]) -> Expr ; + + -- Aggregation of multiple PredApps being applied to the same argument(s). + PredAppMany : BinOp -> (preds : [Expr]) -> (args : [Expr]) -> Expr ; Fold : Expr -> Expr -> Expr -> Expr ; -- When generating natural language for some file that defines a bunch of stuff like cons, map, filter, @@ -173,24 +176,4 @@ abstract Lam4 = { Ge : BinOp ; -- ^ greater-than-or-equal Eq : BinOp ; -- ^ equality (of Booleans, numbers or atoms) Ne : BinOp ; -- ^ inequality (of Booleans, numbers or atoms) -} - -{- -— -LOTTERY { - — how much can be won from the jackpot - `total jackpot`: Integer, - — whether buying tickets from this lottery is tax deductible - `tax deductible status`: Boolean -} - - -This can be rendered as: - -MkTypeDecl (MkMetadata "a game where you lose money") "Lottery" (ConsRowTypeDecl (MkRowDecl (MkMetadata "how much can be won from the jackpot") "‘total jackpot’") (ConsRowTypeDecl (MkRowDecl (MkMetadata "whether buying tickets from this lottery is tax deductible") "‘tax deductible status’") BaseRowTypeDecl)) - -A/An ‘Lottery’ is . -Each lottery has associated with it information like - * its ‘total jackpot’; i.e., how much can be won from the jackpot - * its ‘tax deductible status’; i.e., whether buying tickets from this lottery is tax deductible --} \ No newline at end of file +} \ No newline at end of file diff --git a/lam4-backend/gf-grammar/Lam4.pgf b/lam4-backend/gf-grammar/Lam4.pgf index 44214023f61b15a200d55000b15b51565dee2b3c..85d9a14a409254fc03d8224cc98a15d42f5c1be3 100644 GIT binary patch delta 2068 zcmaJ=OK%%h6#nkL^RPXRo#xRrfLaC1dXEPtZR=XIL!Hvs zGi9^nB}j48Sog`aZRR|}rpuOx6^?l~L961>gc9pZS9L3H7IiO0OIXEH#>(o8Z^4qfKNL$EK90`Xh0R1UVXYVV$<%XIuXtH-a^lu03x3g^{(|gN{FfRgJNc@@W|qjAg7GD3O^o zGE_dzs8QtiQQS#Fg8!ej75`VY>Z!L!31xCEx91Kc@7A973{w(!I(i?FY3Hln&$?#n zM}-h2zL_so771wl20ePlxg0wZNJ!%3kPFVIv6y;}&Xnk}v(A&)sMFflNm5R%?_hT_ zoHBAbQ+H1e>6Pm%LJu!HcHiD=I+(h?VBeb3vnH8qspF+eUa#}{fAED+>bf7i)J#^J z$;D=}qNMCx*|h17V%>@MPX^CRb7r|n4^26%{R0D&&BumJ zY-8iw*qHOE|08F0{}Sz*WEiIe@(sVFb`a(ZbCE=I$s4 z3A*qifr4XHY%xv{s2FE;OfVs#4c&N#(@7DRFeQwPxG)ONFjR$#AR#_y-5N>4RkIWw z+_fOEEXF4j0M zxgE-)%}vTb1h<5X;5Nmxyl6!j1#eJjoV_WGf;$vDc}o3%+$BPLkBFXJM;S)l0!yyR zawj8rho=#VpcgW!;w2H26pA4MWE>PmQ7K}S-zSP;@lgX5ef)Ou_mD7wAVEJu1c$|- zL5<>w03p0Aj20%CLkqz?A_V&pB{)jaj$N$;IqV=z*@CCHV45`&#Nxf>`8zu$thvP^c+~|_yvFKXB6!^e f(Va2|fHB}4unxS9F3ML)-bG1-M7wLh4W`K7R#5!T delta 2412 zcmaJ>NpBQK7=2YW-LrbZ3&ueph_MY=!I(7=2jgXI20Y%)YB1xOwrSk%9;T-OXB$XD zBB4Y|(z!;$mn@e^$Oo?Z4T%zQL^ZN9gB6mymz4z@^{Z&7{^4-E0ZORlI zGz;#Ztoh5{Bhe@Do~O6&l7;|Bhc(^M%@y}Sss|FUh0T`S1)Lyu=|wlkv`AaF%lBDSve>1l5#K+#L_W8?g!<( zG{02#OMF1>m)KCdUso=e*1auzc3rhYW*_&n|DwvS+?VR(s<|wh-rR`x(PYpNo3P5_ zeB8g{ho#?S$=lpOqQfmq}<%0WVgf%$=wn^Om<29W3or$7d5ykwIKCQYGgXtN_;-7zSTF5&ikEh z<>UU8YL^vWq)th^r|$R4o^V={gTzh)3mwmk(`;%<|kV%}g7%7OIjN(=O-uiOf1{p{}k*myuQc z8IwNV#PRg`vTlij-owVVphaGvjq9@Ch6$^*ma#MDa*5wGO?KNjX&URJx@HunO4e;H zF9V`eC9P1?dNSbIoVgxWiwm8e&z0qFcvO(Z-#=p0j#bt!=HyAMGg{s%$@Kq-abk)?z4{1ljr46^Q@cR_f6XcZ#oH4(`&`@`Yi7y zeTSYHcmLjZES8OkVI|kxgYD`&25c7Yc^v zPc7+Gyz{3=uYT3Fw=x^guFhEZMzp*^=IT5=w_emdKK~znF_B%B#v8R{v6d{L zDmaEkdoM+@{N~ZV%XC7cr)T05x{+CSpL7k!uSBK{$EHWlxqo!^^o-TcC>ec)rC(tq z?ojvF+pEJvhQhHS!|re0-*%n?`hhXv954yY1DAj$AP*FP+rTQwA$Mc{&I-XB1Z_A( zpyEx+zdONcf+&WVhY5xwXhJ()<8(yWBS;IOU{nYdnb7gPh`r#a$O=3`c;pmC3&(Q; zuZTq#9!)TWh@i42qyke26&B;O*T&zX4^-R{K;@c}4^-HGLvbEZ_F;lU$A?J{@A?() zi8A*oUkKKPir^iJojldMLa2C;B3a?|eJ(kzP;BQu4~g*n&|5$9){ptxghxa)z-^S_ zte@_pFEp-X1fK}!2tg+lf?i>Ys1%0{C-g!5lb{iE9ji}EKaZ= z34&vy?Rb*nxBv;95F(i(m_Z%EEb0jkpn>2dMKg9Z5-ejI!DWJf_)}>jxDvqT2(D5z z^5|<6+qhU@9&5sNCb+wCa98Cm;BD%M@-EL*;XoBmv%o f.s ++ "holds for" ++ conjX "and" xs } } ; - PredAppMany op args preds = { + PredAppMany op preds args = { s = quote (conjX "and" args) ++ "is" ++ conjX (op.s ! Verbose) preds } ; diff --git a/lam4-backend/src/Lam4/Render/Lam4Gf.hs b/lam4-backend/src/Lam4/Render/Lam4Gf.hs index e4533e69..f06a6772 100644 --- a/lam4-backend/src/Lam4/Render/Lam4Gf.hs +++ b/lam4-backend/src/Lam4/Render/Lam4Gf.hs @@ -95,7 +95,6 @@ data Tree :: * -> * where GPlus :: Tree GBinOp_ GApplyListOp :: GListOp -> GListLExpr -> Tree GExpr_ GBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ - GCertain :: GExpr -> Tree GExpr_ GConjExpr :: GListExpr -> Tree GExpr_ GDefault :: GExpr -> GExpr -> Tree GExpr_ GElif :: GListIfThen -> Tree GExpr_ @@ -105,7 +104,6 @@ data Tree :: * -> * where GIfThenElse :: GExpr -> GExpr -> GExpr -> Tree GExpr_ GInstanceSum :: GExpr -> Tree GExpr_ GInstanceSumIf :: GExpr -> GExpr -> Tree GExpr_ - GKnown :: GExpr -> Tree GExpr_ GKnownFunction :: GName -> Tree GExpr_ GLet :: GS -> GExpr -> Tree GExpr_ GLit :: GName -> Tree GExpr_ @@ -121,8 +119,6 @@ data Tree :: * -> * where GSig :: GListName -> GListExpr -> Tree GExpr_ GUnary :: GUnaryOp -> GExpr -> Tree GExpr_ GUnaryMinusExpr :: GExpr -> Tree GExpr_ - GUncertain :: GExpr -> Tree GExpr_ - GUnknown :: GExpr -> Tree GExpr_ GVar :: GName -> Tree GExpr_ GVerboseBinExpr :: GBinOp -> GExpr -> GExpr -> Tree GExpr_ GFirstIfThen :: GExpr -> GExpr -> Tree GIfThen_ @@ -176,7 +172,6 @@ instance Eq (Tree a) where (GPlus,GPlus) -> and [ ] (GApplyListOp x1 x2,GApplyListOp y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GBinExpr x1 x2 x3,GBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] - (GCertain x1,GCertain y1) -> and [ x1 == y1 ] (GConjExpr x1,GConjExpr y1) -> and [ x1 == y1 ] (GDefault x1 x2,GDefault y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GElif x1,GElif y1) -> and [ x1 == y1 ] @@ -186,7 +181,6 @@ instance Eq (Tree a) where (GIfThenElse x1 x2 x3,GIfThenElse y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GInstanceSum x1,GInstanceSum y1) -> and [ x1 == y1 ] (GInstanceSumIf x1 x2,GInstanceSumIf y1 y2) -> and [ x1 == y1 , x2 == y2 ] - (GKnown x1,GKnown y1) -> and [ x1 == y1 ] (GKnownFunction x1,GKnownFunction y1) -> and [ x1 == y1 ] (GLet x1 x2,GLet y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GLit x1,GLit y1) -> and [ x1 == y1 ] @@ -202,8 +196,6 @@ instance Eq (Tree a) where (GSig x1 x2,GSig y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GUnary x1 x2,GUnary y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GUnaryMinusExpr x1,GUnaryMinusExpr y1) -> and [ x1 == y1 ] - (GUncertain x1,GUncertain y1) -> and [ x1 == y1 ] - (GUnknown x1,GUnknown y1) -> and [ x1 == y1 ] (GVar x1,GVar y1) -> and [ x1 == y1 ] (GVerboseBinExpr x1 x2 x3,GVerboseBinExpr y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GFirstIfThen x1 x2,GFirstIfThen y1 y2) -> and [ x1 == y1 , x2 == y2 ] @@ -278,7 +270,6 @@ instance Gf GBinOp where instance Gf GExpr where gf (GApplyListOp x1 x2) = mkApp (mkCId "ApplyListOp") [gf x1, gf x2] gf (GBinExpr x1 x2 x3) = mkApp (mkCId "BinExpr") [gf x1, gf x2, gf x3] - gf (GCertain x1) = mkApp (mkCId "Certain") [gf x1] gf (GConjExpr x1) = mkApp (mkCId "ConjExpr") [gf x1] gf (GDefault x1 x2) = mkApp (mkCId "Default") [gf x1, gf x2] gf (GElif x1) = mkApp (mkCId "Elif") [gf x1] @@ -288,7 +279,6 @@ instance Gf GExpr where gf (GIfThenElse x1 x2 x3) = mkApp (mkCId "IfThenElse") [gf x1, gf x2, gf x3] gf (GInstanceSum x1) = mkApp (mkCId "InstanceSum") [gf x1] gf (GInstanceSumIf x1 x2) = mkApp (mkCId "InstanceSumIf") [gf x1, gf x2] - gf (GKnown x1) = mkApp (mkCId "Known") [gf x1] gf (GKnownFunction x1) = mkApp (mkCId "KnownFunction") [gf x1] gf (GLet x1 x2) = mkApp (mkCId "Let") [gf x1, gf x2] gf (GLit x1) = mkApp (mkCId "Lit") [gf x1] @@ -304,8 +294,6 @@ instance Gf GExpr where gf (GSig x1 x2) = mkApp (mkCId "Sig") [gf x1, gf x2] gf (GUnary x1 x2) = mkApp (mkCId "Unary") [gf x1, gf x2] gf (GUnaryMinusExpr x1) = mkApp (mkCId "UnaryMinusExpr") [gf x1] - gf (GUncertain x1) = mkApp (mkCId "Uncertain") [gf x1] - gf (GUnknown x1) = mkApp (mkCId "Unknown") [gf x1] gf (GVar x1) = mkApp (mkCId "Var") [gf x1] gf (GVerboseBinExpr x1 x2 x3) = mkApp (mkCId "VerboseBinExpr") [gf x1, gf x2, gf x3] @@ -313,7 +301,6 @@ instance Gf GExpr where case unApp t of Just (i,[x1,x2]) | i == mkCId "ApplyListOp" -> GApplyListOp (fg x1) (fg x2) Just (i,[x1,x2,x3]) | i == mkCId "BinExpr" -> GBinExpr (fg x1) (fg x2) (fg x3) - Just (i,[x1]) | i == mkCId "Certain" -> GCertain (fg x1) Just (i,[x1]) | i == mkCId "ConjExpr" -> GConjExpr (fg x1) Just (i,[x1,x2]) | i == mkCId "Default" -> GDefault (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "Elif" -> GElif (fg x1) @@ -323,7 +310,6 @@ instance Gf GExpr where Just (i,[x1,x2,x3]) | i == mkCId "IfThenElse" -> GIfThenElse (fg x1) (fg x2) (fg x3) Just (i,[x1]) | i == mkCId "InstanceSum" -> GInstanceSum (fg x1) Just (i,[x1,x2]) | i == mkCId "InstanceSumIf" -> GInstanceSumIf (fg x1) (fg x2) - Just (i,[x1]) | i == mkCId "Known" -> GKnown (fg x1) Just (i,[x1]) | i == mkCId "KnownFunction" -> GKnownFunction (fg x1) Just (i,[x1,x2]) | i == mkCId "Let" -> GLet (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "Lit" -> GLit (fg x1) @@ -339,8 +325,6 @@ instance Gf GExpr where Just (i,[x1,x2]) | i == mkCId "Sig" -> GSig (fg x1) (fg x2) Just (i,[x1,x2]) | i == mkCId "Unary" -> GUnary (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "UnaryMinusExpr" -> GUnaryMinusExpr (fg x1) - Just (i,[x1]) | i == mkCId "Uncertain" -> GUncertain (fg x1) - Just (i,[x1]) | i == mkCId "Unknown" -> GUnknown (fg x1) Just (i,[x1]) | i == mkCId "Var" -> GVar (fg x1) Just (i,[x1,x2,x3]) | i == mkCId "VerboseBinExpr" -> GVerboseBinExpr (fg x1) (fg x2) (fg x3) @@ -534,7 +518,6 @@ instance Compos Tree where compos r a f t = case t of GApplyListOp x1 x2 -> r GApplyListOp `a` f x1 `a` f x2 GBinExpr x1 x2 x3 -> r GBinExpr `a` f x1 `a` f x2 `a` f x3 - GCertain x1 -> r GCertain `a` f x1 GConjExpr x1 -> r GConjExpr `a` f x1 GDefault x1 x2 -> r GDefault `a` f x1 `a` f x2 GElif x1 -> r GElif `a` f x1 @@ -544,7 +527,6 @@ instance Compos Tree where GIfThenElse x1 x2 x3 -> r GIfThenElse `a` f x1 `a` f x2 `a` f x3 GInstanceSum x1 -> r GInstanceSum `a` f x1 GInstanceSumIf x1 x2 -> r GInstanceSumIf `a` f x1 `a` f x2 - GKnown x1 -> r GKnown `a` f x1 GKnownFunction x1 -> r GKnownFunction `a` f x1 GLet x1 x2 -> r GLet `a` f x1 `a` f x2 GLit x1 -> r GLit `a` f x1 @@ -560,8 +542,6 @@ instance Compos Tree where GSig x1 x2 -> r GSig `a` f x1 `a` f x2 GUnary x1 x2 -> r GUnary `a` f x1 `a` f x2 GUnaryMinusExpr x1 -> r GUnaryMinusExpr `a` f x1 - GUncertain x1 -> r GUncertain `a` f x1 - GUnknown x1 -> r GUnknown `a` f x1 GVar x1 -> r GVar `a` f x1 GVerboseBinExpr x1 x2 x3 -> r GVerboseBinExpr `a` f x1 `a` f x2 `a` f x3 GFirstIfThen x1 x2 -> r GFirstIfThen `a` f x1 `a` f x2 diff --git a/lam4-backend/src/Lam4/Render/Render.hs b/lam4-backend/src/Lam4/Render/Render.hs index 90f32c76..1a29a0de 100644 --- a/lam4-backend/src/Lam4/Render/Render.hs +++ b/lam4-backend/src/Lam4/Render/Render.hs @@ -262,19 +262,11 @@ unVerboseBinExpr x = composOp unVerboseBinExpr x aggregatePredApp :: Tree a -> Tree a aggregatePredApp tree@(GBinExpr op (GPredApp f arg) (GPredApp g arg')) = if sameTree arg arg' - then GPredAppMany op arg (GListExpr [f,g]) + then GPredAppMany op (GListExpr [f,g]) arg else tree aggregatePredApp tree@(GVerboseBinExpr op (GPredApp f arg) (GPredApp g arg')) = if sameTree arg arg' - then GPredAppMany op arg (GListExpr [f,g]) - else tree -aggregatePredApp tree@(GBinExpr op (GFunApp f arg) (GFunApp g arg')) = - if sameTree arg arg' - then GPredAppMany op arg (GListExpr [f,g]) - else tree -aggregatePredApp tree@(GVerboseBinExpr op (GFunApp f arg) (GFunApp g arg')) = - if sameTree arg arg' - then GPredAppMany op arg (GListExpr [f,g]) + then GPredAppMany op (GListExpr [f,g]) arg else tree aggregatePredApp x = composOp aggregatePredApp x @@ -396,13 +388,24 @@ parseExpr name = -- other BinExprs are "verbose" = newlines and stuff BinExpr op lc rc -> GVerboseBinExpr (parseBinOp op) (f lc) (f rc) IfThenElse cond thn els -> GIfThenElse (f cond) (f thn) (f els) - FunApp (Var (N.MkName "instanceSumIf" _ _)) args -> parseInstanceSum args - FunApp (Var (N.MkName "instanceSum" _ _)) args -> parseInstanceSum args - FunApp (Var (N.MkName "round" _ _)) args -> parseRound args - FunApp (Var (N.MkName "default" _ _)) args -> parseDefault args + + -- Basic arithmetic operations that have been defined as custom function FunApp (Var (N.MkName "div" _ _)) [lc,rc] -> parseExpr name (BinExpr Divide lc rc) FunApp (Var (N.MkName "mult" _ _)) [lc,rc] -> parseExpr name (BinExpr Mult lc rc) FunApp (Var (N.MkName "add" _ _)) [lc,rc] -> parseExpr name (BinExpr Plus lc rc) + + -- Basic arithmetic operation that is hardly domain-specific + -- Current linearization of Round takes Expr, Int + -- and just outputs the Expr instead of "Expr rounded into precision of Int decimals" + -- But this should be configurable. + FunApp (Var (N.MkName "round" _ _)) args -> parseRound args + + -- These should be replaced with a general annotation-based approach + FunApp (Var (N.MkName "default" _ _)) args -> parseDefault args + FunApp (Var (N.MkName "instanceSumIf" _ _)) args -> parseInstanceSum args + FunApp (Var (N.MkName "instanceSum" _ _)) args -> parseInstanceSum args + + FunApp fun args -> if isPredicate fun then parseExpr name (PredApp fun args) else GFunApp (f fun) (GListExpr $ fmap f args) @@ -410,7 +413,6 @@ parseExpr name = -- Record rows -> GRecord Project record label -> GOnlyFieldProject (f record) (parseNameForRecord label) -- TODO: annotation to decide whether to print out the record name or only label? Fun md args body -> GFun (parseName name) (parseFunMetadata md) (GListName $ fmap parseName args) (f body) --- Let decl body -> Let decl (f body) Predicate md args body -> GPredicate (parseName name) (parseFunMetadata md) (GListName $ fmap parseName args) (f body) PredApp predicate args -> GPredApp (f predicate) (GListExpr $ fmap f args) Foldr combine nil over -> GFold (f combine) (f nil) (f over) From e77645d83bba8314db5a4210d71f32921fe73ae7 Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Thu, 21 Nov 2024 00:00:23 +0100 Subject: [PATCH 11/14] remove InstanceSum* and replace with generic FunApp* --- lam4-backend/gf-grammar/Lam4.gf | 14 ++- lam4-backend/gf-grammar/Lam4.pgf | Bin 11402 -> 11400 bytes lam4-backend/gf-grammar/Lam4Eng.gf | 16 ++-- lam4-backend/src/Lam4/Render/Lam4Gf.hs | 20 ++--- lam4-backend/src/Lam4/Render/Render.hs | 119 +++++++++++++------------ 5 files changed, 87 insertions(+), 82 deletions(-) diff --git a/lam4-backend/gf-grammar/Lam4.gf b/lam4-backend/gf-grammar/Lam4.gf index 20b53dbb..02be0d7c 100644 --- a/lam4-backend/gf-grammar/Lam4.gf +++ b/lam4-backend/gf-grammar/Lam4.gf @@ -85,15 +85,11 @@ abstract Lam4 = { -} -{- [The investor's total allocation in Energy] - is calculated by (AssignS) - adding up (InstanceSumIf) - [the investor's funds allocated to the investment as per sector share] - where - [the investment is in Energy] --} - InstanceSumIf : (entities, condition : Expr)-> Expr ; - InstanceSum : (entities : Expr) -> Expr ; + -- For linearizing functions that have a NLG annotation + FunApp1 : (description : String) -> (arg : Expr) -> Expr ; + FunApp2 : (desc1 : String) -> (arg1 : Expr) -> (desc2 : String) -> (arg2 : Expr) -> Expr ; + + -- For linearizing functions that don't have NLG annotation FunApp : Expr -> [Expr] -> Expr ; -- Record : (Row Expr) -> Expr ; -- record construction OnlyFieldProject, diff --git a/lam4-backend/gf-grammar/Lam4.pgf b/lam4-backend/gf-grammar/Lam4.pgf index 85d9a14a409254fc03d8224cc98a15d42f5c1be3..e4f44070b3eb81176909f47c1f40edbf74a456b3 100644 GIT binary patch delta 360 zcmeB*?1RtkAW??q$o2loq>Tlu_%4AAe)2@ zRG|?I11m_OAwmfYP>CS}i)%$e5d%ch2vyPuWWeOftm&I`*uFBevlJAirZBKf-pHlC zxrgf~vjofy_KQ4KCIJ!5s>!u{(wh(QO=X+>PlT75k%3{7xSW6hGmA}1jva_Bv4e=>9CHhYRLW&-KmyjUWSn@K@wvam`Elf2^OnJRm=VU{w= zz^r4GWpYntvhikeFJUtG;_^%j$w0J4+aL$$!!`%N^VRH a|AC;Mfsw(T1*@QfUbQ delta 332 zcmeB(?26nlnRT)*6XI^nhVqS7;aA__h14n9JNoGlAYVjm?32j~^DbF+}gd_ut zYehj30|RGreqIVtd43*H`Q|RRugpx01)E#AlvpMo;}cdwHrjrXr^+NCLN#;qMZURg zo4<=rWs>A%X0b`hu>+AMcFb&vDJhwG>C8-}1(WAX$f*e9l4WKs$;dBGWoF7x11X$* zMvRw@wLBxWD0T8d5xL2EqP&}DO5|}f$tg_cRB2(7m7mU8- nn#jZ`Gx?_aR2DY|2KUKD8btyg%nXcR=n0~{m^QO%HZcPL0Y79- diff --git a/lam4-backend/gf-grammar/Lam4Eng.gf b/lam4-backend/gf-grammar/Lam4Eng.gf index fabf28b2..d853659a 100644 --- a/lam4-backend/gf-grammar/Lam4Eng.gf +++ b/lam4-backend/gf-grammar/Lam4Eng.gf @@ -238,17 +238,19 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { ConsIfThen = consIfThen ; Elif its = its ; -- {s = ul its.s} ; - -- : Expr -> Expr -> Expr ; - InstanceSumIf entities condition = { - s = dl "adding up those of" entities.s - ++ dl "where" condition.s + + -- : (description : String) -> (arg : Expr) -> Expr ; + FunApp1 adding_up entities = { + s = dl adding_up.s entities.s } ; - -- : Expr -> Expr ; - InstanceSum entities = { - s = dl "adding up" entities.s + -- : (desc1 : String) -> (arg1 : Expr) -> (desc2 : String) -> (arg2 : Expr) -> Expr ; + FunApp2 desc1 entities desc2 condition = { + s = dl desc1.s entities.s + ++ dl desc2.s condition.s } ; + -- If no annotation available, just put together function and arguments in a definition list -- : Expr -> [Expr] -> Expr ; FunApp f xs = { s = dl f.s (linArgs "" xs) diff --git a/lam4-backend/src/Lam4/Render/Lam4Gf.hs b/lam4-backend/src/Lam4/Render/Lam4Gf.hs index f06a6772..d4343cce 100644 --- a/lam4-backend/src/Lam4/Render/Lam4Gf.hs +++ b/lam4-backend/src/Lam4/Render/Lam4Gf.hs @@ -101,9 +101,9 @@ data Tree :: * -> * where GFold :: GExpr -> GExpr -> GExpr -> Tree GExpr_ GFun :: GName -> GMetadata -> GListName -> GExpr -> Tree GExpr_ GFunApp :: GExpr -> GListExpr -> Tree GExpr_ + GFunApp1 :: GString -> GExpr -> Tree GExpr_ + GFunApp2 :: GString -> GExpr -> GString -> GExpr -> Tree GExpr_ GIfThenElse :: GExpr -> GExpr -> GExpr -> Tree GExpr_ - GInstanceSum :: GExpr -> Tree GExpr_ - GInstanceSumIf :: GExpr -> GExpr -> Tree GExpr_ GKnownFunction :: GName -> Tree GExpr_ GLet :: GS -> GExpr -> Tree GExpr_ GLit :: GName -> Tree GExpr_ @@ -178,9 +178,9 @@ instance Eq (Tree a) where (GFold x1 x2 x3,GFold y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] (GFun x1 x2 x3 x4,GFun y1 y2 y3 y4) -> and [ x1 == y1 , x2 == y2 , x3 == y3 , x4 == y4 ] (GFunApp x1 x2,GFunApp y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GFunApp1 x1 x2,GFunApp1 y1 y2) -> and [ x1 == y1 , x2 == y2 ] + (GFunApp2 x1 x2 x3 x4,GFunApp2 y1 y2 y3 y4) -> and [ x1 == y1 , x2 == y2 , x3 == y3 , x4 == y4 ] (GIfThenElse x1 x2 x3,GIfThenElse y1 y2 y3) -> and [ x1 == y1 , x2 == y2 , x3 == y3 ] - (GInstanceSum x1,GInstanceSum y1) -> and [ x1 == y1 ] - (GInstanceSumIf x1 x2,GInstanceSumIf y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GKnownFunction x1,GKnownFunction y1) -> and [ x1 == y1 ] (GLet x1 x2,GLet y1 y2) -> and [ x1 == y1 , x2 == y2 ] (GLit x1,GLit y1) -> and [ x1 == y1 ] @@ -276,9 +276,9 @@ instance Gf GExpr where gf (GFold x1 x2 x3) = mkApp (mkCId "Fold") [gf x1, gf x2, gf x3] gf (GFun x1 x2 x3 x4) = mkApp (mkCId "Fun") [gf x1, gf x2, gf x3, gf x4] gf (GFunApp x1 x2) = mkApp (mkCId "FunApp") [gf x1, gf x2] + gf (GFunApp1 x1 x2) = mkApp (mkCId "FunApp1") [gf x1, gf x2] + gf (GFunApp2 x1 x2 x3 x4) = mkApp (mkCId "FunApp2") [gf x1, gf x2, gf x3, gf x4] gf (GIfThenElse x1 x2 x3) = mkApp (mkCId "IfThenElse") [gf x1, gf x2, gf x3] - gf (GInstanceSum x1) = mkApp (mkCId "InstanceSum") [gf x1] - gf (GInstanceSumIf x1 x2) = mkApp (mkCId "InstanceSumIf") [gf x1, gf x2] gf (GKnownFunction x1) = mkApp (mkCId "KnownFunction") [gf x1] gf (GLet x1 x2) = mkApp (mkCId "Let") [gf x1, gf x2] gf (GLit x1) = mkApp (mkCId "Lit") [gf x1] @@ -307,9 +307,9 @@ instance Gf GExpr where Just (i,[x1,x2,x3]) | i == mkCId "Fold" -> GFold (fg x1) (fg x2) (fg x3) Just (i,[x1,x2,x3,x4]) | i == mkCId "Fun" -> GFun (fg x1) (fg x2) (fg x3) (fg x4) Just (i,[x1,x2]) | i == mkCId "FunApp" -> GFunApp (fg x1) (fg x2) + Just (i,[x1,x2]) | i == mkCId "FunApp1" -> GFunApp1 (fg x1) (fg x2) + Just (i,[x1,x2,x3,x4]) | i == mkCId "FunApp2" -> GFunApp2 (fg x1) (fg x2) (fg x3) (fg x4) Just (i,[x1,x2,x3]) | i == mkCId "IfThenElse" -> GIfThenElse (fg x1) (fg x2) (fg x3) - Just (i,[x1]) | i == mkCId "InstanceSum" -> GInstanceSum (fg x1) - Just (i,[x1,x2]) | i == mkCId "InstanceSumIf" -> GInstanceSumIf (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "KnownFunction" -> GKnownFunction (fg x1) Just (i,[x1,x2]) | i == mkCId "Let" -> GLet (fg x1) (fg x2) Just (i,[x1]) | i == mkCId "Lit" -> GLit (fg x1) @@ -524,9 +524,9 @@ instance Compos Tree where GFold x1 x2 x3 -> r GFold `a` f x1 `a` f x2 `a` f x3 GFun x1 x2 x3 x4 -> r GFun `a` f x1 `a` f x2 `a` f x3 `a` f x4 GFunApp x1 x2 -> r GFunApp `a` f x1 `a` f x2 + GFunApp1 x1 x2 -> r GFunApp1 `a` f x1 `a` f x2 + GFunApp2 x1 x2 x3 x4 -> r GFunApp2 `a` f x1 `a` f x2 `a` f x3 `a` f x4 GIfThenElse x1 x2 x3 -> r GIfThenElse `a` f x1 `a` f x2 `a` f x3 - GInstanceSum x1 -> r GInstanceSum `a` f x1 - GInstanceSumIf x1 x2 -> r GInstanceSumIf `a` f x1 `a` f x2 GKnownFunction x1 -> r GKnownFunction `a` f x1 GLet x1 x2 -> r GLet `a` f x1 `a` f x2 GLit x1 -> r GLit `a` f x1 diff --git a/lam4-backend/src/Lam4/Render/Render.hs b/lam4-backend/src/Lam4/Render/Render.hs index 1a29a0de..20d5da77 100644 --- a/lam4-backend/src/Lam4/Render/Render.hs +++ b/lam4-backend/src/Lam4/Render/Render.hs @@ -1,6 +1,7 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedRecordDot #-} {-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE ViewPatterns #-} module Lam4.Render.Render (NLGConfig (..), NLGEnv, makeNLGEnv, renderCstProgramToNL) where @@ -125,8 +126,7 @@ style = [r| } dl dl dl > dt { - font-weight: bold; - + //font-weight: bold; color: #880e4f; } @@ -143,7 +143,7 @@ style = [r| } dl dl dl dl > dt { - font-weight: bold; + // font-weight: bold; color: #e65100; } @@ -159,7 +159,7 @@ style = [r| } dl dl dl dl dl > dt { - font-weight: bold; + // font-weight: bold; color: #79b47e; } @@ -181,31 +181,31 @@ renderCstProgramToNL env decls = T.unlines ( ) renderCstDeclToNL :: NLGEnv -> Decl -> T.Text -renderCstDeclToNL env = gfLin env . gf . genericTreeTrans . parseDecl +renderCstDeclToNL env = gfLin env . gf . genericTreeTrans . parseDecl env renderCstDeclToGFtrees :: NLGEnv -> Decl -> T.Text -renderCstDeclToGFtrees env = gfTree env . gf . genericTreeTrans . parseDecl +renderCstDeclToGFtrees env = gfTree env . gf . genericTreeTrans . parseDecl env -- TODO: do we flatten nested Let-definitions? -- for royalflush case, that'd be the best thing to do -- how about generally? -parseDecl :: Decl -> GS -parseDecl = \case +parseDecl :: NLGEnv -> Decl -> GS +parseDecl env = \case DataDecl name typedecl -> GTypeDeclS dummyId $ parseTypeDecl name typedecl Rec name expr -> if commonFunction name.name then GExprS dummyId $ GKnownFunction $ parseName name - else GExprS dummyId $ parseExpr name expr + else GExprS dummyId $ parseExpr env name expr NonRec name (Sig [] []) -> GAtomicConcept dummyId (parseName name) NonRec name expr@(BinExpr binop _ _) -> if booleanOp binop - then GLetIsTrue dummyId (parseName name) $ parseExpr noName expr - else GAssignS dummyId (parseName name) $ parseExpr noName expr - NonRec name expr -> GAssignS dummyId (parseName name) $ parseExpr noName expr + then GLetIsTrue dummyId (parseName name) $ parseExpr env noName expr + else GAssignS dummyId (parseName name) $ parseExpr env noName expr + NonRec name expr -> GAssignS dummyId (parseName name) $ parseExpr env noName expr Eval expr -> quoteVars $ if isBool expr - then GEvalWhetherS dummyId $ parseExpr noName expr - else GEvalS dummyId $ parseExpr noName expr + then GEvalWhetherS dummyId $ parseExpr env noName expr + else GEvalS dummyId $ parseExpr env noName expr -- to wrap all declarations in

dummyId :: GString @@ -229,10 +229,15 @@ commonFunction x = T.unpack x `elem` ["id", "map", "filter", "cons", "nil", "min booleanOp :: BinOp -> Bool booleanOp op = op `elem` [Eq, Lt, Gt, Le, Ge, Ne, And, Or] +getName :: Expr -> Maybe String +getName = \case + Var (N.MkName name _ _) -> Just $ T.unpack name + _ -> Nothing + isPredicate :: Expr -> Bool -isPredicate = \case - Var (N.MkName name _ _) -> name `elem` ["certain", "known", "uncertain", "unknown"] - _ -> False +isPredicate (getName -> Just name) = name `elem` ["certain", "known", "uncertain", "unknown"] +isPredicate _ = False + varFromFun :: Expr -> Expr varFromFun = \case @@ -366,13 +371,16 @@ parseLit = \case BoolLit bool -> GMkName $ GString $ show bool StringLit string -> GMkName $ GString $ T.unpack string -parseExpr :: N.Name -> Expr -> GExpr -parseExpr name = - let f = parseExpr name in \case +parseExpr :: NLGEnv -> N.Name -> Expr -> GExpr +parseExpr env name = + let f = parseExpr env name in \case Var var -> GVar (parseName var) Lit lit -> GLit (parseLit lit) - Unary UnaryMinus expr -> GUnaryMinusExpr (f expr) ; + -- Totally generic transformation—treat unary minus differently from other unary functions + Unary UnaryMinus expr -> GUnaryMinusExpr (f expr) Unary op expr -> GUnary (parseUnaOp op) (f expr) + + -- Specific decisions about verbosity of binary operations -- e.g. "x / y" BinExpr op lc@Var{} rc@Var{} -> GBinExpr (parseBinOp op) (f lc) (f rc) @@ -387,64 +395,63 @@ parseExpr name = -- other BinExprs are "verbose" = newlines and stuff BinExpr op lc rc -> GVerboseBinExpr (parseBinOp op) (f lc) (f rc) + + IfThenElse cond thn els -> GIfThenElse (f cond) (f thn) (f els) -- Basic arithmetic operations that have been defined as custom function - FunApp (Var (N.MkName "div" _ _)) [lc,rc] -> parseExpr name (BinExpr Divide lc rc) - FunApp (Var (N.MkName "mult" _ _)) [lc,rc] -> parseExpr name (BinExpr Mult lc rc) - FunApp (Var (N.MkName "add" _ _)) [lc,rc] -> parseExpr name (BinExpr Plus lc rc) + + FunApp (getName -> Just "div") [lc,rc] -> f (BinExpr Divide lc rc) + FunApp (getName -> Just "mult") [lc,rc] -> f (BinExpr Mult lc rc) + FunApp (getName -> Just "add") [lc,rc] -> f (BinExpr Plus lc rc) -- Basic arithmetic operation that is hardly domain-specific -- Current linearization of Round takes Expr, Int -- and just outputs the Expr instead of "Expr rounded into precision of Int decimals" -- But this should be configurable. - FunApp (Var (N.MkName "round" _ _)) args -> parseRound args - - -- These should be replaced with a general annotation-based approach - FunApp (Var (N.MkName "default" _ _)) args -> parseDefault args - FunApp (Var (N.MkName "instanceSumIf" _ _)) args -> parseInstanceSum args - FunApp (Var (N.MkName "instanceSum" _ _)) args -> parseInstanceSum args + FunApp (getName -> Just "round") [expr, prec] -> GRound (f expr) (f prec) FunApp fun args -> if isPredicate fun - then parseExpr name (PredApp fun args) - else GFunApp (f fun) (GListExpr $ fmap f args) --- FunApp fun args -> GFunApp (f fun) (GListExpr $ fmap f args) --- Record rows -> GRecord - Project record label -> GOnlyFieldProject (f record) (parseNameForRecord label) -- TODO: annotation to decide whether to print out the record name or only label? + then f (PredApp fun args) + else case getAnnotation env (f <$> args) fun of + [(ann, i)] -> GFunApp1 ann (f $ args !! i) + [(ann1, i), (ann2, j)] -> GFunApp2 ann1 (f $ args !! i) ann2 (f $ args !! j) + _ -> GFunApp (f fun) (GListExpr $ fmap f args) + Project record label -> GOnlyFieldProject (f record) (parseName label) -- TODO: annotation to decide whether to print out the record name or only label? Fun md args body -> GFun (parseName name) (parseFunMetadata md) (GListName $ fmap parseName args) (f body) Predicate md args body -> GPredicate (parseName name) (parseFunMetadata md) (GListName $ fmap parseName args) (f body) PredApp predicate args -> GPredApp (f predicate) (GListExpr $ fmap f args) Foldr combine nil over -> GFold (f combine) (f nil) (f over) Foldl combine nil over -> GFold (f combine) (f nil) (f over) Sig parents relations -> GSig (GListName $ fmap parseName parents) (GListExpr $ fmap f relations) - Let decl expr -> GLet (parseDecl decl) (f expr) + Let decl expr -> GLet (parseDecl env decl) (f expr) Cons e1 e2 -> GConjExpr (GListExpr [f e1, f e2]) List es -> GConjExpr (GListExpr $ fmap f es) - Record rows -> GConjExpr (GListExpr $ fmap parseRecordRow rows) + Record rows -> GConjExpr (GListExpr [GRecord (parseName rname) (f row) | (rname,row) <- rows]) --) StatementBlock statements -> undefined -- TODO x -> error [i|parseExpr: not yet implemented #{x}|] -parseInstanceSum :: [Expr] -> GExpr -parseInstanceSum [_set, inst, cond] = GInstanceSumIf instExpr condExpr - where - instExpr = parseExpr noName $ varFromFun inst - condExpr = parseExpr noName $ varFromFun cond -parseInstanceSum [_set, inst] = GInstanceSum instExpr - where - instExpr = parseExpr noName $ varFromFun inst -parseInstanceSum _ = GKnownFunction $ GMkName $ GString "SOMETHING WENT WRONG D:" - -parseRound :: [Expr] -> GExpr -parseRound [expr, prec] = GRound (parseExpr noName expr) (parseExpr noName prec) -parseRound _ = GKnownFunction $ GMkName $ GString "SOMETHING WENT WRONG D:" - -parseDefault :: [Expr] -> GExpr -parseDefault [expr, deflt] = GDefault (parseExpr noName expr) (parseExpr noName deflt) -parseDefault _ = GKnownFunction $ GMkName $ GString "SOMETHING WENT WRONG D:" +-- TODO: This whole thing should come from external annotation +-- Not hardcoded into Haskell code (nor GF code) +-- NB. Indices start from 0, we just happen to have examples where 0th isn't used +getAnnotation :: NLGEnv -> [GExpr] -> Expr -> [(GString, Int)] +getAnnotation env args (getName -> Just name) = case name of + "default" -> [ (GString [i|if #{gfLin env $ gf $ head args} is uncertain, then|], 1) + , (GString "else", 0) ] + "instanceSumIf" -> [ (GString "adding up those of", 1) + , (GString "where", 2) ] + "instanceSum" -> [ (GString "adding up", 1) ] + _ -> [] +getAnnotation _ _ _ = [] +{- +The annotation needs to include the following: +- name of the function +- which of its arguments are used +- what text is put before/after which argument +- currently only puts stuff before argument, TODO also support after argument +-} -parseRecordRow :: (N.Name, Expr) -> GExpr -parseRecordRow (name, expr) = GRecord (parseName name) (parseExpr name expr) parseTypeDecl :: N.Name -> DataDecl -> GTypeDecl parseTypeDecl name typedecl = From 414df4fd0e8ac10f9cd183cb3941b8f8f365650c Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Thu, 21 Nov 2024 00:01:29 +0100 Subject: [PATCH 12/14] fix typo --- lam4-backend/gf-grammar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lam4-backend/gf-grammar/README.md b/lam4-backend/gf-grammar/README.md index 612d9b13..db5bcab1 100644 --- a/lam4-backend/gf-grammar/README.md +++ b/lam4-backend/gf-grammar/README.md @@ -10,7 +10,7 @@ $ gf Lam4Eng.gf linking ... OK Languages: Lam4Eng -Lam4> l -unlextext MkTypeDecl (MkMetadata "a game where you lose money") (MkName "Lottery") (ConsRowTypeDecl (MkRowDecl (MkMetadata "how much can be won from the jackpot") (MkName "‘total jackpot’")) (ConsRcowTypeDecl (MkRowDecl (MkMetadata "whether buying tickets from this lottery is tax deductible") (MkName "‘tax deductible status’")) BaseRowTypeDecl)) | ? tr "°∞" " \n" +Lam4> l -unlextext MkTypeDecl (MkMetadata "a game where you lose money") (MkName "Lottery") (ConsRowTypeDecl (MkRowDecl (MkMetadata "how much can be won from the jackpot") (MkName "‘total jackpot’")) (ConsRowTypeDecl (MkRowDecl (MkMetadata "whether buying tickets from this lottery is tax deductible") (MkName "‘tax deductible status’")) BaseRowTypeDecl)) | ? tr "°∞" " \n" ``` should linearize into the following ``` From d0c5d4af70862ccd9aee697563962e35dd9973e7 Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Thu, 21 Nov 2024 00:07:06 +0100 Subject: [PATCH 13/14] remove dead code --- lam4-backend/src/Lam4/Render/Render.hs | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/lam4-backend/src/Lam4/Render/Render.hs b/lam4-backend/src/Lam4/Render/Render.hs index 20d5da77..902c3d17 100644 --- a/lam4-backend/src/Lam4/Render/Render.hs +++ b/lam4-backend/src/Lam4/Render/Render.hs @@ -34,9 +34,8 @@ data NLGConfig = MkNLGConfig { -- Loosely copied from dsl/…/natural4 -- | Env that's needed for NLG operations -data NLGEnv = NLGEnv +newtype NLGEnv = NLGEnv { gfLin :: GFLinearizer - , gfTree :: GFLinearizer } gfPath :: String -> String @@ -54,8 +53,7 @@ makeNLGEnv config = do -- Set up PGF Language and GF Linearizer let lang = initializeGFLang config.concreteSyntaxName gr linearizer = makeGFLinearizer gr lang - printTree = T.pack . PGF.showExpr [] - pure $ NLGEnv linearizer printTree + pure $ NLGEnv linearizer makeGFLinearizer :: PGF.PGF -> PGF.Language -> GFLinearizer makeGFLinearizer gr lang = postprocessText . T.pack . PGF.linearize gr lang @@ -183,10 +181,6 @@ renderCstProgramToNL env decls = T.unlines ( renderCstDeclToNL :: NLGEnv -> Decl -> T.Text renderCstDeclToNL env = gfLin env . gf . genericTreeTrans . parseDecl env -renderCstDeclToGFtrees :: NLGEnv -> Decl -> T.Text -renderCstDeclToGFtrees env = gfTree env . gf . genericTreeTrans . parseDecl env - - -- TODO: do we flatten nested Let-definitions? -- for royalflush case, that'd be the best thing to do -- how about generally? @@ -217,12 +211,6 @@ noName = N.MkName mempty Nothing N.NotEntrypoint parseName :: N.Name -> GName parseName = GMkName . GString . T.unpack . N.name -parseNameForRecord :: N.Name -> GName -parseNameForRecord = GMkName . GString . T.unpack . rmThe . N.name - where - rmThe :: T.Text -> T.Text - rmThe input = input & [regex|^\s?the+\s+|] . match %~ const "" - commonFunction :: T.Text -> Bool commonFunction x = T.unpack x `elem` ["id", "map", "filter", "cons", "nil", "minus", "plus", "div", "mult", "add", "modulo", "pow", "round", "certain", "uncertain", "known", "unknown", "default", "instanceSumIf", "instanceSum"] @@ -238,11 +226,6 @@ isPredicate :: Expr -> Bool isPredicate (getName -> Just name) = name `elem` ["certain", "known", "uncertain", "unknown"] isPredicate _ = False - -varFromFun :: Expr -> Expr -varFromFun = \case - Fun _md _args (Project _rec label) -> Var label - e -> e ---- Tree transformations ----- genericTreeTrans :: Tree a -> Tree a From 331977153eac8dcf9b04a9ed453f44587ec4438d Mon Sep 17 00:00:00 2001 From: Inari Listenmaa Date: Tue, 26 Nov 2024 08:17:45 +0100 Subject: [PATCH 14/14] remove italics from and and or --- lam4-backend/gf-grammar/Lam4.pgf | Bin 11400 -> 11448 bytes lam4-backend/gf-grammar/Lam4Eng.gf | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lam4-backend/gf-grammar/Lam4.pgf b/lam4-backend/gf-grammar/Lam4.pgf index e4f44070b3eb81176909f47c1f40edbf74a456b3..891a51b8aa5ec481f2f0cd503702e43d28148e15 100644 GIT binary patch delta 156 zcmeB(+!47UR&4SaaV{3-#JrTr^Q9ywuayv(+#@E4DR@SVcQU^OlFIWU0+aWNpPTG2 z#s^f*&6HmRH^4<4WB`f~R68?F8Ax}YDDUQ(68YSW%9A-&S{aol_p7{QRNP#t%Fhk} DB4;wr delta 195 zcmdlH*%7%RR!oq^CN~pg_+exAIP43UP5m26fr>@GIzvy1<>_OW)zp7>@UU# zm0-#*LNZH{fss*!nZ+h0#|}i6fJl&)sH!Fd&E-dv02=#ta-Jyf=93cn+>A<-Emc|> R6({dkdC91}d8H~pI{@APG+h7y diff --git a/lam4-backend/gf-grammar/Lam4Eng.gf b/lam4-backend/gf-grammar/Lam4Eng.gf index d853659a..8fa2c70d 100644 --- a/lam4-backend/gf-grammar/Lam4Eng.gf +++ b/lam4-backend/gf-grammar/Lam4Eng.gf @@ -41,8 +41,8 @@ concrete Lam4Eng of Lam4 = open Prelude, Coordination in { ifKw : Str = hilight Strong "if" ; thenKw : Str = hilight Strong "then" ; elseKw : Str = hilight Strong "else" ; - andKw : Str = hilight Emph "and" ; - orKw : Str = hilight Emph "or" ; + andKw : Str = hilight Strong "and" ; + orKw : Str = hilight Strong "or" ; allKw : Str = hilight Strong (hilight Emph "all of") ; anyKw : Str = hilight Strong (hilight Emph "any of") ;