Improve Typescript Interface
This commit is contained in:
parent
67bcd7052b
commit
25a6c374d1
|
@ -1,34 +1,16 @@
|
|||
import { run } from '../src/js/index';
|
||||
import { run, exportToString } from '../src/js/index';
|
||||
|
||||
let testRun = (x: string) => {
|
||||
let result = run(x)
|
||||
if(result.tag == 'Ok'){
|
||||
return { tag: 'Ok', value: result.value.exports }
|
||||
}
|
||||
else {
|
||||
return result
|
||||
}
|
||||
}
|
||||
let testRun = (expression: string): string => exportToString(run(expression)[0])
|
||||
|
||||
let runTest = (expression: string, expected: string) => test(expression, () => expect(testRun(expression)).toEqual(expected))
|
||||
|
||||
let runErrorTest = (expression: string, expected: string) => test(`${expression} will error`, () => expect(() => testRun(expression)).toThrowError(expected))
|
||||
|
||||
describe("Simple calculations and results", () => {
|
||||
test("mean(normal(5,2))", () => {
|
||||
expect(testRun("mean(normal(5,2))")).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 5 } ] })
|
||||
})
|
||||
test("10+10", () => {
|
||||
let foo = testRun("10 + 10")
|
||||
expect(foo).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 20 } ] })
|
||||
})
|
||||
})
|
||||
describe("Log function", () => {
|
||||
test("log(1) = 0", () => {
|
||||
let foo = testRun("log(1)")
|
||||
expect(foo).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 0} ]})
|
||||
})
|
||||
runTest("mean(normal(5,2))", "5")
|
||||
runTest("10 + 10", "20")
|
||||
})
|
||||
|
||||
describe("Multimodal too many weights error", () => {
|
||||
test("mm(0,0,[0,0,0])", () => {
|
||||
let foo = testRun("mm(0,0,[0,0,0])")
|
||||
expect(foo).toEqual({ "tag": "Error", "value": "Function multimodal error: Too many weights provided" })
|
||||
describe("Log function", () => {
|
||||
runTest("log(1)", "0")
|
||||
})
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ open Jest
|
|||
open Expect
|
||||
|
||||
let expectEvalToBe = (expr: string, answer: string) =>
|
||||
Reducer.eval(expr)->ExpressionValue.toStringResult->expect->toBe(answer)
|
||||
Reducer.evaluate(expr)->ExpressionValue.toStringResult->expect->toBe(answer)
|
||||
|
||||
describe("builtin", () => {
|
||||
// All MathJs operators and functions are available for string, number and boolean
|
||||
|
|
|
@ -8,7 +8,7 @@ let expectParseToBe = (expr: string, answer: string) =>
|
|||
Reducer.parse(expr)->Expression.toStringResult->expect->toBe(answer)
|
||||
|
||||
let expectEvalToBe = (expr: string, answer: string) =>
|
||||
Reducer.eval(expr)->ExpressionValue.toStringResult->expect->toBe(answer)
|
||||
Reducer.evaluate(expr)->ExpressionValue.toStringResult->expect->toBe(answer)
|
||||
|
||||
// Current configuration does not ignore this file so we have to have a test
|
||||
test("test helpers", () => expect(1)->toBe(1))
|
||||
|
|
|
@ -33,7 +33,9 @@
|
|||
"gentypeconfig": {
|
||||
"language": "typescript",
|
||||
"module": "commonjs",
|
||||
"shims": {},
|
||||
"shims": {
|
||||
"Js": "Js"
|
||||
},
|
||||
"debug": {
|
||||
"all": false,
|
||||
"basic": false
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import {runAll} from '../rescript/ProgramEvaluator.gen';
|
||||
import type { Inputs_SamplingInputs_t as SamplingInputs, exportEnv, exportType, exportDistribution} from '../rescript/ProgramEvaluator.gen';
|
||||
export type { SamplingInputs, exportEnv, exportDistribution }
|
||||
export type {t as DistPlus} from '../rescript/OldInterpreter/DistPlus.gen';
|
||||
import * as _ from 'lodash';
|
||||
import {evaluate} from '../rescript/Reducer/Reducer.gen';
|
||||
import type { expressionValue } from '../rescript/Reducer/Reducer_Expression/Reducer_Expression.gen';
|
||||
import type { pointSetDist } from '../rescript/Distributions/PointSetDist/PointSetTypes.gen';
|
||||
import type { genericDist } from '../rescript/Distributions/GenericDist/GenericDist_Types.gen';
|
||||
import { errorToString } from '../rescript/Reducer/Reducer_ErrorValue.gen';
|
||||
import { toPointSet, inv } from '../rescript/Distributions/GenericDist/GenericDist.gen';
|
||||
import type { Inputs_SamplingInputs_t as SamplingInputs, exportEnv, exportDistribution} from '../rescript/ProgramEvaluator.gen';
|
||||
export type { SamplingInputs, exportEnv, exportDistribution, tsExport }
|
||||
|
||||
export let defaultSamplingInputs : SamplingInputs = {
|
||||
sampleCount : 10000,
|
||||
|
@ -9,9 +14,140 @@ export let defaultSamplingInputs : SamplingInputs = {
|
|||
pointDistLength : 1000
|
||||
}
|
||||
|
||||
export function run(squiggleString : string, samplingInputs? : SamplingInputs, environment?: exportEnv) : { tag: "Ok"; value: exportType }
|
||||
| { tag: "Error"; value: string } {
|
||||
let si : SamplingInputs = samplingInputs ? samplingInputs : defaultSamplingInputs
|
||||
let env : exportEnv = environment ? environment : []
|
||||
return runAll(squiggleString, si, env)
|
||||
type taggedOption<tag,value> = {
|
||||
tag: tag,
|
||||
value: value
|
||||
}
|
||||
|
||||
function tagOption<T, V>(tag : T, value: V): taggedOption<T,V> {
|
||||
return { tag: tag, value: value};
|
||||
}
|
||||
type tsExport = taggedOption<"string", string> | taggedOption<"symbol", string> | taggedOption<"number", number> | taggedOption<"boolean", boolean> | taggedOption<"distribution", Distribution> | taggedOption<"array", tsExport[]> | taggedOption<"record", {[key: string]: tsExport}> | taggedOption<"function", (x: number) => tsExport>
|
||||
|
||||
// This is here mainly for testing purposes
|
||||
export function exportToString(result : tsExport) : string{
|
||||
if(result.tag === "string"){
|
||||
return `"${result.value}"`
|
||||
}
|
||||
else if(result.tag === "boolean"){
|
||||
return `${result.value}`
|
||||
}
|
||||
else if(result.tag === "array"){
|
||||
return `[${result.value.map(exportToString).join(", ")}]`
|
||||
}
|
||||
else if(result.tag === "distribution"){
|
||||
return result.value.toString()
|
||||
}
|
||||
else if(result.tag === "number"){
|
||||
return `${result.value}`
|
||||
}
|
||||
else if(result.tag === "symbol"){
|
||||
return `${result.value}`
|
||||
}
|
||||
else if(result.tag === "record"){
|
||||
return `${_.mapValues(result.value, exportToString)}`
|
||||
}
|
||||
}
|
||||
|
||||
function expressionValueToValue(value : expressionValue, samplingInputs: SamplingInputs) : tsExport {
|
||||
if(value.tag == "EvArray"){
|
||||
return tagOption("array", value.value.map((val) => expressionValueToValue(val,samplingInputs)));
|
||||
}else if (value.tag == "EvBool"){
|
||||
return tagOption("boolean", value.value)
|
||||
}
|
||||
else if(value.tag == "EvDistribution"){
|
||||
return tagOption("distribution", new Distribution(value.value, samplingInputs));
|
||||
}
|
||||
else if(value.tag == "EvNumber"){
|
||||
return tagOption("number", value.value);
|
||||
}
|
||||
else if(value.tag == "EvString"){
|
||||
return tagOption("string", value.value);
|
||||
}
|
||||
else if(value.tag == "EvSymbol"){
|
||||
return tagOption("symbol", value.value);
|
||||
}
|
||||
else if(value.tag == "EvRecord"){
|
||||
return tagOption("record", _.mapValues(value.value, (val) => expressionValueToValue(val, samplingInputs)));
|
||||
}
|
||||
}
|
||||
|
||||
export function run(squiggleString : string, samplingInputs : SamplingInputs = defaultSamplingInputs, _environment?: exportEnv): tsExport[] {
|
||||
let result = evaluate(squiggleString);
|
||||
if(result.tag == "Ok"){
|
||||
return [expressionValueToValue(result.value, samplingInputs)];
|
||||
}
|
||||
else{
|
||||
throw Error(errorToString(result.value));
|
||||
}
|
||||
}
|
||||
|
||||
class Distribution {
|
||||
dist: genericDist
|
||||
samplingInputs : SamplingInputs
|
||||
constructor(dist : genericDist, samplingInputs: SamplingInputs){
|
||||
this.dist = dist;
|
||||
this.samplingInputs = samplingInputs;
|
||||
}
|
||||
|
||||
pointShape() {
|
||||
let pointSet = toPointSet({xyPointLength: this.samplingInputs.outputXYPoints, sampleCount: this.samplingInputs.sampleCount}, this.dist)
|
||||
if(pointSet.tag == "Ok"){
|
||||
return new Shape(pointSet.value);
|
||||
}
|
||||
}
|
||||
|
||||
inv(x: number): number{
|
||||
let result= inv(this.dist, x)
|
||||
if (result.tag == "Ok") {
|
||||
return result.value;
|
||||
}
|
||||
else {
|
||||
throw Error(result.value.toString())
|
||||
}
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return "Todo"
|
||||
}
|
||||
}
|
||||
|
||||
type point = { x: number, y: number, cdf: number}
|
||||
class Shape {
|
||||
shape : pointSetDist
|
||||
constructor(shape : pointSetDist){
|
||||
this.shape = shape;
|
||||
}
|
||||
|
||||
discretePoints(): point[]{
|
||||
let discreteShape = undefined;
|
||||
if(this.shape.tag == "Discrete"){
|
||||
discreteShape = this.shape.value;
|
||||
} else if (this.shape.tag == "Mixed"){
|
||||
discreteShape = this.shape.value.discrete;
|
||||
}
|
||||
if(discreteShape !== undefined) {
|
||||
return _.zipWith(discreteShape.xyShape.xs, discreteShape.xyShape.ys, discreteShape.integralCache.xyShape.ys, (x, y, c) => ({x, y, cdf: c}))
|
||||
}
|
||||
else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
continuousPoints(): point[]{
|
||||
let continuousShape = undefined;
|
||||
console.log(this.shape.tag)
|
||||
if(this.shape.tag == "Continuous"){
|
||||
continuousShape = this.shape.value;
|
||||
} else if (this.shape.tag == "Mixed"){
|
||||
continuousShape = this.shape.value.continuous;
|
||||
}
|
||||
if(continuousShape !== undefined) {
|
||||
return _.zipWith(continuousShape.xyShape.xs, continuousShape.xyShape.ys, continuousShape.integralCache.xyShape.ys, (x, y, c) => ({x, y, cdf: c}))
|
||||
}
|
||||
else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,13 @@ let sampleN = (t: t, n) =>
|
|||
| SampleSet(_) => Error(GenericDist_Types.NotYetImplemented)
|
||||
}
|
||||
|
||||
let inv = (t: t, x: float): result<float, error> =>
|
||||
switch t {
|
||||
| PointSet(r) => Ok(PointSetDist.inv(x, r))
|
||||
| Symbolic(r) => Ok(SymbolicDist.T.inv(x, r))
|
||||
| SampleSet(_) => Error(GenericDist_Types.NotYetImplemented)
|
||||
}
|
||||
|
||||
let fromFloat = (f: float): t => Symbolic(SymbolicDist.Float.make(f))
|
||||
|
||||
let toString = (t: t) =>
|
||||
|
|
|
@ -7,6 +7,9 @@ type pointwiseAddFn = (t, t) => result<t, error>
|
|||
|
||||
let sampleN: (t, int) => result<array<float>, error>
|
||||
|
||||
@genType
|
||||
let inv : (t, float) => result<float, error>
|
||||
|
||||
let fromFloat: float => t
|
||||
|
||||
let toString: t => string
|
||||
|
@ -19,6 +22,7 @@ let toFloatOperation: (
|
|||
~distToFloatOperation: Operation.distToFloatOperation,
|
||||
) => result<float, error>
|
||||
|
||||
@genType
|
||||
let toPointSet: (
|
||||
~xyPointLength: int,
|
||||
~sampleCount: int,
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
@genType
|
||||
type genericDist =
|
||||
| PointSet(PointSetTypes.pointSetDist)
|
||||
| SampleSet(SampleSet.t)
|
||||
| Symbolic(SymbolicDistTypes.symbolicDist)
|
||||
|
||||
@genType
|
||||
type error =
|
||||
| NotYetImplemented
|
||||
| Unreachable
|
||||
|
|
|
@ -5,5 +5,5 @@ module Extra = Reducer_Extra
|
|||
module Js = Reducer_Js
|
||||
module MathJs = Reducer_MathJs
|
||||
|
||||
let eval = Expression.eval
|
||||
let evaluate = Expression.eval
|
||||
let parse = Expression.parse
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
module Dispatch = Reducer_Dispatch
|
||||
@genType
|
||||
module ErrorValue = Reducer_ErrorValue
|
||||
@genType
|
||||
module Expression = Reducer_Expression
|
||||
module Extra = Reducer_Extra
|
||||
module Js = Reducer_Js
|
||||
module MathJs = Reducer_MathJs
|
||||
let eval: string => result<Expression.expressionValue, ErrorValue.errorValue>
|
||||
@genType
|
||||
let evaluate: string => result<Reducer_Expression.expressionValue, Reducer_ErrorValue.errorValue>
|
||||
let parse: string => result<Expression.expression, ErrorValue.errorValue>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
@genType
|
||||
type errorValue =
|
||||
| REArrayIndexNotFound(string, int)
|
||||
| REFunctionExpected(string)
|
||||
|
@ -7,6 +8,7 @@ type errorValue =
|
|||
|
||||
type t = errorValue
|
||||
|
||||
@genType
|
||||
let errorToString = err =>
|
||||
switch err {
|
||||
| REArrayIndexNotFound(msg, index) => `${msg}: ${Js.String.make(index)}`
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module Result = Belt.Result
|
||||
module T = Reducer_Expression_T
|
||||
type expression = T.expression
|
||||
type expressionValue = ReducerInterface.ExpressionValue.expressionValue
|
||||
@genType
|
||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
||||
type t = expression
|
||||
let toString: T.expression => Js.String.t
|
||||
let toStringResult: result<T.expression, 'a> => string
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
module Extra_Array = Reducer_Extra_Array
|
||||
module ErrorValue = Reducer_ErrorValue
|
||||
|
||||
@genType
|
||||
type rec expressionValue =
|
||||
| EvBool(bool)
|
||||
| EvNumber(float)
|
||||
|
|
1
packages/squiggle-lang/src/rescript/shims/Js.shim.ts
Normal file
1
packages/squiggle-lang/src/rescript/shims/Js.shim.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export type Dict_t<T> = {[key: string]: T}
|
Loading…
Reference in New Issue
Block a user