[-*- 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 :chain astring expr-plus j ::pr
([("[[expr-plus('(',' op ',')')]]")]
"("
(::c "for(many_trees::const_iterator pos=my_expr_plus->v.begin();pos!=my_expr_plus->v.end();++pos){")
(::c "if(pos!=my_expr_plus->v.begin()){")
"[[astring]]"
(::c "}(*pos)->print();}")
")"
))
(f :join expr-plus j ::pr("[[expr-plus('(',' >>= ',')')]]"))
(f :cc expr-star j ::pr ("[[expr-star('(',' ++ ',')')]]"))
(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
("("
(::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();" "}")
")"
)
)
(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 :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 :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]])"))
(f :field-edit expr field-edit-plus j
[plus is required by Haskell]
::pr("([[expr]][[field-edit-plus('{',',','}')]])"))
)
(gz field-edit (f id expr j ::pr ("[[id]] = [[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
[NoMonomorphismRestriction]
)
(main)
(
Data.Maybe
System.Environment
Debug.Trace
Data.Tree.NTree.Zipper.TypeDefs
Data.Tree.Class
Data.Tree.NTree.TypeDefs
Data.Tree.NavigatableTree.Class
Data.List
System.IO
Control.Monad
)
(: main :fun (IO :unit) ()
(:join
getArgs
(:lcase
((:nil)(:join(read-eval-print-loop mkEmpty)print-tree))
((:plist(:pstring "run"))run)
((:plist(:pstring "repl"))(:join(read-eval-print-loop two-to-connect)print-tree))
)
))
(: Node :type-synonym (:tuple (Maybe String) Mydata))
(: Nnode :type-synonym (NTree Node))
(: Mydata :type-synonym :unit)
(: Edit :type-synonym (NTZipper Node))
(: no-data :fun Mydata () :nothing)
(: make-node :fun Node ((s String))
(:mtuple (Just s) no-data))
(: placeholder :fun Node ()
(:mtuple Nothing no-data))
(: empty-tree :fun Nnode()
(list-make(:mlist)))
(: leaf-make :fun Nnode((s String))
(mkTree (make-node s)(:mlist)))
(: list-make :fun (:fn (t Node)((l(:list (t Node)))))()
:context((Tree t))
(mkTree placeholder))
(: mkEmpty :fun Edit()
(fromTree empty-tree))
(: run :fun (IO :unit)()
(:do
(:rpipe mkEmpty make-child-here mvDown fromJust add-tree-left fromJust
(set-val (make-node "hello")) print)
(:rpipe sample print-tree)
(:rpipe to-promote-sample left-promote fromJust mvUp fromJust print-tree)
(:rpipe to-promote-sample right-promote fromJust mvUp fromJust print-tree)
))
(: add-tree-left :fun (Maybe Edit) ((t Edit))
(addTreeLeft empty-tree t)
)
(: add-tree-right :fun (Maybe Edit) ((t Edit))
(addTreeRight empty-tree t)
)
(: edit-node :fun (nt a) ((f (:fn (t a)((in (t a)))))(t (nt a)))
:context((NavigatableTreeToTree nt t)
(NavigatableTreeModify nt t)
)
(substThisTree (:rpipe t toTree f) t))
(: EE :type-synonym (:fn Edit((t Edit))))
(: make-child-here :fun EE()
(edit-node (setChildren (:mlist empty-tree))))
(: set-val :fun EE ((x Node))
(edit-node (setNode x)))
(: show-tree :fun String ((x (t Node)))
:context ((Tree t))
(:case (:rpipe x getNode fst)
(Nothing
(:rpipe
x getChildren (map show-local-tree)
(intersperse " ") concat)
)
:else
(error "data node at root")
))
(: show-local-tree :fun String ((x (t Node)))
:context ((Tree t))
(:case (:rpipe x getNode fst)
((Just j)
(:case (getChildren x)
((:nil)j)
:else
(error (:cc "internal data node:" (show j)))))
:else
(:cc
"("
(:rpipe
x getChildren (map show-local-tree)
(intersperse " ") concat)
")")))
(: print-tree :fun (:fn(IO :unit)((x(t Node))))()
:context ((Tree t))
(:rcompose show-tree putStrLn))
(: push-down-node :fun (t Node)((input (t Node)))
:context((Tree t))
(list-make(:mlist input)))
(: push-down :fun EE ()
(edit-node push-down-node))
(: this-down-right :fun Edit ((z Edit))
(:case (:rpipe z context)
((:cons(NTC(left)(parent)(right))(rest-context))
(:let
(: new-node :fun Nnode ()
(list-make(:mcons (ntree z)right)))
(NTZ new-node
(:mcons(NTC left parent (:mlist))rest-context))
))))
[
old a - x y z
new a - x pp(y z)
old ntree y context1 x a z,
new ntree pp(y z) context x a ()
]
(: this-down-left :fun Edit ((z Edit))
(:case (:rpipe z context)
((:cons(NTC(left)(parent)(right))(rest-context))
(:let
(: new-node :fun Nnode ()
(list-make (endcons left (ntree z))))
(NTZ new-node
(:mcons(NTC (:mlist) parent right)rest-context))
))))
(: endcons :fun (:list a) ((init(:list a))(last a))
[finger trees later]
(++ init (:mlist last)))
(: to-promote-sample :fun Edit()
(:rpipe sample mvDown fromJust mvRight fromJust mvRight fromJust mvDown fromJust mvRight fromJust mvRight fromJust))
[
(a b (c d e f) g h)
(a b (c d) e f g h)
promote all children would have the minor nit of where to put the cursor
a - x pp(y z)
NTZ {ntree = NTree (Just "z",()) [], context = [
NTC [NTree (Just "y",()) []] (Just "pp",()) [],
NTC [NTree (Just "x",()) []] (Just "a",()) []]}
]
(: sample1 :fun Edit ()
(fromTree(NTree (make-node "root")
(:cc
(map leaf-make (words "a b"))
(:mlist (NTree (make-node "inner")
(map leaf-make (words "c d e f"))))
(map leaf-make (words "g h"))))))
(: right-promote :fun (m Edit) ((z Edit))
:context((Monad m))
(:case (:rpipe z context)
((:cons(NTC(myleft)(myparent)(myright))
(:cons(NTC(pleft)(pparent)(pright))
(grandparent-context)))
(:let
(: new-right :fun (:list Nnode)()
(++ myright pright))
(: new-left :fun Nnode()
(NTree myparent (reverse myleft)))
(return (NTZ (ntree z) (:mcons (NTC (:mcons new-left pleft) pparent new-right)grandparent-context)))
))
:else (fail "right-promote did not have parent")
))
[
(a b (c d e f) g h)
(a b c d e (f) g h)
]
(: left-promote :fun (m Edit) ((z Edit))
:context ((Monad m))
(:case (:rpipe z context)
((:cons(NTC(myleft)(myparent)(myright))
(:cons(NTC(pleft)(pparent)(pright))
(grandparent-context)))
(:let
(: new-left :fun (:list Nnode)()
(++ myleft pleft))
(: new-right :fun Nnode()
(NTree myparent myright))
(return (NTZ (ntree z) (:mcons (NTC new-left pparent (:mcons new-right pright) )grandparent-context)))
))
:else (fail "left-promote did not have parent")
))
(: sample :fun Edit ()
(fromTree(list-make
(:cc
(map leaf-make (words "a b"))
(:mlist (list-make
(map leaf-make (words "c d e f"))))
(map leaf-make (words "g h"))))))
(: two-to-connect :fun Edit ()
(fromTree(list-make
(:cc
(map leaf-make (words "a b"))
(:mlist (list-make
(map leaf-make (words "c d e f")))
(list-make
(map leaf-make (words "j j j j"))))
(map leaf-make (words "g h"))))))
(: get-full-tree :fun Edit ((e Edit))
(:case (mvUp e)
(Nothing e)
((Just x) (get-full-tree x))))
[(: m :fun (:fn (Maybe p)((x p))) ((f(:fn p ((x p)))))
(:rcompose f Just))]
(: safe-child :fun (m Edit) ((z Edit))
:context((MonadPlus m))
(:do
(:rpipe z ntree isLeaf guard)
(:rpipe z ntree getNode fst isNothing guard)
(:rpipe z make-child-here return)))
(: safe-set :fun (m Edit) ((s String)(z Edit))
:context((MonadPlus m))
(:do
(:rpipe z ntree isLeaf guard)
(:rpipe z ntree getNode fst isNothing guard)
(:rpipe z (set-val (make-node s)) return)
))
(: unset :fun (m Edit) ((z Edit))
:context((MonadPlus m))
(:do
(:rpipe z ntree isLeaf guard)
(:rpipe z (set-val placeholder) return)
))
(: no-children :fun Edit ((z Edit))
(:field-edit z (ntree (mkTree (:rpipe z ntree getNode)(:mlist)))))
(: Rep-type :type-synonym (IO Nnode))
(: read-eval-print-loop :fun Rep-type ((z Edit))
(:do
[(:rpipe z get-full-tree ntree print-tree)]
[(print z)]
(putStr "$ ")
(hFlush stdout)
(:= l String getLine)
(putStrLn (:cc "You said: " (show l)))
(:case (== l "exit")
(True (:rpipe z get-full-tree ntree return))
:else
(:let
(: go :fun Rep-type((f (:fn (Maybe Edit)((x Edit)))))
(:case (f z)
(Nothing
(:do
(putStrLn "failed")
(read-eval-print-loop z)))
((Just(j))
(read-eval-print-loop j))))
(: no-change :fun Rep-type((action (IO :unit)))
(:do
action
(read-eval-print-loop z)))
(:case (words l)
((:plist(:pstring"child")) (go safe-child))
((:plist(:pstring"down"))(go mvDown))
((:plist(:pstring"up"))(go mvUp))
((:plist(:pstring"left"))(go mvLeft))
((:plist(:pstring"right"))(go mvRight))
((:plist(:pstring"set")(val))(go (safe-set val)))
((:plist(:pstring"show"))(no-change (print z)))
((:plist(:pstring"top"))(:rpipe z get-full-tree ntree print-tree no-change))
((:plist(:pstring"aleft"))(go add-tree-left))
((:plist(:pstring"aright"))(go add-tree-right))
((:plist(:pstring"dleft"))(go dropTreeLeft))
((:plist(:pstring"dright"))(go dropTreeRight))
((:plist(:pstring"push"))(go (:rcompose push-down Just)))
((:plist(:pstring"tright"))(go (:rcompose this-down-right Just)))
((:plist(:pstring"tleft"))(go (:rcompose this-down-left Just)))
((:plist(:pstring"pright"))(go right-promote))
((:plist(:pstring"pleft"))(go left-promote))
((:plist(:pstring"unset"))(go unset))
((:plist(:pstring"noc"))(go (:rcompose no-children Just)))
:else
(no-change
(putStrLn "bad command")
))))))
[next unsolved: undo, readline]