Kaynağa Gözat

Generics WIP.
Fixes #297. Fixes #293. Fixes #300. Fixes #303. Fixes #304

woollybah 7 yıl önce
ebeveyn
işleme
662a3d32c7
8 değiştirilmiş dosya ile 112 ekleme ve 21 silme
  1. 2 0
      bcc.bmx
  2. 9 0
      config.bmx
  3. 4 0
      ctranslator.bmx
  4. 29 14
      decl.bmx
  5. 1 0
      expr.bmx
  6. 50 4
      parser.bmx
  7. 1 1
      toker.bmx
  8. 16 2
      type.bmx

+ 2 - 0
bcc.bmx

@@ -47,6 +47,8 @@ If opt_buildtype = BUILDTYPE_MODULE Then
 	End If
 End If
 
+TGenProcessor.processor = New TParser
+
 Local app:TAppDecl 
 Local trans:TCTranslator 
 Try

+ 9 - 0
config.bmx

@@ -472,6 +472,15 @@ Type TTemplateRecord
 	End Function
 End Type
 
+Type TGenProcessor Abstract
+
+	Global processor:TGenProcessor
+
+	Method ParseGeneric:Object(templ:TTemplateRecord)
+	End Method
+	
+End Type
+
 Extern
 	Function strlen_:Int(s:Byte Ptr)="strlen"
 End Extern

+ 4 - 0
ctranslator.bmx

@@ -4327,6 +4327,10 @@ End Rem
 			' field initialisation
 			For Local decl:TFieldDecl=EachIn classDecl.Decls()
 			
+				If Not decl.IsSemanted() Then
+					decl.Semant()
+				End If
+			
 				Local fld:String
 	
 				' ((int*)((char*)o + 5))[0] =

+ 29 - 14
decl.bmx

@@ -2306,7 +2306,13 @@ End Rem
 			If equal Return inst
 		Next
 
-		Local inst:TClassDecl=New TClassDecl.Create( ident,Null,superTy,impltys, attrs )
+		Local inst:TClassDecl = TClassDecl(TGenProcessor.processor.ParseGeneric(templateSource))
+		inst.ident=ident
+		inst.args=Null
+		inst.instances = Null
+		inst.superTy=superTy
+		inst.impltys=impltys
+		inst.attrs=attrs
 
 		inst.attrs:&~DECL_SEMANTED
 
@@ -2320,26 +2326,35 @@ End Rem
 		
 		inst.declImported = declImported
 
+		PushEnv inst
+
 		For Local i:Int=0 Until args.Length
 		
+			Local arg:TTemplateArg = args[i]
+
+			inst.InsertDecl New TAliasDecl.Create( arg.ident,instArgs[i],0 )
+
 			' ensure parameter types are compatible
-			If args[i].superTy Then
-				args[i].superTy = args[i].superTy.Semant()
-				If Not instArgs[i].EqualsType(args[i].superTy) And Not instArgs[i].ExtendsType(args[i].superTy) Then
-					Err "Type parameter '" + instArgs[i].ToString() + "' is not within its bound; should extend '" + args[i].superTy.ToString() + "'"
-				End If
+			If arg.superTy Then
+				For Local n:Int = 0 Until arg.superTy.length
+					arg.superTy[n] = arg.superTy[n].Semant()
+					If Not instArgs[i].EqualsType(arg.superTy[n]) And Not instArgs[i].ExtendsType(arg.superTy[n]) Then
+						Err "Type parameter '" + instArgs[i].ToString() + "' is not within its bound; should extend '" + arg.superTy[n].ToString() + "'"
+					End If
+				Next
 			End If
 		
-			inst.InsertDecl New TAliasDecl.Create( args[i].ident,instArgs[i],0 )
 		Next
+		
+		PopEnv
 
-		For Local decl:TDecl=EachIn _decls
-			If TClassDecl(decl) Then
-				inst.InsertDecl TClassDecl(decl).GenClassInstance(instArgs, declImported), True
-			Else
-				inst.InsertDecl decl.Copy(), True
-			End If
-		Next
+'		For Local decl:TDecl=EachIn _decls
+'			If TClassDecl(decl) Then
+'				inst.InsertDecl TClassDecl(decl).GenClassInstance(instArgs, declImported), True
+'			Else
+'				inst.InsertDecl decl.Copy(), True
+'			End If
+'		Next
 
 		If Not declImported Then
 			inst.scope = _env.ModuleScope()

+ 1 - 0
expr.bmx

@@ -201,6 +201,7 @@ Type TExpr
 				If TObjectType(rhs) And TObjectType(rhs).classDecl.ident = "Object" Then
 					Return rhs
 				End If
+				Return New TStringType
 			Else
 				Return New TStringType
 			End If

+ 50 - 4
parser.bmx

@@ -336,7 +336,7 @@ Type TIncbin
 End Type
 
 '***** Parser *****
-Type TParser
+Type TParser Extends TGenProcessor
 
 	Field _toker:TToker
 	Field _toke:String
@@ -2980,9 +2980,9 @@ End Rem
 				Local arg:TTemplateArg = New TTemplateArg
 				arg.ident = ParseIdent()
 				
-				If CParse("extends") Then
-					arg.superTy = ParseIdentType()
-				End If
+'				If CParse("extends") Then
+'					arg.superTy = ParseIdentType()
+'				End If
 				
 				args.AddLast arg
 
@@ -2990,6 +2990,34 @@ End Rem
 			'args=args[..nargs]
 
 			Parse ">"
+
+			If CParse( "where" ) Then
+'DebugStop
+				Repeat
+					Local argIdent:String = ParseIdent()
+					
+					Parse("extends")
+					
+					Local found:Int
+					For Local arg:TTemplateArg = EachIn args
+						If arg.ident = argIdent Then
+						
+							Repeat
+							
+								arg.ExtendsType(ParseIdentType())
+							
+							Until Not CParse("and")
+						
+							found = True
+							Exit
+						EndIf
+					Next
+					If Not found Then
+						Err "Use of undeclared type '" + argIdent + "'."
+					End If
+					
+				Until Not CParse(",")
+			End If
 		EndIf
 
 		If CParse( "extends" )
@@ -3681,6 +3709,24 @@ End Rem
 		Return attrs
 	End Method
 
+	Method ParseGeneric:Object(templateSource:TTemplateRecord)
+		Local toker:TToker = New TToker.Create(templateSource.file, templateSource.source, False, templateSource.start)
+		Local parser:TParser = New TParser.Create( toker, _appInstance )
+		
+		Local m:TModuleDecl = New TModuleDecl
+		parser._module = m
+		
+		Local cdecl:TClassDecl = Null
+		
+		Select parser._toke
+		Case "type"
+			cdecl = parser.ParseClassDecl(parser._toke,0)
+		Case "interface"
+			cdecl = parser.ParseClassDecl(parser._toke, CLASS_INTERFACE|DECL_ABSTRACT )
+		End Select
+		
+		Return cdecl
+	End Method
 
 	Method ParseMain()
 

+ 1 - 1
toker.bmx

@@ -49,7 +49,7 @@ Type TToker
 		"and,or,shl,shr,sar,end,if,then,else,elseif,endif,while,wend,repeat,until,forever,for,to,step," + ..
 		"next,return,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,operator"
+		"endinterface,implements,size_t,uint,ulong,struct,endstruct,operator,where"
 	Global _keywords:TMap
 
 	Field _path$

+ 16 - 2
type.bmx

@@ -2012,12 +2012,26 @@ End Type
 
 Type TTemplateArg
 	Field ident:String
-	Field superTy:TType
+	Field superTy:TType[]
+	
+	Method ExtendsType(ty:TType)
+		If Not superTy Then
+			superTy = New TType[0]
+		End If
+		
+		superTy :+ [ty]
+	End Method
 	
 	Method ToString:String()
 		Local s:String = ident
 		If superTy Then
-			s :+ " Extends " + superTy.ToString()
+			s :+ " Extends "
+			For Local i:Int = 0 Until superTy.length
+				If i Then
+					s:+ " And "
+				End If
+				s :+ superTy[i].ToString()
+			Next
 		End If
 	End Method
 End Type