예제 #1
0
파일: emitter.go 프로젝트: jmptrader/agora
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))
}
예제 #2
0
파일: asm.go 프로젝트: jmptrader/agora
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()
	}
}
예제 #3
0
			exp: &bytecode.File{
				Fns: []*bytecode.Fn{
					&bytecode.Fn{
						// := emits Second before First, so literal is K0
						Ks: []*bytecode.K{
							&bytecode.K{
								Type: bytecode.KtInteger,
								Val:  int64(5),
							},
							&bytecode.K{
								Type: bytecode.KtString,
								Val:  "a",
							},
						},
						Is: []bytecode.Instr{
							bytecode.NewInstr(bytecode.OP_PUSH, bytecode.FLG_K, 0),
							bytecode.NewInstr(bytecode.OP_POP, bytecode.FLG_V, 1),
						},
					},
				},
			},
		},
		1: {
			// return nil
			src: []*parser.Symbol{
				&parser.Symbol{Id: "return", Ar: parser.ArStatement, First: &parser.Symbol{Id: "nil", Ar: parser.ArName, Val: nil}},
			},
			exp: &bytecode.File{
				Fns: []*bytecode.Fn{
					&bytecode.Fn{
						Is: []bytecode.Instr{
예제 #4
0
파일: emitter.go 프로젝트: jmptrader/agora
func (e *Emitter) updateJumpfInstr(fn *bytecode.Fn, ix int) {
	fn.Is[ix] = bytecode.NewInstr(bytecode.OP_JMP, bytecode.FLG_Jf, uint64(len(fn.Is)-ix-1))
}
예제 #5
0
파일: emitter.go 프로젝트: jmptrader/agora
func (e *Emitter) updateTestInstr(fn *bytecode.Fn, ix int) {
	fn.Is[ix] = bytecode.NewInstr(bytecode.OP_TEST, bytecode.FLG_Jf, uint64(len(fn.Is)-ix-1))
}
예제 #6
0
파일: asm_test.go 프로젝트: jmptrader/agora
i5
[l]
[i]
PUSH K 1 // Push constant value 5 on the stack
POP V 0  // Pop the value from the stack into variable identified by constant 0 (a)
PUSH V 0 // Push value of variable identified by constant 0 on the stack (a)
DUMP S 1
RET _ 0
`,
			exp: AppendAny(SigVer(bytecode.Version()), Int64ToByteSlice(4), 't', 'e', 's', 't',
				// StackSz - ExpArgs - ParentFnIx - LineStart - LineEnd
				Int64ToByteSlice(1), ExpZeroInt64, ExpZeroInt64, ExpZeroInt64, Int64ToByteSlice(2),
				// Ks - Ls - Is
				Int64ToByteSlice(2), 's', Int64ToByteSlice(1), 'a', 'i', Int64ToByteSlice(5), ExpZeroInt64, Int64ToByteSlice(5),
				// 5 ops
				UInt64ToByteSlice(uint64(bytecode.NewInstr(bytecode.NewOpcode("PUSH"), bytecode.NewFlag("K"), 1))),
				UInt64ToByteSlice(uint64(bytecode.NewInstr(bytecode.NewOpcode("POP"), bytecode.NewFlag("V"), 0))),
				UInt64ToByteSlice(uint64(bytecode.NewInstr(bytecode.NewOpcode("PUSH"), bytecode.NewFlag("V"), 0))),
				UInt64ToByteSlice(uint64(bytecode.NewInstr(bytecode.NewOpcode("DUMP"), bytecode.NewFlag("S"), 1))),
				UInt64ToByteSlice(uint64(bytecode.NewInstr(bytecode.NewOpcode("RET"), bytecode.NewFlag("_"), 0))),
			),
		},
		3: {
			// Unknown opcode
			id: "test",
			src: `
[f]
test
1
0
0