static void Parse(lua_State* L, void* userData) { // We currently can't run the GC while parsing because some objects used by // the parser are not properly stored in a root location. ParseArgs* args = static_cast<ParseArgs*>(userData); Input input; Input_Initialize(L, &input, args->reader, args->userdata); Prototype* prototype = NULL; if (Input_PeekByte(&input) == '\033') { // The data is a pre-compiled binary. prototype = LoadBinary(L, &input, args->name); } else { prototype = Parse(L, &input, args->name); } ASSERT(prototype != NULL); PushPrototype(L, prototype); Table* env = L->globals.table; Closure* closure = Closure_Create(L, prototype, env); PushClosure(L, closure); // Initialize the up values. Typically a top level check won't have any up // values, but if the chunk was created using string.dump or a similar method // it may. These up values will cease to function once the chunk is loaded. for (int i = 0; i < closure->lclosure.numUpValues; ++i) { closure->lclosure.upValue[i] = UpValue_Create(L); } // Remove the prototype from the stack. ASSERT( (L->stackTop - 2)->object == prototype ); State_Remove(L, L->stackTop - 2); }
Prototype* Function_CreatePrototype(lua_State* L, Function* function, String* source) { int convertedCodeSize = Prototype_GetConvertedCodeSize( function->code, function->codeSize ); Prototype* prototype = Prototype_Create( L, function->codeSize, convertedCodeSize, function->numConstants, function->numFunctions, function->numUpValues); PushPrototype(L, prototype); // Store the up values. memcpy(prototype->upValue, function->upValue, sizeof(String*) * function->numUpValues); // Store the code. memcpy(prototype->code, function->code, function->codeSize * sizeof(Instruction)); // Store the source information. prototype->source = source; Gc_IncrementReference(&L->gc, prototype, prototype->source); memcpy(prototype->sourceLine, function->sourceLine, function->codeSize * sizeof(int)); // Store the functions. for (int i = 0; i < function->numFunctions; ++i) { prototype->prototype[i] = Function_CreatePrototype(L, function->function[i], source); Gc_IncrementReference(&L->gc, prototype, prototype->prototype[i]); } // Store the constants. Value key; SetNil(&key); Table* constants = function->constants; const Value* value; while (value = Table_Next(L, constants, &key)) { int i; if (!Value_GetIsInteger(value, &i)) { ASSERT(0); } if (Value_GetIsTable(&key) && key.table == constants) { // The table itself is used to indicate nil values since nil values // cannot be saved in the table. SetNil(&prototype->constant[i]); } else { prototype->constant[i] = key; } Gc_IncrementReference(&L->gc, prototype, &prototype->constant[i]); } prototype->varArg = function->varArg; prototype->numParams = function->numParams; prototype->maxStackSize = function->maxStackSize; prototype->numUpValues = function->numUpValues; prototype->lineDefined = 0; prototype->lastLineDefined = 0; //PrintFunction(prototype); ASSERT( (L->stackTop - 1)->object == prototype ); Pop(L, 1); return prototype; }