All Downloads are FREE. Search and download functionalities are using the official Maven repository.

swam.syntax.pretty.package.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2018 Lucas Satabin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package swam
package syntax

import util.pretty._

package object pretty {

  implicit object LimitsPretty extends Pretty[Limits] {
    def pretty(l: Limits): Doc =
      l match {
        case Limits(min, Some(max)) => str("{min ") ++ int(min) ++ str(", max ") ++ int(max) ++ str("}")
        case Limits(min, None)      => str("{min ") ++ int(min) ++ str("}")
      }
  }

  implicit object MutPretty extends Pretty[Mut] {
    def pretty(m: Mut): Doc =
      m match {
        case Mut.Const => str("const")
        case Mut.Var   => str("var")
      }
  }

  implicit object TypePretty extends Pretty[Type] {
    def pretty(tpe: Type): Doc =
      tpe match {
        case ValType.I32      => str("i32")
        case ValType.I64      => str("i64")
        case ValType.F32      => str("f32")
        case ValType.F64      => str("f64")
        case ResultType(tpes) => str("[") ++ seq(str(", "), tpes) ++ str("]")
        case FuncType(params, result) =>
          str("[") ++ seq(str(", "), params) ++ str("] → [") ++ seq(str(", "), result) ++ str("]")
        case TableType(tpe, limits) => limits.pretty ++ space ++ tpe.pretty
        case MemType(limits)        => limits.pretty
        case GlobalType(tpe, mut)   => mut.pretty ++ space ++ tpe.pretty
        case ElemType.FuncRef       => str("funcref")
      }
  }

  implicit object BlockTypePretty extends Pretty[BlockType] {
    def pretty(bt: BlockType): Doc =
      bt match {
        case BlockType.NoType            => empty
        case BlockType.ValueType(tpe)    => tpe.pretty
        case BlockType.FunctionType(idx) => str("@") ++ int(idx)
      }
  }

  implicit object InstPretty extends Pretty[Inst] {

    def pretty(i: Inst): Doc =
      i match {
        case i32.Const(v)               => str(s"i32.const $v")
        case i32.Clz                    => str("i32.clz")
        case i32.Ctz                    => str("i32.ctz")
        case i32.Popcnt                 => str("i32.popcnt")
        case i32.Add                    => str("i32.add")
        case i32.Sub                    => str("i32.sub")
        case i32.Mul                    => str("i32.mul")
        case i32.DivS                   => str("i32.div_s")
        case i32.DivU                   => str("i32.div_u")
        case i32.RemS                   => str("i32.rem_s")
        case i32.RemU                   => str("i32.rem_u")
        case i32.And                    => str("i32.and")
        case i32.Or                     => str("i32.or")
        case i32.Xor                    => str("i32.xor")
        case i32.Shl                    => str("i32.shl")
        case i32.ShrS                   => str("i32.shr_s")
        case i32.ShrU                   => str("i32.shr_u")
        case i32.Rotl                   => str("i32.rotl")
        case i32.Rotr                   => str("i32.rotr")
        case i32.Eqz                    => str("i32.eqz")
        case i32.Eq                     => str("i32.eq")
        case i32.Ne                     => str("i32.ne")
        case i32.LtS                    => str("i32.lt_s")
        case i32.LtU                    => str("i32.lt_u")
        case i32.GtS                    => str("i32.gt_s")
        case i32.GtU                    => str("i32.gt_u")
        case i32.LeS                    => str("i32.le_s")
        case i32.LeU                    => str("i32.le_u")
        case i32.GeS                    => str("i32.ge_s")
        case i32.GeU                    => str("i32.ge_u")
        case i32.WrapI64                => str("i32.wrap_i64")
        case i32.TruncSF32              => str("i32.trunc_f32_s")
        case i32.TruncUF32              => str("i32.trunc_f32_u")
        case i32.TruncSF64              => str("i32.trunc_f64_s")
        case i32.TruncUF64              => str("i32.trunc_f64_u")
        case i32.TruncSatSF32           => str("i32.trunc_sat_f32_s")
        case i32.TruncSatUF32           => str("i32.trunc_sat_f32_u")
        case i32.TruncSatSF64           => str("i32.trunc_sat_f64_s")
        case i32.TruncSatUF64           => str("i32.trunc_sat_f64_u")
        case i32.ReinterpretF32         => str("i32.reinterpret_f32")
        case i32.Extend8S               => str("i32.extend8_s")
        case i32.Extend16S              => str("i32.extend16_s")
        case i32.Load(offset, align)    => str(s"i32.load {offset $offset, align $align}")
        case i32.Store(offset, align)   => str(s"i32.store {offset $offset, align $align}")
        case i32.Load8S(offset, align)  => str(s"i32.load8_s {offset $offset, align $align}")
        case i32.Load8U(offset, align)  => str(s"i32.load8_u {offset $offset, align $align}")
        case i32.Load16S(offset, align) => str(s"i32.load16_s {offset $offset, align $align}")
        case i32.Load16U(offset, align) => str(s"i32.load16_u {offset $offset, align $align}")
        case i32.Store8(offset, align)  => str(s"i32.store8 {offset $offset, align $align}")
        case i32.Store16(offset, align) => str(s"i32.store16 {offset $offset, align $align}")

        case i64.Const(v)               => str(s"i64.const $v")
        case i64.Clz                    => str("i64.clz")
        case i64.Ctz                    => str("i64.ctz")
        case i64.Popcnt                 => str("i64.popcnt")
        case i64.Add                    => str("i64.add")
        case i64.Sub                    => str("i64.sub")
        case i64.Mul                    => str("i64.mul")
        case i64.DivS                   => str("i64.div_s")
        case i64.DivU                   => str("i64.div_u")
        case i64.RemS                   => str("i64.rem_s")
        case i64.RemU                   => str("i64.rem_u")
        case i64.And                    => str("i64.and")
        case i64.Or                     => str("i64.or")
        case i64.Xor                    => str("i64.xor")
        case i64.Shl                    => str("i64.shl")
        case i64.ShrS                   => str("i64.shr_s")
        case i64.ShrU                   => str("i64.shr_u")
        case i64.Rotl                   => str("i64.rotl")
        case i64.Rotr                   => str("i64.rotr")
        case i64.Eqz                    => str("i64.eqz")
        case i64.Eq                     => str("i64.eq")
        case i64.Ne                     => str("i64.ne")
        case i64.LtS                    => str("i64.lt_s")
        case i64.LtU                    => str("i64.lt_u")
        case i64.GtS                    => str("i64.gt_s")
        case i64.GtU                    => str("i64.gt_u")
        case i64.LeS                    => str("i64.le_s")
        case i64.LeU                    => str("i64.le_u")
        case i64.GeS                    => str("i64.ge_s")
        case i64.GeU                    => str("i64.ge_u")
        case i64.ExtendSI32             => str("i64.extends_i32")
        case i64.ExtendUI32             => str("i64.extendu_i32")
        case i64.TruncSF32              => str("i64.trunc_f32_s")
        case i64.TruncUF32              => str("i64.trunc_f32_u")
        case i64.TruncSF64              => str("i64.trunc_f64_s")
        case i64.TruncUF64              => str("i64.trunc_f64_u")
        case i64.TruncSatSF32           => str("i64.trunc_sat_f32_s")
        case i64.TruncSatUF32           => str("i64.trunc_sat_f32_u")
        case i64.TruncSatSF64           => str("i64.trunc_sat_f64_s")
        case i64.TruncSatUF64           => str("i64.trunc_sat_f64_u")
        case i64.ReinterpretF64         => str("i64.reinterpret_f64")
        case i64.Extend8S               => str("i64.extend8_s")
        case i64.Extend16S              => str("i64.extend16_s")
        case i64.Extend32S              => str("i64.extend32_s")
        case i64.Load(offset, align)    => str(s"i64.load {offset $offset, align $align}")
        case i64.Store(offset, align)   => str(s"i64.store {offset $offset, align $align}")
        case i64.Load8S(offset, align)  => str(s"i64.load8_s {offset $offset, align $align}")
        case i64.Load8U(offset, align)  => str(s"i64.load8_u {offset $offset, align $align}")
        case i64.Load16S(offset, align) => str(s"i64.load16_s {offset $offset, align $align}")
        case i64.Load16U(offset, align) => str(s"i64.load16_u {offset $offset, align $align}")
        case i64.Load32S(offset, align) => str(s"i64.load32_s {offset $offset, align $align}")
        case i64.Load32U(offset, align) => str(s"i64.load32_u {offset $offset, align $align}")
        case i64.Store8(offset, align)  => str(s"i64.store8 {offset $offset, align $align}")
        case i64.Store16(offset, align) => str(s"i64.store16 {offset $offset, align $align}")
        case i64.Store32(offset, align) => str(s"i64.store32 {offset $offset, align $align}")

        case f32.Const(v)             => str(s"f32.const $v")
        case f32.Abs                  => str("f32.abs")
        case f32.Neg                  => str("f32.neg")
        case f32.Sqrt                 => str("f32.sqrt")
        case f32.Ceil                 => str("f32.ceil")
        case f32.Floor                => str("f32.floor")
        case f32.Trunc                => str("f32.trunc")
        case f32.Nearest              => str("f32.nearest")
        case f32.Add                  => str("f32.add")
        case f32.Sub                  => str("f32.sub")
        case f32.Mul                  => str("f32.mul")
        case f32.Div                  => str("f32.div")
        case f32.Min                  => str("f32.min")
        case f32.Max                  => str("f32.max")
        case f32.Copysign             => str("f32.copysign")
        case f32.Eq                   => str("f32.eq")
        case f32.Ne                   => str("f32.ne")
        case f32.Lt                   => str("f32.lt")
        case f32.Gt                   => str("f32.gt")
        case f32.Le                   => str("f32.le")
        case f32.Ge                   => str("f32.ge")
        case f32.DemoteF64            => str("f32.demote_f64")
        case f32.ConvertSI32          => str("f32.convert_i32_s")
        case f32.ConvertUI32          => str("f32.convert_i32_u")
        case f32.ConvertSI64          => str("f32.convert_i64_s")
        case f32.ConvertUI64          => str("f32.convert_i64_u")
        case f32.ReinterpretI32       => str("f32.reinterpret_i32")
        case f32.Load(offset, align)  => str(s"f32.load {offset $offset, align $align}")
        case f32.Store(offset, align) => str(s"f32.store {offset $offset, align $align}")

        case f64.Const(v)             => str(s"f64.const $v")
        case f64.Abs                  => str("f64.abs")
        case f64.Neg                  => str("f64.neg")
        case f64.Sqrt                 => str("f64.sqrt")
        case f64.Ceil                 => str("f64.ceil")
        case f64.Floor                => str("f64.floor")
        case f64.Trunc                => str("f64.trunc")
        case f64.Nearest              => str("f64.nearest")
        case f64.Add                  => str("f64.add")
        case f64.Sub                  => str("f64.sub")
        case f64.Mul                  => str("f64.mul")
        case f64.Div                  => str("f64.div")
        case f64.Min                  => str("f64.min")
        case f64.Max                  => str("f64.max")
        case f64.Copysign             => str("f64.copysign")
        case f64.Eq                   => str("f64.eq")
        case f64.Ne                   => str("f64.ne")
        case f64.Lt                   => str("f64.lt")
        case f64.Gt                   => str("f64.gt")
        case f64.Le                   => str("f64.le")
        case f64.Ge                   => str("f64.ge")
        case f64.PromoteF32           => str("f64.promote_f32")
        case f64.ConvertSI32          => str("f64.convert_i32_s")
        case f64.ConvertUI32          => str("f64.convert_i32_u")
        case f64.ConvertSI64          => str("f64.convert_i64_s")
        case f64.ConvertUI64          => str("f64.convert_i64_u")
        case f64.ReinterpretI64       => str("f64.reinterpret_i64")
        case f64.Load(offset, align)  => str(s"f64.load {offset $offset, align $align}")
        case f64.Store(offset, align) => str(s"f64.store {offset $offset, align $align}")

        case Drop   => str("drop")
        case Select => str("select")

        case LocalGet(idx)  => str(s"local.get $idx")
        case LocalSet(idx)  => str(s"local.set $idx")
        case LocalTee(idx)  => str(s"local.tee $idx")
        case GlobalGet(idx) => str(s"global.get $idx")
        case GlobalSet(idx) => str(s"global.set $idx")

        case MemorySize => str("memory.size")
        case MemoryGrow => str("memory.grow")

        case Nop         => str("nop")
        case Unreachable => str("unreachable")

        case Block(tpe, is) =>
          group(str("block") ++ space ++ tpe.pretty ++ nest(2, group(line ++ seq(line, is))) ++ line ++ str("end"))

        case Loop(tpe, is) =>
          group(str("loop") ++ space ++ tpe.pretty ++ nest(2, group(line ++ seq(line, is))) ++ line ++ str("end"))

        case If(tpe, t, e) =>
          group(
            str("if") ++ space ++ tpe.pretty ++ nest(2, group(line ++ seq(line, t))) ++ line ++ str("else") ++ nest(
              2,
              group(line ++ seq(line, e))) ++ line ++ str("end"))

        case Br(lbl)             => str(s"br $lbl")
        case BrIf(lbl)           => str(s"br_if $lbl")
        case BrTable(table, lbl) => str(s"br_table ${table.mkString(", ")} $lbl")
        case Return              => str("return")
        case Call(idx)           => str(s"call $idx")
        case CallIndirect(tpe)   => str(s"call_indirect $tpe")
      }

  }

  implicit object LocalEntryPretty extends Pretty[LocalEntry] {
    def pretty(le: LocalEntry): Doc =
      seq(newline, for (_ <- 0 until le.count) yield str("local") ++ space ++ le.tpe.pretty)
  }

  implicit object ImportPretty extends Pretty[Import] {
    def pretty(i: Import): Doc =
      i match {
        case Import.Function(module, field, tpe) =>
          str("{module ") ++ str(module) ++ str(", name ") ++ str(field) ++ str(", func ") ++ int(tpe) ++ str("}")
        case Import.Table(module, field, tpe) =>
          str("{module ") ++ str(module) ++ str(", name ") ++ str(field) ++ str(", table ") ++ tpe.pretty ++ str("}")
        case Import.Memory(module, field, tpe) =>
          str("{module ") ++ str(module) ++ str(", name ") ++ str(field) ++ str(",  mem ") ++ tpe.pretty ++ str("}")
        case Import.Global(module, field, tpe) =>
          str("{module ") ++ str(module) ++ str(", name ") ++ str(field) ++ str(",  global ") ++ tpe.pretty ++ str("}")
      }
  }

  implicit object ExportPretty extends Pretty[Export] {
    def pretty(e: Export): Doc = {
      val kind = e.kind match {
        case ExternalKind.Function => str("func ")
        case ExternalKind.Table    => str("table ")
        case ExternalKind.Memory   => str("mem ")
        case ExternalKind.Global   => str("global ")
      }
      str("{name ") ++ str(e.fieldName) ++ str(", ") ++ kind ++ int(e.index) ++ str("}")
    }
  }

  implicit object GlobalPretty extends Pretty[Global] {
    def pretty(g: Global): Doc =
      group(g.tpe.pretty ++ line ++ seq(line, g.init))
  }

  implicit object FuncBodyPretty extends Pretty[FuncBody] {
    def pretty(body: FuncBody): Doc =
      if (body.locals.isEmpty)
        seq(newline, body.code)
      else
        seq(newline, body.locals) ++ newline ++ seq(newline, body.code)
  }

  implicit object ElemPretty extends Pretty[Elem] {
    def pretty(elem: Elem): Doc =
      str("; table") ++ newline ++ int(elem.table) ++ newline ++ str("; offset") ++ newline ++ seq(newline, elem.offset) ++ newline ++ indexedseq(
        str("; func "),
        elem.init)
  }

  implicit object DataPretty extends Pretty[Data] {
    def pretty(data: Data): Doc =
      str("; memory") ++ newline ++ int(data.data) ++ newline ++ str("; offset") ++ newline ++ seq(newline, data.offset) ++ newline ++ str(
        "; data") ++ str(data.init.toHex)
  }

  implicit object SectionPretty extends Pretty[Section] {
    def pretty(s: Section): Doc =
      s match {
        case Section.Types(types) =>
          str("""; section "Types"""") ++ newline ++ indexedseq(str("; type "), types)
        case Section.Imports(imports) =>
          str("""; section "Imports"""") ++ newline ++ group(seq(newline, imports))
        case Section.Functions(tpes) =>
          str("""; section "Functions"""") ++ newline ++ indexedseq(str("; function type "), tpes)
        case Section.Tables(tables) =>
          str("""; section "Tables"""") ++ newline ++ indexedseq(str("; table "), tables)
        case Section.Memories(mems) =>
          str("""; section "Memories"""") ++ newline ++ indexedseq(str("; memory "), mems)
        case Section.Globals(globals) =>
          str("""; section "Globals"""") ++ newline ++ indexedseq(str("; global "), globals)
        case Section.Exports(exports) =>
          str("""; section "Exports"""") ++ newline ++ group(seq(newline, exports))
        case Section.Start(idx) =>
          str("""; section "Start"""") ++ newline ++ str("func ") ++ int(idx)
        case Section.Elements(elts) =>
          str("""; section "Elements"""") ++ newline ++ seq(newline, elts)
        case Section.Code(bodies) =>
          str("""; section "Code"""") ++ newline ++ group(indexedseq(str("; function body "), bodies))
        case Section.Datas(data) =>
          str("""; section "Data"""") ++ newline ++ seq(newline, data)
        case Section.Custom(name, payload) =>
          str("""; custom section """") ++ str(name) ++ str("\"") ++ newline ++ str(payload.toHex)
      }
  }

  private def indexedseq[T](prefix: Doc, s: Seq[T])(implicit T: Pretty[T]): Doc =
    group(seq(newline, s.zipWithIndex.map {
      case (t, idx) => prefix ++ int(idx) ++ newline ++ t.pretty
    }))

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy