diff --git a/lama-spec.pdf b/lama-spec.pdf index 46874c8e7..98ea3fa3e 100644 Binary files a/lama-spec.pdf and b/lama-spec.pdf differ diff --git a/runtime/runtime.c b/runtime/runtime.c index 7dc479224..45fde2475 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -1512,7 +1512,7 @@ extern void __gc_root_scan_stack (); /* ======================================== */ //static size_t SPACE_SIZE = 16; -static size_t SPACE_SIZE = 64 * 1024 * 1024; +static size_t SPACE_SIZE = 256 * 1024 * 1024; // static size_t SPACE_SIZE = 128; // static size_t SPACE_SIZE = 1024 * 1024; diff --git a/spec/06.standard_library.tex b/spec/06.standard_library.tex index 6d0f51ef2..3bf2dd7a5 100644 --- a/spec/06.standard_library.tex +++ b/spec/06.standard_library.tex @@ -94,6 +94,45 @@ program start time.} \descr{\lstinline|fun time ()|}{Returns the elapsed time from program start in microseconds.} +\section{Unit \texttt{Data}} +\label{sec:data} + +Generic data manupulation. + +\descr{\lstinline|infix =?= at < (x, y)|}{A generic comparison operator similar to \lstinline|compare|, but capable of handling cyclic/shared data structures.} +\descr{\lstinline|infix === at == (x, y)|}{A generic equality operator capable of handling cyclic/shared data structures.} + +\section{Unit \texttt{Random}} +\label{sec:random} + +Random data structures generation functions. + +\descr{\lstinline|fun randomInt ()|}{Generates a random representable integer value.} + +\descr{\lstinline|fun randomString (len)|}{Generates a random string of printable ASCII characters of given length.} + +\descr{\lstinline|fun randomArray (f, n)|}{Generates a random array of \emph{deep} size \lstinline|n|. The length of the array is chosen randomly, and \lstinline|f| is intended to be an element-generating function which takes the size of the element as an argument.} + +\descr{\lstinline|fun split (n, k)|}{Splits a non-negative integer \lstinline|n| in \lstinline|k| random summands. Returns an array if length \lstinline|k|. \lstinline|k| has to be non-negative.} + +\newsavebox\strubox + +\begin{lrbox}{\strubox} +\begin{lstlisting} + structure (100, + [[2, fun ([x, y]) {Add (x, y)}], + [2, fun ([x, y]) {Sub (x, y)}]], + fun () {Const (randomInt ())} + ) +\end{lstlisting} +\end{lrbox} + +\descr{\lstinline|fun structure (n, nodeSpec, leaf)|}{Generates a random tree-shaped data structure of size \lstinline|n|. \lstinline|nodeSpec| is an array of pairs \lstinline|[$k$, $f_k$]|, where $k$ is a non-negative integer and $f_k$ is a function which takes an array of length $k$ as its argument. Each pair describes a generator of a certain kind of interior node with degree $k$. \lstinline|leaf| is a zero-argument function which generates the leaves of the tree. For example, the following code + +\usebox\strubox + +can be used to generate a random arithmetic expression of size 100.} + \section{Unit \texttt{Array}} \label{sec:array} @@ -308,6 +347,27 @@ fresh list if images in the same order.} \descr{\lstinline|fun filter (f, l)|}{Removes all values, not satisfying the predicate "\lstinline|f|", from the list "\lstinline|l|". The function "\lstinline|f|" should return integers, treated as booleans.} +\section{Unit \texttt{Buffer}} +\label{sec:std:buffer} + +Mutable buffers. + +\descr{\lstinline|fun emptyBuffer ()|}{Creates an empty buffer.} + +\descr{\lstinline|fun singletonBuffer (x)|}{Creates a buffer from a single element.} + +\descr{\lstinline|fun listBuffer (x)|}{Creates a buffer from a list.} + +\descr{\lstinline|fun getBuffer (buf)|}{Gets the contents of a buffer as a list.} + +\descr{\lstinline|fun addBuffer (buf, x)|}{Adds an element \lstinline|x| to the end of buffer \lstinline|buf| and returns the updated buffer. The buffer \lstinline|buf| can be updated in-place.} + +\descr{\lstinline|fun concatBuffer (buf, x)|}{Adds buffer \lstinline|x| to the end of buffer \lstinline|buf| and returns the updated buffer. The buffer \lstinline|buf| can be updated in-place.} + +\descr{\lstinline|infixl <+> before + (b1, b2)|}{Infix synonym for \lstinline|concatBuffer|.} + +\descr{\lstinline|infix <+ at <+> (b, x)|}{Infix synonym for \lstinline|addBuffer|.} + \section{Unit \texttt{Matcher}} The unit provides some primitives for matching strings against regular patterns. Matchers are immutable structures which store diff --git a/src/version.ml b/src/version.ml index 86effb8bc..a234ecfdc 100644 --- a/src/version.ml +++ b/src/version.ml @@ -1 +1 @@ -let version = "Version 1.00, 6f9d0850c, Fri Aug 7 21:40:51 2020 +0300" +let version = "Version 1.00, 94e4b1626, Mon Aug 10 20:55:10 2020 +0300" diff --git a/stdlib/Buffer.lama b/stdlib/Buffer.lama new file mode 100644 index 000000000..4e19e9c93 --- /dev/null +++ b/stdlib/Buffer.lama @@ -0,0 +1,66 @@ +-- Buffer. +-- (C) Dmitry Boulytchev, JetBrains Research, St. Petersburg State University, 2020 +-- +-- This unit provides a simple add-to-the-end buffer implemetation. + +import List; + +-- Creates an empty buffer +public fun emptyBuffer () { + {} +} + +-- Creates a buffer with one element x +public fun singletonBuffer (x) { + local y = singleton (x); + + [y, y] +} + +-- Creates a buffer from a list x +public fun listBuffer (x) { + foldl (addBuffer, emptyBuffer (), x) +} + +-- Adds x to the end of buffer buf +public fun addBuffer (buf, x) { + case buf of + {} -> local y = singleton (x); + [y, y] + | [head, last] -> + last[1] := singleton (x); + [head, last[1]] + esac +} + +-- Adds the contents of buffer x to the end of buffer buf +public fun concatBuffer (buf, x) { + case buf of + {} -> x + | [head, last] -> + case x of + {} -> buf + | [h, l] -> + last[1] := h; + [head, l] + esac + esac +} + +-- Infix synonym for concatBuffer +public infixl <+> before + (b1, b2) { + concatBuffer (b1, b2) +} + +-- Infix synonym for addBuffer +public infix <+ at <+> (b, x) { + addBuffer (b, x) +} + +-- Gets the contents of the buffer buf (as a list) +public fun getBuffer (buf) { + case buf of + {} -> {} + | [head, _] -> head + esac +} diff --git a/stdlib/List.lama b/stdlib/List.lama index c2dc5143f..4ed5f856e 100644 --- a/stdlib/List.lama +++ b/stdlib/List.lama @@ -79,12 +79,20 @@ public fun flatten (l) { fun append (x) { local new = x : {}; - + curr [0][1] := new; curr [0] := new } + + fun traverse (l) { + case l of + _ : _ -> iter (traverse, l) + | {} -> skip + | _ -> append (l) + esac + } - iter (fun (x) {iter (append, x)}, l); + traverse (l); res [1] } diff --git a/stdlib/Makefile b/stdlib/Makefile index 69403a61e..e6ce887f0 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -16,6 +16,8 @@ Array.o: List.o Ostap.o: List.o Collection.o Ref.o Fun.o Matcher.o +Buffer.o: List.o + Expr.o: Ostap.o %.o: %.lama diff --git a/stdlib/Random.lama b/stdlib/Random.lama index a6d325fea..257f4683c 100644 --- a/stdlib/Random.lama +++ b/stdlib/Random.lama @@ -28,13 +28,12 @@ public fun randomString (len) { -- Generates a random array of (deep) size n. f is element-generation -- function which takes the size of the element public fun randomArray (f, n) { - mapArray (f, split (n)) + mapArray (f, split (n, random (n + 1))) } --- Splits a number in a random sequence of summands -public fun split (n) { - local k = random (n) + 1, - a = makeArray (k), +-- Splits a number n in a random sequence of k summands +public fun split (n, k) { + local a = makeArray (k), m = n; for local i = 0;, i < k, i := i + 1 @@ -49,3 +48,22 @@ public fun split (n) { a } + +-- Generates a (recursive) data structure of size n. nodeSpec is an array of pairs [n, fn] where +-- fn gets an array of values of length n and generates some node; leaf is a fucntion without +-- arguments which create a leaf. +public fun structure (n, nodeSpec, leaf) { + local k = nodeSpec.length; + + fun rec (n) { + if n <= 1 + then leaf () + else + local ns = nodeSpec [random (k)]; + + ns [1] (mapArray (rec, split (n, ns [0]))) + fi + } + + rec (n) +} \ No newline at end of file diff --git a/stdlib/regression/test30.lama b/stdlib/regression/test30.lama index c3807915d..35c059e60 100644 --- a/stdlib/regression/test30.lama +++ b/stdlib/regression/test30.lama @@ -24,7 +24,7 @@ fun genCyclicArrays (n, eq, cross) { x -> [x, clone (x)] esac else - local a = split (n), + local a = split (n, random (n+1)), b = mapArray (id, a), index = initArray (random (a.length + 1), fun (_) {random (a.length)});