diff --git a/src/lib-sieve/plugins/variables/cmd-set.c b/src/lib-sieve/plugins/variables/cmd-set.c
index 157cd69a09ef452855186f162094e4b752f0cb2a..4a2dae08637e81f377342899bacc8be814a69c3f 100644
--- a/src/lib-sieve/plugins/variables/cmd-set.c
+++ b/src/lib-sieve/plugins/variables/cmd-set.c
@@ -199,6 +199,7 @@ static bool cmd_set_operation_dump
 	sieve_code_descend(denv);
 
 	return 
+		sieve_opr_string_dump(denv, address) &&
 		sieve_opr_string_dump(denv, address);
 }
 
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c
index c21c7d1a02c1431f698c4febfa97524745dba180..ef8aa49e2658d152e675b46b64c08ab06a4761b1 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.c
@@ -1,10 +1,16 @@
 #include "lib.h"
 #include "hash.h"
+#include "str.h"
 
 #include "sieve-common.h"
 #include "sieve-ast.h"
+#include "sieve-binary.h"
+#include "sieve-code.h"
 #include "sieve-commands.h"
 #include "sieve-validator.h"
+#include "sieve-generator.h"
+#include "sieve-code-dumper.h"
+#include "sieve-interpreter.h"
 
 #include "ext-variables-common.h"
 
@@ -127,7 +133,7 @@ static bool arg_variable_generate
 	(struct sieve_generator *generator, struct sieve_ast_argument *arg, 
 		struct sieve_command_context *context);
 
-const struct sieve_argument variable_argument =
+const struct sieve_argument variable_argument = 
 	{ "@variable", NULL, NULL, NULL, arg_variable_generate };
 
 void ext_variables_variable_argument_activate
@@ -146,11 +152,70 @@ void ext_variables_variable_argument_activate
 
 static bool arg_variable_generate
 (struct sieve_generator *generator, struct sieve_ast_argument *arg, 
-	struct sieve_command_context *context)
+	struct sieve_command_context *context ATTR_UNUSED)
 {
+	struct sieve_variable *var = (struct sieve_variable *) arg->context;
+	
+	ext_variables_variable_emit(sieve_generator_get_binary(generator), var);
+
 	return TRUE;
 }
 
+/* Variable operands */
+
+static bool opr_variable_read
+	(struct sieve_binary *sbin, sieve_size_t *address, string_t **str);
+static bool opr_variable_dump
+	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
+
+const struct sieve_opr_string_interface variable_interface = { 
+	opr_variable_dump,
+	opr_variable_read
+};
+		
+const struct sieve_operand variable_operand = { 
+	"variable", 
+	&variables_extension, 0,
+	&string_class,
+	&variable_interface
+};	
+
+void ext_variables_variable_emit
+	(struct sieve_binary *sbin, struct sieve_variable *var) 
+{
+	(void) sieve_operand_emit_code(sbin, &variable_operand, ext_variables_my_id);
+	(void) sieve_binary_emit_integer(sbin, var->index);
+}
+
+static bool opr_variable_dump
+	(const struct sieve_dumptime_env *denv, sieve_size_t *address) 
+{
+	sieve_size_t number = 0;
+	
+	if (sieve_binary_read_integer(denv->sbin, address, &number) ) {
+		sieve_code_dumpf(denv, "VARIABLE: %ld [?]", (long) number);
+
+		return TRUE;
+	}
+	
+	return FALSE;
+}
+
+static bool opr_variable_read
+  (struct sieve_binary *sbin, sieve_size_t *address, string_t **str)
+{ 
+	sieve_size_t number = 0;
+	
+	if (sieve_binary_read_integer(sbin, address, &number) ) {
+		*str = t_str_new(10);
+		str_append(*str, "VARIABLE");
+
+		return TRUE;
+	}
+	
+	return FALSE;
+}
+
 /* Set modifier registration */
 
 const struct ext_variables_set_modifier *ext_variables_set_modifier_find
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.h b/src/lib-sieve/plugins/variables/ext-variables-common.h
index e8420cc18f0c3481f418f9df00de4d697f45fbd1..5768717d0d9c74a9dfa025de119d252a84b16981 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.h
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.h
@@ -41,6 +41,9 @@ const struct ext_variables_set_modifier *ext_variables_set_modifier_find
 	
 /* Variables */
 
+void ext_variables_variable_emit
+	(struct sieve_binary *sbin, struct sieve_variable *var);
+
 void ext_variables_variable_argument_activate
 	(struct sieve_validator *validator, struct sieve_ast_argument *arg);
 
diff --git a/src/lib-sieve/plugins/variables/ext-variables.c b/src/lib-sieve/plugins/variables/ext-variables.c
index e25fa996ef5297dc3300d65853e79009f300b6c3..b3b2c0494622ab2bc030a27c8d8bbd2192df9ee2 100644
--- a/src/lib-sieve/plugins/variables/ext-variables.c
+++ b/src/lib-sieve/plugins/variables/ext-variables.c
@@ -38,6 +38,10 @@ const struct sieve_operation *ext_variables_operations[] = {
 	&cmd_set_operation, &tst_string_operation
 };
 
+/* Operands */
+
+extern const struct sieve_operand variable_operand;
+
 /* Extension definitions */
 
 int ext_variables_my_id;
@@ -48,7 +52,7 @@ struct sieve_extension variables_extension = {
 	ext_variables_validator_load, 
 	NULL, NULL, NULL, 
 	SIEVE_EXT_DEFINE_OPERATIONS(ext_variables_operations), 
-	SIEVE_EXT_DEFINE_NO_OPERANDS
+	SIEVE_EXT_DEFINE_OPERAND(variable_operand)
 };
 
 static bool ext_variables_load(int ext_id) 
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index 12f336bcf1b1bffab3b4efb54a36ce3ffc609b96..036eacea68f17b5fc83e4a8fd4dacf92f7952638 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -88,12 +88,13 @@ static bool seffect_binary_load(struct sieve_binary *sbin)
  */
  
 static struct sieve_operand_class side_effect_class = 
-	{ "side-effect", NULL };
+	{ "side-effect" };
 
 struct sieve_operand side_effect_operand = { 
 	"side-effect", 
 	NULL, SIEVE_OPERAND_SIDE_EFFECT,
-	&side_effect_class
+	&side_effect_class,
+	NULL
 };
 
 void sieve_opr_side_effect_emit
diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c
index 6e14743720529fe62b5727a8904e17b0fbf331cf..42806dfc6b6541e0b5c26ad7b177774ddc5c2faf 100644
--- a/src/lib-sieve/sieve-address-parts.c
+++ b/src/lib-sieve/sieve-address-parts.c
@@ -197,12 +197,13 @@ static bool addrp_binary_load(struct sieve_binary *sbin)
  */
  
 struct sieve_operand_class address_part_class = 
-	{ "address-part", NULL };
+	{ "address-part" };
 
 struct sieve_operand address_part_operand = { 
 	"address-part", 
 	NULL, SIEVE_OPERAND_ADDRESS_PART,
-	&address_part_class
+	&address_part_class,
+	NULL
 };
 
 /* 
diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index f6c14515f8e13a12f178428db01c8589d4e1d092..1dfa9dc674d12cc7cf30ba9cabfbd6de17143334 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -119,11 +119,9 @@ bool sieve_coded_stringlist_read_all
 }
 
 /*
- * Operands
+ * Core operands
  */
  
-/* Core operands */
-
 const struct sieve_operand number_operand;
 const struct sieve_operand string_operand;
 const struct sieve_operand stringlist_operand;
@@ -149,7 +147,9 @@ const unsigned int sieve_operand_count =
 static struct sieve_extension_obj_registry oprd_default_reg =
 	SIEVE_EXT_DEFINE_OPERANDS(sieve_operands);
 
-/* Operand functions */
+/* 
+ * Operand functions 
+ */
 
 inline sieve_size_t sieve_operand_emit_code
 	(struct sieve_binary *sbin, const struct sieve_operand *opr, int ext_id)
@@ -180,42 +180,6 @@ const struct sieve_operand *sieve_operand_read
 			sieve_operand_registry_get);
 }
 
-/*
-inline sieve_size_t sieve_operand_emit_code
-	(struct sieve_binary *sbin, int operand)
-{
-	unsigned char op = operand;
-	
-	return sieve_binary_emit_byte(sbin, op);
-}
- 
-const struct sieve_operand *sieve_operand_read
-	(struct sieve_binary *sbin, sieve_size_t *address) 
-{
-	unsigned int operand;
-	
-	if ( sieve_binary_read_byte(sbin, address, &operand) ) {
-		if ( operand < SIEVE_OPERAND_CUSTOM ) {
-			if ( operand < sieve_operand_count )
-				return sieve_operands[operand];
-			else
-				return NULL;
-		} else {
-/ *			int ext_id = -1;
-		  const struct sieve_extension *ext = 
-		  	sieve_binary_extension_get_by_index
-		  		(sbin, operand - SIEVE_OPERAND_CUSTOM, &ext_id);
-		  
-		  if ( ext != NULL )
-		  	return ext->operand;	
-		  else * /
-		  	return NULL;
-		}
-	}		
-	
-	return NULL;
-}*/
-
 bool sieve_operand_optional_present
 	(struct sieve_binary *sbin, sieve_size_t *address)
 {	
@@ -259,12 +223,13 @@ const struct sieve_opr_number_interface number_interface = {
 };
 
 const struct sieve_operand_class number_class = 
-	{ "number", &number_interface };
+	{ "number" };
 	
 const struct sieve_operand number_operand = { 
 	"@number", 
 	NULL, SIEVE_OPERAND_NUMBER,
-	&number_class 
+	&number_class,
+	&number_interface 
 };
 
 /* String */
@@ -280,12 +245,13 @@ const struct sieve_opr_string_interface string_interface ={
 };
 	
 const struct sieve_operand_class string_class = 
-	{ "string", &string_interface };
+	{ "string" };
 	
 const struct sieve_operand string_operand = { 
 	"@string", 
 	NULL, SIEVE_OPERAND_STRING,
-	&string_class
+	&string_class,
+	&string_interface
 };	
 
 /* String List */
@@ -301,12 +267,13 @@ const struct sieve_opr_stringlist_interface stringlist_interface = {
 };
 
 const struct sieve_operand_class stringlist_class = 
-	{ "string-list", &stringlist_interface };
+	{ "string-list" };
 
 const struct sieve_operand stringlist_operand =	{ 
 	"@string-list", 
 	NULL, SIEVE_OPERAND_STRING_LIST,
-	&stringlist_class
+	&stringlist_class, 
+	&stringlist_interface
 };
 	
 /* 
@@ -334,7 +301,7 @@ bool sieve_opr_number_dump
 	if ( operand == NULL || operand->class != &number_class ) 
 		return FALSE;
 		
-	intf = (const struct sieve_opr_number_interface *) operand->class->interface; 
+	intf = (const struct sieve_opr_number_interface *) operand->interface; 
 	
 	if ( intf->dump == NULL )
 		return FALSE;
@@ -351,7 +318,7 @@ bool sieve_opr_number_read
 	if ( operand == NULL || operand->class != &number_class ) 
 		return FALSE;
 		
-	intf = (const struct sieve_opr_number_interface *) operand->class->interface; 
+	intf = (const struct sieve_opr_number_interface *) operand->interface; 
 	
 	if ( intf->read == NULL )
 		return FALSE;
@@ -399,7 +366,7 @@ bool sieve_opr_string_dump
 	if ( operand == NULL || operand->class != &string_class ) 
 		return FALSE;
 		
-	intf = (const struct sieve_opr_string_interface *) operand->class->interface; 
+	intf = (const struct sieve_opr_string_interface *) operand->interface; 
 	
 	if ( intf->dump == NULL ) 
 		return FALSE;
@@ -416,7 +383,7 @@ bool sieve_opr_string_read
 	if ( operand == NULL || operand->class != &string_class ) 
 		return FALSE;
 		
-	intf = (const struct sieve_opr_string_interface *) operand->class->interface; 
+	intf = (const struct sieve_opr_string_interface *) operand->interface; 
 	
 	if ( intf->read == NULL )
 		return FALSE;
@@ -500,7 +467,7 @@ bool sieve_opr_stringlist_dump
 	
 	if ( operand->class == &stringlist_class ) {
 		const struct sieve_opr_stringlist_interface *intf =
-			(const struct sieve_opr_stringlist_interface *) operand->class->interface; 
+			(const struct sieve_opr_stringlist_interface *) operand->interface; 
 		
 		if ( intf->dump == NULL )
 			return FALSE;
@@ -508,7 +475,7 @@ bool sieve_opr_stringlist_dump
 		return intf->dump(denv, address); 
 	} else if ( operand->class == &string_class ) {
 		const struct sieve_opr_string_interface *intf =
-			(const struct sieve_opr_string_interface *) operand->class->interface; 
+			(const struct sieve_opr_string_interface *) operand->interface; 
 	
 		if ( intf->dump == NULL ) 
 			return FALSE;
@@ -530,7 +497,7 @@ struct sieve_coded_stringlist *sieve_opr_stringlist_read
 		
 	if ( operand->class == &stringlist_class ) {
 		const struct sieve_opr_stringlist_interface *intf = 
-			(const struct sieve_opr_stringlist_interface *) operand->class->interface;
+			(const struct sieve_opr_stringlist_interface *) operand->interface;
 			
 		if ( intf->read == NULL ) 
 			return NULL;
@@ -539,7 +506,7 @@ struct sieve_coded_stringlist *sieve_opr_stringlist_read
 	} else if ( operand->class == &string_class ) {
 		/* Special case, accept single string as string list as well. */
 		const struct sieve_opr_string_interface *intf = 
-			(const struct sieve_opr_string_interface *) operand->class->interface;
+			(const struct sieve_opr_string_interface *) operand->interface;
 		
   	if ( intf->read == NULL || !intf->read(sbin, address, NULL) ) {
   		printf("FAILED TO SKIP\n");
diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h
index a05d9074cbc703a295eed1420b47d636308fd23f..82eabe4f726788149f8438141826640a84364b70 100644
--- a/src/lib-sieve/sieve-code.h
+++ b/src/lib-sieve/sieve-code.h
@@ -31,8 +31,6 @@ inline sieve_size_t sieve_coded_stringlist_get_current_offset
 
 struct sieve_operand_class {
 	const char *name;
-	
-	const void *interface;
 };
 
 struct sieve_operand {
@@ -42,6 +40,7 @@ struct sieve_operand {
 	unsigned int code;
 	
 	const struct sieve_operand_class *class;
+	const void *interface;
 };
 
 struct sieve_opr_number_interface {
@@ -78,6 +77,14 @@ enum sieve_core_operand {
 	SIEVE_OPERAND_CUSTOM
 };
 
+const struct sieve_operand_class number_class;
+const struct sieve_operand_class string_class;
+const struct sieve_operand_class stringlist_class;
+
+extern const struct sieve_operand number_operand;
+extern const struct sieve_operand string_operand;
+extern const struct sieve_operand stringlist_operand;
+
 extern const struct sieve_operand *sieve_operands[];
 extern const unsigned int sieve_operand_count;
 
diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c
index e018663d88f2cc0c364206aaa0101efecfc46e5f..6ab9de1914a9a47d9256f1a1c75992c435a57c5f 100644
--- a/src/lib-sieve/sieve-comparators.c
+++ b/src/lib-sieve/sieve-comparators.c
@@ -200,12 +200,13 @@ static bool cmp_binary_load(struct sieve_binary *sbin)
  */
  
 struct sieve_operand_class comparator_class = 
-	{ "comparator", NULL };
+	{ "comparator" };
 
 struct sieve_operand comparator_operand = { 
 	"comparator", 
 	NULL, SIEVE_OPERAND_COMPARATOR, 
-	&comparator_class
+	&comparator_class,
+	NULL
 };
 
 /* 
diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c
index 1cf22c434f88e8bb58dba743a84521392c3f28cf..e312de4cd1c6a716c994cb83c997645b0dc50dc9 100644
--- a/src/lib-sieve/sieve-match-types.c
+++ b/src/lib-sieve/sieve-match-types.c
@@ -194,13 +194,14 @@ static bool mtch_binary_load(struct sieve_binary *sbin)
  */
  
 struct sieve_operand_class match_type_class = 
-	{ "match-type", NULL };
+	{ "match-type" };
 
 struct sieve_operand match_type_operand = { 
 	"match-type", 
 	NULL,
 	SIEVE_OPERAND_MATCH_TYPE,
-	&match_type_class
+	&match_type_class,
+	NULL
 };
 
 /*