Browse Source

Implemented enum Flags stuff.

woollybah 6 years ago
parent
commit
6967d51d89
2 changed files with 69 additions and 16 deletions
  1. 41 12
      decl.bmx
  2. 28 4
      expr.bmx

+ 41 - 12
decl.bmx

@@ -3453,7 +3453,7 @@ Type TEnumDecl Extends TScopeDecl
 	Method OnSemant()
 		' validate type
 		If Not TIntegralType(ty) Then
-			Err "Invalid type '" + ty.ToString() + "'. Enums can only be declared with integral types."
+			Err "Invalid type '" + ty.ToString() + "'. Enums can only be declared as integral types."
 		End If
 		
 		For Local val:TEnumValueDecl = EachIn values
@@ -3486,7 +3486,7 @@ Type TEnumDecl Extends TScopeDecl
 		fdecl = New TFuncDecl.CreateF("Ordinal", ty, Null, FUNC_METHOD)
 		InsertDecl fdecl
 		fdecl.Semant()
-		
+
 		fdecl = New TFuncDecl.CreateF("Values", New TArrayType.Create(New TEnumType.Create(Self), 1), Null, 0)
 		InsertDecl fdecl
 		fdecl.Semant()
@@ -3500,13 +3500,12 @@ End Type
 Type TEnumValueDecl Extends TDecl
 
 	Field expr:TExpr
-	Field ordinal:Int
+	Field index:Int
 	
-	Field generatedValue:Int
 	
-	Method Create:TEnumValueDecl(id:String, ordinal:Int, expr:TExpr)
+	Method Create:TEnumValueDecl(id:String, index:Int, expr:TExpr)
 		Self.ident = id
-		Self.ordinal = ordinal
+		Self.index = index
 		Self.expr = expr
 		Return Self
 	End Method
@@ -3514,30 +3513,60 @@ Type TEnumValueDecl Extends TDecl
 	Method OnSemant()
 		Local parent:TEnumDecl = TEnumDecl(scope)
 		Local previous:TEnumValueDecl
-		If ordinal > 0 Then
-			previous = parent.values[ordinal - 1]
+		If index > 0 Then
+			previous = parent.values[index - 1]
 		End If
 
 		If expr Then
+
 			expr = expr.Semant()
+
+			' 			
+			If TIdentEnumExpr(expr) Then
+				If TIdentEnumExpr(expr).value.scope = parent Then
+					expr = New TConstExpr.Create(parent.ty, TIdentEnumExpr(expr).value.Value()).Semant()
+				End If
+			End If
+			
+			If parent.isFlags And TBinaryMathExpr(expr) Then
+				expr = New TConstExpr.Create(parent.ty, TBinaryMathExpr(expr).Eval())
+			End If
 			
 			If Not TConstExpr(expr) Or Not TIntegralType(TConstExpr(expr).ty) Then
 				Err "Enum values must be integral constants."
 			End If
 		Else
-			Local val:Long = ordinal
+			Local val:Long
+
 			If previous Then
-				val = TConstExpr(previous.expr).value.ToLong() + 1
+				'
+				If TConstExpr(previous.expr)
+
+					val = TConstExpr(previous.expr).value.ToLong()
+
+					If parent.isFlags Then
+						If val = 0 Then
+							val = 1 
+						Else If (val & (val - 1)) = 0 Then ' power of 2 ?
+							val :Shl 1
+						Else
+							val :+ 1
+						End If
+					Else
+						val :+ 1
+					End If
+				Else
+					InternalErr "TEnumValueDecl.OnSemant"
+				End If
 			End If
 
 			expr = New TConstExpr.Create( parent.ty.Copy(), val).Semant()
-			generatedValue = True
 		
 		End If
 	End Method
 
 	Method OnCopy:TDecl(deep:Int = True)
-		Return New TEnumValueDecl.Create(ident, ordinal, expr)
+		Return New TEnumValueDecl.Create(ident, index, expr)
 	End Method
 	
 	Method Value:String()

+ 28 - 4
expr.bmx

@@ -1558,10 +1558,15 @@ Type TCastExpr Extends TExpr
 			Return expr
 		End If
 		
-		If TIntegralType(ty) And TEnumType(src) And flags & CAST_EXPLICIT Then
+		If TIntegralType(ty) And TEnumType(src) And (flags & CAST_EXPLICIT Or flags & 2) Then
 			exprType = ty
 			Return Self
 		End If
+		
+		If TIntegralType(src) And TEnumType(ty) And flags & 2 Then
+			exprType = src
+			Return Self
+		End If
 
 		If Not exprType
 			Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
@@ -1806,6 +1811,7 @@ Type TBinaryMathExpr Extends TBinaryExpr
 			End Try
 		End If
 
+		Local bitEnumOp:Int
 		Select op
 		Case "&","~~","|","shl","shr","sar"
 			If TFloat128Type(lhs.exprType) Then
@@ -1830,6 +1836,12 @@ Type TBinaryMathExpr Extends TBinaryExpr
 				exprType=New TWParamType
 			Else If TLParamType(lhs.exprType) Then
 				exprType=New TLParamType
+			Else If TEnumType(lhs.exprType) And TEnumType(lhs.exprType).decl.isFlags Then
+				exprType = lhs.exprType.Copy()
+				bitEnumOp = 2
+			Else If TEnumType(rhs.exprType) And TEnumType(rhs.exprType).decl.isFlags Then
+				exprType = rhs.exprType.Copy()
+				bitEnumOp = 2
 			Else
 				exprType=New TIntType
 			End If
@@ -1855,13 +1867,13 @@ Type TBinaryMathExpr Extends TBinaryExpr
 		If (op = "+" Or op = "-") And IsPointerType(exprType, 0, TType.T_POINTER) And TNumericType(lhs.exprType) Then
 			' with pointer addition we don't cast the numeric to a pointer
 		Else
-			lhs=lhs.Cast( exprType )
+			lhs=lhs.Cast( exprType, bitEnumOp )
 		End If
 		
 		If (op = "+" Or op = "-") And IsPointerType(exprType, 0, TType.T_POINTER) And TNumericType(rhs.exprType) Then
 			' with pointer addition we don't cast the numeric to a pointer
 		Else
-			rhs=rhs.Cast( exprType )
+			rhs=rhs.Cast( exprType, bitEnumOp )
 		End If
 		
 		If IsPointerType( lhs.exprType, 0, TType.T_POINTER ) And IsPointerType( rhs.exprType, 0, TType.T_POINTER ) And op = "-" Then
@@ -1876,7 +1888,7 @@ Type TBinaryMathExpr Extends TBinaryExpr
 	Method Eval$()
 		Local lhs$=Self.lhs.Eval()
 		Local rhs$=Self.rhs.Eval()
-		If TIntType( exprType )
+		If TIntType( exprType ) Or TByteType( exprType ) Or TShortType( exprType )
 			Local x:Int=Int(lhs),y:Int=Int(rhs)
 			Select op
 			Case "^" Return x^y
@@ -1951,6 +1963,18 @@ Type TBinaryMathExpr Extends TBinaryExpr
 				_appInstance.removeStringConst(rhs)
 				Return lhs+rhs
 			End Select
+		Else If TEnumType( exprType )
+			Local x:Long=Long(lhs),y:Long=Long(rhs)
+			Select op
+			Case "shl" Return x Shl y
+			Case "shr" Return x Shr y
+			Case "sar" Return x Sar y
+			Case "+" Return x + y
+			Case "-" Return x - y
+			Case "&" Return x & y
+			Case "~~" Return x ~ y
+			Case "|" Return x | y
+			End Select
 		EndIf
 		InternalErr "TBinaryMathExpr.Eval"
 	End Method