Share

MAXScript Compiler and Interpreter

The MAXScript engine executes MAXScript code using the following steps:

  • First a Parser object (found in maxscrpt\parser.h) is instantiated with an output stream (i.e. a CharStream object found maxscrpt\streams.h) for debugging and error output.
  • Next the Parser::Compile(CharStream*) method is called, which will return an expression that can be executed represented as a Value*. This might be CodeTree instance, but could also be a simple literal.
  • The method Value::eval() is then called to the CodeTree instance or do nothing if the Value is a literal..

The following code snippet (from maxsdk\howto\maxscript\testdlx\tester.cpp) demonstrates these steps:

static Value* file_in(CharStream* source, MAXScript::ScriptSource scriptSource, int quiet)
{
    ScopedMaxScriptEvaluationContext scopedMaxScriptEvaluationContext;
    MAXScript_TLS* _tls = scopedMaxScriptEvaluationContext.Get_TLS();
    three_typed_value_locals_tls(Parser* parser, Value* code, Value* result);

    CharStream* out = _tls->current_stdout;
    if (!quiet)
        source->log_to(out);

    save_current_source_tls();
    MacroRecorder::MacroRecorderDisable macroRecorderDisable;
    // loop through stream compiling & evaluating all expressions
    try
    {
        // make a new compiler instance
        vl.parser = new Parser (out);
        source->flush_whitespace();
        while (!source->at_eos() || vl.parser->back_tracked)
        {
            vl.code = vl.parser->compile(source, scriptSource);
            vl.result = vl.code->eval();
            if (!quiet)
                vl.result->print();
            source->flush_whitespace();
        }
        if (vl.parser->expr_level != 0 || vl.parser->back_tracked && vl.parser->token != t_end)
            throw RuntimeError (MaxSDK::GetResourceStringAsMSTR(IDS_UNEXPECTED_END_OF_FILE_DURING_FILEIN));
        source->close();
    }
    catch (...)
    {
        // catch any errors and tell what file we are in if any
        out->puts(_T("Error occurred during fileIn: "));
        source->sprin1(out);
        out->puts(_T("\n"));
        source->close();
        restore_current_source_tls();
        throw;
    }
    restore_current_source_tls();

    // if there was one, return last expression in stream as result
    if (vl.result == NULL)
        vl.result = &ok;
    else
        vl.result = vl.result->get_heap_ptr();
    return_value_tls(vl.result);
}

Was this information helpful?