public void Add(CodeLine c) { MaxLineLength = Math.Max(MaxLineLength, c.Code.Length); c.Depth = Depth; Lines.Add(c); }
public CodeBlock CreateStatement(VarDeclarationNode node) { var output = new CodeBlock(); foreach (var id in node.Ids) { var t = NextTemporary; var v = new Variable { Name = id.Token.Content, Scope = CurrentScope }; AddTemporary(v, t); if (node.Type is SimpleTypeNode) { output.Add(CodeLine.Of($"{VarSignature(node, t.Representation)};", id.Token.Content, id.Token.Line)); } else { HasArrays = true; var at = (ArrayTypeNode)node.Type; var size = -1; var type = _types[at.SubType]; var sizeStr = ""; switch (at.Size) { case NoOpNode _: t.Dynamic = true; t.Size = 0; sizeStr = "0"; break; case ValueNode vn: t.Size = vn.Value; sizeStr = $"{t.Size}"; break; default: { var(sizeTemp, sizeCode) = ComputeTemporary(at.Size); output.Add(sizeCode); sizeStr = sizeTemp.Representation; break; } } // TODO: skip this if value _arrayDefinitions.Add($"typedef _array({type}, {at.SubType});"); output.Add(CodeLine.Of($"_array_{at.SubType} {t.Representation};")); output.Add(CodeLine.Of($"_initArray({t.Representation}, {sizeStr});", $"{id}: array[{(at.Size is NoOpNode ? "" : at.Size.ToString())}] of {at.Type.Token.Content}", node.Token.Line)); AddFreeable(t); } } return(output); }
public string Generate() { foreach (var cfg in Cfgs) { var function = cfg.Function; _scopeStack.Push(function.Scope); _freeable[function.Scope] = new List <string>(); var signature = FunctionSignature(function); if (!signature.Equals("main")) { _forwardDeclarations.Add($"{signature};"); } var cfgCodeBlock = new CodeBlock(); cfgCodeBlock.Add(CodeLine.Of($"{signature} {{", $"{cfg.Function}")); cfgCodeBlock.Indent(); foreach (var block in cfg.Blocks) { var blockCodeBlock = new CodeBlock { Depth = cfgCodeBlock.Depth }; blockCodeBlock.Dedent(); blockCodeBlock.Add(CodeLine.Of($"L{block.Index}:;")); blockCodeBlock.Indent(); foreach (dynamic statement in block.Statements) { var c = CreateStatement(statement); blockCodeBlock.Add(c); } if (block.Child is BranchBlock bb) { var expression = bb.Expression; var(t, code) = ComputeTemporary(expression); var ifBlock = new CodeBlock { Depth = blockCodeBlock.Depth }; ifBlock.Add(code); ifBlock.Add(CodeLine.Of($"if ({t.Name}) goto L{bb.TrueBlock.Index};", $"{bb.Type.ToString().ToLower()} {bb.Expression}", bb.Expression.Token.Line)); ifBlock.Add(CodeLine.Of($"goto L{bb.FalseBlock.Index};", bb.Type == BranchBlockType.If ? "else" : "end while")); blockCodeBlock.Add(ifBlock); } else if (block.Child != null) { if (block.Child.Index != block.Index + 1) { blockCodeBlock.Add(CodeLine.Of($"goto L{block.Child.Index};")); } } else if (blockCodeBlock.Lines.Count > 0 && !blockCodeBlock.Lines[^ 1].Code.StartsWith("return")) { // TODO: default value, main returns 0? blockCodeBlock.Add(CodeLine.Of("return;")); } /*if (blockCodeBlock.Lines.Count == 0 || blockCodeBlock.Lines[^1].Code.StartsWith("return")) * { * // BlockCodeBlock.Dedent(); * _code.Add(blockCodeBlock); * continue; * } * * blockCodeBlock.Add(CodeLine.Of("return;")); * }*/ cfgCodeBlock.Add(blockCodeBlock); } cfgCodeBlock.Dedent(); cfgCodeBlock.Add(CodeLine.Of("}", cfg.Function.ToString())); _code.Add(cfgCodeBlock); _scopeStack.Pop(); } var output = ""; if (HasArrays) { _includes.Add("stdlib.h"); } output += string.Join("\n", _includes.Select(s => $"#include <{s}>")) + "\n\n"; if (HasArrays) { output += ArrayMacros; } if (HasAssert) { output += AssertionMacro; } output += string.Join("\n", _arrayDefinitions) + "\n\n"; output += string.Join("\n", _forwardDeclarations) + "\n\n"; output += string.Join("\n\n", _code); return(output); //string.Join("\n", _code); }