initial commit
This commit is contained in:
		
						commit
						837bc19293
					
				
					 31 changed files with 3301 additions and 0 deletions
				
			
		
							
								
								
									
										31
									
								
								LightScript.sln
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								LightScript.sln
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Microsoft Visual Studio Solution File, Format Version 12.00
 | 
				
			||||||
 | 
					# Visual Studio 15
 | 
				
			||||||
 | 
					VisualStudioVersion = 15.0.27004.2006
 | 
				
			||||||
 | 
					MinimumVisualStudioVersion = 10.0.40219.1
 | 
				
			||||||
 | 
					Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LightScript", "LightScript\LightScript.vcxproj", "{99DA223F-E88F-4E97-A314-E798486955A8}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
 | 
					Global
 | 
				
			||||||
 | 
						GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
				
			||||||
 | 
							Debug|x64 = Debug|x64
 | 
				
			||||||
 | 
							Debug|x86 = Debug|x86
 | 
				
			||||||
 | 
							Release|x64 = Release|x64
 | 
				
			||||||
 | 
							Release|x86 = Release|x86
 | 
				
			||||||
 | 
						EndGlobalSection
 | 
				
			||||||
 | 
						GlobalSection(ProjectConfigurationPlatforms) = postSolution
 | 
				
			||||||
 | 
							{99DA223F-E88F-4E97-A314-E798486955A8}.Debug|x64.ActiveCfg = Debug|x64
 | 
				
			||||||
 | 
							{99DA223F-E88F-4E97-A314-E798486955A8}.Debug|x64.Build.0 = Debug|x64
 | 
				
			||||||
 | 
							{99DA223F-E88F-4E97-A314-E798486955A8}.Debug|x86.ActiveCfg = Debug|Win32
 | 
				
			||||||
 | 
							{99DA223F-E88F-4E97-A314-E798486955A8}.Debug|x86.Build.0 = Debug|Win32
 | 
				
			||||||
 | 
							{99DA223F-E88F-4E97-A314-E798486955A8}.Release|x64.ActiveCfg = Release|x64
 | 
				
			||||||
 | 
							{99DA223F-E88F-4E97-A314-E798486955A8}.Release|x64.Build.0 = Release|x64
 | 
				
			||||||
 | 
							{99DA223F-E88F-4E97-A314-E798486955A8}.Release|x86.ActiveCfg = Release|Win32
 | 
				
			||||||
 | 
							{99DA223F-E88F-4E97-A314-E798486955A8}.Release|x86.Build.0 = Release|Win32
 | 
				
			||||||
 | 
						EndGlobalSection
 | 
				
			||||||
 | 
						GlobalSection(SolutionProperties) = preSolution
 | 
				
			||||||
 | 
							HideSolutionNode = FALSE
 | 
				
			||||||
 | 
						EndGlobalSection
 | 
				
			||||||
 | 
						GlobalSection(ExtensibilityGlobals) = postSolution
 | 
				
			||||||
 | 
							SolutionGuid = {E7E084EF-B1D4-4770-BAE8-A037A0458A76}
 | 
				
			||||||
 | 
						EndGlobalSection
 | 
				
			||||||
 | 
					EndGlobal
 | 
				
			||||||
							
								
								
									
										210
									
								
								LightScript/AST.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								LightScript/AST.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,210 @@
 | 
				
			||||||
 | 
					#include "AST.h"
 | 
				
			||||||
 | 
					#include "ByteCode.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_Ident::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						t.push(code_t::push, BoxedVar(name));
 | 
				
			||||||
 | 
						t.push(code_t::load);
 | 
				
			||||||
 | 
						return 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_SentenceList::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
						for (auto & it : sentences) {
 | 
				
			||||||
 | 
							ret += it->generateCode(t);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_CommonSentence::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = expression->generateCode(t);
 | 
				
			||||||
 | 
						t.push(code_t::pop);
 | 
				
			||||||
 | 
						return ret + 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_VarSentence::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = RHS->generateCode(t);
 | 
				
			||||||
 | 
						t.push(code_t::push, BoxedVar(LHS->name));
 | 
				
			||||||
 | 
						t.push(code_t::new_var);
 | 
				
			||||||
 | 
						return ret + 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_AssignmentSentence::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = RHS->generateCode(t);
 | 
				
			||||||
 | 
						ret += LHS->generateCode(t);
 | 
				
			||||||
 | 
						t.push(code_t::store);
 | 
				
			||||||
 | 
						return ret + 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_Binary::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = RHS->generateCode(t);
 | 
				
			||||||
 | 
						ret += LHS->generateCode(t);
 | 
				
			||||||
 | 
						t.push(static_cast<code_t>(op));
 | 
				
			||||||
 | 
						return ret + 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_Unary::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = LHS->generateCode(t);
 | 
				
			||||||
 | 
						t.push(static_cast<code_t>(op));
 | 
				
			||||||
 | 
						return ret + 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_While::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						t.loopStart();
 | 
				
			||||||
 | 
						int ret = condition->generateCode(t);
 | 
				
			||||||
 | 
						t.push(code_t::push, BoxedVar());
 | 
				
			||||||
 | 
						auto e = t.currentPos();
 | 
				
			||||||
 | 
						t.push(code_t::jf);
 | 
				
			||||||
 | 
						ret += 2;
 | 
				
			||||||
 | 
						auto r = ret;
 | 
				
			||||||
 | 
						t.push(code_t::enterScope);
 | 
				
			||||||
 | 
						ret++;
 | 
				
			||||||
 | 
						ret += sentences->generateCode(t);
 | 
				
			||||||
 | 
						t.push(code_t::leaveScope);
 | 
				
			||||||
 | 
						ret++;
 | 
				
			||||||
 | 
						ret++;
 | 
				
			||||||
 | 
						t.push(code_t::push, BoxedVar(-ret));
 | 
				
			||||||
 | 
						t.push(code_t::jmp);
 | 
				
			||||||
 | 
						ret++;
 | 
				
			||||||
 | 
						t.loopEnd();
 | 
				
			||||||
 | 
						t.set(e, BoxedVar(ret + 1 - r));
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_If::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = condition->generateCode(t);
 | 
				
			||||||
 | 
						ret++;
 | 
				
			||||||
 | 
						t.push(code_t::push, BoxedVar());
 | 
				
			||||||
 | 
						auto r = ret;
 | 
				
			||||||
 | 
						auto e = t.currentPos();
 | 
				
			||||||
 | 
						t.push(code_t::jf);
 | 
				
			||||||
 | 
						t.push(code_t::enterScope);
 | 
				
			||||||
 | 
						ret += 3;
 | 
				
			||||||
 | 
						ret += ifSentence->generateCode(t);
 | 
				
			||||||
 | 
						t.push(code_t::leaveScope);
 | 
				
			||||||
 | 
						ret++;
 | 
				
			||||||
 | 
						t.set(e, BoxedVar(ret - r + (elseSentence != nullptr ? 1 : 0) /*뒤의 명령어 갯수*/));
 | 
				
			||||||
 | 
						if (elseSentence != nullptr) {
 | 
				
			||||||
 | 
							t.push(code_t::jmp, BoxedVar());
 | 
				
			||||||
 | 
							auto cur = ret;
 | 
				
			||||||
 | 
							auto code_operand_address = t.currentPos();
 | 
				
			||||||
 | 
							t.push(code_t::enterScope);
 | 
				
			||||||
 | 
							ret++;
 | 
				
			||||||
 | 
							ret += elseSentence->generateCode(t);
 | 
				
			||||||
 | 
							t.push(code_t::leaveScope);
 | 
				
			||||||
 | 
							ret++;
 | 
				
			||||||
 | 
							t.set(code_operand_address, BoxedVar(ret - cur));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_Dot::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = 2;
 | 
				
			||||||
 | 
						t.push(code_t::push, BoxedVar(RHS->name));
 | 
				
			||||||
 | 
						ret += LHS->generateCode(t);
 | 
				
			||||||
 | 
						t.push(code_t::ref);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_Index::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = 1;
 | 
				
			||||||
 | 
						ret += RHS->generateCode(t);
 | 
				
			||||||
 | 
						ret += LHS->generateCode(t);
 | 
				
			||||||
 | 
						t.push(code_t::ref);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_ForIn::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = 1;
 | 
				
			||||||
 | 
						t.push(code_t::enterScope);
 | 
				
			||||||
 | 
						ret += iterable->generateCode(t);
 | 
				
			||||||
 | 
						t.push(code_t::getiter);
 | 
				
			||||||
 | 
						t.push(code_t::push, BoxedVar());
 | 
				
			||||||
 | 
						t.push(code_t::push, BoxedVar(id->name));
 | 
				
			||||||
 | 
						t.push(code_t::new_var);
 | 
				
			||||||
 | 
						ret += 4;
 | 
				
			||||||
 | 
						t.loopStart();
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							t.push(code_t::isEnd);
 | 
				
			||||||
 | 
							t.push(code_t::push, BoxedVar(3));
 | 
				
			||||||
 | 
							t.push(code_t::jf);
 | 
				
			||||||
 | 
							t.registerBreak();
 | 
				
			||||||
 | 
							t.push(code_t::getvalue);
 | 
				
			||||||
 | 
							t.push(code_t::push, BoxedVar(id->name));
 | 
				
			||||||
 | 
							t.push(code_t::store);
 | 
				
			||||||
 | 
							ret += 8;
 | 
				
			||||||
 | 
							ret += sentences->generateCode(t);
 | 
				
			||||||
 | 
							t.push(code_t::next);
 | 
				
			||||||
 | 
							ret++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ret += t.registerContinue();
 | 
				
			||||||
 | 
						t.push(code_t::pop);
 | 
				
			||||||
 | 
						t.push(code_t::leaveScope);
 | 
				
			||||||
 | 
						ret += 2;
 | 
				
			||||||
 | 
						t.loopEnd();
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_CallExpr::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
						int argnum = 0;
 | 
				
			||||||
 | 
						for (auto it = args.rbegin(); it != args.rend(); it++) {
 | 
				
			||||||
 | 
							ret += (*it)->generateCode(t);
 | 
				
			||||||
 | 
							argnum++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.push(code_t::push, BoxedVar(argnum));
 | 
				
			||||||
 | 
						ret++;
 | 
				
			||||||
 | 
						ret += callee->generateCode(t);
 | 
				
			||||||
 | 
						t.push(code_t::call);
 | 
				
			||||||
 | 
						return ret + 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_Break::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return t.registerBreak();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_Continue::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return t.registerContinue();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_Function::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{	//일단 가변적인 인자 고려없이 이렇게 짬.
 | 
				
			||||||
 | 
						static int64_t num=0;
 | 
				
			||||||
 | 
						auto c = std::unique_ptr<FunctionCode, FunctionCodeDeleter>(new FunctionCode);
 | 
				
			||||||
 | 
						auto presentFrame = t.getFrame();
 | 
				
			||||||
 | 
						t.setFrame(c.get());
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							t.push(code_t::pop);
 | 
				
			||||||
 | 
							t.push(code_t::enterScope);
 | 
				
			||||||
 | 
							for (auto & it : args){
 | 
				
			||||||
 | 
								t.push(code_t::push, BoxedVar(it->name));
 | 
				
			||||||
 | 
								t.push(code_t::new_var);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							sentences->generateCode(t);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.setFrame(presentFrame);
 | 
				
			||||||
 | 
						t.push(code_t::push, BoxedVar( std::to_string(num++), move(c) )
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ls::AST_Return::generateCode(GenerationContext & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = return_value->generateCode(t);
 | 
				
			||||||
 | 
						t.push(code_t::ret);
 | 
				
			||||||
 | 
						return ret + 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										439
									
								
								LightScript/AST.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										439
									
								
								LightScript/AST.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,439 @@
 | 
				
			||||||
 | 
					#include<string>
 | 
				
			||||||
 | 
					#include<memory>
 | 
				
			||||||
 | 
					#include<ostream>
 | 
				
			||||||
 | 
					#include<cstdint>
 | 
				
			||||||
 | 
					#include<list>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include"Operators.h"
 | 
				
			||||||
 | 
					#include"CompoundType.h"
 | 
				
			||||||
 | 
					#include"CodeGeneration.h"
 | 
				
			||||||
 | 
					#include"LuaScriptGeneration.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LS_AST_H_
 | 
				
			||||||
 | 
					#define LS_AST_H_
 | 
				
			||||||
 | 
					namespace ls {
 | 
				
			||||||
 | 
						using std::move;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class AST_Sentence
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &) = 0;
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream &) = 0;
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext &) = 0;
 | 
				
			||||||
 | 
							virtual ~AST_Sentence() {}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_SentenceList : public AST_Sentence {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							void push_back(std::unique_ptr<AST_Sentence> s) {
 | 
				
			||||||
 | 
								sentences.emplace_back(move(s));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) override {
 | 
				
			||||||
 | 
								for (auto & it : sentences) {
 | 
				
			||||||
 | 
									it->printDebugInfo(os);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								for (auto & it : sentences)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									lsgc.sentence_tap();
 | 
				
			||||||
 | 
									it->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							std::list< std::unique_ptr<AST_Sentence> > sentences;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_Expr {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &) = 0;
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext &) = 0;
 | 
				
			||||||
 | 
							//Twin String 만들어야지. 나중에 바꾼다.
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream &) = 0;
 | 
				
			||||||
 | 
							virtual ~AST_Expr() {}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						//Lvalue 표현식 생각 날 때까지 미룸.
 | 
				
			||||||
 | 
						class AST_Variable : public AST_Expr {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class AST_Ident : public AST_Variable {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_Ident(const std::string & s) :name(s) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) {
 | 
				
			||||||
 | 
								os << name;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								lsgc.out() << name;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string name;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						inline std::ostream & operator<<(std::ostream & os, std::unique_ptr<AST_Sentence> & rhs) {
 | 
				
			||||||
 | 
							rhs->printDebugInfo(os);
 | 
				
			||||||
 | 
							return os;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inline std::ostream & operator<<(std::ostream & os, std::unique_ptr<AST_SentenceList> & rhs) {
 | 
				
			||||||
 | 
							rhs->printDebugInfo(os);
 | 
				
			||||||
 | 
							return os;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inline std::ostream & operator<<(std::ostream & os, std::unique_ptr<AST_Expr> & rhs) {
 | 
				
			||||||
 | 
							rhs->printDebugInfo(os);
 | 
				
			||||||
 | 
							return os;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inline std::ostream & operator<<(std::ostream & os, std::unique_ptr<AST_Variable> & rhs) {
 | 
				
			||||||
 | 
							rhs->printDebugInfo(os);
 | 
				
			||||||
 | 
							return os;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inline std::ostream & operator<<(std::ostream & os, std::unique_ptr<AST_Ident> & rhs) {
 | 
				
			||||||
 | 
							rhs->printDebugInfo(os);
 | 
				
			||||||
 | 
							return os;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						class AST_CommonSentence : public AST_Sentence {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_CommonSentence(std::unique_ptr<AST_Expr> expr) :expression(move(expr)) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) override {
 | 
				
			||||||
 | 
								os << expression << "\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								expression->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << "\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> expression;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_VarSentence : public AST_Sentence {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							AST_VarSentence(std::unique_ptr<AST_Ident> lhs, std::unique_ptr<AST_Expr> rhs)
 | 
				
			||||||
 | 
								:LHS(move(lhs)), RHS(move(rhs)) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext & t);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) override {
 | 
				
			||||||
 | 
								os  <<"var "<< LHS <<" = " << RHS << "\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								if (lsgc.depth > 0){
 | 
				
			||||||
 | 
									lsgc.out() << "local ";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								lsgc.out() << LHS->name << " = ";
 | 
				
			||||||
 | 
								RHS->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << "\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Ident> LHS;
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> RHS;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_AssignmentSentence : public AST_Sentence {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							AST_AssignmentSentence(std::unique_ptr<AST_Expr> lhs, std::unique_ptr<AST_Expr> rhs)
 | 
				
			||||||
 | 
								:LHS(move(lhs)), RHS(move(rhs)) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext & t);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) override {
 | 
				
			||||||
 | 
								os << LHS << " = " << RHS << "\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								LHS->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << " = ";
 | 
				
			||||||
 | 
								RHS->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << "\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> LHS;
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> RHS;
 | 
				
			||||||
 | 
						}; 
 | 
				
			||||||
 | 
						class AST_If : public AST_Sentence {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_If(std::unique_ptr<AST_Expr> cond, std::unique_ptr<AST_SentenceList> s)
 | 
				
			||||||
 | 
								:condition(move(cond)), ifSentence(move(s)),elseSentence(nullptr) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							void setElse(std::unique_ptr<AST_SentenceList> e) { elseSentence = move(e); }
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) override {
 | 
				
			||||||
 | 
								os << "if " << condition << " then\n";
 | 
				
			||||||
 | 
								os << ifSentence;
 | 
				
			||||||
 | 
								if (elseSentence != nullptr)
 | 
				
			||||||
 | 
									os << "else\n" << elseSentence;
 | 
				
			||||||
 | 
								os << "end\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								lsgc.out() << "if ";
 | 
				
			||||||
 | 
								condition->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << " then\n";
 | 
				
			||||||
 | 
								lsgc.depth++;
 | 
				
			||||||
 | 
								ifSentence->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								if (elseSentence != nullptr) {
 | 
				
			||||||
 | 
									lsgc.out() << "else\n";
 | 
				
			||||||
 | 
									elseSentence->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								lsgc.out() << "end\n";
 | 
				
			||||||
 | 
								lsgc.depth--;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> condition;
 | 
				
			||||||
 | 
							std::unique_ptr<AST_SentenceList> ifSentence;
 | 
				
			||||||
 | 
							std::unique_ptr<AST_SentenceList> elseSentence;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_While : public AST_Sentence {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_While(std::unique_ptr<AST_Expr> cond, std::unique_ptr<AST_SentenceList> s)
 | 
				
			||||||
 | 
								:condition(move(cond)),sentences(move(s)) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) override {
 | 
				
			||||||
 | 
								os << "while " << condition << " do\n";
 | 
				
			||||||
 | 
								sentences->printDebugInfo(os);
 | 
				
			||||||
 | 
								os << "end\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								lsgc.out() << "while ";
 | 
				
			||||||
 | 
								condition->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << " do\n";
 | 
				
			||||||
 | 
								lsgc.depth++;
 | 
				
			||||||
 | 
								sentences->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << "end\n";
 | 
				
			||||||
 | 
								lsgc.depth--;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> condition;
 | 
				
			||||||
 | 
							std::unique_ptr<AST_SentenceList> sentences;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_ForIn : public AST_Sentence {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_ForIn(std::unique_ptr<AST_Ident> i,std::unique_ptr<AST_Expr> cond,
 | 
				
			||||||
 | 
								std::unique_ptr<AST_SentenceList> s) 
 | 
				
			||||||
 | 
								:id(move(i)),iterable(move(cond)),sentences(move(s)) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) override {
 | 
				
			||||||
 | 
								os << "for " << id << " in " << iterable << " do\n";
 | 
				
			||||||
 | 
								sentences->printDebugInfo(os);
 | 
				
			||||||
 | 
								os << "end\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								lsgc.out() << "for " << id->name << ", _ in pairs(";
 | 
				
			||||||
 | 
								iterable->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << ") do\n";
 | 
				
			||||||
 | 
								lsgc.depth++;
 | 
				
			||||||
 | 
								sentences->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << "end\n";
 | 
				
			||||||
 | 
								lsgc.depth--;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Ident> id;
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> iterable;
 | 
				
			||||||
 | 
							std::unique_ptr<AST_SentenceList> sentences;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_Break : public AST_Sentence {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_Break() {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) override {
 | 
				
			||||||
 | 
								os << "break\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								lsgc.out() << "break\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}; 
 | 
				
			||||||
 | 
						class AST_Continue : public AST_Sentence {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_Continue() {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) override {
 | 
				
			||||||
 | 
								os << "continue\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								lsgc.out() << "continue\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_Return : public AST_Sentence {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_Return(std::unique_ptr<AST_Expr> r)
 | 
				
			||||||
 | 
							:return_value(move(r)){}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) override {
 | 
				
			||||||
 | 
								os << "return " << return_value << "\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								lsgc.out() << "return ";
 | 
				
			||||||
 | 
								return_value->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << "\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> return_value;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_Binary : public AST_Expr {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_Binary(Opers oper, std::unique_ptr<AST_Expr> l, std::unique_ptr<AST_Expr> r)
 | 
				
			||||||
 | 
								:op(oper), LHS(move(l)), RHS(std::move(r)) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) {
 | 
				
			||||||
 | 
								os << LHS << " " << to_string(op) << " " << RHS;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								LHS->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << to_string(op);
 | 
				
			||||||
 | 
								RHS->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							Opers op;
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> LHS, RHS;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_Unary : public AST_Expr {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_Unary(Opers oper, std::unique_ptr<AST_Expr> l) :op(oper)
 | 
				
			||||||
 | 
								, LHS(move(l)) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) {
 | 
				
			||||||
 | 
								os << to_string(op) << " " << LHS;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								if(op != Opers::kPlus)
 | 
				
			||||||
 | 
									lsgc.out() << to_string(op);
 | 
				
			||||||
 | 
								LHS->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							Opers op;
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> LHS;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_Index : public AST_Variable {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_Index(std::unique_ptr<AST_Expr> l, std::unique_ptr<AST_Expr> r)
 | 
				
			||||||
 | 
								:LHS(move(l)), RHS(std::move(r)) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) {
 | 
				
			||||||
 | 
								os << LHS << "[" << RHS << "]";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								LHS->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << "[";
 | 
				
			||||||
 | 
								RHS->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << "]";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> LHS, RHS;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_Dot : public AST_Variable {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_Dot(std::unique_ptr<AST_Expr> l, std::unique_ptr<AST_Ident> r)
 | 
				
			||||||
 | 
								:LHS(move(l)), RHS(std::move(r)) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) {
 | 
				
			||||||
 | 
								os << LHS << "." << RHS;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								LHS->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.out() << "." << RHS->name;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> LHS;
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Ident> RHS;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_CallExpr : public AST_Variable {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_CallExpr(std::unique_ptr<AST_Expr> l)
 | 
				
			||||||
 | 
								:callee(move(l)){}
 | 
				
			||||||
 | 
							void push_back(std::unique_ptr<AST_Expr> arg) { args.emplace_back(move(arg)); }
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) {
 | 
				
			||||||
 | 
								os << callee << "(";
 | 
				
			||||||
 | 
								if (args.size() != 0) {
 | 
				
			||||||
 | 
									auto it = args.begin();
 | 
				
			||||||
 | 
									os << *it++;
 | 
				
			||||||
 | 
									while (it != args.end()) {
 | 
				
			||||||
 | 
										os << "," << *it++;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								os << ")";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								lsgc.out() << callee << "(";
 | 
				
			||||||
 | 
								if (args.size() != 0) {
 | 
				
			||||||
 | 
									auto it = args.begin();
 | 
				
			||||||
 | 
									(*it++)->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
									while (it != args.end()) {
 | 
				
			||||||
 | 
										lsgc.out() << ",";
 | 
				
			||||||
 | 
										(*it++)->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								lsgc.out() << ")";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							std::unique_ptr<AST_Expr> callee;
 | 
				
			||||||
 | 
							std::list<std::unique_ptr<AST_Expr>> args;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_Function : public AST_Expr {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							void push_back(std::unique_ptr<AST_Ident> arg) { args.emplace_back(move(arg)); }
 | 
				
			||||||
 | 
							void setSentenceList(std::unique_ptr<AST_SentenceList> s) { sentences = move(s); }
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext &);
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) {
 | 
				
			||||||
 | 
								os << "fn " << "(";
 | 
				
			||||||
 | 
								if (args.size() != 0) {
 | 
				
			||||||
 | 
									auto it = args.begin();
 | 
				
			||||||
 | 
									os << *it++;
 | 
				
			||||||
 | 
									while (it != args.end()) {
 | 
				
			||||||
 | 
										os << "," << *it++;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								os << ")\n";
 | 
				
			||||||
 | 
								os << sentences << "end\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								lsgc.out() << "function" << "(";
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								if (args.size() != 0) {
 | 
				
			||||||
 | 
									auto it = args.begin();
 | 
				
			||||||
 | 
									lsgc.out() << (*it++)->name;
 | 
				
			||||||
 | 
									while (it != args.end()) {
 | 
				
			||||||
 | 
										lsgc.out() << "," << (*it++)->name;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								lsgc.out() << ")\n";
 | 
				
			||||||
 | 
								lsgc.depth++;
 | 
				
			||||||
 | 
								sentences->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								lsgc.depth--;
 | 
				
			||||||
 | 
								lsgc.out() << "end\n";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							std::list<std::unique_ptr<AST_Ident>> args;
 | 
				
			||||||
 | 
							std::unique_ptr<AST_SentenceList> sentences;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						template<typename Ty>
 | 
				
			||||||
 | 
						class AST_Value : public AST_Expr {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit AST_Value(const Ty & v) :value(v) {}
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext & gctx) override {
 | 
				
			||||||
 | 
								gctx.push(code_t::push, BoxedVar(value));
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) {
 | 
				
			||||||
 | 
								os << value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								lsgc.out() << value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						protected:
 | 
				
			||||||
 | 
							Ty value;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class AST_Int : public AST_Value<int64_t> {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							using AST_Value<int64_t>::AST_Value;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class AST_Float : public AST_Value<double> {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							using AST_Value<double>::AST_Value;
 | 
				
			||||||
 | 
						}; 
 | 
				
			||||||
 | 
						class AST_None : public AST_Expr {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							virtual int generateCode(GenerationContext & gctx) override {
 | 
				
			||||||
 | 
								gctx.push(code_t::push, BoxedVar());
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void printDebugInfo(std::ostream & os) {
 | 
				
			||||||
 | 
								os << "None";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual void luaCodeGen(LuaScriptGenerateContext & lsgc) override {
 | 
				
			||||||
 | 
								lsgc.out() << "nil";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										10
									
								
								LightScript/BoxedVar.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								LightScript/BoxedVar.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					#include "BoxedVar.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ls::BoxedVar::BoxedVar(const BoxedVar & var)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto p = var.ptr->copy();
 | 
				
			||||||
 | 
						if (p == nullptr)
 | 
				
			||||||
 | 
							ptr = var.ptr;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ptr = p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										44
									
								
								LightScript/BoxedVar.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								LightScript/BoxedVar.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,44 @@
 | 
				
			||||||
 | 
					#include<string>
 | 
				
			||||||
 | 
					#include<cstdint>
 | 
				
			||||||
 | 
					#include"CompoundType.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LS_BoxedVar_H_
 | 
				
			||||||
 | 
					#define LS_BoxedVar_H_
 | 
				
			||||||
 | 
					namespace ls {
 | 
				
			||||||
 | 
						struct function_tag {};
 | 
				
			||||||
 | 
						class BoxedVar {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							BoxedVar() :
 | 
				
			||||||
 | 
								ptr(createVar()) {}
 | 
				
			||||||
 | 
							explicit BoxedVar(bool b):
 | 
				
			||||||
 | 
								ptr(createVar(b)) {}
 | 
				
			||||||
 | 
							explicit BoxedVar(int64_t i) :
 | 
				
			||||||
 | 
								ptr(createVar(i)) {}
 | 
				
			||||||
 | 
							explicit BoxedVar(int i) :
 | 
				
			||||||
 | 
								ptr(createVar(i)) {}
 | 
				
			||||||
 | 
							explicit BoxedVar(double d) :
 | 
				
			||||||
 | 
								ptr(createVar(d)) {}
 | 
				
			||||||
 | 
							explicit BoxedVar(const std::string & str) :
 | 
				
			||||||
 | 
								ptr(createVar(str)) {}
 | 
				
			||||||
 | 
							explicit BoxedVar(const std::string & name, std::unique_ptr<FunctionCode, FunctionCodeDeleter> t) :
 | 
				
			||||||
 | 
								ptr(createVar(name,move(t))) {}
 | 
				
			||||||
 | 
							explicit BoxedVar(std::function<std::shared_ptr<CompoundType>(std::vector<BoxedVar>&)> t, function_tag) :
 | 
				
			||||||
 | 
								ptr(createVar(t)) {}
 | 
				
			||||||
 | 
							BoxedVar(const BoxedVar & var);
 | 
				
			||||||
 | 
							explicit BoxedVar(const std::shared_ptr<CompoundType> & t)
 | 
				
			||||||
 | 
							:ptr(t){}
 | 
				
			||||||
 | 
							explicit BoxedVar(const std::shared_ptr<CompoundType> && t)
 | 
				
			||||||
 | 
								:ptr(std::move(t)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::shared_ptr<CompoundType> get() const { return ptr; }
 | 
				
			||||||
 | 
							void set(const std::shared_ptr<CompoundType> & t) { ptr = t; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string to_string() const { return ptr->to_string(); }
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							std::shared_ptr<CompoundType> ptr;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						inline BoxedVar createBoxedFunction(std::function<std::shared_ptr<CompoundType>(std::vector<BoxedVar>&)> t) {
 | 
				
			||||||
 | 
							return BoxedVar(t, function_tag());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										44
									
								
								LightScript/ByteCode.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								LightScript/ByteCode.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,44 @@
 | 
				
			||||||
 | 
					#include "ByteCode.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ls::isInOpers(code_t c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (c)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case ls::code_t::and:
 | 
				
			||||||
 | 
						case ls::code_t:: or:
 | 
				
			||||||
 | 
						case ls::code_t::not:
 | 
				
			||||||
 | 
						case ls::code_t::plus:
 | 
				
			||||||
 | 
						case ls::code_t::minus:
 | 
				
			||||||
 | 
						case ls::code_t::add:
 | 
				
			||||||
 | 
						case ls::code_t::sub:
 | 
				
			||||||
 | 
						case ls::code_t::mul:
 | 
				
			||||||
 | 
						case ls::code_t::div:
 | 
				
			||||||
 | 
						case ls::code_t::eq:
 | 
				
			||||||
 | 
						case ls::code_t::neq:
 | 
				
			||||||
 | 
						case ls::code_t::gte:
 | 
				
			||||||
 | 
						case ls::code_t::gt:
 | 
				
			||||||
 | 
						case ls::code_t::less:
 | 
				
			||||||
 | 
						case ls::code_t::leq:
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string ls::to_string(code_t t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const char * lookup[] = { "nop",
 | 
				
			||||||
 | 
						"and","or","not",
 | 
				
			||||||
 | 
						"plus","minus",
 | 
				
			||||||
 | 
						"add","sub","mul","div",
 | 
				
			||||||
 | 
						"eq","neq","gt","gte","less","leq",
 | 
				
			||||||
 | 
						"push","pop","load","store","new_var",
 | 
				
			||||||
 | 
						"jmp","jt","jf",
 | 
				
			||||||
 | 
						"enterScope","leaveScope",
 | 
				
			||||||
 | 
						"call","ret","ref","getiter","getvalue",
 | 
				
			||||||
 | 
						"isEnd","next",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						if(t != code_t::ERROR)
 | 
				
			||||||
 | 
							return lookup[static_cast<size_t>(t)];
 | 
				
			||||||
 | 
						return "Error";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										110
									
								
								LightScript/ByteCode.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								LightScript/ByteCode.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,110 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include<cstdint>
 | 
				
			||||||
 | 
					#include<vector>
 | 
				
			||||||
 | 
					#include<map>
 | 
				
			||||||
 | 
					#include"Operators.h"
 | 
				
			||||||
 | 
					#include"BoxedVar.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LS_ByteCode_H_
 | 
				
			||||||
 | 
					#define LS_ByteCode_H_
 | 
				
			||||||
 | 
					namespace ls {
 | 
				
			||||||
 | 
						typedef int64_t pos_t;
 | 
				
			||||||
 | 
						enum class code_t : uint16_t
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							//아무것도 안함.
 | 
				
			||||||
 | 
							nop = 0,
 | 
				
			||||||
 | 
							//스택에서 2개 뽑아서 and 연산 한 다음 스택에 저장.
 | 
				
			||||||
 | 
							and = kAnd,
 | 
				
			||||||
 | 
							//스택에서 2개 뽑아서 or 연산 한 다음 스택에 저장.
 | 
				
			||||||
 | 
							or = kOr,
 | 
				
			||||||
 | 
							//스택에서 2개 뽑아서 and 연산 한 다음 스택에 저장.
 | 
				
			||||||
 | 
							not = kNot,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//스택에서 1개 뽑아서 plus 연산 한 다음 스택에 저장.
 | 
				
			||||||
 | 
							plus = kPlus,
 | 
				
			||||||
 | 
							//스택에서 1개 뽑아서 minus 연산 한 다음 스택에 저장.
 | 
				
			||||||
 | 
							minus = kMinus,
 | 
				
			||||||
 | 
							//스택에서 2개 뽑아서 더한 다음 스택에 저장.
 | 
				
			||||||
 | 
							add = kAdd,
 | 
				
			||||||
 | 
							//스택에서 2개 뽑아서 빼고 스택에 저장.
 | 
				
			||||||
 | 
							sub = kSub,
 | 
				
			||||||
 | 
							//스택에서 2개 뽑아서 곱한 다음 스택에 저장.
 | 
				
			||||||
 | 
							mul = kMul,
 | 
				
			||||||
 | 
							//스택에서 2개 뽑아서 나눈 다음 스택에 저장.
 | 
				
			||||||
 | 
							div = kDiv,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//스택에서 2개 뽑아서 비교한 다음 bool 값을 스택에 저장.
 | 
				
			||||||
 | 
							eq = kEqual,
 | 
				
			||||||
 | 
							neq = kNotEqual,
 | 
				
			||||||
 | 
							gt = kGreater, 
 | 
				
			||||||
 | 
							gte = kEqualGreater,
 | 
				
			||||||
 | 
							less = kLess,
 | 
				
			||||||
 | 
							leq = kLessEqual,
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							//스택에 하나 저장
 | 
				
			||||||
 | 
							push,
 | 
				
			||||||
 | 
							//스택에서 한개 뽑아내기.
 | 
				
			||||||
 | 
							pop,
 | 
				
			||||||
 | 
							//스택에서 변수이름 받아서 변수참조 되돌려 주기.
 | 
				
			||||||
 | 
							load,
 | 
				
			||||||
 | 
							//스택에서 2개 뽑아서 처음 뽑은 것에다 나중에 뽑은 것 넣기.
 | 
				
			||||||
 | 
							store,
 | 
				
			||||||
 | 
							//스택에서 변수이름 받아서 새로운 변수 생성
 | 
				
			||||||
 | 
							new_var,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//상대 주소 점프. ProgramCounter 에다 더하면 됨.
 | 
				
			||||||
 | 
							jmp,
 | 
				
			||||||
 | 
							//스택에서 1개 뽑아서 참일때 점프
 | 
				
			||||||
 | 
							jt,
 | 
				
			||||||
 | 
							//스택에서 1개 뽑아서 거짓일때 점프
 | 
				
			||||||
 | 
							jf,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//변수 스코프 진입.
 | 
				
			||||||
 | 
							enterScope,
 | 
				
			||||||
 | 
							//스코프에서 나오기.
 | 
				
			||||||
 | 
							leaveScope,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//함수 호출
 | 
				
			||||||
 | 
							call,
 | 
				
			||||||
 | 
							//참조 operator [] 나 . 으로 멤버 참조하는 거.
 | 
				
			||||||
 | 
							ref,
 | 
				
			||||||
 | 
							//return
 | 
				
			||||||
 | 
							ret,
 | 
				
			||||||
 | 
							//get iterator from object.
 | 
				
			||||||
 | 
							getiter,
 | 
				
			||||||
 | 
							//get value from iterator.
 | 
				
			||||||
 | 
							getvalue,
 | 
				
			||||||
 | 
							//true if iterator is terminated, otherwise false.
 | 
				
			||||||
 | 
							isEnd,
 | 
				
			||||||
 | 
							//get next sequence iterator.
 | 
				
			||||||
 | 
							next,
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ERROR = 0xffff,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct instruction {
 | 
				
			||||||
 | 
							code_t code;
 | 
				
			||||||
 | 
							pos_t pos = -1;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						bool isInOpers(code_t c);
 | 
				
			||||||
 | 
						std::string to_string(code_t t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct FunctionCode
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							std::vector<instruction> code;
 | 
				
			||||||
 | 
							std::vector<BoxedVar> operands;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct InstructionCode {
 | 
				
			||||||
 | 
							FunctionCode mainframe;
 | 
				
			||||||
 | 
							FunctionCode * ptr;
 | 
				
			||||||
 | 
							explicit InstructionCode() {
 | 
				
			||||||
 | 
								ptr = &mainframe;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							FunctionCode * operator->() { return ptr; }
 | 
				
			||||||
 | 
							const FunctionCode * operator->() const { return ptr; }
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										37
									
								
								LightScript/CodeGeneration.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								LightScript/CodeGeneration.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					#include "CodeGeneration.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::ostream & ls::operator<<(std::ostream & os, const GenerationContext & gc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						for (auto it : (gc.inst)->code)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							os << to_string(it.code) << "\t";
 | 
				
			||||||
 | 
							if (it.pos >= 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								os << (gc.inst)->operands[it.pos].to_string();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							os << "\n";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::GenerationContext::loopStart()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						lpos.emplace_back();
 | 
				
			||||||
 | 
						lpos.back().b = inst->code.size();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::GenerationContext::loopEnd()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int64_t e = inst->code.size();
 | 
				
			||||||
 | 
						if (lpos.size() == 0)
 | 
				
			||||||
 | 
							throw std::exception("Depth Error!");
 | 
				
			||||||
 | 
						for (auto it : lpos.back().break_pos)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							set(it.operandPos, BoxedVar(e - it.codePos));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for (auto it : lpos.back().continue_pos)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							set(it.operandPos, BoxedVar(lpos.back().b - it.codePos));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						lpos.pop_back();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										63
									
								
								LightScript/CodeGeneration.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								LightScript/CodeGeneration.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,63 @@
 | 
				
			||||||
 | 
					#include<memory>
 | 
				
			||||||
 | 
					#include<ostream>
 | 
				
			||||||
 | 
					#include"ByteCode.h"
 | 
				
			||||||
 | 
					#include "BoxedVar.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LS_CodeGeneration_H_
 | 
				
			||||||
 | 
					#define LS_CodeGeneration_H_
 | 
				
			||||||
 | 
					namespace ls {
 | 
				
			||||||
 | 
						class GenerationContext
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							inline void push(code_t c) {
 | 
				
			||||||
 | 
								inst->code.push_back(instruction{ c, -1 });
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							inline void push(code_t c, BoxedVar var) {
 | 
				
			||||||
 | 
								inst->operands.push_back(var);
 | 
				
			||||||
 | 
								inst->code.push_back(instruction{ c, static_cast<int64_t>(inst->operands.size() - 1 )});//errorÀÇ À§Çù. º¸¾È À§Çù.
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							inline int64_t currentPos() { return inst->operands.size() - 1; }
 | 
				
			||||||
 | 
							inline void set(int64_t pos, BoxedVar var) { inst->operands[pos] = var; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inline int64_t currentCodePos() { return inst->code.size() - 1; }
 | 
				
			||||||
 | 
							//inline int64_t setCodePos(int64_t pos, code_t c) { inst->code[pos].code = c; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void loopStart();
 | 
				
			||||||
 | 
							void loopEnd();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							int registerBreak() { 
 | 
				
			||||||
 | 
								push(code_t::push, BoxedVar());
 | 
				
			||||||
 | 
								lpos.back().break_pos.push_back({ currentCodePos() + 1,currentPos() });
 | 
				
			||||||
 | 
								push(code_t::jmp);
 | 
				
			||||||
 | 
								return 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							int registerContinue() {
 | 
				
			||||||
 | 
								push(code_t::push, BoxedVar());
 | 
				
			||||||
 | 
								lpos.back().continue_pos.push_back({ currentCodePos() + 1,currentPos() });
 | 
				
			||||||
 | 
								push(code_t::jmp);
 | 
				
			||||||
 | 
								return 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							void setFrame(FunctionCode * t) {
 | 
				
			||||||
 | 
								inst.ptr = t;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							FunctionCode * getFrame() { return inst.ptr; }
 | 
				
			||||||
 | 
							friend std::ostream & operator<<(std::ostream & os, const GenerationContext & a);
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							InstructionCode inst;
 | 
				
			||||||
 | 
							struct LoopPos
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								struct CodePos{
 | 
				
			||||||
 | 
									int64_t codePos;
 | 
				
			||||||
 | 
									int64_t operandPos;
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								int64_t b;
 | 
				
			||||||
 | 
								std::vector<CodePos> continue_pos;
 | 
				
			||||||
 | 
								std::vector<CodePos> break_pos;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							std::vector<LoopPos> lpos;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						std::ostream & operator<<(std::ostream & os, const GenerationContext & a);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										134
									
								
								LightScript/CompoundType.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								LightScript/CompoundType.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,134 @@
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include "CompoundType.h"
 | 
				
			||||||
 | 
					#include"ByteCode.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace ls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::CompoundType::binaryGo(Opers op, CompoundType * ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (op) {
 | 
				
			||||||
 | 
						case kEqual:
 | 
				
			||||||
 | 
							return createVar(this == ptr);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case kNotEqual:
 | 
				
			||||||
 | 
							return createVar(this != ptr);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::BooleanType::unaryGo(Opers op)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (op == kNot) {
 | 
				
			||||||
 | 
							return createVar(!value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::BooleanType::binaryGo(Opers op, CompoundType * rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto r = dynamic_cast<BooleanType *>(rhs);
 | 
				
			||||||
 | 
						if (r == nullptr) return nullptr;
 | 
				
			||||||
 | 
						auto ret = LogicalBinaryGo<bool, bool>(op, value, r->value);
 | 
				
			||||||
 | 
						if (ret != nullptr) return ret;
 | 
				
			||||||
 | 
						switch (op) {
 | 
				
			||||||
 | 
						case kEqual:
 | 
				
			||||||
 | 
							return createVar(value == r->value);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case kNotEqual:
 | 
				
			||||||
 | 
							return createVar(value != r->value);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::BooleanType::copy()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return createVar(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::IntegerType::unaryGo(Opers op)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ArithmeticUnaryGo(op, value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::IntegerType::binaryGo(Opers op, CompoundType * rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (rhs->Type()) {
 | 
				
			||||||
 | 
						case kInteger:
 | 
				
			||||||
 | 
							return ArithmeticBinaryGo(op, value, dynamic_cast<IntegerType *>(rhs)->value);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case kFloat:
 | 
				
			||||||
 | 
							return ArithmeticBinaryGo(op, value, dynamic_cast<FloatType *>(rhs)->value);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case kString:
 | 
				
			||||||
 | 
							if (op== kAdd){
 | 
				
			||||||
 | 
								return createVar(to_string() + dynamic_cast<StringType *>(rhs)->value);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::IntegerType::copy()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return createVar(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::FloatType::unaryGo(Opers op)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ArithmeticUnaryGo(op, value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::FloatType::binaryGo(Opers op, CompoundType * rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (rhs->Type()) {
 | 
				
			||||||
 | 
						case kInteger:
 | 
				
			||||||
 | 
							return ArithmeticBinaryGo(op, value, dynamic_cast<IntegerType *>(rhs)->value);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case kFloat:
 | 
				
			||||||
 | 
							return ArithmeticBinaryGo(op, value, dynamic_cast<FloatType *>(rhs)->value);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::FloatType::copy()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return createVar(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::StringType::binaryGo(Opers op, CompoundType * rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (op != kAdd)
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						return createVar(value + rhs->to_string());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<CompoundType> ls::StringType::copy()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return createVar(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string ls::TableType::to_string()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::stringstream ss;
 | 
				
			||||||
 | 
						ss << "{";
 | 
				
			||||||
 | 
						for (auto& it : map){
 | 
				
			||||||
 | 
							ss << it.first->to_string() << "="
 | 
				
			||||||
 | 
								<< it.second->to_string() << ",";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ss << "}";
 | 
				
			||||||
 | 
						return ss.str();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::FunctionCodeDeleter::operator()(FunctionCode * p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						delete p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										312
									
								
								LightScript/CompoundType.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								LightScript/CompoundType.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,312 @@
 | 
				
			||||||
 | 
					#include<string>
 | 
				
			||||||
 | 
					#include<cstdint>
 | 
				
			||||||
 | 
					#include<memory>
 | 
				
			||||||
 | 
					#include<unordered_map>
 | 
				
			||||||
 | 
					#include<exception>
 | 
				
			||||||
 | 
					#include<functional>
 | 
				
			||||||
 | 
					#include"Operators.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LS_CompoundType_H_
 | 
				
			||||||
 | 
					#define LS_CompoundType_H_
 | 
				
			||||||
 | 
					namespace ls {
 | 
				
			||||||
 | 
						using std::shared_ptr;
 | 
				
			||||||
 | 
						using std::make_shared;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//순서 바꾸지 마시요.
 | 
				
			||||||
 | 
						enum TypeKind {
 | 
				
			||||||
 | 
							kNone = 0,
 | 
				
			||||||
 | 
							kBoolean,
 | 
				
			||||||
 | 
							kInteger,
 | 
				
			||||||
 | 
							kFloat,
 | 
				
			||||||
 | 
							kString,
 | 
				
			||||||
 | 
							kTable,
 | 
				
			||||||
 | 
							kTableIter,
 | 
				
			||||||
 | 
							kFunction,
 | 
				
			||||||
 | 
							kFunctionProxy,
 | 
				
			||||||
 | 
							kUserDefined,
 | 
				
			||||||
 | 
							kDEF_END
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class BoxedVar;
 | 
				
			||||||
 | 
						struct FunctionCode;
 | 
				
			||||||
 | 
						//std::unordered_map<std::string, void(IntType::*)()> st;
 | 
				
			||||||
 | 
						class TypeError : public std::logic_error
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							using std::logic_error::logic_error;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class InvalidOperation : public TypeError
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							InvalidOperation() :TypeError("InvalidOperation") {}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class DividedByZero : public TypeError
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							DividedByZero() :TypeError("attempt to divide by zero") {}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class CompoundType
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							CompoundType() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//virtual void searchMethod(const std::string & str) {}
 | 
				
			||||||
 | 
							virtual BoxedVar * index(CompoundType *) { return nullptr; }
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							//바꾸는 것 고려해야함.
 | 
				
			||||||
 | 
							virtual bool next() { return false; }
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> unaryGo(Opers op) { return nullptr; }
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> binaryGo(Opers op, CompoundType *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual TypeKind Type() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> copy() { return nullptr; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//virtual std::shared_ptr<CompoundType> cast(TypeKind tk) { throw InvalidOperation(); }
 | 
				
			||||||
 | 
							virtual std::string to_string() { return "<UnknownObject>"; }
 | 
				
			||||||
 | 
							virtual ~CompoundType() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual size_t hash() { return reinterpret_cast<size_t>(this); }
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					namespace std {
 | 
				
			||||||
 | 
						template<> struct hash<ls::CompoundType *>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							typedef ls::CompoundType * argument_type;
 | 
				
			||||||
 | 
							typedef std::size_t result_type;
 | 
				
			||||||
 | 
							result_type operator()(argument_type s) const noexcept{
 | 
				
			||||||
 | 
								return s->hash();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					namespace ls
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						class NoneType final : public CompoundType {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							virtual TypeKind Type() { return TypeKind::kNone; }
 | 
				
			||||||
 | 
							virtual std::string to_string() { return "None"; }
 | 
				
			||||||
 | 
							virtual size_t hash() override { return 0x12345678; };
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class BooleanType final : public CompoundType {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit BooleanType(bool b) :value(b) {}
 | 
				
			||||||
 | 
							virtual TypeKind Type() override { return TypeKind::kBoolean; }
 | 
				
			||||||
 | 
							virtual std::string to_string() { return value ? "true" : "false"; }
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> unaryGo(Opers op) override;
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> binaryGo(Opers op, CompoundType * rhs) override;
 | 
				
			||||||
 | 
							virtual size_t hash() override { return std::hash<bool>{}(value); };
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> copy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool value;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class IntegerType final : public CompoundType {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit IntegerType(int64_t i) :value(i) {}
 | 
				
			||||||
 | 
							virtual TypeKind Type() { return TypeKind::kInteger; }
 | 
				
			||||||
 | 
							virtual std::string to_string() { return std::to_string(value); }
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> unaryGo(Opers op) override;
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> binaryGo(Opers op, CompoundType * rhs) override;
 | 
				
			||||||
 | 
							virtual size_t hash() override { return value; };
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> copy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int64_t value;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class FloatType final : public CompoundType {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit FloatType(double i) :value(i) {}
 | 
				
			||||||
 | 
							virtual TypeKind Type() { return TypeKind::kFloat; }
 | 
				
			||||||
 | 
							virtual std::string to_string() { return std::to_string(value); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> unaryGo(Opers op) override;
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> binaryGo(Opers op, CompoundType * rhs) override;
 | 
				
			||||||
 | 
							virtual size_t hash() override { return std::hash<double>{}(value); };
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> copy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							double value;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class StringType final : public CompoundType {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit StringType(const std::string & str) :value(str) {}
 | 
				
			||||||
 | 
							virtual TypeKind Type() { return TypeKind::kString; }
 | 
				
			||||||
 | 
							virtual std::string to_string() { return "\"" + value + "\""; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> unaryGo(Opers op) override { return nullptr; }
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> binaryGo(Opers op, CompoundType * rhs) override;
 | 
				
			||||||
 | 
							virtual size_t hash() override { return std::hash<std::string>{}(value); };
 | 
				
			||||||
 | 
							virtual shared_ptr<CompoundType> copy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string value;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typedef std::unordered_map< CompoundType *, shared_ptr<CompoundType> > dict_type;
 | 
				
			||||||
 | 
						typedef dict_type::iterator dict_iterator_type;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/*class IterativeType : public CompoundType {
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						필요할까?
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
 | 
						class TableIterType final : public CompoundType {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit TableIterType(dict_iterator_type it, dict_iterator_type end_iterator)
 | 
				
			||||||
 | 
								:cur(it), end(end_iterator) {}
 | 
				
			||||||
 | 
							virtual TypeKind Type() { return TypeKind::kTableIter; }
 | 
				
			||||||
 | 
							virtual std::string to_string() override {
 | 
				
			||||||
 | 
								if (cur != end)
 | 
				
			||||||
 | 
									return cur->first->to_string();
 | 
				
			||||||
 | 
								else return "<End Iteraor>";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							inline virtual bool next() override {
 | 
				
			||||||
 | 
								if (cur != end)
 | 
				
			||||||
 | 
									cur++;
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							inline bool isEnd() {
 | 
				
			||||||
 | 
								return cur != end;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							inline shared_ptr<CompoundType> & value() {
 | 
				
			||||||
 | 
								return cur->second;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							dict_iterator_type cur;
 | 
				
			||||||
 | 
							dict_iterator_type end;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class TableType final : public CompoundType {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit TableType() {}
 | 
				
			||||||
 | 
							virtual TypeKind Type() { return TypeKind::kTable; }
 | 
				
			||||||
 | 
							virtual std::string to_string() override;
 | 
				
			||||||
 | 
							virtual shared_ptr<TableIterType> getiter() {
 | 
				
			||||||
 | 
								return make_shared<TableIterType>(map.begin(), map.end());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							dict_type map;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class FunctionProxyType : public CompoundType {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit FunctionProxyType(std::function<std::shared_ptr<CompoundType>(std::vector<BoxedVar>&)> v) :value(v) {}
 | 
				
			||||||
 | 
							std::shared_ptr<CompoundType> call(std::vector<BoxedVar> & stack) {
 | 
				
			||||||
 | 
								return value(stack);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							virtual TypeKind Type() override { return TypeKind::kFunctionProxy; }
 | 
				
			||||||
 | 
							virtual std::string to_string() override { return debugName; }
 | 
				
			||||||
 | 
							std::string debugName = "<FunctionProxy>";
 | 
				
			||||||
 | 
							std::function<std::shared_ptr<CompoundType>(std::vector<BoxedVar>&)> value;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct FunctionCodeDeleter{
 | 
				
			||||||
 | 
							void operator()(FunctionCode * );
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class FunctionType : public CompoundType {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							FunctionType(const std::string & n, std::unique_ptr<FunctionCode, FunctionCodeDeleter> c)
 | 
				
			||||||
 | 
								:name(n), code(move(c)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							virtual TypeKind Type() override { return TypeKind::kFunction; }
 | 
				
			||||||
 | 
							virtual std::string to_string() override { return "<Function:"+name+">"; }
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							std::string name = "<Function>";
 | 
				
			||||||
 | 
							std::unique_ptr<FunctionCode, FunctionCodeDeleter> code;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						inline std::shared_ptr<CompoundType> createVar(void) {
 | 
				
			||||||
 | 
							static std::shared_ptr < CompoundType > ret(new NoneType);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inline std::shared_ptr<CompoundType> createVar(int64_t t) {
 | 
				
			||||||
 | 
							return std::make_shared<IntegerType>(t);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inline std::shared_ptr<CompoundType> createVar(int t) {
 | 
				
			||||||
 | 
							return std::make_shared<IntegerType>(t);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inline std::shared_ptr<CompoundType> createVar(bool t) {
 | 
				
			||||||
 | 
							return std::make_shared<BooleanType>(t);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inline std::shared_ptr<CompoundType> createVar(double t) {
 | 
				
			||||||
 | 
							return std::make_shared<FloatType>(t);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inline std::shared_ptr<CompoundType> createVar(const std::string & t) {
 | 
				
			||||||
 | 
							return std::make_shared<StringType>(t);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inline std::shared_ptr<CompoundType> createVar(std::function<std::shared_ptr<CompoundType>(std::vector<BoxedVar>&)> v) {
 | 
				
			||||||
 | 
							return std::make_shared<FunctionProxyType>(v);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						inline std::shared_ptr<CompoundType> createVar(const std::string & name, std::unique_ptr<FunctionCode, FunctionCodeDeleter> t) {
 | 
				
			||||||
 | 
							return std::make_shared<FunctionType>(name, move(t));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						template<typename LHStype,typename RHStype>
 | 
				
			||||||
 | 
						shared_ptr<CompoundType> LogicalBinaryGo(Opers op,const LHStype & lhs,const RHStype & rhs) {
 | 
				
			||||||
 | 
							switch (op)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							case kAnd:
 | 
				
			||||||
 | 
								return createVar(lhs && rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case kOr:
 | 
				
			||||||
 | 
								return createVar(lhs || rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return nullptr;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						template<typename LHStype>
 | 
				
			||||||
 | 
						shared_ptr<CompoundType> ArithmeticUnaryGo(Opers op, const LHStype & lhs) {
 | 
				
			||||||
 | 
							switch (op)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							case kPlus:
 | 
				
			||||||
 | 
								return createVar(+lhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case kMinus:
 | 
				
			||||||
 | 
								return createVar(-lhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return nullptr;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						template<typename LHStype, typename RHStype>
 | 
				
			||||||
 | 
						shared_ptr<CompoundType> ArithmeticBinaryGo(Opers op, const LHStype & lhs, const RHStype & rhs) {
 | 
				
			||||||
 | 
							switch (op)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							case kAdd:
 | 
				
			||||||
 | 
								return createVar(lhs + rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case kSub:
 | 
				
			||||||
 | 
								return createVar(lhs - rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case kMul:
 | 
				
			||||||
 | 
								return createVar(lhs * rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case kDiv:
 | 
				
			||||||
 | 
								if (rhs == 0){
 | 
				
			||||||
 | 
									throw DividedByZero();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return createVar(lhs / rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case kGreater:
 | 
				
			||||||
 | 
								return createVar(lhs > rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case kEqualGreater:
 | 
				
			||||||
 | 
								return createVar(lhs >= rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case kEqual:
 | 
				
			||||||
 | 
								return createVar(lhs == rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case kNotEqual:
 | 
				
			||||||
 | 
								return createVar(lhs != rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case kLess:
 | 
				
			||||||
 | 
								return createVar(lhs < rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case kLessEqual:
 | 
				
			||||||
 | 
								return createVar(lhs <= rhs);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return nullptr;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										111
									
								
								LightScript/Lexer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								LightScript/Lexer.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,111 @@
 | 
				
			||||||
 | 
					#include<algorithm>
 | 
				
			||||||
 | 
					#include "Lexer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace ls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool isCutCharactor(int ch) {
 | 
				
			||||||
 | 
						static char s[] = " \n\t+-/*.,!|<>[]{}()&\'\"^%:;~`$#\\?#@=\r\0";
 | 
				
			||||||
 | 
						auto pos = std::find(std::begin(s), std::end(s), ch);
 | 
				
			||||||
 | 
						return pos != std::end(s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool isOperatorWord(int ch) {
 | 
				
			||||||
 | 
						static char s[] = "+-/*!|<>&^%~$?=(),";
 | 
				
			||||||
 | 
						auto pos = std::find(std::begin(s), std::end(s), ch);
 | 
				
			||||||
 | 
						return pos != std::end(s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool isIgnoreWord(int ch) {
 | 
				
			||||||
 | 
						static char s[] = " \n\r\t";
 | 
				
			||||||
 | 
						auto pos = std::find(std::begin(s), std::end(s), ch);
 | 
				
			||||||
 | 
						return pos != std::end(s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Token IstreamTokenizer::get()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Token t;
 | 
				
			||||||
 | 
						if (is->eof()) {
 | 
				
			||||||
 | 
							t.type = ttEof;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							eatSpace();
 | 
				
			||||||
 | 
							t.line = line;
 | 
				
			||||||
 | 
							auto ch = is->peek();
 | 
				
			||||||
 | 
							if (isdigit(ch))
 | 
				
			||||||
 | 
								getNumber(t);
 | 
				
			||||||
 | 
							else if (isOperatorWord(ch))
 | 
				
			||||||
 | 
								getOperator(t);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								getLiteral(t);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return t;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IstreamTokenizer::getLiteral(Token & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto ch = is->get();
 | 
				
			||||||
 | 
						t.str += ch;
 | 
				
			||||||
 | 
						while (!isCutCharactor(ch = is->peek()))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (is->eof()) break;
 | 
				
			||||||
 | 
							t.str += ch;
 | 
				
			||||||
 | 
							is->get();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (t.str == "end"||t.str == "else"||
 | 
				
			||||||
 | 
							t.str=="if"||t.str=="for"||t.str == "in"
 | 
				
			||||||
 | 
							||t.str =="break"||t.str=="continue"||t.str=="fn"||t.str =="return") {	//임시로 해놓은 것. 나중에 바꾸자.
 | 
				
			||||||
 | 
							t.type = ttKeyword;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.type = ttIdentifier;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IstreamTokenizer::getNumber(Token & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto ch = is->get();
 | 
				
			||||||
 | 
						t.str += ch;
 | 
				
			||||||
 | 
						while (isdigit(ch = is->peek())) 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							t.str += ch;
 | 
				
			||||||
 | 
							is->get();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (is->peek() == '.') {
 | 
				
			||||||
 | 
							while (isdigit(ch = is->peek()))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								t.str += ch;
 | 
				
			||||||
 | 
								is->get();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							t.type = ttFloat;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else t.type = ttInteger;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::IstreamTokenizer::getOperator(Token & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto ch = is->get();
 | 
				
			||||||
 | 
						t.str += ch;
 | 
				
			||||||
 | 
						while (isOperatorWord(ch = is->peek()))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							t.str += ch;
 | 
				
			||||||
 | 
							is->get();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.type = ttOperator;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IstreamTokenizer::eatSpace()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ch;
 | 
				
			||||||
 | 
						while(isIgnoreWord(ch = is->peek()))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (ch == '\n')
 | 
				
			||||||
 | 
								line++;
 | 
				
			||||||
 | 
							is->get();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::istream & ls::operator>>(std::istream & is, Token & t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						IstreamTokenizer tokenizer(is);
 | 
				
			||||||
 | 
						t = tokenizer.get();
 | 
				
			||||||
 | 
						return is;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								LightScript/Lexer.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								LightScript/Lexer.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					#include<istream>
 | 
				
			||||||
 | 
					#include"Token.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LS_Lexer_H_
 | 
				
			||||||
 | 
					#define LS_Lexer_H_
 | 
				
			||||||
 | 
					namespace ls {
 | 
				
			||||||
 | 
						class IstreamTokenizer {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit IstreamTokenizer(std::istream & istream)
 | 
				
			||||||
 | 
								:is(&istream){}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Token get();
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							void getLiteral(Token &);
 | 
				
			||||||
 | 
							void getNumber(Token &);
 | 
				
			||||||
 | 
							void getOperator(Token &);
 | 
				
			||||||
 | 
							void eatSpace();
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							std::istream * is;
 | 
				
			||||||
 | 
							int line;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::istream & operator>>(std::istream &, Token &);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										145
									
								
								LightScript/LightScript.vcxproj
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								LightScript/LightScript.vcxproj
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,145 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 | 
				
			||||||
 | 
					  <ItemGroup Label="ProjectConfigurations">
 | 
				
			||||||
 | 
					    <ProjectConfiguration Include="Debug|Win32">
 | 
				
			||||||
 | 
					      <Configuration>Debug</Configuration>
 | 
				
			||||||
 | 
					      <Platform>Win32</Platform>
 | 
				
			||||||
 | 
					    </ProjectConfiguration>
 | 
				
			||||||
 | 
					    <ProjectConfiguration Include="Release|Win32">
 | 
				
			||||||
 | 
					      <Configuration>Release</Configuration>
 | 
				
			||||||
 | 
					      <Platform>Win32</Platform>
 | 
				
			||||||
 | 
					    </ProjectConfiguration>
 | 
				
			||||||
 | 
					    <ProjectConfiguration Include="Debug|x64">
 | 
				
			||||||
 | 
					      <Configuration>Debug</Configuration>
 | 
				
			||||||
 | 
					      <Platform>x64</Platform>
 | 
				
			||||||
 | 
					    </ProjectConfiguration>
 | 
				
			||||||
 | 
					    <ProjectConfiguration Include="Release|x64">
 | 
				
			||||||
 | 
					      <Configuration>Release</Configuration>
 | 
				
			||||||
 | 
					      <Platform>x64</Platform>
 | 
				
			||||||
 | 
					    </ProjectConfiguration>
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <PropertyGroup Label="Globals">
 | 
				
			||||||
 | 
					    <VCProjectVersion>15.0</VCProjectVersion>
 | 
				
			||||||
 | 
					    <ProjectGuid>{99DA223F-E88F-4E97-A314-E798486955A8}</ProjectGuid>
 | 
				
			||||||
 | 
					    <RootNamespace>LightScript</RootNamespace>
 | 
				
			||||||
 | 
					    <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
 | 
				
			||||||
 | 
					  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
 | 
				
			||||||
 | 
					    <ConfigurationType>Application</ConfigurationType>
 | 
				
			||||||
 | 
					    <UseDebugLibraries>true</UseDebugLibraries>
 | 
				
			||||||
 | 
					    <PlatformToolset>v141</PlatformToolset>
 | 
				
			||||||
 | 
					    <CharacterSet>MultiByte</CharacterSet>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
 | 
				
			||||||
 | 
					    <ConfigurationType>Application</ConfigurationType>
 | 
				
			||||||
 | 
					    <UseDebugLibraries>false</UseDebugLibraries>
 | 
				
			||||||
 | 
					    <PlatformToolset>v141</PlatformToolset>
 | 
				
			||||||
 | 
					    <WholeProgramOptimization>true</WholeProgramOptimization>
 | 
				
			||||||
 | 
					    <CharacterSet>MultiByte</CharacterSet>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
 | 
				
			||||||
 | 
					    <ConfigurationType>Application</ConfigurationType>
 | 
				
			||||||
 | 
					    <UseDebugLibraries>true</UseDebugLibraries>
 | 
				
			||||||
 | 
					    <PlatformToolset>v141</PlatformToolset>
 | 
				
			||||||
 | 
					    <CharacterSet>MultiByte</CharacterSet>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
 | 
				
			||||||
 | 
					    <ConfigurationType>Application</ConfigurationType>
 | 
				
			||||||
 | 
					    <UseDebugLibraries>false</UseDebugLibraries>
 | 
				
			||||||
 | 
					    <PlatformToolset>v141</PlatformToolset>
 | 
				
			||||||
 | 
					    <WholeProgramOptimization>true</WholeProgramOptimization>
 | 
				
			||||||
 | 
					    <CharacterSet>MultiByte</CharacterSet>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
 | 
				
			||||||
 | 
					  <ImportGroup Label="ExtensionSettings">
 | 
				
			||||||
 | 
					  </ImportGroup>
 | 
				
			||||||
 | 
					  <ImportGroup Label="Shared">
 | 
				
			||||||
 | 
					  </ImportGroup>
 | 
				
			||||||
 | 
					  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
 | 
				
			||||||
 | 
					    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
 | 
				
			||||||
 | 
					  </ImportGroup>
 | 
				
			||||||
 | 
					  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
 | 
				
			||||||
 | 
					    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
 | 
				
			||||||
 | 
					  </ImportGroup>
 | 
				
			||||||
 | 
					  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
 | 
				
			||||||
 | 
					    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
 | 
				
			||||||
 | 
					  </ImportGroup>
 | 
				
			||||||
 | 
					  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
 | 
				
			||||||
 | 
					    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
 | 
				
			||||||
 | 
					  </ImportGroup>
 | 
				
			||||||
 | 
					  <PropertyGroup Label="UserMacros" />
 | 
				
			||||||
 | 
					  <PropertyGroup />
 | 
				
			||||||
 | 
					  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
 | 
				
			||||||
 | 
					    <ClCompile>
 | 
				
			||||||
 | 
					      <WarningLevel>Level3</WarningLevel>
 | 
				
			||||||
 | 
					      <Optimization>Disabled</Optimization>
 | 
				
			||||||
 | 
					      <SDLCheck>true</SDLCheck>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					  </ItemDefinitionGroup>
 | 
				
			||||||
 | 
					  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
 | 
				
			||||||
 | 
					    <ClCompile>
 | 
				
			||||||
 | 
					      <WarningLevel>Level3</WarningLevel>
 | 
				
			||||||
 | 
					      <Optimization>Disabled</Optimization>
 | 
				
			||||||
 | 
					      <SDLCheck>true</SDLCheck>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					  </ItemDefinitionGroup>
 | 
				
			||||||
 | 
					  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
 | 
				
			||||||
 | 
					    <ClCompile>
 | 
				
			||||||
 | 
					      <WarningLevel>Level3</WarningLevel>
 | 
				
			||||||
 | 
					      <Optimization>MaxSpeed</Optimization>
 | 
				
			||||||
 | 
					      <FunctionLevelLinking>true</FunctionLevelLinking>
 | 
				
			||||||
 | 
					      <IntrinsicFunctions>true</IntrinsicFunctions>
 | 
				
			||||||
 | 
					      <SDLCheck>true</SDLCheck>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <Link>
 | 
				
			||||||
 | 
					      <EnableCOMDATFolding>true</EnableCOMDATFolding>
 | 
				
			||||||
 | 
					      <OptimizeReferences>true</OptimizeReferences>
 | 
				
			||||||
 | 
					    </Link>
 | 
				
			||||||
 | 
					  </ItemDefinitionGroup>
 | 
				
			||||||
 | 
					  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
 | 
				
			||||||
 | 
					    <ClCompile>
 | 
				
			||||||
 | 
					      <WarningLevel>Level3</WarningLevel>
 | 
				
			||||||
 | 
					      <Optimization>MaxSpeed</Optimization>
 | 
				
			||||||
 | 
					      <FunctionLevelLinking>true</FunctionLevelLinking>
 | 
				
			||||||
 | 
					      <IntrinsicFunctions>true</IntrinsicFunctions>
 | 
				
			||||||
 | 
					      <SDLCheck>true</SDLCheck>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <Link>
 | 
				
			||||||
 | 
					      <EnableCOMDATFolding>true</EnableCOMDATFolding>
 | 
				
			||||||
 | 
					      <OptimizeReferences>true</OptimizeReferences>
 | 
				
			||||||
 | 
					    </Link>
 | 
				
			||||||
 | 
					  </ItemDefinitionGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <ClCompile Include="AST.cpp" />
 | 
				
			||||||
 | 
					    <ClCompile Include="ByteCode.cpp" />
 | 
				
			||||||
 | 
					    <ClCompile Include="CodeGeneration.cpp" />
 | 
				
			||||||
 | 
					    <ClCompile Include="CompoundType.cpp" />
 | 
				
			||||||
 | 
					    <ClCompile Include="Lexer.cpp" />
 | 
				
			||||||
 | 
					    <ClCompile Include="main.cpp" />
 | 
				
			||||||
 | 
					    <ClCompile Include="Operators.cpp" />
 | 
				
			||||||
 | 
					    <ClCompile Include="Parser.cpp" />
 | 
				
			||||||
 | 
					    <ClCompile Include="Token.cpp" />
 | 
				
			||||||
 | 
					    <ClCompile Include="BoxedVar.cpp" />
 | 
				
			||||||
 | 
					    <ClCompile Include="VirtualMachine.cpp" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <ClInclude Include="AST.h" />
 | 
				
			||||||
 | 
					    <ClInclude Include="ByteCode.h" />
 | 
				
			||||||
 | 
					    <ClInclude Include="CodeGeneration.h" />
 | 
				
			||||||
 | 
					    <ClInclude Include="CompoundType.h" />
 | 
				
			||||||
 | 
					    <ClInclude Include="Lexer.h" />
 | 
				
			||||||
 | 
					    <ClInclude Include="BoxedVar.h" />
 | 
				
			||||||
 | 
					    <ClInclude Include="LuaScriptGeneration.h" />
 | 
				
			||||||
 | 
					    <ClInclude Include="Operators.h" />
 | 
				
			||||||
 | 
					    <ClInclude Include="Parser.h" />
 | 
				
			||||||
 | 
					    <ClInclude Include="Token.h" />
 | 
				
			||||||
 | 
					    <ClInclude Include="VirtualMachine.h" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <None Include="aaa.ls" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
 | 
				
			||||||
 | 
					  <ImportGroup Label="ExtensionTargets">
 | 
				
			||||||
 | 
					  </ImportGroup>
 | 
				
			||||||
 | 
					</Project>
 | 
				
			||||||
							
								
								
									
										92
									
								
								LightScript/LightScript.vcxproj.filters
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								LightScript/LightScript.vcxproj.filters
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,92 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <Filter Include="소스 파일">
 | 
				
			||||||
 | 
					      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
 | 
				
			||||||
 | 
					      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
 | 
				
			||||||
 | 
					    </Filter>
 | 
				
			||||||
 | 
					    <Filter Include="헤더 파일">
 | 
				
			||||||
 | 
					      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
 | 
				
			||||||
 | 
					      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
 | 
				
			||||||
 | 
					    </Filter>
 | 
				
			||||||
 | 
					    <Filter Include="리소스 파일">
 | 
				
			||||||
 | 
					      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
 | 
				
			||||||
 | 
					      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
 | 
				
			||||||
 | 
					    </Filter>
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <ClCompile Include="main.cpp">
 | 
				
			||||||
 | 
					      <Filter>소스 파일</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <ClCompile Include="Token.cpp">
 | 
				
			||||||
 | 
					      <Filter>소스 파일</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <ClCompile Include="Lexer.cpp">
 | 
				
			||||||
 | 
					      <Filter>소스 파일</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <ClCompile Include="CompoundType.cpp">
 | 
				
			||||||
 | 
					      <Filter>소스 파일</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <ClCompile Include="Parser.cpp">
 | 
				
			||||||
 | 
					      <Filter>소스 파일</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <ClCompile Include="Operators.cpp">
 | 
				
			||||||
 | 
					      <Filter>소스 파일</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <ClCompile Include="ByteCode.cpp">
 | 
				
			||||||
 | 
					      <Filter>소스 파일</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <ClCompile Include="AST.cpp">
 | 
				
			||||||
 | 
					      <Filter>소스 파일</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <ClCompile Include="CodeGeneration.cpp">
 | 
				
			||||||
 | 
					      <Filter>소스 파일</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <ClCompile Include="VirtualMachine.cpp">
 | 
				
			||||||
 | 
					      <Filter>소스 파일</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					    <ClCompile Include="BoxedVar.cpp">
 | 
				
			||||||
 | 
					      <Filter>소스 파일</Filter>
 | 
				
			||||||
 | 
					    </ClCompile>
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <ClInclude Include="Token.h">
 | 
				
			||||||
 | 
					      <Filter>헤더 파일</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					    <ClInclude Include="Lexer.h">
 | 
				
			||||||
 | 
					      <Filter>헤더 파일</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					    <ClInclude Include="Parser.h">
 | 
				
			||||||
 | 
					      <Filter>헤더 파일</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					    <ClInclude Include="AST.h">
 | 
				
			||||||
 | 
					      <Filter>헤더 파일</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					    <ClInclude Include="CompoundType.h">
 | 
				
			||||||
 | 
					      <Filter>헤더 파일</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					    <ClInclude Include="Operators.h">
 | 
				
			||||||
 | 
					      <Filter>헤더 파일</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					    <ClInclude Include="VirtualMachine.h">
 | 
				
			||||||
 | 
					      <Filter>헤더 파일</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					    <ClInclude Include="ByteCode.h">
 | 
				
			||||||
 | 
					      <Filter>헤더 파일</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					    <ClInclude Include="CodeGeneration.h">
 | 
				
			||||||
 | 
					      <Filter>헤더 파일</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					    <ClInclude Include="BoxedVar.h">
 | 
				
			||||||
 | 
					      <Filter>헤더 파일</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					    <ClInclude Include="LuaScriptGeneration.h">
 | 
				
			||||||
 | 
					      <Filter>헤더 파일</Filter>
 | 
				
			||||||
 | 
					    </ClInclude>
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <None Include="aaa.ls">
 | 
				
			||||||
 | 
					      <Filter>리소스 파일</Filter>
 | 
				
			||||||
 | 
					    </None>
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					</Project>
 | 
				
			||||||
							
								
								
									
										11
									
								
								LightScript/LightScript.vcxproj.user
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								LightScript/LightScript.vcxproj.user
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 | 
				
			||||||
 | 
					  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
 | 
				
			||||||
 | 
					    <LocalDebuggerCommandArguments>aaa.ls --debug true --mode lua_script</LocalDebuggerCommandArguments>
 | 
				
			||||||
 | 
					    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
 | 
				
			||||||
 | 
					    <LocalDebuggerCommandArguments>aaa.ls --debug true --mode lua_script</LocalDebuggerCommandArguments>
 | 
				
			||||||
 | 
					    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					</Project>
 | 
				
			||||||
							
								
								
									
										23
									
								
								LightScript/LuaScriptGeneration.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								LightScript/LuaScriptGeneration.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					#include<sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LS_LuaScriptGeneration_H_
 | 
				
			||||||
 | 
					#define LS_LuaScriptGeneration_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ls {
 | 
				
			||||||
 | 
						struct LuaScriptGenerateContext
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							std::ostream * outstream;
 | 
				
			||||||
 | 
							int depth = 0;
 | 
				
			||||||
 | 
							inline std::ostream & out() { return *outstream; }
 | 
				
			||||||
 | 
							inline void out(std::ostream & os) { outstream = &os; }
 | 
				
			||||||
 | 
							inline void sentence_tap() {
 | 
				
			||||||
 | 
								for (size_t i = 0; i < depth; i++)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									out() << "\t";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								LightScript/Operators.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								LightScript/Operators.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					#include "Operators.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string ls::to_string(Opers op)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const char * const lookup[] = { "ERROR",
 | 
				
			||||||
 | 
							"and","or","not","+","-",
 | 
				
			||||||
 | 
							"+","-","*","/",
 | 
				
			||||||
 | 
							"==","!=",">",">=","<",
 | 
				
			||||||
 | 
							"<="
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						return lookup[op];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								LightScript/Operators.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								LightScript/Operators.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,30 @@
 | 
				
			||||||
 | 
					#include<string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LS_Operators_H_
 | 
				
			||||||
 | 
					#define LS_Operators_H_
 | 
				
			||||||
 | 
					namespace ls {
 | 
				
			||||||
 | 
						enum Opers
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							kERROR,
 | 
				
			||||||
 | 
							kAnd,
 | 
				
			||||||
 | 
							kOr,
 | 
				
			||||||
 | 
							kNot,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							kPlus,
 | 
				
			||||||
 | 
							kMinus,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							kAdd,
 | 
				
			||||||
 | 
							kSub,
 | 
				
			||||||
 | 
							kMul,
 | 
				
			||||||
 | 
							kDiv,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							kEqual,
 | 
				
			||||||
 | 
							kNotEqual,
 | 
				
			||||||
 | 
							kGreater,
 | 
				
			||||||
 | 
							kEqualGreater,
 | 
				
			||||||
 | 
							kLess,
 | 
				
			||||||
 | 
							kLessEqual,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						std::string to_string(Opers op);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										447
									
								
								LightScript/Parser.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										447
									
								
								LightScript/Parser.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,447 @@
 | 
				
			||||||
 | 
					#include "Parser.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace ls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using std::make_unique;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_SentenceList> ls::Parser::parseSentenceList()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto ret = make_unique<AST_SentenceList>();
 | 
				
			||||||
 | 
						for (;;) {
 | 
				
			||||||
 | 
							auto sentence = parseSentence();
 | 
				
			||||||
 | 
							if (sentence == nullptr)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							ret->push_back(move(sentence));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Sentence> ls::Parser::parseSentence()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unique_ptr<AST_Sentence> ret;
 | 
				
			||||||
 | 
						if (it->str == "continue") {
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							ret = make_unique<AST_Continue>();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (it->str == "break") {
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							ret = make_unique<AST_Break>();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (it->str == "var") {
 | 
				
			||||||
 | 
							ret = parseVarSentence();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (it->str == "return") {
 | 
				
			||||||
 | 
							ret = parseReturn();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (it->str == "while") {
 | 
				
			||||||
 | 
							ret = parseWhileSentence();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (it->str == "if") {
 | 
				
			||||||
 | 
							ret = parseIfSentence();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (it->str == "for") {
 | 
				
			||||||
 | 
							ret = parseForInSentence();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							ret = parseCommonSentence();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Sentence> ls::Parser::parseCommonSentence()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unique_ptr<AST_Sentence> ret;
 | 
				
			||||||
 | 
						auto lvalue = expr();
 | 
				
			||||||
 | 
						if (lvalue == nullptr) return nullptr;
 | 
				
			||||||
 | 
						if (it->str == "=") {
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto r = expr();
 | 
				
			||||||
 | 
							return make_unique<AST_AssignmentSentence>(move(lvalue), move(r));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return make_unique<AST_CommonSentence>(move(lvalue));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Sentence> ls::Parser::parseVarSentence()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->str == "var") {
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto lv = parseIdentifier();
 | 
				
			||||||
 | 
							if (lv == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Lvalue Expected");
 | 
				
			||||||
 | 
							if (it->str != "=")
 | 
				
			||||||
 | 
								ThrowExpected("expected symbol \'=\'");
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto r = expr();
 | 
				
			||||||
 | 
							if (r == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Rvalue Expected");
 | 
				
			||||||
 | 
							return (make_unique<AST_VarSentence>(move(lv), move(r)));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Sentence> ls::Parser::parseWhileSentence()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->str == "while") {
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto lv = expr();
 | 
				
			||||||
 | 
							if (lv == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("expr Expected");
 | 
				
			||||||
 | 
							if (it->str != "do")
 | 
				
			||||||
 | 
								ThrowExpected("expected keyword \'do\'");
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto r = parseSentenceList();
 | 
				
			||||||
 | 
							if (r == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Rvalue Expected");
 | 
				
			||||||
 | 
							if (it->str != "end")
 | 
				
			||||||
 | 
								ThrowExpected("end Expected");
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							return (make_unique<AST_While>(move(lv), move(r)));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Sentence> ls::Parser::parseIfSentence()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->str == "if") {
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto lv = expr();
 | 
				
			||||||
 | 
							if (lv == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("expr Expected");
 | 
				
			||||||
 | 
							if (it->str != "then")
 | 
				
			||||||
 | 
								ThrowExpected("expected keyword \'then\'");
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto r = parseSentenceList();
 | 
				
			||||||
 | 
							if (r == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Rvalue Expected");
 | 
				
			||||||
 | 
							auto ret = (make_unique<AST_If>(move(lv), move(r)));
 | 
				
			||||||
 | 
							if (it->str == "else") {
 | 
				
			||||||
 | 
								it++;
 | 
				
			||||||
 | 
								auto elsec = parseSentenceList();
 | 
				
			||||||
 | 
								if (elsec == nullptr)
 | 
				
			||||||
 | 
									ThrowExpected("expected Sentence next to else");
 | 
				
			||||||
 | 
								ret->setElse(move(elsec));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (it->str != "end")
 | 
				
			||||||
 | 
								ThrowExpected("end Expected");
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Sentence> ls::Parser::parseForInSentence()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->str == "for") {
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto id = parseIdentifier();
 | 
				
			||||||
 | 
							if (id == nullptr) {
 | 
				
			||||||
 | 
								ThrowExpected("expected identifier");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (it->str != "in")
 | 
				
			||||||
 | 
								ThrowExpected("expected keyword \'in\'");
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto lv = expr();
 | 
				
			||||||
 | 
							if (lv == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("expr Expected");
 | 
				
			||||||
 | 
							if (it->str != "do")
 | 
				
			||||||
 | 
								ThrowExpected("expected keyword \'do\'");
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto sl = parseSentenceList();
 | 
				
			||||||
 | 
							if (sl == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Rvalue Expected");
 | 
				
			||||||
 | 
							if (it->str != "end")
 | 
				
			||||||
 | 
								ThrowExpected("end Expected");
 | 
				
			||||||
 | 
							return make_unique<AST_ForIn>(move(id), move(lv), move(sl));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Sentence> ls::Parser::parseReturn()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->str == "return") {
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto retValue = expr();
 | 
				
			||||||
 | 
							if (retValue != nullptr)
 | 
				
			||||||
 | 
								return make_unique<AST_Return>(move(retValue));
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								return make_unique<AST_Return>(make_unique<AST_None>());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> Parser::parseLogicalBinary()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unique_ptr<AST_Expr> LHS, RHS;
 | 
				
			||||||
 | 
						LHS = parseLogicalUnary();
 | 
				
			||||||
 | 
						if (LHS == nullptr)
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						while (it->str == "and" || it->str == "or") {
 | 
				
			||||||
 | 
							auto op = it->str;
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							RHS = parseLogicalUnary();
 | 
				
			||||||
 | 
							if (RHS == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Expected Expression");
 | 
				
			||||||
 | 
							if (op == "and")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kAnd,move(LHS), move(RHS));
 | 
				
			||||||
 | 
							else if (op == "or")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kOr,move(LHS), move(RHS));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return LHS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> ls::Parser::parseLogicalUnary()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->str == "not") {
 | 
				
			||||||
 | 
							++it; 
 | 
				
			||||||
 | 
							auto ret = parseComparison();
 | 
				
			||||||
 | 
							if (ret == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Expected Expression");
 | 
				
			||||||
 | 
							return make_unique<AST_Unary>(kNot,move(ret));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return parseComparison();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> ls::Parser::parseComparison()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unique_ptr<AST_Expr> LHS, RHS;
 | 
				
			||||||
 | 
						LHS = parseAddAndSub();
 | 
				
			||||||
 | 
						if (LHS == nullptr)
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						while (it->str == "=="||
 | 
				
			||||||
 | 
							it->str == "!="||
 | 
				
			||||||
 | 
							it->str == "<"||
 | 
				
			||||||
 | 
							it->str == "<="||
 | 
				
			||||||
 | 
							it->str == ">"||
 | 
				
			||||||
 | 
							it->str == ">=") {
 | 
				
			||||||
 | 
							auto op = it->str;
 | 
				
			||||||
 | 
							++it;
 | 
				
			||||||
 | 
							RHS = parseAddAndSub();
 | 
				
			||||||
 | 
							if (RHS == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Expected Expression");
 | 
				
			||||||
 | 
							if (op == "==")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kEqual, move(LHS), move(RHS));
 | 
				
			||||||
 | 
							else if (op == "!=")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kNotEqual, move(LHS), move(RHS));
 | 
				
			||||||
 | 
							else if (op == ">")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kGreater, move(LHS), move(RHS));
 | 
				
			||||||
 | 
							else if (op == ">=")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kEqualGreater, move(LHS), move(RHS));
 | 
				
			||||||
 | 
							else if (op == "<")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kLess, move(LHS), move(RHS));
 | 
				
			||||||
 | 
							else if (op == "<=")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kLessEqual, move(LHS), move(RHS));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return LHS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> ls::Parser::parseAddAndSub()	//code ¸®ÆåÅ丵 ÇÒ °÷.
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unique_ptr<AST_Expr> LHS, RHS;
 | 
				
			||||||
 | 
						if (it->str == "+") {
 | 
				
			||||||
 | 
							++it;
 | 
				
			||||||
 | 
							LHS = parseMulAndDiv();
 | 
				
			||||||
 | 
							if (LHS == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Expected Expression");
 | 
				
			||||||
 | 
							LHS = make_unique<AST_Unary>(kPlus,move(LHS));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (it->str == "-") {
 | 
				
			||||||
 | 
							++it;
 | 
				
			||||||
 | 
							LHS = parseMulAndDiv();
 | 
				
			||||||
 | 
							if (LHS == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Expected Expression");
 | 
				
			||||||
 | 
							LHS = make_unique<AST_Unary>(kMinus,move(LHS));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							LHS = parseMulAndDiv();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (LHS == nullptr)
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						while (it->str == "+" || it->str == "-") {
 | 
				
			||||||
 | 
							auto op = it->str;
 | 
				
			||||||
 | 
							++it;
 | 
				
			||||||
 | 
							RHS = parseMulAndDiv();
 | 
				
			||||||
 | 
							if (RHS == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Expected Expression");
 | 
				
			||||||
 | 
							if (op == "+")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kAdd,move(LHS), move(RHS));
 | 
				
			||||||
 | 
							else if (op == "-")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kSub,move(LHS), move(RHS));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return LHS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> ls::Parser::parseMulAndDiv()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unique_ptr<AST_Expr> LHS, RHS;
 | 
				
			||||||
 | 
						LHS = parseAttrAccess();
 | 
				
			||||||
 | 
						if (LHS == nullptr)
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						while (it->str == "*" || it->str == "/") {
 | 
				
			||||||
 | 
							auto op = it->str;
 | 
				
			||||||
 | 
							++it;
 | 
				
			||||||
 | 
							RHS = parseAttrAccess();
 | 
				
			||||||
 | 
							if (RHS == nullptr)
 | 
				
			||||||
 | 
								ThrowExpected("Expected Expression");
 | 
				
			||||||
 | 
							if (op == "*")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kMul,move(LHS), move(RHS));
 | 
				
			||||||
 | 
							else if (op == "/")
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Binary>(kDiv,move(LHS), move(RHS));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return LHS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> ls::Parser::parseAttrAccess()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unique_ptr<AST_Expr> LHS;
 | 
				
			||||||
 | 
						LHS = parsePrimary();
 | 
				
			||||||
 | 
						if (LHS == nullptr)
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						for(;;){
 | 
				
			||||||
 | 
							if (it->str == "[") {
 | 
				
			||||||
 | 
								++it;
 | 
				
			||||||
 | 
								auto RHS = expr();
 | 
				
			||||||
 | 
								if (RHS == nullptr)
 | 
				
			||||||
 | 
									ThrowExpected("Expected Expression");
 | 
				
			||||||
 | 
								if (it->str != "]")
 | 
				
			||||||
 | 
									ThrowExpected("Expected \')\'");
 | 
				
			||||||
 | 
								it++;
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Index>(move(LHS), move(RHS));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (it->str == ".") {
 | 
				
			||||||
 | 
								it++;
 | 
				
			||||||
 | 
								auto RHS = parseIdentifier();
 | 
				
			||||||
 | 
								LHS = make_unique<AST_Dot>(move(LHS), move(RHS));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (it->str == "(") {
 | 
				
			||||||
 | 
								++it;
 | 
				
			||||||
 | 
								auto L = make_unique<AST_CallExpr>(move(LHS));
 | 
				
			||||||
 | 
								if (it->str != ")")
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									auto RHS = expr();
 | 
				
			||||||
 | 
									if (RHS == nullptr) {
 | 
				
			||||||
 | 
										ThrowExpected("Expected expression.");
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									L->push_back(move(RHS));
 | 
				
			||||||
 | 
									while (it->str != ")") {
 | 
				
			||||||
 | 
										if (it->str != ",") {
 | 
				
			||||||
 | 
											ThrowExpected("Expected \',\'");
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										it++;
 | 
				
			||||||
 | 
										RHS = expr();
 | 
				
			||||||
 | 
										if (RHS == nullptr)
 | 
				
			||||||
 | 
											ThrowExpected("Expected expression.");
 | 
				
			||||||
 | 
										L->push_back(move(RHS));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									it++;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								LHS = move(L);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return LHS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> ls::Parser::parsePrimary()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->str == "(")
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							auto ret = expr();
 | 
				
			||||||
 | 
							if (ret == nullptr) {
 | 
				
			||||||
 | 
								ThrowExpected("expected expression");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (it->str != ")") {
 | 
				
			||||||
 | 
								ThrowExpected("expected \')\'");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (it->type == ttIdentifier) {
 | 
				
			||||||
 | 
							return parseIdentifier();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return parseLiteral();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> ls::Parser::parseLiteral()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->type == ls::TokenType::ttInteger) {
 | 
				
			||||||
 | 
							return parseInteger();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (it->type == ttFloat) {
 | 
				
			||||||
 | 
							return parseFloating();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (it->str == "fn") {
 | 
				
			||||||
 | 
							return parseFunction();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (it->str == "{") {
 | 
				
			||||||
 | 
							return parseTableExpr();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> Parser::parseInteger()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->type != TokenType::ttInteger)
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						auto value = std::stoll(it->str);
 | 
				
			||||||
 | 
						it++;
 | 
				
			||||||
 | 
						return make_unique<AST_Int>(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> Parser::parseFloating()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->type != TokenType::ttFloat)
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						auto value = std::stod(it->str);
 | 
				
			||||||
 | 
						it++;
 | 
				
			||||||
 | 
						return make_unique<AST_Float>(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> ls::Parser::parseFunction()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->str != "fn")
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						it++;
 | 
				
			||||||
 | 
						if (it->str != "(")
 | 
				
			||||||
 | 
							ThrowExpected("expected \'(\'");
 | 
				
			||||||
 | 
						auto L = make_unique<AST_Function>();
 | 
				
			||||||
 | 
						it++;
 | 
				
			||||||
 | 
						if (it->str != ")")
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto Id = parseIdentifier();
 | 
				
			||||||
 | 
							if (Id == nullptr) {
 | 
				
			||||||
 | 
								ThrowExpected("Expected Identifier.");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							L->push_back(move(Id));
 | 
				
			||||||
 | 
							while (it->str != ")") {
 | 
				
			||||||
 | 
								if (it->str != ",") {
 | 
				
			||||||
 | 
									ThrowExpected("Expected \',\'");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								it++;
 | 
				
			||||||
 | 
								Id = parseIdentifier();
 | 
				
			||||||
 | 
								if (Id == nullptr)
 | 
				
			||||||
 | 
									ThrowExpected("Expected Identifier.");
 | 
				
			||||||
 | 
								L->push_back(move(Id));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						L->setSentenceList(parseSentenceList());
 | 
				
			||||||
 | 
						if (it->str != "end")
 | 
				
			||||||
 | 
							ThrowExpected("expected \'end\'");
 | 
				
			||||||
 | 
						it++;
 | 
				
			||||||
 | 
						return L;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Expr> ls::Parser::parseTableExpr()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unique_ptr<AST_Ident> ls::Parser::parseIdentifier()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (it->type == ttIdentifier) {
 | 
				
			||||||
 | 
							auto ret = make_unique<AST_Ident>(it->str);
 | 
				
			||||||
 | 
							it++;
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										75
									
								
								LightScript/Parser.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								LightScript/Parser.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,75 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include<memory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include<list>
 | 
				
			||||||
 | 
					#include<exception>
 | 
				
			||||||
 | 
					#include"Token.h"
 | 
				
			||||||
 | 
					#include"AST.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LS_Parser_H_
 | 
				
			||||||
 | 
					#define LS_Parser_H_
 | 
				
			||||||
 | 
					namespace ls {
 | 
				
			||||||
 | 
						typedef std::list<Token> Container;
 | 
				
			||||||
 | 
						typedef Container::const_iterator Tokit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class ExpectedException : public std::exception {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							ExpectedException(const char * const message, int l) 
 | 
				
			||||||
 | 
								:std::exception(message), line(l) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int line;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						using std::unique_ptr;
 | 
				
			||||||
 | 
						class Parser {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							inline void ThrowExpected(const char * const message) {
 | 
				
			||||||
 | 
								throw ExpectedException(message, it->line);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void set(Tokit begin) { it = begin; }
 | 
				
			||||||
 | 
							unique_ptr<AST_SentenceList> parseSentenceList();
 | 
				
			||||||
 | 
							unique_ptr<AST_Sentence> parseSentence();
 | 
				
			||||||
 | 
							inline unique_ptr<AST_Expr> expr() { return parseLogicalBinary(); }
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							unique_ptr<AST_Sentence> parseCommonSentence();
 | 
				
			||||||
 | 
							unique_ptr<AST_Sentence> parseVarSentence();
 | 
				
			||||||
 | 
							unique_ptr<AST_Sentence> parseWhileSentence();
 | 
				
			||||||
 | 
							unique_ptr<AST_Sentence> parseIfSentence();
 | 
				
			||||||
 | 
							unique_ptr<AST_Sentence> parseForInSentence();
 | 
				
			||||||
 | 
							unique_ptr<AST_Sentence> parseReturn();
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							//<LogicalBinary> := <LogicalUnary>{("and"|"or")-<LogicalUnary>}
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parseLogicalBinary();
 | 
				
			||||||
 | 
							//<LogicalUnary> := ["not"]<Comparison>
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parseLogicalUnary();
 | 
				
			||||||
 | 
							//<Comparison> := <AddAndSub>{("=="|"!="|"<="|"<"|">="|">")-<AddAndSub>}
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parseComparison();
 | 
				
			||||||
 | 
							//<AddAndSub> := ["+"|"-"]<MulAndDiv>{("+"|"-")-<MulAndDiv>}
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parseAddAndSub();
 | 
				
			||||||
 | 
							//<MulAndDiv> := <AttrAccess>{("*"|"/")-<AttrAccess>}
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parseMulAndDiv();
 | 
				
			||||||
 | 
							//<AttrAccess> := <PrimaryExpr>{("["-<expr>-"]")|("("-([<Expr>],{","-<Expr>})-")")|"."<Identifer>}
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parseAttrAccess();
 | 
				
			||||||
 | 
							//<Primary> := "("-<expr>-")"|<Identifier>|<Literal>
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parsePrimary();
 | 
				
			||||||
 | 
							//<Literal> := <Interger>|<Floating>|<String>|<Table>|<Function>
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parseLiteral();
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parseInteger();
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parseFloating();
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parseFunction();
 | 
				
			||||||
 | 
							//¿Ï¼º ¾ÈµÊ.
 | 
				
			||||||
 | 
							unique_ptr<AST_Expr> parseTableExpr();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							unique_ptr<AST_Ident> parseIdentifier();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							//unique_ptr<AST_Expr> level6()
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							Tokit it;
 | 
				
			||||||
 | 
							Tokit end;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										20
									
								
								LightScript/Token.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								LightScript/Token.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include "Token.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char * ls::keyword_list[20] = { "if","else","elif","fn","for","in","while","loop","end","then" };
 | 
				
			||||||
 | 
					static const char * token_type_list[] = {"eof","op",
 | 
				
			||||||
 | 
					"int",
 | 
				
			||||||
 | 
					"kwrd",
 | 
				
			||||||
 | 
					"float",
 | 
				
			||||||
 | 
					"str",
 | 
				
			||||||
 | 
					"ident",
 | 
				
			||||||
 | 
					"hex",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::ostream & ls::operator<<(std::ostream & os, const Token & tk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						os <<"[" << tk.str<<",";
 | 
				
			||||||
 | 
						os << token_type_list[tk.type]<<"]";
 | 
				
			||||||
 | 
						return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										37
									
								
								LightScript/Token.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								LightScript/Token.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					#include<string>
 | 
				
			||||||
 | 
					#include<ostream>
 | 
				
			||||||
 | 
					#ifndef LS_Token_H_
 | 
				
			||||||
 | 
					#define LS_Token_H_
 | 
				
			||||||
 | 
					//#ifndef _LS_Token_H_
 | 
				
			||||||
 | 
					//#define _LS_Token_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ls {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum TokenType
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ttEof,
 | 
				
			||||||
 | 
							ttOperator,
 | 
				
			||||||
 | 
							ttInteger,
 | 
				
			||||||
 | 
							ttKeyword,
 | 
				
			||||||
 | 
							ttFloat,
 | 
				
			||||||
 | 
							ttString,
 | 
				
			||||||
 | 
							ttIdentifier,
 | 
				
			||||||
 | 
							ttHexnumber,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						struct Token
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							TokenType type;
 | 
				
			||||||
 | 
							int line;
 | 
				
			||||||
 | 
							std::string str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Token():type(ttEof),line(0)
 | 
				
			||||||
 | 
							{}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						extern const char * keyword_list[20];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::ostream & operator<<(std::ostream & os, const Token & tk);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										435
									
								
								LightScript/VirtualMachine.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										435
									
								
								LightScript/VirtualMachine.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,435 @@
 | 
				
			||||||
 | 
					#include "VirtualMachine.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace ls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ls::VirtualMachine::runOneCode()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (programCounter>=programFrameEnd) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						switch (programFrame->code[programCounter].code)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case code_t::nop:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::add:
 | 
				
			||||||
 | 
							add();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::enterScope:
 | 
				
			||||||
 | 
							enterScope();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::leaveScope:
 | 
				
			||||||
 | 
							leaveScope();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::load:
 | 
				
			||||||
 | 
							load();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::and:
 | 
				
			||||||
 | 
							and();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::or:
 | 
				
			||||||
 | 
							or();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::not:
 | 
				
			||||||
 | 
							not();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::sub:
 | 
				
			||||||
 | 
							sub();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::mul:
 | 
				
			||||||
 | 
							mul();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::div:
 | 
				
			||||||
 | 
							div();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::plus:
 | 
				
			||||||
 | 
							plus();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::minus:
 | 
				
			||||||
 | 
							minus();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::eq:
 | 
				
			||||||
 | 
							eq();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::neq:
 | 
				
			||||||
 | 
							neq();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::gt:
 | 
				
			||||||
 | 
							gt();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::gte:
 | 
				
			||||||
 | 
							gte();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::less:
 | 
				
			||||||
 | 
							less();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::leq:
 | 
				
			||||||
 | 
							leq();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::push:
 | 
				
			||||||
 | 
							push();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::pop:
 | 
				
			||||||
 | 
							pop();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::store:
 | 
				
			||||||
 | 
							store();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::new_var:
 | 
				
			||||||
 | 
							new_var();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::jmp:
 | 
				
			||||||
 | 
							jmp();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::jt:
 | 
				
			||||||
 | 
							jt();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::jf:
 | 
				
			||||||
 | 
							jf();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::call:
 | 
				
			||||||
 | 
							call();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::ref:
 | 
				
			||||||
 | 
							ref();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case code_t::ret:
 | 
				
			||||||
 | 
							inst_ret();
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							throw std::runtime_error("Invailed op code.");
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						programCounter++;
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BoxedVar & ls::VirtualMachine::searchVar(const std::string & str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						for (auto it = variableMap.rbegin(), E = variableMap.rend(); it != E; it++) {
 | 
				
			||||||
 | 
							auto f = it->find(str);
 | 
				
			||||||
 | 
							if(f != it->end()){
 | 
				
			||||||
 | 
								return f->second;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						throw std::runtime_error("Unknown Variable");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::enterScope()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						variableMap.emplace_back();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::leaveScope()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						variableMap.pop_back();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::add()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kAdd, RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::load()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto str = popValue();
 | 
				
			||||||
 | 
						if (str.get()->Type() != kString) {
 | 
				
			||||||
 | 
							throw std::runtime_error("Load Failed!");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						TempVariable t(&searchVar(static_cast<StringType *>(str.get())->value));
 | 
				
			||||||
 | 
						pushValue(t);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::sub()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kSub, RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::mul()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kMul, RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::div()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kDiv, RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::plus()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->unaryGo(Opers::kPlus));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::minus()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->unaryGo(Opers::kMinus));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::eq()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kEqual, RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::gt()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kGreater, RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::gte()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kEqualGreater, RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::less()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kLess, RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::leq()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kLessEqual, RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::neq()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kNotEqual, RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::new_var()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto lst = popValue();
 | 
				
			||||||
 | 
						auto rst = popValue();
 | 
				
			||||||
 | 
						if (lst.get()->Type() != kString)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							throw std::runtime_error("변수이름은 문자열이어야 합니다.");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto name = static_cast<StringType *>(lst.get())->value;
 | 
				
			||||||
 | 
						auto pos = variableMap.back().find(name);
 | 
				
			||||||
 | 
						if (pos != variableMap.back().end()) {
 | 
				
			||||||
 | 
							throw std::runtime_error("이미 선언된 변수.");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						variableMap.back().emplace(name, *rst.val());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::jmp()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto st = popValue();
 | 
				
			||||||
 | 
						auto s = st.cast<IntegerType>(kInteger);
 | 
				
			||||||
 | 
						programCounter += s->value;
 | 
				
			||||||
 | 
						programCounter--;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::jt()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto jmp_count = popValue();
 | 
				
			||||||
 | 
						auto condition = popValue();
 | 
				
			||||||
 | 
						auto jmp = jmp_count.cast<IntegerType>(kInteger);
 | 
				
			||||||
 | 
						auto cond = condition.cast<BooleanType>(kBoolean);
 | 
				
			||||||
 | 
						if (cond->value) {
 | 
				
			||||||
 | 
							programCounter += jmp->value;
 | 
				
			||||||
 | 
							programCounter--;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::jf()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto jmp_count = popValue();
 | 
				
			||||||
 | 
						auto condition = popValue();
 | 
				
			||||||
 | 
						auto jmp = jmp_count.cast<IntegerType>(kInteger);
 | 
				
			||||||
 | 
						auto cond = condition.cast<BooleanType>(kBoolean);
 | 
				
			||||||
 | 
						if (!cond->value) {
 | 
				
			||||||
 | 
							programCounter += jmp->value;
 | 
				
			||||||
 | 
							programCounter--;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::store()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto fvar = popValue();//LHS=RHS
 | 
				
			||||||
 | 
						auto lvar = popValue();
 | 
				
			||||||
 | 
						*fvar.val() = *lvar.val();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::and()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kAnd, LHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::or()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->binaryGo(Opers::kOr, RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::not()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(LHS.get()->unaryGo(Opers::kNot));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::pop()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						popValue();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::push()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.setval(&programFrame->operands[programFrame->code[programCounter].pos]);
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::inst_ret()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (callstack.size() == 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							throw std::runtime_error("Call Stack Error");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stack.back().copyTemp();
 | 
				
			||||||
 | 
						auto b = callstack.back();
 | 
				
			||||||
 | 
						programFrame = b.frame;
 | 
				
			||||||
 | 
						programFrameEnd = b.frame->code.size();
 | 
				
			||||||
 | 
						programCounter = b.address;
 | 
				
			||||||
 | 
						callstack.pop_back();
 | 
				
			||||||
 | 
						leaveScope();
 | 
				
			||||||
 | 
						programCounter--;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::next()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						bool vailed = LHS.get()->next();
 | 
				
			||||||
 | 
						if (!vailed) {
 | 
				
			||||||
 | 
							throw std::runtime_error("Type not able to iterate");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pushValue(LHS);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::getvalue()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto t = LHS.cast<TableIterType>(kTableIter);
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(t->value());
 | 
				
			||||||
 | 
						pushValue(LHS);
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::isEnd()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto t = LHS.cast<TableIterType>(kTableIter);
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(createVar(t->isEnd()));
 | 
				
			||||||
 | 
						pushValue(LHS);
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::getiter()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto table = LHS.cast<TableType>(kTable);
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.val()->set(table->getiter());
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::call()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto f = popValue();
 | 
				
			||||||
 | 
						switch (f.get()->Type()) {
 | 
				
			||||||
 | 
						case kFunctionProxy:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto fn = static_cast<FunctionProxyType *>(f.get());
 | 
				
			||||||
 | 
							auto arg_numT = popValue();
 | 
				
			||||||
 | 
							auto arg_num = arg_numT.cast<IntegerType>(kInteger);
 | 
				
			||||||
 | 
							std::vector<BoxedVar> C_stack;
 | 
				
			||||||
 | 
							for (size_t i = 0,endnum = arg_num->value; i < endnum; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto tmp = popValue();
 | 
				
			||||||
 | 
								C_stack.push_back(*tmp.val());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							auto ret = TempVariable();
 | 
				
			||||||
 | 
							ret.val()->set(fn->call(C_stack));
 | 
				
			||||||
 | 
							pushValue(ret);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
						case kFunction:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto fn = static_cast<FunctionType *>(f.get());
 | 
				
			||||||
 | 
							callstack.push_back({ programFrame,programCounter+1 });
 | 
				
			||||||
 | 
							programFrame = fn->code.get();
 | 
				
			||||||
 | 
							programFrameEnd = programFrame->code.size();
 | 
				
			||||||
 | 
							programCounter = -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							unexpected();//
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ls::VirtualMachine::ref()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto LHS = popValue();
 | 
				
			||||||
 | 
						auto RHS = popValue();
 | 
				
			||||||
 | 
						TempVariable tmp;
 | 
				
			||||||
 | 
						tmp.setval(LHS.get()->index(RHS.get()));
 | 
				
			||||||
 | 
						pushValue(tmp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										126
									
								
								LightScript/VirtualMachine.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								LightScript/VirtualMachine.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,126 @@
 | 
				
			||||||
 | 
					#include<memory>
 | 
				
			||||||
 | 
					#include<unordered_map>
 | 
				
			||||||
 | 
					#include<string>
 | 
				
			||||||
 | 
					#include"ByteCode.h"
 | 
				
			||||||
 | 
					#include"BoxedVar.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LS_VirtualMachine_H_
 | 
				
			||||||
 | 
					#define LS_VirtualMachine_H_
 | 
				
			||||||
 | 
					namespace ls {
 | 
				
			||||||
 | 
						//아름답지 못한 꼼수. 나중에 최적화 할 수 있는데로 해보겠음.
 | 
				
			||||||
 | 
						struct TempVariable{
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							BoxedVar * value;
 | 
				
			||||||
 | 
							BoxedVar temp;
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							explicit TempVariable() :value(nullptr) {}
 | 
				
			||||||
 | 
							explicit TempVariable(BoxedVar * ptr) :value(ptr) {}
 | 
				
			||||||
 | 
							TempVariable(const TempVariable & rhs)
 | 
				
			||||||
 | 
								:value(rhs.value), temp(rhs.temp) {
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							inline BoxedVar * val() { 
 | 
				
			||||||
 | 
								if (nullptr == value) return &temp;
 | 
				
			||||||
 | 
								return value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							inline CompoundType * get() {
 | 
				
			||||||
 | 
								return val()->get().get();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							inline void setval(BoxedVar * ptr) { value = ptr;}
 | 
				
			||||||
 | 
							inline void copyTemp() { 
 | 
				
			||||||
 | 
								temp = *value;
 | 
				
			||||||
 | 
								value = nullptr;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							template<typename Ty>
 | 
				
			||||||
 | 
							Ty * cast(TypeKind t) {
 | 
				
			||||||
 | 
								auto ret = get();
 | 
				
			||||||
 | 
								if (ret->Type() != t)
 | 
				
			||||||
 | 
									throw std::exception("Invaild Type Casting Error!");
 | 
				
			||||||
 | 
								return static_cast<Ty *>(ret);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						class VirtualMachine {
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							VirtualMachine(){
 | 
				
			||||||
 | 
								std::unordered_map<std::string, BoxedVar> t;
 | 
				
			||||||
 | 
								variableMap.push_back(t);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							//보안적으로 위험함. 메모리 위험.
 | 
				
			||||||
 | 
							void set(FunctionCode * ic) { instcodes = ic;
 | 
				
			||||||
 | 
							programFrame = ic;
 | 
				
			||||||
 | 
							programFrameEnd = ic->code.size();
 | 
				
			||||||
 | 
							programCounter = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							bool runOneCode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							BoxedVar & searchVar(const std::string & str);
 | 
				
			||||||
 | 
							BoxedVar & setVar(const std::string & str) { return variableMap.back()[str]; }
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							void enterScope();
 | 
				
			||||||
 | 
							void leaveScope();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							void add();
 | 
				
			||||||
 | 
							void sub();
 | 
				
			||||||
 | 
							void mul();
 | 
				
			||||||
 | 
							void div();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							void plus();
 | 
				
			||||||
 | 
							void minus();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							void eq();
 | 
				
			||||||
 | 
							void neq();
 | 
				
			||||||
 | 
							void gt();
 | 
				
			||||||
 | 
							void gte();
 | 
				
			||||||
 | 
							void less();
 | 
				
			||||||
 | 
							void leq();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							void store();
 | 
				
			||||||
 | 
							void new_var();
 | 
				
			||||||
 | 
							void jmp();
 | 
				
			||||||
 | 
							void jt();
 | 
				
			||||||
 | 
							void jf();
 | 
				
			||||||
 | 
							void call();
 | 
				
			||||||
 | 
							void ref();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							void load();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void and();
 | 
				
			||||||
 | 
							void or();
 | 
				
			||||||
 | 
							void not();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void pop();
 | 
				
			||||||
 | 
							void push();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void inst_ret();
 | 
				
			||||||
 | 
							void next();
 | 
				
			||||||
 | 
							void getvalue();
 | 
				
			||||||
 | 
							void isEnd();
 | 
				
			||||||
 | 
							void getiter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							TempVariable popValue()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (stack.size() == 0)
 | 
				
			||||||
 | 
									throw std::runtime_error("invaild");
 | 
				
			||||||
 | 
								auto v = stack.back();
 | 
				
			||||||
 | 
								stack.pop_back();
 | 
				
			||||||
 | 
								return v;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							inline void pushValue(const TempVariable & t) {
 | 
				
			||||||
 | 
								stack.emplace_back(t);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							struct CallStackValue
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								FunctionCode * frame;
 | 
				
			||||||
 | 
								pos_t address;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							std::list<std::unordered_map<std::string, BoxedVar> > variableMap;
 | 
				
			||||||
 | 
							std::vector<TempVariable> stack;
 | 
				
			||||||
 | 
							std::vector<CallStackValue> callstack;
 | 
				
			||||||
 | 
							FunctionCode * instcodes;
 | 
				
			||||||
 | 
							FunctionCode * programFrame;
 | 
				
			||||||
 | 
							pos_t programFrameEnd;
 | 
				
			||||||
 | 
							pos_t programCounter;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										11
									
								
								LightScript/aaa.ls
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								LightScript/aaa.ls
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					var sum = fn(x,y)
 | 
				
			||||||
 | 
						var r = 0
 | 
				
			||||||
 | 
						var i = x
 | 
				
			||||||
 | 
						while y >= i do
 | 
				
			||||||
 | 
							r = r + i
 | 
				
			||||||
 | 
							i = i+1
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					var a = sum(1,10)
 | 
				
			||||||
 | 
					print(a)
 | 
				
			||||||
							
								
								
									
										202
									
								
								LightScript/main.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								LightScript/main.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,202 @@
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include "Lexer.h"
 | 
				
			||||||
 | 
					#include "Parser.h"
 | 
				
			||||||
 | 
					#include "VirtualMachine.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Option {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						Option(int n, const char ** v) :argnum(n), argvalue(v),cur(1)
 | 
				
			||||||
 | 
						{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char * find(const char * optname) {
 | 
				
			||||||
 | 
							for (size_t i = cur; i < argnum; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (strcmp(argvalue[i], optname) == 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (i + 1 < argnum)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										return argvalue[i + 1];
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										std::cout << "invailed argument";
 | 
				
			||||||
 | 
										exit(1);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						const char * getFile() {
 | 
				
			||||||
 | 
							return argvalue[cur++];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						int argnum;
 | 
				
			||||||
 | 
						const char ** argvalue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int cur;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void usage()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::cout <<
 | 
				
			||||||
 | 
							"usage : LightScript inputfile [-m][-d]\n"
 | 
				
			||||||
 | 
							"	-m, --mode : intepreter, lua_script\n"
 | 
				
			||||||
 | 
							"		(default is native)\n"
 | 
				
			||||||
 | 
							"	-d --debug : true, false\n"
 | 
				
			||||||
 | 
							"		(default is false)\n"
 | 
				
			||||||
 | 
							"	-o --output : path of the output file\n"
 | 
				
			||||||
 | 
							"				  only needed if mode is lua_script.\n"
 | 
				
			||||||
 | 
							"		(default is \"./output.lua\")\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//std::shared_ptr<CompoundType> call(std::vector<BoxedVar> & stack)
 | 
				
			||||||
 | 
					std::shared_ptr<ls::CompoundType> my_print(std::vector<ls::BoxedVar> & stack) {
 | 
				
			||||||
 | 
						std::cout << stack[0].to_string() << std::endl;
 | 
				
			||||||
 | 
						return ls::createVar();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//=================================
 | 
				
			||||||
 | 
					//option
 | 
				
			||||||
 | 
					//=================================
 | 
				
			||||||
 | 
					bool debug = false;
 | 
				
			||||||
 | 
					std::string mode = "native";
 | 
				
			||||||
 | 
					std::string output_path = "./output.lua";
 | 
				
			||||||
 | 
					//=================================
 | 
				
			||||||
 | 
					void setOption(Option & opt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, const char * argv[]) {
 | 
				
			||||||
 | 
						Option opt(argc, argv);
 | 
				
			||||||
 | 
						if (argc == 1) {
 | 
				
			||||||
 | 
							usage();
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						std::string filename(opt.getFile());
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						setOption(opt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::list<ls::Token> tokens;
 | 
				
			||||||
 | 
						ls::GenerationContext gct;
 | 
				
			||||||
 | 
						ls::VirtualMachine vm;
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							std::ifstream file(filename);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							ls::IstreamTokenizer tokenizer(file);
 | 
				
			||||||
 | 
							ls::Token t;
 | 
				
			||||||
 | 
							do {
 | 
				
			||||||
 | 
								t = tokenizer.get();
 | 
				
			||||||
 | 
								tokens.push_back(t);
 | 
				
			||||||
 | 
							} while (t.type != ls::ttEof);
 | 
				
			||||||
 | 
							file.close();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (debug)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							std::cout << 
 | 
				
			||||||
 | 
								"========================\n"
 | 
				
			||||||
 | 
								"tokens\n"
 | 
				
			||||||
 | 
								"========================\n";
 | 
				
			||||||
 | 
							for (auto it : tokens)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								std::cout << it;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							std::cout << std::endl;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ls::Parser ps;
 | 
				
			||||||
 | 
							ps.set(tokens.begin());
 | 
				
			||||||
 | 
							std::unique_ptr<ls::AST_SentenceList> tree;
 | 
				
			||||||
 | 
							try
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								tree = ps.parseSentenceList();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							catch (const ls::ExpectedException & e)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								std::cout <<"Grammar error : "<< e.what() << "\n"
 | 
				
			||||||
 | 
									" line : " << e.line << "\n";
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if (debug)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								std::cout << "========================\n"
 | 
				
			||||||
 | 
									<<"tree\n"
 | 
				
			||||||
 | 
									<<"========================\n"
 | 
				
			||||||
 | 
									<<tree << std::endl;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (mode == "native") {
 | 
				
			||||||
 | 
								tree->generateCode(gct);
 | 
				
			||||||
 | 
								if (debug)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									std::cout <<"========================\n"
 | 
				
			||||||
 | 
										"instruction code\n"
 | 
				
			||||||
 | 
										"========================\n"
 | 
				
			||||||
 | 
										<< gct
 | 
				
			||||||
 | 
										<< "========================\n";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if(mode == "lua_script") {
 | 
				
			||||||
 | 
								std::ofstream output(output_path);
 | 
				
			||||||
 | 
								if (!output.is_open()) {
 | 
				
			||||||
 | 
									std::cout << "open failed!\n";
 | 
				
			||||||
 | 
									return 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ls::LuaScriptGenerateContext lsgc;
 | 
				
			||||||
 | 
								lsgc.out(output);
 | 
				
			||||||
 | 
								tree->luaCodeGen(lsgc);
 | 
				
			||||||
 | 
								output.close();
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								std::cout << "invailed mode input";
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							vm.setVar("print") = ls::createBoxedFunction(my_print);
 | 
				
			||||||
 | 
							vm.set(gct.getFrame());
 | 
				
			||||||
 | 
							try
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								while (vm.runOneCode());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							catch (const std::exception& e)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								std::cout << e.what();
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setOption(Option & opt) {
 | 
				
			||||||
 | 
						const char * d1 = opt.find("-d");
 | 
				
			||||||
 | 
						if (d1 != nullptr)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							debug |= (strcmp(d1, "true") == 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						const char * d2 = opt.find("--debug");
 | 
				
			||||||
 | 
						if (d2 != nullptr)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							debug |= (strcmp(d2, "true") == 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						const char * t1 = opt.find("-m");
 | 
				
			||||||
 | 
						const char * t2 = opt.find("--mode");
 | 
				
			||||||
 | 
						if (t1 != nullptr)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							mode = t1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (t2 != nullptr)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							mode = t2;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t1 = opt.find("-o");
 | 
				
			||||||
 | 
						t2 = opt.find("--ouput");
 | 
				
			||||||
 | 
						if (t1 != nullptr)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							output_path = t1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (t2 != nullptr)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							output_path = t2;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										12
									
								
								LightScript/output.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								LightScript/output.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					sum = function(x,y)
 | 
				
			||||||
 | 
						local r = 0
 | 
				
			||||||
 | 
						local i = x
 | 
				
			||||||
 | 
						while y>=i do
 | 
				
			||||||
 | 
							r = r+i
 | 
				
			||||||
 | 
							i = i+1
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					a = sum(1,10)
 | 
				
			||||||
 | 
					print(a)
 | 
				
			||||||
							
								
								
									
										2
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								README.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					# LightScript
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										44
									
								
								replacePragmaOnce.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								replacePragmaOnce.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,44 @@
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import glob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def checkContent(lst,oper):
 | 
				
			||||||
 | 
					    if len(lst) < len(oper):
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					    for i,k in enumerate(oper):
 | 
				
			||||||
 | 
					        if lst[i].strip() != k:
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					    return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def replacePragmaOnce(name):
 | 
				
			||||||
 | 
					    hitContents=False
 | 
				
			||||||
 | 
					    with open(name,"r") as file:
 | 
				
			||||||
 | 
					        temp = open(name+".temp","w")
 | 
				
			||||||
 | 
					        nameheader = os.path.splitext(os.path.split(name)[-1])[0]
 | 
				
			||||||
 | 
					        for line in file:
 | 
				
			||||||
 | 
					            words = line.split()
 | 
				
			||||||
 | 
					            if hitContents:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					            elif checkContent(words,["#pragma","once"]):
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            elif line.startswith("#ifndef"):
 | 
				
			||||||
 | 
					                temp.close()
 | 
				
			||||||
 | 
					                os.remove(name+".temp")
 | 
				
			||||||
 | 
					                return None
 | 
				
			||||||
 | 
					            elif line.startswith("#include"):
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					            elif len(words)==0:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					            elif line.strip() == "":
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                temp.write("#ifndef LS_{}_H_\n".format(nameheader))
 | 
				
			||||||
 | 
					                temp.write("#define LS_{}_H_\n".format(nameheader))
 | 
				
			||||||
 | 
					                hitContents=True
 | 
				
			||||||
 | 
					            temp.writelines(line)
 | 
				
			||||||
 | 
					        temp.write("\n#endif")
 | 
				
			||||||
 | 
					        temp.close()
 | 
				
			||||||
 | 
					    os.remove(name)
 | 
				
			||||||
 | 
					    os.rename(name+".temp",name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for pth in glob.iglob('LightScript\\*.h'):
 | 
				
			||||||
 | 
					    replacePragmaOnce(pth)
 | 
				
			||||||
							
								
								
									
										5
									
								
								가상머신 필독.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								가상머신 필독.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					ByteCode.h 에 있는 code_t 에 일단 명령어 있음.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					가상머신 스택 항상 첫번째로 꺼낸 것이 왼쪽. 두번째가 오른쪽.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					64비트 전용임.
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue