Beispiel #1
0
        /// <summary>
        /// <see cref="KecaknoahSource"/>から指定の<see cref="Stream"/>にバイトコードを出力します。
        /// </summary>
        /// <param name="source">対象の<see cref="KecaknoahSource"/></param>
        /// <param name="output">出力先</param>
        public static void Save(KecaknoahSource source, Stream output)
        {
            using (var writer = new BinaryWriter(output, stringEncoding, true))
            {
                writer.Write(magicNumber);
                writer.Write(BytecodeVersion);

                writer.Write(source.Uses.Count + source.Classes.Count + source.TopLevelMethods.Count);
                foreach (var x in source.Uses)
                {
                    writer.Write((byte)TopLevelBlockType.Use);
                    writer.Write(x);
                }

                foreach (var x in source.Classes)
                {
                    writer.Write((byte)TopLevelBlockType.Class);
                    WriteClass(x, writer);
                }

                foreach (var x in source.TopLevelMethods)
                {
                    writer.Write((byte)TopLevelBlockType.TopLevelMethod);
                    WriteMethod(x, writer);
                }
            }
        }
 /// <summary>
 /// 1つのソースコード全体からなる<see cref="KecaknoahAst"/>をプリコンパイルします。
 /// </summary>
 /// <param name="ast">対象の<see cref="KecaknoahAst"/></param>
 /// <returns>プリコンパイル結果</returns>
 public KecaknoahSource PrecompileAll(KecaknoahAst ast)
 {
     var result = new KecaknoahSource();
     current = result;
     foreach (var i in ast.RootNode.Children)
     {
         if (i is KecaknoahClassAstNode)
         {
             result.classes.Add(PrecompileClass(i as KecaknoahClassAstNode));
         }
         else if (i is KecaknoahFunctionAstNode)
         {
             result.methods.Add(PrecompileFunction(i as KecaknoahFunctionAstNode));
         }
         else if (i is KecaknoahUseAstNode)
         {
             result.uses.Add((i as KecaknoahUseAstNode).Target);
         }
         else
         {
             throw new InvalidOperationException("トップレベルにはクラスとメソッドとuse文以外おけません");
         }
     }
     current = null;
     return result;
 }
Beispiel #3
0
 /// <summary>
 /// プリコンパイルしたソースコードを登録します。
 /// </summary>
 /// <param name="src">登録する<see cref="KecaknoahSource"/></param>
 public void RegisterSource(KecaknoahSource src)
 {
     foreach (var c in src.Classes)
     {
         classes.Add(c);
         classReferences.Add(KecaknoahReference.CreateRightReference(new KecaknoahScriptClassObject(c)));
     }
     foreach (var m in src.TopLevelMethods)
     {
         topMethods.Add(m);
         methodReferences.Add(KecaknoahReference.CreateRightReference(new KecaknoahScriptFunction(KecaknoahNil.Instance, m)));
     }
 }
Beispiel #4
0
 /// <summary>
 /// プリコンパイルしたソースコードを登録します。
 /// </summary>
 /// <param name="src">登録する<see cref="KecaknoahSource"/></param>
 public void RegisterSource(KecaknoahSource src)
 {
     foreach (var c in src.Classes)
     {
         classes.Add(c);
         classReferences.Add(KecaknoahReference.CreateRightReference(new KecaknoahScriptClassObject(c)));
     }
     foreach (var m in src.TopLevelMethods)
     {
         topMethods.Add(m);
         methodReferences.Add(KecaknoahReference.CreateRightReference(new KecaknoahScriptFunction(KecaknoahNil.Instance, m)));
     }
 }
Beispiel #5
0
 static IList<string> AssembleSource(KecaknoahSource info)
 {
     var result = new List<string>();
     foreach (var i in info.Classes)
     {
         result.AddRange(AssembleClass(i as KecaknoahScriptClassInfo));
         result.Add("");
     }
     foreach (var i in info.TopLevelMethods)
     {
         result.AddRange(AssembleFunction(i as KecaknoahScriptMethodInfo));
         result.Add("");
     }
     return result;
 }
        /// <summary>
        /// 1つのソースコード全体からなる<see cref="KecaknoahAst"/>をプリコンパイルします。
        /// </summary>
        /// <param name="ast">対象の<see cref="KecaknoahAst"/></param>
        /// <returns>プリコンパイル結果</returns>
        public KecaknoahSource PrecompileAll(KecaknoahAst ast)
        {
            var result = new KecaknoahSource();

            current = result;
            foreach (var i in ast.RootNode.Children)
            {
                if (i is KecaknoahClassAstNode)
                {
                    result.classes.Add(PrecompileClass(i as KecaknoahClassAstNode));
                }
                else if (i is KecaknoahFunctionAstNode)
                {
                    result.methods.Add(PrecompileFunction(i as KecaknoahFunctionAstNode));
                }
                else
                {
                    throw new InvalidOperationException("トップレベルにはクラスとメソッド以外おけません");
                }
            }
            current = null;
            return(result);
        }
Beispiel #7
0
        /// <summary>
        /// バイトコードを読み込み、<see cref="KecaknoahSource"/>に変換します。
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static KecaknoahSource Load(Stream input)
        {
            using (var reader = new BinaryReader(input, stringEncoding, true))
            {
                if (!reader.ReadBytes(magicNumber.Length).SequenceEqual(magicNumber))
                    throw new InvalidDataException("合言葉は「KC」");

                var version = reader.ReadUInt16();
                if (version > BytecodeVersion)
                    throw new InvalidDataException($"Kecaknoah Bytecode v{version} には対応していません。");

                var result = new KecaknoahSource();
                var count = reader.ReadInt32();

                for (var i = 0; i < count; i++)
                {
                    switch ((TopLevelBlockType)reader.ReadByte())
                    {
                        case TopLevelBlockType.Use:
                            result.uses.Add(reader.ReadString());
                            break;
                        case TopLevelBlockType.Class:
                            result.classes.Add(ReadClass(reader));
                            break;
                        case TopLevelBlockType.TopLevelMethod:
                            result.methods.Add(ReadMethod(reader));
                            break;
                        default:
                            throw new InvalidDataException("変なデータが出ーた!wwww");
                    }
                }

                return result;
            }
        }
Beispiel #8
0
 private void ProcessUseDirective(KecaknoahSource src)
 {
     var cur = Directory.GetCurrentDirectory();
     var asm = Path.GetDirectoryName(typeof(KecaknoahModule).Assembly.Location);
     var lex = new KecaknoahLexer();
     var par = new KecaknoahParser();
     var prc = new KecaknoahPrecompiler();
     foreach (var text in src.Uses)
     {
         var arg = text.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
         switch (arg[0])
         {
             case "import":
                 var it = Path.Combine(cur, arg[1]);
                 Directory.SetCurrentDirectory(Path.GetDirectoryName(it));
                 var s = prc.PrecompileAll(par.Parse(lex.AnalyzeFromFile(it)));
                 RegisterSource(s);
                 Directory.SetCurrentDirectory(cur);
                 break;
             case "stdlib":
                 var lt = Path.Combine(asm, "lib");
                 Directory.SetCurrentDirectory(Path.GetDirectoryName(lt));
                 var s2 = prc.PrecompileAll(par.Parse(lex.AnalyzeFromFile(lt)));
                 RegisterSource(s2);
                 Directory.SetCurrentDirectory(cur);
                 break;
         }
     }
 }