瀏覽代碼

Merge pull request #228 from bmx-ng/bcc_op

Operator overloading.
Brucey 8 年之前
父節點
當前提交
e994e6e8ae
共有 9 個文件被更改,包括 219 次插入33 次删除
  1. 13 0
      config.bmx
  2. 19 5
      ctranslator.bmx
  3. 1 0
      decl.bmx
  4. 29 1
      expr.bmx
  5. 17 1
      iparser.bmx
  6. 41 12
      parser.bmx
  7. 32 5
      stmt.bmx
  8. 2 4
      toker.bmx
  9. 65 5
      translator.bmx

+ 13 - 0
config.bmx

@@ -47,6 +47,9 @@ Global OBJECT_BASE_OFFSET:Int = 8
 ' 4 bytes on 32-bit, 8 bytes on 64-bit
 Global POINTER_SIZE:Int = 4
 
+Global _symbols$[]=[ "..","[]",":*",":/",":+",":-",":|",":&",":~~",":shr",":shl",":sar",":mod"]
+Global _symbols_map$[]=[ "..","[]","*=","/=","+=","-=","|=","&=","^=",">>=", "<<=",">>=","%=" ]
+
 Function PushErr( errInfo$ )
 	_errStack.AddLast _errInfo
 	_errInfo=errInfo
@@ -114,6 +117,16 @@ Function IsStandardFunc:Int(func:String)
 	Return funcs.Find(func) > 0
 End Function
 
+Function mapSymbol:String(sym:String)
+	For Local i:Int = 0 Until _symbols.length
+		If sym = _symbols[i] Then
+			Return _symbols_map[i]
+		End If
+	Next
+	Return sym
+End Function
+
+
 'enquote depending on ENV_LANG
 '
 Function LangEnquote$( str$ )

+ 19 - 5
ctranslator.bmx

@@ -2444,7 +2444,7 @@ t:+"NULLNULLNULL"
 			rhs = "0"
 		End If
 
-		If stmt.op = "%=" Then
+		If stmt.op = ":%" Then
 			If TDecimalType(stmt.lhs.exprType) Or TDecimalType(stmt.rhs.exprType) Then
 				Return lhs + "=fmod" + Bra(lhs + "," + rhs)
 			End If
@@ -2454,7 +2454,7 @@ t:+"NULLNULLNULL"
 '			s:+ "{"
 '			s:+ "BBSTRING tmp=" + lhs + ";~n"
 
-			If stmt.op = "+=" Then
+			If stmt.op = ":+" Then
 				s :+ lhs+"=bbStringConcat("+lhs+","+rhs+")"
 			Else If rhs = "&bbNullObject" Then
 				s :+ lhs+TransAssignOp( stmt.op )+"&bbEmptyString"
@@ -2474,7 +2474,7 @@ t:+"NULLNULLNULL"
 
 			s :+ lhs+TransAssignOp( stmt.op )+rhs
 		Else If TArrayType(stmt.lhs.exprType) Then
-			If stmt.op = "+=" Then
+			If stmt.op = ":+" Then
 				s :+ lhs+"=bbArrayConcat("+ TransArrayType(TArrayType(stmt.lhs.exprType).elemType) + "," + lhs+","+rhs+")"
 			Else If rhs = "&bbNullObject" Then
 				s :+ lhs+TransAssignOp( stmt.op )+"&bbEmptyArray"
@@ -2688,7 +2688,13 @@ End Rem
 		End If	
 	
 		If Not fdecl.mangled Then
-			fdecl.mangled = fdecl.ident + MangleMethod(fdecl)
+			Local id:String = fdecl.ident
+
+			If fdecl.attrs & FUNC_OPERATOR Then
+				id = MungSymbol(id)
+			End If
+
+			fdecl.mangled = id + MangleMethod(fdecl)
 		End If
 
 		Return fdecl.mangled		
@@ -4557,7 +4563,11 @@ End Rem
 			func :+ "+"
 		End If
 
-		func :+ funcDecl.ident
+		If funcDecl.attrs & FUNC_OPERATOR Then
+			func :+ BmxEnquote(funcDecl.ident)
+		Else
+			func :+ funcDecl.ident
+		End If
 
 		func :+ TransIfcType(funcDecl.retType, funcDecl.ModuleScope().IsSuperStrict())
 
@@ -4569,6 +4579,10 @@ End Rem
 		Else If funcDecl.attrs & DECL_ABSTRACT Then
 			func :+ "A"
 		End If
+		
+		If funcDecl.attrs & FUNC_OPERATOR Then
+			func :+ "O"
+		End If
 
 		func :+ "="
 

+ 1 - 0
decl.bmx

@@ -1458,6 +1458,7 @@ Const FUNC_PTR:Int=      $0100
 Const FUNC_BUILTIN:Int = $0080
 Const FUNC_INIT:Int =    $0200
 Const FUNC_NESTED:Int =  $0400
+Const FUNC_OPERATOR:Int= $0800
 
 'Fix! A func is NOT a block/scope!
 '

+ 29 - 1
expr.bmx

@@ -865,7 +865,7 @@ Type TNewObjectExpr Extends TExpr
 			Local eType:TType = objTy
 			
 			Local errorDetails:String
-			
+
 			While i < parts.length
 				Local id:String = parts[i]
 				i :+ 1
@@ -1622,6 +1622,20 @@ Type TBinaryMathExpr Extends TBinaryExpr
 
 		lhs=lhs.Semant()
 		rhs=rhs.Semant()
+		
+		
+		' operator overload?
+		If TObjectType(lhs.exprType) Then
+			Local args:TExpr[] = [rhs]
+			Try
+				Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
+				If decl Then
+					Return New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
+				End If
+			Catch error:String
+				Err "Operator " + op + " cannot be used with Objects."
+			End Try
+		End If
 
 		Select op
 		Case "&","~~","|","shl","shr"
@@ -1777,6 +1791,20 @@ Type TBinaryCompareExpr Extends TBinaryExpr
 		lhs=lhs.Semant()
 		rhs=rhs.Semant()
 
+		' operator overload?
+		If TObjectType(lhs.exprType) Then
+			Local args:TExpr[] = [rhs]
+			Try
+				Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
+				If decl Then
+					Return New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
+				End If
+			Catch error:String
+				' no overload, continue...
+			End Try
+		End If
+
+
 		ty=BalanceTypes( lhs.exprType,rhs.exprType )
 
 		lhs=lhs.Cast( ty )

+ 17 - 1
iparser.bmx

@@ -750,7 +750,11 @@ Type TIParser
 					attrs:&~FUNC_METHOD
 					ty=ParseDeclType(attrs, True)
 				Else
-					id=ParseIdent()
+					If _toker._tokeType = TOKE_STRINGLIT Then
+						id = ParseStringLit()
+					Else
+						id=ParseIdent()
+					End If
 					ty=ParseDeclType(attrs, True)
 				EndIf
 			Else
@@ -861,6 +865,18 @@ Type TIParser
 				attrs:|DECL_ABSTRACT | DECL_API_WIN32
 			Else If CParse( "W" )
 				attrs:|DECL_API_WIN32
+			Else If CParse( "O" )
+				attrs:|FUNC_OPERATOR
+			Else If CParse( "OW" )
+				attrs:|FUNC_OPERATOR| DECL_API_WIN32
+			Else If CParse( "FO" )
+				attrs:|DECL_FINAL|FUNC_OPERATOR
+			Else If CParse( "FOW" )
+				attrs:|DECL_FINAL|FUNC_OPERATOR| DECL_API_WIN32
+			Else If CParse( "AO" )
+				attrs:|DECL_ABSTRACT|FUNC_OPERATOR
+			Else If CParse( "AOW" )
+				attrs:|DECL_ABSTRACT|FUNC_OPERATOR| DECL_API_WIN32
 			'Else If CParse( "property" )
 			'	If attrs & FUNC_METHOD
 			'		attrs:|FUNC_PROPERTY

+ 41 - 12
parser.bmx

@@ -2327,22 +2327,22 @@ End Rem
 					Case "=",":*",":/",":+",":-",":&",":|",":~~","mod","shl","shr", ":shl", ":shr", "sar", ":sar", ":mod"
 
 						' remap symbols...
-						For Local i:Int = 0 Until TToker._symbols.length
-							Local sym$= TToker._symbols[i]
-							If _toke.ToLower() = sym
-								_toke = TToker._symbols_map[i]
-								Exit
-							EndIf
-						Next
+						'For Local i:Int = 0 Until TToker._symbols.length
+						'	Local sym$= TToker._symbols[i]
+						'	If _toke.ToLower() = sym
+						'		_toke = TToker._symbols_map[i]
+						'		Exit
+						'	EndIf
+						'Next
 	
 	
 						If TIdentExpr( expr ) Or TIndexExpr( expr )
-							Local op$=_toke
+							Local op$=_toke.ToLower()
 							NextToke
-							If Not op.EndsWith( "=" ) And Not op.StartsWith("=")
-								Parse "="
-								op:+"="
-							EndIf
+						'	If Not op.EndsWith( "=" ) And Not op.StartsWith("=")
+						'		Parse "="
+						'		op:+"="
+						'	EndIf
 							_block.AddStmt New TAssignStmt.Create( op,expr,ParseExpr() )
 						Else
 							Err "Assignment operator '"+_toke+"' cannot be used this way."
@@ -2683,6 +2683,35 @@ End Rem
 					NextToke
 					attrs:|FUNC_CTOR
 					attrs:&~FUNC_METHOD
+				Else If _toke="operator" Then
+					attrs:|FUNC_OPERATOR
+					NextToke
+					
+					Local t:String = _toke.ToLower()
+					NextToke
+					
+					Select t
+						Case "*","/","+","-","&","|","~~"
+							id = t
+						Case ":*",":/",":+",":-",":&",":|",":~~"
+							id = t
+						Case "<",">"',"="',"<=",">=","=","<>"
+							If CParse("=") Then
+								t :+ "="
+							Else If t = "<" And CParse(">") Then
+								t :+ ">"
+							End If
+							id = t
+						Case "="
+							id = t
+						Case "mod", "shl", "shr"
+							id = t
+						Case ":mod", ":shl", ":shr"
+							id = t
+						Default
+							DoErr "Operator must be one of: * / + - & | ~~ :* :/ :+ :- :& :| :~~ < > <= >= = <> mod shl shr :mod :shl :shr"
+					End Select
+					ty=ParseDeclType()
 				Else
 					id=ParseIdent()
 					ty=ParseDeclType()

+ 32 - 5
stmt.bmx

@@ -124,22 +124,49 @@ Type TAssignStmt Extends TStmt
 						rhs=rhs.Cast( lhs.exprType )
 						splitOp = False
 						
-					Case "*=","/=","+=","-="
+					Case ":*",":/",":+",":-"
 					
 						If TNumericType( lhs.exprType ) And lhs.exprType.EqualsType( rhs.exprType ) Then
 							splitOp = False
 						End If
+						
+						If TObjectType(lhs.exprType) Then
+							Local args:TExpr[] = [rhs]
+							Try
+								Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
+								If decl Then
+									lhs = New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
+									rhs = Null
+									Return
+								End If
+							Catch error:String
+								Err "Operator " + op + " cannot be used with Objects."
+							End Try
+						End If
 					
-					Case "&=","|=","^=","<<=",">>=","%="
+					Case ":&",":|",":^",":shl",":shr",":mod"
 					
-						If TIntType( lhs.exprType ) And lhs.exprType.EqualsType( rhs.exprType ) Then
+						If (TIntType( lhs.exprType ) And lhs.exprType.EqualsType( rhs.exprType ))  Or TObjectType(lhs.exprType) Then
 							splitOp = False
 						End If
-				
+
+						If TObjectType(lhs.exprType) Then
+							Local args:TExpr[] = [rhs]
+							Try
+								Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,,SCOPE_CLASS_HEIRARCHY))
+								If decl Then
+									lhs = New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
+									rhs = Null
+									Return
+								End If
+							Catch error:String
+								Err "Operator " + op + " cannot be used with Objects."
+							End Try
+						End If
 				End Select
 				
 				If splitOp Then
-					rhs = New TBinaryMathExpr.Create(op[..op.length - 1], lhs, rhs).Semant().Cast(lhs.exprType)
+					rhs = New TBinaryMathExpr.Create(op[1..], lhs, rhs).Semant().Cast(lhs.exprType)
 					op = "="
 				End If
 				

+ 2 - 4
toker.bmx

@@ -56,10 +56,9 @@ Type TToker
 	"alias;rem;endrem;throw;assert;try;catch;nodebug;incbin;"+ ..
 	"endselect;endmethod;endfunction;endtype;endextern;endtry;endwhile;pi;release;defdata;readdata;restoredata;" + ..
 	"interface;endinterface;implements;"+ ..
-	"size_t;uint;ulong;struct;endstruct;"
+	"size_t;uint;ulong;struct;endstruct;" + ..
+	"operator;"
 
-	Global _symbols$[]=[ "..","[]",":*",":/",":+",":-",":|",":&",":~~",":shr",":shl",":sar",":mod"]
-	Global _symbols_map$[]=[ "..","[]","*=","/=","+=","-=","|=","&=","^=",">>=", "<<=",">>=","%=" ]
 	'Global _symbols$[]=[ "..","[]",":=",":*",":/",":+",":-",":|",":&",":~~" ]
 	'Global _symbols_map$[]=[ "..","[]",":=","*=","/=","+=","-=","|=","&=","~~=" ]
 
@@ -368,5 +367,4 @@ Type TToker
 		If _tokePos+i<_source.Length Return Chr( _source[_tokePos+i] )
 	End Method
 	
-	
 End Type

+ 65 - 5
translator.bmx

@@ -325,7 +325,13 @@ Type TTranslator
 		EndIf
 
 		If fdecl.scope Then
-			fdecl.munged = fdecl.scope.munged + "_" + fdecl.ident
+			Local id:String = fdecl.ident
+
+			If fdecl.attrs & FUNC_OPERATOR Then
+				id = MungSymbol(id)
+			End If
+			
+			fdecl.munged = fdecl.scope.munged + "_" + id
 			
 			If Not equalsBuiltInFunc(fdecl.classScope(), fdecl) And Not fdecl.noMangle Then
 				fdecl.munged :+ MangleMethod(fdecl)
@@ -343,6 +349,58 @@ Type TTranslator
 		funcs.AddLast fdecl
 	End Method
 	
+	Method MungSymbol:String(sym:String)
+		Select sym
+			Case "*"
+				Return "_mul"
+			Case "/"
+				Return "_div"
+			Case "+"
+				Return "_add"
+			Case "-"
+				Return "_sub"
+			Case "&"
+				Return "_and"
+			Case "|"
+				Return "_or"
+			Case "~~"
+				Return "_xor"
+			Case ":*"
+				Return "_muleq"
+			Case ":/"
+				Return "_diveq"
+			Case ":+"
+				Return "_addeq"
+			Case ":-"
+				Return "_subeq"
+			Case ":&"
+				Return "_andeq"
+			Case ":|"
+				Return "_oreq"
+			Case ":~~"
+				Return "_xoreq"
+			Case "<"
+				Return "_lt"
+			Case "<="
+				Return "_le"
+			Case ">"
+				Return "_gt"
+			Case ">="
+				Return "_ge"
+			Case "="
+				Return "_eq"
+			Case "<>"
+				Return "_ne"
+			Case "mod"
+				Return "_mod"
+			Case "shl"
+				Return "_shl"
+			Case "shr"
+				Return "_shr"
+		End Select
+		Return "?? unknown symbol ?? : " + sym
+	End Method
+	
 	Method MungDecl( decl:TDecl, addIfNotInScope:Int = False )
 
 		If decl.munged Then
@@ -570,6 +628,7 @@ End Rem
 	
 	Method TransBinaryOp$( op$,rhs$ )
 'DebugLog "TransBinaryOp '" + op + "' : '" + rhs + "'"
+op = mapSymbol(op)
 		Select op
 		Case "+","-"
 			If rhs.StartsWith( op ) Return op+" "
@@ -595,11 +654,12 @@ End Rem
 	End Method
 	
 	Method TransAssignOp$( op$ )
+op = mapSymbol(op)
 		Select op
-		Case "mod=" Return "%="
-		Case "shl=" Return "<<="
-		Case "shr=" Return ">>="
-		Case "sar=" Return ">>="
+		Case ":mod" Return "%="
+		Case ":shl" Return "<<="
+		Case ":shr" Return ">>="
+		Case ":sar" Return ">>="
 		End Select
 		Return op
 	End Method