Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Umur Ozkul committed Apr 15, 2022
1 parent 53c44cd commit 3f95ca4
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ let expectParseToBe = (expr: string, answer: string) =>

let expectEvalToBe = (expr: string, answer: string) =>
Reducer.evaluate(expr)->ExpressionValue.toStringResult->expect->toBe(answer)

let expectEvalBindingsToBe = (expr: string, bindings: Reducer.externalBindings, answer: string) =>
Reducer.evaluateWBindings(expr, bindings)->ExpressionValue.toStringResult->expect->toBe(answer)
18 changes: 18 additions & 0 deletions packages/squiggle-lang/__tests__/Reducer/Reducer_test.res
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ let testEvalToBe = (expr, answer) => test(expr, () => expectEvalToBe(expr, answe

let testDescriptionEvalToBe = (desc, expr, answer) => test(desc, () => expectEvalToBe(expr, answer))

let testEvalBindingsToBe = (expr, bindings, answer) =>
test(expr, () => expectEvalBindingsToBe(expr, bindings, answer))

describe("reducer using mathjs parse", () => {
// Test the MathJs parser compatibility
// Those tests toString that there is a semantic mapping from MathJs to Expression
Expand Down Expand Up @@ -102,6 +105,21 @@ describe("eval", () => {
testEvalToBe("1; 1", "Error(Assignment expected)")
testEvalToBe("x=1; x=1", "Error(Expression expected)")
})
describe("external bindings", () => {
testEvalBindingsToBe(
"y=1; x+1",
list{("x", ExpressionValue.EvNumber(1.))}->Js.Dict.fromList,
"Ok(2)",
)
testEvalBindingsToBe(
// This will go away when we have a proper parser
// x+1 is an expression not a block!
// Bindings are done for blocks only
"x+1",
list{("x", ExpressionValue.EvNumber(1.))}->Js.Dict.fromList,
"Error(JS Exception: Error: Undefined symbol x)",
)
})
})

describe("test exceptions", () => {
Expand Down
2 changes: 2 additions & 0 deletions packages/squiggle-lang/src/rescript/Reducer/Reducer.res
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ module Js = Reducer_Js
module MathJs = Reducer_MathJs

type expressionValue = Reducer_Expression.expressionValue
type externalBindings = Expression.externalBindings
let evaluate = Expression.eval
let evaluateWBindings = Expression.evalWBindings
let parse = Expression.parse
5 changes: 4 additions & 1 deletion packages/squiggle-lang/src/rescript/Reducer/Reducer.resi
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ module MathJs = Reducer_MathJs

@genType
type expressionValue = ReducerInterface_ExpressionValue.expressionValue

@genType
type externalBindings = Expression.externalBindings
@genType
let evaluate: string => result<expressionValue, Reducer_ErrorValue.errorValue>
@genType
let evaluateWBindings: (string, externalBindings) => result<expressionValue, Reducer_ErrorValue.errorValue>
let parse: string => result<Expression.expression, ErrorValue.errorValue>
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,31 @@ let reduceExpression = (expression: t, bindings: T.bindings): result<expressionV
)
}

let evalWBindingsExpression = (aExpression, bindings): result<expressionValue, 'e> =>
let evalWBindingsExpression_ = (aExpression, bindings): result<expressionValue, 'e> =>
reduceExpression(aExpression, bindings)

/*
Evaluates MathJs code via Reducer using bindings and answers the result
*/
let evalWBindings = (codeText: string, bindings: T.bindings) => {
parse(codeText)->Result.flatMap(code => code->evalWBindingsExpression(bindings))
let evalWBindings_ = (codeText: string, bindings: T.bindings) => {
parse(codeText)->Result.flatMap(code => code->evalWBindingsExpression_(bindings))
}

/*
Evaluates MathJs code via Reducer and answers the result
*/
let eval = (code: string) => evalWBindings(code, defaultBindings)
let eval = (code: string) => evalWBindings_(code, defaultBindings)

type externalBindings = Js.Dict.t<expressionValue>

/*
Evaluates code with external bindings. External bindings are a record of expression values.
*/
let evalWBindings = (code: string, externalBindings: externalBindings) => {
let keys = Js.Dict.keys(externalBindings)
let bindings = keys->Belt.Array.reduce(defaultBindings, (acc, key) => {
let value = Js.Dict.unsafeGet(externalBindings, key)
acc->Belt.Map.String.set(key, T.EValue(value))
})
evalWBindings_(code, bindings)
}

0 comments on commit 3f95ca4

Please sign in to comment.