diff --git a/CMakeLists.txt b/CMakeLists.txt index f22fafb..c1a6ef9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,6 +173,7 @@ src/vm/filereader.cpp src/vm/gc.cpp src/vm/gclist.cpp src/vm/vm.cpp +src/vm/exception.cpp src/archive.cpp src/markedtobject.cpp ) diff --git a/include/CrossLang.hpp b/include/CrossLang.hpp index d28e1a7..e86dc3a 100644 --- a/include/CrossLang.hpp +++ b/include/CrossLang.hpp @@ -661,7 +661,8 @@ typedef enum { JMPIFBREAK, JMPIFCONTINUE, JMPIFDEFINED, - DECLARECONSTVARIABLE + DECLARECONSTVARIABLE, + LINEINFO } Instruction; /** * @brief Base type for bytecode instruction @@ -1239,6 +1240,10 @@ constexpr std::string_view AwaitExpression = "awaitExpression"; * @brief ?? operator */ constexpr std::string_view NullCoalescingExpression = "nullCoalescingExpression"; +/** + * @brief For debugging (store line info and filename) + */ +constexpr std::string_view LineNode="lineNode"; /** * @brief Advanced AST node * @@ -1315,8 +1320,11 @@ class Parser { void ParseHtml(std::vector& nodes,std::string var); GC* gc; TRootEnvironment* env; + int lastLine=-1; + std::string lastFile=""; + bool CanEmit(LexTokenLineInfo& token); public: - + bool debug=true; /** * @brief Construct a new Parser object * @@ -1455,6 +1463,7 @@ class GC { TFile* file; std::vector code; std::vector args; + std::optional name; void Mark(); }; @@ -1642,6 +1651,7 @@ class GC { void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb,std::function destroy); void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb,std::function destroy); TObject CallMethod(GCList& ls, std::string key, std::vector args); + TObject CallMethodWithFatalError(GCList& ls, std::string key, std::vector args); }; @@ -1655,9 +1665,12 @@ class GC { TObject tag; std::string documentation; virtual TObject Call(GCList& ls,std::vector args)=0; + TObject CallWithFatalError(GCList& ls, std::vector args); virtual void Mark(); }; + void ThrowFatalError(std::exception& ex); + void ThrowConstError(std::string key); class TEnvironment : public THeapObject { @@ -1694,7 +1707,7 @@ class GC { void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb,std::function destroy); void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb,std::function destroy); TObject CallFunction(GCList& ls, std::string key, std::vector args); - + TObject CallFunctionWithFatalError(GCList& ls, std::string key, std::vector args); }; class TClassEnvironment; class TClassObject : public THeapObject @@ -2134,18 +2147,21 @@ class GC { ~TDynamicDictionary(); }; - + class InterperterThread; class CallStackEntry : public THeapObject { public: static CallStackEntry* Create(GCList* ls); static CallStackEntry* Create(GCList& ls); + InterperterThread* thread; std::vector stack; TEnvironment* env; TClosure* callable; uint32_t ip; uint32_t scopes; + int64_t srcline; + std::string srcfile; bool mustReturn; void Mark(); @@ -2262,6 +2278,7 @@ class GC { bool PushContinue(GC* gc); bool JumpIfBreak(GC* gc); bool JumpIfContinue(GC* gc); + bool LineInfo(GC* gc); public: static InterperterThread* Create(GCList* ls); static InterperterThread* Create(GCList& ls); @@ -2387,22 +2404,30 @@ class GC { public: TObject exception; + std::vector stack_trace; + VMByteCodeException() { } - VMByteCodeException(GC* gc,TObject obj) + VMByteCodeException(GC* gc,TObject obj, CallStackEntry* ent) { gcList = std::make_shared(gc); - gcList.get()->Add(obj); + gcList->Add(obj); + if(ent != nullptr && ent->thread != nullptr) + { + this->stack_trace = ent->thread->call_stack_entries; + for(auto item : this->stack_trace) + gcList->Add(item); + } this->exception = obj; UpdateError(); } void UpdateError() { - lastErrorText = ToString(gcList.get()->GetGC(),exception); + lastErrorText = ToString(gcList->GetGC(),exception); } @@ -2410,14 +2435,19 @@ class GC { { return lastErrorText.c_str(); } + std::shared_ptr GetGCList() { + return this->gcList; + } }; class SyntaxException : public std::exception { std::string msg={}; + LexTokenLineInfo line; + std::string message; public: - SyntaxException(LexTokenLineInfo lineInfo, std::string message) + SyntaxException(LexTokenLineInfo lineInfo, std::string message) : line(lineInfo), message(message) { msg.append("in file: "); msg.append(lineInfo.filename); @@ -2434,6 +2464,9 @@ class GC { { return msg.c_str(); } + + std::string Message() { return message;} + LexTokenLineInfo LineInfo() { return line;} }; diff --git a/src/assembler/asm.cpp b/src/assembler/asm.cpp index e5df266..59e7f24 100644 --- a/src/assembler/asm.cpp +++ b/src/assembler/asm.cpp @@ -281,6 +281,10 @@ namespace Tesses::CrossLang { { instrs.push_back(std::make_shared(NOP)); } + else if(name == "lineinfo") + { + instrs.push_back(std::make_shared(LINEINFO)); + } else if(name == "pushclosure") { auto closure = std::make_shared(true); diff --git a/src/assembler/disasm.cpp b/src/assembler/disasm.cpp index a61582b..758f1da 100644 --- a/src/assembler/disasm.cpp +++ b/src/assembler/disasm.cpp @@ -571,6 +571,9 @@ namespace Tesses::CrossLang { case BREAKPOINT: buffer.append("breakpoint"); break; + case LINEINFO: + buffer.append("lineinfo"); + break; case PUSHBREAK: buffer.append("push break"); break; diff --git a/src/compiler/codegen.cpp b/src/compiler/codegen.cpp index f1858d0..9e2207a 100644 --- a/src/compiler/codegen.cpp +++ b/src/compiler/codegen.cpp @@ -522,7 +522,14 @@ namespace Tesses::CrossLang TWO_EXPR(NotEqualsExpression, NEQ) TWO_EXPR(EqualsExpression, EQ) TWO_EXPR(XOrExpression, XOR) - if(adv.nodeName == NullCoalescingExpression && adv.nodes.size() == 2) + if(adv.nodeName == LineNode && adv.nodes.size() == 2) + { + + GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); + GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); + instructions.push_back(new SimpleInstruction(LINEINFO)); + } + else if(adv.nodeName == NullCoalescingExpression && adv.nodes.size() == 2) { uint32_t ifId = NewId(); std::string ifIdTrue = "__compGenTrue"; diff --git a/src/compiler/parser.cpp b/src/compiler/parser.cpp index 3feafa4..349fa74 100644 --- a/src/compiler/parser.cpp +++ b/src/compiler/parser.cpp @@ -1304,6 +1304,15 @@ namespace Tesses::CrossLang } return node; } + bool Parser::CanEmit(LexTokenLineInfo& ifo) + { + if(!this->debug) return false; + bool same = ifo.line == this->lastLine && ifo.filename == this->lastFile; + this->lastFile = ifo.filename; + this->lastLine = ifo.line; + + return !same; + } SyntaxNode Parser::ParseNode(bool isRoot) { std::string documentation=""; @@ -1324,6 +1333,8 @@ namespace Tesses::CrossLang while(i < tokens.size() && (isRoot || !IsSymbol("}",false))) { + auto token = tokens[i]; + if(CanEmit(token.lineInfo)) aSN.nodes.push_back(AdvancedSyntaxNode::Create(LineNode,false, {(int64_t)tokens[i].lineInfo.line,tokens[i].lineInfo.filename})); aSN.nodes.push_back(ParseNode()); IsSymbol(";"); } diff --git a/src/crosslang.cpp b/src/crosslang.cpp index a033d86..852b7a5 100644 --- a/src/crosslang.cpp +++ b/src/crosslang.cpp @@ -127,7 +127,7 @@ int main(int argc, char** argv) for(int arg=1;argAdd(std::string(argv[arg])); - auto res = env->CallFunction(ls,"main",{args}); + auto res = env->CallFunctionWithFatalError(ls,"main",{args}); int64_t iresult; if(GetObject(res,iresult)) return (int)iresult; diff --git a/src/crosslangcompiler.cpp b/src/crosslangcompiler.cpp index 7e29fe1..2e8fa46 100644 --- a/src/crosslangcompiler.cpp +++ b/src/crosslangcompiler.cpp @@ -13,6 +13,7 @@ void Help(const char* filename) printf(" -I: Set icon resource name (in the resource folder), should be a 128x128 png\n"); printf(" -v: Set version (1.0.0.0-prod defaults to 1.0.0.0-dev)\n"); printf(" -d: Add dependency (DependencyName-1.0.0.0-prod)\n"); + printf(" -D: enable debug)\n"); printf(" -t: Declare a tool (ToolName-1.0.0.0-prod)\n"); printf(" -n: Set name (MyAppOrLibName defaults to out)\n"); printf(" -r: Set resource directory (RESDIR defaults to res)\n"); @@ -46,7 +47,7 @@ int main(int argc, char** argv) std::string icon=""; std::string comptime="none"; TVMVersion version; - + bool debug=false; @@ -56,6 +57,7 @@ int main(int argc, char** argv) { Help(argv[0]); } + else if(strcmp(argv[i], "-o") == 0) { i++; @@ -187,6 +189,10 @@ int main(int argc, char** argv) } } } + else if(strcmp(argv[i],"-D") == 0) + { + debug = true; + } else { source.push_back(argv[i]); } @@ -202,7 +208,7 @@ int main(int argc, char** argv) for(auto src : source) { std::ifstream strm(src,std::ios_base::in|std::ios_base::binary); - int res = Lex(argv[1],strm,tokens); + int res = Lex(std::filesystem::absolute(src).string(),strm,tokens); } @@ -248,7 +254,7 @@ int main(int argc, char** argv) } Parser parser(tokens,gc,env); - + parser.debug = debug; CodeGen gen; gen.GenRoot(parser.ParseRoot()); gen.name = name; diff --git a/src/crosslanginterperter.cpp b/src/crosslanginterperter.cpp index d99c88f..bea43c2 100644 --- a/src/crosslanginterperter.cpp +++ b/src/crosslanginterperter.cpp @@ -49,7 +49,7 @@ int main(int argc, char** argv) for(int arg=1;argAdd(std::string(argv[arg])); - auto res = env->CallFunction(ls,"main",{args}); + auto res = env->CallFunctionWithFatalError(ls,"main",{args}); int64_t iresult; if(GetObject(res,iresult)) return (int)iresult; diff --git a/src/crosslangvm.cpp b/src/crosslangvm.cpp index c42c973..1abe834 100644 --- a/src/crosslangvm.cpp +++ b/src/crosslangvm.cpp @@ -35,7 +35,7 @@ int main(int argc, char** argv) args2->Add(item); } - auto res = env->CallFunction(ls, "WebAppMain", {args2}); + auto res = env->CallFunctionWithFatalError(ls, "WebAppMain", {args2}); auto svr2 = Tesses::CrossLang::ToHttpServer(&gc,res); if(svr2 == nullptr) return 1; Tesses::Framework::Http::HttpServer svr(port,svr2); @@ -58,7 +58,7 @@ int main(int argc, char** argv) for(int arg=1;argAdd(std::string(argv[arg])); - auto res = env->CallFunction(ls,"main",{args}); + auto res = env->CallFunctionWithFatalError(ls,"main",{args}); int64_t iresult; if(GetObject(res,iresult)) return (int)iresult; diff --git a/src/runtime_methods/vm.cpp b/src/runtime_methods/vm.cpp index ea14aac..9789ec9 100644 --- a/src/runtime_methods/vm.cpp +++ b/src/runtime_methods/vm.cpp @@ -138,6 +138,7 @@ namespace Tesses::CrossLang std::vector> tools; std::string info; std::string icon; + bool debug=false; std::shared_ptr vfs; ls.GetGC()->BarrierBegin(); @@ -152,6 +153,7 @@ namespace Tesses::CrossLang TObject _resourceFileSystem = dict->GetValue("ResourceFileSystem"); TObject _out = dict->GetValue("Output"); + TObject _dbg = dict->GetValue("Debug"); TList* _toolList; TList* _depList; TList* srcLst; TRootEnvironment* comptimeEnv=nullptr; @@ -160,6 +162,7 @@ namespace Tesses::CrossLang GetObject(_icon,icon); GetObject(_resourceFileSystem, vfs); GetObjectHeap(_comptime,comptimeEnv); + GetObject(_dbg,debug); std::string v2; if(GetObject(_version,v2)) TVMVersion::TryParse(v2, version); @@ -258,6 +261,7 @@ namespace Tesses::CrossLang } } Parser parser(tokens,ls.GetGC(),comptimeEnv); + parser.debug = debug; SyntaxNode n = parser.ParseRoot(); CodeGen gen; gen.GenRoot(n); @@ -282,11 +286,43 @@ namespace Tesses::CrossLang return Failure(ls, ex.what()); } } + static TObject VM_GetStacktrace(GCList& ls, std::vector args) + { + if(current_function != nullptr) + { + if(current_function->thread != nullptr) + { + TList* list = TList::Create(ls); + ls.GetGC()->BarrierBegin(); + for(auto item : current_function->thread->call_stack_entries) + { + auto dict = TDictionary::Create(ls); + if(item->callable->closure->name) + dict->SetValue("Name", *item->callable->closure->name); + + dict->SetValue("Closure", item->callable->closure); + dict->SetValue("FileName", item->callable->file->name + "-" + item->callable->file->version.ToString() + ".crvm"); + dict->SetValue("IP",(int64_t)item->ip); + if(item->srcline >= 1) + { + dict->SetValue("SourceFile", item->srcfile); + dict->SetValue("SourceLine",item->srcline); + } + list->Add(dict); + } + ls.GetGC()->BarrierEnd(); + return list; + } + } + return nullptr; + } void TStd::RegisterVM(GC* gc,TRootEnvironment* env) { env->permissions.canRegisterVM=true; GCList ls(gc); + TDictionary* dict = TDictionary::Create(ls); + dict->DeclareFunction(gc, "GetStacktrace","Get the current stack trace", {}, VM_GetStacktrace); dict->DeclareFunction(gc, "getRootEnvironmentAsDictionary","Get root environment as a dictionary",{},[env](GCList& ls, std::vector args)-> TObject{ return env->GetDictionary(); }); diff --git a/src/types/class.cpp b/src/types/class.cpp index e7dc9fa..c1938d7 100644 --- a/src/types/class.cpp +++ b/src/types/class.cpp @@ -154,6 +154,7 @@ namespace Tesses::CrossLang else { auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId); + clos->closure->name = obj->name + "::" + ent.name; clos->className = ownerNow; clos->documentation = entry.documentation; ent.value = clos; @@ -163,6 +164,7 @@ namespace Tesses::CrossLang if(entry.isAbstract) ent.value = Undefined(); else { auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId); + clos->closure->name = obj->name + "::" + ent.name; clos->className = ownerNow; ent.value = clos->Call(*ls,{}); } diff --git a/src/types/dictionary.cpp b/src/types/dictionary.cpp index cc671b1..aab8d01 100644 --- a/src/types/dictionary.cpp +++ b/src/types/dictionary.cpp @@ -126,6 +126,33 @@ namespace Tesses::CrossLang { } return Undefined(); } + TObject TDictionary::CallMethodWithFatalError(GCList& ls, std::string key, std::vector args) + { + ls.GetGC()->BarrierBegin(); + auto res = this->GetValue(key); + ls.GetGC()->BarrierEnd(); + TCallable* callable; + + if(GetObjectHeap(res,callable)) + { + auto closure = dynamic_cast(callable); + if(closure != nullptr && !closure->closure->args.empty() && closure->closure->args.front() == "this") + { + std::vector args2; + args2.push_back(this); + args2.insert(args2.end(), args.begin(),args.end()); + return closure->CallWithFatalError(ls,args2); + + } + else + { + return callable->CallWithFatalError(ls,args); + + } + } + return Undefined(); + } + void TDictionary::DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector argNames, std::function args)> cb) { gc->BarrierBegin(); @@ -204,4 +231,5 @@ namespace Tesses::CrossLang { _gc->Watch(dict); return dict; } + }; \ No newline at end of file diff --git a/src/types/rootenvironment.cpp b/src/types/rootenvironment.cpp index 9b2dfea..e84d44c 100644 --- a/src/types/rootenvironment.cpp +++ b/src/types/rootenvironment.cpp @@ -118,6 +118,7 @@ namespace Tesses::CrossLang { throw VMException("Lex error at line: " + std::to_string(res)); } Parser parser(tokens); + SyntaxNode n = parser.ParseRoot(); CodeGen gen; gen.GenRoot(n); @@ -230,6 +231,9 @@ namespace Tesses::CrossLang { std::vector method=file->classes[i].name; method.push_back(meth.name); auto clo = TClosure::Create(ls,this,file,meth.chunkId); + clo->closure->name = JoinPeriod(method); + + clo->documentation = meth.documentation; this->DeclareVariable(gc, method, clo); } @@ -239,7 +243,6 @@ namespace Tesses::CrossLang { for(auto fn : file->functions) { - std::string name; if(fn.first.size() < 2) throw VMException("No function name."); @@ -248,6 +251,7 @@ namespace Tesses::CrossLang { if(fn.second >= file->chunks.size()) throw VMException("ChunkId out of bounds."); TFileChunk* chunk = file->chunks[fn.second]; + chunk->name = JoinPeriod(items); GCList ls(gc); TClosure* closure=TClosure::Create(ls,this,file,fn.second); closure->documentation = fn.first[0]; diff --git a/src/types/subenvironment.cpp b/src/types/subenvironment.cpp index 37d8c53..ea9e418 100644 --- a/src/types/subenvironment.cpp +++ b/src/types/subenvironment.cpp @@ -163,6 +163,19 @@ namespace Tesses::CrossLang { } return Undefined(); } + TObject TEnvironment::CallFunctionWithFatalError(GCList& ls, std::string key, std::vector args) + { + ls.GetGC()->BarrierBegin(); + auto res = this->GetVariable(key); + ls.GetGC()->BarrierEnd(); + TCallable* callable; + + if(GetObjectHeap(res,callable)) + { + return callable->CallWithFatalError(ls,args); + } + return Undefined(); + } TSubEnvironment* TEnvironment::GetSubEnvironment(GCList* gc) { auto dict=TDictionary::Create(gc); diff --git a/src/vm/exception.cpp b/src/vm/exception.cpp new file mode 100644 index 0000000..16446d4 --- /dev/null +++ b/src/vm/exception.cpp @@ -0,0 +1,107 @@ +#include "CrossLang.hpp" + +namespace Tesses::CrossLang { + TObject TCallable::CallWithFatalError(GCList& ls, std::vector args) + { + try { + return Call(ls,args); + } + catch(VMByteCodeException& ex) + { + ThrowFatalError(ex); + } + catch(VMException& ex) + { + ThrowFatalError(ex); + } + catch(SyntaxException& ex) + { + ThrowFatalError(ex); + } + catch(std::runtime_error& ex) + { + ThrowFatalError(ex); + } + catch(std::exception& ex) + { + ThrowFatalError(ex); + } + return (int64_t)1; + } + void ThrowFatalError(std::exception& ex) + { + using namespace Tesses::Framework::TextStreams; + std::exception* ex2 = &ex; + auto clexcept = dynamic_cast(ex2); + auto clrtexcept = dynamic_cast(ex2); + auto compiler = dynamic_cast(ex2); + Tesses::Framework::TextStreams::ConsoleWriter error(true); + + if(clexcept != nullptr) + { + error.WriteLine("CrossLang has encountered a fatal exception"); + error.WriteLine(); + + error.WriteLine(ToString(clexcept->GetGCList()->GetGC(),clexcept->exception)); + error.WriteLine(); + error.WriteLine("STACKTRACE:"); + + for(auto ittr = clexcept->stack_trace.crbegin(); ittr != clexcept->stack_trace.crend(); ittr++) + { + auto item = *ittr; + std::string text = "\t"; + text += item->callable->closure->name.value_or((std::string)""); + text += "("; + bool first=true; + for(auto& arg : item->callable->closure->args) + { + if(!first) text += ", "; + text += arg; + first=false; + } + text += ")"; + if(item->srcline >= 1) + { + text += " at "; + text += item->srcfile; + text += ":"; + text += std::to_string(item->srcline); + } + error.WriteLine(text); + } + + exit(1); + } + if(clrtexcept != nullptr) + { + error.WriteLine("CrossLang has encountered a fatal runtime exception"); + error.WriteLine(); + error.WriteLine(clrtexcept->what()); + exit(1); + } + if(compiler != nullptr) + { + error.WriteLine("CrossLang has encountered a compiler error"); + error.WriteLine(); + error.WriteLine(compiler->Message()); + error.WriteLine(); + auto li = compiler->LineInfo(); + error.Write("in file: "); + error.Write(li.filename); + error.Write(":"); + error.Write((int64_t)li.line); + error.Write(":"); + error.Write((int64_t)li.column); + error.Write(":"); + error.WriteLine((int64_t)li.offset); + + exit(1); + } + + error.WriteLine("CrossLang has encountered a fatal C++ exception"); + error.WriteLine(); + error.Write("what(): "); + error.WriteLine(ex2->what()); + exit(1); + } +} \ No newline at end of file diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 12c20d6..6366f65 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -4237,7 +4237,7 @@ namespace Tesses::CrossLang { if(args.size() > 0) { try { - throw VMByteCodeException(gc,args[0]); + throw VMByteCodeException(gc,args[0],cse.back()); } catch(...) { ttask->SetFailed(std::current_exception()); } @@ -7012,7 +7012,7 @@ namespace Tesses::CrossLang { { auto env = cse.back()->env; if(!env->GetRootEnvironment()->HandleException(gc,env, _res2)) - throw VMByteCodeException(gc,_res2); + throw VMByteCodeException(gc,_res2,cse.back()); } return false; } @@ -7167,6 +7167,24 @@ namespace Tesses::CrossLang { auto stk = cse.back(); stk->Push(gc,Undefined()); + return false; + } + bool InterperterThread::LineInfo(GC* gc) + { + GCList ls(gc); + std::vector& cse=this->call_stack_entries; + auto stk = cse.back(); + auto file = stk->Pop(ls); + auto line = stk->Pop(ls); + + //Set the fields in this cse + GetObject(file,stk->srcfile); + GetObject(line,stk->srcline); + + //TODO: implement lines (this will make the language work until we get it rigged up) + + + return false; } bool InterperterThread::PushFalse(GC* gc) @@ -7867,6 +7885,9 @@ namespace Tesses::CrossLang { { CallStackEntry* cse = new CallStackEntry(); cse->mustReturn=false; + cse->srcline = -1; + cse->srcfile = ""; + cse->thread=nullptr; GC* _gc = ls.GetGC(); ls.Add(cse); _gc->Watch(cse); @@ -7877,6 +7898,9 @@ namespace Tesses::CrossLang { { CallStackEntry* cse = new CallStackEntry(); cse->mustReturn=false; + cse->srcline = -1; + cse->srcfile = ""; + cse->thread=nullptr; GC* _gc = ls->GetGC(); ls->Add(cse); _gc->Watch(cse); @@ -7886,6 +7910,7 @@ namespace Tesses::CrossLang { { ls.GetGC()->BarrierBegin(); CallStackEntry* cse = CallStackEntry::Create(ls); + cse->thread = this; cse->callable = closure; cse->env = closure->chunkId == 0 ? closure->env : closure->ownScope ? closure->env->GetSubEnvironment(ls) : closure->env; cse->ip = 0; diff --git a/src/vm/vm_opcode_table.h b/src/vm/vm_opcode_table.h index 9df75cb..f21914e 100644 --- a/src/vm/vm_opcode_table.h +++ b/src/vm/vm_opcode_table.h @@ -64,7 +64,7 @@ static opcode opcodes[256]={ &InterperterThread::JumpIfContinue, &InterperterThread::JumpIfDefined, &InterperterThread::DeclareConstVariable, - &InterperterThread::Illegal, + &InterperterThread::LineInfo, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal,