예제 #1
0
        public override void Define()
        {
            Statement("block", list => list.Last().Type,
                      (c, list) => list.Skip(1).ForEach(x => GenerateStatement(c, (PList)x)));

            Expression("block", list => list.Last().Type,
                       list => $@"([=]() -> {GenerateType(list.Type)} {{
{string.Join('\n', list.Skip(1).Select((x, i) => {
					string code;
					if(x is PList xl) {
						var c = new CodeBuilder();
						GenerateStatement(c, xl);
						code = c.Code;
					} else
						code = GenerateExpression(x) + "                        ; ";
					if(i == list.Count - 2)
						return $"                         \ t \ treturn {
                code.Trim()
            } ";
					return $"                     \ t \ t {
                code.Trim()
            } ";
				}))}
	}})()"    ,
                       list => $@"([=]() -> {GenerateType(list.Type)} {{
{string.Join('\n', list.Skip(1).Select((x, i) => {
					string code;
					if(x is PList xl) {
						var c = new CodeBuilder();
						GenerateStatement(c, xl);
						code = c.Code;
					} else
						code = GenerateExpression(x) + "                        ; ";
					if(i == list.Count - 2)
						return $"                         \ t \ treturn({ code.Trim().TrimEnd(';') }).Store(); ";
					return $"                     \ t \ t {
                code.Trim()
            } ";
				}))}
	}})()"    );

            Statement("if",
                      list => list[2].Type.AsRuntime(list[1].Type.Runtime ||
                                                     !(list[2].Type is EUnit) && list[2].Type.Runtime ||
                                                     !(list[3].Type is EUnit) && list[3].Type.Runtime),
                      (c, list) => {
                c += $"if(({GenerateExpression(list[1])}) != 0) {{";
                c++;
                GenerateStatement(c, (PList)list[2]);
                c--;
                c += "} else {";
                c++;
                GenerateStatement(c, (PList)list[3]);
                c--;
                c += "}";
            }, (c, list) => {
                if (list[1].Type.Runtime)
                {
                    var if_label   = TempName();
                    var end_label  = TempName();
                    var else_label = TempName();
                    c += $"LabelTag {if_label} = DefineLabel(), {else_label} = DefineLabel(), {end_label} = DefineLabel();";
                    c += $"BranchIf({GenerateExpression(list[1])}, {if_label}, {else_label});";
                    c += $"Label({if_label});";
                    GenerateStatement(c, (PList)list[2]);
                    c += $"Branch({end_label});";
                    c += $"Label({else_label});";
                    GenerateStatement(c, (PList)list[3]);
                    c += $"Branch({end_label});";
                    c += $"Label({end_label});";
                }
                else
                {
                    c += $"if(({GenerateExpression(list[1])}) != 0) {{";
                    c++;
                    GenerateStatement(c, (PList)list[2]);
                    c--;
                    c += "} else {";
                    c++;
                    GenerateStatement(c, (PList)list[3]);
                    c--;
                    c += "}";
                }
            });

            Expression("if", list => list[2].Type, list => {
                var a = GenerateExpression(list[2]);
                var b = GenerateExpression(list[3]);
                if (!a.StartsWith("throw"))
                {
                    a = $"({a})";
                }
                if (!b.StartsWith("throw"))
                {
                    b = $"({b})";
                }
                return($"({GenerateExpression(list[1])} != 0) ? {a} : {b}");
            }, list => {
                var a = GenerateExpression(list[2]);
                var b = GenerateExpression(list[3]);

                if (list[1].Type.Runtime)
                {
                    if (a.StartsWith("throw"))
                    {
                        a = "null";
                    }
                    if (b.StartsWith("throw"))
                    {
                        b = "null";
                    }
                    return($"Ternary<{GenerateType(list[1].Type.AsCompiletime())}, {GenerateType(list[2].Type.AsCompiletime())}>((RuntimeValue<{GenerateType(list[1].Type.AsCompiletime())}>) ({GenerateExpression(list[1])}), {a}, {b})");
                }

                if (!a.StartsWith("throw"))
                {
                    a = $"({a})";
                }
                if (!b.StartsWith("throw"))
                {
                    b = $"({b})";
                }
                return($"({GenerateExpression(list[1])}) != 0 ? {a} : {b}");
            });

            Statement("match", list => list.Count == 3 ? list[2].Type : list[3].Type,
                      (c, list) => {
                c += $"switch({GenerateExpression(list[1])}) {{";
                c++;
                for (var i = 2; i < list.Count; i += 2)
                {
                    if (i + 1 == list.Count)
                    {
                        c += "default: {";
                        c++;
                        GenerateStatement(c, (PList)list[i]);
                        c += "break;";
                        c--;
                        c += "}";
                    }
                    else
                    {
                        c += $"case {GenerateExpression(list[i])}: {{";
                        c++;
                        GenerateStatement(c, (PList)list[i + 1]);
                        c += "break;";
                        c--;
                        c += "}";
                    }
                }
                c--;
                c += "}";
            });

            string GenerateReturn(string expr) => expr.StartsWith("throw ") ? expr : $"return {expr}";

            Expression("match", list => list.Count == 3 ? list[2].Type : list[3].Type,
                       list => {
                var opts = new List <string>();
                for (var i = 2; i < list.Count; i += 2)
                {
                    opts.Add(i + 1 == list.Count
                                                        ? $"default: {GenerateReturn(GenerateExpression(list[i]))};"
                                                        : $"case {GenerateExpression(list[i])}: {GenerateReturn(GenerateExpression(list[i + 1]))};");
                }
                var tn = TempName();
                return($"([=](auto {tn}) -> {GenerateType(list.Count == 3 ? list[2].Type : list[3].Type)} {{ switch({tn}) {{ {string.Join(" ", opts)} }} }})({GenerateExpression(list[1])})");
            }, list => {
                string Expr(PTree expr)
                {
                    var str = GenerateExpression(expr);
                    return(str.StartsWith("throw ") ? str : $"({GenerateType(list.Type)}) ({str})");
                }
                var opts = new List <string>();
                for (var i = 2; i < list.Count; i += 2)
                {
                    opts.Add(i + 1 == list.Count
                                                        ? $"default: {GenerateReturn(GenerateExpression(list[i]))};"
                                                        : $"case {GenerateExpression(list[i])}: {GenerateReturn(Expr(list[i + 1]))};");
                }
                var tn = TempName();
                return($"([=](auto {tn}) -> {GenerateType(list.Count == 3 ? list[2].Type : list[3].Type)} {{ switch({tn}) {{ {string.Join(" ", opts)} }} }})({GenerateExpression(list[1])})");
            });

            Expression("svc", _ => EType.Unit.AsRuntime(),
                       list => $"Svc({GenerateExpression(list[1])})",
                       list => $"CallSvc({GenerateExpression(list[1])})");

            Expression("branch", _ => EType.Unit.AsRuntime(), list => $"Branch({GenerateExpression(list[1])})");
            Expression("branch-linked", _ => EType.Unit.AsRuntime(), list => $"BranchLinked({GenerateExpression(list[1])})");
            Expression("branch-linked-register", _ => EType.Unit.AsRuntime(), list => $"BranchLinkedRegister({GenerateExpression(list[1])})");
            Expression("branch-register", _ => EType.Unit.AsRuntime(), list => $"BranchRegister({GenerateExpression(list[1])})");
            Expression("branch-default", _ => EType.Unit.AsRuntime(), list => $"Branch(pc + 4)");

            Expression("unimplemented", _ => EType.Unit, _ => "throw \"Not implemented\"");
        }
예제 #2
0
		public static void GenerateStatement(CodeBuilder c, PList list) => Program.GenerateStatement(c, list);