diff --git a/checker/checker.go b/checker/checker.go
index e71f1d7e..3a711326 100644
--- a/checker/checker.go
+++ b/checker/checker.go
@@ -99,7 +99,7 @@ func Check(tree *parser.Tree, config *conf.Config) (reflect.Type, error) {
 		}
 
 		switch v.config.Expect {
-		case reflect.Int, reflect.Int64, reflect.Float64:
+		case reflect.Int, reflect.Int64, reflect.Float64, reflect.Int32, reflect.Int16, reflect.Int8:
 			if !isNumber(nt) {
 				return nil, fmt.Errorf("expected %v, but got %v", v.config.Expect, nt)
 			}
diff --git a/compiler/compiler.go b/compiler/compiler.go
index 68eae5ea..05b4bd33 100644
--- a/compiler/compiler.go
+++ b/compiler/compiler.go
@@ -40,12 +40,18 @@ func Compile(tree *parser.Tree, config *conf.Config) (program *Program, err erro
 
 	if c.config != nil {
 		switch c.config.Expect {
-		case reflect.Int:
-			c.emit(OpCast, 0)
+		case reflect.Int8:
+			c.emit(OpCast, runtime.ResultAsTypInt8)
+		case reflect.Int16:
+			c.emit(OpCast, runtime.ResultAsTypInt16)
+		case reflect.Int32:
+			c.emit(OpCast, runtime.ResultAsTypInt32)
 		case reflect.Int64:
-			c.emit(OpCast, 1)
+			c.emit(OpCast, runtime.ResultAsTypInt64)
+		case reflect.Int:
+			c.emit(OpCast, runtime.ResultAsTypInt)
 		case reflect.Float64:
-			c.emit(OpCast, 2)
+			c.emit(OpCast, runtime.ResultAsTypFloat64)
 		}
 		if c.config.Optimize {
 			c.optimize()
diff --git a/expr_test.go b/expr_test.go
index f10350b2..0a102709 100644
--- a/expr_test.go
+++ b/expr_test.go
@@ -210,6 +210,97 @@ func ExampleAsInt() {
 	// Output: int(42)
 }
 
+func ExampleAsInt32() {
+	program, err := expr.Compile("42", expr.AsKind(reflect.Int32))
+	if err != nil {
+		fmt.Printf("%v", err)
+		return
+	}
+
+	output, err := expr.Run(program, nil)
+	if err != nil {
+		fmt.Printf("%v", err)
+		return
+	}
+
+	fmt.Printf("%T(%v)", output, output)
+
+	// Output: int32(42)
+}
+
+func TestAsResult(t *testing.T) {
+	type Case struct {
+		Name string
+		Want any
+		Code string
+		Opts []expr.Option
+	}
+	var cases = []Case{
+		{
+			Name: "StrAsInt32",
+			Want: int32(42),
+			Code: "42",
+			Opts: []expr.Option{
+				expr.AsKind(reflect.Int32),
+			},
+		},
+		{
+			Name: "FloatAsInt32",
+			Want: int32(42),
+			Code: "42.111",
+			Opts: []expr.Option{
+				expr.AsKind(reflect.Int32),
+			},
+		},
+		{
+			Name: "StrAsInt16",
+			Want: int16(42),
+			Code: "42",
+			Opts: []expr.Option{
+				expr.AsKind(reflect.Int16),
+			},
+		},
+		{
+			Name: "FloatAsInt16",
+			Want: int16(42),
+			Code: "42.111",
+			Opts: []expr.Option{
+				expr.AsKind(reflect.Int16),
+			},
+		},
+		{
+			Name: "StrAsInt8",
+			Want: int8(42),
+			Code: "42",
+			Opts: []expr.Option{
+				expr.AsKind(reflect.Int8),
+			},
+		},
+		{
+			Name: "FloatAsInt8",
+			Want: int8(42),
+			Code: "42.111",
+			Opts: []expr.Option{
+				expr.AsKind(reflect.Int8),
+			},
+		},
+	}
+	for _, c := range cases {
+		t.Run(c.Name, func(t *testing.T) {
+			program, err := expr.Compile(c.Code, c.Opts...)
+			if err != nil {
+				t.Fatalf("unexpected error: %v", err)
+			}
+
+			output, err := expr.Run(program, nil)
+			if err != nil {
+				t.Fatalf("unexpected error: %v", err)
+			}
+			assert.Equal(t, c.Want, output)
+		})
+	}
+}
+
 func ExampleAsInt64() {
 	env := map[string]any{
 		"rating": 5.5,
diff --git a/vm/runtime/runtime.go b/vm/runtime/runtime.go
index cd48a280..9c7a20b6 100644
--- a/vm/runtime/runtime.go
+++ b/vm/runtime/runtime.go
@@ -318,6 +318,99 @@ func ToInt(a any) int {
 	}
 }
 
+func ToInt8(a any) int8 {
+	switch x := a.(type) {
+	case float32:
+		return int8(x)
+	case float64:
+		return int8(x)
+	case int:
+		return int8(x)
+	case int8:
+		return int8(x)
+	case int16:
+		return int8(x)
+	case int32:
+		return int8(x)
+	case int64:
+		return int8(x)
+	case uint:
+		return int8(x)
+	case uint8:
+		return int8(x)
+	case uint16:
+		return int8(x)
+	case uint32:
+		return int8(x)
+	case uint64:
+		return int8(x)
+	default:
+		panic(fmt.Sprintf("invalid operation: int8(%T)", x))
+	}
+}
+
+func ToInt16(a any) int16 {
+	switch x := a.(type) {
+	case float32:
+		return int16(x)
+	case float64:
+		return int16(x)
+	case int:
+		return int16(x)
+	case int8:
+		return int16(x)
+	case int16:
+		return int16(x)
+	case int32:
+		return int16(x)
+	case int64:
+		return int16(x)
+	case uint:
+		return int16(x)
+	case uint8:
+		return int16(x)
+	case uint16:
+		return int16(x)
+	case uint32:
+		return int16(x)
+	case uint64:
+		return int16(x)
+	default:
+		panic(fmt.Sprintf("invalid operation: int16(%T)", x))
+	}
+}
+
+func ToInt32(a any) int32 {
+	switch x := a.(type) {
+	case float32:
+		return int32(x)
+	case float64:
+		return int32(x)
+	case int:
+		return int32(x)
+	case int8:
+		return int32(x)
+	case int16:
+		return int32(x)
+	case int32:
+		return x
+	case int64:
+		return int32(x)
+	case uint:
+		return int32(x)
+	case uint8:
+		return int32(x)
+	case uint16:
+		return int32(x)
+	case uint32:
+		return int32(x)
+	case uint64:
+		return int32(x)
+	default:
+		panic(fmt.Sprintf("invalid operation: int32(%T)", x))
+	}
+}
+
 func ToInt64(a any) int64 {
 	switch x := a.(type) {
 	case float32:
@@ -392,3 +485,13 @@ func IsNil(v any) bool {
 		return false
 	}
 }
+
+const (
+	ResultAsTypUnknown int = iota
+	ResultAsTypInt8
+	ResultAsTypInt16
+	ResultAsTypInt32
+	ResultAsTypInt64
+	ResultAsTypInt
+	ResultAsTypFloat64
+)
diff --git a/vm/vm.go b/vm/vm.go
index 5c40f26c..e58fc7b9 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -449,11 +449,17 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
 
 		case OpCast:
 			switch arg {
-			case 0:
+			case runtime.ResultAsTypInt8:
+				vm.push(runtime.ToInt8(vm.pop()))
+			case runtime.ResultAsTypInt16:
+				vm.push(runtime.ToInt16(vm.pop()))
+			case runtime.ResultAsTypInt:
 				vm.push(runtime.ToInt(vm.pop()))
-			case 1:
+			case runtime.ResultAsTypInt32:
+				vm.push(runtime.ToInt32(vm.pop()))
+			case runtime.ResultAsTypInt64:
 				vm.push(runtime.ToInt64(vm.pop()))
-			case 2:
+			case runtime.ResultAsTypFloat64:
 				vm.push(runtime.ToFloat64(vm.pop()))
 			}