Example #1
0
        private static void WriteClass(KecaknoahScriptClassInfo klass, BinaryWriter writer)
        {
            writer.Write((byte)ClassElementType.Name);
            writer.Write(klass.Name);

            writer.Write((byte)ClassElementType.StartBlocks);
            writer.Write(klass.inners.Count + klass.methods.Count + klass.classMethods.Count + klass.Locals.Count);

            foreach (var x in klass.inners)
            {
                writer.Write((byte)ClassBlockType.InnerClass);
                WriteClass(x, writer);
            }

            foreach (var x in klass.methods)
            {
                writer.Write((byte)ClassBlockType.InstanceMethod);
                WriteMethod(x, writer);
            }

            foreach (var x in klass.classMethods)
            {
                writer.Write((byte)ClassBlockType.ClassMethod);
                WriteMethod(x, writer);
            }

            foreach (var x in klass.Locals)
            {
                writer.Write((byte)ClassBlockType.Local);
                writer.Write(x);
            }
        }
Example #2
0
 static IList<string> AssembleClass(KecaknoahScriptClassInfo info)
 {
     var result = new List<string>();
     result.Add($".class {info.Name}");
     foreach (var i in info.Locals)
     {
         result.Add("  .local" + i);
     }
     result.Add("  ");
     foreach (var i in info.InstanceMethods)
     {
         result.AddRange(AssembleFunction(i as KecaknoahScriptMethodInfo).Select(p => "  " + p));
         result.Add("  ");
     }
     foreach (var i in info.ClassMethods)
     {
         result.AddRange(AssembleFunction(i as KecaknoahScriptMethodInfo).Select(p => "  " + p));
         result.Add("  ");
     }
     foreach (var i in info.InnerClasses)
     {
         result.AddRange(AssembleClass(i as KecaknoahScriptClassInfo).Select(p => "  " + p));
         result.Add("  ");
     }
     return result;
 }
 private KecaknoahScriptClassInfo PrecompileClass(KecaknoahClassAstNode ast)
 {
     //TODO: local初期値式対応
     var result = new KecaknoahScriptClassInfo(ast.Name);
     cuc.Push(result);
     foreach (var i in ast.Functions)
     {
         if (i.StaticMethod)
         {
             result.AddClassMethod(PrecompileFunction(i));
         }
         else
         {
             result.AddInstanceMethod(PrecompileFunction(i));
         }
     }
     foreach (var i in ast.Locals)
     {
         if (i.InitialExpression != null)
         {
             var il = new KecaknoahIL();
             il.PushCodes(PrecompileExpression(i.InitialExpression));
             result.AddLocal(i.Name, il);
         }
         else
         {
             result.AddLocal(i.Name, null);
         }
     }
     cuc.Pop();
     return result;
 }
 /// <summary>
 /// インナークラスを追加します。
 /// </summary>
 /// <param name="klass">追加するクラス</param>
 internal void AddInnerClass(KecaknoahScriptClassInfo klass)
 {
     if (inners.Any(p => p.Name == klass.Name))
     {
         throw new ArgumentException("同じ名前のインナークラスがすでに存在します。");
     }
     inners.Add(klass);
 }
        private KecaknoahScriptClassInfo PrecompileClass(KecaknoahClassAstNode ast)
        {
            //TODO: local初期値式対応
            var result = new KecaknoahScriptClassInfo(ast.Name);

            cuc.Push(result);
            foreach (var i in ast.Functions)
            {
                if (i.StaticMethod)
                {
                    result.AddClassMethod(PrecompileFunction(i));
                }
                else
                {
                    result.AddInstanceMethod(PrecompileFunction(i));
                }
            }
            foreach (var i in ast.Locals)
            {
                result.AddLocal(i.Name);
            }
            cuc.Pop();
            return(result);
        }
Example #6
0
 private static KecaknoahScriptClassInfo ReadClass(BinaryReader reader)
 {
     string name = null;
     while (true)
     {
         switch ((ClassElementType)reader.ReadByte())
         {
             case ClassElementType.Name:
                 name = reader.ReadString();
                 break;
             case ClassElementType.StartBlocks:
                 var klass = new KecaknoahScriptClassInfo(name);
                 var count = reader.ReadInt32();
                 for (var i = 0; i < count; i++)
                 {
                     switch ((ClassBlockType)reader.ReadByte())
                     {
                         case ClassBlockType.InnerClass:
                             klass.AddInnerClass(ReadClass(reader));
                             break;
                         case ClassBlockType.InstanceMethod:
                             klass.AddInstanceMethod(ReadMethod(reader));
                             break;
                         case ClassBlockType.ClassMethod:
                             klass.AddInstanceMethod(ReadMethod(reader));
                             break;
                         case ClassBlockType.Local:
                             klass.AddLocal(reader.ReadString(), null);
                             break;
                         default:
                             throw new InvalidDataException("やめて");
                     }
                 }
                 return klass;
             default:
                 throw new InvalidDataException("無効なクラス");
         }
     }
 }
 /// <summary>
 /// インナークラスを追加します。
 /// </summary>
 /// <param name="klass">追加するクラス</param>
 internal void AddInnerClass(KecaknoahScriptClassInfo klass)
 {
     if (inners.Any(p => p.Name == klass.Name)) throw new ArgumentException("同じ名前のインナークラスがすでに存在します。");
     inners.Add(klass);
 }
 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;
 }