├── .gitignore ├── Doc ├── BNF.txt ├── Implement.md ├── Style.md ├── TODO.md └── VM.md ├── LICENSE ├── Photon ├── AST │ ├── ArrayExpr.cs │ ├── AssignStmt.cs │ ├── BaseLit.cs │ ├── BasicLit.cs │ ├── BinaryExpr.cs │ ├── BlockStmt.cs │ ├── BreakStmt.cs │ ├── CallExpr.cs │ ├── ClassDeclare.cs │ ├── ConstDeclareStmt.cs │ ├── ContinueStmt.cs │ ├── DelegateDeclare.cs │ ├── ExprStmt.cs │ ├── FileNode.cs │ ├── ForRangeStmt.cs │ ├── ForStmt.cs │ ├── FuncDeclare.cs │ ├── FuncLit.cs │ ├── FuncType.cs │ ├── Ident.cs │ ├── IfStmt.cs │ ├── ImportStmt.cs │ ├── IncDecStmt.cs │ ├── IndexExpr.cs │ ├── LoopStmt.cs │ ├── MapExpr.cs │ ├── NewExpr.cs │ ├── Node.cs │ ├── ParenExpr.cs │ ├── ReturnStmt.cs │ ├── SelectorExpr.cs │ ├── Symbol.cs │ ├── UnaryExpr.cs │ ├── VarDeclareStmt.cs │ └── WhileStmt.cs ├── Accessor │ ├── Convertor.cs │ ├── DataAccessor.cs │ ├── RegisterAccessor.cs │ └── StackAccessor.cs ├── Build │ ├── CompileParameter.cs │ ├── Compiler.cs │ ├── ContentLoader.cs │ └── FileLoader.cs ├── Builtin │ ├── Array.cs │ ├── ArrayWrapper.cs │ ├── Map.cs │ └── MapWrapper.cs ├── CodeGen │ ├── Collector.cs │ ├── Generator.cs │ ├── Model.cs │ └── Printer.cs ├── Model │ ├── CodeFile.cs │ ├── Command.cs │ ├── ConstantSet.cs │ ├── DataStack.cs │ ├── Exception.cs │ ├── Executable.cs │ ├── NativeType.cs │ ├── ObjectName.cs │ ├── OpCode.cs │ ├── Package.cs │ ├── Register.cs │ ├── Scope.cs │ ├── ScopeManager.cs │ ├── SourceFile.cs │ └── Token.cs ├── Parser │ ├── LexerInit.cs │ ├── ParseDecl.cs │ ├── ParseExpr.cs │ ├── ParseStmt.cs │ └── Parser.cs ├── PhotonCore.csproj ├── PhotonLibrary.csproj ├── Properties │ └── AssemblyInfo.cs ├── Serializer │ └── TokenPosSerializer.cs ├── Utility │ ├── CodePrinter.cs │ └── Logger.cs ├── VM │ ├── Instruction.cs │ ├── InstructionFlow.cs │ ├── InstructionMath.cs │ ├── InstructionStore.cs │ ├── RuntimeFrame.cs │ ├── RuntimePackage.cs │ └── VMachine.cs └── Value │ ├── Value.cs │ ├── ValueArrayIterator.cs │ ├── ValueBool.cs │ ├── ValueClassType.cs │ ├── ValueClosure.cs │ ├── ValueFloat32.cs │ ├── ValueFloat64.cs │ ├── ValueFunc.cs │ ├── ValueInteger32.cs │ ├── ValueInteger64.cs │ ├── ValueIterator.cs │ ├── ValueMapIterator.cs │ ├── ValueNativeClassIns.cs │ ├── ValueNativeClassType.cs │ ├── ValueNativeFunc.cs │ ├── ValueNil.cs │ ├── ValueObject.cs │ ├── ValuePhoClassIns.cs │ ├── ValuePhoClassType.cs │ ├── ValuePhoFunc.cs │ └── ValueString.cs ├── PhotonCompiler ├── App.config ├── FlagSet.cs ├── PhotonCompiler.csproj ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── PhotonSystem.sln ├── PhotonToy ├── App.config ├── AssemblyLocation.cs ├── CodeList.cs ├── DebugBox.cs ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── PhotonToy.csproj ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── VMState.cs └── VarGuard.cs ├── README.md ├── ScreenShot └── debugger.png ├── TestCase ├── Array.pho ├── Class.pho ├── ClassInherit.pho ├── Closure.pho ├── ComplexClosure.pho ├── Constant.pho ├── DataStackBalance.pho ├── Delegate.pho ├── Execute.pho ├── ForLoop.pho ├── If.pho ├── Map.pho ├── Math.pho ├── MultiCall.pho ├── MyPackage │ ├── Add.pho │ ├── Entry.pho │ └── Sub.pho ├── NativeClass.pho ├── Package.pho ├── Scope.pho ├── SwapVar.pho ├── Test.pho └── WhileLoop.pho └── UnitTest ├── App.config ├── BasicTest.cs ├── ClassTest.cs ├── ContainerTest.cs ├── DataStackBalanceTest.cs ├── DataStackBalanceTestWrapper.cs ├── DelegateExecuteTest.cs ├── FlowTest.cs ├── FuncPackageTest.cs ├── NativeClassTest.cs ├── NativeClassWrapper.cs ├── Program.cs ├── TestBox.cs ├── TestCase.cs └── UnitTest.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.user 3 | /Photon/bin 4 | /Photon/obj 5 | /PhotonCompiler/bin 6 | /PhotonCompiler/obj 7 | /PhotonToy/bin 8 | /PhotonToy/obj 9 | /UnitTest/bin 10 | /UnitTest/obj -------------------------------------------------------------------------------- /Doc/BNF.txt: -------------------------------------------------------------------------------- 1 | PrimaryExpr = 2 | Operand | 3 | PrimaryExpr Selector | 4 | PrimaryExpr Index | 5 | PrimaryExpr Arguments . 6 | 7 | Selector = "." identifier . 8 | Index = "[" Expression "]" . 9 | Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" . 10 | 11 | Operand = Literal | OperandName | MethodExpr | "(" Expression ")" . 12 | Literal = BasicLit | CompositeLit | FunctionLit . 13 | BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit . 14 | OperandName = identifier . 15 | 16 | 17 | Expression = UnaryExpr | Expression binary_op UnaryExpr . 18 | UnaryExpr = PrimaryExpr | unary_op UnaryExpr . 19 | 20 | binary_op = "+" | "-" | "*" | "/" . 21 | rel_op = "==" | "!=" | "<" | "<=" | ">" | ">=" . 22 | 23 | unary_op = "+" | "-" | "!" . 24 | 25 | TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) . 26 | TypeSpec = identifier Type . 27 | 28 | VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) . 29 | VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) . 30 | 31 | 32 | Statement = 33 | Declaration | LabeledStmt | SimpleStmt | 34 | GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt | Block | IfStmt | ForStmt . 35 | 36 | Block = "{" StatementList "}" . 37 | StatementList = { Statement ";" } . 38 | 39 | FunctionDecl = "func" FunctionName ( Function | Signature ) . 40 | FunctionName = identifier . 41 | Function = Signature FunctionBody . 42 | FunctionBody = Block . 43 | 44 | 45 | 46 | FunctionType = "func" Signature . 47 | Signature = Parameters [ Result ] . 48 | Result = Parameters | Type . 49 | Parameters = "(" [ ParameterList [ "," ] ] ")" . 50 | ParameterList = ParameterDecl { "," ParameterDecl } . 51 | ParameterDecl = [ IdentifierList ] [ "..." ] Type . 52 | 53 | 54 | 55 | SimpleStmt = EmptyStmt | ExpressionStmt | Assignment | ShortVarDecl . 56 | 57 | 58 | IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] . 59 | 60 | 61 | ForStmt = "for" [ Condition | ForClause | RangeClause ] Block . 62 | Condition = Expression . 63 | 64 | ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] . 65 | InitStmt = SimpleStmt . 66 | PostStmt = SimpleStmt . 67 | 68 | RangeClause = "var" IdentifierList "in" Expression . 69 | 70 | 71 | ReturnStmt = "return" [ ExpressionList ] . -------------------------------------------------------------------------------- /Doc/Implement.md: -------------------------------------------------------------------------------- 1 | # 实现思路 2 | 3 | # 闭包 4 | 寄存器跟随函数体 5 | 6 | 函数调用时, 寄存器入栈保存 7 | 8 | 闭包引用整个寄存器体及索引 9 | 10 | 11 | # 寄存器分配规则 12 | 全局Scope分配在每个Package的全局寄存器 13 | 14 | 函数及以下的寄存器分配在Local寄存器上 15 | 16 | 每个函数体有记录最大的寄存器用量, 调用函数时, 寄存器保留调用函数的最大寄存器分配量 17 | 18 | for, while等函数体内的其他block scope的寄存器在函数体寄存器上分配, 同层覆盖 19 | 20 | # 返回值平衡 21 | 22 | 多级调用时, 根据上级AST关系, 可以判断出是否需要保留数据栈(不清空,不调整) 23 | 24 | 在碰到函数有接收返回值时, 父级为AssignStmt 25 | 26 | 计算接收返回值数量传给CALL 27 | 28 | 在运行期根据实际返回数量与接收数量进行栈平衡 29 | 30 | # Symbol与寄存器 31 | 32 | 函数声明, import名是Symbol, 但不分配寄存器 33 | 34 | 只有 变量, 形式参数的需要分配寄存器 35 | 36 | 37 | # 包寄存器和Local寄存器 38 | 39 | 每个包有全局有全局变量, 这些变量通过包寄存器进行内存分配和操作 40 | 41 | Local寄存器整个虚拟机只有1份, 所有包共用 42 | 43 | # Package 44 | 45 | 函数注册时, 将函数注册到方法区 46 | 47 | # 外部类注册 48 | 49 | 通过在方法特性标示区分在语言中的表现方法 50 | 51 | - 类静态函数->包函数 52 | 53 | - 类成员函数->类成员函数 54 | 55 | 函数入口只支持静态函数 56 | 57 | 类成员函数调用时, 第一个参数为self 58 | 59 | # 层次 60 | 一个Executable包含N个包, 1个ScopeManager 61 | 每个包有N个SourceFile和对应的FileNode 62 | FileNode间共享ScopeManager的Scope信息 63 | 64 | 65 | # init和main 66 | lua的每个文件的全局部分=init/main 67 | 68 | 但是init和main可以让代码的声明和运行清晰 69 | 70 | # hot patch与import 71 | lua可以做hot patch. 前一个文件跑着的时候, vm没释放时可以直接再次加载另外一个文件并混合前面的vm状态继续执行 72 | 73 | pho不支持这个特性. 但是可以做函数的edit & continue技术 -------------------------------------------------------------------------------- /Doc/Style.md: -------------------------------------------------------------------------------- 1 | # 多重赋值 2 | a, b, c = 1, "hello", e 3 | 4 | 5 | # 多返回值 6 | func foo( a, b, c) 7 | { 8 | return d, e, f 9 | } 10 | 11 | 数组 12 | a = { 13 | 1, 2, "hello" 14 | } 15 | 16 | 遍历器, target可以是 range()数值遍历器 17 | for k, v in target 18 | { 19 | 20 | } 21 | 22 | 23 | if expr { 24 | 25 | }else if expr{ 26 | 27 | } -------------------------------------------------------------------------------- /Doc/TODO.md: -------------------------------------------------------------------------------- 1 | # 重要, 紧急实现 2 | 3 | 字符串类库C#绑定 4 | 5 | 数学库C#绑定 6 | 7 | # 重要,不紧急实现 8 | 9 | 使用. import导入, 在列表中搜索可能用到的包 10 | 11 | 读取注释 12 | 13 | 格式化 14 | 15 | 包名使用路径名 16 | 17 | # 不重要,不紧急实现 18 | 19 | 调试版不输出scope 20 | 21 | Value的代码生成, 使用C#模板 22 | 23 | is, as 24 | 25 | 可变参数传递 26 | 27 | 尾递归实现 28 | 29 | 容器获取值时, 可以增加ok取值是否存在 30 | 31 | AST生成go源码生成exe 32 | 33 | # 优化 34 | 用不到的常量 35 | 36 | 没用的变量 37 | 38 | # 错误检查 39 | 40 | 派生包外的类, 循环父类引用检查 41 | 42 | import自己 -------------------------------------------------------------------------------- /Doc/VM.md: -------------------------------------------------------------------------------- 1 | # 虚拟机 2 | 3 | # 功能 4 | 寄存器 5 | 变量放置点, 由语法分析提前分配好 6 | 7 | 栈 8 | 动态交换, 函数体与函数体交换数据用 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (C) 2016 davyxu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Photon/AST/ArrayExpr.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using SharpLexer; 3 | 4 | namespace Photon 5 | { 6 | 7 | internal class ArrayExpr : Expr 8 | { 9 | List Values = new List(); 10 | 11 | public TokenPos LBracketPos; 12 | public TokenPos RBracketPos; 13 | 14 | public ArrayExpr(List values, TokenPos lbracket, TokenPos rbracket) 15 | { 16 | Values = values; 17 | LBracketPos = lbracket; 18 | RBracketPos = rbracket; 19 | 20 | BuildRelation(); 21 | } 22 | 23 | public override IEnumerable Child() 24 | { 25 | foreach (var v in Values) 26 | { 27 | yield return v; 28 | } 29 | } 30 | 31 | public override string ToString() 32 | { 33 | return "ArrayExpr"; 34 | } 35 | 36 | internal override void Compile(CompileParameter param) 37 | { 38 | var cmd = param.CS.Add(new Command(Opcode.NEW )).SetCodePos(LBracketPos).SetComment("Builtin.Array"); 39 | cmd.EntryName = new ObjectName("Builtin", "Array"); 40 | 41 | 42 | foreach (var v in Values) 43 | { 44 | v.Compile(param); 45 | } 46 | 47 | if (Values.Count > 0) 48 | { 49 | param.CS.Add(new Command(Opcode.SETA, Values.Count)).SetCodePos(LBracketPos); 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Photon/AST/AssignStmt.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | using System.Collections.Generic; 3 | 4 | namespace Photon 5 | { 6 | internal class AssignStmt : Stmt 7 | { 8 | public List LHS = new List(); 9 | public List RHS = new List(); 10 | 11 | public TokenPos AssignPos; 12 | public TokenType Op; 13 | 14 | public AssignStmt(List lhs, List rhs, TokenPos assignPos, TokenType op ) 15 | { 16 | LHS = lhs; 17 | RHS = rhs; 18 | Op = op; 19 | AssignPos = assignPos; 20 | 21 | BuildRelation(); 22 | } 23 | 24 | public AssignStmt(Expr lhs, Expr rhs, TokenPos assignPos, TokenType op) 25 | { 26 | AssignPos = assignPos; 27 | Op = op; 28 | LHS.Add(lhs); 29 | 30 | RHS.Add(rhs); 31 | 32 | BuildRelation(); 33 | } 34 | 35 | public override IEnumerable Child() 36 | { 37 | foreach (var e in LHS) 38 | { 39 | yield return e; 40 | } 41 | 42 | 43 | foreach (var e in RHS) 44 | { 45 | yield return e; 46 | } 47 | } 48 | 49 | public override string ToString() 50 | { 51 | return string.Format("AssignStmt {0}", Op ); 52 | } 53 | static Opcode Token2OpCode(TokenType tk) 54 | { 55 | switch (tk) 56 | { 57 | case TokenType.AddAssign: 58 | return Opcode.ADD; 59 | case TokenType.MulAssign: 60 | return Opcode.MUL; 61 | case TokenType.SubAssign: 62 | return Opcode.SUB; 63 | case TokenType.QuoAssign: 64 | return Opcode.DIV; 65 | } 66 | 67 | return Opcode.NOP; 68 | } 69 | 70 | 71 | internal override void Compile(CompileParameter param) 72 | { 73 | 74 | switch (Op) 75 | { 76 | case TokenType.Assign: 77 | { 78 | foreach (var e in RHS) 79 | { 80 | e.Compile(param.SetLHS(false)); 81 | } 82 | } 83 | break; 84 | case TokenType.AddAssign: 85 | case TokenType.SubAssign: 86 | case TokenType.MulAssign: 87 | case TokenType.QuoAssign: 88 | { 89 | // 这种操作只允许一个一个来 90 | if ( LHS.Count != 1 || RHS.Count != 1 ) 91 | { 92 | throw new CompileException("assignment require 1 operand", AssignPos); 93 | } 94 | 95 | LHS[0].Compile(param.SetLHS(false)); 96 | 97 | RHS[0].Compile(param.SetLHS(false)); 98 | 99 | param.CS.Add(new Command(Token2OpCode(Op))) 100 | .SetCodePos(AssignPos); 101 | 102 | 103 | } 104 | break; 105 | } 106 | 107 | foreach (var e in LHS) 108 | { 109 | e.Compile(param.SetLHS(true)); 110 | } 111 | } 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /Photon/AST/BaseLit.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | 3 | namespace Photon 4 | { 5 | internal class BaseLit : Expr 6 | { 7 | public TokenPos Pos; 8 | 9 | public BaseLit(TokenPos pos) 10 | { 11 | Pos = pos; 12 | } 13 | 14 | public override string ToString() 15 | { 16 | return string.Format("BaseLit {0}", Pos); 17 | } 18 | 19 | internal override void Compile(CompileParameter param) 20 | { 21 | 22 | } 23 | 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Photon/AST/BasicLit.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | using System; 3 | 4 | namespace Photon 5 | { 6 | internal class BasicLit : Expr 7 | { 8 | public TokenType Type; 9 | public string Value; 10 | public TokenPos Pos; 11 | 12 | int _constIndex; 13 | 14 | public BasicLit(string v, TokenType t, TokenPos pos ) 15 | { 16 | Value = v; 17 | Type = t; 18 | Pos = pos; 19 | } 20 | 21 | public override string ToString() 22 | { 23 | return string.Format("'{0}' ({1}) {2} C{3}", Value, Type, Pos, _constIndex); 24 | } 25 | 26 | internal override void Compile(CompileParameter param) 27 | { 28 | var c = Lit2Const( ); 29 | _constIndex = param.Constants.Add(c); 30 | 31 | param.CS.Add(new Command(Opcode.LOADK, _constIndex)).SetComment(c.ToString()).SetCodePos(Pos); 32 | } 33 | 34 | static bool IsFloat( string s ) 35 | { 36 | return s.IndexOf('.') != -1; 37 | } 38 | 39 | Value Lit2Const() 40 | { 41 | Value c = null; 42 | 43 | switch (Type) 44 | { 45 | case TokenType.Number: 46 | { 47 | if (IsFloat(Value)) 48 | { 49 | float v; 50 | if (!float.TryParse(Value, out v)) 51 | return null; 52 | 53 | c = new ValueFloat32(v); 54 | } 55 | else 56 | { 57 | Int32 v; 58 | if (!Int32.TryParse(Value, out v)) 59 | return null; 60 | 61 | c = new ValueInteger32(v); 62 | } 63 | 64 | } 65 | break; 66 | case TokenType.QuotedString: 67 | { 68 | c = new ValueString(Value); 69 | } 70 | break; 71 | default: 72 | break; 73 | } 74 | 75 | 76 | return c; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Photon/AST/BinaryExpr.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | using System.Collections.Generic; 3 | 4 | namespace Photon 5 | { 6 | internal class BinaryExpr : Expr 7 | { 8 | public Expr X; 9 | public TokenType Op; 10 | public Expr Y; 11 | public TokenPos OpPos; 12 | 13 | 14 | public BinaryExpr(Expr x, Expr y, TokenType t,TokenPos oppos ) 15 | { 16 | X = x; 17 | Y = y; 18 | Op = t; 19 | OpPos = oppos; 20 | 21 | BuildRelation(); 22 | } 23 | 24 | public override IEnumerable Child() 25 | { 26 | yield return X; 27 | 28 | yield return Y; 29 | } 30 | 31 | public override string ToString() 32 | { 33 | return string.Format("BinaryExpr {0}", Op.ToString()); 34 | } 35 | 36 | static Opcode Token2OpCode( TokenType tk ) 37 | { 38 | switch (tk) 39 | { 40 | case TokenType.Add: 41 | return Opcode.ADD; 42 | case TokenType.Mul: 43 | return Opcode.MUL; 44 | case TokenType.Sub: 45 | return Opcode.SUB; 46 | case TokenType.Div: 47 | return Opcode.DIV; 48 | case TokenType.GreatThan: 49 | return Opcode.GT; 50 | case TokenType.GreatEqual: 51 | return Opcode.GE; 52 | case TokenType.LessThan: 53 | return Opcode.LT; 54 | case TokenType.LessEqual: 55 | return Opcode.LE; 56 | case TokenType.Equal: 57 | return Opcode.EQ; 58 | case TokenType.NotEqual: 59 | return Opcode.NE; 60 | } 61 | 62 | return Opcode.NOP; 63 | } 64 | 65 | internal override void Compile(CompileParameter param) 66 | { 67 | X.Compile(param); 68 | Y.Compile(param); 69 | 70 | 71 | param.CS.Add(new Command(Token2OpCode(Op))) 72 | .SetCodePos(OpPos); 73 | 74 | } 75 | 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Photon/AST/BlockStmt.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | using System.Collections.Generic; 3 | 4 | namespace Photon 5 | { 6 | internal class BlockStmt : Stmt 7 | { 8 | public List Stmts = new List(); 9 | public TokenPos LBracePos; 10 | public TokenPos RBracePos; 11 | 12 | public BlockStmt(TokenPos lpos, TokenPos rpos) 13 | { 14 | 15 | } 16 | 17 | public BlockStmt(List list, TokenPos lpos, TokenPos rpos) 18 | { 19 | Stmts = list; 20 | LBracePos = lpos; 21 | RBracePos = rpos; 22 | 23 | BuildRelation(); 24 | } 25 | 26 | public override IEnumerable Child() 27 | { 28 | foreach (var s in Stmts) 29 | { 30 | yield return s; 31 | } 32 | } 33 | 34 | public override string ToString() 35 | { 36 | return "BlockStmt"; 37 | } 38 | 39 | internal override void Compile(CompileParameter param) 40 | { 41 | foreach (var b in Stmts) 42 | { 43 | b.Compile(param.SetLHS(false)); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Photon/AST/BreakStmt.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | 3 | namespace Photon 4 | { 5 | internal class BreakStmt : Stmt 6 | { 7 | public TokenPos Pos; 8 | 9 | public BreakStmt(TokenPos pos) 10 | { 11 | Pos = pos; 12 | } 13 | 14 | public override string ToString() 15 | { 16 | return string.Format("BreakStmt {0}", Pos); 17 | } 18 | 19 | LoopStmt nearestLoopStmt; 20 | 21 | Command cmd; 22 | 23 | internal override void Resolve(CompileParameter param) 24 | { 25 | cmd.DataA = nearestLoopStmt.LoopEndCmdID; 26 | } 27 | 28 | internal override void Compile(CompileParameter param) 29 | { 30 | nearestLoopStmt = LoopStmt.FindLoop(this); 31 | if ( nearestLoopStmt == null ) 32 | { 33 | throw new CompileException("'break' should in loop statement", Pos); 34 | } 35 | 36 | param.NextPassToResolve(this); 37 | 38 | cmd = param.CS.Add(new Command(Opcode.JMP, -1)) 39 | .SetCodePos(Pos).SetComment("break"); 40 | } 41 | 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Photon/AST/CallExpr.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using SharpLexer; 3 | 4 | namespace Photon 5 | { 6 | 7 | internal class CallExpr : Expr 8 | { 9 | public Expr Func; 10 | public List Args; 11 | public Scope S; 12 | 13 | public TokenPos LParen; 14 | public TokenPos RParen; 15 | 16 | public CallExpr(Expr f, List args, Scope s, TokenPos lparen, TokenPos rparen) 17 | { 18 | Func = f; 19 | Args = args; 20 | S = s; 21 | LParen = lparen; 22 | RParen = rparen; 23 | 24 | BuildRelation(); 25 | } 26 | 27 | public override IEnumerable Child() 28 | { 29 | yield return Func; 30 | 31 | foreach( var e in Args) 32 | { 33 | yield return e; 34 | } 35 | } 36 | 37 | public override string ToString() 38 | { 39 | return "CallExpr"; 40 | } 41 | 42 | int GetReceiverCount( ) 43 | { 44 | // 单独的一句时, 需要平衡数据栈 45 | var assign = Parent as AssignStmt; 46 | if (assign != null ) 47 | { 48 | return assign.LHS.Count; 49 | } 50 | 51 | // 没有任何接收者 52 | if ( Parent is ExprStmt ) 53 | { 54 | return 0; 55 | } 56 | 57 | // 无需处理返回值 58 | if ( Parent is ReturnStmt ) 59 | { 60 | return -1; 61 | } 62 | 63 | 64 | return 1; 65 | } 66 | 67 | internal override void Compile(CompileParameter param) 68 | { 69 | int SelfCount = 0; 70 | 71 | 72 | // 尝试放入self作为第一个参数 73 | var selector = Func as SelectorExpr; 74 | if (selector != null) 75 | { 76 | SelfCount += selector.CompileSelfParameter(param.SetLHS(false)); 77 | } 78 | 79 | 80 | // 先放参数 81 | foreach (var arg in Args) 82 | { 83 | arg.Compile(param.SetLHS(false)); 84 | } 85 | 86 | // 本包及动态闭包调用 87 | Func.Compile(param.SetLHS(false)); 88 | 89 | param.CS.Add(new Command(Opcode.CALL, Args.Count + SelfCount, GetReceiverCount())).SetCodePos(LParen); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Photon/AST/ClassDeclare.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | 8 | internal class ClassDeclare : Stmt 9 | { 10 | public TokenPos ClassPos; 11 | 12 | public Ident Name; 13 | 14 | public TokenPos ColonPos; 15 | 16 | public Ident ParentName; 17 | 18 | public Scope ScopeInfo; 19 | 20 | public List Member; 21 | 22 | ValuePhoClassType _class; 23 | 24 | public ClassDeclare(Ident name, Ident parentName, Scope s, List member, TokenPos classpos) 25 | { 26 | Name = name; 27 | ParentName = parentName; 28 | ClassPos = classpos; 29 | Member = member; 30 | ScopeInfo = s; 31 | 32 | BuildRelation(); 33 | } 34 | 35 | public override IEnumerable Child() 36 | { 37 | foreach (var s in Member) 38 | { 39 | yield return s; 40 | } 41 | } 42 | 43 | public override string ToString() 44 | { 45 | return "ClassStmt"; 46 | } 47 | 48 | bool ResolveParent(CompileParameter param, int pass ) 49 | { 50 | var parent = param.Exe.GetClassTypeByName( new ObjectName(param.Pkg.Name, ParentName.Name)) as ValuePhoClassType; 51 | if (parent != null) 52 | { 53 | _class.ParentID = parent.ID; 54 | _class.Parent = param.Exe.FindClassByPersistantID(parent.ID); 55 | 56 | return true; 57 | } 58 | 59 | if ( pass > 1 ) 60 | { 61 | throw new CompileException("unknown parent class: " + ParentName.Name, ColonPos); 62 | } 63 | 64 | return false; 65 | } 66 | 67 | internal override void Resolve(CompileParameter param) 68 | { 69 | ResolveParent(param, 2); 70 | } 71 | 72 | 73 | internal override void Compile(CompileParameter param) 74 | { 75 | _class = new ValuePhoClassType(param.Pkg, new ObjectName(param.Pkg.Name, Name.Name)); 76 | 77 | _class.ID = param.Exe.GenPersistantID(); 78 | 79 | foreach( var m in Member ) 80 | { 81 | var ki = param.Constants.AddString(m.Name); 82 | 83 | _class.AddMemeber(ki, m.Name); 84 | } 85 | 86 | param.Exe.AddClassType(_class); 87 | 88 | 89 | if (ParentName != null && !ResolveParent(param, 1)) 90 | { 91 | param.NextPassToResolve(this); 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Photon/AST/ConstDeclareStmt.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | // var XXX 纯变量定义 8 | internal class ConstDeclareStmt : Stmt 9 | { 10 | public Ident Name; 11 | 12 | public Expr Value; 13 | 14 | public TokenPos ConstPos; 15 | 16 | public ConstDeclareStmt(Ident name, Expr value, TokenPos defpos) 17 | { 18 | Name = name; 19 | ConstPos = defpos; 20 | Value = value; 21 | 22 | BuildRelation(); 23 | } 24 | 25 | public override IEnumerable Child() 26 | { 27 | yield return Name; 28 | 29 | yield return Value; 30 | } 31 | 32 | public override string ToString() 33 | { 34 | return "ConstDeclareStmt"; 35 | } 36 | 37 | internal override void Compile(CompileParameter param) 38 | { 39 | var newset = new ValuePhoFunc(new ObjectName("fakepkg", "constcalc"), ConstPos, 0, null); 40 | 41 | 42 | var funcParam = param.SetCmdSet(newset); 43 | 44 | // 用空的常量表 45 | funcParam.Constants = new ConstantSet(); 46 | 47 | // 生成表达式计算指令 48 | Value.Compile(funcParam); 49 | 50 | try 51 | { 52 | var eval = VMachine.MiniExec(newset, funcParam.Constants); 53 | 54 | var ci = param.Constants.Add(eval); 55 | Name.Symbol.RegIndex = ci; 56 | } 57 | catch(RuntimeException) 58 | { 59 | throw new CompileException("Expect constant value to caculate value", ConstPos); 60 | } 61 | 62 | 63 | 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Photon/AST/ContinueStmt.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | 3 | namespace Photon 4 | { 5 | internal class ContinueStmt : Stmt 6 | { 7 | public TokenPos Pos; 8 | 9 | public ContinueStmt(TokenPos pos) 10 | { 11 | Pos = pos; 12 | } 13 | 14 | public override string ToString() 15 | { 16 | return string.Format("ContinueStmt {0}", Pos); 17 | } 18 | 19 | LoopStmt nearestForStmt; 20 | 21 | Command cmd; 22 | 23 | internal override void Resolve(CompileParameter param) 24 | { 25 | cmd.DataA = nearestForStmt.LoopBeginCmdID; 26 | } 27 | 28 | internal override void Compile(CompileParameter param) 29 | { 30 | nearestForStmt = LoopStmt.FindLoop(this); 31 | if ( nearestForStmt == null ) 32 | { 33 | throw new CompileException("'continue' should in for statement", Pos); 34 | } 35 | 36 | param.NextPassToResolve(this); 37 | 38 | cmd = param.CS.Add(new Command(Opcode.JMP, -1)) 39 | .SetCodePos(Pos).SetComment("continue"); 40 | } 41 | 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Photon/AST/DelegateDeclare.cs: -------------------------------------------------------------------------------- 1 |  2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Photon 6 | { 7 | // 函数前置声明 8 | internal class DelegateDeclare : Stmt 9 | { 10 | public Ident Name; 11 | 12 | public FuncType TypeInfo; 13 | 14 | public DelegateDeclare(Ident name, FuncType ft ) 15 | { 16 | Name = name; 17 | TypeInfo = ft; 18 | 19 | BuildRelation(); 20 | } 21 | 22 | public override string ToString() 23 | { 24 | return string.Format("DelegateDeclare {0} {1}", Name.Name, TypeInfo.ToString()); 25 | } 26 | 27 | public override IEnumerable Child() 28 | { 29 | yield break; 30 | } 31 | 32 | 33 | internal override void Compile(CompileParameter param) 34 | { 35 | param.Exe.AddFunc(new ValueNativeFunc( new ObjectName( param.Pkg.Name, Name.Name ) ) ); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Photon/AST/ExprStmt.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | using System.Collections.Generic; 3 | 4 | namespace Photon 5 | { 6 | // 单独的一句表达式(例如: 纯函数调用) 7 | internal class ExprStmt : Stmt 8 | { 9 | public List X; 10 | public TokenPos DefPos; 11 | 12 | public ExprStmt(List x, TokenPos defpos ) 13 | { 14 | X = x; 15 | DefPos = defpos; 16 | 17 | BuildRelation(); 18 | } 19 | 20 | public override IEnumerable Child() 21 | { 22 | foreach (var e in X) 23 | { 24 | yield return e; 25 | } 26 | } 27 | 28 | public override string ToString() 29 | { 30 | return "ExprStmt"; 31 | } 32 | 33 | internal override void Compile(CompileParameter param) 34 | { 35 | 36 | foreach (var b in X) 37 | { 38 | // ExprStmt下不出现CallExpr可能是-foo(); 1+foo() 这种奇葩写法 39 | // 返回值无法被回收, 所以直接报错 40 | if (!(b is CallExpr)) 41 | { 42 | throw new CompileException("invalid expression statement", DefPos); 43 | } 44 | 45 | b.Compile(param.SetLHS(false)); 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Photon/AST/FileNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Photon 4 | { 5 | internal class FileNode : Node 6 | { 7 | public List Imports = new List(); 8 | 9 | public BlockStmt Block; 10 | 11 | public FileNode(BlockStmt block, List imports) 12 | { 13 | Block = block; 14 | Imports = imports; 15 | 16 | BuildRelation(); 17 | } 18 | 19 | public override IEnumerable Child() 20 | { 21 | foreach (var im in Imports) 22 | { 23 | yield return im; 24 | } 25 | 26 | yield return Block; 27 | 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return "File"; 33 | } 34 | 35 | internal override void Compile(CompileParameter param) 36 | { 37 | foreach (var im in Imports) 38 | { 39 | im.Compile(param); 40 | } 41 | 42 | Block.Compile(param); 43 | 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Photon/AST/ForRangeStmt.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | // for k, v in x 8 | internal class ForRangeStmt : LoopStmt 9 | { 10 | public Ident Key; 11 | 12 | public Ident Value; 13 | 14 | public Expr X; 15 | 16 | public TokenPos InPos; 17 | 18 | public ForRangeStmt(Ident key, Ident value, Expr x, TokenPos inpos, TokenPos defpos, Scope s, BlockStmt body) 19 | { 20 | Key = key; 21 | Value = value; 22 | X = x; 23 | InPos = inpos; 24 | Pos = defpos; 25 | ScopeInfo = s; 26 | Body = body; 27 | 28 | BuildRelation(); 29 | } 30 | 31 | 32 | public override string ToString() 33 | { 34 | return "ForRangeStmt"; 35 | } 36 | 37 | public override IEnumerable Child() 38 | { 39 | if (Key != null) 40 | { 41 | yield return Key; 42 | } 43 | 44 | if (Value != null) 45 | { 46 | yield return Value; 47 | } 48 | 49 | 50 | yield return X; 51 | 52 | yield return Body; 53 | } 54 | 55 | Ident DelcareIteratorVar( ) 56 | { 57 | var iter = new Ident(new Token(Pos, null, "@Iterator")); 58 | iter.BaseScope = ScopeInfo; 59 | iter.Symbol = new Symbol(); 60 | iter.Symbol.Name = iter.Name; 61 | iter.Symbol.Decl = this; 62 | iter.Symbol.DefinePos = Pos; 63 | iter.Symbol.Usage = SymbolUsage.Variable; 64 | ScopeInfo.Insert(iter.Symbol); 65 | 66 | return iter; 67 | } 68 | // 手动分配1个iterator变量 69 | // k, v, iter = ITER( x, iter ) 70 | // 71 | internal override void Compile(CompileParameter param) 72 | { 73 | var iterVar = DelcareIteratorVar(); 74 | 75 | param.CS.Add(new Command(Opcode.INITR, iterVar.Symbol.RegIndex)) 76 | .SetCodePos(Pos) 77 | .SetComment("init iterator"); 78 | 79 | 80 | LoopBeginCmdID = param.CS.CurrCmdID; 81 | 82 | X.Compile(param); 83 | 84 | iterVar.Compile(param); 85 | 86 | var jmpCmd = param.CS.Add(new Command(Opcode.VISIT, -1 )) 87 | .SetCodePos(Pos) 88 | .SetComment("for kv"); 89 | 90 | Key.Compile(param.SetLHS(true)); 91 | 92 | Value.Compile(param.SetLHS(true)); 93 | 94 | iterVar.Compile(param.SetLHS(true)); 95 | 96 | Body.Compile(param.SetLHS(false)); 97 | 98 | 99 | param.CS.Add(new Command(Opcode.JMP, LoopBeginCmdID)) 100 | .SetCodePos(Pos) 101 | .SetComment("for kv loop"); 102 | 103 | // 循环结束 104 | LoopEndCmdID = param.CS.CurrCmdID; 105 | jmpCmd.DataA = LoopEndCmdID; 106 | } 107 | 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Photon/AST/ForStmt.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | internal class ForStmt : LoopStmt 8 | { 9 | public Stmt Init; 10 | 11 | public Expr Condition; 12 | 13 | public Stmt Post; 14 | 15 | public ForStmt(Stmt init, Expr con, Stmt post, TokenPos defpos, Scope s, BlockStmt body) 16 | { 17 | Condition = con; 18 | Init = init; 19 | Post = post; 20 | Pos = defpos; 21 | ScopeInfo = s; 22 | Body = body; 23 | 24 | BuildRelation(); 25 | } 26 | 27 | 28 | public override string ToString() 29 | { 30 | return "ForStmt"; 31 | } 32 | 33 | public override IEnumerable Child() 34 | { 35 | if (Init != null) 36 | { 37 | yield return Init; 38 | } 39 | 40 | if (Condition != null) 41 | { 42 | yield return Condition; 43 | } 44 | 45 | if (Post != null) 46 | { 47 | yield return Post; 48 | } 49 | 50 | yield return Body; 51 | } 52 | 53 | internal override void Compile(CompileParameter param) 54 | { 55 | if (Init != null) 56 | { 57 | Init.Compile(param.SetLHS(false)); 58 | } 59 | 60 | LoopBeginCmdID = param.CS.CurrCmdID; 61 | 62 | Command jzCmd = null; 63 | 64 | if (Condition != null) 65 | { 66 | Condition.Compile(param.SetLHS(false)); 67 | 68 | jzCmd = param.CS.Add(new Command(Opcode.JZ, -1)) 69 | .SetCodePos(Pos) 70 | .SetComment("for condition"); 71 | } 72 | 73 | Body.Compile(param.SetLHS(false)); 74 | 75 | if (Post != null) 76 | { 77 | Post.Compile(param.SetLHS(false)); 78 | } 79 | 80 | 81 | param.CS.Add(new Command(Opcode.JMP, LoopBeginCmdID)) 82 | .SetCodePos(Pos) 83 | .SetComment("for loop"); 84 | 85 | // false body跳入 86 | if (jzCmd != null) 87 | { 88 | jzCmd.DataA = param.CS.CurrCmdID; 89 | } 90 | 91 | LoopEndCmdID = param.CS.CurrCmdID; 92 | } 93 | 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Photon/AST/FuncDeclare.cs: -------------------------------------------------------------------------------- 1 |  2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Photon 6 | { 7 | internal class FuncDeclare : Stmt 8 | { 9 | public Ident Name; 10 | 11 | public FuncType TypeInfo; 12 | 13 | public BlockStmt Body; 14 | 15 | public Ident ClassName; 16 | 17 | ValueFunc _proc; 18 | 19 | internal ValuePhoFunc bodyCS; 20 | 21 | public FuncDeclare(Ident name, FuncType ft ) 22 | { 23 | Name = name; 24 | 25 | TypeInfo = ft; 26 | } 27 | 28 | 29 | public override string ToString() 30 | { 31 | return string.Format("FuncDeclare '{0}' {1}", Name.Name, TypeInfo.ToString()); 32 | } 33 | 34 | public override IEnumerable Child() 35 | { 36 | return Body.Child(); 37 | } 38 | 39 | internal override void Resolve(CompileParameter param) 40 | { 41 | var c = param.Exe.GetClassTypeByName(new ObjectName(param.Pkg.Name, ClassName.Name)); 42 | if (c == null) 43 | { 44 | throw new CompileException("unknown class name: " + ClassName.Name, TypeInfo.FuncPos); 45 | } 46 | else 47 | { 48 | int nameKey = param.Constants.AddString(Name.Name); 49 | var cc = c as ValuePhoClassType; 50 | cc.AddMethod(nameKey, _proc); 51 | } 52 | } 53 | 54 | 55 | internal override void Compile(CompileParameter param) 56 | { 57 | ObjectName on = new ObjectName(param.Pkg.Name, Name.Name); 58 | 59 | if (ClassName != null) 60 | { 61 | // 成员函数必须有至少1个参数(self) 62 | if (TypeInfo.Params.Count < 1) 63 | { 64 | throw new CompileException("Expect 'self' in method", TypeInfo.FuncPos); 65 | } 66 | 67 | on.ClassName = ClassName.Name; 68 | } 69 | 70 | var newset = new ValuePhoFunc(on, TypeInfo.FuncPos, TypeInfo.ScopeInfo.CalcUsedReg(), TypeInfo.ScopeInfo); 71 | bodyCS = newset; 72 | 73 | _proc = param.Exe.AddFunc(newset); 74 | 75 | if ( ClassName != null ) 76 | { 77 | param.NextPassToResolve(this); 78 | } 79 | 80 | var funcParam = param.SetLHS(false).SetCmdSet(newset); 81 | Body.Compile(funcParam); 82 | 83 | TypeInfo.GenDefaultRet(Body.Child(), funcParam); 84 | 85 | newset.InputValueCount = TypeInfo.Params.Count; 86 | 87 | newset.OutputValueCount = FuncType.CalcReturnValueCount(Body.Child()); 88 | 89 | 90 | 91 | } 92 | 93 | 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Photon/AST/FuncType.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Photon 7 | { 8 | internal class FuncType 9 | { 10 | public TokenPos FuncPos; 11 | 12 | public List Params; 13 | 14 | public Scope ScopeInfo; 15 | 16 | public FuncType( TokenPos funcPos, List param, Scope s ) 17 | { 18 | FuncPos = funcPos; 19 | Params = param; 20 | ScopeInfo = s; 21 | } 22 | 23 | public override string ToString() 24 | { 25 | StringBuilder sb = new StringBuilder(); 26 | 27 | int index = 0; 28 | foreach (var i in Params) 29 | { 30 | if (index > 0) 31 | { 32 | sb.Append(", "); 33 | } 34 | 35 | sb.Append(i.Name.ToString()); 36 | 37 | 38 | index++; 39 | } 40 | 41 | return sb.ToString(); 42 | } 43 | 44 | internal static int CalcReturnValueCount(IEnumerable nodeEnum) 45 | { 46 | foreach (var c in nodeEnum) 47 | { 48 | var retStmt = c as ReturnStmt; 49 | if (retStmt == null) 50 | { 51 | continue; 52 | } 53 | 54 | return retStmt.Results.Count; 55 | } 56 | 57 | return 0; 58 | } 59 | 60 | 61 | internal void GenDefaultRet(IEnumerable nodeEnum, CompileParameter param) 62 | { 63 | bool anyCode = false; 64 | foreach (var c in nodeEnum) 65 | { 66 | anyCode = true; 67 | 68 | var retStmt = c as ReturnStmt; 69 | if (retStmt != null) 70 | { 71 | return; 72 | } 73 | } 74 | 75 | var cmd = param.CS.Add(new Command(Opcode.RET)); 76 | 77 | // 有任意代码, 且有指令, 用最后的代码位置生成RET的代码位置 78 | if (anyCode && param.CS.CurrCmdID > 1) 79 | { 80 | cmd.SetCodePos(param.CS.Commands[param.CS.CurrCmdID - 2].CodePos); 81 | } 82 | else 83 | { 84 | // 使用函数定义地方做exit位置 85 | cmd.SetCodePos(FuncPos); 86 | } 87 | } 88 | 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Photon/AST/IfStmt.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | internal class IfStmt : Stmt 8 | { 9 | public Expr Condition; 10 | 11 | public BlockStmt Body; 12 | 13 | public BlockStmt ElseBody; 14 | 15 | public TokenPos IfPos; 16 | 17 | public IfStmt(Expr con, BlockStmt body, BlockStmt elsebody, TokenPos ifpos) 18 | { 19 | Condition = con; 20 | Body = body; 21 | ElseBody = elsebody; 22 | IfPos = ifpos; 23 | 24 | BuildRelation(); 25 | } 26 | 27 | 28 | public override string ToString() 29 | { 30 | return "IfStmt"; 31 | } 32 | 33 | public override IEnumerable Child() 34 | { 35 | yield return Condition; 36 | 37 | yield return Body; 38 | 39 | yield return ElseBody; 40 | } 41 | 42 | internal override void Compile(CompileParameter param) 43 | { 44 | Condition.Compile(param.SetLHS(false)); 45 | 46 | var jnzCmd = param.CS.Add(new Command(Opcode.JZ, 0)) 47 | .SetCodePos(IfPos) 48 | .SetComment("if condition false"); 49 | 50 | Body.Compile(param.SetLHS(false)); 51 | 52 | var jmpCmd = param.CS.Add(new Command(Opcode.JMP, 0)) 53 | .SetCodePos(IfPos) 54 | .SetComment("if condition true"); 55 | 56 | // false body跳入 57 | jnzCmd.DataA = param.CS.CurrCmdID; 58 | 59 | if (ElseBody.Stmts.Count > 0) 60 | { 61 | ElseBody.Compile(param.SetLHS(false)); 62 | } 63 | 64 | // true body执行完毕跳出 65 | jmpCmd.DataA = param.CS.CurrCmdID; 66 | } 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Photon/AST/ImportStmt.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | class ImportStmt : Stmt 8 | { 9 | public BasicLit Source; 10 | public TokenPos ImportPos; 11 | 12 | public ImportStmt(BasicLit src, TokenPos pos) 13 | { 14 | Source = src; 15 | ImportPos = pos; 16 | 17 | BuildRelation(); 18 | } 19 | 20 | public override IEnumerable Child() 21 | { 22 | yield return Source; 23 | } 24 | 25 | public override string ToString() 26 | { 27 | return "ImportStmt"; 28 | } 29 | 30 | internal override void Compile(CompileParameter param) 31 | { 32 | 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Photon/AST/IncDecStmt.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | using System.Collections.Generic; 3 | 4 | namespace Photon 5 | { 6 | internal class IncDecStmt : Stmt 7 | { 8 | public TokenType Op; 9 | public Expr X; 10 | 11 | public TokenPos OpPos; 12 | 13 | public IncDecStmt(Expr x, TokenType t, TokenPos oppos) 14 | { 15 | X = x; 16 | Op = t; 17 | OpPos = oppos; 18 | 19 | BuildRelation(); 20 | } 21 | 22 | public override IEnumerable Child() 23 | { 24 | yield return X; 25 | } 26 | 27 | public override string ToString() 28 | { 29 | return string.Format("IncDecStmt {0}", Op.ToString()); 30 | } 31 | 32 | static Opcode Token2OpCode(TokenType tk) 33 | { 34 | switch (tk) 35 | { 36 | case TokenType.Increase: 37 | return Opcode.INC; 38 | case TokenType.Decrease: 39 | return Opcode.DEC; 40 | } 41 | 42 | return Opcode.NOP; 43 | } 44 | 45 | internal override void Compile(CompileParameter param) 46 | { 47 | var opcode = Token2OpCode(Op); 48 | 49 | if (opcode != Opcode.NOP) 50 | { 51 | X.Compile(param); 52 | } 53 | else 54 | { 55 | throw new CompileException("Unknown unary operator", OpPos); 56 | } 57 | 58 | param.CS.Add(new Command(opcode)).SetCodePos(OpPos); 59 | 60 | // 赋值 61 | X.Compile(param.SetLHS(true)); 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /Photon/AST/IndexExpr.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | // a.b x=a index=b 8 | 9 | internal class IndexExpr : Expr 10 | { 11 | public Expr X; 12 | public Expr Index; 13 | 14 | public TokenPos LBrackPos; 15 | public TokenPos RBrackPos; 16 | 17 | public IndexExpr(Expr x, Expr index, TokenPos lpos, TokenPos rpos) 18 | { 19 | X = x; 20 | Index = index; 21 | LBrackPos = lpos; 22 | RBrackPos = rpos; 23 | 24 | BuildRelation(); 25 | } 26 | 27 | public override IEnumerable Child() 28 | { 29 | yield return X; 30 | 31 | yield return Index; 32 | } 33 | 34 | public override string ToString() 35 | { 36 | return "IndexExpr"; 37 | } 38 | 39 | internal override void Compile(CompileParameter param) 40 | { 41 | Index.Compile(param.SetLHS(false)); 42 | 43 | X.Compile(param.SetLHS(false)); 44 | 45 | if ( param.LHS ) 46 | { 47 | // 赋值 48 | param.CS.Add(new Command(Opcode.SETI)).SetCodePos(LBrackPos); 49 | } 50 | else 51 | { 52 | // 取值 53 | param.CS.Add(new Command(Opcode.LOADI)).SetCodePos(LBrackPos); 54 | } 55 | 56 | 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Photon/AST/LoopStmt.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | 3 | namespace Photon 4 | { 5 | class LoopStmt : Stmt 6 | { 7 | public TokenPos Pos; 8 | 9 | public Scope ScopeInfo; // for 有独立的作用域, 在body block的外层 10 | 11 | public BlockStmt Body; 12 | 13 | internal int LoopBeginCmdID = -1; 14 | 15 | internal int LoopEndCmdID = -1; 16 | 17 | internal static LoopStmt FindLoop(Node start) 18 | { 19 | Node n = start; 20 | while (n != null) 21 | { 22 | if (n is LoopStmt) 23 | return n as LoopStmt; 24 | 25 | n = n.Parent; 26 | } 27 | 28 | return null; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Photon/AST/MapExpr.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using SharpLexer; 3 | 4 | namespace Photon 5 | { 6 | 7 | internal class MapExpr : Expr 8 | { 9 | Dictionary Values = new Dictionary(); 10 | 11 | public TokenPos LBracePos; 12 | public TokenPos RBracePos; 13 | 14 | public MapExpr(Dictionary values, TokenPos lbrace, TokenPos rbrace) 15 | { 16 | Values = values; 17 | LBracePos = lbrace; 18 | RBracePos = rbrace; 19 | 20 | BuildRelation(); 21 | } 22 | 23 | public override IEnumerable Child() 24 | { 25 | foreach (var v in Values) 26 | { 27 | yield return v.Key; 28 | yield return v.Value; 29 | } 30 | } 31 | 32 | public override string ToString() 33 | { 34 | return "MapExpr"; 35 | } 36 | 37 | internal override void Compile(CompileParameter param) 38 | { 39 | 40 | var cmd = param.CS.Add(new Command(Opcode.NEW )).SetCodePos(LBracePos).SetComment("Builtin.Map"); 41 | cmd.EntryName = new ObjectName("Builtin", "Map"); 42 | 43 | 44 | var kvParam = param.SetLHS(false); 45 | foreach (var kv in Values) 46 | { 47 | kv.Key.Compile(kvParam); 48 | kv.Value.Compile(kvParam); 49 | } 50 | 51 | param.CS.Add(new Command(Opcode.SETD, Values.Count)).SetCodePos(LBracePos); 52 | 53 | 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Photon/AST/NewExpr.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using SharpLexer; 3 | 4 | namespace Photon 5 | { 6 | 7 | internal class NewExpr : Expr 8 | { 9 | public Ident ClassName; 10 | 11 | public Ident PackageName; 12 | 13 | public TokenPos NewPos; 14 | 15 | Command _cmd; 16 | 17 | public NewExpr(Ident className, Ident pkgName, TokenPos newpos ) 18 | { 19 | NewPos = newpos; 20 | ClassName = className; 21 | PackageName = pkgName; 22 | 23 | BuildRelation(); 24 | } 25 | 26 | public override IEnumerable Child() 27 | { 28 | yield return ClassName; 29 | 30 | if (PackageName != null) 31 | { 32 | yield return PackageName; 33 | } 34 | } 35 | 36 | public override string ToString() 37 | { 38 | return "NewExpr"; 39 | } 40 | 41 | 42 | internal override void Compile(CompileParameter param) 43 | { 44 | ObjectName on = ObjectName.Empty; 45 | on.EntryName = ClassName.Name; 46 | if (PackageName != null) 47 | { 48 | on.PackageName = PackageName.Name; 49 | } 50 | else 51 | { 52 | on.PackageName = param.Pkg.Name; 53 | } 54 | 55 | _cmd = param.CS.Add(new Command(Opcode.NEW)) 56 | .SetCodePos(NewPos); 57 | 58 | _cmd.EntryName = on; 59 | 60 | _cmd.SetComment(on.ToString()); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Photon/AST/Node.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System; 3 | using SharpLexer; 4 | 5 | namespace Photon 6 | { 7 | internal class Node 8 | { 9 | public Node Parent; 10 | 11 | public virtual IEnumerable Child() 12 | { 13 | yield break; 14 | } 15 | 16 | internal virtual void Compile(CompileParameter param) 17 | { 18 | throw new Exception("'Compile' not implement: " + this.ToString()); 19 | } 20 | 21 | internal virtual void Resolve(CompileParameter param) 22 | { 23 | 24 | } 25 | 26 | public void BuildRelation( ) 27 | { 28 | foreach( var c in Child() ) 29 | { 30 | c.Parent = this; 31 | } 32 | } 33 | } 34 | 35 | 36 | internal class Stmt : Node 37 | { 38 | 39 | } 40 | 41 | internal class BadStmt : Stmt 42 | { 43 | internal override void Compile(CompileParameter param) 44 | { 45 | throw new CompileException("Bad statement", TokenPos.Invalid); 46 | } 47 | } 48 | 49 | internal class Expr : Node 50 | { 51 | 52 | } 53 | 54 | internal class BadExpr : Expr 55 | { 56 | 57 | } 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /Photon/AST/ParenExpr.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | internal class ParenExpr : Expr 8 | { 9 | public TokenPos LParenPos; 10 | public Expr X; 11 | public TokenPos RParenPos; 12 | 13 | 14 | public ParenExpr(Expr x, TokenPos lparen, TokenPos rparen) 15 | { 16 | X = x; 17 | LParenPos = lparen; 18 | RParenPos = rparen; 19 | 20 | BuildRelation(); 21 | } 22 | 23 | public override IEnumerable Child() 24 | { 25 | yield return X; 26 | } 27 | 28 | public override string ToString() 29 | { 30 | return string.Format("ParenExpr"); 31 | } 32 | 33 | 34 | internal override void Compile(CompileParameter param) 35 | { 36 | X.Compile(param); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Photon/AST/ReturnStmt.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | 8 | internal class ReturnStmt : Stmt 9 | { 10 | public List Results = new List(); 11 | public TokenPos RetPos; 12 | 13 | public ReturnStmt(List list, TokenPos retpos) 14 | { 15 | Results = list; 16 | RetPos = retpos; 17 | 18 | BuildRelation(); 19 | } 20 | 21 | public override IEnumerable Child() 22 | { 23 | foreach (var s in Results) 24 | { 25 | yield return s; 26 | } 27 | } 28 | 29 | public override string ToString() 30 | { 31 | return "ReturnStmt"; 32 | } 33 | 34 | internal override void Compile(CompileParameter param) 35 | { 36 | for (int i = Results.Count - 1; i >= 0;i-- ) 37 | { 38 | Results[i].Compile(param.SetLHS(false)); 39 | } 40 | 41 | 42 | param.CS.Add(new Command(Opcode.RET)).SetCodePos(RetPos); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Photon/AST/Symbol.cs: -------------------------------------------------------------------------------- 1 | using MarkSerializer; 2 | using SharpLexer; 3 | 4 | namespace Photon 5 | { 6 | enum SymbolUsage 7 | { 8 | None, 9 | Delegate, 10 | Func, 11 | Variable, 12 | Constant, 13 | SelfParameter, 14 | Parameter, 15 | Member, 16 | Package, 17 | Class, 18 | } 19 | 20 | 21 | internal class Symbol : IMarkSerializable 22 | { 23 | public string Name; 24 | 25 | public TokenPos DefinePos; 26 | 27 | public Node Decl; 28 | 29 | public int RegIndex; 30 | 31 | public Scope RegBelong; 32 | 33 | public SymbolUsage Usage; 34 | 35 | 36 | public void Serialize(BinarySerializer ser) 37 | { 38 | ser.Serialize(ref Name); 39 | ser.Serialize(ref DefinePos); 40 | ser.Serialize(ref RegIndex); 41 | ser.Serialize(ref Usage); 42 | } 43 | 44 | 45 | public bool IsGlobal 46 | { 47 | get 48 | { 49 | if (RegBelong == null) 50 | return false; 51 | 52 | return RegBelong.Type == ScopeType.Package; 53 | } 54 | } 55 | 56 | public override string ToString() 57 | { 58 | if ( RegIndex == -1 ) 59 | return string.Format("'{0}' ({1}) {2}", Name, Usage, DefinePos); 60 | 61 | string RegType = IsGlobal ? "G":"R"; 62 | 63 | return string.Format("'{0}' ({1}) {2} {3}{4}", Name, Usage, DefinePos, RegType, RegIndex); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Photon/AST/UnaryExpr.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | internal class UnaryExpr : Expr 8 | { 9 | public TokenType Op; 10 | public Expr X; 11 | 12 | public TokenPos OpPos; 13 | 14 | public UnaryExpr(Expr x, TokenType t, TokenPos oppos) 15 | { 16 | X = x; 17 | Op = t; 18 | OpPos = oppos; 19 | 20 | BuildRelation(); 21 | } 22 | 23 | public override IEnumerable Child() 24 | { 25 | yield return X; 26 | } 27 | 28 | public override string ToString() 29 | { 30 | return string.Format("UnaryExpr {0}", Op.ToString()); 31 | } 32 | 33 | static Opcode Token2OpCode(TokenType tk) 34 | { 35 | switch (tk) 36 | { 37 | case TokenType.Sub: 38 | return Opcode.MINUS; 39 | case TokenType.Not: 40 | return Opcode.NOT; 41 | case TokenType.Len: 42 | return Opcode.LEN; 43 | case TokenType.New: 44 | return Opcode.NEW; 45 | case TokenType.Int32: 46 | return Opcode.INT32; 47 | case TokenType.Int64: 48 | return Opcode.INT64; 49 | case TokenType.Float32: 50 | return Opcode.FLOAT32; 51 | case TokenType.Float64: 52 | return Opcode.FLOAT64; 53 | } 54 | 55 | return Opcode.NOP; 56 | } 57 | 58 | internal override void Compile(CompileParameter param) 59 | { 60 | var opcode = Token2OpCode(Op); 61 | 62 | if ( opcode != Opcode.NOP ) 63 | { 64 | X.Compile(param); 65 | } 66 | else 67 | { 68 | throw new CompileException("Unknown unary operator", OpPos); 69 | } 70 | 71 | param.CS.Add(new Command(opcode)).SetCodePos(OpPos); 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /Photon/AST/VarDeclareStmt.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | // var XXX 纯变量定义 8 | internal class VarDeclareStmt : Stmt 9 | { 10 | public List Names; 11 | 12 | public TokenPos VarPos; 13 | 14 | public VarDeclareStmt(List names, TokenPos varpos ) 15 | { 16 | Names = names; 17 | VarPos = varpos; 18 | 19 | BuildRelation(); 20 | } 21 | 22 | public override IEnumerable Child() 23 | { 24 | foreach (var e in Names) 25 | { 26 | yield return e; 27 | } 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return "VarDeclareStmt"; 33 | } 34 | 35 | internal override void Compile(CompileParameter param) 36 | { 37 | 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Photon/AST/WhileStmt.cs: -------------------------------------------------------------------------------- 1 |  2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace Photon 6 | { 7 | internal class WhileStmt : LoopStmt 8 | { 9 | public Expr Condition; 10 | 11 | public WhileStmt(Expr con, TokenPos defpos, Scope s, BlockStmt body) 12 | { 13 | Condition = con; 14 | Pos = defpos; 15 | ScopeInfo = s; 16 | Body = body; 17 | 18 | BuildRelation(); 19 | } 20 | 21 | public override string ToString() 22 | { 23 | return "WhileStmt"; 24 | } 25 | 26 | public override IEnumerable Child() 27 | { 28 | yield return Condition; 29 | 30 | yield return Body; 31 | } 32 | 33 | internal override void Compile(CompileParameter param) 34 | { 35 | LoopBeginCmdID = param.CS.CurrCmdID; 36 | 37 | Condition.Compile(param.SetLHS(false)); 38 | 39 | var jzCmd = param.CS.Add(new Command(Opcode.JZ, 0)) 40 | .SetCodePos(Pos) 41 | .SetComment("while condition"); 42 | 43 | param.LHS = false; 44 | Body.Compile(param.SetLHS(false)); 45 | 46 | param.CS.Add(new Command(Opcode.JMP, LoopBeginCmdID)) 47 | .SetCodePos(Pos) 48 | .SetComment("while loop"); 49 | 50 | // false body跳入 51 | LoopEndCmdID = param.CS.CurrCmdID; 52 | jzCmd.DataA = LoopEndCmdID; 53 | } 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Photon/Accessor/DataAccessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Photon 4 | { 5 | public partial class DataAccessor 6 | { 7 | internal virtual Value Get(int index) 8 | { 9 | throw new NotImplementedException(); 10 | } 11 | 12 | internal virtual void Set(int index, Value v) 13 | { 14 | throw new NotImplementedException(); 15 | } 16 | 17 | public virtual string DebugString(int index) 18 | { 19 | return Get(index).DebugString(); 20 | } 21 | 22 | public ValueKind GetValueKind( int index ) 23 | { 24 | return Get(index).Kind; 25 | } 26 | 27 | 28 | public Int32 GetInteger32(int index) 29 | { 30 | return Convertor.ValueToInteger32(Get(index)); 31 | } 32 | 33 | public Int64 GetInteger64(int index) 34 | { 35 | return Convertor.ValueToInteger64(Get(index)); 36 | } 37 | 38 | public bool GetBool(int index) 39 | { 40 | return Convertor.ValueToBool(Get(index)); 41 | } 42 | 43 | public float GetFloat32(int index) 44 | { 45 | return Convertor.ValueToFloat32(Get(index)); 46 | } 47 | 48 | public double GetFloat64(int index) 49 | { 50 | return Convertor.ValueToFloat64(Get(index)); 51 | } 52 | 53 | public string GetString(int index) 54 | { 55 | return Convertor.ValueToString(Get(index)); 56 | } 57 | 58 | internal Value GetValue(int index) 59 | { 60 | return Get(index); 61 | } 62 | 63 | public T GetNativeInstance(int index) where T : class 64 | { 65 | return Convertor.CastObject(Get(index)).Raw as T; 66 | } 67 | 68 | public bool IsNil(int index) 69 | { 70 | return Get(index).Kind == ValueKind.Nil; 71 | } 72 | 73 | 74 | internal void SetInteger32(int index, Int32 v) 75 | { 76 | Set(index, new ValueInteger32(v)); 77 | } 78 | 79 | internal void SetInteger64(int index, Int64 v) 80 | { 81 | Set(index, new ValueInteger64(v)); 82 | } 83 | 84 | internal void SetBool(int index, bool v) 85 | { 86 | Set(index, new ValueBool(v)); 87 | } 88 | 89 | internal void SetFloat32(int index, float v) 90 | { 91 | Set(index, new ValueFloat32(v)); 92 | } 93 | internal void SetFloat64(int index, double v) 94 | { 95 | Set(index, new ValueFloat64(v)); 96 | } 97 | 98 | public void SetString(int index, string v) 99 | { 100 | Set(index, new ValueString(v)); 101 | } 102 | 103 | internal void SetNil(int index) 104 | { 105 | Set(index, new ValueNil()); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Photon/Accessor/RegisterAccessor.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Photon 3 | { 4 | public partial class RuntimePackage 5 | { 6 | public int GetVarAsInteger32(string name) 7 | { 8 | return Convertor.ValueToInteger32(GetRegisterValue(name)); 9 | } 10 | 11 | public bool GetVarAsBool(string name) 12 | { 13 | return Convertor.ValueToBool(GetRegisterValue(name)); 14 | } 15 | 16 | public float GetVarAsFloat32(string name) 17 | { 18 | return Convertor.ValueToFloat32(GetRegisterValue(name)); 19 | } 20 | 21 | public string GetVarAsString(string name) 22 | { 23 | return Convertor.ValueToString(GetRegisterValue(name)); 24 | } 25 | 26 | public bool EqualsValue(string name, object v ) 27 | { 28 | return GetRegisterValue(name).Equals(Convertor.NativeValueToValue(v)); 29 | } 30 | 31 | public T GetVarAsNativeInstance(string name) where T:class 32 | { 33 | return Convertor.ValueToObject(GetRegisterValue(name)) as T; 34 | } 35 | 36 | public ValueKind GetVarKind(string name) 37 | { 38 | return GetRegisterValue(name).Kind; 39 | } 40 | 41 | public bool IsVarNil( string name ) 42 | { 43 | return GetRegisterValue(name) is ValueNil; 44 | } 45 | 46 | public void SetVarInteger32(string name, int v) 47 | { 48 | SetRegisterValue(name, Convertor.Integer32ToValue(v) ); 49 | } 50 | 51 | public void SetVarBool(string name, bool v) 52 | { 53 | SetRegisterValue(name, Convertor.BoolToValue(v)); 54 | } 55 | 56 | public void SetVarFloat32(string name, int v) 57 | { 58 | SetRegisterValue(name, Convertor.Float32ToValue(v)); 59 | } 60 | 61 | public void SetVarString(string name, string v) 62 | { 63 | SetRegisterValue(name, Convertor.StringToValue(v)); 64 | } 65 | 66 | public void SetVarNativeInstance(string name, T ins) where T : class 67 | { 68 | if ( _pkg == null ) 69 | return; 70 | 71 | var classType = _pkg.Exe.GetClassTypeByNativeType( typeof(T) ) as ValueNativeClassType; 72 | if ( classType == null ) 73 | { 74 | throw new RuntimeException("native class not registed: " + name); 75 | } 76 | 77 | SetRegisterValue(name, new ValueNativeClassIns(classType, ins )); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Photon/Accessor/StackAccessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Photon 4 | { 5 | public partial class DataStack 6 | { 7 | public void PushInteger32(Int32 v) 8 | { 9 | Push(new ValueInteger32(v)); 10 | } 11 | 12 | public void PushInteger64(Int64 v) 13 | { 14 | Push(new ValueInteger64(v)); 15 | } 16 | 17 | public void PushBool(bool v) 18 | { 19 | Push(new ValueBool(v)); 20 | } 21 | 22 | public void PushFloat32(float v) 23 | { 24 | Push(new ValueFloat32(v)); 25 | } 26 | 27 | public void PushFloat64(float v) 28 | { 29 | Push(new ValueFloat64(v)); 30 | } 31 | 32 | public void PushString(string v) 33 | { 34 | Push(new ValueString(v)); 35 | } 36 | 37 | internal void PushValue(Value v) 38 | { 39 | Push(v); 40 | } 41 | 42 | public void PushNil() 43 | { 44 | Push(new ValueNil()); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Photon/Build/CompileParameter.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Photon 3 | { 4 | struct CompileContext 5 | { 6 | internal Node node; 7 | internal CompileParameter parameter; 8 | } 9 | 10 | 11 | internal struct CompileParameter 12 | { 13 | internal Package Pkg; 14 | internal Executable Exe; 15 | internal ValuePhoFunc CS; 16 | internal ConstantSet Constants; 17 | internal bool LHS; 18 | 19 | internal CompileParameter SetLHS(bool lhs) 20 | { 21 | var copy = (CompileParameter)this.MemberwiseClone(); 22 | copy.LHS = lhs; 23 | return copy; 24 | } 25 | 26 | internal CompileParameter SetCmdSet(ValuePhoFunc cs) 27 | { 28 | var copy = (CompileParameter)this.MemberwiseClone(); 29 | copy.CS = cs; 30 | return copy; 31 | } 32 | 33 | internal CompileParameter SetPackage(Package pkg) 34 | { 35 | var copy = (CompileParameter)this.MemberwiseClone(); 36 | copy.Pkg = pkg; 37 | return copy; 38 | } 39 | 40 | internal CompileParameter Clone( ) 41 | { 42 | return (CompileParameter)this.MemberwiseClone(); 43 | } 44 | 45 | internal void NextPassToResolve(Node n) 46 | { 47 | Pkg.AddSecondPass(n, this); 48 | } 49 | 50 | internal bool IsNodeInNextPass(Node n) 51 | { 52 | return Pkg.ContainSecondPassNode(n); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /Photon/Build/Compiler.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | using System.IO; 3 | 4 | namespace Photon 5 | { 6 | public enum ImportMode 7 | { 8 | Directory, 9 | File, 10 | } 11 | 12 | public class Compiler 13 | { 14 | public static void GenerateBuiltinFiles() 15 | { 16 | Array.GenerateWrapper(); 17 | Map.GenerateWrapper(); 18 | } 19 | 20 | 21 | internal static void Import(Executable exe, ContentLoader loader, string packageName, string sourceName, ImportMode mode ) 22 | { 23 | var pkg = new Package(packageName, false); 24 | 25 | var parser = new Parser(exe, loader, pkg.ScopeMgr); 26 | 27 | loader.Load(pkg, parser, sourceName, mode); 28 | 29 | exe.AddPackage(pkg); 30 | 31 | var initPos = TokenPos.Init; 32 | initPos.SourceName = sourceName; 33 | 34 | // 全局入口( 不进入函数列表, 只在Package上保存 ) 35 | var cs = new ValuePhoFunc(new ObjectName(pkg.Name, "@init"), initPos, pkg.PackageScope.RegCount, pkg.PackageScope); 36 | pkg.InitEntry = cs; 37 | 38 | var param = new CompileParameter(); 39 | 40 | param.Pkg = pkg; 41 | param.CS = cs; 42 | param.Exe = exe; 43 | param.Constants = exe.Constants; 44 | 45 | pkg.Compile(param); 46 | 47 | cs.Add(new Command(Opcode.EXIT).SetCodePos(parser.CurrTokenPos)); 48 | } 49 | 50 | public static Executable CompileFile(string filename) 51 | { 52 | Executable exe = new Executable(); 53 | exe.RegisterBuiltinPackage(); 54 | 55 | Compiler.Compile(exe, new FileLoader(Directory.GetCurrentDirectory()), filename); 56 | 57 | return exe; 58 | } 59 | 60 | public static void Compile(Executable exe, ContentLoader loader, string filename) 61 | { 62 | Import(exe, loader, "main", filename, ImportMode.File); 63 | 64 | for( int i = 0;i _data = new List(); 9 | 10 | internal List Raw 11 | { 12 | get { return _data; } 13 | } 14 | 15 | public void Add(Value v) 16 | { 17 | _data.Add(v); 18 | } 19 | 20 | public void Remove(Value v) 21 | { 22 | _data.Remove(v); 23 | } 24 | 25 | public void RemoveAt(int index) 26 | { 27 | _data.RemoveAt(index); 28 | } 29 | 30 | public bool TryGet(int index, out Value v ) 31 | { 32 | if (index > 0 || index >= _data.Count) 33 | { 34 | v = Value.Nil; 35 | 36 | return false; 37 | } 38 | 39 | v = _data[index]; 40 | 41 | return true; 42 | } 43 | 44 | public bool TrySet(int index, Value v ) 45 | { 46 | if (index > 0 || index >= _data.Count) 47 | { 48 | return false; 49 | } 50 | 51 | _data[index] = v; 52 | 53 | return true; 54 | } 55 | 56 | public Value Get(int index) 57 | { 58 | if (index < 0 || index >= _data.Count) 59 | { 60 | throw new RuntimeException("Array out of bound"); 61 | } 62 | 63 | return _data[index]; 64 | } 65 | 66 | public void Set(int index, Value v) 67 | { 68 | if (index > 0 || index >= _data.Count) 69 | { 70 | throw new RuntimeException("Array out of bound"); 71 | } 72 | 73 | _data[index] = v; 74 | } 75 | 76 | public bool Contains(Value v) 77 | { 78 | return _data.Contains(v); 79 | } 80 | 81 | public int IndexOf(Value v) 82 | { 83 | return _data.IndexOf(v); 84 | } 85 | 86 | public void Clear() 87 | { 88 | _data.Clear(); 89 | } 90 | 91 | [NoGenWrapper] 92 | public void SetKeyValue(Value k, Value v) 93 | { 94 | int key = Convertor.ValueToInteger32(k); 95 | Set(key, v); 96 | } 97 | 98 | [NoGenWrapper] 99 | public Value GetKeyValue(Value k) 100 | { 101 | int key = Convertor.ValueToInteger32(k); 102 | return Get(key); 103 | } 104 | 105 | [NoGenWrapper] 106 | public int GetCount( ) 107 | { 108 | return _data.Count; 109 | } 110 | 111 | [NoGenWrapper] 112 | public ValueIterator GetIterator( ) 113 | { 114 | return new ValueArrayIterator(this); 115 | } 116 | 117 | internal static void Register( Executable exe ) 118 | { 119 | exe.RegisterNativeClass(Assembly.GetExecutingAssembly(), "Photon.ArrayWrapper", "Builtin"); 120 | } 121 | 122 | internal static void GenerateWrapper() 123 | { 124 | WrapperCodeGenerator.GenerateClass(typeof(Photon.Array), "Photon", "../Photon/Builtin/ArrayWrapper.cs"); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Photon/Builtin/ArrayWrapper.cs: -------------------------------------------------------------------------------- 1 | // Generated by github.com/davyxu/PhotonSharp 2 | // DO NOT EDIT!! 3 | using Photon; 4 | using System; 5 | 6 | namespace Photon 7 | { 8 | [NativeWrapperClass(typeof(Photon.Array))] 9 | public class ArrayWrapper 10 | { 11 | [NativeEntry(NativeEntryType.ClassMethod)] 12 | public static int Add( VMachine phoVM ) 13 | { 14 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 15 | 16 | var v = phoVM.DataStack.GetValue(1); 17 | 18 | phoClassIns.Add( v ); 19 | 20 | 21 | return 0; 22 | } 23 | 24 | [NativeEntry(NativeEntryType.ClassMethod)] 25 | public static int Remove( VMachine phoVM ) 26 | { 27 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 28 | 29 | var v = phoVM.DataStack.GetValue(1); 30 | 31 | phoClassIns.Remove( v ); 32 | 33 | 34 | return 0; 35 | } 36 | 37 | [NativeEntry(NativeEntryType.ClassMethod)] 38 | public static int RemoveAt( VMachine phoVM ) 39 | { 40 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 41 | 42 | var index = phoVM.DataStack.GetInteger32(1); 43 | 44 | phoClassIns.RemoveAt( index ); 45 | 46 | 47 | return 0; 48 | } 49 | 50 | [NativeEntry(NativeEntryType.ClassMethod)] 51 | public static int TryGet( VMachine phoVM ) 52 | { 53 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 54 | 55 | var index = phoVM.DataStack.GetInteger32(1); 56 | 57 | Value v = default(Value); 58 | var phoRetArg = phoClassIns.TryGet( index, out v ); 59 | 60 | phoVM.DataStack.PushValue( v ); 61 | phoVM.DataStack.PushBool( phoRetArg ); 62 | 63 | return 2; 64 | } 65 | 66 | [NativeEntry(NativeEntryType.ClassMethod)] 67 | public static int TrySet( VMachine phoVM ) 68 | { 69 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 70 | 71 | var index = phoVM.DataStack.GetInteger32(1); 72 | var v = phoVM.DataStack.GetValue(2); 73 | 74 | var phoRetArg = phoClassIns.TrySet( index, v ); 75 | 76 | phoVM.DataStack.PushBool( phoRetArg ); 77 | 78 | return 1; 79 | } 80 | 81 | [NativeEntry(NativeEntryType.ClassMethod)] 82 | public static int Get( VMachine phoVM ) 83 | { 84 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 85 | 86 | var index = phoVM.DataStack.GetInteger32(1); 87 | 88 | var phoRetArg = phoClassIns.Get( index ); 89 | 90 | phoVM.DataStack.PushValue( phoRetArg ); 91 | 92 | return 1; 93 | } 94 | 95 | [NativeEntry(NativeEntryType.ClassMethod)] 96 | public static int Set( VMachine phoVM ) 97 | { 98 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 99 | 100 | var index = phoVM.DataStack.GetInteger32(1); 101 | var v = phoVM.DataStack.GetValue(2); 102 | 103 | phoClassIns.Set( index, v ); 104 | 105 | 106 | return 0; 107 | } 108 | 109 | [NativeEntry(NativeEntryType.ClassMethod)] 110 | public static int Contains( VMachine phoVM ) 111 | { 112 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 113 | 114 | var v = phoVM.DataStack.GetValue(1); 115 | 116 | var phoRetArg = phoClassIns.Contains( v ); 117 | 118 | phoVM.DataStack.PushBool( phoRetArg ); 119 | 120 | return 1; 121 | } 122 | 123 | [NativeEntry(NativeEntryType.ClassMethod)] 124 | public static int IndexOf( VMachine phoVM ) 125 | { 126 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 127 | 128 | var v = phoVM.DataStack.GetValue(1); 129 | 130 | var phoRetArg = phoClassIns.IndexOf( v ); 131 | 132 | phoVM.DataStack.PushInteger32( phoRetArg ); 133 | 134 | return 1; 135 | } 136 | 137 | [NativeEntry(NativeEntryType.ClassMethod)] 138 | public static int Clear( VMachine phoVM ) 139 | { 140 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 141 | 142 | phoClassIns.Clear( ); 143 | 144 | 145 | return 0; 146 | } 147 | 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Photon/Builtin/Map.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Reflection; 3 | 4 | namespace Photon 5 | { 6 | class Map : IContainer 7 | { 8 | Dictionary _data = new Dictionary(); 9 | 10 | internal Dictionary Raw 11 | { 12 | get { return _data; } 13 | } 14 | 15 | [NoGenWrapper] 16 | public void SetKeyValue(Value k, Value v) 17 | { 18 | if ( v.Equals(Value.Nil) ) 19 | { 20 | _data.Remove(k); 21 | } 22 | else if (!_data.ContainsKey(k)) 23 | { 24 | _data[k] = v; 25 | } 26 | } 27 | 28 | [NoGenWrapper] 29 | public Value GetKeyValue(Value k) 30 | { 31 | Value ret; 32 | if (_data.TryGetValue(k, out ret)) 33 | { 34 | return ret; 35 | } 36 | 37 | return Value.Nil; 38 | } 39 | 40 | [NoGenWrapper] 41 | public int GetCount() 42 | { 43 | return _data.Count; 44 | } 45 | 46 | [NoGenWrapper] 47 | public ValueIterator GetIterator() 48 | { 49 | return new ValueMapIterator(this); 50 | } 51 | 52 | public bool ContainsKey(Value k) 53 | { 54 | return _data.ContainsKey(k); 55 | } 56 | 57 | public bool ContainsValue(Value k) 58 | { 59 | return _data.ContainsKey(k); 60 | } 61 | 62 | public void Clear() 63 | { 64 | _data.Clear(); 65 | } 66 | 67 | internal static void Register( Executable exe ) 68 | { 69 | exe.RegisterNativeClass(Assembly.GetExecutingAssembly(), "Photon.MapWrapper", "Builtin"); 70 | } 71 | 72 | internal static void GenerateWrapper() 73 | { 74 | WrapperCodeGenerator.GenerateClass(typeof(Photon.Map), "Photon", "../Photon/Builtin/MapWrapper.cs"); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Photon/Builtin/MapWrapper.cs: -------------------------------------------------------------------------------- 1 | // Generated by github.com/davyxu/PhotonSharp 2 | // DO NOT EDIT!! 3 | using Photon; 4 | using System; 5 | 6 | namespace Photon 7 | { 8 | [NativeWrapperClass(typeof(Photon.Map))] 9 | public class MapWrapper 10 | { 11 | [NativeEntry(NativeEntryType.ClassMethod)] 12 | public static int ContainsKey( VMachine phoVM ) 13 | { 14 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 15 | 16 | var k = phoVM.DataStack.GetValue(1); 17 | 18 | var phoRetArg = phoClassIns.ContainsKey( k ); 19 | 20 | phoVM.DataStack.PushBool( phoRetArg ); 21 | 22 | return 1; 23 | } 24 | 25 | [NativeEntry(NativeEntryType.ClassMethod)] 26 | public static int ContainsValue( VMachine phoVM ) 27 | { 28 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 29 | 30 | var k = phoVM.DataStack.GetValue(1); 31 | 32 | var phoRetArg = phoClassIns.ContainsValue( k ); 33 | 34 | phoVM.DataStack.PushBool( phoRetArg ); 35 | 36 | return 1; 37 | } 38 | 39 | [NativeEntry(NativeEntryType.ClassMethod)] 40 | public static int Clear( VMachine phoVM ) 41 | { 42 | var phoClassIns = phoVM.DataStack.GetNativeInstance(0); 43 | 44 | phoClassIns.Clear( ); 45 | 46 | 47 | return 0; 48 | } 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Photon/CodeGen/Collector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace Photon 5 | { 6 | class WrapperCodeCollector 7 | { 8 | internal static T GetCustomAttribute(PropertyInfo pi) where T : class 9 | { 10 | object[] objs = pi.GetCustomAttributes(typeof(T), false); 11 | if (objs.Length > 0) 12 | return (T)objs[0]; 13 | 14 | return null; 15 | } 16 | 17 | internal static T GetCustomAttribute(MethodInfo mi) where T : class 18 | { 19 | object[] objs = mi.GetCustomAttributes(typeof(T), false); 20 | if (objs.Length > 0) 21 | return (T)objs[0]; 22 | 23 | return null; 24 | } 25 | 26 | internal static void CollectClassInfo(WrapperGenPackage genPkg, Type cls, string filename) 27 | { 28 | if ( !cls.IsClass) 29 | { 30 | throw new RuntimeException("Require class type"); 31 | } 32 | 33 | var genClass = new WrapperGenClass(); 34 | genClass.Name = cls.Name; 35 | genClass.NativePackageName = cls.Namespace; 36 | genPkg.Classes.Add(genClass); 37 | 38 | 39 | foreach (var propInfo in cls.GetProperties()) 40 | { 41 | // 必须是本类自己的成员 42 | if (propInfo.DeclaringType != cls) 43 | continue; 44 | 45 | if (GetCustomAttribute(propInfo) != null) 46 | { 47 | continue; 48 | } 49 | 50 | 51 | var prop = new WrapperGenProperty(); 52 | prop.Name = propInfo.Name; 53 | prop.TypeString = Convertor.NativeTypeToTypeName(propInfo.PropertyType); 54 | prop.CanRead = propInfo.CanRead; 55 | prop.CanWrite = propInfo.CanWrite; 56 | genClass.Properties.Add(prop); 57 | } 58 | 59 | 60 | foreach (var methodInfo in cls.GetMethods()) 61 | { 62 | // 必须是本类自己的成员 63 | if (methodInfo.DeclaringType != cls) 64 | continue; 65 | 66 | // 掠过属性生成的函数 67 | if (methodInfo.IsSpecialName) 68 | continue; 69 | 70 | var attr = GetCustomAttribute(methodInfo); 71 | // 有标签的掠过, 无需生成 72 | if (attr != null) 73 | continue; 74 | 75 | // 不生成wrapper 76 | if (GetCustomAttribute(methodInfo) != null) 77 | { 78 | continue; 79 | } 80 | 81 | 82 | var genFunc = new WrapperGenFunc( ); 83 | genFunc.Name = methodInfo.Name; 84 | 85 | if ( methodInfo.IsStatic ) 86 | { 87 | genFunc.Mode = WrapperFuncMode.PackageFunc; 88 | } 89 | else 90 | { 91 | genFunc.Mode = WrapperFuncMode.ClassMethod; 92 | } 93 | 94 | genFunc.RetParameter = WrapperGenParameter.FromParameterInfo(methodInfo.ReturnParameter); 95 | 96 | foreach( var param in methodInfo.GetParameters() ) 97 | { 98 | var genParam = WrapperGenParameter.FromParameterInfo(param); 99 | 100 | if (param.IsOut) 101 | { 102 | genFunc.OutputParameters.Add(genParam); 103 | } 104 | else 105 | { 106 | genFunc.InputParameters.Add(genParam); 107 | } 108 | } 109 | 110 | 111 | genClass.Methods.Add(genFunc); 112 | 113 | 114 | } 115 | } 116 | 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Photon/CodeGen/Generator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace Photon 5 | { 6 | public class WrapperCodeGenerator 7 | { 8 | public static void GenerateClass(Type cls, string csharpNamespaceName, string filename) 9 | { 10 | var genPkg = new WrapperGenPackage(); 11 | genPkg.Name = csharpNamespaceName; 12 | WrapperCodeCollector.CollectClassInfo(genPkg, cls, filename); 13 | 14 | var content = WrapperCodePrinter.Print(genPkg ); 15 | 16 | Directory.CreateDirectory(Path.GetDirectoryName(filename)); 17 | System.IO.File.WriteAllText(filename, content, System.Text.Encoding.UTF8); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Photon/CodeGen/Model.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace Photon 6 | { 7 | 8 | class WrapperGenParameter 9 | { 10 | public string Name; 11 | public string TypeString; 12 | public string NativeTypeString; 13 | 14 | internal static WrapperGenParameter FromParameterInfo(ParameterInfo pi) 15 | { 16 | var genParam = new WrapperGenParameter(); 17 | genParam.Name = pi.Name; 18 | 19 | Type t; 20 | // out类型, 要转下 21 | if (pi.ParameterType.IsByRef) 22 | { 23 | t = pi.ParameterType.GetElementType(); 24 | } 25 | else 26 | { 27 | t = pi.ParameterType; 28 | } 29 | 30 | genParam.NativeTypeString = t.Name; 31 | 32 | genParam.TypeString = Convertor.NativeTypeToTypeName(t); 33 | 34 | if (string.IsNullOrEmpty(genParam.TypeString)) 35 | { 36 | throw new RuntimeException("Unknown parameter type: " + pi.ToString()); 37 | } 38 | 39 | return genParam; 40 | } 41 | } 42 | 43 | enum WrapperFuncMode 44 | { 45 | PackageFunc, 46 | ClassMethod, 47 | } 48 | 49 | class WrapperGenFunc 50 | { 51 | public string Name; 52 | public WrapperFuncMode Mode; 53 | public List InputParameters = new List(); 54 | public List OutputParameters = new List(); 55 | 56 | public WrapperGenParameter RetParameter; 57 | 58 | } 59 | 60 | class WrapperGenProperty 61 | { 62 | public string Name; 63 | public string TypeString; 64 | public bool CanRead; 65 | public bool CanWrite; 66 | } 67 | 68 | class WrapperGenClass 69 | { 70 | public string Name; 71 | public string NativePackageName; 72 | public List Methods = new List(); 73 | public List Properties = new List(); 74 | 75 | public string FullName 76 | { 77 | get { return NativePackageName + "." + Name; } 78 | } 79 | } 80 | 81 | 82 | class WrapperGenPackage 83 | { 84 | public string Name; 85 | 86 | public List Classes = new List(); 87 | 88 | public List PackageFuncs = new List(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Photon/Model/CodeFile.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Photon 3 | { 4 | public class CodeFile 5 | { 6 | internal SourceFile Source; 7 | 8 | // 调试Symbol 9 | internal FileNode AST; 10 | 11 | public override string ToString() 12 | { 13 | return Source.Name; 14 | } 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Photon/Model/Command.cs: -------------------------------------------------------------------------------- 1 | using MarkSerializer; 2 | using SharpLexer; 3 | using System.Text; 4 | 5 | namespace Photon 6 | { 7 | 8 | public class Command : IMarkSerializable 9 | { 10 | internal Opcode Op; 11 | 12 | const int MaxDataCount = 2; 13 | 14 | int[] _data = new int[MaxDataCount]; 15 | bool[] _dataUsed = new bool[MaxDataCount]; 16 | 17 | string _comment; 18 | 19 | TokenPos _pos; 20 | 21 | // 类名/函数名 22 | internal ObjectName EntryName; 23 | 24 | public void Serialize(BinarySerializer ser) 25 | { 26 | ser.Serialize(ref Op); 27 | ser.Serialize(ref _data); 28 | ser.Serialize(ref _dataUsed); 29 | ser.Serialize(ref _comment); 30 | ser.Serialize(ref EntryName); 31 | } 32 | 33 | 34 | internal int DataA 35 | { 36 | get 37 | { 38 | if (_dataUsed[0]) 39 | return _data[0]; 40 | else 41 | return -1; 42 | } 43 | 44 | set 45 | { 46 | _data[0] = value; 47 | _dataUsed[0] = true; 48 | } 49 | } 50 | 51 | internal int DataB 52 | { 53 | get 54 | { 55 | if (_dataUsed[1]) 56 | return _data[1]; 57 | else 58 | return -1; 59 | } 60 | 61 | set 62 | { 63 | _data[1] = value; 64 | _dataUsed[1] = true; 65 | } 66 | } 67 | 68 | internal int UsedDataCount 69 | { 70 | get { 71 | 72 | int ret = 0; 73 | foreach( var used in _dataUsed ) 74 | { 75 | if ( used ) 76 | { 77 | ret++; 78 | } 79 | } 80 | 81 | return ret; 82 | 83 | } 84 | } 85 | 86 | internal Command(Opcode op) 87 | { 88 | Op = op; 89 | } 90 | 91 | public string Comment 92 | { 93 | get { return _comment; } 94 | } 95 | 96 | public TokenPos CodePos 97 | { 98 | get { return _pos; } 99 | } 100 | 101 | public Command() 102 | { 103 | 104 | } 105 | 106 | internal Command(Opcode op, int data) 107 | { 108 | Op = op; 109 | DataA = data; 110 | } 111 | 112 | internal Command(Opcode op, int dataA, int dataB) 113 | { 114 | Op = op; 115 | DataA = dataA; 116 | DataB = dataB; 117 | } 118 | 119 | 120 | internal Command SetComment( string text ) 121 | { 122 | _comment = text; 123 | 124 | return this; 125 | } 126 | 127 | internal Command SetCodePos(TokenPos pos) 128 | { 129 | _pos = pos; 130 | return this; 131 | } 132 | 133 | public override string ToString() 134 | { 135 | 136 | var sb = new StringBuilder(); 137 | 138 | sb.Append(Op); 139 | sb.Append(" "); 140 | 141 | var usedCount = UsedDataCount; 142 | 143 | 144 | if (usedCount >= 1) 145 | { 146 | sb.Append(DataA); 147 | sb.Append(" "); 148 | } 149 | 150 | if (usedCount >= 2) 151 | { 152 | sb.Append(DataB); 153 | sb.Append(" "); 154 | } 155 | 156 | 157 | 158 | if ( !string.IsNullOrEmpty(Comment) ) 159 | { 160 | sb.Append("; "); 161 | sb.Append(Comment); 162 | sb.Append(" "); 163 | } 164 | 165 | return sb.ToString(); 166 | } 167 | } 168 | 169 | } 170 | -------------------------------------------------------------------------------- /Photon/Model/ConstantSet.cs: -------------------------------------------------------------------------------- 1 | using MarkSerializer; 2 | using System.Collections.Generic; 3 | 4 | namespace Photon 5 | { 6 | class ConstantSet : DataAccessor, IMarkSerializable 7 | { 8 | List _cset = new List(); 9 | 10 | 11 | public void Serialize(BinarySerializer ser) 12 | { 13 | ser.Serialize(ref _cset); 14 | } 15 | 16 | 17 | internal int Add(Value inc) 18 | { 19 | int index = 0; 20 | foreach( var c in _cset ) 21 | { 22 | if (c.Equals(inc)) 23 | return index; 24 | 25 | index++; 26 | } 27 | 28 | _cset.Add( inc ); 29 | 30 | return _cset.Count - 1; 31 | } 32 | internal int AddString( string s ) 33 | { 34 | return Add(new ValueString(s)); 35 | } 36 | 37 | internal int Count 38 | { 39 | get { return _cset.Count; } 40 | } 41 | 42 | internal override Value Get(int index) 43 | { 44 | return _cset[index]; 45 | } 46 | 47 | internal void DebugPrint( ) 48 | { 49 | int index = 0; 50 | foreach (var c in _cset) 51 | { 52 | Logger.DebugLine("C{0}: {1}", index, c.ToString()); 53 | index++; 54 | } 55 | 56 | Logger.DebugLine(""); 57 | } 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Photon/Model/Exception.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | using System; 3 | 4 | namespace Photon 5 | { 6 | public class CompileException : Exception 7 | { 8 | public TokenPos Pos; 9 | 10 | public CompileException(string msg, TokenPos pos) 11 | : base(msg) 12 | { 13 | Pos = pos; 14 | } 15 | 16 | public override string ToString() 17 | { 18 | return string.Format("{0} at line {1}", this.Message, Pos.Line); 19 | } 20 | } 21 | 22 | public class RuntimeException : Exception 23 | { 24 | public RuntimeException(string msg) 25 | : base( msg ) 26 | { 27 | 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Photon/Model/NativeType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Photon 4 | { 5 | public delegate int NativeFunction(VMachine vm); 6 | public delegate void NativeProperty(object phoIns, ref object value, bool isGet); 7 | 8 | public enum NativeEntryType 9 | { 10 | StaticFunc, 11 | ClassMethod, 12 | Class, 13 | Property, 14 | } 15 | 16 | public sealed class NativeWrapperClassAttribute : Attribute 17 | { 18 | Type _bindingClassType; 19 | public Type BindingClass 20 | { 21 | get { return _bindingClassType; } 22 | } 23 | 24 | public NativeWrapperClassAttribute(Type bindingClass) 25 | { 26 | _bindingClassType = bindingClass; 27 | } 28 | } 29 | 30 | // 不生成自动绑定类 31 | public sealed class NoGenWrapperAttribute : Attribute 32 | { 33 | 34 | } 35 | 36 | // 绑定到语言的入口 37 | public sealed class NativeEntryAttribute : Attribute 38 | { 39 | 40 | string _entryName; 41 | NativeEntryType _type; 42 | 43 | internal NativeEntryType Type 44 | { 45 | get { return _type; } 46 | } 47 | 48 | internal string EntryName 49 | { 50 | get { return _entryName; } 51 | } 52 | 53 | public NativeEntryAttribute(NativeEntryType type) 54 | { 55 | _type = type; 56 | } 57 | 58 | public NativeEntryAttribute(NativeEntryType type, string entryName) 59 | { 60 | _type = type; 61 | _entryName = entryName; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Photon/Model/ObjectName.cs: -------------------------------------------------------------------------------- 1 |  2 | using MarkSerializer; 3 | namespace Photon 4 | { 5 | internal struct ObjectName : IMarkSerializable 6 | { 7 | public string PackageName; 8 | 9 | public string EntryName; 10 | 11 | public string ClassName; 12 | 13 | internal static readonly ObjectName Empty = new ObjectName(string.Empty, string.Empty, string.Empty); 14 | 15 | public void Serialize(BinarySerializer ser) 16 | { 17 | ser.Serialize(ref PackageName); 18 | ser.Serialize(ref EntryName); 19 | ser.Serialize(ref ClassName); 20 | } 21 | 22 | internal ObjectName(string pkg, string entry) 23 | { 24 | PackageName = pkg; 25 | EntryName = entry; 26 | ClassName = string.Empty; 27 | } 28 | 29 | internal ObjectName(string pkg, string className, string entry) 30 | { 31 | PackageName = pkg; 32 | ClassName = className; 33 | EntryName = entry; 34 | } 35 | 36 | public override bool Equals(object obj) 37 | { 38 | var other = (ObjectName)obj; 39 | 40 | return PackageName == other.PackageName && 41 | EntryName == other.EntryName && 42 | ClassName == other.ClassName; 43 | } 44 | 45 | public override int GetHashCode() 46 | { 47 | return PackageName.GetHashCode() + EntryName.GetHashCode() + ClassName.GetHashCode(); 48 | } 49 | 50 | public override string ToString() 51 | { 52 | 53 | if ( string.IsNullOrEmpty(ClassName) ) 54 | { 55 | return string.Format("{0}.{1}", PackageName, EntryName); 56 | } 57 | 58 | return string.Format("{0}.{1}.{2}", PackageName, ClassName,EntryName); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Photon/Model/OpCode.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Photon 3 | { 4 | // S: 栈 R: 寄存器 K:常量表 I:索引 F: 函数表 Top: 栈顶 M: 类成员 5 | enum Opcode 6 | { 7 | NOP = 0, 8 | 9 | // 双目元操作 10 | ADD, // S[Top] = S[I] + S[I+1] 11 | SUB, // S[Top] = S[I] - S[I+1] 12 | MUL, // S[Top] = S[I] * S[I+1] 13 | DIV, // S[Top] = S[I] / S[I+1] 14 | GT, // S[Top] = S[I] > S[I+1] 15 | GE, // S[Top] = S[I] >= S[I+1] 16 | LT, // S[Top] = S[I] < S[I+1] 17 | LE, // S[Top] = S[I] <= S[I+1] 18 | EQ, // S[Top] = S[I] == S[I+1] 19 | NE, // S[Top] = S[I] != S[I+1] 20 | 21 | // 单目元操作 22 | MINUS, 23 | INC, 24 | DEC, 25 | NOT, 26 | LEN, 27 | INT32, 28 | INT64, 29 | FLOAT32, 30 | FLOAT64, 31 | 32 | 33 | // 存取操作 34 | LOADK, // S[Top] = K[I] 35 | LOADR, // S[Top] = R[I] 36 | LOADG, // S[Top] = G[I] 37 | LOADU, // S[Top] = U[I] // Upvalue 38 | LOADF, // S[Top] = F[PackageID + CmdSetID] 39 | LOADM, // S[Top] = Class[C].Member[I] 40 | LOADB, // S[Top] = base Class[C].Member[I] 41 | LOADI, 42 | SETR, // R[I] = S[I+1] 43 | SETG, // G[I] = S[I+1] 44 | SETU, // U[I] = * S[I+1] 45 | SETM, // Class[C].Member[I] = S[I+1] 46 | SETI, // S[Top] = S[I][ S[I+1] ] key为非字符串 47 | INITR, // 寄存器=nil 48 | SEL, // S[Top] = S[I][ P1 ] 显式字符串key调用 49 | LINKU, // 让Upvalue与寄存器建立引用 50 | CLOSURE, // 创建闭包 51 | NEW, // C[I] -> ClassInstance 52 | SETA, // Array = S[I], S[I+1].. 53 | SETD, // Map = S[I], S[I+1].. 54 | VISIT, // k, v, iter = VISIT( x, iter ) 55 | 56 | // 流程控制 57 | CALL, // S[I](S[I+1], ... ) 栈交换 58 | RET, // 59 | JZ, // S[Top] != 0 60 | JMP, // 无条件 61 | EXIT, 62 | 63 | 64 | MAX, 65 | } 66 | 67 | 68 | 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /Photon/Model/Register.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | namespace Photon 4 | { 5 | public class Register : DataAccessor 6 | { 7 | Value[] _values; 8 | int _usedSlot = 0; 9 | string _usage; 10 | Scope _scope; 11 | 12 | internal Register( string usage ) 13 | { 14 | _usage = usage; 15 | _values = new Value[4]; 16 | Clear(); 17 | } 18 | 19 | public int Count 20 | { 21 | get { return _usedSlot; } 22 | } 23 | 24 | internal void AttachScope(Scope s) 25 | { 26 | _scope = s; 27 | } 28 | 29 | internal void SetCount( int count ) 30 | { 31 | _usedSlot = count; 32 | if ( count > _values.Length ) 33 | { 34 | var newValues = new Value[2 * count]; 35 | _values.CopyTo(newValues, 0); 36 | 37 | 38 | for (int i = _values.Length; i < newValues.Length; i++) 39 | { 40 | newValues[i] = Value.Nil; 41 | } 42 | 43 | _values = newValues; 44 | } 45 | } 46 | 47 | internal override void Set( int index, Value v ) 48 | { 49 | _values[index] = v; 50 | } 51 | 52 | internal override Value Get(int index) 53 | { 54 | return _values[index]; 55 | } 56 | 57 | internal void Clear() 58 | { 59 | for (int i = 0; i < _values.Length; i++) 60 | { 61 | _values[i] = Value.Nil; 62 | } 63 | 64 | _usedSlot = 0; 65 | } 66 | 67 | public override string ToString() 68 | { 69 | return string.Format("{0} used:{1}", _usage, _usedSlot); 70 | } 71 | 72 | public override string DebugString(int index) 73 | { 74 | var v = Get(index); 75 | 76 | var symbol = _scope.FindRegisterByIndex(index); 77 | 78 | 79 | return string.Format("{0}{1} ({2}): {3}", _usage, index, symbol != null ? symbol.Name:"#NA", v.ToString()); 80 | } 81 | 82 | public void DebugPrint( ) 83 | { 84 | if ( _scope == null ) 85 | { 86 | for (int i = 0; i < _usedSlot; i++) 87 | { 88 | var v = _values[i]; 89 | 90 | Logger.DebugLine("{0}{1}: {2}", _usage, i, v.ToString()); 91 | } 92 | } 93 | else 94 | { 95 | for (int i = 0; i < _usedSlot; i++) 96 | { 97 | 98 | Logger.DebugLine(DebugString(i)); 99 | } 100 | } 101 | 102 | 103 | 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Photon/Model/ScopeManager.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | using MarkSerializer; 3 | 4 | namespace Photon 5 | { 6 | 7 | class ScopeManager : IMarkSerializable 8 | { 9 | Scope _topScope; 10 | 11 | Scope _global; 12 | 13 | 14 | public void Serialize(BinarySerializer ser) 15 | { 16 | ser.Serialize(ref _global); 17 | } 18 | 19 | 20 | internal Scope PackageScope 21 | { 22 | get { return _global; } 23 | } 24 | 25 | internal Scope TopScope 26 | { 27 | get { return _topScope; } 28 | set { _topScope = value; } 29 | } 30 | 31 | public ScopeManager() 32 | { 33 | OpenScope( ScopeType.Package, TokenPos.Invalid ); 34 | _global = _topScope; 35 | } 36 | 37 | internal Scope OpenScope(ScopeType type, TokenPos pos) 38 | { 39 | var s = new Scope(_topScope, type, pos ); 40 | _topScope = s; 41 | return s; 42 | } 43 | 44 | internal void CloseScope() 45 | { 46 | _topScope = _topScope.Outter; 47 | } 48 | 49 | internal Scope OpenClassScope(string name, TokenPos pos) 50 | { 51 | var exists = GetClassScope(name); 52 | if ( exists != null ) 53 | { 54 | // 被函数提前定义, 所以这里补下主定义位置 55 | exists.CodePos = pos; 56 | return exists; 57 | } 58 | 59 | var s = OpenScope(ScopeType.Class, pos); 60 | s.ClassName = name; 61 | return s; 62 | } 63 | 64 | internal Scope GetClassScope(string name) 65 | { 66 | foreach( var s in _global.Child ) 67 | { 68 | if ( s.Type == ScopeType.Class && s.ClassName == name ) 69 | { 70 | return s; 71 | } 72 | } 73 | 74 | return null; 75 | } 76 | 77 | internal static Symbol Declare(Node declareNode, Scope s, string name, TokenPos pos, SymbolUsage usage ) 78 | { 79 | var pre = s.FindSymbol(name); 80 | if ( pre != null ) 81 | { 82 | throw new CompileException(string.Format("{0} redeclared, pre define: {1}", name, pre.DefinePos), pos); 83 | } 84 | 85 | Symbol sb = new Symbol(); 86 | sb.Name = name; 87 | sb.Decl = declareNode; 88 | sb.DefinePos = pos; 89 | sb.Usage = usage; 90 | 91 | 92 | s.Insert( sb ); 93 | 94 | if ( declareNode != null ) 95 | { 96 | var ident = declareNode as Ident; 97 | 98 | if (ident == null) 99 | return sb; 100 | 101 | ident.Symbol = sb; 102 | } 103 | 104 | return sb; 105 | } 106 | 107 | internal void Resolve(Node x, Scope beginScope = null) 108 | { 109 | var ident = x as Ident; 110 | 111 | if (ident == null) 112 | return; 113 | 114 | if ( beginScope == null ) 115 | { 116 | beginScope = _topScope; 117 | } 118 | 119 | ident.BaseScope = beginScope; 120 | 121 | for (var s = beginScope; s != null; s = s.Outter) 122 | { 123 | var data = s.FindSymbol(ident.Name); 124 | if ( data != null ) 125 | { 126 | ident.Symbol = data; 127 | 128 | // 从闭包开始搜索, 如果已经不是在本层找到, 一定是upvalue 129 | if (beginScope.Type == ScopeType.Closure && s != beginScope) 130 | { 131 | ident.UpValue = true; 132 | } 133 | 134 | return; 135 | } 136 | } 137 | 138 | int a = 1; 139 | // 这里不再检查symbol是否存在, 而是放到AST里去 140 | // 这里检查将阻碍颠倒顺序函数定义 141 | //Error(string.Format("undeclared symbol {0}", ident.Name), ident.DefinePos ); 142 | 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /Photon/Model/SourceFile.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Photon 4 | { 5 | public class SourceFile 6 | { 7 | List _sourceLine = new List(); 8 | 9 | string _src; 10 | 11 | string _name; 12 | 13 | public string Source 14 | { 15 | get { return _src; } 16 | } 17 | 18 | public string Name 19 | { 20 | get { return _name; } 21 | } 22 | 23 | public List Lines 24 | { 25 | get { return _sourceLine; } 26 | } 27 | 28 | public SourceFile( string src, string name ) 29 | { 30 | _src = src; 31 | _name = name; 32 | 33 | var lines = src.Split('\r'); 34 | foreach (var line in lines) 35 | { 36 | string trimedLine; 37 | if (line.Length > 0 && line[0] == '\n') 38 | { 39 | trimedLine = line.Substring(1); 40 | } 41 | else 42 | { 43 | trimedLine = line; 44 | } 45 | 46 | _sourceLine.Add(trimedLine); 47 | } 48 | } 49 | 50 | public string GetLine( int line ) 51 | { 52 | if ( line == 0 ) 53 | { 54 | return string.Empty; 55 | } 56 | 57 | var final =line - 1; 58 | 59 | if (final < 0 || final >= _sourceLine.Count) 60 | return string.Empty; 61 | 62 | return _sourceLine[line - 1]; 63 | } 64 | 65 | public override string ToString() 66 | { 67 | return Name; 68 | } 69 | 70 | public void DebugPrint( ) 71 | { 72 | Logger.DebugLine("source:"); 73 | var lineCount = 0; 74 | foreach( var line in _sourceLine ) 75 | { 76 | lineCount++; 77 | Logger.DebugLine(string.Format("{0} {1}", lineCount, line)); 78 | } 79 | 80 | Logger.DebugLine(""); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Photon/Model/Token.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Photon 3 | { 4 | enum TokenType 5 | { 6 | EOF, 7 | Unknown, 8 | Whitespace, 9 | LineEnd, 10 | 11 | Comment, 12 | Identifier, 13 | Number, 14 | QuotedString, 15 | 16 | Assign, // = 17 | Equal, // == 18 | NotEqual, // != 19 | LessThan, // < 20 | GreatThan, // > 21 | LessEqual, // <= 22 | GreatEqual, // >= 23 | AddAssign, // += 24 | SubAssign, // -= 25 | MulAssign, // *= 26 | QuoAssign, // /= 27 | Increase, // ++ 28 | Decrease, // -- 29 | Not, // ! 30 | Add, // + 31 | Sub, // - 32 | Mul, // * 33 | Div, // / 34 | Comma, // , 35 | Dot, // . 36 | Colon, // : 37 | SemiColon, // ; 38 | LParen, // ( 39 | RParen, // ) 40 | LBracket, // [ 41 | RBracket, // ] 42 | LBrace, // { 43 | RBrace, // } 44 | Len, // len 45 | Func, // func 46 | Nil, // nil 47 | Var, // var 48 | Const, // const 49 | Return, // return 50 | If, // if 51 | Else, // else 52 | For, // for 53 | In, // in 54 | While, // while 55 | Break, // break 56 | Continue, // continue 57 | Import, // import 58 | Class, // class 59 | New, // new 60 | Is, // is 61 | Base, // base 62 | Int32, // int32 63 | Int64, // int64 64 | Float32, // float32 65 | Float64, // float64 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /Photon/Parser/Parser.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | 3 | namespace Photon 4 | { 5 | internal partial class Parser 6 | { 7 | Lexer _lexer; 8 | 9 | Token _token; 10 | 11 | Executable _exe; 12 | 13 | ContentLoader _loader; 14 | 15 | ScopeManager _scopemgr; 16 | 17 | internal Executable Exe 18 | { 19 | get { return _exe; } 20 | } 21 | 22 | internal ContentLoader Loader 23 | { 24 | get { return _loader; } 25 | } 26 | 27 | internal ScopeManager ScopeMgr 28 | { 29 | get { return _scopemgr; } 30 | } 31 | 32 | public Parser(Executable exe, ContentLoader loader, ScopeManager scopemgr) 33 | { 34 | _exe = exe; 35 | _loader = loader; 36 | _scopemgr = scopemgr; 37 | } 38 | 39 | public FileNode ParseFile(SourceFile file) 40 | { 41 | _lexer = NewLexer(file); 42 | 43 | Next(); 44 | 45 | var importList = ParseImportStmt( ); 46 | 47 | var lpos = CurrTokenPos; 48 | var list = ParseStatmentList(); 49 | var rpos = CurrTokenPos; 50 | 51 | return new FileNode(new BlockStmt(list, lpos, rpos), importList); 52 | } 53 | 54 | public override string ToString() 55 | { 56 | return _token.ToString(); 57 | } 58 | 59 | void Next() 60 | { 61 | _token = _lexer.Read(); 62 | 63 | if (CurrTokenType == TokenType.Unknown) 64 | { 65 | throw new CompileException("unknown token", CurrTokenPos); 66 | } 67 | } 68 | 69 | TokenType CurrTokenType 70 | { 71 | get { return (TokenType)_token.MatcherID; } 72 | } 73 | 74 | internal TokenPos CurrTokenPos 75 | { 76 | get { return _token.Pos; } 77 | } 78 | 79 | string CurrTokenValue 80 | { 81 | get { return _token.Value; } 82 | } 83 | 84 | Token Expect(TokenType t) 85 | { 86 | if (CurrTokenType != t) 87 | { 88 | throw new CompileException(string.Format("expect token: {0}", t.ToString()), CurrTokenPos); 89 | } 90 | 91 | var tk = _token; 92 | 93 | Next(); 94 | 95 | return tk; 96 | } 97 | 98 | 99 | public static void PrintAST(Node n, string indent = "") 100 | { 101 | Logger.DebugLine(indent + n.ToString()); 102 | 103 | foreach (var c in n.Child()) 104 | { 105 | PrintAST(c, indent + "\t"); 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Photon/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ScriptLib")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ScriptLib")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6ed40ffa-b1df-4508-b4ff-23cc959a4458")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Photon/Serializer/TokenPosSerializer.cs: -------------------------------------------------------------------------------- 1 | using MarkSerializer; 2 | using SharpLexer; 3 | using System; 4 | 5 | namespace Photon 6 | { 7 | 8 | public class TokenPosSerializer : TypeSerializer 9 | { 10 | public override bool Match(Type ft) 11 | { 12 | return ft == typeof(TokenPos); 13 | } 14 | 15 | public override bool Serialize(BinarySerializer ser, Type ft, ref object obj) 16 | { 17 | var ins = (TokenPos)obj; 18 | 19 | ser.Serialize(ref ins.Col); 20 | ser.Serialize(ref ins.Line); 21 | ser.Serialize(ref ins.SourceName); 22 | 23 | return true; 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Photon/Utility/CodePrinter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace Photon 4 | { 5 | 6 | /// 7 | /// 代码生成类 8 | /// 9 | public class CodePrinter 10 | { 11 | StringBuilder _builder = new StringBuilder(); 12 | string _indend; 13 | 14 | public override string ToString() 15 | { 16 | return _builder.ToString(); 17 | } 18 | 19 | public void Print(params object[] values) 20 | { 21 | foreach (object obj in values) 22 | { 23 | _builder.Append(obj.ToString()); 24 | } 25 | } 26 | 27 | public void BeginLine() 28 | { 29 | _builder.Append(_indend); 30 | } 31 | 32 | public void EndLine() 33 | { 34 | _builder.Append("\n"); 35 | } 36 | 37 | /// 38 | /// 把多个参数打到一行里 39 | /// 40 | /// 41 | public void PrintLine(params object[] values) 42 | { 43 | BeginLine(); 44 | Print(values); 45 | EndLine(); 46 | } 47 | 48 | /// 49 | /// 进入一个层次, 例如括号 50 | /// 51 | public void In() 52 | { 53 | _indend += "\t"; 54 | } 55 | 56 | /// 57 | /// 退出一个层次 58 | /// 59 | public void Out() 60 | { 61 | if (_indend.Length > 0) 62 | { 63 | _indend = _indend.Substring(1); 64 | } 65 | } 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /Photon/Utility/Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Photon 5 | { 6 | public enum LogLevel 7 | { 8 | Debug, 9 | Info, 10 | Warnning, 11 | Error, 12 | } 13 | 14 | public class Logger 15 | { 16 | public static bool OutputToDebugger = true; 17 | 18 | public static bool OutputToConsole = false; 19 | 20 | static void WriteLine(LogLevel level, string msg) 21 | { 22 | if (OutputToDebugger) 23 | { 24 | Debug.WriteLine(msg); 25 | } 26 | 27 | if (OutputToConsole) 28 | { 29 | Console.WriteLine(msg); 30 | } 31 | } 32 | 33 | public static void DebugLine(string fmt, params object[] args) 34 | { 35 | var text = string.Format(fmt, args); 36 | 37 | WriteLine(LogLevel.Debug, text); 38 | } 39 | 40 | public static void InfoLine(string fmt, params object[] args) 41 | { 42 | var text = string.Format(fmt, args); 43 | 44 | WriteLine(LogLevel.Info, text); 45 | } 46 | 47 | public static void WarningLine(string fmt, params object[] args) 48 | { 49 | var text = string.Format(fmt, args); 50 | 51 | WriteLine(LogLevel.Warnning, text); 52 | } 53 | 54 | public static void ErrorLine(string fmt, params object[] args) 55 | { 56 | var text = string.Format(fmt, args); 57 | 58 | WriteLine(LogLevel.Error, text); 59 | } 60 | 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Photon/VM/Instruction.cs: -------------------------------------------------------------------------------- 1 |  2 | using System; 3 | using System.Reflection; 4 | 5 | namespace Photon 6 | { 7 | class InstructionAttribute : Attribute 8 | { 9 | public Opcode Cmd 10 | { 11 | get; 12 | set; 13 | } 14 | } 15 | 16 | 17 | class Instruction 18 | { 19 | public virtual bool Execute( VMachine vm, Command cmd ) 20 | { 21 | // true表示下一条指令 22 | return true; 23 | } 24 | 25 | public virtual string Print( Command cmd ) 26 | { 27 | return string.Empty; 28 | } 29 | } 30 | 31 | 32 | class InstructionSet 33 | { 34 | // 指令集 35 | Instruction[] _instruction = new Instruction[(int)Opcode.MAX]; 36 | 37 | internal static T GetCustomAttribute(Type type) where T : class 38 | { 39 | object[] objs = type.GetCustomAttributes(typeof(T), false); 40 | if (objs.Length > 0) 41 | return (T)objs[0]; 42 | 43 | return null; 44 | } 45 | 46 | internal InstructionSet(VMachine vm) 47 | { 48 | var ass = Assembly.GetExecutingAssembly(); 49 | 50 | foreach (var t in ass.GetTypes()) 51 | { 52 | var att = GetCustomAttribute(t); 53 | if (att == null) 54 | continue; 55 | 56 | var cmd = Activator.CreateInstance(t) as Instruction; 57 | _instruction[(int)att.Cmd] = cmd; 58 | } 59 | } 60 | 61 | internal string InstructToString(Command cmd) 62 | { 63 | var inc = _instruction[(int)cmd.Op]; 64 | 65 | if (inc == null) 66 | { 67 | return string.Empty; 68 | } 69 | 70 | return inc.Print(cmd); 71 | } 72 | 73 | internal bool ExecCode(VMachine vm, Command cmd) 74 | { 75 | var inc = _instruction[(int)cmd.Op]; 76 | 77 | if (inc == null) 78 | { 79 | throw new RuntimeException("invalid instruction"); 80 | } 81 | 82 | 83 | return inc.Execute(vm,cmd); 84 | } 85 | } 86 | 87 | 88 | } 89 | -------------------------------------------------------------------------------- /Photon/VM/InstructionFlow.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | 3 | namespace Photon 4 | { 5 | [Instruction(Cmd = Opcode.JZ)] 6 | class CmdJZ : Instruction 7 | { 8 | public override bool Execute(VMachine vm, Command cmd) 9 | { 10 | var targetPC = cmd.DataA; 11 | 12 | var x = Convertor.ValueToBool(vm.DataStack.Pop()); 13 | 14 | if ( x == false) 15 | { 16 | vm.CurrFrame.PC = targetPC; 17 | return false; 18 | } 19 | 20 | return true; 21 | } 22 | 23 | public override string Print( Command cmd) 24 | { 25 | return string.Format("PC : {0}", cmd.DataA); 26 | } 27 | } 28 | 29 | [Instruction(Cmd = Opcode.JMP)] 30 | class CmdJmp : Instruction 31 | { 32 | public override bool Execute(VMachine vm, Command cmd) 33 | { 34 | vm.CurrFrame.PC = cmd.DataA; 35 | 36 | return false; 37 | } 38 | 39 | public override string Print( Command cmd) 40 | { 41 | return string.Format("PC : {0}", cmd.DataA); 42 | } 43 | } 44 | 45 | 46 | 47 | [Instruction(Cmd = Opcode.CALL)] 48 | class CmdCall : Instruction 49 | { 50 | public override bool Execute(VMachine vm, Command cmd) 51 | { 52 | var obj = vm.DataStack.Pop(); 53 | 54 | var func = Convertor.CastFunc(obj); 55 | 56 | return func.Invoke(vm, cmd.DataA, cmd.DataB, obj as ValueClosure); 57 | } 58 | 59 | public override string Print(Command cmd) 60 | { 61 | return string.Format("ArgCount : {0} ReceiverCount: {1}", cmd.DataA, cmd.DataB); 62 | } 63 | } 64 | 65 | 66 | [Instruction(Cmd = Opcode.RET)] 67 | class CmdRet : Instruction 68 | { 69 | public override bool Execute(VMachine vm, Command cmd) 70 | { 71 | vm.LeaveFrame(); 72 | 73 | // 让指令完CALL后, 往后走 74 | return true; 75 | } 76 | } 77 | 78 | [Instruction(Cmd = Opcode.EXIT)] 79 | class CmdExit : Instruction 80 | { 81 | public override bool Execute(VMachine vm, Command cmd) 82 | { 83 | vm.CurrFrame.PC = -1; 84 | 85 | return false; 86 | } 87 | } 88 | [Instruction(Cmd = Opcode.NOP)] 89 | class CmdNop : Instruction 90 | { 91 | public override bool Execute(VMachine vm, Command cmd) 92 | { 93 | 94 | return true; 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /Photon/VM/InstructionMath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Photon 4 | { 5 | class InstructionBinaryMath : Instruction 6 | { 7 | public override bool Execute(VMachine vm, Command cmd) 8 | { 9 | var b = vm.DataStack.Pop(); 10 | var a = vm.DataStack.Pop(); 11 | 12 | var x = a.OperateBinary(cmd.Op, b); 13 | 14 | vm.DataStack.Push(x); 15 | 16 | return true; 17 | } 18 | } 19 | 20 | 21 | [Instruction(Cmd = Opcode.ADD)] 22 | class CmdAdd : InstructionBinaryMath 23 | { 24 | } 25 | 26 | [Instruction(Cmd = Opcode.SUB)] 27 | class CmdSub : InstructionBinaryMath 28 | { 29 | } 30 | 31 | [Instruction(Cmd = Opcode.MUL)] 32 | class CmdMul : InstructionBinaryMath 33 | { 34 | } 35 | 36 | [Instruction(Cmd = Opcode.DIV)] 37 | class CmdDiv : InstructionBinaryMath 38 | { 39 | } 40 | 41 | [Instruction(Cmd = Opcode.GT)] 42 | class CmdGT : InstructionBinaryMath 43 | { 44 | } 45 | 46 | [Instruction(Cmd = Opcode.GE)] 47 | class CmdGE : InstructionBinaryMath 48 | { 49 | } 50 | 51 | [Instruction(Cmd = Opcode.LT)] 52 | class CmdLT : InstructionBinaryMath 53 | { 54 | } 55 | 56 | [Instruction(Cmd = Opcode.LE)] 57 | class CmdLE : InstructionBinaryMath 58 | { 59 | } 60 | 61 | [Instruction(Cmd = Opcode.EQ)] 62 | class CmdEQ : InstructionBinaryMath 63 | { 64 | } 65 | 66 | [Instruction(Cmd = Opcode.NE)] 67 | class CmdNE : InstructionBinaryMath 68 | { 69 | } 70 | 71 | 72 | class InstructionUnaryMath : Instruction 73 | { 74 | public override bool Execute(VMachine vm, Command cmd) 75 | { 76 | var a = vm.DataStack.Pop(); 77 | 78 | var x = a.OperateUnary(cmd.Op); 79 | 80 | vm.DataStack.Push(x); 81 | 82 | return true; 83 | } 84 | } 85 | 86 | [Instruction(Cmd = Opcode.LEN)] 87 | class CmdLen : InstructionUnaryMath 88 | { 89 | } 90 | 91 | [Instruction(Cmd = Opcode.MINUS)] 92 | class CmdMinus : InstructionUnaryMath 93 | { 94 | } 95 | 96 | [Instruction(Cmd = Opcode.INC)] 97 | class CmdInc : InstructionUnaryMath 98 | { 99 | } 100 | 101 | 102 | [Instruction(Cmd = Opcode.DEC)] 103 | class CmdDec : InstructionUnaryMath 104 | { 105 | } 106 | 107 | 108 | [Instruction(Cmd = Opcode.INT32)] 109 | class CmdInt32 : InstructionUnaryMath 110 | { 111 | } 112 | 113 | [Instruction(Cmd = Opcode.INT64)] 114 | class CmdInt64 : InstructionUnaryMath 115 | { 116 | } 117 | 118 | [Instruction(Cmd = Opcode.FLOAT32)] 119 | class CmdFloat32 : InstructionUnaryMath 120 | { 121 | } 122 | 123 | [Instruction(Cmd = Opcode.FLOAT64)] 124 | class CmdFloat64 : InstructionUnaryMath 125 | { 126 | } 127 | 128 | 129 | } 130 | -------------------------------------------------------------------------------- /Photon/VM/RuntimeFrame.cs: -------------------------------------------------------------------------------- 1 | using SharpLexer; 2 | using System.Collections.Generic; 3 | 4 | namespace Photon 5 | { 6 | public class RuntimeFrame 7 | { 8 | public int PC; 9 | 10 | internal ValuePhoFunc Func; 11 | 12 | internal int DataStackBase; 13 | 14 | // 函数返回值接收变量数量 15 | internal int ReceiverCount; 16 | 17 | internal ValueClosure Closure; 18 | 19 | internal Register Reg = new Register("R" ); 20 | 21 | public int FuncID 22 | { 23 | get { return Func.ID; } 24 | } 25 | public string FuncName 26 | { 27 | get { return Func.Name.ToString(); } 28 | } 29 | 30 | 31 | public TokenPos FuncDefPos 32 | { 33 | get { return Func.DefPos; } 34 | } 35 | 36 | public string PkgName 37 | { 38 | get { return Func.Name.PackageName; } 39 | } 40 | 41 | public List Commands 42 | { 43 | get { return Func.Commands; } 44 | } 45 | 46 | public TokenPos CodePos 47 | { 48 | get { 49 | var cmd = GetCurrCommand(); 50 | if (cmd == null) 51 | return TokenPos.Invalid; 52 | 53 | return cmd.CodePos; 54 | } 55 | } 56 | 57 | internal RuntimeFrame(ValuePhoFunc cs) 58 | { 59 | Func = cs; 60 | } 61 | 62 | internal Command GetCurrCommand() 63 | { 64 | if (PC >= Func.Commands.Count || PC < 0) 65 | { 66 | return null; 67 | } 68 | 69 | return Func.Commands[PC]; 70 | } 71 | 72 | public string DebugString() 73 | { 74 | return string.Format("{0} {1}", CodePos, Func.Name); 75 | } 76 | 77 | public override string ToString() 78 | { 79 | return DebugString(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Photon/VM/RuntimePackage.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Photon 3 | { 4 | public partial class RuntimePackage 5 | { 6 | public Register Reg = new Register("G" ); 7 | 8 | Package _pkg; 9 | 10 | public string Name 11 | { 12 | get { return _pkg.Name; } 13 | } 14 | 15 | public override string ToString() 16 | { 17 | return _pkg.Name; 18 | } 19 | 20 | internal RuntimePackage( Package pkg ) 21 | { 22 | _pkg = pkg; 23 | Reg.AttachScope(pkg.TopScope); 24 | } 25 | 26 | internal Value GetRegisterValue(string name) 27 | { 28 | if (_pkg == null) 29 | return Value.Nil; 30 | 31 | var symbol = _pkg.PackageScope.FindRegister(name); 32 | if (symbol == null) 33 | return Value.Nil; 34 | 35 | return Reg.Get(symbol.RegIndex) as Value; 36 | } 37 | 38 | void SetRegisterValue(string name, object v) 39 | { 40 | if (_pkg == null) 41 | return; 42 | 43 | var symbol = _pkg.PackageScope.FindRegister(name); 44 | if (symbol == null) 45 | return; 46 | 47 | Reg.Set(symbol.RegIndex, v as Value); 48 | } 49 | 50 | 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Photon/Value/Value.cs: -------------------------------------------------------------------------------- 1 | using MarkSerializer; 2 | 3 | namespace Photon 4 | { 5 | public enum ValueKind 6 | { 7 | Nil = 0, 8 | Float32, 9 | Float64, 10 | Integer32, 11 | Integer64, 12 | Bool, 13 | String, 14 | Func, 15 | ArrayIterator, 16 | MapIterator, 17 | ClassType, 18 | ClassInstance, 19 | NativeClassType, 20 | NativeClassInstance, 21 | } 22 | 23 | internal interface IContainer 24 | { 25 | void SetKeyValue(Value k, Value v); 26 | 27 | Value GetKeyValue(Value k); 28 | 29 | int GetCount(); 30 | 31 | ValueIterator GetIterator( ); 32 | } 33 | 34 | class Value : IMarkSerializable 35 | { 36 | internal static Value Nil = new ValueNil(); 37 | 38 | public override string ToString() 39 | { 40 | return DebugString(); 41 | } 42 | 43 | public virtual void Serialize(BinarySerializer ser) 44 | { 45 | 46 | } 47 | public virtual bool Visit(Value iter, DataStack ds) 48 | { 49 | return false; 50 | } 51 | 52 | public virtual string DebugString( ) 53 | { 54 | throw new RuntimeException("NotImplementToString"); 55 | } 56 | 57 | public virtual ValueKind Kind 58 | { 59 | get { return ValueKind.Nil; } 60 | } 61 | 62 | public virtual string TypeName 63 | { 64 | get { return string.Empty; } 65 | } 66 | 67 | internal virtual object Raw 68 | { 69 | get { throw new System.NotImplementedException(); } 70 | } 71 | 72 | internal virtual Value OperateBinary(Opcode code, Value other) 73 | { 74 | throw new RuntimeException("Expect 'OperateBinary' operand"); 75 | } 76 | 77 | internal virtual Value OperateUnary(Opcode code) 78 | { 79 | throw new RuntimeException("Expect 'OperateUnary' operand"); 80 | } 81 | 82 | // 动态获取 83 | internal virtual void OperateSetKeyValue(Value k, Value v) 84 | { 85 | throw new RuntimeException("Expect 'OperateSetKeyValue' operand"); 86 | } 87 | 88 | internal virtual Value OperateGetKeyValue(Value k) 89 | { 90 | throw new RuntimeException("Expect 'OperateGetKeyValue' operand"); 91 | } 92 | 93 | // 编译期确认的成员函数和变量 94 | internal virtual void OperateSetMemberValue(int nameKey, Value v) 95 | { 96 | throw new RuntimeException("Expect 'OperateSetMemberValue' operand"); 97 | } 98 | 99 | internal virtual Value OperateGetMemberValue(int nameKey) 100 | { 101 | throw new RuntimeException("Expect 'OperateGetMemberValue' operand"); 102 | } 103 | } 104 | 105 | 106 | 107 | } 108 | -------------------------------------------------------------------------------- /Photon/Value/ValueArrayIterator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Photon 4 | { 5 | class ValueArrayIterator : ValueIterator 6 | { 7 | IEnumerator _data; 8 | int _index; 9 | 10 | public ValueArrayIterator( Array arr ) 11 | { 12 | _data = arr.Raw.GetEnumerator(); 13 | _index = 0; 14 | _data.MoveNext(); 15 | } 16 | 17 | internal override void Next() 18 | { 19 | _data.MoveNext(); 20 | _index++; 21 | } 22 | 23 | // k, v, iter = ITER( x, iter ) 24 | internal override bool Iterate(DataStack ds) 25 | { 26 | if (_data.Current == null) 27 | return false; 28 | 29 | ds.Push(this); 30 | ds.Push(_data.Current); 31 | ds.Push(new ValueInteger32(_index)); 32 | 33 | return true; 34 | } 35 | 36 | public IEnumerator RawValue 37 | { 38 | get { return _data; } 39 | } 40 | 41 | internal override object Raw 42 | { 43 | get { return _data; } 44 | } 45 | 46 | public override bool Equals(object other) 47 | { 48 | var otherT = other as ValueArrayIterator; 49 | if (otherT == null) 50 | return false; 51 | 52 | return otherT._data.Equals(_data); 53 | } 54 | 55 | public override int GetHashCode() 56 | { 57 | return _data.GetHashCode(); 58 | } 59 | 60 | public override string DebugString() 61 | { 62 | return string.Format("'{0}' (arr iterator)", _data.Current); 63 | } 64 | 65 | public override ValueKind Kind 66 | { 67 | get { return ValueKind.ArrayIterator; } 68 | } 69 | } 70 | 71 | 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /Photon/Value/ValueBool.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Photon 3 | { 4 | class ValueBool : Value 5 | { 6 | bool _data; 7 | 8 | public ValueBool(bool data) 9 | { 10 | _data = data; 11 | } 12 | 13 | public bool RawValue 14 | { 15 | get { return _data; } 16 | } 17 | 18 | internal override object Raw 19 | { 20 | get { return _data; } 21 | } 22 | 23 | public override bool Equals(object other) 24 | { 25 | var otherT = other as ValueBool; 26 | if (otherT == null) 27 | return false; 28 | 29 | return otherT._data == _data; 30 | } 31 | 32 | public override int GetHashCode() 33 | { 34 | return _data.GetHashCode(); 35 | } 36 | 37 | public override string DebugString() 38 | { 39 | return _data.ToString() + " (bool)"; 40 | } 41 | 42 | public override ValueKind Kind 43 | { 44 | get { return ValueKind.Bool; } 45 | } 46 | } 47 | 48 | 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /Photon/Value/ValueClassType.cs: -------------------------------------------------------------------------------- 1 |  2 | using MarkSerializer; 3 | namespace Photon 4 | { 5 | class ValueClassType : Value 6 | { 7 | internal int ID = -1; 8 | 9 | protected ObjectName _name; 10 | public ObjectName Name 11 | { 12 | get { return _name; } 13 | } 14 | 15 | protected Package _pkg; 16 | internal Package Pkg 17 | { 18 | get { return _pkg; } 19 | } 20 | 21 | internal virtual int GetInheritLevel() { return 0; } 22 | 23 | internal virtual void OnSerializeDone(Executable exe) { } 24 | 25 | public ValueClassType() 26 | { 27 | 28 | } 29 | 30 | public override void Serialize(BinarySerializer ser) 31 | { 32 | ser.Serialize(ref ID); 33 | ser.Serialize(ref _name); 34 | } 35 | 36 | 37 | internal ValueClassType( ObjectName name) 38 | { 39 | _name = name; 40 | } 41 | 42 | public override bool Equals(object v) 43 | { 44 | var other = v as ValueClassType; 45 | if (other == null) 46 | return false; 47 | 48 | return _name.Equals(other._name); 49 | } 50 | 51 | public override int GetHashCode() 52 | { 53 | return _name.GetHashCode(); 54 | } 55 | 56 | public override string TypeName 57 | { 58 | get { return Name.ToString(); } 59 | } 60 | 61 | internal virtual ValueObject CreateInstance( ) 62 | { 63 | return null; 64 | } 65 | 66 | internal string Key2Name(int key) 67 | { 68 | var v = Pkg.Exe.Constants.Get(key) as ValueString; 69 | if (v == null) 70 | return string.Empty; 71 | 72 | return v.RawValue; 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /Photon/Value/ValueClosure.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Photon 4 | { 5 | class RuntimeUpValue 6 | { 7 | public Register Reg; 8 | public int Index; 9 | } 10 | 11 | class ValueClosure : ValueFunc 12 | { 13 | List _upvalues = new List(); 14 | 15 | ValueFunc _func; 16 | internal ValueClosure( ValueFunc func ) 17 | : base( func.Name ) 18 | { 19 | _func = func; 20 | } 21 | 22 | internal void AddUpValue( Register reg, int index ) 23 | { 24 | RuntimeUpValue ru = new RuntimeUpValue() ; 25 | ru.Reg = reg; 26 | ru.Index = index; 27 | 28 | _upvalues.Add(ru); 29 | } 30 | 31 | internal void SetValue(int index, Value v) 32 | { 33 | var ru = _upvalues[index]; 34 | ru.Reg.Set(ru.Index, v); 35 | } 36 | 37 | internal Value GetValue(int index) 38 | { 39 | var ru = _upvalues[index]; 40 | return ru.Reg.Get(ru.Index); 41 | } 42 | 43 | internal RuntimeUpValue GetUpValue( int index ) 44 | { 45 | return _upvalues[index]; 46 | } 47 | 48 | internal override bool Invoke(VMachine vm, int argCount, int receiverCount, ValueClosure closure) 49 | { 50 | return _func.Invoke(vm, argCount, receiverCount, closure ); 51 | } 52 | 53 | public override string DebugString() 54 | { 55 | return string.Format("{0} (closure)", _func.ToString()); 56 | } 57 | 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /Photon/Value/ValueFloat64.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Photon 4 | { 5 | class ValueFloat64 : Value 6 | { 7 | double _data = 0; 8 | 9 | public ValueFloat64( double data ) 10 | { 11 | _data = data; 12 | } 13 | 14 | public double RawValue 15 | { 16 | get { return _data; } 17 | } 18 | 19 | internal override object Raw 20 | { 21 | get { return _data; } 22 | } 23 | 24 | public override bool Equals(object other) 25 | { 26 | var otherT = other as ValueFloat64; 27 | if (otherT == null) 28 | return false; 29 | 30 | return otherT._data == _data; 31 | } 32 | 33 | public override int GetHashCode() 34 | { 35 | return _data.GetHashCode(); 36 | } 37 | 38 | public override string DebugString() 39 | { 40 | return _data.ToString() + " (double32)"; 41 | } 42 | 43 | public override ValueKind Kind 44 | { 45 | get { return ValueKind.Float64; } 46 | } 47 | 48 | internal override Value OperateBinary(Opcode code, Value other) 49 | { 50 | var a = RawValue; 51 | 52 | double b; 53 | 54 | // 类型匹配 55 | switch (other.Kind) 56 | { 57 | case ValueKind.Integer32: 58 | return new ValueInteger32((Int32)this.RawValue).OperateBinary(code, other); 59 | case ValueKind.Integer64: 60 | return new ValueInteger64((Int64)this.RawValue).OperateBinary(code, other); 61 | case ValueKind.Float32: 62 | return new ValueFloat32((float)this.RawValue).OperateBinary(code, other); 63 | case ValueKind.Float64: 64 | b = (other as ValueFloat64).RawValue; 65 | break; 66 | default: 67 | throw new RuntimeException("Binary operator value type not match:" + other.ToString()); 68 | } 69 | 70 | switch (code) 71 | { 72 | case Opcode.ADD: 73 | return new ValueFloat64(a + b); 74 | case Opcode.SUB: 75 | return new ValueFloat64(a - b); 76 | case Opcode.MUL: 77 | return new ValueFloat64(a * b); 78 | case Opcode.DIV: 79 | return new ValueFloat64(a / b); 80 | case Opcode.GT: 81 | return new ValueBool(a > b); 82 | case Opcode.GE: 83 | return new ValueBool(a >= b); 84 | case Opcode.LT: 85 | return new ValueBool(a < b); 86 | case Opcode.LE: 87 | return new ValueBool(a <= b); 88 | case Opcode.EQ: 89 | return new ValueBool(a == b); 90 | case Opcode.NE: 91 | return new ValueBool(a != b); 92 | default: 93 | throw new RuntimeException("Unknown binary operator:" + code.ToString()); 94 | } 95 | } 96 | 97 | internal override Value OperateUnary(Opcode code) 98 | { 99 | var a = RawValue; 100 | 101 | switch (code) 102 | { 103 | case Opcode.MINUS: 104 | return new ValueFloat64(-a); 105 | case Opcode.INC: 106 | return new ValueFloat64(++a); 107 | case Opcode.DEC: 108 | return new ValueFloat64(--a); 109 | case Opcode.INT32: 110 | return new ValueInteger32((Int32)a); 111 | case Opcode.INT64: 112 | return new ValueInteger64((Int64)a); 113 | case Opcode.FLOAT32: 114 | return new ValueFloat32((float)a); 115 | case Opcode.FLOAT64: 116 | return this; 117 | default: 118 | throw new RuntimeException("Unknown unary operator:" + code.ToString()); 119 | } 120 | } 121 | } 122 | 123 | 124 | 125 | 126 | } 127 | -------------------------------------------------------------------------------- /Photon/Value/ValueFunc.cs: -------------------------------------------------------------------------------- 1 |  2 | using MarkSerializer; 3 | using SharpLexer; 4 | namespace Photon 5 | { 6 | class ValueFunc : Value 7 | { 8 | internal int ID = -1; 9 | 10 | ObjectName _name; 11 | 12 | public ObjectName Name 13 | { 14 | get { return _name; } 15 | } 16 | 17 | // 传入参数数量 18 | internal int InputValueCount { get; set; } 19 | 20 | // 返回值数量 21 | internal int OutputValueCount { get; set; } 22 | 23 | 24 | public override void Serialize(BinarySerializer ser) 25 | { 26 | ser.Serialize(ref ID); 27 | ser.Serialize(ref _name); 28 | } 29 | 30 | public ValueFunc() 31 | { 32 | 33 | } 34 | 35 | internal ValueFunc(ObjectName name) 36 | { 37 | _name = name; 38 | } 39 | 40 | internal virtual bool Invoke(VMachine vm, int argCount, int receiverCount, ValueClosure closure) 41 | { 42 | return false; 43 | } 44 | 45 | internal virtual void DebugPrint(Executable exe ) 46 | { 47 | 48 | } 49 | 50 | public override ValueKind Kind 51 | { 52 | get { return ValueKind.Func; } 53 | } 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /Photon/Value/ValueIterator.cs: -------------------------------------------------------------------------------- 1 | using MarkSerializer; 2 | 3 | namespace Photon 4 | { 5 | class ValueIterator : Value 6 | { 7 | internal virtual void Next( ) 8 | { 9 | 10 | } 11 | 12 | internal virtual bool Iterate(DataStack ds) 13 | { 14 | return false; 15 | } 16 | 17 | public override void Serialize(BinarySerializer ser) 18 | { 19 | throw new RuntimeException("Can not serialize iterator"); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Photon/Value/ValueMapIterator.cs: -------------------------------------------------------------------------------- 1 | using MarkSerializer; 2 | using System.Collections.Generic; 3 | 4 | namespace Photon 5 | { 6 | class ValueMapIterator : ValueIterator 7 | { 8 | IEnumerator> _data; 9 | static KeyValuePair nullKV = new KeyValuePair(); 10 | 11 | public ValueMapIterator(Map arr) 12 | { 13 | _data = arr.Raw.GetEnumerator(); 14 | _data.MoveNext(); 15 | } 16 | 17 | internal override void Next() 18 | { 19 | _data.MoveNext(); 20 | } 21 | 22 | // k, v, iter = ITER( x, iter ) 23 | internal override bool Iterate(DataStack ds) 24 | { 25 | if (_data.Current.Equals(nullKV)) 26 | return false; 27 | 28 | ds.Push(this); 29 | var kv = _data.Current; 30 | ds.Push(kv.Value); 31 | ds.Push(kv.Key); 32 | 33 | return true; 34 | } 35 | 36 | public IEnumerator> RawValue 37 | { 38 | get { return _data; } 39 | } 40 | 41 | internal override object Raw 42 | { 43 | get { return _data; } 44 | } 45 | 46 | public override bool Equals(object other) 47 | { 48 | var otherT = other as ValueMapIterator; 49 | if (otherT == null) 50 | return false; 51 | 52 | return otherT._data.Equals(_data); 53 | } 54 | 55 | public override int GetHashCode() 56 | { 57 | return _data.GetHashCode(); 58 | } 59 | 60 | public override string DebugString() 61 | { 62 | return string.Format("'{0}' (map iterator)", _data.Current); 63 | } 64 | 65 | public override ValueKind Kind 66 | { 67 | get { return ValueKind.MapIterator; } 68 | } 69 | } 70 | 71 | 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /Photon/Value/ValueNativeClassIns.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace Photon 4 | { 5 | class ValueNativeClassIns : ValueObject 6 | { 7 | ValueNativeClassType _type; 8 | 9 | object _data; 10 | 11 | internal override object Raw 12 | { 13 | get { return _data; } 14 | } 15 | 16 | internal ValueNativeClassIns(ValueNativeClassType t, object nativeIns ) 17 | { 18 | _type = t; 19 | _data = nativeIns; 20 | } 21 | 22 | 23 | internal override void OperateSetMemberValue(int nameKey, Value v) 24 | { 25 | object obj = _type.GetMember(nameKey); 26 | 27 | var fastProp = obj as NativeProperty; 28 | if (fastProp != null) 29 | { 30 | object retValue = v; 31 | fastProp(_data, ref retValue, false); 32 | return; 33 | } 34 | 35 | throw new RuntimeException("member not exists: " + _type.Key2Name(nameKey)); 36 | } 37 | 38 | internal override Value OperateGetMemberValue(int nameKey) 39 | { 40 | object obj = _type.GetMember(nameKey); 41 | var func = obj as ValueNativeFunc; 42 | if (func != null) 43 | return func; 44 | 45 | var fastProp = obj as NativeProperty; 46 | if (fastProp != null) 47 | { 48 | object retValue = null; 49 | fastProp(_data, ref retValue, true); 50 | return retValue as Value; 51 | } 52 | 53 | throw new RuntimeException("member not exists: " + _type.Key2Name(nameKey)); 54 | } 55 | 56 | public override bool Equals(object other) 57 | { 58 | var otherT = other as ValueNativeClassIns; 59 | if (otherT == null) 60 | return false; 61 | 62 | return otherT._data == _data; 63 | } 64 | 65 | public override int GetHashCode() 66 | { 67 | return _data.GetHashCode(); 68 | } 69 | 70 | public override string DebugString() 71 | { 72 | return string.Format("{0}(native class ins)", TypeName); 73 | } 74 | 75 | public override string TypeName 76 | { 77 | get { return _type.ToString(); } 78 | } 79 | 80 | 81 | public override ValueKind Kind 82 | { 83 | get { return ValueKind.NativeClassInstance; } 84 | } 85 | 86 | 87 | 88 | 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /Photon/Value/ValueNativeFunc.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Photon 3 | { 4 | 5 | class ValueNativeFunc : ValueFunc 6 | { 7 | NativeFunction _data; 8 | 9 | internal ValueNativeFunc(ObjectName name) 10 | : base( name ) 11 | { 12 | 13 | } 14 | 15 | internal ValueNativeFunc(ObjectName name, NativeFunction entry) 16 | : base(name) 17 | { 18 | _data = entry; 19 | } 20 | 21 | public override bool Equals(object other) 22 | { 23 | var otherT = other as ValueNativeFunc; 24 | if (otherT == null) 25 | return false; 26 | 27 | return otherT._data == _data; 28 | } 29 | 30 | public override int GetHashCode() 31 | { 32 | return _data.GetHashCode(); 33 | } 34 | 35 | internal override object Raw 36 | { 37 | get { return _data; } 38 | } 39 | 40 | public override string DebugString() 41 | { 42 | return string.Format("{0} id: {1}", Name, ID); 43 | } 44 | 45 | internal override bool Invoke(VMachine vm, int argCount, int receiverCount, ValueClosure closure) 46 | { 47 | // 外部调用不进行栈调整 48 | var preTop = vm.DataStack.Count - argCount; 49 | 50 | if (_data != null) 51 | { 52 | // 暂时不使用返回值, 可以通过前后top差判断出来 53 | _data(vm); 54 | } 55 | 56 | // 手工push值是按从左到右顺序, 和栈顺序反的, 需要倒置 57 | vm.DataStack.Reverse(preTop); 58 | 59 | // 去掉输入参数 60 | vm.DataStack.PopMulti(argCount); 61 | 62 | // 调整返回参 63 | vm.DataStack.Adjust(preTop, receiverCount ); 64 | 65 | return true; 66 | } 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /Photon/Value/ValueNil.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Photon 3 | { 4 | class ValueNil : Value 5 | { 6 | public override bool Equals(object other) 7 | { 8 | return (other as ValueNil) != null; 9 | } 10 | 11 | public override string DebugString() 12 | { 13 | return "(nil)"; 14 | } 15 | 16 | public override ValueKind Kind 17 | { 18 | get { return ValueKind.Nil; } 19 | } 20 | 21 | internal override object Raw 22 | { 23 | get { return null; } 24 | } 25 | 26 | 27 | public override int GetHashCode() 28 | { 29 | return base.GetHashCode(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Photon/Value/ValueObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Photon 4 | { 5 | class ValueObject : Value 6 | { 7 | internal override Value OperateUnary(Opcode code) 8 | { 9 | var con = Raw as IContainer; 10 | if (con == null) 11 | { 12 | throw new RuntimeException("Expect 'IContainer'"); 13 | } 14 | 15 | switch (code) 16 | { 17 | case Opcode.LEN: 18 | return new ValueInteger32(con.GetCount()); 19 | default: 20 | throw new RuntimeException("Unknown binary operator:" + code.ToString()); 21 | } 22 | } 23 | 24 | internal override void OperateSetKeyValue(Value k, Value v) 25 | { 26 | var con = Raw as IContainer; 27 | if (con == null) 28 | { 29 | throw new RuntimeException("Expect 'IContainer'"); 30 | } 31 | 32 | con.SetKeyValue(k, v); 33 | } 34 | 35 | internal override Value OperateGetKeyValue(Value k) 36 | { 37 | var con = Raw as IContainer; 38 | if (con == null) 39 | { 40 | throw new RuntimeException("Expect 'IContainer'"); 41 | } 42 | 43 | return con.GetKeyValue(k); 44 | } 45 | 46 | public override bool Visit(Value iter, DataStack ds) 47 | { 48 | var con = Raw as IContainer; 49 | if (con == null) 50 | { 51 | throw new RuntimeException("Expect 'IContainer'"); 52 | } 53 | 54 | ValueIterator iterObj = null; 55 | if (iter.Equals(Value.Nil)) 56 | { 57 | iterObj = con.GetIterator(); 58 | } 59 | else 60 | { 61 | iterObj = iter as ValueIterator; 62 | 63 | if ( iterObj == null ) 64 | { 65 | throw new RuntimeException("Expect 'Iterator"); 66 | } 67 | 68 | iterObj.Next(); 69 | } 70 | 71 | return iterObj.Iterate(ds); 72 | } 73 | 74 | 75 | 76 | 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /Photon/Value/ValuePhoClassIns.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Photon 4 | { 5 | class ValuePhoClassIns : ValueObject 6 | { 7 | ValuePhoClassType _type; 8 | 9 | Dictionary _memberVar = new Dictionary(); 10 | 11 | internal ValuePhoClassIns(ValuePhoClassType t) 12 | { 13 | _type = t; 14 | } 15 | 16 | 17 | internal override void OperateSetMemberValue(int nameKey, Value v) 18 | { 19 | Value tt; 20 | if (!_type.GetVirtualMember(nameKey, out tt)) 21 | { 22 | throw new RuntimeException("member not exists:" + _type.Key2Name(nameKey)); 23 | } 24 | 25 | if (tt.Kind == ValueKind.Func) 26 | { 27 | throw new RuntimeException("member function is immutable:" + _type.Key2Name(nameKey)); 28 | } 29 | 30 | 31 | _memberVar[nameKey] = v; 32 | } 33 | 34 | internal override Value OperateGetMemberValue(int nameKey) 35 | { 36 | // 从类型虚表中取 37 | Value tt; 38 | if (!_type.GetVirtualMember(nameKey, out tt)) 39 | { 40 | throw new RuntimeException("member not exists:" + _type.Key2Name(nameKey)); 41 | } 42 | 43 | // 函数优先返回 44 | if (tt.Kind == ValueKind.Func) 45 | { 46 | return tt; 47 | } 48 | 49 | 50 | Value existV; 51 | if (_memberVar.TryGetValue(nameKey, out existV)) 52 | { 53 | return existV; 54 | } 55 | 56 | return Value.Nil; 57 | } 58 | 59 | internal Value GetBaseValue(int nameKey) 60 | { 61 | // 从类型虚表中取 62 | Value tt; 63 | if (!_type.GetBaseMember(nameKey, out tt)) 64 | { 65 | throw new RuntimeException("member not exists:" + _type.Key2Name(nameKey)); 66 | } 67 | 68 | // 函数优先返回 69 | if (tt.Kind == ValueKind.Func) 70 | { 71 | return tt; 72 | } 73 | 74 | 75 | Value existV; 76 | if (_memberVar.TryGetValue(nameKey, out existV)) 77 | { 78 | return existV; 79 | } 80 | 81 | return Value.Nil; 82 | } 83 | 84 | public override string DebugString() 85 | { 86 | return string.Format("{0}(class ins)", TypeName); 87 | } 88 | 89 | public override string TypeName 90 | { 91 | get { return _type.Name.ToString(); } 92 | } 93 | 94 | 95 | public override ValueKind Kind 96 | { 97 | get { return ValueKind.ClassInstance; } 98 | } 99 | 100 | 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /Photon/Value/ValuePhoClassType.cs: -------------------------------------------------------------------------------- 1 | using MarkSerializer; 2 | using System.Collections.Generic; 3 | 4 | namespace Photon 5 | { 6 | class ValuePhoClassType : ValueClassType 7 | { 8 | Dictionary _member = new Dictionary(); 9 | 10 | internal ValuePhoClassType Parent { get; set; } 11 | internal int ParentID = 0; 12 | 13 | internal override int GetInheritLevel( ) 14 | { 15 | ValuePhoClassType classType = Parent; 16 | 17 | int total = 0; 18 | 19 | while (classType != null) 20 | { 21 | total++; 22 | 23 | classType = classType.Parent; 24 | } 25 | 26 | return total; 27 | } 28 | 29 | 30 | public ValuePhoClassType() 31 | { 32 | 33 | } 34 | 35 | internal ValuePhoClassType(Package pkg, ObjectName name) 36 | : base( name ) 37 | { 38 | _pkg = pkg; 39 | } 40 | 41 | public override void Serialize(BinarySerializer ser) 42 | { 43 | base.Serialize(ser); 44 | 45 | ser.Serialize(ref _member); 46 | ser.Serialize(ref ParentID); 47 | 48 | 49 | } 50 | 51 | internal override void OnSerializeDone(Executable exe) 52 | { 53 | Parent = exe.FindClassByPersistantID(ParentID); 54 | } 55 | 56 | internal void AddMethod( int nameKey, ValueFunc proc ) 57 | { 58 | _member.Add(nameKey, proc ); 59 | } 60 | 61 | internal void AddMemeber( int nameKey, string name ) 62 | { 63 | _member.Add(nameKey, new ValueNil()); 64 | } 65 | 66 | internal bool GetBaseMember(int nameKey, out Value v) 67 | { 68 | v = Value.Nil; 69 | 70 | if (Parent == null) 71 | return true; 72 | 73 | if (Parent._member.TryGetValue(nameKey, out v)) 74 | { 75 | return true; 76 | } 77 | 78 | return false; 79 | } 80 | 81 | internal bool GetVirtualMember( int nameKey, out Value v ) 82 | { 83 | v = Value.Nil; 84 | 85 | ValuePhoClassType ct = this; 86 | 87 | while( ct != null ) 88 | { 89 | if (ct._member.TryGetValue(nameKey, out v)) 90 | { 91 | return true; 92 | } 93 | 94 | ct = ct.Parent; 95 | } 96 | 97 | return false; 98 | } 99 | 100 | 101 | public override bool Equals(object v) 102 | { 103 | var other = v as ValuePhoClassType; 104 | if (other == null) 105 | return false; 106 | 107 | return _name.Equals(other._name); 108 | } 109 | 110 | public override int GetHashCode() 111 | { 112 | return _name.GetHashCode(); 113 | } 114 | 115 | internal override ValueObject CreateInstance() 116 | { 117 | return new ValuePhoClassIns( this ); 118 | } 119 | 120 | public override string DebugString() 121 | { 122 | return string.Format("{0}(class type)", TypeName); 123 | } 124 | 125 | public override string TypeName 126 | { 127 | get { return Name.ToString(); } 128 | } 129 | 130 | public override ValueKind Kind 131 | { 132 | get { return ValueKind.ClassType; } 133 | } 134 | 135 | 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /Photon/Value/ValueString.cs: -------------------------------------------------------------------------------- 1 |  2 | using MarkSerializer; 3 | namespace Photon 4 | { 5 | class ValueString : Value 6 | { 7 | string _data; 8 | 9 | public override void Serialize(BinarySerializer ser) 10 | { 11 | ser.Serialize(ref _data); 12 | } 13 | 14 | public ValueString() 15 | { 16 | 17 | } 18 | 19 | internal ValueString(string v) 20 | { 21 | _data = v; 22 | } 23 | 24 | public string RawValue 25 | { 26 | get { return _data; } 27 | } 28 | 29 | internal override object Raw 30 | { 31 | get { return _data; } 32 | } 33 | 34 | internal override Value OperateUnary(Opcode code) 35 | { 36 | switch (code) 37 | { 38 | case Opcode.LEN: 39 | return new ValueInteger32(_data.Length); 40 | default: 41 | throw new RuntimeException("Unknown binary operator:" + code.ToString()); 42 | } 43 | 44 | } 45 | 46 | public override bool Equals(object other) 47 | { 48 | var otherT = other as ValueString; 49 | if (otherT == null) 50 | return false; 51 | 52 | return otherT._data == _data; 53 | } 54 | 55 | public override int GetHashCode() 56 | { 57 | return _data.GetHashCode(); 58 | } 59 | 60 | public override string DebugString() 61 | { 62 | return string.Format("'{0}' (string)", _data); 63 | } 64 | 65 | public override ValueKind Kind 66 | { 67 | get { return ValueKind.String; } 68 | } 69 | 70 | internal override Value OperateBinary(Opcode code, Value other) 71 | { 72 | var a = RawValue; 73 | 74 | var b = Convertor.ValueToString(other); 75 | 76 | 77 | switch (code) 78 | { 79 | case Opcode.ADD: 80 | return new ValueString(a + b); 81 | default: 82 | throw new RuntimeException("Unknown binary operator:" + code.ToString()); 83 | } 84 | } 85 | } 86 | 87 | 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /PhotonCompiler/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /PhotonCompiler/FlagSet.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace PhotonCompiler 4 | { 5 | class FlagSet 6 | { 7 | Dictionary _options = new Dictionary(); 8 | List _args = new List(); 9 | 10 | public List Args 11 | { 12 | get { return _args; } 13 | } 14 | 15 | public string StringOption(string name) 16 | { 17 | string v; 18 | if (_options.TryGetValue(name, out v)) 19 | { 20 | return v; 21 | } 22 | 23 | return string.Empty; 24 | } 25 | 26 | public int IntOption(string name) 27 | { 28 | int r; 29 | 30 | int.TryParse(StringOption(name), out r); 31 | 32 | return r; 33 | } 34 | 35 | public bool BoolOption(string name) 36 | { 37 | bool r; 38 | 39 | bool.TryParse(StringOption(name), out r); 40 | 41 | return r; 42 | } 43 | 44 | public FlagSet(string[] args, int startIndex) 45 | { 46 | for (int i = startIndex; i < args.Length; i++) 47 | { 48 | var s = args[i]; 49 | 50 | if (s.StartsWith("--")) 51 | { 52 | if (_args.Count > 0) 53 | return; 54 | 55 | var kvstr = s.Split('='); 56 | if (kvstr.Length != 2) 57 | { 58 | return; 59 | } 60 | 61 | _options.Add(kvstr[0], kvstr[1]); 62 | } 63 | else if (s.StartsWith("-")) 64 | { 65 | if (_args.Count > 0) 66 | return; 67 | 68 | if (s.Length > 1) 69 | { 70 | _options.Add(s, "true"); 71 | } 72 | } 73 | else 74 | { 75 | _args.Add(s); 76 | } 77 | } 78 | } 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /PhotonCompiler/PhotonCompiler.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {0ACC0994-F7F2-4CE8-AC21-306712CF6A0A} 8 | Exe 9 | Properties 10 | PhotonCompiler 11 | pho 12 | v2.0 13 | 512 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {129399c8-6ed0-47da-8829-5781d54c2a48} 51 | PhotonLibrary 52 | 53 | 54 | 55 | 62 | -------------------------------------------------------------------------------- /PhotonCompiler/Program.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | 6 | namespace PhotonCompiler 7 | { 8 | 9 | partial class Program 10 | { 11 | static void Help( ) 12 | { 13 | Console.WriteLine("Usage:"); 14 | Console.WriteLine("pho command [arguments] pho files..."); 15 | Console.WriteLine("The commands are:"); 16 | Console.WriteLine(" compile compile packages and dependencies"); 17 | Console.WriteLine(" run compile and run"); 18 | } 19 | 20 | static int Main(string[] args) 21 | { 22 | if ( args.Length < 2 ) 23 | { 24 | Help(); 25 | return 1; 26 | } 27 | 28 | var mode = args[0]; 29 | var fs = new FlagSet(args, 1); 30 | bool needRun = false; 31 | 32 | switch( mode ) 33 | { 34 | case "compile": 35 | { 36 | needRun = false; 37 | } 38 | break; 39 | case "run": 40 | { 41 | needRun = true; 42 | 43 | } 44 | break; 45 | default: 46 | Help(); 47 | return 1; 48 | } 49 | int ret = 0; 50 | 51 | if ( Debugger.IsAttached ) 52 | { 53 | Run(fs.Args, needRun, fs.BoolOption("-l")); 54 | } 55 | else 56 | { 57 | try 58 | { 59 | Run(fs.Args, needRun, fs.BoolOption("-l")); 60 | } 61 | catch (Exception ex ) 62 | { 63 | Console.WriteLine(ex.ToString()); 64 | ret = 1; 65 | } 66 | } 67 | 68 | return ret; 69 | } 70 | 71 | static void Run( List files, bool run, bool debugInfo ) 72 | { 73 | if (files.Count == 0) 74 | return; 75 | 76 | var exe = Compiler.CompileFile(files[0]); 77 | 78 | if ( debugInfo ) 79 | { 80 | exe.DebugPrint(); 81 | } 82 | 83 | if ( run) 84 | { 85 | var vm = new VMachine(); 86 | 87 | vm.ShowDebugInfo = debugInfo; 88 | 89 | vm.Execute( exe ); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /PhotonCompiler/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PhotonCompiler")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("PhotonCompiler")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("9d30fdba-892a-4a3f-88c5-041b56a8fc67")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PhotonToy/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /PhotonToy/AssemblyLocation.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | using SharpLexer; 3 | using System.Collections.Generic; 4 | 5 | namespace PhotonToy 6 | { 7 | public struct AssemblyLocation 8 | { 9 | public int FuncID; 10 | public string FuncName; 11 | public TokenPos FuncDefPos; 12 | 13 | public int PC;// 汇编位置 14 | public TokenPos CodePos;//当前代码运行位置 15 | public List Commands; 16 | 17 | 18 | public bool IsDiff( AssemblyLocation other ) 19 | { 20 | return this.FuncID != other.FuncID || 21 | this.CodePos.SourceName != other.CodePos.SourceName; 22 | } 23 | 24 | public override bool Equals(object obj) 25 | { 26 | var other = (AssemblyLocation)obj; 27 | 28 | return this.FuncID == other.FuncID && 29 | this.PC == other.PC && 30 | this.CodePos.SourceName == other.CodePos.SourceName; 31 | } 32 | 33 | public override int GetHashCode() 34 | { 35 | return PC.GetHashCode() + FuncID.GetHashCode() + CodePos.SourceName.GetHashCode(); 36 | } 37 | 38 | public override string ToString() 39 | { 40 | return string.Format("{0} {1} {2}", FuncName, PC, CodePos.SourceName); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /PhotonToy/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace PhotonToy 5 | { 6 | static class Program 7 | { 8 | /// 9 | /// The main entry point for the application. 10 | /// 11 | [STAThread] 12 | static void Main(string[] args) 13 | { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault(false); 16 | Application.Run(new MainForm(args)); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /PhotonToy/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PhotonToy")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("PhotonToy")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6dcadc86-b96d-4ac1-82a4-745177012442")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PhotonToy/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18444 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace PhotonToy.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PhotonToy.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /PhotonToy/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18444 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace PhotonToy.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /PhotonToy/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PhotonToy/VMState.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | using System.Collections.Generic; 3 | 4 | namespace PhotonToy 5 | { 6 | class VMState 7 | { 8 | public AssemblyLocation Location; 9 | public List Register = new List(); 10 | public List DataStack = new List(); 11 | public List CallStack = new List(); 12 | public string RegPackage; 13 | 14 | public VMState(VMachine vm, string regpkg) 15 | { 16 | Location.FuncID = vm.CurrFrame.FuncID; 17 | Location.FuncName = vm.CurrFrame.FuncName; 18 | Location.PC = vm.CurrFrame.PC; 19 | Location.Commands = vm.CurrFrame.Commands; 20 | Location.FuncDefPos = vm.CurrFrame.FuncDefPos; 21 | RegPackage = regpkg; 22 | 23 | 24 | Location.CodePos = vm.CurrFrame.CodePos; 25 | 26 | if (string.IsNullOrEmpty(regpkg )) 27 | { 28 | for (int i = 0; i < vm.LocalReg.Count; i++) 29 | { 30 | Register.Add(vm.LocalReg.DebugString(i)); 31 | } 32 | } 33 | else 34 | { 35 | var pkg = vm.GetRuntimePackageByName(regpkg); 36 | for (int i = 0; i < pkg.Reg.Count; i++) 37 | { 38 | Register.Add(pkg.Reg.DebugString(i)); 39 | } 40 | } 41 | 42 | 43 | for (int i = 0; i < vm.DataStack.Count; i++) 44 | { 45 | DataStack.Add(vm.DataStack.DebugString(i)); 46 | } 47 | 48 | var arr = vm.CallStack.ToArray(); 49 | 50 | for (int i = 0; i < arr.Length; i++) 51 | { 52 | CallStack.Add(arr[i].DebugString()); 53 | } 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /PhotonToy/VarGuard.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace PhotonToy 3 | { 4 | class VarGuard 5 | { 6 | T _value; 7 | object _guard = new object(); 8 | 9 | public VarGuard(T init) 10 | { 11 | _value = init; 12 | } 13 | 14 | public T Value 15 | { 16 | get 17 | { 18 | lock (_guard) 19 | { 20 | return _value; 21 | } 22 | } 23 | 24 | set 25 | { 26 | lock (_guard) 27 | { 28 | _value = value; 29 | } 30 | } 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PhotonSharp 2 | 一个结构易读的完整脚本系统 3 | 4 | ## 语言特性 5 | 6 | * 无类型 7 | 8 | * 多返回值 9 | 10 | * 面向对象类支持, 无构造函数系统 11 | 12 | * 包系统支持 13 | 14 | * 自动生成C#类绑定。 15 | 16 | * C#类绑定实例化,成员函数及属性访问 17 | 18 | * 内建容器支持Array,Map 19 | 20 | * 通用的词法分析器 21 | 22 | * 抽象语法树 23 | 24 | * 序列化输出编译内容 25 | 26 | * 抽象内容加载器 27 | 28 | * 抽象虚拟机及指令 29 | 30 | ## 语言一览 31 | 32 | ```golang 33 | // 函数调用(支持多返回值) 34 | func mul( a, b ){ 35 | return a * b 36 | } 37 | 38 | func foo( a, b ){ 39 | return a + mul( b, 2 ) 40 | } 41 | 42 | var y = foo( 1, 2 ) 43 | 44 | // 变量交换 45 | var x, y = 1, 2 46 | x, y = y, x 47 | 48 | // for数字循环 49 | var x = 10 50 | for i = 1;i < 3;i=i+1 { 51 | x = x - 1 52 | } 53 | 54 | // 支持多层复杂闭包 55 | func foo( ){ 56 | var a = 2 57 | 58 | return func( x ){ 59 | var y = 1 60 | return x + y + a 61 | } 62 | } 63 | 64 | // 包支持 65 | import "MyPackage" 66 | 67 | var c = MyPackage.AddValue( 1, 2 ) 68 | 69 | 70 | // 面向对象支持 71 | class Animal { 72 | type 73 | } 74 | 75 | func Animal.foo( self ){ 76 | self.type = "animal" 77 | } 78 | 79 | func Animal.out( self ){ 80 | base.foo( self ) 81 | return self.type 82 | } 83 | 84 | 85 | class Cat : Animal{ 86 | 87 | } 88 | 89 | func Cat.foo( self ){ 90 | self.type = "cat" 91 | } 92 | 93 | 94 | var c = new(Cat) 95 | 96 | c.foo( ) 97 | 98 | var k = c.out( ) 99 | 100 | // 数组,映射支持 101 | 102 | var arr = [] 103 | 104 | arr.Add(1) 105 | 106 | arr[0] = 1 107 | 108 | var x = arr[0] 109 | 110 | var g = arr.Get(0) 111 | 112 | arr.Set(0, "hello") 113 | 114 | var count = arr.Count 115 | 116 | var v, ok = arr.TryGet(119) 117 | 118 | // 映射支持 119 | 120 | var sugar = { 121 | 1 : 12345, 122 | "hello": "world", 123 | } 124 | 125 | ``` 126 | 127 | 128 | # 调试器 129 | ![调试器](ScreenShot/debugger.png) 130 | 131 | ## 特性 132 | 133 | 基本的StepIn, StepOut, StepOver 指令调试 134 | 135 | 数据栈, 调用栈和本地,包寄存器查看 136 | 137 | # 第三方工程依赖 138 | https://github.com/davyxu/SharpLexer 139 | 140 | https://github.com/davyxu/MarkSerializer 141 | 142 | # 运行 143 | 144 | 设置工程工作目录为PhotonSharp\TestCase 145 | 146 | # 备注 147 | 148 | 感觉不错请star, 谢谢! 149 | 150 | 知乎: [http://www.zhihu.com/people/sunicdavy](http://www.zhihu.com/people/sunicdavy) 151 | -------------------------------------------------------------------------------- /ScreenShot/debugger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davyxu/PhotonSharp/05f9282c5eb305b7c9fb0783fe0fe5fbc841c041/ScreenShot/debugger.png -------------------------------------------------------------------------------- /TestCase/Array.pho: -------------------------------------------------------------------------------- 1 | var arr = new(Builtin.Array) 2 | 3 | arr.Add(199) 4 | 5 | arr[0] = 120 6 | 7 | var x = arr[0] 8 | 9 | var g = arr.Get(0) 10 | 11 | arr.Set(0, "hello") 12 | 13 | var count = len(arr) 14 | 15 | var v, ok = arr.TryGet(119) 16 | 17 | var sugar = [1,2] 18 | 19 | var sugarlen = len(sugar) 20 | 21 | var sugar1 = sugar[0] 22 | 23 | var sugar2 = sugar[1] -------------------------------------------------------------------------------- /TestCase/Class.pho: -------------------------------------------------------------------------------- 1 | 2 | class Animal { 3 | 4 | Name 5 | 6 | Speed 7 | } 8 | 9 | func Animal.Do( self ){ 10 | 11 | self.Speed = 5 12 | 13 | return self.Speed, self.Name 14 | 15 | } 16 | 17 | func neAnimal( name ){ 18 | 19 | var self = new(Animal) 20 | self.Name = name 21 | return self 22 | } 23 | 24 | var a = neAnimal( "cat" ) 25 | 26 | var h, n = a.Do( ) -------------------------------------------------------------------------------- /TestCase/ClassInherit.pho: -------------------------------------------------------------------------------- 1 | 2 | class Animal { 3 | type 4 | } 5 | 6 | func Animal.foo( self ){ 7 | self.type = "animal" 8 | } 9 | 10 | func Animal.out( self ){ 11 | return self.type 12 | } 13 | 14 | 15 | class Cat : Animal{ 16 | 17 | } 18 | 19 | func Cat.foo( self ){ 20 | self.type = "cat" 21 | } 22 | 23 | func Cat.callParent( self ){ 24 | base.foo( self ) 25 | return self.type 26 | } 27 | 28 | 29 | var c = new(Cat) 30 | 31 | c.foo( ) 32 | 33 | var k = c.out( ) 34 | 35 | var p = c.callParent( ) -------------------------------------------------------------------------------- /TestCase/Closure.pho: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | func foo( ){ 5 | var a = 2 6 | 7 | return func( x ){ 8 | var y = 1 9 | return x + y + a 10 | } 11 | } 12 | 13 | 14 | var c = foo( ) 15 | var x = c( 9 ) -------------------------------------------------------------------------------- /TestCase/ComplexClosure.pho: -------------------------------------------------------------------------------- 1 | 2 | func foo( ){ 3 | var a = 1 4 | 5 | return func( ){ 6 | var b = 2 7 | 8 | return func( x ){ 9 | 10 | var c = 3 11 | 12 | return a + b + c + x 13 | } 14 | } 15 | 16 | } 17 | 18 | 19 | 20 | 21 | var c = foo( ) 22 | 23 | var x = c() 24 | 25 | var y = x( 9 ) -------------------------------------------------------------------------------- /TestCase/Constant.pho: -------------------------------------------------------------------------------- 1 | const a = 2 * (5 + 6) 2 | var b = a -------------------------------------------------------------------------------- /TestCase/DataStackBalance.pho: -------------------------------------------------------------------------------- 1 | import "DataStackBalanceTest" 2 | 3 | // 将输入数加上一个返回 4 | func ret2( x ){ 5 | return x, 1 6 | } 7 | 8 | func less( ){ 9 | 10 | return 2, 4 11 | } 12 | 13 | // 在上一级上继续返回 14 | func more( ){ 15 | return ret2(3), 4 16 | } 17 | 18 | 19 | // 填充返回值 20 | var a, b, c = less() 21 | 22 | // 丢弃返回值 23 | var d, e = more() 24 | 25 | 26 | 27 | var m, n = DataStackBalanceTest.native_less( ) 28 | 29 | var p, q = DataStackBalanceTest.native_more( ) -------------------------------------------------------------------------------- /TestCase/Delegate.pho: -------------------------------------------------------------------------------- 1 | import "DelegateTest" 2 | var a = DelegateTest.add( 1, 2 ) 3 | 4 | -------------------------------------------------------------------------------- /TestCase/Execute.pho: -------------------------------------------------------------------------------- 1 | 2 | func foo( a , b ){ 3 | return a + b, new(Builtin.Array) 4 | } -------------------------------------------------------------------------------- /TestCase/ForLoop.pho: -------------------------------------------------------------------------------- 1 | var m = 0 2 | for ;m<2; { 3 | m++ 4 | } 5 | 6 | 7 | var n = 0 8 | for ;;n=n+1 { 9 | if n > 2{ 10 | break 11 | } 12 | } 13 | 14 | 15 | var p = 0 16 | for ;p < 2;p=p+1 { 17 | 18 | } 19 | 20 | 21 | var q = 10 22 | for i = 1;i < 3;i=i+1 { 23 | q = q - 1 24 | } 25 | 26 | 27 | var arr = [ 1, 2] 28 | 29 | var arr2 = [] 30 | 31 | for k, v in arr 32 | { 33 | arr2.Add( v ) 34 | } 35 | 36 | var larr = len(arr2) 37 | var arrm1 = arr2[0] 38 | var arrm2 = arr2[1] 39 | 40 | 41 | 42 | var dict = { 43 | 1 : 12345, 44 | "hello": 100, 45 | } 46 | 47 | 48 | var dict2 = {} 49 | 50 | for k, v in dict 51 | { 52 | dict2[k] = v 53 | } 54 | 55 | var ldict = len(dict2) 56 | var dictm1 = dict2[1] 57 | var dictm2 = dict2["hello"] 58 | -------------------------------------------------------------------------------- /TestCase/If.pho: -------------------------------------------------------------------------------- 1 | var x = 1 2 | var y 3 | if x >= 1 { 4 | var c = 5 5 | y = c 6 | }else{ 7 | y = 2 8 | } -------------------------------------------------------------------------------- /TestCase/Map.pho: -------------------------------------------------------------------------------- 1 | var map = new(Builtin.Map) 2 | var k = "hello" 3 | map[k] = 1678 4 | var x = map["hello"] 5 | var c = len(map) 6 | 7 | 8 | var w = "world" 9 | 10 | var sugar = { 11 | 1 : 12345, 12 | "hello": w, 13 | } 14 | 15 | var sugarlen = len(sugar) 16 | var sugarA = sugar[1] 17 | var sugarB = sugar["hello"] 18 | -------------------------------------------------------------------------------- /TestCase/Math.pho: -------------------------------------------------------------------------------- 1 | 2 | var a = 1 3 | a = -a 4 | 5 | // 强制类型转换 6 | var b = int64(5.0) 7 | 8 | // ANSI 隐式类型转换 9 | var c = 1 + 2.0 10 | 11 | var s = "hello " + "world" 12 | 13 | var m = 0 14 | m++ 15 | m-=2 16 | -------------------------------------------------------------------------------- /TestCase/MultiCall.pho: -------------------------------------------------------------------------------- 1 | 2 | func foo( a, b ){ 3 | 4 | return a + mul( 7, 2 ) 5 | } 6 | 7 | func mul( a, b ){ 8 | return a * b 9 | } 10 | 11 | 12 | var y = foo( 1, 2 ) -------------------------------------------------------------------------------- /TestCase/MyPackage/Add.pho: -------------------------------------------------------------------------------- 1 | 2 | func AddValue( a, b ){ 3 | 4 | return a + b 5 | } -------------------------------------------------------------------------------- /TestCase/MyPackage/Entry.pho: -------------------------------------------------------------------------------- 1 | var entry = "here" -------------------------------------------------------------------------------- /TestCase/MyPackage/Sub.pho: -------------------------------------------------------------------------------- 1 | 2 | func SubValue( a, b ){ 3 | 4 | return a - b 5 | } -------------------------------------------------------------------------------- /TestCase/NativeClass.pho: -------------------------------------------------------------------------------- 1 | 2 | 3 | // Native类访问 4 | var x = new(NativeClassTest.NativeClass) 5 | 6 | // 'cat' 7 | var b = x.foo(2016) 8 | 9 | // C#的out出参作为语言的多返回值 10 | var c, d = x.outAsRetValue(10, "a") 11 | 12 | // 手动绑定 13 | var e = x.manualBinding(567) 14 | 15 | // 访问C#的属性 16 | var f = x.MyProp 17 | 18 | // 设置C#的属性 19 | x.MyProp = "MP" -------------------------------------------------------------------------------- /TestCase/Package.pho: -------------------------------------------------------------------------------- 1 | import "MyPackage" 2 | 3 | // add.pho 4 | var c = MyPackage.AddValue( 1, 2 ) 5 | 6 | // sub.pho 7 | var s = MyPackage.SubValue( 5, 2 ) 8 | 9 | -------------------------------------------------------------------------------- /TestCase/Scope.pho: -------------------------------------------------------------------------------- 1 | var a = 1 2 | 3 | func foo( a ){ 4 | 5 | var x = a 6 | 7 | return x 8 | } 9 | 10 | var c = foo( a ) -------------------------------------------------------------------------------- /TestCase/SwapVar.pho: -------------------------------------------------------------------------------- 1 | var x, y = 1, 2 2 | x, y = y, x -------------------------------------------------------------------------------- /TestCase/Test.pho: -------------------------------------------------------------------------------- 1 | func printf( fmt, param ... ) 2 | { 3 | 4 | } -------------------------------------------------------------------------------- /TestCase/WhileLoop.pho: -------------------------------------------------------------------------------- 1 | var x = 1 2 | 3 | while x < 3 { 4 | x = x + 1 5 | } -------------------------------------------------------------------------------- /UnitTest/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /UnitTest/BasicTest.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | 3 | namespace UnitTest 4 | { 5 | partial class Program 6 | { 7 | static void TestBasic() 8 | { 9 | new TestBox().RunFile("Math.pho") 10 | .CheckGlobalVarMatchValue("a", -1) 11 | .CheckGlobalVarMatchValue("b", (System.Int64)5) 12 | .CheckGlobalVarMatchValue("c", 3.0f) 13 | .CheckGlobalVarMatchValue("m", -1) 14 | .CheckGlobalVarMatchValue("s", "hello world"); 15 | 16 | new TestBox().RunFile("SwapVar.pho") 17 | .CheckGlobalVarMatchValue("x", 2) 18 | .CheckGlobalVarMatchValue("y", 1); 19 | 20 | new TestBox().RunFile("Constant.pho") 21 | .CheckGlobalVarMatchValue("b", 22); 22 | 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /UnitTest/ClassTest.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | 3 | namespace UnitTest 4 | { 5 | partial class Program 6 | { 7 | static void TestClass() 8 | { 9 | new TestBox().RunFile("Class.pho") 10 | .CheckGlobalVarMatchKind("a", ValueKind.ClassInstance) 11 | .CheckGlobalVarMatchValue("h", 5) 12 | .CheckGlobalVarMatchValue("n", "cat"); 13 | 14 | new TestBox().RunFile("ClassInherit.pho") 15 | .CheckGlobalVarMatchKind("c", ValueKind.ClassInstance) 16 | .CheckGlobalVarMatchValue("k", "cat") 17 | .CheckGlobalVarMatchValue("p", "animal"); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /UnitTest/ContainerTest.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | using System.Collections.Generic; 3 | 4 | namespace UnitTest 5 | { 6 | 7 | 8 | 9 | partial class Program 10 | { 11 | static void TestContainer() 12 | { 13 | { 14 | var testbox = new TestBox(); 15 | 16 | testbox.RunFile("Map.pho") 17 | .CheckGlobalVarMatchKind("map", ValueKind.NativeClassInstance) 18 | .CheckGlobalVarMatchValue("x", 1678) 19 | .CheckGlobalVarMatchValue("c", 1) 20 | .CheckGlobalVarMatchKind("sugar", ValueKind.NativeClassInstance) 21 | .CheckGlobalVarMatchValue("sugarlen", 2) 22 | .CheckGlobalVarMatchValue("sugarA", 12345) 23 | .CheckGlobalVarMatchValue("sugarB", "world"); 24 | } 25 | 26 | { 27 | var testbox = new TestBox(); 28 | 29 | testbox.RunFile("Array.pho") 30 | .CheckGlobalVarMatchKind("arr", ValueKind.NativeClassInstance) 31 | .CheckGlobalVarMatchValue("x", 120) 32 | .CheckGlobalVarMatchValue("g", 120) 33 | .CheckGlobalVarMatchValue("count", 1) 34 | .CheckGlobalVarMatchKind("v", ValueKind.Nil) 35 | .CheckGlobalVarMatchValue("ok", false) 36 | .CheckGlobalVarMatchKind("sugar", ValueKind.NativeClassInstance) 37 | .CheckGlobalVarMatchValue("sugarlen", 2) 38 | .CheckGlobalVarMatchValue("sugar1", 1) 39 | .CheckGlobalVarMatchValue("sugar2", 2); 40 | } 41 | 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /UnitTest/DataStackBalanceTest.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | using System.Reflection; 3 | 4 | namespace UnitTest 5 | { 6 | public class DataStackBalanceTest 7 | { 8 | public static int native_less() 9 | { 10 | return 9; 11 | } 12 | 13 | public static void native_more(out int out1, out int out2, out int out3) 14 | { 15 | out1 = 2; 16 | out2 = 4; 17 | out3 = 6; 18 | } 19 | } 20 | 21 | 22 | partial class Program 23 | { 24 | 25 | static void TestDataStackBalance() 26 | { 27 | if (GenAllFile) 28 | { 29 | WrapperCodeGenerator.GenerateClass(typeof(DataStackBalanceTest), "UnitTest", "../UnitTest/DataStackBalanceTestWrapper.cs"); 30 | } 31 | 32 | 33 | new TestBox().RegisterRunFile(delegate(Executable exe) 34 | { 35 | exe.RegisterNativeClass(Assembly.GetEntryAssembly(), 36 | "UnitTest.DataStackBalanceTestWrapper", 37 | "DataStackBalanceTest"); 38 | },"DataStackBalance.pho") 39 | .CheckGlobalVarMatchValue("a", 2) 40 | .CheckGlobalVarMatchValue("b", 4) 41 | .CheckGlobalVarMatchKind("c", ValueKind.Nil) 42 | .CheckGlobalVarMatchValue("e", 1) 43 | .CheckGlobalVarMatchValue("m", 9) 44 | .CheckGlobalVarMatchKind("n", ValueKind.Nil) 45 | .CheckGlobalVarMatchValue("p", 2) 46 | .CheckGlobalVarMatchValue("q", 4); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /UnitTest/DataStackBalanceTestWrapper.cs: -------------------------------------------------------------------------------- 1 | // Generated by github.com/davyxu/PhotonSharp 2 | // DO NOT EDIT!! 3 | using Photon; 4 | using System; 5 | 6 | namespace UnitTest 7 | { 8 | [NativeWrapperClass(typeof(UnitTest.DataStackBalanceTest))] 9 | public class DataStackBalanceTestWrapper 10 | { 11 | [NativeEntry(NativeEntryType.StaticFunc)] 12 | public static int native_less( VMachine vm ) 13 | { 14 | var phoRetArg = UnitTest.DataStackBalanceTest.native_less( ); 15 | 16 | vm.DataStack.PushInteger32( phoRetArg ); 17 | 18 | return 1; 19 | } 20 | 21 | [NativeEntry(NativeEntryType.StaticFunc)] 22 | public static int native_more( VMachine vm ) 23 | { 24 | Int32 out1 = default(Int32); 25 | Int32 out2 = default(Int32); 26 | Int32 out3 = default(Int32); 27 | UnitTest.DataStackBalanceTest.native_more( out out1, out out2, out out3 ); 28 | 29 | vm.DataStack.PushInteger32( out1 ); 30 | vm.DataStack.PushInteger32( out2 ); 31 | vm.DataStack.PushInteger32( out3 ); 32 | 33 | return 3; 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /UnitTest/DelegateExecuteTest.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | 3 | namespace UnitTest 4 | { 5 | public class DelegateTest 6 | { 7 | [NativeEntry(NativeEntryType.StaticFunc, "add")] 8 | public static int AddValue(VMachine vm) 9 | { 10 | var a = vm.DataStack.GetInteger32(0); 11 | var b = vm.DataStack.GetInteger32(1); 12 | 13 | vm.DataStack.PushInteger32(a + b); 14 | 15 | return 1; 16 | } 17 | } 18 | 19 | 20 | partial class Program 21 | { 22 | static void TestDelegateExecute() 23 | { 24 | new TestBox().RegisterRunFile(delegate(Executable exe) 25 | { 26 | 27 | exe.RegisterNativeClass(typeof(DelegateTest), "DelegateTest"); 28 | 29 | }, "Delegate.pho") 30 | .CheckGlobalVarMatchValue("a", 3); 31 | 32 | 33 | { 34 | var testbox = new TestBox(); 35 | testbox.CompileFile("Execute.pho"); 36 | //testbox.VM.ShowDebugInfo = Test; 37 | 38 | var retValue = testbox.VM.Execute(testbox.Exe, "main", "foo", new object[] { 1, 2 }, 2); 39 | 40 | if ( retValue.Length != 2 ) 41 | { 42 | testbox.Error("ret value not match"); 43 | } 44 | 45 | if ( (System.Int32)retValue[0] != 3 ) 46 | { 47 | testbox.Error("ret value not match"); 48 | } 49 | 50 | if (!retValue[1].GetType().IsClass) 51 | { 52 | testbox.Error("ret value not match"); 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /UnitTest/FlowTest.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | 3 | namespace UnitTest 4 | { 5 | partial class Program 6 | { 7 | static void TestFlow() 8 | { 9 | new TestBox().RunFile("ForLoop.pho") 10 | .CheckGlobalVarMatchValue("m", 2) 11 | .CheckGlobalVarMatchValue("n", 3) 12 | .CheckGlobalVarMatchValue("p", 2) 13 | .CheckGlobalVarMatchValue("q", 8) 14 | .CheckGlobalVarMatchValue("larr", 2) 15 | .CheckGlobalVarMatchValue("arrm1", 1) 16 | .CheckGlobalVarMatchValue("arrm2", 2) 17 | .CheckGlobalVarMatchValue("ldict", 2) 18 | .CheckGlobalVarMatchValue("dictm1", 12345) 19 | .CheckGlobalVarMatchValue("dictm2", 100); 20 | 21 | new TestBox().RunFile("If.pho") 22 | .CheckGlobalVarMatchValue("x", 1) 23 | .CheckGlobalVarMatchValue("y", 5); 24 | 25 | new TestBox().RunFile("WhileLoop.pho") 26 | .CheckGlobalVarMatchValue("x", 3); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /UnitTest/FuncPackageTest.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | 3 | namespace UnitTest 4 | { 5 | partial class Program 6 | { 7 | static void TestFuncPackage() 8 | { 9 | new TestBox().RunFile("Scope.pho") 10 | .CheckGlobalVarMatchValue("a", 1) 11 | .CheckGlobalVarMatchValue("c", 1); 12 | 13 | new TestBox().RunFile("MultiCall.pho") 14 | .CheckGlobalVarMatchValue("y", 15); 15 | 16 | new TestBox().RunFile("Closure.pho") 17 | .CheckGlobalVarMatchKind("c", ValueKind.Func) 18 | .CheckGlobalVarMatchValue("x", 12); 19 | 20 | new TestBox().RunFile("ComplexClosure.pho") 21 | .CheckGlobalVarMatchKind("c", ValueKind.Func) 22 | .CheckGlobalVarMatchKind("x", ValueKind.Func) 23 | .CheckGlobalVarMatchValue("y", 15); 24 | 25 | new TestBox().RunFile("Package.pho") 26 | .CheckGlobalVarMatchValue("c", 3) 27 | .CheckGlobalVarMatchValue("s", 3); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /UnitTest/NativeClassTest.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | using System.Reflection; 3 | 4 | namespace UnitTest 5 | { 6 | class NativeClass 7 | { 8 | public string MyProp 9 | { 10 | get; 11 | set; 12 | } 13 | 14 | public string outAsRetValue(int a, string c, out int b) 15 | { 16 | b = 89; 17 | 18 | return "xx"; 19 | } 20 | 21 | 22 | public string foo(int a) 23 | { 24 | return "cat"; 25 | } 26 | 27 | public NativeClass() 28 | { 29 | MyProp = "HP"; 30 | } 31 | 32 | // 手动额外绑定 33 | [NativeEntry(NativeEntryType.ClassMethod, "manualBinding")] 34 | public static int VMFoo(VMachine vm) 35 | { 36 | var instance = vm.DataStack.GetNativeInstance(0); 37 | 38 | var a = vm.DataStack.GetInteger32(1); 39 | 40 | vm.DataStack.PushString("wa"); 41 | 42 | return 1; 43 | } 44 | } 45 | 46 | 47 | partial class Program 48 | { 49 | static void TestNativeClass() 50 | { 51 | if (GenAllFile) 52 | { 53 | WrapperCodeGenerator.GenerateClass(typeof(NativeClass), "UnitTest", "../UnitTest/NativeClassWrapper.cs"); 54 | } 55 | 56 | new TestBox().RegisterRunFile(delegate(Executable exe) 57 | { 58 | exe.RegisterNativeClass(Assembly.GetExecutingAssembly(), "UnitTest.NativeClassWrapper", "NativeClassTest"); 59 | }, 60 | "NativeClass.pho") 61 | .CheckGlobalVarMatchKind("x", ValueKind.NativeClassInstance) 62 | .CheckGlobalVarMatchValue("b", "cat") 63 | .CheckGlobalVarMatchValue("c", 89) 64 | .CheckGlobalVarMatchValue("d", "xx") 65 | .CheckGlobalVarMatchValue("e", "wa") 66 | .CheckGlobalVarMatchValue("f", "HP"); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /UnitTest/NativeClassWrapper.cs: -------------------------------------------------------------------------------- 1 | // Generated by github.com/davyxu/PhotonSharp 2 | // DO NOT EDIT!! 3 | using Photon; 4 | using System; 5 | 6 | namespace UnitTest 7 | { 8 | [NativeWrapperClass(typeof(UnitTest.NativeClass))] 9 | public class NativeClassWrapper 10 | { 11 | [NativeEntry(NativeEntryType.Property)] 12 | public static void MyProp(object phoIns, ref object value, bool isGet ) 13 | { 14 | var phoClassIns = phoIns as NativeClass; 15 | 16 | if (isGet) 17 | { 18 | value = Convertor.StringToValue(phoClassIns.MyProp); 19 | } 20 | else 21 | { 22 | phoClassIns.MyProp = Convertor.ValueToString(value); 23 | } 24 | } 25 | 26 | [NativeEntry(NativeEntryType.ClassMethod)] 27 | public static int outAsRetValue( VMachine vm ) 28 | { 29 | var phoClassIns = vm.DataStack.GetNativeInstance(0); 30 | 31 | var a = vm.DataStack.GetInteger32(1); 32 | var c = vm.DataStack.GetString(2); 33 | 34 | Int32 b = default(Int32); 35 | var phoRetArg = phoClassIns.outAsRetValue( a, c, out b ); 36 | 37 | vm.DataStack.PushInteger32( b ); 38 | vm.DataStack.PushString( phoRetArg ); 39 | 40 | return 2; 41 | } 42 | 43 | [NativeEntry(NativeEntryType.ClassMethod)] 44 | public static int foo( VMachine vm ) 45 | { 46 | var phoClassIns = vm.DataStack.GetNativeInstance(0); 47 | 48 | var a = vm.DataStack.GetInteger32(1); 49 | 50 | var phoRetArg = phoClassIns.foo( a ); 51 | 52 | vm.DataStack.PushString( phoRetArg ); 53 | 54 | return 1; 55 | } 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /UnitTest/Program.cs: -------------------------------------------------------------------------------- 1 | namespace UnitTest 2 | { 3 | 4 | partial class Program 5 | { 6 | static void Main(string[] args) 7 | { 8 | TestCase(); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /UnitTest/TestCase.cs: -------------------------------------------------------------------------------- 1 | using Photon; 2 | using System.IO; 3 | 4 | namespace UnitTest 5 | { 6 | partial class Program 7 | { 8 | static bool GenAllFile = false; 9 | 10 | static void TestCase() 11 | { 12 | Directory.SetCurrentDirectory("../../../TestCase"); 13 | 14 | if (GenAllFile) 15 | { 16 | Compiler.GenerateBuiltinFiles(); 17 | } 18 | 19 | TestBasic(); 20 | 21 | TestDataStackBalance(); 22 | 23 | TestFuncPackage(); 24 | 25 | TestDelegateExecute(); 26 | 27 | TestFlow(); 28 | 29 | TestClass(); 30 | 31 | TestNativeClass(); 32 | 33 | TestContainer(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /UnitTest/UnitTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {0AB986D1-0226-417A-A87D-ECDF6C020282} 8 | Exe 9 | Properties 10 | UnitTest 11 | UnitTest 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Code 49 | 50 | 51 | 52 | 53 | 54 | 55 | Code 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | {a853de6b-97d7-4a0f-8561-940a4f267c02} 67 | MarkSerializer 68 | 69 | 70 | {129399c8-6ed0-47da-8829-5781d54c2a48} 71 | PhotonLibrary 72 | 73 | 74 | 75 | 76 | 77 | 78 | 85 | --------------------------------------------------------------------------------