func (e *Emitter) registerK(fn *bytecode.Fn, val interface{}, isName bool, local bool) uint64 { var kt bytecode.KType s, ok := val.(string) if ok { if isName { val = s kt = bytecode.KtString } else if s[0] == '"' || s[0] == '`' { // Unquote the string, keeping escaped characters var err error s, err = strconv.Unquote(s) e.assert(err == nil, err) val = s kt = bytecode.KtString } else if strings.Index(s, ".") >= 0 { val, e.err = strconv.ParseFloat(s, 64) kt = bytecode.KtFloat } else { val, e.err = strconv.ParseInt(s, 10, 64) kt = bytecode.KtInteger } } else { kt = bytecode.KtBoolean if v := val.(bool); v { s = "true" val = int64(1) } else { s = "false" val = int64(0) } } // Create the map slot for this function if this is its first symbol m, ok := e.kMap[fn] if !ok { m = make(map[kId]int) e.kMap[fn] = m } // Check if this symbol already exists for this fn with this same type, otherwise add it to its Ks i, ok := m[kId{s, kt}] if !ok { i = len(m) m[kId{s, kt}] = i fn.Ks = append(fn.Ks, &bytecode.K{Type: kt, Val: val}) } // If this is a local definition, add the K index to this function's L table. // It can't have duplicates by definition, because it would have been caught as an // error in the parser stage. if local { fn.Ls = append(fn.Ls, int64(i)) } return uint64(i) }
func (e *Emitter) addInstr(fn *bytecode.Fn, op bytecode.Opcode, flg bytecode.Flag, ix uint64) { if e.err != nil { return } switch op { case bytecode.OP_PUSH: e.stackSz[fn] += 1 case bytecode.OP_NEW: e.stackSz[fn] += (1 - (2 * int64(ix))) case bytecode.OP_POP, bytecode.OP_RET, bytecode.OP_UNM, bytecode.OP_NOT, bytecode.OP_TEST, bytecode.OP_LT, bytecode.OP_LTE, bytecode.OP_GT, bytecode.OP_GTE, bytecode.OP_EQ, bytecode.OP_ADD, bytecode.OP_SUB, bytecode.OP_MUL, bytecode.OP_DIV, bytecode.OP_MOD, bytecode.OP_GFLD, bytecode.OP_NEQ: e.stackSz[fn] -= 1 case bytecode.OP_SFLD: e.stackSz[fn] -= 3 case bytecode.OP_CALL: e.stackSz[fn] -= (int64(ix) + 1) case bytecode.OP_CFLD: e.stackSz[fn] -= (int64(ix) + 2) } if e.stackSz[fn] > fn.Header.StackSz { fn.Header.StackSz = e.stackSz[fn] } fn.Is = append(fn.Is, bytecode.NewInstr(op, flg, ix)) }
func (a *Asm) readKs(fn *bytecode.Fn) { // While the L section is not reached for l, ok := a.getLine(true); ok && l != "[l]"; l, ok = a.getLine(true) { var err error k := new(bytecode.K) // The K Type is the first character of the line k.Type = bytecode.KType(l[0]) switch k.Type { case bytecode.KtInteger, bytecode.KtBoolean: // Finish the trim val := strings.TrimRight(l[1:], " \t") k.Val, err = strconv.ParseInt(val, 10, 64) case bytecode.KtFloat: val := strings.TrimRight(l[1:], " \t") k.Val, err = strconv.ParseFloat(val, 64) default: // Untrimmed string value k.Val = l[1:] } fn.Ks = append(fn.Ks, k) if err != nil && a.err == nil { a.err = err } } a.readLs(fn) }
func (a *Asm) readLs(fn *bytecode.Fn) { // While the L section is not reached for l, ok := a.getLine(false); ok && l != "[i]"; l, ok = a.getLine(false) { var i int64 i, a.err = strconv.ParseInt(l, 10, 64) fn.Ls = append(fn.Ls, i) } a.readIs(fn) }
func (a *Asm) readIs(fn *bytecode.Fn) { var l string var ok bool // While a new F section is not reached for l, ok = a.getLine(false); ok && l != "[f]"; l, ok = a.getLine(false) { // Split in three parts parts := strings.SplitN(l, " ", 3) if a.assertIParts(parts) { var ix uint64 o := bytecode.NewOpcode(parts[0]) f := bytecode.NewFlag(parts[1]) ix, a.err = strconv.ParseUint(parts[2], 10, 64) fn.Is = append(fn.Is, bytecode.NewInstr(o, f, ix)) } } if ok { a.readFn() } }