[-*- Mode: emacs-lisp -*-] [Copyright 2011 Ken Takusagawa This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ] [-----grammar (gz start (prog)) (gz prog (module)) (gz module (id language-pragma-opt exports imports topdecl-star ::pr("[[language-pragma-opt]]module [[id]] [[exports]] where{\n[[imports]]\n" "[[topdecl-star('',';\n','\n')]]}\n\n"))) (gz language-pragma ( :language-pragma f id-non-star j ::pr ("{-# LANGUAGE [[id-non-star('',',','')]] #-}\n"))) (gz exports (f export-star j ::pr("[[export-star('(',', ',')')]]")) (:export-everything ::pr(""))) (gz export (id) (f :module-export id j ::pr("module [[id]]")) ) (gz imports (f import-star j ::pr("[[import-star('',';\n',';\n')]]"))) (gz import(id ::pr( "import [[id]]")) (f :qualified (original-name ::is id) (new-name ::is id) j ::pr ( "import qualified [[original-name]] as [[new-name]]")) (f :specific id id-non-star j ::pr ("import [[id]][[id-non-star('(',',',')')]]")) ) (gz type-class (f decl-mark (class-name ::is id) :type-class context-opt id-non-plus f type-class-decl-star j j ::pr("class [[context-opt]][[class-name]] [[id-non-plus('',' ','')]] where{\n" "[[type-class-decl-star('',';\n','\n')]]}"))) (gz topdecl (decl) (data)(type-synonym)(newtype)(instance)(type-class)) (gz type-class-decl (type-signature)(decl)) (gz type-signature (f :tysig name ret-type-and-params j ::pr("[[name]] :: [[ret-type-and-params]]"))) (gz instance (f :instance (type ::is id) (name ::is simpletype) decls j ::pr ("instance [[type]] ([[name]]) where [[decls]]"))) [(gz instance (f :instance context-opt (type ::is id) simpletype-plus :x decls j ::pr ("instance [[context-opt]][[type]] [[simpletype-plus('(',')(',')')]] where [[decls]]")))] (gz newtype (f decl-mark (name ::is id) :newtype type-vars-opt constr-or-wrap deriving-opt j ::pr("newtype [[name]] [[type-vars-opt]] = [[constr-or-wrap{my_name}]][[deriving-opt]]"))) (gz constr-or-wrap ::gets "tr-id*{name}" (constr)(wrap-constr ::pr("[[wrap-constr{name}]]"))) (gz wrap-constr ::gets "tr-id*{name}" ( :wrap id ::pr( (::c "name->print();") " {un_" (::c "name->print();") " :: [[id]]}"))) (gz deriving (:deriving f id-non-plus j ::pr(" deriving [[id-non-plus('(',', ',')')]]"))) (gz id-non (id)) (gz type-synonym (f decl-mark id :type-synonym type-vars-opt type j ::pr("type [[id]] [[type-vars-opt]] = [[type]]"))) (gz data (f decl-mark id :data type-vars-opt constrs deriving-opt j ::pr("data [[id]] [[type-vars-opt]] = [[constrs]][[deriving-opt]]"))) (gz simpletype (f id-non-plus j ::pr ("[[id-non-plus('',' ','')]]"))) (gz type-vars (:args f id-non-star j ::pr ("[[id-non-star('',' ','')]]"))) (gz constrs(constr-star ::pr("[[constr-star('',' | ','')]]")) ) (gz field-type-and-param (f param type j ::pr("[[param]] :: [[type]]"))) (gz type-and-param ( f param type j ::pr("[[type]]"))) (gz constr(positional-constructor) (field-label-constructor) ) (gz field-label-constructor(f type-ctor :field field-type-and-param-star j ::pr("[[type-ctor]][[field-type-and-param-star('{',', ','}')]]"))) (gz decls ( decl-star ::pr("{[[decl-star('\n',';\n','\n')]]}\n"))) (gz context (:context f a-context-plus j ::pr ("[[a-context-plus('(',', ',')')]] => "))) (gz a-context [(f (type ::is id) id-non-plus j ::pr("[[type]] [[id-non-plus('',' ','')]]"))] (f (class ::is id) type-plus j ::pr("[[class]] [[type-plus('(',')(',')')]]")) ) (gz forall (:forall f id-non-plus j ::pr("forall [[id-non-plus('',' ','')]] . "))) (gz ret-type-and-params (type f type-and-param-star j forall-opt context-opt ::pr("[[forall-opt]][[context-opt]][[type-and-param-star('',' \x2d> ','')]]" (::c "if(my_type_and_param_star->v.size()>0)out(' \x2d> ');") "[[type]]"))) (gz decl (f decl-mark name :fun ret-type-and-params expr j ::pr("[[name]] :: [[ret-type-and-params]];\n" "[[name]]" (::c "for(many_trees::const_iterator pos = my_ret_type_and_params->my_type_and_param_star->v.begin();pos!= my_ret_type_and_params->my_type_and_param_star->v.end();++pos){" "const tr_type_and_param* t=dynamic_cast(*pos);" "assert(t);" "out(' ');" "t->my_param->print();" "}") " = [[expr]]")) (f decl-mark name :fun :no-sig ret-type-and-params expr j ::pr("[[name]]" (::c "for(many_trees::const_iterator pos = my_ret_type_and_params->my_type_and_param_star->v.begin();pos!= my_ret_type_and_params->my_type_and_param_star->v.end();++pos){" "const tr_type_and_param* t=dynamic_cast(*pos);" "assert(t);" "out(' ');" "t->my_param->print();" "}") " = [[expr]]")) (f decl-mark name :simple expr j ::pr("[[name]] = [[expr]]")) ) (gz name (id)) (gz positional-constructor ["this one is sketchy"] (type-ctor ::pr("[[type-ctor]]")) (f type-ctor typepls-opt j ::pr("[[type-ctor]][[typepls-opt]]")) (f :tuple type-plus j ::pr("[[type-plus('(',', ',')')]]")) ) (gz pattern (id) (f pattern-ctor pattern-star j ::pr ("([[pattern-ctor]] [[pattern-star('',' ','')]])")) (f pattern-ctor :fpat f fpat-star j j ::pr ("[[pattern-ctor]][[fpat-star('{',', ','}')]]")) (f :ptuple pattern-plus j [pattern-plus cuz :nil exists for empty lists] ::pr("[[pattern-plus('(',', ',')')]]")) (f :plist pattern-plus j [pattern-plus cuz :nil exists for empty lists] ::pr("[[pattern-plus('\x5b',', ','\x5d')]]")) (f :pchar astring j ::pr("(\x27[[astring]]\x27)")) (f :pstring astring j ::pr("\x22[[astring]]\x22")) (f :as id pattern j ::pr("[[id]]@[[pattern]]")) ) (gz pattern-ctor (id) (:cons ::pr ("(:)")) (:nil ::pr ("[]"))) (gz fpat (f (variable ::is id) pattern j ::pr("[[variable]] = [[pattern]]"))) (gz type (f :fn ret-type-and-params j ::pr ("([[ret-type-and-params]])")) (:unit ::pr("()")) (positional-constructor)) (gz typepls (paren-type-plus)) (gz paren-type (type ::pr( "([[type]])")) (f :strict type j ::pr("!([[type]])")) (f :generic id j ::pr (" [[id]] "))) (gz type-ctor(id)(:list ::pr ("[]"))(:nondet ::pr ("[]"))) (gz param (pattern)) (gz qastring (astring ::pr("\x22[[astring]]\x22"))) (gz expr (id) (:mcons ::pr ("(:)")) [(:nil ::pr ("[]"))] [(f :pipe expr-plus j ::pr[("[[expr-star('(',' $ ',')')]]")] ( (::c "for(many_trees::const_iterator pos = my_expr_plus->v.begin();" "pos!=my_expr_plus->v.end();++pos){") "(" (::c "(*pos)->print();" "}") (::c "for(many_trees::const_iterator pos = my_expr_plus->v.begin();" "pos!=my_expr_plus->v.end();++pos){") ")" (::c "}") ) )] (f :join expr-plus j ::pr("[[expr-plus('(',' >>= ',')')]]")) (f :rpipe expr-plus j ::pr[("[[expr-star('(',' $ ',')')]]")] (["http;//gcc.gnu.org/bugzilla/show_bug.cgi?id=11729"] (::c "for(many_trees::reverse_iterator pos = my_expr_plus->v.rbegin();" "pos!=my_expr_plus->v.rend();++pos){") "(" (::c "(*pos)->print();" "}") (::c "for(many_trees::const_iterator pos = my_expr_plus->v.begin();" "pos!=my_expr_plus->v.end();++pos){") ")" (::c "}") ) ) (f :rcompose expr-plus j ::pr [("[[expr-plus('(',' . ',')')]]")] ("(" (::c "for(many_trees::reverse_iterator pos = my_expr_plus->v.rbegin();" "pos!=my_expr_plus->v.rend();++pos){") (::c "if(pos!=my_expr_plus->v.rbegin())") " . " (::c "(*pos)->print();" "}") ")" ) ) (f :cc expr-star j ::pr ("[[expr-star('(',' ++ ',')')]]")) (qastring) (f :lit astring j ::pr("[[astring]]")) (f :ty type expr j ::pr("([[expr]] :: [[type]])")) (f (fun-name ::is expr) expr-star j ::pr ("([[fun-name]][[expr-star(' ',' ','')]])")) [(f :construct ctor expr-star j ::pr ("([[ctor]] [[expr-star('',' ','')]])"))] (f :do stmt-star j ::pr("(do{\n[[stmt-star(' ','\n ','\n')]]})")) (f :case expr alt-star j ::pr("(case [[expr]] of {\n[[alt-star(' ',';\n ','\n')]]})")) (f :case expr alt-star :else (underbar ::is expr) j ["the else is there so the grammar does not have a reduce/reduce conflict"] ::pr("(case [[expr]] of {\n[[alt-star(' ',';\n ',';\n')]]" " _ -> [[underbar]]\n" "})")) (f :lcase alt-star j ::pr("(\x5clambda_case_var ->" "case lambda_case_var of {\n" "[[alt-star(' ',';\n ','\n')]]})")) (f :lcase alt-star :else (underbar ::is expr) j ::pr("(\x5clambda_case_var ->" "case lambda_case_var of {\n" "[[alt-star(' ',';\n ',';\n')]]" " _ -> [[underbar]]\n" "})")) (f :let decl-star expr j ::pr("(let {[[decl-star('\n',';\n','\n')]]}\n in [[expr]])")) (f :rlet expr decl-star j ::pr("(let {[[decl-star('\n',';\n','\n')]]}\n in [[expr]])")) (f :cfd expr assignments-star j ::pr("([[expr]][[assignments-star('{',', ','}')]])")) [(f :compose (a ::is expr) (b ::is expr) j ::pr("((.)[[a]] [[b]])"))] [(:compose ::pr ("(.)"))] [(f :compose expr-plus j ::pr ("[[expr-plus('(',' . ',')')]]"))] (f :mlist expr-star j ::pr("[[expr-star('\x5b',', ','\x5d')]]")) (f :cons-list expr-star j ::pr("[[expr-star('(',':',')')]]")) (f :mtuple expr-star j ::pr("[[expr-star('(',', ',')')]]")) (:nothing ::pr ("()")) (f :lambda name ret-type-and-params expr j ::pr("(let {[[name]] :: [[ret-type-and-params]];\n" "[[name]]" (::c "for(many_trees::const_iterator pos = my_ret_type_and_params->my_type_and_param_star->v.begin();pos!= my_ret_type_and_params->my_type_and_param_star->v.end();++pos){" "const tr_type_and_param* t=dynamic_cast(*pos);" "assert(t);" "out(' ');" "t->my_param->print();" "}") " = [[expr]]} in [[name]])")) (f :lambda-simple id-non expr j [recommended only for reordering arguments to functions and other simple expressions] [only one variable to keep it simple] ::pr ("(\x5c[[id-non]] -> [[expr]])")) ) (gz assignments (f id expr j ::pr("[[id]] = [[expr]]"))) (gz stmt (expr ::pr("[[expr]];")) (f ":=" pattern type expr j ::pr("[[pattern]] :: [[type]] <- [[expr]];")) (f :dlet decl-star j ::pr ("let {[[decl-star('\n',';\n','\n')]]};")) ) (gz alt (f pattern expr-or-gpat j ::pr("[[pattern]][[expr-or-gpat]]"))) (gz expr-or-gpat (expr ::pr ("-> [[expr]]")) (where-opt :gpats pred-expr-star [silly lookahead limitation] ::pr ("\n[[pred-expr-star('','','')]] [[where-opt]]" ))) (gz pred-expr ( f (pred ::is expr) (do ::is expr) j ::pr ("| [[pred]]\n -> [[do]]\n"))) (gz where (:where decls ::pr ("where [[decls]]"))) (gz decl-mark (":")) ] Main :language-pragma ( ScopedTypeVariables [PatternSignatures] GeneralizedNewtypeDeriving ) (main) ( Data.Maybe Data.List [Array] Data.Char ) (: main :fun (IO :unit) () [(:join getContents (:rcompose id putStrLn ))] example ) (: Permutation :type-synonym :args (a b) (:list (:tuple a b))) (: enum-zero-size :fun (:list Int) ((length Int)) (take length (enumFrom 0))) (: do-substitution :fun b ((p (Permutation a b))(x a)):context ((Eq a)) (:rpipe (lookup x p) fromJust)) (: do-permutation :fun (:list a) ((template(:list Int))(l(:list a))) (:do (:= i Int (enum-zero-size (length l))) (return (!! l (!! template i))) )) (: bacon-list :fun (:list String) () (:rpipe "ab" (replicate 5) sequence)) (: a32lphabet :fun String () latin-alphabet-32) (: punctuation-alphabet :fun String () (++ alphabet26 ".,'-_\\")) (: latin-alphabet-32 :fun String () (++ alphabet26 (map toEnum (:mlist 229 233 234 243 248 252 )))) (: alphabet26 :fun String () (enumFromTo (head "a") (head "z"))) [concatMap {do_substitution {zip a32lphabet bacon_list}} "hello"] (: bacon-sep :fun (:fn(:list String) ((s String)))() (substitution a32lphabet bacon-list)) (: bacon :fun (:fn String ((s String)))() (:rcompose bacon-sep concat)) (: un-bacon :fun String ((s String)) (:rpipe s (n-chunk 5) (map (do-substitution (zip bacon-list a32lphabet))))) (: arrange-into-columns :fun (:list(:list a))((num-columns Int)(l (:list a))) (:rpipe l (n-chunk num-columns) transpose)) (: columnar-transposition :fun (:list a) ((p (:list Int))(l(:list a))) (:rpipe l (arrange-into-columns (length p)) (do-permutation p) concat [reversing "concat" is going to be nontrivial])) (: n-chunk :fun(:list(:list a))((n Int)(l(:list a))) (:case l ((:nil)(:mlist) ) ((_)(:mcons (take n l) (n-chunk n (drop n l)))) )) (: Op :type-synonym :args(a) (:fn a ((x a)(y a)))) (: encrypt-cipher-block-chain-for-scanl :fun ivtype ((xor (:fn ivtype ((iv ivtype)(c ciphertype)))) (cipher(:fn ciphertype((p plaintype)))) (iv ivtype)(p plaintype)) (xor iv (cipher p))) (: decrypt-cipher-block-chain :fun (:list plaintype) ((unxor(:fn ciphertype((civ ivtype)(iv ivtype)))) (decipher(:fn plaintype ((c ciphertype)))) (iv ivtype)(civs(:list ivtype))) :forall(plaintype ciphertype ivtype) (:case civs ((:nil)(:mlist)) ((:cons(civ)(t)) (:let (: c :fun ciphertype () (unxor civ iv)) (:mcons (decipher c) (decrypt-cipher-block-chain unxor decipher civ t)))))) (: index-alphabet :fun Int ((alphabet(:list a))(x a)):context ((Eq a)) (:rpipe 0 enumFrom (zip alphabet)(lookup x) fromJust)) (: plus-cyclic-alphabet :fun a ((alphabet(:list a))(x a)(y a)):context((Eq a)) (!! alphabet (mod (+ (index-alphabet alphabet x) (index-alphabet alphabet y)) (length alphabet)))) (: minus-cyclic-alphabet :fun a ((alphabet(:list a))(x a)(y a)):context((Eq a)) (!! alphabet (mod (- (index-alphabet alphabet x) (index-alphabet alphabet y)) (length alphabet)))) (: auto-cipher :fun (:list output) ((input-to-iv(:fn ivtype ((p input)))) (cipher(:fn(:list output) ((iv ivtype)(p(:list input))))) (p(:list input))) :forall (input ivtype output) (:case p ((:nil)(:mlist)) ((:cons(h)(t)) (:let (: iv :fun ivtype () (input-to-iv h)) (cipher iv t) )))) (: Iv :newtype :args(a) :wrap a :deriving (Show)) (: Plain :newtype :args(a) :wrap a) (: Cipher :newtype :args(a) :wrap a) (: cycle-encrypt :fun (Iv Char) ((alphabet String)(iv (Iv Char))(c (Cipher Char))) (Iv (plus-cyclic-alphabet alphabet (un-Cipher c) (un-Iv iv)))) (: cycle-decrypt :fun (Cipher Char) ((alphabet String)(civ (Iv Char))(iv (Iv Char))) (Cipher (minus-cyclic-alphabet alphabet (un-Iv civ) (un-Iv iv)))) (: id-cipher :fun (:fn(Cipher a)((p(Plain a))))() (:rcompose un-Plain Cipher)) (: id-decipher :fun (:fn(Plain a)((c(Cipher a))))() (:rcompose un-Cipher Plain)) (: p-to-iv :fun (:fn(Iv a)((p(Plain a))))() (:rcompose un-Plain Iv)) (: cbc-encrypt :fun (:fn String((p String)))((alphabet String)) (:rcompose (map Plain) (auto-cipher p-to-iv (scanl (encrypt-cipher-block-chain-for-scanl (cycle-encrypt alphabet) id-cipher))) (map un-Iv) )) (: cbc-decrypt :fun String((alphabet String)(c String)) (:case c ((:nil)(:mlist)) :else (:mcons (head c) (:rpipe c (map Iv) (auto-cipher id (decrypt-cipher-block-chain (cycle-decrypt alphabet) id-decipher)) (map un-Plain))) )) (: division-list :fun (:list Int) ((big Int)(small Int)) (:let (: dm :fun (:tuple Int Int)() (divMod big small)) (++ (replicate (snd dm) (+ 1 (fst dm))) (replicate (- small (snd dm)) (fst dm))))) (: nm-chunk :fun (:list(:list a)) ((ns(:list Int))(as(:list a))) (:case ns ((:nil)(:mlist)) ["not checked in length"] ((:cons(h)(t)) ["also, neither take nor drop are checked in length"] (:mcons (take h as) (nm-chunk t (drop h as)))))) (: un-columnar-transposition :fun (:list a) ((p(:list Int))(l(:list a))) (:rpipe l (nm-chunk(do-permutation p(division-list (length l) (length p)))) (do-permutation (inverse-permutation p)) transpose concat )) (: inverse-permutation :fun (:list Int) ((p(:list Int))) ["use arrays for better performance"] (:rpipe p length enum-zero-size (map (index-alphabet p)))) [(: inverse-permutation :fun (:list Int)((p(:list Int))) (:rpipe (enumFrom 0) (zip p) (array (:mtuple 0 (:rpipe p length pred))) elems))] (: Template :data (C Char) Upper Lower :deriving (Show)) (: make-template :fun Template ((c Char)) (:case (isAlpha c) (False (C c)) :else (:case (isUpper c) (True Upper) (False Lower)))) (: fill-template :fun String ((t(:list Template))(s String)) (:case t ((:nil)(:mlist)) ((:cons(h)(t)) (:let (: rest :fun String ((h Char)(s String)) (:mcons h (fill-template t s))) (:case h ((C c)(rest c s)) (Lower (rest (head s)(tail s))) (Upper (rest (:rpipe s head toUpper)(tail s)))))))) (: get-lower :fun (:fn String ((s String))) () (:rcompose (filter isAlpha) (map toLower))) (: wrap-template :fun String ((f(:fn String ((s String))))(s String)) (:rpipe s get-lower f (fill-template (map make-template s)) )) (: first-amd :fun String () "Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech, or of the press; or the right of the people peaceably to assemble, and to petition the Government for a redress of grievances.") (: tfirst :fun String () (:cc (take 270 first-amd) "b.")) (: permutation-32 :fun (:list Int) () (:mlist 19 6 24 27 1 22 2 0 12 11 26 14 17 9 15 3 4 29 7 20 30 5 13 21 16 25 18 23 31 28 10 8)) (: letter-26-permutation :fun String () "bmtisxlqnpwgkuzerfdavhcjyo") (: sub32 :fun (:fn String ((s String)))() (substitution a32lphabet (map (!! a32lphabet) permutation-32))) (: un-sub32 :fun (:fn String ((s String)))() (un-substitution a32lphabet (map (!! a32lphabet) permutation-32))) (: sub26 :fun (:fn String ((s String)))() (substitution alphabet26 letter-26-permutation)) (: un-sub26 :fun (:fn String ((s String)))() (un-substitution alphabet26 letter-26-permutation)) (: substitution :fun (:list b) ((as(:list a))(bs(:list b)) (x (:list a))):context ((Eq a)) (map (do-substitution (zip as bs)) x)) (: un-substitution :fun (:list a) ((as(:list a))(bs(:list b)) (x (:list b))):context ((Eq b)) (map (do-substitution (zip bs as)) x)) (: perm :fun (:fn (:list a)((l(:list a)))) () (columnar-transposition permutation-32)) (: un-perm :fun (:fn (:list a)((l(:list a))))() (un-columnar-transposition permutation-32)) (: cbc :fun (:fn String((s String)))() (cbc-encrypt a32lphabet)) (: un-cbc :fun (:fn String((s String)))() (cbc-decrypt a32lphabet)) (: run :fun (IO :unit) ((f(:fn String ((s String))))) (:rpipe first-amd (wrap-template f) putStrLn)) (: caesar-substitution :fun String ((n Int)) (map (plus-cyclic-alphabet a32lphabet(!! a32lphabet n)) a32lphabet)) (: caesar :fun (:fn String ((s String))) ((n Int)) (substitution a32lphabet (caesar-substitution n))) (: n-iterate :fun a ((n Int)(f(:fn a ((x a))))(x a)) (!! (iterate f x) n)) (: example :fun (IO :unit)() (:do (:rpipe latin-alphabet-32 (intersperse (head " ")) putStrLn) (:rpipe permutation-32 (map show) unwords putStrLn) (putStrLn first-amd) (run (caesar 2)) (run sub32) (run perm) (:rpipe first-amd get-lower bacon-sep unwords putStrLn) (run (:rcompose bacon perm un-bacon)) (run cbc) (run (:rcompose cbc sub32)) (putStrLn "=========================") (putStrLn tfirst) (run (:rcompose sub32 bacon perm un-bacon)) (:rpipe tfirst (wrap-template (:rcompose sub32 bacon perm un-bacon)) putStrLn) (putStrLn "=========================") (:dlet (: x :fun (:fn String ((s String)))() (:rcompose sub32 bacon perm un-bacon cbc)) (: y :fun (:fn String ((s String)))() (:rcompose un-cbc bacon un-perm un-bacon un-sub32)) ) (run x) (:rpipe tfirst (wrap-template x) putStrLn) (putStrLn "=========================") (run (:rcompose x x x)) (:rpipe tfirst (wrap-template (:rcompose x x x)) putStrLn) (putStrLn "=========================") (run (:rcompose x x x y y y)) (run (n-iterate 3 x)) (run (n-iterate 1000000 x)) ))