Przeglądaj źródła

Improved String reference handling. Now removes/adds references during semantic checking of const/evaluated expressions.
Implemented support for Chr and Asc keywords.
Added some simple tests.

woollybah 11 lat temu
rodzic
commit
7193b0a4f9

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+*.bak
+.bmx

+ 7 - 0
README.md

@@ -2,3 +2,10 @@ bcc
 ===
 
 Monkey-originated bcc parser for BlitzMax
+Generates BlitzMax (mostly) compatible C-source which has the added advantage of being more portable than the original bcc-generated processor-specific assembler.
+
+
+Testing
+-------
+
+Automated tests can be performed using our custom [SimpleCodeTester](https://github.com/GWRon/SimpleCodeTester) testing tool.

+ 1 - 1
bcc.bmx

@@ -5,7 +5,7 @@ Framework brl.StandardIO
 Import "ctranslator.bmx"
 
 ?macos
-putenv_("BMXPATH=/Users/brucey/Documents/programming/Blitz/BlitzMaxTestArea")
+putenv_("BMXPATH=/Users/brucey/Documents/programming/BlitzMax_NG")
 ?linux
 putenv_("BMXPATH=/home/brucey/000_programming/BlitzMaxTestArea")
 ?

+ 23 - 14
ctranslator.bmx

@@ -264,7 +264,7 @@ Type TCTranslator Extends TTranslator
 			If lhs Then
 				If lhs.exprType = TType.stringType Then
 					Return decl.munged + TransArgs(args, decl, TransSubExpr( lhs ))
-'If decl.ident = "ToCString" DebugStop
+'If decl.ident = "Print" DebugStop
 'DebugStop				
 				End If
 'If decl.ident = "Eof" DebugStop
@@ -281,10 +281,10 @@ Return class + "->md_" + decl.ident+TransArgs( args,decl, TransSubExpr( lhs ) )
 			Local class:String = Bra("(" + obj + "o)->clas")
 			Return class + "->md_" + decl.ident+TransArgs( args,decl, "o" )
 		EndIf
-		
+
 		' built-in functions
-		Select decl.ident
-			Case "Min", "Max", "Len"
+		Select decl.ident.ToLower()
+			Case "min", "max", "len", "asc", "chr"
 				Return TransBuiltin(decl, args)
 		End Select
 'If decl.ident = "stat_" DebugStop
@@ -300,8 +300,8 @@ Return class + "->md_" + decl.ident+TransArgs( args,decl, TransSubExpr( lhs ) )
 	End Method
 
 	Method TransBuiltin$( decl:TFuncDecl,args:TExpr[] )
-		Select decl.ident
-			Case "Min", "Max"
+		Select decl.ident.ToLower()
+			Case "min", "max"
 				Local isFloat:Int
 				For Local arg:TExpr = EachIn args
 					If TFloatType(arg.exprType) Or TDoubleType(arg.exprType) Then
@@ -314,12 +314,18 @@ Return class + "->md_" + decl.ident+TransArgs( args,decl, TransSubExpr( lhs ) )
 					' TODO : Long support
 					Return "bbInt" + decl.ident + TransArgs(args, decl)
 				End If
-			Case "Len"
-'DebugStop
+			Case "len"
 				Local arg:TExpr = args[0]
 				If TStringType(arg.exprType) Then
 					Return TVarExpr(arg).decl.munged + "->length"
 				End If
+			Case "asc"
+				Local arg:TExpr = args[0]
+				If TConstExpr(arg) InternalErr ' we should have handled this case already
+				Return "bbStringAsc" + TransArgs(args, decl)
+			Case "chr"
+				If TConstExpr(args[0]) InternalErr ' we should have handled this case already
+				Return "bbStringFromChar" + TransArgs(args, decl)
 		End Select
 	End Method
 		
@@ -336,19 +342,22 @@ Return class + "->md_" + decl.ident+TransArgs( args,decl, TransSubExpr( lhs ) )
 	Field stringMap:TMap = New TMap
 	
 	Method TransStringConst:String(value:String)
-		Local s:String = String(_app.stringConsts.ValueForKey(value))
+		Local sc:TStringConst = TStringConst(_app.stringConsts.ValueForKey(value))
+		Local s:String
 		
-		If Not s Then
+		If Not sc Then
 			'InternalErr
 			s = "bbEmptyString"
 '			s = "_s" + stringConstCount
 '
 '			stringMap.Insert(value, s)
 '
-'			stringConstCount:+ 1
+'			stringConstCount:+ 1e
+		Else
+			s = sc.id
 		End If
 
-		Return "&" + s	
+		Return "&" + s
 	End Method
 	
 	Method TransNewObjectExpr$( expr:TNewObjectExpr )
@@ -1852,9 +1861,9 @@ DebugLog mdecl.munged
 
 		' strings
 		For Local s:String = EachIn app.stringConsts.Keys()
-			Local key:String = String(app.stringConsts.ValueForKey(s))
+			Local key:TStringConst = TStringConst(app.stringConsts.ValueForKey(s))
 
-			Emit "static BBString " + key + "={"
+			Emit "static BBString " + key.id + "={"
 			Emit "&bbStringClass,"
 			Emit "2147483647,"
 			Emit s.length + ","

+ 29 - 5
decl.bmx

@@ -16,6 +16,8 @@ Const CLASS_THROWABLE:Int=	$002000
 Global _env:TScopeDecl
 Global _envStack:TList=New TList
 
+Global _appInstance:TAppDecl
+
 Global _loopnest:Int
 
 Function PushEnv( env:TScopeDecl )
@@ -584,7 +586,7 @@ End Rem
 	
 	Method FindFuncDecl:TFuncDecl( ident$,argExprs:TExpr[] = Null,explicit:Int=False )
 'DebugLog "FindFuncDecl : " + ident
-'If ident = "ReadStream" Then DebugStop
+'If ident = "Print" Then DebugStop
 		'Local funcs:TFuncDeclList=TFuncDeclList( FindDecl( ident ) )
 		Local f:TDecl = TDecl(findDecl(ident))
 		If Not f Then Return Null
@@ -1714,15 +1716,37 @@ pushenv Self
 	End Method
 	
 	Method mapStringConsts(value:String)
-		Local s:String = String(stringConsts.ValueForKey(value))
+		Local sc:TStringConst = TStringConst(stringConsts.ValueForKey(value))
+		
+		If Not sc Then
+			Local sc:TStringConst = New TStringConst
+			sc.count = 1
 		
-		If Not s Then
-			s = "_s" + stringConstCount
+			sc.id = "_s" + stringConstCount
 
-			stringConsts.Insert(value, s)
+			stringConsts.Insert(value, sc)
 
 			stringConstCount:+ 1
+		Else
+			sc.count :+ 1
 		End If
 	End Method
 	
+	Method removeStringConst(value:String)
+		Local sc:TStringConst = TStringConst(stringConsts.ValueForKey(value))
+		If sc Then
+			sc.count :- 1
+			If sc.count = 0 Then
+				stringConsts.Remove(value)
+			End If
+		End If
+	End Method
+	
+End Type
+
+Type TStringConst
+
+	Field id:String
+	Field count:Int
+
 End Type

+ 28 - 4
expr.bmx

@@ -32,7 +32,11 @@ Type TExpr
 	End Method
 	
 	Method EvalConst:TExpr()
-		Return New TConstExpr.Create( exprType,Eval() ).Semant()
+		Local expr:TExpr = New TConstExpr.Create( exprType,Eval() ).Semant()
+		If TStringType(TConstExpr(expr).ty) Then
+			_appInstance.mapStringConsts(TConstExpr(expr).value)
+		End If
+		Return expr
 	End Method
 	
 	Method Trans$()
@@ -322,10 +326,30 @@ Type TInvokeExpr Extends TExpr
 	End Method
 	
 	Method Semant:TExpr()
-'If decl.ident = "Create"
-'DebugStop
-'End If
+
 		If exprType Return Self
+		
+		' handle Asc and Chr keywords/functions for const values
+		Select decl.ident.ToLower()
+			Case "asc"
+				Local arg:TExpr = args[0]
+				If TConstExpr(arg) Then
+					Local expr:TExpr = New TConstExpr.Create(TType.intType, Asc(TConstExpr(arg).value))
+					_appInstance.removeStringConst(TConstExpr(arg).value)
+					expr.Semant()
+					Return expr
+				End If
+			Case "chr"
+				Local arg:TExpr = args[0]
+				If TConstExpr(arg) Then
+					Local expr:TConstExpr = New TConstExpr.Create(TType.stringType, Chr(Int(TConstExpr(arg).value)))
+					expr.Semant()
+					_appInstance.mapStringConsts(expr.value)
+					Return expr
+				End If
+		End Select
+		
+		
 		If Not decl.retType
 			decl.Semant()
 		End If

+ 2 - 0
parser.bmx

@@ -2702,6 +2702,8 @@ End Function
 Function ParseApp:TAppDecl( path$ )
 
 	Local app:TAppDecl=New TAppDecl
+	
+	_appInstance = app
 
 	Local source$=PreProcess( path )
 	'Local source:String = LoadString(path)

+ 4 - 0
tests/README.md

@@ -0,0 +1,4 @@
+Generally, .res output is taken from the results of the test as compiled with the
+original bcc app (bmx->asm).
+In theory, output should be identical, unless there is some specific reason for that
+not to be the case.

+ 6 - 0
tests/base.conf

@@ -0,0 +1,6 @@
+#app_type  = (Console/GUI)
+#arch_type = x86
+#threads   = (1 or 0, 0 is default)
+#debug     = (1 or 0, 0 is default)
+
+bmk_path = ../../../bin/bmk

+ 13 - 0
tests/framework/numerics/num_01.bmx

@@ -0,0 +1,13 @@
+SuperStrict
+
+Framework BRL.StandardIO
+
+Local i:Int = 100
+Local n:Int = 50
+
+Local x:Int = i + n
+
+Print i
+Print n
+Print x
+

+ 3 - 0
tests/framework/numerics/num_01.res

@@ -0,0 +1,3 @@
+100
+50
+150

+ 15 - 0
tests/framework/numerics/num_02.bmx

@@ -0,0 +1,15 @@
+SuperStrict
+
+Framework BRL.StandardIO
+
+Local f1:Float = 2.5
+Local f2:Float = 43
+
+Print f1 * f2
+Print (f1 * f2)
+Print f1 * (f2)
+Print f1 / f2
+Print (f1 / f2)
+Print f1 / (f2)
+
+

+ 6 - 0
tests/framework/numerics/num_02.res

@@ -0,0 +1,6 @@
+107.500000
+107.500000
+107.500000
+0.0581395365
+0.0581395365
+0.0581395365