logo

class

compiler::FMethod

sys::Obj
  compiler::FSlot
    compiler::FMethod : compiler::CMethod
//
// Copyright (c) 2006, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   26 Dec 05  Brian Frank  Creation
//   19 Aug 06  Brian Frank  Ported from Java to Fan
//

**
** FMethod is the read/write fcode representation of sys::Method.
**
class FMethod : FSlot, CMethod
{

//////////////////////////////////////////////////////////////////////////
// Constructor
//////////////////////////////////////////////////////////////////////////

  new make(FType fparent)
    : super(fparent)
  {
  }

//////////////////////////////////////////////////////////////////////////
// Access
//////////////////////////////////////////////////////////////////////////

  FMethodVar[] fparams()
  {
    return vars.findAll |FMethodVar v->Bool| { return v.isParam }
  }

//////////////////////////////////////////////////////////////////////////
// CMethod
//////////////////////////////////////////////////////////////////////////

  override CType returnType() { return fparent.fpod.toType(ret) }
  override CParam[] params() { return fparams }

  override Str signature()
  {
    return "$returnType $name(" + params.join(",") + ")"
  }

  override Bool isGeneric
  {
    get
    {
      if (@isGeneric == null) @isGeneric = calcGeneric(this)
      return @isGeneric
    }
  }

  override CType inheritedReturnType()
  {
    return fparent.fpod.toType(inheritedRet)
  }

//////////////////////////////////////////////////////////////////////////
// IO
//////////////////////////////////////////////////////////////////////////

  Void write(OutStream out)
  {
    super.writeCommon(out)
    out.writeI2(ret)
    out.writeI2(inheritedRet)
    out.write(maxStack)
    out.write(paramCount)
    out.write(localCount)
    vars.each |FMethodVar var| { var.write(out) }
    FUtil.writeBuf(out, code)
    super.writeAttrs(out)
  }

  FMethod read(InStream in)
  {
    super.readCommon(in)
    ret = in.readU2
    inheritedRet = in.readU2
    maxStack   = in.readU1
    paramCount = in.readU1
    localCount = in.readU1
    vars = FMethodVar[,];
    (paramCount+localCount).times |,| { vars.add(FMethodVar.make(this).read(in)) }
    code = FUtil.readBuf(in)
    super.readAttrs(in)
    return this
  }

  Void dump()
  {
    p := FPrinter.make(fparent.fpod)
    p.showCode = true
    p.method(this)
  }

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

  Int ret              // type qname index
  Int inheritedRet     // type qname index
  FMethodVar[] vars    // parameters and local variables
  Int paramCount       // number of params in vars
  Int localCount       // number of locals in vars
  Buf code             // method executable code
  Int maxStack := 16   // TODO - need to calculate in compiler

}

**************************************************************************
** FMethodVar
**************************************************************************

**
** FMethodVar models one parameter or local variable in a FMethod
**
class FMethodVar : FConst, CParam
{
  new make(FMethod fmethod) { this.fmethod = fmethod }

  override Str name() { return fpod.n(nameIndex) }
  override CType paramType() { return fpod.toType(typeRef) }
  override Bool hasDefault() { return def != null }
  override Str toStr() { return "$paramType $name" }

  Bool isParam()  { return flags & FConst.Param != 0 }

  Void write(OutStream out)
  {
    out.writeI2(nameIndex)
    out.writeI2(typeRef)
    out.write(flags)

    // we currently only support the DefaultParam attr
    if (def == null) out.writeI2(0)
    else
    {
      out.writeI2(1)
      out.writeI2(defNameIndex)
      FUtil.writeBuf(out, def)
    }
  }

  FMethodVar read(InStream in)
  {
    nameIndex = in.readU2
    typeRef   = in.readU2
    flags     = in.readU1

    // we currently only support the DefaultParam attr
    in.readU2.times |,|
    {
      attrNameIndex := in.readU2
      attrBuf  := FUtil.readBuf(in)
      if (fmethod.pod.n(attrNameIndex) == ParamDefaultAttr)
      {
        defNameIndex = attrNameIndex
        def = attrBuf
      }
    }
    return this
  }

  FPod fpod() { return fmethod.fparent.fpod }

  readonly FMethod fmethod
  Int nameIndex    // name index
  Int typeRef      // typeRef index
  Int flags        // method variable flags
  Int defNameIndex // name index of DefaultParamAttr
  Buf def          // default expression or null (only for params)

}