module ErrorValue = Reducer_ErrorValue module ExternalExpressionValue = ReducerInterface_ExpressionValue module Extra_Array = Reducer_Extra_Array type internalCode = ExternalExpressionValue.internalCode type environment = ExternalExpressionValue.environment let defaultEnvironment = ExternalExpressionValue.defaultEnvironment type rec expressionValue = | IevArray(array) // FIXME: Convert | IevArrayString(array) // FIXME: Convert | IevBool(bool) | IevCall(string) // External function call | IevDate(Js.Date.t) | IevDeclaration(lambdaDeclaration) | IevDistribution(DistributionTypes.genericDist) | IevLambda(lambdaValue) | IevModule(nameSpace) // FIXME: Convert | IevNumber(float) | IevRecord(map) | IevString(string) | IevSymbol(string) | IevTimeDuration(float) | IevTypeIdentifier(string) and map = Belt.Map.String.t and nameSpace = NameSpace(Belt.Map.String.t) and tmpExternalBindings = Js.Dict.t // FIXME: Remove and lambdaValue = { parameters: array, context: nameSpace, body: internalCode, } and lambdaDeclaration = Declaration.declaration type t = expressionValue type functionCall = (string, array) let rec toString = aValue => switch aValue { | IevArray(anArray) => { let args = anArray->Js.Array2.map(each => toString(each))->Js.Array2.toString `[${args}]` } | IevArrayString(anArray) => { let args = anArray->Js.Array2.toString `[${args}]` } | IevBool(aBool) => Js.String.make(aBool) | IevCall(fName) => `:${fName}` | IevDate(date) => DateTime.Date.toString(date) | IevDeclaration(d) => Declaration.toString(d, r => toString(IevLambda(r))) | IevDistribution(dist) => GenericDist.toString(dist) | IevLambda(lambdaValue) => `lambda(${Js.Array2.toString(lambdaValue.parameters)}=>internal code)` | IevModule(m) => `@${m->toStringNameSpace}` | IevNumber(aNumber) => Js.String.make(aNumber) | IevRecord(aMap) => aMap->toStringMap | IevString(aString) => `'${aString}'` | IevSymbol(aString) => `:${aString}` | IevTimeDuration(t) => DateTime.Duration.toString(t) | IevTypeIdentifier(id) => `#${id}` } and toStringMap = aMap => { let pairs = aMap ->Belt.Map.String.toArray ->Js.Array2.map(((eachKey, eachValue)) => `${eachKey}: ${toString(eachValue)}`) ->Js.Array2.toString `{${pairs}}` } and toStringNameSpace = nameSpace => { let NameSpace(container) = nameSpace container->toStringMap } let toStringWithType = aValue => switch aValue { | IevArray(_) => `Array::${toString(aValue)}` | IevArrayString(_) => `ArrayString::${toString(aValue)}` | IevBool(_) => `Bool::${toString(aValue)}` | IevCall(_) => `Call::${toString(aValue)}` | IevDistribution(_) => `Distribution::${toString(aValue)}` | IevLambda(_) => `Lambda::${toString(aValue)}` | IevNumber(_) => `Number::${toString(aValue)}` | IevRecord(_) => `Record::${toString(aValue)}` | IevString(_) => `String::${toString(aValue)}` | IevSymbol(_) => `Symbol::${toString(aValue)}` | IevDate(_) => `Date::${toString(aValue)}` | IevTimeDuration(_) => `Date::${toString(aValue)}` | IevDeclaration(_) => `Declaration::${toString(aValue)}` | IevTypeIdentifier(_) => `TypeIdentifier::${toString(aValue)}` | IevModule(_) => `Module::${toString(aValue)}` } let argsToString = (args: array): string => { args->Js.Array2.map(arg => arg->toString)->Js.Array2.toString } let toStringFunctionCall = ((fn, args)): string => `${fn}(${argsToString(args)})` let toStringResult = x => switch x { | Ok(a) => `Ok(${toString(a)})` | Error(m) => `Error(${ErrorValue.errorToString(m)})` } let toStringResultOkless = (codeResult: result): string => switch codeResult { | Ok(a) => toString(a) | Error(m) => `Error(${ErrorValue.errorToString(m)})` } let toStringResultRecord = x => switch x { | Ok(a) => `Ok(${ExternalExpressionValue.toStringRecord(a)})` | Error(m) => `Error(${ErrorValue.errorToString(m)})` } type expressionValueType = | EvtArray | EvtArrayString | EvtBool | EvtCall | EvtDistribution | EvtLambda | EvtNumber | EvtRecord | EvtString | EvtSymbol | EvtDate | EvtTimeDuration | EvtDeclaration | EvtTypeIdentifier | EvtModule type functionCallSignature = CallSignature(string, array) type functionDefinitionSignature = FunctionDefinitionSignature(functionCallSignature, expressionValueType) let valueToValueType = value => switch value { | IevArray(_) => EvtArray | IevArrayString(_) => EvtArrayString | IevBool(_) => EvtBool | IevCall(_) => EvtCall | IevDistribution(_) => EvtDistribution | IevLambda(_) => EvtLambda | IevNumber(_) => EvtNumber | IevRecord(_) => EvtRecord | IevString(_) => EvtString | IevSymbol(_) => EvtSymbol | IevDate(_) => EvtDate | IevTimeDuration(_) => EvtTimeDuration | IevDeclaration(_) => EvtDeclaration | IevTypeIdentifier(_) => EvtTypeIdentifier | IevModule(_) => EvtModule } let functionCallToCallSignature = (functionCall: functionCall): functionCallSignature => { let (fn, args) = functionCall CallSignature(fn, args->Js.Array2.map(valueToValueType)) } let valueTypeToString = (valueType: expressionValueType): string => switch valueType { | EvtArray => `Array` | EvtArrayString => `ArrayString` | EvtBool => `Bool` | EvtCall => `Call` | EvtDistribution => `Distribution` | EvtLambda => `Lambda` | EvtNumber => `Number` | EvtRecord => `Record` | EvtString => `String` | EvtSymbol => `Symbol` | EvtDate => `Date` | EvtTimeDuration => `Duration` | EvtDeclaration => `Declaration` | EvtTypeIdentifier => `TypeIdentifier` | EvtModule => `Module` } let functionCallSignatureToString = (functionCallSignature: functionCallSignature): string => { let CallSignature(fn, args) = functionCallSignature `${fn}(${args->Js.Array2.map(valueTypeToString)->Js.Array2.toString})` } let rec toExternal = (iev: expressionValue): ExternalExpressionValue.expressionValue => { switch iev { | IevArray(v) => v->Belt.Array.map(e => toExternal(e))->EvArray | IevArrayString(v) => EvArrayString(v) | IevBool(v) => EvBool(v) | IevCall(v) => EvCall(v) | IevDistribution(v) => EvDistribution(v) | IevLambda(v) => EvLambda(lambdaValueToExternal(v)) | IevNumber(v) => EvNumber(v) | IevRecord(v) => v->mapToExternal->EvRecord | IevString(v) => EvString(v) | IevSymbol(v) => EvSymbol(v) | IevDate(v) => EvDate(v) | IevTimeDuration(v) => EvTimeDuration(v) | IevDeclaration(v) => { let fn = lambdaValueToExternal(v.fn) let args = v.args EvDeclaration({fn: fn, args: args}) } | IevTypeIdentifier(v) => EvTypeIdentifier(v) | IevModule(v) => v->nameSpaceToTypeScriptBindings->EvModule } } and mapToExternal = v => v->Belt.Map.String.map(e => toExternal(e))->Belt.Map.String.toArray->Js.Dict.fromArray and lambdaValueToExternal = v => { let p = v.parameters let c = v.context->nameSpaceToTypeScriptBindings let b = v.body {parameters: p, context: c, body: b} } and nameSpaceToTypeScriptBindings = ( nameSpace: nameSpace, ): ReducerInterface_ExpressionValue.externalBindings => { let NameSpace(container) = nameSpace Belt.Map.String.map(container, e => toExternal(e))->Belt.Map.String.toArray->Js.Dict.fromArray } let rec toInternal = (ev: ExternalExpressionValue.expressionValue): expressionValue => { switch ev { | EvArray(v) => v->Belt.Array.map(e => toInternal(e))->IevArray | EvArrayString(v) => IevArrayString(v) | EvBool(v) => IevBool(v) | EvCall(v) => IevCall(v) | EvDistribution(v) => IevDistribution(v) | EvLambda(v) => IevLambda(lambdaValueToInternal(v)) | EvNumber(v) => IevNumber(v) | EvRecord(v) => v->recordToInternal->IevRecord | EvString(v) => IevString(v) | EvSymbol(v) => IevSymbol(v) | EvDate(v) => IevDate(v) | EvTimeDuration(v) => IevTimeDuration(v) | EvDeclaration(v) => { let fn = lambdaValueToInternal(v.fn) let args = v.args IevDeclaration({fn: fn, args: args}) } | EvTypeIdentifier(v) => IevTypeIdentifier(v) | EvModule(v) => v->nameSpaceFromTypeScriptBindings->IevModule } } and recordToInternal = v => v->Js.Dict.entries->Belt.Map.String.fromArray->Belt.Map.String.map(e => toInternal(e)) and lambdaValueToInternal = v => { let p = v.parameters let c = v.context->nameSpaceFromTypeScriptBindings let b = v.body {parameters: p, context: c, body: b} } and nameSpaceFromTypeScriptBindings = ( r: ReducerInterface_ExpressionValue.externalBindings, ): nameSpace => r->Js.Dict.entries->Belt.Map.String.fromArray->Belt.Map.String.map(e => toInternal(e))->NameSpace