@soundscript/soundscript 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +10 -0
  3. package/async.d.ts +81 -0
  4. package/async.js +214 -0
  5. package/async.js.map +1 -0
  6. package/bin/soundscript.js +54 -0
  7. package/codec.d.ts +31 -0
  8. package/codec.js +31 -0
  9. package/codec.js.map +1 -0
  10. package/compare.d.ts +28 -0
  11. package/compare.js +121 -0
  12. package/compare.js.map +1 -0
  13. package/decode.d.ts +84 -0
  14. package/decode.js +249 -0
  15. package/decode.js.map +1 -0
  16. package/encode.d.ts +98 -0
  17. package/encode.js +128 -0
  18. package/encode.js.map +1 -0
  19. package/experimental/component.d.ts +40 -0
  20. package/experimental/component.js +46 -0
  21. package/experimental/component.js.map +1 -0
  22. package/experimental/css.d.ts +16 -0
  23. package/experimental/css.js +10 -0
  24. package/experimental/css.js.map +1 -0
  25. package/experimental/debug.d.ts +2 -0
  26. package/experimental/debug.js +10 -0
  27. package/experimental/debug.js.map +1 -0
  28. package/experimental/graphql.d.ts +16 -0
  29. package/experimental/graphql.js +10 -0
  30. package/experimental/graphql.js.map +1 -0
  31. package/experimental/sql.d.ts +22 -0
  32. package/experimental/sql.js +24 -0
  33. package/experimental/sql.js.map +1 -0
  34. package/failures.d.ts +23 -0
  35. package/failures.js +42 -0
  36. package/failures.js.map +1 -0
  37. package/hash.d.ts +34 -0
  38. package/hash.js +116 -0
  39. package/hash.js.map +1 -0
  40. package/hkt.d.ts +40 -0
  41. package/hkt.js +4 -0
  42. package/hkt.js.map +1 -0
  43. package/index.d.ts +9 -0
  44. package/index.js +16 -0
  45. package/index.js.map +1 -0
  46. package/json.d.ts +98 -0
  47. package/json.js +638 -0
  48. package/json.js.map +1 -0
  49. package/match.d.ts +11 -0
  50. package/match.js +14 -0
  51. package/match.js.map +1 -0
  52. package/package.json +153 -0
  53. package/result.d.ts +52 -0
  54. package/result.js +104 -0
  55. package/result.js.map +1 -0
  56. package/soundscript/async.sts +315 -0
  57. package/soundscript/codec.sts +75 -0
  58. package/soundscript/compare.sts +159 -0
  59. package/soundscript/decode.sts +382 -0
  60. package/soundscript/encode.sts +254 -0
  61. package/soundscript/experimental/component.sts +69 -0
  62. package/soundscript/experimental/css.sts +28 -0
  63. package/soundscript/experimental/debug.sts +10 -0
  64. package/soundscript/experimental/graphql.sts +28 -0
  65. package/soundscript/experimental/sql.sts +53 -0
  66. package/soundscript/failures.sts +64 -0
  67. package/soundscript/hash.sts +196 -0
  68. package/soundscript/hkt.sts +41 -0
  69. package/soundscript/index.sts +23 -0
  70. package/soundscript/json.sts +824 -0
  71. package/soundscript/match.sts +26 -0
  72. package/soundscript/result.sts +179 -0
  73. package/soundscript/thunk.sts +15 -0
  74. package/soundscript/typeclasses.sts +167 -0
  75. package/thunk.d.ts +2 -0
  76. package/thunk.js +10 -0
  77. package/thunk.js.map +1 -0
  78. package/typeclasses.d.ts +57 -0
  79. package/typeclasses.js +78 -0
  80. package/typeclasses.js.map +1 -0
@@ -0,0 +1,28 @@
1
+ export interface CssRawFragment {
2
+ readonly __cssKind: 'raw';
3
+ readonly text: string;
4
+ }
5
+
6
+ export interface CssTemplate {
7
+ readonly text: string;
8
+ readonly values: readonly unknown[];
9
+ }
10
+
11
+ export interface CssTag {
12
+ (strings: TemplateStringsArray, ...values: readonly unknown[]): CssTemplate;
13
+ raw(text: string): CssRawFragment;
14
+ }
15
+
16
+ const cssTag: CssTag = Object.assign(
17
+ (strings: TemplateStringsArray, ...values: readonly unknown[]): CssTemplate => ({
18
+ text: String.raw({ raw: strings }, ...values.map(String)),
19
+ values: [...values],
20
+ }),
21
+ {
22
+ raw(text: string): CssRawFragment {
23
+ return { __cssKind: 'raw', text };
24
+ },
25
+ },
26
+ );
27
+
28
+ export const css = cssTag;
@@ -0,0 +1,10 @@
1
+ export function assert(condition: unknown, message = 'Assertion failed.'): asserts condition {
2
+ if (!condition) {
3
+ throw new Error(message);
4
+ }
5
+ }
6
+
7
+ export function log<T>(value: T): T {
8
+ console.log(value);
9
+ return value;
10
+ }
@@ -0,0 +1,28 @@
1
+ export interface GraphqlRawFragment {
2
+ readonly __graphqlKind: 'raw';
3
+ readonly text: string;
4
+ }
5
+
6
+ export interface GraphqlQuery {
7
+ readonly query: string;
8
+ readonly values: readonly unknown[];
9
+ }
10
+
11
+ export interface GraphqlTag {
12
+ (strings: TemplateStringsArray, ...values: readonly unknown[]): GraphqlQuery;
13
+ raw(text: string): GraphqlRawFragment;
14
+ }
15
+
16
+ const graphqlTag: GraphqlTag = Object.assign(
17
+ (strings: TemplateStringsArray, ...values: readonly unknown[]): GraphqlQuery => ({
18
+ query: String.raw({ raw: strings }, ...values.map(String)),
19
+ values: [...values],
20
+ }),
21
+ {
22
+ raw(text: string): GraphqlRawFragment {
23
+ return { __graphqlKind: 'raw', text };
24
+ },
25
+ },
26
+ );
27
+
28
+ export const graphql = graphqlTag;
@@ -0,0 +1,53 @@
1
+ export interface SqlQuery {
2
+ readonly text: string;
3
+ readonly params: readonly unknown[];
4
+ }
5
+
6
+ export interface SqlIdentifier {
7
+ readonly __sqlKind: 'identifier';
8
+ readonly name: string;
9
+ }
10
+
11
+ export interface SqlRawFragment {
12
+ readonly __sqlKind: 'raw';
13
+ readonly text: string;
14
+ }
15
+
16
+ export interface SqlTag {
17
+ (strings: TemplateStringsArray, ...values: readonly unknown[]): SqlQuery;
18
+ ident(name: string): SqlIdentifier;
19
+ raw(text: string): SqlRawFragment;
20
+ }
21
+
22
+ function buildSqlQuery(
23
+ strings: TemplateStringsArray,
24
+ values: readonly unknown[],
25
+ ): SqlQuery {
26
+ let text = '';
27
+ for (let index = 0; index < strings.length; index += 1) {
28
+ text += strings[index] ?? '';
29
+ if (index < values.length) {
30
+ text += `$${index + 1}`;
31
+ }
32
+ }
33
+
34
+ return {
35
+ text,
36
+ params: [...values],
37
+ };
38
+ }
39
+
40
+ const sqlTag = ((strings: TemplateStringsArray, ...values: readonly unknown[]) =>
41
+ buildSqlQuery(strings, values)) as SqlTag;
42
+
43
+ sqlTag.ident = (name: string): SqlIdentifier => ({
44
+ __sqlKind: 'identifier',
45
+ name,
46
+ });
47
+
48
+ sqlTag.raw = (text: string): SqlRawFragment => ({
49
+ __sqlKind: 'raw',
50
+ text,
51
+ });
52
+
53
+ export const sql = sqlTag;
@@ -0,0 +1,64 @@
1
+ export type ErrorFrame = {
2
+ readonly column: number;
3
+ readonly file: string;
4
+ readonly fn?: string;
5
+ readonly line: number;
6
+ };
7
+
8
+ export class Failure {
9
+ readonly cause?: unknown;
10
+ readonly message: string;
11
+ readonly name: string;
12
+ readonly trace: readonly ErrorFrame[];
13
+
14
+ constructor(
15
+ message = '',
16
+ options: {
17
+ cause?: unknown;
18
+ trace?: readonly ErrorFrame[];
19
+ } = {},
20
+ ) {
21
+ this.name = new.target.name;
22
+ this.message = message;
23
+ if ('cause' in options) {
24
+ this.cause = options.cause;
25
+ }
26
+ this.trace = options.trace ?? [];
27
+ }
28
+
29
+ withFrame(frame: ErrorFrame): this {
30
+ const prototype = Object.getPrototypeOf(this as object);
31
+ const clone = (prototype === null ? Object.create(null) : Object.create(prototype)) as this;
32
+ Object.defineProperties(clone, Object.getOwnPropertyDescriptors(this));
33
+ Object.defineProperty(clone, 'trace', {
34
+ configurable: true,
35
+ enumerable: true,
36
+ writable: false,
37
+ value: [...this.trace, frame],
38
+ });
39
+ return clone;
40
+ }
41
+ }
42
+
43
+ export function normalizeThrown(value: unknown): Error {
44
+ if (value instanceof Error) {
45
+ return value;
46
+ }
47
+
48
+ const details = typeof value === 'object' && value !== null
49
+ ? value as { message?: unknown; name?: unknown; stack?: unknown }
50
+ : undefined;
51
+ const message = typeof details?.message === 'string'
52
+ ? details.message
53
+ : 'Non-Error thrown value.';
54
+ const error = new Error(message, { cause: value });
55
+
56
+ if (typeof details?.name === 'string') {
57
+ error.name = details.name;
58
+ }
59
+ if (typeof details?.stack === 'string') {
60
+ error.stack = details.stack;
61
+ }
62
+
63
+ return error;
64
+ }
@@ -0,0 +1,196 @@
1
+ import type { Eq } from '@soundscript/soundscript/compare';
2
+ import type { Option, Result } from '@soundscript/soundscript/result';
3
+
4
+ export type HashCode = number;
5
+
6
+ export interface Hash<T> {
7
+ hash(value: T): HashCode;
8
+ }
9
+
10
+ export interface HashEq<T> extends Hash<T>, Eq<T> {}
11
+
12
+ type HashEqValue<THashEq> = THashEq extends HashEq<infer TValue> ? TValue : never;
13
+
14
+ export function fromHashEq<T>(
15
+ hash: (value: T) => HashCode,
16
+ equals: (left: T, right: T) => boolean,
17
+ ): HashEq<T> {
18
+ return {
19
+ hash(value) {
20
+ return normalizeHashCode(hash(value));
21
+ },
22
+ equals,
23
+ };
24
+ }
25
+
26
+ export function contramap<A, B>(
27
+ hashEq: HashEq<A>,
28
+ project: (value: B) => A,
29
+ ): HashEq<B> {
30
+ return fromHashEq(
31
+ (value) => hashEq.hash(project(value)),
32
+ (left, right) => hashEq.equals(project(left), project(right)),
33
+ );
34
+ }
35
+
36
+ export function lazyHashEq<T>(getHashEq: () => HashEq<T>): HashEq<T> {
37
+ return fromHashEq(
38
+ (value) => getHashEq().hash(value),
39
+ (left, right) => getHashEq().equals(left, right),
40
+ );
41
+ }
42
+
43
+ export function arrayHash<T>(itemHash: HashEq<T>): HashEq<readonly T[]> {
44
+ return fromHashEq(
45
+ (value) => combineHashes(...value.map((entry) => itemHash.hash(entry))),
46
+ (left, right) => {
47
+ if (left.length !== right.length) {
48
+ return false;
49
+ }
50
+
51
+ for (let index = 0; index < left.length; index += 1) {
52
+ if (!itemHash.equals(left[index]!, right[index]!)) {
53
+ return false;
54
+ }
55
+ }
56
+
57
+ return true;
58
+ },
59
+ );
60
+ }
61
+
62
+ export function tupleHash<const THashEqs extends readonly HashEq<unknown>[]>(
63
+ ...elements: THashEqs
64
+ ): HashEq<{ readonly [K in keyof THashEqs]: HashEqValue<THashEqs[K]> }> {
65
+ return fromHashEq(
66
+ (value) => {
67
+ const values = value as readonly unknown[];
68
+ if (values.length !== elements.length) {
69
+ return 0;
70
+ }
71
+ return combineHashes(
72
+ ...elements.map((elementHash, index) => elementHash.hash(values[index])),
73
+ );
74
+ },
75
+ (left, right) => {
76
+ const leftValues = left as readonly unknown[];
77
+ const rightValues = right as readonly unknown[];
78
+ if (leftValues.length !== elements.length || rightValues.length !== elements.length) {
79
+ return false;
80
+ }
81
+
82
+ for (let index = 0; index < elements.length; index += 1) {
83
+ const elementHash = elements[index];
84
+ if (!elementHash) {
85
+ continue;
86
+ }
87
+ if (!elementHash.equals(leftValues[index], rightValues[index])) {
88
+ return false;
89
+ }
90
+ }
91
+
92
+ return true;
93
+ },
94
+ );
95
+ }
96
+
97
+ export function optionHash<T>(itemHash: HashEq<T>): HashEq<Option<T>> {
98
+ return fromHashEq(
99
+ (value) =>
100
+ value.tag === 'ok'
101
+ ? combineHashes(stringHash.hash('ok'), itemHash.hash(value.value))
102
+ : stringHash.hash('err'),
103
+ (left, right) => {
104
+ if (left.tag !== right.tag) {
105
+ return false;
106
+ }
107
+
108
+ if (left.tag === 'ok' && right.tag === 'ok') {
109
+ return itemHash.equals(left.value, right.value);
110
+ }
111
+
112
+ return true;
113
+ },
114
+ );
115
+ }
116
+
117
+ export function resultHash<T, E>(okHash: HashEq<T>, errHash: HashEq<E>): HashEq<Result<T, E>> {
118
+ return fromHashEq(
119
+ (value) =>
120
+ value.tag === 'ok'
121
+ ? combineHashes(stringHash.hash('ok'), okHash.hash(value.value))
122
+ : combineHashes(stringHash.hash('err'), errHash.hash(value.error)),
123
+ (left, right) => {
124
+ if (left.tag !== right.tag) {
125
+ return false;
126
+ }
127
+
128
+ if (left.tag === 'ok' && right.tag === 'ok') {
129
+ return okHash.equals(left.value, right.value);
130
+ }
131
+
132
+ if (left.tag === 'err' && right.tag === 'err') {
133
+ return errHash.equals(left.error, right.error);
134
+ }
135
+
136
+ return false;
137
+ },
138
+ );
139
+ }
140
+
141
+ export const stringHash: HashEq<string> = fromHashEq(
142
+ hashString,
143
+ (left, right) => left === right,
144
+ );
145
+
146
+ export const numberHash: HashEq<number> = fromHashEq(
147
+ (value) => hashString(normalizeNumberKey(value)),
148
+ (left, right) => left === right || (Number.isNaN(left) && Number.isNaN(right)),
149
+ );
150
+
151
+ export const booleanHash: HashEq<boolean> = fromHashEq(
152
+ (value) => value ? 1 : 0,
153
+ (left, right) => left === right,
154
+ );
155
+
156
+ export const bigintHash: HashEq<bigint> = fromHashEq(
157
+ (value) => hashString(value.toString()),
158
+ (left, right) => left === right,
159
+ );
160
+
161
+ export function combineHashes(...hashes: readonly HashCode[]): HashCode {
162
+ let hash = 0;
163
+ for (const value of hashes) {
164
+ hash = Math.imul(hash ^ normalizeHashCode(value), 0x01000193);
165
+ }
166
+ return normalizeHashCode(hash);
167
+ }
168
+
169
+ function normalizeHashCode(value: number): HashCode {
170
+ if (!Number.isFinite(value)) {
171
+ return 0;
172
+ }
173
+
174
+ return value | 0;
175
+ }
176
+
177
+ function normalizeNumberKey(value: number): string {
178
+ if (Number.isNaN(value)) {
179
+ return 'NaN';
180
+ }
181
+
182
+ if (value === 0) {
183
+ return '0';
184
+ }
185
+
186
+ return String(value);
187
+ }
188
+
189
+ function hashString(value: string): HashCode {
190
+ let hash = 0x811c9dc5;
191
+ for (let index = 0; index < value.length; index += 1) {
192
+ hash ^= value.charCodeAt(index);
193
+ hash = Math.imul(hash, 0x01000193);
194
+ }
195
+ return hash | 0;
196
+ }
@@ -0,0 +1,41 @@
1
+ export interface TypeLambda {
2
+ readonly Args: readonly unknown[];
3
+ readonly type: unknown;
4
+ }
5
+
6
+ export type Apply<F extends TypeLambda, Args extends readonly unknown[]> = F extends {
7
+ readonly __target: infer Target extends TypeLambda;
8
+ readonly __prefix: infer Prefix extends readonly unknown[];
9
+ } ? Apply<Target, [...Prefix, ...Args]>
10
+ : (F & { readonly Args: Args })['type'];
11
+
12
+ export type Bind<F extends TypeLambda, Prefix extends readonly unknown[]> = TypeLambda & {
13
+ readonly __target: F;
14
+ readonly __prefix: Prefix;
15
+ };
16
+
17
+ export type Kind<F extends TypeLambda, A> = Apply<F, [A]>;
18
+ export type Kind2<F extends TypeLambda, A, B> = Apply<F, [A, B]>;
19
+ export type Kind3<F extends TypeLambda, A, B, C> = Apply<F, [A, B, C]>;
20
+
21
+ export type MonadTypeLambda<M extends { readonly __type_lambda?: TypeLambda }> = M extends {
22
+ readonly __type_lambda?: infer F extends TypeLambda;
23
+ } ? F
24
+ : never;
25
+ export type BoundEffect<F extends TypeLambda, A = unknown> = Kind<F, A>;
26
+ export type BoundValue<F extends TypeLambda, Value> = Value extends BoundEffect<F, infer A> ? A
27
+ : never;
28
+ export type Binder<F extends TypeLambda> = <A>(value: BoundEffect<F, A>) => A;
29
+
30
+ export type {
31
+ Applicative,
32
+ AsyncMonad,
33
+ Contravariant,
34
+ Functor,
35
+ Invariant,
36
+ Monad,
37
+ } from '@soundscript/soundscript/typeclasses';
38
+ export { Do, monadGen } from '@soundscript/soundscript/typeclasses';
39
+
40
+ // Macro binding placeholder. The compiler-owned macro pipeline consumes this symbol.
41
+ export const hkt: unknown = undefined;
@@ -0,0 +1,23 @@
1
+ export type { Err, None, Ok, Option, Result, Some } from '@soundscript/soundscript/result';
2
+
3
+ export { err, isErr, isNone, isOk, isSome, none, ok, some, Try } from '@soundscript/soundscript/result';
4
+ export { Match, where } from '@soundscript/soundscript/match';
5
+ export { Failure } from '@soundscript/soundscript/failures';
6
+
7
+ function macroRuntimeError(name: string): never {
8
+ throw new Error(
9
+ `${name}(...) is a Soundscript macro and should be removed during Soundscript expansion.`,
10
+ );
11
+ }
12
+
13
+ export function Defer(_cleanup: () => unknown): never {
14
+ return macroRuntimeError('Defer');
15
+ }
16
+
17
+ export function todo(message?: string): never {
18
+ throw new Error(message ? `TODO: ${message}` : 'TODO');
19
+ }
20
+
21
+ export function unreachable(message?: string): never {
22
+ throw new Error(message ? `Unreachable: ${message}` : 'Unreachable');
23
+ }