Esempio n. 1
0
        public static bool TryParse(string content, FiMReport report, int start, int length, out KirinNode result)
        {
            result = null;
            if (!content.StartsWith("I "))
            {
                return(false);
            }
            var match = Keywords.FirstOrDefault(k => content.StartsWith(k));

            if (match == null)
            {
                return(false);
            }

            string value = content.Substring(match.Length);
            var    node  = new KirinFunctionCall(start, length)
            {
                FunctionName = value
            };

            int keywordIndex = value.IndexOf(FunctionParam);

            if (keywordIndex > -1)
            {
                node.FunctionName  = value.Substring(0, keywordIndex);
                node.RawParameters = value.Substring(keywordIndex + FunctionParam.Length);
            }
            else
            {
                node.RawParameters = string.Empty;
            }

            result = node;
            return(true);
        }
Esempio n. 2
0
 public static void AddExperimentalFunctions(FiMReport report)
 {
     report.AddParagraph("count of an array", new Func <IDictionary, double>((value) =>
     {
         return(value.Keys.Count);
     }));
     report.AddParagraph("length of a string", new Func <string, double>((value) =>
     {
         return(value.Length);
     }));
     report.AddParagraph("convert a number to char", new Func <double, char>((value) =>
     {
         return((char)value);
     }));
     report.AddParagraph("convert a char to num", new Func <char, double>((value) =>
     {
         return((double)char.Parse(value.ToString()));
     }));
     report.AddParagraph("convert a number to literal string", new Func <double, string>((value) =>
     {
         return(value.ToString());
     }));
     report.AddParagraph("convert a char to literal num", new Func <char, double>((value) =>
     {
         return(int.Parse(value.ToString()));
     }));
     report.AddParagraph("square root of a num", new Func <double, double>((value) =>
     {
         return(Math.Sqrt(value));
     }));
 }
Esempio n. 3
0
        public static FiMReport GetReport(string path)
        {
            FiMReport report = FiMReport.FromFile(path);

            FiMSharp.CLI.Program.AddExperimentalFunctions(report);
            report.Output = (l) => Console.Write(l);
            report.Input  = (p, _) =>
            {
                if (string.IsNullOrWhiteSpace(p))
                {
                    Console.Write(p);
                }
                return(Console.ReadLine());
            };
            return(report);
        }
        // READ FILE CONTENT
        public void ReadReport(string path)
        {
            Report = new FiMReport();

            // CHECKS
            if (!Directory.Exists(path))
            {
                throw new FiMException("Directory doesn't exist!");
            }
            if (!File.Exists(path + "/main.fpp"))
            {
                throw new FiMException("main.fpp doesn't exist!");
            }
            //

            List <string> lines = File.ReadAllLines(path + "/main.fpp").ToList();

            #region Read main.fpp File

            try
            {
                lines = NetFIMMethods.SanitizeReport(lines);
            }
            catch (Exception e)
            {
                throw e;
            }

            // lets be strict on the report
            if (!lines.First().StartsWith(NetFIMGlobal.ReportStart))
            {
                throw new Exception("Invalid Report beginning");
            }
            else
            {
                Report.ReportName = lines.First().Remove(0, NetFIMGlobal.ReportStart.Length);
            }

            lines = NetFIMMethods.RemoveLinesAfterReportEnd(lines);
            if (!lines.Last().StartsWith(NetFIMGlobal.ReportEnd))
            {
                throw new Exception("Invalid Report ending");
            }
            else
            {
                Report.Writer = lines.Last().Remove(0, NetFIMGlobal.ReportEnd.Length);
            }

            // Grab global variables
            bool gv_inside = false;
            for (int i = 0; i < lines.Count; i++)
            {
                string line = lines[i];
                if (line.Replace("Today ", "").StartsWith("I learned "))
                {
                    gv_inside = true;
                }
                if (line.StartsWith("That's all about "))
                {
                    gv_inside = false;
                }

                if (!gv_inside)
                {
                    if (line.StartsWith(NetFIMGlobal.Keywords.Method_Declare))
                    {
                        string    variableName;
                        FiMObject obj;
                        try { obj = NetFIMMethods.InterpretVariableDecleration(line, out variableName, Report.GlobalVariables); }
                        catch (Exception e) { throw new Exception("[" + i + "] " + e.Message); }

                        if (Report.GlobalVariables.ContainsKey(variableName))
                        {
                            throw new Exception("A global variable with the name '" + variableName + "' already exists.");
                        }

                        Report.GlobalVariables.Add(variableName, obj);
                    }
                }
            }

            // Grab functions
            for (int i = 0; i < lines.Count(); i++)
            {
                string line = lines[i];
                if (line.Replace("Today ", "").StartsWith("I learned "))
                {
                    string funcName = line.Replace("Today ", "").Replace("I learned ", "");

                    FiMObjectTypes funcType = FiMObjectTypes.UNKNOWN;
                    FiMObjectTypes retrType = FiMObjectTypes.UNKNOWN;
                    string         retrName = null;

                    if (NetFIMGlobal.Keywords.Method_Return.Any(x => funcName.Contains(x)) || funcName.Contains(NetFIMGlobal.Keywords.Method_Parameter))
                    {
                        if (NetFIMGlobal.Keywords.Method_Return.Any(x => funcName.Contains(x)))
                        {
                            string r_ph = NetFIMGlobal.Keywords.Method_Return.Where(x => funcName.Contains(x)).FirstOrDefault();
                            string r_ap;
                            try
                            {
                                funcType = NetFIMMethods.GetVariableInitializerType(funcName.Split(new string[] { r_ph }, StringSplitOptions.None)[1].TrimStart(' ').TrimEnd(' '), out r_ap);
                            }
                            catch (Exception ex) { throw new Exception("Invalid Paragraph return - " + ex); }
                            //
                            funcName = funcName.Replace(" " + r_ph + " " + r_ap, "");
                        }
                        if (funcName.Contains(NetFIMGlobal.Keywords.Method_Parameter))
                        {
                            string p_ap;
                            try
                            {
                                retrType = NetFIMMethods.GetVariableInitializerType(funcName.Split(new string[] { NetFIMGlobal.Keywords.Method_Parameter }, StringSplitOptions.None)[1].TrimStart(' ').TrimEnd(' '), out p_ap);
                                retrName = funcName.Split(new string[] { NetFIMGlobal.Keywords.Method_Parameter + " " + p_ap }, StringSplitOptions.None)[1].TrimStart(' ');
                            }
                            catch { throw new Exception("Invalid Paragraph parameter"); }
                            //
                            funcName = funcName.Split(new string[] { NetFIMGlobal.Keywords.Method_Parameter + " " + p_ap }, StringSplitOptions.None)[0].TrimEnd(' ');
                        }
                    }

                    if (NetFIMGlobal.KeywordsList.Any(x => funcName.Contains(x)))
                    {
                        throw new Exception("Paragraph name '" + funcName + "' has broken one or more restrictions");
                    }

                    List <string> iLines = new List <string>();

                    int  il   = i + 1;
                    bool ibrk = false;
                    while (!ibrk)
                    {
                        string inn = lines[il];

                        if (inn.StartsWith("That's all about "))
                        {
                            // might also want to do the check here
                            if (inn.Substring("That's all about ".Length) != funcName)
                            {
                                throw new Exception("Paragraph '" + funcName + "' doesn't end with the same name");
                            }
                            ibrk = true;
                        }
                        else
                        {
                            iLines.Add(inn);
                        }

                        il++;
                    }

                    if (!ibrk)
                    {
                        throw new Exception("Paragraph '" + funcName + "' doesn't end properly");
                    }

                    FiMParagraph paragraph = new FiMParagraph(iLines, i, line.StartsWith("Today "), returnType: funcType, paramType: retrType, paramName: retrName);

                    if (Report.Paragraphs.Any(x => x.Value.isMainFunction == true && line.StartsWith("Today ")))
                    {
                        throw new Exception("Multiple main paragraphs found");
                    }

                    Report.Paragraphs.Add(funcName, paragraph);

                    i = il;
                }
            }

            #endregion
        }
Esempio n. 5
0
        public static string Transpile(
            FiMReport report,
            string indent = "    ",
            Func <string, JavascriptInternalFunction> onInternalFunction = null,
            string output        = "console.log",
            string outputNewline = "console.log",
            string input         = "prompt"
            )
        {
            StringBuilder sb = new StringBuilder();

            var container = new JavascriptContainer()
            {
                report            = report,
                globalVariables   = new List <string>(),
                internalFunctions = new Dictionary <string, string>(),

                output        = output,
                outputNewline = outputNewline,
                input         = input,
            };

            sb.AppendLine("'use strict';");

            sb.AppendLine("");

            sb.AppendLine("/**");
            sb.AppendLine(" * ");
            sb.AppendLine($" * This report, entitled \"{ report.Info.Name }\", was written by: { report.Author.Name } ");
            sb.AppendLine(" * ");
            sb.AppendLine(" */");

            sb.AppendLine("");

            // Helpers
            // fim_index(x,y) = Index arrays normally, minus one for strings.
            sb.AppendLine("function fim_index(x,y){return y-(Array.isArray(x)?0:1)}");
            // fim_forin(x) = Removes the first (null) element if passed an array
            sb.AppendLine("function fim_forin(x){return Array.isArray(x)?x.slice(1):x}");

            Dictionary <string, string> internalHelpers = new Dictionary <string, string>();

            foreach (var paragraph in report.Paragraphs.Reverse().Where(p => p.FunctionType == "KirinInternalFunction"))
            {
                if (onInternalFunction == null)
                {
                    throw new Exception("Report requests an internal function conversion: " + paragraph.Name);
                }

                var iFunc = onInternalFunction(paragraph.Name);
                sb.AppendLine(iFunc.Function);
                container.internalFunctions.Add(paragraph.Name, iFunc.Name);
            }

            sb.AppendLine("");

            sb.AppendLine($"const { SanitizeName(report.Info.Recipient) } = function() {{}}");
            string name = SanitizeName(report.Info.Name);

            if (int.TryParse(name[0].ToString(), out int _))
            {
                name = $"_{name}";
            }
            sb.AppendLine($"function { name }() {{");

            foreach (var variable in report.Variables.GlobalVariables.Reverse())
            {
                sb.AppendLine($"{ indent }this.{ SanitizeName(variable.Name) } = { SanitizeObject(variable.Value, variable.Type) }");
                container.globalVariables.Add(variable.Name);
            }
            foreach (var paragraph in report.Paragraphs.Reverse().Where(p => p.FunctionType != "KirinInternalFunction"))
            {
                var    func = (KirinFunction)paragraph.Function;
                string args = "";
                if (func.Arguments != null)
                {
                    args = string.Join(", ",
                                       func.Arguments.Select(a =>
                                                             $"/** @type {{{ KirinTypeAsJavascriptType(a.Type) }}} */ { SanitizeName(a.Name) } = { DefaultValue(a.Type) }"
                                                             )
                                       );
                }

                sb.AppendLine($"{ indent }this.{ SanitizeName(paragraph.Name) } = function({ args }) {{");
                TranspileStatements(sb, container, func.Statement, indent, 2);
                sb.AppendLine($"{ indent }}}");
            }

            if (report.MainParagraph != null)
            {
                sb.AppendLine("");
                sb.AppendLine($"{ indent }this.today = function() {{");
                sb.AppendLine($"{ indent }{ indent }this.{ SanitizeName(report.MainParagraph.Name) }();");
                sb.AppendLine($"{ indent }}}");
            }

            sb.AppendLine($"}}");
            sb.AppendLine($"{name}.prototype = new {SanitizeName(report.Info.Recipient)}();");

            sb.AppendLine("");

            sb.AppendLine($"new {name}().today();");
            return(sb.ToString());
        }
Esempio n. 6
0
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                string report_path  = "";
                bool   pretty       = false;
                bool   show_help    = false;
                bool   experimental = false;
                bool   js           = false;

                OptionSet p = new OptionSet()
                              .Add("p|pretty", "Prettify console output.", v => pretty               = true)
                              .Add("h|help", "Show this message and exit.", v => show_help           = true)
                              .Add("e|experimental", "Add experimental functions", v => experimental = true)
                              .Add("j|javascript", "Convert file to Javascript", v => js             = true);
                List <string> extra = p.Parse(args);

                if (show_help)
                {
                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                    {
                        Console.WriteLine("Usage: fim [options] <report_path>");
                    }
                    else
                    {
                        Console.WriteLine("Usage: ./fim [options] <report_path>");
                    }

                    Console.WriteLine("Interprets the specified FiM++ report.");
                    Console.WriteLine();
                    Console.WriteLine("Options:");
                    p.WriteOptionDescriptions(Console.Out);
                    return;
                }

                if (extra.Count > 0)
                {
                    report_path = extra[0];
                }
                if (string.IsNullOrWhiteSpace(report_path) || !FileExists(report_path))
                {
                    throw new FileNotFoundException($"Cannot find report '{ report_path }'");
                }

#if DEBUG
                var debugTime = new System.Diagnostics.Stopwatch();
                debugTime.Start();
#endif

                FiMReport report = FiMReport.FromFile(report_path);

                if (experimental)
                {
                    AddExperimentalFunctions(report);
                }

                if (js)
                {
                    string filename = Path.GetFileNameWithoutExtension(report_path);
                    string old_path = Path.GetPathRoot(report_path);
                    string new_path = Path.GetFullPath(Path.Combine(old_path, filename + ".js"));

                    File.WriteAllText(
                        new_path,
                        Changeling.Javascript.Transpile(
                            report,
                            onInternalFunction: (name) =>
                    {
                        var func = new Changeling.Javascript.JavascriptInternalFunction()
                        {
                            Name     = "",
                            Function = ""
                        };

                        switch (name)
                        {
                        case "count of an array":
                            {
                                func.Name     = "fim_count";
                                func.Function = "function fim_count(a){return a.filter(x=>x).length}";
                            }
                            break;

                        case "length of a string":
                            {
                                func.Name     = "fim_length";
                                func.Function = "function fim_length(s){return s.length}";
                            }
                            break;

                        case "convert a number to char":
                            {
                                func.Name     = "fim_ntc";
                                func.Function = "function fim_ntc(n){return String.fromCharCode(n)}";
                            }
                            break;

                        case "convert a char to num":
                            {
                                func.Name     = "fim_ctn";
                                func.Function = "function fim_ctn(c){return c.charCodeAt(0)}";
                            }
                            break;

                        case "convert a number to literal string":
                            {
                                func.Name     = "fim_ntls";
                                func.Function = "function fim_ntls(n){return n+''}";
                            }
                            break;

                        case "convert a char to literal num":
                            {
                                func.Name     = "fim_ctln";
                                func.Function = "function fim_ctln(c){return +c}";
                            }
                            break;

                        case "square root of a num":
                            {
                                func.Name     = "fim_sqrt";
                                func.Function = "function fim_sqrt(n){return Math.sqrt(n)}";
                            }
                            break;
                        }

                        return(func);
                    }
                            )
                        );
                }

                else
                {
                    report.Output = (l) => Console.Write(l);
                    report.Input  = (p, n) =>
                    {
                        if (string.IsNullOrEmpty(p))
                        {
                            Console.Write($"{n} is asking for an input: ");
                        }
                        else
                        {
                            Console.Write(p);
                        }

                        return(Console.ReadLine());
                    };

                    if (pretty)
                    {
                        Console.WriteLine($"[ FiMSharp v{GetVersion()} ]");
                        Console.WriteLine($"Report Name: {report.Info.Name}");
                        Console.WriteLine($"Student Name: {report.Author.Name}");
                        Console.WriteLine("[@]===[@]");
                    }

                    report.MainParagraph?.Execute();

                    if (pretty)
                    {
                        Console.WriteLine("[@]===[@]");
                    }
                }

#if DEBUG
                Console.WriteLine($"[Debug] Code execution took {debugTime.Elapsed:d\\.hh\\:mm\\:ss\\:fff}.");
#endif
            }
        }