logo

class

compiler::CheckParamDefs

sys::Obj
  compiler::CompilerSupport
    compiler::CompilerStep
      compiler::CheckParamDefs
  1  //
  2  // Copyright (c) 2006, Brian Frank and Andy Frank
  3  // Licensed under the Academic Free License version 3.0
  4  //
  5  // History:
  6  //   20 Jun 06  Brian Frank  Creation
  7  //    1 Oct 06  Brian Frank  Port from Java to Fan
  8  //
  9  
 10  **
 11  ** CheckParamDefs is used to process all the parameter default
 12  ** expressions for all the methods.  What we are looking for is
 13  ** default expressions which use default expressions before it
 14  ** which require us to insert a store instruction.
 15  **
 16  class CheckParamDefs : CompilerStep
 17  {
 18  
 19    new make(Compiler compiler)
 20      : super(compiler)
 21    {
 22    }
 23  
 24    override Void run()
 25    {
 26      walk(types, VisitDepth.slotDef)
 27    }
 28  
 29    override Void visitMethodDef(MethodDef m)
 30    {
 31      // unless there are two or more defaults don't bother
 32      params := m.paramDefs
 33      num := params.size
 34      if (num <= 1 || params[-2].def == null)
 35        return
 36  
 37      // if a def expr calculates a local used after it,
 38      // then we need to insert a store (local set)
 39      (num-1).times |Int i|
 40      {
 41        if (params[i].def == null) return
 42        if (usedInSuccDef(params, i))
 43        {
 44          param := params[i]
 45          var   := m.vars[i]
 46          loc   := param.location
 47  
 48          if (!param.name.equals(var.name)) throw err("invalid state", loc)
 49  
 50          param.def = BinaryExpr.makeAssign(LocalVarExpr.make(loc, var), param.def, true)
 51        }
 52      }
 53    }
 54  
 55    Bool usedInSuccDef(ParamDef[] params, Int index)
 56    {
 57      this.name = params[index].name
 58      for (i:=index+1; i<params.size; ++i)
 59      {
 60        this.used = false
 61        params[i].def.walk(this)
 62        if (this.used) return true
 63      }
 64      return false
 65    }
 66  
 67    override Expr visitExpr(Expr expr)
 68    {
 69      if (expr.id === ExprId.localVar)
 70      {
 71        local := (LocalVarExpr)expr
 72        if (name == local.var.name) used = true
 73      }
 74      return expr
 75    }
 76  
 77    Str name
 78    Bool used
 79  
 80  }