Skip to content

Commit b8818e8

Browse files
committed
map literals
1 parent 197dca0 commit b8818e8

File tree

14 files changed

+318
-63
lines changed

14 files changed

+318
-63
lines changed

src/next/ast/expression.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Id, Range, TypeId } from "@/next/ast/common";
2-
import type { Type } from "@/next/ast/type";
2+
import type { Type, TypeMap } from "@/next/ast/type";
33

44
export type Expression =
55
| OpBinary
@@ -18,7 +18,9 @@ export type Expression =
1818
| Var
1919
| Unit
2020
| Tuple
21-
| Tensor;
21+
| Tensor
22+
| MapLiteral
23+
| SetLiteral;
2224

2325
export type Var = {
2426
readonly kind: "var";
@@ -133,6 +135,25 @@ export type StructFieldInitializer = {
133135
readonly loc: Range;
134136
};
135137

138+
export type MapLiteral = {
139+
readonly kind: "map_literal";
140+
readonly type: TypeMap;
141+
readonly fields: readonly MapField[];
142+
readonly loc: Range;
143+
};
144+
145+
export type MapField = {
146+
readonly key: Expression;
147+
readonly value: Expression;
148+
};
149+
150+
export type SetLiteral = {
151+
readonly kind: "set_literal";
152+
readonly valueType: Type;
153+
readonly fields: readonly Expression[];
154+
readonly loc: Range;
155+
};
156+
136157
export type InitOf = {
137158
readonly kind: "init_of";
138159
readonly contract: TypeId;

src/next/ast/generated/expression.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,37 @@ export const OpBinary = (
251251
});
252252
export const isOpBinary = ($value: OpBinary) => $value.kind === "op_binary";
253253
export type Expression = $.Expression;
254+
export type MapField = $.MapField;
255+
export const MapField = (key: $.Expression, value: $.Expression): $.MapField =>
256+
Object.freeze({
257+
key,
258+
value,
259+
});
260+
export type MapLiteral = $.MapLiteral;
261+
export const MapLiteral = (
262+
type_: $t.TypeMap,
263+
fields: readonly $.MapField[],
264+
loc: $c.Range,
265+
): $.MapLiteral =>
266+
Object.freeze({
267+
kind: "map_literal",
268+
type: type_,
269+
fields,
270+
loc,
271+
});
272+
export const isMapLiteral = ($value: MapLiteral) =>
273+
$value.kind === "map_literal";
274+
export type SetLiteral = $.SetLiteral;
275+
export const SetLiteral = (
276+
valueType: $t.Type,
277+
fields: readonly $.Expression[],
278+
loc: $c.Range,
279+
): $.SetLiteral =>
280+
Object.freeze({
281+
kind: "set_literal",
282+
valueType,
283+
fields,
284+
loc,
285+
});
286+
export const isSetLiteral = ($value: SetLiteral) =>
287+
$value.kind === "set_literal";

src/next/ast/generated/type.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,12 @@ export const TypeCons = (
138138
});
139139
export const isTypeCons = ($value: TypeCons) => $value.kind === "cons_type";
140140
export type Type = $.Type;
141+
export type TypeMap = $.TypeMap;
142+
export const TypeMap = (key: $.Type, value: $.Type, loc: $c.Range): $.TypeMap =>
143+
Object.freeze({
144+
kind: "map_type",
145+
key,
146+
value,
147+
loc,
148+
});
149+
export const isTypeMap = ($value: TypeMap) => $value.kind === "map_type";

src/next/ast/type.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Range, TypeId } from "@/next/ast/common";
22

33
export type Type =
4+
| TypeMap
45
| TypeCons
56
| TypeInt
67
| TypeSlice
@@ -86,3 +87,10 @@ export type TypeTensor = {
8687
readonly typeArgs: readonly Type[];
8788
readonly loc: Range;
8889
};
90+
91+
export type TypeMap = {
92+
readonly kind: "map_type";
93+
readonly key: Type; // any type except tensor
94+
readonly value: Type; // any type except tensor
95+
readonly loc: Range;
96+
};

src/next/fs/memory-fs.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,38 @@ import type { Logger } from "@/error/logger-util";
77

88
type Options = {
99
// FIXME: should we pass log here, or into functions?
10-
readonly log: Logger<string, void>,
10+
readonly log: Logger<string, void>;
1111

1212
/**
1313
* Files present in memory file system at creation time
1414
*/
15-
readonly files: Map<string, Blob>,
15+
readonly files: Map<string, Blob>;
1616

1717
/**
1818
* Path to the root, used only for logging
19-
*
19+
*
2020
* Absolute paths do not make sense in memory FS, as
2121
* it doesn't have the actual root
2222
*/
23-
readonly root: RelativePath,
23+
readonly root: RelativePath;
2424

2525
/**
2626
* Whether it's possible to `write` into
2727
*/
28-
readonly isReadonly: boolean,
29-
}
28+
readonly isReadonly: boolean;
29+
};
3030

3131
export const emptyFiles: Map<string, Blob> = new Map();
3232

3333
/**
3434
* Create in-memory file system
3535
*/
36-
export function createMemoryFs(
37-
{ log, files, root, isReadonly }: Options
38-
): Cursor {
36+
export function createMemoryFs({
37+
log,
38+
files,
39+
root,
40+
isReadonly,
41+
}: Options): Cursor {
3942
const errors = FsErrors(log);
4043

4144
function builder(currPath: RelativePath): Cursor {

src/next/fs/proxy-fs.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import type { Logger } from "@/error/logger-util";
1111
const asRecord = <T>(t: Record<string, T>) => t;
1212

1313
type Options = {
14-
readonly log: Logger<string, void>,
15-
readonly root: string,
16-
readonly isReadonly: boolean,
14+
readonly log: Logger<string, void>;
15+
readonly root: string;
16+
readonly isReadonly: boolean;
1717
};
1818

1919
/**

src/next/grammar/errors.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,14 @@ export const SyntaxErrors = <M, R>(l: SourceLogger<M, R>) => ({
218218
constDeclNoType: () => (loc: Range) => {
219219
return l.at(loc).error(l.text`Constant declaration must have a type`);
220220
},
221+
mapArgCount: () => (loc: Range) => {
222+
return l
223+
.at(loc)
224+
.error(l.text`map<K, V> takes exactly two type arguments`);
225+
},
226+
setArgCount: () => (loc: Range) => {
227+
return l.at(loc).error(l.text`set<V> takes exactly one type argument`);
228+
},
221229
});
222230

223231
export type SyntaxErrors<M, R> = ReturnType<typeof SyntaxErrors<M, R>>;

src/next/grammar/gen.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
pgen src/next/grammar/grammar.gg -o src/next/grammar/grammar.ts
1+
pgen src/next/grammar/grammar.peggy -o src/next/grammar/grammar.ts

src/next/grammar/grammar.gg renamed to src/next/grammar/grammar.peggy

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ primary
322322
/ Tensor
323323
/ Tuple
324324
/ Parens
325+
/ MapLiteral
326+
/ SetLiteral
325327
/ StructInstance
326328
/ IntegerLiteral
327329
/ BoolLiteral
@@ -348,6 +350,21 @@ StructInstance =
348350
"}";
349351
StructFieldInitializer = name:Id init:(":" @expression)?;
350352

353+
MapLiteral =
354+
keyword<"map">
355+
typeArgs:typeArgs
356+
"{"
357+
fields:commaList<mapField>?
358+
"}";
359+
mapField = key:expression ":" value:expression;
360+
361+
SetLiteral =
362+
"set"
363+
typeArgs:typeArgs
364+
"{"
365+
fields:commaList<expression>?
366+
"}";
367+
351368
InitOf = keyword<"initOf"> name:TypeId params:parameterList<expression>;
352369
CodeOf = "codeOf" name:TypeId;
353370

src/next/grammar/grammar.ts

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,16 @@ export namespace $ast {
493493
readonly $: "Parens";
494494
readonly child: parens;
495495
}>;
496+
export type MapLiteral = $.Located<{
497+
readonly $: "MapLiteral";
498+
readonly typeArgs: typeArgs;
499+
readonly fields: commaList<mapField> | undefined;
500+
}>;
501+
export type SetLiteral = $.Located<{
502+
readonly $: "SetLiteral";
503+
readonly typeArgs: typeArgs;
504+
readonly fields: commaList<expression> | undefined;
505+
}>;
496506
export type StructInstance = $.Located<{
497507
readonly $: "StructInstance";
498508
readonly type: TypeId;
@@ -528,6 +538,8 @@ export namespace $ast {
528538
| Tensor
529539
| Tuple
530540
| Parens
541+
| MapLiteral
542+
| SetLiteral
531543
| StructInstance
532544
| IntegerLiteral
533545
| BoolLiteral
@@ -542,6 +554,10 @@ export namespace $ast {
542554
readonly name: Id;
543555
readonly init: expression | undefined;
544556
}>;
557+
export type mapField = {
558+
readonly key: expression;
559+
readonly value: expression;
560+
};
545561
export type ParameterList<T> = $.Located<{
546562
readonly $: "ParameterList";
547563
readonly values: commaList<T> | undefined;
@@ -2290,6 +2306,48 @@ export const Parens: $.Parser<$ast.Parens> = $.loc(
22902306
),
22912307
),
22922308
);
2309+
export const MapLiteral: $.Parser<$ast.MapLiteral> = $.loc(
2310+
$.field(
2311+
$.pure("MapLiteral"),
2312+
"$",
2313+
$.right(
2314+
keyword($.str("map")),
2315+
$.field(
2316+
typeArgs,
2317+
"typeArgs",
2318+
$.right(
2319+
$.str("{"),
2320+
$.field(
2321+
$.opt(commaList($.lazy(() => mapField))),
2322+
"fields",
2323+
$.right($.str("}"), $.eps),
2324+
),
2325+
),
2326+
),
2327+
),
2328+
),
2329+
);
2330+
export const SetLiteral: $.Parser<$ast.SetLiteral> = $.loc(
2331+
$.field(
2332+
$.pure("SetLiteral"),
2333+
"$",
2334+
$.right(
2335+
$.str("set"),
2336+
$.field(
2337+
typeArgs,
2338+
"typeArgs",
2339+
$.right(
2340+
$.str("{"),
2341+
$.field(
2342+
$.opt(commaList(expression)),
2343+
"fields",
2344+
$.right($.str("}"), $.eps),
2345+
),
2346+
),
2347+
),
2348+
),
2349+
),
2350+
);
22932351
export const StructInstance: $.Parser<$ast.StructInstance> = $.loc(
22942352
$.field(
22952353
$.pure("StructInstance"),
@@ -2380,16 +2438,25 @@ export const primary: $.Parser<$ast.primary> = $.alt(
23802438
$.alt(
23812439
Parens,
23822440
$.alt(
2383-
StructInstance,
2441+
MapLiteral,
23842442
$.alt(
2385-
IntegerLiteral,
2443+
SetLiteral,
23862444
$.alt(
2387-
BoolLiteral,
2445+
StructInstance,
23882446
$.alt(
2389-
InitOf,
2447+
IntegerLiteral,
23902448
$.alt(
2391-
CodeOf,
2392-
$.alt(Null, $.alt(StringLiteral, Id)),
2449+
BoolLiteral,
2450+
$.alt(
2451+
InitOf,
2452+
$.alt(
2453+
CodeOf,
2454+
$.alt(
2455+
Null,
2456+
$.alt(StringLiteral, Id),
2457+
),
2458+
),
2459+
),
23932460
),
23942461
),
23952462
),
@@ -2415,6 +2482,11 @@ export const StructFieldInitializer: $.Parser<$ast.StructFieldInitializer> =
24152482
),
24162483
),
24172484
);
2485+
export const mapField: $.Parser<$ast.mapField> = $.field(
2486+
expression,
2487+
"key",
2488+
$.right($.str(":"), $.field(expression, "value", $.eps)),
2489+
);
24182490
export const ParameterList = <T>(
24192491
T: $.Parser<T>,
24202492
): $.Parser<$ast.ParameterList<T>> =>

0 commit comments

Comments
 (0)