Selaa lähdekoodia

Merge pull request #377 from HurryStarfish/master

Index operator overloading
Brucey 6 vuotta sitten
vanhempi
commit
f0b5eb2c20
3 muutettua tiedostoa jossa 57 lisäystä ja 23 poistoa
  1. 49 22
      expr.bmx
  2. 4 1
      parser.bmx
  3. 4 0
      translator.bmx

+ 49 - 22
expr.bmx

@@ -153,7 +153,7 @@ Type TExpr
 
 
 					If TConstExpr(argExpr) Or TBinaryExpr(argExpr) Or (TIndexExpr(argExpr) And TStringType(TIndexExpr(argExpr).expr.exprType)) Or ..
 					If TConstExpr(argExpr) Or TBinaryExpr(argExpr) Or (TIndexExpr(argExpr) And TStringType(TIndexExpr(argExpr).expr.exprType)) Or ..
 							TInvokeExpr(argExpr) Or TInvokeMemberExpr(argExpr) Then
 							TInvokeExpr(argExpr) Or TInvokeMemberExpr(argExpr) Then
-						Err "Expression for 'Var' parameter must be a variable"
+						Err "Expression for 'Var' parameter must be a variable or an element of an array or pointer"
 					End If
 					End If
 
 
 					' Passing a "new" object into a Var, requires us to create a local variable and pass its address instead.
 					' Passing a "new" object into a Var, requires us to create a local variable and pass its address instead.
@@ -1513,7 +1513,7 @@ Type TCastExpr Extends TExpr
 		If TVarPtrType(ty) Then
 		If TVarPtrType(ty) Then
 			If Not TVarExpr(expr) And Not TMemberVarExpr(expr) And Not (TStmtExpr(expr) And TIndexExpr(TStmtExpr(expr).expr)) Then
 			If Not TVarExpr(expr) And Not TMemberVarExpr(expr) And Not (TStmtExpr(expr) And TIndexExpr(TStmtExpr(expr).expr)) Then
 				If Not TIndexExpr(expr) Or (TIndexExpr(expr) And Not TVarExpr(TIndexExpr(expr).expr) And Not TMemberVarExpr(TIndexExpr(expr).expr))  Then
 				If Not TIndexExpr(expr) Or (TIndexExpr(expr) And Not TVarExpr(TIndexExpr(expr).expr) And Not TMemberVarExpr(TIndexExpr(expr).expr))  Then
-					Err "Subexpression for 'Ptr' must be a variable"
+					Err "Subexpression for 'Varptr' must be a variable or an element of an array, pointer or string"
 				End If
 				End If
 			End If
 			End If
 			exprType = src.Copy()
 			exprType = src.Copy()
@@ -1661,7 +1661,7 @@ Type TUnaryExpr Extends TExpr
 				If error.StartsWith("Compile Error") Then
 				If error.StartsWith("Compile Error") Then
 					Throw error
 					Throw error
 				Else
 				Else
-					Err "Operator " + op + " cannot be used with Objects."
+					Err "Operator " + op + " is not defined for type '" + expr.exprType.ToString() + "'"
 				End If
 				End If
 			End Try
 			End Try
 		End If
 		End If
@@ -1775,7 +1775,7 @@ Type TBinaryMathExpr Extends TBinaryExpr
 				If error.StartsWith("Compile Error") Then
 				If error.StartsWith("Compile Error") Then
 					Throw error
 					Throw error
 				Else
 				Else
-					Err "Operator " + op + " cannot be used with Objects."
+					Err "Operator " + op + " is not defined between types '" + lhs.exprType.ToString() + "' and '" + rhs.exprType.ToString() + "'"
 				End If
 				End If
 			End Try
 			End Try
 		End If
 		End If
@@ -2103,7 +2103,7 @@ Type TIndexExpr Extends TExpr
 		Return New TIndexExpr.Create( CopyExpr(expr),ind )
 		Return New TIndexExpr.Create( CopyExpr(expr),ind )
 	End Method
 	End Method
 
 
-	Method Semant:TExpr()
+	Method _Semant:TExpr(set:Int, rhs:TExpr)
 		If exprType Return Self
 		If exprType Return Self
 
 
 		expr=expr.Semant()
 		expr=expr.Semant()
@@ -2117,13 +2117,49 @@ Type TIndexExpr Extends TExpr
 		End If
 		End If
 
 
 		For Local i:Int = 0 Until index.length
 		For Local i:Int = 0 Until index.length
-			If Not(TNumericType(expr.exprType) And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)) Then
+			If Not TObjectType(expr.exprType) And Not (TNumericType(expr.exprType) And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)) Then
 				index[i]=index[i].SemantAndCast( New TUIntType, True )
 				index[i]=index[i].SemantAndCast( New TUIntType, True )
 			Else
 			Else
 				index[i]=index[i].Semant()
 				index[i]=index[i].Semant()
 			End If
 			End If
 		Next
 		Next
-
+		
+		' operator overload?
+		If TObjectType(expr.exprType) Then
+			Local args:TExpr[]
+			Local op:String
+			If set Then
+				args = index + [rhs]
+				op = "[]="
+			Else
+				args = index
+				op = "[]"
+			End If
+			Try
+				Local decl:TFuncDecl = TFuncDecl(TObjectType(expr.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
+				If decl Then
+					Return New TInvokeMemberExpr.Create( expr, decl, args ).Semant()
+				End If
+			Catch error:String
+				If error.StartsWith("Compile Error") Then
+					Throw error
+				Else
+					Local istr:String
+					Local vstr:String
+					If index.length = 1 Then
+						istr = " with '" + index[0].exprType.ToString() + "' index"
+					Else
+						For Local i:TExpr = EachIn index
+							istr :+ ", '" + i.exprType.ToString() + "'"
+						Next
+						istr = " with " + istr[1..] + " indices"
+					End If
+					If set Then vstr = " and '" + rhs.exprType.ToString() + "' value"
+					Err "Operator " + op + istr + vstr + " is not defined for type '" + expr.exprType.ToString() + "'"
+				End If
+			End Try
+		End If
+		
 		If TStringType( expr.exprType )
 		If TStringType( expr.exprType )
 			exprType=New TIntType
 			exprType=New TIntType
 			If index.length > 1 Then
 			If index.length > 1 Then
@@ -2136,17 +2172,12 @@ Type TIndexExpr Extends TExpr
 
 
 				' a multi-dimensional array of arrays is slightly more complex
 				' a multi-dimensional array of arrays is slightly more complex
 				If TArrayType(exprType) Then
 				If TArrayType(exprType) Then
-
-				'	Local tmpArr:TLocalDecl=New TLocalDecl.Create( "", NewPointerType(TType.T_ARRAY), expr )
-				'	Local stmt:TExpr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), Self ).Semant()
-
 					Local sizeExpr:TExpr = New TArraySizeExpr.Create(expr, Null, index)
 					Local sizeExpr:TExpr = New TArraySizeExpr.Create(expr, Null, index)
 					index = [sizeExpr]
 					index = [sizeExpr]
 					Local tmp:TLocalDecl=New TLocalDecl.Create( "", NewPointerType(TType.T_UINT), sizeExpr,,True )
 					Local tmp:TLocalDecl=New TLocalDecl.Create( "", NewPointerType(TType.T_UINT), sizeExpr,,True )
 					TArraySizeExpr(sizeExpr).val = tmp
 					TArraySizeExpr(sizeExpr).val = tmp
 					Local stmt:TExpr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), Self ).Semant()
 					Local stmt:TExpr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), Self ).Semant()
 					stmt.exprType = exprType
 					stmt.exprType = exprType
-
 					Return stmt
 					Return stmt
 				Else
 				Else
 					Local sizeExpr:TExpr = New TArraySizeExpr.Create(expr, Null, index).Semant()
 					Local sizeExpr:TExpr = New TArraySizeExpr.Create(expr, Null, index).Semant()
@@ -2158,27 +2189,23 @@ Type TIndexExpr Extends TExpr
 					Return stmt
 					Return stmt
 				End If
 				End If
 			End If
 			End If
-			'If TObjectType(exprType) And Not TStringType(exprType) And Not TArrayType(exprType) Then
-			'	Local tmp:TLocalDecl=New TLocalDecl.Create( "", exprType,expr )
-			'	Local stmt:TExpr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ),New TVarExpr.Create( tmp ) ).Semant()
-			'	stmt.exprType = exprType
-			'	Return stmt
-			'End If
 		Else If TNumericType(expr.exprType) And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)' And Not TFunctionPtrType( expr.exprType )
 		Else If TNumericType(expr.exprType) And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)' And Not TFunctionPtrType( expr.exprType )
 			exprType=TType.MapPointerToPrim(TNumericType(expr.exprType))
 			exprType=TType.MapPointerToPrim(TNumericType(expr.exprType))
-			'exprType=TType.intType
 		Else If TObjectType(expr.exprType) And TObjectType(expr.exprType).classDecl.IsStruct() And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)' And Not TFunctionPtrType( expr.exprType )
 		Else If TObjectType(expr.exprType) And TObjectType(expr.exprType).classDecl.IsStruct() And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)' And Not TFunctionPtrType( expr.exprType )
 			exprType = expr.exprType
 			exprType = expr.exprType
 		Else
 		Else
-			Err "Only strings, arrays and pointers may be indexed."
+			Err "Expression of type '" + expr.exprType.ToString() + "' cannot be indexed"
 		EndIf
 		EndIf
 
 
 		Return Self
 		Return Self
 	End Method
 	End Method
+	
+	Method Semant:TExpr()
+		Return _Semant(False, Null)
+	End Method
 
 
 	Method SemantSet:TExpr( op$,rhs:TExpr )
 	Method SemantSet:TExpr( op$,rhs:TExpr )
-		Return Semant()
-		'Return Self
+		Return _Semant(True, rhs)
 	End Method
 	End Method
 	
 	
 	Method SemantFunc:TExpr( args:TExpr[] , throwError:Int = True, funcCall:Int = False )
 	Method SemantFunc:TExpr( args:TExpr[] , throwError:Int = True, funcCall:Int = False )

+ 4 - 1
parser.bmx

@@ -2684,8 +2684,11 @@ End Rem
 						id = t
 						id = t
 					Case ":mod", ":shl", ":shr"
 					Case ":mod", ":shl", ":shr"
 						id = t
 						id = t
+					Case "[]"
+						If CParse("=") Then t :+ "="
+						id = t
 					Default
 					Default
-						DoErr "Operator must be one of: * / + - & | ~~ :* :/ :+ :- :& :| :~~ < > <= >= = <> mod shl shr :mod :shl :shr"
+						DoErr "Operator must be one of: * / + - & | ~~ :* :/ :+ :- :& :| :~~ < > <= >= = <> mod shl shr :mod :shl :shr [] []="
 				End Select
 				End Select
 				ty=ParseDeclType()
 				ty=ParseDeclType()
 			Else
 			Else

+ 4 - 0
translator.bmx

@@ -453,6 +453,10 @@ Type TTranslator
 				Return "_shleq"
 				Return "_shleq"
 			Case ":shr"
 			Case ":shr"
 				Return "_shreq"
 				Return "_shreq"
+			Case "[]"
+				Return "_iget"
+			Case "[]="
+				Return "_iset"
 		End Select
 		End Select
 		Err "?? unknown symbol ?? : " + sym
 		Err "?? unknown symbol ?? : " + sym
 	End Method
 	End Method