#!/usr/bin/perl -w # Author: Paul Fitzpatrick, paulfitz@ai.mit.edu # Copyright (c) 2003 Paul Fitzpatrick # # This file is part of CosmicOS. # # CosmicOS 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 2 of the License, or # (at your option) any later version. # # CosmicOS 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 CosmicOS; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA use strict; my %token; # library of tokens (symbol sequences) used for designer's convenience. # make sure names are uniquely decodable, or put in spaces! $token{";"} = "7\n"; # end of line -- not strictly necessary $token{" "} = ""; # whitespace is ignored - no translation $token{"\n"} = ""; $token{"\r"} = ""; $token{"\t"} = ""; $token{"0"} = "0"; # zero - constant zero $token{"."} = "1"; # increment - add one $token{":"} = "2"; # double - multiply by two $token{"("} = "3"; $token{")"} = "4"; $token{"?"} = "5"; # lambda $token{"^"} = "6"; # identifier sub irand { return int(rand(shift)); }; sub prand { my $top = shift; my $crop = $top; if ($#_>=0) { $crop = shift; } my @lst = (0 .. ($top-1)); my @lst_out = (); for (my $i=$top; $i>0; $i--) { my $sel = irand($i); push(@lst_out,$lst[$sel]); if ($sel<$i-1) { $lst[$sel] = $lst[$i-1]; } } if ($crop<$top) { @lst_out = @lst_out[0 .. ($crop-1)]; } return @lst_out; }; sub Tokens2Msg { my $msg = ""; foreach my $t (@_) { if (!($t =~ /\[/)) { $msg .= $token{$t}; } } return $msg; }; my $first_high = 0; my %translate_high; my %translate_back; sub Text2Tokens { my $txt = shift; my $base = 0; my @tokens = (); $txt =~ s/\#.*//g; #$txt =~ s/\[[^\]]*\]//g; while ($txt =~ /([a-zA-Z_\+\*\-\/\=\>\<\!][a-zA-Z_\+\*\-\/\=\>\<\!0-9]*)/) { my $x = $1; my $qx = quotemeta($x); if (!defined($translate_high{$x})) { $translate_high{$x} = "^$first_high"; $translate_back{$first_high} = $x; $first_high++; } my $qy = $translate_high{$x}; $txt =~ s/$qx/$qy/; } while ($txt =~ /([1-9][0-9]*)/) { my $n = $1; my $t = ShowBinaryVerbose($n); $txt =~ s/$n/$t/; } while ($txt =~ /(\{\^([^\}]*)\})/) { my $x = $1; my $qy = $2; my $qx = quotemeta($x); $txt =~ s/$qx/$qy/g; # print "$qx -> $qy\n"; # die; } my $line = 0; #print "MESSAGE before tokenizing is:\n$txt\n"; for (my $i=0; $i=0; $i--) { my $ch = substr($txt,$i,1); if ($ch eq ":") { $x *= 2; } if ($ch eq ".") { $x += 1; } } return $x; }; sub Decompile { # decompile a message to make sure it is sane; my $txt = shift; my $src = ""; my %detoken; foreach my $k (keys %token) { $detoken{$token{$k}} = $k; } $detoken{'7'} = ";\n"; for (my $i=0; $i $detoken{$ch}\n"; } } while ($src =~ /\^([\:\.]*0)/) { my $t = $1; my $q = quotemeta($t); my $n = EvalBinary($t); my $id = $translate_back{$n}; $src =~ s/\^$q/ $id /g; } while ($src =~ /[^\:\.]([\:\.]+0)/) { my $t = $1; my $q = quotemeta($t); my $n = EvalBinary($t); $src =~ s/([^\:\.])$q/$1 $n /g; } return $src; }; sub ShowUnary { my $txt = "0"; my $ct = shift; for (my $i=0; $i<$ct; $i++) { $txt = "." . $txt; } return $txt; }; sub ShowBinary { my $txt = ""; my $i = shift; $txt .= "[$i]"; return $txt; }; sub ShowBinaryVerbose { my $txt = "0"; my $i = shift; my $val = $i; if ($i>0) { my $p = int(log($val)/log(2)); for (my $j=$p; $j>=0; $j--) { if ($j<$p) { $txt = ":" . $txt; } if ($val>=(2**$j)) { $txt = "." . $txt; $val -= (2**$j); } } } # $txt .= "[$i]"; return $txt; }; sub ShowTerm { return join(" ",@_); }; sub Paren { return "(" . ShowTerm(@_) . ")"; }; sub ShowLine { return ShowTerm(@_) . ";\n"; }; sub Op1 { my $cmp = shift; my $o1 = shift; return Paren($cmp, $o1); }; sub BareOp1 { my $cmp = shift; my $o1 = shift; return "$cmp$o1"; }; sub Op2 { my $cmp = shift; my $o1 = shift; my $o2 = shift; return Paren($cmp, $o1, $o2); }; sub Op { return Paren(@_); }; sub Lit { my $x = shift; return $x; }; sub Tag { my $x = shift; return "{$x}"; }; sub Num { my $x = shift; return "$x"; }; sub Proc { return Paren("?", @_); }; sub ProcMultiple { my $plist = shift; my @args = @$plist; my $txt = ""; foreach my $arg (@args) { $txt .= "?" . $arg; } return Paren($txt, @_); }; sub Apply { return Paren(@_); }; sub ShowUnaryLesson { my $txt = ""; $txt .= "# MATH introduce numbers (in unary notation)\n"; for (my $i=0; $i<=27; $i++) { $txt .= ShowLine(Op("intro",ShowUnary($i))); } for (my $i=27; $i>=0; $i--) { $txt .= ShowLine(Op("intro",ShowUnary($i))); } foreach my $i (0, 1, 2, 3, 5, 7, 11, 13, 17, 19, 23) { $txt .= ShowLine(Op("intro",ShowUnary($i))); } foreach my $i (0, 1, 4, 9, 16, 25) { $txt .= ShowLine(Op("intro",ShowUnary($i))); } foreach my $i (0, 1, 8, 27) { $txt .= ShowLine(Op("intro",ShowUnary($i))); } $txt .= "# MATH now show equality\n"; $txt .= ShowLine(Op("intro","=")); my @examples = prand(10,5); for (my $i=0; $i<=$#examples; $i++) { my $r = $examples[$i]; $txt .= ShowLine(Op2("=",ShowUnary($r),ShowUnary($r))); } $txt .= "# MATH now show other relational operators\n"; $txt .= ShowLine(Op("intro",">")); for (my $i=0; $i<=10; $i++) { my $r = irand(6); my $r2 = irand($r); $txt .= ShowLine(Op2(">",ShowUnary($r+1),ShowUnary($r2))); } $txt .= ShowLine(Op("intro","<")); for (my $i=0; $i<=10; $i++) { my $r = irand(6); my $r2 = irand($r); $txt .= ShowLine(Op2("<",ShowUnary($r2),ShowUnary($r+1))); } for (my $i=0; $i<=10; $i++) { my $r = irand(6); my $r2 = irand(6); my $cmp = "="; if ($r>$r2) { $cmp = ">"; } elsif ($r<$r2) { $cmp = "<"; } $txt .= ShowLine(Op2($cmp,ShowUnary($r),ShowUnary($r2))); } return $txt; }; sub ShowNotLogicLesson { my $txt = ""; $txt .= "# MATH introduce the NOT logical operator\n"; $txt .= ShowLine(Op("intro","not")); for (my $i=0; $i<=5; $i++) { my $r = irand(6); $txt .= ShowLine(Op2("=",ShowUnary($r),ShowUnary($r))); $txt .= ShowLine(Op1("not",Op2("<",ShowUnary($r),ShowUnary($r)))); $txt .= ShowLine(Op1("not",Op2(">",ShowUnary($r),ShowUnary($r)))); } for (my $i=0; $i<=5; $i++) { my $r = irand(6); my $r2 = $r+1+irand(3); $txt .= ShowLine(Op1("not",Op2("=",ShowUnary($r),ShowUnary($r2)))); $txt .= ShowLine(Op1("<",ShowUnary($r),ShowUnary($r2))); $txt .= ShowLine(Op1("not",Op2(">",ShowUnary($r),ShowUnary($r2)))); } for (my $i=0; $i<=5; $i++) { my $r = irand(6); my $r2 = $r+1+irand(3); $txt .= ShowLine(Op1("not",Op2("=",ShowUnary($r2),ShowUnary($r)))); $txt .= ShowLine(Op2(">",ShowUnary($r2),ShowUnary($r))); $txt .= ShowLine(Op1("not",Op2("<",ShowUnary($r2),ShowUnary($r)))); } return $txt; }; sub ShowTrueComparison { my $txt = ""; my $c = irand(3); if ($c==0) { my $r = irand(6); $txt .= Op2("=",ShowUnary($r),ShowUnary($r)); } elsif ($c==1) { my $r = irand(6); my $r2 = $r+1+irand(3); $txt .= Op2("<",ShowUnary($r),ShowUnary($r2)); } else { my $r = irand(6); my $r2 = $r+1+irand(3); $txt .= Op2(">",ShowUnary($r2),ShowUnary($r)); } return $txt; } sub ShowFalseComparison { my $txt = ""; my $c = irand(3); if ($c==0) { my $r = irand(6); my $r2 = irand(6); if ($r == $r2) { if(irand(2)==1) { $r++; } else { $r2++; } } $txt .= Op2("=",ShowUnary($r),ShowUnary($r2)); } else { my $r = irand(7); my $r2 = irand(7); my $cmp = ">"; if ($r>$r2) { $cmp = "<"; } else { $cmp = ">"; } $txt .= Op2($cmp,ShowUnary($r),ShowUnary($r2)); } return $txt; } sub ShowAndLogicLesson { my $txt = ""; $txt .= "# MATH introduce the AND logical operator\n"; $txt .= ShowLine(Op("intro","and")); for (my $i=0; $i<10; $i++) { $txt .= ShowLine(Op2("and",ShowTrueComparison(),ShowTrueComparison())); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op1("not", Op2("and", ShowTrueComparison(), ShowFalseComparison()))); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op1("not", Op2("and", ShowFalseComparison(), ShowTrueComparison()))); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op1("not", Op2("and", ShowFalseComparison(), ShowFalseComparison()))); } for (my $i=0; $i<10; $i++) { my $t1 = irand(2); my $t2 = irand(2); my $c1 = ""; my $c2 = ""; if ($t1==1) { $c1 = ShowTrueComparison(); } else { $c1 = ShowFalseComparison(); } if ($t2==1) { $c2 = ShowTrueComparison(); } else { $c2 = ShowFalseComparison(); } my $c = Op2("and",$c1,$c2); if (!(($t1==1)&&($t2==1))) { $c = Op1("not",$c); } $txt .= ShowLine($c); } return $txt; } sub ShowOrLogicLesson { my $txt = ""; $txt .= "# MATH introduce the OR logical operator\n"; $txt .= ShowLine(Op("intro","or")); for (my $i=0; $i<10; $i++) { $txt .= ShowLine(Op2("or",ShowTrueComparison(),ShowTrueComparison())); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op2("or",ShowTrueComparison(),ShowFalseComparison())); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op2("or",ShowFalseComparison(),ShowTrueComparison())); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op1("not", Op2("or", ShowFalseComparison(), ShowFalseComparison()))); } for (my $i=0; $i<10; $i++) { my $t1 = irand(2); my $t2 = irand(2); my $c1 = ""; my $c2 = ""; if ($t1==1) { $c1 = ShowTrueComparison(); } else { $c1 = ShowFalseComparison(); } if ($t2==1) { $c2 = ShowTrueComparison(); } else { $c2 = ShowFalseComparison(); } my $c = Op2("or",$c1,$c2); if (!(($t1==1)||($t2==1))) { $c = Op1("not",$c); } $txt .= ShowLine($c); } return $txt; } sub ShowTrueFalseLesson { my $txt = ""; $txt .= "# MATH use equality for truth values\n"; for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op2("=",ShowTrueComparison(),ShowTrueComparison())); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op2("=",ShowFalseComparison(),ShowFalseComparison())); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op1("not", Op2("=", ShowFalseComparison(), ShowTrueComparison()))); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op1("not", Op2("=", ShowTrueComparison(), ShowFalseComparison()))); } $txt .= ShowLine(Op("intro","true")); $txt .= ShowLine(Op("intro","false")); for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op2("=","true",ShowTrueComparison())); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op2("=",ShowTrueComparison(),"true")); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op2("=","false",ShowFalseComparison())); } for (my $i=0; $i<5; $i++) { $txt .= ShowLine(Op2("=",ShowFalseComparison(),"false")); } $txt .= ShowLine(Op2("=","true","true")); $txt .= ShowLine(Op2("=","false","false")); $txt .= ShowLine(Op1("not",Op2("=","true","false"))); $txt .= ShowLine(Op1("not",Op2("=","false","true"))); return $txt; }; sub ShowQuantifierLesson { my $txt = ""; $txt .= "# MATH introduce universal quantifier\n"; $txt .= "# really need to link with sets for true correctness\n"; $txt .= "# and the examples here are REALLY sparse, need much more\n"; $txt .= ShowLine(Op("intro","forall")); for (my $i=5; $i>=0; $i--) { $txt .= ShowLine(Op2("<", Num($i), Op2("+",Num($i),Num(1)))); } $txt .= ShowLine(Op("forall", Proc(Lit("x"), Op2("<", Lit("x"), Op2("+",Lit("x"),Num(1)))))); for (my $i=5; $i>=0; $i--) { my $txt0 = Op2("<", Num($i), Op2("*",Num($i),Num(2))); if (!($i<$i*2)) { $txt0 = Op1("not",$txt0); } $txt .= ShowLine($txt0); } $txt .= ShowLine(Op1("not", Op("forall", Proc(Lit("x"), Op2("<", Lit("x"), Op2("*",Lit("x"),Num(2))))))); $txt .= "# MATH introduce existential quantifier\n"; $txt .= "# really need to link with sets for true correctness\n"; $txt .= "# and the examples here are REALLY sparse, need much more\n"; for (my $i=5; $i>=0; $i--) { my $txt0 = Op2("=", Num($i), Op2("*",Num(2),Num(2))); if (!($i==2*2)) { $txt0 = Op1("not",$txt0); } $txt .= ShowLine($txt0); } $txt .= ShowLine(Op("intro","exists")); $txt .= ShowLine(Op("exists", Proc(Lit("x"), Op2("=", Lit("x"), Op2("*",Num(2),Num(2)))))); for (my $i=5; $i>=0; $i--) { my $txt0 = Op2("=", Num($i), Op2("+",Num($i),Num(2))); if (!($i==$i+1)) { $txt0 = Op1("not",$txt0); } $txt .= ShowLine($txt0); } $txt .= ShowLine(Op("not", Op("exists", Proc(Lit("x"), Op2("=", Lit("x"), Op2("+",Lit("x"),Num(2))))))); return $txt; }; sub ShowImplicationLesson { my $txt = ""; $txt .= "# MATH introduce logical implication\n"; $txt .= ShowLine(Op("intro","=>")); $txt .= ShowLine(Op2("=>","true","true")); $txt .= ShowLine(Op1("not",Op2("=>","true","false"))); $txt .= ShowLine(Op2("=>","false","true")); $txt .= ShowLine(Op2("=>","false","false")); $txt .= ShowLine(Op("forall", Lit("x"), Op("forall", Lit("y"), Op2("=>", Op2("=>", Lit("x"), Lit("y")), Op2("=>", Op1("not",Lit("y")), Op1("not",Lit("x"))))))); return $txt; }; sub ShowAdditionLesson { my $txt = ""; $txt .= "# MATH introduce addition\n"; $txt .= ShowLine(Op("intro","+")); for (my $i=0; $i<10; $i++) { my $r = irand(5); my $r2 = irand(5); $txt .= ShowLine(Op2("=", Op2("+", ShowUnary($r), ShowUnary($r2)), ShowUnary($r+$r2))); } return $txt; }; sub ShowSubtractionLesson { my $txt = ""; $txt .= "# MATH introduce subtraction\n"; $txt .= ShowLine(Op("intro","-")); for (my $i=0; $i<10; $i++) { my $r = irand(5); my $r2 = irand(5); $txt .= ShowLine(Op2("=", Op2("-", ShowUnary($r+$r2), ShowUnary($r2)), ShowUnary($r))); } return $txt; }; sub ShowMultiplicationLesson { my $txt = ""; $txt .= "# MATH introduce multiplication\n"; $txt .= ShowLine(Op("intro","*")); for (my $i=0; $i<=3; $i++) { for (my $j=0; $j<=3; $j++) { $txt .= ShowLine(Op2("=", Op2("*", ShowUnary($i), ShowUnary($j)), ShowUnary($i*$j))); } } for (my $i=0; $i<10; $i++) { my $r = irand(4); my $r2 = irand(4); $txt .= ShowLine(Op2("=", Op2("*", ShowUnary($r), ShowUnary($r2)), ShowUnary($r*$r2))); } return $txt; }; sub ShowDoubleLesson { my $txt = ""; $txt .= "# MATH introduce doubling as a special case of multiplication\n"; $txt .= "# as prelude to binary representation\n"; $txt .= ShowLine(Op("intro",":")); for (my $i=0; $i<=4; $i++) { $txt .= ShowLine(Op2("=",Op1(":",ShowUnary($i)),ShowUnary($i*2))); } for (my $i=0; $i<=4; $i++) { $txt .= ShowLine(Op2("=",ShowUnary($i*2),Op1(":",ShowUnary($i)))); } for (my $i=0; $i<=4; $i++) { $txt .= ShowLine(Op2("=", Op2("*",ShowUnary($i),ShowUnary(2)), Op1(":",ShowUnary($i)))); } for (my $i=0; $i<=4; $i++) { $txt .= ShowLine(Op2("=", BareOp1(":",ShowUnary($i)), Op1(":",ShowUnary($i)))); } return $txt; }; sub ShowBinaryLesson { my $txt = ""; $txt .= "# MATH introduce a simple form of binary notation\n"; $txt .= "# After this lesson, in the higher-level version of the message,\n"; $txt .= "# will expand decimal to stand for the binary notation given.\n"; for (my $i=0; $i<16; $i++) { $txt .= ShowLine(Op2("=",ShowUnary($i),ShowBinaryVerbose($i))); } for (my $i=0; $i<16; $i++) { my $j = irand(16); $txt .= ShowLine(Op2("=",ShowBinaryVerbose($j),ShowUnary($j))); } for (my $i=0; $i<8; $i++) { my $r = irand(16); my $r2 = irand(16); $txt .= ShowLine(Op2("=", Op2("+", ShowBinaryVerbose($r), ShowBinaryVerbose($r2)), ShowBinaryVerbose($r+$r2))); } for (my $i=0; $i<8; $i++) { my $r = irand(16); my $r2 = irand(16); $txt .= ShowLine(Op2("=", Op2("*", ShowBinaryVerbose($r), ShowBinaryVerbose($r2)), ShowBinaryVerbose($r*$r2))); } return $txt; }; sub ShowEvaluationLesson { my $txt = ""; $txt .= "# MATH demonstrate idea of leaving gaps in an expression\n"; $txt .= "# and then filling them in afterwards\n"; $txt .= "# the examples given leave a lot to be desired!\n"; for (my $i=0; $i<8; $i++) { my $r = irand(16); my $r2 = irand(16); $txt .= ShowLine(Apply(Proc(Lit("x"), Op2("=", Op2("+",Num($r),Lit("x")), Num($r+$r2))), Num($r2))); } for (my $i=0; $i<8; $i++) { my $r = irand(16); my $r2 = irand(16); $txt .= ShowLine(Apply(Apply(Proc(Lit("x"), Proc(Lit("y"), Op2("=", Op2("*", Lit("x"), Lit("y")), Num($r*$r2)))), Num($r)), Num($r2))); } for (my $i=0; $i<8; $i++) { my $r = irand(16); my $r2 = irand(16); $txt .= ShowLine(Apply(Apply(Apply(Proc(Lit("x"), Proc(Lit("y"), Proc(Lit("z"), Op2("=", Op2("*", Lit("x"), Lit("y")), Lit("z"))))), Num($r*$r2)), Num($r)), Num($r2))); } return $txt; }; sub ShowDefineFunctionLesson { my $txt = ""; $txt .= "# MATH show some simple function calls\n"; $txt .= "# and show a way to remember functions across statements\n"; for (my $i=0; $i<8; $i++) { my $r = irand(10); $txt .= ShowLine(Op2("=", Apply(Proc(Lit("square"), Apply(Lit("square"), Num($r))), Proc(Lit("x"), Op2("*", Lit("x"), Lit("x")))), Num($r*$r))); } $txt .= ShowLine(Op2("define", Lit("square"), Proc(Lit("x"), Op2("*", Lit("x"), Lit("x"))))); for (my $i=0; $i<4; $i++) { my $r = irand(10); $txt .= ShowLine(Op2("=", Apply(Lit("square"), Num($r)), Num($r*$r))); } $txt .= ShowLine(Op2("define", Lit("plusone"), Proc(Lit("x"), Op2("+", Lit("x"), Lit("1"))))); for (my $i=0; $i<4; $i++) { my $r = irand(10); $txt .= ShowLine(Op2("=", Apply(Lit("plusone"), Num($r)), Num($r+1))); } return $txt; }; sub ShowIfLesson { my $txt = ""; $txt .= "# MATH show mechanisms for branching\n"; $txt .= ShowLine(Op("intro","if")); for (my $i=0; $i<16; $i++) { my $r1 = irand(2); my $r2 = irand(10); my $r3 = irand(10); my $cmp = "true"; my $out = ""; if ($r1) { $cmp = "true"; } else { $cmp = "false"; } if ($r1) { $out .= Num($r2); } else { $out = Num($r3); } $txt .= ShowLine(Op2("=", Op("if", $cmp, Num($r2), Num($r3)), $out)); } return $txt; }; sub Factorial { my $r = 1; my $x = shift; if ($x>0) { $r = $x*Factorial($x-1); } return $r; }; sub ShowRecursionLesson { my $txt = ""; $txt .= "# MATH show an example of recursive evaluation\n"; $txt .= "# skipping over a lot of definitions and desugarings\n"; $txt .= ShowLine(Op2("define", Lit("factorial"), Proc(Lit("x"), (Op("if", Op2(">",Lit("x"),Num(0)), Op2("*", Lit("x"), Apply(Lit("factorial"), Op2("-",Lit("x"),Num(1)))), 1))))); for (my $i=0; $i<=5; $i++) { $txt .= ShowLine(Op2("=", Apply("factorial", Num($i)), Factorial($i))); } return $txt; }; sub ShowSetLesson { my $txt = ""; $txt .= "# MATH introduce sets and set membership\n"; for (my $i=0; $i<5; $i++) { my %hset; for (my $j=0; $j<6; $j++) { $hset{irand(10)} = 1; } my @set = keys %hset; for (my $j=0; $j<3; $j++) { my $mem = $set[irand($#set+1)]; $txt .= ShowLine(Op("element", Num($mem), Op("set", @set))); } } for (my $i=0; $i<5; $i++) { my %hset; for (my $j=0; $j<6; $j++) { $hset{irand(10)} = 1; } my @set = keys %hset; (my $mem, @set) = @set; $txt .= ShowLine(Op1("not", Op("element", Num($mem), Op("set", @set)))); } $txt .= ShowLine(Op2("=", Op("set", "1", "5", "9"), Op("set", "5", "1", "9"))); $txt .= ShowLine(Op2("=", Op("set", "1", "5", "9"), Op("set", "9", "1", "5"))); $txt .= ShowLine(Op1("not", Op2("=", Op("set", "1", "5", "9"), Op("set", "1", "5")))); $txt .= ShowLine(Op2("element", Num(5), Op("all", Proc(Lit("x"), Op("=", Op2("+", Lit("x"), Num(10)), Num(15)))))); $txt .= ShowLine(Op2("element", Num(3), Op("all", Proc(Lit("x"), Op("=", Op2("*", Lit("x"), Num(3)), Op2("+", Lit("x"), Num(6))))))); $txt .= ShowLine(Op("define", Lit("empty_set"), Op("set"))); $txt .= ShowLine(Op2("element", Num(0), Lit("natural_set"))); $txt .= ShowLine(Op("forall", Proc(Lit("x"), Op2("=>", Op2("element", Lit("x"), Lit("natural_set")), Op2("element", Op2("+", Lit("x"), Num(1)), Lit("natural_set")))))); for (my $i=1; $i<10; $i++) { $txt .= ShowLine(Op2("element", Num($i), Lit("natural_set"))); } $txt .= ShowLine(Op1("not", Op2("element", "true", Lit("natural_set")))); $txt .= ShowLine(Op1("not", Op2("element", "false", Lit("natural_set")))); $txt .= ShowLine(Op("define", Lit("boolean_set"), Op("set", "true", "false"))); $txt .= ShowLine(Op2("element", Lit("true"), Lit("boolean_set"))); $txt .= ShowLine(Op2("element", Lit("false"), Lit("boolean_set"))); $txt .= ShowLine(Op1("not", Op2("element", "0", Lit("boolean_set")))); $txt .= ShowLine(Op("define", Lit("even_natural_set"), Op1("all", Proc(Lit("x"), Op1("exists", Proc(Lit("y"), Op2("and", Op2("element", "y", "natural_set"), Op2("equals", Op2("*",2,"y"), "x")))))))); for (my $i=0; $i<=6; $i++) { my $txt0 = Op2("element", Num($i), Lit("even_natural_set")); if (($i%2)!=0) { $txt0 = Op1("not",$txt0); } $txt .= ShowLine(Op2("element", Num($i), Lit("natural_set"))); $txt .= ShowLine($txt0); } return $txt; }; sub ShowListLesson { my $txt = ""; $txt .= "# MATH illustrate lists and some list operators\n"; $txt .= "# still using examples rather than definition by formula -\n"; $txt .= "# could change this to reduce ambiguity, but that would create\n"; $txt .= "# more order constraints in the lessons\n"; for (my $i=0; $i<10; $i++) { my $len = irand(10)+1; my @lst = (); for (my $j=0; $j<$len; $j++) { push(@lst,irand(20)); } my ($head, @tail) = @lst; $txt .= ShowLine(Op2("=", Op1("head", Op("list", @lst)), $head)); $txt .= ShowLine(Op2("=", Op1("tail", Op("list", @lst)), Op("list", @tail))); } for (my $i=0; $i<10; $i++) { my $len = irand(10)+1; my @lst = (); for (my $j=0; $j<$len; $j++) { push(@lst,irand(20)); } my $idx = irand($len); my $val = $lst[$idx]; $txt .= ShowLine(Op2("=", Op2("list-ref", Op("list", @lst), $idx), $val)); } for (my $i=0; $i<5; $i++) { my $len = $i; my @lst = (); my $cmp = "="; for (my $j=0; $j<$len; $j++) { push(@lst,irand(20)); } my $idx = irand($len); my $val = $lst[$idx]; $txt .= ShowLine(Op2($cmp, Op("list", @lst), Op("list", @lst))); } $txt .= "# this next batch of examples are a bit misleading, should streamline\n"; for (my $i=0; $i<5; $i++) { my $len = $i; my @lst = (); my $cmp = "="; for (my $j=0; $j<$len; $j++) { push(@lst,irand(20)); } my $idx = irand($len); my $val = $lst[$idx]; $txt .= ShowLine(Op1("not", Op2($cmp, Op("list", @lst), Op("list", (irand(10), @lst))))); $txt .= ShowLine(Op1("not", Op2($cmp, Op("list", @lst), Op("list", (@lst, irand(10)))))); } $txt .= "# some helpful functions\n"; $txt .= ShowLine(Op2("define", "list-length", Proc("x", Op("if", Op2("=", "x", Op("list")), 0, Op2("+", 1, Op1("list-length", Op1("tail","x"))))))); my @examples = prand(10,5); for (my $i=0; $i<=$#examples; $i++) { my $r = $examples[$i]; $txt .= ShowLine(Op2("=", Op1("list-length", Op("list", prand(10,$r))), $r)); } $txt .= ShowLine(Op2("define", "pair", Proc("x", Proc("y", Op("list", "x", "y"))))); @examples = prand(10,3); my @examples2 = prand(10,$#examples+1); for (my $i=0; $i<=$#examples; $i++) { my $r = $examples[$i]; my $r2 = $examples2[$i]; $txt .= ShowLine(Op2("=", Op2("pair", $r, $r2), Op2("list", $r, $r2))); $txt .= ShowLine(Op2("=", Op1("first",Op2("pair", $r, $r2)), $r)); $txt .= ShowLine(Op2("=", Op1("second",Op2("pair", $r, $r2)), $r2)); } return $txt; }; sub ShowMultipleParameterLesson { my $txt = ""; $txt .= "# MATH build up functions of several variables\n"; $txt .= "# there should be nothing actually new here, if the basic\n"; $txt .= "# symbols are interpreted correctly - but this isn't obvious\n"; for (my $i=0; $i<5; $i++) { my $r2 = irand(10); my $r1 = irand(10)+$r2; $txt .= ShowLine(Op2("=", Apply(ProcMultiple(["x","y"], Op2("-","x","y")), $r1, $r2), Num($r1-$r2))); } $txt .= ShowLine(Op2("define", "apply", ProcMultiple(["x","y"], Op("if", Op2("=", "y", Op("list")), "x", Op2("apply", Apply("x", Op1("head", "y")), Op1("tail", "y")))))); for (my $i=0; $i<5; $i++) { my $r2 = irand(10); my $r1 = irand(10)+$r2; $txt .= ShowLine(Op2("=", Op2("apply", ProcMultiple(["x","y"], Op2("-","x","y")), Op("list", $r1, $r2)), Num($r1-$r2))); } return $txt; }; sub ShowHashLesson { my $txt = ""; $txt .= "# MATH introduce environment/hashmap structure\n"; $txt .= "# note that something written as {name} is just converted to a number\n"; $txt .= "# it does NOT yield an identifier\n"; $txt .= "# this section needs a LOT more examples :-)\n"; $txt .= ShowLine(Op2("define", "hash-add", ProcMultiple(["h","x","y","z"], Op("if", Op2("=","z","x"), "y", Op("h", "z"))))); $txt .= ShowLine(Op2("define", "hash-ref", ProcMultiple(["h","x"], Op("h", "x")))); $txt .= ShowLine(Op2("define", "hash-null", Proc("z","undefined"))); $txt .= ShowLine(Op2("define", "test-hash", Op("hash-add", Op("hash-add", "hash-null", 3, 2), 4, 9))); $txt .= ShowLine(Op2("=", Op("hash-ref", "test-hash", 4), 9)); $txt .= ShowLine(Op2("=", Op("hash-ref", "test-hash", 3), 2)); $txt .= ShowLine(Op2("=", Op("hash-ref", "test-hash", 8), "undefined")); $txt .= ShowLine(Op2("=", Op("hash-ref", "test-hash", 15), "undefined")); $txt .= ShowLine(Op2("=", Op("hash-ref", Op("hash-add", "test-hash", 15, 33), 15), 33)); $txt .= ShowLine(Op2("=", Op("hash-ref", "test-hash", 15), "undefined")); $txt .= ShowLine(Op2("define", "make-hash", Proc("x", Op2("=","x",Op("list")), "hash-null", Op("hash-add", Op("make-hash", Op1("tail", "x")), Op1("first",Op1("head","x")), Op1("second",Op1("head","x")))))); $txt .= ShowLine(Op2("=", Op2("hash-ref", Op1("make-hash", Op("list", Op2("pair", 3, 10), Op2("pair", 2, 20), Op2("pair", 1, 30))), 3), 10)); $txt .= ShowLine(Op2("=", Op2("hash-ref", Op1("make-hash", Op("list", Op2("pair", 3, 10), Op2("pair", 2, 20), Op2("pair", 1, 30))), 1), 30)); return $txt; }; sub ShowMutableLesson { my $txt = ""; $txt .= "# MATH introduce mutable objects, and side-effects\n"; $txt .= ShowLine(Op("intro","make-cell")); $txt .= ShowLine(Op("intro","set!")); $txt .= ShowLine(Op("intro","get!")); $txt .= ShowLine(Op("define", "demo-mut1", Op("make-cell", 0))); $txt .= ShowLine(Op2("set!", "demo-mut1", 15)); $txt .= ShowLine(Op2("=", Op1("get!", "demo-mut1"), 15)); $txt .= ShowLine(Op2("set!", "demo-mut1", 5)); $txt .= ShowLine(Op2("set!", "demo-mut1", 7)); $txt .= ShowLine(Op2("=", Op1("get!", "demo-mut1"), 7)); $txt .= ShowLine(Op("define", "demo-mut2", Op("make-cell", 11))); $txt .= ShowLine(Op2("=", Op1("get!", "demo-mut2"), 11)); $txt .= ShowLine(Op2("set!", "demo-mut2", 22)); $txt .= ShowLine(Op2("=", Op1("get!", "demo-mut2"), 22)); $txt .= ShowLine(Op2("=", Op1("get!", "demo-mut1"), 7)); $txt .= ShowLine(Op2("=", Op2("+", Op1("get!", "demo-mut1"), Op1("get!", "demo-mut2")), 29)); $txt .= ShowLine(Op("if", Op("=", Op1("get!", "demo-mut1"), 7), Op2("set!", "demo-mut1", 88), Op2("set!", "demo-mut1", 99))); $txt .= ShowLine(Op2("=", Op1("get!", "demo-mut1"), 88)); $txt .= ShowLine(Op("if", Op("=", Op1("get!", "demo-mut1"), 7), Op2("set!", "demo-mut1", 88), Op2("set!", "demo-mut1", 99))); $txt .= ShowLine(Op2("=", Op1("get!", "demo-mut1"), 99)); return $txt; }; sub ShowGraphLesson { my $txt = ""; $txt .= "#MATH introduce simple graph structures\n"; return $txt; }; sub ShowMUDLesson { my $txt = ""; $txt .= "# MUD under development\n"; $txt .= "# need a lot more structure/record/object abstractions\n"; $txt .= "# adding these to MATH section...\n"; $txt .= "# currently just use this section to play around\n"; $txt .= ShowLine(Op("intro","reflect")); $txt .= ShowLine(Op2("define", "reflect", Proc("x", Apply("x", "x")))); # $txt .= ShowLine(Op("define", # "Point2D", return $txt; }; # generate message # use consistent random choices # (really not acceptable to use random numbers, should use # look-up tables on a per lesson basis, to ensure stability # of sequences within lessons) srand(1); my $txt = ""; $txt .= "# Author: Paul Fitzpatrick, paulfitz\@ai.mit.edu # Copyright (c) 2003 Paul Fitzpatrick # # This file is part of CosmicOS. # # CosmicOS 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 2 of the License, or # (at your option) any later version. # # CosmicOS 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 CosmicOS; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # "; $txt .= ShowUnaryLesson(); $txt .= ShowNotLogicLesson(); $txt .= ShowAndLogicLesson(); $txt .= ShowOrLogicLesson(); $txt .= ShowTrueFalseLesson(); $txt .= ShowAdditionLesson(); $txt .= ShowSubtractionLesson(); $txt .= ShowMultiplicationLesson(); $txt .= ShowDoubleLesson(); $txt .= ShowBinaryLesson(); $txt .= ShowEvaluationLesson(); $txt .= ShowDefineFunctionLesson(); $txt .= ShowIfLesson(); $txt .= ShowRecursionLesson(); $txt .= ShowQuantifierLesson(); $txt .= ShowImplicationLesson(); $txt .= ShowSetLesson(); $txt .= ShowListLesson(); $txt .= ShowMultipleParameterLesson(); $txt .= ShowHashLesson(); $txt .= ShowMutableLesson(); $txt .= ShowMUDLesson(); # Establish some terms which will have a fairly short representation. # Identifying numbers are allocated on a first come first served basis. Text2Tokens("intro = < > not and or true false x y z => exists forall cell set get if <= >="); my $msg = Tokens2Msg(Text2Tokens($txt)); $msg =~ s/\n//g; $msg =~ s/([a-z0-9]{80})/$1\n*** /g; print "*** $msg\n"; print "$txt\n\n"; # can call Decompile to make sure everything is getting put in # the final message #print Decompile($msg);