desmost 0.10.1 → 0.11.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.
- package/README.md +5 -5
- package/dist/compiler/compile.d.ts +1 -1
- package/dist/compiler/compile.js +1 -1
- package/dist/compiler/compiler.d.ts.map +1 -1
- package/dist/compiler/compiler.js +9 -8
- package/dist/compiler/compiler.js.map +1 -1
- package/dist/compiler/format.js +1 -1
- package/dist/compiler/format.js.map +1 -1
- package/dist/decompiler/decompile.d.ts +13 -5
- package/dist/decompiler/decompile.d.ts.map +1 -1
- package/dist/decompiler/decompile.js +24 -13
- package/dist/decompiler/decompile.js.map +1 -1
- package/dist/decompiler/emit.d.ts +5 -2
- package/dist/decompiler/emit.d.ts.map +1 -1
- package/dist/decompiler/emit.js +41 -20
- package/dist/decompiler/emit.js.map +1 -1
- package/dist/decompiler/extract.d.ts +1 -9
- package/dist/decompiler/extract.d.ts.map +1 -1
- package/dist/decompiler/extract.js +24 -58
- package/dist/decompiler/extract.js.map +1 -1
- package/dist/decompiler/format.d.ts +0 -1
- package/dist/decompiler/format.d.ts.map +1 -1
- package/dist/decompiler/format.js +3 -9
- package/dist/decompiler/format.js.map +1 -1
- package/dist/errors.d.ts +14 -7
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +20 -2
- package/dist/errors.js.map +1 -1
- package/dist/magic/expr/index.js +6 -6
- package/dist/magic/expr/index.js.map +1 -1
- package/dist/magic/expr/latex.d.ts +5 -2
- package/dist/magic/expr/latex.d.ts.map +1 -1
- package/dist/magic/expr/latex.js +4 -2
- package/dist/magic/expr/latex.js.map +1 -1
- package/dist/magic/expr/text.d.ts +5 -2
- package/dist/magic/expr/text.d.ts.map +1 -1
- package/dist/magic/expr/text.js +4 -2
- package/dist/magic/expr/text.js.map +1 -1
- package/dist/magic/global/{dark-mode.d.ts → dark.d.ts} +6 -2
- package/dist/magic/global/dark.d.ts.map +1 -0
- package/dist/magic/global/dark.js +20 -0
- package/dist/magic/global/dark.js.map +1 -0
- package/dist/magic/global/desmos.d.ts +4 -1
- package/dist/magic/global/desmos.d.ts.map +1 -1
- package/dist/magic/global/desmos.js +23 -0
- package/dist/magic/global/desmos.js.map +1 -1
- package/dist/magic/global/index.d.ts +5 -5
- package/dist/magic/global/index.d.ts.map +1 -1
- package/dist/magic/global/index.js +8 -11
- package/dist/magic/global/index.js.map +1 -1
- package/dist/magic/global/viewport.d.ts +3 -0
- package/dist/magic/global/viewport.d.ts.map +1 -1
- package/dist/magic/global/viewport.js +20 -0
- package/dist/magic/global/viewport.js.map +1 -1
- package/dist/magic/incantation.d.ts +15 -2
- package/dist/magic/incantation.d.ts.map +1 -1
- package/dist/magic/incantation.js +8 -1
- package/dist/magic/incantation.js.map +1 -1
- package/dist/magic/local/anim.d.ts +5 -1
- package/dist/magic/local/anim.d.ts.map +1 -1
- package/dist/magic/local/anim.js +12 -1
- package/dist/magic/local/anim.js.map +1 -1
- package/dist/magic/local/colour.d.ts +7 -3
- package/dist/magic/local/colour.d.ts.map +1 -1
- package/dist/magic/local/colour.js +13 -3
- package/dist/magic/local/colour.js.map +1 -1
- package/dist/magic/local/dashed.d.ts +5 -1
- package/dist/magic/local/dashed.d.ts.map +1 -1
- package/dist/magic/local/dashed.js +12 -1
- package/dist/magic/local/dashed.js.map +1 -1
- package/dist/magic/local/fill.d.ts +5 -1
- package/dist/magic/local/fill.d.ts.map +1 -1
- package/dist/magic/local/fill.js +15 -1
- package/dist/magic/local/fill.js.map +1 -1
- package/dist/magic/local/hide.d.ts +5 -1
- package/dist/magic/local/hide.d.ts.map +1 -1
- package/dist/magic/local/hide.js +12 -1
- package/dist/magic/local/hide.js.map +1 -1
- package/dist/magic/local/index.d.ts +13 -2
- package/dist/magic/local/index.d.ts.map +1 -1
- package/dist/magic/local/index.js +24 -24
- package/dist/magic/local/index.js.map +1 -1
- package/dist/magic/local/label.d.ts +6 -2
- package/dist/magic/local/label.d.ts.map +1 -1
- package/dist/magic/local/label.js +19 -1
- package/dist/magic/local/label.js.map +1 -1
- package/dist/magic/local/line.d.ts +5 -1
- package/dist/magic/local/line.d.ts.map +1 -1
- package/dist/magic/local/line.js +19 -1
- package/dist/magic/local/line.js.map +1 -1
- package/dist/magic/local/no-line.d.ts +5 -1
- package/dist/magic/local/no-line.d.ts.map +1 -1
- package/dist/magic/local/no-line.js +12 -1
- package/dist/magic/local/no-line.js.map +1 -1
- package/dist/magic/local/point.d.ts +5 -1
- package/dist/magic/local/point.d.ts.map +1 -1
- package/dist/magic/local/point.js +19 -1
- package/dist/magic/local/point.js.map +1 -1
- package/dist/magic/local/secret.d.ts +5 -1
- package/dist/magic/local/secret.d.ts.map +1 -1
- package/dist/magic/local/secret.js +12 -1
- package/dist/magic/local/secret.js.map +1 -1
- package/dist/magic/local/slider.d.ts +5 -1
- package/dist/magic/local/slider.d.ts.map +1 -1
- package/dist/magic/local/slider.js +13 -1
- package/dist/magic/local/slider.js.map +1 -1
- package/dist/parser/ast.d.ts +9 -3
- package/dist/parser/ast.d.ts.map +1 -1
- package/dist/parser/ast.js +3 -1
- package/dist/parser/ast.js.map +1 -1
- package/dist/parser/desmost-parser.d.ts +2 -2
- package/dist/parser/desmost-parser.d.ts.map +1 -1
- package/dist/parser/desmost-parser.js +6 -4
- package/dist/parser/desmost-parser.js.map +1 -1
- package/dist/parser/errors.d.ts +11 -0
- package/dist/parser/errors.d.ts.map +1 -0
- package/dist/parser/errors.js +4 -0
- package/dist/parser/errors.js.map +1 -0
- package/dist/parser/generic-parser.d.ts +7 -5
- package/dist/parser/generic-parser.d.ts.map +1 -1
- package/dist/parser/generic-parser.js +7 -10
- package/dist/parser/generic-parser.js.map +1 -1
- package/package.json +1 -1
- package/src/compiler/compile.ts +1 -1
- package/src/compiler/compiler.ts +10 -9
- package/src/compiler/format.ts +1 -1
- package/src/decompiler/decompile.ts +30 -14
- package/src/decompiler/emit.ts +57 -25
- package/src/decompiler/extract.ts +30 -89
- package/src/decompiler/format.ts +3 -14
- package/src/decompiler/readme.md +2 -2
- package/src/errors.ts +13 -7
- package/src/magic/.template.ts +8 -0
- package/src/magic/expr/index.ts +6 -7
- package/src/magic/expr/latex.ts +8 -4
- package/src/magic/expr/text.ts +8 -4
- package/src/magic/global/dark.ts +29 -0
- package/src/magic/global/desmos.ts +35 -5
- package/src/magic/global/index.ts +8 -14
- package/src/magic/global/viewport.ts +29 -0
- package/src/magic/incantation.ts +28 -6
- package/src/magic/local/anim.ts +16 -3
- package/src/magic/local/colour.ts +18 -6
- package/src/magic/local/dashed.ts +16 -2
- package/src/magic/local/fill.ts +20 -3
- package/src/magic/local/hide.ts +16 -2
- package/src/magic/local/index.ts +24 -25
- package/src/magic/local/label.ts +31 -8
- package/src/magic/local/line.ts +25 -3
- package/src/magic/local/no-line.ts +16 -2
- package/src/magic/local/point.ts +27 -3
- package/src/magic/local/secret.ts +16 -2
- package/src/magic/local/slider.ts +18 -3
- package/src/parser/ast.ts +10 -7
- package/src/parser/desmost-parser.ts +10 -6
- package/src/parser/errors.ts +10 -0
- package/src/parser/generic-parser.ts +9 -11
- package/svelte/desmost.svelte +107 -107
- package/dist/magic/expr/index.d.ts +0 -3
- package/dist/magic/expr/index.d.ts.map +0 -1
- package/dist/magic/global/dark-mode.d.ts.map +0 -1
- package/dist/magic/global/dark-mode.js +0 -9
- package/dist/magic/global/dark-mode.js.map +0 -1
- package/src/magic/global/dark-mode.ts +0 -15
package/src/magic/local/anim.ts
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
import { Incantation, type LOCAL } from "../incantation";
|
|
2
|
+
import { Ast } from "../../parser";
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
export class AnimIncantation extends Incantation<LOCAL>
|
|
5
6
|
{
|
|
6
|
-
override readonly
|
|
7
|
-
= "Animate the slider of a block."
|
|
8
|
-
|
|
7
|
+
override readonly effect = Incantation.Effect.LOCAL
|
|
9
8
|
override readonly identifier = "anim"
|
|
9
|
+
override readonly description
|
|
10
|
+
= `Animate the slider of a block.`
|
|
10
11
|
|
|
11
12
|
override apply(target: Desmos.ExpressionState)
|
|
12
13
|
{
|
|
13
14
|
super.require_expr_type(target.type, "expression");
|
|
14
15
|
target.playing = true;
|
|
15
16
|
}
|
|
17
|
+
|
|
18
|
+
override extract(target: Desmos.Expression): Ast.IncantationInvocation<LOCAL> | void
|
|
19
|
+
{
|
|
20
|
+
if (target.playing) {
|
|
21
|
+
return {
|
|
22
|
+
kind: Ast.Kind.INCANTATION_INVOCATION,
|
|
23
|
+
incantation: anim,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
16
27
|
}
|
|
28
|
+
|
|
29
|
+
export const anim = new AnimIncantation();
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Incantation, ArgIncantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
|
-
import { DesmostError } from "../../errors";
|
|
4
3
|
import type { DesmostOptions } from "../../options";
|
|
4
|
+
import { DesmostError } from "../../errors";
|
|
5
|
+
import { Ast } from "../../parser";
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
type DesmosColourName = keyof typeof Desmos.Colors;
|
|
@@ -12,13 +13,13 @@ const VALID_COLOURS = ["RED", "BLUE", "GREEN", "PURPLE", "ORANGE", "BLACK"];
|
|
|
12
13
|
|
|
13
14
|
export class ColourIncantation extends ArgIncantation<LOCAL>
|
|
14
15
|
{
|
|
15
|
-
override readonly
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
override readonly identifier = "color"
|
|
19
|
-
override readonly alias = "colour"
|
|
16
|
+
override readonly effect = Incantation.Effect.LOCAL
|
|
17
|
+
override readonly identifier = "colour"
|
|
18
|
+
override readonly alias = "color"
|
|
20
19
|
override readonly requires_arg = true
|
|
21
20
|
override readonly arg_type = Incantation.ArgType.ENUM
|
|
21
|
+
override readonly description
|
|
22
|
+
= "Change the colour of a rendered expression, such as a line, region, polygon, etc."
|
|
22
23
|
|
|
23
24
|
override apply(target: Desmos.ExpressionState, data: DesmosColour)
|
|
24
25
|
{
|
|
@@ -46,4 +47,15 @@ export class ColourIncantation extends ArgIncantation<LOCAL>
|
|
|
46
47
|
return internal;
|
|
47
48
|
}
|
|
48
49
|
}
|
|
50
|
+
|
|
51
|
+
override extract(target: Desmos.Expression): Ast.IncantationInvocation<LOCAL>
|
|
52
|
+
{
|
|
53
|
+
return {
|
|
54
|
+
kind: Ast.Kind.INCANTATION_INVOCATION,
|
|
55
|
+
incantation: colour,
|
|
56
|
+
arg_raw: target.color, // FIXME use name
|
|
57
|
+
};
|
|
58
|
+
}
|
|
49
59
|
}
|
|
60
|
+
|
|
61
|
+
export const colour = new ColourIncantation();
|
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
import { Incantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
|
+
import { Ast } from "../../parser";
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
export class DashedIncantation extends Incantation<LOCAL>
|
|
5
7
|
{
|
|
8
|
+
override readonly effect = Incantation.Effect.LOCAL
|
|
9
|
+
override readonly identifier = "dashed"
|
|
6
10
|
override readonly description
|
|
7
11
|
= "Render a block as a dashed line."
|
|
8
|
-
|
|
9
|
-
override readonly identifier = "dashed"
|
|
10
12
|
|
|
11
13
|
override apply(target: Desmos.ExpressionState)
|
|
12
14
|
{
|
|
13
15
|
super.require_expr_type(target.type, "expression");
|
|
14
16
|
target.lineStyle = Desmos.Styles.DASHED;
|
|
15
17
|
}
|
|
18
|
+
|
|
19
|
+
override extract(target: Desmos.Expression): Ast.IncantationInvocation<LOCAL> | void
|
|
20
|
+
{
|
|
21
|
+
if (target.lineStyle === Desmos.Styles.DASHED) {
|
|
22
|
+
return {
|
|
23
|
+
kind: Ast.Kind.INCANTATION_INVOCATION,
|
|
24
|
+
incantation: dashed,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
16
28
|
}
|
|
29
|
+
|
|
30
|
+
export const dashed = new DashedIncantation();
|
package/src/magic/local/fill.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Incantation, ArgIncantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
|
+
import { Ast } from "../../parser";
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
interface FillOptions
|
|
5
7
|
{
|
|
@@ -9,16 +11,31 @@ interface FillOptions
|
|
|
9
11
|
|
|
10
12
|
export class FillIncantation extends ArgIncantation<LOCAL>
|
|
11
13
|
{
|
|
12
|
-
override readonly
|
|
13
|
-
= "Change fill styles for a rendered block."
|
|
14
|
-
|
|
14
|
+
override readonly effect = Incantation.Effect.LOCAL
|
|
15
15
|
override readonly identifier = "fill"
|
|
16
16
|
override readonly requires_arg = true
|
|
17
17
|
override readonly arg_type = Incantation.ArgType.OBJECT
|
|
18
|
+
override readonly description
|
|
19
|
+
= "Change fill styles for a rendered block."
|
|
18
20
|
|
|
19
21
|
override apply(target: Desmos.ExpressionState, data: FillOptions)
|
|
20
22
|
{
|
|
21
23
|
super.require_expr_type(target.type, "expression");
|
|
22
24
|
target.fillOpacity = data.opacity;
|
|
23
25
|
}
|
|
26
|
+
|
|
27
|
+
override extract(target: Desmos.Expression): Ast.IncantationInvocation<LOCAL> | void
|
|
28
|
+
{
|
|
29
|
+
if (target.fillOpacity) {
|
|
30
|
+
return {
|
|
31
|
+
kind: Ast.Kind.INCANTATION_INVOCATION,
|
|
32
|
+
incantation: fill,
|
|
33
|
+
arg_raw: super.emit_object_arg({
|
|
34
|
+
opacity: target.fillOpacity,
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
24
39
|
}
|
|
40
|
+
|
|
41
|
+
export const fill = new FillIncantation();
|
package/src/magic/local/hide.ts
CHANGED
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
import { Incantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
|
+
import { Ast } from "../../parser";
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
export class HideIncantation extends Incantation<LOCAL>
|
|
5
7
|
{
|
|
8
|
+
override readonly effect = Incantation.Effect.LOCAL
|
|
9
|
+
override readonly identifier = "hide"
|
|
6
10
|
override readonly description
|
|
7
11
|
= "Hide rendering for a block. This includes graphs, points, polygons, etc."
|
|
8
|
-
|
|
9
|
-
override readonly identifier = "hide"
|
|
10
12
|
|
|
11
13
|
apply(target: Desmos.ExpressionState)
|
|
12
14
|
{
|
|
13
15
|
super.require_expr_type(target.type, "expression");
|
|
14
16
|
target.hidden = true;
|
|
15
17
|
}
|
|
18
|
+
|
|
19
|
+
override extract(target: Desmos.Expression): Ast.IncantationInvocation<LOCAL> | void
|
|
20
|
+
{
|
|
21
|
+
if (target.hidden) {
|
|
22
|
+
return {
|
|
23
|
+
kind: Ast.Kind.INCANTATION_INVOCATION,
|
|
24
|
+
incantation: hide,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
16
28
|
}
|
|
29
|
+
|
|
30
|
+
export const hide = new HideIncantation();
|
package/src/magic/local/index.ts
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
import { Incantation, type LOCAL } from "../incantation";
|
|
2
|
-
import { AnimIncantation } from "./anim";
|
|
3
2
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
3
|
+
import { anim } from "./anim";
|
|
4
|
+
import { colour } from "./colour";
|
|
5
|
+
import { dashed } from "./dashed";
|
|
6
|
+
import { fill } from "./fill";
|
|
7
|
+
import { hide } from "./hide";
|
|
8
|
+
import { label } from "./label";
|
|
9
|
+
import { line } from "./line";
|
|
10
|
+
import { no_line } from "./no-line";
|
|
11
|
+
import { point } from "./point";
|
|
12
|
+
import { secret } from "./secret";
|
|
13
|
+
import { slider } from "./slider";
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
export const LOCAL_INCANTATIONS
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
];
|
|
16
|
+
export const LOCAL_INCANTATIONS = {
|
|
17
|
+
anim,
|
|
18
|
+
colour,
|
|
19
|
+
dashed,
|
|
20
|
+
fill,
|
|
21
|
+
hide,
|
|
22
|
+
label,
|
|
23
|
+
line,
|
|
24
|
+
no_line,
|
|
25
|
+
point,
|
|
26
|
+
secret,
|
|
27
|
+
slider,
|
|
28
|
+
} satisfies Record<string, Incantation<LOCAL>>;
|
package/src/magic/local/label.ts
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import { Incantation, ArgIncantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
|
-
import { DesmostError } from "../../errors";
|
|
4
3
|
import type { DesmostOptions } from "../../options";
|
|
4
|
+
import { DesmostError } from "../../errors";
|
|
5
|
+
import { Ast } from "../../parser";
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
interface LabelOptions
|
|
8
9
|
{
|
|
9
|
-
text:
|
|
10
|
-
show?: boolean
|
|
11
|
-
size?: number
|
|
12
|
-
pos?:
|
|
10
|
+
text: string
|
|
11
|
+
show?: boolean
|
|
12
|
+
size?: number
|
|
13
|
+
pos?:
|
|
14
|
+
| "DEFAULT"
|
|
15
|
+
| "ABOVE" | "BELOW" | "LEFT" | "RIGHT"
|
|
16
|
+
| "ABOVE_LEFT" | "ABOVE_RIGHT" | "BELOW_LEFT" | "BELOW_RIGHT"
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
const VALID_FIELDS = ["text", "show", "size", "pos"];
|
|
16
20
|
|
|
17
21
|
const VALID_POSITIONS = [
|
|
22
|
+
"DEFAULT",
|
|
18
23
|
"ABOVE", "BELOW", "LEFT", "RIGHT",
|
|
19
24
|
"ABOVE_LEFT", "ABOVE_RIGHT", "BELOW_LEFT", "BELOW_RIGHT",
|
|
20
25
|
];
|
|
@@ -22,12 +27,12 @@ const VALID_POSITIONS = [
|
|
|
22
27
|
|
|
23
28
|
export class LabelIncantation extends ArgIncantation<LOCAL>
|
|
24
29
|
{
|
|
25
|
-
override readonly
|
|
26
|
-
= "Label a block that evaluates to a point(s)."
|
|
27
|
-
|
|
30
|
+
override readonly effect = Incantation.Effect.LOCAL
|
|
28
31
|
override readonly identifier = "label"
|
|
29
32
|
override readonly requires_arg = true
|
|
30
33
|
override readonly arg_type = Incantation.ArgType.OBJECT
|
|
34
|
+
override readonly description
|
|
35
|
+
= "Label a block that evaluates to a point(s)."
|
|
31
36
|
|
|
32
37
|
override apply(target: Desmos.ExpressionState, data: LabelOptions)
|
|
33
38
|
{
|
|
@@ -84,4 +89,22 @@ export class LabelIncantation extends ArgIncantation<LOCAL>
|
|
|
84
89
|
|
|
85
90
|
return out;
|
|
86
91
|
}
|
|
92
|
+
|
|
93
|
+
override extract(target: Desmos.Expression): Ast.IncantationInvocation<LOCAL> | void
|
|
94
|
+
{
|
|
95
|
+
if (target.label || target.showLabel) {
|
|
96
|
+
return {
|
|
97
|
+
kind: Ast.Kind.INCANTATION_INVOCATION,
|
|
98
|
+
incantation: label,
|
|
99
|
+
arg_raw: super.emit_object_arg({
|
|
100
|
+
text: target.label,
|
|
101
|
+
show: target.showLabel,
|
|
102
|
+
size: target.labelSize,
|
|
103
|
+
pos: target.labelOrientation,
|
|
104
|
+
}),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
87
108
|
}
|
|
109
|
+
|
|
110
|
+
export const label = new LabelIncantation();
|
package/src/magic/local/line.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Incantation, ArgIncantation, type LOCAL } from "../incantation";
|
|
|
2
2
|
|
|
3
3
|
import type { DesmostOptions } from "../../options";
|
|
4
4
|
import type { Fallible } from "../../errors";
|
|
5
|
+
import { Ast } from "../../parser";
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
interface LineOptions
|
|
@@ -16,12 +17,12 @@ const VALID_FIELDS = ["style", "width", "opacity"];
|
|
|
16
17
|
|
|
17
18
|
export class LineIncantation extends ArgIncantation<LOCAL>
|
|
18
19
|
{
|
|
19
|
-
override readonly
|
|
20
|
-
= "Change line styles for a rendered block."
|
|
21
|
-
|
|
20
|
+
override readonly effect = Incantation.Effect.LOCAL
|
|
22
21
|
override readonly identifier = "line"
|
|
23
22
|
override readonly requires_arg = true
|
|
24
23
|
override readonly arg_type = Incantation.ArgType.OBJECT
|
|
24
|
+
override readonly description
|
|
25
|
+
= "Change line styles for a rendered block."
|
|
25
26
|
|
|
26
27
|
override apply(target: Desmos.ExpressionState, data: LineOptions)
|
|
27
28
|
{
|
|
@@ -43,4 +44,25 @@ export class LineIncantation extends ArgIncantation<LOCAL>
|
|
|
43
44
|
|
|
44
45
|
return out;
|
|
45
46
|
}
|
|
47
|
+
|
|
48
|
+
override extract(target: Desmos.Expression): Ast.IncantationInvocation<LOCAL> | void
|
|
49
|
+
{
|
|
50
|
+
if (
|
|
51
|
+
target.lineStyle !== Desmos.Styles.SOLID
|
|
52
|
+
|| target.lineWidth
|
|
53
|
+
|| target.lineOpacity
|
|
54
|
+
) {
|
|
55
|
+
return {
|
|
56
|
+
kind: Ast.Kind.INCANTATION_INVOCATION,
|
|
57
|
+
incantation: line,
|
|
58
|
+
arg_raw: super.emit_object_arg({
|
|
59
|
+
style: target.lineStyle,
|
|
60
|
+
width: target.lineWidth,
|
|
61
|
+
opacity: target.lineOpacity,
|
|
62
|
+
}),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
46
66
|
}
|
|
67
|
+
|
|
68
|
+
export const line = new LineIncantation();
|
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
import { Incantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
|
+
import { Ast } from "../../parser";
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
export class NoLineIncantation extends Incantation<LOCAL>
|
|
5
7
|
{
|
|
8
|
+
override readonly effect = Incantation.Effect.LOCAL
|
|
9
|
+
override readonly identifier = "no-line"
|
|
6
10
|
override readonly description
|
|
7
11
|
= "Disable rendering lines for a block."
|
|
8
|
-
|
|
9
|
-
override readonly identifier = "no-line"
|
|
10
12
|
|
|
11
13
|
override apply(target: Desmos.ExpressionState)
|
|
12
14
|
{
|
|
13
15
|
super.require_expr_type(target.type, "expression");
|
|
14
16
|
target.lines = false;
|
|
15
17
|
}
|
|
18
|
+
|
|
19
|
+
override extract(target: Desmos.Expression): Ast.IncantationInvocation<LOCAL> | void
|
|
20
|
+
{
|
|
21
|
+
if (target.lines === false) {
|
|
22
|
+
return {
|
|
23
|
+
kind: Ast.Kind.INCANTATION_INVOCATION,
|
|
24
|
+
incantation: no_line,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
16
28
|
}
|
|
29
|
+
|
|
30
|
+
export const no_line = new NoLineIncantation();
|
package/src/magic/local/point.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Incantation, ArgIncantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
|
+
import { Ast } from "../../parser";
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
interface PointStyles
|
|
5
7
|
{
|
|
@@ -11,12 +13,12 @@ interface PointStyles
|
|
|
11
13
|
|
|
12
14
|
export class PointIncantation extends ArgIncantation<LOCAL>
|
|
13
15
|
{
|
|
14
|
-
override readonly
|
|
15
|
-
= ""
|
|
16
|
-
|
|
16
|
+
override readonly effect = Incantation.Effect.LOCAL
|
|
17
17
|
override readonly identifier = "point"
|
|
18
18
|
override readonly requires_arg = true
|
|
19
19
|
override readonly arg_type = Incantation.ArgType.OBJECT
|
|
20
|
+
override readonly description
|
|
21
|
+
= ""
|
|
20
22
|
|
|
21
23
|
override apply(target: Desmos.ExpressionState, data: Partial<PointStyles>)
|
|
22
24
|
{
|
|
@@ -26,4 +28,26 @@ export class PointIncantation extends ArgIncantation<LOCAL>
|
|
|
26
28
|
if (data.size != undefined) target.pointSize = data.size;
|
|
27
29
|
if (data.opacity != undefined) target.pointOpacity = data.opacity;
|
|
28
30
|
}
|
|
31
|
+
|
|
32
|
+
override extract(target: Desmos.Expression): Ast.IncantationInvocation<LOCAL> | void
|
|
33
|
+
{
|
|
34
|
+
if (
|
|
35
|
+
target.pointStyle && target.pointStyle !== Desmos.Styles.POINT
|
|
36
|
+
|| target.pointSize
|
|
37
|
+
|| target.pointOpacity
|
|
38
|
+
)
|
|
39
|
+
{
|
|
40
|
+
return {
|
|
41
|
+
kind: Ast.Kind.INCANTATION_INVOCATION,
|
|
42
|
+
incantation: point,
|
|
43
|
+
arg_raw: super.emit_object_arg({
|
|
44
|
+
style: target.pointStyle,
|
|
45
|
+
size: target.pointSize,
|
|
46
|
+
opacity: target.pointOpacity,
|
|
47
|
+
}),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
29
51
|
}
|
|
52
|
+
|
|
53
|
+
export const point = new PointIncantation();
|
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
import { Incantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
|
+
import { Ast } from "../../parser";
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
export class SecretIncantation extends Incantation<LOCAL>
|
|
5
7
|
{
|
|
8
|
+
override readonly effect = Incantation.Effect.LOCAL
|
|
9
|
+
override readonly identifier = "secret"
|
|
6
10
|
override readonly description
|
|
7
11
|
= "Turn a block into a secret expression, which is hidden from the end user."
|
|
8
|
-
|
|
9
|
-
override readonly identifier = "secret"
|
|
10
12
|
|
|
11
13
|
override apply(target: Desmos.ExpressionState)
|
|
12
14
|
{
|
|
13
15
|
super.require_expr_type(target.type, "expression");
|
|
14
16
|
target.secret = true;
|
|
15
17
|
}
|
|
18
|
+
|
|
19
|
+
override extract(target: Desmos.Expression): Ast.IncantationInvocation<LOCAL> | void
|
|
20
|
+
{
|
|
21
|
+
if (target.secret) {
|
|
22
|
+
return {
|
|
23
|
+
kind: Ast.Kind.INCANTATION_INVOCATION,
|
|
24
|
+
incantation: secret,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
16
28
|
}
|
|
29
|
+
|
|
30
|
+
export const secret = new SecretIncantation();
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Incantation, ArgIncantation, type LOCAL } from "../incantation";
|
|
2
2
|
|
|
3
|
+
import { Ast } from "../../parser";
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
interface SliderBounds
|
|
5
7
|
{
|
|
@@ -11,16 +13,29 @@ interface SliderBounds
|
|
|
11
13
|
|
|
12
14
|
export class SliderIncantation extends ArgIncantation<LOCAL>
|
|
13
15
|
{
|
|
14
|
-
override readonly
|
|
15
|
-
= "Set the bounds of the slider for a variable."
|
|
16
|
-
|
|
16
|
+
override readonly effect = Incantation.Effect.LOCAL
|
|
17
17
|
override readonly identifier = "slider"
|
|
18
18
|
override readonly requires_arg = true
|
|
19
19
|
override readonly arg_type = Incantation.ArgType.OBJECT
|
|
20
|
+
override readonly description
|
|
21
|
+
= "Set the bounds of the slider for a variable."
|
|
20
22
|
|
|
21
23
|
override apply(target: Desmos.ExpressionState, data: SliderBounds)
|
|
22
24
|
{
|
|
23
25
|
super.require_expr_type(target.type, "expression");
|
|
24
26
|
target.sliderBounds = data;
|
|
25
27
|
}
|
|
28
|
+
|
|
29
|
+
override extract(target: Desmos.Expression): Ast.IncantationInvocation<LOCAL> | void
|
|
30
|
+
{
|
|
31
|
+
if (target.sliderBounds != undefined) {
|
|
32
|
+
return {
|
|
33
|
+
kind: Ast.Kind.INCANTATION_INVOCATION,
|
|
34
|
+
incantation: slider,
|
|
35
|
+
arg_raw: super.emit_object_arg(target.sliderBounds),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
26
39
|
}
|
|
40
|
+
|
|
41
|
+
export const slider = new SliderIncantation();
|
package/src/parser/ast.ts
CHANGED
|
@@ -3,15 +3,17 @@ import { Incantation, ArgIncantation } from "../magic";
|
|
|
3
3
|
|
|
4
4
|
export namespace Ast
|
|
5
5
|
{
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/**
|
|
7
|
+
* What kind of AST node this is.
|
|
8
|
+
*/
|
|
9
|
+
export enum Kind {
|
|
9
10
|
EXPRESSION = "Expression",
|
|
10
11
|
INCANTATION_INVOCATION = "Incantation-Invocation",
|
|
11
12
|
}
|
|
12
|
-
|
|
13
13
|
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* A Desmos expression to add to the calculator.
|
|
16
|
+
*/
|
|
15
17
|
export interface Expression
|
|
16
18
|
{
|
|
17
19
|
kind: Kind.EXPRESSION
|
|
@@ -19,8 +21,9 @@ export namespace Ast
|
|
|
19
21
|
incantations: IncantationInvocation<Incantation.Effect.LOCAL>[]
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
/**
|
|
25
|
+
* A pending incantation invocation that requires applying its argument (if any), then applying its effect.
|
|
26
|
+
*/
|
|
24
27
|
export type IncantationInvocation<Effect extends Incantation.Effect = Incantation.Effect> =
|
|
25
28
|
| {
|
|
26
29
|
kind: Kind.INCANTATION_INVOCATION
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { GenericParser } from "./generic-parser";
|
|
2
2
|
import { Ast } from "./ast";
|
|
3
|
+
import { NO_MATCH, INVALID_PARSE } from "./errors";
|
|
4
|
+
import type { NoMatch, InvalidParse } from "./errors";
|
|
3
5
|
|
|
4
6
|
import type { DesmostOptions } from "../options";
|
|
5
|
-
import {
|
|
6
|
-
import type { NoMatch, Fallible } from "../errors";
|
|
7
|
+
import { DesmostError, type Fallible } from "../errors";
|
|
7
8
|
import * as utils from "../utils";
|
|
8
9
|
|
|
9
10
|
import {
|
|
@@ -116,7 +117,7 @@ export class DesmostParser extends GenericParser
|
|
|
116
117
|
{
|
|
117
118
|
// 1 global incantation
|
|
118
119
|
try {
|
|
119
|
-
let r = this.try_parse_incantation(GLOBAL_INCANTATIONS);
|
|
120
|
+
let r = this.try_parse_incantation(Object.values(GLOBAL_INCANTATIONS));
|
|
120
121
|
|
|
121
122
|
if (r !== NO_MATCH) {
|
|
122
123
|
this.eat_whitespace();
|
|
@@ -133,7 +134,7 @@ export class DesmostParser extends GenericParser
|
|
|
133
134
|
|
|
134
135
|
while (this.current === "/") {
|
|
135
136
|
try {
|
|
136
|
-
var invocation = this.try_parse_incantation(LOCAL_INCANTATIONS);
|
|
137
|
+
var invocation = this.try_parse_incantation(Object.values(LOCAL_INCANTATIONS));
|
|
137
138
|
}
|
|
138
139
|
catch (e) {
|
|
139
140
|
this.errors.push(e as Error);
|
|
@@ -310,14 +311,17 @@ export class DesmostParser extends GenericParser
|
|
|
310
311
|
return NO_MATCH;
|
|
311
312
|
}
|
|
312
313
|
|
|
313
|
-
let incantation =
|
|
314
|
+
let incantation =
|
|
315
|
+
Object.values(EXPR_INCANTATIONS)
|
|
316
|
+
.find(inc => inc.identifier === ident || inc.alias === ident);
|
|
317
|
+
|
|
314
318
|
if (incantation == undefined) {
|
|
315
319
|
this.i = init;
|
|
316
320
|
return NO_MATCH;
|
|
317
321
|
}
|
|
318
322
|
|
|
319
323
|
/* NOTE: All expression incantations currently require arguments, and all for the foreseeable future will too */
|
|
320
|
-
let arg_raw = this.parse_incantation_arg(
|
|
324
|
+
let arg_raw = this.parse_incantation_arg(incantation.arg_type);
|
|
321
325
|
|
|
322
326
|
let data = {};
|
|
323
327
|
incantation.apply(data, arg_raw);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** The parser failed to parse something (usually during speculative parsing), which only results in internal backtracking. */
|
|
2
|
+
export const NO_MATCH = Symbol("no-match");
|
|
3
|
+
|
|
4
|
+
/** The compiler encountered a non-fatal recoverable failure (usually during speculative parsing), which only results in internal backtracking. */
|
|
5
|
+
export type NoMatch = typeof NO_MATCH & { readonly __brand?: unique symbol };
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export const INVALID_PARSE = Symbol("invalid-parse");
|
|
9
|
+
|
|
10
|
+
export type InvalidParse = typeof INVALID_PARSE & { readonly __brand?: unique symbol };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { NO_MATCH,
|
|
2
|
-
import type { NoMatch,
|
|
1
|
+
import { NO_MATCH, INVALID_PARSE } from "./errors";
|
|
2
|
+
import type { NoMatch, InvalidParse } from "./errors";
|
|
3
|
+
|
|
4
|
+
import { DesmostError, type Fallible } from "../errors";
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
const IGNORED_CHARACTERS = new Set([
|
|
@@ -189,28 +191,24 @@ export class GenericParser
|
|
|
189
191
|
}
|
|
190
192
|
|
|
191
193
|
/**
|
|
192
|
-
* Consume 0 or more space or tab characters.
|
|
194
|
+
* Consume 0 or more space or tab characters (but not newlines).
|
|
195
|
+
*
|
|
196
|
+
* This is always safe to call, and will match 0 characters if the parser is out of bounds.
|
|
193
197
|
*/
|
|
194
198
|
protected eat_whitespace(): void
|
|
195
199
|
{
|
|
196
|
-
/* NOTE: Callers should be able to assume this is safe to call even when at end of input, since it should just match 0 characters */
|
|
197
|
-
if (this.out_of_bounds()) return;
|
|
198
|
-
|
|
199
200
|
while (this.current === ' ' || this.current === '\t') {
|
|
200
201
|
this.advance();
|
|
201
202
|
}
|
|
202
203
|
}
|
|
203
204
|
|
|
204
205
|
/**
|
|
205
|
-
* Consume 0 or more whitespace characters.
|
|
206
|
+
* Consume 0 or more whitespace characters (including newlines).
|
|
206
207
|
*
|
|
207
|
-
*
|
|
208
|
+
* This is always safe to call, and will match 0 characters if the parser is out of bounds.
|
|
208
209
|
*/
|
|
209
210
|
protected eat_newlines(): void
|
|
210
211
|
{
|
|
211
|
-
/* NOTE: Callers should be able to assume this is safe to call even when at end of input, since it should just match 0 characters */
|
|
212
|
-
if (this.i >= this.length) return;
|
|
213
|
-
|
|
214
212
|
while (
|
|
215
213
|
this.current === ' '
|
|
216
214
|
|| this.current === '\n'
|