Merge pull request #33 from QURIresearch/lang-function-interface

Change the function interface into a js function.
This commit is contained in:
Ozzie Gooen 2022-02-27 07:53:16 -05:00 committed by GitHub
commit 4ebb11182f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 5281 additions and 273 deletions

View File

@ -13,3 +13,5 @@ yarn-error.log
# Local Netlify folder
.netlify
.idea
*.gen.ts
*.gen.js

View File

@ -27,15 +27,20 @@ This package is mainly written in [ReScript](https://rescript-lang.org/). But ha
a typescript interface.
ReScript has an interesting philosophy of not providing much in the way of effective
build tools. Every ReScript file is compiled into a .bs.js file with the same name
and same location, and then you can use these .bs.js files in other js files to
create your program. To generate this .bs.js files to build the package, you run
build tools. Every ReScript file is compiled into .bs.js and .gen.ts files with the same name
and same location, and then you can use these files in other js files to
create your program. To generate these files to build the package, you run
`yarn build`.
```bash
yarn build
```
.gen.ts files are created by [genType](https://rescript-lang.org/docs/gentype/latest/getting-started),
which creates typescript typings for needed parts of the codebase so that they
can be easily used in typescript. These .gen.ts files reference the .bs.js files
generated by rescript.
You can also go `yarn start` for the purposes of watching for file changes and
rebuilding every time there is one.

View File

@ -2,7 +2,7 @@ import { run } from '../src/js/index';
describe("A simple result", () => {
test("mean(normal(5,2))", () => {
expect(run("mean(normal(5,2))")).toEqual({ tag: 'Ok', value: {hd: { NAME: 'Float', VAL: 5 }, tl: 0} });
expect(run("mean(normal(5,2))")).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 5 } ] });
});
test("10+10", () => {
let foo = run("normal(5,2)");
@ -10,6 +10,6 @@ describe("A simple result", () => {
});
test("log(1) = 0", () => {
let foo = run("log(1)");
expect(foo).toEqual({ tag: 'Ok', value: { hd: { NAME: 'Float', VAL: 0}, tl: 0}});
expect(foo).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 0} ]});
})
});

View File

@ -31,7 +31,8 @@
"rationale"
],
"gentypeconfig": {
"language": "untyped",
"language": "typescript",
"generatedFileExtension": ".gen.ts",
"module": "commonjs",
"shims": {},
"debug": {

View File

@ -1 +1,3 @@
export {runAll as run} from '../rescript/ProgramEvaluator.gen'
import {runAll} from '../rescript/ProgramEvaluator.gen';
export type {t as DistPlus} from '../rescript/pointSetDist/DistPlus.gen';
export let run = runAll

View File

@ -1,12 +0,0 @@
/* Untyped file generated from ProgramEvaluator.res by genType. */
/* eslint-disable */
const ProgramEvaluatorBS = require('./ProgramEvaluator.bs');
const runAll = function (Arg1) {
const result = ProgramEvaluatorBS.runAll(Arg1);
return result.TAG===0
? {tag:"Ok", value:result._0}
: {tag:"Error", value:result._0}
};;
exports.runAll = runAll

View File

@ -5,7 +5,7 @@ module Inputs = {
sampleCount: option<int>,
outputXYPoints: option<int>,
kernelWidth: option<float>,
pointSetDistLength: option<int>,
pointDistLength: option<int>,
}
}
let defaultRecommendedLength = 100
@ -21,7 +21,7 @@ module Inputs = {
sampleCount: None,
outputXYPoints: None,
kernelWidth: None,
pointSetDistLength: None,
pointDistLength: None,
}
let make = (
@ -36,13 +36,10 @@ module Inputs = {
}
}
type exported = [
type exportType = [
| #DistPlus(DistPlus.t)
| #Float(float)
| #Function(
(array<string>, ASTTypes.node),
ASTTypes.environment,
)
| #Function((float) => Belt.Result.t<DistPlus.t,string>)
]
module Internals = {
@ -62,13 +59,13 @@ module Internals = {
graph: ASTTypes.node,
pointSetDist: PointSetTypes.pointSetDist,
}
let makeOutputs = (graph, pointSetDist): outputs => {graph: graph, pointSetDist: pointSetDist}
let makeOutputs = (graph, shape): outputs => {graph: graph, pointSetDist: shape}
let makeInputs = (inputs: Inputs.inputs): SamplingInputs.samplingInputs => {
sampleCount: inputs.samplingInputs.sampleCount |> E.O.default(10000),
outputXYPoints: inputs.samplingInputs.outputXYPoints |> E.O.default(10000),
kernelWidth: inputs.samplingInputs.kernelWidth,
pointSetDistLength: inputs.samplingInputs.pointSetDistLength |> E.O.default(10000),
pointSetDistLength: inputs.samplingInputs.pointDistLength |> E.O.default(10000),
}
let runNode = (inputs, node) =>
@ -91,7 +88,7 @@ module Internals = {
}
let inputsToLeaf = (inputs: Inputs.inputs) =>
Parser.fromString(inputs.squiggleString) -> E.R.bind(g => runProgram(inputs, g))
Parser.fromString(inputs.squiggleString) |> E.R.bind(_, g => runProgram(inputs, g))
let outputToDistPlus = (inputs: Inputs.inputs, pointSetDist: PointSetTypes.pointSetDist) =>
DistPlus.make(~pointSetDist, ~squiggleString=Some(inputs.squiggleString), ())
@ -121,12 +118,31 @@ let renderIfNeeded = (inputs: Inputs.inputs, node: ASTTypes.node): result<
}
)
// TODO: Consider using ASTTypes.getFloat or similar in this function
let coersionToExportedTypes = (
let rec returnDist = (functionInfo : (array<string>, ASTTypes.node),
inputs : Inputs.inputs,
env : ASTTypes.environment) => {
(input : float) => {
let foo: Inputs.inputs = {...inputs, environment: env};
evaluateFunction(
foo,
functionInfo,
[#SymbolicDist(#Float(input))],
) |> E.R.bind(_, a =>
switch a {
| #DistPlus(d) => Ok(DistPlus.T.normalize(d))
| n =>
Js.log2("Error here", n)
Error("wrong type")
}
)
}
}
// TODO: Consider using ExpressionTypes.ExpressionTree.getFloat or similar in this function
and coersionToExportedTypes = (
inputs,
env: ASTTypes.environment,
node: ASTTypes.node,
): result<exported, string> =>
): result<exportType, string> =>
node
|> renderIfNeeded(inputs)
|> E.R.bind(_, x =>
@ -134,31 +150,12 @@ let coersionToExportedTypes = (
| #RenderedDist(Discrete({xyShape: {xs: [x], ys: [1.0]}})) => Ok(#Float(x))
| #SymbolicDist(#Float(x)) => Ok(#Float(x))
| #RenderedDist(n) => Ok(#DistPlus(Internals.outputToDistPlus(inputs, n)))
| #Function(n) => Ok(#Function(n, env))
| #Function(n) => Ok(#Function(returnDist(n, inputs, env)))
| n => Error("Didn't output a rendered distribution. Format:" ++ AST.toString(n))
}
)
let rec mapM = (f, xs) =>
switch xs {
| list{} => Ok(list{})
| list{x, ...rest} =>
switch f(x) {
| Error(err) => Error(err)
| Ok(val) =>
switch mapM(f, rest) {
| Error(err) => Error(err)
| Ok(restList) => Ok(list{val, ...restList})
}
}
}
let evaluateProgram = (inputs: Inputs.inputs) =>
inputs
|> Internals.inputsToLeaf
|> E.R.bind(_, xs => mapM(((a, b)) => coersionToExportedTypes(inputs, a, b), Array.to_list(xs)))
let evaluateFunction = (
and evaluateFunction = (
inputs: Inputs.inputs,
fn: (array<string>, ASTTypes.node),
fnInputs,
@ -172,6 +169,29 @@ let evaluateFunction = (
output |> E.R.bind(_, coersionToExportedTypes(inputs, inputs.environment))
}
let rec mapM = (f, xs) =>
switch xs {
| [] => Ok([])
| arr =>
switch f(arr[0]) {
| Error(err) => Error(err)
| Ok(val) =>
switch mapM(f, Belt.Array.sliceToEnd(arr, 1)) {
| Error(err) => Error(err)
| Ok(restList) => Ok(Belt.Array.concat([val], restList))
}
}
}
let evaluateProgram = (inputs: Inputs.inputs) =>
inputs
|> Internals.inputsToLeaf
|> E.R.bind(_, xs => mapM(((a, b)) => coersionToExportedTypes(inputs, a, b), xs))
@genType
let runAll = (squiggleString: string) => {
let inputs = Inputs.make(
@ -179,12 +199,12 @@ let runAll = (squiggleString: string) => {
sampleCount: Some(10000),
outputXYPoints: Some(10000),
kernelWidth: None,
pointSetDistLength: Some(1000),
pointDistLength: Some(1000),
},
~squiggleString,
~environment=[]->Belt.Map.String.fromArray,
(),
)
let response1 = evaluateProgram(inputs);
response1;
response1
}

View File

@ -1,5 +1,6 @@
open PointSetTypes;
@genType
type t = PointSetTypes.distPlus;
let pointSetDistIntegral = pointSetDist => PointSetDist.T.Integral.get(pointSetDist);

View File

@ -55,6 +55,7 @@ type pointSetDistMonad<'a, 'b, 'c> =
| Discrete('b)
| Continuous('c)
@genType
type pointSetDist = pointSetDistMonad<mixedShape, discreteShape, continuousShape>
module ShapeMonad = {
@ -73,6 +74,7 @@ type generationSource =
type distributionUnit =
| UnspecifiedDistribution
@genType
type distPlus = {
pointSetDist: pointSetDist,
domain: domain,

5423
yarn.lock

File diff suppressed because it is too large Load Diff