Procházet zdrojové kódy

Added ReadOnly field property. Fixes #343.

woollybah před 7 roky
rodič
revize
5561fc115f
7 změnil soubory, kde provedl 45 přidání a 7 odebrání
  1. 7 1
      ctranslator.bmx
  2. 5 0
      decl.bmx
  3. 4 1
      iparser.bmx
  4. 1 1
      options.bmx
  5. 9 3
      parser.bmx
  6. 18 0
      stmt.bmx
  7. 1 1
      toker.bmx

+ 7 - 1
ctranslator.bmx

@@ -5046,7 +5046,13 @@ End Rem
 	End Method
 
 	Method EmitIfcFieldDecl(fieldDecl:TFieldDecl)
-		Local f:String = "." + fieldDecl.ident + TransIfcType(fieldDecl.ty, fieldDecl.ModuleScope().IsSuperStrict())
+		Local f:String
+		If fieldDecl.IsReadOnly() Then
+			f :+ "@"
+		Else
+			f :+ "."
+		End If
+		f :+ fieldDecl.ident + TransIfcType(fieldDecl.ty, fieldDecl.ModuleScope().IsSuperStrict())
 
 		f :+ "&"
 		

+ 5 - 0
decl.bmx

@@ -26,6 +26,7 @@ Const DECL_EXTERN:Int=        $010000
 Const DECL_PRIVATE:Int=       $020000
 Const DECL_ABSTRACT:Int=      $040000
 Const DECL_FINAL:Int=         $080000
+Const DECL_READ_ONLY:Int=     $000100
 
 Const DECL_SEMANTED:Int=      $100000
 Const DECL_SEMANTING:Int=     $200000
@@ -178,6 +179,10 @@ Type TDecl
 		Return Not (IsPrivate() Or IsProtected())
 	End Method
 	
+	Method IsReadOnly:Int()
+		Return (attrs & DECL_READ_ONLY)<>0
+	End Method
+	
 	Method IsAbstract:Int()
 		Return (attrs & DECL_ABSTRACT)<>0
 	End Method

+ 4 - 1
iparser.bmx

@@ -702,7 +702,10 @@ Type TIParser
 				'If decl.IsCtor() decl.retTypeExpr=New TObjectType.Create( classDecl )
 				classDecl.InsertDecl decl
 
-			Case "." ' field
+			Case ".", "@" ' field
+				If _toker._toke = "@" Then
+					decl_attrs :| DECL_READ_ONLY
+				End If
 				NextToke
 				decl_attrs :| DECL_FIELD
 				Local decl:TDecl= ParseDecl( _toke,decl_attrs )

+ 1 - 1
options.bmx

@@ -25,7 +25,7 @@ SuperStrict
 
 Import "base.configmap.bmx"
 
-Const version:String = "0.95"
+Const version:String = "0.96"
 
 Const BUILDTYPE_APP:Int = 0
 Const BUILDTYPE_MODULE:Int = 1

+ 9 - 3
parser.bmx

@@ -2412,9 +2412,9 @@ End Rem
 					init=ParseExpr()
 				End If
 			End If
-		Else If CParse( ":=" )
-			init=ParseExpr()
-			ty = init.exprType
+'		Else If CParse( ":=" )
+'			init=ParseExpr()
+'			ty = init.exprType
 		Else
 			ty=ParseDeclType(attrs & DECL_API_STDCALL)
 
@@ -2444,6 +2444,12 @@ End Rem
 			Else
 				Err "Constants must be initialized."
 			EndIf
+			
+			If toke = "field" Then
+				If CParse("readonly") Then
+					attrs :| DECL_READ_ONLY
+				End If
+			End If
 		EndIf
 		
 

+ 18 - 0
stmt.bmx

@@ -128,6 +128,24 @@ Type TAssignStmt Extends TStmt
 		If TInvokeExpr( lhs ) Or TInvokeMemberExpr( lhs )
 			rhs=Null
 		Else
+		
+			' can't assign to readonly field outside of its class constructor
+			If TVarExpr(lhs) Or TMemberVarExpr(lhs) Then
+				Local decl:TFieldDecl
+				If TVarExpr(lhs) Then
+					decl = TFieldDecl(TVarExpr(lhs).decl)
+				Else
+					decl = TFieldDecl(TMemberVarExpr(lhs).decl)
+				End If
+				If decl And decl.IsReadOnly() Then
+					' check scope for ctor
+					Local scope:TFuncDecl = _env.FuncScope()
+					If Not scope Or Not scope.IsCtor() Or (decl.ClassScope() <> scope.ClassScope()) Then
+						Err "Cannot modify ReadOnly field " + decl.ident
+					End If
+				End If
+			End If
+		
 			If IsPointerType(lhs.exprType, 0, TType.T_POINTER | TType.T_VARPTR) And TNumericType(rhs.exprType) Then
 				' with pointer assignment we don't cast the numeric to a pointer
 				

+ 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,finally,nodebug,incbin,endselect,endmethod," + ..
 		"endfunction,endtype,endextern,endtry,endwhile,pi,release,defdata,readdata,restoredata,interface," + ..
-		"endinterface,implements,size_t,uint,ulong,struct,endstruct,operator,where"
+		"endinterface,implements,size_t,uint,ulong,struct,endstruct,operator,where,readonly"
 	Global _keywords:TMap
 
 	Field _path$