UNPKG

js-slang

Version:

Javascript-based implementations of Source, written in Typescript

2 lines (1 loc) 6.88 kB
export declare const listPrelude = "\n\n// equal computes the structural equality\n// over its arguments\n\nfunction equal(xs, ys) {\n return is_pair(xs)\n ? (is_pair(ys) &&\n equal(head(xs), head(ys)) &&\n equal(tail(xs), tail(ys)))\n : is_null(xs)\n ? is_null(ys)\n : is_number(xs)\n ? (is_number(ys) && xs === ys)\n : is_boolean(xs)\n ? (is_boolean(ys) && ((xs && ys) || (!xs && !ys)))\n : is_string(xs)\n ? (is_string(ys) && xs === ys)\n : is_undefined(xs)\n ? is_undefined(ys)\n : is_function(xs)\n // we know now that xs is a function,\n // but we use an if check anyway to make use of the type predicate\n ? (is_function(ys) && xs === ys)\n : false;\n}\n\n\n// returns the length of a given argument list\n// assumes that the argument is a list\n\nfunction $length(xs, acc) {\n return is_null(xs) ? acc : $length(tail(xs), acc + 1);\n}\nfunction length(xs) {\n return $length(xs, 0);\n}\n\n// map applies first arg f, assumed to be a unary function,\n// to the elements of the second argument, assumed to be a list.\n// f is applied element-by-element:\n// map(f, list(1, 2)) results in list(f(1), f(2))\n\nfunction $map(f, xs, acc) {\n return is_null(xs)\n ? reverse(acc)\n : $map(f, tail(xs), pair(f(head(xs)), acc));\n}\nfunction map(f, xs) {\n return $map(f, xs, null);\n}\n\n// build_list takes a a function fun as first argument, \n// and a nonnegative integer n as second argument,\n// build_list returns a list of n elements, that results from\n// applying fun to the numbers from 0 to n-1.\n\nfunction $build_list(i, fun, already_built) {\n return i < 0 ? already_built : $build_list(i - 1, fun, pair(fun(i), already_built));\n}\n\nfunction build_list(fun, n) {\n return $build_list(n - 1, fun, null);\n}\n\n// for_each applies first arg fun, assumed to be a unary function,\n// to the elements of the second argument, assumed to be a list.\n// fun is applied element-by-element:\n// for_each(fun, list(1, 2)) results in the calls fun(1) and fun(2).\n// for_each returns true.\n\nfunction for_each(fun, xs) {\n if (is_null(xs)) {\n return true;\n } else {\n fun(head(xs));\n return for_each(fun, tail(xs));\n }\n}\n\n// list_to_string returns a string that represents the argument list.\n// It applies itself recursively on the elements of the given list.\n// When it encounters a non-list, it applies to_string to it.\n\nfunction $list_to_string(xs, cont) {\n return is_null(xs)\n ? cont(\"null\")\n : is_pair(xs)\n ? $list_to_string(\n head(xs),\n x => $list_to_string(\n tail(xs),\n y => cont(\"[\" + x + \",\" + y + \"]\")))\n : cont(stringify(xs));\n}\n\nfunction list_to_string(xs) {\n return $list_to_string(xs, x => x);\n}\n\n// reverse reverses the argument, assumed to be a list\n\nfunction $reverse(original, reversed) {\n return is_null(original)\n ? reversed\n : $reverse(tail(original), pair(head(original), reversed));\n}\n\nfunction reverse(xs) {\n return $reverse(xs, null);\n}\n\n// append first argument, assumed to be a list, to the second argument.\n// In the result null at the end of the first argument list\n// is replaced by the second argument, regardless what the second\n// argument consists of.\n\nfunction $append(xs, ys, cont) {\n return is_null(xs)\n ? cont(ys)\n : $append(tail(xs), ys, zs => cont(pair(head(xs), zs)));\n}\n\nfunction append(xs, ys) {\n return $append(xs, ys, xs => xs);\n}\n\n// member looks for a given first-argument element in the\n// second argument, assumed to be a list. It returns the first\n// postfix sublist that starts with the given element. It returns null if the\n// element does not occur in the list\n\nfunction member(v, xs) {\n return is_null(xs)\n ? null\n\t : v === head(xs)\n\t ? xs\n\t : member(v, tail(xs));\n}\n\n// removes the first occurrence of a given first-argument element\n// in second-argument, assmed to be a list. Returns the original\n// list if there is no occurrence.\n\nfunction $remove(v, xs, acc) {\n // Ensure that typechecking of append and reverse are done independently\n const app = append;\n const rev = reverse;\n return is_null(xs)\n ? app(rev(acc), xs)\n : v === head(xs)\n ? app(rev(acc), tail(xs))\n : $remove(v, tail(xs), pair(head(xs), acc));\n}\n\nfunction remove(v, xs) {\n return $remove(v, xs, null);\n}\n\n// Similar to remove, but removes all instances of v\n// instead of just the first\n\nfunction $remove_all(v, xs, acc) {\n // Ensure that typechecking of append and reverse are done independently\n const app = append;\n const rev = reverse;\n return is_null(xs)\n ? app(rev(acc), xs)\n : v === head(xs)\n ? $remove_all(v, tail(xs), acc)\n : $remove_all(v, tail(xs), pair(head(xs), acc));\n}\n\nfunction remove_all(v, xs) {\n return $remove_all(v, xs, null);\n}\n\n// filter returns the sublist of elements of the second argument\n// (assumed to be a list), for which the given predicate function\n// returns true.\n\nfunction $filter(pred, xs, acc) {\n return is_null(xs)\n ? reverse(acc)\n : pred(head(xs))\n ? $filter(pred, tail(xs), pair(head(xs), acc))\n : $filter(pred, tail(xs), acc);\n}\n\nfunction filter(pred, xs) {\n return $filter(pred, xs, null);\n}\n\n// enumerates numbers starting from start, assumed to be a number,\n// using a step size of 1, until the number exceeds end, assumed\n// to be a number\n\nfunction $enum_list(start, end, acc) {\n // Ensure that typechecking of reverse are done independently\n const rev = reverse;\n return start > end\n ? rev(acc)\n : $enum_list(start + 1, end, pair(start, acc));\n}\n\nfunction enum_list(start, end) {\n return $enum_list(start, end, null);\n}\n\n// Returns the item in xs (assumed to be a list) at index n,\n// assumed to be a nonnegative integer.\n// Note: the first item is at position 0\n\nfunction list_ref(xs, n) {\n return n === 0\n ? head(xs)\n : list_ref(tail(xs), n - 1);\n}\n\n// accumulate applies an operation op (assumed to be a binary function)\n// to elements of sequence (assumed to be a list) in a right-to-left order.\n// first apply op to the last element and initial, resulting in r1, then to\n// the second-last element and r1, resulting in r2, etc, and finally\n// to the first element and r_n-1, where n is the length of the\n// list.\n// accumulate(op, zero, list(1, 2, 3)) results in\n// op(1, op(2, op(3, zero)))\n\nfunction $accumulate(f, initial, xs, cont) {\n return is_null(xs)\n ? cont(initial)\n : $accumulate(f, initial, tail(xs), x => cont(f(head(xs), x)));\n}\n\nfunction accumulate(f, initial, xs) {\n return $accumulate(f, initial, xs, x => x);\n}\n";