Added tutorial

This commit is contained in:
Dmitry Boulytchev 2020-02-19 15:28:29 +03:00
parent b7271d167a
commit b0e5bc26e3
10 changed files with 153 additions and 6 deletions

View file

@ -72,7 +72,8 @@ 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| 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 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}) 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. designates an anonymous functional value in the form of closure.
\begin{figure}[h] \begin{figure}[h]

View file

@ -15,7 +15,8 @@ redefinition of builtin infix operators:
\begin{itemize} \begin{itemize}
\item redefinitions of builtin infix operators can not be exported; \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} \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. The syntax for infix operator definition is shown on Fig.~\ref{custom_infix_construct}; a custom infix definition must specify exactly two arguments.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 636 B

View file

@ -382,11 +382,18 @@ static void printStringBuf (char *fmt, ...) {
vprintStringBuf (fmt, args); vprintStringBuf (fmt, args);
} }
int is_valid_heap_pointer (void *p);
static void printValue (void *p) { static void printValue (void *p) {
data *a = (data*) BOX(NULL); data *a = (data*) BOX(NULL);
int i = BOX(0); int i = BOX(0);
if (UNBOXED(p)) printStringBuf ("%d", UNBOX(p)); if (UNBOXED(p)) printStringBuf ("%d", UNBOX(p));
else { else {
if (! is_valid_heap_pointer(p)) {
printStringBuf ("0x%x", p);
return;
}
a = TO_DATA(p); a = TO_DATA(p);
switch (TAG(a->tag)) { switch (TAG(a->tag)) {
@ -398,7 +405,7 @@ static void printValue (void *p) {
printStringBuf ("<closure "); printStringBuf ("<closure ");
for (i = 0; i < LEN(a->tag); i++) { for (i = 0; i < LEN(a->tag); i++) {
if (i) printValue ((void*)((int*) a->contents)[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 (", "); if (i != LEN(a->tag) - 1) printStringBuf (", ");
} }
@ -453,7 +460,7 @@ static void printValue (void *p) {
break; break;
default: 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; break;
default: 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) \ # define IS_FORWARD_PTR(p) \
(!UNBOXED(p) && IN_PASSIVE_SPACE(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); extern size_t * gc_copy (size_t *obj);
static void copy_elements (size_t *where, size_t *from, int len) { static void copy_elements (size_t *where, size_t *from, int len) {

15
tutorial/Expressions.lama Normal file
View file

@ -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
)

7
tutorial/Functions.lama Normal file
View file

@ -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)

12
tutorial/Hello.lama Normal file
View file

@ -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")

13
tutorial/Makefile Normal file
View file

@ -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 *~

View file

@ -0,0 +1,54 @@
fun show (x) {
fun show (level, x) {
for local i; i := 0, i<level, i := i + 1 do
printf (" ")
od;
case x of
#unboxed -> 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

33
tutorial/Values.lama Normal file
View file

@ -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 ()