# -*- mode: Perl -*- # /=====================================================================\ # # | proof.sty | # # | Implementation for LaTeXML | # # |=====================================================================| # # | Part of LaTeXML: | # # | Public domain software, produced as part of work done by the | # # | United States Government & not subject to copyright in the US. | # # |---------------------------------------------------------------------| # # | Bruce Miller #_# | # # | http://dlmf.nist.gov/LaTeXML/ (o o) | # # \=========================================================ooo==U==ooo=/ # package LaTeXML::Package::Pool; use strict; use warnings; use LaTeXML::Package; # The premises can be separated by "&" (which is NOT being used for alignment!) DefMath('\lx@proof@logical@and', "\x{2003}", meaning => 'and', role => 'ADDOP'); DefMacro('\lx@proof@split@and{}', sub { my ($gullet, $tokens) = @_; my @clauses = SplitTokens($tokens, T_ALIGN); if (!@clauses) { return; } elsif (scalar(@clauses) == 1) { return Tokens(@{ $clauses[0] }); } else { return I_apply(undef, T_CS('\lx@proof@logical@and'), map { Tokens(@$_); } @clauses); } }); # An extremely contrived stack of premises and conclusion. # The mess is since they can be separated by a single or double bar, or \vdots or even a label # the bars should be stretched to the full width. # The label can also be to the side. # Args are $top, $middle (if any), $bottom, $sidelabel (if any) DefConstructor('\lx@proof@stack{}{}{}{}', "" . "#1" . "?#4(#4)()" # Should vertically center . "" . "?#2(#2)()" . "#3" . "" . "", afterDigest => sub { my ($doc, $whatsit) = @_; my ($top, $op, $bot) = $whatsit->getArgs; if ($top->getWidth->valueOf > $bot->getWidth->valueOf) { $bot->setProperty(stretchto => $top->getWidth); } return; }); # Put 1 or 2 bars over the conclusion (possibly stretched) DefConstructor('\lx@proof@bars OptionalMatch:= {}', "\x{203E}" . "?#1(\x{203E})()" . "#2" . "?#1()()" . ""); # \infer (* or =) [label] {lower}{uppers} DefMacro('\infer OptionalMatch:* OptionalMatch:= [] {}{}', sub { my ($gullet, $multistep, $double, $label, $lower, $uppers) = @_; my $meaning = ($multistep ? "multistep-infer" : "infer"); my $cmd = I_dual({}, I_apply({}, I_symbol({ meaning => $meaning }), I_arg(1), I_arg(2)), ($multistep ? Invocation(T_CS('\lx@proof@stack'), I_arg(2), T_CS('\vdots'), I_arg(1), I_arg(3)) : Invocation(T_CS('\lx@proof@stack'), I_arg(2), undef, Invocation(T_CS('\lx@proof@bars'), $double, I_arg(1)), I_arg(3))), $lower, Invocation(T_CS('\lx@proof@split@and'), $uppers), $label); return Tokens(T_CS('\ensuremath'), T_BEGIN, $cmd, T_END); }); # Similar, no bars, label (if any) replaces the bars DefMacro('\deduce [] {}{}', sub { my ($gullet, $label, $lower, $uppers) = @_; my $meaning = "deduce"; my $cmd = I_dual({}, I_apply({}, I_symbol({ meaning => $meaning }), I_arg(1), I_arg(2)), Invocation(T_CS('\lx@proof@stack'), I_arg(2), $label, I_arg(1)), $lower, Invocation(T_CS('\lx@proof@split@and'), $uppers)); return Tokens(T_CS('\ensuremath'), T_BEGIN, $cmd, T_END); }); 1;