예제 #1
0
 private KecaknoahScriptMethodInfo PrecompileFunction(KecaknoahFunctionAstNode ast)
 {
     var al = ast.Parameters;
     var result = new KecaknoahScriptMethodInfo(ast.Name, ast.Parameters.Count, ast.AllowsVariableArguments);
     result.Codes = new KecaknoahIL();
     var b = PrecompileBlock(ast.Children, "").ToList();
     foreach (var i in b.Where(p => p.Type == KecaknoahILCodeType.Jump || p.Type == KecaknoahILCodeType.FalseJump || p.Type == KecaknoahILCodeType.TrueJump))
     {
         i.IntegerValue = b.FindIndex(p => p.Type == KecaknoahILCodeType.Label && p.StringValue == i.StringValue);
     }
     foreach (var i in b.Where(p => p.Type == KecaknoahILCodeType.Label)) i.Type = KecaknoahILCodeType.Nop;
     if (b.Any(p => (p.Type == KecaknoahILCodeType.Jump || p.Type == KecaknoahILCodeType.FalseJump || p.Type == KecaknoahILCodeType.TrueJump) && p.IntegerValue == -1))
     {
         throw new InvalidOperationException("対応していないラベルがあります");
     }
     result.Codes.PushCodes(b);
     foreach (var i in result.Codes.Codes)
     {
         if (i.Type == KecaknoahILCodeType.LoadObject && al.Contains(i.StringValue))
         {
             i.Type = KecaknoahILCodeType.PushArgument;
             i.IntegerValue = al.IndexOf(i.StringValue);
         }
     }
     return result;
 }
예제 #2
0
        private KecaknoahScriptMethodInfo PrecompileFunction(KecaknoahFunctionAstNode ast)
        {
            var al     = ast.Parameters;
            var result = new KecaknoahScriptMethodInfo(ast.Name, ast.Parameters.Count, ast.AllowsVariableArguments);

            result.Codes = new KecaknoahIL();
            var b = PrecompileBlock(ast.Children, "").ToList();

            foreach (var i in b.Where(p => p.Type == KecaknoahILCodeType.Jump || p.Type == KecaknoahILCodeType.FalseJump || p.Type == KecaknoahILCodeType.TrueJump))
            {
                i.IntegerValue = b.FindIndex(p => p.Type == KecaknoahILCodeType.Label && p.StringValue == i.StringValue);
            }
            foreach (var i in b.Where(p => p.Type == KecaknoahILCodeType.Label))
            {
                i.Type = KecaknoahILCodeType.Nop;
            }
            if (b.Any(p => (p.Type == KecaknoahILCodeType.Jump || p.Type == KecaknoahILCodeType.FalseJump || p.Type == KecaknoahILCodeType.TrueJump) && p.IntegerValue == -1))
            {
                throw new InvalidOperationException("対応していないラベルがあります");
            }
            result.Codes.PushCodes(b);
            foreach (var i in result.Codes.Codes)
            {
                if (i.Type == KecaknoahILCodeType.LoadObject && al.Contains(i.StringValue))
                {
                    i.Type         = KecaknoahILCodeType.PushArgument;
                    i.IntegerValue = al.IndexOf(i.StringValue);
                }
            }
            return(result);
        }
예제 #3
0
파일: Program.cs 프로젝트: utgwkk/Kecaknoah
 static IList<string> AssembleFunction(KecaknoahScriptMethodInfo info)
 {
     var result = new List<string>();
     result.Add($".function {info.Name}");
     foreach (var i in info.Codes.Codes)
     {
         result.Add("  " + i.ToString());
     }
     return result;
 }
예제 #4
0
 /// <summary>
 /// メソッドを追加します。
 /// </summary>
 /// <param name="method">追加するメソッド</param>
 internal void AddClassMethod(KecaknoahScriptMethodInfo method)
 {
     classMethods.Add(method);
 }
예제 #5
0
 /// <summary>
 /// メソッドを追加します。
 /// </summary>
 /// <param name="method">追加するメソッド</param>
 internal void AddInstanceMethod(KecaknoahScriptMethodInfo method)
 {
     methods.Add(method);
 }
예제 #6
0
        private IList <KecaknoahILCode> PrecompileExpression(KecaknoahAstNode node)
        {
            var result = new List <KecaknoahILCode>();

            if (node.Type != KecaknoahAstNodeType.Expression)
            {
                throw new ArgumentException("ASTが式でない件について");
            }
            var en = node as KecaknoahExpressionAstNode;

            if (en is KecaknoahBinaryExpressionAstNode)
            {
                var exp = en as KecaknoahBinaryExpressionAstNode;
                result.AddRange(PrecompileBinaryExpression(exp));
            }
            else if (en is KecaknoahFactorExpressionAstNode)
            {
                var exp = en as KecaknoahFactorExpressionAstNode;
                switch (exp.FactorType)
                {
                case KecaknoahFactorType.IntegerValue:
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.PushInteger, IntegerValue = exp.IntegerValue
                    });
                    break;

                case KecaknoahFactorType.SingleValue:
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.PushDouble, FloatValue = exp.SingleValue
                    });
                    break;

                case KecaknoahFactorType.DoubleValue:
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.PushDouble, FloatValue = exp.DoubleValue
                    });
                    break;

                case KecaknoahFactorType.StringValue:
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.PushString, StringValue = exp.StringValue
                    });
                    break;

                case KecaknoahFactorType.BooleanValue:
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.PushBoolean, BooleanValue = exp.BooleanValue
                    });
                    break;

                case KecaknoahFactorType.Nil:
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.PushNil
                    });
                    break;

                case KecaknoahFactorType.Identifer:
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.LoadObject, StringValue = exp.StringValue
                    });
                    break;

                case KecaknoahFactorType.ParenExpression:
                    result.AddRange(PrecompileExpression(exp.ExpressionNode));
                    break;

                case KecaknoahFactorType.CoroutineResume:
                    if (exp.BooleanValue)
                    {
                        // state = coresume(cor, val)
                        result.AddRange(PrecompileExpression(exp.ExpressionNode));
                    }
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.ResumeCoroutine, StringValue = exp.StringValue, BooleanValue = exp.BooleanValue
                    });
                    break;

                case KecaknoahFactorType.Array:
                    foreach (var i in exp.ElementNodes)
                    {
                        result.AddRange(PrecompileExpression(i));
                    }
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.MakeArray, IntegerValue = exp.ElementNodes.Count
                    });
                    break;

                case KecaknoahFactorType.Lambda:
                    var lma  = exp.ElementNodes.Select(p => ((KecaknoahFactorExpressionAstNode)p).StringValue).ToList();
                    var name = $"Lambda-{Guid.NewGuid().ToString().Substring(0, 17)}";
                    var func = new KecaknoahScriptMethodInfo(name);
                    var eil  = PrecompileExpression(exp.ExpressionNode);
                    eil.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.Return
                    });
                    foreach (var i in eil.Where(p => p.Type == KecaknoahILCodeType.LoadObject && lma.Contains(p.StringValue)))
                    {
                        i.Type         = KecaknoahILCodeType.PushArgument;
                        i.IntegerValue = lma.IndexOf(i.StringValue);
                    }
                    func.Codes = new KecaknoahIL();
                    func.Codes.PushCodes(eil);
                    if (cuc.Count == 0)
                    {
                        current.methods.Add(func);
                    }
                    else
                    {
                        cuc.Peek().AddInstanceMethod(func);
                    }
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.LoadObject, StringValue = name
                    });
                    break;
                }
            }
            else if (en is KecaknoahArgumentCallExpressionAstNode)
            {
                var exp = en as KecaknoahArgumentCallExpressionAstNode;
                if (exp.Target is KecaknoahFactorExpressionAstNode && (exp.Target as KecaknoahFactorExpressionAstNode).FactorType == KecaknoahFactorType.VariableArguments)
                {
                    //vargs
                    foreach (var arg in exp.Arguments)
                    {
                        result.AddRange(PrecompileExpression(arg));
                    }
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.LoadVarg, IntegerValue = exp.Arguments.Count
                    });
                }
                else
                {
                    if (exp.ExpressionType == KecaknoahOperatorType.IndexerAccess)
                    {
                        result.AddRange(PrecompileIndexerCall(exp));
                    }
                    else
                    {
                        result.AddRange(PrecompileFunctionCall(exp));
                    }
                }
            }
            else if (en is KecaknoahMemberAccessExpressionAstNode)
            {
                var exp = en as KecaknoahMemberAccessExpressionAstNode;
                result.AddRange(PrecompileExpression(exp.Target));
                result.Add(new KecaknoahILCode {
                    Type = KecaknoahILCodeType.LoadMember, StringValue = exp.MemberName
                });
            }
            else if (en is KecaknoahPrimaryExpressionAstNode)
            {
                var exp = en as KecaknoahPrimaryExpressionAstNode;
                //後置

                switch (exp.ExpressionType)
                {
                case KecaknoahOperatorType.Increment:
                    result.AddRange(PrecompileSuffixIncrement(exp));
                    break;

                case KecaknoahOperatorType.Decrement:
                    result.AddRange(PrecompileSuffixDecrement(exp));
                    break;

                default:
                    throw new NotImplementedException("多分実装してない1次式なんだと思う");
                }
                result.Add(new KecaknoahILCode {
                    Type = KecaknoahILCodeType.Pop
                });
            }
            else if (en is KecaknoahUnaryExpressionAstNode)
            {
                var exp = en as KecaknoahUnaryExpressionAstNode;
                switch (exp.ExpressionType)
                {
                case KecaknoahOperatorType.Minus:
                    result.AddRange(PrecompileExpression(exp.Target));
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.Negative
                    });
                    break;

                case KecaknoahOperatorType.Not:
                    result.AddRange(PrecompileExpression(exp.Target));
                    result.Add(new KecaknoahILCode {
                        Type = KecaknoahILCodeType.Not
                    });
                    break;

                case KecaknoahOperatorType.Increment:
                    result.AddRange(PrecompilePrefixIncrement(exp));
                    break;

                case KecaknoahOperatorType.Decrement:
                    result.AddRange(PrecompilePrefixDecrement(exp));

                    break;
                }
            }
            else
            {
                throw new InvalidOperationException("ごめん何言ってるかさっぱりわかんない");
            }
            return(result);
        }
예제 #7
0
        private static KecaknoahScriptMethodInfo ReadMethod(BinaryReader reader)
        {
            string name = null;
            var length = 0;
            var vargs = false;

            while (true)
            {
                switch ((MethodElementType)reader.ReadByte())
                {
                    case MethodElementType.Name:
                        name = reader.ReadString();
                        break;
                    case MethodElementType.ArgumentLength:
                        length = reader.ReadInt32();
                        break;
                    case MethodElementType.VariableArgument:
                        vargs = true;
                        break;
                    case MethodElementType.StartCode:
                        var method = new KecaknoahScriptMethodInfo(name, length, vargs);
                        var il = new KecaknoahIL();
                        method.Codes = il;
                        var count = reader.ReadInt32();
                        for (var i = 0; i < count; i++)
                        {
                            switch (reader.ReadByte())
                            {
                                case 0:
                                    il.PushCode(KecaknoahILCodeType.Nop);
                                    break;
                                case 1:
                                    il.PushCode(KecaknoahILCodeType.PushInteger, reader.ReadInt64());
                                    break;
                                case 2:
                                    il.PushCode(KecaknoahILCodeType.PushString, reader.ReadString());
                                    break;
                                case 3:
                                    il.PushCode(KecaknoahILCodeType.PushSingle, reader.ReadSingle());
                                    break;
                                case 4:
                                    il.PushCode(KecaknoahILCodeType.PushDouble, reader.ReadDouble());
                                    break;
                                case 5:
                                    il.PushCode(KecaknoahILCodeType.PushBoolean, false);
                                    break;
                                case 6:
                                    il.PushCode(KecaknoahILCodeType.PushBoolean, true);
                                    break;
                                case 7:
                                    il.PushCode(KecaknoahILCodeType.PushNil);
                                    break;
                                case 8:
                                    il.PushCode(KecaknoahILCodeType.Pop);
                                    break;
                                case 9:
                                    il.PushCode(KecaknoahILCodeType.Plus);
                                    break;
                                case 10:
                                    il.PushCode(KecaknoahILCodeType.Minus);
                                    break;
                                case 11:
                                    il.PushCode(KecaknoahILCodeType.Multiply);
                                    break;
                                case 12:
                                    il.PushCode(KecaknoahILCodeType.Divide);
                                    break;
                                case 13:
                                    il.PushCode(KecaknoahILCodeType.Modular);
                                    break;
                                case 14:
                                    il.PushCode(KecaknoahILCodeType.And);
                                    break;
                                case 15:
                                    il.PushCode(KecaknoahILCodeType.Or);
                                    break;
                                case 16:
                                    il.PushCode(KecaknoahILCodeType.Xor);
                                    break;
                                case 17:
                                    il.PushCode(KecaknoahILCodeType.Not);
                                    break;
                                case 18:
                                    il.PushCode(KecaknoahILCodeType.Negative);
                                    break;
                                case 19:
                                    il.PushCode(KecaknoahILCodeType.AndAlso);
                                    break;
                                case 20:
                                    il.PushCode(KecaknoahILCodeType.OrElse);
                                    break;
                                case 21:
                                    il.PushCode(KecaknoahILCodeType.LeftBitShift);
                                    break;
                                case 22:
                                    il.PushCode(KecaknoahILCodeType.RightBitShift);
                                    break;
                                case 23:
                                    il.PushCode(KecaknoahILCodeType.Equal);
                                    break;
                                case 24:
                                    il.PushCode(KecaknoahILCodeType.NotEqual);
                                    break;
                                case 25:
                                    il.PushCode(KecaknoahILCodeType.Greater);
                                    break;
                                case 26:
                                    il.PushCode(KecaknoahILCodeType.Lesser);
                                    break;
                                case 27:
                                    il.PushCode(KecaknoahILCodeType.GreaterEqual);
                                    break;
                                case 28:
                                    il.PushCode(KecaknoahILCodeType.LesserEqual);
                                    break;
                                case 29:
                                    il.PushCode(KecaknoahILCodeType.Assign);
                                    break;
                                case 30:
                                    il.PushCode(KecaknoahILCodeType.Jump, reader.ReadInt32());
                                    break;
                                case 31:
                                    il.PushCode(KecaknoahILCodeType.TrueJump, reader.ReadInt32());
                                    break;
                                case 32:
                                    il.PushCode(KecaknoahILCodeType.FalseJump, reader.ReadInt32());
                                    break;
                                case 33:
                                    il.PushCode(KecaknoahILCodeType.Return);
                                    break;
                                case 34:
                                    il.PushCode(KecaknoahILCodeType.Yield);
                                    break;
                                case 35:
                                    il.PushCode(KecaknoahILCodeType.Call, reader.ReadInt32());
                                    break;
                                case 36:
                                    il.PushCode(KecaknoahILCodeType.IndexerCall, reader.ReadInt32());
                                    break;
                                case 37:
                                    il.PushCode(KecaknoahILCodeType.PushArgument, reader.ReadInt32());
                                    break;
                                case 38:
                                    il.PushCode(KecaknoahILCodeType.LoadObject, reader.ReadString());
                                    break;
                                case 39:
                                    il.PushCode(KecaknoahILCodeType.LoadMember, reader.ReadString());
                                    break;
                                case 40:
                                    il.PushCode(KecaknoahILCodeType.AsValue);
                                    break;
                                case 41:
                                    il.PushCode(KecaknoahILCodeType.LoadVarg, reader.ReadInt32());
                                    break;
                                case 42:
                                    var code = new KecaknoahILCode() { Type = KecaknoahILCodeType.StartCoroutine };
                                    code.StringValue = reader.ReadString();
                                    code.IntegerValue = reader.ReadInt32();
                                    il.PushCode(code);
                                    break;
                                case 43:
                                    il.PushCode(new KecaknoahILCode()
                                    {
                                        Type = KecaknoahILCodeType.ResumeCoroutine,
                                        StringValue = reader.ReadString(),
                                        BooleanValue = false
                                    });
                                    break;
                                case 44:
                                    il.PushCode(new KecaknoahILCode()
                                    {
                                        Type = KecaknoahILCodeType.ResumeCoroutine,
                                        StringValue = reader.ReadString(),
                                        BooleanValue = true
                                    });
                                    break;
                                case 45:
                                    il.PushCode(KecaknoahILCodeType.MakeArray, reader.ReadInt32());
                                    break;
                                case 46:
                                    il.PushCode(KecaknoahILCodeType.PlusAssign);
                                    break;
                                case 47:
                                    il.PushCode(KecaknoahILCodeType.MinusAssign);
                                    break;
                                case 48:
                                    il.PushCode(KecaknoahILCodeType.MultiplyAssign);
                                    break;
                                case 49:
                                    il.PushCode(KecaknoahILCodeType.DivideAssign);
                                    break;
                                case 50:
                                    il.PushCode(KecaknoahILCodeType.AndAssign);
                                    break;
                                case 51:
                                    il.PushCode(KecaknoahILCodeType.OrAssign);
                                    break;
                                case 52:
                                    il.PushCode(KecaknoahILCodeType.XorAssign);
                                    break;
                                case 53:
                                    il.PushCode(KecaknoahILCodeType.ModularAssign);
                                    break;
                                case 54:
                                    il.PushCode(KecaknoahILCodeType.LeftBitShiftAssign);
                                    break;
                                case 55:
                                    il.PushCode(KecaknoahILCodeType.RightBitShiftAssign);
                                    break;
                                case 56:
                                    il.PushCode(KecaknoahILCodeType.NilAssign);
                                    break;
                                default:
                                    throw new InvalidDataException("危険オペコードにはダマされない!!近づかない!!");
                            }
                        }

                        return method;
                    default:
                        throw new InvalidDataException("無効なメソッド");
                }
            }
        }
예제 #8
0
        private static void WriteMethod(KecaknoahScriptMethodInfo method, BinaryWriter writer)
        {
            writer.Write((byte)MethodElementType.Name);
            writer.Write(method.Name);

            writer.Write((byte)MethodElementType.ArgumentLength);
            writer.Write(method.ArgumentLength);

            if (method.VariableArgument)
                writer.Write((byte)MethodElementType.VariableArgument);

            writer.Write((byte)MethodElementType.StartCode);
            var codes = method.Codes.Codes;
            writer.Write(codes.Count);

            foreach (var x in codes)
            {
                switch (x.Type)
                {
                    case KecaknoahILCodeType.Nop:
                        writer.Write((byte)0);
                        break;
                    case KecaknoahILCodeType.Label:
                        goto case KecaknoahILCodeType.Nop;
                    case KecaknoahILCodeType.PushInteger:
                        writer.Write((byte)1);
                        writer.Write(x.IntegerValue);
                        break;
                    case KecaknoahILCodeType.PushString:
                        writer.Write((byte)2);
                        writer.Write(x.StringValue);
                        break;
                    case KecaknoahILCodeType.PushSingle:
                        writer.Write((byte)3);
                        writer.Write((float)x.FloatValue);
                        break;
                    case KecaknoahILCodeType.PushDouble:
                        writer.Write((byte)4);
                        writer.Write(x.FloatValue);
                        break;
                    case KecaknoahILCodeType.PushBoolean:
                        writer.Write(x.BooleanValue ? (byte)6 : (byte)5);
                        break;
                    case KecaknoahILCodeType.PushNil:
                        writer.Write((byte)7);
                        break;
                    case KecaknoahILCodeType.Pop:
                        writer.Write((byte)8);
                        break;
                    case KecaknoahILCodeType.Plus:
                        writer.Write((byte)9);
                        break;
                    case KecaknoahILCodeType.Minus:
                        writer.Write((byte)10);
                        break;
                    case KecaknoahILCodeType.Multiply:
                        writer.Write((byte)11);
                        break;
                    case KecaknoahILCodeType.Divide:
                        writer.Write((byte)12);
                        break;
                    case KecaknoahILCodeType.Modular:
                        writer.Write((byte)13);
                        break;
                    case KecaknoahILCodeType.And:
                        writer.Write((byte)14);
                        break;
                    case KecaknoahILCodeType.Or:
                        writer.Write((byte)15);
                        break;
                    case KecaknoahILCodeType.Xor:
                        writer.Write((byte)16);
                        break;
                    case KecaknoahILCodeType.Not:
                        writer.Write((byte)17);
                        break;
                    case KecaknoahILCodeType.Negative:
                        writer.Write((byte)18);
                        break;
                    case KecaknoahILCodeType.AndAlso:
                        writer.Write((byte)19);
                        break;
                    case KecaknoahILCodeType.OrElse:
                        writer.Write((byte)20);
                        break;
                    case KecaknoahILCodeType.LeftBitShift:
                        writer.Write((byte)21);
                        break;
                    case KecaknoahILCodeType.RightBitShift:
                        writer.Write((byte)22);
                        break;
                    case KecaknoahILCodeType.Equal:
                        writer.Write((byte)23);
                        break;
                    case KecaknoahILCodeType.NotEqual:
                        writer.Write((byte)24);
                        break;
                    case KecaknoahILCodeType.Greater:
                        writer.Write((byte)25);
                        break;
                    case KecaknoahILCodeType.Lesser:
                        writer.Write((byte)26);
                        break;
                    case KecaknoahILCodeType.GreaterEqual:
                        writer.Write((byte)27);
                        break;
                    case KecaknoahILCodeType.LesserEqual:
                        writer.Write((byte)28);
                        break;
                    case KecaknoahILCodeType.Assign:
                        writer.Write((byte)29);
                        break;
                    case KecaknoahILCodeType.Jump:
                        writer.Write((byte)30);
                        writer.Write((int)x.IntegerValue);
                        break;
                    case KecaknoahILCodeType.TrueJump:
                        writer.Write((byte)31);
                        writer.Write((int)x.IntegerValue);
                        break;
                    case KecaknoahILCodeType.FalseJump:
                        writer.Write((byte)32);
                        writer.Write((int)x.IntegerValue);
                        break;
                    case KecaknoahILCodeType.Return:
                        writer.Write((byte)33);
                        break;
                    case KecaknoahILCodeType.Yield:
                        writer.Write((byte)34);
                        break;
                    case KecaknoahILCodeType.Call:
                        writer.Write((byte)35);
                        writer.Write((int)x.IntegerValue);
                        break;
                    case KecaknoahILCodeType.IndexerCall:
                        writer.Write((byte)36);
                        writer.Write((int)x.IntegerValue);
                        break;
                    case KecaknoahILCodeType.PushArgument:
                        writer.Write((byte)37);
                        writer.Write((int)x.IntegerValue);
                        break;
                    case KecaknoahILCodeType.LoadObject:
                        writer.Write((byte)38);
                        writer.Write(x.StringValue);
                        break;
                    case KecaknoahILCodeType.LoadMember:
                        writer.Write((byte)39);
                        writer.Write(x.StringValue);
                        break;
                    case KecaknoahILCodeType.AsValue:
                        writer.Write((byte)40);
                        break;
                    case KecaknoahILCodeType.LoadVarg:
                        writer.Write((byte)41);
                        writer.Write((int)x.IntegerValue);
                        break;
                    case KecaknoahILCodeType.StartCoroutine:
                        writer.Write((byte)42);
                        writer.Write(x.StringValue);
                        writer.Write((int)x.IntegerValue);
                        break;
                    case KecaknoahILCodeType.ResumeCoroutine:
                        writer.Write(x.BooleanValue ? (byte)44 : (byte)43);
                        writer.Write(x.StringValue);
                        break;
                    case KecaknoahILCodeType.MakeArray:
                        writer.Write((byte)45);
                        writer.Write((int)x.IntegerValue);
                        break;
                    case KecaknoahILCodeType.PlusAssign:
                        writer.Write((byte)46);
                        break;
                    case KecaknoahILCodeType.MinusAssign:
                        writer.Write((byte)47);
                        break;
                    case KecaknoahILCodeType.MultiplyAssign:
                        writer.Write((byte)48);
                        break;
                    case KecaknoahILCodeType.DivideAssign:
                        writer.Write((byte)49);
                        break;
                    case KecaknoahILCodeType.AndAssign:
                        writer.Write((byte)50);
                        break;
                    case KecaknoahILCodeType.OrAssign:
                        writer.Write((byte)51);
                        break;
                    case KecaknoahILCodeType.XorAssign:
                        writer.Write((byte)52);
                        break;
                    case KecaknoahILCodeType.ModularAssign:
                        writer.Write((byte)53);
                        break;
                    case KecaknoahILCodeType.LeftBitShiftAssign:
                        writer.Write((byte)54);
                        break;
                    case KecaknoahILCodeType.RightBitShiftAssign:
                        writer.Write((byte)55);
                        break;
                    case KecaknoahILCodeType.NilAssign:
                        writer.Write((byte)56);
                        break;
                    default:
                        throw new InvalidDataException("In Kecaknoah, please");
                }
            }
        }
예제 #9
0
        private IList<KecaknoahILCode> PrecompileExpression(KecaknoahAstNode node)
        {
            var result = new List<KecaknoahILCode>();
            if (node.Type != KecaknoahAstNodeType.Expression) throw new ArgumentException("ASTが式でない件について");
            var en = node as KecaknoahExpressionAstNode;
            if (en is KecaknoahBinaryExpressionAstNode)
            {
                var exp = en as KecaknoahBinaryExpressionAstNode;
                result.AddRange(PrecompileBinaryExpression(exp));
            }
            else if (en is KecaknoahFactorExpressionAstNode)
            {
                var exp = en as KecaknoahFactorExpressionAstNode;
                switch (exp.FactorType)
                {
                    case KecaknoahFactorType.IntegerValue:
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushInteger, IntegerValue = exp.IntegerValue });
                        break;
                    case KecaknoahFactorType.SingleValue:
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushDouble, FloatValue = exp.SingleValue });
                        break;
                    case KecaknoahFactorType.DoubleValue:
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushDouble, FloatValue = exp.DoubleValue });
                        break;
                    case KecaknoahFactorType.StringValue:
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushString, StringValue = exp.StringValue });
                        break;
                    case KecaknoahFactorType.BooleanValue:
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushBoolean, BooleanValue = exp.BooleanValue });
                        break;
                    case KecaknoahFactorType.Nil:
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.PushNil });
                        break;
                    case KecaknoahFactorType.Identifer:
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadObject, StringValue = exp.StringValue });
                        break;
                    case KecaknoahFactorType.ParenExpression:
                        result.AddRange(PrecompileExpression(exp.ExpressionNode));
                        break;
                    case KecaknoahFactorType.CoroutineResume:
                        if (exp.BooleanValue)
                        {
                            // state = coresume(cor, val)
                            result.AddRange(PrecompileExpression(exp.ExpressionNode));
                        }
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.ResumeCoroutine, StringValue = exp.StringValue, BooleanValue = exp.BooleanValue });
                        break;
                    case KecaknoahFactorType.Array:
                        foreach (var i in exp.ElementNodes) result.AddRange(PrecompileExpression(i));
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.MakeArray, IntegerValue = exp.ElementNodes.Count });
                        break;
                    case KecaknoahFactorType.Lambda:
                        var lma = exp.ElementNodes.Select(p => ((KecaknoahFactorExpressionAstNode)p).StringValue).ToList();
                        var name = $"Lambda-{Guid.NewGuid().ToString().Substring(0, 17)}";
                        var func = new KecaknoahScriptMethodInfo(name);
                        var eil = PrecompileExpression(exp.ExpressionNode);
                        eil.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Return });
                        foreach (var i in eil.Where(p => p.Type == KecaknoahILCodeType.LoadObject && lma.Contains(p.StringValue)))
                        {
                            i.Type = KecaknoahILCodeType.PushArgument;
                            i.IntegerValue = lma.IndexOf(i.StringValue);
                        }
                        func.Codes = new KecaknoahIL();
                        func.Codes.PushCodes(eil);
                        if (cuc.Count == 0)
                        {
                            current.methods.Add(func);
                        }
                        else
                        {
                            cuc.Peek().AddInstanceMethod(func);
                        }
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadObject, StringValue = name });
                        break;
                }
            }
            else if (en is KecaknoahArgumentCallExpressionAstNode)
            {
                var exp = en as KecaknoahArgumentCallExpressionAstNode;
                if (exp.Target is KecaknoahFactorExpressionAstNode && (exp.Target as KecaknoahFactorExpressionAstNode).FactorType == KecaknoahFactorType.VariableArguments)
                {
                    //vargs
                    foreach (var arg in exp.Arguments) result.AddRange(PrecompileExpression(arg));
                    result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadVarg, IntegerValue = exp.Arguments.Count });
                }
                else
                {
                    if (exp.ExpressionType == KecaknoahOperatorType.IndexerAccess)
                    {
                        result.AddRange(PrecompileIndexerCall(exp));
                    }
                    else
                    {
                        result.AddRange(PrecompileFunctionCall(exp));
                    }
                }
            }
            else if (en is KecaknoahMemberAccessExpressionAstNode)
            {
                var exp = en as KecaknoahMemberAccessExpressionAstNode;
                result.AddRange(PrecompileExpression(exp.Target));
                result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadMember, StringValue = exp.MemberName });
            }
            else if (en is KecaknoahPrimaryExpressionAstNode)
            {
                var exp = en as KecaknoahPrimaryExpressionAstNode;
                //後置

                switch (exp.ExpressionType)
                {
                    case KecaknoahOperatorType.Increment:
                        result.AddRange(PrecompileSuffixIncrement(exp));
                        break;
                    case KecaknoahOperatorType.Decrement:
                        result.AddRange(PrecompileSuffixDecrement(exp));
                        break;
                    default:
                        throw new NotImplementedException("多分実装してない1次式なんだと思う");
                }
                result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Pop });

            }
            else if (en is KecaknoahUnaryExpressionAstNode)
            {
                var exp = en as KecaknoahUnaryExpressionAstNode;
                switch (exp.ExpressionType)
                {
                    case KecaknoahOperatorType.Minus:
                        result.AddRange(PrecompileExpression(exp.Target));
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Negative });
                        break;
                    case KecaknoahOperatorType.Not:
                        result.AddRange(PrecompileExpression(exp.Target));
                        result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Not });
                        break;
                    case KecaknoahOperatorType.Increment:
                        result.AddRange(PrecompilePrefixIncrement(exp));
                        break;
                    case KecaknoahOperatorType.Decrement:
                        result.AddRange(PrecompilePrefixDecrement(exp));

                        break;
                }
            }
            else
            {
                throw new InvalidOperationException("ごめん何言ってるかさっぱりわかんない");
            }
            return result;
        }
예제 #10
0
 /// <summary>
 /// メソッドを追加します。
 /// </summary>
 /// <param name="method">追加するメソッド</param>
 internal void AddClassMethod(KecaknoahScriptMethodInfo method)
 {
     classMethods.Add(method);
 }
예제 #11
0
 /// <summary>
 /// メソッドを追加します。
 /// </summary>
 /// <param name="method">追加するメソッド</param>
 internal void AddInstanceMethod(KecaknoahScriptMethodInfo method)
 {
     methods.Add(method);
 }
예제 #12
0
 private IList<KecaknoahILCode> PrecompileLexicalLambda(IList<KecaknoahILCode> il, List<string> lma)
 {
     var caps = new List<string>();
     for (int i = 0; i < il.Count; i++)
     {
         var c = il[i];
         if (c.Type == KecaknoahILCodeType.LoadObject)
         {
             var name = c.StringValue;
             if (lma.Contains(name))
             {
                 c.Type = KecaknoahILCodeType.PushArgument;
                 c.IntegerValue = lma.IndexOf(name);
             }
             else
             {
                 //キャプチャ対象
                 c.Type = KecaknoahILCodeType.LoadMember;
                 if (caps.Contains(name))
                 {
                     c.StringValue = $"cap_{caps.IndexOf(name)}";
                 }
                 else
                 {
                     c.StringValue = $"cap_{caps.Count}";
                     caps.Add(name);
                 }
                 il.Insert(i, new KecaknoahILCode { Type = KecaknoahILCodeType.LoadObject, StringValue = "self" });
             }
         }
     }
     var ln = $"Lambda-{Guid.NewGuid().ToString().Substring(0, 17)}";
     var cl = new KecaknoahScriptClassInfo(ln);
     var ctor = new KecaknoahIL();
     for (int i = 0; i < caps.Count; i++)
     {
         cl.AddLocal($"cap_{i}", null);
         ctor.PushCode(KecaknoahILCodeType.LoadObject, "self");
         ctor.PushCode(KecaknoahILCodeType.LoadMember, $"cap_{i}");
         ctor.PushCode(KecaknoahILCodeType.PushArgument, i);
         ctor.PushCode(KecaknoahILCodeType.Assign);
     }
     var ci = new KecaknoahScriptMethodInfo("new", caps.Count, false);
     ci.Codes = ctor;
     cl.AddClassMethod(ci);
     var fi = new KecaknoahScriptMethodInfo("body", lma.Count, false);
     fi.Codes = new KecaknoahIL();
     fi.Codes.PushCodes(il);
     cl.AddInstanceMethod(fi);
     current.classes.Add(cl);
     var result = new List<KecaknoahILCode>();
     result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadObject, StringValue = ln });
     result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadMember, StringValue = "new" });
     foreach (var i in caps) result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadObject, StringValue = i });
     result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.Call, IntegerValue = caps.Count });
     result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadMember, StringValue = "body" });
     return result;
 }
예제 #13
0
 private IList<KecaknoahILCode> PrecompileClassLambda(IList<KecaknoahILCode> il, List<string> lma)
 {
     var caps = new List<string>();
     for (int i = 0; i < il.Count; i++)
     {
         var c = il[i];
         if (c.Type == KecaknoahILCodeType.LoadObject)
         {
             var name = c.StringValue;
             if (lma.Contains(name))
             {
                 c.Type = KecaknoahILCodeType.PushArgument;
                 c.IntegerValue = lma.IndexOf(name);
             }
         }
     }
     var ln = $"Lambda-{Guid.NewGuid().ToString().Substring(0, 17)}"; ;
     var mi = new KecaknoahScriptMethodInfo(ln, lma.Count, false);
     var lc = new KecaknoahIL();
     lc.PushCodes(il);
     mi.Codes = lc;
     var result = new List<KecaknoahILCode>();
     current.methods.Add(mi);
     result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadObject, StringValue = ln });
     return result;
 }