FunctionName ParseFunctionName() { if (NextToken().m_type != (int)TokenType.NAME) { throw NewParserException("expect 'id' after 'function'", _current); } var func_name = new FunctionName(_current.m_line); func_name.names.Add(_current); while (LookAhead().m_type == (int)'.') { NextToken(); if (NextToken().m_type != (int)TokenType.NAME) { throw NewParserException("unexpect token in function name after '.'", _current); } func_name.names.Add(_current); } return(func_name); }
void HandleFunctionName(FunctionName tree) { int func_register = GenerateRegisterId(); var f = GetCurrentFunction(); Instruction code = new Instruction(); var first_name = tree.names[0]; LexicalScope scope; int index = SearchNameAndScope(first_name.m_string, out scope); if (tree.names.Count == 1) { if (scope == LexicalScope.Global) { code = Instruction.ABx(OpType.OpType_SetGlobal, func_register, index); } else if (scope == LexicalScope.Upvalue) { code = Instruction.ABx(OpType.OpType_SetUpvalue, func_register, index); } else if (scope == LexicalScope.Local) { code = Instruction.AB(OpType.OpType_Move, index, func_register); } f.AddInstruction(code, first_name.m_line); } else { var table_register = GenerateRegisterId(); int key_register = GenerateRegisterId(); if (scope == LexicalScope.Global) { code = Instruction.ABx(OpType.OpType_GetGlobal, table_register, index); } else if (scope == LexicalScope.Upvalue) { code = Instruction.AB(OpType.OpType_GetUpvalue, table_register, index); } else if (scope == LexicalScope.Local) { code = Instruction.AB(OpType.OpType_Move, table_register, index); } f.AddInstruction(code, tree.line); Action <Token> load_key = (Token name) => { int l_index = f.AddConstString(name.m_string); CheckConstIdx(l_index); var l_code = Instruction.ABx(OpType.OpType_LoadConst, key_register, l_index); f.AddInstruction(l_code, name.m_line); }; for (int i = 1; i < tree.names.Count - 1; ++i) { load_key(tree.names[i]); code = Instruction.ABC(OpType.OpType_GetTable, table_register, key_register, table_register); f.AddInstruction(code, tree.line); } load_key(tree.names.Last <Token>()); code = Instruction.ABC(OpType.OpType_SetTable, table_register, key_register, func_register); f.AddInstruction(code, tree.line); } // 回收寄存器 ResetRegisterId(func_register); }