type environment = GenericDist.env @genType.opaque type rec value = | IEvArray(arrayValue) | IEvArrayString(array) | IEvBool(bool) // | IEvCall(string) // External function call | IEvDate(Js.Date.t) | IEvDeclaration(lambdaDeclaration) | IEvDistribution(DistributionTypes.genericDist) | IEvLambda(lambdaValue) | IEvBindings(nameSpace) | IEvNumber(float) | IEvRecord(map) | IEvString(string) // | IEvSymbol(string) | IEvTimeDuration(float) | IEvType(map) | IEvTypeIdentifier(string) | IEvVoid @genType.opaque and arrayValue = array @genType.opaque and map = Belt.Map.String.t @genType.opaque and nameSpace = NameSpace(Belt.MutableMap.String.t, option) @genType.opaque and lambdaValue = | LNoFFI({ parameters: array, context: nameSpace, body: (array, environment, reducerFn) => value, }) | LFFI({ body: (array, environment, reducerFn) => value, }) @genType.opaque and lambdaDeclaration = Declaration.declaration and expression = | EBlock(array) | EProgram(array) // programs are similar to blocks, but don't create an inner scope. there can be only one program at the top level of the expression. | EArray(array) | ERecord(Belt.Map.String.t) | ESymbol(string) | ETernary(expression, expression, expression) | EAssign(string, expression) | ECall(expression, array) | ELambda(array, expression) | EValue(value) and context = { bindings: nameSpace, environment: environment, } and reducerFn = (expression, context) => value