-
Notifications
You must be signed in to change notification settings - Fork 105
Open
Description
Currently, invalid formulas fail silently or produce cryptic error messages. Game designers using the visual editor need clear, actionable feedback when their formulas contain errors.
Current Behavior
fx.evaluate('ATK * ') // Returns 0 or throws generic error
fx.evaluate('unknown_var + 5') // Silent failure
fx.evaluate('1 / 0') // Returns Infinity (no warning)Proposed Validation API
ValidationResult Interface
interface ValidationError {
code: string
message: string
position: { start: number; end: number }
severity: 'error' | 'warning' | 'info'
suggestion?: string
}
interface ValidationResult {
valid: boolean
errors: ValidationError[]
warnings: ValidationError[]
ast?: FormulaAST // Parsed AST if valid
variables: string[] // Referenced variables
functions: string[] // Referenced functions
}Validation Methods
// Full validation with all checks
const result = fx.validate('ATK * (1 - DEF/100)')
if (!result.valid) {
result.errors.forEach(err => {
console.log(`Error at position ${err.position.start}: ${err.message}`)
if (err.suggestion) {
console.log(` Suggestion: ${err.suggestion}`)
}
})
}
// Quick syntax check only
const isValid = fx.isValidSyntax('ATK + 5')
// Validate with custom variable context
const result = fx.validate('ATK + customVar', {
knownVariables: ['ATK', 'DEF', 'HP'],
strictMode: true // Error on unknown variables
})Error Codes and Messages
Syntax Errors
| Code | Message | Example |
|---|---|---|
E001 |
Unexpected end of expression | ATK * |
E002 |
Missing closing parenthesis | (ATK + DEF |
E003 |
Invalid operator | ATK ** DEF |
E004 |
Empty parentheses | ATK + () * DEF |
E005 |
Adjacent operators | ATK + * DEF |
Semantic Errors
| Code | Message | Example |
|---|---|---|
E101 |
Unknown variable: '{name}' | ATTACK + 5 |
E102 |
Unknown function: '{name}' | sine(45) |
E103 |
Wrong argument count for '{fn}' | max(1) |
E104 |
Type mismatch in operation | "text" + 5 |
Warnings
| Code | Message | Example |
|---|---|---|
W001 |
Division by zero possible | ATK / level |
W002 |
Result may be NaN | sqrt(-1) |
W003 |
Overflow risk | pow(999, 999) |
W004 |
Unused parentheses | ((ATK)) |
W005 |
Always true/false condition | 1 > 0 ? a : b |
Info
| Code | Message | Example |
|---|---|---|
I001 |
Can be simplified | ATK * 1 → ATK |
I002 |
Consider using built-in | a > b ? a : b → max(a, b) |
Real-time Validation for Editor
// Debounced validation for editor integration
const validateDebounced = fx.createValidator({
debounceMs: 300,
strictMode: false,
customVariables: gameContext.getAllVariables()
})
inputField.addEventListener('input', (e) => {
const result = validateDebounced(e.target.value)
updateEditorMarkers(result.errors)
updateAutoComplete(result.variables)
})Position Tracking
const result = fx.validate('ATK + unknownVar * 5')
// result.errors[0]:
// {
// code: 'E101',
// message: "Unknown variable: 'unknownVar'",
// position: { start: 6, end: 16 },
// severity: 'error',
// suggestion: "Did you mean 'ATK' or 'DEF'?"
// }Batch Validation
// Validate multiple formulas efficiently
const results = fx.validateBatch([
{ id: 'damage', formula: 'ATK * crit' },
{ id: 'heal', formula: 'maxHP * 0.1' },
{ id: 'broken', formula: 'ATK +' }
])
results.invalid.forEach(r => {
console.log(`Formula '${r.id}' has errors:`, r.errors)
})Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels