Example #1
0
 /// <summary>
 /// ノードを追加します。
 /// </summary>
 /// <param name="node">追加するノード</param>
 protected internal void AddNode(KecaknoahAstNode node) => children.Add(node);
Example #2
0
 private KecaknoahAstNode ParseFirstLevel(Queue<KecaknoahToken> tokens)
 {
     var result = new KecaknoahAstNode();
     tokens.SkipLogicalLineBreak();
     try
     {
         while (tokens.Count != 0)
         {
             var t = tokens.Dequeue();
             switch (t.Type)
             {
                 case KecaknoahTokenType.ClassKeyword:
                     result.AddNode(ParseClass(tokens));
                     break;
                 case KecaknoahTokenType.FuncKeyword:
                     result.AddNode(ParseFunction(tokens, true));
                     break;
                 default:
                     throw new KecaknoahParseException(t.CreateErrorAt("トップレベルにはクラスとメソッド以外は定義できません。"));
             }
             tokens.SkipLogicalLineBreak();
         }
     }
     catch (KecaknoahParseException)
     {
         throw;
     }
     return result;
 }
Example #3
0
 private KecaknoahAstNode ParseFirstLevel(Queue<KecaknoahToken> tokens)
 {
     var result = new KecaknoahAstNode();
     tokens.SkipLogicalLineBreak();
     try
     {
         while (tokens.Count != 0)
         {
             var t = tokens.Dequeue();
             switch (t.Type)
             {
                 case KecaknoahTokenType.UseKeyword:
                     t = tokens.Dequeue();
                     if (t.Type != KecaknoahTokenType.StringLiteral) throw new KecaknoahParseException(t.CreateErrorAt("use文には文字列を指定してください。"));
                     result.AddNode(new KecaknoahUseAstNode { Target = t.TokenString });
                     break;
                 case KecaknoahTokenType.ClassKeyword:
                     result.AddNode(ParseClass(tokens));
                     break;
                 case KecaknoahTokenType.FuncKeyword:
                     result.AddNode(ParseFunction(tokens, true));
                     break;
                 default:
                     throw new KecaknoahParseException(t.CreateErrorAt("トップレベルにはクラスとメソッド、use文以外は定義できません。"));
             }
             tokens.SkipLogicalLineBreak();
         }
     }
     catch (KecaknoahParseException)
     {
         throw;
     }
     return result;
 }
Example #4
0
 /// <summary>
 /// ノードを追加します。
 /// </summary>
 /// <param name="node">追加するノード</param>
 protected internal void AddNode(KecaknoahAstNode node) => children.Add(node);
Example #5
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;
        }
        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:
                        result.AddRange(PrecompileLambda(exp));
                        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;
        }