Index: expression.c
===================================================================
--- expression.c	(revision 241)
+++ expression.c	(working copy)
@@ -5228,6 +5228,7 @@
 	   op == TOKandass ||
 	   op == TOKorass ||
 	   op == TOKxorass ||
+	   op == TOKpowass ||
 	   op == TOKin ||
 	   op == TOKremove)
 	return 1;
@@ -8925,6 +8926,69 @@
 
 /************************************************************/
 
+PowAssignExp::PowAssignExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKpowass, sizeof(PowAssignExp), e1, e2)
+{
+}
+
+Expression *PowAssignExp::semantic(Scope *sc)
+{
+    BinExp::semantic(sc);
+    Expression *e;
+
+    if (type)
+	return this;
+
+    BinExp::semanticp(sc);
+    e1 = e1->modifiableLvalue(sc, e1);
+    e = op_overload(sc);
+    if (e)
+	return e;
+    assert(e1->type && e2->type);
+    if ( (e1->type->isintegral() || e1->type->isfloating()) &&
+	 (e2->type->isintegral() || e2->type->isfloating()))
+    {
+	// For built-in numeric types, there are three cases:
+	// x ^^= 1   ----> x
+	// x ^^= 0.5 ----> x = sqrt(x)
+	// x ^^= y   ----> x = pow(x, y)
+	// TODO: This isn't really correct, it's evaluating e1 twice.
+	// TODO: backend support, especially for  e1 ^^= 2.
+	bool wantSqrt = false;	
+	e2 = e2->optimize(0);
+	if ((e2->op == TOKfloat64 && ((RealExp *)e2)->value == 1.0) ||
+	    (e2->op == TOKint64 && ((IntegerExp *)e2)->value == 1))
+	{
+	  return e1;  // Replace x ^^ 1 with x.
+	}
+	if (e2->op == TOKfloat64 && ((RealExp *)e2)->value == 0.5)
+	{   // Replace x ^^ 0.5 with sqrt(x)
+	    Identifier *sqrtid = new Identifier("sqrt", TOKidentifier);
+	    if (!sc->search(loc, sqrtid, NULL)) {
+		error("%s^^=0.5 requires sqrt()", e1->type->toChars());
+		return new ErrorExp();
+	    }
+	    e = new CallExp(loc, new IdentifierExp(loc, sqrtid), e1);
+	}
+	else 
+	{
+	    Identifier *powid = new Identifier("pow", TOKidentifier);
+	    if (!sc->search(loc, powid, NULL)) {
+		error("%s^^=%s requires pow()", e1->type->toChars(), e2->type->toChars() );
+		return new ErrorExp();
+	    }
+ 	    e = new CallExp(loc, new IdentifierExp(loc, powid), e1, e2);	
+	}
+        e = new AssignExp(loc, e1, e);	
+	e = e->semantic(sc);
+	return e;
+    }
+    error("%s ^^= %s is not supported", e1->type->toChars(), e2->type->toChars() );
+    return new ErrorExp();
+}
+
+/************************************************************/
+
 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
 	: BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
 {
@@ -9498,6 +9562,63 @@
     return this;
 }
 
+
+PowExp::PowExp(Loc loc, Expression *e1, Expression *e2)
+	: BinExp(loc, TOKpow, sizeof(PowExp), e1, e2)
+{
+}
+
+Expression *PowExp::semantic(Scope *sc)
+{   Expression *e;
+
+    if (type)
+	return this;
+
+    BinExp::semanticp(sc);
+    e = op_overload(sc);
+    if (e)
+	return e;
+    assert(e1->type && e2->type);
+    if ( (e1->type->isintegral() || e1->type->isfloating()) &&
+	 (e2->type->isintegral() || e2->type->isfloating()))
+    {
+	// For built-in numeric types, there are three cases:
+	// x ^^ 1   ----> x
+	// x ^^ 0.5 ----> sqrt(x)
+	// x ^^ y   ----> pow(x, y)
+	// TODO: backend support, especially for  e1 ^^ 2.
+	bool wantSqrt = false;	
+	e2 = e2->optimize(0);
+	if ((e2->op == TOKfloat64 && ((RealExp *)e2)->value == 1.0) ||
+	    (e2->op == TOKint64 && ((IntegerExp *)e2)->value == 1))
+	{
+	  return e1;  // Replace x ^^ 1 with x.
+	}
+	if (e2->op == TOKfloat64 && ((RealExp *)e2)->value == 0.5)
+	{   // Replace x ^^ 0.5 with sqrt(x)
+	    Identifier *sqrtid = new Identifier("sqrt", TOKidentifier);
+	    if (!sc->search(loc, sqrtid, NULL)) {
+		error("%s^^0.5 requires sqrt()", e1->type->toChars());
+		return new ErrorExp();
+	    }
+	    e = new CallExp(loc, new IdentifierExp(loc, sqrtid), e1);
+	}
+	else 
+	{
+	    Identifier *powid = new Identifier("pow", TOKidentifier);
+	    if (!sc->search(loc, powid, NULL)) {
+		error("%s^^%s requires pow()", e1->type->toChars(), e2->type->toChars() );
+		return new ErrorExp();
+	    }
+ 	    e = new CallExp(loc, new IdentifierExp(loc, powid), e1, e2);	
+	}	
+	e = e->semantic(sc);
+	return e;
+    }
+    error("%s ^^ %s is not supported", e1->type->toChars(), e2->type->toChars() );
+    return new ErrorExp();
+}
+
 /************************************************************/
 
 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2)
Index: expression.h
===================================================================
--- expression.h	(revision 241)
+++ expression.h	(working copy)
@@ -1188,8 +1188,17 @@
 ASSIGNEXP(Xor)
 #undef X
 
+// Only a reduced subset of operations for now.
+struct PowAssignExp : BinExp
+{
+    PowAssignExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    
+    // For operator overloading
+    Identifier *opId();    
+};
+
 #define X(a)
-
 ASSIGNEXP(Shl)
 ASSIGNEXP(Shr)
 ASSIGNEXP(Ushr)
@@ -1262,6 +1271,16 @@
     elem *toElem(IRState *irs);
 };
 
+struct PowExp : BinExp
+{
+    PowExp(Loc loc, Expression *e1, Expression *e2);
+    Expression *semantic(Scope *sc);
+    
+    // For operator overloading
+    Identifier *opId();
+    Identifier *opId_r();
+};
+
 struct DivExp : BinExp
 {
     DivExp(Loc loc, Expression *e1, Expression *e2);
Index: idgen.c
===================================================================
--- idgen.c	(revision 241)
+++ idgen.c	(working copy)
@@ -208,6 +208,9 @@
     { "opStar" },
     { "opDot" },
     { "opImplicitCast" },
+    { "pow", "opPow" },
+    { "pow_r", "opPow_r" },
+    { "powass", "opPowAssign" },
 
     { "classNew", "new" },
     { "classDelete", "delete" },
Index: lexer.c
===================================================================
--- lexer.c	(revision 241)
+++ lexer.c	(working copy)
@@ -1178,13 +1178,33 @@
 		else			\
 		    t->value = tok1;	\
 		return;
-
+		
 	    DOUBLE('*', TOKmul, '=', TOKmulass)
 	    DOUBLE('%', TOKmod, '=', TOKmodass)
-	    DOUBLE('^', TOKxor, '=', TOKxorass)
-
+	    
 #undef DOUBLE
 
+	    case '^':
+		p++;
+		if (*p == '^')
+		{   p++;
+		    if (*p == '=')
+		    {   p++;
+			t->value = TOKpowass;  // ^^=
+		    }
+		    else
+			t->value = TOKpow;     // ^^
+		}
+		else if (*p == '=')
+		{   p++;
+		    t->value = TOKxorass;    // ^=
+		}
+		else
+		    t->value = TOKxor;       // ^
+		return;
+	    
+#undef TRIPLE
+
 	    case '#':
 		p++;
 		pragma();
@@ -3084,6 +3104,8 @@
     Token::tochars[TOKorass]		= "|=";
     Token::tochars[TOKidentifier]	= "identifier";
     Token::tochars[TOKat]		= "@";
+    Token::tochars[TOKpow]		= "^^";
+    Token::tochars[TOKpowass]		= "^^=";
 
      // For debugging
     Token::tochars[TOKerror]		= "error";
Index: lexer.h
===================================================================
--- lexer.h	(revision 241)
+++ lexer.h	(working copy)
@@ -32,6 +32,7 @@
 	*	/	%	*=	/=	%=
 	&	| 	^	&=	|=	^=
 	=	!	~	@
+	^^	^^=
 	++	--
 	.	->	:	,
 	?	&&	||
@@ -162,6 +163,8 @@
 	TOKfile,
 	TOKshared,
 	TOKat,
+	TOKpow,
+	TOKpowass,
 #endif
 
 	TOKMAX
Index: opover.c
===================================================================
--- opover.c	(revision 241)
+++ opover.c	(working copy)
@@ -105,6 +105,9 @@
 Identifier *ModExp::opId()   { return Id::mod; }
 Identifier *ModExp::opId_r() { return Id::mod_r; }
 
+Identifier *PowExp::opId()   { return Id::pow; }
+Identifier *PowExp::opId_r() { return Id::pow_r; }
+
 Identifier *ShlExp::opId()   { return Id::shl; }
 Identifier *ShlExp::opId_r() { return Id::shl_r; }
 
@@ -142,6 +145,7 @@
 Identifier * ShrAssignExp::opId()  { return Id::shrass;  }
 Identifier *UshrAssignExp::opId()  { return Id::ushrass; }
 Identifier * CatAssignExp::opId()  { return Id::catass;  }
+Identifier * PowAssignExp::opId()  { return Id::powass; }
 
 int EqualExp::isCommutative()  { return TRUE; }
 Identifier *EqualExp::opId()   { return Id::eq; }
Index: parse.c
===================================================================
--- parse.c	(revision 241)
+++ parse.c	(working copy)
@@ -5510,6 +5510,7 @@
 	    case TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
 	    case TOKdiv:   nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
 	    case TOKmod:  nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
+	    case TOKpow:   nextToken(); e2 = parseUnaryExp(); e = new PowExp(loc,e,e2); continue;
 
 	    default:
 		break;
@@ -5854,6 +5855,7 @@
 	    X(TOKmulass,    MulAssignExp);
 	    X(TOKdivass,    DivAssignExp);
 	    X(TOKmodass,    ModAssignExp);
+	    X(TOKpowass,    PowAssignExp);
 	    X(TOKandass,    AndAssignExp);
 	    X(TOKorass,     OrAssignExp);
 	    X(TOKxorass,    XorAssignExp);
