changeset 1497:0b639858200b

Tutorial tweaks
author Adam Chlipala <adam@chlipala.net>
date Fri, 15 Jul 2011 18:45:03 -0400
parents 3010472edf44
children 8c32c7191bf0
files doc/intro.ur src/elisp/urweb-mode.el src/tutorial.sml
diffstat 3 files changed, 90 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/doc/intro.ur	Fri Jul 15 17:31:57 2011 -0400
+++ b/doc/intro.ur	Fri Jul 15 18:45:03 2011 -0400
@@ -1,15 +1,75 @@
 (* Introduction *)
 
-(* This tutorial is licensed under a <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/">Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License</a>. *)
+(* begin hide *)
+val show_string = mkShow (fn s => "\"" ^ s ^ "\"")
+(* end *)
 
-(* Test evaluation.... *)
+(* This tutorial by <a href="http://adam.chlipala.net/">Adam Chlipala</a> is licensed under a <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/">Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License</a>. *)
 
-fun f [a] (x : a) : a = x
+(* This is a tutorial for the <a href="http://www.impredicative.com/ur/">Ur/Web</a> programming language.  The <a href="http://www.impredicative.com/ur/">official project web site</a> is your starting point for information, like a reference manual and where to download the latest code release.  In this tutorial, we'll just focus on introducing the language features. *)
+
+(* Ur/Web contains a web-indendent core language called Ur, which will be the subject of the first few chapters of the tutorial.  Ur inherits its foundation from ML and Haskell, then going further to add fancier stuff.  This first chapter of the tutorial reviews the key ML and Haskell features, giving their syntax in Ur. *)
+
+(* * Basics *)
+
+(* Let's start with features shared with both ML and Haskell.  First, we have the basic numeric, string, and Boolean stuff.  (In the following examples, "==" is used to indicate the result of evaluating an expression.  It's not valid Ur syntax!) *)
 
 (* begin eval *)
-f 6
+1 + 1
 (* end *)
 
-(** Section *)
+(* begin eval *)
+1.2 + 3.4
+(* end *)
 
-val y = 9
+(* begin eval *)
+"Hello " ^ "world!"
+(* end *)
+
+(* begin eval *)
+1 + 1 < 6
+(* end *)
+
+(* begin eval *)
+0.0 < -3.2
+(* end *)
+
+(* begin eval *)
+"Hello" = "Goodbye" || (1 * 2 <> 8 && True <> False)
+(* end *)
+
+(* We also have function definitions with type inference for parameter and return types. *)
+
+fun double n = 2 * n
+
+(* begin eval *)
+double 8
+(* end *)
+
+fun fact n = if n = 0 then 1 else n * fact (n - 1)
+
+(* begin eval *)
+fact 5
+(* end *)
+
+(* Of course we have anonymous functions, too. *)
+
+val inc = fn x => x + 1
+
+(* begin eval *)
+inc 3
+(* end *)
+
+(* Then there's parametric polymorphism.  Unlike in ML and Haskell, polymorphic functions in Ur/Web often require full type annotations.  That is because more advanced features (which we'll get to in the next chapter) make Ur type inference undecidable. *)
+
+fun id [a] (x : a) : a = x
+
+(* begin eval *)
+id "hi"
+(* end *)
+
+fun compose [a] [b] [c] (f : b -> c) (g : a -> b) (x : a) : c = f (g x)
+
+(* begin eval *)
+compose inc inc 3
+(* end *)
--- a/src/elisp/urweb-mode.el	Fri Jul 15 17:31:57 2011 -0400
+++ b/src/elisp/urweb-mode.el	Fri Jul 15 18:45:03 2011 -0400
@@ -181,13 +181,11 @@
          ((save-excursion (backward-char 1) (or (looking-at "=>")
                                                 (looking-at "->")
                                                 (looking-at "<>")))
-          nil)
+          (setq finished t))
          ((or (looking-at "< ") (looking-at "<="))
           nil)
          ((looking-at "<")
           (setq finished t))
-         ((save-excursion (backward-char 1) (looking-at " >"))
-          nil)
          ((looking-at ">")
           (cond
            ((> depth 0)
--- a/src/tutorial.sml	Fri Jul 15 17:31:57 2011 -0400
+++ b/src/tutorial.sml	Fri Jul 15 18:45:03 2011 -0400
@@ -54,10 +54,10 @@
             in
                 if Substring.isEmpty after then
                     TextIO.outputSubstr (outf, source)
-                else if Substring.size after >= 8 andalso Substring.string (Substring.slice (after, 1, SOME 7)) = "amp;lt;" then
+                else if Substring.size after >= 4 andalso Substring.string (Substring.slice (after, 1, SOME 3)) = "lt;" then
                     (TextIO.outputSubstr (outf, befor);
                      TextIO.output (outf, "<");
-                     proseLoop (Substring.slice (after, 8, NONE)))
+                     proseLoop (Substring.slice (after, 4, NONE)))
                 else if Substring.size after >= 4 andalso Substring.string (Substring.slice (after, 1, SOME 3)) = "gt;" then
                     (TextIO.outputSubstr (outf, befor);
                      TextIO.output (outf, ">");
@@ -75,26 +75,7 @@
                 val (befor, after) = Substring.position "<span class=\"comment-delimiter\">(* </span><span class=\"comment\">" source
             in
                 if Substring.isEmpty after then
-                    let
-                        val (befor, after) = Substring.position "<span class=\"comment-delimiter\">(** </span><span class=\"comment\">" source
-                    in
-                        if Substring.isEmpty after then
-                            TextIO.outputSubstr (outf, source)
-                        else
-                            let
-                                val (befor', after) = Substring.position " </span><span class=\"comment-delimiter\">*)</span>"
-                                                                         (Substring.slice (after, 65, NONE))
-                            in
-                                if Substring.isEmpty after then
-                                    TextIO.outputSubstr (outf, source)
-                                else
-                                    (TextIO.outputSubstr (outf, befor);
-                                     TextIO.output (outf, "<h2>");
-                                     proseLoop befor';
-                                     TextIO.output (outf, "</h2>");
-                                     loop (Substring.slice (after, 49, NONE)))
-                            end
-                    end
+                   TextIO.outputSubstr (outf, source)
                 else
                     let
                         val (befor', after) = Substring.position " </span><span class=\"comment-delimiter\">*)</span>"
@@ -104,9 +85,16 @@
                             TextIO.outputSubstr (outf, source)
                         else
                             (TextIO.outputSubstr (outf, befor);
-                             TextIO.output (outf, "<div class=\"prose\">");
-                             proseLoop befor';
-                             TextIO.output (outf, "</div>");
+                             TextIO.output (outf, "</pre>");
+                             if Substring.size befor' >= 1 andalso Substring.sub (befor', 0) = #"*" then
+                                 (TextIO.output (outf, "<h2>");
+                                  proseLoop (Substring.slice (befor', 2, NONE));
+                                  TextIO.output (outf, "</h2>"))
+                             else
+                                 (TextIO.output (outf, "<div class=\"prose\">");
+                                  proseLoop befor';
+                                  TextIO.output (outf, "</div>"));
+                             TextIO.output (outf, "<pre>");
                              loop (Substring.slice (after, 49, NONE)))
                     end
             end
@@ -130,6 +118,14 @@
              TextIO.output (outf, "\t\tbackground-color: #99FF99;\n");
              TextIO.output (outf, "\t\tpadding: 5px;\n");
              TextIO.output (outf, "\t}\n");
+             TextIO.output (outf, "\ta:link {\n");
+             TextIO.output (outf, "\t\ttext-decoration: underline;\n");
+             TextIO.output (outf, "\t\tcolor: blue;\n");
+             TextIO.output (outf, "\t}\n");
+             TextIO.output (outf, "\ta:visited {\n");
+             TextIO.output (outf, "\t\ttext-decoration: underline;\n");
+             TextIO.output (outf, "\t\tcolor: red;\n");
+             TextIO.output (outf, "\t}\n");
              TextIO.output (outf, "-->\n");
              TextIO.output (outf, "</style>\n");
              TextIO.output (outf, "<title>");
@@ -287,13 +283,14 @@
                                           ^ "/\\\") "
                                           ^ "(load \\\"urweb-mode-startup\\\") "
                                           ^ "(urweb-mode) "
-                                          ^ "(find-file \\\"/tmp/final.ur\\\") "
+                                          ^ "(find-file \\\"/tmp/final2.ur\\\") "
                                           ^ "(switch-to-buffer (htmlize-buffer)) "
                                           ^ "(write-file \\\"/tmp/final.html\\\") "
                                           ^ "(kill-emacs))\""
                             in
                                 eatNls befor;
                                 TextIO.closeOut outf;
+                                ignore (OS.Process.system "sed -e 's/&lt;/</g;s/&amp;/\\&/g' </tmp/final.ur >/tmp/final2.ur");
                                 ignore (OS.Process.system cmd);
                                 fixupFile (fname, title)
                             end