66
77/* tslint:disable:max-classes-per-file */
88
9+ import { ErrorType } from "@sourceacademy/conductor/common" ;
910import { ExprNS , StmtNS } from "../ast-types" ;
1011import * as error from "../errors/errors" ;
1112import { BuiltinReassignmentError } from "../errors/errors" ;
@@ -31,6 +32,7 @@ import {
3132 isFalsy ,
3233} from "./operators" ;
3334import { Stash , Value } from "./stash" ;
35+ import { displayError } from "./streams" ;
3436import {
3537 AppInstr ,
3638 AssmtInstr ,
@@ -53,12 +55,7 @@ type CmdEvaluator = (
5355 control : Control ,
5456 stash : Stash ,
5557 isPrelude : boolean ,
56- ) => void ;
57-
58- let cseFinalPrint = "" ;
59- export function addPrint ( str : string ) {
60- cseFinalPrint = cseFinalPrint + str + "\n" ;
61- }
58+ ) => void | Promise < void > ;
6259
6360/**
6461 * Function that returns the appropriate Promise<Result> given the output of CSE machine evaluating, depending
@@ -73,7 +70,7 @@ export function CSEResultPromise(context: Context, value: Value): Promise<Result
7370 resolve ( { status : "suspended-cse-eval" , context } ) ;
7471 } else if ( value . type === "error" ) {
7572 const msg = value . message ;
76- const representation = new Representation ( cseFinalPrint + msg ) ;
73+ const representation = new Representation ( msg ) ;
7774 resolve ( { status : "finished" , context, value, representation } ) ;
7875 } else {
7976 const representation = new Representation ( toPythonString ( value ) ) ;
@@ -93,26 +90,26 @@ let source = "";
9390 * @param options Evaluation options.
9491 * @returns The result of running the CSE machine.
9592 */
96- export function evaluate (
93+ export async function evaluate (
9794 code : string ,
9895 program : StmtNS . Stmt ,
9996 context : Context ,
10097 options : RecursivePartial < IOptions > = { } ,
101- ) : Value {
98+ ) : Promise < Value > {
10299 source = code ;
103100 try {
104101 // TODO: is undefined variables check necessary for Python?
105102 // checkProgramForUndefinedVariables(program, context)
106103 } catch ( error ) {
107- return { type : " error" , message : error instanceof Error ? error . message : String ( error ) } ;
104+ return displayError ( context , error , ErrorType . EVALUATOR_RUNTIME ) ;
108105 }
109106
110107 try {
111108 context . runtime . isRunning = true ;
112109 context . control = new Control ( program ) ;
113110 context . stash = new Stash ( ) ;
114111 // Adaptation for new feature
115- const result = runCSEMachine (
112+ const result = await runCSEMachine (
116113 code ,
117114 context ,
118115 context . control ,
@@ -121,9 +118,9 @@ export function evaluate(
121118 options . stepLimit ! ,
122119 options . isPrelude ,
123120 ) ;
124- return context . output ? { type : "string" , value : context . output } : result ;
121+ return result ;
125122 } catch ( error ) {
126- return { type : " error" , message : error instanceof Error ? error . message : String ( error ) } ;
123+ return await displayError ( context , error , ErrorType . EVALUATOR_RUNTIME ) ;
127124 } finally {
128125 context . runtime . isRunning = false ;
129126 }
@@ -179,15 +176,15 @@ export function evaluate(
179176 * @param isPrelude Whether the program is the prelude.
180177 * @returns The top value of the stash after execution.
181178 */
182- export function runCSEMachine (
179+ export async function runCSEMachine (
183180 code : string ,
184181 context : Context ,
185182 control : Control ,
186183 stash : Stash ,
187184 envSteps : number ,
188185 stepLimit : number ,
189186 isPrelude : boolean = false ,
190- ) : Value {
187+ ) : Promise < Value > {
191188 const eceState = generateCSEMachineStateStream (
192189 code ,
193190 context ,
@@ -200,7 +197,7 @@ export function runCSEMachine(
200197
201198 // Execute the generator until it completes
202199 // eslint-disable-next-line @typescript-eslint/no-unused-vars
203- for ( const _value of eceState ) {
200+ for await ( const _value of eceState ) {
204201 }
205202
206203 // Return the value at the top of the storage as the result
@@ -219,7 +216,7 @@ export function runCSEMachine(
219216 * @param isPrelude Whether the program is the prelude.
220217 * @yields The current state of the stash, control stack, and step count.
221218 */
222- export function * generateCSEMachineStateStream (
219+ export async function * generateCSEMachineStateStream (
223220 code : string ,
224221 context : Context ,
225222 control : Control ,
@@ -265,7 +262,7 @@ export function* generateCSEMachineStateStream(
265262 context . runtime . nodes . shift ( ) ;
266263 context . runtime . nodes . unshift ( command ) ;
267264
268- cmdEvaluators [ nodeType ] ( code , command , context , control , stash , isPrelude ) ;
265+ await cmdEvaluators [ nodeType ] ( code , command , context , control , stash , isPrelude ) ;
269266
270267 if ( context . runtime . break && context . runtime . debuggerOn ) {
271268 // TODO
@@ -278,7 +275,7 @@ export function* generateCSEMachineStateStream(
278275 } else {
279276 // Command is an instruction
280277 const instr = command as Instr ;
281- cmdEvaluators [ instr . instrType ] ( code , command , context , control , stash , isPrelude ) ;
278+ await cmdEvaluators [ instr . instrType ] ( code , command , context , control , stash , isPrelude ) ;
282279 }
283280
284281 command = control . peek ( ) ;
@@ -760,7 +757,7 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
760757 stash . pop ( ) ;
761758 } ,
762759
763- [ InstrType . APPLICATION ] : function (
760+ [ InstrType . APPLICATION ] : async function (
764761 code : string ,
765762 command : ControlItem ,
766763 context : Context ,
@@ -802,7 +799,7 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
802799 }
803800 } else {
804801 if ( callable && callable . type === "builtin" ) {
805- const result = callable . func ( args , code , instr . srcNode , context ) ;
802+ const result = await callable . func ( args , code , instr . srcNode , context ) ;
806803 stash . push ( result ) ;
807804 }
808805 }
0 commit comments