diff --git a/doc/spec/03.04.expressions.tex b/doc/spec/03.04.expressions.tex index cb0e86fdc..9d042d1c3 100644 --- a/doc/spec/03.04.expressions.tex +++ b/doc/spec/03.04.expressions.tex @@ -72,8 +72,9 @@ Multiple postfixes are allowed, for example The basic form of expression is \nonterm{primary}. The simplest form of primary is an identifier or constant. Keywords \lstinline|true| and \lstinline|false| designate integer constants 1 and 0 respectively, character constant is implicitly converted into its ASCII code. String constants designate arrays -of one-byte characters. Infix constants allow to reference a functional value associated with corresponding infix operator, and functional constant (\emph{lambda-expression}) -designates an anonymous functional value in the form of closure. +of one-byte characters. Infix constants allow to reference a functional value associated with corresponding infix operator (however, a value associated with +builtin assognment operator "\lstinline|:=|" can not be taken), and functional constant (\emph{lambda-expression}) +designates an anonymous functional value in the form of closure. \begin{figure}[h] \[ diff --git a/doc/spec/04.extensions.tex b/doc/spec/04.extensions.tex index 82ac11d8d..274497681 100644 --- a/doc/spec/04.extensions.tex +++ b/doc/spec/04.extensions.tex @@ -15,7 +15,8 @@ redefinition of builtin infix operators: \begin{itemize} \item redefinitions of builtin infix operators can not be exported; -\item the assignment operator "\lstinline|:=|" can not be redefined. +\item the assignment operator "\lstinline|:=|" can not be redefined; +\item infix definitions can not be mutually recursive. \end{itemize} The syntax for infix operator definition is shown on Fig.~\ref{custom_infix_construct}; a custom infix definition must specify exactly two arguments. diff --git a/lalgol.png b/lalgol.png deleted file mode 100644 index c1eeda962..000000000 Binary files a/lalgol.png and /dev/null differ diff --git a/runtime/runtime.c b/runtime/runtime.c index 62c128909..d24f1946e 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -382,11 +382,18 @@ static void printStringBuf (char *fmt, ...) { vprintStringBuf (fmt, args); } +int is_valid_heap_pointer (void *p); + static void printValue (void *p) { data *a = (data*) BOX(NULL); int i = BOX(0); if (UNBOXED(p)) printStringBuf ("%d", UNBOX(p)); else { + if (! is_valid_heap_pointer(p)) { + printStringBuf ("0x%x", p); + return; + } + a = TO_DATA(p); switch (TAG(a->tag)) { @@ -398,7 +405,7 @@ static void printValue (void *p) { printStringBuf ("tag); i++) { if (i) printValue ((void*)((int*) a->contents)[i]); - else printStringBuf ("%x", (void*)((int*) a->contents)[i]); + else printStringBuf ("0x%x", (void*)((int*) a->contents)[i]); if (i != LEN(a->tag) - 1) printStringBuf (", "); } @@ -453,7 +460,7 @@ static void printValue (void *p) { break; default: - printStringBuf ("*** invalid tag: %x ***", TAG(a->tag)); + printStringBuf ("*** invalid tag: 0x%x ***", TAG(a->tag)); } } } @@ -494,7 +501,7 @@ static void stringcat (void *p) { break; default: - printStringBuf ("*** invalid tag: %x ***", TAG(a->tag)); + printStringBuf ("*** invalid tag: 0x%x ***", TAG(a->tag)); } } } @@ -1437,6 +1444,10 @@ static void gc_swap_spaces (void) { # define IS_FORWARD_PTR(p) \ (!UNBOXED(p) && IN_PASSIVE_SPACE(p)) +int is_valid_heap_pointer (void *p) { + return IS_VALID_HEAP_POINTER(p); +} + extern size_t * gc_copy (size_t *obj); static void copy_elements (size_t *where, size_t *from, int len) { diff --git a/tutorial/Expressions.lama b/tutorial/Expressions.lama new file mode 100644 index 000000000..78c75f2de --- /dev/null +++ b/tutorial/Expressions.lama @@ -0,0 +1,15 @@ +printf ("if, case, for, while, repeat etc. are all expressions.\n"); + +printf ("Case-expression: %s\n", case A (1, 2, 3) of A (x, y, z) -> z esac.string); + +printf ("If-expression: %s\n", if true then 2 else 3 fi + + if false then 6 else 7 fi.string); + +printf ("Scope-expression: %s\n", {local i, s = 0; + for i := 0, i < 10, i := i + 1 do + s := s + i + od; + s + }.string + ) + diff --git a/tutorial/Functions.lama b/tutorial/Functions.lama new file mode 100644 index 000000000..cdd85c549 --- /dev/null +++ b/tutorial/Functions.lama @@ -0,0 +1,7 @@ +import Fun; +import List; + +printf ("Functions are first-class, higher-order.\n"); + +printf ("Factorial: %d\n", fix (fun (f) {fun (n) {if n == 1 then 1 else n * f (n-1) fi}})(5)); +printf ("Function composition: %d\n", foldl (infix #, id, map (fun (i) {fun (x) {x+i}}, {1, 2, 3})) $ 10) diff --git a/tutorial/Hello.lama b/tutorial/Hello.lama new file mode 100644 index 000000000..3105d9ef6 --- /dev/null +++ b/tutorial/Hello.lama @@ -0,0 +1,12 @@ +printf ("Hi, this is Lama...\n"); +printf ("I can construct values of various shapes,\n"); +printf ("convert them into strings and print. Here you are:\n"); + +printf ("Regular integers: %d or even %s\n", 3, 3.string); +printf ("Lists: %s\n", {1, 2, 3}.string); +printf ("Arrays/tuples: %s\n", [1, 2, 3].string); +printf ("S-expressions: %s\n", Man ("Jonh", "Smith").string); +printf ("Functions: %s\n", fun (x, y) {x+y}.string); +printf ("These structures can be nested and heterogeneous: %s\n", {[1, "2"], Apple, fun (x) {Melon (3)}}.string); + +printf ("That's all for now, bye!\n") diff --git a/tutorial/Makefile b/tutorial/Makefile new file mode 100644 index 000000000..47df55a9c --- /dev/null +++ b/tutorial/Makefile @@ -0,0 +1,13 @@ +SHELL := /bin/bash + +FILES=$(wildcard *.lama) +ALL=$(sort $(FILES:.lama=)) +LAMAC=../src/lamac + +all: $(ALL) + +%: %.lama + $(LAMAC) $< + +clean: + rm -Rf *.s *.o *.i *~ diff --git a/tutorial/PatternMatching.lama b/tutorial/PatternMatching.lama new file mode 100644 index 000000000..51a3bda8f --- /dev/null +++ b/tutorial/PatternMatching.lama @@ -0,0 +1,54 @@ +fun show (x) { + fun show (level, x) { + for local i; i := 0, i printf ("integer %d\n", x); + return + | #array -> printf ("array\n") + | #string -> printf ("string\n") + | #sexp -> printf ("S-expression\n") + | #fun -> printf ("closure 0x%x\n", x[0]) + esac; + + for local i; i := case x of #fun -> 1 | _ -> 0 esac, i < x.length, i := i + 1 do + show (level + 2, x[i]) + od + } + + show (0, x) +} + +printf ("Pattern matching is a better way to deal with the structure of a value:\n"); +show (3); +show ([3]); +show ({1, 2}); +show (["abc", [1, fun (x) {x+1}], {3, 4}]); + +printf ("But the main designation of pattern matching is to deal with S-expressions.\n"); +printf ("You can discriminate the scrutinee on the tag:\n"); + +case E of + A -> printf ("Nope.\n") +| B -> printf ("Nope.\n") +| C -> printf ("Nope.\n") +| D -> printf ("Nope.\n") +| E -> printf ("Yes, this is E.\n") +esac; + +printf ("You can discriminate the scrutinee on the number of arguments as well:\n"); + +case A of + A (_) -> printf ("Nope.\n") +| A (_, _) -> printf ("Nope.\n") +| A -> printf ("This is A with no subvalues.\n") +| A (_, _, _) -> printf ("Nope.\n") +esac; + +printf ("You may also use composite patterns:\n"); + +case A (["x", "y", "z"], {1, 2, 3}) of + A (a@[_, _, z], _ : tl) -> printf ("a=%s, z=%s, tl=%s\n", a.string, z.string, tl.string) +esac \ No newline at end of file diff --git a/tutorial/Values.lama b/tutorial/Values.lama new file mode 100644 index 000000000..95f7a90d3 --- /dev/null +++ b/tutorial/Values.lama @@ -0,0 +1,33 @@ +local samples = [ + {"a", "b", "c"}, + "string", + [], + Fruit ("apple"), + fun (){skip} +]; + +fun show () { + -- Note: it would be much better to use iterArray from standard unit Array; + -- in that case, however, we wouldn't be able to showcase + -- for-loops and []-expressions. + for local i; i := 0, i < samples.length, i := i+1 do + printf (" %s has %d subvalue(s):\n", samples[i].string, samples[i].length); + for local j; j := 0, j < samples[i].length, j := j+1 do + printf (" subvalue [%d] = %s\n", j, samples[i][j].string) + od + od +} + +printf ("And now we look at accessing/modifying/analyzing the values.\n"); +printf ("Any composite value can be asked on the number of its immediate subvalues,\n"); +printf ("and these subvalues can be accessed:\n"); + +show (); + +printf ("And the subvalues of a composite value can be reassigned.\n"); + +samples [2] := [1, 2, 3]; +samples [0][1] := {}; + +show () +