1

I am creating a GUI using Scala which should play a signal dependent on the algorithm but into the textField, eg. sin(2*Pi*400*t). The playing function works perfectly, however the issue is the input for the GUI. The textField takes the function and converts it to a string, now I was wondering is there a simple way to convert the string back into a function. I was considering matching the input to various valid functions, however I don't want to restrict the possible functions, as I want the user to be more create

I am still relatively new to Scala, hopefully one of you have a better idea. Here is the code I have so far, its a basic setup focusing on functionality.

object PlayApp extends SimpleGUIApplication {
  def top = new MainFrame {
    title = "Play Function App"
    val label = new Label("Type in function to be played")

    object Function extends TextField ( columns = 10)
    val label2 = new Label("Type in length of time to play")
    object Time extends TextField { columns = 10}  
    val button = new Button("Play")

    contents = new BoxPanel(Orientation.Vertical) {
      contents += label
      contents += Function
      contents += label2
      contents += Time
      contents += button
      border = Swing.EmptyBorder(50, 50, 20, 50)
    }

    var f = "sin(t)"
    var x = 0

    listenTo(Function, Time, button) 
    reactions += {
      case EditDone(Function) =>
        f = Function.text.toString
      case EditDone(Time)     =>
        x = Time.text.toInt
      case ButtonClicked(b)   =>
        play(t => f.toDouble,0,x)
    }
  }
}
  • What is the permitted grammar of the input? Check out parser combinators. The GUI aspect of this question seems to be irrelevant & may put people off reading it. – Luigi Plinge Dec 20 '12 at 15:00
  • Agree with Luigi: I expected a lonely unloved Swing question. Also agree that depending on what you mean by "creative", parse the expr yourself. – som-snytt Dec 20 '12 at 18:07
  • The input needs to be a mathematical expression, most likely a combination of sines and cosines at different frequencies. Thanks for the tip, I'll remove the GUI comments. By creative I meant that I didn't want to restrict the number or combination of sine and cosine, or limit other possible combinations by putting in cases for each option. – user1917645 Dec 20 '12 at 22:53

1 Answers1

1

You want to compile the line of code that the user enters, with some useful preamble.

I haven't done this so I don't have a snippet handy (but try searching), but you can embed the REPL, have it compile the line of code, and then extract the result.

Here is a snippet that uses ILoop to get some output, but you want to use IMain to get a result with the result class that wraps the user function.

import scala.tools.nsc.interpreter.ILoop
import java.io.StringReader
import java.io.StringWriter
import java.io.PrintWriter
import java.io.BufferedReader
import scala.tools.nsc.Settings

object FuncRunner extends App {

  val line = "sin(2 * Pi * 400 * t)"

  val lines = """import scala.math._
    |var t = 1""".stripMargin

  val in = new StringReader(lines + "\n" + line + "\nval f = (t: Int) => " + line)
  val out = new StringWriter

  val settings = new Settings

  val looper = new ILoop(new BufferedReader(in), new PrintWriter(out))
  val res = looper process settings
  Console println s"[$res] $out"
}
som-snytt
  • 39,429
  • 2
  • 47
  • 129