]> git.unchartedbackwaters.co.uk Git - francis/ofc.git/commitdiff
Implement Fortran line wrapping.
authorFrancis Russell <francis@unchartedbackwaters.co.uk>
Sun, 8 Apr 2012 03:34:44 +0000 (04:34 +0100)
committerFrancis Russell <francis@unchartedbackwaters.co.uk>
Sun, 8 Apr 2012 03:34:44 +0000 (04:34 +0100)
src/ofc/codegen/FortranGenerator.scala

index 5eca5e657866a6387bcc6c2e5bf058ec830b8b87..474644218e9821ee3858df7ee015a72a76e031db 100644 (file)
@@ -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._