Execute input in the REPL.

Guesses whether the input is an expression or statement and handles it
appropriately. Finally, after over a year, the Wren REPL automatically
prints "3" if you type in "1 + 2". \o/
This commit is contained in:
Bob Nystrom
2016-06-09 19:16:41 -07:00
parent 689cd42269
commit bc7f1de758
9 changed files with 347 additions and 177 deletions
+24 -13
View File
@@ -3345,6 +3345,7 @@ static void variableDefinition(Compiler* compiler)
// Compile the initializer.
if (match(compiler, TOKEN_EQ))
{
ignoreNewlines(compiler);
expression(compiler);
}
else
@@ -3387,7 +3388,7 @@ void definition(Compiler* compiler)
}
ObjFn* wrenCompile(WrenVM* vm, ObjModule* module, const char* source,
bool printErrors)
bool isExpression, bool printErrors)
{
Parser parser;
parser.vm = vm;
@@ -3415,29 +3416,39 @@ ObjFn* wrenCompile(WrenVM* vm, ObjModule* module, const char* source,
// Read the first token.
nextToken(&parser);
int numExistingVariables = module->variables.count;
Compiler compiler;
initCompiler(&compiler, &parser, NULL, true);
ignoreNewlines(&compiler);
while (!match(&compiler, TOKEN_EOF))
if (isExpression)
{
definition(&compiler);
// If there is no newline, it must be the end of the block on the same line.
if (!matchLine(&compiler))
{
consume(&compiler, TOKEN_EOF, "Expect end of file.");
break;
}
expression(&compiler);
}
emitOp(&compiler, CODE_NULL);
else
{
while (!match(&compiler, TOKEN_EOF))
{
definition(&compiler);
// If there is no newline, it must be the end of the block on the same line.
if (!matchLine(&compiler))
{
consume(&compiler, TOKEN_EOF, "Expect end of file.");
break;
}
}
emitOp(&compiler, CODE_NULL);
}
emitOp(&compiler, CODE_RETURN);
// See if there are any implicitly declared module-level variables that never
// got an explicit definition. They will have values that are numbers
// indicating the line where the variable was first used.
for (int i = 0; i < parser.module->variables.count; i++)
for (int i = numExistingVariables; i < parser.module->variables.count; i++)
{
if (IS_NUM(parser.module->variables.data[i]))
{
+5 -1
View File
@@ -26,10 +26,14 @@ typedef struct sCompiler Compiler;
// [ObjFn] that will execute that code when invoked. Returns `NULL` if the
// source contains any syntax errors.
//
// If [isExpression] is `true`, [source] should be a single expression, and
// this compiles it to a function that evaluates and returns that expression.
// Otherwise, [source] should be a series of top level statements.
//
// If [printErrors] is `true`, any compile errors are output to stderr.
// Otherwise, they are silently discarded.
ObjFn* wrenCompile(WrenVM* vm, ObjModule* module, const char* source,
bool printErrors);
bool isExpression, bool printErrors);
// When a class is defined, its superclass is not known until runtime since
// class definitions are just imperative statements. Most of the bytecode for a
+1 -1
View File
@@ -484,7 +484,7 @@ static ObjFiber* loadModule(WrenVM* vm, Value name, const char* source)
}
}
ObjFn* fn = wrenCompile(vm, module, source, true);
ObjFn* fn = wrenCompile(vm, module, source, false, true);
if (fn == NULL)
{
// TODO: Should we still store the module even if it didn't compile?