all repos — min @ 8b12c40913b7ce7ab4c1ec7aa2512817ac0d53d3

A small but practical concatenative programming language.

minpkg/core/vm.nim

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
import
    strutils,
    sequtils

import
    meta,
    baseutils,
    parser,
    interpreter,
    opcodes

proc newVM*(): MinVm =
    result.interpreter = newMinInterpreter("<vm>")

proc bytecode(s: string, symbol = false): seq[byte] =
    result = newSeq[byte](0)
    if symbol:
        result.add opSym.byte
        result.add s.len.byte
        for c in s:
            result.add c.ord.byte
    else:
        result.add opStrBeg.byte
        for c in s:
            result.add c.ord.byte
        result.add OpStrEnd.byte

proc bytecode(n: BiggestInt): seq[byte] =
    result = newSeq[byte](0)
    result.add opPushIn.byte
    result = result.concat(cast[array[0..7, byte]](n).toSeq)

proc bytecode(n: BiggestFloat): seq[byte] =
    result = newSeq[byte](0)
    result.add opPushFl.byte
    result = result.concat(cast[array[0..7, byte]](n).toSeq)

proc compileToBytecode*(vm: MinVm, s = ""): seq[byte] =
    result = newSeq[byte](0)
    result.add opHead.byte
    for c in pkgName:
        result.add c.ord.byte
    let v = pkgVersion.split(".")
    result.add v[0].parseInt.byte
    result.add v[1].parseInt.byte
    result.add v[2].parseInt.byte
    result.add opUndef.byte
    result.add opUndef.byte
    var p = vm.parser
    case p.token:
    of tkNull:
        result.add opPushNl.byte
        discard p.getToken()
    of tkTrue:
        result.add opPushTr.byte
        discard p.getToken()
    of tkFalse:
        result.add opPushFa.byte
        discard p.getToken()
    of tkInt:
        result = result.concat(p.a.parseInt.bytecode)
        p.a = ""
        discard p.getToken()
    of tkFloat:
        result = result.concat(p.a.parseFloat.bytecode)
        p.a = ""
        discard p.getToken()
    of tkString:
        result = result.concat(p.a.escapeEx.bytecode)
        p.a = ""
        discard p.getToken()
    of tkSymbol:
        result = result.concat(p.a.escapeEx.bytecode(true))
        p.a = ""
        discard p.getToken()
    else:
        raiseUndefined(p, "Undefined value: '"&p.a&"'")


proc printBytecode*(vm: MinVm, code: seq[byte]) =
    for b in code:
        echo b.toHex