def apply(stat: Statement) : String = {
processStatement(stat)
- buffer.prepend("\n")
- buffer.prependAll(symbolManager.getDeclarations)
+ prependLine("\n")
+ prependLines(symbolManager.getDeclarations)
FortranGenerator.wrapLines(buffer).mkString("\n")
}
+ def apply(func: Function[_ <: Type]) : String = {
+ in
+ processStatement(func.getBlock)
+ prependLine("\n")
+ prependLines(symbolManager.getDeclarations)
+ out
+
+ // parameters are only named after processing the body
+ val paramNames = func.getParameters.map(symbolManager.getName(_))
+ val (header, footer) = func.getReturnType match {
+ case (_: VoidType) => {
+ val header = "subroutine " + func.getName + paramNames.mkString("(", ", ", ")")
+ val footer = "end subroutine"
+ (header, footer)
+ }
+ case _ => throw new UnimplementedException("Fortran function code generation not implemented.")
+ }
+
+ prependLine(header)
+ addLine(footer)
+ FortranGenerator.wrapLines(buffer).mkString("\n")
+ }
+
+
private def processStatement(stat: Statement) {
stat match {
case (x : NullStatement) => ()
private def addLine(line: String) {
buffer += " "*indentLevel + line
}
+
+ private def prependLine(line: String) {
+ buffer.prepend(" "*indentLevel + line)
+ }
+
+ private def prependLines(lines: Seq[String]) {
+ for(line <- lines.reverse)
+ prependLine(line)
+ }
+
}
import ofc.InvalidInputException
import ofc.parser
+import ofc.codegen
import ofc.expression
import ofc.generators.onetep._
class Onetep extends Generator {
val dictionary = new Dictionary
+ var parameters : Map[String, codegen.VarSymbol[_ <: codegen.Type]] = Map.empty
+ var functionIdentifiers : Option[(String, Seq[String])] = None
def acceptInput(exprDictionary: expression.Dictionary, exprAssignment:
expression.Assignment, targetSpecific : Seq[parser.TargetAssignment]) {
buildDictionary(exprDictionary, targetSpecific)
+ val function = buildFunction(targetSpecific)
val assignment = new Assignment(buildScalarExpression(exprAssignment.lhs), buildScalarExpression(exprAssignment.rhs))
- val codeGenerator = new CodeGenerator(dictionary)
+ val codeGenerator = new CodeGenerator(dictionary, function.getBlock)
codeGenerator(assignment)
+
+ val generator = new codegen.FortranGenerator
+ val code = generator(function)
+ println(code)
}
private def buildDictionary(exprDictionary: expression.Dictionary, targetSpecific : Seq[parser.TargetAssignment]) {
}
}
+ private def buildFunction(targetSpecific : Seq[parser.TargetAssignment]) = {
+ import parser._
+ import codegen._
+
+ val outputCall = targetSpecific.filter(_.id == Identifier("output")) match {
+ case Seq(x) => x.value
+ case Seq(_,_,_*) => throw new InvalidInputException("Too many output function specifications.")
+ case Nil => throw new InvalidInputException("No output function specification found.")
+ }
+
+ outputCall match {
+ case FunctionCall(Identifier("FortranFunction"), callInfo) => callInfo match {
+ case ParameterList(StringParameter(funcName), funcParams: ParameterList) => {
+ val function = new Function(funcName, new VoidType)
+
+ for(funcParam <- funcParams.toSeq) funcParam match {
+ case StringParameter(paramName) => parameters.get(paramName) match {
+ case Some(symbol) => function.addParameter(symbol)
+ case None => throw new InvalidInputException("Unable to find definition of parameter "+paramName)
+ }
+ case _ => throw new InvalidInputException("FortranFunction only takes string parameters")
+ }
+
+ function
+ }
+ case _ => throw new InvalidInputException("FortranFunction takes a name and a parameter list.")
+ }
+ case _ => throw new InvalidInputException("Unknown output type "+outputCall.name)
+ }
+ }
+
private def getIndex(exprIndex: Seq[expression.Index]) : Seq[NamedIndex] = {
for(index <- exprIndex) yield
dictionary.getIndex(index.getIdentifier)
private def buildMatrix(id: parser.Identifier, call : Option[parser.FunctionCall]) {
import parser._
+ import codegen._
call match {
case Some(FunctionCall(matType, params)) => (matType, params) match {
- case (Identifier("SPAM3"), ParameterList(StringParameter(name))) =>
- dictionary.addScalar(id, new SPAM3(name, _: Seq[NamedIndex]))
+ case (Identifier("SPAM3"), ParameterList(StringParameter(name))) => {
+ val mat = new DeclaredVarSymbol[StructType](name, OnetepTypes.SPAM3)
+ parameters += (name -> mat)
+ dictionary.addScalar(id, new SPAM3(mat, _: Seq[NamedIndex]))
+ }
case _ => throw new InvalidInputException("Unknown usage of type: "+matType.name)
}
case _ => throw new InvalidInputException("Undefined concrete type for matrix: "+id.name)
private def buildFunctionSet(id: parser.Identifier, call : Option[parser.FunctionCall]) {
import parser._
+ import codegen._
call match {
case Some(FunctionCall(fSetType, params)) => (fSetType, params) match {
- case (Identifier("PPDFunctionSet"), ParameterList(StringParameter(basis), StringParameter(data))) =>
+ case (Identifier("PPDFunctionSet"), ParameterList(StringParameter(basisName), StringParameter(dataName))) => {
+ val basis = new DeclaredVarSymbol[StructType](basisName, OnetepTypes.FunctionBasis)
+ val data = new DeclaredVarSymbol[ArrayType[FloatType]](dataName, new ArrayType[FloatType](1))
+ parameters += (basisName -> basis)
+ parameters += (dataName -> data)
dictionary.addField(id, new PPDFunctionSet(basis, data, _: Seq[NamedIndex]))
+ }
case _ => throw new InvalidInputException("Unknown usage of type: "+fSetType.name)
}
case _ => throw new InvalidInputException("Undefined concrete type for function set: "+id.name)
}
}
-
- /*
- def buildBindingIndex(id: parser.Identifier, call : Option[parser.FunctionCall]) {
- call match {
- case Some(_) => throw new InvalidInputException("Index "+id.name+" cannot have concrete type.")
- case None => dictionary.indices += (id -> new BindingIndex(id.name))
- }
- }
-
- def buildDefinition(definition : parser.Definition) {
- val builder = new TreeBuilder(dictionary)
- val assignment = builder(definition.term, definition.expr)
- val codeGenerator = new CodeGenerator(builder.getIndexBindings)
- codeGenerator(assignment)
- }
-
- def buildDefinitions(statements : Seq[parser.Statement]) {
- val definitions = filterStatements[parser.Definition](statements)
- if (definitions.size != 1)
- throw new InvalidInputException("Input file should only contain a single definition.")
- else
- buildDefinition(definitions.head)
- }
- */
}
package ofc.generators.onetep
import ofc.codegen._
-class CodeGenerator(dictionary: Dictionary) {
- /*
- val indexSyms : Map[NamedIndex, DeclaredVarSymbol[IntType]] = {
- for(index <- dictionary.getIndices) yield
- (index, new DeclaredVarSymbol[IntType](index.getName))
- }.toMap
-
- val indexMap : Map[NamedIndex, Expression[IntType]] = {
- for((index, sym) <- indexSyms) yield
- (index, sym: Expression[IntType])
- }.toMap
- */
-
+class CodeGenerator(dictionary: Dictionary, scope: ScopeStatement) {
class Context extends GenerationContext {
val block = new BlockStatement
lhsFragment.setValue(context, rhsFragment.getValue)
rhsFragment.teardown(context)
- val generator = new FortranGenerator
val iterated = iterationInfo.getContext.toConcrete(context.getStatement)
- val code = generator(iterated)
- println(code)
+ scope += iterated;
}
}