-
Notifications
You must be signed in to change notification settings - Fork 104
Stepper
To use the stepper in a REPL, you can run the repl with subst
as its last command line argument:
cd js-slang
yarn build && node dist/repl/repl.js 1 subst
The primary point of entry for the stepper tool is via the getEvaluationSteps-function. This function takes a program an array. This array contains the different program states as the program is being evaluated.
- The method starts off by replacing all predefined constants (such as math_PI) in the program with their corresponding value. This is done via the substPredefinedConstants function.
- The next step is to substitute all predefined functions in the program. This is done with the help of the substPredefinedFns function.
- It then repeatedly reduces the program (which basically means doing repeated one step evaluations) with the help of the reduce function. For every reduction it performs it stores the program state in the return-array. This allows for playback through the evaluation steps.
The function uses an array, mathConstants, that contains all predefined mathematical constants. Each entry of this array is of the form [name, value] - where "name" is the name of the constant (e.g. math_PI) & "value" is the corresponding value (e.g. 3.141592653589793).
The method loops through all elements of mathConstants and replaces all occurrences of the name in the program with the associated value. it does so via the substituteMain method.
This method substitutes all predefined functions in the program. What does substituting these mean?
substituteMain(name: es.Identifier, replacement: irreducibleNodes, target: substituterNodes): substituterNodes
This is a wrapper function for the substitute function. It provides the substitute function with "substituters", which is a datastructure full of functions. Each function describes how to replace a specific target type.
It also provides a map "seenBefore". This map is re-initialized every time substituteMain is called and therefore only keeps track of the targets seen within the substituteMain function. The reason why it's needed is that the substitute function will be called recursively, which would have the potential for creating infinite loops. Keeping track of what targets have been seen before allows us to only evaluate a target once.
In summary the substituteMain function is to provide a closure in which we can keep seenBefore like a "global variable" in the eyes of the substitute function
This function performs substitution of the provided target.
apply(callee: es.FunctionExpression | es.ArrowFunctionExpression, args: irreducibleNodes[]): BlockExpression | es.Expression
The reduce function is given the task of reducing the program, which basically means taking the first statement in the program and doing one step evaluation on it. Repeated application of this function will therefore cause the program to fully evaluate.
In order to perform the one step evaluation reduce uses the datastructure "reducers". Much like the substituters datastructure it contains instructions for how to handle all types of statements that we could potentially encounter.
This function ....
...