Jelajahi Sumber

Initial Import.

woollybah 11 tahun lalu
induk
melakukan
a99371e05b
12 mengubah file dengan 11598 tambahan dan 0 penghapusan
  1. 103 0
      bcc.bmx
  2. 275 0
      config.bmx
  3. 2038 0
      ctranslator.bmx
  4. 1728 0
      decl.bmx
  5. 1160 0
      expr.bmx
  6. 970 0
      iparser.bmx
  7. 168 0
      options.bmx
  8. 2801 0
      parser.bmx
  9. 356 0
      stmt.bmx
  10. 218 0
      toker.bmx
  11. 749 0
      translator.bmx
  12. 1032 0
      type.bmx

+ 103 - 0
bcc.bmx

@@ -0,0 +1,103 @@
+SuperStrict
+
+Framework brl.StandardIO
+
+Import "ctranslator.bmx"
+
+?macos
+putenv_("BMXPATH=/Users/brucey/Documents/programming/Blitz/BlitzMaxTestArea")
+?linux
+putenv_("BMXPATH=/home/brucey/000_programming/BlitzMaxTestArea")
+?
+
+Local args:String[] = ParseArgs(AppArgs[1..])
+
+If args.length = 0 Then
+	Print "bcc[ng] Release Version " + version
+End If
+
+If args.length <> 1 Then
+	CmdError("Command line error")
+End If
+
+opt_filepath = args[0]
+
+
+If opt_buildtype = BUILDTYPE_MODULE Then
+	If opt_filepath.ToLower() = ModuleSource(opt_modulename).ToLower() Then
+		opt_ismain = True
+	End If
+End If
+
+Local app:TAppDecl = ParseApp(opt_filepath)
+
+app.Semant()
+
+Local trans:TCTranslator = New TCTranslator
+
+trans.TransApp(app)
+
+Local makeApp:Int = False
+If opt_apptype Then
+	makeApp = True
+End If
+
+Local mung:String = FileMung(makeApp)
+
+SaveInterface(opt_filepath, trans, mung)
+SaveHeader(opt_filepath, trans, mung)
+SaveSource(opt_filepath, trans, mung)
+
+
+Function SaveInterface(file:String, trans:TCTranslator, mung:String)
+	
+	Local path:String
+
+	If opt_buildtype = BUILDTYPE_MODULE Then
+
+		If opt_ismain Then
+			' module interface
+			path = ModuleInterface(opt_modulename, mung)
+		Else
+			' file interface
+			path = OutputFilePath(file, mung, "i")
+		End If
+		
+	Else
+	
+		' file interface
+		path = OutputFilePath(file, mung, "i")
+		
+	End If
+	
+	SaveText(trans.JoinLines("interface"), path)
+
+End Function
+
+Function SaveHeader(file:String, trans:TCTranslator, mung:String)
+
+	Local path:String = OutputFilePath(file, mung, "h")
+	
+	Local header:String = BuildHeaderName(path).ToUpper().Replace(".", "_")
+	Local text:String = HeaderComment()
+	text :+ "#ifndef " + header + "~n"
+	text :+ "#define " + header + "~n~n"
+	
+	If opt_buildtype = BUILDTYPE_MODULE And opt_modulename = "brl.blitz" Then
+		text :+ "#include <brl.mod/blitz.mod/blitz.h>~n"
+	End If
+	
+	text :+ trans.JoinLines("head")
+	text :+ "~n~n#endif~n"
+
+	SaveText(text, path)
+	
+End Function
+
+Function SaveSource(file:String, trans:TCTranslator, mung:String)
+
+	Local path:String = OutputFilePath(file, mung, "c")
+	
+	SaveText(trans.JoinLines("source"), path)
+	
+End Function

+ 275 - 0
config.bmx

@@ -0,0 +1,275 @@
+SuperStrict
+
+Import BRL.LinkedList
+Import BRL.Map
+Import BRL.FileSystem
+
+Import "options.bmx"
+
+Global ENV_LANG$
+
+Global _errInfo$
+Global _errStack:TList = New TList
+
+' bytes offset to the first field
+Global OBJECT_BASE_OFFSET:Int = 8
+' 4 bytes on 32-bit, 8 bytes on 64-bit
+Global POINTER_SIZE:Int = 4
+
+Function PushErr( errInfo$ )
+	_errStack.AddLast _errInfo
+	_errInfo=errInfo
+End Function
+
+Function PopErr()
+	_errInfo=String(_errStack.RemoveLast())
+End Function
+
+Function Err( err$ )
+	Print _errInfo+" : Error : "+err
+'	Print _errInfo+" "+err
+DebugStop
+	End
+End Function
+
+Function InternalErr()
+	Print _errInfo+" : Error : Internal error."
+	DebugStop
+	'Error _errInfo+" : Error : Internal error."
+End Function
+
+Function IsSpace:Int( ch:Int )
+	Return ch<=Asc(" ")
+End Function
+
+Function IsDigit:Int( ch:Int )
+	Return ch>=Asc("0") And ch<=Asc("9")
+End Function
+
+Function IsAlpha:Int( ch:Int )
+	Return (ch>=Asc("A") And ch<=Asc("Z")) Or (ch>=Asc("a") And ch<=Asc("z"))
+End Function
+
+Function IsBinDigit:Int( ch:Int )
+	Return ch=Asc("0") Or ch=Asc("1")
+End Function
+
+Function IsHexDigit:Int( ch:Int )
+	Return IsDigit(ch) Or (ch>=Asc("A") And ch<=Asc("F")) Or (ch>=Asc("a") And ch<=Asc("f"))
+End Function
+
+Function Todo() 
+	Err "TODO!"
+End Function
+
+'enquote depending on ENV_LANG
+'
+Function LangEnquote$( str$ )
+	str=str.Replace( "\","\\" )
+	str=str.Replace( "~q","\~q" )
+	str=str.Replace( "~n","\n" )
+	str=str.Replace( "~r","\r" )
+	str=str.Replace( "~t","\t" )
+'	str=str.Replace( "~0","\0" )	'Fix me?
+	For Local i:Int=0 Until str.Length
+		If str[i]>=32 And str[i]<128 Continue
+		Local t$,n:Int=str[i]
+		While n
+			Local c:Int=(n&15)+48
+			If c>=58 c:+97-58
+			t=Chr( c )+t
+			n=(n Shr 4) & $0fffffff
+		Wend
+		If Not t t="0"
+		If ENV_LANG = "cpp" Then
+		'Case "cpp"
+			t="~q~q\x"+t+"~q~q"
+		Else
+			t="\u"+("0000"+t)[-4..]
+		End If
+		str=str[..i]+t+str[i+1..]
+		i:+t.Length-1
+	Next
+	str="~q"+str+"~q"
+	If ENV_LANG="cpp" str="L"+str
+	Return str
+End Function
+
+Function BmxEnquote$( str$ )
+	str=str.Replace( "~~","~~~~" )
+	str=str.Replace( "~q","~~q" )
+	str=str.Replace( "~n","~~n" )
+	str=str.Replace( "~r","~~r" )
+	str=str.Replace( "~t","~~t" )
+	str=str.Replace( "~0","~~0" )
+	str="~q"+str+"~q"
+	Return str
+End Function
+
+Function BmxUnquote$( str$ )
+	str=str[1..str.Length-1]
+	str=str.Replace( "~~~~","~~z" )	'a bit dodgy - uses bad esc sequence ~z 
+	str=str.Replace( "~~q","~q" )
+	str=str.Replace( "~~n","~n" )
+	str=str.Replace( "~~r","~r" )
+	str=str.Replace( "~~t","~t" )
+	str=str.Replace( "~~0","~0" )
+	str=str.Replace( "~~z","~~" )
+	Return str
+End Function
+
+Type TStack Extends TList
+
+	Method Push(obj:Object)
+		AddFirst(obj)
+	End Method
+
+	Method Length:Int()
+		Return count()
+	End Method
+	
+	Method Get:Object(index:Int)
+		Return ValueAtIndex(index)
+	End Method
+	
+	Method Pop:Object()
+		Return RemoveFirst()
+	End Method
+	
+End Type
+
+Type TStringList Extends TList
+	Method Join:String(s:String)
+		Local str:String
+		For Local t:String = EachIn Self
+			If str Then
+				str :+ s
+			End If
+			str:+ t
+		Next
+		Return str
+	End Method
+End Type
+
+Function MakeKeywords:String()
+	Local keywords:String
+	
+	keywords :+ "Asc%(v$)=~qbrl_blitz_keywords_asc~q~n"
+	keywords :+ "Chr$(v%)=~qbrl_blitz_keywords_chr~q~n"
+	keywords :+ "Len%(v$)=~qbrl_blitz_keywords_len~q~n"
+	keywords :+ "Min%(v1%,v2%)=~qbrl_blitz_keywords_min~q~n"
+	keywords :+ "SizeOf%(v%)=~qbrl_blitz_keywords_sizeof~q~n"
+ 
+	Return keywords
+End Function
+
+Function FilePath:String(path:String)
+	Local baseDir:String = ExtractDir(path)
+	Local bmxDir:String = baseDir + "/.bmx"
+	
+	If FileType(bmxDir) <> FILETYPE_DIR Then
+		Throw "Missing : " + bmxDir
+	End If
+	
+	Return bmxDir
+End Function
+
+Function BuildHeaderName:String(path:String)
+	path = StripDir(path)
+
+	If opt_buildtype = BUILDTYPE_MODULE Then
+		path = opt_modulename + "." + path
+	End If
+	
+	Return path
+End Function
+
+Function MungModuleName:String(ident:String)
+	Local mung:String = "__bb_" + ident + "_" + ident[ident.Find(".") + 1..]
+	Return mung.Replace(".", "_")
+End Function
+
+Function MungImportFromFile:String(file:String)
+	Return "// TODO : MungImportFromFile()"
+End Function
+
+Rem
+bbdoc: Get the header file name from a given module ident, optionally with include path.
+End Rem
+Function ModuleHeaderFromIdent:String(ident:String, includePath:Int = False)
+	Local ns:String = ident[..ident.find(".")]
+	Local name:String = ident[ident.find(".") + 1..]
+	
+	Local file:String = name + ".bmx" + FileMung() + ".h"
+	
+	If includePath Then
+		file = ns + ".mod/" + name + ".mod/.bmx/" + file
+	End If
+	
+	Return file
+End Function
+
+Function FileHeaderFromFile:String(filepath:String, includePath:Int = False)
+
+	Local name:String = StripAll(filepath)
+	Local dir:String = ExtractDir(filePath)
+
+	Local file:String = name + ".bmx" + FileMung(opt_apptype) + ".h"
+
+	If includePath Then
+		'Local parent:String = dir[dir.FindLast("/") + 1..]
+		'file = parent + "/.bmx/" + file
+	End If
+
+	Return file
+End Function
+
+Function HeaderFile:String(path:String, mung:String)
+	Local fileDir:String = FilePath(path)
+	Local file:String = StripDir(path)
+	
+	Return fileDir + "/" + file + mung + ".h"
+End Function
+
+Function OutputFilePath:String(path:String, mung:String, suffix:String, bmxDir:Int = False)
+	Local fileDir:String = FilePath(path)
+	If bmxDir Then
+		fileDir :+ "/.bmx"
+	End If
+	Local file:String = StripDir(path)
+	
+	Return fileDir + "/" + file + mung + "." + suffix
+End Function
+
+Function FileMung:String(makeApp:Int = False)
+	Local m:String = "."
+	
+	If makeApp Then
+		Select opt_apptype
+			Case APPTYPE_CONSOLE
+				m :+ "console."
+			Case APPTYPE_GUI
+				m :+ "gui."
+		End Select
+	End If
+	
+	If opt_release Then
+		m :+ "release"
+	Else
+		m :+ "debug"
+	End If
+	
+	If opt_threaded Then
+		m :+ ".mt"
+	End If
+	
+	m :+ "." + opt_platform
+	
+	m :+ "." + opt_arch
+	
+	Return m
+End Function
+
+Function HeaderComment:String()
+	' TODO
+End Function

+ 2038 - 0
ctranslator.bmx

@@ -0,0 +1,2038 @@
+SuperStrict
+
+Import "parser.bmx"
+
+Type TCTranslator Extends TTranslator
+
+	Field _app:TAppDecl
+	'Field stringConstCount:Int
+
+	Field prefix:String
+
+	Method New()
+		_trans = Self
+	End Method
+	
+	Method TransArrayType$( ty:TType)
+		If TByteType( ty ) Return "~qb~q"
+		If TShortType( ty ) Return "~qs~q"
+		If TIntType( ty ) Return "~qi~q"
+		If TFloatType( ty ) Return "~qf~q"
+		If TDoubleType( ty ) Return "~qd~q"
+		If TLongType( ty ) Return "~ql~q"
+		If TStringType( ty ) Return "~q$~q"
+		If TArrayType( ty ) Return "~q[~q"
+		If TObjectType( ty ) Return "~q:~q"
+	End Method
+
+	Method TransType$( ty:TType, ident:String)
+		If TVoidType( ty ) Or Not ty Then
+'DebugStop
+			Return "void"
+		End If
+		If TBoolType( ty ) Return "BBINT"
+		If TByteType( ty ) Return "BBBYTE"
+		If TShortType( ty ) Return "BBSHORT"
+		If TIntType( ty ) Return "BBINT"
+		If TFloatType( ty ) Return "BBFLOAT"
+		If TDoubleType( ty ) Return "BBDOUBLE"
+		If TLongType( ty ) Return "BBLONG"
+		If TStringType( ty ) Return "BBSTRING"
+		If TArrayType( ty ) Return "BBARRAY"
+		If TObjectType( ty ) Return "BBOBJECT"
+		If TBytePtrType( ty ) Return "BBBYTE *"
+		If TShortPtrType( ty ) Return "BBSHORT *"
+		If TIntPtrType( ty ) Return "BBINT *"
+		If TFloatPtrType( ty ) Return "BBFLOAT *"
+		If TDoublePtrType( ty ) Return "BBDOUBLE *"
+		If TLongPtrType( ty ) Return "BBLONG *"
+		If TFunctionPtrType( ty ) Then
+			Local retType:String = TransType(TFunctionPtrType(ty).func.retType, "")
+			Local args:String = "/* TODO */"
+			Return retType + Bra("* " + ident) + Bra(args)
+		End If
+		If TBytePtrPtrType( ty ) Return "BBBYTE **"
+		If TShortPtrPtrType( ty ) Return "BBSHORT **"
+		If TIntPtrPtrType( ty ) Return "BBINT **"
+		If TFloatPtrPtrType( ty ) Return "BBFLOAT **"
+		If TDoublePtrPtrType( ty ) Return "BBDOUBLE **"
+		If TLongPtrPtrType( ty ) Return "BBLONG **"
+		InternalErr
+	End Method
+
+	Method TransIfcType$( ty:TType )
+		If TVoidType( ty ) Or Not ty Return "%"
+		If TByteType( ty ) Return "@"
+		If TShortType( ty ) Return "@@"
+		If TIntType( ty ) Return "%"
+		If TFloatType( ty ) Return "#"
+		If TDoubleType( ty ) Return "!"
+		If TLongType( ty ) Return "%%"
+		If TStringType( ty ) Return "$"
+		If TArrayType( ty ) Return TransIfcType(TArrayType( ty ).elemType) + "&[]"
+		If TObjectType( ty ) Return ":" + TObjectType(ty).classDecl.ident
+		If TBytePtrType( ty ) Return "@*"
+		If TShortPtrType( ty ) Return "@@*"
+		If TIntPtrType( ty ) Return "%*"
+		If TFloatPtrType( ty ) Return "#*"
+		If TDoublePtrType( ty ) Return "!*"
+		If TLongPtrType( ty ) Return "%%*"
+		If TFunctionPtrType( ty ) Return TransIfcType(TFunctionPtrType(ty).func.retType) + TransIfcArgs(TFunctionPtrType(ty).func)
+		If TBytePtrPtrType( ty ) Return "@**"
+		If TShortPtrPtrType( ty ) Return "@@**"
+		If TIntPtrPtrType( ty ) Return "%**"
+		If TFloatPtrPtrType( ty ) Return "#**"
+		If TDoublePtrPtrType( ty ) Return "!**"
+		If TLongPtrPtrType( ty ) Return "%%**"
+		If TByteVarPtrType( ty ) Return "@ Var"
+		If TShortVarPtrType( ty ) Return "@@ Var"
+		If TIntVarPtrType( ty ) Return "% Var"
+		If TFloatVarPtrType( ty ) Return "# Var"
+		If TDoubleVarPtrType( ty ) Return "! Var"
+		If TLongVarPtrType( ty ) Return "%% Var"
+		If TStringVarPtrType( ty ) Return "$ Var"
+		InternalErr
+	End Method
+
+	Method TransRefType$( ty:TType, ident:String )
+		If TObjectType( ty ) And ty.GetClass().IsInterface() Return "gc_iptr<"+ty.GetClass().actual.munged+">"
+		Return TransType( ty, ident )
+	End Method
+	
+	Method TransValue$( ty:TType,value$ )
+		If value
+			If TBoolType( ty ) Return "1"
+			If TShortType( ty ) Return value
+			If TIntType( ty ) Return value
+			If TLongType( ty ) Return value+"LL"
+			If TFloatType( ty ) Return value+"f"
+			If TDoubleType( ty ) Return value+"f"
+			If TStringType( ty ) Return "String("+Enquote( value )+")"
+			If TByteType( ty ) Return value
+		Else
+			If TBoolType( ty ) Return "0"
+			If TNumericType( ty ) Return "0"
+			If TStringType( ty ) Return "String()"
+			If TArrayType( ty ) Return "Array<"+TransRefType( TArrayType(ty).elemType, "PP" )+" >()"
+			If TObjectType( ty ) Return "0"
+			If TPointerType( ty) Return "0" ' todo ??
+			If TByteType( ty ) Return "0"
+		EndIf
+		InternalErr
+	End Method
+	
+	Method TransArgs$( args:TExpr[],decl:TFuncDecl, objParam:String = Null )
+		Local t$
+		If objParam Then
+			t:+ objParam
+		End If
+		For Local i:Int=0 Until args.Length
+			If t t:+","
+			t:+TransTemplateCast( TArgDecl(decl.argDecls[i].actual).ty,args[i].exprType,args[i].Trans() )
+		Next
+		Return Bra(t)
+	End Method
+
+	Method TransArgsTypes$( args:TExpr[],declArgTypes:TType[])
+		Local t$
+		For Local i:Int=0 Until args.Length
+			If t t:+","
+			t:+TransTemplateCast( declArgTypes[i],args[i].exprType,args[i].Trans() )
+		Next
+		Return Bra(t)
+	End Method
+
+	Method TransPtrCast$( ty:TType,src:TType,expr$,cast$ )
+'DebugStop
+		If TPointerType(ty) Then
+			' TODO : pointer stuff
+			Return expr
+		End If
+
+'		If TIntType(ty) And TStringType(src) Then
+'DebugStop
+'			Return "bbObjectDowncast" + Bra(expr + ",&" + TStringType(src).cDecl.munged)
+'		End If
+
+		If TStringType(ty) And TObjectType(src) Then
+			Return "bbObjectDowncast" + Bra(expr + ",&" + TStringType(ty).cDecl.munged)
+		End If
+
+
+		If TIntType(ty) And TStringType(src) Then
+			Return Bra(expr + " != &bbEmptyString")
+		End If
+
+'		If TIntType(ty) And TObjectType(src) Then
+'			Return Bra(expr + " != &bbNullObject")
+'		End If
+		If TObjectType(ty) And TStringType(src) Then
+			Return expr
+		End If
+
+		If Not TObjectType(ty) Or Not TObjectType(src) InternalErr
+		
+		Local t$=TransType(ty, "TODO: TransPtrCast")
+		
+		If src.GetClass().IsInterface() Or ty.GetClass().IsInterface() cast="dynamic"
+		
+		If src.GetClass().IsInterface() And Not ty.GetClass().IsInterface() Then
+			Return cast+"_cast<"+TransType(ty, "TODO: TransPtrCast")+">"+Bra( expr )
+		End If
+		
+		'upcast?
+		If src.GetClass().ExtendsClass( ty.GetClass() ) Return expr
+'DebugStop
+		If TObjectType(ty) Then
+			Return "bbObjectDowncast" + Bra(expr + ",&" + TObjectType(ty).classDecl.munged)
+		End If
+
+		Return cast+"_cast<"+TransType(ty, "TODO: TransPtrCast")+">"+Bra( expr )
+		
+	End Method
+	
+	'***** Utility *****
+	
+	Method TransLocalDecl$( munged$,init:TExpr )
+		Return TransType( init.exprType, munged )+" "+munged+"="+init.Trans()
+	End Method
+	
+	Method EmitPushErr()
+		Emit "pushErr();"
+	End Method
+	
+	Method EmitSetErr( info$ )
+		Emit "errInfo=~q"+info.Replace( "\","/" )+"~q;"
+	End Method
+	
+	Method EmitPopErr()
+		Emit "popErr();"
+	End Method
+
+	'***** Declarations *****
+	
+	Method TransStatic$( decl:TDecl )
+		If decl.IsExtern() Then
+			If Not decl.munged
+				Return decl.ident
+			End If
+			Return decl.munged
+		Else If _env And decl.scope And decl.scope=_env.ClassScope()
+			Return decl.munged
+		Else If TClassDecl( decl.scope )
+			'Return decl.scope.munged+"::"+decl.munged
+			Return decl.munged
+		Else If TModuleDecl( decl.scope )
+			Return decl.munged
+		EndIf
+		InternalErr
+	End Method
+	
+	Method TransTemplateCast$( ty:TType,src:TType,expr$ )
+
+		If ty=src Return expr
+
+		ty=ty.ActualType()
+		'src=src.ActualType()
+		
+		If ty.EqualsType( src ) Return expr
+		
+		Return TransPtrCast( ty,src,expr,"static" )
+
+	End Method
+	
+	Method TransGlobal$( decl:TGlobalDecl )
+		Return TransStatic( decl )
+	End Method
+	
+	Method TransField$( decl:TFieldDecl,lhs:TExpr )
+		If lhs Then
+			Return TransFieldRef(decl, TransSubExpr( lhs ))
+		Else
+			Return TransFieldRef(decl, "o")
+		End If
+'		Local swiz$
+'		If TObjectType( decl.ty )
+'			If TObjectType( decl.ty ).classDecl.IsInterface() swiz=".p"
+'		EndIf
+'		If lhs Return TransSubExpr( lhs )+"->"+decl.munged+swiz
+'		Return decl.munged+swiz
+	End Method
+		
+	Method TransFunc$( decl:TFuncDecl,args:TExpr[],lhs:TExpr )
+		If decl.IsMethod()
+			If lhs Then
+				If lhs.exprType = TType.stringType Then
+					Return decl.munged + TransArgs(args, decl, TransSubExpr( lhs ))
+'If decl.ident = "ToCString" DebugStop
+'DebugStop				
+				End If
+'If decl.ident = "Eof" DebugStop
+Local cdecl:TClassDecl = TObjectType(TVarExpr(lhs).decl.ty).classDecl
+Local obj:String = Bra("struct " + cdecl.munged + "_obj*")
+Local class:String = Bra("(" + obj + TransSubExpr( lhs ) + ")->clas")
+Return class + "->md_" + decl.ident+TransArgs( args,decl, TransSubExpr( lhs ) )
+				'Return TransSubExpr( lhs )+"->"+decl.munged+TransArgs( args,decl )
+				'Return decl.munged+TransArgs( args,decl, TransSubExpr( lhs ) )
+			End If
+ 
+			' ((brl_standardio_TCStandardIO_obj*)o->clas)->md_Read(o, xxx, xxx)
+			Local obj:String = Bra("struct " + decl.scope.munged + "_obj*")
+			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"
+				Return TransBuiltin(decl, args)
+		End Select
+'If decl.ident = "stat_" DebugStop
+		Return TransStatic( decl )+TransArgs( args,decl )
+	End Method
+	
+	Method TransSuperFunc$( decl:TFuncDecl,args:TExpr[] )
+		If decl.IsMethod()
+			Return decl.ClassScope().munged+".md_"+decl.ident+TransArgs( args,decl, "o" )
+		Else
+			Return decl.ClassScope().munged+".fn_"+decl.ident+TransArgs( args,decl)
+		End If
+	End Method
+
+	Method TransBuiltin$( decl:TFuncDecl,args:TExpr[] )
+		Select decl.ident
+			Case "Min", "Max"
+				Local isFloat:Int
+				For Local arg:TExpr = EachIn args
+					If TFloatType(arg.exprType) Or TDoubleType(arg.exprType) Then
+						isFloat = True
+					End If
+				Next
+				If isFloat Then
+					Return "bbFloat" + decl.ident + TransArgsTypes(args, [TType.floatType, TType.floatType])
+				Else
+					' TODO : Long support
+					Return "bbInt" + decl.ident + TransArgs(args, decl)
+				End If
+			Case "Len"
+'DebugStop
+				Local arg:TExpr = args[0]
+				If TStringType(arg.exprType) Then
+					Return TVarExpr(arg).decl.munged + "->length"
+				End If
+		End Select
+	End Method
+		
+	'***** Expressions *****
+
+	Method TransConstExpr$( expr:TConstExpr )
+		If TStringType(expr.exprType) Then
+			Return TransStringConst(expr.value)
+		Else
+			Return TransValue( expr.exprType,expr.value )
+		End If
+	End Method
+	
+	Field stringMap:TMap = New TMap
+	
+	Method TransStringConst:String(value:String)
+		Local s:String = String(_app.stringConsts.ValueForKey(value))
+		
+		If Not s Then
+			'InternalErr
+			s = "bbEmptyString"
+'			s = "_s" + stringConstCount
+'
+'			stringMap.Insert(value, s)
+'
+'			stringConstCount:+ 1
+		End If
+
+		Return "&" + s	
+	End Method
+	
+	Method TransNewObjectExpr$( expr:TNewObjectExpr )
+		Local t$ = "bbObjectNew(&" + expr.classDecl.actual.munged + ")"
+		'Local t$="(new "+expr.classDecl.actual.munged+")"
+		'If expr.ctor t:+"->"+expr.ctor.actual.munged+TransArgs( expr.args,expr.ctor )
+		Return t
+	End Method
+	
+	Method TransNewArrayExpr$( expr:TNewArrayExpr )
+'		Local texpr$=expr.expr.Trans()
+		'
+		Return "bbArrayNew1D" + Bra(TransArrayType(expr.ty) + ", " + expr.expr.Trans())
+		'Return "Array<"+TransRefType( expr.ty, "LL" )+" >"+Bra( expr.expr.Trans() )
+	End Method
+		
+	Method TransSelfExpr$( expr:TSelfExpr )
+		Return "this"
+	End Method
+	
+	Method TransCastExpr$( expr:TCastExpr )
+	
+		Local t$= expr.expr.Trans()
+		
+		Local dst:TType=expr.exprType
+		Local src:TType=expr.expr.exprType
+		
+		If TBoolType( dst )
+			If TBoolType( src ) Return t
+			If TIntType( src ) Return Bra( t+"!=0" )
+			If TFloatType( src ) Return Bra( t+"!=0.0f" )
+		'	If TArrayType( src ) Return Bra( t+".Length()!=0" )
+			If TStringType( src ) Return Bra( t+"!= &bbEmptyString" )
+			If TObjectType( src ) Return Bra( t+"!= &bbNullObject" )
+			If TPointerType( src ) Return Bra( t )
+		Else If TIntType( dst )
+			If TBoolType( src ) Return Bra( t )
+			If TByteType( src) Return Bra("(BBINT)"+t)
+			If TShortType( src) Return Bra("(BBINT)"+t)
+			If TBoolType( src ) Return t
+			If TIntType( src ) Return t
+			If TFloatType( src ) Return Bra("(BBINT)"+t)
+			If TDoubleType( src ) Return Bra("(BBINT)"+t)
+			If TStringType( src ) Return "bbStringToInt" + Bra(t)
+		 Else If TLongType( dst )
+			If TByteType( src) Return Bra("(BBLONG)"+t)
+			If TShortType( src) Return Bra("(BBLONG)"+t)
+			If TIntType( src) Return Bra("(BBLONG)"+t)
+			If TLongType( src ) Return t
+			If TFloatType( src ) Return Bra("(BBLONG)"+t)
+			If TDoubleType( src ) Return Bra("(BBLONG)"+t)
+			If TStringType( src ) Return "bbStringToLong" + Bra(t)
+		Else If TFloatType( dst )
+			If TIntType( src ) Return Bra("(BBFLOAT)"+t)
+			If TFloatType( src ) Return t
+			If TDoubleType( src ) Return Bra("(BBFLOAT)"+t)
+			If TStringType( src ) Return "bbStringToFloat" + Bra(t)
+		Else If TDoubleType( dst )
+			If TIntType( src ) Return Bra("(BBDOUBLE)"+t)
+			If TDoubleType( src ) Return t
+			If TFloatType( src ) Return Bra("(BBDOUBLE)"+t)
+			If TStringType( src ) Return "bbStringToDouble" + Bra(t)
+		Else If TStringType( dst )
+			If TByteType( src ) Return "bbStringFromInt"+Bra( t )
+			If TShortType( src ) Return "bbStringFromInt"+Bra( t )
+			If TIntType( src ) Return "bbStringFromInt"+Bra( t )
+			If TLongType( src ) Return "bbStringFromLong"+Bra( t )
+			If TFloatType( src ) Return "bbStringFromFloat"+Bra( t )
+			If TDoubleType( src ) Return "bbStringFromDouble"+Bra( t )
+			If TStringType( src ) Return t
+		Else If TByteType( dst )
+			If TByteType( src) Return t
+			If TIntType( src ) Return Bra("(BBBYTE)"+t)
+			If TFloatType( src ) Return Bra("(BBBYTE)"+t)
+			If TDoubleType( src ) Return Bra("(BBBYTE)"+t)
+			If TStringType( src ) Return t+".ToByte()"
+		Else If TShortType( dst )
+			If TShortType( src) Return t
+			If TByteType( src) Return Bra("(BBSHORT)"+t)
+			If TIntType( src ) Return Bra("(BBSHORT)"+t)
+			If TFloatType( src ) Return Bra("(BBSHORT)"+t)
+			If TDoubleType( src ) Return Bra("(BBSHORT)"+t)
+			If TStringType( src ) Return "bbStringToShort" + Bra(t)
+		Else If TVarPtrType( dst )
+			If TByteType( src) Return Bra("&"+t)
+			If TShortType( src) Return Bra("&"+t)
+			If TFloatType( src) Return Bra("&"+t)
+			If TIntType( src) Return Bra("&"+t)
+			If TDoubleType( src) Return Bra("&"+t)
+		
+		Else If TPointerType( dst )
+			If TArrayType(src) Then
+				Return Bra(Bra(TransType(dst, "")) + "BBARRAYDATA(" + t + "," + t + "->dims)")
+			End If
+			If TByteType( src) Return Bra("&"+t)
+		EndIf
+		
+		Return TransPtrCast( dst,src,t,"dynamic" )
+
+		Err "C++ translator can't convert "+src.ToString()+" to "+dst.ToString()
+	End Method
+	
+	Method TransUnaryExpr$( expr:TUnaryExpr )
+		Local pri:Int=ExprPri( expr )
+		Local t_expr$
+		
+		If TVarExpr(expr.expr) Then
+			If TObjectType(TVarExpr(expr.expr).exprType) Then
+				t_expr = Bra( expr.expr.Trans() + "!= &bbNullObject")
+			Else If TStringType(TVarExpr(expr.expr).exprType)  Then
+				t_expr = Bra( expr.expr.Trans() + "!= &bbEmptyString")
+			Else
+				t_expr = TransSubExpr( expr.expr,pri )
+			End If
+		Else
+				t_expr = TransSubExpr( expr.expr,pri )
+		End If
+
+'		TransSubExpr( expr.expr,pri )
+		Return TransUnaryOp( expr.op )+t_expr
+	End Method
+	
+	Method TransBinaryExpr$( expr:TBinaryExpr )
+		Local pri:Int=ExprPri( expr )
+		Local t_lhs$=TransSubExpr( expr.lhs,pri )
+		Local t_rhs$=TransSubExpr( expr.rhs,pri-1 )
+
+		If TStringType(expr.exprType) And expr.op = "+" Then
+			Return "bbStringConcat(" + t_lhs + "," + t_rhs + ")"
+		End If
+		
+		Return bra(t_lhs+TransBinaryOp( expr.op,t_rhs )+t_rhs)
+	End Method
+	
+	Method TransIndexExpr$( expr:TIndexExpr )
+	
+		Local t_expr$=TransSubExpr( expr.expr )
+		Local t_index$=expr.index.Trans()
+		
+		If TStringType( expr.expr.exprType ) Then
+			Return t_expr + "->buf[" + t_index + "]" 
+			'Return "(BBINT)"+t_expr+"["+t_index+"]"
+		End If
+		
+		If TArrayType( expr.expr.exprType ) Then
+'DebugStop
+			Return Bra("(" + TransType(expr.exprType, "") + "*)BBARRAYDATA(" + t_expr + "," + t_expr + "->dims)") + "[" + t_index + "]"
+		End If
+		
+		Local swiz$
+		If TObjectType( expr.exprType )And expr.exprType.GetClass().IsInterface() swiz=".p"
+		
+		'If ENV_CONFIG="debug" Return t_expr+".At("+t_index+")"+swiz
+		
+		Return t_expr+"["+t_index+"]"+swiz
+	End Method
+	
+	Method TransSliceExpr$( expr:TSliceExpr )
+		Local t_expr:String=TransSubExpr( expr.expr )
+		Local t_args$
+		If expr.from Then
+			t_args=expr.from.Trans()
+		Else
+			t_args = "0"
+		End If
+		If expr.term Then
+			t_args:+","+expr.term.Trans()
+		Else
+			If TArrayType(expr.exprType) Then
+				t_args :+ "," + t_expr + "->scales[0]"
+			Else
+				t_args :+ "," + t_expr + "->length"
+			End If
+		End If
+		
+		If TArrayType(expr.exprType) Then
+			Return "bbArraySlice" + Bra(TransArrayType(TArrayType(expr.exprType).elemType) + "," + t_expr + "," + t_args)
+		Else
+			Return "bbStringSlice" + Bra(t_expr + "," + t_args)
+		End If
+		'Return t_expr+".Slice("+t_args+")"
+	End Method
+	
+	Method TransArrayExpr$( expr:TArrayExpr )
+		Local elemType:TType=TArrayType( expr.exprType ).elemType
+
+		Local tmp:TLocalDecl =New TLocalDecl.Create( "",TType.voidType,Null )
+		MungDecl tmp
+		
+		Local t$
+		Local count:Int
+		For Local elem:TExpr=EachIn expr.exprs
+			If t t:+","
+			t:+elem.Trans()
+			count :+ 1
+		Next
+		
+		Local tt$
+'		If Not _env tt="static "
+
+		Emit tt+TransType( elemType, tmp.munged )+" "+tmp.munged+"[]={"+t+"};"
+'DebugStop
+		Return "bbArrayFromData" + Bra(TransArrayType(elemType) + "," + count + "," + tmp.munged )
+		'Return "Array<"+TransRefType( elemType, "MM" )+" >("+tmp.munged+","+expr.exprs.Length+")"
+	End Method
+
+	Method TransIntrinsicExpr$( decl:TDecl,expr:TExpr,args:TExpr[] )
+		Local texpr$,arg0$,arg1$,arg2$
+		
+		If expr texpr=TransSubExpr( expr )
+		
+		If args.Length>0 And args[0] arg0=args[0].Trans()
+		If args.Length>1 And args[1] arg1=args[1].Trans()
+		If args.Length>2 And args[2] arg2=args[2].Trans()
+		
+		Local id$=decl.munged[1..]
+		Local id2$=id[..1].ToUpper()+id[1..]
+		
+		Select id
+		'
+		'global functions
+		Case "print" Return "Print"+Bra( arg0 )
+		Case "error" Return "Error"+Bra( arg0 )
+		'
+		'string/array methods
+		Case "length" Return texpr+".Length()"
+		Case "resize" Return texpr+".Resize"+Bra( arg0 )
+		
+		'string methods
+		Case "compare" Return texpr+".Compare"+Bra( arg0 )
+		Case "find" Return texpr+".Find"+Bra( arg0+","+arg1 )
+		Case "findlast" Return texpr+".FindLast"+Bra( arg0 )
+		Case "findlast2" Return texpr+".FindLast"+Bra( arg0+","+arg1 )
+		Case "trim" Return texpr+".Trim()"
+		Case "join" Return texpr+".Join"+Bra( arg0 )
+		Case "split" Return texpr+".Split"+Bra( arg0 )
+		Case "replace" Return texpr+".Replace"+Bra( arg0+","+arg1 )
+		Case "tolower" Return texpr+".ToLower()"
+		Case "toupper" Return texpr+".ToUpper()"
+		Case "contains" Return texpr+".Contains"+Bra( arg0 )
+		Case "startswith" Return texpr+".StartsWith"+Bra( arg0 )
+		Case "endswith" Return texpr+".EndsWith"+Bra( arg0 )
+		
+		'string functions
+		Case "fromchar" Return "String"+Bra( "(Char)"+Bra(arg0)+",1" )
+
+		'math methods
+		Case "sin","cos","tan" Return "(float)"+id+Bra( Bra(arg0)+"*D2R" )
+		Case "asin","acos","atan" Return "(float)"+Bra( id+Bra(arg0)+"*R2D" )
+		Case "atan2" Return "(float)"+Bra( id+Bra(arg0+","+arg1)+"*R2D" )
+		Case "sqrt","floor","ceil","log" Return "(float)"+id+Bra( arg0 )
+		Case "pow" Return "(float)"+id+Bra( arg0+","+arg1 )
+		'
+		End Select
+		InternalErr
+	End Method
+
+	'***** Statements *****
+	
+	Method TransAssignStmt$( stmt:TAssignStmt )
+		If Not stmt.rhs Return stmt.lhs.Trans()
+'DebugStop
+		Local rhs$=stmt.rhs.Trans()
+		Local lhs$=stmt.lhs.TransVar()
+		
+		Local s:String
+		
+'		If ObjectType( stmt.rhs.exprType )
+'			If stmt.rhs.exprType.GetClass().IsInterface() rhs="GC_IPTR"+Bra(rhs)
+'		Endif
+		If TStringType(stmt.lhs.exprType) Then
+			s:+ "{"	
+			s:+ "BBSTRING tmp=" + lhs + ";~n"
+
+			
+			If stmt.op = "+=" Then
+				s :+ lhs+"=bbStringConcat("+lhs+","+rhs+")"
+			Else
+				s :+ lhs+TransAssignOp( stmt.op )+rhs
+			End If
+
+			s :+ ";~nBBRETAIN(" + lhs +")~n"
+			s :+ "BBRELEASE(tmp)~n"
+			
+			s:+ "}"
+		Else
+		
+				s :+ lhs+TransAssignOp( stmt.op )+rhs
+
+		End If
+		
+		Return s
+	End Method
+	
+	Method TransThrowStmt:String( stmt:TThrowStmt )
+		Local s:String = "bbExThrow("
+		
+		s:+ stmt.expr.Trans()
+		
+		s :+ ")"
+		Return s
+	End Method
+	
+	'***** Declarations *****
+Rem	
+	Method EmitFuncProto( decl:TFuncDecl )
+		PushMungScope
+
+		decl.Semant
+		
+		MungDecl decl
+
+		'Find decl we override
+		Local odecl:TFuncDecl=decl
+		While odecl.overrides
+			odecl=odecl.overrides
+		Wend
+
+		Local args$
+		For Local arg:TArgDecl=EachIn odecl.argDecls
+			If args args:+","
+			args:+TransType( arg.ty )
+		Next
+		
+		Local t$=TransType( odecl.retType )+" "+decl.munged+Bra( args )
+		If decl.IsAbstract() t:+"=0"
+		
+		Local q$
+		If decl.IsExtern() q:+"extern "
+		If decl.IsMethod() q:+"virtual "
+		If decl.IsStatic() And decl.ClassScope() q:+"static "
+		
+		Emit q+t+";"
+		
+		PopMungScope
+	End Method
+End Rem
+	Method EmitBBClassFuncProto( decl:TFuncDecl)
+		'PushMungScope
+		BeginLocalScope
+'DebugStop
+'		decl.Semant
+		
+'		MungDecl decl
+		
+		'Find decl we override
+		Local odecl:TFuncDecl=decl
+		If odecl.overrides Then Return
+'DebugLog decl.ident
+'		While odecl.overrides
+'			odecl=odecl.overrides
+'		Wend
+
+		Local id$=decl.munged
+		Local pre:String
+		
+		If decl.IsMethod() Then
+			id :+ "_md"
+			pre = "md_"
+		Else
+			id :+ "_fn"
+			pre = "fn_"
+		End If
+
+		Local bk:String = ";"
+		'Local pre:String = "typedef "
+		'If odecl.IsExtern() Then
+		'	pre = "extern "
+		'End If
+'DebugLog "id = " + id
+		Emit id + " " + pre + odecl.ident + ";"
+
+'		If Not proto Or (proto And Not odecl.IsExtern()) Then
+Rem
+			If Not TFunctionPtrType(odecl.retType) Then
+				If Not odecl.castTo Then
+					Emit pre + TransType( odecl.retType, "" )+" "+ Bra("*" + id)+Bra( args ) + bk
+				Else
+					If Not odecl.noCastGen Then
+						Emit pre + odecl.castTo +" "+Bra("*" + id)+Bra( args ) + bk
+					End If
+				End If
+			Else
+				If Not odecl.castTo Then
+					Emit pre + TransType( odecl.retType, id )+" "+Bra( args ) + bk
+				Else
+					If Not odecl.noCastGen Then
+						Emit pre + odecl.castTo +" "+Bra( args ) + bk
+					End If
+				End If
+			End If
+	
+			For Local t$=EachIn argCasts
+				Emit t
+			Next
+'		End If
+End Rem
+		'PopMungScope
+		EndLocalScope
+	End Method
+
+	Method EmitClassFuncProto( decl:TFuncDecl)
+		'PushMungScope
+		BeginLocalScope
+		
+		decl.Semant
+		
+		MungDecl decl
+		
+		'Find decl we override
+		Local odecl:TFuncDecl=decl
+'		If odecl.overrides Then Return
+		While odecl.overrides
+			odecl=odecl.overrides
+		Wend
+
+		'Generate 'args' string and arg casts
+		Local args$
+
+		' pass object for method
+		If decl.IsMethod() Then
+			args :+ "BBOBJECT "
+		End If
+
+		Local argCasts:TStack =New TStack
+		For Local i:Int=0 Until decl.argDecls.Length
+			Local arg:TArgDecl=decl.argDecls[i]
+			Local oarg:TArgDecl=odecl.argDecls[i]
+			MungDecl arg
+			If args args:+","
+			If Not TFunctionPtrType(oarg.ty) Then
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )
+				Else
+					args:+ oarg.castTo + " " + arg.munged
+				End If
+			Else
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )
+				Else
+					args:+ oarg.castTo
+				End If
+			End If
+			If arg.ty.EqualsType( oarg.ty ) Continue
+			Local t$=arg.munged
+			arg.munged=""
+			MungDecl arg
+			argCasts.Push TransType( arg.ty, arg.munged )+" "+arg.munged+"=static_cast<"+TransType(arg.ty, "")+" >"+Bra(t)+";"
+		Next
+		
+		Local id$=decl.munged
+
+		Local bk:String = ";"
+		Local pre:String = "typedef "
+		If decl.IsMethod() Then
+			id :+ "_md"
+		Else
+			id :+ "_fn"
+		End If
+		'If odecl.IsExtern() Then
+		'	pre = "extern "
+		'End If
+
+'		If Not proto Or (proto And Not odecl.IsExtern()) Then
+			If Not TFunctionPtrType(odecl.retType) Then
+				If Not odecl.castTo Then
+					If Not decl.overrides Then
+						Emit pre + TransType( odecl.retType, "" )+" "+ Bra("*" + id)+Bra( args ) + bk
+					End If
+					If decl.IsMethod() Then
+						Emit TransType(odecl.retType, "") + " _" + decl.munged +Bra( args ) + bk
+					Else
+						Emit TransType(odecl.retType, "") + " " + decl.munged +Bra( args ) + bk
+					End If
+				Else
+					If Not odecl.noCastGen Then
+						If Not decl.overrides Then
+							Emit pre + odecl.castTo +" "+Bra("*" + id)+Bra( args ) + bk
+						End If
+						If decl.IsMethod() Then
+							Emit odecl.castTo + " _" + decl.munged +Bra( args ) + bk
+						Else
+							Emit odecl.castTo + " " + decl.munged +Bra( args ) + bk
+						End If
+					End If
+				End If
+			Else
+				If Not odecl.castTo Then
+					Emit pre + TransType( odecl.retType, id )+" "+Bra( args ) + bk
+				Else
+					If Not odecl.noCastGen Then
+						Emit pre + odecl.castTo +" "+Bra( args ) + bk
+					End If
+				End If
+			End If
+	
+			For Local t$=EachIn argCasts
+				Emit t
+			Next
+'		End If
+
+		'PopMungScope
+		EndLocalScope
+	End Method
+
+
+
+	Method EmitFuncDecl( decl:TFuncDecl, proto:Int = False, classFunc:Int = False )
+		'If Not proto And decl.IsAbstract() Return
+		
+		'PushMungScope
+		BeginLocalScope
+'DebugStop
+		decl.Semant
+		
+		MungDecl decl
+		
+		'Find decl we override
+		Local odecl:TFuncDecl=decl
+		While odecl.overrides
+			odecl=odecl.overrides
+		Wend
+
+		'Generate 'args' string and arg casts
+		Local args$
+
+		' pass object for method
+		If decl.IsMethod() Then
+			args :+ "BBOBJECT o"
+		End If
+
+		Local argCasts:TStack =New TStack
+		For Local i:Int=0 Until decl.argDecls.Length
+			Local arg:TArgDecl=decl.argDecls[i]
+			Local oarg:TArgDecl=odecl.argDecls[i]
+			MungDecl arg
+			If args args:+","
+			If Not TFunctionPtrType(oarg.ty) Then
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )+" "+arg.munged
+				Else
+					args:+ oarg.castTo + " " + arg.munged
+				End If
+			Else
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )
+				Else
+					args:+ oarg.castTo
+				End If
+			End If
+			If arg.ty.EqualsType( oarg.ty ) Continue
+			Local t$=arg.munged
+			arg.munged=""
+			MungDecl arg
+			argCasts.Push TransType( arg.ty, arg.munged )+" "+arg.munged+"=static_cast<"+TransType(arg.ty, "")+" >"+Bra(t)+";"
+		Next
+		
+		Local id$=decl.munged
+		
+		If classFunc Then
+			If decl.IsMethod() Then
+				id = "_" + id
+			End If
+		Else
+			If Not odecl.IsExtern() Then
+				id = id
+			End If
+		End If
+
+		Local bk:String = "{"
+		Local pre:String
+		If proto Then
+			If odecl.IsExtern() Then
+				pre = "extern "
+			End If
+			bk = ";"
+		End If
+
+'		If Not proto Or (proto And Not odecl.IsExtern()) Then
+			If Not TFunctionPtrType(odecl.retType) Then
+				If Not odecl.castTo Then
+					Emit pre + TransType( odecl.retType, "" )+" "+id+Bra( args ) + bk
+				Else
+					If Not odecl.noCastGen Then
+						Emit pre + odecl.castTo +" "+id+Bra( args ) + bk
+					End If
+				End If
+			Else
+				If Not odecl.castTo Then
+					Emit pre + TransType( odecl.retType, id )+" "+Bra( args ) + bk
+				Else
+					If Not odecl.noCastGen Then
+						Emit pre + odecl.castTo +" "+Bra( args ) + bk
+					End If
+				End If
+			End If
+	
+			For Local t$=EachIn argCasts
+				Emit t
+			Next
+'		End If
+
+		If Not proto Then
+			If decl.IsAbstract() Then
+				Emit "brl_blitz_NullMethodError();"
+			Else
+If decl.ident = "Eof" DebugStop
+
+				decl.Semant()
+'If decl.ident = "LoadByteArray" DebugStop
+		' TODO : enable block output
+				EmitBlock decl
+		'		Emit "// TODO : enable block output"
+		'		Emit "printf(~qTODO : " + decl.munged + "\n~q);fflush(stdout);"
+
+			End If
+			Emit "}"
+		End If
+
+		EndLocalScope
+		'PopMungScope
+	End Method
+	
+	Method EmitClassFieldsProto(classDecl:TClassDecl)
+	
+		If classDecl.superClass Then
+			EmitClassFieldsProto(classDecl.superClass)
+		End If
+		
+		For Local decl:TFieldDecl = EachIn classDecl.Decls()
+			decl.Semant()
+			
+			Emit "~t" + TransType(decl.ty, classDecl.actual.munged) + " _" + classDecl.actual.munged.ToLower() + "_" + decl.ident.ToLower() + ";"
+		Next
+		
+	End Method
+	
+	Method EmitBBClassClassFuncProto( classDecl:TClassDecl )
+
+		Local reserved:String = "New,Delete,ToString,ObjectCompare,SendMessage,_reserved1_,_reserved2_,_reserved3_".ToLower()
+
+		If classDecl.superClass Then
+			EmitBBClassClassFuncProto(classDecl.superClass)
+		End If
+
+		' user defined functions and methods
+		'Local fdecls:TFuncDecl[] = classDecl.GetAllFuncDecls()
+		'For Local fdecl:TFuncDecl = EachIn fdecls
+		For Local decl:TDecl=EachIn classDecl.Decls()
+			Local fdecl:TFuncDecl =TFuncDecl( decl )
+			If fdecl
+				If reserved.Find(fdecl.ident.ToLower()) = -1 Then
+					EmitBBClassFuncProto( fdecl )
+					Continue
+				End If
+			EndIf
+		Next
+		
+	End Method
+	
+	Method EmitClassProto( classDecl:TClassDecl )
+
+		Local classid$=classDecl.munged
+		Local superid$=classDecl.superClass.actual.munged
+
+
+		If opt_issuperstrict Then
+			Emit "void _" + classid + "_New(BBOBJECT o);"
+			Emit "void _" + classid + "_Delete(BBOBJECT o);"
+		Else
+			Emit "int _" + classid + "_New(BBOBJECT o);"
+			Emit "int _" + classid + "_Delete(BBOBJECT o);"
+		End If
+
+		If classHasFunction(classDecl, "ToString") Then
+			Emit "BBSTRING _" + classid + "_ToString(BBOBJECT o);"
+		End If
+		
+		If classHasFunction(classDecl, "ObjectCompare") Then
+			Emit "BBINT _" + classid + "_ObjectCompare(BBOBJECT o, BBOBJECT otherObject);"
+		End If
+
+		If classHasFunction(classDecl, "SendMessage") Then
+			Emit "void _" + classid + "_SendMessage(BBOBJECT o, BBOBJECT message, BBOBJECT source);"
+		End If
+
+		Local reserved:String = "New,Delete,ToString,ObjectCompare,SendMessage,_reserved1_,_reserved2_,_reserved3_".ToLower()
+		
+		'Local fdecls:TFuncDecl[] = classDecl.GetAllFuncDecls(Null, False)
+		For Local decl:TDecl=EachIn classDecl.Decls()
+		'For Local fdecl:TFuncDecl = EachIn fdecls
+		
+			Local fdecl:TFuncDecl =TFuncDecl( decl )
+			If fdecl
+				If reserved.Find(fdecl.ident.ToLower()) = -1 Then
+					EmitClassFuncProto( fdecl )
+					Continue
+				End If
+			EndIf
+			
+			'Local gdecl:TGlobalDecl =TGlobalDecl( decl )
+			'If gdecl
+			'	Emit "static "+TransRefType( gdecl.ty )+" "+gdecl.munged+";"
+			'	Continue
+			'EndIf
+		Next
+
+		Emit ""
+
+		' bbobject def
+		
+		Rem
+		struct BBString{
+			BBClass*	clas;
+			int		refs;
+			int		length;
+			BBChar	buf[];
+		};
+		End Rem
+		
+		
+		' emit the class structure
+		Emit "struct BBClass_" + classid + " {"
+		If classDecl.superClass.ident = "Object" Then
+			Emit "BBClass*  super;"
+		Else
+			Emit "struct BBClass_" + classDecl.superClass.munged + "*  super;"
+		End If
+		Emit "void      (*free)( BBObject *o );"
+		Emit "BBDebugScope* debug_scope;"
+		Emit "int       instance_size;"
+		Emit "void      (*ctor)( BBOBJECT o );"
+		Emit "void      (*dtor)( BBOBJECT o );"
+		Emit "BBSTRING (*ToString)( BBOBJECT x );"
+		Emit "int       (*Compare)( BBOBJECT x,BBOBJECT y );"
+		Emit "BBOBJECT (*SendMessage)( BBOBJECT m,BBOBJECT s );"
+		Emit "void      (*_reserved1_)();"
+		Emit "void      (*_reserved2_)();"
+		Emit "void      (*_reserved3_)();"
+		
+		EmitBBClassClassFuncProto(classDecl)
+		
+'		' user defined functions and methods
+'		For Local decl:TDecl=EachIn classDecl.Decls()
+'			Local fdecl:TFuncDecl =TFuncDecl( decl )
+'			If fdecl
+'				If reserved.Find(fdecl.ident.ToLower()) = -1 Then
+'					EmitBBClassFuncProto( fdecl )
+'					Continue
+'				End If
+'			EndIf
+'		Next
+		
+		
+		Emit "};~n"
+		
+		
+		
+		
+		
+		'Emit "typedef struct " + classid + "_obj {"
+		Emit "struct " + classid + "_obj {"
+		Emit "struct BBClass_" + classid + "* clas;"
+		Emit "int refs;"
+
+		BeginLocalScope
+		EmitClassFieldsProto(classDecl)		
+		EndLocalScope
+'		For Local decl:TFieldDecl = EachIn classDecl.Decls()
+'			Emit "~t" + TransType(decl.declTy) + " _" + decl.ident.ToLower() + ";"
+'		Next
+		
+		'Emit "} " + classid + "_obj;"
+		Emit "};"
+
+
+
+
+		Emit "struct BBClass_" + classid + " " + classid + ";"
+Rem	
+		' super class
+'		If Not classDecl.superClass Then
+'			Emit "~t&bbObjectClass,"
+'		Else
+'		If classDecl.superClass.ident = "Object" Then
+			Emit "&" + classDecl.superClass.munged + ","
+'		Else
+'			Emit "&_" + classDecl.superClass.munged + ","
+'		End If
+'		End If
+		
+		Emit "bbObjectFree,"
+		
+		Emit "0,"
+		'Emit "~t" + (OBJECT_BASE_OFFSET + classDecl.lastOffset) + ","
+		Emit "sizeof" + Bra("struct " + classid + "_obj") + ","
+		
+		
+		Emit "_" + classid + "_New,"
+		Emit "_" + classid + "_Delete,"
+		
+		If classHasFunction(classDecl, "ToString") Then
+			Emit "_" + classid + "_ToString,"
+		Else
+			Emit "bbObjectToString,"
+		End If
+		
+		If classHasFunction(classDecl, "ObjectCompare") Then
+			Emit "_" + classid + "_ObjectCompare,"
+		Else
+			Emit "bbObjectCompare,"
+		End If
+
+		If classHasFunction(classDecl, "SendMessage") Then
+			Emit "_" + classid + "_SendMessage,"
+		Else
+			Emit "bbObjectSendMessage,"
+		End If
+		
+		'Emit "public:"
+
+		'fields
+		'For Local decl:TDecl=EachIn classDecl.Semanted()
+		'	Local fdecl:TFieldDecl =TFieldDecl( decl )
+		'	If fdecl
+		'		Emit TransRefType( fdecl.ty )+" "+fdecl.munged+";"
+		'		Continue
+		'	EndIf
+		'Next
+
+		'fields ctor
+		'Emit classid+"();"
+
+		'methods		
+		'For Local decl:TDecl=EachIn classDecl.Semanted()
+		'
+		'	Local fdecl:TFuncDecl =TFuncDecl( decl )
+		'	If fdecl
+		'		EmitFuncProto fdecl
+		'		Continue
+		'	EndIf
+		'	
+		'	Local gdecl:TGlobalDecl =TGlobalDecl( decl )
+		'	If gdecl
+		'		Emit "static "+TransRefType( gdecl.ty )+" "+gdecl.munged+";"
+		'		Continue
+		'	EndIf
+		'Next
+
+		'gc mark
+		'Emit "void mark();"
+
+		Emit "bbObjectReserved,"
+		Emit "bbObjectReserved,"
+		Emit "bbObjectReserved"
+
+		' methods/funcs
+		'reserved = "New,Delete,ToString,ObjectCompare,SendMessage".ToLower()
+
+		Local fdecls:TFuncDecl[] = classDecl.GetAllFuncDecls()
+		'For Local decl:TFuncDecl = EachIn classDecl.Decls()
+		For Local decl:TFuncDecl = EachIn fdecls
+			If reserved.Find(decl.ident.ToLower()) = -1 Then
+			
+				MungDecl decl
+
+				Emit ",_" + decl.munged
+			End If
+		Next
+		
+		Emit "};~n"
+End Rem
+
+
+		' fields
+		For Local decl:TFieldDecl = EachIn classDecl.Decls()
+'DebugStop
+			MungDecl decl
+			
+			'Emit "#define " + decl.munged + " " + (OBJECT_BASE_OFFSET + decl.offset)
+		
+		Next
+
+	End Method
+	
+	Method classHasFunction:Int(classDecl:TClassDecl, func:String)
+'DebugStop
+		For Local decl:TFuncDecl = EachIn classDecl.Decls()
+			If decl.ident.ToLower() = func.toLower() Then
+				Return True
+			End If
+		Next
+		Return False
+	End Method
+	
+	Method EmitMark( id$,ty:TType,queue:Int )
+	
+		If TObjectType( ty )
+		
+			If id.EndsWith( ".p" )
+				If ty.GetClass().IsInterface() id=id[..-2] Else InternalErr
+			Else 
+				If ty.GetClass().IsInterface() InternalErr
+			EndIf
+
+			If queue
+				Emit "gc_mark_q("+id+");"
+			Else
+				Emit "gc_mark("+id+");"
+			EndIf
+		Else If TArrayType( ty )
+			Emit "gc_mark("+id+");"
+			Return
+		EndIf
+	End Method
+	
+	Method EmitClassDecl( classDecl:TClassDecl )
+
+		'If classDecl.IsTemplateInst()
+		'	Return
+		'EndIf
+		
+		If classDecl.IsInterface()
+			Return
+		EndIf
+
+		Local classid$=classDecl.munged
+		Local superid$=classDecl.superClass.actual.munged
+		
+		EmitClassDeclNew(classDecl)
+		EmitClassDeclDelete(classDecl)
+		
+		Rem 
+		'fields ctor		
+		Emit classid+"::"+classid+"(){"
+		For Local decl:TDecl=EachIn classDecl.Semanted()
+			Local fdecl:TFieldDecl=TFieldDecl( decl )
+			If Not fdecl Continue
+			Emit TransField(fdecl,Null)+"="+fdecl.init.Trans()+";"
+		Next
+		Emit "}"
+		End Rem
+		Local reserved:String = "New,Delete".ToLower()
+
+		'methods		
+		For Local decl:TDecl=EachIn classDecl.Decls()
+		
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl
+				If reserved.Find(fdecl.ident.ToLower()) = -1 Then
+					EmitFuncDecl fdecl, , True
+					Continue
+				End If
+			EndIf
+			
+			'Local gdecl:TGlobalDecl=TGlobalDecl( decl )
+			'If gdecl
+		'		Emit TransRefType( gdecl.ty )+" "+classid+"::"+gdecl.munged+";"
+		'		Continue
+		'	EndIf
+		Next
+		Rem 
+		'gc_mark
+		Emit "void "+classid+"::mark(){"
+		If classDecl.superClass 
+			Emit classDecl.superClass.actual.munged+"::mark();"
+		EndIf
+		For Local decl:TDecl=EachIn classDecl.Semanted()
+			Local fdecl:TFieldDecl=TFieldDecl( decl )
+			If fdecl EmitMark TransField(fdecl,Null),fdecl.ty,True
+		Next
+		Emit "}"
+	End Rem
+	
+	
+		reserved = "New,Delete,ToString,ObjectCompare,SendMessage,_reserved1_,_reserved2_,_reserved3_".ToLower()
+	
+		Emit "struct BBClass_" + classid + " " + classid + "={"
+		
+		' super class
+'		If Not classDecl.superClass Then
+'			Emit "~t&bbObjectClass,"
+'		Else
+'		If classDecl.superClass.ident = "Object" Then
+			Emit "&" + classDecl.superClass.munged + ","
+'		Else
+'			Emit "&_" + classDecl.superClass.munged + ","
+'		End If
+'		End If
+		
+		Emit "bbObjectFree,"
+		
+		Emit "0,"
+		'Emit "~t" + (OBJECT_BASE_OFFSET + classDecl.lastOffset) + ","
+		Emit "sizeof" + Bra("struct " + classid + "_obj") + ","
+		
+		
+		Emit "_" + classid + "_New,"
+		Emit "_" + classid + "_Delete,"
+		
+		If classHasFunction(classDecl, "ToString") Then
+			Emit "_" + classid + "_ToString,"
+		Else
+			Emit "bbObjectToString,"
+		End If
+		
+		If classHasFunction(classDecl, "ObjectCompare") Then
+			Emit "_" + classid + "_ObjectCompare,"
+		Else
+			Emit "bbObjectCompare,"
+		End If
+
+		If classHasFunction(classDecl, "SendMessage") Then
+			Emit "_" + classid + "_SendMessage,"
+		Else
+			Emit "bbObjectSendMessage,"
+		End If
+		
+		'Emit "public:"
+
+		'fields
+		'For Local decl:TDecl=EachIn classDecl.Semanted()
+		'	Local fdecl:TFieldDecl =TFieldDecl( decl )
+		'	If fdecl
+		'		Emit TransRefType( fdecl.ty )+" "+fdecl.munged+";"
+		'		Continue
+		'	EndIf
+		'Next
+
+		'fields ctor
+		'Emit classid+"();"
+
+		'methods		
+		'For Local decl:TDecl=EachIn classDecl.Semanted()
+		'
+		'	Local fdecl:TFuncDecl =TFuncDecl( decl )
+		'	If fdecl
+		'		EmitFuncProto fdecl
+		'		Continue
+		'	EndIf
+		'	
+		'	Local gdecl:TGlobalDecl =TGlobalDecl( decl )
+		'	If gdecl
+		'		Emit "static "+TransRefType( gdecl.ty )+" "+gdecl.munged+";"
+		'		Continue
+		'	EndIf
+		'Next
+
+		'gc mark
+		'Emit "void mark();"
+
+		Emit "bbObjectReserved,"
+		Emit "bbObjectReserved,"
+		Emit "bbObjectReserved"
+
+		' methods/funcs
+		'reserved = "New,Delete,ToString,ObjectCompare,SendMessage".ToLower()
+
+		Local fdecls:TFuncDecl[] = classDecl.GetAllFuncDecls()
+		'For Local decl:TFuncDecl = EachIn classDecl.Decls()
+		For Local decl:TFuncDecl = EachIn fdecls
+			If reserved.Find(decl.ident.ToLower()) = -1 Then
+			
+				MungDecl decl
+
+				If decl.IsMethod() Then
+					Emit ",_" + decl.munged
+				Else
+					Emit "," + decl.munged
+				End If
+			End If
+		Next
+		
+		Emit "};~n"
+	
+	
+	End Method
+	
+	Method EmitClassDeclNew( classDecl:TClassDecl )
+		Local classid$=classDecl.munged
+		Local superid$=classDecl.superClass.actual.munged
+		
+		' New
+		If opt_issuperstrict Then
+			Emit "void _" + classid + "_New(BBObject *o) {"
+		Else
+			Emit "int _" + classid + "_New(BBObject *o) {"
+		End If
+		
+		If classDecl.superClass.ident = "Object" Then
+			Emit "bbObjectCtor(o);"
+		Else
+			Emit "_" + superid + "_New(o);"
+		End If
+		
+		Emit "o->clas = (BBClass*)&" + classid + ";"
+		
+		' field initialisation
+		For Local decl:TFieldDecl=EachIn classDecl.Decls()
+			' TODO : assume zero/null defaults for now
+			Local fld:String
+
+			' ((int*)((char*)o + 5))[0] = 
+			fld :+ TransFieldRef(decl, "o")
+
+			If TNumericType(decl.ty) Or TObjectType(decl.ty) Or TPointerType(decl.ty) Then
+				fld :+ "= 0;"
+			Else If TStringType(decl.ty) Then
+				fld :+ "= &bbEmptyString;"
+			End If
+			
+			Emit fld
+		Next
+
+		Emit "// TODO: implement our own New() code"
+		' TODO
+		
+		'
+		Emit "}"
+	End Method
+
+	Method EmitClassDeclDelete( classDecl:TClassDecl )
+		Local classid$=classDecl.munged
+		Local superid$=classDecl.superClass.actual.munged
+		
+		' New
+		If opt_issuperstrict Then
+			Emit "void _" + classid + "_Delete(BBObject *o) {"
+		Else
+			Emit "int _" + classid + "_Delete(BBObject *o) {"
+		End If
+		
+		Emit "// TODO: implement our own Delete() code"
+		' TODO
+	
+		
+		' field cleanup
+		For Local decl:TFieldDecl=EachIn classDecl.Decls()
+
+			
+			' String
+			If TStringType(decl.declTy) Then
+				Emit "BBRELEASE(" + TransFieldRef(decl, "o") + ")"
+			End If
+			
+			' object
+			' TODO
+
+		Next
+
+		' finally, call super delete
+		If classDecl.superClass.ident = "Object" Then
+			Emit "bbObjectDtor(o);"
+		Else
+			Emit "_" + superid + "_Delete(o);"
+		End If
+		
+		'
+		Emit "}"
+	End Method
+
+	Method TransFieldRef:String(decl:TFieldDecl, variable:String)
+		Local s:String = variable
+
+		' array.length
+		If decl.scope And decl.scope.ident = "Array" Then
+			If decl.ident = "length" Then
+				Return Bra(variable + "->scales[0]")
+			End If
+		End If
+		
+		' string methods
+		If decl.scope And decl.scope.ident = "String" Then
+			If decl.ident = "length" Then
+				Return Bra(variable + "->length")
+			End If
+		End If
+
+		If TNumericType(decl.ty) Then
+			' ((int*)((char*)o + 5))[0]
+			's = "(" + TransType(decl.declTy) + "*((char*)" + variable + "+" + decl.munged + "))[0]"
+			's = "((" + TransType(decl.declTy, "BB") + ")(struct " + decl.scope.munged + "_obj*)" + variable + ")->" + decl.munged + "))"
+			s = "((struct " + decl.scope.munged + "_obj*)" + variable + ")->" + decl.munged + " "
+		Else If TStringType(decl.ty) Then
+			' ((BBString*)((char*)o+5))
+			's = "((BBSTRING)(((" + decl.scope.munged + "_obj*)" + variable + ")->" + decl.munged + "))"
+			s = "((struct " + decl.scope.munged + "_obj*)" + variable + ")->" + decl.munged + " "
+		Else If TObjectType(decl.ty) Then
+			' ((BBString*)((char*)o+5))
+			's = "((BBSTRING)(((" + decl.scope.munged + "_obj*)" + variable + ")->" + decl.munged + "))"
+			s = "((struct " + decl.scope.munged + "_obj*)" + variable + ")->" + decl.munged + " "
+		Else If TPointerType(decl.ty) Then
+			s = "((struct " + decl.scope.munged + "_obj*)" + variable + ")->" + decl.munged + " "
+		End If
+		
+		Return s
+	End Method
+	
+	' " _" + classDecl.actual.munged + "_" + decl.ident.ToLower(
+
+	Method TransIfcArgs:String(funcDecl:TFuncDecl)
+		Local args:String
+
+		For Local i:Int=0 Until funcDecl.argDecls.Length
+			Local arg:TArgDecl = funcDecl.argDecls[i]
+
+			If args args:+","
+			args:+ arg.ident + TransIfcType( arg.ty )
+
+			If arg.init Then
+				args:+ "=" + TransIfcConstExpr(arg.init)
+			End If
+		Next
+			
+		Return Bra(args)
+	End Method
+	
+	Method EmitIfcClassFuncDecl(funcDecl:TFuncDecl)
+	
+		Local func:String
+	
+		' method / function	
+		If funcDecl.IsMethod() Then
+			func :+ "-"
+		Else
+			func :+ "+"
+		End If
+
+		func :+ funcDecl.ident
+		
+		func :+ TransIfcType(funcDecl.retType)
+		
+		' function args
+		func :+ TransIfcArgs(funcDecl)
+		
+		func :+ "="
+		
+		func :+ Enquote(funcDecl.munged)
+		
+		Emit func
+		
+	End Method
+
+	Method EmitIfcFuncDecl(funcDecl:TFuncDecl)
+	
+		Local func:String
+	
+		func :+ funcDecl.ident
+		
+		func :+ TransIfcType(funcDecl.retType)
+		
+		' function args
+		func :+ TransIfcArgs(funcDecl)
+		
+		func :+ "="
+		
+		func :+ Enquote(funcDecl.munged)
+		
+		If funcDecl.castTo Then
+			func :+ ":" + funcDecl.castTo
+			func :+ " " + funcDecl.munged + "("
+			
+			For Local i:Int = 0 Until funcDecl.argDecls.length
+				If i Then
+					func :+ ", "
+				End If
+				
+				func :+ funcDecl.argDecls[i].castTo
+			Next
+			
+			func :+ ")"
+		End If
+		
+		Emit func
+		
+	End Method
+	
+	Method TransIfcConstExpr:String(expr:TExpr)
+	
+		If Not expr.exprType Then
+			expr.Semant()
+		End If
+
+		If TNumericType(expr.exprType) Then
+			Return expr.Eval()
+		EndIf
+
+		If TStringType(expr.exprType) Then
+			Return "$" + Enquote(expr.Eval())
+		EndIf
+
+	End Method
+
+	Method EmitIfcConstDecl(constDecl:TConstDecl)
+		Local c:String
+		c = constDecl.ident + TransIfcType(constDecl.declTy)
+
+		If TExpr(constDecl.declInit) Then
+			c:+ "=" + TransIfcConstExpr(TExpr(constDecl.init))
+		End If		
+		
+		Emit c
+	End Method
+	
+	Method EmitIfcFieldDecl(fieldDecl:TFieldDecl)
+		Local f:String = "." + fieldDecl.ident + TransIfcType(fieldDecl.ty)
+		
+		f :+ "&"
+		
+		Emit f
+	End Method
+	
+	Method EmitIfcClassDecl(classDecl:TClassDecl)
+
+		Emit classDecl.ident + "^" + classDecl.superClass.ident + "{", False
+		
+		'PushMungScope
+		BeginLocalScope
+		
+		' fields, globals and consts
+'		For Local decl:TDecl=EachIn classDecl.Decls()
+		
+		' const
+		For Local cDecl:TConstDecl = EachIn classDecl.Decls()
+			EmitIfcConstDecl(cDecl)
+		Next
+			
+			' global
+		For Local gDecl:TGlobalDecl = EachIn classDecl.Decls()
+			EmitIfcGlobalDecl(gDecl)
+		Next
+			
+			
+			' field
+		For Local fDecl:TFieldDecl = EachIn classDecl.Decls()
+			EmitIfcFieldDecl(fDecl)
+		Next
+		
+		
+		' functions
+		Emit "-New%()=" + Enquote("_" + classDecl.munged + "_New")
+		Emit "-Delete%()=" + Enquote("_" + classDecl.munged + "_Delete")
+		
+		Local reserved:String = "New,Delete,ToString,ObjectCompare,SendMessage,_reserved1_,_reserved2_,_reserved3_".ToLower()
+
+		For Local decl:TDecl=EachIn classDecl.Decls()
+		
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl
+				If reserved.Find(fdecl.ident.ToLower()) = -1 Then
+					EmitIfcClassFuncDecl fdecl
+				End If
+				Continue
+			EndIf
+
+		Next
+	
+		
+		Emit "}=" + Enquote(classDecl.munged), False
+
+		'PopMungScope
+		EndLocalScope
+		
+	End Method
+	
+	Method EmitIfcGlobalDecl(globalDecl:TGlobalDecl)
+		Local g:String = globalDecl.ident
+		
+		g:+ TransIfcType(globalDecl.ty)
+		
+		g:+ "&"
+		
+		g :+ "="
+
+		g :+ "mem:p("
+		If TFunctionPtrType(globalDecl.ty) Then
+			g :+ Enquote(TFunctionPtrType(globalDecl.ty).func.munged)
+		Else
+			g :+ Enquote(globalDecl.munged)
+		End If
+		g :+ ")"
+		
+		Emit g
+	End Method
+	
+	Method EmitModuleInclude(moduleDecl:TModuleDecl)
+		If moduleDecl.filepath Then
+			' a module import
+			If FileType(moduleDecl.filepath) = FILETYPE_DIR Or opt_ismain Then
+				Emit "#include <" + ModuleHeaderFromIdent(moduleDecl.ident, True) + ">"
+			Else
+				' maybe a file import...
+				Emit "#include ~q" + FileHeaderFromFile(moduleDecl.filepath) + "~q"
+			End If
+'			DebugLog moduleDecl.filepath
+		End If
+	End Method
+	
+	Method EmitModuleInit(moduleDecl:TModuleDecl)
+		If moduleDecl.filepath Then
+			' a module import
+			If FileType(moduleDecl.filepath) = FILETYPE_DIR Then
+				Emit MungModuleName(moduleDecl.ident) + "();"
+			Else
+				' maybe a file import...
+				Emit MungImportFromFile(moduleDecl.filepath) + "();"
+			End If
+		End If
+	End Method
+	
+	Method TransHeader(app:TAppDecl)
+	
+		SetOutput("head")
+	
+		_app = app
+	
+		prefix = app.GetPathPrefix()
+	
+		' TODO
+'DebugStop
+		If Not opt_apptype Then
+			app.mainFunc.munged="bb_localmain"
+		Else
+			app.mainFunc.munged="bb_main"
+		End If
+		
+		For Local decl:TModuleDecl=EachIn app.imported.Values()
+			For Local mdecl:TDecl=EachIn decl.imported.Values()
+'DebugStop
+				MungDecl mdecl
+DebugLog mdecl.munged
+
+				If TModuleDecl(mdecl) And app.mainModule <> mdecl And mdecl.ident <> "brl.classes" And mdecl.ident <> "brl.blitzkeywords" Then
+					EmitModuleInclude(TModuleDecl(mdecl))
+				End If
+			Next
+		Next
+
+		Emit "int " + app.munged + "();"
+
+		For Local decl:TDecl=EachIn app.Semanted()
+		
+			MungDecl decl
+
+			Local cdecl:TClassDecl=TClassDecl( decl )
+			If Not cdecl Continue
+
+' mung, but don't emit			
+'			Emit prefix + decl.munged+";"
+			
+			'PushMungScope
+			BeginLocalScope
+			
+			For Local decl:TDecl=EachIn cdecl.Semanted()
+				MungDecl decl
+			Next
+			
+			EndLocalScope
+			'PopMungScope
+		Next
+
+		'prototypes/header!
+		For Local decl:TDecl=EachIn app.Semanted()
+		
+			Local gdecl:TGlobalDecl=TGlobalDecl( decl )
+			If gdecl
+				If Not TFunctionPtrType(gdecl.ty) Then
+					Emit "extern "+TransRefType( gdecl.ty, "" )+" "+gdecl.munged+";"	'forward reference...
+				Else
+					Emit "extern "+TransRefType( gdecl.ty, gdecl.munged )+";"	'forward reference...
+				End If
+				Continue
+			EndIf
+		
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl' And Not fdecl.IsExtern()
+				' don't include the main function - it's handled separately
+				If fdecl = app.mainFunc Then
+					Continue
+				End If
+			
+				EmitFuncDecl( fdecl, True)
+				Continue
+			EndIf
+		
+			Local cdecl:TClassDecl=TClassDecl( decl )
+			If cdecl
+				EmitClassProto cdecl
+				Continue
+			EndIf
+		Next
+			
+	End Method
+	
+	Method TransSource(app:TAppDecl)
+
+		SetOutput("source")
+
+		' include our header
+		EmitModuleInclude(app.mainModule)
+
+		' strings
+		For Local s:String = EachIn app.stringConsts.Keys()
+			Local key:String = String(app.stringConsts.ValueForKey(s))
+
+			Emit "static BBString " + key + "={"
+			Emit "&bbStringClass,"
+			Emit "2147483647,"
+			Emit s.length + ","
+			
+			Local t:String = "{"
+			
+			For Local i:Int = 0 Until s.length
+				If i Then
+					t:+ ","
+				End If
+				t:+ s[i]
+				
+				If i And Not (i Mod 16) Then
+					Emit t
+					t = ""
+				End If
+			Next
+			
+			Emit t + "}"
+			
+			Emit "};"
+		Next
+		
+		'definitions!
+		For Local decl:TDecl=EachIn app.Semanted()
+			
+			Local gdecl:TGlobalDecl=TGlobalDecl( decl )
+			If gdecl
+				If Not TFunctionPtrType(gdecl.ty) Then
+					Emit TransRefType( gdecl.ty, "WW" )+" "+gdecl.munged+";"
+				Else
+					Emit TransRefType( gdecl.ty, gdecl.munged ) + ";"
+				End If
+				Continue
+			EndIf
+			
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl And Not fdecl.IsExtern()
+				' don't include the main function - it's handled separately
+				If fdecl = app.mainFunc Then
+					Continue
+				End If
+
+				EmitFuncDecl fdecl
+				Continue
+			EndIf
+
+			Local cdecl:TClassDecl=TClassDecl( decl )
+			If cdecl
+				EmitClassDecl cdecl
+				Continue
+			EndIf
+		Next
+
+		Emit "static int " + app.munged + "_inited" + " = 0;"	
+		
+		Emit "int " + app.munged + "(){"
+		
+		' call any imported mod inits
+		For Local decl:TModuleDecl=EachIn app.imported.Values()
+			For Local mdecl:TDecl=EachIn decl.imported.Values()
+				If TModuleDecl(mdecl) And app.mainModule <> mdecl And mdecl.ident <> "brl.classes" Then
+					EmitModuleInit(TModuleDecl(mdecl))
+				End If
+			Next
+		Next
+		
+		' initialise stuff
+		Emit "if (!" + app.munged + "_inited) {"
+		Emit app.munged + "_inited = 1;"
+		
+		' register types
+		For Local decl:TDecl=EachIn app.Semanted()
+			Local cdecl:TClassDecl=TClassDecl( decl )
+			If cdecl
+				Emit "bbObjectRegisterType(&" + cdecl.munged + ");"
+			EndIf
+		Next
+		'
+		
+		' initialise globals
+		For Local decl:TGlobalDecl=EachIn app.semantedGlobals
+'DebugStop
+			decl.Semant
+			
+			' TODO : what about OnDebugStop etc, who have no init ?
+			If decl.init Then
+				Emit TransGlobal( decl )+"="+decl.init.Trans()+";"
+			End If
+		Next
+		
+		' now do the local main stuff
+		app.mainFunc.Semant()
+		EmitBlock app.mainFunc
+		
+		
+		Emit "}"
+		Emit "return 0;"
+		Emit "}"
+
+		'Emit "void gc_mark(){"
+		'For Local decl:TGlobalDecl=EachIn app.semantedGlobals
+		'	EmitMark TransGlobal( decl ),decl.ty,False
+		'Next
+		'Emit "}"
+		
+	End Method
+	
+	Method TransInterface(app:TAppDecl)
+
+		SetOutput("interface")
+
+		' module info
+		For Local info:String = EachIn app.mainModule.modInfo
+			Emit "ModuleInfo ~q" + info + "~q"
+		Next
+		
+		' module imports
+		For Local decl:TDecl=EachIn app.mainModule.imported.Values()
+			Local mdecl:TModuleDecl=TModuleDecl( decl )
+			If mdecl Then
+				If mdecl.IsActualModule() Then
+					Emit "import " + mdecl.ident
+				End If
+			End If
+		Next
+		
+		' other imports
+		For Local s:String = EachIn app.fileImports
+			Emit "import ~q" + s + "~q"
+		Next
+
+		' consts
+		For Local decl:TDecl=EachIn app.Semanted()
+			Local cdecl:TConstDecl=TConstDecl( decl )
+			If cdecl
+				EmitIfcConstDecl(cdecl)
+			End If
+		Next
+
+		' classes
+		For Local decl:TDecl=EachIn app.Semanted()
+			Local cdecl:TClassDecl=TClassDecl( decl )
+			If cdecl
+				EmitIfcClassDecl(cdecl)
+			EndIf
+		Next
+
+		' functions
+		For Local decl:TDecl=EachIn app.Semanted()
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl And fdecl <> app.mainFunc Then
+				EmitIfcFuncDecl(fdecl)
+			End If
+		Next
+		
+		' globals
+		For Local decl:TDecl=EachIn app.Semanted()
+			Local gdecl:TGlobalDecl=TGlobalDecl( decl )
+			If gdecl
+				EmitIfcGlobalDecl(gdecl)
+			End If
+		Next
+		
+	End Method
+	
+	Method TransApp( app:TAppDecl )
+	
+		If app.mainModule.IsSuperStrict()
+			opt_issuperstrict = True
+		End If
+	
+		TransHeader(app)
+	
+		TransSource(app)
+		
+		TransInterface(app)
+	
+	End Method
+	
+End Type

+ 1728 - 0
decl.bmx

@@ -0,0 +1,1728 @@
+'SuperStrict
+
+Const DECL_EXTERN:Int=		$010000
+Const DECL_PRIVATE:Int=	$020000
+Const DECL_ABSTRACT:Int=	$040000
+Const DECL_FINAL:Int=		$080000
+
+Const DECL_SEMANTED:Int=	$100000
+Const DECL_SEMANTING:Int=	$200000
+
+Const DECL_POINTER:Int=	$400000
+
+Const CLASS_INTERFACE:Int=	$001000
+Const CLASS_THROWABLE:Int=	$002000
+
+Global _env:TScopeDecl
+Global _envStack:TList=New TList
+
+Global _loopnest:Int
+
+Function PushEnv( env:TScopeDecl )
+	If _env _envStack.AddLast( _env )
+	_env=env
+End Function
+
+Function PopEnv()
+	_env=TScopeDecl( _envStack.RemoveLast() )
+End Function
+
+Type TFuncDeclList Extends TList
+End Type
+
+Type TDecl
+	Field ident$
+	Field munged$
+	Field errInfo$
+	Field actual:TDecl
+	Field scope:TScopeDecl
+	Field attrs:Int
+	
+	Field declImported:Int = False
+	
+	Method New()
+		errInfo=_errInfo
+		actual=Self
+	End Method
+	
+	Method OnCopy:TDecl() Abstract
+	
+	Method ToString$()
+		If TClassDecl( scope ) Return scope.ToString()+"."+ident
+		Return ident
+	End Method
+	
+	Method IsExtern:Int()
+		Return (attrs & DECL_EXTERN)<>0
+	End Method
+	
+	Method IsPrivate:Int()
+		Return (attrs & DECL_PRIVATE)<>0
+	End Method
+	
+	Method IsAbstract:Int()
+		Return (attrs & DECL_ABSTRACT)<>0
+	End Method
+	
+	Method IsSemanted:Int()
+		Return (attrs & DECL_SEMANTED)<>0
+	End Method
+	
+	Method IsSemanting:Int()
+		Return (attrs & DECL_SEMANTING)<>0
+	End Method
+	
+	Method FuncScope:TFuncDecl()
+		If TFuncDecl( Self ) Return TFuncDecl( Self )
+		If scope Return scope.FuncScope()
+	End Method
+
+	Method ClassScope:TClassDecl()
+		If TClassDecl( Self ) Return TClassDecl( Self )
+		If scope Return scope.ClassScope()
+	End Method
+	
+	Method ModuleScope:TModuleDecl()
+		If TModuleDecl( Self ) Return TModuleDecl( Self )
+		If scope Return scope.ModuleScope()
+	End Method
+	
+	Method AppScope:TAppDecl()
+		If TAppDecl( Self ) Return TAppDecl( Self )
+		If scope Return scope.AppScope()
+	End Method
+	
+	Method CheckAccess:Int()
+		If IsPrivate() And ModuleScope()<>_env.ModuleScope() Return False
+		Return True
+	End Method
+	
+	Method AssertAccess()
+		If Not CheckAccess()
+			Err ToString() +" is private."
+		EndIf
+	End Method
+
+	Method Copy:TDecl()
+		Local t:TDecl=OnCopy()
+		t.munged=munged
+		t.errInfo=errInfo
+		Return t
+	End Method
+
+	Method Semant()
+'DebugStop
+		If IsSemanted() Return
+'DebugLog "Semant : " + ident
+		
+		If IsSemanting() Err "Cyclic declaration of '"+ident+"'."
+		
+		If actual<>Self
+			actual.Semant
+		EndIf
+
+		PushErr errInfo
+		
+		If scope
+			PushEnv scope
+		EndIf
+		
+		attrs:|DECL_SEMANTING
+
+		'If ident And ClassScope() Print "Semanting "+ToString()
+
+		OnSemant
+		
+		attrs:&~DECL_SEMANTING
+
+		attrs:|DECL_SEMANTED
+
+		If scope 
+			'If Not IsExtern()
+			If TFuncDecl(Self) And attrs & FUNC_PTR
+			DebugLog "**** " + ident
+			Else
+
+				scope._semanted.AddLast Self
+				
+				If TGlobalDecl( Self )
+					' FIXME
+					If AppScope() Then
+						AppScope().semantedGlobals.AddLast TGlobalDecl( Self )
+					End If
+				EndIf
+				
+				If TModuleDecl( scope )
+'DebugStop
+					' FIXME
+					Local app:TAppDecl = AppScope()
+					If app Then
+						app._semanted.AddLast Self
+					End If
+				EndIf
+			
+			EndIf
+			
+			PopEnv
+		EndIf
+		
+		PopErr
+	End Method
+	
+	Method InitInstance:TDecl( decl:TDecl )
+		decl.ident=ident
+		decl.munged=munged
+		decl.errInfo=errInfo
+		decl.actual=actual
+		decl.scope=Null
+		decl.attrs=attrs & ~(DECL_SEMANTED|DECL_SEMANTING)
+		Return decl
+	End Method
+	
+	Method GenInstance:TDecl()
+		InternalErr
+	End Method
+	
+	Method OnSemant() Abstract
+
+End Type
+
+Type TValDecl Extends TDecl
+	'pre-semant
+	Field declTy:TType
+	Field declInit:TExpr
+	'post-semant
+	Field ty:TType
+	Field init:TExpr
+	
+	Method ToString$()
+		Local t$=Super.ToString()
+		If ty Return t+":"+ty.ToString()
+		If declTy Return t+":"+declTy.ToString()
+		Return t+":?"
+	End Method
+
+	Method CopyInit:TExpr()
+		If init Return init.Copy()
+	End Method
+	
+	Method OnSemant()
+		If declTy
+			ty=declTy.Semant()
+			If declInit init=declInit.Copy().SemantAndCast(ty)
+		Else If declInit
+			init=declInit.Copy().Semant()
+			ty=init.exprType
+		Else
+			InternalErr
+		EndIf
+	End Method
+	
+End Type
+
+Type TConstDecl Extends TValDecl
+	Field value$
+	
+	Method Create:TConstDecl( ident$,ty:TType,init:TExpr,attrs:Int )
+		Self.ident=ident
+		Self.munged=ident
+		Self.declTy=ty
+		Self.declInit=init
+		Self.attrs=attrs
+		Return Self
+	End Method
+
+	Method GenInstance:TDecl()
+		Local inst:TConstDecl = New TConstDecl
+		InitInstance inst
+		inst.declTy=declTy
+		inst.declInit=declInit
+		Return inst
+	End Method
+
+	Method OnCopy:TDecl()
+		Return New TConstDecl.Create( ident,ty,CopyInit(), attrs )
+	End Method
+	
+	Method OnSemant()
+		Super.OnSemant()
+		'If Not IsExtern() value=init.Eval()
+		If init Then
+			value=init.Eval()
+		End If
+	End Method
+	
+End Type
+
+Type TVarDecl Extends TValDecl
+
+End Type
+
+Type TLocalDecl Extends TVarDecl
+
+	Method Create:TLocalDecl( ident$,ty:TType,init:TExpr,attrs:Int=0 )
+		Self.ident=ident
+		Self.declTy=ty
+		Self.declInit=init
+		Self.attrs=attrs
+		Return Self
+	End Method
+	
+	Method OnCopy:TDecl()
+		Return New TLocalDecl.Create( ident,ty,CopyInit(),attrs )
+	End Method
+	
+	Method ToString$()
+		Return "Local "+Super.ToString()
+	End Method
+
+End Type
+
+Type TArgDecl Extends TLocalDecl
+
+	Field castTo:String
+	
+	Method Create:TArgDecl( ident$,ty:TType,init:TExpr,attrs:Int=0 )
+		Self.ident=ident
+		Self.declTy=ty
+		Self.declInit=init
+		Self.attrs=attrs
+		Return Self
+	End Method
+	
+	Method GenInstance:TDecl()
+		Local inst:TArgDecl=New TArgDecl
+		InitInstance inst
+		inst.declTy=declTy
+		inst.declInit=declInit
+		Return inst
+	End Method
+	
+	Method OnCopy:TDecl()
+		Return New TArgDecl.Create( ident,ty,CopyInit(),attrs )
+	End Method
+	
+	Method ToString$()
+		Return Super.ToString()
+	End Method
+
+	
+End Type
+
+Type TGlobalDecl Extends TVarDecl
+	
+	Method Create:TGlobalDecl( ident$,ty:TType,init:TExpr,attrs:Int=0 )
+		Self.ident=ident
+		Self.declTy=ty
+		Self.declInit=init
+		Self.attrs=attrs
+		Return Self
+	End Method
+
+	Method OnCopy:TDecl()
+		Return New TGlobalDecl.Create( ident,ty,CopyInit(),attrs )
+	End Method
+	
+	Method ToString$()
+		Return "Global "+Super.ToString()
+	End Method
+
+	Method GenInstance:TDecl()
+'		PushErr errInfo
+'		Err "Global variables cannot be used inside generic classes."
+		Local inst:TGlobalDecl=New TGlobalDecl
+		InitInstance inst
+		inst.declTy=declTy
+		inst.declInit=declInit
+		Return inst
+	End Method
+	
+End Type
+
+Type TFieldDecl Extends TVarDecl
+
+	' location offset in object variable data
+	Field offset:Int
+
+	Method Create:TFieldDecl( ident$,ty:TType,init:TExpr,attrs:Int=0 )
+		Self.ident=ident
+		Self.declTy=ty
+		Self.declInit=init
+		Self.attrs=attrs
+		Return Self
+	End Method
+
+	Method OnCopy:TDecl()
+		Return New TFieldDecl.Create( ident,ty,CopyInit(),attrs )
+	End Method
+	
+	Method ToString$()
+		Return "Field "+Super.ToString()
+	End Method
+	
+	Method GenInstance:TDecl()
+		Local inst:TFieldDecl=New TFieldDecl
+		InitInstance inst
+		inst.declTy=declTy
+		inst.declInit=declInit
+		Return inst
+	End Method
+	
+End Type
+
+Type TAliasDecl Extends TDecl
+
+	Field decl:Object
+	
+	Method Create:TAliasDecl( ident$,decl:Object,attrs:Int=0 )
+		Self.ident=ident
+		Self.decl=decl
+		Self.attrs=attrs
+		Return Self
+	End Method
+	
+	Method OnCopy:TDecl()
+		Return New TAliasDecl.Create( ident,decl,attrs )
+	End Method
+	
+	Method OnSemant()
+	End Method
+	
+End Type
+
+Type TScopeDecl Extends TDecl
+
+'Private
+
+	Field _decls:TList=New TList'<TDecl>
+	Field _semanted:TList=New TList'<TDecl>
+
+	Field declsMap:TMap=New TMap'<Object>
+
+'Public
+
+	Method OnCopy:TDecl()
+		InternalErr
+	End Method
+
+	Method Decls:TList()
+		Return _decls
+	End Method
+	
+	Method Semanted:TList()
+		Return _semanted
+	End Method
+	
+	Method FuncDecls:TList( id$="" )
+		Local fdecls:TList=New TList
+		For Local decl:TDecl=EachIn _decls
+			If id And decl.ident<>id Continue
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl fdecls.AddLast fdecl
+		Next
+		Return fdecls
+	End Method
+	
+	Method MethodDecls:TList( id$="" )
+		Local fdecls:TList=New TList
+		For Local decl:TDecl=EachIn _decls
+			If id And decl.ident<>id Continue
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl And fdecl.IsMethod() fdecls.AddLast fdecl
+		Next
+		Return fdecls
+	End Method
+	
+	Method SemantedFuncs:TList( id$="" )
+		Local fdecls:TList=New TList
+		For Local decl:TDecl=EachIn _semanted
+			If id And decl.ident<>id Continue
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl fdecls.AddLast fdecl
+		Next
+		Return fdecls
+	End Method
+	
+	Method SemantedMethods:TList( id$="" )
+		Local fdecls:TList=New TList
+		For Local decl:TDecl=EachIn _semanted
+			If id And decl.ident<>id Continue
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl And fdecl.IsMethod() fdecls.AddLast fdecl
+		Next
+		Return fdecls
+	End Method
+	
+	Method InsertDecl( decl:TDecl )
+		If decl.scope InternalErr
+		
+		Local ident$=decl.ident
+		If Not ident Return
+		
+		decl.scope=Self
+		_decls.AddLast decl
+
+		'Local _decls:TMap
+		Local tdecl_:Object=declsMap.ValueForKey( ident.ToLower() )
+		
+		'If TFuncDecl( decl )
+		'	Local funcs:TFuncDeclList=TFuncDeclList( tdecl_ )
+		'	If funcs Or Not tdecl_
+		'		If Not funcs
+		'			funcs=New TFuncDeclList
+		'			declsMap.Insert ident.ToLower(),funcs
+		'		EndIf
+		'		funcs.AddLast TFuncDecl( decl )
+		'	Else
+		'		Err "Duplicate identifier '"+ident+"'."
+		'	EndIf
+		'Else
+		If Not tdecl_
+'DebugLog "Adding " + decl.ident
+			declsMap.Insert ident.ToLower(),decl
+		Else
+			Err "Duplicate identifier '"+ident+"'."
+		EndIf
+
+	End Method
+
+	Method InsertDecls( _decls:TList )
+		For Local decl:TDecl=EachIn _decls
+			InsertDecl decl
+		Next
+	End Method
+	
+	'This is overridden by TClassDecl and TModuleDecl
+	Method GetDecl:Object( ident$ )
+'DebugLog "GetDecl (" + Self.ident + ") : " + ident
+		Local decl:Object=Object(declsMap.ValueForKey( ident.ToLower() ))
+		
+		If Not decl Then
+			If Self.ident.ToLower() = ident.ToLower() Then
+				decl = Self
+			End If
+		End If
+		
+		If Not decl Return Null
+		
+		Local adecl:TAliasDecl=TAliasDecl( decl )
+		If Not adecl Return decl
+		
+		If adecl.CheckAccess() Return adecl.decl
+	End Method
+	
+	Method FindDecl:Object( ident$ )
+		Local decl:Object=GetDecl( ident )
+		If decl Return decl
+		If scope Return scope.FindDecl( ident )
+	End Method
+	
+	Method FindValDecl:TValDecl( ident$ )
+		Local decl:TValDecl=TValDecl( FindDecl( ident ) )
+		If Not decl Return Null
+		decl.AssertAccess
+		decl.Semant
+		Return decl
+	End Method
+
+	Method FindType:TType( ident$,args:TType[] )
+		Local decl:Object=(GetDecl( ident ))
+		If decl Then
+			Local ty:TType=TType(decl)
+			If ty
+				If args.Length Err "Wrong number of type arguments"
+				Return ty
+			EndIf
+			Local cdecl:TClassDecl=TClassDecl( decl )
+			If cdecl
+				cdecl.AssertAccess
+				cdecl=cdecl.GenClassInstance( args )
+				cdecl.Semant
+				Return cdecl.objectType
+			EndIf
+		EndIf
+		If scope Return scope.FindType( ident,args )
+	End Method
+	
+	Method FindScopeDecl:TScopeDecl( ident$ )
+		Local decl:TScopeDecl=TScopeDecl( FindDecl( ident ) )
+		If Not decl Return Null
+		decl.AssertAccess
+		decl.Semant
+		Return decl
+	End Method
+Rem	
+	Method FindClassDecl:TClassDecl( ident$,args:TClassDecl[] = Null )
+		Local decl:TClassDecl=TClassDecl( GetDecl( ident ) )
+		If Not args Then
+			args = New TClassDecl[0]
+		End If
+		If Not decl
+			If scope Return scope.FindClassDecl( ident,args )
+			Return Null
+		EndIf
+		decl.AssertAccess
+		decl.Semant
+		Return decl.GenClassInstance( args )
+	End Method
+End Rem	
+	Method FindModuleDecl:TModuleDecl( ident$ )
+'DebugStop
+		Local decl:TModuleDecl=TModuleDecl( GetDecl( ident ) )
+		If Not decl
+			If scope Return scope.FindModuleDecl( ident )
+			Return Null
+		EndIf
+		decl.AssertAccess
+		
+		' only semant on "real" module
+		If Not decl.declImported Then
+			decl.Semant
+		End If
+		Return decl
+	End Method
+	
+	Method FindFuncDecl:TFuncDecl( ident$,argExprs:TExpr[] = Null,explicit:Int=False )
+'DebugLog "FindFuncDecl : " + ident
+'If ident = "ReadStream" Then DebugStop
+		'Local funcs:TFuncDeclList=TFuncDeclList( FindDecl( ident ) )
+		Local f:TDecl = TDecl(findDecl(ident))
+		If Not f Then Return Null
+		
+		Local func:TFuncDecl = TFuncDecl(f)
+		If Not func Then
+			If TVarDecl(f) Then
+				If TFunctionPtrType(TVarDecl(f).ty) Then
+					func = TFunctionPtrType(TVarDecl(f).ty).func
+					If Not func.scope Then
+						func.scope = f.scope
+					End If
+				End If
+			End If
+		End If
+		If Not func Return Null
+
+		If Not argExprs
+			argExprs = New TExpr[0]
+		End If
+	
+		'For Local func:TFuncDecl=EachIn funcs
+			func.Semant()
+		'Next
+		
+		Local match:TFuncDecl,isexact:Int
+		Local _err$
+'DebugStop
+		'For Local func:TFuncDecl=EachIn funcs
+		While True
+			If Not func.CheckAccess() Exit
+			
+			Local argDecls:TArgDecl[]=func.argDecls
+			
+			If argExprs.Length>argDecls.Length Exit
+			
+			Local exact:Int=True
+			Local possible:Int=True
+			
+			For Local i:Int=0 Until argDecls.Length
+
+				If i<argExprs.Length And argExprs[i]
+				
+					Local declTy:TType=argDecls[i].ty
+					Local exprTy:TType=argExprs[i].exprType
+					
+					If exprTy.EqualsType( declTy ) Exit
+					
+					exact=False
+					
+					If Not explicit And exprTy.ExtendsType( declTy ) Exit
+
+				Else If argDecls[i].init
+
+					exact=False
+
+					If Not explicit Exit
+				EndIf
+			
+				possible=False
+				Exit
+			Next
+			
+			If Not possible Exit
+			
+			If exact
+				If isexact
+					Err "Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
+				Else
+					_err=""
+					match=func
+					isexact=True
+				EndIf
+			Else
+				If Not isexact
+					If match 
+						_err="Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
+					Else
+						match=func
+					EndIf
+				EndIf
+			EndIf
+			Exit
+		Wend
+		
+		If Not isexact
+			If _err Err _err
+			If explicit Return Null
+		EndIf
+		
+		If Not match
+			Local t$
+			For Local i:Int=0 Until argExprs.Length
+				If t t:+","
+				If argExprs[i] t:+argExprs[i].exprType.ToString()
+			Next
+			Err "Unable to find overload for "+ident+"("+t+")."
+		EndIf
+		
+		match.AssertAccess
+
+		Return match
+	End Method
+	
+	Method OnSemant()
+	End Method
+	
+End Type
+
+Type TBlockDecl Extends TScopeDecl
+	Field stmts:TList=New TList
+	
+	Method Create:TBlockDecl( scope:TScopeDecl )
+		Self.scope=scope
+		Return Self
+	End Method
+	
+	Method AddStmt( stmt:TStmt )
+		stmts.AddLast stmt
+	End Method
+	
+	Method OnCopy:TDecl()
+		Local t:TBlockDecl=New TBlockDecl
+		For Local stmt:TStmt=EachIn stmts
+			t.AddStmt stmt.Copy( t )
+		Next
+		Return t
+	End Method
+
+	Method OnSemant()
+		PushEnv Self
+		For Local stmt:TStmt=EachIn stmts
+			stmt.Semant
+		Next
+		PopEnv
+	End Method
+
+	Method CopyBlock:TBlockDecl( scope:TScopeDecl )
+		Local t:TBlockDecl=TBlockDecl( Copy() )
+		t.scope=scope
+		Return t
+	End Method
+
+End Type
+
+Const FUNC_METHOD:Int=1			'mutually exclusive with ctor
+Const FUNC_CTOR:Int=2
+Const FUNC_PROPERTY:Int=4
+Const FUNC_PTR:Int=8
+Const FUNC_BUILTIN:Int = $10
+
+'Fix! A func is NOT a block/scope!
+'
+Type TFuncDecl Extends TBlockDecl
+
+	Field retType:TType
+	Field retTypeExpr:TType
+	Field argDecls:TArgDecl[]
+
+	Field overrides:TFuncDecl
+	Field superCtor:TInvokeSuperExpr
+	
+	Field castTo:String
+	Field noCastGen:Int
+	
+	Method CreateF:TFuncDecl( ident$,ty:TType,argDecls:TArgDecl[],attrs:Int )
+		Self.ident=ident
+		Self.retTypeExpr=ty
+		If argDecls
+			Self.argDecls=argDecls
+		Else
+			Self.argDecls = New TArgDecl[0]
+		End If
+		Self.attrs=attrs
+		Return Self
+	End Method
+	
+	Method OnCopy:TDecl()
+		Local args:TArgDecl[]=argDecls[..]
+		For Local i:Int=0 Until args.Length
+			args[i]=TArgDecl( args[i].Copy() )
+		Next
+		Local t:TFuncDecl=New TFuncDecl.CreateF( ident,retType,args,attrs )
+		For Local stmt:TStmt=EachIn stmts
+			t.AddStmt stmt.Copy( t )
+		Next
+		Return  t
+	End Method
+
+	Method GenInstance:TDecl()
+		Local inst:TFuncDecl=New TFuncDecl
+		InitInstance inst
+		inst.retTypeExpr=retTypeExpr
+		inst.argDecls=argDecls[..]
+		For Local i:Int=0 Until argDecls.Length
+			inst.argDecls[i]=TArgDecl( argDecls[i].GenInstance() )
+		Next
+		Return inst
+	End Method
+	
+	Method ToString$()
+		Local t$
+		For Local decl:TArgDecl=EachIn argDecls
+			If t t:+","
+			t:+decl.ToString()
+		Next
+		Local q$
+		If IsCtor()
+			q="Method "+Super.ToString()
+		Else
+			If IsMethod() q="Method " Else q="Function "
+			q:+Super.ToString()+":"
+			If retType
+				q:+retType.ToString()
+			Else If retTypeExpr 
+				q:+retTypeExpr.ToString()
+			Else
+				q:+"?"
+			EndIf
+		EndIf
+		Return q+"("+t+")"
+	End Method
+	
+	Method IsBuiltIn:Int()
+		Return (attrs & FUNC_BUILTIN)<>0
+	End Method
+	
+	Method IsCtor:Int()
+		Return (attrs & FUNC_CTOR)<>0
+	End Method
+
+	Method IsMethod:Int()
+		Return (attrs & FUNC_METHOD)<>0
+	End Method
+	
+	Method IsStatic:Int()
+		Return (attrs & (FUNC_METHOD|FUNC_CTOR))=0
+	End Method
+	
+	Method IsProperty:Int()
+		Return (attrs & FUNC_PROPERTY)<>0
+	End Method
+	
+	Method EqualsArgs:Int( decl:TFuncDecl )
+		If argDecls.Length<>decl.argDecls.Length Return False
+		For Local i:Int=0 Until argDecls.Length
+			If Not argDecls[i].ty.EqualsType( decl.argDecls[i].ty ) Return False
+		Next
+		Return True
+	End Method
+
+	Method EqualsFunc:Int( decl:TFuncDecl )
+		Return retType.EqualsType( decl.retType ) And EqualsArgs( decl )
+	End Method
+
+	Method OnSemant()
+
+		'semant ret type
+		If Not retTypeExpr Then
+			retType = TType.voidType
+		Else
+			retType=retTypeExpr.Semant()
+		End If
+		
+		If TArrayType( retType ) And Not retType.EqualsType( retType.ActualType() )
+'			Err "Return type cannot be an array of generic objects."
+		EndIf
+		
+		'semant args
+		For Local arg:TArgDecl=EachIn argDecls
+			InsertDecl arg
+			arg.Semant
+		Next
+		
+		If actual<>Self Return
+		
+		'check for duplicate decl
+		For Local decl:TFuncDecl=EachIn scope.SemantedFuncs( ident )
+			If decl<>Self And EqualsArgs( decl )
+				Err "Duplicate declaration "+ToString()
+			EndIf
+		Next
+		
+		'get cdecl, sclasss
+		Local cdecl:TClassDecl=ClassScope(),sclass:TClassDecl
+		If cdecl sclass=TClassDecl( cdecl.superClass )
+		
+		'prefix call to super ctor if necessary
+		If IsCtor() And superCtor=Null 
+			If sclass.FindFuncDecl( "new", Null )
+				superCtor=New TInvokeSuperExpr.Create( "new" )
+				stmts.AddFirst New TExprStmt.Create( superCtor )
+			EndIf
+		EndIf
+		
+		'append a return statement if necessary
+		If Not IsExtern() And Not TVoidType( retType ) And Not TReturnStmt( stmts.Last() )
+			Local stmt:TReturnStmt
+			If IsCtor()
+				stmt=New TReturnStmt.Create( Null )
+			Else
+				stmt=New TReturnStmt.Create( New TConstExpr.Create( retType,"" ) )
+			EndIf
+			stmt.errInfo=errInfo
+			stmts.AddLast stmt
+		EndIf
+
+		'check we exactly match an override
+		If sclass And IsMethod()
+'DebugStop
+'DebugLog ident + "..."
+			While sclass
+'DebugLog "Checking " + sclass.ident
+				Local found:Int
+				For Local decl:TFuncDecl=EachIn sclass.MethodDecls( )
+'DebugLog "Method = " + decl.ident
+					If Not decl.IsSemanted() Then
+						decl.Semant
+					End If
+					
+					If decl.ident = ident Then
+						found=True
+						If EqualsFunc( decl ) 
+'DebugLog "Found"
+							overrides=TFuncDecl( decl.actual )
+						'If overrides.munged
+						'	If munged And munged<>overrides.munged
+						'		InternalErr
+						'	EndIf
+						'	munged=overrides.munged
+						'EndIf
+						EndIf
+					End If
+				Next
+				If found
+					If Not overrides Err "Overriding method does not match any overridden method."
+					Exit
+				EndIf
+				sclass=sclass.superClass
+			Wend
+		EndIf
+'If ident = "OnDebugStop" DebugStop
+		attrs:|DECL_SEMANTED
+		
+		Super.OnSemant()
+	End Method
+	
+End Type
+
+'Const CLASS_INTERFACE:Int=1
+'Const CLASS_TEMPLATEARG:Int=2
+'Const CLASS_TEMPLATEINST:Int=4
+'Const CLASS_INSTANCED:Int=8		'class used in New?
+Const CLASS_INSTANCED:Int=1
+Const CLASS_EXTENDSOBJECT:Int=2
+Const CLASS_FINALIZED:Int=4
+
+Type TNullDecl Extends TClassDecl
+
+End Type
+
+Type TClassDecl Extends TScopeDecl
+
+	Field lastOffset:Int
+
+	Field args:TClassDecl[]
+	Field superTy:TIdentType
+	Field impltys:TIdentType[]
+
+	Field superClass:TClassDecl
+	
+	Field implments:TClassDecl[]			'interfaces immediately implemented
+	Field implmentsAll:TClassDecl[]		'all interfaces implemented
+	
+	Field instanceof:TClassDecl			'for instances
+	Field instances:TList		'for actual (non-arg, non-instance)
+	Field instArgs:TType[]
+
+	Field objectType:TObjectType '"canned" objectType
+
+	Global nullObjectClass:TClassDecl=New TNullDecl.Create( "{NULL}",Null,Null,Null,DECL_ABSTRACT|DECL_EXTERN )
+	
+	Method Create:TClassDecl( ident$,args:TClassDecl[],superTy:TIdentType,impls:TIdentType[],attrs:Int )
+		Self.ident=ident
+		Self.args=args
+		Self.superTy=superTy
+		Self.impltys=impls
+		Self.attrs=attrs
+		Self.objectType=New TObjectType.Create( Self )
+		If args
+			instances=New TList
+			instances.AddLast Self
+		EndIf
+		Return Self
+	End Method
+	
+	Method OnCopy:TDecl()
+		InternalErr
+	End Method
+	
+	Method ToString$()
+		Local t$
+		If args Then
+				For Local i:Int=0 Until args.Length
+				If i t:+","
+				t:+args[i].ToString()
+			Next
+		ElseIf instargs
+		End If
+		If t t="<"+t+">"
+		Return ident+t
+	End Method
+Rem	
+	Method GenClassInstance:TClassDecl( instArgs:TClassDecl[] )
+		If Not IsSemanted() InternalErr
+		
+		'no args
+		If Not instArgs
+			If Not args Return Self
+			If instanceof Return Self
+			For Local inst:TClassDecl=EachIn instances
+				If _env.ClassScope()=inst Return inst
+			Next
+		EndIf
+		
+		'If Not instanceof And Not instArgs Return Self
+		
+		'check number of args
+		If instanceof Or args.Length<>instArgs.Length
+			Err "Wrong number of class arguments for "+ToString()
+		EndIf
+		
+		'look for existing instance
+		For Local inst:TClassDecl=EachIn instances
+			Local equal:Int=True
+			For Local i:Int=0 Until args.Length
+				If inst.args[i]=instArgs[i] Continue
+				equal=False
+				Exit
+			Next
+			If equal Return inst
+		Next
+		
+		Local inst:TClassDecl=New TClassDecl
+
+		InitInstance inst
+
+		inst.scope=scope
+		inst.attrs:|CLASS_TEMPLATEINST
+		inst.args=instArgs
+		inst.superTy=superTy
+		inst.instanceof=Self
+		instances.AddLast inst
+		
+		For Local i:Int=0 Until args.Length
+			inst.InsertDecl New TAliasDecl.Create( args[i].ident,instArgs[i] )
+		Next
+		
+		For Local decl:TDecl=EachIn _decls
+			If TClassDecl( decl ) Continue
+			inst.InsertDecl decl.GenInstance()
+		Next
+
+		'inst.Semant
+		'A bit cheeky...
+		inst.OnSemant
+		inst.attrs:|DECL_SEMANTED
+		
+		Return inst
+	End Method
+End Rem
+
+	Method GenClassInstance:TClassDecl( instArgs:TType[] )
+
+		If instanceof InternalErr
+		
+		'no args
+		If Not instArgs
+			If Not args Return Self
+			For Local inst:TClassDecl=EachIn instances
+				If _env.ClassScope()=inst Return inst
+			Next
+		EndIf
+		
+		'check number of args
+		If args.Length<>instArgs.Length
+			Err "Wrong number of type arguments for class "+ToString()
+		EndIf
+		
+		'look for existing instance
+		For Local inst:TClassDecl=EachIn instances
+			Local equal:Int=True
+			For Local i:Int=0 Until args.Length
+				If Not inst.instArgs[i].EqualsType( instArgs[i] )
+					equal=False
+					Exit
+				EndIf
+			Next
+			If equal Return inst
+		Next
+		
+		Local inst:TClassDecl=New TClassDecl.Create( ident,Null,superTy,impltys, attrs )
+
+		inst.attrs:&~DECL_SEMANTED
+		inst.munged=munged
+		inst.errInfo=errInfo
+		inst.scope=scope
+		inst.instanceof=Self
+		inst.instArgs=instArgs
+		instances.AddLast inst
+		
+		For Local i:Int=0 Until args.Length
+			inst.InsertDecl New TAliasDecl.Create( args[i].ToString(),instArgs[i],0 )
+		Next
+		
+		For Local decl:TDecl=EachIn _decls
+			inst.InsertDecl decl.Copy()
+		Next
+
+		Return inst
+	End Method
+
+	Method IsInterface:Int()
+		Return (attrs & CLASS_INTERFACE)<>0
+	End Method
+
+	Method IsThrowable:Int()
+		Return (attrs & CLASS_THROWABLE)<>0
+	End Method
+
+	Method IsFinalized:Int()
+		Return (attrs & CLASS_FINALIZED)<>0
+	End Method
+
+	Method ExtendsObject:Int()
+		Return (attrs & CLASS_EXTENDSOBJECT)<>0
+	End Method
+	
+	Method IsInstanced:Int()
+		Return (attrs & CLASS_INSTANCED)<>0
+	End Method
+	
+	Method GetDecl:Object( ident$ )
+	
+		Local cdecl:TClassDecl=Self
+		While cdecl
+			Local decl:Object=cdecl.GetDecl2( ident )
+			If decl Return decl
+			
+			cdecl=cdecl.superClass
+		Wend
+
+	End Method
+	
+	'needs this 'coz you can't go blah.Super.GetDecl()...
+	Method GetDecl2:Object( ident$ )
+		Return Super.GetDecl( ident )
+	End Method
+	
+	Method FindFuncDecl:TFuncDecl( ident$,args:TExpr[] = Null ,explicit:Int=False )
+	
+		If args = Null Then
+			args = New TExpr[0]
+		End If
+	
+		If Not IsInterface()
+			' try getdecl first&
+			Local decl:TFuncDecl = TFuncDecl(GetDecl(ident))
+			If decl Then
+				Return decl
+			End If
+			Return FindFuncDecl2( ident,args,explicit )
+		EndIf
+		
+		Local fdecl:TFuncDecl=FindFuncDecl2( ident,args,True )
+		
+		For Local iface:TClassDecl=EachIn implmentsAll
+			Local decl:TFuncDecl=iface.FindFuncDecl2( ident,args,True )
+			If Not decl Continue
+			
+			If fdecl
+				If fdecl.EqualsFunc( decl ) Continue
+				Err "Unable to determine overload to use: "+fdecl.ToString()+" or "+decl.ToString()+"."
+			EndIf
+			fdecl=decl
+		Next
+		
+		If fdecl Or explicit Return fdecl
+		
+		fdecl=FindFuncDecl2( ident,args,False )
+		
+		For Local iface:TClassDecl=EachIn implmentsAll
+			Local decl:TFuncDecl=iface.FindFuncDecl2( ident,args,False )
+			If Not decl Continue
+			
+			If fdecl
+				If fdecl.EqualsFunc( decl ) Continue
+				Err "Unable to determine overload to use: "+fdecl.ToString()+" or "+decl.ToString()+"."
+			EndIf
+			fdecl=decl
+		Next
+		
+		Return fdecl
+	End Method
+	
+	Method FindFuncDecl2:TFuncDecl( ident$,args:TExpr[],explicit:Int )
+		Return Super.FindFuncDecl( ident,args,explicit )
+	End Method
+	
+	Method GetAllFuncDecls:TFuncDecl[](funcs:TFuncDecl[] = Null, includeSuper:Int = True)
+		If Not funcs Then
+			funcs = New TFuncDecl[0]
+		End If
+		
+		If superClass And includeSuper Then
+			funcs = superClass.GetAllFuncDecls(funcs)
+		End If
+		
+		
+		For Local func:TFuncDecl = EachIn _decls
+		
+			Local matched:Int = False
+			
+			For Local i:Int = 0 Until funcs.length
+				' found a match - we are overriding it
+				If func.ident.ToLower() = funcs[i].ident.ToLower() Then
+					matched = True
+					' set this to our own func
+					funcs[i] = func
+					Exit
+				End If
+			Next
+			
+			If Not matched Then
+				funcs :+ [func]
+			End If
+		
+		Next
+		
+		Return funcs
+	End Method
+	
+	Method ExtendsClass:Int( cdecl:TClassDecl )
+		If Self=nullObjectClass Return True
+		
+'		If cdecl.IsTemplateArg()
+'			cdecl=TType.objectType.FindClass()
+'		EndIf
+		
+		Local tdecl_:TClassDecl=Self
+		While tdecl_
+			If tdecl_=cdecl Return True
+			If cdecl.IsInterface()
+				For Local iface:TClassDecl=EachIn tdecl_.implmentsAll
+					If iface=cdecl Return True
+				Next
+			EndIf
+			tdecl_=tdecl_.superClass
+		Wend
+		
+		Return False
+	End Method
+	
+	Method OnSemant()
+
+		'Print "Semanting "+ToString()
+		
+		PushEnv Self
+
+		'If Not IsTemplateInst()
+		'	For Local i:Int=0 Until args.Length
+		'		InsertDecl args[i]
+		'		args[i].Semant
+		'	Next
+		'EndIf
+		
+		'Semant superclass		
+		If superTy
+			'superClass=superTy.FindClass()
+			superClass=superTy.SemantClass()
+			If superClass.IsInterface() Err superClass.ToString()+" is an interface, not a class."
+		EndIf
+		
+		'Semant implemented interfaces
+		Local impls:TClassDecl[]=New TClassDecl[impltys.Length]
+		Local implsall:TStack=New TStack
+		For Local i:Int=0 Until impltys.Length
+			Local cdecl:TClassDecl=impltys[i].SemantClass()
+			If Not cdecl.IsInterface()
+				Err cdecl.ToString()+" is a class, not an interface."
+			EndIf
+			For Local j:Int=0 Until i
+				If impls[j]=cdecl
+					Err "Duplicate interface "+cdecl.ToString()+"."
+				EndIf
+			Next
+			impls[i]=cdecl
+			implsall.Push cdecl
+			For Local tdecl_:TDecl=EachIn cdecl.implmentsAll
+				implsall.Push tdecl_
+			Next
+		Next
+		implmentsAll=New TClassDecl[implsall.Length()]
+		For Local i:Int=0 Until implsall.Length()
+			implmentsAll[i]=TClassDecl(implsall.Get(i))
+		Next
+		implments=impls
+
+		Rem
+		If IsInterface()
+			'add implemented methods to our methods
+			For Local iface:=EachIn implmentsAll
+				For Local decl:=EachIn iface.FuncDecls
+					InsertAlias decl.ident,decl
+				Next
+			Next
+		EndIf
+		EndRem
+				
+'		attrs|=DECL_SEMANTED
+		
+		PopEnv
+		
+		'If IsTemplateArg()
+		'	actual=TType.objectType.FindClass()
+		'	Return
+		'EndIf
+		
+		'If IsTemplateInst()
+		'	Return
+		'EndIf
+		
+		'Are we abstract?
+		If Not IsAbstract()
+			For Local decl:TDecl=EachIn _decls
+				Local fdecl:TFuncDecl=TFuncDecl( decl )
+				If fdecl And fdecl.IsAbstract()
+					attrs:|DECL_ABSTRACT
+					Exit
+				EndIf
+			Next
+		EndIf
+		
+		If Not lastOffset And superClass Then
+			lastOffset = superClass.LastOffset
+		End If
+
+		For Local decl:TFieldDecl=EachIn _decls
+			GetFieldOffset(decl)
+		Next
+
+		If Not IsExtern() And Not IsInterface()
+			Local fdecl:TFuncDecl
+			For Local decl:TFuncDecl=EachIn FuncDecls()
+				If Not decl.IsCtor() Continue
+				Local nargs:Int
+				For Local arg:TArgDecl=EachIn decl.argDecls
+					If Not arg.init nargs:+1
+				Next
+				If nargs Continue
+				fdecl=decl
+				Exit
+			Next
+			
+			For Local decl:TConstDecl = EachIn Decls()
+				decl.Semant()
+			Next
+			
+			For Local decl:TGlobalDecl = EachIn Decls()
+				decl.Semant()
+			Next
+			
+			' Don't need default new?
+			'If Not fdecl
+			'	fdecl=New TFuncDecl.CreateF( "new",New TObjectType.Create( Self ),Null,FUNC_CTOR )
+			'	fdecl.AddStmt New TReturnStmt.Create( Null )
+			'	InsertDecl fdecl
+			'EndIf
+		EndIf
+
+		'NOTE: do this AFTER super semant so UpdateAttrs order is cool.
+		If AppScope() Then
+			AppScope().semantedClasses.AddLast Self
+		End If
+	End Method
+	
+	'Ok, this dodgy looking beast 'resurrects' methods that may not currently be alive, but override methods that ARE.
+	Method UpdateLiveMethods:Int()
+	
+		If IsInterface() Return 0
+
+		If Not superClass Return 0
+
+		Local n:Int
+		For Local decl:TFuncDecl=EachIn MethodDecls()
+			If decl.IsSemanted() Continue
+			
+			Local live:Int
+			Local unsem:TList=New TList'<TFuncDecl>
+			
+			unsem.AddLast decl
+			
+			Local sclass:TClassDecl=superClass
+			While sclass
+				For Local decl2:TFuncDecl=EachIn sclass.MethodDecls( decl.ident )
+					If decl2.IsSemanted()
+						live=True
+					Else
+						unsem.AddLast decl2
+						If decl2.IsExtern() live=True
+						If decl2.actual.IsSemanted() live=True
+					EndIf
+				Next
+				sclass=sclass.superClass
+			Wend
+			
+			If Not live
+				Local cdecl:TClassDecl=Self
+				While cdecl
+					For Local iface:TClassDecl=EachIn cdecl.implmentsAll
+						For Local decl2:TFuncDecl=EachIn iface.MethodDecls( decl.ident )
+							If decl2.IsSemanted()
+								live=True
+							Else
+								unsem.AddLast decl2
+								If decl2.IsExtern() live=True
+								If decl2.actual.IsSemanted() live=True
+							EndIf
+						Next
+					Next
+					cdecl=cdecl.superClass
+				Wend
+			EndIf
+			
+			If Not live Continue
+			
+			For Local decl:TDecl=EachIn unsem
+				decl.Semant
+				n:+1
+			Next
+		Next
+		
+		Return n
+	End Method
+	
+	Method FinalizeClass()
+
+		PushErr errInfo
+		
+		If Not IsInterface()
+			'
+			'check for duplicate fields!
+			'
+			For Local decl:TDecl=EachIn Semanted()
+				Local fdecl:TFieldDecl=TFieldDecl( decl )
+				If Not fdecl Continue
+				Local cdecl:TClassDecl=superClass
+				While cdecl
+					For Local decl:TDecl=EachIn cdecl.Semanted()
+						If decl.ident=fdecl.ident Err "Field '"+fdecl.ident+"' in class "+ToString()+" overrides existing declaration in class "+cdecl.ToString()
+					Next
+					cdecl=cdecl.superClass
+				Wend
+			Next
+			'
+			'Check we implement all abstract methods!
+			'
+			If IsInstanced()
+				Local cdecl:TClassDecl=Self
+				Local impls:TList=New TList'<TFuncDecl>
+				While cdecl
+					For Local decl:TFuncDecl=EachIn cdecl.SemantedMethods()
+						If decl.IsAbstract()
+							Local found:Int
+							For Local decl2:TFuncDecl=EachIn impls
+								If decl.EqualsFunc( decl2 )
+									found=True
+									Exit
+								EndIf
+							Next
+							If Not found
+								Err "Can't create instance of class "+ToString()+" due to abstract method "+decl.ToString()+"."
+							EndIf
+						Else
+							impls.AddLast decl
+						EndIf
+					Next
+					cdecl=cdecl.superClass
+				Wend
+			EndIf
+			'
+			'Check we implement all interface methods!
+			'
+			For Local iface:TClassDecl=EachIn implmentsAll
+				For Local decl:TFuncDecl=EachIn iface.SemantedMethods()
+					Local found:Int
+					For Local decl2:TFuncDecl=EachIn SemantedMethods( decl.ident )
+						If decl.EqualsFunc( decl2 )
+							If decl2.munged
+								Err "Extern methods cannot be used to implement interface methods."
+							EndIf
+							found=True
+						EndIf
+					Next
+					If Not found
+						Err decl.ToString()+" must be implemented by class "+ToString()
+					EndIf
+				Next
+			Next
+		EndIf
+		
+		PopErr
+		
+	End Method
+	
+	Method GetFieldOffset(decl:TFieldDecl)
+		
+		Local ty:TType = decl.declTy
+		
+		Local modifier:Int = POINTER_SIZE
+		
+		If TIntType(ty) Or TFloatType(ty) Then
+			modifier = 4
+		Else If TShortType(ty) Then
+			modifier = 2
+		Else If TLongType(ty) Or TDoubleType(ty) Then
+			modifier = 8
+		Else If TByteType(ty) Then
+			modifier = 1
+		End If
+
+		If modifier > 1 And lastOffset Mod modifier Then
+			lastOffset :+ modifier - (lastOffset Mod modifier)
+		End If
+		
+		decl.offset = lastOffset
+		
+		lastOffset :+ modifier
+	End Method
+	
+End Type
+
+Const MODULE_STRICT:Int=1
+Const MODULE_SUPERSTRICT:Int=2
+Const MODULE_ACTUALMOD:Int=4
+
+Type TModuleDecl Extends TScopeDecl
+
+	Field filepath$
+	Field relpath$
+	Field imported:TMap=New TMap'<TModuleDecl>		'Maps filepath to modules
+	Field pubImported:TMap=New TMap'<TModuleDecl>	'Ditto for publicly imported modules
+	
+	' cache of ModuleInfo lines
+	Field modInfo:TList = New TList
+
+	Method ToString$()
+		Return "Module "+munged
+	End Method
+	
+	Method Create:TModuleDecl( ident$,munged$,filepath$,attrs:Int )
+		Self.ident=ident
+		Self.munged=munged
+		Self.filepath=filepath
+		Self.attrs=attrs
+		Return Self
+	End Method
+	
+	Method IsStrict:Int()
+		Return (attrs & MODULE_STRICT)<>0
+	End Method
+
+	Method IsSuperStrict:Int()
+		Return (attrs & MODULE_SUPERSTRICT)<>0
+	End Method
+	
+	Method IsActualModule:Int()
+		Return (attrs & MODULE_ACTUALMOD)<>0
+	End Method
+	
+	Method GetDecl:Object( ident$ )
+'DebugLog "GetDecl (" + ident + ") : " + filepath
+		Local todo:TList=New TList'<TModuleDecl>
+		Local done:TMap=New TMap'<TModuleDecl>
+		
+		todo.AddLast Self
+		done.Insert filepath,Self
+		
+		Local decl:Object,declmod$
+		
+		While Not todo.IsEmpty()
+	
+			Local mdecl:TModuleDecl=TModuleDecl(todo.RemoveLast())
+			Local tdecl_:Object=mdecl.GetDecl2( ident )
+			
+			If tdecl_ And tdecl_<>decl
+				If mdecl=Self Return tdecl_
+				If decl
+					Err "Duplicate identifier '"+ident+"' found in module '"+declmod+"' and module '"+mdecl.ident+"'."
+				EndIf
+				decl=tdecl_
+				declmod=mdecl.ident
+			EndIf
+			
+			'If Not _env Exit
+			
+			Local imps:TMap=mdecl.imported
+			'If mdecl<>_env.ModuleScope() imps=mdecl.pubImported
+
+			For Local mdecl2:TModuleDecl=EachIn imps.Values()
+				If Not done.Contains( mdecl2.filepath )
+					todo.AddLast mdecl2
+					done.Insert mdecl2.filepath,mdecl2
+				EndIf
+				
+				If ident = mdecl2.ident
+					Return mdecl2
+				End If
+			Next
+
+		Wend
+		
+		Return decl
+	End Method
+	
+	Method GetDecl2:Object( ident$ )
+		Return Super.GetDecl( ident )
+	End Method
+
+	Method OnSemant()
+		For Local gdecl:TGlobalDecl=EachIn _decls
+			gdecl.Semant
+		Next
+
+		For Local cdecl:TClassDecl=EachIn _decls
+			cdecl.Semant
+		Next
+
+		For Local fdecl:TFuncDecl=EachIn _decls
+			fdecl.Semant
+		Next
+
+		For Local cdecl:TConstDecl=EachIn _decls
+			cdecl.Semant
+		Next
+	End Method
+
+End Type
+
+Type TAppDecl Extends TScopeDecl
+
+	Field imported:TMap=New TMap'<TModuleDecl>			'maps modpath->mdecl
+	
+	Field mainModule:TModuleDecl
+	Field mainFunc:TFuncDecl	
+		
+	Field semantedClasses:TList=New TList'<TClassDecl>			'in-order (ie: base before derived) list of _semanted classes
+	Field semantedGlobals:TList=New TList'<TGlobalDecl>			'in-order (ie: dependancy sorted) list of _semanted globals
+
+	Field fileImports:TList=New TList'StringList
+	
+	Field stringConsts:TMap = New TMap
+	Field stringConstCount:Int
+	
+	Method GetPathPrefix:String()
+		If opt_buildtype = BUILDTYPE_MODULE Then
+			Local prefix:String
+			Local path:String[] = mainModule.filepath.split("/")
+			Local c:Int = 0
+			For Local dir:String = EachIn path
+				If c Then
+					prefix :+ dir.Replace(".mod", "") + "_"
+					c:- 1
+				End If
+				If dir = "mod" Then
+					c = 2
+				End If
+			Next
+		Else
+			Return "bb_"
+		End If
+	End Method
+	
+	Method InsertModule( mdecl:TModuleDecl )
+		mdecl.scope=Self
+		imported.Insert mdecl.filepath,mdecl
+		If Not mainModule
+			mainModule=mdecl
+		EndIf
+	End Method
+	
+	Method GetDecl:Object( ident$ )
+		Local obj:Object = Super.GetDecl(ident)
+		If Not obj Then
+			Return mainModule.GetDecl(ident)
+		End If
+		Return obj
+	End Method
+
+	Method OnSemant()
+'DebugStop		
+		_env=Null
+pushenv Self
+		mainModule.Semant
+
+		mainFunc=mainModule.FindFuncDecl( "LocalMain" )
+		
+		
+		' FIXME
+		If Not mainFunc Err "Function 'Main' not found."
+		
+		'If Not TIntType( mainFunc.retType ) Or mainFunc.argDecls.Length
+		'	Err "Main function must be of type Main:Int()"
+		'EndIf
+
+		Repeat
+			Local more:Int
+			For Local cdecl:TClassDecl=EachIn semantedClasses
+				more:+cdecl.UpdateLiveMethods()
+			Next
+			If Not more Exit
+		Forever
+		
+		For Local cdecl:TClassDecl=EachIn semantedClasses
+			cdecl.FinalizeClass
+		Next
+	End Method
+	
+	Method mapStringConsts(value:String)
+		Local s:String = String(stringConsts.ValueForKey(value))
+		
+		If Not s Then
+			s = "_s" + stringConstCount
+
+			stringConsts.Insert(value, s)
+
+			stringConstCount:+ 1
+		End If
+	End Method
+	
+End Type

+ 1160 - 0
expr.bmx

@@ -0,0 +1,1160 @@
+
+
+Type TExpr
+	Field exprType:TType
+	
+	Method ToString$()
+		Return "<TExpr>"
+	End Method
+	
+	Method Copy:TExpr()
+		InternalErr
+	End Method
+	
+	Method Semant:TExpr()
+		InternalErr
+	End Method
+	
+	Method SemantSet:TExpr( op$,rhs:TExpr )
+		Err ToString()+" cannot be assigned to."
+	End Method
+	
+	Method SemantFunc:TExpr( args:TExpr[] )
+		Err ToString()+" cannot be invoked."
+	End Method
+	
+	Method SemantScope:TScopeDecl()
+		Return Null
+	End Method
+
+	Method Eval$()
+		Err ToString()+" cannot be statically evaluated."
+	End Method
+	
+	Method EvalConst:TExpr()
+		Return New TConstExpr.Create( exprType,Eval() ).Semant()
+	End Method
+	
+	Method Trans$()
+		Todo
+	End Method
+	
+	Method TransStmt$()
+		Return Trans()
+	End Method
+	
+	Method TransVar$()
+		InternalErr
+	End Method
+	
+	'semant and cast
+	Method SemantAndCast:TExpr( ty:TType,castFlags:Int=0 )
+'DebugStop
+		Local expr:TExpr=Semant()
+		If expr.exprType.EqualsType( ty ) Return expr
+		Return New TCastExpr.Create( ty,expr,castFlags ).Semant()
+	End Method
+
+	'expr and ty already semanted!
+	Method Cast:TExpr( ty:TType,castFlags:Int=0 )
+		If Not exprType Then
+			Semant()
+		End If
+		If exprType.EqualsType( ty ) Return Self
+		Return New TCastExpr.Create( ty,Self,castFlags ).Semant()
+	End Method
+	
+	Method SemantArgs:TExpr[]( args:TExpr[] )
+		args=args[..]
+		For Local i:Int=0 Until args.Length
+			If args[i] args[i]=args[i].Semant()
+		Next
+		Return args
+	End Method
+	
+	Method CastArgs:TExpr[]( args:TExpr[],funcDecl:TFuncDecl )
+		If args.Length>funcDecl.argDecls.Length InternalErr
+
+		' FIXME
+		'args=args.Resize( funcDecl.argDecls.Length )
+		' FIXME
+		
+		For Local i:Int=0 Until args.Length
+			If args[i]
+				If Not funcDecl.argDecls[i].IsSemanted() Then
+					funcDecl.argDecls[i].Semant()
+				End If
+				args[i]=args[i].Cast( funcDecl.argDecls[i].ty )
+			Else If funcDecl.argDecls[i].init
+				args[i]=funcDecl.argDecls[i].init	
+			Else
+				Err "Missing function argument '"+funcDecl.argDecls[i].ident+"'."
+			EndIf
+		Next
+		Return args
+	End Method
+	
+	Method BalanceTypes:TType( lhs:TType,rhs:TType )
+		If TStringType( lhs ) Or TStringType( rhs ) Return TType.stringType
+		If TFloatType( lhs ) Or TFloatType( rhs ) Return TType.floatType
+		If TIntType( lhs ) Or TIntType( rhs ) Return TType.intType
+		If lhs.ExtendsType( rhs ) Return rhs
+		If rhs.ExtendsType( lhs ) Return lhs
+		Err "Can't balance types "+lhs.ToString()+" and "+rhs.ToString()+"."
+	End Method
+	
+	Method CopyExpr:TExpr( expr:TExpr )
+		If Not expr Return Null
+		Return expr.Copy()
+	End Method
+	
+	Method CopyArgs:TExpr[]( exprs:TExpr[] )
+		exprs=exprs[..]
+		For Local i:Int=0 Until exprs.Length
+			exprs[i]=CopyExpr( exprs[i] )
+		Next
+		Return exprs
+	End Method
+
+End Type
+
+'	exec a stmt, return an expr
+Type TStmtExpr Extends TExpr
+	Field stmt:TStmt
+	Field expr:TExpr
+	
+	Method Create:TStmtExpr( stmt:TStmt,expr:TExpr )
+		Self.stmt=stmt
+		Self.expr=expr
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TStmtExpr.Create( stmt,CopyExpr(expr) )
+	End Method
+	
+	Method ToString$()
+		Return "TStmtExpr(,"+expr.ToString()+")"
+	End Method
+		
+	Method Semant:TExpr()
+		If exprType Return Self
+		
+		stmt.Semant()
+		expr=expr.Semant()
+		exprType=expr.exprType
+		Return Self
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransStmtExpr( Self )
+	End Method
+
+End Type
+
+'	literal
+Type TConstExpr Extends TExpr
+	Field ty:TType
+	Field value$
+	
+	Method Create:TConstExpr( ty:TType,value$ )
+		If TIntType( ty )
+			Local radix:Int
+			If value.StartsWith( "%" )
+				radix=1
+			Else If value.StartsWith( "$" )
+				radix=4
+			EndIf
+			If radix
+				Local val:Int=0
+				For Local i:Int=1 Until value.Length
+					Local ch:Int=value[i]
+					If ch>=48 And ch<58
+						val=val Shl radix | (ch & 15)
+					Else
+						val=val Shl radix | ((ch & 15)+9)
+					EndIf
+				Next
+				value=String( val )
+			EndIf
+		Else If TFloatType( ty )
+			If Not (value.Contains("e") Or value.Contains("E") Or value.Contains("."))
+				value:+".0"
+			EndIf
+		EndIf
+		Self.ty=ty
+		Self.value=value
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TConstExpr.Create( ty,value )
+	End Method
+	
+	Method ToString$()
+		Return "TConstExpr(~q"+value+"~q)"
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+		
+		exprType=ty.Semant()
+		Return Self
+	End Method
+	
+	Method Eval$()
+		Return value
+	End Method
+	
+	Method EvalConst:TExpr()
+		Return Self
+	End Method
+	
+	Method Trans$()
+		Semant
+		Return _trans.TransConstExpr( Self )
+	End Method
+
+End Type
+
+Type TVarExpr Extends TExpr
+	Field decl:TVarDecl
+	
+	Method Create:TVarExpr( decl:TVarDecl )
+		Self.decl=decl
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return Self
+	End Method
+	
+	Method ToString$()
+		Return "TVarExpr("+decl.ToString()+")"
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+		If Not decl.IsSemanted() InternalErr
+		exprType=decl.ty
+		Return Self
+	End Method
+	
+	Method SemantSet:TExpr( op$,rhs:TExpr )
+		Return Semant()
+	End Method
+	
+	Method Trans$()
+		Semant
+		Return _trans.TransTemplateCast( exprType,TVarDecl(decl.actual).ty,_trans.TransVarExpr( Self ) )
+	End Method
+	
+	Method TransVar$()
+		Semant
+		Return _trans.TransVarExpr( Self )
+	End Method
+	
+End Type
+
+Type TMemberVarExpr Extends TExpr
+	Field expr:TExpr
+	Field decl:TVarDecl
+	
+	Method Create:TMemberVarExpr( expr:TExpr,decl:TVarDecl )
+		Self.expr=expr
+		Self.decl=decl
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return Self
+	End Method
+	
+	Method ToString$()
+		Return "TMemberVarExpr("+expr.ToString()+","+decl.ToString()+")"
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+		If Not decl.IsSemanted() InternalErr
+		exprType=decl.ty
+		Return Self
+	End Method
+	
+	Method SemantSet:TExpr( op$,rhs:TExpr )
+		Return Semant()
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransTemplateCast( exprType,TVarDecl(decl.actual).ty,_trans.TransMemberVarExpr( Self ) )
+	End Method
+	
+	Method TransVar$()
+		Return _trans.TransMemberVarExpr( Self )
+ 	End Method
+
+End Type
+
+Type TInvokeExpr Extends TExpr
+	Field decl:TFuncDecl
+	Field args:TExpr[]
+
+	Method Create:TInvokeExpr( decl:TFuncDecl,args:TExpr[]=Null )
+		Self.decl=decl
+		If args Then
+			Self.args=args
+		Else
+			Self.args = New TExpr[0]
+		End If
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return Self
+	End Method
+	
+	Method ToString$()
+		Local t$="TInvokeExpr("+decl.ToString()
+		For Local arg:TExpr=EachIn args
+			t:+","+arg.ToString()
+		Next
+		Return t+")"
+	End Method
+	
+	Method Semant:TExpr()
+'If decl.ident = "Create"
+'DebugStop
+'End If
+		If exprType Return Self
+		If Not decl.retType
+			decl.Semant()
+		End If
+		If TIdentType(decl.retType) Then
+			exprType = decl.retType.Semant()
+		Else
+			exprType=decl.retType
+		End If
+		
+		args=CastArgs( args,decl )
+		Return Self
+	End Method
+	
+	Method Trans$()
+'		Return _trans.TransTemplateCast( exprType,TFuncDecl(decl.actual).retType,_trans.TransInvokeExpr( Self ) )
+		Return _trans.TransInvokeExpr( Self )
+	End Method
+	
+	Method TransStmt$()
+		Return _trans.TransInvokeExpr( Self )
+	End Method
+
+	Method Eval$()
+		Select decl.ident.ToLower()
+			Case "asc"
+				If args.length = 1 Then
+					Local v:String = String(args[0].Eval())
+					If v And v.length = 1 Then
+						Return Asc(v)
+					End If
+				End If
+				DebugStop
+			Case "chr"
+				DebugStop
+		Default
+			Return Super.Eval()
+		End Select
+	End Method
+
+End Type
+
+Type TInvokeMemberExpr Extends TExpr
+	Field expr:TExpr
+	Field decl:TFuncDecl
+	Field args:TExpr[]
+	Field isResize:Int	'FIXME - butt ugly!
+	
+	Method Create:TInvokeMemberExpr( expr:TExpr,decl:TFuncDecl,args:TExpr[]=Null )
+		Self.expr=expr
+		Self.decl=decl
+		If args
+			Self.args=args
+		Else
+			Self.args = New TExpr[0]
+		End If
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return Self
+	End Method
+	
+	Method ToString$()
+		Local t$="TInvokeMemberExpr("+expr.ToString()+","+decl.ToString()
+		For Local arg:TExpr=EachIn args
+			t:+","+arg.ToString()
+		Next
+		Return t+")"
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+		
+		If Not decl.IsSemanted() decl.Semant()
+		exprType=decl.retType
+		args=CastArgs( args,decl )
+
+		'Array $resize hack!
+		If TArrayType( exprType ) And TVoidType( TArrayType( exprType ).elemType )
+			isResize=True
+			exprType=expr.exprType
+		EndIf
+		
+		Return Self
+	End Method
+	
+	Method Trans$()
+		'Array $resize hack!
+		If isResize Return _trans.TransInvokeMemberExpr( Self )
+		
+		Return _trans.TransTemplateCast( exprType,TFuncDecl(decl.actual).retType,_trans.TransInvokeMemberExpr( Self ) )
+	End Method
+	
+	Method TransStmt$()
+		Return _trans.TransInvokeMemberExpr( Self )
+	End Method
+	
+End Type
+
+Type TNewObjectExpr Extends TExpr
+	Field ty:TType
+	Field args:TExpr[]
+	Field ctor:TFuncDecl	
+	Field classDecl:TClassDecl
+	
+	Method Create:TNewObjectExpr( ty:TType,args:TExpr[] )
+		Self.ty=ty
+		Self.args=args
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TNewObjectExpr.Create( ty,CopyArgs(args) )
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+		
+		ty=ty.Semant()
+		args=SemantArgs( args )
+		
+		Local objTy:TObjectType=TObjectType( ty )
+		If Not objTy
+			Err "Expression is not a class."
+		EndIf
+
+		classDecl=objTy.classDecl
+		
+		If classDecl.IsInterface() Err "Cannot create instance of an interface."
+		If classDecl.IsAbstract() Err "Cannot create instance of an abstract class."
+		'If classDecl.IsTemplateArg() Err "Cannot create instance of a generic argument."
+		If classDecl.args And Not classDecl.instanceof Err "Cannot create instance of a generic class."
+
+		If classDecl.IsExtern()
+			If args Err "No suitable constructor found for class "+classDecl.ToString()+"."
+		Else
+'DebugStop
+			ctor=classDecl.FindFuncDecl( "new",args )
+			If Not ctor	Err "No suitable constructor found for class "+classDecl.ToString()+"."
+			args=CastArgs( args,ctor )
+		EndIf
+		
+		classDecl.attrs:|CLASS_INSTANCED
+
+		exprType=ty
+		Return Self
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransNewObjectExpr( Self )
+	End Method
+End Type
+
+Type TNewArrayExpr Extends TExpr
+	Field ty:TType
+	Field expr:TExpr
+	
+	Method Create:TNewArrayExpr( ty:TType,expr:TExpr )
+		Self.ty=ty
+		Self.expr=expr
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		If exprType InternalErr
+		Return New TNewArrayExpr.Create( ty,CopyExpr(expr) )
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+		
+		ty=ty.Semant()
+		exprType=New TArrayType.Create( ty )
+		expr=expr.SemantAndCast( TType.intType )
+		Return Self
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransNewArrayExpr( Self )
+	End Method
+
+End Type
+
+'	super.ident( args )
+Type TInvokeSuperExpr Extends TExpr
+	Field ident$
+	Field args:TExpr[]
+	Field funcDecl:TFuncDecl
+	Field classScope:TClassDecl
+	Field superClass:TClassDecl
+
+	Method Create:TInvokeSuperExpr( ident$,args:TExpr[] = Null )
+		Self.ident=ident
+		If args Then
+			Self.args=args
+		Else
+			Self.args = New TExpr[0]
+		End If
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TInvokeSuperExpr.Create( ident,CopyArgs(args) )
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+	
+		If _env.FuncScope().IsStatic() Err "Illegal use of Super."
+		
+		classScope=_env.ClassScope()
+		superClass=classScope.superClass
+
+		If Not superClass Err "Type has no super class."
+
+		args=SemantArgs( args )
+		funcDecl=superClass.FindFuncDecl( ident,args )
+		If Not funcDecl Err "Can't find superclass method '"+ident+"'."
+		args=CastArgs( args,funcDecl )
+		exprType=funcDecl.retType
+		Return Self
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransInvokeSuperExpr( Self )
+	End Method
+
+End Type
+
+'	Self
+Type TSelfExpr Extends TExpr
+
+	Method Copy:TExpr()
+		Return New TSelfExpr
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+	
+		If _env.FuncScope().IsStatic() Err "Illegal use of Self within static scope."
+		exprType=New TObjectType.Create( _env.ClassScope() )
+		Return Self
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransSelfExpr( Self )
+	End Method
+
+End Type
+
+Const CAST_EXPLICIT:Int=1
+
+Type TCastExpr Extends TExpr
+	Field ty:TType
+	Field expr:TExpr
+	Field flags:Int
+	
+	Method Create:TCastExpr( ty:TType,expr:TExpr,flags:Int=0 )
+		Self.ty=ty
+		Self.expr=expr
+		Self.flags=flags
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TCastExpr.Create( ty,CopyExpr(expr),flags )
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+'DebugStop		
+		ty=ty.Semant()
+		expr=expr.Semant()
+		
+		Local src:TType=expr.exprType
+
+		'equal?
+		If src.EqualsType( ty ) Return expr
+		
+		'upcast?
+		If src.ExtendsType( ty )
+	
+			'cast from void[] to T[]
+			If TArrayType(src) And TVoidType( TArrayType(src).elemType )
+				Return New TConstExpr.Create( ty,"" ).Semant()
+			EndIf
+		
+			'Box/unbox?...
+			'If TObjectType( ty ) And Not TObjectType( src )
+
+				'Box!
+			'	expr=New TNewObjectExpr.Create( ty,[expr] ).Semant()
+				
+			'Else 
+			If TObjectType( src ) And Not TObjectType( ty ) And Not TStringType( ty )
+
+				'Unbox!
+				Local op$
+				'If TBoolType( ty )
+				'	op="ToBool"
+				'Else
+				If TIntType( ty ) 
+					op="ToInt"
+				Else If TFloatType( ty )
+					op="ToFloat"
+				Else If TStringType( ty )
+					op="ToString"
+				Else
+					InternalErr
+				EndIf
+				Local fdecl:TFuncDecl=src.GetClass().FindFuncDecl( op )
+				expr=New TInvokeMemberExpr.Create( expr,fdecl ).Semant()
+
+			EndIf
+			exprType=ty
+
+		Else If TBoolType( ty )
+		
+			'If VoidType( src )				
+			'	Err "Cannot convert from Void to Bool."
+			'EndIf
+
+			If  flags & CAST_EXPLICIT 
+				exprType=ty
+			EndIf
+
+		Else If ty.ExtendsType( src )
+		
+			If flags & CAST_EXPLICIT
+'DebugStop			
+				'if both objects or both non-objects...
+				If (TObjectType(ty)<>Null)=(TObjectType(src)<>Null) exprType=ty
+
+			EndIf
+		
+		EndIf
+
+'		If TArrayType(src) And TPointerType(ty) Then
+'			exprType = ty
+'			Return expr
+'		End If
+		
+		If TIntType(ty) And TPointerType(src) Then
+			exprType = ty
+			Return expr
+		End If
+
+'		If TPointerType(ty) And TIntType(src) Then
+'			exprType = ty
+'			Return expr
+'		End If
+		
+		If TIntType(ty) And TObjectType(src) Then
+' DebugStop ' Bah woz ere
+			exprType = ty
+			Return expr
+		End If
+		
+		If TObjectType(src) And TNullDecl(TObjectType(src).classDecl) Then
+			exprType = ty
+			Return expr
+		End If
+		
+		If TPointerType(ty) Then
+'DebugStop
+			If TNumericType(src) Then
+				If TType.pointerType = ty Then
+					exprType = TNumericType(src).ToPointer()
+				Else
+					exprType = ty
+				End If
+				Return Self
+			Else
+				If TArrayType(src) Then
+					If TNumericType(TArrayType(src).elemType) Then
+						exprType = TNumericType(TArrayType(src).elemType).ToPointer()
+						Return Self
+					End If
+				End If
+			End If
+		End If
+		
+		If Not exprType
+			Err "Cannot convert from "+src.ToString()+" to "+ty.ToString()+"."
+		EndIf
+		
+		If TConstExpr( expr ) Return EvalConst()
+		Return Self
+	End Method
+	
+	Method Eval$()
+		Local val$=expr.Eval()
+		If Not val Return val
+		If TBoolType( exprType )
+			If TIntType( expr.exprType )
+				If Int( val ) Return "1"
+				Return ""
+			Else If TFloatType( expr.exprType )
+				If Float( val ) Return "1"
+				Return ""
+			Else If TStringType( expr.exprType )
+				If val.Length Return "1"
+				Return ""
+			EndIf
+		Else If TIntType( exprType )
+			If TBoolType( expr.exprType )
+				If val Return "1"
+				Return "0"
+			EndIf
+			Return Int( val )
+		Else If TShortType( exprType )
+			Return Short( val )
+		Else If TFloatType( exprType )
+			Return Float( val )
+		Else If TDoubleType( exprType )
+			Return Double( val )
+		Else If TLongType( exprType )
+			Return Long( val )
+		Else If TStringType( exprType )
+			Return String( val )
+		Else If TByteType( exprType )
+			Return Byte( val )
+		EndIf
+		Return Super.Eval()
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransCastExpr( Self )
+	End Method
+
+End Type
+
+'op = '+', '-', '~' 
+Type TUnaryExpr Extends TExpr
+	Field op$,expr:TExpr
+	
+	Method Create:TUnaryExpr( op$,expr:TExpr )
+		Self.op=op
+		Self.expr=expr
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TUnaryExpr.Create( op,CopyExpr(expr) )
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+		
+		Select op
+		Case "+","-"
+			expr=expr.Semant()
+			If Not TNumericType( expr.exprType ) Err expr.ToString()+" must be numeric for use with unary operator '"+op+"'"
+			exprType=expr.exprType
+		Case "~~"
+			expr=expr.SemantAndCast( TType.intType )
+			exprType=TType.intType
+		Case "not"
+			expr=expr.SemantAndCast( TType.boolType,CAST_EXPLICIT )
+			exprType=TType.boolType
+		Default
+			InternalErr
+		End Select
+		
+		If TConstExpr( expr ) Return EvalConst()
+		Return Self
+	End Method
+	
+	Method Eval$()
+		Local val$=expr.Eval()
+		Select op
+		Case "~~"
+			Return ~Int( val )
+		Case "+"
+			Return val
+		Case "-"
+			If val.StartsWith( "-" ) Return val[1..]
+			Return "-"+val
+		Case "not"
+			If val Return ""
+			Return "1"
+		End Select
+		InternalErr
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransUnaryExpr( Self )
+	End Method
+
+End Type
+
+Type TBinaryExpr Extends TExpr
+	Field op$
+	Field lhs:TExpr
+	Field rhs:TExpr
+	
+	Method Trans$()
+		Return _trans.TransBinaryExpr( Self )
+	End Method
+
+End Type
+
+' * / + / & ~ | ^ shl shr
+Type TBinaryMathExpr Extends TBinaryExpr
+
+	Method Create:TBinaryMathExpr( op$,lhs:TExpr,rhs:TExpr )
+		Self.op=op
+		Self.lhs=lhs
+		Self.rhs=rhs
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TBinaryMathExpr.Create( op,CopyExpr(lhs),CopyExpr(rhs) )
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+	
+		lhs=lhs.Semant()
+		rhs=rhs.Semant()
+		
+		Select op
+		Case "&","~~","|","mod","shl","shr"
+			exprType=TType.intType
+		Default
+			exprType=BalanceTypes( lhs.exprType,rhs.exprType )
+			If TStringType( exprType )
+				If op<>"+" 
+					Err "Illegal string operator."
+				EndIf
+			Else If Not TNumericType( exprType )
+				Err "Illegal expression type."
+			EndIf
+		End Select
+		
+		lhs=lhs.Cast( exprType )
+		rhs=rhs.Cast( exprType )
+		
+		If TConstExpr( lhs ) And TConstExpr( rhs ) Return EvalConst()
+
+		Return Self
+	End Method
+	
+	Method Eval$()
+		Local lhs$=Self.lhs.Eval()
+		Local rhs$=Self.rhs.Eval()
+		If TIntType( exprType )
+			Local x:Int=Int(lhs),y:Int=Int(rhs)
+			Select op
+			Case "*" Return x*y
+			Case "/" Return x/y
+			Case "mod" Return x Mod y
+			Case "shl" Return x Shl y
+			Case "shr" Return x Shr y
+			Case "+" Return x + y
+			Case "-" Return x - y
+			Case "&" Return x & y
+			Case "~~" Return x ~ y
+			Case "|" Return x | y
+			End Select
+		Else If TFloatType( exprType )
+			Local x#=Float(lhs),y#=Float(rhs)
+			Select op
+			Case "*" Return x * y
+			Case "/" Return x / y
+			Case "+" Return x + y
+			Case "-" Return x - y
+			End Select
+		Else If TStringType( exprType )
+			Select op
+			Case "+" Return lhs+rhs
+			End Select
+		EndIf
+		InternalErr
+	End Method
+	
+End Type
+
+'=,<>,<,<=,>,>=
+Type TBinaryCompareExpr Extends TBinaryExpr
+	Field ty:TType
+
+	Method Create:TBinaryCompareExpr( op$,lhs:TExpr,rhs:TExpr )
+		Self.op=op
+		Self.lhs=lhs
+		Self.rhs=rhs
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TBinaryCompareExpr.Create( op,CopyExpr(lhs),CopyExpr(rhs) )
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+		
+		lhs=lhs.Semant()
+		rhs=rhs.Semant()
+
+		ty=BalanceTypes( lhs.exprType,rhs.exprType )
+		If TArrayType( ty )
+			Err "Arrays cannot be compared."
+		EndIf
+
+		lhs=lhs.Cast( ty )
+		rhs=rhs.Cast( ty )
+
+		exprType=TType.boolType
+		
+		If TConstExpr( lhs ) And TConstExpr( rhs ) Return EvalConst()
+		
+		Return Self
+	End Method
+	
+	Method Eval$()
+		Local r:Int=-1
+		If TBoolType( ty )
+			Local lhs:Int=Int(Self.lhs.Eval())
+			Local rhs:Int=Int(Self.rhs.Eval())
+			Select op
+			Case "="  r=(lhs= rhs)
+			Case "<>" r=(lhs<>rhs)
+			End Select
+		Else If TIntType( ty )
+			Local lhs:Int=Int( Self.lhs.Eval() )
+			Local rhs:Int=Int( Self.rhs.Eval() )
+			Select op
+			Case "="  r=(lhs= rhs)
+			Case "<>" r=(lhs<>rhs)
+			Case "<"  r=(lhs< rhs)
+			Case "<=" r=(lhs<=rhs)
+			Case ">"  r=(lhs> rhs)
+			Case ">=" r=(lhs>=rhs)
+			End Select
+		Else If TFloatType( ty )
+			Local lhs:Float=Float( Self.lhs.Eval() )
+			Local rhs:Float=Float( Self.rhs.Eval() )
+			Select op
+			Case "="  r=(lhs= rhs)
+			Case "<>" r=(lhs<>rhs)
+			Case "<"  r=(lhs< rhs)
+			Case "<=" r=(lhs<=rhs)
+			Case ">"  r=(lhs> rhs)
+			Case ">=" r=(lhs>=rhs)
+			End Select
+		Else If TStringType( ty )
+			Local lhs:String=String( Self.lhs.Eval() )
+			Local rhs:String=String( Self.rhs.Eval() )
+			Select op
+			Case "="  r=(lhs= rhs)
+			Case "<>" r=(lhs<>rhs)
+			Case "<"  r=(lhs< rhs)
+			Case "<=" r=(lhs<=rhs)
+			Case ">"  r=(lhs> rhs)
+			Case ">=" r=(lhs>=rhs)
+			End Select
+		EndIf
+		If r=1 Return "1"
+		If r=0 Return ""
+		InternalErr
+	End Method
+End Type
+
+'and, or
+Type TBinaryLogicExpr Extends TBinaryExpr
+
+	Method Create:TBinaryLogicExpr( op$,lhs:TExpr,rhs:TExpr )
+		Self.op=op
+		Self.lhs=lhs
+		Self.rhs=rhs
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TBinaryLogicExpr.Create( op,CopyExpr(lhs),CopyExpr(rhs) )
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+		
+		lhs=lhs.SemantAndCast( TType.boolType,CAST_EXPLICIT )
+		rhs=rhs.SemantAndCast( TType.boolType,CAST_EXPLICIT )
+		
+		exprType=TType.boolType
+		
+		If TConstExpr( lhs ) And TConstExpr( rhs ) Return EvalConst()
+		
+		Return Self
+	End Method
+	
+	Method Eval$()
+		Select op
+		Case "and" If lhs.Eval() And rhs.Eval() Return "1" Else Return ""
+		Case "or"  If lhs.Eval() Or rhs.Eval() Return "1" Else Return ""
+		End Select
+		InternalErr
+	End Method
+End Type
+
+Type TIndexExpr Extends TExpr
+	Field expr:TExpr
+	Field index:TExpr
+	
+	Method Create:TIndexExpr( expr:TExpr,index:TExpr )
+		Self.expr=expr
+		Self.index=index
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TIndexExpr.Create( CopyExpr(expr),CopyExpr(index) )
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+	
+		expr=expr.Semant()
+		index=index.SemantAndCast( TType.intType )
+		
+		If TStringType( expr.exprType )
+			exprType=TType.intType
+		Else If TArrayType( expr.exprType )
+			exprType=TArrayType( expr.exprType ).elemType
+		Else If TPointerType( expr.exprType) And Not TFunctionPtrType( expr.exprType )
+			exprType=TType.intType
+		Else
+			Err "Only strings, arrays and pointers may be indexed."
+		EndIf
+
+		Return Self
+	End Method
+	
+	Method SemantSet:TExpr( op$,rhs:TExpr )
+		Semant
+		Return Self
+	End Method
+
+	Method Trans$()
+		Return _trans.TransIndexExpr( Self )
+	End Method
+	
+	Method TransVar$()
+		Return _trans.TransIndexExpr( Self )
+	End Method
+
+End Type
+
+Type TSliceExpr Extends TExpr
+	Field expr:TExpr
+	Field from:TExpr
+	Field term:TExpr
+	
+	Method Create:TSliceExpr( expr:TExpr,from:TExpr,term:TExpr )
+		Self.expr=expr
+		Self.from=from
+		Self.term=term
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TSliceExpr.Create( CopyExpr(expr),CopyExpr(from),CopyExpr(term) )
+	End Method
+	
+	Method Semant:TExpr()
+		If exprType Return Self
+	
+		expr=expr.Semant()
+		If TArrayType( expr.exprType ) Or TStringType( expr.exprType )
+			If from from=from.SemantAndCast( TType.intType )
+			If term term=term.SemantAndCast( TType.intType )
+			exprType=expr.exprType
+		Else
+			Err "Slices can only be used on strings or arrays."
+		EndIf
+		
+'		If TConstExpr( expr ) And TConstExpr( from ) And TConstExpr( term ) Return EvalConst()
+
+		Return Self
+	End Method
+	
+	Method Eval$()
+		Local from:Int=Int( Self.from.Eval() )
+		Local term:Int=Int( Self.term.Eval() )
+		If TStringType( expr.exprType )
+			Return expr.Eval()[ from..term ]
+		Else If TArrayType( expr.exprType )
+			Todo
+		EndIf
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransSliceExpr( Self )
+	End Method
+End Type
+
+Type TArrayExpr Extends TExpr
+	Field exprs:TExpr[]
+	
+	Method Create:TArrayExpr( exprs:TExpr[] )
+		Self.exprs=exprs
+		Return Self
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TArrayExpr.Create( CopyArgs(exprs) )
+	End Method
+
+	Method Semant:TExpr()
+		If exprType Return Self
+		
+		exprs[0]=exprs[0].Semant()
+		Local ty:TType=exprs[0].exprType
+		
+		For Local i:Int=1 Until exprs.Length
+			exprs[i]=exprs[i].Semant()
+			ty=BalanceTypes( ty,exprs[i].exprType )
+		Next
+		
+		For Local i:Int=0 Until exprs.Length
+			exprs[i]=exprs[i].Cast( ty )
+		Next
+		
+		exprType=New TArrayType.Create( ty )
+		Return Self	
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransArrayExpr( Self )
+	End Method
+
+End Type

+ 970 - 0
iparser.bmx

@@ -0,0 +1,970 @@
+SuperStrict
+
+Import BRL.MaxUtil
+
+Import "toker.bmx"
+Rem
+Global globalMod:TModuleDecl = New TModuleDecl.Create("brl.global", "bbGlobal", "", 0)
+
+Local m:String = "brl.blitz"
+Local path:String = modulepath(m)
+
+' "/Volumes/Multimedia1TB/programming/BlitzMax/mod/bah.mod/crypto.mod/crypto.release.macos.x86.i"
+
+Local par:TIParser = New TIParser
+par.ParseModuleImport(globalMod, m, path, "blitz_classes.i")
+par.ParseModuleImport(globalMod, m, path)
+End Rem
+'m = "bah.freeimage"
+'path = modulepath(m)
+'par.ParseModuleImport(globalMod, m, path)
+
+
+Const DECL_GLOBAL:Int = $10
+Const DECL_FIELD:Int = $20
+Const DECL_CONST:Int = $40
+Const DECL_LOCAL:Int = $80
+
+
+Type TIParser
+
+	Field _toker:TToker
+	Field _toke$
+	Field _tokeType:Int
+	Field _tokeSpace:Int
+	Field _tokerStack:TList=New TList'<TToker>
+
+	Method ParseModuleImport:Int(pmod:TModuleDecl, modpath:String, path:String, imp:String = Null, iData:String = Null, attrs:Int = 0, relPath:String = "")
+'DebugStop	
+		Const STATE_CLASS:Int = 1
+		
+	
+		Local _mod:TModuleDecl = New TModuleDecl.Create(modpath, "bb" + modpath, path, attrs)
+		Select modpath
+			Case "brl.classes", "brl.blitzkeywords"
+				_mod.filepath :+ "." + modpath
+		End Select
+
+		_mod.declImported = True
+		_mod.relpath = relPath
+
+		If modpath = "brl.blitz" Then
+			If pmod.imported.Contains(modpath) Then
+				_mod = TModuleDecl(pmod.imported.ValueForKey(modpath))
+			Else
+				pmod.imported.Insert(modpath, _mod)
+			End If
+			
+			' import Object and String definitions
+			Local par:TIParser = New TIParser
+			par.ParseModuleImport(_mod, "brl.classes", modulepath("brl.blitz"), "blitz_classes.i")
+	
+			' set up built-in keywords
+			par = New TIParser
+			par.ParseModuleImport(_mod, "brl.blitzkeywords", "", "", MakeKeywords())
+
+		Else
+			pmod.imported.Insert(modpath, _mod)
+		End If
+		
+		Local ipath:String
+		
+		'Local ipath:String = path + "\" + ModuleIdent(modpath) + ".release.macos.x86.i"
+		If imp Then
+			ipath = path + "/" + imp
+		Else
+			ipath = path + "/" + ModuleIdent(modpath) + FileMung() + ".i"
+		End If
+		
+		If Not iData Then
+DebugLog ipath
+			If Not FileType(ipath) Then
+				Return False
+			End If
+	
+			'Local ifile:String[] = LoadString(ipath).Split("~n")
+		
+			_toker = New TToker.Create( ipath,LoadString( ipath ) )
+		Else
+			_toker = New TToker.Create( ipath, iData)
+		End If
+
+
+	Local toker:TToker = _toker
+	
+		
+	 Repeat
+		Local pos:Int
+	
+		pos = toker._tokePos
+		toker.NextToke
+	
+		
+		Local line:Int
+		Local state:Int
+		Local class:TClassDecl
+		Local stm:String
+		
+		
+		
+		Select toker.Toke().ToLower()
+			Case "import"
+			
+				toker.NextToke()
+				If toker.TokeType()=TOKE_SPACE toker.NextToke()
+				
+				' skip non-module imports
+				If toker.TokeType()=TOKE_STRINGLIT
+					Continue
+				End If
+				
+
+				Local m:String = toker._toke
+				toker.NextToke()
+				
+				Parse(".")
+				
+				m :+ "." + toker._toke
+				
+				Local mdecl:TDecl=TDecl(pmod.GetDecl( m ))
+'DebugStop
+
+				If Not mdecl
+					Local path:String = modulepath(m)
+					' parse the imported module
+					New TIParser.ParseModuleImport( _mod, m, path )
+				Else
+					_mod.imported.Insert(m, mdecl)
+				EndIf
+				
+				Continue
+				
+			
+			Case "moduleinfo"
+				toker.nextToke()
+				If toker.TokeType()=TOKE_SPACE toker.NextToke()
+				Continue
+			Case "~r", "~n"
+				Continue
+			Default
+'DebugStop
+				
+				stm = toker.Toke()
+				
+				Local v:String = toker.NextToke()			
+
+				Select v
+					Case "^"
+
+						toker.rollback(pos)
+						toker.NextToke()
+						' class decl
+						class = ParseClassDecl( stm,0 )
+						_mod.InsertDecl(class)
+
+						If CParse("F")
+							class.attrs :| DECL_ABSTRACT
+						Else If CParse("A")
+							class.attrs :| DECL_FINAL
+						Else If CParse("AF")
+							class.attrs :| DECL_ABSTRACT | DECL_FINAL
+						End If
+'DebugStop
+						If CParse( "=" )
+'DebugStop
+							class.munged=ParseStringLit()
+				
+						EndIf
+
+						DebugLog ""
+						'state = STATE_CLASS
+						'Exit
+				'	Case "%"
+				Default
+					If toker._tokeType = TOKE_EOF
+'DebugStop
+						Exit
+					End If
+
+					Local a:Int
+					Local ty:TType = ParseDeclType(a)
+
+					If CParse("(") Then
+						toker.rollback(pos)
+						toker.NextToke()
+
+						Local decl:TFuncDecl = ParseFuncDecl( _toke, 0 )
+						_mod.InsertDecl decl
+
+					Else
+'DebugStop
+						toker.rollback(pos)
+						toker.NextToke()
+						
+						Local decl:TDecl = ParseDecl( _toke, DECL_CONST | DECL_EXTERN)'DECL_GLOBAL | DECL_EXTERN )
+						_mod.InsertDecl decl
+
+					End If
+				
+				End Select
+				
+				'Continue
+		End Select
+			line :+ 1
+			
+		Forever
+		
+		
+		Return True
+		
+	End Method
+
+	Method ParseUnaryExpr:TExpr()
+
+		SkipEols
+	
+		Local op$=_toke
+		Select op
+		Case "+","-","~~","not"
+			NextToke
+			Local expr:TExpr=ParseUnaryExpr()
+			Return New TUnaryExpr.Create( op,expr )
+		End Select
+		Return ParsePrimaryExpr( False )
+	End Method
+
+	Method ParsePrimaryExpr:TExpr( stmt:Int )
+	
+		Local expr:TExpr
+
+			Select _tokeType
+			'Case TOKE_IDENT
+			'	expr=New TIdentExpr.Create( ParseIdent() )
+			Case TOKE_INTLIT
+				expr=New TConstExpr.Create( TType.intType,_toke )
+				NextToke
+			Case TOKE_LONGLIT
+				expr=New TConstExpr.Create( TType.longType,_toke )
+				NextToke
+			Case TOKE_FLOATLIT
+				expr=New TConstExpr.Create( TType.floatType,_toke )
+				NextToke
+			Case TOKE_STRINGLIT
+				expr=New TConstExpr.Create( TType.stringType,BmxUnquote( _toke ) )
+				NextToke
+			Default
+				Err "Syntax error - unexpected token '"+_toke+"'"
+			End Select
+
+		Return expr
+		
+	End Method
+
+	Method ParseClassDecl:TClassDecl( toke$,attrs:Int )
+		'SetErr
+
+		'If toke Parse toke
+		
+		Local id$=ParseIdent()
+		Local args:TClassDecl[]
+		Local superTy:TIdentType
+		Local imps:TIdentType[]
+
+		DebugLog "Found Class :  " + id
+'If id = "TTextStream" DebugStop
+'DebugStop 
+'End If
+		If CParse( "^" )
+
+			If CParse( "null" )
+			
+				superTy=Null
+				
+			Else
+				superTy=ParseIdentType()
+				'If superTy.ident <> "Object" Then
+				'	superTy = TIdentType(superTy.Semant())
+				'EndIf
+			EndIf
+		Else
+			superTy = TType.objectType
+		EndIf
+'DebugStop
+		Local classDecl:TClassDecl=New TClassDecl.Create( id,args,superTy,imps,attrs )
+		
+		If classDecl.IsExtern()
+			classDecl.munged=classDecl.ident
+			If CParse( "=" ) classDecl.munged=ParseStringLit()
+		EndIf
+		
+		'If classDecl.IsTemplateArg() Return classDecl
+
+		Local decl_attrs:Int=(attrs & DECL_EXTERN)
+		
+		Local method_attrs:Int=decl_attrs
+		If attrs & CLASS_INTERFACE method_attrs:|DECL_ABSTRACT
+
+
+		Repeat
+			SkipEols
+			'If IsSpace(Asc(_toker._toke))
+			'	_toker.NextToke
+			'End If
+			
+			Select _toker._toke
+			Case "{"
+				'_toker.
+				NextToke
+			Case "}"
+				'_toker.
+				NextToke
+				Exit
+			Case "-" ' method
+				'DebugStop
+				'_toker.
+				NextToke
+				
+				Local decl:TFuncDecl = ParseFuncDecl( _toke,method_attrs|FUNC_METHOD )
+				'If decl.IsCtor() decl.retTypeExpr=New TObjectType.Create( classDecl )
+				classDecl.InsertDecl decl
+				
+			Case "+" ' function
+				NextToke
+				
+				Local decl:TFuncDecl = ParseFuncDecl( _toke,method_attrs )
+				'If decl.IsCtor() decl.retTypeExpr=New TObjectType.Create( classDecl )
+				classDecl.InsertDecl decl
+
+			Case "." ' field
+				NextToke
+				
+				decl_attrs :| DECL_FIELD
+				
+				Local decl:TDecl= ParseDecl( _toke,decl_attrs )
+				classDecl.InsertDecl decl
+			Rem
+			Case "private"
+				NextToke
+				decl_attrs=decl_attrs | DECL_PRIVATE
+			Case "public"
+				NextToke
+				decl_attrs=decl_attrs & ~DECL_PRIVATE
+			Case "const","global","field"
+				If (attrs & CLASS_INTERFACE) And _toke<>"const"
+					Err "Interfaces can only contain constants and methods."
+				EndIf
+				classDecl.InsertDecls ParseDecls( _toke,decl_attrs )
+			Case "method"
+				Local decl:TFuncDecl=ParseFuncDecl( _toke,method_attrs )
+				If decl.IsCtor() decl.retTypeExpr=New TObjectType.Create( classDecl )
+				classDecl.InsertDecl decl
+			Case "function"
+				If (attrs & CLASS_INTERFACE) And _toke<>"const"
+					Err "Interfaces can only contain constants and methods."
+				EndIf
+				Local decl:TFuncDecl=ParseFuncDecl( _toke,decl_attrs )
+				classDecl.InsertDecl decl
+				End Rem
+			'Default
+			'	Err "Syntax error - expecting class member declaration."
+			End Select
+			
+			If _toker._tokeType = TOKE_IDENT Then
+				' Const / Global?
+				'NextToke
+				
+				decl_attrs :| DECL_CONST
+				
+				Local decl:TDecl= ParseDecl( _toke,decl_attrs )
+				classDecl.InsertDecl decl
+			End If
+			
+		Forever
+		
+		If toke CParse toke
+		
+		Return classDecl
+
+	End Method
+
+	Method Parse( toke$ )
+		If Not CParse( toke )
+			Err "Syntax error - expecting '"+toke+"'."
+		EndIf
+	End Method
+
+	Method ParseIdent$()
+		Select _toker._toke.tolower()
+		Case "@" _toker.NextToke
+		Case "string","array","object"
+		Default	
+			If _toker._tokeType<>TOKE_IDENT Err "Syntax error - expecting identifier."
+		End Select
+		Local id$=_toker._toke
+		NextToke
+		Return id
+	End Method
+
+	Method ParseIdentType:TIdentType()
+		Local id$=ParseIdent()
+		
+		While CParse( "." )
+			id:+"."+ParseIdent()
+		Wend
+		Local args:TIdentType[]
+		Return New TIdentType.Create( id,args )
+	End Method
+
+	Method NextToke$()
+		Local toke$=_toke
+		
+		_tokeSpace=False
+		
+		Repeat
+			_toke=_toker.NextToke()
+			_tokeType=_toker.TokeType()
+			If _tokeType<>TOKE_SPACE Exit
+			_tokeSpace=True
+		Forever
+		
+		If _tokeType=TOKE_KEYWORD _toke=_toke.ToLower()
+
+		If toke="," SkipEols
+
+		Return _toke
+	End Method
+	
+	Method CParse:Int( toke$ )
+		If _toker._toke.tolower()<>toke.tolower()
+			Return False
+		EndIf
+		'_toker.
+		NextToke
+		Return True
+	End Method
+
+	Method SkipEols()
+		Local found:Int = True
+		While found
+			found = False
+			If CParse( "~n" )
+				found = True
+			End If
+			If CParse("~r")
+				found = True
+			End If
+		Wend
+		
+		'SetErr
+	End Method
+
+	Method ParseStringLit$()
+		If _toker._tokeType<>TOKE_STRINGLIT Err "Expecting string literal."
+		Local str$=BmxUnquote( _toker._toke )
+		'_toker.
+		NextToke
+		Return str
+	End Method
+
+Method ParseFuncDecl:TFuncDecl( toke$,attrs:Int )
+		'SetErr
+
+		'If toke Parse toke
+	
+		Local id$
+		Local ty:TType
+		Local meth:Int = attrs & FUNC_METHOD
+		
+		If attrs & FUNC_METHOD
+			If _toker._toke.tolower() = "new"
+'DebugStop
+				If attrs & DECL_EXTERN
+					Err "Extern classes cannot have constructors"
+				EndIf
+				id=_toker._toke
+				NextToke
+				attrs:|FUNC_CTOR
+				attrs:&~FUNC_METHOD
+				ty=ParseDeclType(attrs)
+			Else
+				id=ParseIdent()
+				ty=ParseDeclType(attrs)
+			EndIf
+		Else
+			id=ParseIdent()
+			ty=ParseDeclType(attrs)
+		EndIf
+		
+		If attrs & FUNC_METHOD
+'DebugLog "Found Method :  " + id
+		Else
+'DebugLog "Found Function :  " + id
+		End If
+		
+		Local args:TArgDecl[]
+		
+		Parse "("
+		SkipEols
+
+		If _toker._toke<>")"
+			Local nargs:Int
+			Repeat
+
+				Local pos:Int, tokeType:Int
+				pos = _toker._tokePos
+				tokeType = _toker._tokeType
+'DebugStop
+				Local id$=ParseIdent()
+'If id = "stream" DebugStop
+				Local ty:TType=ParseDeclType(attrs)
+				Local init:TExpr
+
+				If CParse( "(") Then
+'DebugStop
+					' function pointer
+					_toker.rollback(pos, tokeType)
+					_toker._toke = id
+					'_toker.NextToke()
+					Local decl:TFuncDecl = ParseFuncDecl( id, 0 )
+					ty = New TFunctionPtrType
+					TFunctionPtrType(ty).func = decl
+					
+				End If
+				
+				If CParse("Var") Then
+					ty = TType.MapToVarPointerType(ty)
+				End If
+
+				If CParse( "=" ) Then
+					'DebugLog "TODO : parse default values..."
+					If CParse("$") Then
+						' a string default
+						init = ParseUnaryExpr()
+					Else
+						init = ParseUnaryExpr()
+					End If
+					' has a default value
+					'DebugStop
+					'init=ParseExpr()
+				End If
+				
+				Local arg:TArgDecl=New TArgDecl.Create( id,ty,init )
+				If args.Length=nargs args=args + New TArgDecl[10]
+				args[nargs]=arg
+				nargs:+1
+				If _toker._toke=")" Exit
+				Parse ","
+			Forever
+			args=args[..nargs]
+		EndIf
+		Parse ")"
+		
+		Repeat		
+			If CParse( "final" )
+				attrs:|DECL_FINAL
+			Else If CParse( "abstract" )
+				attrs:|DECL_ABSTRACT
+			Else If CParse( "property" )
+				If attrs & FUNC_METHOD
+					attrs:|FUNC_PROPERTY
+				Else
+					Err "Only methods can be properties."
+				EndIf
+			Else
+				Exit
+			EndIf
+		Forever
+		
+		Local funcDecl:TFuncDecl=New TFuncDecl.CreateF( id,ty,args,attrs )
+		
+		funcDecl.retType = ty
+		
+		If CParse("&") Then
+			funcDecl.attrs :| DECL_POINTER
+		End If
+		
+		'If funcDecl.IsExtern()
+		'	funcDecl.munged=funcDecl.ident
+			If CParse( "=" )
+
+				If CParse("mem")
+					If CParse(":")
+						If CParse("p")
+							If CParse("(") Then
+								
+								'DebugStop
+
+								'_toker.NextToke()
+								
+								funcDecl.munged = ParseStringLit()
+								
+								Cparse(")")
+
+							EndIf
+						End If
+					End If
+				Else
+					funcDecl.munged=ParseStringLit()
+					
+				End If
+
+
+
+				
+				'Array $resize hack!
+				'If funcDecl.munged="$resize"
+				'	funcDecl.retTypeExpr=TType.emptyArrayType
+				'EndIf
+				
+			EndIf
+			
+		' read function cast stuff
+		If CParse(":") Then
+			' ret type
+			Local rt$=_toker._toke
+			NextToke
+			If CParse("*") Then
+				rt:+ "*"
+				
+				If CParse("*") Then
+					rt:+ "*"
+				End If
+			End If
+			
+			funcDecl.castTo = rt
+
+			' fname
+			Local fn$=_toker._toke
+			NextToke
+
+			' args
+			Parse("(")
+
+			If Not CParse(")") Then
+				Local i:Int = 0			
+				Repeat
+					Local at$=_toker._toke
+					
+					If CParse("const") Then
+						at :+ " " + _toker._toke
+					End If
+					
+					If CParse("unsigned") Then
+						at :+ " " + _toker._toke
+					End If
+
+
+					NextToke
+					If CParse("*") Then
+						at:+ "*"
+						
+						If CParse("*") Then
+							at:+ "*"
+						End If
+					End If
+
+
+					' function pointer
+					If CParse("(") Then
+
+						Parse("*")
+						Parse(")")
+						at :+ "(*)"
+						
+						Parse("(")
+						at :+ "("
+						
+						While Not CParse(")")
+							NextToke
+							at :+ _toker._toke
+						Wend
+						
+						at :+ ")"
+					End If
+
+
+
+					args[i].castTo = at
+					
+				
+					If _toker._toke=")" Exit
+					Parse ","
+					
+					i:+ 1
+				Forever
+			End If
+				
+
+		End If
+			
+		'	Return funcDecl
+		'EndIf
+		
+		'If funcDecl.IsAbstract() Return funcDecl
+		Return funcDecl
+		
+	End Method
+	
+	Method ParseDecl:TDecl( toke$,attrs:Int )
+		'SetErr
+		Local id$=ParseIdent()
+		Local ty:TType
+		Local init:TExpr
+		
+'DebugLog "Found Field :  " + id
+		If attrs & DECL_EXTERN
+			ty=ParseDeclType(attrs)
+
+		'Else If CParse( ":=" )
+	'		init=ParseExpr()
+		Else
+			ty=ParseDeclType(attrs)
+			If CParse( "=" )
+				' TODO init=ParseExpr()
+				init = ParseUnaryExpr()
+				'DebugLog "TODO : ParseExpression"
+			Else If CParse( "[" )
+				'Local ln:TExpr=ParseExpr()
+				Parse "]"
+				'While CParse( "[]" )
+				'	ty=New TArrayType.Create(ty)
+				'Wend
+				'init=New TNewArrayExpr.Create( ty,ln)
+				'ty=New TArrayType.Create( ty )
+			Else If toke<>"const"
+				init=New TConstExpr.Create( ty,"" )
+			Else
+				Err "Constants must be initialized."
+			EndIf
+		EndIf
+		
+		Local decl:TValDecl
+		
+		If attrs & DECL_GLOBAL
+			decl=New TGlobalDecl.Create( id,ty,init,attrs )
+		Else If attrs & DECL_FIELD
+			decl=New TFieldDecl.Create( id,ty,init,attrs )
+		Else If attrs & DECL_CONST
+			decl=New TConstDecl.Create( id,ty,init,attrs )
+		Else If attrs & DECL_LOCAL
+			decl=New TLocalDecl.Create( id,ty,init,attrs )
+		EndIf
+		
+		If decl.IsExtern() 
+			If CParse( "=" )
+				'decl.munged=ParseStringLit()
+				
+				If CParse("mem")
+					' change to global
+'DebugStop
+					If attrs & DECL_CONST Then
+						attrs :| DECL_GLOBAL
+						attrs :~ DECL_CONST
+						decl=New TGlobalDecl.Create( id,ty,init,attrs )
+					End If
+				
+				
+					If CParse(":")
+						If CParse("p")
+							If CParse("(") Then
+								
+'								DebugStop
+
+								'_toker.NextToke()
+								
+								decl.munged = ParseStringLit()
+								
+								Cparse(")")
+
+							EndIf
+						End If
+					Else
+						If CParse("(") Then
+								
+'							DebugStop
+
+								'_toker.NextToke()
+								
+							decl.munged = ParseStringLit()
+							
+							Cparse(")")
+
+						EndIf
+					End If
+				Else
+					If ty = TType.stringType
+						decl.munged=ParseStringLit()
+					Else
+						' a default value ?
+'DebugStop
+						Local value:String
+						'_toker.NextToke()
+						
+						If CParse("-") Then
+							value = "-"
+							_toker.NextToke()
+						End If
+						
+						decl.init = New TConstExpr.Create(ty, value + _toker._toke)
+						
+					End If
+				End If
+				
+				
+				
+			Else
+				decl.munged=decl.ident
+			EndIf
+		EndIf
+	
+		Return decl
+	End Method
+
+	Method ParseDeclType:TType(attrs:Int Var)
+		Local ty:TType
+		Select _toker._toke
+		'Case "?"
+		'	NextToke
+		'	ty=TType.boolType
+		Case "%"
+			NextToke
+			ty=TType.intType
+
+			If CParse("%") Then
+				ty = TType.longType
+			End If
+			
+			If CParse("&") Then
+				attrs :| DECL_GLOBAL
+				attrs :~ DECL_CONST
+			End If
+
+
+			If CParse( "*" ) Then
+'DebugStop
+				If ty = TType.longType Then
+					ty = TType.longPointerType
+				Else
+					ty = TType.intPointerType
+				End If
+				
+			End If
+			
+		Case "#"
+			NextToke
+			ty=TType.floatType
+
+			If CParse("&") Then
+				attrs :| DECL_GLOBAL
+				attrs :~ DECL_CONST
+			End If
+			
+		Case "$"
+			NextToke
+			ty=TType.stringType
+			If CParse( "&" )
+				attrs :| DECL_GLOBAL
+				attrs :~ DECL_CONST
+			End If
+		Case "!"
+			NextToke
+			ty=TType.doubleType
+		Case ":"
+			NextToke
+			ty=ParseNewType()
+		Case "@"
+			NextToke
+			ty=TType.byteType
+			
+			If CParse("@") Then
+				ty = TType.shortType
+			End If
+
+			
+			If CParse( "&" )
+'DebugStop
+			End If
+			
+			If CParse( "*" ) Then
+
+				If ty = TType.byteType Then
+					ty = TType.bytePointerType
+				Else
+					ty = TType.shortPointerType
+				End If
+				
+				' byte pointer pointer ?
+				If CParse("*")  Then
+					If ty = TType.byteType Then
+						ty = TType.bytePointerPtrType
+					Else
+						ty = TType.shortPointerPtrType
+					End If
+				End If
+				
+			End If
+' TODO
+'		Case "!" ' BaH Double
+'			NextToke
+'			ty=TType.doubleType
+		Default
+			'If _module.IsStrict() Err "Illegal type expression."
+'DebugStop
+			ty=TType.intType
+		End Select
+		While CParse( "[]" )
+			ty=New TArrayType.Create( ty )
+		Wend
+		
+		If CParse( "&" ) Then
+		End If
+		
+		Return ty
+	End Method
+
+	Method ParseNewType:TType()
+		If CParse( "byte" ) Or CParse( "@" )
+'DebugStop
+			If CParse("ptr") Or CParse( "*" ) Then
+				Return TType.bytePointerType
+			End If
+			Return TType.byteType
+		End If
+		If CParse( "short" ) 
+			If CParse("ptr") Then
+				Return TType.bytePointerType
+			End If
+			Return TType.shortType
+		End If
+		If CParse( "int" ) Or CParse( "%" )
+			If CParse("ptr") Or CParse( "*" ) Then
+				Return TType.bytePointerType
+			End If
+			Return TType.intType
+		End If
+		If CParse( "float" )
+			If CParse("ptr") Then
+				Return TType.bytePointerType
+			End If
+			Return TType.floatType
+		End If
+		If CParse( "string" ) Return TType.stringType
+		If CParse( "object" ) Return TType.objectType
+		If CParse( "long" )
+			If CParse("ptr") Then
+				Return TType.bytePointerType
+			End If
+			Return TType.longType ' BaH Long
+		End If
+		If CParse( "double" )
+			If CParse("ptr") Then
+				Return TType.bytePointerType
+			End If
+			Return TType.doubleType
+		End If
+		Return ParseIdentType()
+	End Method
+
+End Type
+
+

+ 168 - 0
options.bmx

@@ -0,0 +1,168 @@
+SuperStrict
+
+Const version:String = "0.10"
+
+Const BUILDTYPE_APP:Int = 0
+Const BUILDTYPE_MODULE:Int = 1
+
+Const APPTYPE_NONE:Int = 0
+Const APPTYPE_CONSOLE:Int = 1
+Const APPTYPE_GUI:Int = 2
+
+' buildtype
+'    module
+'    app
+Global opt_buildtype:Int = BUILDTYPE_APP
+' modulename
+'    name of the module to build
+Global opt_modulename:String
+' arch
+'    x86
+'    ppc
+'    x64
+'    arm
+Global opt_arch:String
+' platform
+'    win32
+'    macos
+'    linux
+Global opt_platform:String
+' framework
+Global opt_framework:String
+' filename
+'    the base filename for app/module to compile against
+Global opt_filename:String
+' outfile
+'    full path to the outputfile (excluding final extension - there will be a .h, .c and .i generated)
+Global opt_outfile:String
+' apptype
+'    console
+'    gui
+Global opt_apptype:Int = APPTYPE_NONE
+' debug
+Global opt_debug:Int = True
+' threaded
+Global opt_threaded:Int = False
+' release
+Global opt_release:Int = False
+' quiet
+Global opt_quiet:Int = False
+' verbose
+Global opt_verbose:Int = False
+' ismain
+'    this is the main file for either the module, or the application.
+Global opt_ismain:Int = False
+' issuperstrict
+'
+Global opt_issuperstrict:Int = False
+
+Global opt_filepath:String
+
+Function CmdError(details:String = Null, fullUsage:Int = False)
+	Local s:String = "Compile Error"
+	If details Then
+		s:+ ": " + details
+	End If
+	s:+ "~n"
+	
+	's:+ Usage(fullUsage)
+	
+	Throw s
+End Function
+
+Function ParseArgs:String[](args:String[])
+
+	DefaultOptions()
+	
+	Local count:Int
+
+	While count < args.length
+	
+		Local arg:String = args[count]
+		
+		If arg[..1] <> "-" Then
+			Exit
+		End If
+		
+		Select arg[1..]
+			Case "q"
+				opt_quiet=True
+			Case "v"
+				opt_verbose=True
+			Case "r"
+				opt_debug=False
+				opt_release=True
+			Case "h"
+				opt_threaded=True
+			Case "g"
+				count:+1
+				If count = args.length Then
+					CmdError "Command line error - Missing arg for '-g'"
+				End If
+				opt_arch = args[count].ToLower()
+			Case "m"
+				count:+1
+				If count = args.length Then
+					CmdError "Command line error - Missing arg for '-m'"
+				End If
+				opt_buildtype = BUILDTYPE_MODULE
+				opt_modulename = args[count].ToLower()
+			Case "o"
+				count:+1
+				If count = args.length Then
+					CmdError "Command line error - Missing arg for '-o'"
+				End If
+				opt_outfile = args[count]
+			Case "t"
+				count:+1
+				If count = args.length Then
+					CmdError "Command line error - Missing arg for '-t'"
+				End If
+				Local apptype:String = args[count].ToLower()
+				Select apptype
+					Case "console"
+						opt_apptype = APPTYPE_CONSOLE
+					Case "gui"
+						opt_apptype = APPTYPE_GUI
+					Default
+						CmdError "Command line error - Invalid app type '" + opt_apptype + "'"
+				End Select
+			Case "f"
+				count:+1
+				If count = args.length Then
+					CmdError "Command line error - Missing arg for '-f'"
+				End If
+				opt_framework = args[count]
+		End Select
+	
+		count:+ 1
+	Wend
+	
+	If opt_buildtype = BUILDTYPE_MODULE Then
+		opt_apptype = APPTYPE_NONE
+	End If
+
+	Return args[count..]
+
+End Function
+
+Function DefaultOptions()
+?x86
+	opt_arch = "x86"
+?ppc
+	opt_arch = "ppc"
+?x64
+	opt_arch = "x64"
+?arm
+	opt_arch = "arm"
+?
+
+?win32
+	opt_platform = "win32"
+?macos
+	opt_platform = "macos"
+?linux
+	opt_platform = "linux"
+?
+End Function
+

+ 2801 - 0
parser.bmx

@@ -0,0 +1,2801 @@
+SuperStrict
+
+Import BRL.MaxUtil
+Import "toker.bmx"
+Import "iparser.bmx"
+
+
+Global FILE_EXT$="bmx"
+
+Type TScopeExpr Extends TExpr
+	Field scope:TScopeDecl
+
+	Method Create:TScopeExpr( scope:TScopeDecl )
+		Self.scope=scope
+		Return Self
+	End Method
+
+	Method Copy:TExpr()
+		Return Self
+	End Method
+
+	Method ToString$()
+		Return "TScopeExpr("+scope.ToString()+")"
+	End Method
+
+	Method Semant:TExpr()
+		Err "Syntax error."
+	End Method
+
+	Method SemantScope:TScopeDecl()
+		Return scope
+	End Method
+End Type
+
+Type TForEachinStmt Extends TStmt
+	Field varid$
+	Field varty:TType
+	Field varlocal:Int
+	Field expr:TExpr
+	Field block:TBlockDecl
+
+	Field stmts:TList=New TList
+
+	Method Create:TForEachinStmt( varid$,varty:TType,varlocal:Int,expr:TExpr,block:TBlockDecl )
+		Self.varid=varid
+		Self.varty=varty
+		Self.varlocal=varlocal
+		Self.expr=expr
+		Self.block=block
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TForEachinStmt.Create( varid,varty,varlocal,expr.Copy(),block.CopyBlock( scope ) )
+	End Method
+
+	Method OnSemant()
+		expr=expr.Semant()
+
+		If TArrayType( expr.exprType ) Or TStringType( expr.exprType )
+
+			Local exprTmp:TLocalDecl=New TLocalDecl.Create( "",Null,expr )
+			Local indexTmp:TLocalDecl=New TLocalDecl.Create( "",Null,New TConstExpr.Create( TType.intType,"0" ) )
+
+			Local lenExpr:TExpr=New TIdentExpr.Create( "Length",New TVarExpr.Create( exprTmp ) )
+
+			Local cmpExpr:TExpr=New TBinaryCompareExpr.Create( "<",New TVarExpr.Create( indexTmp ),lenExpr )
+
+			Local indexExpr:TExpr=New TIndexExpr.Create( New TVarExpr.Create( exprTmp ),New TVarExpr.Create( indexTmp ) )
+			Local addExpr:TExpr=New TBinaryMathExpr.Create( "+",New TVarExpr.Create( indexTmp ),New TConstExpr.Create( TType.intType,"1" ) )
+
+			block.stmts.AddFirst New TAssignStmt.Create( "=",New TVarExpr.Create( indexTmp ),addExpr )
+
+			If varlocal
+				Local varTmp:TLocalDecl=New TLocalDecl.Create( varid,varty,indexExpr )
+				block.stmts.AddFirst New TDeclStmt.Create( varTmp )
+			Else
+				block.stmts.AddFirst New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),indexExpr )
+			EndIf
+
+			Local whileStmt:TWhileStmt=New TWhileStmt.Create( cmpExpr,block )
+
+			block=New TBlockDecl.Create( block.scope )
+			block.AddStmt New TDeclStmt.Create( exprTmp )
+			block.AddStmt New TDeclStmt.Create( indexTmp )
+			block.AddStmt whileStmt
+
+		Else If TObjectType( expr.exprType )
+
+			Local enumerInit:TExpr=New TFuncCallExpr.Create( New TIdentExpr.Create( "ObjectEnumerator",expr ) )
+			Local enumerTmp:TLocalDecl=New TLocalDecl.Create( "",Null,enumerInit )
+
+			Local hasNextExpr:TExpr=New TFuncCallExpr.Create( New TIdentExpr.Create( "HasNext",New TVarExpr.Create( enumerTmp ) ) )
+			Local nextObjExpr:TExpr=New TFuncCallExpr.Create( New TIdentExpr.Create( "NextObject",New TVarExpr.Create( enumerTmp ) ) )
+
+			If varlocal
+				Local varTmp:TLocalDecl=New TLocalDecl.Create( varid,varty,nextObjExpr )
+				block.stmts.AddFirst New TDeclStmt.Create( varTmp )
+			Else
+				block.stmts.AddFirst New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),nextObjExpr )
+			EndIf
+
+			Local whileStmt:TWhileStmt=New TWhileStmt.Create( hasNextExpr,block )
+
+			block=New TBlockDecl.Create( block.scope )
+			block.AddStmt New TDeclStmt.Create( enumerTmp )
+			block.AddStmt whileStmt
+
+		Else
+			InternalErr
+		EndIf
+
+		block.Semant
+	End Method
+
+	Method Trans$()
+		_trans.EmitBlock block
+	End Method
+
+End Type
+
+Type TIdentTypeExpr Extends TExpr
+	Field cdecl:TClassDecl
+	
+	Method Create:TIdentTypeExpr( ty:TType )
+		Self.exprType=ty
+	End Method
+	
+	Method Copy:TExpr()
+		Return New TIdentTypeExpr.Create( exprType )
+	End Method
+
+	Method _Semant()
+		If cdecl Return
+		exprType=exprType.Semant()
+		cdecl=exprType.GetClass()
+		If Not cdecl InternalErr
+	End Method
+		
+	Method Semant:TExpr()
+		_Semant
+		Err "Expression can't be used in this way"
+	End Method
+	
+	Method SemantFunc:TExpr( args:TExpr[] )
+		_Semant
+		If args.Length=1 And args[0] Return args[0].Cast( cdecl.objectType,CAST_EXPLICIT )
+		Err "Illegal number of arguments for type conversion"
+	End Method
+	
+	Method SemantScope:TScopeDecl()
+		_Semant
+		Return cdecl
+	End	Method
+
+End Type
+
+Type TIdentExpr Extends TExpr
+	Field ident$
+	Field expr:TExpr
+	Field scope:TScopeDecl
+	Field static:Int
+
+	Method Create:TIdentExpr( ident$,expr:TExpr=Null )
+		Self.ident=ident
+		Self.expr=expr
+		Return Self
+	End Method
+
+	Method Copy:TExpr()
+		Return New TIdentExpr.Create( ident,CopyExpr(expr) )
+	End Method
+
+	Method ToString$()
+		Local t$="TIdentExpr(~q"+ident+"~q"
+		If expr t:+","+expr.ToString()
+		Return t+")"
+	End Method
+
+	Method _Semant()
+		If scope Return
+
+		If expr Then
+			scope=expr.SemantScope()
+			If scope
+				static=True
+			Else
+				expr=expr.Semant()
+				scope=expr.exprType.GetClass()
+				If Not scope Err "Expression has no scope"
+			End If
+		Else
+			scope=_env
+			static=_env.FuncScope()=Null Or _env.FuncScope().IsStatic()
+		End If
+		
+	End Method
+
+	Method IdentScope:TScopeDecl()
+		If Not expr Return _env
+
+		Local scope:TScopeDecl=expr.SemantScope()
+		If scope
+			expr=Null
+		Else
+			expr=expr.Semant()
+			scope=expr.exprType.GetClass()
+			If Not scope Err "Expression has no scope."
+		EndIf
+		Return scope
+	End Method
+
+	Method IdentErr( )
+		If scope
+			Local close$
+			For Local decl:TDecl=EachIn scope.Decls()
+				If ident.ToLower()=decl.ident.ToLower()
+					close=decl.ident
+				EndIf
+			Next
+			If close And ident<>close Then
+				Err "Identifier '"+ident+"' not found - perhaps you meant '"+close+"'?"
+			EndIf
+		EndIf
+		Err "Identifier '"+ident+"' not found."
+	End Method
+
+	Method IdentNotFound()
+	End Method
+
+	Method IsVar()
+		InternalErr
+	End Method
+
+	Method Semant:TExpr()
+'DebugStop
+		Return SemantSet( "",Null )
+	End Method
+
+	Method SemantSet:TExpr( op$,rhs:TExpr )
+	
+		_Semant
+		
+		'Local scope:TScopeDecl=IdentScope()
+'DebugStop
+		Local vdecl:TValDecl=scope.FindValDecl( ident )
+		If vdecl
+
+			If TConstDecl( vdecl )
+'				If rhs Err "Constant '"+ident+"' cannot be modified."
+'				Return New TConstExpr.Create( vdecl.ty,TConstDecl( vdecl ).value ).Semant()
+				If rhs Err "Constant '"+ident+"' cannot be modified."
+				Local cexpr:TConstExpr =New TConstExpr.Create( vdecl.ty,TConstDecl( vdecl ).value )
+				If Not static And (TInvokeExpr( expr ) Or TInvokeMemberExpr( expr )) Return New TStmtExpr.Create( New TExprStmt.Create( expr ),cexpr ).Semant()
+				Return cexpr.Semant()
+
+			Else If TFieldDecl( vdecl )
+				If static Err "Field '"+ident+"' cannot be accessed from here."
+				If expr Return New TMemberVarExpr.Create( expr,TVarDecl( vdecl ) ).Semant()
+'				If expr Return New TMemberVarExpr.Create( expr,TVarDecl( vdecl ) ).Semant()
+'				If scope<>_env Or Not _env.FuncScope() Or _env.FuncScope().IsStatic() Err "Field '"+ident+"' cannot be accessed from here."
+			EndIf
+
+			Return New TVarExpr.Create( TVarDecl( vdecl ) ).Semant()
+		EndIf
+
+		If op And op<>"="
+
+			Local fdecl:TFuncDecl=scope.FindFuncDecl( ident )
+			If Not fdecl IdentErr
+
+			If _env.ModuleScope().IsStrict() And Not fdecl.IsProperty() Err "Identifier '"+ident+"' cannot be used in this way."
+
+			Local lhs:TExpr
+
+			If fdecl.IsStatic() Or (scope=_env And Not _env.FuncScope().IsStatic())
+				lhs=New TInvokeExpr.Create( fdecl )
+			Else If expr
+				Local tmp:TLocalDecl=New TLocalDecl.Create( "",Null,expr )
+				lhs=New TInvokeMemberExpr.Create( New TVarExpr.Create( tmp ),fdecl )
+				lhs=New TStmtExpr.Create( New TDeclStmt.Create( tmp ),lhs )
+			Else
+				Return Null
+			EndIf
+
+			Local bop$=op[..1]
+			Select bop
+			Case "*","/","shl","shr","+","-","&","|","~~"
+				rhs=New TBinaryMathExpr.Create( bop,lhs,rhs )
+			Default
+				InternalErr
+			End Select
+			rhs=rhs.Semant()
+		EndIf
+
+		Local args:TExpr[]
+		If rhs args=[rhs]
+
+		Local fdecl:TFuncDecl=scope.FindFuncDecl( ident,args )
+		
+		If fdecl
+			If _env.ModuleScope().IsStrict() And Not fdecl.IsProperty() Err "Identifier '"+ident+"' cannot be used in this way."
+	
+			If Not fdecl.IsStatic()
+				If expr Return New TInvokeMemberExpr.Create( expr,fdecl,args ).Semant()
+				If scope<>_env Or Not _env.FuncScope() Or _env.FuncScope().IsStatic() Err "Method '"+ident+"' cannot be accessed from here."
+			EndIf
+	
+			Return New TInvokeExpr.Create( fdecl,args ).Semant()
+		End If
+		
+		IdentErr
+	End Method
+
+	Method SemantFunc:TExpr( args:TExpr[] )
+
+		_Semant
+
+		'Local scope:TScopeDecl=IdentScope()
+		Local fdecl:TFuncDecl=scope.FindFuncDecl( ident,args )
+
+		If fdecl
+			If Not fdecl.IsStatic()
+				If static Err "Method '"+ident+"' cannot be accessed from here."
+				If expr Return New TInvokeMemberExpr.Create( expr,fdecl,args ).Semant()
+				'If scope<>_env Or _env.FuncScope().IsStatic() Err "Method '"+ident+"' cannot be accessed from here."
+			EndIf
+			Return New TInvokeExpr.Create( fdecl,args ).Semant()
+		EndIf
+
+		'If args.Length=1 And args[0] And TObjectType( args[0].exprType )
+		'	Local cdecl:TClassDecl=TClassDecl( scope.FindScopeDecl( ident ) )
+		'	If cdecl Return args[0].Cast( New TObjectType.Create(cdecl),CAST_EXPLICIT )
+		'EndIf
+
+		Local ty:TType=scope.FindType( ident,Null )
+		If ty Then
+			If args.Length=1 And args[0] Return args[0].Cast( ty,CAST_EXPLICIT )
+			Err "Illegal number of arguments for type conversion"
+		End If
+
+		IdentErr
+	End Method
+
+	Method SemantScope:TScopeDecl()
+		If Not expr Return _env.FindScopeDecl( ident )
+		Local scope:TScopeDecl=expr.SemantScope()
+		If scope Return scope.FindScopeDecl( ident )
+	End Method
+
+'	Method Trans$()
+'		Return _trans.TransIdentExpr( Self )
+'	End Method
+
+End Type
+
+Type TFuncCallExpr Extends TExpr
+	Field expr:TExpr
+	Field args:TExpr[]
+
+	Method Create:TFuncCallExpr( expr:TExpr,args:TExpr[]=Null )
+		Self.expr=expr
+		If args Then
+			Self.args=args
+		Else
+			Self.args = New TExpr[0]
+		End If
+		Return Self
+	End Method
+
+	Method Copy:TExpr()
+		Return New TFuncCallExpr.Create( CopyExpr(expr),CopyArgs(args) )
+	End Method
+
+	Method ToString$()
+		Local t$="TFuncCallExpr("+expr.ToString()
+		For Local arg:TExpr=EachIn args
+			t:+","+arg.ToString()
+		Next
+		Return t+")"
+	End Method
+
+	Method Semant:TExpr()
+		args=SemantArgs( args )
+		Return expr.SemantFunc( args )
+	End Method
+
+End Type
+
+'***** Parser *****
+Type TParser
+
+	Field _toker:TToker
+	Field _toke$
+	Field _tokeType:Int
+	Field _tokerStack:TList=New TList'<TToker>
+
+	Field _block:TBlockDecl
+	Field _blockStack:TList=New TList'<TBlockDecl>
+	Field _errStack:TStringList=New TStringList
+
+	Field _app:TAppDecl
+	Field _module:TModuleDecl
+	
+	Field _externCasts:TMap = New TMap
+
+	Method SetErr()
+		If _toker.Path()
+			_errInfo=_toker.Path()+"<"+_toker.Line()+">"
+		EndIf
+	End Method
+	
+	Method DoErr(error:String)
+		SetErr()
+		Err error
+	End Method
+	
+	Method PushBlock( block:TBlockDecl )
+		If _block <> Null Then
+			_blockStack.AddLast _block
+		End If
+		_errStack.AddLast _errInfo
+		_block=block
+	End Method
+
+	Method PopBlock()
+		_block=TBlockDecl(_blockStack.RemoveLast())
+		_errInfo=String(_errStack.RemoveLast())
+	End Method
+
+	Method RealPath$( path$ )
+		Local popDir$=CurrentDir()
+		ChangeDir ExtractDir( _toker.Path() )
+		path=BRL.FileSystem.RealPath( path )
+		ChangeDir popDir
+		Return path
+	End Method
+
+	Method NextToke$()
+		Local toke$=_toke
+
+		Repeat
+			_toke=_toker.NextToke()
+			_tokeType=_toker.TokeType()
+		Until _tokeType<>TOKE_SPACE
+
+		If _tokeType=TOKE_KEYWORD _toke=_toke.ToLower()
+
+		If toke="," SkipEols
+
+		Return _toke
+	End Method
+
+	Method NextTokeToker$(toker:TToker)
+		Local toke$=toker._toke
+
+		Local tokeSpace:Int=False
+
+		Repeat
+			toker.NextToke()
+			If toker.tokeType()<>TOKE_SPACE Exit
+			tokeSpace=True
+		Forever
+
+		Return toker._toke
+	End Method
+
+	Method CParse:Int( toke$ )
+		If _toke.ToLower()<>toke
+			Return False
+		EndIf
+		NextToke
+		Return True
+	End Method
+
+	Method CParseToker:Int( toker:TToker, toke$ )
+		If toker._toke.ToLower()<>toke
+			Return False
+		EndIf
+		NextTokeToker(toker)
+		Return True
+	End Method
+
+	Method Parse( toke$ )
+		If Not CParse( toke )
+			DoErr "Syntax error - expecting '"+toke+"'."
+		EndIf
+	End Method
+
+	Method ParseToker( toker:TToker, toke$ )
+		If Not CParseToker( toker, toke )
+			DoErr "Syntax error - expecting '"+toke+"'."
+		EndIf
+	End Method
+
+	Method AtEos:Int()
+		Return _toke="" Or _toke=";" Or _toke="~n" Or _toke="else"
+	End Method
+
+	Method SkipEols()
+		While CParse( "~n" )
+		Wend
+		SetErr
+	End Method
+
+	Method SkipEolsToker(toker:TToker)
+		While CParseToker( toker, "~n" )
+		Wend
+		SetErr
+	End Method
+
+	Method ParseStringLit$()
+		If _tokeType<>TOKE_STRINGLIT Err "Expecting string literal."
+		Local str$=BmxUnquote( _toke )
+		NextToke
+		Return str
+	End Method
+
+	Method ParseIdent$()
+		Select _toke
+		Case "@" NextToke
+		Case "string","array","object"
+		Default
+			If _tokeType<>TOKE_IDENT Err "Syntax error - expecting identifier."
+		End Select
+		Local id$=_toke
+		NextToke
+		Return id
+	End Method
+
+	Method ParseIdentType:TIdentType()
+		Local id$=ParseIdent()
+'DebugLog "ParseIdentType : " + id
+		If CParse( "." ) id:+"."+ParseIdent()
+		Local args:TIdentType[]
+		If CParse( "<" )
+			Local nargs:Int
+			Repeat
+				Local arg:TIdentType=ParseIdentType()
+				If args.Length=nargs args=args+ New TIdentType[10]
+				args[nargs]=arg
+				nargs:+1
+			Until Not CParse(",")
+			args=args[..nargs]
+			Parse ">"
+		EndIf
+		Return New TIdentType.Create( id,args )
+	End Method
+
+	Method CParseIdentType:TIdentType( inner:Int=False )
+		If _tokeType<>TOKE_IDENT Return Null
+		Local id$=ParseIdent()
+		If CParse( "." )
+			If _tokeType<>TOKE_IDENT Return Null
+			id:+"."+ParseIdent()
+		End If
+		If Not CParse( "<" ) 
+			If inner Return New TIdentType.Create( id,Null )
+			Return Null
+		EndIf
+		Local args:TType[]
+		Local nargs:Int
+		Repeat
+			Local arg:TType=CParsePrimitiveType()
+			If Not arg 
+				arg=CParseIdentType( True )
+				If Not arg Return Null
+			EndIf
+			While CParse( "[]" )
+				arg=arg.ArrayOf()
+			Wend
+			args = args + [arg]
+			nargs :+ 1
+		Until Not CParse(",")
+		If Not CParse( ">" ) Return Null
+		Return New TIdentType.Create( id,args )
+	End Method
+
+	Method CParsePrimitiveType:TType()
+		If CParse( "short" ) Return TType.shortType
+		If CParse( "byte" ) Return TType.byteType
+		If CParse( "int" ) Return TType.intType
+		If CParse( "float" ) Return TType.floatType
+		If CParse( "string" ) Return TType.stringType
+		If CParse( "object" ) Return TType.objectType
+		If CParse( "long" ) Return TType.intType ' BaH Long
+		If CParse( "double" ) Return TType.doubleType
+	End	Method
+
+	Method CParsePrimitiveNumberType:TType()
+		If CParse( "short" ) Return TType.shortType
+		If CParse( "byte" ) Return TType.byteType
+		If CParse( "int" ) Return TType.intType
+		If CParse( "float" ) Return TType.floatType
+		If CParse( "long" ) Return TType.intType ' BaH Long
+		If CParse( "double" ) Return TType.doubleType
+	End	Method
+
+	Method ParseNewType:TType()
+		If CParse( "void" ) Return TType.voidType
+		If CParse( "short" ) Return TType.shortType
+		If CParse( "byte" ) Return TType.byteType
+		If CParse( "int" ) Return TType.intType
+		If CParse( "float" ) Return TType.floatType
+		If CParse( "string" ) Return TType.stringType
+		If CParse( "object" ) Return TType.objectType
+		If CParse( "long" ) Return TType.intType ' BaH Long
+		If CParse( "double" ) Return TType.doubleType
+		Return ParseIdentType()
+	End Method
+
+	Method ParseType:TType()
+		Local ty:TType=CParsePrimitiveType()
+		If ty Return ty
+		Return ParseIdentType()
+	End Method
+
+	Method ParseConstNumberType:TType()
+		Local ty:TType
+		Select _toke
+		Case "%"
+			NextToke
+			ty=TType.intType
+		Case "#"
+			NextToke
+			ty=TType.floatType
+		Case "$"
+			NextToke
+			ty=TType.stringType
+		Case "!"
+			NextToke
+			ty=TType.doubleType
+		Case ":"
+			NextToke
+			ty=CParsePrimitiveNumberType()
+		End Select
+		
+		Return ty
+	End Method
+	
+	Method ParseDeclType:TType()
+		Local ty:TType
+		Select _toke
+		'Case "?"
+		'	NextToke
+		'	ty=TType.boolType
+		Case "%"
+			NextToke
+			ty=TType.intType
+
+			If CParse("var") Then
+				ty = TType.MapToVarPointerType(ty)
+			End If
+		Case "#"
+			NextToke
+			ty=TType.floatType
+
+			If CParse("var") Then
+				ty = TType.MapToVarPointerType(ty)
+			End If
+		Case "$"
+			NextToke
+			ty=TType.stringType
+
+			If CParse("var") Then
+				ty = TType.MapToVarPointerType(ty)
+			End If
+		Case "!"
+			NextToke
+			ty=TType.doubleType
+
+			If CParse("var") Then
+				ty = TType.MapToVarPointerType(ty)
+			End If
+		Case ":"
+			NextToke
+			ty=ParseType()
+
+			If CParse("ptr") Then
+				ty = TType.MapToPointerType(ty)
+
+				' pointer pointer
+				If CParse("ptr") Then
+					ty = TType.MapToPointerType(ty)
+				End If
+
+				If Not ty DoErr "Invalid Pointer type."
+			End If
+			
+			If CParse("var") Then
+				ty = TType.MapToVarPointerType(ty)
+			End If
+
+' TODO
+'		Case "!" ' BaH Double
+'			NextToke
+'			ty=TType.doubleType
+		Case "("
+			' nothing to see here.
+			If _module.IsSuperStrict() Then
+				' BaH : default return type when not defined
+				ty=TType.voidType
+			Else
+				ty=TType.intType
+			End If
+		Default
+			If _module.IsSuperStrict() Err "Illegal type expression."
+			ty=TType.intType
+			
+			If CParse("var") Then
+				ty = TType.MapToVarPointerType(ty)
+			End If
+		End Select
+		While CParse( "[]" )
+			ty=New TArrayType.Create( ty )
+		Wend
+		Return ty
+	End Method
+
+	Method ParseArrayExpr:TArrayExpr()
+		Parse "["
+		Local args:TExpr[],nargs:Int
+		Repeat
+			If CParse("..") Then
+				If Not CParse("~n") Then
+					Err "Expecting expression but encountered '..'"
+				End If
+			End If
+			Local arg:TExpr=ParseExpr()
+			If args.Length=nargs args=args + New TExpr[10]
+			args[nargs]=arg
+			nargs:+1
+		Until Not CParse(",")
+		args=args[..nargs]
+		Parse "]"
+		Return New TArrayExpr.Create( args )
+	End Method
+
+	Method ParseArgs:TExpr[]( stmt:Int )
+
+		Local args:TExpr[]
+'DebugStop
+		If stmt
+			If AtEos() Return args
+		Else
+			If _toke<>"(" Return args
+		EndIf
+
+		Local nargs:Int,eat:Int
+
+		If _toke="("
+			If stmt
+				Local toker:TToker=New TToker.Copy(_toker),bra:Int=1
+				Repeat
+					toker.NextToke
+					toker.SkipSpace
+					Select toker.Toke().ToLower()
+					Case "","else"
+						Err "Parenthesis mismatch error."
+					Case "(","["
+						bra:+1
+					Case "]",")"
+						bra:-1
+						If bra Continue
+						toker.NextToke
+						toker.SkipSpace
+						Select toker.Toke().ToLower()
+						Case ".","(","[","",";","~n","Else"
+							eat=True
+						End Select
+						Exit
+					Case ","
+						If bra<>1 Continue
+						eat=True
+						Exit
+					Case ".."
+						NextToke
+					End Select
+				Forever
+			Else
+				eat=True
+			EndIf
+			If eat And NextToke()=")"
+				NextToke
+				Return args
+			EndIf
+		EndIf
+
+		Repeat
+			Local arg:TExpr
+			If _toke And _toke<>"," arg=ParseExpr()
+			If args.Length=nargs args=args + New TExpr[10]
+			args[nargs]=arg
+			nargs:+1
+		Until Not CParse(",")
+		args=args[..nargs]
+
+		If eat Parse ")"
+
+		Return args
+	End Method
+
+	Method ParsePrimaryExpr:TExpr( stmt:Int )
+
+		Local expr:TExpr
+
+		Select _toke.ToLower()
+		Case "("
+			NextToke
+			expr=ParseExpr()
+			Parse ")"
+		Case "["
+			expr=ParseArrayExpr()
+		Case "[]"
+			NextToke
+			expr=New TConstExpr.Create( TType.emptyArrayType,"" )
+		Case "."
+			expr=New TScopeExpr.Create( _module )
+		Case "new"
+			NextToke
+			Local ty:TType=ParseType()
+			If CParse( "[" )
+				Local ln:TExpr=ParseExpr()
+				Parse "]"
+				While CParse( "[]" )
+					ty=New TArrayType.Create( ty)
+				Wend
+				expr=New TNewArrayExpr.Create( ty,ln )
+			Else
+				expr=New TNewObjectExpr.Create( ty,ParseArgs( stmt ) )
+			EndIf
+		Case "null"
+			NextToke
+			expr=New TConstExpr.Create( TType.nullObjectType,"" )
+		Case "true"
+			NextToke
+			expr=New TConstExpr.Create( TType.intType,"1" )
+		Case "false"
+			NextToke
+			expr=New TConstExpr.Create( TType.intType,"" )
+		Case "int","long","float","double","array","object","short","byte"
+
+			Local id$=_toke
+			Local ty:TType=ParseType()
+
+			If CParse("ptr") Then
+				ty = TType.MapToPointerType(ty)
+			End If
+
+			' optional brackets
+			If CParse( "(" )
+				expr=ParseExpr()
+				Parse ")"
+				expr=New TCastExpr.Create( ty,expr,CAST_EXPLICIT )
+			Else
+				expr=ParseExpr()
+'				Parse ")"
+				expr=New TCastExpr.Create( ty,expr,CAST_EXPLICIT )
+'				expr=New TIdentExpr.Create( id )
+			EndIf
+		Case "string"
+			Local id$=_toke
+			Local ty:TType=ParseType()
+
+			If CParse("ptr") Then
+				ty = TType.MapToPointerType(ty)
+			End If
+
+			If CParse( "(" )
+				expr=ParseExpr()
+				Parse ")"
+				expr=New TCastExpr.Create( ty,expr,CAST_EXPLICIT )
+			Else
+				expr=New TIdentExpr.Create( id )
+			EndIf
+			
+		Case "varptr"
+			NextToke
+			expr=ParseExpr()
+			expr=New TCastExpr.Create( TType.varPointerType, expr, CAST_EXPLICIT )
+		Case "self"
+			NextToke
+			expr=New TSelfExpr
+		Case "super"
+			NextToke
+			Parse "."
+			If _toke="new"
+				Err "Call to super class constructor must be first statement in a constructor."
+			EndIf
+			Local id$=ParseIdent()
+			expr=New TInvokeSuperExpr.Create( id,ParseArgs( stmt ) )
+		Case ".." ' handle end-of-line "dot dot return"
+			Local tok:TToker = New TToker.Copy(_toker)
+			Local t:String = tok.NextToke()
+			If t = "~r" Then
+				t = tok.NextToke()
+				If t = "~n" Then
+					NextToke
+					NextToke
+				Else
+					NextToke
+				End If
+			Else
+				If t = "~n" Then
+					NextToke
+				End If
+			End If
+
+			expr=ParseExpr()
+			
+			'NextToke
+			
+			'If Not CParse("~n") Then
+			'	Err "Expecting expression but encountered '..'"
+			'End If
+			'NextToke
+		Default
+			Select _tokeType
+			Case TOKE_IDENT
+				Local tok:TToker=New TToker.Copy( _toker )
+				
+				Local ty:TType=CParseIdentType()
+				If ty
+					expr=New TIdentTypeExpr.Create( ty )
+				Else
+					_toker=tok
+					_toke=_toker.Toke()
+					_tokeType=_toker.TokeType()
+					expr=New TIdentExpr.Create( ParseIdent() )
+					
+					ParseConstNumberType()
+				EndIf
+
+				'expr=New TIdentExpr.Create( ParseIdent() )
+			Case TOKE_INTLIT
+
+				expr=New TConstExpr.Create( TType.intType,_toke )
+				NextToke
+				
+				Local ty:TType = ParseConstNumberType()
+				If ty Then
+					TConstExpr(expr).ty = ty
+				End If
+			Case TOKE_LONGLIT
+				expr=New TConstExpr.Create( TType.longType,_toke )
+				NextToke
+			Case TOKE_FLOATLIT
+				expr=New TConstExpr.Create( TType.floatType,_toke )
+				NextToke
+			Case TOKE_STRINGLIT
+				expr=New TConstExpr.Create( TType.stringType,BmxUnquote( _toke ) )
+				_app.mapStringConsts(BmxUnquote( _toke ))
+				NextToke
+			Default
+				Err "Expecting expression but encountered '"+_toke+"'"
+			End Select
+		End Select
+
+		Repeat
+
+			Select _toke
+			Case "."
+'DebugLog "FOUND DOT for : " + expr.ToString() + " : " + _toker._line
+				NextToke
+				expr=New TIdentExpr.Create( ParseIdent(),expr )
+'DebugLog expr.ToString()
+			Case "("
+
+				If expr = Null Then
+					NextToke
+					expr=ParseExpr()
+					Parse ")"
+				Else
+					expr=New TFuncCallExpr.Create( expr,ParseArgs( stmt ) )
+				End If
+
+			Case "["
+
+				NextToke
+				If CParse( ".." )
+					If _toke="]"
+						expr=New TSliceExpr.Create( expr,Null,Null )
+					Else
+						expr=New TSliceExpr.Create( expr,Null,ParseExpr() )
+					EndIf
+				Else
+					Local from:TExpr=ParseExpr()
+					If CParse( ".." )
+						If _toke="]"
+							expr=New TSliceExpr.Create( expr,from,Null )
+						Else
+							expr=New TSliceExpr.Create( expr,from,ParseExpr() )
+						EndIf
+					Else
+						expr=New TIndexExpr.Create( expr,from )
+					EndIf
+				EndIf
+				Parse "]"
+			Default
+				Return expr
+			End Select
+		Forever
+
+	End Method
+
+	Method ParseUnaryExpr:TExpr()
+
+		SkipEols
+
+		Local op$=_toke
+		Select op
+		Case "+","-","~~","not"
+			NextToke
+			Local expr:TExpr=ParseUnaryExpr()
+			Return New TUnaryExpr.Create( op,expr )
+		End Select
+		Return ParsePrimaryExpr( False )
+	End Method
+
+	Method ParseMulDivExpr:TExpr()
+		Local expr:TExpr=ParseUnaryExpr()
+		Repeat
+			Local op$=_toke
+			Select op
+			Case "*","/","mod","shl","shr"
+				NextToke
+				Local rhs:TExpr=ParseUnaryExpr()
+				expr=New TBinaryMathExpr.Create( op,expr,rhs )
+			Case ".." ' handle end-of-line "dot dot return"
+				Local tok:TToker = New TToker.Copy(_toker)
+				Local t:String = tok.NextToke()
+				If t = "~r" Then
+					t = tok.NextToke()
+					If t = "~n" Then
+						NextToke
+						NextToke
+					Else
+						NextToke
+					End If
+				Else
+					If t = "~n" Then
+						NextToke
+					End If
+				End If
+				Return expr
+			Default
+				Return expr
+			End Select
+		Forever
+	End Method
+
+	Method ParseAddSubExpr:TExpr()
+		Local expr:TExpr=ParseMulDivExpr()
+		Repeat
+			Local op$=_toke
+			Select op
+			Case "+","-"
+				NextToke
+				Local rhs:TExpr=ParseMulDivExpr()
+				expr=New TBinaryMathExpr.Create( op,expr,rhs )
+			Default
+				Return expr
+			End Select
+		Forever
+	End Method
+
+	Method ParseBitandExpr:TExpr()
+		Local expr:TExpr=ParseAddSubExpr()
+		Repeat
+			Local op$=_toke
+			Select op
+			Case "&","~~"
+				NextToke
+				Local rhs:TExpr=ParseAddSubExpr()
+				expr=New TBinaryMathExpr.Create( op,expr,rhs )
+			Default
+				Return expr
+			End Select
+		Forever
+	End Method
+
+	Method ParseBitorExpr:TExpr()
+		Local expr:TExpr=ParseBitandExpr()
+		Repeat
+			Local op$=_toke
+			Select op
+			Case "|"
+				NextToke
+				Local rhs:TExpr=ParseBitandExpr()
+				expr=New TBinaryMathExpr.Create( op,expr,rhs )
+			Default
+				Return expr
+			End Select
+		Forever
+	End Method
+
+	Method ParseCompareExpr:TExpr()
+		Local expr:TExpr=ParseBitorExpr()
+		Repeat
+			Local op$=_toke
+			Select op
+			Case "=","<",">","<=",">=","<>"
+				NextToke
+				If op=">" And (_toke="=")
+					op:+_toke
+					NextToke
+				Else If op="<" And (_toke="=" Or _toke=">")
+					op:+_toke
+					NextToke
+				EndIf
+				Local rhs:TExpr=ParseBitorExpr()
+				expr=New TBinaryCompareExpr.Create( op,expr,rhs )
+			Default
+				Return expr
+			End Select
+		Forever
+	End Method
+
+	Method ParseAndExpr:TExpr()
+		Local expr:TExpr=ParseCompareExpr()
+		Repeat
+			Local op$=_toke
+			If op="and"
+				NextToke
+				Local rhs:TExpr=ParseCompareExpr()
+				expr=New TBinaryLogicExpr.Create( op,expr,rhs )
+			Else
+				Return expr
+			EndIf
+		Forever
+	End Method
+
+	Method ParseOrExpr:TExpr()
+		Local expr:TExpr=ParseAndExpr()
+		Repeat
+			Local op$=_toke
+			If op="or"
+				NextToke
+				Local rhs:TExpr=ParseAndExpr()
+				expr=New TBinaryLogicExpr.Create( op,expr,rhs )
+			Else
+				Return expr
+			EndIf
+		Forever
+	End Method
+
+	Method ParseExpr:TExpr()
+		Return ParseOrExpr()
+	End Method
+
+	Method ParseIfStmt( term$ )
+
+		CParse "if"
+'DebugStop
+		Local expr:TExpr=ParseExpr()
+
+		CParse "then"
+
+		Local thenBlock:TBlockDecl=New TBlockDecl.Create( _block )
+		Local elseBlock:TBlockDecl=New TBlockDecl.Create( _block )
+
+		Local eatTerm:Int
+		If Not term
+			If _toke="~n" term="end" Else term="~n"
+			eatTerm=True
+		EndIf
+
+		PushBlock thenBlock
+		While _toke<>term
+			Select _toke
+			Case "endif"
+				If term="end" Exit
+				Err "Syntax error - expecting 'End'."
+			Case "else","elseif"
+				Local elif:Int=_toke="elseif"
+				NextToke
+				If _block=elseBlock
+					Err "If statement can only have one 'else' block."
+				EndIf
+				PopBlock
+				PushBlock elseBlock
+				If elif Or _toke="if"
+					ParseIfStmt term
+				EndIf
+			Default
+				ParseStmt
+			End Select
+		Wend
+		PopBlock
+
+		If eatTerm
+			NextToke
+			If term="end" CParse "if"
+		EndIf
+
+		Local stmt:TIfStmt=New TIfStmt.Create( expr,thenBlock,elseBlock )
+
+		_block.AddStmt stmt
+	End Method
+
+	Method ParseWhileStmt()
+
+		Parse "while"
+
+		Local expr:TExpr=ParseExpr()
+		Local block:TBlockDecl=New TBlockDecl.Create( _block )
+
+		PushBlock block
+		While Not CParse( "wend" )
+			If CParse( "end" )
+				CParse "while"
+				Exit
+			EndIf
+			ParseStmt
+		Wend
+		PopBlock
+
+		Local stmt:TWhileStmt=New TWhileStmt.Create( expr,block )
+
+		_block.AddStmt stmt
+	End Method
+
+	Method ParseRepeatStmt()
+
+		Parse "repeat"
+
+		Local block:TBlockDecl=New TBlockDecl.Create( _block )
+
+		PushBlock block
+		While _toke<>"until" And _toke<>"forever"
+			ParseStmt
+		Wend
+		PopBlock
+
+		SetErr
+
+		Local expr:TExpr
+		If CParse( "until" )
+			expr=ParseExpr()
+		Else
+			Parse "forever"
+			expr=New TConstExpr.Create( TType.boolType,"" )
+		EndIf
+
+		Local stmt:TRepeatStmt=New TRepeatStmt.Create( block,expr )
+
+		_block.AddStmt stmt
+	End Method
+
+	Method ParseForStmt()
+'DebugStop
+		Parse "for"
+
+		Local varid$,varty:TType,varlocal:Int
+
+		If CParse( "local" )
+			varlocal=True
+			varid=ParseIdent()
+			'If Not CParse( ":=" )
+				varty=ParseDeclType()
+				Parse( "=" )
+			'EndIf
+		Else
+			varlocal=False
+			varid=ParseIdent()
+			Parse "="
+		EndIf
+
+		If CParse( "eachin" )
+			Local expr:TExpr=ParseExpr()
+			Local block:TBlockDecl=New TBlockDecl.Create( _block )
+
+			PushBlock block
+			While Not CParse( "next" )
+				If CParse( "end" )
+					CParse "for"
+					Exit
+				EndIf
+				ParseStmt
+			Wend
+			PopBlock
+
+			Local stmt:TForEachinStmt=New TForEachinStmt.Create( varid,varty,varlocal,expr,block )
+
+			_block.AddStmt stmt
+
+			Return
+		EndIf
+
+		Local from:TExpr=ParseExpr()
+
+		Local op$
+		If CParse( "to" )
+			op="<="
+		Else If CParse( "until" )
+			op="<"
+		Else
+			Err "Expecting 'To' or 'Until'."
+		EndIf
+
+		Local term:TExpr=ParseExpr()
+
+		Local stp:TExpr
+
+		If CParse( "step" )
+			stp=ParseExpr()
+		Else
+			stp=New TConstExpr.Create( TType.intType,"1" )
+		EndIf
+
+		Local init:TStmt,expr:TExpr,incr:TStmt
+
+		If varlocal
+			Local indexVar:TLocalDecl=New TLocalDecl.Create( varid,varty,from,0 )
+			init=New TDeclStmt.Create( indexVar )
+			expr=New TBinaryCompareExpr.Create( op,New TVarExpr.Create( indexVar ),term )
+			incr=New TAssignStmt.Create( "=",New TVarExpr.Create( indexVar ),New TBinaryMathExpr.Create( "+",New TVarExpr.Create( indexVar ),stp ) )
+		Else
+			init=New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),from )
+			expr=New TBinaryCompareExpr.Create( op,New TIdentExpr.Create( varid ),term )
+			incr=New TAssignStmt.Create( "=",New TIdentExpr.Create( varid ),New TBinaryMathExpr.Create( "+",New TIdentExpr.Create( varid ),stp ) )
+		EndIf
+
+		Local block:TBlockDecl=New TBlockDecl.Create( _block )
+
+		PushBlock block
+		While Not CParse( "next" )
+			If CParse( "end" )
+				CParse "for"
+				Exit
+			EndIf
+			ParseStmt
+		Wend
+		PopBlock
+
+		NextToke
+
+		Local stmt:TForStmt=New TForStmt.Create( init,expr,incr,block )
+
+		_block.AddStmt stmt
+	End Method
+
+	Method ParseReturnStmt()
+		Parse "return"
+		Local expr:TExpr
+		If Not AtEos() expr=ParseExpr()
+		_block.AddStmt New TReturnStmt.Create( expr )
+	End Method
+
+	Method ParseExitStmt()
+		Parse "exit"
+		_block.AddStmt New TBreakStmt
+	End Method
+
+	Method ParseContinueStmt()
+		Parse "continue"
+		_block.AddStmt New TContinueStmt
+	End Method
+
+	Method ParseTryStmt()
+		Err "TODO : ParseTryStmt"
+	End Method
+	
+	Method ParseThrowStmt()
+		Parse "throw"
+		Local expr:TExpr = ParseExpr()
+		_block.AddStmt New TThrowStmt.Create( expr )
+	End Method
+
+	Method ParseAssertStmt()
+		Parse "assert"
+		Local expr:TExpr = ParseExpr()
+		Local elseExpr:TExpr
+		
+		If _toke = "," Or _toke = "else" Then
+			NextToke
+			elseExpr = ParseExpr()
+		End If
+		
+		_block.AddStmt New TAssertStmt.Create( expr, elseExpr )
+	End Method
+
+	Method ParseSelectStmt()
+		Parse "select"
+
+		Local block:TBlockDecl=_block
+
+		Local tmpVar:TLocalDecl=New TLocalDecl.Create( "",Null,ParseExpr() )
+
+		block.AddStmt New TDeclStmt.Create( tmpVar )
+
+		While _toke<>"end" And _toke<>"default"
+			SetErr
+			Select _toke
+			Case "~n"
+				NextToke
+			Case "case"
+				NextToke
+				Local comp:TExpr
+				Repeat
+					Local expr:TExpr=New TVarExpr.Create( tmpVar )
+					expr=New TBinaryCompareExpr.Create( "=",expr,ParseExpr() )
+					If comp
+						comp=New TBinaryLogicExpr.Create( "or",comp,expr )
+					Else
+						comp=expr
+					EndIf
+				Until Not CParse(",")
+
+				Local thenBlock:TBlockDecl=New TBlockDecl.Create( _block )
+				Local elseBlock:TBlockDecl=New TBlockDecl.Create( _block )
+
+				Local ifstmt:TIfStmt=New TIfStmt.Create( comp,thenBlock,elseBlock )
+				block.AddStmt ifstmt
+				block=ifstmt.thenBlock
+
+				PushBlock block
+				While _toke<>"case" And _toke<>"default" And _toke<>"end"
+					ParseStmt
+				Wend
+				PopBlock
+
+				block=elseBlock
+			Default
+				Err "Syntax error - expecting 'Case', 'Default' or 'End'."
+			End Select
+		Wend
+
+		If _toke="default"
+			NextToke
+			PushBlock block
+			While _toke<>"end"
+				SetErr
+				Select _toke
+				Case "case"
+					Err "Case can not appear after default."
+				Case "default"
+					Err "Select statement can have only one default block."
+				End Select
+				ParseStmt
+			Wend
+			PopBlock
+		EndIf
+
+		SetErr
+		Parse "end"
+		CParse "select"
+	End Method
+
+	Method ParseRemStmt()
+		Parse "rem"
+
+' TODO : end/rem should be at the beginning of a line... ignore otherwise
+		While _toke
+			SkipEols()
+'			If CParse( "endrem" ) Then
+'DebugStop
+			 	Local line:String = _toker._lines[_toker._line - 1].Trim().toLower()
+				If line.startswith("endrem") Then
+					Exit
+				End If
+
+				If CParse( "end" )
+					CParse "rem"
+				End If
+
+				If line.startswith("end rem") Then
+					Exit
+				End If
+
+'			EndIf
+			NextToke
+		Wend
+
+		NextToke
+
+	End Method
+
+	Method ParseStmt()
+		SetErr
+		Select _toke
+		Case ";","~n"
+			NextToke
+		Case "rem"
+			ParseRemStmt()
+		Case "const","local"
+			ParseDeclStmts
+		Case "return"
+			ParseReturnStmt()
+		Case "exit"
+			ParseExitStmt()
+		Case "continue"
+			ParseContinueStmt()
+		Case "if"
+			ParseIfStmt( "" )
+		Case "while"
+			ParseWhileStmt()
+		Case "repeat"
+			ParseRepeatStmt()
+		Case "for"
+			ParseForStmt()
+		Case "select"
+			ParseSelectStmt()
+		Case "assert"
+			ParseAssertStmt()
+		Case "try"
+			ParseTryStmt()
+		Case "throw"
+			ParseThrowStmt()
+		Default
+'If _toker._line = 246 Then
+'DebugStop
+'End If
+			Local expr:TExpr=ParsePrimaryExpr( True )
+
+			Select _toke.ToLower()
+			'"=","*=","/=","+=","-=","&=","|=","~~=","mod","shl","shr"
+			Case "=",":*",":/",":+",":-",":&",":|",":~~","mod","shl","shr", ":shl", ":shr"
+'DebugLog _toke
+				' 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]
+'DebugLog _toke
+						Exit
+					EndIf
+				Next
+
+
+				If TIdentExpr( expr ) Or TIndexExpr( expr )
+					Local op$=_toke
+					NextToke
+					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."
+				EndIf
+				Return
+			End Select
+
+			If TIdentExpr( expr )
+
+				expr=New TFuncCallExpr.Create( expr,ParseArgs( True ) )
+
+			Else If TFuncCallExpr( expr) Or TInvokeSuperExpr( expr ) Or TNewObjectExpr( expr )
+
+			Else
+				Err "Expression cannot be used as a statement."
+			EndIf
+
+			_block.AddStmt New TExprStmt.Create( expr )
+
+		End Select
+	End Method
+
+	Method ParseDecl:TDecl( toke$,attrs:Int )
+		SetErr
+		Local id$=ParseIdent()
+		Local ty:TType
+		Local init:TExpr
+'If id = "StandardIOStream" DebugStop
+		If attrs & DECL_EXTERN
+			ty=ParseDeclType()
+
+'			If CParse("(") Then
+			If _toke = "(" Then
+'DebugStop
+				' function pointer?
+				Local decl:TFuncDecl = ParseFuncDecl("", attrs | FUNC_PTR)
+
+				If Not ty Then
+					ty = New TFunctionPtrType
+					TFunctionPtrType(ty).func = decl
+				Else
+					decl.retType = ty
+					ty = New TFunctionPtrType
+					TFunctionPtrType(ty).func = decl
+				End If
+
+				TFunctionPtrType(ty).func.ident = id
+			Else If toke = "const" Then
+				If CParse("=") Then
+					init=ParseExpr()
+				End If
+			End If
+		Else If CParse( ":=" )
+			init=ParseExpr()
+		Else
+			ty=ParseDeclType()
+			If CParse( "=" )
+				init=ParseExpr()
+			Else If CParse( "[" )
+				Local ln:TExpr=ParseExpr()
+				Parse "]"
+				While CParse( "[]" )
+					ty=New TArrayType.Create(ty)
+				Wend
+				init=New TNewArrayExpr.Create( ty,ln)
+				ty=New TArrayType.Create( ty )
+			Else If _toke = "(" Then
+	 			' function pointer?
+
+				Local fdecl:TFuncDecl = ParseFuncDecl("", FUNC_PTR)
+
+				If Not ty Then
+					ty = New TFunctionPtrType
+					TFunctionPtrType(ty).func = fdecl
+				Else
+					fdecl.retType = ty
+					ty = New TFunctionPtrType
+					TFunctionPtrType(ty).func = fdecl
+				End If
+
+				TFunctionPtrType(ty).func.ident = ""
+
+			Else If toke<>"const"
+				init=New TConstExpr.Create( ty,"" )
+			Else
+				Err "Constants must be initialized."
+			EndIf
+		EndIf
+
+		Local decl:TValDecl
+
+		Select toke
+		Case "global" decl=New TGlobalDecl.Create( id,ty,init,attrs )
+		Case "field"  decl=New TFieldDecl.Create( id,ty,init,attrs )
+		Case "const"  decl=New TConstDecl.Create( id,ty,init,attrs )
+		Case "local"  decl=New TLocalDecl.Create( id,ty,init,attrs )
+		End Select
+
+		If decl.IsExtern()
+			If CParse( "=" )
+				decl.munged=ParseStringLit()
+			Else
+				decl.munged=decl.ident
+			EndIf
+		EndIf
+
+		Return decl
+	End Method
+
+	Method ParseDecls:TList( toke$,attrs:Int )
+		If toke Parse toke
+
+		Local decls:TList=New TList'<Decl>
+		Repeat
+			Local decl:TDecl=ParseDecl( toke,attrs )
+			decls.AddLast decl
+			If Not CParse(",") Return decls
+		Forever
+	End Method
+
+	Method ParseDeclStmts()
+		Local toke$=_toke
+		NextToke
+		Repeat
+			Local decl:TDecl=ParseDecl( toke,0 )
+			_block.AddStmt New TDeclStmt.Create( decl )
+		Until Not CParse(",")
+	End Method
+
+	Method ParseFuncDecl:TFuncDecl( toke$,attrs:Int )
+		SetErr
+
+		If toke Parse toke
+
+		Local id$
+		Local ty:TType
+		Local meth:Int = attrs & FUNC_METHOD
+
+		If attrs & FUNC_METHOD
+			If _toke="new"
+'DebugStop
+				If attrs & DECL_EXTERN
+					Err "Extern classes cannot have constructors"
+				EndIf
+				id=_toke
+				NextToke
+				attrs:|FUNC_CTOR
+				attrs:&~FUNC_METHOD
+			Else
+				id=ParseIdent()
+'If id = "Flush" DebugStop
+				ty=ParseDeclType()
+			EndIf
+		Else
+			If Not (attrs & FUNC_PTR) Then
+				id=ParseIdent()
+				ty=ParseDeclType()
+			End If
+		EndIf
+
+		Local args:TArgDecl[]
+'If _toker._line = 63 DebugStop
+		Parse "("
+		SkipEols
+		If _toke<>")"
+			Local nargs:Int
+			Repeat
+				If _toke =".." ' handle end-of-line "dot dot return"
+					Local tok:TToker = New TToker.Copy(_toker)
+					Local t:String = tok.NextToke()
+					If t = "~r" Then
+						t = tok.NextToke()
+						If t = "~n" Then
+							NextToke
+							NextToke
+						Else
+							NextToke
+						End If
+					End If
+				End If
+
+				Local id$=ParseIdent()
+'If id = "Flush" Then
+'DebugStop
+'End If
+				Local ty:TType=ParseDeclType()
+				Local init:TExpr
+				' function pointer ?
+				If _toke = "(" Then
+
+					Local fdecl:TFuncDecl = ParseFuncDecl("", FUNC_PTR)
+
+					If Not ty Then
+						ty = New TFunctionPtrType
+						TFunctionPtrType(ty).func = fdecl
+					Else
+						fdecl.retType = ty
+						ty = New TFunctionPtrType
+						TFunctionPtrType(ty).func = fdecl
+					End If
+
+					TFunctionPtrType(ty).func.ident = id
+
+				End If
+				If CParse( "=" ) init=ParseExpr()
+				Local arg:TArgDecl=New TArgDecl.Create( id,ty,init )
+				If args.Length=nargs args=args + New TArgDecl[10]
+				args[nargs]=arg
+				nargs:+1
+				If _toke=")" Exit
+
+				If _toke =".." ' handle end-of-line "dot dot return"
+					Local tok:TToker = New TToker.Copy(_toker)
+					Local t:String = tok.NextToke()
+					If t = "~r" Then
+						t = tok.NextToke()
+						If t = "~n" Then
+							NextToke
+							NextToke
+						Else
+							NextToke
+						End If
+					End If
+				End If
+
+				Parse ","
+			Forever
+			args=args[..nargs]
+		EndIf
+		Parse ")"
+
+		Repeat
+			If CParse( "final" )
+				attrs:|DECL_FINAL
+			Else If CParse( "abstract" )
+				attrs:|DECL_ABSTRACT
+			Else If CParse( "property" )
+				If attrs & FUNC_METHOD
+					attrs:|FUNC_PROPERTY
+				Else
+					Err "Only methods can be properties."
+				EndIf
+			Else
+				Exit
+			EndIf
+		Forever
+If Not ty Then
+'DebugStop
+End If
+		Local funcDecl:TFuncDecl=New TFuncDecl.CreateF( id,ty,args,attrs )
+
+		If funcDecl.IsExtern() Or (attrs & FUNC_PTR)
+			funcDecl.munged=funcDecl.ident
+			If CParse( "=" )
+				funcDecl.munged=ParseStringLit()
+
+				'Array $resize hack!
+				'If funcDecl.munged="$resize"
+				'	funcDecl.retTypeExpr=TType.emptyArrayType
+				'EndIf
+
+			EndIf
+
+			If funcDecl.munged Then
+				' look up extern cast list
+				Local cdets:TCastDets = TCastDets(_externCasts.ValueForKey(funcDecl.munged))
+				If cdets Then
+					funcDecl.castTo = cdets.retType
+					If cdets.noGen Then
+						funcDecl.noCastGen = True
+					End If
+					For Local i:Int = 0 Until cdets.args.length
+						funcDecl.argDecls[i].castTo = cdets.args[i]
+					Next
+				End If
+			End If
+
+			Return funcDecl
+		EndIf
+
+		If funcDecl.IsAbstract() Return funcDecl
+
+		'Ok, only first statement of a constructor can call super constructor - not pretty, should be in semant.
+		If attrs & FUNC_CTOR
+			SkipEols
+			If CParse( "super" )
+				Parse "."
+				If _toke="new"
+					Local id$=_toke
+					NextToke
+					funcDecl.superCtor=New TInvokeSuperExpr.Create( id,ParseArgs( True ) )
+					funcDecl.AddStmt New TExprStmt.Create( funcDecl.superCtor )
+				Else
+					Local id$=ParseIdent()
+					funcDecl.AddStmt New TExprStmt.Create( New TInvokeSuperExpr.Create( id,ParseArgs( True ) ) )
+				EndIf
+			Else
+					'Invoke super default ctor
+					'funcDecl.superCtor=New InvokeSuperExpr( "new",[] )
+					'funcDecl.AddStmt New TExprStmt( funcDecl.superCtor )
+			EndIf
+		EndIf
+
+		PushBlock funcDecl
+		While (Not meth And _toke<>"endfunction") Or (meth And _toke<>"endmethod")
+			If CParse( "end" )
+				If (Not meth And CParse("function")) Or (meth And CParse("method"))
+					Exit
+				End If
+			EndIf
+
+			ParseStmt
+		Wend
+		PopBlock
+
+		'DebugStop ' BaH
+
+		NextToke
+		If toke CParse toke
+
+		Return funcDecl
+	End Method
+
+	Method ParseClassDecl:TClassDecl( toke$,attrs:Int )
+		SetErr
+
+		If toke Parse toke
+
+		Local id$=ParseIdent()
+		Local args:TClassDecl[]
+		Local superTy:TIdentType
+		Local imps:TIdentType[]
+
+		If (attrs & CLASS_INTERFACE) And (attrs & DECL_EXTERN)
+			Err "Interfaces cannot be extern."
+		EndIf
+Rem
+		If CParse( "<" )
+
+			If attrs & DECL_EXTERN
+				Err "Extern classes cannot be generic."
+			EndIf
+
+			If attrs & CLASS_INTERFACE
+				Err "Interfaces cannot be generic."
+			EndIf
+
+			If attrs & CLASS_TEMPLATEARG
+				Err "Class parameters cannot be generic."
+			EndIf
+
+			Local nargs:Int
+			Repeat
+				Local decl:TClassDecl=ParseClassDecl( "",CLASS_TEMPLATEARG )
+				If args.Length=nargs args=args + New TClassDecl[10]
+				args[nargs]=decl
+				nargs:+1
+			Until Not CParse(",")
+			args=args[..nargs]
+
+			Parse ">"
+		EndIf
+End Rem
+		If CParse( "extends" )
+
+			'If attrs & CLASS_TEMPLATEARG
+			'	Err "Extends cannot be used with class parameters."
+			'EndIf
+
+			If CParse( "null" )
+
+				If attrs & CLASS_INTERFACE
+					Err "Interfaces cannot extend null"
+				EndIf
+
+				If Not (attrs & DECL_EXTERN)
+					Err "Only extern objects can extend null."
+				EndIf
+
+				superTy=Null
+
+			Else If attrs & CLASS_INTERFACE
+
+				Local nimps:Int
+				Repeat
+					If imps.Length=nimps imps=imps + New TIdentType[10]
+					imps[nimps]=ParseIdentType()
+					nimps:+1
+				Until Not CParse(",")
+				imps=imps[..nimps]
+				superTy=TType.objectType
+			Else
+				superTy=ParseIdentType()
+			EndIf
+		Else
+			superTy=TType.objectType
+		EndIf
+Rem
+		If CParse( "implements" )
+
+			If attrs & DECL_EXTERN
+				Err "Implements cannot be used with external classes."
+			EndIf
+
+			If attrs & CLASS_INTERFACE
+				Err "Implements cannot be used with interfaces."
+			EndIf
+
+			If attrs & CLASS_TEMPLATEARG
+				Err "Implements cannot be used with class parameters."
+			EndIf
+
+			Local nimps:Int
+			Repeat
+				If imps.Length=nimps imps=imps + New TIdentType[10]
+				imps[nimps]=ParseIdentType()
+				nimps:+1
+			Until Not CParse(",")
+			imps=imps[..nimps]
+		EndIf
+End Rem
+		Repeat
+			If CParse( "final" )
+
+				If attrs & CLASS_INTERFACE
+					Err "Final cannot be used with interfaces."
+				EndIf
+
+				attrs:|DECL_FINAL
+
+			Else If CParse( "abstract" )
+
+				If attrs & CLASS_INTERFACE
+					Err "Abstract cannot be used with interfaces."
+				EndIf
+
+				attrs:|DECL_ABSTRACT
+			Else
+				Exit
+			EndIf
+		Forever
+
+		Local classDecl:TClassDecl=New TClassDecl.Create( id,args,superTy,imps,attrs )
+
+		If classDecl.IsExtern()
+			classDecl.munged=classDecl.ident
+			If CParse( "=" ) classDecl.munged=ParseStringLit()
+		EndIf
+
+		'If classDecl.IsTemplateArg() Return classDecl
+
+		Local decl_attrs:Int=(attrs & DECL_EXTERN)
+
+		Local method_attrs:Int=decl_attrs|FUNC_METHOD
+		If attrs & CLASS_INTERFACE method_attrs:|DECL_ABSTRACT
+
+		Repeat
+			SkipEols
+			Select _toke
+			Case "end"
+				NextToke
+				Exit
+			Case "private"
+				NextToke
+				decl_attrs=decl_attrs | DECL_PRIVATE
+			Case "public"
+				NextToke
+				decl_attrs=decl_attrs & ~DECL_PRIVATE
+			Case "const","global","field"
+				If (attrs & CLASS_INTERFACE) And _toke<>"const"
+					Err "Interfaces can only contain constants and methods."
+				EndIf
+				classDecl.InsertDecls ParseDecls( _toke,decl_attrs )
+			Case "method"
+				Local decl:TFuncDecl=ParseFuncDecl( _toke,method_attrs )
+				If decl.IsCtor() decl.retTypeExpr=New TObjectType.Create( classDecl )
+				classDecl.InsertDecl decl
+			Case "function"
+				If (attrs & CLASS_INTERFACE) And _toke<>"const"
+					Err "Interfaces can only contain constants and methods."
+				EndIf
+				Local decl:TFuncDecl=ParseFuncDecl( _toke,decl_attrs )
+				classDecl.InsertDecl decl
+			Case "rem"
+				ParseRemStmt()
+			Default
+				Err "Syntax error - expecting class member declaration, not '" + _toke + "'"
+			End Select
+		Forever
+
+		If toke CParse toke
+
+		Return classDecl
+	End Method
+
+	Method ParseModuleDecl:String( toke$,attrs:Int )
+		NextToke
+
+		' namespace . module
+		Return ParseModPath().ToLower()
+	End Method
+
+	Method ParseModPath$()
+		Local path$=ParseIdent()
+		While CParse( "." )
+			path:+"."+ParseIdent()
+		Wend
+		Return path
+	End Method
+
+	Method ExtractModIdent$( modpath$ )
+		Local i:Int=modpath.FindLast( "." )
+		If i<>-1 Return modpath[i+1..]
+		Return modpath
+	End Method
+
+	Method ImportFile( filepath$ )
+		
+		If filepath.Endswith(".bmx") Then
+
+			Local path:String = RealPath(filepath)
+			path = OutputFilePath(path, FileMung(), "i")
+	
+			If FileType( path )<>FILETYPE_FILE
+				Err "File '"+ path +"' not found."
+			EndIf
+	
+			
+			If _module.imported.Contains( path ) Return
+	
+			' try to import interface
+			Local par:TIParser = New TIParser
+	
+			If par.ParseModuleImport(_module, "", "", path, , , filepath) Return
+		Else
+			If filepath.startswith("-") Then
+				_app.fileimports.AddLast filepath
+			End If
+		End If
+		
+	End Method
+
+	Method ImportModule( modpath$,attrs:Int )
+' TODO
+
+		modpath = modpath.ToLower()
+		Local basepath:String = ModulePath(modpath.ToLower())
+
+
+'DebugStop
+
+Rem
+		Local filepath$
+
+		Local cd$=CurrentDir()
+		ChangeDir ExtractDir( _toker.Path() )
+
+		For Local dir:String=EachIn ENV_MODPATH.Split( ";" )
+
+			filepath=RealPath( dir )+"/"+modpath.Replace( ".","/" )+"."+FILE_EXT			'/blah/etc.monkey
+			Local filepath2$=StripExt( filepath )+"/"+StripDir( filepath )					'/blah/etc/etc.monkey
+
+			If FileType( filepath )=FILETYPE_FILE
+				If FileType( filepath2 )<>FILETYPE_FILE Exit
+				Err "Duplicate module file: '"+filepath+"' and '"+filepath2+"'."
+			EndIf
+
+			filepath=filepath2
+			If FileType( filepath )=FILETYPE_FILE Exit
+
+			filepath=""
+		Next
+
+		ChangeDir cd
+
+		If Not filepath Err "Module '"+modpath+"' not found."
+
+		'Note: filepath needs to be an *exact* match.
+		'
+		'Would be nice to have a version of realpath that fixed case and normalized separators for this.
+		'
+		'Currently, frontend is assumed to have done this with main src path, proj dir and mod dir.
+End Rem
+		If _module.imported.Contains( basepath ) Return
+
+		' try to import interface
+		Local par:TIParser = New TIParser
+
+		If par.ParseModuleImport(_module, modpath, basepath, , , attrs) Return
+
+'DebugStop
+
+		'Local mdecl:TDecl=_app.imported.ValueForKey( basepath )
+
+		'If Not mdecl
+		'	mdecl=ParseModule( filepath,_app )
+		'EndIf
+
+		'_module.imported.Insert mdecl.filepath,mdecl
+
+		'If Not (attrs & DECL_PRIVATE) _module.pubImported.Insert mdecl.filepath,mdecl
+
+		'_module.InsertDecl New AliasDecl( mdecl.ident,mdecl,attrs )
+'End Rem
+	End Method
+
+	Method ValidateModIdent( id$ )
+		If id.Length
+			If IsAlpha( id[0] ) Or id[0]="_"[0]
+				Local err:Int
+				For Local i:Int=1 Until id.Length
+					If IsAlpha( id[i] ) Or IsDigit( id[i] ) Or id[i]="_"[0] Continue
+					err=1
+					Exit
+				Next
+				If Not err Return
+			EndIf
+		EndIf
+		Err "Invalid module identifier '"+id+"'."
+	End Method
+
+	Method MungAppDecl(app:TAppDecl)
+		If opt_buildtype = BUILDTYPE_MODULE And opt_ismain Then
+			app.munged = MungModuleName(opt_modulename)
+		Else
+			' main application file?
+			If opt_apptype Then
+				app.munged = "_bb_main"
+			Else
+				Local dir:String = ExtractDir(opt_filepath).ToLower()
+				dir = dir[dir.findLast("/") + 1..]
+				If dir.EndsWith(".mod") Then
+					dir = dir.Replace(".mod", "")
+				End If
+				dir = dir.Replace(".", "_")
+				Local file:String = StripDir(opt_filepath).ToLower()
+				app.munged = "bb_" + dir + "_" + StripExt(file)
+			End If
+		End If
+	End Method
+
+	' load external cast defs
+	Method LoadExternCasts(path:String)
+	
+		path = StripExt(path) + ".x"
+
+		If FileType(path) = FILETYPE_FILE Then
+
+			Local toker:TToker=New TToker.Create( path,LoadString( path ) )
+			toker.NextToke
+			
+			While True
+			
+				SkipEolsToker(toker)
+				
+				If toker._tokeType = TOKE_EOF Exit
+				
+				Local rt$=toker._toke
+				NextTokeToker(toker)
+				If CParseToker(toker,"*") Then
+					rt:+ "*"
+					
+					If CParseToker(toker,"*") Then
+						rt:+ "*"
+					End If
+				End If
+				
+				
+				Local dets:TCastDets = New TCastDets
+				
+				' fname
+				Local fn$=toker._toke
+				NextTokeToker(toker)
+				
+				dets.name = fn
+				dets.retType = rt
+				
+				_externCasts.Insert(fn, dets)
+				
+				' args
+				ParseToker(toker, "(")
+	
+				If CParseToker(toker, ")") Then
+				
+					NextTokeToker(toker)
+					
+					' don't generate header extern
+					If CParseToker(toker, "!") Then
+						dets.noGen = True
+					End If
+					
+					Continue
+				End If
+	
+				Local i:Int = 0			
+				Repeat
+					Local at$=toker._toke
+					
+					If CParseToker(toker, "const") Then
+						at :+ " " + toker._toke
+					End If
+					
+					If CParseToker(toker, "unsigned") Then
+						at :+ " " + toker._toke
+					End If
+					
+					NextTokeToker(toker)
+					If CParseToker(toker, "*") Then
+						at:+ "*"
+						
+						If CParseToker(toker, "*") Then
+							at:+ "*"
+						End If
+					End If
+					
+					' function pointer
+					If CParseToker(toker, "(") Then
+
+						ParseToker(toker, "*")
+						ParseToker(toker, ")")
+						at :+ "(*)"
+						
+						ParseToker(toker, "(")
+						at :+ "("
+						
+						While Not CParseToker(toker, ")")
+							NextTokeToker(toker)
+							at :+ toker._toke
+						Wend
+						
+						at :+ ")"
+					End If
+					
+
+					dets.args :+ [at]
+				
+					If toker._toke=")" Exit
+					ParseToker(toker, ",")
+					
+					i:+ 1
+				Forever
+				
+				NextTokeToker(toker)
+			
+				' don't generate header extern
+				If CParseToker(toker, "!") Then
+					dets.noGen = True
+				End If
+			
+			Wend
+		
+		End If
+	
+	End Method
+
+	Method ParseMain()
+
+		SkipEols
+
+		Local mattrs:Int
+		'If CParse( "strict" ) mattrs:|MODULE_STRICT
+		'If CParse( "superstrict" ) mattrs:|MODULE_SUPERSTRICT
+
+
+		Local path$=_toker.Path()
+		Local ident$=StripAll( path )
+		Local munged$	'="bb_"+ident+"_"
+
+		If opt_buildtype = BUILDTYPE_MODULE And opt_ismain
+			ValidateModIdent ident
+		End If
+		
+		If opt_ismain Then 'And opt_modulename <> "brl.blitz" Then
+			ident = opt_modulename
+		End If
+
+		_module=New TModuleDecl.Create( ident,munged,path,mattrs )
+
+		_module.imported.Insert path,_module
+
+		_app.InsertModule _module
+
+		' mung the app decl
+		MungAppDecl(_app)
+
+
+		If opt_buildtype = BUILDTYPE_MODULE And opt_modulename = "brl.blitz" Then
+			' import Object and String definitions
+			Local par:TIParser = New TIParser
+			par.ParseModuleImport(_module, "brl.classes", modulepath("brl.blitz"), "blitz_classes.i")
+	
+			' set up built-in keywords
+			par = New TIParser
+			par.ParseModuleImport(_module, "brl.blitzkeywords", "", "", MakeKeywords())
+		End If
+
+		' don't import ourself
+		If opt_buildtype = BUILDTYPE_MODULE And opt_modulename <> "brl.blitz" Then
+			Local par:TIParser = New TIParser
+			par.ParseModuleImport(_module, "brl.blitz", modulepath("brl.blitz"), , , MODULE_ACTUALMOD)
+		End If
+
+		LoadExternCasts(path)
+
+		Local attrs:Int
+
+
+		Local mainFunc:TFuncDecl = New TFuncDecl.CreateF("LocalMain", New TIntType,Null,0)
+'DebugStop
+		'_app.InsertDecl mainFunc
+		_module.insertDecl(mainFunc)
+		'Local mainBlock:TBlockDecl = New TBlockDecl.Create( _block )
+
+		'Parse header - imports etc.
+		While _toke
+			SetErr
+			Select _toke.ToLower()
+			Case "~n", ".."
+				NextToke
+			Case "public"
+				NextToke
+				attrs=0
+			Case "private"
+				NextToke
+				attrs=DECL_PRIVATE
+			Case "import"
+				NextToke
+				If _tokeType=TOKE_STRINGLIT
+' TODO
+					'ImportFile ReplaceEnvTags( ParseStringLit() )
+					ImportFile ParseStringLit()
+				Else
+					ImportModule ParseModPath(),attrs | MODULE_ACTUALMOD
+				EndIf
+			Case "framework"
+				NextToke
+				ImportModule ParseModPath(),attrs
+			Case "alias"
+				NextToke
+				Repeat
+					Local ident$=ParseIdent()
+					Parse "="
+
+					Local decl:Object
+					Local scope:TScopeDecl=_module
+
+					_env=_module	'naughty! Shouldn't be doing GetDecl in parser...
+
+					Repeat
+						Local id$=ParseIdent()
+						decl=scope.FindDecl( id )
+						If Not decl Err "Identifier '"+id+"' not found."
+						If Not CParse( "." ) Exit
+						scope=TScopeDecl( decl )
+						If Not scope Or TFuncDecl( scope ) Err "Invalid scope '"+id+"'."
+					Forever
+
+					_env=Null	'/naughty
+
+					_module.InsertDecl New TAliasDecl.Create( ident,decl,attrs )
+
+				Until Not CParse(",")
+			Case "module"
+				Local m:String = ParseModuleDecl(_toke, attrs)
+
+				If m.ToLower() <> opt_modulename Then
+					Err "Module does not match commandline module"
+				End If
+
+				_module.munged = m.Replace(".", "_")
+			Case "rem"
+				ParseRemStmt()
+			Case "nodebug"
+				NextToke
+			Case "strict"
+				If _module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT) Then
+					Err "Strict or SuperStrict already specified"
+				End If
+
+				_module.attrs :| MODULE_STRICT
+				nextToke
+			Case "superstrict"
+				If _module.attrs & (MODULE_STRICT | MODULE_SUPERSTRICT) Then
+					Err "Strict or SuperStrict already specified"
+				End If
+
+				_module.attrs :| MODULE_SUPERSTRICT
+				nextToke
+			Case "moduleinfo"
+				NextToke
+				Local info:String = ParseStringLit()
+				_module.modInfo.AddLast(info)
+			Default
+				Exit
+			End Select
+		Wend
+'DebugStop
+		' app code
+		PushBlock(mainFunc)
+
+		'Parse main app
+		While _toke
+			SetErr
+			Select _toke
+			Case "~n"
+				NextToke
+			Case "public"
+				NextToke
+				attrs=0
+			Case "private"
+				NextToke
+				attrs=DECL_PRIVATE
+			Case "extern"
+'DebugStop
+				
+				'If ENV_SAFEMODE
+				'	If _app.mainModule=_module
+				'		Err "Extern not permitted in safe mode."
+				'	EndIf
+				'EndIf
+				NextToke
+				
+				If _tokeType=TOKE_STRINGLIT
+					DebugLog "EXTERN : " + ParseStringLit()
+				End If
+				
+				
+				attrs=DECL_EXTERN
+				If CParse( "private" ) attrs=attrs|DECL_PRIVATE
+
+
+				While _toke<>"endextern"
+					If CParse( "end" )
+						If CParse("extern")
+							Exit
+						End If
+					EndIf
+
+					SetErr
+					Select _toke
+						Case "~n"
+							NextToke
+						Case "const","global"
+							_module.InsertDecls ParseDecls( _toke,attrs )
+						Case "type"
+							_module.InsertDecl ParseClassDecl( _toke,attrs )
+						Case "function"
+							_module.InsertDecl ParseFuncDecl( _toke,attrs )
+						Case "rem"
+							ParseRemStmt()
+					End Select
+
+				Wend
+
+				attrs = 0
+
+			Case "const","global"
+				_module.InsertDecls ParseDecls( _toke,attrs )
+			Case "type"
+				_module.InsertDecl ParseClassDecl( _toke,attrs )
+			'Case "interface"
+			'	_module.InsertDecl ParseClassDecl( _toke,attrs|CLASS_INTERFACE|DECL_ABSTRACT )
+			Case "function"
+				_module.InsertDecl ParseFuncDecl( _toke,attrs )
+			Case "rem"
+'DebugStop
+				ParseRemStmt()
+			Default
+				ParseStmt
+				'Err "Syntax error - expecting declaration."
+			End Select
+		Wend
+
+		PopBlock
+
+	End Method
+
+	Method ParseModule()
+
+	End Method
+
+
+	Method Create:TParser( toker:TToker,app:TAppDecl )
+		_toke="~n"
+		_toker=toker
+		_app=app
+		SetErr
+		NextToke
+		Return Self
+	End Method
+End Type
+
+Function Eval$( toker:TToker,_type:TType )
+	Local src$
+	While toker.Toke() And toker.Toke()<>"'" And toker.Toke()<>"~n" And toker.Toke()<>"~r"
+		src:+toker.Toke()
+		toker.NextToke()
+	Wend
+	Local t:String=EvalS( src,_type )
+	Return t
+End Function
+
+Function PreProcess$( path$ )
+
+	Local ifnest:Int,con:Int=1,line:Int,source:TStringList=New TStringList
+
+	Local toker:TToker=New TToker.Create( path,LoadString( path ) )
+
+	toker.NextToke
+
+	Repeat
+
+		If line
+			source.AddLast "~n"
+			While toker.Toke() And toker.Toke()<>"~n" And toker.TokeType()<>TOKE_LINECOMMENT
+				toker.NextToke()
+			Wend
+			If Not toker.Toke() Exit
+			toker.NextToke()
+		EndIf
+		line:+1
+
+		_errInfo=toker.Path()+"<"+toker.Line()+">"
+
+		If toker.TokeType()=TOKE_SPACE toker.NextToke()
+
+		If toker.Toke()<>"?"
+			If con
+				Local line$
+				While toker.Toke() And toker.Toke()<>"~n" And toker.TokeType()<>TOKE_LINECOMMENT
+					Local toke$=toker.Toke()
+					line:+toke
+					toker.NextToke()
+				Wend
+				If line source.AddLast line
+
+			EndIf
+			Continue
+		EndIf
+'DebugStop
+		Local stm$=toker.NextToke().ToLower()
+		'toker.NextToke()
+
+		Local isNot:Int = False
+
+		If stm = "not" Then
+			If toker.TokeType()=TOKE_SPACE toker.NextToke()
+			stm = toker.Toke().ToLower()
+			isNot = True
+		End If
+
+		'If stm="end" Or stm="else"
+		'	If toker.TokeType()=TOKE_SPACE toker.NextToke()
+		'	If toker.Toke().ToLower()="if"
+		'		toker.NextToke()
+		'		stm:+"if"
+		'	EndIf
+		'EndIf
+Rem
+Debug	True if program is being compiled in debug mode.
+Threaded	True if program is being compiled in threaded mode.
+Win32	True if program is being compiled for the Windows operating system.
+MacOS	True if program is being compiled for the MacOS operating system.
+Linux	True if program is being compiled for the Linux operating system.
+X86	True if program is being compiled for the Intel CPU.
+PPC	True if program is being compiled for the PowerPC CPU.
+MacOSX86	True if program is being compiled for an Intel Mac.
+MacOSPPC	True if program is being compiled for a PowerPC Mac.
+BigEndian	True if program is being compiled for a big endian CPU.
+LittleEndian
+End Rem
+		Select stm
+		Case "~r", "~n"
+			'ifnest = 0
+			con = 1
+
+		Default
+
+			con = 0
+			If Eval( toker,TType.intType ) = "1" con = 1
+		
+Rem
+		Case "macos", "macosx86", "x86", "littleendian", "bigendian"
+			con = 1
+		'	If con=ifnest
+		'		If Eval( toker,TType.intType ) con:+1
+		'	EndIf
+		'
+			ifnest = 1
+
+'		Case "rem"
+'
+'			ifnest:+1
+		Case "threaded", "win32", "linux", "ppc", "win32x86", "linuxx86", "macosppc"
+
+			If isNot Then
+				con = 1
+			Else
+				con = 0
+			End If
+
+			ifnest = 1
+
+		Case "else","elseif"
+
+			If Not ifnest Err "#Else without #If"
+
+			If con=ifnest
+				con=-con
+			Else If con=ifnest-1
+				If stm="elseif"
+					If Eval( toker,TType.intType ) con:+1
+				Else
+					con:+1
+				EndIf
+			EndIf
+
+		Case "end","endif"
+
+			If Not ifnest Err "#End without #If"
+
+			ifnest:-1
+			If con<0 con=-con
+			If ifnest<con con=ifnest
+
+'		Case "print"
+
+'			If con=ifnest
+' TODO
+				'Print ReplaceEnvTags( Eval( toker,TType.stringType ) )
+'			EndIf
+
+'		Case "error"
+
+'			If con=ifnest
+' TODO
+				'Err ReplaceEnvTags( Eval( toker,TType.stringType ) )
+'			EndIf
+
+		Default
+			Err "Unrecognized preprocessor directive '"+stm+"'."
+End Rem
+		End Select
+	Forever
+
+	Return source.Join( "" )
+End Function
+
+Function ParseModule:TModuleDecl( path$,app:TAppDecl )
+
+	'Local source$=PreProcess( path )
+	Local source:String = LoadString(path)
+
+	Local toker:TToker=New TToker.Create( path,source )
+
+	Local parser:TParser=New TParser.Create( toker,app )
+
+	parser.ParseMain
+
+	Return parser._module
+End Function
+
+'***** PUBLIC API ******
+
+Function ParseApp:TAppDecl( path$ )
+
+	Local app:TAppDecl=New TAppDecl
+
+	Local source$=PreProcess( path )
+	'Local source:String = LoadString(path)
+
+	Local toker:TToker=New TToker.Create( path,source )
+
+	Local parser:TParser=New TParser.Create( toker,app )
+
+	parser.ParseMain
+
+	Return app
+End Function
+
+Function EvalS$( source$,ty:TType )
+
+	Local env:TScopeDecl=New TScopeDecl
+
+Rem
+Debug	True if program is being compiled in debug mode.
+Threaded	True if program is being compiled in threaded mode.
+Win32	True if program is being compiled for the Windows operating system.
+MacOS	True if program is being compiled for the MacOS operating system.
+Linux	True if program is being compiled for the Linux operating system.
+X86	True if program is being compiled for the Intel CPU.
+PPC	True if program is being compiled for the PowerPC CPU.
+MacOSX86	True if program is being compiled for an Intel Mac.
+MacOSPPC	True if program is being compiled for a PowerPC Mac.
+BigEndian	True if program is being compiled for a big endian CPU.
+LittleEndian
+End Rem
+
+	' debug/release
+	env.InsertDecl New TConstDecl.Create( "debug",TType.intType,New TConstExpr.Create( TType.intType,opt_debug ),0 )
+	'env.InsertDecl New TConstDecl.Create( "release",TType.intType,New TConstExpr.Create( TType.intType,opt_release ),0 )
+
+	' threaded
+	env.InsertDecl New TConstDecl.Create( "threaded",TType.intType,New TConstExpr.Create( TType.intType,opt_threaded ),0 )
+
+	' macos
+	env.InsertDecl New TConstDecl.Create( "macos",TType.intType,New TConstExpr.Create( TType.intType,opt_platform="macos" ),0 )
+	env.InsertDecl New TConstDecl.Create( "macosx86",TType.intType,New TConstExpr.Create( TType.intType,opt_platform="macos" And opt_arch="x86"),0 )
+	env.InsertDecl New TConstDecl.Create( "macosppc",TType.intType,New TConstExpr.Create( TType.intType,opt_platform="macos" And opt_arch="ppc"),0 )
+	env.InsertDecl New TConstDecl.Create( "macosx64",TType.intType,New TConstExpr.Create( TType.intType,opt_platform="macos" And opt_arch="x64"),0 )
+
+	' windows
+	env.InsertDecl New TConstDecl.Create( "win32",TType.intType,New TConstExpr.Create( TType.intType,opt_platform="win32" ),0 )
+	env.InsertDecl New TConstDecl.Create( "win32x64",TType.intType,New TConstExpr.Create( TType.intType,(opt_platform="win64" And opt_arch="x64") Or (opt_platform="win32" And opt_arch="x64")),0 )
+	env.InsertDecl New TConstDecl.Create( "win64",TType.intType,New TConstExpr.Create( TType.intType,(opt_platform="win64" And opt_arch="x64") Or (opt_platform="win32" And opt_arch="x64")),0 )
+	
+	' linux
+	env.InsertDecl New TConstDecl.Create( "linux",TType.intType,New TConstExpr.Create( TType.intType,opt_platform="linux" ),0 )
+	env.InsertDecl New TConstDecl.Create( "linuxx86",TType.intType,New TConstExpr.Create( TType.intType,opt_platform="linux" And opt_arch="x86"),0 )
+	env.InsertDecl New TConstDecl.Create( "linuxx64",TType.intType,New TConstExpr.Create( TType.intType,opt_platform="linux" And opt_arch="x64"),0 )
+	env.InsertDecl New TConstDecl.Create( "linuxARM",TType.intType,New TConstExpr.Create( TType.intType,opt_platform="linux" And opt_arch="arm"),0 )
+	
+	' arch
+	env.InsertDecl New TConstDecl.Create( "ppc",TType.intType,New TConstExpr.Create( TType.intType,opt_arch="ppc" ),0 )
+	env.InsertDecl New TConstDecl.Create( "x86",TType.intType,New TConstExpr.Create( TType.intType,opt_arch="x86" ),0 )
+	env.InsertDecl New TConstDecl.Create( "x64",TType.intType,New TConstExpr.Create( TType.intType,opt_arch="x64" ),0 )
+	env.InsertDecl New TConstDecl.Create( "arm",TType.intType,New TConstExpr.Create( TType.intType,opt_arch="arm" ),0 )
+	
+	' endian
+	env.InsertDecl New TConstDecl.Create( "bigendian",TType.intType,New TConstExpr.Create( TType.intType,opt_arch="ppc" ),0 )
+	env.InsertDecl New TConstDecl.Create( "littleendian",TType.intType,New TConstExpr.Create( TType.intType,opt_arch<>"ppc" ),0 )
+	
+'	env.InsertDecl New TConstDecl.Create( "LANG",TType.stringType,New TConstExpr.Create( TType.stringType,ENV_LANG ),0 )
+'	env.InsertDecl New TConstDecl.Create( "TARGET",TType.stringType,New TConstExpr.Create( TType.stringType,ENV_TARGET ),0 )
+'	env.InsertDecl New TConstDecl.Create( "CONFIG",TType.stringType,New TConstExpr.Create( TType.stringType,ENV_CONFIG ),0 )
+
+	PushEnv env
+
+	Local toker:TToker=New TToker.Create( "",source )
+
+	Local parser:TParser=New TParser.Create( toker,Null )
+
+	Local expr:TExpr=parser.ParseExpr()
+
+	expr=expr.Semant()
+
+	If ty expr=expr.Cast( ty )
+
+	Local val$=expr.Eval()
+
+	PopEnv
+
+	Return val
+End Function
+
+Type TCastDets
+
+	Field name:String
+	Field retType:String
+	Field noGen:Int
+	Field args:String[0]
+
+End Type
+

+ 356 - 0
stmt.bmx

@@ -0,0 +1,356 @@
+
+Type TStmt
+	Field errInfo$
+	
+	Method New()
+		errInfo=_errInfo
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl ) Abstract
+	
+	Method Semant()
+		PushErr errInfo
+		OnSemant
+		PopErr
+	End Method
+
+	Method Copy:TStmt( scope:TScopeDecl )
+		Local t:TStmt=OnCopy( scope )
+		t.errInfo=errInfo
+		Return t
+	End Method
+	
+	Method OnSemant() Abstract
+
+	Method Trans$() Abstract
+
+End Type
+
+Type TDeclStmt Extends TStmt
+	Field decl:TDecl
+	
+	Method Create:TDeclStmt( decl:TDecl )
+		Self.decl=decl
+		Return Self
+	End Method
+	
+	Method CreateWithId:TDeclStmt( id$,ty:TType,init:TExpr )
+		Self.decl=New TLocalDecl.Create( id,ty,init,0 )	
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TDeclStmt.Create( decl.Copy() )
+	End Method
+	
+	Method OnSemant()
+		decl.Semant
+		_env.InsertDecl decl
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransDeclStmt( Self )
+	End Method
+End Type
+
+Type TAssignStmt Extends TStmt
+	Field op$
+	Field lhs:TExpr
+	Field rhs:TExpr
+	
+	Method Create:TAssignStmt( op$,lhs:TExpr,rhs:TExpr )
+		Self.op=op
+		Self.lhs=lhs
+		Self.rhs=rhs
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TAssignStmt.Create( op,lhs.Copy(),rhs.Copy() )
+	End Method
+	
+	Method OnSemant()
+		rhs=rhs.Semant()
+		lhs=lhs.SemantSet( op,rhs )
+		If TInvokeExpr( lhs ) Or TInvokeMemberExpr( lhs )
+			rhs=Null
+		Else
+			rhs=rhs.Cast( lhs.exprType )
+		EndIf
+	End Method
+	
+	Method Trans$()
+		_errInfo=errInfo
+		Return _trans.TransAssignStmt( Self )
+	End Method
+End Type
+
+Type TExprStmt Extends TStmt
+	Field expr:TExpr
+	
+	Method Create:TExprStmt( expr:TExpr )
+		Self.expr=expr
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TExprStmt.Create( expr.Copy() )
+	End Method
+		
+	Method OnSemant()
+		expr=expr.Semant()
+		If Not expr InternalErr
+	End Method
+
+	Method Trans$()
+		Return _trans.TransExprStmt( Self )
+	End Method
+End Type
+
+Type TReturnStmt Extends TStmt
+	Field expr:TExpr
+
+	Method Create:TReturnStmt( expr:TExpr )
+		Self.expr=expr
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		If expr Return New TReturnStmt.Create( expr.Copy() )
+		Return New TReturnStmt.Create( Null )
+	End Method
+	
+	Method OnSemant()
+		Local fdecl:TFuncDecl=_env.FuncScope()
+		If expr
+			If fdecl.IsCtor() Err "Constructors may not return a value."
+			If TVoidType( fdecl.retType ) Err "Void functions may not return a value."
+			expr=expr.SemantAndCast( fdecl.retType )
+		Else If fdecl.IsCtor()
+			expr=New TSelfExpr.Semant()
+		Else If Not TVoidType( fdecl.retType )
+			If _env.ModuleScope().IsSuperStrict() Err "Missing return expression."
+			expr=New TConstExpr.Create( fdecl.retType,"" ).Semant()
+		EndIf
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransReturnStmt( Self )
+	End Method
+End Type
+
+Type TThrowStmt Extends TStmt
+	Field expr:TExpr
+
+	Method Create:TThrowStmt( expr:TExpr )
+		Self.expr=expr
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TThrowStmt.Create( expr.Copy() )
+	End Method
+	
+	Method OnSemant()
+		expr=expr.Semant()
+		If Not TObjectType( expr.exprType ) And Not TStringType(expr.exprType) Err "Expression Type must extend Throwable"
+		'If Not expr.exprType.GetClass().IsThrowable() Err "Expression type must extend Throwable"
+	End Method
+	
+	Method Trans$()
+	' TODO
+		Return _trans.TransThrowStmt( Self )
+	End Method
+End Type
+
+Type TBreakStmt Extends TStmt
+
+	Method OnSemant()
+		If Not _loopnest Err "Exit statement must appear inside a loop."
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TBreakStmt
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransBreakStmt( Self )
+	End Method
+	
+End Type
+
+Type TContinueStmt Extends TStmt
+
+	Method OnSemant()
+		If Not _loopnest Err "Continue statement must appear inside a loop."
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TContinueStmt
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransContinueStmt( Self )
+	End Method
+	
+End Type
+
+Type TIfStmt Extends TStmt
+	Field expr:TExpr
+	Field thenBlock:TBlockDecl
+	Field elseBlock:TBlockDecl
+	
+	Method Create:TIfStmt( expr:TExpr,thenBlock:TBlockDecl,elseBlock:TBlockDecl )
+		Self.expr=expr
+		Self.thenBlock=thenBlock
+		Self.elseBlock=elseBlock
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TIfStmt.Create( expr.Copy(),thenBlock.CopyBlock( scope ),elseBlock.CopyBlock( scope ) )
+	End Method
+	
+	Method OnSemant()
+		expr=expr.SemantAndCast( TType.boolType,CAST_EXPLICIT )
+		thenBlock.Semant
+		elseBlock.Semant
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransIfStmt( Self )
+	End Method
+End Type
+
+Type TWhileStmt Extends TStmt
+	Field expr:TExpr
+	Field block:TBlockDecl
+	
+	Method Create:TWhileStmt( expr:TExpr,block:TBlockDecl )
+		Self.expr=expr
+		Self.block=block
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TWhileStmt.Create( expr.Copy(),block.CopyBlock( scope ) )
+	End Method
+	
+	Method OnSemant()
+		expr=expr.SemantAndCast( TType.boolType,CAST_EXPLICIT )
+		_loopnest:+1
+		block.Semant
+		_loopnest:-1
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransWhileStmt( Self )
+	End Method
+End Type
+
+Type TRepeatStmt Extends TStmt
+	Field block:TBlockDecl
+	Field expr:TExpr
+	
+	Method Create:TRepeatStmt( block:TBlockDecl,expr:TExpr )
+		Self.block=block
+		Self.expr=expr
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TRepeatStmt.Create( block.CopyBlock( scope ),expr.Copy() )
+	End Method
+	
+	Method OnSemant()
+		_loopnest:+1
+		block.Semant
+		_loopnest:-1
+		expr=expr.SemantAndCast( TType.boolType,CAST_EXPLICIT )
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransRepeatStmt( Self )
+	End Method
+End Type
+
+Type TForStmt Extends TStmt
+	Field init:TStmt	'assignment or local decl...
+	Field expr:TExpr
+	Field incr:TStmt	'assignment...
+	Field block:TBlockDecl
+	
+	Method Create:TForStmt( init:TStmt,expr:TExpr,incr:TStmt,block:TBlockDecl )
+		Self.init=init
+		Self.expr=expr
+		Self.incr=incr
+		Self.block=block
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TForStmt.Create( init.Copy( scope ),expr.Copy(),incr.Copy( scope ),block.CopyBlock( scope ) )
+	End Method
+	
+	Method OnSemant()
+
+		PushEnv block
+		init.Semant
+		PopEnv
+		
+		expr=expr.Semant()
+		
+		_loopnest:+1
+		block.Semant
+		_loopnest:-1
+
+		incr.Semant
+		
+		'dodgy as hell! Reverse comparison for backward loops!
+		Local assop:TAssignStmt=TAssignStmt( incr )
+		Local addop:TBinaryExpr=TBinaryExpr( assop.rhs )
+		Local stpval$=addop.rhs.Eval()
+		If stpval.StartsWith( "-" )
+			Local bexpr:TBinaryExpr=TBinaryExpr( expr )
+			Select bexpr.op
+			Case "<" bexpr.op=">"
+			Case "<=" bexpr.op=">="
+			End Select
+		EndIf
+		
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransForStmt( Self )
+	End Method
+End Type
+
+Type TAssertStmt Extends TStmt
+	Field expr:TExpr
+	Field elseExpr:TExpr
+	
+	Method Create:TAssertStmt( expr:TExpr, elseExpr:TExpr )
+		Self.expr=expr
+		Self.elseExpr=elseExpr
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		If elseExpr Then
+			Return New TAssertStmt.Create( expr.Copy(),elseExpr.Copy() )
+		Else
+			Return New TAssertStmt.Create( expr.Copy(), Null )
+		End If
+	End Method
+	
+	Method OnSemant()
+		expr=expr.SemantAndCast( TType.intType,CAST_EXPLICIT )
+		If elseExpr Then
+			elseExpr = elseExpr.SemantAndCast(TType.stringType,CAST_EXPLICIT)
+		End If
+	End Method
+	
+	Method Trans$()
+		Return _trans.TransAssertStmt( Self )
+	End Method
+End Type

+ 218 - 0
toker.bmx

@@ -0,0 +1,218 @@
+SuperStrict
+
+Import "config.bmx"
+Import "type.bmx"
+
+'toke_type
+Const TOKE_EOF:Int=0
+Const TOKE_SPACE:Int=1
+Const TOKE_IDENT:Int=2
+Const TOKE_KEYWORD:Int=3
+Const TOKE_INTLIT:Int=4
+Const TOKE_FLOATLIT:Int=5
+Const TOKE_STRINGLIT:Int=6
+Const TOKE_STRINGLITEX:Int=7
+Const TOKE_SYMBOL:Int=8
+Const TOKE_LINECOMMENT:Int=9
+Const TOKE_LONGLIT:Int=10
+
+'***** Tokenizer *****
+Type TToker
+
+	Const _keywords$=";"+ ..
+	"strict;superstrict;"+ ..
+	"public;private;property;"+ ..
+	"short;int;float;double;long;string;array;object;ptr;var;varptr;mod;continue;exit;"+ ..
+	"include;import;module;extern;framework;"+ ..
+	"new;self;super;eachin;true;false;null;not;"+ ..
+	"extends;abstract;select;case;default;"+ ..
+	"const;local;global;field;method;function;type;"+ ..
+	"and;or;shl;shr;end;if;then;else;elseif;endif;while;wend;repeat;until;forever;"+ ..
+	"for;to;step;next;return;"+ ..
+	"alias;rem;endrem;throw;assert;"
+
+	Global _symbols$[]=[ "..","[]",":*",":/",":+",":-",":|",":&",":~~",":shr",":shl" ]
+	Global _symbols_map$[]=[ "..","[]","*=","/=","+=","-=","|=","&=","~~=","=>>", "=<<" ]
+	'Global _symbols$[]=[ "..","[]",":=",":*",":/",":+",":-",":|",":&",":~~" ]
+	'Global _symbols_map$[]=[ "..","[]",":=","*=","/=","+=","-=","|=","&=","~~=" ]
+
+	Field _path$
+	Field _line:Int
+	Field _lines:String[]
+	Field _source$
+	Field _toke$
+	Field _tokeType:Int
+	Field _tokePos:Int
+	
+	Method Create:TToker( path$,source$ )
+		_path=path
+		_line=1
+		_source=source
+		_toke=""
+		_tokeType=TOKE_EOF
+		_tokePos=0
+		_lines = source.split("~n")
+		Return Self
+	End Method
+	
+	Method rollback(pos:Int, toketype:Int = -1)
+		_tokePos = pos
+		If toketype >= 0
+			_tokeType = toketype
+		End If
+	End Method
+	
+	Method Copy:TToker( toker:TToker )
+		_path=toker._path
+		_line=toker._line
+		_source=toker._source
+		_toke=toker._toke
+		_tokeType=toker._tokeType
+		_tokePos=toker._tokePos
+		_lines=toker._lines
+		Return Self
+	End Method
+	
+	Method Path$()
+		Return _path
+	End Method
+	
+	Method Line:Int()
+		Return _line
+	End Method
+	
+	Method NextToke$()
+
+		If _tokePos=_source.Length
+			_toke=""
+			_tokeType=TOKE_EOF
+			Return _toke
+		EndIf
+				
+		Local char:Int=_source[_tokePos]
+		Local str$=Chr( char )
+		
+		Local start:Int=_tokePos
+		_tokePos:+1
+		_toke=""
+
+		If str="~n"
+			_line:+1
+			_tokeType=TOKE_SYMBOL
+		Else If IsSpace( char )
+			While _tokePos<_source.Length And IsSpace( TCHR() ) And TSTR()<>"~n"
+				_tokePos:+1
+			Wend
+			_tokeType=TOKE_SPACE
+		Else If str="_" Or IsAlpha( char )
+			_tokeType=TOKE_IDENT
+			While _tokePos<_source.Length
+				Local char:Int=_source[_tokePos]
+				If char<>Asc("_") And Not IsAlpha( char ) And Not IsDigit( char ) Exit
+				_tokePos:+1
+			Wend
+			_toke=_source[start.._tokePos]
+			If _keywords.Contains( ";"+_toke.ToLower()+";" )
+				_tokeType=TOKE_KEYWORD
+			EndIf
+		Else If IsDigit( char ) Or (str="." And IsDigit( TCHR() ))
+'Print "IS DIGIT..."
+			_tokeType=TOKE_INTLIT
+			If str="." _tokeType=TOKE_FLOATLIT
+			While IsDigit( TCHR() )
+				_tokePos:+1
+			Wend
+			If _tokeType=TOKE_INTLIT And TSTR()="." And IsDigit( TCHR(1) )
+				_tokeType=TOKE_FLOATLIT
+				_tokePos:+2
+				While IsDigit( TCHR() )
+					_tokePos:+1
+				Wend
+			EndIf
+			If TSTR().ToLower()="e"
+				_tokeType=TOKE_FLOATLIT
+				_tokePos:+1
+				If TSTR()="+" Or TSTR()="-" _tokePos:+1
+				While IsDigit( TCHR() )
+					_tokePos:+1
+				Wend
+			EndIf
+			If _tokeType=TOKE_INTLIT And _tokePos-start > 10 ' BaH Long
+				_tokeType=TOKE_LONGLIT
+			EndIf
+		Else If str="%" And IsBinDigit( TCHR() )
+			_tokeType=TOKE_INTLIT
+			_tokePos:+1
+			While IsBinDigit( TCHR() )
+				_tokePos:+1
+			Wend
+		Else If str="$" And IsHexDigit( TCHR() )
+			_tokeType=TOKE_INTLIT
+			_tokePos:+1
+			While IsHexDigit( TCHR() )
+				_tokePos:+1
+			Wend
+		Else If str="~q"
+			_tokeType=TOKE_STRINGLIT
+			While TSTR() And TSTR()<>"~q"
+				_tokePos:+1
+			Wend
+			If _tokePos<_source.Length _tokePos:+1 Else _tokeType=TOKE_STRINGLITEX
+		Else If str="'"
+			_tokeType=TOKE_LINECOMMENT
+			While TSTR() And TSTR()<>"~n"
+				_tokePos:+1
+			Wend
+			If _tokePos<_source.Length
+				_tokePos:+1
+				_line:+1
+			EndIf
+		Else
+			_tokeType=TOKE_SYMBOL
+			For Local i:Int = 0 Until _symbols.length
+'If i = 9 And _line = 42 DebugStop
+				Local sym$=_symbols[i]
+				If char<>sym[0] Continue
+'Local a:String = _source[_tokePos-1.._tokePos+sym.length-1]
+				If _source[_tokePos-1.._tokePos+sym.length-1].ToLower()=sym
+					'_toke = _symbols_map[i]
+					
+					_tokePos:+sym.length-1
+					
+					Exit
+				EndIf
+			Next
+		EndIf
+
+		If Not _toke _toke=_source[start.._tokePos]
+				
+'Print "TOKE... : " + _toke		
+		Return _toke
+	End Method
+	
+	Method Toke$()
+		Return _toke
+	End Method
+	
+	Method TokeType:Int()
+		Return _tokeType
+	End Method
+	
+	Method SkipSpace()
+		While _tokeType=TOKE_SPACE
+			NextToke
+		Wend
+	End Method
+	
+'Private
+
+	Method TCHR:Int( i:Int=0 )
+		If _tokePos+i<_source.Length Return _source[_tokePos+i]
+	End Method
+	
+	Method TSTR$( i:Int=0 )
+		If _tokePos+i<_source.Length Return Chr( _source[_tokePos+i] )
+	End Method
+	
+	
+End Type

+ 749 - 0
translator.bmx

@@ -0,0 +1,749 @@
+'SuperStrict
+
+Global _trans:TTranslator
+
+Type TTranslator
+
+	Field outputFiles:TMap = New TMap
+
+	Field indent$
+	Field LINES:TStringList'=New TStringList
+	Field unreachable:Int,broken:Int
+	
+	'Munging needs a big cleanup!
+	
+	Field mungScope:TMap=New TMap'<TDecl>
+	Field mungStack:TStack=New TStack'< StringMap<TDecl> >
+	Field funcMungs:TMap=New TMap'<FuncDeclList>
+
+	Field mungedScopes:TMap=New TMap'<StringSet>
+'	Field funcMungs:=New StringMap<FuncDeclList>
+'	Field mungedFuncs:=New StringMap<FuncDecl>
+
+'	Method PushMungScope()
+'		mungStack.Push mungScope
+'		mungScope:TMap=New TMap'<TDecl>
+'	End Method
+	
+'	Method PopMungScope()
+'		mungScope=TMap(mungStack.Pop())
+'	End Method
+	
+	Method MungFuncDecl( fdecl:TFuncDecl )
+
+		If fdecl.munged Return
+		
+		If fdecl.overrides
+			MungFuncDecl fdecl.overrides
+			fdecl.munged=fdecl.overrides.munged
+			Return
+		EndIf
+		
+		Local funcs:TFuncDeclList=TFuncDeclList(funcMungs.ValueForKey( fdecl.ident ))
+		If funcs
+			For Local tdecl:TFuncDecl=EachIn funcs
+				If fdecl.argDecls.Length=tdecl.argDecls.Length
+					Local match:Int=True
+					For Local i:Int=0 Until fdecl.argDecls.Length
+						Local ty:TType=TArgDecl( fdecl.argDecls[i].actual ).ty
+						Local ty2:TType=TArgDecl( tdecl.argDecls[i].actual ).ty
+						If ty.EqualsType( ty2 ) Continue
+						match=False
+						Exit
+					Next
+					If match
+						fdecl.munged=tdecl.munged
+						Return
+					EndIf
+				EndIf
+			Next
+		Else
+			funcs=New TFuncDeclList
+			funcMungs.Insert fdecl.ident,funcs
+		EndIf
+		
+		fdecl.munged="bbm_"+fdecl.ident
+		If Not funcs.IsEmpty() fdecl.munged:+String(funcs.Count()+1)
+		funcs.AddLast fdecl
+	End Method
+	
+	Method MungDecl( decl:TDecl )
+
+		If decl.munged Return
+
+		Local fdecl:TFuncDecl=TFuncDecl( decl )
+		
+		'If fdecl And fdecl.IsMethod() 
+		'	MungFuncDecl( fdecl )
+		'	Return
+		'End If
+		
+		Local id$=decl.ident,munged$
+		
+		'this lot just makes output a bit more readable...
+'		Select ENV_LANG
+'		Case "js"
+'			If TModuleDecl( decl.scope ) Or TGlobalDecl( decl ) Or (fdecl And Not fdecl.IsMethod())
+'				munged=decl.ModuleScope().munged+"_"+id
+'			EndIf
+'		Case "as"
+'			If TModuleDecl( decl.scope )
+'				munged=decl.ModuleScope().munged+"_"+id
+'			EndIf
+'		Case "cs"
+'			If TClassDecl( decl )
+'				munged=decl.ModuleScope().munged+"_"+id
+'			EndIf
+'		Case "java"
+'			If TClassDecl( decl )
+'				munged=decl.ModuleScope().munged+"_"+id
+'			EndIf
+'		Case "cpp"
+			If TModuleDecl( decl.scope )
+				munged=decl.ModuleScope().munged+"_"+id
+			EndIf
+
+			If TModuleDecl( decl )
+'DebugStop
+				munged=decl.ModuleScope().munged+"_"+id
+			EndIf
+
+'		End Select
+'DebugStop
+		
+		If Not munged
+			If TLocalDecl( decl )
+				munged="bbt_"+id
+			Else
+				If decl.scope Then
+					munged = decl.scope.munged + "_" + id
+					
+					If TFieldDecl(decl) Then
+						munged = "_" + munged.ToLower()
+					End If
+				Else
+					munged="bb_"+id
+				End If
+			EndIf
+		EndIf
+		
+		If mungScope.Contains( munged )
+			Local t$,i:Int=1
+			Repeat
+				i:+1
+				t=munged+i
+			Until Not mungScope.Contains( t )
+			munged=t
+		EndIf
+		mungScope.Insert munged,decl
+		decl.munged=munged
+	End Method
+
+Rem
+	Method MungDecl( decl:TDecl )
+
+		If decl.munged Return
+
+		Local fdecl:TFuncDecl=TFuncDecl( decl )
+		If fdecl And fdecl.IsMethod() Then
+'			DebugStop
+			MungFuncDecl( fdecl )
+			Return
+		End If
+		
+		Local id:String=decl.ident,munged$,scope$
+		
+		If TLocalDecl( decl )
+			scope="$"
+			munged="t_"+id
+		Else If TClassDecl( decl )
+			scope=""
+			munged="c_"+id
+		Else If TModuleDecl( decl )
+			scope=""
+			munged="bb_"+id
+		Else If TClassDecl( decl.scope )
+			scope=decl.scope.munged
+			munged="m_"+id
+		Else If TModuleDecl( decl.scope )
+			'If ENV_LANG="cs" Or ENV_LANG="java"
+			'	scope=decl.scope.munged
+			'	munged="g_"+id
+			'Else
+				scope=""
+				munged=decl.scope.munged+"_"+id
+			'EndIf
+		Else
+			InternalErr
+		EndIf
+		
+		Local set:TMap=TMap(mungedScopes.ValueForKey( scope ))
+		If set
+			If set.Contains( munged.ToLower() )
+				Local id:Int=1
+				Repeat
+					id :+ 1
+					Local t$=munged+id
+					If set.Contains( t.ToLower() ) Continue
+					munged=t
+					Exit
+				Forever
+			End If
+		Else
+			If scope="$"
+				Print "OOPS2"
+				InternalErr
+			EndIf
+			set=New TMap
+			mungedScopes.Insert scope,set
+		End If
+		set.Insert munged.ToLower(), ""
+		decl.munged=munged
+	End Method
+End Rem
+
+
+
+	
+	Method Bra$( str$ )
+		If str.StartsWith( "(" ) And str.EndsWith( ")" )
+			Local n:Int=1
+			For Local i:Int=1 Until str.Length-1
+				Select str[i..i+1]
+				Case "("
+					n:+1
+				Case ")"
+					n:-1
+					If Not n Return "("+str+")"
+				End Select
+			Next
+			If n=1 Return str
+'			If str.FindLast("(")<str.Find(")") Return str
+		EndIf
+		Return "("+str+")"
+	End Method
+	
+	'Utility C/C++ style...
+	Method Enquote$( str$ )
+		Return LangEnquote( str )
+	End Method
+
+	Method TransUnaryOp$( op$ )
+		Select op
+		Case "+" Return "+"
+		Case "-" Return "-"
+		Case "~~" Return op
+		Case "not" Return "!"
+		End Select
+		InternalErr
+	End Method
+	
+	Method TransBinaryOp$( op$,rhs$ )
+'DebugLog "TransBinaryOp '" + op + "' : '" + rhs + "'"
+		Select op
+		Case "+","-"
+			If rhs.StartsWith( op ) Return op+" "
+			Return op
+		Case "*","/" Return op
+		Case "shl" Return "<<"
+		Case "shr" Return ">>"
+		Case "mod" Return " % "
+		Case "and" Return " && "
+		Case "or" Return " || "
+		Case "=" Return "=="
+		Case "<>" Return "!="
+		Case "<","<=",">",">=" Return op
+		Case "&","|" Return op
+		Case "~~" Return "^"
+		End Select
+		InternalErr
+	End Method
+	
+	Method TransAssignOp$( op$ )
+		Select op
+		Case "mod=" Return "%="
+		Case "shl=" Return "<<="
+		Case "shr=" Return ">>="
+		End Select
+		Return op
+	End Method
+	
+	Method ExprPri:Int( expr:TExpr )
+		'
+		'1=primary,
+		'2=postfix
+		'3=prefix
+		'
+		If TNewObjectExpr( expr )
+			Return 3
+		Else If TUnaryExpr( expr )
+			Select TUnaryExpr( expr ).op
+			Case "+","-","~~","not" Return 3
+			End Select
+			InternalErr
+		Else If TBinaryExpr( expr )
+			Select TBinaryExpr( expr ).op
+			Case "*","/","mod" Return 4
+			Case "+","-" Return 5
+			Case "shl","shr" Return 6
+			Case "<","<=",">",">=" Return 7
+			Case "=","<>" Return 8
+			Case "&" Return 9
+			Case "~~" Return 10
+			Case "|" Return 11
+			Case "and" Return 12
+			Case "or" Return 13
+			End Select
+			InternalErr
+		EndIf
+		Return 2
+	End Method
+	
+	Method TransSubExpr$( expr:TExpr,pri:Int=2 )
+		Local t_expr$=expr.Trans()
+		If ExprPri( expr )>pri t_expr=Bra( t_expr )
+		Return t_expr
+	End Method
+	
+	Method TransExprNS$( expr:TExpr )
+		If TVarExpr( expr ) Return expr.Trans()
+		If TConstExpr( expr ) Return expr.Trans()
+		Return CreateLocal( expr )
+	End Method
+	
+	Method CreateLocal$( expr:TExpr )
+		Local tmp:TLocalDecl=New TLocalDecl.Create( "",expr.exprType,expr )
+		MungDecl tmp
+		Emit TransLocalDecl( tmp.munged,expr )+";"
+		Return tmp.munged
+	End Method
+	
+	'***** Utility *****
+
+	Method TransLocalDecl$( munged$,init:TExpr ) Abstract
+	
+	Method EmitPushErr()
+	End Method
+	
+	Method EmitSetErr( errInfo$ )
+	End Method
+	
+	Method EmitPopErr()
+	End Method
+	
+	'***** Declarations *****
+	
+	Method TransGlobal$( decl:TGlobalDecl ) Abstract
+	
+	Method TransField$( decl:TFieldDecl,lhs:TExpr ) Abstract
+	
+	Method TransFunc$( decl:TFuncDecl,args:TExpr[],lhs:TExpr ) Abstract
+	
+	Method TransSuperFunc$( decl:TFuncDecl,args:TExpr[] ) Abstract
+	
+	
+	'***** Expressions *****
+	
+	Method TransConstExpr$( expr:TConstExpr ) Abstract
+	
+	Method TransNewObjectExpr$( expr:TNewObjectExpr ) Abstract
+	
+	Method TransNewArrayExpr$( expr:TNewArrayExpr ) Abstract
+	
+	Method TransSelfExpr$( expr:TSelfExpr ) Abstract
+	
+	Method TransCastExpr$( expr:TCastExpr ) Abstract
+	
+	Method TransUnaryExpr$( expr:TUnaryExpr ) Abstract
+	
+	Method TransBinaryExpr$( expr:TBinaryExpr ) Abstract
+	
+	Method TransIndexExpr$( expr:TIndexExpr ) Abstract
+	
+	Method TransSliceExpr$( expr:TSliceExpr ) Abstract
+	
+	Method TransArrayExpr$( expr:TArrayExpr ) Abstract
+	
+	Method TransIntrinsicExpr$( decl:TDecl,expr:TExpr,args:TExpr[]=Null ) Abstract
+
+	Method BeginLocalScope()
+		mungStack.Push mungScope
+		mungScope:TMap=New TMap'<TDecl>
+'		mungedScopes.Insert "$",New TMap
+	End Method
+	
+	Method EndLocalScope()
+		mungScope=TMap(mungStack.Pop())
+'		mungedScopes.Insert "$",Null
+	End Method
+
+Rem	
+	Method MungMethodDecl( fdecl:TFuncDecl )
+
+		If fdecl.munged Return
+		
+		If fdecl.overrides
+			MungMethodDecl fdecl.overrides
+			fdecl.munged=fdecl.overrides.munged
+			Return
+		EndIf
+		
+		Local funcs:=funcMungs.Get( fdecl.ident )
+		If funcs
+			For Local tdecl:=EachIn funcs
+				If fdecl.EqualsArgs( tdecl )
+					fdecl.munged=tdecl.munged
+					Return
+				EndIf
+			Next
+		Else
+			funcs=New FuncDeclList
+			funcMungs.Set fdecl.ident,funcs
+		EndIf
+		
+		Local id:=fdecl.ident
+		If mungedFuncs.Contains( id )
+			Local n:=1
+			Repeat
+				n+=1
+				id=fdecl.ident+String(n)
+			Until Not mungedFuncs.Contains( id )
+		EndIf
+		
+		mungedFuncs.Set id,fdecl
+		fdecl.munged="p_"+id
+		funcs.AddLast fdecl
+	End
+End Rem	
+	'***** Simple statements *****
+	
+	'Expressions
+	Method TransStmtExpr$( expr:TStmtExpr )
+		Local t$=expr.stmt.Trans()
+		If t Emit t+";"
+		Return expr.expr.Trans()
+	End Method
+	
+	Method TransTemplateCast$( ty:TType,src:TType,expr$ )
+		Return expr
+	End Method
+	
+	Method TransVarExpr$( expr:TVarExpr )
+		Local decl:TVarDecl=TVarDecl( expr.decl.actual )
+		
+		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,Null )
+		
+		If TLocalDecl( decl ) Return decl.munged
+		
+		If TFieldDecl( decl ) Return TransField( TFieldDecl( decl ),Null )
+		
+		If TGlobalDecl( decl ) Return TransGlobal( TGlobalDecl( decl ) )
+		
+		InternalErr
+	End Method
+	
+	Method TransMemberVarExpr$( expr:TMemberVarExpr )
+		Local decl:TVarDecl=TVarDecl( expr.decl.actual )
+		
+		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr.expr )
+		
+		If TFieldDecl( decl ) Return TransField( TFieldDecl( decl ),expr.expr )
+
+		InternalErr
+	End Method
+	
+	Method TransInvokeExpr$( expr:TInvokeExpr )
+		Local decl:TFuncDecl=TFuncDecl( expr.decl.actual ),t$
+		
+		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,Null,expr.args )
+		
+		If decl Return TransFunc( TFuncDecl(decl),expr.args,Null )
+		
+		InternalErr
+	End Method
+	
+	Method TransInvokeMemberExpr$( expr:TInvokeMemberExpr )
+		Local decl:TFuncDecl=TFuncDecl( expr.decl.actual ),t$
+
+		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr.expr,expr.args )
+		
+		If decl Return TransFunc( TFuncDecl(decl),expr.args,expr.expr )	
+		
+		InternalErr
+	End Method
+	
+	Method TransInvokeSuperExpr$( expr:TInvokeSuperExpr )
+		Local decl:TFuncDecl=TFuncDecl( expr.funcDecl.actual ),t$
+
+		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr )
+		
+		If decl Return TransSuperFunc( TFuncDecl( decl ),expr.args )
+		
+		InternalErr
+	End Method
+	
+	Method TransExprStmt$( stmt:TExprStmt )
+		Return stmt.expr.TransStmt()
+	End Method
+	
+	Method TransAssignStmt$( stmt:TAssignStmt )
+		If stmt.rhs Return stmt.lhs.TransVar()+TransAssignOp(stmt.op)+stmt.rhs.Trans()
+		Return stmt.lhs.Trans()
+	End Method
+	
+	Method TransReturnStmt$( stmt:TReturnStmt )
+		Local t$="return"
+		If stmt.expr t:+" "+stmt.expr.Trans()
+		unreachable=True
+		Return t
+	End Method
+	
+	Method TransContinueStmt$( stmt:TContinueStmt )
+		unreachable=True
+		Return "continue"
+	End Method
+	
+	Method TransBreakStmt$( stmt:TBreakStmt )
+		unreachable=True
+		broken:+1
+		Return "break"
+	End Method
+	
+	Method TransThrowStmt$( stmt:TThrowStmt )
+	End Method
+	
+	'***** Block statements - all very C like! *****
+	
+	Method Emit( t$, useIndent:Int = True )
+		If Not t Return
+		If useIndent
+			If t.StartsWith( "}" )
+				indent=indent[..indent.Length-1]
+			EndIf
+		End If
+		LINES.AddLast indent+t
+		'code+=indent+t+"~n"
+		If useIndent
+			If t.EndsWith( "{" )
+				indent:+"~t"
+			EndIf
+		End If
+	End Method
+	
+	Method JoinLines$( file:String )
+		Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
+		
+		Local code$=_lines.Join( "~n" )
+		_lines.Clear
+		Return code
+	End Method
+	
+	'returns unreachable status!
+	Method EmitBlock:Int( block:TBlockDecl )
+
+		'If ENV_CONFIG="debug"
+		'	If TFuncDecl( block ) EmitPushErr
+		'EndIf
+		
+		PushEnv block
+
+		For Local stmt:TStmt=EachIn block.stmts
+		
+			_errInfo=stmt.errInfo
+			
+			If unreachable And ENV_LANG<>"as"
+				'If stmt.errInfo Print "Unreachable:"+stmt.errInfo
+				Exit
+			EndIf
+
+Rem
+			If ENV_CONFIG="debug"
+				Local rs:TReturnStmt=TReturnStmt( stmt )
+				If rs
+					If rs.expr
+						EmitSetErr stmt.errInfo
+						Local t_expr$=TransExprNS( rs.expr )
+						EmitPopErr
+						Emit "return "+t_expr+";"
+					Else
+						EmitPopErr
+						Emit "return;"
+					EndIf
+					unreachable=True
+					Continue
+				EndIf
+				EmitSetErr stmt.errInfo
+			EndIf
+End Rem
+			Local t$=stmt.Trans()
+			If t Emit t+";"
+			
+		Next
+		Local r:Int=unreachable
+		unreachable=False
+		PopEnv
+		Return r
+	End Method
+	
+	Method TransDeclStmt$( stmt:TDeclStmt )
+		Local decl:TLocalDecl=TLocalDecl( stmt.decl )
+		If decl
+			MungDecl decl
+			Return TransLocalDecl( decl.munged,decl.init )
+		EndIf
+		Local cdecl:TConstDecl=TConstDecl( stmt.decl )
+		If cdecl
+			Return Null
+		EndIf
+		InternalErr
+	End Method
+	
+	Method TransIfStmt$( stmt:TIfStmt )
+'DebugStop
+		If TConstExpr( stmt.expr )
+			If TConstExpr( stmt.expr ).value
+'				Emit "if"+Bra( stmt.expr.Trans() )+"{"
+				If EmitBlock( stmt.thenBlock ) unreachable=True
+'				Emit "}"
+			Else If stmt.elseBlock.stmts.First()
+'				Emit "if(!"+Bra( stmt.expr.Trans() )+"){"
+				If EmitBlock( stmt.elseBlock ) unreachable=True
+'				Emit "}"
+			EndIf
+		Else If stmt.elseBlock.stmts.First()
+			Emit "if"+Bra( stmt.expr.Trans() )+"{"
+			Local unr:Int=EmitBlock( stmt.thenBlock )
+			Emit "}else{"
+			Local unr2:Int=EmitBlock( stmt.elseBlock )
+			Emit "}"
+			If unr And unr2 unreachable=True
+		Else
+
+'			Emit "if"+ Bra(TransCondition(stmt.expr)) + "{"
+'			If TVarExpr(stmt.expr) Then
+'				If TObjectType(TVarExpr(stmt.expr).exprType) Then
+'					Emit "if"+Bra( stmt.expr.Trans() + "!= &bbNullObject") + "{"
+'				Else If TStringType(TVarExpr(stmt.expr).exprType)  Then
+'					Emit "if"+Bra( stmt.expr.Trans() + "!= &bbEmptyString") + "{"
+'				Else
+'					Emit "if"+Bra( stmt.expr.Trans() )+"{"
+'				End If
+'			Else
+				Emit "if"+Bra( stmt.expr.Trans() )+"{"
+'			End If
+			Local unr:Int=EmitBlock( stmt.thenBlock )
+			Emit "}"
+		EndIf
+	End Method
+	
+'	Method TransCondition:String(expr:TExpr)
+'		If TVarExpr(expr) Then
+'			If TObjectType(TVarExpr(expr).exprType) Then
+'				Return Bra( expr.Trans() + "!= &bbNullObject")
+'			Else If TStringType(TVarExpr(expr).exprType)  Then
+'				Return Bra( expr.Trans() + "!= &bbEmptyString")
+'			Else
+'				Return Bra( expr.Trans() )
+'			End If
+'		Else
+'			Return Bra( expr.Trans() )
+'		End If
+'	End Method
+	
+	Method TransWhileStmt$( stmt:TWhileStmt )
+		Local nbroken:Int=broken
+
+		Emit "while"+Bra( stmt.expr.Trans() )+"{"
+		
+		Local unr:Int=EmitBlock( stmt.block )
+		
+		Emit "}"
+		
+		If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
+		broken=nbroken
+	End Method
+
+	Method TransRepeatStmt$( stmt:TRepeatStmt )
+		Local nbroken:Int=broken
+
+		Emit "do{"
+		
+		Local unr:Int=EmitBlock( stmt.block )
+		
+		Emit "}while(!"+Bra( stmt.expr.Trans() )+");"
+
+		If broken=nbroken And TConstExpr( stmt.expr ) And Not TConstExpr( stmt.expr ).value unreachable=True
+		broken=nbroken
+	End Method
+
+	Method TransForStmt$( stmt:TForStmt )
+		Local nbroken:Int=broken
+
+		Local init$
+
+		Local decl:Int
+		If TDeclStmt(stmt.init) Then
+			decl = True
+			Emit "{"
+			Emit stmt.init.Trans() + ";"
+			init = TDeclStmt(stmt.init).decl.munged
+		Else
+			init=stmt.init.Trans()
+		End If
+		Local expr$=stmt.expr.Trans()
+		Local incr$=stmt.incr.Trans()
+
+		Emit "for("+init+";"+expr+";"+incr+"){"
+		
+		Local unr:Int=EmitBlock( stmt.block )
+		
+		Emit "}"
+		
+		If decl Then
+			Emit "}"
+		End If
+		
+		If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
+		broken=nbroken
+	End Method
+
+	Method TransAssertStmt$( stmt:TAssertStmt )
+		
+		Emit "// TODO : assert statement"
+
+	End Method
+	
+	'module
+	Method TransApp( app:TAppDecl ) Abstract
+
+Rem	
+	Method MungOverrides( cdecl:TClassDecl )
+		For Local decl:=Eachin cdecl.Semanted
+			Local fdecl:=TFuncDecl( decl )
+			If fdecl And fdecl.overrides
+				If Not fdecl.overrides.munged InternalErr
+				fdecl.munged=fdecl.overrides.munged
+				mungScope.Insert fdecl.munged,fdecl
+			Endif
+		Next
+	End
+End Rem
+	
+	Method PostProcess$( source$ ) 
+		Return source
+	End Method
+	
+	Method SetOutput( file:String )
+		Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
+		
+		If Not _lines Then
+			_lines = New TStringList
+			outputFiles.Insert(file, _lines)
+		End If
+		
+		LINES = _lines
+		
+	End Method
+	
+End Type
+

+ 1032 - 0
type.bmx

@@ -0,0 +1,1032 @@
+SuperStrict
+
+Import "config.bmx"
+
+Include "translator.bmx"
+Include "decl.bmx"
+Include "expr.bmx"
+Include "stmt.bmx"
+
+Type TType
+
+	Method ActualType:TType()
+		Return Self
+	End Method
+
+	Method EqualsType:Int( ty:TType )
+		Return False
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		Return EqualsType( ty )
+	End Method
+	
+	Method Semant:TType()
+		Return Self
+	End Method
+
+	Method GetClass:TClassDecl()
+		Return Null
+	End Method
+	
+	Method ToString$()
+		Return "??Type??"
+	End Method
+
+	Method ArrayOf:TArrayType()
+		If Not _arrayOf Then
+			_arrayOf=New TArrayType.Create( Self )
+		End If
+		Return _arrayOf
+	End Method
+	
+	Global voidType:TVoidType=New TVoidType
+	Global boolType:TBoolType=New TBoolType
+	Global intType:TIntType=New TIntType
+	Global shortType:TShortType=New TShortType
+	Global floatType:TFloatType=New TFloatType
+	Global stringType:TStringType=New TStringType
+	Global emptyArrayType:TArrayType=New TArrayType.Create( voidType )
+	Global objectType:TIdentType=New TIdentType.Create( "brl.classes.object" )
+	Global nullObjectType:TIdentType=New TIdentType.Create( "" )
+	Global longType:TLongType=New TLongType ' BaH Long
+	Global doubleType:TDoubleType=New TDoubleType
+	Global byteType:TByteType=New TByteType
+	Global pointerType:TPointerType=New TPointerType
+	Global bytePointerType:TBytePtrType=New TBytePtrType
+	Global intPointerType:TIntPtrType=New TIntPtrType
+	Global shortPointerType:TShortPtrType=New TShortPtrType
+	Global floatPointerType:TFloatPtrType=New TFloatPtrType
+	Global doublePointerType:TDoublePtrType=New TDoublePtrType
+	Global longPointerType:TLongPtrType=New TLongPtrType
+
+	Global stringPointerType:TStringPtrType=New TStringPtrType
+	Global varPointerType:TVarPtrType=New TVarPtrType
+
+	Global byteVarPointerType:TByteVarPtrType=New TByteVarPtrType
+	Global intVarPointerType:TIntVarPtrType=New TIntVarPtrType
+	Global shortVarPointerType:TShortVarPtrType=New TShortVarPtrType
+	Global floatVarPointerType:TFloatVarPtrType=New TFloatVarPtrType
+	Global doubleVarPointerType:TDoubleVarPtrType=New TDoubleVarPtrType
+	Global longVarPointerType:TLongVarPtrType=New TLongVarPtrType
+	Global stringVarPointerType:TStringVarPtrType=New TStringVarPtrType
+	
+	Global functionPointerType:TFunctionPtrType=New TFunctionPtrType
+	
+	Global pointerPointerType:TPointerPtrType=New TPointerPtrType
+	Global bytePointerPtrType:TBytePtrPtrType=New TBytePtrPtrType
+	Global intPointerPtrType:TIntPtrPtrType=New TIntPtrPtrType
+	Global shortPointerPtrType:TShortPtrPtrType=New TShortPtrPtrType
+	Global floatPointerPtrType:TFloatPtrPtrType=New TFloatPtrPtrType
+	Global doublePointerPtrType:TDoublePtrPtrType=New TDoublePtrPtrType
+	Global longPointerPtrType:TLongPtrPtrType=New TLongPtrPtrType
+
+	Rem
+	bbdoc: map to a pointer type
+	End Rem
+	Function MapToPointerType:TPointerType(ty:TType)
+		If TByteType(ty) Return bytePointerType
+		If TIntType(ty) Return intPointerType
+		If TShortType(ty) Return shortPointerType
+		If TFloatType(ty) Return floatPointerType
+		If TDoubleType(ty) Return doublePointerType
+		If TLongType(ty) Return longPointerType
+
+		If TStringType(ty) Return stringPointerType
+		
+		' pointer pointer
+		If TBytePtrType(ty) Return bytePointerPtrType
+		If TIntPtrType(ty) Return intPointerPtrType
+		If TShortPtrType(ty) Return shortPointerPtrType
+		If TFloatPtrType(ty) Return floatPointerPtrType
+		If TDoublePtrType(ty) Return doublePointerPtrType
+		If TLongPtrType(ty) Return longPointerPtrType
+		
+		Return Null
+	End Function
+
+	Rem
+	bbdoc: map to a var pointer type
+	End Rem
+	Function MapToVarPointerType:TVarPtrType(ty:TType)
+		If TByteType(ty) Return byteVarPointerType
+		If TIntType(ty) Return intVarPointerType
+		If TShortType(ty) Return shortVarPointerType
+		If TFloatType(ty) Return floatVarPointerType
+		If TDoubleType(ty) Return doubleVarPointerType
+		If TLongType(ty) Return longVarPointerType
+
+		If TStringType(ty) Return stringVarPointerType
+		
+		' pointer pointer
+' TODO ??
+'		If TBytePtrType(ty) Return bytePointerPtrType
+'		If TIntPtrType(ty) Return intPointerPtrType
+'		If TShortPtrType(ty) Return shortPointerPtrType
+'		If TFloatPtrType(ty) Return floatPointerPtrType
+'		If TDoublePtrType(ty) Return doublePointerPtrType
+'		If TLongPtrType(ty) Return longPointerPtrType
+		
+		Return Null
+	End Function
+	
+	Field _arrayOf:TArrayType
+	
+End Type
+
+Type TVoidType Extends TType
+
+	Method EqualsType:Int( ty:TType )
+		Return TVoidType( ty )<>Null Or TIntType( ty) <> Null ' TODO : Void and int are interchangable...
+	End Method
+	
+	Method ToString$()
+		Return "Void"
+	End Method
+End Type
+
+Type TBoolType Extends TType
+
+	Method EqualsType:Int( ty:TType )
+		Return TBoolType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		Return TIntType( ty )<>Null Or TBoolType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Bool"
+	End Method
+
+End Type
+
+Type TNumericType Extends TType
+
+	Method ToPointer:TPointerType() Abstract
+	
+End Type
+
+Type TIntType Extends TNumericType
+	
+	Method EqualsType:Int( ty:TType )
+		Return TIntType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null
+	End Method
+	
+	Method ToPointer:TPointerType()
+		Return intPointerType
+	End Method
+
+	Method ToString$()
+		Return "Int"
+	End Method
+End Type
+
+Type TByteType Extends TNumericType
+	
+	Method EqualsType:Int( ty:TType )
+		Return TByteType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null
+	End Method
+
+	Method ToPointer:TPointerType()
+		Return bytePointerType
+	End Method
+
+	Method ToString$()
+		Return "Byte"
+	End Method
+End Type
+
+Type TShortType Extends TNumericType
+
+	Method EqualsType:Int( ty:TType )
+		Return TShortType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null
+	End Method
+	
+	Method ToPointer:TPointerType()
+		Return shortPointerType
+	End Method
+
+	Method ToString$()
+		Return "Short"
+	End Method
+End Type
+
+Type TLongType Extends TNumericType ' BaH Long
+	
+	Method EqualsType:Int( ty:TType )
+		Return TLongType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null
+	End Method
+	
+	Method ToPointer:TPointerType()
+		Return longPointerType
+	End Method
+
+	Method ToString$()
+		Return "Long"
+	End Method
+End Type
+
+Type TFloatType Extends TNumericType
+	
+	Method EqualsType:Int( ty:TType )
+		Return TFloatType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf	
+		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null
+	End Method
+
+	Method ToPointer:TPointerType()
+		Return floatPointerType
+	End Method
+	
+	Method ToString$()
+		Return "Float"
+	End Method
+
+End Type
+
+Type TDoubleType Extends TNumericType
+	
+	Method EqualsType:Int( ty:TType )
+		Return TDoubleType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf	
+		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null
+	End Method
+
+	Method ToPointer:TPointerType()
+		Return doublePointerType
+	End Method
+
+	Method ToString$()
+		Return "Double"
+	End Method
+
+End Type
+
+Type TStringType Extends TType
+
+	Field cdecl:TClassDecl
+
+	Method EqualsType:Int( ty:TType )
+		Return TStringType( ty )<>Null
+	End Method
+
+	Method ExtendsType:Int( ty:TType )	
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return EqualsType( ty )
+	End Method
+	
+	Method GetClass:TClassDecl()
+		If cdecl Return cdecl
+		
+		Local modid$="brl.classes"
+		Local mdecl:TModuleDecl=_env.FindModuleDecl( modid )
+		If Not mdecl Err "Module '"+modid+"' not found"
+		'clsid=ident[i+1..] ' BaH
+	'DebugStop
+		cdecl=TClassDecl(mdecl.FindDecl( "string" ))
+
+		'Return _env.FindClassDecl( "brl.classes.string" )
+		Return cdecl
+	End Method
+	
+	Method ToString$()
+		Return "String"
+	End Method
+End Type
+
+Type TArrayType Extends TType
+	Field elemType:TType
+	
+	Method Create:TArrayType( elemType:TType )
+		Self.elemType=elemType
+		Return Self
+	End Method
+	
+	Method ActualType:TType()
+		Local ty:TType=elemType.ActualType()
+		If ty=elemType Return Self
+		Return New TArrayType.Create( ty )
+	End Method
+		
+	Method EqualsType:Int( ty:TType )
+		Local arrayType:TArrayType=TArrayType( ty )
+		Return arrayType And elemType.EqualsType( arrayType.elemType )
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		Local arrayType:TArrayType=TArrayType( ty )
+		Return (arrayType And ( TVoidType( elemType ) Or elemType.EqualsType( arrayType.elemType ) )) Or TPointerType(ty)
+	End Method
+	
+	Method Semant:TType()
+		Local ty:TType=elemType.Semant()
+		If ty<>elemType Return New TArrayType.Create( ty )
+		Return Self
+	End Method
+	
+	Method GetClass:TClassDecl()
+		'Return _env.FindClassDecl( "array" )
+		Return TClassDecl( _env.FindDecl( "array" ) )
+	End Method
+	
+	Method ToString$()
+		Return elemType.ToString()+"[]"
+	End Method
+End Type
+
+Type TObjectType Extends TType
+	Field classDecl:TClassDecl
+	
+	Method Create:TObjectType( classDecl:TClassDecl )
+		Self.classDecl=classDecl
+		Return Self
+	End Method
+	
+	Method ActualType:TType()
+		If classDecl.actual=classDecl Return Self
+		Return New TObjectType.Create( TClassDecl(classDecl.actual) )
+	End Method
+	
+	Method EqualsType:Int( ty:TType )
+		Local objty:TObjectType=TObjectType( ty )
+		Return objty And classDecl=objty.classDecl
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		Local objty:TObjectType=TObjectType( ty )
+		If objty Return classDecl.ExtendsClass( objty.classDecl )
+		Local op$
+		If TBoolType( ty )
+			op="ToBool"
+		Else If TIntType( ty ) 
+			op="ToInt"
+		Else If TFloatType( ty )
+			op="ToFloat"
+		Else If TStringType( ty )
+			op="ToString"
+		Else If TLongType( ty ) ' BaH Long
+			op="ToLong"
+		Else
+			Return False
+		EndIf
+		Local fdecl:TFuncDecl=GetClass().FindFuncDecl( op,Null,True )
+		Return fdecl And fdecl.IsMethod() And fdecl.retType.EqualsType( ty )
+	End Method
+	
+	Method GetClass:TClassDecl()
+		Return classDecl
+	End Method
+	
+	Method ToString$()
+		Return classDecl.ToString()
+	End Method
+End Type
+
+Type TIdentType Extends TType
+	Field ident$
+	Field args:TType[]
+	
+	Method Create:TIdentType( ident$,args:TType[] = Null )
+		Self.ident=ident
+		If args = Null Then
+			Self.args = New TType[0]
+		Else
+			Self.args=args
+		End If
+		Return Self
+	End Method
+	
+	Method ActualType:TType()
+		InternalErr
+	End Method
+	
+	Method EqualsType:Int( ty:TType )
+		InternalErr
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		InternalErr
+	End Method
+	
+	'Method Semant:TType()
+	'	If ident Return New TObjectType.Create( FindClass() )
+	'	Return New TObjectType.Create( TClassDecl.nullObjectClass )
+	'End Method
+	
+	
+	Method Semant:TType()
+		If Not ident Return TClassDecl.nullObjectClass.objectType
+	
+		Local targs:TType[args.Length]
+		For Local i:Int=0 Until args.Length
+			targs[i]=args[i].Semant()
+		Next
+		
+		Local tyid$,ty:TType
+		Local i:Int=ident.FindLast( "." )
+		
+		If i=-1
+			tyid=ident
+			ty=_env.FindType( tyid,targs )
+		Else
+			Local modid$=ident[..i]
+			Local mdecl:TModuleDecl=_env.FindModuleDecl( modid )
+			If Not mdecl Err "Module '"+modid+"' not found"
+			tyid=ident[i+1..]
+			ty=mdecl.FindType( tyid,targs )
+		EndIf
+		If Not ty Err "Type '"+tyid+"' not found"
+		Return ty
+	End Method
+	
+	
+	
+Rem
+	Method FindClass:TClassDecl()
+	
+		Local argClasses:TClassDecl[args.Length]
+
+		For Local i:Int=0 Until args.Length
+			argClasses[i]=args[i].FindClass()
+		Next
+		
+		Local clsid$
+		Local cdecl:TClassDecl
+		Local i:Int=ident.FindLast( "." )
+		If i=-1
+			clsid=ident
+			cdecl=_env.FindClassDecl( clsid,argClasses )
+		Else
+			Local modid$=ident[..i]
+			Local mdecl:TModuleDecl=_env.FindModuleDecl( modid )
+			If Not mdecl Err "Module '"+modid+"' not found"
+			clsid=ident[i+1..] ' BaH
+'DebugStop
+			cdecl=mdecl.FindClassDecl( clsid,argClasses )
+		EndIf
+		If Not cdecl Err "Class '"+clsid+"' not found"
+		Return cdecl
+	End Method
+End Rem
+
+	Method SemantClass:TClassDecl()
+		Local ty:TObjectType=TObjectType( Semant() )
+		If Not ty Err "Type is not a class"
+		Return ty.classDecl
+	End Method
+
+	Method ToString$()
+		Local t$
+		For Local arg:TIdentType=EachIn args
+			If t t:+","
+			t:+arg.ToString()
+		Next
+		If t Return "$"+ident+"<"+t.Replace("$","")+">"
+		Return "$"+ident
+	End Method
+End Type
+
+Type TPointerType Extends TType
+
+End Type
+
+Type TPointerPtrType Extends TPointerType
+
+	Method EqualsType:Int( ty:TType )
+		Return TPointerPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Pointer Ptr"
+	End Method
+
+End Type
+
+Type TVarPtrType Extends TPointerType
+
+	Method EqualsType:Int( ty:TType )
+		Return TVarPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "VarPtr"
+	End Method
+
+End Type
+
+Type TBytePtrType Extends TPointerType
+
+	Method EqualsType:Int( ty:TType )
+		Return TBytePtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Byte Ptr"
+	End Method
+
+End Type
+
+Type TByteVarPtrType Extends TVarPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TByteVarPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Byte Var"
+	End Method
+
+End Type
+
+Type TShortPtrType Extends TPointerType
+
+	Method EqualsType:Int( ty:TType )
+		Return TShortPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Short Ptr"
+	End Method
+
+End Type
+
+Type TShortVarPtrType Extends TVarPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TShortVarPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Short Var"
+	End Method
+
+End Type
+
+Type TIntPtrType Extends TPointerType
+
+	Method EqualsType:Int( ty:TType )
+		Return TIntPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Int Ptr"
+	End Method
+
+End Type
+
+Type TIntVarPtrType Extends TVarPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TIntVarPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Int Var"
+	End Method
+
+End Type
+
+Type TFloatPtrType Extends TPointerType
+
+	Method EqualsType:Int( ty:TType )
+		Return TFloatPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Float Ptr"
+	End Method
+
+End Type
+
+Type TFloatVarPtrType Extends TVarPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TFloatVarPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Float Var"
+	End Method
+
+End Type
+
+Type TDoublePtrType Extends TPointerType
+
+	Method EqualsType:Int( ty:TType )
+		Return TDoublePtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Byte Ptr"
+	End Method
+
+End Type
+
+Type TDoubleVarPtrType Extends TVarPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TDoubleVarPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Double Var"
+	End Method
+
+End Type
+
+Type TLongPtrType Extends TPointerType
+
+	Method EqualsType:Int( ty:TType )
+		Return TLongPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Long Ptr"
+	End Method
+
+End Type
+
+Type TLongVarPtrType Extends TVarPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TLongVarPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Long Var"
+	End Method
+
+End Type
+
+Type TStringPtrType Extends TPointerType
+
+	Method EqualsType:Int( ty:TType )
+		Return TStringPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "String Ptr"
+	End Method
+
+End Type
+
+Type TStringVarPtrType Extends TVarPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TStringVarPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "String Var"
+	End Method
+
+End Type
+
+Type TFunctionPtrType Extends TPointerType
+
+	Field func:TFuncDecl
+
+	Method EqualsType:Int( ty:TType )
+' TODO : compare function decl
+		Return TFunctionPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Function Ptr"
+	End Method
+
+End Type
+
+Type TBytePtrPtrType Extends TPointerPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TBytePtrPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Byte Ptr Ptr"
+	End Method
+
+End Type
+
+Type TShortPtrPtrType Extends TPointerPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TShortPtrPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Short Ptr Ptr"
+	End Method
+
+End Type
+
+Type TIntPtrPtrType Extends TPointerPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TIntPtrPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Int Ptr Ptr"
+	End Method
+
+End Type
+
+Type TFloatPtrPtrType Extends TPointerPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TFloatPtrPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Float Ptr Ptr"
+	End Method
+
+End Type
+
+Type TDoublePtrPtrType Extends TPointerPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TDoublePtrPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Double Ptr Ptr"
+	End Method
+
+End Type
+
+Type TLongPtrPtrType Extends TPointerPtrType
+
+	Method EqualsType:Int( ty:TType )
+		Return TLongPtrPtrType( ty )<>Null
+	End Method
+	
+	Method ExtendsType:Int( ty:TType )
+		If TObjectType( ty )
+			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Return ctor And ctor.IsCtor()
+		EndIf
+		Return TPointerType( ty )<>Null
+	End Method
+	
+	Method ToString$()
+		Return "Long Ptr Ptr"
+	End Method
+
+End Type