Typed operands

This commit is contained in:
Ian Gulliver
2021-11-19 16:14:38 -10:00
parent 534c4fe513
commit 6e36152b6a
3 changed files with 81 additions and 30 deletions

View File

@@ -61,12 +61,13 @@ func assembleInstruction(in instruction) (*vm.Instruction, error) {
instr.OpCode = opCode
operands := in[1:]
if len(operands) != operandsByOpCode[instr.OpCode] {
return nil, fmt.Errorf("Incorrect number of operands: expected %d, found %d\n", operandsByOpCode[instr.OpCode], len(operands))
pattern := operandsByOpCode[instr.OpCode]
if len(operands) != len(pattern) {
return nil, fmt.Errorf("Incorrect number of operands: expected %d, found %d\n", len(pattern), len(operands))
}
if len(operands) >= 1 {
op1, err := assembleOperand(operands[0])
op1, err := assembleOperand(operands[0], pattern[0])
if err != nil {
return nil, errors.Wrapf(err, "In first operand")
}
@@ -75,7 +76,7 @@ func assembleInstruction(in instruction) (*vm.Instruction, error) {
}
if len(operands) >= 2 {
op2, err := assembleOperand(operands[1])
op2, err := assembleOperand(operands[1], pattern[1])
if err != nil {
return nil, errors.Wrapf(err, "In second operand")
}
@@ -86,7 +87,7 @@ func assembleInstruction(in instruction) (*vm.Instruction, error) {
return instr, nil
}
func assembleOperand(op string) (vm.Operand, error) {
func assembleOperand(op string, t operandType) (vm.Operand, error) {
op = strings.ToLower(op)
ret := vm.Operand{}
numStr := ""
@@ -100,25 +101,31 @@ func assembleOperand(op string) (vm.Operand, error) {
ret.Type = vm.GlobalMemoryIndex
numStr = strings.TrimPrefix(op, "g")
default:
case t == s || t == u || t == us:
ret.Type = vm.Literal
numStr = op
default:
return ret, fmt.Errorf("Invalid operand value type: %s", op)
}
switch {
case strings.HasPrefix(numStr, "+") || strings.HasPrefix(numStr, "-"):
case t == s || (t == us && (strings.HasPrefix(numStr, "+") || strings.HasPrefix(numStr, "-"))):
num, err := strconv.ParseInt(numStr, 10, 64)
if err != nil {
return ret, errors.Wrapf(err, "While parsing operand value %s", numStr)
}
ret.Value = uint64(num)
default:
case t == u || t == us || t == r:
num, err := strconv.ParseUint(numStr, 10, 64)
if err != nil {
return ret, errors.Wrapf(err, "While parsing operand value %s", numStr)
}
ret.Value = num
default:
return ret, fmt.Errorf("Invalid operand value: %s", numStr)
}
return ret, nil

View File

@@ -50,29 +50,38 @@ var opCodeByName = map[string]vm.OpCodeType{
"jmpf": vm.OpJmpF,
}
var operandsByOpCode = map[vm.OpCodeType]int{
vm.OpNop: 0,
vm.OpCal: 1,
vm.OpRet: 0,
type operandType int
vm.OpMov: 2,
vm.OpAdd: 2,
vm.OpSub: 2,
vm.OpMul: 2,
vm.OpDivU: 2,
vm.OpDivS: 2,
const (
u operandType = 0
s = 1
us = 2
r = 3
)
vm.OpEq: 2,
vm.OpLTU: 2,
vm.OpLTS: 2,
vm.OpGTU: 2,
vm.OpGTS: 2,
vm.OpLTEU: 2,
vm.OpLTES: 2,
vm.OpGTEU: 2,
vm.OpGTES: 2,
var operandsByOpCode = map[vm.OpCodeType][]operandType{
vm.OpNop: []operandType{},
vm.OpCal: []operandType{s},
vm.OpRet: []operandType{},
vm.OpJmp: 1,
vm.OpJmpT: 1,
vm.OpJmpF: 1,
vm.OpMov: []operandType{r, us},
vm.OpAdd: []operandType{r, us},
vm.OpSub: []operandType{r, us},
vm.OpMul: []operandType{r, us},
vm.OpDivU: []operandType{r, u},
vm.OpDivS: []operandType{r, s},
vm.OpEq: []operandType{us, us},
vm.OpLTU: []operandType{u, u},
vm.OpLTS: []operandType{s, s},
vm.OpGTU: []operandType{u, u},
vm.OpGTS: []operandType{s, s},
vm.OpLTEU: []operandType{u, u},
vm.OpLTES: []operandType{s, s},
vm.OpGTEU: []operandType{u, u},
vm.OpGTES: []operandType{s, s},
vm.OpJmp: []operandType{s},
vm.OpJmpT: []operandType{s},
vm.OpJmpF: []operandType{s},
}