From e09876367b377055447372247e69ef5e0fcb9133 Mon Sep 17 00:00:00 2001 From: Francis Russell Date: Sun, 8 Apr 2012 04:34:44 +0100 Subject: [PATCH] Implement Fortran line wrapping. --- src/ofc/codegen/FortranGenerator.scala | 96 +++++++++++++++++--------- 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/src/ofc/codegen/FortranGenerator.scala b/src/ofc/codegen/FortranGenerator.scala index 5eca5e6..4746442 100644 --- a/src/ofc/codegen/FortranGenerator.scala +++ b/src/ofc/codegen/FortranGenerator.scala @@ -51,11 +51,10 @@ class SymbolManager { }.toSeq.sorted } -class FortranGenerator { - private var indentLevel = 0 +object FortranGenerator { private val maxPrec = 30 - private val symbolManager = new SymbolManager - private val buffer = scala.collection.mutable.Buffer[String]() + + case class BinaryOpInfo(template: String, precedence: Int, assoc: BinaryOpInfo.Associativity) object BinaryOpInfo { sealed abstract class Associativity @@ -64,7 +63,65 @@ class FortranGenerator { object FUNCTION extends Associativity } - case class BinaryOpInfo(template: String, precedence: Int, assoc: BinaryOpInfo.Associativity) + private def getBinaryOpInfo(op: NumericOperations.CompareOp) : BinaryOpInfo = { + import NumericOperations._ + import BinaryOpInfo._ + op match { + case LT => BinaryOpInfo("%s .lt. %s", 16, LEFT) + case LE => BinaryOpInfo("%s .le. %s", 16, LEFT) + case EQ => BinaryOpInfo("%s .eq. %s", 16, LEFT) + case NE => BinaryOpInfo("%s .ne. %s", 16, LEFT) + case GT => BinaryOpInfo("%s .gt. %s", 16, LEFT) + case GE => BinaryOpInfo("%s .ge. %s", 16, LEFT) + case x => throw new UnimplementedException("Unknown comparison type in FORTRAN generator: "+x.toString) + } + } + + private def getBinaryOpInfo(op: NumericOperations.FieldOp) : BinaryOpInfo = { + import NumericOperations._ + import BinaryOpInfo._ + op match { + case Add => BinaryOpInfo("%s + %s", 22, LEFT) + case Sub => BinaryOpInfo("%s - %s", 22, LEFT) + case Mul => BinaryOpInfo("%s * %s", 26, LEFT) + case Div => BinaryOpInfo("%s / %s", 26, LEFT) + case Mod => BinaryOpInfo("mod(%s, %s)", maxPrec, FUNCTION) + case x => throw new UnimplementedException("Unknown numeric operator in FORTRAN generator: "+x.toString) + } + } + + private def wrapLine(line: String) : Seq[String] = { + // Fortran95 maximum line length is 132 characters, but let's assume people + // might want to indent further. + val maxLineLength = 120 + val buffer = scala.collection.mutable.Buffer[String]() + val marginMatch = "^\\s*".r + val margin = marginMatch.findFirstIn(line) match { + case Some(string) => string + case _ => "" + } + + var remaining = line.drop(margin.length) + while (remaining.length + margin.length > maxLineLength) { + val takeLength = maxLineLength - margin.length + 1 + val nextSubLine = margin + remaining.take(takeLength) + "&" + remaining = "&"+remaining.drop(takeLength) + buffer.append(nextSubLine) + } + buffer.append(margin + remaining) + buffer.toSeq + } + + private def wrapLines(lines: Seq[String]) : Seq[String] = lines.flatMap(wrapLine(_)) +} + +class FortranGenerator { + import FortranGenerator.{maxPrec, BinaryOpInfo, getBinaryOpInfo} + + private var indentLevel = 0 + private val symbolManager = new SymbolManager + private val buffer = scala.collection.mutable.Buffer[String]() + case class ExpHolder(prec: Int, exp: String) { override def toString = exp } @@ -74,7 +131,7 @@ class FortranGenerator { buffer.prepend("\n") buffer.prependAll(symbolManager.getDeclarations) - buffer.mkString("\n") + FortranGenerator.wrapLines(buffer).mkString("\n") } private def processStatement(stat: Statement) { @@ -133,33 +190,6 @@ class FortranGenerator { ExpHolder(maxPrec, name) } - private def getBinaryOpInfo(op: NumericOperations.CompareOp) : BinaryOpInfo = { - import NumericOperations._ - import BinaryOpInfo._ - op match { - case LT => BinaryOpInfo("%s .lt. %s", 16, LEFT) - case LE => BinaryOpInfo("%s .le. %s", 16, LEFT) - case EQ => BinaryOpInfo("%s .eq. %s", 16, LEFT) - case NE => BinaryOpInfo("%s .ne. %s", 16, LEFT) - case GT => BinaryOpInfo("%s .gt. %s", 16, LEFT) - case GE => BinaryOpInfo("%s .ge. %s", 16, LEFT) - case x => throw new UnimplementedException("Unknown comparison type in FORTRAN generator: "+x.toString) - } - } - - private def getBinaryOpInfo(op: NumericOperations.FieldOp) : BinaryOpInfo = { - import NumericOperations._ - import BinaryOpInfo._ - op match { - case Add => BinaryOpInfo("%s + %s", 22, LEFT) - case Sub => BinaryOpInfo("%s - %s", 22, LEFT) - case Mul => BinaryOpInfo("%s * %s", 26, LEFT) - case Div => BinaryOpInfo("%s / %s", 26, LEFT) - case Mod => BinaryOpInfo("mod(%s, %s)", maxPrec, FUNCTION) - case x => throw new UnimplementedException("Unknown numeric operator in FORTRAN generator: "+x.toString) - } - } - private def buildBinaryOperation(opInfo: BinaryOpInfo, left: ExpHolder, right: ExpHolder) : ExpHolder = { import BinaryOpInfo._ -- 2.47.3