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;
 }
        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 #3
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("無効なクラス");
         }
     }
 }
 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;
 }