import { Variables } from './Variables/Variables' ; import { Variable } from './Variables/Variable' ; import { CommandInterface } from './Commands' ; import * as Constants from './Constants' ; export class Expression { private static readonly CLEAN_REGEX = /\s*'\s*/g ; public static evaluate ( expression , runtime , ctx , callback ) { if ( ctx === Constants . CTX_CONSOLE ) { runtime . execute ( expression ) ; callback ( '' ) ; } else { const hoverExpression = expression . replace ( Expression . CLEAN_REGEX , '' ) ; if ( hoverExpression !== '' ) { Expression . type ( hoverExpression , runtime , ( value , type ) => { if ( value === undefined && type === undefined ) { callback ( Constants . EVAL_UNDEF ) ; } else if ( ctx === Constants . CTX_HOVER || ctx === Constants . CTX_WATCH ) { Expression . handleHover ( hoverExpression , runtime , value , type , callback ) ; } else { Expression . forceEvaluate ( expression , runtime , callback ) ; } } ) ; } else { callback ( Constants . EVAL_UNDEF ) ; } } } public static handleHover ( expression , runtime , val , type , callback ) { if ( type !== undefined && ( type === 'file' || type === 'function' ) ) { callback ( val ) ; } else { Expression . loadAsVariable ( expression , runtime , callback ) ; } } public static loadAsVariable ( expression , runtime , callback ) { Variables . loadVariable ( expression , runtime , ( v ) => { if ( v === null ) { Variables . getSize ( expression , runtime , ( size ) => { if ( Variables . loadable ( size ) ) { Expression . forceEvaluate ( expression , runtime , callback ) ; } else { callback ( size . join ( Constants . SIZE_SEPARATOR ) ) ; } } ) ; } else { callback ( v . value ( ) ) ; } } ) ; } public static forceEvaluate ( expression , runtime , callback ) { runtime . evaluateAsLine ( expression , ( output ) => { callback ( Variables . removeName ( expression , output ) ) ; } ) ; } public static type ( expression , runtime , callback ) { const typeRegex = new RegExp ( `^.*'${ expression }' is (?:a|the) (?:built-in )?(\\S+).*$` ) ; let val = undefined ; let type = undefined ; runtime . evaluate ( `which ${ expression }` , ( output ) => { output . forEach ( line => { const match = line . match ( typeRegex ) ; if ( match !== null ) { val = line ; type = match [ 1 ] ; } else if ( val === undefined && line . length !== 0 ) { val = '' ; } } ) ; callback ( val , type ) ; } ) ; } }