Beispiel #1
0
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)
}
Beispiel #2
0
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))
}
Beispiel #3
0
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)
}
Beispiel #4
0
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)
}
Beispiel #5
0
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()
	}
}