Fix constant definition and comparison bugs found after more thorough testing

This commit is contained in:
SpectralFlame 2022-07-07 05:58:41 -05:00 committed by cyip92
parent 0eed13a421
commit 2f47247be2
4 changed files with 55 additions and 41 deletions

View File

@ -64,11 +64,6 @@ import { AutomatorLexer } from "./lexer";
token: "keyword",
next: "commandArgs"
},
{
regex: /define\s/ui,
token: "keyword",
next: "defineIdentifier"
},
{
regex: /start\s|unlock\s/ui,
token: "keyword",
@ -128,11 +123,6 @@ import { AutomatorLexer } from "./lexer";
{ regex: /\}/ui, dedent: true },
{ regex: /\S+/ui, token: "error" },
],
defineIdentifier: [
commentRule,
{ sol: true, next: "start" },
{ regex: /[a-zA-Z_][a-zA-Z_0-9]*/u, token: "variable", next: "commandArgs" },
],
startUnlock: [
commentRule,
{ sol: true, next: "start" },
@ -166,6 +156,7 @@ import { AutomatorLexer } from "./lexer";
{ regex: / sec(onds ?) ?| min(utes ?) ?| hours ?/ui, token: "variable-2" },
{ regex: /([0-9]+:[0-5][0-9]:[0-5][0-9]|[0-5]?[0-9]:[0-5][0-9]|t[1-4])/ui, token: "number" },
{ regex: /-?(0|[1-9]\d*)(\.\d+)?([eE][+-]?\d+)?/ui, token: "number" },
{ regex: /[a-zA-Z_][a-zA-Z_0-9]*/u, token: "variable" },
{ regex: /\{/ui, indent: true, next: "commandDone" },
// This seems necessary to have a closing curly brace de-indent automatically in some cases
{ regex: /\}/ui, dedent: true },

View File

@ -42,11 +42,12 @@ export const AutomatorCommands = ((() => {
// Extracts the conditional out of a command and returns it as text
function parseConditionalIntoText(ctx) {
const comp = ctx.comparison[0].children;
const getters = comp.compareValue.map(cv => (
cv.children.AutomatorCurrency
? () => cv.children.AutomatorCurrency[0].image
: () => format(cv.children.$value, 2, 2)
));
const getters = comp.compareValue.map(cv => {
if (cv.children.AutomatorCurrency) return () => cv.children.AutomatorCurrency[0].image;
const val = cv.children.$value;
if (typeof val === "string") return () => val;
return () => format(val, 2, 2);
});
const compareFn = comp.ComparisonOperator[0].image;
return `${getters[0]()} ${compareFn} ${getters[1]()}`;
}
@ -368,8 +369,14 @@ export const AutomatorCommands = ((() => {
compile: ctx => {
const duration = ctx.$duration;
return S => {
const dur = ctx.duration[0].children;
const timeString = `${dur.NumberLiteral[0].image} ${dur.TimeUnit[0].image.replace("\\s", "")}`;
let timeString;
if (ctx.duration) {
const c = ctx.duration[0].children;
timeString = `${c.NumberLiteral[0].image} ${c.TimeUnit[0].image}`;
} else {
// This is the case for a defined constant; its value was parsed out during validation
timeString = TimeSpan.fromMilliseconds(duration);
}
if (S.commandState === null) {
S.commandState = { timeMs: 0 };
AutomatorData.logCommandEvent(`Pause started (waiting ${timeString})`, ctx.startLine);
@ -385,10 +392,16 @@ export const AutomatorCommands = ((() => {
};
},
blockify: ctx => {
const c = ctx.duration[0].children;
let blockArg;
if (ctx.duration) {
const c = ctx.duration[0].children;
blockArg = `${c.NumberLiteral[0].image} ${c.TimeUnit[0].image}`;
} else {
blockArg = `${ctx.Identifier[0].image}`;
}
return {
...automatorBlocksMap.PAUSE,
singleTextInput: `${c.NumberLiteral[0].image} ${c.TimeUnit[0].image}`
singleTextInput: blockArg
};
}
},

View File

@ -198,17 +198,21 @@ import { AutomatorLexer } from "./lexer";
return undefined;
}
let studyParts;
switch (type) {
case AUTOMATOR_VAR_TYPES.NUMBER:
case AUTOMATOR_VAR_TYPES.DURATION:
varInfo.value = new Decimal(value);
break;
case AUTOMATOR_VAR_TYPES.STUDIES:
studyParts = value.split("|");
varInfo.value = {
normal: value,
ec: 0
normal: studyParts[0].split(",").map(ts => parseInt(ts, 10)),
ec: parseInt(studyParts[1], 10)
};
break;
case AUTOMATOR_VAR_TYPES.DURATION:
varInfo.value = parseInt(1000 * value, 10);
break;
}
return varInfo;
@ -315,7 +319,7 @@ import { AutomatorLexer } from "./lexer";
ctx.$value = new Decimal(ctx.NumberLiteral[0].image);
} else if (ctx.Identifier) {
const varLookup = this.lookupVar(ctx.Identifier[0], AUTOMATOR_VAR_TYPES.NUMBER);
if (varLookup) ctx.$value = varLookup.value;
if (varLookup) ctx.$value = ctx.Identifier[0].image;
}
}
@ -331,7 +335,7 @@ import { AutomatorLexer } from "./lexer";
}
const T = AutomatorLexer.tokenMap;
if (ctx.ComparisonOperator[0].tokenType === T.OpEQ || ctx.ComparisonOperator[0].tokenType === T.EqualSign) {
this.addError(ctx, "Please use an inequality comparison (>,<,>=,<=)",
this.addError(ctx, "Please use an inequality comparison (>, <, >=, <=)",
"Comparisons cannot be done with equality, only with inequality operators");
}
}
@ -405,9 +409,12 @@ import { AutomatorLexer } from "./lexer";
}
comparison(ctx) {
const getters = ctx.compareValue.map(cv => (
cv.children.AutomatorCurrency ? cv.children.AutomatorCurrency[0].tokenType.$getter : () => cv.children.$value
));
const getters = ctx.compareValue.map(cv => {
if (cv.children.AutomatorCurrency) return cv.children.AutomatorCurrency[0].tokenType.$getter;
const val = cv.children.$value;
if (typeof val === "string") return () => player.reality.automator.constants[val];
return () => val;
});
const compareFun = ctx.ComparisonOperator[0].tokenType.$compare;
return () => compareFun(getters[0](), getters[1]());
}
@ -447,19 +454,17 @@ import { AutomatorLexer } from "./lexer";
}
comparison(ctx) {
const getValue = index => {
const isCurrency = Boolean(ctx.compareValue[index].children.AutomatorCurrency);
if (isCurrency) {
return ctx.compareValue[index].children.AutomatorCurrency[0].image;
}
const valueChildren = ctx.compareValue[index].children;
const isDecimalValue = Boolean(ctx.compareValue[index].children.$value);
return isDecimalValue ? valueChildren.$value.toString() : valueChildren.NumberLiteral[0].image;
const parseInput = index => {
const comp = ctx.compareValue[index];
const isCurrency = Boolean(comp.children.AutomatorCurrency);
if (isCurrency) return comp.children.AutomatorCurrency[0].image;
return comp.children.$value;
};
return {
genericInput1: getValue(0),
compOperator: ctx.ComparisonOperator[0].image,
genericInput2: getValue(1),
genericInput1: parseInput(0),
genericInput2: parseInput(1),
};
}

View File

@ -364,16 +364,21 @@ export const AutomatorLexer = (() => {
const automatorCurrencyNames = tokenLists.AutomatorCurrency.map(i => i.$autocomplete.toUpperCase());
const standardizeAutomatorValues = function(x) {
// This first line exists for this function to usually return quickly;
// otherwise it's called enough to cause lag.
if (automatorCurrencyNames.includes(x.toUpperCase())) return x.toUpperCase();
try {
if (automatorCurrencyNames.includes(x.toUpperCase())) return x.toUpperCase();
} catch {
// This only happens if the input is a number or Decimal, in which case we don't attempt to change any formatting
// and simply return
return x;
}
for (const i of tokenLists.AutomatorCurrency) {
// Check for a match of the full string.
if (x.match(i.PATTERN) && x.match(i.PATTERN)[0].length === x.length) {
return i.$autocomplete.toUpperCase();
}
}
// If we get to this point, we haven't matched a currency name and instead assume it's a constant and return it
// If we get to this point, we haven't matched a currency name and instead assume it's a defined constant and
// return it without any format changes since these are case-sensitive
return x;
};