diff --git a/CHANGELOG.md b/CHANGELOG.md index e568a20a1..13601b416 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Dates are in `YYYY-MM-DD` format and versions are in [semantic versioning](http: - [#514](https://github.com/wordplaydev/wordplay/issues/514) Fixed cursor position on hidden language tags. - Fixed parsing bug that prevented complete parsing of the program. - Fixed reactivity dependency bug that included evaluates in branch dependencies. +- Fixed selection of locale in evaluation. ## 0.10.4 2024-07-08 diff --git a/src/components/app/PlayView.svelte b/src/components/app/PlayView.svelte index e17312a48..ba1ef827e 100644 --- a/src/components/app/PlayView.svelte +++ b/src/components/app/PlayView.svelte @@ -16,7 +16,7 @@ let evaluator: Evaluator; let latest: Value | undefined = undefined; $: { - evaluator = new Evaluator(project, DB, $locales); + evaluator = new Evaluator(project, DB, $locales.getLocales()); if (evaluator) { evaluator.stop(); evaluator.ignore(update); diff --git a/src/components/app/ProjectPreview.svelte b/src/components/app/ProjectPreview.svelte index 9fd0420bd..e565c1ef5 100644 --- a/src/components/app/ProjectPreview.svelte +++ b/src/components/app/ProjectPreview.svelte @@ -34,7 +34,12 @@ $: path = link ?? project.getLink(true); function updatePreview() { - const evaluator = new Evaluator(project, DB, $locales, false); + const evaluator = new Evaluator( + project, + DB, + $locales.getLocales(), + false, + ); const value = evaluator.getInitialValue(); evaluator.stop(); const stage = value ? toStage(evaluator, value) : undefined; diff --git a/src/components/concepts/ExampleUI.svelte b/src/components/concepts/ExampleUI.svelte index 7a9d78012..4b0276071 100644 --- a/src/components/concepts/ExampleUI.svelte +++ b/src/components/concepts/ExampleUI.svelte @@ -35,7 +35,7 @@ if (evaluator) evaluator.ignore(update); if (evaluated) { - evaluator = new Evaluator(project, DB, $locales); + evaluator = new Evaluator(project, DB, $locales.getLocales()); evaluator.observe(update); evaluator.start(); } else { diff --git a/src/components/project/ProjectView.svelte b/src/components/project/ProjectView.svelte index df20f0e71..dec546bfd 100644 --- a/src/components/project/ProjectView.svelte +++ b/src/components/project/ProjectView.svelte @@ -125,8 +125,9 @@ import { AnimationFactorIcons } from '@db/AnimationFactorSetting'; import { COPY_SYMBOL } from '@parser/Symbols'; import CopyButton from './CopyButton.svelte'; - import { toLocaleString } from '@locale/Locale'; + import { toLocaleString, type Locale } from '@locale/Locale'; import { default as ModeChooser } from '@components/widgets/Mode.svelte'; + import DefaultLocale from '@locale/DefaultLocale'; export let project: Project; export let original: Project | undefined = undefined; @@ -227,6 +228,9 @@ }); setContext(KeyModfifierSymbol, keyModifiers); + /** Keep a currently selected output locale to send to the Evaluator for evaluation and rendering */ + let evaluationLocale: Locale | undefined; + // When keyboard edit idle changes to true, set a timeout // to reset it to false after a delay. $: { @@ -324,7 +328,10 @@ const newEvaluator = new Evaluator( newProject, DB, - newProject.getLocales(), + // Choose the selected evaluation locale or if not selected, currently selected IDE locale + evaluationLocale + ? [evaluationLocale, DefaultLocale] + : $locales.getLocales(), true, replayInputs ? $evaluator : undefined, ); diff --git a/src/edit/OutputExpression.ts b/src/edit/OutputExpression.ts index 06a0102b0..9bde036a8 100644 --- a/src/edit/OutputExpression.ts +++ b/src/edit/OutputExpression.ts @@ -136,7 +136,7 @@ export default class OutputExpression { expression instanceof Expression ? expression : undefined, value: expression instanceof Literal - ? expression.getValue(this.locales) + ? expression.getValue(this.locales.getLocales()) : undefined, }; } diff --git a/src/edit/OutputProperties.ts b/src/edit/OutputProperties.ts index 712baee20..970406ac0 100644 --- a/src/edit/OutputProperties.ts +++ b/src/edit/OutputProperties.ts @@ -27,7 +27,7 @@ function getPoseProperty(project: Project, name: NameAndDoc): OutputProperty { expr instanceof Evaluate && (expr.is(project.shares.output.Pose, context) || expr.is(project.shares.output.Sequence, context)), - (locales) => createPoseLiteral(project, locales) + (locales) => createPoseLiteral(project, locales), ); } @@ -38,7 +38,7 @@ export function getDurationProperty(locales: Locales): OutputProperty { false, false, (expr) => expr instanceof NumberLiteral, - () => NumberLiteral.make(0.25, Unit.create(['s'])) + () => NumberLiteral.make(0.25, Unit.create(['s'])), ); } @@ -51,26 +51,26 @@ export function getStyleProperty(locales: Locales): OutputProperty { ...all, ...(Array.isArray(next) ? next : [next]), ], - [] + [], ), true, (text: string) => TextLiteral.make(text), (expression: Expression | undefined) => expression instanceof TextLiteral - ? expression.getValue(locales).text - : undefined + ? expression.getValue(locales.getLocales()).text + : undefined, ), false, false, (expr) => expr instanceof TextLiteral, - () => TextLiteral.make(DefaultStyle) + () => TextLiteral.make(DefaultStyle), ); } // All type output has these properties. export function getTypeOutputProperties( project: Project, - locales: Locales + locales: Locales, ): OutputProperty[] { return [ new OutputProperty( @@ -79,7 +79,7 @@ export function getTypeOutputProperties( false, true, (expr) => expr instanceof NumberLiteral, - () => NumberLiteral.make(1, Unit.meters()) + () => NumberLiteral.make(1, Unit.meters()), ), new OutputProperty( locales.get((l) => l.output.Phrase.face), @@ -89,13 +89,13 @@ export function getTypeOutputProperties( (text: string) => TextLiteral.make(text), (expression: Expression | undefined) => expression instanceof TextLiteral - ? expression.getValue(locales).text - : undefined + ? expression.getValue(locales.getLocales()).text + : undefined, ), false, true, (expr) => expr instanceof TextLiteral, - () => TextLiteral.make(locales.get((l) => l.ui.font.app)) + () => TextLiteral.make(locales.get((l) => l.ui.font.app)), ), new OutputProperty( locales.get((l) => l.output.Phrase.place), @@ -111,14 +111,14 @@ export function getTypeOutputProperties( Evaluate.make( Reference.make( locales.getName(project.shares.output.Place.names), - project.shares.output.Place + project.shares.output.Place, ), [ NumberLiteral.make(0, Unit.meters()), NumberLiteral.make(0, Unit.meters()), NumberLiteral.make(0, Unit.meters()), - ] - ) + ], + ), ), ...getOutputProperties(project, locales), ]; @@ -128,7 +128,7 @@ export function getTypeOutputProperties( // All type output has these properties, in this order. export function getOutputProperties( project: Project, - locales: Locales + locales: Locales, ): OutputProperty[] { return [ new OutputProperty( @@ -137,7 +137,7 @@ export function getOutputProperties( false, false, (expr) => expr instanceof TextLiteral, - () => TextLiteral.make('') + () => TextLiteral.make(''), ), new OutputProperty( locales.get((l) => l.output.Phrase.selectable), @@ -145,24 +145,24 @@ export function getOutputProperties( false, false, (expr) => expr instanceof BooleanLiteral, - () => BooleanLiteral.make(false) + () => BooleanLiteral.make(false), ), ...getPoseProperties(project, locales, true), getPoseProperty( project, - locales.get((l) => l.output.Phrase.entering) + locales.get((l) => l.output.Phrase.entering), ), getPoseProperty( project, - locales.get((l) => l.output.Phrase.resting) + locales.get((l) => l.output.Phrase.resting), ), getPoseProperty( project, - locales.get((l) => l.output.Phrase.moving) + locales.get((l) => l.output.Phrase.moving), ), getPoseProperty( project, - locales.get((l) => l.output.Phrase.exiting) + locales.get((l) => l.output.Phrase.exiting), ), getDurationProperty(locales), getStyleProperty(locales), diff --git a/src/examples/examples.test.ts b/src/examples/examples.test.ts index b16ab722a..e4a039d0e 100644 --- a/src/examples/examples.test.ts +++ b/src/examples/examples.test.ts @@ -170,7 +170,12 @@ test.each([...projects])( `Ensure $name doesn't evaluate to exception`, async (example: SerializedProject) => { const project = await Project.deserialize(Locales, example); - const evaluator = new Evaluator(project, DB, DefaultLocales, false); + const evaluator = new Evaluator( + project, + DB, + DefaultLocales.getLocales(), + false, + ); const value = evaluator.getInitialValue(); evaluator.stop(); expect(value).not.toBeInstanceOf(ExceptionValue); diff --git a/src/nodes/FormattedLiteral.ts b/src/nodes/FormattedLiteral.ts index 729991fe8..cbaec3f98 100644 --- a/src/nodes/FormattedLiteral.ts +++ b/src/nodes/FormattedLiteral.ts @@ -146,8 +146,8 @@ export default class FormattedLiteral extends Literal { return Glyphs.Formatted; } - getValue(locales: Locales): Value { - const preferred = this.getPreferredText(locales.getLocales()); + getValue(locales: Locale[]): Value { + const preferred = this.getPreferredText(locales); return new MarkupValue(this, preferred.markup); } diff --git a/src/nodes/Literal.ts b/src/nodes/Literal.ts index 7e907320e..901a66d82 100644 --- a/src/nodes/Literal.ts +++ b/src/nodes/Literal.ts @@ -6,7 +6,7 @@ import SimpleExpression from './SimpleExpression'; import type Expression from './Expression'; import Purpose from '../concepts/Purpose'; import type Context from './Context'; -import type Locales from '../locale/Locales'; +import type Locale from '@locale/Locale'; export default abstract class Literal extends SimpleExpression { constructor() { @@ -29,8 +29,8 @@ export default abstract class Literal extends SimpleExpression { evaluate(evaluator: Evaluator, prior: Value | undefined): Value { if (prior) return prior; - return this.getValue(evaluator.locales); + return this.getValue(evaluator.getLocales()); } - abstract getValue(locales: Locales): Value; + abstract getValue(locales: Locale[]): Value; } diff --git a/src/nodes/Program.test.ts b/src/nodes/Program.test.ts index 84adeb49b..3c77df440 100644 --- a/src/nodes/Program.test.ts +++ b/src/nodes/Program.test.ts @@ -6,7 +6,6 @@ import Project from '../models/Project'; import type Value from '../values/Value'; import { DB } from '../db/Database'; import DefaultLocale from '../locale/DefaultLocale'; -import Locales from '../locale/Locales'; test.each([ // A single source with 1 should evaluate to 1 @@ -23,14 +22,12 @@ test.each([ code .slice(1) .map((code, index) => new Source(`sup${index + 1}`, code)), - DefaultLocale + DefaultLocale, ); - const value = new Evaluator( - project, - DB, - new Locales([DefaultLocale], DefaultLocale) - ).getInitialValue(); + const value = new Evaluator(project, DB, [ + DefaultLocale, + ]).getInitialValue(); expect(value).toBeDefined(); expect((value as Value).constructor).toBe(valueType); - } + }, ); diff --git a/src/nodes/Reaction.test.ts b/src/nodes/Reaction.test.ts index 264ab141a..a0cb97a6d 100644 --- a/src/nodes/Reaction.test.ts +++ b/src/nodes/Reaction.test.ts @@ -11,7 +11,6 @@ import Reaction from './Reaction'; import ExpectedStream from '../conflicts/ExpectedStream'; import { DB } from '../db/Database'; import DefaultLocale from '../locale/DefaultLocale'; -import Locales from '../locale/Locales'; const makeOne = (creator: Expression) => Time.make(creator, 1); @@ -46,16 +45,12 @@ test.each([ code: string, value: (expression: Expression) => Value, expectedInitial: string, - expectedNext: string + expectedNext: string, ) => { // Make the project const source = new Source('test', code); const project = Project.make(null, 'test', source, [], DefaultLocale); - const evaluator = new Evaluator( - project, - DB, - new Locales([DefaultLocale], DefaultLocale) - ); + const evaluator = new Evaluator(project, DB, [DefaultLocale]); evaluator.start(); @@ -75,7 +70,7 @@ test.each([ const actualNext = evaluator.getLatestSourceValue(source); expect(actualNext?.toString()).toBe(expectedNext); evaluator.stop(); - } + }, ); testConflict('1 … ∆ Time() … 1 + .', '1 … ⊤ … 1 + .', Reaction, ExpectedStream); diff --git a/src/nodes/TextLiteral.ts b/src/nodes/TextLiteral.ts index c59d6da2e..9347638fd 100644 --- a/src/nodes/TextLiteral.ts +++ b/src/nodes/TextLiteral.ts @@ -178,9 +178,9 @@ export default class TextLiteral extends Literal { : getPreferred(locales, this.texts); } - getValue(locales: Locales): TextValue { + getValue(locales: Locale[]): TextValue { // Get the alternatives - const best = this.getLocaleText(locales.getLocales()); + const best = this.getLocaleText(locales); return new TextValue( this, best.getText(), diff --git a/src/runtime/Evaluator.test.ts b/src/runtime/Evaluator.test.ts index 2d8de1b81..444902f9b 100644 --- a/src/runtime/Evaluator.test.ts +++ b/src/runtime/Evaluator.test.ts @@ -15,7 +15,7 @@ test.each([0, 1, 10, 15])('Step back %i', (steps: number) => { const source = new Source('test', fib); const project = Project.make(null, 'test', source, [], DefaultLocale); - const evaluator = new Evaluator(project, DB, DefaultLocales); + const evaluator = new Evaluator(project, DB, DefaultLocales.getLocales()); evaluator.start(); const stepIndex = evaluator.getStepIndex(); @@ -38,7 +38,7 @@ test('Too many steps', () => { const source = new Source('test', fib); const project = Project.make(null, 'test', source, [], DefaultLocale); - const evaluator = new Evaluator(project, DB, DefaultLocales); + const evaluator = new Evaluator(project, DB, DefaultLocales.getLocales()); const value = evaluator.getInitialValue(); expect(value).toBeInstanceOf(StepLimitException); }); @@ -51,7 +51,7 @@ test('Too many evaluations', () => { const source = new Source('test', fib); const project = Project.make(null, 'test', source, [], DefaultLocale); - const evaluator = new Evaluator(project, DB, DefaultLocales); + const evaluator = new Evaluator(project, DB, DefaultLocales.getLocales()); const value = evaluator.getInitialValue(); expect(value).toBeInstanceOf(EvaluationLimitException); }); diff --git a/src/runtime/Evaluator.ts b/src/runtime/Evaluator.ts index d3985f5bd..b6382e1c5 100644 --- a/src/runtime/Evaluator.ts +++ b/src/runtime/Evaluator.ts @@ -37,7 +37,6 @@ import NumberGenerator from 'recoverable-random'; import type { Database } from '../db/Database'; import ReactionStream from '../values/ReactionStream'; import type Animator from '../output/Animator'; -import Locales from '../locale/Locales'; import DefaultLocale from '../locale/DefaultLocale'; import StructureValue from '@values/StructureValue'; import ListValue from '@values/ListValue'; @@ -83,7 +82,7 @@ export default class Evaluator { readonly project: Project; /** The preferred locales for evaluation. */ - readonly locales: Locales; + readonly locales: Locale[]; /** The database that contains settings for evaluation */ readonly database: Database; @@ -259,7 +258,7 @@ export default class Evaluator { constructor( project: Project, database: Database, - locales: Locales, + locales: Locale[], reactive = true, prior: Evaluator | undefined = undefined, ) { @@ -313,11 +312,10 @@ export default class Evaluator { ), locale, ); - return new Evaluator( - project, - database, - new Locales([locale], DefaultLocale), - ).getInitialValue(); + return new Evaluator(project, database, [ + locale, + DefaultLocale, + ]).getInitialValue(); } /** Mirror the given evaluator's stream history and state, but with the new source. */ @@ -434,7 +432,7 @@ export default class Evaluator { /** Get the currently selected locales from the database */ getLocales() { - return this.locales.getLocales(); + return this.locales; } getCurrentEvaluation() { diff --git a/src/runtime/evaluate.ts b/src/runtime/evaluate.ts index 847f407c6..e355fdfe6 100644 --- a/src/runtime/evaluate.ts +++ b/src/runtime/evaluate.ts @@ -13,7 +13,7 @@ import Evaluator from './Evaluator'; export default function evaluateCode( main: string, supplements?: string[], - locales?: Locales + locales?: Locales, ): Value | undefined { const source = new Source('test', main); const project = Project.make( @@ -21,16 +21,13 @@ export default function evaluateCode( 'test', source, (supplements ?? []).map( - (code, index) => new Source(`sup${index + 1}`, code) + (code, index) => new Source(`sup${index + 1}`, code), ), - locales?.getLocales() ?? DefaultLocale + locales?.getLocales() ?? DefaultLocale, ); return new Evaluator( project, DB, - new Locales( - locales === undefined ? [DefaultLocale] : locales.getLocales(), - DefaultLocale - ) + locales === undefined ? [DefaultLocale] : locales.getLocales(), ).getInitialValue(); }