HailScriptLoader.scala 18.6 KB
Newer Older
Kunshan Wang's avatar
Kunshan Wang committed
1
2
package uvm.refimpl.hail

Kunshan Wang's avatar
Kunshan Wang committed
3
import java.io.Reader
Kunshan Wang's avatar
Kunshan Wang committed
4
import scala.collection.JavaConversions._
Kunshan Wang's avatar
Kunshan Wang committed
5
6
7
8
import scala.collection.mutable.HashMap
import org.antlr.v4.runtime.ANTLRInputStream
import org.antlr.v4.runtime.CommonTokenStream
import org.antlr.v4.runtime.ParserRuleContext
Kunshan Wang's avatar
Kunshan Wang committed
9
10
import org.slf4j.LoggerFactory
import com.typesafe.scalalogging.Logger
Kunshan Wang's avatar
Kunshan Wang committed
11
import uvm.Function
Kunshan Wang's avatar
Kunshan Wang committed
12
13
14
import uvm.ir.textinput.TextIRParsingException
import uvm.ir.textinput.gen.HAILLexer
import uvm.ir.textinput.gen.HAILParser
Kunshan Wang's avatar
Kunshan Wang committed
15
16
import uvm.ir.textinput.gen.HAILParser._
import uvm.refimpl._
Kunshan Wang's avatar
Kunshan Wang committed
17
18
import uvm.refimpl.mem.HeaderUtils
import uvm.refimpl.mem.MemorySupport
Kunshan Wang's avatar
Kunshan Wang committed
19
import uvm.ssavariables._
Kunshan Wang's avatar
Kunshan Wang committed
20
import uvm.ssavariables.MemoryOrder.NOT_ATOMIC
Kunshan Wang's avatar
Kunshan Wang committed
21
22
import uvm.types._
import uvm.utils.AntlrHelpers._
Kunshan Wang's avatar
Kunshan Wang committed
23
24
25
26
27
28
import uvm.utils.IOHelpers
import uvm.utils.AdvancedAntlrHelper

object HailScriptLoader {
  val logger = Logger(LoggerFactory.getLogger(getClass.getName))
}
Kunshan Wang's avatar
Kunshan Wang committed
29

30
class HailScriptLoader(recordSourceInfo: Boolean = true)(implicit microVM: MicroVM, memorySupport: MemorySupport) {
Kunshan Wang's avatar
Kunshan Wang committed
31
32
33
34
35
36
  import HailScriptLoader._

  def loadHail(hailScript: Reader): Unit = {
    loadHail(IOHelpers.slurp(hailScript))
  }

Kunshan Wang's avatar
Kunshan Wang committed
37
  def loadHail(hailScript: String): Unit = {
Kunshan Wang's avatar
Kunshan Wang committed
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    val ais = new ANTLRInputStream(hailScript)
    val ea = new AccumulativeAntlrErrorListener(hailScript)

    val lexer = new HAILLexer(ais)
    lexer.removeErrorListeners()
    lexer.addErrorListener(ea)
    val tokens = new CommonTokenStream(lexer)
    val parser = new HAILParser(tokens)
    parser.removeErrorListeners()
    parser.addErrorListener(ea)
    val ast = parser.hail()
    if (ea.hasError) {
      throw new TextIRParsingException("Syntax error:\n" + ea.getMessages)
    }

Kunshan Wang's avatar
Kunshan Wang committed
53
    val mc = microVM.newContext()
54
    val ihsl = new InstanceHailScriptLoader(microVM, memorySupport, mc, hailScript, recordSourceInfo)
Kunshan Wang's avatar
Kunshan Wang committed
55
56
57
58
59
60
    try {
      ihsl.loadTopLevel(ast)
    } finally {
      mc.closeContext()
    }

Kunshan Wang's avatar
Kunshan Wang committed
61
  }
Kunshan Wang's avatar
Kunshan Wang committed
62
63
}

64
65
class InstanceHailScriptLoader(microVM: MicroVM, memorySupport: MemorySupport, mc: MuCtx, source: String,
    val recordSourceInfo: Boolean) extends AdvancedAntlrHelper {
Kunshan Wang's avatar
Kunshan Wang committed
66
67
68
  import HailScriptLoader._

  val sourceLines = source.lines.toIndexedSeq
Kunshan Wang's avatar
Kunshan Wang committed
69
70

  private type HailObjMap = HashMap[String, MuRefValue]
Kunshan Wang's avatar
Kunshan Wang committed
71
  val hailObjMap = new HailObjMap
Kunshan Wang's avatar
Kunshan Wang committed
72

Kunshan Wang's avatar
Kunshan Wang committed
73
74
75
76
77
78
79
80
81
82
  def loadTopLevel(ast: HailContext): Unit = {
    ast.topLevelDef.map(_.getChild(0)) foreach {
      case tl: FixedAllocContext => {
        val hailName = tl.nam.getText

        logger.debug("Executing fixed alloc: %s".format(tl.getText))

        val ty = resTy(tl.ty)
        if (ty.isInstanceOf[TypeHybrid]) {
          throw new UvmHailParsingException(inCtx(tl, "Cannot allocate hybrid using '.new'. Found: %s".format(ty)))
Kunshan Wang's avatar
Kunshan Wang committed
83
        }
Kunshan Wang's avatar
Kunshan Wang committed
84
85
86
        val obj = mc.newFixed(ty.id)
        if (hailObjMap.contains(hailName)) {
          throw new UvmHailParsingException(inCtx(tl, "HAIL name %s already used.".format(hailName)))
Kunshan Wang's avatar
Kunshan Wang committed
87
        }
Kunshan Wang's avatar
Kunshan Wang committed
88
        hailObjMap(hailName) = obj
Kunshan Wang's avatar
Kunshan Wang committed
89
      }
Kunshan Wang's avatar
Kunshan Wang committed
90
91
      case tl: HybridAllocContext => {
        val hailName = tl.nam.getText
Kunshan Wang's avatar
Kunshan Wang committed
92

Kunshan Wang's avatar
Kunshan Wang committed
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
        logger.debug("Executing hybrid alloc: %s".format(tl.getText))

        val ty = resTy(tl.ty)
        if (!ty.isInstanceOf[TypeHybrid]) {
          throw new UvmHailParsingException(inCtx(tl, "hybrid required. Found %s".format(ty)))
        }
        val len: Long = evalIntExpr(tl.len).toLong
        val hLen = mc.handleFromInt(len, 64)
        val obj = mc.newHybrid(ty.id, hLen)
        mc.deleteValue(hLen)
        if (hailObjMap.contains(hailName)) {
          throw new UvmHailParsingException(inCtx(tl, "HAIL name %s already used.".format(hailName)))
        }
        hailObjMap(hailName) = obj
      }
      case init: MemInitContext => {
        logger.debug("Executing init: %s".format(init.getText))
        val lv = evalLValue(init.lv)
        assign(lv, init.rv)
112
        mc.deleteValue(lv.iref)
Kunshan Wang's avatar
Kunshan Wang committed
113
      }
Kunshan Wang's avatar
Kunshan Wang committed
114
    }
Kunshan Wang's avatar
Kunshan Wang committed
115

Kunshan Wang's avatar
Kunshan Wang committed
116
117
118
  }

  class LValue private (val iref: MuIRefValue, val varLen: Option[Long], val baseCtx: ParserRuleContext, val curCtx: ParserRuleContext) {
Kunshan Wang's avatar
Kunshan Wang committed
119
    def indexInto(index: Long, ctx: ParserRuleContext): LValue = {
Kunshan Wang's avatar
Kunshan Wang committed
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
      val (newIRef, newVarLen) = varLen match {
        case None => { // not in the var-part of a hybrid
          iref.ty.ty match {
            case t: TypeStruct => {
              val ii = index.toInt
              if (ii < 0 || ii >= t.fieldTys.length) {
                throw new UvmHailParsingException(inCtx(ctx, "Index out of bound. Struct %s has %d fields. Found index: %d".format(
                  t, t.fieldTys.length, ii)))
              }
              val nir = mc.getFieldIRef(iref, index.toInt)
              (nir, None)
            }
            case t: TypeHybrid => {
              val ii = index.toInt
              if (ii < 0 || ii > t.fieldTys.length) {
Kunshan Wang's avatar
Kunshan Wang committed
135
136
                throw new UvmHailParsingException(inCtx(ctx, "Index out of bound. Hybrid %s has %d fields (%d-%d). Var part index is %d. Found index: %d".format(
                  t, t.fieldTys.length, 0, t.fieldTys.length - 1, t.fieldTys.length, ii)))
Kunshan Wang's avatar
Kunshan Wang committed
137
138
139
140
              }
              if (ii == t.fieldTys.length) {
                val nir = mc.getVarPartIRef(iref)
                // For debug purpose, we keep the upperbound recorded. Out-of-bound access has undefined behaviour.
Kunshan Wang's avatar
Kunshan Wang committed
141
                val len = HeaderUtils.getVarLength(iref.vb.objRef)(memorySupport)
Kunshan Wang's avatar
Kunshan Wang committed
142
                (nir, Some(len))
Kunshan Wang's avatar
Kunshan Wang committed
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
              } else {
                val nir = mc.getFieldIRef(iref, index.toInt)
                (nir, None)
              }
            }
            case t: AbstractSeqType => {
              val ii = index.toLong
              if (ii < 0 || ii >= t.len) {
                throw new UvmHailParsingException(inCtx(ctx, "Index out of bound. Sequence type %s has %d elements. Found index: %d".format(
                  t, t.len, ii)))
              }
              val hII = mc.handleFromInt(ii, 64)
              val nir = mc.getElemIRef(iref, hII)
              mc.deleteValue(hII)
              (nir, None)
            }
          }
        }
        case Some(l) => { // in the var-part of a hybrid
          val ii = index.toLong
          if (ii < 0 || ii >= l) {
            throw new UvmHailParsingException(inCtx(ctx, "Index out of bound. Hybrid %s has %d actual var-part elements. Found index: %d".format(
              iref.ty, l, ii)))
          }
          val hII = mc.handleFromInt(ii, 64)
          val nir = mc.shiftIRef(iref, hII)
          mc.deleteValue(hII)
          (nir, None)
        }
      }
Kunshan Wang's avatar
Kunshan Wang committed
173

Kunshan Wang's avatar
Kunshan Wang committed
174
175
176
177
178
      new LValue(newIRef, newVarLen, baseCtx, ctx)
    }
  }

  object LValue {
Kunshan Wang's avatar
Kunshan Wang committed
179
    def forName(name: String, baseCtx: ParserRuleContext): LValue = {
Kunshan Wang's avatar
Kunshan Wang committed
180
181
182
183
184
185
186
187
188
      val base = name.charAt(0) match {
        case '@' => {
          val global = microVM.globalBundle.globalCellNs.get(name).getOrElse {
            throw new UvmHailParsingException(inCtx(baseCtx, "Global cell %s not found".format(name)))
          }
          val gc = mc.handleFromGlobal(global.id)
          gc
        }
        case '$' => {
Kunshan Wang's avatar
Kunshan Wang committed
189
          val ref = resHailRef(name, baseCtx)
Kunshan Wang's avatar
Kunshan Wang committed
190
191
192
193
          val iref = mc.getIRef(ref)
          iref
        }
      }
Kunshan Wang's avatar
Kunshan Wang committed
194

Kunshan Wang's avatar
Kunshan Wang committed
195
196
197
198
      new LValue(base, None, baseCtx, baseCtx)
    }
  }

Kunshan Wang's avatar
Kunshan Wang committed
199
  def evalLValue(lv: LValueContext): LValue = {
Kunshan Wang's avatar
Kunshan Wang committed
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
    val base = LValue.forName(lv.nam.getText, lv)

    var cur: LValue = base

    for (ic <- lv.indices) {
      val index = evalIntExpr(ic.intExpr()).toLong
      val newCur = cur.indexInto(index, ic)
      val oldCur = cur
      cur = newCur
      mc.deleteValue(oldCur.iref)
    }

    cur
  }

Kunshan Wang's avatar
Kunshan Wang committed
215
  def assign(lv: LValue, rv: RValueContext): Unit = {
Kunshan Wang's avatar
Kunshan Wang committed
216
217
218
    val lir = lv.iref
    val lty = lir.ty.ty // LValue referent type.

Kunshan Wang's avatar
Kunshan Wang committed
219
220
    // error reporting

Kunshan Wang's avatar
Kunshan Wang committed
221
    def unexpectedRValueError(): Nothing = {
Kunshan Wang's avatar
Kunshan Wang committed
222
      throw new UvmHailParsingException(inCtx(rv, "Unsuitable RValue %s for LValue type %s".format(rv.getText, lty)))
Kunshan Wang's avatar
Kunshan Wang committed
223
224
225
226
227
228
229
    }

    def unexpectedGlobalTypeError(gv: GlobalVariable): Nothing = {
      throw new UvmHailParsingException(inCtx(rv, "Unsuitable global variable type. Expected: %s, Found: %s".format(
        lty, TypeInferer.inferType(gv))))
    }

Kunshan Wang's avatar
Kunshan Wang committed
230
231
    // Reused by their types as well as tagref64

Kunshan Wang's avatar
Kunshan Wang committed
232
    def resForDoubleType(rv: RValueContext): MuDoubleValue = {
Kunshan Wang's avatar
Kunshan Wang committed
233
234
235
236
237
238
239
240
      rv match {
        case fl: RVDoubleContext         => mc.handleFromDouble(fl.doubleLiteral)
        case RVGlobalOf(gv: ConstDouble) => mc.handleFromConst(gv.id).asInstanceOf[MuDoubleValue]
        case RVGlobalOf(gv)              => unexpectedGlobalTypeError(gv)
        case _                           => unexpectedRValueError()
      }
    }

Kunshan Wang's avatar
Kunshan Wang committed
241
    def resForIntType(rv: RValueContext, len: Int): MuIntValue = {
Kunshan Wang's avatar
Kunshan Wang committed
242
243
244
245
246
247
248
249
      rv match {
        case il: RVIntContext                         => mc.handleFromInt(il.intLiteral, len)
        case RVGlobalOf(gv @ ConstInt(_: TypeInt, _)) => mc.handleFromConst(gv.id).asInstanceOf[MuIntValue]
        case RVGlobalOf(gv)                           => unexpectedGlobalTypeError(gv)
        case _                                        => unexpectedRValueError()
      }
    }

Kunshan Wang's avatar
Kunshan Wang committed
250
    def resForRefType(rv: RValueContext): (MuRefValue, Boolean) = {
Kunshan Wang's avatar
Kunshan Wang committed
251
252
253
254
255
256
257
      rv match {
        case nu: RVNullContext    => (mc.handleFromConst(InternalTypes.NULL_REF_VOID.id).asInstanceOf[MuRefValue], true)
        case hr: RVHailRefContext => (resRVHailRef(hr), false)
        case _                    => unexpectedRValueError()
      }
    }

Kunshan Wang's avatar
Kunshan Wang committed
258
    def resForTagRef64Type(rv: RValueContext): MuTagRef64Value = {
Kunshan Wang's avatar
Kunshan Wang committed
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
      val (kind, hv) = rv match {
        case fl: RVDoubleContext         => (1, mc.handleFromDouble(fl.doubleLiteral))
        case RVGlobalOf(gv: ConstDouble) => (1, mc.handleFromConst(gv.id).asInstanceOf[MuDoubleValue])
        case il: RVIntContext            => (2, mc.handleFromInt(il.intLiteral, 52))
        case RVGlobalOf(gv: ConstInt)    => (2, mc.handleFromConst(gv.id).asInstanceOf[MuIntValue])
        case lst: RVListContext => {
          val elems = lst.list.rv.toSeq
          elems match {
            case Seq(rv1, rv2) => {
              val (hr, del) = resForRefType(rv1)
              val ht = resForIntType(rv2, 6)
              val r = mc.tr64FromRef(hr, ht)
              if (del) mc.deleteValue(hr)
              mc.deleteValue(ht)
              (3, r)
            }
            case _ => unexpectedRValueError()
          }
        }
        case RVGlobalOf(gv) => unexpectedGlobalTypeError(gv)
        case _              => unexpectedRValueError()
      }

      kind match {
        case 1 => { val r = mc.tr64FromFp(hv.asInstanceOf[MuDoubleValue]); mc.deleteValue(hv); r }
        case 2 => { val r = mc.tr64FromInt(hv.asInstanceOf[MuIntValue]); mc.deleteValue(hv); r }
        case 3 => { hv.asInstanceOf[MuTagRef64Value] }
      }
    }

    // actual assigning

Kunshan Wang's avatar
Kunshan Wang committed
291
292
293
294
295
296
297
298
299
300
    if (lv.varLen.isDefined || lty.isInstanceOf[AbstractCompositeType]) {
      rv match {
        case lst: RVListContext => {
          val elems = lst.list.rv.toSeq
          for ((innerRv, i) <- elems.zipWithIndex) {
            val innerLv = lv.indexInto(i, innerRv)
            assign(innerLv, innerRv)
          }
        }
        case _ => unexpectedRValueError()
Kunshan Wang's avatar
Kunshan Wang committed
301
      }
302
303
304
305
306
307
308
309
310
311
312
    } else if (rv.isInstanceOf[RVValueOfContext]) {
      val vo = rv.asInstanceOf[RVValueOfContext]
      val rir = evalLValue(vo.lValue()).iref
      val rval = mc.load(NOT_ATOMIC, rir)
      try {
        mc.store(NOT_ATOMIC, lir, rval)
      } catch {
        case e: Exception => throw new UvmHailParsingException(inCtx(rv, "Failed to store to LValue. Actual RValue: %s".format(rval)), e)
      }
      mc.deleteValue(rir)
      mc.deleteValue(rval)
Kunshan Wang's avatar
Kunshan Wang committed
313
314
315
316
317
318
319
    } else {
      lty match {
        case TypeInt(len) => {
          val hi = resForIntType(rv, len)
          mc.store(NOT_ATOMIC, lir, hi)
          mc.deleteValue(hi)
        }
Kunshan Wang's avatar
Kunshan Wang committed
320

Kunshan Wang's avatar
Kunshan Wang committed
321
322
323
324
325
326
327
328
329
        case t @ TypeUPtr(_) => {
          val hi = rv match {
            case il: RVIntContext                          => mc.handleFromPtr(t.id, il.intLiteral.toLong)
            case RVGlobalOf(gv @ ConstInt(_: TypeUPtr, _)) => mc.handleFromConst(gv.id).asInstanceOf[MuUPtrValue]
            case RVGlobalOf(gv)                            => unexpectedGlobalTypeError(gv)
            case _                                         => unexpectedRValueError()
          }
          mc.store(NOT_ATOMIC, lir, hi)
          mc.deleteValue(hi)
Kunshan Wang's avatar
Kunshan Wang committed
330
        }
Kunshan Wang's avatar
Kunshan Wang committed
331
332
333
334
335
336
337
338
339
340
        case t @ TypeUFuncPtr(_) => {
          val hi = rv match {
            case il: RVIntContext => mc.handleFromFP(t.id, il.intLiteral.toLong)
            case RVGlobalOf(gv @ ConstInt(_: TypeUFuncPtr, _)) => mc.handleFromConst(gv.id).asInstanceOf[MuUFPValue]
            case RVGlobalOf(gv: ExposedFunc) => mc.handleFromExpose(gv.id).asInstanceOf[MuUFPValue]
            case RVGlobalOf(gv) => unexpectedGlobalTypeError(gv)
            case _ => unexpectedRValueError()
          }
          mc.store(NOT_ATOMIC, lir, hi)
          mc.deleteValue(hi)
Kunshan Wang's avatar
Kunshan Wang committed
341
        }
Kunshan Wang's avatar
Kunshan Wang committed
342

Kunshan Wang's avatar
Kunshan Wang committed
343
344
345
346
347
348
349
350
351
        case TypeFloat() => {
          val hf = rv match {
            case fl: RVFloatContext         => mc.handleFromFloat(fl.floatLiteral)
            case RVGlobalOf(gv: ConstFloat) => mc.handleFromConst(gv.id)
            case RVGlobalOf(gv)             => unexpectedGlobalTypeError(gv)
            case _                          => unexpectedRValueError()
          }
          mc.store(NOT_ATOMIC, lir, hf)
          mc.deleteValue(hf)
Kunshan Wang's avatar
Kunshan Wang committed
352
        }
Kunshan Wang's avatar
Kunshan Wang committed
353
354
355
356
        case TypeDouble() => {
          val hf = resForDoubleType(rv)
          mc.store(NOT_ATOMIC, lir, hf)
          mc.deleteValue(hf)
Kunshan Wang's avatar
Kunshan Wang committed
357
        }
Kunshan Wang's avatar
Kunshan Wang committed
358
359
360
361
        case _: AbstractObjRefType => {
          val (hr, del) = resForRefType(rv)
          mc.store(NOT_ATOMIC, lir, hr)
          if (del) mc.deleteValue(hr)
Kunshan Wang's avatar
Kunshan Wang committed
362
        }
Kunshan Wang's avatar
Kunshan Wang committed
363
364
365
366
367
368
369
370
371
372
        case t: TypeIRef => {
          val hr = rv match {
            case nu: RVNullContext          => mc.handleFromConst(InternalTypes.NULL_IREF_VOID.id)
            case io: RVIRefOfContext        => evalLValue(io.lValue()).iref
            case RVGlobalOf(gv: GlobalCell) => mc.handleFromGlobal(gv.id)
            case RVGlobalOf(gv)             => unexpectedGlobalTypeError(gv)
            case _                          => unexpectedRValueError()
          }
          mc.store(NOT_ATOMIC, lir, hr)
          mc.deleteValue(hr)
Kunshan Wang's avatar
Kunshan Wang committed
373
        }
Kunshan Wang's avatar
Kunshan Wang committed
374
375
376
377
378
379
380
381
382
        case t: TypeFuncRef => {
          val hr = rv match {
            case nu: RVNullContext        => mc.handleFromConst(InternalTypes.NULL_FUNCREF_VV.id)
            case RVGlobalOf(gv: Function) => mc.handleFromFunc(gv.id)
            case RVGlobalOf(gv)           => unexpectedGlobalTypeError(gv)
            case _                        => unexpectedRValueError()
          }
          mc.store(NOT_ATOMIC, lir, hr)
          mc.deleteValue(hr)
Kunshan Wang's avatar
Kunshan Wang committed
383
        }
Kunshan Wang's avatar
Kunshan Wang committed
384
385
386
387
        case t: TypeThreadRef => {
          val hr = rv match {
            case nu: RVNullContext => mc.handleFromConst(InternalTypes.NULL_THREADREF.id)
            case _                 => unexpectedRValueError()
Kunshan Wang's avatar
Kunshan Wang committed
388
          }
Kunshan Wang's avatar
Kunshan Wang committed
389
390
          mc.store(NOT_ATOMIC, lir, hr)
          mc.deleteValue(hr)
Kunshan Wang's avatar
Kunshan Wang committed
391
        }
Kunshan Wang's avatar
Kunshan Wang committed
392
393
394
395
396
397
398
399
400
401
402
403
404
405
        case t: TypeStackRef => {
          val hr = rv match {
            case nu: RVNullContext => mc.handleFromConst(InternalTypes.NULL_STACKREF.id)
            case _                 => unexpectedRValueError()
          }
          mc.store(NOT_ATOMIC, lir, hr)
          mc.deleteValue(hr)
        }
        case t: TypeTagRef64 => {
          val hr = resForTagRef64Type(rv)
          mc.store(NOT_ATOMIC, lir, hr)
          mc.deleteValue(hr)
        }
        case _ => unexpectedRValueError()
Kunshan Wang's avatar
Kunshan Wang committed
406
      }
Kunshan Wang's avatar
Kunshan Wang committed
407
408
409
410
411
    }
  }

  def evalIntExpr(ie: IntExprContext): BigInt = {
    ie match {
Kunshan Wang's avatar
Kunshan Wang committed
412
      case i: IntLitContext    => IntLiteralToBigInt(i.intLiteral())
Kunshan Wang's avatar
Kunshan Wang committed
413
414
415
416
417
418
419
420
421
422
423
424
425
426
      case i: IntGlobalContext => resConstInt(i)
    }
  }

  val IntRe = """([+-]?)(0x|0|)([0-9a-fA-F]*)""".r

  implicit def IntLiteralToBigInt(il: IntLiteralContext): BigInt = {
    val txt = il.getText()

    txt match {
      case IntRe(sign, prefix, nums) => {
        val neg = sign match {
          case "+" => false
          case "-" => true
Kunshan Wang's avatar
Kunshan Wang committed
427
          case ""  => false
Kunshan Wang's avatar
Kunshan Wang committed
428
429
430
        }
        val abs = prefix match {
          case "0x" => BigInt(nums, 16)
Kunshan Wang's avatar
Kunshan Wang committed
431
432
          case "0"  => if (nums == "") BigInt(0) else BigInt(nums, 8)
          case ""   => BigInt(nums, 10)
Kunshan Wang's avatar
Kunshan Wang committed
433
434
435
436
437
438
439
440
441
442
443
444
445
        }
        return if (neg) -abs else abs
      }
    }
  }

  implicit def floatLiteralToFloat(fl: FloatLiteralContext): Float = fl match {
    case num: FloatNumberContext => num.FP_NUM.getText.toFloat
    case fi: FloatInfContext => {
      if (fi.getText.startsWith("-"))
        java.lang.Float.NEGATIVE_INFINITY
      else java.lang.Float.POSITIVE_INFINITY
    }
Kunshan Wang's avatar
Kunshan Wang committed
446
    case _: FloatNanContext     => java.lang.Float.NaN
Kunshan Wang's avatar
Kunshan Wang committed
447
448
449
450
451
452
453
454
455
456
    case bits: FloatBitsContext => java.lang.Float.intBitsToFloat(bits.intLiteral().intValue())
  }

  implicit def doubleLiteralToDouble(dl: DoubleLiteralContext): Double = dl match {
    case num: DoubleNumberContext => num.FP_NUM.getText.toDouble
    case fi: DoubleInfContext => {
      if (fi.getText.startsWith("-"))
        java.lang.Double.NEGATIVE_INFINITY
      else java.lang.Double.POSITIVE_INFINITY
    }
Kunshan Wang's avatar
Kunshan Wang committed
457
    case _: DoubleNanContext     => java.lang.Double.NaN
Kunshan Wang's avatar
Kunshan Wang committed
458
459
    case bits: DoubleBitsContext => java.lang.Double.longBitsToDouble(bits.intLiteral().longValue())
  }
Kunshan Wang's avatar
Kunshan Wang committed
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490

  def catchIn[T](ctx: ParserRuleContext, s: String)(func: => T): T = try {
    func
  } catch {
    case e: UvmHailParsingException => throw new UvmHailParsingException(inCtx(ctx, e.getMessage), e)
    case e: Exception               => throw new UvmHailParsingException(inCtx(ctx, s), e)
  }

  implicit def resTy(ctx: TypeContext): Type = catchIn(ctx, "Unable to resolve type") { resTyByName(ctx.getText) }
  private def resTyByName(name: String): Type = microVM.globalBundle.typeNs(name)

  implicit def resConstInt(ctx: IntGlobalContext): BigInt = catchIn(ctx, "Unable to resolve constant int") { resConstIntByName(ctx.getText) }
  private def resConstIntByName(name: String): BigInt = {
    val const = microVM.globalBundle.constantNs.get(name).getOrElse {
      throw new UvmHailParsingException("Type %s not found".format(name))
    }

    const match {
      case ConstInt(ty, num) => num
      case _                 => throw new UvmHailParsingException("Expected constant int. Found %s: ty=".format(const.repr, const.constTy))
    }
  }

  def resRVGlobal(ctx: RVGlobalContext): GlobalVariable = {
    val name = ctx.GLOBAL_NAME.getText
    val gv = microVM.globalBundle.globalVarNs.get(name).getOrElse {
      throw new UvmHailParsingException(inCtx(ctx, "Global variable %s not found".format(name)))
    }
    gv
  }

Kunshan Wang's avatar
Kunshan Wang committed
491
492
493
  def resHailRef(name: String, ctx: ParserRuleContext): MuRefValue = {
    hailObjMap.getOrElse(name, {
      throw new UvmHailParsingException(inCtx(ctx, "HAIL name %s not defined. It needs to be defined BEFORE use.".format(name)))
Kunshan Wang's avatar
Kunshan Wang committed
494
    })
Kunshan Wang's avatar
Kunshan Wang committed
495
496
497
498
499
  }

  def resRVHailRef(hrc: RVHailRefContext): MuRefValue = {
    val name = hrc.HAIL_NAME().getText
    resHailRef(name, hrc)
Kunshan Wang's avatar
Kunshan Wang committed
500
501
502
503
504
505
  }

  def rvListCtxToSeq(rvc: RVListContext): Seq[RValueContext] = {
    rvc.list.rv.toSeq
  }

Kunshan Wang's avatar
Kunshan Wang committed
506
507
508
509
510
511
  object RVGlobalOf {
    def unapply(g: RVGlobalContext): Option[GlobalVariable] = {
      val gv = resRVGlobal(g)
      Some(gv)
    }
  }
Kunshan Wang's avatar
Kunshan Wang committed
512
}