import { toException } from "./exceptions" ; import { GetValueT , SetValueT } from "./nodeTypes" ; import { Continuation , Environment , EnvironmentBase , PartialErrorContinuation } from "./types" ; type EnvironmentLike = EnvironmentBase | Environment | any ; export function isEnvironment ( env ) { return typeof env === "object" && "values" in env ; } export function toEnvironment ( environment ? ) { return environment ? ( isEnvironment ( environment ) ? environment : { values : environment } ) : { values : { } } ; } export function createEnvironment ( environmentLike , prev ? ) { return { ... toEnvironment ( environmentLike ) , ... { prev : prev && toEnvironment ( prev ) } } ; } export function getEnvironmentBy ( env , condition ) { let _env = env ; while ( _env ) { if ( condition ( _env ) ) { return _env ; } _env = _env . prev ; } return null ; } export function getEnvironmentForValue ( env , name ) { return getEnvironmentBy ( env , ( env ) => name in env . values ) ; } export const getSuperEnv = ( name , closestEnv ) => { const { prev } = closestEnv ; if ( prev ) { return getEnvironmentForValue ( prev , name ) ; } else { throw new Error ( "Provided environment doesn't have outer (prev) environment to search in." ) ; } } ; export function SetValue < T > ( { name , value , isDeclaration } , c , cerr , env ) { let writableEnv = env ; while ( writableEnv && writableEnv . internal ) { writableEnv = writableEnv . prev ; } if ( ! writableEnv ) { return cerr ( toException ( new Error ( `Can't write to '${ name }' value.` ) ) ) ; } if ( isDeclaration ) { c ( ( writableEnv . values [ name ] = value ) ) ; } else { const _env = getEnvironmentForValue ( writableEnv , name ) ; if ( _env ) { c ( ( _env . values [ name ] = value ) ) ; } else { cerr ( { type : "Error" , value : new ReferenceError ( `'${ name }' is not defined.` ) } ) ; } } } export function GetValue < T > ( { name } , c , cerr , env ) { let _env = env ; do { if ( Object . hasOwnProperty . call ( _env . values , name ) ) { return c ( _env . values [ name ] ) ; } } while ( ( _env = _env . prev ) ) ; cerr ( { type : "Error" , value : new ReferenceError ( `"${ name }" is not defined.` ) } ) ; } export const createInternalEnv = ( values , prev ? ) => < const > { ... createEnvironment ( values , prev ) , internal : true } ;