import { isConstantNode, isNode, type MathNode } from 'mathjs'; import type { Result } from './interface.js'; import { serialize } from './serialize.js'; import type { State } from './state.js'; import { migrateNode } from './node.js'; import { globalFnName } from './utils.js'; /** 转换 AST */ export function toBoolean(state: State, node: MathNode | Result): Result { const helper = (): void => { state.helper( "fn @@to_boolean { if it is nil { nil } else { it != '' && it != '0' && it != 0 && it is not nan && it != false } }", ); }; if (!isNode(node)) { if (node.type === 'boolean') return node; if (node.as_boolean) { return { type: 'boolean', code: node.as_boolean, }; } helper(); return { type: 'boolean', code: `@@to_boolean(${node.code})`, }; } if (isConstantNode(node)) { const lit = Boolean(node.value); return { type: 'boolean', literal: lit, code: serialize(lit), }; } const migrated = migrateNode(state, node, { format: 'no-paren' }); return toBoolean(state, migrated); } /** 转换 AST */ export function toString(state: State, node: MathNode | Result): Result { if (!isNode(node)) { if (node.type === 'string') return node; if (node.as_string) { return { type: 'string', code: node.as_string, }; } if (node.type === 'number' && node.literal !== undefined) { const lit = String(node.literal); return { type: 'string', literal: lit, code: serialize(lit), }; } return { type: 'string', code: `${globalFnName(state, 'to_string')}(${node.code})`, }; } if (isConstantNode(node)) { const lit = String(node.value); return { type: 'string', literal: lit, code: serialize(lit), }; } const migrated = migrateNode(state, node, { format: 'no-paren' }); return toString(state, migrated); } /** 转换 AST */ export function toNumber(state: State, node: MathNode | Result): Result { if (!isNode(node)) { if (node.type === 'number') return node; if (node.as_number) { return { type: 'number', code: node.as_number, }; } if ((node.type === 'string' || node.type === 'boolean') && node.literal !== undefined) { const lit = Number(node.literal); return { type: 'number', literal: lit, code: serialize(lit), }; } return { type: 'number', code: `${globalFnName(state, 'to_number')}(${node.code})`, }; } if (isConstantNode(node)) { const lit = Number(node.value); return { type: 'number', literal: lit, code: serialize(lit), }; } const migrated = migrateNode(state, node, { format: 'no-paren' }); return toNumber(state, migrated); }