Fan

 

class

fansh::Main

sys::Obj
  fansh::Main
//
// Copyright (c) 2008, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   1 Jan 08  Brian Frank  Creation
//

using compiler

**
** Fan Shell
**
class Shell
{

//////////////////////////////////////////////////////////////////////////
// Main Loop
//////////////////////////////////////////////////////////////////////////

  **
  ** Run the shell main loop.
  **
  Void run()
  {
    warmup
    out.printLine("Fan Shell v${type.pod.version} ('?' for help)")
    while (isAlive)
    {
      // input next line
      out.print("fansh> ").flush
      line := in.readLine

      // quit on eof
      if (line == null) break

      // skip empty lines
      line = line.trim
      if (line.size == 0) continue

      // check if line maps to predefined command
      if (command(line)) continue

      // evaluate the line
      Evaluator(this).eval(line)
    }
  }

  private Void warmup()
  {
    // launch a dummy evaluator to preload
    // all the compiler code into memory
    f := |,| { Evaluator(null).eval("0") }
    Thread(null, f).start
  }

//////////////////////////////////////////////////////////////////////////
// Commands
//////////////////////////////////////////////////////////////////////////

  **
  ** If the line maps to a command function, then run
  ** it and return true.  Otherwise return false.
  **
  Bool command(Str line)
  {
    switch (line)
    {
      case "bye":
      case "exit":
      case "quit":
        quit
        return true
      case "help":
      case "usage":
      case "?":
        help
        return true
      case "clear":
        scope.clear
        return true
      case "scope":
        dumpScope
        return true
      default:
        return false
    }
  }

  **
  ** Run the 'quit' command.
  **
  Void quit()
  {
    isAlive = false
  }

  **
  ** Run the 'help' command.
  **
  Void help()
  {
    out.printLine
    out.printLine("Fan Shell v${type.pod.version}")
    out.printLine("Commands:")
    out.printLine("  quit, exit, bye   exit shell")
    out.printLine("  ?, help, usage    help summary")
    out.printLine("  clear             clear the local variables")
    out.printLine("  scope             dump the local variables")
    out.printLine
  }

  **
  ** Run the 'scope' command.
  **
  Void dumpScope()
  {
    out.printLine
    out.printLine("Current Scope:")
    scope.values.sort.each |Var v|
    {
      out.printLine("  $v.of $v.name = $v.val")
    }
    out.printLine
  }

//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////

  Var findInScope(Str name)
  {
    return scope.find |Var v->Bool| { return v.name == name }
  }

//////////////////////////////////////////////////////////////////////////
// Fields
//////////////////////////////////////////////////////////////////////////

  OutStream out := Sys.out
  InStream in := Sys.in
  internal Bool isAlive := true
  internal Int evalCount := 0
  internal Str:Var scope := Str:Var[:]

}

**************************************************************************
** Var
**************************************************************************

internal class Var
{
  override Int compare(Obj obj) { return ((Var)obj).name <=> name }

  Type of := Obj#
  Str name
  Obj? val
}

**************************************************************************
** Main
**************************************************************************

**
** Main launcher for fan shell.
**
class Main { static Void main() { Shell.make.run } }