├── ASCIIMathML_with_modified_escapes.js ├── MOLLY.html ├── MOLLY.pl ├── MOLLY.tangle ├── MOLLY.weave ├── README ├── eeerotate.jpg ├── examples ├── Finite.dimensional.Lie.algebras.mht ├── LiterateLie.litsrc └── README-example └── new_project_template.weave /MOLLY.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | #----------------------------------------------------------------------------------------- 4 | # MOLLY - A MO-DULE FOR LI-TERATE PROGRAMMING 5 | #----------------------------------------------------------------------------------------- 6 | # ............................................ 7 | # .......licensed under GPL version 3......... 8 | # ............................................ 9 | # ....... Author: unixtechie; email: ......... 10 | # .. /same/ .. at .. yahoo .. dot .. com .... 11 | # ............................................ 12 | # ..... Git depos. - docs and download: ...... 13 | # http://github.com/unixtechie/Literate-Molly/ 14 | # ............................................ 15 | # 16 | #----------------------------------------------------------------------------------------- 17 | #---|-4-|-8-|-12----|-20------|-30------|-40------|-50------|-60------|-70------|-80------| 18 | 19 | 20 | # need to fool the noweb "notangle" utility, switch markup modes etc. 21 | $lt = "<"; 22 | $gt = ">"; 23 | $lt_esc = "<"; 24 | $gt_esc = ">"; 25 | $dash = "-"; 26 | $dot = "\."; 27 | 28 | # ----- GENERAL settings ----- 29 | 30 | # print toc? 1:0 31 | $print_toc = 1 unless defined $print_toc; 32 | 33 | # keep TOC expanded on initial load? "block":"none" 34 | $toc_expanded = $toc_expanded || "block"; 35 | 36 | # keep TOC expanded in initial load? "block":"none" 37 | $ind_expanded = $ind_expanded || "none"; 38 | 39 | # what is the file extention to weave it? (perms must allow execution!) 40 | # e.g. "scriptname.weave" or "scriptname.cgi" etc. 41 | $weave_extension = $weave_extension || "weave"; # default is "weave" 42 | 43 | # what is the file extention to tangle it? (perms must allow execution!) 44 | # e.g. "scriptname.tangle", "scriptname.pl" etc. 45 | $tangle_extension = $tangle_extension || "tangle"; # default is "tangle" 46 | 47 | 48 | #When tangling, should I use the built-in tangler? 0:1 49 | # (if 0, the "pass-through" tangling will call "notangle" 50 | # from Ramsey's "noweb" tools, must be installed and in your path) 51 | # use_builtin_tangler = 0; # default for now is to use external "notangle" 52 | $use_builtin_tangler = $use_builtin_tangler || 0; 53 | 54 | # Actually, let's always do it and disallow unsetting 55 | # number lines ? 1 : else 56 | $line_numbering = 1; 57 | 58 | # Print LitSource's line nums as a reference in the tangled output? deflt is 0. 59 | $print_ref_linenos_when_tangling = $print_ref_linenos_when_tangling || 0; 60 | $code_sections_comment_symbol = $code_sections_comment_symbol || "# "; 61 | 62 | 63 | # find and print root chunks in the LitSrc (i.e. instead of tangling when it is run 64 | # as "./LitSrc.tangle" from command line) ? 0:1 65 | $show_all_roots = $show_all_roots || 0; # default is not (i.e. to tangle) 66 | 67 | 68 | # how are doc sections marked? "dotHTML":"rawHTML" 69 | $weave_markup = $weave_markup || "rawHTML"; # default is "rawHTML" 70 | 71 | if ($weave_markup eq "dotHTML") { 72 | $tag_open = $dot; # this will take care of default 73 | $tag_close = $dot; # when no var is set in the Lit Src file 74 | } 75 | elsif ($weave_markup eq "rawHTML") { 76 | $tag_open = $lt; 77 | $tag_close = $gt; 78 | } #fi 79 | 80 | 81 | # enable MathML interpretation? 1 : 0 82 | $enable_ASCIIMathML = $enable_ASCIIMathML || 0; 83 | # If enabled, set the path; default is local in current dir 84 | $path_to_ASCIIMathML = $path_to_ASCIIMathML || "ASCIIMathML_with_modified_escapes.js"; 85 | 86 | # -- MAIN DESPATCHER WITH CL---- 87 | use Getopt::Std; 88 | 89 | 90 | sub usage { 91 | 92 | print STDERR<<'end_of_usage'; 93 | 94 | USAGE: MOLLY.pl [options] [--] filename 95 | 96 | -h, or no filename 97 | get this help message 98 | 99 | 100 | TANGLING Options: 101 | Tangling mode is default, no special option to force needed. 102 | 103 | -R "root_chunk_name", 104 | tangle starting from this chunk. if omitted, "*" is default. 105 | 106 | -l 'comment symbol for your language', 107 | add comments with coresponding line numbers in Lit Src 108 | 109 | -i information on root chunks 110 | 111 | 112 | WEAVING options: 113 | 114 | -w, 115 | weave from the external target file (rawHTML), or 116 | -wd 117 | same for dotHTML-encoded files 118 | 119 | -m 'URL or path/to/ASCIIMathML.js library' 120 | process the file with ASCIIMathML lib. Option used in addition 121 | to mode-setting -w or -wd 122 | 123 | 124 | FORESTRY mode: 125 | 126 | -t -1, or -t 3 etc. (for default rawHTML-encoded files) 127 | -dt -2, or -dt 1 etc. (for "dotHTML"-encoded files) 128 | run as a "tree replant" filter: 129 | move subtree up 1 level or down 3 levels, etc. 130 | when employed as a filter on an editor's selected text. 131 | Renumbers html headings and vim folding marks. 132 | 133 | MOLLY.pl [-d] -t# < LitSource.file 134 | renumber headings and vim folding marks for a whole file from CL 135 | 136 | 137 | 138 | FOR INTERNALLY MOLLIFIED FILES: 139 | shortcut invocation - depending on file extension. If run as script 140 | 141 | "lit_prog_file.tangle" 142 | tangles to STDOUT, from default root "*" only. 143 | "lit_prog_file.weave" 144 | weaves to STDOUT as folding HTML; usable under CGI 145 | 146 | / OR: set your own extensions in your lit.source configuraton section / 147 | 148 | end_of_usage 149 | 150 | exit; 151 | } 152 | 153 | 154 | my @LITSOURCE_list = (); 155 | my %LITSOURCE_hash = (); 156 | 157 | # -1- shortcut invocations for "mollified" LitSrc file depending on its extension --- 158 | 159 | if ( $0 =~ m!\w+\.$weave_extension$! ) { 160 | 161 | open LITSOURCE, "< $0" or die "\n\tcould not open the target file\n\n"; 162 | goto WEAVE_ME; 163 | } 164 | elsif ( $0 =~ m!\w+\.$tangle_extension$! ) { 165 | 166 | open LITSOURCE0, "< $0" or die "\n\tcould not open the target file for tangling\n\n"; 167 | push @LITSOURCE_list, 'LITSOURCE0'; 168 | $LITSOURCE_hash{'LITSOURCE0'} = $0; 169 | goto TANGLE_ME; 170 | } 171 | 172 | # -2- MOLLY.pl as a standalone script is called from CGI, nothing in here yet --- 173 | 174 | elsif (defined $ENV{'REQUEST_METHOD'}) { 175 | 176 | 177 | print "Content-Type: text/html; charset=utf-8\n\n"; 178 | print <<_XXX_; 179 | 180 |

181 | I was caled as CGI, but this invocation seems to be meaningless.
182 | Maybe you meant to "weave", but set a wrong file extension.
183 | Goodbye.
184 | -- MOLLY.pl -- 185 |

186 | 187 | _XXX_ 188 | 189 | exit; 190 | 191 | 192 | } 193 | 194 | # -3- several cases for application of Molly to an external target file from CL --- 195 | 196 | #elsif (-t STDIN) { 197 | else { # do not check; assume it is command line now; will take piped input now. 198 | 199 | 200 | #print STDERR "$0 was called from command line..\n"; 201 | 202 | #-- getopts invocation 203 | getopts("hwm:dt:l:R:i", \%cl_args); 204 | 205 | # -- set doc sections markup (if not default=html): 206 | if($cl_args{d}) { 207 | $tag_open = $dot; 208 | $tag_close = $dot; 209 | $weave_markup = "dotHTML"; 210 | #print STDERR setting dotHTML markup\n"; 211 | } 212 | 213 | # -- "forestry" mode - act as a filter to move subtree levels 214 | if($cl_args{t}) { 215 | $replant_tree = $cl_args{t}; 216 | #print STDERR "moving subtree by '$replant_tree' levels\n"; 217 | goto FORESTRY; 218 | } 219 | 220 | 221 | # -- print USAGE if not evoked correctly 222 | if( (! defined $ARGV[0] ) or ( $cl_args{h} ) ) { usage(); exit }; 223 | 224 | # -- does target file exist? 225 | if ( -f $ARGV[0] ) { 226 | ; # nop, a debug printout 227 | #print STDERR "target file to operate on is $ARGV[0]\n"; 228 | } 229 | else { 230 | die "\n\tERROR: No target file $ARGV[0] seem to exist\n\n"; 231 | }; 232 | 233 | 234 | # -- Final CL despatch, do it: -- 235 | 236 | 237 | if($cl_args{w}) { # this is weaving - and I put "forestry" in here too 238 | 239 | if (@ARGV > 1) { 240 | print STDERR "\n\n\tDo not know how to weave several files\n"; 241 | print STDERR "\tweaving the first one: $cl_args{w}\n\n"; 242 | } 243 | 244 | if ($cl_args{m}) { 245 | # print STDERR "using ASCIIMathML.js - located at $cl_args{m}\n"; 246 | $enable_ASCIIMathML = 1; 247 | $path_to_ASCIIMathML = $cl_args{m}; 248 | } 249 | 250 | open LITSOURCE, "< $ARGV[0]" || die "could not open the target file\n"; 251 | goto WEAVE_ME; 252 | 253 | } 254 | 255 | else { # this is tangling, default action, no opt 256 | 257 | 258 | if($cl_args{d}) { 259 | #print STDERR "doc sections in coments; comment char is $cl_args{d}\n"; 260 | }; 261 | 262 | if($cl_args{u}) { 263 | #print STDERR "applying UN-tangling with script char is $cl_args{u}\n"; 264 | }; 265 | 266 | if($cl_args{i}) { 267 | #print STDERR "printing information on roots, discovered chunks\n"; 268 | $show_all_roots = 1; 269 | 270 | }; 271 | 272 | if($cl_args{l}) { 273 | #print STDERR "will add reflines; comment char is $cl_args{l}\n"; 274 | $print_ref_linenos_when_tangling = 1; 275 | $code_sections_comment_symbol = $cl_args{l}; 276 | }; 277 | 278 | # -- getting the root chunk for tangling -- 279 | if($cl_args{R}) { 280 | $root_chunk = $cl_args{R}; 281 | print STDERR "tangling root chunk '$root_chunk'\n"; 282 | }; 283 | 284 | 285 | for (my $countem=0; $countem < @ARGV; $countem++) { 286 | 287 | $LITSOURCE_multi = 'LITSOURCE' . $countem; 288 | open $LITSOURCE_multi, "< $ARGV[$countem]" 289 | or die "\n\tCould not open target file $ARGV[$countem]\n\n"; 290 | 291 | push @LITSOURCE_list, $LITSOURCE_multi; 292 | $LITSOURCE_hash{$LITSOURCE_multi} = $ARGV[$countem]; 293 | 294 | } # rof 295 | 296 | goto SEEK_PEEK_TANGLER; 297 | 298 | } # fi - CL final despatch 299 | 300 | exit; #redundant and unused 301 | 302 | 303 | } 304 | 305 | # # -4- other cases --- 306 | # 307 | # else { 308 | # 309 | # die "MOLLY.pl: I do not know how I was called, exiting anyway\n"; 310 | # 311 | # } # esle, fi - end of despatcher 312 | 313 | exit; # just in case 314 | 315 | 316 | TANGLE_ME: 317 | 318 | 319 | if ( $use_builtin_tangler ) { 320 | 321 | 322 | SEEK_PEEK_TANGLER: 323 | 324 | 325 | 326 | my $chunk_beg_pattern = q(^<\<(.*)>\>=); 327 | my $chunk_end_pattern = q(^@\s.*$); 328 | my $chunk_ref_pattern = q(<\<(.*?)>\>[^=]); # can be used several times in a line 329 | 330 | my $current_chunk_name = ""; 331 | my $current_chunk_start_foff = 0;; # "foff" is a "file offset" 332 | my $current_chunk_end_foff = 0; 333 | 334 | my %file_offsets_hash = (); 335 | my %file_lines_hash = (); 336 | my $parents_list = (); 337 | 338 | my $line_num = 0; 339 | my $previous_line_foff = 0; # "foff" is a "file offset" 340 | 341 | 342 | foreach $LITSOURCE_multi(@LITSOURCE_list) { 343 | 344 | 345 | while (<$LITSOURCE_multi>) { 346 | $line_num++; 347 | 348 | # --- CODE CHUNKS -- not inside documentation section 349 | if ( m!$chunk_beg_pattern! .. m!$chunk_end_pattern! ) { 350 | 351 | 352 | if ( $_ =~ m!$chunk_beg_pattern! ) { 353 | $current_chunk_name = $1; 354 | $current_chunk_start_foff = $LITSOURCE_multi . "-" . (tell $LITSOURCE_multi); 355 | 356 | # -- collecting offset and line number, actually 357 | push @{$file_offsets_hash{$current_chunk_name}}, $current_chunk_start_foff; 358 | push @{$file_lines_hash{$current_chunk_name}}, $LITSOURCE_multi . "-" . $.; 359 | #~ print "----> chunk $1 line $. offset $current_chunk_start_foff\n"; 360 | 361 | } 362 | 363 | 364 | elsif ( $_ =~ m!$chunk_end_pattern! ) { 365 | 366 | $current_chunk_end_foff = $LITSOURCE_multi . "-" . $previous_line_foff; 367 | # -- collecting offset and line number: 368 | push @{$file_offsets_hash{$current_chunk_name}}, $current_chunk_end_foff; 369 | push @{$file_lines_hash{$current_chunk_name}}, $LITSOURCE_multi . "-" . $.; 370 | #~ print "\tline $. offset $current_chunk_end_foff<------\n"; 371 | 372 | $current_chunk_name = ""; 373 | } 374 | 375 | 376 | elsif ( $_ =~ m!$chunk_ref_pattern!g ) { 377 | 378 | my $line = $_; 379 | my $current_foff_pos = $previous_line_foff; 380 | my $initial_margin = ""; 381 | my $homegrown_pos = 0; 382 | 383 | while ($line =~ m!(.*?)<\<(.*?)>\>!g) { 384 | 385 | my $pre_ref_match = $1; 386 | my $ref_match = $2; 387 | my $len_pre_ref_match = length $pre_ref_match; 388 | my $len_ref_match = length $ref_match; 389 | 390 | # "end" of prev pair; collecting offset and line number 391 | push @{$file_offsets_hash{$current_chunk_name}}, 392 | $LITSOURCE_multi . "-" . ($current_foff_pos + $len_pre_ref_match); 393 | push @{$file_lines_hash{$current_chunk_name}}, $LITSOURCE_multi . "-" . $.; 394 | 395 | 396 | #-------deal with pushing ("ref", "chunkname") pair ----- 397 | # special id string for refs 398 | push @{$file_offsets_hash{$current_chunk_name}}, "ref"; 399 | # name of reference 400 | push @{$file_offsets_hash{$current_chunk_name}}, $ref_match; 401 | # .. and form pairs for toposort (cycles check, search roots): 402 | push @parents_list, ($current_chunk_name, $ref_match); 403 | 404 | # -- next a special entry for refs: (left_margin) 405 | # I keep tabs and spaces and subst all else to spaces 406 | $pre_ref_match =~ s!\S! !g; 407 | $initial_margin .= $pre_ref_match; 408 | push @{$file_offsets_hash{$current_chunk_name}}, $initial_margin; 409 | $initial_margin .= " " x ( $len_ref_match + 2*( length "<>") ); 410 | 411 | my $homegrown_pos = $len_pre_ref_match + $len_ref_match + 2*(length "<>"); 412 | my $end_of_match_pos = $current_foff_pos + $homegrown_pos; 413 | 414 | # "start" a new pair.. - ok, let's not use "pos" at all, if it fails 415 | # .. and collect both offset and the line number 416 | push @{$file_offsets_hash{$current_chunk_name}}, 417 | $LITSOURCE_multi . "-" . $end_of_match_pos; 418 | push @{$file_lines_hash{$current_chunk_name}}, $LITSOURCE_multi . "-" . $.; 419 | 420 | # I'll need to reset current_foff_pos to the pos 421 | # (or to the directly caclucalted offset, if I prefer that): 422 | $current_foff_pos = $end_of_match_pos; 423 | 424 | } # elihw 425 | 426 | # This is where chunk refs get an extra newline ? 427 | 428 | } # fisle 429 | 430 | 431 | else { # chunk body 432 | ; # nop; here just not to hide an implicit case 433 | #~ print "."; # debug: show dots for lines 434 | } 435 | 436 | 437 | } #fi 438 | 439 | $previous_line_foff = tell $LITSOURCE_multi; 440 | 441 | } # eliwh 442 | 443 | } # hcaerof iteration over all files collecting file offsets 444 | 445 | 446 | 447 | 448 | sub topological_sort { 449 | 450 | my $flag_show_roots = shift; 451 | my %pairs; # all pairs ($l, $r) 452 | my %npred; # number of predecessors 453 | my %succ; # list of successors 454 | my $opt_b = 0; 455 | 456 | my @topo_list_out = ''; 457 | 458 | while ( @_ ) { 459 | my $l = shift @_; 460 | my $r = shift @_; 461 | my @l = ($l, $r); 462 | #my ($l, $r) = my @l = split; 463 | next unless @l == 2; 464 | next if defined $pairs{$l}{$r}; 465 | $pairs{$l}{$r}++; 466 | $npred {$l} += 0; 467 | ++$npred{$r}; 468 | push @{$succ{$l}}, $r; 469 | } 470 | 471 | # create a list of nodes without predecessors 472 | my @list = grep {!$npred{$_}} keys %npred; 473 | 474 | #--print discovered roots, if asked-- 475 | if ($flag_show_roots) { 476 | print "\n\t--roots of multi-chunk chains--\n"; 477 | for (@list) { print "\t$lt$lt$_$gt$gt\n";} 478 | print "\t-------------------------------\n"; 479 | } 480 | 481 | while (@list) { 482 | $_ = pop @list; 483 | unshift @topo_list_out, $_; 484 | #print "$_\n"; 485 | foreach my $child (@{$succ{$_}}) { 486 | if ($opt_b) { # breadth-first 487 | unshift @list, $child unless --$npred{$child}; 488 | } else { # depth-first (default) 489 | push @list, $child unless --$npred{$child}; 490 | } 491 | 492 | } 493 | } 494 | 495 | # mm.. better if I warn, print out the list so far, and then exit 496 | # the user will have the place where the problem occured 497 | #~ warn "cycle detected\n" if grep {$npred{$_}} keys %npred; 498 | if ( grep {$npred{$_}} keys %npred ){ 499 | warn "\n\tERROR: cycle detected - aborting execution!\n"; 500 | print "\n---chunks discovered before the 'cycle' ERROR - sorted topologically ---\n"; 501 | for (@topo_list_out) { 502 | print "$_\n"; 503 | } # rof 504 | 505 | exit; 506 | } # fi check for cycles 507 | 508 | # -DEBUG- 509 | # if ($flag_show_roots){ 510 | # print "\t--all chunks discovered--\n"; 511 | # for (@topo_list_out) { 512 | # print $_, "\n"; 513 | # } 514 | # exit; 515 | # } 516 | 517 | return @topo_list_out; 518 | #return 1; 519 | } # tros_lacigolopot 520 | 521 | 522 | # will abort if cycles detected. Does not detect all cycles? - need to check 523 | my @chunks_in_chains = topological_sort($show_all_roots, @parents_list); 524 | 525 | if ($show_all_roots){ 526 | 527 | # non-standalone roots are already printed from inside "topological_sort" 528 | print "\n\t------single-chunk roots-------\n"; 529 | my %lookup_hash = (); 530 | for (@chunks_in_chains){ $lookup_hash{$_} = 1;} 531 | 532 | for (keys %file_offsets_hash) { 533 | print "\t$lt$lt$_$gt$gt\n" 534 | unless exists $lookup_hash{$_}; 535 | } 536 | print "\t-------------------------------\n\n"; 537 | exit; 538 | } 539 | 540 | 541 | # USAGE: print_chunk(name_of_chunk, left_margin, print_newline_flag) 542 | sub print_chunk { 543 | 544 | (my $chunk_being_printed, 545 | my $snippet_left_margin, 546 | my $snippet_print_newline_flag, @rest) = @_; 547 | 548 | 549 | #~ print "\n---- printing chunk $chunk_being_printed --------\n"; 550 | #~ print "DEBUG: got left.m. $snippet_left_margin nl. flag $snippet_print_newline_flag \n"; 551 | 552 | # -- error mess. not to fail silently -- 553 | unless ( defined $file_offsets_hash{$chunk_being_printed} ) { 554 | die "\n\tERROR: chunk $chunk_being_printed not found in file $ARGV[0]\n\n"; 555 | } 556 | 557 | 558 | # iterate over splinters of a chunk, which are foff pairs 559 | my $iterate_lines = 0; 560 | for ( my $iterate_foffs = 0; 561 | exists $file_offsets_hash{$chunk_being_printed}[$iterate_foffs];) 562 | { 563 | 564 | my $snippet_position = $file_offsets_hash{$chunk_being_printed}[$iterate_foffs++]; 565 | my $snippet_end = $file_offsets_hash{$chunk_being_printed}[$iterate_foffs++]; 566 | 567 | #~ print "debug got: beg $snippet_position -- end $snippet_end\n"; 568 | 569 | 570 | if ($snippet_position eq "ref") { 571 | 572 | my $snippet_left_margin_ref = 573 | $file_offsets_hash{$chunk_being_printed}[$iterate_foffs++]; 574 | 575 | # any call to a ref uncurs "print newline" flag of 0 576 | print_chunk($snippet_end, $snippet_left_margin_ref, 0); 577 | 578 | } 579 | 580 | else { # .. print it here 581 | 582 | (my $litsrc_fhname_beg, my $litsrc_line_beg) = 583 | split '-', $file_lines_hash{$chunk_being_printed}[$iterate_lines++]; 584 | (my $litsrc_fhname_end, my $litsrc_line_end) = 585 | split '-', $file_lines_hash{$chunk_being_printed}[$iterate_lines++]; 586 | 587 | (my $litsrc_fhname_beg, my $litsrc_foff_beg) = split '-', $snippet_position; 588 | (my $litsrc_fhname_end, my $litsrc_foff_end) = split '-', $snippet_end; 589 | # DEBUG prints: 590 | #print "in file_beg $litsrc_fhname_beg $litsrc_foff_beg\n"; 591 | #print "in file_end $litsrc_fhname_end $litsrc_foff_end\n------\n"; 592 | 593 | 594 | # the file is always the same, though. You cannot have one chunk splinter 595 | # start in one file and end in another one. (2 splinters can live in 2 files) 596 | seek $litsrc_fhname_beg, $litsrc_foff_beg, 0; 597 | read $litsrc_fhname_end, $buffer_out, ($litsrc_foff_end - $litsrc_foff_beg); 598 | 599 | #----Newlines at the end of chunks and refs. 600 | # only for the last splinter of a chunk, do newline control: 601 | if ( ((scalar @{$file_offsets_hash{$chunk_being_printed}}) - $iterate_foffs ) == 0 ) 602 | { 603 | # works, but is suspicious logically: 604 | # maybe I just have not invented a counterexample yet, and 605 | # it's a trap waiting for its quarry. But it works 606 | $buffer_out =~ s!\n([\s]*)$!$1! unless ($snippet_print_newline_flag); 607 | } 608 | 609 | #----Left indent/margin. Seems OK 610 | 611 | $chunk_left_margin = $snippet_left_margin; 612 | $buffer_out =~ s!(\n)!$1$chunk_left_margin!sg; 613 | 614 | 615 | #----And Print Out: 616 | 617 | if ($print_ref_linenos_when_tangling){ 618 | print $code_sections_comment_symbol, 619 | "[line ", $litsrc_line_beg," in file ", 620 | $LITSOURCE_hash{$litsrc_fhname_beg}, "]__start" ; 621 | print "_________________________________\n"; 622 | } 623 | 624 | print $buffer_out; 625 | 626 | if ($print_ref_linenos_when_tangling) { 627 | print $code_sections_comment_symbol, 628 | "[line ", $litsrc_line_end," in file ", 629 | $LITSOURCE_hash{$litsrc_fhname_end}, "]__end" ; 630 | print "___________________________________\n"; 631 | } 632 | 633 | } #esle for printout 634 | 635 | 636 | } # rof non-destructive 637 | 638 | return 1; 639 | } # bus -- ends the recursive sub 640 | 641 | 642 | $root_chunk = $root_chunk || "*"; 643 | 644 | # USAGE: print_chunk(name_of_chunk, left_margin, print_newline_flag) 645 | print_chunk($root_chunk, "", 1); 646 | 647 | # and close all the opened files 648 | for (@LITSOURCE_list){close $_;} 649 | 650 | 651 | exit; 652 | 653 | 654 | } 655 | else { # pass to "notangle" from "noweb" tools by Ramsey 656 | 657 | open TANGLE_PIPE, "| notangle -t4 -"; 658 | 659 | while () { 660 | 661 | if ( m!^<\<(.*)>\>=! ... m!^@\s*$! ) { # -- CODE CHUNKS ONLY -- 662 | print TANGLE_PIPE $_; 663 | } 664 | 665 | } # elihw 666 | 667 | close TANGLE_PIPE; 668 | close LITSOURCE0; 669 | 670 | } #; esle, pass-through clause end 671 | 672 | exit; 673 | 674 | 675 | 676 | WEAVE_ME: 677 | 678 | #1. Set formatting strings for weaver 679 | 680 | #----SETTING FORMATTING STRINGS----------- 681 | 682 | $html_head = < 685 | 686 | 687 | head_end_1 688 | 689 | #switch on ASCIIMathML.js library if enabled in template options: 690 | if ($enable_ASCIIMathML) { 691 | $html_head .= "\n" 692 | . qq() 693 | . "\n"; 694 | } 695 | 696 | $html_head .= < 700 | 701 | function toggleDiv(divid) { 702 | var el = document.getElementById(divid); 703 | el.style.display = (el.style.display == 'block') ? 'none' : 'block'; 704 | } 705 | 706 | 707 | function toggleCombined(divid){ 708 | if(document.getElementById(divid).style.display == 'none'){ 709 | document.getElementById(divid).style.display = 'block'; 710 | document.getElementById("toc"+divid).className="hilited"; 711 | } 712 | else{ 713 | document.getElementById(divid).style.display = 'none'; 714 | document.getElementById("toc"+divid).className="unhilited"; 715 | } 716 | } 717 | 718 | 719 | function showAll(){ 720 | for(i=1; i <= 10000; i++){ 721 | document.getElementById(i).style.display = 'block'; 722 | document.getElementById("toc"+i).className="hilited"; 723 | }; 724 | } 725 | 726 | function hideAll(){ 727 | for(i=1; i <= 10000; i++){ 728 | document.getElementById(i).style.display = 'none'; 729 | document.getElementById("toc"+i).className="unhilited"; 730 | }; 731 | } 732 | 733 | 734 | function open_all_above(someid){ 735 | 736 | elem = document.getElementById(someid); 737 | elem.style.display = 'block'; 738 | document.getElementById('toc'+someid).className = 'hilited'; 739 | 740 | while (elem.parentNode.id != 1) { 741 | if (elem.parentNode.nodeType == 1) { 742 | elem.parentNode.style.display = 'block'; 743 | //document.getElementById(elem.parentNode.id).className = 'hilited'; 744 | var toc_elem = document.getElementById('toc'+elem.id); 745 | if (toc_elem) {toc_elem.className = 'hilited'}; 746 | } 747 | elem = elem.parentNode; 748 | } 749 | } 750 | 751 | 752 | 753 | // DELETING a CLONE -- this works too: 754 | function DeleteVirtualNode(someid) { 755 | 756 | elem = document.getElementById(someid); 757 | 758 | while (elem.childNodes.length > 0) { 759 | elem.removeChild(elem.firstChild); 760 | } 761 | } 762 | 763 | // CREATING a CLONE - this works 764 | /* for clean execution - run "delete" before any creation */ 765 | function CreateVirtualNode(clone_from_id, append_to_id){ 766 | DeleteVirtualNode(append_to_id); 767 | 768 | if ( document.getElementById(append_to_id).childNodes.length == 0 ) { 769 | var elem = document.createElement("div"); 770 | 771 | elem = document.getElementById(clone_from_id).cloneNode(1); 772 | elem.style.display = 'block'; 773 | document.getElementById(append_to_id).appendChild(elem); 774 | 775 | } /* fi - do not create duplicates of the cloned node */ 776 | 777 | } 778 | 779 | 780 | 781 | 782 | 934 | 935 | 936 | 937 | head_end 938 | 939 | $html_body_table = "

"; 940 | $html_body_table_end = "\n
\n"; 941 | 942 | 943 | $folding_section_start1_str = <<'fold_sect_start_1_xxx'; 944 |
945 | fold_sect_start_1_xxx 946 | 947 | 948 | $folding_section_start2_str = <<'fold_sect_start_2_xxx'; 949 |
950 |

951 |

$highlight_state 952 | 959 |

960 |
961 | 962 | 963 | Close the subsection 964 | -- 965 | 966 | expand all -- 967 | 968 | collapse all 969 | 970 | 971 |

972 |

973 | 974 | folding_section_end_xxx 975 | 976 | 977 | $code_fieldset_start_pre = q(
); 978 | $code_fieldset_start_post = "="; 979 | $code_fieldset_end = "
\n"; 980 | 981 | 982 | #2. accumulate result in a buffer 983 | #2. accumulate result in a buffer 984 | 985 | 986 | # vars for the main loop over lines of the target file 987 | 988 | $chunkbuf = ''; # collects whole formatted project file in memory 989 | $tocbuf = ""; # will accumulate TOC contents, i.e. small 990 | @indbuf = (); # accumulates index of code chunks, small 991 | @headings = (); # the stack for nested subsections numbers/ids 992 | %headings_id_hash = (); 993 | %chunks_id_hash = (); 994 | 995 | $section_num = 0; 996 | $section_num_prev = 0; 997 | $section_level = 0; 998 | $prev_section_level = $section_level; 999 | $line_counter = 0; 1000 | $in_pre_tag = 0; 1001 | 1002 | 1003 | 1004 | while () { 1005 | 1006 | $line_counter++; 1007 | 1008 | 1009 | if ( ($line_counter == 1) && (m!^#.*perl!) ) { 1010 | 1011 | # Matched? - this must be either the mollifying template or some perl script. 1012 | 1013 | do { 1014 | $_ = ; 1015 | $line_counter++; 1016 | if (eof LITSOURCE) { 1017 | print "\n\t--------ERROR: wrong target file format for weaving--------\n"; 1018 | print "\tmay be a regular perl script, without a call for Molly\n\n"; 1019 | exit; 1020 | } 1021 | } until ( lc($_) =~ m!^do.*molly!) ; 1022 | 1023 | # throw away lines until DATA, then process/weave normally 1024 | do { 1025 | $_ = ; 1026 | $line_counter++; 1027 | if (eof LITSOURCE) { 1028 | print "\n\t--------ERROR: wrong target file format for weaving--------\n"; 1029 | print "\tdid not find the __DATA__ keyword in first pos on its line\n\n"; 1030 | exit; 1031 | } 1032 | } until ( m!^__DATA__! ) ; 1033 | 1034 | next; 1035 | 1036 | } # fi cutting out MOLLY.pl template/config if present in lit.source target file 1037 | 1038 | 1039 | 1040 | if ( m!^<\<(.*)>\>=! ... m!^@\s*$! ) { # -- CODE CHUNKS -- 1041 | 1042 | s/&/&/g; # escape & 1043 | s//>/g; # escape > 1045 | my $codechunk_id = ""; 1046 | 1047 | if ( m!(<<(.+?)>>)(=)?! ) 1048 | { 1049 | $chunk_title = $2; 1050 | $reference = $1; 1051 | $ind_str = "<<$2>> $section_num"; 1052 | if (defined $3) {$ind_str .= "def"} 1053 | else { s!$reference!$reference! } 1054 | 1055 | unshift @indbuf, $ind_str; 1056 | 1057 | # /.. "if" is not finished in this chunk yet.. read on/ 1058 | 1059 | # cut-in for virtual links handling: create codechunk_id 1060 | if (defined $3) { 1061 | 1062 | $codechunk_id = 'codechunk' . $.; 1063 | push @{$chunks_id_hash{$chunk_title}}, $codechunk_id; # with splinters 1064 | 1065 | my $splinter_number = ''; 1066 | $splinter_number = @{$chunks_id_hash{$chunk_title}} 1067 | if @{$chunks_id_hash{$chunk_title}} > 1; 1068 | 1069 | # simple fieldset frames around code snippets if chunk definition 1070 | # /changing current line $_ which will get appended to $chunkbuf/ 1071 | s!^<<(.+)>>=! 1072 |
1073 | $code_fieldset_start_pre<<$1>>$splinter_number$code_fieldset_start_post!x; 1074 | 1075 | } # fi - cut-in for virtual chunk links 1076 | 1077 | } # fi - chunks index accumulation 1078 | 1079 | 1080 | # close fieldset frame at end of code chunk 1081 | s!^@\s*$!$code_fieldset_end
!; 1082 | 1083 | 1084 | if ( $line_numbering ) { 1085 | $chunkbuf .= "" . $line_counter . " " . $_; 1086 | } 1087 | else{ 1088 | $chunkbuf .= $_; 1089 | } 1090 | 1091 | } # fi code chunks 1092 | 1093 | 1094 | # -- SECTION HEADINGS 1095 | #elsif ( m!\.(\+)?h(\d)\.(.*?)\./h\d\.! ) { # old version, no "rawHTML" enabled yet 1096 | elsif 1097 | ( m!$tag_open(\+)?h(\d{1,2})$tag_close(.*?)$tag_open/h\d{1,2}$tag_close! ) 1098 | { 1099 | 1100 | # -- using split vars for substitution to avoid 1101 | # regexps and need to keep old state -- 1102 | 1103 | $section_num_prev = $section_num; 1104 | $section_num = $section_num + 1; 1105 | 1106 | 1107 | #default for fold state in "settings" ?? 1108 | if ($1 eq "+") { 1109 | $fold_state="block"; 1110 | $highlight_state = qq! !; 1113 | } 1114 | else { 1115 | $fold_state="none"; 1116 | $highlight_state = ""; 1117 | }; 1118 | $section_level = $2; 1119 | $section_title = $3; 1120 | 1121 | # add-on for virtual nodes; DEBUG for now 1122 | $stripped_section_title = $section_title; 1123 | $stripped_section_title =~ s!\s*(.*\S)\s*!$1!; 1124 | $headings_id_hash{$stripped_section_title} = $section_num; 1125 | 1126 | 1127 | $folding_section_start1 = $folding_section_start1_str; 1128 | $folding_section_start2 = $folding_section_start2_str; 1129 | $folding_section_end = $folding_section_end_str; 1130 | 1131 | 1132 | $folding_section_start1 =~ s!(\$section_num)!$1!ee; 1133 | $folding_section_start2 =~ s!(\$section_num)!$1!ee; 1134 | $folding_section_start2 =~ s!(\$fold_state)!$1!ee; 1135 | $folding_section_start2 =~ s!(\$highlight_state)!$1!ee; 1136 | $folding_section_end =~ s!(\$section_num_prev)!$1!ee; 1137 | 1138 | 1139 | $section_id = $section_level . '-' . $section_num; 1140 | 1141 | # finish previous subsection if not the first section in the file 1142 | # ..and deal with nesting of sections according to their "depth level" 1143 | 1144 | # this is NOT the first section: 1145 | if ( exists $headings[0] ){ 1146 | 1147 | ($prev_section_level, $prev_section_num) = split /-/, $headings[0]; 1148 | 1149 | if ($section_level == $prev_section_level){ 1150 | 1151 | # close prev, start new 1152 | $chunkbuf .= $folding_section_end; 1153 | shift @headings; 1154 | 1155 | } 1156 | 1157 | elsif($section_level < $prev_section_level){ 1158 | 1159 | # close a bunch of them, in a loop -- THEN start a new one. 1160 | do { 1161 | ($prev_section_level, $section_num_prev) = split /-/, shift @headings; 1162 | 1163 | $folding_section_end = $folding_section_end_str; 1164 | $folding_section_end =~ s!(\$section_num_prev)!$1!ee; 1165 | $chunkbuf .= $folding_section_end; 1166 | 1167 | } while ( $section_level < $prev_section_level ); 1168 | } 1169 | } # fi not the first section 1170 | 1171 | # end of "finish previous subsection if not the first section in the file" 1172 | 1173 | # common operations 1174 | unshift @headings, $section_id ; 1175 | $chunkbuf .= $folding_section_start1; 1176 | $chunkbuf .= "(" . $section_num . ")" 1177 | . " " . $section_title 1178 | . " (line " 1179 | . $line_counter 1180 | . ")"; 1181 | 1182 | $chunkbuf .= " toc"; 1183 | 1184 | #for F-links 1185 | $chunkbuf .= ""; 1186 | 1187 | $chunkbuf .= $folding_section_start2; 1188 | 1189 | #$chunkbuf .= "\n" . "------ line " . $line_counter . 1190 | # " ------
\n"; 1191 | 1192 | # TOC Navigation: open all parents, then junp to section 1193 | my $open_all_and_jump = 1194 | q/ 
/ . '))'; 1199 | 1200 | 1201 | # TOC Navigation: open_all_above(someid) 1202 | $tocbuf .= 1203 | $open_all_and_jump . " " 1204 | . q/ / . '' . $section_num . ''; 1207 | 1208 | $toc_indent = " "x4 . ". " x (($section_level-1) * 3); 1209 | 1210 | # old-disabled 1211 | #$toc_indent = " " x ($section_level * 7); 1212 | #$toc_indent = " " x (($section_level-1) * 7 ); 1213 | #$tocbuf .= "\n

\n" if ( $section_level == 1 ); 1214 | 1215 | $tocbuf .= $toc_indent . 1216 | #--disabled--#"" . $section_num . "" . 1217 | qq/ / . 1221 | $section_title . " (line " . 1222 | $line_counter . ")" . 1223 | ""; 1224 | 1225 | # and end the line 1226 | $tocbuf .= "
\n"; 1227 | 1228 | 1229 | 1230 | } #; fisle: end elif headings 1231 | 1232 | 1233 | 1234 | else { # this is the body of the doc section 1235 | 1236 | if( $weave_markup eq "rawHTML" ) { # if the doc chunks marked up with real HTML 1237 | s!^#-----.*!!; 1238 | 1239 | #s/^{{{\d+(.*)$/$1/; # - eliminate vim folding markup, start 1240 | # - dummy, as it's killed in "headings" processing 1241 | s/^}}}\d+//; # - eliminate vim folding markup, end 1242 | 1243 | 1244 | # Paragraphs and line breaks are automatic now: 1245 | # ... unless we are dealing with the "preformat" tag 1246 | #--note! that ranges do not work here 1247 | $in_pre_tag = 1 if (m!

!);
1248 |                 $in_pre_tag = 0 if (m!
!);; 1249 | 1250 | 1251 | unless ($in_pre_tag) { 1252 | (m/^\s*$/) and s/$_/

\n/ 1253 | or s/\n/
\n/; 1254 | } 1255 | 1256 | $chunkbuf .= $_; 1257 | 1258 | } # fi - default rawHTML formatter for body of doc chunks 1259 | 1260 | 1261 | 1262 | elsif( $weave_markup eq "dotHTML" ) { # dotHTML formatter here 1263 | 1264 | s/^=begin.*$//; # - eliminate perl escaping, start 1265 | s/^=cut.*$//; # - eliminate perl escaping, end 1266 | #s/^{{{\d+(.*)$/$1/; # - eliminate vim folding markup, start 1267 | # - dummy, as it is killed in "headings" processing 1268 | s/^}}}\d+//; # - eliminate vim folding markup, end 1269 | 1270 | s/&/&/g; # escape & 1271 | s//>/g; # escape > 1273 | 1274 | 1275 | # Paragraphs and line breaks are automatic now: 1276 | # ... unless we are dealing with the "preformat" tag 1277 | #--note! that ranges do not work here 1278 | $in_pre_tag = 1 if (m!\.pre\.!); 1279 | $in_pre_tag = 0 if (m!\./pre\.!);; 1280 | 1281 | s/\.(\/?)pre\./<$1pre>/g; 1282 | 1283 | unless ($in_pre_tag) { 1284 | (m/^\s*$/) and s/$_/

\n/ 1285 | or s/\n/
\n/; 1286 | } 1287 | 1288 | # originally I separated header from the body with such a line 1289 | #s/^#-----.*/starting the table here/; 1290 | s/^#-----.*//; 1291 | 1292 | 1293 | # add more here 1294 | 1295 | s/\.(\/?)b\./<$1b>/g; 1296 | s/\.(\/?)i\./<$1i>/g; 1297 | s/\.(\/?)ul\./<$1ul>/g; 1298 | s/\.(\/?)li\./<$1li>/g; 1299 | s/\.(\/?)ol\./<$1ol>/g; 1300 | s/\.(\/?)s\./<$1s>/g; 1301 | s/\.(\/?)div\./<$1div>/g; 1302 | s/\.br\./
/g; 1303 | s/\.p\./

/g; 1304 | s/\.sp\./ /g; 1305 | 1306 | s/\.(\/?)tab\./<$1ul>/g; # "tabbing" with "ul" 1307 | 1308 | 1309 | # this is some bullshit ??? 1310 | s/\.hr\./


/g; 1312 | 1313 | s!\.a\.(.+?)\.\/a\.!$1!g; 1314 | 1315 | # rudimentary   s p a c i n g   (one word only) 1316 | #s!\.x\.(.+?)\./x\.!join " ","  ",(split //, $1),"  "!eg; 1317 | 1318 | # slightly better spacing (phrases, too): 1319 | # although redundant with more work than is needed 1320 | if ( m!(\.x\.)(.+?)(\./x\.)!g) { 1321 | s!(\.x\.)(.+?)(\./x\.)!join " _ ", $1, (split / /, $2), $3!eg; 1322 | s!\.x\.(.+?)\./x\.!join " ", (split //, $1)!eg; 1323 | s! _ !   !g; 1324 | } 1325 | 1326 | # generic for all tags with options 1327 | s!\.<\. !!g; 1329 | 1330 | 1331 | $chunkbuf .= $_; 1332 | 1333 | } # fisle - end of "dotHTML" body formatter 1334 | 1335 | 1336 | 1337 | if (m!^\s*\[\[LINKED_CHUNK(_\d+)?\s+(.*\S)\s*\]\]\s*
$!) { # -- CHUNK LINKS -- 1338 | my $index_str = "<<$2>> " . $section_num . "link"; 1339 | unshift @indbuf, $index_str; 1340 | } 1341 | 1342 | } # esle, fi -- end of processing inside 'while' over the file lines. 1343 | 1344 | 1345 | # debug 1346 | #print "---- $_"; 1347 | 1348 | 1349 | } #elihw over the whole input file 1350 | 1351 | close LITSOURCE; 1352 | 1353 | foreach (@headings) { 1354 | 1355 | ($section_level, $section_num_prev) = split /-/, $_; 1356 | $folding_section_end = $folding_section_end_str; 1357 | $folding_section_end =~ s!(\$section_num_prev)!$1!ee; 1358 | $chunkbuf .= $folding_section_end; 1359 | 1360 | }; 1361 | 1362 | 1363 | #3. print out the TOC, the Chunks Index, the output buffer and close the page. 1364 | 1365 | # begin the page: 1366 | 1367 | # /disabled doctype line/ - it garbles output of TOC (!!) 1368 | #print q(), "\n"; 1370 | 1371 | print "\n $html_head\n $html_body_table \n"; 1372 | 1373 | # print out the TOC, the Chunks Index, the output buffer and close the page. 1374 | 1375 | 1376 | print <
1378 | TABLE OF CONTENTS: outline of the document structure 1379 | 1380 |
    1381 |

    1382 |
    1383 |

    1387 | 1431 |

    1432 |
    1433 |

    1434 |

    1435 |

    1436 | 1437 | TABLE OF CONTENTS [expand/collapse] 1438 | 1439 |

    1440 | 1441 |
    1442 | 1443 |
    1444 | 1445 |

    Section name toggles expanded state. Subsection number on the left opens 1446 |
    all parent sections to make it visible. Leftmost symbol opens parents and 1447 |
    jumps to the section. 1448 |
    1449 |

    1450 | 1451 | end_of_print 1452 | 1453 | 1454 | print "$tocbuf" if $print_toc; 1455 | #print "$tocbuf"; 1456 | 1457 | print "
    \n"; 1458 | 1459 | 1460 | print < 1462 |
    1463 |

    1464 | 1465 |

    1469 | 1470 |

    1471 |

    1472 |
      1473 |

      1474 | A "def" superscript means the chunk is defined,
      1475 | a "link" that the chunk is being linked to from that section,
      1476 | and a bare number means the chunk is being used in a section. 1477 |

      1478 | end_of_print 1479 | 1480 | 1481 | $ind_outbuf = ''; 1482 | $prev_ch_name = ''; 1483 | 1484 | #for (sort @indbuf){ print $_, "
      ";} 1485 | 1486 | for (sort @indbuf){ 1487 | 1488 | ($ch_name, $closing_bracket, $ref_num) = split />/, $_; 1489 | #/ - for editor colouring bug 1490 | 1491 | if ( $ch_name eq $prev_ch_name ){ 1492 | $ind_outbuf .= " " . $ref_num . " "; 1493 | } 1494 | else{ 1495 | print $ind_outbuf, "
      \n"; 1496 | $ch_namestr = $ch_name; 1497 | $ch_namestr =~ s!<<!!; 1498 | $ind_outbuf = 1499 | "<<" . 1500 | $ch_namestr . 1501 | ">> -- " . 1502 | $ref_num . 1503 | " "; 1504 | } 1505 | $prev_ch_name = $ch_name; 1506 | 1507 | }; # rof - forming the code chunks index 1508 | 1509 | print $ind_outbuf, "
      \n"; 1510 | 1511 | 1512 | # The "expand all" "collapse all" control 1513 | 1514 | print <\n

      1516 |
      1517 |

      1523 | end_of_print 1524 | 1525 | 1526 | print "

\n
"; 1527 | 1528 | 1529 | #The FULL OUTPUT, the file body (with links handling added): 1530 | 1531 | 1532 | sub print_chunk_link { 1533 | 1534 | (my $name_of_linked_chunk, $virtual_id, my $created_clone_div_id, my $shown_splinter_num) = @_; 1535 | 1536 | print <<"end_of_clone_sect"; 1537 | 1538 |

1539 | 1540 | $lt_esc$lt_esc$name_of_linked_chunk$gt_esc$gt_esc $shown_splinter_num 1541 | 1542 | [open] 1545 | [close] 1548 | 1549 |
1550 |
1551 |
1552 | 1553 | end_of_clone_sect 1554 | 1555 | # a DEBUG printout: 1556 | #for (keys %chunks_id_hash) {print "[$_] => $chunks_id_hash{$_}
\n"} 1557 | 1558 | #
DEBUG: trying to clone [[$1]] whose id is [$virtual_id] 1559 | #OR [$chunks_id_hash{$name_of_linked_chunk}] 1560 | 1561 | } # bus -- printing out formatted CHUNK_LINK cloning line 1562 | 1563 | 1564 | my $clonebody_cnt = 0; # to assign unique id's to divs to put clones in. 1565 | 1566 | while ($chunkbuf =~ m!^(.*)$!gm ) { # -- line by line iteration over the doc as string in mem 1567 | my $printed_line = $1; 1568 | 1569 | 1570 | if ($printed_line =~ m!^\s*\[\[LINKED_CHUNK(_\d+)?\s+(.*\S)\s*\]\]\s*
$!) { # -- CHUNK LINKS -- 1571 | 1572 | my $name_of_linked_chunk = $2; 1573 | 1574 | unless ( exists $chunks_id_hash{$name_of_linked_chunk} ) { 1575 | 1576 | print <<"end_of_clone_sect"; 1577 |
1578 | 1579 | <<$name_of_linked_chunk>>broken_link 1580 | 1581 |
1582 | end_of_clone_sect 1583 | 1584 | next; 1585 | } 1586 | 1587 | if ($1) { # printing a single splinter LINKED_CHUNK_N of a given number 1588 | 1589 | my $splinter_cnt = (substr $1, 1); 1590 | my $virtual_id = $chunks_id_hash{$name_of_linked_chunk}[$splinter_cnt-1]; 1591 | my $created_clone_div_id = "clonebody" . $clonebody_cnt; 1592 | $clonebody_cnt++; 1593 | 1594 | my $shown_splinter_num = "(" . $splinter_cnt . ")" ; 1595 | 1596 | print_chunk_link($name_of_linked_chunk, $virtual_id, $created_clone_div_id, $shown_splinter_num); 1597 | 1598 | } 1599 | else { # regular case: printing all splinters of a LINKED_CHUNK 1600 | for (my $splinter_cnt=0; 1601 | exists $chunks_id_hash{$name_of_linked_chunk}[$splinter_cnt]; ) 1602 | { 1603 | 1604 | my $virtual_id = $chunks_id_hash{$name_of_linked_chunk}[$splinter_cnt++]; 1605 | my $created_clone_div_id = "clonebody" . $clonebody_cnt; 1606 | $clonebody_cnt++; 1607 | 1608 | my $shown_splinter_num = 1609 | "(" . $splinter_cnt . ")" 1610 | if $splinter_cnt > 1; 1611 | 1612 | print_chunk_link($name_of_linked_chunk, $virtual_id, $created_clone_div_id, $shown_splinter_num); 1613 | 1614 | 1615 | } # rof over chunk splinters 1616 | 1617 | } # fi-esle 1618 | 1619 | } # fi treatment of LINKED_CHUNKs 1620 | 1621 | 1622 | elsif ($printed_line =~ m!^(.*)\[\[FLINK\s+(.*\S)\s*\]\](.*)$!) { # --FLINKS-- 1623 | 1624 | print $1; 1625 | 1626 | unless ( exists $headings_id_hash{$2} ) { 1627 | print "$2"; 1628 | print "broken_flink
\n"; 1629 | next; 1630 | } 1631 | 1632 | my $virtual_id_ancor = $headings_id_hash{$2}; # this works with sections 1633 | my $virtual_id_ancor_href = "#" . $virtual_id_ancor; 1634 | print <<"end_of_clone_sect"; 1635 | ($virtual_id_ancor) $2flink 1638 | end_of_clone_sect 1639 | 1640 | print $3,"\n"; 1641 | 1642 | # a DEBUG printout: 1643 | #for (keys %headings_id_hash) {print "[$_] => $headings_id_hash{$_}
\n"} 1644 | #
DEBUG: trying to clone [[$2]] whose id is [$virtual_id_ancor] 1645 | #OR [$headings_id_hash{$2}] and ancor is $virtual_id_ancor_href 1646 | } # fisle - end of FLINKs 1647 | 1648 | 1649 | else{ # -- BODY OF THE DOCUMENT-- no virtual links met. Just print 1650 | print $printed_line, "\n"; 1651 | } # 1652 | } # eliwh - end of line-by-line iteration over the buffer string in memory 1653 | 1654 | 1655 | # close the page 1656 | print $html_body_table_end; 1657 | 1658 | 1659 | #--- END OF SCRIPT --- 1660 | 1661 | 1662 | exit; 1663 | 1664 | 1665 | FORESTRY: 1666 | 1667 | $shift_by_numlevels = $replant_tree || 0; 1668 | 1669 | while () { 1670 | 1671 | #~ html headings -- /change var for raw/dotHTML switching/ 1672 | s/(\s*)($tag_open\+?h)(\d+)(.*?$tag_close)(.*)($tag_open\/h)(\d+)$tag_close/ 1673 | $1 1674 | .$2.($3+$shift_by_numlevels).$4 1675 | .$5 1676 | .$6.($7+$shift_by_numlevels)."$tag_close" 1677 | /ex; 1678 | 1679 | #~ vim folds - opening 1680 | s/^(\{\{\{)(\d+)/$1.($2+$shift_by_numlevels)/e; 1681 | #~ vim folds - closing 1682 | s/^(\}\}\})(\d+)/$1.($2+$shift_by_numlevels)/e; 1683 | 1684 | print; 1685 | 1686 | } # elihw 1687 | 1688 | close LITSOURCE; 1689 | exit; 1690 | 1691 | # just in case: 1692 | exit; 1693 | 1694 | # END OF SCRIPT 1695 | 1696 | -------------------------------------------------------------------------------- /MOLLY.tangle: -------------------------------------------------------------------------------- 1 | MOLLY.weave -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | WHAT IS MOLLY? 3 | 4 | Molly, a MO-dule for LI-terate programming is a tool for enhanced Literate 5 | Programing which creates autogenerated rich "folding HTML" file out of plain 6 | raw literate source marked in the simplest and most popular "noweb" notation. 7 | Molly can generate it on the fly as you work on the file , an extra step for 8 | "weaving" docs or "tangling" code can be skipped in "Quick Mode" running 9 | under CGI. 10 | 11 | Folding HTML format, a marriage of HTML with the idea of outlining, noticeably 12 | reduces load on a programmer's memory and allows a number of techniques of source 13 | management not available before in Literate Programming, such as "virtual views" 14 | on the code, and greatly improves scalability encouraging the programmer to keep 15 | all files in one Literate Source Project file. 16 | 17 | Currently Molly includes both a weaver and a tangler and is a standalone tool 18 | in core perl. Generated folding HTML operation has been tested on Unix and 19 | Windows for Firefox and Opera. 20 | 21 | Autogeneration of rich html format with Molly can be applied to simple 22 | pre-existing html files, such as documentation or even books, and used for 23 | non-programming tasks. 24 | 25 | MOLLY also can directly use MathML (a great LGPLed third-party javascript 26 | library), i.e. mathematical expressions typed in a simple ASCII notation 27 | with LaTeX constants will be turned into MathML output to get displayed by 28 | Firefox, Opera (or other MathML-aware browsers) on the fly. 29 | 30 | 31 | CURRENT VERSION: 0.69 32 | 33 | CURRENT VERSION FEATURES: 34 | 35 | * creates folding documents on the fly from Literate Source files.. 36 | * ..based on rawHTML or dotHTML markup in document sections 37 | /i.e. either creates new docs or displays some existing HTML in folding fmt/ 38 | * and generates dynamically TOC and code chunks index; 39 | * ties collapsing/expandind of sections with TOC highlighting. 40 | * Provides pass-through tangling with "noweb" and 41 | * provides built-in fully-fledged tangler 42 | * provides a (trivial) tie to ASCIIMathML.js library for inclusion of 43 | mathematical expressions in your documents. 44 | * can tangle and weave from command line like traditiona lit prog tools 45 | * allows for the project to be split into several files or reassembled 46 | at will: the tangler can process many LitSrc files on command line. 47 | * has options to print all roots in your progect, autodetects cycles 48 | (not checked fully) 49 | * can print comments with line numbers referring to the Lit Source in 50 | the tangled output 51 | * further enhances traditional LitProg with "Virtual Views" with 52 | LINKED_CHUNKs, which are like unix soft links to code chunks 53 | from any place in your document. 54 | * improved navigation in the folding document with FLINKs, 55 | "folding hyperlinks" 56 | * "forestry" submode to move section trees in the folding document 57 | 58 | 59 | This script is a test of the concept (LitProg+folding+dynamic web formatting) 60 | 61 | 62 | FILES IN THE PROJECT: 63 | 64 | "MOLLY.html" is the extracted folding html documentation for the project. 65 | Get and read it first. Make sure JavaScript is enabled in your browser. 66 | "eeerotate.jpg" is an illustration for the file. 67 | 68 | "MOLLY.weave" is a literate source file for the project, one main project file 69 | which includes all documentation and code, tests, todo and bugs subsections etc. 70 | 71 | "MOLLY.tangle" is a link to main lit. source file, "MOLLY.weave", for Quick Mode 72 | operation. 73 | 74 | "MOLLY.pl" is the pre-extracted perl module (i.e. weaver and tangler) 75 | 76 | "ASCIIMathML.js" is an excellent LGPLed JavaScript library that enables 77 | MathML inside a weaved HTML file. If you wish to use MathML in the project, 78 | get it as well AND enable the switches in the header of your template file. 79 | 80 | "new_project_template.weave" is a skeleton file to copy and use when you 81 | start a new project. Rename it preserving the file extension (or set a new 82 | file extension in config at the top of it -- see MOLLY documentation) 83 | It can be solf-linked to another name, "new_project_template.tangle" if 84 | you also wish to tangle through MOLLY for speed during development 85 | 86 | Please, get MOLLY.html first and read it. Again, make sure JavaScript is 87 | enabled in your browser. 88 | 89 | The script is licensed under GPL version 3 90 | -------------------------------------------------------------------------------- /eeerotate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixtechie/Literate-Molly/f79f13f7908e404bff9daffbf24bd2c64d4658bb/eeerotate.jpg -------------------------------------------------------------------------------- /examples/LiterateLie.litsrc: -------------------------------------------------------------------------------- 1 | 2 | Finite dimensional Lie algebras 3 |
4 | Finite dimensional Lie algebras 5 | Anton Nazarov 6 |
7 | 8 | 9 | 10 | #---------------------------------------------- 11 | {{{2

Abstract

12 | #---------------------------------------------- 13 | 14 | We present concise introduction to the representation theory of finite-dimensional Lie algebras and illustrate it with the computational algorithms implemented in Scheme. 15 | 16 | 17 | #---------------------------------------------- 18 |

1. Introduction

19 | #---------------------------------------------- 20 | 21 | Representation theory of finite-dimensional Lie algebras is central to the study of continuous symmetries in physics. This theory is well-understood and there exist standard courses and textbooks on the subject [], [humphreys]. Nevertheless some problems of the representation theory require extensive computation and no standard textbook on the computational algorithms is known to the author of this notes. There exists a volume [], but it was written in 1970-es and have not been updated since, so its contents are limited to the early approaches and implementations on the old hardware which is unavailable now. Also some progress was made in the computational algorithms of the representation theory since the publication of []. It is important to mention series of papers by Patera et al. (see [] and references therein) and books [], [] which introduce new and optimised algorithms although do not discuss the implementations. 22 | 23 | There exist several solid implementation of the core algorithms. We want to mention Maple package Coxeter/Weyl [] and standalone programs LiE [] and LambdaTensor []. These programs are solid and rather fast but have not seen any updates in last several years. Also they are not always convenient to use since they lack graphical user interface and interoperability with the popular programming languages and mathematical programs such as Mathematica, Python or Fortran. 24 | 25 | We want to summarise some basic notions and algorithms of representation theory in order to stimulate the emergence of more modern and universal software or at least give some tools to the scientists who by some reasons can not use the existing software. 26 | 27 | Our implementation use programming language Scheme and is presented as the Literate program []. The choice of the language is due to high portability of its implementations 1, wide use of Scheme for the teaching [] and personal preferences of the author. 28 | 29 | }}}2 30 | 31 | 32 | #---------------------------------------------- 33 | {{{2

2. Lie algebras

34 | #---------------------------------------------- 35 | 36 | Definition 1: Lie algebra ``\mathfrakg`` is a linear space with the bilinear operation (eq 1) 37 |
    ``[ , ]:\mathfrak{g}\otimes \mathfrak{g}\to \mathfrak{g}``
38 | with the additional property that Jacoby identity holds (eq 2) 39 |
    40 | ``[x,[y,z]]+\text{(cyclic permutations)}=0``
41 | 42 | Lie algebras can be finite- or infinite-dimensional. Finite-dimensional Lie algebras are classified. 43 | 44 |

45 | We will represent Lie algebra in the code as the object of class lie-algebra. We use very simple class system, which is described in the Appendix . So lie-algebra is really an interface, but since our object system doesn't have interfaces we make it an abstract class and concrete classes such as semisimple-lie-algebra inherit it. 46 | Lie algebra is a vector space, so we really should create class for the vector space which contains methods for the change of basis. But for now we use only one standard basis for Lie algebras and lie-algebra is the subclass of the most genral class object. 47 | 48 | <>= 49 | (class 'lie-algebra 'object 50 | <>) 51 | @ 52 | 53 | 54 | We need to add several definitions and describe a structure of Lie algebra in order to discuss fields and methods of lie-algebra class. 55 | 56 | Definition 2: Ideal ``\mathfrak{e}\subset\mathfrak{g}: [\mathfrak{g},\mathfrak{e}]\subset \mathfrak{e}`` 57 | 58 | 59 | Definition 3: ``\mathfrakg`` is a simple Lie algebra if ``\mathfrakg`` has no proper ideal (except ``\mathfrakg`` and ``{0}``). 60 | 61 | 62 | Definition 4: A Lie algebra ``\mathfrak{g}`` is called soluble if ``\mathfrak{g}^{(n)}={0}``, where ``\mathfrak{g}^{(n)}=[\mathfrak{g}^{(n-1)},\mathfrak{g}^{(n-1)}]``. 63 | 64 | 65 | Definition 5: ``\mathfrak{g}`` is semisimple if its maximal soluble ideal ``R\subset\mathfrak{g}`` is equal to ``{0}``. 66 | 67 | Semisimple Lie algebra is a direct sum of simple Lie algebras. 68 | 69 | Since Lie algebra is a linear space, it can be specified by a set of generators ``J_a\in \mathfrak{g}`` with the commutation relations ``[J_a,J_b]=if_{ab}^cJ_c``. ``f_{ab}^c`` are called structure constants. The number of generators is equal to the dimension of Lie algebra. 70 | 71 | 72 | Now we need to discuss internal structre of Lie algebras, which can be representated with the code constructs and used for the study of algebra properties. 73 | 74 | Definition 6: Cartan subalgebra ``\mathfrak{h}\subset\mathfrak{g}`` - is the maximal commutative subalgebra of ``\mathfrak{g}``. The dimension of the Cartan subalgebra ``\mathfrak{h}`` is called rank of Lie algebra ``\mathfrak{g}``. 75 | 76 | 77 | 78 | <>= 79 | `(rank ,(lambda (self) 80 | (error "Abstract class!"))) 81 | `(dimension ,(lambda (self) 82 | (error "Abstract class!"))) 83 | `(cartan-subalgebra ,(lambda (self) 84 | (error "Abstract class!"))) 85 | 86 | @ 87 | 88 | 89 | Commutative algebras constitute first concrete class of Lie algebras. 90 | 91 | <>= 92 | (class 'commutative-algebra 'lie-algebra 93 | '(dim 1) 94 | `(rank ,(lambda (self) (send self 'dim))) 95 | `(dimension ,(lambda (self) (send self 'dim))) 96 | `(cartan-subalgebra ,(lambda (self) self))) 97 | 98 | ;; The constructor 99 | (define (make-commutative-algebra dim) 100 | (new 'commutative-algebra `(dim ,dim))) 101 | @ 102 | 103 | TODO
104 | It can be interesting and useful to add a method which show commutation relatons of the algebra in the symbolic form, but this task is left for the future 105 | 106 | }}}2 107 | 108 | #---------------------------------------------- 109 | {{{2

3. Semisimple Lie algebras

110 | #---------------------------------------------- 111 | 112 | The structure of simple and semisimple Lie algebras can be encoded by the set of simple roots. 113 | 114 | <>= 115 | (class 'semisimple-lie-algebra 'lie-algebra 116 | '(simple-roots ()) 117 | <>) 118 | ;; The constructor 119 | (define (make-semisimple-lie-algebra simple-roots) 120 | (new 'semisimple-lie-algebra `(simple-roots ,simple-roots))) 121 | 122 | @ 123 | 124 | 125 | #---------------------------------------------- 126 |

3.1. Root systems

127 | #---------------------------------------------- 128 | 129 | Definition 7: 130 | In the Cartan-Weyl basis the genrators are constructed as follows. 131 | First we choose the genrators ``H_i\in \mathfrak{h}`` of the Cartan subalgebra. All these generators commute ``[H_i,H_j]=0`` and their representations can be diagonalised simultaneously. The remaining generators ``E_{\alpha}`` are chosen to be a linear combinations of ``J_a`` such that (eq:4) 132 |
    ``[H_i,E_{\alpha}]=\alpha_i E_{\alpha}``
133 | The vector ``\alpha=(\alpha_1,\ldots,\alpha_r),\; r=rank(\mathfrak{g})`` is called a root and the corresponding operator ``E_{\alpha}`` is called ladder operator. 134 | 135 | The root ``\alpha`` maps ``H_i`` to the number ``\alpha(H_i)=\alpha_i`` hence ``\alpha\in \mathfrak{h}^{*}`` - element of the dual to the Cartan subalgebra. The set of all the roos ``\alpha`` is denoted by ``\Delta=\{\alpha,\; \alpha \text{ - root}\}``. So it is natural for the lie-algebra class to have a method which lists all the roots. 136 | 137 | <>= 138 | `(rank ,(lambda (self) 139 | (length (send self 'simple-roots)))) 140 | 141 | `(cartan-subalgebra ,(lambda (self) 142 | (make-commutative-algebra (send self 'rank)))) 143 | <> 144 | @ 145 | 146 | All the roots are the linear combinations of simple roots with the integral coefficients. There exists discrete group of symmetry called Weyl group which can be used to produce all the roots from the set of simple roots. 147 | 148 |
149 | Definition 8: 150 | Weyl group ``W`` of finite-dimension Lie algebra is a finite reflection group of ``\mathfrak{h}^*`` generated by the basic reflections corresponding to the simple roots. 151 | Each simple root ``\alpha_i`` corresponds to the reflection ``r_{i}`` in hyperplane orthogonal to ``\alpha``. (eq 5) 152 |
    ``r_{i}\lambda=\lambda-\frac{(\lambda,\alpha_i)}{(\alpha_i,\alpha_i)}\alpha_i``
153 | For ``w\in W`` there exists several equivalent realizations of the form ``w=r_{i_1}\cdot r_{i_2} \ldots r_{i_k},\; i_1 \ldots i_k=1..r``. The expression of the smallest length is called reduced. 154 | 155 | We will implement represent Weyl group elements as the lists of numbers of basic reflection (eq 6) 156 |
    ``w=r_{i_1}\cdot r_{i_2} \ldots r_{i_k} \leftrightarrow (i_1, i_2, \ldots ,i_k)``
157 | 158 | 159 | Then we will implement action of Weyl group elements on ``\mathfrak{h}^*`` using the recipies from \cite{stembridge2001computational}, \cite{casselman1994machine}, but it will be done in the future. For now we are not implementing abstract construction of Weyl group since it is enough to be able to construct Weyl group orbits of ``\mathfrak{h}^*`` elements. 160 | 161 | So we need just two following general functions: 162 | 163 | <>= 164 | (define (co-root r) 165 | (div (mul 2 r) (prod r r))) 166 | 167 | (define (reflect weight root) 168 | (sub weight (mul (prod weight (co-root root)) root))) 169 | @ 170 | 171 | Here co-root ``\alpha^{\vee}`` is the element of the dual space ``(\mathfrak{h}^*)^*`` which is identified with ``\mathfrak{h}^*\approx \mathfrak{h}`` since we have scalar product on ``\mathfrak{h}``. 172 | 173 | Now we can implement wide range of root system related methods of semisimple-lie-algebra class 174 | 175 | <>= 176 | `(simple-co-roots ,(lambda (self) 177 | (map co-root (send self 'simple-roots)))) 178 | @ 179 | 180 | 181 |

182 | Definition 9: 183 | Cartan matrix with the elements (eq 7) 184 |

    ``a_{ij}=(\alpha_i,\alpha_j^{\vee})=\frac{2(\alpha_i,\alpha_j)}{(\alpha_j,\alpha_j)}``
185 | completely determines the set of simple roots and is useful for the classification and compact description of Lie algebras. 186 | 187 | <>= 188 | `(cartan-matrix 189 | ,(lambda (self) 190 | (map (lambda (a) 191 | (map (lambda (av) (prod a av)) (send self 'simple-co-roots))) 192 | (send self 'simple-roots)))) 193 | @ 194 | 195 | 196 | We have already introduced Weyl group of reflections 3.1, now we implement procedure which constructs the union of Weyl group orbits of the set of weights. 197 | 198 | <>= 199 | `(orbit , 200 | (lambda (self weights) 201 | (let ((addon 202 | (filter (lambda (x) (not (element-of-set? x weights))) 203 | (fold-right union-set '() 204 | (map (lambda (w) 205 | (map 206 | (lambda (x) (reflect w x)) 207 | (send self 'simple-roots))) 208 | weights))))) 209 | (if (null? addon) 210 | weights 211 | (send self 'orbit (union-set weights addon) ))))) 212 | @ 213 | 214 | 215 | Definition 10: 216 | Fundamental weights form a basis ``w_1,\ldots,w_r`` dual to the basis of simple co-roots ``\alpha_1^{\vee},\ldots,\alpha_r^{\vee}``. 217 | 218 | <>= 219 | `(fundamental-weights 220 | ,(lambda (self) 221 | (map (lambda (x) 222 | (sum (map-n (lambda (y z) (mul y z)) x (send self 'simple-roots)))) 223 | (matrix-inverse (send self 'cartan-matrix))))) 224 | @ 225 | 226 | Weyl vector ``\rho=\sum_i w_i=\frac{1}{2}\sum_{\alpha\in \Delta^{+}}\alpha``. 227 | 228 | 229 | <>= 230 | `(rho ,(lambda (self) 231 | (sum (send self 'fundamental-weights)))) 232 | 233 | @ 234 | 235 | 236 | We can construct the full set of Lie algebra roots using Weyl symmetry. 237 | 238 | <>= 239 | `(roots ,(lambda (self) 240 | (send self 'orbit (send self 'simple-roots)))) 241 | @ 242 | 243 | 244 | #---------------------------------------------- 245 |

3.2. Simple Lie algebras

246 | #---------------------------------------------- 247 | 248 | Simple Lie algebras are classified by the use of Dynkin diagrams (which we will draw in the upcoming versions of this program) []. 249 | 250 |

251 | Here we explicitly construct simple roots for the classical series of finite-dimensional Lie algebras 252 | 253 | <>= 254 | (define (make-simple-lie-algebra series rank) 255 | (define (simple-roots series rank) 256 | (cond ((eq? series 'A) 257 | (do ((i 0 (+ i 1)) 258 | (base '() 259 | (cons 260 | (do ((j 0 (+ j 1)) 261 | (v '() 262 | (cons 263 | (cond ((= j i) 1) 264 | ((= j (+ i 1)) -1) 265 | (else 0)) 266 | v))) 267 | ((> j rank) (reverse v))) 268 | base))) 269 | ((= i rank) (reverse base)))) 270 | ((eq? series 'B) 271 | (do ((i 0 (+ i 1)) 272 | (base '() 273 | (cons 274 | (do ((j 0 (+ j 1)) 275 | (v '() 276 | (cons 277 | (cond ((= j i) 1) 278 | ((= j (+ i 1)) -1) 279 | (else 0)) 280 | v))) 281 | ((= j rank) (reverse v))) 282 | base))) 283 | ((= i rank) (reverse base)))) 284 | ((eq? series 'C) 285 | (do ((i 0 (+ i 1)) 286 | (base '() 287 | (cons 288 | (do ((j 0 (+ j 1)) 289 | (v '() 290 | (cons 291 | (cond ((and (= i (- rank 1)) (= i j)) 2) 292 | ((= j i) 1) 293 | ((= j (+ i 1)) -1) 294 | (else 0)) 295 | v))) 296 | ((= j rank) (reverse v))) 297 | base))) 298 | ((= i rank) (reverse base)))) 299 | ((eq? series 'D) 300 | (do ((i 0 (+ i 1)) 301 | (base '() 302 | (cons 303 | (do ((j 0 (+ j 1)) 304 | (v '() 305 | (cons 306 | (cond ((and (= i (- rank 1)) (= (- i 1) j)) 1) 307 | ((= j i) 1) 308 | ((= j (+ i 1)) -1) 309 | (else 0)) 310 | v))) 311 | ((= j rank) (reverse v))) 312 | base))) 313 | ((= i rank) (reverse base)))))) 314 | (make-semisimple-lie-algebra (simple-roots series rank))) 315 | @ 316 | 317 | }}}2 318 | 319 | #---------------------------------------------- 320 | {{{2

4. Representations

321 | #---------------------------------------------- 322 | 323 | Definition 11: 324 | Representation of Lie algebra ``\mathfrak{g}`` on a linear space ``L`` is a homomorphism ``V:\mathfrak{g}\to Aut L``. It has the property (eq 7) 325 |
    ``V([g,h])v=V(g)(V(h)v)-V(h)(V(g)v), \;\text{for}\; g,h\in \mathfrak{g};\; v\in L``
326 | 327 | There exists a classification of finite-dimensional representations of Lie algebras. 328 | 329 | For the finite-dimensional representations we introduce abstract class representation and concrete class highest-weight-representation. Then we can describe tensor product of two highest weight representations as the object of class representation (but not of class highest-weight-representation. 330 | 331 | <>= 332 | (class 'representation 'object 333 | `(dim ()) 334 | `(multiplicity , (lambda (self weight) 335 | (error "Class is abstract!"))) 336 | '(lie-algebra ()) 337 | ) 338 | @ 339 | 340 | 341 |

342 | 343 | <>= 344 | (class 'highest-weight-representation 'representation 345 | '(highest-weight ()) 346 | <> 347 | <>) 348 | `(multiplicity , (lambda (self weight) 349 | @ 350 | 351 | 352 | We use the recurrent method of calculation of weight multiplicities described in [], []. Weight multiplicities are determined using the set of anomalous points, which is constructed by the code below. 353 | 354 | <>= 355 | `(anomalous-weights , 356 | (lambda (self) 357 | (let* ((algebra (send self 'lie-algebra)) 358 | (rho (send algebra 'rho))) 359 | (map (lambda (x) 360 | (sub x rho)) 361 | (send algebra 'orbit (add (send self 'highest-weight) rho)))))) 362 | @ 363 | 364 | 365 |

366 | 367 | <>= 368 | 369 | @ 370 | 371 | }}}2 372 | 373 | #---------------------------------------------- 374 | {{{2

5. General outline of the code

375 | #---------------------------------------------- 376 | 377 | The code goes to several files of which library.scm is a compatibility layer which consists of auxiliary functions and allows portability between different Scheme implementations on different OS-es and hardware platforms. library.scm is described in the appendix . 378 | All the mathematical code which is connected with Lie theory is collected in the file lie-algebra.scm. 379 | 380 | <>= 381 | <> 382 | <> 383 | <> 384 | <> 385 | <> 386 | <> 387 | @ 388 | 389 | }}}2 390 | 391 | 392 | #---------------------------------------------- 393 | {{{2

A. Library

394 | #---------------------------------------------- 395 | 396 | Since one of our target implementations of Scheme is LispMe, which is only partially R4RS-compliant, we create compatibility layer of common functions. 397 | Also this library can be used to port the code for Lie algebras to other Scheme implementations. 398 | 399 | <>= 400 | <> 401 | <> 402 | <> 403 | <> 404 | @ 405 | 406 | 407 | #---------------------------------------------- 408 |

A.1. Commonly used Scheme procedures

409 | #---------------------------------------------- 410 | 411 | Due to the limitations of Palm OS platform functions such as map or fold-left in LispMe are in the separate library, which should be loaded by hand. Also function map accepts only 1-argument function and list, so we add these functions to our library. 412 | 413 | 414 | <>= 415 | (define nil ()) 416 | (define true #t) 417 | (define false #f) 418 | 419 | (define (zero? v) 420 | (= v 0)) 421 | 422 | (define (map op list) 423 | (if (null? list) () 424 | (cons (op (car list)) (map op (cdr list))))) 425 | 426 | (define (map-n op . lists) 427 | (define (map-n0 op lists) 428 | (if (or (null? lists) (null? (car lists))) '() 429 | (cons (apply op (map car lists)) 430 | (map-n0 op (map cdr lists))))) 431 | (map-n0 op lists)) 432 | 433 | (define (accumulate op initial sequence) 434 | (if (null? sequence) 435 | initial 436 | (op (car sequence) 437 | (accumulate op initial (cdr sequence))))) 438 | 439 | (define (filter predicate sequence) 440 | (cond ((null? sequence) ()) 441 | ((predicate (car sequence)) 442 | (cons (car sequence) 443 | (filter predicate (cdr sequence)))) 444 | (else (filter predicate (cdr sequence))))) 445 | 446 | (define (fold-left op initial sequence) 447 | (define (iter result rest) 448 | (if (null? rest) 449 | result 450 | (iter (op result (car rest)) 451 | (cdr rest)))) 452 | (iter initial sequence)) 453 | 454 | (define (fold-right op init s) (accumulate op init s)) 455 | @ 456 | 457 | We need couple of functions for sets. We represent set as list. 458 | 459 | <>= 460 | (define (element-of-set? x set) 461 | (cond ((null? set) false) 462 | ((equal? x (car set)) true) 463 | (else (element-of-set? x (cdr set))))) 464 | 465 | (define (adjoin-set x set) 466 | (if (element-of-set? x set) 467 | set 468 | (cons x set))) 469 | 470 | (define (intersection-set set1 set2) 471 | (cond ((or (null? set1) (null? set2)) '()) 472 | ((element-of-set? (car set1) set2) 473 | (cons (car set1) 474 | (intersection-set (cdr set1) set2))) 475 | (else (intersection-set (cdr set1) set2)))) 476 | 477 | (define (union-set set1 set2) 478 | (if (null? set1) set2 479 | (union-set (cdr set1) 480 | (adjoin-set (car set1) set2)) 481 | ) 482 | ) 483 | 484 | @ 485 | 486 | 487 | 488 | #---------------------------------------------- 489 |

A.2. Object system

490 | #---------------------------------------------- 491 | 492 | It is natural to represent Lie algebras, root systems and representation as objects, so we need a class system. Since standard Scheme class systems such as TinyCLOS, GOOPS, SOS can not be used on LispMe due to the lack of hygienic macros, we use the minimal class system called LispMeObjects. 493 | 494 | Here is the original documentation: 495 | 496 |
497 | . 
498 | ; Classes
499 | 
500 |  ; LispMeObjects
501 |  ; http://c2.com/cgi/wiki?LispMeObjects
502 |  ; written by Don Wells
503 |  ; Create a new class with (class name super '(slot value)... '(method function)).
504 |  ; Always use 'object as the super
505 |  ; class at the very least.
506 |  ; a function used as a method 
507 |  ; will take at least one argument 
508 |  ; self, the object that originally
509 |  ; received the method.
510 |  ; Invoke a function by sending the 
511 |  ; name and arguments to an
512 |  ; object. (e.g. (send anObject 'add 'sum 10))
513 |  ; where add is the method and sum and 10
514 |  ; are arguments)
515 |  ; Get the value of a slot by sending
516 |  ; the slot's name.
517 |  ; (e.g. (send anObject 'sum))
518 |  ; Set the value of a slot by sending
519 |  ; the set method defined on object.
520 |  ; (e.g. (send anObject 'set 'sum 20))
521 |  ; Always evaluate (clearClasses) before
522 |  ; doing anything.
523 | 
524 |  ; an object is (superName (slotname value)... (methodName closure)...)
525 |  ; a class is (className . object)
526 | 
527 | 528 | New classes are created with 529 | 530 |
531 | (class '<classname> '<superclass> (list '<fieldname> <default-value>) ...)
532 | 
533 | Instances of classes: 534 | 535 |
536 | (define <instance-name> (new '<classname> (list '<fieldname> <value>) ...))
537 | 
538 | 539 | <>= 540 | 541 | (define *classes* '()) 542 | 543 | 544 | (define (clearClasses) 545 | (set! *classes* 546 | `((object #f 547 | (set ,setSlot) 548 | (super 549 | ,(lambda (self) 550 | (getClass (car self)))))))) 551 | 552 | 553 | (define (setSlot self aSlotName aValue) 554 | (let ((slot (assoc aSlotName (cdr self)))) 555 | (cond 556 | ((not slot) 557 | (set-cdr! self 558 | (cons 559 | (list aSlotName aValue) 560 | (cdr self)))) 561 | (else 562 | (set-car! (cdr slot) aValue)))) 563 | aValue) 564 | 565 | 566 | (define (getClass aClass) 567 | (let ((class (assoc aClass *classes*))) 568 | (cond 569 | ((not class) #f) 570 | (else (cdr class))))) 571 | 572 | 573 | (define (class aName aSuperName . aDefinition) 574 | (set! *classes* 575 | (cons 576 | (cons aName (cons aSuperName aDefinition)) 577 | *classes*)) 578 | aName) 579 | 580 | 581 | (define (new aSuperName . args) 582 | (cons aSuperName args)) 583 | 584 | 585 | (define (send anObject aMessage . args) 586 | (sendWithSelf anObject anObject aMessage args)) 587 | 588 | 589 | (define (sendWithSelf self anObject aMessage args) 590 | (let 591 | ((superName (car anObject)) 592 | (slot (assoc aMessage (cdr anObject)))) 593 | (cond 594 | (slot (valueOfSlot self slot args)) 595 | ((not superName) #f) 596 | (else 597 | (let ((superClass (getClass superName))) 598 | (cond 599 | ((not superClass) #f) 600 | (else 601 | (sendWithSelf self superClass aMessage args)))))))) 602 | 603 | 604 | (define (valueOfSlot self theSlot args) 605 | (let ((value (cadr theSlot))) 606 | (cond 607 | ((procedure? value) 608 | (apply value (cons self args))) 609 | (else value)))) 610 | 611 | 612 | @ 613 | 614 | 615 | 616 | #---------------------------------------------- 617 |

A.3. Vector and matrix manipulation

618 | #---------------------------------------------- 619 | 620 | Here we have colleced simple tools for manipulation with vectors and matrices. They are important for the portability, since one of our target Scheme implementations doesn't support full R5RS-Scheme ([]) and portable Scheme libraries such as SLIB. 621 | 622 | <>= 623 | <> 624 | <> 625 | @ 626 | 627 | We represent vectors with lists since for now we don't want to have object system A.2 overhead. It can be changed in the future. 628 | 629 | <>= 630 | (define (add a b) 631 | (map-n + a b)) 632 | 633 | (define (sum list) 634 | (fold-left add (car list) (cdr list))) 635 | 636 | (define (sub a b) 637 | (map-n - a b)) 638 | 639 | (define (mul a b) 640 | (cond ((and (list? a) (number? b)) (map (lambda (x) (* x b)) a)) 641 | ((and (number? a) (list? b)) (mul b a)) 642 | ((and (number? a) (number? b)) (* a b)) 643 | (else (error "Can not multiply")))) 644 | 645 | (define (div a b) 646 | (map (lambda (x) (/ x b)) a)) 647 | 648 | (define (prod a b) 649 | (fold-left + 0 (map-n * a b))) 650 | @ 651 | 652 | For the matrix inverse and determinant we use the implementation with the cofactors extracted from the SLIB. It is not the fastest and should be replaced with the Gaussian elimination. 653 | 654 | <>= 655 | (define (matrix-cofactor mat i j) 656 | (define (butnth n lst) 657 | (if (<= n 1) 658 | (cdr lst) 659 | (cons (car lst) 660 | (butnth (+ -1 n) (cdr lst))))) 661 | (define (minor matrix i j) 662 | (map (lambda (x) 663 | (butnth j x)) 664 | (butnth i mat))) 665 | (* (if (odd? (+ i j)) -1 1) 666 | (matrix-determinant (minor mat i j)))) 667 | 668 | (define (matrix-determinant mat) 669 | (let ((n (length mat))) 670 | (if (eqv? 1 n) (caar mat) 671 | (do ((j n (+ -1 j)) 672 | (ans 0 (+ ans (* (list-ref (car mat) (+ -1 j)) 673 | (matrix-cofactor mat 1 j))))) 674 | ((<= j 0) ans))))) 675 | 676 | 677 | (define (matrix-inverse mat) 678 | (let* ((det (matrix-determinant mat)) 679 | (rank (length mat))) 680 | (and (not (zero? det)) 681 | (do ((i rank (+ -1 i)) 682 | (inv '() (cons 683 | (do ((j rank (+ -1 j)) 684 | (row '() 685 | (cons (/ (matrix-cofactor mat j i) det) row))) 686 | ((<= j 0) row)) 687 | inv))) 688 | ((<= i 0) inv))))) 689 | 690 | @ 691 | 692 | }}}2 693 | 694 | #---------------------------------------------- 695 | {{{2

Footnotes:

696 | #---------------------------------------------- 697 | 698 | 1There exist Scheme implementations for UNIX, Windows, Linux, Mac OS, Palm OS, Windows CE/Pocket PC/Windows Mobile, Java platform and even micro-controllers, see [some website] for the details 699 |
700 | 701 | }}}2 702 | 703 | -------------------------------------------------------------------------------- /examples/README-example: -------------------------------------------------------------------------------- 1 | 2 | 1. This example is a hybrid: TeX source was puth through a converter, then 3 | adjusted manually with regular expressions from Vim. 4 | Therefore all those   lines, which otherwise would not be present in 5 | literate source, only automatically inserted by Molly in the "folding html' 6 | output of its weaver. 7 | 8 | 2. I did not even download references; Molly does not have functionality to 9 | automatically number equations and definitions, or deal with foonotes or 10 | references. It might be the TeX to HTML converted could deal with refs if I 11 | included them 12 | 13 | 3. \dots in the original had to be changed to \ldots to display correctly 14 | 15 | 4. TeX escapes $....$ for math were changed to ``...`` not to conflict with 16 | other parts of the document 17 | 18 | 5. Display of some elements with the math font included with Firefox and 19 | Opera looks ugly (and is almost unreadable for some "h"-like and "h*" 20 | characters). 21 | 22 | It is possible to avoid using ASCIIMathML.js and use mimeTeX directly; it 23 | will produce images (supposedly better rendered). 24 | 25 | Multiple gif images for math formulas could be saved exactly like 26 | ASCIIMathML.js copy is saved inside the output.mht file. 27 | 28 | 29 | -------------------------------------------------------------------------------- /new_project_template.weave: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | #{{{1--------------CONFIGURATION----------------------- 4 | # -------TOC and INDEX behaviour------ 5 | 6 | # print TOC? 1:0 7 | #$print_toc=1; # default is to print 8 | 9 | # should we keep TOC expanded? "block":"none" 10 | #$toc_expanded="block"; # default is to unfold 11 | 12 | # should we keep Chunks Index expanded? "block":"none" 13 | #$ind_expanded="none"; # default is to keep folded 14 | 15 | 16 | # should we number lines in code sections? 1 : else 17 | #$line_numbering = 1; # default is to number 18 | 19 | 20 | #------------------------------------- 21 | #---------MathML options-------------- 22 | # should we enable MathML via ASCIIMathML.js or LaTeXMathML.js library? 1:0 23 | #$enable_ASCIIMathML = 0; #default is to disable as it slows down web browsers 24 | #$enable_ASCIIMathML = 1; 25 | 26 | # If yes, what is the full path to the lib? Remember to get the one with proper 27 | # escapes for your work, default or modified (see documenation) 28 | # CAN BE: (a) local "/full/path/from/root/to/ASCIIMathML_with_modified_escapes.js" or 29 | # (b) in current dir "ASCIIMathML_with_modified_escapes.js" or 30 | # (c) on the web, e.g. the original site of the library (unmodified) is: 31 | #$path_to_ASCIIMathML = "http://www1.chapman.edu/~jipsen/mathml/ASCIIMathML.js"; 32 | #$path_to_ASCIIMathML = "ASCIIMathML_with_modified_escapes.js"; # default is current dir 33 | 34 | 35 | #------------------------------------- 36 | #--------Document Markup lang--------- 37 | 38 | # how are doc sections marked? "dotHTML":"rawHTML" 39 | # $weave_markup = "rawHTML"; # default is "rawHTML" 40 | 41 | 42 | #-------------------------------------- 43 | #---------File extensions and tangling options------ 44 | 45 | # what is the file extention to weave it? (perms must allow execution!) 46 | # e.g. "scriptname.weave" or "scriptname.cgi" etc. 47 | #$weave_extension = "weave"; # default is "weave" 48 | 49 | # what is the file extention to tangle it? (perms must allow execution!) 50 | # e.g. "scriptname.tangle", "scriptname.pl" etc. 51 | #$tangle_extension = "tangle"; # default is "tangle" 52 | 53 | #When tangling, should I use the built-in tangler? 0:1 54 | # (if 0, the "pass-through" tangling will call "notangle" 55 | # from Ramsey's "noweb" tools, must be installed and in your path) 56 | # use_builtin_tangler = 0; # default for now is to use external "notangle" 57 | $use_builtin_tangler = 1; 58 | 59 | # Print LitSource's line no's as a reference in the tangled output? 60 | #$print_ref_linenos_when_tangling = 0; # default = 0, no. 61 | #$print_ref_linenos_when_tangling = 1; 62 | 63 | # ..and the comment for this line-numbering tangle-out and the language will be: 64 | #$code_sections_comment_symbol = "# "; #default is the hash-space 65 | 66 | # find and print root chunks in the LitSrc (i.e. instead of tangling when run 67 | # as "./LitSrc.tangle" from command line) ? 0:1 68 | # $show_all_roots = 0; default is not (i.e. to tangle) 69 | 70 | 71 | #-------------------------------------- 72 | #---------invocation of MOLLY.pl------- 73 | do "MOLLY.pl"; 74 | exit; 75 | __DATA__ 76 | #--------------start of script--------------------------- 77 | #-------------------------------------------------------- 78 | #-----------------------------------------------------}}}1 79 | 80 | 81 | 82 | #---------------------- 83 |

MY PROJECT

84 | #---------------------- 85 | 86 | The main idea for my new project is .. 87 | bla-bla-bla 88 | 89 | 90 | #-------------------------- 91 |

Subsection 1

92 | #-------------------------- 93 | 94 | The math formula that explains what my software 95 | is supposed to do ;)) 96 | 97 | 98 | AA x in CC (sin^2x+cos^2x=1) ---> ``AA x in CC (sin^2x+cos^2x=1)`` 99 | and one more: sum_(i=1)^n i^3=((n(n+1))/2)^2 ---> ``sum_(i=1)^n i^3=((n(n+1))/2)^2`` 100 | 101 | Next comes quadratic equation (ASCIIMathML notation): 102 | 103 | amath 104 | Example: Solving the quadratic equation. 105 | Suppose a x^2+b x+c=0 and a!=0. We first divide by \a to get x^2+b/a x+c/a=0. 106 | 107 | Then we complete the square and obtain x^2+b/a x+(b/(2a))^2-(b/(2a))^2+c/a=0. 108 | The first three terms factor to give (x+b/(2a))^2=(b^2)/(4a^2)-c/a. 109 | Now we take square roots on both sides and get x+b/(2a)=+-sqrt((b^2)/(4a^2)-c/a). 110 | 111 | Finally we move the b/(2a) to the right and simplify to get 112 | the two solutions: x_(1,2)=(-b+-sqrt(b^2-4a c))/(2a) 113 | endamath 114 | 115 | And more of math follows here (LaTeX side of the lib does not seem to 116 | understand a m a t h - e n d a m a t h tags; delimit with double backticks): 117 | 118 | ``mult(\xi)=\frac{2}{(\mu+\rho|\mu+\rho)-(\xi+\rho|\xi+\rho)}\sum_{\alpha\in\Delta^{+}} mult(\alpha) \sum_{k=1}^{\infty}mult(\xi+k\alpha)(\xi+k\alpha|\alpha)`` 119 | It includes roots ``\Delta=\left\{k\delta+\alpha|k\in Z,\; \alpha\in \Delta_0\right\}`` 120 | positive roots ``\Delta^{+}=\{k\delta+\alpha|k\geq 0,\; \alpha\in \Delta_0^{+}\}\cup \{k\delta+\alpha|k\geq 1,\; \alpha\in \Delta_0\setminus \Delta_0^{+}\}`` 121 | 122 | 123 | #-------------------------------------- 124 |

Subsection 2 - My Prog

125 | #-------------------------------------- 126 | 127 | So the program is ......... 128 | 129 | #-------------------------------------- 130 |

Subsection 3 - the code

131 | #-------------------------------------- 132 | 133 | Here I explain things that may come first 134 | 135 | 136 | <>= 137 | 138 | print STDOUT <>= 147 | Those can be out of machine order and rather be 148 | kept in their logical order in your Literate 149 | Source file 150 | 151 | end_of_it 152 | 153 | @ 154 | 155 | 156 | 157 | And this is a chunk of code (to tangle and 158 | then run, the "main" for the script): 159 | 160 | <>= 161 | #!/usr/bin/perl 162 | 163 | <> 164 | 165 | exit; 166 | @ 167 | 168 | 169 |

level 4

170 | 171 |
level 5
172 | 173 |
level 6
174 | 175 | level 7 176 | 177 | level 8 178 | 179 | level9 180 | 181 | level10 182 | 183 | level11 184 | 185 | level12 186 | 187 | 188 | #-------------------------------------- 189 |

Virtual Chunks included here

190 | #-------------------------------------- 191 | 192 | this chunk contains 2 splinters: 193 | 194 | [[LINKED_CHUNK print the explanation]] 195 | 196 | and this one is one whole piece: 197 | 198 | [[LINKED_CHUNK MyProject.pl]] 199 | 200 | Click to create clones, then delete the clones. 201 | These work exactly like soft links in unix and 202 | create "virtual views" of your code 203 | 204 | 205 | 206 | 207 | 208 | --------------------------------------------------------------------------------